From 12f5b9ecbc0206a2721b6d4e93ad0dd70c78511a Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Sat, 21 Aug 2021 14:11:54 +0800 Subject: [PATCH 001/763] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=E5=AE=89=E8=A3=85=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2cdb7ba9..fb90e32f 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Zeus-IOT 支持 Centos 7、Ubuntu 20.04、Debain 10 、Kylin、UOS 等基于x86_64平台的 Linux 操作系统。 ```shell -curl -L https://github.com/zmops/zeus-iot/blob/develop/docs/quick-install.sh | bash +curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/quick-install.sh | bash ``` 访问 `http://` 登录 Zeus-IOT 系统。[快速开始](./docs/quick-start.rst) From ac44542bba043b586786cc6209f5b02910f2ee43 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 21 Aug 2021 14:36:18 +0800 Subject: [PATCH 002/763] =?UTF-8?q?=E7=94=A8=E6=88=B7=E6=96=B0=E5=A2=9E=20?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=E8=A7=92=E8=89=B2=E6=98=AF=E5=90=A6=E5=AD=98?= =?UTF-8?q?=E5=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/exception/enums/BizExceptionEnum.java | 1 + .../web/sys/service/OperationLogService.java | 2 +- .../iot/web/sys/service/SysUserService.java | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index 54a54d2d..7a74c043 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -53,6 +53,7 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { ROLE_HAS_EXIST(601, "角色已存在"), ROLE_HAS_BIND_USER(602, "角色绑定了用户,请先解除绑定!"), MENU_NOT_EXIST_OR_NO_PRERMISSION(603, "菜单不存在或无权授权此菜单"), + ROLE_NOT_EXIST(604, "角色不存在"), /** * 账户问题 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/OperationLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/OperationLogService.java index 1b931d81..6148801f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/OperationLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/OperationLogService.java @@ -23,7 +23,7 @@ public Pager list(Long beginTime, Long endTime, String logName, qSysOperationLog.createTime.le(LocalDateTimeUtils.getLDTByMilliSeconds(endTime)); } if (ToolUtil.isNotEmpty(logName)) { - qSysOperationLog.logName.eq(logName); + qSysOperationLog.logName.contains(logName); } if (ToolUtil.isNotEmpty(logType)) { qSysOperationLog.logType.eq(logType); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java index 6f07ba08..c454c3df 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java @@ -8,6 +8,7 @@ import com.zmops.iot.core.util.RsaUtil; import com.zmops.iot.core.util.SaltUtil; import com.zmops.iot.domain.sys.SysUser; +import com.zmops.iot.domain.sys.query.QSysRole; import com.zmops.iot.domain.sys.query.QSysUser; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; @@ -80,6 +81,8 @@ public Pager userList(UserParam userParam) { public SysUser createUser(UserDto user) { // 判断账号是否重复 checkByAccount(user.getAccount()); + //判断角色是否存在 + checkByRole(user.getRoleId()); // 完善账号信息 String password = user.getPassword(); @@ -117,6 +120,9 @@ public SysUser updateUser(UserDto user) { if (null == oldUser) { throw new ServiceException(BizExceptionEnum.USER_NOT_EXIST); } + //判断角色是否存在 + checkByRole(user.getRoleId()); + SysUser sysUser = UserFactory.editUser(user, oldUser); //取对应的ZBX用户组ID String usrZbxId = sysUserGroupService.getZabUsrGrpId(user.getUserGroupId()); @@ -157,6 +163,18 @@ private void checkByAccount(String account) { } } + /** + * 检查所选角色是否存在 + * + * @param roleId + */ + private void checkByRole(Long roleId) { + int count = new QSysRole().roleId.eq(roleId).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.ROLE_NOT_EXIST); + } + } + /** * 修改密码 * From c9d97bee8560d713a2978f6b596503dbe909e68d Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 21 Aug 2021 17:19:57 +0800 Subject: [PATCH 003/763] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E5=A2=9E=E5=8A=A0=20?= =?UTF-8?q?=E5=9C=B0=E5=9D=80=20=E5=9D=90=E6=A0=87=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/zmops/iot/domain/device/Device.java | 4 ++++ .../src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java | 4 ++++ .../java/com/zmops/iot/web/device/service/DeviceService.java | 2 ++ 3 files changed, 10 insertions(+) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java index 23aed28f..9da122f7 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java @@ -36,6 +36,10 @@ public class Device extends BaseEntity { private String zbxId; + private String addr; + + private String position; + @Aggregation("count(*)") Long totalCount; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java index 719e67ea..1434a745 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java @@ -59,4 +59,8 @@ public class DeviceDto implements BaseDto { private String groupName; + private String addr; + + private String position; + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 39b96be6..19c0bf53 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -142,6 +142,8 @@ private StringBuilder generateBaseSql() { " d.update_time, " + " d.update_user, " + " d.TYPE, " + + " d.addr, " + + " d.position, " + " P.NAME product_name, " + " ds.group_name, " + " ds.groupIds " + From 5fe2de41c260206d1c3e3c9fe6e06ff685d122db Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 23 Aug 2021 10:35:52 +0800 Subject: [PATCH 004/763] =?UTF-8?q?=E7=94=A8=E6=88=B7=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/zmops/iot/web/sys/dto/UserDto.java | 4 ++-- .../java/com/zmops/iot/web/sys/service/SysUserService.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java index 7da64383..dd07100a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java @@ -32,10 +32,10 @@ public class UserDto { @NotNull(groups = BaseEntity.Update.class) private Long userId; - @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + @NotBlank(groups = {BaseEntity.Create.class}) private String account; - @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + @NotBlank(groups = {BaseEntity.Create.class}) private String password; @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java index c454c3df..95148333 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java @@ -170,7 +170,7 @@ private void checkByAccount(String account) { */ private void checkByRole(Long roleId) { int count = new QSysRole().roleId.eq(roleId).findCount(); - if (count > 0) { + if (count <= 0) { throw new ServiceException(BizExceptionEnum.ROLE_NOT_EXIST); } } From a905df12a931ba2945444be30d8d56e0ea9241c3 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 23 Aug 2021 10:37:37 +0800 Subject: [PATCH 005/763] =?UTF-8?q?=E6=9C=80=E6=96=B0=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zeus/driver/service/ZbxHistoryGet.java | 3 +- .../api-json/history/history.get.ftl | 2 +- .../analyse/controller/LatestController.java | 29 +++++++ .../zmops/iot/web/analyse/dto/LatestDto.java | 23 ++++++ .../web/analyse/dto/param/LatestParam.java | 19 +++++ .../web/analyse/service/LatestService.java | 76 +++++++++++++++++++ 6 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/LatestParam.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java index 5b385efe..7a7429ac 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java @@ -18,5 +18,6 @@ public interface ZbxHistoryGet { @JsonPath("/history/history.get") String historyGet(@ParamName("hostid") String hostid, @ParamName("itemids") List itemids, - @ParamName("hisNum") String hisNum); + @ParamName("hisNum") Integer hisNum, + @ParamName("valueType") Integer valueType); } diff --git a/zeus-driver/src/main/resources/api-json/history/history.get.ftl b/zeus-driver/src/main/resources/api-json/history/history.get.ftl index a274186d..0ded0832 100644 --- a/zeus-driver/src/main/resources/api-json/history/history.get.ftl +++ b/zeus-driver/src/main/resources/api-json/history/history.get.ftl @@ -3,7 +3,7 @@ "method": "history.get", "params": { "output": "extend", - "history": 0, + "history": ${valueType}, <#if hostid??> "hostids": "${hostid}", diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java new file mode 100644 index 00000000..e8f7aa1a --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java @@ -0,0 +1,29 @@ +package com.zmops.iot.web.analyse.controller; + +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.analyse.dto.param.LatestParam; +import com.zmops.iot.web.analyse.service.LatestService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + * + * 最新数据 + **/ +@RestController +@RequestMapping("/latest") +public class LatestController { + + @Autowired + LatestService latestService; + + @RequestMapping("/query") + public ResponseData qeuryLatest(@Validated @RequestBody LatestParam latestParam){ + return ResponseData.success(latestService.qeuryLatest(latestParam)); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java new file mode 100644 index 00000000..8ebe7f5b --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java @@ -0,0 +1,23 @@ +package com.zmops.iot.web.analyse.dto; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class LatestDto { + + private String name; + + private String itemid; + + private String clock; + + private String value; + + private String change; + + private String tags; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/LatestParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/LatestParam.java new file mode 100644 index 00000000..783c9341 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/LatestParam.java @@ -0,0 +1,19 @@ +package com.zmops.iot.web.analyse.dto.param; + +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class LatestParam { + @NotNull(message = "请选择一个设备再查询") + private Long deviceId; + + private List attrIds; + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java new file mode 100644 index 00000000..be56d17c --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java @@ -0,0 +1,76 @@ +package com.zmops.iot.web.analyse.service; + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductAttribute; +import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.analyse.dto.LatestDto; +import com.zmops.iot.web.analyse.dto.param.LatestParam; +import com.zmops.zeus.driver.service.ZbxHistoryGet; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 最新数据服务 + **/ +@Service +public class LatestService { + + @Autowired + ZbxHistoryGet zbxHistoryGet; + + /** + * 查询最新数据 + * + * @param latestParam + * @return + */ + public List qeuryLatest(LatestParam latestParam) { + return qeuryLatest(latestParam.getDeviceId(), latestParam.getAttrIds()); + } + + public List qeuryLatest(Long deviceId, List attrIds) { + //查询出设备 + Device one = new QDevice().deviceId.eq(deviceId).findOne(); + if (null == one || ToolUtil.isEmpty(one.getZbxId())) { + return Collections.emptyList(); + } + //查询设备属性 + QProductAttribute query = new QProductAttribute().productId.eq(deviceId); + if (ToolUtil.isNotEmpty(attrIds)) { + query.attrId.in(attrIds); + } + List list = query.findList(); + if (ToolUtil.isEmpty(list)) { + return Collections.emptyList(); + } + //取出属性对应的ItemID + List zbxIds = list.parallelStream().map(ProductAttribute::getZbxId).collect(Collectors.toList()); + Map> valueTypeMap = list.parallelStream().collect(Collectors.groupingBy(ProductAttribute::getValueType)); + Map itemIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getZbxId, ProductAttribute::getName)); + List latestDtos = new ArrayList<>(); + //根据属性值类型 分组查询最新数据 + for (Map.Entry> map : valueTypeMap.entrySet()) { + String res = zbxHistoryGet.historyGet(one.getZbxId(), zbxIds, map.getValue().size(), Integer.parseInt(map.getKey())); + latestDtos.addAll(JSONObject.parseArray(res, LatestDto.class)); + } + + latestDtos.forEach(latestDto -> { + if (null != itemIdMap.get(latestDto.getItemid())) { + latestDto.setName(itemIdMap.get(latestDto.getItemid())); + } + }); + + return latestDtos; + } +} From 60d9598efcbc98fe6a931decd100360a62663fea Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 23 Aug 2021 15:22:59 +0800 Subject: [PATCH 006/763] =?UTF-8?q?=E8=B0=83=E6=95=B4=20server-sender=20?= =?UTF-8?q?=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iot-server/server-sender/pom.xml | 1 - .../sender/module/ZabbixSenderModule.java | 2 +- .../{protocol => }/ZabbixSenderClient.java | 8 +-- .../sender/provider/ZabbixSenderProvider.java | 3 +- .../protocol/bean/ZabbixProtocolType.java | 51 -------------- .../protocol/bean/ZabbixTrapperRequest.java | 70 ------------------- .../service/ZabbixSenderService.java | 23 +++++- 7 files changed, 27 insertions(+), 131 deletions(-) rename iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/{protocol => }/ZabbixSenderClient.java (86%) delete mode 100644 iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/bean/ZabbixProtocolType.java delete mode 100644 iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/bean/ZabbixTrapperRequest.java rename iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/{provider => }/service/ZabbixSenderService.java (83%) diff --git a/iot-server/server-sender/pom.xml b/iot-server/server-sender/pom.xml index 64672f98..4ce0db54 100644 --- a/iot-server/server-sender/pom.xml +++ b/iot-server/server-sender/pom.xml @@ -15,7 +15,6 @@ com.zmops library-module 1.0-beta - compile diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/module/ZabbixSenderModule.java b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/module/ZabbixSenderModule.java index 5f4e63ad..5dd90d24 100644 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/module/ZabbixSenderModule.java +++ b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/module/ZabbixSenderModule.java @@ -1,7 +1,7 @@ package com.zmops.zeus.iot.server.sender.module; import com.zmops.zeus.iot.server.library.module.ModuleDefine; -import com.zmops.zeus.iot.server.sender.provider.service.ZabbixSenderService; +import com.zmops.zeus.iot.server.sender.service.ZabbixSenderService; /** * @author nantian created at 2021/8/14 14:35 diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/ZabbixSenderClient.java b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderClient.java similarity index 86% rename from iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/ZabbixSenderClient.java rename to iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderClient.java index fd3c60e6..498c632e 100644 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/ZabbixSenderClient.java +++ b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderClient.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.sender.provider.protocol; +package com.zmops.zeus.iot.server.sender.provider; import com.zmops.zeus.iot.server.sender.provider.ZabbixSenderModuleConfig; import lombok.extern.slf4j.Slf4j; @@ -8,6 +8,8 @@ /** * @author nantian created at 2021/8/14 14:46 + *

+ * Zabbix 发送 Socket Client */ @Slf4j @@ -23,8 +25,7 @@ public ZabbixSenderClient(ZabbixSenderModuleConfig config) { * 启动 TCP Sender 客户端 */ public void start() { - log.debug("Zabbix Sender 模块已经启动,Trapper 服务地址:{}:{}", - socketConfig.getHost(), socketConfig.getPort()); + log.debug("Zabbix Sender 模块已经启动,Trapper 服务地址:{}:{}", socketConfig.getHost(), socketConfig.getPort()); } @@ -41,7 +42,6 @@ public static Socket getSocket() { } catch (Exception e) { e.printStackTrace(); } - return trapperSocket; } } diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderProvider.java b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderProvider.java index 16e52e8c..b73ffc19 100644 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderProvider.java +++ b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderProvider.java @@ -2,8 +2,7 @@ import com.zmops.zeus.iot.server.library.module.*; import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; -import com.zmops.zeus.iot.server.sender.provider.protocol.ZabbixSenderClient; -import com.zmops.zeus.iot.server.sender.provider.service.ZabbixSenderService; +import com.zmops.zeus.iot.server.sender.service.ZabbixSenderService; import lombok.extern.slf4j.Slf4j; /** diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/bean/ZabbixProtocolType.java b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/bean/ZabbixProtocolType.java deleted file mode 100644 index e16e2aca..00000000 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/bean/ZabbixProtocolType.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.sender.provider.protocol.bean; - -import lombok.Getter; - -import java.util.Objects; - -/** - * Zabbix protocol type - */ -@Getter -public enum ZabbixProtocolType { - ACTIVE_CHECKS("active checks"), - AGENT_DATA("agent data"), - SENDER_DATA("sender data"); - - private final String name; - - ZabbixProtocolType(String name) { - this.name = name; - } - - /** - * Parse type by name - */ - public static ZabbixProtocolType parse(String name) { - for (ZabbixProtocolType type : ZabbixProtocolType.values()) { - if (Objects.equals(type.name, name)) { - return type; - } - } - return null; - } -} \ No newline at end of file diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/bean/ZabbixTrapperRequest.java b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/bean/ZabbixTrapperRequest.java deleted file mode 100644 index e2e0e500..00000000 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/bean/ZabbixTrapperRequest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.sender.provider.protocol.bean; - -import lombok.Data; -import lombok.Getter; -import lombok.Setter; - -import java.util.List; - - -public class ZabbixTrapperRequest { - - /** - * Request type - */ - private ZabbixProtocolType type; - - @Setter - @Getter - private String request = ZabbixProtocolType.SENDER_DATA.getName(); - - /** - * Agent push data - * - * @see ZabbixProtocolType#AGENT_DATA - */ - @Setter - @Getter - private List data; - - @Setter - @Getter - private long clock = System.currentTimeMillis() / 1000L; - - @Setter - @Getter - private long ns = System.nanoTime() % 1_000_000_000L; - - @Data - public static class SenderData { - private String host; - private String key; - private String value; - private long clock; - private long ns; - - public SenderData() { - this.clock = System.currentTimeMillis() / 1000L; - this.ns = System.nanoTime() % 1_000_000_000L; - } - } - -} diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/service/ZabbixSenderService.java b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/service/ZabbixSenderService.java similarity index 83% rename from iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/service/ZabbixSenderService.java rename to iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/service/ZabbixSenderService.java index f3a6ec5a..2c285f35 100644 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/service/ZabbixSenderService.java +++ b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/service/ZabbixSenderService.java @@ -1,9 +1,9 @@ -package com.zmops.zeus.iot.server.sender.provider.service; +package com.zmops.zeus.iot.server.sender.service; import com.google.gson.Gson; import com.zmops.zeus.iot.server.library.module.ModuleManager; import com.zmops.zeus.iot.server.library.module.Service; -import com.zmops.zeus.iot.server.sender.provider.protocol.ZabbixSenderClient; +import com.zmops.zeus.iot.server.sender.provider.ZabbixSenderClient; import lombok.extern.slf4j.Slf4j; import java.io.IOException; @@ -31,6 +31,25 @@ public ZabbixSenderService(ModuleManager moduleManager) { this.moduleManager = moduleManager; } + /** + * 指定格式的 JSON + * + * @param message see + * https://www.zabbix.com/documentation/current/manual/appendix/items/trapper + * + * { + * "request":"sender data", + * "data":[ + * { + * "host":"device.info", + * "key":"device.temp", + * "value":"86" + * } + * ] + * } + * @return String + * @throws IOException ex + */ public String sendData(String message) throws IOException { Socket trapperSocket = ZabbixSenderClient.getSocket(); From 2a348c86f8054cafd2e56c74191857cd2c039bd6 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 23 Aug 2021 15:43:07 +0800 Subject: [PATCH 007/763] =?UTF-8?q?=E5=85=A8=E5=B1=80=E7=BF=BB=E8=AF=91?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/zmops/iot/model/cache/filter/CachedValueFilter.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java index dd48d22f..50e758f8 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java @@ -52,8 +52,10 @@ public void serialize(Object object, JsonGenerator jsonGenerator, SerializerProv if (value instanceof LocalDateTime) { jsonGenerator.writeStringField(fieldName, LocalDateTimeUtils.dateToStr(value.toString())); - } else { + } else if (value instanceof String) { jsonGenerator.writeStringField(fieldName, value.toString()); + } else { + jsonGenerator.writeObjectField(fieldName, value); } if (cachedValues.length == 0) { From d9d5d93d43006f9eee018512dbae49d6adc7012d Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 23 Aug 2021 15:44:35 +0800 Subject: [PATCH 008/763] =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E5=8F=82=E6=95=B0=20?= =?UTF-8?q?=E5=8A=A0=E6=98=AF=E5=90=A6=E5=8F=AF=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/zmops/iot/domain/sys/SysConfig.java | 5 +++++ .../main/java/com/zmops/iot/web/product/dto/ProductAttr.java | 4 ---- .../java/com/zmops/iot/web/sys/service/SysParamService.java | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysConfig.java b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysConfig.java index 2c887528..6bd2bfc2 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysConfig.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysConfig.java @@ -56,4 +56,9 @@ public class SysConfig extends BaseEntity implements Serializable { */ private String remark; + /** + * 是否可修改 ENABLE DISABLE + */ + private String status; + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java index c172b160..c1557187 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java @@ -97,9 +97,5 @@ public String getParams() { return ""; } } - -// public void setParams(String params){ -// this.params = params.split("\\n"); -// } } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysParamService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysParamService.java index 535847cd..34facecc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysParamService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysParamService.java @@ -2,6 +2,7 @@ import com.zmops.iot.domain.sys.SysConfig; import com.zmops.iot.domain.sys.query.QSysConfig; +import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.web.sys.dto.SysParamDto; import io.ebean.DB; import org.springframework.stereotype.Service; @@ -17,7 +18,7 @@ public class SysParamService { public List list() { - return new QSysConfig().orderBy().id.desc().findList(); + return new QSysConfig().status.eq(CommonStatus.ENABLE.getCode()).orderBy().id.desc().findList(); } public void update(SysParamDto sysParamDto) { From 23c77acf1ecf0aa38ff71ba8d5063acf686af318 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 23 Aug 2021 16:02:54 +0800 Subject: [PATCH 009/763] =?UTF-8?q?=E4=BA=A7=E5=93=81=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E5=AD=97=E6=AE=B5=E7=BB=9F=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zmops/iot/web/product/controller/ProductController.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java index 9f08519c..964439b2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java @@ -61,7 +61,7 @@ public ResponseData prodList(@RequestBody ProductBasicInfo prodBasicInfo) { * 产品详情 */ @GetMapping("/detail") - public ResponseData prodDetail(@RequestParam("prodId") Long prodId) { + public ResponseData prodDetail(@RequestParam("productId") Long prodId) { return ResponseData.success(productService.prodDetail(prodId)); } @@ -69,7 +69,7 @@ public ResponseData prodDetail(@RequestParam("prodId") Long prodId) { * 产品标签列表 */ @GetMapping("/prodTag/list") - public ResponseData prodTagList(@RequestParam("prodId") Long prodId) { + public ResponseData prodTagList(@RequestParam("productId") Long prodId) { return ResponseData.success(productService.prodTagList(prodId)); } @@ -77,7 +77,7 @@ public ResponseData prodTagList(@RequestParam("prodId") Long prodId) { * 值映射列表 */ @GetMapping("/valueMap/list") - public ResponseData valueMapList(@RequestParam("prodId") Long prodId) { + public ResponseData valueMapList(@RequestParam("productId") Long prodId) { return ResponseData.success(productService.valueMapList(prodId)); } From 87f038e7d745f42841fa382d45501fe9049e5ff9 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 23 Aug 2021 16:09:20 +0800 Subject: [PATCH 010/763] =?UTF-8?q?=E4=BA=A7=E5=93=81=20=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=E5=8F=82=E6=95=B0=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/web/device/controller/DeviceController.java | 9 +++++---- .../com/zmops/iot/web/device/service/DeviceService.java | 8 ++++---- .../iot/web/product/controller/ProductController.java | 7 ++++--- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java index 4391e72a..a49a2ace 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java @@ -54,8 +54,9 @@ public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody Devi } deviceService.checkProductExist(deviceDto); - - return ResponseData.success(deviceService.create(deviceDto)); + Long deviceId = deviceService.create(deviceDto); + deviceDto.setDeviceId(deviceId); + return ResponseData.success(deviceDto); } /** @@ -69,9 +70,9 @@ public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody Devi } deviceService.checkProductExist(deviceDto); + deviceService.update(deviceDto); - - return ResponseData.success(deviceService.update(deviceDto)); + return ResponseData.success(deviceDto); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 19c0bf53..b92c7333 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -169,7 +169,7 @@ private StringBuilder generateBaseSql() { * @param deviceDto * @return */ - public Object create(DeviceDto deviceDto) { + public Long create(DeviceDto deviceDto) { WorkerWrapper saveTagWork = WorkerWrapper.builder().id("saveTagWork") .worker(saveTagWorker).param(deviceDto).build(); @@ -206,7 +206,7 @@ public Object create(DeviceDto deviceDto) { e.printStackTrace(); } - return deviceWork.getWorkResult().getResult(); + return deviceWork.getWorkResult().getResult().getDeviceId(); } /** @@ -215,7 +215,7 @@ public Object create(DeviceDto deviceDto) { * @param deviceDto * @return */ - public Device update(DeviceDto deviceDto) { + public Long update(DeviceDto deviceDto) { Device device = new QDevice().deviceId.eq(deviceDto.getDeviceId()).findOne(); if (null == device) { throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); @@ -254,7 +254,7 @@ public Device update(DeviceDto deviceDto) { e.printStackTrace(); } - return deviceWork.getWorkResult().getResult(); + return deviceWork.getWorkResult().getResult().getDeviceId(); } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java index 964439b2..de42bbe4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java @@ -101,8 +101,9 @@ public ResponseData prodCreate(@RequestBody @Validated(value = BaseEntity.Create // 第二步:创建产品 String zbxId = JSON.parseObject(result, TemplateIds.class).getTemplateids()[0]; - Product prod = productService.createProduct(zbxId, prodId, prodBasicInfo); - return ResponseData.success(prod); + productService.createProduct(zbxId, prodId, prodBasicInfo); + prodBasicInfo.setProductId(prodId); + return ResponseData.success(prodBasicInfo); } @@ -123,7 +124,7 @@ public ResponseData prodUpdate(@RequestBody @Validated(value = BaseEntity.Update Product product = productService.updateProduct(prodBasicInfo); - return ResponseData.success(product); + return ResponseData.success(prodBasicInfo); } From 8395252fa44e19e1a64fe12f538e9fc127f524fc Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 23 Aug 2021 18:19:51 +0800 Subject: [PATCH 011/763] =?UTF-8?q?zabbix=20sender=20=E9=87=87=E7=94=A8=20?= =?UTF-8?q?=E9=98=9F=E5=88=97=E5=AE=9E=E7=8E=B0=E6=95=B0=E6=8D=AE=E5=8F=91?= =?UTF-8?q?=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iot-server/server-core/pom.xml | 10 ++ .../iot/server/core/UnexpectedException.java | 29 ++++ .../iot/server/core/camel/IOTDeviceValue.java | 23 +++ .../core/camel/ZabbixTrapperProducer.java | 46 ++---- .../server/core/worker/AbstractWorker.java | 47 ++++++ .../core/worker/ItemDataTransferWorker.java | 139 ++++++++++++++++++ .../server/core/worker/TransferWorker.java | 46 ++++++ .../server/core/worker/data/BufferedData.java | 41 ++++++ .../iot/server/core/worker/data/Item.java | 23 +++ .../server/core/worker/data/ItemValue.java | 53 +++++++ .../core/worker/data/ZabbixTrapper.java | 26 ++++ .../server-library/library-client/pom.xml | 19 +++ .../client/request/PrepareRequest.java | 21 +++ iot-server/server-library/pom.xml | 1 + .../http-receiver-plugin/pom.xml | 2 - .../http/process/JsonToItemValueProcess.java | 64 ++++++++ .../http/provider/HttpRouteBuilder.java | 4 +- 17 files changed, 557 insertions(+), 37 deletions(-) create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/UnexpectedException.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/IOTDeviceValue.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/AbstractWorker.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/ItemDataTransferWorker.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/TransferWorker.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/BufferedData.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/Item.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ItemValue.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ZabbixTrapper.java create mode 100644 iot-server/server-library/library-client/pom.xml create mode 100644 iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/request/PrepareRequest.java create mode 100644 iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/process/JsonToItemValueProcess.java diff --git a/iot-server/server-core/pom.xml b/iot-server/server-core/pom.xml index 5bf5c694..76cfa7f7 100644 --- a/iot-server/server-core/pom.xml +++ b/iot-server/server-core/pom.xml @@ -31,6 +31,16 @@ library-server 1.0-beta + + com.zmops + library-client + 1.0-beta + + + com.zmops + iot-datacarrier + 1.0-beta + diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/UnexpectedException.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/UnexpectedException.java new file mode 100644 index 00000000..bb6d504d --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/UnexpectedException.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.core; + +public class UnexpectedException extends RuntimeException { + public UnexpectedException(String message) { + super(message); + } + + public UnexpectedException(String message, Exception cause) { + super(message, cause); + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/IOTDeviceValue.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/IOTDeviceValue.java new file mode 100644 index 00000000..21871498 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/IOTDeviceValue.java @@ -0,0 +1,23 @@ +package com.zmops.zeus.iot.server.core.camel; + +import lombok.Getter; +import lombok.Setter; + +/** + * @author nantian created at 2021/8/23 18:01 + *

+ * 方便大家理解,转换一下 命名 + */ + +@Getter +@Setter +public class IOTDeviceValue { + + private String deviceId; // 设备ID + + private String deviceAttrKey; // 设备属性Key + + private String deviceAttrValue; // 设备属性值 + + private Long deviceTime; // 毫秒,70年到现在时间戳 +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java index 4f8dbac1..ced37d9b 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java @@ -1,16 +1,14 @@ package com.zmops.zeus.iot.server.core.camel; +import com.zmops.zeus.iot.server.core.worker.ItemDataTransferWorker; +import com.zmops.zeus.iot.server.core.worker.data.ItemValue; import com.zmops.zeus.iot.server.library.module.ModuleManager; -import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; -import com.zmops.zeus.iot.server.sender.provider.service.ZabbixSenderService; import org.apache.camel.Endpoint; import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.camel.impl.DefaultProducer; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; +import java.util.List; /** * @author nantian created at 2021/8/16 22:48 @@ -19,47 +17,27 @@ */ public class ZabbixTrapperProducer extends DefaultProducer { - private final ModuleManager moduleManager; + private final ModuleManager moduleManager; + private final ItemDataTransferWorker itemDataTransferWorker; public ZabbixTrapperProducer(Endpoint endpoint, ModuleManager moduleManager) { super(endpoint); this.moduleManager = moduleManager; + this.itemDataTransferWorker = new ItemDataTransferWorker(moduleManager); } /** - * TODO 数据写入 队列,进来之前 是 JSON 格式 + * Body 必须是 ItemValue * * @param exchange Exchange */ @Override - public void process(Exchange exchange) throws Exception { - Message message = exchange.getIn(); - InputStream bodyStream = (InputStream) message.getBody(); - String inputContext = this.analysisMessage(bodyStream); + public void process(Exchange exchange) { + Message message = exchange.getIn(); + List values = (List) message.getBody(); - ZabbixSenderService senderService = moduleManager.find(ZabbixSenderModule.NAME).provider().getService(ZabbixSenderService.class); - - String resp = senderService.sendData(inputContext); - - // 把Zabbix 响应结果放入 Message 返回 - message.setBody(resp); - } - - - private String analysisMessage(InputStream bodyStream) throws IOException { - ByteArrayOutputStream outStream = new ByteArrayOutputStream(); - byte[] contextBytes = new byte[4096]; - int realLen; - while ((realLen = bodyStream.read(contextBytes, 0, 4096)) != -1) { - outStream.write(contextBytes, 0, realLen); - } - - // 返回从Stream中读取的字串 - try { - return outStream.toString("UTF-8"); - } finally { - outStream.close(); - } + values.forEach(itemDataTransferWorker::in); + exchange.getMessage().setBody("{\"success\":\"true\"}"); } } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/AbstractWorker.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/AbstractWorker.java new file mode 100644 index 00000000..0536f05a --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/AbstractWorker.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.core.worker; + +import com.zmops.zeus.iot.server.library.module.ModuleDefineHolder; +import lombok.Getter; + + +/** + * Abstract worker definition. Provide the {@link ModuleDefineHolder} to make sure the worker could find and access + * services in different modules. Also, {@link #in(Object)} is provided as the primary entrance of every worker. + *

+ * + * @param the datatype this worker implementation processes. + * @editor nantian + * 数据从协议入口 发送到 zabbix 过程中的队列,to("zabbix") + */ +public abstract class AbstractWorker { + + @Getter + private final ModuleDefineHolder moduleDefineHolder; + + public AbstractWorker(ModuleDefineHolder moduleDefineHolder) { + this.moduleDefineHolder = moduleDefineHolder; + } + + /** + * Main entrance of this worker. + */ + public abstract void in(INPUT input); +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/ItemDataTransferWorker.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/ItemDataTransferWorker.java new file mode 100644 index 00000000..39d38345 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/ItemDataTransferWorker.java @@ -0,0 +1,139 @@ +package com.zmops.zeus.iot.server.core.worker; + +import com.google.gson.Gson; +import com.zmops.zeus.iot.server.core.UnexpectedException; +import com.zmops.zeus.iot.server.core.worker.data.ItemValue; +import com.zmops.zeus.iot.server.core.worker.data.ZabbixTrapper; +import com.zmops.zeus.iot.server.datacarrier.DataCarrier; +import com.zmops.zeus.iot.server.datacarrier.consumer.BulkConsumePool; +import com.zmops.zeus.iot.server.datacarrier.consumer.ConsumerPoolFactory; +import com.zmops.zeus.iot.server.datacarrier.consumer.IConsumer; +import com.zmops.zeus.iot.server.library.module.ModuleManager; +import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; +import com.zmops.zeus.iot.server.sender.service.ZabbixSenderService; +import com.zmops.zeus.iot.server.telemetry.TelemetryModule; +import com.zmops.zeus.iot.server.telemetry.api.CounterMetrics; +import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; +import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * @author nantian created at 2021/8/23 15:11 + *

+ * 数据发送队列 + */ +@Slf4j +public class ItemDataTransferWorker extends TransferWorker { + + + private final DataCarrier dataCarrier; + private final CounterMetrics iotDataTransferCounter; + private final Gson gson = new Gson(); + + public ItemDataTransferWorker(ModuleManager moduleManager) { + super(moduleManager); + + String name = "ITEMVALUE_TRANSFER_TUNNEL"; + + int size = BulkConsumePool.Creator.recommendMaxSize() / 8; + if (size == 0) { + size = 1; + } + BulkConsumePool.Creator creator = new BulkConsumePool.Creator(name, size, 20); + try { + ConsumerPoolFactory.INSTANCE.createIfAbsent(name, creator); + } catch (Exception e) { + throw new UnexpectedException(e.getMessage(), e); + } + + this.dataCarrier = new DataCarrier<>("ZABBIX_SENDER", name, 4, 2000); + this.dataCarrier.consume(ConsumerPoolFactory.INSTANCE.get(name), new SenderConsumer()); + + // #### 发送数量 指标采集 + MetricsCreator metricsCreator = moduleManager.find(TelemetryModule.NAME) + .provider() + .getService(MetricsCreator.class); + + iotDataTransferCounter = metricsCreator.createCounter( + "transfer_data_count", "The count number of iot device data in transfer", + new MetricsTag.Keys("name"), + new MetricsTag.Values("transfer_data_count") + ); + } + + + @Override + public void in(ItemValue itemValue) { + iotDataTransferCounter.inc(); + dataCarrier.produce(itemValue); + } + + @Override + public void prepareBatch(Collection lastCollection) { + long start = System.currentTimeMillis(); + if (lastCollection.size() == 0) { + return; + } + + int maxBatchGetSize = 500; + final int batchSize = Math.min(maxBatchGetSize, lastCollection.size()); + List valueList = new ArrayList<>(); + + for (ItemValue data : lastCollection) { + valueList.add(data); + if (valueList.size() == batchSize) { + batchSenderDataToZabbix(valueList); + } + } + + if (valueList.size() > 0) { + batchSenderDataToZabbix(valueList); + } + + log.debug("batch sender data size:{}, took time: {}", lastCollection.size(), System.currentTimeMillis() - start); + } + + + private void batchSenderDataToZabbix(List valueList) { + ZabbixTrapper zabbixTrapper = new ZabbixTrapper(valueList); + ZabbixSenderService senderService = getModuleDefineHolder().find(ZabbixSenderModule.NAME) + .provider().getService(ZabbixSenderService.class); + try { + senderService.sendData(gson.toJson(zabbixTrapper)); + } catch (IOException e) { + log.error(" itemvalue data sender error,msg :{}", e.getMessage()); + e.printStackTrace(); + } finally { + valueList.clear(); + } + } + + + private class SenderConsumer implements IConsumer { + @Override + public void init() { + + } + + @Override + public void consume(List data) { + ItemDataTransferWorker.this.onWork(data); + } + + @Override + public void onError(List data, Throwable t) { + log.error(t.getMessage(), t); + } + + @Override + public void onExit() { + } + } + + +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/TransferWorker.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/TransferWorker.java new file mode 100644 index 00000000..a652611f --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/TransferWorker.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.core.worker; + +import com.zmops.zeus.iot.server.core.worker.data.Item; +import com.zmops.zeus.iot.server.library.module.ModuleDefineHolder; +import lombok.extern.slf4j.Slf4j; + +import java.util.Collection; +import java.util.List; + +/** + * 1. 协议入口 -> zabbix trapper item + * + * @param The type of worker input. + */ +@Slf4j +public abstract class TransferWorker extends AbstractWorker { + + TransferWorker(ModuleDefineHolder moduleDefineHolder) { + super(moduleDefineHolder); + } + + void onWork(List input) { + prepareBatch(input); + } + + public abstract void prepareBatch(Collection lastCollection); + +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/BufferedData.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/BufferedData.java new file mode 100644 index 00000000..ba5a7346 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/BufferedData.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.core.worker.data; + +import java.util.List; + +/** + * BufferedData represents a data collection in the memory. Data could be accepted and be drain to other collection. + *

+ * {@link #accept(Object)} and {@link #read()} wouldn't be required to thread-safe. + */ +public interface BufferedData { + /** + * Accept the data into the cache if it fits the conditions. The implementation maybe wouldn't accept the new input + * data. + * + * @param data to be added potentially. + */ + void accept(T data); + + /** + * Read all existing buffered data, and clear the memory. + */ + List read(); +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/Item.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/Item.java new file mode 100644 index 00000000..40f5c79b --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/Item.java @@ -0,0 +1,23 @@ +package com.zmops.zeus.iot.server.core.worker.data; + +/** + * @author nantian created at 2021/8/23 15:14 + *

+ * 对应设备的属性 + */ +public interface Item { + + /** + * 设备ID 唯一 + * + * @return string + */ + String host(); + + /** + * 属性标识 唯一 + * + * @return string + */ + String key(); +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ItemValue.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ItemValue.java new file mode 100644 index 00000000..120478e5 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ItemValue.java @@ -0,0 +1,53 @@ +package com.zmops.zeus.iot.server.core.worker.data; + +import lombok.Getter; +import lombok.Setter; + +/** + * @author nantian created at 2021/8/23 15:15 + */ + +@Getter +@Setter +public class ItemValue implements Item { + + private String host; // 【设备ID】 + + private String key; // 【属性标识】 + + // 【设备上报 值】,都是文本 + // Zabbix 会根据配置的ITEM 类型,进行转换,如果失败就报错 + private String value; + + private Long clock; // 毫秒,如果为 Null,则 zabbix 以接收时间为准 + + private Long ns; // 纳秒,如果为 Null,则 zabbix 以接收时间为准 + + public ItemValue(String host, String key, String value) { + this.host = host; + this.key = key; + this.value = value; + } + + /** + * 设置 数据时间,单独设置 以设备推送的时间数据为准 + * + * @param clock 毫秒,70年到现在 + * @param ns 纳秒,0-9位数 + */ + public void setTime(Long clock, Long ns) { + this.clock = clock; + this.ns = ns; + } + + + @Override + public String host() { + return getHost(); + } + + @Override + public String key() { + return getKey(); + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ZabbixTrapper.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ZabbixTrapper.java new file mode 100644 index 00000000..ea89c2b3 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ZabbixTrapper.java @@ -0,0 +1,26 @@ +package com.zmops.zeus.iot.server.core.worker.data; + +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author nantian created at 2021/8/23 16:49 + */ +public class ZabbixTrapper { + + + @Getter + private final String request = "sender data"; + + @Setter + @Getter + private List data; + + public ZabbixTrapper(List itemValues) { + data = new ArrayList<>(); + data.addAll(itemValues); + } +} diff --git a/iot-server/server-library/library-client/pom.xml b/iot-server/server-library/library-client/pom.xml new file mode 100644 index 00000000..0ee97fd6 --- /dev/null +++ b/iot-server/server-library/library-client/pom.xml @@ -0,0 +1,19 @@ + + + + server-library + com.zmops + 1.0-beta + + 4.0.0 + + library-client + + + 8 + 8 + + + \ No newline at end of file diff --git a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/request/PrepareRequest.java b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/request/PrepareRequest.java new file mode 100644 index 00000000..f9a6a368 --- /dev/null +++ b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/request/PrepareRequest.java @@ -0,0 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.library.client.request; + +public interface PrepareRequest { +} diff --git a/iot-server/server-library/pom.xml b/iot-server/server-library/pom.xml index cb2a1dad..a117a798 100644 --- a/iot-server/server-library/pom.xml +++ b/iot-server/server-library/pom.xml @@ -15,6 +15,7 @@ library-module library-util library-server + library-client diff --git a/iot-server/server-receiver-plugin/http-receiver-plugin/pom.xml b/iot-server/server-receiver-plugin/http-receiver-plugin/pom.xml index 5884284b..58ef0317 100644 --- a/iot-server/server-receiver-plugin/http-receiver-plugin/pom.xml +++ b/iot-server/server-receiver-plugin/http-receiver-plugin/pom.xml @@ -31,13 +31,11 @@ com.zmops server-sender 1.0-beta - compile com.zmops server-core 1.0-beta - compile diff --git a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/process/JsonToItemValueProcess.java b/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/process/JsonToItemValueProcess.java new file mode 100644 index 00000000..bf34ee2b --- /dev/null +++ b/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/process/JsonToItemValueProcess.java @@ -0,0 +1,64 @@ +package com.zmops.zeus.iot.server.receiver.http.process; + +import com.google.common.reflect.TypeToken; +import com.google.gson.Gson; +import com.zmops.zeus.iot.server.core.camel.IOTDeviceValue; +import com.zmops.zeus.iot.server.core.worker.data.ItemValue; +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.Processor; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * @author nantian created at 2021/8/23 17:16 + *

+ * Json 转 对象,进队列,一定要转成 ItemValue 对象,{@link ItemValue} + */ +public class JsonToItemValueProcess implements Processor { + + private final Gson gson = new Gson(); + + @Override + public void process(Exchange exchange) throws Exception { + Message message = exchange.getIn(); + InputStream bodyStream = (InputStream) message.getBody(); + String inputContext = this.analysisMessage(bodyStream); + + + List valueList = gson.fromJson(inputContext, new TypeToken>() {}.getType()); + + // 多一步 命名转换,方便 Json 字段理解 + List itemValueList = new ArrayList<>(); + valueList.forEach(i -> { + ItemValue item = new ItemValue(i.getDeviceId(), i.getDeviceAttrKey(), i.getDeviceAttrValue()); + if (i.getDeviceTime() != null) { + item.setClock(i.getDeviceTime()); + } + itemValueList.add(item); + }); + + exchange.getMessage().setBody(itemValueList); + } + + + private String analysisMessage(InputStream bodyStream) throws IOException { + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + byte[] contextBytes = new byte[4096]; + int realLen; + while ((realLen = bodyStream.read(contextBytes, 0, 4096)) != -1) { + outStream.write(contextBytes, 0, realLen); + } + + // 返回从Stream中读取的字串 + try { + return outStream.toString("UTF-8"); + } finally { + outStream.close(); + } + } +} diff --git a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpRouteBuilder.java b/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpRouteBuilder.java index edc51ce9..8b788dd9 100644 --- a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpRouteBuilder.java +++ b/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpRouteBuilder.java @@ -1,6 +1,7 @@ package com.zmops.zeus.iot.server.receiver.http.provider; import com.zmops.zeus.iot.server.receiver.http.predicate.HeaderPredicate; +import com.zmops.zeus.iot.server.receiver.http.process.JsonToItemValueProcess; import org.apache.camel.builder.RouteBuilder; /** @@ -16,8 +17,9 @@ public HttpRouteBuilder(HttpReceiverConfig config) { @Override public void configure() throws Exception { - fromF("netty4-http:http://0.0.0.0:%d/foo", config.getPort()) + fromF("netty4-http:http://0.0.0.0:%d/data/receiver?sync=true", config.getPort()) .threads(10) + .process(new JsonToItemValueProcess()) .choice() .when(new HeaderPredicate()) .to("Zabbix"); From 546b0d656462b76640762f71747908447c8575a3 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 23 Aug 2021 18:39:57 +0800 Subject: [PATCH 012/763] =?UTF-8?q?=E5=A4=8D=E7=94=A8=20json=20process?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/server/core/camel}/process/JsonToItemValueProcess.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename iot-server/{server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http => server-core/src/main/java/com/zmops/zeus/iot/server/core/camel}/process/JsonToItemValueProcess.java (97%) diff --git a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/process/JsonToItemValueProcess.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/JsonToItemValueProcess.java similarity index 97% rename from iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/process/JsonToItemValueProcess.java rename to iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/JsonToItemValueProcess.java index bf34ee2b..4e48223c 100644 --- a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/process/JsonToItemValueProcess.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/JsonToItemValueProcess.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.receiver.http.process; +package com.zmops.zeus.iot.server.core.camel.process; import com.google.common.reflect.TypeToken; import com.google.gson.Gson; From 21de9368efaef8f177fa06204302620a1b4bc59a Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 23 Aug 2021 19:23:47 +0800 Subject: [PATCH 013/763] =?UTF-8?q?=E5=8E=86=E5=8F=B2=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zeus/driver/service/ZbxHistoryGet.java | 4 +- .../api-json/history/history.get.ftl | 6 ++ .../analyse/controller/HistoryController.java | 28 ++++++++ .../zmops/iot/web/analyse/dto/LatestDto.java | 2 + .../web/analyse/dto/param/HistoryParam.java | 22 ++++++ .../web/analyse/service/HistoryService.java | 72 +++++++++++++++++++ .../web/analyse/service/LatestService.java | 7 +- 7 files changed, 137 insertions(+), 4 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HistoryController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/HistoryParam.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java index 7a7429ac..b470f03e 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java @@ -19,5 +19,7 @@ public interface ZbxHistoryGet { String historyGet(@ParamName("hostid") String hostid, @ParamName("itemids") List itemids, @ParamName("hisNum") Integer hisNum, - @ParamName("valueType") Integer valueType); + @ParamName("valueType") Integer valueType, + @ParamName("timeFrom") Long timeFrom, + @ParamName("timeTill") Long timeTill); } diff --git a/zeus-driver/src/main/resources/api-json/history/history.get.ftl b/zeus-driver/src/main/resources/api-json/history/history.get.ftl index 0ded0832..511ca5ac 100644 --- a/zeus-driver/src/main/resources/api-json/history/history.get.ftl +++ b/zeus-driver/src/main/resources/api-json/history/history.get.ftl @@ -14,6 +14,12 @@ ], + <#if timeFrom??> + "time_from":${timeFrom}, + + <#if timeTill??> + "time_till":${timeTill}, + "sortfield": "clock", "sortorder": "DESC", "limit": ${hisNum} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HistoryController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HistoryController.java new file mode 100644 index 00000000..ac172637 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HistoryController.java @@ -0,0 +1,28 @@ +package com.zmops.iot.web.analyse.controller; + +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.analyse.dto.param.HistoryParam; +import com.zmops.iot.web.analyse.service.HistoryService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + *

+ * 历史数据 + **/ +@RestController +@RequestMapping("/history") +public class HistoryController { + + @Autowired + HistoryService historyService; + + @RequestMapping("/query") + public ResponseData qeuryHistory(@Validated @RequestBody HistoryParam historyParam) { + return ResponseData.success(historyService.qeuryHistory(historyParam)); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java index 8ebe7f5b..fc111841 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java @@ -12,6 +12,8 @@ public class LatestDto { private String itemid; + private Long attrId; + private String clock; private String value; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/HistoryParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/HistoryParam.java new file mode 100644 index 00000000..d69cf720 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/HistoryParam.java @@ -0,0 +1,22 @@ +package com.zmops.iot.web.analyse.dto.param; + +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class HistoryParam { + + @NotNull(message = "请选择一个设备再查询") + private Long deviceId; + + private List attrIds; + + private Long timeFrom; + + private Long timeTill; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java new file mode 100644 index 00000000..ce1d30e4 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java @@ -0,0 +1,72 @@ +package com.zmops.iot.web.analyse.service; + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductAttribute; +import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.util.LocalDateTimeUtils; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.analyse.dto.LatestDto; +import com.zmops.iot.web.analyse.dto.param.HistoryParam; +import com.zmops.zeus.driver.service.ZbxHistoryGet; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 历史数据服务 + **/ +@Service +public class HistoryService { + + @Autowired + ZbxHistoryGet zbxHistoryGet; + + public List qeuryHistory(HistoryParam historyParam) { + return qeuryHistory(historyParam.getDeviceId(), historyParam.getAttrIds(), historyParam.getTimeFrom(), historyParam.getTimeTill()); + } + + public List qeuryHistory(Long deviceId, List attrIds, Long timeFrom, Long timeTill) { + //查询出设备 + Device one = new QDevice().deviceId.eq(deviceId).findOne(); + if (null == one || ToolUtil.isEmpty(one.getZbxId())) { + return Collections.emptyList(); + } + //查询设备属性 + QProductAttribute query = new QProductAttribute().productId.eq(deviceId); + if (ToolUtil.isNotEmpty(attrIds)) { + query.attrId.in(attrIds); + } + List list = query.findList(); + if (ToolUtil.isEmpty(list)) { + return Collections.emptyList(); + } + //取出属性对应的ItemID + List zbxIds = list.parallelStream().map(ProductAttribute::getZbxId).collect(Collectors.toList()); + Map> valueTypeMap = list.parallelStream().collect(Collectors.groupingBy(ProductAttribute::getValueType)); + Map itemIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getZbxId, ProductAttribute::getName)); + List latestDtos = new ArrayList<>(); + if (null == timeFrom) { + timeFrom = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); + } + //根据属性值类型 分组查询历史数据 + for (Map.Entry> map : valueTypeMap.entrySet()) { + String res = zbxHistoryGet.historyGet(one.getZbxId(), zbxIds, 1000, Integer.parseInt(map.getKey()), timeFrom, timeTill); + latestDtos.addAll(JSONObject.parseArray(res, LatestDto.class)); + } + + latestDtos.forEach(latestDto -> { + if (null != itemIdMap.get(latestDto.getItemid())) { + latestDto.setName(itemIdMap.get(latestDto.getItemid())); + } + }); + + return latestDtos; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java index be56d17c..77fc1b46 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java @@ -57,17 +57,18 @@ public List qeuryLatest(Long deviceId, List attrIds) { //取出属性对应的ItemID List zbxIds = list.parallelStream().map(ProductAttribute::getZbxId).collect(Collectors.toList()); Map> valueTypeMap = list.parallelStream().collect(Collectors.groupingBy(ProductAttribute::getValueType)); - Map itemIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getZbxId, ProductAttribute::getName)); + Map itemIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getZbxId, o -> o)); List latestDtos = new ArrayList<>(); //根据属性值类型 分组查询最新数据 for (Map.Entry> map : valueTypeMap.entrySet()) { - String res = zbxHistoryGet.historyGet(one.getZbxId(), zbxIds, map.getValue().size(), Integer.parseInt(map.getKey())); + String res = zbxHistoryGet.historyGet(one.getZbxId(), zbxIds, map.getValue().size(), Integer.parseInt(map.getKey()), null, null); latestDtos.addAll(JSONObject.parseArray(res, LatestDto.class)); } latestDtos.forEach(latestDto -> { if (null != itemIdMap.get(latestDto.getItemid())) { - latestDto.setName(itemIdMap.get(latestDto.getItemid())); + latestDto.setName(itemIdMap.get(latestDto.getItemid()).getName()); + latestDto.setAttrId(itemIdMap.get(latestDto.getItemid()).getAttrId()); } }); From 40fbfd18f02be2798d671ce4e1aeb5b1a3faf24e Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 23 Aug 2021 20:07:28 +0800 Subject: [PATCH 014/763] =?UTF-8?q?=E5=90=84=E7=B1=BB=E5=8D=8F=E8=AE=AE?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=20=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../process/ByteArrayToItemValueProcess.java | 44 ++++++++++++++ .../camel/process/StringItemValueProcess.java | 60 +++++++++++++++++++ .../http/provider/HttpRouteBuilder.java | 7 ++- .../mqtt/process/MqttPacketProcess.java | 15 ----- .../mqtt/provider/MqttRouteBuilder.java | 7 ++- .../tcp/process/TcpPacketProcess.java | 2 + .../tcp/provider/TcpRouteBuilder.java | 7 ++- 7 files changed, 120 insertions(+), 22 deletions(-) create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/StringItemValueProcess.java delete mode 100644 iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/process/MqttPacketProcess.java diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java new file mode 100644 index 00000000..c2bb66b7 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java @@ -0,0 +1,44 @@ +package com.zmops.zeus.iot.server.core.camel.process; + +import com.google.common.reflect.TypeToken; +import com.google.gson.Gson; +import com.zmops.zeus.iot.server.core.camel.IOTDeviceValue; +import com.zmops.zeus.iot.server.core.worker.data.ItemValue; +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.Processor; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +/** + * @author nantian created at 2021/8/23 17:16 + *

+ * Json 转 对象,进队列,一定要转成 ItemValue 对象,{@link ItemValue} + */ +public class ByteArrayToItemValueProcess implements Processor { + + private final Gson gson = new Gson(); + + @Override + public void process(Exchange exchange) throws Exception { + Message message = exchange.getIn(); + byte[] messageBytes = (byte[]) message.getBody(); + + String inputContext = new String(messageBytes, StandardCharsets.UTF_8); + + List valueList = gson.fromJson(inputContext, new TypeToken>() {}.getType()); + + // 多一步 命名转换,方便 Json 字段理解 + List itemValueList = new ArrayList<>(); + valueList.forEach(i -> { + ItemValue item = new ItemValue(i.getDeviceId(), i.getDeviceAttrKey(), i.getDeviceAttrValue()); + if (i.getDeviceTime() != null) { + item.setClock(i.getDeviceTime()); + } + itemValueList.add(item); + }); + exchange.getMessage().setBody(itemValueList); + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/StringItemValueProcess.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/StringItemValueProcess.java new file mode 100644 index 00000000..a2236e26 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/StringItemValueProcess.java @@ -0,0 +1,60 @@ +package com.zmops.zeus.iot.server.core.camel.process; + +import com.google.common.reflect.TypeToken; +import com.google.gson.Gson; +import com.zmops.zeus.iot.server.core.camel.IOTDeviceValue; +import com.zmops.zeus.iot.server.core.worker.data.ItemValue; +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.Processor; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * @author nantian created at 2021/8/23 17:16 + *

+ * Json 转 对象,进队列,一定要转成 ItemValue 对象,{@link ItemValue} + */ +public class StringItemValueProcess implements Processor { + + private final Gson gson = new Gson(); + + @Override + public void process(Exchange exchange) throws Exception { + Message message = exchange.getIn(); + List valueList = gson.fromJson((String) message.getBody(), new TypeToken>() {}.getType()); + + // 多一步 命名转换,方便 Json 字段理解 + List itemValueList = new ArrayList<>(); + valueList.forEach(i -> { + ItemValue item = new ItemValue(i.getDeviceId(), i.getDeviceAttrKey(), i.getDeviceAttrValue()); + if (i.getDeviceTime() != null) { + item.setClock(i.getDeviceTime()); + } + itemValueList.add(item); + }); + + exchange.getMessage().setBody(itemValueList); + } + + + private String analysisMessage(InputStream bodyStream) throws IOException { + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + byte[] contextBytes = new byte[4096]; + int realLen; + while ((realLen = bodyStream.read(contextBytes, 0, 4096)) != -1) { + outStream.write(contextBytes, 0, realLen); + } + + // 返回从Stream中读取的字串 + try { + return outStream.toString("UTF-8"); + } finally { + outStream.close(); + } + } +} diff --git a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpRouteBuilder.java b/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpRouteBuilder.java index 8b788dd9..af167f49 100644 --- a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpRouteBuilder.java +++ b/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpRouteBuilder.java @@ -1,7 +1,8 @@ package com.zmops.zeus.iot.server.receiver.http.provider; + +import com.zmops.zeus.iot.server.core.camel.process.JsonToItemValueProcess; import com.zmops.zeus.iot.server.receiver.http.predicate.HeaderPredicate; -import com.zmops.zeus.iot.server.receiver.http.process.JsonToItemValueProcess; import org.apache.camel.builder.RouteBuilder; /** @@ -19,9 +20,11 @@ public HttpRouteBuilder(HttpReceiverConfig config) { public void configure() throws Exception { fromF("netty4-http:http://0.0.0.0:%d/data/receiver?sync=true", config.getPort()) .threads(10) - .process(new JsonToItemValueProcess()) .choice() + .when(new HeaderPredicate()) + + .process(new JsonToItemValueProcess()) .to("Zabbix"); } } diff --git a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/process/MqttPacketProcess.java b/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/process/MqttPacketProcess.java deleted file mode 100644 index 868f47ca..00000000 --- a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/process/MqttPacketProcess.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.zmops.zeus.iot.server.receiver.mqtt.process; - -import org.apache.camel.Exchange; -import org.apache.camel.Processor; - -/** - * @author yefei - */ -public class MqttPacketProcess implements Processor { - - @Override - public void process(Exchange exchange) throws Exception { - System.out.println(exchange.getMessage()); - } -} diff --git a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttRouteBuilder.java b/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttRouteBuilder.java index 20490532..9558ad9f 100644 --- a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttRouteBuilder.java +++ b/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttRouteBuilder.java @@ -1,6 +1,7 @@ package com.zmops.zeus.iot.server.receiver.mqtt.provider; -import com.zmops.zeus.iot.server.receiver.mqtt.process.MqttPacketProcess; +import com.zmops.zeus.iot.server.core.camel.process.ByteArrayToItemValueProcess; +import com.zmops.zeus.iot.server.core.camel.process.JsonToItemValueProcess; import org.apache.camel.builder.RouteBuilder; /** @@ -17,8 +18,8 @@ public MqttRouteBuilder(MqttReceiverConfig mqttReceiverConfig) { @Override public void configure() throws Exception { - fromF("mqtt://127.0.0.1:%d?subscribeTopicNames=test.mqtt.topic", mqttReceiverConfig.getPort()) - .process(new MqttPacketProcess()) + fromF("mqtt:zeus-iot-mqtt?host=tcp://172.16.3.72:%d&subscribeTopicNames=test.mqtt.topic", mqttReceiverConfig.getPort()) + .process(new ByteArrayToItemValueProcess()) .to("Zabbix"); } } diff --git a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/process/TcpPacketProcess.java b/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/process/TcpPacketProcess.java index df5f2d0b..781d19e1 100644 --- a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/process/TcpPacketProcess.java +++ b/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/process/TcpPacketProcess.java @@ -11,5 +11,7 @@ public class TcpPacketProcess implements Processor { @Override public void process(Exchange exchange) throws Exception { + // 处理协议,想怎么写 就怎么写, 塞回 Body 最后 to("Zabbix"),show time !!! + } } diff --git a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpRouteBuilder.java b/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpRouteBuilder.java index fe44598f..a0f45d22 100644 --- a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpRouteBuilder.java +++ b/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpRouteBuilder.java @@ -1,6 +1,7 @@ package com.zmops.zeus.iot.server.receiver.tcp.provider; -import com.zmops.zeus.iot.server.receiver.tcp.process.TcpPacketProcess; +import com.zmops.zeus.iot.server.core.camel.process.ByteArrayToItemValueProcess; +import com.zmops.zeus.iot.server.core.camel.process.StringItemValueProcess; import org.apache.camel.builder.RouteBuilder; /** @@ -17,6 +18,8 @@ public TcpRouteBuilder(TcpReceiverConfig tcpReceiverConfig) { @Override public void configure() throws Exception { - fromF("netty4:tcp://0.0.0.0:%d", tcpReceiverConfig.getPort()).process(new TcpPacketProcess()); + fromF("netty4:tcp://0.0.0.0:%d", tcpReceiverConfig.getPort()) + .process(new StringItemValueProcess()) + .to("Zabbix"); } } From 1a4af4c297e1c8056399fdbd68782f9c5f51a2cb Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 23 Aug 2021 20:14:37 +0800 Subject: [PATCH 015/763] =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=BB=84=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/SysUserGroupController.java | 3 +- .../zmops/iot/web/sys/dto/UserGroupDto.java | 17 +++++++++ .../iot/web/sys/dto/param/UserGroupParam.java | 6 ++++ .../web/sys/service/SysUserGroupService.java | 35 +++++++++++++++---- 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserGroupController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserGroupController.java index 952937d2..d4bdddad 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserGroupController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserGroupController.java @@ -2,7 +2,6 @@ import com.zmops.iot.core.log.BussinessLog; import com.zmops.iot.domain.BaseEntity; -import com.zmops.iot.domain.sys.SysUserGroup; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.web.sys.dto.UserGroupDto; @@ -33,7 +32,7 @@ public class SysUserGroupController { * @return */ @PostMapping("/getUsrGrpByPage") - public Pager getUsrGrpByPage(@RequestBody UserGroupParam userGroupParam) { + public Pager getUsrGrpByPage(@RequestBody UserGroupParam userGroupParam) { return sysUserGroupService.userGroupPageList(userGroupParam); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java index 091b7c10..06b45535 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java @@ -16,10 +16,15 @@ package com.zmops.iot.web.sys.dto; import com.zmops.iot.domain.BaseEntity; +import io.ebean.annotation.WhenModified; +import io.ebean.annotation.WhoCreated; +import io.ebean.annotation.WhoModified; import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; +import java.util.List; /** * 用户组传输bean @@ -39,4 +44,16 @@ public class UserGroupDto { private String remark; + private List deviceGroupIds; + + //列表返回的设备组ID + private String groupIds; + + LocalDateTime createTime; + + LocalDateTime updateTime; + + Long createUser; + + Long updateUser; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/UserGroupParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/UserGroupParam.java index 54063ff7..376b9d55 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/UserGroupParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/UserGroupParam.java @@ -16,7 +16,10 @@ package com.zmops.iot.web.sys.dto.param; import com.zmops.iot.domain.BaseEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; import javax.validation.constraints.NotNull; import java.util.List; @@ -27,6 +30,9 @@ * @author yefei */ @Data +@Builder +@NoArgsConstructor +@AllArgsConstructor public class UserGroupParam extends BaseQueryParam { private String groupName; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java index 3cd71f58..43d93b81 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java @@ -19,10 +19,11 @@ import com.zmops.iot.web.sys.dto.param.UserGroupParam; import com.zmops.zeus.driver.service.ZbxUserGroup; import io.ebean.DB; -import io.ebean.PagedList; +import io.ebean.DtoQuery; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; @@ -44,15 +45,27 @@ public class SysUserGroupService { * @param userGroupParam * @return */ - public Pager userGroupPageList(UserGroupParam userGroupParam) { - + public Pager userGroupPageList(UserGroupParam userGroupParam) { QSysUserGroup qSysUserGroup = new QSysUserGroup(); + StringBuilder sql = new StringBuilder("SELECT " + + " sug.group_name, sug.remark, sug.create_time, sug.create_user, sug.update_time, sug.update_user, sug.status, sug.user_group_id, " + + " dg.groupIds " + + "FROM " + + " sys_user_group sug " + + " LEFT JOIN ( SELECT user_group_id, array_to_string( ARRAY_AGG ( device_group_id ), ',' ) groupIds FROM sys_usrgrp_devicegrp GROUP BY user_group_id ) dg " + + " ON dg.user_group_id = sug.user_group_id"); + if (ToolUtil.isNotEmpty(userGroupParam.getGroupName())) { + sql.append(" where sug.group_name like :groupName"); + } + sql.append(" order by sug.create_time desc "); + DtoQuery dto = DB.findDto(UserGroupDto.class, sql.toString()); if (ToolUtil.isNotEmpty(userGroupParam.getGroupName())) { + dto.setParameter("groupName", "%" + userGroupParam.getGroupName() + "%"); qSysUserGroup.groupName.contains(userGroupParam.getGroupName()); } - qSysUserGroup.setFirstRow((userGroupParam.getPage() - 1) * userGroupParam.getMaxRow()).setMaxRows(userGroupParam.getMaxRow()); - PagedList pagedList = qSysUserGroup.orderBy("create_time desc").findPagedList(); - return new Pager<>(pagedList.getList(), pagedList.getTotalCount()); + List list = dto.setFirstRow((userGroupParam.getPage() - 1) * userGroupParam.getMaxRow()) + .setMaxRows(userGroupParam.getMaxRow()).findList(); + return new Pager<>(list, qSysUserGroup.findCount()); } /** @@ -72,6 +85,7 @@ public List userGroupList() { /** * 添加用戶組 */ + @Transactional(rollbackFor = Exception.class) public SysUserGroup createUserGroup(UserGroupDto userGroup) { // 判断用户组是否重复 checkByGroupName(userGroup.getGroupName(), -1L); @@ -87,6 +101,10 @@ public SysUserGroup createUserGroup(UserGroupDto userGroup) { newUserGroup.setZbxId(userGrpids.get(0).toString()); DB.save(newUserGroup); + if (ToolUtil.isNotEmpty(userGroup.getDeviceGroupIds())) { + bindHostGrp(UserGroupParam.builder().userGroupId(usrGrpId).deviceGroupIds(userGroup.getDeviceGroupIds()).build()); + } + return newUserGroup; } @@ -103,6 +121,11 @@ public SysUserGroup updateUserGroup(UserGroupDto userGroup) { SysUserGroup newUserGroup = new SysUserGroup(); BeanUtils.copyProperties(userGroup, newUserGroup); DB.update(newUserGroup); + + if (ToolUtil.isNotEmpty(userGroup.getDeviceGroupIds())) { + bindHostGrp(UserGroupParam.builder().userGroupId(userGroup.getUserGroupId()).deviceGroupIds(userGroup.getDeviceGroupIds()).build()); + } + return newUserGroup; } From d8f1f8856e16f5c4cb795aad03ffa9fa13be13d8 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 23 Aug 2021 20:28:20 +0800 Subject: [PATCH 016/763] =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=8F=82=E6=95=B0=20=E4=BD=BF=E7=94=A8=20=E5=8F=98=E9=87=8F?= =?UTF-8?q?=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.yml | 56 ++++++++++--------- .../http/provider/HttpReceiverConfig.java | 5 ++ .../mqtt/provider/MqttReceiverConfig.java | 7 ++- .../mqtt/provider/MqttRouteBuilder.java | 1 - .../tcp/provider/TcpReceiverConfig.java | 8 ++- 5 files changed, 48 insertions(+), 29 deletions(-) diff --git a/iot-server/server-bootstrap/src/main/resources/application.yml b/iot-server/server-bootstrap/src/main/resources/application.yml index 4962fbe2..23685945 100644 --- a/iot-server/server-bootstrap/src/main/resources/application.yml +++ b/iot-server/server-bootstrap/src/main/resources/application.yml @@ -1,3 +1,32 @@ +# Zabbix Trapper Sender +zabbix-sender: + selector: ${ZS_RECEIVER_ZABBIX_SENDER:default} + default: + port: ${ZS_RECEIVER_ZABBIX_POST:10051} + host: ${ZS_RECEIVER_ZABBIX_HOST:127.0.0.1} + +# Http Server +receiver-http: + selector: ${ZS_RECEIVER_HTTP:-} + default: + port: ${ZS_RECEIVER_HTTP_PORT:9010} + host: ${ZS_RECEIVER_HTTP_HOST:0.0.0.0} + +# TCP Server +receiver-tcp: + selector: ${ZS_RECEIVER_TCP:-} + default: + port: ${ZS_RECEIVER_TCP_PORT:9020} + host: ${ZS_RECEIVER_TCP_HOST:0.0.0.0} + +# MQTT Client +receiver-mqtt: + selector: ${ZS_RECEIVER_MQTT:-} + default: + port: ${ZS_RECEIVER_MQTT_PORT:1883} + host: ${ZS_RECEIVER_MQTT_HOST:127.0.0.1} + + # 核心模块 core: selector: ${ZS_CORE:default} @@ -28,29 +57,4 @@ telemetry: port: ${ZS_TELEMETRY_PROMETHEUS_PORT:1234} sslEnabled: ${ZS_TELEMETRY_PROMETHEUS_SSL_ENABLED:false} sslKeyPath: ${ZS_TELEMETRY_PROMETHEUS_SSL_KEY_PATH:""} - sslCertChainPath: ${ZS_TELEMETRY_PROMETHEUS_SSL_CERT_CHAIN_PATH:""} - -# Zabbix Trapper Sender -zabbix-sender: - selector: ${ZS_RECEIVER_ZABBIX_SENDER:default} - default: - host: 172.16.3.72 - port: 10051 - -# Http Server -receiver-http: - selector: ${ZS_RECEIVER_HTTP:-} - default: - port: 9010 - -# TCP Server -receiver-tcp: - selector: ${ZS_RECEIVER_TCP:-} - default: - port: 9020 - -# MQTT Client -receiver-mqtt: - selector: ${ZS_RECEIVER_MQTT:-} - default: - port: 1883 \ No newline at end of file + sslCertChainPath: ${ZS_TELEMETRY_PROMETHEUS_SSL_CERT_CHAIN_PATH:""} \ No newline at end of file diff --git a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpReceiverConfig.java b/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpReceiverConfig.java index cd43a94c..3ca36e98 100644 --- a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpReceiverConfig.java +++ b/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpReceiverConfig.java @@ -17,4 +17,9 @@ public class HttpReceiverConfig extends ModuleConfig { * Export http port */ private int port = 8080; + + /** + * Export http host ip + */ + private String host = "0.0.0.0"; } diff --git a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttReceiverConfig.java b/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttReceiverConfig.java index d2bb261a..d7a2d73c 100644 --- a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttReceiverConfig.java +++ b/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttReceiverConfig.java @@ -14,7 +14,12 @@ public class MqttReceiverConfig extends ModuleConfig { /** - * Export http port + * Export mqtt port */ private int port = 9020; + + /** + * Export mqtt ip address + */ + private String host = "127.0.0.1"; } diff --git a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttRouteBuilder.java b/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttRouteBuilder.java index 9558ad9f..3ed528af 100644 --- a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttRouteBuilder.java +++ b/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttRouteBuilder.java @@ -1,7 +1,6 @@ package com.zmops.zeus.iot.server.receiver.mqtt.provider; import com.zmops.zeus.iot.server.core.camel.process.ByteArrayToItemValueProcess; -import com.zmops.zeus.iot.server.core.camel.process.JsonToItemValueProcess; import org.apache.camel.builder.RouteBuilder; /** diff --git a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpReceiverConfig.java b/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpReceiverConfig.java index 8ac7c9b1..9d3b6add 100644 --- a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpReceiverConfig.java +++ b/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpReceiverConfig.java @@ -14,7 +14,13 @@ public class TcpReceiverConfig extends ModuleConfig { /** - * Export http port + * Export tcp port */ private int port = 9020; + + + /** + * Export tcp host ip + */ + private String host = "0.0.0.0"; } From 1886f5b601e2a3ede735230cc31df5aca263f034 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 23 Aug 2021 20:37:07 +0800 Subject: [PATCH 017/763] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20execute=5Fon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/api-json/script/script.init.create.ftl | 2 +- zeus-starter/src/main/resources/application.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl b/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl index 2321d950..837be555 100644 --- a/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl +++ b/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl @@ -5,7 +5,7 @@ "name": "__offline_status__", "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"hostname\\":\\"{HOST.HOST}\\",\\"deviceStatus\\":\\"{EVENT.ID}\\"}' http://${zeusServerIp}:${zeusServerPort}/rest/device/webhook", "type": 0, - "execute_on": 1 + "execute_on": 2 }, "auth": "${userAuth}", "id": 1 diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index 3322eefa..54e3be20 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -43,7 +43,7 @@ forest: zbxServerPort: ${ZEUS_ZABBIX_PORT:10051} zbxApiToken: e39f259dc2b5a5deb583531380a56d85 - ## 设备状态变更 等回调地址 + ## 设备触发告警,执行动作回调 IOT-SERVER 处理 zeusServerIp: ${ZEUS_CALLBACK_HOST:127.0.0.1} zeusServerPort: ${ZEUS_CALLBACK_PORT:9090} interceptors: From e5c005441755e2833b236909f748d98e01425509 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 24 Aug 2021 00:44:22 +0800 Subject: [PATCH 018/763] add module EventBus --- iot-common/iot-eventbus/pom.xml | 29 +++ .../eventbus/constant/EventConstant.java | 15 ++ .../zeus/iot/server/eventbus/core/Event.java | 41 ++++ .../server/eventbus/core/EventController.java | 23 ++ .../eventbus/core/EventControllerFactory.java | 98 +++++++++ .../eventbus/core/EventControllerImpl.java | 46 ++++ .../iot/server/eventbus/core/EventType.java | 31 +++ .../eventbus/thread/ThreadPoolFactory.java | 193 +++++++++++++++++ .../thread/constant/ThreadConstant.java | 19 ++ .../thread/entity/ThreadCustomization.java | 70 ++++++ .../thread/entity/ThreadParameter.java | 42 ++++ .../thread/entity/ThreadQueueType.java | 32 +++ .../entity/ThreadRejectedPolicyType.java | 34 +++ .../thread/policy/AbortPolicyWithReport.java | 31 +++ .../policy/BlockingPolicyWithReport.java | 47 ++++ .../policy/CallerRunsPolicyWithReport.java | 30 +++ .../policy/DiscardedPolicyWithReport.java | 43 ++++ .../policy/RejectedPolicyWithReport.java | 51 +++++ .../thread/policy/RejectedRunnable.java | 6 + .../server/eventbus/thread/util/NetUtil.java | 204 ++++++++++++++++++ .../eventbus/thread/util/StringUtil.java | 15 ++ .../zeus/iot/server/core/CoreModule.java | 2 + 22 files changed, 1102 insertions(+) create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/constant/EventConstant.java create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/Event.java create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventController.java create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerImpl.java create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventType.java create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/ThreadPoolFactory.java create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/constant/ThreadConstant.java create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadCustomization.java create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadParameter.java create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadQueueType.java create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadRejectedPolicyType.java create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/AbortPolicyWithReport.java create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/BlockingPolicyWithReport.java create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/CallerRunsPolicyWithReport.java create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/DiscardedPolicyWithReport.java create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/RejectedPolicyWithReport.java create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/RejectedRunnable.java create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/NetUtil.java create mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/StringUtil.java diff --git a/iot-common/iot-eventbus/pom.xml b/iot-common/iot-eventbus/pom.xml index 6a3d5e21..d2072cd8 100644 --- a/iot-common/iot-eventbus/pom.xml +++ b/iot-common/iot-eventbus/pom.xml @@ -17,4 +17,33 @@ 8 + + + org.apache.commons + commons-lang3 + 3.4 + + + com.google.guava + guava + 25.1-jre + + + org.projectlombok + lombok + 1.18.20 + + + + org.apache.logging.log4j + log4j-api + 2.13.3 + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.13.3 + + + \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/constant/EventConstant.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/constant/EventConstant.java new file mode 100644 index 00000000..a08b0887 --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/constant/EventConstant.java @@ -0,0 +1,15 @@ +package com.zmops.zeus.iot.server.eventbus.constant; + +/** + * Created by nantian on 2021-03-11 0:25 + * + * @version 1.0 + */ +public class EventConstant { + + public static final String EVENTBUS_VERSION = "2.0.13"; + + public static final String EVENTBUS_ENABLED = "eventbus.enabled"; + + public static final String SHARED_CONTROLLER = "SharedController"; +} diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/Event.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/Event.java new file mode 100644 index 00000000..c5567f30 --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/Event.java @@ -0,0 +1,41 @@ +package com.zmops.zeus.iot.server.eventbus.core; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.io.Serializable; + +public class Event implements Serializable { + private static final long serialVersionUID = 7090050666419528496L; + + protected Object source; + + public Event() { + this(null); + } + + public Event(Object source) { + this.source = source; + } + + public Object getSource() { + return source; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object object) { + return EqualsBuilder.reflectionEquals(this, object); + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventController.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventController.java new file mode 100644 index 00000000..62312777 --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventController.java @@ -0,0 +1,23 @@ +package com.zmops.zeus.iot.server.eventbus.core; + +import java.util.Collection; + +/** + * EventBus 控制器 + * + * @author nantian + */ +public interface EventController { + + void register(Object object); + + void unregister(Object object); + + void post(Object event); + + void post(Collection event); + + void postEvent(Event event); + + void postEvent(Collection events); +} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java new file mode 100644 index 00000000..feaa7060 --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java @@ -0,0 +1,98 @@ +package com.zmops.zeus.iot.server.eventbus.core; + +import com.google.common.eventbus.AsyncEventBus; +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.SubscriberExceptionHandler; + + +import com.zmops.zeus.iot.server.eventbus.constant.EventConstant; +import com.zmops.zeus.iot.server.eventbus.thread.ThreadPoolFactory; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executor; + + public final class EventControllerFactory { + + private final ThreadPoolFactory threadPoolFactory; + + public EventControllerFactory(ThreadPoolFactory threadPoolFactory) { + this.threadPoolFactory = threadPoolFactory; + } + + private final Map syncControllerMap = new ConcurrentHashMap(); + private final Map asyncControllerMap = new ConcurrentHashMap(); + + public EventController getAsyncController() { + return getAsyncController(EventConstant.SHARED_CONTROLLER); + } + + public EventController getAsyncController(String identifier) { + return getController(identifier, true); + } + + public EventController getSyncController() { + return getSyncController(EventConstant.SHARED_CONTROLLER); + } + + public EventController getSyncController(String identifier) { + return getController(identifier, false); + } + + public EventController getController(String identifier, boolean async) { + return getController(identifier, async ? EventType.ASYNC : EventType.SYNC); + } + + public EventController getController(String identifier, EventType type) { + switch (type) { + case SYNC: + EventController syncEventController = syncControllerMap.get(identifier); + if (syncEventController == null) { + EventController newEventController = createSyncController(identifier); + syncEventController = syncControllerMap.putIfAbsent(identifier, newEventController); + if (syncEventController == null) { + syncEventController = newEventController; + } + } + + return syncEventController; + case ASYNC: + EventController asyncEventController = asyncControllerMap.get(identifier); + if (asyncEventController == null) { + EventController newEventController = createAsyncController(identifier, threadPoolFactory.getThreadPoolExecutor(identifier)); + asyncEventController = asyncControllerMap.putIfAbsent(identifier, newEventController); + if (asyncEventController == null) { + asyncEventController = newEventController; + } + } + + return asyncEventController; + } + + return null; + } + + public EventController createSyncController() { + return new EventControllerImpl(new EventBus()); + } + + public EventController createSyncController(String identifier) { + return new EventControllerImpl(new EventBus(identifier)); + } + + public EventController createSyncController(SubscriberExceptionHandler subscriberExceptionHandler) { + return new EventControllerImpl(new EventBus(subscriberExceptionHandler)); + } + + public EventController createAsyncController(String identifier, Executor executor) { + return new EventControllerImpl(new AsyncEventBus(identifier, executor)); + } + + public EventController createAsyncController(Executor executor, SubscriberExceptionHandler subscriberExceptionHandler) { + return new EventControllerImpl(new AsyncEventBus(executor, subscriberExceptionHandler)); + } + + public EventController createAsyncController(Executor executor) { + return new EventControllerImpl(new AsyncEventBus(executor)); + } +} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerImpl.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerImpl.java new file mode 100644 index 00000000..58b186c3 --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerImpl.java @@ -0,0 +1,46 @@ +package com.zmops.zeus.iot.server.eventbus.core; + +import com.google.common.eventbus.EventBus; + +import java.util.Collection; + +public class EventControllerImpl implements EventController { + + private final EventBus eventBus; + + public EventControllerImpl(EventBus eventBus) { + this.eventBus = eventBus; + } + + @Override + public void register(Object object) { + eventBus.register(object); + } + + @Override + public void unregister(Object object) { + eventBus.unregister(object); + } + + @Override + public void post(Object event) { + eventBus.post(event); + } + + @Override + public void post(Collection events) { + for (Object event : events) { + eventBus.post(event); + } + } + + @Override + public void postEvent(Event event) { + post(event); + } + + @Override + public void postEvent(Collection events) { + post(events); + } +} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventType.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventType.java new file mode 100644 index 00000000..1f8fd650 --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventType.java @@ -0,0 +1,31 @@ +package com.zmops.zeus.iot.server.eventbus.core; + +public enum EventType { + SYNC("Sync"), + ASYNC("Async"); + + private final String value; + + private EventType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public static EventType fromString(String value) { + for (EventType type : EventType.values()) { + if (type.getValue().equalsIgnoreCase(value.trim())) { + return type; + } + } + + throw new IllegalArgumentException("Mismatched type with value=" + value); + } + + @Override + public String toString() { + return value; + } +} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/ThreadPoolFactory.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/ThreadPoolFactory.java new file mode 100644 index 00000000..9b646270 --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/ThreadPoolFactory.java @@ -0,0 +1,193 @@ +package com.zmops.zeus.iot.server.eventbus.thread; + + +import com.zmops.zeus.iot.server.eventbus.thread.constant.ThreadConstant; +import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadCustomization; +import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadParameter; +import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadQueueType; +import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadRejectedPolicyType; +import com.zmops.zeus.iot.server.eventbus.thread.policy.*; +import com.zmops.zeus.iot.server.eventbus.thread.util.NetUtil; +import com.zmops.zeus.iot.server.eventbus.thread.util.StringUtil; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * 线程池工厂类 + * + * @author nantian + */ +public class ThreadPoolFactory { + private static final Logger LOG = LoggerFactory.getLogger(ThreadPoolFactory.class); + + private final Map threadPoolExecutorMap = new ConcurrentHashMap(); + private ThreadPoolExecutor threadPoolExecutor; + + private final ThreadCustomization threadCustomization; + private final ThreadParameter threadParameter; + + public ThreadPoolFactory(ThreadCustomization threadCustomization, ThreadParameter threadParameter) { + this.threadCustomization = threadCustomization; + this.threadParameter = threadParameter; + } + + public ThreadPoolExecutor getThreadPoolExecutor(String threadPoolName) { + boolean threadPoolMultiMode = threadCustomization.isThreadPoolMultiMode(); + String poolName = createThreadPoolName(threadPoolName); + + if (threadPoolMultiMode) { + ThreadPoolExecutor threadPoolExecutor = threadPoolExecutorMap.get(poolName); + if (threadPoolExecutor == null) { + ThreadPoolExecutor newThreadPoolExecutor = createThreadPoolExecutor(poolName); + threadPoolExecutor = threadPoolExecutorMap.putIfAbsent(poolName, newThreadPoolExecutor); + if (threadPoolExecutor == null) { + threadPoolExecutor = newThreadPoolExecutor; + } + } + + return threadPoolExecutor; + } else { + return createSharedThreadPoolExecutor(); + } + } + + private ThreadPoolExecutor createSharedThreadPoolExecutor() { + String threadPoolSharedName = threadCustomization.getThreadPoolSharedName(); + if (StringUtils.isEmpty(threadPoolSharedName)) { + threadPoolSharedName = ThreadConstant.DEFAULT_THREADPOOL_SHARED_NAME; + } + + String poolName = createThreadPoolName(threadPoolSharedName); + if (threadPoolExecutor == null) { + synchronized (ThreadPoolFactory.class) { + if (threadPoolExecutor == null) { + threadPoolExecutor = createThreadPoolExecutor(poolName); + } + } + } + + return threadPoolExecutor; + } + + private String createThreadPoolName(String threadPoolName) { + boolean threadPoolNameIPShown = threadCustomization.isThreadPoolNameIPShown(); + + return threadPoolNameIPShown ? StringUtil.firstLetterToUpper(threadPoolName) + "-" + NetUtil.getLocalHost() + "-thread" : StringUtil.firstLetterToUpper(threadPoolName) + "-thread"; + } + + private ThreadPoolExecutor createThreadPoolExecutor(String threadPoolName) { + boolean threadPoolNameCustomized = threadCustomization.isThreadPoolNameCustomized(); + + return threadPoolNameCustomized ? createThreadPoolExecutor(threadPoolName, threadParameter) : createThreadPoolExecutor(threadParameter); + } + + public static ThreadPoolExecutor createThreadPoolExecutor(String threadPoolName, ThreadParameter threadParameter) { + int corePoolSize = threadParameter.getThreadPoolCorePoolSize(); + int maximumPoolSize = threadParameter.getThreadPoolMaximumPoolSize(); + long keepAliveTime = threadParameter.getThreadPoolKeepAliveTime(); + boolean allowCoreThreadTimeout = threadParameter.isThreadPoolAllowCoreThreadTimeout(); + String queue = threadParameter.getThreadPoolQueue(); + int queueCapacity = threadParameter.getThreadPoolQueueCapacity(); + String rejectedPolicy = threadParameter.getThreadPoolRejectedPolicy(); + + LOG.info("Thread pool executor is created, threadPoolName={}, threadParameter={}", threadPoolName, threadParameter); + + ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, + maximumPoolSize, + keepAliveTime, + TimeUnit.MILLISECONDS, + Objects.requireNonNull(createBlockingQueue(queue, queueCapacity)), + new ThreadFactory() { + private final AtomicInteger number = new AtomicInteger(0); + + @Override + public Thread newThread(Runnable runnable) { + return new Thread(runnable, threadPoolName + "-" + number.getAndIncrement()); + } + }, + Objects.requireNonNull(createRejectedPolicy(rejectedPolicy))); + threadPoolExecutor.allowCoreThreadTimeOut(allowCoreThreadTimeout); + + return threadPoolExecutor; + } + + public static ThreadPoolExecutor createThreadPoolExecutor(ThreadParameter threadParameter) { + int corePoolSize = threadParameter.getThreadPoolCorePoolSize(); + int maximumPoolSize = threadParameter.getThreadPoolMaximumPoolSize(); + long keepAliveTime = threadParameter.getThreadPoolKeepAliveTime(); + boolean allowCoreThreadTimeout = threadParameter.isThreadPoolAllowCoreThreadTimeout(); + String queue = threadParameter.getThreadPoolQueue(); + int queueCapacity = threadParameter.getThreadPoolQueueCapacity(); + String rejectedPolicy = threadParameter.getThreadPoolRejectedPolicy(); + + LOG.info("Thread pool executor is created, threadParameter={}", threadParameter); + + ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, + maximumPoolSize, + keepAliveTime, + TimeUnit.MILLISECONDS, + Objects.requireNonNull(createBlockingQueue(queue, queueCapacity)), + Objects.requireNonNull(createRejectedPolicy(rejectedPolicy))); + threadPoolExecutor.allowCoreThreadTimeOut(allowCoreThreadTimeout); + + return threadPoolExecutor; + } + + private static BlockingQueue createBlockingQueue(String queue, int queueCapacity) { + ThreadQueueType queueType = ThreadQueueType.fromString(queue); + + switch (queueType) { + case LINKED_BLOCKING_QUEUE: + return new LinkedBlockingQueue(queueCapacity); + case ARRAY_BLOCKING_QUEUE: + return new ArrayBlockingQueue(queueCapacity); + case SYNCHRONOUS_QUEUE: + return new SynchronousQueue(); + } + + return null; + } + + private static RejectedExecutionHandler createRejectedPolicy(String rejectedPolicy) { + ThreadRejectedPolicyType rejectedPolicyType = ThreadRejectedPolicyType.fromString(rejectedPolicy); + + switch (rejectedPolicyType) { + case BLOCKING_POLICY_WITH_REPORT: + return new BlockingPolicyWithReport(); + case CALLER_RUNS_POLICY_WITH_REPORT: + return new CallerRunsPolicyWithReport(); + case ABORT_POLICY_WITH_REPORT: + return new AbortPolicyWithReport(); + case REJECTED_POLICY_WITH_REPORT: + return new RejectedPolicyWithReport(); + case DISCARDED_POLICY_WITH_REPORT: + return new DiscardedPolicyWithReport(); + } + + return null; + } + + public void shutdown() { + if (threadPoolExecutor != null && !threadPoolExecutor.isShutdown()) { + LOG.info("Shutting down thread pool executor [{}]...", threadPoolExecutor); + + threadPoolExecutor.shutdown(); + } + + for (Map.Entry entry : threadPoolExecutorMap.entrySet()) { + ThreadPoolExecutor executor = entry.getValue(); + + if (executor != null && !executor.isShutdown()) { + LOG.info("Shutting down thread pool executor [{}] ...", threadPoolExecutor); + + executor.shutdown(); + } + } + } +} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/constant/ThreadConstant.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/constant/ThreadConstant.java new file mode 100644 index 00000000..42d6eaa2 --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/constant/ThreadConstant.java @@ -0,0 +1,19 @@ +package com.zmops.zeus.iot.server.eventbus.thread.constant; + +public class ThreadConstant { + public static final int CPUS = Math.max(2, Runtime.getRuntime().availableProcessors()); + + public static final String THREAD_POOL_MULTI_MODE = "threadpool.multi.mode"; + public static final String THREAD_POOL_SHARED_NAME = "threadpool.shared.name"; + public static final String THREAD_POOL_NAME_CUSTOMIZED = "threadpool.name.customized"; + public static final String THREAD_POOL_NAME_IP_SHOWN = "threadpool.name.ipshown"; + public static final String THREAD_POOL_CORE_POOL_SIZE = "threadpool.core.pool.size"; + public static final String THREAD_POOL_MAXIMUM_POOL_SIZE = "threadpool.maximum.pool.size"; + public static final String THREAD_POOL_KEEP_ALIVE_TIME = "threadpool.keep.alive.time"; + public static final String THREAD_POOL_ALLOW_CORE_THREAD_TIMEOUT = "threadpool.allow.core.thread.timeout"; + public static final String THREAD_POOL_QUEUE = "threadpool.queue"; + public static final String THREAD_POOL_QUEUE_CAPACITY = "threadpool.queue.capacity"; + public static final String THREAD_POOL_REJECTED_POLICY = "threadpool.rejected.policy"; + + public static final String DEFAULT_THREADPOOL_SHARED_NAME = "SharedThreadPool"; +} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadCustomization.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadCustomization.java new file mode 100644 index 00000000..35492bda --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadCustomization.java @@ -0,0 +1,70 @@ +package com.zmops.zeus.iot.server.eventbus.thread.entity; + + +import com.zmops.zeus.iot.server.eventbus.thread.constant.ThreadConstant; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.io.Serializable; + + +/** + * + */ +public class ThreadCustomization implements Serializable { + private static final long serialVersionUID = -927120657442228832L; + + private boolean threadPoolMultiMode = false; + private String threadPoolSharedName = ThreadConstant.DEFAULT_THREADPOOL_SHARED_NAME; + private boolean threadPoolNameCustomized = true; + private boolean threadPoolNameIPShown = true; + + public boolean isThreadPoolMultiMode() { + return threadPoolMultiMode; + } + + public void setThreadPoolMultiMode(boolean threadPoolMultiMode) { + this.threadPoolMultiMode = threadPoolMultiMode; + } + + public String getThreadPoolSharedName() { + return threadPoolSharedName; + } + + public void setThreadPoolSharedName(String threadPoolSharedName) { + this.threadPoolSharedName = threadPoolSharedName; + } + + public boolean isThreadPoolNameCustomized() { + return threadPoolNameCustomized; + } + + public void setThreadPoolNameCustomized(boolean threadPoolNameCustomized) { + this.threadPoolNameCustomized = threadPoolNameCustomized; + } + + public boolean isThreadPoolNameIPShown() { + return threadPoolNameIPShown; + } + + public void setThreadPoolNameIPShown(boolean threadPoolNameIPShown) { + this.threadPoolNameIPShown = threadPoolNameIPShown; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object object) { + return EqualsBuilder.reflectionEquals(this, object); + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadParameter.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadParameter.java new file mode 100644 index 00000000..244e12f2 --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadParameter.java @@ -0,0 +1,42 @@ +package com.zmops.zeus.iot.server.eventbus.thread.entity; + + +import com.zmops.zeus.iot.server.eventbus.thread.constant.ThreadConstant; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.io.Serializable; + +@Getter +@Setter +public class ThreadParameter implements Serializable { + private static final long serialVersionUID = 6869706244434951605L; + + private int threadPoolCorePoolSize = ThreadConstant.CPUS; + private int threadPoolMaximumPoolSize = ThreadConstant.CPUS * 2; + private long threadPoolKeepAliveTime = 900000; + private boolean threadPoolAllowCoreThreadTimeout = false; + private String threadPoolQueue = "LinkedBlockingQueue"; + private int threadPoolQueueCapacity = ThreadConstant.CPUS * 128; + private String threadPoolRejectedPolicy = "BlockingPolicyWithReport"; + + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object object) { + return EqualsBuilder.reflectionEquals(this, object); + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadQueueType.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadQueueType.java new file mode 100644 index 00000000..e6c13050 --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadQueueType.java @@ -0,0 +1,32 @@ +package com.zmops.zeus.iot.server.eventbus.thread.entity; + +public enum ThreadQueueType { + LINKED_BLOCKING_QUEUE("LinkedBlockingQueue"), + ARRAY_BLOCKING_QUEUE("ArrayBlockingQueue"), + SYNCHRONOUS_QUEUE("SynchronousQueue"); + + private final String value; + + private ThreadQueueType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public static ThreadQueueType fromString(String value) { + for (ThreadQueueType type : ThreadQueueType.values()) { + if (type.getValue().equalsIgnoreCase(value.trim())) { + return type; + } + } + + throw new IllegalArgumentException("Mismatched type with value=" + value); + } + + @Override + public String toString() { + return value; + } +} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadRejectedPolicyType.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadRejectedPolicyType.java new file mode 100644 index 00000000..c329d831 --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadRejectedPolicyType.java @@ -0,0 +1,34 @@ +package com.zmops.zeus.iot.server.eventbus.thread.entity; + +public enum ThreadRejectedPolicyType { + BLOCKING_POLICY_WITH_REPORT("BlockingPolicyWithReport"), + CALLER_RUNS_POLICY_WITH_REPORT("CallerRunsPolicyWithReport"), + ABORT_POLICY_WITH_REPORT("AbortPolicyWithReport"), + REJECTED_POLICY_WITH_REPORT("RejectedPolicyWithReport"), + DISCARDED_POLICY_WITH_REPORT("DiscardedPolicyWithReport"); + + private final String value; + + private ThreadRejectedPolicyType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public static ThreadRejectedPolicyType fromString(String value) { + for (ThreadRejectedPolicyType type : ThreadRejectedPolicyType.values()) { + if (type.getValue().equalsIgnoreCase(value.trim())) { + return type; + } + } + + throw new IllegalArgumentException("Mismatched type with value=" + value); + } + + @Override + public String toString() { + return value; + } +} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/AbortPolicyWithReport.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/AbortPolicyWithReport.java new file mode 100644 index 00000000..12fb2cc9 --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/AbortPolicyWithReport.java @@ -0,0 +1,31 @@ +package com.zmops.zeus.iot.server.eventbus.thread.policy; + + +import lombok.extern.slf4j.Slf4j; + +import java.util.concurrent.ThreadPoolExecutor; + +// 任务饱和时, 抛弃任务,抛出异常 +@Slf4j +public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy { + + + private final String threadName; + + public AbortPolicyWithReport() { + this(null); + } + + public AbortPolicyWithReport(String threadName) { + this.threadName = threadName; + } + + @Override + public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) { + if (threadName != null) { + log.error("Thread pool [{}] is exhausted, executor={}", threadName, executor.toString()); + } + + super.rejectedExecution(runnable, executor); + } +} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/BlockingPolicyWithReport.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/BlockingPolicyWithReport.java new file mode 100644 index 00000000..8af23ad8 --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/BlockingPolicyWithReport.java @@ -0,0 +1,47 @@ +package com.zmops.zeus.iot.server.eventbus.thread.policy; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ThreadPoolExecutor; + +// 使用阻塞生产者的饱和策略,不抛弃任务,也不抛出异常,当队列满时改为调用BlockingQueue.put来实现生产者的阻塞 +public class BlockingPolicyWithReport implements RejectedExecutionHandler { + private static final Logger LOG = LoggerFactory.getLogger(BlockingPolicyWithReport.class); + + private final String threadName; + + public BlockingPolicyWithReport() { + this(null); + } + + public BlockingPolicyWithReport(String threadName) { + this.threadName = threadName; + } + + // 队列用法: + // 1.add 增加一个元素,如果队列已满,则抛出一个IIIegaISlabEepeplian异常 + // 2.remove 移除并返回队列头部的元素,如果队列为空,则抛出一个NoSuchElementException异常 + // 3.element 返回队列头部的元素,如果队列为空,则抛出一个NoSuchElementException异常 + // 4.offer 添加一个元素并返回true,如果队列已满,则返回false + // 5.poll 移除并返问队列头部的元素,如果队列为空,则返回null + // 6.peek 返回队列头部的元,如果队列为空,则返回null + // 7.put 添加一个元素,如果队列已满,则阻塞 + // 8.take 移除并返回队列头部的元素,如果队列为空,则阻塞 + @Override + public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) { + if (threadName != null) { + LOG.error("Thread pool [{}] is exhausted, executor={}", threadName, executor.toString()); + } + + if (!executor.isShutdown()) { + try { + // 添加一个元素, 如果队列满,则阻塞 + executor.getQueue().put(runnable); + } catch (InterruptedException e) { + // should not be interrupted + } + } + } +} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/CallerRunsPolicyWithReport.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/CallerRunsPolicyWithReport.java new file mode 100644 index 00000000..88817867 --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/CallerRunsPolicyWithReport.java @@ -0,0 +1,30 @@ +package com.zmops.zeus.iot.server.eventbus.thread.policy; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.ThreadPoolExecutor; + +// 使用Caller-Runs(调用者执行)饱和策略,不抛弃任务,也不抛出异常,而是将当前任务回退到发起这个调用者执行的线程所在的上级线程去执行 +public class CallerRunsPolicyWithReport extends ThreadPoolExecutor.CallerRunsPolicy { + private static final Logger LOG = LoggerFactory.getLogger(CallerRunsPolicyWithReport.class); + + private final String threadName; + + public CallerRunsPolicyWithReport() { + this(null); + } + + public CallerRunsPolicyWithReport(String threadName) { + this.threadName = threadName; + } + + @Override + public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) { + if (threadName != null) { + LOG.error("Thread pool [{}] is exhausted, executor={}", threadName, executor.toString()); + } + + super.rejectedExecution(runnable, executor); + } +} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/DiscardedPolicyWithReport.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/DiscardedPolicyWithReport.java new file mode 100644 index 00000000..93d5b333 --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/DiscardedPolicyWithReport.java @@ -0,0 +1,43 @@ +package com.zmops.zeus.iot.server.eventbus.thread.policy; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ThreadPoolExecutor; + +// 任务饱和时以FIFO的方式抛弃队列中一部分现有任务,再添加新任务 +public class DiscardedPolicyWithReport implements RejectedExecutionHandler { + private static final Logger LOG = LoggerFactory.getLogger(DiscardedPolicyWithReport.class); + + private final String threadName; + + public DiscardedPolicyWithReport() { + this(null); + } + + public DiscardedPolicyWithReport(String threadName) { + this.threadName = threadName; + } + + @Override + public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) { + if (threadName != null) { + LOG.error("Thread pool [{}] is exhausted, executor={}", threadName, executor.toString()); + } + + if (!executor.isShutdown()) { + BlockingQueue queue = executor.getQueue(); + // 舍弃1/2队列元素,例如7个单位的元素,舍弃3个 + int discardSize = queue.size() >> 1; + for (int i = 0; i < discardSize; i++) { + // 从头部移除并返问队列头部的元素 + queue.poll(); + } + + // 添加元素,如果队列满,不阻塞,返回false + queue.offer(runnable); + } + } +} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/RejectedPolicyWithReport.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/RejectedPolicyWithReport.java new file mode 100644 index 00000000..da7cbb9c --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/RejectedPolicyWithReport.java @@ -0,0 +1,51 @@ +package com.zmops.zeus.iot.server.eventbus.thread.policy; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ThreadPoolExecutor; + +// 如果该任务实现了RejectedRunnable接口,那么交给用户去实现拒绝服务的逻辑,否则以FIFO的方式抛弃队列中一部分现有任务,再添加新任务 +public class RejectedPolicyWithReport implements RejectedExecutionHandler { + private static final Logger LOG = LoggerFactory.getLogger(RejectedPolicyWithReport.class); + + private final String threadName; + + public RejectedPolicyWithReport() { + this(null); + } + + public RejectedPolicyWithReport(String threadName) { + this.threadName = threadName; + } + + @Override + public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) { + if (threadName != null) { + LOG.error("Thread pool [{}] is exhausted, executor={}", threadName, executor.toString()); + } + + if (runnable instanceof RejectedRunnable) { + ((RejectedRunnable) runnable).rejected(); // 交给用户来处理 + } else { + if (!executor.isShutdown()) { + BlockingQueue queue = executor.getQueue(); + // 舍弃1/2队列元素,例如7个单位的元素,舍弃3个 + int discardSize = queue.size() >> 1; + for (int i = 0; i < discardSize; i++) { + // 从头部移除并返问队列头部的元素 + queue.poll(); + } + + try { + // 添加一个元素, 如果队列满,则阻塞 + queue.put(runnable); + } catch (InterruptedException e) { + // should not be interrupted + } + } + } + } +} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/RejectedRunnable.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/RejectedRunnable.java new file mode 100644 index 00000000..64b9ce1c --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/RejectedRunnable.java @@ -0,0 +1,6 @@ +package com.zmops.zeus.iot.server.eventbus.thread.policy; + +public interface RejectedRunnable extends Runnable { + // 如果任务被拒绝,用户自行处理 + void rejected(); +} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/NetUtil.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/NetUtil.java new file mode 100644 index 00000000..bcd7e9cc --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/NetUtil.java @@ -0,0 +1,204 @@ +package com.zmops.zeus.iot.server.eventbus.thread.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.*; +import java.util.Enumeration; +import java.util.Random; +import java.util.regex.Pattern; + +public class NetUtil { + private static final Logger LOG = LoggerFactory.getLogger(NetUtil.class); + + public static final String LOCALHOST = "localhost"; + public static final String LOCALHOST_IP = "127.0.0.1"; + public static final String ANYHOST_IP = "0.0.0.0"; + + private static final Random RANDOM = new Random(System.currentTimeMillis()); + private static final int RND_PORT_START = 30000; + private static final int RND_PORT_RANGE = 10000; + private static final int MIN_PORT = 0; + private static final int MAX_PORT = 65535; + + private static final Pattern ADDRESS_PATTERN = Pattern.compile("^\\d{1,3}(\\.\\d{1,3}){3}\\:\\d{1,5}$"); + private static final Pattern LOCAL_IP_PATTERN = Pattern.compile("127(\\.\\d{1,3}){3}$"); + private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$"); + + private static volatile InetAddress LOCAL_ADDRESS = null; + + public static int getRandomPort() { + return RND_PORT_START + RANDOM.nextInt(RND_PORT_RANGE); + } + + public static int getAvailablePort() { + ServerSocket serverSocket = null; + try { + serverSocket = new ServerSocket(); + serverSocket.bind(null); + + return serverSocket.getLocalPort(); + } catch (IOException e) { + return getRandomPort(); + } finally { + if (serverSocket != null) { + try { + serverSocket.close(); + } catch (IOException e) { + } + } + } + } + + public static int getAvailablePort(int port) { + if (port <= 0) { + return getAvailablePort(); + } + + for (int i = port; i < MAX_PORT; i++) { + ServerSocket serverSocket = null; + try { + serverSocket = new ServerSocket(i); + return i; + } catch (IOException e) { + } finally { + if (serverSocket != null) { + try { + serverSocket.close(); + } catch (IOException e) { + } + } + } + } + + return port; + } + + public static boolean isInvalidPort(int port) { + return port <= MIN_PORT || port > MAX_PORT; + } + + public static boolean isValidAddress(String address) { + return ADDRESS_PATTERN.matcher(address).matches(); + } + + public static boolean isLocalHost(String host) { + return host != null && (LOCAL_IP_PATTERN.matcher(host).matches() || host.equalsIgnoreCase(LOCALHOST)); + } + + public static boolean isAnyHost(String host) { + return ANYHOST_IP.equals(host); + } + + public static boolean isInvalidLocalHost(String host) { + return host == null || host.length() == 0 || host.equalsIgnoreCase(LOCALHOST) || host.equals(ANYHOST_IP) || (LOCAL_IP_PATTERN.matcher(host).matches()); + } + + public static boolean isValidLocalHost(String host) { + return !isInvalidLocalHost(host); + } + + public static InetSocketAddress getLocalSocketAddress(String host, int port) { + return isInvalidLocalHost(host) ? new InetSocketAddress(port) : new InetSocketAddress(host, port); + } + + static boolean isValidAddress(InetAddress address) { + if (address == null || address.isLoopbackAddress()) { + return false; + } + + String name = address.getHostAddress(); + + return (name != null && !ANYHOST_IP.equals(name) && !LOCALHOST_IP.equals(name) && IP_PATTERN.matcher(name).matches()); + } + + public static String getLocalHost() { + InetAddress address = getLocalAddress(); + + return address == null ? LOCALHOST_IP : address.getHostAddress(); + } + + /** + * Find first valid IP from local network card + * @return first valid local IP + */ + public static InetAddress getLocalAddress() { + if (LOCAL_ADDRESS != null) { + return LOCAL_ADDRESS; + } + + InetAddress localAddress = getLocalAddress0(); + LOCAL_ADDRESS = localAddress; + + return localAddress; + } + + private static InetAddress getLocalAddress0() { + InetAddress localAddress = null; + try { + localAddress = InetAddress.getLocalHost(); + if (isValidAddress(localAddress)) { + return localAddress; + } + } catch (Throwable e) { + LOG.warn("Get local address0 failed", e); + } + try { + Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); + if (interfaces != null) { + while (interfaces.hasMoreElements()) { + try { + NetworkInterface network = interfaces.nextElement(); + Enumeration addresses = network.getInetAddresses(); + if (addresses != null) { + while (addresses.hasMoreElements()) { + try { + InetAddress address = addresses.nextElement(); + if (isValidAddress(address)) { + return address; + } + } catch (Throwable e) { + LOG.warn("Get local address0 failed", e); + } + } + } + } catch (Throwable e) { + LOG.warn("Get local address0 failed", e); + } + } + } + } catch (Throwable e) { + LOG.warn("Get local address0 failed", e); + } + + return localAddress; + } + + public static String getIpByHost(String hostName) { + try { + return InetAddress.getByName(hostName).getHostAddress(); + } catch (UnknownHostException e) { + return hostName; + } + } + + public static String toAddressString(InetSocketAddress address) { + return address.getAddress().getHostAddress() + ":" + address.getPort(); + } + + public static InetSocketAddress toAddress(String address) { + int i = address.indexOf(':'); + String host; + int port; + if (i > -1) { + host = address.substring(0, i); + port = Integer.parseInt(address.substring(i + 1)); + } else { + host = address; + port = 0; + } + + return new InetSocketAddress(host, port); + } +} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/StringUtil.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/StringUtil.java new file mode 100644 index 00000000..762d39f7 --- /dev/null +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/StringUtil.java @@ -0,0 +1,15 @@ +package com.zmops.zeus.iot.server.eventbus.thread.util; + +public class StringUtil { + public static String firstLetterToUpper(String value) { + Character character = Character.toUpperCase(value.charAt(0)); + + return character.toString().concat(value.substring(1)); + } + + public static String firstLetterToLower(String value) { + Character character = Character.toLowerCase(value.charAt(0)); + + return character.toString().concat(value.substring(1)); + } +} \ No newline at end of file diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModule.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModule.java index 245bce7f..4ba8bfc5 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModule.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModule.java @@ -1,6 +1,7 @@ package com.zmops.zeus.iot.server.core; import com.zmops.zeus.iot.server.core.camel.CamelContextHolderService; +import com.zmops.zeus.iot.server.core.eventbus.EventBusService; import com.zmops.zeus.iot.server.core.server.JettyHandlerRegister; import com.zmops.zeus.iot.server.core.servlet.HttpItemTrapperHandler; import com.zmops.zeus.iot.server.library.module.ModuleDefine; @@ -25,6 +26,7 @@ public Class[] services() { classes.add(JettyHandlerRegister.class); classes.add(CamelContextHolderService.class); + classes.add(EventBusService.class); return classes.toArray(new Class[]{}); } From 287a7ef467cb7f4f2c60a879a0975102bd7c662c Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 24 Aug 2021 00:45:50 +0800 Subject: [PATCH 019/763] action trigger by eventbus --- iot-server/pom.xml | 1 + iot-server/server-action/pom.xml | 19 ++++++++++++ .../server/action/ActionRouteIdentifier.java | 9 ++++++ .../iot/server/action/HelloWorldAction.java | 22 ++++++++++++++ .../iot/server/action/bean/ActionParam.java | 15 ++++++++++ iot-server/server-core/pom.xml | 10 +++++++ .../iot/server/core/CoreModuleProvider.java | 27 +++++++++++++++-- .../core/camel/ZabbixTrapperProducer.java | 19 +++++++++++- .../server/core/eventbus/EventBusService.java | 23 ++++++++++++++ .../servlet/DeviceTriggerActionHandler.java | 30 ++++++++++++++----- .../src/main/resources/application.yaml | 2 +- 11 files changed, 166 insertions(+), 11 deletions(-) create mode 100644 iot-server/server-action/pom.xml create mode 100644 iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/ActionRouteIdentifier.java create mode 100644 iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/HelloWorldAction.java create mode 100644 iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/bean/ActionParam.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/eventbus/EventBusService.java diff --git a/iot-server/pom.xml b/iot-server/pom.xml index 76d50df6..bd29c779 100644 --- a/iot-server/pom.xml +++ b/iot-server/pom.xml @@ -21,6 +21,7 @@ server-telemetry server-receiver-plugin server-sender + server-action diff --git a/iot-server/server-action/pom.xml b/iot-server/server-action/pom.xml new file mode 100644 index 00000000..01060167 --- /dev/null +++ b/iot-server/server-action/pom.xml @@ -0,0 +1,19 @@ + + + + iot-server + com.zmops + 1.0-beta + + 4.0.0 + + server-action + + + 8 + 8 + + + \ No newline at end of file diff --git a/iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/ActionRouteIdentifier.java b/iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/ActionRouteIdentifier.java new file mode 100644 index 00000000..d40b1ba7 --- /dev/null +++ b/iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/ActionRouteIdentifier.java @@ -0,0 +1,9 @@ +package com.zmops.zeus.iot.server.action; + +/** + * @author nantian created at 2021/8/24 0:33 + */ +public interface ActionRouteIdentifier { + + String helloworld = "HelloWorld"; +} diff --git a/iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/HelloWorldAction.java b/iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/HelloWorldAction.java new file mode 100644 index 00000000..08c63ac9 --- /dev/null +++ b/iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/HelloWorldAction.java @@ -0,0 +1,22 @@ +package com.zmops.zeus.iot.server.action; + +import com.google.common.eventbus.Subscribe; +import com.zmops.zeus.iot.server.action.bean.ActionParam; +import lombok.extern.slf4j.Slf4j; + +/** + * @author nantian created at 2021/8/24 0:07 + *

+ * 动作触发示例,基于 Camel 动态执行 + */ + +@Slf4j +public class HelloWorldAction { + + + @Subscribe + public void subscribe(ActionParam event) { + log.info("子线程接收异步事件, 设备ID - {} ", event.getTriggerDevice()); + } + +} diff --git a/iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/bean/ActionParam.java b/iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/bean/ActionParam.java new file mode 100644 index 00000000..77035afc --- /dev/null +++ b/iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/bean/ActionParam.java @@ -0,0 +1,15 @@ +package com.zmops.zeus.iot.server.action.bean; + +import lombok.Getter; +import lombok.Setter; + +/** + * @author nantian created at 2021/8/24 0:16 + */ +@Getter +@Setter +public class ActionParam { + + + private String triggerDevice; +} diff --git a/iot-server/server-core/pom.xml b/iot-server/server-core/pom.xml index 76cfa7f7..2b9f5260 100644 --- a/iot-server/server-core/pom.xml +++ b/iot-server/server-core/pom.xml @@ -41,6 +41,16 @@ iot-datacarrier 1.0-beta + + com.zmops + iot-eventbus + 1.0-beta + + + com.zmops + server-action + 1.0-beta + diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java index 30daea79..51ebbf8b 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java @@ -1,10 +1,18 @@ package com.zmops.zeus.iot.server.core; +import com.zmops.zeus.iot.server.action.ActionRouteIdentifier; +import com.zmops.zeus.iot.server.action.HelloWorldAction; import com.zmops.zeus.iot.server.core.camel.CamelContextHolderService; import com.zmops.zeus.iot.server.core.camel.ZabbixSenderComponent; +import com.zmops.zeus.iot.server.core.eventbus.EventBusService; import com.zmops.zeus.iot.server.core.server.JettyHandlerRegister; import com.zmops.zeus.iot.server.core.server.JettyHandlerRegisterImpl; +import com.zmops.zeus.iot.server.core.servlet.DeviceTriggerActionHandler; import com.zmops.zeus.iot.server.core.servlet.HttpItemTrapperHandler; +import com.zmops.zeus.iot.server.eventbus.core.EventControllerFactory; +import com.zmops.zeus.iot.server.eventbus.thread.ThreadPoolFactory; +import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadCustomization; +import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadParameter; import com.zmops.zeus.iot.server.library.module.*; import com.zmops.zeus.iot.server.library.server.jetty.JettyServer; import com.zmops.zeus.iot.server.library.server.jetty.JettyServerConfig; @@ -21,7 +29,9 @@ public class CoreModuleProvider extends ModuleProvider { private final CoreModuleConfig moduleConfig; private ModelCamelContext camelContext; - private JettyServer jettyServer; + private JettyServer jettyServer; + private ThreadPoolFactory threadPoolFactory; + private EventControllerFactory eventControllerFactory; public CoreModuleProvider() { @@ -48,6 +58,9 @@ public ModuleConfig createConfigBeanIfAbsent() { @Override public void prepare() throws ServiceNotProvidedException, ModuleStartException { + threadPoolFactory = new ThreadPoolFactory(new ThreadCustomization(), new ThreadParameter()); + eventControllerFactory = new EventControllerFactory(threadPoolFactory); + JettyServerConfig jettyServerConfig = JettyServerConfig.builder() .host(moduleConfig.getRestHost()) .port(moduleConfig.getRestPort()) @@ -66,11 +79,11 @@ public void prepare() throws ServiceNotProvidedException, ModuleStartException { this.registerServiceImplementation(JettyHandlerRegister.class, new JettyHandlerRegisterImpl(jettyServer)); - camelContext = new DefaultCamelContext(); camelContext.addComponent(Const.CAMEL_ZABBIX_COMPONENT_NAME, new ZabbixSenderComponent(getManager())); this.registerServiceImplementation(CamelContextHolderService.class, new CamelContextHolderService(camelContext, getManager())); + this.registerServiceImplementation(EventBusService.class, new EventBusService(eventControllerFactory)); } @Override @@ -85,10 +98,20 @@ public void start() throws ServiceNotProvidedException, ModuleStartException { } } + public void shutdown() { + threadPoolFactory.shutdown(); + } + @Override public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { JettyHandlerRegister service = getManager().find(CoreModule.NAME).provider().getService(JettyHandlerRegister.class); service.addHandler(new HttpItemTrapperHandler()); + service.addHandler(new DeviceTriggerActionHandler(getManager())); + + + // ### 可以自定义添加 Action 的动作异步处理,指定 ID + eventControllerFactory.getAsyncController(ActionRouteIdentifier.helloworld).register(new HelloWorldAction()); + } @Override diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java index ced37d9b..ebcaca64 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java @@ -1,14 +1,18 @@ package com.zmops.zeus.iot.server.core.camel; +import com.google.gson.Gson; import com.zmops.zeus.iot.server.core.worker.ItemDataTransferWorker; import com.zmops.zeus.iot.server.core.worker.data.ItemValue; import com.zmops.zeus.iot.server.library.module.ModuleManager; +import com.zmops.zeus.iot.server.util.StringUtil; import org.apache.camel.Endpoint; import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.camel.impl.DefaultProducer; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; /** * @author nantian created at 2021/8/16 22:48 @@ -19,6 +23,7 @@ public class ZabbixTrapperProducer extends DefaultProducer { private final ModuleManager moduleManager; private final ItemDataTransferWorker itemDataTransferWorker; + private final ExecutorService itemValueThread = Executors.newFixedThreadPool(20); public ZabbixTrapperProducer(Endpoint endpoint, ModuleManager moduleManager) { @@ -37,7 +42,19 @@ public void process(Exchange exchange) { Message message = exchange.getIn(); List values = (List) message.getBody(); - values.forEach(itemDataTransferWorker::in); + for (ItemValue itemValue : values) { + if (StringUtil.isEmpty(itemValue.getHost()) + || StringUtil.isEmpty(itemValue.getKey()) + || StringUtil.isEmpty(itemValue.getValue())) { + log.error(" process item data error,{}", new Gson().toJson(itemValue)); + break; + } + + itemValueThread.submit(() -> { + itemDataTransferWorker.in(itemValue); + }); + } + exchange.getMessage().setBody("{\"success\":\"true\"}"); } } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/eventbus/EventBusService.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/eventbus/EventBusService.java new file mode 100644 index 00000000..f7e4b7ae --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/eventbus/EventBusService.java @@ -0,0 +1,23 @@ +package com.zmops.zeus.iot.server.core.eventbus; + +import com.zmops.zeus.iot.server.action.bean.ActionParam; +import com.zmops.zeus.iot.server.eventbus.core.EventControllerFactory; +import com.zmops.zeus.iot.server.library.module.Service; + +/** + * @author nantian created at 2021/8/24 0:12 + *

+ * EventBus post service + */ +public class EventBusService implements Service { + + private final EventControllerFactory eventControllerFactory; + + public EventBusService(EventControllerFactory eventControllerFactory) { + this.eventControllerFactory = eventControllerFactory; + } + + public void postExecuteActionMsg(String identifier, ActionParam param) { + eventControllerFactory.getAsyncController(identifier).post(param); + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java index 77dadab9..d20d8bb5 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java @@ -1,6 +1,11 @@ package com.zmops.zeus.iot.server.core.servlet; import com.google.gson.JsonElement; +import com.zmops.zeus.iot.server.action.ActionRouteIdentifier; +import com.zmops.zeus.iot.server.action.bean.ActionParam; +import com.zmops.zeus.iot.server.core.CoreModule; +import com.zmops.zeus.iot.server.core.eventbus.EventBusService; +import com.zmops.zeus.iot.server.library.module.ModuleManager; import com.zmops.zeus.iot.server.library.server.jetty.ArgumentsParseException; import com.zmops.zeus.iot.server.library.server.jetty.JettyJsonHandler; @@ -14,6 +19,11 @@ */ public class DeviceTriggerActionHandler extends JettyJsonHandler { + private final ModuleManager moduleManager; + + public DeviceTriggerActionHandler(ModuleManager moduleManager) { + this.moduleManager = moduleManager; + } @Override public String pathSpec() { @@ -21,16 +31,22 @@ public String pathSpec() { } + /** + * 动作触发Http入口,可在设备 上面设置 宏 定义,动态传入 identifier + * + * @param req + * @return JsonElement + * @throws ArgumentsParseException ex + * @throws IOException ex + */ @Override protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException, IOException { - return null; - } + EventBusService eventBusService = moduleManager.find(CoreModule.NAME).provider().getService(EventBusService.class); + ActionParam actionParam = new ActionParam(); + actionParam.setTriggerDevice("10084"); + eventBusService.postExecuteActionMsg(ActionRouteIdentifier.helloworld, actionParam); - /** - * 执行 Action,进 EventBus,方便订阅处理 - */ - private void execute() { - + return null; } } diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index 54e3be20..4e22273a 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -41,7 +41,7 @@ forest: zbxApiUrl: http://${ZEUS_ZABBIX_HOST:127.0.0.1}:${ZEUS_ZABBIX_API_PORT:80}/zabbix/api_jsonrpc.php zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:10051} - zbxApiToken: e39f259dc2b5a5deb583531380a56d85 + zbxApiToken: 8f59e5bf64ec05b32a5b1b45f9d0951b5cf5d8c484393e1f496dd691c026c44d ## 设备触发告警,执行动作回调 IOT-SERVER 处理 zeusServerIp: ${ZEUS_CALLBACK_HOST:127.0.0.1} From 32d5f4de69c8e08a28d8bdecf25f60163e3f20da Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 24 Aug 2021 00:56:57 +0800 Subject: [PATCH 020/763] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=8F=91=E9=80=81?= =?UTF-8?q?=EF=BC=8C=E9=80=BB=E8=BE=91=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java index ebcaca64..d40facab 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java @@ -47,7 +47,7 @@ public void process(Exchange exchange) { || StringUtil.isEmpty(itemValue.getKey()) || StringUtil.isEmpty(itemValue.getValue())) { log.error(" process item data error,{}", new Gson().toJson(itemValue)); - break; + continue; } itemValueThread.submit(() -> { From 4a2ec6ca4fe0c78a67e2b1642bdfc56bf7a3cec6 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 24 Aug 2021 01:08:32 +0800 Subject: [PATCH 021/763] add class EventControllerFactory desc --- .../iot/server/eventbus/core/EventControllerFactory.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java index feaa7060..7434a937 100644 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java @@ -12,7 +12,12 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; - public final class EventControllerFactory { +/** + * 事件控制器 工厂类 + * + * @author nantian + */ +public final class EventControllerFactory { private final ThreadPoolFactory threadPoolFactory; From a5e08c55ec1316848e9cb1789eb2adf452b02e28 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 24 Aug 2021 09:55:10 +0800 Subject: [PATCH 022/763] =?UTF-8?q?=E6=81=A2=E5=A4=8D=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zeus-starter/src/main/resources/application.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index 4e22273a..54e3be20 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -41,7 +41,7 @@ forest: zbxApiUrl: http://${ZEUS_ZABBIX_HOST:127.0.0.1}:${ZEUS_ZABBIX_API_PORT:80}/zabbix/api_jsonrpc.php zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:10051} - zbxApiToken: 8f59e5bf64ec05b32a5b1b45f9d0951b5cf5d8c484393e1f496dd691c026c44d + zbxApiToken: e39f259dc2b5a5deb583531380a56d85 ## 设备触发告警,执行动作回调 IOT-SERVER 处理 zeusServerIp: ${ZEUS_CALLBACK_HOST:127.0.0.1} From 19994fd26d12d9dd556aff685d54dda9af5457cf Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 24 Aug 2021 09:57:59 +0800 Subject: [PATCH 023/763] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/zmops/iot/web/sys/service/SysUserGroupService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java index 43d93b81..282a4e64 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java @@ -138,9 +138,9 @@ public SysUserGroup updateUserGroup(UserGroupDto userGroup) { private void checkByGroupName(String groupName, Long userGroupId) { int count; if (userGroupId > 0) { - count = new QSysUserGroup().groupName.equalTo(groupName).userGroupId.ne(userGroupId).findCount(); + count = new QSysUserGroup().groupName.eq(groupName).userGroupId.ne(userGroupId).findCount(); } else { - count = new QSysUserGroup().groupName.equalTo(groupName).findCount(); + count = new QSysUserGroup().groupName.eq(groupName).findCount(); } if (count > 0) { throw new ServiceException(BizExceptionEnum.USERGROUP_HAS_EXIST); @@ -181,7 +181,7 @@ public String getZabUsrGrpId(Long usrGrpId) { } return usrGrp.getZbxId(); } - + /** * 用户组绑定设备组 * From 237ba2cbef110f5c744333bcfaefd074be7717cd Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 24 Aug 2021 13:02:01 +0800 Subject: [PATCH 024/763] parent pom edit. --- iot-server-dist/pom.xml | 4 ++-- {zeus-server-pom => iot-server-pom}/pom.xml | 2 +- iot-server/pom.xml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) rename {zeus-server-pom => iot-server-pom}/pom.xml (99%) diff --git a/iot-server-dist/pom.xml b/iot-server-dist/pom.xml index cc7b91d2..79d0ff67 100644 --- a/iot-server-dist/pom.xml +++ b/iot-server-dist/pom.xml @@ -3,10 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - zeus-server-pom + iot-server-pom com.zmops 1.0-beta - ../zeus-server-pom/pom.xml + ../iot-server-pom/pom.xml 4.0.0 diff --git a/zeus-server-pom/pom.xml b/iot-server-pom/pom.xml similarity index 99% rename from zeus-server-pom/pom.xml rename to iot-server-pom/pom.xml index 28e7581e..e6d59db0 100644 --- a/zeus-server-pom/pom.xml +++ b/iot-server-pom/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.zmops - zeus-server-pom + iot-server-pom 1.0-beta pom diff --git a/iot-server/pom.xml b/iot-server/pom.xml index bd29c779..ff1a6836 100644 --- a/iot-server/pom.xml +++ b/iot-server/pom.xml @@ -3,10 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - zeus-server-pom + iot-server-pom com.zmops 1.0-beta - ../zeus-server-pom + ../iot-server-pom 4.0.0 From cfb4b82cd83c74db8083e3016198eb6d977dc163 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 24 Aug 2021 13:02:53 +0800 Subject: [PATCH 025/763] edit offline or online trigger rule. --- .../api-json/action/action.init.create.ftl | 17 +++++++++++++++-- .../api-json/script/script.init.create.ftl | 4 ++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/zeus-driver/src/main/resources/api-json/action/action.init.create.ftl b/zeus-driver/src/main/resources/api-json/action/action.init.create.ftl index 0b41642d..a06222b5 100644 --- a/zeus-driver/src/main/resources/api-json/action/action.init.create.ftl +++ b/zeus-driver/src/main/resources/api-json/action/action.init.create.ftl @@ -19,9 +19,22 @@ "operations": [ { "operationtype": 1, - "opcommand_grp": [ + "opcommand_hst": [ { - "groupid": "${groupId}" + "hostid": "0" + } + ], + "opcommand": { + "scriptid": "${scriptId}" + } + } + ], + "recovery_operations": [ + { + "operationtype": "1", + "opcommand_hst": [ + { + "hostid": "0" } ], "opcommand": { diff --git a/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl b/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl index 837be555..d6c4687c 100644 --- a/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl +++ b/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl @@ -3,9 +3,9 @@ "method": "script.create", "params": { "name": "__offline_status__", - "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"hostname\\":\\"{HOST.HOST}\\",\\"deviceStatus\\":\\"{EVENT.ID}\\"}' http://${zeusServerIp}:${zeusServerPort}/rest/device/webhook", + "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"hostname\\":\\"{HOST.HOST}\\",\\"deviceStatus\\":\\"{EVENT.ID}\\"}' http://${zeusServerIp}:${zeusServerPort}/device/action/exec", "type": 0, - "execute_on": 2 + "execute_on": 1 }, "auth": "${userAuth}", "id": 1 From 6344822ccc677235d2b5d27813d0e125aa365f30 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 24 Aug 2021 14:26:43 +0800 Subject: [PATCH 026/763] =?UTF-8?q?=E5=85=A8=E5=B1=80=E6=A6=82=E8=A7=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zmops/zeus/driver/service/ZbxHost.java | 9 ++ .../zmops/zeus/driver/service/ZbxItem.java | 10 ++ .../main/resources/api-json/host/host.get.ftl | 11 ++- .../main/resources/api-json/item/item.get.ftl | 19 ++-- .../analyse/controller/HistoryController.java | 2 +- .../analyse/controller/HomeController.java | 25 +++++ .../web/analyse/service/HistoryService.java | 20 ++-- .../iot/web/analyse/service/HomeService.java | 94 +++++++++++++++++++ 8 files changed, 174 insertions(+), 16 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java index fadf9a22..0898acb9 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java @@ -64,6 +64,15 @@ String hostUpdate(@ParamName("hostid") String hostid, @JsonPath("/host/host.get") String hostDetail(@ParamName("hostid") String hostid); + /** + * 查询主机 + * + * @param host 主机ID + */ + @Post + @JsonPath("/host/host.get") + String hostGet(@ParamName("host") String host); + /** * 更新主机宏 * diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java index 491bb28d..5023d393 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java @@ -85,4 +85,14 @@ String updateTrapperItem(@ParamName("itemid") String itemid, @Post @JsonPath("/item/item.get") String getItemInfo(@ParamName("itemId") String itemId, @ParamName("hostid") String hostid); + + /** + * 根据item name 获取 ITEM 信息 + * + * @param key key + * @return String + */ + @Post + @JsonPath("/item/item.get") + String getItemList(@ParamName("key") String key, @ParamName("hostid") String hostid); } diff --git a/zeus-driver/src/main/resources/api-json/host/host.get.ftl b/zeus-driver/src/main/resources/api-json/host/host.get.ftl index dd180015..5968dfbe 100644 --- a/zeus-driver/src/main/resources/api-json/host/host.get.ftl +++ b/zeus-driver/src/main/resources/api-json/host/host.get.ftl @@ -2,11 +2,18 @@ "jsonrpc": "2.0", "method": "host.get", "params": { + <#if groupids??> + "filter": { + "host":${host} + }, + + <#if groupids??> + "hostids":${hostid}, + "output": "extend", "selectTags":"extend", "selectMacros":"extend", - "selectValueMaps":"extend", - "hostids":${hostid} + "selectValueMaps":"extend" }, "auth": "${userAuth}", "id": 1 diff --git a/zeus-driver/src/main/resources/api-json/item/item.get.ftl b/zeus-driver/src/main/resources/api-json/item/item.get.ftl index cd11da3a..7f5c8d2f 100644 --- a/zeus-driver/src/main/resources/api-json/item/item.get.ftl +++ b/zeus-driver/src/main/resources/api-json/item/item.get.ftl @@ -5,6 +5,17 @@ "selectTags":"extend", "selectValueMap":"extend", "selectPreprocessing":"extend", + <#if key??> + "search":{ + "key_":"${key}" + }, + + <#if itemId??> + "itemids": "${itemId}", + + <#if hostid??> + "hostids": "${hostid}", + "output": [ "itemid", "hostid", @@ -15,13 +26,7 @@ "units", "valuemapid", "interfaceid" - ], - <#if itemId??> - "itemids": "${itemId}" - - <#if hostid??> - "hostids": "${hostid}" - + ] }, "auth": "${userAuth}", "id": 1 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HistoryController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HistoryController.java index ac172637..b940dfc5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HistoryController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HistoryController.java @@ -23,6 +23,6 @@ public class HistoryController { @RequestMapping("/query") public ResponseData qeuryHistory(@Validated @RequestBody HistoryParam historyParam) { - return ResponseData.success(historyService.qeuryHistory(historyParam)); + return ResponseData.success(historyService.queryHistory(historyParam)); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java new file mode 100644 index 00000000..3b07e3f7 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java @@ -0,0 +1,25 @@ +package com.zmops.iot.web.analyse.controller; + +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.analyse.service.HomeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + * + * 全局概览 + **/ +@RestController +@RequestMapping("/home") +public class HomeController { + + @Autowired + HomeService homeService; + + @RequestMapping("/collectonRate") + public ResponseData collectonRate(){ + return ResponseData.success(homeService.collectonRate()); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java index ce1d30e4..c2d448a2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java @@ -14,7 +14,10 @@ import org.springframework.stereotype.Service; import java.time.LocalDateTime; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; /** @@ -28,11 +31,11 @@ public class HistoryService { @Autowired ZbxHistoryGet zbxHistoryGet; - public List qeuryHistory(HistoryParam historyParam) { - return qeuryHistory(historyParam.getDeviceId(), historyParam.getAttrIds(), historyParam.getTimeFrom(), historyParam.getTimeTill()); + public List queryHistory(HistoryParam historyParam) { + return queryHistory(historyParam.getDeviceId(), historyParam.getAttrIds(), historyParam.getTimeFrom(), historyParam.getTimeTill()); } - public List qeuryHistory(Long deviceId, List attrIds, Long timeFrom, Long timeTill) { + public List queryHistory(Long deviceId, List attrIds, Long timeFrom, Long timeTill) { //查询出设备 Device one = new QDevice().deviceId.eq(deviceId).findOne(); if (null == one || ToolUtil.isEmpty(one.getZbxId())) { @@ -57,8 +60,7 @@ public List qeuryHistory(Long deviceId, List attrIds, Long time } //根据属性值类型 分组查询历史数据 for (Map.Entry> map : valueTypeMap.entrySet()) { - String res = zbxHistoryGet.historyGet(one.getZbxId(), zbxIds, 1000, Integer.parseInt(map.getKey()), timeFrom, timeTill); - latestDtos.addAll(JSONObject.parseArray(res, LatestDto.class)); + latestDtos.addAll(queryHitoryData(one.getZbxId(), zbxIds, Integer.parseInt(map.getKey()), timeFrom, timeTill)); } latestDtos.forEach(latestDto -> { @@ -69,4 +71,10 @@ public List qeuryHistory(Long deviceId, List attrIds, Long time return latestDtos; } + + public List queryHitoryData(String hostId, List itemIds, Integer valueType, Long timeFrom, Long timeTill) { + String res = zbxHistoryGet.historyGet(hostId, itemIds, 1000, valueType, timeFrom, timeTill); + return JSONObject.parseArray(res, LatestDto.class); + } + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java new file mode 100644 index 00000000..e80d9fb6 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -0,0 +1,94 @@ +package com.zmops.iot.web.analyse.service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.util.LocalDateTimeUtils; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.analyse.dto.LatestDto; +import com.zmops.zeus.driver.entity.ZbxItemInfo; +import com.zmops.zeus.driver.service.ZbxHost; +import com.zmops.zeus.driver.service.ZbxItem; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 全局概览服务 + **/ +@Service +public class HomeService { + + @Autowired + private ZbxHost zbxHost; + + @Autowired + private ZbxItem zbxItem; + + @Autowired + HistoryService historyService; + + private static String hostId = ""; + + private static Map ITEM_Map = new ConcurrentHashMap<>(5); + + //Zbx 指标取数速率 key + private static final String KEY = "zabbix[wcache,values"; + + public Map> collectonRate() { + if (ToolUtil.isEmpty(hostId)) { + if (ToolUtil.isEmpty(getZbxServerId())) { + return new HashMap<>(0); + } + } + if (ToolUtil.isEmpty(ITEM_Map)) { + if (ToolUtil.isEmpty(getItemMap())) { + return new HashMap<>(0); + } + } + List itemIds = new ArrayList<>(ITEM_Map.keySet()); + List latestDtos = historyService.queryHitoryData(hostId, itemIds, 0, LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.minu(LocalDateTime.now(), + 7, ChronoUnit.DAYS)), LocalDateTimeUtils.getSecondsByTime(LocalDateTime.now())); + + latestDtos.forEach(latestDto -> { + if (null != ITEM_Map.get(latestDto.getItemid())) { + latestDto.setName(ITEM_Map.get(latestDto.getItemid())); + } + }); + + return latestDtos.parallelStream().collect(Collectors.groupingBy(LatestDto::getName)); + } + + private String getZbxServerId() { + String response = zbxHost.hostGet("Zabbix server"); + List> ids = JSON.parseObject(response, List.class); + if (null != ids && ids.size() > 0) { + hostId = ids.get(0).get("hostid"); + return hostId; + } + return ""; + } + + private Map getItemMap() { + String itemList = zbxItem.getItemList(KEY, hostId); + List itemInfos = JSONObject.parseArray(itemList, ZbxItemInfo.class); + for (ZbxItemInfo itemInfo : itemInfos) { + ITEM_Map.put(itemInfo.getItemid(), formatName(itemInfo.getName())); + } + return ITEM_Map; + } + + private static String formatName(String name) { + return name.substring(35, name.length() - 18); + } + +} From 91127d2c5bf51c4d36df5f7f82916068b08a99be Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 24 Aug 2021 14:34:28 +0800 Subject: [PATCH 027/763] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/device/controller/DeviceController.java | 11 ++++++++++- .../iot/web/device/service/DeviceService.java | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java index a49a2ace..29dffeb7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java @@ -37,11 +37,20 @@ public class DeviceController { * * @return */ - @RequestMapping("/getDeviceByPage") + @PostMapping("/getDeviceByPage") public Pager devicePageList(@RequestBody DeviceParam deviceParam) { return deviceService.devicePageList(deviceParam); } + /** + * 设备列表 + * + * @return + */ + @PostMapping("/list") + public ResponseData deviceList(@RequestBody DeviceParam deviceParam) { + return ResponseData.success(deviceService.deviceList(deviceParam)); + } /** * 设备创建 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index b92c7333..c9723df1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -63,6 +63,20 @@ public class DeviceService { @Autowired private ZbxValueMap zbxValueMap; + /** + * 设备列表 + * + * @param deviceParam + * @return + */ + public List deviceList(DeviceParam deviceParam) { + QDevice qDevice = new QDevice(); + if (ToolUtil.isNotEmpty(deviceParam.getName())) { + qDevice.name.contains(deviceParam.getName()); + } + return qDevice.findList(); + } + /** * 设备分页列表 * @@ -432,4 +446,5 @@ private JSONArray getZbxHostInfo(Long deviceId) { } return JSONObject.parseArray(zbxHost.hostDetail(zbxId)); } + } From 74cd05261fefa9b19b317889c63295dff86c6545 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 24 Aug 2021 15:50:17 +0800 Subject: [PATCH 028/763] =?UTF-8?q?=E5=91=8A=E8=AD=A6=E9=A9=B1=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/api-json/problem/problem.get.ftl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 zeus-driver/src/main/resources/api-json/problem/problem.get.ftl diff --git a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl new file mode 100644 index 00000000..f23e3a92 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl @@ -0,0 +1,18 @@ +{ + "jsonrpc": "2.0", + "method": "problem.get", + "params": { + "output": "extend", + "selectAcknowledges": "extend", + "selectTags": "extend", + "selectSuppressionData": "extend", + "recent": "true", + "sortfield": ["eventid"], + <#if hostId??> + "hostids":"${hostId}" + + "sortorder": "DESC" + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file From 52b7ff23cd68812d6335e7f9ae51a6ce3a108c8a Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 24 Aug 2021 16:08:37 +0800 Subject: [PATCH 029/763] edit zeus-alarm pom.xml. --- zeus-alarm/pom.xml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/zeus-alarm/pom.xml b/zeus-alarm/pom.xml index 4cee762d..478ed524 100644 --- a/zeus-alarm/pom.xml +++ b/zeus-alarm/pom.xml @@ -9,13 +9,12 @@ 4.0.0 - iot-alarm + zeus-alarm com.zmops zeus-common 1.0-beta - compile io.netty @@ -26,7 +25,6 @@ com.zmops zeus-driver 1.0-beta - compile From 0e9959d7bfda32f2dd3b2d8053d52a63abeee59e Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Tue, 24 Aug 2021 16:38:56 +0800 Subject: [PATCH 030/763] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E6=A1=A3?= =?UTF-8?q?=EF=BC=9A=E6=96=B0=E5=A2=9Eubuntu=20=E9=83=A8=E7=BD=B2=E8=84=9A?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 18 +- docs/README.md | 101 ++++++- docs/quick-install.sh | 610 +++++++++++++++++++++-------------------- docs/ubuntu/install.sh | 196 +++++++++++++ 4 files changed, 621 insertions(+), 304 deletions(-) create mode 100644 docs/ubuntu/install.sh diff --git a/README.md b/README.md index fb90e32f..e3388324 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,19 @@ Zeus-IOT 支持 Centos 7、Ubuntu 20.04、Debain 10 、Kylin、UOS 等基于x86_64平台的 Linux 操作系统。 -```shell -curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/quick-install.sh | bash -``` +- Centos7、RedHat 7 -访问 `http://` 登录 Zeus-IOT 系统。[快速开始](./docs/quick-start.rst) + ```shell + curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/rhel/quick-install.sh | bash + ``` + +- Ubuntu 20.04 + + ```shell + curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/ubuntu/install.sh | bash + ``` + +访问 `http://` 登录 Zeus-IOT 系统[快速开始](./docs/quick-start.rst) 。 + +假如您已经有自己的 **zabbix** 且 **zabbix** 版本是 **5.4.0+**。可以选择[自定义安装 Zeus iot](./docs/README.md) diff --git a/docs/README.md b/docs/README.md index 61dd488d..a95168f0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1 +1,100 @@ -### Zeus IOT Document \ No newline at end of file +### Zeus IOT Document + +#### 自定义安装 + +``` +⚠️ : 自定义安装是在本身已有 zabbix 或 分开部署zabbix 和 zeus。 +``` + +- zabbix 安装可参照[zabbix官网](https://www.zabbix.com/download) 。或者[快速安装](../README.md)。这里就不做详细介绍。 + +- zeus iot 安装 + + - 前端 UI 部署 + + 可采用 nginx 做为web服务器来部署 ui。 + + - Ubuntu 安装 nginx + + ```shell + apt install nginx -y + ``` + + - Centos/RedHat 安装 nginx + + ```shell + yum install nginx -y + ``` + + - nginx 配置文件 + + ```shell + tee /etc/nginx/conf.d/zabbix.conf < zeus server 是以 jar 包的形式部署在服务器上。 + + 需要安装 JDK 1.8 以上开发工具包。 + + - Ubuntu 安装 JDK 1.8 + + ```shell + apt install openjdk-8-jdk -y + ``` + + - Centos/Redhat 安装 JDK 1.8 + + ```shell + yum install java-1.8.0-openjdk.x86_64 -y + ``` + + - 获取 zeus-iot.jar 包 + + - 直接下载 release 包 + + - 从源码编译 + + ```shell + git clone https://github.com/zmops/zeus-iot.git + cd zeus-iot/ && mvn clean package -U -Dmaven.test.skip=true + ``` + + - 启动服务 + + ```shell + export ZEUS_DB_HOST=127.0.0.1 #zeus 数据库地址,默认: 127.0.0.1 + export ZEUS_DB_PORT=5432 #zeus 数据库端口,默认: 5432 + export ZEUS_DB_USERNAME=postgres #zeus 数据库用户名,默认: postgres + export ZEUS_DB_PASSWORD=postgres #zeus 数据库密码,默认: postgres + export ZEUS_ZABBIX_HOST=127.0.0.1 #zabbix server 地址,默认: 127.0.0.1 + export ZEUS_ZABBIX_API_PORT=80 #zabbix web 端口,默认: 80 + export ZEUS_ZABBIX_PORT=10051 #zabbix server 端口,默认: 10051 + export ZEUS_CALLBACK_HOST=127.0.0.1 #zeus-iot 地址,默认: 127.0.0.1 + export ZEUS_CALLBACK_PORT=9090 #zeus-iot 端口,默认: 9090 + ``` + + 以上环境变量,根据服务架构环境,做相应修改。不设置即使用默认值 + + ```shell + nohup java -jar zeus-iot.jar > /tmp/zeus-iot.log 2>&1 & + ``` + + + diff --git a/docs/quick-install.sh b/docs/quick-install.sh index 4b8379ae..608776b1 100755 --- a/docs/quick-install.sh +++ b/docs/quick-install.sh @@ -53,331 +53,343 @@ if [ "$cores" -lt 0 ] || [ "$memstotal" -lt 0 ] || [ "$disks" -eq 0 ]; then fi ## 系统环境初始化 -echo "初始化系统环境" -if ! hostnamectl set-hostname zeus-server; then - echo "主机名修改失败" - exit -fi +function InitSystem() { + echo "初始化系统环境" + if ! hostnamectl set-hostname zeus-server; then + echo "主机名修改失败" + exit + fi -### 修改时区 -if ! ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime; then - echo "时区修改失败" - exit 0 -fi + ### 修改时区 + if ! ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime; then + echo "时区修改失败" + exit 0 + fi -### 关闭Selinux -setenforce 0 || true -sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config + ### 关闭Selinux + setenforce 0 || true + sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config -### 加强对抗SYN Flood的能力 -echo "net.ipv4.tcp_syncookies = 1" >>/etc/sysctl.conf + ### 加强对抗SYN Flood的能力 + echo "net.ipv4.tcp_syncookies = 1" >>/etc/sysctl.conf -### linux文件打开数量限制 -###/etc/security/limits.conf & /etc/rc.local -echo "* soft nofile 65535" >>/etc/security/limits.conf -echo "* hard nofile 65535 " >>/etc/security/limits.conf -echo "ulimit -SHn 65535" >>/etc/rc.local + ### linux文件打开数量限制 + ###/etc/security/limits.conf & /etc/rc.local + echo "* soft nofile 65535" >>/etc/security/limits.conf + echo "* hard nofile 65535 " >>/etc/security/limits.conf + echo "ulimit -SHn 65535" >>/etc/rc.local -### 添加用户 -groupadd --system zeus || true -useradd --system -g zeus zeus || true + ### 添加用户 + groupadd --system zeus || true + useradd --system -g zeus zeus || true -### 添加安装目录 -[ ! -d /opt/zeus ] && mkdir -p /opt/zeus + ### 添加安装目录 + [ ! -d /opt/zeus ] && mkdir -p /opt/zeus +} # 开始安装 ## 配置 YUM 源 -### 基础 YUM 源 -if ! curl -s -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo; then - echo "YUM 仓库配置异常,请检查网络" -fi -sed -i '/mirrors.aliyuncs.com/,/mirrors.cloud.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo -### Postgresql && timescaleDB -tee /etc/yum.repos.d/postgresql_timescaledb.repo </dev/null -[epel] -name=Extra Packages for Enterprise Linux 7 - \$basearch -baseurl=http://mirrors.aliyun.com/epel/7/\$basearch -failovermethod=priority -enabled=1 -gpgcheck=0 - -[timescale_timescaledb] -name=timescale_timescaledb -baseurl=https://packagecloud.io/timescale/timescaledb/el/$(rpm -E %{rhel})/\$basearch -gpgcheck=0 -enabled=1 - -[centos-sclo-rh] -name=CentOS-7 - SCLo rh -baseurl=https://mirrors.aliyun.com/centos/7/sclo/\$basearch/rh/ -gpgcheck=0 -enabled=1 - -[pgdg-common] -name=PostgreSQL common RPMs for RHEL/CentOS \$releasever - \$basearch -baseurl=https://download.postgresql.org/pub/repos/yum/common/redhat/rhel-\$releasever-\$basearch -enabled=1 -gpgcheck=0 - - -[pgdg13] -name=PostgreSQL 13 for RHEL/CentOS \$releasever - \$basearch -baseurl=https://download.postgresql.org/pub/repos/yum/13/redhat/rhel-\$releasever-\$basearch -enabled=1 -gpgcheck=0 - -[pgdg12] -name=PostgreSQL 12 for RHEL/CentOS \$releasever - \$basearch -baseurl=https://download.postgresql.org/pub/repos/yum/12/redhat/rhel-\$releasever-\$basearch -enabled=1 -gpgcheck=0 +function AddInstallRepo() { + ### 基础 YUM 源 + if ! curl -s -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo; then + echo "YUM 仓库配置异常,请检查网络" + fi + sed -i '/mirrors.aliyuncs.com/,/mirrors.cloud.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo + ### Postgresql && timescaleDB + tee /etc/yum.repos.d/postgresql_timescaledb.repo </dev/null + [epel] + name=Extra Packages for Enterprise Linux 7 - \$basearch + baseurl=http://mirrors.aliyun.com/epel/7/\$basearch + failovermethod=priority + enabled=1 + gpgcheck=0 + + [timescale_timescaledb] + name=timescale_timescaledb + baseurl=https://packagecloud.io/timescale/timescaledb/el/$(rpm -E %{rhel})/\$basearch + gpgcheck=0 + enabled=1 + + [centos-sclo-rh] + name=CentOS-7 - SCLo rh + baseurl=https://mirrors.aliyun.com/centos/7/sclo/\$basearch/rh/ + gpgcheck=0 + enabled=1 + + [pgdg-common] + name=PostgreSQL common RPMs for RHEL/CentOS \$releasever - \$basearch + baseurl=https://download.postgresql.org/pub/repos/yum/common/redhat/rhel-\$releasever-\$basearch + enabled=1 + gpgcheck=0 + + + [pgdg13] + name=PostgreSQL 13 for RHEL/CentOS \$releasever - \$basearch + baseurl=https://download.postgresql.org/pub/repos/yum/13/redhat/rhel-\$releasever-\$basearch + enabled=1 + gpgcheck=0 + + [pgdg12] + name=PostgreSQL 12 for RHEL/CentOS \$releasever - \$basearch + baseurl=https://download.postgresql.org/pub/repos/yum/12/redhat/rhel-\$releasever-\$basearch + enabled=1 + gpgcheck=0 EOL -echo "配置安装 YUM 源 。。。" -yum clean all 1>/dev/null && yum makecache 1>/dev/null -logprint "yum 源配置失败详细看安装日志输出" + echo "配置安装 YUM 源 。。。" + yum clean all 1>/dev/null && yum makecache 1>/dev/null + logprint "yum 源配置失败详细看安装日志输出" +} ## 安装 PostgreSQL +function PGInstall() { + yum -y install postgresql13.x86_64 \ + postgresql13-devel.x86_64 \ + postgresql13-plpython3.x86_64 \ + timescaledb-2-postgresql-13.x86_64 1>/dev/null + + logprint "yum 源配置失败详细看安装日志输出" + + ### 创建 PostgreSQL 用户 + ### 修改启动文件 + echo "安装 PG-timescaledb " + [ ! -d $PGDATA ] && mkdir -p $PGDATA + if ! chown postgres. $PGDATA; then + echo "修改PGDATA用户失败" + exit + fi -yum -y install postgresql13.x86_64 \ - postgresql13-devel.x86_64 \ - postgresql13-plpython3.x86_64 \ - timescaledb-2-postgresql-13.x86_64 1>/dev/null - -logprint "yum 源配置失败详细看安装日志输出" - -### 创建 PostgreSQL 用户 -### 修改启动文件 -echo "安装 PG-timescaledb " -[ ! -d $PGDATA ] && mkdir -p $PGDATA -if ! chown postgres. $PGDATA; then - echo "修改PGDATA用户失败" - exit -fi - -startfile=/usr/lib/systemd/system/postgresql-13.service -#sed -i 's/\(^User\=\).*/\1zeus/g' $startfile -#sed -i 's/\(^Group\=\).*/\1zeus/g' $startfile -sed -i 's/\(^Environment\=PGDATA\=\).*/\1\/opt\/zeus\/pgdata/g' $startfile -### 初始化数据库 -echo "开始初始化 PG" -/usr/pgsql-13/bin/postgresql-13-setup initdb 1>/dev/null -logprint "初始化错误" - -echo "shared_preload_libraries = 'timescaledb'" >>/opt/zeus/pgdata/postgresql.conf -### 启动数据库 -systemctl enable postgresql-13 &>/dev/null -systemctl start postgresql-13 -### 修改数据库管理员密码 -cd /tmp || exit -sudo -u postgres /usr/pgsql-13/bin/psql -c "ALTER USER postgres WITH PASSWORD 'zeusiot';" 2>/tmp/pg.log -cd "$basename" || exit + startfile=/usr/lib/systemd/system/postgresql-13.service + #sed -i 's/\(^User\=\).*/\1zeus/g' $startfile + #sed -i 's/\(^Group\=\).*/\1zeus/g' $startfile + sed -i 's/\(^Environment\=PGDATA\=\).*/\1\/opt\/zeus\/pgdata/g' $startfile + ### 初始化数据库 + echo "开始初始化 PG" + /usr/pgsql-13/bin/postgresql-13-setup initdb 1>/dev/null + logprint "初始化错误" + + echo "shared_preload_libraries = 'timescaledb'" >>/opt/zeus/pgdata/postgresql.conf + ### 启动数据库 + systemctl enable postgresql-13 &>/dev/null + systemctl start postgresql-13 + ### 修改数据库管理员密码 + cd /tmp || exit + sudo -u postgres /usr/pgsql-13/bin/psql -c "ALTER USER postgres WITH PASSWORD 'zeusiot';" 2>/tmp/pg.log +} ## 编译安装 zabbix 5.4 -echo "编译 zabbix" -### 安装编译依赖 -yum -y install vim \ - wget \ - gcc \ - gcc-c++ \ - net-snmp \ - net-snmp-libs \ - net-snmp-utils \ - net-snmp-devel \ - libssh2-devel \ - OpenIPMI-devel \ - libevent-devel \ - libcurl-devel \ - libxml2 \ - libxml2-devel 1>/dev/null - -### 创建 zabbix 用户 -groupadd --system zabbix || true -useradd --system -g zabbix -d /opt/zeus/zabbix -s /sbin/nologin -c "Zabbix Monitoring System" zabbix || true - -wget -c https://cdn.zabbix.com/zabbix/sources/stable/5.4/zabbix-5.4.3.tar.gz -o /dev/null -O - | tar -xz -logprint "下载zabbix源码失败,请检查网络。。。" - -cd "$zabbixsrc" && ./configure --prefix=$ZABBIX_HOME \ - --enable-server \ - --enable-agent \ - --with-postgresql=/usr/pgsql-13/bin/pg_config \ - --with-net-snmp \ - --with-libcurl \ - --with-libxml2 \ - --with-openipmi \ - --with-openssl \ - --with-ssh2 1>/dev/null -logprint "zabbix 编译异常" -echo "安装 zabbix" -make install 1>/dev/null -logprint "zabbix 编译异常" -### 前端内容部署 -mv ui $ZABBIX_HOME/web && chown zeus. $ZABBIX_HOME/web -R -mv $ZABBIX_HOME/web/conf/zabbix.conf.php.example $ZABBIX_HOME/web/conf/zabbix.conf.php -sed -i "s/\($DB\['PASSWORD'\]\s*=\).*/\1 'zabbix';/g" $ZABBIX_HOME/web/conf/zabbix.conf.php -sed -i "s/\($DB\['TYPE'\]\s*=\).*/\1 \'POSTGRESQL\';/g" $ZABBIX_HOME/web/conf/zabbix.conf.php - -### 数据初始化 -echo "初始化 zabbix 数据库" -cd /tmp/ || exit -sudo -u postgres createuser zabbix -sudo -u postgres /usr/pgsql-13/bin/psql -c "ALTER USER zabbix WITH PASSWORD 'zabbix';" -sudo -u postgres createdb -O zabbix -E Unicode -T template0 zabbix -cat $zabbixsrc/database/postgresql/schema.sql | sudo -u zabbix psql zabbix 1>/dev/null -cat $zabbixsrc/database/postgresql/images.sql | sudo -u zabbix psql zabbix 1>/dev/null -cat $zabbixsrc/database/postgresql/data.sql | sudo -u zabbix psql zabbix 1>/dev/null -echo "CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;" | sudo -u postgres psql zabbix &>/dev/null -cat $zabbixsrc/database/postgresql/timescaledb.sql | sudo -u zabbix psql zabbix 1>/dev/null -cd "$basename" || exit -### 配置zabbix配置文件 -echo "启动zabbix" -sed -i 's/^# DBPassword=/DBPassword=zabbix/g' $ZABBIX_HOME/etc/zabbix_server.conf -### 配置启动文件 -tee /usr/lib/systemd/system/zabbix-server.service </dev/null -[Unit] -Description=Zabbix Server - -After=network.target -After=postgresql-13.service - -[Service] -Environment="CONFFILE=$ZABBIX_HOME/etc/zabbix_server.conf" -EnvironmentFile=-/etc/default/zabbix-server -Type=forking -Restart=on-failure -PIDFile=/tmp/zabbix_server.pid -KillMode=control-group -ExecStart=$ZABBIX_HOME/sbin/zabbix_server -c \$CONFFILE -ExecStop=/bin/kill -SIGTERM \$MAINPID -RestartSec=10s -TimeoutSec=0 - -[Install] -WantedBy=multi-user.target +function ZbxInstall() { + echo "编译 zabbix" + ### 安装编译依赖 + cd "$basename" || exit + yum -y install vim \ + wget \ + gcc \ + gcc-c++ \ + net-snmp \ + net-snmp-libs \ + net-snmp-utils \ + net-snmp-devel \ + libssh2-devel \ + OpenIPMI-devel \ + libevent-devel \ + libcurl-devel \ + libxml2 \ + libxml2-devel 1>/dev/null + + ### 创建 zabbix 用户 + groupadd --system zabbix || true + useradd --system -g zabbix -d /opt/zeus/zabbix -s /sbin/nologin -c "Zabbix Monitoring System" zabbix || true + + wget -c https://cdn.zabbix.com/zabbix/sources/stable/5.4/zabbix-5.4.3.tar.gz -o /dev/null -O - | tar -xz + logprint "下载zabbix源码失败,请检查网络。。。" + + cd "$zabbixsrc" && ./configure --prefix=$ZABBIX_HOME \ + --enable-server \ + --enable-agent \ + --with-postgresql=/usr/pgsql-13/bin/pg_config \ + --with-net-snmp \ + --with-libcurl \ + --with-libxml2 \ + --with-openipmi \ + --with-openssl \ + --with-ssh2 1>/dev/null + logprint "zabbix 编译异常" + echo "安装 zabbix" + make install 1>/dev/null + logprint "zabbix 编译异常" + ### 前端内容部署 + mv ui $ZABBIX_HOME/zabbix && chown zeus. $ZABBIX_HOME/zabbix -R + mv $ZABBIX_HOME/zabbix/conf/zabbix.conf.php.example $ZABBIX_HOME/zabbix/conf/zabbix.conf.php + sed -i "s/\($DB\['PASSWORD'\]\s*=\).*/\1 'zabbix';/g" $ZABBIX_HOME/zabbix/conf/zabbix.conf.php + sed -i "s/\($DB\['TYPE'\]\s*=\).*/\1 \'POSTGRESQL\';/g" $ZABBIX_HOME/zabbix/conf/zabbix.conf.php + + ### 数据初始化 + echo "初始化 zabbix 数据库" + cd /tmp/ || exit + sudo -u postgres createuser zabbix + sudo -u postgres /usr/pgsql-13/bin/psql -c "ALTER USER zabbix WITH PASSWORD 'zabbix';" + sudo -u postgres createdb -O zabbix -E Unicode -T template0 zabbix + cat $zabbixsrc/database/postgresql/schema.sql | sudo -u zabbix psql zabbix 1>/dev/null + cat $zabbixsrc/database/postgresql/images.sql | sudo -u zabbix psql zabbix 1>/dev/null + cat $zabbixsrc/database/postgresql/data.sql | sudo -u zabbix psql zabbix 1>/dev/null + echo "CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;" | sudo -u postgres psql zabbix &>/dev/null + cat $zabbixsrc/database/postgresql/timescaledb.sql | sudo -u zabbix psql zabbix 1>/dev/null + cd "$basename" || exit + ### 配置zabbix配置文件 + echo "启动zabbix" + sed -i 's/^# DBPassword=/DBPassword=zabbix/g' $ZABBIX_HOME/etc/zabbix_server.conf + ### 配置启动文件 + tee /usr/lib/systemd/system/zabbix-server.service </dev/null + [Unit] + Description=Zabbix Server + + After=network.target + After=postgresql-13.service + + [Service] + Environment="CONFFILE=$ZABBIX_HOME/etc/zabbix_server.conf" + EnvironmentFile=-/etc/default/zabbix-server + Type=forking + Restart=on-failure + PIDFile=/tmp/zabbix_server.pid + KillMode=control-group + ExecStart=$ZABBIX_HOME/sbin/zabbix_server -c \$CONFFILE + ExecStop=/bin/kill -SIGTERM \$MAINPID + RestartSec=10s + TimeoutSec=0 + + [Install] + WantedBy=multi-user.target EOL -tee /usr/lib/systemd/system/zabbix-agent.service </dev/null -[Unit] -Description=Zabbix Agent -After=network.target - -[Service] -Environment="CONFFILE=$ZABBIX_HOME/etc/zabbix_agentd.conf" -EnvironmentFile=-/etc/default/zabbix-agent -Type=forking -Restart=on-failure -PIDFile=/tmp/zabbix_agentd.pid -KillMode=control-group -ExecStart=$ZABBIX_HOME/sbin/zabbix_agentd -c \$CONFFILE -ExecStop=/bin/kill -SIGTERM \$MAINPID -RestartSec=10s -User=zabbix -Group=zabbix - -[Install] -WantedBy=multi-user.target + tee /usr/lib/systemd/system/zabbix-agent.service </dev/null + [Unit] + Description=Zabbix Agent + After=network.target + + [Service] + Environment="CONFFILE=$ZABBIX_HOME/etc/zabbix_agentd.conf" + EnvironmentFile=-/etc/default/zabbix-agent + Type=forking + Restart=on-failure + PIDFile=/tmp/zabbix_agentd.pid + KillMode=control-group + ExecStart=$ZABBIX_HOME/sbin/zabbix_agentd -c \$CONFFILE + ExecStop=/bin/kill -SIGTERM \$MAINPID + RestartSec=10s + User=zabbix + Group=zabbix + + [Install] + WantedBy=multi-user.target EOL -systemctl daemon-reload -systemctl enable zabbix-server -systemctl enable zabbix-agent -systemctl start zabbix-server -systemctl start zabbix-agent - + systemctl daemon-reload + systemctl enable zabbix-server + systemctl enable zabbix-agent + systemctl start zabbix-server + systemctl start zabbix-agent +} ## 安装 php -echo "安装 zabbix-web" -yum -y install rh-php73.x86_64 \ - rh-php73-php-fpm.x86_64 \ - rh-php73-php-bcmath.x86_64 \ - rh-php73-php-gd.x86_64 \ - rh-php73-php-mbstring.x86_64 \ - rh-php73-php-ldap.x86_64 \ - rh-php73-php-pgsql.x86_64 1>/dev/null - -### php配置文件修改 -sed -i 's/post_max_size = 8M/post_max_size = 16M/' $PHP_CONF/php.ini -sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 20M/' $PHP_CONF/php.ini -sed -i 's/max_execution_time = 30/max_execution_time = 300/' $PHP_CONF/php.ini -sed -i 's/max_input_time = 60/max_input_time = 300/' $PHP_CONF/php.ini -sed -i 's/; date.timezone =/date.timezone = "Asia\/Shanghai"/' $PHP_CONF/php.ini -sed -i 's/user = apache/user = zeus/g' $PHP_CONF/php-fpm.d/www.conf -sed -i 's/group = apache/group = zeus/g' $PHP_CONF/php-fpm.d/www.conf -sed -i 's/;listen.owner = nobody/listen.owner = zeus/g' $PHP_CONF/php-fpm.d/www.conf -sed -i 's/;listen.group = nobody/listen.group = zeus/g' $PHP_CONF/php-fpm.d/www.conf -sed -i 's/\(^listen =\).*/\1\/var\/run\/php-fpm.sock/g' $PHP_CONF/php-fpm.d/www.conf - -## 安装 nginx -yum -y install nginx 1>/dev/null - -## 编辑 nginx 配置文件 -tee /etc/nginx/conf.d/zabbix.conf </dev/null +function PHPInstall() { + echo "安装 zabbix-web" + yum -y install rh-php73.x86_64 \ + rh-php73-php-fpm.x86_64 \ + rh-php73-php-bcmath.x86_64 \ + rh-php73-php-gd.x86_64 \ + rh-php73-php-mbstring.x86_64 \ + rh-php73-php-ldap.x86_64 \ + rh-php73-php-pgsql.x86_64 1>/dev/null + + ### php配置文件修改 + sed -i 's/post_max_size = 8M/post_max_size = 16M/' $PHP_CONF/php.ini + sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 20M/' $PHP_CONF/php.ini + sed -i 's/max_execution_time = 30/max_execution_time = 300/' $PHP_CONF/php.ini + sed -i 's/max_input_time = 60/max_input_time = 300/' $PHP_CONF/php.ini + sed -i 's/; date.timezone =/date.timezone = "Asia\/Shanghai"/' $PHP_CONF/php.ini + sed -i 's/user = apache/user = zeus/g' $PHP_CONF/php-fpm.d/www.conf + sed -i 's/group = apache/group = zeus/g' $PHP_CONF/php-fpm.d/www.conf + sed -i 's/;listen.owner = nobody/listen.owner = zeus/g' $PHP_CONF/php-fpm.d/www.conf + sed -i 's/;listen.group = nobody/listen.group = zeus/g' $PHP_CONF/php-fpm.d/www.conf + sed -i 's/\(^listen =\).*/\1\/var\/run\/php-fpm.sock/g' $PHP_CONF/php-fpm.d/www.conf +} + +function ZeusInstall() { + + ## 安装 nginx + yum -y install nginx 1>/dev/null + + + cd /opt/zeus + wget -c https://packages.zmops.cn/zeus-iot/app-1.0.tar.gz -o /dev/null -O - | tar -xz + wget -c https://packages.zmops.cn/zeus-iot/web-1.0.tar.gz -o /dev/null -O - | tar -xz + wget -c https://packages.zmops.cn/zeus-iot/zeus-iot.sql + sudo -u postgres createdb zeus-iot + cat zeus-iot.sql | sudo -u postgres psql zeus-iot + + ## 编辑 nginx 配置文件 + tee /etc/nginx/conf.d/zabbix.conf </dev/null server { - listen 80; -# server_name example.com; - - root $ZABBIX_HOME/web; - - index index.php; - - location = /favicon.ico { - log_not_found off; - } - - location / { - try_files \$uri \$uri/ =404; - } - - location /assets { - access_log off; - expires 10d; - } - - location ~ /\.ht { - deny all; - } - - location ~ /(api\/|conf[^\.]|include|locale|vendor) { - deny all; - return 404; - } - - location ~ [^/]\.php(/|$) { - fastcgi_pass unix:/var/run/php-fpm.sock; - fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_index index.php; - - fastcgi_param DOCUMENT_ROOT $ZABBIX_HOME/web; - fastcgi_param SCRIPT_FILENAME $ZABBIX_HOME/web\$fastcgi_script_name; - fastcgi_param PATH_TRANSLATED $ZABBIX_HOME/web\$fastcgi_script_name; - - include fastcgi_params; - fastcgi_param QUERY_STRING \$query_string; - fastcgi_param REQUEST_METHOD \$request_method; - fastcgi_param CONTENT_TYPE \$content_type; - fastcgi_param CONTENT_LENGTH \$content_length; - - fastcgi_intercept_errors on; - fastcgi_ignore_client_abort off; - fastcgi_connect_timeout 60; - fastcgi_send_timeout 180; - fastcgi_read_timeout 180; - fastcgi_buffer_size 128k; - fastcgi_buffers 4 256k; - fastcgi_busy_buffers_size 256k; - fastcgi_temp_file_write_size 256k; - } + listen 80; + + + location / { + root /opt/zeus/web; + index index.html; + try_files \$uri \$uri/ /index.html; + } + + location ^~/api/ { + client_body_buffer_size 10m; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_pass http://127.0.0.1:9090/; + } + + location /zabbix { + alias $ZABBIX_HOME/zabbix; + index index.html index.htm index.php; + } + + location ~ ^/zabbix/.+\.php$ { + fastcgi_pass unix:/var/run/php/zabbix.sock; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $ZABBIX_HOME\$fastcgi_script_name; + include fastcgi_params; + + fastcgi_param QUERY_STRING \$query_string; + fastcgi_param REQUEST_METHOD \$request_method; + fastcgi_param CONTENT_TYPE \$content_type; + fastcgi_param CONTENT_LENGTH \$content_length; + + fastcgi_intercept_errors on; + fastcgi_ignore_client_abort off; + fastcgi_connect_timeout 60; + fastcgi_send_timeout 180; + fastcgi_read_timeout 180; + fastcgi_buffer_size 128k; + fastcgi_buffers 4 256k; + fastcgi_busy_buffers_size 256k; + fastcgi_temp_file_write_size 256k; + } } EOL -## 修改 nginx 配置用户 -sed -i 's/user nginx;/user zeus;/g' /etc/nginx/nginx.conf -systemctl enable rh-php73-php-fpm -systemctl enable nginx -systemctl start rh-php73-php-fpm -systemctl start nginx - + ## 修改 nginx 配置用户 + sed -i 's/user nginx;/user zeus;/g' /etc/nginx/nginx.conf + systemctl enable rh-php73-php-fpm + systemctl enable nginx + systemctl start rh-php73-php-fpm + systemctl start nginx +} echo "安装完成。。。请访问 "http://localIP"" ## +InitSystem +AddInstallRepo +PGInstall +ZbxInstall +PHPInstall +ZeusInstall # 安装结束 diff --git a/docs/ubuntu/install.sh b/docs/ubuntu/install.sh new file mode 100644 index 00000000..9f0b60b3 --- /dev/null +++ b/docs/ubuntu/install.sh @@ -0,0 +1,196 @@ +#!/usr/bin/env bash +set -e +# 初始化系统 + +function logprint() { + if [ $? != 0 ]; then + echo "$1" + exit + fi +} + +# 安装前准备 +## 系统环境检测 +if [ "$(uname)" != Linux ]; then + echo "该脚本只使用 Linux 系统" + exit $E_BADOD +fi + +if [ "$UID" -ne "$ROOT_UID" ]; then + echo "Must be root to install" + exit $E_NOTROOT +fi +### 操作系统 +if [ ! -f /etc/redhat-release ]; then + if [[ "$(cat /etc/issue)" =~ ^Ubuntu* ]]; then + release=Ubuntu + fi +fi +### 网络 +if ! ping -c 3 mirrors.aliyun.com &>/dev/null; then + echo "网络异常。。。" + exit +fi + +### cpu、mem、disk +cores=$(grep 10)printf("%s\t%d\n",$7,$3/1024/1024)}' | grep -v -c "/boot") + +if [ "$cores" -lt 0 ] || [ "$memstotal" -lt 0 ] || [ "$disks" -eq 0 ]; then + echo "要求最低配置为 CPU 2核 内存 4GB 存储空间 100G" + exit 70 +fi + + + +function InitSystem() { + ## 修改主机名 + if ! hostnamectl set-hostname zeus-server; then + echo "主机名修改失败" + exit + fi + ## 修改时区 + if ! ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime; then + echo "时区修改失败" + exit 0 + fi + ## 更新下载源 + mv /etc/apt/sources.list /etc/apt/sources.listbak + tee /etc/apt/sources.list </dev/null +deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse +deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse + +deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse +deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse + +deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse +deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse + +deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse +deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse + +deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse +deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse +EOL +} + +function AddInstallRepo() { + ## 安装PGsql源 + echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -c -s)-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list + wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - + sudo sh -c "echo 'deb https://packagecloud.io/timescale/timescaledb/ubuntu/ $(lsb_release -c -s) main' > /etc/apt/sources.list.d/timescaledb.list" + wget --quiet -O - https://packagecloud.io/timescale/timescaledb/gpgkey | sudo apt-key add - + ## 安装zabbix 5.4 源 + wget https://repo.zabbix.com/zabbix/5.4/ubuntu/pool/main/z/zabbix-release/zabbix-release_5.4-1+ubuntu20.04_all.deb + dpkg -i zabbix-release_5.4-1+ubuntu20.04_all.deb + apt update + +} + +function PGInstall() { + # PG 安装 + apt install timescaledb-2-postgresql-13 -y + echo "shared_preload_libraries = 'timescaledb'" >> /etc/postgresql/13/main/postgresql.conf + cd /tmp || exit + sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD 'zeusiot';" 2> /tmp/pg.log + systemctl restart postgresql +} + +function ZbxInstall() { + # zabbix 安装 + apt install zabbix-server-pgsql zabbix-frontend-php php7.4-pgsql zabbix-nginx-conf zabbix-sql-scripts zabbix-agent -y + # 初始化 zabbix 配置 + cd /tmp || exit + sudo -u postgres createuser zabbix + sudo -u postgres psql -c "ALTER USER zabbix WITH PASSWORD 'zabbix';" + sudo -u postgres createdb -O zabbix zabbix + zcat /usr/share/doc/zabbix-sql-scripts/postgresql/create.sql.gz | sudo -u zabbix psql zabbix + echo "CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;" | sudo -u postgres psql zabbix + cat /usr/share/doc/zabbix-sql-scripts/postgresql/timescaledb.sql | sudo -u zabbix psql zabbix 1>/dev/null + + sed -i 's/^# DBPassword=/DBPassword=zabbix/g' /etc/zabbix/zabbix_server.conf + mv /usr/share/zabbix/conf/zabbix.conf.php.example /usr/share/zabbix/conf/zabbix.conf.php + sed -i "s/\($DB\['PASSWORD'\]\s*=\).*/\1 'zabbix';/g" /usr/share/zabbix/conf/zabbix.conf.php + sed -i "s/\($DB\['TYPE'\]\s*=\).*/\1 \'POSTGRESQL\';/g" /usr/share/zabbix/conf/zabbix.conf.php + # 修改 php 配置 + sed -i 's/post_max_size = 8M/post_max_size = 16M/' /etc/php/7.4/fpm/php.ini + sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 20M/' /etc/php/7.4/fpm/php.ini + sed -i 's/max_execution_time = 30/max_execution_time = 300/' /etc/php/7.4/fpm/php.ini + sed -i 's/max_input_time = 60/max_input_time = 300/' /etc/php/7.4/fpm/php.ini + sed -i 's/; date.timezone =/date.timezone = "Asia\/Shanghai"/' /etc/php/7.4/fpm/php.ini + # 修改 nginx 配置 + sed -i '/sites-enabled/d' /etc/nginx/nginx.conf + sed -i '/listen/s/#//' /etc/nginx/conf.d/zabbix.conf + sed -i '/listen/s/80/8871/' /etc/nginx/conf.d/zabbix.conf + systemctl restart zabbix-server zabbix-agent nginx php7.4-fpm +} + +function ZeusInstall() { + ## 安装web + [ ! -d /opt/zeus ] && mkdir -p /opt/zeus + cd /opt/zeus + wget -c https://packages.zmops.cn/zeus-iot/app-1.0.tar.gz -o /dev/null -O - | tar -xz + wget -c https://packages.zmops.cn/zeus-iot/web-1.0.tar.gz -o /dev/null -O - | tar -xz + wget -c https://packages.zmops.cn/zeus-iot/zeus-iot.sql + sudo -u postgres createdb zeus-iot + cat zeus-iot.sql | sudo -u postgres psql zeus-iot + + # 配置 nginx + tee /etc/nginx/conf.d/zeus.conf </dev/null +server { + listen 80; + + + location / { + root /opt/zeus/web; + index index.html; + try_files \$uri \$uri/ /index.html; + } + + location ^~/api/ { + client_body_buffer_size 10m; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_pass http://127.0.0.1:9090/; + } + location /zabbix { + alias /usr/share/zabbix; + index index.html index.htm index.php; + } + + location ~ ^/zabbix/.+\.php$ { + fastcgi_pass unix:/var/run/php/zabbix.sock; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME /usr/share\$fastcgi_script_name; + include fastcgi_params; + + fastcgi_param QUERY_STRING \$query_string; + fastcgi_param REQUEST_METHOD \$request_method; + fastcgi_param CONTENT_TYPE \$content_type; + fastcgi_param CONTENT_LENGTH \$content_length; + + fastcgi_intercept_errors on; + fastcgi_ignore_client_abort off; + fastcgi_connect_timeout 60; + fastcgi_send_timeout 180; + fastcgi_read_timeout 180; + fastcgi_buffer_size 128k; + fastcgi_buffers 4 256k; + fastcgi_busy_buffers_size 256k; + fastcgi_temp_file_write_size 256k; + } + +} +EOL + + # 启动 + systemctl restart nginx + cd /opt/zeus/app && ./start.sh + +} +InitSystem +AddInstallRepo +PGInstall +ZbxInstall +ZeusInstall \ No newline at end of file From b29370ccb85075f227d932c40a4ad49a6beacbdd Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Tue, 24 Aug 2021 17:14:44 +0800 Subject: [PATCH 031/763] =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/docs/README.md b/docs/README.md index a95168f0..734c4973 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,11 +6,11 @@ ⚠️ : 自定义安装是在本身已有 zabbix 或 分开部署zabbix 和 zeus。 ``` -- zabbix 安装可参照[zabbix官网](https://www.zabbix.com/download) 。或者[快速安装](../README.md)。这里就不做详细介绍。 +- **zabbix 安装可参照[zabbix官网](https://www.zabbix.com/download) 。或者[快速安装](../README.md)。这里就不做详细介绍。** -- zeus iot 安装 +- **zeus iot 安装** - - 前端 UI 部署 + - **前端 UI 部署** 可采用 nginx 做为web服务器来部署 ui。 @@ -47,7 +47,21 @@ EOL ``` - - zeus-iot 安装 + - 获取 zeus-ui + + - 直接下载[release]()包 + + - 从源码编译 + + ```shell + git clone http://code.zmops.cn/zeus-iot/zeus-iot-ui/zeus-iot-ui.git + cd zeus-iot-ui/ && npm install && npm run build + mv dist /opt/zeus/web + ``` + + + + - **zeus-iot 安装** > zeus server 是以 jar 包的形式部署在服务器上。 From 089cd1d3deaaf2285e25051e5b354036da50ff66 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 25 Aug 2021 10:44:44 +0800 Subject: [PATCH 032/763] code collation. --- .../com/zmops/zeus/iot/server/core/CoreModuleProvider.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java index 51ebbf8b..150d061a 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java @@ -77,11 +77,10 @@ public void prepare() throws ServiceNotProvidedException, ModuleStartException { jettyServer = new JettyServer(jettyServerConfig); jettyServer.initialize(); - this.registerServiceImplementation(JettyHandlerRegister.class, new JettyHandlerRegisterImpl(jettyServer)); - camelContext = new DefaultCamelContext(); camelContext.addComponent(Const.CAMEL_ZABBIX_COMPONENT_NAME, new ZabbixSenderComponent(getManager())); + this.registerServiceImplementation(JettyHandlerRegister.class, new JettyHandlerRegisterImpl(jettyServer)); this.registerServiceImplementation(CamelContextHolderService.class, new CamelContextHolderService(camelContext, getManager())); this.registerServiceImplementation(EventBusService.class, new EventBusService(eventControllerFactory)); } From 22752cbcc7714d786e51b906ad5f97f46d759427 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 25 Aug 2021 14:13:28 +0800 Subject: [PATCH 033/763] code collation. --- .../config/ApplicationConfigLoader.java | 52 ++++++++++++------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java index 11304f41..b8401390 100644 --- a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java +++ b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java @@ -59,23 +59,22 @@ public ApplicationConfiguration load() throws ConfigFileNotFoundException { @SuppressWarnings("unchecked") private void loadConfig(ApplicationConfiguration configuration) throws ConfigFileNotFoundException { try { - Reader applicationReader = ResourceUtils.read("application.yml"); - Map> moduleConfig = yaml.loadAs(applicationReader, Map.class); + Reader applicationReader = ResourceUtils.read("application.yml"); + + Map> moduleConfig = yaml.loadAs(applicationReader, Map.class); if (CollectionUtils.isNotEmpty(moduleConfig)) { selectConfig(moduleConfig); moduleConfig.forEach((moduleName, providerConfig) -> { if (providerConfig.size() > 0) { log.info("Get a module define from application.yml, module name: {}", moduleName); - ApplicationConfiguration.ModuleConfiguration moduleConfiguration = configuration.addModule( - moduleName); + ApplicationConfiguration.ModuleConfiguration moduleConfiguration = configuration.addModule(moduleName); providerConfig.forEach((providerName, config) -> { - log.info( - "Get a provider define belong to {} module, provider name: {}", moduleName, - providerName - ); + log.info("Get a provider define belong to {} module, provider name: {}", moduleName, providerName); + final Map propertiesConfig = (Map) config; final Properties properties = new Properties(); + if (propertiesConfig != null) { propertiesConfig.forEach((propertyName, propertyValue) -> { if (propertyValue instanceof Map) { @@ -91,6 +90,7 @@ private void loadConfig(ApplicationConfiguration configuration) throws ConfigFil } }); } + moduleConfiguration.addProviderConfiguration(providerName, properties); }); } else { @@ -103,10 +103,9 @@ private void loadConfig(ApplicationConfiguration configuration) throws ConfigFil } } - private void replacePropertyAndLog(final Object propertyName, final Object propertyValue, final Properties target, - final Object providerName) { - final String valueString = PropertyPlaceholderHelper.INSTANCE - .replacePlaceholders(propertyValue + "", target); + private void replacePropertyAndLog(final Object propertyName, final Object propertyValue, final Properties target, final Object providerName) { + final String valueString = PropertyPlaceholderHelper.INSTANCE.replacePlaceholders(propertyValue + "", target); + if (valueString != null) { if (valueString.trim().length() == 0) { target.replace(propertyName, valueString); @@ -136,16 +135,20 @@ private void overrideConfigBySystemEnv(ApplicationConfiguration configuration) { private void selectConfig(final Map> moduleConfiguration) { Iterator>> moduleIterator = moduleConfiguration.entrySet().iterator(); while (moduleIterator.hasNext()) { - Map.Entry> entry = moduleIterator.next(); - final String moduleName = entry.getKey(); - final Map providerConfig = entry.getValue(); + Map.Entry> entry = moduleIterator.next(); + + final String moduleName = entry.getKey(); + final Map providerConfig = entry.getValue(); + if (!providerConfig.containsKey(SELECTOR)) { continue; } + final String selector = (String) providerConfig.get(SELECTOR); final String resolvedSelector = PropertyPlaceholderHelper.INSTANCE.replacePlaceholders( selector, System.getProperties() ); + providerConfig.entrySet().removeIf(e -> !resolvedSelector.equals(e.getKey())); if (!providerConfig.isEmpty()) { @@ -171,25 +174,30 @@ private void overrideModuleSettings(ApplicationConfiguration configuration, Stri if (moduleAndConfigSeparator <= 0) { return; } - String moduleName = key.substring(0, moduleAndConfigSeparator); - String providerSettingSubKey = key.substring(moduleAndConfigSeparator + 1); - ApplicationConfiguration.ModuleConfiguration moduleConfiguration = configuration.getModuleConfiguration(moduleName); + String moduleName = key.substring(0, moduleAndConfigSeparator); + String providerSettingSubKey = key.substring(moduleAndConfigSeparator + 1); + + ApplicationConfiguration.ModuleConfiguration moduleConfiguration = configuration.getModuleConfiguration(moduleName); if (moduleConfiguration == null) { return; } + int providerAndConfigSeparator = providerSettingSubKey.indexOf('.'); if (providerAndConfigSeparator <= 0) { return; } + String providerName = providerSettingSubKey.substring(0, providerAndConfigSeparator); String settingKey = providerSettingSubKey.substring(providerAndConfigSeparator + 1); if (!moduleConfiguration.has(providerName)) { return; } + Properties providerSettings = moduleConfiguration.getProviderConfiguration(providerName); if (!providerSettings.containsKey(settingKey)) { return; } + Object originValue = providerSettings.get(settingKey); Class type = originValue.getClass(); if (type.equals(int.class) || type.equals(Integer.class)) @@ -204,8 +212,12 @@ else if (type.equals(boolean.class) || type.equals(Boolean.class)) { return; } - log.info("The setting has been override by key: {}, value: {}, in {} provider of {} module through {}", settingKey, - value, providerName, moduleName, "System.properties" + log.info("The setting has been override by key: {}, value: {}, in {} provider of {} module through {}", + settingKey, + value, + providerName, + moduleName, + "System.properties" ); } } From 195acf3b614bb30d5a6e4e4c18de2d87fe9d8c04 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 25 Aug 2021 14:35:24 +0800 Subject: [PATCH 034/763] =?UTF-8?q?zeus-alarm=20=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E5=BC=95=E5=85=A5=20pom=20=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zeus-starter/pom.xml | 2 +- zeus-webapp/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index de8c0d12..2ef2c112 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -44,7 +44,7 @@ com.zmops - iot-alarm + zeus-alarm ${project.version} diff --git a/zeus-webapp/pom.xml b/zeus-webapp/pom.xml index d0305752..4351c702 100644 --- a/zeus-webapp/pom.xml +++ b/zeus-webapp/pom.xml @@ -23,7 +23,7 @@ com.zmops - iot-alarm + zeus-alarm ${project.version} From a0b4d277fa9a6b6119708615c6138b7c5757bb18 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 25 Aug 2021 18:02:51 +0800 Subject: [PATCH 035/763] =?UTF-8?q?=E6=9C=80=E6=96=B0=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/zmops/iot/web/analyse/dto/LatestDto.java | 10 +++++++++- .../zmops/iot/web/analyse/service/HistoryService.java | 6 ++++-- .../zmops/iot/web/analyse/service/LatestService.java | 4 +++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java index fc111841..df517cdf 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java @@ -1,12 +1,17 @@ package com.zmops.iot.web.analyse.dto; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.domain.BaseDto; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; import lombok.Data; /** * @author yefei **/ @Data -public class LatestDto { +@JsonSerialize(using = CachedValueFilter.class) +public class LatestDto implements BaseDto { private String name; @@ -22,4 +27,7 @@ public class LatestDto { private String tags; + @CachedValue(value = "UNITS") + private String units; + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java index c2d448a2..733431b1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java @@ -53,7 +53,7 @@ public List queryHistory(Long deviceId, List attrIds, Long time //取出属性对应的ItemID List zbxIds = list.parallelStream().map(ProductAttribute::getZbxId).collect(Collectors.toList()); Map> valueTypeMap = list.parallelStream().collect(Collectors.groupingBy(ProductAttribute::getValueType)); - Map itemIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getZbxId, ProductAttribute::getName)); + Map itemIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getZbxId, o -> o)); List latestDtos = new ArrayList<>(); if (null == timeFrom) { timeFrom = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); @@ -65,7 +65,9 @@ public List queryHistory(Long deviceId, List attrIds, Long time latestDtos.forEach(latestDto -> { if (null != itemIdMap.get(latestDto.getItemid())) { - latestDto.setName(itemIdMap.get(latestDto.getItemid())); + latestDto.setName(itemIdMap.get(latestDto.getItemid()).getName()); + latestDto.setAttrId(itemIdMap.get(latestDto.getItemid()).getAttrId()); + latestDto.setUnits(itemIdMap.get(latestDto.getItemid()).getUnits()); } }); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java index 77fc1b46..0d0580f5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java @@ -36,7 +36,8 @@ public class LatestService { * @return */ public List qeuryLatest(LatestParam latestParam) { - return qeuryLatest(latestParam.getDeviceId(), latestParam.getAttrIds()); + List latestDtos = qeuryLatest(latestParam.getDeviceId(), latestParam.getAttrIds()); + return latestDtos; } public List qeuryLatest(Long deviceId, List attrIds) { @@ -69,6 +70,7 @@ public List qeuryLatest(Long deviceId, List attrIds) { if (null != itemIdMap.get(latestDto.getItemid())) { latestDto.setName(itemIdMap.get(latestDto.getItemid()).getName()); latestDto.setAttrId(itemIdMap.get(latestDto.getItemid()).getAttrId()); + latestDto.setUnits(itemIdMap.get(latestDto.getItemid()).getUnits()); } }); From 5d974acd2758a8ffb378b1855a785ab733e26783 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 25 Aug 2021 19:05:02 +0800 Subject: [PATCH 036/763] =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zeus-driver/src/main/resources/api-json/host/host.get.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-driver/src/main/resources/api-json/host/host.get.ftl b/zeus-driver/src/main/resources/api-json/host/host.get.ftl index 5968dfbe..46db7fa3 100644 --- a/zeus-driver/src/main/resources/api-json/host/host.get.ftl +++ b/zeus-driver/src/main/resources/api-json/host/host.get.ftl @@ -7,7 +7,7 @@ "host":${host} }, - <#if groupids??> + <#if hostid??> "hostids":${hostid}, "output": "extend", From c1070b3bfad0691427a6b93a33898f3262a926bb Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 25 Aug 2021 20:29:05 +0800 Subject: [PATCH 037/763] =?UTF-8?q?=E9=80=9A=E7=9F=A5=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/domain/messages/MessageBody.java | 33 ++++ .../zmops/iot/domain/messages/Messages.java | 31 +++ zeus-rest/pom.xml | 6 + .../rest/DeviceStatusWebhookController.java | 20 +- .../config/security/WebSecurityConfig.java | 2 +- .../alarm/controller/MessageController.java | 69 +++++++ .../iot/web/alarm/dto/param/MessageParam.java | 16 ++ .../web/alarm/service/AlarmNoticeWorker.java | 36 ++++ .../iot/web/alarm/service/MessageService.java | 144 ++++++++++++++ .../iot/web/alarm/socket/WebSocketConfig.java | 16 ++ .../iot/web/alarm/socket/WebSocketServer.java | 179 ++++++++++++++++++ 11 files changed, 550 insertions(+), 2 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/messages/MessageBody.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/messages/Messages.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MessageController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/MessageParam.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/alarm/socket/WebSocketConfig.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/alarm/socket/WebSocketServer.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/messages/MessageBody.java b/zeus-common/src/main/java/com/zmops/iot/domain/messages/MessageBody.java new file mode 100644 index 00000000..6d8e881b --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/messages/MessageBody.java @@ -0,0 +1,33 @@ +package com.zmops.iot.domain.messages; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author: yefei + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MessageBody { + private String msg; + private String type; + private List to; + private Map body; + private boolean persist = false; + + + public void addBody(String k, Object v) { + if (this.body == null) { + this.body = new HashMap<>(); + } + this.body.put(k, v); + } +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/messages/Messages.java b/zeus-common/src/main/java/com/zmops/iot/domain/messages/Messages.java new file mode 100644 index 00000000..fd2846da --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/messages/Messages.java @@ -0,0 +1,31 @@ +package com.zmops.iot.domain.messages; + + +import com.zmops.iot.constant.IdTypeConsts; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + */ + +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "messages") +public class Messages { + @Id + private Integer id; + private Integer classify; + private String title; + private String content; + private Long clock; + private String module; + private Integer readed; + private Long userId; +} diff --git a/zeus-rest/pom.xml b/zeus-rest/pom.xml index 1b33a1a7..ed15e077 100644 --- a/zeus-rest/pom.xml +++ b/zeus-rest/pom.xml @@ -17,6 +17,12 @@ 1.0-beta compile + + com.zmops + zeus-webapp + 1.0-beta + compile + diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java index 5696a669..a73c78eb 100644 --- a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java @@ -1,8 +1,14 @@ package com.zmops.iot.rest; import com.alibaba.fastjson.JSON; +import com.zmops.iot.async.executor.Async; +import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.model.response.ResponseData; -import org.springframework.web.bind.annotation.*; +import com.zmops.iot.web.alarm.service.AlarmNoticeWorker; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.util.Map; @@ -16,6 +22,8 @@ @RequestMapping("/rest/device") public class DeviceStatusWebhookController { + @Autowired + private AlarmNoticeWorker alarmNoticeWorker; /** * 在线状态 回调 @@ -29,6 +37,16 @@ public ResponseData deviceStatusWebhook(@RequestBody Map params) System.out.println(JSON.toJSONString(params)); + WorkerWrapper, Boolean> alarmNoticeWork = WorkerWrapper., Boolean>builder().id("alarmNoticeWork") + .worker(alarmNoticeWorker).param(params) + .build(); + + try { + Async.work(3000, alarmNoticeWork).awaitFinish(); + } catch (Exception e) { + e.printStackTrace(); + } + return ResponseData.success("OK"); } } diff --git a/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java b/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java index 4ae7e403..73886794 100644 --- a/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java +++ b/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java @@ -85,7 +85,7 @@ public void configure(WebSecurity web) throws Exception { .and().ignoring().antMatchers(HttpMethod.GET, "/assets/**", "/favicon.ico", - "/activiti-editor/**" + "/activiti-editor/**","/websocket/alarm/**" ); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MessageController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MessageController.java new file mode 100644 index 00000000..749636f5 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MessageController.java @@ -0,0 +1,69 @@ +package com.zmops.iot.web.alarm.controller; + + +import com.zmops.iot.domain.messages.Messages; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.web.alarm.dto.param.MessageParam; +import com.zmops.iot.web.alarm.service.MessageService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +/** + * @author yefei + **/ +@RestController +@RequestMapping("/message") +public class MessageController { + + @Autowired + MessageService messageService; + + /** + * 消息分页列表 + * + * @param messageParam + * @return + */ + @RequestMapping("/getMessageByPage") + public Pager getMessageByPage(@RequestBody MessageParam messageParam) { + return messageService.list(messageParam); + } + + /** + * 消息详情 + * + * @param id + * @return + */ + @RequestMapping("/info") + public Messages info(@RequestParam("id") Integer id) { + return messageService.info(id); + } + + + /** + * 消息置为已读 + * + * @param messageVo + * @return + */ + @RequestMapping("/read") + public List read(@RequestBody MessageParam messageVo) { + return messageService.read(messageVo); + } + + /** + * 未读消息数 + * + * @return + */ + @GetMapping("/num") + public Map unReadNum() { + return messageService.unReadNum(); + } + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/MessageParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/MessageParam.java new file mode 100644 index 00000000..409907e3 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/MessageParam.java @@ -0,0 +1,16 @@ +package com.zmops.iot.web.alarm.dto.param; + +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class MessageParam extends BaseQueryParam { + private Integer readed; + + private List ids; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java new file mode 100644 index 00000000..3118bda2 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java @@ -0,0 +1,36 @@ +package com.zmops.iot.web.alarm.service; + +import com.zmops.iot.async.callback.IWorker; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.messages.MessageBody; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author yefei + **/ +@Service +public class AlarmNoticeWorker implements IWorker, Boolean> { + + @Autowired + MessageService messageService; + + @Override + public Boolean action(Map alarmInfo, Map> allWrappers) { + Map alarmInfo2 = new HashMap<>(alarmInfo); + messageService.push(buildMessage(alarmInfo2)); + return null; + } + + private MessageBody buildMessage(Map alarmInfo) { + + return MessageBody.builder().msg("告警消息").body(alarmInfo).build(); + } + + + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java new file mode 100644 index 00000000..4092656c --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java @@ -0,0 +1,144 @@ +package com.zmops.iot.web.alarm.service; + +import com.alibaba.fastjson.JSON; +import com.zmops.iot.core.auth.context.LoginContextHolder; +import com.zmops.iot.core.auth.model.LoginUser; +import com.zmops.iot.domain.messages.MessageBody; +import com.zmops.iot.domain.messages.Messages; +import com.zmops.iot.domain.messages.query.QMessages; +import com.zmops.iot.domain.sys.SysUser; +import com.zmops.iot.domain.sys.query.QSysUser; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.alarm.dto.param.MessageParam; +import com.zmops.iot.web.alarm.socket.WebSocketServer; +import io.ebean.DB; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 消息服务 + **/ +@Service +public class MessageService { + + protected final static int sys = 1; + + /** + * 发送消息 + * + * @param body + */ + public void push(MessageBody body) { + Objects.requireNonNull(body.getMsg()); + if (body.isPersist()) { + List tos; + if (!CollectionUtils.isEmpty(body.getTo())) { + tos = body.getTo(); + } else { + List userList = new QSysUser().findList(); + tos = userList.parallelStream().map(SysUser::getUserId).collect(Collectors.toList()); + } + tos.forEach(to -> { + Messages messages = new Messages(); + messages.setClassify(sys); + messages.setTitle(body.getMsg()); + messages.setUserId(to); + String content = ""; + if (ToolUtil.isNotEmpty(body.getBody())) { + content = JSON.toJSONString(body.getBody()); + messages.setContent(content); + } + messages.setClock(System.currentTimeMillis() / 1000); + saveMessage(messages); + }); + } + body.addBody("classify", sys); + + if (!CollectionUtils.isEmpty(body.getTo())) { + body.getTo().forEach(to -> { + WebSocketServer.sendMessageTo(JSON.toJSONString(body), to + ""); + }); + } else { + WebSocketServer.sendMessageToAll(JSON.toJSONString(body)); + } + } + + /** + * 消息列表 + * + * @param messageParam + * @return + */ + public Pager list(MessageParam messageParam) { + LoginUser user = LoginContextHolder.getContext().getUser(); + QMessages qMessages = new QMessages(); + qMessages.userId.eq(user.getId()); + + if (messageParam.getReaded() != null) { + qMessages.readed.eq(messageParam.getReaded()); + } + qMessages.orderBy(" readed asc, clock desc"); + List list = qMessages.setFirstRow((messageParam.getPage() - 1) * messageParam.getMaxRow()) + .setMaxRows(messageParam.getMaxRow()).findList(); + + return new Pager<>(list, qMessages.findCount()); + } + + /** + * 读消息 + * + * @param messageParam + * @return + */ + public List read(MessageParam messageParam) { + LoginUser user = LoginContextHolder.getContext().getUser(); + Messages messages = new Messages(); + messages.setReaded(1); + QMessages qMessages = new QMessages(); + if (!CollectionUtils.isEmpty(messageParam.getIds())) { + qMessages.id.in(messageParam.getIds()); + } + qMessages.userId.eq(user.getId()); + + new QMessages().asUpdate().set("readed", 1).update(); + return messageParam.getIds(); + } + + /** + * 未读消息数 + * + * @return + */ + public Map unReadNum() { + LoginUser user = LoginContextHolder.getContext().getUser(); + Map map = new HashMap<>(); + int count = new QMessages().readed.eq(0).userId.eq(user.getId()).findCount(); + map.put("count", count); + return map; + } + + /** + * 消息详情 + * + * @param id + * @return + */ + public Messages info(Integer id) { + return new QMessages().id.eq(id).findOne(); + } + + + private void saveMessage(Messages messages) { + DB.save(messages); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/socket/WebSocketConfig.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/socket/WebSocketConfig.java new file mode 100644 index 00000000..e728cb60 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/socket/WebSocketConfig.java @@ -0,0 +1,16 @@ +package com.zmops.iot.web.alarm.socket; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.server.standard.ServerEndpointExporter; + +/** + * @author yefei + */ +@Configuration +public class WebSocketConfig { + @Bean + public ServerEndpointExporter serverEndpointExporter() { + return new ServerEndpointExporter(); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/socket/WebSocketServer.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/socket/WebSocketServer.java new file mode 100644 index 00000000..a573b395 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/socket/WebSocketServer.java @@ -0,0 +1,179 @@ +package com.zmops.iot.web.alarm.socket; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.util.ToolUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.websocket.*; +import javax.websocket.server.PathParam; +import javax.websocket.server.ServerEndpoint; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + + +/** + * @author yefei + */ + +@ServerEndpoint("/websocket/alarm/{userid}") +@Component +@Slf4j +public class WebSocketServer { + + /** + * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 + */ + private static int onlineCount = 0; + /** + * concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。 + */ + private static ConcurrentHashMap webSocketMap = new ConcurrentHashMap<>(); + /** + * 与某个客户端的连接会话,需要通过它来给客户端发送数据 + */ + private Session session; + /** + * 接收token + */ + private String token = ""; + /** + * userid + */ + private String userid = ""; + + /** + * 连接建立成功调用的方法 + */ + @OnOpen + public void onOpen(@PathParam("userid") String userid, Session session) { + Map> map = session.getRequestParameterMap(); + this.session = session; + this.userid = userid; + if (webSocketMap.containsKey(userid)) { + webSocketMap.remove(userid); + //加入map中 + webSocketMap.put(userid, this); + } else { + //加入map中 + webSocketMap.put(userid, this); + //在线数加1 + addOnlineCount(); + } + + log.info("用户连接:" + userid + ",当前在线人数为:" + getOnlineCount()); + + try { + sendMessage("连接成功"); + } catch (IOException e) { + log.error("用户:" + userid + ",网络异常!!!!!!"); + } + } + + /** + * 连接关闭调用的方法 + */ + @OnClose + public void onClose() { + if (webSocketMap.containsKey(userid)) { + //从map中删除 + webSocketMap.remove(userid); + subOnlineCount(); + } + log.info("用户退出:" + userid + ",当前在线人数为:" + getOnlineCount()); + } + + /** + * 收到客户端消息后调用的方法 + * + * @param message 客户端发送过来的消息 + */ + @OnMessage + public void onMessage(String message, Session session) { + log.info("用户消息:" + userid + ",报文:" + message); + //消息保存到数据库、redis + if (ToolUtil.isNotEmpty(message)) { + try { + //解析发送的报文 + JSONObject jsonObject = JSON.parseObject(message); + //追加发送人(防止串改) + jsonObject.put("fromUserId", this.token); + String toUserId = jsonObject.getString("toUserId"); + //传送给对应toUserId用户的websocket + if (ToolUtil.isNotEmpty(toUserId) && webSocketMap.containsKey(toUserId)) { + webSocketMap.get(toUserId).sendMessage(jsonObject.toJSONString()); + } else { + log.error("请求的userId:" + toUserId + "不在该服务器上"); + //否则不在这个服务器上,发送到mysql或者redis + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** + * @param session + * @param error + */ + @OnError + public void onError(Session session, Throwable error) { + log.error("用户错误:" + this.userid + ",原因:" + error.getMessage()); + error.printStackTrace(); + } + + /** + * 实现服务器主动推送 + */ + public void sendMessage(String message) throws IOException { + this.session.getBasicRemote().sendText(message); + } + + /** + * 实现服务器主动推送给固定人 + */ + public static void sendMessageTo(String message, String to) { + try { + if (webSocketMap != null && webSocketMap.get(to) != null) { + webSocketMap.get(to).session.getBasicRemote().sendText(message); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + // this.session.getBasicRemote().sendText(message); + } + + + /** + * 群发消息 + * + * @param message + */ + public static void sendMessageToAll(String message) { + if (webSocketMap != null) { + webSocketMap.values().forEach(e -> { + try { + e.sendMessage(message); + } catch (IOException ex) { + ex.printStackTrace(); + } + }); + } + } + + + public static synchronized int getOnlineCount() { + return onlineCount; + } + + public static synchronized void addOnlineCount() { + WebSocketServer.onlineCount++; + } + + public static synchronized void subOnlineCount() { + WebSocketServer.onlineCount--; + } +} From b00c8b0f48dfe0881e72d96d36972edc6d836d7a Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 26 Aug 2021 10:49:59 +0800 Subject: [PATCH 038/763] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java | 2 +- .../src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java | 3 ++- .../main/java/com/zmops/iot/web/product/dto/ProductAttr.java | 3 ++- .../com/zmops/iot/web/product/dto/param/ProductAttrParam.java | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java index 3118bda2..a9e36065 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java @@ -27,7 +27,7 @@ public Boolean action(Map alarmInfo, Map alarmInfo) { - return MessageBody.builder().msg("告警消息").body(alarmInfo).build(); + return MessageBody.builder().msg("告警消息").persist(true).body(alarmInfo).build(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java index 1434a745..8d3a40c3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java @@ -9,6 +9,7 @@ import lombok.Data; import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.time.LocalDateTime; import java.util.List; @@ -31,7 +32,7 @@ public class DeviceDto implements BaseDto { private String productName; - @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + @NotEmpty(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private List deviceGroupIds; private String status; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java index c1557187..6f70af15 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java @@ -6,6 +6,7 @@ import lombok.Getter; import lombok.Setter; +import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.time.LocalDateTime; import java.util.List; @@ -58,7 +59,7 @@ public class ProductAttr { //预处理 private List processStepList; - @NotNull(groups = BaseEntity.Delete.class) + @NotEmpty(groups = BaseEntity.Delete.class) private List attrIds; LocalDateTime createTime; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java index 41617f57..703fa86f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java @@ -5,6 +5,7 @@ import lombok.Data; import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.util.List; @@ -21,6 +22,6 @@ public class ProductAttrParam extends BaseQueryParam { private String key; - @NotNull(groups = BaseEntity.Delete.class) + @NotEmpty(groups = BaseEntity.Delete.class) private List ids; } From 08664cab160498f864f01b971cef1782d7200a21 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 26 Aug 2021 11:47:31 +0800 Subject: [PATCH 039/763] =?UTF-8?q?pom=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zeus-webapp/pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zeus-webapp/pom.xml b/zeus-webapp/pom.xml index 4351c702..4077aff0 100644 --- a/zeus-webapp/pom.xml +++ b/zeus-webapp/pom.xml @@ -38,6 +38,10 @@ 1.0-beta compile + + org.springframework.boot + spring-boot-starter-websocket + From 25a2cc3b3dc943f1e702cc48b47a8dabf484ae98 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 26 Aug 2021 12:48:38 +0800 Subject: [PATCH 040/763] remove global forest interceptor. --- .../driver/inteceptor/JsonBodyBuildInterceptor.java | 9 ++++++++- .../com/zmops/zeus/driver/service/ZbxAction.java | 6 +++++- .../com/zmops/zeus/driver/service/ZbxApiInfo.java | 6 +++++- .../zeus/driver/service/ZbxDeviceStatusTrigger.java | 6 +++++- .../zmops/zeus/driver/service/ZbxHistoryGet.java | 6 +++++- .../java/com/zmops/zeus/driver/service/ZbxHost.java | 6 +++++- .../com/zmops/zeus/driver/service/ZbxHostGroup.java | 6 +++++- .../java/com/zmops/zeus/driver/service/ZbxItem.java | 6 +++++- .../com/zmops/zeus/driver/service/ZbxScript.java | 6 +++++- .../com/zmops/zeus/driver/service/ZbxTemplate.java | 6 +++++- .../java/com/zmops/zeus/driver/service/ZbxUser.java | 13 ++++++++++--- .../com/zmops/zeus/driver/service/ZbxUserGroup.java | 6 +++++- .../com/zmops/zeus/driver/service/ZbxValueMap.java | 6 +++++- zeus-starter/src/main/resources/application.yaml | 5 ++--- 14 files changed, 75 insertions(+), 18 deletions(-) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/JsonBodyBuildInterceptor.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/JsonBodyBuildInterceptor.java index 2328b46d..c021c9ea 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/JsonBodyBuildInterceptor.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/JsonBodyBuildInterceptor.java @@ -1,6 +1,7 @@ package com.zmops.zeus.driver.inteceptor; import com.alibaba.fastjson.JSON; +import com.dtflys.forest.http.ForestCookies; import com.dtflys.forest.http.ForestRequest; import com.dtflys.forest.http.ForestResponse; import com.dtflys.forest.interceptor.Interceptor; @@ -48,7 +49,7 @@ public void onInvokeMethod(ForestRequest request, ForestMethod method, Object[] } else { Annotation[][] paramAnnos = method.getMethod().getParameterAnnotations(); for (int i = 0; i < args.length; i++) { - if (paramAnnos[i][0] instanceof ParamName) { + if (paramAnnos[i].length > 0 && paramAnnos[i][0] instanceof ParamName) { ParamName paramAnno = (ParamName) paramAnnos[i][0]; paramMap.put(paramAnno.value(), args[i]); } @@ -80,4 +81,10 @@ public void onSuccess(String data, ForestRequest request, ForestResponse respons response.setResult(responseData.getResult()); Interceptor.super.onSuccess(data, request, response); } + + @Override + public void onSaveCookie(ForestRequest request, ForestCookies cookies) { + // 获取请求URI的主机名 + String host = request.getURI().getHost(); + } } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java index 8093da2a..5a08122a 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java @@ -4,12 +4,16 @@ import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; /** * @author nantian created at 2021/8/7 23:27 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxAction { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxApiInfo.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxApiInfo.java index ff6aa3ad..340fb0c1 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxApiInfo.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxApiInfo.java @@ -3,12 +3,16 @@ import com.dtflys.forest.annotation.BaseRequest; import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; /** * @author nantian created at 2021/8/3 11:58 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxApiInfo { /** diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java index 97b2bfb8..8cc002e7 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java @@ -4,13 +4,17 @@ import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; /** * @author nantian created at 2021/8/10 16:32 *

* 设备离线 在线触发器,判断设备 在线,离线 状态 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxDeviceStatusTrigger { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java index b470f03e..203b2b84 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java @@ -4,6 +4,7 @@ import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; import java.util.List; @@ -11,7 +12,10 @@ * @author nantian created at 2021/8/3 14:50 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxHistoryGet { @Post diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java index 0898acb9..e29965fb 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java @@ -4,6 +4,7 @@ import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; import lombok.Data; import java.util.List; @@ -14,7 +15,10 @@ *

* 主机驱动 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxHost { /** diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java index d9f1af37..2061088e 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java @@ -4,6 +4,7 @@ import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; import java.util.List; @@ -11,7 +12,10 @@ * @author nantian created at 2021/8/3 16:02 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxHostGroup { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java index 5023d393..828ba821 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java @@ -5,6 +5,7 @@ import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; import com.zmops.zeus.driver.entity.ZbxProcessingStep; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; import java.util.List; import java.util.Map; @@ -13,7 +14,10 @@ * @author nantian created at 2021/8/4 18:07 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxItem { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java index 900bb399..1b6934fb 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java @@ -4,11 +4,15 @@ import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; /** * @author nantian created at 2021/8/7 20:42 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxScript { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java index e44a957c..41a4d2cf 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java @@ -4,6 +4,7 @@ import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; import java.util.Map; @@ -11,7 +12,10 @@ * @author nantian created at 2021/8/3 15:47 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxTemplate { /** diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java index eb84cd36..d56d686e 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java @@ -4,6 +4,7 @@ import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; import java.util.List; @@ -13,7 +14,10 @@ * ZABBIX User 接口 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxUser { /** @@ -39,7 +43,9 @@ String userLogin(@ParamName("username") String username, */ @Post @JsonPath("/user/userAdd") - String userAdd(@ParamName("name") String name, @ParamName("password") String password, @ParamName("usrGrpId") String usrGrpId); + String userAdd(@ParamName("name") String name, + @ParamName("password") String password, + @ParamName("usrGrpId") String usrGrpId); /** * 用户修改 @@ -50,7 +56,8 @@ String userLogin(@ParamName("username") String username, */ @Post @JsonPath("/user/userUpdate") - String userUpdate(@ParamName("userId") String userId, @ParamName("usrGrpId") String usrGrpId); + String userUpdate(@ParamName("userId") String userId, + @ParamName("usrGrpId") String usrGrpId); /** * 用户删除 diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java index 5ccf1d46..271881c2 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java @@ -4,6 +4,7 @@ import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; import java.util.List; @@ -13,7 +14,10 @@ * ZABBIX UserGrp 接口 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxUserGroup { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxValueMap.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxValueMap.java index 54ec7e61..37378b6d 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxValueMap.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxValueMap.java @@ -4,6 +4,7 @@ import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; import java.util.Map; @@ -12,7 +13,10 @@ *

* 值映射设置 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxValueMap { /** diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index 54e3be20..2d6188d0 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -41,13 +41,12 @@ forest: zbxApiUrl: http://${ZEUS_ZABBIX_HOST:127.0.0.1}:${ZEUS_ZABBIX_API_PORT:80}/zabbix/api_jsonrpc.php zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:10051} - zbxApiToken: e39f259dc2b5a5deb583531380a56d85 + zbxApiToken: 5fb3c3b5cc8a2e9c0606db59c5d4c65bddcdfc8f8a74640cb367e4a27f6180f1 ## 设备触发告警,执行动作回调 IOT-SERVER 处理 zeusServerIp: ${ZEUS_CALLBACK_HOST:127.0.0.1} zeusServerPort: ${ZEUS_CALLBACK_PORT:9090} - interceptors: - - com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor + log-enabled: false timeout: 5000 From 13a85bd4df5c12bce326a029e76285953e393b03 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 26 Aug 2021 13:45:55 +0800 Subject: [PATCH 041/763] =?UTF-8?q?=E5=90=AF=E5=8A=A8=E5=88=9B=E5=BB=BA=20?= =?UTF-8?q?=E5=8F=AA=E8=AF=BB=E6=9D=83=E9=99=90=20=E7=94=A8=E6=88=B7guest?= =?UTF-8?q?=EF=BC=8C=E4=BB=A5=E8=8E=B7=E5=8F=96=20cookie?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zeus/driver/service/ZbxInitService.java | 29 +++++++++++++++++++ .../usergroup/cookieUserGroupCreate.ftl | 14 +++++++++ .../com/zmops/iot/web/auth/AuthService.java | 19 +++++++++++- .../zmops/iot/web/init/BasicSettingsInit.java | 24 +++++++++++++++ .../iot/web/init/DeviceSatusScriptInit.java | 3 ++ 5 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java create mode 100644 zeus-driver/src/main/resources/api-json/usergroup/cookieUserGroupCreate.ftl diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java new file mode 100644 index 00000000..83074cae --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java @@ -0,0 +1,29 @@ +package com.zmops.zeus.driver.service; + +import com.dtflys.forest.annotation.BaseRequest; +import com.dtflys.forest.annotation.Body; +import com.dtflys.forest.annotation.Post; +import com.dtflys.forest.callback.OnSaveCookie; +import com.zmops.zeus.driver.annotation.JsonPath; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; + +/** + * @author nantian created at 2021/8/26 12:20 + */ + +public interface ZbxInitService { + + @Post( + url = "http://${zbxServerIp}/zabbix/index.php", + headers = {"Content-Type: application/x-www-form-urlencoded"} + ) + String getCookie(@Body String body, OnSaveCookie onSaveCookie); + + + @Post( + url = "${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class + ) + @JsonPath("/usergroup/cookieUserGroupCreate") + String createCookieUserGroup(String hostGroupId); +} diff --git a/zeus-driver/src/main/resources/api-json/usergroup/cookieUserGroupCreate.ftl b/zeus-driver/src/main/resources/api-json/usergroup/cookieUserGroupCreate.ftl new file mode 100644 index 00000000..9cea5716 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/usergroup/cookieUserGroupCreate.ftl @@ -0,0 +1,14 @@ +{ + "jsonrpc": "2.0", + "method": "usergroup.create", + "params": { + "name": "cookie", + "gui_access": 0, + "rights": { + "permission": 2, + "id": "${hostGroupId}" + } + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java index 135d38df..483bc5e8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java @@ -2,6 +2,7 @@ import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.convert.Convert; +import com.dtflys.forest.http.ForestCookie; import com.zmops.iot.core.auth.cache.SessionManager; import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.core.auth.exception.AuthException; @@ -21,6 +22,7 @@ import com.zmops.iot.web.log.factory.LogTaskFactory; import com.zmops.iot.web.sys.dto.LoginUserDto; import com.zmops.iot.web.sys.factory.UserFactory; +import com.zmops.zeus.driver.service.ZbxCookieGet; import com.zmops.zeus.driver.service.ZbxUser; import io.ebean.DB; import io.ebean.SqlRow; @@ -34,6 +36,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.concurrent.atomic.AtomicReference; import static com.zmops.iot.constant.ConstantsContext.getJwtSecretExpireSec; import static com.zmops.iot.constant.ConstantsContext.getTokenHeaderName; @@ -49,6 +52,9 @@ public class AuthService { @Autowired private ZbxUser zbxUser; + @Autowired + private ZbxCookieGet zbxCookieGet; + /** * 用户名 和 密码 登陆 @@ -58,6 +64,18 @@ public class AuthService { * @return */ public LoginUserDto login(String username, String password) { + + AtomicReference cookieAtomic = new AtomicReference<>(null); + + String param = "name=Admin&password=zabbix&autologin=1&enter=Sign+in"; + + zbxCookieGet.getCookie(param, (request, cookies) -> { + cookieAtomic.set(cookies.allCookies().get(0)); + }); + + ForestCookie cookie = cookieAtomic.get(); + + SysUser user = new QSysUser().account.eq(username).findOne(); // 账号不存在 @@ -92,7 +110,6 @@ public LoginUserDto login(String username, String password) { throw new ServiceException(BizExceptionEnum.ZBX_TOKEN_SAVE_ERROR); } - return LoginUserDto.buildLoginUser(user, login(user)); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java index 849309ec..0f1b2197 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java @@ -4,8 +4,10 @@ import com.dtflys.forest.config.ForestConfiguration; import com.zmops.zeus.driver.service.ZbxAction; import com.zmops.zeus.driver.service.ZbxHostGroup; +import com.zmops.zeus.driver.service.ZbxInitService; import com.zmops.zeus.driver.service.ZbxScript; import lombok.Data; +import org.checkerframework.checker.units.qual.A; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -32,6 +34,9 @@ public class BasicSettingsInit { @Autowired private ZbxAction zbxAction; + @Autowired + private ZbxInitService zbxInitService; + private String zeusServerIp; private String zeusServerPort; private String zbxApiToken; @@ -55,6 +60,23 @@ public String createGlobalHostGroup() { return JSON.parseObject(response, ZbxResponseIds.class).getGroupids()[0]; } + + /** + * 创建 只读权限用户组 + * + * @param globalHostGroupId 全局主机组ID + * @return String + */ + public String createCookieUserGroup(String globalHostGroupId) { + String response = zbxInitService.createCookieUserGroup(globalHostGroupId); + return JSON.parseObject(response, ZbxResponseIds.class).getUsrgrpids()[0]; + } + + /** + * 创建全局主机组 + * + * @return String + */ public String getGlobalHostGroup() { String response = zbxHostGroup.getGlobalHostGroup(zbxApiToken); List> ids = JSON.parseObject(response, List.class); @@ -101,5 +123,7 @@ static class ZbxResponseIds { String[] groupids; String[] scriptids; String[] actionids; + + String[] usrgrpids; } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java index db23e880..2b111a03 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java @@ -39,6 +39,9 @@ public void run(String... args) throws Exception { groupId = basicSettingsInit.createGlobalHostGroup(); } + String userGroupId = basicSettingsInit.createCookieUserGroup(groupId); + + DB.update(SysConfig.class).where().eq("code", GLOBAL_HOST_GROUP_CODE).asUpdate().set("value", groupId).update(); // 第二步:创建全局回调脚本 From 814bf09da943a4e5bcf8b6b75a973da886058ae0 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 26 Aug 2021 14:09:03 +0800 Subject: [PATCH 042/763] =?UTF-8?q?=E4=BF=AE=E6=94=B9zbxApiToken?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zeus-starter/src/main/resources/application.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index 2d6188d0..6f579bf1 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -41,7 +41,7 @@ forest: zbxApiUrl: http://${ZEUS_ZABBIX_HOST:127.0.0.1}:${ZEUS_ZABBIX_API_PORT:80}/zabbix/api_jsonrpc.php zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:10051} - zbxApiToken: 5fb3c3b5cc8a2e9c0606db59c5d4c65bddcdfc8f8a74640cb367e4a27f6180f1 + zbxApiToken: 0fc68dae932f185a22901cd7d3f1ee55d70353ff03f2a2cdea795043aa4ca2a7 ## 设备触发告警,执行动作回调 IOT-SERVER 处理 zeusServerIp: ${ZEUS_CALLBACK_HOST:127.0.0.1} From b632af217771928d0591815feaf98b5075f1abff Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 26 Aug 2021 14:23:54 +0800 Subject: [PATCH 043/763] cookie get --- .../src/main/java/com/zmops/iot/web/auth/AuthService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java index 483bc5e8..92316069 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java @@ -22,7 +22,7 @@ import com.zmops.iot.web.log.factory.LogTaskFactory; import com.zmops.iot.web.sys.dto.LoginUserDto; import com.zmops.iot.web.sys.factory.UserFactory; -import com.zmops.zeus.driver.service.ZbxCookieGet; +import com.zmops.zeus.driver.service.ZbxInitService; import com.zmops.zeus.driver.service.ZbxUser; import io.ebean.DB; import io.ebean.SqlRow; @@ -53,7 +53,7 @@ public class AuthService { private ZbxUser zbxUser; @Autowired - private ZbxCookieGet zbxCookieGet; + private ZbxInitService zbxInitService; /** @@ -69,7 +69,7 @@ public LoginUserDto login(String username, String password) { String param = "name=Admin&password=zabbix&autologin=1&enter=Sign+in"; - zbxCookieGet.getCookie(param, (request, cookies) -> { + zbxInitService.getCookie(param, (request, cookies) -> { cookieAtomic.set(cookies.allCookies().get(0)); }); From e76658599bb24d3fc2933efe577dbd22562c3601 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 26 Aug 2021 14:40:50 +0800 Subject: [PATCH 044/763] update readme.md --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index e3388324..aa84e36a 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,6 @@ ![Version](https://img.shields.io/badge/version-1.0.0--RELEASE-brightgreen) [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) -### 简介 - -**Zeus-IOT**是 - ### 快速安装 Zeus-IOT 支持 Centos 7、Ubuntu 20.04、Debain 10 、Kylin、UOS 等基于x86_64平台的 Linux 操作系统。 From 5c4e6c382740fdbd2c9b25a01468511475fd5a1f Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 26 Aug 2021 14:42:11 +0800 Subject: [PATCH 045/763] Update readme. md. --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index aa84e36a..5d468070 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@ ## Zeus IOT 宙斯物联网分布式采集平台 -[![GitHub stars](https://img.shields.io/github/stars/zmops/zeus-iot.svg?style=for-the-badge&label=Stars&logo=github)](https://github.com/zmops/zeus-iot) -[![GitHub issues](https://img.shields.io/github/issues/zmops/zeus-iot?style=for-the-badge&label=Issuess&logo=github)](https://github.com/zmops/zeus-iot) -[![GitHub forks](https://img.shields.io/github/forks/zmops/zeus-iot?style=for-the-badge&label=Forks&logo=github)](https://github.com/zmops/zeus-iot) - +[![GitHub stars](https://img.shields.io/github/stars/zmops/zeus-iot.svg?label=Stars&logo=github)](https://github.com/zmops/zeus-iot) +[![GitHub issues](https://img.shields.io/github/issues/zmops/zeus-iot?label=Issuess&logo=github)](https://github.com/zmops/zeus-iot) +[![GitHub forks](https://img.shields.io/github/forks/zmops/zeus-iot?label=Forks&logo=github)](https://github.com/zmops/zeus-iot) ![Version](https://img.shields.io/badge/version-1.0.0--RELEASE-brightgreen) [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) From 1836f7b7ac42ac583e834d7f17a9e75f15dc6f5c Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 26 Aug 2021 15:15:46 +0800 Subject: [PATCH 046/763] =?UTF-8?q?=E8=8E=B7=E5=8F=96Zbx=20Cookie?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zeus/driver/service/ZbxInitService.java | 31 ++++++++++-- .../resources/api-json/user/cookieUserAdd.ftl | 16 ++++++ .../resources/api-json/user/cookieUserGet.ftl | 12 +++++ .../api-json/usergroup/cookieUserGroupGet.ftl | 13 +++++ .../src/main/resources/application.yaml | 4 +- .../com/zmops/iot/web/auth/AuthService.java | 23 ++++----- .../zmops/iot/web/init/BasicSettingsInit.java | 49 ++++++++++++++++--- .../iot/web/init/DeviceSatusScriptInit.java | 18 +++---- .../web/sys/controller/LoginController.java | 5 ++ 9 files changed, 139 insertions(+), 32 deletions(-) create mode 100644 zeus-driver/src/main/resources/api-json/user/cookieUserAdd.ftl create mode 100644 zeus-driver/src/main/resources/api-json/user/cookieUserGet.ftl create mode 100644 zeus-driver/src/main/resources/api-json/usergroup/cookieUserGroupGet.ftl diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java index 83074cae..723529a7 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java @@ -1,10 +1,10 @@ package com.zmops.zeus.driver.service; -import com.dtflys.forest.annotation.BaseRequest; import com.dtflys.forest.annotation.Body; import com.dtflys.forest.annotation.Post; import com.dtflys.forest.callback.OnSaveCookie; import com.zmops.zeus.driver.annotation.JsonPath; +import com.zmops.zeus.driver.annotation.ParamName; import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; /** @@ -14,7 +14,7 @@ public interface ZbxInitService { @Post( - url = "http://${zbxServerIp}/zabbix/index.php", + url = "http://${zbxServerIp}:${zbxServerPort}/zabbix/index.php", headers = {"Content-Type: application/x-www-form-urlencoded"} ) String getCookie(@Body String body, OnSaveCookie onSaveCookie); @@ -22,8 +22,33 @@ public interface ZbxInitService { @Post( url = "${zbxApiUrl}", + headers = "authTag: noAuth", interceptor = JsonBodyBuildInterceptor.class ) @JsonPath("/usergroup/cookieUserGroupCreate") - String createCookieUserGroup(String hostGroupId); + String createCookieUserGroup(@ParamName("hostGroupId") String hostGroupId,@ParamName("userAuth") String userAuth); + + @Post( + url = "${zbxApiUrl}", + headers = "authTag: noAuth", + interceptor = JsonBodyBuildInterceptor.class + ) + @JsonPath("/usergroup/cookieUserGroupGet") + String getCookieUserGroup(@ParamName("userAuth") String userAuth); + + @Post( + url = "${zbxApiUrl}", + headers = "authTag: noAuth", + interceptor = JsonBodyBuildInterceptor.class + ) + @JsonPath("/user/cookieUserGet") + String getCookieUser(@ParamName("userAuth") String userAuth); + + @Post( + url = "${zbxApiUrl}", + headers = "authTag: noAuth", + interceptor = JsonBodyBuildInterceptor.class + ) + @JsonPath("/user/cookieUserAdd") + String createCookieUser(@ParamName("usrGrpId") String usrGrpId,@ParamName("userAuth") String userAuth); } diff --git a/zeus-driver/src/main/resources/api-json/user/cookieUserAdd.ftl b/zeus-driver/src/main/resources/api-json/user/cookieUserAdd.ftl new file mode 100644 index 00000000..14226d8c --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/user/cookieUserAdd.ftl @@ -0,0 +1,16 @@ +{ + "jsonrpc": "2.0", + "method": "user.create", + "params": { + "username": "cookie", + "passwd": "cookie", + "roleid": "4", + "usrgrps": [ + { + "usrgrpid": "${usrGrpId}" + } + ] + }, + "id": 1, + "auth": "${userAuth}" +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/user/cookieUserGet.ftl b/zeus-driver/src/main/resources/api-json/user/cookieUserGet.ftl new file mode 100644 index 00000000..b46b16f4 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/user/cookieUserGet.ftl @@ -0,0 +1,12 @@ +{ + "jsonrpc": "2.0", + "method": "user.get", + "params": { + "output": "extend", + "filter":{ + "username":"cookie" + } + }, + "id": 1, + "auth": "${userAuth}" +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/usergroup/cookieUserGroupGet.ftl b/zeus-driver/src/main/resources/api-json/usergroup/cookieUserGroupGet.ftl new file mode 100644 index 00000000..fc3925ce --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/usergroup/cookieUserGroupGet.ftl @@ -0,0 +1,13 @@ +{ + "jsonrpc": "2.0", + "method": "usergroup.get", + "params": { + "output": "extend", + "status": 0, + "filter":{ + "name":"cookie" + } + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index 6f579bf1..5f0bb6ae 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -38,9 +38,9 @@ spring: forest: variables: ## Zabbix API IP 和 端口 - zbxApiUrl: http://${ZEUS_ZABBIX_HOST:127.0.0.1}:${ZEUS_ZABBIX_API_PORT:80}/zabbix/api_jsonrpc.php + zbxApiUrl: http://${ZEUS_ZABBIX_HOST:127.0.0.1}:${ZEUS_ZABBIX_PORT:80}/zabbix/api_jsonrpc.php zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} - zbxServerPort: ${ZEUS_ZABBIX_PORT:10051} + zbxServerPort: ${ZEUS_ZABBIX_PORT:80} zbxApiToken: 0fc68dae932f185a22901cd7d3f1ee55d70353ff03f2a2cdea795043aa4ca2a7 ## 设备触发告警,执行动作回调 IOT-SERVER 处理 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java index 92316069..31289491 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java @@ -65,17 +65,6 @@ public class AuthService { */ public LoginUserDto login(String username, String password) { - AtomicReference cookieAtomic = new AtomicReference<>(null); - - String param = "name=Admin&password=zabbix&autologin=1&enter=Sign+in"; - - zbxInitService.getCookie(param, (request, cookies) -> { - cookieAtomic.set(cookies.allCookies().get(0)); - }); - - ForestCookie cookie = cookieAtomic.get(); - - SysUser user = new QSysUser().account.eq(username).findOne(); // 账号不存在 @@ -113,6 +102,18 @@ public LoginUserDto login(String username, String password) { return LoginUserDto.buildLoginUser(user, login(user)); } + public String getCookie() { + AtomicReference cookieAtomic = new AtomicReference<>(null); + + String param = "name=cookie&password=cookie&autologin=1&enter=Sign+in"; + + zbxInitService.getCookie(param, (request, cookies) -> { + cookieAtomic.set(cookies.allCookies().get(0)); + }); + + ForestCookie cookie = cookieAtomic.get(); + return cookie.getValue(); + } /** * 用户名 登陆 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java index 0f1b2197..6f2dffee 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java @@ -7,7 +7,6 @@ import com.zmops.zeus.driver.service.ZbxInitService; import com.zmops.zeus.driver.service.ZbxScript; import lombok.Data; -import org.checkerframework.checker.units.qual.A; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -49,6 +48,19 @@ public void init() { zbxApiToken = configuration.getVariables().get("zbxApiToken").toString(); } + /** + * 查询全局主机组 + * + * @return String + */ + public String getGlobalHostGroup() { + String response = zbxHostGroup.getGlobalHostGroup(zbxApiToken); + List> ids = JSON.parseObject(response, List.class); + if (null != ids && ids.size() > 0) { + return ids.get(0).get("groupid"); + } + return null; + } /** * 创建默认全局主机组 @@ -60,6 +72,19 @@ public String createGlobalHostGroup() { return JSON.parseObject(response, ZbxResponseIds.class).getGroupids()[0]; } + /** + * 查询只读权限用户组 + * + * @return String + */ + public String getCookieUserGroup() { + String response = zbxInitService.getCookieUserGroup(zbxApiToken); + List> ids = JSON.parseObject(response, List.class); + if (null != ids && ids.size() > 0) { + return ids.get(0).get("usrgrpid"); + } + return null; + } /** * 创建 只读权限用户组 @@ -68,24 +93,34 @@ public String createGlobalHostGroup() { * @return String */ public String createCookieUserGroup(String globalHostGroupId) { - String response = zbxInitService.createCookieUserGroup(globalHostGroupId); + String response = zbxInitService.createCookieUserGroup(globalHostGroupId,zbxApiToken); return JSON.parseObject(response, ZbxResponseIds.class).getUsrgrpids()[0]; } /** - * 创建全局主机组 + * 查询 只读权限用户 * * @return String */ - public String getGlobalHostGroup() { - String response = zbxHostGroup.getGlobalHostGroup(zbxApiToken); + public String getCookieUser() { + String response = zbxInitService.getCookieUser(zbxApiToken); List> ids = JSON.parseObject(response, List.class); if (null != ids && ids.size() > 0) { - return ids.get(0).get("groupid"); + return ids.get(0).get("userid"); } return null; } + /** + * 创建 只读权限用户 + * + * @param groupId 只读用户组ID + * @return String + */ + public String createCookieUser(String groupId) { + String response = zbxInitService.createCookieUser(groupId,zbxApiToken); + return JSON.parseObject(response, ZbxResponseIds.class).getUserids()[0]; + } public String createOfflineStatusScript() { String response = zbxScript.createOfflineStatusScript(zbxApiToken, zeusServerIp, zeusServerPort); @@ -123,7 +158,7 @@ static class ZbxResponseIds { String[] groupids; String[] scriptids; String[] actionids; - + String[] userids; String[] usrgrpids; } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java index 2b111a03..87d28667 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java @@ -1,20 +1,12 @@ package com.zmops.iot.web.init; -import com.alibaba.fastjson.JSON; -import com.dtflys.forest.config.ForestConfiguration; import com.zmops.iot.domain.sys.SysConfig; -import com.zmops.iot.domain.sys.query.QSysConfig; -import com.zmops.zeus.driver.service.ZbxScript; import io.ebean.DB; -import lombok.Data; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; - /** * @author nantian created at 2021/8/7 20:25 */ @@ -39,7 +31,15 @@ public void run(String... args) throws Exception { groupId = basicSettingsInit.createGlobalHostGroup(); } - String userGroupId = basicSettingsInit.createCookieUserGroup(groupId); + //判断只读用户是否存在 不存在就创建一个 + String userId = basicSettingsInit.getCookieUser(); + if (userId == null) { + String userGroupId = basicSettingsInit.getCookieUserGroup(); + if (userGroupId == null) { + userGroupId = basicSettingsInit.createCookieUserGroup(groupId); + } + basicSettingsInit.createCookieUser(userGroupId); + } DB.update(SysConfig.class).where().eq("code", GLOBAL_HOST_GROUP_CODE).asUpdate().set("value", groupId).update(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java index 9e764618..448c206d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java @@ -59,4 +59,9 @@ public ResponseData logOut() { authService.logout(); return new SuccessResponseData(); } + + @RequestMapping("/getCookie") + public ResponseData getCookie() { + return ResponseData.success(authService.getCookie()); + } } From 0683175deedffbbaad86c9f424c617ebb9fc673b Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 26 Aug 2021 16:34:27 +0800 Subject: [PATCH 047/763] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=94=A8=E6=88=B7=20?= =?UTF-8?q?=E8=A7=92=E8=89=B2=E5=8A=A8=E6=80=81=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zeus/driver/service/ZbxInitService.java | 22 +++++++++++-- .../zmops/zeus/driver/service/ZbxUser.java | 3 +- .../resources/api-json/role/adminRole.get.ftl | 12 +++++++ .../resources/api-json/role/guestRole.get.ftl | 12 +++++++ .../resources/api-json/user/cookieUserAdd.ftl | 2 +- .../main/resources/api-json/user/userAdd.ftl | 2 +- .../zmops/iot/web/init/BasicSettingsInit.java | 32 +++++++++++++++++-- .../iot/web/init/DeviceSatusScriptInit.java | 12 +++++-- .../iot/web/sys/service/SysUserService.java | 6 +++- 9 files changed, 93 insertions(+), 10 deletions(-) create mode 100644 zeus-driver/src/main/resources/api-json/role/adminRole.get.ftl create mode 100644 zeus-driver/src/main/resources/api-json/role/guestRole.get.ftl diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java index 723529a7..cb898f05 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java @@ -26,7 +26,7 @@ public interface ZbxInitService { interceptor = JsonBodyBuildInterceptor.class ) @JsonPath("/usergroup/cookieUserGroupCreate") - String createCookieUserGroup(@ParamName("hostGroupId") String hostGroupId,@ParamName("userAuth") String userAuth); + String createCookieUserGroup(@ParamName("hostGroupId") String hostGroupId, @ParamName("userAuth") String userAuth); @Post( url = "${zbxApiUrl}", @@ -50,5 +50,23 @@ public interface ZbxInitService { interceptor = JsonBodyBuildInterceptor.class ) @JsonPath("/user/cookieUserAdd") - String createCookieUser(@ParamName("usrGrpId") String usrGrpId,@ParamName("userAuth") String userAuth); + String createCookieUser(@ParamName("usrGrpId") String usrGrpId, + @ParamName("userAuth") String userAuth, + @ParamName("roleId") String roleId); + + @Post( + url = "${zbxApiUrl}", + headers = "authTag: noAuth", + interceptor = JsonBodyBuildInterceptor.class + ) + @JsonPath("/role/adminRole.get") + String getAdminRole(@ParamName("userAuth") String zbxApiToken); + + @Post( + url = "${zbxApiUrl}", + headers = "authTag: noAuth", + interceptor = JsonBodyBuildInterceptor.class + ) + @JsonPath("/role/guestRole.get") + String getGuestRole(@ParamName("userAuth") String zbxApiToken); } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java index d56d686e..97697261 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java @@ -45,7 +45,8 @@ String userLogin(@ParamName("username") String username, @JsonPath("/user/userAdd") String userAdd(@ParamName("name") String name, @ParamName("password") String password, - @ParamName("usrGrpId") String usrGrpId); + @ParamName("usrGrpId") String usrGrpId, + @ParamName("roleId") String roleId); /** * 用户修改 diff --git a/zeus-driver/src/main/resources/api-json/role/adminRole.get.ftl b/zeus-driver/src/main/resources/api-json/role/adminRole.get.ftl new file mode 100644 index 00000000..60de160e --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/role/adminRole.get.ftl @@ -0,0 +1,12 @@ +{ + "jsonrpc": "2.0", + "method": "role.get", + "params": { + "output": "extend", + "filter": { + "name":"Admin role" + } + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/role/guestRole.get.ftl b/zeus-driver/src/main/resources/api-json/role/guestRole.get.ftl new file mode 100644 index 00000000..0b0022b4 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/role/guestRole.get.ftl @@ -0,0 +1,12 @@ +{ + "jsonrpc": "2.0", + "method": "role.get", + "params": { + "output": "extend", + "filter": { + "name":"Guest role" + } + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/user/cookieUserAdd.ftl b/zeus-driver/src/main/resources/api-json/user/cookieUserAdd.ftl index 14226d8c..6eeaa644 100644 --- a/zeus-driver/src/main/resources/api-json/user/cookieUserAdd.ftl +++ b/zeus-driver/src/main/resources/api-json/user/cookieUserAdd.ftl @@ -4,7 +4,7 @@ "params": { "username": "cookie", "passwd": "cookie", - "roleid": "4", + "roleid": "${roleId}", "usrgrps": [ { "usrgrpid": "${usrGrpId}" diff --git a/zeus-driver/src/main/resources/api-json/user/userAdd.ftl b/zeus-driver/src/main/resources/api-json/user/userAdd.ftl index e8962ea7..940b08be 100644 --- a/zeus-driver/src/main/resources/api-json/user/userAdd.ftl +++ b/zeus-driver/src/main/resources/api-json/user/userAdd.ftl @@ -4,7 +4,7 @@ "params": { "username": "${name}", "passwd": "${password}", - "roleid": "2", + "roleid": "${roleId}", "usrgrps": [ { "usrgrpid": "${usrGrpId}" diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java index 6f2dffee..d0f0d01a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java @@ -117,11 +117,39 @@ public String getCookieUser() { * @param groupId 只读用户组ID * @return String */ - public String createCookieUser(String groupId) { - String response = zbxInitService.createCookieUser(groupId,zbxApiToken); + public String createCookieUser(String groupId,String roleId) { + String response = zbxInitService.createCookieUser(groupId,zbxApiToken,roleId); return JSON.parseObject(response, ZbxResponseIds.class).getUserids()[0]; } + /** + * 查询 管理员用户角色 + * + * @return String + */ + public String getAdminRoleId() { + String response = zbxInitService.getAdminRole(zbxApiToken); + List> ids = JSON.parseObject(response, List.class); + if (null != ids && ids.size() > 0) { + return ids.get(0).get("roleid"); + } + return null; + } + + /** + * 查询 访客用户角色 + * + * @return String + */ + public String getGuestRoleId() { + String response = zbxInitService.getGuestRole(zbxApiToken); + List> ids = JSON.parseObject(response, List.class); + if (null != ids && ids.size() > 0) { + return ids.get(0).get("roleid"); + } + return null; + } + public String createOfflineStatusScript() { String response = zbxScript.createOfflineStatusScript(zbxApiToken, zeusServerIp, zeusServerPort); return JSON.parseObject(response, ZbxResponseIds.class).getScriptids()[0]; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java index 87d28667..d42e4e09 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java @@ -18,6 +18,7 @@ public class DeviceSatusScriptInit implements CommandLineRunner { public static final String GLOBAL_HOST_GROUP_CODE = "ZEUS_HOST_GROUP_ID"; public static final String GLOBAL_ACTION_CODE = "ZEUS_ACTION_ID"; + public static final String GLOBAL_ADMIN_ROLE_CODE = "ZEUS_ADMIN_ROLE_ID"; @Autowired private BasicSettingsInit basicSettingsInit; @@ -30,6 +31,12 @@ public void run(String... args) throws Exception { if (groupId == null) { groupId = basicSettingsInit.createGlobalHostGroup(); } + DB.update(SysConfig.class).where().eq("code", GLOBAL_HOST_GROUP_CODE).asUpdate().set("value", groupId).update(); + + //判断系统参数是否存在 zbx管理员ID + String roleId = basicSettingsInit.getAdminRoleId(); + DB.update(SysConfig.class).where().eq("code", GLOBAL_ADMIN_ROLE_CODE).asUpdate().set("value", roleId).update(); + //判断只读用户是否存在 不存在就创建一个 String userId = basicSettingsInit.getCookieUser(); @@ -38,11 +45,12 @@ public void run(String... args) throws Exception { if (userGroupId == null) { userGroupId = basicSettingsInit.createCookieUserGroup(groupId); } - basicSettingsInit.createCookieUser(userGroupId); + String guestRoleId = basicSettingsInit.getGuestRoleId(); + basicSettingsInit.createCookieUser(userGroupId,guestRoleId); } - DB.update(SysConfig.class).where().eq("code", GLOBAL_HOST_GROUP_CODE).asUpdate().set("value", groupId).update(); + // 第二步:创建全局回调脚本 String scriptId = basicSettingsInit.getOfflineStatusScript(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java index 95148333..0670274f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java @@ -2,6 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.constant.ConstantsContext; import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.core.auth.exception.enums.AuthExceptionEnum; import com.zmops.iot.core.auth.model.LoginUser; @@ -30,6 +31,9 @@ import java.util.List; import java.util.stream.Collectors; +import static com.zmops.iot.web.init.DeviceSatusScriptInit.GLOBAL_ADMIN_ROLE_CODE; +import static com.zmops.iot.web.init.DeviceSatusScriptInit.GLOBAL_HOST_GROUP_CODE; + /** * @author yefei *

@@ -100,7 +104,7 @@ public SysUser createUser(UserDto user) { SysUser newUser = UserFactory.createUser(user, password, salt); //取对应的ZBX用户组ID String usrZbxId = sysUserGroupService.getZabUsrGrpId(user.getUserGroupId()); - JSONObject result = JSONObject.parseObject(zbxUser.userAdd(user.getAccount(), decryptPwd, usrZbxId)); + JSONObject result = JSONObject.parseObject(zbxUser.userAdd(user.getAccount(), decryptPwd, usrZbxId, ConstantsContext.getConstntsMap().get(GLOBAL_ADMIN_ROLE_CODE).toString())); JSONArray userids = result.getJSONArray("userids"); newUser.setZbxId(String.valueOf(userids.get(0))); DB.save(newUser); From 932039c6bc55d08a5632f638e0092833a870908c Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 26 Aug 2021 18:39:11 +0800 Subject: [PATCH 048/763] pom scope level to provider --- zeus-driver/pom.xml | 1 - zeus-webapp/pom.xml | 2 -- 2 files changed, 3 deletions(-) diff --git a/zeus-driver/pom.xml b/zeus-driver/pom.xml index 7c4982a1..f17ccd52 100644 --- a/zeus-driver/pom.xml +++ b/zeus-driver/pom.xml @@ -15,7 +15,6 @@ com.zmops zeus-core 1.0-beta - compile diff --git a/zeus-webapp/pom.xml b/zeus-webapp/pom.xml index 4077aff0..758bbccd 100644 --- a/zeus-webapp/pom.xml +++ b/zeus-webapp/pom.xml @@ -30,13 +30,11 @@ com.zmops zeus-driver 1.0-beta - compile com.zmops toolkit-async 1.0-beta - compile org.springframework.boot From 23a85a3ed48ed60317357234f54fc9733fd77b4f Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 26 Aug 2021 19:07:37 +0800 Subject: [PATCH 049/763] edit log level in log4j2.xml --- zeus-starter/src/main/resources/log4j2.xml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/zeus-starter/src/main/resources/log4j2.xml b/zeus-starter/src/main/resources/log4j2.xml index f0789393..82c64a42 100644 --- a/zeus-starter/src/main/resources/log4j2.xml +++ b/zeus-starter/src/main/resources/log4j2.xml @@ -72,9 +72,7 @@ - - - + From 46c4e6dff6299927f369376ce9b216040815d2d4 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 26 Aug 2021 21:04:41 +0800 Subject: [PATCH 050/763] remove unused code. --- .../zeus/driver/inteceptor/JsonBodyBuildInterceptor.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/JsonBodyBuildInterceptor.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/JsonBodyBuildInterceptor.java index c021c9ea..fc4b6fb4 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/JsonBodyBuildInterceptor.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/JsonBodyBuildInterceptor.java @@ -1,7 +1,6 @@ package com.zmops.zeus.driver.inteceptor; import com.alibaba.fastjson.JSON; -import com.dtflys.forest.http.ForestCookies; import com.dtflys.forest.http.ForestRequest; import com.dtflys.forest.http.ForestResponse; import com.dtflys.forest.interceptor.Interceptor; @@ -81,10 +80,4 @@ public void onSuccess(String data, ForestRequest request, ForestResponse respons response.setResult(responseData.getResult()); Interceptor.super.onSuccess(data, request, response); } - - @Override - public void onSaveCookie(ForestRequest request, ForestCookies cookies) { - // 获取请求URI的主机名 - String host = request.getURI().getHost(); - } } From 62f85d6befb64f62db3132e0af74b670420edd99 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 26 Aug 2021 21:19:57 +0800 Subject: [PATCH 051/763] add zeus-iot-ui gitmodule --- .gitmodules | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .gitmodules diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..05d54264 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "zeus-iot-ui"] + path = zeus-iot-ui + url = https://github.com/zmops/zeus-iot-ui.git \ No newline at end of file From a02865345ea11601043df2dfdded08d11519014c Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 26 Aug 2021 21:23:31 +0800 Subject: [PATCH 052/763] remove gitmodule --- .gitmodules | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .gitmodules diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 05d54264..00000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "zeus-iot-ui"] - path = zeus-iot-ui - url = https://github.com/zmops/zeus-iot-ui.git \ No newline at end of file From 03ec260603829870213ad41021c8015d7948d3e4 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 26 Aug 2021 21:26:44 +0800 Subject: [PATCH 053/763] add zeus-iot-ui submodule --- .gitmodules | 3 +++ zeus-iot-ui | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 zeus-iot-ui diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..3b721b2e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "zeus-iot-ui"] + path = zeus-iot-ui + url = https://github.com/zmops/zeus-iot-ui.git diff --git a/zeus-iot-ui b/zeus-iot-ui new file mode 160000 index 00000000..94648c2c --- /dev/null +++ b/zeus-iot-ui @@ -0,0 +1 @@ +Subproject commit 94648c2c643dd611574752c6c8a2f47bba2b45e0 From 9b121e5deadbeab14c2ecc6674b60ec4582e32fb Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 26 Aug 2021 21:38:10 +0800 Subject: [PATCH 054/763] =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=E8=B6=8B=E5=8A=BF=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zeus/driver/service/ZbxInitService.java | 9 --- zeus-webapp/pom.xml | 5 ++ .../com/zmops/iot/web/auth/AuthService.java | 76 ++++++++++++++++--- .../web/sys/controller/LoginController.java | 13 +++- 4 files changed, 81 insertions(+), 22 deletions(-) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java index cb898f05..98307926 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java @@ -1,8 +1,6 @@ package com.zmops.zeus.driver.service; -import com.dtflys.forest.annotation.Body; import com.dtflys.forest.annotation.Post; -import com.dtflys.forest.callback.OnSaveCookie; import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; @@ -13,13 +11,6 @@ public interface ZbxInitService { - @Post( - url = "http://${zbxServerIp}:${zbxServerPort}/zabbix/index.php", - headers = {"Content-Type: application/x-www-form-urlencoded"} - ) - String getCookie(@Body String body, OnSaveCookie onSaveCookie); - - @Post( url = "${zbxApiUrl}", headers = "authTag: noAuth", diff --git a/zeus-webapp/pom.xml b/zeus-webapp/pom.xml index 758bbccd..1f39a23c 100644 --- a/zeus-webapp/pom.xml +++ b/zeus-webapp/pom.xml @@ -40,6 +40,11 @@ org.springframework.boot spring-boot-starter-websocket + + commons-httpclient + commons-httpclient + 3.1 + diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java index 31289491..1f6143ac 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java @@ -2,7 +2,6 @@ import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.convert.Convert; -import com.dtflys.forest.http.ForestCookie; import com.zmops.iot.core.auth.cache.SessionManager; import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.core.auth.exception.AuthException; @@ -13,6 +12,7 @@ import com.zmops.iot.core.util.HttpContext; import com.zmops.iot.core.util.RsaUtil; import com.zmops.iot.core.util.SaltUtil; +import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.domain.sys.SysUser; import com.zmops.iot.domain.sys.query.QSysUser; import com.zmops.iot.model.exception.ServiceException; @@ -26,17 +26,21 @@ import com.zmops.zeus.driver.service.ZbxUser; import io.ebean.DB; import io.ebean.SqlRow; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.methods.PostMethod; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.OutputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.concurrent.atomic.AtomicReference; import static com.zmops.iot.constant.ConstantsContext.getJwtSecretExpireSec; import static com.zmops.iot.constant.ConstantsContext.getTokenHeaderName; @@ -55,6 +59,12 @@ public class AuthService { @Autowired private ZbxInitService zbxInitService; + @Value("${forest.variables.zbxServerIp}") + private String zbxServerIp; + + @Value("${forest.variables.zbxServerPort}") + private String zbxServerPort; + /** * 用户名 和 密码 登陆 @@ -102,17 +112,63 @@ public LoginUserDto login(String username, String password) { return LoginUserDto.buildLoginUser(user, login(user)); } - public String getCookie() { - AtomicReference cookieAtomic = new AtomicReference<>(null); + public void getCharts(HttpServletResponse response, String from, String to, List attrIds, String width, String height) { + try { + String cookie = getCookie(); + List itemids = getItemIds(attrIds); + + HttpClient client = new HttpClient(); + PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort + "/zabbix/chart.php?type=0&profileIdx=web.item.graph.filter&profileIdx2=36816&_=v14ede3k"); + NameValuePair[] nameValuePairs = new NameValuePair[itemids.size() + 4]; + nameValuePairs[0] = new NameValuePair("from", from); + nameValuePairs[1] = new NameValuePair("to", to); + nameValuePairs[2] = new NameValuePair("width", width); + nameValuePairs[3] = new NameValuePair("height", height); + for (int index = 0; index < itemids.size(); index++) { + nameValuePairs[4 + index] = new NameValuePair("itemids[" + index + "]", itemids.get(index)); + } + + postMethod.setRequestBody(nameValuePairs); + postMethod.setRequestHeader("Content_Type", "application/json-rpc"); + postMethod.setRequestHeader("Cookie", cookie); - String param = "name=cookie&password=cookie&autologin=1&enter=Sign+in"; + //执行请求 + client.executeMethod(postMethod); + byte[] responseBody = postMethod.getResponseBody(); + response.setContentType("image/jpeg"); + OutputStream out = response.getOutputStream(); + out.write(responseBody); + out.flush(); + //关闭响应输出流 + out.close(); - zbxInitService.getCookie(param, (request, cookies) -> { - cookieAtomic.set(cookies.allCookies().get(0)); - }); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private List getItemIds(List attrIds) { + return new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(attrIds).findSingleAttributeList(); + } - ForestCookie cookie = cookieAtomic.get(); - return cookie.getValue(); + private String getCookie() throws Exception { + HttpClient client = new HttpClient(); + PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort + "/zabbix/index.php"); + //推荐的数据存储方式,类似key-value形式 + + NameValuePair namePair = new NameValuePair("name", "cookie"); + NameValuePair pwdPair = new NameValuePair("password", "cookie"); + NameValuePair autologinPair = new NameValuePair("autologin", "1"); + NameValuePair enterPair = new NameValuePair("enter", "Sign in"); + //构建表单参数 + + postMethod.setRequestBody(new NameValuePair[]{namePair, pwdPair, autologinPair, enterPair}); + postMethod.setRequestHeader("Content_Type", "application/json"); + //执行请求 + client.executeMethod(postMethod); + //通过Post/GetMethod对象获取响应头信息 + String cookie = postMethod.getResponseHeader("Set-Cookie").getValue(); + return cookie; } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java index 448c206d..09900828 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java @@ -12,7 +12,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; +import java.util.List; /** * @author nantian created at 2021/7/29 19:55 @@ -60,8 +62,13 @@ public ResponseData logOut() { return new SuccessResponseData(); } - @RequestMapping("/getCookie") - public ResponseData getCookie() { - return ResponseData.success(authService.getCookie()); + @RequestMapping("/getCharts") + public void getCookie(HttpServletResponse response, + @RequestParam("from") String from, + @RequestParam("to") String to, + @RequestParam("attrIds") List attrIds, + @RequestParam("width") String width, + @RequestParam("height") String height) { + authService.getCharts(response,from,to,attrIds,width,height); } } From 078758b6fd52e76ae28f9e90dec9deae65127633 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 26 Aug 2021 22:14:55 +0800 Subject: [PATCH 055/763] code optimization. --- zeus-starter/src/main/resources/log4j2.xml | 4 + .../com/zmops/iot/web/auth/AuthService.java | 109 ++++++++++++------ 2 files changed, 79 insertions(+), 34 deletions(-) diff --git a/zeus-starter/src/main/resources/log4j2.xml b/zeus-starter/src/main/resources/log4j2.xml index 82c64a42..da090853 100644 --- a/zeus-starter/src/main/resources/log4j2.xml +++ b/zeus-starter/src/main/resources/log4j2.xml @@ -77,6 +77,10 @@ + + + + diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java index 1f6143ac..8b2e2264 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java @@ -37,6 +37,9 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collections; @@ -112,63 +115,101 @@ public LoginUserDto login(String username, String password) { return LoginUserDto.buildLoginUser(user, login(user)); } - public void getCharts(HttpServletResponse response, String from, String to, List attrIds, String width, String height) { - try { - String cookie = getCookie(); - List itemids = getItemIds(attrIds); - - HttpClient client = new HttpClient(); - PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort + "/zabbix/chart.php?type=0&profileIdx=web.item.graph.filter&profileIdx2=36816&_=v14ede3k"); - NameValuePair[] nameValuePairs = new NameValuePair[itemids.size() + 4]; - nameValuePairs[0] = new NameValuePair("from", from); - nameValuePairs[1] = new NameValuePair("to", to); - nameValuePairs[2] = new NameValuePair("width", width); - nameValuePairs[3] = new NameValuePair("height", height); - for (int index = 0; index < itemids.size(); index++) { - nameValuePairs[4 + index] = new NameValuePair("itemids[" + index + "]", itemids.get(index)); - } + /** + * 获取 数据图形展示 + * + * @param response http响应 + * @param from 开始时间 + * @param to 结束时间 + * @param attrIds 设备属性ID + * @param width 图表宽度 + * @param height 图表高度 + */ + public void getCharts(HttpServletResponse response, + String from, String to, + List attrIds, String width, String height) { + + String cookie = getCookie(); + List itemids = getItemIds(attrIds); + + HttpClient client = new HttpClient(); + PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort + + "/zabbix/chart.php?type=0&profileIdx=web.item.graph.filter&profileIdx2=36816&_=v14ede3k"); - postMethod.setRequestBody(nameValuePairs); - postMethod.setRequestHeader("Content_Type", "application/json-rpc"); - postMethod.setRequestHeader("Cookie", cookie); + NameValuePair[] nameValuePairs = new NameValuePair[itemids.size() + 4]; + nameValuePairs[0] = new NameValuePair("from", from); + nameValuePairs[1] = new NameValuePair("to", to); + nameValuePairs[2] = new NameValuePair("width", width); + nameValuePairs[3] = new NameValuePair("height", height); - //执行请求 + for (int index = 0; index < itemids.size(); index++) { + nameValuePairs[4 + index] = new NameValuePair("itemids[" + index + "]", itemids.get(index)); + } + + postMethod.setRequestBody(nameValuePairs); + postMethod.setRequestHeader("Content_Type", "application/json-rpc"); + postMethod.setRequestHeader("Cookie", cookie); + + OutputStream out = null; + try { client.executeMethod(postMethod); - byte[] responseBody = postMethod.getResponseBody(); + InputStream responseBody = postMethod.getResponseBodyAsStream(); response.setContentType("image/jpeg"); - OutputStream out = response.getOutputStream(); - out.write(responseBody); + + out = response.getOutputStream(); + out.write(toByteArray(responseBody)); + out.flush(); - //关闭响应输出流 - out.close(); + } catch (IOException ioException) { + ioException.printStackTrace(); + } finally { + try { + if (null != out) out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } - } catch (Exception e) { - e.printStackTrace(); + } + + private static byte[] toByteArray(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + + byte[] buffer = new byte[4096]; + int n = 0; + + while (-1 != (n = input.read(buffer))) { + output.write(buffer, 0, n); } + + return output.toByteArray(); } + private List getItemIds(List attrIds) { return new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(attrIds).findSingleAttributeList(); } - private String getCookie() throws Exception { + + private String getCookie() { HttpClient client = new HttpClient(); PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort + "/zabbix/index.php"); - //推荐的数据存储方式,类似key-value形式 + //TODO 使用了一个只读权限的访客用户 NameValuePair namePair = new NameValuePair("name", "cookie"); NameValuePair pwdPair = new NameValuePair("password", "cookie"); NameValuePair autologinPair = new NameValuePair("autologin", "1"); NameValuePair enterPair = new NameValuePair("enter", "Sign in"); - //构建表单参数 postMethod.setRequestBody(new NameValuePair[]{namePair, pwdPair, autologinPair, enterPair}); postMethod.setRequestHeader("Content_Type", "application/json"); - //执行请求 - client.executeMethod(postMethod); - //通过Post/GetMethod对象获取响应头信息 - String cookie = postMethod.getResponseHeader("Set-Cookie").getValue(); - return cookie; + + try { + client.executeMethod(postMethod); + } catch (IOException ioException) { + ioException.printStackTrace(); + } + return postMethod.getResponseHeader("Set-Cookie").getValue(); } /** From 8fb73efc798c46c4a58990ca64db316418fd71c3 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 27 Aug 2021 09:28:30 +0800 Subject: [PATCH 056/763] =?UTF-8?q?=E5=B1=9E=E6=80=A7=E8=B6=8B=E5=8A=BF?= =?UTF-8?q?=E5=9B=BE=E6=8E=A5=E5=8F=A3=20=E7=A7=BB=E5=88=B0=E5=85=A8?= =?UTF-8?q?=E5=B1=80=E6=A6=82=E8=A7=88=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analyse/controller/HomeController.java | 24 ++++ .../iot/web/analyse/service/HomeService.java | 117 ++++++++++++++++++ .../com/zmops/iot/web/auth/AuthService.java | 116 ----------------- .../web/sys/controller/LoginController.java | 9 -- 4 files changed, 141 insertions(+), 125 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java index 3b07e3f7..71fbf561 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java @@ -4,8 +4,12 @@ import com.zmops.iot.web.analyse.service.HomeService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import javax.servlet.http.HttpServletResponse; +import java.util.List; + /** * @author yefei * @@ -22,4 +26,24 @@ public class HomeController { public ResponseData collectonRate(){ return ResponseData.success(homeService.collectonRate()); } + + /** + * 获取 数据图形展示 + * + * @param response http响应 + * @param from 开始时间 + * @param to 结束时间 + * @param attrIds 设备属性ID + * @param width 图表宽度 + * @param height 图表高度 + */ + @RequestMapping("/getCharts") + public void getCookie(HttpServletResponse response, + @RequestParam("from") String from, + @RequestParam("to") String to, + @RequestParam("attrIds") List attrIds, + @RequestParam("width") String width, + @RequestParam("height") String height) { + homeService.getCharts(response,from,to,attrIds,width,height); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index e80d9fb6..ac98f154 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -2,15 +2,26 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.analyse.dto.LatestDto; import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.service.ZbxHost; +import com.zmops.zeus.driver.service.ZbxInitService; import com.zmops.zeus.driver.service.ZbxItem; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.methods.PostMethod; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; import java.util.ArrayList; @@ -37,6 +48,15 @@ public class HomeService { @Autowired HistoryService historyService; + @Autowired + private ZbxInitService zbxInitService; + + @Value("${forest.variables.zbxServerIp}") + private String zbxServerIp; + + @Value("${forest.variables.zbxServerPort}") + private String zbxServerPort; + private static String hostId = ""; private static Map ITEM_Map = new ConcurrentHashMap<>(5); @@ -91,4 +111,101 @@ private static String formatName(String name) { return name.substring(35, name.length() - 18); } + + /** + * 获取 数据图形展示 + * + * @param response http响应 + * @param from 开始时间 + * @param to 结束时间 + * @param attrIds 设备属性ID + * @param width 图表宽度 + * @param height 图表高度 + */ + public void getCharts(HttpServletResponse response, + String from, String to, + List attrIds, String width, String height) { + + String cookie = getCookie(); + List itemids = getItemIds(attrIds); + + HttpClient client = new HttpClient(); + PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort + + "/zabbix/chart.php?type=0&profileIdx=web.item.graph.filter&profileIdx2=36816&_=v14ede3k"); + + NameValuePair[] nameValuePairs = new NameValuePair[itemids.size() + 4]; + nameValuePairs[0] = new NameValuePair("from", from); + nameValuePairs[1] = new NameValuePair("to", to); + nameValuePairs[2] = new NameValuePair("width", width); + nameValuePairs[3] = new NameValuePair("height", height); + + for (int index = 0; index < itemids.size(); index++) { + nameValuePairs[4 + index] = new NameValuePair("itemids[" + index + "]", itemids.get(index)); + } + + postMethod.setRequestBody(nameValuePairs); + postMethod.setRequestHeader("Content_Type", "application/json-rpc"); + postMethod.setRequestHeader("Cookie", cookie); + + OutputStream out = null; + try { + client.executeMethod(postMethod); + InputStream responseBody = postMethod.getResponseBodyAsStream(); + response.setContentType("image/jpeg"); + + out = response.getOutputStream(); + out.write(toByteArray(responseBody)); + + out.flush(); + } catch (IOException ioException) { + ioException.printStackTrace(); + } finally { + try { + if (null != out) out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + } + + private static byte[] toByteArray(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + + byte[] buffer = new byte[4096]; + int n = 0; + + while (-1 != (n = input.read(buffer))) { + output.write(buffer, 0, n); + } + + return output.toByteArray(); + } + + + private List getItemIds(List attrIds) { + return new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(attrIds).findSingleAttributeList(); + } + + + private String getCookie() { + HttpClient client = new HttpClient(); + PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort + "/zabbix/index.php"); + + //TODO 使用了一个只读权限的访客用户 + NameValuePair namePair = new NameValuePair("name", "cookie"); + NameValuePair pwdPair = new NameValuePair("password", "cookie"); + NameValuePair autologinPair = new NameValuePair("autologin", "1"); + NameValuePair enterPair = new NameValuePair("enter", "Sign in"); + + postMethod.setRequestBody(new NameValuePair[]{namePair, pwdPair, autologinPair, enterPair}); + postMethod.setRequestHeader("Content_Type", "application/json"); + + try { + client.executeMethod(postMethod); + } catch (IOException ioException) { + ioException.printStackTrace(); + } + return postMethod.getResponseHeader("Set-Cookie").getValue(); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java index 8b2e2264..456da9f6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java @@ -12,7 +12,6 @@ import com.zmops.iot.core.util.HttpContext; import com.zmops.iot.core.util.RsaUtil; import com.zmops.iot.core.util.SaltUtil; -import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.domain.sys.SysUser; import com.zmops.iot.domain.sys.query.QSysUser; import com.zmops.iot.model.exception.ServiceException; @@ -22,25 +21,16 @@ import com.zmops.iot.web.log.factory.LogTaskFactory; import com.zmops.iot.web.sys.dto.LoginUserDto; import com.zmops.iot.web.sys.factory.UserFactory; -import com.zmops.zeus.driver.service.ZbxInitService; import com.zmops.zeus.driver.service.ZbxUser; import io.ebean.DB; import io.ebean.SqlRow; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.NameValuePair; -import org.apache.commons.httpclient.methods.PostMethod; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -59,15 +49,6 @@ public class AuthService { @Autowired private ZbxUser zbxUser; - @Autowired - private ZbxInitService zbxInitService; - - @Value("${forest.variables.zbxServerIp}") - private String zbxServerIp; - - @Value("${forest.variables.zbxServerPort}") - private String zbxServerPort; - /** * 用户名 和 密码 登陆 @@ -115,103 +96,6 @@ public LoginUserDto login(String username, String password) { return LoginUserDto.buildLoginUser(user, login(user)); } - /** - * 获取 数据图形展示 - * - * @param response http响应 - * @param from 开始时间 - * @param to 结束时间 - * @param attrIds 设备属性ID - * @param width 图表宽度 - * @param height 图表高度 - */ - public void getCharts(HttpServletResponse response, - String from, String to, - List attrIds, String width, String height) { - - String cookie = getCookie(); - List itemids = getItemIds(attrIds); - - HttpClient client = new HttpClient(); - PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort - + "/zabbix/chart.php?type=0&profileIdx=web.item.graph.filter&profileIdx2=36816&_=v14ede3k"); - - NameValuePair[] nameValuePairs = new NameValuePair[itemids.size() + 4]; - nameValuePairs[0] = new NameValuePair("from", from); - nameValuePairs[1] = new NameValuePair("to", to); - nameValuePairs[2] = new NameValuePair("width", width); - nameValuePairs[3] = new NameValuePair("height", height); - - for (int index = 0; index < itemids.size(); index++) { - nameValuePairs[4 + index] = new NameValuePair("itemids[" + index + "]", itemids.get(index)); - } - - postMethod.setRequestBody(nameValuePairs); - postMethod.setRequestHeader("Content_Type", "application/json-rpc"); - postMethod.setRequestHeader("Cookie", cookie); - - OutputStream out = null; - try { - client.executeMethod(postMethod); - InputStream responseBody = postMethod.getResponseBodyAsStream(); - response.setContentType("image/jpeg"); - - out = response.getOutputStream(); - out.write(toByteArray(responseBody)); - - out.flush(); - } catch (IOException ioException) { - ioException.printStackTrace(); - } finally { - try { - if (null != out) out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - } - - private static byte[] toByteArray(InputStream input) throws IOException { - ByteArrayOutputStream output = new ByteArrayOutputStream(); - - byte[] buffer = new byte[4096]; - int n = 0; - - while (-1 != (n = input.read(buffer))) { - output.write(buffer, 0, n); - } - - return output.toByteArray(); - } - - - private List getItemIds(List attrIds) { - return new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(attrIds).findSingleAttributeList(); - } - - - private String getCookie() { - HttpClient client = new HttpClient(); - PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort + "/zabbix/index.php"); - - //TODO 使用了一个只读权限的访客用户 - NameValuePair namePair = new NameValuePair("name", "cookie"); - NameValuePair pwdPair = new NameValuePair("password", "cookie"); - NameValuePair autologinPair = new NameValuePair("autologin", "1"); - NameValuePair enterPair = new NameValuePair("enter", "Sign in"); - - postMethod.setRequestBody(new NameValuePair[]{namePair, pwdPair, autologinPair, enterPair}); - postMethod.setRequestHeader("Content_Type", "application/json"); - - try { - client.executeMethod(postMethod); - } catch (IOException ioException) { - ioException.printStackTrace(); - } - return postMethod.getResponseHeader("Set-Cookie").getValue(); - } - /** * 用户名 登陆 * diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java index 09900828..0a168bec 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java @@ -62,13 +62,4 @@ public ResponseData logOut() { return new SuccessResponseData(); } - @RequestMapping("/getCharts") - public void getCookie(HttpServletResponse response, - @RequestParam("from") String from, - @RequestParam("to") String to, - @RequestParam("attrIds") List attrIds, - @RequestParam("width") String width, - @RequestParam("height") String height) { - authService.getCharts(response,from,to,attrIds,width,height); - } } From 1277978e60df982868de0b6cdce7e8b2deef7723 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 27 Aug 2021 11:35:22 +0800 Subject: [PATCH 057/763] =?UTF-8?q?=E5=8E=86=E5=8F=B2=E6=95=B0=E6=8D=AE=20?= =?UTF-8?q?=E6=97=A5=E6=9C=9F=E5=8F=82=E6=95=B0=E7=B1=BB=E5=9E=8B=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/zmops/iot/util/LocalDateTimeUtils.java | 7 ++++++- .../com/zmops/iot/web/analyse/dto/param/HistoryParam.java | 4 ++-- .../com/zmops/iot/web/analyse/service/HistoryService.java | 4 +++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java b/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java index 05052388..3fd7a68b 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java @@ -43,6 +43,11 @@ public static Long getSecondsByTime(LocalDateTime time) { return time.atZone(ZoneId.systemDefault()).toInstant().getEpochSecond(); } + // 获取指定日期的秒 + public static Long getSecondsByStr(String date) { + return getSecondsByTime(dateToStamp(date)); + } + /** * 根据秒获取时间 * @@ -178,6 +183,6 @@ public static LocalDateTime getThisWeekMonday() { } public static void main(String[] args) { - System.out.println(formatTime(dateToStamp("2021-08-18T14:25:38.059"))); + System.out.println(getSecondsByStr("2021-08-18T14:25:38.059")); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/HistoryParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/HistoryParam.java index d69cf720..eb6650c0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/HistoryParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/HistoryParam.java @@ -16,7 +16,7 @@ public class HistoryParam { private List attrIds; - private Long timeFrom; + private String timeFrom; - private Long timeTill; + private String timeTill; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java index 733431b1..cd277794 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java @@ -32,7 +32,9 @@ public class HistoryService { ZbxHistoryGet zbxHistoryGet; public List queryHistory(HistoryParam historyParam) { - return queryHistory(historyParam.getDeviceId(), historyParam.getAttrIds(), historyParam.getTimeFrom(), historyParam.getTimeTill()); + return queryHistory(historyParam.getDeviceId(), historyParam.getAttrIds(), + LocalDateTimeUtils.getSecondsByStr(historyParam.getTimeFrom()), + LocalDateTimeUtils.getSecondsByStr(historyParam.getTimeTill())); } public List queryHistory(Long deviceId, List attrIds, Long timeFrom, Long timeTill) { From 59cd975bf5aab84b205990bdfa10118c8dfbde90 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 27 Aug 2021 14:42:29 +0800 Subject: [PATCH 058/763] =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=8C=96=E6=9C=80?= =?UTF-8?q?=E6=96=B0=E6=95=B0=E6=8D=AE=20=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/zmops/iot/web/analyse/service/HistoryService.java | 1 + .../java/com/zmops/iot/web/analyse/service/HomeService.java | 3 ++- .../java/com/zmops/iot/web/analyse/service/LatestService.java | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java index cd277794..5574561c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java @@ -66,6 +66,7 @@ public List queryHistory(Long deviceId, List attrIds, Long time } latestDtos.forEach(latestDto -> { + latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Long.parseLong(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); if (null != itemIdMap.get(latestDto.getItemid())) { latestDto.setName(itemIdMap.get(latestDto.getItemid()).getName()); latestDto.setAttrId(itemIdMap.get(latestDto.getItemid()).getAttrId()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index ac98f154..1f232715 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -80,6 +80,7 @@ public Map> collectonRate() { 7, ChronoUnit.DAYS)), LocalDateTimeUtils.getSecondsByTime(LocalDateTime.now())); latestDtos.forEach(latestDto -> { + latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Long.parseLong(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); if (null != ITEM_Map.get(latestDto.getItemid())) { latestDto.setName(ITEM_Map.get(latestDto.getItemid())); } @@ -131,7 +132,7 @@ public void getCharts(HttpServletResponse response, HttpClient client = new HttpClient(); PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort - + "/zabbix/chart.php?type=0&profileIdx=web.item.graph.filter&profileIdx2=36816&_=v14ede3k"); + + "/zabbix/chart.php?type=0&profileIdx=web.item.graph.filter"); NameValuePair[] nameValuePairs = new NameValuePair[itemids.size() + 4]; nameValuePairs[0] = new NameValuePair("from", from); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java index 0d0580f5..fad5cf15 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java @@ -5,6 +5,7 @@ import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.analyse.dto.LatestDto; import com.zmops.iot.web.analyse.dto.param.LatestParam; @@ -67,6 +68,7 @@ public List qeuryLatest(Long deviceId, List attrIds) { } latestDtos.forEach(latestDto -> { + latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Long.parseLong(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); if (null != itemIdMap.get(latestDto.getItemid())) { latestDto.setName(itemIdMap.get(latestDto.getItemid()).getName()); latestDto.setAttrId(itemIdMap.get(latestDto.getItemid()).getAttrId()); From b2dada8ac6c615d1515e262e60ee0dbe6c1c4f9f Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 27 Aug 2021 15:15:38 +0800 Subject: [PATCH 059/763] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E6=9C=80=E6=96=B0?= =?UTF-8?q?=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analyse/controller/HistoryController.java | 7 +++--- .../analyse/controller/LatestController.java | 10 ++++---- .../web/analyse/dto/param/HistoryParam.java | 3 ++- .../web/analyse/dto/param/LatestParam.java | 3 ++- .../web/analyse/service/HistoryService.java | 8 ++++-- .../web/analyse/service/LatestService.java | 7 ++++-- .../controller/DeviceModelController.java | 2 +- .../device/service/DeviceModelService.java | 25 +++++++++++++++---- .../iot/web/product/dto/ProductAttrDto.java | 5 ++++ .../product/dto/param/ProductAttrParam.java | 2 +- 10 files changed, 51 insertions(+), 21 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HistoryController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HistoryController.java index b940dfc5..30bef652 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HistoryController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HistoryController.java @@ -1,6 +1,7 @@ package com.zmops.iot.web.analyse.controller; -import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.web.analyse.dto.LatestDto; import com.zmops.iot.web.analyse.dto.param.HistoryParam; import com.zmops.iot.web.analyse.service.HistoryService; import org.springframework.beans.factory.annotation.Autowired; @@ -22,7 +23,7 @@ public class HistoryController { HistoryService historyService; @RequestMapping("/query") - public ResponseData qeuryHistory(@Validated @RequestBody HistoryParam historyParam) { - return ResponseData.success(historyService.queryHistory(historyParam)); + public Pager qeuryHistory(@Validated @RequestBody HistoryParam historyParam) { + return historyService.queryHistory(historyParam); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java index e8f7aa1a..ac89cd01 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java @@ -1,18 +1,18 @@ package com.zmops.iot.web.analyse.controller; -import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.web.analyse.dto.LatestDto; import com.zmops.iot.web.analyse.dto.param.LatestParam; import com.zmops.iot.web.analyse.service.LatestService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** * @author yefei - * + *

* 最新数据 **/ @RestController @@ -23,7 +23,7 @@ public class LatestController { LatestService latestService; @RequestMapping("/query") - public ResponseData qeuryLatest(@Validated @RequestBody LatestParam latestParam){ - return ResponseData.success(latestService.qeuryLatest(latestParam)); + public Pager qeuryLatest(@Validated @RequestBody LatestParam latestParam) { + return latestService.qeuryLatest(latestParam); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/HistoryParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/HistoryParam.java index eb6650c0..40a215e7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/HistoryParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/HistoryParam.java @@ -1,5 +1,6 @@ package com.zmops.iot.web.analyse.dto.param; +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; import lombok.Data; import javax.validation.constraints.NotNull; @@ -9,7 +10,7 @@ * @author yefei **/ @Data -public class HistoryParam { +public class HistoryParam extends BaseQueryParam { @NotNull(message = "请选择一个设备再查询") private Long deviceId; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/LatestParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/LatestParam.java index 783c9341..bfbe7f79 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/LatestParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/LatestParam.java @@ -1,5 +1,6 @@ package com.zmops.iot.web.analyse.dto.param; +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; import lombok.Data; import javax.validation.constraints.NotNull; @@ -9,7 +10,7 @@ * @author yefei **/ @Data -public class LatestParam { +public class LatestParam extends BaseQueryParam{ @NotNull(message = "请选择一个设备再查询") private Long deviceId; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java index 5574561c..6d52b67e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java @@ -5,6 +5,7 @@ import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.analyse.dto.LatestDto; @@ -31,10 +32,13 @@ public class HistoryService { @Autowired ZbxHistoryGet zbxHistoryGet; - public List queryHistory(HistoryParam historyParam) { - return queryHistory(historyParam.getDeviceId(), historyParam.getAttrIds(), + public Pager queryHistory(HistoryParam historyParam) { + List latestDtos = queryHistory(historyParam.getDeviceId(), historyParam.getAttrIds(), LocalDateTimeUtils.getSecondsByStr(historyParam.getTimeFrom()), LocalDateTimeUtils.getSecondsByStr(historyParam.getTimeTill())); + List collect = latestDtos.stream().skip((historyParam.getMaxRow() - 1) * historyParam.getPage()) + .limit(historyParam.getMaxRow()).collect(Collectors.toList()); + return new Pager<>(collect,latestDtos.size()); } public List queryHistory(Long deviceId, List attrIds, Long timeFrom, Long timeTill) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java index fad5cf15..8f1df2cc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java @@ -5,6 +5,7 @@ import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.analyse.dto.LatestDto; @@ -36,9 +37,11 @@ public class LatestService { * @param latestParam * @return */ - public List qeuryLatest(LatestParam latestParam) { + public Pager qeuryLatest(LatestParam latestParam) { List latestDtos = qeuryLatest(latestParam.getDeviceId(), latestParam.getAttrIds()); - return latestDtos; + List collect = latestDtos.stream().skip((latestParam.getMaxRow() - 1) * latestParam.getPage()) + .limit(latestParam.getMaxRow()).collect(Collectors.toList()); + return new Pager<>(collect,latestDtos.size()); } public List qeuryLatest(Long deviceId, List attrIds) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java index b3c045c5..7d99b4ad 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java @@ -41,7 +41,7 @@ public class DeviceModelController { * @return ResponseData */ @RequestMapping("/getAttrTrapperByPage") - public Pager prodModelAttributeList(@RequestBody ProductAttrParam productAttr) { + public Pager prodModelAttributeList(@Validated(BaseEntity.Get.class) @RequestBody ProductAttrParam productAttr) { return deviceModelService.prodModelAttributeList(productAttr); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index f33d59b0..6fa5e7eb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -4,13 +4,13 @@ import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.query.QDevice; -import com.zmops.iot.domain.product.Product; import com.zmops.iot.domain.product.ProductAttribute; -import com.zmops.iot.domain.product.query.QProduct; import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.analyse.dto.LatestDto; +import com.zmops.iot.web.analyse.service.LatestService; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.iot.web.product.dto.ProductAttrDto; @@ -36,6 +36,9 @@ public class DeviceModelService { @Autowired private ZbxItem zbxItem; + @Autowired + LatestService latestService; + /** * 设备属性分页列表 * @@ -45,9 +48,8 @@ public class DeviceModelService { public Pager prodModelAttributeList(ProductAttrParam productAttr) { QProductAttribute qProductAttribute = new QProductAttribute(); - if (null != productAttr.getProdId()) { - qProductAttribute.productId.eq(productAttr.getProdId()); - } + qProductAttribute.productId.eq(productAttr.getProdId()); + if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { qProductAttribute.name.contains(productAttr.getAttrName()); } @@ -57,6 +59,19 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr List pagedList = qProductAttribute.setFirstRow((productAttr.getPage() - 1) * productAttr.getMaxRow()) .setMaxRows(productAttr.getMaxRow()).orderBy(" create_time desc").asDto(ProductAttrDto.class).findList(); + + //查询最新数据 + List attrIds = pagedList.parallelStream().map(ProductAttrDto::getAttrId).collect(Collectors.toList()); + List latestDtos = latestService.qeuryLatest(productAttr.getProdId(), attrIds); + Map map = latestDtos.parallelStream().collect(Collectors.toMap(LatestDto::getAttrId, o -> o)); + + pagedList.forEach(productAttrDto -> { + if (null != map.get(productAttrDto.getAttrId())) { + productAttrDto.setClock(map.get(productAttrDto.getAttrId()).getClock()); + productAttrDto.setValue(map.get(productAttrDto.getAttrId()).getValue()); + } + }); + int count = qProductAttribute.findCount(); return new Pager<>(pagedList, count); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java index 05c18ddb..36a4bad4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java @@ -64,4 +64,9 @@ public class ProductAttrDto implements BaseDto { @CachedValue(type = DicType.SysUserName) private Long updateUser; + private String clock; + + private String value; + + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java index 703fa86f..b205649a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java @@ -4,7 +4,6 @@ import com.zmops.iot.web.sys.dto.param.BaseQueryParam; import lombok.Data; -import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.util.List; @@ -15,6 +14,7 @@ @Data public class ProductAttrParam extends BaseQueryParam { + @NotNull(groups = BaseEntity.Get.class,message = "请选择一个设备再查询") private Long prodId; private String attrName; From 45e4505531728043bc2163063bd669a3bf2cd271 Mon Sep 17 00:00:00 2001 From: nantian Date: Sun, 29 Aug 2021 11:06:05 +0800 Subject: [PATCH 060/763] add license file. --- LICENSE | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..1acf21ee --- /dev/null +++ b/LICENSE @@ -0,0 +1,214 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +======================================================================= +zeus-iot Subcomponents: + +The zeus-iot project contains subcomponents with separate copyright +notices and license terms. Your use of the source code for the these +subcomponents is subject to the terms and conditions of the following +licenses. + +proto files from iot-server: https://github.com/apache/skywalking Apache 2.0 +mvnw files from https://github.com/takari/maven-wrapper Apache 2.0 + +proto files from zeus-common,zeus-core https://github.com/stylefeng/Guns LGPL-3.0 \ No newline at end of file From f2af8dbb4812c012caecd33e8a5c23c593963377 Mon Sep 17 00:00:00 2001 From: yefei Date: Sun, 29 Aug 2021 11:40:59 +0800 Subject: [PATCH 061/763] =?UTF-8?q?=E6=9C=80=E6=96=B0=E6=95=B0=E6=8D=AE=20?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E6=A0=BC=E5=BC=8F=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/zmops/iot/util/LocalDateTimeUtils.java | 10 ++++++++++ .../main/resources/api-json/problem/problem.get.ftl | 3 +++ .../zmops/iot/web/analyse/service/HistoryService.java | 2 +- .../zmops/iot/web/analyse/service/LatestService.java | 2 +- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java b/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java index 3fd7a68b..9b0b7905 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java @@ -141,6 +141,16 @@ public static String convertTimeToString(Long time, String pattern) { return LocalDateTimeUtils.formatTime(LocalDateTimeUtils.getLDTByMilliSeconds(time), pattern); } + /* + * 秒转 String + */ + public static String convertTimeToString(Integer time, String pattern) { + if (time == null) { + return null; + } + return LocalDateTimeUtils.formatTime(LocalDateTimeUtils.getLDTBySeconds(time), pattern); + } + public static LocalDateTime dateToStamp(String str) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { diff --git a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl index f23e3a92..9b14dd97 100644 --- a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl +++ b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl @@ -11,6 +11,9 @@ <#if hostId??> "hostids":"${hostId}" + "filter":{ + "source":"0" + }, "sortorder": "DESC" }, "auth": "${userAuth}", diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java index 6d52b67e..c9557591 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java @@ -70,7 +70,7 @@ public List queryHistory(Long deviceId, List attrIds, Long time } latestDtos.forEach(latestDto -> { - latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Long.parseLong(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); + latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); if (null != itemIdMap.get(latestDto.getItemid())) { latestDto.setName(itemIdMap.get(latestDto.getItemid()).getName()); latestDto.setAttrId(itemIdMap.get(latestDto.getItemid()).getAttrId()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java index 8f1df2cc..559cf528 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java @@ -71,7 +71,7 @@ public List qeuryLatest(Long deviceId, List attrIds) { } latestDtos.forEach(latestDto -> { - latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Long.parseLong(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); + latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); if (null != itemIdMap.get(latestDto.getItemid())) { latestDto.setName(itemIdMap.get(latestDto.getItemid()).getName()); latestDto.setAttrId(itemIdMap.get(latestDto.getItemid()).getAttrId()); From fa6b8ade8f6a8f6d4d18a225a73c8a90f1df9203 Mon Sep 17 00:00:00 2001 From: nantian Date: Sun, 29 Aug 2021 17:41:47 +0800 Subject: [PATCH 062/763] =?UTF-8?q?=E7=99=BB=E9=99=86=20=E5=AF=86=E7=A0=81?= =?UTF-8?q?=E5=8A=A0=E5=AF=86=E6=96=B9=E5=BC=8F=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/zmops/iot/core/util/RsaUtil.java | 21 ----------- .../com/zmops/iot/web/auth/AuthService.java | 7 +++- .../iot/web/sys/service/SysUserService.java | 37 ++++++++++++------- 3 files changed, 28 insertions(+), 37 deletions(-) diff --git a/zeus-core/src/main/java/com/zmops/iot/core/util/RsaUtil.java b/zeus-core/src/main/java/com/zmops/iot/core/util/RsaUtil.java index 984f6d64..7d17670a 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/util/RsaUtil.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/util/RsaUtil.java @@ -17,27 +17,6 @@ */ public class RsaUtil { - //公钥为:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwgmYk5tASrKzbjPwYffD9eAt1WRjBL2oN8x0FSff0YBrwdaozUFX0uU6z/gkfcjHwdvEJ7PJAt3ELNZ2xyOcUyeLbS0ds7Yx4pMT7kOYGod4IQDRqjXx0NZIe+f8cijYp9Myg37gL1ptXKV7mWX5cOUfP0g9qI0XLqf3dPSJ77wIDAQAB - - private static final String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALCCZiTm0BKsrNuM/Bh98P14C3VZGMEvag3zHQVJ9/RgGvB1qjNQVfS5TrP" + - "+CR9yMfB28Qns8kC3cQs1nbHI5xTJ4ttLR2ztjHikxPuQ5gah3ghANGqNfHQ1kh75/xyKNin0zKDfuAvWm1cpXuZZflw5R8/SD2ojRcup/d09InvvAgMBAAECgYEAmxWXhai" + - "+/Ql2v1i6TxKo4SvOdYaY93QfbK5Eu1boY3Dleo0HxBo7y8/dVMxJW7XMJwl6c0wa9b23ty+epIxuayDWFiN3xSmQH0l/7H8MMxPY3AA/6U9AoyTUeSoUGRx6W+Lvv12jiVVGiL" + - "ZNaI6Ucm8irRunPSNdc2YcP5kptgECQQDmJel83TiOICj2TSiC5paAQTouhD31BHOgC5tMetXfmt/im1DGRPmocLqXO2uythZcvrhFGohgk7V6IQWAQ2lvAkEAxFYQSfcJcl2S8JTET" + - "td15JSUsfO1WCD+3Ik3q1v7jAxc8TubrCPlMZutmDzcalme150Nfh+siEZXyqjGQB/VgQJAGeYkS0/dwGiwE1+Fco2eXBp7AKcTDdKNbHJB7K5aCQq1rRuLUHSMn77n0IL4UKkbBR7VP7" + - "mHpU6Z+n9izhdH8wJAZMRXL98edhgYpml0J5Ll6x9nAb43QLgOllnGvKhE/qgJu7YAO+VgaImiGxSBfAPrRnZQyn6vKnIP9O+ScK7mAQJAd1zJBY/1ezjD9GvgC6mdG3b1xoBlBVvTxK5T" + - "0v5jybWe8W/H6gLEprWhzM0LgwA9CsLWe1KXmOcAGeyKwb02CA=="; - - /** - * 私钥解密 - */ - public static String decryptPwd(String password) throws Exception { - if (ToolUtil.isEmpty(password)) { - throw new IllegalArgumentException("密码为空!"); - } else { - return decrypt(password, privateKey); - } - } - /** * RSA私钥解密 */ diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java index 456da9f6..defb0ed9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java @@ -24,6 +24,8 @@ import com.zmops.zeus.driver.service.ZbxUser; import io.ebean.DB; import io.ebean.SqlRow; +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,6 +33,7 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -73,8 +76,8 @@ public LoginUserDto login(String username, String password) { //验证账号密码是否正确 try { - password = RsaUtil.decryptPwd(password); - } catch (Exception e) { + password = new String(Hex.decodeHex(password)); + } catch (DecoderException e) { throw new AuthException(AuthExceptionEnum.USERNAME_PWD_ERROR); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java index 0670274f..d565d0a9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java @@ -6,7 +6,6 @@ import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.core.auth.exception.enums.AuthExceptionEnum; import com.zmops.iot.core.auth.model.LoginUser; -import com.zmops.iot.core.util.RsaUtil; import com.zmops.iot.core.util.SaltUtil; import com.zmops.iot.domain.sys.SysUser; import com.zmops.iot.domain.sys.query.QSysRole; @@ -22,6 +21,7 @@ import com.zmops.zeus.driver.service.ZbxUser; import io.ebean.DB; import io.ebean.DtoQuery; +import org.apache.commons.codec.binary.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; @@ -32,7 +32,6 @@ import java.util.stream.Collectors; import static com.zmops.iot.web.init.DeviceSatusScriptInit.GLOBAL_ADMIN_ROLE_CODE; -import static com.zmops.iot.web.init.DeviceSatusScriptInit.GLOBAL_HOST_GROUP_CODE; /** * @author yefei @@ -57,8 +56,11 @@ public class SysUserService implements CommandLineRunner { */ public Pager userList(UserParam userParam) { QSysUser qSysUser = new QSysUser(); - StringBuilder sql = new StringBuilder("select u.account, u.name, u.email, u.phone, u.role_id,r.name role_name," + - "u.user_group_id,g.group_name user_group_name, u.status, u.create_user, u.update_user, u.create_time, u.update_time, u.user_id FROM sys_user u"); + StringBuilder sql = new StringBuilder( + "select u.account, u.name, u.email, u.phone, u.role_id,r.name role_name," + + "u.user_group_id,g.group_name user_group_name, u.status, u.create_user, " + + "u.update_user, u.create_time, u.update_time, u.user_id FROM sys_user u"); + sql.append(" LEFT JOIN sys_role r ON r.role_id = u.role_id "); sql.append(" LEFT JOIN sys_user_group g ON g.user_group_id = u.user_group_id "); @@ -74,7 +76,9 @@ public Pager userList(UserParam userParam) { dto.setParameter("%" + userParam.getName() + "%"); } List pagedList = dto.setFirstRow((userParam.getPage() - 1) * userParam.getMaxRow()).setMaxRows(userParam.getMaxRow()).findList(); - int count = qSysUser.findCount(); + + int count = qSysUser.findCount(); + return new Pager<>(pagedList, count); } @@ -92,7 +96,7 @@ public SysUser createUser(UserDto user) { String password = user.getPassword(); String decryptPwd = ""; try { - password = RsaUtil.decryptPwd(password); + password = new String(Hex.decodeHex(password)); decryptPwd = password; } catch (Exception e) { throw new ServiceException(BizExceptionEnum.PWD_DECRYPT_ERR); @@ -102,13 +106,18 @@ public SysUser createUser(UserDto user) { password = SaltUtil.md5Encrypt(password, salt); SysUser newUser = UserFactory.createUser(user, password, salt); + //取对应的ZBX用户组ID - String usrZbxId = sysUserGroupService.getZabUsrGrpId(user.getUserGroupId()); - JSONObject result = JSONObject.parseObject(zbxUser.userAdd(user.getAccount(), decryptPwd, usrZbxId, ConstantsContext.getConstntsMap().get(GLOBAL_ADMIN_ROLE_CODE).toString())); - JSONArray userids = result.getJSONArray("userids"); + String usrZbxId = sysUserGroupService.getZabUsrGrpId(user.getUserGroupId()); + JSONObject result = JSONObject.parseObject( + zbxUser.userAdd(user.getAccount(), decryptPwd, usrZbxId, ConstantsContext.getConstntsMap().get(GLOBAL_ADMIN_ROLE_CODE).toString())); + + JSONArray userids = result.getJSONArray("userids"); newUser.setZbxId(String.valueOf(userids.get(0))); + DB.save(newUser); updateUserCache(); + return newUser; } @@ -170,7 +179,7 @@ private void checkByAccount(String account) { /** * 检查所选角色是否存在 * - * @param roleId + * @param roleId 角色ID */ private void checkByRole(Long roleId) { int count = new QSysRole().roleId.eq(roleId).findCount(); @@ -182,8 +191,8 @@ private void checkByRole(Long roleId) { /** * 修改密码 * - * @param oldPassword - * @param newPassword + * @param oldPassword String + * @param newPassword String */ public void changePwd(String oldPassword, String newPassword) { LoginUser loginUser = LoginContextHolder.getContext().getUser(); @@ -194,8 +203,8 @@ public void changePwd(String oldPassword, String newPassword) { SysUser user = new QSysUser().userId.eq(loginUser.getId()).findOne(); try { - oldPassword = RsaUtil.decryptPwd(oldPassword); - newPassword = RsaUtil.decryptPwd(newPassword); + oldPassword = new String(Hex.decodeHex(oldPassword)); + newPassword = new String(Hex.decodeHex(newPassword)); } catch (Exception e) { throw new ServiceException(BizExceptionEnum.PWD_DECRYPT_ERR); } From 1d488a61629655fb0b68732e939ba90a382c3741 Mon Sep 17 00:00:00 2001 From: yefei Date: Sun, 29 Aug 2021 18:10:53 +0800 Subject: [PATCH 063/763] =?UTF-8?q?=20=E7=BC=93=E5=AD=98=E8=8E=B7=E5=8F=96?= =?UTF-8?q?Zbx=20Cookie?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zmops/iot/util/LocalDateTimeUtils.java | 2 +- .../iot/web/analyse/service/HomeService.java | 25 ++++++++++++++----- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java b/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java index 9b0b7905..d274cdc4 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java @@ -124,7 +124,7 @@ public static LocalDateTime getDayEnd(LocalDateTime time) { /* * 时间戳转 LocalDateTime */ - public static LocalDateTime convertDateToLocalDateTime(Long time) { + public static LocalDateTime convertDateToLocalDateTime(Integer time) { if (time == null) { return null; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index 1f232715..586304fe 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -61,6 +61,10 @@ public class HomeService { private static Map ITEM_Map = new ConcurrentHashMap<>(5); + private static String COOKIE = ""; + + private static LocalDateTime COOKIE_TIME; + //Zbx 指标取数速率 key private static final String KEY = "zabbix[wcache,values"; @@ -80,7 +84,7 @@ public Map> collectonRate() { 7, ChronoUnit.DAYS)), LocalDateTimeUtils.getSecondsByTime(LocalDateTime.now())); latestDtos.forEach(latestDto -> { - latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Long.parseLong(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); + latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); if (null != ITEM_Map.get(latestDto.getItemid())) { latestDto.setName(ITEM_Map.get(latestDto.getItemid())); } @@ -109,6 +113,9 @@ private Map getItemMap() { } private static String formatName(String name) { + if (name.length() < 53) { + return "avg"; + } return name.substring(35, name.length() - 18); } @@ -126,8 +133,11 @@ private static String formatName(String name) { public void getCharts(HttpServletResponse response, String from, String to, List attrIds, String width, String height) { + if (ToolUtil.isEmpty(COOKIE) || + LocalDateTimeUtils.betweenTwoTime(COOKIE_TIME, LocalDateTime.now(), ChronoUnit.DAYS) >= 30) { + getCookie(); + } - String cookie = getCookie(); List itemids = getItemIds(attrIds); HttpClient client = new HttpClient(); @@ -146,7 +156,7 @@ public void getCharts(HttpServletResponse response, postMethod.setRequestBody(nameValuePairs); postMethod.setRequestHeader("Content_Type", "application/json-rpc"); - postMethod.setRequestHeader("Cookie", cookie); + postMethod.setRequestHeader("Cookie", COOKIE); OutputStream out = null; try { @@ -162,7 +172,9 @@ public void getCharts(HttpServletResponse response, ioException.printStackTrace(); } finally { try { - if (null != out) out.close(); + if (null != out) { + out.close(); + } } catch (IOException e) { e.printStackTrace(); } @@ -189,7 +201,7 @@ private List getItemIds(List attrIds) { } - private String getCookie() { + private void getCookie() { HttpClient client = new HttpClient(); PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort + "/zabbix/index.php"); @@ -207,6 +219,7 @@ private String getCookie() { } catch (IOException ioException) { ioException.printStackTrace(); } - return postMethod.getResponseHeader("Set-Cookie").getValue(); + COOKIE = postMethod.getResponseHeader("Set-Cookie").getValue(); + COOKIE_TIME = LocalDateTime.now(); } } From 357a0e9c2a00dbdf407715183369fa04525b6827 Mon Sep 17 00:00:00 2001 From: yefei Date: Sun, 29 Aug 2021 18:11:31 +0800 Subject: [PATCH 064/763] =?UTF-8?q?=E8=AE=BE=E5=A4=87=20=E7=BB=A7=E6=89=BF?= =?UTF-8?q?=E6=9D=A5=E7=9A=84=E5=B1=9E=E6=80=A7=20=20=E5=8F=AA=E8=83=BD?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=A4=87=E6=B3=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/device/service/DeviceModelService.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index 6fa5e7eb..60857751 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -147,15 +147,18 @@ public void createProductAttr(ProductAttr productAttr, String zbxId) { } private ProductAttribute buildProdAttribute(ProductAttribute prodAttribute, ProductAttr productAttr) { + if(null == prodAttribute.getTemplateId()){ + prodAttribute.setName(productAttr.getAttrName()); + prodAttribute.setKey(productAttr.getKey()); + prodAttribute.setSource(productAttr.getSource()); + prodAttribute.setUnits(productAttr.getUnits()); + prodAttribute.setDepAttrId(productAttr.getDepAttrId()); + prodAttribute.setValueType(productAttr.getValueType()); + } prodAttribute.setProductId(productAttr.getProductId()); - prodAttribute.setName(productAttr.getAttrName()); - prodAttribute.setKey(productAttr.getKey()); - prodAttribute.setSource(productAttr.getSource()); - prodAttribute.setUnits(productAttr.getUnits()); prodAttribute.setRemark(productAttr.getRemark()); - prodAttribute.setValueType(productAttr.getValueType()); prodAttribute.setAttrId(productAttr.getAttrId()); - prodAttribute.setDepAttrId(productAttr.getDepAttrId()); + return prodAttribute; } From d422c940f84a932b1a692fd6b28e0c43973bcef8 Mon Sep 17 00:00:00 2001 From: yefei Date: Sun, 29 Aug 2021 18:13:17 +0800 Subject: [PATCH 065/763] =?UTF-8?q?=E4=BA=A7=E5=93=81=20=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/domain/product/ProductService.java | 27 ++++ .../domain/product/ProductServiceParam.java | 25 +++ .../web/exception/enums/BizExceptionEnum.java | 6 + .../controller/ProductServiceController.java | 50 ++++++ .../web/product/dto/ProductServiceDto.java | 37 +++++ .../product/dto/param/ProductSvcParam.java | 15 ++ .../product/service/ProductSvcService.java | 150 ++++++++++++++++++ 7 files changed, 310 insertions(+) create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceParam.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductSvcParam.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java new file mode 100644 index 00000000..43a784ba --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java @@ -0,0 +1,27 @@ +package com.zmops.iot.domain.product; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "product_service") +public class ProductService { + @Id + private Long id; + + private String name; + private String mark; + private String remark; + private Long sid; + private Long templateId; + private Integer async; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceParam.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceParam.java new file mode 100644 index 00000000..cb9ed60e --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceParam.java @@ -0,0 +1,25 @@ +package com.zmops.iot.domain.product; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "product_service_param") +public class ProductServiceParam { + + @Id + private Long id; + private Long serviceId; + private String name; + private String key; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index 7a74c043..eb8e96df 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -145,6 +145,12 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { DEVICE_EXISTS(1501, "设备名称已存在"), DEVICE_NOT_EXISTS(1502, "设备不存在"), + /** + * 服务相关 + */ + SERVICE_EXISTS(1601,"服务已存在"), + SERVICE_NOT_EXISTS(1602,"服务不存在"), + /** * 租户相关的异常 */ diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java index e5c244c1..e00e27af 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java @@ -1,5 +1,12 @@ package com.zmops.iot.web.product.controller; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.product.dto.ProductServiceDto; +import com.zmops.iot.web.product.dto.param.ProductSvcParam; +import com.zmops.iot.web.product.service.ProductSvcService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -13,5 +20,48 @@ @RequestMapping("/product/service") public class ProductServiceController { + @Autowired + ProductSvcService productSvcService; + /** + * 服务分页列表 + */ + @RequestMapping("/getServiceByPage") + public Pager getServiceByPage(@RequestBody ProductSvcParam productSvcParam) { + return productSvcService.getServiceByPage(productSvcParam); + } + + /** + * 服务列表 + */ + @RequestMapping("/list") + public ResponseData list(@RequestBody ProductSvcParam productSvcParam) { + return ResponseData.success(productSvcService.list(productSvcParam)); + } + + + /** + * 服务创建 + */ + @RequestMapping("/create") + public ResponseData create(@RequestBody ProductServiceDto productServiceDto) { + return ResponseData.success(productSvcService.create(productServiceDto)); + } + + /** + * 服务修改 + */ + @RequestMapping("/update") + public ResponseData update(@RequestBody ProductServiceDto productServiceDto) { + return ResponseData.success(productSvcService.update(productServiceDto)); + } + + /** + * 服务删除 + */ + @RequestMapping("/delete") + public ResponseData delete(@RequestBody ProductServiceDto productServiceDto) { + productSvcService.delete(productServiceDto.getIds()); + return ResponseData.success(productServiceDto.getIds()); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java new file mode 100644 index 00000000..7358d72f --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java @@ -0,0 +1,37 @@ +package com.zmops.iot.web.product.dto; + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.product.ProductServiceParam; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class ProductServiceDto { + + @NotNull(groups = BaseEntity.Update.class) + private Long id; + + @NotBlank(groups = BaseEntity.Create.class) + private String name; + + private String mark; + + private String remark; + + @NotNull(groups = BaseEntity.Create.class) + private Long sid; + + private Integer async; + + private List productServiceParamList; + + + @NotNull(groups = BaseEntity.Delete.class) + private List ids; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductSvcParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductSvcParam.java new file mode 100644 index 00000000..e8751156 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductSvcParam.java @@ -0,0 +1,15 @@ +package com.zmops.iot.web.product.dto.param; + +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class ProductSvcParam extends BaseQueryParam { + + private String name; + + private String mark; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java new file mode 100644 index 00000000..519b85a2 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -0,0 +1,150 @@ +package com.zmops.iot.web.product.service; + +import com.zmops.iot.domain.product.ProductService; +import com.zmops.iot.domain.product.ProductServiceParam; +import com.zmops.iot.domain.product.query.QProductService; +import com.zmops.iot.domain.product.query.QProductServiceParam; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.product.dto.ProductServiceDto; +import com.zmops.iot.web.product.dto.param.ProductSvcParam; +import io.ebean.DB; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 产品 物模型 服务 + **/ +@Service +public class ProductSvcService { + + /** + * 服务分页列表 + * + * @param productSvcParam + * @return + */ + public Pager getServiceByPage(ProductSvcParam productSvcParam) { + QProductService qProductService = new QProductService(); + if (ToolUtil.isNotEmpty(productSvcParam.getName())) { + qProductService.name.contains(productSvcParam.getName()); + } + if (ToolUtil.isNotEmpty(productSvcParam.getMark())) { + qProductService.mark.contains(productSvcParam.getMark()); + } + qProductService.orderBy(" id desc"); + List productServiceDtoList = qProductService.setFirstRow((productSvcParam.getPage() - 1) * productSvcParam.getMaxRow()) + .setMaxRows(productSvcParam.getMaxRow()).asDto(ProductServiceDto.class).findList(); + + if (ToolUtil.isEmpty(productServiceDtoList)) { + return new Pager<>(productServiceDtoList, 0); + } + //查询关联的参数 + List sids = productServiceDtoList.parallelStream().map(ProductServiceDto::getId).collect(Collectors.toList()); + List serviceParamList = new QProductServiceParam().serviceId.in(sids).findList(); + Map> map = serviceParamList.parallelStream().collect(Collectors.groupingBy(ProductServiceParam::getServiceId)); + productServiceDtoList.forEach(productServiceDto -> { + if (null != map.get(productServiceDto.getId())) { + productServiceDto.setProductServiceParamList(map.get(productServiceDto.getId())); + } + }); + return new Pager<>(productServiceDtoList, qProductService.findCount()); + } + + /** + * 服务列表 + * + * @param productSvcParam + * @return + */ + public List list(ProductSvcParam productSvcParam) { + QProductService qProdService = new QProductService(); + if (ToolUtil.isNotEmpty(productSvcParam.getName())) { + qProdService.name.contains(productSvcParam.getName()); + } + if (ToolUtil.isNotEmpty(productSvcParam.getMark())) { + qProdService.mark.contains(productSvcParam.getMark()); + } + qProdService.orderBy(" id desc"); + return qProdService.findList(); + } + + /** + * 服务创建 + * + * @param productServiceDto + * @return + */ + @Transactional(rollbackFor = Exception.class) + public Object create(ProductServiceDto productServiceDto) { + int count = new QProductService().name.eq(productServiceDto.getName()).sid.eq(productServiceDto.getSid()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.SERVICE_EXISTS); + } + ProductService productService = new ProductService(); + ToolUtil.copyProperties(productServiceDto, productService); + DB.save(productService); + Long serviceId = productService.getId(); + productServiceDto.setId(serviceId); + + if (ToolUtil.isNotEmpty(productServiceDto.getProductServiceParamList())) { + for (ProductServiceParam productServiceParam : productServiceDto.getProductServiceParamList()) { + productServiceParam.setServiceId(serviceId); + } + DB.saveAll(productServiceDto.getProductServiceParamList()); + } + + //TODO 同步到设备 + return productServiceDto; + } + + /** + * 服务修改 + * + * @param productServiceDto + * @return + */ + public Object update(ProductServiceDto productServiceDto) { + int count = new QProductService().name.eq(productServiceDto.getName()).sid.eq(productServiceDto.getSid()) + .id.ne(productServiceDto.getId()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.SERVICE_EXISTS); + } + ProductService productService = new ProductService(); + ToolUtil.copyProperties(productServiceDto, productService); + DB.save(productService); + + new QProductServiceParam().serviceId.eq(productServiceDto.getId()).delete(); + if (ToolUtil.isNotEmpty(productServiceDto.getProductServiceParamList())) { + for (ProductServiceParam productServiceParam : productServiceDto.getProductServiceParamList()) { + productServiceParam.setServiceId(productServiceDto.getId()); + } + DB.saveAll(productServiceDto.getProductServiceParamList()); + } + //TODO 同步到设备 + + return productServiceDto; + } + + /** + * 服务删除 + * + * @param ids + * @return + */ + public void delete(List ids) { + + new QProductServiceParam().serviceId.in(ids).delete(); + new QProductService().id.in(ids).delete(); + + //TODO 同步到设备 + } +} From 71031fcdbf7ee48f41b635d5e527b5959f1db284 Mon Sep 17 00:00:00 2001 From: nantian Date: Sun, 29 Aug 2021 23:26:56 +0800 Subject: [PATCH 066/763] add submodule camel-zabbix-agent --- .gitmodules | 3 +++ camel-zabbix-agent | 1 + 2 files changed, 4 insertions(+) create mode 160000 camel-zabbix-agent diff --git a/.gitmodules b/.gitmodules index 3b721b2e..568e7a2d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "zeus-iot-ui"] path = zeus-iot-ui url = https://github.com/zmops/zeus-iot-ui.git +[submodule "camel-zabbix-agent"] + path = camel-zabbix-agent + url = https://github.com/zmops/camel-zabbix-agent.git diff --git a/camel-zabbix-agent b/camel-zabbix-agent new file mode 160000 index 00000000..848bad39 --- /dev/null +++ b/camel-zabbix-agent @@ -0,0 +1 @@ +Subproject commit 848bad39d68dc056f6704d491e8e619ce3d765d6 From 1922fd92761312fda32042689e5d322f4fa77ba1 Mon Sep 17 00:00:00 2001 From: nantian Date: Sun, 29 Aug 2021 23:52:44 +0800 Subject: [PATCH 067/763] update submodule. --- camel-zabbix-agent | 2 +- zeus-iot-ui | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/camel-zabbix-agent b/camel-zabbix-agent index 848bad39..a05c6036 160000 --- a/camel-zabbix-agent +++ b/camel-zabbix-agent @@ -1 +1 @@ -Subproject commit 848bad39d68dc056f6704d491e8e619ce3d765d6 +Subproject commit a05c6036a8823557892eb5d44816cd3cc63a5730 diff --git a/zeus-iot-ui b/zeus-iot-ui index 94648c2c..f0d461d2 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit 94648c2c643dd611574752c6c8a2f47bba2b45e0 +Subproject commit f0d461d2c5f5009de3f5566d2552ae3400795c90 From 6eb0cd5770962c8f39365254143133dd889f0743 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 30 Aug 2021 09:32:00 +0800 Subject: [PATCH 068/763] =?UTF-8?q?=E5=8E=BB=E6=8E=89=E6=97=A0=E6=95=88?= =?UTF-8?q?=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/zmops/iot/web/auth/AuthService.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java index defb0ed9..236a8599 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java @@ -10,7 +10,6 @@ import com.zmops.iot.core.auth.jwt.payload.JwtPayLoad; import com.zmops.iot.core.auth.model.LoginUser; import com.zmops.iot.core.util.HttpContext; -import com.zmops.iot.core.util.RsaUtil; import com.zmops.iot.core.util.SaltUtil; import com.zmops.iot.domain.sys.SysUser; import com.zmops.iot.domain.sys.query.QSysUser; @@ -33,7 +32,6 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.List; From 8c5660043e54131ae48d889dccc4b4246f3853a8 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 30 Aug 2021 11:10:32 +0800 Subject: [PATCH 069/763] =?UTF-8?q?=E4=BA=A7=E5=93=81=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ProductServiceController.java | 8 ++- .../web/product/dto/ProductServiceDto.java | 2 + .../product/service/ProductSvcService.java | 35 +++++++++- .../service/work/SaveProdSvcWorker.java | 61 +++++++++++++++++ .../service/work/UpdateProdSvcWorker.java | 65 +++++++++++++++++++ 5 files changed, 165 insertions(+), 6 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java index e00e27af..c5729675 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java @@ -1,11 +1,13 @@ package com.zmops.iot.web.product.controller; +import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.web.product.dto.ProductServiceDto; import com.zmops.iot.web.product.dto.param.ProductSvcParam; import com.zmops.iot.web.product.service.ProductSvcService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -44,7 +46,7 @@ public ResponseData list(@RequestBody ProductSvcParam productSvcParam) { * 服务创建 */ @RequestMapping("/create") - public ResponseData create(@RequestBody ProductServiceDto productServiceDto) { + public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody ProductServiceDto productServiceDto) { return ResponseData.success(productSvcService.create(productServiceDto)); } @@ -52,7 +54,7 @@ public ResponseData create(@RequestBody ProductServiceDto productServiceDto) { * 服务修改 */ @RequestMapping("/update") - public ResponseData update(@RequestBody ProductServiceDto productServiceDto) { + public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody ProductServiceDto productServiceDto) { return ResponseData.success(productSvcService.update(productServiceDto)); } @@ -60,7 +62,7 @@ public ResponseData update(@RequestBody ProductServiceDto productServiceDto) { * 服务删除 */ @RequestMapping("/delete") - public ResponseData delete(@RequestBody ProductServiceDto productServiceDto) { + public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody ProductServiceDto productServiceDto) { productSvcService.delete(productServiceDto.getIds()); return ResponseData.success(productServiceDto.getIds()); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java index 7358d72f..9cf5d799 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java @@ -29,6 +29,8 @@ public class ProductServiceDto { private Integer async; + private Long templateId; + private List productServiceParamList; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index 519b85a2..53854db3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -1,5 +1,7 @@ package com.zmops.iot.web.product.service; +import com.zmops.iot.async.executor.Async; +import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductService; import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.product.query.QProductService; @@ -8,9 +10,14 @@ import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.iot.web.product.dto.ProductServiceDto; import com.zmops.iot.web.product.dto.param.ProductSvcParam; +import com.zmops.iot.web.product.service.work.SaveProdSvcWorker; +import com.zmops.iot.web.product.service.work.UpdateProdSvcWorker; import io.ebean.DB; +import org.checkerframework.checker.units.qual.A; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -26,6 +33,12 @@ @Service public class ProductSvcService { + @Autowired + SaveProdSvcWorker saveProdSvcWorker; + + @Autowired + UpdateProdSvcWorker updateProdSvcWorker; + /** * 服务分页列表 * @@ -102,7 +115,15 @@ public Object create(ProductServiceDto productServiceDto) { DB.saveAll(productServiceDto.getProductServiceParamList()); } - //TODO 同步到设备 + //同步到设备 + WorkerWrapper saveProdAttrWork = WorkerWrapper.builder().worker(saveProdSvcWorker).build(); + + try { + Async.work(100, saveProdAttrWork).awaitFinish(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return productServiceDto; } @@ -120,7 +141,7 @@ public Object update(ProductServiceDto productServiceDto) { } ProductService productService = new ProductService(); ToolUtil.copyProperties(productServiceDto, productService); - DB.save(productService); + DB.update(productService); new QProductServiceParam().serviceId.eq(productServiceDto.getId()).delete(); if (ToolUtil.isNotEmpty(productServiceDto.getProductServiceParamList())) { @@ -129,7 +150,15 @@ public Object update(ProductServiceDto productServiceDto) { } DB.saveAll(productServiceDto.getProductServiceParamList()); } - //TODO 同步到设备 + + //同步到设备 + WorkerWrapper updateProdSvcWork = WorkerWrapper.builder().worker(updateProdSvcWorker).build(); + + try { + Async.work(100, updateProdSvcWork).awaitFinish(); + } catch (InterruptedException e) { + e.printStackTrace(); + } return productServiceDto; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java new file mode 100644 index 00000000..3b2b3108 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java @@ -0,0 +1,61 @@ +package com.zmops.iot.web.product.service.work; + + +import com.zmops.iot.async.callback.IWorker; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductService; +import com.zmops.iot.domain.product.ProductServiceParam; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.product.dto.ProductServiceDto; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author yefei + *

+ * 产品服务创建 同步到设备 步骤 + */ +@Slf4j +@Component +public class SaveProdSvcWorker implements IWorker { + + + @Override + public Boolean action(ProductServiceDto productServiceDto, Map> map) { + log.debug("处理产品 新增服务 同步到设备工作…………"); + + Long prodId = productServiceDto.getSid(); + + List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(prodId).findSingleAttributeList(); + + for (Long deviceId : deviceIds) { + ProductService productService = new ProductService(); + ToolUtil.copyProperties(productServiceDto, productService); + productService.setSid(deviceId); + productService.setTemplateId(productServiceDto.getId()); + DB.save(productService); + + if (ToolUtil.isNotEmpty(productServiceDto.getProductServiceParamList())) { + for (ProductServiceParam productServiceParam : productServiceDto.getProductServiceParamList()) { + productServiceParam.setServiceId(productService.getId()); + } + DB.saveAll(productServiceDto.getProductServiceParamList()); + } + } + + return true; + } + + + @Override + public Boolean defaultValue() { + return true; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java new file mode 100644 index 00000000..844611ea --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java @@ -0,0 +1,65 @@ +package com.zmops.iot.web.product.service.work; + + +import com.zmops.iot.async.callback.IWorker; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.product.ProductService; +import com.zmops.iot.domain.product.ProductServiceParam; +import com.zmops.iot.domain.product.query.QProductService; +import com.zmops.iot.domain.product.query.QProductServiceParam; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.product.dto.ProductServiceDto; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 产品服务修改 同步到设备 步骤 + */ +@Slf4j +@Component +public class UpdateProdSvcWorker implements IWorker { + + + @Override + public Boolean action(ProductServiceDto productServiceDto, Map> map) { + log.debug("处理产品服务修改 同步到设备工作…………"); + + Long Id = productServiceDto.getId(); + + List list = new QProductService().templateId.eq(Id).findList(); + + for (ProductService productService : list) { + productService.setName(productServiceDto.getName()); + productService.setMark(productServiceDto.getMark()); + productService.setAsync(productServiceDto.getAsync()); + } + DB.updateAll(list); + + //处理服务参数 + List ids = list.parallelStream().map(ProductService::getId).collect(Collectors.toList()); + new QProductServiceParam().serviceId.in(ids).delete(); + if (ToolUtil.isNotEmpty(productServiceDto.getProductServiceParamList())) { + for (Long id : ids) { + for (ProductServiceParam productServiceParam : productServiceDto.getProductServiceParamList()) { + productServiceParam.setServiceId(id); + } + } + DB.saveAll(productServiceDto.getProductServiceParamList()); + } + return true; + } + + + @Override + public Boolean defaultValue() { + return true; + } + +} From 5093a0961108fdf5fdeb12878ecfc2e0887351a8 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 30 Aug 2021 14:06:43 +0800 Subject: [PATCH 070/763] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E6=96=B0=E5=A2=9E=E5=90=8C=E6=AD=A5=E5=88=B0?= =?UTF-8?q?=E8=AE=BE=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zmops/zeus/driver/entity/ZbxItemInfo.java | 8 +++ .../zmops/zeus/driver/service/ZbxItem.java | 12 +++- .../resources/api-json/item/item.name.get.ftl | 25 ++++++++ .../product/service/ProductModelService.java | 13 ++-- .../service/work/AsyncAttrZbxIdWorker.java | 61 +++++++++++++++++++ .../service/work/SaveProdAttrWorker.java | 1 + 6 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 zeus-driver/src/main/resources/api-json/item/item.name.get.ftl create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxItemInfo.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxItemInfo.java index 506d53f4..7119727e 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxItemInfo.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxItemInfo.java @@ -25,4 +25,12 @@ public class ZbxItemInfo { private String valuemapid; private String interfaceid; + + private HostInfo hosts; + + @Data + public static class HostInfo { + private String hostid; + private String host; + } } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java index 828ba821..0e135524 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java @@ -91,7 +91,7 @@ String updateTrapperItem(@ParamName("itemid") String itemid, String getItemInfo(@ParamName("itemId") String itemId, @ParamName("hostid") String hostid); /** - * 根据item name 获取 ITEM 信息 + * 根据item key 获取 ITEM 信息 * * @param key key * @return String @@ -99,4 +99,14 @@ String updateTrapperItem(@ParamName("itemid") String itemid, @Post @JsonPath("/item/item.get") String getItemList(@ParamName("key") String key, @ParamName("hostid") String hostid); + + /** + * 根据item name 获取 ITEM 信息 + * + * @param name name + * @return String + */ + @Post + @JsonPath("/item/name/item.get") + String getItemListByName(@ParamName("name") String name); } diff --git a/zeus-driver/src/main/resources/api-json/item/item.name.get.ftl b/zeus-driver/src/main/resources/api-json/item/item.name.get.ftl new file mode 100644 index 00000000..dd978aec --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/item/item.name.get.ftl @@ -0,0 +1,25 @@ +{ + "jsonrpc": "2.0", + "method": "item.get", + "params": { + "selectHosts":["host"], + "search":{ + <#if name??> + "name":"${name}" + + }, + "output": [ + "itemid", + "hostid", + "name", + "key_", + "status", + "value_type", + "units", + "valuemapid", + "interfaceid" + ] + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index e054f9ea..7f84686f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -6,26 +6,23 @@ import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.Product; import com.zmops.iot.domain.product.ProductAttribute; -import com.zmops.iot.domain.product.ProductType; import com.zmops.iot.domain.product.query.QProduct; import com.zmops.iot.domain.product.query.QProductAttribute; -import com.zmops.iot.domain.product.query.QProductType; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; -import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.iot.web.product.dto.ProductAttrDto; import com.zmops.iot.web.product.dto.ProductTag; import com.zmops.iot.web.product.dto.param.ProductAttrParam; +import com.zmops.iot.web.product.service.work.AsyncAttrZbxIdWorker; import com.zmops.iot.web.product.service.work.SaveProdAttrWorker; import com.zmops.iot.web.product.service.work.UpdateAttributeWorker; import com.zmops.zeus.driver.entity.ZbxProcessingStep; import com.zmops.zeus.driver.service.ZbxItem; import io.ebean.DB; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Service; import java.util.*; @@ -43,6 +40,9 @@ public class ProductModelService { @Autowired SaveProdAttrWorker saveProdAttrWorker; + @Autowired + AsyncAttrZbxIdWorker asyncAttrZbxIdWorker; + @Autowired UpdateAttributeWorker updateProdAttrWorker; @@ -138,8 +138,11 @@ public void createProductAttr(ProductAttr productAttr, String zbxId) { buildProdAttribute(productAttribute, productAttr); productAttribute.setZbxId(zbxId); productAttribute.save(); + productAttr.setAttrId(productAttribute.getAttrId()); + - WorkerWrapper saveProdAttrWork = WorkerWrapper.builder().worker(saveProdAttrWorker).build(); + WorkerWrapper asyncAttrZbxIdWork = WorkerWrapper.builder().worker(asyncAttrZbxIdWorker).build(); + WorkerWrapper saveProdAttrWork = WorkerWrapper.builder().worker(saveProdAttrWorker).nextOf(asyncAttrZbxIdWork).build(); try { Async.work(100, saveProdAttrWork).awaitFinish(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java new file mode 100644 index 00000000..4a8ba468 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java @@ -0,0 +1,61 @@ +package com.zmops.iot.web.product.service.work; + + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.async.callback.IWorker; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.product.ProductAttribute; +import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.product.dto.ProductAttr; +import com.zmops.zeus.driver.entity.ZbxItemInfo; +import com.zmops.zeus.driver.service.ZbxItem; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 更新设备属性中ZBXID + */ +@Slf4j +@Component +public class AsyncAttrZbxIdWorker implements IWorker { + + @Autowired + ZbxItem zbxItem; + + @Override + public Boolean action(ProductAttr productAttr, Map> map) { + log.debug("处理Attr zbx回填工作……"); + Long attrId = productAttr.getAttrId(); + + //根据name 取出监控项 + List itemInfos = JSONObject.parseArray(zbxItem.getItemListByName(attrId + ""), ZbxItemInfo.class); + if (ToolUtil.isEmpty(itemInfos)) { + return true; + } + + Map itemMap = itemInfos.parallelStream().collect(Collectors.toMap(o -> o.getHosts().getHost(), o -> o)); + //取出继承的属性 并塞入对应的 itemId + List productAttributeList = new QProductAttribute().templateId.eq(attrId).findList(); + for (ProductAttribute productAttribute : productAttributeList) { + productAttribute.setZbxId(itemMap.get(productAttribute.getTemplateId() + "").getItemid()); + } + + DB.updateAll(productAttributeList); + return true; + } + + @Override + public Boolean defaultValue() { + return true; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java index 386ba9a4..6ca0678f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java @@ -41,6 +41,7 @@ public Boolean action(ProductAttr productAttr, Map> ToolUtil.copyProperties(productAttr, productAttrbute); productAttrbute.setAttrId(IdUtil.getSnowflake().nextId()); productAttrbute.setProductId(deviceId); + productAttrbute.setTemplateId(productAttr.getAttrId()); productAttributeList.add(productAttrbute); } DB.saveAll(productAttributeList); From 8e799fae6517159aa852672fe5c4dde86be21015 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 30 Aug 2021 17:13:49 +0800 Subject: [PATCH 071/763] =?UTF-8?q?=E4=BA=A7=E5=93=81=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/zmops/iot/domain/product/ProductService.java | 12 ++++++------ .../com/zmops/zeus/driver/entity/ZbxItemInfo.java | 4 +++- .../java/com/zmops/zeus/driver/service/ZbxItem.java | 2 +- .../main/resources/api-json/item/item.name.get.ftl | 6 +++--- .../iot/web/device/service/DeviceModelService.java | 4 ++-- .../zmops/iot/web/device/service/DeviceService.java | 2 +- .../iot/web/product/service/ProductModelService.java | 11 ++++++----- .../product/service/work/AsyncAttrZbxIdWorker.java | 4 ++-- .../web/product/service/work/SaveProdAttrWorker.java | 1 + 9 files changed, 25 insertions(+), 21 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java index 43a784ba..b8482312 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java @@ -18,10 +18,10 @@ public class ProductService { @Id private Long id; - private String name; - private String mark; - private String remark; - private Long sid; - private Long templateId; - private Integer async; + private String name; + private String mark; + private String remark; + private Long sid; + private Long templateId; + private String async; } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxItemInfo.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxItemInfo.java index 7119727e..24104465 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxItemInfo.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxItemInfo.java @@ -2,6 +2,8 @@ import lombok.Data; +import java.util.List; + /** * @author nantian created at 2021/8/10 17:52 */ @@ -26,7 +28,7 @@ public class ZbxItemInfo { private String interfaceid; - private HostInfo hosts; + private List hosts; @Data public static class HostInfo { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java index 0e135524..87c51b7c 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java @@ -107,6 +107,6 @@ String updateTrapperItem(@ParamName("itemid") String itemid, * @return String */ @Post - @JsonPath("/item/name/item.get") + @JsonPath("/item/item.name.get") String getItemListByName(@ParamName("name") String name); } diff --git a/zeus-driver/src/main/resources/api-json/item/item.name.get.ftl b/zeus-driver/src/main/resources/api-json/item/item.name.get.ftl index dd978aec..91cc12fe 100644 --- a/zeus-driver/src/main/resources/api-json/item/item.name.get.ftl +++ b/zeus-driver/src/main/resources/api-json/item/item.name.get.ftl @@ -2,12 +2,12 @@ "jsonrpc": "2.0", "method": "item.get", "params": { - "selectHosts":["host"], + "selectHosts":["host"], + <#if name??> "search":{ - <#if name??> "name":"${name}" - }, + "output": [ "itemid", "hostid", diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index 60857751..dd2c6f34 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -63,7 +63,7 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr //查询最新数据 List attrIds = pagedList.parallelStream().map(ProductAttrDto::getAttrId).collect(Collectors.toList()); List latestDtos = latestService.qeuryLatest(productAttr.getProdId(), attrIds); - Map map = latestDtos.parallelStream().collect(Collectors.toMap(LatestDto::getAttrId, o -> o)); + Map map = latestDtos.parallelStream().distinct().collect(Collectors.toMap(LatestDto::getAttrId, o -> o, (a, b) -> b)); pagedList.forEach(productAttrDto -> { if (null != map.get(productAttrDto.getAttrId())) { @@ -147,7 +147,7 @@ public void createProductAttr(ProductAttr productAttr, String zbxId) { } private ProductAttribute buildProdAttribute(ProductAttribute prodAttribute, ProductAttr productAttr) { - if(null == prodAttribute.getTemplateId()){ + if (null == prodAttribute.getTemplateId()) { prodAttribute.setName(productAttr.getAttrName()); prodAttribute.setKey(productAttr.getKey()); prodAttribute.setSource(productAttr.getSource()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index c9723df1..27b453e9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -196,7 +196,7 @@ public Long create(DeviceDto deviceDto) { .build(); WorkerWrapper updateAttrZbxIdWork = WorkerWrapper.builder().id("updateAttrZbxIdWork") - .worker(updateAttrZbxIdWorker) + .worker(updateAttrZbxIdWorker).param(deviceDto) .build(); WorkerWrapper updateDeviceZbxIdWork = WorkerWrapper.builder().id("updateDeviceZbxIdWork") diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index 7f84686f..2c815afb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -138,15 +138,16 @@ public void createProductAttr(ProductAttr productAttr, String zbxId) { buildProdAttribute(productAttribute, productAttr); productAttribute.setZbxId(zbxId); productAttribute.save(); - productAttr.setAttrId(productAttribute.getAttrId()); - WorkerWrapper asyncAttrZbxIdWork = WorkerWrapper.builder().worker(asyncAttrZbxIdWorker).build(); - WorkerWrapper saveProdAttrWork = WorkerWrapper.builder().worker(saveProdAttrWorker).nextOf(asyncAttrZbxIdWork).build(); + WorkerWrapper asyncAttrZbxIdWork = WorkerWrapper.builder() + .worker(asyncAttrZbxIdWorker).param(productAttr).build(); + WorkerWrapper saveProdAttrWork = WorkerWrapper.builder() + .worker(saveProdAttrWorker).param(productAttr).nextOf(asyncAttrZbxIdWork).build(); try { - Async.work(100, saveProdAttrWork).awaitFinish(); - } catch (InterruptedException e) { + Async.work(10000, saveProdAttrWork).awaitFinish(); + } catch (Exception e) { e.printStackTrace(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java index 4a8ba468..ded8c4b2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java @@ -42,11 +42,11 @@ public Boolean action(ProductAttr productAttr, Map> return true; } - Map itemMap = itemInfos.parallelStream().collect(Collectors.toMap(o -> o.getHosts().getHost(), o -> o)); + Map itemMap = itemInfos.parallelStream().collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), o -> o)); //取出继承的属性 并塞入对应的 itemId List productAttributeList = new QProductAttribute().templateId.eq(attrId).findList(); for (ProductAttribute productAttribute : productAttributeList) { - productAttribute.setZbxId(itemMap.get(productAttribute.getTemplateId() + "").getItemid()); + productAttribute.setZbxId(itemMap.get(productAttribute.getProductId()+"").getItemid()); } DB.updateAll(productAttributeList); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java index 6ca0678f..fd5aa388 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java @@ -40,6 +40,7 @@ public Boolean action(ProductAttr productAttr, Map> ProductAttribute productAttrbute = new ProductAttribute(); ToolUtil.copyProperties(productAttr, productAttrbute); productAttrbute.setAttrId(IdUtil.getSnowflake().nextId()); + productAttrbute.setName(productAttr.getAttrName()); productAttrbute.setProductId(deviceId); productAttrbute.setTemplateId(productAttr.getAttrId()); productAttributeList.add(productAttrbute); From 0bd0e83b0e7ccc25d6c1a3d004af0861ffcbfe36 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 30 Aug 2021 17:16:00 +0800 Subject: [PATCH 072/763] =?UTF-8?q?=E4=BA=A7=E5=93=81=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/zmops/iot/web/product/dto/ProductServiceDto.java | 7 ++++++- .../zmops/iot/web/product/dto/param/ProductSvcParam.java | 2 ++ .../zmops/iot/web/product/service/ProductSvcService.java | 3 +++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java index 9cf5d799..6f612570 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java @@ -1,7 +1,10 @@ package com.zmops.iot.web.product.dto; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.product.ProductServiceParam; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; import lombok.Data; import javax.validation.constraints.NotBlank; @@ -12,6 +15,7 @@ * @author yefei **/ @Data +@JsonSerialize(using = CachedValueFilter.class) public class ProductServiceDto { @NotNull(groups = BaseEntity.Update.class) @@ -27,7 +31,8 @@ public class ProductServiceDto { @NotNull(groups = BaseEntity.Create.class) private Long sid; - private Integer async; + @CachedValue(value = "EXECUTE_TYPE") + private String async; private Long templateId; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductSvcParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductSvcParam.java index e8751156..07b3db1e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductSvcParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductSvcParam.java @@ -12,4 +12,6 @@ public class ProductSvcParam extends BaseQueryParam { private String name; private String mark; + + private Long prodId; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index 53854db3..34df78b8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -53,6 +53,9 @@ public Pager getServiceByPage(ProductSvcParam productSvcParam if (ToolUtil.isNotEmpty(productSvcParam.getMark())) { qProductService.mark.contains(productSvcParam.getMark()); } + if (null != productSvcParam.getProdId()) { + qProductService.sid.eq(productSvcParam.getProdId()); + } qProductService.orderBy(" id desc"); List productServiceDtoList = qProductService.setFirstRow((productSvcParam.getPage() - 1) * productSvcParam.getMaxRow()) .setMaxRows(productSvcParam.getMaxRow()).asDto(ProductServiceDto.class).findList(); From ec19c7b29f32f15054026a5c425f0e7a1630fe48 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 30 Aug 2021 17:28:53 +0800 Subject: [PATCH 073/763] =?UTF-8?q?=E4=BA=A7=E5=93=81=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/zmops/iot/web/product/dto/ProductServiceDto.java | 3 ++- .../zmops/iot/web/product/service/ProductSvcService.java | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java index 6f612570..48d4bf0a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java @@ -1,6 +1,7 @@ package com.zmops.iot.web.product.dto; import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.domain.BaseDto; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.model.cache.filter.CachedValue; @@ -16,7 +17,7 @@ **/ @Data @JsonSerialize(using = CachedValueFilter.class) -public class ProductServiceDto { +public class ProductServiceDto implements BaseDto { @NotNull(groups = BaseEntity.Update.class) private Long id; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index 34df78b8..43a677d4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -10,13 +10,11 @@ import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.exception.enums.BizExceptionEnum; -import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.iot.web.product.dto.ProductServiceDto; import com.zmops.iot.web.product.dto.param.ProductSvcParam; import com.zmops.iot.web.product.service.work.SaveProdSvcWorker; import com.zmops.iot.web.product.service.work.UpdateProdSvcWorker; import io.ebean.DB; -import org.checkerframework.checker.units.qual.A; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -100,7 +98,7 @@ public List list(ProductSvcParam productSvcParam) { * @return */ @Transactional(rollbackFor = Exception.class) - public Object create(ProductServiceDto productServiceDto) { + public ProductServiceDto create(ProductServiceDto productServiceDto) { int count = new QProductService().name.eq(productServiceDto.getName()).sid.eq(productServiceDto.getSid()).findCount(); if (count > 0) { throw new ServiceException(BizExceptionEnum.SERVICE_EXISTS); @@ -136,7 +134,7 @@ public Object create(ProductServiceDto productServiceDto) { * @param productServiceDto * @return */ - public Object update(ProductServiceDto productServiceDto) { + public ProductServiceDto update(ProductServiceDto productServiceDto) { int count = new QProductService().name.eq(productServiceDto.getName()).sid.eq(productServiceDto.getSid()) .id.ne(productServiceDto.getId()).findCount(); if (count > 0) { From 99141d57a9b57d1d4dd6cf7ce88ef35ed0e82ee2 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 31 Aug 2021 09:53:39 +0800 Subject: [PATCH 074/763] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/web/analyse/controller/HomeController.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java index 71fbf561..bd819e39 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java @@ -12,7 +12,7 @@ /** * @author yefei - * + *

* 全局概览 **/ @RestController @@ -22,8 +22,13 @@ public class HomeController { @Autowired HomeService homeService; + /** + * 服务器取数速率 + * + * @return + */ @RequestMapping("/collectonRate") - public ResponseData collectonRate(){ + public ResponseData collectonRate() { return ResponseData.success(homeService.collectonRate()); } @@ -44,6 +49,6 @@ public void getCookie(HttpServletResponse response, @RequestParam("attrIds") List attrIds, @RequestParam("width") String width, @RequestParam("height") String height) { - homeService.getCharts(response,from,to,attrIds,width,height); + homeService.getCharts(response, from, to, attrIds, width, height); } } From 47f35845658ff543a8dbcf8fa65c4be1e85f173a Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 31 Aug 2021 10:58:26 +0800 Subject: [PATCH 075/763] =?UTF-8?q?=E5=B1=9E=E6=80=A7=E6=9D=A5=E6=BA=90?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E7=BF=BB=E8=AF=91=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java index 36a4bad4..68f66a47 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java @@ -32,7 +32,7 @@ public class ProductAttrDto implements BaseDto { @CachedValue(value = "UNITS") private String units; - @CachedValue(value = "DEVICE_TYPE") + @CachedValue(value = "ATTR_TYPE") private String source; private String remark; From 14c9132e7e8ea4bfff491166ddbb723fc6c9a5f5 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 31 Aug 2021 11:17:50 +0800 Subject: [PATCH 076/763] =?UTF-8?q?=E7=8A=B6=E6=80=81=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/zmops/iot/web/device/dto/DeviceDto.java | 1 + .../main/java/com/zmops/iot/web/sys/dto/UserDto.java | 8 +++++++- .../java/com/zmops/iot/web/sys/dto/UserGroupDto.java | 11 +++++++---- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java index 8d3a40c3..7b5ff41d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java @@ -35,6 +35,7 @@ public class DeviceDto implements BaseDto { @NotEmpty(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private List deviceGroupIds; + @CachedValue(value = "STATUS") private String status; @CachedValue(value = "DEVICE_TYPE") diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java index dd07100a..8b39ddec 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java @@ -15,7 +15,11 @@ */ package com.zmops.iot.web.sys.dto; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.domain.BaseDto; import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; import lombok.Data; import javax.validation.constraints.NotBlank; @@ -27,7 +31,8 @@ * @author stylefeng */ @Data -public class UserDto { +@JsonSerialize(using = CachedValueFilter.class) +public class UserDto implements BaseDto { @NotNull(groups = BaseEntity.Update.class) private Long userId; @@ -48,6 +53,7 @@ public class UserDto { @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private Long userGroupId; + @CachedValue(value = "STATUS") private String status; @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java index 06b45535..c48da827 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java @@ -15,10 +15,11 @@ */ package com.zmops.iot.web.sys.dto; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.domain.BaseDto; import com.zmops.iot.domain.BaseEntity; -import io.ebean.annotation.WhenModified; -import io.ebean.annotation.WhoCreated; -import io.ebean.annotation.WhoModified; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; import lombok.Data; import javax.validation.constraints.NotBlank; @@ -32,7 +33,8 @@ * @author yefei */ @Data -public class UserGroupDto { +@JsonSerialize(using = CachedValueFilter.class) +public class UserGroupDto implements BaseDto { @NotNull(groups = BaseEntity.Update.class) private Long userGroupId; @@ -40,6 +42,7 @@ public class UserGroupDto { @NotBlank private String groupName; + @CachedValue(value = "STATUS") private String status; private String remark; From 13f1130bf114716e59bd48663147b5ac2cc77ccc Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 1 Sep 2021 01:15:37 +0800 Subject: [PATCH 077/763] update zabbix agent submodule. --- camel-zabbix-agent | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/camel-zabbix-agent b/camel-zabbix-agent index a05c6036..167deeab 160000 --- a/camel-zabbix-agent +++ b/camel-zabbix-agent @@ -1 +1 @@ -Subproject commit a05c6036a8823557892eb5d44816cd3cc63a5730 +Subproject commit 167deeabf366e045629fd0b950b09ee643ac6541 From 809abdfff3a853ae2fa2d0665ff04157ec3b4562 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Wed, 1 Sep 2021 11:15:49 +0800 Subject: [PATCH 078/763] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/quick-install.sh | 152 +++++++++++++++++++++--------------------- 1 file changed, 76 insertions(+), 76 deletions(-) diff --git a/docs/quick-install.sh b/docs/quick-install.sh index 608776b1..fc3eb7f4 100755 --- a/docs/quick-install.sh +++ b/docs/quick-install.sh @@ -97,43 +97,43 @@ function AddInstallRepo() { sed -i '/mirrors.aliyuncs.com/,/mirrors.cloud.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo ### Postgresql && timescaleDB tee /etc/yum.repos.d/postgresql_timescaledb.repo </dev/null - [epel] - name=Extra Packages for Enterprise Linux 7 - \$basearch - baseurl=http://mirrors.aliyun.com/epel/7/\$basearch - failovermethod=priority - enabled=1 - gpgcheck=0 - - [timescale_timescaledb] - name=timescale_timescaledb - baseurl=https://packagecloud.io/timescale/timescaledb/el/$(rpm -E %{rhel})/\$basearch - gpgcheck=0 - enabled=1 - - [centos-sclo-rh] - name=CentOS-7 - SCLo rh - baseurl=https://mirrors.aliyun.com/centos/7/sclo/\$basearch/rh/ - gpgcheck=0 - enabled=1 - - [pgdg-common] - name=PostgreSQL common RPMs for RHEL/CentOS \$releasever - \$basearch - baseurl=https://download.postgresql.org/pub/repos/yum/common/redhat/rhel-\$releasever-\$basearch - enabled=1 - gpgcheck=0 - - - [pgdg13] - name=PostgreSQL 13 for RHEL/CentOS \$releasever - \$basearch - baseurl=https://download.postgresql.org/pub/repos/yum/13/redhat/rhel-\$releasever-\$basearch - enabled=1 - gpgcheck=0 - - [pgdg12] - name=PostgreSQL 12 for RHEL/CentOS \$releasever - \$basearch - baseurl=https://download.postgresql.org/pub/repos/yum/12/redhat/rhel-\$releasever-\$basearch - enabled=1 - gpgcheck=0 +[epel] +name=Extra Packages for Enterprise Linux 7 - \$basearch +baseurl=http://mirrors.aliyun.com/epel/7/\$basearch +failovermethod=priority +enabled=1 +gpgcheck=0 + +[timescale_timescaledb] +name=timescale_timescaledb +baseurl=https://packagecloud.io/timescale/timescaledb/el/$(rpm -E %{rhel})/\$basearch +gpgcheck=0 +enabled=1 + +[centos-sclo-rh] +name=CentOS-7 - SCLo rh +baseurl=https://mirrors.aliyun.com/centos/7/sclo/\$basearch/rh/ +gpgcheck=0 +enabled=1 + +[pgdg-common] +name=PostgreSQL common RPMs for RHEL/CentOS \$releasever - \$basearch +baseurl=https://download.postgresql.org/pub/repos/yum/common/redhat/rhel-\$releasever-\$basearch +enabled=1 +gpgcheck=0 + + +[pgdg13] +name=PostgreSQL 13 for RHEL/CentOS \$releasever - \$basearch +baseurl=https://download.postgresql.org/pub/repos/yum/13/redhat/rhel-\$releasever-\$basearch +enabled=1 +gpgcheck=0 + +[pgdg12] +name=PostgreSQL 12 for RHEL/CentOS \$releasever - \$basearch +baseurl=https://download.postgresql.org/pub/repos/yum/12/redhat/rhel-\$releasever-\$basearch +enabled=1 +gpgcheck=0 EOL echo "配置安装 YUM 源 。。。" @@ -241,48 +241,48 @@ function ZbxInstall() { sed -i 's/^# DBPassword=/DBPassword=zabbix/g' $ZABBIX_HOME/etc/zabbix_server.conf ### 配置启动文件 tee /usr/lib/systemd/system/zabbix-server.service </dev/null - [Unit] - Description=Zabbix Server - - After=network.target - After=postgresql-13.service - - [Service] - Environment="CONFFILE=$ZABBIX_HOME/etc/zabbix_server.conf" - EnvironmentFile=-/etc/default/zabbix-server - Type=forking - Restart=on-failure - PIDFile=/tmp/zabbix_server.pid - KillMode=control-group - ExecStart=$ZABBIX_HOME/sbin/zabbix_server -c \$CONFFILE - ExecStop=/bin/kill -SIGTERM \$MAINPID - RestartSec=10s - TimeoutSec=0 - - [Install] - WantedBy=multi-user.target +[Unit] +Description=Zabbix Server + +After=network.target +After=postgresql-13.service + +[Service] +Environment="CONFFILE=$ZABBIX_HOME/etc/zabbix_server.conf" +EnvironmentFile=-/etc/default/zabbix-server +Type=forking +Restart=on-failure +PIDFile=/tmp/zabbix_server.pid +KillMode=control-group +ExecStart=$ZABBIX_HOME/sbin/zabbix_server -c \$CONFFILE +ExecStop=/bin/kill -SIGTERM \$MAINPID +RestartSec=10s +TimeoutSec=0 + +[Install] +WantedBy=multi-user.target EOL tee /usr/lib/systemd/system/zabbix-agent.service </dev/null - [Unit] - Description=Zabbix Agent - After=network.target - - [Service] - Environment="CONFFILE=$ZABBIX_HOME/etc/zabbix_agentd.conf" - EnvironmentFile=-/etc/default/zabbix-agent - Type=forking - Restart=on-failure - PIDFile=/tmp/zabbix_agentd.pid - KillMode=control-group - ExecStart=$ZABBIX_HOME/sbin/zabbix_agentd -c \$CONFFILE - ExecStop=/bin/kill -SIGTERM \$MAINPID - RestartSec=10s - User=zabbix - Group=zabbix - - [Install] - WantedBy=multi-user.target +[Unit] +Description=Zabbix Agent +After=network.target + +[Service] +Environment="CONFFILE=$ZABBIX_HOME/etc/zabbix_agentd.conf" +EnvironmentFile=-/etc/default/zabbix-agent +Type=forking +Restart=on-failure +PIDFile=/tmp/zabbix_agentd.pid +KillMode=control-group +ExecStart=$ZABBIX_HOME/sbin/zabbix_agentd -c \$CONFFILE +ExecStop=/bin/kill -SIGTERM \$MAINPID +RestartSec=10s +User=zabbix +Group=zabbix + +[Install] +WantedBy=multi-user.target EOL systemctl daemon-reload From bfdb89184a7350b9d8d9ac4472c36dcd296395fe Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 1 Sep 2021 17:49:16 +0800 Subject: [PATCH 079/763] library-module class description edit. --- .../zmops/zeus/iot/server/library/module/BootstrapFlow.java | 3 +++ .../com/zmops/zeus/iot/server/library/module/ModuleDefine.java | 3 +++ .../zmops/zeus/iot/server/library/module/ModuleManager.java | 3 +++ 3 files changed, 9 insertions(+) diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/BootstrapFlow.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/BootstrapFlow.java index dbea1943..2ce3d1ab 100644 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/BootstrapFlow.java +++ b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/BootstrapFlow.java @@ -27,6 +27,9 @@ import java.util.List; import java.util.Map; +/** + * 模块化依赖管理,被依赖模块要优先启动 + */ class BootstrapFlow { private static final Logger LOGGER = LoggerFactory.getLogger(BootstrapFlow.class); diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefine.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefine.java index ebe29a22..3c414354 100644 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefine.java +++ b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefine.java @@ -28,6 +28,9 @@ /** * A module definition. + * 模块定义,需要被继承,实现模块化定义 + *

+ * TODO 基于页面的配置,实现模块化动态的加载 */ public abstract class ModuleDefine implements ModuleProviderHolder { diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleManager.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleManager.java index 53c67145..cc5f86b3 100644 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleManager.java +++ b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleManager.java @@ -22,6 +22,9 @@ /** * The ModuleManager takes charge of all {@link ModuleDefine}s in collector. + *

+ * 实现模块之间的 Service 发布调用 + * TODO 使用 google guice @Inject 实现 */ public class ModuleManager implements ModuleDefineHolder { private boolean isInPrepareStage = true; From 288f618e2db206cc33f2936a1c1a89be0733bd8d Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 2 Sep 2021 10:57:18 +0800 Subject: [PATCH 080/763] add http endpoint for zabbix config reader --- .../src/main/resources/application.yml | 1 + .../iot/server/core/CoreModuleConfig.java | 1 + .../iot/server/core/CoreModuleProvider.java | 2 + .../core/servlet/ZabbixConfigHandler.java | 53 +++++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/ZabbixConfigHandler.java diff --git a/iot-server/server-bootstrap/src/main/resources/application.yml b/iot-server/server-bootstrap/src/main/resources/application.yml index 23685945..96589234 100644 --- a/iot-server/server-bootstrap/src/main/resources/application.yml +++ b/iot-server/server-bootstrap/src/main/resources/application.yml @@ -41,6 +41,7 @@ core: restAcceptorPriorityDelta: ${ZS_CORE_REST_JETTY_DELTA:0} restAcceptQueueSize: ${ZS_CORE_REST_JETTY_QUEUE_SIZE:0} httpMaxRequestHeaderSize: ${ZS_CORE_HTTP_MAX_REQUEST_HEADER_SIZE:8192} + zabbixConfigPath: ${ZS_CORE_ZABBIX_CONFIG_PATH:E:\\zabbix_server.conf} # 健康检查 health-checker: diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java index 2a7255dc..2e000f1b 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java @@ -26,6 +26,7 @@ public class CoreModuleConfig extends ModuleConfig { private long restIdleTimeOut = 30000; private int restAcceptorPriorityDelta = 0; private int restAcceptQueueSize = 0; + private String zabbixConfigPath = "/etc/zabbix/zabbix_server.conf"; // yum or apt install default location. /** diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java index 150d061a..bba9c582 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java @@ -9,6 +9,7 @@ import com.zmops.zeus.iot.server.core.server.JettyHandlerRegisterImpl; import com.zmops.zeus.iot.server.core.servlet.DeviceTriggerActionHandler; import com.zmops.zeus.iot.server.core.servlet.HttpItemTrapperHandler; +import com.zmops.zeus.iot.server.core.servlet.ZabbixConfigHandler; import com.zmops.zeus.iot.server.eventbus.core.EventControllerFactory; import com.zmops.zeus.iot.server.eventbus.thread.ThreadPoolFactory; import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadCustomization; @@ -106,6 +107,7 @@ public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleSta JettyHandlerRegister service = getManager().find(CoreModule.NAME).provider().getService(JettyHandlerRegister.class); service.addHandler(new HttpItemTrapperHandler()); service.addHandler(new DeviceTriggerActionHandler(getManager())); + service.addHandler(new ZabbixConfigHandler(moduleConfig.getZabbixConfigPath())); // ### 可以自定义添加 Action 的动作异步处理,指定 ID diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/ZabbixConfigHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/ZabbixConfigHandler.java new file mode 100644 index 00000000..02f000be --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/ZabbixConfigHandler.java @@ -0,0 +1,53 @@ +package com.zmops.zeus.iot.server.core.servlet; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.zmops.zeus.iot.server.library.server.jetty.ArgumentsParseException; +import com.zmops.zeus.iot.server.library.server.jetty.JettyJsonHandler; + +import javax.servlet.http.HttpServletRequest; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +/** + * @author nantian created at 2021/9/2 10:20 + */ +public class ZabbixConfigHandler extends JettyJsonHandler { + + private final String zabbixConfigPath; + private final Gson gson = new Gson(); + + public ZabbixConfigHandler(String zabbixConfigPath) { + this.zabbixConfigPath = zabbixConfigPath; + } + + @Override + public String pathSpec() { + return "/zabbix/config"; + } + + @Override + protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException, IOException { + + Properties prop = new Properties(); + InputStream in = new FileInputStream(zabbixConfigPath); + + prop.load(in); + in.close(); + + Set confNames = prop.stringPropertyNames(); + + Map confMap = new HashMap<>(); + confNames.forEach(i -> { + confMap.put(i, prop.getProperty(i)); + }); + + return gson.fromJson(gson.toJson(confMap), JsonObject.class); + } +} From e5b818739fc6d12bbeb21fe8b0e007b2b2b4ad64 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 2 Sep 2021 11:09:59 +0800 Subject: [PATCH 081/763] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.yml | 1 - .../iot/server/core/CoreModuleConfig.java | 53 -------- .../iot/server/core/CoreModuleProvider.java | 125 ------------------ .../core/servlet/ZabbixConfigHandler.java | 53 -------- 4 files changed, 232 deletions(-) delete mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java delete mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java delete mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/ZabbixConfigHandler.java diff --git a/iot-server/server-bootstrap/src/main/resources/application.yml b/iot-server/server-bootstrap/src/main/resources/application.yml index 96589234..23685945 100644 --- a/iot-server/server-bootstrap/src/main/resources/application.yml +++ b/iot-server/server-bootstrap/src/main/resources/application.yml @@ -41,7 +41,6 @@ core: restAcceptorPriorityDelta: ${ZS_CORE_REST_JETTY_DELTA:0} restAcceptQueueSize: ${ZS_CORE_REST_JETTY_QUEUE_SIZE:0} httpMaxRequestHeaderSize: ${ZS_CORE_HTTP_MAX_REQUEST_HEADER_SIZE:8192} - zabbixConfigPath: ${ZS_CORE_ZABBIX_CONFIG_PATH:E:\\zabbix_server.conf} # 健康检查 health-checker: diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java deleted file mode 100644 index 2e000f1b..00000000 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.zmops.zeus.iot.server.core; - -import com.zmops.zeus.iot.server.library.module.ModuleConfig; -import lombok.Getter; -import lombok.Setter; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author nantian created at 2021/8/16 22:29 - */ - -@Setter -@Getter -public class CoreModuleConfig extends ModuleConfig { - - - private String nameSpace; - - private String restHost; - private int restPort; - private String restContextPath; - private int restMinThreads = 1; - private int restMaxThreads = 200; - private long restIdleTimeOut = 30000; - private int restAcceptorPriorityDelta = 0; - private int restAcceptQueueSize = 0; - private String zabbixConfigPath = "/etc/zabbix/zabbix_server.conf"; // yum or apt install default location. - - - /** - * Timeout for cluster internal communication, in seconds. - */ - private int remoteTimeout = 20; - - - /** - * The number of threads used to prepare metrics data to the storage. - * - * @since 8.7.0 - */ - @Setter - @Getter - private int prepareThreads = 2; - - /** - * The maximum size in bytes allowed for request headers. - * Use -1 to disable it. - */ - private int httpMaxRequestHeaderSize = 8192; - -} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java deleted file mode 100644 index bba9c582..00000000 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.zmops.zeus.iot.server.core; - -import com.zmops.zeus.iot.server.action.ActionRouteIdentifier; -import com.zmops.zeus.iot.server.action.HelloWorldAction; -import com.zmops.zeus.iot.server.core.camel.CamelContextHolderService; -import com.zmops.zeus.iot.server.core.camel.ZabbixSenderComponent; -import com.zmops.zeus.iot.server.core.eventbus.EventBusService; -import com.zmops.zeus.iot.server.core.server.JettyHandlerRegister; -import com.zmops.zeus.iot.server.core.server.JettyHandlerRegisterImpl; -import com.zmops.zeus.iot.server.core.servlet.DeviceTriggerActionHandler; -import com.zmops.zeus.iot.server.core.servlet.HttpItemTrapperHandler; -import com.zmops.zeus.iot.server.core.servlet.ZabbixConfigHandler; -import com.zmops.zeus.iot.server.eventbus.core.EventControllerFactory; -import com.zmops.zeus.iot.server.eventbus.thread.ThreadPoolFactory; -import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadCustomization; -import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadParameter; -import com.zmops.zeus.iot.server.library.module.*; -import com.zmops.zeus.iot.server.library.server.jetty.JettyServer; -import com.zmops.zeus.iot.server.library.server.jetty.JettyServerConfig; -import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; -import com.zmops.zeus.iot.server.telemetry.TelemetryModule; -import org.apache.camel.impl.DefaultCamelContext; -import org.apache.camel.model.ModelCamelContext; - -/** - * @author nantian created at 2021/8/16 22:26 - */ -public class CoreModuleProvider extends ModuleProvider { - - private final CoreModuleConfig moduleConfig; - private ModelCamelContext camelContext; - - private JettyServer jettyServer; - private ThreadPoolFactory threadPoolFactory; - private EventControllerFactory eventControllerFactory; - - - public CoreModuleProvider() { - super(); - this.moduleConfig = new CoreModuleConfig(); - } - - - @Override - public String name() { - return "default"; - } - - @Override - public Class module() { - return CoreModule.class; - } - - @Override - public ModuleConfig createConfigBeanIfAbsent() { - return moduleConfig; - } - - @Override - public void prepare() throws ServiceNotProvidedException, ModuleStartException { - - threadPoolFactory = new ThreadPoolFactory(new ThreadCustomization(), new ThreadParameter()); - eventControllerFactory = new EventControllerFactory(threadPoolFactory); - - JettyServerConfig jettyServerConfig = JettyServerConfig.builder() - .host(moduleConfig.getRestHost()) - .port(moduleConfig.getRestPort()) - .contextPath(moduleConfig.getRestContextPath()) - .jettyIdleTimeOut(moduleConfig.getRestIdleTimeOut()) - .jettyAcceptorPriorityDelta(moduleConfig.getRestAcceptorPriorityDelta()) - .jettyMinThreads(moduleConfig.getRestMinThreads()) - .jettyMaxThreads(moduleConfig.getRestMaxThreads()) - .jettyAcceptQueueSize(moduleConfig.getRestAcceptQueueSize()) - .jettyHttpMaxRequestHeaderSize(moduleConfig.getHttpMaxRequestHeaderSize()) - .build(); - - - jettyServer = new JettyServer(jettyServerConfig); - jettyServer.initialize(); - - camelContext = new DefaultCamelContext(); - camelContext.addComponent(Const.CAMEL_ZABBIX_COMPONENT_NAME, new ZabbixSenderComponent(getManager())); - - this.registerServiceImplementation(JettyHandlerRegister.class, new JettyHandlerRegisterImpl(jettyServer)); - this.registerServiceImplementation(CamelContextHolderService.class, new CamelContextHolderService(camelContext, getManager())); - this.registerServiceImplementation(EventBusService.class, new EventBusService(eventControllerFactory)); - } - - @Override - public void start() throws ServiceNotProvidedException, ModuleStartException { - try { - - jettyServer.start(); - camelContext.start(); - - } catch (Exception e) { - e.printStackTrace(); - } - } - - public void shutdown() { - threadPoolFactory.shutdown(); - } - - @Override - public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { - JettyHandlerRegister service = getManager().find(CoreModule.NAME).provider().getService(JettyHandlerRegister.class); - service.addHandler(new HttpItemTrapperHandler()); - service.addHandler(new DeviceTriggerActionHandler(getManager())); - service.addHandler(new ZabbixConfigHandler(moduleConfig.getZabbixConfigPath())); - - - // ### 可以自定义添加 Action 的动作异步处理,指定 ID - eventControllerFactory.getAsyncController(ActionRouteIdentifier.helloworld).register(new HelloWorldAction()); - - } - - @Override - public String[] requiredModules() { - return new String[]{ - TelemetryModule.NAME, - ZabbixSenderModule.NAME - }; - } -} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/ZabbixConfigHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/ZabbixConfigHandler.java deleted file mode 100644 index 02f000be..00000000 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/ZabbixConfigHandler.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.zmops.zeus.iot.server.core.servlet; - -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.zmops.zeus.iot.server.library.server.jetty.ArgumentsParseException; -import com.zmops.zeus.iot.server.library.server.jetty.JettyJsonHandler; - -import javax.servlet.http.HttpServletRequest; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -/** - * @author nantian created at 2021/9/2 10:20 - */ -public class ZabbixConfigHandler extends JettyJsonHandler { - - private final String zabbixConfigPath; - private final Gson gson = new Gson(); - - public ZabbixConfigHandler(String zabbixConfigPath) { - this.zabbixConfigPath = zabbixConfigPath; - } - - @Override - public String pathSpec() { - return "/zabbix/config"; - } - - @Override - protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException, IOException { - - Properties prop = new Properties(); - InputStream in = new FileInputStream(zabbixConfigPath); - - prop.load(in); - in.close(); - - Set confNames = prop.stringPropertyNames(); - - Map confMap = new HashMap<>(); - confNames.forEach(i -> { - confMap.put(i, prop.getProperty(i)); - }); - - return gson.fromJson(gson.toJson(confMap), JsonObject.class); - } -} From 7506b8cc31115ce9104e13c3d947894cacbc5743 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 2 Sep 2021 11:17:20 +0800 Subject: [PATCH 082/763] =?UTF-8?q?=E6=81=A2=E5=A4=8D=E8=AF=AF=E5=88=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/server/core/CoreModuleConfig.java | 49 +++++++ .../iot/server/core/CoreModuleProvider.java | 123 ++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java new file mode 100644 index 00000000..f60c3931 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java @@ -0,0 +1,49 @@ +package com.zmops.zeus.iot.server.core; + +import com.zmops.zeus.iot.server.library.module.ModuleConfig; +import lombok.Getter; +import lombok.Setter; + +/** + * @author nantian created at 2021/8/16 22:29 + */ + +@Setter +@Getter +public class CoreModuleConfig extends ModuleConfig { + + + private String nameSpace; + + private String restHost; + private int restPort; + private String restContextPath; + private int restMinThreads = 1; + private int restMaxThreads = 200; + private long restIdleTimeOut = 30000; + private int restAcceptorPriorityDelta = 0; + private int restAcceptQueueSize = 0; + + + /** + * Timeout for cluster internal communication, in seconds. + */ + private int remoteTimeout = 20; + + + /** + * The number of threads used to prepare metrics data to the storage. + * + * @since 8.7.0 + */ + @Setter + @Getter + private int prepareThreads = 2; + + /** + * The maximum size in bytes allowed for request headers. + * Use -1 to disable it. + */ + private int httpMaxRequestHeaderSize = 8192; + +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java new file mode 100644 index 00000000..150d061a --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java @@ -0,0 +1,123 @@ +package com.zmops.zeus.iot.server.core; + +import com.zmops.zeus.iot.server.action.ActionRouteIdentifier; +import com.zmops.zeus.iot.server.action.HelloWorldAction; +import com.zmops.zeus.iot.server.core.camel.CamelContextHolderService; +import com.zmops.zeus.iot.server.core.camel.ZabbixSenderComponent; +import com.zmops.zeus.iot.server.core.eventbus.EventBusService; +import com.zmops.zeus.iot.server.core.server.JettyHandlerRegister; +import com.zmops.zeus.iot.server.core.server.JettyHandlerRegisterImpl; +import com.zmops.zeus.iot.server.core.servlet.DeviceTriggerActionHandler; +import com.zmops.zeus.iot.server.core.servlet.HttpItemTrapperHandler; +import com.zmops.zeus.iot.server.eventbus.core.EventControllerFactory; +import com.zmops.zeus.iot.server.eventbus.thread.ThreadPoolFactory; +import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadCustomization; +import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadParameter; +import com.zmops.zeus.iot.server.library.module.*; +import com.zmops.zeus.iot.server.library.server.jetty.JettyServer; +import com.zmops.zeus.iot.server.library.server.jetty.JettyServerConfig; +import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; +import com.zmops.zeus.iot.server.telemetry.TelemetryModule; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.model.ModelCamelContext; + +/** + * @author nantian created at 2021/8/16 22:26 + */ +public class CoreModuleProvider extends ModuleProvider { + + private final CoreModuleConfig moduleConfig; + private ModelCamelContext camelContext; + + private JettyServer jettyServer; + private ThreadPoolFactory threadPoolFactory; + private EventControllerFactory eventControllerFactory; + + + public CoreModuleProvider() { + super(); + this.moduleConfig = new CoreModuleConfig(); + } + + + @Override + public String name() { + return "default"; + } + + @Override + public Class module() { + return CoreModule.class; + } + + @Override + public ModuleConfig createConfigBeanIfAbsent() { + return moduleConfig; + } + + @Override + public void prepare() throws ServiceNotProvidedException, ModuleStartException { + + threadPoolFactory = new ThreadPoolFactory(new ThreadCustomization(), new ThreadParameter()); + eventControllerFactory = new EventControllerFactory(threadPoolFactory); + + JettyServerConfig jettyServerConfig = JettyServerConfig.builder() + .host(moduleConfig.getRestHost()) + .port(moduleConfig.getRestPort()) + .contextPath(moduleConfig.getRestContextPath()) + .jettyIdleTimeOut(moduleConfig.getRestIdleTimeOut()) + .jettyAcceptorPriorityDelta(moduleConfig.getRestAcceptorPriorityDelta()) + .jettyMinThreads(moduleConfig.getRestMinThreads()) + .jettyMaxThreads(moduleConfig.getRestMaxThreads()) + .jettyAcceptQueueSize(moduleConfig.getRestAcceptQueueSize()) + .jettyHttpMaxRequestHeaderSize(moduleConfig.getHttpMaxRequestHeaderSize()) + .build(); + + + jettyServer = new JettyServer(jettyServerConfig); + jettyServer.initialize(); + + camelContext = new DefaultCamelContext(); + camelContext.addComponent(Const.CAMEL_ZABBIX_COMPONENT_NAME, new ZabbixSenderComponent(getManager())); + + this.registerServiceImplementation(JettyHandlerRegister.class, new JettyHandlerRegisterImpl(jettyServer)); + this.registerServiceImplementation(CamelContextHolderService.class, new CamelContextHolderService(camelContext, getManager())); + this.registerServiceImplementation(EventBusService.class, new EventBusService(eventControllerFactory)); + } + + @Override + public void start() throws ServiceNotProvidedException, ModuleStartException { + try { + + jettyServer.start(); + camelContext.start(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void shutdown() { + threadPoolFactory.shutdown(); + } + + @Override + public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { + JettyHandlerRegister service = getManager().find(CoreModule.NAME).provider().getService(JettyHandlerRegister.class); + service.addHandler(new HttpItemTrapperHandler()); + service.addHandler(new DeviceTriggerActionHandler(getManager())); + + + // ### 可以自定义添加 Action 的动作异步处理,指定 ID + eventControllerFactory.getAsyncController(ActionRouteIdentifier.helloworld).register(new HelloWorldAction()); + + } + + @Override + public String[] requiredModules() { + return new String[]{ + TelemetryModule.NAME, + ZabbixSenderModule.NAME + }; + } +} From 3e249c6160ffe80bc6150ce3f094c2f5d80b350d Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 2 Sep 2021 11:50:45 +0800 Subject: [PATCH 083/763] update zeus-iot-ui submodule. --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index f0d461d2..2147c329 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit f0d461d2c5f5009de3f5566d2552ae3400795c90 +Subproject commit 2147c3291fa1061727ee998ecc8751ca3fc88e9a From 0edaad0749e3caa99e12240fdee4e894d1ae4714 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 3 Sep 2021 01:10:50 +0800 Subject: [PATCH 084/763] add tdengine storage module. --- iot-server/server-storage-plugin/pom.xml | 23 ++++++++++++++++ .../server-tdengine-plugin/pom.xml | 27 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 iot-server/server-storage-plugin/pom.xml create mode 100644 iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml diff --git a/iot-server/server-storage-plugin/pom.xml b/iot-server/server-storage-plugin/pom.xml new file mode 100644 index 00000000..0559d914 --- /dev/null +++ b/iot-server/server-storage-plugin/pom.xml @@ -0,0 +1,23 @@ + + + + iot-server + com.zmops + 1.0-beta + + 4.0.0 + + server-storage-plugin + pom + + server-tdengine-plugin + + + + 8 + 8 + + + \ No newline at end of file diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml new file mode 100644 index 00000000..5f98093f --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml @@ -0,0 +1,27 @@ + + + + server-storage-plugin + com.zmops + 1.0-beta + + 4.0.0 + + server-tdengine-plugin + + + 8 + 8 + + + + + com.taosdata.jdbc + taos-jdbcdriver + 2.0.30 + + + + \ No newline at end of file From 5c43744fd1842661cc365afe831ee241dc3aa254 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 3 Sep 2021 01:11:17 +0800 Subject: [PATCH 085/763] add storage module. --- iot-server/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/iot-server/pom.xml b/iot-server/pom.xml index ff1a6836..8077fadf 100644 --- a/iot-server/pom.xml +++ b/iot-server/pom.xml @@ -22,6 +22,7 @@ server-receiver-plugin server-sender server-action + server-storage-plugin From 9eaca0a2644edd8b4867a12dfa1477c062d31c08 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 3 Sep 2021 14:38:36 +0800 Subject: [PATCH 086/763] =?UTF-8?q?=E8=AE=BE=E5=A4=87ID=20=E5=8F=AF?= =?UTF-8?q?=E8=BE=93=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/zmops/iot/domain/device/Device.java | 3 +-- .../iot/domain/device/DevicesGroups.java | 2 +- .../java/com/zmops/iot/domain/device/Tag.java | 2 +- .../iot/domain/product/ProductAttribute.java | 2 +- .../web/analyse/dto/param/HistoryParam.java | 2 +- .../web/analyse/dto/param/LatestParam.java | 2 +- .../web/analyse/service/HistoryService.java | 2 +- .../web/analyse/service/LatestService.java | 2 +- .../device/controller/DeviceController.java | 21 ++++++++++++------- .../zmops/iot/web/device/dto/DeviceDto.java | 5 ++++- .../iot/web/device/service/DeviceService.java | 20 +++++++++--------- .../service/work/SaveAttributeWorker.java | 19 +++++++++-------- .../device/service/work/SaveDeviceWorker.java | 8 +++---- .../device/service/work/SaveTagWorker.java | 14 +++++++------ .../service/work/UpdateAttrZbxIdWorker.java | 15 ++++++------- .../service/work/UpdateZbxTagWorker.java | 2 +- .../product/controller/ProductController.java | 8 +++---- .../iot/web/product/dto/ProductAttr.java | 2 +- .../iot/web/product/dto/ProductAttrDto.java | 2 +- .../zmops/iot/web/product/dto/ProductTag.java | 2 +- .../zmops/iot/web/product/dto/ValueMap.java | 2 +- .../product/dto/param/ProductAttrParam.java | 2 +- .../product/service/ProductModelService.java | 6 +++--- .../web/product/service/ProductService.java | 2 +- .../service/work/SaveProdAttrWorker.java | 6 +++--- 25 files changed, 83 insertions(+), 70 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java index 9da122f7..0978267f 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java @@ -21,8 +21,7 @@ public class Device extends BaseEntity { @Id - @GeneratedValue(generator = IdTypeConsts.ID_SNOW) - private Long deviceId; + private String deviceId; private String name; diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/DevicesGroups.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/DevicesGroups.java index 5a8e32e0..0073135e 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/DevicesGroups.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/DevicesGroups.java @@ -20,7 +20,7 @@ public class DevicesGroups { @Id private Long id; - private Long deviceId; + private String deviceId; private Long deviceGroupId; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/Tag.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/Tag.java index 013e391f..b2f2ef90 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/Tag.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/Tag.java @@ -25,7 +25,7 @@ public class Tag extends BaseEntity { @Id private Long id; - private Long sid; + private String sid; private String tag; diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java index ee5acdbc..c86446a5 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java @@ -35,7 +35,7 @@ public class ProductAttribute extends BaseEntity { private Long depAttrId; - private Long productId; // 产品ID + private String productId; // 产品ID private String zbxId; // Zabbix itemId diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/HistoryParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/HistoryParam.java index 40a215e7..a0f82f6d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/HistoryParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/HistoryParam.java @@ -13,7 +13,7 @@ public class HistoryParam extends BaseQueryParam { @NotNull(message = "请选择一个设备再查询") - private Long deviceId; + private String deviceId; private List attrIds; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/LatestParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/LatestParam.java index bfbe7f79..f3404d8e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/LatestParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/LatestParam.java @@ -12,7 +12,7 @@ @Data public class LatestParam extends BaseQueryParam{ @NotNull(message = "请选择一个设备再查询") - private Long deviceId; + private String deviceId; private List attrIds; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java index c9557591..95233bd4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java @@ -41,7 +41,7 @@ public Pager queryHistory(HistoryParam historyParam) { return new Pager<>(collect,latestDtos.size()); } - public List queryHistory(Long deviceId, List attrIds, Long timeFrom, Long timeTill) { + public List queryHistory(String deviceId, List attrIds, Long timeFrom, Long timeTill) { //查询出设备 Device one = new QDevice().deviceId.eq(deviceId).findOne(); if (null == one || ToolUtil.isEmpty(one.getZbxId())) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java index 559cf528..c052214b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java @@ -44,7 +44,7 @@ public Pager qeuryLatest(LatestParam latestParam) { return new Pager<>(collect,latestDtos.size()); } - public List qeuryLatest(Long deviceId, List attrIds) { + public List qeuryLatest(String deviceId, List attrIds) { //查询出设备 Device one = new QDevice().deviceId.eq(deviceId).findOne(); if (null == one || ToolUtil.isEmpty(one.getZbxId())) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java index 29dffeb7..85f1e19a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java @@ -1,5 +1,6 @@ package com.zmops.iot.web.device.controller; +import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.device.Device; @@ -57,13 +58,19 @@ public ResponseData deviceList(@RequestBody DeviceParam deviceParam) { */ @RequestMapping("/create") public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody DeviceDto deviceDto) { - int count = new QDevice().name.eq(deviceDto.getName()).findCount(); + QDevice qDevice = new QDevice().or().name.eq(deviceDto.getName()); + if (ToolUtil.isNotEmpty(deviceDto.getDeviceId())) { + qDevice.deviceId.eq(deviceDto.getDeviceId()); + } else { + deviceDto.setDeviceId(IdUtil.getSnowflake().nextId() + ""); + } + int count = qDevice.findCount(); if (count > 0) { throw new ServiceException(BizExceptionEnum.DEVICE_EXISTS); } deviceService.checkProductExist(deviceDto); - Long deviceId = deviceService.create(deviceDto); + String deviceId = deviceService.create(deviceDto); deviceDto.setDeviceId(deviceId); return ResponseData.success(deviceDto); } @@ -105,7 +112,7 @@ public ResponseData prodDetail(@RequestParam("deviceId") Long deviceId) { * 设备标签列表 */ @GetMapping("/tag/list") - public ResponseData prodTagList(@RequestParam("deviceId") Long deviceId) { + public ResponseData prodTagList(@RequestParam("deviceId") String deviceId) { return ResponseData.success(deviceService.deviceTagList(deviceId)); } @@ -113,7 +120,7 @@ public ResponseData prodTagList(@RequestParam("deviceId") Long deviceId) { * 设备值映射列表 */ @GetMapping("/valueMap/list") - public ResponseData valueMapList(@RequestParam("deviceId") Long deviceId) { + public ResponseData valueMapList(@RequestParam("deviceId") String deviceId) { return ResponseData.success(deviceService.valueMapList(deviceId)); } @@ -125,14 +132,14 @@ public ResponseData valueMapList(@RequestParam("deviceId") Long deviceId) { @PostMapping("/tag/update") public ResponseData deviceTagCreate(@RequestBody @Valid ProductTag productTag) { - Long deviceId = productTag.getProductId(); + String deviceId = productTag.getProductId(); Device device = new QDevice().deviceId.eq(deviceId).findOne(); if (null == device) { throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); } - deviceService.deviceTagCreate(productTag,device.getZbxId()); + deviceService.deviceTagCreate(productTag, device.getZbxId()); return ResponseData.success(productTag); } @@ -170,7 +177,7 @@ public ResponseData prodValueMapCreate(@RequestBody @Validated(BaseEntity.Create */ @PostMapping("/valuemap/delete") public ResponseData prodValueMapDelete(@RequestBody @Validated(BaseEntity.Delete.class) ValueMap valueMap) { - String response = deviceService.valueMapDelete(valueMap.getValuemapid()); + String response = deviceService.valueMapDelete(valueMap.getValuemapid()); return ResponseData.success(JSONObject.parseObject(response).getJSONArray("valuemapids").get(0)); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java index 7b5ff41d..38f0b204 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java @@ -22,7 +22,10 @@ public class DeviceDto implements BaseDto { @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Delete.class}) - private Long deviceId; + private String deviceId; + + @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) + private String edit; @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private String name; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 27b453e9..d17fbdde 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -183,7 +183,7 @@ private StringBuilder generateBaseSql() { * @param deviceDto * @return */ - public Long create(DeviceDto deviceDto) { + public String create(DeviceDto deviceDto) { WorkerWrapper saveTagWork = WorkerWrapper.builder().id("saveTagWork") .worker(saveTagWorker).param(deviceDto).build(); @@ -229,7 +229,7 @@ public Long create(DeviceDto deviceDto) { * @param deviceDto * @return */ - public Long update(DeviceDto deviceDto) { + public String update(DeviceDto deviceDto) { Device device = new QDevice().deviceId.eq(deviceDto.getDeviceId()).findOne(); if (null == device) { throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); @@ -284,25 +284,25 @@ public void checkProductExist(DeviceDto deviceDto) { deviceDto.setType(product.getType()); } - public Long delete(DeviceDto deviceDto) { + public String delete(DeviceDto deviceDto) { Device device = new QDevice().deviceId.eq(deviceDto.getDeviceId()).findOne(); if (null == device) { return deviceDto.getDeviceId(); } String zbxId = device.getZbxId(); - WorkerWrapper delTagWork = WorkerWrapper.builder().id("delTagWork") + WorkerWrapper delTagWork = WorkerWrapper.builder().id("delTagWork") .worker((deviceId, allWrappers) -> { new QTag().sid.eq(deviceId).delete(); return true; }).param(deviceDto.getDeviceId()).build(); - WorkerWrapper delAttrWork = WorkerWrapper.builder().id("delAttrWork") + WorkerWrapper delAttrWork = WorkerWrapper.builder().id("delAttrWork") .worker((deviceId, allWrappers) -> { new QProductAttribute().productId.eq(deviceId).delete(); return true; }).param(deviceDto.getDeviceId()).build(); - WorkerWrapper delGropusWork = WorkerWrapper.builder().id("delGropusWork") + WorkerWrapper delGropusWork = WorkerWrapper.builder().id("delGropusWork") .worker((deviceId, allWrappers) -> { new QDevicesGroups().deviceId.eq(deviceId).delete(); return true; @@ -314,7 +314,7 @@ public Long delete(DeviceDto deviceDto) { return true; }).param(zbxId).build(); - WorkerWrapper delDeviceWork = WorkerWrapper.builder().id("delDeviceWork") + WorkerWrapper delDeviceWork = WorkerWrapper.builder().id("delDeviceWork") .worker((deviceId, allWrappers) -> { new QDevice().deviceId.eq(deviceId).delete(); return true; @@ -419,7 +419,7 @@ public DeviceDto deviceDetail(Long deviceId) { * @param deviceId * @return */ - public List deviceTagList(Long deviceId) { + public List deviceTagList(String deviceId) { QTag tag = QTag.alias(); return new QTag().select(tag.id, tag.sid, tag.tag, tag.value).sid.eq(deviceId).findList(); } @@ -430,7 +430,7 @@ public List deviceTagList(Long deviceId) { * @param deviceId * @return */ - public JSONArray valueMapList(Long deviceId) { + public JSONArray valueMapList(String deviceId) { JSONArray zbxTemplateInfo = getZbxHostInfo(deviceId); if (zbxTemplateInfo.size() == 0) { return new JSONArray(); @@ -439,7 +439,7 @@ public JSONArray valueMapList(Long deviceId) { return JSONObject.parseArray(zbxTemplateInfo.getJSONObject(0).getString("valuemaps")); } - private JSONArray getZbxHostInfo(Long deviceId) { + private JSONArray getZbxHostInfo(String deviceId) { String zbxId = new QDevice().select(QDevice.alias().zbxId).deviceId.eq(deviceId).findSingleAttribute(); if (null == zbxId) { return new JSONArray(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java index 72158ba6..3ea77ab6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java @@ -19,7 +19,7 @@ /** * @author yefei - * + *

* 设备属性处理步骤 */ @Slf4j @@ -31,23 +31,24 @@ public class SaveAttributeWorker implements IWorker { public Boolean action(DeviceDto deviceDto, Map> map) { log.debug("处理Attr工作…………"); - Long deviceId = deviceDto.getDeviceId(); - //创建 - if (null == deviceId) { - Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); - deviceId = device.getDeviceId(); - } else { - //修改 + String deviceId = deviceDto.getDeviceId(); + if (ToolUtil.isNotEmpty(deviceDto.getEdit()) && "true".equals(deviceDto.getEdit())) { + //修改 //没有修改关联的产品 不做处理 if (deviceDto.getProductId().equals(deviceDto.getOldProductId())) { return true; } new QProductAttribute().productId.eq(deviceId).templateId.isNotNull().delete(); + } else { + //创建 + Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); + deviceId = device.getDeviceId(); + } - List productAttributeList = new QProductAttribute().productId.eq(deviceDto.getProductId()).findList(); + List productAttributeList = new QProductAttribute().productId.eq(deviceDto.getProductId() + "").findList(); List newProductAttributeList = new ArrayList<>(); for (ProductAttribute productAttribute : productAttributeList) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java index 40d25add..91566f30 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java @@ -15,7 +15,7 @@ /** * @author yefei - * + *

* 保存设备 */ @Slf4j @@ -29,11 +29,11 @@ public Device action(DeviceDto deviceDto, Map> allWr Device device = new Device(); ToolUtil.copyProperties(deviceDto, device); - if (null == deviceDto.getDeviceId()) { + if (ToolUtil.isNotEmpty(deviceDto.getEdit()) && "true".equals(deviceDto.getEdit())) { + DB.update(device); + } else { device.setStatus(CommonStatus.ENABLE.getCode()); DB.save(device); - } else { - DB.update(device); } return device; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java index 48ae81c0..a261755a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java @@ -5,6 +5,7 @@ import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.query.QTag; +import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; @@ -25,12 +26,9 @@ public class SaveTagWorker implements IWorker { public Boolean action(DeviceDto deviceDto, Map> allWrappers) { log.debug("处理tag工作…………"); - Long deviceId = deviceDto.getDeviceId(); - //创建 - if (null == deviceId) { - Device device = (Device) allWrappers.get("saveDvice").getWorkResult().getResult(); - deviceId = device.getDeviceId(); - } else { + String deviceId = deviceDto.getDeviceId(); + + if (ToolUtil.isNotEmpty(deviceDto.getEdit()) && "true".equals(deviceDto.getEdit())) { //修改 //没有修改关联的产品 不做处理 @@ -38,6 +36,10 @@ public Boolean action(DeviceDto deviceDto, Map> allW return true; } new QTag().sid.eq(deviceId).delete(); + } else { + //创建 + Device device = (Device) allWrappers.get("saveDvice").getWorkResult().getResult(); + deviceId = device.getDeviceId(); } DB.sqlUpdate("insert into tag (sid,tag,value,template_id) SELECT :deviceId,tag,value,id template_id from tag where sid=:sid") diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java index d5b1d1d8..1572b2a0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java @@ -23,7 +23,7 @@ /** * @author yefei - * + *

* 更新设备属性中ZBXID */ @Slf4j @@ -36,18 +36,19 @@ public class UpdateAttrZbxIdWorker implements IWorker { @Override public Boolean action(DeviceDto deviceDto, Map> map) { log.debug("处理Attr zbx回填工作……"); - Long deviceId = deviceDto.getDeviceId(); - //创建 - if (null == deviceId) { - Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); - deviceId = device.getDeviceId(); - } else { + String deviceId = deviceDto.getDeviceId(); + + if (ToolUtil.isNotEmpty(deviceDto.getEdit()) && "true".equals(deviceDto.getEdit())) { //修改 //没有修改关联的产品 不做处理 if (deviceDto.getProductId().equals(deviceDto.getOldProductId())) { return true; } + } else { + //创建 + Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); + deviceId = device.getDeviceId(); } //取出 ZBX hostid diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java index 68a25fa8..19962cb0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java @@ -39,7 +39,7 @@ public Boolean action(DeviceDto deviceDto, Map> map) //取 设备ID Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); - Long deviceId = device.getDeviceId(); + String deviceId = device.getDeviceId(); //查询出本地tag List list = new QTag().sid.eq(deviceId).findList(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java index de42bbe4..778830fe 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java @@ -69,7 +69,7 @@ public ResponseData prodDetail(@RequestParam("productId") Long prodId) { * 产品标签列表 */ @GetMapping("/prodTag/list") - public ResponseData prodTagList(@RequestParam("productId") Long prodId) { + public ResponseData prodTagList(@RequestParam("productId") String prodId) { return ResponseData.success(productService.prodTagList(prodId)); } @@ -168,8 +168,8 @@ public ResponseData prodDelete(@RequestBody @Validated(value = BaseEntity.Delete @PostMapping("/tag/update") public ResponseData prodTagCreate(@RequestBody @Valid ProductTag productTag) { - Long productId = productTag.getProductId(); - Product product = new QProduct().productId.eq(productId).findOne(); + String productId = productTag.getProductId(); + Product product = new QProduct().productId.eq(Integer.parseInt(productId)).findOne(); if (null == product) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); @@ -203,7 +203,7 @@ public ResponseData prodTagCreate(@RequestBody @Valid ProductTag productTag) { @PostMapping("/valuemap/update") public ResponseData prodValueMapCreate(@RequestBody @Validated(BaseEntity.Create.class) ValueMap valueMap) { - Product product = new QProduct().productId.eq(valueMap.getProductId()).findOne(); + Product product = new QProduct().productId.eq(Integer.parseInt(valueMap.getProductId())).findOne(); if (null == product) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java index 6f70af15..3121acae 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java @@ -46,7 +46,7 @@ public class ProductAttr { private String zbxId; @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) - private Long productId; + private String productId; @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) private String valueType; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java index 68f66a47..5a42c19a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java @@ -42,7 +42,7 @@ public class ProductAttrDto implements BaseDto { @JsonIgnore private String zbxId; - private Long productId; + private String productId; @CachedValue(value = "DATA_TYPE") private String valueType; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductTag.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductTag.java index 45db0104..b76030d5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductTag.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductTag.java @@ -16,7 +16,7 @@ public class ProductTag { @NotNull - private Long productId; + private String productId; private List productTag; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ValueMap.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ValueMap.java index ca89bd7c..e1af8f96 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ValueMap.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ValueMap.java @@ -14,7 +14,7 @@ public class ValueMap { @NotNull(groups = BaseEntity.Create.class) - private Long productId; + private String productId; @NotNull(groups = BaseEntity.Create.class) private String valueMapName; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java index b205649a..f1e8c612 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java @@ -15,7 +15,7 @@ public class ProductAttrParam extends BaseQueryParam { @NotNull(groups = BaseEntity.Get.class,message = "请选择一个设备再查询") - private Long prodId; + private String prodId; private String attrName; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index 2c815afb..53a2f76a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -55,7 +55,7 @@ public class ProductModelService { public Pager prodModelAttributeList(ProductAttrParam productAttr) { QProductAttribute qProductAttribute = new QProductAttribute(); - if (null != productAttr.getProdId()) { + if (ToolUtil.isNotEmpty(productAttr.getProdId())) { qProductAttribute.productId.eq(productAttr.getProdId()); } if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { @@ -176,7 +176,7 @@ public String createTrapperItem(ProductAttr productAttr) { String itemName = productAttr.getAttrId() + ""; - Product prod = new QProduct().productId.eq(productAttr.getProductId()).findOne(); + Product prod = new QProduct().productId.eq(Integer.parseInt(productAttr.getProductId())).findOne(); if (null == prod) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } @@ -212,7 +212,7 @@ public String createTrapperItem(ProductAttr productAttr) { public ProductAttr updateTrapperItem(ProductAttr productAttr) { ProductAttribute productAttribute = new QProductAttribute().attrId.eq(productAttr.getAttrId()).findOne(); buildProdAttribute(productAttribute, productAttr); - Product prod = new QProduct().productId.eq(productAttr.getProductId()).findOne(); + Product prod = new QProduct().productId.eq(Integer.parseInt(productAttr.getProductId())).findOne(); if (null == prod) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java index 49a65167..f5f3fb29 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java @@ -241,7 +241,7 @@ public ProductDto prodDetail(Long prodId) { * @param prodId * @return */ - public List prodTagList(Long prodId) { + public List prodTagList(String prodId) { QTag tag = QTag.alias(); return new QTag().select(tag.id, tag.sid, tag.tag, tag.value).sid.eq(prodId).orderBy(" create_time desc").findList(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java index fd5aa388..a5f18daf 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java @@ -30,13 +30,13 @@ public class SaveProdAttrWorker implements IWorker { public Boolean action(ProductAttr productAttr, Map> map) { log.debug("处理产品 新增Attr 同步到设备工作…………"); - Long prodId = productAttr.getProductId(); + String prodId = productAttr.getProductId(); - List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(prodId).findSingleAttributeList(); + List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Integer.parseInt(prodId)).findSingleAttributeList(); List productAttributeList = new ArrayList<>(); - for (Long deviceId : deviceIds) { + for (String deviceId : deviceIds) { ProductAttribute productAttrbute = new ProductAttribute(); ToolUtil.copyProperties(productAttr, productAttrbute); productAttrbute.setAttrId(IdUtil.getSnowflake().nextId()); From 6295f4ec69e1ef3915ad7db474780ba7f4f852d6 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 3 Sep 2021 15:15:19 +0800 Subject: [PATCH 087/763] =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E6=98=AF=E5=90=A6=E7=BB=91=E5=AE=9A=E8=AE=BE?= =?UTF-8?q?=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zmops/iot/web/exception/enums/BizExceptionEnum.java | 5 +++-- .../iot/web/product/controller/ProductController.java | 7 +++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index eb8e96df..04d761fb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -133,6 +133,7 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { PRODUCT_TYPE_HAS_BIND(1304, "产品分类已绑定产品"), PRODUCT_TYPE_PID_NOT_EXIST(1305, "父节点不存在"), PRODUCT_TYPE_PID_ERR(1306, "父节点不可以是自已或子节点"), + PRODUCT_HAS_BIND_DEVICE(1307, "产品已绑定设备"), /** * 属性相关 @@ -148,8 +149,8 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { /** * 服务相关 */ - SERVICE_EXISTS(1601,"服务已存在"), - SERVICE_NOT_EXISTS(1602,"服务不存在"), + SERVICE_EXISTS(1601, "服务已存在"), + SERVICE_NOT_EXISTS(1602, "服务不存在"), /** * 租户相关的异常 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java index 778830fe..7d774a52 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.device.Tag; +import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.device.query.QTag; import com.zmops.iot.domain.product.Product; import com.zmops.iot.domain.product.query.QProduct; @@ -137,13 +138,15 @@ public ResponseData prodUpdate(@RequestBody @Validated(value = BaseEntity.Update @PostMapping("/delete") public ResponseData prodDelete(@RequestBody @Validated(value = BaseEntity.Delete.class) ProductBasicInfo prodBasicInfo) { - //第一步:验证产品下 是否有设备存在 Product product = new QProduct().productId.eq(prodBasicInfo.getProductId()).findOne(); if (null == product) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } - // TODO 判断该产品下 是否有设备 + int deviceNum = new QDevice().productId.eq(prodBasicInfo.getProductId()).findCount(); + if(deviceNum>0){ + throw new ServiceException(BizExceptionEnum.PRODUCT_HAS_BIND_DEVICE); + } //第二步:删除Zabbix对应的模板 From b5aa72e26ffa288363b701257398b0e920fec732 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 3 Sep 2021 17:43:19 +0800 Subject: [PATCH 088/763] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/zmops/iot/domain/product/ProductService.java | 2 +- .../zmops/iot/web/device/controller/DeviceController.java | 2 +- .../com/zmops/iot/web/device/service/DeviceService.java | 2 +- .../com/zmops/iot/web/product/dto/ProductServiceDto.java | 2 +- .../zmops/iot/web/product/dto/param/ProductSvcParam.java | 2 +- .../zmops/iot/web/product/service/ProductSvcService.java | 2 +- .../iot/web/product/service/work/SaveProdSvcWorker.java | 6 +++--- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java index b8482312..146ca728 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java @@ -21,7 +21,7 @@ public class ProductService { private String name; private String mark; private String remark; - private Long sid; + private String sid; private Long templateId; private String async; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java index 85f1e19a..02b201d4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java @@ -104,7 +104,7 @@ public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody Devi * 设备详情 */ @GetMapping("/detail") - public ResponseData prodDetail(@RequestParam("deviceId") Long deviceId) { + public ResponseData prodDetail(@RequestParam("deviceId") String deviceId) { return ResponseData.success(deviceService.deviceDetail(deviceId)); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index d17fbdde..da888ab0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -406,7 +406,7 @@ public String valueMapDelete(String valueMapId) { * @param deviceId * @return */ - public DeviceDto deviceDetail(Long deviceId) { + public DeviceDto deviceDetail(String deviceId) { StringBuilder sql = generateBaseSql(); sql.append(" where d.device_id=:deviceId"); DeviceDto deviceDto = DB.findDto(DeviceDto.class, sql.toString()).setParameter("deviceId", deviceId).findOne(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java index 48d4bf0a..d393683e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java @@ -30,7 +30,7 @@ public class ProductServiceDto implements BaseDto { private String remark; @NotNull(groups = BaseEntity.Create.class) - private Long sid; + private String sid; @CachedValue(value = "EXECUTE_TYPE") private String async; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductSvcParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductSvcParam.java index 07b3db1e..5bd81535 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductSvcParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductSvcParam.java @@ -13,5 +13,5 @@ public class ProductSvcParam extends BaseQueryParam { private String mark; - private Long prodId; + private String prodId; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index 43a677d4..dc2e7a43 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -51,7 +51,7 @@ public Pager getServiceByPage(ProductSvcParam productSvcParam if (ToolUtil.isNotEmpty(productSvcParam.getMark())) { qProductService.mark.contains(productSvcParam.getMark()); } - if (null != productSvcParam.getProdId()) { + if (ToolUtil.isNotEmpty(productSvcParam.getProdId())) { qProductService.sid.eq(productSvcParam.getProdId()); } qProductService.orderBy(" id desc"); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java index 3b2b3108..8cbf2138 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java @@ -30,11 +30,11 @@ public class SaveProdSvcWorker implements IWorker { public Boolean action(ProductServiceDto productServiceDto, Map> map) { log.debug("处理产品 新增服务 同步到设备工作…………"); - Long prodId = productServiceDto.getSid(); + String prodId = productServiceDto.getSid(); - List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(prodId).findSingleAttributeList(); + List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); - for (Long deviceId : deviceIds) { + for (String deviceId : deviceIds) { ProductService productService = new ProductService(); ToolUtil.copyProperties(productServiceDto, productService); productService.setSid(deviceId); From d54633638458cb4a991263f2f1131e4139aa9bfa Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 3 Sep 2021 21:51:27 +0800 Subject: [PATCH 089/763] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5d468070..5ebe36f7 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ### 快速安装 -Zeus-IOT 支持 Centos 7、Ubuntu 20.04、Debain 10 、Kylin、UOS 等基于x86_64平台的 Linux 操作系统。 +Zeus-IoT 支持 Centos 7、Ubuntu 20.04、Debain 10 、Kylin、UOS 等基于x86_64平台的 Linux 操作系统。 - Centos7、RedHat 7 From ba41bfb499caeb060d90baeed791bffabeecf620 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 3 Sep 2021 21:51:43 +0800 Subject: [PATCH 090/763] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5ebe36f7..5cd73780 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Zeus IOT 宙斯物联网分布式采集平台 +## Zeus IoT 宙斯物联网分布式采集平台 [![GitHub stars](https://img.shields.io/github/stars/zmops/zeus-iot.svg?label=Stars&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub issues](https://img.shields.io/github/issues/zmops/zeus-iot?label=Issuess&logo=github)](https://github.com/zmops/zeus-iot) From 234d9796549a70c380ae44ca7b2ffc82142d3dbd Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 4 Sep 2021 12:07:46 +0800 Subject: [PATCH 091/763] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/zmops/iot/web/device/controller/DeviceController.java | 4 ++-- .../src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java index 02b201d4..3d4fe499 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java @@ -68,7 +68,7 @@ public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody Devi if (count > 0) { throw new ServiceException(BizExceptionEnum.DEVICE_EXISTS); } - + deviceDto.setEdit("false"); deviceService.checkProductExist(deviceDto); String deviceId = deviceService.create(deviceDto); deviceDto.setDeviceId(deviceId); @@ -84,7 +84,7 @@ public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody Devi if (count > 0) { throw new ServiceException(BizExceptionEnum.DEVICE_EXISTS); } - + deviceDto.setEdit("true"); deviceService.checkProductExist(deviceDto); deviceService.update(deviceDto); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java index 38f0b204..dec63b2d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java @@ -24,7 +24,6 @@ public class DeviceDto implements BaseDto { @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Delete.class}) private String deviceId; - @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) private String edit; @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) From d8abdd1f10d6f73ad059d0411ecff5bf16fa06ad Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 4 Sep 2021 13:55:08 +0800 Subject: [PATCH 092/763] =?UTF-8?q?=E5=B1=9E=E6=80=A7=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/zmops/iot/web/device/service/DeviceModelService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index dd2c6f34..66e4614e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -82,7 +82,7 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr * @param productAttr * @return */ - public List list(ProductAttrParam productAttr) { + public List list(ProductAttrParam productAttr) { QProductAttribute qProductAttribute = new QProductAttribute(); if (null != productAttr.getProdId()) { qProductAttribute.productId.eq(productAttr.getProdId()); @@ -93,7 +93,7 @@ public List list(ProductAttrParam productAttr) { if (ToolUtil.isNotEmpty(productAttr.getKey())) { qProductAttribute.key.contains(productAttr.getKey()); } - return qProductAttribute.findList(); + return qProductAttribute.asDto(ProductAttrDto.class).findList(); } /** From 0a9fb776d4b01dbe3ba7c72832dcaee00c96c124 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 4 Sep 2021 22:31:14 +0800 Subject: [PATCH 093/763] invoke zabbix send method result to log --- .../iot/server/core/worker/ItemDataTransferWorker.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/ItemDataTransferWorker.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/ItemDataTransferWorker.java index 39d38345..fa7f2fe7 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/ItemDataTransferWorker.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/ItemDataTransferWorker.java @@ -101,10 +101,13 @@ public void prepareBatch(Collection lastCollection) { private void batchSenderDataToZabbix(List valueList) { ZabbixTrapper zabbixTrapper = new ZabbixTrapper(valueList); - ZabbixSenderService senderService = getModuleDefineHolder().find(ZabbixSenderModule.NAME) - .provider().getService(ZabbixSenderService.class); + + ZabbixSenderService senderService = getModuleDefineHolder() + .find(ZabbixSenderModule.NAME).provider().getService(ZabbixSenderService.class); + try { - senderService.sendData(gson.toJson(zabbixTrapper)); + String sendResult = senderService.sendData(gson.toJson(zabbixTrapper)); + log.debug(sendResult); } catch (IOException e) { log.error(" itemvalue data sender error,msg :{}", e.getMessage()); e.printStackTrace(); From 3904d52b1c6cc579caca7dc1122169828245add4 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 6 Sep 2021 13:34:41 +0800 Subject: [PATCH 094/763] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20=E4=BA=A7=E5=93=81?= =?UTF-8?q?ID=E7=B1=BB=E5=9E=8B=E8=BD=AC=E6=8D=A2=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zmops/iot/web/product/controller/ProductController.java | 4 ++-- .../zmops/iot/web/product/service/ProductModelService.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java index 7d774a52..69d3096d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java @@ -172,7 +172,7 @@ public ResponseData prodDelete(@RequestBody @Validated(value = BaseEntity.Delete public ResponseData prodTagCreate(@RequestBody @Valid ProductTag productTag) { String productId = productTag.getProductId(); - Product product = new QProduct().productId.eq(Integer.parseInt(productId)).findOne(); + Product product = new QProduct().productId.eq(Long.parseLong(productId)).findOne(); if (null == product) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); @@ -206,7 +206,7 @@ public ResponseData prodTagCreate(@RequestBody @Valid ProductTag productTag) { @PostMapping("/valuemap/update") public ResponseData prodValueMapCreate(@RequestBody @Validated(BaseEntity.Create.class) ValueMap valueMap) { - Product product = new QProduct().productId.eq(Integer.parseInt(valueMap.getProductId())).findOne(); + Product product = new QProduct().productId.eq(Long.parseLong(valueMap.getProductId())).findOne(); if (null == product) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index 53a2f76a..02da7648 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -176,7 +176,7 @@ public String createTrapperItem(ProductAttr productAttr) { String itemName = productAttr.getAttrId() + ""; - Product prod = new QProduct().productId.eq(Integer.parseInt(productAttr.getProductId())).findOne(); + Product prod = new QProduct().productId.eq(Long.parseLong(productAttr.getProductId())).findOne(); if (null == prod) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } @@ -212,7 +212,7 @@ public String createTrapperItem(ProductAttr productAttr) { public ProductAttr updateTrapperItem(ProductAttr productAttr) { ProductAttribute productAttribute = new QProductAttribute().attrId.eq(productAttr.getAttrId()).findOne(); buildProdAttribute(productAttribute, productAttr); - Product prod = new QProduct().productId.eq(Integer.parseInt(productAttr.getProductId())).findOne(); + Product prod = new QProduct().productId.eq(Long.parseLong(productAttr.getProductId())).findOne(); if (null == prod) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } From 9556605dd91e878cd424f6f23660678e5c20b383 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 6 Sep 2021 15:14:44 +0800 Subject: [PATCH 095/763] =?UTF-8?q?=E5=AD=97=E5=85=B8=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/zmops/iot/web/sys/dto/SysDictDto.java | 76 +++++++++++++++++++ .../zmops/iot/web/sys/dto/SysDictTypeDto.java | 72 ++++++++++++++++++ .../iot/web/sys/service/DictService.java | 13 ++-- .../iot/web/sys/service/DictTypeService.java | 7 +- 4 files changed, 160 insertions(+), 8 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictTypeDto.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictDto.java new file mode 100644 index 00000000..5a2a525a --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictDto.java @@ -0,0 +1,76 @@ +package com.zmops.iot.web.sys.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.constant.IdTypeConsts; +import com.zmops.iot.domain.BaseDto; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import io.ebean.annotation.WhenModified; +import io.ebean.annotation.WhoCreated; +import io.ebean.annotation.WhoModified; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 基础字典 + *

+ */ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class SysDictDto implements BaseDto { + + /** + * 字典id + */ + private Long dictId; + + /** + * 所属字典类型的id + */ + private Long dictTypeId; + + /** + * 字典编码 + */ + private String code; + + /** + * 字典名称 + */ + private String name; + + /** + * 状态 + */ + @CachedValue(value = "STATUS") + private String status; + + /** + * 排序 + */ + private Integer sort; + + /** + * 字典的描述 + */ + private String remark; + + private String groups; + + LocalDateTime createTime; + + LocalDateTime updateTime; + + Long createUser; + + Long updateUser; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictTypeDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictTypeDto.java new file mode 100644 index 00000000..d92b206c --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictTypeDto.java @@ -0,0 +1,72 @@ +package com.zmops.iot.web.sys.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.constant.IdTypeConsts; +import com.zmops.iot.domain.BaseDto; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 字典类型表 + *

+ */ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class SysDictTypeDto implements BaseDto { + + /** + * 字典类型id + */ + private Long dictTypeId; + + /** + * 字典类型编码 + */ + private String code; + + /** + * 字典类型名称 + */ + private String name; + + /** + * 字典描述 + */ + private String remark; + + /** + * 是否是系统字典,Y-是,N-否 + */ + private String systemFlag = "N"; + + /** + * 状态 + */ + @CachedValue(value = "STATUS") + private String status; + + /** + * 排序 + */ + private Integer sort; + + LocalDateTime createTime; + + LocalDateTime updateTime; + + Long createUser; + + Long updateUser; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictService.java index 435c39f5..f2eead06 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictService.java @@ -11,6 +11,7 @@ import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.sys.dto.SysDictDto; import com.zmops.iot.web.sys.dto.param.DictParam; import io.ebean.DB; import org.springframework.beans.factory.annotation.Autowired; @@ -112,14 +113,14 @@ public SysDict update(DictParam param) { /** * 查询字典列表,通过字典ID */ - public List listDicts(Long dictTypeId) { - return new QSysDict().dictTypeId.eq(dictTypeId).orderBy(" sort desc").findList(); + public List listDicts(Long dictTypeId) { + return new QSysDict().dictTypeId.eq(dictTypeId).orderBy(" sort desc").asDto(SysDictDto.class).findList(); } /** * 查询字典列表,通过字典编码 */ - public List listDicts(String dictTypeCode) { + public List listDicts(String dictTypeCode) { Long dictTypeId = new QSysDictType().select(QSysDictType.alias().dictTypeId).code.eq(dictTypeCode).findSingleAttribute(); return listDicts(dictTypeId); } @@ -127,13 +128,13 @@ public List listDicts(String dictTypeCode) { /** * 分组查询字典列表,通过字典编码 */ - public Map> groupDictByCode(String dictTypeCode) { + public Map> groupDictByCode(String dictTypeCode) { Long dictTypeId = new QSysDictType().select(QSysDictType.alias().dictTypeId).code.eq(dictTypeCode).findSingleAttribute(); - List sysDicts = listDicts(dictTypeId); + List sysDicts = listDicts(dictTypeId); if (ToolUtil.isEmpty(sysDicts)) { return new HashMap<>(); } - return sysDicts.parallelStream().collect(Collectors.groupingBy(SysDict::getGroups)); + return sysDicts.parallelStream().collect(Collectors.groupingBy(SysDictDto::getGroups)); } private void updateDictionaries() { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictTypeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictTypeService.java index 500f4601..28d4c610 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictTypeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictTypeService.java @@ -8,6 +8,7 @@ import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.sys.dto.SysDictTypeDto; import com.zmops.iot.web.sys.dto.param.DictTypeParam; import io.ebean.DB; import io.ebean.PagedList; @@ -15,6 +16,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + /** *

* 字典类型表 服务实现类 @@ -95,8 +98,8 @@ public Pager findPageBySpec(DictTypeParam param) { } qSysDictType.orderBy("create_time desc"); qSysDictType.setFirstRow((param.getPage() - 1) * param.getMaxRow()).setMaxRows(param.getMaxRow()); - PagedList pagedList = qSysDictType.findPagedList(); - return new Pager<>(pagedList.getList(), pagedList.getTotalCount()); + List pagedList = qSysDictType.asDto(SysDictTypeDto.class).findList(); + return new Pager<>(pagedList, qSysDictType.findCount()); } private SysDictType getEntity(DictTypeParam param) { From 5f97553dacd809454a1eced4480bed99cd21f0d1 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 6 Sep 2021 17:47:05 +0800 Subject: [PATCH 096/763] TDEngien storage module. --- .../iot/server/core/CoreModuleProvider.java | 27 ++- .../zeus/iot/server/core/analysis/Stream.java | 45 +++++ .../analysis/StreamAnnotationListener.java | 41 +++++ .../server/core/analysis/StreamProcessor.java | 14 ++ .../core/analysis/manual/history/History.java | 38 ++++ .../analysis/manual/history/UIntHistory.java | 38 ++++ .../core/analysis/manual/trends/Trends.java | 7 + .../analysis/manual/trends/UIntTrends.java | 7 + .../server/core/analysis/record/Record.java | 30 ++++ .../worker/RecordPersistentWorker.java | 38 ++++ .../worker/RecordStreamProcessor.java | 47 +++++ .../core/annotation/AnnotationListener.java | 30 ++++ .../core/annotation/AnnotationScan.java | 96 +++++++++++ .../zeus/iot/server/core/storage/DAO.java | 28 +++ .../iot/server/core/storage/IBatchDAO.java | 49 ++++++ .../iot/server/core/storage/IRecordDAO.java | 34 ++++ .../iot/server/core/storage/StorageDAO.java | 31 ++++ .../iot/server/core/storage/StorageData.java | 29 ++++ .../server/core/storage/StorageException.java | 30 ++++ .../server/core/storage/StorageModule.java | 42 +++++ .../iot/server/core/storage/model/Model.java | 36 ++++ .../iot/server/library/client/Client.java | 28 +++ .../library/client/ClientException.java | 29 ++++ .../healthcheck/DelegatedHealthChecker.java | 49 ++++++ .../client/healthcheck/HealthCheckable.java | 34 ++++ .../client/jdbc/JDBCClientException.java | 33 ++++ .../jdbc/hikaricp/JDBCHikariCPClient.java | 163 ++++++++++++++++++ .../library/client/request/InsertRequest.java | 21 +++ .../server-tdengine-plugin/pom.xml | 10 ++ .../storage/plugin/jdbc/SQLBuilder.java | 56 ++++++ .../storage/plugin/jdbc/SQLExecutor.java | 58 +++++++ .../jdbc/tdengine/TDEngineBatchDAO.java | 104 +++++++++++ .../tdengine/TDEngineDatabaseInstaller.java | 28 +++ .../jdbc/tdengine/TDEngineStorageConfig.java | 24 +++ .../tdengine/TDEngineStorageProvider.java | 79 +++++++++ .../jdbc/tdengine/dao/TDEngineRecordDAO.java | 26 +++ .../tdengine/dao/TDEngineSqlExecutor.java | 30 ++++ .../jdbc/tdengine/dao/TDEngineStorageDAO.java | 23 +++ 38 files changed, 1526 insertions(+), 6 deletions(-) create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/Stream.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamAnnotationListener.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamProcessor.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/trends/Trends.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/trends/UIntTrends.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/record/Record.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordPersistentWorker.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordStreamProcessor.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationListener.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationScan.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/DAO.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IBatchDAO.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IRecordDAO.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageDAO.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageData.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageException.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageModule.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/model/Model.java create mode 100644 iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/Client.java create mode 100644 iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/ClientException.java create mode 100644 iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/healthcheck/DelegatedHealthChecker.java create mode 100644 iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/healthcheck/HealthCheckable.java create mode 100644 iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/JDBCClientException.java create mode 100644 iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/hikaricp/JDBCHikariCPClient.java create mode 100644 iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/request/InsertRequest.java create mode 100644 iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLBuilder.java create mode 100644 iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java create mode 100644 iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineBatchDAO.java create mode 100644 iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java create mode 100644 iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageConfig.java create mode 100644 iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java create mode 100644 iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineRecordDAO.java create mode 100644 iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java create mode 100644 iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineStorageDAO.java diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java index 150d061a..bca950c4 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java @@ -2,6 +2,8 @@ import com.zmops.zeus.iot.server.action.ActionRouteIdentifier; import com.zmops.zeus.iot.server.action.HelloWorldAction; +import com.zmops.zeus.iot.server.core.analysis.StreamAnnotationListener; +import com.zmops.zeus.iot.server.core.annotation.AnnotationScan; import com.zmops.zeus.iot.server.core.camel.CamelContextHolderService; import com.zmops.zeus.iot.server.core.camel.ZabbixSenderComponent; import com.zmops.zeus.iot.server.core.eventbus.EventBusService; @@ -9,6 +11,7 @@ import com.zmops.zeus.iot.server.core.server.JettyHandlerRegisterImpl; import com.zmops.zeus.iot.server.core.servlet.DeviceTriggerActionHandler; import com.zmops.zeus.iot.server.core.servlet.HttpItemTrapperHandler; +import com.zmops.zeus.iot.server.core.storage.StorageException; import com.zmops.zeus.iot.server.eventbus.core.EventControllerFactory; import com.zmops.zeus.iot.server.eventbus.thread.ThreadPoolFactory; import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadCustomization; @@ -21,6 +24,8 @@ import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.model.ModelCamelContext; +import java.io.IOException; + /** * @author nantian created at 2021/8/16 22:26 */ @@ -33,10 +38,13 @@ public class CoreModuleProvider extends ModuleProvider { private ThreadPoolFactory threadPoolFactory; private EventControllerFactory eventControllerFactory; + private final AnnotationScan annotationScan; + public CoreModuleProvider() { super(); this.moduleConfig = new CoreModuleConfig(); + this.annotationScan = new AnnotationScan(); } @@ -61,6 +69,8 @@ public void prepare() throws ServiceNotProvidedException, ModuleStartException { threadPoolFactory = new ThreadPoolFactory(new ThreadCustomization(), new ThreadParameter()); eventControllerFactory = new EventControllerFactory(threadPoolFactory); + annotationScan.registerListener(new StreamAnnotationListener(getManager())); + JettyServerConfig jettyServerConfig = JettyServerConfig.builder() .host(moduleConfig.getRestHost()) .port(moduleConfig.getRestPort()) @@ -88,12 +98,9 @@ public void prepare() throws ServiceNotProvidedException, ModuleStartException { @Override public void start() throws ServiceNotProvidedException, ModuleStartException { try { - - jettyServer.start(); - camelContext.start(); - - } catch (Exception e) { - e.printStackTrace(); + annotationScan.scan(); + } catch (IOException | StorageException e) { + throw new ModuleStartException(e.getMessage(), e); } } @@ -103,6 +110,14 @@ public void shutdown() { @Override public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { + + try { + jettyServer.start(); + camelContext.start(); + } catch (Exception e) { + throw new ModuleStartException(e.getMessage(), e); + } + JettyHandlerRegister service = getManager().find(CoreModule.NAME).provider().getService(JettyHandlerRegister.class); service.addHandler(new HttpItemTrapperHandler()); service.addHandler(new DeviceTriggerActionHandler(getManager())); diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/Stream.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/Stream.java new file mode 100644 index 00000000..ab7754fc --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/Stream.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.core.analysis; + + +import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Stream annotation represents a metadata definition. + * See {@link RecordStreamProcessor} + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface Stream { + /** + * @return name of this stream definition. + */ + String name(); + + /** + * @return the stream processor type, {@link RecordStreamProcessor} for more details. + */ + Class processor(); +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamAnnotationListener.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamAnnotationListener.java new file mode 100644 index 00000000..de67faea --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamAnnotationListener.java @@ -0,0 +1,41 @@ +package com.zmops.zeus.iot.server.core.analysis; + +import com.zmops.zeus.iot.server.core.UnexpectedException; +import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; +import com.zmops.zeus.iot.server.core.annotation.AnnotationListener; +import com.zmops.zeus.iot.server.core.storage.StorageException; +import com.zmops.zeus.iot.server.library.module.ModuleDefineHolder; + +import java.lang.annotation.Annotation; + +/** + * @author nantian created at 2021/9/6 17:37 + */ +public class StreamAnnotationListener implements AnnotationListener { + + private final ModuleDefineHolder moduleDefineHolder; + + public StreamAnnotationListener(ModuleDefineHolder moduleDefineHolder) { + this.moduleDefineHolder = moduleDefineHolder; + } + + @Override + public Class annotation() { + return Stream.class; + } + + @Override + public void notify(Class aClass) throws StorageException { + if (aClass.isAnnotationPresent(Stream.class)) { + Stream stream = (Stream) aClass.getAnnotation(Stream.class); + + if (stream.processor().equals(RecordStreamProcessor.class)) { + RecordStreamProcessor.getInstance().create(moduleDefineHolder, stream, aClass); + } else { + throw new UnexpectedException("Unknown stream processor."); + } + } else { + throw new UnexpectedException("Stream annotation listener could only parse the class present stream annotation."); + } + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamProcessor.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamProcessor.java new file mode 100644 index 00000000..201ca9ea --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamProcessor.java @@ -0,0 +1,14 @@ +package com.zmops.zeus.iot.server.core.analysis; + +/** + * @author nantian created at 2021/9/6 16:49 + */ +public interface StreamProcessor { + + /** + * 写入数据 + * + * @param stream + */ + void in(STREAM stream); +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java new file mode 100644 index 00000000..f164a20c --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java @@ -0,0 +1,38 @@ +package com.zmops.zeus.iot.server.core.analysis.manual.history; + +import com.zmops.zeus.iot.server.core.analysis.Stream; +import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; +import com.zmops.zeus.iot.server.core.storage.StorageData; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; +import java.util.Map; + +/** + * @author nantian created at 2021/9/6 17:07 + */ +@Getter +@Setter +@Stream(name = "hitory", processor = RecordStreamProcessor.class) +public class History implements StorageData { + + private Integer itemid; + + private Long clock; + + private Long ns; + + private Long value; // 浮点数 + + private Map itemTags; + + private List hostGroups; + + @Override + public String id() { + return null; + } + + +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java new file mode 100644 index 00000000..f57bef81 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java @@ -0,0 +1,38 @@ +package com.zmops.zeus.iot.server.core.analysis.manual.history; + +import com.zmops.zeus.iot.server.core.analysis.Stream; +import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; +import com.zmops.zeus.iot.server.core.storage.StorageData; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; +import java.util.Map; + +/** + * @author nantian created at 2021/9/6 17:07 + */ +@Getter +@Setter +@Stream(name = "uint_hitory", processor = RecordStreamProcessor.class) +public class UIntHistory implements StorageData { + + private Integer itemid; + + private Long clock; + + private Long ns; + + private String value; // 浮点数 + + private Map itemTags; + + private List hostGroups; + + @Override + public String id() { + return null; + } + + +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/trends/Trends.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/trends/Trends.java new file mode 100644 index 00000000..c8fe7d04 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/trends/Trends.java @@ -0,0 +1,7 @@ +package com.zmops.zeus.iot.server.core.analysis.manual.trends; + +/** + * @author nantian created at 2021/9/6 17:32 + */ +public class Trends { +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/trends/UIntTrends.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/trends/UIntTrends.java new file mode 100644 index 00000000..446ae22d --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/trends/UIntTrends.java @@ -0,0 +1,7 @@ +package com.zmops.zeus.iot.server.core.analysis.manual.trends; + +/** + * @author nantian created at 2021/9/6 17:32 + */ +public class UIntTrends { +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/record/Record.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/record/Record.java new file mode 100644 index 00000000..ea22f781 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/record/Record.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.core.analysis.record; + +import com.zmops.zeus.iot.server.core.storage.StorageData; +import lombok.Getter; +import lombok.Setter; + +public abstract class Record implements StorageData { + + @Getter + @Setter + private long itemid; +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordPersistentWorker.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordPersistentWorker.java new file mode 100644 index 00000000..bdf393de --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordPersistentWorker.java @@ -0,0 +1,38 @@ +package com.zmops.zeus.iot.server.core.analysis.worker; + +import com.zmops.zeus.iot.server.core.analysis.record.Record; +import com.zmops.zeus.iot.server.core.storage.IBatchDAO; +import com.zmops.zeus.iot.server.core.storage.IRecordDAO; +import com.zmops.zeus.iot.server.core.storage.StorageModule; +import com.zmops.zeus.iot.server.core.storage.model.Model; +import com.zmops.zeus.iot.server.core.worker.AbstractWorker; +import com.zmops.zeus.iot.server.library.client.request.InsertRequest; +import com.zmops.zeus.iot.server.library.module.ModuleDefineHolder; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; + +@Slf4j +public class RecordPersistentWorker extends AbstractWorker { + + private final Model model; + private final IRecordDAO recordDAO; + private final IBatchDAO batchDAO; + + public RecordPersistentWorker(ModuleDefineHolder moduleDefineHolder, Model model, IRecordDAO recordDAO) { + super(moduleDefineHolder); + this.model = model; + this.recordDAO = recordDAO; + this.batchDAO = moduleDefineHolder.find(StorageModule.NAME).provider().getService(IBatchDAO.class); + } + + @Override + public void in(Record record) { + try { + InsertRequest insertRequest = recordDAO.prepareBatchInsert(model, record); + batchDAO.insert(insertRequest); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordStreamProcessor.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordStreamProcessor.java new file mode 100644 index 00000000..8be2b52a --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordStreamProcessor.java @@ -0,0 +1,47 @@ +package com.zmops.zeus.iot.server.core.analysis.worker; + +import com.zmops.zeus.iot.server.core.analysis.Stream; +import com.zmops.zeus.iot.server.core.analysis.StreamProcessor; +import com.zmops.zeus.iot.server.core.analysis.record.Record; +import com.zmops.zeus.iot.server.core.storage.IRecordDAO; +import com.zmops.zeus.iot.server.core.storage.StorageDAO; +import com.zmops.zeus.iot.server.core.storage.StorageModule; +import com.zmops.zeus.iot.server.core.storage.model.Model; +import com.zmops.zeus.iot.server.library.module.ModuleDefineHolder; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author nantian created at 2021/9/6 16:47 + */ +public class RecordStreamProcessor implements StreamProcessor { + + private final Map, RecordPersistentWorker> workers = new HashMap<>(); + + private final static RecordStreamProcessor PROCESSOR = new RecordStreamProcessor(); + + public static RecordStreamProcessor getInstance() { + return PROCESSOR; + } + + @Override + public void in(Record record) { + RecordPersistentWorker worker = workers.get(record.getClass()); + if (worker != null) { + worker.in(record); + } + } + + public void create(ModuleDefineHolder moduleDefineHolder, Stream stream, Class recordClass) { + + StorageDAO storageDAO = moduleDefineHolder.find(StorageModule.NAME).provider().getService(StorageDAO.class); + IRecordDAO recordDAO = storageDAO.newRecordDao(); + + Model model = new Model(stream.name()); + + RecordPersistentWorker persistentWorker = new RecordPersistentWorker(moduleDefineHolder, model, recordDAO); + + workers.put(recordClass, persistentWorker); + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationListener.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationListener.java new file mode 100644 index 00000000..155fcdbf --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationListener.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.core.annotation; + +import com.zmops.zeus.iot.server.core.storage.StorageException; + +import java.lang.annotation.Annotation; + +public interface AnnotationListener { + + Class annotation(); + + void notify(Class aClass) throws StorageException; +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationScan.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationScan.java new file mode 100644 index 00000000..4382947a --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationScan.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.core.annotation; + +import com.google.common.collect.ImmutableSet; +import com.google.common.reflect.ClassPath; +import com.zmops.zeus.iot.server.core.storage.StorageException; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.util.Comparator; +import java.util.LinkedList; +import java.util.List; + +/** + * Scan the annotation, and notify the listener(s) + */ +public class AnnotationScan { + + private final List listeners; + + public AnnotationScan() { + this.listeners = new LinkedList<>(); + } + + /** + * Register the callback listener + * + * @param listener to be called after class found w/ annotation + */ + public void registerListener(AnnotationListener listener) { + listeners.add(new AnnotationListenerCache(listener)); + } + + /** + * Begin to scan classes. + */ + public void scan() throws IOException, StorageException { + ClassPath classpath = ClassPath.from(this.getClass().getClassLoader()); + ImmutableSet classes = classpath.getTopLevelClassesRecursive("com.zmops.zeus.iot"); + for (ClassPath.ClassInfo classInfo : classes) { + Class aClass = classInfo.load(); + + for (AnnotationListenerCache listener : listeners) { + if (aClass.isAnnotationPresent(listener.annotation())) { + listener.addMatch(aClass); + } + } + } + + for (AnnotationListenerCache listener : listeners) { + listener.complete(); + } + } + + private class AnnotationListenerCache { + private AnnotationListener listener; + private List> matchedClass; + + private AnnotationListenerCache(AnnotationListener listener) { + this.listener = listener; + matchedClass = new LinkedList<>(); + } + + private Class annotation() { + return this.listener.annotation(); + } + + private void addMatch(Class aClass) { + matchedClass.add(aClass); + } + + private void complete() throws StorageException { + matchedClass.sort(Comparator.comparing(Class::getName)); + for (Class aClass : matchedClass) { + listener.notify(aClass); + } + } + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/DAO.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/DAO.java new file mode 100644 index 00000000..03fba9b8 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/DAO.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.core.storage; + + +import com.zmops.zeus.iot.server.library.module.Service; + +/** + * A specific interface for storage layer services. + */ +public interface DAO extends Service { +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IBatchDAO.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IBatchDAO.java new file mode 100644 index 00000000..5c1c6f42 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IBatchDAO.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.core.storage; + + +import com.zmops.zeus.iot.server.library.client.request.InsertRequest; +import com.zmops.zeus.iot.server.library.client.request.PrepareRequest; + +import java.util.List; + +/** + * IBatchDAO provides two modes of data persistence supported by most databases, including pure insert and batch hybrid + * insert/update. + */ +public interface IBatchDAO extends DAO { + /** + * Push data into the database in async mode. This method is driven by streaming process. This method doesn't + * request the data queryable immediately after the method finished. + * + * @param insertRequest data to insert. + */ + void insert(InsertRequest insertRequest); + + /** + * Push data collection into the database in async mode. This method is driven by streaming process. This method + * doesn't request the data queryable immediately after the method finished. + *

+ * The method requires thread safe. The OAP core would call this concurrently. + * + * @param prepareRequests data to insert or update. No delete happens in streaming mode. + */ + void flush(List prepareRequests); +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IRecordDAO.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IRecordDAO.java new file mode 100644 index 00000000..5aec851c --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IRecordDAO.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.core.storage; + + +import com.zmops.zeus.iot.server.core.analysis.record.Record; +import com.zmops.zeus.iot.server.core.storage.model.Model; +import com.zmops.zeus.iot.server.library.client.request.InsertRequest; + +import java.io.IOException; + +/** + * DAO specifically for {@link Record} implementations. + */ +public interface IRecordDAO extends DAO { + + InsertRequest prepareBatchInsert(Model model, Record record) throws IOException; +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageDAO.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageDAO.java new file mode 100644 index 00000000..bbc21ff7 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageDAO.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.core.storage; + +import com.zmops.zeus.iot.server.library.module.Service; + +/** + * StorageDAO is a DAO factory for storage layer. Provide the implementations of typical DAO interfaces. + */ +public interface StorageDAO extends Service { + +// IMetricsDAO newMetricsDao(StorageBuilder storageBuilder); + + IRecordDAO newRecordDao(); +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageData.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageData.java new file mode 100644 index 00000000..4f7bef74 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageData.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.core.storage; + +/** + * Any persistent entity should be an implementation of this interface. + */ +public interface StorageData { + /** + * @return the unique id used in any storage option. + */ + String id(); +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageException.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageException.java new file mode 100644 index 00000000..4cd73613 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageException.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.core.storage; + +public class StorageException extends Exception { + + public StorageException(String message) { + super(message); + } + + public StorageException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageModule.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageModule.java new file mode 100644 index 00000000..8a8bc83a --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageModule.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.core.storage; + +import com.zmops.zeus.iot.server.library.module.ModuleDefine; + +/** + * StorageModule provides the capabilities(services) to interact with the database. With different databases, this + * module could have different providers, such as currently, H2, MySQL, ES, TiDB. + */ +public class StorageModule extends ModuleDefine { + + public static final String NAME = "storage"; + + public StorageModule() { + super(NAME); + } + + @Override + public Class[] services() { + return new Class[]{ + IBatchDAO.class, + StorageDAO.class + }; + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/model/Model.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/model/Model.java new file mode 100644 index 00000000..eefe9a9a --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/model/Model.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.core.storage.model; + +import lombok.EqualsAndHashCode; +import lombok.Getter; + +/** + * The model definition of a logic entity. + */ +@Getter +@EqualsAndHashCode +public class Model { + + private final String name; + + public Model(final String name) { + this.name = name; + } +} diff --git a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/Client.java b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/Client.java new file mode 100644 index 00000000..d65ad5f3 --- /dev/null +++ b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/Client.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.library.client; + +import java.io.IOException; + +public interface Client { + + void connect() throws Exception; + + void shutdown() throws IOException; +} diff --git a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/ClientException.java b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/ClientException.java new file mode 100644 index 00000000..3b90fb73 --- /dev/null +++ b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/ClientException.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.library.client; + +public abstract class ClientException extends Exception { + public ClientException(String message) { + super(message); + } + + public ClientException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/healthcheck/DelegatedHealthChecker.java b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/healthcheck/DelegatedHealthChecker.java new file mode 100644 index 00000000..7723fdcf --- /dev/null +++ b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/healthcheck/DelegatedHealthChecker.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.library.client.healthcheck; + + +import com.zmops.zeus.iot.server.library.util.HealthChecker; + +import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; + +public class DelegatedHealthChecker implements HealthChecker { + + private final AtomicReference delegated = new AtomicReference<>(); + + @Override + public void health() { + Optional.ofNullable(delegated.get()).ifPresent(HealthChecker::health); + } + + @Override + public void unHealth(Throwable t) { + Optional.ofNullable(delegated.get()).ifPresent(d -> d.unHealth(t)); + } + + @Override + public void unHealth(String reason) { + Optional.ofNullable(delegated.get()).ifPresent(d -> d.unHealth(reason)); + } + + public void register(HealthChecker healthChecker) { + delegated.set(healthChecker); + } +} diff --git a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/healthcheck/HealthCheckable.java b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/healthcheck/HealthCheckable.java new file mode 100644 index 00000000..043eebe9 --- /dev/null +++ b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/healthcheck/HealthCheckable.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.library.client.healthcheck; + +import com.zmops.zeus.iot.server.library.util.HealthChecker; + +/** + * HealthCheckable indicate the client has the capacity of health check and need to register healthChecker. + */ +public interface HealthCheckable { + + /** + * Register health checker. + * + * @param healthChecker HealthChecker to be registered. + */ + void registerChecker(HealthChecker healthChecker); +} diff --git a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/JDBCClientException.java b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/JDBCClientException.java new file mode 100644 index 00000000..4c8866f5 --- /dev/null +++ b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/JDBCClientException.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.library.client.jdbc; + +import java.io.IOException; + +public class JDBCClientException extends IOException { + + public JDBCClientException(String message) { + super(message); + } + + public JDBCClientException(String message, Throwable cause) { + super(message, cause); + } +} + diff --git a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/hikaricp/JDBCHikariCPClient.java b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/hikaricp/JDBCHikariCPClient.java new file mode 100644 index 00000000..70f3abaf --- /dev/null +++ b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/hikaricp/JDBCHikariCPClient.java @@ -0,0 +1,163 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.library.client.jdbc.hikaricp; + + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import com.zmops.zeus.iot.server.library.client.Client; +import com.zmops.zeus.iot.server.library.client.healthcheck.DelegatedHealthChecker; +import com.zmops.zeus.iot.server.library.client.healthcheck.HealthCheckable; +import com.zmops.zeus.iot.server.library.client.jdbc.JDBCClientException; +import com.zmops.zeus.iot.server.library.util.HealthChecker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.*; +import java.util.Properties; + +/** + * JDBC Client uses HikariCP connection management lib to execute SQL. + */ +public class JDBCHikariCPClient implements Client, HealthCheckable { + private static final Logger LOGGER = LoggerFactory.getLogger(JDBCHikariCPClient.class); + + private final HikariConfig hikariConfig; + private final DelegatedHealthChecker healthChecker; + private HikariDataSource dataSource; + + public JDBCHikariCPClient(Properties properties) { + hikariConfig = new HikariConfig(properties); + this.healthChecker = new DelegatedHealthChecker(); + } + + @Override + public void connect() { + dataSource = new HikariDataSource(hikariConfig); + } + + @Override + public void shutdown() { + } + + /** + * Default getConnection is set in auto-commit. + */ + public Connection getConnection() throws JDBCClientException { + return getConnection(true); + } + + public Connection getTransactionConnection() throws JDBCClientException { + return getConnection(false); + } + + public Connection getConnection(boolean autoCommit) throws JDBCClientException { + try { + Connection connection = dataSource.getConnection(); + connection.setAutoCommit(autoCommit); + return connection; + } catch (SQLException e) { + throw new JDBCClientException(e.getMessage(), e); + } + } + + public void execute(Connection connection, String sql) throws JDBCClientException { + LOGGER.debug("execute sql: {}", sql); + try (Statement statement = connection.createStatement()) { + statement.execute(sql); + healthChecker.health(); + } catch (SQLException e) { + healthChecker.unHealth(e); + throw new JDBCClientException(e.getMessage(), e); + } + } + + public int executeUpdate(Connection connection, String sql, Object... params) throws JDBCClientException { + LOGGER.debug("execute query with result: {}", sql); + int result; + PreparedStatement statement = null; + try { + statement = connection.prepareStatement(sql); + setStatementParam(statement, params); + result = statement.executeUpdate(); + statement.closeOnCompletion(); + healthChecker.health(); + } catch (SQLException e) { + if (statement != null) { + try { + statement.close(); + } catch (SQLException e1) { + } + } + healthChecker.unHealth(e); + throw new JDBCClientException(e.getMessage(), e); + } + + return result; + } + + public ResultSet executeQuery(Connection connection, String sql, Object... params) throws JDBCClientException { + LOGGER.debug("execute query with result: {}", sql); + ResultSet rs; + PreparedStatement statement = null; + try { + statement = connection.prepareStatement(sql); + setStatementParam(statement, params); + rs = statement.executeQuery(); + statement.closeOnCompletion(); + healthChecker.health(); + } catch (SQLException e) { + if (statement != null) { + try { + statement.close(); + } catch (SQLException e1) { + } + } + healthChecker.unHealth(e); + throw new JDBCClientException(e.getMessage(), e); + } + + return rs; + } + + private void setStatementParam(PreparedStatement statement, + Object[] params) throws SQLException, JDBCClientException { + if (params != null) { + for (int i = 0; i < params.length; i++) { + Object param = params[i]; + if (param instanceof String) { + statement.setString(i + 1, (String) param); + } else if (param instanceof Integer) { + statement.setInt(i + 1, (int) param); + } else if (param instanceof Double) { + statement.setDouble(i + 1, (double) param); + } else if (param instanceof Long) { + statement.setLong(i + 1, (long) param); + } else { + throw new JDBCClientException("Unsupported data type, type=" + param.getClass().getName()); + } + } + } + } + + @Override + public void registerChecker(HealthChecker healthChecker) { + this.healthChecker.register(healthChecker); + } +} diff --git a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/request/InsertRequest.java b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/request/InsertRequest.java new file mode 100644 index 00000000..720db6a7 --- /dev/null +++ b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/request/InsertRequest.java @@ -0,0 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.library.client.request; + +public interface InsertRequest extends PrepareRequest { +} diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml index 5f98093f..5573d5c3 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml @@ -22,6 +22,16 @@ taos-jdbcdriver 2.0.30 + + com.zmops + library-module + 1.0-beta + + + com.zmops + server-core + 1.0-beta + \ No newline at end of file diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLBuilder.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLBuilder.java new file mode 100644 index 00000000..1538d792 --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLBuilder.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.storage.plugin.jdbc; + +/** + * SQLBuilder + */ +public class SQLBuilder { + private static String LINE_END = System.lineSeparator(); + + private StringBuilder text; + + public SQLBuilder() { + this.text = new StringBuilder(); + } + + public SQLBuilder(String initLine) { + this(); + this.appendLine(initLine); + } + + public SQLBuilder append(String fragment) { + text.append(fragment); + return this; + } + + public SQLBuilder appendLine(String line) { + text.append(line).append(LINE_END); + return this; + } + + public String toStringInNewLine() { + return LINE_END + toString(); + } + + @Override + public String toString() { + return text.toString(); + } +} diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java new file mode 100644 index 00000000..d9e62bdc --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.zmops.zeus.iot.server.storage.plugin.jdbc; + +import com.zmops.zeus.iot.server.library.client.request.InsertRequest; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.List; + +/** + * A SQL executor. + */ +public class SQLExecutor implements InsertRequest { + + private static final Logger LOGGER = LoggerFactory.getLogger(SQLExecutor.class); + + private final String sql; + private final List param; + + public SQLExecutor(String sql, List param) { + this.sql = sql; + this.param = param; + } + + public void invoke(Connection connection) throws SQLException { + PreparedStatement preparedStatement = connection.prepareStatement(sql); + + for (int i = 0; i < param.size(); i++) { + preparedStatement.setObject(i + 1, param.get(i)); + } + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("execute sql in batch: {}, parameters: {}", sql, param); + } + preparedStatement.execute(); + } +} diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineBatchDAO.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineBatchDAO.java new file mode 100644 index 00000000..63f2e432 --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineBatchDAO.java @@ -0,0 +1,104 @@ +package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine; + +import com.zmops.zeus.iot.server.core.UnexpectedException; +import com.zmops.zeus.iot.server.core.storage.IBatchDAO; +import com.zmops.zeus.iot.server.datacarrier.DataCarrier; +import com.zmops.zeus.iot.server.datacarrier.consumer.BulkConsumePool; +import com.zmops.zeus.iot.server.datacarrier.consumer.ConsumerPoolFactory; +import com.zmops.zeus.iot.server.datacarrier.consumer.IConsumer; +import com.zmops.zeus.iot.server.library.client.jdbc.JDBCClientException; +import com.zmops.zeus.iot.server.library.client.jdbc.hikaricp.JDBCHikariCPClient; +import com.zmops.zeus.iot.server.library.client.request.InsertRequest; +import com.zmops.zeus.iot.server.library.client.request.PrepareRequest; +import com.zmops.zeus.iot.server.library.util.CollectionUtils; +import com.zmops.zeus.iot.server.storage.plugin.jdbc.SQLExecutor; +import lombok.extern.slf4j.Slf4j; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.List; + +/** + * @author nantian created at 2021/9/4 0:31 + */ +@Slf4j +public class TDEngineBatchDAO implements IBatchDAO { + + private final JDBCHikariCPClient tdengineClient; + private final DataCarrier dataCarrier; + + public TDEngineBatchDAO(JDBCHikariCPClient client) { + this.tdengineClient = client; + + String name = "TDENGINE_ASYNCHRONOUS_BATCH_PERSISTENT"; + + BulkConsumePool.Creator creator = new BulkConsumePool.Creator(name, 1, 20); + try { + ConsumerPoolFactory.INSTANCE.createIfAbsent(name, creator); + } catch (Exception e) { + throw new UnexpectedException(e.getMessage(), e); + } + + this.dataCarrier = new DataCarrier<>(1, 10000); + this.dataCarrier.consume(ConsumerPoolFactory.INSTANCE.get(name), new TDEngineBatchConsumer(this)); + } + + + @Override + public void flush(List prepareRequests) { + if (CollectionUtils.isEmpty(prepareRequests)) { + return; + } + + if (log.isDebugEnabled()) { + log.debug("batch sql statements execute, data size: {}", prepareRequests.size()); + } + + try (Connection connection = tdengineClient.getConnection()) { + for (PrepareRequest prepareRequest : prepareRequests) { + try { + SQLExecutor sqlExecutor = (SQLExecutor) prepareRequest; + sqlExecutor.invoke(connection); + } catch (SQLException e) { + // Just avoid one execution failure makes the rest of batch failure. + log.error(e.getMessage(), e); + } + } + } catch (SQLException | JDBCClientException e) { + log.error(e.getMessage(), e); + } + } + + @Override + public void insert(InsertRequest insertRequest) { + this.dataCarrier.produce(insertRequest); + } + + private static class TDEngineBatchConsumer implements IConsumer { + + private final TDEngineBatchDAO tdengineBatchDAO; + + private TDEngineBatchConsumer(TDEngineBatchDAO h2BatchDAO) { + this.tdengineBatchDAO = h2BatchDAO; + } + + @Override + public void init() { + + } + + @Override + public void consume(List prepareRequests) { + tdengineBatchDAO.flush(prepareRequests); + } + + @Override + public void onError(List prepareRequests, Throwable t) { + log.error(t.getMessage(), t); + } + + @Override + public void onExit() { + } + } +} diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java new file mode 100644 index 00000000..0721c772 --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java @@ -0,0 +1,28 @@ +package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine; + +import com.zmops.zeus.iot.server.library.client.Client; +import com.zmops.zeus.iot.server.library.module.ModuleManager; + +/** + * @author nantian created at 2021/9/4 1:16 + */ +public class TDEngineDatabaseInstaller { + + protected final Client client; + private final ModuleManager moduleManager; + private final TDEngineStorageConfig config; + + public TDEngineDatabaseInstaller(Client client, + ModuleManager moduleManager, + TDEngineStorageConfig config) { + this.config = config; + this.client = client; + this.moduleManager = moduleManager; + } + + + protected void createDatabase() { + + } + +} diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageConfig.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageConfig.java new file mode 100644 index 00000000..f18b8ab8 --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageConfig.java @@ -0,0 +1,24 @@ +package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine; + +import com.zmops.zeus.iot.server.library.module.ModuleConfig; +import lombok.Getter; +import lombok.Setter; + +/** + * @author nantian created at 2021/9/3 23:40 + */ +@Setter +@Getter +public class TDEngineStorageConfig extends ModuleConfig { + + private final String driver = "com.taosdata.jdbc.TSDBDriver"; + + private String url = ""; + private String user = ""; + private String password = ""; + + private int dataKeep = 365; //数据保留天数 + private int oneFileDays = 10; // 每多少天一个数据文件 + private int memoryBlocks = 6; // 内存块数 + private int dataUpdate = 1; // 是否允许更新数据,1 允许 +} diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java new file mode 100644 index 00000000..69617f9e --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java @@ -0,0 +1,79 @@ +package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine; + +import com.zmops.zeus.iot.server.core.CoreModule; +import com.zmops.zeus.iot.server.core.storage.IBatchDAO; +import com.zmops.zeus.iot.server.core.storage.StorageModule; +import com.zmops.zeus.iot.server.library.client.jdbc.hikaricp.JDBCHikariCPClient; +import com.zmops.zeus.iot.server.library.module.*; +import com.zmops.zeus.iot.server.telemetry.TelemetryModule; +import com.zmops.zeus.iot.server.telemetry.api.HealthCheckMetrics; +import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; +import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; + +import java.util.Properties; + +/** + * @author nantian created at 2021/9/3 23:39 + */ +public class TDEngineStorageProvider extends ModuleProvider { + + private TDEngineStorageConfig config; + private JDBCHikariCPClient client; + + public TDEngineStorageProvider(TDEngineStorageConfig config) { + this.config = config; + } + + @Override + public String name() { + return "tdengine"; + } + + @Override + public Class module() { + return StorageModule.class; + } + + @Override + public ModuleConfig createConfigBeanIfAbsent() { + return null; + } + + @Override + public void prepare() throws ServiceNotProvidedException, ModuleStartException { + + Properties settings = new Properties(); + settings.setProperty("dataSourceClassName", config.getDriver()); + settings.setProperty("dataSource.url", config.getUrl()); + settings.setProperty("dataSource.user", config.getUser()); + settings.setProperty("dataSource.password", config.getPassword()); + client = new JDBCHikariCPClient(settings); + + this.registerServiceImplementation(IBatchDAO.class, new TDEngineBatchDAO(client)); + } + + @Override + public void start() throws ServiceNotProvidedException, ModuleStartException { + + MetricsCreator metricCreator = getManager().find(TelemetryModule.NAME).provider().getService(MetricsCreator.class); + HealthCheckMetrics healthChecker = metricCreator.createHealthCheckerGauge("storage_tdengine", MetricsTag.EMPTY_KEY, MetricsTag.EMPTY_VALUE); + + client.registerChecker(healthChecker); + client.connect(); + + TDEngineDatabaseInstaller installer = new TDEngineDatabaseInstaller(client, getManager(), config); + installer.createDatabase(); +// getManager().find(CoreModule.NAME).provider().getService(ModelCreator.class).addModelListener(installer); + + } + + @Override + public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { + + } + + @Override + public String[] requiredModules() { + return new String[]{CoreModule.NAME}; + } +} diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineRecordDAO.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineRecordDAO.java new file mode 100644 index 00000000..9339f5ef --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineRecordDAO.java @@ -0,0 +1,26 @@ +package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine.dao; + +import com.zmops.zeus.iot.server.core.analysis.record.Record; +import com.zmops.zeus.iot.server.core.storage.IRecordDAO; +import com.zmops.zeus.iot.server.core.storage.model.Model; +import com.zmops.zeus.iot.server.library.client.jdbc.hikaricp.JDBCHikariCPClient; +import com.zmops.zeus.iot.server.library.client.request.InsertRequest; + +import java.io.IOException; + +/** + * @author nantian created at 2021/9/5 0:27 + */ +public class TDEngineRecordDAO extends TDEngineSqlExecutor implements IRecordDAO { + + private final JDBCHikariCPClient jdbcClient; + + public TDEngineRecordDAO(JDBCHikariCPClient jdbcClient) { + this.jdbcClient = jdbcClient; + } + + @Override + public InsertRequest prepareBatchInsert(Model model, Record record) throws IOException { + return getInsertExecutor(model.getName(), record); + } +} diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java new file mode 100644 index 00000000..9a420563 --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java @@ -0,0 +1,30 @@ +package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine.dao; + +import com.zmops.zeus.iot.server.core.analysis.record.Record; +import com.zmops.zeus.iot.server.core.storage.StorageData; +import com.zmops.zeus.iot.server.storage.plugin.jdbc.SQLBuilder; +import com.zmops.zeus.iot.server.storage.plugin.jdbc.SQLExecutor; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author nantian created at 2021/9/5 0:29 + */ + +@Slf4j +public class TDEngineSqlExecutor { + + + protected SQLExecutor getInsertExecutor(String modelName, T metrics) { + + SQLBuilder sqlBuilder = new SQLBuilder("INSERT INTO " + modelName + " VALUES"); + + List param = new ArrayList<>(); + + return new SQLExecutor(sqlBuilder.toString(), param); + } + +} diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineStorageDAO.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineStorageDAO.java new file mode 100644 index 00000000..2dd64348 --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineStorageDAO.java @@ -0,0 +1,23 @@ +package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine.dao; + +import com.zmops.zeus.iot.server.core.storage.IRecordDAO; +import com.zmops.zeus.iot.server.core.storage.StorageDAO; +import com.zmops.zeus.iot.server.library.client.jdbc.hikaricp.JDBCHikariCPClient; +import com.zmops.zeus.iot.server.library.module.ModuleManager; +import lombok.RequiredArgsConstructor; + +/** + * @author nantian created at 2021/9/6 16:33 + */ +@RequiredArgsConstructor +public class TDEngineStorageDAO implements StorageDAO { + + private final ModuleManager manager; + private final JDBCHikariCPClient client; + + + @Override + public IRecordDAO newRecordDao() { + return new TDEngineRecordDAO(client); + } +} From 59f7bcdf2e3d31be1183206f8d7c4ce0a397abb0 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 6 Sep 2021 19:05:38 +0800 Subject: [PATCH 097/763] TDEngine storage module edit. --- iot-server/server-bootstrap/pom.xml | 13 ++++++++++++ .../src/main/resources/application.yml | 9 +++++++++ ...eus.iot.server.library.module.ModuleDefine | 1 + .../server-library/library-client/pom.xml | 12 +++++++++++ .../jdbc/hikaricp/JDBCHikariCPClient.java | 15 +++++++++----- .../tdengine/TDEngineStorageProvider.java | 15 ++++++++------ ...s.iot.server.library.module.ModuleProvider | 20 +++++++++++++++++++ 7 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 iot-server/server-storage-plugin/server-tdengine-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider diff --git a/iot-server/server-bootstrap/pom.xml b/iot-server/server-bootstrap/pom.xml index 27b4cbb8..534cf6fb 100644 --- a/iot-server/server-bootstrap/pom.xml +++ b/iot-server/server-bootstrap/pom.xml @@ -63,6 +63,19 @@ mqtt-receiver-plugin ${project.version} + + + org.apache.camel + camel-zabbix-agent + ${camel.version} + + + + com.zmops + server-tdengine-plugin + 1.0-beta + + diff --git a/iot-server/server-bootstrap/src/main/resources/application.yml b/iot-server/server-bootstrap/src/main/resources/application.yml index 23685945..21925dc3 100644 --- a/iot-server/server-bootstrap/src/main/resources/application.yml +++ b/iot-server/server-bootstrap/src/main/resources/application.yml @@ -42,6 +42,15 @@ core: restAcceptQueueSize: ${ZS_CORE_REST_JETTY_QUEUE_SIZE:0} httpMaxRequestHeaderSize: ${ZS_CORE_HTTP_MAX_REQUEST_HEADER_SIZE:8192} +storage: + selector: ${SW_STORAGE:tdengine} + tdengine: + url: ${ZS_STORAGE_TDENGINE_URL:jdbc:TAOS://zmops-zabbix:6030/test} + user: ${ZS_STORAGE_TDENGINE_USER:root} + password: ${ZS_STORAGE_TDENGINE_PASSWORD:taosdata} + + + # 健康检查 health-checker: selector: ${ZS_HEALTH_CHECKER:default} diff --git a/iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine b/iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine index 4e0077b4..02f80702 100644 --- a/iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine +++ b/iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine @@ -16,4 +16,5 @@ # # +com.zmops.zeus.iot.server.core.storage.StorageModule com.zmops.zeus.iot.server.core.CoreModule diff --git a/iot-server/server-library/library-client/pom.xml b/iot-server/server-library/library-client/pom.xml index 0ee97fd6..11216847 100644 --- a/iot-server/server-library/library-client/pom.xml +++ b/iot-server/server-library/library-client/pom.xml @@ -10,6 +10,18 @@ 4.0.0 library-client + + + com.zmops + library-util + 1.0-beta + + + com.zaxxer + HikariCP + 3.1.0 + + 8 diff --git a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/hikaricp/JDBCHikariCPClient.java b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/hikaricp/JDBCHikariCPClient.java index 70f3abaf..770242f2 100644 --- a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/hikaricp/JDBCHikariCPClient.java +++ b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/hikaricp/JDBCHikariCPClient.java @@ -38,12 +38,17 @@ public class JDBCHikariCPClient implements Client, HealthCheckable { private static final Logger LOGGER = LoggerFactory.getLogger(JDBCHikariCPClient.class); - private final HikariConfig hikariConfig; + private final HikariConfig hikariConfig; private final DelegatedHealthChecker healthChecker; - private HikariDataSource dataSource; + private HikariDataSource dataSource; public JDBCHikariCPClient(Properties properties) { - hikariConfig = new HikariConfig(properties); + hikariConfig = new HikariConfig(); + hikariConfig.setJdbcUrl(properties.getProperty("dataSource.url")); + hikariConfig.setUsername(properties.getProperty("dataSource.user")); + hikariConfig.setPassword(properties.getProperty("dataSource.password")); + hikariConfig.setConnectionTestQuery("select server_status()"); + this.healthChecker = new DelegatedHealthChecker(); } @@ -90,7 +95,7 @@ public void execute(Connection connection, String sql) throws JDBCClientExceptio public int executeUpdate(Connection connection, String sql, Object... params) throws JDBCClientException { LOGGER.debug("execute query with result: {}", sql); - int result; + int result; PreparedStatement statement = null; try { statement = connection.prepareStatement(sql); @@ -114,7 +119,7 @@ public int executeUpdate(Connection connection, String sql, Object... params) th public ResultSet executeQuery(Connection connection, String sql, Object... params) throws JDBCClientException { LOGGER.debug("execute query with result: {}", sql); - ResultSet rs; + ResultSet rs; PreparedStatement statement = null; try { statement = connection.prepareStatement(sql); diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java index 69617f9e..b3cb4453 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java @@ -2,9 +2,11 @@ import com.zmops.zeus.iot.server.core.CoreModule; import com.zmops.zeus.iot.server.core.storage.IBatchDAO; +import com.zmops.zeus.iot.server.core.storage.StorageDAO; import com.zmops.zeus.iot.server.core.storage.StorageModule; import com.zmops.zeus.iot.server.library.client.jdbc.hikaricp.JDBCHikariCPClient; import com.zmops.zeus.iot.server.library.module.*; +import com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine.dao.TDEngineStorageDAO; import com.zmops.zeus.iot.server.telemetry.TelemetryModule; import com.zmops.zeus.iot.server.telemetry.api.HealthCheckMetrics; import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; @@ -17,11 +19,11 @@ */ public class TDEngineStorageProvider extends ModuleProvider { - private TDEngineStorageConfig config; - private JDBCHikariCPClient client; + private final TDEngineStorageConfig config; + private JDBCHikariCPClient client; - public TDEngineStorageProvider(TDEngineStorageConfig config) { - this.config = config; + public TDEngineStorageProvider() { + this.config = new TDEngineStorageConfig(); } @Override @@ -36,7 +38,7 @@ public Class module() { @Override public ModuleConfig createConfigBeanIfAbsent() { - return null; + return config; } @Override @@ -50,12 +52,13 @@ public void prepare() throws ServiceNotProvidedException, ModuleStartException { client = new JDBCHikariCPClient(settings); this.registerServiceImplementation(IBatchDAO.class, new TDEngineBatchDAO(client)); + this.registerServiceImplementation(StorageDAO.class, new TDEngineStorageDAO(getManager(), client)); } @Override public void start() throws ServiceNotProvidedException, ModuleStartException { - MetricsCreator metricCreator = getManager().find(TelemetryModule.NAME).provider().getService(MetricsCreator.class); + MetricsCreator metricCreator = getManager().find(TelemetryModule.NAME).provider().getService(MetricsCreator.class); HealthCheckMetrics healthChecker = metricCreator.createHealthCheckerGauge("storage_tdengine", MetricsTag.EMPTY_KEY, MetricsTag.EMPTY_VALUE); client.registerChecker(healthChecker); diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider new file mode 100644 index 00000000..4f238716 --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider @@ -0,0 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# + + +com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine.TDEngineStorageProvider \ No newline at end of file From 81e9b4c1d797d16eb24e9bb9b501f81e80fffc94 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 6 Sep 2021 21:19:06 +0800 Subject: [PATCH 098/763] zabbix history data flush. --- .../src/main/resources/application.yml | 3 +-- .../zeus/iot/server/core/CoreModuleProvider.java | 2 ++ .../core/analysis/manual/history/History.java | 15 +++++++++------ .../core/analysis/manual/history/UIntHistory.java | 13 ++++++++----- .../iot/server/core/analysis/record/Record.java | 5 ++++- 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/iot-server/server-bootstrap/src/main/resources/application.yml b/iot-server/server-bootstrap/src/main/resources/application.yml index 21925dc3..4f68df85 100644 --- a/iot-server/server-bootstrap/src/main/resources/application.yml +++ b/iot-server/server-bootstrap/src/main/resources/application.yml @@ -45,12 +45,11 @@ core: storage: selector: ${SW_STORAGE:tdengine} tdengine: - url: ${ZS_STORAGE_TDENGINE_URL:jdbc:TAOS://zmops-zabbix:6030/test} + url: ${ZS_STORAGE_TDENGINE_URL:jdbc:TAOS://192.168.1.1:6030/zeus_data} # TDEngine jdbcUrl user: ${ZS_STORAGE_TDENGINE_USER:root} password: ${ZS_STORAGE_TDENGINE_PASSWORD:taosdata} - # 健康检查 health-checker: selector: ${ZS_HEALTH_CHECKER:default} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java index bca950c4..22c40d9d 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java @@ -9,6 +9,7 @@ import com.zmops.zeus.iot.server.core.eventbus.EventBusService; import com.zmops.zeus.iot.server.core.server.JettyHandlerRegister; import com.zmops.zeus.iot.server.core.server.JettyHandlerRegisterImpl; +import com.zmops.zeus.iot.server.core.servlet.DataTransferHandler; import com.zmops.zeus.iot.server.core.servlet.DeviceTriggerActionHandler; import com.zmops.zeus.iot.server.core.servlet.HttpItemTrapperHandler; import com.zmops.zeus.iot.server.core.storage.StorageException; @@ -121,6 +122,7 @@ public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleSta JettyHandlerRegister service = getManager().find(CoreModule.NAME).provider().getService(JettyHandlerRegister.class); service.addHandler(new HttpItemTrapperHandler()); service.addHandler(new DeviceTriggerActionHandler(getManager())); + service.addHandler(new DataTransferHandler()); // ### 可以自定义添加 Action 的动作异步处理,指定 ID diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java index f164a20c..2d139b7c 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java @@ -1,6 +1,7 @@ package com.zmops.zeus.iot.server.core.analysis.manual.history; import com.zmops.zeus.iot.server.core.analysis.Stream; +import com.zmops.zeus.iot.server.core.analysis.record.Record; import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; import com.zmops.zeus.iot.server.core.storage.StorageData; import lombok.Getter; @@ -14,16 +15,14 @@ */ @Getter @Setter -@Stream(name = "hitory", processor = RecordStreamProcessor.class) -public class History implements StorageData { - - private Integer itemid; +@Stream(name = "history", processor = RecordStreamProcessor.class) +public class History extends Record { private Long clock; private Long ns; - private Long value; // 浮点数 + private String value; // 浮点数 private Map itemTags; @@ -34,5 +33,9 @@ public String id() { return null; } - + @Override + public void setValue(String value, Long clock) { + this.value = value; + this.clock = clock; + } } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java index f57bef81..16d9891b 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java @@ -1,8 +1,9 @@ package com.zmops.zeus.iot.server.core.analysis.manual.history; import com.zmops.zeus.iot.server.core.analysis.Stream; +import com.zmops.zeus.iot.server.core.analysis.record.Record; import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; -import com.zmops.zeus.iot.server.core.storage.StorageData; + import lombok.Getter; import lombok.Setter; @@ -15,9 +16,7 @@ @Getter @Setter @Stream(name = "uint_hitory", processor = RecordStreamProcessor.class) -public class UIntHistory implements StorageData { - - private Integer itemid; +public class UIntHistory extends Record { private Long clock; @@ -34,5 +33,9 @@ public String id() { return null; } - + @Override + public void setValue(String value, Long clock) { + this.value = value; + this.clock = clock; + } } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/record/Record.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/record/Record.java index ea22f781..20c06c30 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/record/Record.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/record/Record.java @@ -26,5 +26,8 @@ public abstract class Record implements StorageData { @Getter @Setter - private long itemid; + private Integer itemid; + + + public abstract void setValue(String value, Long clock); } From f51d22e4f2da2d918f34f2995bf4998a014bb836 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 6 Sep 2021 22:05:29 +0800 Subject: [PATCH 099/763] edit record setValue method. --- .../iot/server/core/analysis/manual/history/History.java | 5 ++++- .../iot/server/core/analysis/manual/history/UIntHistory.java | 5 ++++- .../zmops/zeus/iot/server/core/analysis/record/Record.java | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java index 2d139b7c..9d50da16 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java @@ -24,6 +24,8 @@ public class History extends Record { private String value; // 浮点数 + private String deviceId; // host + private Map itemTags; private List hostGroups; @@ -34,7 +36,8 @@ public String id() { } @Override - public void setValue(String value, Long clock) { + public void setValue(String deviceId,String value, Long clock) { + this.deviceId = deviceId; this.value = value; this.clock = clock; } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java index 16d9891b..c72a4ec6 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java @@ -24,6 +24,8 @@ public class UIntHistory extends Record { private String value; // 浮点数 + private String deviceId; + private Map itemTags; private List hostGroups; @@ -34,7 +36,8 @@ public String id() { } @Override - public void setValue(String value, Long clock) { + public void setValue(String deviceId, String value, Long clock) { + this.deviceId = deviceId; this.value = value; this.clock = clock; } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/record/Record.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/record/Record.java index 20c06c30..5dcdcf73 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/record/Record.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/record/Record.java @@ -29,5 +29,5 @@ public abstract class Record implements StorageData { private Integer itemid; - public abstract void setValue(String value, Long clock); + public abstract void setValue(String deviceId, String value, Long clock); } From c300b8d1944fab036c27636be83f7cd6d3f81ee7 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 6 Sep 2021 22:06:55 +0800 Subject: [PATCH 100/763] zeus_transfer http post data entry. --- .../core/servlet/DataTransferHandler.java | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java new file mode 100644 index 00000000..5e636e50 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java @@ -0,0 +1,91 @@ +package com.zmops.zeus.iot.server.core.servlet; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.zmops.zeus.iot.server.core.analysis.manual.history.History; +import com.zmops.zeus.iot.server.core.analysis.manual.history.UIntHistory; +import com.zmops.zeus.iot.server.core.analysis.record.Record; +import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; +import com.zmops.zeus.iot.server.library.server.jetty.ArgumentsParseException; +import com.zmops.zeus.iot.server.library.server.jetty.JettyJsonHandler; +import lombok.Getter; +import lombok.Setter; + +import javax.servlet.http.HttpServletRequest; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.Map; +import java.util.zip.GZIPInputStream; + +/** + * @author nantian created at 2021/9/2 12:58 + */ +public class DataTransferHandler extends JettyJsonHandler { + + private final Gson gson = new Gson(); + + @Override + public String pathSpec() { + return "/zabbix/data-transfer"; + } + + /** + * 接收来自 zeus_transfer 数据, 写入时序库 + * + * @param req request + * @return NULL + * @throws ArgumentsParseException + * @throws IOException + */ + @Override + protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException, IOException { + GZIPInputStream gzin = new GZIPInputStream(req.getInputStream()); + BufferedReader reader = new BufferedReader(new InputStreamReader(gzin)); + + String line; + while ((line = reader.readLine()) != null) { + insert(line); + } + + return null; + } + + private void insert(String itemRecord) { + ItemValue itemValue = gson.fromJson(itemRecord, ItemValue.class); + + Record record; + + if (itemValue.getType() == 3) { //uint + record = new UIntHistory(); + } else { + record = new History(); + } + + record.setItemid(itemValue.itemid); + record.setValue(itemValue.getHost().get("host"), itemValue.value, itemValue.clock); + + RecordStreamProcessor.getInstance().in(record); + } + + + @Setter + @Getter + static class ItemValue { + + private Integer type; + + private String name; + + private Long clock; + + private Integer itemid; + + private Long ns; + + private String value; + + private Map host; + } +} From e3fe2801361a4f714f44535e687e22e0800867ad Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 7 Sep 2021 09:15:53 +0800 Subject: [PATCH 101/763] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zmops/iot/web/product/service/work/SaveProdAttrWorker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java index a5f18daf..1b8ca466 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java @@ -32,7 +32,7 @@ public Boolean action(ProductAttr productAttr, Map> String prodId = productAttr.getProductId(); - List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Integer.parseInt(prodId)).findSingleAttributeList(); + List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); List productAttributeList = new ArrayList<>(); From ab677f316df9fc8531b5a00d6ef3744323d89fa2 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 7 Sep 2021 09:44:39 +0800 Subject: [PATCH 102/763] zabbix history write to TDEngine. --- .../core/analysis/manual/history/History.java | 6 +-- .../analysis/manual/history/UIntHistory.java | 6 +-- .../core/servlet/DataTransferHandler.java | 6 ++- .../iot/server/core/storage/StorageData.java | 2 +- .../storage/plugin/jdbc/SQLExecutor.java | 2 + .../jdbc/tdengine/TDEngineBatchDAO.java | 41 ++++++++++++++----- .../tdengine/TDEngineDatabaseInstaller.java | 28 +++++++++++-- .../tdengine/TDEngineStorageProvider.java | 8 +++- .../tdengine/dao/TDEngineSqlExecutor.java | 19 +++++++-- 9 files changed, 91 insertions(+), 27 deletions(-) diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java index 9d50da16..1ccf63d5 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java @@ -31,12 +31,12 @@ public class History extends Record { private List hostGroups; @Override - public String id() { - return null; + public Integer itemid() { + return getItemid(); } @Override - public void setValue(String deviceId,String value, Long clock) { + public void setValue(String deviceId, String value, Long clock) { this.deviceId = deviceId; this.value = value; this.clock = clock; diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java index c72a4ec6..883114a5 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java @@ -15,7 +15,7 @@ */ @Getter @Setter -@Stream(name = "uint_hitory", processor = RecordStreamProcessor.class) +@Stream(name = "history_uint", processor = RecordStreamProcessor.class) public class UIntHistory extends Record { private Long clock; @@ -31,8 +31,8 @@ public class UIntHistory extends Record { private List hostGroups; @Override - public String id() { - return null; + public Integer itemid() { + return getItemid(); } @Override diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java index 5e636e50..abfc5709 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java @@ -64,7 +64,7 @@ record = new History(); } record.setItemid(itemValue.itemid); - record.setValue(itemValue.getHost().get("host"), itemValue.value, itemValue.clock); + record.setValue(itemValue.getHost().get("host"), itemValue.value, itemValue.getTimestamp()); RecordStreamProcessor.getInstance().in(record); } @@ -87,5 +87,9 @@ static class ItemValue { private String value; private Map host; + + public Long getTimestamp() { + return Long.valueOf(clock + String.format("%09d", ns).substring(0, 3)); + } } } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageData.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageData.java index 4f7bef74..9c4ab518 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageData.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageData.java @@ -25,5 +25,5 @@ public interface StorageData { /** * @return the unique id used in any storage option. */ - String id(); + Integer itemid(); } diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java index d9e62bdc..1e6931ad 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java @@ -20,6 +20,7 @@ import com.zmops.zeus.iot.server.library.client.request.InsertRequest; +import lombok.Getter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,6 +36,7 @@ public class SQLExecutor implements InsertRequest { private static final Logger LOGGER = LoggerFactory.getLogger(SQLExecutor.class); + @Getter private final String sql; private final List param; diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineBatchDAO.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineBatchDAO.java index 63f2e432..7557a041 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineBatchDAO.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineBatchDAO.java @@ -11,12 +11,16 @@ import com.zmops.zeus.iot.server.library.client.request.InsertRequest; import com.zmops.zeus.iot.server.library.client.request.PrepareRequest; import com.zmops.zeus.iot.server.library.util.CollectionUtils; +import com.zmops.zeus.iot.server.storage.plugin.jdbc.SQLBuilder; import com.zmops.zeus.iot.server.storage.plugin.jdbc.SQLExecutor; import lombok.extern.slf4j.Slf4j; import java.sql.Connection; +import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; /** * @author nantian created at 2021/9/4 0:31 @@ -27,6 +31,8 @@ public class TDEngineBatchDAO implements IBatchDAO { private final JDBCHikariCPClient tdengineClient; private final DataCarrier dataCarrier; + private final ExecutorService executor = Executors.newFixedThreadPool(10); + public TDEngineBatchDAO(JDBCHikariCPClient client) { this.tdengineClient = client; @@ -39,7 +45,7 @@ public TDEngineBatchDAO(JDBCHikariCPClient client) { throw new UnexpectedException(e.getMessage(), e); } - this.dataCarrier = new DataCarrier<>(1, 10000); + this.dataCarrier = new DataCarrier<>(4, 2500); this.dataCarrier.consume(ConsumerPoolFactory.INSTANCE.get(name), new TDEngineBatchConsumer(this)); } @@ -54,19 +60,34 @@ public void flush(List prepareRequests) { log.debug("batch sql statements execute, data size: {}", prepareRequests.size()); } - try (Connection connection = tdengineClient.getConnection()) { - for (PrepareRequest prepareRequest : prepareRequests) { + SQLBuilder execSql = new SQLBuilder(" INSERT INTO "); + for (PrepareRequest prepareRequest : prepareRequests) { + SQLExecutor sqlExecutor = (SQLExecutor) prepareRequest; + execSql.appendLine(sqlExecutor.getSql()); + } + execSql.append(";"); + + executor.submit(() -> { + PreparedStatement preparedStatement; + Connection connection = null; + try { + connection = tdengineClient.getConnection(); + preparedStatement = connection.prepareStatement(execSql.toString()); + preparedStatement.execute(); + } catch (SQLException | JDBCClientException e) { + e.printStackTrace(); + } finally { try { - SQLExecutor sqlExecutor = (SQLExecutor) prepareRequest; - sqlExecutor.invoke(connection); + if (connection != null) { + connection.close(); + } } catch (SQLException e) { - // Just avoid one execution failure makes the rest of batch failure. - log.error(e.getMessage(), e); + e.printStackTrace(); } } - } catch (SQLException | JDBCClientException e) { - log.error(e.getMessage(), e); - } + }); + + } @Override diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java index 0721c772..748c05d7 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java @@ -1,8 +1,14 @@ package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine; +import com.zmops.zeus.iot.server.core.storage.StorageException; import com.zmops.zeus.iot.server.library.client.Client; +import com.zmops.zeus.iot.server.library.client.jdbc.JDBCClientException; +import com.zmops.zeus.iot.server.library.client.jdbc.hikaricp.JDBCHikariCPClient; import com.zmops.zeus.iot.server.library.module.ModuleManager; +import java.sql.Connection; +import java.sql.SQLException; + /** * @author nantian created at 2021/9/4 1:16 */ @@ -12,16 +18,30 @@ public class TDEngineDatabaseInstaller { private final ModuleManager moduleManager; private final TDEngineStorageConfig config; - public TDEngineDatabaseInstaller(Client client, - ModuleManager moduleManager, - TDEngineStorageConfig config) { + private static final String CREATE_ZEUS_STABLE_HISTORY = "create stable if not exists history(clock TIMESTAMP, value DOUBLE) tags (deviceid BINARY(20))"; + private static final String CREATE_ZEUS_STABLE_HISTORY_UINT = "create stable if not exists history_uint(clock TIMESTAMP, value BIGINT) tags (deviceid BINARY(20))"; + + private static final String CREATE_ZEUS_STABLE_TRENDS = "create stable if not exists trends(clock TIMESTAMP, value_min DOUBLE, value_avg DOUBLE, value_max DOUBLE) tags (hostid BINARY(20))"; + private static final String CREATE_ZEUS_STABLE_TRENDS_UINT = "create stable if not exists trends_uint(clock TIMESTAMP, value_min BIGINT, value_avg BIGINT, value_max BIGINT) tags (hostid BINARY(20))"; + + public TDEngineDatabaseInstaller(Client client, ModuleManager moduleManager, TDEngineStorageConfig config) { this.config = config; this.client = client; this.moduleManager = moduleManager; } + protected void createDatabase() throws StorageException { + JDBCHikariCPClient jdbcHikariCPClient = (JDBCHikariCPClient) client; + try (Connection connection = jdbcHikariCPClient.getConnection()) { + + jdbcHikariCPClient.execute(connection, CREATE_ZEUS_STABLE_HISTORY); + jdbcHikariCPClient.execute(connection, CREATE_ZEUS_STABLE_HISTORY_UINT); + jdbcHikariCPClient.execute(connection, CREATE_ZEUS_STABLE_TRENDS); + jdbcHikariCPClient.execute(connection, CREATE_ZEUS_STABLE_TRENDS_UINT); - protected void createDatabase() { + } catch (JDBCClientException | SQLException e) { + throw new StorageException(e.getMessage(), e); + } } diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java index b3cb4453..d837df38 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java @@ -3,6 +3,7 @@ import com.zmops.zeus.iot.server.core.CoreModule; import com.zmops.zeus.iot.server.core.storage.IBatchDAO; import com.zmops.zeus.iot.server.core.storage.StorageDAO; +import com.zmops.zeus.iot.server.core.storage.StorageException; import com.zmops.zeus.iot.server.core.storage.StorageModule; import com.zmops.zeus.iot.server.library.client.jdbc.hikaricp.JDBCHikariCPClient; import com.zmops.zeus.iot.server.library.module.*; @@ -65,9 +66,12 @@ public void start() throws ServiceNotProvidedException, ModuleStartException { client.connect(); TDEngineDatabaseInstaller installer = new TDEngineDatabaseInstaller(client, getManager(), config); - installer.createDatabase(); + try { + installer.createDatabase(); + } catch (StorageException e) { + e.printStackTrace(); + } // getManager().find(CoreModule.NAME).provider().getService(ModelCreator.class).addModelListener(installer); - } @Override diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java index 9a420563..cb9c2777 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java @@ -1,5 +1,7 @@ package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine.dao; +import com.zmops.zeus.iot.server.core.analysis.manual.history.History; +import com.zmops.zeus.iot.server.core.analysis.manual.history.UIntHistory; import com.zmops.zeus.iot.server.core.analysis.record.Record; import com.zmops.zeus.iot.server.core.storage.StorageData; import com.zmops.zeus.iot.server.storage.plugin.jdbc.SQLBuilder; @@ -17,13 +19,24 @@ @Slf4j public class TDEngineSqlExecutor { - protected SQLExecutor getInsertExecutor(String modelName, T metrics) { - SQLBuilder sqlBuilder = new SQLBuilder("INSERT INTO " + modelName + " VALUES"); + SQLBuilder sqlBuilder = new SQLBuilder().append("h_").append(metrics.itemid() + " USING "); - List param = new ArrayList<>(); + if (modelName.equals("history")) { + + History history = (History) metrics; + sqlBuilder.append("history TAGS('").append(history.getDeviceId()).append("') VALUES (") + .append(history.getClock() + "").append(",").append(history.getValue()).append(")"); + } else if (modelName.equals("history_uint")) { + + UIntHistory uihistory = (UIntHistory) metrics; + sqlBuilder.append("history_uint TAGS('").append(uihistory.getDeviceId()).append("') VALUES (") + .append(uihistory.getClock() + "").append(",").append(uihistory.getValue()).append(")"); + } + + List param = new ArrayList<>(); return new SQLExecutor(sqlBuilder.toString(), param); } From 83dfc8bd6e75d79a6912d4b60dda85a108b15ca1 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 7 Sep 2021 11:07:33 +0800 Subject: [PATCH 103/763] tdengine add itemid tag. --- .../jdbc/tdengine/TDEngineDatabaseInstaller.java | 8 ++++---- .../plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java | 10 ++++++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java index 748c05d7..da7dae1e 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java @@ -18,11 +18,11 @@ public class TDEngineDatabaseInstaller { private final ModuleManager moduleManager; private final TDEngineStorageConfig config; - private static final String CREATE_ZEUS_STABLE_HISTORY = "create stable if not exists history(clock TIMESTAMP, value DOUBLE) tags (deviceid BINARY(20))"; - private static final String CREATE_ZEUS_STABLE_HISTORY_UINT = "create stable if not exists history_uint(clock TIMESTAMP, value BIGINT) tags (deviceid BINARY(20))"; + private static final String CREATE_ZEUS_STABLE_HISTORY = "create stable if not exists history(clock TIMESTAMP, value DOUBLE) tags (deviceid BINARY(20), itemid BINARY(20))"; + private static final String CREATE_ZEUS_STABLE_HISTORY_UINT = "create stable if not exists history_uint(clock TIMESTAMP, value BIGINT) tags (deviceid BINARY(20), itemid BINARY(20))"; - private static final String CREATE_ZEUS_STABLE_TRENDS = "create stable if not exists trends(clock TIMESTAMP, value_min DOUBLE, value_avg DOUBLE, value_max DOUBLE) tags (hostid BINARY(20))"; - private static final String CREATE_ZEUS_STABLE_TRENDS_UINT = "create stable if not exists trends_uint(clock TIMESTAMP, value_min BIGINT, value_avg BIGINT, value_max BIGINT) tags (hostid BINARY(20))"; + private static final String CREATE_ZEUS_STABLE_TRENDS = "create stable if not exists trends(clock TIMESTAMP, value_min DOUBLE, value_avg DOUBLE, value_max DOUBLE) tags (hostid BINARY(20), itemid BINARY(20))"; + private static final String CREATE_ZEUS_STABLE_TRENDS_UINT = "create stable if not exists trends_uint(clock TIMESTAMP, value_min BIGINT, value_avg BIGINT, value_max BIGINT) tags (hostid BINARY(20), itemid BINARY(20))"; public TDEngineDatabaseInstaller(Client client, ModuleManager moduleManager, TDEngineStorageConfig config) { this.config = config; diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java index cb9c2777..ad9fd779 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java @@ -26,13 +26,19 @@ protected SQLExecutor getInsertExecutor(String modelName if (modelName.equals("history")) { History history = (History) metrics; - sqlBuilder.append("history TAGS('").append(history.getDeviceId()).append("') VALUES (") + sqlBuilder.append("history (deviceid, itemid) TAGS") + .append("('").append(history.getDeviceId()).append("'") + .append(",").append(history.getItemid() + " )") + .append(" VALUES (") .append(history.getClock() + "").append(",").append(history.getValue()).append(")"); } else if (modelName.equals("history_uint")) { UIntHistory uihistory = (UIntHistory) metrics; - sqlBuilder.append("history_uint TAGS('").append(uihistory.getDeviceId()).append("') VALUES (") + sqlBuilder.append("history_uint (deviceid, itemid) TAGS") + .append(" ('").append(uihistory.getDeviceId()).append("'") + .append(",").append(uihistory.getItemid() + " )") + .append(" VALUES (") .append(uihistory.getClock() + "").append(",").append(uihistory.getValue()).append(")"); } From 1654fe5687d77887692d2a318099ba69092d9acd Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 7 Sep 2021 12:13:32 +0800 Subject: [PATCH 104/763] =?UTF-8?q?=E6=9C=80=E6=96=B0=E6=95=B0=E6=8D=AE=20?= =?UTF-8?q?=E5=88=86=E9=A1=B5=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/zmops/iot/web/analyse/service/HistoryService.java | 2 +- .../java/com/zmops/iot/web/analyse/service/LatestService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java index 95233bd4..abc043aa 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java @@ -36,7 +36,7 @@ public Pager queryHistory(HistoryParam historyParam) { List latestDtos = queryHistory(historyParam.getDeviceId(), historyParam.getAttrIds(), LocalDateTimeUtils.getSecondsByStr(historyParam.getTimeFrom()), LocalDateTimeUtils.getSecondsByStr(historyParam.getTimeTill())); - List collect = latestDtos.stream().skip((historyParam.getMaxRow() - 1) * historyParam.getPage()) + List collect = latestDtos.stream().skip((historyParam.getPage() - 1) * historyParam.getMaxRow()) .limit(historyParam.getMaxRow()).collect(Collectors.toList()); return new Pager<>(collect,latestDtos.size()); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java index c052214b..c89cb7b1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java @@ -39,7 +39,7 @@ public class LatestService { */ public Pager qeuryLatest(LatestParam latestParam) { List latestDtos = qeuryLatest(latestParam.getDeviceId(), latestParam.getAttrIds()); - List collect = latestDtos.stream().skip((latestParam.getMaxRow() - 1) * latestParam.getPage()) + List collect = latestDtos.stream().skip((latestParam.getPage() - 1) * latestParam.getMaxRow()) .limit(latestParam.getMaxRow()).collect(Collectors.toList()); return new Pager<>(collect,latestDtos.size()); } From e015e6ce8e56af7233117206927f6df5ce985e93 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 7 Sep 2021 16:55:08 +0800 Subject: [PATCH 105/763] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=85=A8=E5=B1=80?= =?UTF-8?q?=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/zmops/iot/domain/BaseDto.java | 6 --- .../model/cache/filter/CachedValueFilter.java | 5 --- .../zmops/zeus/driver/service/ZbxItem.java | 2 + .../api-json/item/item.trapper.create.ftl | 2 +- .../api-json/item/item.trapper.update.ftl | 2 +- .../zmops/iot/web/analyse/dto/LatestDto.java | 3 +- .../zmops/iot/web/device/dto/DeviceDto.java | 3 +- .../device/service/DeviceModelService.java | 4 +- .../iot/web/product/dto/ProductAttrDto.java | 3 +- .../zmops/iot/web/product/dto/ProductDto.java | 3 +- .../web/product/dto/ProductServiceDto.java | 3 +- .../product/service/ProductModelService.java | 4 +- .../iot/web/sys/controller/LogController.java | 13 +++--- .../sys/controller/LoginLogController.java | 11 ++--- .../com/zmops/iot/web/sys/dto/SysDictDto.java | 14 +------ .../zmops/iot/web/sys/dto/SysDictTypeDto.java | 11 +---- .../zmops/iot/web/sys/dto/SysLoginLogDto.java | 38 +++++++++++++++++ .../iot/web/sys/dto/SysOperationLogDto.java | 42 +++++++++++++++++++ .../com/zmops/iot/web/sys/dto/UserDto.java | 3 +- .../zmops/iot/web/sys/dto/UserGroupDto.java | 3 +- .../iot/web/sys/service/LoginLogService.java | 11 ++--- .../web/sys/service/OperationLogService.java | 11 ++--- 22 files changed, 122 insertions(+), 75 deletions(-) delete mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/BaseDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysLoginLogDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysOperationLogDto.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/BaseDto.java b/zeus-common/src/main/java/com/zmops/iot/domain/BaseDto.java deleted file mode 100644 index 779887ca..00000000 --- a/zeus-common/src/main/java/com/zmops/iot/domain/BaseDto.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.zmops.iot.domain; - -public interface BaseDto { - - -} \ No newline at end of file diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java index 50e758f8..87167741 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; -import com.zmops.iot.domain.BaseDto; import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.LocalDateTimeUtils; @@ -25,10 +24,6 @@ public class CachedValueFilter extends JsonSerializer { @Override public void serialize(Object object, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { - if (!(object instanceof BaseDto)) { - return; - } - jsonGenerator.writeStartObject(); for (Field field : getAllFields(object.getClass())) { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java index 87c51b7c..2eeacc3d 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java @@ -39,6 +39,7 @@ public interface ZbxItem { String createTrapperItem(@ParamName("itemName") String itemName, @ParamName("itemKey") String itemKey, @ParamName("hostId") String hostId, + @ParamName("source") String source, @ParamName("valueType") String valueType, @ParamName("units") String units, @ParamName("processList") List processingStepList, @@ -65,6 +66,7 @@ String updateTrapperItem(@ParamName("itemid") String itemid, @ParamName("itemName") String itemName, @ParamName("itemKey") String itemKey, @ParamName("hostId") String hostId, + @ParamName("source") String source, @ParamName("valueType") String valueType, @ParamName("units") String units, @ParamName("processList") List processingStepList, diff --git a/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl b/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl index 9b62e833..2fc3865a 100644 --- a/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl +++ b/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl @@ -5,7 +5,7 @@ "name": "${itemName}", "key_": "${itemKey}", "hostid": "${hostId}", - "type": 2, <#--zabbix trapper--> + "type": ${source}, <#--zabbix trapper--> "value_type": ${valueType}, <#if valuemapid?? && valuemapid != ''> "valuemapid":${valuemapid}, diff --git a/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl b/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl index e9c39023..ebbb5d90 100644 --- a/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl +++ b/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl @@ -6,7 +6,7 @@ "name": "${itemName}", "key_": "${itemKey}", "hostid": "${hostId}", - "type": 2, <#--zabbix trapper--> + "type": ${source}, <#--zabbix trapper--> "value_type": ${valueType}, <#if valuemapid??> "valuemapid":${valuemapid}, diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java index df517cdf..b351273d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java @@ -1,7 +1,6 @@ package com.zmops.iot.web.analyse.dto; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.zmops.iot.domain.BaseDto; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; import lombok.Data; @@ -11,7 +10,7 @@ **/ @Data @JsonSerialize(using = CachedValueFilter.class) -public class LatestDto implements BaseDto { +public class LatestDto { private String name; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java index dec63b2d..d3365291 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java @@ -1,7 +1,6 @@ package com.zmops.iot.web.device.dto; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.zmops.iot.domain.BaseDto; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; @@ -19,7 +18,7 @@ **/ @Data @JsonSerialize(using = CachedValueFilter.class) -public class DeviceDto implements BaseDto { +public class DeviceDto { @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Delete.class}) private String deviceId; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index 66e4614e..210b53ae 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -196,7 +196,7 @@ public String createTrapperItem(ProductAttr productAttr) { } return zbxItem.createTrapperItem(itemName, productAttr.getKey(), - hostId, productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(),productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); } /** @@ -233,7 +233,7 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { zbxItem.updateTrapperItem(productAttribute.getZbxId(), productAttr.getAttrId() + "", productAttr.getKey(), - hostId, productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(),productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); DB.update(productAttribute); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java index 5a42c19a..12b88928 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java @@ -3,7 +3,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.zmops.iot.domain.BaseDto; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; import com.zmops.iot.model.cache.filter.DicType; @@ -20,7 +19,7 @@ @Data @JsonSerialize(using = CachedValueFilter.class) -public class ProductAttrDto implements BaseDto { +public class ProductAttrDto { private Long attrId; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java index 9aad1777..8ec60953 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java @@ -2,7 +2,6 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.zmops.iot.domain.BaseDto; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; import com.zmops.iot.model.cache.filter.DicType; @@ -13,7 +12,7 @@ **/ @Data @JsonSerialize(using = CachedValueFilter.class) -public class ProductDto implements BaseDto { +public class ProductDto { private Long productId; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java index d393683e..dec6f825 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java @@ -1,7 +1,6 @@ package com.zmops.iot.web.product.dto; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.zmops.iot.domain.BaseDto; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.model.cache.filter.CachedValue; @@ -17,7 +16,7 @@ **/ @Data @JsonSerialize(using = CachedValueFilter.class) -public class ProductServiceDto implements BaseDto { +public class ProductServiceDto { @NotNull(groups = BaseEntity.Update.class) private Long id; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index 02da7648..b73be0a5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -200,7 +200,7 @@ public String createTrapperItem(ProductAttr productAttr) { } return zbxItem.createTrapperItem(itemName, productAttr.getKey(), - hostId, productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(),productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); } /** @@ -237,7 +237,7 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { zbxItem.updateTrapperItem(productAttribute.getZbxId(), productAttr.getAttrId() + "", productAttr.getKey(), - hostId, productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(),productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); DB.update(productAttribute); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LogController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LogController.java index 78ce093b..e21d3df9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LogController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LogController.java @@ -2,6 +2,7 @@ import com.zmops.iot.domain.sys.SysOperationLog; import com.zmops.iot.model.page.Pager; +import com.zmops.iot.web.sys.dto.SysOperationLogDto; import com.zmops.iot.web.sys.service.OperationLogService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; @@ -24,12 +25,12 @@ public class LogController { */ @RequestMapping("/getOperationLogByPage") @ResponseBody - public Pager list(@RequestParam(required = false) Long beginTime, - @RequestParam(required = false) Long endTime, - @RequestParam(required = false) String logName, - @RequestParam(required = false) String logType, - @RequestParam(required = false, defaultValue = "1") int page, - @RequestParam(required = false, defaultValue = "20") int maxRow) { + public Pager list(@RequestParam(required = false) Long beginTime, + @RequestParam(required = false) Long endTime, + @RequestParam(required = false) String logName, + @RequestParam(required = false) String logType, + @RequestParam(required = false, defaultValue = "1") int page, + @RequestParam(required = false, defaultValue = "20") int maxRow) { return operationLogService.list(beginTime, endTime, logName, logType, page, maxRow); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginLogController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginLogController.java index 0301eabd..9dbc203a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginLogController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginLogController.java @@ -2,6 +2,7 @@ import com.zmops.iot.domain.sys.SysLoginLog; import com.zmops.iot.model.page.Pager; +import com.zmops.iot.web.sys.dto.SysLoginLogDto; import com.zmops.iot.web.sys.service.LoginLogService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; @@ -24,11 +25,11 @@ public class LoginLogController { */ @RequestMapping("/getLoginLogByPage") @ResponseBody - public Pager list(@RequestParam(required = false) Long beginTime, - @RequestParam(required = false) Long endTime, - @RequestParam(required = false) String logName, - @RequestParam(required = false, defaultValue = "1") int page, - @RequestParam(required = false, defaultValue = "20") int maxRow) { + public Pager list(@RequestParam(required = false) Long beginTime, + @RequestParam(required = false) Long endTime, + @RequestParam(required = false) String logName, + @RequestParam(required = false, defaultValue = "1") int page, + @RequestParam(required = false, defaultValue = "20") int maxRow) { return loginLogService.list(beginTime, endTime, logName, page, maxRow); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictDto.java index 5a2a525a..ba873264 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictDto.java @@ -1,22 +1,10 @@ package com.zmops.iot.web.sys.dto; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.zmops.iot.constant.IdTypeConsts; -import com.zmops.iot.domain.BaseDto; -import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; -import io.ebean.annotation.WhenModified; -import io.ebean.annotation.WhoCreated; -import io.ebean.annotation.WhoModified; import lombok.Data; -import lombok.EqualsAndHashCode; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Table; -import java.io.Serializable; import java.time.LocalDateTime; /** @@ -26,7 +14,7 @@ */ @Data @JsonSerialize(using = CachedValueFilter.class) -public class SysDictDto implements BaseDto { +public class SysDictDto { /** * 字典id diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictTypeDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictTypeDto.java index d92b206c..362cd216 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictTypeDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictTypeDto.java @@ -1,19 +1,10 @@ package com.zmops.iot.web.sys.dto; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.zmops.iot.constant.IdTypeConsts; -import com.zmops.iot.domain.BaseDto; -import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; import lombok.Data; -import lombok.EqualsAndHashCode; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Table; -import java.io.Serializable; import java.time.LocalDateTime; /** @@ -23,7 +14,7 @@ */ @Data @JsonSerialize(using = CachedValueFilter.class) -public class SysDictTypeDto implements BaseDto { +public class SysDictTypeDto { /** * 字典类型id diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysLoginLogDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysLoginLogDto.java new file mode 100644 index 00000000..ec8d85bf --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysLoginLogDto.java @@ -0,0 +1,38 @@ +package com.zmops.iot.web.sys.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.constant.IdTypeConsts; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import java.time.LocalDateTime; + + +/** + * @author nantian created at 2021/7/31 18:20 + */ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class SysLoginLogDto { + + long loginLogId; + + String logName; + + @CachedValue(type = DicType.SysUserName) + Long userId; + + LocalDateTime createTime; + + String succeed; + + String message; + + String ipAddress; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysOperationLogDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysOperationLogDto.java new file mode 100644 index 00000000..8b77391e --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysOperationLogDto.java @@ -0,0 +1,42 @@ +package com.zmops.iot.web.sys.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.constant.IdTypeConsts; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import java.time.LocalDateTime; + +/** + * @author nantian created at 2021/8/1 22:04 + */ + +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class SysOperationLogDto { + + private Long operationLogId; + + private String logType; + + private String logName; + + @CachedValue(type = DicType.SysUserName) + private Long userId; + + private String className; + + private String method; + + private String succeed; + + private String message; + + private LocalDateTime createTime; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java index 8b39ddec..26303226 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java @@ -16,7 +16,6 @@ package com.zmops.iot.web.sys.dto; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.zmops.iot.domain.BaseDto; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; @@ -32,7 +31,7 @@ */ @Data @JsonSerialize(using = CachedValueFilter.class) -public class UserDto implements BaseDto { +public class UserDto { @NotNull(groups = BaseEntity.Update.class) private Long userId; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java index c48da827..0e3ea1be 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java @@ -16,7 +16,6 @@ package com.zmops.iot.web.sys.dto; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.zmops.iot.domain.BaseDto; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; @@ -34,7 +33,7 @@ */ @Data @JsonSerialize(using = CachedValueFilter.class) -public class UserGroupDto implements BaseDto { +public class UserGroupDto { @NotNull(groups = BaseEntity.Update.class) private Long userGroupId; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/LoginLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/LoginLogService.java index eb5de5ab..b12d680f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/LoginLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/LoginLogService.java @@ -1,20 +1,21 @@ package com.zmops.iot.web.sys.service; -import com.zmops.iot.domain.sys.SysLoginLog; import com.zmops.iot.domain.sys.query.QSysLoginLog; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; -import io.ebean.PagedList; +import com.zmops.iot.web.sys.dto.SysLoginLogDto; import org.springframework.stereotype.Service; +import java.util.List; + /** * @author yefei **/ @Service public class LoginLogService { - public Pager list(Long beginTime, Long endTime, String logName, int page, int maxRow) { + public Pager list(Long beginTime, Long endTime, String logName, int page, int maxRow) { QSysLoginLog qSysLoginLog = new QSysLoginLog(); if (ToolUtil.isNotEmpty(beginTime)) { qSysLoginLog.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(beginTime)); @@ -26,7 +27,7 @@ public Pager list(Long beginTime, Long endTime, String logName, int qSysLoginLog.logName.eq(logName); } qSysLoginLog.setFirstRow((page - 1) * maxRow).setMaxRows(maxRow); - PagedList pagedList = qSysLoginLog.orderBy("create_time desc").findPagedList(); - return new Pager<>(pagedList.getList(), pagedList.getTotalCount()); + List pagedList = qSysLoginLog.orderBy("create_time desc").asDto(SysLoginLogDto.class).findList(); + return new Pager<>(pagedList, qSysLoginLog.findCount()); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/OperationLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/OperationLogService.java index 6148801f..151fe951 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/OperationLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/OperationLogService.java @@ -1,20 +1,21 @@ package com.zmops.iot.web.sys.service; -import com.zmops.iot.domain.sys.SysOperationLog; import com.zmops.iot.domain.sys.query.QSysOperationLog; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; -import io.ebean.PagedList; +import com.zmops.iot.web.sys.dto.SysOperationLogDto; import org.springframework.stereotype.Service; +import java.util.List; + /** * @author yefei **/ @Service public class OperationLogService { - public Pager list(Long beginTime, Long endTime, String logName, String logType, int page, int maxRow) { + public Pager list(Long beginTime, Long endTime, String logName, String logType, int page, int maxRow) { QSysOperationLog qSysOperationLog = new QSysOperationLog(); if (ToolUtil.isNotEmpty(beginTime)) { qSysOperationLog.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(beginTime)); @@ -29,7 +30,7 @@ public Pager list(Long beginTime, Long endTime, String logName, qSysOperationLog.logType.eq(logType); } qSysOperationLog.setFirstRow((page - 1) * maxRow).setMaxRows(maxRow); - PagedList pagedList = qSysOperationLog.orderBy("create_time desc").findPagedList(); - return new Pager<>(pagedList.getList(), pagedList.getTotalCount()); + List pagedList = qSysOperationLog.orderBy("create_time desc").asDto(SysOperationLogDto.class).findList(); + return new Pager<>(pagedList, qSysOperationLog.findCount()); } } From d772db4cb8356dd790701f162244e6944e6dd359 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 7 Sep 2021 17:20:35 +0800 Subject: [PATCH 106/763] =?UTF-8?q?=E4=BA=A7=E5=93=81=E5=B1=9E=E6=80=A7=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BE=9D=E8=B5=96=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zmops/zeus/driver/service/ZbxItem.java | 2 ++ .../api-json/item/item.trapper.create.ftl | 5 +++- .../api-json/item/item.trapper.update.ftl | 5 +++- .../controller/DeviceModelController.java | 25 +++++++++++++++++++ .../device/service/DeviceModelService.java | 5 ++-- .../web/exception/enums/BizExceptionEnum.java | 2 ++ .../controller/ProductModelController.java | 25 +++++++++++++++++++ .../iot/web/product/dto/ProductAttr.java | 3 +++ .../product/service/ProductModelService.java | 4 +-- 9 files changed, 69 insertions(+), 7 deletions(-) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java index 2eeacc3d..9e1bb4eb 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java @@ -40,6 +40,7 @@ String createTrapperItem(@ParamName("itemName") String itemName, @ParamName("itemKey") String itemKey, @ParamName("hostId") String hostId, @ParamName("source") String source, + @ParamName("masterItemid") String masterItemid, @ParamName("valueType") String valueType, @ParamName("units") String units, @ParamName("processList") List processingStepList, @@ -67,6 +68,7 @@ String updateTrapperItem(@ParamName("itemid") String itemid, @ParamName("itemKey") String itemKey, @ParamName("hostId") String hostId, @ParamName("source") String source, + @ParamName("masterItemid") String masterItemid, @ParamName("valueType") String valueType, @ParamName("units") String units, @ParamName("processList") List processingStepList, diff --git a/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl b/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl index 2fc3865a..9f425a82 100644 --- a/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl +++ b/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl @@ -5,7 +5,10 @@ "name": "${itemName}", "key_": "${itemKey}", "hostid": "${hostId}", - "type": ${source}, <#--zabbix trapper--> + "type": ${source}, + <#if source == '18'> + "master_itemid":${masterItemid}, + "value_type": ${valueType}, <#if valuemapid?? && valuemapid != ''> "valuemapid":${valuemapid}, diff --git a/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl b/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl index ebbb5d90..9a516543 100644 --- a/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl +++ b/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl @@ -6,7 +6,10 @@ "name": "${itemName}", "key_": "${itemKey}", "hostid": "${hostId}", - "type": ${source}, <#--zabbix trapper--> + "type": ${source}, + <#if source == '18'> + "master_itemid":${masterItemid}, + "value_type": ${valueType}, <#if valuemapid??> "valuemapid":${valuemapid}, diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java index 7d99b4ad..6f62327c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java @@ -3,6 +3,7 @@ import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSON; import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; @@ -34,6 +35,8 @@ public class DeviceModelController { @Autowired private DeviceModelService deviceModelService; + //依赖属性类型 + private static final String ATTR_SOURCE_DEPEND = "18"; /** * 设备物模型 分页列表 @@ -77,6 +80,17 @@ public ResponseData prodModelAttributeCreate(@RequestBody @Validated(BaseEntity. throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_EXISTS); } + if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { + if(productAttr.getDepAttrId() == null){ + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NULL); + } + ProductAttribute productAttribute = new QProductAttribute().attrId.eq(productAttr.getDepAttrId()).findOne(); + if(null == productAttribute){ + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); + } + productAttr.setMasterItemId(productAttr.getZbxId()); + } + Long attrId = IdUtil.getSnowflake().nextId(); productAttr.setAttrId(attrId); @@ -101,6 +115,17 @@ public ResponseData prodModelAttributeUpdate(@RequestBody @Validated(BaseEntity. throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_EXISTS); } + if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { + if(productAttr.getDepAttrId() == null){ + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NULL); + } + ProductAttribute productAttribute = new QProductAttribute().attrId.eq(productAttr.getDepAttrId()).findOne(); + if(null == productAttribute){ + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); + } + productAttr.setMasterItemId(productAttr.getZbxId()); + } + return ResponseData.success(deviceModelService.updateTrapperItem(productAttr)); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index 210b53ae..b8112a25 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -196,7 +196,7 @@ public String createTrapperItem(ProductAttr productAttr) { } return zbxItem.createTrapperItem(itemName, productAttr.getKey(), - hostId, productAttr.getSource(),productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(),productAttr.getMasterItemId(),productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); } /** @@ -231,9 +231,8 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { .collect(Collectors.toMap(ProductTag.Tag::getTag, ProductTag.Tag::getValue, (k1, k2) -> k2)); } - zbxItem.updateTrapperItem(productAttribute.getZbxId(), productAttr.getAttrId() + "", productAttr.getKey(), - hostId, productAttr.getSource(),productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(),productAttr.getMasterItemId(),productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); DB.update(productAttribute); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index 04d761fb..7e5ad020 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -139,6 +139,8 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { * 属性相关 */ PRODUCT_ATTR_KEY_EXISTS(1401, "该属性Key已存在"), + PRODUCT_ATTR_DEPTED_NULL(1402,"依赖的属性不能为空"), + PRODUCT_ATTR_DEPTED_NOT_EXIST(1403,"依赖的属性不能为空"), /** * 设备相关 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java index fdd6d166..abb81220 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java @@ -3,6 +3,7 @@ import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSON; import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; @@ -34,6 +35,8 @@ public class ProductModelController { @Autowired private ProductModelService productModelService; + //依赖属性类型 + private static final String ATTR_SOURCE_DEPEND = "18"; /** * 产品物模型 属性 分页列表 @@ -77,6 +80,17 @@ public ResponseData prodModelAttributeCreate(@RequestBody @Validated(BaseEntity. throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_EXISTS); } + if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { + if(productAttr.getDepAttrId() == null){ + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NULL); + } + ProductAttribute productAttribute = new QProductAttribute().attrId.eq(productAttr.getDepAttrId()).findOne(); + if(null == productAttribute){ + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); + } + productAttr.setMasterItemId(productAttr.getZbxId()); + } + Long attrId = IdUtil.getSnowflake().nextId(); productAttr.setAttrId(attrId); @@ -101,6 +115,17 @@ public ResponseData prodModelAttributeUpdate(@RequestBody @Validated(BaseEntity. throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_EXISTS); } + if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { + if(productAttr.getDepAttrId() == null){ + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NULL); + } + ProductAttribute productAttribute = new QProductAttribute().attrId.eq(productAttr.getDepAttrId()).findOne(); + if(null == productAttribute){ + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); + } + productAttr.setMasterItemId(productAttr.getZbxId()); + } + return ResponseData.success(productModelService.updateTrapperItem(productAttr)); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java index 3121acae..f916e4b4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java @@ -42,6 +42,9 @@ public class ProductAttr { private Long depAttrId; + @JsonIgnore + private String masterItemId; + @JsonIgnore private String zbxId; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index b73be0a5..66f70ef3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -200,7 +200,7 @@ public String createTrapperItem(ProductAttr productAttr) { } return zbxItem.createTrapperItem(itemName, productAttr.getKey(), - hostId, productAttr.getSource(),productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(),productAttr.getMasterItemId(),productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); } /** @@ -237,7 +237,7 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { zbxItem.updateTrapperItem(productAttribute.getZbxId(), productAttr.getAttrId() + "", productAttr.getKey(), - hostId, productAttr.getSource(),productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(),productAttr.getMasterItemId(),productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); DB.update(productAttribute); From a4e57e65c5b78e0a314d76ce66aa188d91ffdee7 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 7 Sep 2021 17:31:46 +0800 Subject: [PATCH 107/763] =?UTF-8?q?=E4=BA=A7=E5=93=81=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/web/device/controller/DeviceModelController.java | 4 ++-- .../iot/web/product/controller/ProductModelController.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java index 6f62327c..1d920023 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java @@ -88,7 +88,7 @@ public ResponseData prodModelAttributeCreate(@RequestBody @Validated(BaseEntity. if(null == productAttribute){ throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); } - productAttr.setMasterItemId(productAttr.getZbxId()); + productAttr.setMasterItemId(productAttribute.getZbxId()); } Long attrId = IdUtil.getSnowflake().nextId(); @@ -123,7 +123,7 @@ public ResponseData prodModelAttributeUpdate(@RequestBody @Validated(BaseEntity. if(null == productAttribute){ throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); } - productAttr.setMasterItemId(productAttr.getZbxId()); + productAttr.setMasterItemId(productAttribute.getZbxId()); } return ResponseData.success(deviceModelService.updateTrapperItem(productAttr)); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java index abb81220..f22ca2c2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java @@ -88,7 +88,7 @@ public ResponseData prodModelAttributeCreate(@RequestBody @Validated(BaseEntity. if(null == productAttribute){ throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); } - productAttr.setMasterItemId(productAttr.getZbxId()); + productAttr.setMasterItemId(productAttribute.getZbxId()); } Long attrId = IdUtil.getSnowflake().nextId(); @@ -123,7 +123,7 @@ public ResponseData prodModelAttributeUpdate(@RequestBody @Validated(BaseEntity. if(null == productAttribute){ throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); } - productAttr.setMasterItemId(productAttr.getZbxId()); + productAttr.setMasterItemId(productAttribute.getZbxId()); } return ResponseData.success(productModelService.updateTrapperItem(productAttr)); From 6a8e4c05021501583e43aee74d726ceb6b06dc96 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 7 Sep 2021 18:09:59 +0800 Subject: [PATCH 108/763] =?UTF-8?q?=E4=BA=A7=E5=93=81=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/zmops/iot/web/product/service/ProductModelService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index 66f70ef3..448c76f1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -241,7 +241,7 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { DB.update(productAttribute); - WorkerWrapper updateProdAttrWork = WorkerWrapper.builder().worker(updateProdAttrWorker).build(); + WorkerWrapper updateProdAttrWork = WorkerWrapper.builder().worker(updateProdAttrWorker).param(productAttr).build(); try { Async.work(100, updateProdAttrWork).awaitFinish(); From b97fde568ad2231fd93a103209f62bc61efb071f Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 7 Sep 2021 19:37:37 +0800 Subject: [PATCH 109/763] =?UTF-8?q?=E5=85=A8=E5=B1=80=E6=A6=82=E8=A7=88=20?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E6=95=B0=E9=87=8F=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analyse/controller/HomeController.java | 8 ++++ .../iot/web/analyse/service/HomeService.java | 45 ++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java index bd819e39..934ed581 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java @@ -22,6 +22,14 @@ public class HomeController { @Autowired HomeService homeService; + /** + * 设备数量统计 + */ + @RequestMapping("/deviceNum") + public ResponseData getDeviceNum(){ + return ResponseData.success(homeService.getDeviceNum()); + } + /** * 服务器取数速率 * diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index 586304fe..37f729e2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -2,6 +2,9 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.query.QProduct; import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; @@ -68,6 +71,11 @@ public class HomeService { //Zbx 指标取数速率 key private static final String KEY = "zabbix[wcache,values"; + /** + * 服务器取数速率统计 + * + * @return + */ public Map> collectonRate() { if (ToolUtil.isEmpty(hostId)) { if (ToolUtil.isEmpty(getZbxServerId())) { @@ -93,6 +101,11 @@ public Map> collectonRate() { return latestDtos.parallelStream().collect(Collectors.groupingBy(LatestDto::getName)); } + /** + * 获取服务器 hostid + * + * @return + */ private String getZbxServerId() { String response = zbxHost.hostGet("Zabbix server"); List> ids = JSON.parseObject(response, List.class); @@ -103,6 +116,11 @@ private String getZbxServerId() { return ""; } + /** + * 获取服务器 取数的ITEM + * + * @return + */ private Map getItemMap() { String itemList = zbxItem.getItemList(KEY, hostId); List itemInfos = JSONObject.parseArray(itemList, ZbxItemInfo.class); @@ -112,6 +130,9 @@ private Map getItemMap() { return ITEM_Map; } + /** + * 格式化显示的名称 + */ private static String formatName(String name) { if (name.length() < 53) { return "avg"; @@ -200,7 +221,9 @@ private List getItemIds(List attrIds) { return new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(attrIds).findSingleAttributeList(); } - + /** + * 用户访客 获取cookie + */ private void getCookie() { HttpClient client = new HttpClient(); PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort + "/zabbix/index.php"); @@ -222,4 +245,24 @@ private void getCookie() { COOKIE = postMethod.getResponseHeader("Set-Cookie").getValue(); COOKIE_TIME = LocalDateTime.now(); } + + /** + * 统计设备数量 + * + * @return + */ + public Map getDeviceNum() { + Map deviceNumMap = new HashMap<>(4); + + deviceNumMap.put("online", 0); + + List list = new QDevice().findList(); + deviceNumMap.put("total", list.size()); + deviceNumMap.put("disable", (int) list.parallelStream().filter(o -> "DISABLE".equals(o.getStatus())).count()); + deviceNumMap.put("product", new QProduct().findCount()); + + + return deviceNumMap; + } + } From 78815a8d27e72293a8c57d17382d9e64926c1ad2 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 8 Sep 2021 09:07:14 +0800 Subject: [PATCH 110/763] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=20=E5=85=A8?= =?UTF-8?q?=E5=B1=80=E8=84=9A=E6=9C=AC=E5=8A=A8=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zmops/zeus/driver/service/ZbxAction.java | 4 +- .../api-json/action/action.init.create.ftl | 4 +- .../api-json/action/action.offline.get.ftl | 2 +- .../api-json/script/script.init.create.ftl | 24 ++++++--- .../api-json/script/script.offline.get.ftl | 8 ++- .../zmops/iot/web/init/BasicSettingsInit.java | 31 +++++++----- .../iot/web/init/DeviceSatusScriptInit.java | 50 +++++++++++++------ 7 files changed, 81 insertions(+), 42 deletions(-) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java index 5a08122a..8bbeb36f 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java @@ -28,6 +28,8 @@ public interface ZbxAction { @Post(headers = "authTag: noAuth") @JsonPath("/action/action.init.create") String createOfflineStatusAction(@ParamName("userAuth") String userAuth, + @ParamName("name") String name, + @ParamName("tagName") String tagName, @ParamName("scriptId") String scriptId, @ParamName("groupId") String groupId); @@ -40,5 +42,5 @@ String createOfflineStatusAction(@ParamName("userAuth") String userAuth, */ @Post(headers = "authTag: noAuth") @JsonPath("/action/action.offline.get") - String getOfflineStatusAction(@ParamName("userAuth") String userAuth); + String getOfflineStatusAction(@ParamName("userAuth") String userAuth,@ParamName("name") String name); } diff --git a/zeus-driver/src/main/resources/api-json/action/action.init.create.ftl b/zeus-driver/src/main/resources/api-json/action/action.init.create.ftl index a06222b5..37b0908c 100644 --- a/zeus-driver/src/main/resources/api-json/action/action.init.create.ftl +++ b/zeus-driver/src/main/resources/api-json/action/action.init.create.ftl @@ -2,7 +2,7 @@ "jsonrpc": "2.0", "method": "action.create", "params": { - "name": "__offline_status__", + "name": "${name}", "eventsource": 0, "status": 0, "esc_period": "2m", @@ -12,7 +12,7 @@ { "conditiontype": 25, "operator": 0, - "value": "DEVICE_STATUS" + "value": "${tagName}" } ] }, diff --git a/zeus-driver/src/main/resources/api-json/action/action.offline.get.ftl b/zeus-driver/src/main/resources/api-json/action/action.offline.get.ftl index 7d6e83e9..50d576be 100644 --- a/zeus-driver/src/main/resources/api-json/action/action.offline.get.ftl +++ b/zeus-driver/src/main/resources/api-json/action/action.offline.get.ftl @@ -6,7 +6,7 @@ "actionid" ], "search": { - "name": "__offline_status__" + "name": "${name}" } }, "auth": "${userAuth}", diff --git a/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl b/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl index d6c4687c..e581f696 100644 --- a/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl +++ b/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl @@ -1,12 +1,24 @@ { "jsonrpc": "2.0", "method": "script.create", - "params": { - "name": "__offline_status__", - "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"hostname\\":\\"{HOST.HOST}\\",\\"deviceStatus\\":\\"{EVENT.ID}\\"}' http://${zeusServerIp}:${zeusServerPort}/device/action/exec", - "type": 0, - "execute_on": 1 - }, + "params": [ + { + "name": "__offline_status__", <#--上下线 调用 webapp--> + "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"hostname\\":\\"{HOST.HOST}\\"}' http://127.0.0.1:9090/device/status", + "type": 0, + "execute_on": 1 + },{ + "name": "__trigger_webhook__", <#-- 告警 回调 --> + "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"hostname\\":\\"{HOST.HOST}\\"}' http://127.0.0.1:9090/device/problem", + "type": 0, + "execute_on": 1 + },{ + "name": "__trigger_webhook__", <#-- 执行 方法 --> + "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"hostname\\":\\"{HOST.HOST}\\"}' http://127.0.0.1:12800/device/action/exec", + "type": 0, + "execute_on": 1 + } + ], "auth": "${userAuth}", "id": 1 } \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/script/script.offline.get.ftl b/zeus-driver/src/main/resources/api-json/script/script.offline.get.ftl index fbbb7015..7c8afce2 100644 --- a/zeus-driver/src/main/resources/api-json/script/script.offline.get.ftl +++ b/zeus-driver/src/main/resources/api-json/script/script.offline.get.ftl @@ -3,11 +3,9 @@ "method": "script.get", "params": { "output": [ - "scriptid" - ], - "search": { - "name": "__offline_status__" <#--在线状态--> - } + "scriptid", + "name" + ] }, "auth": "${userAuth}", "id": 1 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java index d0f0d01a..ad33c0c0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java @@ -11,6 +11,7 @@ import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -93,7 +94,7 @@ public String getCookieUserGroup() { * @return String */ public String createCookieUserGroup(String globalHostGroupId) { - String response = zbxInitService.createCookieUserGroup(globalHostGroupId,zbxApiToken); + String response = zbxInitService.createCookieUserGroup(globalHostGroupId, zbxApiToken); return JSON.parseObject(response, ZbxResponseIds.class).getUsrgrpids()[0]; } @@ -117,8 +118,8 @@ public String getCookieUser() { * @param groupId 只读用户组ID * @return String */ - public String createCookieUser(String groupId,String roleId) { - String response = zbxInitService.createCookieUser(groupId,zbxApiToken,roleId); + public String createCookieUser(String groupId, String roleId) { + String response = zbxInitService.createCookieUser(groupId, zbxApiToken, roleId); return JSON.parseObject(response, ZbxResponseIds.class).getUserids()[0]; } @@ -150,29 +151,33 @@ public String getGuestRoleId() { return null; } - public String createOfflineStatusScript() { - String response = zbxScript.createOfflineStatusScript(zbxApiToken, zeusServerIp, zeusServerPort); - return JSON.parseObject(response, ZbxResponseIds.class).getScriptids()[0]; + public Map createOfflineStatusScript() { + zbxScript.createOfflineStatusScript(zbxApiToken, zeusServerIp, zeusServerPort); + + return getOfflineStatusScript(); } - public String getOfflineStatusScript() { + public Map getOfflineStatusScript() { String response = zbxScript.getOfflineStatusScript(zbxApiToken); List> ids = JSON.parseObject(response, List.class); + Map map = new HashMap<>(3); if (null != ids && ids.size() > 0) { - return ids.get(0).get("scriptid"); + ids.forEach(script -> { + map.put(script.get("name"), script.get("scriptid")); + }); } - return null; + return map; } - public String createOfflineStatusAction(String scriptId, String groupId) { - String response = zbxAction.createOfflineStatusAction(zbxApiToken, scriptId, groupId); + public String createAction(String name,String tagName,String scriptId, String groupId) { + String response = zbxAction.createOfflineStatusAction(zbxApiToken,tagName,name, scriptId, groupId); return JSON.parseObject(response, ZbxResponseIds.class).getActionids()[0]; } - public String getOfflineStatusAction() { - String response = zbxAction.getOfflineStatusAction(zbxApiToken); + public String getAction(String name) { + String response = zbxAction.getOfflineStatusAction(zbxApiToken,name); List> ids = JSON.parseObject(response, List.class); if (null != ids && ids.size() > 0) { return ids.get(0).get("actionid"); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java index d42e4e09..90c5c580 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java @@ -1,12 +1,15 @@ package com.zmops.iot.web.init; import com.zmops.iot.domain.sys.SysConfig; +import com.zmops.iot.util.ToolUtil; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; +import java.util.Map; + /** * @author nantian created at 2021/8/7 20:25 */ @@ -16,10 +19,21 @@ public class DeviceSatusScriptInit implements CommandLineRunner { - public static final String GLOBAL_HOST_GROUP_CODE = "ZEUS_HOST_GROUP_ID"; - public static final String GLOBAL_ACTION_CODE = "ZEUS_ACTION_ID"; + public static final String GLOBAL_HOST_GROUP_CODE = "ZEUS_HOST_GROUP_ID"; + public static final String GLOBAL_OFFLINE_ACTION_CODE = "ZEUS_OFFLINE_ACTION_ID"; + public static final String GLOBAL_ALARM_ACTION_CODE = "ZEUS_ALARM_ACTION_ID"; + public static final String GLOBAL_EXEC_ACTION_CODE = "ZEUS_EXEC_ACTION_ID"; public static final String GLOBAL_ADMIN_ROLE_CODE = "ZEUS_ADMIN_ROLE_ID"; + public static final String SCRIPT_OFFLINE = "__offline_status__"; + public static final String SCRIPT_ALARM = "__alarm__"; + public static final String SCRIPT_EXECUTE = "__execute__"; + + public static final String ACTION_TAG_OFFLINE = "__offline__"; + public static final String ACTION_TAG_ALARM = "__alarm__"; + public static final String ACTION_TAG_EXECUTE = "__execute__"; + + @Autowired private BasicSettingsInit basicSettingsInit; @@ -37,7 +51,6 @@ public void run(String... args) throws Exception { String roleId = basicSettingsInit.getAdminRoleId(); DB.update(SysConfig.class).where().eq("code", GLOBAL_ADMIN_ROLE_CODE).asUpdate().set("value", roleId).update(); - //判断只读用户是否存在 不存在就创建一个 String userId = basicSettingsInit.getCookieUser(); if (userId == null) { @@ -46,25 +59,34 @@ public void run(String... args) throws Exception { userGroupId = basicSettingsInit.createCookieUserGroup(groupId); } String guestRoleId = basicSettingsInit.getGuestRoleId(); - basicSettingsInit.createCookieUser(userGroupId,guestRoleId); + basicSettingsInit.createCookieUser(userGroupId, guestRoleId); } - - // 第二步:创建全局回调脚本 - String scriptId = basicSettingsInit.getOfflineStatusScript(); - if (scriptId == null) { - scriptId = basicSettingsInit.createOfflineStatusScript(); + Map script = basicSettingsInit.getOfflineStatusScript(); + if (ToolUtil.isEmpty(script)) { + script = basicSettingsInit.createOfflineStatusScript(); } - String actionId = basicSettingsInit.getOfflineStatusAction(); - if (actionId == null) { - actionId = basicSettingsInit.createOfflineStatusAction(scriptId, groupId); + String offLineActionId = basicSettingsInit.getAction(SCRIPT_OFFLINE); + if (offLineActionId == null) { + offLineActionId = basicSettingsInit.createAction(SCRIPT_OFFLINE,ACTION_TAG_OFFLINE, script.get(SCRIPT_OFFLINE), groupId); } + DB.update(SysConfig.class).where().eq("code", GLOBAL_OFFLINE_ACTION_CODE).asUpdate().set("value", offLineActionId).update(); - DB.update(SysConfig.class).where().eq("code", GLOBAL_ACTION_CODE).asUpdate().set("value", actionId).update(); + String AlarmActionId = basicSettingsInit.getAction(SCRIPT_ALARM); + if (AlarmActionId == null) { + AlarmActionId = basicSettingsInit.createAction(SCRIPT_ALARM,ACTION_TAG_ALARM, script.get(SCRIPT_ALARM), groupId); + } + DB.update(SysConfig.class).where().eq("code", GLOBAL_ALARM_ACTION_CODE).asUpdate().set("value", AlarmActionId).update(); + + String execActionId = basicSettingsInit.getAction(SCRIPT_EXECUTE); + if (execActionId == null) { + execActionId = basicSettingsInit.createAction(SCRIPT_EXECUTE,ACTION_TAG_EXECUTE, script.get(SCRIPT_EXECUTE), groupId); + } + DB.update(SysConfig.class).where().eq("code", GLOBAL_EXEC_ACTION_CODE).asUpdate().set("value", execActionId).update(); - log.info("全局主机组ID:{},在线触发动作ID:{}", groupId, actionId); + log.info("全局主机组ID:{},在线触发动作ID:{},告警触发动作ID:{},命令执行触发动作ID:{}", groupId, offLineActionId, AlarmActionId, execActionId); } } From f6072fe63cbec4159be939eb9b93f9bfa5ea9b6b Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 8 Sep 2021 09:52:45 +0800 Subject: [PATCH 111/763] =?UTF-8?q?=E5=85=A8=E5=B1=80=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/api-json/script/script.init.create.ftl | 2 +- .../main/resources/api-json/script/script.offline.get.ftl | 5 ++++- .../java/com/zmops/iot/web/init/DeviceSatusScriptInit.java | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl b/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl index e581f696..fc39e840 100644 --- a/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl +++ b/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl @@ -13,7 +13,7 @@ "type": 0, "execute_on": 1 },{ - "name": "__trigger_webhook__", <#-- 执行 方法 --> + "name": "__trigger_execute__", <#-- 执行 方法 --> "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"hostname\\":\\"{HOST.HOST}\\"}' http://127.0.0.1:12800/device/action/exec", "type": 0, "execute_on": 1 diff --git a/zeus-driver/src/main/resources/api-json/script/script.offline.get.ftl b/zeus-driver/src/main/resources/api-json/script/script.offline.get.ftl index 7c8afce2..c34fe440 100644 --- a/zeus-driver/src/main/resources/api-json/script/script.offline.get.ftl +++ b/zeus-driver/src/main/resources/api-json/script/script.offline.get.ftl @@ -5,7 +5,10 @@ "output": [ "scriptid", "name" - ] + ], + "search": { + "name": "__" <#--在线状态--> + } }, "auth": "${userAuth}", "id": 1 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java index 90c5c580..4430c1bb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java @@ -26,8 +26,8 @@ public class DeviceSatusScriptInit implements CommandLineRunner { public static final String GLOBAL_ADMIN_ROLE_CODE = "ZEUS_ADMIN_ROLE_ID"; public static final String SCRIPT_OFFLINE = "__offline_status__"; - public static final String SCRIPT_ALARM = "__alarm__"; - public static final String SCRIPT_EXECUTE = "__execute__"; + public static final String SCRIPT_ALARM = "__trigger_webhook__"; + public static final String SCRIPT_EXECUTE = "__trigger_execute__"; public static final String ACTION_TAG_OFFLINE = "__offline__"; public static final String ACTION_TAG_ALARM = "__alarm__"; From a646ead4c13e4e707a4e269ed31fda6bb4af92a3 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 8 Sep 2021 10:04:17 +0800 Subject: [PATCH 112/763] =?UTF-8?q?=E5=85=A8=E5=B1=80=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java index ad33c0c0..35384970 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java @@ -171,7 +171,7 @@ public Map getOfflineStatusScript() { public String createAction(String name,String tagName,String scriptId, String groupId) { - String response = zbxAction.createOfflineStatusAction(zbxApiToken,tagName,name, scriptId, groupId); + String response = zbxAction.createOfflineStatusAction(zbxApiToken,name,tagName, scriptId, groupId); return JSON.parseObject(response, ZbxResponseIds.class).getActionids()[0]; } From a175df21e1ec5a9def02d6849749a258bcbb488a Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 8 Sep 2021 14:05:36 +0800 Subject: [PATCH 113/763] =?UTF-8?q?=E5=85=A8=E5=B1=80=E6=A6=82=E8=A7=88=20?= =?UTF-8?q?=E5=91=8A=E8=AD=A6=E6=95=B0=E9=87=8F=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zeus/driver/entity/ZbxProblemInfo.java | 44 +++++ .../zmops/zeus/driver/service/ZbxProblem.java | 27 +++ .../api-json/problem/problem.get.ftl | 3 + .../web/alarm/controller/AlarmController.java | 8 + .../com/zmops/iot/web/alarm/dto/AlarmDto.java | 40 ++++ .../iot/web/alarm/dto/param/AlarmParam.java | 14 ++ .../iot/web/alarm/service/AlarmService.java | 44 +++++ .../analyse/controller/HomeController.java | 15 +- .../iot/web/analyse/service/HomeService.java | 172 +++++------------- .../web/analyse/service/ZbxChartsService.java | 146 +++++++++++++++ 10 files changed, 385 insertions(+), 128 deletions(-) create mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxProblemInfo.java create mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/AlarmParam.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxProblemInfo.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxProblemInfo.java new file mode 100644 index 00000000..556b5570 --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxProblemInfo.java @@ -0,0 +1,44 @@ +package com.zmops.zeus.driver.entity; + +import lombok.Data; + +/** + * @author nantian created at 2021/8/10 17:52 + */ +@Data +public class ZbxProblemInfo { + + private String eventid; + + private String source; + + private String object; + + private String objectid; + + private String clock; + + private String ns; + + private String r_eventid; + + private String r_clock; + + private String r_ns; + + private String correlationid; + + private String userid; + + private String name; + + private String acknowledged; + + private String severity; + + private String opdata; + + private String acknowledges; + + +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java new file mode 100644 index 00000000..12e025af --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java @@ -0,0 +1,27 @@ +package com.zmops.zeus.driver.service; + +import com.dtflys.forest.annotation.BaseRequest; +import com.dtflys.forest.annotation.Post; +import com.zmops.zeus.driver.annotation.JsonPath; +import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; + +/** + * @author nantian created at 2021/8/7 23:27 + */ + +@BaseRequest(baseURL = "${zbxApiUrl}", interceptor = JsonBodyBuildInterceptor.class) +public interface ZbxProblem { + + + /** + * 告警列表 + * + * @param hostId + * @return String + */ + @Post + @JsonPath("/problem/problem.get") + String getProblem(@ParamName("hostId") String hostId, @ParamName("timeFrom") long timeFrom); + +} diff --git a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl index 9b14dd97..10e30986 100644 --- a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl +++ b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl @@ -11,6 +11,9 @@ <#if hostId??> "hostids":"${hostId}" + <#if timeFrom??> + "time_from":${timeFrom}, + "filter":{ "source":"0" }, diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java index dd3e58d7..f5d65c36 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java @@ -1,7 +1,10 @@ package com.zmops.iot.web.alarm.controller; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.alarm.dto.param.AlarmParam; import com.zmops.iot.web.alarm.service.AlarmService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -19,4 +22,9 @@ public class AlarmController { public void test() { alarmService.test(); } + + @RequestMapping("/list") + public ResponseData getAlarmByPage(@RequestBody AlarmParam alarmParam){ + return ResponseData.success(alarmService.getAlarmByPage(alarmParam)); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java new file mode 100644 index 00000000..fab7d431 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java @@ -0,0 +1,40 @@ +package com.zmops.iot.web.alarm.dto; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class AlarmDto { + + private String eventid; + + private String source; + + private String object; + + private String clock; + + private String ns; + + private String r_eventid; + + private String r_clock; + + private String r_ns; + + private String correlationid; + + private String userid; + + private String name; + + private String acknowledged; + + private String severity; + + private String opdata; + + private String acknowledges; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/AlarmParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/AlarmParam.java new file mode 100644 index 00000000..29cd5fa6 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/AlarmParam.java @@ -0,0 +1,14 @@ +package com.zmops.iot.web.alarm.dto.param; + +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class AlarmParam extends BaseQueryParam { + private String deviceId; + + private long clock; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 1b81acec..cd07693f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -1,13 +1,22 @@ package com.zmops.iot.web.alarm.service; +import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.alarm.AlarmMessage; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.mediaType.AlarmCallback; +import com.zmops.iot.web.alarm.dto.AlarmDto; +import com.zmops.iot.web.alarm.dto.param.AlarmParam; +import com.zmops.zeus.driver.entity.ZbxProblemInfo; +import com.zmops.zeus.driver.service.ZbxProblem; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; /** * @author yefei @@ -18,6 +27,9 @@ public class AlarmService { @Autowired Collection alarmCallbacks; + @Autowired + ZbxProblem zbxProblem; + public void test() { List alarmMessages = new ArrayList<>(); @@ -28,4 +40,36 @@ public void test() { } }); } + + + public List getAlarmByPage(AlarmParam alarmParam) { + + List zbxProblemInfos = getAlarmList(alarmParam); + + //分页 + List problemList = zbxProblemInfos.stream().skip((alarmParam.getPage() - 1) * alarmParam.getMaxRow()).limit(alarmParam.getMaxRow()).collect(Collectors.toList()); + + //根据triggerid查询出deviceId + + + return null; + } + + public List getAlarmList(AlarmParam alarmParam) { + String hostId = null; + if (null != alarmParam.getDeviceId()) { + Device one = new QDevice().deviceId.eq(alarmParam.getDeviceId()).findOne(); + if (null == one) { + return Collections.EMPTY_LIST; + } + hostId = one.getZbxId(); + } + //从zbx取告警记录 + String problem = zbxProblem.getProblem(hostId, alarmParam.getClock()); + List zbxProblemInfos = JSONObject.parseArray(problem, ZbxProblemInfo.class); + + + return zbxProblemInfos; + } + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java index 934ed581..bd1f5bd6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java @@ -2,6 +2,7 @@ import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.web.analyse.service.HomeService; +import com.zmops.iot.web.analyse.service.ZbxChartsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -22,6 +23,9 @@ public class HomeController { @Autowired HomeService homeService; + @Autowired + ZbxChartsService zbxChartsService; + /** * 设备数量统计 */ @@ -30,6 +34,15 @@ public ResponseData getDeviceNum(){ return ResponseData.success(homeService.getDeviceNum()); } + /** + * 告警数量统计 + */ + @RequestMapping("/alarmNum") + public ResponseData getAlarmNum(){ + return ResponseData.success(homeService.getAlarmNum()); + } + + /** * 服务器取数速率 * @@ -57,6 +70,6 @@ public void getCookie(HttpServletResponse response, @RequestParam("attrIds") List attrIds, @RequestParam("width") String width, @RequestParam("height") String height) { - homeService.getCharts(response, from, to, attrIds, width, height); + zbxChartsService.getCharts(response, from, to, attrIds, width, height); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index 37f729e2..a7fb7633 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -5,26 +5,18 @@ import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.query.QProduct; -import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.alarm.dto.param.AlarmParam; +import com.zmops.iot.web.alarm.service.AlarmService; import com.zmops.iot.web.analyse.dto.LatestDto; import com.zmops.zeus.driver.entity.ZbxItemInfo; +import com.zmops.zeus.driver.entity.ZbxProblemInfo; import com.zmops.zeus.driver.service.ZbxHost; -import com.zmops.zeus.driver.service.ZbxInitService; import com.zmops.zeus.driver.service.ZbxItem; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.NameValuePair; -import org.apache.commons.httpclient.methods.PostMethod; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import javax.servlet.http.HttpServletResponse; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; import java.util.ArrayList; @@ -52,22 +44,12 @@ public class HomeService { HistoryService historyService; @Autowired - private ZbxInitService zbxInitService; - - @Value("${forest.variables.zbxServerIp}") - private String zbxServerIp; - - @Value("${forest.variables.zbxServerPort}") - private String zbxServerPort; + AlarmService alarmService; private static String hostId = ""; private static Map ITEM_Map = new ConcurrentHashMap<>(5); - private static String COOKIE = ""; - - private static LocalDateTime COOKIE_TIME; - //Zbx 指标取数速率 key private static final String KEY = "zabbix[wcache,values"; @@ -141,111 +123,6 @@ private static String formatName(String name) { } - /** - * 获取 数据图形展示 - * - * @param response http响应 - * @param from 开始时间 - * @param to 结束时间 - * @param attrIds 设备属性ID - * @param width 图表宽度 - * @param height 图表高度 - */ - public void getCharts(HttpServletResponse response, - String from, String to, - List attrIds, String width, String height) { - if (ToolUtil.isEmpty(COOKIE) || - LocalDateTimeUtils.betweenTwoTime(COOKIE_TIME, LocalDateTime.now(), ChronoUnit.DAYS) >= 30) { - getCookie(); - } - - List itemids = getItemIds(attrIds); - - HttpClient client = new HttpClient(); - PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort - + "/zabbix/chart.php?type=0&profileIdx=web.item.graph.filter"); - - NameValuePair[] nameValuePairs = new NameValuePair[itemids.size() + 4]; - nameValuePairs[0] = new NameValuePair("from", from); - nameValuePairs[1] = new NameValuePair("to", to); - nameValuePairs[2] = new NameValuePair("width", width); - nameValuePairs[3] = new NameValuePair("height", height); - - for (int index = 0; index < itemids.size(); index++) { - nameValuePairs[4 + index] = new NameValuePair("itemids[" + index + "]", itemids.get(index)); - } - - postMethod.setRequestBody(nameValuePairs); - postMethod.setRequestHeader("Content_Type", "application/json-rpc"); - postMethod.setRequestHeader("Cookie", COOKIE); - - OutputStream out = null; - try { - client.executeMethod(postMethod); - InputStream responseBody = postMethod.getResponseBodyAsStream(); - response.setContentType("image/jpeg"); - - out = response.getOutputStream(); - out.write(toByteArray(responseBody)); - - out.flush(); - } catch (IOException ioException) { - ioException.printStackTrace(); - } finally { - try { - if (null != out) { - out.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - } - - private static byte[] toByteArray(InputStream input) throws IOException { - ByteArrayOutputStream output = new ByteArrayOutputStream(); - - byte[] buffer = new byte[4096]; - int n = 0; - - while (-1 != (n = input.read(buffer))) { - output.write(buffer, 0, n); - } - - return output.toByteArray(); - } - - - private List getItemIds(List attrIds) { - return new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(attrIds).findSingleAttributeList(); - } - - /** - * 用户访客 获取cookie - */ - private void getCookie() { - HttpClient client = new HttpClient(); - PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort + "/zabbix/index.php"); - - //TODO 使用了一个只读权限的访客用户 - NameValuePair namePair = new NameValuePair("name", "cookie"); - NameValuePair pwdPair = new NameValuePair("password", "cookie"); - NameValuePair autologinPair = new NameValuePair("autologin", "1"); - NameValuePair enterPair = new NameValuePair("enter", "Sign in"); - - postMethod.setRequestBody(new NameValuePair[]{namePair, pwdPair, autologinPair, enterPair}); - postMethod.setRequestHeader("Content_Type", "application/json"); - - try { - client.executeMethod(postMethod); - } catch (IOException ioException) { - ioException.printStackTrace(); - } - COOKIE = postMethod.getResponseHeader("Set-Cookie").getValue(); - COOKIE_TIME = LocalDateTime.now(); - } - /** * 统计设备数量 * @@ -265,4 +142,45 @@ public Map getDeviceNum() { return deviceNumMap; } + /** + * 告警数量统计 + * + * @return + */ + private static final String[] severity = {"", "信息", "低级", "中级", "高级", "紧急"}; + + public Map getAlarmNum() { + AlarmParam alarmParam = new AlarmParam(); + //7天前的日期 + alarmParam.setClock(LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.minu(LocalDateTime.now(), 7, ChronoUnit.DAYS))); + List alarmList = alarmService.getAlarmList(alarmParam); + Map alarmMap = new HashMap<>(6); + if (ToolUtil.isEmpty(alarmList)) { + return alarmMap; + } + + Map> tmpMap = alarmList.parallelStream().filter(o -> o.getR_clock().equals("0") && !o.getSeverity().equals("0")).collect( + Collectors.groupingBy(ZbxProblemInfo::getSeverity, + Collectors.groupingBy(ZbxProblemInfo::getClock, Collectors.counting() + ) + ) + ); + + tmpMap.forEach((key, value) -> { + List list = new ArrayList(); + value.forEach((date, val) -> { + Map valMap = new HashMap<>(2); + valMap.put("date", date); + valMap.put("val", val); + list.add(valMap); + }); + alarmMap.put(severity[Integer.parseInt(key)], list); + }); + + //今日开始时间 + Long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); + Long todayAlarmNum = alarmList.parallelStream().filter(o -> Long.parseLong(o.getClock()) >= timeStart).collect(Collectors.counting()); + alarmMap.put("today", todayAlarmNum); + return alarmMap; + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java new file mode 100644 index 00000000..e2bf1c99 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java @@ -0,0 +1,146 @@ +package com.zmops.iot.web.analyse.service; + +import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.util.LocalDateTimeUtils; +import com.zmops.iot.util.ToolUtil; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.methods.PostMethod; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.List; + +/** + * @author yefei + *

+ * 全局概览服务 + **/ +@Service +public class ZbxChartsService { + + @Value("${forest.variables.zbxServerIp}") + private String zbxServerIp; + + @Value("${forest.variables.zbxServerPort}") + private String zbxServerPort; + + private static String COOKIE = ""; + + private static LocalDateTime COOKIE_TIME; + + + /** + * 获取 数据图形展示 + * + * @param response http响应 + * @param from 开始时间 + * @param to 结束时间 + * @param attrIds 设备属性ID + * @param width 图表宽度 + * @param height 图表高度 + */ + public void getCharts(HttpServletResponse response, + String from, String to, + List attrIds, String width, String height) { + if (ToolUtil.isEmpty(COOKIE) || + LocalDateTimeUtils.betweenTwoTime(COOKIE_TIME, LocalDateTime.now(), ChronoUnit.DAYS) >= 30) { + getCookie(); + } + + List itemids = getItemIds(attrIds); + + HttpClient client = new HttpClient(); + PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort + + "/zabbix/chart.php?type=0&profileIdx=web.item.graph.filter"); + + NameValuePair[] nameValuePairs = new NameValuePair[itemids.size() + 4]; + nameValuePairs[0] = new NameValuePair("from", from); + nameValuePairs[1] = new NameValuePair("to", to); + nameValuePairs[2] = new NameValuePair("width", width); + nameValuePairs[3] = new NameValuePair("height", height); + + for (int index = 0; index < itemids.size(); index++) { + nameValuePairs[4 + index] = new NameValuePair("itemids[" + index + "]", itemids.get(index)); + } + + postMethod.setRequestBody(nameValuePairs); + postMethod.setRequestHeader("Content_Type", "application/json-rpc"); + postMethod.setRequestHeader("Cookie", COOKIE); + + OutputStream out = null; + try { + client.executeMethod(postMethod); + InputStream responseBody = postMethod.getResponseBodyAsStream(); + response.setContentType("image/jpeg"); + + out = response.getOutputStream(); + out.write(toByteArray(responseBody)); + + out.flush(); + } catch (IOException ioException) { + ioException.printStackTrace(); + } finally { + try { + if (null != out) { + out.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + } + + private static byte[] toByteArray(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + + byte[] buffer = new byte[4096]; + int n = 0; + + while (-1 != (n = input.read(buffer))) { + output.write(buffer, 0, n); + } + + return output.toByteArray(); + } + + + private List getItemIds(List attrIds) { + return new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(attrIds).findSingleAttributeList(); + } + + /** + * 用户访客 获取cookie + */ + private void getCookie() { + HttpClient client = new HttpClient(); + PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort + "/zabbix/index.php"); + + //TODO 使用了一个只读权限的访客用户 + NameValuePair namePair = new NameValuePair("name", "cookie"); + NameValuePair pwdPair = new NameValuePair("password", "cookie"); + NameValuePair autologinPair = new NameValuePair("autologin", "1"); + NameValuePair enterPair = new NameValuePair("enter", "Sign in"); + + postMethod.setRequestBody(new NameValuePair[]{namePair, pwdPair, autologinPair, enterPair}); + postMethod.setRequestHeader("Content_Type", "application/json"); + + try { + client.executeMethod(postMethod); + } catch (IOException ioException) { + ioException.printStackTrace(); + } + COOKIE = postMethod.getResponseHeader("Set-Cookie").getValue(); + COOKIE_TIME = LocalDateTime.now(); + } + + +} From 86fd71cf12b4ca4b28442a3884f0b42b4b03d387 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 8 Sep 2021 15:08:14 +0800 Subject: [PATCH 114/763] =?UTF-8?q?=E6=9C=80=E6=96=B0=E6=95=B0=E6=8D=AE=20?= =?UTF-8?q?=E5=8E=BB=E9=87=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zmops/iot/web/analyse/service/HomeService.java | 12 +++++++++--- .../iot/web/analyse/service/LatestService.java | 14 +++++++++----- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index a7fb7633..f89016d1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -154,7 +154,7 @@ public Map getAlarmNum() { //7天前的日期 alarmParam.setClock(LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.minu(LocalDateTime.now(), 7, ChronoUnit.DAYS))); List alarmList = alarmService.getAlarmList(alarmParam); - Map alarmMap = new HashMap<>(6); + Map alarmMap = new HashMap<>(3); if (ToolUtil.isEmpty(alarmList)) { return alarmMap; } @@ -166,6 +166,7 @@ public Map getAlarmNum() { ) ); + Map trendsMap = new HashMap<>(6); tmpMap.forEach((key, value) -> { List list = new ArrayList(); value.forEach((date, val) -> { @@ -174,13 +175,18 @@ public Map getAlarmNum() { valMap.put("val", val); list.add(valMap); }); - alarmMap.put(severity[Integer.parseInt(key)], list); + trendsMap.put(severity[Integer.parseInt(key)], list); }); + alarmMap.put("trnds", trendsMap); + + long total = alarmList.parallelStream().filter(o -> "0".equals(o.getR_clock()) && !"0".equals(o.getSeverity())).count(); + alarmMap.put("total", total); //今日开始时间 Long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); - Long todayAlarmNum = alarmList.parallelStream().filter(o -> Long.parseLong(o.getClock()) >= timeStart).collect(Collectors.counting()); + Long todayAlarmNum = alarmList.parallelStream().filter(o -> Long.parseLong(o.getClock()) >= timeStart).count(); alarmMap.put("today", todayAlarmNum); + return alarmMap; } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java index c89cb7b1..ab109e64 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java @@ -14,10 +14,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; /** @@ -41,7 +38,7 @@ public Pager qeuryLatest(LatestParam latestParam) { List latestDtos = qeuryLatest(latestParam.getDeviceId(), latestParam.getAttrIds()); List collect = latestDtos.stream().skip((latestParam.getPage() - 1) * latestParam.getMaxRow()) .limit(latestParam.getMaxRow()).collect(Collectors.toList()); - return new Pager<>(collect,latestDtos.size()); + return new Pager<>(collect, latestDtos.size()); } public List qeuryLatest(String deviceId, List attrIds) { @@ -70,6 +67,13 @@ public List qeuryLatest(String deviceId, List attrIds) { latestDtos.addAll(JSONObject.parseArray(res, LatestDto.class)); } + //根据itemid去重 + latestDtos = latestDtos.parallelStream().collect( + Collectors.collectingAndThen( + Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(LatestDto::getItemid))), + ArrayList::new) + ); + latestDtos.forEach(latestDto -> { latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); if (null != itemIdMap.get(latestDto.getItemid())) { From 1253d137612a626359d24139e31cc2c617ae9f5e Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 8 Sep 2021 16:25:29 +0800 Subject: [PATCH 115/763] =?UTF-8?q?=E5=85=A8=E5=B1=80=E6=A6=82=E8=A7=88=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=97=B6=E9=97=B4=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zmops/zeus/driver/service/ZbxProblem.java | 5 +- .../api-json/problem/problem.get.ftl | 5 +- .../iot/web/alarm/dto/param/AlarmParam.java | 5 +- .../iot/web/alarm/service/AlarmService.java | 2 +- .../analyse/controller/HomeController.java | 10 +- .../iot/web/analyse/service/HomeService.java | 91 ++++++++++--------- 6 files changed, 68 insertions(+), 50 deletions(-) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java index 12e025af..71ba63d8 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java @@ -22,6 +22,9 @@ public interface ZbxProblem { */ @Post @JsonPath("/problem/problem.get") - String getProblem(@ParamName("hostId") String hostId, @ParamName("timeFrom") long timeFrom); + String getProblem(@ParamName("hostId") String hostId, + @ParamName("timeFrom") Long timeFrom, + @ParamName("timeTill") Long timeTill, + @ParamName("recent") String recent); } diff --git a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl index 10e30986..31181186 100644 --- a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl +++ b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl @@ -6,7 +6,7 @@ "selectAcknowledges": "extend", "selectTags": "extend", "selectSuppressionData": "extend", - "recent": "true", + "recent": ${recent}, "sortfield": ["eventid"], <#if hostId??> "hostids":"${hostId}" @@ -14,6 +14,9 @@ <#if timeFrom??> "time_from":${timeFrom}, + <#if timeTill??> + "time_till":${timeTill}, + "filter":{ "source":"0" }, diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/AlarmParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/AlarmParam.java index 29cd5fa6..df4780ad 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/AlarmParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/AlarmParam.java @@ -10,5 +10,8 @@ public class AlarmParam extends BaseQueryParam { private String deviceId; - private long clock; + private Long timeFrom; + private Long timeTill; + + private String recent = "true"; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index cd07693f..c2a0fcf5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -65,7 +65,7 @@ public List getAlarmList(AlarmParam alarmParam) { hostId = one.getZbxId(); } //从zbx取告警记录 - String problem = zbxProblem.getProblem(hostId, alarmParam.getClock()); + String problem = zbxProblem.getProblem(hostId, alarmParam.getTimeFrom(),alarmParam.getTimeTill(),alarmParam.getRecent()); List zbxProblemInfos = JSONObject.parseArray(problem, ZbxProblemInfo.class); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java index bd1f5bd6..b8e7a70d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java @@ -30,7 +30,7 @@ public class HomeController { * 设备数量统计 */ @RequestMapping("/deviceNum") - public ResponseData getDeviceNum(){ + public ResponseData getDeviceNum() { return ResponseData.success(homeService.getDeviceNum()); } @@ -38,8 +38,8 @@ public ResponseData getDeviceNum(){ * 告警数量统计 */ @RequestMapping("/alarmNum") - public ResponseData getAlarmNum(){ - return ResponseData.success(homeService.getAlarmNum()); + public ResponseData getAlarmNum(@RequestParam("timeFrom") long timeFrom, @RequestParam("timeTill") long timeTill) { + return ResponseData.success(homeService.getAlarmNum(timeFrom, timeTill)); } @@ -49,8 +49,8 @@ public ResponseData getAlarmNum(){ * @return */ @RequestMapping("/collectonRate") - public ResponseData collectonRate() { - return ResponseData.success(homeService.collectonRate()); + public ResponseData collectonRate(@RequestParam("timeFrom") long timeFrom, @RequestParam("timeTill") long timeTill) { + return ResponseData.success(homeService.collectonRate(timeFrom, timeTill)); } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index f89016d1..a68be6ea 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -18,11 +18,7 @@ import org.springframework.stereotype.Service; import java.time.LocalDateTime; -import java.time.temporal.ChronoUnit; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -58,20 +54,19 @@ public class HomeService { * * @return */ - public Map> collectonRate() { + public List> collectonRate(long timeFrom, long timeTill) { if (ToolUtil.isEmpty(hostId)) { if (ToolUtil.isEmpty(getZbxServerId())) { - return new HashMap<>(0); + return Collections.emptyList(); } } if (ToolUtil.isEmpty(ITEM_Map)) { if (ToolUtil.isEmpty(getItemMap())) { - return new HashMap<>(0); + return Collections.emptyList(); } } - List itemIds = new ArrayList<>(ITEM_Map.keySet()); - List latestDtos = historyService.queryHitoryData(hostId, itemIds, 0, LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.minu(LocalDateTime.now(), - 7, ChronoUnit.DAYS)), LocalDateTimeUtils.getSecondsByTime(LocalDateTime.now())); + List itemIds = new ArrayList<>(ITEM_Map.keySet()); + List latestDtos = historyService.queryHitoryData(hostId, itemIds, 0, timeFrom, timeTill); latestDtos.forEach(latestDto -> { latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); @@ -79,8 +74,15 @@ public Map> collectonRate() { latestDto.setName(ITEM_Map.get(latestDto.getItemid())); } }); - - return latestDtos.parallelStream().collect(Collectors.groupingBy(LatestDto::getName)); + Map> collect = latestDtos.parallelStream().collect(Collectors.groupingBy(LatestDto::getName)); + List> collectList = new ArrayList(); + collect.forEach((key, value) -> { + Map collectMap = new HashMap<>(2); + collectMap.put("name", key); + collectMap.put("data", value); + collectList.add(collectMap); + }); + return collectList; } /** @@ -149,42 +151,49 @@ public Map getDeviceNum() { */ private static final String[] severity = {"", "信息", "低级", "中级", "高级", "紧急"}; - public Map getAlarmNum() { + public Map getAlarmNum(long timeFrom, long timeTill) { AlarmParam alarmParam = new AlarmParam(); - //7天前的日期 - alarmParam.setClock(LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.minu(LocalDateTime.now(), 7, ChronoUnit.DAYS))); + alarmParam.setRecent("false"); List alarmList = alarmService.getAlarmList(alarmParam); Map alarmMap = new HashMap<>(3); - if (ToolUtil.isEmpty(alarmList)) { - return alarmMap; - } - Map> tmpMap = alarmList.parallelStream().filter(o -> o.getR_clock().equals("0") && !o.getSeverity().equals("0")).collect( - Collectors.groupingBy(ZbxProblemInfo::getSeverity, - Collectors.groupingBy(ZbxProblemInfo::getClock, Collectors.counting() - ) - ) - ); - - Map trendsMap = new HashMap<>(6); - tmpMap.forEach((key, value) -> { - List list = new ArrayList(); - value.forEach((date, val) -> { - Map valMap = new HashMap<>(2); - valMap.put("date", date); - valMap.put("val", val); - list.add(valMap); + if (ToolUtil.isNotEmpty(alarmList)) { + + alarmMap.put("total", alarmList.size()); + + //过滤出指定时间段内的告警 + Map> tmpMap = alarmList.parallelStream() + .filter(o -> !o.getSeverity().equals("0") + && Long.parseLong(o.getClock()) >= timeFrom + && Long.parseLong(o.getClock()) < timeTill + ).collect( + Collectors.groupingBy(ZbxProblemInfo::getSeverity, + Collectors.groupingBy(ZbxProblemInfo::getClock, Collectors.counting() + ) + ) + ); + + Map trendsMap = new HashMap<>(6); + tmpMap.forEach((key, value) -> { + List list = new ArrayList(); + value.forEach((date, val) -> { + Map valMap = new HashMap<>(2); + valMap.put("date", date); + valMap.put("val", val); + list.add(valMap); + }); + trendsMap.put(severity[Integer.parseInt(key)], list); }); - trendsMap.put(severity[Integer.parseInt(key)], list); - }); - alarmMap.put("trnds", trendsMap); + alarmMap.put("trends", trendsMap); + } - long total = alarmList.parallelStream().filter(o -> "0".equals(o.getR_clock()) && !"0".equals(o.getSeverity())).count(); - alarmMap.put("total", total); //今日开始时间 - Long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); - Long todayAlarmNum = alarmList.parallelStream().filter(o -> Long.parseLong(o.getClock()) >= timeStart).count(); + Long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); + AlarmParam todayParam = new AlarmParam(); + todayParam.setTimeFrom(timeStart); + List todayAlarmList = alarmService.getAlarmList(todayParam); + Long todayAlarmNum = todayAlarmList.parallelStream().filter(o -> !o.getSeverity().equals("0")).count(); alarmMap.put("today", todayAlarmNum); return alarmMap; From 846476c1af1f6a32afd489b4c27129ad392e8af0 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 8 Sep 2021 16:35:20 +0800 Subject: [PATCH 116/763] =?UTF-8?q?=E5=85=A8=E5=B1=80=E6=A6=82=E8=A7=88=20?= =?UTF-8?q?=E5=8F=96=E6=95=B0=E9=80=9F=E7=8E=87=20=E5=8E=BB=E9=99=A4?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E6=A0=BC=E5=BC=8F=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/zmops/iot/web/analyse/service/HomeService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index a68be6ea..eb0aa0c5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -69,7 +69,7 @@ public List> collectonRate(long timeFrom, long timeTill) { List latestDtos = historyService.queryHitoryData(hostId, itemIds, 0, timeFrom, timeTill); latestDtos.forEach(latestDto -> { - latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); +// latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); if (null != ITEM_Map.get(latestDto.getItemid())) { latestDto.setName(ITEM_Map.get(latestDto.getItemid())); } From 815c57e9b36049b9136d1d8a91acb2eb7746875f Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 8 Sep 2021 17:35:22 +0800 Subject: [PATCH 117/763] =?UTF-8?q?=E5=85=A8=E5=B1=80=E6=A6=82=E8=A7=88=20?= =?UTF-8?q?=E5=91=8A=E8=AD=A6=E7=BB=9F=E8=AE=A1=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zmops/iot/web/analyse/service/HomeService.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index eb0aa0c5..44f236a4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -172,19 +172,21 @@ public Map getAlarmNum(long timeFrom, long timeTill) { ) ) ); - - Map trendsMap = new HashMap<>(6); + List> trendsList = new ArrayList<>(); tmpMap.forEach((key, value) -> { - List list = new ArrayList(); + Map trendsMap = new HashMap<>(2); + List list = new ArrayList<>(); value.forEach((date, val) -> { Map valMap = new HashMap<>(2); valMap.put("date", date); valMap.put("val", val); list.add(valMap); }); - trendsMap.put(severity[Integer.parseInt(key)], list); + trendsMap.put("name", severity[Integer.parseInt(key)]); + trendsMap.put("data", list); + trendsList.add(trendsMap); }); - alarmMap.put("trends", trendsMap); + alarmMap.put("trends", trendsList); } From 8778f5799cb230585199e4fe77a4525a48804629 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 8 Sep 2021 17:40:28 +0800 Subject: [PATCH 118/763] =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=8C=96=E6=97=B6?= =?UTF-8?q?=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/zmops/iot/web/analyse/service/HomeService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index 44f236a4..a6010d90 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -69,7 +69,7 @@ public List> collectonRate(long timeFrom, long timeTill) { List latestDtos = historyService.queryHitoryData(hostId, itemIds, 0, timeFrom, timeTill); latestDtos.forEach(latestDto -> { -// latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); + latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); if (null != ITEM_Map.get(latestDto.getItemid())) { latestDto.setName(ITEM_Map.get(latestDto.getItemid())); } From 611d6437cc6445cb0da9794e6e6516971814787e Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 8 Sep 2021 17:52:18 +0800 Subject: [PATCH 119/763] =?UTF-8?q?=E8=B6=8B=E5=8A=BF=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E9=A1=BA=E5=BA=8F=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/zmops/iot/web/analyse/service/HomeService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index a6010d90..543d5dca 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -67,7 +67,7 @@ public List> collectonRate(long timeFrom, long timeTill) { } List itemIds = new ArrayList<>(ITEM_Map.keySet()); List latestDtos = historyService.queryHitoryData(hostId, itemIds, 0, timeFrom, timeTill); - + Collections.reverse(latestDtos); latestDtos.forEach(latestDto -> { latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); if (null != ITEM_Map.get(latestDto.getItemid())) { From 0acdfa6c68432d2bba8f602059b023ef7e0c3bd5 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 8 Sep 2021 18:32:23 +0800 Subject: [PATCH 120/763] =?UTF-8?q?=E5=85=A8=E5=B1=80=E6=A6=82=E8=A7=88=20?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=E6=95=B0=E6=8D=AE=E6=A0=BC=E5=BC=8F=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/analyse/service/HistoryService.java | 6 ++-- .../iot/web/analyse/service/HomeService.java | 29 ++++++++----------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java index abc043aa..cffde152 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java @@ -66,7 +66,7 @@ public List queryHistory(String deviceId, List attrIds, Long ti } //根据属性值类型 分组查询历史数据 for (Map.Entry> map : valueTypeMap.entrySet()) { - latestDtos.addAll(queryHitoryData(one.getZbxId(), zbxIds, Integer.parseInt(map.getKey()), timeFrom, timeTill)); + latestDtos.addAll(queryHitoryData(one.getZbxId(), zbxIds,1000, Integer.parseInt(map.getKey()), timeFrom, timeTill)); } latestDtos.forEach(latestDto -> { @@ -81,8 +81,8 @@ public List queryHistory(String deviceId, List attrIds, Long ti return latestDtos; } - public List queryHitoryData(String hostId, List itemIds, Integer valueType, Long timeFrom, Long timeTill) { - String res = zbxHistoryGet.historyGet(hostId, itemIds, 1000, valueType, timeFrom, timeTill); + public List queryHitoryData(String hostId, List itemIds,int hisNum, Integer valueType, Long timeFrom, Long timeTill) { + String res = zbxHistoryGet.historyGet(hostId, itemIds, hisNum, valueType, timeFrom, timeTill); return JSONObject.parseArray(res, LatestDto.class); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index 543d5dca..a041be0d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -66,16 +66,18 @@ public List> collectonRate(long timeFrom, long timeTill) { } } List itemIds = new ArrayList<>(ITEM_Map.keySet()); - List latestDtos = historyService.queryHitoryData(hostId, itemIds, 0, timeFrom, timeTill); + List latestDtos = historyService.queryHitoryData(hostId, itemIds,100000, 0, timeFrom, timeTill); Collections.reverse(latestDtos); latestDtos.forEach(latestDto -> { - latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); + latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd")); if (null != ITEM_Map.get(latestDto.getItemid())) { latestDto.setName(ITEM_Map.get(latestDto.getItemid())); } }); - Map> collect = latestDtos.parallelStream().collect(Collectors.groupingBy(LatestDto::getName)); - List> collectList = new ArrayList(); + Map> collect = latestDtos.parallelStream().collect( + Collectors.groupingBy(LatestDto::getName, Collectors.groupingBy(LatestDto::getClock, Collectors.averagingDouble(o -> Double.parseDouble(o.getValue())))) + ); + List> collectList = new ArrayList(); collect.forEach((key, value) -> { Map collectMap = new HashMap<>(2); collectMap.put("name", key); @@ -172,24 +174,17 @@ public Map getAlarmNum(long timeFrom, long timeTill) { ) ) ); + List> trendsList = new ArrayList<>(); tmpMap.forEach((key, value) -> { - Map trendsMap = new HashMap<>(2); - List list = new ArrayList<>(); - value.forEach((date, val) -> { - Map valMap = new HashMap<>(2); - valMap.put("date", date); - valMap.put("val", val); - list.add(valMap); - }); - trendsMap.put("name", severity[Integer.parseInt(key)]); - trendsMap.put("data", list); - trendsList.add(trendsMap); + Map collectMap = new HashMap<>(2); + collectMap.put("name", severity[Integer.parseInt(key)]); + collectMap.put("data", value); + trendsList.add(collectMap); }); alarmMap.put("trends", trendsList); } - - + //今日开始时间 Long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); AlarmParam todayParam = new AlarmParam(); From f0fd1f01a9c0f9ada3db49b7604b8aed9857a700 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 8 Sep 2021 18:57:05 +0800 Subject: [PATCH 121/763] =?UTF-8?q?=E5=85=A8=E5=B1=80=E6=A6=82=E8=A7=88=20?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=A0=BC=E5=BC=8F=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/web/analyse/service/HomeService.java | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index a041be0d..ea13942c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -66,7 +66,7 @@ public List> collectonRate(long timeFrom, long timeTill) { } } List itemIds = new ArrayList<>(ITEM_Map.keySet()); - List latestDtos = historyService.queryHitoryData(hostId, itemIds,100000, 0, timeFrom, timeTill); + List latestDtos = historyService.queryHitoryData(hostId, itemIds, 100000, 0, timeFrom, timeTill); Collections.reverse(latestDtos); latestDtos.forEach(latestDto -> { latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd")); @@ -79,11 +79,19 @@ public List> collectonRate(long timeFrom, long timeTill) { ); List> collectList = new ArrayList(); collect.forEach((key, value) -> { - Map collectMap = new HashMap<>(2); + Map collectMap = new HashMap<>(2); + List> tmpList = new ArrayList<>(); + value.forEach((date, val) -> { + Map valMap = new HashMap<>(2); + valMap.put("date", date); + valMap.put("val", val); + tmpList.add(valMap); + }); collectMap.put("name", key); - collectMap.put("data", value); + collectMap.put("data", tmpList); collectList.add(collectMap); }); + return collectList; } @@ -174,17 +182,24 @@ public Map getAlarmNum(long timeFrom, long timeTill) { ) ) ); - List> trendsList = new ArrayList<>(); tmpMap.forEach((key, value) -> { - Map collectMap = new HashMap<>(2); - collectMap.put("name", severity[Integer.parseInt(key)]); - collectMap.put("data", value); - trendsList.add(collectMap); + Map trendsMap = new HashMap<>(2); + List list = new ArrayList<>(); + value.forEach((date, val) -> { + Map valMap = new HashMap<>(2); + valMap.put("date", date); + valMap.put("val", val); + list.add(valMap); + }); + trendsMap.put("name", severity[Integer.parseInt(key)]); + trendsMap.put("data", list); + trendsList.add(trendsMap); }); alarmMap.put("trends", trendsList); } - + + //今日开始时间 Long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); AlarmParam todayParam = new AlarmParam(); From 56c70444cd97d06c587212fe3279d8e0280b49e5 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 8 Sep 2021 19:24:51 +0800 Subject: [PATCH 122/763] =?UTF-8?q?=E5=85=A8=E5=B1=80=E6=A6=82=E8=A7=88=20?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E6=A0=BC=E5=BC=8F=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/zmops/iot/web/analyse/service/HomeService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index ea13942c..08ddaf48 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -170,15 +170,15 @@ public Map getAlarmNum(long timeFrom, long timeTill) { if (ToolUtil.isNotEmpty(alarmList)) { alarmMap.put("total", alarmList.size()); - - //过滤出指定时间段内的告警 + Collections.reverse(alarmList); + //过滤出指定时间段内的告警 并顺序排序 Map> tmpMap = alarmList.parallelStream() .filter(o -> !o.getSeverity().equals("0") && Long.parseLong(o.getClock()) >= timeFrom && Long.parseLong(o.getClock()) < timeTill ).collect( Collectors.groupingBy(ZbxProblemInfo::getSeverity, - Collectors.groupingBy(ZbxProblemInfo::getClock, Collectors.counting() + Collectors.groupingBy(o -> LocalDateTimeUtils.convertTimeToString(Integer.parseInt(o.getClock()), "yyyy-MM-dd"), Collectors.counting() ) ) ); From aefb67b4d35b7277abefecb404aeeee3fab8ef53 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 8 Sep 2021 21:14:31 +0800 Subject: [PATCH 123/763] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E5=9C=A8=E7=BA=BF?= =?UTF-8?q?=E6=83=85=E5=86=B5=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/zmops/iot/domain/device/Device.java | 4 +-- .../iot/domain/device/DeviceOnlineReprot.java | 28 +++++++++++++++++++ .../domain/device/ServiceExecuteRecord.java | 26 +++++++++++++++++ .../zmops/iot/web/device/dto/DeviceDto.java | 2 ++ .../schedule/DeviceOnlineReprotSchedule.java | 26 +++++++++++++++++ 5 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReprot.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/device/ServiceExecuteRecord.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java index 0978267f..75fba808 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java @@ -1,13 +1,11 @@ package com.zmops.iot.domain.device; -import com.zmops.iot.constant.IdTypeConsts; import com.zmops.iot.domain.BaseEntity; import io.ebean.annotation.Aggregation; import lombok.Data; import lombok.EqualsAndHashCode; import javax.persistence.Entity; -import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; @@ -39,6 +37,8 @@ public class Device extends BaseEntity { private String position; + private Integer online; + @Aggregation("count(*)") Long totalCount; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReprot.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReprot.java new file mode 100644 index 00000000..62710186 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReprot.java @@ -0,0 +1,28 @@ +package com.zmops.iot.domain.device; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Table(name = "device_online_report") +@Entity +public class DeviceOnlineReprot { + + @Id + private Long id; + + private String createTime; + + private Integer online; + + private Integer offline; + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/ServiceExecuteRecord.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/ServiceExecuteRecord.java new file mode 100644 index 00000000..4c204b99 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/ServiceExecuteRecord.java @@ -0,0 +1,26 @@ +package com.zmops.iot.domain.device; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.time.LocalDateTime; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Table(name = "service_execute_record") +@Entity +public class ServiceExecuteRecord { + + @Id + private Long id; + + private LocalDateTime createTime; + + private Long serviceId; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java index d3365291..52d2ffdb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java @@ -66,4 +66,6 @@ public class DeviceDto { private String position; + private Integer online; + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java new file mode 100644 index 00000000..1c030d99 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java @@ -0,0 +1,26 @@ +package com.zmops.iot.web.device.schedule; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +/** + * @author yefei + **/ +@EnableScheduling +@Component +@Slf4j +public class DeviceOnlineReprotSchedule { + + @Scheduled(cron = "0 59 23 1/1 * ? ") + public void report(){ + log.info("开始查询设备在线情况"); + + //TODO 统计出 当前 设备在线情况 + + //插入 在线情况表 + + } + +} From 3a367b085180864cd36e7c4c355c764c342787f2 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 8 Sep 2021 22:53:04 +0800 Subject: [PATCH 124/763] adjust global maven packaging structure. --- dist-material/log4j2.xml | 44 +++++ iot-common/iot-datacarrier/pom.xml | 81 ++------- iot-common/pom.xml | 3 +- iot-server-bom/pom.xml | 99 ++++++++++ iot-server-dist/pom.xml | 24 --- iot-server-pom/pom.xml | 133 -------------- iot-server/pom.xml | 55 ++++-- iot-server/server-bootstrap/pom.xml | 2 +- .../server/core/analysis/StreamProcessor.java | 2 +- .../http-receiver-plugin/pom.xml | 1 - .../mqtt-receiver-plugin/pom.xml | 1 - .../tcp-receiver-plugin/pom.xml | 1 - iot-server/server-sender/pom.xml | 1 + pom.xml | 172 ++++++------------ zeus-alarm/pom.xml | 4 +- zeus-common/pom.xml | 3 +- zeus-core/pom.xml | 3 +- zeus-driver/pom.xml | 3 +- zeus-iot-dist/pom.xml | 91 +++++++++ zeus-iot-dist/src/main/assembly/binary.xml | 70 +++++++ zeus-rest/pom.xml | 3 +- zeus-starter/pom.xml | 3 +- zeus-starter/src/main/assembly/webapp.yml | 46 +++++ zeus-webapp-bom/pom.xml | 153 ++++++++++++++++ zeus-webapp/pom.xml | 3 +- 25 files changed, 628 insertions(+), 373 deletions(-) create mode 100644 dist-material/log4j2.xml create mode 100644 iot-server-bom/pom.xml delete mode 100644 iot-server-dist/pom.xml delete mode 100644 iot-server-pom/pom.xml create mode 100644 zeus-iot-dist/pom.xml create mode 100644 zeus-iot-dist/src/main/assembly/binary.xml create mode 100644 zeus-starter/src/main/assembly/webapp.yml create mode 100644 zeus-webapp-bom/pom.xml diff --git a/dist-material/log4j2.xml b/dist-material/log4j2.xml new file mode 100644 index 00000000..5d09ef22 --- /dev/null +++ b/dist-material/log4j2.xml @@ -0,0 +1,44 @@ + + + + + + ${sys:oap.logDir} + + + + + %d - %c - %L [%t] %-5p %x - %m%n + + + + + + + + + + + + + + + + diff --git a/iot-common/iot-datacarrier/pom.xml b/iot-common/iot-datacarrier/pom.xml index 8fc7799b..ebc60bb8 100644 --- a/iot-common/iot-datacarrier/pom.xml +++ b/iot-common/iot-datacarrier/pom.xml @@ -1,75 +1,22 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - com.zmops - iot-datacarrier - 1.0-beta + + iot-common + com.zmops + 1.0-beta + - iot-datacarrier - - http://www.example.com + iot-datacarrier + 1.0-beta - - UTF-8 - 1.7 - 1.7 - + iot-datacarrier - - - junit - junit - 4.11 - test - - - - - - - - - maven-clean-plugin - 3.1.0 - - - - maven-resources-plugin - 3.0.2 - - - maven-compiler-plugin - 3.8.0 - - - maven-surefire-plugin - 2.22.1 - - - maven-jar-plugin - 3.0.2 - - - maven-install-plugin - 2.5.2 - - - maven-deploy-plugin - 2.8.2 - - - - maven-site-plugin - 3.7.1 - - - maven-project-info-reports-plugin - 3.0.0 - - - - + + 8 + 8 + diff --git a/iot-common/pom.xml b/iot-common/pom.xml index 5647a4c4..84d2aa1d 100644 --- a/iot-common/pom.xml +++ b/iot-common/pom.xml @@ -3,10 +3,9 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - zeus-iot-server + zeus-iot com.zmops 1.0-beta - ../iot-server-dist/pom.xml 4.0.0 diff --git a/iot-server-bom/pom.xml b/iot-server-bom/pom.xml new file mode 100644 index 00000000..749b410b --- /dev/null +++ b/iot-server-bom/pom.xml @@ -0,0 +1,99 @@ + + + + + com.zmops + zeus-iot + 1.0-beta + + + pom + 4.0.0 + iot-server-bom + + IoT Server 协议解析层 + + + 2.25.4 + 1.18.20 + 2.13.3 + 25.1-jre + 4.1.65.Final + 2.8.7 + + + + + + io.netty + netty-bom + ${netty.version} + import + pom + + + org.projectlombok + lombok + ${lombok.version} + + + org.apache.logging.log4j + log4j-api + ${log4j.version} + + + org.apache.logging.log4j + log4j-slf4j-impl + ${log4j.version} + + + com.google.guava + guava + ${guava.version} + + + + org.apache.logging.log4j + log4j-core + ${log4j.version} + + + org.apache.camel + camel-core + ${camel.version} + + + org.apache.camel + camel-jsonpath + ${camel.version} + + + com.google.code.gson + gson + ${gson.version} + + + org.apache.camel + camel-zabbix-agent + ${camel.version} + + + org.apache.camel + camel-netty4-http + ${camel.version} + + + org.apache.camel + camel-netty4 + ${camel.version} + + + org.apache.camel + camel-mqtt + ${camel.version} + + + + \ No newline at end of file diff --git a/iot-server-dist/pom.xml b/iot-server-dist/pom.xml deleted file mode 100644 index 79d0ff67..00000000 --- a/iot-server-dist/pom.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - iot-server-pom - com.zmops - 1.0-beta - ../iot-server-pom/pom.xml - - 4.0.0 - - zeus-iot-server - pom - - ../iot-common - - - - 8 - 8 - - - \ No newline at end of file diff --git a/iot-server-pom/pom.xml b/iot-server-pom/pom.xml deleted file mode 100644 index e6d59db0..00000000 --- a/iot-server-pom/pom.xml +++ /dev/null @@ -1,133 +0,0 @@ - - - 4.0.0 - - com.zmops - iot-server-pom - 1.0-beta - - pom - - - ../iot-server - ../iot-server-dist - - - - 1.8 - 8 - 8 - - UTF-8 - - 1.6.2 - 3.0.0-M2 - - 2.8.2 - 3.1.0 - 3.1.0 - 3.8.0 - 3.1.0 - 3.0.1 - 1.8 - 3.1.1 - 0.4.13 - 2.25.4 - - - - - - - - maven-antrun-plugin - ${maven-antrun-plugin.version} - - - maven-deploy-plugin - ${maven-deploy-plugin.version} - - - maven-assembly-plugin - ${maven-assembly-plugin.version} - - - maven-jar-plugin - ${maven-jar-plugin.version} - - true - - - - maven-shade-plugin - ${maven-shade-plugin.version} - - - - - - kr.motd.maven - os-maven-plugin - ${os-maven-plugin.version} - - - initialize - - detect - - - - - - maven-enforcer-plugin - ${maven-enforcer-plugin.version} - - - enforce-java - - enforce - - validate - - - - - 1.8 - - - 3.6 - - - - - - - - maven-compiler-plugin - ${maven-compiler-plugin.version} - - ${compiler.version} - ${compiler.version} - ${project.build.sourceEncoding} - - - - maven-resources-plugin - ${maven-resource-plugin.version} - - ${project.build.sourceEncoding} - - - - com.spotify - docker-maven-plugin - ${docker.plugin.version} - - true - - - - - \ No newline at end of file diff --git a/iot-server/pom.xml b/iot-server/pom.xml index 8077fadf..c9f92f27 100644 --- a/iot-server/pom.xml +++ b/iot-server/pom.xml @@ -3,15 +3,22 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - iot-server-pom com.zmops + zeus-iot 1.0-beta - ../iot-server-pom 4.0.0 - iot-server pom + + + + UTF-8 + 0.30.0 + 8 + 8 + + server-library server-core @@ -25,73 +32,83 @@ server-storage-plugin + + + + com.zmops + iot-server-bom + 1.0-beta + import + pom + + + + org.projectlombok lombok - 1.18.20 org.apache.logging.log4j log4j-api - 2.13.3 org.apache.logging.log4j log4j-slf4j-impl - 2.13.3 com.google.guava guava - 25.1-jre io.netty netty-codec-http - 4.1.65.Final io.netty netty-handler - 4.1.65.Final io.netty netty-resolver-dns - 4.1.65.Final io.netty netty-codec-dns - 4.1.65.Final org.apache.logging.log4j log4j-core - 2.13.3 org.apache.camel camel-core - ${camel.version} org.apache.camel camel-jsonpath - ${camel.version} com.google.code.gson gson - 2.8.7 + + + org.apache.camel + camel-netty4 + + + io.netty + netty-example + + + + + org.apache.camel + camel-mqtt - - 8 - 8 - \ No newline at end of file diff --git a/iot-server/server-bootstrap/pom.xml b/iot-server/server-bootstrap/pom.xml index 534cf6fb..1bf47841 100644 --- a/iot-server/server-bootstrap/pom.xml +++ b/iot-server/server-bootstrap/pom.xml @@ -67,7 +67,6 @@ org.apache.camel camel-zabbix-agent - ${camel.version} @@ -110,6 +109,7 @@ 8 8 + 1.8 \ No newline at end of file diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamProcessor.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamProcessor.java index 201ca9ea..698a1079 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamProcessor.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamProcessor.java @@ -8,7 +8,7 @@ public interface StreamProcessor { /** * 写入数据 * - * @param stream + * @param stream record */ void in(STREAM stream); } diff --git a/iot-server/server-receiver-plugin/http-receiver-plugin/pom.xml b/iot-server/server-receiver-plugin/http-receiver-plugin/pom.xml index 58ef0317..a4a72479 100644 --- a/iot-server/server-receiver-plugin/http-receiver-plugin/pom.xml +++ b/iot-server/server-receiver-plugin/http-receiver-plugin/pom.xml @@ -19,7 +19,6 @@ org.apache.camel camel-netty4-http - ${camel.version} io.netty diff --git a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/pom.xml b/iot-server/server-receiver-plugin/mqtt-receiver-plugin/pom.xml index a5f2b571..0ef80d60 100644 --- a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/pom.xml +++ b/iot-server/server-receiver-plugin/mqtt-receiver-plugin/pom.xml @@ -21,7 +21,6 @@ org.apache.camel camel-mqtt - ${camel.version} com.zmops diff --git a/iot-server/server-receiver-plugin/tcp-receiver-plugin/pom.xml b/iot-server/server-receiver-plugin/tcp-receiver-plugin/pom.xml index bcd2a5f5..11a79cc6 100644 --- a/iot-server/server-receiver-plugin/tcp-receiver-plugin/pom.xml +++ b/iot-server/server-receiver-plugin/tcp-receiver-plugin/pom.xml @@ -16,7 +16,6 @@ org.apache.camel camel-netty4 - ${camel.version} io.netty diff --git a/iot-server/server-sender/pom.xml b/iot-server/server-sender/pom.xml index 4ce0db54..e915df85 100644 --- a/iot-server/server-sender/pom.xml +++ b/iot-server/server-sender/pom.xml @@ -10,6 +10,7 @@ 4.0.0 server-sender + com.zmops diff --git a/pom.xml b/pom.xml index 0c3a736a..1e096021 100644 --- a/pom.xml +++ b/pom.xml @@ -9,21 +9,8 @@ pom 1.0-beta - - org.springframework.boot - spring-boot-starter-parent - 2.3.12.RELEASE - - - zeus-webapp - zeus-common - zeus-driver - zeus-rest - zeus-starter - zeus-core - zeus-alarm - zeus-application-toolkit + iot-common @@ -32,114 +19,69 @@ 8 8 latest + + 1.8 + 2.10 + 2.8.2 + 3.1.0 + 2.22.0 - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-tomcat - - - org.springframework.boot - spring-boot-starter-logging - - - + + + server + + true + + + iot-server + iot-server-bom + + + - - - org.springframework.boot - spring-boot-starter-log4j2 - + + webapp + + true + + + zeus-webapp-bom + zeus-application-toolkit + + - - - org.springframework.boot - spring-boot-starter-undertow - - - org.springframework - spring-jdbc - - - com.alibaba - druid-spring-boot-starter - 1.2.6 - - - org.springframework.boot - spring-boot-configuration-processor - - - org.springframework.boot - spring-boot-starter-actuator - - - org.springframework.boot - spring-boot-starter-validation - + + dist + + true + + + zeus-iot-dist + + - - org.freemarker - freemarker - + - - com.alibaba - fastjson - 1.2.56 - - - org.aspectj - aspectjweaver - - - org.postgresql - postgresql - - - org.projectlombok - lombok - true - - - one.util - streamex - 0.7.3 - - - com.github.penggle - kaptcha - 2.3.2 - - - commons-lang - commons-lang - 2.6 - + + + + + maven-antrun-plugin + ${maven-antrun-plugin.version} + + + maven-deploy-plugin + ${maven-deploy-plugin.version} + + + maven-assembly-plugin + ${maven-assembly-plugin.version} + + + + - - com.dtflys.forest - forest-spring-boot-starter - 1.5.1 - - - commons-logging - commons-logging - - - - - io.ebean - ebean - 12.9.3 - - \ No newline at end of file diff --git a/zeus-alarm/pom.xml b/zeus-alarm/pom.xml index 478ed524..b19bd4af 100644 --- a/zeus-alarm/pom.xml +++ b/zeus-alarm/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - zeus-iot + zeus-webapp-bom com.zmops 1.0-beta + ../zeus-webapp-bom/pom.xml 4.0.0 @@ -19,7 +20,6 @@ io.netty netty-codec-http - ${netty.version} com.zmops diff --git a/zeus-common/pom.xml b/zeus-common/pom.xml index 541d3c59..2f944b35 100644 --- a/zeus-common/pom.xml +++ b/zeus-common/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - zeus-iot + zeus-webapp-bom com.zmops 1.0-beta + ../zeus-webapp-bom/pom.xml 4.0.0 diff --git a/zeus-core/pom.xml b/zeus-core/pom.xml index 815d6586..9ab69a7b 100644 --- a/zeus-core/pom.xml +++ b/zeus-core/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - zeus-iot + zeus-webapp-bom com.zmops 1.0-beta + ../zeus-webapp-bom/pom.xml 4.0.0 diff --git a/zeus-driver/pom.xml b/zeus-driver/pom.xml index f17ccd52..29709683 100644 --- a/zeus-driver/pom.xml +++ b/zeus-driver/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - zeus-iot + zeus-webapp-bom com.zmops 1.0-beta + ../zeus-webapp-bom/pom.xml 4.0.0 diff --git a/zeus-iot-dist/pom.xml b/zeus-iot-dist/pom.xml new file mode 100644 index 00000000..1c81a6ae --- /dev/null +++ b/zeus-iot-dist/pom.xml @@ -0,0 +1,91 @@ + + + + com.zmops + zeus-iot + 1.0-beta + + 4.0.0 + + zmops-zeus-iot + pom + + + + + server + + true + + + + com.zmops + server-starter + 1.0-beta + + + + + webapp + + true + + + + com.zmops + zeus-starter + 1.0-beta + + + + + + + + + maven-assembly-plugin + + + dist + package + + single + + + zeus-iot-bin + + ${project.basedir}/src/main/assembly/binary.xml + + + + + + true + posix + false + false + + + + maven-antrun-plugin + + + dist + package + + run + + + + + + + + + + + + + \ No newline at end of file diff --git a/zeus-iot-dist/src/main/assembly/binary.xml b/zeus-iot-dist/src/main/assembly/binary.xml new file mode 100644 index 00000000..68e1aa54 --- /dev/null +++ b/zeus-iot-dist/src/main/assembly/binary.xml @@ -0,0 +1,70 @@ + + + + dist + + tar.gz + + + + ${project.basedir}/../dist-material/bin + bin + + *.sh + *.bat + + 0755 + + + ${project.basedir}/../dist-material + config + + log4j2.xml + + + + + ${project.basedir}/../iot-server/server-bootstrap/src/main/resources + + application.yml + + config + + + ${project.basedir}/../iot-server/server-starter/target/zeus-iot-server-assembly/iot-server/libs + iot-server-libs + + + + + + ${project.basedir}/../zeus-starter/target/zeus-iot-webapp.jar + webapp + 0644 + + + ${project.basedir}/../zeus-starter/src/main/assembly/webapp.yml + webapp + 0644 + + + diff --git a/zeus-rest/pom.xml b/zeus-rest/pom.xml index ed15e077..89de706d 100644 --- a/zeus-rest/pom.xml +++ b/zeus-rest/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - zeus-iot + zeus-webapp-bom com.zmops 1.0-beta + ../zeus-webapp-bom/pom.xml 4.0.0 diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index 2ef2c112..36497769 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - zeus-iot + zeus-webapp-bom com.zmops 1.0-beta + ../zeus-webapp-bom/pom.xml 4.0.0 diff --git a/zeus-starter/src/main/assembly/webapp.yml b/zeus-starter/src/main/assembly/webapp.yml new file mode 100644 index 00000000..b339c45e --- /dev/null +++ b/zeus-starter/src/main/assembly/webapp.yml @@ -0,0 +1,46 @@ +# =========== 宙斯物联网采集分析基础平台 =========== +server: + port: 9090 + max-http-header-size: 10240 + shutdown: graceful + undertow: + threads: + worker: 256 + buffer-size: 1024 + direct-buffers: true +management: + endpoint: + shutdown: + enabled: true + endpoints: + web: + exposure: + include: shutdown + +# EBean Database 配置 +spring: + application: + name: ZEUS-IOT + datasource: + druid: + driver-class-name: org.postgresql.Driver + username: ${ZEUS_DB_USERNAME:postgres} + password: ${ZEUS_DB_PASSWORD:postgres} + url: jdbc:postgresql://${ZEUS_DB_HOST:127.0.0.1}:${ZEUS_DB_PORT:5432}/zeus-iot + servlet: + multipart: + max-request-size: 200MB + max-file-size: 200MB + jackson: + generator: + write_numbers_as_strings: true + +forest: + log-enabled: false + timeout: 5000 + variables: + ## Zabbix API IP 和 ServerIp and ServerPort + zbxApiUrl: http://${ZEUS_ZABBIX_HOST:127.0.0.1}:${ZEUS_ZABBIX_PORT:80}/zabbix/api_jsonrpc.php + zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} + zbxServerPort: ${ZEUS_ZABBIX_PORT:80} + zbxApiToken: 3464dee6b3fa3ce4173972e0497d7b84a93bdf8477ff1bdd51a7719cc0db2cd9 diff --git a/zeus-webapp-bom/pom.xml b/zeus-webapp-bom/pom.xml new file mode 100644 index 00000000..14df17ac --- /dev/null +++ b/zeus-webapp-bom/pom.xml @@ -0,0 +1,153 @@ + + + + zeus-iot + com.zmops + 1.0-beta + + 4.0.0 + pom + zeus-webapp-bom + + Zeus IoT 业务平台 + + + 8 + 8 + 2.25.4 + 4.1.65.Final + + + + ../zeus-common + ../zeus-alarm + ../zeus-core + ../zeus-driver + ../zeus-rest + ../zeus-starter + ../zeus-webapp + + + + + + org.springframework.boot + spring-boot-dependencies + 2.3.12.RELEASE + import + pom + + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + + + org.springframework.boot + spring-boot-starter-logging + + + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + + + org.springframework.boot + spring-boot-starter-undertow + + + org.springframework + spring-jdbc + + + com.alibaba + druid-spring-boot-starter + 1.2.6 + + + org.springframework.boot + spring-boot-configuration-processor + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-validation + + + + org.freemarker + freemarker + + + + com.alibaba + fastjson + 1.2.56 + + + org.aspectj + aspectjweaver + + + org.postgresql + postgresql + + + org.projectlombok + lombok + true + + + one.util + streamex + 0.7.3 + + + com.github.penggle + kaptcha + 2.3.2 + + + commons-lang + commons-lang + 2.6 + + + com.dtflys.forest + forest-spring-boot-starter + 1.5.1 + + + commons-logging + commons-logging + + + + + io.ebean + ebean + 12.9.3 + + + + + \ No newline at end of file diff --git a/zeus-webapp/pom.xml b/zeus-webapp/pom.xml index 1f39a23c..54d03b26 100644 --- a/zeus-webapp/pom.xml +++ b/zeus-webapp/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - zeus-iot + zeus-webapp-bom com.zmops 1.0-beta + ../zeus-webapp-bom/pom.xml 4.0.0 From d1fbbf7bcc99c5f41ceff603190f8f49dd34679b Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 8 Sep 2021 22:59:31 +0800 Subject: [PATCH 125/763] http receiver example. --- .../iot/server/receiver/http/predicate/HeaderPredicate.java | 4 +--- .../iot/server/receiver/http/provider/HttpRouteBuilder.java | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/predicate/HeaderPredicate.java b/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/predicate/HeaderPredicate.java index 187857a9..14ee55d6 100644 --- a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/predicate/HeaderPredicate.java +++ b/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/predicate/HeaderPredicate.java @@ -10,8 +10,6 @@ public class HeaderPredicate implements Predicate { @Override public boolean matches(Exchange exchange) { - - - return exchange.getIn().getHeader("username").equals("zhangsan"); + return exchange.getIn().getHeader("deviceType").equals("1010"); // just for example } } diff --git a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpRouteBuilder.java b/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpRouteBuilder.java index af167f49..1f426abf 100644 --- a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpRouteBuilder.java +++ b/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpRouteBuilder.java @@ -21,9 +21,7 @@ public void configure() throws Exception { fromF("netty4-http:http://0.0.0.0:%d/data/receiver?sync=true", config.getPort()) .threads(10) .choice() - .when(new HeaderPredicate()) - .process(new JsonToItemValueProcess()) .to("Zabbix"); } From 370b2c01934cbe675d4cb467619613112a4fc6c3 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 8 Sep 2021 23:21:29 +0800 Subject: [PATCH 126/763] add maven package plugin. --- iot-server/server-bootstrap/pom.xml | 6 ---- iot-server/server-starter/pom.xml | 27 ++++++++++++--- .../src/main/assembly/assembly.xml | 33 +++++++++++++++++++ pom.xml | 1 + 4 files changed, 57 insertions(+), 10 deletions(-) create mode 100644 iot-server/server-starter/src/main/assembly/assembly.xml diff --git a/iot-server/server-bootstrap/pom.xml b/iot-server/server-bootstrap/pom.xml index 1bf47841..c15ccaee 100644 --- a/iot-server/server-bootstrap/pom.xml +++ b/iot-server/server-bootstrap/pom.xml @@ -106,10 +106,4 @@ - - 8 - 8 - 1.8 - - \ No newline at end of file diff --git a/iot-server/server-starter/pom.xml b/iot-server/server-starter/pom.xml index 3361d93e..ca60b017 100644 --- a/iot-server/server-starter/pom.xml +++ b/iot-server/server-starter/pom.xml @@ -24,9 +24,28 @@ - - 8 - 8 - + + iot-server + + + org.apache.maven.plugins + maven-assembly-plugin + + + assembly + package + + single + + + + src/main/assembly/assembly.xml + + + + + + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/assembly/assembly.xml b/iot-server/server-starter/src/main/assembly/assembly.xml new file mode 100644 index 00000000..7281a1e6 --- /dev/null +++ b/iot-server/server-starter/src/main/assembly/assembly.xml @@ -0,0 +1,33 @@ + + + + assembly + + dir + + + + /libs + runtime + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 1e096021..39fa8751 100644 --- a/pom.xml +++ b/pom.xml @@ -19,6 +19,7 @@ 8 8 latest + 1.8 1.8 2.10 From c5febce9f974752873df15eea953ee315e1b9255 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 9 Sep 2021 10:45:51 +0800 Subject: [PATCH 127/763] =?UTF-8?q?=E5=85=A8=E5=B1=80=E6=A6=82=E8=A7=88=20?= =?UTF-8?q?=E5=8F=96=E6=95=B0=E9=80=9F=E7=8E=87=20=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=A0=BC=E5=BC=8F=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/zmops/iot/enums/ValueType.java | 39 +++++++++++++++++++ .../iot/web/analyse/service/HomeService.java | 3 +- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/enums/ValueType.java diff --git a/zeus-common/src/main/java/com/zmops/iot/enums/ValueType.java b/zeus-common/src/main/java/com/zmops/iot/enums/ValueType.java new file mode 100644 index 00000000..0e469e40 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/enums/ValueType.java @@ -0,0 +1,39 @@ +package com.zmops.iot.enums; + +import lombok.Getter; + +/** + * @author yefei + **/ +@Getter +public enum ValueType { + + CHARACTER("character", "字符型"), + NOTSUPPORT("not supported", "不支持的类型"), + LOG("log", "日志型"), + FLOAT("numeric (float)", "单精度型"), + NUMERIC("numeric (unsigned)", "数值型"), + TEXT("text", "文本型"), + AVG("avg", "平均值"); + + String code; + String value; + + ValueType(String code, String value) { + this.code = code; + this.value = value; + } + + public static String getVal(String status) { + if (status == null) { + return ""; + } else { + for (ValueType s : ValueType.values()) { + if (s.getCode().equals(status)) { + return s.getValue(); + } + } + return ""; + } + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index 08ddaf48..5f5aa241 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -5,6 +5,7 @@ import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.query.QProduct; +import com.zmops.iot.enums.ValueType; import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.alarm.dto.param.AlarmParam; @@ -87,7 +88,7 @@ public List> collectonRate(long timeFrom, long timeTill) { valMap.put("val", val); tmpList.add(valMap); }); - collectMap.put("name", key); + collectMap.put("name", ValueType.getVal(key)); collectMap.put("data", tmpList); collectList.add(collectMap); }); From 482c95542b89f8eaa29170f5ed53fd544b65e8a6 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 9 Sep 2021 15:08:50 +0800 Subject: [PATCH 128/763] =?UTF-8?q?=E7=94=A8=E6=88=B7=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/zmops/iot/web/sys/factory/UserFactory.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/factory/UserFactory.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/factory/UserFactory.java index 264c40fd..67a9303d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/factory/UserFactory.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/factory/UserFactory.java @@ -74,6 +74,9 @@ public static SysUser editUser(UserDto newUser, SysUser oldUser) { if (ToolUtil.isNotEmpty(newUser.getPhone())) { oldUser.setPhone(newUser.getPhone()); } + if (ToolUtil.isNotEmpty(newUser.getStatus())) { + oldUser.setStatus(newUser.getStatus()); + } return oldUser; } } From 9e8095d8eeeca5a592c807e28f2304f90e33b487 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 9 Sep 2021 19:39:55 +0800 Subject: [PATCH 129/763] git ignore node_module. --- .gitignore | 1 + dist-material/bin/IOTServerStart.sh | 0 2 files changed, 1 insertion(+) delete mode 100644 dist-material/bin/IOTServerStart.sh diff --git a/.gitignore b/.gitignore index 4e0f9461..95205bda 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ *.iml **/target/* .vscode +**/node_modules/* diff --git a/dist-material/bin/IOTServerStart.sh b/dist-material/bin/IOTServerStart.sh deleted file mode 100644 index e69de29b..00000000 From a019a071ec95266a00ef8d28e475d188017f265b Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 9 Sep 2021 19:41:33 +0800 Subject: [PATCH 130/763] maven assembly. --- .gitignore | 1 + .muse/config.toml | 2 + .muse/setup.sh | 2 + pom.xml | 153 +++++++++++++++++- zeus-iot-dist/pom.xml | 5 +- zeus-iot-dist/src/main/assembly/binary.xml | 16 +- zeus-starter/pom.xml | 82 ++++++++-- zeus-starter/src/main/assembly/webapp.yml | 5 +- .../src/main/resources/application.yaml | 20 +-- 9 files changed, 246 insertions(+), 40 deletions(-) create mode 100644 .muse/config.toml create mode 100644 .muse/setup.sh diff --git a/.gitignore b/.gitignore index 95205bda..c2ebb149 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ **/target/* .vscode **/node_modules/* +dist/ diff --git a/.muse/config.toml b/.muse/config.toml new file mode 100644 index 00000000..344d17e4 --- /dev/null +++ b/.muse/config.toml @@ -0,0 +1,2 @@ +jdk8 = true +setup = ".muse/setup.sh" diff --git a/.muse/setup.sh b/.muse/setup.sh new file mode 100644 index 00000000..6bc9e756 --- /dev/null +++ b/.muse/setup.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +git submodule update --init --recursive diff --git a/pom.xml b/pom.xml index 39fa8751..a9f2ea0b 100644 --- a/pom.xml +++ b/pom.xml @@ -8,6 +8,7 @@ zeus-iot pom 1.0-beta + Zeus IoT 物联网分布式采集平台 iot-common @@ -20,12 +21,32 @@ 8 latest 1.8 + 1.6.2 + + 0.4.13 + 0.6.1 + 1.6.0 1.8 2.10 2.8.2 3.1.0 2.22.0 + 3.2.0 + 2.22.0 + 3.1.0 + 3.1.1 + 3.0.0-M2 + 3.8.0 + 3.1.0 + 3.0.1 + 2.5 + 4.3.0 + 3.1.0 + 1.21 + 1.5 + 2.7 + true @@ -40,7 +61,6 @@ - webapp @@ -62,6 +82,47 @@ + + all + + false + + + iot-server + iot-server-bom + zeus-webapp-bom + zeus-application-toolkit + zeus-iot-dist + + + + + org.codehaus.mojo + exec-maven-plugin + ${exec-maven-plugin.version} + + + git submodule update + initialize + false + + git + + submodule + update + --init + --recursive + + + + exec + + + + + + + @@ -80,8 +141,98 @@ maven-assembly-plugin ${maven-assembly-plugin.version} + + + maven-jar-plugin + ${maven-jar-plugin.version} + + true + + + + maven-shade-plugin + ${maven-shade-plugin.version} + + + + + kr.motd.maven + os-maven-plugin + ${os-maven-plugin.version} + + + initialize + + detect + + + + + + maven-enforcer-plugin + ${maven-enforcer-plugin.version} + + + enforce-java + + enforce + + validate + + + + + 1.8 + + + 3.6 + + + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + maven-resources-plugin + ${maven-resource-plugin.version} + + ${project.build.sourceEncoding} + + + + com.spotify + docker-maven-plugin + ${docker.plugin.version} + + true + + + + maven-source-plugin + ${maven-source-plugin.version} + + + attach-sources + none + + jar + + + + + + diff --git a/zeus-iot-dist/pom.xml b/zeus-iot-dist/pom.xml index 1c81a6ae..37a67839 100644 --- a/zeus-iot-dist/pom.xml +++ b/zeus-iot-dist/pom.xml @@ -23,10 +23,11 @@ com.zmops server-starter - 1.0-beta + ${project.version} + webapp @@ -36,7 +37,7 @@ com.zmops zeus-starter - 1.0-beta + ${project.version} diff --git a/zeus-iot-dist/src/main/assembly/binary.xml b/zeus-iot-dist/src/main/assembly/binary.xml index 68e1aa54..5fc94844 100644 --- a/zeus-iot-dist/src/main/assembly/binary.xml +++ b/zeus-iot-dist/src/main/assembly/binary.xml @@ -15,11 +15,11 @@ ~ limitations under the License. ~ --> - + + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd"> dist tar.gz @@ -41,7 +41,6 @@ log4j2.xml - ${project.basedir}/../iot-server/server-bootstrap/src/main/resources @@ -50,14 +49,15 @@ config - ${project.basedir}/../iot-server/server-starter/target/zeus-iot-server-assembly/iot-server/libs + ${project.basedir}/../iot-server/server-starter/target/iot-server-assembly/iot-server/libs + iot-server-libs - + - ${project.basedir}/../zeus-starter/target/zeus-iot-webapp.jar + ${project.basedir}/../zeus-starter/target/zeus-webapp.jar webapp 0644 diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index 36497769..e7c800f1 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -9,12 +9,16 @@ ../zeus-webapp-bom/pom.xml 4.0.0 - + jar zeus-starter 8 8 + + 1.11.0 + ../zeus-iot-ui + 2.3.12.RELEASE @@ -51,28 +55,84 @@ + zeus-webapp - - src/main/resources - - **/*.* - - true - - + + + maven-compiler-plugin + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + com.github.eirslett + frontend-maven-plugin + ${frontend-maven-plugin.version} + + ${ui.path} + v14.17.2 + + + + install node and npm + + install-node-and-npm + + + + npm install + + npm + + + install --registry=https://registry.npmjs.org/ + + + + npm run build + + npm + + + run build + + + + + + maven-resources-plugin + + ${project.build.sourceEncoding} + ${project.build.directory} + + + ${basedir}/target/classes/public + ${ui.path}/dist + + + ${basedir}/target/classes + src/main/resources + + + + org.springframework.boot spring-boot-maven-plugin - 2.3.12.RELEASE + ${spring.boot.version} com.zmops.iot.IOTApplication - repackage + + repackage + diff --git a/zeus-starter/src/main/assembly/webapp.yml b/zeus-starter/src/main/assembly/webapp.yml index b339c45e..15d985f3 100644 --- a/zeus-starter/src/main/assembly/webapp.yml +++ b/zeus-starter/src/main/assembly/webapp.yml @@ -1,4 +1,3 @@ -# =========== 宙斯物联网采集分析基础平台 =========== server: port: 9090 max-http-header-size: 10240 @@ -17,7 +16,7 @@ management: exposure: include: shutdown -# EBean Database 配置 +# EBean Database Setting spring: application: name: ZEUS-IOT @@ -39,7 +38,7 @@ forest: log-enabled: false timeout: 5000 variables: - ## Zabbix API IP 和 ServerIp and ServerPort + ## Zabbix API IP And ServerIp and ServerPort zbxApiUrl: http://${ZEUS_ZABBIX_HOST:127.0.0.1}:${ZEUS_ZABBIX_PORT:80}/zabbix/api_jsonrpc.php zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:80} diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index 5f0bb6ae..15d985f3 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -1,4 +1,3 @@ -# =========== 宙斯物联网采集分析基础平台 =========== server: port: 9090 max-http-header-size: 10240 @@ -17,7 +16,7 @@ management: exposure: include: shutdown -# EBean Database 配置 +# EBean Database Setting spring: application: name: ZEUS-IOT @@ -36,20 +35,11 @@ spring: write_numbers_as_strings: true forest: + log-enabled: false + timeout: 5000 variables: - ## Zabbix API IP 和 端口 + ## Zabbix API IP And ServerIp and ServerPort zbxApiUrl: http://${ZEUS_ZABBIX_HOST:127.0.0.1}:${ZEUS_ZABBIX_PORT:80}/zabbix/api_jsonrpc.php zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:80} - zbxApiToken: 0fc68dae932f185a22901cd7d3f1ee55d70353ff03f2a2cdea795043aa4ca2a7 - - ## 设备触发告警,执行动作回调 IOT-SERVER 处理 - zeusServerIp: ${ZEUS_CALLBACK_HOST:127.0.0.1} - zeusServerPort: ${ZEUS_CALLBACK_PORT:9090} - - log-enabled: false - timeout: 5000 - -logging: - level: - io.ebean: DEBUG \ No newline at end of file + zbxApiToken: 3464dee6b3fa3ce4173972e0497d7b84a93bdf8477ff1bdd51a7719cc0db2cd9 From 740311ba9355fea64371f68d42a515d6ec2ffb39 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 9 Sep 2021 19:50:23 +0800 Subject: [PATCH 131/763] update zeus-iot-ui submodule. --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index 2147c329..e03af763 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit 2147c3291fa1061727ee998ecc8751ca3fc88e9a +Subproject commit e03af76310c183a4aee1b4d36b579ba80608a24f From 2a7424c47daeb3da41c412f3aefad5d6dcd67f12 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 9 Sep 2021 19:54:23 +0800 Subject: [PATCH 132/763] zeus-iot start script. --- dist-material/bin/IoTServer.bat | 37 ++++++++++++++++++++ dist-material/bin/IoTServer.sh | 49 +++++++++++++++++++++++++++ dist-material/bin/IoTServerInit.bat | 37 ++++++++++++++++++++ dist-material/bin/IoTServerInit.sh | 49 +++++++++++++++++++++++++++ dist-material/bin/IoTServerNoInit.bat | 37 ++++++++++++++++++++ dist-material/bin/IoTServerNoInit.sh | 49 +++++++++++++++++++++++++++ dist-material/bin/startup.bat | 22 ++++++++++++ dist-material/bin/startup.sh | 26 ++++++++++++++ dist-material/bin/webappService.bat | 41 ++++++++++++++++++++++ dist-material/bin/webappService.sh | 46 +++++++++++++++++++++++++ 10 files changed, 393 insertions(+) create mode 100644 dist-material/bin/IoTServer.bat create mode 100644 dist-material/bin/IoTServer.sh create mode 100644 dist-material/bin/IoTServerInit.bat create mode 100644 dist-material/bin/IoTServerInit.sh create mode 100644 dist-material/bin/IoTServerNoInit.bat create mode 100644 dist-material/bin/IoTServerNoInit.sh create mode 100644 dist-material/bin/startup.bat create mode 100644 dist-material/bin/startup.sh create mode 100644 dist-material/bin/webappService.bat create mode 100644 dist-material/bin/webappService.sh diff --git a/dist-material/bin/IoTServer.bat b/dist-material/bin/IoTServer.bat new file mode 100644 index 00000000..299b1a6b --- /dev/null +++ b/dist-material/bin/IoTServer.bat @@ -0,0 +1,37 @@ +@REM +@REM Licensed to the Apache Software Foundation (ASF) under one or more +@REM contributor license agreements. See the NOTICE file distributed with +@REM this work for additional information regarding copyright ownership. +@REM The ASF licenses this file to You under the Apache License, Version 2.0 +@REM (the "License"); you may not use this file except in compliance with +@REM the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, software +@REM distributed under the License is distributed on an "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@REM See the License for the specific language governing permissions and +@REM limitations under the License. + +@echo off + +setlocal +set OAP_PROCESS_TITLE=Skywalking-Collector +set OAP_HOME=%~dp0%.. +set OAP_OPTS="-Xms256M -Xmx512M -Doap.logDir=%OAP_HOME%\logs" + +set CLASSPATH=%OAP_HOME%\config;.; +set CLASSPATH=%OAP_HOME%\oap-libs\*;%CLASSPATH% + +if defined JAVA_HOME ( + set _EXECJAVA="%JAVA_HOME%\bin\java" +) + +if not defined JAVA_HOME ( + echo "JAVA_HOME not set." + set _EXECJAVA=java +) + +start "%OAP_PROCESS_TITLE%" %_EXECJAVA% "%OAP_OPTS%" -cp "%CLASSPATH%" org.apache.skywalking.oap.server.starter.OAPServerStartUp +endlocal diff --git a/dist-material/bin/IoTServer.sh b/dist-material/bin/IoTServer.sh new file mode 100644 index 00000000..b881ccb3 --- /dev/null +++ b/dist-material/bin/IoTServer.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env sh +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +PRG="$0" +PRGDIR=$(dirname "$PRG") +[ -z "$OAP_HOME" ] && OAP_HOME=$(cd "$PRGDIR/.." > /dev/null || exit 1; pwd) + +OAP_LOG_DIR="${OAP_LOG_DIR:-${OAP_HOME}/logs}" +JAVA_OPTS="${JAVA_OPTS:- -Xms256M -Xmx512M}" + +if [ ! -d "${OAP_LOG_DIR}" ]; then + mkdir -p "${OAP_LOG_DIR}" +fi + +_RUNJAVA=${JAVA_HOME}/bin/java +[ -z "$JAVA_HOME" ] && _RUNJAVA=java + +CLASSPATH="$OAP_HOME/config:$CLASSPATH" +for i in "$OAP_HOME"/oap-libs/*.jar +do + CLASSPATH="$i:$CLASSPATH" +done + +OAP_OPTIONS=" -Doap.logDir=${OAP_LOG_DIR}" + +eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${OAP_OPTIONS} -classpath $CLASSPATH org.apache.skywalking.oap.server.starter.OAPServerStartUp \ + 2>${OAP_LOG_DIR}/oap.log 1> /dev/null &" + +if [ $? -eq 0 ]; then + sleep 1 + echo "SkyWalking OAP started successfully!" +else + echo "SkyWalking OAP started failure!" + exit 1 +fi diff --git a/dist-material/bin/IoTServerInit.bat b/dist-material/bin/IoTServerInit.bat new file mode 100644 index 00000000..69e453e2 --- /dev/null +++ b/dist-material/bin/IoTServerInit.bat @@ -0,0 +1,37 @@ +@REM +@REM Licensed to the Apache Software Foundation (ASF) under one or more +@REM contributor license agreements. See the NOTICE file distributed with +@REM this work for additional information regarding copyright ownership. +@REM The ASF licenses this file to You under the Apache License, Version 2.0 +@REM (the "License"); you may not use this file except in compliance with +@REM the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, software +@REM distributed under the License is distributed on an "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@REM See the License for the specific language governing permissions and +@REM limitations under the License. + +@echo off + +setlocal +set OAP_PROCESS_TITLE=Skywalking-Collector +set OAP_HOME=%~dp0%.. +set OAP_OPTS="-Xms256M -Xmx512M -Doap.logDir=%OAP_HOME%\logs" + +set CLASSPATH=%OAP_HOME%\config;.; +set CLASSPATH=%OAP_HOME%\oap-libs\*;%CLASSPATH% + +if defined JAVA_HOME ( + set _EXECJAVA="%JAVA_HOME%\bin\java" +) + +if not defined JAVA_HOME ( + echo "JAVA_HOME not set." + set _EXECJAVA=java +) + +start "%OAP_PROCESS_TITLE%" %_EXECJAVA% "%OAP_OPTS%" -cp "%CLASSPATH%" -Dmode=init org.apache.skywalking.oap.server.starter.OAPServerStartUp +endlocal diff --git a/dist-material/bin/IoTServerInit.sh b/dist-material/bin/IoTServerInit.sh new file mode 100644 index 00000000..cd2db309 --- /dev/null +++ b/dist-material/bin/IoTServerInit.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env sh +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +PRG="$0" +PRGDIR=$(dirname "$PRG") +[ -z "$OAP_HOME" ] && OAP_HOME=$(cd "$PRGDIR/.." > /dev/null || exit 1; pwd) + +OAP_LOG_DIR="${OAP_HOME}/logs" +JAVA_OPTS="${JAVA_OPTS:- -Xms256M -Xmx512M}" + +if [ ! -d "${OAP_HOME}/logs" ]; then + mkdir -p "${OAP_LOG_DIR}" +fi + +_RUNJAVA=${JAVA_HOME}/bin/java +[ -z "$JAVA_HOME" ] && _RUNJAVA=java + +CLASSPATH="$OAP_HOME/config:$CLASSPATH" +for i in "$OAP_HOME"/oap-libs/*.jar +do + CLASSPATH="$i:$CLASSPATH" +done + +OAP_OPTIONS=" -Doap.logDir=${OAP_LOG_DIR}" + +eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${OAP_OPTIONS} -classpath $CLASSPATH -Dmode=init org.apache.skywalking.oap.server.starter.OAPServerStartUp \ + 2>${OAP_LOG_DIR}/oap.log 1> /dev/null &" + +if [ $? -eq 0 ]; then + sleep 1 + echo "SkyWalking OAP started successfully!" +else + echo "SkyWalking OAP started failure!" + exit 1 +fi diff --git a/dist-material/bin/IoTServerNoInit.bat b/dist-material/bin/IoTServerNoInit.bat new file mode 100644 index 00000000..47175c53 --- /dev/null +++ b/dist-material/bin/IoTServerNoInit.bat @@ -0,0 +1,37 @@ +@REM +@REM Licensed to the Apache Software Foundation (ASF) under one or more +@REM contributor license agreements. See the NOTICE file distributed with +@REM this work for additional information regarding copyright ownership. +@REM The ASF licenses this file to You under the Apache License, Version 2.0 +@REM (the "License"); you may not use this file except in compliance with +@REM the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, software +@REM distributed under the License is distributed on an "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@REM See the License for the specific language governing permissions and +@REM limitations under the License. + +@echo off + +setlocal +set OAP_PROCESS_TITLE=Skywalking-Collector +set OAP_HOME=%~dp0%.. +set OAP_OPTS="-Xms256M -Xmx512M -Doap.logDir=%OAP_HOME%\logs" + +set CLASSPATH=%OAP_HOME%\config;.; +set CLASSPATH=%OAP_HOME%\oap-libs\*;%CLASSPATH% + +if defined JAVA_HOME ( + set _EXECJAVA="%JAVA_HOME%\bin\java" +) + +if not defined JAVA_HOME ( + echo "JAVA_HOME not set." + set _EXECJAVA=java +) + +start "%OAP_PROCESS_TITLE%" %_EXECJAVA% "%OAP_OPTS%" -cp "%CLASSPATH%" -Dmode=no-init org.apache.skywalking.oap.server.starter.OAPServerStartUp +endlocal diff --git a/dist-material/bin/IoTServerNoInit.sh b/dist-material/bin/IoTServerNoInit.sh new file mode 100644 index 00000000..42c54e60 --- /dev/null +++ b/dist-material/bin/IoTServerNoInit.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env sh +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +PRG="$0" +PRGDIR=$(dirname "$PRG") +[ -z "$OAP_HOME" ] && OAP_HOME=$(cd "$PRGDIR/.." > /dev/null || exit 1; pwd) + +OAP_LOG_DIR=${OAP_LOG_DIR:-"${OAP_HOME}/logs"} +JAVA_OPTS="${JAVA_OPTS:- -Xms256M -Xmx512M}" + +if [ ! -d "${OAP_HOME}/logs" ]; then + mkdir -p "${OAP_LOG_DIR}" +fi + +_RUNJAVA=${JAVA_HOME}/bin/java +[ -z "$JAVA_HOME" ] && _RUNJAVA=java + +CLASSPATH="$OAP_HOME/config:$CLASSPATH" +for i in "$OAP_HOME"/oap-libs/*.jar +do + CLASSPATH="$i:$CLASSPATH" +done + +OAP_OPTIONS=" -Doap.logDir=${OAP_LOG_DIR}" + +eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${OAP_OPTIONS} -classpath $CLASSPATH -Dmode=no-init org.apache.skywalking.oap.server.starter.OAPServerStartUp \ + 2>${OAP_LOG_DIR}/oap.log 1> /dev/null &" + +if [ $? -eq 0 ]; then + sleep 1 + echo "SkyWalking OAP started successfully!" +else + echo "SkyWalking OAP started failure!" + exit 1 +fi diff --git a/dist-material/bin/startup.bat b/dist-material/bin/startup.bat new file mode 100644 index 00000000..f9d27473 --- /dev/null +++ b/dist-material/bin/startup.bat @@ -0,0 +1,22 @@ +@REM +@REM Licensed to the Apache Software Foundation (ASF) under one or more +@REM contributor license agreements. See the NOTICE file distributed with +@REM this work for additional information regarding copyright ownership. +@REM The ASF licenses this file to You under the Apache License, Version 2.0 +@REM (the "License"); you may not use this file except in compliance with +@REM the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, software +@REM distributed under the License is distributed on an "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@REM See the License for the specific language governing permissions and +@REM limitations under the License. + +@echo off + +setlocal +call "%~dp0"\oapService.bat start +call "%~dp0"\webappService.bat start +endlocal diff --git a/dist-material/bin/startup.sh b/dist-material/bin/startup.sh new file mode 100644 index 00000000..19f7af72 --- /dev/null +++ b/dist-material/bin/startup.sh @@ -0,0 +1,26 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#!/usr/bin/env sh + +PRG="$0" +PRGDIR=`dirname "$PRG"` +OAP_EXE=oapService.sh +WEBAPP_EXE=webappService.sh + +"$PRGDIR"/"$OAP_EXE" + +"$PRGDIR"/"$WEBAPP_EXE" diff --git a/dist-material/bin/webappService.bat b/dist-material/bin/webappService.bat new file mode 100644 index 00000000..a1ca98c0 --- /dev/null +++ b/dist-material/bin/webappService.bat @@ -0,0 +1,41 @@ +@REM +@REM Licensed to the Apache Software Foundation (ASF) under one or more +@REM contributor license agreements. See the NOTICE file distributed with +@REM this work for additional information regarding copyright ownership. +@REM The ASF licenses this file to You under the Apache License, Version 2.0 +@REM (the "License"); you may not use this file except in compliance with +@REM the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, software +@REM distributed under the License is distributed on an "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@REM See the License for the specific language governing permissions and +@REM limitations under the License. + +@echo off + +setlocal +set WEBAPP_PROCESS_TITLE=Skywalking-Webapp +set WEBAPP_HOME=%~dp0%.. +set JARPATH=%WEBAPP_HOME%\webapp +set WEBAPP_LOG_DIR=%WEBAPP_HOME%\logs + +if not exist "%WEBAPP_LOG_DIR%" ( + mkdir "%WEBAPP_LOG_DIR%" +) + +set LOG_FILE_LOCATION=%WEBAPP_LOG_DIR%\webapp.log + +if defined JAVA_HOME ( + set _EXECJAVA="%JAVA_HOME%\bin\java" +) + +if not defined JAVA_HOME ( + echo "JAVA_HOME not set." + set _EXECJAVA=java +) + +start "%WEBAPP_PROCESS_TITLE%" %_EXECJAVA% -jar %JARPATH%/skywalking-webapp.jar --spring.config.location=%JARPATH%/webapp.yml --logging.file=%LOG_FILE_LOCATION% +endlocal diff --git a/dist-material/bin/webappService.sh b/dist-material/bin/webappService.sh new file mode 100644 index 00000000..dde778c5 --- /dev/null +++ b/dist-material/bin/webappService.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env sh +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +PRG="$0" +PRGDIR=$(dirname "$PRG") +[ -z "$WEBAPP_HOME" ] && WEBAPP_HOME=$(cd "$PRGDIR/.." > /dev/null || exit 1; pwd) + +WEBAPP_LOG_DIR="${WEBAPP_LOG_DIR:-${WEBAPP_HOME}/logs}" +JAVA_OPTS="${JAVA_OPTS:- -Xms256M -Xmx512M}" +JAR_PATH="${WEBAPP_HOME}/webapp" + +if [ ! -d "${WEBAPP_LOG_DIR}" ]; then + mkdir -p "${WEBAPP_LOG_DIR}" +fi + +LOG_FILE_LOCATION=${WEBAPP_LOG_DIR}/webapp.log + +_RUNJAVA=${JAVA_HOME}/bin/java +[ -z "$JAVA_HOME" ] && _RUNJAVA=java + +eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} -jar ${JAR_PATH}/skywalking-webapp.jar \ + --spring.config.location=${JAR_PATH}/webapp.yml \ + --logging.file=${LOG_FILE_LOCATION} \ + 2>${WEBAPP_LOG_DIR}/webapp-console.log 1> /dev/null &" + +if [ $? -eq 0 ]; then + sleep 1 + echo "SkyWalking Web Application started successfully!" +else + echo "SkyWalking Web Application started failure!" + exit 1 +fi From 3bba5eaff1dc455a8eee181acfba9d9ddc636658 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 9 Sep 2021 22:17:44 +0800 Subject: [PATCH 133/763] =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server-tdengine-plugin/pom.xml | 2 +- zeus-starter/pom.xml | 26 ++++++------------- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml index 5573d5c3..c0eff4b9 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml @@ -20,7 +20,7 @@ com.taosdata.jdbc taos-jdbcdriver - 2.0.30 + 2.0.31 com.zmops diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index e7c800f1..11e90a96 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -57,7 +57,13 @@ zeus-webapp - + + src/main/resources + + **/*.* + + true + @@ -103,23 +109,7 @@ - - maven-resources-plugin - - ${project.build.sourceEncoding} - ${project.build.directory} - - - ${basedir}/target/classes/public - ${ui.path}/dist - - - ${basedir}/target/classes - src/main/resources - - - - + org.springframework.boot spring-boot-maven-plugin From 28e1c1da631e6f92848b0b83c4e5ad770e0636bf Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 9 Sep 2021 22:17:58 +0800 Subject: [PATCH 134/763] script init update --- .../java/com/zmops/zeus/driver/service/ZbxScript.java | 6 +----- .../java/com/zmops/iot/web/init/BasicSettingsInit.java | 10 +++++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java index 1b6934fb..b9224aaa 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java @@ -20,15 +20,11 @@ public interface ZbxScript { * 创建 在线状态 回调地址 * * @param userApiToken apiToekn - * @param zeusServerIp 平台IP - * @param zeusServerPort 平台端口 * @return String */ @Post(headers = "authTag: noAuth") @JsonPath("/script/script.init.create") - String createOfflineStatusScript(@ParamName("userAuth") String userApiToken, - @ParamName("zeusServerIp") String zeusServerIp, - @ParamName("zeusServerPort") String zeusServerPort); + String createOfflineStatusScript(@ParamName("userAuth") String userApiToken); /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java index 35384970..161b4c67 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java @@ -37,15 +37,15 @@ public class BasicSettingsInit { @Autowired private ZbxInitService zbxInitService; - private String zeusServerIp; - private String zeusServerPort; +// private String zeusServerIp; +// private String zeusServerPort; private String zbxApiToken; @PostConstruct public void init() { - zeusServerIp = configuration.getVariables().get("zeusServerIp").toString(); - zeusServerPort = configuration.getVariables().get("zeusServerPort").toString(); + //zeusServerIp = configuration.getVariables().get("zeusServerIp").toString(); + //zeusServerPort = configuration.getVariables().get("zeusServerPort").toString(); zbxApiToken = configuration.getVariables().get("zbxApiToken").toString(); } @@ -152,7 +152,7 @@ public String getGuestRoleId() { } public Map createOfflineStatusScript() { - zbxScript.createOfflineStatusScript(zbxApiToken, zeusServerIp, zeusServerPort); + zbxScript.createOfflineStatusScript(zbxApiToken); return getOfflineStatusScript(); } From 0b2fc1b4047564c2bc19801fbbd70cf1dcc26627 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 9 Sep 2021 22:19:18 +0800 Subject: [PATCH 135/763] update zeus-starter pom. --- zeus-starter/pom.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index e7c800f1..9de773a6 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -15,10 +15,8 @@ 8 8 - 1.11.0 ../zeus-iot-ui - 2.3.12.RELEASE @@ -57,7 +55,10 @@ zeus-webapp - + + src/main/resources + true + @@ -66,6 +67,7 @@ ${compiler.version} ${compiler.version} ${project.build.sourceEncoding} + false @@ -130,9 +132,7 @@ - - repackage - + repackage From e0841a437768f0c5f1fb3eb5611fb25b7c4c5688 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 9 Sep 2021 22:25:21 +0800 Subject: [PATCH 136/763] update root pom. --- pom.xml | 2 ++ zeus-webapp-bom/pom.xml | 8 +++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index a9f2ea0b..5adaf00a 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,8 @@ 1.8 1.6.2 + 2.3.12.RELEASE + 0.4.13 0.6.1 diff --git a/zeus-webapp-bom/pom.xml b/zeus-webapp-bom/pom.xml index 14df17ac..835b87e5 100644 --- a/zeus-webapp-bom/pom.xml +++ b/zeus-webapp-bom/pom.xml @@ -35,9 +35,9 @@ org.springframework.boot spring-boot-dependencies - 2.3.12.RELEASE - import + ${spring.boot.version} pom + import @@ -92,16 +92,14 @@ org.springframework.boot spring-boot-starter-validation - org.freemarker freemarker - com.alibaba fastjson - 1.2.56 + 1.2.58 org.aspectj From 5797608eee0fe1c4de30354a34a2797bb4c136fe Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 9 Sep 2021 22:28:18 +0800 Subject: [PATCH 137/763] update merge. --- .../java/com/zmops/zeus/driver/service/ZbxScript.java | 6 +----- .../java/com/zmops/iot/web/init/BasicSettingsInit.java | 10 +++++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java index 1b6934fb..b9224aaa 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java @@ -20,15 +20,11 @@ public interface ZbxScript { * 创建 在线状态 回调地址 * * @param userApiToken apiToekn - * @param zeusServerIp 平台IP - * @param zeusServerPort 平台端口 * @return String */ @Post(headers = "authTag: noAuth") @JsonPath("/script/script.init.create") - String createOfflineStatusScript(@ParamName("userAuth") String userApiToken, - @ParamName("zeusServerIp") String zeusServerIp, - @ParamName("zeusServerPort") String zeusServerPort); + String createOfflineStatusScript(@ParamName("userAuth") String userApiToken); /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java index 35384970..161b4c67 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java @@ -37,15 +37,15 @@ public class BasicSettingsInit { @Autowired private ZbxInitService zbxInitService; - private String zeusServerIp; - private String zeusServerPort; +// private String zeusServerIp; +// private String zeusServerPort; private String zbxApiToken; @PostConstruct public void init() { - zeusServerIp = configuration.getVariables().get("zeusServerIp").toString(); - zeusServerPort = configuration.getVariables().get("zeusServerPort").toString(); + //zeusServerIp = configuration.getVariables().get("zeusServerIp").toString(); + //zeusServerPort = configuration.getVariables().get("zeusServerPort").toString(); zbxApiToken = configuration.getVariables().get("zbxApiToken").toString(); } @@ -152,7 +152,7 @@ public String getGuestRoleId() { } public Map createOfflineStatusScript() { - zbxScript.createOfflineStatusScript(zbxApiToken, zeusServerIp, zeusServerPort); + zbxScript.createOfflineStatusScript(zbxApiToken); return getOfflineStatusScript(); } From ed9ce02aee099385f58f002410ca135c35734b16 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 9 Sep 2021 22:32:10 +0800 Subject: [PATCH 138/763] script init update --- .../main/java/com/zmops/iot/web/init/BasicSettingsInit.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java index 161b4c67..a647e881 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java @@ -37,15 +37,11 @@ public class BasicSettingsInit { @Autowired private ZbxInitService zbxInitService; -// private String zeusServerIp; -// private String zeusServerPort; private String zbxApiToken; @PostConstruct public void init() { - //zeusServerIp = configuration.getVariables().get("zeusServerIp").toString(); - //zeusServerPort = configuration.getVariables().get("zeusServerPort").toString(); zbxApiToken = configuration.getVariables().get("zbxApiToken").toString(); } From be72167b8239693fc5e44b25f783ad8051cc6ac1 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 10 Sep 2021 10:31:49 +0800 Subject: [PATCH 139/763] edit zeus-starter pom.xml. --- zeus-starter/pom.xml | 26 ++++++++++++++++++-------- zeus-webapp-bom/pom.xml | 4 ++++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index fe4cc7d6..86e8284a 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -55,13 +55,7 @@ zeus-webapp - - src/main/resources - - **/*.* - - true - + @@ -108,7 +102,23 @@ - + + maven-resources-plugin + + ${project.build.sourceEncoding} + ${project.build.directory}/classes + + + ${basedir}/target/classes/public + ${ui.path}/dist + + + ${basedir}/target/classes + src/main/resources + + + + org.springframework.boot spring-boot-maven-plugin diff --git a/zeus-webapp-bom/pom.xml b/zeus-webapp-bom/pom.xml index 835b87e5..74695c97 100644 --- a/zeus-webapp-bom/pom.xml +++ b/zeus-webapp-bom/pom.xml @@ -114,6 +114,10 @@ lombok true + + org.yaml + snakeyaml + one.util streamex From a36cde87c8c23a2c178e3584e7ff2f634cf19cec Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 10 Sep 2021 10:35:06 +0800 Subject: [PATCH 140/763] :tada: zeus-iot is opensource now. --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5adaf00a..458eefd9 100644 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,6 @@ latest 1.8 1.6.2 - 2.3.12.RELEASE From beee024362d23ea8ea3a1852fd964c2cfea3fc91 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 10 Sep 2021 10:47:36 +0800 Subject: [PATCH 141/763] :art: update root pom. --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index 458eefd9..3a6b97ee 100644 --- a/pom.xml +++ b/pom.xml @@ -184,7 +184,6 @@ - 1.8 From a68a13848dd5c6418e58da7661084052e005d0fd Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 10 Sep 2021 17:50:15 +0800 Subject: [PATCH 142/763] product attribute update --- .../java/com/zmops/iot/domain/product/ProductAttribute.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java index c86446a5..9ce8dbdc 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java @@ -1,5 +1,6 @@ package com.zmops.iot.domain.product; +import com.fasterxml.jackson.annotation.JsonProperty; import com.zmops.iot.domain.BaseEntity; import lombok.Data; import lombok.EqualsAndHashCode; @@ -21,6 +22,7 @@ public class ProductAttribute extends BaseEntity { @Id private Long attrId; //属性ID + @JsonProperty("attrName") private String name; // 属性名称 private String key; // 属性唯一Key From c872de72d7c928749fba130de81c68ec0d3443d8 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 10 Sep 2021 20:59:36 +0800 Subject: [PATCH 143/763] :sparkles: add device offline or online rule. --- .../service/ZbxDeviceStatusTrigger.java | 39 +++++++------------ .../trigger/device.status.trigger.ftl | 29 ++++++++++++++ .../api-json/trigger/trigger.last.create.ftl | 14 ------- .../trigger/trigger.nodata.0.create.ftl | 14 ------- .../trigger/trigger.nodata.1.create.ftl | 14 ------- .../api-json/trigger/trigger.update.ftl | 0 .../ProductStatusTriggerController.java | 22 ++++------- .../product/dto/ProductStatusJudgeRule.java | 35 ++++++++++++----- .../service/ProductTriggerService.java | 36 +++++++---------- 9 files changed, 90 insertions(+), 113 deletions(-) create mode 100644 zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.ftl delete mode 100644 zeus-driver/src/main/resources/api-json/trigger/trigger.last.create.ftl delete mode 100644 zeus-driver/src/main/resources/api-json/trigger/trigger.nodata.0.create.ftl delete mode 100644 zeus-driver/src/main/resources/api-json/trigger/trigger.nodata.1.create.ftl delete mode 100644 zeus-driver/src/main/resources/api-json/trigger/trigger.update.ftl diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java index 8cc002e7..9391c324 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java @@ -6,6 +6,8 @@ import com.zmops.zeus.driver.annotation.ParamName; import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; +import java.util.Map; + /** * @author nantian created at 2021/8/10 16:32 *

@@ -19,36 +21,23 @@ public interface ZbxDeviceStatusTrigger { /** - * 在线状态 - */ - @Post - @JsonPath("/trigger/trigger.nodata.0.create") - public String nodataOnline(@ParamName("hostName") String hostName, - @ParamName("itemKey") String itemKey, - @ParamName("nodatTime") String nodataTime, - @ParamName("triggerName") String triggerName); - - - /** - * 离线状态 + * 创建 设备 在线,离线 触发器 + * + * @param triggerRule rule object + * @return String */ @Post - @JsonPath("/trigger/trigger.nodata.1.create") - public String nodataOffline(@ParamName("hostName") String hostName, - @ParamName("itemKey") String itemKey, - @ParamName("nodatTime") String nodataTime, - @ParamName("triggerName") String triggerName); + @JsonPath("/trigger/device.status.trigger") + String createDeviceStatusTrigger(@ParamName("rule") Map triggerRule); /** - * 自定义状态,最新值等于 ? 触发 + * 修改 设备 在线,离线 触发器 + * + * @param triggerRule rule object + * @return String */ @Post - @JsonPath("/trigger/trigger.last.create") - public String lastValueJudge(@ParamName("hostName") String hostName, - @ParamName("itemKey") String itemKey, - @ParamName("dataValue") String dataValue, - @ParamName("triggerName") String triggerName); - - + @JsonPath("/trigger/device.status.trigger.update") + String updateDeviceStatusTrigger(@ParamName("rule") Map triggerRule); } diff --git a/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.ftl b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.ftl new file mode 100644 index 00000000..881d1f2f --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.ftl @@ -0,0 +1,29 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.create", + "params": [ + { + "description": "${rule.ruleId}", <#--trigger name--> + <#if rule.ruleFunction == "nodata"> + "expression": "nodata(/${rule.deviceId}/${rule.itemKey},${rule.ruleCondition}) = 1", <#--下线规则,nodata = 1 --> + <#else> + "expression": "last(/${rule.deviceId}/${rule.itemKey}) ${rule.ruleFunction} ${rule.ruleCondition}", + + "recovery_mode": 1, + <#if rule.ruleFunctionSecond == "nodata"> + "recovery_expression": "nodata(/${rule.deviceId}/${rule.itemKeySecond},${rule.ruleConditionSecond}) = 0", <#-- 上线规则 nodata = 0 --> + <#else> + "recovery_expression": "last(/${rule.deviceId}/${rule.itemKeySecond}) ${rule.ruleFunctionSecond} ${rule.ruleConditionSecond}", + + "tags": [ + { + "tag": "__offline__", + "value": "{HOST.HOST}" <#--device id--> + } + ] + } + <#-- nodata(/Zabbix server/system.cpu.util[,nice],20s)=0 --> + ], + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.last.create.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.last.create.ftl deleted file mode 100644 index 4ca18746..00000000 --- a/zeus-driver/src/main/resources/api-json/trigger/trigger.last.create.ftl +++ /dev/null @@ -1,14 +0,0 @@ -{ - "jsonrpc": "2.0", - "method": "trigger.create", - "params": [ - { - "description": "${triggerName}", - "expression": "last(/${hostName}/${itemKey})=${dataValue}", - "recovery_mode": 2, - "status": 1 - } - ], - "auth": "${userAuth}", - "id": 1 -} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.nodata.0.create.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.nodata.0.create.ftl deleted file mode 100644 index a6ecc32e..00000000 --- a/zeus-driver/src/main/resources/api-json/trigger/trigger.nodata.0.create.ftl +++ /dev/null @@ -1,14 +0,0 @@ -{ - "jsonrpc": "2.0", - "method": "trigger.create", - "params": [ - { - "description": "${triggerName}", <#--多长时间内有数据--> - "expression": "nodata(/${hostName}/${itemKey},${nodataTime})=0", - "recovery_mode": 2, - "status": 1 - } - ], - "auth": "${userAuth}", - "id": 1 -} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.nodata.1.create.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.nodata.1.create.ftl deleted file mode 100644 index f0442b46..00000000 --- a/zeus-driver/src/main/resources/api-json/trigger/trigger.nodata.1.create.ftl +++ /dev/null @@ -1,14 +0,0 @@ -{ - "jsonrpc": "2.0", - "method": "trigger.create", - "params": [ - { - "description": "${triggerName}", <#--多长时间内没数据--> - "expression": "nodata(/${hostName}/${itemKey},${nodataTime})=1", - "recovery_mode": 2, - "status": 1 - } - ], - "auth": "${userAuth}", - "id": 1 -} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.update.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.update.ftl deleted file mode 100644 index e69de29b..00000000 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java index e60b965c..fde1d355 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java @@ -22,7 +22,7 @@ /** * @author nantian created at 2021/8/3 19:45 *

- * 设备在线状态 触发器 + * 设备在线 离线状态 触发器 */ @RestController @@ -44,23 +44,15 @@ public class ProductStatusTriggerController { * @return ResponseData */ @PostMapping("/create") - public ResponseData createOfflineTrigger(@RequestBody @Valid ProductStatusJudgeRule rule) { + public ResponseData createDeviceStatusTrigger(@RequestBody @Valid ProductStatusJudgeRule rule) { - // nodata(/sanshi-host/sender.a,1m)=1 - // 查询 itemid itemkey 和 template name - ProductAttribute prodAttr = new QProductAttribute().attrId.eq(rule.getProductAttrId()).findOne(); - if (null == prodAttr) { + ProductAttribute prodAttr = new QProductAttribute().attrId.eq(rule.getProductAttrId()).findOne(); + ProductAttribute prodAttrSecond = new QProductAttribute().attrId.eq(rule.getProductAttrIdSecond()).findOne(); + + if (null == prodAttr || null == prodAttrSecond) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } - List itemInfo = JSON.parseObject(zbxItem.getItemInfo(prodAttr.getZbxId(), null), List.class); - - String key = itemInfo.get(0).getKey_(); // item key - - - productTriggerService.createDeviceStatusJudgeTrigger(rule); - - - return ResponseData.success(); + return ResponseData.success(productTriggerService.createDeviceStatusJudgeTrigger(rule)); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java index 332767dd..639c50f8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java @@ -7,12 +7,21 @@ /** * @author nantian created at 2021/8/5 16:06 *

- * 设备 离线/上线 规则 + * 设备 离线/上线 规则 last(/Zabbix server/system.cpu.util[,user])>10 */ @Data public class ProductStatusJudgeRule { + + @NotNull + private String deviceId; // deviceid + + private String ruleId; // 自动生成,trigger name + + + //##################### 下线规则 + @NotNull private Long productAttrId; // 设备属性ID @@ -20,20 +29,26 @@ public class ProductStatusJudgeRule { private String ruleType; // 触发离线 还是 触发在线 @NotNull - private String ruleFunction; // nodata 或者 last 函数 + private String ruleFunction; // nodata 或者 > < = 函数 @NotNull - private String ruleValue; // 时间 或者 值 + private String ruleCondition; // 时间 或者 特定值 + @NotNull + private String productAttrKey; // 属性 Key - private String triggerName; // ID - private String itemKey; - private String hostName; + //##################### 上线规则 - public static final String ON_LINE = "online"; // 上线触发器 - public static final String OFF_LINE = "offline"; // 离线触发器 - public static final String NODATA = "nodata"; - public static final String LASTDATA = "lastdata"; + @NotNull + private Long productAttrIdSecond; // 设备属性ID + + @NotNull + private String ruleFunctionSecond; // nodata 或者 > < = 函数 + @NotNull + private String ruleConditionSecond; // 时间 或者 特定值 + + @NotNull + private String productAttrKeySecond; // 属性 Key } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java index cfedf564..e2058d8c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java @@ -7,10 +7,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import static com.zmops.iot.web.product.dto.ProductStatusJudgeRule.OFF_LINE; -import static com.zmops.iot.web.product.dto.ProductStatusJudgeRule.ON_LINE; -import static com.zmops.iot.web.product.dto.ProductStatusJudgeRule.NODATA; -import static com.zmops.iot.web.product.dto.ProductStatusJudgeRule.LASTDATA; +import java.util.HashMap; +import java.util.Map; /** * @author nantian created at 2021/8/10 17:55 @@ -35,29 +33,25 @@ public class ProductTriggerService { */ public Integer createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { - String triggerName = judgeRule.getTriggerName(); - String hostName = judgeRule.getHostName(); - String itemKey = judgeRule.getItemKey(); - String ruleValue = judgeRule.getRuleValue(); + Map rule = new HashMap<>(); - if (NODATA.equals(judgeRule.getRuleFunction())) { - // 上线触发器 - if (ON_LINE.equals(judgeRule.getRuleType())) { - return getTriggerId(deviceStatusTrigger.nodataOnline(hostName, itemKey, ruleValue, triggerName)); - } + rule.put("ruleId", judgeRule.getRuleId()); + rule.put("deviceId", judgeRule.getDeviceId()); - if (OFF_LINE.equals(judgeRule.getRuleType())) { - return getTriggerId(deviceStatusTrigger.nodataOffline(hostName, itemKey, ruleValue, triggerName)); - } - } + rule.put("ruleFunction", judgeRule.getRuleFunction()); + rule.put("ruleCondition", judgeRule.getRuleCondition()); + rule.put("itemKey", judgeRule.getProductAttrKey()); - if (LASTDATA.equals(judgeRule.getRuleFunction())) { - return getTriggerId(deviceStatusTrigger.lastValueJudge(hostName, itemKey, ruleValue, triggerName)); - } + rule.put("itemKeySecond", judgeRule.getProductAttrKeySecond()); + rule.put("ruleConditionSecond", judgeRule.getRuleConditionSecond()); + rule.put("ruleFunctionSecond", judgeRule.getRuleFunctionSecond()); - return null; + String res = deviceStatusTrigger.createDeviceStatusTrigger(rule); + + return getTriggerId(res); } + private Integer getTriggerId(String responseStr) { TriggerIds ids = JSON.parseObject(responseStr, TriggerIds.class); if (null != ids && ids.getTriggerids().length > 0) { From 273561470c65096b3778e7641547686d2041f7bd Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 10 Sep 2021 22:20:06 +0800 Subject: [PATCH 144/763] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5cd73780..aba7d1aa 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Zeus IoT 宙斯物联网分布式采集平台 +## Zeus IoT distributed collection platform [![GitHub stars](https://img.shields.io/github/stars/zmops/zeus-iot.svg?label=Stars&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub issues](https://img.shields.io/github/issues/zmops/zeus-iot?label=Issuess&logo=github)](https://github.com/zmops/zeus-iot) @@ -6,9 +6,9 @@ ![Version](https://img.shields.io/badge/version-1.0.0--RELEASE-brightgreen) [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) -### 快速安装 +### Quick install -Zeus-IoT 支持 Centos 7、Ubuntu 20.04、Debain 10 、Kylin、UOS 等基于x86_64平台的 Linux 操作系统。 +Zeus-IoT supports Linux operating systems based on the x86_64 platform, such as Centos 7, Ubuntu 20.04, Debain 10, Kylin, and UOS. - Centos7、RedHat 7 From ac47ffd5f44202fc23f5e1db24d94c74a8f355a8 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 11 Sep 2021 10:52:01 +0800 Subject: [PATCH 145/763] :sparkles: product offline event trigger. --- .../trigger/device.status.trigger.update.ftl | 24 ++++++++++++++ .../service/ProductTriggerService.java | 32 ++++++++++++++++--- 2 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl diff --git a/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl new file mode 100644 index 00000000..3026986e --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl @@ -0,0 +1,24 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.create", + "params": [ + { + "triggerid": "${triggerId}", + "description": "${rule.ruleId}", <#--trigger name--> + <#if rule.ruleFunction == "nodata"> + "expression": "nodata(/${rule.deviceId}/${rule.itemKey},${rule.ruleCondition}) = 1", <#--下线规则,nodata = 1 --> + <#else> + "expression": "last(/${rule.deviceId}/${rule.itemKey}) ${rule.ruleFunction} ${rule.ruleCondition}", + + "recovery_mode": 1, + <#if rule.ruleFunctionSecond == "nodata"> + "recovery_expression": "nodata(/${rule.deviceId}/${rule.itemKeySecond},${rule.ruleConditionSecond}) = 0" <#-- 上线规则 nodata = 0 --> + <#else> + "recovery_expression": "last(/${rule.deviceId}/${rule.itemKeySecond}) ${rule.ruleFunctionSecond} ${rule.ruleConditionSecond}" + + } + <#-- nodata(/Zabbix server/system.cpu.util[,nice],20s)=0 --> + ], + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java index e2058d8c..f3480024 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java @@ -34,7 +34,35 @@ public class ProductTriggerService { public Integer createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { Map rule = new HashMap<>(); + buildTriggerCreateMap(rule, judgeRule); + String res = deviceStatusTrigger.createDeviceStatusTrigger(rule); + return getTriggerId(res); + } + + /** + * 修改 设备状态 触发器 + * + * @param judgeRule 判断规则 + * @return Integer + */ + public Integer updateDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { + Map rule = new HashMap<>(); + buildTriggerCreateMap(rule, judgeRule); + + rule.put("triggerId", judgeRule.getTriggerId()); + String res = deviceStatusTrigger.createDeviceStatusTrigger(rule); + + return getTriggerId(res); + } + + /** + * 值拷贝 + * + * @param rule 新规则 + * @param judgeRule 规则 + */ + private void buildTriggerCreateMap(Map rule, ProductStatusJudgeRule judgeRule) { rule.put("ruleId", judgeRule.getRuleId()); rule.put("deviceId", judgeRule.getDeviceId()); @@ -45,10 +73,6 @@ public Integer createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) rule.put("itemKeySecond", judgeRule.getProductAttrKeySecond()); rule.put("ruleConditionSecond", judgeRule.getRuleConditionSecond()); rule.put("ruleFunctionSecond", judgeRule.getRuleFunctionSecond()); - - String res = deviceStatusTrigger.createDeviceStatusTrigger(rule); - - return getTriggerId(res); } From 2bb8cdab3bb7160528390e3ef8e26591f26fdccc Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 11 Sep 2021 11:00:26 +0800 Subject: [PATCH 146/763] :art: optimize the trigger field variable name. --- .../trigger/device.status.trigger.ftl | 6 ++--- .../trigger/device.status.trigger.update.ftl | 6 ++--- .../ProductStatusTriggerController.java | 27 ++++++++++++++++--- .../product/dto/ProductStatusJudgeRule.java | 10 ++++--- .../service/ProductTriggerService.java | 6 ++--- 5 files changed, 38 insertions(+), 17 deletions(-) diff --git a/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.ftl b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.ftl index 881d1f2f..33ba2061 100644 --- a/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.ftl +++ b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.ftl @@ -10,10 +10,10 @@ "expression": "last(/${rule.deviceId}/${rule.itemKey}) ${rule.ruleFunction} ${rule.ruleCondition}", "recovery_mode": 1, - <#if rule.ruleFunctionSecond == "nodata"> - "recovery_expression": "nodata(/${rule.deviceId}/${rule.itemKeySecond},${rule.ruleConditionSecond}) = 0", <#-- 上线规则 nodata = 0 --> + <#if rule.ruleFunctionRecovery == "nodata"> + "recovery_expression": "nodata(/${rule.deviceId}/${rule.itemKeyRecovery},${rule.ruleConditionRecovery}) = 0", <#-- 上线规则 nodata = 0 --> <#else> - "recovery_expression": "last(/${rule.deviceId}/${rule.itemKeySecond}) ${rule.ruleFunctionSecond} ${rule.ruleConditionSecond}", + "recovery_expression": "last(/${rule.deviceId}/${rule.itemKeyRecovery}) ${rule.ruleFunctionRecovery} ${rule.ruleConditionRecovery}", "tags": [ { diff --git a/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl index 3026986e..0e6e0a06 100644 --- a/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl +++ b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl @@ -11,10 +11,10 @@ "expression": "last(/${rule.deviceId}/${rule.itemKey}) ${rule.ruleFunction} ${rule.ruleCondition}", "recovery_mode": 1, - <#if rule.ruleFunctionSecond == "nodata"> - "recovery_expression": "nodata(/${rule.deviceId}/${rule.itemKeySecond},${rule.ruleConditionSecond}) = 0" <#-- 上线规则 nodata = 0 --> + <#if rule.ruleFunctionRecovery == "nodata"> + "recovery_expression": "nodata(/${rule.deviceId}/${rule.itemKeyRecovery},${rule.ruleConditionRecovery}) = 0" <#-- 上线规则 nodata = 0 --> <#else> - "recovery_expression": "last(/${rule.deviceId}/${rule.itemKeySecond}) ${rule.ruleFunctionSecond} ${rule.ruleConditionSecond}" + "recovery_expression": "last(/${rule.deviceId}/${rule.itemKeyRecovery}) ${rule.ruleFunctionRecovery} ${rule.ruleConditionRecovery}" } <#-- nodata(/Zabbix server/system.cpu.util[,nice],20s)=0 --> diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java index fde1d355..6b01170e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java @@ -1,6 +1,5 @@ package com.zmops.iot.web.product.controller; -import com.alibaba.fastjson.JSON; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.model.exception.ServiceException; @@ -8,7 +7,6 @@ import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductStatusJudgeRule; import com.zmops.iot.web.product.service.ProductTriggerService; -import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.service.ZbxItem; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; @@ -17,7 +15,6 @@ import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; -import java.util.List; /** * @author nantian created at 2021/8/3 19:45 @@ -47,7 +44,7 @@ public class ProductStatusTriggerController { public ResponseData createDeviceStatusTrigger(@RequestBody @Valid ProductStatusJudgeRule rule) { ProductAttribute prodAttr = new QProductAttribute().attrId.eq(rule.getProductAttrId()).findOne(); - ProductAttribute prodAttrSecond = new QProductAttribute().attrId.eq(rule.getProductAttrIdSecond()).findOne(); + ProductAttribute prodAttrSecond = new QProductAttribute().attrId.eq(rule.getProductAttrIdRecovery()).findOne(); if (null == prodAttr || null == prodAttrSecond) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); @@ -55,4 +52,26 @@ public ResponseData createDeviceStatusTrigger(@RequestBody @Valid ProductStatusJ return ResponseData.success(productTriggerService.createDeviceStatusJudgeTrigger(rule)); } + + + /** + * 修改 离线 或者 在线触发器 + * + * @param rule 在线规则 + * @return ResponseData + */ + @PostMapping("/update") + public ResponseData updateDeviceStatusTrigger(@RequestBody @Valid ProductStatusJudgeRule rule) { + + ProductAttribute prodAttr = new QProductAttribute().attrId.eq(rule.getProductAttrId()).findOne(); + ProductAttribute prodAttrSecond = new QProductAttribute().attrId.eq(rule.getProductAttrIdRecovery()).findOne(); + + if (null == prodAttr || null == prodAttrSecond) { + throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); + } + + // 数据库查询 triggerId 并且赋值 + + return ResponseData.success(productTriggerService.updateDeviceStatusJudgeTrigger(rule)); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java index 639c50f8..fc10bc52 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java @@ -19,6 +19,8 @@ public class ProductStatusJudgeRule { private String ruleId; // 自动生成,trigger name + private String triggerId; // zbxId + //##################### 下线规则 @@ -41,14 +43,14 @@ public class ProductStatusJudgeRule { //##################### 上线规则 @NotNull - private Long productAttrIdSecond; // 设备属性ID + private Long productAttrIdRecovery; // 设备属性ID @NotNull - private String ruleFunctionSecond; // nodata 或者 > < = 函数 + private String ruleFunctionRecovery; // nodata 或者 > < = 函数 @NotNull - private String ruleConditionSecond; // 时间 或者 特定值 + private String ruleConditionRecovery; // 时间 或者 特定值 @NotNull - private String productAttrKeySecond; // 属性 Key + private String productAttrKeyRecovery; // 属性 Key } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java index f3480024..928db537 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java @@ -70,9 +70,9 @@ private void buildTriggerCreateMap(Map rule, ProductStatusJudgeR rule.put("ruleCondition", judgeRule.getRuleCondition()); rule.put("itemKey", judgeRule.getProductAttrKey()); - rule.put("itemKeySecond", judgeRule.getProductAttrKeySecond()); - rule.put("ruleConditionSecond", judgeRule.getRuleConditionSecond()); - rule.put("ruleFunctionSecond", judgeRule.getRuleFunctionSecond()); + rule.put("itemKeyRecovery", judgeRule.getProductAttrKeyRecovery()); + rule.put("ruleConditionRecovery", judgeRule.getRuleConditionRecovery()); + rule.put("ruleFunctionRecovery", judgeRule.getRuleFunctionRecovery()); } From fe6580ffd98eb7e3300ac0caf415a463492cc9c4 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 11 Sep 2021 11:33:33 +0800 Subject: [PATCH 147/763] :art: optimize the conversion of device value and item value. --- .../process/ByteArrayToItemValueProcess.java | 14 +++----- .../camel/process/JsonToItemValueProcess.java | 13 +++----- .../camel/process/StringItemValueProcess.java | 33 ++++--------------- 3 files changed, 16 insertions(+), 44 deletions(-) diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java index c2bb66b7..c8a6621b 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java @@ -30,15 +30,11 @@ public void process(Exchange exchange) throws Exception { List valueList = gson.fromJson(inputContext, new TypeToken>() {}.getType()); - // 多一步 命名转换,方便 Json 字段理解 List itemValueList = new ArrayList<>(); - valueList.forEach(i -> { - ItemValue item = new ItemValue(i.getDeviceId(), i.getDeviceAttrKey(), i.getDeviceAttrValue()); - if (i.getDeviceTime() != null) { - item.setClock(i.getDeviceTime()); - } - itemValueList.add(item); - }); - exchange.getMessage().setBody(itemValueList); + + ItemValue item = new ItemValue(itemValueList); + valueList.forEach(item::addItemValue); + + exchange.getMessage().setBody(item.getValueList()); } } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/JsonToItemValueProcess.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/JsonToItemValueProcess.java index 4e48223c..8c467eb9 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/JsonToItemValueProcess.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/JsonToItemValueProcess.java @@ -32,17 +32,12 @@ public void process(Exchange exchange) throws Exception { List valueList = gson.fromJson(inputContext, new TypeToken>() {}.getType()); - // 多一步 命名转换,方便 Json 字段理解 List itemValueList = new ArrayList<>(); - valueList.forEach(i -> { - ItemValue item = new ItemValue(i.getDeviceId(), i.getDeviceAttrKey(), i.getDeviceAttrValue()); - if (i.getDeviceTime() != null) { - item.setClock(i.getDeviceTime()); - } - itemValueList.add(item); - }); - exchange.getMessage().setBody(itemValueList); + ItemValue item = new ItemValue(itemValueList); + valueList.forEach(item::addItemValue); + + exchange.getMessage().setBody(item.getValueList()); } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/StringItemValueProcess.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/StringItemValueProcess.java index a2236e26..7802affc 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/StringItemValueProcess.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/StringItemValueProcess.java @@ -25,36 +25,17 @@ public class StringItemValueProcess implements Processor { @Override public void process(Exchange exchange) throws Exception { - Message message = exchange.getIn(); - List valueList = gson.fromJson((String) message.getBody(), new TypeToken>() {}.getType()); + Message message = exchange.getIn(); + + List valueList = gson.fromJson((String) message.getBody(), new TypeToken>() { + }.getType()); // 多一步 命名转换,方便 Json 字段理解 List itemValueList = new ArrayList<>(); - valueList.forEach(i -> { - ItemValue item = new ItemValue(i.getDeviceId(), i.getDeviceAttrKey(), i.getDeviceAttrValue()); - if (i.getDeviceTime() != null) { - item.setClock(i.getDeviceTime()); - } - itemValueList.add(item); - }); - - exchange.getMessage().setBody(itemValueList); - } + ItemValue item = new ItemValue(itemValueList); + valueList.forEach(item::addItemValue); - private String analysisMessage(InputStream bodyStream) throws IOException { - ByteArrayOutputStream outStream = new ByteArrayOutputStream(); - byte[] contextBytes = new byte[4096]; - int realLen; - while ((realLen = bodyStream.read(contextBytes, 0, 4096)) != -1) { - outStream.write(contextBytes, 0, realLen); - } - - // 返回从Stream中读取的字串 - try { - return outStream.toString("UTF-8"); - } finally { - outStream.close(); - } + exchange.getMessage().setBody(item.getValueList()); } } From 6884f08bd1f49ef69ccd50b8a923e4d36f6f00ed Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 11 Sep 2021 11:40:26 +0800 Subject: [PATCH 148/763] itemvalue. --- .../server/core/worker/data/ItemValue.java | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ItemValue.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ItemValue.java index 120478e5..482cddb4 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ItemValue.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ItemValue.java @@ -1,8 +1,13 @@ package com.zmops.zeus.iot.server.core.worker.data; +import afu.org.checkerframework.checker.igj.qual.I; +import com.zmops.zeus.iot.server.core.camel.IOTDeviceValue; import lombok.Getter; import lombok.Setter; +import java.util.ArrayList; +import java.util.List; + /** * @author nantian created at 2021/8/23 15:15 */ @@ -23,12 +28,33 @@ public class ItemValue implements Item { private Long ns; // 纳秒,如果为 Null,则 zabbix 以接收时间为准 - public ItemValue(String host, String key, String value) { - this.host = host; - this.key = key; - this.value = value; + + public ItemValue(List itemValueList) { + this.valueList = itemValueList; + } + + public ItemValue() { + super(); + } + + private List valueList; + + public void addItemValue(IOTDeviceValue deviceValue) { + + ItemValue itemValue = new ItemValue(); + + itemValue.setHost(deviceValue.getDeviceId()); + itemValue.setKey(deviceValue.getDeviceAttrKey()); + itemValue.setValue(deviceValue.getDeviceAttrValue()); + + if (deviceValue.getDeviceTime() != null) { + itemValue.setClock(deviceValue.getDeviceTime()); + } + + this.valueList.add(itemValue); } + /** * 设置 数据时间,单独设置 以设备推送的时间数据为准 * From 1899ec3555d34c538c7194b50d8df8c9e140d783 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 11 Sep 2021 12:11:27 +0800 Subject: [PATCH 149/763] offline event trigger update --- .../domain/product/ProductStatusFunction.java | 14 ++++-- .../ProductStatusFunctionRelation.java | 25 ++++++++++ .../web/exception/enums/BizExceptionEnum.java | 5 ++ .../ProductStatusTriggerController.java | 16 +++++-- .../product/dto/ProductStatusJudgeRule.java | 36 ++++++++------- .../service/ProductTriggerService.java | 46 +++++++++++++++---- 6 files changed, 107 insertions(+), 35 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunction.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunction.java index dcebc208..8ddd6db7 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunction.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunction.java @@ -19,15 +19,21 @@ public class ProductStatusFunction extends BaseEntity { @Id - private Long triggerId; + private Long ruleId; - private Integer zbxId; + private String zbxId; - private String ruleType; + private String ruleFunction; - private String fuleFunction; + private Long attrId; private String ruleValue; private Integer ruleStatus; + + private String ruleFunctionRecovery; + + private String ruleValueRecovery; + + private Long attrIdRecovery; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java new file mode 100644 index 00000000..632dacfb --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java @@ -0,0 +1,25 @@ +package com.zmops.iot.domain.product; + +import com.zmops.iot.domain.BaseEntity; +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author nantian created at 2021/8/11 17:02 + */ + +@Getter +@Setter +@Entity +@Table(name = "product_status_function_relation") +public class ProductStatusFunctionRelation { + + private Long ruleId; + + private String relationId; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index 7e5ad020..32339d10 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -154,6 +154,11 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { SERVICE_EXISTS(1601, "服务已存在"), SERVICE_NOT_EXISTS(1602, "服务不存在"), + /** + * 触发规则相关 + */ + RULE_NOT_EXISTS(1701, "规则不存在"), + /** * 租户相关的异常 */ diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java index 6b01170e..cc675834 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java @@ -1,7 +1,9 @@ package com.zmops.iot.web.product.controller; import com.zmops.iot.domain.product.ProductAttribute; +import com.zmops.iot.domain.product.ProductStatusFunction; import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.domain.product.query.QProductStatusFunction; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.web.exception.enums.BizExceptionEnum; @@ -43,8 +45,8 @@ public class ProductStatusTriggerController { @PostMapping("/create") public ResponseData createDeviceStatusTrigger(@RequestBody @Valid ProductStatusJudgeRule rule) { - ProductAttribute prodAttr = new QProductAttribute().attrId.eq(rule.getProductAttrId()).findOne(); - ProductAttribute prodAttrSecond = new QProductAttribute().attrId.eq(rule.getProductAttrIdRecovery()).findOne(); + ProductAttribute prodAttr = new QProductAttribute().attrId.eq(rule.getAttrId()).findOne(); + ProductAttribute prodAttrSecond = new QProductAttribute().attrId.eq(rule.getAttrIdRecovery()).findOne(); if (null == prodAttr || null == prodAttrSecond) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); @@ -63,14 +65,20 @@ public ResponseData createDeviceStatusTrigger(@RequestBody @Valid ProductStatusJ @PostMapping("/update") public ResponseData updateDeviceStatusTrigger(@RequestBody @Valid ProductStatusJudgeRule rule) { - ProductAttribute prodAttr = new QProductAttribute().attrId.eq(rule.getProductAttrId()).findOne(); - ProductAttribute prodAttrSecond = new QProductAttribute().attrId.eq(rule.getProductAttrIdRecovery()).findOne(); + ProductAttribute prodAttr = new QProductAttribute().attrId.eq(rule.getAttrId()).findOne(); + ProductAttribute prodAttrSecond = new QProductAttribute().attrId.eq(rule.getAttrIdRecovery()).findOne(); if (null == prodAttr || null == prodAttrSecond) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } // 数据库查询 triggerId 并且赋值 + ProductStatusFunction productStatusFunction = new QProductStatusFunction().ruleId.eq(rule.getRuleId()).findOne(); + if(null == productStatusFunction){ + throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); + } + rule.setTriggerId(productStatusFunction.getZbxId()); + return ResponseData.success(productTriggerService.updateDeviceStatusJudgeTrigger(rule)); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java index fc10bc52..c656b468 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java @@ -1,7 +1,9 @@ package com.zmops.iot.web.product.dto; +import com.zmops.iot.domain.BaseEntity; import lombok.Data; +import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; /** @@ -14,43 +16,43 @@ public class ProductStatusJudgeRule { - @NotNull - private String deviceId; // deviceid + @NotBlank(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) + private String relationId; // deviceid - private String ruleId; // 自动生成,trigger name + @NotNull(groups = BaseEntity.Update.class) + private Long ruleId; // 自动生成,trigger name - private String triggerId; // zbxId + @NotBlank(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) + private String ruleName; + private String triggerId; // zbxId //##################### 下线规则 - @NotNull - private Long productAttrId; // 设备属性ID - - @NotNull - private String ruleType; // 触发离线 还是 触发在线 + @NotNull(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) + private Long attrId; // 设备属性ID - @NotNull + @NotBlank(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) private String ruleFunction; // nodata 或者 > < = 函数 - @NotNull + @NotBlank(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) private String ruleCondition; // 时间 或者 特定值 - @NotNull + @NotBlank(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) private String productAttrKey; // 属性 Key //##################### 上线规则 - @NotNull - private Long productAttrIdRecovery; // 设备属性ID + @NotNull(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) + private Long attrIdRecovery; // 设备属性ID - @NotNull + @NotBlank(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) private String ruleFunctionRecovery; // nodata 或者 > < = 函数 - @NotNull + @NotBlank(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) private String ruleConditionRecovery; // 时间 或者 特定值 - @NotNull + @NotBlank(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) private String productAttrKeyRecovery; // 属性 Key } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java index 928db537..aab04560 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java @@ -1,11 +1,17 @@ package com.zmops.iot.web.product.service; +import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSON; +import com.zmops.iot.domain.product.ProductStatusFunction; +import com.zmops.iot.domain.product.ProductStatusFunctionRelation; import com.zmops.iot.web.product.dto.ProductStatusJudgeRule; import com.zmops.zeus.driver.service.ZbxDeviceStatusTrigger; +import io.ebean.DB; import lombok.Data; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.HashMap; import java.util.Map; @@ -31,13 +37,29 @@ public class ProductTriggerService { * @param judgeRule 判断规则 * @return Integer */ - public Integer createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { + @Transactional(rollbackFor = Exception.class) + public Long createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { + long ruleId = IdUtil.getSnowflake().nextId(); + judgeRule.setRuleId(ruleId); Map rule = new HashMap<>(); buildTriggerCreateMap(rule, judgeRule); - String res = deviceStatusTrigger.createDeviceStatusTrigger(rule); - return getTriggerId(res); + String res = deviceStatusTrigger.createDeviceStatusTrigger(rule); + String triggerId = getTriggerId(res); + + ProductStatusFunction productStatusFunction = new ProductStatusFunction(); + BeanUtils.copyProperties(judgeRule, productStatusFunction); + productStatusFunction.setZbxId(triggerId); + productStatusFunction.setRuleId(ruleId); + DB.save(productStatusFunction); + + ProductStatusFunctionRelation productStatusFunctionRelation = new ProductStatusFunctionRelation(); + productStatusFunctionRelation.setRelationId(judgeRule.getRelationId()); + productStatusFunctionRelation.setRuleId(ruleId); + DB.save(productStatusFunctionRelation); + + return productStatusFunction.getRuleId(); } /** @@ -46,14 +68,18 @@ public Integer createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) * @param judgeRule 判断规则 * @return Integer */ - public Integer updateDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { + public Long updateDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { Map rule = new HashMap<>(); buildTriggerCreateMap(rule, judgeRule); rule.put("triggerId", judgeRule.getTriggerId()); - String res = deviceStatusTrigger.createDeviceStatusTrigger(rule); + deviceStatusTrigger.updateDeviceStatusTrigger(rule); + + ProductStatusFunction productStatusFunction = new ProductStatusFunction(); + BeanUtils.copyProperties(judgeRule, productStatusFunction); + DB.update(productStatusFunction); - return getTriggerId(res); + return judgeRule.getRuleId(); } /** @@ -63,8 +89,8 @@ public Integer updateDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) * @param judgeRule 规则 */ private void buildTriggerCreateMap(Map rule, ProductStatusJudgeRule judgeRule) { - rule.put("ruleId", judgeRule.getRuleId()); - rule.put("deviceId", judgeRule.getDeviceId()); + rule.put("ruleId", judgeRule.getRuleId() + ""); + rule.put("deviceId", judgeRule.getRelationId()); rule.put("ruleFunction", judgeRule.getRuleFunction()); rule.put("ruleCondition", judgeRule.getRuleCondition()); @@ -76,7 +102,7 @@ private void buildTriggerCreateMap(Map rule, ProductStatusJudgeR } - private Integer getTriggerId(String responseStr) { + private String getTriggerId(String responseStr) { TriggerIds ids = JSON.parseObject(responseStr, TriggerIds.class); if (null != ids && ids.getTriggerids().length > 0) { return ids.getTriggerids()[0]; @@ -87,6 +113,6 @@ private Integer getTriggerId(String responseStr) { @Data static class TriggerIds { - Integer[] triggerids; + String[] triggerids; } } From bb198727e18677de801ed185483efd2996e8c116 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 11 Sep 2021 15:01:39 +0800 Subject: [PATCH 150/763] offline event trigger update --- .../domain/product/ProductStatusFunction.java | 4 +- .../service/ZbxDeviceStatusTrigger.java | 21 ++++++-- .../trigger/device.status.trigger.ftl | 14 +++--- .../trigger/device.status.trigger.update.ftl | 16 +++---- .../rest/DeviceStatusWebhookController.java | 33 ++++++++++++- .../web/exception/enums/BizExceptionEnum.java | 3 +- .../ProductStatusTriggerController.java | 48 ++++++++++++++----- .../product/dto/ProductStatusJudgeRule.java | 21 ++++---- .../service/ProductTriggerService.java | 43 +++++++++++++---- 9 files changed, 149 insertions(+), 54 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunction.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunction.java index 8ddd6db7..1af9e26a 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunction.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunction.java @@ -27,13 +27,13 @@ public class ProductStatusFunction extends BaseEntity { private Long attrId; - private String ruleValue; + private String ruleCondition; private Integer ruleStatus; private String ruleFunctionRecovery; - private String ruleValueRecovery; + private String ruleConditionRecovery; private Long attrIdRecovery; } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java index 9391c324..89463188 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java @@ -23,21 +23,34 @@ public interface ZbxDeviceStatusTrigger { /** * 创建 设备 在线,离线 触发器 * - * @param triggerRule rule object * @return String */ @Post @JsonPath("/trigger/device.status.trigger") - String createDeviceStatusTrigger(@ParamName("rule") Map triggerRule); + String createDeviceStatusTrigger(@ParamName("ruleId") String ruleId, + @ParamName("deviceId") String deviceId, + @ParamName("itemKey") String itemKey, + @ParamName("ruleCondition") String ruleCondition, + @ParamName("ruleFunction") String ruleFunction, + @ParamName("itemKeyRecovery") String itemKeyRecovery, + @ParamName("ruleConditionRecovery") String ruleConditionRecovery, + @ParamName("ruleFunctionRecovery") String ruleFunctionRecovery); /** * 修改 设备 在线,离线 触发器 * - * @param triggerRule rule object * @return String */ @Post @JsonPath("/trigger/device.status.trigger.update") - String updateDeviceStatusTrigger(@ParamName("rule") Map triggerRule); + String updateDeviceStatusTrigger(@ParamName("triggerId") String triggerId, + @ParamName("ruleId") String ruleId, + @ParamName("deviceId") String deviceId, + @ParamName("itemKey") String itemKey, + @ParamName("ruleCondition") String ruleCondition, + @ParamName("ruleFunction") String ruleFunction, + @ParamName("itemKeyRecovery") String itemKeyRecovery, + @ParamName("ruleConditionRecovery") String ruleConditionRecovery, + @ParamName("ruleFunctionRecovery") String ruleFunctionRecovery); } diff --git a/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.ftl b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.ftl index 33ba2061..7f7be923 100644 --- a/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.ftl +++ b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.ftl @@ -3,17 +3,17 @@ "method": "trigger.create", "params": [ { - "description": "${rule.ruleId}", <#--trigger name--> - <#if rule.ruleFunction == "nodata"> - "expression": "nodata(/${rule.deviceId}/${rule.itemKey},${rule.ruleCondition}) = 1", <#--下线规则,nodata = 1 --> + "description": "${ruleId}", <#--trigger name--> + <#if ruleFunction == "nodata"> + "expression": "nodata(/${deviceId}/${itemKey},${ruleCondition}) = 1", <#--下线规则,nodata = 1 --> <#else> - "expression": "last(/${rule.deviceId}/${rule.itemKey}) ${rule.ruleFunction} ${rule.ruleCondition}", + "expression": "last(/${deviceId}/${itemKey}) ${ruleFunction} ${ruleCondition}", "recovery_mode": 1, - <#if rule.ruleFunctionRecovery == "nodata"> - "recovery_expression": "nodata(/${rule.deviceId}/${rule.itemKeyRecovery},${rule.ruleConditionRecovery}) = 0", <#-- 上线规则 nodata = 0 --> + <#if ruleFunctionRecovery == "nodata"> + "recovery_expression": "nodata(/${deviceId}/${itemKeyRecovery},${ruleConditionRecovery}) = 0", <#-- 上线规则 nodata = 0 --> <#else> - "recovery_expression": "last(/${rule.deviceId}/${rule.itemKeyRecovery}) ${rule.ruleFunctionRecovery} ${rule.ruleConditionRecovery}", + "recovery_expression": "last(/${deviceId}/${itemKeyRecovery}) ${ruleFunctionRecovery} ${ruleConditionRecovery}", "tags": [ { diff --git a/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl index 0e6e0a06..728d6734 100644 --- a/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl +++ b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl @@ -1,20 +1,20 @@ { "jsonrpc": "2.0", - "method": "trigger.create", + "method": "trigger.update", "params": [ { "triggerid": "${triggerId}", - "description": "${rule.ruleId}", <#--trigger name--> - <#if rule.ruleFunction == "nodata"> - "expression": "nodata(/${rule.deviceId}/${rule.itemKey},${rule.ruleCondition}) = 1", <#--下线规则,nodata = 1 --> + "description": "${ruleId}", <#--trigger name--> + <#if ruleFunction == "nodata"> + "expression": "nodata(/${deviceId}/${itemKey},${ruleCondition}) = 1", <#--下线规则,nodata = 1 --> <#else> - "expression": "last(/${rule.deviceId}/${rule.itemKey}) ${rule.ruleFunction} ${rule.ruleCondition}", + "expression": "last(/${deviceId}/${itemKey}) ${ruleFunction} ${ruleCondition}", "recovery_mode": 1, - <#if rule.ruleFunctionRecovery == "nodata"> - "recovery_expression": "nodata(/${rule.deviceId}/${rule.itemKeyRecovery},${rule.ruleConditionRecovery}) = 0" <#-- 上线规则 nodata = 0 --> + <#if ruleFunctionRecovery == "nodata"> + "recovery_expression": "nodata(/${deviceId}/${itemKeyRecovery},${ruleConditionRecovery}) = 0" <#-- 上线规则 nodata = 0 --> <#else> - "recovery_expression": "last(/${rule.deviceId}/${rule.itemKeyRecovery}) ${rule.ruleFunctionRecovery} ${rule.ruleConditionRecovery}" + "recovery_expression": "last(/${deviceId}/${itemKeyRecovery}) ${ruleFunctionRecovery} ${ruleConditionRecovery}" } <#-- nodata(/Zabbix server/system.cpu.util[,nice],20s)=0 --> diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java index a73c78eb..71ac5d96 100644 --- a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java @@ -5,6 +5,7 @@ import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.web.alarm.service.AlarmNoticeWorker; +import com.zmops.iot.web.device.service.work.DeviceOnlineWorker; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -19,22 +20,50 @@ */ @RestController -@RequestMapping("/rest/device") +@RequestMapping("/device") public class DeviceStatusWebhookController { @Autowired private AlarmNoticeWorker alarmNoticeWorker; + @Autowired + DeviceOnlineWorker deviceOnlineWorker; + /** * 在线状态 回调 * * @param params webhook 回调参数 * @return ResponseData */ - @RequestMapping("/webhook") + @RequestMapping("/status") public ResponseData deviceStatusWebhook(@RequestBody Map params) { + System.out.println(JSON.toJSONString(params)); + + WorkerWrapper, Boolean> deviceOnlineWork = WorkerWrapper., Boolean>builder().id("deviceOnlineWork") + .worker(deviceOnlineWorker).param(params) + .build(); + + try { + Async.work(3000, deviceOnlineWork).awaitFinish(); + } catch (Exception e) { + e.printStackTrace(); + } + + return ResponseData.success("OK"); + } + + /** + * 设备告警 回调 + * + * @param params webhook 回调参数 + * @return ResponseData + */ + @RequestMapping("/problem") + public ResponseData deviceProblemWebhook(@RequestBody Map params) { + + System.out.println(JSON.toJSONString(params)); WorkerWrapper, Boolean> alarmNoticeWork = WorkerWrapper., Boolean>builder().id("alarmNoticeWork") diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index 32339d10..825d4a08 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -157,7 +157,8 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { /** * 触发规则相关 */ - RULE_NOT_EXISTS(1701, "规则不存在"), + RULE_NOT_EXISTS(1701, "上下线规则不存在"), + RULE_EXISTS(1702, "上下线规则已存在"), /** * 租户相关的异常 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java index cc675834..9ffeee30 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java @@ -1,22 +1,21 @@ package com.zmops.iot.web.product.controller; +import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.ProductStatusFunction; import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.domain.product.query.QProductStatusFunction; +import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductStatusJudgeRule; import com.zmops.iot.web.product.service.ProductTriggerService; import com.zmops.zeus.driver.service.ZbxItem; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.validation.Valid; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; /** * @author nantian created at 2021/8/3 19:45 @@ -35,6 +34,17 @@ public class ProductStatusTriggerController { @Autowired private ProductTriggerService productTriggerService; + /** + * 离线 或者 在线触发器 信息 + * + * @param relationId 关联产品或设备ID + * @return ResponseData + */ + @GetMapping("/detail") + public ResponseData getRule(@RequestParam("relationId") String relationId){ + return ResponseData.success(productTriggerService.getRule(relationId)); + } + /** * 创建 离线 或者 在线触发器 @@ -43,7 +53,7 @@ public class ProductStatusTriggerController { * @return ResponseData */ @PostMapping("/create") - public ResponseData createDeviceStatusTrigger(@RequestBody @Valid ProductStatusJudgeRule rule) { + public ResponseData createDeviceStatusTrigger(@RequestBody @Validated(BaseEntity.Create.class) ProductStatusJudgeRule rule) { ProductAttribute prodAttr = new QProductAttribute().attrId.eq(rule.getAttrId()).findOne(); ProductAttribute prodAttrSecond = new QProductAttribute().attrId.eq(rule.getAttrIdRecovery()).findOne(); @@ -52,6 +62,10 @@ public ResponseData createDeviceStatusTrigger(@RequestBody @Valid ProductStatusJ throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } + int count = new QProductStatusFunctionRelation().relationId.eq(rule.getRelationId()).findCount(); + if(count>0){ + throw new ServiceException(BizExceptionEnum.RULE_EXISTS); + } return ResponseData.success(productTriggerService.createDeviceStatusJudgeTrigger(rule)); } @@ -63,7 +77,7 @@ public ResponseData createDeviceStatusTrigger(@RequestBody @Valid ProductStatusJ * @return ResponseData */ @PostMapping("/update") - public ResponseData updateDeviceStatusTrigger(@RequestBody @Valid ProductStatusJudgeRule rule) { + public ResponseData updateDeviceStatusTrigger(@RequestBody @Validated(BaseEntity.Update.class) ProductStatusJudgeRule rule) { ProductAttribute prodAttr = new QProductAttribute().attrId.eq(rule.getAttrId()).findOne(); ProductAttribute prodAttrSecond = new QProductAttribute().attrId.eq(rule.getAttrIdRecovery()).findOne(); @@ -74,12 +88,24 @@ public ResponseData updateDeviceStatusTrigger(@RequestBody @Valid ProductStatusJ // 数据库查询 triggerId 并且赋值 ProductStatusFunction productStatusFunction = new QProductStatusFunction().ruleId.eq(rule.getRuleId()).findOne(); - if(null == productStatusFunction){ - throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); + if (null == productStatusFunction) { + throw new ServiceException(BizExceptionEnum.RULE_NOT_EXISTS); } rule.setTriggerId(productStatusFunction.getZbxId()); - return ResponseData.success(productTriggerService.updateDeviceStatusJudgeTrigger(rule)); } + + /** + * 删除 离线 或者 在线触发器 + * + * @param rule 在线规则 + * @return ResponseData + */ + @PostMapping("/delete") + public ResponseData deleteDeviceStatusTrigger(@RequestBody @Validated(BaseEntity.Delete.class) ProductStatusJudgeRule rule) { + productTriggerService.deleteDeviceStatusTrigger(rule.getRuleId()); + return ResponseData.success(); + } + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java index c656b468..c13ba00e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java @@ -16,43 +16,42 @@ public class ProductStatusJudgeRule { - @NotBlank(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) + @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) private String relationId; // deviceid - @NotNull(groups = BaseEntity.Update.class) + @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Delete.class}) private Long ruleId; // 自动生成,trigger name - @NotBlank(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) private String ruleName; private String triggerId; // zbxId //##################### 下线规则 - @NotNull(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) + @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) private Long attrId; // 设备属性ID - @NotBlank(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) + @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) private String ruleFunction; // nodata 或者 > < = 函数 - @NotBlank(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) + @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) private String ruleCondition; // 时间 或者 特定值 - @NotBlank(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) + @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) private String productAttrKey; // 属性 Key //##################### 上线规则 - @NotNull(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) + @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) private Long attrIdRecovery; // 设备属性ID - @NotBlank(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) + @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) private String ruleFunctionRecovery; // nodata 或者 > < = 函数 - @NotBlank(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) + @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) private String ruleConditionRecovery; // 时间 或者 特定值 - @NotBlank(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) + @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) private String productAttrKeyRecovery; // 属性 Key } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java index aab04560..51fcf9a5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java @@ -4,6 +4,8 @@ import com.alibaba.fastjson.JSON; import com.zmops.iot.domain.product.ProductStatusFunction; import com.zmops.iot.domain.product.ProductStatusFunctionRelation; +import com.zmops.iot.domain.product.query.QProductStatusFunction; +import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; import com.zmops.iot.web.product.dto.ProductStatusJudgeRule; import com.zmops.zeus.driver.service.ZbxDeviceStatusTrigger; import io.ebean.DB; @@ -13,7 +15,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.HashMap; import java.util.Map; /** @@ -30,6 +31,18 @@ public class ProductTriggerService { @Autowired private ZbxDeviceStatusTrigger deviceStatusTrigger; + /** + * 离线 或者 在线触发器 信息 + * + * @param relationId 在线规则 + * @return ResponseData + */ + public ProductStatusFunction getRule(String relationId) { + ProductStatusFunctionRelation productStatusFunctionRelation = new QProductStatusFunctionRelation().relationId.eq(relationId).findOne(); + + return new QProductStatusFunction().ruleId.eq(productStatusFunctionRelation.getRuleId()).findOne(); + } + /** * 创建 设备状态 触发器 @@ -42,10 +55,13 @@ public Long createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { long ruleId = IdUtil.getSnowflake().nextId(); judgeRule.setRuleId(ruleId); - Map rule = new HashMap<>(); - buildTriggerCreateMap(rule, judgeRule); +// Map rule = new HashMap<>(); +// buildTriggerCreateMap(rule, judgeRule); + + String res = deviceStatusTrigger.createDeviceStatusTrigger(judgeRule.getRuleId() + "", judgeRule.getRelationId(), + judgeRule.getProductAttrKey(), judgeRule.getRuleCondition(), judgeRule.getRuleFunction(), judgeRule.getProductAttrKeyRecovery(), + judgeRule.getRuleConditionRecovery(), judgeRule.getRuleFunctionRecovery()); - String res = deviceStatusTrigger.createDeviceStatusTrigger(rule); String triggerId = getTriggerId(res); ProductStatusFunction productStatusFunction = new ProductStatusFunction(); @@ -69,11 +85,12 @@ public Long createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { * @return Integer */ public Long updateDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { - Map rule = new HashMap<>(); - buildTriggerCreateMap(rule, judgeRule); +// Map rule = new HashMap<>(); +// buildTriggerCreateMap(rule, judgeRule); - rule.put("triggerId", judgeRule.getTriggerId()); - deviceStatusTrigger.updateDeviceStatusTrigger(rule); + deviceStatusTrigger.updateDeviceStatusTrigger(judgeRule.getTriggerId(), judgeRule.getRuleId() + "", judgeRule.getRelationId(), + judgeRule.getProductAttrKey(), judgeRule.getRuleCondition(), judgeRule.getRuleFunction(), judgeRule.getProductAttrKeyRecovery(), + judgeRule.getRuleConditionRecovery(), judgeRule.getRuleFunctionRecovery()); ProductStatusFunction productStatusFunction = new ProductStatusFunction(); BeanUtils.copyProperties(judgeRule, productStatusFunction); @@ -110,6 +127,16 @@ private String getTriggerId(String responseStr) { return null; } + /** + * 删除 离线 或者 在线触发器 + */ + @Transactional(rollbackFor = Exception.class) + public void deleteDeviceStatusTrigger(Long ruleId) { + new QProductStatusFunctionRelation().ruleId.eq(ruleId).delete(); + + new QProductStatusFunction().ruleId.eq(ruleId).delete(); + } + @Data static class TriggerIds { From d298b522ad0418b5152f0094f5bedd8de4226dc9 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 11 Sep 2021 17:47:38 +0800 Subject: [PATCH 151/763] Update quick-start.rst modify document title. --- docs/quick-start.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/quick-start.rst b/docs/quick-start.rst index 094b387c..76155834 100644 --- a/docs/quick-start.rst +++ b/docs/quick-start.rst @@ -1,2 +1,2 @@ -赶快体验自己的 Zeus-IOT -====================== \ No newline at end of file +Quickly experience Zeus-IOT +=========================== From 79f2d5080c707be47d90eec54c274e4eb403b2df Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 11 Sep 2021 18:46:17 +0800 Subject: [PATCH 152/763] offline event trigger update --- .../domain/product/ProductStatusFunction.java | 4 ++ .../core/auth/filter/NoneAuthedResources.java | 3 +- .../api-json/script/script.init.create.ftl | 2 +- .../service/work/DeviceOnlineWorker.java | 53 +++++++++++++++ .../product/dto/ProductStatusFunctionDto.java | 66 +++++++++++++++++++ .../product/dto/ProductStatusJudgeRule.java | 23 ++++--- .../product/service/ProductModelService.java | 8 +-- .../service/ProductTriggerService.java | 18 ++--- 8 files changed, 154 insertions(+), 23 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusFunctionDto.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunction.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunction.java index 1af9e26a..b8b3072c 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunction.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunction.java @@ -36,4 +36,8 @@ public class ProductStatusFunction extends BaseEntity { private String ruleConditionRecovery; private Long attrIdRecovery; + + private String unit; + + private String unitRecovery; } diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java index a346c96d..09de04d2 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java @@ -22,7 +22,8 @@ public class NoneAuthedResources { */ public static final String[] NO_AUTH_API = { "/login", - "/rest/device/webhook" + "/device/status", + "/device/problem" }; diff --git a/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl b/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl index fc39e840..fdcaef45 100644 --- a/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl +++ b/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl @@ -4,7 +4,7 @@ "params": [ { "name": "__offline_status__", <#--上下线 调用 webapp--> - "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"hostname\\":\\"{HOST.HOST}\\"}' http://127.0.0.1:9090/device/status", + "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"hostname\\":\\"{HOST.HOST}\\",\\"recovery\\":\\"{EVENT.RECOVERY.STATUS}\\"}' http://127.0.0.1:9090/device/status", "type": 0, "execute_on": 1 },{ diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java new file mode 100644 index 00000000..bc5231cc --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java @@ -0,0 +1,53 @@ +package com.zmops.iot.web.device.service.work; + + +import com.zmops.iot.async.callback.IWorker; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.util.ToolUtil; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author yefei + *

+ * 更新设备 在线状态 + */ +@Slf4j +@Component +public class DeviceOnlineWorker implements IWorker, Boolean> { + + @Override + public Boolean action(Map param, Map> allWrappers) { + log.debug("更新设备 在线状态…………"); + + String deviceId = param.get("hostname"); + if (ToolUtil.isEmpty(deviceId)) { + return false; + } + Device device = new QDevice().deviceId.eq(deviceId).findSingleAttribute(); + if (null == device) { + return false; + } + int status = 0; + String recovery = param.get("recovery"); + if (ToolUtil.isNotEmpty(recovery) && "RESOLVED".equals(recovery)) { + status = 1; + } + device.setOnline(status); + DB.update(device); + + return true; + } + + + @Override + public Boolean defaultValue() { + return true; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusFunctionDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusFunctionDto.java new file mode 100644 index 00000000..e3a2999f --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusFunctionDto.java @@ -0,0 +1,66 @@ +package com.zmops.iot.web.product.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +/** + * @author nantian created at 2021/8/5 16:06 + *

+ * 设备 离线/上线 规则 last(/Zabbix server/system.cpu.util[,user])>10 + */ + +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class ProductStatusFunctionDto { + + + private String relationId; + + private Long ruleId; + + private Long attrId; + + private Integer ruleStatus; + + private String ruleFunction; + + private String ruleCondition; + + @CachedValue(value = "UNITS") + private String unit; + + @CachedValue(value = "UNITS") + private String units; + + @CachedValue(value = "UNITS") + private String unitsRecovery; + + private String productAttrKey; + + private Long attrIdRecovery; + + private String ruleFunctionRecovery; + + private String ruleConditionRecovery; + + private String productAttrKeyRecovery; + + @CachedValue(value = "UNITS") + private String unitRecovery; + + private String attrName; + + private String zbxId; + + private String attrNameRecovery; + + @CachedValue(type = DicType.SysUserName) + private String createUser; + private String createTime; + @CachedValue(type = DicType.SysUserName) + private String updateUser; + private String updateTime; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java index c13ba00e..7dc91561 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java @@ -16,7 +16,7 @@ public class ProductStatusJudgeRule { - @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) + @NotBlank(groups = { BaseEntity.Create.class}) private String relationId; // deviceid @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Delete.class}) @@ -28,30 +28,35 @@ public class ProductStatusJudgeRule { //##################### 下线规则 - @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) + @NotNull(groups = { BaseEntity.Create.class}) private Long attrId; // 设备属性ID - @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) + @NotBlank(groups = { BaseEntity.Create.class}) private String ruleFunction; // nodata 或者 > < = 函数 - @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) + @NotBlank(groups = {BaseEntity.Create.class}) private String ruleCondition; // 时间 或者 特定值 - @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) + @NotNull(groups = { BaseEntity.Create.class}) + private String unit; //单位 s m h 或空 + + @NotBlank(groups = { BaseEntity.Create.class}) private String productAttrKey; // 属性 Key //##################### 上线规则 - @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) + @NotNull(groups = {BaseEntity.Create.class}) private Long attrIdRecovery; // 设备属性ID - @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) + @NotBlank(groups = { BaseEntity.Create.class}) private String ruleFunctionRecovery; // nodata 或者 > < = 函数 - @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) + @NotBlank(groups = {BaseEntity.Create.class}) private String ruleConditionRecovery; // 时间 或者 特定值 - @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) + @NotBlank(groups = { BaseEntity.Create.class}) private String productAttrKeyRecovery; // 属性 Key + + private String unitRecovery; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index 448c76f1..332816fc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -76,7 +76,7 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr * @param productAttr * @return */ - public List list(ProductAttrParam productAttr) { + public List list(ProductAttrParam productAttr) { QProductAttribute qProductAttribute = new QProductAttribute(); if (null != productAttr.getProdId()) { qProductAttribute.productId.eq(productAttr.getProdId()); @@ -87,7 +87,7 @@ public List list(ProductAttrParam productAttr) { if (ToolUtil.isNotEmpty(productAttr.getKey())) { qProductAttribute.key.contains(productAttr.getKey()); } - return qProductAttribute.orderBy(" create_time desc").findList(); + return qProductAttribute.orderBy(" create_time desc").asDto(ProductAttrDto.class).findList(); } /** @@ -200,7 +200,7 @@ public String createTrapperItem(ProductAttr productAttr) { } return zbxItem.createTrapperItem(itemName, productAttr.getKey(), - hostId, productAttr.getSource(),productAttr.getMasterItemId(),productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(), productAttr.getMasterItemId(), productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); } /** @@ -237,7 +237,7 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { zbxItem.updateTrapperItem(productAttribute.getZbxId(), productAttr.getAttrId() + "", productAttr.getKey(), - hostId, productAttr.getSource(),productAttr.getMasterItemId(),productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(), productAttr.getMasterItemId(), productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); DB.update(productAttribute); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java index 51fcf9a5..88b5fedc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java @@ -6,6 +6,7 @@ import com.zmops.iot.domain.product.ProductStatusFunctionRelation; import com.zmops.iot.domain.product.query.QProductStatusFunction; import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; +import com.zmops.iot.web.product.dto.ProductStatusFunctionDto; import com.zmops.iot.web.product.dto.ProductStatusJudgeRule; import com.zmops.zeus.driver.service.ZbxDeviceStatusTrigger; import io.ebean.DB; @@ -37,10 +38,11 @@ public class ProductTriggerService { * @param relationId 在线规则 * @return ResponseData */ - public ProductStatusFunction getRule(String relationId) { - ProductStatusFunctionRelation productStatusFunctionRelation = new QProductStatusFunctionRelation().relationId.eq(relationId).findOne(); - - return new QProductStatusFunction().ruleId.eq(productStatusFunctionRelation.getRuleId()).findOne(); + public ProductStatusFunctionDto getRule(String relationId) { + String sql = "select s.*,p.name attrName,p2.name attrNameRecovery,p.units,p2.units unitsRecovery " + + " from product_status_function s LEFT JOIN product_attribute p on p.attr_id = s.attr_id LEFT JOIN product_attribute p2 on p2.attr_id = s.attr_id_recovery \n" + + " where s.rule_id in (select rule_id from product_status_function_relation where relation_id = :relationId)"; + return DB.findDto(ProductStatusFunctionDto.class, sql).setParameter("relationId", relationId).findOne(); } @@ -59,8 +61,8 @@ public Long createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { // buildTriggerCreateMap(rule, judgeRule); String res = deviceStatusTrigger.createDeviceStatusTrigger(judgeRule.getRuleId() + "", judgeRule.getRelationId(), - judgeRule.getProductAttrKey(), judgeRule.getRuleCondition(), judgeRule.getRuleFunction(), judgeRule.getProductAttrKeyRecovery(), - judgeRule.getRuleConditionRecovery(), judgeRule.getRuleFunctionRecovery()); + judgeRule.getProductAttrKey(), judgeRule.getRuleCondition() + judgeRule.getUnit(), judgeRule.getRuleFunction(), judgeRule.getProductAttrKeyRecovery(), + judgeRule.getRuleConditionRecovery() + judgeRule.getUnitRecovery(), judgeRule.getRuleFunctionRecovery()); String triggerId = getTriggerId(res); @@ -89,8 +91,8 @@ public Long updateDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { // buildTriggerCreateMap(rule, judgeRule); deviceStatusTrigger.updateDeviceStatusTrigger(judgeRule.getTriggerId(), judgeRule.getRuleId() + "", judgeRule.getRelationId(), - judgeRule.getProductAttrKey(), judgeRule.getRuleCondition(), judgeRule.getRuleFunction(), judgeRule.getProductAttrKeyRecovery(), - judgeRule.getRuleConditionRecovery(), judgeRule.getRuleFunctionRecovery()); + judgeRule.getProductAttrKey(), judgeRule.getRuleCondition() + judgeRule.getUnit(), judgeRule.getRuleFunction(), judgeRule.getProductAttrKeyRecovery(), + judgeRule.getRuleConditionRecovery() + judgeRule.getUnitRecovery(), judgeRule.getRuleFunctionRecovery()); ProductStatusFunction productStatusFunction = new ProductStatusFunction(); BeanUtils.copyProperties(judgeRule, productStatusFunction); From 709b28dea332ee823e20c4310192c465271384d0 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 11 Sep 2021 21:29:58 +0800 Subject: [PATCH 153/763] [style]: change the data receiving format --- .../iot/server/core/camel/IOTDeviceValue.java | 8 ++--- .../process/ByteArrayToItemValueProcess.java | 14 +++++---- .../camel/process/JsonToItemValueProcess.java | 14 +++++---- .../camel/process/StringItemValueProcess.java | 19 ++++++------ .../server/core/worker/data/ItemValue.java | 29 ++++--------------- 5 files changed, 36 insertions(+), 48 deletions(-) diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/IOTDeviceValue.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/IOTDeviceValue.java index 21871498..6a94db86 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/IOTDeviceValue.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/IOTDeviceValue.java @@ -3,6 +3,8 @@ import lombok.Getter; import lombok.Setter; +import java.util.Map; + /** * @author nantian created at 2021/8/23 18:01 *

@@ -15,9 +17,7 @@ public class IOTDeviceValue { private String deviceId; // 设备ID - private String deviceAttrKey; // 设备属性Key - - private String deviceAttrValue; // 设备属性值 + private Map attributes; // key : value - private Long deviceTime; // 毫秒,70年到现在时间戳 + private Long clock; // 毫秒,70年到现在时间戳 } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java index c8a6621b..e5a6e6a8 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java @@ -1,6 +1,5 @@ package com.zmops.zeus.iot.server.core.camel.process; -import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import com.zmops.zeus.iot.server.core.camel.IOTDeviceValue; import com.zmops.zeus.iot.server.core.worker.data.ItemValue; @@ -28,13 +27,18 @@ public void process(Exchange exchange) throws Exception { String inputContext = new String(messageBytes, StandardCharsets.UTF_8); - List valueList = gson.fromJson(inputContext, new TypeToken>() {}.getType()); + IOTDeviceValue iotValue = gson.fromJson(inputContext, IOTDeviceValue.class); List itemValueList = new ArrayList<>(); - ItemValue item = new ItemValue(itemValueList); - valueList.forEach(item::addItemValue); + iotValue.getAttributes().forEach((key, value) -> { + ItemValue item = new ItemValue(iotValue.getDeviceId(), iotValue.getClock()); + item.setKey(key); + item.setValue(value); - exchange.getMessage().setBody(item.getValueList()); + itemValueList.add(item); + }); + + exchange.getMessage().setBody(itemValueList); } } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/JsonToItemValueProcess.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/JsonToItemValueProcess.java index 8c467eb9..9490903f 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/JsonToItemValueProcess.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/JsonToItemValueProcess.java @@ -1,6 +1,5 @@ package com.zmops.zeus.iot.server.core.camel.process; -import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import com.zmops.zeus.iot.server.core.camel.IOTDeviceValue; import com.zmops.zeus.iot.server.core.worker.data.ItemValue; @@ -30,14 +29,19 @@ public void process(Exchange exchange) throws Exception { String inputContext = this.analysisMessage(bodyStream); - List valueList = gson.fromJson(inputContext, new TypeToken>() {}.getType()); + IOTDeviceValue iotValue = gson.fromJson(inputContext, IOTDeviceValue.class); List itemValueList = new ArrayList<>(); - ItemValue item = new ItemValue(itemValueList); - valueList.forEach(item::addItemValue); + iotValue.getAttributes().forEach((key, value) -> { + ItemValue item = new ItemValue(iotValue.getDeviceId(), iotValue.getClock()); + item.setKey(key); + item.setValue(value); - exchange.getMessage().setBody(item.getValueList()); + itemValueList.add(item); + }); + + exchange.getMessage().setBody(itemValueList); } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/StringItemValueProcess.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/StringItemValueProcess.java index 7802affc..9753b2d2 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/StringItemValueProcess.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/StringItemValueProcess.java @@ -1,6 +1,5 @@ package com.zmops.zeus.iot.server.core.camel.process; -import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import com.zmops.zeus.iot.server.core.camel.IOTDeviceValue; import com.zmops.zeus.iot.server.core.worker.data.ItemValue; @@ -8,9 +7,6 @@ import org.apache.camel.Message; import org.apache.camel.Processor; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.List; @@ -27,15 +23,18 @@ public class StringItemValueProcess implements Processor { public void process(Exchange exchange) throws Exception { Message message = exchange.getIn(); - List valueList = gson.fromJson((String) message.getBody(), new TypeToken>() { - }.getType()); + IOTDeviceValue iotValue = gson.fromJson((String) message.getBody(), IOTDeviceValue.class); - // 多一步 命名转换,方便 Json 字段理解 List itemValueList = new ArrayList<>(); - ItemValue item = new ItemValue(itemValueList); - valueList.forEach(item::addItemValue); + iotValue.getAttributes().forEach((key, value) -> { + ItemValue item = new ItemValue(iotValue.getDeviceId(), iotValue.getClock()); + item.setKey(key); + item.setValue(value); - exchange.getMessage().setBody(item.getValueList()); + itemValueList.add(item); + }); + + exchange.getMessage().setBody(itemValueList); } } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ItemValue.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ItemValue.java index 482cddb4..1e767ea4 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ItemValue.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ItemValue.java @@ -24,37 +24,18 @@ public class ItemValue implements Item { // Zabbix 会根据配置的ITEM 类型,进行转换,如果失败就报错 private String value; - private Long clock; // 毫秒,如果为 Null,则 zabbix 以接收时间为准 + private Long clock; // 秒,如果为 Null,则 zabbix 以接收时间为准 private Long ns; // 纳秒,如果为 Null,则 zabbix 以接收时间为准 - public ItemValue(List itemValueList) { - this.valueList = itemValueList; - } - - public ItemValue() { - super(); - } - - private List valueList; - - public void addItemValue(IOTDeviceValue deviceValue) { - - ItemValue itemValue = new ItemValue(); - - itemValue.setHost(deviceValue.getDeviceId()); - itemValue.setKey(deviceValue.getDeviceAttrKey()); - itemValue.setValue(deviceValue.getDeviceAttrValue()); - - if (deviceValue.getDeviceTime() != null) { - itemValue.setClock(deviceValue.getDeviceTime()); + public ItemValue(String host, Long clock) { + this.host = host; + if (clock != null) { + this.clock = clock; } - - this.valueList.add(itemValue); } - /** * 设置 数据时间,单独设置 以设备推送的时间数据为准 * From 73558debedadb9a0f832179e3bc0fdb6b469c88a Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 11 Sep 2021 22:05:00 +0800 Subject: [PATCH 154/763] [style]: change code style --- .../zeus/iot/server/eventbus/thread/ThreadPoolFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/ThreadPoolFactory.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/ThreadPoolFactory.java index 9b646270..ffb49ffe 100644 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/ThreadPoolFactory.java +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/ThreadPoolFactory.java @@ -26,7 +26,7 @@ public class ThreadPoolFactory { private static final Logger LOG = LoggerFactory.getLogger(ThreadPoolFactory.class); - private final Map threadPoolExecutorMap = new ConcurrentHashMap(); + private final Map threadPoolExecutorMap = new ConcurrentHashMap<>(); private ThreadPoolExecutor threadPoolExecutor; private final ThreadCustomization threadCustomization; From 654dfe16f9fbc7979bee27f6d5ebe268a324d3d0 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 11 Sep 2021 22:18:53 +0800 Subject: [PATCH 155/763] [style]: change code style --- .../main/java/com/zmops/iot/web/product/dto/ProductAttr.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java index f916e4b4..9768e0f0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java @@ -97,9 +97,8 @@ public String getParams() { paramStr.append(param).append("\\\\n"); } return paramStr.substring(0, paramStr.length() - 3); - } else { - return ""; } + return ""; } } } From 9e2ddae2fbff4051919c8bf12922e544b1a16086 Mon Sep 17 00:00:00 2001 From: nantian Date: Sun, 12 Sep 2021 21:25:47 +0800 Subject: [PATCH 156/763] [feat]: update ebean version to 12.11.3 --- zeus-alarm/pom.xml | 2 +- zeus-common/pom.xml | 4 ++-- zeus-rest/pom.xml | 2 +- zeus-webapp-bom/pom.xml | 2 +- zeus-webapp/pom.xml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/zeus-alarm/pom.xml b/zeus-alarm/pom.xml index b19bd4af..cd2d207e 100644 --- a/zeus-alarm/pom.xml +++ b/zeus-alarm/pom.xml @@ -44,7 +44,7 @@ true - io.ebean.tile:enhancement:12.9.3 + io.ebean.tile:enhancement:12.11.3 diff --git a/zeus-common/pom.xml b/zeus-common/pom.xml index 2f944b35..f1b97d4d 100644 --- a/zeus-common/pom.xml +++ b/zeus-common/pom.xml @@ -31,7 +31,7 @@ io.ebean querybean-generator - 12.9.3 + 12.11.3 com.google.guava @@ -50,7 +50,7 @@ true - io.ebean.tile:enhancement:12.9.3 + io.ebean.tile:enhancement:12.11.3 diff --git a/zeus-rest/pom.xml b/zeus-rest/pom.xml index 89de706d..9912ce6f 100644 --- a/zeus-rest/pom.xml +++ b/zeus-rest/pom.xml @@ -42,7 +42,7 @@ true - io.ebean.tile:enhancement:12.9.3 + io.ebean.tile:enhancement:12.11.3 diff --git a/zeus-webapp-bom/pom.xml b/zeus-webapp-bom/pom.xml index 74695c97..aff5cb10 100644 --- a/zeus-webapp-bom/pom.xml +++ b/zeus-webapp-bom/pom.xml @@ -147,7 +147,7 @@ io.ebean ebean - 12.9.3 + 12.11.3 diff --git a/zeus-webapp/pom.xml b/zeus-webapp/pom.xml index 54d03b26..56c10298 100644 --- a/zeus-webapp/pom.xml +++ b/zeus-webapp/pom.xml @@ -63,7 +63,7 @@ true - io.ebean.tile:enhancement:12.9.3 + io.ebean.tile:enhancement:12.11.3 From bebc3203de05a026ba3e6a0a055ade130f949eef Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 13 Sep 2021 11:00:53 +0800 Subject: [PATCH 157/763] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E5=9C=A8=E7=BA=BF?= =?UTF-8?q?=E5=88=86=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ineReprot.java => DeviceOnlineReport.java} | 14 +++++++---- .../analyse/controller/HomeController.java | 4 +-- .../iot/web/analyse/service/HomeService.java | 25 +++++++++++++++---- .../schedule/DeviceOnlineReprotSchedule.java | 24 +++++++++++++++--- 4 files changed, 51 insertions(+), 16 deletions(-) rename zeus-common/src/main/java/com/zmops/iot/domain/device/{DeviceOnlineReprot.java => DeviceOnlineReport.java} (64%) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReprot.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReport.java similarity index 64% rename from zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReprot.java rename to zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReport.java index 62710186..3b3fb1a8 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReprot.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReport.java @@ -1,7 +1,6 @@ package com.zmops.iot.domain.device; -import lombok.Data; -import lombok.EqualsAndHashCode; +import lombok.*; import javax.persistence.Entity; import javax.persistence.Id; @@ -14,15 +13,20 @@ @Data @Table(name = "device_online_report") @Entity -public class DeviceOnlineReprot { +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DeviceOnlineReport { @Id private Long id; private String createTime; - private Integer online; + private Long online; - private Integer offline; + private Long offline; + + private String type; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java index b8e7a70d..5b6f3511 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java @@ -30,8 +30,8 @@ public class HomeController { * 设备数量统计 */ @RequestMapping("/deviceNum") - public ResponseData getDeviceNum() { - return ResponseData.success(homeService.getDeviceNum()); + public ResponseData getDeviceNum(@RequestParam("timeFrom") long timeFrom, @RequestParam("timeTill") long timeTill) { + return ResponseData.success(homeService.getDeviceNum(timeFrom, timeTill)); } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index 5f5aa241..e54069ea 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -3,7 +3,9 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.DeviceOnlineReport; import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.device.query.QDeviceOnlineReprot; import com.zmops.iot.domain.product.query.QProduct; import com.zmops.iot.enums.ValueType; import com.zmops.iot.util.LocalDateTimeUtils; @@ -141,8 +143,8 @@ private static String formatName(String name) { * * @return */ - public Map getDeviceNum() { - Map deviceNumMap = new HashMap<>(4); + public Map getDeviceNum(long timeFrom, long timeTill) { + Map deviceNumMap = new HashMap<>(4); deviceNumMap.put("online", 0); @@ -151,6 +153,19 @@ public Map getDeviceNum() { deviceNumMap.put("disable", (int) list.parallelStream().filter(o -> "DISABLE".equals(o.getStatus())).count()); deviceNumMap.put("product", new QProduct().findCount()); + List onLineList = new QDeviceOnlineReprot().createTime.ge(LocalDateTimeUtils.convertTimeToString(timeFrom, "yyyy-MM-dd")).createTime.lt(LocalDateTimeUtils.convertTimeToString(timeTill, "yyyy-MM-dd")).findList(); + + Map collect = onLineList.parallelStream().collect(Collectors.groupingBy(DeviceOnlineReport::getCreateTime, Collectors.summingLong(DeviceOnlineReport::getOnline))); + + List> trendsList = new ArrayList<>(); + + collect.forEach((key, value) -> { + Map map = new ConcurrentHashMap<>(2); + map.put("date", key); + map.put("val", value); + trendsList.add(map); + }); + deviceNumMap.put("trends", trendsList); return deviceNumMap; } @@ -166,7 +181,7 @@ public Map getAlarmNum(long timeFrom, long timeTill) { AlarmParam alarmParam = new AlarmParam(); alarmParam.setRecent("false"); List alarmList = alarmService.getAlarmList(alarmParam); - Map alarmMap = new HashMap<>(3); + Map alarmMap = new ConcurrentHashMap<>(3); if (ToolUtil.isNotEmpty(alarmList)) { @@ -185,10 +200,10 @@ public Map getAlarmNum(long timeFrom, long timeTill) { ); List> trendsList = new ArrayList<>(); tmpMap.forEach((key, value) -> { - Map trendsMap = new HashMap<>(2); + Map trendsMap = new ConcurrentHashMap<>(2); List list = new ArrayList<>(); value.forEach((date, val) -> { - Map valMap = new HashMap<>(2); + Map valMap = new ConcurrentHashMap<>(2); valMap.put("date", date); valMap.put("val", val); list.add(valMap); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java index 1c030d99..39972fda 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java @@ -1,10 +1,21 @@ package com.zmops.iot.web.device.schedule; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.DeviceOnlineReport; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.util.LocalDateTimeUtils; +import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + /** * @author yefei **/ @@ -14,13 +25,18 @@ public class DeviceOnlineReprotSchedule { @Scheduled(cron = "0 59 23 1/1 * ? ") - public void report(){ + public void report() { log.info("开始查询设备在线情况"); - //TODO 统计出 当前 设备在线情况 - + //统计出 当前 设备在线情况 + List deviceList = new QDevice().findList(); + Map> onLinemap = deviceList.parallelStream().collect(Collectors.groupingBy(Device::getType, Collectors.groupingBy(Device::getOnline, Collectors.counting()))); + List list = new ArrayList<>(); + onLinemap.forEach((key, value) -> { + list.add(DeviceOnlineReport.builder().type(key).createTime(LocalDateTimeUtils.formatTimeDate(LocalDateTime.now())).online(value.get(1)).offline(value.get(0)).build()); + }); //插入 在线情况表 - + DB.saveAll(list); } } From 6981907bd03f635f898bf15388df2802d2b5cd23 Mon Sep 17 00:00:00 2001 From: nantian Date: Sun, 12 Sep 2021 21:25:47 +0800 Subject: [PATCH 158/763] [feat]: update ebean version to 12.11.3 --- zeus-alarm/pom.xml | 2 +- zeus-common/pom.xml | 4 ++-- zeus-rest/pom.xml | 2 +- zeus-webapp-bom/pom.xml | 2 +- zeus-webapp/pom.xml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/zeus-alarm/pom.xml b/zeus-alarm/pom.xml index b19bd4af..cd2d207e 100644 --- a/zeus-alarm/pom.xml +++ b/zeus-alarm/pom.xml @@ -44,7 +44,7 @@ true - io.ebean.tile:enhancement:12.9.3 + io.ebean.tile:enhancement:12.11.3 diff --git a/zeus-common/pom.xml b/zeus-common/pom.xml index 2f944b35..f1b97d4d 100644 --- a/zeus-common/pom.xml +++ b/zeus-common/pom.xml @@ -31,7 +31,7 @@ io.ebean querybean-generator - 12.9.3 + 12.11.3 com.google.guava @@ -50,7 +50,7 @@ true - io.ebean.tile:enhancement:12.9.3 + io.ebean.tile:enhancement:12.11.3 diff --git a/zeus-rest/pom.xml b/zeus-rest/pom.xml index 89de706d..9912ce6f 100644 --- a/zeus-rest/pom.xml +++ b/zeus-rest/pom.xml @@ -42,7 +42,7 @@ true - io.ebean.tile:enhancement:12.9.3 + io.ebean.tile:enhancement:12.11.3 diff --git a/zeus-webapp-bom/pom.xml b/zeus-webapp-bom/pom.xml index 74695c97..aff5cb10 100644 --- a/zeus-webapp-bom/pom.xml +++ b/zeus-webapp-bom/pom.xml @@ -147,7 +147,7 @@ io.ebean ebean - 12.9.3 + 12.11.3 diff --git a/zeus-webapp/pom.xml b/zeus-webapp/pom.xml index 54d03b26..56c10298 100644 --- a/zeus-webapp/pom.xml +++ b/zeus-webapp/pom.xml @@ -63,7 +63,7 @@ true - io.ebean.tile:enhancement:12.9.3 + io.ebean.tile:enhancement:12.11.3 From 2275ad7761f37a49af7b470b3fa2a9864e1234f0 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 13 Sep 2021 11:00:53 +0800 Subject: [PATCH 159/763] [feat]: equipment online analysis --- ...ineReprot.java => DeviceOnlineReport.java} | 14 +++++++---- .../analyse/controller/HomeController.java | 4 +-- .../iot/web/analyse/service/HomeService.java | 25 +++++++++++++++---- .../schedule/DeviceOnlineReprotSchedule.java | 24 +++++++++++++++--- 4 files changed, 51 insertions(+), 16 deletions(-) rename zeus-common/src/main/java/com/zmops/iot/domain/device/{DeviceOnlineReprot.java => DeviceOnlineReport.java} (64%) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReprot.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReport.java similarity index 64% rename from zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReprot.java rename to zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReport.java index 62710186..3b3fb1a8 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReprot.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReport.java @@ -1,7 +1,6 @@ package com.zmops.iot.domain.device; -import lombok.Data; -import lombok.EqualsAndHashCode; +import lombok.*; import javax.persistence.Entity; import javax.persistence.Id; @@ -14,15 +13,20 @@ @Data @Table(name = "device_online_report") @Entity -public class DeviceOnlineReprot { +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DeviceOnlineReport { @Id private Long id; private String createTime; - private Integer online; + private Long online; - private Integer offline; + private Long offline; + + private String type; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java index b8e7a70d..5b6f3511 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java @@ -30,8 +30,8 @@ public class HomeController { * 设备数量统计 */ @RequestMapping("/deviceNum") - public ResponseData getDeviceNum() { - return ResponseData.success(homeService.getDeviceNum()); + public ResponseData getDeviceNum(@RequestParam("timeFrom") long timeFrom, @RequestParam("timeTill") long timeTill) { + return ResponseData.success(homeService.getDeviceNum(timeFrom, timeTill)); } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index 5f5aa241..e54069ea 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -3,7 +3,9 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.DeviceOnlineReport; import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.device.query.QDeviceOnlineReprot; import com.zmops.iot.domain.product.query.QProduct; import com.zmops.iot.enums.ValueType; import com.zmops.iot.util.LocalDateTimeUtils; @@ -141,8 +143,8 @@ private static String formatName(String name) { * * @return */ - public Map getDeviceNum() { - Map deviceNumMap = new HashMap<>(4); + public Map getDeviceNum(long timeFrom, long timeTill) { + Map deviceNumMap = new HashMap<>(4); deviceNumMap.put("online", 0); @@ -151,6 +153,19 @@ public Map getDeviceNum() { deviceNumMap.put("disable", (int) list.parallelStream().filter(o -> "DISABLE".equals(o.getStatus())).count()); deviceNumMap.put("product", new QProduct().findCount()); + List onLineList = new QDeviceOnlineReprot().createTime.ge(LocalDateTimeUtils.convertTimeToString(timeFrom, "yyyy-MM-dd")).createTime.lt(LocalDateTimeUtils.convertTimeToString(timeTill, "yyyy-MM-dd")).findList(); + + Map collect = onLineList.parallelStream().collect(Collectors.groupingBy(DeviceOnlineReport::getCreateTime, Collectors.summingLong(DeviceOnlineReport::getOnline))); + + List> trendsList = new ArrayList<>(); + + collect.forEach((key, value) -> { + Map map = new ConcurrentHashMap<>(2); + map.put("date", key); + map.put("val", value); + trendsList.add(map); + }); + deviceNumMap.put("trends", trendsList); return deviceNumMap; } @@ -166,7 +181,7 @@ public Map getAlarmNum(long timeFrom, long timeTill) { AlarmParam alarmParam = new AlarmParam(); alarmParam.setRecent("false"); List alarmList = alarmService.getAlarmList(alarmParam); - Map alarmMap = new HashMap<>(3); + Map alarmMap = new ConcurrentHashMap<>(3); if (ToolUtil.isNotEmpty(alarmList)) { @@ -185,10 +200,10 @@ public Map getAlarmNum(long timeFrom, long timeTill) { ); List> trendsList = new ArrayList<>(); tmpMap.forEach((key, value) -> { - Map trendsMap = new HashMap<>(2); + Map trendsMap = new ConcurrentHashMap<>(2); List list = new ArrayList<>(); value.forEach((date, val) -> { - Map valMap = new HashMap<>(2); + Map valMap = new ConcurrentHashMap<>(2); valMap.put("date", date); valMap.put("val", val); list.add(valMap); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java index 1c030d99..39972fda 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java @@ -1,10 +1,21 @@ package com.zmops.iot.web.device.schedule; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.DeviceOnlineReport; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.util.LocalDateTimeUtils; +import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + /** * @author yefei **/ @@ -14,13 +25,18 @@ public class DeviceOnlineReprotSchedule { @Scheduled(cron = "0 59 23 1/1 * ? ") - public void report(){ + public void report() { log.info("开始查询设备在线情况"); - //TODO 统计出 当前 设备在线情况 - + //统计出 当前 设备在线情况 + List deviceList = new QDevice().findList(); + Map> onLinemap = deviceList.parallelStream().collect(Collectors.groupingBy(Device::getType, Collectors.groupingBy(Device::getOnline, Collectors.counting()))); + List list = new ArrayList<>(); + onLinemap.forEach((key, value) -> { + list.add(DeviceOnlineReport.builder().type(key).createTime(LocalDateTimeUtils.formatTimeDate(LocalDateTime.now())).online(value.get(1)).offline(value.get(0)).build()); + }); //插入 在线情况表 - + DB.saveAll(list); } } From b82b352063960c6357a66a285b116a5f992a35ad Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 13 Sep 2021 12:00:06 +0800 Subject: [PATCH 160/763] [style]: change code style --- .../controller/ProductEventTriggerController.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index 96e1974b..23c5c825 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -1,16 +1,24 @@ package com.zmops.iot.web.product.controller; +import com.zmops.iot.model.response.ResponseData; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author nantian created at 2021/8/7 11:58 *

- * 配置告警规则 + * 配置告警规则 属性 事件 触发 方法回调 */ @RestController -@RequestMapping("/product/trigger/event") +@RequestMapping("/product/event/trigger") public class ProductEventTriggerController { - + + @RequestMapping("/create") + public ResponseData createEventTrigger() { + return ResponseData.success(); + } + + + } From 19f1d75a8e37ceb0ec3f7e26f663db194a26e70c Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 14 Sep 2021 11:44:01 +0800 Subject: [PATCH 161/763] [style]: change sql format --- .../iot/web/product/service/ProductTriggerService.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java index 88b5fedc..14e85025 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java @@ -40,9 +40,11 @@ public class ProductTriggerService { */ public ProductStatusFunctionDto getRule(String relationId) { String sql = "select s.*,p.name attrName,p2.name attrNameRecovery,p.units,p2.units unitsRecovery " + - " from product_status_function s LEFT JOIN product_attribute p on p.attr_id = s.attr_id LEFT JOIN product_attribute p2 on p2.attr_id = s.attr_id_recovery \n" + + " from product_status_function s" + + " LEFT JOIN product_attribute p on p.attr_id = s.attr_id" + + " LEFT JOIN product_attribute p2 on p2.attr_id = s.attr_id_recovery" + " where s.rule_id in (select rule_id from product_status_function_relation where relation_id = :relationId)"; - return DB.findDto(ProductStatusFunctionDto.class, sql).setParameter("relationId", relationId).findOne(); + return DB.findDto(ProductStatusFunctionDto.class, sql).setParameter("relationId", relationId).findOne(); } From b7c02a61756041847944b2ca527bc4918ba2e23b Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 14 Sep 2021 11:54:18 +0800 Subject: [PATCH 162/763] [feat]: global view device online trends --- .../zmops/iot/web/analyse/controller/HomeController.java | 2 +- .../com/zmops/iot/web/analyse/service/HomeService.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java index 5b6f3511..a0ec9dfb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java @@ -50,7 +50,7 @@ public ResponseData getAlarmNum(@RequestParam("timeFrom") long timeFrom, @Reques */ @RequestMapping("/collectonRate") public ResponseData collectonRate(@RequestParam("timeFrom") long timeFrom, @RequestParam("timeTill") long timeTill) { - return ResponseData.success(homeService.collectonRate(timeFrom, timeTill)); + return ResponseData.success(homeService.collectionRate(timeFrom, timeTill)); } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index e54069ea..1ae0bd3e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -5,7 +5,7 @@ import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.DeviceOnlineReport; import com.zmops.iot.domain.device.query.QDevice; -import com.zmops.iot.domain.device.query.QDeviceOnlineReprot; +import com.zmops.iot.domain.device.query.QDeviceOnlineReport; import com.zmops.iot.domain.product.query.QProduct; import com.zmops.iot.enums.ValueType; import com.zmops.iot.util.LocalDateTimeUtils; @@ -57,7 +57,7 @@ public class HomeService { * * @return */ - public List> collectonRate(long timeFrom, long timeTill) { + public List> collectionRate(long timeFrom, long timeTill) { if (ToolUtil.isEmpty(hostId)) { if (ToolUtil.isEmpty(getZbxServerId())) { return Collections.emptyList(); @@ -80,7 +80,7 @@ public List> collectonRate(long timeFrom, long timeTill) { Map> collect = latestDtos.parallelStream().collect( Collectors.groupingBy(LatestDto::getName, Collectors.groupingBy(LatestDto::getClock, Collectors.averagingDouble(o -> Double.parseDouble(o.getValue())))) ); - List> collectList = new ArrayList(); + List> collectList = new ArrayList<>(); collect.forEach((key, value) -> { Map collectMap = new HashMap<>(2); List> tmpList = new ArrayList<>(); @@ -153,7 +153,7 @@ public Map getDeviceNum(long timeFrom, long timeTill) { deviceNumMap.put("disable", (int) list.parallelStream().filter(o -> "DISABLE".equals(o.getStatus())).count()); deviceNumMap.put("product", new QProduct().findCount()); - List onLineList = new QDeviceOnlineReprot().createTime.ge(LocalDateTimeUtils.convertTimeToString(timeFrom, "yyyy-MM-dd")).createTime.lt(LocalDateTimeUtils.convertTimeToString(timeTill, "yyyy-MM-dd")).findList(); + List onLineList = new QDeviceOnlineReport().createTime.ge(LocalDateTimeUtils.convertTimeToString(timeFrom, "yyyy-MM-dd")).createTime.lt(LocalDateTimeUtils.convertTimeToString(timeTill, "yyyy-MM-dd")).findList(); Map collect = onLineList.parallelStream().collect(Collectors.groupingBy(DeviceOnlineReport::getCreateTime, Collectors.summingLong(DeviceOnlineReport::getOnline))); From 63b4c15e39204b3e7aaeb4c1c5aa96f8381b6ba7 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 14 Sep 2021 19:10:00 +0800 Subject: [PATCH 163/763] [feat]: Uniform interface name --- .../src/main/resources/api-json/item/item.trapper.create.ftl | 2 ++ .../src/main/resources/api-json/item/item.trapper.update.ftl | 4 +++- .../com/zmops/iot/web/device/controller/DeviceController.java | 2 +- .../zmops/iot/web/product/controller/ProductController.java | 4 ++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl b/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl index 9f425a82..537a8b2b 100644 --- a/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl +++ b/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl @@ -13,9 +13,11 @@ <#if valuemapid?? && valuemapid != ''> "valuemapid":${valuemapid}, + <#if valueType == '0' || valueType == '3'> <#if units??> "units": "${units}", + "preprocessing": [ <#if processList??> <#list processList as process> diff --git a/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl b/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl index 9a516543..8d786913 100644 --- a/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl +++ b/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl @@ -15,7 +15,9 @@ "valuemapid":${valuemapid}, <#if valueType == '0' || valueType == '3'> - "units": "${units}", + <#if units??> + "units": "${units}", + "preprocessing": [ <#if processList??> diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java index 3d4fe499..fe81b6af 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java @@ -151,7 +151,7 @@ public ResponseData deviceTagCreate(@RequestBody @Valid ProductTag productTag) { * @param valueMap * @return */ - @PostMapping("/valuemap/update") + @PostMapping("/valueMap/update") public ResponseData prodValueMapCreate(@RequestBody @Validated(BaseEntity.Create.class) ValueMap valueMap) { Device device = new QDevice().deviceId.eq(valueMap.getProductId()).findOne(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java index 69d3096d..92bf631c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java @@ -69,7 +69,7 @@ public ResponseData prodDetail(@RequestParam("productId") Long prodId) { /** * 产品标签列表 */ - @GetMapping("/prodTag/list") + @GetMapping("/tag/list") public ResponseData prodTagList(@RequestParam("productId") String prodId) { return ResponseData.success(productService.prodTagList(prodId)); } @@ -228,7 +228,7 @@ public ResponseData prodValueMapCreate(@RequestBody @Validated(BaseEntity.Create * @param valueMap * @return */ - @PostMapping("/valuemap/delete") + @PostMapping("/valueMap/delete") public ResponseData prodValueMapDelete(@RequestBody @Validated(BaseEntity.Delete.class) ValueMap valueMap) { String response = productService.valueMapDelete(valueMap.getValuemapid()); String valuemapid = JSON.parseObject(response, TemplateIds.class).getValuemapids()[0]; From 2ceb1343070a5f98e9901b6e01f51ecb6c66d1f6 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 14 Sep 2021 21:44:52 +0800 Subject: [PATCH 164/763] [fix]: fix product service relation --- .../iot/domain/product/ProductService.java | 1 - .../product/ProductServiceRelation.java | 23 ++++++++++ .../web/product/dto/ProductServiceDto.java | 2 +- .../product/service/ProductSvcService.java | 43 +++++++++++-------- .../service/work/SaveProdSvcWorker.java | 27 ++++-------- 5 files changed, 57 insertions(+), 39 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceRelation.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java index 146ca728..9b0d057b 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java @@ -21,7 +21,6 @@ public class ProductService { private String name; private String mark; private String remark; - private String sid; private Long templateId; private String async; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceRelation.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceRelation.java new file mode 100644 index 00000000..4b964423 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceRelation.java @@ -0,0 +1,23 @@ +package com.zmops.iot.domain.product; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Entity; +import javax.persistence.Table; + +/** + * @author nantian created at 2021/8/11 17:02 + */ + +@Getter +@Setter +@Entity +@Table(name = "product_service_relation") +public class ProductServiceRelation { + + private Long serviceId; + + private String relationId; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java index dec6f825..dda6e94a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java @@ -29,7 +29,7 @@ public class ProductServiceDto { private String remark; @NotNull(groups = BaseEntity.Create.class) - private String sid; + private String relationId; @CachedValue(value = "EXECUTE_TYPE") private String async; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index dc2e7a43..8254ee69 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -6,6 +6,7 @@ import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.product.query.QProductService; import com.zmops.iot.domain.product.query.QProductServiceParam; +import com.zmops.iot.domain.product.query.QProductServiceRelation; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; @@ -52,7 +53,10 @@ public Pager getServiceByPage(ProductSvcParam productSvcParam qProductService.mark.contains(productSvcParam.getMark()); } if (ToolUtil.isNotEmpty(productSvcParam.getProdId())) { - qProductService.sid.eq(productSvcParam.getProdId()); + List serviceIds = getServiceIdList(productSvcParam.getProdId()); + if (ToolUtil.isNotEmpty(serviceIds)) { + qProductService.id.in(serviceIds); + } } qProductService.orderBy(" id desc"); List productServiceDtoList = qProductService.setFirstRow((productSvcParam.getPage() - 1) * productSvcParam.getMaxRow()) @@ -99,9 +103,12 @@ public List list(ProductSvcParam productSvcParam) { */ @Transactional(rollbackFor = Exception.class) public ProductServiceDto create(ProductServiceDto productServiceDto) { - int count = new QProductService().name.eq(productServiceDto.getName()).sid.eq(productServiceDto.getSid()).findCount(); - if (count > 0) { - throw new ServiceException(BizExceptionEnum.SERVICE_EXISTS); + List serviceIds = getServiceIdList(productServiceDto.getRelationId()); + if (ToolUtil.isNotEmpty(serviceIds)) { + int count = new QProductService().name.eq(productServiceDto.getName()).id.in(serviceIds).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.SERVICE_EXISTS); + } } ProductService productService = new ProductService(); ToolUtil.copyProperties(productServiceDto, productService); @@ -135,10 +142,13 @@ public ProductServiceDto create(ProductServiceDto productServiceDto) { * @return */ public ProductServiceDto update(ProductServiceDto productServiceDto) { - int count = new QProductService().name.eq(productServiceDto.getName()).sid.eq(productServiceDto.getSid()) - .id.ne(productServiceDto.getId()).findCount(); - if (count > 0) { - throw new ServiceException(BizExceptionEnum.SERVICE_EXISTS); + List serviceIds = getServiceIdList(productServiceDto.getRelationId()); + if (ToolUtil.isNotEmpty(serviceIds)) { + int count = new QProductService().name.eq(productServiceDto.getName()).id.in(serviceIds) + .id.ne(productServiceDto.getId()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.SERVICE_EXISTS); + } } ProductService productService = new ProductService(); ToolUtil.copyProperties(productServiceDto, productService); @@ -152,18 +162,14 @@ public ProductServiceDto update(ProductServiceDto productServiceDto) { DB.saveAll(productServiceDto.getProductServiceParamList()); } - //同步到设备 - WorkerWrapper updateProdSvcWork = WorkerWrapper.builder().worker(updateProdSvcWorker).build(); - - try { - Async.work(100, updateProdSvcWork).awaitFinish(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return productServiceDto; } + private List getServiceIdList(String relationId) { + return new QProductServiceRelation().select(QProductServiceRelation.Alias.serviceId).relationId.eq(relationId) + .findSingleAttributeList(); + } + /** * 服务删除 * @@ -173,8 +179,7 @@ public ProductServiceDto update(ProductServiceDto productServiceDto) { public void delete(List ids) { new QProductServiceParam().serviceId.in(ids).delete(); + new QProductServiceRelation().serviceId.in(ids).delete(); new QProductService().id.in(ids).delete(); - - //TODO 同步到设备 } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java index 8cbf2138..111e8ef1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java @@ -4,9 +4,7 @@ import com.zmops.iot.async.callback.IWorker; import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.query.QDevice; -import com.zmops.iot.domain.product.ProductService; -import com.zmops.iot.domain.product.ProductServiceParam; -import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.domain.product.ProductServiceRelation; import com.zmops.iot.web.product.dto.ProductServiceDto; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; @@ -30,24 +28,17 @@ public class SaveProdSvcWorker implements IWorker { public Boolean action(ProductServiceDto productServiceDto, Map> map) { log.debug("处理产品 新增服务 同步到设备工作…………"); - String prodId = productServiceDto.getSid(); - - List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); + String prodId = productServiceDto.getRelationId(); + List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); + List productServiceRelationList = new ArrayList<>(); for (String deviceId : deviceIds) { - ProductService productService = new ProductService(); - ToolUtil.copyProperties(productServiceDto, productService); - productService.setSid(deviceId); - productService.setTemplateId(productServiceDto.getId()); - DB.save(productService); - - if (ToolUtil.isNotEmpty(productServiceDto.getProductServiceParamList())) { - for (ProductServiceParam productServiceParam : productServiceDto.getProductServiceParamList()) { - productServiceParam.setServiceId(productService.getId()); - } - DB.saveAll(productServiceDto.getProductServiceParamList()); - } + ProductServiceRelation productServiceRelation = new ProductServiceRelation(); + productServiceRelation.setRelationId(deviceId); + productServiceRelation.setServiceId(productServiceDto.getId()); + productServiceRelationList.add(productServiceRelation); } + DB.saveAll(productServiceRelationList); return true; } From 3bf21035a80881de21e3b080dc5c28622da95d22 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 15 Sep 2021 11:23:00 +0800 Subject: [PATCH 165/763] [fix]: fix device online report --- .../java/com/zmops/iot/domain/device/DeviceOnlineReport.java | 2 +- .../com/zmops/iot/domain/product/ProductServiceRelation.java | 5 +++++ .../iot/domain/product/ProductStatusFunctionRelation.java | 3 +++ .../com/zmops/iot/web/analyse/controller/HomeController.java | 2 +- .../java/com/zmops/iot/web/analyse/service/HomeService.java | 2 +- .../iot/web/device/schedule/DeviceOnlineReprotSchedule.java | 4 +++- 6 files changed, 14 insertions(+), 4 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReport.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReport.java index 3b3fb1a8..f8dcf510 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReport.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReport.java @@ -27,6 +27,6 @@ public class DeviceOnlineReport { private Long offline; - private String type; + private Integer type; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceRelation.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceRelation.java index 4b964423..a7f0d963 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceRelation.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceRelation.java @@ -1,9 +1,11 @@ package com.zmops.iot.domain.product; +import afu.org.checkerframework.checker.igj.qual.I; import lombok.Getter; import lombok.Setter; import javax.persistence.Entity; +import javax.persistence.Id; import javax.persistence.Table; /** @@ -16,6 +18,9 @@ @Table(name = "product_service_relation") public class ProductServiceRelation { + @Id + private Long id; + private Long serviceId; private String relationId; diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java index 632dacfb..133c1b29 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java @@ -18,6 +18,9 @@ @Table(name = "product_status_function_relation") public class ProductStatusFunctionRelation { + @Id + private Long id; + private Long ruleId; private String relationId; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java index a0ec9dfb..6011c1c2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java @@ -30,7 +30,7 @@ public class HomeController { * 设备数量统计 */ @RequestMapping("/deviceNum") - public ResponseData getDeviceNum(@RequestParam("timeFrom") long timeFrom, @RequestParam("timeTill") long timeTill) { + public ResponseData getDeviceNum(@RequestParam("timeFrom") Integer timeFrom, @RequestParam("timeTill") Integer timeTill) { return ResponseData.success(homeService.getDeviceNum(timeFrom, timeTill)); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index 1ae0bd3e..d2945170 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -143,7 +143,7 @@ private static String formatName(String name) { * * @return */ - public Map getDeviceNum(long timeFrom, long timeTill) { + public Map getDeviceNum(Integer timeFrom, Integer timeTill) { Map deviceNumMap = new HashMap<>(4); deviceNumMap.put("online", 0); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java index 39972fda..e019d473 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java @@ -14,6 +14,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; /** @@ -33,7 +34,8 @@ public void report() { Map> onLinemap = deviceList.parallelStream().collect(Collectors.groupingBy(Device::getType, Collectors.groupingBy(Device::getOnline, Collectors.counting()))); List list = new ArrayList<>(); onLinemap.forEach((key, value) -> { - list.add(DeviceOnlineReport.builder().type(key).createTime(LocalDateTimeUtils.formatTimeDate(LocalDateTime.now())).online(value.get(1)).offline(value.get(0)).build()); + list.add(DeviceOnlineReport.builder().type(Integer.parseInt(key)).createTime(LocalDateTimeUtils.formatTimeDate(LocalDateTime.now())) + .online(Optional.ofNullable(value.get(1)).orElse(0L)).offline(Optional.ofNullable(value.get(0)).orElse(0L)).build()); }); //插入 在线情况表 DB.saveAll(list); From 645b0695c2b8d97e5d8809059108961f5a60afa3 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 15 Sep 2021 11:38:45 +0800 Subject: [PATCH 166/763] [style]: remove callsuper = false --- .../java/com/zmops/iot/domain/device/DeviceOnlineReport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReport.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReport.java index 3b3fb1a8..4b7bdf83 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReport.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReport.java @@ -9,7 +9,7 @@ /** * @author yefei **/ -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode @Data @Table(name = "device_online_report") @Entity From 500deb453a784611df934457cee85bd1670e08e2 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 15 Sep 2021 11:40:15 +0800 Subject: [PATCH 167/763] [style]: change code style --- .../schedule/DeviceOnlineReprotSchedule.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java index e019d473..6922e024 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java @@ -30,12 +30,18 @@ public void report() { log.info("开始查询设备在线情况"); //统计出 当前 设备在线情况 - List deviceList = new QDevice().findList(); - Map> onLinemap = deviceList.parallelStream().collect(Collectors.groupingBy(Device::getType, Collectors.groupingBy(Device::getOnline, Collectors.counting()))); - List list = new ArrayList<>(); + List deviceList = new QDevice().findList(); + + Map> onLinemap = deviceList.parallelStream() + .collect(Collectors.groupingBy(Device::getType, Collectors.groupingBy(Device::getOnline, Collectors.counting()))); + + List list = new ArrayList<>(); + onLinemap.forEach((key, value) -> { - list.add(DeviceOnlineReport.builder().type(Integer.parseInt(key)).createTime(LocalDateTimeUtils.formatTimeDate(LocalDateTime.now())) - .online(Optional.ofNullable(value.get(1)).orElse(0L)).offline(Optional.ofNullable(value.get(0)).orElse(0L)).build()); + list.add(DeviceOnlineReport.builder().type(Integer.parseInt(key)) + .createTime(LocalDateTimeUtils.formatTimeDate(LocalDateTime.now())) + .online(Optional.ofNullable(value.get(1)).orElse(0L)) + .offline(Optional.ofNullable(value.get(0)).orElse(0L)).build()); }); //插入 在线情况表 DB.saveAll(list); From c0777071ab930d1f333f9f0035e7ecd740a16b44 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 15 Sep 2021 16:25:13 +0800 Subject: [PATCH 168/763] [fix]: fix product service relation device --- .../iot/domain/product/ProductService.java | 1 - .../product/ProductServiceRelation.java | 3 +- .../device/service/work/SaveOtherWorker.java | 57 +++++++++++++++++++ .../web/product/dto/ProductServiceDto.java | 4 +- .../product/service/ProductSvcService.java | 31 ++++++++-- .../service/work/SaveProdSvcWorker.java | 1 + 6 files changed, 89 insertions(+), 8 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java index 9b0d057b..e5c62ae0 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java @@ -21,6 +21,5 @@ public class ProductService { private String name; private String mark; private String remark; - private Long templateId; private String async; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceRelation.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceRelation.java index a7f0d963..60261c2b 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceRelation.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceRelation.java @@ -1,6 +1,5 @@ package com.zmops.iot.domain.product; -import afu.org.checkerframework.checker.igj.qual.I; import lombok.Getter; import lombok.Setter; @@ -25,4 +24,6 @@ public class ProductServiceRelation { private String relationId; + private Integer inherit; + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java new file mode 100644 index 00000000..02ce7aff --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java @@ -0,0 +1,57 @@ +package com.zmops.iot.web.device.service.work; + + +import com.zmops.iot.async.callback.IWorker; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.product.query.QProductServiceRelation; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.DeviceDto; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author yefei + *

+ * 设备标签处理步骤 + */ +@Slf4j +@Component +public class SaveOtherWorker implements IWorker { + + @Override + public Boolean action(DeviceDto deviceDto, Map> allWrappers) { + log.debug("处理 其它 工作…………"); + + String deviceId = deviceDto.getDeviceId(); + + if (ToolUtil.isNotEmpty(deviceDto.getEdit()) && "true".equals(deviceDto.getEdit())) { + //修改 + + //没有修改关联的产品 不做处理 + if (deviceDto.getProductId().equals(deviceDto.getOldProductId())) { + return true; + } + //删除服务关联 + new QProductServiceRelation().relationId.eq(deviceId).delete(); + } else { + //创建 + Device device = (Device) allWrappers.get("saveDvice").getWorkResult().getResult(); + deviceId = device.getDeviceId(); + } + + //服务关联 + DB.sqlUpdate("insert into product_service_relation (relation_id,service_id,inherit) SELECT :deviceId,service_id,1 from product_service_relation where relation_id=:relationId") + .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId()).execute(); + + return true; + } + + @Override + public Boolean defaultValue() { + return true; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java index dda6e94a..9d986a40 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java @@ -34,11 +34,11 @@ public class ProductServiceDto { @CachedValue(value = "EXECUTE_TYPE") private String async; - private Long templateId; + @CachedValue(value = "WHETHER") + private String inherit; private List productServiceParamList; - @NotNull(groups = BaseEntity.Delete.class) private List ids; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index 8254ee69..89778038 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -4,6 +4,7 @@ import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductService; import com.zmops.iot.domain.product.ProductServiceParam; +import com.zmops.iot.domain.product.ProductServiceRelation; import com.zmops.iot.domain.product.query.QProductService; import com.zmops.iot.domain.product.query.QProductServiceParam; import com.zmops.iot.domain.product.query.QProductServiceRelation; @@ -16,6 +17,7 @@ import com.zmops.iot.web.product.service.work.SaveProdSvcWorker; import com.zmops.iot.web.product.service.work.UpdateProdSvcWorker; import io.ebean.DB; +import io.ebean.DtoQuery; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -45,22 +47,37 @@ public class ProductSvcService { * @return */ public Pager getServiceByPage(ProductSvcParam productSvcParam) { + StringBuilder sql = new StringBuilder("SELECT s.*,r.inherit from product_service s LEFT JOIN product_service_relation r on r.service_id=s.id where 1=1 "); QProductService qProductService = new QProductService(); if (ToolUtil.isNotEmpty(productSvcParam.getName())) { + sql.append(" and s.name like :name"); qProductService.name.contains(productSvcParam.getName()); } if (ToolUtil.isNotEmpty(productSvcParam.getMark())) { + sql.append(" and s.mark like :mark"); qProductService.mark.contains(productSvcParam.getMark()); } if (ToolUtil.isNotEmpty(productSvcParam.getProdId())) { + sql.append(" and r.relation_id = :relationId"); List serviceIds = getServiceIdList(productSvcParam.getProdId()); if (ToolUtil.isNotEmpty(serviceIds)) { qProductService.id.in(serviceIds); } } - qProductService.orderBy(" id desc"); - List productServiceDtoList = qProductService.setFirstRow((productSvcParam.getPage() - 1) * productSvcParam.getMaxRow()) - .setMaxRows(productSvcParam.getMaxRow()).asDto(ProductServiceDto.class).findList(); + sql.append(" order by id desc"); + DtoQuery query = DB.findDto(ProductServiceDto.class, sql.toString()); + if (ToolUtil.isNotEmpty(productSvcParam.getName())) { + query.setParameter("name", "%" + productSvcParam.getName() + "%"); + } + if (ToolUtil.isNotEmpty(productSvcParam.getMark())) { + query.setParameter("mark", "%" + productSvcParam.getMark() + "%"); + } + if (ToolUtil.isNotEmpty(productSvcParam.getProdId())) { + query.setParameter("relationId", productSvcParam.getProdId()); + } + + List productServiceDtoList = query.setFirstRow((productSvcParam.getPage() - 1) * productSvcParam.getMaxRow()) + .setMaxRows(productSvcParam.getMaxRow()).findList(); if (ToolUtil.isEmpty(productServiceDtoList)) { return new Pager<>(productServiceDtoList, 0); @@ -116,6 +133,12 @@ public ProductServiceDto create(ProductServiceDto productServiceDto) { Long serviceId = productService.getId(); productServiceDto.setId(serviceId); + ProductServiceRelation productServiceRelation = new ProductServiceRelation(); + productServiceRelation.setInherit(0); + productServiceRelation.setServiceId(productService.getId()); + productServiceRelation.setRelationId(productServiceDto.getRelationId()); + DB.save(productServiceRelation); + if (ToolUtil.isNotEmpty(productServiceDto.getProductServiceParamList())) { for (ProductServiceParam productServiceParam : productServiceDto.getProductServiceParamList()) { productServiceParam.setServiceId(serviceId); @@ -124,7 +147,7 @@ public ProductServiceDto create(ProductServiceDto productServiceDto) { } //同步到设备 - WorkerWrapper saveProdAttrWork = WorkerWrapper.builder().worker(saveProdSvcWorker).build(); + WorkerWrapper saveProdAttrWork = WorkerWrapper.builder().worker(saveProdSvcWorker).param(productServiceDto).build(); try { Async.work(100, saveProdAttrWork).awaitFinish(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java index 111e8ef1..9d1aa212 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java @@ -36,6 +36,7 @@ public Boolean action(ProductServiceDto productServiceDto, Map Date: Wed, 15 Sep 2021 16:46:19 +0800 Subject: [PATCH 169/763] [fix]: fix product status function relation device --- .../product/ProductServiceRelation.java | 2 +- .../ProductStatusFunctionRelation.java | 2 + .../device/service/work/SaveOtherWorker.java | 7 +++ .../product/service/ProductSvcService.java | 1 - .../service/ProductTriggerService.java | 3 ++ .../work/SaveProdStatusTriggerWorker.java | 54 +++++++++++++++++++ .../service/work/SaveProdSvcWorker.java | 2 +- 7 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceRelation.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceRelation.java index 60261c2b..ca4f60c8 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceRelation.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceRelation.java @@ -24,6 +24,6 @@ public class ProductServiceRelation { private String relationId; - private Integer inherit; + private String inherit; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java index 133c1b29..cd225aeb 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java @@ -25,4 +25,6 @@ public class ProductStatusFunctionRelation { private String relationId; + private String inherit; + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java index 02ce7aff..8b42d95a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java @@ -5,6 +5,7 @@ import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.product.query.QProductServiceRelation; +import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; import io.ebean.DB; @@ -37,6 +38,8 @@ public Boolean action(DeviceDto deviceDto, Map> allW } //删除服务关联 new QProductServiceRelation().relationId.eq(deviceId).delete(); + //删除上下线规则关联 + new QProductStatusFunctionRelation().relationId.eq(deviceId).delete(); } else { //创建 Device device = (Device) allWrappers.get("saveDvice").getWorkResult().getResult(); @@ -47,6 +50,10 @@ public Boolean action(DeviceDto deviceDto, Map> allW DB.sqlUpdate("insert into product_service_relation (relation_id,service_id,inherit) SELECT :deviceId,service_id,1 from product_service_relation where relation_id=:relationId") .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId()).execute(); + //上下线规则关联 + DB.sqlUpdate("insert into product_status_function_relation (relation_id,rule_id,inherit) SELECT :deviceId,rule_id,1 from product_status_function_relation where relation_id=:relationId") + .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId()).execute(); + return true; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index 89778038..a9418bf7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -134,7 +134,6 @@ public ProductServiceDto create(ProductServiceDto productServiceDto) { productServiceDto.setId(serviceId); ProductServiceRelation productServiceRelation = new ProductServiceRelation(); - productServiceRelation.setInherit(0); productServiceRelation.setServiceId(productService.getId()); productServiceRelation.setRelationId(productServiceDto.getRelationId()); DB.save(productServiceRelation); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java index 14e85025..499379ce 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java @@ -77,8 +77,11 @@ public Long createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { ProductStatusFunctionRelation productStatusFunctionRelation = new ProductStatusFunctionRelation(); productStatusFunctionRelation.setRelationId(judgeRule.getRelationId()); productStatusFunctionRelation.setRuleId(ruleId); + productStatusFunctionRelation.setRuleId(ruleId); DB.save(productStatusFunctionRelation); + + return productStatusFunction.getRuleId(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java new file mode 100644 index 00000000..dd40a24f --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java @@ -0,0 +1,54 @@ +package com.zmops.iot.web.product.service.work; + + +import com.zmops.iot.async.callback.IWorker; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductServiceRelation; +import com.zmops.iot.domain.product.ProductStatusFunctionRelation; +import com.zmops.iot.web.product.dto.ProductServiceDto; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author yefei + *

+ * 产品服务创建 同步到设备 步骤 + */ +@Slf4j +@Component +public class SaveProdStatusTriggerWorker implements IWorker { + + + @Override + public Boolean action(ProductServiceDto productServiceDto, Map> map) { + log.debug("处理产品 新增上下线规则 同步到设备工作…………"); + + String prodId = productServiceDto.getRelationId(); + + List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); + List productStatusFunctionRelationList = new ArrayList<>(); + for (String deviceId : deviceIds) { + ProductStatusFunctionRelation productStatusFunctionRelation = new ProductStatusFunctionRelation(); + productStatusFunctionRelation.setRelationId(deviceId); + productStatusFunctionRelation.setRuleId(productServiceDto.getId()); + productStatusFunctionRelation.setInherit("1"); + productStatusFunctionRelationList.add(productStatusFunctionRelation); + } + DB.saveAll(productStatusFunctionRelationList); + + return true; + } + + + @Override + public Boolean defaultValue() { + return true; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java index 9d1aa212..e79bcf6d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java @@ -36,7 +36,7 @@ public Boolean action(ProductServiceDto productServiceDto, Map Date: Wed, 15 Sep 2021 17:42:06 +0800 Subject: [PATCH 170/763] [fix]: fix product service --- .../service/work/UpdateProdSvcWorker.java | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java index 844611ea..66410bbb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java @@ -31,28 +31,7 @@ public class UpdateProdSvcWorker implements IWorker public Boolean action(ProductServiceDto productServiceDto, Map> map) { log.debug("处理产品服务修改 同步到设备工作…………"); - Long Id = productServiceDto.getId(); - List list = new QProductService().templateId.eq(Id).findList(); - - for (ProductService productService : list) { - productService.setName(productServiceDto.getName()); - productService.setMark(productServiceDto.getMark()); - productService.setAsync(productServiceDto.getAsync()); - } - DB.updateAll(list); - - //处理服务参数 - List ids = list.parallelStream().map(ProductService::getId).collect(Collectors.toList()); - new QProductServiceParam().serviceId.in(ids).delete(); - if (ToolUtil.isNotEmpty(productServiceDto.getProductServiceParamList())) { - for (Long id : ids) { - for (ProductServiceParam productServiceParam : productServiceDto.getProductServiceParamList()) { - productServiceParam.setServiceId(id); - } - } - DB.saveAll(productServiceDto.getProductServiceParamList()); - } return true; } From f2f8d2193f044f30f61cf08eefab734f34eaa3d8 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 15 Sep 2021 18:06:57 +0800 Subject: [PATCH 171/763] [feat]: create product event trigger --- .../iot/domain/product/ProductEvent.java | 31 +++++ .../product/ProductEventExpression.java | 33 ++++++ .../zmops/zeus/driver/service/ZbxTrigger.java | 62 ++++++++++ .../api-json/trigger/trigger.create.ftl | 11 ++ .../api-json/trigger/trigger.tags.update.ftl | 17 +++ .../controller/DeviceModelController.java | 8 +- .../controller/ProductEventController.java | 103 +++++++++++++++++ .../iot/web/product/dto/ProductEventRule.java | 106 ++++++++++++++++++ .../product/service/ProductEventService.java | 67 +++++++++++ 9 files changed, 434 insertions(+), 4 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java create mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java create mode 100644 zeus-driver/src/main/resources/api-json/trigger/trigger.tags.update.ftl create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventService.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java new file mode 100644 index 00000000..3e43b0b5 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java @@ -0,0 +1,31 @@ +package com.zmops.iot.domain.product; + +import com.zmops.iot.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author nantian created at 2021/9/15 1:02 + */ + +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "product_event") +public class ProductEvent extends BaseEntity { + + @Id + private Long eventRuleId; + + private String eventRuleName; + private Byte eventLevel; + private String expLogic; + private String remark; + private Byte eventNotify; + private Integer zbxId; + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java new file mode 100644 index 00000000..7006ad99 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java @@ -0,0 +1,33 @@ +package com.zmops.iot.domain.product; + +import com.zmops.iot.constant.IdTypeConsts; +import io.ebean.Model; +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author nantian created at 2021/9/15 16:50 + *

+ * 触发器 表达式 函数 + */ + +@Data +@Entity +@Table(name = "product_event_expression") +public class ProductEventExpression extends Model { + + @Id + @GeneratedValue(generator = IdTypeConsts.ID_SNOW) + private Long eventExpId; + private Long eventRuleId; + private String function; + private String scope; + private String condition; + private String value; + private String productId; + private String productAttrKey; +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java new file mode 100644 index 00000000..21264463 --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java @@ -0,0 +1,62 @@ +package com.zmops.zeus.driver.service; + + +import com.dtflys.forest.annotation.BaseRequest; +import com.dtflys.forest.annotation.Post; +import com.zmops.zeus.driver.annotation.JsonPath; +import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; + +import java.util.List; +import java.util.Map; + +@BaseRequest( + baseURL = "${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) +public interface ZbxTrigger { + + /** + * 创建告警触发器 + * + * @param triggerName 触发器名称 + * @param expression 触发器 表达式 + * @param ruleLevel 告警等级 + * @return + */ + @Post + @JsonPath("/trigger/trigger.create") + String triggerCreate(@ParamName("triggerName") String triggerName, + @ParamName("expression") String expression, + @ParamName("ruleLevel") Byte ruleLevel); + + + /** + * 更新告警触发器 + * + * @param triggerId 触发器ID + * @param triggerName 触发器名称 + * @param expression 触发器 表达式 + * @param ruleLevel 告警等级 + * @return + */ + @Post + @JsonPath("/trigger/trigger.update") + String triggerUpdate(@ParamName("triggerId") Long triggerId, + @ParamName("triggerName") String triggerName, + @ParamName("expression") String expression, + @ParamName("ruleLevel") Byte ruleLevel); + + + /** + * 更新创建 触发器 Tag + * + * @param triggerId 触发器ID + * @param tags 标签 + * @return + */ + @Post + @JsonPath("/trigger/trigger.tags.update") + String triggerTagCreate(@ParamName("triggerId") Long triggerId, + @ParamName("tagMap") Map tags); +} diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.create.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.create.ftl index e69de29b..d338ad2b 100644 --- a/zeus-driver/src/main/resources/api-json/trigger/trigger.create.ftl +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.create.ftl @@ -0,0 +1,11 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.create", + "params": { + "description": "${triggerName}", + "expression": "${expression}", + "priority" : ${ruleLevel} + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.tags.update.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.tags.update.ftl new file mode 100644 index 00000000..0e0078f1 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.tags.update.ftl @@ -0,0 +1,17 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.update", + "params": { + "triggerid": "${triggerId}", + "tags": [ + <#list tagMap?keys as key> + { + "tag": "${key}", + "value": "${tagMap[key]}" + }<#if key_has_next>, + + ] + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java index 1d920023..84346feb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java @@ -81,11 +81,11 @@ public ResponseData prodModelAttributeCreate(@RequestBody @Validated(BaseEntity. } if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { - if(productAttr.getDepAttrId() == null){ + if (productAttr.getDepAttrId() == null) { throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NULL); } ProductAttribute productAttribute = new QProductAttribute().attrId.eq(productAttr.getDepAttrId()).findOne(); - if(null == productAttribute){ + if (null == productAttribute) { throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); } productAttr.setMasterItemId(productAttribute.getZbxId()); @@ -116,11 +116,11 @@ public ResponseData prodModelAttributeUpdate(@RequestBody @Validated(BaseEntity. } if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { - if(productAttr.getDepAttrId() == null){ + if (productAttr.getDepAttrId() == null) { throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NULL); } ProductAttribute productAttribute = new QProductAttribute().attrId.eq(productAttr.getDepAttrId()).findOne(); - if(null == productAttribute){ + if (null == productAttribute) { throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); } productAttr.setMasterItemId(productAttribute.getZbxId()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java new file mode 100644 index 00000000..879e598f --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java @@ -0,0 +1,103 @@ +package com.zmops.iot.web.product.controller; + +import cn.hutool.core.util.IdUtil; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.ProductEventExpression; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.product.dto.ProductEventRule; +import com.zmops.iot.web.product.service.ProductEventService; +import io.ebean.DB; +import io.ebean.annotation.Transactional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author nantian created at 2021/8/26 23:04 + *

+ * 产品 物模型功能【事件】 类似于 属性处理 + */ + +@RestController +@RequestMapping("/product/event") +public class ProductEventController { + + + @Autowired + private ProductEventService productEventService; + + + @Transactional + @PostMapping("/create") + public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseEntity.Create.class) + ProductEventRule eventRule) { + + Long eventRuleId = IdUtil.getSnowflake().nextId(); // ruleId, trigger name + + //step 1: 先创建 zbx 触发器 + String expression = eventRule.getExpList() + .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); + + String triggerId = productEventService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); + + //step 2:保存 业务触发器对象 + ProductEvent event = new ProductEvent(); + event.setEventRuleId(eventRuleId); + event.setEventLevel(eventRule.getEventLevel()); + event.setExpLogic(eventRule.getExpLogic()); + event.setEventNotify(eventRule.getEventNotify()); + event.setRemark(eventRule.getRemark()); + event.setEventRuleName(eventRule.getEventRuleName()); + event.setZbxId(Integer.valueOf(triggerId)); + + productEventService.createProductEventRule(event); + + //step 3: 保存 表达式,方便回显 + + List expList = new ArrayList<>(); + + eventRule.getExpList().forEach(i -> { + + ProductEventExpression exp = new ProductEventExpression(); + exp.setEventRuleId(eventRuleId); + exp.setCondition(i.getCondition()); + exp.setFunction(i.getFunction()); + exp.setScope(i.getScope()); + exp.setValue(i.getValue()); + exp.setProductId(i.getProductId()); + exp.setProductAttrKey(i.getProductAttrKey()); + + expList.add(exp); + }); + + productEventService.createProductEventExpression(expList); + + // step 4: 保存 tag + if (eventRule.getTags() != null) { + productEventService.createProductEventTags(triggerId, eventRule.getTags()); + } + + // step 5: 保存 调用 Service + if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { + eventRule.getDeviceServices().forEach(i -> { + DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id, service_id) values (:eventRuleId, :deviceId, :serviceId)") + .setParameter("eventRuleId", eventRuleId) + .setParameter("deviceId", i.getDeviceId()) + .setParameter("serviceId", i.getServiceId()) + .execute(); + }); + } + + return ResponseData.success(eventRuleId); // 返回触发器ID + } + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java new file mode 100644 index 00000000..490a8baa --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java @@ -0,0 +1,106 @@ +package com.zmops.iot.web.product.dto; + +import com.zmops.iot.domain.BaseEntity; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; +import java.util.Map; + +/** + * @author nantian created at 2021/9/14 14:47 + *

+ * 告警规则 + */ + +@Getter +@Setter +public class ProductEventRule { + + private String eventRuleId; + + @NotNull(groups = BaseEntity.Create.class) + private Byte eventNotify; // 0 否 1 是,默认 1 + + // 告警规则名称 + @NotBlank(groups = BaseEntity.Create.class) + private String eventRuleName; + + // 告警规则级别 + @NotNull(groups = BaseEntity.Create.class) + private Byte eventLevel; + + // 表达式列表 + @Valid + @NotEmpty(groups = BaseEntity.Create.class) + private List expList; + + @NotBlank(groups = BaseEntity.Create.class) + private String expLogic; // and or + + private String remark; + + private List deviceServices; + + private Map tags; + + + @Getter + @Setter + // 告警表达式 构成 + public static class Expression { + + @NotBlank(groups = BaseEntity.Create.class) + private String function; // last avg max min sum change nodata + + private String scope; // s m h T + + @NotBlank(groups = BaseEntity.Create.class) + private String condition; // > < = <> >= <= + + @NotBlank(groups = BaseEntity.Create.class) + private String value; + + @NotNull(groups = BaseEntity.Create.class) + private String productAttrKey; // 产品属性 Key + + @NotBlank(groups = BaseEntity.Create.class) + private String productId; // 产品ID + + @Override + public String toString() { + StringBuilder expression = new StringBuilder(); + expression.append(function); + expression.append("(/"); + expression.append(productId); + expression.append("/"); + expression.append(productAttrKey); + + if (null != scope) { + expression.append(", "); + expression.append(scope); + } + expression.append(") ").append(condition).append(" ").append(value); + return expression.toString(); + } + } + + + @Setter + @Getter + public static class DeviceService { + + private Long deviceId; + + private Long serviceId; + } + +} + + + + diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventService.java new file mode 100644 index 00000000..d72810ab --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventService.java @@ -0,0 +1,67 @@ +package com.zmops.iot.web.product.service; + +import com.alibaba.fastjson.JSON; +import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.ProductEventExpression; +import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +/** + * @author nantian created at 2021/9/15 13:59 + */ + +@Slf4j +@Service +public class ProductEventService { + + @Autowired + private ZbxTrigger zbxTrigger; + + + /** + * 保存触发器 + * + * @param productEvent productEvent + */ + public void createProductEventRule(ProductEvent productEvent) { + productEvent.save(); + } + + + public void createProductEventExpression(List expressionList) { + DB.saveAll(expressionList); + } + + + public void createProductEventTags(String triggerId, Map tags) { + String res = zbxTrigger.triggerTagCreate(Long.valueOf(triggerId), tags); + log.debug(res); + } + + + /** + * 创建 触发器 + * + * @param triggerName 触发器名称 + * @param expression 表达式 + * @param level 告警等级 + * @return 触发器ID + */ + public String createZbxTrigger(String triggerName, String expression, Byte level) { + String res = zbxTrigger.triggerCreate(triggerName, expression, level); + return JSON.parseObject(res, TriggerIds.class).getTriggerids()[0]; + } + + + @Data + static class TriggerIds { + private String[] triggerids; + } +} From 9180e423fac5d70f8cc30d56a3870841bffe830a Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 15 Sep 2021 19:02:04 +0800 Subject: [PATCH 172/763] [style]: change code style --- .../product/controller/ProductController.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java index 92bf631c..4bf4a823 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java @@ -101,7 +101,7 @@ public ResponseData prodCreate(@RequestBody @Validated(value = BaseEntity.Create String result = productService.zbxTemplateCreate(prodId + ""); // 第二步:创建产品 - String zbxId = JSON.parseObject(result, TemplateIds.class).getTemplateids()[0]; + String zbxId = JSON.parseObject(result, TemplateIds.class).getTemplateids()[0]; productService.createProduct(zbxId, prodId, prodBasicInfo); prodBasicInfo.setProductId(prodId); return ResponseData.success(prodBasicInfo); @@ -144,7 +144,7 @@ public ResponseData prodDelete(@RequestBody @Validated(value = BaseEntity.Delete throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } int deviceNum = new QDevice().productId.eq(prodBasicInfo.getProductId()).findCount(); - if(deviceNum>0){ + if (deviceNum > 0) { throw new ServiceException(BizExceptionEnum.PRODUCT_HAS_BIND_DEVICE); } @@ -171,20 +171,24 @@ public ResponseData prodDelete(@RequestBody @Validated(value = BaseEntity.Delete @PostMapping("/tag/update") public ResponseData prodTagCreate(@RequestBody @Valid ProductTag productTag) { - String productId = productTag.getProductId(); + String productId = productTag.getProductId(); Product product = new QProduct().productId.eq(Long.parseLong(productId)).findOne(); if (null == product) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } + new QTag().sid.eq(productTag.getProductId()).delete(); + List tags = new ArrayList<>(); for (ProductTag.Tag tag : productTag.getProductTag()) { - tags.add( - Tag.builder().sid(productTag.getProductId()) - .tag(tag.getTag()).value(tag.getValue()) - .build()); + tags.add(Tag.builder() + .sid(productTag.getProductId()) + .tag(tag.getTag()).value(tag.getValue()) + .build() + ); } + DB.saveAll(tags); String response = productService.updateTemplateTags(product.getZbxId(), productTag); From 80cb38e7abfc5be336206b1a730e819989063309 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 15 Sep 2021 19:44:05 +0800 Subject: [PATCH 173/763] [feat]: event trigger page list --- .../iot/domain/product/ProductEvent.java | 2 +- .../controller/ProductEventController.java | 33 +++++++++++++++++++ .../iot/web/product/dto/ProductEventDto.java | 29 ++++++++++++++++ .../iot/web/product/dto/param/EventParm.java | 15 +++++++++ .../product/service/ProductEventService.java | 28 ++++++++++++++++ 5 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/EventParm.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java index 3e43b0b5..30355691 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java @@ -27,5 +27,5 @@ public class ProductEvent extends BaseEntity { private String remark; private Byte eventNotify; private Integer zbxId; - + private String status; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java index 879e598f..8d834174 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java @@ -4,8 +4,12 @@ import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.ProductEventExpression; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.product.dto.ProductEventDto; import com.zmops.iot.web.product.dto.ProductEventRule; +import com.zmops.iot.web.product.dto.param.EventParm; import com.zmops.iot.web.product.service.ProductEventService; import io.ebean.DB; import io.ebean.annotation.Transactional; @@ -34,7 +38,23 @@ public class ProductEventController { @Autowired private ProductEventService productEventService; + /** + * 触发器 分页列表 + * + * @param eventParm + * @return + */ + @PostMapping("/getEventByPage") + public Pager getEventByPage(@RequestBody EventParm eventParm) { + return productEventService.getEventByPage(eventParm); + } + /** + * 创建 触发器 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ @Transactional @PostMapping("/create") public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseEntity.Create.class) @@ -57,6 +77,7 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE event.setRemark(eventRule.getRemark()); event.setEventRuleName(eventRule.getEventRuleName()); event.setZbxId(Integer.valueOf(triggerId)); + event.setStatus(CommonStatus.ENABLE.getCode()); productEventService.createProductEventRule(event); @@ -99,5 +120,17 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE return ResponseData.success(eventRuleId); // 返回触发器ID } + /** + * 修改 触发器 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ + @Transactional + @PostMapping("/update") + public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseEntity.Create.class) + ProductEventRule eventRule) { + return ResponseData.success(); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java new file mode 100644 index 00000000..c86a65ac --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java @@ -0,0 +1,29 @@ +package com.zmops.iot.web.product.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import lombok.Data; + +/** + * @author yefei + **/ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class ProductEventDto { + + private String eventRuleId; + + private Byte eventNotify; + + private String eventRuleName; + + private String eventLevel; + + @CachedValue(value = "STATUS") + private String status; + + private String remark; + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/EventParm.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/EventParm.java new file mode 100644 index 00000000..311135da --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/EventParm.java @@ -0,0 +1,15 @@ +package com.zmops.iot.web.product.dto.param; + +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class EventParm extends BaseQueryParam { + + private String eventRuleName; + + private String prodId; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventService.java index d72810ab..e5fb687d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventService.java @@ -3,6 +3,12 @@ import com.alibaba.fastjson.JSON; import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.ProductEventExpression; +import com.zmops.iot.domain.product.query.QProductEvent; +import com.zmops.iot.domain.product.query.QProductEventExpression; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.product.dto.ProductEventDto; +import com.zmops.iot.web.product.dto.param.EventParm; import com.zmops.zeus.driver.service.ZbxTrigger; import io.ebean.DB; import lombok.Data; @@ -59,6 +65,28 @@ public String createZbxTrigger(String triggerName, String expression, Byte level return JSON.parseObject(res, TriggerIds.class).getTriggerids()[0]; } + /** + * 触发器 分页列表 + * + * @param eventParm + * @return + */ + public Pager getEventByPage(EventParm eventParm) { + QProductEvent query = new QProductEvent(); + if (ToolUtil.isNotEmpty(eventParm.getEventRuleName())) { + query.eventRuleName.contains(eventParm.getEventRuleName()); + } + if (ToolUtil.isNotEmpty(eventParm.getProdId())) { + List eventRuleIdList = new QProductEventExpression().select(QProductEventExpression.alias().eventRuleId).productId.eq(eventParm.getProdId()).findSingleAttributeList(); + if (ToolUtil.isNotEmpty(eventRuleIdList)) { + query.eventRuleId.in(eventRuleIdList); + } + } + List list = query.setFirstRow((eventParm.getPage() - 1) * eventParm.getMaxRow()) + .setMaxRows(eventParm.getMaxRow()).orderBy(" create_time desc").asDto(ProductEventDto.class).findList(); + return new Pager<>(list, query.findCount()); + } + @Data static class TriggerIds { From f597046118879bf6bbe390652d3e73b284c16569 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 15 Sep 2021 22:24:10 +0800 Subject: [PATCH 174/763] [style]: remove unused code --- .../iot/core/web/base/BaseController.java | 7 -- .../core/web/base/BaseControllerWrapper.java | 76 ------------------- 2 files changed, 83 deletions(-) delete mode 100644 zeus-core/src/main/java/com/zmops/iot/core/web/base/BaseControllerWrapper.java diff --git a/zeus-core/src/main/java/com/zmops/iot/core/web/base/BaseController.java b/zeus-core/src/main/java/com/zmops/iot/core/web/base/BaseController.java index 56b3530c..ab23672d 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/web/base/BaseController.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/web/base/BaseController.java @@ -51,13 +51,6 @@ protected void setAttr(String name, Object value) { Objects.requireNonNull(HttpContext.getRequest()).setAttribute(name, value); } - /** - * 包装一个list,让list增加额外属性 - */ - protected Object warpObject(BaseControllerWrapper warpper) { - return warpper.wrap(); - } - /** * 删除cookie */ diff --git a/zeus-core/src/main/java/com/zmops/iot/core/web/base/BaseControllerWrapper.java b/zeus-core/src/main/java/com/zmops/iot/core/web/base/BaseControllerWrapper.java deleted file mode 100644 index 8f8500e9..00000000 --- a/zeus-core/src/main/java/com/zmops/iot/core/web/base/BaseControllerWrapper.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.zmops.iot.core.web.base; - -import java.util.List; -import java.util.Map; - -/** - * @author nantian created at 2021/7/29 20:32 - */ -public abstract class BaseControllerWrapper { - -// private Page> page = null; -// -// private PageResult> pageResult = null; - - private Map single = null; - - private List> multi = null; - - public BaseControllerWrapper(Map single) { - this.single = single; - } - - public BaseControllerWrapper(List> multi) { - this.multi = multi; - } - -// public BaseControllerWrapper(Page> page) { -// if (page != null && page.getRecords() != null) { -// this.page = page; -// this.multi = page.getRecords(); -// } -// } -// -// public BaseControllerWrapper(PageResult> pageResult) { -// if (pageResult != null && pageResult.getRows() != null) { -// this.pageResult = pageResult; -// this.multi = pageResult.getRows(); -// } -// } - - @SuppressWarnings("unchecked") - public T wrap() { - - /** - * 包装结果 - */ - if (single != null) { - wrapTheMap(single); - } - if (multi != null) { - for (Map map : multi) { - wrapTheMap(map); - } - } - - /** - * 根据请求的参数响应 - */ -// if (page != null) { -// return (T) page; -// } -// if (pageResult != null) { -// return (T) pageResult; -// } - if (single != null) { - return (T) single; - } - if (multi != null) { - return (T) multi; - } - - return null; - } - - protected abstract void wrapTheMap(Map map); -} From e9481e8dc8762847088f257f2a546cb0520dd366 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 16 Sep 2021 01:00:55 +0800 Subject: [PATCH 175/763] [fix]: code optimization --- .../controller/ProductEventController.java | 77 +++------- .../web/product/service/EventRuleService.java | 144 ++++++++++++++++++ .../product/service/ProductEventService.java | 95 ------------ 3 files changed, 164 insertions(+), 152 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventService.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java index 8d834174..169c8bda 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java @@ -2,16 +2,13 @@ import cn.hutool.core.util.IdUtil; import com.zmops.iot.domain.BaseEntity; -import com.zmops.iot.domain.product.ProductEvent; -import com.zmops.iot.domain.product.ProductEventExpression; -import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.web.product.dto.ProductEventDto; import com.zmops.iot.web.product.dto.ProductEventRule; import com.zmops.iot.web.product.dto.param.EventParm; -import com.zmops.iot.web.product.service.ProductEventService; -import io.ebean.DB; +import com.zmops.iot.web.product.service.EventRuleService; +import com.zmops.zeus.driver.service.ZbxTrigger; import io.ebean.annotation.Transactional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; @@ -20,8 +17,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.util.ArrayList; -import java.util.List; import java.util.stream.Collectors; /** @@ -36,7 +31,10 @@ public class ProductEventController { @Autowired - private ProductEventService productEventService; + private EventRuleService eventRuleService; + + @Autowired + private ZbxTrigger zbxTrigger; /** * 触发器 分页列表 @@ -46,7 +44,7 @@ public class ProductEventController { */ @PostMapping("/getEventByPage") public Pager getEventByPage(@RequestBody EventParm eventParm) { - return productEventService.getEventByPage(eventParm); + return eventRuleService.getEventByPage(eventParm); } /** @@ -62,62 +60,25 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE Long eventRuleId = IdUtil.getSnowflake().nextId(); // ruleId, trigger name + eventRuleService.createProductEventRule(eventRuleId, eventRule); + //step 1: 先创建 zbx 触发器 String expression = eventRule.getExpList() .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); - String triggerId = productEventService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); - - //step 2:保存 业务触发器对象 - ProductEvent event = new ProductEvent(); - event.setEventRuleId(eventRuleId); - event.setEventLevel(eventRule.getEventLevel()); - event.setExpLogic(eventRule.getExpLogic()); - event.setEventNotify(eventRule.getEventNotify()); - event.setRemark(eventRule.getRemark()); - event.setEventRuleName(eventRule.getEventRuleName()); - event.setZbxId(Integer.valueOf(triggerId)); - event.setStatus(CommonStatus.ENABLE.getCode()); - - productEventService.createProductEventRule(event); - - //step 3: 保存 表达式,方便回显 - - List expList = new ArrayList<>(); + //step 2: zbx 保存触发器 + String triggerId = eventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); - eventRule.getExpList().forEach(i -> { - - ProductEventExpression exp = new ProductEventExpression(); - exp.setEventRuleId(eventRuleId); - exp.setCondition(i.getCondition()); - exp.setFunction(i.getFunction()); - exp.setScope(i.getScope()); - exp.setValue(i.getValue()); - exp.setProductId(i.getProductId()); - exp.setProductAttrKey(i.getProductAttrKey()); - - expList.add(exp); - }); - - productEventService.createProductEventExpression(expList); - - // step 4: 保存 tag + //step 3: zbx 触发器创建 Tag if (eventRule.getTags() != null) { - productEventService.createProductEventTags(triggerId, eventRule.getTags()); + zbxTrigger.triggerTagCreate(Long.valueOf(triggerId), eventRule.getTags()); } - // step 5: 保存 调用 Service - if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { - eventRule.getDeviceServices().forEach(i -> { - DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id, service_id) values (:eventRuleId, :deviceId, :serviceId)") - .setParameter("eventRuleId", eventRuleId) - .setParameter("deviceId", i.getDeviceId()) - .setParameter("serviceId", i.getServiceId()) - .execute(); - }); - } + //step 4: 更新 zbxId + eventRuleService.updateProductEventRuleZbxId(eventRuleId, Integer.valueOf(triggerId)); - return ResponseData.success(eventRuleId); // 返回触发器ID + // 返回触发器ID + return ResponseData.success(eventRuleId); } /** @@ -128,8 +89,10 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE */ @Transactional @PostMapping("/update") - public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseEntity.Create.class) + public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) ProductEventRule eventRule) { + + return ResponseData.success(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java new file mode 100644 index 00000000..f00ebdc3 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java @@ -0,0 +1,144 @@ +package com.zmops.iot.web.product.service; + +import com.alibaba.fastjson.JSON; +import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.ProductEventExpression; +import com.zmops.iot.domain.product.query.QProductEvent; +import com.zmops.iot.domain.product.query.QProductEventExpression; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.product.dto.ProductEventDto; +import com.zmops.iot.web.product.dto.ProductEventRule; +import com.zmops.iot.web.product.dto.param.EventParm; +import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author nantian created at 2021/9/15 13:59 + *

+ * 告警规则 创建,产品 和 设备 + */ + +@Slf4j +@Service +public class EventRuleService { + + @Autowired + private ZbxTrigger zbxTrigger; + + /** + * 保存触发器 + * + * @param eventRuleId 触发器ID + * @param eventRule 告警规则 + */ + public void createProductEventRule(Long eventRuleId, ProductEventRule eventRule) { + // step 1: 保存产品告警规则 + ProductEvent event = new ProductEvent(); + event.setEventRuleId(eventRuleId); + event.setEventLevel(eventRule.getEventLevel()); + event.setExpLogic(eventRule.getExpLogic()); + event.setEventNotify(eventRule.getEventNotify()); + event.setRemark(eventRule.getRemark()); + event.setEventRuleName(eventRule.getEventRuleName()); + event.setStatus(CommonStatus.ENABLE.getCode()); + + DB.save(event); + + //step 2: 保存 表达式,方便回显 + List expList = new ArrayList<>(); + + eventRule.getExpList().forEach(i -> { + ProductEventExpression exp = new ProductEventExpression(); + exp.setEventRuleId(eventRuleId); + exp.setCondition(i.getCondition()); + exp.setFunction(i.getFunction()); + exp.setScope(i.getScope()); + exp.setValue(i.getValue()); + exp.setProductId(i.getProductId()); + exp.setProductAttrKey(i.getProductAttrKey()); + expList.add(exp); + }); + + DB.saveAll(expList); + + //step 3: 保存触发器 调用 本产品方法 + if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { + eventRule.getDeviceServices().forEach(i -> { + DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id, service_id) values (:eventRuleId, :deviceId, :serviceId)") + .setParameter("eventRuleId", eventRuleId) + .setParameter("deviceId", i.getDeviceId()) + .setParameter("serviceId", i.getServiceId()) + .execute(); + }); + } + } + + + /** + * 更新 触发器规则 zbxId + * + * @param triggerId 规则ID + * @param zbxId triggerId + */ + public void updateProductEventRuleZbxId(Long triggerId, Integer zbxId) { + DB.update(ProductEvent.class).where().eq("eventRuleId", triggerId).asUpdate().set("zbxId", zbxId).update(); + } + + + /** + * 创建 触发器 + * + * @param triggerName 触发器名称 + * @param expression 表达式 + * @param level 告警等级 + * @return 触发器ID + */ + public String createZbxTrigger(String triggerName, String expression, Byte level) { + String res = zbxTrigger.triggerCreate(triggerName, expression, level); + return JSON.parseObject(res, TriggerIds.class).getTriggerids()[0]; + } + + /** + * 触发器 分页列表 + * + * @param eventParm + * @return + */ + public Pager getEventByPage(EventParm eventParm) { + QProductEvent query = new QProductEvent(); + + if (ToolUtil.isNotEmpty(eventParm.getEventRuleName())) { + query.eventRuleName.contains(eventParm.getEventRuleName()); + } + + if (ToolUtil.isNotEmpty(eventParm.getProdId())) { + List eventRuleIdList = new QProductEventExpression().select(QProductEventExpression.alias().eventRuleId) + .productId.eq(eventParm.getProdId()).findSingleAttributeList(); + + if (ToolUtil.isNotEmpty(eventRuleIdList)) { + query.eventRuleId.in(eventRuleIdList); + } + } + + List list = query.setFirstRow((eventParm.getPage() - 1) * eventParm.getMaxRow()) + .setMaxRows(eventParm.getMaxRow()).orderBy(" create_time desc").asDto(ProductEventDto.class).findList(); + + return new Pager<>(list, query.findCount()); + } + + + @Data + static class TriggerIds { + private String[] triggerids; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventService.java deleted file mode 100644 index e5fb687d..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventService.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.zmops.iot.web.product.service; - -import com.alibaba.fastjson.JSON; -import com.zmops.iot.domain.product.ProductEvent; -import com.zmops.iot.domain.product.ProductEventExpression; -import com.zmops.iot.domain.product.query.QProductEvent; -import com.zmops.iot.domain.product.query.QProductEventExpression; -import com.zmops.iot.model.page.Pager; -import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.product.dto.ProductEventDto; -import com.zmops.iot.web.product.dto.param.EventParm; -import com.zmops.zeus.driver.service.ZbxTrigger; -import io.ebean.DB; -import lombok.Data; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Map; - -/** - * @author nantian created at 2021/9/15 13:59 - */ - -@Slf4j -@Service -public class ProductEventService { - - @Autowired - private ZbxTrigger zbxTrigger; - - - /** - * 保存触发器 - * - * @param productEvent productEvent - */ - public void createProductEventRule(ProductEvent productEvent) { - productEvent.save(); - } - - - public void createProductEventExpression(List expressionList) { - DB.saveAll(expressionList); - } - - - public void createProductEventTags(String triggerId, Map tags) { - String res = zbxTrigger.triggerTagCreate(Long.valueOf(triggerId), tags); - log.debug(res); - } - - - /** - * 创建 触发器 - * - * @param triggerName 触发器名称 - * @param expression 表达式 - * @param level 告警等级 - * @return 触发器ID - */ - public String createZbxTrigger(String triggerName, String expression, Byte level) { - String res = zbxTrigger.triggerCreate(triggerName, expression, level); - return JSON.parseObject(res, TriggerIds.class).getTriggerids()[0]; - } - - /** - * 触发器 分页列表 - * - * @param eventParm - * @return - */ - public Pager getEventByPage(EventParm eventParm) { - QProductEvent query = new QProductEvent(); - if (ToolUtil.isNotEmpty(eventParm.getEventRuleName())) { - query.eventRuleName.contains(eventParm.getEventRuleName()); - } - if (ToolUtil.isNotEmpty(eventParm.getProdId())) { - List eventRuleIdList = new QProductEventExpression().select(QProductEventExpression.alias().eventRuleId).productId.eq(eventParm.getProdId()).findSingleAttributeList(); - if (ToolUtil.isNotEmpty(eventRuleIdList)) { - query.eventRuleId.in(eventRuleIdList); - } - } - List list = query.setFirstRow((eventParm.getPage() - 1) * eventParm.getMaxRow()) - .setMaxRows(eventParm.getMaxRow()).orderBy(" create_time desc").asDto(ProductEventDto.class).findList(); - return new Pager<>(list, query.findCount()); - } - - - @Data - static class TriggerIds { - private String[] triggerids; - } -} From c0e6c888c642757f51efc1bb97257c18d7d85b40 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 16 Sep 2021 02:49:48 +0800 Subject: [PATCH 176/763] [feat]: product trigger update --- .../product/ProductEventExpression.java | 3 +- .../zmops/zeus/driver/service/ZbxTrigger.java | 6 +- .../api-json/trigger/trigger.update.ftl | 11 +++ .../controller/ProductEventController.java | 22 ++++- .../iot/web/product/dto/ProductEventRule.java | 29 +++--- .../web/product/service/EventRuleService.java | 91 +++++++++++++++---- 6 files changed, 128 insertions(+), 34 deletions(-) create mode 100644 zeus-driver/src/main/resources/api-json/trigger/trigger.update.ftl diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java index 7006ad99..4ee04c91 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java @@ -22,7 +22,8 @@ public class ProductEventExpression extends Model { @Id @GeneratedValue(generator = IdTypeConsts.ID_SNOW) - private Long eventExpId; + private Long eventExpId; + private Long eventRuleId; private String function; private String scope; diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java index 21264463..db9b7fbe 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java @@ -35,15 +35,13 @@ String triggerCreate(@ParamName("triggerName") String triggerName, * 更新告警触发器 * * @param triggerId 触发器ID - * @param triggerName 触发器名称 * @param expression 触发器 表达式 * @param ruleLevel 告警等级 * @return */ @Post @JsonPath("/trigger/trigger.update") - String triggerUpdate(@ParamName("triggerId") Long triggerId, - @ParamName("triggerName") String triggerName, + String triggerUpdate(@ParamName("triggerId") Integer triggerId, @ParamName("expression") String expression, @ParamName("ruleLevel") Byte ruleLevel); @@ -57,6 +55,6 @@ String triggerUpdate(@ParamName("triggerId") Long triggerId, */ @Post @JsonPath("/trigger/trigger.tags.update") - String triggerTagCreate(@ParamName("triggerId") Long triggerId, + String triggerTagCreate(@ParamName("triggerId") Integer triggerId, @ParamName("tagMap") Map tags); } diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.update.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.update.ftl new file mode 100644 index 00000000..e520f230 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.update.ftl @@ -0,0 +1,11 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.update", + "params": { + "triggerid": "${triggerId}", + "expression": "${expression}", + "priority" : ${ruleLevel} + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java index 169c8bda..0c94912f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java @@ -2,6 +2,8 @@ import cn.hutool.core.util.IdUtil; import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.query.QProductEvent; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.web.product.dto.ProductEventDto; @@ -9,6 +11,7 @@ import com.zmops.iot.web.product.dto.param.EventParm; import com.zmops.iot.web.product.service.EventRuleService; import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; import io.ebean.annotation.Transactional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; @@ -71,7 +74,7 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE //step 3: zbx 触发器创建 Tag if (eventRule.getTags() != null) { - zbxTrigger.triggerTagCreate(Long.valueOf(triggerId), eventRule.getTags()); + zbxTrigger.triggerTagCreate(Integer.valueOf(triggerId), eventRule.getTags()); } //step 4: 更新 zbxId @@ -92,8 +95,23 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) ProductEventRule eventRule) { + //step 1: 更新所有服务 + eventRuleService.updateProductEventRule(eventRule.getEventRuleId(), eventRule); - return ResponseData.success(); + //step 2: 更新zbx表达式 + String expression = eventRule.getExpList() + .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); + + ProductEvent event = new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).findOne(); + if (null != event) { + zbxTrigger.triggerUpdate(event.getZbxId(), expression, eventRule.getEventLevel()); + + if (eventRule.getTags() != null) { + zbxTrigger.triggerTagCreate(event.getZbxId(), eventRule.getTags()); + } + } + + return ResponseData.success(eventRule.getEventRuleId()); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java index 490a8baa..83691f59 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java @@ -21,25 +21,26 @@ @Setter public class ProductEventRule { - private String eventRuleId; + @NotNull(groups = BaseEntity.Update.class) + private Long eventRuleId; - @NotNull(groups = BaseEntity.Create.class) + @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private Byte eventNotify; // 0 否 1 是,默认 1 // 告警规则名称 - @NotBlank(groups = BaseEntity.Create.class) + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private String eventRuleName; // 告警规则级别 - @NotNull(groups = BaseEntity.Create.class) + @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private Byte eventLevel; // 表达式列表 @Valid - @NotEmpty(groups = BaseEntity.Create.class) + @NotEmpty(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private List expList; - @NotBlank(groups = BaseEntity.Create.class) + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private String expLogic; // and or private String remark; @@ -48,27 +49,33 @@ public class ProductEventRule { private Map tags; + @NotNull(groups = BaseEntity.Update.class) + private Integer zbxId; + @Getter @Setter // 告警表达式 构成 public static class Expression { - @NotBlank(groups = BaseEntity.Create.class) + @NotNull(groups = BaseEntity.Update.class) + private Long eventExpId; + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private String function; // last avg max min sum change nodata private String scope; // s m h T - @NotBlank(groups = BaseEntity.Create.class) + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private String condition; // > < = <> >= <= - @NotBlank(groups = BaseEntity.Create.class) + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private String value; - @NotNull(groups = BaseEntity.Create.class) + @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private String productAttrKey; // 产品属性 Key - @NotBlank(groups = BaseEntity.Create.class) + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private String productId; // 产品ID @Override diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java index f00ebdc3..72d4fdab 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java @@ -20,7 +20,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Map; /** * @author nantian created at 2021/9/15 13:59 @@ -43,29 +42,16 @@ public class EventRuleService { */ public void createProductEventRule(Long eventRuleId, ProductEventRule eventRule) { // step 1: 保存产品告警规则 - ProductEvent event = new ProductEvent(); + ProductEvent event = initEventRule(eventRule); event.setEventRuleId(eventRuleId); - event.setEventLevel(eventRule.getEventLevel()); - event.setExpLogic(eventRule.getExpLogic()); - event.setEventNotify(eventRule.getEventNotify()); - event.setRemark(eventRule.getRemark()); - event.setEventRuleName(eventRule.getEventRuleName()); - event.setStatus(CommonStatus.ENABLE.getCode()); - DB.save(event); //step 2: 保存 表达式,方便回显 List expList = new ArrayList<>(); eventRule.getExpList().forEach(i -> { - ProductEventExpression exp = new ProductEventExpression(); + ProductEventExpression exp = initEventExpression(i); exp.setEventRuleId(eventRuleId); - exp.setCondition(i.getCondition()); - exp.setFunction(i.getFunction()); - exp.setScope(i.getScope()); - exp.setValue(i.getValue()); - exp.setProductId(i.getProductId()); - exp.setProductAttrKey(i.getProductAttrKey()); expList.add(exp); }); @@ -83,6 +69,78 @@ public void createProductEventRule(Long eventRuleId, ProductEventRule eventRule) } } + /** + * 更新触发器 + * + * @param eventRuleId 触发器ID + * @param eventRule 告警规则 + */ + public void updateProductEventRule(Long eventRuleId, ProductEventRule eventRule) { + + //step 1: 函数表达式 + DB.sqlUpdate("delete from product_event_expression where event_rule_id = :eventRuleId") + .setParameter("eventRuleId", eventRule.getEventRuleId()) + .execute(); + + //step 2: 删除服务方法调用 + DB.sqlUpdate("delete from product_event_service where event_rule_id = :eventRuleId") + .setParameter("eventRuleId", eventRule.getEventRuleId()) + .execute(); + + + // step 3: 保存产品告警规则 + ProductEvent event = initEventRule(eventRule); + event.setEventRuleId(eventRuleId); + DB.update(event); + + //step 4: 保存 表达式,方便回显 + List expList = new ArrayList<>(); + + eventRule.getExpList().forEach(i -> { + ProductEventExpression exp = initEventExpression(i); + exp.setEventRuleId(eventRuleId); + expList.add(exp); + }); + + DB.saveAll(expList); + + //step 5: 保存触发器 调用 本产品方法 + if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { + + eventRule.getDeviceServices().forEach(i -> { + DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id, service_id) values (:eventRuleId, :deviceId, :serviceId)") + .setParameter("eventRuleId", eventRuleId) + .setParameter("deviceId", i.getDeviceId()) + .setParameter("serviceId", i.getServiceId()) + .execute(); + }); + } + } + + + private ProductEvent initEventRule(ProductEventRule eventRule) { + ProductEvent event = new ProductEvent(); + event.setEventLevel(eventRule.getEventLevel()); + event.setExpLogic(eventRule.getExpLogic()); + event.setEventNotify(eventRule.getEventNotify()); + event.setRemark(eventRule.getRemark()); + event.setEventRuleName(eventRule.getEventRuleName()); + event.setStatus(CommonStatus.ENABLE.getCode()); + return event; + } + + private ProductEventExpression initEventExpression(ProductEventRule.Expression exp) { + ProductEventExpression eventExpression = new ProductEventExpression(); + eventExpression.setEventExpId(exp.getEventExpId()); + eventExpression.setCondition(exp.getCondition()); + eventExpression.setFunction(exp.getFunction()); + eventExpression.setScope(exp.getScope()); + eventExpression.setValue(exp.getValue()); + eventExpression.setProductId(exp.getProductId()); + eventExpression.setProductAttrKey(exp.getProductAttrKey()); + return eventExpression; + } + /** * 更新 触发器规则 zbxId @@ -108,6 +166,7 @@ public String createZbxTrigger(String triggerName, String expression, Byte level return JSON.parseObject(res, TriggerIds.class).getTriggerids()[0]; } + /** * 触发器 分页列表 * From dd6b062fc4ef1136cea1a0bd35354408112ed593 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 16 Sep 2021 15:36:47 +0800 Subject: [PATCH 177/763] [style]: change code style --- .../web/product/dto/ProductStatusJudgeRule.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java index 7dc91561..379d7a72 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java @@ -16,7 +16,7 @@ public class ProductStatusJudgeRule { - @NotBlank(groups = { BaseEntity.Create.class}) + @NotBlank(groups = {BaseEntity.Create.class}) private String relationId; // deviceid @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Delete.class}) @@ -28,19 +28,19 @@ public class ProductStatusJudgeRule { //##################### 下线规则 - @NotNull(groups = { BaseEntity.Create.class}) + @NotNull(groups = {BaseEntity.Create.class}) private Long attrId; // 设备属性ID - @NotBlank(groups = { BaseEntity.Create.class}) + @NotBlank(groups = {BaseEntity.Create.class}) private String ruleFunction; // nodata 或者 > < = 函数 @NotBlank(groups = {BaseEntity.Create.class}) private String ruleCondition; // 时间 或者 特定值 - @NotNull(groups = { BaseEntity.Create.class}) + @NotNull(groups = {BaseEntity.Create.class}) private String unit; //单位 s m h 或空 - @NotBlank(groups = { BaseEntity.Create.class}) + @NotBlank(groups = {BaseEntity.Create.class}) private String productAttrKey; // 属性 Key @@ -49,13 +49,13 @@ public class ProductStatusJudgeRule { @NotNull(groups = {BaseEntity.Create.class}) private Long attrIdRecovery; // 设备属性ID - @NotBlank(groups = { BaseEntity.Create.class}) + @NotBlank(groups = {BaseEntity.Create.class}) private String ruleFunctionRecovery; // nodata 或者 > < = 函数 @NotBlank(groups = {BaseEntity.Create.class}) private String ruleConditionRecovery; // 时间 或者 特定值 - @NotBlank(groups = { BaseEntity.Create.class}) + @NotBlank(groups = {BaseEntity.Create.class}) private String productAttrKeyRecovery; // 属性 Key private String unitRecovery; From 3cb715dad4f2577d9deb44dc64405d443209433c Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 16 Sep 2021 18:14:32 +0800 Subject: [PATCH 178/763] [feat]: iot-server start script --- dist-material/bin/IoTServer.bat | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dist-material/bin/IoTServer.bat b/dist-material/bin/IoTServer.bat index 299b1a6b..4627b511 100644 --- a/dist-material/bin/IoTServer.bat +++ b/dist-material/bin/IoTServer.bat @@ -17,12 +17,12 @@ @echo off setlocal -set OAP_PROCESS_TITLE=Skywalking-Collector +set OAP_PROCESS_TITLE=Zeus-IoT-Server set OAP_HOME=%~dp0%.. -set OAP_OPTS="-Xms256M -Xmx512M -Doap.logDir=%OAP_HOME%\logs" +set OAP_OPTS="-Xms1024M -Xmx1024M -Doap.logDir=%OAP_HOME%\logs" set CLASSPATH=%OAP_HOME%\config;.; -set CLASSPATH=%OAP_HOME%\oap-libs\*;%CLASSPATH% +set CLASSPATH=%OAP_HOME%\iot-server-libs\*;%CLASSPATH% if defined JAVA_HOME ( set _EXECJAVA="%JAVA_HOME%\bin\java" @@ -33,5 +33,5 @@ if not defined JAVA_HOME ( set _EXECJAVA=java ) -start "%OAP_PROCESS_TITLE%" %_EXECJAVA% "%OAP_OPTS%" -cp "%CLASSPATH%" org.apache.skywalking.oap.server.starter.OAPServerStartUp +start "%OAP_PROCESS_TITLE%" %_EXECJAVA% "%OAP_OPTS%" -cp "%CLASSPATH%" com.zmops.zeus.iot.server.starter.IOTServerStartUp endlocal From fc5df523ab93def0b1c525937a3c77b51572db77 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 16 Sep 2021 19:51:43 +0800 Subject: [PATCH 179/763] [feat]: product event trigger --- .../iot/domain/product/ProductEvent.java | 1 - .../product/ProductEventExpression.java | 3 +- .../domain/product/ProductEventRelation.java | 30 ++++++++++ .../domain/product/ProductEventService.java | 22 +++++++ .../zmops/zeus/driver/service/ZbxTrigger.java | 22 ++++++- .../api-json/trigger/trigger.get.ftl | 16 +++++ .../device/service/work/SaveOtherWorker.java | 36 +++++++++++- .../controller/ProductEventController.java | 50 ++++++++++++---- .../controller/ProductServiceController.java | 8 +++ .../iot/web/product/dto/ProductEventRule.java | 2 + .../web/product/service/EventRuleService.java | 58 ++++++++++++++++--- .../product/service/ProductSvcService.java | 13 +++++ 12 files changed, 237 insertions(+), 24 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventService.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java index 30355691..d2d50ce5 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java @@ -26,6 +26,5 @@ public class ProductEvent extends BaseEntity { private String expLogic; private String remark; private Byte eventNotify; - private Integer zbxId; private String status; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java index 4ee04c91..f60cbec5 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java @@ -29,6 +29,7 @@ public class ProductEventExpression extends Model { private String scope; private String condition; private String value; - private String productId; + private String deviceId; private String productAttrKey; + private String unit; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java new file mode 100644 index 00000000..0366a5e0 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java @@ -0,0 +1,30 @@ +package com.zmops.iot.domain.product; + +import lombok.*; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author nantian created at 2021/8/11 17:02 + */ + +@Getter +@Setter +@Entity +@Table(name = "product_event_relation") +public class ProductEventRelation { + + @Id + private Long id; + + private Long eventRuleId; + + private String relationId; + + private String zbxId; + + private String inherit; + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventService.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventService.java new file mode 100644 index 00000000..5b051b4c --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventService.java @@ -0,0 +1,22 @@ +package com.zmops.iot.domain.product; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "product_event_service") +public class ProductEventService { + + private Long eventRuleId; + private Long serviceId; + private String deviceId; + private String executeDeviceId; +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java index db9b7fbe..25cdad74 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java @@ -41,7 +41,7 @@ String triggerCreate(@ParamName("triggerName") String triggerName, */ @Post @JsonPath("/trigger/trigger.update") - String triggerUpdate(@ParamName("triggerId") Integer triggerId, + String triggerUpdate(@ParamName("triggerId") String triggerId, @ParamName("expression") String expression, @ParamName("ruleLevel") Byte ruleLevel); @@ -55,6 +55,24 @@ String triggerUpdate(@ParamName("triggerId") Integer triggerId, */ @Post @JsonPath("/trigger/trigger.tags.update") - String triggerTagCreate(@ParamName("triggerId") Integer triggerId, + String triggerTagCreate(@ParamName("triggerId") String triggerId, @ParamName("tagMap") Map tags); + + /** + * 根据TRIGGER ID查询触发器 + * + * @param triggerIds 触发器IDs + */ + @Post + @JsonPath("/trigger/trigger.get") + String triggerGet(@ParamName("triggerIds") String triggerIds); + + /** + * 根据host 查询触发器 + * + * @param host 设备ID + */ + @Post + @JsonPath("/trigger/trigger.get") + String triggerGetByHost(@ParamName("host") String host); } diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl index e69de29b..69350dd5 100644 --- a/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl @@ -0,0 +1,16 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.get", + "params": { + "selectHosts":["host"], + <#if triggerids??> + "triggerids":[${triggerids}], + + <#if host??> + "host":${host}, + + "output": "extend" + }, + "id": 1, + "auth": "${userAuth}" +} \ No newline at end of file diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java index 8b42d95a..34f5724c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java @@ -1,18 +1,28 @@ package com.zmops.iot.web.device.service.work; +import com.alibaba.fastjson.JSONObject; import com.zmops.iot.async.callback.IWorker; import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventService; import com.zmops.iot.domain.product.query.QProductServiceRelation; import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.product.service.EventRuleService; +import com.zmops.zeus.driver.service.ZbxTrigger; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; /** * @author yefei @@ -23,6 +33,9 @@ @Component public class SaveOtherWorker implements IWorker { + @Autowired + ZbxTrigger zbxTrigger; + @Override public Boolean action(DeviceDto deviceDto, Map> allWrappers) { log.debug("处理 其它 工作…………"); @@ -38,8 +51,13 @@ public Boolean action(DeviceDto deviceDto, Map> allW } //删除服务关联 new QProductServiceRelation().relationId.eq(deviceId).delete(); - //删除上下线规则关联 + //删除 上下线规则关联 new QProductStatusFunctionRelation().relationId.eq(deviceId).delete(); + //删除 告警规则关联 + new QProductEventRelation().relationId.eq(deviceId).delete(); + //删除 告警执行动作关联 + new QProductEventService().deviceId.eq(deviceId).delete(); + } else { //创建 Device device = (Device) allWrappers.get("saveDvice").getWorkResult().getResult(); @@ -54,6 +72,22 @@ public Boolean action(DeviceDto deviceDto, Map> allW DB.sqlUpdate("insert into product_status_function_relation (relation_id,rule_id,inherit) SELECT :deviceId,rule_id,1 from product_status_function_relation where relation_id=:relationId") .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId()).execute(); + //告警规则关联 并 回填zbx triggerId + List triggers = JSONObject.parseArray(zbxTrigger.triggerGet(deviceId), EventRuleService.Triggers.class); + Map map = triggers.parallelStream().collect(Collectors.toMap(EventRuleService.Triggers::getDescription, EventRuleService.Triggers::getTriggerid)); + List productEventRelationList = new QProductEventRelation().relationId.eq(deviceDto.getProductId() + "").findList(); + for (ProductEventRelation productEventRelation : productEventRelationList) { + productEventRelation.setId(null); + productEventRelation.setRelationId(deviceId); + productEventRelation.setInherit("1"); + productEventRelation.setZbxId(Optional.ofNullable(map.get(productEventRelation.getEventRuleId())).orElse("")); + } + DB.saveAll(productEventRelationList); + //告警执行动作关联 + DB.sqlUpdate("insert into product_event_service (service_id,device_id,execute_device_id,event_rule_id,inherit) SELECT service_id,:deviceId,:executeDeviceId,event_rule_id,1 from product_event_service where relation_id=:relationId") + .setParameter("deviceId", deviceId).setParameter("executeDeviceId", deviceId).setParameter("relationId", deviceDto.getProductId()).execute(); + + return true; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java index 0c94912f..778a1a74 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java @@ -3,15 +3,17 @@ import cn.hutool.core.util.IdUtil; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.ProductEventRelation; import com.zmops.iot.domain.product.query.QProductEvent; +import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.product.dto.ProductEventDto; import com.zmops.iot.web.product.dto.ProductEventRule; import com.zmops.iot.web.product.dto.param.EventParm; import com.zmops.iot.web.product.service.EventRuleService; import com.zmops.zeus.driver.service.ZbxTrigger; -import io.ebean.DB; import io.ebean.annotation.Transactional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; @@ -20,6 +22,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; /** @@ -39,6 +43,10 @@ public class ProductEventController { @Autowired private ZbxTrigger zbxTrigger; + private static final String ALARM_TAG_NAME = "__alarm__"; + private static final String EXECUTE_TAG_NAME = "__execute__"; + + /** * 触发器 分页列表 * @@ -70,15 +78,23 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); //step 2: zbx 保存触发器 - String triggerId = eventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); + String[] triggerIds = eventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); - //step 3: zbx 触发器创建 Tag - if (eventRule.getTags() != null) { - zbxTrigger.triggerTagCreate(Integer.valueOf(triggerId), eventRule.getTags()); + //step 4: zbx 触发器创建 Tag + Map tags = eventRule.getTags(); + if (tags == null || !tags.containsKey(ALARM_TAG_NAME)) { + tags.put(ALARM_TAG_NAME, eventRule.getEventRuleId() + ""); + } + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { + tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); + } + for (String triggerId : triggerIds) { + zbxTrigger.triggerTagCreate(triggerId, tags); } - //step 4: 更新 zbxId - eventRuleService.updateProductEventRuleZbxId(eventRuleId, Integer.valueOf(triggerId)); + + //step 5: 更新 zbxId + eventRuleService.updateProductEventRuleZbxId(eventRuleId, triggerIds); // 返回触发器ID return ResponseData.success(eventRuleId); @@ -102,13 +118,23 @@ public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseE String expression = eventRule.getExpList() .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); + ProductEvent event = new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).findOne(); if (null != event) { - zbxTrigger.triggerUpdate(event.getZbxId(), expression, eventRule.getEventLevel()); - - if (eventRule.getTags() != null) { - zbxTrigger.triggerTagCreate(event.getZbxId(), eventRule.getTags()); - } + List list = new QProductEventRelation().eventRuleId.eq(event.getEventRuleId()).findList(); + list.forEach(productEventRelation -> { + zbxTrigger.triggerUpdate(productEventRelation.getZbxId(), expression, eventRule.getEventLevel()); + + //step 3: zbx 触发器创建 Tag + Map tags = eventRule.getTags(); + if (tags == null || !tags.containsKey(ALARM_TAG_NAME)) { + tags.put(ALARM_TAG_NAME, eventRule.getEventRuleId() + ""); + } + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { + tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); + } + zbxTrigger.triggerTagCreate(productEventRelation.getZbxId(), tags); + }); } return ResponseData.success(eventRule.getEventRuleId()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java index c5729675..d9f13062 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java @@ -10,6 +10,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** @@ -41,6 +42,13 @@ public ResponseData list(@RequestBody ProductSvcParam productSvcParam) { return ResponseData.success(productSvcService.list(productSvcParam)); } + /** + * 根据服务 获取参数列表 + */ + @RequestMapping("/param/list") + public ResponseData paramList(@RequestParam("serviceId") long serviceId) { + return ResponseData.success(productSvcService.paramList(serviceId)); + } /** * 服务创建 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java index 83691f59..5f5a0ee8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java @@ -78,6 +78,8 @@ public static class Expression { @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private String productId; // 产品ID + private String unit; + @Override public String toString() { StringBuilder expression = new StringBuilder(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java index 72d4fdab..7725996f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java @@ -1,10 +1,13 @@ package com.zmops.iot.web.product.service; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.ProductEventExpression; +import com.zmops.iot.domain.product.ProductEventRelation; import com.zmops.iot.domain.product.query.QProductEvent; import com.zmops.iot.domain.product.query.QProductEventExpression; +import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; @@ -19,7 +22,10 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @author nantian created at 2021/9/15 13:59 @@ -67,6 +73,17 @@ public void createProductEventRule(Long eventRuleId, ProductEventRule eventRule) .execute(); }); } + + //step 4: 保存关联关系 + List relationIds = eventRule.getExpList().parallelStream().map(ProductEventRule.Expression::getProductId).distinct().collect(Collectors.toList()); + List lists = new ArrayList<>(); + relationIds.forEach(relationId -> { + ProductEventRelation productEventRelation = new ProductEventRelation(); + productEventRelation.setEventRuleId(eventRuleId); + productEventRelation.setRelationId(relationId); + }); + + } /** @@ -136,8 +153,9 @@ private ProductEventExpression initEventExpression(ProductEventRule.Expression e eventExpression.setFunction(exp.getFunction()); eventExpression.setScope(exp.getScope()); eventExpression.setValue(exp.getValue()); - eventExpression.setProductId(exp.getProductId()); + eventExpression.setDeviceId(exp.getProductId()); eventExpression.setProductAttrKey(exp.getProductAttrKey()); + eventExpression.setUnit(exp.getUnit()); return eventExpression; } @@ -148,8 +166,21 @@ private ProductEventExpression initEventExpression(ProductEventRule.Expression e * @param triggerId 规则ID * @param zbxId triggerId */ - public void updateProductEventRuleZbxId(Long triggerId, Integer zbxId) { - DB.update(ProductEvent.class).where().eq("eventRuleId", triggerId).asUpdate().set("zbxId", zbxId).update(); + public void updateProductEventRuleZbxId(Long triggerId, String[] zbxId) { + + List triggers = JSONObject.parseArray(zbxTrigger.triggerGet(Arrays.toString(zbxId)), Triggers.class); + + Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.host, Triggers::getTriggerid)); + + List productEventRelationList = new QProductEventRelation().eventRuleId.eq(triggerId).findList(); + + productEventRelationList.forEach(productEventRelation -> { + if (null != map.get(productEventRelation.getRelationId())) { + DB.update(ProductEventRelation.class).where().eq("ruleId", triggerId).eq("relationId", productEventRelation.getRelationId()) + .asUpdate().set("zbxId", map.get(productEventRelation.getRelationId())).update(); + } + }); + } @@ -161,9 +192,9 @@ public void updateProductEventRuleZbxId(Long triggerId, Integer zbxId) { * @param level 告警等级 * @return 触发器ID */ - public String createZbxTrigger(String triggerName, String expression, Byte level) { + public String[] createZbxTrigger(String triggerName, String expression, Byte level) { String res = zbxTrigger.triggerCreate(triggerName, expression, level); - return JSON.parseObject(res, TriggerIds.class).getTriggerids()[0]; + return JSON.parseObject(res, TriggerIds.class).getTriggerids(); } @@ -181,8 +212,8 @@ public Pager getEventByPage(EventParm eventParm) { } if (ToolUtil.isNotEmpty(eventParm.getProdId())) { - List eventRuleIdList = new QProductEventExpression().select(QProductEventExpression.alias().eventRuleId) - .productId.eq(eventParm.getProdId()).findSingleAttributeList(); + List eventRuleIdList = new QProductEventRelation().select(QProductEventRelation.alias().eventRuleId) + .relationId.eq(eventParm.getProdId()).findSingleAttributeList(); if (ToolUtil.isNotEmpty(eventRuleIdList)) { query.eventRuleId.in(eventRuleIdList); @@ -200,4 +231,17 @@ public Pager getEventByPage(EventParm eventParm) { static class TriggerIds { private String[] triggerids; } + + @Data + public static class Triggers { + private String triggerid; + private String description; + private Hosts hosts; + } + + @Data + static class Hosts { + private String hostid; + private String host; + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index a9418bf7..60474674 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -105,6 +105,12 @@ public List list(ProductSvcParam productSvcParam) { if (ToolUtil.isNotEmpty(productSvcParam.getName())) { qProdService.name.contains(productSvcParam.getName()); } + if (ToolUtil.isNotEmpty(productSvcParam.getProdId())) { + List serviceIds = getServiceIdList(productSvcParam.getProdId()); + if (ToolUtil.isNotEmpty(serviceIds)) { + qProdService.id.in(serviceIds); + } + } if (ToolUtil.isNotEmpty(productSvcParam.getMark())) { qProdService.mark.contains(productSvcParam.getMark()); } @@ -204,4 +210,11 @@ public void delete(List ids) { new QProductServiceRelation().serviceId.in(ids).delete(); new QProductService().id.in(ids).delete(); } + + /** + * 根据服务 获取参数列表 + */ + public List paramList(long serviceId) { + return new QProductServiceParam().serviceId.eq(serviceId).findList(); + } } From bf791dce9a9a7005df983f48745472c7e27c3415 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 16 Sep 2021 20:06:11 +0800 Subject: [PATCH 180/763] [style]: change code style --- .../com/zmops/iot/web/product/service/EventRuleService.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java index 72d4fdab..087daa0a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java @@ -87,7 +87,6 @@ public void updateProductEventRule(Long eventRuleId, ProductEventRule eventRule) .setParameter("eventRuleId", eventRule.getEventRuleId()) .execute(); - // step 3: 保存产品告警规则 ProductEvent event = initEventRule(eventRule); event.setEventRuleId(eventRuleId); @@ -106,7 +105,6 @@ public void updateProductEventRule(Long eventRuleId, ProductEventRule eventRule) //step 5: 保存触发器 调用 本产品方法 if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { - eventRule.getDeviceServices().forEach(i -> { DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id, service_id) values (:eventRuleId, :deviceId, :serviceId)") .setParameter("eventRuleId", eventRuleId) From 6def62b38ddd512c747ddce3c709071f8fe9dc0f Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 16 Sep 2021 20:17:33 +0800 Subject: [PATCH 181/763] [fix]: product event trigger fix --- .../java/com/zmops/iot/web/product/dto/ProductEventRule.java | 2 ++ .../com/zmops/iot/web/product/service/EventRuleService.java | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java index 5f5a0ee8..d7c42b8a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java @@ -105,6 +105,8 @@ public static class DeviceService { private Long deviceId; + private Long executeDeviceId; + private Long serviceId; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java index 7725996f..8cf2d78f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java @@ -66,9 +66,10 @@ public void createProductEventRule(Long eventRuleId, ProductEventRule eventRule) //step 3: 保存触发器 调用 本产品方法 if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { eventRule.getDeviceServices().forEach(i -> { - DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id, service_id) values (:eventRuleId, :deviceId, :serviceId)") + DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") .setParameter("eventRuleId", eventRuleId) - .setParameter("deviceId", i.getDeviceId()) + .setParameter("deviceId", eventRuleId) + .setParameter("executeDeviceId", i.getExecuteDeviceId()) .setParameter("serviceId", i.getServiceId()) .execute(); }); From 2e1f117cf71e86dad145f6aa0729f77a775a61df Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 16 Sep 2021 20:59:45 +0800 Subject: [PATCH 182/763] [fix]: fix device relation work --- .../iot/web/device/service/DeviceService.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index da888ab0..00a3c444 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -57,6 +57,9 @@ public class DeviceService { @Autowired private UpdateDeviceZbxIdWorker updateDeviceZbxIdWorker; + @Autowired + private SaveOtherWorker saveOtherWorker; + @Autowired private ZbxHost zbxHost; @@ -203,6 +206,10 @@ public String create(DeviceDto deviceDto) { .worker(updateDeviceZbxIdWorker) .build(); + WorkerWrapper saveOtherWork = WorkerWrapper.builder().id("saveOtherWork") + .worker(saveOtherWorker).param(deviceDto) + .build(); + WorkerWrapper saveZbxHostWork = WorkerWrapper.builder().id("saveZbxHostWork") .worker(saveZbxHostWorker).param(deviceDto) .nextOf(updateAttrZbxIdWork, updateDeviceZbxIdWork) @@ -210,7 +217,7 @@ public String create(DeviceDto deviceDto) { WorkerWrapper deviceWork = WorkerWrapper.builder().id("saveDvice") .worker(saveDeviceWorker).param(deviceDto) - .nextOf(saveTagWork, saveAttributeWork, saveDeviceGrpWork, saveZbxHostWork) + .nextOf(saveTagWork, saveAttributeWork, saveDeviceGrpWork, saveOtherWork, saveZbxHostWork) .build(); try { @@ -251,6 +258,10 @@ public String update(DeviceDto deviceDto) { .worker(updateAttrZbxIdWorker) .build(); + WorkerWrapper saveOtherWork = WorkerWrapper.builder().id("saveOtherWork") + .worker(saveOtherWorker).param(deviceDto) + .build(); + WorkerWrapper saveZbxHostWork = WorkerWrapper.builder().id("saveZbxHostWork") .worker(saveZbxHostWorker).param(deviceDto) .nextOf(updateAttrZbxIdWork) @@ -258,7 +269,7 @@ public String update(DeviceDto deviceDto) { WorkerWrapper deviceWork = WorkerWrapper.builder().id("saveDvice") .worker(saveDeviceWorker).param(deviceDto) - .nextOf(saveTagWork, saveAttributeWork, saveDeviceGrpWork, saveZbxHostWork) + .nextOf(saveTagWork, saveAttributeWork, saveDeviceGrpWork, saveOtherWork, saveZbxHostWork) .build(); try { From fe7dd7c9e9e76314d441b19f8088a88f0577b812 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 16 Sep 2021 21:31:06 +0800 Subject: [PATCH 183/763] [fix]: fix device relation --- .../main/resources/api-json/trigger/trigger.get.ftl | 12 ++++++------ .../zmops/iot/web/device/service/DeviceService.java | 4 ++-- .../iot/web/device/service/work/SaveOtherWorker.java | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl index 69350dd5..08feb1d5 100644 --- a/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl @@ -3,12 +3,12 @@ "method": "trigger.get", "params": { "selectHosts":["host"], - <#if triggerids??> - "triggerids":[${triggerids}], - - <#if host??> - "host":${host}, - + <#if triggerids??> + "triggerids":${triggerids}, + + <#if host??> + "host":"${host}", + "output": "extend" }, "id": 1, diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 00a3c444..2e7e8df7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -274,7 +274,7 @@ public String update(DeviceDto deviceDto) { try { - Async.work(3000, deviceWork).awaitFinish(); + Async.work(10000, deviceWork).awaitFinish(); } catch (Exception e) { e.printStackTrace(); } @@ -334,7 +334,7 @@ public String delete(DeviceDto deviceDto) { try { - Async.work(3000, delDeviceWork).awaitFinish(); + Async.work(10000, delDeviceWork).awaitFinish(); } catch (Exception e) { e.printStackTrace(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java index 34f5724c..abdeb09f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java @@ -66,14 +66,14 @@ public Boolean action(DeviceDto deviceDto, Map> allW //服务关联 DB.sqlUpdate("insert into product_service_relation (relation_id,service_id,inherit) SELECT :deviceId,service_id,1 from product_service_relation where relation_id=:relationId") - .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId()).execute(); + .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "").execute(); //上下线规则关联 DB.sqlUpdate("insert into product_status_function_relation (relation_id,rule_id,inherit) SELECT :deviceId,rule_id,1 from product_status_function_relation where relation_id=:relationId") - .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId()).execute(); + .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "").execute(); //告警规则关联 并 回填zbx triggerId - List triggers = JSONObject.parseArray(zbxTrigger.triggerGet(deviceId), EventRuleService.Triggers.class); + List triggers = JSONObject.parseArray(zbxTrigger.triggerGetByHost(deviceId), EventRuleService.Triggers.class); Map map = triggers.parallelStream().collect(Collectors.toMap(EventRuleService.Triggers::getDescription, EventRuleService.Triggers::getTriggerid)); List productEventRelationList = new QProductEventRelation().relationId.eq(deviceDto.getProductId() + "").findList(); for (ProductEventRelation productEventRelation : productEventRelationList) { @@ -85,7 +85,7 @@ public Boolean action(DeviceDto deviceDto, Map> allW DB.saveAll(productEventRelationList); //告警执行动作关联 DB.sqlUpdate("insert into product_event_service (service_id,device_id,execute_device_id,event_rule_id,inherit) SELECT service_id,:deviceId,:executeDeviceId,event_rule_id,1 from product_event_service where relation_id=:relationId") - .setParameter("deviceId", deviceId).setParameter("executeDeviceId", deviceId).setParameter("relationId", deviceDto.getProductId()).execute(); + .setParameter("deviceId", deviceId).setParameter("executeDeviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "").execute(); return true; From 4cb2c27021e248bb5d1b80f893a4947c47b910a1 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 16 Sep 2021 21:40:43 +0800 Subject: [PATCH 184/763] [fix]: delete device relation --- .../iot/web/device/service/DeviceService.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 2e7e8df7..51cbc7f0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -10,8 +10,7 @@ import com.zmops.iot.domain.device.query.QDevicesGroups; import com.zmops.iot.domain.device.query.QTag; import com.zmops.iot.domain.product.Product; -import com.zmops.iot.domain.product.query.QProduct; -import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.domain.product.query.*; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; @@ -222,7 +221,7 @@ public String create(DeviceDto deviceDto) { try { - Async.work(3000, deviceWork).awaitFinish(); + Async.work(10000, deviceWork).awaitFinish(); } catch (Exception e) { e.printStackTrace(); } @@ -325,16 +324,24 @@ public String delete(DeviceDto deviceDto) { return true; }).param(zbxId).build(); + WorkerWrapper delOtherWork = WorkerWrapper.builder().id("delOtherWork") + .worker((deviceId, allWrappers) -> { + new QProductServiceRelation().relationId.eq(deviceId).delete(); + new QProductEventRelation().relationId.eq(deviceId).delete(); + new QProductEventService().deviceId.eq(deviceId).delete(); + return true; + }).param(zbxId).build(); + WorkerWrapper delDeviceWork = WorkerWrapper.builder().id("delDeviceWork") .worker((deviceId, allWrappers) -> { new QDevice().deviceId.eq(deviceId).delete(); return true; }).param(deviceDto.getDeviceId()) - .nextOf(delTagWork, delAttrWork, delGropusWork, delZbxWork).build(); + .nextOf(delTagWork, delAttrWork, delGropusWork, delZbxWork,delOtherWork).build(); try { - Async.work(10000, delDeviceWork).awaitFinish(); + Async.work(5000, delDeviceWork).awaitFinish(); } catch (Exception e) { e.printStackTrace(); } From 3172ab8dae48295afbf65ef746d99ce8694a2a40 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 16 Sep 2021 21:51:13 +0800 Subject: [PATCH 185/763] [fix]: delete device realation --- .../java/com/zmops/iot/web/device/service/DeviceService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 51cbc7f0..d65afe84 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -326,6 +326,7 @@ public String delete(DeviceDto deviceDto) { WorkerWrapper delOtherWork = WorkerWrapper.builder().id("delOtherWork") .worker((deviceId, allWrappers) -> { + new QProductStatusFunctionRelation().relationId.eq(deviceId).delete(); new QProductServiceRelation().relationId.eq(deviceId).delete(); new QProductEventRelation().relationId.eq(deviceId).delete(); new QProductEventService().deviceId.eq(deviceId).delete(); From f7f9b6469a578cd57ddd421cb11ba857758f5e1f Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 16 Sep 2021 23:11:18 +0800 Subject: [PATCH 186/763] [fix]: fix history data date --- .../web/analyse/service/HistoryService.java | 38 ++++++++++++++++--- .../iot/web/device/service/DeviceService.java | 2 +- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java index cffde152..9b5df149 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java @@ -15,6 +15,7 @@ import org.springframework.stereotype.Service; import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -34,11 +35,38 @@ public class HistoryService { public Pager queryHistory(HistoryParam historyParam) { List latestDtos = queryHistory(historyParam.getDeviceId(), historyParam.getAttrIds(), - LocalDateTimeUtils.getSecondsByStr(historyParam.getTimeFrom()), - LocalDateTimeUtils.getSecondsByStr(historyParam.getTimeTill())); + dateTransfer(historyParam.getTimeFrom()), + dateTransfer(historyParam.getTimeTill())); List collect = latestDtos.stream().skip((historyParam.getPage() - 1) * historyParam.getMaxRow()) .limit(historyParam.getMaxRow()).collect(Collectors.toList()); - return new Pager<>(collect,latestDtos.size()); + return new Pager<>(collect, latestDtos.size()); + } + + private long dateTransfer(String date) { + LocalDateTime now = LocalDateTime.now(); + if (ToolUtil.isEmpty(date)) { + return LocalDateTimeUtils.getSecondsByTime(now); + } + if (date.startsWith("now-")) { + String value = date.substring(date.indexOf("-") + 1, date.length() - 1); + String unit = date.substring(date.length() - 1); + switch (unit) { + case "m": + return LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.minu(now, Integer.valueOf(value), ChronoUnit.MINUTES)); + case "d": + return LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.minu(now, Integer.valueOf(value), ChronoUnit.DAYS)); + case "M": + return LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.minu(now, Integer.valueOf(value), ChronoUnit.MONTHS)); + case "h": + return LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.minu(now, Integer.valueOf(value), ChronoUnit.HOURS)); + case "y": + return LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.minu(now, Integer.valueOf(value), ChronoUnit.YEARS)); + default: + return LocalDateTimeUtils.getSecondsByTime(now); + } + } else { + return LocalDateTimeUtils.getSecondsByStr(date); + } } public List queryHistory(String deviceId, List attrIds, Long timeFrom, Long timeTill) { @@ -66,7 +94,7 @@ public List queryHistory(String deviceId, List attrIds, Long ti } //根据属性值类型 分组查询历史数据 for (Map.Entry> map : valueTypeMap.entrySet()) { - latestDtos.addAll(queryHitoryData(one.getZbxId(), zbxIds,1000, Integer.parseInt(map.getKey()), timeFrom, timeTill)); + latestDtos.addAll(queryHitoryData(one.getZbxId(), zbxIds, 1000, Integer.parseInt(map.getKey()), timeFrom, timeTill)); } latestDtos.forEach(latestDto -> { @@ -81,7 +109,7 @@ public List queryHistory(String deviceId, List attrIds, Long ti return latestDtos; } - public List queryHitoryData(String hostId, List itemIds,int hisNum, Integer valueType, Long timeFrom, Long timeTill) { + public List queryHitoryData(String hostId, List itemIds, int hisNum, Integer valueType, Long timeFrom, Long timeTill) { String res = zbxHistoryGet.historyGet(hostId, itemIds, hisNum, valueType, timeFrom, timeTill); return JSONObject.parseArray(res, LatestDto.class); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index d65afe84..f33f6aed 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -331,7 +331,7 @@ public String delete(DeviceDto deviceDto) { new QProductEventRelation().relationId.eq(deviceId).delete(); new QProductEventService().deviceId.eq(deviceId).delete(); return true; - }).param(zbxId).build(); + }).param(deviceDto.getDeviceId()).build(); WorkerWrapper delDeviceWork = WorkerWrapper.builder().id("delDeviceWork") .worker((deviceId, allWrappers) -> { From 1d67232d40eb5e0a9af08c3072c660e036625d53 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 16 Sep 2021 23:23:34 +0800 Subject: [PATCH 187/763] [fix]: fix history data date --- .../java/com/zmops/iot/web/analyse/service/HistoryService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java index 9b5df149..6d98c3df 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java @@ -44,7 +44,7 @@ public Pager queryHistory(HistoryParam historyParam) { private long dateTransfer(String date) { LocalDateTime now = LocalDateTime.now(); - if (ToolUtil.isEmpty(date)) { + if (ToolUtil.isEmpty(date) || date.equals("now")) { return LocalDateTimeUtils.getSecondsByTime(now); } if (date.startsWith("now-")) { From 4976b4ae0e6fa548fe35d8538246edcbf9c03710 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 17 Sep 2021 10:10:51 +0800 Subject: [PATCH 188/763] [fix]: server collection rate fix --- .../zmops/iot/web/analyse/service/HomeService.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index d2945170..f81e5be0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -68,9 +68,11 @@ public List> collectionRate(long timeFrom, long timeTill) { return Collections.emptyList(); } } - List itemIds = new ArrayList<>(ITEM_Map.keySet()); - List latestDtos = historyService.queryHitoryData(hostId, itemIds, 100000, 0, timeFrom, timeTill); - Collections.reverse(latestDtos); + List latestDtos = new ArrayList<>(); + ITEM_Map.forEach((key, value) -> { + latestDtos.addAll(historyService.queryHitoryData(hostId, Collections.singletonList(key), 10000, 0, timeFrom, timeTill)); + }); + latestDtos.forEach(latestDto -> { latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd")); if (null != ITEM_Map.get(latestDto.getItemid())) { @@ -90,8 +92,9 @@ public List> collectionRate(long timeFrom, long timeTill) { valMap.put("val", val); tmpList.add(valMap); }); + List> dataList = tmpList.parallelStream().sorted(Comparator.comparing(o -> o.get("date").toString())).collect(Collectors.toList()); collectMap.put("name", ValueType.getVal(key)); - collectMap.put("data", tmpList); + collectMap.put("data", dataList); collectList.add(collectMap); }); From c3c3ad2017eb8e3a9e9fca30d9c70442949acabc Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 17 Sep 2021 10:51:43 +0800 Subject: [PATCH 189/763] [feat]: product event trigger delete --- .../controller/ProductEventController.java | 26 +++++++++++++++++++ .../iot/web/product/dto/ProductEventRule.java | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java index 778a1a74..55ac8615 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java @@ -5,7 +5,9 @@ import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.ProductEventRelation; import com.zmops.iot.domain.product.query.QProductEvent; +import com.zmops.iot.domain.product.query.QProductEventExpression; import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventService; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.util.ToolUtil; @@ -140,4 +142,28 @@ public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseE return ResponseData.success(eventRule.getEventRuleId()); } + /** + * 删除 触发器 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ + @Transactional + @PostMapping("/delete") + public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseEntity.Delete.class) + ProductEventRule eventRule) { + //step 1:删除 与产品 设备的关联 + new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 2:删除 关联的执行服务 + new QProductEventService().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 3:删除 关联的表达式 + new QProductEventExpression().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 4:删除 触发器 + new QProductEventService().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + return ResponseData.success(); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java index d7c42b8a..e5eacbcf 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java @@ -21,7 +21,7 @@ @Setter public class ProductEventRule { - @NotNull(groups = BaseEntity.Update.class) + @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Delete.class}) private Long eventRuleId; @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) From 5997d4b72f259cb3d5c0c5e93592c2567498e6b0 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 17 Sep 2021 11:14:49 +0800 Subject: [PATCH 190/763] [feat]: device event trigger update --- .../controller/DeviceEventController.java | 95 +++++++++++ .../device/service/DeviceEventService.java | 156 ++++++++++++++++++ 2 files changed, 251 insertions(+) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java new file mode 100644 index 00000000..3b922dba --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java @@ -0,0 +1,95 @@ +package com.zmops.iot.web.device.controller; + +import cn.hutool.core.util.IdUtil; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.service.DeviceEventService; +import com.zmops.iot.web.product.dto.ProductEventRule; +import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.annotation.Transactional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 设备 物模型功能【事件】 类似于 属性处理 + **/ +@RestController +@RequestMapping("/device/event") +public class DeviceEventController { + + @Autowired + DeviceEventService deviceEventService; + + @Autowired + private ZbxTrigger zbxTrigger; + + private static final String ALARM_TAG_NAME = "__alarm__"; + private static final String EXECUTE_TAG_NAME = "__execute__"; + + /** + * 修改 触发器 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ + @Transactional + @PostMapping("/update") + public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) + ProductEventRule eventRule) { + + + //step 1: 删除原有的 关联关系 + List deviceIds = eventRule.getExpList().parallelStream().map(ProductEventRule.Expression::getProductId) + .collect(Collectors.toList()); + + deviceIds.forEach(deviceId -> { + new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).relationId.eq(deviceId).delete(); + new QProductEventService().eventRuleId.eq(eventRule.getEventRuleId()).deviceId.eq(deviceId).delete(); + }); + + + Long eventRuleId = IdUtil.getSnowflake().nextId(); // ruleId, trigger name + + deviceEventService.createProductEventRule(eventRuleId, eventRule); + + //step 1: 先创建 zbx 触发器 + String expression = eventRule.getExpList() + .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); + + //step 2: zbx 保存触发器 + String[] triggerIds = deviceEventService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); + + //step 4: zbx 触发器创建 Tag + Map tags = eventRule.getTags(); + if (tags == null || !tags.containsKey(ALARM_TAG_NAME)) { + tags.put(ALARM_TAG_NAME, eventRule.getEventRuleId() + ""); + } + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { + tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); + } + for (String triggerId : triggerIds) { + zbxTrigger.triggerTagCreate(triggerId, tags); + } + + + //step 5: 更新 zbxId + deviceEventService.updateProductEventRuleZbxId(eventRuleId, triggerIds); + + // 返回触发器ID + return ResponseData.success(eventRuleId); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java new file mode 100644 index 00000000..7c7ed8a6 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java @@ -0,0 +1,156 @@ +package com.zmops.iot.web.device.service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.ProductEventExpression; +import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.web.product.dto.ProductEventRule; +import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; +import lombok.Data; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + **/ +@Service +public class DeviceEventService { + + @Autowired + private ZbxTrigger zbxTrigger; + + /** + * 保存触发器 + * + * @param eventRuleId 触发器ID + * @param eventRule 告警规则 + */ + public void createProductEventRule(Long eventRuleId, ProductEventRule eventRule) { + // step 1: 保存产品告警规则 + ProductEvent event = initEventRule(eventRule); + event.setEventRuleId(eventRuleId); + DB.save(event); + + //step 2: 保存 表达式,方便回显 + List expList = new ArrayList<>(); + + eventRule.getExpList().forEach(i -> { + ProductEventExpression exp = initEventExpression(i); + exp.setEventRuleId(eventRuleId); + expList.add(exp); + }); + + DB.saveAll(expList); + + //step 3: 保存触发器 调用 本产品方法 + if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { + eventRule.getDeviceServices().forEach(i -> { + DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") + .setParameter("eventRuleId", eventRuleId) + .setParameter("deviceId", eventRuleId) + .setParameter("executeDeviceId", i.getExecuteDeviceId()) + .setParameter("serviceId", i.getServiceId()) + .execute(); + }); + } + + //step 4: 保存关联关系 + List relationIds = eventRule.getExpList().parallelStream().map(ProductEventRule.Expression::getProductId).distinct().collect(Collectors.toList()); + List lists = new ArrayList<>(); + relationIds.forEach(relationId -> { + ProductEventRelation productEventRelation = new ProductEventRelation(); + productEventRelation.setEventRuleId(eventRuleId); + productEventRelation.setRelationId(relationId); + }); + + + } + + private ProductEvent initEventRule(ProductEventRule eventRule) { + ProductEvent event = new ProductEvent(); + event.setEventLevel(eventRule.getEventLevel()); + event.setExpLogic(eventRule.getExpLogic()); + event.setEventNotify(eventRule.getEventNotify()); + event.setRemark(eventRule.getRemark()); + event.setEventRuleName(eventRule.getEventRuleName()); + event.setStatus(CommonStatus.ENABLE.getCode()); + return event; + } + + private ProductEventExpression initEventExpression(ProductEventRule.Expression exp) { + ProductEventExpression eventExpression = new ProductEventExpression(); + eventExpression.setEventExpId(exp.getEventExpId()); + eventExpression.setCondition(exp.getCondition()); + eventExpression.setFunction(exp.getFunction()); + eventExpression.setScope(exp.getScope()); + eventExpression.setValue(exp.getValue()); + eventExpression.setDeviceId(exp.getProductId()); + eventExpression.setProductAttrKey(exp.getProductAttrKey()); + eventExpression.setUnit(exp.getUnit()); + return eventExpression; + } + + /** + * 更新 触发器规则 zbxId + * + * @param triggerId 规则ID + * @param zbxId triggerId + */ + public void updateProductEventRuleZbxId(Long triggerId, String[] zbxId) { + + List triggers = JSONObject.parseArray(zbxTrigger.triggerGet(Arrays.toString(zbxId)), Triggers.class); + + Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.host, Triggers::getTriggerid)); + + List productEventRelationList = new QProductEventRelation().eventRuleId.eq(triggerId).findList(); + + productEventRelationList.forEach(productEventRelation -> { + if (null != map.get(productEventRelation.getRelationId())) { + DB.update(ProductEventRelation.class).where().eq("ruleId", triggerId).eq("relationId", productEventRelation.getRelationId()) + .asUpdate().set("zbxId", map.get(productEventRelation.getRelationId())).update(); + } + }); + + } + + /** + * 创建 触发器 + * + * @param triggerName 触发器名称 + * @param expression 表达式 + * @param level 告警等级 + * @return 触发器ID + */ + public String[] createZbxTrigger(String triggerName, String expression, Byte level) { + String res = zbxTrigger.triggerCreate(triggerName, expression, level); + return JSON.parseObject(res, TriggerIds.class).getTriggerids(); + } + + @Data + static class TriggerIds { + private String[] triggerids; + } + + @Data + public static class Triggers { + private String triggerid; + private String description; + private Hosts hosts; + } + + @Data + static class Hosts { + private String hostid; + private String host; + } +} From 428a93462fb302404f6dd641ae647482829d790a Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 17 Sep 2021 11:48:07 +0800 Subject: [PATCH 191/763] [fix]: fix maven version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3a6b97ee..e5b6245d 100644 --- a/pom.xml +++ b/pom.xml @@ -187,7 +187,7 @@ 1.8 - 3.6 + 3.5 From 578c86631e81f8211e75b39aa1a39dd3d1c22f2a Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 17 Sep 2021 15:35:36 +0800 Subject: [PATCH 192/763] [fix]: fix pom --- zeus-starter/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index 86e8284a..df28e9d6 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -88,7 +88,7 @@ npm - install --registry=https://registry.npmjs.org/ + install --registry=https://registry.npm.taobao.org/ From ecf4408d66c88e22ebaea3e9eb4b8dd7bc9ccf77 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 17 Sep 2021 16:58:06 +0800 Subject: [PATCH 193/763] =?UTF-8?q?=E5=91=8A=E8=AD=A6=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api-json/problem/problem.get.ftl | 2 ++ .../web/alarm/controller/AlarmController.java | 2 +- .../com/zmops/iot/web/alarm/dto/AlarmDto.java | 27 ++++---------- .../iot/web/alarm/service/AlarmService.java | 35 ++++++++++++++----- 4 files changed, 36 insertions(+), 30 deletions(-) diff --git a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl index 31181186..2bb6f4a5 100644 --- a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl +++ b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl @@ -17,6 +17,8 @@ <#if timeTill??> "time_till":${timeTill}, + "evaltype":2, + "tags":[{"tag": "__alarm__"},{"tag": "__execute__"}], "filter":{ "source":"0" }, diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java index f5d65c36..423c8eac 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java @@ -23,7 +23,7 @@ public void test() { alarmService.test(); } - @RequestMapping("/list") + @RequestMapping("/getAlarmByPage") public ResponseData getAlarmByPage(@RequestBody AlarmParam alarmParam){ return ResponseData.success(alarmService.getAlarmByPage(alarmParam)); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java index fab7d431..e4bbecbd 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java @@ -1,40 +1,27 @@ package com.zmops.iot.web.alarm.dto; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; import lombok.Data; /** * @author yefei **/ @Data +@JsonSerialize(using = CachedValueFilter.class) public class AlarmDto { private String eventid; - private String source; - - private String object; - private String clock; - private String ns; - - private String r_eventid; - - private String r_clock; - - private String r_ns; - - private String correlationid; - - private String userid; + private String rClock; private String name; - private String acknowledged; - + @CachedValue(value = "EVENT_LEVEL") private String severity; - private String opdata; - - private String acknowledges; + private String deviceName; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index c2a0fcf5..7c7baf52 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -5,17 +5,18 @@ import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.mediaType.AlarmCallback; +import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.alarm.dto.AlarmDto; import com.zmops.iot.web.alarm.dto.param.AlarmParam; +import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.zeus.driver.entity.ZbxProblemInfo; import com.zmops.zeus.driver.service.ZbxProblem; +import io.ebean.DB; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; /** @@ -45,14 +46,30 @@ public void test() { public List getAlarmByPage(AlarmParam alarmParam) { List zbxProblemInfos = getAlarmList(alarmParam); - + if (ToolUtil.isEmpty(zbxProblemInfos)) { + return Collections.emptyList(); + } //分页 List problemList = zbxProblemInfos.stream().skip((alarmParam.getPage() - 1) * alarmParam.getMaxRow()).limit(alarmParam.getMaxRow()).collect(Collectors.toList()); - //根据triggerid查询出deviceId - + //根据triggerid查询出 所属设备 + List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).collect(Collectors.toList()); + List deviceList = DB.findDto(DeviceDto.class, "select name,r.zbx_id from device d INNER JOIN (select relation_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.relation_id=d.device_id") + .setParameter("zbxIds", triggerIds).findList(); + Map deviceMap = deviceList.parallelStream().collect(Collectors.toMap(DeviceDto::getZbxId, DeviceDto::getName)); + + List alarmDtoList = new ArrayList<>(); + problemList.forEach(zbxProblemInfo -> { + AlarmDto alarmDto = new AlarmDto(); + BeanUtils.copyProperties(zbxProblemInfo, alarmDto); + alarmDto.setRClock(zbxProblemInfo.getR_clock()); + if (null != deviceMap.get(zbxProblemInfo.getObjectid())) { + alarmDto.setDeviceName(deviceMap.get(zbxProblemInfo.getObjectid())); + } + alarmDtoList.add(alarmDto); + }); - return null; + return alarmDtoList; } public List getAlarmList(AlarmParam alarmParam) { @@ -65,7 +82,7 @@ public List getAlarmList(AlarmParam alarmParam) { hostId = one.getZbxId(); } //从zbx取告警记录 - String problem = zbxProblem.getProblem(hostId, alarmParam.getTimeFrom(),alarmParam.getTimeTill(),alarmParam.getRecent()); + String problem = zbxProblem.getProblem(hostId, alarmParam.getTimeFrom(), alarmParam.getTimeTill(), alarmParam.getRecent()); List zbxProblemInfos = JSONObject.parseArray(problem, ZbxProblemInfo.class); From d912d3193b3a6082a3b1dbbb55c10f2ca7b51f7d Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 17 Sep 2021 17:24:33 +0800 Subject: [PATCH 194/763] [fix]: fix tdengine pom version --- iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml index 5573d5c3..c0eff4b9 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml @@ -20,7 +20,7 @@ com.taosdata.jdbc taos-jdbcdriver - 2.0.30 + 2.0.31 com.zmops From 0ce2606ef6ab941b117c5eb7fd9938cee32380fc Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 17 Sep 2021 17:27:23 +0800 Subject: [PATCH 195/763] [fix]: fix start script --- dist-material/bin/IoTServer.sh | 22 +++++++++++----------- dist-material/bin/webappService.sh | 6 +++--- dist-material/log4j2.xml | 4 ++-- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/dist-material/bin/IoTServer.sh b/dist-material/bin/IoTServer.sh index b881ccb3..8e9889c1 100644 --- a/dist-material/bin/IoTServer.sh +++ b/dist-material/bin/IoTServer.sh @@ -17,33 +17,33 @@ PRG="$0" PRGDIR=$(dirname "$PRG") -[ -z "$OAP_HOME" ] && OAP_HOME=$(cd "$PRGDIR/.." > /dev/null || exit 1; pwd) +[ -z "$IOT_HOME" ] && IOT_HOME=$(cd "$PRGDIR/.." > /dev/null || exit 1; pwd) -OAP_LOG_DIR="${OAP_LOG_DIR:-${OAP_HOME}/logs}" +IOT_LOG_DIR="${IOT_LOG_DIR:-${IOT_HOME}/logs}" JAVA_OPTS="${JAVA_OPTS:- -Xms256M -Xmx512M}" -if [ ! -d "${OAP_LOG_DIR}" ]; then - mkdir -p "${OAP_LOG_DIR}" +if [ ! -d "${IOT_LOG_DIR}" ]; then + mkdir -p "${IOT_LOG_DIR}" fi _RUNJAVA=${JAVA_HOME}/bin/java [ -z "$JAVA_HOME" ] && _RUNJAVA=java -CLASSPATH="$OAP_HOME/config:$CLASSPATH" -for i in "$OAP_HOME"/oap-libs/*.jar +CLASSPATH="$IOT_HOME/config:$CLASSPATH" +for i in "$IOT_HOME"/iot-server-libs/*.jar do CLASSPATH="$i:$CLASSPATH" done -OAP_OPTIONS=" -Doap.logDir=${OAP_LOG_DIR}" +IOT_OPTIONS=" -Doap.logDir=${IOT_LOG_DIR}" -eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${OAP_OPTIONS} -classpath $CLASSPATH org.apache.skywalking.oap.server.starter.OAPServerStartUp \ - 2>${OAP_LOG_DIR}/oap.log 1> /dev/null &" +eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${IOT_OPTIONS} -classpath $CLASSPATH com.zmops.zeus.iot.server.starter.IOTServerStartUp \ + 2>${IOT_LOG_DIR}/zeus_iot.log 1> /dev/null &" if [ $? -eq 0 ]; then sleep 1 - echo "SkyWalking OAP started successfully!" + echo "Zeus IOT started successfully!" else - echo "SkyWalking OAP started failure!" + echo "Zeus IOT OAP started failure!" exit 1 fi diff --git a/dist-material/bin/webappService.sh b/dist-material/bin/webappService.sh index dde778c5..5e93d2d3 100644 --- a/dist-material/bin/webappService.sh +++ b/dist-material/bin/webappService.sh @@ -32,15 +32,15 @@ LOG_FILE_LOCATION=${WEBAPP_LOG_DIR}/webapp.log _RUNJAVA=${JAVA_HOME}/bin/java [ -z "$JAVA_HOME" ] && _RUNJAVA=java -eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} -jar ${JAR_PATH}/skywalking-webapp.jar \ +eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} -jar ${JAR_PATH}/zeus-webapp.jar \ --spring.config.location=${JAR_PATH}/webapp.yml \ --logging.file=${LOG_FILE_LOCATION} \ 2>${WEBAPP_LOG_DIR}/webapp-console.log 1> /dev/null &" if [ $? -eq 0 ]; then sleep 1 - echo "SkyWalking Web Application started successfully!" + echo "Zeus Web Application started successfully!" else - echo "SkyWalking Web Application started failure!" + echo "Zeus Web Application started failure!" exit 1 fi diff --git a/dist-material/log4j2.xml b/dist-material/log4j2.xml index 5d09ef22..0ce331bf 100644 --- a/dist-material/log4j2.xml +++ b/dist-material/log4j2.xml @@ -22,8 +22,8 @@ ${sys:oap.logDir} - + %d - %c - %L [%t] %-5p %x - %m%n From 0761e74fe174795864707f695cd1542ab911848b Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 17 Sep 2021 19:46:55 +0800 Subject: [PATCH 196/763] [fix]: fix product event trigger --- .../java/com/zmops/iot/domain/BaseEntity.java | 5 ++ .../api-json/trigger/trigger.get.ftl | 4 +- .../controller/DeviceEventController.java | 21 +++++--- .../device/service/DeviceEventService.java | 39 ++++++++++----- .../web/exception/enums/BizExceptionEnum.java | 2 + .../controller/ProductEventController.java | 30 ++++++++++-- .../iot/web/product/dto/ProductEventDto.java | 10 +++- .../iot/web/product/dto/ProductEventRule.java | 11 +++-- .../web/product/service/EventRuleService.java | 49 ++++++++++++------- 9 files changed, 121 insertions(+), 50 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/BaseEntity.java b/zeus-common/src/main/java/com/zmops/iot/domain/BaseEntity.java index edf0bc0c..c2f242fa 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/BaseEntity.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/BaseEntity.java @@ -63,4 +63,9 @@ public interface Get { public interface MassRemove { } + /** + * 数据校验组:状态 + */ + public interface Status { + } } diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl index 08feb1d5..d4399adb 100644 --- a/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl @@ -3,8 +3,8 @@ "method": "trigger.get", "params": { "selectHosts":["host"], - <#if triggerids??> - "triggerids":${triggerids}, + <#if triggerIds??> + "triggerids":${triggerIds}, <#if host??> "host":"${host}", diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java index 3b922dba..8ece5890 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java @@ -4,9 +4,11 @@ import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.service.DeviceEventService; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductEventRule; import com.zmops.zeus.driver.service.ZbxTrigger; import io.ebean.annotation.Transactional; @@ -17,6 +19,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -50,11 +53,12 @@ public class DeviceEventController { public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) ProductEventRule eventRule) { - - //step 1: 删除原有的 关联关系 - List deviceIds = eventRule.getExpList().parallelStream().map(ProductEventRule.Expression::getProductId) + List deviceIds = eventRule.getExpList().parallelStream().map(ProductEventRule.Expression::getDeviceId) .collect(Collectors.toList()); - + if(ToolUtil.isEmpty(deviceIds)){ + throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); + } + //step 1: 删除原有的 关联关系 deviceIds.forEach(deviceId -> { new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).relationId.eq(deviceId).delete(); new QProductEventService().eventRuleId.eq(eventRule.getEventRuleId()).deviceId.eq(deviceId).delete(); @@ -74,11 +78,14 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn //step 4: zbx 触发器创建 Tag Map tags = eventRule.getTags(); - if (tags == null || !tags.containsKey(ALARM_TAG_NAME)) { - tags.put(ALARM_TAG_NAME, eventRule.getEventRuleId() + ""); + if (ToolUtil.isEmpty(tags)){ + tags = new HashMap<>(2); + } + if (!tags.containsKey(ALARM_TAG_NAME)) { + tags.put(ALARM_TAG_NAME, eventRuleId + ""); } if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { - tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); + tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); } for (String triggerId : triggerIds) { zbxTrigger.triggerTagCreate(triggerId, tags); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java index 7c7ed8a6..703ac385 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java @@ -7,6 +7,9 @@ import com.zmops.iot.domain.product.ProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductEventRule; import com.zmops.zeus.driver.service.ZbxTrigger; import io.ebean.DB; @@ -65,14 +68,26 @@ public void createProductEventRule(Long eventRuleId, ProductEventRule eventRule) } //step 4: 保存关联关系 - List relationIds = eventRule.getExpList().parallelStream().map(ProductEventRule.Expression::getProductId).distinct().collect(Collectors.toList()); - List lists = new ArrayList<>(); - relationIds.forEach(relationId -> { + //step 4: 保存关联关系 + if (ToolUtil.isNotEmpty(eventRule.getProductId())) { ProductEventRelation productEventRelation = new ProductEventRelation(); productEventRelation.setEventRuleId(eventRuleId); - productEventRelation.setRelationId(relationId); - }); - + productEventRelation.setRelationId(eventRule.getProductId()); + DB.save(productEventRelation); + } else { + List relationIds = eventRule.getExpList().parallelStream().map(ProductEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); + if (ToolUtil.isEmpty(relationIds)) { + throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); + } + List productEventRelationList = new ArrayList<>(); + relationIds.forEach(relationId -> { + ProductEventRelation productEventRelation = new ProductEventRelation(); + productEventRelation.setEventRuleId(eventRuleId); + productEventRelation.setRelationId(relationId); + productEventRelationList.add(productEventRelation); + }); + DB.saveAll(productEventRelationList); + } } @@ -94,7 +109,7 @@ private ProductEventExpression initEventExpression(ProductEventRule.Expression e eventExpression.setFunction(exp.getFunction()); eventExpression.setScope(exp.getScope()); eventExpression.setValue(exp.getValue()); - eventExpression.setDeviceId(exp.getProductId()); + eventExpression.setDeviceId(exp.getDeviceId()); eventExpression.setProductAttrKey(exp.getProductAttrKey()); eventExpression.setUnit(exp.getUnit()); return eventExpression; @@ -110,13 +125,13 @@ public void updateProductEventRuleZbxId(Long triggerId, String[] zbxId) { List triggers = JSONObject.parseArray(zbxTrigger.triggerGet(Arrays.toString(zbxId)), Triggers.class); - Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.host, Triggers::getTriggerid)); + Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.get(0).host, Triggers::getTriggerid)); List productEventRelationList = new QProductEventRelation().eventRuleId.eq(triggerId).findList(); productEventRelationList.forEach(productEventRelation -> { if (null != map.get(productEventRelation.getRelationId())) { - DB.update(ProductEventRelation.class).where().eq("ruleId", triggerId).eq("relationId", productEventRelation.getRelationId()) + DB.update(ProductEventRelation.class).where().eq("eventRuleId", triggerId).eq("relationId", productEventRelation.getRelationId()) .asUpdate().set("zbxId", map.get(productEventRelation.getRelationId())).update(); } }); @@ -143,9 +158,9 @@ static class TriggerIds { @Data public static class Triggers { - private String triggerid; - private String description; - private Hosts hosts; + private String triggerid; + private String description; + private List hosts; } @Data diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index 825d4a08..20e00463 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -160,6 +160,8 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { RULE_NOT_EXISTS(1701, "上下线规则不存在"), RULE_EXISTS(1702, "上下线规则已存在"), + EVENT_HAS_NOT_DEVICE(1703,"告警规则缺少关联产品或设备"), + /** * 租户相关的异常 */ diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java index 55ac8615..3a785c64 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java @@ -16,6 +16,7 @@ import com.zmops.iot.web.product.dto.param.EventParm; import com.zmops.iot.web.product.service.EventRuleService; import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; import io.ebean.annotation.Transactional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; @@ -24,6 +25,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -84,11 +86,14 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE //step 4: zbx 触发器创建 Tag Map tags = eventRule.getTags(); - if (tags == null || !tags.containsKey(ALARM_TAG_NAME)) { - tags.put(ALARM_TAG_NAME, eventRule.getEventRuleId() + ""); + if (ToolUtil.isEmpty(tags)){ + tags = new HashMap<>(2); + } + if (!tags.containsKey(ALARM_TAG_NAME)) { + tags.put(ALARM_TAG_NAME, eventRuleId + ""); } if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { - tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); + tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); } for (String triggerId : triggerIds) { zbxTrigger.triggerTagCreate(triggerId, tags); @@ -129,7 +134,10 @@ public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseE //step 3: zbx 触发器创建 Tag Map tags = eventRule.getTags(); - if (tags == null || !tags.containsKey(ALARM_TAG_NAME)) { + if (ToolUtil.isEmpty(tags)){ + tags = new HashMap<>(2); + } + if (!tags.containsKey(ALARM_TAG_NAME)) { tags.put(ALARM_TAG_NAME, eventRule.getEventRuleId() + ""); } if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { @@ -142,6 +150,18 @@ public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseE return ResponseData.success(eventRule.getEventRuleId()); } + /** + * 修改 触发器 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ + @PostMapping("/status") + public ResponseData updateProductEventStatus(@RequestBody @Validated(value = BaseEntity.Status.class) ProductEventRule eventRule) { + DB.update(ProductEvent.class).where().eq("eventRuleId",eventRule.getEventRuleId()).asUpdate().set("status",eventRule.getStatus()).update(); + return ResponseData.success(); + } + /** * 删除 触发器 * @@ -162,7 +182,7 @@ public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseE new QProductEventExpression().eventRuleId.eq(eventRule.getEventRuleId()).delete(); //step 4:删除 触发器 - new QProductEventService().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).delete(); return ResponseData.success(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java index c86a65ac..fe2bcf44 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; import lombok.Data; /** @@ -18,6 +19,7 @@ public class ProductEventDto { private String eventRuleName; + @CachedValue(value = "EVENT_LEVEL") private String eventLevel; @CachedValue(value = "STATUS") @@ -25,5 +27,11 @@ public class ProductEventDto { private String remark; - + private String expLogic; + @CachedValue(type = DicType.SysUserName) + private String createUser; + private String createTime; + @CachedValue(type = DicType.SysUserName) + private String updateUser; + private String updateTime; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java index e5eacbcf..462ac556 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java @@ -21,7 +21,7 @@ @Setter public class ProductEventRule { - @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Delete.class}) + @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Delete.class, BaseEntity.Status.class}) private Long eventRuleId; @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) @@ -52,6 +52,10 @@ public class ProductEventRule { @NotNull(groups = BaseEntity.Update.class) private Integer zbxId; + private String productId; // 产品ID + + @NotBlank(groups = BaseEntity.Status.class) + private String status; @Getter @Setter @@ -75,8 +79,7 @@ public static class Expression { @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private String productAttrKey; // 产品属性 Key - @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) - private String productId; // 产品ID + private String deviceId; // 设备ID private String unit; @@ -85,7 +88,7 @@ public String toString() { StringBuilder expression = new StringBuilder(); expression.append(function); expression.append("(/"); - expression.append(productId); + expression.append(deviceId); expression.append("/"); expression.append(productAttrKey); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java index c0fdc8d8..1306924e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java @@ -6,11 +6,12 @@ import com.zmops.iot.domain.product.ProductEventExpression; import com.zmops.iot.domain.product.ProductEventRelation; import com.zmops.iot.domain.product.query.QProductEvent; -import com.zmops.iot.domain.product.query.QProductEventExpression; import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductEventDto; import com.zmops.iot.web.product.dto.ProductEventRule; import com.zmops.iot.web.product.dto.param.EventParm; @@ -76,15 +77,25 @@ public void createProductEventRule(Long eventRuleId, ProductEventRule eventRule) } //step 4: 保存关联关系 - List relationIds = eventRule.getExpList().parallelStream().map(ProductEventRule.Expression::getProductId).distinct().collect(Collectors.toList()); - List lists = new ArrayList<>(); - relationIds.forEach(relationId -> { + if (ToolUtil.isNotEmpty(eventRule.getProductId())) { ProductEventRelation productEventRelation = new ProductEventRelation(); productEventRelation.setEventRuleId(eventRuleId); - productEventRelation.setRelationId(relationId); - }); - - + productEventRelation.setRelationId(eventRule.getProductId()); + DB.save(productEventRelation); + } else { + List relationIds = eventRule.getExpList().parallelStream().map(ProductEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); + if (ToolUtil.isEmpty(relationIds)) { + throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); + } + List productEventRelationList = new ArrayList<>(); + relationIds.forEach(relationId -> { + ProductEventRelation productEventRelation = new ProductEventRelation(); + productEventRelation.setEventRuleId(eventRuleId); + productEventRelation.setRelationId(relationId); + productEventRelationList.add(productEventRelation); + }); + DB.saveAll(productEventRelationList); + } } /** @@ -152,7 +163,7 @@ private ProductEventExpression initEventExpression(ProductEventRule.Expression e eventExpression.setFunction(exp.getFunction()); eventExpression.setScope(exp.getScope()); eventExpression.setValue(exp.getValue()); - eventExpression.setDeviceId(exp.getProductId()); + eventExpression.setDeviceId(exp.getDeviceId()); eventExpression.setProductAttrKey(exp.getProductAttrKey()); eventExpression.setUnit(exp.getUnit()); return eventExpression; @@ -162,20 +173,20 @@ private ProductEventExpression initEventExpression(ProductEventRule.Expression e /** * 更新 触发器规则 zbxId * - * @param triggerId 规则ID + * @param eventRuleId 规则ID * @param zbxId triggerId */ - public void updateProductEventRuleZbxId(Long triggerId, String[] zbxId) { - - List triggers = JSONObject.parseArray(zbxTrigger.triggerGet(Arrays.toString(zbxId)), Triggers.class); + public void updateProductEventRuleZbxId(Long eventRuleId, String[] zbxId) { + String s = zbxTrigger.triggerGet(Arrays.toString(zbxId)); + List triggers = JSONObject.parseArray(s, Triggers.class); - Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.host, Triggers::getTriggerid)); + Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.get(0).host, Triggers::getTriggerid)); - List productEventRelationList = new QProductEventRelation().eventRuleId.eq(triggerId).findList(); + List productEventRelationList = new QProductEventRelation().eventRuleId.eq(eventRuleId).findList(); productEventRelationList.forEach(productEventRelation -> { if (null != map.get(productEventRelation.getRelationId())) { - DB.update(ProductEventRelation.class).where().eq("ruleId", triggerId).eq("relationId", productEventRelation.getRelationId()) + DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRuleId).eq("relationId", productEventRelation.getRelationId()) .asUpdate().set("zbxId", map.get(productEventRelation.getRelationId())).update(); } }); @@ -233,9 +244,9 @@ static class TriggerIds { @Data public static class Triggers { - private String triggerid; - private String description; - private Hosts hosts; + private String triggerid; + private String description; + private List hosts; } @Data From 5f4a80bc8c37601ce60c80edeb893376ff0a5402 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 17 Sep 2021 21:26:14 +0800 Subject: [PATCH 197/763] [fix]: fix product service --- .../zmops/iot/web/product/service/ProductSvcService.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index 60474674..4b48e3a8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -22,6 +22,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -107,9 +108,10 @@ public List list(ProductSvcParam productSvcParam) { } if (ToolUtil.isNotEmpty(productSvcParam.getProdId())) { List serviceIds = getServiceIdList(productSvcParam.getProdId()); - if (ToolUtil.isNotEmpty(serviceIds)) { - qProdService.id.in(serviceIds); + if (ToolUtil.isEmpty(serviceIds)) { + return Collections.emptyList(); } + qProdService.id.in(serviceIds); } if (ToolUtil.isNotEmpty(productSvcParam.getMark())) { qProdService.mark.contains(productSvcParam.getMark()); From a100ee72882e016b65a6c67f83a9115467bf37f2 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 17 Sep 2021 22:09:32 +0800 Subject: [PATCH 198/763] [fix]: fix global view --- .../com/zmops/iot/web/analyse/service/ZbxChartsService.java | 6 ++++++ .../com/zmops/iot/web/exception/enums/BizExceptionEnum.java | 1 + 2 files changed, 7 insertions(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java index e2bf1c99..2dc25bde 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java @@ -1,8 +1,10 @@ package com.zmops.iot.web.analyse.service; import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.methods.PostMethod; @@ -50,12 +52,16 @@ public class ZbxChartsService { public void getCharts(HttpServletResponse response, String from, String to, List attrIds, String width, String height) { + if (ToolUtil.isEmpty(COOKIE) || LocalDateTimeUtils.betweenTwoTime(COOKIE_TIME, LocalDateTime.now(), ChronoUnit.DAYS) >= 30) { getCookie(); } List itemids = getItemIds(attrIds); + if (ToolUtil.isEmpty(itemids)) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_NOT_EXISTS); + } HttpClient client = new HttpClient(); PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index 20e00463..882ab546 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -139,6 +139,7 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { * 属性相关 */ PRODUCT_ATTR_KEY_EXISTS(1401, "该属性Key已存在"), + PRODUCT_ATTR_KEY_NOT_EXISTS(1404, "该属性Key不存在"), PRODUCT_ATTR_DEPTED_NULL(1402,"依赖的属性不能为空"), PRODUCT_ATTR_DEPTED_NOT_EXIST(1403,"依赖的属性不能为空"), From 79e662a13442d5104230466ef502958fc996100d Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 18 Sep 2021 09:55:04 +0800 Subject: [PATCH 199/763] [feat]: add stop script --- dist-material/bin/stop.sh | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 dist-material/bin/stop.sh diff --git a/dist-material/bin/stop.sh b/dist-material/bin/stop.sh new file mode 100644 index 00000000..5e03aa58 --- /dev/null +++ b/dist-material/bin/stop.sh @@ -0,0 +1,2 @@ +#!/bin/bash +ps -ef | grep zeus-iot-bin | grep -v grep | awk '{print $2}' | xargs kill -9 From 3e0fa971b5c46f26cb828a67e5d9eaf3c0bf4d4c Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 18 Sep 2021 11:18:43 +0800 Subject: [PATCH 200/763] [fix]: fix product event trigger tag --- .../controller/DeviceEventController.java | 3 +- .../controller/ProductEventController.java | 9 ++-- .../iot/web/product/dto/ProductEventRule.java | 19 +++++-- .../web/product/service/EventRuleService.java | 53 ++++++++++--------- 4 files changed, 50 insertions(+), 34 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java index 8ece5890..83faedd2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java @@ -77,7 +77,8 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn String[] triggerIds = deviceEventService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); //step 4: zbx 触发器创建 Tag - Map tags = eventRule.getTags(); + Map tags = eventRule.getTags().stream() + .collect(Collectors.toMap(ProductEventRule.Tag::getTag, ProductEventRule.Tag::getValue, (k1, k2) -> k2)); if (ToolUtil.isEmpty(tags)){ tags = new HashMap<>(2); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java index 3a785c64..7efd04cc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java @@ -13,6 +13,7 @@ import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.product.dto.ProductEventDto; import com.zmops.iot.web.product.dto.ProductEventRule; +import com.zmops.iot.web.product.dto.ProductTag; import com.zmops.iot.web.product.dto.param.EventParm; import com.zmops.iot.web.product.service.EventRuleService; import com.zmops.zeus.driver.service.ZbxTrigger; @@ -83,9 +84,10 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE //step 2: zbx 保存触发器 String[] triggerIds = eventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); - + //step 4: zbx 触发器创建 Tag - Map tags = eventRule.getTags(); + Map tags = eventRule.getTags().stream() + .collect(Collectors.toMap(ProductEventRule.Tag::getTag, ProductEventRule.Tag::getValue, (k1, k2) -> k2)); if (ToolUtil.isEmpty(tags)){ tags = new HashMap<>(2); } @@ -133,7 +135,8 @@ public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseE zbxTrigger.triggerUpdate(productEventRelation.getZbxId(), expression, eventRule.getEventLevel()); //step 3: zbx 触发器创建 Tag - Map tags = eventRule.getTags(); + Map tags = eventRule.getTags().stream() + .collect(Collectors.toMap(ProductEventRule.Tag::getTag, ProductEventRule.Tag::getValue, (k1, k2) -> k2)); if (ToolUtil.isEmpty(tags)){ tags = new HashMap<>(2); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java index 462ac556..4c3a504d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java @@ -1,15 +1,16 @@ package com.zmops.iot.web.product.dto; import com.zmops.iot.domain.BaseEntity; +import lombok.Data; import lombok.Getter; import lombok.Setter; import javax.validation.Valid; +import javax.validation.constraints.Max; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.util.List; -import java.util.Map; /** * @author nantian created at 2021/9/14 14:47 @@ -47,7 +48,7 @@ public class ProductEventRule { private List deviceServices; - private Map tags; + private List tags; @NotNull(groups = BaseEntity.Update.class) private Integer zbxId; @@ -57,6 +58,16 @@ public class ProductEventRule { @NotBlank(groups = BaseEntity.Status.class) private String status; + @Data + public static class Tag { + + @Max(20) + private String tag; + + @Max(50) + private String value; + } + @Getter @Setter // 告警表达式 构成 @@ -106,9 +117,9 @@ public String toString() { @Getter public static class DeviceService { - private Long deviceId; + private String deviceId; - private Long executeDeviceId; + private String executeDeviceId; private Long serviceId; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java index 1306924e..2c407ab4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java @@ -64,38 +64,38 @@ public void createProductEventRule(Long eventRuleId, ProductEventRule eventRule) DB.saveAll(expList); - //step 3: 保存触发器 调用 本产品方法 - if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { - eventRule.getDeviceServices().forEach(i -> { - DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") - .setParameter("eventRuleId", eventRuleId) - .setParameter("deviceId", eventRuleId) - .setParameter("executeDeviceId", i.getExecuteDeviceId()) - .setParameter("serviceId", i.getServiceId()) - .execute(); - }); - } - - //step 4: 保存关联关系 + List relationIds = new ArrayList<>(); if (ToolUtil.isNotEmpty(eventRule.getProductId())) { - ProductEventRelation productEventRelation = new ProductEventRelation(); - productEventRelation.setEventRuleId(eventRuleId); - productEventRelation.setRelationId(eventRule.getProductId()); - DB.save(productEventRelation); + relationIds.add(eventRule.getProductId()); } else { - List relationIds = eventRule.getExpList().parallelStream().map(ProductEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); + relationIds = eventRule.getExpList().parallelStream().map(ProductEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); if (ToolUtil.isEmpty(relationIds)) { throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); } - List productEventRelationList = new ArrayList<>(); + } + //step 3: 保存触发器 调用 本产品方法 + if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { relationIds.forEach(relationId -> { - ProductEventRelation productEventRelation = new ProductEventRelation(); - productEventRelation.setEventRuleId(eventRuleId); - productEventRelation.setRelationId(relationId); - productEventRelationList.add(productEventRelation); + eventRule.getDeviceServices().forEach(i -> { + DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") + .setParameter("eventRuleId", eventRuleId) + .setParameter("deviceId", relationId) + .setParameter("executeDeviceId", i.getExecuteDeviceId()) + .setParameter("serviceId", i.getServiceId()) + .execute(); + }); }); - DB.saveAll(productEventRelationList); } + + //step 4: 保存关联关系 + List productEventRelationList = new ArrayList<>(); + relationIds.forEach(relationId -> { + ProductEventRelation productEventRelation = new ProductEventRelation(); + productEventRelation.setEventRuleId(eventRuleId); + productEventRelation.setRelationId(relationId); + productEventRelationList.add(productEventRelation); + }); + DB.saveAll(productEventRelationList); } /** @@ -137,7 +137,8 @@ public void updateProductEventRule(Long eventRuleId, ProductEventRule eventRule) eventRule.getDeviceServices().forEach(i -> { DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id, service_id) values (:eventRuleId, :deviceId, :serviceId)") .setParameter("eventRuleId", eventRuleId) - .setParameter("deviceId", i.getDeviceId()) + .setParameter("deviceId", eventRule.getProductId()) + .setParameter("executeDeviceId", i.getExecuteDeviceId()) .setParameter("serviceId", i.getServiceId()) .execute(); }); @@ -174,7 +175,7 @@ private ProductEventExpression initEventExpression(ProductEventRule.Expression e * 更新 触发器规则 zbxId * * @param eventRuleId 规则ID - * @param zbxId triggerId + * @param zbxId triggerId */ public void updateProductEventRuleZbxId(Long eventRuleId, String[] zbxId) { String s = zbxTrigger.triggerGet(Arrays.toString(zbxId)); From 6fbbeb090eafe18a941c2ff749c5a2789ce36ab1 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 18 Sep 2021 11:18:44 +0800 Subject: [PATCH 201/763] [feat]: macro service driver --- .../zmops/zeus/driver/service/ZbxMacro.java | 87 +++++++++++++++++++ .../api-json/macro/usermacro.create.ftl | 11 +++ .../api-json/macro/usermacro.delete.ftl | 11 +++ .../api-json/macro/usermacro.filter.get.ftl | 17 ++++ .../api-json/macro/usermacro.get.ftl | 14 +++ .../api-json/macro/usermacro.update.ftl | 10 +++ 6 files changed, 150 insertions(+) create mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java create mode 100644 zeus-driver/src/main/resources/api-json/macro/usermacro.create.ftl create mode 100644 zeus-driver/src/main/resources/api-json/macro/usermacro.delete.ftl create mode 100644 zeus-driver/src/main/resources/api-json/macro/usermacro.filter.get.ftl create mode 100644 zeus-driver/src/main/resources/api-json/macro/usermacro.get.ftl create mode 100644 zeus-driver/src/main/resources/api-json/macro/usermacro.update.ftl diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java new file mode 100644 index 00000000..65110cf9 --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java @@ -0,0 +1,87 @@ +package com.zmops.zeus.driver.service; + + +import com.dtflys.forest.annotation.BaseRequest; +import com.dtflys.forest.annotation.Post; +import com.zmops.zeus.driver.annotation.JsonPath; +import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; + +/** + * 宏定义接口 + */ +@BaseRequest( + baseURL = "${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) +public interface ZbxMacro { + + + /** + * 创建宏 + * + * @param hostid 主机ID + * @param macro 宏 Key + * @param value 宏 Value + * @return + */ + @Post + @JsonPath("/macro/usermacro.create") + String macroCreate(@ParamName("hostid") String hostid, + @ParamName("macro") String macro, + @ParamName("value") String value); + + + /** + * 更新 宏 + * + * @param hostmacroid 宏 ID + * @param macro 宏 Key + * @param value 宏 Value + * @return + */ + @Post + @JsonPath("/macro/usermacro.update") + String macroUpdate(@ParamName("hostmacroid") String macroid, + @ParamName("macro") String macro, + @ParamName("value") String value); + + /** + * 获取 宏 + * + * @param hostid 主机ID + * @param macro 宏 Key + * @param value 宏 Value + * @return + */ + @Post + @JsonPath("/macro/usermacro.get") + String macroGet(@ParamName("hostid") String hostid, + @ParamName("macro") String macro, + @ParamName("value") String value); + + + /** + * 搜索 宏 ID + * + * @param hostid 主机ID + * @param macro 宏 Key + * @return + */ + @Post + @JsonPath("/macro/usermacro.filter.get") + String macroQuery(@ParamName("hostid") String hostid, + @ParamName("macro") String macro); + + + /** + * 删除宏 + * + * @param macroids 宏IDs + * @return + */ + @Post + @JsonPath("/macro/usermacro.delete") + String macroDelete(@ParamName("hostid") String macroids); + +} diff --git a/zeus-driver/src/main/resources/api-json/macro/usermacro.create.ftl b/zeus-driver/src/main/resources/api-json/macro/usermacro.create.ftl new file mode 100644 index 00000000..a3e661f7 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/macro/usermacro.create.ftl @@ -0,0 +1,11 @@ +{ + "jsonrpc": "2.0", + "method": "usermacro.create", + "params": { + "hostid": "${hostid}", + "macro": "${macro}", + "value": "${value}" + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/macro/usermacro.delete.ftl b/zeus-driver/src/main/resources/api-json/macro/usermacro.delete.ftl new file mode 100644 index 00000000..10cc7292 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/macro/usermacro.delete.ftl @@ -0,0 +1,11 @@ +{ + "jsonrpc": "2.0", + "method": "usermacro.delete", + "params": [ + <#list macroids as id> + "${id}"<#if id_has_next>, + + ], + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/macro/usermacro.filter.get.ftl b/zeus-driver/src/main/resources/api-json/macro/usermacro.filter.get.ftl new file mode 100644 index 00000000..484e73dc --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/macro/usermacro.filter.get.ftl @@ -0,0 +1,17 @@ +{ + "jsonrpc": "2.0", + "method": "usermacro.get", + "params": { + "output": [ + "macro", + "value", + "description" + ], + "hostids": "${hostId}", + "filter": { + "macro": "${macro}" + } + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/macro/usermacro.get.ftl b/zeus-driver/src/main/resources/api-json/macro/usermacro.get.ftl new file mode 100644 index 00000000..34b20f3f --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/macro/usermacro.get.ftl @@ -0,0 +1,14 @@ +{ + "jsonrpc": "2.0", + "method": "usermacro.get", + "params": { + "output": [ + "macro", + "value", + "description" + ], + "hostids": "${hostId}" + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/macro/usermacro.update.ftl b/zeus-driver/src/main/resources/api-json/macro/usermacro.update.ftl new file mode 100644 index 00000000..db443afc --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/macro/usermacro.update.ftl @@ -0,0 +1,10 @@ +{ + "jsonrpc": "2.0", + "method": "usermacro.update", + "params": { + "hostmacroid": "${macroid}", + "value": "${value}" + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file From 75d2e33438764e563ca8c0ed3f16d6a41650e975 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 18 Sep 2021 11:52:09 +0800 Subject: [PATCH 202/763] [fix]: alarm notice fix --- .../web/alarm/service/AlarmNoticeWorker.java | 4 ++++ .../iot/web/alarm/service/AlarmService.java | 20 ++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java index a9e36065..e8cd9f95 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java @@ -18,10 +18,14 @@ public class AlarmNoticeWorker implements IWorker, Boolean> @Autowired MessageService messageService; + @Autowired + AlarmService alarmService; + @Override public Boolean action(Map alarmInfo, Map> allWrappers) { Map alarmInfo2 = new HashMap<>(alarmInfo); messageService.push(buildMessage(alarmInfo2)); + alarmService.alarm(alarmInfo); return null; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 7c7baf52..95480a67 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -4,6 +4,8 @@ import com.zmops.iot.domain.alarm.AlarmMessage; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.query.QProductEvent; import com.zmops.iot.mediaType.AlarmCallback; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.alarm.dto.AlarmDto; @@ -32,13 +34,21 @@ public class AlarmService { ZbxProblem zbxProblem; - public void test() { + public void alarm(Map alarmInfo) { + String deviceId = alarmInfo.get("hostname"); + String eventRuleId = alarmInfo.get("triggername"); + if (ToolUtil.isEmpty(deviceId) || ToolUtil.isEmpty(eventRuleId)) { + return; + } + Device device = new QDevice().deviceId.eq(deviceId).findOne(); + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(Long.parseLong(eventRuleId)).findOne(); + String alarmmessage = "设备:" + device.getName() + "发生告警,告警内容:" + productEvent.getEventRuleName(); List alarmMessages = new ArrayList<>(); - alarmMessages.add(AlarmMessage.builder().alarmMessage("DELTA 一级预警").build()); + alarmMessages.add(AlarmMessage.builder().alarmMessage(alarmmessage).build()); alarmCallbacks.forEach(alarmCallback -> { - if (alarmCallback.getType().equals("welink")) { - alarmCallback.doAlarm(alarmMessages); - } +// if (alarmCallback.getType().equals("welink")) { + alarmCallback.doAlarm(alarmMessages); +// } }); } From 7addf4e06768d9bc7631f6f5ff15ceb6b48f75d2 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Sat, 18 Sep 2021 11:52:09 +0800 Subject: [PATCH 203/763] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dist-material/bin/IoTServer.sh | 2 +- dist-material/bin/startup.sh | 4 ++-- dist-material/bin/stop.sh | 0 dist-material/bin/webappService.sh | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) mode change 100644 => 100755 dist-material/bin/stop.sh diff --git a/dist-material/bin/IoTServer.sh b/dist-material/bin/IoTServer.sh index 8e9889c1..b6fbee23 100644 --- a/dist-material/bin/IoTServer.sh +++ b/dist-material/bin/IoTServer.sh @@ -38,7 +38,7 @@ done IOT_OPTIONS=" -Doap.logDir=${IOT_LOG_DIR}" eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${IOT_OPTIONS} -classpath $CLASSPATH com.zmops.zeus.iot.server.starter.IOTServerStartUp \ - 2>${IOT_LOG_DIR}/zeus_iot.log 1> /dev/null &" + &> ${IOT_LOG_DIR}/zeus_iot.log &" if [ $? -eq 0 ]; then sleep 1 diff --git a/dist-material/bin/startup.sh b/dist-material/bin/startup.sh index 19f7af72..6b20758d 100644 --- a/dist-material/bin/startup.sh +++ b/dist-material/bin/startup.sh @@ -18,9 +18,9 @@ PRG="$0" PRGDIR=`dirname "$PRG"` -OAP_EXE=oapService.sh +IOT_EXE=IoTServer.sh WEBAPP_EXE=webappService.sh -"$PRGDIR"/"$OAP_EXE" +"$PRGDIR"/"$IOT_EXE" "$PRGDIR"/"$WEBAPP_EXE" diff --git a/dist-material/bin/stop.sh b/dist-material/bin/stop.sh old mode 100644 new mode 100755 diff --git a/dist-material/bin/webappService.sh b/dist-material/bin/webappService.sh index 5e93d2d3..83abf6e7 100644 --- a/dist-material/bin/webappService.sh +++ b/dist-material/bin/webappService.sh @@ -35,7 +35,7 @@ _RUNJAVA=${JAVA_HOME}/bin/java eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} -jar ${JAR_PATH}/zeus-webapp.jar \ --spring.config.location=${JAR_PATH}/webapp.yml \ --logging.file=${LOG_FILE_LOCATION} \ - 2>${WEBAPP_LOG_DIR}/webapp-console.log 1> /dev/null &" + &> ${WEBAPP_LOG_DIR}/webapp-console.log &" if [ $? -eq 0 ]; then sleep 1 From 70335a9c1ecd8586b7be5760e18ae0a8db8f5e20 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 18 Sep 2021 11:53:14 +0800 Subject: [PATCH 204/763] [fix]: remove test method --- .../zmops/iot/web/alarm/controller/AlarmController.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java index 423c8eac..c7cf9dc6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java @@ -18,10 +18,10 @@ public class AlarmController { @Autowired AlarmService alarmService; - @RequestMapping("/test") - public void test() { - alarmService.test(); - } +// @RequestMapping("/test") +// public void test() { +// alarmService.test(); +// } @RequestMapping("/getAlarmByPage") public ResponseData getAlarmByPage(@RequestBody AlarmParam alarmParam){ From 2d97f8476c551adf24654c711efba940762342b4 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 18 Sep 2021 12:06:25 +0800 Subject: [PATCH 205/763] [fix]: fix stop script --- dist-material/bin/stop.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/dist-material/bin/stop.sh b/dist-material/bin/stop.sh index 5e03aa58..126effa4 100755 --- a/dist-material/bin/stop.sh +++ b/dist-material/bin/stop.sh @@ -1,2 +1,10 @@ #!/bin/bash -ps -ef | grep zeus-iot-bin | grep -v grep | awk '{print $2}' | xargs kill -9 +status=`ps -ef | grep zeus-iot-bin | grep -v grep | awk '{print $2}' | wc -l` + +if [[ $status -ne 0 ]] +then + for i in `ps -ef | grep zeus-iot-bin | grep -v grep | awk '{print $2}'` + do + kill $i + done +fi From b5ed2ad3983f968198bdaf4ee7d556f44ebe45b3 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 18 Sep 2021 12:32:49 +0800 Subject: [PATCH 206/763] [feat]: macro service update --- .../web/macro/controller/MacroController.java | 48 +++++++++++++++++++ .../zmops/iot/web/macro/dto/UserMacro.java | 23 +++++++++ 2 files changed, 71 insertions(+) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java new file mode 100644 index 00000000..fa16b2d9 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java @@ -0,0 +1,48 @@ +package com.zmops.iot.web.macro.controller; + +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.macro.dto.UserMacro; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * @author nantian created at 2021/9/18 10:53 + */ + +@RequestMapping("/macro") +public class MacroController { + + /** + * 创建宏 + * + * @return + */ + @RequestMapping("/create") + public ResponseData createUserMacro(@RequestBody UserMacro userMacro) { + + + return ResponseData.success(); + } + + + @RequestMapping("/update") + public ResponseData updateUserMacro(@RequestBody UserMacro userMacro) { + + return ResponseData.success(); + } + + + @RequestMapping("/get") + public ResponseData getUserMacro(@RequestBody UserMacro userMacro) { + + return ResponseData.success(); + } + + + @RequestMapping("/delete") + public ResponseData deleteUserMacro(@RequestBody UserMacro userMacro) { + + return ResponseData.success(); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java new file mode 100644 index 00000000..82164a2a --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java @@ -0,0 +1,23 @@ +package com.zmops.iot.web.macro.dto; + +import lombok.Getter; +import lombok.Setter; + +/** + * @author nantian created at 2021/9/18 11:47 + */ + +@Getter +@Setter +public class UserMacro { + + private Long deviceId; // 产品ID 或者 设备ID + + private String macro; + + private String value; + + private String description; + + private String macro_old; +} From 9ebbef38436aa4c16eb24357ed9fde7d25831ff2 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 18 Sep 2021 14:49:34 +0800 Subject: [PATCH 207/763] [fix]: fix start script --- dist-material/bin/startup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist-material/bin/startup.sh b/dist-material/bin/startup.sh index 6b20758d..1a3efcc3 100644 --- a/dist-material/bin/startup.sh +++ b/dist-material/bin/startup.sh @@ -15,7 +15,7 @@ # limitations under the License. #!/usr/bin/env sh - +source /etc/profile PRG="$0" PRGDIR=`dirname "$PRG"` IOT_EXE=IoTServer.sh From da3da060749a93a1019cf7c53baa02ec01f85e3a Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 18 Sep 2021 16:50:50 +0800 Subject: [PATCH 208/763] [feat]: product attribute event --- .../domain/product/ProductAttributeEvent.java | 44 +++ .../zmops/zeus/driver/service/ZbxTrigger.java | 9 + .../api-json/script/script.init.create.ftl | 9 +- .../api-json/trigger/triggerAndTags.get.ftl | 11 + .../controller/DeviceEventController.java | 26 +- .../device/service/DeviceEventService.java | 19 ++ .../service/work/SaveAttributeWorker.java | 24 +- .../web/exception/enums/BizExceptionEnum.java | 1 + .../iot/web/init/DeviceSatusScriptInit.java | 23 +- .../ProductAttributeEventController.java | 125 ++++++++ .../controller/ProductEventController.java | 31 +- .../iot/web/product/dto/ProductAttr.java | 5 +- .../iot/web/product/dto/ProductAttrDto.java | 3 + .../web/product/dto/ProductEventRuleDto.java | 65 +++++ .../web/product/service/EventRuleService.java | 26 +- .../service/ProductAttributeEventService.java | 273 ++++++++++++++++++ .../work/AsyncAttrEventZbxIdWorker.java | 61 ++++ .../work/SaveProdAttrEventTriggerWorker.java | 49 ++++ .../service/work/SaveProdAttrEventWorker.java | 63 ++++ .../work/UpdateAttributeEventWorker.java | 51 ++++ 20 files changed, 884 insertions(+), 34 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttributeEvent.java create mode 100644 zeus-driver/src/main/resources/api-json/trigger/triggerAndTags.get.ftl create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttributeEvent.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttributeEvent.java new file mode 100644 index 00000000..046a043b --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttributeEvent.java @@ -0,0 +1,44 @@ +package com.zmops.iot.domain.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.zmops.iot.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author nantian created at 2021/8/5 13:03 + */ + +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "product_attribute_event") +public class ProductAttributeEvent extends BaseEntity { + + @Id + private Long attrId; //属性ID + + @JsonProperty("attrName") + private String name; // 属性名称 + + private String key; // 属性唯一Key + + private String units; // 单位 0 3 才有 + + private Byte eventLevel; + + private String remark; // 备注 + + private String valueType; + + private String productId; // 产品ID + + private String zbxId; // Zabbix itemId + + private Long templateId;//继承的ID + +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java index 25cdad74..42394c10 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java @@ -67,6 +67,15 @@ String triggerTagCreate(@ParamName("triggerId") String triggerId, @JsonPath("/trigger/trigger.get") String triggerGet(@ParamName("triggerIds") String triggerIds); + /** + * 根据TRIGGER ID查询触发器及触发器标签 + * + * @param triggerIds 触发器IDs + */ + @Post + @JsonPath("/trigger/triggerAndTags.get") + String triggerAndTagsGet(@ParamName("triggerIds") String triggerIds); + /** * 根据host 查询触发器 * diff --git a/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl b/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl index fdcaef45..66bb1720 100644 --- a/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl +++ b/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl @@ -9,12 +9,17 @@ "execute_on": 1 },{ "name": "__trigger_webhook__", <#-- 告警 回调 --> - "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"hostname\\":\\"{HOST.HOST}\\"}' http://127.0.0.1:9090/device/problem", + "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"hostname\\":\\"{HOST.HOST}\\",\\"triggerName\\":\\"{TRIGGER.NAME}\\"}' http://127.0.0.1:9090/device/problem", "type": 0, "execute_on": 1 },{ "name": "__trigger_execute__", <#-- 执行 方法 --> - "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"hostname\\":\\"{HOST.HOST}\\"}' http://127.0.0.1:12800/device/action/exec", + "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"triggerName\\":\\"{TRIGGER.NAME}\\",\\"triggerId\\":\\"{TRIGGER.ID}\\"}' http://127.0.0.1:12800/device/action/exec", + "type": 0, + "execute_on": 1 + },{ + "name": "__attr_event__", <#-- 属性事件 回调 --> + "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"hostname\\":\\"{HOST.HOST}\\",\\"itemName\\":\\"{ITEM.NAME}\\"}' http://127.0.0.1:12800/device/event", "type": 0, "execute_on": 1 } diff --git a/zeus-driver/src/main/resources/api-json/trigger/triggerAndTags.get.ftl b/zeus-driver/src/main/resources/api-json/trigger/triggerAndTags.get.ftl new file mode 100644 index 00000000..44f21db6 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/trigger/triggerAndTags.get.ftl @@ -0,0 +1,11 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.get", + "params": { + "selectTags":"extend", + "triggerids":${triggerIds}, + "output": "extend" + }, + "id": 1, + "auth": "${userAuth}" +} \ No newline at end of file diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java index 83faedd2..16acb204 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java @@ -2,6 +2,8 @@ import cn.hutool.core.util.IdUtil; import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.query.QProductEvent; import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventService; import com.zmops.iot.model.exception.ServiceException; @@ -14,10 +16,7 @@ import io.ebean.annotation.Transactional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.List; @@ -42,6 +41,21 @@ public class DeviceEventController { private static final String ALARM_TAG_NAME = "__alarm__"; private static final String EXECUTE_TAG_NAME = "__execute__"; + /** + * 触发器 详情 + * + * @param eventRuleId + * @return + */ + @GetMapping("/detail") + public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId, @RequestParam("deviceId") String deviceId) { + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRuleId).findOne(); + if (null == productEvent) { + throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); + } + return ResponseData.success(deviceEventService.detail(productEvent, eventRuleId, deviceId)); + } + /** * 修改 触发器 * @@ -55,7 +69,7 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn List deviceIds = eventRule.getExpList().parallelStream().map(ProductEventRule.Expression::getDeviceId) .collect(Collectors.toList()); - if(ToolUtil.isEmpty(deviceIds)){ + if (ToolUtil.isEmpty(deviceIds)) { throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); } //step 1: 删除原有的 关联关系 @@ -79,7 +93,7 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn //step 4: zbx 触发器创建 Tag Map tags = eventRule.getTags().stream() .collect(Collectors.toMap(ProductEventRule.Tag::getTag, ProductEventRule.Tag::getValue, (k1, k2) -> k2)); - if (ToolUtil.isEmpty(tags)){ + if (ToolUtil.isEmpty(tags)) { tags = new HashMap<>(2); } if (!tags.containsKey(ALARM_TAG_NAME)) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java index 703ac385..ab3efb97 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java @@ -1,16 +1,20 @@ package com.zmops.iot.web.device.service; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.ProductEventExpression; import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventExpression; import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventService; import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductEventRule; +import com.zmops.iot.web.product.dto.ProductEventRuleDto; import com.zmops.zeus.driver.service.ZbxTrigger; import io.ebean.DB; import lombok.Data; @@ -138,6 +142,21 @@ public void updateProductEventRuleZbxId(Long triggerId, String[] zbxId) { } + + public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, String deviceId) { + ProductEventRuleDto productEventRuleDto = new ProductEventRuleDto(); + ToolUtil.copyProperties(productEvent, productEventRuleDto); + + productEventRuleDto.setExpList(new QProductEventExpression().eventRuleId.eq(eventRuleId).findList()); + productEventRuleDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).deviceId.eq(deviceId).findList()); + + ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(deviceId).eventRuleId.eq(eventRuleId).findOne(); + JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); + productEventRuleDto.setTags(JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class)); + + return productEventRuleDto; + } + /** * 创建 触发器 * diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java index 3ea77ab6..625e944c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java @@ -6,7 +6,9 @@ import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.product.ProductAttribute; +import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.domain.product.query.QProductAttributeEvent; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; import io.ebean.DB; @@ -29,7 +31,7 @@ public class SaveAttributeWorker implements IWorker { @Override public Boolean action(DeviceDto deviceDto, Map> map) { - log.debug("处理Attr工作…………"); + log.debug("处理Attr 及Attr事件 工作…………"); String deviceId = deviceDto.getDeviceId(); @@ -40,14 +42,14 @@ public Boolean action(DeviceDto deviceDto, Map> map) return true; } new QProductAttribute().productId.eq(deviceId).templateId.isNotNull().delete(); + new QProductAttributeEvent().productId.eq(deviceId).templateId.isNotNull().delete(); } else { //创建 Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); deviceId = device.getDeviceId(); - } - + //属性 List productAttributeList = new QProductAttribute().productId.eq(deviceDto.getProductId() + "").findList(); List newProductAttributeList = new ArrayList<>(); @@ -62,6 +64,22 @@ public Boolean action(DeviceDto deviceDto, Map> map) } DB.saveAll(newProductAttributeList); + //属性事件 + List productAttributeEventList = new QProductAttributeEvent().productId.eq(deviceDto.getProductId() + "").findList(); + List newProductAttributeEventList = new ArrayList<>(); + + for (ProductAttributeEvent productAttributeEvent : productAttributeEventList) { + ProductAttributeEvent newProductAttrbuteEvent = new ProductAttributeEvent(); + ToolUtil.copyProperties(productAttributeEvent, newProductAttrbuteEvent); + newProductAttrbuteEvent.setTemplateId(productAttributeEvent.getAttrId()); + newProductAttrbuteEvent.setZbxId(""); + newProductAttrbuteEvent.setAttrId(IdUtil.getSnowflake().nextId()); + newProductAttrbuteEvent.setProductId(deviceId); + newProductAttributeEventList.add(newProductAttrbuteEvent); + } + DB.saveAll(newProductAttributeEventList); + + return true; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index 882ab546..9ed801a7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -162,6 +162,7 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { RULE_EXISTS(1702, "上下线规则已存在"), EVENT_HAS_NOT_DEVICE(1703,"告警规则缺少关联产品或设备"), + EVENT_NOT_EXISTS(1704, "告警规则不存在"), /** * 租户相关的异常 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java index 4430c1bb..c18bb91b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java @@ -24,14 +24,17 @@ public class DeviceSatusScriptInit implements CommandLineRunner { public static final String GLOBAL_ALARM_ACTION_CODE = "ZEUS_ALARM_ACTION_ID"; public static final String GLOBAL_EXEC_ACTION_CODE = "ZEUS_EXEC_ACTION_ID"; public static final String GLOBAL_ADMIN_ROLE_CODE = "ZEUS_ADMIN_ROLE_ID"; + public static final String GLOBAL_EVENT_ACTION_CODE = "ZEUS_EVENT_ACTION_ID"; public static final String SCRIPT_OFFLINE = "__offline_status__"; public static final String SCRIPT_ALARM = "__trigger_webhook__"; public static final String SCRIPT_EXECUTE = "__trigger_execute__"; + public static final String SCRIPT_EVENT = "__attr_event__"; public static final String ACTION_TAG_OFFLINE = "__offline__"; public static final String ACTION_TAG_ALARM = "__alarm__"; public static final String ACTION_TAG_EXECUTE = "__execute__"; + public static final String ACTION_TAG_EXENT = "__event__"; @Autowired @@ -71,22 +74,28 @@ public void run(String... args) throws Exception { String offLineActionId = basicSettingsInit.getAction(SCRIPT_OFFLINE); if (offLineActionId == null) { - offLineActionId = basicSettingsInit.createAction(SCRIPT_OFFLINE,ACTION_TAG_OFFLINE, script.get(SCRIPT_OFFLINE), groupId); + offLineActionId = basicSettingsInit.createAction(SCRIPT_OFFLINE, ACTION_TAG_OFFLINE, script.get(SCRIPT_OFFLINE), groupId); } DB.update(SysConfig.class).where().eq("code", GLOBAL_OFFLINE_ACTION_CODE).asUpdate().set("value", offLineActionId).update(); - String AlarmActionId = basicSettingsInit.getAction(SCRIPT_ALARM); - if (AlarmActionId == null) { - AlarmActionId = basicSettingsInit.createAction(SCRIPT_ALARM,ACTION_TAG_ALARM, script.get(SCRIPT_ALARM), groupId); + String alarmActionId = basicSettingsInit.getAction(SCRIPT_ALARM); + if (alarmActionId == null) { + alarmActionId = basicSettingsInit.createAction(SCRIPT_ALARM, ACTION_TAG_ALARM, script.get(SCRIPT_ALARM), groupId); } - DB.update(SysConfig.class).where().eq("code", GLOBAL_ALARM_ACTION_CODE).asUpdate().set("value", AlarmActionId).update(); + DB.update(SysConfig.class).where().eq("code", GLOBAL_ALARM_ACTION_CODE).asUpdate().set("value", alarmActionId).update(); String execActionId = basicSettingsInit.getAction(SCRIPT_EXECUTE); if (execActionId == null) { - execActionId = basicSettingsInit.createAction(SCRIPT_EXECUTE,ACTION_TAG_EXECUTE, script.get(SCRIPT_EXECUTE), groupId); + execActionId = basicSettingsInit.createAction(SCRIPT_EXECUTE, ACTION_TAG_EXECUTE, script.get(SCRIPT_EXECUTE), groupId); } DB.update(SysConfig.class).where().eq("code", GLOBAL_EXEC_ACTION_CODE).asUpdate().set("value", execActionId).update(); - log.info("全局主机组ID:{},在线触发动作ID:{},告警触发动作ID:{},命令执行触发动作ID:{}", groupId, offLineActionId, AlarmActionId, execActionId); + String eventActionId = basicSettingsInit.getAction(SCRIPT_EVENT); + if (eventActionId == null) { + eventActionId = basicSettingsInit.createAction(SCRIPT_EVENT, ACTION_TAG_EXENT, script.get(SCRIPT_EVENT), groupId); + } + DB.update(SysConfig.class).where().eq("code", GLOBAL_EVENT_ACTION_CODE).asUpdate().set("value", eventActionId).update(); + + log.info("全局主机组ID:{},在线触发动作ID:{},告警触发动作ID:{},命令执行触发动作ID:{},事件触发动作ID:{}", groupId, offLineActionId, alarmActionId, execActionId, eventActionId); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java new file mode 100644 index 00000000..6ccf663d --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java @@ -0,0 +1,125 @@ +package com.zmops.iot.web.product.controller; + +import cn.hutool.core.util.IdUtil; +import com.alibaba.fastjson.JSON; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.product.ProductAttribute; +import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.product.dto.ProductAttr; +import com.zmops.iot.web.product.dto.ProductAttrDto; +import com.zmops.iot.web.product.dto.param.ProductAttrParam; +import com.zmops.iot.web.product.service.ProductAttributeEventService; +import com.zmops.iot.web.product.service.ProductModelService; +import lombok.Data; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author nantian created at 2021/8/3 19:44 + *

+ * 产品 属性事件 + */ + +@RestController +@RequestMapping("/product/attribute/event") +public class ProductAttributeEventController { + + + @Autowired + private ProductAttributeEventService productAttributeEventService; + + + /** + * 产品属性事件 分页列表 + * + * @return ResponseData + */ + @RequestMapping("/getAttrEventByPage") + public Pager prodAttributeEventList(@RequestBody ProductAttrParam productAttr) { + return productAttributeEventService.prodAttributeEventList(productAttr); + } + + /** + * 属性事件 列表 + * + * @return ResponseData + */ + @RequestMapping("/list") + public ResponseData list(@RequestBody ProductAttrParam productAttr) { + return ResponseData.success(productAttributeEventService.list(productAttr)); + } + + /** + * 属性事件 详情 + * + * @return ResponseData + */ + @RequestMapping("/detail") + public ResponseData detail(@RequestParam(value = "attrId") Long attrId) { + return ResponseData.success(productAttributeEventService.detail(attrId)); + } + + /** + * 创建 产品属性事件 + * + * @return ResponseData + */ + @RequestMapping("/create") + public ResponseData prodModelAttributeCreate(@RequestBody @Validated(BaseEntity.Create.class) ProductAttr productAttr) { + int i = new QProductAttribute().productId.eq(productAttr.getProductId()).key.eq(productAttr.getKey()).findCount(); + if (i > 0) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_EXISTS); + } + + Long attrId = IdUtil.getSnowflake().nextId(); + productAttr.setAttrId(attrId); + + String response = productAttributeEventService.createTrapperItem(productAttr); + String zbxId = JSON.parseObject(response, TemplateIds.class).getItemids()[0]; + + productAttributeEventService.createProductAttr(productAttr,zbxId); + + return ResponseData.success(productAttr); + } + + /** + * 修改 产品属性事件 + * + * @return ResponseData + */ + @RequestMapping("/update") + public ResponseData prodModelAttributeUpdate(@RequestBody @Validated(BaseEntity.Update.class) ProductAttr productAttr) { + int i = new QProductAttribute().productId.eq(productAttr.getProductId()).key.eq(productAttr.getKey()) + .attrId.ne(productAttr.getAttrId()).findCount(); + if (i > 0) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_EXISTS); + } + + return ResponseData.success(productAttributeEventService.updateTrapperItem(productAttr)); + } + + /** + * 删除 产品属性事件 + * + * @return ResponseData + */ + @RequestMapping("/delete") + public ResponseData prodModelAttributeDelete(@RequestBody @Validated(BaseEntity.Delete.class) ProductAttr productAttr) { + + productAttributeEventService.deleteTrapperItem(productAttr); + return ResponseData.success(); + } + + @Data + static class TemplateIds { + private String[] itemids; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java index 7efd04cc..2c3b9e21 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java @@ -8,12 +8,13 @@ import com.zmops.iot.domain.product.query.QProductEventExpression; import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductEventDto; import com.zmops.iot.web.product.dto.ProductEventRule; -import com.zmops.iot.web.product.dto.ProductTag; import com.zmops.iot.web.product.dto.param.EventParm; import com.zmops.iot.web.product.service.EventRuleService; import com.zmops.zeus.driver.service.ZbxTrigger; @@ -21,10 +22,7 @@ import io.ebean.annotation.Transactional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.List; @@ -63,6 +61,21 @@ public Pager getEventByPage(@RequestBody EventParm eventParm) { return eventRuleService.getEventByPage(eventParm); } + /** + * 触发器 详情 + * + * @param eventRuleId + * @return + */ + @GetMapping("/detail") + public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId,@RequestParam("prodId") String prodId) { + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRuleId).findOne(); + if (null == productEvent) { + throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); + } + return ResponseData.success(eventRuleService.detail(productEvent,eventRuleId,prodId)); + } + /** * 创建 触发器 * @@ -84,11 +97,11 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE //step 2: zbx 保存触发器 String[] triggerIds = eventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); - + //step 4: zbx 触发器创建 Tag Map tags = eventRule.getTags().stream() .collect(Collectors.toMap(ProductEventRule.Tag::getTag, ProductEventRule.Tag::getValue, (k1, k2) -> k2)); - if (ToolUtil.isEmpty(tags)){ + if (ToolUtil.isEmpty(tags)) { tags = new HashMap<>(2); } if (!tags.containsKey(ALARM_TAG_NAME)) { @@ -137,7 +150,7 @@ public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseE //step 3: zbx 触发器创建 Tag Map tags = eventRule.getTags().stream() .collect(Collectors.toMap(ProductEventRule.Tag::getTag, ProductEventRule.Tag::getValue, (k1, k2) -> k2)); - if (ToolUtil.isEmpty(tags)){ + if (ToolUtil.isEmpty(tags)) { tags = new HashMap<>(2); } if (!tags.containsKey(ALARM_TAG_NAME)) { @@ -161,7 +174,7 @@ public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseE */ @PostMapping("/status") public ResponseData updateProductEventStatus(@RequestBody @Validated(value = BaseEntity.Status.class) ProductEventRule eventRule) { - DB.update(ProductEvent.class).where().eq("eventRuleId",eventRule.getEventRuleId()).asUpdate().set("status",eventRule.getStatus()).update(); + DB.update(ProductEvent.class).where().eq("eventRuleId", eventRule.getEventRuleId()).asUpdate().set("status", eventRule.getStatus()).update(); return ResponseData.success(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java index 9768e0f0..ef37ed4e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java @@ -31,12 +31,12 @@ public class ProductAttr { private String key; private String units; - private String unitName; //来源:设备 trapper ,属性依赖 dependent @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) private String source; - private String sourceName; + + private Byte eventLevel = 1; private String remark; @@ -53,7 +53,6 @@ public class ProductAttr { @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) private String valueType; - private String valueTypeName; private String valuemapid; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java index 12b88928..1ff13421 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java @@ -38,6 +38,9 @@ public class ProductAttrDto { private Long depAttrId; + @CachedValue(value = "EVENT_LEVEL") + private String eventLevel; + @JsonIgnore private String zbxId; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java new file mode 100644 index 00000000..3e9f5997 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java @@ -0,0 +1,65 @@ +package com.zmops.iot.web.product.dto; + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.product.ProductEventExpression; +import com.zmops.iot.domain.product.ProductEventService; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.Valid; +import javax.validation.constraints.Max; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author nantian created at 2021/9/14 14:47 + *

+ * 告警规则 + */ + +@Getter +@Setter +public class ProductEventRuleDto { + + private Long eventRuleId; + + private Byte eventNotify; + private String eventRuleName; + + private Byte eventLevel; + + private List expList; + + private String expLogic; + + private String remark; + + private List deviceServices; + + private List tags; + + private Integer zbxId; + + private String productId; + + private String status; + + @Data + public static class Tag { + + @Max(20) + private String tag; + + @Max(50) + private String value; + } + + +} + + + + diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java index 2c407ab4..e1682b17 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java @@ -1,12 +1,15 @@ package com.zmops.iot.web.product.service; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.ProductEventExpression; import com.zmops.iot.domain.product.ProductEventRelation; import com.zmops.iot.domain.product.query.QProductEvent; +import com.zmops.iot.domain.product.query.QProductEventExpression; import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventService; import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; @@ -14,6 +17,7 @@ import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductEventDto; import com.zmops.iot.web.product.dto.ProductEventRule; +import com.zmops.iot.web.product.dto.ProductEventRuleDto; import com.zmops.iot.web.product.dto.param.EventParm; import com.zmops.zeus.driver.service.ZbxTrigger; import io.ebean.DB; @@ -22,10 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; /** @@ -225,6 +226,9 @@ public Pager getEventByPage(EventParm eventParm) { if (ToolUtil.isNotEmpty(eventParm.getProdId())) { List eventRuleIdList = new QProductEventRelation().select(QProductEventRelation.alias().eventRuleId) .relationId.eq(eventParm.getProdId()).findSingleAttributeList(); + if (ToolUtil.isEmpty(eventRuleIdList)) { + return new Pager<>(); + } if (ToolUtil.isNotEmpty(eventRuleIdList)) { query.eventRuleId.in(eventRuleIdList); @@ -237,6 +241,20 @@ public Pager getEventByPage(EventParm eventParm) { return new Pager<>(list, query.findCount()); } + public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, String prodId) { + ProductEventRuleDto productEventRuleDto = new ProductEventRuleDto(); + ToolUtil.copyProperties(productEvent, productEventRuleDto); + + productEventRuleDto.setExpList(new QProductEventExpression().eventRuleId.eq(eventRuleId).findList()); + productEventRuleDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).deviceId.isNull().findList()); + + ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(prodId).eventRuleId.eq(eventRuleId).findOne(); + JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); + productEventRuleDto.setTags(JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class)); + + return productEventRuleDto; + } + @Data static class TriggerIds { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java new file mode 100644 index 00000000..c8c8d47e --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -0,0 +1,273 @@ +package com.zmops.iot.web.product.service; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.async.executor.Async; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.product.Product; +import com.zmops.iot.domain.product.ProductAttributeEvent; +import com.zmops.iot.domain.product.query.QProduct; +import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.domain.product.query.QProductAttributeEvent; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.product.dto.ProductAttr; +import com.zmops.iot.web.product.dto.ProductAttrDto; +import com.zmops.iot.web.product.dto.ProductTag; +import com.zmops.iot.web.product.dto.param.ProductAttrParam; +import com.zmops.iot.web.product.service.work.AsyncAttrEventZbxIdWorker; +import com.zmops.iot.web.product.service.work.SaveProdAttrEventWorker; +import com.zmops.iot.web.product.service.work.UpdateAttributeWorker; +import com.zmops.zeus.driver.entity.ZbxProcessingStep; +import com.zmops.zeus.driver.service.ZbxItem; +import io.ebean.DB; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author yefei + **/ +@Service +public class ProductAttributeEventService { + + @Autowired + private ZbxItem zbxItem; + + @Autowired + SaveProdAttrEventWorker saveProdAttrEventWorker; + + @Autowired + AsyncAttrEventZbxIdWorker asyncAttrEventZbxIdWorker; + + @Autowired + UpdateAttributeWorker updateProdAttrWorker; + + /** + * 产品属性分页列表 + * + * @param productAttr + * @return + */ + public Pager prodAttributeEventList(ProductAttrParam productAttr) { + QProductAttribute qProductAttribute = new QProductAttribute(); + + if (ToolUtil.isNotEmpty(productAttr.getProdId())) { + qProductAttribute.productId.eq(productAttr.getProdId()); + } + if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { + qProductAttribute.name.contains(productAttr.getAttrName()); + } + if (ToolUtil.isNotEmpty(productAttr.getKey())) { + qProductAttribute.key.contains(productAttr.getKey()); + } + + List pagedList = qProductAttribute.setFirstRow((productAttr.getPage() - 1) * productAttr.getMaxRow()).setMaxRows(productAttr.getMaxRow()).asDto(ProductAttrDto.class).findList(); + int count = qProductAttribute.findCount(); + return new Pager<>(pagedList, count); + } + + /** + * 产品属性列表 + * + * @param productAttr + * @return + */ + public List list(ProductAttrParam productAttr) { + QProductAttribute qProductAttribute = new QProductAttribute(); + if (null != productAttr.getProdId()) { + qProductAttribute.productId.eq(productAttr.getProdId()); + } + if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { + qProductAttribute.name.contains(productAttr.getAttrName()); + } + if (ToolUtil.isNotEmpty(productAttr.getKey())) { + qProductAttribute.key.contains(productAttr.getKey()); + } + return qProductAttribute.orderBy(" create_time desc").asDto(ProductAttrDto.class).findList(); + } + + /** + * 产品属性详情 + * + * @param attrId + * @return + */ + public ProductAttrDto detail(Long attrId) { + ProductAttrDto attr = new QProductAttribute().attrId.eq(attrId).asDto(ProductAttrDto.class).findOne(); + + if (null == attr.getZbxId()) { + return attr; + } + JSONArray itemInfo = JSONObject.parseArray(zbxItem.getItemInfo(attr.getZbxId(), null)); + attr.setTags(JSONObject.parseArray(itemInfo.getJSONObject(0).getString("tags"), ProductTag.Tag.class)); + attr.setProcessStepList(formatProcessStep(itemInfo.getJSONObject(0).getString("preprocessing"))); + String valuemap = itemInfo.getJSONObject(0).getString("valuemap"); + if (ToolUtil.isNotEmpty(valuemap) && !"[]".equals(valuemap)) { + attr.setValuemapid(JSONObject.parseObject(valuemap).getString("valuemapid")); + } + return attr; + } + + private List formatProcessStep(String preprocessing) { + if (ToolUtil.isEmpty(preprocessing)) { + return Collections.emptyList(); + } + List processingSteps = new ArrayList<>(); + JSONArray jsonArray = JSONObject.parseArray(preprocessing); + for (Object object : jsonArray) { + ProductAttr.ProcessingStep processingStep = new ProductAttr.ProcessingStep(); + processingStep.setType(((JSONObject) object).getString("type")); + processingStep.setParams(((JSONObject) object).getString("params").split("\\n")); + processingSteps.add(processingStep); + } + + return processingSteps; + } + + /** + * 创建 产品属性 + * + * @param productAttr 产品属性DTO + */ + public void createProductAttr(ProductAttr productAttr, String zbxId) { + ProductAttributeEvent productAttributeEvent = new ProductAttributeEvent(); + buildProdAttribute(productAttributeEvent, productAttr); + productAttributeEvent.setZbxId(zbxId); + productAttributeEvent.save(); + + + WorkerWrapper asyncAttrEventZbxIdWork = WorkerWrapper.builder() + .worker(asyncAttrEventZbxIdWorker).param(productAttr).build(); + WorkerWrapper saveProdAttrEventWork = WorkerWrapper.builder() + .worker(saveProdAttrEventWorker).param(productAttr).nextOf(asyncAttrEventZbxIdWork).build(); + + try { + Async.work(10000, saveProdAttrEventWork).awaitFinish(); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + private ProductAttributeEvent buildProdAttribute(ProductAttributeEvent prodAttribute, ProductAttr productAttr) { + prodAttribute.setProductId(productAttr.getProductId()); + prodAttribute.setName(productAttr.getAttrName()); + prodAttribute.setKey(productAttr.getKey()); + prodAttribute.setUnits(productAttr.getUnits()); + prodAttribute.setRemark(productAttr.getRemark()); + prodAttribute.setValueType(productAttr.getValueType()); + prodAttribute.setAttrId(productAttr.getAttrId()); + prodAttribute.setEventLevel(productAttr.getEventLevel()); + return prodAttribute; + } + + /** + * 创建 Trapper 类型 ITEM + * + * @param productAttr 属性 + * @return String + */ + public String createTrapperItem(ProductAttr productAttr) { + + String itemName = productAttr.getAttrId() + ""; + + Product prod = new QProduct().productId.eq(Long.parseLong(productAttr.getProductId())).findOne(); + if (null == prod) { + throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); + } + String hostId = prod.getZbxId(); + + List processingSteps = new ArrayList<>(); + if (ToolUtil.isNotEmpty(productAttr.getProcessStepList())) { + productAttr.getProcessStepList().forEach(i -> { + ZbxProcessingStep step = new ZbxProcessingStep(); + + step.setType(i.getType()); + step.setParams(i.getParams()); + + processingSteps.add(step); + }); + } + Map tagMap = new HashMap<>(); + if (ToolUtil.isNotEmpty(productAttr.getTags())) { + tagMap = productAttr.getTags().stream() + .collect(Collectors.toMap(ProductTag.Tag::getTag, ProductTag.Tag::getValue, (k1, k2) -> k2)); + } + + return zbxItem.createTrapperItem(itemName, productAttr.getKey(), + hostId, "2", null, productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + } + + /** + * 修改 Trapper 类型 ITEM + * + * @param productAttr 属性 + * @return String + */ + public ProductAttr updateTrapperItem(ProductAttr productAttr) { + ProductAttributeEvent productAttributeEvent = new QProductAttributeEvent().attrId.eq(productAttr.getAttrId()).findOne(); + buildProdAttribute(productAttributeEvent, productAttr); + Product prod = new QProduct().productId.eq(Long.parseLong(productAttr.getProductId())).findOne(); + if (null == prod) { + throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); + } + String hostId = prod.getZbxId(); + List processingSteps = new ArrayList<>(); + if (ToolUtil.isNotEmpty(productAttr.getProcessStepList())) { + productAttr.getProcessStepList().forEach(i -> { + ZbxProcessingStep step = new ZbxProcessingStep(); + + step.setType(i.getType()); + step.setParams(i.getParams()); + + processingSteps.add(step); + }); + } + + Map tagMap = new HashMap<>(); + if (ToolUtil.isNotEmpty(productAttr.getTags())) { + tagMap = productAttr.getTags().stream() + .collect(Collectors.toMap(ProductTag.Tag::getTag, ProductTag.Tag::getValue, (k1, k2) -> k2)); + } + + + zbxItem.updateTrapperItem(productAttributeEvent.getZbxId(), productAttr.getAttrId() + "", productAttr.getKey(), + hostId, "2", null, productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + + DB.update(productAttributeEvent); + + WorkerWrapper updateProdAttrWork = WorkerWrapper.builder().worker(updateProdAttrWorker).param(productAttr).build(); + + try { + Async.work(100, updateProdAttrWork).awaitFinish(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + return productAttr; + } + + /** + * 删称 Trapper 类型 ITEM + * + * @param productAttr 属性 + * @return String + */ + public void deleteTrapperItem(ProductAttr productAttr) { + + List zbxIds = new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(productAttr.getAttrIds()).findSingleAttributeList(); + //删除zbx item + zbxItem.deleteTrapperItem(zbxIds); + + //删除 属性 + new QProductAttribute().attrId.in(productAttr.getAttrIds()).delete(); + + //删除 设备 继承的属性 + new QProductAttribute().templateId.in(productAttr.getAttrIds()).delete(); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java new file mode 100644 index 00000000..a8677b0d --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java @@ -0,0 +1,61 @@ +package com.zmops.iot.web.product.service.work; + + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.async.callback.IWorker; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.product.ProductAttributeEvent; +import com.zmops.iot.domain.product.query.QProductAttributeEvent; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.product.dto.ProductAttr; +import com.zmops.zeus.driver.entity.ZbxItemInfo; +import com.zmops.zeus.driver.service.ZbxItem; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 更新设备属性事件中ZBXID + */ +@Slf4j +@Component +public class AsyncAttrEventZbxIdWorker implements IWorker { + + @Autowired + ZbxItem zbxItem; + + @Override + public Boolean action(ProductAttr productAttr, Map> map) { + log.debug("处理Attr zbx回填工作……"); + Long attrId = productAttr.getAttrId(); + + //根据name 取出监控项 + List itemInfos = JSONObject.parseArray(zbxItem.getItemListByName(attrId + ""), ZbxItemInfo.class); + if (ToolUtil.isEmpty(itemInfos)) { + return true; + } + + Map itemMap = itemInfos.parallelStream().collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), o -> o)); + //取出继承的属性 并塞入对应的 itemId + List productAttributeEventList = new QProductAttributeEvent().templateId.eq(attrId).findList(); + for (ProductAttributeEvent productAttributeEvent : productAttributeEventList) { + productAttributeEvent.setZbxId(itemMap.get(productAttributeEvent.getProductId() + "").getItemid()); + } + + DB.updateAll(productAttributeEventList); + return true; + } + + @Override + public Boolean defaultValue() { + return true; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java new file mode 100644 index 00000000..6d62ac9a --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java @@ -0,0 +1,49 @@ +package com.zmops.iot.web.product.service.work; + + +import com.zmops.iot.async.callback.IWorker; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.web.product.dto.ProductAttr; +import com.zmops.zeus.driver.service.ZbxTrigger; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author yefei + *

+ * 产品属性事件创建 告警 步骤 + */ +@Slf4j +@Component +public class SaveProdAttrEventTriggerWorker implements IWorker { + + @Autowired + private ZbxTrigger zbxTrigger; + + @Override + public Boolean action(ProductAttr productAttr, Map> map) { + log.debug("处理产品 新增Attr事件 告警工作…………"); + + String prodId = productAttr.getProductId(); + StringBuilder expression = new StringBuilder(); + expression.append("count(/"); + expression.append(prodId); + expression.append("/"); + expression.append(productAttr.getKey()); + expression.append(",#1"); + expression.append(") >0 "); + zbxTrigger.triggerCreate(productAttr.getProductId(), expression.toString(), productAttr.getEventLevel()); + + return true; + } + + + @Override + public Boolean defaultValue() { + return true; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java new file mode 100644 index 00000000..f0db8be5 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java @@ -0,0 +1,63 @@ +package com.zmops.iot.web.product.service.work; + + +import cn.hutool.core.util.IdUtil; +import com.zmops.iot.async.callback.IWorker; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductAttributeEvent; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.product.dto.ProductAttr; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author yefei + *

+ * 产品属性事件创建 同步到设备 步骤 + */ +@Slf4j +@Component +public class SaveProdAttrEventWorker implements IWorker { + + + @Override + public Boolean action(ProductAttr productAttr, Map> map) { + log.debug("处理产品 新增Attr 同步到设备工作…………"); + String prodId = productAttr.getProductId(); + + int count = new QDevice().deviceId.eq(prodId).findCount(); + if (count > 0) { + return true; + } + + List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); + + List productAttributeEventList = new ArrayList<>(); + + for (String deviceId : deviceIds) { + ProductAttributeEvent productAttributeEvent = new ProductAttributeEvent(); + ToolUtil.copyProperties(productAttr, productAttributeEvent); + productAttributeEvent.setAttrId(IdUtil.getSnowflake().nextId()); + productAttributeEvent.setName(productAttr.getAttrName()); + productAttributeEvent.setProductId(deviceId); + productAttributeEvent.setTemplateId(productAttr.getAttrId()); + productAttributeEventList.add(productAttributeEvent); + } + DB.saveAll(productAttributeEventList); + + return true; + } + + + @Override + public Boolean defaultValue() { + return true; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java new file mode 100644 index 00000000..c643d0f2 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java @@ -0,0 +1,51 @@ +package com.zmops.iot.web.product.service.work; + + +import com.zmops.iot.async.callback.IWorker; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.product.ProductAttributeEvent; +import com.zmops.iot.domain.product.query.QProductAttributeEvent; +import com.zmops.iot.web.product.dto.ProductAttr; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +/** + * @author yefei + *

+ * 产品属性修改 同步到设备 步骤 + */ +@Slf4j +@Component +public class UpdateAttributeEventWorker implements IWorker { + + + @Override + public Boolean action(ProductAttr productAttr, Map> map) { + log.debug("处理产品属性事件修改 同步到设备工作…………"); + + Long attrId = productAttr.getAttrId(); + + List list = new QProductAttributeEvent().templateId.eq(attrId).findList(); + + for (ProductAttributeEvent productAttributeEvent : list) { + productAttributeEvent.setName(productAttr.getAttrName()); + productAttributeEvent.setKey(productAttr.getKey()); + productAttributeEvent.setUnits(productAttr.getUnits()); + productAttributeEvent.setValueType(productAttr.getValueType()); + } + DB.updateAll(list); + + return true; + } + + + @Override + public Boolean defaultValue() { + return true; + } + +} From 8c2937a64bc72539ef3615cea1e0af22197ccc89 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 18 Sep 2021 17:15:06 +0800 Subject: [PATCH 209/763] [fix]: fix sh script --- dist-material/bin/IoTServer.sh | 2 +- dist-material/bin/startup.sh | 2 +- dist-material/bin/webappService.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dist-material/bin/IoTServer.sh b/dist-material/bin/IoTServer.sh index b6fbee23..fe0ff2e6 100644 --- a/dist-material/bin/IoTServer.sh +++ b/dist-material/bin/IoTServer.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env sh +#!/usr/bin/env bash # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information diff --git a/dist-material/bin/startup.sh b/dist-material/bin/startup.sh index 1a3efcc3..274eeffa 100644 --- a/dist-material/bin/startup.sh +++ b/dist-material/bin/startup.sh @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -#!/usr/bin/env sh +#!/usr/bin/env bash source /etc/profile PRG="$0" PRGDIR=`dirname "$PRG"` diff --git a/dist-material/bin/webappService.sh b/dist-material/bin/webappService.sh index 83abf6e7..965940c8 100644 --- a/dist-material/bin/webappService.sh +++ b/dist-material/bin/webappService.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env sh +#!/usr/bin/env bash # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information From 87a08d7334fe51378fddc27ebeff94d369d777f1 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 18 Sep 2021 18:20:51 +0800 Subject: [PATCH 210/763] [fix]: fix product attrubite event --- .../ProductAttributeEventController.java | 7 +- .../iot/web/product/dto/ProductAttrEvent.java | 99 +++++++++++++++++++ .../service/ProductAttributeEventService.java | 30 +++--- .../work/AsyncAttrEventZbxIdWorker.java | 5 +- .../work/SaveProdAttrEventTriggerWorker.java | 6 +- .../service/work/SaveProdAttrEventWorker.java | 5 +- .../work/UpdateAttributeEventWorker.java | 5 +- 7 files changed, 132 insertions(+), 25 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrEvent.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java index 6ccf663d..d75afc88 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java @@ -11,6 +11,7 @@ import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.iot.web.product.dto.ProductAttrDto; +import com.zmops.iot.web.product.dto.ProductAttrEvent; import com.zmops.iot.web.product.dto.param.ProductAttrParam; import com.zmops.iot.web.product.service.ProductAttributeEventService; import com.zmops.iot.web.product.service.ProductModelService; @@ -73,7 +74,7 @@ public ResponseData detail(@RequestParam(value = "attrId") Long attrId) { * @return ResponseData */ @RequestMapping("/create") - public ResponseData prodModelAttributeCreate(@RequestBody @Validated(BaseEntity.Create.class) ProductAttr productAttr) { + public ResponseData prodModelAttributeCreate(@RequestBody @Validated(BaseEntity.Create.class) ProductAttrEvent productAttr) { int i = new QProductAttribute().productId.eq(productAttr.getProductId()).key.eq(productAttr.getKey()).findCount(); if (i > 0) { throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_EXISTS); @@ -96,7 +97,7 @@ public ResponseData prodModelAttributeCreate(@RequestBody @Validated(BaseEntity. * @return ResponseData */ @RequestMapping("/update") - public ResponseData prodModelAttributeUpdate(@RequestBody @Validated(BaseEntity.Update.class) ProductAttr productAttr) { + public ResponseData prodModelAttributeUpdate(@RequestBody @Validated(BaseEntity.Update.class) ProductAttrEvent productAttr) { int i = new QProductAttribute().productId.eq(productAttr.getProductId()).key.eq(productAttr.getKey()) .attrId.ne(productAttr.getAttrId()).findCount(); if (i > 0) { @@ -112,7 +113,7 @@ public ResponseData prodModelAttributeUpdate(@RequestBody @Validated(BaseEntity. * @return ResponseData */ @RequestMapping("/delete") - public ResponseData prodModelAttributeDelete(@RequestBody @Validated(BaseEntity.Delete.class) ProductAttr productAttr) { + public ResponseData prodModelAttributeDelete(@RequestBody @Validated(BaseEntity.Delete.class) ProductAttrEvent productAttr) { productAttributeEventService.deleteTrapperItem(productAttr); return ResponseData.success(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrEvent.java new file mode 100644 index 00000000..75d43bd8 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrEvent.java @@ -0,0 +1,99 @@ +package com.zmops.iot.web.product.dto; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.zmops.iot.domain.BaseEntity; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; +import java.util.List; + +/** + * @author nantian created at 2021/8/5 13:53 + *

+ * dto for product attribute + */ + +@Data +public class ProductAttrEvent { + + @NotNull(groups = BaseEntity.Update.class) + private Long attrId; + + //属性名 非 item name + @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) + private String attrName; + + @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) + private String key; + + private String units; + + private Byte eventLevel = 1; + + private String remark; + + private Long depAttrId; + + @JsonIgnore + private String masterItemId; + + @JsonIgnore + private String zbxId; + + @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) + private String productId; + + @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) + private String valueType; + + private String valuemapid; + + private List tags; + + //预处理 + private List processStepList; + + @NotEmpty(groups = BaseEntity.Delete.class) + private List attrIds; + + LocalDateTime createTime; + LocalDateTime updateTime; + Long createUser; + Long updateUser; + + /** + * 预处理步骤 + */ + public static class ProcessingStep { + + @Getter + @Setter + private String type; + + @Setter + private String[] params; + + @Getter + @Setter + private String errorHandler; + + @Getter + @Setter + private String errorHandlerParams; + + public String getParams() { + StringBuilder paramStr = new StringBuilder(); + if (null != params && params.length > 0) { + for (String param : params) { + paramStr.append(param).append("\\\\n"); + } + return paramStr.substring(0, paramStr.length() - 3); + } + return ""; + } + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java index c8c8d47e..841ad28f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -15,11 +15,10 @@ import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.iot.web.product.dto.ProductAttrDto; +import com.zmops.iot.web.product.dto.ProductAttrEvent; import com.zmops.iot.web.product.dto.ProductTag; import com.zmops.iot.web.product.dto.param.ProductAttrParam; -import com.zmops.iot.web.product.service.work.AsyncAttrEventZbxIdWorker; -import com.zmops.iot.web.product.service.work.SaveProdAttrEventWorker; -import com.zmops.iot.web.product.service.work.UpdateAttributeWorker; +import com.zmops.iot.web.product.service.work.*; import com.zmops.zeus.driver.entity.ZbxProcessingStep; import com.zmops.zeus.driver.service.ZbxItem; import io.ebean.DB; @@ -45,7 +44,10 @@ public class ProductAttributeEventService { AsyncAttrEventZbxIdWorker asyncAttrEventZbxIdWorker; @Autowired - UpdateAttributeWorker updateProdAttrWorker; + UpdateAttributeEventWorker updateAttributeEventWorker; + + @Autowired + SaveProdAttrEventTriggerWorker saveProdAttrEventTriggerWorker; /** * 产品属性分页列表 @@ -134,27 +136,29 @@ private List formatProcessStep(String preprocessing) * * @param productAttr 产品属性DTO */ - public void createProductAttr(ProductAttr productAttr, String zbxId) { + public void createProductAttr(ProductAttrEvent productAttr, String zbxId) { ProductAttributeEvent productAttributeEvent = new ProductAttributeEvent(); buildProdAttribute(productAttributeEvent, productAttr); productAttributeEvent.setZbxId(zbxId); productAttributeEvent.save(); - WorkerWrapper asyncAttrEventZbxIdWork = WorkerWrapper.builder() + WorkerWrapper saveProdAttrEventTriggerWork = WorkerWrapper.builder() + .worker(saveProdAttrEventTriggerWorker).param(productAttr).build(); + WorkerWrapper asyncAttrEventZbxIdWork = WorkerWrapper.builder() .worker(asyncAttrEventZbxIdWorker).param(productAttr).build(); - WorkerWrapper saveProdAttrEventWork = WorkerWrapper.builder() + WorkerWrapper saveProdAttrEventWork = WorkerWrapper.builder() .worker(saveProdAttrEventWorker).param(productAttr).nextOf(asyncAttrEventZbxIdWork).build(); try { - Async.work(10000, saveProdAttrEventWork).awaitFinish(); + Async.work(10000, saveProdAttrEventWork,saveProdAttrEventTriggerWork).awaitFinish(); } catch (Exception e) { e.printStackTrace(); } } - private ProductAttributeEvent buildProdAttribute(ProductAttributeEvent prodAttribute, ProductAttr productAttr) { + private ProductAttributeEvent buildProdAttribute(ProductAttributeEvent prodAttribute, ProductAttrEvent productAttr) { prodAttribute.setProductId(productAttr.getProductId()); prodAttribute.setName(productAttr.getAttrName()); prodAttribute.setKey(productAttr.getKey()); @@ -172,7 +176,7 @@ private ProductAttributeEvent buildProdAttribute(ProductAttributeEvent prodAttri * @param productAttr 属性 * @return String */ - public String createTrapperItem(ProductAttr productAttr) { + public String createTrapperItem(ProductAttrEvent productAttr) { String itemName = productAttr.getAttrId() + ""; @@ -209,7 +213,7 @@ public String createTrapperItem(ProductAttr productAttr) { * @param productAttr 属性 * @return String */ - public ProductAttr updateTrapperItem(ProductAttr productAttr) { + public ProductAttrEvent updateTrapperItem(ProductAttrEvent productAttr) { ProductAttributeEvent productAttributeEvent = new QProductAttributeEvent().attrId.eq(productAttr.getAttrId()).findOne(); buildProdAttribute(productAttributeEvent, productAttr); Product prod = new QProduct().productId.eq(Long.parseLong(productAttr.getProductId())).findOne(); @@ -241,7 +245,7 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { DB.update(productAttributeEvent); - WorkerWrapper updateProdAttrWork = WorkerWrapper.builder().worker(updateProdAttrWorker).param(productAttr).build(); + WorkerWrapper updateProdAttrWork = WorkerWrapper.builder().worker(updateAttributeEventWorker).param(productAttr).build(); try { Async.work(100, updateProdAttrWork).awaitFinish(); @@ -258,7 +262,7 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { * @param productAttr 属性 * @return String */ - public void deleteTrapperItem(ProductAttr productAttr) { + public void deleteTrapperItem(ProductAttrEvent productAttr) { List zbxIds = new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(productAttr.getAttrIds()).findSingleAttributeList(); //删除zbx item diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java index a8677b0d..726b98e4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java @@ -8,6 +8,7 @@ import com.zmops.iot.domain.product.query.QProductAttributeEvent; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.product.dto.ProductAttr; +import com.zmops.iot.web.product.dto.ProductAttrEvent; import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.service.ZbxItem; import io.ebean.DB; @@ -26,13 +27,13 @@ */ @Slf4j @Component -public class AsyncAttrEventZbxIdWorker implements IWorker { +public class AsyncAttrEventZbxIdWorker implements IWorker { @Autowired ZbxItem zbxItem; @Override - public Boolean action(ProductAttr productAttr, Map> map) { + public Boolean action(ProductAttrEvent productAttr, Map> map) { log.debug("处理Attr zbx回填工作……"); Long attrId = productAttr.getAttrId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java index 6d62ac9a..8cab5df3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java @@ -3,7 +3,7 @@ import com.zmops.iot.async.callback.IWorker; import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.web.product.dto.ProductAttr; +import com.zmops.iot.web.product.dto.ProductAttrEvent; import com.zmops.zeus.driver.service.ZbxTrigger; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -18,13 +18,13 @@ */ @Slf4j @Component -public class SaveProdAttrEventTriggerWorker implements IWorker { +public class SaveProdAttrEventTriggerWorker implements IWorker { @Autowired private ZbxTrigger zbxTrigger; @Override - public Boolean action(ProductAttr productAttr, Map> map) { + public Boolean action(ProductAttrEvent productAttr, Map> map) { log.debug("处理产品 新增Attr事件 告警工作…………"); String prodId = productAttr.getProductId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java index f0db8be5..63e63061 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java @@ -8,6 +8,7 @@ import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.product.dto.ProductAttr; +import com.zmops.iot.web.product.dto.ProductAttrEvent; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -23,11 +24,11 @@ */ @Slf4j @Component -public class SaveProdAttrEventWorker implements IWorker { +public class SaveProdAttrEventWorker implements IWorker { @Override - public Boolean action(ProductAttr productAttr, Map> map) { + public Boolean action(ProductAttrEvent productAttr, Map> map) { log.debug("处理产品 新增Attr 同步到设备工作…………"); String prodId = productAttr.getProductId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java index c643d0f2..38a56b6d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java @@ -6,6 +6,7 @@ import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.domain.product.query.QProductAttributeEvent; import com.zmops.iot.web.product.dto.ProductAttr; +import com.zmops.iot.web.product.dto.ProductAttrEvent; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -20,11 +21,11 @@ */ @Slf4j @Component -public class UpdateAttributeEventWorker implements IWorker { +public class UpdateAttributeEventWorker implements IWorker { @Override - public Boolean action(ProductAttr productAttr, Map> map) { + public Boolean action(ProductAttrEvent productAttr, Map> map) { log.debug("处理产品属性事件修改 同步到设备工作…………"); Long attrId = productAttr.getAttrId(); From 88ecac97f62c3d87154b47c61969fa98ff18f65c Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 18 Sep 2021 18:21:14 +0800 Subject: [PATCH 211/763] [feat]: user macro --- .../zmops/zeus/driver/service/ZbxMacro.java | 14 +++-- .../api-json/macro/usermacro.create.ftl | 5 +- .../api-json/macro/usermacro.filter.get.ftl | 4 +- .../api-json/macro/usermacro.update.ftl | 5 +- .../web/macro/controller/MacroController.java | 54 +++++++++++++++---- .../zmops/iot/web/macro/dto/UserMacro.java | 9 +++- 6 files changed, 70 insertions(+), 21 deletions(-) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java index 65110cf9..c9e74eed 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java @@ -7,6 +7,8 @@ import com.zmops.zeus.driver.annotation.ParamName; import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; +import java.util.List; + /** * 宏定义接口 */ @@ -29,22 +31,24 @@ public interface ZbxMacro { @JsonPath("/macro/usermacro.create") String macroCreate(@ParamName("hostid") String hostid, @ParamName("macro") String macro, - @ParamName("value") String value); + @ParamName("value") String value, + @ParamName("description") String description); /** * 更新 宏 * - * @param hostmacroid 宏 ID + * @param macroid 宏 ID * @param macro 宏 Key * @param value 宏 Value * @return */ @Post @JsonPath("/macro/usermacro.update") - String macroUpdate(@ParamName("hostmacroid") String macroid, + String macroUpdate(@ParamName("macroid") String macroid, @ParamName("macro") String macro, - @ParamName("value") String value); + @ParamName("value") String value, + @ParamName("description") String description); /** * 获取 宏 @@ -82,6 +86,6 @@ String macroQuery(@ParamName("hostid") String hostid, */ @Post @JsonPath("/macro/usermacro.delete") - String macroDelete(@ParamName("hostid") String macroids); + String macroDelete(@ParamName("macroids") List macroids); } diff --git a/zeus-driver/src/main/resources/api-json/macro/usermacro.create.ftl b/zeus-driver/src/main/resources/api-json/macro/usermacro.create.ftl index a3e661f7..89563a00 100644 --- a/zeus-driver/src/main/resources/api-json/macro/usermacro.create.ftl +++ b/zeus-driver/src/main/resources/api-json/macro/usermacro.create.ftl @@ -4,7 +4,10 @@ "params": { "hostid": "${hostid}", "macro": "${macro}", - "value": "${value}" + "value": "${value}", + <#if description??> + "description":"${description}" + }, "auth": "${userAuth}", "id": 1 diff --git a/zeus-driver/src/main/resources/api-json/macro/usermacro.filter.get.ftl b/zeus-driver/src/main/resources/api-json/macro/usermacro.filter.get.ftl index 484e73dc..566f24c0 100644 --- a/zeus-driver/src/main/resources/api-json/macro/usermacro.filter.get.ftl +++ b/zeus-driver/src/main/resources/api-json/macro/usermacro.filter.get.ftl @@ -7,10 +7,12 @@ "value", "description" ], - "hostids": "${hostId}", + "hostids": "${hostid}", + <#if macro??> "filter": { "macro": "${macro}" } + }, "auth": "${userAuth}", "id": 1 diff --git a/zeus-driver/src/main/resources/api-json/macro/usermacro.update.ftl b/zeus-driver/src/main/resources/api-json/macro/usermacro.update.ftl index db443afc..71c434ca 100644 --- a/zeus-driver/src/main/resources/api-json/macro/usermacro.update.ftl +++ b/zeus-driver/src/main/resources/api-json/macro/usermacro.update.ftl @@ -3,7 +3,10 @@ "method": "usermacro.update", "params": { "hostmacroid": "${macroid}", - "value": "${value}" + "value": "${value}", + <#if description??> + "description":"${description}" + }, "auth": "${userAuth}", "id": 1 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java index fa16b2d9..b8ab7db2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java @@ -1,47 +1,79 @@ package com.zmops.iot.web.macro.controller; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.query.QProduct; +import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.macro.dto.UserMacro; +import com.zmops.zeus.driver.service.ZbxMacro; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; /** * @author nantian created at 2021/9/18 10:53 */ @RequestMapping("/macro") +@RestController public class MacroController { + @Autowired + ZbxMacro zbxMacro; + /** * 创建宏 * * @return */ @RequestMapping("/create") - public ResponseData createUserMacro(@RequestBody UserMacro userMacro) { - - + public ResponseData createUserMacro(@Validated(BaseEntity.Create.class) @RequestBody UserMacro userMacro) { + String zbxId = new QProduct().select(QProduct.alias().zbxId).productId.eq(Long.parseLong(userMacro.getDeviceId())).findSingleAttribute(); + if (ToolUtil.isEmpty(zbxId)) { + zbxId = new QDevice().select(QDevice.alias().zbxId).deviceId.eq(userMacro.getDeviceId()).findSingleAttribute(); + } + if (ToolUtil.isEmpty(zbxId)) { + throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); + } + zbxMacro.macroCreate(zbxId, userMacro.getMacro(), userMacro.getValue(), userMacro.getDescription()); return ResponseData.success(); } @RequestMapping("/update") - public ResponseData updateUserMacro(@RequestBody UserMacro userMacro) { - + public ResponseData updateUserMacro(@Validated(BaseEntity.Update.class) @RequestBody UserMacro userMacro) { + zbxMacro.macroUpdate(userMacro.getHostMacroId(), userMacro.getMacro(), userMacro.getValue(), userMacro.getDescription()); return ResponseData.success(); } - @RequestMapping("/get") - public ResponseData getUserMacro(@RequestBody UserMacro userMacro) { - - return ResponseData.success(); + @RequestMapping("/list") + public ResponseData getUserMacro(@Validated(BaseEntity.Get.class) @RequestBody UserMacro userMacro) { + String zbxId = new QProduct().select(QProduct.alias().zbxId).productId.eq(Long.parseLong(userMacro.getDeviceId())).findSingleAttribute(); + if (ToolUtil.isEmpty(zbxId)) { + zbxId = new QDevice().select(QDevice.alias().zbxId).deviceId.eq(userMacro.getDeviceId()).findSingleAttribute(); + } + List userMacroList = new ArrayList<>(); + if (ToolUtil.isNotEmpty(zbxId)) { + userMacroList = JSONObject.parseArray(zbxMacro.macroQuery(zbxId, userMacro.getMacro()), UserMacro.class); + } + return ResponseData.success(userMacroList); } @RequestMapping("/delete") - public ResponseData deleteUserMacro(@RequestBody UserMacro userMacro) { - + public ResponseData deleteUserMacro(@Validated(BaseEntity.Delete.class) @RequestBody UserMacro userMacro) { + zbxMacro.macroDelete(Collections.singletonList(userMacro.getHostMacroId())); return ResponseData.success(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java index 82164a2a..3a7e5e2c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java @@ -1,8 +1,11 @@ package com.zmops.iot.web.macro.dto; +import com.zmops.iot.domain.BaseEntity; import lombok.Getter; import lombok.Setter; +import javax.validation.constraints.NotBlank; + /** * @author nantian created at 2021/9/18 11:47 */ @@ -11,7 +14,8 @@ @Setter public class UserMacro { - private Long deviceId; // 产品ID 或者 设备ID + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Get.class}) + private String deviceId; // 产品ID 或者 设备ID private String macro; @@ -19,5 +23,6 @@ public class UserMacro { private String description; - private String macro_old; + @NotBlank(groups = {BaseEntity.Delete.class, BaseEntity.Update.class}) + private String hostMacroId; } From 1fdbd7dea7b08cf8a39ed6f9c384c30d96844412 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 18 Sep 2021 18:46:18 +0800 Subject: [PATCH 212/763] [fix]: fix product attribute event --- .../iot/web/product/dto/ProductAttrEvent.java | 5 ----- .../service/ProductAttributeEventService.java | 21 ++++++++++++------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrEvent.java index 75d43bd8..d90fa160 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrEvent.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrEvent.java @@ -36,11 +36,6 @@ public class ProductAttrEvent { private String remark; - private Long depAttrId; - - @JsonIgnore - private String masterItemId; - @JsonIgnore private String zbxId; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java index 841ad28f..82b4e852 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -4,6 +4,8 @@ import com.alibaba.fastjson.JSONObject; import com.zmops.iot.async.executor.Async; import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.Product; import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.domain.product.query.QProduct; @@ -26,6 +28,8 @@ import org.springframework.stereotype.Service; import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; /** @@ -179,21 +183,24 @@ private ProductAttributeEvent buildProdAttribute(ProductAttributeEvent prodAttri public String createTrapperItem(ProductAttrEvent productAttr) { String itemName = productAttr.getAttrId() + ""; - - Product prod = new QProduct().productId.eq(Long.parseLong(productAttr.getProductId())).findOne(); - if (null == prod) { - throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); + String hostId =""; + Device device = new QDevice().deviceId.eq(productAttr.getProductId()).findOne(); + if(null == device){ + Product prod = new QProduct().productId.eq(Long.parseLong(productAttr.getProductId())).findOne(); + if (null == prod) { + throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); + } + hostId = prod.getZbxId(); + }else{ + hostId = device.getZbxId(); } - String hostId = prod.getZbxId(); List processingSteps = new ArrayList<>(); if (ToolUtil.isNotEmpty(productAttr.getProcessStepList())) { productAttr.getProcessStepList().forEach(i -> { ZbxProcessingStep step = new ZbxProcessingStep(); - step.setType(i.getType()); step.setParams(i.getParams()); - processingSteps.add(step); }); } From cf71adcb43a895f99332b070b104f760adaffcc8 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 18 Sep 2021 19:01:35 +0800 Subject: [PATCH 213/763] [fix]: six sh script --- dist-material/bin/stop.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist-material/bin/stop.sh b/dist-material/bin/stop.sh index 126effa4..d9d81cfc 100755 --- a/dist-material/bin/stop.sh +++ b/dist-material/bin/stop.sh @@ -1,7 +1,7 @@ #!/bin/bash status=`ps -ef | grep zeus-iot-bin | grep -v grep | awk '{print $2}' | wc -l` -if [[ $status -ne 0 ]] +if [ $status -ne 0 ] then for i in `ps -ef | grep zeus-iot-bin | grep -v grep | awk '{print $2}'` do From 7c8a5d500f1a94241e09c18815c5e2c8ff6f81d0 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 18 Sep 2021 19:14:39 +0800 Subject: [PATCH 214/763] [feat]: update submodule --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index e03af763..3b8c4f11 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit e03af76310c183a4aee1b4d36b579ba80608a24f +Subproject commit 3b8c4f1125609b77c875363425e0301240a95aea From 230af1d363de0e03ca3571eee0aed0f8f92a5185 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 18 Sep 2021 19:49:45 +0800 Subject: [PATCH 215/763] [feat]: update node.js version --- zeus-starter/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index df28e9d6..a7213e66 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -74,6 +74,7 @@ ${ui.path} v14.17.2 + 6.14.13 From 6d6de9bb49803f6c41d2dbd73d2c1d975d6a042d Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Mon, 20 Sep 2021 10:53:48 +0800 Subject: [PATCH 216/763] [fix]: fix sh script --- dist-material/bin/stop.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dist-material/bin/stop.sh b/dist-material/bin/stop.sh index d9d81cfc..5992f939 100755 --- a/dist-material/bin/stop.sh +++ b/dist-material/bin/stop.sh @@ -1,4 +1,5 @@ -#!/bin/bash +#!/usr/bin/env bash +set -x status=`ps -ef | grep zeus-iot-bin | grep -v grep | awk '{print $2}' | wc -l` if [ $status -ne 0 ] From 8ca148a4728b51a117dccf6ba47046ea8fe6d85f Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 20 Sep 2021 12:28:38 +0800 Subject: [PATCH 217/763] [feat]: device variable modification --- .../zmops/zeus/driver/service/ZbxHost.java | 21 +++- .../zmops/zeus/driver/service/ZbxMacro.java | 10 +- .../api-json/host/host.tempid.get.ftl | 21 ++++ .../api-json/macro/usermacro.create.ftl | 8 +- .../api-json/macro/usermacro.get.ftl | 3 +- .../api-json/macro/usermacro.update.ftl | 5 +- .../web/macro/controller/MacroController.java | 96 +++++++++++++++++-- .../zmops/iot/web/macro/dto/UserMacro.java | 2 +- 8 files changed, 136 insertions(+), 30 deletions(-) create mode 100644 zeus-driver/src/main/resources/api-json/host/host.tempid.get.ftl diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java index e29965fb..908b8f0a 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java @@ -38,7 +38,7 @@ String hostCreate(@ParamName("hostName") String hostName, /** * 修改主机 * - * @param hostid 主机ID + * @param hostid 主机ID * @param groupids 主机分组IDs * @param templateid 主机模板ID,对应产品物模型ID * @return @@ -46,13 +46,13 @@ String hostCreate(@ParamName("hostName") String hostName, @Post @JsonPath("/host/host.update") String hostUpdate(@ParamName("hostid") String hostid, - @ParamName("groupids") List groupids, - @ParamName("templateid") String templateid); + @ParamName("groupids") List groupids, + @ParamName("templateid") String templateid); /** * 删除主机 * - * @param hostIds 主机ID + * @param hostIds 主机ID * @return */ @Post @@ -99,7 +99,18 @@ String hostMacroUpdate(@ParamName("hostId") String hostId, @Post @JsonPath("/host/host.tag.update") String hostTagUpdate(@ParamName("hostId") String hostId, - @ParamName("tagMap") Map tagMap); + @ParamName("tagMap") Map tagMap); + + + /** + * 通过主机名获取 模板IDS + * + * @param hostname + * @return + */ + @Post + @JsonPath("/host/host.tempid.get") + String hostTempidGet(@ParamName("hostname") String hostname); @Data diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java index c9e74eed..23754296 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java @@ -39,8 +39,8 @@ String macroCreate(@ParamName("hostid") String hostid, * 更新 宏 * * @param macroid 宏 ID - * @param macro 宏 Key - * @param value 宏 Value + * @param macro 宏 Key + * @param value 宏 Value * @return */ @Post @@ -54,15 +54,11 @@ String macroUpdate(@ParamName("macroid") String macroid, * 获取 宏 * * @param hostid 主机ID - * @param macro 宏 Key - * @param value 宏 Value * @return */ @Post @JsonPath("/macro/usermacro.get") - String macroGet(@ParamName("hostid") String hostid, - @ParamName("macro") String macro, - @ParamName("value") String value); + String macroGet(@ParamName("hostid") String hostid); /** diff --git a/zeus-driver/src/main/resources/api-json/host/host.tempid.get.ftl b/zeus-driver/src/main/resources/api-json/host/host.tempid.get.ftl new file mode 100644 index 00000000..953f8ffd --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/host/host.tempid.get.ftl @@ -0,0 +1,21 @@ +<#--通过主机ID查询模板ID--> +{ + "jsonrpc": "2.0", + "method": "host.get", + "params": { + "output": [ + "hostid" + ], + "selectParentTemplates": [ + "templateid", + "name" + ], + "filter": { + "host": [ + "${hostname}" + ] + } + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/macro/usermacro.create.ftl b/zeus-driver/src/main/resources/api-json/macro/usermacro.create.ftl index 89563a00..318648e3 100644 --- a/zeus-driver/src/main/resources/api-json/macro/usermacro.create.ftl +++ b/zeus-driver/src/main/resources/api-json/macro/usermacro.create.ftl @@ -4,10 +4,10 @@ "params": { "hostid": "${hostid}", "macro": "${macro}", - "value": "${value}", - <#if description??> - "description":"${description}" - + "value": "${value}" + <#if description??> + ,"description":"${description}" + }, "auth": "${userAuth}", "id": 1 diff --git a/zeus-driver/src/main/resources/api-json/macro/usermacro.get.ftl b/zeus-driver/src/main/resources/api-json/macro/usermacro.get.ftl index 34b20f3f..76fdb651 100644 --- a/zeus-driver/src/main/resources/api-json/macro/usermacro.get.ftl +++ b/zeus-driver/src/main/resources/api-json/macro/usermacro.get.ftl @@ -3,11 +3,12 @@ "method": "usermacro.get", "params": { "output": [ + "hostmacroid", "macro", "value", "description" ], - "hostids": "${hostId}" + "hostids": "${hostid}" }, "auth": "${userAuth}", "id": 1 diff --git a/zeus-driver/src/main/resources/api-json/macro/usermacro.update.ftl b/zeus-driver/src/main/resources/api-json/macro/usermacro.update.ftl index 71c434ca..666ac75f 100644 --- a/zeus-driver/src/main/resources/api-json/macro/usermacro.update.ftl +++ b/zeus-driver/src/main/resources/api-json/macro/usermacro.update.ftl @@ -3,10 +3,11 @@ "method": "usermacro.update", "params": { "hostmacroid": "${macroid}", + "macro": "${macro}", "value": "${value}", - <#if description??> + <#if description??> "description":"${description}" - + }, "auth": "${userAuth}", "id": 1 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java index b8ab7db2..5fdd210c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java @@ -1,5 +1,6 @@ package com.zmops.iot.web.macro.controller; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.device.query.QDevice; @@ -9,16 +10,19 @@ import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.macro.dto.UserMacro; +import com.zmops.zeus.driver.service.ZbxHost; import com.zmops.zeus.driver.service.ZbxMacro; +import lombok.Getter; +import lombok.Setter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; /** * @author nantian created at 2021/9/18 10:53 @@ -31,50 +35,122 @@ public class MacroController { @Autowired ZbxMacro zbxMacro; + @Autowired + ZbxHost zbxHost; + /** - * 创建宏 + * 创建 变量 * * @return */ @RequestMapping("/create") public ResponseData createUserMacro(@Validated(BaseEntity.Create.class) @RequestBody UserMacro userMacro) { + // 获取 host id String zbxId = new QProduct().select(QProduct.alias().zbxId).productId.eq(Long.parseLong(userMacro.getDeviceId())).findSingleAttribute(); if (ToolUtil.isEmpty(zbxId)) { zbxId = new QDevice().select(QDevice.alias().zbxId).deviceId.eq(userMacro.getDeviceId()).findSingleAttribute(); } + if (ToolUtil.isEmpty(zbxId)) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } - zbxMacro.macroCreate(zbxId, userMacro.getMacro(), userMacro.getValue(), userMacro.getDescription()); - return ResponseData.success(); + + // 创建宏 + String res = zbxMacro.macroCreate(zbxId, userMacro.getMacro().toUpperCase(Locale.ROOT), userMacro.getValue(), userMacro.getDescription()); + + Macroids macroids = JSON.parseObject(res, Macroids.class); + return ResponseData.success(macroids.getHostmacroids()[0]); } + /** + * 变量更新 + * + * @param userMacro + * @return + */ @RequestMapping("/update") public ResponseData updateUserMacro(@Validated(BaseEntity.Update.class) @RequestBody UserMacro userMacro) { - zbxMacro.macroUpdate(userMacro.getHostMacroId(), userMacro.getMacro(), userMacro.getValue(), userMacro.getDescription()); + zbxMacro.macroUpdate(userMacro.getHostmacroid(), userMacro.getMacro(), userMacro.getValue(), userMacro.getDescription()); return ResponseData.success(); } + /** + * 变量列表 + * + * @param userMacro + * @return + */ @RequestMapping("/list") public ResponseData getUserMacro(@Validated(BaseEntity.Get.class) @RequestBody UserMacro userMacro) { + + // 获取 模板ID 或者 设备ID String zbxId = new QProduct().select(QProduct.alias().zbxId).productId.eq(Long.parseLong(userMacro.getDeviceId())).findSingleAttribute(); + + // 模板ID + if (ToolUtil.isNotEmpty(zbxId)) { + List tempMacroList = JSONObject.parseArray(zbxMacro.macroGet(zbxId + ""), UserMacro.class); + return ResponseData.success(tempMacroList); + } + + // 主机ID if (ToolUtil.isEmpty(zbxId)) { zbxId = new QDevice().select(QDevice.alias().zbxId).deviceId.eq(userMacro.getDeviceId()).findSingleAttribute(); } - List userMacroList = new ArrayList<>(); - if (ToolUtil.isNotEmpty(zbxId)) { - userMacroList = JSONObject.parseArray(zbxMacro.macroQuery(zbxId, userMacro.getMacro()), UserMacro.class); + + // 模板IDs + List tempListObject = JSON.parseArray(zbxHost.hostTempidGet(userMacro.getDeviceId()), HostQueryTempObject.class); + + TemplateIdObject tempId = tempListObject.get(0).getParentTemplates().get(0); + if (ToolUtil.isNotEmpty(tempId)) { + // 模板宏 + List tempMacroList = JSONObject.parseArray(zbxMacro.macroGet(tempId.getTemplateid()), UserMacro.class); + + // 主机宏 + List hostMacroList = JSONObject.parseArray(zbxMacro.macroGet(zbxId + ""), UserMacro.class); + + //TODO merge + tempMacroList.addAll(hostMacroList); + + return ResponseData.success(tempMacroList); } - return ResponseData.success(userMacroList); + + return ResponseData.error(ResponseData.DEFAULT_ERROR_CODE, ""); } + /** + * 变量删除 + * + * @param userMacro + * @return + */ @RequestMapping("/delete") public ResponseData deleteUserMacro(@Validated(BaseEntity.Delete.class) @RequestBody UserMacro userMacro) { - zbxMacro.macroDelete(Collections.singletonList(userMacro.getHostMacroId())); + zbxMacro.macroDelete(Collections.singletonList(userMacro.getHostmacroid())); return ResponseData.success(); } + + @Getter + @Setter + static class Macroids { + private Long[] hostmacroids; + } + + @Getter + @Setter + static class HostQueryTempObject { + private String hostid; + private List parentTemplates; + } + + @Getter + @Setter + static class TemplateIdObject { + private String templateid; + private String name; + } + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java index 3a7e5e2c..8a94cce4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java @@ -24,5 +24,5 @@ public class UserMacro { private String description; @NotBlank(groups = {BaseEntity.Delete.class, BaseEntity.Update.class}) - private String hostMacroId; + private String hostmacroid; } From 9e078db02cda95a03c941b7d942cc473b6af674a Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 20 Sep 2021 12:39:31 +0800 Subject: [PATCH 218/763] [style]: change node.js and npm version --- zeus-starter/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index a7213e66..7b958208 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -73,8 +73,8 @@ ${frontend-maven-plugin.version} ${ui.path} - v14.17.2 - 6.14.13 + v12.18.3 + 6.14.6 From 1031f467affaf2a0361662674484f995f3e19dcf Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 20 Sep 2021 12:39:54 +0800 Subject: [PATCH 219/763] [feat]: device trigger action --- .../servlet/DeviceTriggerActionHandler.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java index d20d8bb5..f1096fb8 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java @@ -8,8 +8,10 @@ import com.zmops.zeus.iot.server.library.module.ModuleManager; import com.zmops.zeus.iot.server.library.server.jetty.ArgumentsParseException; import com.zmops.zeus.iot.server.library.server.jetty.JettyJsonHandler; +import lombok.extern.slf4j.Slf4j; import javax.servlet.http.HttpServletRequest; +import java.io.BufferedReader; import java.io.IOException; /** @@ -17,6 +19,7 @@ *

* 设备 告警规则 触发动作,Http 统一入口 */ +@Slf4j public class DeviceTriggerActionHandler extends JettyJsonHandler { private final ModuleManager moduleManager; @@ -41,6 +44,10 @@ public String pathSpec() { */ @Override protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException, IOException { + + String request = getJsonBody(req); + log.debug(request); + EventBusService eventBusService = moduleManager.find(CoreModule.NAME).provider().getService(EventBusService.class); ActionParam actionParam = new ActionParam(); @@ -49,4 +56,15 @@ protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseExcept return null; } + + + public String getJsonBody(HttpServletRequest req) throws IOException { + StringBuffer stringBuffer = new StringBuffer(); + String line = null; + BufferedReader reader = req.getReader(); + while ((line = reader.readLine()) != null) { + stringBuffer.append(line); + } + return stringBuffer.toString(); + } } From 46724c12c91d6d99b02584fb3ea6073d1873ab7e Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 20 Sep 2021 13:32:25 +0800 Subject: [PATCH 220/763] [feat]: delete method comment --- .../com/zmops/iot/web/device/service/DeviceEventService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java index ab3efb97..b01eabe4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java @@ -71,7 +71,6 @@ public void createProductEventRule(Long eventRuleId, ProductEventRule eventRule) }); } - //step 4: 保存关联关系 //step 4: 保存关联关系 if (ToolUtil.isNotEmpty(eventRule.getProductId())) { ProductEventRelation productEventRelation = new ProductEventRelation(); From bddff13ba0c449822107fbd8fc8aa7801114c5ab Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 20 Sep 2021 13:44:01 +0800 Subject: [PATCH 221/763] [style]: change event url endpoint --- .../controller/DeviceEventController.java | 4 +- .../controller/ProductEventController.java | 194 +----------------- .../ProductEventTriggerController.java | 193 ++++++++++++++++- .../controller/ProductModelController.java | 2 +- .../controller/ProductServiceController.java | 2 +- .../ProductStatusTriggerController.java | 8 +- 6 files changed, 201 insertions(+), 202 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java index 16acb204..4700a8ed 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java @@ -26,10 +26,10 @@ /** * @author yefei *

- * 设备 物模型功能【事件】 类似于 属性处理 + * 设备告警规则 **/ @RestController -@RequestMapping("/device/event") +@RequestMapping("/device/event/trigger") public class DeviceEventController { @Autowired diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java index 2c3b9e21..c3180dc6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java @@ -1,205 +1,23 @@ package com.zmops.iot.web.product.controller; -import cn.hutool.core.util.IdUtil; -import com.zmops.iot.domain.BaseEntity; -import com.zmops.iot.domain.product.ProductEvent; -import com.zmops.iot.domain.product.ProductEventRelation; -import com.zmops.iot.domain.product.query.QProductEvent; -import com.zmops.iot.domain.product.query.QProductEventExpression; -import com.zmops.iot.domain.product.query.QProductEventRelation; -import com.zmops.iot.domain.product.query.QProductEventService; -import com.zmops.iot.model.exception.ServiceException; -import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; -import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.exception.enums.BizExceptionEnum; -import com.zmops.iot.web.product.dto.ProductEventDto; -import com.zmops.iot.web.product.dto.ProductEventRule; -import com.zmops.iot.web.product.dto.param.EventParm; -import com.zmops.iot.web.product.service.EventRuleService; -import com.zmops.zeus.driver.service.ZbxTrigger; -import io.ebean.DB; -import io.ebean.annotation.Transactional; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; /** - * @author nantian created at 2021/8/26 23:04 + * @author nantian created at 2021/8/7 11:58 *

- * 产品 物模型功能【事件】 类似于 属性处理 + * 产品物模型: 事件 */ - @RestController @RequestMapping("/product/event") public class ProductEventController { - @Autowired - private EventRuleService eventRuleService; - - @Autowired - private ZbxTrigger zbxTrigger; - - private static final String ALARM_TAG_NAME = "__alarm__"; - private static final String EXECUTE_TAG_NAME = "__execute__"; - - - /** - * 触发器 分页列表 - * - * @param eventParm - * @return - */ - @PostMapping("/getEventByPage") - public Pager getEventByPage(@RequestBody EventParm eventParm) { - return eventRuleService.getEventByPage(eventParm); - } - - /** - * 触发器 详情 - * - * @param eventRuleId - * @return - */ - @GetMapping("/detail") - public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId,@RequestParam("prodId") String prodId) { - ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRuleId).findOne(); - if (null == productEvent) { - throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); - } - return ResponseData.success(eventRuleService.detail(productEvent,eventRuleId,prodId)); - } - - /** - * 创建 触发器 - * - * @param eventRule 触发器规则 - * @return 触发器ID - */ - @Transactional - @PostMapping("/create") - public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseEntity.Create.class) - ProductEventRule eventRule) { - - Long eventRuleId = IdUtil.getSnowflake().nextId(); // ruleId, trigger name - - eventRuleService.createProductEventRule(eventRuleId, eventRule); - - //step 1: 先创建 zbx 触发器 - String expression = eventRule.getExpList() - .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); - - //step 2: zbx 保存触发器 - String[] triggerIds = eventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); - - //step 4: zbx 触发器创建 Tag - Map tags = eventRule.getTags().stream() - .collect(Collectors.toMap(ProductEventRule.Tag::getTag, ProductEventRule.Tag::getValue, (k1, k2) -> k2)); - if (ToolUtil.isEmpty(tags)) { - tags = new HashMap<>(2); - } - if (!tags.containsKey(ALARM_TAG_NAME)) { - tags.put(ALARM_TAG_NAME, eventRuleId + ""); - } - if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { - tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); - } - for (String triggerId : triggerIds) { - zbxTrigger.triggerTagCreate(triggerId, tags); - } - - - //step 5: 更新 zbxId - eventRuleService.updateProductEventRuleZbxId(eventRuleId, triggerIds); - - // 返回触发器ID - return ResponseData.success(eventRuleId); - } - - /** - * 修改 触发器 - * - * @param eventRule 触发器规则 - * @return 触发器ID - */ - @Transactional - @PostMapping("/update") - public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) - ProductEventRule eventRule) { - - //step 1: 更新所有服务 - eventRuleService.updateProductEventRule(eventRule.getEventRuleId(), eventRule); - - //step 2: 更新zbx表达式 - String expression = eventRule.getExpList() - .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); - - - ProductEvent event = new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).findOne(); - if (null != event) { - List list = new QProductEventRelation().eventRuleId.eq(event.getEventRuleId()).findList(); - list.forEach(productEventRelation -> { - zbxTrigger.triggerUpdate(productEventRelation.getZbxId(), expression, eventRule.getEventLevel()); - - //step 3: zbx 触发器创建 Tag - Map tags = eventRule.getTags().stream() - .collect(Collectors.toMap(ProductEventRule.Tag::getTag, ProductEventRule.Tag::getValue, (k1, k2) -> k2)); - if (ToolUtil.isEmpty(tags)) { - tags = new HashMap<>(2); - } - if (!tags.containsKey(ALARM_TAG_NAME)) { - tags.put(ALARM_TAG_NAME, eventRule.getEventRuleId() + ""); - } - if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { - tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); - } - zbxTrigger.triggerTagCreate(productEventRelation.getZbxId(), tags); - }); - } - - return ResponseData.success(eventRule.getEventRuleId()); - } - - /** - * 修改 触发器 - * - * @param eventRule 触发器规则 - * @return 触发器ID - */ - @PostMapping("/status") - public ResponseData updateProductEventStatus(@RequestBody @Validated(value = BaseEntity.Status.class) ProductEventRule eventRule) { - DB.update(ProductEvent.class).where().eq("eventRuleId", eventRule.getEventRuleId()).asUpdate().set("status", eventRule.getStatus()).update(); + @RequestMapping("/create") + public ResponseData createEventTrigger() { return ResponseData.success(); } - /** - * 删除 触发器 - * - * @param eventRule 触发器规则 - * @return 触发器ID - */ - @Transactional - @PostMapping("/delete") - public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseEntity.Delete.class) - ProductEventRule eventRule) { - //step 1:删除 与产品 设备的关联 - new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); - - //step 2:删除 关联的执行服务 - new QProductEventService().eventRuleId.eq(eventRule.getEventRuleId()).delete(); - //step 3:删除 关联的表达式 - new QProductEventExpression().eventRuleId.eq(eventRule.getEventRuleId()).delete(); - - //step 4:删除 触发器 - new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).delete(); - - return ResponseData.success(); - } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index 23c5c825..a971f96b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -1,24 +1,205 @@ package com.zmops.iot.web.product.controller; +import cn.hutool.core.util.IdUtil; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEvent; +import com.zmops.iot.domain.product.query.QProductEventExpression; +import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.product.dto.ProductEventDto; +import com.zmops.iot.web.product.dto.ProductEventRule; +import com.zmops.iot.web.product.dto.param.EventParm; +import com.zmops.iot.web.product.service.EventRuleService; +import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; +import io.ebean.annotation.Transactional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** - * @author nantian created at 2021/8/7 11:58 + * @author nantian created at 2021/8/26 23:04 *

- * 配置告警规则 属性 事件 触发 方法回调 + * 产品 物模型功能 【告警规则】 */ + @RestController @RequestMapping("/product/event/trigger") public class ProductEventTriggerController { - @RequestMapping("/create") - public ResponseData createEventTrigger() { + @Autowired + private EventRuleService eventRuleService; + + @Autowired + private ZbxTrigger zbxTrigger; + + private static final String ALARM_TAG_NAME = "__alarm__"; + private static final String EXECUTE_TAG_NAME = "__execute__"; + + + /** + * 触发器 分页列表 + * + * @param eventParm + * @return + */ + @PostMapping("/getEventByPage") + public Pager getEventByPage(@RequestBody EventParm eventParm) { + return eventRuleService.getEventByPage(eventParm); + } + + /** + * 触发器 详情 + * + * @param eventRuleId + * @return + */ + @GetMapping("/detail") + public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId, @RequestParam("prodId") String prodId) { + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRuleId).findOne(); + if (null == productEvent) { + throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); + } + return ResponseData.success(eventRuleService.detail(productEvent, eventRuleId, prodId)); + } + + /** + * 创建 触发器 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ + @Transactional + @PostMapping("/create") + public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseEntity.Create.class) + ProductEventRule eventRule) { + + Long eventRuleId = IdUtil.getSnowflake().nextId(); // ruleId, trigger name + + eventRuleService.createProductEventRule(eventRuleId, eventRule); + + //step 1: 先创建 zbx 触发器 + String expression = eventRule.getExpList() + .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); + + //step 2: zbx 保存触发器 + String[] triggerIds = eventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); + + //step 4: zbx 触发器创建 Tag + Map tags = eventRule.getTags().stream() + .collect(Collectors.toMap(ProductEventRule.Tag::getTag, ProductEventRule.Tag::getValue, (k1, k2) -> k2)); + if (ToolUtil.isEmpty(tags)) { + tags = new HashMap<>(2); + } + if (!tags.containsKey(ALARM_TAG_NAME)) { + tags.put(ALARM_TAG_NAME, eventRuleId + ""); + } + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { + tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); + } + for (String triggerId : triggerIds) { + zbxTrigger.triggerTagCreate(triggerId, tags); + } + + + //step 5: 更新 zbxId + eventRuleService.updateProductEventRuleZbxId(eventRuleId, triggerIds); + + // 返回触发器ID + return ResponseData.success(eventRuleId); + } + + /** + * 修改 触发器 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ + @Transactional + @PostMapping("/update") + public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) + ProductEventRule eventRule) { + + //step 1: 更新所有服务 + eventRuleService.updateProductEventRule(eventRule.getEventRuleId(), eventRule); + + //step 2: 更新zbx表达式 + String expression = eventRule.getExpList() + .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); + + + ProductEvent event = new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).findOne(); + if (null != event) { + List list = new QProductEventRelation().eventRuleId.eq(event.getEventRuleId()).findList(); + list.forEach(productEventRelation -> { + zbxTrigger.triggerUpdate(productEventRelation.getZbxId(), expression, eventRule.getEventLevel()); + + //step 3: zbx 触发器创建 Tag + Map tags = eventRule.getTags().stream() + .collect(Collectors.toMap(ProductEventRule.Tag::getTag, ProductEventRule.Tag::getValue, (k1, k2) -> k2)); + if (ToolUtil.isEmpty(tags)) { + tags = new HashMap<>(2); + } + if (!tags.containsKey(ALARM_TAG_NAME)) { + tags.put(ALARM_TAG_NAME, eventRule.getEventRuleId() + ""); + } + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { + tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); + } + zbxTrigger.triggerTagCreate(productEventRelation.getZbxId(), tags); + }); + } + + return ResponseData.success(eventRule.getEventRuleId()); + } + + /** + * 修改 触发器 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ + @PostMapping("/status") + public ResponseData updateProductEventStatus(@RequestBody @Validated(value = BaseEntity.Status.class) ProductEventRule eventRule) { + DB.update(ProductEvent.class).where().eq("eventRuleId", eventRule.getEventRuleId()).asUpdate().set("status", eventRule.getStatus()).update(); return ResponseData.success(); } + /** + * 删除 触发器 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ + @Transactional + @PostMapping("/delete") + public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseEntity.Delete.class) + ProductEventRule eventRule) { + //step 1:删除 与产品 设备的关联 + new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + //step 2:删除 关联的执行服务 + new QProductEventService().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + //step 3:删除 关联的表达式 + new QProductEventExpression().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 4:删除 触发器 + new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + return ResponseData.success(); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java index f22ca2c2..38f2aa29 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java @@ -24,7 +24,7 @@ /** * @author nantian created at 2021/8/3 19:44 *

- * 产品物模型: 属性 服务 事件 + * 产品物模型: 属性 */ @RestController diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java index d9f13062..15ad33f6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java @@ -16,7 +16,7 @@ /** * @author nantian created at 2021/8/4 16:33 *

- * 产品 物模型 服务 【功能】 + * 产品物模型: 服务 */ @RestController diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java index 9ffeee30..e64ee761 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java @@ -24,7 +24,7 @@ */ @RestController -@RequestMapping("/product/trigger/status") +@RequestMapping("/product/status/trigger") public class ProductStatusTriggerController { @@ -35,13 +35,13 @@ public class ProductStatusTriggerController { private ProductTriggerService productTriggerService; /** - * 离线 或者 在线触发器 信息 + * 离线 或者 在线触发器 信息 * * @param relationId 关联产品或设备ID * @return ResponseData */ @GetMapping("/detail") - public ResponseData getRule(@RequestParam("relationId") String relationId){ + public ResponseData getRule(@RequestParam("relationId") String relationId) { return ResponseData.success(productTriggerService.getRule(relationId)); } @@ -63,7 +63,7 @@ public ResponseData createDeviceStatusTrigger(@RequestBody @Validated(BaseEntity } int count = new QProductStatusFunctionRelation().relationId.eq(rule.getRelationId()).findCount(); - if(count>0){ + if (count > 0) { throw new ServiceException(BizExceptionEnum.RULE_EXISTS); } return ResponseData.success(productTriggerService.createDeviceStatusJudgeTrigger(rule)); From a8ddc13223b55b70ed3734cf69d6b37a932fddd2 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 20 Sep 2021 13:46:45 +0800 Subject: [PATCH 222/763] [style]: modify the code format --- .../iot/web/product/service/ProductModelService.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index 332816fc..e2f731e9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -65,8 +65,12 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr qProductAttribute.key.contains(productAttr.getKey()); } - List pagedList = qProductAttribute.setFirstRow((productAttr.getPage() - 1) * productAttr.getMaxRow()).setMaxRows(productAttr.getMaxRow()).asDto(ProductAttrDto.class).findList(); - int count = qProductAttribute.findCount(); + List pagedList = qProductAttribute + .setFirstRow((productAttr.getPage() - 1) * productAttr.getMaxRow()) + .setMaxRows(productAttr.getMaxRow()) + .asDto(ProductAttrDto.class).findList(); + + int count = qProductAttribute.findCount(); return new Pager<>(pagedList, count); } @@ -106,9 +110,11 @@ public ProductAttrDto detail(Long attrId) { attr.setTags(JSONObject.parseArray(itemInfo.getJSONObject(0).getString("tags"), ProductTag.Tag.class)); attr.setProcessStepList(formatProcessStep(itemInfo.getJSONObject(0).getString("preprocessing"))); String valuemap = itemInfo.getJSONObject(0).getString("valuemap"); + if (ToolUtil.isNotEmpty(valuemap) && !"[]".equals(valuemap)) { attr.setValuemapid(JSONObject.parseObject(valuemap).getString("valuemapid")); } + return attr; } From 32499948e2f98009963d8a7fa807b69f5e465198 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Mon, 20 Sep 2021 13:52:26 +0800 Subject: [PATCH 223/763] [fix]: fix sh script --- dist-material/bin/stop.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist-material/bin/stop.sh b/dist-material/bin/stop.sh index 5992f939..d6b052db 100755 --- a/dist-material/bin/stop.sh +++ b/dist-material/bin/stop.sh @@ -6,6 +6,6 @@ if [ $status -ne 0 ] then for i in `ps -ef | grep zeus-iot-bin | grep -v grep | awk '{print $2}'` do - kill $i + kill -9 $i done fi From b04c84274186098880f335621e1f0e2a5cda7e92 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 20 Sep 2021 14:47:17 +0800 Subject: [PATCH 224/763] [style]: change code style --- .../iot/web/alarm/service/AlarmService.java | 26 ++++++++++++------- ...java => DeviceEventTriggerController.java} | 11 +++----- .../device/service/DeviceEventService.java | 4 ++- 3 files changed, 23 insertions(+), 18 deletions(-) rename zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/{DeviceEventController.java => DeviceEventTriggerController.java} (94%) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 95480a67..209c718a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -37,14 +37,21 @@ public class AlarmService { public void alarm(Map alarmInfo) { String deviceId = alarmInfo.get("hostname"); String eventRuleId = alarmInfo.get("triggername"); + if (ToolUtil.isEmpty(deviceId) || ToolUtil.isEmpty(eventRuleId)) { return; } - Device device = new QDevice().deviceId.eq(deviceId).findOne(); - ProductEvent productEvent = new QProductEvent().eventRuleId.eq(Long.parseLong(eventRuleId)).findOne(); - String alarmmessage = "设备:" + device.getName() + "发生告警,告警内容:" + productEvent.getEventRuleName(); + + Device device = new QDevice().deviceId.eq(deviceId).findOne(); + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(Long.parseLong(eventRuleId)).findOne(); + List alarmMessages = new ArrayList<>(); - alarmMessages.add(AlarmMessage.builder().alarmMessage(alarmmessage).build()); + + if (null != device && null != productEvent) { + String alarmmessage = "设备:" + device.getName() + "发生告警,告警内容:" + productEvent.getEventRuleName(); + alarmMessages.add(AlarmMessage.builder().alarmMessage(alarmmessage).build()); + } + alarmCallbacks.forEach(alarmCallback -> { // if (alarmCallback.getType().equals("welink")) { alarmCallback.doAlarm(alarmMessages); @@ -60,7 +67,9 @@ public List getAlarmByPage(AlarmParam alarmParam) { return Collections.emptyList(); } //分页 - List problemList = zbxProblemInfos.stream().skip((alarmParam.getPage() - 1) * alarmParam.getMaxRow()).limit(alarmParam.getMaxRow()).collect(Collectors.toList()); + List problemList = zbxProblemInfos.stream() + .skip((alarmParam.getPage() - 1) * alarmParam.getMaxRow()) + .limit(alarmParam.getMaxRow()).collect(Collectors.toList()); //根据triggerid查询出 所属设备 List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).collect(Collectors.toList()); @@ -92,11 +101,8 @@ public List getAlarmList(AlarmParam alarmParam) { hostId = one.getZbxId(); } //从zbx取告警记录 - String problem = zbxProblem.getProblem(hostId, alarmParam.getTimeFrom(), alarmParam.getTimeTill(), alarmParam.getRecent()); - List zbxProblemInfos = JSONObject.parseArray(problem, ZbxProblemInfo.class); - - - return zbxProblemInfos; + String problem = zbxProblem.getProblem(hostId, alarmParam.getTimeFrom(), alarmParam.getTimeTill(), alarmParam.getRecent()); + return JSONObject.parseArray(problem, ZbxProblemInfo.class); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java similarity index 94% rename from zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index 4700a8ed..5cd77921 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -30,7 +30,7 @@ **/ @RestController @RequestMapping("/device/event/trigger") -public class DeviceEventController { +public class DeviceEventTriggerController { @Autowired DeviceEventService deviceEventService; @@ -64,21 +64,18 @@ public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId, @Reque */ @Transactional @PostMapping("/update") - public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) - ProductEventRule eventRule) { - - List deviceIds = eventRule.getExpList().parallelStream().map(ProductEventRule.Expression::getDeviceId) - .collect(Collectors.toList()); + public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) ProductEventRule eventRule) { + List deviceIds = eventRule.getExpList().parallelStream().map(ProductEventRule.Expression::getDeviceId).collect(Collectors.toList()); if (ToolUtil.isEmpty(deviceIds)) { throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); } + //step 1: 删除原有的 关联关系 deviceIds.forEach(deviceId -> { new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).relationId.eq(deviceId).delete(); new QProductEventService().eventRuleId.eq(eventRule.getEventRuleId()).deviceId.eq(deviceId).delete(); }); - Long eventRuleId = IdUtil.getSnowflake().nextId(); // ruleId, trigger name deviceEventService.createProductEventRule(eventRuleId, eventRule); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java index b01eabe4..0623ced7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java @@ -150,7 +150,9 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S productEventRuleDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).deviceId.eq(deviceId).findList()); ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(deviceId).eventRuleId.eq(eventRuleId).findOne(); - JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); + + JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); + productEventRuleDto.setTags(JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class)); return productEventRuleDto; From a558557cca047352b5bba2e7558cc162c29a4335 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Mon, 20 Sep 2021 14:55:07 +0800 Subject: [PATCH 225/763] [fix]: fix sh script --- dist-material/bin/stop.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/dist-material/bin/stop.sh b/dist-material/bin/stop.sh index d6b052db..0f4a107c 100755 --- a/dist-material/bin/stop.sh +++ b/dist-material/bin/stop.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash set -x +ps -ef | grep zeus-iot-bin | grep -v grep status=`ps -ef | grep zeus-iot-bin | grep -v grep | awk '{print $2}' | wc -l` if [ $status -ne 0 ] From 732af98566236115e17ac6cdf88265a5fbb13246 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Mon, 20 Sep 2021 15:58:28 +0800 Subject: [PATCH 226/763] [fix]: fix stop.sh --- dist-material/bin/stop.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dist-material/bin/stop.sh b/dist-material/bin/stop.sh index 0f4a107c..65fe8e1d 100755 --- a/dist-material/bin/stop.sh +++ b/dist-material/bin/stop.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -x -ps -ef | grep zeus-iot-bin | grep -v grep -status=`ps -ef | grep zeus-iot-bin | grep -v grep | awk '{print $2}' | wc -l` +ps -ef | grep zeus-iot-bin | grep -v grep > /tmp/test +status=`ps -ef | grep zeus-iot-bin | grep java | grep -v grep | awk '{print $2}' | wc -l` if [ $status -ne 0 ] then From 915baea274e960972f33a0f536c9c85797c0b28a Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 20 Sep 2021 16:46:46 +0800 Subject: [PATCH 227/763] [feat]: add trigger status update function --- .../iot/domain/product/ProductEvent.java | 12 ++++----- .../zmops/zeus/driver/service/ZbxTrigger.java | 25 ++++++++++++++----- .../trigger/trigger.status.update.ftl | 10 ++++++++ ...rvice.java => DeviceEventRuleService.java} | 0 .../exception/aop/GlobalExceptionHandler.java | 4 +-- ...vice.java => ProductEventRuleService.java} | 17 +++++++++++-- 6 files changed, 52 insertions(+), 16 deletions(-) create mode 100644 zeus-driver/src/main/resources/api-json/trigger/trigger.status.update.ftl rename zeus-webapp/src/main/java/com/zmops/iot/web/device/service/{DeviceEventService.java => DeviceEventRuleService.java} (100%) rename zeus-webapp/src/main/java/com/zmops/iot/web/product/service/{EventRuleService.java => ProductEventRuleService.java} (95%) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java index d2d50ce5..57a03d97 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java @@ -21,10 +21,10 @@ public class ProductEvent extends BaseEntity { @Id private Long eventRuleId; - private String eventRuleName; - private Byte eventLevel; - private String expLogic; - private String remark; - private Byte eventNotify; - private String status; + private String eventRuleName; + private Byte eventLevel; + private String expLogic; + private String remark; + private Byte eventNotify; + private String status; } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java index 42394c10..32bfb099 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java @@ -34,9 +34,9 @@ String triggerCreate(@ParamName("triggerName") String triggerName, /** * 更新告警触发器 * - * @param triggerId 触发器ID - * @param expression 触发器 表达式 - * @param ruleLevel 告警等级 + * @param triggerId 触发器ID + * @param expression 触发器 表达式 + * @param ruleLevel 告警等级 * @return */ @Post @@ -61,7 +61,7 @@ String triggerTagCreate(@ParamName("triggerId") String triggerId, /** * 根据TRIGGER ID查询触发器 * - * @param triggerIds 触发器IDs + * @param triggerIds 触发器IDs */ @Post @JsonPath("/trigger/trigger.get") @@ -70,7 +70,7 @@ String triggerTagCreate(@ParamName("triggerId") String triggerId, /** * 根据TRIGGER ID查询触发器及触发器标签 * - * @param triggerIds 触发器IDs + * @param triggerIds 触发器IDs */ @Post @JsonPath("/trigger/triggerAndTags.get") @@ -79,9 +79,22 @@ String triggerTagCreate(@ParamName("triggerId") String triggerId, /** * 根据host 查询触发器 * - * @param host 设备ID + * @param host 设备ID */ @Post @JsonPath("/trigger/trigger.get") String triggerGetByHost(@ParamName("host") String host); + + + /** + * 修改触发器状态 + * + * @param triggerId + * @param status + * @return + */ + @Post + @JsonPath("/trigger/trigger.status.update") + String triggerStatusUpdate(@ParamName("triggerid") String triggerId, + @ParamName("status") String status); } diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.status.update.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.status.update.ftl new file mode 100644 index 00000000..f5a3aa98 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.status.update.ftl @@ -0,0 +1,10 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.update", + "params": { + "triggerid": "${triggerid}", + "status": ${status} + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java similarity index 100% rename from zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventService.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/aop/GlobalExceptionHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/aop/GlobalExceptionHandler.java index cbcb12b0..e6da81b1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/aop/GlobalExceptionHandler.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/aop/GlobalExceptionHandler.java @@ -95,8 +95,8 @@ public ErrorResponseData handleError(MethodArgumentNotValidException e) { log.warn("Method Argument Not Valid", e); BindingResult result = e.getBindingResult(); FieldError error = result.getFieldError(); -// String message = String.format("%s:%s", error.getField(), error.getDefaultMessage()); - String message = String.format("%s:不能为空", error.getField()); + + String message = String.format("%s:%s", error.getField(), error.getDefaultMessage()); return new ErrorResponseData(400, message); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java similarity index 95% rename from zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index e1682b17..ce4cae18 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/EventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -241,6 +241,14 @@ public Pager getEventByPage(EventParm eventParm) { return new Pager<>(list, query.findCount()); } + /** + * 获取 告警规则 详情 + * + * @param productEvent + * @param eventRuleId + * @param prodId + * @return + */ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, String prodId) { ProductEventRuleDto productEventRuleDto = new ProductEventRuleDto(); ToolUtil.copyProperties(productEvent, productEventRuleDto); @@ -249,8 +257,13 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S productEventRuleDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).deviceId.isNull().findList()); ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(prodId).eventRuleId.eq(eventRuleId).findOne(); - JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); - productEventRuleDto.setTags(JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class)); + + JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); + List tagList = JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class); + + productEventRuleDto.setTags(tagList.stream() + .filter(s -> s.getTag().equals("__execute__") || s.getTag().equals("__alarm__")) + .collect(Collectors.toList())); return productEventRuleDto; } From d0e971098a396993c8ddfdea5956204ed4a5e9f5 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 20 Sep 2021 17:00:21 +0800 Subject: [PATCH 228/763] [style]: change code style --- .../controller/DeviceEventController.java | 21 ++++++++ .../DeviceEventTriggerController.java | 13 +++-- .../service/DeviceEventRuleService.java | 2 +- .../ProductEventTriggerController.java | 16 +++--- .../web/product/dto/ProductEventRuleDto.java | 5 -- .../service/ProductEventRuleService.java | 2 +- .../web/trigger/EventTriggerController.java | 52 +++++++++++++++++++ .../iot/web/trigger/dto/TriggerStatusDto.java | 25 +++++++++ 8 files changed, 114 insertions(+), 22 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/trigger/EventTriggerController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/trigger/dto/TriggerStatusDto.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java new file mode 100644 index 00000000..61f03e74 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java @@ -0,0 +1,21 @@ +package com.zmops.iot.web.device.controller; + +import com.zmops.iot.model.response.ResponseData; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author nantian created at 2021/9/20 14:30 + *

+ * 设备物模型: 事件 + */ +@RestController +@RequestMapping("/device/event") +public class DeviceEventController { + + + @RequestMapping("/create") + public ResponseData createDeviceEvent() { + return ResponseData.success(); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index 5cd77921..0d5f4b57 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -9,7 +9,7 @@ import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.device.service.DeviceEventService; +import com.zmops.iot.web.device.service.DeviceEventRuleService; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductEventRule; import com.zmops.zeus.driver.service.ZbxTrigger; @@ -33,7 +33,7 @@ public class DeviceEventTriggerController { @Autowired - DeviceEventService deviceEventService; + DeviceEventRuleService deviceEventRuleService; @Autowired private ZbxTrigger zbxTrigger; @@ -53,7 +53,7 @@ public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId, @Reque if (null == productEvent) { throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); } - return ResponseData.success(deviceEventService.detail(productEvent, eventRuleId, deviceId)); + return ResponseData.success(deviceEventRuleService.detail(productEvent, eventRuleId, deviceId)); } /** @@ -78,14 +78,14 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn Long eventRuleId = IdUtil.getSnowflake().nextId(); // ruleId, trigger name - deviceEventService.createProductEventRule(eventRuleId, eventRule); + deviceEventRuleService.createProductEventRule(eventRuleId, eventRule); //step 1: 先创建 zbx 触发器 String expression = eventRule.getExpList() .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); //step 2: zbx 保存触发器 - String[] triggerIds = deviceEventService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); + String[] triggerIds = deviceEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); //step 4: zbx 触发器创建 Tag Map tags = eventRule.getTags().stream() @@ -103,9 +103,8 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn zbxTrigger.triggerTagCreate(triggerId, tags); } - //step 5: 更新 zbxId - deviceEventService.updateProductEventRuleZbxId(eventRuleId, triggerIds); + deviceEventRuleService.updateProductEventRuleZbxId(eventRuleId, triggerIds); // 返回触发器ID return ResponseData.success(eventRuleId); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 0623ced7..201ecd83 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -31,7 +31,7 @@ * @author yefei **/ @Service -public class DeviceEventService { +public class DeviceEventRuleService { @Autowired private ZbxTrigger zbxTrigger; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index a971f96b..a7401d44 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -16,7 +16,7 @@ import com.zmops.iot.web.product.dto.ProductEventDto; import com.zmops.iot.web.product.dto.ProductEventRule; import com.zmops.iot.web.product.dto.param.EventParm; -import com.zmops.iot.web.product.service.EventRuleService; +import com.zmops.iot.web.product.service.ProductEventRuleService; import com.zmops.zeus.driver.service.ZbxTrigger; import io.ebean.DB; import io.ebean.annotation.Transactional; @@ -41,7 +41,7 @@ public class ProductEventTriggerController { @Autowired - private EventRuleService eventRuleService; + private ProductEventRuleService productEventRuleService; @Autowired private ZbxTrigger zbxTrigger; @@ -58,7 +58,7 @@ public class ProductEventTriggerController { */ @PostMapping("/getEventByPage") public Pager getEventByPage(@RequestBody EventParm eventParm) { - return eventRuleService.getEventByPage(eventParm); + return productEventRuleService.getEventByPage(eventParm); } /** @@ -73,7 +73,7 @@ public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId, @Reque if (null == productEvent) { throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); } - return ResponseData.success(eventRuleService.detail(productEvent, eventRuleId, prodId)); + return ResponseData.success(productEventRuleService.detail(productEvent, eventRuleId, prodId)); } /** @@ -89,14 +89,14 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE Long eventRuleId = IdUtil.getSnowflake().nextId(); // ruleId, trigger name - eventRuleService.createProductEventRule(eventRuleId, eventRule); + productEventRuleService.createProductEventRule(eventRuleId, eventRule); //step 1: 先创建 zbx 触发器 String expression = eventRule.getExpList() .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); //step 2: zbx 保存触发器 - String[] triggerIds = eventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); + String[] triggerIds = productEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); //step 4: zbx 触发器创建 Tag Map tags = eventRule.getTags().stream() @@ -116,7 +116,7 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE //step 5: 更新 zbxId - eventRuleService.updateProductEventRuleZbxId(eventRuleId, triggerIds); + productEventRuleService.updateProductEventRuleZbxId(eventRuleId, triggerIds); // 返回触发器ID return ResponseData.success(eventRuleId); @@ -134,7 +134,7 @@ public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseE ProductEventRule eventRule) { //step 1: 更新所有服务 - eventRuleService.updateProductEventRule(eventRule.getEventRuleId(), eventRule); + productEventRuleService.updateProductEventRule(eventRule.getEventRuleId(), eventRule); //step 2: 更新zbx表达式 String expression = eventRule.getExpList() diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java index 3e9f5997..4c8d3b2b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java @@ -1,17 +1,12 @@ package com.zmops.iot.web.product.dto; -import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.product.ProductEventExpression; import com.zmops.iot.domain.product.ProductEventService; import lombok.Data; import lombok.Getter; import lombok.Setter; -import javax.validation.Valid; import javax.validation.constraints.Max; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; import java.util.List; /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index ce4cae18..1249fa2a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -37,7 +37,7 @@ @Slf4j @Service -public class EventRuleService { +public class ProductEventRuleService { @Autowired private ZbxTrigger zbxTrigger; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/EventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/EventTriggerController.java new file mode 100644 index 00000000..9c2cc1be --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/EventTriggerController.java @@ -0,0 +1,52 @@ +package com.zmops.iot.web.trigger; + +import com.alibaba.fastjson.JSON; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.trigger.dto.TriggerStatusDto; +import com.zmops.zeus.driver.service.ZbxTrigger; +import lombok.Getter; +import lombok.Setter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +/** + * @author nantian created at 2021/9/20 14:53 + *

+ * 通用触发器相关 + */ + +@RestController +@RequestMapping("/event/trigger") +public class EventTriggerController { + + + @Autowired + private ZbxTrigger zbxTrigger; + + /** + * 修改 设备 产品 告警规则启用禁用 + * + * @return + */ + @RequestMapping("/status/update") + public ResponseData updateTriggerStatus(@RequestBody @Valid TriggerStatusDto statusDto) { + String res = zbxTrigger.triggerStatusUpdate(statusDto.getTriggerId(), statusDto.getStatus()); + +// DB.update(ProductEvent.class) +// .where().eq("eventRuleId", statusDto.getEventRuleId()) +// .asUpdate().set("status", statusDto.getStatus()).update(); // 0 启用,1 禁用 + + + return ResponseData.success(JSON.parseObject(res, TriggerIds.class).getTriggerids()[0]); + } + + @Getter + @Setter + static class TriggerIds { + private String[] triggerids; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/dto/TriggerStatusDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/dto/TriggerStatusDto.java new file mode 100644 index 00000000..3c7915e5 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/dto/TriggerStatusDto.java @@ -0,0 +1,25 @@ +package com.zmops.iot.web.trigger.dto; + +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; + +/** + * @author nantian created at 2021/9/20 15:37 + */ + +@Getter +@Setter +public class TriggerStatusDto { + + @NotBlank + private String triggerId; + + @Pattern(regexp = "^[01]$") + private String status; + + @NotBlank + private String eventRuleId; +} From 0893ce77bd6d8aeca5faf7d515b5677ebaaf5313 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Mon, 20 Sep 2021 17:01:43 +0800 Subject: [PATCH 229/763] [fix]: fix stop.sh --- dist-material/bin/stop.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dist-material/bin/stop.sh b/dist-material/bin/stop.sh index 65fe8e1d..f8efec7c 100755 --- a/dist-material/bin/stop.sh +++ b/dist-material/bin/stop.sh @@ -1,11 +1,11 @@ #!/usr/bin/env bash set -x -ps -ef | grep zeus-iot-bin | grep -v grep > /tmp/test + status=`ps -ef | grep zeus-iot-bin | grep java | grep -v grep | awk '{print $2}' | wc -l` if [ $status -ne 0 ] then - for i in `ps -ef | grep zeus-iot-bin | grep -v grep | awk '{print $2}'` + for i in `ps -ef | grep zeus-iot-bin | grep java | grep -v grep | awk '{print $2}'` do kill -9 $i done From 64618d2615e5a1421e67e9548128918bcf7dfdc7 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 20 Sep 2021 17:13:21 +0800 Subject: [PATCH 230/763] [style]: change code style --- .../iot/web/device/service/work/SaveOtherWorker.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java index abdeb09f..17f32689 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java @@ -12,7 +12,7 @@ import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; -import com.zmops.iot.web.product.service.EventRuleService; +import com.zmops.iot.web.product.service.ProductEventRuleService; import com.zmops.zeus.driver.service.ZbxTrigger; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; @@ -73,9 +73,9 @@ public Boolean action(DeviceDto deviceDto, Map> allW .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "").execute(); //告警规则关联 并 回填zbx triggerId - List triggers = JSONObject.parseArray(zbxTrigger.triggerGetByHost(deviceId), EventRuleService.Triggers.class); - Map map = triggers.parallelStream().collect(Collectors.toMap(EventRuleService.Triggers::getDescription, EventRuleService.Triggers::getTriggerid)); - List productEventRelationList = new QProductEventRelation().relationId.eq(deviceDto.getProductId() + "").findList(); + List triggers = JSONObject.parseArray(zbxTrigger.triggerGetByHost(deviceId), ProductEventRuleService.Triggers.class); + Map map = triggers.parallelStream().collect(Collectors.toMap(ProductEventRuleService.Triggers::getDescription, ProductEventRuleService.Triggers::getTriggerid)); + List productEventRelationList = new QProductEventRelation().relationId.eq(deviceDto.getProductId() + "").findList(); for (ProductEventRelation productEventRelation : productEventRelationList) { productEventRelation.setId(null); productEventRelation.setRelationId(deviceId); From 819514e431e9598238d1cae329a95346f91a7fa0 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 20 Sep 2021 17:39:01 +0800 Subject: [PATCH 231/763] [style]: change code style --- .../domain/product/ProductEventRelation.java | 2 +- .../zmops/zeus/driver/service/ZbxTrigger.java | 8 +++++--- .../DeviceEventTriggerController.java | 4 ++-- .../device/service/DeviceEventRuleService.java | 18 ++++++++++-------- .../device/service/work/SaveOtherWorker.java | 12 ++++++++---- .../ProductEventTriggerController.java | 4 ++-- .../service/ProductEventRuleService.java | 13 +++++++------ 7 files changed, 35 insertions(+), 26 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java index 0366a5e0..a21351cf 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java @@ -23,7 +23,7 @@ public class ProductEventRelation { private String relationId; - private String zbxId; + private Integer zbxId; private String inherit; diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java index 32bfb099..85e0254f 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java @@ -41,7 +41,7 @@ String triggerCreate(@ParamName("triggerName") String triggerName, */ @Post @JsonPath("/trigger/trigger.update") - String triggerUpdate(@ParamName("triggerId") String triggerId, + String triggerUpdate(@ParamName("triggerId") Integer triggerId, @ParamName("expression") String expression, @ParamName("ruleLevel") Byte ruleLevel); @@ -55,7 +55,7 @@ String triggerUpdate(@ParamName("triggerId") String triggerId, */ @Post @JsonPath("/trigger/trigger.tags.update") - String triggerTagCreate(@ParamName("triggerId") String triggerId, + String triggerTagCreate(@ParamName("triggerId") Integer triggerId, @ParamName("tagMap") Map tags); /** @@ -67,6 +67,7 @@ String triggerTagCreate(@ParamName("triggerId") String triggerId, @JsonPath("/trigger/trigger.get") String triggerGet(@ParamName("triggerIds") String triggerIds); + /** * 根据TRIGGER ID查询触发器及触发器标签 * @@ -74,7 +75,8 @@ String triggerTagCreate(@ParamName("triggerId") String triggerId, */ @Post @JsonPath("/trigger/triggerAndTags.get") - String triggerAndTagsGet(@ParamName("triggerIds") String triggerIds); + String triggerAndTagsGet(@ParamName("triggerIds") Integer triggerIds); + /** * 根据host 查询触发器 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index 0d5f4b57..619da889 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -85,7 +85,7 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); //step 2: zbx 保存触发器 - String[] triggerIds = deviceEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); + Integer[] triggerIds = deviceEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); //step 4: zbx 触发器创建 Tag Map tags = eventRule.getTags().stream() @@ -99,7 +99,7 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); } - for (String triggerId : triggerIds) { + for (Integer triggerId : triggerIds) { zbxTrigger.triggerTagCreate(triggerId, tags); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 201ecd83..6192b7b4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -124,11 +124,11 @@ private ProductEventExpression initEventExpression(ProductEventRule.Expression e * @param triggerId 规则ID * @param zbxId triggerId */ - public void updateProductEventRuleZbxId(Long triggerId, String[] zbxId) { + public void updateProductEventRuleZbxId(Long triggerId, Integer[] zbxId) { List triggers = JSONObject.parseArray(zbxTrigger.triggerGet(Arrays.toString(zbxId)), Triggers.class); - Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.get(0).host, Triggers::getTriggerid)); + Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.get(0).host, Triggers::getTriggerid)); List productEventRelationList = new QProductEventRelation().eventRuleId.eq(triggerId).findList(); @@ -151,9 +151,11 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(deviceId).eventRuleId.eq(eventRuleId).findOne(); - JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); - - productEventRuleDto.setTags(JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class)); + if (null != productEventRelation) { + JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); + productEventRuleDto.setTags(JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class)); + productEventRuleDto.setZbxId(productEventRelation.getZbxId()); + } return productEventRuleDto; } @@ -166,19 +168,19 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S * @param level 告警等级 * @return 触发器ID */ - public String[] createZbxTrigger(String triggerName, String expression, Byte level) { + public Integer[] createZbxTrigger(String triggerName, String expression, Byte level) { String res = zbxTrigger.triggerCreate(triggerName, expression, level); return JSON.parseObject(res, TriggerIds.class).getTriggerids(); } @Data static class TriggerIds { - private String[] triggerids; + private Integer[] triggerids; } @Data public static class Triggers { - private String triggerid; + private Integer triggerid; private String description; private List hosts; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java index 17f32689..5d24d3c6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java @@ -73,15 +73,19 @@ public Boolean action(DeviceDto deviceDto, Map> allW .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "").execute(); //告警规则关联 并 回填zbx triggerId - List triggers = JSONObject.parseArray(zbxTrigger.triggerGetByHost(deviceId), ProductEventRuleService.Triggers.class); - Map map = triggers.parallelStream().collect(Collectors.toMap(ProductEventRuleService.Triggers::getDescription, ProductEventRuleService.Triggers::getTriggerid)); - List productEventRelationList = new QProductEventRelation().relationId.eq(deviceDto.getProductId() + "").findList(); + List triggers = JSONObject.parseArray(zbxTrigger.triggerGetByHost(deviceId), ProductEventRuleService.Triggers.class); + + Map map = triggers.parallelStream().collect(Collectors.toMap(ProductEventRuleService.Triggers::getDescription, ProductEventRuleService.Triggers::getTriggerid)); + + List productEventRelationList = new QProductEventRelation().relationId.eq(deviceDto.getProductId() + "").findList(); + for (ProductEventRelation productEventRelation : productEventRelationList) { productEventRelation.setId(null); productEventRelation.setRelationId(deviceId); productEventRelation.setInherit("1"); - productEventRelation.setZbxId(Optional.ofNullable(map.get(productEventRelation.getEventRuleId())).orElse("")); + productEventRelation.setZbxId(productEventRelation.getZbxId()); } + DB.saveAll(productEventRelationList); //告警执行动作关联 DB.sqlUpdate("insert into product_event_service (service_id,device_id,execute_device_id,event_rule_id,inherit) SELECT service_id,:deviceId,:executeDeviceId,event_rule_id,1 from product_event_service where relation_id=:relationId") diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index a7401d44..5d72a0a3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -96,7 +96,7 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); //step 2: zbx 保存触发器 - String[] triggerIds = productEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); + Integer[] triggerIds = productEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); //step 4: zbx 触发器创建 Tag Map tags = eventRule.getTags().stream() @@ -110,7 +110,7 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); } - for (String triggerId : triggerIds) { + for (Integer triggerId : triggerIds) { zbxTrigger.triggerTagCreate(triggerId, tags); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index 1249fa2a..b0e9cedd 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -178,11 +178,12 @@ private ProductEventExpression initEventExpression(ProductEventRule.Expression e * @param eventRuleId 规则ID * @param zbxId triggerId */ - public void updateProductEventRuleZbxId(Long eventRuleId, String[] zbxId) { - String s = zbxTrigger.triggerGet(Arrays.toString(zbxId)); + public void updateProductEventRuleZbxId(Long eventRuleId, Integer[] zbxId) { + String s = zbxTrigger.triggerGet(Arrays.toString(zbxId)); + List triggers = JSONObject.parseArray(s, Triggers.class); - Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.get(0).host, Triggers::getTriggerid)); + Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.get(0).host, Triggers::getTriggerid)); List productEventRelationList = new QProductEventRelation().eventRuleId.eq(eventRuleId).findList(); @@ -204,7 +205,7 @@ public void updateProductEventRuleZbxId(Long eventRuleId, String[] zbxId) { * @param level 告警等级 * @return 触发器ID */ - public String[] createZbxTrigger(String triggerName, String expression, Byte level) { + public Integer[] createZbxTrigger(String triggerName, String expression, Byte level) { String res = zbxTrigger.triggerCreate(triggerName, expression, level); return JSON.parseObject(res, TriggerIds.class).getTriggerids(); } @@ -271,12 +272,12 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S @Data static class TriggerIds { - private String[] triggerids; + private Integer[] triggerids; } @Data public static class Triggers { - private String triggerid; + private Integer triggerid; private String description; private List hosts; } From 9318615a2ab58855bbb0fc2397da1e604f815187 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 20 Sep 2021 18:37:13 +0800 Subject: [PATCH 232/763] [fix]: event trigger update bug fix --- .../DeviceEventTriggerController.java | 16 +---- .../service/DeviceEventRuleService.java | 66 ++++++++++--------- .../device/service/DeviceModelService.java | 10 +-- .../web/exception/enums/BizExceptionEnum.java | 8 ++- .../ProductEventTriggerController.java | 50 +++++++------- .../service/ProductEventRuleService.java | 6 +- 6 files changed, 78 insertions(+), 78 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index 619da889..f39f81b2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -59,26 +59,16 @@ public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId, @Reque /** * 修改 触发器 * - * @param eventRule 触发器规则 + * @param eventRule 触发器规则 TODO 此处不可以修改 产品上的 告警规则 * @return 触发器ID */ @Transactional @PostMapping("/update") public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) ProductEventRule eventRule) { - List deviceIds = eventRule.getExpList().parallelStream().map(ProductEventRule.Expression::getDeviceId).collect(Collectors.toList()); - if (ToolUtil.isEmpty(deviceIds)) { - throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); - } - //step 1: 删除原有的 关联关系 - deviceIds.forEach(deviceId -> { - new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).relationId.eq(deviceId).delete(); - new QProductEventService().eventRuleId.eq(eventRule.getEventRuleId()).deviceId.eq(deviceId).delete(); - }); - Long eventRuleId = IdUtil.getSnowflake().nextId(); // ruleId, trigger name - deviceEventRuleService.createProductEventRule(eventRuleId, eventRule); + deviceEventRuleService.updateDeviceEventRule(eventRuleId, eventRule); //step 1: 先创建 zbx 触发器 String expression = eventRule.getExpList() @@ -103,7 +93,7 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn zbxTrigger.triggerTagCreate(triggerId, tags); } - //step 5: 更新 zbxId + //step 5: 更新 zbxId 反写 deviceEventRuleService.updateProductEventRuleZbxId(eventRuleId, triggerIds); // 返回触发器ID diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 6192b7b4..7bc68893 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -36,19 +36,28 @@ public class DeviceEventRuleService { @Autowired private ZbxTrigger zbxTrigger; - /** - * 保存触发器 - * - * @param eventRuleId 触发器ID - * @param eventRule 告警规则 - */ - public void createProductEventRule(Long eventRuleId, ProductEventRule eventRule) { - // step 1: 保存产品告警规则 + + public void updateDeviceEventRule(Long eventRuleId, ProductEventRule eventRule) { + + //step 1: 函数表达式 + DB.sqlUpdate("delete from product_event_expression where event_rule_id = :eventRuleId") + .setParameter("eventRuleId", eventRule.getEventRuleId()) + .execute(); + + //step 2: 删除服务方法调用 + DB.sqlUpdate("delete from product_event_service where event_rule_id = :eventRuleId") + .setParameter("eventRuleId", eventRule.getEventRuleId()) + .execute(); + + // 删除和所有设备的关联关系 + new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + // step 3: 保存产品告警规则 ProductEvent event = initEventRule(eventRule); event.setEventRuleId(eventRuleId); - DB.save(event); + DB.update(event); - //step 2: 保存 表达式,方便回显 + //step 4: 保存 表达式,方便回显 List expList = new ArrayList<>(); eventRule.getExpList().forEach(i -> { @@ -59,41 +68,34 @@ public void createProductEventRule(Long eventRuleId, ProductEventRule eventRule) DB.saveAll(expList); - //step 3: 保存触发器 调用 本产品方法 + //step 5: 保存触发器 调用 本产品方法 if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { eventRule.getDeviceServices().forEach(i -> { - DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") + DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id, service_id) values (:eventRuleId, :deviceId, :serviceId)") .setParameter("eventRuleId", eventRuleId) - .setParameter("deviceId", eventRuleId) + .setParameter("deviceId", eventRule.getProductId()) .setParameter("executeDeviceId", i.getExecuteDeviceId()) .setParameter("serviceId", i.getServiceId()) .execute(); }); } - //step 4: 保存关联关系 - if (ToolUtil.isNotEmpty(eventRule.getProductId())) { + // step 6: 保存关联关系 + List relationIds = eventRule.getExpList().parallelStream().map(ProductEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); + if (ToolUtil.isEmpty(relationIds)) { + throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); + } + List productEventRelationList = new ArrayList<>(); + relationIds.forEach(relationId -> { ProductEventRelation productEventRelation = new ProductEventRelation(); productEventRelation.setEventRuleId(eventRuleId); - productEventRelation.setRelationId(eventRule.getProductId()); - DB.save(productEventRelation); - } else { - List relationIds = eventRule.getExpList().parallelStream().map(ProductEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); - if (ToolUtil.isEmpty(relationIds)) { - throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); - } - List productEventRelationList = new ArrayList<>(); - relationIds.forEach(relationId -> { - ProductEventRelation productEventRelation = new ProductEventRelation(); - productEventRelation.setEventRuleId(eventRuleId); - productEventRelation.setRelationId(relationId); - productEventRelationList.add(productEventRelation); - }); - DB.saveAll(productEventRelationList); - } - + productEventRelation.setRelationId(relationId); + productEventRelationList.add(productEventRelation); + }); + DB.saveAll(productEventRelationList); } + private ProductEvent initEventRule(ProductEventRule eventRule) { ProductEvent event = new ProductEvent(); event.setEventLevel(eventRule.getEventLevel()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index b8112a25..f9081613 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -196,7 +196,7 @@ public String createTrapperItem(ProductAttr productAttr) { } return zbxItem.createTrapperItem(itemName, productAttr.getKey(), - hostId, productAttr.getSource(),productAttr.getMasterItemId(),productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(), productAttr.getMasterItemId(), productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); } /** @@ -212,15 +212,15 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { if (null == device) { throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); } - String hostId = device.getZbxId(); + String hostId = device.getZbxId(); + List processingSteps = new ArrayList<>(); + if (ToolUtil.isNotEmpty(productAttr.getProcessStepList())) { productAttr.getProcessStepList().forEach(i -> { ZbxProcessingStep step = new ZbxProcessingStep(); - step.setType(i.getType()); step.setParams(i.getParams()); - processingSteps.add(step); }); } @@ -232,7 +232,7 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { } zbxItem.updateTrapperItem(productAttribute.getZbxId(), productAttr.getAttrId() + "", productAttr.getKey(), - hostId, productAttr.getSource(),productAttr.getMasterItemId(),productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(), productAttr.getMasterItemId(), productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); DB.update(productAttribute); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index 9ed801a7..ec52d253 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -140,8 +140,8 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { */ PRODUCT_ATTR_KEY_EXISTS(1401, "该属性Key已存在"), PRODUCT_ATTR_KEY_NOT_EXISTS(1404, "该属性Key不存在"), - PRODUCT_ATTR_DEPTED_NULL(1402,"依赖的属性不能为空"), - PRODUCT_ATTR_DEPTED_NOT_EXIST(1403,"依赖的属性不能为空"), + PRODUCT_ATTR_DEPTED_NULL(1402, "依赖的属性不能为空"), + PRODUCT_ATTR_DEPTED_NOT_EXIST(1403, "依赖的属性不能为空"), /** * 设备相关 @@ -161,8 +161,10 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { RULE_NOT_EXISTS(1701, "上下线规则不存在"), RULE_EXISTS(1702, "上下线规则已存在"), - EVENT_HAS_NOT_DEVICE(1703,"告警规则缺少关联产品或设备"), + EVENT_HAS_NOT_DEVICE(1703, "告警规则缺少关联产品或设备"), EVENT_NOT_EXISTS(1704, "告警规则不存在"), + EVENT_EXPRESSION_NOT_EXISTS(1705, "告警表达式关联关系不存在"), + /** * 租户相关的异常 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index 5d72a0a3..3ab8ce5b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -114,7 +114,6 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE zbxTrigger.triggerTagCreate(triggerId, tags); } - //step 5: 更新 zbxId productEventRuleService.updateProductEventRuleZbxId(eventRuleId, triggerIds); @@ -130,8 +129,7 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE */ @Transactional @PostMapping("/update") - public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) - ProductEventRule eventRule) { + public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) ProductEventRule eventRule) { //step 1: 更新所有服务 productEventRuleService.updateProductEventRule(eventRule.getEventRuleId(), eventRule); @@ -140,28 +138,34 @@ public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseE String expression = eventRule.getExpList() .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); - ProductEvent event = new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).findOne(); - if (null != event) { - List list = new QProductEventRelation().eventRuleId.eq(event.getEventRuleId()).findList(); - list.forEach(productEventRelation -> { - zbxTrigger.triggerUpdate(productEventRelation.getZbxId(), expression, eventRule.getEventLevel()); - - //step 3: zbx 触发器创建 Tag - Map tags = eventRule.getTags().stream() - .collect(Collectors.toMap(ProductEventRule.Tag::getTag, ProductEventRule.Tag::getValue, (k1, k2) -> k2)); - if (ToolUtil.isEmpty(tags)) { - tags = new HashMap<>(2); - } - if (!tags.containsKey(ALARM_TAG_NAME)) { - tags.put(ALARM_TAG_NAME, eventRule.getEventRuleId() + ""); - } - if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { - tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); - } - zbxTrigger.triggerTagCreate(productEventRelation.getZbxId(), tags); - }); + if (event == null) { + throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); + } + + List list = new QProductEventRelation().eventRuleId.eq(event.getEventRuleId()).findList(); + if (list.isEmpty()) { + throw new ServiceException(BizExceptionEnum.EVENT_EXPRESSION_NOT_EXISTS); + } + + zbxTrigger.triggerUpdate(list.get(0).getZbxId(), expression, eventRule.getEventLevel()); + + + //step 3: zbx 触发器创建 Tag + Map tags = eventRule.getTags().stream() + .collect(Collectors.toMap(ProductEventRule.Tag::getTag, ProductEventRule.Tag::getValue, (k1, k2) -> k2)); + + if (ToolUtil.isEmpty(tags)) { + tags = new HashMap<>(2); } + if (!tags.containsKey(ALARM_TAG_NAME)) { + tags.put(ALARM_TAG_NAME, eventRule.getEventRuleId() + ""); + } + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { + tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); + } + + zbxTrigger.triggerTagCreate(list.get(0).getZbxId(), tags); return ResponseData.success(eventRule.getEventRuleId()); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index b0e9cedd..f62a1322 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -259,9 +259,11 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(prodId).eventRuleId.eq(eventRuleId).findOne(); - JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); - List tagList = JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class); + JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); + List tagList = JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class); + + productEventRuleDto.setZbxId(productEventRelation.getZbxId()); productEventRuleDto.setTags(tagList.stream() .filter(s -> s.getTag().equals("__execute__") || s.getTag().equals("__alarm__")) .collect(Collectors.toList())); From 14c2a92f5dd981eb8b83ba33a11ba4ba582608c2 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 20 Sep 2021 19:10:24 +0800 Subject: [PATCH 233/763] [feat]: update zeus-iot-ui --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index 3b8c4f11..10c88971 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit 3b8c4f1125609b77c875363425e0301240a95aea +Subproject commit 10c88971e6bb36808f4ea2b11f2386697da03d00 From cf8e8cea0c51c91b961393b63d384b8c51fadd86 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 20 Sep 2021 19:11:22 +0800 Subject: [PATCH 234/763] [fix]: fix event trigger update bug --- .../iot/domain/product/ProductEvent.java | 4 ++-- .../DeviceEventTriggerController.java | 15 +++++++------- .../service/DeviceEventRuleService.java | 20 ++++++++++++++++--- .../iot/web/product/dto/ProductEventRule.java | 3 ++- .../service/ProductEventRuleService.java | 4 ++-- 5 files changed, 30 insertions(+), 16 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java index 57a03d97..e4de3ba5 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java @@ -22,9 +22,9 @@ public class ProductEvent extends BaseEntity { private Long eventRuleId; private String eventRuleName; - private Byte eventLevel; + private String eventLevel; private String expLogic; private String remark; - private Byte eventNotify; + private String eventNotify; private String status; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index f39f81b2..65c71756 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -65,17 +65,16 @@ public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId, @Reque @Transactional @PostMapping("/update") public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) ProductEventRule eventRule) { - //step 1: 删除原有的 关联关系 - Long eventRuleId = IdUtil.getSnowflake().nextId(); // ruleId, trigger name - deviceEventRuleService.updateDeviceEventRule(eventRuleId, eventRule); + //step 1: 删除原有的 关联关系 + deviceEventRuleService.updateDeviceEventRule(eventRule.getEventRuleId(), eventRule); //step 1: 先创建 zbx 触发器 String expression = eventRule.getExpList() .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); //step 2: zbx 保存触发器 - Integer[] triggerIds = deviceEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); + Integer[] triggerIds = deviceEventRuleService.updateZbxTrigger(eventRule.getZbxId(), expression, eventRule.getEventLevel()); //step 4: zbx 触发器创建 Tag Map tags = eventRule.getTags().stream() @@ -84,20 +83,20 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn tags = new HashMap<>(2); } if (!tags.containsKey(ALARM_TAG_NAME)) { - tags.put(ALARM_TAG_NAME, eventRuleId + ""); + tags.put(ALARM_TAG_NAME, eventRule.getEventRuleId() + ""); } if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { - tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); + tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); } for (Integer triggerId : triggerIds) { zbxTrigger.triggerTagCreate(triggerId, tags); } //step 5: 更新 zbxId 反写 - deviceEventRuleService.updateProductEventRuleZbxId(eventRuleId, triggerIds); + deviceEventRuleService.updateProductEventRuleZbxId(eventRule.getEventRuleId(), triggerIds); // 返回触发器ID - return ResponseData.success(eventRuleId); + return ResponseData.success(eventRule.getEventRuleId()); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 7bc68893..112e8888 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -6,6 +6,7 @@ import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.ProductEventExpression; import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEvent; import com.zmops.iot.domain.product.query.QProductEventExpression; import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventService; @@ -55,7 +56,7 @@ public void updateDeviceEventRule(Long eventRuleId, ProductEventRule eventRule) // step 3: 保存产品告警规则 ProductEvent event = initEventRule(eventRule); event.setEventRuleId(eventRuleId); - DB.update(event); + event.update(); //step 4: 保存 表达式,方便回显 List expList = new ArrayList<>(); @@ -98,9 +99,9 @@ public void updateDeviceEventRule(Long eventRuleId, ProductEventRule eventRule) private ProductEvent initEventRule(ProductEventRule eventRule) { ProductEvent event = new ProductEvent(); - event.setEventLevel(eventRule.getEventLevel()); + event.setEventLevel(eventRule.getEventLevel().toString()); event.setExpLogic(eventRule.getExpLogic()); - event.setEventNotify(eventRule.getEventNotify()); + event.setEventNotify(eventRule.getEventNotify().toString()); event.setRemark(eventRule.getRemark()); event.setEventRuleName(eventRule.getEventRuleName()); event.setStatus(CommonStatus.ENABLE.getCode()); @@ -175,6 +176,19 @@ public Integer[] createZbxTrigger(String triggerName, String expression, Byte le return JSON.parseObject(res, TriggerIds.class).getTriggerids(); } + /** + * 更新 触发器 + * + * @param triggerId + * @param expression + * @param level + * @return + */ + public Integer[] updateZbxTrigger(Integer triggerId, String expression, Byte level) { + String res = zbxTrigger.triggerUpdate(triggerId, expression, level); + return JSON.parseObject(res, TriggerIds.class).getTriggerids(); + } + @Data static class TriggerIds { private Integer[] triggerids; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java index 4c3a504d..d8cd5a1a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java @@ -4,6 +4,7 @@ import lombok.Data; import lombok.Getter; import lombok.Setter; +import org.apache.commons.lang.StringUtils; import javax.validation.Valid; import javax.validation.constraints.Max; @@ -103,7 +104,7 @@ public String toString() { expression.append("/"); expression.append(productAttrKey); - if (null != scope) { + if (StringUtils.isNotBlank(scope)) { expression.append(", "); expression.append(scope); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index f62a1322..73401261 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -149,9 +149,9 @@ public void updateProductEventRule(Long eventRuleId, ProductEventRule eventRule) private ProductEvent initEventRule(ProductEventRule eventRule) { ProductEvent event = new ProductEvent(); - event.setEventLevel(eventRule.getEventLevel()); + event.setEventLevel(eventRule.getEventLevel().toString()); event.setExpLogic(eventRule.getExpLogic()); - event.setEventNotify(eventRule.getEventNotify()); + event.setEventNotify(eventRule.getEventNotify().toString()); event.setRemark(eventRule.getRemark()); event.setEventRuleName(eventRule.getEventRuleName()); event.setStatus(CommonStatus.ENABLE.getCode()); From 8298eaf2e9540549ee65c566850b894dc4c13ec9 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 22 Sep 2021 00:32:25 +0800 Subject: [PATCH 235/763] [style]: add git ignore, static file path --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c2ebb149..ceaab4ca 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ .vscode **/node_modules/* dist/ +zeus-starter/src/main/resources/public/ From d6cdcb2f2701869e9d79f17d1ade754c26c06cfd Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 22 Sep 2021 00:34:59 +0800 Subject: [PATCH 236/763] [feat]: global error page --- .../web/exception/page/GlobalController.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/exception/page/GlobalController.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/page/GlobalController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/page/GlobalController.java new file mode 100644 index 00000000..6fce4466 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/page/GlobalController.java @@ -0,0 +1,31 @@ +package com.zmops.iot.web.exception.page; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * 全局的控制器 + * + * @author fengshuonan + */ +@Controller +@RequestMapping("/global") +public class GlobalController { + + /** + * 跳转到404页面 + */ + @RequestMapping(path = "/error") + public String errorPage() { + return "/404"; + } + + /** + * 跳转到session超时页面 + */ + @RequestMapping(path = "/sessionError") + public String errorPageInfo(Model model) { + return "/index"; + } +} From db824e5a2613ee0cc12c5f0b75d5191152e30253 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 22 Sep 2021 00:45:02 +0800 Subject: [PATCH 237/763] [feat]: publish static page resource path --- .../JwtAuthenticationEntryPoint.java | 5 +- .../core/auth/filter/NoneAuthedResources.java | 6 +- zeus-starter/pom.xml | 2 +- ...OTApplication.java => IoTApplication.java} | 9 ++- .../config/security/WebSecurityConfig.java | 10 ++- .../com/zmops/iot/config/web/WebConfig.java | 10 +++ .../src/main/resources/application.yaml | 8 ++- zeus-webapp-bom/pom.xml | 4 ++ .../web/sys/controller/LoginController.java | 64 ++++++++++++++++--- .../iot/web/sys/service/SysUserService.java | 19 ++++++ 10 files changed, 112 insertions(+), 25 deletions(-) rename zeus-starter/src/main/java/com/zmops/iot/{IOTApplication.java => IoTApplication.java} (62%) diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/entrypoint/JwtAuthenticationEntryPoint.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/entrypoint/JwtAuthenticationEntryPoint.java index 96fdee69..d91ffb20 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/entrypoint/JwtAuthenticationEntryPoint.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/entrypoint/JwtAuthenticationEntryPoint.java @@ -31,8 +31,11 @@ public void commence(HttpServletRequest request, AuthenticationException authException) throws IOException { // GET请求跳转到主页 - if ("get".equalsIgnoreCase(request.getMethod()) && !request.getHeader("Accept").contains("application/json")) { + if ("get".equalsIgnoreCase(request.getMethod()) + && !request.getHeader("Accept").contains("application/json")) { + response.sendRedirect(request.getContextPath() + "/global/sessionError"); + } else { // POST请求返回json response.setCharacterEncoding("utf-8"); diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java index 09de04d2..884271cf 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java @@ -11,9 +11,8 @@ public class NoneAuthedResources { * 前端接口资源 */ public static final String[] FRONTEND_RESOURCES = { - "/assets/**", - "/favicon.ico", - "/activiti-editor/**" + "/static/**", + "/favicon.ico" }; @@ -47,7 +46,6 @@ public class NoneAuthedResources { "/rest/login", // 登录接口放开过滤 "/login", - "/hello", //oauth登录的接口 "/oauth/render/*", diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index 7b958208..b7b873ab 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -125,7 +125,7 @@ spring-boot-maven-plugin ${spring.boot.version} - com.zmops.iot.IOTApplication + com.zmops.iot.IoTApplication diff --git a/zeus-starter/src/main/java/com/zmops/iot/IOTApplication.java b/zeus-starter/src/main/java/com/zmops/iot/IoTApplication.java similarity index 62% rename from zeus-starter/src/main/java/com/zmops/iot/IOTApplication.java rename to zeus-starter/src/main/java/com/zmops/iot/IoTApplication.java index 474044e2..7d645c88 100644 --- a/zeus-starter/src/main/java/com/zmops/iot/IOTApplication.java +++ b/zeus-starter/src/main/java/com/zmops/iot/IoTApplication.java @@ -1,6 +1,8 @@ package com.zmops.iot; import com.dtflys.forest.springboot.annotation.ForestScan; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -13,10 +15,13 @@ */ @SpringBootApplication @ForestScan("com.zmops.zeus.driver.service") -public class IOTApplication { +public class IoTApplication { + + private final static Logger logger = LoggerFactory.getLogger(IoTApplication.class); public static void main(String[] args) { TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); - SpringApplication.run(IOTApplication.class, args); + SpringApplication.run(IoTApplication.class, args); + logger.info(IoTApplication.class.getSimpleName() + " is success!"); } } diff --git a/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java b/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java index 73886794..55baaf8a 100644 --- a/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java +++ b/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java @@ -52,8 +52,6 @@ protected void configure(HttpSecurity httpSecurity) throws Exception { //自定义退出 httpSecurity.logout().disable(); - //禁用匿名用户 - httpSecurity.anonymous().disable(); httpSecurity.exceptionHandling().authenticationEntryPoint(unauthorizedHandler); @@ -83,10 +81,10 @@ public void configure(WebSecurity web) throws Exception { // 静态资源放开过滤 .and().ignoring().antMatchers(HttpMethod.GET, - "/assets/**", - "/favicon.ico", - "/activiti-editor/**","/websocket/alarm/**" - ); + "/static/**", + "/favicon.ico", + "/websocket/alarm/**" + ); } } diff --git a/zeus-starter/src/main/java/com/zmops/iot/config/web/WebConfig.java b/zeus-starter/src/main/java/com/zmops/iot/config/web/WebConfig.java index 772f50b6..6d0469b7 100644 --- a/zeus-starter/src/main/java/com/zmops/iot/config/web/WebConfig.java +++ b/zeus-starter/src/main/java/com/zmops/iot/config/web/WebConfig.java @@ -2,10 +2,13 @@ import com.google.code.kaptcha.impl.DefaultKaptcha; import com.google.code.kaptcha.util.Config; +import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import java.util.Arrays; import java.util.Properties; /** @@ -15,6 +18,11 @@ @Configuration public class WebConfig implements WebMvcConfigurer { + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/static/**").addResourceLocations("classpath:/public/static/"); + } + /** * 验证码 Bean * @@ -32,8 +40,10 @@ public DefaultKaptcha kaptcha() { properties.put("kaptcha.session.key", "code"); properties.put("kaptcha.textproducer.char.length", "4"); properties.put("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑"); + Config config = new Config(properties); DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); + defaultKaptcha.setConfig(config); return defaultKaptcha; } diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index 15d985f3..72fe64cf 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -33,6 +33,12 @@ spring: jackson: generator: write_numbers_as_strings: true + mvc: + view: + prefix: /public + freemarker: + suffix: .html + template-loader-path: classpath:/public/ forest: log-enabled: false @@ -42,4 +48,4 @@ forest: zbxApiUrl: http://${ZEUS_ZABBIX_HOST:127.0.0.1}:${ZEUS_ZABBIX_PORT:80}/zabbix/api_jsonrpc.php zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:80} - zbxApiToken: 3464dee6b3fa3ce4173972e0497d7b84a93bdf8477ff1bdd51a7719cc0db2cd9 + zbxApiToken: 5376d4510465d6873d6c41076f26c58dae42701941e276971e8f068b76e660d0 diff --git a/zeus-webapp-bom/pom.xml b/zeus-webapp-bom/pom.xml index aff5cb10..980e2e88 100644 --- a/zeus-webapp-bom/pom.xml +++ b/zeus-webapp-bom/pom.xml @@ -92,6 +92,10 @@ org.springframework.boot spring-boot-starter-validation + + org.springframework.boot + spring-boot-starter-freemarker + org.freemarker freemarker diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java index 0a168bec..92da99ed 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java @@ -2,43 +2,88 @@ import com.google.code.kaptcha.Constants; import com.zmops.iot.constant.ConstantsContext; +import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.core.web.base.BaseController; +import com.zmops.iot.domain.sys.SysUser; import com.zmops.iot.model.exception.InvalidKaptchaException; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.model.response.SuccessResponseData; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.auth.AuthService; import com.zmops.iot.web.sys.dto.param.LoginParam; +import com.zmops.iot.web.sys.service.SysUserService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.util.List; +import java.util.Map; /** * @author nantian created at 2021/7/29 19:55 *

* 登陆 */ -@RestController +@Controller public class LoginController extends BaseController { @Autowired private AuthService authService; + @Autowired + private SysUserService userService; + + /** + * 跳转到主页 + */ + @RequestMapping(value = "/", method = RequestMethod.GET) + public String index(Model model) { + + //判断用户是否登录 + if (LoginContextHolder.getContext().hasLogin()) { + Map userIndexInfo = userService.getUserIndexInfo(); + + //用户信息为空,提示账号没分配角色登录不进去 + if (userIndexInfo == null) { + model.addAttribute("tips", "该用户没有角色,无法登陆"); + return "/login.html"; + } else { + model.addAllAttributes(userIndexInfo); + return "/index.html"; + } + + } else { + return "/index"; + } + } + + + /** + * 跳转到登录页面 + */ + @RequestMapping(value = "/login", method = RequestMethod.GET) + public String login() { + if (LoginContextHolder.getContext().hasLogin()) { + return REDIRECT + "/"; + } else { + return "/index"; + } + } + /** * 登录返回用户信息 * - * @param vo + * @param loginParam 登陆参数 * @return */ - @PostMapping(value = "/login") - public ResponseData loginVali(@Valid @RequestBody LoginParam vo) { - - String username = vo.getUsername(); - String password = vo.getPassword(); - + @ResponseBody + @RequestMapping(value = "/login", method = RequestMethod.POST) + public ResponseData loginVali(@Valid @RequestBody LoginParam loginParam) { + String username = loginParam.getUsername(); + String password = loginParam.getPassword(); if (ConstantsContext.getKaptchaOpen()) { String kaptcha = super.getPara("kaptcha").trim(); @@ -48,15 +93,14 @@ public ResponseData loginVali(@Valid @RequestBody LoginParam vo) { } } - //登录并返回登录用户信息 return new SuccessResponseData(authService.login(username, password)); } /** * 退出登录 */ - @RequestMapping(value = "/logout") @ResponseBody + @RequestMapping(value = "/logout") public ResponseData logOut() { authService.logout(); return new SuccessResponseData(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java index d565d0a9..907d5300 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java @@ -28,7 +28,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import static com.zmops.iot.web.init.DeviceSatusScriptInit.GLOBAL_ADMIN_ROLE_CODE; @@ -48,6 +50,23 @@ public class SysUserService implements CommandLineRunner { @Autowired private SysUserGroupService sysUserGroupService; + + public Map getUserIndexInfo() { + + //获取当前用户角色列表 + LoginUser user = LoginContextHolder.getContext().getUser(); + List roleList = user.getRoleList(); + + //用户没有角色无法显示首页信息 + if (roleList == null || roleList.size() == 0) { + return null; + } + + HashMap result = new HashMap<>(); + result.put("name", user.getName()); + return result; + } + /** * 用户列表 * From 098dd3a2d48c6dbb5ed079ffdb696e8998a28d6f Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 22 Sep 2021 01:07:33 +0800 Subject: [PATCH 238/763] [fix]: change node and npm version --- zeus-starter/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index b7b873ab..374adceb 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -73,8 +73,8 @@ ${frontend-maven-plugin.version} ${ui.path} - v12.18.3 - 6.14.6 + v14.17.6 + 6.14.15 From 0ee72dea2b6913703ac118afb744385bfbfc389a Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 22 Sep 2021 01:14:28 +0800 Subject: [PATCH 239/763] [feat]: add module zeus-transfer --- iot-server/pom.xml | 1 + iot-server/server-transfer/pom.xml | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 iot-server/server-transfer/pom.xml diff --git a/iot-server/pom.xml b/iot-server/pom.xml index c9f92f27..37f6c8ab 100644 --- a/iot-server/pom.xml +++ b/iot-server/pom.xml @@ -30,6 +30,7 @@ server-sender server-action server-storage-plugin + server-transfer diff --git a/iot-server/server-transfer/pom.xml b/iot-server/server-transfer/pom.xml new file mode 100644 index 00000000..3f3c684b --- /dev/null +++ b/iot-server/server-transfer/pom.xml @@ -0,0 +1,19 @@ + + + + zeus-iot + com.zmops + 1.0-beta + + 4.0.0 + + server-transfer + + + 8 + 8 + + + \ No newline at end of file From d38e0f9e3acf7850f5c8b1a03b6385c8b212dc75 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 22 Sep 2021 01:33:04 +0800 Subject: [PATCH 240/763] [style]: change class name --- .../{IOTServerBootstrap.java => IoTServerBootstrap.java} | 4 ++-- .../com/zmops/zeus/iot/server/starter/IOTServerStartUp.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/{IOTServerBootstrap.java => IoTServerBootstrap.java} (96%) diff --git a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerBootstrap.java b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java similarity index 96% rename from iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerBootstrap.java rename to iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java index a2901dbd..9b1c738d 100644 --- a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerBootstrap.java +++ b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java @@ -34,7 +34,7 @@ * 模块加载启动器,动态加载模块。 */ @Slf4j -public class IOTServerBootstrap { +public class IoTServerBootstrap { public static void start() { String mode = System.getProperty("mode"); RunningMode.setMode(mode); @@ -53,7 +53,7 @@ public static void start() { .setValue(System.currentTimeMillis() / 1000d); if (RunningMode.isInitMode()) { - log.info("Zeus IOT starts up in init mode successfully, exit now..."); + log.info("Zeus IoT starts up in init mode successfully, exit now..."); System.exit(0); } } catch (Throwable t) { diff --git a/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerStartUp.java b/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerStartUp.java index d5ba30b9..4beecf99 100644 --- a/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerStartUp.java +++ b/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerStartUp.java @@ -8,6 +8,6 @@ public class IOTServerStartUp { public static void main(String[] args) { - IOTServerBootstrap.start(); + IoTServerBootstrap.start(); } } From 85e18ad037e53612c90744089db1f0e31deb3bb6 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 22 Sep 2021 01:34:25 +0800 Subject: [PATCH 241/763] [style]: change bootstrap class style --- .../com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java index 9b1c738d..c5cf80bb 100644 --- a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java +++ b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java @@ -40,7 +40,8 @@ public static void start() { RunningMode.setMode(mode); ApplicationConfigLoader configLoader = new ApplicationConfigLoader(); - ModuleManager manager = new ModuleManager(); + + ModuleManager manager = new ModuleManager(); try { ApplicationConfiguration applicationConfiguration = configLoader.load(); manager.init(applicationConfiguration); @@ -56,6 +57,7 @@ public static void start() { log.info("Zeus IoT starts up in init mode successfully, exit now..."); System.exit(0); } + } catch (Throwable t) { log.error(t.getMessage(), t); System.exit(1); From fbdef40c972b975775b453f279c42b92cecdd983 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 22 Sep 2021 09:44:34 +0800 Subject: [PATCH 242/763] [style]: change trigger controller package location --- .../web/trigger/{ => controller}/EventTriggerController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename zeus-webapp/src/main/java/com/zmops/iot/web/trigger/{ => controller}/EventTriggerController.java (96%) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/EventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/controller/EventTriggerController.java similarity index 96% rename from zeus-webapp/src/main/java/com/zmops/iot/web/trigger/EventTriggerController.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/trigger/controller/EventTriggerController.java index 9c2cc1be..47d4d343 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/EventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/controller/EventTriggerController.java @@ -1,4 +1,4 @@ -package com.zmops.iot.web.trigger; +package com.zmops.iot.web.trigger.controller; import com.alibaba.fastjson.JSON; import com.zmops.iot.model.response.ResponseData; From e46d0553c601e795968cd3526c936e7eb9b1e8e8 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 22 Sep 2021 09:50:08 +0800 Subject: [PATCH 243/763] [fix]: change server-transfer parent pom module --- iot-server/server-transfer/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iot-server/server-transfer/pom.xml b/iot-server/server-transfer/pom.xml index 3f3c684b..26f1b5e4 100644 --- a/iot-server/server-transfer/pom.xml +++ b/iot-server/server-transfer/pom.xml @@ -3,7 +3,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - zeus-iot + iot-server com.zmops 1.0-beta From 8fbfdd392ec8c5c81cee0888f72b91af27edb665 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 22 Sep 2021 10:14:05 +0800 Subject: [PATCH 244/763] [fix]: remove websocket and fix page route --- .../iot/web/alarm/socket/WebSocketConfig.java | 16 -- .../iot/web/alarm/socket/WebSocketServer.java | 179 ------------------ .../web/sys/controller/LoginController.java | 4 +- 3 files changed, 2 insertions(+), 197 deletions(-) delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/alarm/socket/WebSocketConfig.java delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/alarm/socket/WebSocketServer.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/socket/WebSocketConfig.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/socket/WebSocketConfig.java deleted file mode 100644 index e728cb60..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/socket/WebSocketConfig.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.zmops.iot.web.alarm.socket; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.socket.server.standard.ServerEndpointExporter; - -/** - * @author yefei - */ -@Configuration -public class WebSocketConfig { - @Bean - public ServerEndpointExporter serverEndpointExporter() { - return new ServerEndpointExporter(); - } -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/socket/WebSocketServer.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/socket/WebSocketServer.java deleted file mode 100644 index a573b395..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/socket/WebSocketServer.java +++ /dev/null @@ -1,179 +0,0 @@ -package com.zmops.iot.web.alarm.socket; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.util.ToolUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.websocket.*; -import javax.websocket.server.PathParam; -import javax.websocket.server.ServerEndpoint; -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - - -/** - * @author yefei - */ - -@ServerEndpoint("/websocket/alarm/{userid}") -@Component -@Slf4j -public class WebSocketServer { - - /** - * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 - */ - private static int onlineCount = 0; - /** - * concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。 - */ - private static ConcurrentHashMap webSocketMap = new ConcurrentHashMap<>(); - /** - * 与某个客户端的连接会话,需要通过它来给客户端发送数据 - */ - private Session session; - /** - * 接收token - */ - private String token = ""; - /** - * userid - */ - private String userid = ""; - - /** - * 连接建立成功调用的方法 - */ - @OnOpen - public void onOpen(@PathParam("userid") String userid, Session session) { - Map> map = session.getRequestParameterMap(); - this.session = session; - this.userid = userid; - if (webSocketMap.containsKey(userid)) { - webSocketMap.remove(userid); - //加入map中 - webSocketMap.put(userid, this); - } else { - //加入map中 - webSocketMap.put(userid, this); - //在线数加1 - addOnlineCount(); - } - - log.info("用户连接:" + userid + ",当前在线人数为:" + getOnlineCount()); - - try { - sendMessage("连接成功"); - } catch (IOException e) { - log.error("用户:" + userid + ",网络异常!!!!!!"); - } - } - - /** - * 连接关闭调用的方法 - */ - @OnClose - public void onClose() { - if (webSocketMap.containsKey(userid)) { - //从map中删除 - webSocketMap.remove(userid); - subOnlineCount(); - } - log.info("用户退出:" + userid + ",当前在线人数为:" + getOnlineCount()); - } - - /** - * 收到客户端消息后调用的方法 - * - * @param message 客户端发送过来的消息 - */ - @OnMessage - public void onMessage(String message, Session session) { - log.info("用户消息:" + userid + ",报文:" + message); - //消息保存到数据库、redis - if (ToolUtil.isNotEmpty(message)) { - try { - //解析发送的报文 - JSONObject jsonObject = JSON.parseObject(message); - //追加发送人(防止串改) - jsonObject.put("fromUserId", this.token); - String toUserId = jsonObject.getString("toUserId"); - //传送给对应toUserId用户的websocket - if (ToolUtil.isNotEmpty(toUserId) && webSocketMap.containsKey(toUserId)) { - webSocketMap.get(toUserId).sendMessage(jsonObject.toJSONString()); - } else { - log.error("请求的userId:" + toUserId + "不在该服务器上"); - //否则不在这个服务器上,发送到mysql或者redis - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - /** - * @param session - * @param error - */ - @OnError - public void onError(Session session, Throwable error) { - log.error("用户错误:" + this.userid + ",原因:" + error.getMessage()); - error.printStackTrace(); - } - - /** - * 实现服务器主动推送 - */ - public void sendMessage(String message) throws IOException { - this.session.getBasicRemote().sendText(message); - } - - /** - * 实现服务器主动推送给固定人 - */ - public static void sendMessageTo(String message, String to) { - try { - if (webSocketMap != null && webSocketMap.get(to) != null) { - webSocketMap.get(to).session.getBasicRemote().sendText(message); - } - } catch (Exception ex) { - ex.printStackTrace(); - } - // this.session.getBasicRemote().sendText(message); - } - - - /** - * 群发消息 - * - * @param message - */ - public static void sendMessageToAll(String message) { - if (webSocketMap != null) { - webSocketMap.values().forEach(e -> { - try { - e.sendMessage(message); - } catch (IOException ex) { - ex.printStackTrace(); - } - }); - } - } - - - public static synchronized int getOnlineCount() { - return onlineCount; - } - - public static synchronized void addOnlineCount() { - WebSocketServer.onlineCount++; - } - - public static synchronized void subOnlineCount() { - WebSocketServer.onlineCount--; - } -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java index 92da99ed..9b683b22 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java @@ -49,10 +49,10 @@ public String index(Model model) { //用户信息为空,提示账号没分配角色登录不进去 if (userIndexInfo == null) { model.addAttribute("tips", "该用户没有角色,无法登陆"); - return "/login.html"; + return "/login"; } else { model.addAllAttributes(userIndexInfo); - return "/index.html"; + return "/index"; } } else { From ebffcb6f69220edf5493b600513df9a60bbe820c Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 22 Sep 2021 10:14:29 +0800 Subject: [PATCH 245/763] [feat]: update zeus-iot-ui submodule --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index 10c88971..16d1a1bc 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit 10c88971e6bb36808f4ea2b11f2386697da03d00 +Subproject commit 16d1a1bcff8863aea21457111a6ec1ddd0d23c5f From 57209e901cc63b9319db8a994cea3f94f53bee8a Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 22 Sep 2021 10:16:43 +0800 Subject: [PATCH 246/763] [style]: change code style --- .../iot/web/alarm/service/MessageService.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java index 4092656c..170abf65 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java @@ -11,7 +11,6 @@ import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.alarm.dto.param.MessageParam; -import com.zmops.iot.web.alarm.socket.WebSocketServer; import io.ebean.DB; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @@ -65,10 +64,10 @@ public void push(MessageBody body) { if (!CollectionUtils.isEmpty(body.getTo())) { body.getTo().forEach(to -> { - WebSocketServer.sendMessageTo(JSON.toJSONString(body), to + ""); + //WebSocketServer.sendMessageTo(JSON.toJSONString(body), to + ""); }); } else { - WebSocketServer.sendMessageToAll(JSON.toJSONString(body)); + //WebSocketServer.sendMessageToAll(JSON.toJSONString(body)); } } @@ -119,10 +118,13 @@ public List read(MessageParam messageParam) { * @return */ public Map unReadNum() { - LoginUser user = LoginContextHolder.getContext().getUser(); - Map map = new HashMap<>(); - int count = new QMessages().readed.eq(0).userId.eq(user.getId()).findCount(); + LoginUser user = LoginContextHolder.getContext().getUser(); + + Map map = new HashMap<>(); + + int count = new QMessages().readed.eq(0).userId.eq(user.getId()).findCount(); map.put("count", count); + return map; } From 724ab20806c15a338e41797948d733aa3a3f4506 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 22 Sep 2021 10:42:19 +0800 Subject: [PATCH 247/763] [style]: change code style --- .../iot/web/device/service/DeviceService.java | 15 +++++++----- .../controller/ProductEventController.java | 23 ------------------- .../service/ProductAttributeEventService.java | 1 + 3 files changed, 10 insertions(+), 29 deletions(-) delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index f33f6aed..704c22a6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -338,7 +338,7 @@ public String delete(DeviceDto deviceDto) { new QDevice().deviceId.eq(deviceId).delete(); return true; }).param(deviceDto.getDeviceId()) - .nextOf(delTagWork, delAttrWork, delGropusWork, delZbxWork,delOtherWork).build(); + .nextOf(delTagWork, delAttrWork, delGropusWork, delZbxWork, delOtherWork).build(); try { @@ -361,21 +361,24 @@ public void deviceTagCreate(ProductTag productTag, String zbxId) { if (ToolUtil.isEmpty(productTag.getProductTag())) { return; } + new QTag().sid.eq(productTag.getProductId()).delete(); List tags = new ArrayList<>(); + for (ProductTag.Tag tag : productTag.getProductTag()) { - tags.add( - Tag.builder().sid(productTag.getProductId()) - .tag(tag.getTag()).value(tag.getValue()) - .build()); + tags.add(Tag.builder().sid(productTag.getProductId()).tag(tag.getTag()).value(tag.getValue()).build()); } + DB.saveAll(tags); if (ToolUtil.isEmpty(zbxId)) { return; } - List list = new QTag().sid.eq(productTag.getProductId()).findList(); + + List list = new QTag().sid.eq(productTag.getProductId()).findList(); + Map tagMap = new HashMap<>(list.size()); + for (Tag tag : list) { tagMap.put(tag.getTag(), tag.getValue()); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java deleted file mode 100644 index c3180dc6..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventController.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.zmops.iot.web.product.controller; - -import com.zmops.iot.model.response.ResponseData; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author nantian created at 2021/8/7 11:58 - *

- * 产品物模型: 事件 - */ -@RestController -@RequestMapping("/product/event") -public class ProductEventController { - - - @RequestMapping("/create") - public ResponseData createEventTrigger() { - return ResponseData.success(); - } - - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java index 82b4e852..bb74a177 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -149,6 +149,7 @@ public void createProductAttr(ProductAttrEvent productAttr, String zbxId) { WorkerWrapper saveProdAttrEventTriggerWork = WorkerWrapper.builder() .worker(saveProdAttrEventTriggerWorker).param(productAttr).build(); + WorkerWrapper asyncAttrEventZbxIdWork = WorkerWrapper.builder() .worker(asyncAttrEventZbxIdWorker).param(productAttr).build(); WorkerWrapper saveProdAttrEventWork = WorkerWrapper.builder() From 5317a9f8a0d1b50a4a289fb61423ebc113ae719b Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 22 Sep 2021 11:01:13 +0800 Subject: [PATCH 248/763] [fix]: edit webapp release setting file --- zeus-starter/src/main/assembly/webapp.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/zeus-starter/src/main/assembly/webapp.yml b/zeus-starter/src/main/assembly/webapp.yml index 15d985f3..8ec3cbf4 100644 --- a/zeus-starter/src/main/assembly/webapp.yml +++ b/zeus-starter/src/main/assembly/webapp.yml @@ -33,6 +33,12 @@ spring: jackson: generator: write_numbers_as_strings: true + mvc: + view: + prefix: /public + freemarker: + suffix: .html + template-loader-path: classpath:/public/ forest: log-enabled: false From ace34fa0050bf5943faec99506a5bac98746aa58 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 22 Sep 2021 11:09:01 +0800 Subject: [PATCH 249/763] [feat]: update zeus-iot-ui submodule --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index 16d1a1bc..91e27b39 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit 16d1a1bcff8863aea21457111a6ec1ddd0d23c5f +Subproject commit 91e27b391abd598e15a4ddad68db700f33760943 From 67046f57eb1020eac790e13d0b498b6b692ded3c Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 22 Sep 2021 12:00:37 +0800 Subject: [PATCH 250/763] [fix]: product event trigger update --- .../iot/domain/product/ProductEvent.java | 4 +- .../domain/product/ProductEventRelation.java | 3 +- .../com/zmops/iot/enums/InheritStatus.java | 52 +++++++ .../zmops/zeus/driver/service/ZbxTrigger.java | 13 +- .../api-json/trigger/trigger.delete.ftl | 9 ++ .../DeviceEventTriggerController.java | 114 ++++++++++++++- .../iot/web/device/dto/DeviceEventRule.java | 133 ++++++++++++++++++ .../service/DeviceEventRuleService.java | 66 +++++++-- .../web/exception/enums/BizExceptionEnum.java | 2 + .../ProductEventTriggerController.java | 15 ++ .../iot/web/product/dto/ProductEventRule.java | 1 + .../service/ProductEventRuleService.java | 56 ++++---- 12 files changed, 419 insertions(+), 49 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/enums/InheritStatus.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java index e4de3ba5..b6a2ddd5 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java @@ -24,7 +24,7 @@ public class ProductEvent extends BaseEntity { private String eventRuleName; private String eventLevel; private String expLogic; - private String remark; + private String eventNotify; - private String status; + } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java index a21351cf..ada9ba2a 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java @@ -26,5 +26,6 @@ public class ProductEventRelation { private Integer zbxId; private String inherit; - + private String status; + private String remark; } diff --git a/zeus-common/src/main/java/com/zmops/iot/enums/InheritStatus.java b/zeus-common/src/main/java/com/zmops/iot/enums/InheritStatus.java new file mode 100644 index 00000000..e8029f42 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/enums/InheritStatus.java @@ -0,0 +1,52 @@ +/** + * Copyright 2018-2020 stylefeng & fengshuonan (https://gitee.com/stylefeng) + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.zmops.iot.enums; + +import lombok.Getter; + +/** + * 是否来自产品 状态 + * + * @author yefei + */ +public enum InheritStatus { + + NO("0", "否"), + YES("1", "是"); + + @Getter + String code; + @Getter + String message; + + InheritStatus(String code, String message) { + this.code = code; + this.message = message; + } + + public static String getDescription(String status) { + if (status == null) { + return ""; + } else { + for (InheritStatus s : InheritStatus.values()) { + if (s.getCode().equals(status)) { + return s.getMessage(); + } + } + return ""; + } + } +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java index 85e0254f..98f03cda 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java @@ -7,7 +7,6 @@ import com.zmops.zeus.driver.annotation.ParamName; import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; -import java.util.List; import java.util.Map; @BaseRequest( @@ -97,6 +96,16 @@ String triggerTagCreate(@ParamName("triggerId") Integer triggerId, */ @Post @JsonPath("/trigger/trigger.status.update") - String triggerStatusUpdate(@ParamName("triggerid") String triggerId, + String triggerStatusUpdate(@ParamName("triggerid") Integer triggerId, @ParamName("status") String status); + + /** + * 修改触发器状态 + * + * @param triggerId + * @return + */ + @Post + @JsonPath("/trigger/trigger.delete") + String triggerDelete(@ParamName("triggerid") Integer triggerId); } diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.delete.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.delete.ftl index e69de29b..083b1843 100644 --- a/zeus-driver/src/main/resources/api-json/trigger/trigger.delete.ftl +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.delete.ftl @@ -0,0 +1,9 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.get", + "params": [ + ${triggerid} + ], + "id": 1, + "auth": "${userAuth}" +} \ No newline at end of file diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index 65c71756..6169c795 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -3,23 +3,27 @@ import cn.hutool.core.util.IdUtil; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.ProductEventRelation; import com.zmops.iot.domain.product.query.QProductEvent; +import com.zmops.iot.domain.product.query.QProductEventExpression; import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.enums.InheritStatus; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.DeviceEventRule; import com.zmops.iot.web.device.service.DeviceEventRuleService; import com.zmops.iot.web.exception.enums.BizExceptionEnum; -import com.zmops.iot.web.product.dto.ProductEventRule; import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; import io.ebean.annotation.Transactional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -56,6 +60,72 @@ public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId, @Reque return ResponseData.success(deviceEventRuleService.detail(productEvent, eventRuleId, deviceId)); } + /** + * 创建 触发器 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ + @Transactional + @PostMapping("/create") + public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Create.class) + DeviceEventRule eventRule) { + + Long eventRuleId = IdUtil.getSnowflake().nextId(); // ruleId, trigger name + + deviceEventRuleService.createDeviceEventRule(eventRuleId, eventRule); + + //step 1: 先创建 zbx 触发器 + String expression = eventRule.getExpList() + .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); + + //step 2: zbx 保存触发器 + Integer[] triggerIds = deviceEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); + + //step 4: zbx 触发器创建 Tag + Map tags = eventRule.getTags().stream() + .collect(Collectors.toMap(DeviceEventRule.Tag::getTag, DeviceEventRule.Tag::getValue, (k1, k2) -> k2)); + if (ToolUtil.isEmpty(tags)) { + tags = new HashMap<>(2); + } + if (!tags.containsKey(ALARM_TAG_NAME)) { + tags.put(ALARM_TAG_NAME, eventRuleId + ""); + } + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { + tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); + } + for (Integer triggerId : triggerIds) { + zbxTrigger.triggerTagCreate(triggerId, tags); + } + + //step 5: 更新 zbxId + deviceEventRuleService.updateProductEventRuleZbxId(eventRuleId, triggerIds); + + // 返回触发器ID + return ResponseData.success(eventRuleId); + } + + /** + * 修改 触发器状态 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ + @PostMapping("/status") + public ResponseData updateProductEventStatus(@RequestBody @Validated(value = BaseEntity.Status.class) DeviceEventRule eventRule) { + DB.update(ProductEvent.class).where().eq("eventRuleId", eventRule.getEventRuleId()).eq("relationId", eventRule.getDeviceId()).asUpdate() + .set("status", eventRule.getStatus()).update(); + + ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()) + .relationId.eq(eventRule.getDeviceId()).findOne(); + + if (null != productEventRelation && null != productEventRelation.getZbxId()) { + zbxTrigger.triggerStatusUpdate(productEventRelation.getZbxId(), eventRule.getStatus().equals(CommonStatus.ENABLE.getCode()) ? "0" : "1"); + } + + return ResponseData.success(); + } + /** * 修改 触发器 * @@ -64,7 +134,7 @@ public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId, @Reque */ @Transactional @PostMapping("/update") - public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) ProductEventRule eventRule) { + public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) DeviceEventRule eventRule) { //step 1: 删除原有的 关联关系 deviceEventRuleService.updateDeviceEventRule(eventRule.getEventRuleId(), eventRule); @@ -78,7 +148,7 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn //step 4: zbx 触发器创建 Tag Map tags = eventRule.getTags().stream() - .collect(Collectors.toMap(ProductEventRule.Tag::getTag, ProductEventRule.Tag::getValue, (k1, k2) -> k2)); + .collect(Collectors.toMap(DeviceEventRule.Tag::getTag, DeviceEventRule.Tag::getValue, (k1, k2) -> k2)); if (ToolUtil.isEmpty(tags)) { tags = new HashMap<>(2); } @@ -99,4 +169,40 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn return ResponseData.success(eventRule.getEventRuleId()); } + + /** + * 删除 触发器 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ + @Transactional + @PostMapping("/delete") + public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseEntity.Delete.class) + DeviceEventRule eventRule) { + ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(eventRule.getDeviceId()) + .eventRuleId.eq(eventRule.getEventRuleId()).findOne(); + + if (InheritStatus.YES.getCode().equals(productEventRelation.getInherit())) { + throw new ServiceException(BizExceptionEnum.EVENT_PRODUCT_CANNOT_DELETE); + } + + //step 1:删除 与设备的关联 + new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 2:删除 关联的执行服务 + new QProductEventService().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 3:删除 关联的表达式 + new QProductEventExpression().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 4:删除 触发器 + new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 5:删除 zbx触发器 + zbxTrigger.triggerDelete(productEventRelation.getZbxId()); + + return ResponseData.success(); + } + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java new file mode 100644 index 00000000..93c61e78 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java @@ -0,0 +1,133 @@ +package com.zmops.iot.web.device.dto; + +import com.zmops.iot.domain.BaseEntity; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang.StringUtils; + +import javax.validation.Valid; +import javax.validation.constraints.Max; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author nantian created at 2021/9/14 14:47 + *

+ * 告警规则 + */ + +@Getter +@Setter +public class DeviceEventRule { + + @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Delete.class, BaseEntity.Status.class}) + private Long eventRuleId; + + @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private Byte eventNotify; // 0 否 1 是,默认 1 + + // 告警规则名称 + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String eventRuleName; + + // 告警规则级别 + @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private Byte eventLevel; + + // 表达式列表 + @Valid + @NotEmpty(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private List expList; + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String expLogic; // and or + + private String remark; + + private List deviceServices; + + private List tags; + + @NotNull(groups = BaseEntity.Update.class) + private Integer zbxId; + + @NotBlank(groups = BaseEntity.Status.class) + private String deviceId; + + @NotBlank(groups = {BaseEntity.Status.class, BaseEntity.Delete.class}) + private String status; + + @Data + public static class Tag { + + @Max(20) + private String tag; + + @Max(50) + private String value; + } + + @Getter + @Setter + // 告警表达式 构成 + public static class Expression { + + @NotNull(groups = BaseEntity.Update.class) + private Long eventExpId; + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String function; // last avg max min sum change nodata + + private String scope; // s m h T + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String condition; // > < = <> >= <= + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String value; + + @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String productAttrKey; // 产品属性 Key + + private String deviceId; // 设备ID + + private String unit; + + @Override + public String toString() { + StringBuilder expression = new StringBuilder(); + expression.append(function); + expression.append("(/"); + expression.append(deviceId); + expression.append("/"); + expression.append(productAttrKey); + + if (StringUtils.isNotBlank(scope)) { + expression.append(", "); + expression.append(scope); + } + expression.append(") ").append(condition).append(" ").append(value); + return expression.toString(); + } + } + + + @Setter + @Getter + public static class DeviceService { + + private String deviceId; + + private String executeDeviceId; + + private Long serviceId; + } + +} + + + + diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 112e8888..64995967 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -6,15 +6,14 @@ import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.ProductEventExpression; import com.zmops.iot.domain.product.ProductEventRelation; -import com.zmops.iot.domain.product.query.QProductEvent; import com.zmops.iot.domain.product.query.QProductEventExpression; import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventService; import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.DeviceEventRule; import com.zmops.iot.web.exception.enums.BizExceptionEnum; -import com.zmops.iot.web.product.dto.ProductEventRule; import com.zmops.iot.web.product.dto.ProductEventRuleDto; import com.zmops.zeus.driver.service.ZbxTrigger; import io.ebean.DB; @@ -38,7 +37,58 @@ public class DeviceEventRuleService { private ZbxTrigger zbxTrigger; - public void updateDeviceEventRule(Long eventRuleId, ProductEventRule eventRule) { + /** + * 保存触发器 + * + * @param eventRuleId 触发器ID + * @param eventRule 告警规则 + */ + public void createDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { + // step 1: 保存产品告警规则 + ProductEvent event = initEventRule(eventRule); + event.setEventRuleId(eventRuleId); + DB.save(event); + + //step 2: 保存 表达式,方便回显 + List expList = new ArrayList<>(); + + eventRule.getExpList().forEach(i -> { + ProductEventExpression exp = initEventExpression(i); + exp.setEventRuleId(eventRuleId); + expList.add(exp); + }); + + DB.saveAll(expList); + + //step 3: 保存触发器 调用 本产品方法 + if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { + eventRule.getDeviceServices().forEach(i -> { + DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") + .setParameter("eventRuleId", eventRuleId) + .setParameter("executeDeviceId", i.getExecuteDeviceId()) + .setParameter("serviceId", i.getServiceId()) + .execute(); + }); + } + + //step 4: 保存关联关系 + List relationIds = eventRule.getExpList().parallelStream().map(DeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); + if (ToolUtil.isEmpty(relationIds)) { + throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); + } + List productEventRelationList = new ArrayList<>(); + relationIds.forEach(relationId -> { + ProductEventRelation productEventRelation = new ProductEventRelation(); + productEventRelation.setEventRuleId(eventRuleId); + productEventRelation.setRelationId(relationId); + productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); + productEventRelation.setRemark(eventRule.getRemark()); + productEventRelationList.add(productEventRelation); + }); + DB.saveAll(productEventRelationList); + } + + public void updateDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { //step 1: 函数表达式 DB.sqlUpdate("delete from product_event_expression where event_rule_id = :eventRuleId") @@ -74,7 +124,7 @@ public void updateDeviceEventRule(Long eventRuleId, ProductEventRule eventRule) eventRule.getDeviceServices().forEach(i -> { DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id, service_id) values (:eventRuleId, :deviceId, :serviceId)") .setParameter("eventRuleId", eventRuleId) - .setParameter("deviceId", eventRule.getProductId()) + .setParameter("deviceId", eventRule.getDeviceId()) .setParameter("executeDeviceId", i.getExecuteDeviceId()) .setParameter("serviceId", i.getServiceId()) .execute(); @@ -82,7 +132,7 @@ public void updateDeviceEventRule(Long eventRuleId, ProductEventRule eventRule) } // step 6: 保存关联关系 - List relationIds = eventRule.getExpList().parallelStream().map(ProductEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); + List relationIds = eventRule.getExpList().parallelStream().map(DeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); if (ToolUtil.isEmpty(relationIds)) { throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); } @@ -97,18 +147,16 @@ public void updateDeviceEventRule(Long eventRuleId, ProductEventRule eventRule) } - private ProductEvent initEventRule(ProductEventRule eventRule) { + private ProductEvent initEventRule(DeviceEventRule eventRule) { ProductEvent event = new ProductEvent(); event.setEventLevel(eventRule.getEventLevel().toString()); event.setExpLogic(eventRule.getExpLogic()); event.setEventNotify(eventRule.getEventNotify().toString()); - event.setRemark(eventRule.getRemark()); event.setEventRuleName(eventRule.getEventRuleName()); - event.setStatus(CommonStatus.ENABLE.getCode()); return event; } - private ProductEventExpression initEventExpression(ProductEventRule.Expression exp) { + private ProductEventExpression initEventExpression(DeviceEventRule.Expression exp) { ProductEventExpression eventExpression = new ProductEventExpression(); eventExpression.setEventExpId(exp.getEventExpId()); eventExpression.setCondition(exp.getCondition()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index ec52d253..d4927d4e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -165,6 +165,8 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { EVENT_NOT_EXISTS(1704, "告警规则不存在"), EVENT_EXPRESSION_NOT_EXISTS(1705, "告警表达式关联关系不存在"), + EVENT_PRODUCT_CANNOT_DELETE(1706, "来自产品的触发器不能删除"), + /** * 租户相关的异常 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index 3ab8ce5b..74e5a3f1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -8,6 +8,7 @@ import com.zmops.iot.domain.product.query.QProductEventExpression; import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; @@ -179,6 +180,13 @@ public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseE @PostMapping("/status") public ResponseData updateProductEventStatus(@RequestBody @Validated(value = BaseEntity.Status.class) ProductEventRule eventRule) { DB.update(ProductEvent.class).where().eq("eventRuleId", eventRule.getEventRuleId()).asUpdate().set("status", eventRule.getStatus()).update(); + + ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).inherit.eq("0").findOne(); + + if (null != productEventRelation && null != productEventRelation.getZbxId()) { + zbxTrigger.triggerStatusUpdate(productEventRelation.getZbxId(), eventRule.getStatus().equals(CommonStatus.ENABLE.getCode()) ? "0" : "1"); + } + return ResponseData.success(); } @@ -192,6 +200,10 @@ public ResponseData updateProductEventStatus(@RequestBody @Validated(value = Bas @PostMapping("/delete") public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseEntity.Delete.class) ProductEventRule eventRule) { + ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).inherit.eq("0").findOne(); + if (null == productEventRelation) { + return ResponseData.success(); + } //step 1:删除 与产品 设备的关联 new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); @@ -204,6 +216,9 @@ public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseE //step 4:删除 触发器 new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + //step 5:删除 zbx触发器 + + zbxTrigger.triggerDelete(productEventRelation.getZbxId()); return ResponseData.success(); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java index d8cd5a1a..5879f18f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java @@ -54,6 +54,7 @@ public class ProductEventRule { @NotNull(groups = BaseEntity.Update.class) private Integer zbxId; + @NotBlank(groups = BaseEntity.Create.class) private String productId; // 产品ID @NotBlank(groups = BaseEntity.Status.class) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index 73401261..f82d4f8e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -11,10 +11,8 @@ import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventService; import com.zmops.iot.enums.CommonStatus; -import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductEventDto; import com.zmops.iot.web.product.dto.ProductEventRule; import com.zmops.iot.web.product.dto.ProductEventRuleDto; @@ -26,7 +24,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; /** @@ -65,38 +66,24 @@ public void createProductEventRule(Long eventRuleId, ProductEventRule eventRule) DB.saveAll(expList); - List relationIds = new ArrayList<>(); - if (ToolUtil.isNotEmpty(eventRule.getProductId())) { - relationIds.add(eventRule.getProductId()); - } else { - relationIds = eventRule.getExpList().parallelStream().map(ProductEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); - if (ToolUtil.isEmpty(relationIds)) { - throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); - } - } //step 3: 保存触发器 调用 本产品方法 if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { - relationIds.forEach(relationId -> { - eventRule.getDeviceServices().forEach(i -> { - DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") - .setParameter("eventRuleId", eventRuleId) - .setParameter("deviceId", relationId) - .setParameter("executeDeviceId", i.getExecuteDeviceId()) - .setParameter("serviceId", i.getServiceId()) - .execute(); - }); + eventRule.getDeviceServices().forEach(i -> { + DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") + .setParameter("eventRuleId", eventRuleId) + .setParameter("executeDeviceId", i.getExecuteDeviceId()) + .setParameter("serviceId", i.getServiceId()) + .execute(); }); } //step 4: 保存关联关系 - List productEventRelationList = new ArrayList<>(); - relationIds.forEach(relationId -> { - ProductEventRelation productEventRelation = new ProductEventRelation(); - productEventRelation.setEventRuleId(eventRuleId); - productEventRelation.setRelationId(relationId); - productEventRelationList.add(productEventRelation); - }); - DB.saveAll(productEventRelationList); + ProductEventRelation productEventRelation = new ProductEventRelation(); + productEventRelation.setEventRuleId(eventRuleId); + productEventRelation.setRelationId(eventRule.getProductId()); + productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); + productEventRelation.setRemark(eventRule.getRemark()); + DB.save(productEventRelation); } /** @@ -144,6 +131,13 @@ public void updateProductEventRule(Long eventRuleId, ProductEventRule eventRule) .execute(); }); } + + //step 6:保存备注 + if (null != eventRule.getRemark()) { + DB.update(QProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).eq("relationId", eventRule.getProductId()) + .asUpdate().set("remark", eventRule.getRemark()).update(); + } + } @@ -152,9 +146,9 @@ private ProductEvent initEventRule(ProductEventRule eventRule) { event.setEventLevel(eventRule.getEventLevel().toString()); event.setExpLogic(eventRule.getExpLogic()); event.setEventNotify(eventRule.getEventNotify().toString()); - event.setRemark(eventRule.getRemark()); + event.setEventRuleName(eventRule.getEventRuleName()); - event.setStatus(CommonStatus.ENABLE.getCode()); + return event; } From 6031b701fdff538864812f5308fbd7993ac82b82 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 22 Sep 2021 12:14:37 +0800 Subject: [PATCH 251/763] [fix]: product event trigger update --- .../iot/web/device/service/DeviceEventRuleService.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 64995967..a85a9ee8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -204,8 +204,12 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S if (null != productEventRelation) { JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); - productEventRuleDto.setTags(JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class)); + List tagList = JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class); + productEventRuleDto.setZbxId(productEventRelation.getZbxId()); + productEventRuleDto.setTags(tagList.stream() + .filter(s -> s.getTag().equals("__execute__") || s.getTag().equals("__alarm__")) + .collect(Collectors.toList())); } return productEventRuleDto; From a5cd86832a28f1aa6a303fa8ec8b392273e4f7fc Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 22 Sep 2021 13:41:33 +0800 Subject: [PATCH 252/763] [feat]: add server-transfer module --- iot-server/server-transfer/pom.xml | 19 + .../zeus/iot/server/transfer/api/Channel.java | 54 +++ .../zeus/iot/server/transfer/api/Filter.java | 30 ++ .../zeus/iot/server/transfer/api/Message.java | 42 ++ .../zeus/iot/server/transfer/api/Reader.java | 51 +++ .../zeus/iot/server/transfer/api/Sink.java | 38 ++ .../zeus/iot/server/transfer/api/Source.java | 36 ++ .../zeus/iot/server/transfer/api/Stage.java | 38 ++ .../zeus/iot/server/transfer/api/Trigger.java | 61 +++ .../iot/server/transfer/api/Validator.java | 32 ++ .../transfer/conf/AbstractConfiguration.java | 263 +++++++++++++ .../transfer/conf/AgentConfiguration.java | 121 ++++++ .../server/transfer/conf/AgentConstants.java | 162 ++++++++ .../server/transfer/conf/CommonConstants.java | 140 +++++++ .../server/transfer/conf/JobConstants.java | 88 +++++ .../iot/server/transfer/conf/JobProfile.java | 85 +++++ .../server/transfer/conf/TriggerProfile.java | 53 +++ .../transfer/exception/FileException.java | 25 ++ .../transfer/filter/DateFormatRegex.java | 138 +++++++ .../transfer/message/DefaultMessage.java | 54 +++ .../iot/server/transfer/sink/ConsoleSink.java | 53 +++ .../transfer/source/TextFileSource.java | 73 ++++ .../source/reader/TextFileReader.java | 165 ++++++++ .../server/transfer/trigger/PathPattern.java | 195 ++++++++++ .../iot/server/transfer/utils/AgentUtils.java | 358 ++++++++++++++++++ .../iot/server/transfer/utils/ByteUtil.java | 235 ++++++++++++ .../server/transfer/utils/PluginUtils.java | 135 +++++++ .../transfer/validator/PatternValidator.java | 35 ++ .../transfer/validator/PrefixValidator.java | 34 ++ 29 files changed, 2813 insertions(+) create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Channel.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Filter.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Message.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Reader.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Sink.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Source.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Stage.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Trigger.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Validator.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AgentConfiguration.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AgentConstants.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobProfile.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TriggerProfile.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/exception/FileException.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/filter/DateFormatRegex.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/message/DefaultMessage.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sink/ConsoleSink.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/source/TextFileSource.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/source/reader/TextFileReader.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/trigger/PathPattern.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/AgentUtils.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/ByteUtil.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/PluginUtils.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/validator/PatternValidator.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/validator/PrefixValidator.java diff --git a/iot-server/server-transfer/pom.xml b/iot-server/server-transfer/pom.xml index 26f1b5e4..c34f782b 100644 --- a/iot-server/server-transfer/pom.xml +++ b/iot-server/server-transfer/pom.xml @@ -8,6 +8,7 @@ 1.0-beta 4.0.0 + 读取 Zabbix 历史数据文件 server-transfer @@ -16,4 +17,22 @@ 8 + + + org.apache.commons + commons-lang3 + 3.12.0 + + + commons-codec + commons-codec + 1.15 + + + org.apache.commons + commons-io + 1.3.2 + + + \ No newline at end of file diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Channel.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Channel.java new file mode 100644 index 00000000..86c74982 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Channel.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.api; + +import java.util.concurrent.TimeUnit; + +/** + * Channel is used as data buffer between source and sink. + */ +public interface Channel extends Stage { + + + /** + * write message + * + * @param message - message + */ + void push(Message message); + + /** + * write message with timeout + * + * @param message + * @param timeout + * @param unit + * @return + */ + boolean push(Message message, long timeout, TimeUnit unit); + + /** + * read message with timeout + * + * @param timeout + * @param unit + * @return + */ + Message pull(long timeout, TimeUnit unit); + +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Filter.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Filter.java new file mode 100644 index 00000000..2a90b3e5 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Filter.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.api; + +/** + * filter for source split + */ +public interface Filter { + + /** + * whether reader is legal. + * @return true if reader is legal else false. + */ + boolean match(); +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Message.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Message.java new file mode 100644 index 00000000..ef5a170d --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Message.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.api; + +import java.util.Map; + +/** + * Message used in inner-data transfer, message is divided into + * two parts, header and body. header is the attributes of message + * and body is the content of message. + */ +public interface Message { + + /** + * Data content of message. + * + * @return bytes body + */ + byte[] getBody(); + + /** + * Data attribute of message + * + * @return map header + */ + Map getHeader(); +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Reader.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Reader.java new file mode 100644 index 00000000..c82bf54b --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Reader.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.api; + +/** + * Reader reads data and provides condition whether the reading action is finished. It's called at + * Task level. + */ +public interface Reader extends Stage { + + /** + * Read message + * + * @return - message + */ + Message read(); + + /** + * Whether finish reading + * + * @return + */ + boolean isFinished(); + + /** + * Return the reader's reading file name + * + * @return + */ + String getReadFile(); + + /** + * set readTimeout + */ + void setReadTimeout(long mill); +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Sink.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Sink.java new file mode 100644 index 00000000..6b55a0c8 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Sink.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.api; + +/** + * Sink data to remote data center + */ +public interface Sink extends Stage { + + /** + * Write data into data center + * + * @param message - message + */ + void write(Message message); + + + /** + * set source file name where the message is generated + * @param sourceFileName + */ + void setSourceFile(String sourceFileName); +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Source.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Source.java new file mode 100644 index 00000000..1209cc75 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Source.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.api; + +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; + +import java.util.List; + +/** + * Source can be split into multiple reader. + */ +public interface Source { + + /** + * Split source into a list of readers. + * + * @param conf job conf + * @return - list of reader + */ + List split(JobProfile conf); +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Stage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Stage.java new file mode 100644 index 00000000..cc4fdda3 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Stage.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.api; + +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; + +/** + * Stage definition. + */ +public interface Stage { + + /** + * Init job. + * + * @param jobConf - job config + */ + void init(JobProfile jobConf); + + /** + * Destroy job. + */ + void destroy(); +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Trigger.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Trigger.java new file mode 100644 index 00000000..ef4ebd9c --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Trigger.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.api; + +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; + +import java.io.IOException; + +/** + * Trigger interface, which generates job in condition. + */ +public interface Trigger { + + /** + * init trigger by trigger profile + * + * @param profile + * @throws IOException + */ + void init(TriggerProfile profile) throws IOException; + + /** + * run trigger. + */ + void run(); + + /** + * destroy trigger. + */ + void destroy(); + + /** + * fetch job profile from trigger + * + * @return - job profile + */ + JobProfile fetchJobProfile(); + + /** + * get trigger profile + * + * @return + */ + TriggerProfile getTriggerProfile(); +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Validator.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Validator.java new file mode 100644 index 00000000..8ed0c295 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Validator.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.api; + +/** + * For every message, there might be validators to filter required ones + */ +public interface Validator { + + /** + * + * @param messageLine + * @return + */ + boolean validate(String messageLine); + +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java new file mode 100644 index 00000000..e7e35fc8 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java @@ -0,0 +1,263 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.conf; + +import com.google.gson.*; +import com.zmops.zeus.iot.server.transfer.utils.AgentUtils; +import org.apache.commons.lang3.StringUtils; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.util.*; + +public abstract class AbstractConfiguration { + + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractConfiguration.class); + private static final JsonParser JSON_PARSER = new JsonParser(); + + private final Map configStorage = new HashMap<>(); + + /** get config file by class loader **/ + private ClassLoader classLoader; + + public AbstractConfiguration() { + classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = AgentConfiguration.class.getClassLoader(); + } + } + + /** + * Check whether all required keys exist + * @return true if all key exist else false. + */ + public abstract boolean allRequiredKeyExist(); + + /** + * support load config file from json/properties file. + * + * @param fileName - file name + * @param isJson - whether is json file + */ + private void loadResource(String fileName, boolean isJson) { + Reader reader = null; + try { + InputStream inputStream = classLoader.getResourceAsStream(fileName); + if (inputStream != null) { + reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); + if (isJson) { + JsonElement tmpElement = JSON_PARSER.parse(reader).getAsJsonObject(); + updateConfig(new HashMap<>(10), 0, tmpElement); + } else { + Properties properties = new Properties(); + properties.load(reader); + properties.forEach((key, value) -> configStorage.put((String) key, + new JsonPrimitive((String) value))); + } + } + } catch (Exception ioe) { + LOGGER.error("error init {}", fileName, ioe); + } finally { + AgentUtils.finallyClose(reader); + } + } + + /** + * load config from json string. + * + * @param jsonStr - json string + */ + public void loadJsonStrResource(String jsonStr) { + JsonElement tmpElement = JSON_PARSER.parse(jsonStr); + updateConfig(new HashMap<>(10), 0, tmpElement); + } + + /** + * load config file from CLASS_PATH. config file is json file. + * + * @param fileName - file name + */ + void loadJsonResource(String fileName) { + loadResource(fileName, true); + } + + void loadPropertiesResource(String fileName) { + loadResource(fileName, false); + } + + /** + * Convert json string to map + * + * @param keyDeptPath - map + * @param dept - json dept + * @param tmpElement - json element + */ + void updateConfig(HashMap keyDeptPath, int dept, JsonElement tmpElement) { + if (tmpElement instanceof JsonObject) { + JsonObject tmpJsonObject = tmpElement.getAsJsonObject(); + for (String key : tmpJsonObject.keySet()) { + keyDeptPath.put(dept, key); + updateConfig(keyDeptPath, dept + 1, tmpJsonObject.get(key)); + } + } else if (tmpElement instanceof JsonArray) { + JsonArray tmpJsonArray = tmpElement.getAsJsonArray(); + String lastKey = keyDeptPath.getOrDefault(dept - 1, ""); + for (int index = 0; index < tmpJsonArray.size(); index++) { + keyDeptPath.put(dept - 1, lastKey + "[" + index + "]"); + updateConfig(keyDeptPath, dept, tmpJsonArray.get(index)); + } + } else if (tmpElement instanceof JsonPrimitive) { + List builder = new ArrayList<>(); + for (int index = 0; index < dept; index++) { + builder.add(keyDeptPath.getOrDefault(index, "")); + } + String keyChain = StringUtils.join(builder, "."); + if (!StringUtils.isBlank(keyChain)) { + configStorage.put(keyChain, tmpElement.getAsJsonPrimitive()); + } + } + } + + /** + * get int from config + * + * @param key - key + * @param defaultValue - default value + * @return value + */ + public int getInt(String key, int defaultValue) { + JsonElement value = configStorage.get(key); + return value == null ? defaultValue : value.getAsInt(); + } + + /** + * get int from config + * + * @param key - key + * @return value + * @throws NullPointerException npe + */ + public int getInt(String key) { + JsonElement value = configStorage.get(key); + if (value == null) { + throw new NullPointerException("null value for key " + key); + } + return value.getAsInt(); + } + + /** + * get long + * + * @param key - key + * @param defaultValue - default value + * @return long + */ + public long getLong(String key, long defaultValue) { + JsonElement value = configStorage.get(key); + return value == null ? defaultValue : value.getAsLong(); + } + + /** + * get boolean + * + * @param key - key + * @param defaultValue - default value + * @return boolean + */ + public boolean getBoolean(String key, boolean defaultValue) { + JsonElement value = configStorage.get(key); + return value == null ? defaultValue : value.getAsBoolean(); + } + + /** + * get string + * + * @param key - key + * @param defaultValue - default value + * @return string + */ + public String get(String key, String defaultValue) { + JsonElement value = configStorage.get(key); + return value == null ? defaultValue : value.getAsString(); + } + + /** + * get string or throw npe + * + * @param key - key + * @return string + * @throws NullPointerException if value is null, throw npe + */ + public String get(String key) { + JsonElement value = configStorage.get(key); + if (value == null) { + throw new NullPointerException("null value for key " + key); + } + return value.getAsString(); + } + + /** + * whether key exists + * + * @param key - key + * @return - true if key exists else not + */ + public boolean hasKey(String key) { + return configStorage.containsKey(key); + } + + /** + * set key/value + * + * @param key - key + * @param value - value + */ + public void set(String key, String value) { + configStorage.put(key, new JsonPrimitive(value)); + } + + public void setInt(String key, int value) { + configStorage.put(key, new JsonPrimitive(value)); + } + + public void setLong(String key, long value) { + configStorage.put(key, new JsonPrimitive(value)); + } + + public void setBoolean(String key, boolean value) { + configStorage.put(key, new JsonPrimitive(value)); + } + + Map getConfigStorage() { + return configStorage; + } + + List getStorageList() { + List result = new ArrayList<>(); + for (Map.Entry entry : configStorage.entrySet()) { + result.add(entry.getKey() + "=" + entry.getValue().getAsString()); + } + return result; + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AgentConfiguration.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AgentConfiguration.java new file mode 100644 index 00000000..7b50bb78 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AgentConfiguration.java @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.conf; + +import org.apache.commons.io.FileUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * agent configuration. Only one instance in the process. + * Basically it use properties file to store configurations. + */ +public class AgentConfiguration extends AbstractConfiguration { + + private static final Logger LOGGER = LoggerFactory.getLogger(AgentConfiguration.class); + + private static final String DEFAULT_CONFIG_FILE = "agent.properties"; + private static final String TMP_CONFIG_FILE = ".tmp.agent.properties"; + + private static final ArrayList LOCAL_RESOURCES = new ArrayList<>(); + + private static final ReadWriteLock LOCK = new ReentrantReadWriteLock(); + + static { + LOCAL_RESOURCES.add(DEFAULT_CONFIG_FILE); + } + + private static volatile AgentConfiguration agentConf = null; + + /** + * load config from agent file. + */ + private AgentConfiguration() { + for (String fileName : LOCAL_RESOURCES) { + super.loadPropertiesResource(fileName); + } + } + + /** + * singleton for agent configuration. + * + * @return - static instance of AgentConfiguration + */ + public static AgentConfiguration getAgentConf() { + if (agentConf == null) { + synchronized (AgentConfiguration.class) { + if (agentConf == null) { + agentConf = new AgentConfiguration(); + } + } + } + return agentConf; + } + + private String getNextBackupFileName() { + SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); + String dateStr = format.format(new Date(System.currentTimeMillis())); + return DEFAULT_CONFIG_FILE + "." + dateStr; + } + + /** + * flush config to local files. + */ + public void flushToLocalPropertiesFile() { + LOCK.writeLock().lock(); + // TODO: flush to local file as properties file. + try { + String agentConfParent = get(AgentConstants.AGENT_CONF_PARENT, AgentConstants.DEFAULT_AGENT_CONF_PARENT); + + File sourceFile = new File(agentConfParent, DEFAULT_CONFIG_FILE); + File targetFile = new File(agentConfParent, getNextBackupFileName()); + File tmpFile = new File(agentConfParent, TMP_CONFIG_FILE); + + if (sourceFile.exists()) { + FileUtils.copyFile(sourceFile, targetFile); + } + + List tmpCache = getStorageList(); + FileUtils.writeLines(tmpFile, tmpCache); + + FileUtils.copyFile(tmpFile, sourceFile); + boolean result = tmpFile.delete(); + if (!result) { + LOGGER.warn("cannot delete file {}", tmpFile); + } + } catch (Exception ex) { + LOGGER.error("error while flush agent conf to local", ex); + } finally { + LOCK.writeLock().unlock(); + } + + } + + @Override + public boolean allRequiredKeyExist() { + return true; + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AgentConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AgentConstants.java new file mode 100644 index 00000000..0e7eb65c --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AgentConstants.java @@ -0,0 +1,162 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.conf; + +import com.zmops.zeus.iot.server.transfer.utils.AgentUtils; + +public class AgentConstants { + + public static final String AGENT_HOME = "agent.home"; + public static final String DEFAULT_AGENT_HOME = System.getProperty("agent.home"); + + public static final String AGENT_LOCAL_CACHE = "agent.local.cache"; + public static final String DEFAULT_AGENT_LOCAL_CACHE = ".local"; + + public static final String AGENT_LOCAL_CACHE_TIMEOUT = "agent.local.cache.timeout"; + /** cache timeout in minutes. **/ + public static final int DEFAULT_AGENT_LOCAL_CACHE_TIMEOUT = 30; + + public static final String AGENT_LOCAL_STORE_PATH = "agent.localStore.path"; + public static final String DEFAULT_AGENT_LOCAL_STORE_PATH = ".bdb"; + + public static final String AGENT_ROCKS_DB_PATH = "agent.rocks.db.path"; + public static final String DEFAULT_AGENT_ROCKS_DB_PATH = ".rocksdb"; + + public static final String AGENT_UNIQ_ID = "agent.uniq.id"; + // default use local ip as uniq id for agent. + public static final String DEFAULT_AGENT_UNIQ_ID = AgentUtils.getLocalIp(); + + public static final String AGENT_DB_INSTANCE_NAME = "agent.db.instance.name"; + public static final String DEFAULT_AGENT_DB_INSTANCE_NAME = "agent"; + + public static final String AGENT_DB_CLASSNAME = "agent.db.classname"; + public static final String DEFAULT_AGENT_DB_CLASSNAME = "org.apache.inlong.agent.db.BerkeleyDbImp"; + + // default is empty. + public static final String AGENT_FETCHER_CLASSNAME = "agent.fetcher.classname"; + + public static final String AGENT_CONF_PARENT = "agent.conf.parent"; + public static final String DEFAULT_AGENT_CONF_PARENT = "conf"; + + public static final String AGENT_LOCAL_STORE_READONLY = "agent.localStore.readonly"; + public static final boolean DEFAULT_AGENT_LOCAL_STORE_READONLY = false; + + public static final String AGENT_HTTP_PORT = "agent.http.port"; + public static final int DEFAULT_AGENT_HTTP_PORT = 8008; + + public static final String AGENT_ENABLE_HTTP = "agent.http.enable"; + public static final boolean DEFAULT_AGENT_ENABLE_HTTP = false; + + public static final String TRIGGER_FETCH_INTERVAL = "trigger.fetch.interval"; + public static final int DEFAULT_TRIGGER_FETCH_INTERVAL = 1; + + public static final String TRIGGER_MAX_RUNNING_NUM = "trigger.max.running.num"; + public static final int DEFAULT_TRIGGER_MAX_RUNNING_NUM = 4096; + + public static final String AGENT_LOCAL_STORE_TRANSACTIONAL = "agent.localStore.transactional"; + public static final boolean DEFAULT_AGENT_LOCAL_STORE_TRANSACTIONAL = true; + + public static final String AGENT_LOCAL_STORE_LOCK_TIMEOUT = "agent.localStore.lockTimeout"; + public static final int DEFAULT_AGENT_LOCAL_STORE_LOCK_TIMEOUT = 10000; + + public static final String AGENT_LOCAL_STORE_NO_SYNC_VOID = "agent.localStore.noSyncVoid"; + public static final boolean DEFAULT_AGENT_LOCAL_STORE_NO_SYNC_VOID = false; + + public static final String AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID = + "agent.localStore.WriteNoSyncVoid"; + public static final boolean DEFAULT_AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID = false; + + public static final String AGENT_FETCH_CENTER_INTERVAL_SECONDS = "agent.fetchCenter.interval"; + public static final int DEFAULT_AGENT_FETCH_CENTER_INTERVAL_SECONDS = 5; + + public static final String AGENT_TRIGGER_CHECK_INTERVAL_SECONDS = "agent.trigger.check.interval"; + public static final int DEFAULT_AGENT_TRIGGER_CHECK_INTERVAL_SECONDS = 1; + + public static final String THREAD_POOL_AWAIT_TIME = "thread.pool.await.time"; + // time in ms + public static final long DEFAULT_THREAD_POOL_AWAIT_TIME = 300; + + public static final String JOB_THREAD_PENDING_MAX = "job.thread.pending.max"; + public static final int DEFAULT_JOB_THREAD_PENDING_MAX = 40; + + public static final String JOB_THREAD_RUNNING_CORE = "job.thread.running.core"; + public static final int DEFAULT_JOB_THREAD_RUNNING_CORE = 4; + + + public static final String JOB_MONITOR_INTERVAL = "job.monitor.interval"; + public static final int DEFAULT_JOB_MONITOR_INTERVAL = 5; + + public static final String JOB_THREAD_RUNNING_MAX = "job.thread.running.max"; + public static final int DEFAULT_JOB_THREAD_RUNNING_MAX = 20; + + public static final String JOB_RUNNING_THREAD_KEEP_ALIVE = "job.running.thread.keepAlive"; + public static final long DEFAULT_JOB_RUNNING_THREAD_KEEP_ALIVE = 60L; + + public static final String JOB_FINISH_CHECK_INTERVAL = "job.finish.checkInterval"; + public static final long DEFAULT_JOB_FINISH_CHECK_INTERVAL = 6L; + + public static final String TASK_PENDING_MAX = "task.pending.max"; + public static final int DEFAULT_TASK_PENDING_MAX = 100; + + public static final String TASK_RUNNING_THREAD_CORE_SIZE = "task.running.thread.coreSize"; + public static final int DEFAULT_TASK_RUNNING_THREAD_CORE_SIZE = 4; + + public static final String TASK_RUNNING_THREAD_MAX_SIZE = "task.running.thread.maxSize"; + public static final int DEFAULT_TASK_RUNNING_THREAD_MAX_SIZE = + Runtime.getRuntime().availableProcessors() * 2; + + public static final String TASK_RUNNING_THREAD_KEEP_ALIVE = "task.running.thread.keepAlive"; + public static final long DEFAULT_TASK_RUNNING_THREAD_KEEP_ALIVE = 60L; + + public static final String TASK_RETRY_MAX_CAPACITY = "task.retry.maxCapacity"; + public static final int DEFAULT_TASK_RETRY_MAX_CAPACITY = 10000; + + public static final String TASK_MONITOR_INTERVAL = "task.monitor.interval"; + public static final int DEFAULT_TASK_MONITOR_INTERVAL = 6; + + public static final String TASK_RETRY_SUBMIT_WAIT_SECONDS = "task.retry.submit.waitSeconds"; + public static final int DEFAULT_TASK_RETRY_SUBMIT_WAIT_SECONDS = 5; + + public static final String TASK_MAX_RETRY_TIME = "task.maxRetry.time"; + public static final int DEFAULT_TASK_MAX_RETRY_TIME = 3; + + public static final String TASK_PUSH_MAX_SECOND = "task.push.maxSecond"; + public static final int DEFAULT_TASK_PUSH_MAX_SECOND = 2; + + public static final String TASK_PULL_MAX_SECOND = "task.pull.maxSecond"; + public static final int DEFAULT_TASK_PULL_MAX_SECOND = 2; + + public static final String CHANNEL_MEMORY_CAPACITY = "channel.memory.capacity"; + public static final int DEFAULT_CHANNEL_MEMORY_CAPACITY = 10000; + + public static final String TRIGGER_CHECK_INTERVAL = "trigger.check.interval"; + public static final int DEFAULT_TRIGGER_CHECK_INTERVAL = 2; + + public static final String WORKER_POOL_AWAIT_TIME = "worker.pool.await.time"; + public static final long DEFAULT_WORKER_POOL_AWAIT_TIME = 10; + + public static final String JOB_DB_CACHE_TIME = "job.db.cache.time"; + // cache for 3 days. + public static final long DEFAULT_JOB_DB_CACHE_TIME = 3 * 24 * 60 * 60 * 1000; + + public static final String JOB_DB_CACHE_CHECK_INTERVAL = "job.db.cache.check.interval"; + public static final int DEFAULT_JOB_DB_CACHE_CHECK_INTERVAL = 60 * 60; + + public static final String AGENT_LOCAL_IP = "agent.local.ip"; + +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java new file mode 100644 index 00000000..2facb49d --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java @@ -0,0 +1,140 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.conf; + +import com.zmops.zeus.iot.server.transfer.utils.AgentUtils; + +public class CommonConstants { + + public static final String PROXY_NET_TAG = "proxy.net.tag"; + public static final String DEFAULT_PROXY_NET_TAG = ""; + + public static final String PROXY_BID = "proxy.bid"; + public static final String POSITION_SUFFIX = ".position"; + + public static final String PROXY_TID = "proxy.tid"; + + + public static final String PROXY_LOCAL_HOST = "proxy.localHost"; + public static final String DEFAULT_PROXY_LOCALHOST = AgentUtils.getLocalIp(); + + public static final String PROXY_IS_LOCAL_VISIT = "proxy.isLocalVisit"; + public static final boolean DEFAULT_PROXY_IS_LOCAL_VISIT = true; + + public static final String PROXY_TOTAL_ASYNC_PROXY_SIZE = "proxy.total.async.proxy.size"; + public static final int DEFAULT_PROXY_TOTAL_ASYNC_PROXY_SIZE = 200 * 1024 * 1024; + + public static final String PROXY_ALIVE_CONNECTION_NUM = "proxy.alive.connection.num"; + public static final int DEFAULT_PROXY_ALIVE_CONNECTION_NUM = 10; + + public static final String PROXY_MSG_TYPE = "proxy.msgType"; + public static final int DEFAULT_PROXY_MSG_TYPE = 7; + + public static final String PROXY_IS_COMPRESS = "proxy.is.compress"; + public static final boolean DEFAULT_PROXY_IS_COMPRESS = true; + + public static final String PROXY_MAX_SENDER_PER_BID = "proxy.max.sender.per.pid"; + public static final int DEFAULT_PROXY_MAX_SENDER_PER_PID = 10; + + // max size of message list + public static final String PROXY_PACKAGE_MAX_SIZE = "proxy.package.maxSize"; + // max size of single batch in bytes, default is 200KB. + public static final int DEFAULT_PROXY_PACKAGE_MAX_SIZE = 200000; + + public static final String PROXY_TID_QUEUE_MAX_NUMBER = "proxy.tid.queue.maxNumber"; + public static final int DEFAULT_PROXY_TID_QUEUE_MAX_NUMBER = 10000; + + public static final String PROXY_PACKAGE_MAX_TIMEOUT_MS = "proxy.package.maxTimeout.ms"; + public static final int DEFAULT_PROXY_PACKAGE_MAX_TIMEOUT_MS = 4 * 1000; + + public static final String PROXY_BATCH_FLUSH_INTERVAL = "proxy.batch.flush.interval"; + public static final int DEFAULT_PROXY_BATCH_FLUSH_INTERVAL = 2 * 1000; + + public static final String PROXY_SENDER_MAX_TIMEOUT = "proxy.sender.maxTimeout"; + // max timeout in seconds. + public static final int DEFAULT_PROXY_SENDER_MAX_TIMEOUT = 20; + + public static final String PROXY_SENDER_MAX_RETRY = "proxy.sender.maxRetry"; + public static final int DEFAULT_PROXY_SENDER_MAX_RETRY = 5; + + public static final String PROXY_IS_FILE = "proxy.isFile"; + public static final boolean DEFAULT_IS_FILE = false; + + public static final String PROXY_RETRY_SLEEP = "proxy.retry.sleep"; + public static final long DEFAULT_PROXY_RETRY_SLEEP = 500; + + public static final String PROXY_KEY_BID = "bid"; + public static final String PROXY_KEY_TID = "tid"; + public static final String PROXY_KEY_ID = "id"; + public static final String PROXY_KEY_AGENT_IP = "agentip"; + public static final String PROXY_OCEANUS_F = "f"; + public static final String PROXY_OCEANUS_BL = "bl"; + + // config for pulsar + // pulsar host port like http://host1:port1 + public static final String PULSAR_SERVERS = "pulsar.servers"; + // pulsar topic name + public static final String PULSAR_TOPIC = "pulsar.topic"; + // whether async sending data + public static final String PULSAR_PRODUCER_ASYNC = "pulsar.producer.async"; + public static final boolean DEFAULT_PULSAR_PRODUCER_ASYNC = true; + + public static final String PULSAR_PRODUCER_MAX_PENDING_COUNT = "pulsar.producer.maxPending.count"; + public static final int DEFAULT_PULSAR_PRODUCER_MAX_PENDING_COUNT = 10000; + + public static final String PULSAR_PRODUCER_THREAD_NUM = "pulsar.producer.thread.num"; + public static final int DEFAULT_PULSAR_PRODUCER_THREAD_NUM = 1; + + public static final String PULSAR_PRODUCER_ENABLE_BATCH = "pulsar.producer.enable.batch"; + public static final boolean DEFAULT_PULSAR_PRODUCER_ENABLE_BATCH = true; + + public static final String PULSAR_SINK_POLL_TIMEOUT = "pulsar.sink.poll.timeout"; + // time in ms + public static final long DEFAULT_PULSAR_SINK_POLL_TIMEOUT = 1000; + + public static final String PULSAR_SINK_CACHE_CAPACITY = "pulsar.sink.cache.capacity"; + public static final int DEFAULT_PULSAR_SINK_CACHE_CAPACITY = 100000; + + public static final String PULSAR_PRODUCER_COMPRESS_TYPE = "pulsar.producer.compress.type"; + public static final String DEFAULT_PULSAR_PRODUCER_COMPRESS_TYPE = "snappy"; + + public static final String PULSAR_PRODUCER_BATCH_MAXSIZE = "pulsar.producer.batch.maxsize"; + public static final int DEFAULT_PULSAR_PRODUCER_BATCH_MAXSIZE = 1024 * 1024; + + public static final String PULSAR_PRODUCER_BATCH_MAXCOUNT = "pulsar.producer.batch.maxcount"; + public static final int DEFAULT_PULSAR_PRODUCER_BATCH_MAXCOUNT = 1000; + + public static final String PULSAR_PRODUCER_BLOCK_QUEUE = "pulsar.producer.block.queue"; + public static final boolean DEFAULT_PULSAR_PRODUCER_BLOCK_QUEUE = true; + + + public static final String FILE_MAX_NUM = "file.max.num"; + public static final int DEFAULT_FILE_MAX_NUM = 4096; + + public static final String TRIGGER_ID_PREFIX = "trigger_"; + + + public static final String COMMAND_STORE_INSTANCE_NAME = "commandStore"; + + + public static final String AGENT_OS_NAME = "os.name"; + public static final String AGENT_NIX_OS = "nix"; + public static final String AGENT_NUX_OS = "nux"; + public static final String AGENT_COLON = ":"; + +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java new file mode 100644 index 00000000..1d9ad53a --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.conf; + + +/** + * Basic config for a single job + */ +public class JobConstants extends CommonConstants { + + // job id + public static final String JOB_ID = "job.id"; + public static final String JOB_INSTANCE_ID = "job.instance.id"; + public static final String JOB_IP = "job.ip"; + public static final String JOB_RETRY = "job.retry"; + + + public static final String JOB_SOURCE = "job.source"; + public static final String JOB_SINK = "job.sink"; + public static final String JOB_CHANNEL = "job.channel"; + public static final String JOB_TRIGGER = "job.trigger"; + public static final String JOB_NAME = "job.name"; + public static final String JOB_LINE_FILTER_PATTERN = "job.pattern"; + public static final String DEFAULT_JOB_NAME = "default"; + public static final String JOB_DESCRIPTION = "job.description"; + public static final String DEFAULT_JOB_DESCRIPTION = "default job description"; + public static final String DEFAULT_JOB_LINE_FILTER = ""; + + // job type, delete/add + public static final String JOB_TYPE = "job.type"; + + public static final String JOB_CHECKPOINT = "job.checkpoint"; + + // offset for time + public static final String JOB_FILE_TIME_OFFSET = "job.timeOffset"; + + public static final String DEFAULT_JOB_FILE_TIME_OFFSET = "0d"; + + public static final String JOB_FILE_MAX_WAIT = "job.file.max.wait"; + // time in min + public static final int DEFAULT_JOB_FILE_MAX_WAIT = 1; + + public static final String JOB_DIR_FILTER_PATTERN = "job.dir.pattern"; + + public static final String JOB_DIR_FILTER_PATH = "job.dir.path"; + + public static final String JOB_ID_PREFIX = "job_"; + + public static final String JOB_STORE_TIME = "job.store.time"; + + public static final String JOB_OP = "job.op"; + + public static final String TRIGGER_ONLY_ONE_JOB = "job.standalone"; + + // field splitter + public static final String JOB_FIELD_SPLITTER = "job.splitter"; + + public static final String JOB_ADDITION_STR = "job.additionStr"; + + // job delivery time + public static final String JOB_DELIVERY_TIME = "job.deliveryTime"; + + // job time reading file + public static final String JOB_DATA_TIME = "job.dataTime"; + + public static final String JOB_CYCLE_UNIT = "job.cycleUnit"; + + /** + * when job is retried, the retry time should be provided + */ + public static final String JOB_RETRY_TIME = "job.retryTime"; + +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobProfile.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobProfile.java new file mode 100644 index 00000000..d37d43b9 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobProfile.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.conf; + +import com.google.gson.Gson; + + +/** + * job profile which contains details describing properties of one job. + * + */ +public class JobProfile extends AbstractConfiguration { + + private final Gson gson = new Gson(); + + /** + * parse json string to configuration instance。 + * + * @param jsonStr + * @return job configuration + */ + public static JobProfile parseJsonStr(String jsonStr) { + JobProfile conf = new JobProfile(); + conf.loadJsonStrResource(jsonStr); + return conf; + } + + /** + * parse properties file + * + * @param fileName - file name. + * @return jobConfiguration. + */ + public static JobProfile parsePropertiesFile(String fileName) { + JobProfile conf = new JobProfile(); + conf.loadPropertiesResource(fileName); + return conf; + } + + /** + * pase json file. + * @param fileName - json file name. + * @return jobConfiguration. + */ + public static JobProfile parseJsonFile(String fileName) { + JobProfile conf = new JobProfile(); + conf.loadJsonResource(fileName); + return conf; + } + + /** + * check whether required keys exists. + * + * @return return true if all required keys exists else false. + */ + @Override + public boolean allRequiredKeyExist() { + return hasKey(JobConstants.JOB_ID) && hasKey(JobConstants.JOB_SOURCE) + && hasKey(JobConstants.JOB_SINK) && hasKey(JobConstants.JOB_CHANNEL) && hasKey( + JobConstants.JOB_NAME); + } + + public String toJsonStr() { + return gson.toJson(getConfigStorage()); + } + + public String getInstanceId() { + return get(JobConstants.JOB_INSTANCE_ID); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TriggerProfile.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TriggerProfile.java new file mode 100644 index 00000000..d75c76e0 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TriggerProfile.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.conf; + +/** + * profile used in trigger. Trigger profile is a special job profile + */ +public class TriggerProfile extends JobProfile { + + @Override + public boolean allRequiredKeyExist() { + return hasKey(JobConstants.JOB_TRIGGER) && super.allRequiredKeyExist(); + } + + public static TriggerProfile parseJsonStr(String jsonStr) { + TriggerProfile conf = new TriggerProfile(); + conf.loadJsonStrResource(jsonStr); + return conf; + } + + public String getTriggerId() { + return get(JobConstants.JOB_ID); + } + + public static TriggerProfile parseJobProfile(JobProfile jobProfile) { + TriggerProfile conf = new TriggerProfile(); + conf.loadJsonStrResource(jobProfile.toJsonStr()); + return conf; + } + + public Integer getOpType() { + return getInt(JobConstants.JOB_OP); + } + + public String getDeliveryTime() { + return get(JobConstants.JOB_DELIVERY_TIME); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/exception/FileException.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/exception/FileException.java new file mode 100644 index 00000000..77e8f632 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/exception/FileException.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.exception; + +public class FileException extends RuntimeException { + + public FileException(String message, Throwable ex) { + super(message, ex); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/filter/DateFormatRegex.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/filter/DateFormatRegex.java new file mode 100644 index 00000000..b80e304d --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/filter/DateFormatRegex.java @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.filter; + +import com.zmops.zeus.iot.server.transfer.api.Filter; +import com.zmops.zeus.iot.server.transfer.utils.AgentUtils; +import org.apache.commons.lang3.StringUtils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * date format with regex string for absolute file path. + */ +public class DateFormatRegex implements Filter { + private static final Logger LOGGER = LoggerFactory.getLogger(DateFormatRegex.class); + + private static final String YEAR = "YYYY"; + private static final String MONTH = "MM"; + private static final String DAY = "DD"; + private static final String HOUR = "HH"; + + private static final String NORMAL_FORMATTER = "yyyyMMddHHmm"; + + private static final String OFFSET_DAY = "d"; + private static final String OFFSET_MIN = "m"; + private static final String OFFSET_HOUR = "h"; + + private int dayOffset = 0; + private int hourOffset = 0; + private int minuteOffset = 0; + + private String formattedTime = ""; + private String formattedRegex; + private File file; + + /** + * set regex with current time + * + * @param regex + * @return + */ + public static DateFormatRegex ofRegex(String regex) { + DateFormatRegex dateFormatRegex = new DateFormatRegex(); + dateFormatRegex.setRegexWithCurrentTime(regex); + return dateFormatRegex; + } + + @Override + public boolean match() { + // TODO: check with more regex + return AgentUtils.regexMatch(file.getAbsolutePath(), formattedRegex); + } + + public DateFormatRegex withOffset(String timeOffset) { + String number = StringUtils.substring(timeOffset, 0, timeOffset.length() - 1); + String mark = StringUtils.substring(timeOffset, timeOffset.length() - 1); + switch (mark) { + case OFFSET_DAY: + dayOffset = Integer.parseInt(number); + break; + case OFFSET_HOUR: + hourOffset = Integer.parseInt(number); + break; + case OFFSET_MIN: + minuteOffset = Integer.parseInt(number); + break; + default: + LOGGER.warn("time offset is invalid, please check {}", timeOffset); + break; + } + return this; + } + + public DateFormatRegex withFile(File file) { + this.file = file; + return this; + } + + /** + * set regex with given time, replace the YYYYDDMM pattern with given time + * + * @param regex + * @param time + */ + public void setRegexWithTime(String regex, String time) { + String[] regexList = StringUtils.splitByWholeSeparatorPreserveAllTokens(regex, + File.separator, 0); + List formattedList = new ArrayList<>(); + for (String regexStr : regexList) { + if (regexStr.contains(YEAR)) { + String tmpRegexStr = regexStr.replace(YEAR, time.substring(0, 4)) + .replace(MONTH, time.substring(4, 6)) + .replace(DAY, time.substring(6, 8)) + .replace(HOUR, time.substring(8, 10)); + formattedList.add(tmpRegexStr); + formattedTime = time; + } else { + formattedList.add(regexStr); + } + } + this.formattedRegex = StringUtils.join(formattedList, File.separatorChar); + LOGGER.info("updated formatted regex is {}", this.formattedRegex); + } + + public void setRegexWithCurrentTime(String regex) { + String currentTime = AgentUtils.formatCurrentTimeWithOffset(NORMAL_FORMATTER, + dayOffset, hourOffset, minuteOffset); + setRegexWithTime(regex, currentTime); + } + + public String getFormattedRegex() { + return formattedRegex; + } + + public String getFormattedTime() { + return formattedTime; + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/message/DefaultMessage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/message/DefaultMessage.java new file mode 100644 index 00000000..431f037b --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/message/DefaultMessage.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.message; + +import com.zmops.zeus.iot.server.transfer.api.Message; + +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +public class DefaultMessage implements Message { + + private final byte[] body; + private final Map header; + + public DefaultMessage(byte[] body, Map header) { + this.body = body; + this.header = header; + } + + public DefaultMessage(byte[] body) { + this(body, new HashMap<>()); + } + + @Override + public byte[] getBody() { + return body; + } + + @Override + public Map getHeader() { + return header; + } + + @Override + public String toString() { + return new String(body, StandardCharsets.UTF_8); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sink/ConsoleSink.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sink/ConsoleSink.java new file mode 100644 index 00000000..d623921e --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sink/ConsoleSink.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.sink; + + +import com.zmops.zeus.iot.server.transfer.api.Message; +import com.zmops.zeus.iot.server.transfer.api.Sink; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; + +import java.nio.charset.StandardCharsets; + +/** + * message write to console + */ +public class ConsoleSink implements Sink { + + @Override + public void write(Message message) { + if (message != null) { + System.out.println(new String(message.getBody(), StandardCharsets.UTF_8)); + } + } + + @Override + public void setSourceFile(String sourceFileName) { + + } + + @Override + public void init(JobProfile jobConf) { + + } + + @Override + public void destroy() { + + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/source/TextFileSource.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/source/TextFileSource.java new file mode 100644 index 00000000..b5e3cd4f --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/source/TextFileSource.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.source; + + +import com.zmops.zeus.iot.server.transfer.api.Reader; +import com.zmops.zeus.iot.server.transfer.api.Source; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import com.zmops.zeus.iot.server.transfer.source.reader.TextFileReader; +import com.zmops.zeus.iot.server.transfer.utils.PluginUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static com.zmops.zeus.iot.server.transfer.conf.CommonConstants.POSITION_SUFFIX; +import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.DEFAULT_JOB_LINE_FILTER; +import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_LINE_FILTER_PATTERN; + +/** + * Read text files + */ +public class TextFileSource implements Source { + + private static final Logger LOGGER = LoggerFactory.getLogger(TextFileSource.class); + + // path + suffix + public static final String MD5_SUFFIX = ".md5"; + + @Override + public List split(JobProfile jobConf) { + Collection allFiles = PluginUtils.findSuitFiles(jobConf); + List result = new ArrayList<>(); + + String filterPattern = jobConf.get(JOB_LINE_FILTER_PATTERN, DEFAULT_JOB_LINE_FILTER); + + + for (File file : allFiles) { + + int seekPosition = jobConf.getInt(file.getAbsolutePath() + POSITION_SUFFIX, 0); + + LOGGER.info("read from history position {} with job profile {}", seekPosition, jobConf.getInstanceId()); + String md5 = jobConf.get(file.getAbsolutePath() + MD5_SUFFIX, ""); + TextFileReader textFileReader = new TextFileReader(file, seekPosition); + addValidator(filterPattern, textFileReader); + result.add(textFileReader); + } + return result; + } + + + private void addValidator(String filterPattern, TextFileReader textFileReader) { + textFileReader.addPatternValidator(filterPattern); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/source/reader/TextFileReader.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/source/reader/TextFileReader.java new file mode 100644 index 00000000..78f72c6b --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/source/reader/TextFileReader.java @@ -0,0 +1,165 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.source.reader; + +import com.zmops.zeus.iot.server.transfer.api.Message; +import com.zmops.zeus.iot.server.transfer.api.Reader; +import com.zmops.zeus.iot.server.transfer.api.Validator; + +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import com.zmops.zeus.iot.server.transfer.exception.FileException; +import com.zmops.zeus.iot.server.transfer.message.DefaultMessage; +import com.zmops.zeus.iot.server.transfer.utils.AgentUtils; +import com.zmops.zeus.iot.server.transfer.validator.PatternValidator; +import org.apache.commons.lang3.StringUtils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; + +import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.DEFAULT_JOB_FILE_MAX_WAIT; +import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_FILE_MAX_WAIT; + +public class TextFileReader implements Reader { + + private static final Logger LOGGER = LoggerFactory.getLogger(TextFileReader.class); + public static final int NEVER_STOP_SIGN = -1; + + private final File file; + private final int position; + private final String md5; + private Iterator iterator; + private Stream stream; + private long timeout; + private long lastTime = 0; + // private final PluginMetric textFileMetric; + private List validators = new ArrayList<>(); + + public TextFileReader(File file, int position) { + this(file, position, ""); + } + + public TextFileReader(File file, int position, String md5) { + this.file = file; + this.position = position; + this.md5 = md5; +// textFileMetric = new PluginMetric(); +// textFileMetric.tagName.setName(file.getAbsolutePath()); + } + + public TextFileReader(File file) { + this(file, 0); + } + + @Override + public Message read() { + if (iterator != null && iterator.hasNext()) { + String message = iterator.next(); + if (validateMessage(message)) { +// textFileMetric.readNum.incr(); + return new DefaultMessage(message.getBytes(StandardCharsets.UTF_8)); + } + } + return null; + } + + + private boolean validateMessage(String message) { + if (validators.isEmpty()) { + return true; + } + return validators.stream().allMatch(v -> v.validate(message)); + } + + @Override + public boolean isFinished() { + if (timeout == NEVER_STOP_SIGN) { + return false; + } + if (iterator == null) { + return true; + } + if (iterator.hasNext()) { + lastTime = 0; + return false; + } else { + if (lastTime == 0) { + lastTime = System.currentTimeMillis(); + } + return System.currentTimeMillis() - lastTime > timeout; + } + } + + @Override + public String getReadFile() { + return file.getAbsolutePath(); + } + + @Override + public void setReadTimeout(long millis) { + timeout = millis; + } + + public void addPatternValidator(String pattern) { + if (pattern.isEmpty()) { + return; + } + validators.add(new PatternValidator(pattern)); + } + + + @Override + public void init(JobProfile jobConf) { + try { + initReadTimeout(jobConf); + String md5 = AgentUtils.getFileMd5(file); + + if (StringUtils.isNotBlank(this.md5) && !this.md5.equals(md5)) { + LOGGER.warn("md5 is differ from origin, origin: {}, new {}", this.md5, md5); + } + LOGGER.info("file name for task is {}, md5 is {}", file, md5); + stream = Files.newBufferedReader(file.toPath()).lines().skip(position); + iterator = stream.iterator(); + } catch (Exception ex) { + throw new FileException("error init stream for " + file.getPath(), ex); + } + } + + private void initReadTimeout(JobProfile jobConf) { + int waitTime = jobConf.getInt(JOB_FILE_MAX_WAIT, DEFAULT_JOB_FILE_MAX_WAIT); + if (waitTime == NEVER_STOP_SIGN) { + timeout = NEVER_STOP_SIGN; + } else { + timeout = TimeUnit.MINUTES.toMillis(waitTime); + } + } + + @Override + public void destroy() { + AgentUtils.finallyClose(stream); +// LOGGER.info("destroy reader with read {} num {}", textFileMetric.tagName.getName(), textFileMetric.readNum.snapshot()); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/trigger/PathPattern.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/trigger/PathPattern.java new file mode 100644 index 00000000..2dc1cde5 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/trigger/PathPattern.java @@ -0,0 +1,195 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.trigger; + +import com.zmops.zeus.iot.server.transfer.filter.DateFormatRegex; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +/** + * path pattern for file filter. + */ +public class PathPattern { + + private static final Logger LOGGER = LoggerFactory.getLogger(PathPattern.class); + + private final DateFormatRegex dateFormatRegex; + + private final String watchDir; + private final String rootDir; + private final Set subDirs; + + public PathPattern(String watchDir) { + this.watchDir = watchDir; + rootDir = findRoot(watchDir); + subDirs = new HashSet<>(); + dateFormatRegex = DateFormatRegex.ofRegex(watchDir); + } + + public PathPattern(String watchDir, String offset) { + this.watchDir = watchDir; + rootDir = findRoot(watchDir); + subDirs = new HashSet<>(); + dateFormatRegex = DateFormatRegex.ofRegex(watchDir).withOffset(offset); + } + + /** + * find last existing path by pattern. + * + * @param watchDir + * @return + */ + private String findRoot(String watchDir) { + Path currentPath = Paths.get(watchDir); + if (!Files.exists(currentPath)) { + Path parentPath = currentPath.getParent(); + if (parentPath != null) { + return findRoot(parentPath.toString()); + } + } + if (Files.isDirectory(currentPath)) { + return watchDir; + } + return currentPath.getParent().toString(); + } + + /** + * walk all suitable files under directory. + * + * @param collectResult + * @param maxNum + */ + private void walkAllSuitableFiles(File dirPath, final Collection collectResult, + int maxNum) throws IOException { + if (collectResult.size() > maxNum) { + LOGGER.warn("max num of files is {}, please check", maxNum); + return; + } + if (dirPath.isFile() && dateFormatRegex.withFile(dirPath).match()) { + collectResult.add(dirPath); + } else if (dirPath.isDirectory()) { + Files.list(dirPath.toPath()).forEach(path -> { + try { + walkAllSuitableFiles(path.toFile(), collectResult, maxNum); + } catch (IOException ex) { + LOGGER.warn("cannot add {}, please check it", path, ex); + } + }); + } + } + + /** + * walk root directory + * + * @param collectResult + * @param maxNum + * @throws IOException + */ + public void walkAllSuitableFiles(final Collection collectResult, + int maxNum) throws IOException { + walkAllSuitableFiles(new File(rootDir), collectResult, maxNum); + } + + /** + * cleanup local cache, subDirs is only used to filter duplicated directories + * in one term watch key check. + */ + public void cleanup() { + subDirs.clear(); + } + + /** + * whether path is suitable + * + * @param pathStr - pathString + * @return true if suit else false. + */ + public boolean suitForWatch(String pathStr) { + // remove common root dir + String briefSubDir = StringUtils.substringAfter(pathStr, rootDir); + // if already watched, then stop deep find + if (subDirs.contains(briefSubDir)) { + LOGGER.info("already watched {}", pathStr); + return false; + } + boolean matched = dateFormatRegex.withFile(new File(pathStr)).match(); + if (matched) { + LOGGER.info("add path {}", pathStr); + subDirs.add(briefSubDir); + } + return matched; + } + + /** + * when a new file is found, update regex since time may change. + * + * @param + */ + public void updateDateFormatRegex() { + dateFormatRegex.setRegexWithCurrentTime(this.watchDir); + } + + /** + * when job is retry job, the time for searching file should be specified. + * + * @param time + */ + public void updateDateFormatRegex(String time) { + dateFormatRegex.setRegexWithTime(this.watchDir, time); + } + + @Override + public String toString() { + return watchDir; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(watchDir, false); + } + + @Override + public boolean equals(Object object) { + if (object instanceof PathPattern) { + PathPattern entity = (PathPattern) object; + return entity.watchDir.equals(this.watchDir); + } else { + return false; + } + } + + public String getRootDir() { + return rootDir; + } + + public String getSuitTime() { + return dateFormatRegex.getFormattedTime(); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/AgentUtils.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/AgentUtils.java new file mode 100644 index 00000000..c7dd766f --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/AgentUtils.java @@ -0,0 +1,358 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.utils; + +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.Closeable; +import java.io.File; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.nio.charset.StandardCharsets; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class AgentUtils { + + private static final Logger LOGGER = LoggerFactory.getLogger(AgentUtils.class); + private static final AtomicLong INDEX = new AtomicLong(0); + private static final String HEX_PREFIX = "0x"; + public static final String EQUAL = "="; + public static final String M_VALUE = "m"; + public static final String ADDITION_SPLITTER = "&"; + public static final String BEIJING_TIME_ZONE = "GMT+8:00"; + public static final String HOUR_PATTERN = "yyyyMMddHH"; + public static final String DAY_PATTERN = "yyyyMMdd"; + public static final String DEFAULT_PATTERN = "yyyyMMddHHmm"; + public static final String DAY = "D"; + public static final String HOUR = "H"; + public static final String HOUR_LOW_CASE = "h"; + public static final String MINUTE = "m"; + + + /** + * get md5 of file. + * @param file - file name + * @return + */ + public static String getFileMd5(File file) { + try (InputStream is = Files.newInputStream(Paths.get(file.getAbsolutePath()))) { + return DigestUtils.md5Hex(is); + } catch (Exception ex) { + LOGGER.warn("cannot get md5 of {}", file, ex); + } + return ""; + } + + /** + * finally close resources + * + * @param resource - resource which is closable. + */ + public static void finallyClose(Closeable resource) { + if (resource != null) { + try { + resource.close(); + } catch (Exception ex) { + LOGGER.info("error while closing", ex); + } + } + } + + /** + * finally close resources. + * + * @param resource - resource which is closable. + */ + public static void finallyClose(AutoCloseable resource) { + if (resource != null) { + try { + resource.close(); + } catch (Exception ex) { + LOGGER.error("error while closing", ex); + } + } + } + + /** + * Get declare fields. + */ + public static List getDeclaredFieldsIncludingInherited(Class clazz) { + List fields = new ArrayList(); + // check whether parent exists + while (clazz != null) { + fields.addAll(Arrays.asList(clazz.getDeclaredFields())); + clazz = clazz.getSuperclass(); + } + return fields; + } + + /** + * Get declare methods. + * + * @param clazz - class of field from method return + * @return list of methods + */ + public static List getDeclaredMethodsIncludingInherited(Class clazz) { + List methods = new ArrayList(); + while (clazz != null) { + methods.addAll(Arrays.asList(clazz.getDeclaredMethods())); + clazz = clazz.getSuperclass(); + } + return methods; + } + + /** + * get random int of [seed, seed * 2] + * @param seed + * @return + */ + public static int getRandomBySeed(int seed) { + return ThreadLocalRandom.current().nextInt(0, seed) + seed; + } + + public static String getLocalIp() { + String ip = "127.0.0.1"; + try (DatagramSocket socket = new DatagramSocket()) { + socket.connect(InetAddress.getByName("8.8.8.8"), 10002); + ip = socket.getLocalAddress().getHostAddress(); + } catch (Exception ex) { + LOGGER.error("error while get local ip", ex); + } + return ip; + } + + /** + * Get uniq id with timestamp. + * + * @return uniq id. + */ + public static String getUniqId(String prefix, String id) { + return getUniqId(prefix, id, 0L); + } + + /** + * Get uniq id with timestamp and index. + * @param id - job id + * @param index - job index + * @return uniq id + */ + public static String getUniqId(String prefix, String id, long index) { + long currentTime = System.currentTimeMillis() / 1000; + return prefix + currentTime + "_" + id + "_" + index; + } + + public static void silenceSleepInMs(long millisecond) { + try { + TimeUnit.MILLISECONDS.sleep(millisecond); + } catch (Exception ignored) { + LOGGER.warn("silenceSleepInMs ", ignored); + } + } + + public static String parseHexStr(String delimiter) throws IllegalArgumentException { + if (delimiter.trim().toLowerCase().startsWith(HEX_PREFIX)) { + //only one char + byte[] byteArr = new byte[1]; + byteArr[0] = Byte.decode(delimiter.trim()); + return new String(byteArr, StandardCharsets.UTF_8); + } else { + throw new IllegalArgumentException("delimiter not start with " + HEX_PREFIX); + } + } + + /** + * formatter for current time + * @param formatter + * @return + */ + public static String formatCurrentTime(String formatter) { + return formatCurrentTime(formatter, Locale.getDefault()); + } + + public static String formatCurrentTime(String formatter, Locale locale) { + ZonedDateTime zoned = ZonedDateTime.now(); + // TODO: locale seems not working + return DateTimeFormatter.ofPattern(formatter).withLocale(locale).format(zoned); + } + + /** + * formatter with time offset + * @param formatter - formatter string + * @param day - day offset + * @param hour - hour offset + * @param min - min offset + * @return current time with offset + */ + public static String formatCurrentTimeWithOffset(String formatter, int day, int hour, int min) { + ZonedDateTime zoned = ZonedDateTime.now().plusDays(day).plusHours(hour).plusMinutes(min); + return DateTimeFormatter.ofPattern(formatter).withLocale(Locale.getDefault()).format(zoned); + } + + + public static String formatCurrentTimeWithoutOffset(String formatter) { + ZonedDateTime zoned = ZonedDateTime.now().plusDays(0).plusHours(0).plusMinutes(0); + return DateTimeFormatter.ofPattern(formatter).withLocale(Locale.getDefault()).format(zoned); + } + + /** + * whether all class of path name are matched + * + * @param pathStr - path string + * @param patternStr - regex pattern + * @return true if all match + */ + public static boolean regexMatch(String pathStr, String patternStr) { + String[] pathNames = StringUtils.split(pathStr, FileSystems.getDefault().getSeparator()); + String[] patternNames = StringUtils + .split(patternStr, FileSystems.getDefault().getSeparator()); + for (int i = 0; i < pathNames.length && i < patternNames.length; i++) { + if (!pathNames[i].equals(patternNames[i])) { + Matcher matcher = Pattern.compile(patternNames[i]).matcher(pathNames[i]); + if (!matcher.matches()) { + return false; + } + } + } + return true; + } + + /** + * parse addition attr, the attributes must be send in proxy sender + * @param additionStr + * @return + */ + public static Pair> parseAddAttr(String additionStr) { + Map attr = new HashMap<>(); + String[] split = additionStr.split(ADDITION_SPLITTER); + String mValue = ""; + for (String s : split) { + if (!s.contains(EQUAL)) { + continue; + } + String[] pairs = s.split(EQUAL); + if (pairs[0].equalsIgnoreCase(M_VALUE)) { + mValue = pairs[1]; + continue; + } + getAttrs(attr, s, pairs); + } + return Pair.of(mValue, attr); + } + + /** + * the attrs in pairs can be complicated in online env + * @param attr + * @param s + * @param pairs + */ + private static void getAttrs(Map attr, String s, String[] pairs) { + // when addiction attr be like "m=10&__addcol1__worldid=" + if (s.endsWith(EQUAL) && pairs.length == 1) { + attr.put(pairs[0], ""); + } else { + attr.put(pairs[0], pairs[1]); + } + } + + /** + * get addition attributes in additionStr + * @param additionStr + * @return + */ + public static Map getAdditionAttr(String additionStr) { + Pair> mValueAttrs = parseAddAttr(additionStr); + return mValueAttrs.getRight(); + } + + + /** + * get m value in additionStr + * @param addictiveAttr + * @return + */ + public static String getmValue(String addictiveAttr) { + Pair> mValueAttrs = parseAddAttr(addictiveAttr); + return mValueAttrs.getLeft(); + } + + /** + * time str convert to mill sec + * @param time + * @param cycleUnit + * @return + */ + public static long timeStrConvertToMillSec(String time, String cycleUnit) { + long defaultTime = System.currentTimeMillis(); + if (time.isEmpty() || cycleUnit.isEmpty()) { + return defaultTime; + } + String pattern = DEFAULT_PATTERN; + switch (cycleUnit) { + case DAY: + pattern = DAY_PATTERN; + time = time.substring(0, 8); + break; + case HOUR: + case HOUR_LOW_CASE: + pattern = HOUR_PATTERN; + time = time.substring(0, 10); + break; + case MINUTE: + break; + default: + LOGGER.error("cycle unit {} is illegal, please check!", cycleUnit); + break; + } + return parseTimeToMillSec(time, pattern); + } + + private static long parseTimeToMillSec(String time, String pattern) { + try { + SimpleDateFormat df = new SimpleDateFormat(pattern); + df.setTimeZone(TimeZone.getTimeZone(BEIJING_TIME_ZONE)); + return df.parse(time).getTime(); + } catch (ParseException e) { + LOGGER.error("convert time string {} to millSec error", time); + } + return System.currentTimeMillis(); + } + + + + + +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/ByteUtil.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/ByteUtil.java new file mode 100644 index 00000000..22ff987b --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/ByteUtil.java @@ -0,0 +1,235 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package com.zmops.zeus.iot.server.transfer.utils; + +import java.util.ArrayList; +import java.util.List; + +public class ByteUtil { + /** + * Splits the source array into multiple array segments using the given separator, up to a + * maximum of count items. This will naturally produce copied byte arrays for each of the split + * segments. To identify the split ranges without the array copies, see {@link + * ByteUtil#splitRanges(byte[], byte[])}. + * + * @param source + * @param separator + * @return + */ + public static byte[][] split(byte[] source, byte[] separator) { + return split(source, separator, -1); + } + + /** + * Splits the source array into multiple array segments using the given separator, up to a + * maximum of count items. This will naturally produce copied byte arrays for each of the split + * segments. To identify the split ranges without the array copies, see {@link + * ByteUtil#splitRanges(byte[], byte[])}. + * + * @param source + * @param separator + * @return + */ + public static byte[][] split(byte[] source, byte[] separator, int limit) { + List segments = splitRanges(source, separator, limit); + + byte[][] splits = new byte[segments.size()][]; + for (int i = 0; i < segments.size(); i++) { + Range r = segments.get(i); + byte[] tmp = new byte[r.length()]; + if (tmp.length > 0) { + System.arraycopy(source, r.start(), tmp, 0, r.length()); + } + splits[i] = tmp; + } + return splits; + } + + /** + * Returns a list of ranges identifying [start, end) -- closed, open -- positions within the + * source byte array that would be split using the separator byte array. + */ + public static List splitRanges(byte[] source, byte[] separator) { + return splitRanges(source, separator, -1); + } + + /** + * Returns a list of ranges identifying [start, end) -- closed, open -- positions within the + * source byte array that would be split using the separator byte array. + * + * @param source the source data + * @param separator the separator pattern to look for + * @param limit the maximum number of splits to identify in the source + */ + public static List splitRanges(byte[] source, byte[] separator, int limit) { + List segments = new ArrayList(); + int start = 0; + itersource: + for (int i = 0; i < source.length; i++) { + for (int j = 0; j < separator.length; j++) { + if (source[i + j] != separator[j]) { + continue itersource; + } + } + // all separator elements matched + if (limit > 0 && segments.size() >= (limit - 1)) { + // everything else goes in one final segment + break; + } + + segments.add(new Range(start, i)); + start = i + separator.length; + // i will be incremented again in outer for loop + i += separator.length - 1; + } + // add in remaining to a final range + if (start <= source.length) { + segments.add(new Range(start, source.length)); + } + return segments; + } + + /** + * Returns a single byte array containing all of the individual component arrays separated by + * the separator array. + * + * @param separator + * @param components + * @return + */ + public static byte[] join(byte[] separator, byte[]... components) { + if (components == null || components.length == 0) { + return new byte[0]; + } + + int finalSize = 0; + if (separator != null) { + finalSize = separator.length * (components.length - 1); + } + for (byte[] comp : components) { + finalSize += comp.length; + } + + byte[] buf = new byte[finalSize]; + int offset = 0; + for (int i = 0; i < components.length; i++) { + System.arraycopy(components[i], 0, buf, offset, components[i].length); + offset += components[i].length; + if (i < (components.length - 1) && separator != null && separator.length > 0) { + System.arraycopy(separator, 0, buf, offset, separator.length); + offset += separator.length; + } + } + return buf; + } + + /** + * Returns the index (start position) of the first occurrence of the specified {@code target} + * within {@code array} starting at {@code fromIndex} , or {@code -1} if there is no such + * occurrence. + * + *

+ * Returns the lowest index {@code k} such that {@code k >= fromIndex} and {@code + * java.util.Arrays.copyOfRange(array, k, k + target.length)} contains exactly the same elements + * as {@code target}. + * + * @param array the array to search for the sequence {@code target} + * @param target the array to search for as a sub-sequence of {@code array} + * @param fromIndex the index to start the search from in {@code array} + */ + public static int indexOf(byte[] array, byte[] target, int fromIndex) { + + if (array == null || target == null) { + return -1; + } + + // Target cannot be beyond array boundaries + if (fromIndex < 0 || (fromIndex > (array.length - target.length))) { + return -1; + } + + // Empty is assumed to be at the fromIndex of any non-null array (after boundary check) + if (target.length == 0) { + return fromIndex; + } + + firstbyte: + for (int i = fromIndex; i < array.length - target.length + 1; i++) { + for (int j = 0; j < target.length; j++) { + if (array[i + j] != target[j]) { + continue firstbyte; + } + } + return i; + } + return -1; + } + + /** + * Returns a copy of the source byte array, starting at offset for the given length. If the + * offset + length is out of bounds for the array, returns null. + * + * @param source + * @param offset + * @param length + * @return + */ + public static byte[] safeCopy(byte[] source, int offset, int length) { + if (length < 0 || source.length < offset + length) { + return null; + } + byte[] copy = new byte[length]; + System.arraycopy(source, offset, copy, 0, length); + return copy; + } + + public static class Range { + + private int startIdx; + private int endIdx; + + /** + * Defines a range from start index (inclusive) to end index (exclusive). + * + * @param start Starting index position + * @param end Ending index position (exclusive) + */ + public Range(int start, int end) { + if (start < 0 || end < start) { + throw new IllegalArgumentException( + "Invalid range, required that: 0 <= start <= end; start=" + start + ", end=" + end); + } + + this.startIdx = start; + this.endIdx = end; + } + + public int start() { + return startIdx; + } + + public int end() { + return endIdx; + } + + public int length() { + return endIdx - startIdx; + } + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/PluginUtils.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/PluginUtils.java new file mode 100644 index 00000000..8fdc8c70 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/PluginUtils.java @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.utils; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.zmops.zeus.iot.server.transfer.conf.JobConstants; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; +import com.zmops.zeus.iot.server.transfer.trigger.PathPattern; +import lombok.extern.slf4j.Slf4j; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.List; + +import static com.zmops.zeus.iot.server.transfer.conf.CommonConstants.*; +import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_DIR_FILTER_PATTERN; +import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_RETRY_TIME; + +/** + * Utils for plugin package. + */ +@Slf4j +public class PluginUtils { + + + private static final Logger LOGGER = LoggerFactory.getLogger(PluginUtils.class); + + + public static String toJsonStr(Object obj) { + GsonBuilder gsonBuilder = new GsonBuilder(); + gsonBuilder.setPrettyPrinting(); + Gson gson = gsonBuilder.create(); + return gson.toJson(obj); + } + + + public static Collection findSuitFiles(JobProfile jobConf) { + String dirPattern = jobConf.get(JOB_DIR_FILTER_PATTERN); + LOGGER.info("start to find files with dir pattern {}", dirPattern); + PathPattern pattern = new PathPattern(dirPattern); + updateRetryTime(jobConf, pattern); + int maxFileNum = jobConf.getInt(FILE_MAX_NUM, DEFAULT_FILE_MAX_NUM); + LOGGER.info("dir pattern {}, max file num {}", dirPattern, maxFileNum); + Collection allFiles = new ArrayList<>(); + try { + pattern.walkAllSuitableFiles(allFiles, maxFileNum); + } catch (IOException ex) { + LOGGER.warn("cannot get all files from {}", dirPattern, ex); + } + return allFiles; + } + + /** + * if the job is retry job, the date is determined + * + * @param jobConf + * @param pattern + */ + public static void updateRetryTime(JobProfile jobConf, PathPattern pattern) { + if (jobConf.hasKey(JOB_RETRY_TIME)) { + LOGGER.info("job {} is retry job with specific time, update file time to {}" + + "", jobConf.toJsonStr(), jobConf.get(JOB_RETRY_TIME)); + pattern.updateDateFormatRegex(jobConf.get(JOB_RETRY_TIME)); + } + } + + public static JobProfile copyJobProfile(TriggerProfile triggerProfile, String dataTime, + File pendingFile) { + JobProfile copiedProfile = TriggerProfile.parseJsonStr(triggerProfile.toJsonStr()); + String md5 = AgentUtils.getFileMd5(pendingFile); + copiedProfile.set(pendingFile.getAbsolutePath() + ".md5", md5); + copiedProfile.set(JobConstants.JOB_DIR_FILTER_PATTERN, pendingFile.getAbsolutePath()); + // the time suit for file name is just the data time + copiedProfile.set(JobConstants.JOB_DATA_TIME, dataTime); + return copiedProfile; + } + + public static List getLocalIpList() { + List allIps = new ArrayList<>(); + try { + String os = System.getProperty(AGENT_OS_NAME).toLowerCase(); + if (os.contains(AGENT_NIX_OS) || os.contains(AGENT_NUX_OS)) { + /* Deal with linux platform. */ + Enumeration nis = NetworkInterface.getNetworkInterfaces(); + while (nis.hasMoreElements()) { + NetworkInterface ni = nis.nextElement(); + addIp(allIps, ni); + } + } else { + /* Deal with windows platform. */ + allIps.add(InetAddress.getLocalHost().getHostAddress()); + } + } catch (Exception e) { + LOGGER.error("get local ip list fail with ex {} ", e); + } + return allIps; + } + + + private static void addIp(List allIps, NetworkInterface ni) { + Enumeration ias = ni.getInetAddresses(); + while (ias.hasMoreElements()) { + InetAddress ia = ias.nextElement(); + if (!ia.isLoopbackAddress() && ia.getHostAddress().contains(AGENT_COLON)) { + allIps.add(ia.getHostAddress()); + } + } + } + +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/validator/PatternValidator.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/validator/PatternValidator.java new file mode 100644 index 00000000..780675d7 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/validator/PatternValidator.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.validator; + + +import com.zmops.zeus.iot.server.transfer.api.Validator; + +public class PatternValidator implements Validator { + + public PatternValidator(String pattern) { + this.pattern = pattern; + } + + private String pattern; + + @Override + public boolean validate(String messageLine) { + return messageLine.contains(pattern); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/validator/PrefixValidator.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/validator/PrefixValidator.java new file mode 100644 index 00000000..5de00291 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/validator/PrefixValidator.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.validator; + +import com.zmops.zeus.iot.server.transfer.api.Validator; + +public class PrefixValidator implements Validator { + + public PrefixValidator(String prefix) { + this.prefix = prefix; + } + + private String prefix; + + @Override + public boolean validate(String messageLine) { + return messageLine.startsWith(prefix); + } +} From ca523eb29e23da31a57ad852c066559a12d2abd0 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 22 Sep 2021 14:00:05 +0800 Subject: [PATCH 253/763] [fix]: product attrubite event update --- .../service/ProductAttributeEventService.java | 10 ++++----- .../controller/EventTriggerController.java | 22 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java index bb74a177..5e2d8b76 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -60,7 +60,7 @@ public class ProductAttributeEventService { * @return */ public Pager prodAttributeEventList(ProductAttrParam productAttr) { - QProductAttribute qProductAttribute = new QProductAttribute(); + QProductAttributeEvent qProductAttribute = new QProductAttributeEvent(); if (ToolUtil.isNotEmpty(productAttr.getProdId())) { qProductAttribute.productId.eq(productAttr.getProdId()); @@ -84,7 +84,7 @@ public Pager prodAttributeEventList(ProductAttrParam productAttr * @return */ public List list(ProductAttrParam productAttr) { - QProductAttribute qProductAttribute = new QProductAttribute(); + QProductAttributeEvent qProductAttribute = new QProductAttributeEvent(); if (null != productAttr.getProdId()) { qProductAttribute.productId.eq(productAttr.getProdId()); } @@ -147,8 +147,8 @@ public void createProductAttr(ProductAttrEvent productAttr, String zbxId) { productAttributeEvent.save(); - WorkerWrapper saveProdAttrEventTriggerWork = WorkerWrapper.builder() - .worker(saveProdAttrEventTriggerWorker).param(productAttr).build(); +// WorkerWrapper saveProdAttrEventTriggerWork = WorkerWrapper.builder() +// .worker(saveProdAttrEventTriggerWorker).param(productAttr).build(); WorkerWrapper asyncAttrEventZbxIdWork = WorkerWrapper.builder() .worker(asyncAttrEventZbxIdWorker).param(productAttr).build(); @@ -156,7 +156,7 @@ public void createProductAttr(ProductAttrEvent productAttr, String zbxId) { .worker(saveProdAttrEventWorker).param(productAttr).nextOf(asyncAttrEventZbxIdWork).build(); try { - Async.work(10000, saveProdAttrEventWork,saveProdAttrEventTriggerWork).awaitFinish(); + Async.work(10000, saveProdAttrEventWork).awaitFinish(); } catch (Exception e) { e.printStackTrace(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/controller/EventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/controller/EventTriggerController.java index 47d4d343..3971b1eb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/controller/EventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/controller/EventTriggerController.java @@ -32,17 +32,17 @@ public class EventTriggerController { * * @return */ - @RequestMapping("/status/update") - public ResponseData updateTriggerStatus(@RequestBody @Valid TriggerStatusDto statusDto) { - String res = zbxTrigger.triggerStatusUpdate(statusDto.getTriggerId(), statusDto.getStatus()); - -// DB.update(ProductEvent.class) -// .where().eq("eventRuleId", statusDto.getEventRuleId()) -// .asUpdate().set("status", statusDto.getStatus()).update(); // 0 启用,1 禁用 - - - return ResponseData.success(JSON.parseObject(res, TriggerIds.class).getTriggerids()[0]); - } +// @RequestMapping("/status/update") +// public ResponseData updateTriggerStatus(@RequestBody @Valid TriggerStatusDto statusDto) { +// String res = zbxTrigger.triggerStatusUpdate(statusDto.getTriggerId(), statusDto.getStatus()); +// +//// DB.update(ProductEvent.class) +//// .where().eq("eventRuleId", statusDto.getEventRuleId()) +//// .asUpdate().set("status", statusDto.getStatus()).update(); // 0 启用,1 禁用 +// +// +// return ResponseData.success(JSON.parseObject(res, TriggerIds.class).getTriggerids()[0]); +// } @Getter @Setter From 8ce70ee19f48c683345010cd8e7753b21bd3ff87 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 22 Sep 2021 14:20:35 +0800 Subject: [PATCH 254/763] [fix]: product event trigger update --- .../zmops/iot/domain/product/ProductEventExpression.java | 2 ++ .../java/com/zmops/iot/web/device/dto/DeviceEventRule.java | 4 ++++ .../com/zmops/iot/web/product/dto/ProductEventRule.java | 6 +++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java index f60cbec5..869cff8d 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java @@ -32,4 +32,6 @@ public class ProductEventExpression extends Model { private String deviceId; private String productAttrKey; private String unit; + private Long productAttrId; + private String productAttrType; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java index 93c61e78..66ebfd11 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java @@ -96,6 +96,10 @@ public static class Expression { private String unit; + private Long productAttrId; + + private String productAttrType; + @Override public String toString() { StringBuilder expression = new StringBuilder(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java index 5879f18f..330bf72c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java @@ -92,10 +92,14 @@ public static class Expression { @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private String productAttrKey; // 产品属性 Key - private String deviceId; // 设备ID + private String deviceId; // 产品 ID private String unit; + private Long productAttrId; + + private String productAttrType; + @Override public String toString() { StringBuilder expression = new StringBuilder(); From 9fd0a79d264a0fc06555641c9bd3f0c3f1d81e8e Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 22 Sep 2021 16:48:08 +0800 Subject: [PATCH 255/763] [feat]: add nats --- .../src/main/resources/application.yaml | 3 +++ zeus-webapp/pom.xml | 5 ++++ .../iot/web/alarm/service/MessageService.java | 25 ++++++++---------- .../zmops/iot/web/nats/NatsConnection.java | 8 ++++++ .../iot/web/nats/NatsConnectionHolder.java | 20 ++++++++++++++ .../iot/web/nats/NatsConnectionImpl.java | 26 +++++++++++++++++++ .../web/nats/NatsConnectionInitializer.java | 25 ++++++++++++++++++ 7 files changed, 98 insertions(+), 14 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnection.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionHolder.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionImpl.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionInitializer.java diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index 72fe64cf..a18e00f7 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -49,3 +49,6 @@ forest: zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:80} zbxApiToken: 5376d4510465d6873d6c41076f26c58dae42701941e276971e8f068b76e660d0 + +nats: + url: nats://${NATS_HOST:127.0.0.1}:${NATS_PORT:4222} \ No newline at end of file diff --git a/zeus-webapp/pom.xml b/zeus-webapp/pom.xml index 56c10298..bbe64d73 100644 --- a/zeus-webapp/pom.xml +++ b/zeus-webapp/pom.xml @@ -46,6 +46,11 @@ commons-httpclient 3.1 + + io.nats + jnats + 2.2.0 + diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java index 170abf65..643d567b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java @@ -11,6 +11,7 @@ import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.alarm.dto.param.MessageParam; +import com.zmops.iot.web.nats.NatsConnectionHolder; import io.ebean.DB; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @@ -38,14 +39,14 @@ public class MessageService { */ public void push(MessageBody body) { Objects.requireNonNull(body.getMsg()); + List tos; + if (!CollectionUtils.isEmpty(body.getTo())) { + tos = body.getTo(); + } else { + List userList = new QSysUser().findList(); + tos = userList.parallelStream().map(SysUser::getUserId).collect(Collectors.toList()); + } if (body.isPersist()) { - List tos; - if (!CollectionUtils.isEmpty(body.getTo())) { - tos = body.getTo(); - } else { - List userList = new QSysUser().findList(); - tos = userList.parallelStream().map(SysUser::getUserId).collect(Collectors.toList()); - } tos.forEach(to -> { Messages messages = new Messages(); messages.setClassify(sys); @@ -62,13 +63,9 @@ public void push(MessageBody body) { } body.addBody("classify", sys); - if (!CollectionUtils.isEmpty(body.getTo())) { - body.getTo().forEach(to -> { - //WebSocketServer.sendMessageTo(JSON.toJSONString(body), to + ""); - }); - } else { - //WebSocketServer.sendMessageToAll(JSON.toJSONString(body)); - } + tos.forEach(to -> { + NatsConnectionHolder.INSTANCE.getConnection().publish(to + "", JSON.toJSONString(body)); + }); } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnection.java b/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnection.java new file mode 100644 index 00000000..bfd67819 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnection.java @@ -0,0 +1,8 @@ +package com.zmops.iot.web.nats; + +/** + * @author yefei + **/ +public interface NatsConnection { + void publish(String topic, String messageBody); +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionHolder.java b/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionHolder.java new file mode 100644 index 00000000..c628ae5f --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionHolder.java @@ -0,0 +1,20 @@ +package com.zmops.iot.web.nats; + +/** + * @author yefei + **/ +public enum NatsConnectionHolder { + + INSTANCE; + + private NatsConnection connection; + + public NatsConnection getConnection() { + return connection; + } + + public void setConnection(NatsConnection connection) { + this.connection = connection; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionImpl.java b/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionImpl.java new file mode 100644 index 00000000..14678e22 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionImpl.java @@ -0,0 +1,26 @@ +package com.zmops.iot.web.nats; + +import io.nats.client.Connection; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.Assert; + +import java.nio.charset.StandardCharsets; + +/** + * @author yefei + **/ +@Slf4j +public class NatsConnectionImpl implements NatsConnection { + + private Connection connection; + + public NatsConnectionImpl(Connection connection) { + Assert.state(connection != null, "connection could not be null"); + this.connection = connection; + } + + @Override + public void publish(String topic, String messageBody) { + connection.publish(topic, messageBody.getBytes(StandardCharsets.UTF_8)); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionInitializer.java b/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionInitializer.java new file mode 100644 index 00000000..9eb41040 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionInitializer.java @@ -0,0 +1,25 @@ +package com.zmops.iot.web.nats; + +import io.nats.client.Connection; +import io.nats.client.Nats; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * * @author yefei + *

+ * 初始化 连接 + **/ +@Component +public class NatsConnectionInitializer implements InitializingBean { + @Value("${nats.url}") + private String url; + + + @Override + public void afterPropertiesSet() throws Exception { + Connection nc = Nats.connect(url); + NatsConnectionHolder.INSTANCE.setConnection(new NatsConnectionImpl(nc)); + } +} From b3a511a7c0e0e953a5e0586e22dfff98bbcdca4d Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 22 Sep 2021 16:49:05 +0800 Subject: [PATCH 256/763] [fix]: device event trigger inherit from pdoduct update --- .../DeviceEventTriggerController.java | 14 ++++++- .../service/ProductAttributeEventService.java | 38 +++++++++++-------- .../service/work/SaveProdAttrEventWorker.java | 1 - 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index 6169c795..14c4c593 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -129,12 +129,24 @@ public ResponseData updateProductEventStatus(@RequestBody @Validated(value = Bas /** * 修改 触发器 * - * @param eventRule 触发器规则 TODO 此处不可以修改 产品上的 告警规则 + * @param eventRule 触发器规则 * @return 触发器ID */ @Transactional @PostMapping("/update") public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) DeviceEventRule eventRule) { + //来自产品的告警规则 只能修改备注 + ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()) + .relationId.eq(eventRule.getDeviceId()).findOne(); + if (null == productEventRelation) { + throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); + } + + if (InheritStatus.YES.getCode().equals(productEventRelation.getInherit())) { + DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).eq("relationId", eventRule.getDeviceId()) + .asUpdate().set("remark", eventRule.getRemark()).update(); + return ResponseData.success(eventRule.getEventRuleId()); + } //step 1: 删除原有的 关联关系 deviceEventRuleService.updateDeviceEventRule(eventRule.getEventRuleId(), eventRule); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java index 5e2d8b76..b5ee6e7f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -9,7 +9,6 @@ import com.zmops.iot.domain.product.Product; import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.domain.product.query.QProduct; -import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.domain.product.query.QProductAttributeEvent; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; @@ -20,7 +19,10 @@ import com.zmops.iot.web.product.dto.ProductAttrEvent; import com.zmops.iot.web.product.dto.ProductTag; import com.zmops.iot.web.product.dto.param.ProductAttrParam; -import com.zmops.iot.web.product.service.work.*; +import com.zmops.iot.web.product.service.work.AsyncAttrEventZbxIdWorker; +import com.zmops.iot.web.product.service.work.SaveProdAttrEventTriggerWorker; +import com.zmops.iot.web.product.service.work.SaveProdAttrEventWorker; +import com.zmops.iot.web.product.service.work.UpdateAttributeEventWorker; import com.zmops.zeus.driver.entity.ZbxProcessingStep; import com.zmops.zeus.driver.service.ZbxItem; import io.ebean.DB; @@ -28,8 +30,6 @@ import org.springframework.stereotype.Service; import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import java.util.stream.Collectors; /** @@ -104,7 +104,7 @@ public List list(ProductAttrParam productAttr) { * @return */ public ProductAttrDto detail(Long attrId) { - ProductAttrDto attr = new QProductAttribute().attrId.eq(attrId).asDto(ProductAttrDto.class).findOne(); + ProductAttrDto attr = new QProductAttributeEvent().attrId.eq(attrId).asDto(ProductAttrDto.class).findOne(); if (null == attr.getZbxId()) { return attr; @@ -184,15 +184,15 @@ private ProductAttributeEvent buildProdAttribute(ProductAttributeEvent prodAttri public String createTrapperItem(ProductAttrEvent productAttr) { String itemName = productAttr.getAttrId() + ""; - String hostId =""; - Device device = new QDevice().deviceId.eq(productAttr.getProductId()).findOne(); - if(null == device){ + String hostId = ""; + Device device = new QDevice().deviceId.eq(productAttr.getProductId()).findOne(); + if (null == device) { Product prod = new QProduct().productId.eq(Long.parseLong(productAttr.getProductId())).findOne(); if (null == prod) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } hostId = prod.getZbxId(); - }else{ + } else { hostId = device.getZbxId(); } @@ -224,11 +224,17 @@ public String createTrapperItem(ProductAttrEvent productAttr) { public ProductAttrEvent updateTrapperItem(ProductAttrEvent productAttr) { ProductAttributeEvent productAttributeEvent = new QProductAttributeEvent().attrId.eq(productAttr.getAttrId()).findOne(); buildProdAttribute(productAttributeEvent, productAttr); - Product prod = new QProduct().productId.eq(Long.parseLong(productAttr.getProductId())).findOne(); - if (null == prod) { - throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); + String hostId = ""; + Device device = new QDevice().deviceId.eq(productAttr.getProductId()).findOne(); + if (null == device) { + Product prod = new QProduct().productId.eq(Long.parseLong(productAttr.getProductId())).findOne(); + if (null == prod) { + throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); + } + hostId = prod.getZbxId(); + } else { + hostId = device.getZbxId(); } - String hostId = prod.getZbxId(); List processingSteps = new ArrayList<>(); if (ToolUtil.isNotEmpty(productAttr.getProcessStepList())) { productAttr.getProcessStepList().forEach(i -> { @@ -272,14 +278,14 @@ public ProductAttrEvent updateTrapperItem(ProductAttrEvent productAttr) { */ public void deleteTrapperItem(ProductAttrEvent productAttr) { - List zbxIds = new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(productAttr.getAttrIds()).findSingleAttributeList(); + List zbxIds = new QProductAttributeEvent().select(QProductAttributeEvent.alias().zbxId).attrId.in(productAttr.getAttrIds()).findSingleAttributeList(); //删除zbx item zbxItem.deleteTrapperItem(zbxIds); //删除 属性 - new QProductAttribute().attrId.in(productAttr.getAttrIds()).delete(); + new QProductAttributeEvent().attrId.in(productAttr.getAttrIds()).delete(); //删除 设备 继承的属性 - new QProductAttribute().templateId.in(productAttr.getAttrIds()).delete(); + new QProductAttributeEvent().templateId.in(productAttr.getAttrIds()).delete(); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java index 63e63061..f5e3911e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java @@ -7,7 +7,6 @@ import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.iot.web.product.dto.ProductAttrEvent; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; From 0cc9aa181f99d028bdcd0828df1fc5fcd9f176dd Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 22 Sep 2021 17:22:00 +0800 Subject: [PATCH 257/763] [feat]: add nats config --- zeus-starter/src/main/assembly/webapp.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zeus-starter/src/main/assembly/webapp.yml b/zeus-starter/src/main/assembly/webapp.yml index 8ec3cbf4..aa376061 100644 --- a/zeus-starter/src/main/assembly/webapp.yml +++ b/zeus-starter/src/main/assembly/webapp.yml @@ -49,3 +49,6 @@ forest: zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:80} zbxApiToken: 3464dee6b3fa3ce4173972e0497d7b84a93bdf8477ff1bdd51a7719cc0db2cd9 + +nats: + url: nats://${NATS_HOST:127.0.0.1}:${NATS_PORT:4222} \ No newline at end of file From 06ef5b7bc4ac046b4f5768cbda75ae3168fbfb93 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 22 Sep 2021 21:33:10 +0800 Subject: [PATCH 258/763] [feat]: edit server-transfer module --- iot-server/server-bootstrap/pom.xml | 18 +- .../src/main/resources/application.yml | 16 +- iot-server/server-transfer/pom.xml | 21 ++ .../transfer/conf/AbstractConfiguration.java | 29 +- .../server/transfer/conf/AgentConstants.java | 2 +- .../server/transfer/conf/CommonConstants.java | 2 +- .../iot/server/transfer/conf/ConfigJetty.java | 115 ++++++++ .../server/transfer/conf/ConfigServlet.java | 109 +++++++ .../server/transfer/conf/ProfileFetcher.java | 40 +++ .../server/transfer/conf/ResponseResult.java | 49 ++++ .../transfer/{ => core}/api/Channel.java | 2 +- .../transfer/{ => core}/api/Filter.java | 2 +- .../transfer/{ => core}/api/Message.java | 2 +- .../transfer/{ => core}/api/Reader.java | 2 +- .../server/transfer/{ => core}/api/Sink.java | 2 +- .../transfer/{ => core}/api/Source.java | 2 +- .../server/transfer/{ => core}/api/Stage.java | 2 +- .../transfer/{ => core}/api/Trigger.java | 2 +- .../transfer/{ => core}/api/Validator.java | 2 +- .../transfer/core/channel/MemoryChannel.java | 111 +++++++ .../transfer/core/common/AbstractDaemon.java | 102 +++++++ .../core/common/AgentThreadFactory.java | 45 +++ .../server/transfer/core/common/Service.java | 42 +++ .../transfer/core/db/BerkeleyDbImp.java | 222 ++++++++++++++ .../zeus/iot/server/transfer/core/db/Db.java | 111 +++++++ .../server/transfer/core/db/JobProfileDb.java | 184 ++++++++++++ .../transfer/core/db/KeyValueEntity.java | 107 +++++++ .../server/transfer/core/db/LocalProfile.java | 72 +++++ .../transfer/core/db/StateSearchKey.java | 32 ++ .../transfer/core/db/TriggerProfileDb.java | 84 ++++++ .../{ => core}/exception/FileException.java | 2 +- .../{ => core}/filter/DateFormatRegex.java | 9 +- .../server/transfer/core/job/CommandDb.java | 90 ++++++ .../transfer/core/job/CommandEntity.java | 50 ++++ .../iot/server/transfer/core/job/Job.java | 97 ++++++ .../server/transfer/core/job/JobManager.java | 252 ++++++++++++++++ .../server/transfer/core/job/JobMetrics.java | 49 ++++ .../server/transfer/core/job/JobWrapper.java | 138 +++++++++ .../transfer/core/manager/AgentManager.java | 200 +++++++++++++ .../{ => core}/message/DefaultMessage.java | 4 +- .../transfer/core/message/EndMessage.java | 40 +++ .../core/metrics/AgentDynamicMBean.java | 126 ++++++++ .../server/transfer/core/metrics/Metric.java | 63 ++++ .../core/metrics/MetricException.java | 29 ++ .../transfer/core/metrics/MetricSnapshot.java | 22 ++ .../server/transfer/core/metrics/Metrics.java | 52 ++++ .../core/metrics/MetricsRegister.java | 148 ++++++++++ .../transfer/core/metrics/MutableMetric.java | 25 ++ .../iot/server/transfer/core/metrics/Tag.java | 40 +++ .../core/metrics/counter/Counter.java | 37 +++ .../core/metrics/counter/CounterInt.java | 41 +++ .../core/metrics/counter/CounterLong.java | 44 +++ .../transfer/core/metrics/gauge/Gauge.java | 49 ++++ .../transfer/core/metrics/gauge/GaugeInt.java | 57 ++++ .../core/metrics/gauge/GaugeLong.java | 57 ++++ .../core/metrics/meta/MetricMeta.java | 77 +++++ .../core/metrics/meta/MetricsMeta.java | 61 ++++ .../transfer/{ => core}/sink/ConsoleSink.java | 6 +- .../{ => core}/source/TextFileSource.java | 17 +- .../source/reader/TextFileReader.java | 16 +- .../core/state/AbstractStateWrapper.java | 95 ++++++ .../iot/server/transfer/core/state/State.java | 36 +++ .../transfer/core/state/StateCallback.java | 26 ++ .../core/state/StateTransferException.java | 26 ++ .../iot/server/transfer/core/task/Task.java | 76 +++++ .../transfer/core/task/TaskManager.java | 253 ++++++++++++++++ .../transfer/core/task/TaskMetrics.java | 56 ++++ .../core/task/TaskPositionManager.java | 153 ++++++++++ .../transfer/core/task/TaskWrapper.java | 196 +++++++++++++ .../core/trigger/DirectoryTrigger.java | 275 ++++++++++++++++++ .../{ => core}/trigger/PathPattern.java | 15 +- .../transfer/core/trigger/TriggerManager.java | 246 ++++++++++++++++ .../transfer/{ => core}/utils/AgentUtils.java | 2 +- .../transfer/{ => core}/utils/ByteUtil.java | 2 +- .../{ => core}/utils/PluginUtils.java | 11 +- .../validator/PatternValidator.java | 4 +- .../{ => core}/validator/PrefixValidator.java | 4 +- .../transfer/module/ServerTransferModule.java | 21 ++ .../provider/ServerTransferConfig.java | 13 + .../provider/ServerTransferProvider.java | 51 ++++ ...eus.iot.server.library.module.ModuleDefine | 19 ++ ...s.iot.server.library.module.ModuleProvider | 19 ++ .../iot/web/alarm/service/MessageService.java | 6 + 83 files changed, 4954 insertions(+), 80 deletions(-) create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ConfigJetty.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ConfigServlet.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ProfileFetcher.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ResponseResult.java rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/api/Channel.java (96%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/api/Filter.java (94%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/api/Message.java (95%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/api/Reader.java (96%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/api/Sink.java (95%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/api/Source.java (95%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/api/Stage.java (95%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/api/Trigger.java (96%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/api/Validator.java (95%) create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AbstractDaemon.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AgentThreadFactory.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/Service.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/Db.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/KeyValueEntity.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/LocalProfile.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/StateSearchKey.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/TriggerProfileDb.java rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/exception/FileException.java (94%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/filter/DateFormatRegex.java (96%) create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandEntity.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/AgentManager.java rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/message/DefaultMessage.java (92%) create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/EndMessage.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/AgentDynamicMBean.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metric.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricException.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricSnapshot.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metrics.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricsRegister.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MutableMetric.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Tag.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/Counter.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterInt.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterLong.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/Gauge.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeInt.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeLong.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricMeta.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricsMeta.java rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/sink/ConsoleSink.java (88%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/source/TextFileSource.java (85%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/source/reader/TextFileReader.java (90%) create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/AbstractStateWrapper.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/State.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateCallback.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateTransferException.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/trigger/PathPattern.java (94%) create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/utils/AgentUtils.java (99%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/utils/ByteUtil.java (99%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/utils/PluginUtils.java (95%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/validator/PatternValidator.java (89%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{ => core}/validator/PrefixValidator.java (89%) create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/module/ServerTransferModule.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferConfig.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java create mode 100644 iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine create mode 100644 iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider diff --git a/iot-server/server-bootstrap/pom.xml b/iot-server/server-bootstrap/pom.xml index c15ccaee..f9890b0f 100644 --- a/iot-server/server-bootstrap/pom.xml +++ b/iot-server/server-bootstrap/pom.xml @@ -26,7 +26,6 @@ snakeyaml 1.26 - com.zmops server-health-checker @@ -42,7 +41,6 @@ telemetry-prometheus ${project.version} - com.zmops server-sender @@ -63,18 +61,20 @@ mqtt-receiver-plugin ${project.version} - - org.apache.camel - camel-zabbix-agent + com.zmops + server-tdengine-plugin + ${project.version} - com.zmops - server-tdengine-plugin - 1.0-beta + server-transfer + ${project.version} + + + org.apache.camel + camel-zabbix-agent - diff --git a/iot-server/server-bootstrap/src/main/resources/application.yml b/iot-server/server-bootstrap/src/main/resources/application.yml index 4f68df85..b442d597 100644 --- a/iot-server/server-bootstrap/src/main/resources/application.yml +++ b/iot-server/server-bootstrap/src/main/resources/application.yml @@ -26,8 +26,7 @@ receiver-mqtt: port: ${ZS_RECEIVER_MQTT_PORT:1883} host: ${ZS_RECEIVER_MQTT_HOST:127.0.0.1} - -# 核心模块 +# core module config core: selector: ${ZS_CORE:default} default: @@ -42,21 +41,28 @@ core: restAcceptQueueSize: ${ZS_CORE_REST_JETTY_QUEUE_SIZE:0} httpMaxRequestHeaderSize: ${ZS_CORE_HTTP_MAX_REQUEST_HEADER_SIZE:8192} + +# ndjson file read realtime +server-transfer: + selector: ${ZS_SERVER_TRANSFER:default} + default: + +# tdengine storage realtime storage: - selector: ${SW_STORAGE:tdengine} + selector: ${ZS_STORAGE:tdengine} tdengine: url: ${ZS_STORAGE_TDENGINE_URL:jdbc:TAOS://192.168.1.1:6030/zeus_data} # TDEngine jdbcUrl user: ${ZS_STORAGE_TDENGINE_USER:root} password: ${ZS_STORAGE_TDENGINE_PASSWORD:taosdata} -# 健康检查 +# health check health-checker: selector: ${ZS_HEALTH_CHECKER:default} default: checkIntervalSeconds: ${ZS_HEALTH_CHECKER_INTERVAL_SECONDS:5} -# 健康遥测 +# health telemetry telemetry: selector: ${ZS_TELEMETRY:prometheus} none: diff --git a/iot-server/server-transfer/pom.xml b/iot-server/server-transfer/pom.xml index c34f782b..9b7a1e56 100644 --- a/iot-server/server-transfer/pom.xml +++ b/iot-server/server-transfer/pom.xml @@ -33,6 +33,27 @@ commons-io 1.3.2 + + com.zmops + library-module + 1.0-beta + + + je + com.sleepycat + 18.3.12 + + + + org.eclipse.jetty + jetty-server + 9.4.34.v20201102 + + + org.eclipse.jetty + jetty-servlet + 9.4.34.v20201102 + \ No newline at end of file diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java index e7e35fc8..00024d15 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java @@ -18,7 +18,7 @@ package com.zmops.zeus.iot.server.transfer.conf; import com.google.gson.*; -import com.zmops.zeus.iot.server.transfer.utils.AgentUtils; +import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; import org.apache.commons.lang3.StringUtils; @@ -33,12 +33,14 @@ public abstract class AbstractConfiguration { - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractConfiguration.class); + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractConfiguration.class); private static final JsonParser JSON_PARSER = new JsonParser(); private final Map configStorage = new HashMap<>(); - /** get config file by class loader **/ + /** + * get config file by class loader + **/ private ClassLoader classLoader; public AbstractConfiguration() { @@ -50,6 +52,7 @@ public AbstractConfiguration() { /** * Check whether all required keys exist + * * @return true if all key exist else false. */ public abstract boolean allRequiredKeyExist(); @@ -58,7 +61,7 @@ public AbstractConfiguration() { * support load config file from json/properties file. * * @param fileName - file name - * @param isJson - whether is json file + * @param isJson - whether is json file */ private void loadResource(String fileName, boolean isJson) { Reader reader = null; @@ -73,7 +76,7 @@ private void loadResource(String fileName, boolean isJson) { Properties properties = new Properties(); properties.load(reader); properties.forEach((key, value) -> configStorage.put((String) key, - new JsonPrimitive((String) value))); + new JsonPrimitive((String) value))); } } } catch (Exception ioe) { @@ -110,8 +113,8 @@ void loadPropertiesResource(String fileName) { * Convert json string to map * * @param keyDeptPath - map - * @param dept - json dept - * @param tmpElement - json element + * @param dept - json dept + * @param tmpElement - json element */ void updateConfig(HashMap keyDeptPath, int dept, JsonElement tmpElement) { if (tmpElement instanceof JsonObject) { @@ -122,7 +125,7 @@ void updateConfig(HashMap keyDeptPath, int dept, JsonElement tm } } else if (tmpElement instanceof JsonArray) { JsonArray tmpJsonArray = tmpElement.getAsJsonArray(); - String lastKey = keyDeptPath.getOrDefault(dept - 1, ""); + String lastKey = keyDeptPath.getOrDefault(dept - 1, ""); for (int index = 0; index < tmpJsonArray.size(); index++) { keyDeptPath.put(dept - 1, lastKey + "[" + index + "]"); updateConfig(keyDeptPath, dept, tmpJsonArray.get(index)); @@ -142,7 +145,7 @@ void updateConfig(HashMap keyDeptPath, int dept, JsonElement tm /** * get int from config * - * @param key - key + * @param key - key * @param defaultValue - default value * @return value */ @@ -169,7 +172,7 @@ public int getInt(String key) { /** * get long * - * @param key - key + * @param key - key * @param defaultValue - default value * @return long */ @@ -181,7 +184,7 @@ public long getLong(String key, long defaultValue) { /** * get boolean * - * @param key - key + * @param key - key * @param defaultValue - default value * @return boolean */ @@ -193,7 +196,7 @@ public boolean getBoolean(String key, boolean defaultValue) { /** * get string * - * @param key - key + * @param key - key * @param defaultValue - default value * @return string */ @@ -230,7 +233,7 @@ public boolean hasKey(String key) { /** * set key/value * - * @param key - key + * @param key - key * @param value - value */ public void set(String key, String value) { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AgentConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AgentConstants.java index 0e7eb65c..7669f586 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AgentConstants.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AgentConstants.java @@ -17,7 +17,7 @@ package com.zmops.zeus.iot.server.transfer.conf; -import com.zmops.zeus.iot.server.transfer.utils.AgentUtils; +import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; public class AgentConstants { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java index 2facb49d..3b667c78 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java @@ -17,7 +17,7 @@ package com.zmops.zeus.iot.server.transfer.conf; -import com.zmops.zeus.iot.server.transfer.utils.AgentUtils; +import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; public class CommonConstants { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ConfigJetty.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ConfigJetty.java new file mode 100644 index 00000000..c7cf2b29 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ConfigJetty.java @@ -0,0 +1,115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.conf; + + +import com.zmops.zeus.iot.server.transfer.core.job.JobManager; +import com.zmops.zeus.iot.server.transfer.core.trigger.TriggerManager; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ServletHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.Closeable; + +import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_TRIGGER; + +/** + * start http server and get job/agent config via http + */ +public class ConfigJetty implements Closeable { + + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigJetty.class); + + private final AgentConfiguration conf; + private final Server server; + private final JobManager jobManager; + private final TriggerManager triggerManager; + + public ConfigJetty(JobManager jobManager, TriggerManager triggerManager) { + this.conf = AgentConfiguration.getAgentConf(); + this.jobManager = jobManager; + this.triggerManager = triggerManager; + server = new Server(); + try { + initJetty(); + } catch (Exception ex) { + LOGGER.error("exception caught", ex); + } + } + + private void initJetty() throws Exception { + ServerConnector connector = new ServerConnector(this.server); + connector.setPort(conf.getInt(AgentConstants.AGENT_HTTP_PORT, AgentConstants.DEFAULT_AGENT_HTTP_PORT)); + server.setConnectors(new Connector[]{connector}); + + ServletHandler servletHandler = new ServletHandler(); + ServletHolder holder = new ServletHolder(new ConfigServlet(this)); + servletHandler.addServletWithMapping(holder, "/config/*"); + server.setHandler(servletHandler); + server.start(); + } + + public void storeJobConf(JobProfile jobProfile) { + // store job conf to bdb + if (jobProfile != null) { + // trigger job is a special kind of job + if (jobProfile.hasKey(JOB_TRIGGER)) { + triggerManager.submitTrigger(TriggerProfile.parseJsonStr(jobProfile.toJsonStr())); + } else { + jobManager.submitJobProfile(jobProfile); + } + } + } + + public void storeAgentConf(String confJsonStr) { + // store agent conf to local file + AgentConfiguration conf = AgentConfiguration.getAgentConf(); + conf.loadJsonStrResource(confJsonStr); + conf.flushToLocalPropertiesFile(); + } + + /** + * delete job from conf + * + * @param jobProfile + */ + public void deleteJobConf(JobProfile jobProfile) { + if (jobProfile != null) { + if (jobProfile.hasKey(JOB_TRIGGER)) { + triggerManager.deleteTrigger(TriggerProfile.parseJobProfile(jobProfile).getTriggerId()); + } else { + jobManager.deleteJob(jobProfile.getInstanceId()); + } + } + } + + @Override + public void close() { + try { + if (this.server != null) { + this.server.stop(); + } + } catch (Exception ex) { + LOGGER.error("exception caught", ex); + } + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ConfigServlet.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ConfigServlet.java new file mode 100644 index 00000000..16765458 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ConfigServlet.java @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.conf; + +import com.google.gson.Gson; +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.PrintWriter; + +public class ConfigServlet extends HttpServlet { + + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigServlet.class); + + private static final String CONTENT_TYPE = "application/json"; + private static final String CHARSET_TYPE = "UTF-8"; + private static final String JOB_TYPE = "job"; + private static final String AGENT_TYPE = "agent"; + private static final String TRIGGER_TYPE = "trigger"; + private static final String OP_TYPE = "op"; + private static final String ADD_OP = "add"; + private static final String DELETE_OP = "delete"; + private final Gson gson = new Gson(); + private final ConfigJetty configHandler; + + public ConfigServlet(ConfigJetty configHandler) { + this.configHandler = configHandler; + } + + public void responseToJson(HttpServletResponse response, + ResponseResult result) throws IOException { + response.setContentType(CONTENT_TYPE); + response.setCharacterEncoding(CHARSET_TYPE); + String jsonStr = gson.toJson(result); + PrintWriter out = response.getWriter(); + out.print(jsonStr); + out.flush(); + } + + /** + * handle path of "/config/job" + * @param jobProfileStr - job profile string + */ + private void handleJob(String jobProfileStr) { + JobProfile jobProfile = JobProfile.parseJsonStr(jobProfileStr); + + String op = jobProfile.get(OP_TYPE); + + if (ADD_OP.equals(op)) { + configHandler.storeJobConf(jobProfile); + } else if (DELETE_OP.equals(op)) { + configHandler.deleteJobConf(jobProfile); + } + } + + private void handleAgent(String agentProfileStr) { + // TODO: handle agent + } + + /** + * handle post requests. + * + * @param req - request + * @param resp - response + */ + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { + String pathInfo = req.getPathInfo(); + ResponseResult responseResult = new ResponseResult(0, ""); + + try (BufferedReader reader = req.getReader()) { + String configJsonStr = IOUtils.toString(reader); + LOGGER.info("Getting request {}", configJsonStr); + // path is "/config/job" + if (pathInfo.endsWith(JOB_TYPE)) { + handleJob(configJsonStr); + } else if (pathInfo.endsWith(AGENT_TYPE)) { + handleAgent(configJsonStr); + } else { + responseResult.setCode(-1).setMessage("child path is not correct"); + } + } catch (Exception ex) { + LOGGER.error("error while handle post", ex); + responseResult.setCode(-1).setMessage(ex.getMessage()); + } + responseToJson(resp, responseResult); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ProfileFetcher.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ProfileFetcher.java new file mode 100644 index 00000000..50b01838 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ProfileFetcher.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.conf; + +import com.zmops.zeus.iot.server.transfer.core.common.Service; + +import java.util.List; + +/** + * fetch profile from other system, communicate with json format string + */ +public interface ProfileFetcher extends Service { + + /** + * get job profiles + * @return - job profile list + */ + List getJobProfiles(); + + /** + * get trigger profiles + * @return - trigger profile lisy + */ + List getTriggerProfiles(); +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ResponseResult.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ResponseResult.java new file mode 100644 index 00000000..0d9671fb --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ResponseResult.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.conf; + +/** + * response json for http requests. + */ +public class ResponseResult { + private int code; + private String message; + + public int getCode() { + return code; + } + + public ResponseResult(int code, String message) { + this.code = code; + this.message = message; + } + + public ResponseResult setCode(int code) { + this.code = code; + return this; + } + + public String getMessage() { + return message; + } + + public ResponseResult setMessage(String message) { + this.message = message; + return this; + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Channel.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Channel.java similarity index 96% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Channel.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Channel.java index 86c74982..03519125 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Channel.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Channel.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.api; +package com.zmops.zeus.iot.server.transfer.core.api; import java.util.concurrent.TimeUnit; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Filter.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Filter.java similarity index 94% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Filter.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Filter.java index 2a90b3e5..00535959 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Filter.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Filter.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.api; +package com.zmops.zeus.iot.server.transfer.core.api; /** * filter for source split diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Message.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Message.java similarity index 95% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Message.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Message.java index ef5a170d..f92c8edd 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Message.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Message.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.api; +package com.zmops.zeus.iot.server.transfer.core.api; import java.util.Map; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Reader.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Reader.java similarity index 96% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Reader.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Reader.java index c82bf54b..63ef33de 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Reader.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Reader.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.api; +package com.zmops.zeus.iot.server.transfer.core.api; /** * Reader reads data and provides condition whether the reading action is finished. It's called at diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Sink.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Sink.java similarity index 95% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Sink.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Sink.java index 6b55a0c8..04bb8fcc 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Sink.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Sink.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.api; +package com.zmops.zeus.iot.server.transfer.core.api; /** * Sink data to remote data center diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Source.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Source.java similarity index 95% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Source.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Source.java index 1209cc75..dff42e4f 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Source.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Source.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.api; +package com.zmops.zeus.iot.server.transfer.core.api; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Stage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Stage.java similarity index 95% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Stage.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Stage.java index cc4fdda3..82f5f2de 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Stage.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Stage.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.api; +package com.zmops.zeus.iot.server.transfer.core.api; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Trigger.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Trigger.java similarity index 96% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Trigger.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Trigger.java index ef4ebd9c..d9c71e34 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Trigger.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Trigger.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.api; +package com.zmops.zeus.iot.server.transfer.core.api; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Validator.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Validator.java similarity index 95% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Validator.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Validator.java index 8ed0c295..45436c0f 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Validator.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Validator.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.api; +package com.zmops.zeus.iot.server.transfer.core.api; /** * For every message, there might be validators to filter required ones diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java new file mode 100644 index 00000000..8a003878 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.channel; + + +import com.zmops.zeus.iot.server.transfer.core.api.Channel; +import com.zmops.zeus.iot.server.transfer.core.api.Message; +import com.zmops.zeus.iot.server.transfer.conf.AgentConstants; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +public class MemoryChannel implements Channel { + + private static final Logger LOGGER = LoggerFactory.getLogger(MemoryChannel.class); + + private LinkedBlockingQueue queue; + +// private final PluginMetric metric = new PluginMetric(); + + /** + * {@inheritDoc} + */ + @Override + public void push(Message message) { + try { + if (message != null) { +// metric.readNum.incr(); + queue.put(message); +// metric.readSuccessNum.incr(); + } + } catch (InterruptedException ex) { +// metric.readFailedNum.incr(); + Thread.currentThread().interrupt(); + } + } + + @Override + public boolean push(Message message, long timeout, TimeUnit unit) { + try { + if (message != null) { +// metric.readNum.incr(); + boolean result = queue.offer(message, timeout, unit); + if (result) { +// metric.readSuccessNum.incr(); + } else { +// metric.readFailedNum.incr(); + } + return result; + } + } catch (InterruptedException ex) { +// metric.readFailedNum.incr(); + Thread.currentThread().interrupt(); + } + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public Message pull(long timeout, TimeUnit unit) { + try { + Message message = queue.poll(timeout, unit); + if (message != null) { +// metric.sendSuccessNum.incr(); + } + return message; + } catch (InterruptedException ex) { +// metric.sendFailedNum.incr(); + Thread.currentThread().interrupt(); + throw new IllegalStateException(ex); + } + } + + @Override + public void init(JobProfile jobConf) { + queue = new LinkedBlockingQueue<>( + jobConf.getInt(AgentConstants.CHANNEL_MEMORY_CAPACITY, + AgentConstants.DEFAULT_CHANNEL_MEMORY_CAPACITY)); + } + + @Override + public void destroy() { + if (queue != null) { + queue.clear(); + } +// LOGGER.info("destroy channel, memory channel metric, readNum: {}, readSuccessNum: {}, " +// + "readFailedNum: {}, sendSuccessNum: {}, sendFailedNum: {}", +// metric.readNum.snapshot(), metric.readSuccessNum.snapshot(), metric.readFailedNum.snapshot(), +// metric.sendSuccessNum.snapshot(), metric.sendFailedNum.snapshot()); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AbstractDaemon.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AbstractDaemon.java new file mode 100644 index 00000000..7263d714 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AbstractDaemon.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.common; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.*; + +/** + * Providing work threads management, those threads run + * periodically until agent is stopped. + */ +public abstract class AbstractDaemon implements Service { + + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractDaemon.class); + + /** + * worker thread pool, share it + **/ + private static final ExecutorService WORKER_SERVICES = new ThreadPoolExecutor( + 0, + Integer.MAX_VALUE, + 60L, + TimeUnit.SECONDS, + new SynchronousQueue(), + new AgentThreadFactory("AbstractDaemon") + ); + + private final List> workerFutures; + + private boolean runnable = true; + + public AbstractDaemon() { + this.workerFutures = new ArrayList<>(); + } + + /** + * Whether threads can in running state with while loop. + * + * @return - true if threads can run + */ + public boolean isRunnable() { + return runnable; + } + + /** + * Stop running threads. + */ + public void stopRunningThreads() { + runnable = false; + } + + /** + * Submit work thread to thread pool. + * + * @param worker - work thread + */ + public void submitWorker(Runnable worker) { + CompletableFuture future = CompletableFuture.runAsync(worker, WORKER_SERVICES); + workerFutures.add(future); + LOGGER.info("{} running worker number is {}", this.getClass().getName(), + workerFutures.size()); + } + + /** + * Wait for threads finish. + */ + @Override + public void join() { + for (CompletableFuture future : workerFutures) { + future.join(); + } + } + + /** + * Stop thread pool and running threads if they're in the running state. + */ + public void waitForTerminate() { + // stop running threads. + if (isRunnable()) { + stopRunningThreads(); + } + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AgentThreadFactory.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AgentThreadFactory.java new file mode 100644 index 00000000..3bedd92f --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AgentThreadFactory.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.common; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +public class AgentThreadFactory implements ThreadFactory { + + private static final Logger LOGGER = LoggerFactory.getLogger(AgentThreadFactory.class); + + private final AtomicInteger mThreadNum = new AtomicInteger(1); + + private final String threadType; + + public AgentThreadFactory(String threadType) { + this.threadType = threadType; + } + + @Override + public Thread newThread(Runnable r) { + Thread t = new Thread(r, threadType + "-running-thread-" + mThreadNum.getAndIncrement()); + LOGGER.debug("{} created", t.getName()); + return t; + } +} \ No newline at end of file diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/Service.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/Service.java new file mode 100644 index 00000000..91791814 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/Service.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.common; + +/** + * Service lifecycle interface. + */ +public interface Service { + + /** + * start service + * @throws Exception + */ + void start() throws Exception; + + /** + * stop service + * @throws Exception + */ + void stop() throws Exception; + + /** + * join and wait until getting signal + * @throws Exception + */ + void join() throws Exception; +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java new file mode 100644 index 00000000..8970b51c --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java @@ -0,0 +1,222 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.db; + +import com.sleepycat.je.Environment; +import com.sleepycat.je.EnvironmentConfig; +import com.sleepycat.persist.*; + +import com.zmops.zeus.iot.server.transfer.conf.AgentConfiguration; +import com.zmops.zeus.iot.server.transfer.conf.AgentConstants; +import com.zmops.zeus.iot.server.transfer.conf.CommonConstants; +import com.zmops.zeus.iot.server.transfer.core.job.CommandEntity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import static java.util.Objects.requireNonNull; + +/** + * DB implement based on berkeley db. + */ +public class BerkeleyDbImp implements Db { + + private static final Logger LOGGER = LoggerFactory.getLogger(BerkeleyDbImp.class); + + private final EntityStore jobStore; + private final EntityStore commandStore; + + private final PrimaryIndex primaryIndex; + private final SecondaryIndex secondaryIndex; + private final PrimaryIndex commandPrimaryIndex; + + private final SecondaryIndex fileNameSecondaryIndex; + private final SecondaryIndex commandSecondaryIndex; + + private final AgentConfiguration agentConf; + + public BerkeleyDbImp() { + + this.agentConf = AgentConfiguration.getAgentConf(); + + StoreConfig storeConfig = initStoreConfig(); + Environment environment = initEnv(); + + String instanceName = agentConf.get(AgentConstants.AGENT_DB_INSTANCE_NAME, AgentConstants.DEFAULT_AGENT_DB_INSTANCE_NAME); + + this.jobStore = new EntityStore(environment, instanceName, storeConfig); + this.commandStore = new EntityStore(environment, CommonConstants.COMMAND_STORE_INSTANCE_NAME, storeConfig); + + commandPrimaryIndex = this.commandStore.getPrimaryIndex(String.class, CommandEntity.class); + + commandSecondaryIndex = commandStore.getSecondaryIndex(commandPrimaryIndex, Boolean.class, "isAcked"); + + primaryIndex = this.jobStore.getPrimaryIndex(String.class, KeyValueEntity.class); + secondaryIndex = this.jobStore.getSecondaryIndex(primaryIndex, StateSearchKey.class, "stateSearchKey"); + + fileNameSecondaryIndex = this.jobStore.getSecondaryIndex(primaryIndex, String.class, "fileName"); + } + + /** + * init store by config + * + * @return store config + */ + private StoreConfig initStoreConfig() { + return new StoreConfig() + .setReadOnly(agentConf.getBoolean(AgentConstants.AGENT_LOCAL_STORE_READONLY, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_READONLY)) + .setAllowCreate(!agentConf.getBoolean(AgentConstants.AGENT_LOCAL_STORE_READONLY, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_READONLY)) + .setTransactional(agentConf.getBoolean(AgentConstants.AGENT_LOCAL_STORE_TRANSACTIONAL, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_TRANSACTIONAL)); + } + + /** + * init local bdb path and get it. + * + * @return local path. + */ + private File tryToInitAndGetPath() { + String storePath = agentConf.get(AgentConstants.AGENT_LOCAL_STORE_PATH, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_PATH); + String parentPath = agentConf.get(AgentConstants.AGENT_HOME, AgentConstants.DEFAULT_AGENT_HOME); + + File finalPath = new File(parentPath, storePath); + try { + boolean result = finalPath.mkdirs(); + LOGGER.info("try to create local path {}, result is {}", finalPath, result); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + return finalPath; + } + + /** + * init env by config + * + * @return env config + */ + private Environment initEnv() { + EnvironmentConfig envConfig = new EnvironmentConfig() + .setReadOnly(agentConf.getBoolean(AgentConstants.AGENT_LOCAL_STORE_READONLY, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_READONLY)) + .setAllowCreate(!agentConf.getBoolean(AgentConstants.AGENT_LOCAL_STORE_READONLY, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_READONLY)) + .setTransactional(agentConf.getBoolean(AgentConstants.AGENT_LOCAL_STORE_TRANSACTIONAL, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_TRANSACTIONAL)) + .setLockTimeout(agentConf.getInt(AgentConstants.AGENT_LOCAL_STORE_LOCK_TIMEOUT, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_LOCK_TIMEOUT), TimeUnit.MILLISECONDS); + + envConfig.setTxnNoSyncVoid(agentConf.getBoolean(AgentConstants.AGENT_LOCAL_STORE_NO_SYNC_VOID, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_NO_SYNC_VOID)); + envConfig.setTxnWriteNoSyncVoid(agentConf.getBoolean(AgentConstants.AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID)); + return new Environment(tryToInitAndGetPath(), envConfig); + } + + @Override + public KeyValueEntity get(String key) { + requireNonNull(key); + return primaryIndex.get(key); + } + + + @Override + public CommandEntity getCommand(String commandId) { + requireNonNull(commandId); + return commandPrimaryIndex.get(commandId); + } + + + @Override + public CommandEntity putCommand(CommandEntity entity) { + requireNonNull(entity); + return commandPrimaryIndex.put(entity); + } + + @Override + public void set(KeyValueEntity entity) { + requireNonNull(entity); + primaryIndex.put(entity); + } + + @Override + public KeyValueEntity put(KeyValueEntity entity) { + requireNonNull(entity); + return primaryIndex.put(entity); + } + + @Override + public KeyValueEntity remove(String key) { + requireNonNull(key); + KeyValueEntity entity = primaryIndex.get(key); + primaryIndex.delete(key); + return entity; + } + + @Override + public List search(StateSearchKey searchKey) { + requireNonNull(searchKey); + List ret = new ArrayList<>(); + + try (EntityCursor children = secondaryIndex.subIndex(searchKey).entities()) { + for (KeyValueEntity entity : children) { + ret.add(entity); + } + } + return ret; + } + + @Override + public List searchCommands(boolean isAcked) { + requireNonNull(isAcked); + List ret = new ArrayList<>(); + try (EntityCursor children = commandSecondaryIndex.subIndex(isAcked).entities()) { + for (CommandEntity entity : children) { + ret.add(entity); + } + } + return ret; + } + + @Override + public KeyValueEntity searchOne(StateSearchKey searchKey) { + requireNonNull(searchKey); + return secondaryIndex.get(searchKey); + } + + @Override + public KeyValueEntity searchOne(String fileName) { + requireNonNull(fileName); + return fileNameSecondaryIndex.get(fileName); + } + + @Override + public List findAll(String prefix) { + requireNonNull(prefix); + List ret = new ArrayList<>(); + try (EntityCursor children = primaryIndex.entities()) { + for (KeyValueEntity entity : children) { + if (entity.getKey().startsWith(prefix)) { + ret.add(entity); + } + } + } + return ret; + } + + @Override + public void close() { + jobStore.close(); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/Db.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/Db.java new file mode 100644 index 00000000..3d83a9cf --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/Db.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.db; + +import com.zmops.zeus.iot.server.transfer.core.job.CommandEntity; + +import javax.management.openmbean.KeyAlreadyExistsException; +import java.io.Closeable; +import java.util.List; + +/** + * local storage for key/value. + */ +public interface Db extends Closeable { + + + abstract KeyValueEntity get(String key); + + /** + * get command by command id + * @param commandId + * @return + */ + CommandEntity getCommand(String commandId); + + /** + * put command entity in db + * @param entity + * @return + */ + CommandEntity putCommand(CommandEntity entity); + + /** + * store keyValue, if key has exists, throw exception. + * + * @param entity - key/value + * @throws NullPointerException key should not be null + * @throws KeyAlreadyExistsException key already exists + */ + void set(KeyValueEntity entity); + + /** + * store keyValue, if key has exists, overwrite it. + * + * @param entity - key/value + * @return null or old value which is overwritten. + * @throws NullPointerException key should not be null. + */ + KeyValueEntity put(KeyValueEntity entity); + + /** + * remove keyValue by key. + * + * @param key - key + * @return key/value + * @throws NullPointerException key should not be null. + */ + KeyValueEntity remove(String key); + + /** + * search keyValue list by search key. + * + * @param searchKey - search keys. + * @return key/value list + * @throws NullPointerException search key should not be null. + */ + List search(StateSearchKey searchKey); + + /** + * search commands using ack status + * @param isAcked + * @return + */ + List searchCommands(boolean isAcked); + + /** + * search one keyValue by search key + * @param searchKey - search key + * @return null or keyValue + */ + KeyValueEntity searchOne(StateSearchKey searchKey); + + /** + * search one keyValue by fileName + * @param fileName + * @return + */ + KeyValueEntity searchOne(String fileName); + + /** + * find all by prefix key. + * @param prefix - prefix string + * @return list of k/v + */ + List findAll(String prefix); +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java new file mode 100644 index 00000000..1372e313 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java @@ -0,0 +1,184 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + + */ + +package com.zmops.zeus.iot.server.transfer.core.db; + + +import com.zmops.zeus.iot.server.transfer.conf.JobConstants; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +/** + * Wrapper for job conf persistence. + */ +public class JobProfileDb { + private static final Logger LOGGER = LoggerFactory.getLogger(JobProfileDb.class); + private final Db db; + + public JobProfileDb(Db db) { + this.db = db; + } + + /** + * get job which in accepted state + * @return null or job conf + */ + public JobProfile getAcceptedJob() { + return getJob(StateSearchKey.ACCEPTED); + } + + public List getAcceptedJobs() { + return getJobs(StateSearchKey.ACCEPTED); + } + + /** + * update job state and search it by key name + * @param jobInstanceId - job key name + * @param stateSearchKey - job state + */ + public void updateJobState(String jobInstanceId, StateSearchKey stateSearchKey) { + KeyValueEntity entity = db.get(jobInstanceId); + if (entity != null) { + entity.setStateSearchKey(stateSearchKey); + db.put(entity); + } + } + + /** + * store job profile + * @param jobProfile - job profile + */ + public void storeJobFirstTime(JobProfile jobProfile) { + if (jobProfile.allRequiredKeyExist()) { + String keyName = jobProfile.get(JobConstants.JOB_INSTANCE_ID); + jobProfile.setLong(JobConstants.JOB_STORE_TIME, System.currentTimeMillis()); + KeyValueEntity entity = new KeyValueEntity(keyName, + jobProfile.toJsonStr(), jobProfile.get(JobConstants.JOB_DIR_FILTER_PATTERN)); + entity.setStateSearchKey(StateSearchKey.ACCEPTED); + db.put(entity); + } + } + + /** + * update job profile + * @param jobProfile + */ + public void updateJobProfile(JobProfile jobProfile) { + String instanceId = jobProfile.getInstanceId(); + KeyValueEntity entity = db.get(instanceId); + if (entity == null) { + LOGGER.warn("job profile {} doesn't exist, update job profile fail {}", instanceId, jobProfile.toJsonStr()); + return; + } + entity.setJsonValue(jobProfile.toJsonStr()); + db.put(entity); + } + + /** + * check whether job is finished, note that non-exist job is regarded as finished. + * @param jobProfile + * @return + */ + public boolean checkJobfinished(JobProfile jobProfile) { + KeyValueEntity entity = db.get(jobProfile.getInstanceId()); + if (entity == null) { + LOGGER.info("job profile {} doesn't exist", jobProfile.getInstanceId()); + return true; + } + return entity.checkFinished(); + } + + public void deleteJob(String keyName) { + db.remove(keyName); + } + + public JobProfile getJobProfile(String jobId) { + KeyValueEntity keyValueEntity = db.get(jobId); + if (keyValueEntity != null) { + return keyValueEntity.getAsJobProfile(); + } + return null; + } + + public void removeExpireJobs(long expireTime) { + // remove finished tasks + List successEntityList = db.search(StateSearchKey.SUCCESS); + List failedEntityList = db.search(StateSearchKey.FAILED); + List entityList = new ArrayList<>(successEntityList); + entityList.addAll(failedEntityList); + for (KeyValueEntity entity : entityList) { + if (entity.getKey().startsWith(JobConstants.JOB_ID_PREFIX)) { + JobProfile profile = entity.getAsJobProfile(); + long storeTime = profile.getLong(JobConstants.JOB_STORE_TIME, 0); + long currentTime = System.currentTimeMillis(); + if (storeTime == 0 || currentTime - storeTime > expireTime) { + LOGGER.info("delete job {} because of timeout store time: {}, expire time: {}", + entity.getKey(), storeTime, expireTime); + deleteJob(entity.getKey()); + } + } + } + } + + /** + * get job conf by state + * @param stateSearchKey - state index for searching. + * @return + */ + public JobProfile getJob(StateSearchKey stateSearchKey) { + KeyValueEntity entity = db.searchOne(stateSearchKey); + if (entity != null && entity.getKey().startsWith(JobConstants.JOB_ID_PREFIX)) { + return entity.getAsJobProfile(); + } + return null; + } + + + /** + * get job reading specific file + * @param fileName + * @return + */ + public JobProfile getJob(String fileName) { + KeyValueEntity entity = db.searchOne(fileName); + if (entity != null && entity.getKey().startsWith(JobConstants.JOB_ID_PREFIX)) { + return entity.getAsJobProfile(); + } + return null; + } + + /** + * get list of job profiles. + * @param stateSearchKey - state search key. + * @return - list of job profile. + */ + public List getJobs(StateSearchKey stateSearchKey) { + List entityList = db.search(stateSearchKey); + List profileList = new ArrayList<>(); + for (KeyValueEntity entity : entityList) { + if (entity.getKey().startsWith(JobConstants.JOB_ID_PREFIX)) { + profileList.add(entity.getAsJobProfile()); + } + } + return profileList; + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/KeyValueEntity.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/KeyValueEntity.java new file mode 100644 index 00000000..d71533c8 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/KeyValueEntity.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.db; + +import com.sleepycat.persist.model.Entity; +import com.sleepycat.persist.model.PrimaryKey; +import com.sleepycat.persist.model.Relationship; +import com.sleepycat.persist.model.SecondaryKey; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; + +/** + * key value entity. key is string and value is a json + */ +@Entity(version = 1) +public class KeyValueEntity { + + @PrimaryKey + private String key; + + @SecondaryKey(relate = Relationship.MANY_TO_ONE) + private StateSearchKey stateSearchKey; + + /** + * stores the file name that the jsonValue refers + */ + @SecondaryKey(relate = Relationship.MANY_TO_ONE) + private String fileName; + + private String jsonValue; + + private KeyValueEntity() { + + } + + public KeyValueEntity(String key, String jsonValue, String fileName) { + this.key = key; + this.jsonValue = jsonValue; + this.stateSearchKey = StateSearchKey.ACCEPTED; + this.fileName = fileName; + } + + public String getKey() { + return key; + } + + public StateSearchKey getStateSearchKey() { + return stateSearchKey; + } + + public KeyValueEntity setStateSearchKey(StateSearchKey stateSearchKey) { + this.stateSearchKey = stateSearchKey; + return this; + } + + public String getJsonValue() { + return jsonValue; + } + + public KeyValueEntity setJsonValue(String jsonValue) { + this.jsonValue = jsonValue; + return this; + } + + /** + * convert keyValue to job profile + * + * @return JobConfiguration + */ + public JobProfile getAsJobProfile() { + // convert jsonValue to jobConfiguration + return JobProfile.parseJsonStr(getJsonValue()); + } + + /** + * convert keyValue to trigger profile + * + * @return + */ + public TriggerProfile getAsTriggerProfile() { + return TriggerProfile.parseJsonStr(getJsonValue()); + } + + /** + * check whether the entity is finished + * + * @return + */ + public boolean checkFinished() { + return stateSearchKey.equals(StateSearchKey.SUCCESS) || stateSearchKey.equals(StateSearchKey.FAILED); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/LocalProfile.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/LocalProfile.java new file mode 100644 index 00000000..bbd71813 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/LocalProfile.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package com.zmops.zeus.iot.server.transfer.core.db; + +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * profile from local file + */ +public class LocalProfile { + private static final Logger LOGGER = LoggerFactory.getLogger(LocalProfile.class); + + private static final String JSON_SUFFIX = ".json"; + private static final String PROPERTIES_SUFFIX = ".properties"; + private static final String PARENT_PATH = "/jobs"; + + private final Path filePath; + + public LocalProfile(String parentConfPath) { + String fileName = parentConfPath + PARENT_PATH; + this.filePath = Paths.get(fileName); + } + + public List readFromLocal() { + List profileList = new ArrayList<>(); + try { + if (Files.isDirectory(this.filePath)) { + // list parent path and find files which name is end with .json or .properties + for (Iterator it = Files.list(this.filePath).iterator(); it.hasNext(); ) { + String childPath = it.next().toString(); + JobProfile jobProfile = null; + if (childPath.endsWith(JSON_SUFFIX)) { + jobProfile = JobProfile.parseJsonFile(childPath); + } else if (childPath.endsWith(PROPERTIES_SUFFIX)) { + jobProfile = JobProfile.parsePropertiesFile(childPath); + } + if (jobProfile != null && jobProfile.allRequiredKeyExist()) { + profileList.add(jobProfile); + } + } + } + } catch (Exception ex) { + LOGGER.error("error in reading files {}", this.filePath); + } + return profileList; + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/StateSearchKey.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/StateSearchKey.java new file mode 100644 index 00000000..1be397f5 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/StateSearchKey.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.db; + +/** + * search key for state. + */ +public enum StateSearchKey { + // success state + SUCCESS, + // fail state + FAILED, + // accepted state + ACCEPTED, + // running state + RUNNING +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/TriggerProfileDb.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/TriggerProfileDb.java new file mode 100644 index 00000000..5a3ff621 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/TriggerProfileDb.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.db; + +import com.zmops.zeus.iot.server.transfer.conf.CommonConstants; +import com.zmops.zeus.iot.server.transfer.conf.JobConstants; +import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +/** + * db interface for trigger profile. + */ +public class TriggerProfileDb { + + private static final Logger LOGGER = LoggerFactory.getLogger(TriggerProfileDb.class); + + private final Db db; + + public TriggerProfileDb(Db db) { + this.db = db; + } + + /** + * get trigger list from db. + * + * @return - list of trigger + */ + public List getTriggers() { + // potential performance issue, needs to find out the speed. + List result = this.db.findAll(CommonConstants.TRIGGER_ID_PREFIX); + List triggerList = new ArrayList<>(); + for (KeyValueEntity entity : result) { + triggerList.add(entity.getAsTriggerProfile()); + } + return triggerList; + } + + /** + * store trigger profile. + * + * @param trigger - trigger + */ + public void storeTrigger(TriggerProfile trigger) { + if (trigger.allRequiredKeyExist()) { + String keyName = CommonConstants.TRIGGER_ID_PREFIX + trigger.get(JobConstants.JOB_ID); + + KeyValueEntity entity = new KeyValueEntity(keyName, trigger.toJsonStr(), trigger.get(JobConstants.JOB_DIR_FILTER_PATTERN)); + + KeyValueEntity oldEntity = db.put(entity); + + if (oldEntity != null) { + LOGGER.warn("trigger profile {} has been replaced", oldEntity.getKey()); + } + } + } + + /** + * delete trigger by id. + * + * @param id + */ + public void deleteTrigger(String id) { + db.remove(CommonConstants.TRIGGER_ID_PREFIX + id); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/exception/FileException.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/exception/FileException.java similarity index 94% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/exception/FileException.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/exception/FileException.java index 77e8f632..5df83ecd 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/exception/FileException.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/exception/FileException.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.exception; +package com.zmops.zeus.iot.server.transfer.core.exception; public class FileException extends RuntimeException { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/filter/DateFormatRegex.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java similarity index 96% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/filter/DateFormatRegex.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java index b80e304d..38b94c1e 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/filter/DateFormatRegex.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java @@ -15,10 +15,12 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.filter; +package com.zmops.zeus.iot.server.transfer.core.filter; -import com.zmops.zeus.iot.server.transfer.api.Filter; -import com.zmops.zeus.iot.server.transfer.utils.AgentUtils; +import com.zmops.zeus.iot.server.transfer.core.api.Filter; + + +import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -74,6 +76,7 @@ public boolean match() { public DateFormatRegex withOffset(String timeOffset) { String number = StringUtils.substring(timeOffset, 0, timeOffset.length() - 1); String mark = StringUtils.substring(timeOffset, timeOffset.length() - 1); + switch (mark) { case OFFSET_DAY: dayOffset = Integer.parseInt(number); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java new file mode 100644 index 00000000..851efa91 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.job; + + +import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; +import com.zmops.zeus.iot.server.transfer.core.db.Db; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +public class CommandDb { + + private static final Logger LOGGER = LoggerFactory.getLogger(CommandDb.class); + + public static final int MANAGER_SUCCESS_CODE = 0; + public static final int MANAGER_FAIL_CODE = 1; + private final Db db; + + public CommandDb(Db db) { + this.db = db; + } + + /** + * store manager command to db + * + * @param commandEntity + */ + public void storeCommand(CommandEntity commandEntity) { + db.putCommand(commandEntity); + } + + /** + * get those commands not ack to manager + * + * @return + */ + public List getUnackedCommands() { + return db.searchCommands(false); + } + + + /** + * save normal command result for trigger + * + * @param profile + * @param success + */ + public void saveNormalCmds(TriggerProfile profile, boolean success) { + CommandEntity entity = new CommandEntity(); + entity.setId(CommandEntity.generateCommanid(profile.getTriggerId(), profile.getOpType())); + entity.setTaskId(profile.getTriggerId()); + entity.setDeliveryTime(profile.getDeliveryTime()); + entity.setCommandResult(success ? MANAGER_SUCCESS_CODE : MANAGER_FAIL_CODE); + entity.setAcked(false); + storeCommand(entity); + } + + /** + * save special command result for trigger (retry\makeup\check) + * + * @param id + * @param taskId + * @param success + */ + public void saveSpecialCmds(Integer id, Integer taskId, boolean success) { + CommandEntity entity = new CommandEntity(); + entity.setId(String.valueOf(id)); + entity.setTaskId(String.valueOf(taskId)); + entity.setAcked(false); + entity.setCommandResult(success ? MANAGER_SUCCESS_CODE : MANAGER_FAIL_CODE); + storeCommand(entity); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandEntity.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandEntity.java new file mode 100644 index 00000000..e9f5999a --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandEntity.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.job; + +import com.sleepycat.persist.model.Entity; +import com.sleepycat.persist.model.PrimaryKey; +import com.sleepycat.persist.model.Relationship; +import com.sleepycat.persist.model.SecondaryKey; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + + +@Entity(version = 1) +@Data +@AllArgsConstructor +@NoArgsConstructor +public class CommandEntity { + + @PrimaryKey + private String id; + + private int commandResult; + + @SecondaryKey(relate = Relationship.MANY_TO_ONE) + private boolean isAcked; + + private String taskId; + + private String deliveryTime; + + public static String generateCommanid(String taskId, int opType) { + return taskId + opType; + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java new file mode 100644 index 00000000..29caf070 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.job; + + +import com.zmops.zeus.iot.server.transfer.conf.JobConstants; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import com.zmops.zeus.iot.server.transfer.core.api.Channel; +import com.zmops.zeus.iot.server.transfer.core.api.Reader; +import com.zmops.zeus.iot.server.transfer.core.api.Sink; +import com.zmops.zeus.iot.server.transfer.core.api.Source; +import com.zmops.zeus.iot.server.transfer.core.task.Task; +import lombok.Getter; +import lombok.Setter; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +/** + * job meta definition, job will be split into several tasks. + */ +public class Job { + + private static final Logger LOGGER = LoggerFactory.getLogger(Job.class); + + private final JobProfile jobConf; + + // job name + @Getter + @Setter + private String name; + + // job description + @Getter + @Setter + private String description; + + @Getter + @Setter + private String jobInstanceId; + + public Job(JobProfile jobConf) { + this.jobConf = jobConf; + this.name = jobConf.get(JobConstants.JOB_NAME, JobConstants.DEFAULT_JOB_NAME); + this.description = jobConf.get(JobConstants.JOB_DESCRIPTION, JobConstants.DEFAULT_JOB_DESCRIPTION); + this.jobInstanceId = jobConf.get(JobConstants.JOB_INSTANCE_ID); + } + + public List createTasks() { + List taskList = new ArrayList<>(); + int index = 0; + try { + LOGGER.info("job id: {}, source: {}, channel: {}, sink: {}", + getJobInstanceId(), jobConf.get(JobConstants.JOB_SOURCE), + jobConf.get(JobConstants.JOB_CHANNEL), + jobConf.get(JobConstants.JOB_SINK)); + + Source source = (Source) Class.forName(jobConf.get(JobConstants.JOB_SOURCE)).newInstance(); + + for (Reader reader : source.split(jobConf)) { + Sink writer = (Sink) Class.forName(jobConf.get(JobConstants.JOB_SINK)).newInstance(); + writer.setSourceFile(reader.getReadFile()); + + Channel channel = (Channel) Class.forName(jobConf.get(JobConstants.JOB_CHANNEL)).newInstance(); + + String taskId = String.format("%s_%d", jobInstanceId, index++); + taskList.add(new Task(taskId, reader, writer, channel, getJobConf())); + } + } catch (Exception ex) { + throw new RuntimeException(ex); + } + return taskList; + } + + public JobProfile getJobConf() { + return this.jobConf; + } + +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java new file mode 100644 index 00000000..4df197fe --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java @@ -0,0 +1,252 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.job; + + +import com.zmops.zeus.iot.server.transfer.conf.AgentConfiguration; +import com.zmops.zeus.iot.server.transfer.conf.AgentConstants; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; +import com.zmops.zeus.iot.server.transfer.core.common.AgentThreadFactory; +import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; +import com.zmops.zeus.iot.server.transfer.core.db.StateSearchKey; +import com.zmops.zeus.iot.server.transfer.core.manager.AgentManager; +import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +import static com.zmops.zeus.iot.server.transfer.conf.AgentConstants.*; +import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.*; + +/** + * JobManager maintains lots of jobs, and communicate between server and task manager. + */ +public class JobManager extends AbstractDaemon { + + private static final Logger LOGGER = LoggerFactory.getLogger(JobManager.class); + + // key is job instance id. + private ConcurrentHashMap jobs; + // jobs which are not accepted by running pool. + private final ConcurrentHashMap pendingJobs; + // job thread pool + private final ThreadPoolExecutor runningPool; + private final AgentManager agentManager; + private final int monitorInterval; + private final long jobDbCacheTime; + private final long jobDbCacheCheckInterval; + + // job profile db is only used to recover instance which is not finished running. + private final JobProfileDb jobConfDB; + private final JobMetrics jobMetrics; + private final AtomicLong index = new AtomicLong(0); + + /** + * init job manager + * + * @param agentManager - agent manager + */ + public JobManager(AgentManager agentManager, JobProfileDb jobConfDb) { + this.jobConfDB = jobConfDb; + this.agentManager = agentManager; + // job thread pool for running + this.runningPool = new ThreadPoolExecutor( + 0, Integer.MAX_VALUE, + 60L, TimeUnit.SECONDS, + new SynchronousQueue<>(), + new AgentThreadFactory("job")); + this.jobs = new ConcurrentHashMap<>(); + this.pendingJobs = new ConcurrentHashMap<>(); + AgentConfiguration conf = AgentConfiguration.getAgentConf(); + this.monitorInterval = conf + .getInt( + AgentConstants.JOB_MONITOR_INTERVAL, AgentConstants.DEFAULT_JOB_MONITOR_INTERVAL); + this.jobDbCacheTime = conf.getLong(JOB_DB_CACHE_TIME, DEFAULT_JOB_DB_CACHE_TIME); + this.jobDbCacheCheckInterval = conf.getLong(JOB_DB_CACHE_CHECK_INTERVAL, DEFAULT_JOB_DB_CACHE_CHECK_INTERVAL); + this.jobMetrics = JobMetrics.create(); + } + + /** + * submit job to work thread. + * + * @param job - job + */ + public void addJob(Job job) { + try { + JobWrapper jobWrapper = new JobWrapper(agentManager, job); + this.runningPool.execute(jobWrapper); + JobWrapper jobWrapperRet = jobs.putIfAbsent(jobWrapper.getJob().getJobInstanceId(), jobWrapper); + if (jobWrapperRet != null) { + LOGGER.warn("{} has been added to running pool, " + + "cannot be added repeatedly", job.getJobInstanceId()); + } else { + jobMetrics.runningJobs.incr(); + } + } catch (Exception rje) { + LOGGER.debug("reject job {}", job.getJobInstanceId(), rje); + pendingJobs.putIfAbsent(job.getJobInstanceId(), job); + } + } + + /** + * add job profile + * + * @param profile - job profile. + */ + public boolean submitJobProfile(JobProfile profile) { + if (profile == null || !profile.allRequiredKeyExist()) { + LOGGER.error("profile is null or not all required key exists {}", profile == null ? null + : profile.toJsonStr()); + return false; + } + String jobId = profile.get(JOB_ID); + profile.set(JOB_INSTANCE_ID, AgentUtils.getUniqId(JOB_ID_PREFIX, jobId, index.incrementAndGet())); + LOGGER.info("submit job profile {}", profile.toJsonStr()); + + getJobConfDb().storeJobFirstTime(profile); + addJob(new Job(profile)); + + return true; + } + + /** + * delete job profile and stop job thread + * + * @param jobInstancId + */ + public void deleteJob(String jobInstancId) { + JobWrapper jobWrapper = jobs.remove(jobInstancId); + if (jobWrapper != null) { + LOGGER.info("delete job instance with job id {}", jobInstancId); + jobWrapper.cleanup(); + getJobConfDb().deleteJob(jobInstancId); + } + } + + /** + * start all accepted jobs. + */ + private void startJobs() { + List profileList = getJobConfDb().getAcceptedJobs(); + for (JobProfile profile : profileList) { + LOGGER.info("init starting job from db {}", profile.toJsonStr()); + addJob(new Job(profile)); + } + } + + public Runnable jobStateCheckThread() { + return () -> { + while (isRunnable()) { + try { + // check pending jobs and try to submit again. + for (String jobId : pendingJobs.keySet()) { + Job job = pendingJobs.remove(jobId); + if (job != null) { + addJob(job); + } + } + TimeUnit.SECONDS.sleep(monitorInterval); + } catch (Exception ex) { + LOGGER.error("error caught", ex); + } + } + }; + } + + /** + * check local db and delete old tasks. + * + * @return + */ + public Runnable dbStorageCheckThread() { + return () -> { + while (isRunnable()) { + try { + jobConfDB.removeExpireJobs(jobDbCacheTime); + TimeUnit.SECONDS.sleep(jobDbCacheCheckInterval); + } catch (Exception ex) { + LOGGER.error("error caught", ex); + } + } + }; + } + + /** + * mark job as success by job id. + * + * @param jobId - job id + */ + public void markJobAsSuccess(String jobId) { + JobWrapper wrapper = jobs.remove(jobId); + if (wrapper != null) { + jobMetrics.runningJobs.decr(); + LOGGER.info("job instance {} is success", jobId); + // mark job as success. + jobConfDB.updateJobState(jobId, StateSearchKey.SUCCESS); + } + } + + public void markJobAsFailed(String jobId) { + JobWrapper wrapper = jobs.remove(jobId); + if (wrapper != null) { + LOGGER.info("job instance {} is failed", jobId); + jobMetrics.runningJobs.decr(); + jobMetrics.fatalJobs.incr(); + // mark job as success. + jobConfDB.updateJobState(jobId, StateSearchKey.FAILED); + } + } + + public JobProfileDb getJobConfDb() { + return jobConfDB; + } + + /** + * check job existence using job file name + * + * @return + */ + public boolean checkJobExsit(String fileName) { + return jobConfDB.getJob(fileName) != null; + } + + public Map getJobs() { + return jobs; + } + + @Override + public void start() { + submitWorker(jobStateCheckThread()); + submitWorker(dbStorageCheckThread()); + startJobs(); + } + + @Override + public void stop() throws Exception { + waitForTerminate(); + this.runningPool.shutdown(); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java new file mode 100644 index 00000000..ef66da34 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package com.zmops.zeus.iot.server.transfer.core.job; + + +import com.zmops.zeus.iot.server.transfer.core.metrics.Metric; +import com.zmops.zeus.iot.server.transfer.core.metrics.Metrics; +import com.zmops.zeus.iot.server.transfer.core.metrics.MetricsRegister; +import com.zmops.zeus.iot.server.transfer.core.metrics.gauge.GaugeInt; + +import java.util.concurrent.atomic.AtomicBoolean; + +@Metrics +public class JobMetrics { + private static final JobMetrics JOB_METRICS = new JobMetrics(); + private static final AtomicBoolean REGISTER_ONCE = new AtomicBoolean(false); + + @Metric + GaugeInt runningJobs; + + @Metric + GaugeInt fatalJobs; + + private JobMetrics() { + } + + static JobMetrics create() { + if (REGISTER_ONCE.compareAndSet(false, true)) { + MetricsRegister.register("Job", "STateSummary", null, JOB_METRICS); + } + return JOB_METRICS; + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java new file mode 100644 index 00000000..3cff3075 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.job; + + +import com.zmops.zeus.iot.server.transfer.conf.AgentConfiguration; +import com.zmops.zeus.iot.server.transfer.conf.AgentConstants; +import com.zmops.zeus.iot.server.transfer.core.manager.AgentManager; +import com.zmops.zeus.iot.server.transfer.core.state.AbstractStateWrapper; +import com.zmops.zeus.iot.server.transfer.core.state.State; +import com.zmops.zeus.iot.server.transfer.core.task.Task; +import com.zmops.zeus.iot.server.transfer.core.task.TaskManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * JobWrapper is used in JobManager, it defines the life cycle of + * running job and maintains the state of job. + */ +public class JobWrapper extends AbstractStateWrapper { + + private static final Logger LOGGER = LoggerFactory.getLogger(JobWrapper.class); + + private final AgentConfiguration agentConf; + private final TaskManager taskManager; + private final JobManager jobManager; + private final Job job; + + private final List allTasks; + + public JobWrapper(AgentManager manager, Job job) { + super(); + this.agentConf = AgentConfiguration.getAgentConf(); + this.taskManager = manager.getTaskManager(); + this.jobManager = manager.getJobManager(); + this.job = job; + this.allTasks = new ArrayList<>(); + doChangeState(State.ACCEPTED); + } + + /** + * check states of all tasks, wait if one of them not finished. + */ + private void checkAllTasksStateAndWait() throws Exception { + boolean isFinished = false; + + long checkInterval = agentConf.getLong(AgentConstants.JOB_FINISH_CHECK_INTERVAL, AgentConstants.DEFAULT_JOB_FINISH_CHECK_INTERVAL); + do { + // check whether all tasks have finished. + isFinished = allTasks.stream().allMatch(task -> taskManager.isTaskFinished(task.getTaskId())); + TimeUnit.SECONDS.sleep(checkInterval); + } while (!isFinished); + + LOGGER.info("all tasks of {} has been checked", job.getJobInstanceId()); + boolean isSuccess = allTasks.stream().allMatch(task -> taskManager.isTaskSuccess(task.getTaskId())); + + if (isSuccess) { + doChangeState(State.SUCCEEDED); + } else { + doChangeState(State.FAILED); + } + } + + /** + * submit all tasks + */ + private void submitAllTasks() { + List tasks = job.createTasks(); + + tasks.forEach(task -> { + allTasks.add(task); + taskManager.submitTask(task); + }); + } + + /** + * get job + * + * @return job + */ + public Job getJob() { + return job; + } + + /** + * cleanup job + */ + public void cleanup() { + allTasks.forEach(task -> taskManager.removeTask(task.getTaskId())); + } + + @Override + public void run() { + try { + doChangeState(State.RUNNING); + + submitAllTasks(); + + checkAllTasksStateAndWait(); + + cleanup(); + } catch (Exception ex) { + doChangeState(State.FAILED); + LOGGER.error("error caught: {}, message: {}", + job.getJobConf().toJsonStr(), ex.getMessage()); + } + } + + @Override + public void addCallbacks() { + this.addCallback(State.ACCEPTED, State.RUNNING, (before, after) -> { + + }).addCallback(State.RUNNING, State.FAILED, (before, after) -> { + jobManager.markJobAsFailed(job.getJobInstanceId()); + }).addCallback(State.RUNNING, State.SUCCEEDED, ((before, after) -> { + jobManager.markJobAsSuccess(job.getJobInstanceId()); + })); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/AgentManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/AgentManager.java new file mode 100644 index 00000000..da05604c --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/AgentManager.java @@ -0,0 +1,200 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.manager; + + +import com.zmops.zeus.iot.server.transfer.conf.*; +import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; +import com.zmops.zeus.iot.server.transfer.core.db.Db; +import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; +import com.zmops.zeus.iot.server.transfer.core.db.LocalProfile; +import com.zmops.zeus.iot.server.transfer.core.db.TriggerProfileDb; +import com.zmops.zeus.iot.server.transfer.core.job.CommandDb; +import com.zmops.zeus.iot.server.transfer.core.job.JobManager; +import com.zmops.zeus.iot.server.transfer.core.task.TaskManager; +import com.zmops.zeus.iot.server.transfer.core.task.TaskPositionManager; +import com.zmops.zeus.iot.server.transfer.core.trigger.TriggerManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Constructor; +import java.util.List; + +import static com.zmops.zeus.iot.server.transfer.conf.AgentConstants.AGENT_CONF_PARENT; +import static com.zmops.zeus.iot.server.transfer.conf.AgentConstants.DEFAULT_AGENT_CONF_PARENT; +import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_TRIGGER; + +/** + * Agent Manager, the bridge for job manager, task manager, db e.t.c it manages agent level + * operations and communicates with outside system. + */ +public class AgentManager extends AbstractDaemon { + + private static final Logger LOGGER = LoggerFactory.getLogger(AgentManager.class); + private final JobManager jobManager; + private final TaskManager taskManager; + private final TriggerManager triggerManager; + private final TaskPositionManager taskPositionManager; + + // jetty for config operations via http. + private ConfigJetty configJetty; + + + private final ProfileFetcher fetcher; + private final AgentConfiguration conf; + private final Db db; + private final LocalProfile localProfile; + private final CommandDb commandDb; + + public AgentManager() { + conf = AgentConfiguration.getAgentConf(); + this.db = initDb(); + commandDb = new CommandDb(db); + + String parentConfPath = conf.get(AGENT_CONF_PARENT, DEFAULT_AGENT_CONF_PARENT); + + localProfile = new LocalProfile(parentConfPath); + fetcher = initFetcher(this); + triggerManager = new TriggerManager(this, new TriggerProfileDb(db)); + + jobManager = new JobManager(this, new JobProfileDb(db)); + taskManager = new TaskManager(this); + taskPositionManager = TaskPositionManager.getTaskPositionManager(this); + + // need to be an option. + if (conf.getBoolean(AgentConstants.AGENT_ENABLE_HTTP, AgentConstants.DEFAULT_AGENT_ENABLE_HTTP)) { + this.configJetty = new ConfigJetty(jobManager, triggerManager); + } + } + + /** + * init fetch by class name + * + * @return + */ + private ProfileFetcher initFetcher(AgentManager agentManager) { + try { + Constructor constructor = Class.forName(conf.get(AgentConstants.AGENT_FETCHER_CLASSNAME)).getDeclaredConstructor(AgentManager.class); + + constructor.setAccessible(true); + return (ProfileFetcher) constructor.newInstance(agentManager); + } catch (Exception ex) { + LOGGER.warn("cannot find fetcher, ignore it {}", ex.getMessage()); + } + return null; + } + + /** + * init db by class name + * + * @return db + */ + private Db initDb() { + try { + // db is a required component, so if not init correctly, + // throw exception and stop running. + return (Db) Class.forName(conf.get(AgentConstants.AGENT_DB_CLASSNAME, AgentConstants.DEFAULT_AGENT_DB_CLASSNAME)).newInstance(); + } catch (Exception ex) { + throw new UnsupportedClassVersionError(ex.getMessage()); + } + } + + public JobManager getJobManager() { + return jobManager; + } + + public Db getDb() { + return db; + } + + public ProfileFetcher getFetcher() { + return fetcher; + } + + public CommandDb getCommandDb() { + return commandDb; + } + + public TriggerManager getTriggerManager() { + return triggerManager; + } + + public TaskPositionManager getTaskPositionManager() { + return taskPositionManager; + } + + public TaskManager getTaskManager() { + return taskManager; + } + + @Override + public void join() { + super.join(); + jobManager.join(); + taskManager.join(); + } + + @Override + public void start() throws Exception { + LOGGER.info("starting agent manager"); + triggerManager.start(); + jobManager.start(); + taskManager.start(); + taskPositionManager.start(); + // read job profiles from local + List profileList = localProfile.readFromLocal(); + for (JobProfile profile : profileList) { + if (profile.hasKey(JOB_TRIGGER)) { + TriggerProfile triggerProfile = TriggerProfile.parseJobProfile(profile); + // there is no need to store this profile in triggerDB, because + // this profile comes from local file. + triggerManager.addTrigger(triggerProfile); + } else { + // job db store instance info, so it's suitable to use submitJobProfile + // to store instance into job db. + jobManager.submitJobProfile(profile); + } + } + if (fetcher != null) { + fetcher.start(); + } + } + + /** + * It should guarantee thread-safe, and can be invoked many times. + * + * @throws Exception exceptions + */ + @Override + public void stop() throws Exception { + if (configJetty != null) { + configJetty.close(); + } + if (fetcher != null) { + fetcher.stop(); + } + // TODO: change job state which is in running state. + LOGGER.info("stopping agent manager"); + // close in order: trigger -> job -> task + triggerManager.stop(); + jobManager.stop(); + taskManager.stop(); + taskPositionManager.stop(); + this.db.close(); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/message/DefaultMessage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/DefaultMessage.java similarity index 92% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/message/DefaultMessage.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/DefaultMessage.java index 431f037b..eb1d2f28 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/message/DefaultMessage.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/DefaultMessage.java @@ -15,9 +15,9 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.message; +package com.zmops.zeus.iot.server.transfer.core.message; -import com.zmops.zeus.iot.server.transfer.api.Message; +import com.zmops.zeus.iot.server.transfer.core.api.Message; import java.nio.charset.StandardCharsets; import java.util.HashMap; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/EndMessage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/EndMessage.java new file mode 100644 index 00000000..261b7865 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/EndMessage.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.message; + +import com.zmops.zeus.iot.server.transfer.core.api.Message; + +import java.util.HashMap; +import java.util.Map; + +/** + * End message, this is an empty message only indicate + * that source data have been completely consumed. + */ +public class EndMessage implements Message { + + @Override + public byte[] getBody() { + return null; + } + + @Override + public Map getHeader() { + return new HashMap<>(10); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/AgentDynamicMBean.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/AgentDynamicMBean.java new file mode 100644 index 00000000..15943ab9 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/AgentDynamicMBean.java @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.metrics; + +import com.zmops.zeus.iot.server.transfer.core.metrics.meta.MetricMeta; +import com.zmops.zeus.iot.server.transfer.core.metrics.meta.MetricsMeta; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.management.*; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Dynamic MBean for agent + */ +public class AgentDynamicMBean implements DynamicMBean { + + private static final Logger LOGGER = LoggerFactory.getLogger(AgentDynamicMBean.class); + + private final ConcurrentHashMap> snapshotAttrs = new ConcurrentHashMap<>(); + + private final MBeanInfo mBeanInfo; + private final List attrs; + private final MetricsMeta metricsMeta; + private final String module; + private final String aspect; + private final String desc; + + public AgentDynamicMBean(String module, String aspect, String desc, MetricsMeta metricsMeta, Object source) { + this.module = module; + this.aspect = aspect; + this.desc = desc; + this.metricsMeta = metricsMeta; + this.attrs = new ArrayList<>(); + this.mBeanInfo = metricsMetaToInfo(); + + formatSnapshotList(source); + } + + private void formatSnapshotList(Object source) { + for (MetricMeta metricMeta : this.metricsMeta.getMetricMetaList()) { + try { + snapshotAttrs.put(metricMeta.getName(), (MetricSnapshot) metricMeta.getField().get(source)); + } catch (Exception ex) { + LOGGER.error("exception while adding snapshot list", ex); + } + } + } + + + private MBeanInfo metricsMetaToInfo() { + // overwrite name, desc from MetricsMeta if not null. + String name = this.module == null ? metricsMeta.getName() : this.module; + String description = this.desc == null ? metricsMeta.getDesc() : this.desc; + + for (MetricMeta fieldMetricMeta : metricsMeta.getMetricMetaList()) { + attrs.add(new MBeanAttributeInfo(fieldMetricMeta.getName(), + fieldMetricMeta.getType(), fieldMetricMeta.getDesc(), true, false, false)); + } + return new MBeanInfo(name, description, attrs.toArray(new MBeanAttributeInfo[0]), + null, null, null); + } + + @Override + public Object getAttribute(String attribute) { + MetricSnapshot snapshot = snapshotAttrs.get(attribute); + return new Attribute(attribute, snapshot.snapshot()); + } + + @Override + public void setAttribute(Attribute attribute) { + throw new UnsupportedOperationException("Metrics are read-only."); + } + + @Override + public AttributeList getAttributes(String[] attributes) { + AttributeList attributeList = new AttributeList(); + for (String attrKey : attributes) { + MetricSnapshot snapshot = snapshotAttrs.get(attrKey); + if (snapshot != null) { + attributeList.add(new Attribute(attrKey, snapshot.snapshot())); + } + } + return attributeList; + } + + @Override + public AttributeList setAttributes(AttributeList attributes) { + throw new UnsupportedOperationException("Metrics are read-only."); + } + + @Override + public Object invoke(String actionName, Object[] params, String[] signature) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public MBeanInfo getMBeanInfo() { + return mBeanInfo; + } + + public String getModule() { + return module; + } + + public String getAspect() { + return aspect; + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metric.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metric.java new file mode 100644 index 00000000..4326f873 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metric.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.metrics; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * metric for field + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.METHOD}) +public @interface Metric { + + /** + * Type of metric + * + * @return metric type + */ + Type type() default Type.DEFAULT; + + /** + * Doc of metric + * + * @return metric doc + */ + String desc() default ""; + + enum Type { + DEFAULT("java.lang.String"), + COUNTER_INT("java.lang.Integer"), + COUNTER_LONG("java.lang.Long"), + GAUGE_INT("java.lang.Integer"), + GAUGE_LONG("java.lang.Long"), + TAG("java.lang.String"); + private final String value; + + private Type(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricException.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricException.java new file mode 100644 index 00000000..514d1e4d --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricException.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.metrics; + +public class MetricException extends RuntimeException { + + public MetricException(String message, Exception ex) { + super(message, ex); + } + + public MetricException(String message) { + super(message); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricSnapshot.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricSnapshot.java new file mode 100644 index 00000000..f15118c0 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricSnapshot.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.metrics; + +public interface MetricSnapshot { + T snapshot(); +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metrics.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metrics.java new file mode 100644 index 00000000..f8058c80 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metrics.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.metrics; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * metric + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Metrics { + + /** + * Metrics name + * + * @return + */ + String name() default ""; + + /** + * Metrics context + * + * @return + */ + String context() default ""; + + /** + * Metrics description + * + * @return + */ + String desc() default ""; +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricsRegister.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricsRegister.java new file mode 100644 index 00000000..54ed2155 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricsRegister.java @@ -0,0 +1,148 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.metrics; + + +import com.zmops.zeus.iot.server.transfer.core.metrics.counter.CounterInt; +import com.zmops.zeus.iot.server.transfer.core.metrics.counter.CounterLong; +import com.zmops.zeus.iot.server.transfer.core.metrics.gauge.GaugeInt; +import com.zmops.zeus.iot.server.transfer.core.metrics.gauge.GaugeLong; +import com.zmops.zeus.iot.server.transfer.core.metrics.meta.MetricMeta; +import com.zmops.zeus.iot.server.transfer.core.metrics.meta.MetricsMeta; +import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.management.MBeanServer; +import javax.management.ObjectName; +import java.lang.annotation.Annotation; +import java.lang.management.ManagementFactory; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +/** + * register for metrics. + */ +public class MetricsRegister { + private static final Logger LOGGER = LoggerFactory.getLogger(MetricsRegister.class); + + private static final String DOMAIN_PREFIX = "Agent:"; + private static final String MODULE_PREFIX = "module="; + private static final String ASPECT_PREFIX = "aspect="; + private static final String COMMA_SPLITTER = ","; + + // object name should be uniq + private static final ConcurrentHashMap CACHED_NAME = new ConcurrentHashMap<>(); + + private MetricsRegister() { + } + + /** + * register object name for metric + * @param agentDynamicMBean agent mbean + */ + private static void innerRegister(AgentDynamicMBean agentDynamicMBean) { + final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + String nameStr = DOMAIN_PREFIX + MODULE_PREFIX + agentDynamicMBean.getModule() + + COMMA_SPLITTER + ASPECT_PREFIX + agentDynamicMBean.getAspect(); + try { + ObjectName tmpName = new ObjectName(nameStr); + ObjectName objectName = CACHED_NAME.putIfAbsent(nameStr, tmpName); + if (objectName == null) { + mbs.registerMBean(agentDynamicMBean, tmpName); + } + } catch (Exception ex) { + LOGGER.error("exception while register mbean", ex); + } + } + + public static void register(String module, String aspect, String desc, Object source) { + List metricMetaList = handleFieldAnnotation(source); + MetricsMeta metricsMeta = handleClassAnnotation(source, metricMetaList); + if (metricsMeta != null) { + innerRegister(new AgentDynamicMBean(module, aspect, desc, metricsMeta, source)); + } else { + LOGGER.error("Cannot find Metrics annotation in {}, invalid metric", source); + } + } + + + /** + * handle class level annotation + */ + private static MetricsMeta handleClassAnnotation(Object source, + List metricMetaList) { + for (Annotation annotation : source.getClass().getAnnotations()) { + if (annotation instanceof Metrics) { + return MetricsMeta.build((Metrics) annotation, metricMetaList); + } + } + return null; + } + + + private static boolean initFieldByType(Object source, Field field) { + try { + if (field.getType() == CounterInt.class) { + field.set(source, new CounterInt()); + return true; + } else if (field.getType() == CounterLong.class) { + field.set(source, new CounterLong()); + return true; + } else if (field.getType() == GaugeInt.class) { + field.set(source, new GaugeInt()); + return true; + } else if (field.getType() == GaugeLong.class) { + field.set(source, new GaugeLong()); + return true; + } else if (field.getType() == Tag.class) { + field.set(source, new Tag()); + return true; + } else { + throw new MetricException("field type error " + field.getType().toString()); + } + } catch (MetricException ex) { + throw ex; + } catch (Exception ex) { + throw new MetricException("Error setting field " + field + + " annotated with metric", ex); + } + } + + /** + * handle field annotation + */ + private static List handleFieldAnnotation(Object source) { + List result = new ArrayList<>(); + for (Field field : AgentUtils.getDeclaredFieldsIncludingInherited(source.getClass())) { + field.setAccessible(true); + for (Annotation fieldAnnotation : field.getAnnotations()) { + if (fieldAnnotation instanceof Metric) { + if (initFieldByType(source, field)) { + result.add(MetricMeta.build((Metric) fieldAnnotation, field)); + } + break; + } + } + } + return result; + } +} + diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MutableMetric.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MutableMetric.java new file mode 100644 index 00000000..ffd05b4a --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MutableMetric.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.metrics; + +/** + * Metric with number + */ +public interface MutableMetric extends MetricSnapshot { + +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Tag.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Tag.java new file mode 100644 index 00000000..2ff785df --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Tag.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.metrics; + +public class Tag implements MetricSnapshot { + + private String name; + + /** + * set string name for tag. + * @param name - tag name + */ + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public String snapshot() { + return name; + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/Counter.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/Counter.java new file mode 100644 index 00000000..c901f7d9 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/Counter.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.metrics.counter; + + +import com.zmops.zeus.iot.server.transfer.core.metrics.MutableMetric; + +public interface Counter extends MutableMetric { + + /** + * +1 + */ + void incr(); + + /** + * +delta + * + * @param delta > 0 + */ + void incr(int delta); + +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterInt.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterInt.java new file mode 100644 index 00000000..f5933e36 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterInt.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.metrics.counter; + +import java.util.concurrent.atomic.AtomicInteger; + +public class CounterInt implements Counter { + + private AtomicInteger value = new AtomicInteger(0); + + @Override + public void incr() { + value.incrementAndGet(); + } + + @Override + public void incr(int delta) { + assert delta > 0; + value.getAndAdd(delta); + } + + @Override + public Integer snapshot() { + return value.get(); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterLong.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterLong.java new file mode 100644 index 00000000..d1a7d464 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterLong.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.metrics.counter; + +import java.util.concurrent.atomic.AtomicLong; + +/** + * atomic long for counter + */ +public class CounterLong implements Counter { + + private final AtomicLong value = new AtomicLong(); + + @Override + public void incr() { + value.incrementAndGet(); + } + + @Override + public void incr(int delta) { + assert delta > 0; + value.getAndAdd(delta); + } + + @Override + public Long snapshot() { + return value.get(); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/Gauge.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/Gauge.java new file mode 100644 index 00000000..beb94e2b --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/Gauge.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.metrics.gauge; + +import com.zmops.zeus.iot.server.transfer.core.metrics.MutableMetric; + +public interface Gauge extends MutableMetric { + + void set(T num); + + /** + * +1 + */ + void incr(); + + /** + * + delt + * + * @param delta > 0 + */ + void incr(int delta); + + /** + * -1 + */ + void decr(); + + /** + * -delta + * + * @param delta > 0 + */ + void decr(int delta); +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeInt.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeInt.java new file mode 100644 index 00000000..f1b608c3 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeInt.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.metrics.gauge; + +import java.util.concurrent.atomic.AtomicInteger; + +public class GaugeInt implements Gauge { + + private final AtomicInteger value = new AtomicInteger(0); + + @Override + public void set(Integer num) { + value.set(num); + } + + @Override + public void incr() { + value.incrementAndGet(); + } + + @Override + public void incr(int delta) { + assert delta > 0; + value.getAndAdd(delta); + } + + @Override + public void decr() { + value.decrementAndGet(); + } + + @Override + public void decr(int delta) { + assert delta > 0; + value.getAndAdd(-delta); + } + + @Override + public Integer snapshot() { + return value.get(); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeLong.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeLong.java new file mode 100644 index 00000000..6bc6e6db --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeLong.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.metrics.gauge; + +import java.util.concurrent.atomic.AtomicLong; + +public class GaugeLong implements Gauge { + + private final AtomicLong value = new AtomicLong(0); + + @Override + public void set(Long num) { + value.set(num); + } + + @Override + public void incr() { + value.incrementAndGet(); + } + + @Override + public void incr(int delta) { + assert delta > 0; + value.getAndAdd(delta); + } + + @Override + public void decr() { + value.decrementAndGet(); + } + + @Override + public void decr(int delta) { + assert delta > 0; + value.getAndAdd(-delta); + } + + @Override + public Long snapshot() { + return value.get(); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricMeta.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricMeta.java new file mode 100644 index 00000000..35c917b0 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricMeta.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.metrics.meta; + +import com.zmops.zeus.iot.server.transfer.core.metrics.Metric; +import com.zmops.zeus.iot.server.transfer.core.metrics.counter.CounterInt; +import com.zmops.zeus.iot.server.transfer.core.metrics.counter.CounterLong; +import com.zmops.zeus.iot.server.transfer.core.metrics.gauge.GaugeInt; +import com.zmops.zeus.iot.server.transfer.core.metrics.gauge.GaugeLong; +import org.apache.commons.lang3.StringUtils; + + +import java.lang.reflect.Field; + +import static com.zmops.zeus.iot.server.transfer.core.metrics.Metric.Type.*; + +/** + * this class is related to {@link Metric} + */ +public class MetricMeta { + + private String name; + private String type; + private String desc; + private Field field; + + public static MetricMeta build(Metric annotation, Field field) { + MetricMeta metricMeta = new MetricMeta(); + metricMeta.name = StringUtils.capitalize(field.getName()); + metricMeta.desc = annotation.desc(); + metricMeta.type = DEFAULT.getValue(); + metricMeta.field = field; + Class clz = field.getType(); + if (clz.isAssignableFrom(CounterLong.class)) { + metricMeta.type = COUNTER_LONG.getValue(); + } else if (clz.isAssignableFrom(CounterInt.class)) { + metricMeta.type = COUNTER_INT.getValue(); + } else if (clz.isAssignableFrom(GaugeInt.class)) { + metricMeta.type = GAUGE_INT.getValue(); + } else if (clz.isAssignableFrom(GaugeLong.class)) { + metricMeta.type = GAUGE_LONG.getValue(); + } + return metricMeta; + } + + public String getType() { + return type; + } + + public String getName() { + return name; + } + + public String getDesc() { + return desc; + } + + public Field getField() { + return field; + } +} + diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricsMeta.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricsMeta.java new file mode 100644 index 00000000..1438600c --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricsMeta.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.metrics.meta; + +import com.zmops.zeus.iot.server.transfer.core.metrics.Metrics; + +import java.util.List; + +/** + * This class is related to {@link Metrics} + */ +public class MetricsMeta { + + private String context; + private String desc; + private String name; + private List metricMetaList; + + private MetricsMeta() { + } + + public static MetricsMeta build(Metrics metrics, List metricMetaList) { + MetricsMeta metricsMeta = new MetricsMeta(); + metricsMeta.context = metrics.context(); + metricsMeta.desc = metrics.desc(); + metricsMeta.name = metrics.name(); + metricsMeta.metricMetaList = metricMetaList; + return metricsMeta; + } + + public String getContext() { + return context; + } + + public String getDesc() { + return desc; + } + + public List getMetricMetaList() { + return metricMetaList; + } + + public String getName() { + return name; + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sink/ConsoleSink.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/ConsoleSink.java similarity index 88% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sink/ConsoleSink.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/ConsoleSink.java index d623921e..2a999e91 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sink/ConsoleSink.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/ConsoleSink.java @@ -15,11 +15,11 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.sink; +package com.zmops.zeus.iot.server.transfer.core.sink; -import com.zmops.zeus.iot.server.transfer.api.Message; -import com.zmops.zeus.iot.server.transfer.api.Sink; +import com.zmops.zeus.iot.server.transfer.core.api.Message; +import com.zmops.zeus.iot.server.transfer.core.api.Sink; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import java.nio.charset.StandardCharsets; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/source/TextFileSource.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java similarity index 85% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/source/TextFileSource.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java index b5e3cd4f..994bcb11 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/source/TextFileSource.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java @@ -15,14 +15,14 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.source; +package com.zmops.zeus.iot.server.transfer.core.source; -import com.zmops.zeus.iot.server.transfer.api.Reader; -import com.zmops.zeus.iot.server.transfer.api.Source; +import com.zmops.zeus.iot.server.transfer.core.api.Reader; +import com.zmops.zeus.iot.server.transfer.core.api.Source; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.source.reader.TextFileReader; -import com.zmops.zeus.iot.server.transfer.utils.PluginUtils; +import com.zmops.zeus.iot.server.transfer.core.source.reader.TextFileReader; +import com.zmops.zeus.iot.server.transfer.core.utils.PluginUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,22 +47,25 @@ public class TextFileSource implements Source { @Override public List split(JobProfile jobConf) { + Collection allFiles = PluginUtils.findSuitFiles(jobConf); + List result = new ArrayList<>(); String filterPattern = jobConf.get(JOB_LINE_FILTER_PATTERN, DEFAULT_JOB_LINE_FILTER); for (File file : allFiles) { - int seekPosition = jobConf.getInt(file.getAbsolutePath() + POSITION_SUFFIX, 0); LOGGER.info("read from history position {} with job profile {}", seekPosition, jobConf.getInstanceId()); - String md5 = jobConf.get(file.getAbsolutePath() + MD5_SUFFIX, ""); + String md5 = jobConf.get(file.getAbsolutePath() + MD5_SUFFIX, ""); + TextFileReader textFileReader = new TextFileReader(file, seekPosition); addValidator(filterPattern, textFileReader); result.add(textFileReader); } + return result; } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/source/reader/TextFileReader.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java similarity index 90% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/source/reader/TextFileReader.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java index 78f72c6b..501f6dfa 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/source/reader/TextFileReader.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java @@ -15,17 +15,17 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.source.reader; +package com.zmops.zeus.iot.server.transfer.core.source.reader; -import com.zmops.zeus.iot.server.transfer.api.Message; -import com.zmops.zeus.iot.server.transfer.api.Reader; -import com.zmops.zeus.iot.server.transfer.api.Validator; +import com.zmops.zeus.iot.server.transfer.core.api.Message; +import com.zmops.zeus.iot.server.transfer.core.api.Reader; +import com.zmops.zeus.iot.server.transfer.core.api.Validator; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.exception.FileException; -import com.zmops.zeus.iot.server.transfer.message.DefaultMessage; -import com.zmops.zeus.iot.server.transfer.utils.AgentUtils; -import com.zmops.zeus.iot.server.transfer.validator.PatternValidator; +import com.zmops.zeus.iot.server.transfer.core.exception.FileException; +import com.zmops.zeus.iot.server.transfer.core.message.DefaultMessage; +import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; +import com.zmops.zeus.iot.server.transfer.core.validator.PatternValidator; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/AbstractStateWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/AbstractStateWrapper.java new file mode 100644 index 00000000..218bab74 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/AbstractStateWrapper.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.state; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +public abstract class AbstractStateWrapper implements Runnable { + + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractStateWrapper.class); + + private final Map, StateCallback> callBacks = new HashMap<>(); + + private volatile State currentState = State.ACCEPTED; + + public AbstractStateWrapper() { + addCallbacks(); + } + + /** + * add callback for state change + */ + public abstract void addCallbacks(); + + + public AbstractStateWrapper addCallback(State begin, State end, StateCallback callback) { + callBacks.put(new ImmutablePair<>(begin, end), callback); + return this; + } + + /** + * change state and execute callback functions + * + * @param nextState - next state + */ + public synchronized void doChangeState(State nextState) { + LOGGER.debug("state change, current state is {}, next state is {}", currentState, nextState); + Pair statePair = new ImmutablePair<>(currentState, nextState); + StateCallback callback = callBacks.get(statePair); + // change state before callback. + currentState = nextState; + if (callback != null) { + callback.call(currentState, nextState); + } + } + + /** + * determine the exception + * + * @return + */ + public boolean isException() { + State tmpState = currentState; + return State.KILLED.equals(tmpState) || State.FAILED.equals(tmpState) || State.FATAL.equals(tmpState); + } + + public boolean isFinished() { + State tmpState = currentState; + return State.FATAL.equals(tmpState) || State.SUCCEEDED.equals(tmpState) || State.KILLED.equals(tmpState); + } + + public boolean isSuccess() { + return State.SUCCEEDED.equals(currentState); + } + + public boolean isFailed() { + return State.FAILED.equals(currentState); + } + + public boolean isFatal() { + State tmpState = currentState; + return State.FATAL.equals(tmpState) || State.KILLED.equals(tmpState); + } + +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/State.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/State.java new file mode 100644 index 00000000..4c307513 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/State.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.state; + +/** + * job/task state + */ +public enum State { + // accepted state + ACCEPTED, + // running + RUNNING, + // succeeded + SUCCEEDED, + // failed + FAILED, + // killed + KILLED, + // fatal after retry failed + FATAL +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateCallback.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateCallback.java new file mode 100644 index 00000000..c2cf2abb --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateCallback.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.state; + +/** + * callbacks + */ +public interface StateCallback { + + void call(State before, State after); +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateTransferException.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateTransferException.java new file mode 100644 index 00000000..836eb0e9 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateTransferException.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.state; + + +public class StateTransferException extends RuntimeException { + + public StateTransferException(State begin, State end) { + super(String.format("%s -> %s not allowed", begin, end)); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java new file mode 100644 index 00000000..1f00e690 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.task; + +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import com.zmops.zeus.iot.server.transfer.core.api.Channel; +import com.zmops.zeus.iot.server.transfer.core.api.Reader; +import com.zmops.zeus.iot.server.transfer.core.api.Sink; + + +/** + * task meta definition which contains reader -> channel -> sink and job config information + */ +public class Task { + + private final String taskId; + private final Reader reader; + private final Sink sink; + private final Channel channel; + private final JobProfile jobConf; + + public Task(String taskId, Reader reader, Sink sink, Channel channel, JobProfile jobConf) { + this.reader = reader; + this.sink = sink; + this.taskId = taskId; + this.channel = channel; + this.jobConf = jobConf; + } + + public boolean isReadFinished() { + return reader.isFinished(); + } + + public String getTaskId() { + return taskId; + } + + public Reader getReader() { + return reader; + } + + public Sink getSink() { + return sink; + } + + public Channel getChannel() { + return channel; + } + + public void init() { + this.channel.init(jobConf); + this.sink.init(jobConf); + this.reader.init(jobConf); + } + + public void destroy() { + this.reader.destroy(); + this.sink.destroy(); + this.channel.destroy(); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java new file mode 100644 index 00000000..3ad9022b --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java @@ -0,0 +1,253 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.task; + + +import com.zmops.zeus.iot.server.transfer.conf.AgentConfiguration; +import com.zmops.zeus.iot.server.transfer.conf.AgentConstants; +import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; +import com.zmops.zeus.iot.server.transfer.core.common.AgentThreadFactory; +import com.zmops.zeus.iot.server.transfer.core.job.JobManager; +import com.zmops.zeus.iot.server.transfer.core.manager.AgentManager; +import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.*; + +/** + * Task manager maintains lots of tasks and communicate with job level components. + * It also provide functions to execute commands from job level like killing/submit tasks. + */ +public class TaskManager extends AbstractDaemon { + + private static final Logger LOGGER = LoggerFactory.getLogger(JobManager.class); + + // task thread pool; + private final ThreadPoolExecutor runningPool; + private final AgentManager agentManager; + private final TaskMetrics taskMetrics; + + private final ConcurrentHashMap tasks; + private final BlockingQueue retryTasks; + + private final int monitorInterval; + private final int taskMaxCapacity; + private final int taskRetryMaxTime; + private final long waitTime; + + /** + * Init task manager. + * + * @param agentManager - agent manager + */ + public TaskManager(AgentManager agentManager) { + this.agentManager = agentManager; + this.runningPool = new ThreadPoolExecutor( + 0, Integer.MAX_VALUE, + 60L, TimeUnit.SECONDS, + new SynchronousQueue<>(), + new AgentThreadFactory("task")); + // metric for task level + taskMetrics = TaskMetrics.create(); + tasks = new ConcurrentHashMap<>(); + + AgentConfiguration conf = AgentConfiguration.getAgentConf(); + + retryTasks = new LinkedBlockingQueue<>(conf.getInt(AgentConstants.TASK_RETRY_MAX_CAPACITY, AgentConstants.DEFAULT_TASK_RETRY_MAX_CAPACITY)); + + monitorInterval = conf.getInt(AgentConstants.TASK_MONITOR_INTERVAL, AgentConstants.DEFAULT_TASK_MONITOR_INTERVAL); + taskRetryMaxTime = conf.getInt(AgentConstants.TASK_RETRY_SUBMIT_WAIT_SECONDS, AgentConstants.DEFAULT_TASK_RETRY_SUBMIT_WAIT_SECONDS); + taskMaxCapacity = conf.getInt(AgentConstants.TASK_RETRY_MAX_CAPACITY, AgentConstants.DEFAULT_TASK_RETRY_MAX_CAPACITY); + waitTime = conf.getLong(AgentConstants.THREAD_POOL_AWAIT_TIME, AgentConstants.DEFAULT_THREAD_POOL_AWAIT_TIME); + } + + /** + * Get task metrics + * + * @return task metrics + */ + public TaskMetrics getTaskMetrics() { + return taskMetrics; + } + + public TaskWrapper getTaskWrapper(String taskId) { + return tasks.get(taskId); + } + + /** + * submit task, wait if task queue is full. + * + * @param task - task + */ + public void submitTask(Task task) { + TaskWrapper taskWrapper = new TaskWrapper(agentManager, task); + submitTask(taskWrapper); + + } + + public void submitTask(TaskWrapper wrapper) { + TaskWrapper retTaskWrapper = tasks.putIfAbsent(wrapper.getTask().getTaskId(), wrapper); + + if (retTaskWrapper == null) { + // pool may be full + boolean notSubmitted = true; + while (notSubmitted) { + try { + this.runningPool.submit(wrapper); + notSubmitted = false; + } catch (Exception ex) { + AgentUtils.silenceSleepInMs(waitTime); + LOGGER.warn("reject task {}", wrapper.getTask().getTaskId(), ex); + } + } + + taskMetrics.runningTasks.incr(); + } + } + + /** + * retry task. + * + * @param wrapper - task wrapper + */ + private boolean addRetryTask(TaskWrapper wrapper) { + LOGGER.info("retry submit task {}", wrapper.getTask().getTaskId()); + try { + boolean success = retryTasks.offer(wrapper, taskRetryMaxTime, TimeUnit.SECONDS); + if (!success) { + LOGGER.error("cannot submit to retry queue, max {}, current {}", taskMaxCapacity, + retryTasks.size()); + } else { + taskMetrics.retryingTasks.incr(); + } + return success; + } catch (Exception ex) { + LOGGER.error("error while offer task", ex); + } + return false; + } + + /** + * Check whether task is finished + * + * @param taskId - task id + * @return - true if task is finished otherwise false + */ + public boolean isTaskFinished(String taskId) { + TaskWrapper wrapper = tasks.get(taskId); + if (wrapper != null) { + return wrapper.isFinished(); + } + return false; + } + + /** + * Check if task is success + * + * @param taskId task id + * @return true if task is success otherwise false + */ + public boolean isTaskSuccess(String taskId) { + TaskWrapper wrapper = tasks.get(taskId); + if (wrapper != null) { + return wrapper.isSuccess(); + } + return false; + } + + /** + * Remove task and wait task to finish by task id + * + * @param taskId - task id + */ + public void removeTask(String taskId) { + taskMetrics.runningTasks.decr(); + TaskWrapper taskWrapper = tasks.remove(taskId); + if (taskWrapper != null) { + taskWrapper.waitForFinish(); + } + } + + /** + * kill task + * + * @param task task + * @return + */ + public boolean killTask(Task task) { + // kill running tasks. + TaskWrapper taskWrapper = tasks.get(task.getTaskId()); + if (taskWrapper != null) { + taskWrapper.kill(); + return true; + } + return false; + } + + /** + * Thread for checking whether task should retry. + * + * @return - runnable thread + */ + public Runnable createTaskMonitorThread() { + return () -> { + while (isRunnable()) { + try { + for (String taskId : tasks.keySet()) { + TaskWrapper wrapper = tasks.get(taskId); + if (wrapper != null && wrapper.isFailed() && wrapper.shouldRetry()) { + boolean success = addRetryTask(wrapper); + if (success) { + removeTask(taskId); + } + } + } + while (!retryTasks.isEmpty()) { + TaskWrapper taskWrapper = retryTasks.poll(); + if (taskWrapper != null) { + taskMetrics.retryingTasks.decr(); + submitTask(taskWrapper); + } + } + TimeUnit.SECONDS.sleep(monitorInterval); + } catch (Exception ex) { + LOGGER.error("Exception caught", ex); + } + } + }; + } + + /** + * start service. + */ + @Override + public void start() { + submitWorker(createTaskMonitorThread()); + } + + /** + * stop service. + */ + @Override + public void stop() throws Exception { + waitForTerminate(); + this.runningPool.shutdown(); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java new file mode 100644 index 00000000..182c4377 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.task; + +import com.zmops.zeus.iot.server.transfer.core.metrics.Metric; +import com.zmops.zeus.iot.server.transfer.core.metrics.Metrics; +import com.zmops.zeus.iot.server.transfer.core.metrics.MetricsRegister; +import com.zmops.zeus.iot.server.transfer.core.metrics.counter.CounterLong; +import com.zmops.zeus.iot.server.transfer.core.metrics.gauge.GaugeInt; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Metric collector for task level. + */ +@Metrics +public class TaskMetrics { + + private static final TaskMetrics TASK_METRICS = new TaskMetrics(); + private static final AtomicBoolean REGISTER_ONCE = new AtomicBoolean(false); + + @Metric + GaugeInt runningTasks; + + @Metric + GaugeInt retryingTasks; + + @Metric + CounterLong fatalTasks; + + private TaskMetrics() { + } + + public static TaskMetrics create() { + // register one time. + if (REGISTER_ONCE.compareAndSet(false, true)) { + MetricsRegister.register("Task", "StateSummary", null, TASK_METRICS); + } + return TASK_METRICS; + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java new file mode 100644 index 00000000..f397c053 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java @@ -0,0 +1,153 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.task; + + +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; +import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; +import com.zmops.zeus.iot.server.transfer.core.manager.AgentManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +import static com.zmops.zeus.iot.server.transfer.conf.CommonConstants.POSITION_SUFFIX; + +/** + * used to store task position to db, task position is stored as properties in JobProfile. + * where key is task read file name and value is task sink position + * note that this class is generated + */ +public class TaskPositionManager extends AbstractDaemon { + + private static final Logger LOGGER = LoggerFactory.getLogger(TaskPositionManager.class); + public static final int DEFAULT_FLUSH_TIMEOUT = 30; + + private final AgentManager agentManager; + private final JobProfileDb jobConfDb; + + private ConcurrentHashMap> jobTaskPositionMap; + + private static volatile TaskPositionManager taskPositionManager = null; + + private TaskPositionManager(AgentManager agentManager) { + this.agentManager = agentManager; + this.jobConfDb = agentManager.getJobManager().getJobConfDb(); + this.jobTaskPositionMap = new ConcurrentHashMap<>(); + } + + /** + * task position manager singleton, can only generated by agent manager + * + * @param agentManager + * @return + */ + public static TaskPositionManager getTaskPositionManager(AgentManager agentManager) { + if (taskPositionManager == null) { + synchronized (TaskPositionManager.class) { + if (taskPositionManager == null) { + taskPositionManager = new TaskPositionManager(agentManager); + } + } + } + return taskPositionManager; + } + + /** + * get taskPositionManager singleton + * + * @return + */ + public static TaskPositionManager getTaskPositionManager() { + if (taskPositionManager == null) { + throw new RuntimeException("task position manager has not been initialized by agentManager"); + } + return taskPositionManager; + } + + @Override + public void start() throws Exception { + submitWorker(taskPositionFlushThread()); + } + + private Runnable taskPositionFlushThread() { + return () -> { + while (isRunnable()) { + try { + // check pending jobs and try to submit again. + for (String jobId : jobTaskPositionMap.keySet()) { + JobProfile jobProfile = jobConfDb.getJobProfile(jobId); + if (jobProfile == null) { + LOGGER.warn("jobProfile {} cannot be found in db, " + + "might be deleted by standalone mode, now delete job position in memory", jobId); + deleteJobPosition(jobId); + continue; + } + flushJobProfile(jobId, jobProfile); + } + TimeUnit.SECONDS.sleep(DEFAULT_FLUSH_TIMEOUT); + } catch (Exception ex) { + LOGGER.error("error caught", ex); + } + } + }; + } + + + private void flushJobProfile(String jobId, JobProfile jobProfile) { + jobTaskPositionMap.get(jobId).forEach( + (fileName, position) -> jobProfile.setLong(fileName + POSITION_SUFFIX, position) + ); + if (jobConfDb.checkJobfinished(jobProfile)) { + LOGGER.info("Cannot update job profile {}, delete memory job in jobTaskPosition", jobId); + deleteJobPosition(jobId); + } else { + jobConfDb.updateJobProfile(jobProfile); + } + } + + private void deleteJobPosition(String jobId) { + jobTaskPositionMap.remove(jobId); + } + + @Override + public void stop() throws Exception { + waitForTerminate(); + } + + public void updateFileSinkPosition(String jobInstanceId, String sourceFilePath, long size) { + ConcurrentHashMap filePositionTemp = new ConcurrentHashMap<>(); + ConcurrentHashMap filePosition = jobTaskPositionMap.putIfAbsent(jobInstanceId, filePositionTemp); + if (filePosition == null) { + filePosition = filePositionTemp; + } + Long beforePosition = filePosition.getOrDefault(sourceFilePath, 1L); + filePosition.put(sourceFilePath, beforePosition + size); + } + + + public ConcurrentHashMap getTaskPositionMap(String jobId) { + return jobTaskPositionMap.get(jobId); + } + + public ConcurrentHashMap> getJobTaskPosition() { + return jobTaskPositionMap; + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java new file mode 100644 index 00000000..979c1e26 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java @@ -0,0 +1,196 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.task; + + +import com.zmops.zeus.iot.server.transfer.conf.AgentConfiguration; +import com.zmops.zeus.iot.server.transfer.conf.AgentConstants; +import com.zmops.zeus.iot.server.transfer.core.api.Message; +import com.zmops.zeus.iot.server.transfer.core.common.AgentThreadFactory; +import com.zmops.zeus.iot.server.transfer.core.manager.AgentManager; +import com.zmops.zeus.iot.server.transfer.core.message.EndMessage; +import com.zmops.zeus.iot.server.transfer.core.state.AbstractStateWrapper; +import com.zmops.zeus.iot.server.transfer.core.state.State; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * TaskWrapper is used in taskManager, it maintains the life cycle of + * running task. + */ +public class TaskWrapper extends AbstractStateWrapper { + + private static final Logger LOGGER = LoggerFactory.getLogger(TaskWrapper.class); + public static final int WAIT_FINISH_TIME_OUT = 1; + + private final TaskManager taskManager; + private final Task task; + + private final AtomicInteger retryTime = new AtomicInteger(0); + + private final int maxRetryTime; + private final int pushMaxWaitTime; + private final int pullMaxWaitTime; + + private ExecutorService executorService; + + public TaskWrapper(AgentManager manager, Task task) { + super(); + this.taskManager = manager.getTaskManager(); + this.task = task; + + AgentConfiguration conf = AgentConfiguration.getAgentConf(); + + maxRetryTime = conf.getInt(AgentConstants.TASK_MAX_RETRY_TIME, AgentConstants.DEFAULT_TASK_MAX_RETRY_TIME); + pushMaxWaitTime = conf.getInt(AgentConstants.TASK_PUSH_MAX_SECOND, AgentConstants.DEFAULT_TASK_PUSH_MAX_SECOND); + pullMaxWaitTime = conf.getInt(AgentConstants.TASK_PULL_MAX_SECOND, AgentConstants.DEFAULT_TASK_PULL_MAX_SECOND); + + if (executorService == null) { + executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, + 60L, TimeUnit.SECONDS, + new SynchronousQueue(), + new AgentThreadFactory("task-reader-writer")); + } + + doChangeState(State.ACCEPTED); + } + + /** + * submit read thread + * + * @return CompletableFuture + */ + private CompletableFuture submitReadThread() { + return CompletableFuture.runAsync(() -> { + Message message = null; + while (!isException() && !task.isReadFinished()) { + if (message == null || task.getChannel().push(message, pushMaxWaitTime, TimeUnit.SECONDS)) { + message = task.getReader().read(); + } + } + LOGGER.info("read end, task exception status is {}, read finish status is {}", isException(), task.isReadFinished()); + // write end message + task.getChannel().push(new EndMessage()); + }, executorService); + } + + /** + * submit write thread + * + * @return CompletableFuture + */ + private CompletableFuture submitWriteThread() { + return CompletableFuture.runAsync(() -> { + while (!isException()) { + Message message = task.getChannel().pull(pullMaxWaitTime, TimeUnit.SECONDS); + if (message instanceof EndMessage) { + break; + } + task.getSink().write(message); + } + }, executorService); + } + + /** + * submit reader/writer + */ + private void submitThreadsAndWait() { + CompletableFuture reader = submitReadThread(); + CompletableFuture writer = submitWriteThread(); + CompletableFuture.allOf(reader, writer) + .exceptionally(ex -> { + doChangeState(State.FAILED); + LOGGER.error("exception caught", ex); + return null; + }).join(); + } + + /** + * kill task + */ + void kill() { + LOGGER.info("task id {} is killed", task.getTaskId()); + doChangeState(State.KILLED); + } + + /** + * In standalone mode, the job to be removed should wait until the read is finished, set + * timeout to WAIT_FINISH_TIME_OUT minute to wait for finishing + */ + void waitForFinish() { + LOGGER.info("set readTime out to 1 minute task id is {}", task.getTaskId()); + task.getReader().setReadTimeout(TimeUnit.MINUTES.toMillis(WAIT_FINISH_TIME_OUT)); + } + + /** + * whether task retry times exceed max retry time. + * + * @return - whether should retry + */ + boolean shouldRetry() { + return retryTime.get() < maxRetryTime; + } + + Task getTask() { + return task; + } + + @Override + public void addCallbacks() { + this.addCallback(State.ACCEPTED, State.RUNNING, (before, after) -> { + + }).addCallback(State.RUNNING, State.FAILED, (before, after) -> { + LOGGER.info("task {} is failed, please check it", task.getTaskId()); + retryTime.incrementAndGet(); + if (!shouldRetry()) { + doChangeState(State.FATAL); + taskManager.getTaskMetrics().fatalTasks.incr(); + } + }).addCallback(State.FAILED, State.FATAL, (before, after) -> { + + }).addCallback(State.FAILED, State.ACCEPTED, (before, after) -> { + + }).addCallback(State.FAILED, State.RUNNING, ((before, after) -> { + + })).addCallback(State.RUNNING, State.SUCCEEDED, (before, after) -> { + + }); + } + + + @Override + public void run() { + try { + LOGGER.info("start to run {}, retry time is {}", task.getTaskId(), retryTime.get()); + doChangeState(State.RUNNING); + task.init(); + submitThreadsAndWait(); + if (!isException()) { + doChangeState(State.SUCCEEDED); + } + LOGGER.info("start to destroy task {}", task.getTaskId()); + task.destroy(); + } catch (Exception ex) { + LOGGER.error("error while running wrapper", ex); + doChangeState(State.FAILED); + } + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java new file mode 100644 index 00000000..31f1ff98 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java @@ -0,0 +1,275 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.trigger; + +import com.zmops.zeus.iot.server.transfer.conf.AgentConstants; +import com.zmops.zeus.iot.server.transfer.conf.JobConstants; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; +import com.zmops.zeus.iot.server.transfer.core.api.Trigger; +import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; +import com.zmops.zeus.iot.server.transfer.core.utils.PluginUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.nio.file.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; + + +/** + * Watch directory, if new valid files are created, create + * jobs correspondingly. + */ +public class DirectoryTrigger extends AbstractDaemon implements Trigger { + + private static final Logger LOGGER = LoggerFactory.getLogger(DirectoryTrigger.class); + private static volatile WatchService watchService; + + private final ConcurrentHashMap> allWatchers = new ConcurrentHashMap<>(); + private final LinkedBlockingQueue queue = new LinkedBlockingQueue<>(); + + private TriggerProfile profile; + private int interval; + + private static void initWatchService() { + try { + if (watchService == null) { + synchronized (DirectoryTrigger.class) { + if (watchService == null) { + watchService = FileSystems.getDefault().newWatchService(); + LOGGER.info("init watch service {}", watchService); + } + } + } + } catch (Exception ex) { + LOGGER.warn("error while init watch service", ex); + } + } + + public TriggerProfile getProfile() { + return profile; + } + + @Override + public void destroy() { + try { + stop(); + } catch (Exception ex) { + LOGGER.error("exception while stopping threads", ex); + } + } + + @Override + public JobProfile fetchJobProfile() { + return queue.poll(); + } + + @Override + public TriggerProfile getTriggerProfile() { + return profile; + } + + @Override + public void stop() { + waitForTerminate(); + releaseResource(); + } + + /** + * register all sub-directory + * + * @param entity - entity + * @param path - path + * @param tmpWatchers - watchers + */ + private void registerAllSubDir(PathPattern entity, + Path path, + List tmpWatchers) throws Exception { + // check regex + LOGGER.info("check whether path {} is suitable", path); + if (entity.suitForWatch(path.toString())) { + if (path.toFile().isDirectory()) { + WatchKey watchKey = path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE); + tmpWatchers.add(watchKey); + try (Stream stream = Files.list(path)) { + Iterator iterator = stream.iterator(); + while (iterator.hasNext()) { + registerAllSubDir(entity, iterator.next().toAbsolutePath(), tmpWatchers); + } + } + } else { + JobProfile copiedJobProfile = PluginUtils.copyJobProfile(profile, entity.getSuitTime(), path.toFile()); + LOGGER.info("trigger {} generate job profile to read file {}", getTriggerProfile().getTriggerId(), path.toString()); + queue.offer(copiedJobProfile); + } + } + } + + /** + * if directory has created, then check whether directory is valid + * + * @param entity - entity + * @param watchKey - watch key + * @param tmpWatchers - watchers + */ + private void registerNewDir(PathPattern entity, + WatchKey watchKey, + List tmpWatchers, + List tmpDeletedWatchers) throws Exception { + Path parentPath = (Path) watchKey.watchable(); + for (WatchEvent event : watchKey.pollEvents()) { + // if watch event is too much, then event would be overflow. + if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE) { + // only watch create event, so else is create-event. + entity.updateDateFormatRegex(); + Path createdPath = (Path) event.context(); + if (createdPath != null) { + registerAllSubDir(entity, parentPath.resolve(createdPath), tmpWatchers); + } + } else if (event.kind() == StandardWatchEventKinds.OVERFLOW) { + LOGGER.info("overflow got {}", parentPath); + // check whether parent path is valid. + if (Files.isDirectory(parentPath)) { + for (Iterator it = Files.list(parentPath).iterator(); it.hasNext(); ) { + Path childPath = it.next(); + registerAllSubDir(entity, parentPath.resolve(childPath), tmpWatchers); + } + } + } + } + if (!Files.exists(parentPath)) { + LOGGER.warn("{} not exist, add watcher to pending delete list", parentPath); + tmpDeletedWatchers.add(watchKey); + } + } + + /** + * handler watchers + * + * @return runnable + */ + private Runnable watchEventHandler() { + return () -> { + while (isRunnable()) { + try { + TimeUnit.SECONDS.sleep(interval); + allWatchers.forEach((pathPattern, watchKeys) -> { + List tmpWatchers = new ArrayList<>(); + List tmpDeletedWatchers = new ArrayList<>(); + pathPattern.cleanup(); + try { + for (WatchKey watchKey : watchKeys) { + registerNewDir(pathPattern, watchKey, tmpWatchers, tmpDeletedWatchers); + } + } catch (Exception ex) { + LOGGER.error("error caught", ex); + } + watchKeys.addAll(tmpWatchers); + watchKeys.removeAll(tmpDeletedWatchers); + }); + } catch (Exception ex) { + LOGGER.error("error caught", ex); + } + } + }; + } + + private void releaseResource() { + allWatchers.forEach((absoluteFilePath, watchKeys) -> { + watchKeys.forEach(WatchKey::cancel); + }); + allWatchers.clear(); + } + + @Override + public void start() throws Exception { + submitWorker(watchEventHandler()); + } + + public void register(String pathPattern) throws IOException { + PathPattern entity = new PathPattern(pathPattern); + innerRegister(pathPattern, entity); + } + + public void register(String pathPattern, String offset) throws IOException { + PathPattern entity = new PathPattern(pathPattern, offset); + innerRegister(pathPattern, entity); + } + + private void innerRegister(String pathPattern, PathPattern entity) throws IOException { + List tmpKeyList = new ArrayList<>(); + List keyList = allWatchers.putIfAbsent(entity, tmpKeyList); + if (keyList == null) { + Path rootPath = Paths.get(entity.getRootDir()); + LOGGER.info("watch root path is {}", rootPath); + WatchKey key = rootPath.register(watchService, StandardWatchEventKinds.ENTRY_CREATE); + tmpKeyList.add(key); + } else { + LOGGER.error("{} exists in watcher list, please check it", pathPattern); + } + } + + public void unregister(String pathPattern) { + PathPattern entity = new PathPattern(pathPattern); + Collection allKeys = allWatchers.remove(entity); + if (allKeys != null) { + LOGGER.info("unregister pattern {}, total size of path {}", pathPattern, + allKeys.size()); + for (WatchKey key : allKeys) { + key.cancel(); + } + } + } + + ConcurrentHashMap> getAllWatchers() { + return allWatchers; + } + + @Override + public void init(TriggerProfile profile) throws IOException { + initWatchService(); + interval = profile.getInt(AgentConstants.TRIGGER_CHECK_INTERVAL, AgentConstants.DEFAULT_TRIGGER_CHECK_INTERVAL); + this.profile = profile; + + if (this.profile.hasKey(JobConstants.JOB_DIR_FILTER_PATTERN)) { + String pathPattern = this.profile.get(JobConstants.JOB_DIR_FILTER_PATTERN); + String timeOffset = this.profile.get(JobConstants.JOB_FILE_TIME_OFFSET, ""); + if (timeOffset.isEmpty()) { + register(pathPattern); + } + register(pathPattern, timeOffset); + } + } + + @Override + public void run() { + try { + start(); + } catch (Exception exception) { + throw new IllegalStateException(exception); + } + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/trigger/PathPattern.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/PathPattern.java similarity index 94% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/trigger/PathPattern.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/PathPattern.java index 2dc1cde5..09475217 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/trigger/PathPattern.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/PathPattern.java @@ -15,9 +15,9 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.trigger; +package com.zmops.zeus.iot.server.transfer.core.trigger; -import com.zmops.zeus.iot.server.transfer.filter.DateFormatRegex; +import com.zmops.zeus.iot.server.transfer.core.filter.DateFormatRegex; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -34,7 +34,9 @@ import java.util.Set; /** - * path pattern for file filter. + * path pattern for file filter. 文件匹配 + * + * @editor nantian */ public class PathPattern { @@ -86,12 +88,12 @@ private String findRoot(String watchDir) { * @param collectResult * @param maxNum */ - private void walkAllSuitableFiles(File dirPath, final Collection collectResult, - int maxNum) throws IOException { + private void walkAllSuitableFiles(File dirPath, final Collection collectResult, int maxNum) throws IOException { if (collectResult.size() > maxNum) { LOGGER.warn("max num of files is {}, please check", maxNum); return; } + if (dirPath.isFile() && dateFormatRegex.withFile(dirPath).match()) { collectResult.add(dirPath); } else if (dirPath.isDirectory()) { @@ -112,8 +114,7 @@ private void walkAllSuitableFiles(File dirPath, final Collection collectRe * @param maxNum * @throws IOException */ - public void walkAllSuitableFiles(final Collection collectResult, - int maxNum) throws IOException { + public void walkAllSuitableFiles(final Collection collectResult, int maxNum) throws IOException { walkAllSuitableFiles(new File(rootDir), collectResult, maxNum); } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java new file mode 100644 index 00000000..ca0cd4a3 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java @@ -0,0 +1,246 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.trigger; + + +import com.zmops.zeus.iot.server.transfer.conf.*; +import com.zmops.zeus.iot.server.transfer.core.api.Trigger; +import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; +import com.zmops.zeus.iot.server.transfer.core.db.TriggerProfileDb; +import com.zmops.zeus.iot.server.transfer.core.job.JobWrapper; +import com.zmops.zeus.iot.server.transfer.core.manager.AgentManager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +import static com.zmops.zeus.iot.server.transfer.conf.AgentConstants.DEFAULT_TRIGGER_MAX_RUNNING_NUM; +import static com.zmops.zeus.iot.server.transfer.conf.AgentConstants.TRIGGER_MAX_RUNNING_NUM; +import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_ID; +import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.TRIGGER_ONLY_ONE_JOB; + +/** + * manager for triggers. + */ +public class TriggerManager extends AbstractDaemon { + + private static final Logger LOGGER = LoggerFactory.getLogger(TriggerManager.class); + public static final int JOB_CHECK_INTERVAL = 1; + + private final AgentManager manager; + private final TriggerProfileDb triggerProfileDB; + private final ConcurrentHashMap triggerMap; + + private final ConcurrentHashMap> triggerJobMap; + + private final AgentConfiguration conf; + + private final int triggerFetchInterval; + private final int maxRunningNum; + + public TriggerManager(AgentManager manager, TriggerProfileDb triggerProfileDb) { + this.conf = AgentConfiguration.getAgentConf(); + this.manager = manager; + this.triggerProfileDB = triggerProfileDb; + this.triggerMap = new ConcurrentHashMap<>(); + this.triggerJobMap = new ConcurrentHashMap<>(); + this.triggerFetchInterval = conf.getInt(AgentConstants.TRIGGER_FETCH_INTERVAL, AgentConstants.DEFAULT_TRIGGER_FETCH_INTERVAL); + this.maxRunningNum = conf.getInt(TRIGGER_MAX_RUNNING_NUM, DEFAULT_TRIGGER_MAX_RUNNING_NUM); + } + + /** + * submit trigger profile. + * + * @param triggerProfile - trigger profile + */ + public boolean addTrigger(TriggerProfile triggerProfile) { + try { + Class triggerClass = Class.forName(triggerProfile.get(JobConstants.JOB_TRIGGER)); + Trigger trigger = (Trigger) triggerClass.newInstance(); + String triggerId = triggerProfile.get(JOB_ID); + if (triggerMap.containsKey(triggerId)) { + deleteTrigger(triggerId); + LOGGER.warn("trigger {} is running, stop it", triggerId); + } + triggerMap.put(triggerId, trigger); + trigger.init(triggerProfile); + trigger.run(); + } catch (Exception ex) { + LOGGER.error("exception caught", ex); + return false; + } + return true; + } + + + public Trigger getTrigger(String triggerId) { + return triggerMap.get(triggerId); + } + + public boolean submitTrigger(TriggerProfile triggerProfile) { + // make sure all required key exists. + if (!triggerProfile.allRequiredKeyExist() || this.triggerMap.size() > maxRunningNum) { + LOGGER.error("trigger {} not all required key exists or size {} exceed {}", triggerProfile.toJsonStr(), this.triggerMap.size(), maxRunningNum); + return false; + } + triggerProfileDB.storeTrigger(triggerProfile); + addTrigger(triggerProfile); + return true; + } + + + private Runnable jobFetchThread() { + return () -> { + while (isRunnable()) { + try { + triggerMap.forEach((s, trigger) -> { + JobProfile profile = trigger.fetchJobProfile(); + if (profile != null) { + TriggerProfile triggerProfile = trigger.getTriggerProfile(); + if (triggerProfile.getBoolean(TRIGGER_ONLY_ONE_JOB, false)) { + deleteRelatedJobs(triggerProfile.getTriggerId()); + } + manager.getJobManager().submitJobProfile(profile); + addToTriggerMap(profile.get(JOB_ID), profile); + } + }); + TimeUnit.SECONDS.sleep(triggerFetchInterval); + } catch (Exception ignored) { + LOGGER.info("ignored Exception ", ignored); + } + } + + }; + } + + /** + * delete jobs generated by the trigger + * + * @param triggerId + */ + private void deleteRelatedJobs(String triggerId) { + LOGGER.info("start to delete related jobs in triggerId {}", triggerId); + ConcurrentHashMap jobProfiles = + triggerJobMap.get(triggerId); + if (jobProfiles != null) { + LOGGER.info("trigger can only run one job, stop the others {}", jobProfiles.keySet()); + jobProfiles.keySet().forEach(this::deleteJob); + triggerJobMap.remove(triggerId); + } + } + + private void deleteJob(String jobInstanceId) { + manager.getJobManager().deleteJob(jobInstanceId); + } + + + private Runnable jobCheckThread() { + return () -> { + while (isRunnable()) { + try { + triggerJobMap.forEach((s, jobProfiles) -> { + for (String jobId : jobProfiles.keySet()) { + Map jobs = manager.getJobManager().getJobs(); + if (jobs.get(jobId) == null) { + triggerJobMap.remove(jobId); + } + } + }); + TimeUnit.MINUTES.sleep(JOB_CHECK_INTERVAL); + } catch (Exception ignored) { + LOGGER.info("ignored Exception ", ignored); + } + } + + }; + } + + /** + * need to put profile in triggerJobMap + * + * @param triggerId + * @param profile + */ + private void addToTriggerMap(String triggerId, JobProfile profile) { + ConcurrentHashMap tmpList = + new ConcurrentHashMap<>(); + ConcurrentHashMap jobWrappers = + triggerJobMap.putIfAbsent(triggerId, tmpList); + if (jobWrappers == null) { + jobWrappers = tmpList; + } + jobWrappers.putIfAbsent(profile.getInstanceId(), profile); + } + + /** + * delete trigger by trigger profile. + * + * @param triggerId - trigger profile. + */ + public boolean deleteTrigger(String triggerId) { + LOGGER.info("delete trigger {}", triggerId); + Trigger trigger = triggerMap.remove(triggerId); + if (trigger != null) { + deleteRelatedJobs(triggerId); + trigger.destroy(); + // delete trigger from db + triggerProfileDB.deleteTrigger(triggerId); + return true; + } + LOGGER.warn("cannot find trigger {}", triggerId); + return false; + } + + + /** + * init all triggers when daemon started. + */ + private void initTriggers() throws Exception { + // fetch all triggers from db + List profileList = triggerProfileDB.getTriggers(); + for (TriggerProfile profile : profileList) { + addTrigger(profile); + } + } + + private void stopTriggers() { + triggerMap.forEach((s, trigger) -> { + trigger.destroy(); + }); + } + + @Override + public void start() throws Exception { + initTriggers(); + submitWorker(jobFetchThread()); + submitWorker(jobCheckThread()); + } + + + @Override + public void stop() { + // stop all triggers + stopTriggers(); + } + + +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/AgentUtils.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/AgentUtils.java similarity index 99% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/AgentUtils.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/AgentUtils.java index c7dd766f..c1001c28 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/AgentUtils.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/AgentUtils.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.utils; +package com.zmops.zeus.iot.server.transfer.core.utils; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.StringUtils; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/ByteUtil.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/ByteUtil.java similarity index 99% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/ByteUtil.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/ByteUtil.java index 22ff987b..a429eee4 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/ByteUtil.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/ByteUtil.java @@ -16,7 +16,7 @@ */ -package com.zmops.zeus.iot.server.transfer.utils; +package com.zmops.zeus.iot.server.transfer.core.utils; import java.util.ArrayList; import java.util.List; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/PluginUtils.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/PluginUtils.java similarity index 95% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/PluginUtils.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/PluginUtils.java index 8fdc8c70..9fb8cfe7 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/PluginUtils.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/PluginUtils.java @@ -15,14 +15,14 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.utils; +package com.zmops.zeus.iot.server.transfer.core.utils; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.zmops.zeus.iot.server.transfer.conf.JobConstants; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; -import com.zmops.zeus.iot.server.transfer.trigger.PathPattern; +import com.zmops.zeus.iot.server.transfer.core.trigger.PathPattern; import lombok.extern.slf4j.Slf4j; import org.slf4j.Logger; @@ -50,7 +50,6 @@ public class PluginUtils { private static final Logger LOGGER = LoggerFactory.getLogger(PluginUtils.class); - public static String toJsonStr(Object obj) { GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.setPrettyPrinting(); @@ -62,10 +61,13 @@ public static String toJsonStr(Object obj) { public static Collection findSuitFiles(JobProfile jobConf) { String dirPattern = jobConf.get(JOB_DIR_FILTER_PATTERN); LOGGER.info("start to find files with dir pattern {}", dirPattern); + PathPattern pattern = new PathPattern(dirPattern); updateRetryTime(jobConf, pattern); + int maxFileNum = jobConf.getInt(FILE_MAX_NUM, DEFAULT_FILE_MAX_NUM); LOGGER.info("dir pattern {}, max file num {}", dirPattern, maxFileNum); + Collection allFiles = new ArrayList<>(); try { pattern.walkAllSuitableFiles(allFiles, maxFileNum); @@ -83,8 +85,7 @@ public static Collection findSuitFiles(JobProfile jobConf) { */ public static void updateRetryTime(JobProfile jobConf, PathPattern pattern) { if (jobConf.hasKey(JOB_RETRY_TIME)) { - LOGGER.info("job {} is retry job with specific time, update file time to {}" - + "", jobConf.toJsonStr(), jobConf.get(JOB_RETRY_TIME)); + LOGGER.info("job {} is retry job with specific time, update file time to {}" + "", jobConf.toJsonStr(), jobConf.get(JOB_RETRY_TIME)); pattern.updateDateFormatRegex(jobConf.get(JOB_RETRY_TIME)); } } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/validator/PatternValidator.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PatternValidator.java similarity index 89% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/validator/PatternValidator.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PatternValidator.java index 780675d7..a35e3ee8 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/validator/PatternValidator.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PatternValidator.java @@ -15,10 +15,10 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.validator; +package com.zmops.zeus.iot.server.transfer.core.validator; -import com.zmops.zeus.iot.server.transfer.api.Validator; +import com.zmops.zeus.iot.server.transfer.core.api.Validator; public class PatternValidator implements Validator { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/validator/PrefixValidator.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PrefixValidator.java similarity index 89% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/validator/PrefixValidator.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PrefixValidator.java index 5de00291..ece5e83b 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/validator/PrefixValidator.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PrefixValidator.java @@ -15,9 +15,9 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.transfer.validator; +package com.zmops.zeus.iot.server.transfer.core.validator; -import com.zmops.zeus.iot.server.transfer.api.Validator; +import com.zmops.zeus.iot.server.transfer.core.api.Validator; public class PrefixValidator implements Validator { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/module/ServerTransferModule.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/module/ServerTransferModule.java new file mode 100644 index 00000000..2b40d290 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/module/ServerTransferModule.java @@ -0,0 +1,21 @@ +package com.zmops.zeus.iot.server.transfer.module; + +import com.zmops.zeus.iot.server.library.module.ModuleDefine; + +/** + * @author nantian created at 2021/9/22 16:39 + */ +public class ServerTransferModule extends ModuleDefine { + + public static final String NAME = "server-transfer"; + + + public ServerTransferModule() { + super(NAME); + } + + @Override + public Class[] services() { + return new Class[0]; + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferConfig.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferConfig.java new file mode 100644 index 00000000..3580ffb8 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferConfig.java @@ -0,0 +1,13 @@ +package com.zmops.zeus.iot.server.transfer.provider; + +import com.zmops.zeus.iot.server.library.module.ModuleConfig; + +/** + * @author nantian created at 2021/9/22 16:46 + *

+ * ndjson 文件读取配置 + */ +public class ServerTransferConfig extends ModuleConfig { + + +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java new file mode 100644 index 00000000..03154d8f --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java @@ -0,0 +1,51 @@ +package com.zmops.zeus.iot.server.transfer.provider; + +import com.zmops.zeus.iot.server.library.module.*; +import com.zmops.zeus.iot.server.transfer.module.ServerTransferModule; + +/** + * @author nantian created at 2021/9/22 16:44 + */ +public class ServerTransferProvider extends ModuleProvider { + + private final ServerTransferConfig serverTransferConfig; + + public ServerTransferProvider() { + this.serverTransferConfig = new ServerTransferConfig(); + } + + @Override + public String name() { + return "default"; + } + + @Override + public Class module() { + return ServerTransferModule.class; + } + + @Override + public ModuleConfig createConfigBeanIfAbsent() { + return serverTransferConfig; + } + + @Override + public void prepare() throws ServiceNotProvidedException, ModuleStartException { + System.out.println(123); + } + + @Override + public void start() throws ServiceNotProvidedException, ModuleStartException { + + } + + @Override + public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { + + } + + @Override + public String[] requiredModules() { + return new String[0]; + } +} diff --git a/iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine b/iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine new file mode 100644 index 00000000..22ed049f --- /dev/null +++ b/iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# + +com.zmops.zeus.iot.server.transfer.module.ServerTransferModule diff --git a/iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider new file mode 100644 index 00000000..3f87ef2f --- /dev/null +++ b/iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# + +com.zmops.zeus.iot.server.transfer.provider.ServerTransferProvider diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java index 643d567b..542df924 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java @@ -39,24 +39,29 @@ public class MessageService { */ public void push(MessageBody body) { Objects.requireNonNull(body.getMsg()); + List tos; + if (!CollectionUtils.isEmpty(body.getTo())) { tos = body.getTo(); } else { List userList = new QSysUser().findList(); tos = userList.parallelStream().map(SysUser::getUserId).collect(Collectors.toList()); } + if (body.isPersist()) { tos.forEach(to -> { Messages messages = new Messages(); messages.setClassify(sys); messages.setTitle(body.getMsg()); messages.setUserId(to); + String content = ""; if (ToolUtil.isNotEmpty(body.getBody())) { content = JSON.toJSONString(body.getBody()); messages.setContent(content); } + messages.setClock(System.currentTimeMillis() / 1000); saveMessage(messages); }); @@ -77,6 +82,7 @@ public void push(MessageBody body) { public Pager list(MessageParam messageParam) { LoginUser user = LoginContextHolder.getContext().getUser(); QMessages qMessages = new QMessages(); + qMessages.userId.eq(user.getId()); if (messageParam.getReaded() != null) { From ea02906fb4a5e63242f7947c77c7ecbe8ee3358d Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 22 Sep 2021 22:04:51 +0800 Subject: [PATCH 259/763] [style]: change code style --- .../transfer/core/channel/MemoryChannel.java | 37 ++++++------ .../transfer/core/common/AbstractDaemon.java | 3 +- .../transfer/core/filter/DateFormatRegex.java | 7 +-- .../server/transfer/core/job/JobManager.java | 11 ++-- .../server/transfer/core/job/JobWrapper.java | 3 +- .../transfer/core/manager/AgentManager.java | 5 ++ .../transfer/core/metrics/PluginMetric.java | 53 +++++++++++++++++ .../core/source/reader/TextFileReader.java | 16 ++--- .../core/state/AbstractStateWrapper.java | 4 +- .../transfer/core/task/TaskManager.java | 1 + .../core/task/TaskPositionManager.java | 2 +- .../transfer/core/task/TaskWrapper.java | 14 +++-- .../transfer/core/utils/AgentUtils.java | 59 +++++++++++-------- .../transfer/core/utils/PluginUtils.java | 5 +- .../provider/ServerTransferProvider.java | 5 ++ 15 files changed, 153 insertions(+), 72 deletions(-) create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/PluginMetric.java diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java index 8a003878..f71136b9 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java @@ -22,6 +22,7 @@ import com.zmops.zeus.iot.server.transfer.core.api.Message; import com.zmops.zeus.iot.server.transfer.conf.AgentConstants; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import com.zmops.zeus.iot.server.transfer.core.metrics.PluginMetric; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,7 +35,7 @@ public class MemoryChannel implements Channel { private LinkedBlockingQueue queue; -// private final PluginMetric metric = new PluginMetric(); + private final PluginMetric metric = new PluginMetric(); /** * {@inheritDoc} @@ -43,12 +44,12 @@ public class MemoryChannel implements Channel { public void push(Message message) { try { if (message != null) { -// metric.readNum.incr(); + metric.readNum.incr(); queue.put(message); -// metric.readSuccessNum.incr(); + metric.readSuccessNum.incr(); } } catch (InterruptedException ex) { -// metric.readFailedNum.incr(); + metric.readFailedNum.incr(); Thread.currentThread().interrupt(); } } @@ -57,17 +58,17 @@ public void push(Message message) { public boolean push(Message message, long timeout, TimeUnit unit) { try { if (message != null) { -// metric.readNum.incr(); + metric.readNum.incr(); boolean result = queue.offer(message, timeout, unit); if (result) { -// metric.readSuccessNum.incr(); + metric.readSuccessNum.incr(); } else { -// metric.readFailedNum.incr(); + metric.readFailedNum.incr(); } return result; } } catch (InterruptedException ex) { -// metric.readFailedNum.incr(); + metric.readFailedNum.incr(); Thread.currentThread().interrupt(); } return false; @@ -81,11 +82,11 @@ public Message pull(long timeout, TimeUnit unit) { try { Message message = queue.poll(timeout, unit); if (message != null) { -// metric.sendSuccessNum.incr(); + metric.sendSuccessNum.incr(); } return message; } catch (InterruptedException ex) { -// metric.sendFailedNum.incr(); + metric.sendFailedNum.incr(); Thread.currentThread().interrupt(); throw new IllegalStateException(ex); } @@ -93,9 +94,8 @@ public Message pull(long timeout, TimeUnit unit) { @Override public void init(JobProfile jobConf) { - queue = new LinkedBlockingQueue<>( - jobConf.getInt(AgentConstants.CHANNEL_MEMORY_CAPACITY, - AgentConstants.DEFAULT_CHANNEL_MEMORY_CAPACITY)); + queue = new LinkedBlockingQueue<>(jobConf.getInt(AgentConstants.CHANNEL_MEMORY_CAPACITY, + AgentConstants.DEFAULT_CHANNEL_MEMORY_CAPACITY)); } @Override @@ -103,9 +103,12 @@ public void destroy() { if (queue != null) { queue.clear(); } -// LOGGER.info("destroy channel, memory channel metric, readNum: {}, readSuccessNum: {}, " -// + "readFailedNum: {}, sendSuccessNum: {}, sendFailedNum: {}", -// metric.readNum.snapshot(), metric.readSuccessNum.snapshot(), metric.readFailedNum.snapshot(), -// metric.sendSuccessNum.snapshot(), metric.sendFailedNum.snapshot()); + LOGGER.info("destroy channel, memory channel metric, readNum: {}, readSuccessNum: {}, " + + "readFailedNum: {}, sendSuccessNum: {}, sendFailedNum: {}", + metric.readNum.snapshot(), + metric.readSuccessNum.snapshot(), + metric.readFailedNum.snapshot(), + metric.sendSuccessNum.snapshot(), + metric.sendFailedNum.snapshot()); } } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AbstractDaemon.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AbstractDaemon.java index 7263d714..608ade6f 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AbstractDaemon.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AbstractDaemon.java @@ -76,8 +76,7 @@ public void stopRunningThreads() { public void submitWorker(Runnable worker) { CompletableFuture future = CompletableFuture.runAsync(worker, WORKER_SERVICES); workerFutures.add(future); - LOGGER.info("{} running worker number is {}", this.getClass().getName(), - workerFutures.size()); + LOGGER.info("{} running worker number is {}", this.getClass().getName(), workerFutures.size()); } /** diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java index 38b94c1e..9209b19a 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java @@ -106,8 +106,8 @@ public DateFormatRegex withFile(File file) { * @param time */ public void setRegexWithTime(String regex, String time) { - String[] regexList = StringUtils.splitByWholeSeparatorPreserveAllTokens(regex, - File.separator, 0); + String[] regexList = StringUtils.splitByWholeSeparatorPreserveAllTokens(regex, File.separator, 0); + List formattedList = new ArrayList<>(); for (String regexStr : regexList) { if (regexStr.contains(YEAR)) { @@ -126,8 +126,7 @@ public void setRegexWithTime(String regex, String time) { } public void setRegexWithCurrentTime(String regex) { - String currentTime = AgentUtils.formatCurrentTimeWithOffset(NORMAL_FORMATTER, - dayOffset, hourOffset, minuteOffset); + String currentTime = AgentUtils.formatCurrentTimeWithOffset(NORMAL_FORMATTER, dayOffset, hourOffset, minuteOffset); setRegexWithTime(regex, currentTime); } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java index 4df197fe..a102bf58 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java @@ -72,18 +72,20 @@ public class JobManager extends AbstractDaemon { public JobManager(AgentManager agentManager, JobProfileDb jobConfDb) { this.jobConfDB = jobConfDb; this.agentManager = agentManager; + // job thread pool for running this.runningPool = new ThreadPoolExecutor( 0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>(), new AgentThreadFactory("job")); + this.jobs = new ConcurrentHashMap<>(); this.pendingJobs = new ConcurrentHashMap<>(); + AgentConfiguration conf = AgentConfiguration.getAgentConf(); - this.monitorInterval = conf - .getInt( - AgentConstants.JOB_MONITOR_INTERVAL, AgentConstants.DEFAULT_JOB_MONITOR_INTERVAL); + + this.monitorInterval = conf.getInt(AgentConstants.JOB_MONITOR_INTERVAL, AgentConstants.DEFAULT_JOB_MONITOR_INTERVAL); this.jobDbCacheTime = conf.getLong(JOB_DB_CACHE_TIME, DEFAULT_JOB_DB_CACHE_TIME); this.jobDbCacheCheckInterval = conf.getLong(JOB_DB_CACHE_CHECK_INTERVAL, DEFAULT_JOB_DB_CACHE_CHECK_INTERVAL); this.jobMetrics = JobMetrics.create(); @@ -118,8 +120,7 @@ public void addJob(Job job) { */ public boolean submitJobProfile(JobProfile profile) { if (profile == null || !profile.allRequiredKeyExist()) { - LOGGER.error("profile is null or not all required key exists {}", profile == null ? null - : profile.toJsonStr()); + LOGGER.error("profile is null or not all required key exists {}", profile == null ? null : profile.toJsonStr()); return false; } String jobId = profile.get(JOB_ID); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java index 3cff3075..61a68d11 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java @@ -120,8 +120,7 @@ public void run() { cleanup(); } catch (Exception ex) { doChangeState(State.FAILED); - LOGGER.error("error caught: {}, message: {}", - job.getJobConf().toJsonStr(), ex.getMessage()); + LOGGER.error("error caught: {}, message: {}", job.getJobConf().toJsonStr(), ex.getMessage()); } } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/AgentManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/AgentManager.java index da05604c..5ae56818 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/AgentManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/AgentManager.java @@ -63,7 +63,9 @@ public class AgentManager extends AbstractDaemon { public AgentManager() { conf = AgentConfiguration.getAgentConf(); + this.db = initDb(); + commandDb = new CommandDb(db); String parentConfPath = conf.get(AGENT_CONF_PARENT, DEFAULT_AGENT_CONF_PARENT); @@ -185,11 +187,14 @@ public void stop() throws Exception { if (configJetty != null) { configJetty.close(); } + if (fetcher != null) { fetcher.stop(); } + // TODO: change job state which is in running state. LOGGER.info("stopping agent manager"); + // close in order: trigger -> job -> task triggerManager.stop(); jobManager.stop(); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/PluginMetric.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/PluginMetric.java new file mode 100644 index 00000000..00790015 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/PluginMetric.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.metrics; + +import com.zmops.zeus.iot.server.transfer.core.metrics.counter.CounterLong; + +/** + * Common plugin metrics + */ +@Metrics +public class PluginMetric { + + @Metric + public Tag tagName; + + @Metric + public CounterLong readNum; + + @Metric + public CounterLong sendNum; + + @Metric + public CounterLong sendFailedNum; + + @Metric + public CounterLong readFailedNum; + + @Metric + public CounterLong readSuccessNum; + + @Metric + public CounterLong sendSuccessNum; + + public PluginMetric() { + // every metric should register, otherwise not working. + MetricsRegister.register("Plugin", "PluginSummary", null, this); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java index 501f6dfa..43828fbe 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java @@ -24,6 +24,7 @@ import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.core.exception.FileException; import com.zmops.zeus.iot.server.transfer.core.message.DefaultMessage; +import com.zmops.zeus.iot.server.transfer.core.metrics.PluginMetric; import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; import com.zmops.zeus.iot.server.transfer.core.validator.PatternValidator; import org.apache.commons.lang3.StringUtils; @@ -54,9 +55,10 @@ public class TextFileReader implements Reader { private Iterator iterator; private Stream stream; private long timeout; - private long lastTime = 0; - // private final PluginMetric textFileMetric; - private List validators = new ArrayList<>(); + private long lastTime = 0; + + private final PluginMetric textFileMetric; + private final List validators = new ArrayList<>(); public TextFileReader(File file, int position) { this(file, position, ""); @@ -66,8 +68,8 @@ public TextFileReader(File file, int position, String md5) { this.file = file; this.position = position; this.md5 = md5; -// textFileMetric = new PluginMetric(); -// textFileMetric.tagName.setName(file.getAbsolutePath()); + textFileMetric = new PluginMetric(); + textFileMetric.tagName.setName(file.getAbsolutePath()); } public TextFileReader(File file) { @@ -79,7 +81,7 @@ public Message read() { if (iterator != null && iterator.hasNext()) { String message = iterator.next(); if (validateMessage(message)) { -// textFileMetric.readNum.incr(); + textFileMetric.readNum.incr(); return new DefaultMessage(message.getBytes(StandardCharsets.UTF_8)); } } @@ -160,6 +162,6 @@ private void initReadTimeout(JobProfile jobConf) { @Override public void destroy() { AgentUtils.finallyClose(stream); -// LOGGER.info("destroy reader with read {} num {}", textFileMetric.tagName.getName(), textFileMetric.readNum.snapshot()); + LOGGER.info("destroy reader with read {} num {}", textFileMetric.tagName.getName(), textFileMetric.readNum.snapshot()); } } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/AbstractStateWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/AbstractStateWrapper.java index 218bab74..2a0774e1 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/AbstractStateWrapper.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/AbstractStateWrapper.java @@ -56,7 +56,9 @@ public AbstractStateWrapper addCallback(State begin, State end, StateCallback ca public synchronized void doChangeState(State nextState) { LOGGER.debug("state change, current state is {}, next state is {}", currentState, nextState); Pair statePair = new ImmutablePair<>(currentState, nextState); - StateCallback callback = callBacks.get(statePair); + + StateCallback callback = callBacks.get(statePair); + // change state before callback. currentState = nextState; if (callback != null) { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java index 3ad9022b..3e2c2c3b 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java @@ -64,6 +64,7 @@ public TaskManager(AgentManager agentManager) { 60L, TimeUnit.SECONDS, new SynchronousQueue<>(), new AgentThreadFactory("task")); + // metric for task level taskMetrics = TaskMetrics.create(); tasks = new ConcurrentHashMap<>(); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java index f397c053..1ac517db 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java @@ -43,7 +43,7 @@ public class TaskPositionManager extends AbstractDaemon { private final AgentManager agentManager; private final JobProfileDb jobConfDb; - private ConcurrentHashMap> jobTaskPositionMap; + private final ConcurrentHashMap> jobTaskPositionMap; private static volatile TaskPositionManager taskPositionManager = null; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java index 979c1e26..993df5f6 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java @@ -115,12 +115,12 @@ private CompletableFuture submitWriteThread() { private void submitThreadsAndWait() { CompletableFuture reader = submitReadThread(); CompletableFuture writer = submitWriteThread(); - CompletableFuture.allOf(reader, writer) - .exceptionally(ex -> { - doChangeState(State.FAILED); - LOGGER.error("exception caught", ex); - return null; - }).join(); + + CompletableFuture.allOf(reader, writer).exceptionally(ex -> { + doChangeState(State.FAILED); + LOGGER.error("exception caught", ex); + return null; + }).join(); } /** @@ -182,10 +182,12 @@ public void run() { LOGGER.info("start to run {}, retry time is {}", task.getTaskId(), retryTime.get()); doChangeState(State.RUNNING); task.init(); + submitThreadsAndWait(); if (!isException()) { doChangeState(State.SUCCEEDED); } + LOGGER.info("start to destroy task {}", task.getTaskId()); task.destroy(); } catch (Exception ex) { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/AgentUtils.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/AgentUtils.java index c1001c28..8958f3e7 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/AgentUtils.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/AgentUtils.java @@ -47,24 +47,25 @@ public class AgentUtils { - private static final Logger LOGGER = LoggerFactory.getLogger(AgentUtils.class); - private static final AtomicLong INDEX = new AtomicLong(0); - private static final String HEX_PREFIX = "0x"; - public static final String EQUAL = "="; - public static final String M_VALUE = "m"; - public static final String ADDITION_SPLITTER = "&"; - public static final String BEIJING_TIME_ZONE = "GMT+8:00"; - public static final String HOUR_PATTERN = "yyyyMMddHH"; - public static final String DAY_PATTERN = "yyyyMMdd"; - public static final String DEFAULT_PATTERN = "yyyyMMddHHmm"; - public static final String DAY = "D"; - public static final String HOUR = "H"; - public static final String HOUR_LOW_CASE = "h"; - public static final String MINUTE = "m"; + private static final Logger LOGGER = LoggerFactory.getLogger(AgentUtils.class); + private static final AtomicLong INDEX = new AtomicLong(0); + private static final String HEX_PREFIX = "0x"; + public static final String EQUAL = "="; + public static final String M_VALUE = "m"; + public static final String ADDITION_SPLITTER = "&"; + public static final String BEIJING_TIME_ZONE = "GMT+8:00"; + public static final String HOUR_PATTERN = "yyyyMMddHH"; + public static final String DAY_PATTERN = "yyyyMMdd"; + public static final String DEFAULT_PATTERN = "yyyyMMddHHmm"; + public static final String DAY = "D"; + public static final String HOUR = "H"; + public static final String HOUR_LOW_CASE = "h"; + public static final String MINUTE = "m"; /** * get md5 of file. + * * @param file - file name * @return */ @@ -137,6 +138,7 @@ public static List getDeclaredMethodsIncludingInherited(Class clazz) /** * get random int of [seed, seed * 2] + * * @param seed * @return */ @@ -166,13 +168,14 @@ public static String getUniqId(String prefix, String id) { /** * Get uniq id with timestamp and index. - * @param id - job id + * + * @param id - job id * @param index - job index * @return uniq id */ public static String getUniqId(String prefix, String id, long index) { long currentTime = System.currentTimeMillis() / 1000; - return prefix + currentTime + "_" + id + "_" + index; + return prefix + currentTime + "_" + id + "_" + index; } public static void silenceSleepInMs(long millisecond) { @@ -196,6 +199,7 @@ public static String parseHexStr(String delimiter) throws IllegalArgumentExcepti /** * formatter for current time + * * @param formatter * @return */ @@ -211,10 +215,11 @@ public static String formatCurrentTime(String formatter, Locale locale) { /** * formatter with time offset + * * @param formatter - formatter string - * @param day - day offset - * @param hour - hour offset - * @param min - min offset + * @param day - day offset + * @param hour - hour offset + * @param min - min offset * @return current time with offset */ public static String formatCurrentTimeWithOffset(String formatter, int day, int hour, int min) { @@ -231,7 +236,7 @@ public static String formatCurrentTimeWithoutOffset(String formatter) { /** * whether all class of path name are matched * - * @param pathStr - path string + * @param pathStr - path string * @param patternStr - regex pattern * @return true if all match */ @@ -252,13 +257,14 @@ public static boolean regexMatch(String pathStr, String patternStr) { /** * parse addition attr, the attributes must be send in proxy sender + * * @param additionStr * @return */ public static Pair> parseAddAttr(String additionStr) { - Map attr = new HashMap<>(); - String[] split = additionStr.split(ADDITION_SPLITTER); - String mValue = ""; + Map attr = new HashMap<>(); + String[] split = additionStr.split(ADDITION_SPLITTER); + String mValue = ""; for (String s : split) { if (!s.contains(EQUAL)) { continue; @@ -275,6 +281,7 @@ public static Pair> parseAddAttr(String additionStr) /** * the attrs in pairs can be complicated in online env + * * @param attr * @param s * @param pairs @@ -290,6 +297,7 @@ private static void getAttrs(Map attr, String s, String[] pairs) /** * get addition attributes in additionStr + * * @param additionStr * @return */ @@ -301,6 +309,7 @@ public static Map getAdditionAttr(String additionStr) { /** * get m value in additionStr + * * @param addictiveAttr * @return */ @@ -311,6 +320,7 @@ public static String getmValue(String addictiveAttr) { /** * time str convert to mill sec + * * @param time * @param cycleUnit * @return @@ -352,7 +362,4 @@ private static long parseTimeToMillSec(String time, String pattern) { } - - - } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/PluginUtils.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/PluginUtils.java index 9fb8cfe7..63098bed 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/PluginUtils.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/PluginUtils.java @@ -93,9 +93,12 @@ public static void updateRetryTime(JobProfile jobConf, PathPattern pattern) { public static JobProfile copyJobProfile(TriggerProfile triggerProfile, String dataTime, File pendingFile) { JobProfile copiedProfile = TriggerProfile.parseJsonStr(triggerProfile.toJsonStr()); - String md5 = AgentUtils.getFileMd5(pendingFile); + + String md5 = AgentUtils.getFileMd5(pendingFile); + copiedProfile.set(pendingFile.getAbsolutePath() + ".md5", md5); copiedProfile.set(JobConstants.JOB_DIR_FILTER_PATTERN, pendingFile.getAbsolutePath()); + // the time suit for file name is just the data time copiedProfile.set(JobConstants.JOB_DATA_TIME, dataTime); return copiedProfile; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java index 03154d8f..8b7e0431 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java @@ -1,6 +1,7 @@ package com.zmops.zeus.iot.server.transfer.provider; import com.zmops.zeus.iot.server.library.module.*; +import com.zmops.zeus.iot.server.transfer.core.manager.AgentManager; import com.zmops.zeus.iot.server.transfer.module.ServerTransferModule; /** @@ -31,6 +32,10 @@ public ModuleConfig createConfigBeanIfAbsent() { @Override public void prepare() throws ServiceNotProvidedException, ModuleStartException { + + AgentManager manager = new AgentManager(); + + System.out.println(123); } From d9ec1ceed8c857bc3ec398d129e52924b4228f64 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 22 Sep 2021 22:31:44 +0800 Subject: [PATCH 260/763] [fix]: product event trigger update --- .../product/ProductEventExpression.java | 2 ++ .../DeviceEventTriggerController.java | 13 ++++--- .../iot/web/device/dto/DeviceEventRule.java | 6 ++-- .../service/DeviceEventRuleService.java | 9 +++++ .../ProductEventTriggerController.java | 5 +-- .../iot/web/product/dto/ProductEventDto.java | 2 +- .../iot/web/product/dto/ProductEventRule.java | 6 ++-- .../iot/web/product/dto/param/EventParm.java | 3 ++ .../service/ProductEventRuleService.java | 36 +++++++++++++------ 9 files changed, 57 insertions(+), 25 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java index 869cff8d..f98ccc75 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java @@ -34,4 +34,6 @@ public class ProductEventExpression extends Model { private String unit; private Long productAttrId; private String productAttrType; + private String period; + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index 14c4c593..8b309315 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -113,7 +113,7 @@ public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEn */ @PostMapping("/status") public ResponseData updateProductEventStatus(@RequestBody @Validated(value = BaseEntity.Status.class) DeviceEventRule eventRule) { - DB.update(ProductEvent.class).where().eq("eventRuleId", eventRule.getEventRuleId()).eq("relationId", eventRule.getDeviceId()).asUpdate() + DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).eq("relationId", eventRule.getDeviceId()).asUpdate() .set("status", eventRule.getStatus()).update(); ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()) @@ -135,14 +135,13 @@ public ResponseData updateProductEventStatus(@RequestBody @Validated(value = Bas @Transactional @PostMapping("/update") public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) DeviceEventRule eventRule) { - //来自产品的告警规则 只能修改备注 - ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()) - .relationId.eq(eventRule.getDeviceId()).findOne(); - if (null == productEventRelation) { + int count = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()) + .findCount(); + if (count == 0) { throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); } - - if (InheritStatus.YES.getCode().equals(productEventRelation.getInherit())) { + //来自产品的告警规则 只能修改备注 + if (count > 1) { DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).eq("relationId", eventRule.getDeviceId()) .asUpdate().set("remark", eventRule.getRemark()).update(); return ResponseData.success(eventRule.getEventRuleId()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java index 66ebfd11..54c6e011 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java @@ -54,10 +54,10 @@ public class DeviceEventRule { @NotNull(groups = BaseEntity.Update.class) private Integer zbxId; - @NotBlank(groups = BaseEntity.Status.class) + @NotBlank(groups = {BaseEntity.Status.class, BaseEntity.Delete.class}) private String deviceId; - @NotBlank(groups = {BaseEntity.Status.class, BaseEntity.Delete.class}) + @NotBlank(groups = BaseEntity.Status.class) private String status; @Data @@ -100,6 +100,8 @@ public static class Expression { private String productAttrType; + private String period; + @Override public String toString() { StringBuilder expression = new StringBuilder(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index a85a9ee8..aa94a867 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -10,6 +10,7 @@ import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventService; import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.enums.InheritStatus; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceEventRule; @@ -81,6 +82,7 @@ public void createDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { ProductEventRelation productEventRelation = new ProductEventRelation(); productEventRelation.setEventRuleId(eventRuleId); productEventRelation.setRelationId(relationId); + productEventRelation.setInherit(InheritStatus.NO.getCode()); productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); productEventRelation.setRemark(eventRule.getRemark()); productEventRelationList.add(productEventRelation); @@ -141,6 +143,8 @@ public void updateDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { ProductEventRelation productEventRelation = new ProductEventRelation(); productEventRelation.setEventRuleId(eventRuleId); productEventRelation.setRelationId(relationId); + productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); + productEventRelation.setRemark(eventRule.getRemark()); productEventRelationList.add(productEventRelation); }); DB.saveAll(productEventRelationList); @@ -165,6 +169,9 @@ private ProductEventExpression initEventExpression(DeviceEventRule.Expression ex eventExpression.setValue(exp.getValue()); eventExpression.setDeviceId(exp.getDeviceId()); eventExpression.setProductAttrKey(exp.getProductAttrKey()); + eventExpression.setProductAttrId(exp.getProductAttrId()); + eventExpression.setProductAttrType(exp.getProductAttrType()); + eventExpression.setPeriod(exp.getPeriod()); eventExpression.setUnit(exp.getUnit()); return eventExpression; } @@ -201,6 +208,8 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S productEventRuleDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).deviceId.eq(deviceId).findList()); ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(deviceId).eventRuleId.eq(eventRuleId).findOne(); + productEventRuleDto.setStatus(productEventRelation.getStatus()); + productEventRuleDto.setRemark(productEventRelation.getRemark()); if (null != productEventRelation) { JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index 74e5a3f1..2f2f9cc9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -49,6 +49,7 @@ public class ProductEventTriggerController { private static final String ALARM_TAG_NAME = "__alarm__"; private static final String EXECUTE_TAG_NAME = "__execute__"; + private static final String EVENT_TAG_NAME = "__event__"; /** @@ -58,7 +59,7 @@ public class ProductEventTriggerController { * @return */ @PostMapping("/getEventByPage") - public Pager getEventByPage(@RequestBody EventParm eventParm) { + public Pager getEventByPage(@Validated @RequestBody EventParm eventParm) { return productEventRuleService.getEventByPage(eventParm); } @@ -179,7 +180,7 @@ public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseE */ @PostMapping("/status") public ResponseData updateProductEventStatus(@RequestBody @Validated(value = BaseEntity.Status.class) ProductEventRule eventRule) { - DB.update(ProductEvent.class).where().eq("eventRuleId", eventRule.getEventRuleId()).asUpdate().set("status", eventRule.getStatus()).update(); + DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).asUpdate().set("status", eventRule.getStatus()).update(); ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).inherit.eq("0").findOne(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java index fe2bcf44..d0dc4c46 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java @@ -13,7 +13,7 @@ @JsonSerialize(using = CachedValueFilter.class) public class ProductEventDto { - private String eventRuleId; + private Long eventRuleId; private Byte eventNotify; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java index 330bf72c..246a6d4d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java @@ -92,7 +92,7 @@ public static class Expression { @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private String productAttrKey; // 产品属性 Key - private String deviceId; // 产品 ID + private String productId; // 产品 ID private String unit; @@ -100,12 +100,14 @@ public static class Expression { private String productAttrType; + private String period; + @Override public String toString() { StringBuilder expression = new StringBuilder(); expression.append(function); expression.append("(/"); - expression.append(deviceId); + expression.append(productId); expression.append("/"); expression.append(productAttrKey); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/EventParm.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/EventParm.java index 311135da..470502ad 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/EventParm.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/EventParm.java @@ -3,6 +3,8 @@ import com.zmops.iot.web.sys.dto.param.BaseQueryParam; import lombok.Data; +import javax.validation.constraints.NotBlank; + /** * @author yefei **/ @@ -11,5 +13,6 @@ public class EventParm extends BaseQueryParam { private String eventRuleName; + @NotBlank private String prodId; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index f82d4f8e..a24874c8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -11,6 +11,7 @@ import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventService; import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.enums.InheritStatus; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.product.dto.ProductEventDto; @@ -82,6 +83,7 @@ public void createProductEventRule(Long eventRuleId, ProductEventRule eventRule) productEventRelation.setEventRuleId(eventRuleId); productEventRelation.setRelationId(eventRule.getProductId()); productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); + productEventRelation.setInherit(InheritStatus.NO.getCode()); productEventRelation.setRemark(eventRule.getRemark()); DB.save(productEventRelation); } @@ -159,8 +161,11 @@ private ProductEventExpression initEventExpression(ProductEventRule.Expression e eventExpression.setFunction(exp.getFunction()); eventExpression.setScope(exp.getScope()); eventExpression.setValue(exp.getValue()); - eventExpression.setDeviceId(exp.getDeviceId()); + eventExpression.setDeviceId(exp.getProductId()); eventExpression.setProductAttrKey(exp.getProductAttrKey()); + eventExpression.setProductAttrId(exp.getProductAttrId()); + eventExpression.setProductAttrType(exp.getProductAttrType()); + eventExpression.setPeriod(exp.getPeriod()); eventExpression.setUnit(exp.getUnit()); return eventExpression; } @@ -218,21 +223,29 @@ public Pager getEventByPage(EventParm eventParm) { query.eventRuleName.contains(eventParm.getEventRuleName()); } - if (ToolUtil.isNotEmpty(eventParm.getProdId())) { - List eventRuleIdList = new QProductEventRelation().select(QProductEventRelation.alias().eventRuleId) - .relationId.eq(eventParm.getProdId()).findSingleAttributeList(); - if (ToolUtil.isEmpty(eventRuleIdList)) { - return new Pager<>(); - } - if (ToolUtil.isNotEmpty(eventRuleIdList)) { - query.eventRuleId.in(eventRuleIdList); - } + List productEventRelationList = new QProductEventRelation().select(QProductEventRelation.alias().eventRuleId) + .relationId.eq(eventParm.getProdId()).findList(); + if (ToolUtil.isEmpty(productEventRelationList)) { + return new Pager<>(); } + List eventRuleIdList = productEventRelationList.parallelStream().map(ProductEventRelation::getEventRuleId).collect(Collectors.toList()); + if (ToolUtil.isNotEmpty(eventRuleIdList)) { + query.eventRuleId.in(eventRuleIdList); + } + Map productEventRelationMap = productEventRelationList.parallelStream().collect(Collectors.toMap(ProductEventRelation::getEventRuleId, o -> o)); + List list = query.setFirstRow((eventParm.getPage() - 1) * eventParm.getMaxRow()) .setMaxRows(eventParm.getMaxRow()).orderBy(" create_time desc").asDto(ProductEventDto.class).findList(); + list.forEach(productEventDto -> { + if (null != productEventRelationMap.get(productEventDto.getEventRuleId())) { + productEventDto.setStatus(productEventRelationMap.get(productEventDto.getEventRuleId()).getStatus()); + productEventDto.setRemark(productEventRelationMap.get(productEventDto.getEventRuleId()).getRemark()); + } + }); + return new Pager<>(list, query.findCount()); } @@ -252,7 +265,8 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S productEventRuleDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).deviceId.isNull().findList()); ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(prodId).eventRuleId.eq(eventRuleId).findOne(); - + productEventRuleDto.setStatus(productEventRelation.getStatus()); + productEventRuleDto.setRemark(productEventRelation.getRemark()); JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); List tagList = JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class); From 2c798d055224ac30e42cf5e9dd8efc7016212228 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 22 Sep 2021 22:32:21 +0800 Subject: [PATCH 261/763] [feat]: add device log --- .../domain/device/ServiceExecuteRecord.java | 6 +- .../zmops/zeus/driver/service/ZbxProblem.java | 6 ++ .../api-json/problem/problem.event.get.ftl | 26 ++++++ .../api-json/problem/problem.get.ftl | 2 +- .../iot/web/alarm/service/AlarmService.java | 86 ++++++++++++++++++- .../iot/web/analyse/service/HomeService.java | 4 +- .../controller/DeviceLogController.java | 28 ++++++ .../iot/web/device/dto/DeviceLogDto.java | 23 +++++ .../web/device/service/DeviceLogService.java | 85 ++++++++++++++++++ 9 files changed, 260 insertions(+), 6 deletions(-) create mode 100644 zeus-driver/src/main/resources/api-json/problem/problem.event.get.ftl create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/ServiceExecuteRecord.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/ServiceExecuteRecord.java index 4c204b99..4bcf4936 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/ServiceExecuteRecord.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/ServiceExecuteRecord.java @@ -22,5 +22,9 @@ public class ServiceExecuteRecord { private LocalDateTime createTime; - private Long serviceId; + private String serviceName; + + private String deviceId; + + private String param; } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java index 71ba63d8..0cc780a7 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java @@ -27,4 +27,10 @@ String getProblem(@ParamName("hostId") String hostId, @ParamName("timeTill") Long timeTill, @ParamName("recent") String recent); + @Post + @JsonPath("/problem/problem.event.get") + String getEventProblem(@ParamName("hostId") String hostId, + @ParamName("timeFrom") Long timeFrom, + @ParamName("timeTill") Long timeTill, + @ParamName("recent") String recent); } diff --git a/zeus-driver/src/main/resources/api-json/problem/problem.event.get.ftl b/zeus-driver/src/main/resources/api-json/problem/problem.event.get.ftl new file mode 100644 index 00000000..9b0b0692 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/problem/problem.event.get.ftl @@ -0,0 +1,26 @@ +{ + "jsonrpc": "2.0", + "method": "problem.get", + "params": { + "output": "extend", + "selectTags": "extend", + "recent": ${recent}, + "sortfield": ["eventid"], + <#if hostId??> + "hostids":"${hostId}", + + <#if timeFrom??> + "time_from":${timeFrom}, + + <#if timeTill??> + "time_till":${timeTill}, + + "tags":[{"tag": "__event__"}], + "filter":{ + "source":"0" + }, + "sortorder": "DESC" + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl index 2bb6f4a5..e0421621 100644 --- a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl +++ b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl @@ -9,7 +9,7 @@ "recent": ${recent}, "sortfield": ["eventid"], <#if hostId??> - "hostids":"${hostId}" + "hostids":"${hostId}", <#if timeFrom??> "time_from":${timeFrom}, diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 209c718a..e4dddbcd 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -11,12 +11,14 @@ import com.zmops.iot.web.alarm.dto.AlarmDto; import com.zmops.iot.web.alarm.dto.param.AlarmParam; import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.product.dto.ProductEventRuleDto; import com.zmops.zeus.driver.entity.ZbxProblemInfo; import com.zmops.zeus.driver.service.ZbxProblem; import io.ebean.DB; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.util.Assert; import java.util.*; import java.util.stream.Collectors; @@ -62,7 +64,7 @@ public void alarm(Map alarmInfo) { public List getAlarmByPage(AlarmParam alarmParam) { - List zbxProblemInfos = getAlarmList(alarmParam); + List zbxProblemInfos = getZbxAlarm(alarmParam); if (ToolUtil.isEmpty(zbxProblemInfos)) { return Collections.emptyList(); } @@ -77,6 +79,11 @@ public List getAlarmByPage(AlarmParam alarmParam) { .setParameter("zbxIds", triggerIds).findList(); Map deviceMap = deviceList.parallelStream().collect(Collectors.toMap(DeviceDto::getZbxId, DeviceDto::getName)); + List ruleList = DB.findDto(ProductEventRuleDto.class, "select event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") + .setParameter("zbxIds", triggerIds).findList(); + Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); + + List alarmDtoList = new ArrayList<>(); problemList.forEach(zbxProblemInfo -> { AlarmDto alarmDto = new AlarmDto(); @@ -85,13 +92,44 @@ public List getAlarmByPage(AlarmParam alarmParam) { if (null != deviceMap.get(zbxProblemInfo.getObjectid())) { alarmDto.setDeviceName(deviceMap.get(zbxProblemInfo.getObjectid())); } + if (null != ruleMap.get(Integer.parseInt(zbxProblemInfo.getObjectid()))) { + alarmDto.setName(ruleMap.get(Integer.parseInt(zbxProblemInfo.getObjectid()))); + } alarmDtoList.add(alarmDto); }); return alarmDtoList; } - public List getAlarmList(AlarmParam alarmParam) { + public List getAlarmList(AlarmParam alarmParam) { + String hostId = null; + Assert.state(ToolUtil.isNotEmpty(alarmParam.getDeviceId()), "设备ID不能为空"); + List problemList = getZbxAlarm(alarmParam); + if (ToolUtil.isEmpty(problemList)) { + return Collections.emptyList(); + } + List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Integer::parseInt).collect(Collectors.toList()); + List ruleList = DB.findDto(ProductEventRuleDto.class, "select d.event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id," + + "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") + .setParameter("zbxIds", triggerIds).findList(); + Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); + + List alarmDtoList = new ArrayList<>(); + problemList.forEach(zbxProblemInfo -> { + AlarmDto alarmDto = new AlarmDto(); + BeanUtils.copyProperties(zbxProblemInfo, alarmDto); + alarmDto.setRClock(zbxProblemInfo.getR_clock()); + if (null != ruleMap.get(Integer.parseInt(zbxProblemInfo.getObjectid()))) { + alarmDto.setName(ruleMap.get(Integer.parseInt(zbxProblemInfo.getObjectid()))); + } + alarmDtoList.add(alarmDto); + }); + + + return alarmDtoList; + } + + public List getZbxAlarm(AlarmParam alarmParam) { String hostId = null; if (null != alarmParam.getDeviceId()) { Device one = new QDevice().deviceId.eq(alarmParam.getDeviceId()).findOne(); @@ -105,4 +143,48 @@ public List getAlarmList(AlarmParam alarmParam) { return JSONObject.parseArray(problem, ZbxProblemInfo.class); } + + public List getEventList(AlarmParam alarmParam) { + String hostId = null; + Assert.state(ToolUtil.isNotEmpty(alarmParam.getDeviceId()), "设备ID不能为空"); + List problemList = getZbxAlarm(alarmParam); + if (ToolUtil.isEmpty(problemList)) { + return Collections.emptyList(); + } + List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Integer::parseInt).collect(Collectors.toList()); + List ruleList = DB.findDto(ProductEventRuleDto.class, "select event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id," + + "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") + .setParameter("zbxIds", triggerIds).findList(); + Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); + + List alarmDtoList = new ArrayList<>(); + problemList.forEach(zbxProblemInfo -> { + AlarmDto alarmDto = new AlarmDto(); + BeanUtils.copyProperties(zbxProblemInfo, alarmDto); + alarmDto.setRClock(zbxProblemInfo.getR_clock()); + if (null != ruleMap.get(Integer.parseInt(zbxProblemInfo.getObjectid()))) { + alarmDto.setName(ruleMap.get(Integer.parseInt(zbxProblemInfo.getObjectid()))); + } + alarmDtoList.add(alarmDto); + }); + + + return alarmDtoList; + } + + public List getEventProblem(AlarmParam alarmParam) { + String hostId = null; + if (null != alarmParam.getDeviceId()) { + Device one = new QDevice().deviceId.eq(alarmParam.getDeviceId()).findOne(); + if (null == one) { + return Collections.EMPTY_LIST; + } + hostId = one.getZbxId(); + } + //从zbx取告警记录 + String problem = zbxProblem.getEventProblem(hostId, alarmParam.getTimeFrom(), alarmParam.getTimeTill(), alarmParam.getRecent()); + return JSONObject.parseArray(problem, ZbxProblemInfo.class); + } + + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index f81e5be0..82bff248 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -183,7 +183,7 @@ public Map getDeviceNum(Integer timeFrom, Integer timeTill) { public Map getAlarmNum(long timeFrom, long timeTill) { AlarmParam alarmParam = new AlarmParam(); alarmParam.setRecent("false"); - List alarmList = alarmService.getAlarmList(alarmParam); + List alarmList = alarmService.getZbxAlarm(alarmParam); Map alarmMap = new ConcurrentHashMap<>(3); if (ToolUtil.isNotEmpty(alarmList)) { @@ -223,7 +223,7 @@ public Map getAlarmNum(long timeFrom, long timeTill) { Long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); AlarmParam todayParam = new AlarmParam(); todayParam.setTimeFrom(timeStart); - List todayAlarmList = alarmService.getAlarmList(todayParam); + List todayAlarmList = alarmService.getZbxAlarm(todayParam); Long todayAlarmNum = todayAlarmList.parallelStream().filter(o -> !o.getSeverity().equals("0")).count(); alarmMap.put("today", todayAlarmNum); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java new file mode 100644 index 00000000..1180ea41 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java @@ -0,0 +1,28 @@ +package com.zmops.iot.web.device.controller; + +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.device.service.DeviceLogService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + **/ +@RestController +@RequestMapping("/device/log") +public class DeviceLogController { + + @Autowired + DeviceLogService deviceLogService; + + @RequestMapping("list") + public ResponseData getLogByPage(@RequestParam(value = "deviceId") String deviceId, + @RequestParam(value = "logType", required = false) String logType, + @RequestParam(value = "timeFrom", required = false) Long timeFrom, + @RequestParam(value = "timeTill", required = false) Long timeTill) { + + return ResponseData.success(deviceLogService.getLogByPage(deviceId, logType, timeFrom, timeTill)); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java new file mode 100644 index 00000000..98dd6894 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java @@ -0,0 +1,23 @@ +package com.zmops.iot.web.device.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * @author yefei + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DeviceLogDto { + private String logType; + private LocalDateTime triggerTime; + private String content; + private String param; + private String status; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java new file mode 100644 index 00000000..6a1de007 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java @@ -0,0 +1,85 @@ +package com.zmops.iot.web.device.service; + +import com.zmops.iot.domain.device.ServiceExecuteRecord; +import com.zmops.iot.domain.device.query.QServiceExecuteRecord; +import com.zmops.iot.util.LocalDateTimeUtils; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.alarm.dto.AlarmDto; +import com.zmops.iot.web.alarm.dto.param.AlarmParam; +import com.zmops.iot.web.alarm.service.AlarmService; +import com.zmops.iot.web.device.dto.DeviceLogDto; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author yefei + **/ +@Service +public class DeviceLogService { + + private static final String LOG_TYPE_ALARM = "告警日志"; + private static final String LOG_TYPE_EVENT = "事件日志"; + private static final String LOG_TYPE_SERVICE = "服务日志"; + + @Autowired + AlarmService alarmService; + + public List getLogByPage(String deviceId, String logType, Long timeFrom, Long timeTill) { + List deviceLogDtoList = new ArrayList<>(); + if (ToolUtil.isEmpty(logType) || (ToolUtil.isNotEmpty(logType) && LOG_TYPE_ALARM.equals(logType))) { + AlarmParam alarmParam = new AlarmParam(); + alarmParam.setDeviceId(deviceId); + alarmParam.setTimeFrom(timeFrom); + alarmParam.setTimeTill(timeTill); + List alarmList = alarmService.getAlarmList(alarmParam); + if (ToolUtil.isNotEmpty(alarmList)) { + alarmList.forEach(alarm -> { + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_ALARM).content(alarm.getName()) + .triggerTime(LocalDateTimeUtils.convertDateToLocalDateTime(Integer.parseInt(alarm.getClock()))) + .status("0".equals(alarm.getRClock()) ? "已解决" : "未解决").build()); + }); + } + } + + if (ToolUtil.isEmpty(logType) || (ToolUtil.isNotEmpty(logType) && LOG_TYPE_EVENT.equals(logType))) { + AlarmParam alarmParam = new AlarmParam(); + alarmParam.setDeviceId(deviceId); + alarmParam.setTimeFrom(timeFrom); + alarmParam.setTimeTill(timeTill); + List alarmList = alarmService.getEventList(alarmParam); + if (ToolUtil.isNotEmpty(alarmList)) { + alarmList.forEach(alarm -> { + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_ALARM).content(alarm.getName()) + .triggerTime(LocalDateTimeUtils.convertDateToLocalDateTime(Integer.parseInt(alarm.getClock()))) + .status("0".equals(alarm.getRClock()) ? "已解决" : "未解决").build()); + }); + } + } + + if (ToolUtil.isEmpty(logType) || (ToolUtil.isNotEmpty(logType) && LOG_TYPE_SERVICE.equals(logType))) { + QServiceExecuteRecord query = new QServiceExecuteRecord().deviceId.eq(deviceId); + if (null != timeFrom) { + query.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(timeFrom)); + } + if (null != timeTill) { + query.createTime.lt(LocalDateTimeUtils.getLDTByMilliSeconds(timeTill)); + } + List list = query.findList(); + if (ToolUtil.isNotEmpty(list)) { + list.forEach(service -> { + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_SERVICE).content(service.getServiceName()) + .triggerTime(service.getCreateTime()) + .param(service.getParam()).build()); + }); + } + } + deviceLogDtoList.parallelStream() + .sorted((o1, o2) -> (int) LocalDateTimeUtils.betweenTwoTime(o1.getTriggerTime(), o2.getTriggerTime(), ChronoUnit.SECONDS)).collect(Collectors.toList()); + return deviceLogDtoList; + } +} From 54140c5c6a0005c41783874074d5ce0ec77d8572 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 23 Sep 2021 09:09:01 +0800 Subject: [PATCH 262/763] [fix]: update device online default value --- .../src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java index 52d2ffdb..84d79105 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java @@ -66,6 +66,6 @@ public class DeviceDto { private String position; - private Integer online; + private Integer online = 1; } From 45ea39886bc76a047f88a8c44aba56c3fc0ef5db Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 23 Sep 2021 09:24:37 +0800 Subject: [PATCH 263/763] [feat]: add event tag --- .../controller/DeviceEventTriggerController.java | 11 +++++++++++ .../controller/ProductEventTriggerController.java | 12 +++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index 8b309315..0c859b31 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -25,6 +25,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; /** @@ -44,6 +45,8 @@ public class DeviceEventTriggerController { private static final String ALARM_TAG_NAME = "__alarm__"; private static final String EXECUTE_TAG_NAME = "__execute__"; + private static final String EVENT_TAG_NAME = "__event__"; + private static final String EVENT_TYPE_NAME = "事件"; /** * 触发器 详情 @@ -94,6 +97,10 @@ public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEn if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); } + Optional any = eventRule.getExpList().parallelStream().filter(o -> EVENT_TYPE_NAME.equals(o.getProductAttrType())).findAny(); + if (any.isPresent()) { + tags.put(EVENT_TAG_NAME, eventRuleId + ""); + } for (Integer triggerId : triggerIds) { zbxTrigger.triggerTagCreate(triggerId, tags); } @@ -169,6 +176,10 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); } + Optional any = eventRule.getExpList().parallelStream().filter(o -> EVENT_TYPE_NAME.equals(o.getProductAttrType())).findAny(); + if (any.isPresent()) { + tags.put(EVENT_TAG_NAME, eventRule.getEventRuleId() + ""); + } for (Integer triggerId : triggerIds) { zbxTrigger.triggerTagCreate(triggerId, tags); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index 2f2f9cc9..8dbf355a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -28,6 +28,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; /** @@ -50,6 +51,7 @@ public class ProductEventTriggerController { private static final String ALARM_TAG_NAME = "__alarm__"; private static final String EXECUTE_TAG_NAME = "__execute__"; private static final String EVENT_TAG_NAME = "__event__"; + private static final String EVENT_TYPE_NAME = "事件"; /** @@ -104,7 +106,7 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE Map tags = eventRule.getTags().stream() .collect(Collectors.toMap(ProductEventRule.Tag::getTag, ProductEventRule.Tag::getValue, (k1, k2) -> k2)); if (ToolUtil.isEmpty(tags)) { - tags = new HashMap<>(2); + tags = new HashMap<>(3); } if (!tags.containsKey(ALARM_TAG_NAME)) { tags.put(ALARM_TAG_NAME, eventRuleId + ""); @@ -112,6 +114,10 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); } + Optional any = eventRule.getExpList().parallelStream().filter(o -> EVENT_TYPE_NAME.equals(o.getProductAttrType())).findAny(); + if(any.isPresent()){ + tags.put(EVENT_TAG_NAME, eventRuleId + ""); + } for (Integer triggerId : triggerIds) { zbxTrigger.triggerTagCreate(triggerId, tags); } @@ -166,6 +172,10 @@ public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseE if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); } + Optional any = eventRule.getExpList().parallelStream().filter(o -> EVENT_TYPE_NAME.equals(o.getProductAttrType())).findAny(); + if(any.isPresent()){ + tags.put(EVENT_TAG_NAME, eventRule.getEventRuleId() + ""); + } zbxTrigger.triggerTagCreate(list.get(0).getZbxId(), tags); From be4207500a9bc46dbdd76721967821ee2c259f73 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 23 Sep 2021 11:32:28 +0800 Subject: [PATCH 264/763] [fix]: server-transfer default - --- iot-server/server-bootstrap/src/main/resources/application.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iot-server/server-bootstrap/src/main/resources/application.yml b/iot-server/server-bootstrap/src/main/resources/application.yml index b442d597..3468f1d3 100644 --- a/iot-server/server-bootstrap/src/main/resources/application.yml +++ b/iot-server/server-bootstrap/src/main/resources/application.yml @@ -44,7 +44,7 @@ core: # ndjson file read realtime server-transfer: - selector: ${ZS_SERVER_TRANSFER:default} + selector: ${ZS_SERVER_TRANSFER:-} default: # tdengine storage realtime From 8ee652a3fedf60e15e995486392ceb04c78191ae Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 23 Sep 2021 13:50:49 +0800 Subject: [PATCH 265/763] [feat]: wark current monitor --- .../iot/web/analyse/controller/LatestController.java | 7 +++++++ .../java/com/zmops/iot/web/analyse/dto/LatestDto.java | 2 ++ .../com/zmops/iot/web/analyse/service/LatestService.java | 9 +++++++++ 3 files changed, 18 insertions(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java index ac89cd01..5f5a9436 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java @@ -1,6 +1,7 @@ package com.zmops.iot.web.analyse.controller; import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.web.analyse.dto.LatestDto; import com.zmops.iot.web.analyse.dto.param.LatestParam; import com.zmops.iot.web.analyse.service.LatestService; @@ -8,6 +9,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** @@ -26,4 +28,9 @@ public class LatestController { public Pager qeuryLatest(@Validated @RequestBody LatestParam latestParam) { return latestService.qeuryLatest(latestParam); } + + @RequestMapping("/queryMap") + public ResponseData queryMap(@RequestParam("deviceId") String deviceId) { + return ResponseData.success(latestService.queryMap(deviceId)); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java index b351273d..611a4db5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java @@ -18,6 +18,8 @@ public class LatestDto { private Long attrId; + private String key; + private String clock; private String value; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java index ab109e64..82b8e183 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java @@ -80,9 +80,18 @@ public List qeuryLatest(String deviceId, List attrIds) { latestDto.setName(itemIdMap.get(latestDto.getItemid()).getName()); latestDto.setAttrId(itemIdMap.get(latestDto.getItemid()).getAttrId()); latestDto.setUnits(itemIdMap.get(latestDto.getItemid()).getUnits()); + latestDto.setKey(itemIdMap.get(latestDto.getItemid()).getKey()); } }); return latestDtos; } + + public Map queryMap(String deviceId) { + List latestDtos = qeuryLatest(deviceId, Collections.emptyList()); + if (ToolUtil.isEmpty(latestDtos)) { + return new HashMap<>(0); + } + return latestDtos.parallelStream().collect(Collectors.toMap(LatestDto::getKey, LatestDto::getValue)); + } } From df22ff44305e59fb17a03bd53ffd384d6b83e99f Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 23 Sep 2021 13:51:19 +0800 Subject: [PATCH 266/763] [fix]: mqtt reciver update --- .../process/ByteArrayToItemValueProcess.java | 23 +++++++++++-------- .../mqtt/provider/MqttRouteBuilder.java | 2 +- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java index e5a6e6a8..8dc5435e 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java @@ -1,15 +1,16 @@ package com.zmops.zeus.iot.server.core.camel.process; import com.google.gson.Gson; -import com.zmops.zeus.iot.server.core.camel.IOTDeviceValue; import com.zmops.zeus.iot.server.core.worker.data.ItemValue; import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.camel.Processor; +import org.apache.commons.lang3.StringUtils; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import java.util.Map; /** * @author nantian created at 2021/8/23 17:16 @@ -27,17 +28,21 @@ public void process(Exchange exchange) throws Exception { String inputContext = new String(messageBytes, StandardCharsets.UTF_8); - IOTDeviceValue iotValue = gson.fromJson(inputContext, IOTDeviceValue.class); - + Map jsonMap = gson.fromJson(inputContext, Map.class); + String key = jsonMap.get("key"); + String value = jsonMap.get("value"); + if (StringUtils.isBlank(key)) { + return; + } + String deviceId = key.substring(0, key.indexOf(".")); + String attributeKey = key.substring(key.indexOf(".") + 1); List itemValueList = new ArrayList<>(); - iotValue.getAttributes().forEach((key, value) -> { - ItemValue item = new ItemValue(iotValue.getDeviceId(), iotValue.getClock()); - item.setKey(key); - item.setValue(value); + ItemValue item = new ItemValue(deviceId, System.currentTimeMillis()/1000); + item.setKey(attributeKey); + item.setValue(value); - itemValueList.add(item); - }); + itemValueList.add(item); exchange.getMessage().setBody(itemValueList); } diff --git a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttRouteBuilder.java b/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttRouteBuilder.java index 3ed528af..c452f409 100644 --- a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttRouteBuilder.java +++ b/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttRouteBuilder.java @@ -17,7 +17,7 @@ public MqttRouteBuilder(MqttReceiverConfig mqttReceiverConfig) { @Override public void configure() throws Exception { - fromF("mqtt:zeus-iot-mqtt?host=tcp://172.16.3.72:%d&subscribeTopicNames=test.mqtt.topic", mqttReceiverConfig.getPort()) + fromF("mqtt:zeus-iot-mqtt?host=tcp://%s:%d&subscribeTopicNames=34EAE784BC4A/up", mqttReceiverConfig.getHost(),mqttReceiverConfig.getPort()) .process(new ByteArrayToItemValueProcess()) .to("Zabbix"); } From 6f640ef018da0f98fd7a12afece611ac06022e28 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 23 Sep 2021 14:49:59 +0800 Subject: [PATCH 267/763] [fix]: user list update --- .../src/main/java/com/zmops/iot/web/sys/dto/UserDto.java | 7 +++++-- .../main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java index 26303226..ccb3f61f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java @@ -19,6 +19,7 @@ import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; import lombok.Data; import javax.validation.constraints.NotBlank; @@ -60,8 +61,10 @@ public class UserDto { private String roleName; private String userGroupName; - private String createUser; + @CachedValue(type = DicType.SysUserName) + private Long createUser; private String createTime; - private String updateUser; + @CachedValue(type = DicType.SysUserName) + private Long updateUser; private String updateTime; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java index 0e3ea1be..a5ea88de 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java @@ -19,6 +19,7 @@ import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; import lombok.Data; import javax.validation.constraints.NotBlank; @@ -55,7 +56,9 @@ public class UserGroupDto { LocalDateTime updateTime; + @CachedValue(type = DicType.SysUserName) Long createUser; + @CachedValue(type = DicType.SysUserName) Long updateUser; } From f1ac747e89097267fb1801e08ecda85722576c19 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 23 Sep 2021 15:17:51 +0800 Subject: [PATCH 268/763] [fix]: product event trigger update --- .../zmops/zeus/driver/service/ZbxTrigger.java | 9 +++ .../api-json/trigger/trigger.delete.ftl | 2 +- .../api-json/trigger/trigger.get.ftl | 5 ++ .../ProductEventTriggerController.java | 23 ++++-- .../service/ProductEventRuleService.java | 13 ++-- .../work/SaveProductEventTriggerWorker.java | 71 +++++++++++++++++++ 6 files changed, 111 insertions(+), 12 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java index 98f03cda..7b4c1f88 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java @@ -86,6 +86,15 @@ String triggerTagCreate(@ParamName("triggerId") Integer triggerId, @JsonPath("/trigger/trigger.get") String triggerGetByHost(@ParamName("host") String host); + /** + * 根据触发器名称 查询触发器 + * + * @param description 触发器名称 + */ + @Post + @JsonPath("/trigger/trigger.get") + String triggerGetByName(@ParamName("description") String description); + /** * 修改触发器状态 diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.delete.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.delete.ftl index 083b1843..766425e2 100644 --- a/zeus-driver/src/main/resources/api-json/trigger/trigger.delete.ftl +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.delete.ftl @@ -1,6 +1,6 @@ { "jsonrpc": "2.0", - "method": "trigger.get", + "method": "trigger.delete", "params": [ ${triggerid} ], diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl index d4399adb..211674fe 100644 --- a/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl @@ -9,6 +9,11 @@ <#if host??> "host":"${host}", + <#if description??> + "filter":{ + "description":${description} + }, + "output": "extend" }, "id": 1, diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index 8dbf355a..0526c183 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -1,6 +1,8 @@ package com.zmops.iot.web.product.controller; import cn.hutool.core.util.IdUtil; +import com.zmops.iot.async.executor.Async; +import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.ProductEventRelation; @@ -18,6 +20,7 @@ import com.zmops.iot.web.product.dto.ProductEventRule; import com.zmops.iot.web.product.dto.param.EventParm; import com.zmops.iot.web.product.service.ProductEventRuleService; +import com.zmops.iot.web.product.service.work.SaveProductEventTriggerWorker; import com.zmops.zeus.driver.service.ZbxTrigger; import io.ebean.DB; import io.ebean.annotation.Transactional; @@ -53,6 +56,8 @@ public class ProductEventTriggerController { private static final String EVENT_TAG_NAME = "__event__"; private static final String EVENT_TYPE_NAME = "事件"; + @Autowired + SaveProductEventTriggerWorker saveProductEventTriggerWorker; /** * 触发器 分页列表 @@ -92,8 +97,8 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE ProductEventRule eventRule) { Long eventRuleId = IdUtil.getSnowflake().nextId(); // ruleId, trigger name - - productEventRuleService.createProductEventRule(eventRuleId, eventRule); + eventRule.setEventRuleId(eventRuleId); + productEventRuleService.createProductEventRule(eventRule); //step 1: 先创建 zbx 触发器 String expression = eventRule.getExpList() @@ -115,7 +120,7 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); } Optional any = eventRule.getExpList().parallelStream().filter(o -> EVENT_TYPE_NAME.equals(o.getProductAttrType())).findAny(); - if(any.isPresent()){ + if (any.isPresent()) { tags.put(EVENT_TAG_NAME, eventRuleId + ""); } for (Integer triggerId : triggerIds) { @@ -125,6 +130,16 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE //step 5: 更新 zbxId productEventRuleService.updateProductEventRuleZbxId(eventRuleId, triggerIds); + //step 6: 同步到产品下的设备 + WorkerWrapper saveProductEventTriggerWork = WorkerWrapper.builder().worker(saveProductEventTriggerWorker).param(eventRule).build(); + + try { + Async.work(100, saveProductEventTriggerWork).awaitFinish(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + // 返回触发器ID return ResponseData.success(eventRuleId); } @@ -173,7 +188,7 @@ public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseE tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); } Optional any = eventRule.getExpList().parallelStream().filter(o -> EVENT_TYPE_NAME.equals(o.getProductAttrType())).findAny(); - if(any.isPresent()){ + if (any.isPresent()) { tags.put(EVENT_TAG_NAME, eventRule.getEventRuleId() + ""); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index a24874c8..4a0fefcd 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -47,13 +47,12 @@ public class ProductEventRuleService { /** * 保存触发器 * - * @param eventRuleId 触发器ID * @param eventRule 告警规则 */ - public void createProductEventRule(Long eventRuleId, ProductEventRule eventRule) { + public void createProductEventRule(ProductEventRule eventRule) { // step 1: 保存产品告警规则 ProductEvent event = initEventRule(eventRule); - event.setEventRuleId(eventRuleId); + event.setEventRuleId(eventRule.getEventRuleId()); DB.save(event); //step 2: 保存 表达式,方便回显 @@ -61,7 +60,7 @@ public void createProductEventRule(Long eventRuleId, ProductEventRule eventRule) eventRule.getExpList().forEach(i -> { ProductEventExpression exp = initEventExpression(i); - exp.setEventRuleId(eventRuleId); + exp.setEventRuleId(eventRule.getEventRuleId()); expList.add(exp); }); @@ -71,7 +70,7 @@ public void createProductEventRule(Long eventRuleId, ProductEventRule eventRule) if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { eventRule.getDeviceServices().forEach(i -> { DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") - .setParameter("eventRuleId", eventRuleId) + .setParameter("eventRuleId", eventRule.getEventRuleId()) .setParameter("executeDeviceId", i.getExecuteDeviceId()) .setParameter("serviceId", i.getServiceId()) .execute(); @@ -80,7 +79,7 @@ public void createProductEventRule(Long eventRuleId, ProductEventRule eventRule) //step 4: 保存关联关系 ProductEventRelation productEventRelation = new ProductEventRelation(); - productEventRelation.setEventRuleId(eventRuleId); + productEventRelation.setEventRuleId(eventRule.getEventRuleId()); productEventRelation.setRelationId(eventRule.getProductId()); productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); productEventRelation.setInherit(InheritStatus.NO.getCode()); @@ -293,7 +292,7 @@ public static class Triggers { } @Data - static class Hosts { + public static class Hosts { private String hostid; private String host; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java new file mode 100644 index 00000000..6d700b60 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java @@ -0,0 +1,71 @@ +package com.zmops.iot.web.product.service.work; + + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.async.callback.IWorker; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.enums.InheritStatus; +import com.zmops.iot.web.product.dto.ProductEventRule; +import com.zmops.iot.web.product.service.ProductEventRuleService; +import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 产品服务创建 同步到设备 步骤 + */ +@Slf4j +@Component +public class SaveProductEventTriggerWorker implements IWorker { + + + @Autowired + ZbxTrigger zbxTrigger; + + @Override + public Boolean action(ProductEventRule productEventRule, Map> map) { + log.debug("处理产品 新增告警规则 同步到设备工作…………"); + + String prodId = productEventRule.getProductId(); + + List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); + List triggers = JSONObject.parseArray(zbxTrigger.triggerGetByName(productEventRule.getEventRuleId() + ""), ProductEventRuleService.Triggers.class); + + Map treiggerMap = triggers.parallelStream().collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ProductEventRuleService.Triggers::getTriggerid)); + List productEventRelationList = new ArrayList<>(); + for (String deviceId : deviceIds) { + ProductEventRelation productEventRelation = new ProductEventRelation(); + productEventRelation.setRelationId(deviceId); + productEventRelation.setEventRuleId(productEventRule.getEventRuleId()); + productEventRelation.setInherit(InheritStatus.YES.getCode()); + productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); + productEventRelation.setRemark(productEventRule.getRemark()); + if (null != treiggerMap.get(deviceId)) { + productEventRelation.setZbxId(treiggerMap.get(deviceId)); + } + productEventRelationList.add(productEventRelation); + } + DB.saveAll(productEventRelationList); + + return true; + } + + + @Override + public Boolean defaultValue() { + return true; + } + +} From fc35b999d44745ea99c7da8c0b79c775653b2669 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 23 Sep 2021 17:32:37 +0800 Subject: [PATCH 269/763] [fix]: Scene event trigger update --- .../main/java/com/zmops/iot/domain/product/ProductEvent.java | 2 +- .../java/com/zmops/iot/web/device/dto/DeviceEventRule.java | 4 +++- .../zmops/iot/web/device/service/DeviceEventRuleService.java | 1 + .../java/com/zmops/iot/web/product/dto/ProductEventRule.java | 2 ++ .../java/com/zmops/iot/web/product/dto/param/EventParm.java | 3 +++ .../iot/web/product/service/ProductEventRuleService.java | 2 +- 6 files changed, 11 insertions(+), 3 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java index b6a2ddd5..9e586e3b 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java @@ -24,7 +24,7 @@ public class ProductEvent extends BaseEntity { private String eventRuleName; private String eventLevel; private String expLogic; - + private String classify; private String eventNotify; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java index 54c6e011..db3c3bc9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java @@ -60,6 +60,8 @@ public class DeviceEventRule { @NotBlank(groups = BaseEntity.Status.class) private String status; + private String classify = "0"; + @Data public static class Tag { @@ -96,7 +98,7 @@ public static class Expression { private String unit; - private Long productAttrId; + private Long productAttrId; private String productAttrType; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index aa94a867..304535da 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -156,6 +156,7 @@ private ProductEvent initEventRule(DeviceEventRule eventRule) { event.setEventLevel(eventRule.getEventLevel().toString()); event.setExpLogic(eventRule.getExpLogic()); event.setEventNotify(eventRule.getEventNotify().toString()); + event.setClassify(eventRule.getClassify()); event.setEventRuleName(eventRule.getEventRuleName()); return event; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java index 246a6d4d..5a2eb9da 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java @@ -60,6 +60,8 @@ public class ProductEventRule { @NotBlank(groups = BaseEntity.Status.class) private String status; + private String classify = "0"; + @Data public static class Tag { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/EventParm.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/EventParm.java index 470502ad..835d7f0e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/EventParm.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/EventParm.java @@ -15,4 +15,7 @@ public class EventParm extends BaseQueryParam { @NotBlank private String prodId; + + @NotBlank + private String classify; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index 4a0fefcd..e66f039b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -147,7 +147,7 @@ private ProductEvent initEventRule(ProductEventRule eventRule) { event.setEventLevel(eventRule.getEventLevel().toString()); event.setExpLogic(eventRule.getExpLogic()); event.setEventNotify(eventRule.getEventNotify().toString()); - + event.setClassify(eventRule.getClassify()); event.setEventRuleName(eventRule.getEventRuleName()); return event; From 50816ecef0d2eb98e9e66b1bbe940cf5922090be Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 23 Sep 2021 17:46:09 +0800 Subject: [PATCH 270/763] [fix]: scene event trigger update --- .../device/controller/DeviceEventTriggerController.java | 9 +++++---- .../controller/ProductEventTriggerController.java | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index 0c859b31..51eda656 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -26,6 +26,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; /** @@ -86,10 +87,10 @@ public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEn Integer[] triggerIds = deviceEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); //step 4: zbx 触发器创建 Tag - Map tags = eventRule.getTags().stream() - .collect(Collectors.toMap(DeviceEventRule.Tag::getTag, DeviceEventRule.Tag::getValue, (k1, k2) -> k2)); - if (ToolUtil.isEmpty(tags)) { - tags = new HashMap<>(2); + Map tags = new ConcurrentHashMap<>(3); + if (ToolUtil.isNotEmpty(eventRule.getTags())) { + tags = eventRule.getTags().stream() + .collect(Collectors.toMap(DeviceEventRule.Tag::getTag, DeviceEventRule.Tag::getValue, (k1, k2) -> k2)); } if (!tags.containsKey(ALARM_TAG_NAME)) { tags.put(ALARM_TAG_NAME, eventRuleId + ""); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index 0526c183..3ae68a07 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; /** @@ -108,10 +109,10 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE Integer[] triggerIds = productEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); //step 4: zbx 触发器创建 Tag - Map tags = eventRule.getTags().stream() - .collect(Collectors.toMap(ProductEventRule.Tag::getTag, ProductEventRule.Tag::getValue, (k1, k2) -> k2)); - if (ToolUtil.isEmpty(tags)) { - tags = new HashMap<>(3); + Map tags = new ConcurrentHashMap<>(3); + if (ToolUtil.isNotEmpty(eventRule.getTags())) { + tags = eventRule.getTags().stream() + .collect(Collectors.toMap(ProductEventRule.Tag::getTag, ProductEventRule.Tag::getValue, (k1, k2) -> k2)); } if (!tags.containsKey(ALARM_TAG_NAME)) { tags.put(ALARM_TAG_NAME, eventRuleId + ""); From 2d47dc982ecdf6c700a3eddd8f88cf80033b75b7 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 23 Sep 2021 18:30:13 +0800 Subject: [PATCH 271/763] [fix]: domain update --- .../java/com/zmops/iot/web/product/dto/ProductEventDto.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java index d0dc4c46..a5965acc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java @@ -26,7 +26,7 @@ public class ProductEventDto { private String status; private String remark; - + private String classify; private String expLogic; @CachedValue(type = DicType.SysUserName) private String createUser; From 079f9b6257b3b3bae190db65441332eba042eb9d Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 01:40:52 +0800 Subject: [PATCH 272/763] [feat]: update module zeus-transfer --- .gitignore | 1 + .../transfer/conf/AbstractConfiguration.java | 8 +- .../server/transfer/conf/CommonConstants.java | 96 ++----- .../iot/server/transfer/conf/ConfigJetty.java | 115 --------- .../server/transfer/conf/ConfigServlet.java | 109 -------- .../server/transfer/conf/JobConstants.java | 22 +- .../iot/server/transfer/conf/JobProfile.java | 6 +- .../server/transfer/conf/ProfileFetcher.java | 40 --- .../server/transfer/conf/ResponseResult.java | 49 ---- ...ration.java => TransferConfiguration.java} | 24 +- ...tConstants.java => TransferConstants.java} | 6 +- .../server/transfer/conf/TriggerProfile.java | 2 +- .../transfer/core/channel/MemoryChannel.java | 6 +- .../transfer/core/db/BerkeleyDbImp.java | 32 +-- .../server/transfer/core/db/JobProfileDb.java | 5 +- .../transfer/core/db/KeyValueEntity.java | 3 +- .../server/transfer/core/db/LocalProfile.java | 72 ------ .../transfer/core/db/TriggerProfileDb.java | 7 +- .../server/transfer/core/job/CommandDb.java | 3 +- .../iot/server/transfer/core/job/Job.java | 16 +- .../server/transfer/core/job/JobManager.java | 27 +- .../server/transfer/core/job/JobWrapper.java | 20 +- .../transfer/core/manager/AgentManager.java | 205 --------------- .../core/manager/TransferManager.java | 131 ++++++++++ .../core/message/PackProxyMessage.java | 147 +++++++++++ .../transfer/core/message/ProxyMessage.java | 75 ++++++ .../transfer/core/sink/ConsoleSink.java | 53 ---- .../server/transfer/core/sink/NdjsonSink.java | 186 ++++++++++++++ .../transfer/core/sink/SenderManager.java | 74 ++++++ .../transfer/core/source/TextFileSource.java | 6 +- .../core/source/reader/TextFileReader.java | 28 ++- .../core/state/StateTransferException.java | 26 -- .../transfer/core/task/TaskManager.java | 31 ++- .../core/task/TaskPositionManager.java | 50 ++-- .../transfer/core/task/TaskWrapper.java | 16 +- .../core/trigger/DirectoryTrigger.java | 24 +- .../transfer/core/trigger/TriggerManager.java | 51 ++-- .../server/transfer/core/utils/ByteUtil.java | 235 ------------------ ...{PluginUtils.java => FileSearchUtils.java} | 58 +---- .../provider/ServerTransferProvider.java | 32 ++- .../src/main/resources/job.json | 25 ++ 41 files changed, 909 insertions(+), 1213 deletions(-) delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ConfigJetty.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ConfigServlet.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ProfileFetcher.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ResponseResult.java rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/{AgentConfiguration.java => TransferConfiguration.java} (82%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/{AgentConstants.java => TransferConstants.java} (97%) delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/LocalProfile.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/AgentManager.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/TransferManager.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/PackProxyMessage.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/ConsoleSink.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java create mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateTransferException.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/ByteUtil.java rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/{PluginUtils.java => FileSearchUtils.java} (65%) create mode 100644 iot-server/server-transfer/src/main/resources/job.json diff --git a/.gitignore b/.gitignore index ceaab4ca..028472b4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ **/node_modules/* dist/ zeus-starter/src/main/resources/public/ +.bdb/ diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java index 00024d15..65e62030 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java @@ -33,7 +33,8 @@ public abstract class AbstractConfiguration { - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractConfiguration.class); + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractConfiguration.class); + private static final JsonParser JSON_PARSER = new JsonParser(); private final Map configStorage = new HashMap<>(); @@ -46,7 +47,7 @@ public abstract class AbstractConfiguration { public AbstractConfiguration() { classLoader = Thread.currentThread().getContextClassLoader(); if (classLoader == null) { - classLoader = AgentConfiguration.class.getClassLoader(); + classLoader = TransferConfiguration.class.getClassLoader(); } } @@ -75,8 +76,7 @@ private void loadResource(String fileName, boolean isJson) { } else { Properties properties = new Properties(); properties.load(reader); - properties.forEach((key, value) -> configStorage.put((String) key, - new JsonPrimitive((String) value))); + properties.forEach((key, value) -> configStorage.put((String) key, new JsonPrimitive((String) value))); } } } catch (Exception ioe) { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java index 3b667c78..f3895d27 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java @@ -17,124 +17,70 @@ package com.zmops.zeus.iot.server.transfer.conf; -import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; - public class CommonConstants { - public static final String PROXY_NET_TAG = "proxy.net.tag"; - public static final String DEFAULT_PROXY_NET_TAG = ""; - - public static final String PROXY_BID = "proxy.bid"; + public static final String PROXY_BID = "proxy.bid"; public static final String POSITION_SUFFIX = ".position"; public static final String PROXY_TID = "proxy.tid"; - - public static final String PROXY_LOCAL_HOST = "proxy.localHost"; - public static final String DEFAULT_PROXY_LOCALHOST = AgentUtils.getLocalIp(); - - public static final String PROXY_IS_LOCAL_VISIT = "proxy.isLocalVisit"; - public static final boolean DEFAULT_PROXY_IS_LOCAL_VISIT = true; - - public static final String PROXY_TOTAL_ASYNC_PROXY_SIZE = "proxy.total.async.proxy.size"; - public static final int DEFAULT_PROXY_TOTAL_ASYNC_PROXY_SIZE = 200 * 1024 * 1024; - - public static final String PROXY_ALIVE_CONNECTION_NUM = "proxy.alive.connection.num"; - public static final int DEFAULT_PROXY_ALIVE_CONNECTION_NUM = 10; - - public static final String PROXY_MSG_TYPE = "proxy.msgType"; - public static final int DEFAULT_PROXY_MSG_TYPE = 7; - - public static final String PROXY_IS_COMPRESS = "proxy.is.compress"; - public static final boolean DEFAULT_PROXY_IS_COMPRESS = true; - public static final String PROXY_MAX_SENDER_PER_BID = "proxy.max.sender.per.pid"; + public static final int DEFAULT_PROXY_MAX_SENDER_PER_PID = 10; // max size of message list public static final String PROXY_PACKAGE_MAX_SIZE = "proxy.package.maxSize"; + // max size of single batch in bytes, default is 200KB. - public static final int DEFAULT_PROXY_PACKAGE_MAX_SIZE = 200000; + public static final int DEFAULT_PROXY_PACKAGE_MAX_SIZE = 2000000; public static final String PROXY_TID_QUEUE_MAX_NUMBER = "proxy.tid.queue.maxNumber"; + public static final int DEFAULT_PROXY_TID_QUEUE_MAX_NUMBER = 10000; public static final String PROXY_PACKAGE_MAX_TIMEOUT_MS = "proxy.package.maxTimeout.ms"; + public static final int DEFAULT_PROXY_PACKAGE_MAX_TIMEOUT_MS = 4 * 1000; public static final String PROXY_BATCH_FLUSH_INTERVAL = "proxy.batch.flush.interval"; - public static final int DEFAULT_PROXY_BATCH_FLUSH_INTERVAL = 2 * 1000; + + public static final int DEFAULT_PROXY_BATCH_FLUSH_INTERVAL = 100; public static final String PROXY_SENDER_MAX_TIMEOUT = "proxy.sender.maxTimeout"; + // max timeout in seconds. public static final int DEFAULT_PROXY_SENDER_MAX_TIMEOUT = 20; public static final String PROXY_SENDER_MAX_RETRY = "proxy.sender.maxRetry"; + public static final int DEFAULT_PROXY_SENDER_MAX_RETRY = 5; - public static final String PROXY_IS_FILE = "proxy.isFile"; + public static final String PROXY_IS_FILE = "proxy.isFile"; public static final boolean DEFAULT_IS_FILE = false; public static final String PROXY_RETRY_SLEEP = "proxy.retry.sleep"; + public static final long DEFAULT_PROXY_RETRY_SLEEP = 500; - public static final String PROXY_KEY_BID = "bid"; - public static final String PROXY_KEY_TID = "tid"; - public static final String PROXY_KEY_ID = "id"; + public static final String PROXY_KEY_BID = "bid"; + public static final String PROXY_KEY_TID = "tid"; + public static final String PROXY_KEY_ID = "id"; public static final String PROXY_KEY_AGENT_IP = "agentip"; - public static final String PROXY_OCEANUS_F = "f"; - public static final String PROXY_OCEANUS_BL = "bl"; - - // config for pulsar - // pulsar host port like http://host1:port1 - public static final String PULSAR_SERVERS = "pulsar.servers"; - // pulsar topic name - public static final String PULSAR_TOPIC = "pulsar.topic"; - // whether async sending data - public static final String PULSAR_PRODUCER_ASYNC = "pulsar.producer.async"; - public static final boolean DEFAULT_PULSAR_PRODUCER_ASYNC = true; - - public static final String PULSAR_PRODUCER_MAX_PENDING_COUNT = "pulsar.producer.maxPending.count"; - public static final int DEFAULT_PULSAR_PRODUCER_MAX_PENDING_COUNT = 10000; - - public static final String PULSAR_PRODUCER_THREAD_NUM = "pulsar.producer.thread.num"; - public static final int DEFAULT_PULSAR_PRODUCER_THREAD_NUM = 1; - - public static final String PULSAR_PRODUCER_ENABLE_BATCH = "pulsar.producer.enable.batch"; - public static final boolean DEFAULT_PULSAR_PRODUCER_ENABLE_BATCH = true; - - public static final String PULSAR_SINK_POLL_TIMEOUT = "pulsar.sink.poll.timeout"; - // time in ms - public static final long DEFAULT_PULSAR_SINK_POLL_TIMEOUT = 1000; - - public static final String PULSAR_SINK_CACHE_CAPACITY = "pulsar.sink.cache.capacity"; - public static final int DEFAULT_PULSAR_SINK_CACHE_CAPACITY = 100000; - - public static final String PULSAR_PRODUCER_COMPRESS_TYPE = "pulsar.producer.compress.type"; - public static final String DEFAULT_PULSAR_PRODUCER_COMPRESS_TYPE = "snappy"; - - public static final String PULSAR_PRODUCER_BATCH_MAXSIZE = "pulsar.producer.batch.maxsize"; - public static final int DEFAULT_PULSAR_PRODUCER_BATCH_MAXSIZE = 1024 * 1024; - - public static final String PULSAR_PRODUCER_BATCH_MAXCOUNT = "pulsar.producer.batch.maxcount"; - public static final int DEFAULT_PULSAR_PRODUCER_BATCH_MAXCOUNT = 1000; - - public static final String PULSAR_PRODUCER_BLOCK_QUEUE = "pulsar.producer.block.queue"; - public static final boolean DEFAULT_PULSAR_PRODUCER_BLOCK_QUEUE = true; + public static final String PROXY_OCEANUS_F = "f"; + public static final String PROXY_OCEANUS_BL = "bl"; public static final String FILE_MAX_NUM = "file.max.num"; + public static final int DEFAULT_FILE_MAX_NUM = 4096; public static final String TRIGGER_ID_PREFIX = "trigger_"; - public static final String COMMAND_STORE_INSTANCE_NAME = "commandStore"; - public static final String AGENT_OS_NAME = "os.name"; - public static final String AGENT_NIX_OS = "nix"; - public static final String AGENT_NUX_OS = "nux"; - public static final String AGENT_COLON = ":"; + public static final String AGENT_NIX_OS = "nix"; + public static final String AGENT_NUX_OS = "nux"; + public static final String AGENT_COLON = ":"; } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ConfigJetty.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ConfigJetty.java deleted file mode 100644 index c7cf2b29..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ConfigJetty.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.zmops.zeus.iot.server.transfer.conf; - - -import com.zmops.zeus.iot.server.transfer.core.job.JobManager; -import com.zmops.zeus.iot.server.transfer.core.trigger.TriggerManager; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.servlet.ServletHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.Closeable; - -import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_TRIGGER; - -/** - * start http server and get job/agent config via http - */ -public class ConfigJetty implements Closeable { - - private static final Logger LOGGER = LoggerFactory.getLogger(ConfigJetty.class); - - private final AgentConfiguration conf; - private final Server server; - private final JobManager jobManager; - private final TriggerManager triggerManager; - - public ConfigJetty(JobManager jobManager, TriggerManager triggerManager) { - this.conf = AgentConfiguration.getAgentConf(); - this.jobManager = jobManager; - this.triggerManager = triggerManager; - server = new Server(); - try { - initJetty(); - } catch (Exception ex) { - LOGGER.error("exception caught", ex); - } - } - - private void initJetty() throws Exception { - ServerConnector connector = new ServerConnector(this.server); - connector.setPort(conf.getInt(AgentConstants.AGENT_HTTP_PORT, AgentConstants.DEFAULT_AGENT_HTTP_PORT)); - server.setConnectors(new Connector[]{connector}); - - ServletHandler servletHandler = new ServletHandler(); - ServletHolder holder = new ServletHolder(new ConfigServlet(this)); - servletHandler.addServletWithMapping(holder, "/config/*"); - server.setHandler(servletHandler); - server.start(); - } - - public void storeJobConf(JobProfile jobProfile) { - // store job conf to bdb - if (jobProfile != null) { - // trigger job is a special kind of job - if (jobProfile.hasKey(JOB_TRIGGER)) { - triggerManager.submitTrigger(TriggerProfile.parseJsonStr(jobProfile.toJsonStr())); - } else { - jobManager.submitJobProfile(jobProfile); - } - } - } - - public void storeAgentConf(String confJsonStr) { - // store agent conf to local file - AgentConfiguration conf = AgentConfiguration.getAgentConf(); - conf.loadJsonStrResource(confJsonStr); - conf.flushToLocalPropertiesFile(); - } - - /** - * delete job from conf - * - * @param jobProfile - */ - public void deleteJobConf(JobProfile jobProfile) { - if (jobProfile != null) { - if (jobProfile.hasKey(JOB_TRIGGER)) { - triggerManager.deleteTrigger(TriggerProfile.parseJobProfile(jobProfile).getTriggerId()); - } else { - jobManager.deleteJob(jobProfile.getInstanceId()); - } - } - } - - @Override - public void close() { - try { - if (this.server != null) { - this.server.stop(); - } - } catch (Exception ex) { - LOGGER.error("exception caught", ex); - } - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ConfigServlet.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ConfigServlet.java deleted file mode 100644 index 16765458..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ConfigServlet.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.zmops.zeus.iot.server.transfer.conf; - -import com.google.gson.Gson; -import org.apache.commons.io.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.PrintWriter; - -public class ConfigServlet extends HttpServlet { - - private static final Logger LOGGER = LoggerFactory.getLogger(ConfigServlet.class); - - private static final String CONTENT_TYPE = "application/json"; - private static final String CHARSET_TYPE = "UTF-8"; - private static final String JOB_TYPE = "job"; - private static final String AGENT_TYPE = "agent"; - private static final String TRIGGER_TYPE = "trigger"; - private static final String OP_TYPE = "op"; - private static final String ADD_OP = "add"; - private static final String DELETE_OP = "delete"; - private final Gson gson = new Gson(); - private final ConfigJetty configHandler; - - public ConfigServlet(ConfigJetty configHandler) { - this.configHandler = configHandler; - } - - public void responseToJson(HttpServletResponse response, - ResponseResult result) throws IOException { - response.setContentType(CONTENT_TYPE); - response.setCharacterEncoding(CHARSET_TYPE); - String jsonStr = gson.toJson(result); - PrintWriter out = response.getWriter(); - out.print(jsonStr); - out.flush(); - } - - /** - * handle path of "/config/job" - * @param jobProfileStr - job profile string - */ - private void handleJob(String jobProfileStr) { - JobProfile jobProfile = JobProfile.parseJsonStr(jobProfileStr); - - String op = jobProfile.get(OP_TYPE); - - if (ADD_OP.equals(op)) { - configHandler.storeJobConf(jobProfile); - } else if (DELETE_OP.equals(op)) { - configHandler.deleteJobConf(jobProfile); - } - } - - private void handleAgent(String agentProfileStr) { - // TODO: handle agent - } - - /** - * handle post requests. - * - * @param req - request - * @param resp - response - */ - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { - String pathInfo = req.getPathInfo(); - ResponseResult responseResult = new ResponseResult(0, ""); - - try (BufferedReader reader = req.getReader()) { - String configJsonStr = IOUtils.toString(reader); - LOGGER.info("Getting request {}", configJsonStr); - // path is "/config/job" - if (pathInfo.endsWith(JOB_TYPE)) { - handleJob(configJsonStr); - } else if (pathInfo.endsWith(AGENT_TYPE)) { - handleAgent(configJsonStr); - } else { - responseResult.setCode(-1).setMessage("child path is not correct"); - } - } catch (Exception ex) { - LOGGER.error("error while handle post", ex); - responseResult.setCode(-1).setMessage(ex.getMessage()); - } - responseToJson(resp, responseResult); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java index 1d9ad53a..51934e75 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java @@ -24,20 +24,16 @@ public class JobConstants extends CommonConstants { // job id - public static final String JOB_ID = "job.id"; + public static final String JOB_ID = "job.id"; public static final String JOB_INSTANCE_ID = "job.instance.id"; - public static final String JOB_IP = "job.ip"; - public static final String JOB_RETRY = "job.retry"; + public static final String JOB_IP = "job.ip"; + public static final String JOB_RETRY = "job.retry"; - - public static final String JOB_SOURCE = "job.source"; - public static final String JOB_SINK = "job.sink"; - public static final String JOB_CHANNEL = "job.channel"; - public static final String JOB_TRIGGER = "job.trigger"; - public static final String JOB_NAME = "job.name"; + public static final String JOB_TRIGGER = "job.trigger"; + public static final String JOB_NAME = "job.name"; public static final String JOB_LINE_FILTER_PATTERN = "job.pattern"; - public static final String DEFAULT_JOB_NAME = "default"; - public static final String JOB_DESCRIPTION = "job.description"; + public static final String DEFAULT_JOB_NAME = "default"; + public static final String JOB_DESCRIPTION = "job.description"; public static final String DEFAULT_JOB_DESCRIPTION = "default job description"; public static final String DEFAULT_JOB_LINE_FILTER = ""; @@ -51,9 +47,9 @@ public class JobConstants extends CommonConstants { public static final String DEFAULT_JOB_FILE_TIME_OFFSET = "0d"; - public static final String JOB_FILE_MAX_WAIT = "job.file.max.wait"; + public static final String JOB_FILE_MAX_WAIT = "job.file.max.wait"; // time in min - public static final int DEFAULT_JOB_FILE_MAX_WAIT = 1; + public static final int DEFAULT_JOB_FILE_MAX_WAIT = 1; public static final String JOB_DIR_FILTER_PATTERN = "job.dir.pattern"; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobProfile.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobProfile.java index d37d43b9..0e923edb 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobProfile.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobProfile.java @@ -22,7 +22,6 @@ /** * job profile which contains details describing properties of one job. - * */ public class JobProfile extends AbstractConfiguration { @@ -54,6 +53,7 @@ public static JobProfile parsePropertiesFile(String fileName) { /** * pase json file. + * * @param fileName - json file name. * @return jobConfiguration. */ @@ -70,9 +70,7 @@ public static JobProfile parseJsonFile(String fileName) { */ @Override public boolean allRequiredKeyExist() { - return hasKey(JobConstants.JOB_ID) && hasKey(JobConstants.JOB_SOURCE) - && hasKey(JobConstants.JOB_SINK) && hasKey(JobConstants.JOB_CHANNEL) && hasKey( - JobConstants.JOB_NAME); + return hasKey(JobConstants.JOB_ID); } public String toJsonStr() { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ProfileFetcher.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ProfileFetcher.java deleted file mode 100644 index 50b01838..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ProfileFetcher.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.zmops.zeus.iot.server.transfer.conf; - -import com.zmops.zeus.iot.server.transfer.core.common.Service; - -import java.util.List; - -/** - * fetch profile from other system, communicate with json format string - */ -public interface ProfileFetcher extends Service { - - /** - * get job profiles - * @return - job profile list - */ - List getJobProfiles(); - - /** - * get trigger profiles - * @return - trigger profile lisy - */ - List getTriggerProfiles(); -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ResponseResult.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ResponseResult.java deleted file mode 100644 index 0d9671fb..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/ResponseResult.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.zmops.zeus.iot.server.transfer.conf; - -/** - * response json for http requests. - */ -public class ResponseResult { - private int code; - private String message; - - public int getCode() { - return code; - } - - public ResponseResult(int code, String message) { - this.code = code; - this.message = message; - } - - public ResponseResult setCode(int code) { - this.code = code; - return this; - } - - public String getMessage() { - return message; - } - - public ResponseResult setMessage(String message) { - this.message = message; - return this; - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AgentConfiguration.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConfiguration.java similarity index 82% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AgentConfiguration.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConfiguration.java index 7b50bb78..940d9897 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AgentConfiguration.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConfiguration.java @@ -33,11 +33,11 @@ * agent configuration. Only one instance in the process. * Basically it use properties file to store configurations. */ -public class AgentConfiguration extends AbstractConfiguration { +public class TransferConfiguration extends AbstractConfiguration { - private static final Logger LOGGER = LoggerFactory.getLogger(AgentConfiguration.class); + private static final Logger LOGGER = LoggerFactory.getLogger(TransferConfiguration.class); - private static final String DEFAULT_CONFIG_FILE = "agent.properties"; + private static final String DEFAULT_CONFIG_FILE = "tansfer.properties"; private static final String TMP_CONFIG_FILE = ".tmp.agent.properties"; private static final ArrayList LOCAL_RESOURCES = new ArrayList<>(); @@ -48,12 +48,12 @@ public class AgentConfiguration extends AbstractConfiguration { LOCAL_RESOURCES.add(DEFAULT_CONFIG_FILE); } - private static volatile AgentConfiguration agentConf = null; + private static volatile TransferConfiguration transferConfig = null; /** * load config from agent file. */ - private AgentConfiguration() { + private TransferConfiguration() { for (String fileName : LOCAL_RESOURCES) { super.loadPropertiesResource(fileName); } @@ -64,15 +64,15 @@ private AgentConfiguration() { * * @return - static instance of AgentConfiguration */ - public static AgentConfiguration getAgentConf() { - if (agentConf == null) { - synchronized (AgentConfiguration.class) { - if (agentConf == null) { - agentConf = new AgentConfiguration(); + public static TransferConfiguration getAgentConf() { + if (transferConfig == null) { + synchronized (TransferConfiguration.class) { + if (transferConfig == null) { + transferConfig = new TransferConfiguration(); } } } - return agentConf; + return transferConfig; } private String getNextBackupFileName() { @@ -88,7 +88,7 @@ public void flushToLocalPropertiesFile() { LOCK.writeLock().lock(); // TODO: flush to local file as properties file. try { - String agentConfParent = get(AgentConstants.AGENT_CONF_PARENT, AgentConstants.DEFAULT_AGENT_CONF_PARENT); + String agentConfParent = get(TransferConstants.AGENT_CONF_PARENT, TransferConstants.DEFAULT_AGENT_CONF_PARENT); File sourceFile = new File(agentConfParent, DEFAULT_CONFIG_FILE); File targetFile = new File(agentConfParent, getNextBackupFileName()); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AgentConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java similarity index 97% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AgentConstants.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java index 7669f586..cfef145a 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AgentConstants.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java @@ -19,7 +19,7 @@ import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; -public class AgentConstants { +public class TransferConstants { public static final String AGENT_HOME = "agent.home"; public static final String DEFAULT_AGENT_HOME = System.getProperty("agent.home"); @@ -45,7 +45,7 @@ public class AgentConstants { public static final String DEFAULT_AGENT_DB_INSTANCE_NAME = "agent"; public static final String AGENT_DB_CLASSNAME = "agent.db.classname"; - public static final String DEFAULT_AGENT_DB_CLASSNAME = "org.apache.inlong.agent.db.BerkeleyDbImp"; + public static final String DEFAULT_AGENT_DB_CLASSNAME = "com.zmops.zeus.iot.server.transfer.core.db.BerkeleyDbImp"; // default is empty. public static final String AGENT_FETCHER_CLASSNAME = "agent.fetcher.classname"; @@ -60,7 +60,7 @@ public class AgentConstants { public static final int DEFAULT_AGENT_HTTP_PORT = 8008; public static final String AGENT_ENABLE_HTTP = "agent.http.enable"; - public static final boolean DEFAULT_AGENT_ENABLE_HTTP = false; + public static final boolean DEFAULT_AGENT_ENABLE_HTTP = true; public static final String TRIGGER_FETCH_INTERVAL = "trigger.fetch.interval"; public static final int DEFAULT_TRIGGER_FETCH_INTERVAL = 1; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TriggerProfile.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TriggerProfile.java index d75c76e0..00dcbe78 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TriggerProfile.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TriggerProfile.java @@ -24,7 +24,7 @@ public class TriggerProfile extends JobProfile { @Override public boolean allRequiredKeyExist() { - return hasKey(JobConstants.JOB_TRIGGER) && super.allRequiredKeyExist(); + return hasKey(JobConstants.JOB_NAME) && super.allRequiredKeyExist(); } public static TriggerProfile parseJsonStr(String jsonStr) { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java index f71136b9..a49d69e3 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java @@ -20,7 +20,7 @@ import com.zmops.zeus.iot.server.transfer.core.api.Channel; import com.zmops.zeus.iot.server.transfer.core.api.Message; -import com.zmops.zeus.iot.server.transfer.conf.AgentConstants; +import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.core.metrics.PluginMetric; import org.slf4j.Logger; @@ -94,8 +94,8 @@ public Message pull(long timeout, TimeUnit unit) { @Override public void init(JobProfile jobConf) { - queue = new LinkedBlockingQueue<>(jobConf.getInt(AgentConstants.CHANNEL_MEMORY_CAPACITY, - AgentConstants.DEFAULT_CHANNEL_MEMORY_CAPACITY)); + queue = new LinkedBlockingQueue<>(jobConf.getInt(TransferConstants.CHANNEL_MEMORY_CAPACITY, + TransferConstants.DEFAULT_CHANNEL_MEMORY_CAPACITY)); } @Override diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java index 8970b51c..75580b7d 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java @@ -21,8 +21,8 @@ import com.sleepycat.je.EnvironmentConfig; import com.sleepycat.persist.*; -import com.zmops.zeus.iot.server.transfer.conf.AgentConfiguration; -import com.zmops.zeus.iot.server.transfer.conf.AgentConstants; +import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; +import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.conf.CommonConstants; import com.zmops.zeus.iot.server.transfer.core.job.CommandEntity; import org.slf4j.Logger; @@ -52,16 +52,16 @@ public class BerkeleyDbImp implements Db { private final SecondaryIndex fileNameSecondaryIndex; private final SecondaryIndex commandSecondaryIndex; - private final AgentConfiguration agentConf; + private final TransferConfiguration transferConfig; public BerkeleyDbImp() { - this.agentConf = AgentConfiguration.getAgentConf(); + this.transferConfig = TransferConfiguration.getAgentConf(); StoreConfig storeConfig = initStoreConfig(); Environment environment = initEnv(); - String instanceName = agentConf.get(AgentConstants.AGENT_DB_INSTANCE_NAME, AgentConstants.DEFAULT_AGENT_DB_INSTANCE_NAME); + String instanceName = transferConfig.get(TransferConstants.AGENT_DB_INSTANCE_NAME, TransferConstants.DEFAULT_AGENT_DB_INSTANCE_NAME); this.jobStore = new EntityStore(environment, instanceName, storeConfig); this.commandStore = new EntityStore(environment, CommonConstants.COMMAND_STORE_INSTANCE_NAME, storeConfig); @@ -83,9 +83,9 @@ public BerkeleyDbImp() { */ private StoreConfig initStoreConfig() { return new StoreConfig() - .setReadOnly(agentConf.getBoolean(AgentConstants.AGENT_LOCAL_STORE_READONLY, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_READONLY)) - .setAllowCreate(!agentConf.getBoolean(AgentConstants.AGENT_LOCAL_STORE_READONLY, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_READONLY)) - .setTransactional(agentConf.getBoolean(AgentConstants.AGENT_LOCAL_STORE_TRANSACTIONAL, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_TRANSACTIONAL)); + .setReadOnly(transferConfig.getBoolean(TransferConstants.AGENT_LOCAL_STORE_READONLY, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_READONLY)) + .setAllowCreate(!transferConfig.getBoolean(TransferConstants.AGENT_LOCAL_STORE_READONLY, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_READONLY)) + .setTransactional(transferConfig.getBoolean(TransferConstants.AGENT_LOCAL_STORE_TRANSACTIONAL, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_TRANSACTIONAL)); } /** @@ -94,8 +94,8 @@ private StoreConfig initStoreConfig() { * @return local path. */ private File tryToInitAndGetPath() { - String storePath = agentConf.get(AgentConstants.AGENT_LOCAL_STORE_PATH, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_PATH); - String parentPath = agentConf.get(AgentConstants.AGENT_HOME, AgentConstants.DEFAULT_AGENT_HOME); + String storePath = transferConfig.get(TransferConstants.AGENT_LOCAL_STORE_PATH, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_PATH); + String parentPath = transferConfig.get(TransferConstants.AGENT_HOME, TransferConstants.DEFAULT_AGENT_HOME); File finalPath = new File(parentPath, storePath); try { @@ -114,13 +114,13 @@ private File tryToInitAndGetPath() { */ private Environment initEnv() { EnvironmentConfig envConfig = new EnvironmentConfig() - .setReadOnly(agentConf.getBoolean(AgentConstants.AGENT_LOCAL_STORE_READONLY, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_READONLY)) - .setAllowCreate(!agentConf.getBoolean(AgentConstants.AGENT_LOCAL_STORE_READONLY, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_READONLY)) - .setTransactional(agentConf.getBoolean(AgentConstants.AGENT_LOCAL_STORE_TRANSACTIONAL, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_TRANSACTIONAL)) - .setLockTimeout(agentConf.getInt(AgentConstants.AGENT_LOCAL_STORE_LOCK_TIMEOUT, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_LOCK_TIMEOUT), TimeUnit.MILLISECONDS); + .setReadOnly(transferConfig.getBoolean(TransferConstants.AGENT_LOCAL_STORE_READONLY, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_READONLY)) + .setAllowCreate(!transferConfig.getBoolean(TransferConstants.AGENT_LOCAL_STORE_READONLY, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_READONLY)) + .setTransactional(transferConfig.getBoolean(TransferConstants.AGENT_LOCAL_STORE_TRANSACTIONAL, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_TRANSACTIONAL)) + .setLockTimeout(transferConfig.getInt(TransferConstants.AGENT_LOCAL_STORE_LOCK_TIMEOUT, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_LOCK_TIMEOUT), TimeUnit.MILLISECONDS); - envConfig.setTxnNoSyncVoid(agentConf.getBoolean(AgentConstants.AGENT_LOCAL_STORE_NO_SYNC_VOID, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_NO_SYNC_VOID)); - envConfig.setTxnWriteNoSyncVoid(agentConf.getBoolean(AgentConstants.AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID, AgentConstants.DEFAULT_AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID)); + envConfig.setTxnNoSyncVoid(transferConfig.getBoolean(TransferConstants.AGENT_LOCAL_STORE_NO_SYNC_VOID, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_NO_SYNC_VOID)); + envConfig.setTxnWriteNoSyncVoid(transferConfig.getBoolean(TransferConstants.AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID)); return new Environment(tryToInitAndGetPath(), envConfig); } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java index 1372e313..053d5df1 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java @@ -69,10 +69,11 @@ public void updateJobState(String jobInstanceId, StateSearchKey stateSearchKey) */ public void storeJobFirstTime(JobProfile jobProfile) { if (jobProfile.allRequiredKeyExist()) { + String keyName = jobProfile.get(JobConstants.JOB_INSTANCE_ID); jobProfile.setLong(JobConstants.JOB_STORE_TIME, System.currentTimeMillis()); - KeyValueEntity entity = new KeyValueEntity(keyName, - jobProfile.toJsonStr(), jobProfile.get(JobConstants.JOB_DIR_FILTER_PATTERN)); + + KeyValueEntity entity = new KeyValueEntity(keyName, jobProfile.toJsonStr(), jobProfile.get(JobConstants.JOB_DIR_FILTER_PATTERN)); entity.setStateSearchKey(StateSearchKey.ACCEPTED); db.put(entity); } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/KeyValueEntity.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/KeyValueEntity.java index d71533c8..909bebaf 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/KeyValueEntity.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/KeyValueEntity.java @@ -44,8 +44,7 @@ public class KeyValueEntity { private String jsonValue; - private KeyValueEntity() { - + public KeyValueEntity() { } public KeyValueEntity(String key, String jsonValue, String fileName) { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/LocalProfile.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/LocalProfile.java deleted file mode 100644 index bbd71813..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/LocalProfile.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package com.zmops.zeus.iot.server.transfer.core.db; - -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * profile from local file - */ -public class LocalProfile { - private static final Logger LOGGER = LoggerFactory.getLogger(LocalProfile.class); - - private static final String JSON_SUFFIX = ".json"; - private static final String PROPERTIES_SUFFIX = ".properties"; - private static final String PARENT_PATH = "/jobs"; - - private final Path filePath; - - public LocalProfile(String parentConfPath) { - String fileName = parentConfPath + PARENT_PATH; - this.filePath = Paths.get(fileName); - } - - public List readFromLocal() { - List profileList = new ArrayList<>(); - try { - if (Files.isDirectory(this.filePath)) { - // list parent path and find files which name is end with .json or .properties - for (Iterator it = Files.list(this.filePath).iterator(); it.hasNext(); ) { - String childPath = it.next().toString(); - JobProfile jobProfile = null; - if (childPath.endsWith(JSON_SUFFIX)) { - jobProfile = JobProfile.parseJsonFile(childPath); - } else if (childPath.endsWith(PROPERTIES_SUFFIX)) { - jobProfile = JobProfile.parsePropertiesFile(childPath); - } - if (jobProfile != null && jobProfile.allRequiredKeyExist()) { - profileList.add(jobProfile); - } - } - } - } catch (Exception ex) { - LOGGER.error("error in reading files {}", this.filePath); - } - return profileList; - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/TriggerProfileDb.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/TriggerProfileDb.java index 5a3ff621..2c7e5a2a 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/TriggerProfileDb.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/TriggerProfileDb.java @@ -28,6 +28,8 @@ /** * db interface for trigger profile. + *

+ * 保存 文件夹触发器 配置文件 */ public class TriggerProfileDb { @@ -46,11 +48,14 @@ public TriggerProfileDb(Db db) { */ public List getTriggers() { // potential performance issue, needs to find out the speed. - List result = this.db.findAll(CommonConstants.TRIGGER_ID_PREFIX); + List result = this.db.findAll(CommonConstants.TRIGGER_ID_PREFIX); + List triggerList = new ArrayList<>(); + for (KeyValueEntity entity : result) { triggerList.add(entity.getAsTriggerProfile()); } + return triggerList; } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java index 851efa91..509dd160 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java @@ -31,7 +31,8 @@ public class CommandDb { public static final int MANAGER_SUCCESS_CODE = 0; public static final int MANAGER_FAIL_CODE = 1; - private final Db db; + + private final Db db; public CommandDb(Db db) { this.db = db; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java index 29caf070..c7ca3349 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java @@ -24,6 +24,9 @@ import com.zmops.zeus.iot.server.transfer.core.api.Reader; import com.zmops.zeus.iot.server.transfer.core.api.Sink; import com.zmops.zeus.iot.server.transfer.core.api.Source; +import com.zmops.zeus.iot.server.transfer.core.channel.MemoryChannel; +import com.zmops.zeus.iot.server.transfer.core.sink.NdjsonSink; +import com.zmops.zeus.iot.server.transfer.core.source.TextFileSource; import com.zmops.zeus.iot.server.transfer.core.task.Task; import lombok.Getter; import lombok.Setter; @@ -43,12 +46,10 @@ public class Job { private final JobProfile jobConf; - // job name @Getter @Setter private String name; - // job description @Getter @Setter private String description; @@ -68,18 +69,15 @@ public List createTasks() { List taskList = new ArrayList<>(); int index = 0; try { - LOGGER.info("job id: {}, source: {}, channel: {}, sink: {}", - getJobInstanceId(), jobConf.get(JobConstants.JOB_SOURCE), - jobConf.get(JobConstants.JOB_CHANNEL), - jobConf.get(JobConstants.JOB_SINK)); + LOGGER.info("job id: {}, job name {} ", getJobInstanceId(), getName()); - Source source = (Source) Class.forName(jobConf.get(JobConstants.JOB_SOURCE)).newInstance(); + Source source = new TextFileSource(); for (Reader reader : source.split(jobConf)) { - Sink writer = (Sink) Class.forName(jobConf.get(JobConstants.JOB_SINK)).newInstance(); + Sink writer = new NdjsonSink(); writer.setSourceFile(reader.getReadFile()); - Channel channel = (Channel) Class.forName(jobConf.get(JobConstants.JOB_CHANNEL)).newInstance(); + Channel channel = new MemoryChannel(); String taskId = String.format("%s_%d", jobInstanceId, index++); taskList.add(new Task(taskId, reader, writer, channel, getJobConf())); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java index a102bf58..1158d05b 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java @@ -18,14 +18,14 @@ package com.zmops.zeus.iot.server.transfer.core.job; -import com.zmops.zeus.iot.server.transfer.conf.AgentConfiguration; -import com.zmops.zeus.iot.server.transfer.conf.AgentConstants; +import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; +import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; import com.zmops.zeus.iot.server.transfer.core.common.AgentThreadFactory; import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; import com.zmops.zeus.iot.server.transfer.core.db.StateSearchKey; -import com.zmops.zeus.iot.server.transfer.core.manager.AgentManager; +import com.zmops.zeus.iot.server.transfer.core.manager.TransferManager; import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,7 +38,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; -import static com.zmops.zeus.iot.server.transfer.conf.AgentConstants.*; +import static com.zmops.zeus.iot.server.transfer.conf.TransferConstants.*; import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.*; /** @@ -53,9 +53,9 @@ public class JobManager extends AbstractDaemon { // jobs which are not accepted by running pool. private final ConcurrentHashMap pendingJobs; // job thread pool - private final ThreadPoolExecutor runningPool; - private final AgentManager agentManager; - private final int monitorInterval; + private final ThreadPoolExecutor runningPool; + private final TransferManager transferManager; + private final int monitorInterval; private final long jobDbCacheTime; private final long jobDbCacheCheckInterval; @@ -67,11 +67,11 @@ public class JobManager extends AbstractDaemon { /** * init job manager * - * @param agentManager - agent manager + * @param transferManager - agent manager */ - public JobManager(AgentManager agentManager, JobProfileDb jobConfDb) { + public JobManager(TransferManager transferManager, JobProfileDb jobConfDb) { this.jobConfDB = jobConfDb; - this.agentManager = agentManager; + this.transferManager = transferManager; // job thread pool for running this.runningPool = new ThreadPoolExecutor( @@ -83,9 +83,9 @@ public JobManager(AgentManager agentManager, JobProfileDb jobConfDb) { this.jobs = new ConcurrentHashMap<>(); this.pendingJobs = new ConcurrentHashMap<>(); - AgentConfiguration conf = AgentConfiguration.getAgentConf(); + TransferConfiguration conf = TransferConfiguration.getAgentConf(); - this.monitorInterval = conf.getInt(AgentConstants.JOB_MONITOR_INTERVAL, AgentConstants.DEFAULT_JOB_MONITOR_INTERVAL); + this.monitorInterval = conf.getInt(TransferConstants.JOB_MONITOR_INTERVAL, TransferConstants.DEFAULT_JOB_MONITOR_INTERVAL); this.jobDbCacheTime = conf.getLong(JOB_DB_CACHE_TIME, DEFAULT_JOB_DB_CACHE_TIME); this.jobDbCacheCheckInterval = conf.getLong(JOB_DB_CACHE_CHECK_INTERVAL, DEFAULT_JOB_DB_CACHE_CHECK_INTERVAL); this.jobMetrics = JobMetrics.create(); @@ -98,7 +98,7 @@ public JobManager(AgentManager agentManager, JobProfileDb jobConfDb) { */ public void addJob(Job job) { try { - JobWrapper jobWrapper = new JobWrapper(agentManager, job); + JobWrapper jobWrapper = new JobWrapper(transferManager, job); this.runningPool.execute(jobWrapper); JobWrapper jobWrapperRet = jobs.putIfAbsent(jobWrapper.getJob().getJobInstanceId(), jobWrapper); if (jobWrapperRet != null) { @@ -124,6 +124,7 @@ public boolean submitJobProfile(JobProfile profile) { return false; } String jobId = profile.get(JOB_ID); + profile.set(JOB_INSTANCE_ID, AgentUtils.getUniqId(JOB_ID_PREFIX, jobId, index.incrementAndGet())); LOGGER.info("submit job profile {}", profile.toJsonStr()); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java index 61a68d11..124a69e2 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java @@ -18,9 +18,9 @@ package com.zmops.zeus.iot.server.transfer.core.job; -import com.zmops.zeus.iot.server.transfer.conf.AgentConfiguration; -import com.zmops.zeus.iot.server.transfer.conf.AgentConstants; -import com.zmops.zeus.iot.server.transfer.core.manager.AgentManager; +import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; +import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; +import com.zmops.zeus.iot.server.transfer.core.manager.TransferManager; import com.zmops.zeus.iot.server.transfer.core.state.AbstractStateWrapper; import com.zmops.zeus.iot.server.transfer.core.state.State; import com.zmops.zeus.iot.server.transfer.core.task.Task; @@ -40,16 +40,16 @@ public class JobWrapper extends AbstractStateWrapper { private static final Logger LOGGER = LoggerFactory.getLogger(JobWrapper.class); - private final AgentConfiguration agentConf; - private final TaskManager taskManager; - private final JobManager jobManager; - private final Job job; + private final TransferConfiguration transferConfig; + private final TaskManager taskManager; + private final JobManager jobManager; + private final Job job; private final List allTasks; - public JobWrapper(AgentManager manager, Job job) { + public JobWrapper(TransferManager manager, Job job) { super(); - this.agentConf = AgentConfiguration.getAgentConf(); + this.transferConfig = TransferConfiguration.getAgentConf(); this.taskManager = manager.getTaskManager(); this.jobManager = manager.getJobManager(); this.job = job; @@ -63,7 +63,7 @@ public JobWrapper(AgentManager manager, Job job) { private void checkAllTasksStateAndWait() throws Exception { boolean isFinished = false; - long checkInterval = agentConf.getLong(AgentConstants.JOB_FINISH_CHECK_INTERVAL, AgentConstants.DEFAULT_JOB_FINISH_CHECK_INTERVAL); + long checkInterval = transferConfig.getLong(TransferConstants.JOB_FINISH_CHECK_INTERVAL, TransferConstants.DEFAULT_JOB_FINISH_CHECK_INTERVAL); do { // check whether all tasks have finished. isFinished = allTasks.stream().allMatch(task -> taskManager.isTaskFinished(task.getTaskId())); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/AgentManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/AgentManager.java deleted file mode 100644 index 5ae56818..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/AgentManager.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.zmops.zeus.iot.server.transfer.core.manager; - - -import com.zmops.zeus.iot.server.transfer.conf.*; -import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; -import com.zmops.zeus.iot.server.transfer.core.db.Db; -import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; -import com.zmops.zeus.iot.server.transfer.core.db.LocalProfile; -import com.zmops.zeus.iot.server.transfer.core.db.TriggerProfileDb; -import com.zmops.zeus.iot.server.transfer.core.job.CommandDb; -import com.zmops.zeus.iot.server.transfer.core.job.JobManager; -import com.zmops.zeus.iot.server.transfer.core.task.TaskManager; -import com.zmops.zeus.iot.server.transfer.core.task.TaskPositionManager; -import com.zmops.zeus.iot.server.transfer.core.trigger.TriggerManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Constructor; -import java.util.List; - -import static com.zmops.zeus.iot.server.transfer.conf.AgentConstants.AGENT_CONF_PARENT; -import static com.zmops.zeus.iot.server.transfer.conf.AgentConstants.DEFAULT_AGENT_CONF_PARENT; -import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_TRIGGER; - -/** - * Agent Manager, the bridge for job manager, task manager, db e.t.c it manages agent level - * operations and communicates with outside system. - */ -public class AgentManager extends AbstractDaemon { - - private static final Logger LOGGER = LoggerFactory.getLogger(AgentManager.class); - private final JobManager jobManager; - private final TaskManager taskManager; - private final TriggerManager triggerManager; - private final TaskPositionManager taskPositionManager; - - // jetty for config operations via http. - private ConfigJetty configJetty; - - - private final ProfileFetcher fetcher; - private final AgentConfiguration conf; - private final Db db; - private final LocalProfile localProfile; - private final CommandDb commandDb; - - public AgentManager() { - conf = AgentConfiguration.getAgentConf(); - - this.db = initDb(); - - commandDb = new CommandDb(db); - - String parentConfPath = conf.get(AGENT_CONF_PARENT, DEFAULT_AGENT_CONF_PARENT); - - localProfile = new LocalProfile(parentConfPath); - fetcher = initFetcher(this); - triggerManager = new TriggerManager(this, new TriggerProfileDb(db)); - - jobManager = new JobManager(this, new JobProfileDb(db)); - taskManager = new TaskManager(this); - taskPositionManager = TaskPositionManager.getTaskPositionManager(this); - - // need to be an option. - if (conf.getBoolean(AgentConstants.AGENT_ENABLE_HTTP, AgentConstants.DEFAULT_AGENT_ENABLE_HTTP)) { - this.configJetty = new ConfigJetty(jobManager, triggerManager); - } - } - - /** - * init fetch by class name - * - * @return - */ - private ProfileFetcher initFetcher(AgentManager agentManager) { - try { - Constructor constructor = Class.forName(conf.get(AgentConstants.AGENT_FETCHER_CLASSNAME)).getDeclaredConstructor(AgentManager.class); - - constructor.setAccessible(true); - return (ProfileFetcher) constructor.newInstance(agentManager); - } catch (Exception ex) { - LOGGER.warn("cannot find fetcher, ignore it {}", ex.getMessage()); - } - return null; - } - - /** - * init db by class name - * - * @return db - */ - private Db initDb() { - try { - // db is a required component, so if not init correctly, - // throw exception and stop running. - return (Db) Class.forName(conf.get(AgentConstants.AGENT_DB_CLASSNAME, AgentConstants.DEFAULT_AGENT_DB_CLASSNAME)).newInstance(); - } catch (Exception ex) { - throw new UnsupportedClassVersionError(ex.getMessage()); - } - } - - public JobManager getJobManager() { - return jobManager; - } - - public Db getDb() { - return db; - } - - public ProfileFetcher getFetcher() { - return fetcher; - } - - public CommandDb getCommandDb() { - return commandDb; - } - - public TriggerManager getTriggerManager() { - return triggerManager; - } - - public TaskPositionManager getTaskPositionManager() { - return taskPositionManager; - } - - public TaskManager getTaskManager() { - return taskManager; - } - - @Override - public void join() { - super.join(); - jobManager.join(); - taskManager.join(); - } - - @Override - public void start() throws Exception { - LOGGER.info("starting agent manager"); - triggerManager.start(); - jobManager.start(); - taskManager.start(); - taskPositionManager.start(); - // read job profiles from local - List profileList = localProfile.readFromLocal(); - for (JobProfile profile : profileList) { - if (profile.hasKey(JOB_TRIGGER)) { - TriggerProfile triggerProfile = TriggerProfile.parseJobProfile(profile); - // there is no need to store this profile in triggerDB, because - // this profile comes from local file. - triggerManager.addTrigger(triggerProfile); - } else { - // job db store instance info, so it's suitable to use submitJobProfile - // to store instance into job db. - jobManager.submitJobProfile(profile); - } - } - if (fetcher != null) { - fetcher.start(); - } - } - - /** - * It should guarantee thread-safe, and can be invoked many times. - * - * @throws Exception exceptions - */ - @Override - public void stop() throws Exception { - if (configJetty != null) { - configJetty.close(); - } - - if (fetcher != null) { - fetcher.stop(); - } - - // TODO: change job state which is in running state. - LOGGER.info("stopping agent manager"); - - // close in order: trigger -> job -> task - triggerManager.stop(); - jobManager.stop(); - taskManager.stop(); - taskPositionManager.stop(); - this.db.close(); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/TransferManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/TransferManager.java new file mode 100644 index 00000000..455d427f --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/TransferManager.java @@ -0,0 +1,131 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.manager; + + +import com.zmops.zeus.iot.server.transfer.conf.*; +import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; +import com.zmops.zeus.iot.server.transfer.core.db.Db; +import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; +import com.zmops.zeus.iot.server.transfer.core.db.TriggerProfileDb; +import com.zmops.zeus.iot.server.transfer.core.job.CommandDb; +import com.zmops.zeus.iot.server.transfer.core.job.JobManager; +import com.zmops.zeus.iot.server.transfer.core.task.TaskManager; +import com.zmops.zeus.iot.server.transfer.core.task.TaskPositionManager; +import com.zmops.zeus.iot.server.transfer.core.trigger.TriggerManager; +import lombok.Getter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_TRIGGER; + +/** + * Zabbix History Data Transfer + */ +public class TransferManager extends AbstractDaemon { + + private static final Logger LOGGER = LoggerFactory.getLogger(TransferManager.class); + + @Getter + private final JobManager jobManager; + + @Getter + private final TaskManager taskManager; + + @Getter + private final TriggerManager triggerManager; + + @Getter + private final TaskPositionManager taskPositionManager; + + private final TransferConfiguration conf; + + @Getter + private final Db db; + + @Getter + private final CommandDb commandDb; + + public TransferManager() { + conf = TransferConfiguration.getAgentConf(); + this.db = initDb(); + commandDb = new CommandDb(db); + + triggerManager = new TriggerManager(this, new TriggerProfileDb(db)); + jobManager = new JobManager(this, new JobProfileDb(db)); + taskManager = new TaskManager(this); + taskPositionManager = TaskPositionManager.getTaskPositionManager(this); + } + + /** + * init db by class name + * + * @return db + */ + private Db initDb() { + try { + // db is a required component, so if not init correctly, throw exception and stop running. + return (Db) Class.forName(conf.get(TransferConstants.AGENT_DB_CLASSNAME, TransferConstants.DEFAULT_AGENT_DB_CLASSNAME)).newInstance(); + } catch (Exception ex) { + throw new UnsupportedClassVersionError(ex.getMessage()); + } + } + + @Override + public void join() { + super.join(); + jobManager.join(); + taskManager.join(); + } + + @Override + public void start() throws Exception { + LOGGER.info("starting zeus-transfer manager"); + + triggerManager.start(); + jobManager.start(); + taskManager.start(); + taskPositionManager.start(); + + JobProfile profile = JobProfile.parseJsonFile("job.json"); + + TriggerProfile triggerProfile = TriggerProfile.parseJobProfile(profile); + triggerManager.addTrigger(triggerProfile); + +// jobManager.submitJobProfile(profile); + } + + /** + * It should guarantee thread-safe, and can be invoked many times. + * + * @throws Exception exceptions + */ + @Override + public void stop() throws Exception { + + // TODO: change job state which is in running state. + LOGGER.info("stopping agent manager"); + + // close in order: trigger -> job -> task + triggerManager.stop(); + jobManager.stop(); + taskManager.stop(); + taskPositionManager.stop(); + this.db.close(); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/PackProxyMessage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/PackProxyMessage.java new file mode 100644 index 00000000..6a9fa7e5 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/PackProxyMessage.java @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.message; + +import org.apache.commons.lang3.tuple.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.atomic.AtomicLong; + +/** + * Handle List of BusMessage, which belong to the same tid. + */ +public class PackProxyMessage { + + private static final Logger LOGGER = LoggerFactory.getLogger(PackProxyMessage.class); + + private final String tid; + + private int currentSize; + + private final int maxPackSize; + + private final int maxQueueNumber; + // ms + private final int cacheTimeout; + + // tid -> list of proxyMessage + private final LinkedBlockingQueue messageQueue; + + private volatile long currentCacheTime = System.currentTimeMillis(); + private final AtomicLong queueSize = new AtomicLong(0); + + /** + * Init PackBusMessage + * + * @param maxPackSize - max pack size for one bid + * @param cacheTimeout - cache timeout for one proxy message + * @param tid - tid + */ + public PackProxyMessage(int maxPackSize, int maxQueueNumber, int cacheTimeout, String tid) { + this.maxPackSize = maxPackSize; + this.maxQueueNumber = maxPackSize * 10; + this.cacheTimeout = cacheTimeout; + + // double size of package + this.messageQueue = new LinkedBlockingQueue<>(maxQueueNumber); + this.tid = tid; + } + + /** + * Check whether queue is nearly full + * + * @return true if is nearly full else false. + */ + private boolean queueIsFull() { + return messageQueue.size() >= maxQueueNumber - 1; + } + + /** + * Add proxy message to cache, proxy message should belong to the same tid. + */ + public void addProxyMessage(ProxyMessage message) { + assert tid.equals(message.getTid()); + try { + if (queueIsFull()) { + LOGGER.warn("message queue is greater than {}, stop adding message, maybe proxy get stuck", maxQueueNumber); + } + messageQueue.put(message); + queueSize.addAndGet(message.getBody().length); + } catch (Exception ex) { + LOGGER.error("exception caught", ex); + } +// messageQueue.offer(message); + } + + /** + * check message queue is empty or not + * + * @return + */ + public boolean isEmpty() { + return messageQueue.isEmpty(); + } + + /** + * Fetch batch of proxy message, timeout message or max number of list satisfied. + * + * @return map of message list, key is tid for the batch. + * return null if there are no valid messages. + */ + public Pair> fetchBatch() { + // if queue is nearly full or package size is satisfied or timeout + long currentTime = System.currentTimeMillis(); + + if (queueSize.get() > maxPackSize || queueIsFull() || currentTime - currentCacheTime > cacheTimeout) { + // refresh cache time. + currentCacheTime = currentTime; + + long resultBatchSize = 0; + + List result = new ArrayList<>(); + + while (!messageQueue.isEmpty()) { + // pre check message size + ProxyMessage peekMessage = messageQueue.peek(); + if (peekMessage == null || resultBatchSize + peekMessage.getBody().length > maxPackSize) { + break; + } + + ProxyMessage message = messageQueue.remove(); + if (message != null) { + int bodySize = message.getBody().length; + resultBatchSize += bodySize; + + // decrease queue size. + queueSize.addAndGet(-bodySize); + result.add(message.getBody()); + } + + } + // make sure result is not empty. + if (!result.isEmpty()) { + return Pair.of(tid, result); + } + } + return null; + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java new file mode 100644 index 00000000..b3ba66fc --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.message; + +import com.zmops.zeus.iot.server.transfer.core.api.Message; + +import java.util.Map; + +/** + * Bus message with body, header, bid and tid. + */ +public class ProxyMessage implements Message { + + private static final String DEFAULT_TID = "__"; + + private final byte[] body; + private final Map header; + private final String bid; + private final String tid; + + + public ProxyMessage(byte[] body, Map header) { + this.body = body; + this.header = header; + this.bid = header.get("bid"); + this.tid = header.getOrDefault("tid", DEFAULT_TID); + } + + /** + * Get first line of body list + * + * @return first line of body list + */ + @Override + public byte[] getBody() { + return body; + } + + /** + * Get header of message + * + * @return header + */ + @Override + public Map getHeader() { + return header; + } + + public String getBid() { + return bid; + } + + public String getTid() { + return tid; + } + + public static ProxyMessage parse(Message message) { + return new ProxyMessage(message.getBody(), message.getHeader()); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/ConsoleSink.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/ConsoleSink.java deleted file mode 100644 index 2a999e91..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/ConsoleSink.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.zmops.zeus.iot.server.transfer.core.sink; - - -import com.zmops.zeus.iot.server.transfer.core.api.Message; -import com.zmops.zeus.iot.server.transfer.core.api.Sink; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; - -import java.nio.charset.StandardCharsets; - -/** - * message write to console - */ -public class ConsoleSink implements Sink { - - @Override - public void write(Message message) { - if (message != null) { - System.out.println(new String(message.getBody(), StandardCharsets.UTF_8)); - } - } - - @Override - public void setSourceFile(String sourceFileName) { - - } - - @Override - public void init(JobProfile jobConf) { - - } - - @Override - public void destroy() { - - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java new file mode 100644 index 00000000..0939eb8f --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java @@ -0,0 +1,186 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.sink; + +import com.zmops.zeus.iot.server.transfer.conf.CommonConstants; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import com.zmops.zeus.iot.server.transfer.core.api.Message; +import com.zmops.zeus.iot.server.transfer.core.api.Sink; +import com.zmops.zeus.iot.server.transfer.core.common.AgentThreadFactory; +import com.zmops.zeus.iot.server.transfer.core.message.EndMessage; +import com.zmops.zeus.iot.server.transfer.core.message.PackProxyMessage; +import com.zmops.zeus.iot.server.transfer.core.message.ProxyMessage; +import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; +import org.apache.commons.lang3.tuple.Pair; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.*; + +import static com.zmops.zeus.iot.server.transfer.conf.CommonConstants.*; +import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.*; + + +public class NdjsonSink implements Sink { + + private static final Logger LOGGER = LoggerFactory.getLogger(NdjsonSink.class); + + private SenderManager senderManager; + + private String bid; + private String tid; + private String sourceFile; + private String jobInstanceId; + + private int maxBatchSize; + private int maxBatchTimeoutMs; + private int batchFlushInterval; + private int maxQueueNumber; + + private final ExecutorService executorService = + new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new AgentThreadFactory("ProxySink")); + + private volatile boolean shutdown = false; + + // key is tid, value is a batch of messages belong to the same tid + private ConcurrentHashMap cache; + + private long dataTime; + + + @Override + public void write(Message message) { + if (message != null && message.getBody().length > 0) { + message.getHeader().put(CommonConstants.PROXY_KEY_BID, bid); + message.getHeader().put(CommonConstants.PROXY_KEY_TID, tid); + if (!(message instanceof EndMessage)) { + + ProxyMessage proxyMessage = ProxyMessage.parse(message); + + // add proxy message to cache. + cache.compute(proxyMessage.getTid(), (s, packProxyMessage) -> { + if (packProxyMessage == null) { + packProxyMessage = new PackProxyMessage(maxBatchSize, maxQueueNumber, maxBatchTimeoutMs, proxyMessage.getTid()); + } + // add message to package proxy + packProxyMessage.addProxyMessage(proxyMessage); + return packProxyMessage; + }); + } + } + } + + @Override + public void setSourceFile(String sourceFileName) { + this.sourceFile = sourceFileName; + } + + /** + * flush cache by batch + * + * @return - thread runner + */ + private Runnable flushCache() { + return () -> { + LOGGER.info("start flush cache thread for {} TDBusSink", bid); + while (!shutdown) { + try { + cache.forEach((s, packProxyMessage) -> { + + Pair> result = packProxyMessage.fetchBatch(); + + if (result != null) { + senderManager.sendBatch(jobInstanceId, bid, result.getKey(), result.getValue(), 0, dataTime); + + LOGGER.info("send bid {} with message size {}, the job id is {}, read file is {}" + + "dataTime is {}", bid, result.getRight().size(), jobInstanceId, sourceFile, dataTime); + } + }); + AgentUtils.silenceSleepInMs(batchFlushInterval); + } catch (Exception ex) { + LOGGER.error("error caught", ex); + } + } + }; + } + + @Override + public void init(JobProfile jobConf) { + maxBatchSize = jobConf.getInt(CommonConstants.PROXY_PACKAGE_MAX_SIZE, CommonConstants.DEFAULT_PROXY_PACKAGE_MAX_SIZE); + maxQueueNumber = jobConf.getInt(CommonConstants.PROXY_TID_QUEUE_MAX_NUMBER, CommonConstants.DEFAULT_PROXY_TID_QUEUE_MAX_NUMBER); + maxBatchTimeoutMs = jobConf.getInt(CommonConstants.PROXY_PACKAGE_MAX_TIMEOUT_MS, CommonConstants.DEFAULT_PROXY_PACKAGE_MAX_TIMEOUT_MS); + + jobInstanceId = jobConf.get(JOB_INSTANCE_ID); + + batchFlushInterval = jobConf.getInt(CommonConstants.PROXY_BATCH_FLUSH_INTERVAL, CommonConstants.DEFAULT_PROXY_BATCH_FLUSH_INTERVAL); + + cache = new ConcurrentHashMap<>(10); + + bid = jobConf.get(PROXY_BID); + dataTime = AgentUtils.timeStrConvertToMillSec(jobConf.get(JOB_DATA_TIME, ""), jobConf.get(JOB_CYCLE_UNIT, "")); + + bid = jobConf.get(PROXY_BID); + tid = jobConf.get(PROXY_TID); + + executorService.execute(flushCache()); + senderManager = new SenderManager(jobConf, bid, sourceFile); + } + + private HashMap parseAttrFromJobProfile(JobProfile jobProfile) { + HashMap attr = new HashMap<>(); + + String additionStr = jobProfile.get(JOB_ADDITION_STR, ""); + if (!additionStr.isEmpty()) { + Map addAttr = AgentUtils.getAdditionAttr(additionStr); + attr.putAll(addAttr); + } + + if (jobProfile.getBoolean(JOB_RETRY, false)) { + // used for online compute filter consume + attr.put(PROXY_OCEANUS_F, PROXY_OCEANUS_BL); + } + attr.put(PROXY_KEY_ID, jobProfile.get(JOB_ID)); + attr.put(PROXY_KEY_AGENT_IP, jobProfile.get(JOB_IP)); + + return attr; + } + + @Override + public void destroy() { + LOGGER.info("destroy sink which sink from source file {}", sourceFile); + while (!sinkFinish()) { + LOGGER.info("job {} wait until cache all flushed to proxy", jobInstanceId); + AgentUtils.silenceSleepInMs(batchFlushInterval); + } + shutdown = true; + executorService.shutdown(); + } + + /** + * check whether all tid messages finished + * + * @return + */ + private boolean sinkFinish() { + return cache.values().stream().allMatch(PackProxyMessage::isEmpty); + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java new file mode 100644 index 00000000..867eab5a --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zmops.zeus.iot.server.transfer.core.sink; + + +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import com.zmops.zeus.iot.server.transfer.core.metrics.PluginMetric; +import com.zmops.zeus.iot.server.transfer.core.task.TaskPositionManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.concurrent.TimeUnit; + + +/** + * proxy client + */ +public class SenderManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(SenderManager.class); + + private final TaskPositionManager taskPositionManager; + private final String sourceFilePath; + private final PluginMetric metric = new PluginMetric(); + + public SenderManager(JobProfile jobConf, String bid, String sourceFilePath) { + taskPositionManager = TaskPositionManager.getTaskPositionManager(); + this.sourceFilePath = sourceFilePath; + } + + /** + * Send message to proxy by batch, use message cache. + * + * @param bid - bid + * @param tid - tid + * @param bodyList - body list + * @param retry - retry time + */ + public void sendBatch(String jobId, String bid, String tid, List bodyList, int retry, long dataTime) { + try { + + metric.sendSuccessNum.incr(bodyList.size()); + taskPositionManager.updateFileSinkPosition(jobId, sourceFilePath, bodyList.size()); + + System.out.println(metric.sendSuccessNum.snapshot()); + + } catch (Exception exception) { + LOGGER.error("Exception caught", exception); + // retry time + try { + TimeUnit.SECONDS.sleep(1); + sendBatch(jobId, bid, tid, bodyList, retry + 1, dataTime); + } catch (Exception ignored) { + // ignore it. + } + } + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java index 994bcb11..0313c363 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java @@ -22,7 +22,7 @@ import com.zmops.zeus.iot.server.transfer.core.api.Source; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.core.source.reader.TextFileReader; -import com.zmops.zeus.iot.server.transfer.core.utils.PluginUtils; +import com.zmops.zeus.iot.server.transfer.core.utils.FileSearchUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,13 +48,11 @@ public class TextFileSource implements Source { @Override public List split(JobProfile jobConf) { - Collection allFiles = PluginUtils.findSuitFiles(jobConf); - + Collection allFiles = FileSearchUtils.findSuitFiles(jobConf); List result = new ArrayList<>(); String filterPattern = jobConf.get(JOB_LINE_FILTER_PATTERN, DEFAULT_JOB_LINE_FILTER); - for (File file : allFiles) { int seekPosition = jobConf.getInt(file.getAbsolutePath() + POSITION_SUFFIX, 0); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java index 43828fbe..04ec21ef 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java @@ -44,18 +44,26 @@ import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.DEFAULT_JOB_FILE_MAX_WAIT; import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_FILE_MAX_WAIT; +/** + * ndjson 文件读取 + * + * @editor nantian + */ public class TextFileReader implements Reader { - private static final Logger LOGGER = LoggerFactory.getLogger(TextFileReader.class); - public static final int NEVER_STOP_SIGN = -1; + private static final Logger LOGGER = LoggerFactory.getLogger(TextFileReader.class); + + public static final int NEVER_STOP_SIGN = -1; + + private final File file; + private final int position; + private final String md5; - private final File file; - private final int position; - private final String md5; - private Iterator iterator; - private Stream stream; - private long timeout; - private long lastTime = 0; + private Iterator iterator; + private Stream stream; + + private long timeout; + private long lastTime = 0; private final PluginMetric textFileMetric; private final List validators = new ArrayList<>(); @@ -142,7 +150,9 @@ public void init(JobProfile jobConf) { if (StringUtils.isNotBlank(this.md5) && !this.md5.equals(md5)) { LOGGER.warn("md5 is differ from origin, origin: {}, new {}", this.md5, md5); } + LOGGER.info("file name for task is {}, md5 is {}", file, md5); + stream = Files.newBufferedReader(file.toPath()).lines().skip(position); iterator = stream.iterator(); } catch (Exception ex) { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateTransferException.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateTransferException.java deleted file mode 100644 index 836eb0e9..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateTransferException.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.zmops.zeus.iot.server.transfer.core.state; - - -public class StateTransferException extends RuntimeException { - - public StateTransferException(State begin, State end) { - super(String.format("%s -> %s not allowed", begin, end)); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java index 3e2c2c3b..7f2a9be8 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java @@ -18,12 +18,12 @@ package com.zmops.zeus.iot.server.transfer.core.task; -import com.zmops.zeus.iot.server.transfer.conf.AgentConfiguration; -import com.zmops.zeus.iot.server.transfer.conf.AgentConstants; +import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; +import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; import com.zmops.zeus.iot.server.transfer.core.common.AgentThreadFactory; import com.zmops.zeus.iot.server.transfer.core.job.JobManager; -import com.zmops.zeus.iot.server.transfer.core.manager.AgentManager; +import com.zmops.zeus.iot.server.transfer.core.manager.TransferManager; import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; import org.slf4j.Logger; @@ -41,7 +41,7 @@ public class TaskManager extends AbstractDaemon { // task thread pool; private final ThreadPoolExecutor runningPool; - private final AgentManager agentManager; + private final TransferManager transferManager; private final TaskMetrics taskMetrics; private final ConcurrentHashMap tasks; @@ -55,10 +55,10 @@ public class TaskManager extends AbstractDaemon { /** * Init task manager. * - * @param agentManager - agent manager + * @param transferManager - agent manager */ - public TaskManager(AgentManager agentManager) { - this.agentManager = agentManager; + public TaskManager(TransferManager transferManager) { + this.transferManager = transferManager; this.runningPool = new ThreadPoolExecutor( 0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, @@ -69,14 +69,14 @@ public TaskManager(AgentManager agentManager) { taskMetrics = TaskMetrics.create(); tasks = new ConcurrentHashMap<>(); - AgentConfiguration conf = AgentConfiguration.getAgentConf(); + TransferConfiguration conf = TransferConfiguration.getAgentConf(); - retryTasks = new LinkedBlockingQueue<>(conf.getInt(AgentConstants.TASK_RETRY_MAX_CAPACITY, AgentConstants.DEFAULT_TASK_RETRY_MAX_CAPACITY)); + retryTasks = new LinkedBlockingQueue<>(conf.getInt(TransferConstants.TASK_RETRY_MAX_CAPACITY, TransferConstants.DEFAULT_TASK_RETRY_MAX_CAPACITY)); - monitorInterval = conf.getInt(AgentConstants.TASK_MONITOR_INTERVAL, AgentConstants.DEFAULT_TASK_MONITOR_INTERVAL); - taskRetryMaxTime = conf.getInt(AgentConstants.TASK_RETRY_SUBMIT_WAIT_SECONDS, AgentConstants.DEFAULT_TASK_RETRY_SUBMIT_WAIT_SECONDS); - taskMaxCapacity = conf.getInt(AgentConstants.TASK_RETRY_MAX_CAPACITY, AgentConstants.DEFAULT_TASK_RETRY_MAX_CAPACITY); - waitTime = conf.getLong(AgentConstants.THREAD_POOL_AWAIT_TIME, AgentConstants.DEFAULT_THREAD_POOL_AWAIT_TIME); + monitorInterval = conf.getInt(TransferConstants.TASK_MONITOR_INTERVAL, TransferConstants.DEFAULT_TASK_MONITOR_INTERVAL); + taskRetryMaxTime = conf.getInt(TransferConstants.TASK_RETRY_SUBMIT_WAIT_SECONDS, TransferConstants.DEFAULT_TASK_RETRY_SUBMIT_WAIT_SECONDS); + taskMaxCapacity = conf.getInt(TransferConstants.TASK_RETRY_MAX_CAPACITY, TransferConstants.DEFAULT_TASK_RETRY_MAX_CAPACITY); + waitTime = conf.getLong(TransferConstants.THREAD_POOL_AWAIT_TIME, TransferConstants.DEFAULT_THREAD_POOL_AWAIT_TIME); } /** @@ -98,7 +98,7 @@ public TaskWrapper getTaskWrapper(String taskId) { * @param task - task */ public void submitTask(Task task) { - TaskWrapper taskWrapper = new TaskWrapper(agentManager, task); + TaskWrapper taskWrapper = new TaskWrapper(transferManager, task); submitTask(taskWrapper); } @@ -133,8 +133,7 @@ private boolean addRetryTask(TaskWrapper wrapper) { try { boolean success = retryTasks.offer(wrapper, taskRetryMaxTime, TimeUnit.SECONDS); if (!success) { - LOGGER.error("cannot submit to retry queue, max {}, current {}", taskMaxCapacity, - retryTasks.size()); + LOGGER.error("cannot submit to retry queue, max {}, current {}", taskMaxCapacity, retryTasks.size()); } else { taskMetrics.retryingTasks.incr(); } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java index 1ac517db..11651755 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java @@ -21,7 +21,7 @@ import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; -import com.zmops.zeus.iot.server.transfer.core.manager.AgentManager; +import com.zmops.zeus.iot.server.transfer.core.manager.TransferManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,32 +38,32 @@ public class TaskPositionManager extends AbstractDaemon { private static final Logger LOGGER = LoggerFactory.getLogger(TaskPositionManager.class); - public static final int DEFAULT_FLUSH_TIMEOUT = 30; + public static final int DEFAULT_FLUSH_TIMEOUT = 3; - private final AgentManager agentManager; - private final JobProfileDb jobConfDb; + private final TransferManager transferManager; + private final JobProfileDb jobConfDb; private final ConcurrentHashMap> jobTaskPositionMap; private static volatile TaskPositionManager taskPositionManager = null; - private TaskPositionManager(AgentManager agentManager) { - this.agentManager = agentManager; - this.jobConfDb = agentManager.getJobManager().getJobConfDb(); + private TaskPositionManager(TransferManager transferManager) { + this.transferManager = transferManager; + this.jobConfDb = transferManager.getJobManager().getJobConfDb(); this.jobTaskPositionMap = new ConcurrentHashMap<>(); } /** * task position manager singleton, can only generated by agent manager * - * @param agentManager + * @param transferManager * @return */ - public static TaskPositionManager getTaskPositionManager(AgentManager agentManager) { + public static TaskPositionManager getTaskPositionManager(TransferManager transferManager) { if (taskPositionManager == null) { synchronized (TaskPositionManager.class) { if (taskPositionManager == null) { - taskPositionManager = new TaskPositionManager(agentManager); + taskPositionManager = new TaskPositionManager(transferManager); } } } @@ -87,6 +87,11 @@ public void start() throws Exception { submitWorker(taskPositionFlushThread()); } + /** + * 定时存储到本地DB + * + * @return + */ private Runnable taskPositionFlushThread() { return () -> { while (isRunnable()) { @@ -110,10 +115,12 @@ private Runnable taskPositionFlushThread() { }; } - private void flushJobProfile(String jobId, JobProfile jobProfile) { jobTaskPositionMap.get(jobId).forEach( - (fileName, position) -> jobProfile.setLong(fileName + POSITION_SUFFIX, position) + (fileName, position) -> { + LOGGER.info(" ==========> 写入本地存储行号:{}", position); + jobProfile.setLong(fileName + POSITION_SUFFIX, position); + } ); if (jobConfDb.checkJobfinished(jobProfile)) { LOGGER.info("Cannot update job profile {}, delete memory job in jobTaskPosition", jobId); @@ -132,17 +139,30 @@ public void stop() throws Exception { waitForTerminate(); } + /** + * 更新 文件读取位置 + * + * @param jobInstanceId 任务实例ID + * @param sourceFilePath 源文件路径 + * @param size position + */ public void updateFileSinkPosition(String jobInstanceId, String sourceFilePath, long size) { ConcurrentHashMap filePositionTemp = new ConcurrentHashMap<>(); - ConcurrentHashMap filePosition = jobTaskPositionMap.putIfAbsent(jobInstanceId, filePositionTemp); + + ConcurrentHashMap filePosition = jobTaskPositionMap.putIfAbsent(jobInstanceId, filePositionTemp); + + long beforePosition; + if (filePosition == null) { filePosition = filePositionTemp; + beforePosition = jobConfDb.getJobProfile(jobInstanceId).getLong(sourceFilePath + POSITION_SUFFIX, 0); + } else { + beforePosition = filePosition.getOrDefault(sourceFilePath, 1L); } - Long beforePosition = filePosition.getOrDefault(sourceFilePath, 1L); + filePosition.put(sourceFilePath, beforePosition + size); } - public ConcurrentHashMap getTaskPositionMap(String jobId) { return jobTaskPositionMap.get(jobId); } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java index 993df5f6..c2e1194f 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java @@ -18,11 +18,11 @@ package com.zmops.zeus.iot.server.transfer.core.task; -import com.zmops.zeus.iot.server.transfer.conf.AgentConfiguration; -import com.zmops.zeus.iot.server.transfer.conf.AgentConstants; +import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; +import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.core.api.Message; import com.zmops.zeus.iot.server.transfer.core.common.AgentThreadFactory; -import com.zmops.zeus.iot.server.transfer.core.manager.AgentManager; +import com.zmops.zeus.iot.server.transfer.core.manager.TransferManager; import com.zmops.zeus.iot.server.transfer.core.message.EndMessage; import com.zmops.zeus.iot.server.transfer.core.state.AbstractStateWrapper; import com.zmops.zeus.iot.server.transfer.core.state.State; @@ -52,16 +52,16 @@ public class TaskWrapper extends AbstractStateWrapper { private ExecutorService executorService; - public TaskWrapper(AgentManager manager, Task task) { + public TaskWrapper(TransferManager manager, Task task) { super(); this.taskManager = manager.getTaskManager(); this.task = task; - AgentConfiguration conf = AgentConfiguration.getAgentConf(); + TransferConfiguration conf = TransferConfiguration.getAgentConf(); - maxRetryTime = conf.getInt(AgentConstants.TASK_MAX_RETRY_TIME, AgentConstants.DEFAULT_TASK_MAX_RETRY_TIME); - pushMaxWaitTime = conf.getInt(AgentConstants.TASK_PUSH_MAX_SECOND, AgentConstants.DEFAULT_TASK_PUSH_MAX_SECOND); - pullMaxWaitTime = conf.getInt(AgentConstants.TASK_PULL_MAX_SECOND, AgentConstants.DEFAULT_TASK_PULL_MAX_SECOND); + maxRetryTime = conf.getInt(TransferConstants.TASK_MAX_RETRY_TIME, TransferConstants.DEFAULT_TASK_MAX_RETRY_TIME); + pushMaxWaitTime = conf.getInt(TransferConstants.TASK_PUSH_MAX_SECOND, TransferConstants.DEFAULT_TASK_PUSH_MAX_SECOND); + pullMaxWaitTime = conf.getInt(TransferConstants.TASK_PULL_MAX_SECOND, TransferConstants.DEFAULT_TASK_PULL_MAX_SECOND); if (executorService == null) { executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java index 31f1ff98..9be6c191 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java @@ -17,13 +17,13 @@ package com.zmops.zeus.iot.server.transfer.core.trigger; -import com.zmops.zeus.iot.server.transfer.conf.AgentConstants; +import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.conf.JobConstants; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; import com.zmops.zeus.iot.server.transfer.core.api.Trigger; import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; -import com.zmops.zeus.iot.server.transfer.core.utils.PluginUtils; +import com.zmops.zeus.iot.server.transfer.core.utils.FileSearchUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -110,18 +110,22 @@ private void registerAllSubDir(PathPattern entity, List tmpWatchers) throws Exception { // check regex LOGGER.info("check whether path {} is suitable", path); + if (entity.suitForWatch(path.toString())) { + if (path.toFile().isDirectory()) { WatchKey watchKey = path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE); tmpWatchers.add(watchKey); + try (Stream stream = Files.list(path)) { Iterator iterator = stream.iterator(); while (iterator.hasNext()) { registerAllSubDir(entity, iterator.next().toAbsolutePath(), tmpWatchers); } } + } else { - JobProfile copiedJobProfile = PluginUtils.copyJobProfile(profile, entity.getSuitTime(), path.toFile()); + JobProfile copiedJobProfile = FileSearchUtils.copyJobProfile(profile, entity.getSuitTime(), path.toFile()); LOGGER.info("trigger {} generate job profile to read file {}", getTriggerProfile().getTriggerId(), path.toString()); queue.offer(copiedJobProfile); } @@ -135,11 +139,10 @@ private void registerAllSubDir(PathPattern entity, * @param watchKey - watch key * @param tmpWatchers - watchers */ - private void registerNewDir(PathPattern entity, - WatchKey watchKey, - List tmpWatchers, - List tmpDeletedWatchers) throws Exception { + private void registerNewDir(PathPattern entity, WatchKey watchKey, List tmpWatchers, List tmpDeletedWatchers) throws Exception { + Path parentPath = (Path) watchKey.watchable(); + for (WatchEvent event : watchKey.pollEvents()) { // if watch event is too much, then event would be overflow. if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE) { @@ -179,6 +182,7 @@ private Runnable watchEventHandler() { allWatchers.forEach((pathPattern, watchKeys) -> { List tmpWatchers = new ArrayList<>(); List tmpDeletedWatchers = new ArrayList<>(); + pathPattern.cleanup(); try { for (WatchKey watchKey : watchKeys) { @@ -222,6 +226,7 @@ public void register(String pathPattern, String offset) throws IOException { private void innerRegister(String pathPattern, PathPattern entity) throws IOException { List tmpKeyList = new ArrayList<>(); List keyList = allWatchers.putIfAbsent(entity, tmpKeyList); + if (keyList == null) { Path rootPath = Paths.get(entity.getRootDir()); LOGGER.info("watch root path is {}", rootPath); @@ -236,8 +241,7 @@ public void unregister(String pathPattern) { PathPattern entity = new PathPattern(pathPattern); Collection allKeys = allWatchers.remove(entity); if (allKeys != null) { - LOGGER.info("unregister pattern {}, total size of path {}", pathPattern, - allKeys.size()); + LOGGER.info("unregister pattern {}, total size of path {}", pathPattern, allKeys.size()); for (WatchKey key : allKeys) { key.cancel(); } @@ -251,7 +255,7 @@ ConcurrentHashMap> getAllWatchers() { @Override public void init(TriggerProfile profile) throws IOException { initWatchService(); - interval = profile.getInt(AgentConstants.TRIGGER_CHECK_INTERVAL, AgentConstants.DEFAULT_TRIGGER_CHECK_INTERVAL); + interval = profile.getInt(TransferConstants.TRIGGER_CHECK_INTERVAL, TransferConstants.DEFAULT_TRIGGER_CHECK_INTERVAL); this.profile = profile; if (this.profile.hasKey(JobConstants.JOB_DIR_FILTER_PATTERN)) { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java index ca0cd4a3..b479d5e2 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java @@ -23,7 +23,7 @@ import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; import com.zmops.zeus.iot.server.transfer.core.db.TriggerProfileDb; import com.zmops.zeus.iot.server.transfer.core.job.JobWrapper; -import com.zmops.zeus.iot.server.transfer.core.manager.AgentManager; +import com.zmops.zeus.iot.server.transfer.core.manager.TransferManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,8 +33,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; -import static com.zmops.zeus.iot.server.transfer.conf.AgentConstants.DEFAULT_TRIGGER_MAX_RUNNING_NUM; -import static com.zmops.zeus.iot.server.transfer.conf.AgentConstants.TRIGGER_MAX_RUNNING_NUM; +import static com.zmops.zeus.iot.server.transfer.conf.TransferConstants.DEFAULT_TRIGGER_MAX_RUNNING_NUM; +import static com.zmops.zeus.iot.server.transfer.conf.TransferConstants.TRIGGER_MAX_RUNNING_NUM; import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_ID; import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.TRIGGER_ONLY_ONE_JOB; @@ -43,27 +43,29 @@ */ public class TriggerManager extends AbstractDaemon { - private static final Logger LOGGER = LoggerFactory.getLogger(TriggerManager.class); - public static final int JOB_CHECK_INTERVAL = 1; + private static final Logger LOGGER = LoggerFactory.getLogger(TriggerManager.class); + + public static final int JOB_CHECK_INTERVAL = 1; + + private final TransferManager manager; + private final TriggerProfileDb triggerProfileDB; - private final AgentManager manager; - private final TriggerProfileDb triggerProfileDB; private final ConcurrentHashMap triggerMap; private final ConcurrentHashMap> triggerJobMap; - private final AgentConfiguration conf; - private final int triggerFetchInterval; private final int maxRunningNum; - public TriggerManager(AgentManager manager, TriggerProfileDb triggerProfileDb) { - this.conf = AgentConfiguration.getAgentConf(); + public TriggerManager(TransferManager manager, TriggerProfileDb triggerProfileDb) { + + TransferConfiguration conf = TransferConfiguration.getAgentConf(); + this.manager = manager; this.triggerProfileDB = triggerProfileDb; this.triggerMap = new ConcurrentHashMap<>(); this.triggerJobMap = new ConcurrentHashMap<>(); - this.triggerFetchInterval = conf.getInt(AgentConstants.TRIGGER_FETCH_INTERVAL, AgentConstants.DEFAULT_TRIGGER_FETCH_INTERVAL); + this.triggerFetchInterval = conf.getInt(TransferConstants.TRIGGER_FETCH_INTERVAL, TransferConstants.DEFAULT_TRIGGER_FETCH_INTERVAL); this.maxRunningNum = conf.getInt(TRIGGER_MAX_RUNNING_NUM, DEFAULT_TRIGGER_MAX_RUNNING_NUM); } @@ -74,16 +76,18 @@ public TriggerManager(AgentManager manager, TriggerProfileDb triggerProfileDb) { */ public boolean addTrigger(TriggerProfile triggerProfile) { try { - Class triggerClass = Class.forName(triggerProfile.get(JobConstants.JOB_TRIGGER)); - Trigger trigger = (Trigger) triggerClass.newInstance(); - String triggerId = triggerProfile.get(JOB_ID); + Trigger trigger = new DirectoryTrigger(); + String triggerId = triggerProfile.get(JOB_ID); + if (triggerMap.containsKey(triggerId)) { deleteTrigger(triggerId); LOGGER.warn("trigger {} is running, stop it", triggerId); } + triggerMap.put(triggerId, trigger); trigger.init(triggerProfile); trigger.run(); + } catch (Exception ex) { LOGGER.error("exception caught", ex); return false; @@ -114,11 +118,14 @@ private Runnable jobFetchThread() { try { triggerMap.forEach((s, trigger) -> { JobProfile profile = trigger.fetchJobProfile(); + if (profile != null) { TriggerProfile triggerProfile = trigger.getTriggerProfile(); + if (triggerProfile.getBoolean(TRIGGER_ONLY_ONE_JOB, false)) { deleteRelatedJobs(triggerProfile.getTriggerId()); } + manager.getJobManager().submitJobProfile(profile); addToTriggerMap(profile.get(JOB_ID), profile); } @@ -139,8 +146,8 @@ private Runnable jobFetchThread() { */ private void deleteRelatedJobs(String triggerId) { LOGGER.info("start to delete related jobs in triggerId {}", triggerId); - ConcurrentHashMap jobProfiles = - triggerJobMap.get(triggerId); + ConcurrentHashMap jobProfiles = triggerJobMap.get(triggerId); + if (jobProfiles != null) { LOGGER.info("trigger can only run one job, stop the others {}", jobProfiles.keySet()); jobProfiles.keySet().forEach(this::deleteJob); @@ -181,13 +188,13 @@ private Runnable jobCheckThread() { * @param profile */ private void addToTriggerMap(String triggerId, JobProfile profile) { - ConcurrentHashMap tmpList = - new ConcurrentHashMap<>(); - ConcurrentHashMap jobWrappers = - triggerJobMap.putIfAbsent(triggerId, tmpList); + ConcurrentHashMap tmpList = new ConcurrentHashMap<>(); + ConcurrentHashMap jobWrappers = triggerJobMap.putIfAbsent(triggerId, tmpList); + if (jobWrappers == null) { jobWrappers = tmpList; } + jobWrappers.putIfAbsent(profile.getInstanceId(), profile); } @@ -199,6 +206,7 @@ private void addToTriggerMap(String triggerId, JobProfile profile) { public boolean deleteTrigger(String triggerId) { LOGGER.info("delete trigger {}", triggerId); Trigger trigger = triggerMap.remove(triggerId); + if (trigger != null) { deleteRelatedJobs(triggerId); trigger.destroy(); @@ -217,6 +225,7 @@ public boolean deleteTrigger(String triggerId) { private void initTriggers() throws Exception { // fetch all triggers from db List profileList = triggerProfileDB.getTriggers(); + for (TriggerProfile profile : profileList) { addTrigger(profile); } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/ByteUtil.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/ByteUtil.java deleted file mode 100644 index a429eee4..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/ByteUtil.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package com.zmops.zeus.iot.server.transfer.core.utils; - -import java.util.ArrayList; -import java.util.List; - -public class ByteUtil { - /** - * Splits the source array into multiple array segments using the given separator, up to a - * maximum of count items. This will naturally produce copied byte arrays for each of the split - * segments. To identify the split ranges without the array copies, see {@link - * ByteUtil#splitRanges(byte[], byte[])}. - * - * @param source - * @param separator - * @return - */ - public static byte[][] split(byte[] source, byte[] separator) { - return split(source, separator, -1); - } - - /** - * Splits the source array into multiple array segments using the given separator, up to a - * maximum of count items. This will naturally produce copied byte arrays for each of the split - * segments. To identify the split ranges without the array copies, see {@link - * ByteUtil#splitRanges(byte[], byte[])}. - * - * @param source - * @param separator - * @return - */ - public static byte[][] split(byte[] source, byte[] separator, int limit) { - List segments = splitRanges(source, separator, limit); - - byte[][] splits = new byte[segments.size()][]; - for (int i = 0; i < segments.size(); i++) { - Range r = segments.get(i); - byte[] tmp = new byte[r.length()]; - if (tmp.length > 0) { - System.arraycopy(source, r.start(), tmp, 0, r.length()); - } - splits[i] = tmp; - } - return splits; - } - - /** - * Returns a list of ranges identifying [start, end) -- closed, open -- positions within the - * source byte array that would be split using the separator byte array. - */ - public static List splitRanges(byte[] source, byte[] separator) { - return splitRanges(source, separator, -1); - } - - /** - * Returns a list of ranges identifying [start, end) -- closed, open -- positions within the - * source byte array that would be split using the separator byte array. - * - * @param source the source data - * @param separator the separator pattern to look for - * @param limit the maximum number of splits to identify in the source - */ - public static List splitRanges(byte[] source, byte[] separator, int limit) { - List segments = new ArrayList(); - int start = 0; - itersource: - for (int i = 0; i < source.length; i++) { - for (int j = 0; j < separator.length; j++) { - if (source[i + j] != separator[j]) { - continue itersource; - } - } - // all separator elements matched - if (limit > 0 && segments.size() >= (limit - 1)) { - // everything else goes in one final segment - break; - } - - segments.add(new Range(start, i)); - start = i + separator.length; - // i will be incremented again in outer for loop - i += separator.length - 1; - } - // add in remaining to a final range - if (start <= source.length) { - segments.add(new Range(start, source.length)); - } - return segments; - } - - /** - * Returns a single byte array containing all of the individual component arrays separated by - * the separator array. - * - * @param separator - * @param components - * @return - */ - public static byte[] join(byte[] separator, byte[]... components) { - if (components == null || components.length == 0) { - return new byte[0]; - } - - int finalSize = 0; - if (separator != null) { - finalSize = separator.length * (components.length - 1); - } - for (byte[] comp : components) { - finalSize += comp.length; - } - - byte[] buf = new byte[finalSize]; - int offset = 0; - for (int i = 0; i < components.length; i++) { - System.arraycopy(components[i], 0, buf, offset, components[i].length); - offset += components[i].length; - if (i < (components.length - 1) && separator != null && separator.length > 0) { - System.arraycopy(separator, 0, buf, offset, separator.length); - offset += separator.length; - } - } - return buf; - } - - /** - * Returns the index (start position) of the first occurrence of the specified {@code target} - * within {@code array} starting at {@code fromIndex} , or {@code -1} if there is no such - * occurrence. - * - *

- * Returns the lowest index {@code k} such that {@code k >= fromIndex} and {@code - * java.util.Arrays.copyOfRange(array, k, k + target.length)} contains exactly the same elements - * as {@code target}. - * - * @param array the array to search for the sequence {@code target} - * @param target the array to search for as a sub-sequence of {@code array} - * @param fromIndex the index to start the search from in {@code array} - */ - public static int indexOf(byte[] array, byte[] target, int fromIndex) { - - if (array == null || target == null) { - return -1; - } - - // Target cannot be beyond array boundaries - if (fromIndex < 0 || (fromIndex > (array.length - target.length))) { - return -1; - } - - // Empty is assumed to be at the fromIndex of any non-null array (after boundary check) - if (target.length == 0) { - return fromIndex; - } - - firstbyte: - for (int i = fromIndex; i < array.length - target.length + 1; i++) { - for (int j = 0; j < target.length; j++) { - if (array[i + j] != target[j]) { - continue firstbyte; - } - } - return i; - } - return -1; - } - - /** - * Returns a copy of the source byte array, starting at offset for the given length. If the - * offset + length is out of bounds for the array, returns null. - * - * @param source - * @param offset - * @param length - * @return - */ - public static byte[] safeCopy(byte[] source, int offset, int length) { - if (length < 0 || source.length < offset + length) { - return null; - } - byte[] copy = new byte[length]; - System.arraycopy(source, offset, copy, 0, length); - return copy; - } - - public static class Range { - - private int startIdx; - private int endIdx; - - /** - * Defines a range from start index (inclusive) to end index (exclusive). - * - * @param start Starting index position - * @param end Ending index position (exclusive) - */ - public Range(int start, int end) { - if (start < 0 || end < start) { - throw new IllegalArgumentException( - "Invalid range, required that: 0 <= start <= end; start=" + start + ", end=" + end); - } - - this.startIdx = start; - this.endIdx = end; - } - - public int start() { - return startIdx; - } - - public int end() { - return endIdx; - } - - public int length() { - return endIdx - startIdx; - } - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/PluginUtils.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/FileSearchUtils.java similarity index 65% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/PluginUtils.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/FileSearchUtils.java index 63098bed..02895137 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/PluginUtils.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/FileSearchUtils.java @@ -17,27 +17,21 @@ package com.zmops.zeus.iot.server.transfer.core.utils; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; import com.zmops.zeus.iot.server.transfer.conf.JobConstants; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; import com.zmops.zeus.iot.server.transfer.core.trigger.PathPattern; import lombok.extern.slf4j.Slf4j; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; -import java.net.InetAddress; -import java.net.NetworkInterface; import java.util.ArrayList; import java.util.Collection; -import java.util.Enumeration; -import java.util.List; -import static com.zmops.zeus.iot.server.transfer.conf.CommonConstants.*; +import static com.zmops.zeus.iot.server.transfer.conf.CommonConstants.DEFAULT_FILE_MAX_NUM; +import static com.zmops.zeus.iot.server.transfer.conf.CommonConstants.FILE_MAX_NUM; import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_DIR_FILTER_PATTERN; import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_RETRY_TIME; @@ -45,18 +39,9 @@ * Utils for plugin package. */ @Slf4j -public class PluginUtils { - - - private static final Logger LOGGER = LoggerFactory.getLogger(PluginUtils.class); - - public static String toJsonStr(Object obj) { - GsonBuilder gsonBuilder = new GsonBuilder(); - gsonBuilder.setPrettyPrinting(); - Gson gson = gsonBuilder.create(); - return gson.toJson(obj); - } +public class FileSearchUtils { + private static final Logger LOGGER = LoggerFactory.getLogger(FileSearchUtils.class); public static Collection findSuitFiles(JobProfile jobConf) { String dirPattern = jobConf.get(JOB_DIR_FILTER_PATTERN); @@ -90,8 +75,7 @@ public static void updateRetryTime(JobProfile jobConf, PathPattern pattern) { } } - public static JobProfile copyJobProfile(TriggerProfile triggerProfile, String dataTime, - File pendingFile) { + public static JobProfile copyJobProfile(TriggerProfile triggerProfile, String dataTime, File pendingFile) { JobProfile copiedProfile = TriggerProfile.parseJsonStr(triggerProfile.toJsonStr()); String md5 = AgentUtils.getFileMd5(pendingFile); @@ -104,36 +88,4 @@ public static JobProfile copyJobProfile(TriggerProfile triggerProfile, String da return copiedProfile; } - public static List getLocalIpList() { - List allIps = new ArrayList<>(); - try { - String os = System.getProperty(AGENT_OS_NAME).toLowerCase(); - if (os.contains(AGENT_NIX_OS) || os.contains(AGENT_NUX_OS)) { - /* Deal with linux platform. */ - Enumeration nis = NetworkInterface.getNetworkInterfaces(); - while (nis.hasMoreElements()) { - NetworkInterface ni = nis.nextElement(); - addIp(allIps, ni); - } - } else { - /* Deal with windows platform. */ - allIps.add(InetAddress.getLocalHost().getHostAddress()); - } - } catch (Exception e) { - LOGGER.error("get local ip list fail with ex {} ", e); - } - return allIps; - } - - - private static void addIp(List allIps, NetworkInterface ni) { - Enumeration ias = ni.getInetAddresses(); - while (ias.hasMoreElements()) { - InetAddress ia = ias.nextElement(); - if (!ia.isLoopbackAddress() && ia.getHostAddress().contains(AGENT_COLON)) { - allIps.add(ia.getHostAddress()); - } - } - } - } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java index 8b7e0431..d98055c9 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java @@ -1,14 +1,18 @@ package com.zmops.zeus.iot.server.transfer.provider; import com.zmops.zeus.iot.server.library.module.*; -import com.zmops.zeus.iot.server.transfer.core.manager.AgentManager; +import com.zmops.zeus.iot.server.transfer.core.manager.TransferManager; import com.zmops.zeus.iot.server.transfer.module.ServerTransferModule; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author nantian created at 2021/9/22 16:44 */ public class ServerTransferProvider extends ModuleProvider { + private static final Logger LOGGER = LoggerFactory.getLogger(ServerTransferProvider.class); + private final ServerTransferConfig serverTransferConfig; public ServerTransferProvider() { @@ -33,15 +37,35 @@ public ModuleConfig createConfigBeanIfAbsent() { @Override public void prepare() throws ServiceNotProvidedException, ModuleStartException { - AgentManager manager = new AgentManager(); + } - System.out.println(123); + /** + * Stopping agent gracefully if get killed. + * + * @param manager - agent manager + */ + private static void stopManagerIfKilled(TransferManager manager) { + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + try { + LOGGER.info("stopping agent gracefully"); + manager.stop(); + } catch (Exception ex) { + LOGGER.error("exception while stopping threads", ex); + } + })); } @Override public void start() throws ServiceNotProvidedException, ModuleStartException { - + TransferManager manager = new TransferManager(); + try { + manager.start(); + stopManagerIfKilled(manager); +// manager.join(); + } catch (Exception e) { + e.printStackTrace(); + } } @Override diff --git a/iot-server/server-transfer/src/main/resources/job.json b/iot-server/server-transfer/src/main/resources/job.json new file mode 100644 index 00000000..8030761d --- /dev/null +++ b/iot-server/server-transfer/src/main/resources/job.json @@ -0,0 +1,25 @@ +{ + "job": { + "dir": { + "path": "", + "pattern": "E:\\data\\2.ndjson" + }, + "id": 1, + "thread": { + "running": { + "core": "4" + } + }, + "file": { + "max": { + "wait": -1 + } + }, + "name": "zeus-transfer" + }, + "proxy": { + "bid": "bid10", + "tid": "bid10" + }, + "op": "add" +} \ No newline at end of file From dbced29b862920cdce9d88c79bacf7a10d7ffcaf Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 01:43:09 +0800 Subject: [PATCH 273/763] [feat]: add start notice info --- .../com/zmops/zeus/iot/server/starter/IOTServerStartUp.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerStartUp.java b/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerStartUp.java index 4beecf99..f2f422c7 100644 --- a/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerStartUp.java +++ b/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerStartUp.java @@ -1,13 +1,17 @@ package com.zmops.zeus.iot.server.starter; +import lombok.extern.slf4j.Slf4j; + /** * @author nantian created at 2021/8/13 15:26 *

* 宙斯服务 协议层启动 */ +@Slf4j public class IOTServerStartUp { public static void main(String[] args) { IoTServerBootstrap.start(); + log.info("IoT Server Platform start successfully ..."); } } From 4d0edbdd5b19b7f18cb85a4366e646b920f3c422 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 11:01:46 +0800 Subject: [PATCH 274/763] [feat]: update zeus-transfer module --- .../transfer/conf/AbstractConfiguration.java | 4 +-- .../transfer/conf/TransferConstants.java | 4 +-- .../server/transfer/core/db/JobProfileDb.java | 32 +++++++++++++------ .../transfer/core/filter/DateFormatRegex.java | 6 ++-- .../server/transfer/core/job/JobManager.java | 4 +-- .../core/manager/TransferManager.java | 1 + .../core/message/PackProxyMessage.java | 22 ++----------- .../core/metrics/MetricException.java | 17 ---------- .../core/metrics/MetricsRegister.java | 4 +-- .../server/transfer/core/sink/NdjsonSink.java | 10 +++--- .../transfer/core/sink/SenderManager.java | 4 +++ .../core/source/reader/TextFileReader.java | 6 ++-- .../transfer/core/task/TaskManager.java | 4 +-- .../transfer/core/trigger/TriggerManager.java | 22 ++----------- .../transfer/core/utils/FileSearchUtils.java | 2 +- .../{AgentUtils.java => TransferUtils.java} | 21 ++---------- .../core/validator/PrefixValidator.java | 17 ---------- 17 files changed, 57 insertions(+), 123 deletions(-) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/{AgentUtils.java => TransferUtils.java} (92%) diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java index 65e62030..43cc6774 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java @@ -18,7 +18,7 @@ package com.zmops.zeus.iot.server.transfer.conf; import com.google.gson.*; -import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; +import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; import org.apache.commons.lang3.StringUtils; @@ -82,7 +82,7 @@ private void loadResource(String fileName, boolean isJson) { } catch (Exception ioe) { LOGGER.error("error init {}", fileName, ioe); } finally { - AgentUtils.finallyClose(reader); + TransferUtils.finallyClose(reader); } } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java index cfef145a..948a35a6 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java @@ -17,7 +17,7 @@ package com.zmops.zeus.iot.server.transfer.conf; -import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; +import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; public class TransferConstants { @@ -39,7 +39,7 @@ public class TransferConstants { public static final String AGENT_UNIQ_ID = "agent.uniq.id"; // default use local ip as uniq id for agent. - public static final String DEFAULT_AGENT_UNIQ_ID = AgentUtils.getLocalIp(); + public static final String DEFAULT_AGENT_UNIQ_ID = TransferUtils.getLocalIp(); public static final String AGENT_DB_INSTANCE_NAME = "agent.db.instance.name"; public static final String DEFAULT_AGENT_DB_INSTANCE_NAME = "agent"; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java index 053d5df1..d35332da 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java @@ -32,7 +32,7 @@ */ public class JobProfileDb { private static final Logger LOGGER = LoggerFactory.getLogger(JobProfileDb.class); - private final Db db; + private final Db db; public JobProfileDb(Db db) { this.db = db; @@ -40,6 +40,7 @@ public JobProfileDb(Db db) { /** * get job which in accepted state + * * @return null or job conf */ public JobProfile getAcceptedJob() { @@ -52,7 +53,8 @@ public List getAcceptedJobs() { /** * update job state and search it by key name - * @param jobInstanceId - job key name + * + * @param jobInstanceId - job key name * @param stateSearchKey - job state */ public void updateJobState(String jobInstanceId, StateSearchKey stateSearchKey) { @@ -65,6 +67,7 @@ public void updateJobState(String jobInstanceId, StateSearchKey stateSearchKey) /** * store job profile + * * @param jobProfile - job profile */ public void storeJobFirstTime(JobProfile jobProfile) { @@ -81,11 +84,12 @@ public void storeJobFirstTime(JobProfile jobProfile) { /** * update job profile + * * @param jobProfile */ public void updateJobProfile(JobProfile jobProfile) { - String instanceId = jobProfile.getInstanceId(); - KeyValueEntity entity = db.get(instanceId); + String instanceId = jobProfile.getInstanceId(); + KeyValueEntity entity = db.get(instanceId); if (entity == null) { LOGGER.warn("job profile {} doesn't exist, update job profile fail {}", instanceId, jobProfile.toJsonStr()); return; @@ -96,6 +100,7 @@ public void updateJobProfile(JobProfile jobProfile) { /** * check whether job is finished, note that non-exist job is regarded as finished. + * * @param jobProfile * @return */ @@ -123,17 +128,21 @@ public JobProfile getJobProfile(String jobId) { public void removeExpireJobs(long expireTime) { // remove finished tasks List successEntityList = db.search(StateSearchKey.SUCCESS); - List failedEntityList = db.search(StateSearchKey.FAILED); + List failedEntityList = db.search(StateSearchKey.FAILED); + List entityList = new ArrayList<>(successEntityList); + entityList.addAll(failedEntityList); + for (KeyValueEntity entity : entityList) { if (entity.getKey().startsWith(JobConstants.JOB_ID_PREFIX)) { JobProfile profile = entity.getAsJobProfile(); - long storeTime = profile.getLong(JobConstants.JOB_STORE_TIME, 0); + + long storeTime = profile.getLong(JobConstants.JOB_STORE_TIME, 0); long currentTime = System.currentTimeMillis(); + if (storeTime == 0 || currentTime - storeTime > expireTime) { - LOGGER.info("delete job {} because of timeout store time: {}, expire time: {}", - entity.getKey(), storeTime, expireTime); + LOGGER.info("delete job {} because of timeout store time: {}, expire time: {}", entity.getKey(), storeTime, expireTime); deleteJob(entity.getKey()); } } @@ -142,6 +151,7 @@ public void removeExpireJobs(long expireTime) { /** * get job conf by state + * * @param stateSearchKey - state index for searching. * @return */ @@ -156,6 +166,7 @@ public JobProfile getJob(StateSearchKey stateSearchKey) { /** * get job reading specific file + * * @param fileName * @return */ @@ -169,12 +180,13 @@ public JobProfile getJob(String fileName) { /** * get list of job profiles. + * * @param stateSearchKey - state search key. * @return - list of job profile. */ public List getJobs(StateSearchKey stateSearchKey) { - List entityList = db.search(stateSearchKey); - List profileList = new ArrayList<>(); + List entityList = db.search(stateSearchKey); + List profileList = new ArrayList<>(); for (KeyValueEntity entity : entityList) { if (entity.getKey().startsWith(JobConstants.JOB_ID_PREFIX)) { profileList.add(entity.getAsJobProfile()); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java index 9209b19a..ec24e3fe 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java @@ -20,7 +20,7 @@ import com.zmops.zeus.iot.server.transfer.core.api.Filter; -import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; +import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -70,7 +70,7 @@ public static DateFormatRegex ofRegex(String regex) { @Override public boolean match() { // TODO: check with more regex - return AgentUtils.regexMatch(file.getAbsolutePath(), formattedRegex); + return TransferUtils.regexMatch(file.getAbsolutePath(), formattedRegex); } public DateFormatRegex withOffset(String timeOffset) { @@ -126,7 +126,7 @@ public void setRegexWithTime(String regex, String time) { } public void setRegexWithCurrentTime(String regex) { - String currentTime = AgentUtils.formatCurrentTimeWithOffset(NORMAL_FORMATTER, dayOffset, hourOffset, minuteOffset); + String currentTime = TransferUtils.formatCurrentTimeWithOffset(NORMAL_FORMATTER, dayOffset, hourOffset, minuteOffset); setRegexWithTime(regex, currentTime); } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java index 1158d05b..a00d0e3a 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java @@ -26,7 +26,7 @@ import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; import com.zmops.zeus.iot.server.transfer.core.db.StateSearchKey; import com.zmops.zeus.iot.server.transfer.core.manager.TransferManager; -import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; +import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -125,7 +125,7 @@ public boolean submitJobProfile(JobProfile profile) { } String jobId = profile.get(JOB_ID); - profile.set(JOB_INSTANCE_ID, AgentUtils.getUniqId(JOB_ID_PREFIX, jobId, index.incrementAndGet())); + profile.set(JOB_INSTANCE_ID, TransferUtils.getUniqId(JOB_ID_PREFIX, jobId, index.incrementAndGet())); LOGGER.info("submit job profile {}", profile.toJsonStr()); getJobConfDb().storeJobFirstTime(profile); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/TransferManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/TransferManager.java index 455d427f..f72e6b81 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/TransferManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/TransferManager.java @@ -104,6 +104,7 @@ public void start() throws Exception { JobProfile profile = JobProfile.parseJsonFile("job.json"); + TriggerProfile triggerProfile = TriggerProfile.parseJobProfile(profile); triggerManager.addTrigger(triggerProfile); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/PackProxyMessage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/PackProxyMessage.java index 6a9fa7e5..3fcd1892 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/PackProxyMessage.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/PackProxyMessage.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.message; import org.apache.commons.lang3.tuple.Pair; @@ -46,8 +29,9 @@ public class PackProxyMessage { // tid -> list of proxyMessage private final LinkedBlockingQueue messageQueue; - private volatile long currentCacheTime = System.currentTimeMillis(); - private final AtomicLong queueSize = new AtomicLong(0); + private volatile long currentCacheTime = System.currentTimeMillis(); + + private final AtomicLong queueSize = new AtomicLong(0); /** * Init PackBusMessage diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricException.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricException.java index 514d1e4d..99262d04 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricException.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricException.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.metrics; public class MetricException extends RuntimeException { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricsRegister.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricsRegister.java index 54ed2155..185b1e3e 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricsRegister.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricsRegister.java @@ -24,7 +24,7 @@ import com.zmops.zeus.iot.server.transfer.core.metrics.gauge.GaugeLong; import com.zmops.zeus.iot.server.transfer.core.metrics.meta.MetricMeta; import com.zmops.zeus.iot.server.transfer.core.metrics.meta.MetricsMeta; -import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; +import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -131,7 +131,7 @@ private static boolean initFieldByType(Object source, Field field) { */ private static List handleFieldAnnotation(Object source) { List result = new ArrayList<>(); - for (Field field : AgentUtils.getDeclaredFieldsIncludingInherited(source.getClass())) { + for (Field field : TransferUtils.getDeclaredFieldsIncludingInherited(source.getClass())) { field.setAccessible(true); for (Annotation fieldAnnotation : field.getAnnotations()) { if (fieldAnnotation instanceof Metric) { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java index 0939eb8f..b258cc0d 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java @@ -25,7 +25,7 @@ import com.zmops.zeus.iot.server.transfer.core.message.EndMessage; import com.zmops.zeus.iot.server.transfer.core.message.PackProxyMessage; import com.zmops.zeus.iot.server.transfer.core.message.ProxyMessage; -import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; +import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; @@ -115,7 +115,7 @@ private Runnable flushCache() { + "dataTime is {}", bid, result.getRight().size(), jobInstanceId, sourceFile, dataTime); } }); - AgentUtils.silenceSleepInMs(batchFlushInterval); + TransferUtils.silenceSleepInMs(batchFlushInterval); } catch (Exception ex) { LOGGER.error("error caught", ex); } @@ -136,7 +136,7 @@ public void init(JobProfile jobConf) { cache = new ConcurrentHashMap<>(10); bid = jobConf.get(PROXY_BID); - dataTime = AgentUtils.timeStrConvertToMillSec(jobConf.get(JOB_DATA_TIME, ""), jobConf.get(JOB_CYCLE_UNIT, "")); + dataTime = TransferUtils.timeStrConvertToMillSec(jobConf.get(JOB_DATA_TIME, ""), jobConf.get(JOB_CYCLE_UNIT, "")); bid = jobConf.get(PROXY_BID); tid = jobConf.get(PROXY_TID); @@ -150,7 +150,7 @@ private HashMap parseAttrFromJobProfile(JobProfile jobProfile) { String additionStr = jobProfile.get(JOB_ADDITION_STR, ""); if (!additionStr.isEmpty()) { - Map addAttr = AgentUtils.getAdditionAttr(additionStr); + Map addAttr = TransferUtils.getAdditionAttr(additionStr); attr.putAll(addAttr); } @@ -169,7 +169,7 @@ public void destroy() { LOGGER.info("destroy sink which sink from source file {}", sourceFile); while (!sinkFinish()) { LOGGER.info("job {} wait until cache all flushed to proxy", jobInstanceId); - AgentUtils.silenceSleepInMs(batchFlushInterval); + TransferUtils.silenceSleepInMs(batchFlushInterval); } shutdown = true; executorService.shutdown(); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java index 867eab5a..8b0bdc82 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java @@ -55,6 +55,10 @@ public SenderManager(JobProfile jobConf, String bid, String sourceFilePath) { public void sendBatch(String jobId, String bid, String tid, List bodyList, int retry, long dataTime) { try { + bodyList.forEach(i -> { + LOGGER.info(new String(i)); + }); + metric.sendSuccessNum.incr(bodyList.size()); taskPositionManager.updateFileSinkPosition(jobId, sourceFilePath, bodyList.size()); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java index 04ec21ef..fad0bd1b 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java @@ -25,7 +25,7 @@ import com.zmops.zeus.iot.server.transfer.core.exception.FileException; import com.zmops.zeus.iot.server.transfer.core.message.DefaultMessage; import com.zmops.zeus.iot.server.transfer.core.metrics.PluginMetric; -import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; +import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; import com.zmops.zeus.iot.server.transfer.core.validator.PatternValidator; import org.apache.commons.lang3.StringUtils; @@ -145,7 +145,7 @@ public void addPatternValidator(String pattern) { public void init(JobProfile jobConf) { try { initReadTimeout(jobConf); - String md5 = AgentUtils.getFileMd5(file); + String md5 = TransferUtils.getFileMd5(file); if (StringUtils.isNotBlank(this.md5) && !this.md5.equals(md5)) { LOGGER.warn("md5 is differ from origin, origin: {}, new {}", this.md5, md5); @@ -171,7 +171,7 @@ private void initReadTimeout(JobProfile jobConf) { @Override public void destroy() { - AgentUtils.finallyClose(stream); + TransferUtils.finallyClose(stream); LOGGER.info("destroy reader with read {} num {}", textFileMetric.tagName.getName(), textFileMetric.readNum.snapshot()); } } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java index 7f2a9be8..386fdd2c 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java @@ -24,7 +24,7 @@ import com.zmops.zeus.iot.server.transfer.core.common.AgentThreadFactory; import com.zmops.zeus.iot.server.transfer.core.job.JobManager; import com.zmops.zeus.iot.server.transfer.core.manager.TransferManager; -import com.zmops.zeus.iot.server.transfer.core.utils.AgentUtils; +import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -114,7 +114,7 @@ public void submitTask(TaskWrapper wrapper) { this.runningPool.submit(wrapper); notSubmitted = false; } catch (Exception ex) { - AgentUtils.silenceSleepInMs(waitTime); + TransferUtils.silenceSleepInMs(waitTime); LOGGER.warn("reject task {}", wrapper.getTask().getTaskId(), ex); } } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java index b479d5e2..45b03ab8 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java @@ -1,23 +1,5 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.trigger; - import com.zmops.zeus.iot.server.transfer.conf.*; import com.zmops.zeus.iot.server.transfer.core.api.Trigger; import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; @@ -39,7 +21,9 @@ import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.TRIGGER_ONLY_ONE_JOB; /** - * manager for triggers. + * 文件变动监听触发器管理 + * + * @editor nantian */ public class TriggerManager extends AbstractDaemon { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/FileSearchUtils.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/FileSearchUtils.java index 02895137..fe8fcc4f 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/FileSearchUtils.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/FileSearchUtils.java @@ -78,7 +78,7 @@ public static void updateRetryTime(JobProfile jobConf, PathPattern pattern) { public static JobProfile copyJobProfile(TriggerProfile triggerProfile, String dataTime, File pendingFile) { JobProfile copiedProfile = TriggerProfile.parseJsonStr(triggerProfile.toJsonStr()); - String md5 = AgentUtils.getFileMd5(pendingFile); + String md5 = TransferUtils.getFileMd5(pendingFile); copiedProfile.set(pendingFile.getAbsolutePath() + ".md5", md5); copiedProfile.set(JobConstants.JOB_DIR_FILTER_PATTERN, pendingFile.getAbsolutePath()); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/AgentUtils.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/TransferUtils.java similarity index 92% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/AgentUtils.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/TransferUtils.java index 8958f3e7..19ea148d 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/AgentUtils.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/TransferUtils.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.utils; import org.apache.commons.codec.digest.DigestUtils; @@ -45,9 +28,9 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -public class AgentUtils { +public class TransferUtils { - private static final Logger LOGGER = LoggerFactory.getLogger(AgentUtils.class); + private static final Logger LOGGER = LoggerFactory.getLogger(TransferUtils.class); private static final AtomicLong INDEX = new AtomicLong(0); private static final String HEX_PREFIX = "0x"; public static final String EQUAL = "="; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PrefixValidator.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PrefixValidator.java index ece5e83b..23fcaa77 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PrefixValidator.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PrefixValidator.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.validator; import com.zmops.zeus.iot.server.transfer.core.api.Validator; From b481bbc21253524eb9ef2ca3edc18424cdd83086 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 11:57:23 +0800 Subject: [PATCH 275/763] [feat]: update zeus-transfer module --- .../src/main/resources/application.yml | 5 ++- iot-server/server-transfer/pom.xml | 5 +++ .../server/transfer/conf/JobConstants.java | 17 ---------- .../core/manager/TransferManager.java | 34 +++++++------------ .../transfer/core/sink/SenderManager.java | 10 ++---- .../provider/ServerTransferConfig.java | 12 ++++++- .../provider/ServerTransferProvider.java | 13 ++++--- .../src/main/resources/job.json | 18 ++-------- 8 files changed, 46 insertions(+), 68 deletions(-) diff --git a/iot-server/server-bootstrap/src/main/resources/application.yml b/iot-server/server-bootstrap/src/main/resources/application.yml index 3468f1d3..a382e1bb 100644 --- a/iot-server/server-bootstrap/src/main/resources/application.yml +++ b/iot-server/server-bootstrap/src/main/resources/application.yml @@ -44,8 +44,11 @@ core: # ndjson file read realtime server-transfer: - selector: ${ZS_SERVER_TRANSFER:-} + selector: ${ZS_SERVER_TRANSFER:default} default: + name: ${ZS_TRANSFER_NAME:zeus-transfer} + pattern: ${ZS_TRANSFER_PATTERN:E:\data\history-history-syncer-\\d.ndjson} + fileMaxWait: ${ZS_TRANSFER_FILE_MAXWAIT:5} # tdengine storage realtime storage: diff --git a/iot-server/server-transfer/pom.xml b/iot-server/server-transfer/pom.xml index 9b7a1e56..f664e57f 100644 --- a/iot-server/server-transfer/pom.xml +++ b/iot-server/server-transfer/pom.xml @@ -54,6 +54,11 @@ jetty-servlet 9.4.34.v20201102 + + com.zmops + server-core + 1.0-beta + \ No newline at end of file diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java index 51934e75..ee9e5846 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.conf; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/TransferManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/TransferManager.java index f72e6b81..6ec3839e 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/TransferManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/TransferManager.java @@ -1,23 +1,5 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.manager; - import com.zmops.zeus.iot.server.transfer.conf.*; import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; import com.zmops.zeus.iot.server.transfer.core.db.Db; @@ -28,11 +10,14 @@ import com.zmops.zeus.iot.server.transfer.core.task.TaskManager; import com.zmops.zeus.iot.server.transfer.core.task.TaskPositionManager; import com.zmops.zeus.iot.server.transfer.core.trigger.TriggerManager; +import com.zmops.zeus.iot.server.transfer.provider.ServerTransferConfig; import lombok.Getter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_TRIGGER; +import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_FILE_MAX_WAIT; +import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_NAME; +import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_DIR_FILTER_PATTERN; /** * Zabbix History Data Transfer @@ -61,7 +46,12 @@ public class TransferManager extends AbstractDaemon { @Getter private final CommandDb commandDb; - public TransferManager() { + @Getter + private final ServerTransferConfig moduleConfig; + + public TransferManager(ServerTransferConfig config) { + moduleConfig = config; + conf = TransferConfiguration.getAgentConf(); this.db = initDb(); commandDb = new CommandDb(db); @@ -103,7 +93,9 @@ public void start() throws Exception { taskPositionManager.start(); JobProfile profile = JobProfile.parseJsonFile("job.json"); - + profile.setInt(JOB_FILE_MAX_WAIT, moduleConfig.getFileMaxWait()); + profile.set(JOB_NAME, moduleConfig.getName()); + profile.set(JOB_DIR_FILTER_PATTERN, moduleConfig.getPattern()); TriggerProfile triggerProfile = TriggerProfile.parseJobProfile(profile); triggerManager.addTrigger(triggerProfile); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java index 8b0bdc82..6b7502cb 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java @@ -17,7 +17,6 @@ package com.zmops.zeus.iot.server.transfer.core.sink; - import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.core.metrics.PluginMetric; import com.zmops.zeus.iot.server.transfer.core.task.TaskPositionManager; @@ -29,7 +28,7 @@ /** - * proxy client + * 发送管理 */ public class SenderManager { @@ -54,16 +53,11 @@ public SenderManager(JobProfile jobConf, String bid, String sourceFilePath) { */ public void sendBatch(String jobId, String bid, String tid, List bodyList, int retry, long dataTime) { try { - - bodyList.forEach(i -> { - LOGGER.info(new String(i)); - }); +// RecordStreamProcessor.getInstance().in(record); //TODO metric.sendSuccessNum.incr(bodyList.size()); taskPositionManager.updateFileSinkPosition(jobId, sourceFilePath, bodyList.size()); - System.out.println(metric.sendSuccessNum.snapshot()); - } catch (Exception exception) { LOGGER.error("Exception caught", exception); // retry time diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferConfig.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferConfig.java index 3580ffb8..89697a6d 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferConfig.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferConfig.java @@ -1,13 +1,23 @@ package com.zmops.zeus.iot.server.transfer.provider; import com.zmops.zeus.iot.server.library.module.ModuleConfig; +import lombok.Getter; +import lombok.Setter; /** * @author nantian created at 2021/9/22 16:46 *

* ndjson 文件读取配置 */ +@Getter +@Setter public class ServerTransferConfig extends ModuleConfig { - + private String name; + + private String pattern; + + // 文件读取超时 线程回收 + private Integer fileMaxWait; + } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java index d98055c9..6f3282eb 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java @@ -1,5 +1,6 @@ package com.zmops.zeus.iot.server.transfer.provider; +import com.zmops.zeus.iot.server.core.CoreModule; import com.zmops.zeus.iot.server.library.module.*; import com.zmops.zeus.iot.server.transfer.core.manager.TransferManager; import com.zmops.zeus.iot.server.transfer.module.ServerTransferModule; @@ -13,10 +14,10 @@ public class ServerTransferProvider extends ModuleProvider { private static final Logger LOGGER = LoggerFactory.getLogger(ServerTransferProvider.class); - private final ServerTransferConfig serverTransferConfig; + private final ServerTransferConfig config; public ServerTransferProvider() { - this.serverTransferConfig = new ServerTransferConfig(); + this.config = new ServerTransferConfig(); } @Override @@ -31,7 +32,7 @@ public Class module() { @Override public ModuleConfig createConfigBeanIfAbsent() { - return serverTransferConfig; + return config; } @Override @@ -58,7 +59,7 @@ private static void stopManagerIfKilled(TransferManager manager) { @Override public void start() throws ServiceNotProvidedException, ModuleStartException { - TransferManager manager = new TransferManager(); + TransferManager manager = new TransferManager(config); try { manager.start(); stopManagerIfKilled(manager); @@ -75,6 +76,8 @@ public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleSta @Override public String[] requiredModules() { - return new String[0]; + return new String[]{ + CoreModule.NAME + }; } } diff --git a/iot-server/server-transfer/src/main/resources/job.json b/iot-server/server-transfer/src/main/resources/job.json index 8030761d..e030a11f 100644 --- a/iot-server/server-transfer/src/main/resources/job.json +++ b/iot-server/server-transfer/src/main/resources/job.json @@ -1,21 +1,9 @@ { "job": { - "dir": { - "path": "", - "pattern": "E:\\data\\2.ndjson" - }, "id": 1, - "thread": { - "running": { - "core": "4" - } - }, - "file": { - "max": { - "wait": -1 - } - }, - "name": "zeus-transfer" + "dir": { + "path": "" + } }, "proxy": { "bid": "bid10", From 4a8c5cb1a6c5840cf0a1351220d242c24cefa44c Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 12:00:44 +0800 Subject: [PATCH 276/763] [style]: edit code style --- .../transfer/conf/AbstractConfiguration.java | 19 -- .../server/transfer/conf/CommonConstants.java | 17 -- .../iot/server/transfer/conf/JobProfile.java | 17 -- .../transfer/conf/TransferConfiguration.java | 17 -- .../transfer/conf/TransferConstants.java | 163 ++++++++---------- .../server/transfer/conf/TriggerProfile.java | 17 -- .../iot/server/transfer/core/api/Channel.java | 17 -- .../iot/server/transfer/core/api/Filter.java | 18 +- .../iot/server/transfer/core/api/Message.java | 17 -- .../iot/server/transfer/core/api/Reader.java | 17 -- .../iot/server/transfer/core/api/Sink.java | 18 +- .../iot/server/transfer/core/api/Source.java | 17 -- .../iot/server/transfer/core/api/Stage.java | 17 -- .../iot/server/transfer/core/api/Trigger.java | 17 -- .../server/transfer/core/api/Validator.java | 18 -- .../transfer/core/channel/MemoryChannel.java | 21 +-- .../transfer/core/common/AbstractDaemon.java | 17 -- .../core/common/AgentThreadFactory.java | 17 -- .../server/transfer/core/common/Service.java | 20 +-- .../transfer/core/db/BerkeleyDbImp.java | 20 +-- .../zeus/iot/server/transfer/core/db/Db.java | 25 +-- .../server/transfer/core/db/JobProfileDb.java | 1 - .../transfer/core/db/KeyValueEntity.java | 17 -- .../transfer/core/db/StateSearchKey.java | 17 -- .../transfer/core/db/TriggerProfileDb.java | 17 -- .../core/exception/FileException.java | 17 -- .../transfer/core/filter/DateFormatRegex.java | 20 --- .../server/transfer/core/job/CommandDb.java | 17 -- .../transfer/core/job/CommandEntity.java | 17 -- .../iot/server/transfer/core/job/Job.java | 18 -- .../server/transfer/core/job/JobManager.java | 27 +-- .../server/transfer/core/job/JobMetrics.java | 18 -- .../server/transfer/core/job/JobWrapper.java | 17 -- .../core/manager/TransferManager.java | 9 +- .../transfer/core/message/DefaultMessage.java | 17 -- .../transfer/core/message/EndMessage.java | 17 -- .../transfer/core/message/ProxyMessage.java | 23 +-- .../core/metrics/AgentDynamicMBean.java | 17 -- .../server/transfer/core/metrics/Metric.java | 17 -- .../transfer/core/metrics/MetricSnapshot.java | 17 -- .../server/transfer/core/metrics/Metrics.java | 17 -- .../core/metrics/MetricsRegister.java | 28 +-- .../transfer/core/metrics/MutableMetric.java | 17 -- .../transfer/core/metrics/PluginMetric.java | 17 -- .../iot/server/transfer/core/metrics/Tag.java | 18 +- .../core/metrics/counter/Counter.java | 17 -- .../core/metrics/counter/CounterInt.java | 17 -- .../core/metrics/counter/CounterLong.java | 17 -- .../transfer/core/metrics/gauge/Gauge.java | 17 -- .../transfer/core/metrics/gauge/GaugeInt.java | 17 -- .../core/metrics/gauge/GaugeLong.java | 17 -- .../core/metrics/meta/MetricMeta.java | 18 -- .../core/metrics/meta/MetricsMeta.java | 17 -- .../server/transfer/core/sink/NdjsonSink.java | 18 -- .../transfer/core/sink/SenderManager.java | 17 -- .../transfer/core/source/TextFileSource.java | 19 +- .../core/source/reader/TextFileReader.java | 21 +-- .../core/state/AbstractStateWrapper.java | 17 -- .../iot/server/transfer/core/state/State.java | 17 -- .../transfer/core/state/StateCallback.java | 17 -- .../iot/server/transfer/core/task/Task.java | 17 -- .../transfer/core/task/TaskManager.java | 18 -- .../transfer/core/task/TaskMetrics.java | 17 -- .../core/task/TaskPositionManager.java | 17 -- .../transfer/core/task/TaskWrapper.java | 17 -- .../core/trigger/DirectoryTrigger.java | 19 +- .../transfer/core/trigger/PathPattern.java | 18 -- .../transfer/core/trigger/TriggerManager.java | 10 +- .../transfer/core/utils/FileSearchUtils.java | 17 -- .../core/validator/PatternValidator.java | 17 -- 70 files changed, 118 insertions(+), 1255 deletions(-) diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java index 43cc6774..4dc89b39 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java @@ -1,27 +1,8 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.conf; import com.google.gson.*; import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; import org.apache.commons.lang3.StringUtils; - - import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java index f3895d27..6e7b4427 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.conf; public class CommonConstants { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobProfile.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobProfile.java index 0e923edb..61f022cb 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobProfile.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobProfile.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.conf; import com.google.gson.Gson; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConfiguration.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConfiguration.java index 940d9897..ffd1e810 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConfiguration.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConfiguration.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.conf; import org.apache.commons.io.FileUtils; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java index 948a35a6..f43e6344 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java @@ -1,161 +1,146 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.conf; import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; public class TransferConstants { - public static final String AGENT_HOME = "agent.home"; + public static final String AGENT_HOME = "agent.home"; public static final String DEFAULT_AGENT_HOME = System.getProperty("agent.home"); - public static final String AGENT_LOCAL_CACHE = "agent.local.cache"; + public static final String AGENT_LOCAL_CACHE = "agent.local.cache"; public static final String DEFAULT_AGENT_LOCAL_CACHE = ".local"; - public static final String AGENT_LOCAL_CACHE_TIMEOUT = "agent.local.cache.timeout"; - /** cache timeout in minutes. **/ - public static final int DEFAULT_AGENT_LOCAL_CACHE_TIMEOUT = 30; + public static final String AGENT_LOCAL_CACHE_TIMEOUT = "agent.local.cache.timeout"; + /** + * cache timeout in minutes. + **/ + public static final int DEFAULT_AGENT_LOCAL_CACHE_TIMEOUT = 30; - public static final String AGENT_LOCAL_STORE_PATH = "agent.localStore.path"; + public static final String AGENT_LOCAL_STORE_PATH = "agent.localStore.path"; public static final String DEFAULT_AGENT_LOCAL_STORE_PATH = ".bdb"; - public static final String AGENT_ROCKS_DB_PATH = "agent.rocks.db.path"; + public static final String AGENT_ROCKS_DB_PATH = "agent.rocks.db.path"; public static final String DEFAULT_AGENT_ROCKS_DB_PATH = ".rocksdb"; - public static final String AGENT_UNIQ_ID = "agent.uniq.id"; + public static final String AGENT_UNIQ_ID = "agent.uniq.id"; // default use local ip as uniq id for agent. public static final String DEFAULT_AGENT_UNIQ_ID = TransferUtils.getLocalIp(); - public static final String AGENT_DB_INSTANCE_NAME = "agent.db.instance.name"; + public static final String AGENT_DB_INSTANCE_NAME = "agent.db.instance.name"; public static final String DEFAULT_AGENT_DB_INSTANCE_NAME = "agent"; - public static final String AGENT_DB_CLASSNAME = "agent.db.classname"; + public static final String AGENT_DB_CLASSNAME = "agent.db.classname"; public static final String DEFAULT_AGENT_DB_CLASSNAME = "com.zmops.zeus.iot.server.transfer.core.db.BerkeleyDbImp"; // default is empty. public static final String AGENT_FETCHER_CLASSNAME = "agent.fetcher.classname"; - public static final String AGENT_CONF_PARENT = "agent.conf.parent"; + public static final String AGENT_CONF_PARENT = "agent.conf.parent"; public static final String DEFAULT_AGENT_CONF_PARENT = "conf"; - public static final String AGENT_LOCAL_STORE_READONLY = "agent.localStore.readonly"; + public static final String AGENT_LOCAL_STORE_READONLY = "agent.localStore.readonly"; public static final boolean DEFAULT_AGENT_LOCAL_STORE_READONLY = false; - public static final String AGENT_HTTP_PORT = "agent.http.port"; - public static final int DEFAULT_AGENT_HTTP_PORT = 8008; + public static final String AGENT_HTTP_PORT = "agent.http.port"; + public static final int DEFAULT_AGENT_HTTP_PORT = 8008; - public static final String AGENT_ENABLE_HTTP = "agent.http.enable"; + public static final String AGENT_ENABLE_HTTP = "agent.http.enable"; public static final boolean DEFAULT_AGENT_ENABLE_HTTP = true; - public static final String TRIGGER_FETCH_INTERVAL = "trigger.fetch.interval"; - public static final int DEFAULT_TRIGGER_FETCH_INTERVAL = 1; + public static final String TRIGGER_FETCH_INTERVAL = "trigger.fetch.interval"; + public static final int DEFAULT_TRIGGER_FETCH_INTERVAL = 1; - public static final String TRIGGER_MAX_RUNNING_NUM = "trigger.max.running.num"; - public static final int DEFAULT_TRIGGER_MAX_RUNNING_NUM = 4096; + public static final String TRIGGER_MAX_RUNNING_NUM = "trigger.max.running.num"; + public static final int DEFAULT_TRIGGER_MAX_RUNNING_NUM = 4096; - public static final String AGENT_LOCAL_STORE_TRANSACTIONAL = "agent.localStore.transactional"; + public static final String AGENT_LOCAL_STORE_TRANSACTIONAL = "agent.localStore.transactional"; public static final boolean DEFAULT_AGENT_LOCAL_STORE_TRANSACTIONAL = true; - public static final String AGENT_LOCAL_STORE_LOCK_TIMEOUT = "agent.localStore.lockTimeout"; - public static final int DEFAULT_AGENT_LOCAL_STORE_LOCK_TIMEOUT = 10000; + public static final String AGENT_LOCAL_STORE_LOCK_TIMEOUT = "agent.localStore.lockTimeout"; + public static final int DEFAULT_AGENT_LOCAL_STORE_LOCK_TIMEOUT = 10000; - public static final String AGENT_LOCAL_STORE_NO_SYNC_VOID = "agent.localStore.noSyncVoid"; + public static final String AGENT_LOCAL_STORE_NO_SYNC_VOID = "agent.localStore.noSyncVoid"; public static final boolean DEFAULT_AGENT_LOCAL_STORE_NO_SYNC_VOID = false; - public static final String AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID = + public static final String AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID = "agent.localStore.WriteNoSyncVoid"; public static final boolean DEFAULT_AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID = false; - public static final String AGENT_FETCH_CENTER_INTERVAL_SECONDS = "agent.fetchCenter.interval"; - public static final int DEFAULT_AGENT_FETCH_CENTER_INTERVAL_SECONDS = 5; + public static final String AGENT_FETCH_CENTER_INTERVAL_SECONDS = "agent.fetchCenter.interval"; + public static final int DEFAULT_AGENT_FETCH_CENTER_INTERVAL_SECONDS = 5; - public static final String AGENT_TRIGGER_CHECK_INTERVAL_SECONDS = "agent.trigger.check.interval"; - public static final int DEFAULT_AGENT_TRIGGER_CHECK_INTERVAL_SECONDS = 1; + public static final String AGENT_TRIGGER_CHECK_INTERVAL_SECONDS = "agent.trigger.check.interval"; + public static final int DEFAULT_AGENT_TRIGGER_CHECK_INTERVAL_SECONDS = 1; - public static final String THREAD_POOL_AWAIT_TIME = "thread.pool.await.time"; + public static final String THREAD_POOL_AWAIT_TIME = "thread.pool.await.time"; // time in ms - public static final long DEFAULT_THREAD_POOL_AWAIT_TIME = 300; + public static final long DEFAULT_THREAD_POOL_AWAIT_TIME = 300; - public static final String JOB_THREAD_PENDING_MAX = "job.thread.pending.max"; - public static final int DEFAULT_JOB_THREAD_PENDING_MAX = 40; + public static final String JOB_THREAD_PENDING_MAX = "job.thread.pending.max"; + public static final int DEFAULT_JOB_THREAD_PENDING_MAX = 40; - public static final String JOB_THREAD_RUNNING_CORE = "job.thread.running.core"; - public static final int DEFAULT_JOB_THREAD_RUNNING_CORE = 4; + public static final String JOB_THREAD_RUNNING_CORE = "job.thread.running.core"; + public static final int DEFAULT_JOB_THREAD_RUNNING_CORE = 4; - public static final String JOB_MONITOR_INTERVAL = "job.monitor.interval"; - public static final int DEFAULT_JOB_MONITOR_INTERVAL = 5; + public static final String JOB_MONITOR_INTERVAL = "job.monitor.interval"; + public static final int DEFAULT_JOB_MONITOR_INTERVAL = 5; - public static final String JOB_THREAD_RUNNING_MAX = "job.thread.running.max"; - public static final int DEFAULT_JOB_THREAD_RUNNING_MAX = 20; + public static final String JOB_THREAD_RUNNING_MAX = "job.thread.running.max"; + public static final int DEFAULT_JOB_THREAD_RUNNING_MAX = 20; - public static final String JOB_RUNNING_THREAD_KEEP_ALIVE = "job.running.thread.keepAlive"; - public static final long DEFAULT_JOB_RUNNING_THREAD_KEEP_ALIVE = 60L; + public static final String JOB_RUNNING_THREAD_KEEP_ALIVE = "job.running.thread.keepAlive"; + public static final long DEFAULT_JOB_RUNNING_THREAD_KEEP_ALIVE = 60L; - public static final String JOB_FINISH_CHECK_INTERVAL = "job.finish.checkInterval"; - public static final long DEFAULT_JOB_FINISH_CHECK_INTERVAL = 6L; + public static final String JOB_FINISH_CHECK_INTERVAL = "job.finish.checkInterval"; + public static final long DEFAULT_JOB_FINISH_CHECK_INTERVAL = 6L; - public static final String TASK_PENDING_MAX = "task.pending.max"; - public static final int DEFAULT_TASK_PENDING_MAX = 100; + public static final String TASK_PENDING_MAX = "task.pending.max"; + public static final int DEFAULT_TASK_PENDING_MAX = 100; - public static final String TASK_RUNNING_THREAD_CORE_SIZE = "task.running.thread.coreSize"; - public static final int DEFAULT_TASK_RUNNING_THREAD_CORE_SIZE = 4; + public static final String TASK_RUNNING_THREAD_CORE_SIZE = "task.running.thread.coreSize"; + public static final int DEFAULT_TASK_RUNNING_THREAD_CORE_SIZE = 4; - public static final String TASK_RUNNING_THREAD_MAX_SIZE = "task.running.thread.maxSize"; - public static final int DEFAULT_TASK_RUNNING_THREAD_MAX_SIZE = + public static final String TASK_RUNNING_THREAD_MAX_SIZE = "task.running.thread.maxSize"; + public static final int DEFAULT_TASK_RUNNING_THREAD_MAX_SIZE = Runtime.getRuntime().availableProcessors() * 2; - public static final String TASK_RUNNING_THREAD_KEEP_ALIVE = "task.running.thread.keepAlive"; - public static final long DEFAULT_TASK_RUNNING_THREAD_KEEP_ALIVE = 60L; + public static final String TASK_RUNNING_THREAD_KEEP_ALIVE = "task.running.thread.keepAlive"; + public static final long DEFAULT_TASK_RUNNING_THREAD_KEEP_ALIVE = 60L; - public static final String TASK_RETRY_MAX_CAPACITY = "task.retry.maxCapacity"; - public static final int DEFAULT_TASK_RETRY_MAX_CAPACITY = 10000; + public static final String TASK_RETRY_MAX_CAPACITY = "task.retry.maxCapacity"; + public static final int DEFAULT_TASK_RETRY_MAX_CAPACITY = 10000; - public static final String TASK_MONITOR_INTERVAL = "task.monitor.interval"; - public static final int DEFAULT_TASK_MONITOR_INTERVAL = 6; + public static final String TASK_MONITOR_INTERVAL = "task.monitor.interval"; + public static final int DEFAULT_TASK_MONITOR_INTERVAL = 6; - public static final String TASK_RETRY_SUBMIT_WAIT_SECONDS = "task.retry.submit.waitSeconds"; - public static final int DEFAULT_TASK_RETRY_SUBMIT_WAIT_SECONDS = 5; + public static final String TASK_RETRY_SUBMIT_WAIT_SECONDS = "task.retry.submit.waitSeconds"; + public static final int DEFAULT_TASK_RETRY_SUBMIT_WAIT_SECONDS = 5; - public static final String TASK_MAX_RETRY_TIME = "task.maxRetry.time"; - public static final int DEFAULT_TASK_MAX_RETRY_TIME = 3; + public static final String TASK_MAX_RETRY_TIME = "task.maxRetry.time"; + public static final int DEFAULT_TASK_MAX_RETRY_TIME = 3; - public static final String TASK_PUSH_MAX_SECOND = "task.push.maxSecond"; - public static final int DEFAULT_TASK_PUSH_MAX_SECOND = 2; + public static final String TASK_PUSH_MAX_SECOND = "task.push.maxSecond"; + public static final int DEFAULT_TASK_PUSH_MAX_SECOND = 2; - public static final String TASK_PULL_MAX_SECOND = "task.pull.maxSecond"; - public static final int DEFAULT_TASK_PULL_MAX_SECOND = 2; + public static final String TASK_PULL_MAX_SECOND = "task.pull.maxSecond"; + public static final int DEFAULT_TASK_PULL_MAX_SECOND = 2; - public static final String CHANNEL_MEMORY_CAPACITY = "channel.memory.capacity"; - public static final int DEFAULT_CHANNEL_MEMORY_CAPACITY = 10000; + public static final String CHANNEL_MEMORY_CAPACITY = "channel.memory.capacity"; + public static final int DEFAULT_CHANNEL_MEMORY_CAPACITY = 10000; - public static final String TRIGGER_CHECK_INTERVAL = "trigger.check.interval"; - public static final int DEFAULT_TRIGGER_CHECK_INTERVAL = 2; + public static final String TRIGGER_CHECK_INTERVAL = "trigger.check.interval"; + public static final int DEFAULT_TRIGGER_CHECK_INTERVAL = 2; - public static final String WORKER_POOL_AWAIT_TIME = "worker.pool.await.time"; - public static final long DEFAULT_WORKER_POOL_AWAIT_TIME = 10; + public static final String WORKER_POOL_AWAIT_TIME = "worker.pool.await.time"; + public static final long DEFAULT_WORKER_POOL_AWAIT_TIME = 10; - public static final String JOB_DB_CACHE_TIME = "job.db.cache.time"; + public static final String JOB_DB_CACHE_TIME = "job.db.cache.time"; // cache for 3 days. - public static final long DEFAULT_JOB_DB_CACHE_TIME = 3 * 24 * 60 * 60 * 1000; + public static final long DEFAULT_JOB_DB_CACHE_TIME = 3 * 24 * 60 * 60 * 1000; - public static final String JOB_DB_CACHE_CHECK_INTERVAL = "job.db.cache.check.interval"; - public static final int DEFAULT_JOB_DB_CACHE_CHECK_INTERVAL = 60 * 60; + public static final String JOB_DB_CACHE_CHECK_INTERVAL = "job.db.cache.check.interval"; + public static final int DEFAULT_JOB_DB_CACHE_CHECK_INTERVAL = 60 * 60; public static final String AGENT_LOCAL_IP = "agent.local.ip"; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TriggerProfile.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TriggerProfile.java index 00dcbe78..4facae51 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TriggerProfile.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TriggerProfile.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.conf; /** diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Channel.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Channel.java index 03519125..93882c34 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Channel.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Channel.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.api; import java.util.concurrent.TimeUnit; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Filter.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Filter.java index 00535959..41ba07a3 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Filter.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Filter.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.api; /** @@ -24,6 +7,7 @@ public interface Filter { /** * whether reader is legal. + * * @return true if reader is legal else false. */ boolean match(); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Message.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Message.java index f92c8edd..1ed82436 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Message.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Message.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.api; import java.util.Map; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Reader.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Reader.java index 63ef33de..2bd32524 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Reader.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Reader.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.api; /** diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Sink.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Sink.java index 04bb8fcc..aa591f98 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Sink.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Sink.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.api; /** @@ -32,6 +15,7 @@ public interface Sink extends Stage { /** * set source file name where the message is generated + * * @param sourceFileName */ void setSourceFile(String sourceFileName); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Source.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Source.java index dff42e4f..0ed2d8de 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Source.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Source.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.api; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Stage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Stage.java index 82f5f2de..2419ac14 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Stage.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Stage.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.api; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Trigger.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Trigger.java index d9c71e34..5656b445 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Trigger.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Trigger.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.api; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Validator.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Validator.java index 45436c0f..025cd6c1 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Validator.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Validator.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.api; /** @@ -23,7 +6,6 @@ public interface Validator { /** - * * @param messageLine * @return */ diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java index a49d69e3..9a232016 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java @@ -1,27 +1,10 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.channel; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.core.api.Channel; import com.zmops.zeus.iot.server.transfer.core.api.Message; -import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.core.metrics.PluginMetric; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AbstractDaemon.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AbstractDaemon.java index 608ade6f..b1c7d263 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AbstractDaemon.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AbstractDaemon.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.common; import org.slf4j.Logger; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AgentThreadFactory.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AgentThreadFactory.java index 3bedd92f..350a1c22 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AgentThreadFactory.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AgentThreadFactory.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.common; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/Service.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/Service.java index 91791814..30026149 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/Service.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/Service.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.common; /** @@ -24,18 +7,21 @@ public interface Service { /** * start service + * * @throws Exception */ void start() throws Exception; /** * stop service + * * @throws Exception */ void stop() throws Exception; /** * join and wait until getting signal + * * @throws Exception */ void join() throws Exception; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java index 75580b7d..7942f067 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java @@ -1,29 +1,11 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.db; import com.sleepycat.je.Environment; import com.sleepycat.je.EnvironmentConfig; import com.sleepycat.persist.*; - +import com.zmops.zeus.iot.server.transfer.conf.CommonConstants; import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; -import com.zmops.zeus.iot.server.transfer.conf.CommonConstants; import com.zmops.zeus.iot.server.transfer.core.job.CommandEntity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/Db.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/Db.java index 3d83a9cf..8a250cfb 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/Db.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/Db.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.db; import com.zmops.zeus.iot.server.transfer.core.job.CommandEntity; @@ -33,6 +16,7 @@ public interface Db extends Closeable { /** * get command by command id + * * @param commandId * @return */ @@ -40,6 +24,7 @@ public interface Db extends Closeable { /** * put command entity in db + * * @param entity * @return */ @@ -49,7 +34,7 @@ public interface Db extends Closeable { * store keyValue, if key has exists, throw exception. * * @param entity - key/value - * @throws NullPointerException key should not be null + * @throws NullPointerException key should not be null * @throws KeyAlreadyExistsException key already exists */ void set(KeyValueEntity entity); @@ -83,6 +68,7 @@ public interface Db extends Closeable { /** * search commands using ack status + * * @param isAcked * @return */ @@ -90,6 +76,7 @@ public interface Db extends Closeable { /** * search one keyValue by search key + * * @param searchKey - search key * @return null or keyValue */ @@ -97,6 +84,7 @@ public interface Db extends Closeable { /** * search one keyValue by fileName + * * @param fileName * @return */ @@ -104,6 +92,7 @@ public interface Db extends Closeable { /** * find all by prefix key. + * * @param prefix - prefix string * @return list of k/v */ diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java index d35332da..03a45d0d 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java @@ -15,7 +15,6 @@ * limitations under the License. */ - package com.zmops.zeus.iot.server.transfer.core.db; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/KeyValueEntity.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/KeyValueEntity.java index 909bebaf..c423c264 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/KeyValueEntity.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/KeyValueEntity.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.db; import com.sleepycat.persist.model.Entity; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/StateSearchKey.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/StateSearchKey.java index 1be397f5..efdf1dda 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/StateSearchKey.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/StateSearchKey.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.db; /** diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/TriggerProfileDb.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/TriggerProfileDb.java index 2c7e5a2a..958e15f7 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/TriggerProfileDb.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/TriggerProfileDb.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.db; import com.zmops.zeus.iot.server.transfer.conf.CommonConstants; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/exception/FileException.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/exception/FileException.java index 5df83ecd..b38b275e 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/exception/FileException.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/exception/FileException.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.exception; public class FileException extends RuntimeException { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java index ec24e3fe..d585a501 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java @@ -1,28 +1,8 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.filter; import com.zmops.zeus.iot.server.transfer.core.api.Filter; - - import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; import org.apache.commons.lang3.StringUtils; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java index 509dd160..bf021f85 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.job; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandEntity.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandEntity.java index e9f5999a..eef18705 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandEntity.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandEntity.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.job; import com.sleepycat.persist.model.Entity; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java index c7ca3349..0929ae2e 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.job; @@ -30,7 +13,6 @@ import com.zmops.zeus.iot.server.transfer.core.task.Task; import lombok.Getter; import lombok.Setter; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java index a00d0e3a..9cc96b51 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java @@ -1,26 +1,9 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.job; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; import com.zmops.zeus.iot.server.transfer.core.common.AgentThreadFactory; import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; @@ -38,8 +21,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; -import static com.zmops.zeus.iot.server.transfer.conf.TransferConstants.*; import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.*; +import static com.zmops.zeus.iot.server.transfer.conf.TransferConstants.*; /** * JobManager maintains lots of jobs, and communicate between server and task manager. @@ -53,9 +36,9 @@ public class JobManager extends AbstractDaemon { // jobs which are not accepted by running pool. private final ConcurrentHashMap pendingJobs; // job thread pool - private final ThreadPoolExecutor runningPool; - private final TransferManager transferManager; - private final int monitorInterval; + private final ThreadPoolExecutor runningPool; + private final TransferManager transferManager; + private final int monitorInterval; private final long jobDbCacheTime; private final long jobDbCacheCheckInterval; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java index ef66da34..1033165d 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java @@ -1,21 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - package com.zmops.zeus.iot.server.transfer.core.job; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java index 124a69e2..59719148 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.job; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/TransferManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/TransferManager.java index 6ec3839e..afbd2e5e 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/TransferManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/TransferManager.java @@ -1,6 +1,9 @@ package com.zmops.zeus.iot.server.transfer.core.manager; -import com.zmops.zeus.iot.server.transfer.conf.*; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; +import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; +import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; import com.zmops.zeus.iot.server.transfer.core.db.Db; import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; @@ -15,9 +18,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_FILE_MAX_WAIT; -import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_NAME; -import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_DIR_FILTER_PATTERN; +import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.*; /** * Zabbix History Data Transfer diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/DefaultMessage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/DefaultMessage.java index eb1d2f28..a755ad0a 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/DefaultMessage.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/DefaultMessage.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.message; import com.zmops.zeus.iot.server.transfer.core.api.Message; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/EndMessage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/EndMessage.java index 261b7865..3ec03969 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/EndMessage.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/EndMessage.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.message; import com.zmops.zeus.iot.server.transfer.core.api.Message; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java index b3ba66fc..64031547 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.message; import com.zmops.zeus.iot.server.transfer.core.api.Message; @@ -28,10 +11,10 @@ public class ProxyMessage implements Message { private static final String DEFAULT_TID = "__"; - private final byte[] body; + private final byte[] body; private final Map header; - private final String bid; - private final String tid; + private final String bid; + private final String tid; public ProxyMessage(byte[] body, Map header) { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/AgentDynamicMBean.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/AgentDynamicMBean.java index 15943ab9..9ee7e5c9 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/AgentDynamicMBean.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/AgentDynamicMBean.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.metrics; import com.zmops.zeus.iot.server.transfer.core.metrics.meta.MetricMeta; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metric.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metric.java index 4326f873..6c90406d 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metric.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metric.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.metrics; import java.lang.annotation.ElementType; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricSnapshot.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricSnapshot.java index f15118c0..47d89de9 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricSnapshot.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricSnapshot.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.metrics; public interface MetricSnapshot { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metrics.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metrics.java index f8058c80..03fc295b 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metrics.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metrics.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.metrics; import java.lang.annotation.ElementType; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricsRegister.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricsRegister.java index 185b1e3e..72899517 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricsRegister.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricsRegister.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.metrics; @@ -43,9 +26,9 @@ public class MetricsRegister { private static final Logger LOGGER = LoggerFactory.getLogger(MetricsRegister.class); - private static final String DOMAIN_PREFIX = "Agent:"; - private static final String MODULE_PREFIX = "module="; - private static final String ASPECT_PREFIX = "aspect="; + private static final String DOMAIN_PREFIX = "Agent:"; + private static final String MODULE_PREFIX = "module="; + private static final String ASPECT_PREFIX = "aspect="; private static final String COMMA_SPLITTER = ","; // object name should be uniq @@ -56,6 +39,7 @@ private MetricsRegister() { /** * register object name for metric + * * @param agentDynamicMBean agent mbean */ private static void innerRegister(AgentDynamicMBean agentDynamicMBean) { @@ -63,7 +47,7 @@ private static void innerRegister(AgentDynamicMBean agentDynamicMBean) { String nameStr = DOMAIN_PREFIX + MODULE_PREFIX + agentDynamicMBean.getModule() + COMMA_SPLITTER + ASPECT_PREFIX + agentDynamicMBean.getAspect(); try { - ObjectName tmpName = new ObjectName(nameStr); + ObjectName tmpName = new ObjectName(nameStr); ObjectName objectName = CACHED_NAME.putIfAbsent(nameStr, tmpName); if (objectName == null) { mbs.registerMBean(agentDynamicMBean, tmpName); @@ -88,7 +72,7 @@ public static void register(String module, String aspect, String desc, Object so * handle class level annotation */ private static MetricsMeta handleClassAnnotation(Object source, - List metricMetaList) { + List metricMetaList) { for (Annotation annotation : source.getClass().getAnnotations()) { if (annotation instanceof Metrics) { return MetricsMeta.build((Metrics) annotation, metricMetaList); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MutableMetric.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MutableMetric.java index ffd05b4a..cefef8d6 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MutableMetric.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MutableMetric.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.metrics; /** diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/PluginMetric.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/PluginMetric.java index 00790015..6c0cdf2a 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/PluginMetric.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/PluginMetric.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.metrics; import com.zmops.zeus.iot.server.transfer.core.metrics.counter.CounterLong; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Tag.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Tag.java index 2ff785df..c3b8250c 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Tag.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Tag.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.metrics; public class Tag implements MetricSnapshot { @@ -23,6 +6,7 @@ public class Tag implements MetricSnapshot { /** * set string name for tag. + * * @param name - tag name */ public void setName(String name) { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/Counter.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/Counter.java index c901f7d9..9c64fc24 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/Counter.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/Counter.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.metrics.counter; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterInt.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterInt.java index f5933e36..8e0cc454 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterInt.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterInt.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.metrics.counter; import java.util.concurrent.atomic.AtomicInteger; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterLong.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterLong.java index d1a7d464..ba7fac22 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterLong.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterLong.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.metrics.counter; import java.util.concurrent.atomic.AtomicLong; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/Gauge.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/Gauge.java index beb94e2b..0f4fc4e0 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/Gauge.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/Gauge.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.metrics.gauge; import com.zmops.zeus.iot.server.transfer.core.metrics.MutableMetric; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeInt.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeInt.java index f1b608c3..9779bc88 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeInt.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeInt.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.metrics.gauge; import java.util.concurrent.atomic.AtomicInteger; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeLong.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeLong.java index 6bc6e6db..aa7a54da 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeLong.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeLong.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.metrics.gauge; import java.util.concurrent.atomic.AtomicLong; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricMeta.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricMeta.java index 35c917b0..73be1dfc 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricMeta.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricMeta.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.metrics.meta; import com.zmops.zeus.iot.server.transfer.core.metrics.Metric; @@ -24,7 +7,6 @@ import com.zmops.zeus.iot.server.transfer.core.metrics.gauge.GaugeLong; import org.apache.commons.lang3.StringUtils; - import java.lang.reflect.Field; import static com.zmops.zeus.iot.server.transfer.core.metrics.Metric.Type.*; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricsMeta.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricsMeta.java index 1438600c..20b58669 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricsMeta.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricsMeta.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.metrics.meta; import com.zmops.zeus.iot.server.transfer.core.metrics.Metrics; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java index b258cc0d..63933bc4 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.sink; import com.zmops.zeus.iot.server.transfer.conf.CommonConstants; @@ -27,7 +10,6 @@ import com.zmops.zeus.iot.server.transfer.core.message.ProxyMessage; import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; import org.apache.commons.lang3.tuple.Pair; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java index 6b7502cb..d593eb2f 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.sink; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java index 0313c363..cf5f1a8f 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java @@ -1,26 +1,9 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.source; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.core.api.Reader; import com.zmops.zeus.iot.server.transfer.core.api.Source; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.core.source.reader.TextFileReader; import com.zmops.zeus.iot.server.transfer.core.utils.FileSearchUtils; import org.slf4j.Logger; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java index fad0bd1b..d1fa87ff 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java @@ -1,34 +1,15 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.source.reader; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.core.api.Message; import com.zmops.zeus.iot.server.transfer.core.api.Reader; import com.zmops.zeus.iot.server.transfer.core.api.Validator; - -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.core.exception.FileException; import com.zmops.zeus.iot.server.transfer.core.message.DefaultMessage; import com.zmops.zeus.iot.server.transfer.core.metrics.PluginMetric; import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; import com.zmops.zeus.iot.server.transfer.core.validator.PatternValidator; import org.apache.commons.lang3.StringUtils; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/AbstractStateWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/AbstractStateWrapper.java index 2a0774e1..cb8f84dc 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/AbstractStateWrapper.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/AbstractStateWrapper.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.state; import org.apache.commons.lang3.tuple.ImmutablePair; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/State.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/State.java index 4c307513..8ad02019 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/State.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/State.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.state; /** diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateCallback.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateCallback.java index c2cf2abb..328afaf8 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateCallback.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateCallback.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.state; /** diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java index 1f00e690..d61339fa 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.task; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java index 386fdd2c..c67faf23 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.task; @@ -25,7 +8,6 @@ import com.zmops.zeus.iot.server.transfer.core.job.JobManager; import com.zmops.zeus.iot.server.transfer.core.manager.TransferManager; import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java index 182c4377..beb77554 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.task; import com.zmops.zeus.iot.server.transfer.core.metrics.Metric; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java index 11651755..6f200c98 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.task; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java index c2e1194f..3e436f34 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.task; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java index 9be6c191..6e0c30b9 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java @@ -1,25 +1,8 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.trigger; -import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.conf.JobConstants; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; import com.zmops.zeus.iot.server.transfer.core.api.Trigger; import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/PathPattern.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/PathPattern.java index 09475217..b38c0a90 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/PathPattern.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/PathPattern.java @@ -1,26 +1,8 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.trigger; import com.zmops.zeus.iot.server.transfer.core.filter.DateFormatRegex; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.HashCodeBuilder; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java index 45b03ab8..84e772d4 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java @@ -1,12 +1,14 @@ package com.zmops.zeus.iot.server.transfer.core.trigger; -import com.zmops.zeus.iot.server.transfer.conf.*; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; +import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; +import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; import com.zmops.zeus.iot.server.transfer.core.api.Trigger; import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; import com.zmops.zeus.iot.server.transfer.core.db.TriggerProfileDb; import com.zmops.zeus.iot.server.transfer.core.job.JobWrapper; import com.zmops.zeus.iot.server.transfer.core.manager.TransferManager; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -15,10 +17,10 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; -import static com.zmops.zeus.iot.server.transfer.conf.TransferConstants.DEFAULT_TRIGGER_MAX_RUNNING_NUM; -import static com.zmops.zeus.iot.server.transfer.conf.TransferConstants.TRIGGER_MAX_RUNNING_NUM; import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_ID; import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.TRIGGER_ONLY_ONE_JOB; +import static com.zmops.zeus.iot.server.transfer.conf.TransferConstants.DEFAULT_TRIGGER_MAX_RUNNING_NUM; +import static com.zmops.zeus.iot.server.transfer.conf.TransferConstants.TRIGGER_MAX_RUNNING_NUM; /** * 文件变动监听触发器管理 diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/FileSearchUtils.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/FileSearchUtils.java index fe8fcc4f..14fa1863 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/FileSearchUtils.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/FileSearchUtils.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.utils; import com.zmops.zeus.iot.server.transfer.conf.JobConstants; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PatternValidator.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PatternValidator.java index a35e3ee8..ad0a4fd5 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PatternValidator.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PatternValidator.java @@ -1,20 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.zmops.zeus.iot.server.transfer.core.validator; From e10b3fff8e48b7546ee9c58d831c8a110886b30c Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 24 Sep 2021 12:13:19 +0800 Subject: [PATCH 277/763] [feat]: synchronize taos tag --- .../src/main/resources/application.yaml | 7 +- zeus-webapp/pom.xml | 5 + .../device/schedule/SyncTaosTagSchedule.java | 98 +++++++++++++++++++ .../iot/web/tdengine/JdbcConnection.java | 15 +++ .../web/tdengine/JdbcConnectionHolder.java | 19 ++++ .../tdengine/JdbcConnectionInitializer.java | 35 +++++++ .../web/tdengine/JdbcTemplateConnection.java | 35 +++++++ 7 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnection.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionHolder.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionInitializer.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcTemplateConnection.java diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index a18e00f7..dda39c76 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -51,4 +51,9 @@ forest: zbxApiToken: 5376d4510465d6873d6c41076f26c58dae42701941e276971e8f068b76e660d0 nats: - url: nats://${NATS_HOST:127.0.0.1}:${NATS_PORT:4222} \ No newline at end of file + url: nats://${NATS_HOST:127.0.0.1}:${NATS_PORT:4222} + +taos: + url: jdbc:TAOS://${TAOS_HOST:127.0.0.1}:${TAOS_PORT:6030}/zeus_data + username: root + password: taosdata \ No newline at end of file diff --git a/zeus-webapp/pom.xml b/zeus-webapp/pom.xml index bbe64d73..568d4561 100644 --- a/zeus-webapp/pom.xml +++ b/zeus-webapp/pom.xml @@ -51,6 +51,11 @@ jnats 2.2.0 + + com.taosdata.jdbc + taos-jdbcdriver + 2.0.31 + diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java new file mode 100644 index 00000000..72593abd --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java @@ -0,0 +1,98 @@ +package com.zmops.iot.web.device.schedule; + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.device.Tag; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.device.query.QTag; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.tdengine.JdbcConnectionHolder; +import com.zmops.zeus.driver.entity.ZbxItemInfo; +import com.zmops.zeus.driver.service.ZbxItem; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + **/ +@EnableScheduling +@Component +@Slf4j +public class SyncTaosTagSchedule { + + @Autowired + ZbxItem zbxItem; + + @Scheduled(cron = "0 01 12 1/1 * ? ") + public void sync() { + List deviceIds = new QDevice().select(QDevice.alias().deviceId).findSingleAttributeList(); + List tagList = new QTag().sid.in(deviceIds).findList(); + if (ToolUtil.isEmpty(tagList)) { + return; + } + Map> tagMap = tagList.parallelStream().collect(Collectors.groupingBy(Tag::getSid)); + List> historyDesc = JdbcConnectionHolder.INSTANCE.getConnection().queryForList("DESCRIBE history"); + List taosTagNames = historyDesc.parallelStream().filter(o -> "TAG".equals(new String((byte[]) o.get("Note")))).map(o -> new String((byte[]) o.get("Field"))) + .collect(Collectors.toList()); + + if (ToolUtil.isEmpty(taosTagNames)) { + return; + } + List tagNames = tagList.parallelStream().map(Tag::getTag).collect(Collectors.toList()); + //新增taos没有的标签 + addTaosTag(tagNames, taosTagNames); + //删除taos标签 + delTaosTag(taosTagNames, tagNames); + + //更新子表 标签值 + tagMap.forEach((deviceId, tags) -> { + //根据deviceId 找到 设备下所有itemId + String hostid = new QDevice().select(QDevice.alias().zbxId).deviceId.eq(deviceId).findSingleAttribute(); + if (ToolUtil.isEmpty(hostid)) { + return; + } + List itemInfos = JSONObject.parseArray(zbxItem.getItemList(null, hostid), ZbxItemInfo.class); + List itemIds = itemInfos.parallelStream().map(ZbxItemInfo::getItemid).collect(Collectors.toList()); + + itemIds.forEach(itemId -> { + tags.forEach(tag -> { + JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER TABLE history_uint SET TAG " + tag.getTag() + "=" + tag.getValue()); + }); + }); + + }); + } + + private void delTaosTag(List list1, List list2) { + List tagNames = list2; + List taosTagNames = list1; + taosTagNames.removeAll(tagNames); + if (ToolUtil.isEmpty(taosTagNames)) { + return; + } + taosTagNames.forEach(tagName -> { + JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER STABLE history_uint DROP TAG " + tagName); + JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER STABLE history DROP TAG " + tagName); + }); + } + + private void addTaosTag(List list1, List list2) { + List tagNames = list1; + List taosTagNames = list2; + tagNames.removeAll(taosTagNames); + if (ToolUtil.isEmpty(tagNames)) { + return; + } + tagNames.forEach(tagName -> { + JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER STABLE history_uint ADD TAG " + tagName + " NCHAR(16)"); + JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER STABLE history ADD TAG " + tagName + " NCHAR(16)"); + }); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnection.java b/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnection.java new file mode 100644 index 00000000..a8733418 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnection.java @@ -0,0 +1,15 @@ +package com.zmops.iot.web.tdengine; + +import org.springframework.dao.DataAccessException; + +import java.util.List; +import java.util.Map; + +public interface JdbcConnection { + + + List> queryForList(String sql) throws DataAccessException; + + + void execute(final String sql) throws DataAccessException; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionHolder.java b/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionHolder.java new file mode 100644 index 00000000..b2bf2131 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionHolder.java @@ -0,0 +1,19 @@ +package com.zmops.iot.web.tdengine; + +/** + * jdbcConnection singleton + **/ +public enum JdbcConnectionHolder { + + INSTANCE; + + private JdbcConnection connection; + + public JdbcConnection getConnection() { + return connection; + } + + public void setConnection(JdbcConnection connection) { + this.connection = connection; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionInitializer.java b/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionInitializer.java new file mode 100644 index 00000000..6371704f --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionInitializer.java @@ -0,0 +1,35 @@ +package com.zmops.iot.web.tdengine; + +import com.alibaba.druid.pool.DruidDataSource; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Component; + +@Component +public class JdbcConnectionInitializer implements InitializingBean { + + @Value("${taos.url}") + public String url; + @Value("${taos.username}") + public String username; + @Value("${taos.password}") + public String password; + + @Override + public void afterPropertiesSet() throws Exception { + DruidDataSource dataSource = new DruidDataSource(); + dataSource.setDriverClassName("com.taosdata.jdbc.TSDBDriver"); + dataSource.setUrl(url); + dataSource.setUsername(username); + dataSource.setPassword(password); + + dataSource.setInitialSize(10); + dataSource.setMinIdle(10); + dataSource.setMaxActive(10); + dataSource.setMaxWait(30000); + dataSource.setValidationQuery("select server_status()"); + JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); + JdbcConnectionHolder.INSTANCE.setConnection(new JdbcTemplateConnection(jdbcTemplate)); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcTemplateConnection.java b/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcTemplateConnection.java new file mode 100644 index 00000000..3f975218 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcTemplateConnection.java @@ -0,0 +1,35 @@ +package com.zmops.iot.web.tdengine; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.util.Assert; + +import java.util.List; +import java.util.Map; + +/** + * 只读的jdbcTemplate + * + * @author yefei + */ +@Slf4j +public class JdbcTemplateConnection implements JdbcConnection { + + private JdbcTemplate jdbcTemplate; + + public JdbcTemplateConnection(JdbcTemplate jdbcTemplate) { + Assert.state(jdbcTemplate != null, "jdbcTemplate could not be null"); + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public List> queryForList(String sql) throws DataAccessException { + return jdbcTemplate.queryForList(sql); + } + + @Override + public void execute(String sql) throws DataAccessException { + jdbcTemplate.execute(sql); + } +} From 4e865b0a809e3bff551de5108c211fe442479546 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 12:46:32 +0800 Subject: [PATCH 278/763] [feat]: optimize package structure --- .../src/main/resources/application.yml | 4 ++-- .../server/transfer/{core => }/api/Channel.java | 2 +- .../iot/server/transfer/{core => }/api/Filter.java | 2 +- .../server/transfer/{core => }/api/Message.java | 2 +- .../iot/server/transfer/{core => }/api/Reader.java | 2 +- .../iot/server/transfer/{core => }/api/Sink.java | 2 +- .../iot/server/transfer/{core => }/api/Source.java | 2 +- .../iot/server/transfer/{core => }/api/Stage.java | 2 +- .../server/transfer/{core => }/api/Trigger.java | 2 +- .../server/transfer/{core => }/api/Validator.java | 2 +- .../transfer/{core => }/common/AbstractDaemon.java | 4 ++-- .../server/transfer/{core => }/common/Service.java | 2 +- .../TransferThreadFactory.java} | 8 ++++---- .../core/{exception => }/FileException.java | 2 +- .../core/{manager => }/TransferManager.java | 4 ++-- .../transfer/core/channel/MemoryChannel.java | 6 +++--- .../transfer/core/filter/DateFormatRegex.java | 2 +- .../zeus/iot/server/transfer/core/job/Job.java | 8 ++++---- .../iot/server/transfer/core/job/JobManager.java | 8 ++++---- .../iot/server/transfer/core/job/JobMetrics.java | 8 ++++---- .../iot/server/transfer/core/job/JobWrapper.java | 2 +- .../transfer/core/message/DefaultMessage.java | 2 +- .../server/transfer/core/message/EndMessage.java | 2 +- .../server/transfer/core/message/ProxyMessage.java | 2 +- .../iot/server/transfer/core/sink/NdjsonSink.java | 8 ++++---- .../server/transfer/core/sink/SenderManager.java | 2 +- .../transfer/core/source/TextFileSource.java | 4 ++-- .../core/source/reader/TextFileReader.java | 10 +++++----- .../zeus/iot/server/transfer/core/task/Task.java | 6 +++--- .../iot/server/transfer/core/task/TaskManager.java | 8 ++++---- .../iot/server/transfer/core/task/TaskMetrics.java | 10 +++++----- .../transfer/core/task/TaskPositionManager.java | 4 ++-- .../iot/server/transfer/core/task/TaskWrapper.java | 8 ++++---- .../transfer/core/trigger/DirectoryTrigger.java | 4 ++-- .../transfer/core/trigger/TriggerManager.java | 6 +++--- .../transfer/core/validator/PatternValidator.java | 2 +- .../transfer/core/validator/PrefixValidator.java | 2 +- .../{core => }/metrics/AgentDynamicMBean.java | 6 +++--- .../server/transfer/{core => }/metrics/Metric.java | 2 +- .../{core => }/metrics/MetricException.java | 2 +- .../{core => }/metrics/MetricSnapshot.java | 2 +- .../transfer/{core => }/metrics/Metrics.java | 2 +- .../{core => }/metrics/MetricsRegister.java | 14 +++++++------- .../transfer/{core => }/metrics/MutableMetric.java | 2 +- .../transfer/{core => }/metrics/PluginMetric.java | 4 ++-- .../server/transfer/{core => }/metrics/Tag.java | 2 +- .../{core => }/metrics/counter/Counter.java | 4 ++-- .../{core => }/metrics/counter/CounterInt.java | 2 +- .../{core => }/metrics/counter/CounterLong.java | 2 +- .../transfer/{core => }/metrics/gauge/Gauge.java | 4 ++-- .../{core => }/metrics/gauge/GaugeInt.java | 2 +- .../{core => }/metrics/gauge/GaugeLong.java | 2 +- .../{core => }/metrics/meta/MetricMeta.java | 14 +++++++------- .../{core => }/metrics/meta/MetricsMeta.java | 4 ++-- .../transfer/provider/ServerTransferProvider.java | 2 +- 55 files changed, 114 insertions(+), 114 deletions(-) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/api/Channel.java (92%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/api/Filter.java (78%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/api/Message.java (89%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/api/Reader.java (90%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/api/Sink.java (87%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/api/Source.java (86%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/api/Stage.java (84%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/api/Trigger.java (93%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/api/Validator.java (80%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/common/AbstractDaemon.java (94%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/common/Service.java (87%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core/common/AgentThreadFactory.java => common/TransferThreadFactory.java} (75%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/{exception => }/FileException.java (71%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/{manager => }/TransferManager.java (96%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/metrics/AgentDynamicMBean.java (94%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/metrics/Metric.java (94%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/metrics/MetricException.java (80%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/metrics/MetricSnapshot.java (50%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/metrics/Metrics.java (90%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/metrics/MetricsRegister.java (90%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/metrics/MutableMetric.java (63%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/metrics/PluginMetric.java (81%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/metrics/Tag.java (86%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/metrics/counter/Counter.java (58%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/metrics/counter/CounterInt.java (86%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/metrics/counter/CounterLong.java (87%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/metrics/gauge/Gauge.java (71%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/metrics/gauge/GaugeInt.java (91%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/metrics/gauge/GaugeLong.java (91%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/metrics/meta/MetricMeta.java (72%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/metrics/meta/MetricsMeta.java (88%) diff --git a/iot-server/server-bootstrap/src/main/resources/application.yml b/iot-server/server-bootstrap/src/main/resources/application.yml index a382e1bb..9ed8f512 100644 --- a/iot-server/server-bootstrap/src/main/resources/application.yml +++ b/iot-server/server-bootstrap/src/main/resources/application.yml @@ -44,10 +44,10 @@ core: # ndjson file read realtime server-transfer: - selector: ${ZS_SERVER_TRANSFER:default} + selector: ${ZS_SERVER_TRANSFER:-} default: name: ${ZS_TRANSFER_NAME:zeus-transfer} - pattern: ${ZS_TRANSFER_PATTERN:E:\data\history-history-syncer-\\d.ndjson} + pattern: ${ZS_TRANSFER_PATTERN:E:\data\history-history-syncer-[0-9]{1}.ndjson} fileMaxWait: ${ZS_TRANSFER_FILE_MAXWAIT:5} # tdengine storage realtime diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Channel.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Channel.java similarity index 92% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Channel.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Channel.java index 93882c34..98a197e4 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Channel.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Channel.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.api; +package com.zmops.zeus.iot.server.transfer.api; import java.util.concurrent.TimeUnit; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Filter.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Filter.java similarity index 78% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Filter.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Filter.java index 41ba07a3..f7b23f39 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Filter.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Filter.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.api; +package com.zmops.zeus.iot.server.transfer.api; /** * filter for source split diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Message.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Message.java similarity index 89% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Message.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Message.java index 1ed82436..67d5db84 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Message.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Message.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.api; +package com.zmops.zeus.iot.server.transfer.api; import java.util.Map; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Reader.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Reader.java similarity index 90% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Reader.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Reader.java index 2bd32524..0e651ae6 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Reader.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Reader.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.api; +package com.zmops.zeus.iot.server.transfer.api; /** * Reader reads data and provides condition whether the reading action is finished. It's called at diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Sink.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Sink.java similarity index 87% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Sink.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Sink.java index aa591f98..3ac66655 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Sink.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Sink.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.api; +package com.zmops.zeus.iot.server.transfer.api; /** * Sink data to remote data center diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Source.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Source.java similarity index 86% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Source.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Source.java index 0ed2d8de..2393a38e 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Source.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Source.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.api; +package com.zmops.zeus.iot.server.transfer.api; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Stage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Stage.java similarity index 84% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Stage.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Stage.java index 2419ac14..160e859a 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Stage.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Stage.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.api; +package com.zmops.zeus.iot.server.transfer.api; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Trigger.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Trigger.java similarity index 93% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Trigger.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Trigger.java index 5656b445..a744a0d6 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Trigger.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Trigger.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.api; +package com.zmops.zeus.iot.server.transfer.api; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Validator.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Validator.java similarity index 80% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Validator.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Validator.java index 025cd6c1..25af38e8 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/api/Validator.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Validator.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.api; +package com.zmops.zeus.iot.server.transfer.api; /** * For every message, there might be validators to filter required ones diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AbstractDaemon.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/AbstractDaemon.java similarity index 94% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AbstractDaemon.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/AbstractDaemon.java index b1c7d263..7bcdcdcc 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AbstractDaemon.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/AbstractDaemon.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.common; +package com.zmops.zeus.iot.server.transfer.common; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,7 +24,7 @@ public abstract class AbstractDaemon implements Service { 60L, TimeUnit.SECONDS, new SynchronousQueue(), - new AgentThreadFactory("AbstractDaemon") + new TransferThreadFactory("AbstractDaemon") ); private final List> workerFutures; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/Service.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/Service.java similarity index 87% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/Service.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/Service.java index 30026149..ae278dd6 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/Service.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/Service.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.common; +package com.zmops.zeus.iot.server.transfer.common; /** * Service lifecycle interface. diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AgentThreadFactory.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/TransferThreadFactory.java similarity index 75% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AgentThreadFactory.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/TransferThreadFactory.java index 350a1c22..e98925c9 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/common/AgentThreadFactory.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/TransferThreadFactory.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.common; +package com.zmops.zeus.iot.server.transfer.common; import org.slf4j.Logger; @@ -7,15 +7,15 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; -public class AgentThreadFactory implements ThreadFactory { +public class TransferThreadFactory implements ThreadFactory { - private static final Logger LOGGER = LoggerFactory.getLogger(AgentThreadFactory.class); + private static final Logger LOGGER = LoggerFactory.getLogger(TransferThreadFactory.class); private final AtomicInteger mThreadNum = new AtomicInteger(1); private final String threadType; - public AgentThreadFactory(String threadType) { + public TransferThreadFactory(String threadType) { this.threadType = threadType; } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/exception/FileException.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/FileException.java similarity index 71% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/exception/FileException.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/FileException.java index b38b275e..b88603ab 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/exception/FileException.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/FileException.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.exception; +package com.zmops.zeus.iot.server.transfer.core; public class FileException extends RuntimeException { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/TransferManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/TransferManager.java similarity index 96% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/TransferManager.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/TransferManager.java index afbd2e5e..d6eeedac 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/manager/TransferManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/TransferManager.java @@ -1,10 +1,10 @@ -package com.zmops.zeus.iot.server.transfer.core.manager; +package com.zmops.zeus.iot.server.transfer.core; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; -import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; +import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; import com.zmops.zeus.iot.server.transfer.core.db.Db; import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; import com.zmops.zeus.iot.server.transfer.core.db.TriggerProfileDb; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java index 9a232016..dac4fb98 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java @@ -3,9 +3,9 @@ import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; -import com.zmops.zeus.iot.server.transfer.core.api.Channel; -import com.zmops.zeus.iot.server.transfer.core.api.Message; -import com.zmops.zeus.iot.server.transfer.core.metrics.PluginMetric; +import com.zmops.zeus.iot.server.transfer.api.Channel; +import com.zmops.zeus.iot.server.transfer.api.Message; +import com.zmops.zeus.iot.server.transfer.metrics.PluginMetric; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java index d585a501..4e565fa3 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java @@ -1,6 +1,6 @@ package com.zmops.zeus.iot.server.transfer.core.filter; -import com.zmops.zeus.iot.server.transfer.core.api.Filter; +import com.zmops.zeus.iot.server.transfer.api.Filter; import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java index 0929ae2e..6d6d6c3d 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java @@ -3,10 +3,10 @@ import com.zmops.zeus.iot.server.transfer.conf.JobConstants; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.core.api.Channel; -import com.zmops.zeus.iot.server.transfer.core.api.Reader; -import com.zmops.zeus.iot.server.transfer.core.api.Sink; -import com.zmops.zeus.iot.server.transfer.core.api.Source; +import com.zmops.zeus.iot.server.transfer.api.Channel; +import com.zmops.zeus.iot.server.transfer.api.Reader; +import com.zmops.zeus.iot.server.transfer.api.Sink; +import com.zmops.zeus.iot.server.transfer.api.Source; import com.zmops.zeus.iot.server.transfer.core.channel.MemoryChannel; import com.zmops.zeus.iot.server.transfer.core.sink.NdjsonSink; import com.zmops.zeus.iot.server.transfer.core.source.TextFileSource; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java index 9cc96b51..de075b5b 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java @@ -4,11 +4,11 @@ import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; -import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; -import com.zmops.zeus.iot.server.transfer.core.common.AgentThreadFactory; +import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; +import com.zmops.zeus.iot.server.transfer.common.TransferThreadFactory; import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; import com.zmops.zeus.iot.server.transfer.core.db.StateSearchKey; -import com.zmops.zeus.iot.server.transfer.core.manager.TransferManager; +import com.zmops.zeus.iot.server.transfer.core.TransferManager; import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -61,7 +61,7 @@ public JobManager(TransferManager transferManager, JobProfileDb jobConfDb) { 0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>(), - new AgentThreadFactory("job")); + new TransferThreadFactory("job")); this.jobs = new ConcurrentHashMap<>(); this.pendingJobs = new ConcurrentHashMap<>(); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java index 1033165d..064c0dbd 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java @@ -1,10 +1,10 @@ package com.zmops.zeus.iot.server.transfer.core.job; -import com.zmops.zeus.iot.server.transfer.core.metrics.Metric; -import com.zmops.zeus.iot.server.transfer.core.metrics.Metrics; -import com.zmops.zeus.iot.server.transfer.core.metrics.MetricsRegister; -import com.zmops.zeus.iot.server.transfer.core.metrics.gauge.GaugeInt; +import com.zmops.zeus.iot.server.transfer.metrics.Metric; +import com.zmops.zeus.iot.server.transfer.metrics.Metrics; +import com.zmops.zeus.iot.server.transfer.metrics.MetricsRegister; +import com.zmops.zeus.iot.server.transfer.metrics.gauge.GaugeInt; import java.util.concurrent.atomic.AtomicBoolean; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java index 59719148..6daff282 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java @@ -3,7 +3,7 @@ import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; -import com.zmops.zeus.iot.server.transfer.core.manager.TransferManager; +import com.zmops.zeus.iot.server.transfer.core.TransferManager; import com.zmops.zeus.iot.server.transfer.core.state.AbstractStateWrapper; import com.zmops.zeus.iot.server.transfer.core.state.State; import com.zmops.zeus.iot.server.transfer.core.task.Task; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/DefaultMessage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/DefaultMessage.java index a755ad0a..2d6dfd0b 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/DefaultMessage.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/DefaultMessage.java @@ -1,6 +1,6 @@ package com.zmops.zeus.iot.server.transfer.core.message; -import com.zmops.zeus.iot.server.transfer.core.api.Message; +import com.zmops.zeus.iot.server.transfer.api.Message; import java.nio.charset.StandardCharsets; import java.util.HashMap; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/EndMessage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/EndMessage.java index 3ec03969..5b702d5e 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/EndMessage.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/EndMessage.java @@ -1,6 +1,6 @@ package com.zmops.zeus.iot.server.transfer.core.message; -import com.zmops.zeus.iot.server.transfer.core.api.Message; +import com.zmops.zeus.iot.server.transfer.api.Message; import java.util.HashMap; import java.util.Map; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java index 64031547..ab860371 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java @@ -1,6 +1,6 @@ package com.zmops.zeus.iot.server.transfer.core.message; -import com.zmops.zeus.iot.server.transfer.core.api.Message; +import com.zmops.zeus.iot.server.transfer.api.Message; import java.util.Map; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java index 63933bc4..48e8075a 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java @@ -2,9 +2,9 @@ import com.zmops.zeus.iot.server.transfer.conf.CommonConstants; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.core.api.Message; -import com.zmops.zeus.iot.server.transfer.core.api.Sink; -import com.zmops.zeus.iot.server.transfer.core.common.AgentThreadFactory; +import com.zmops.zeus.iot.server.transfer.api.Message; +import com.zmops.zeus.iot.server.transfer.api.Sink; +import com.zmops.zeus.iot.server.transfer.common.TransferThreadFactory; import com.zmops.zeus.iot.server.transfer.core.message.EndMessage; import com.zmops.zeus.iot.server.transfer.core.message.PackProxyMessage; import com.zmops.zeus.iot.server.transfer.core.message.ProxyMessage; @@ -39,7 +39,7 @@ public class NdjsonSink implements Sink { private int maxQueueNumber; private final ExecutorService executorService = - new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new AgentThreadFactory("ProxySink")); + new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new TransferThreadFactory("ProxySink")); private volatile boolean shutdown = false; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java index d593eb2f..b7765dae 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java @@ -1,7 +1,7 @@ package com.zmops.zeus.iot.server.transfer.core.sink; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.core.metrics.PluginMetric; +import com.zmops.zeus.iot.server.transfer.metrics.PluginMetric; import com.zmops.zeus.iot.server.transfer.core.task.TaskPositionManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java index cf5f1a8f..39519189 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java @@ -2,8 +2,8 @@ import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.core.api.Reader; -import com.zmops.zeus.iot.server.transfer.core.api.Source; +import com.zmops.zeus.iot.server.transfer.api.Reader; +import com.zmops.zeus.iot.server.transfer.api.Source; import com.zmops.zeus.iot.server.transfer.core.source.reader.TextFileReader; import com.zmops.zeus.iot.server.transfer.core.utils.FileSearchUtils; import org.slf4j.Logger; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java index d1fa87ff..0d3be884 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java @@ -1,12 +1,12 @@ package com.zmops.zeus.iot.server.transfer.core.source.reader; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.core.api.Message; -import com.zmops.zeus.iot.server.transfer.core.api.Reader; -import com.zmops.zeus.iot.server.transfer.core.api.Validator; -import com.zmops.zeus.iot.server.transfer.core.exception.FileException; +import com.zmops.zeus.iot.server.transfer.api.Message; +import com.zmops.zeus.iot.server.transfer.api.Reader; +import com.zmops.zeus.iot.server.transfer.api.Validator; +import com.zmops.zeus.iot.server.transfer.core.FileException; import com.zmops.zeus.iot.server.transfer.core.message.DefaultMessage; -import com.zmops.zeus.iot.server.transfer.core.metrics.PluginMetric; +import com.zmops.zeus.iot.server.transfer.metrics.PluginMetric; import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; import com.zmops.zeus.iot.server.transfer.core.validator.PatternValidator; import org.apache.commons.lang3.StringUtils; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java index d61339fa..e9bf734b 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java @@ -1,9 +1,9 @@ package com.zmops.zeus.iot.server.transfer.core.task; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.core.api.Channel; -import com.zmops.zeus.iot.server.transfer.core.api.Reader; -import com.zmops.zeus.iot.server.transfer.core.api.Sink; +import com.zmops.zeus.iot.server.transfer.api.Channel; +import com.zmops.zeus.iot.server.transfer.api.Reader; +import com.zmops.zeus.iot.server.transfer.api.Sink; /** diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java index c67faf23..c1b48a17 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java @@ -3,10 +3,10 @@ import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; -import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; -import com.zmops.zeus.iot.server.transfer.core.common.AgentThreadFactory; +import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; +import com.zmops.zeus.iot.server.transfer.common.TransferThreadFactory; import com.zmops.zeus.iot.server.transfer.core.job.JobManager; -import com.zmops.zeus.iot.server.transfer.core.manager.TransferManager; +import com.zmops.zeus.iot.server.transfer.core.TransferManager; import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,7 +45,7 @@ public TaskManager(TransferManager transferManager) { 0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>(), - new AgentThreadFactory("task")); + new TransferThreadFactory("task")); // metric for task level taskMetrics = TaskMetrics.create(); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java index beb77554..2ae4a896 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java @@ -1,10 +1,10 @@ package com.zmops.zeus.iot.server.transfer.core.task; -import com.zmops.zeus.iot.server.transfer.core.metrics.Metric; -import com.zmops.zeus.iot.server.transfer.core.metrics.Metrics; -import com.zmops.zeus.iot.server.transfer.core.metrics.MetricsRegister; -import com.zmops.zeus.iot.server.transfer.core.metrics.counter.CounterLong; -import com.zmops.zeus.iot.server.transfer.core.metrics.gauge.GaugeInt; +import com.zmops.zeus.iot.server.transfer.metrics.Metric; +import com.zmops.zeus.iot.server.transfer.metrics.Metrics; +import com.zmops.zeus.iot.server.transfer.metrics.MetricsRegister; +import com.zmops.zeus.iot.server.transfer.metrics.counter.CounterLong; +import com.zmops.zeus.iot.server.transfer.metrics.gauge.GaugeInt; import java.util.concurrent.atomic.AtomicBoolean; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java index 6f200c98..a1ac3c46 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java @@ -2,9 +2,9 @@ import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; +import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; -import com.zmops.zeus.iot.server.transfer.core.manager.TransferManager; +import com.zmops.zeus.iot.server.transfer.core.TransferManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java index 3e436f34..13de322c 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java @@ -3,9 +3,9 @@ import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; -import com.zmops.zeus.iot.server.transfer.core.api.Message; -import com.zmops.zeus.iot.server.transfer.core.common.AgentThreadFactory; -import com.zmops.zeus.iot.server.transfer.core.manager.TransferManager; +import com.zmops.zeus.iot.server.transfer.api.Message; +import com.zmops.zeus.iot.server.transfer.common.TransferThreadFactory; +import com.zmops.zeus.iot.server.transfer.core.TransferManager; import com.zmops.zeus.iot.server.transfer.core.message.EndMessage; import com.zmops.zeus.iot.server.transfer.core.state.AbstractStateWrapper; import com.zmops.zeus.iot.server.transfer.core.state.State; @@ -50,7 +50,7 @@ public TaskWrapper(TransferManager manager, Task task) { executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue(), - new AgentThreadFactory("task-reader-writer")); + new TransferThreadFactory("task-reader-writer")); } doChangeState(State.ACCEPTED); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java index 6e0c30b9..1f4fe564 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java @@ -4,8 +4,8 @@ import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; -import com.zmops.zeus.iot.server.transfer.core.api.Trigger; -import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; +import com.zmops.zeus.iot.server.transfer.api.Trigger; +import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; import com.zmops.zeus.iot.server.transfer.core.utils.FileSearchUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java index 84e772d4..2786814d 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java @@ -4,11 +4,11 @@ import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; -import com.zmops.zeus.iot.server.transfer.core.api.Trigger; -import com.zmops.zeus.iot.server.transfer.core.common.AbstractDaemon; +import com.zmops.zeus.iot.server.transfer.api.Trigger; +import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; import com.zmops.zeus.iot.server.transfer.core.db.TriggerProfileDb; import com.zmops.zeus.iot.server.transfer.core.job.JobWrapper; -import com.zmops.zeus.iot.server.transfer.core.manager.TransferManager; +import com.zmops.zeus.iot.server.transfer.core.TransferManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PatternValidator.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PatternValidator.java index ad0a4fd5..67b87b9f 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PatternValidator.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PatternValidator.java @@ -1,7 +1,7 @@ package com.zmops.zeus.iot.server.transfer.core.validator; -import com.zmops.zeus.iot.server.transfer.core.api.Validator; +import com.zmops.zeus.iot.server.transfer.api.Validator; public class PatternValidator implements Validator { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PrefixValidator.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PrefixValidator.java index 23fcaa77..b349dd2a 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PrefixValidator.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PrefixValidator.java @@ -1,6 +1,6 @@ package com.zmops.zeus.iot.server.transfer.core.validator; -import com.zmops.zeus.iot.server.transfer.core.api.Validator; +import com.zmops.zeus.iot.server.transfer.api.Validator; public class PrefixValidator implements Validator { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/AgentDynamicMBean.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/AgentDynamicMBean.java similarity index 94% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/AgentDynamicMBean.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/AgentDynamicMBean.java index 9ee7e5c9..4838b3ed 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/AgentDynamicMBean.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/AgentDynamicMBean.java @@ -1,7 +1,7 @@ -package com.zmops.zeus.iot.server.transfer.core.metrics; +package com.zmops.zeus.iot.server.transfer.metrics; -import com.zmops.zeus.iot.server.transfer.core.metrics.meta.MetricMeta; -import com.zmops.zeus.iot.server.transfer.core.metrics.meta.MetricsMeta; +import com.zmops.zeus.iot.server.transfer.metrics.meta.MetricMeta; +import com.zmops.zeus.iot.server.transfer.metrics.meta.MetricsMeta; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metric.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Metric.java similarity index 94% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metric.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Metric.java index 6c90406d..dc57eb64 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metric.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Metric.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.metrics; +package com.zmops.zeus.iot.server.transfer.metrics; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricException.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricException.java similarity index 80% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricException.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricException.java index 99262d04..b6c5705b 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricException.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricException.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.metrics; +package com.zmops.zeus.iot.server.transfer.metrics; public class MetricException extends RuntimeException { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricSnapshot.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricSnapshot.java similarity index 50% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricSnapshot.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricSnapshot.java index 47d89de9..9eb658c9 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricSnapshot.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricSnapshot.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.metrics; +package com.zmops.zeus.iot.server.transfer.metrics; public interface MetricSnapshot { T snapshot(); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metrics.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Metrics.java similarity index 90% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metrics.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Metrics.java index 03fc295b..2e71f1ff 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Metrics.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Metrics.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.metrics; +package com.zmops.zeus.iot.server.transfer.metrics; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricsRegister.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricsRegister.java similarity index 90% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricsRegister.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricsRegister.java index 72899517..649411be 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MetricsRegister.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricsRegister.java @@ -1,12 +1,12 @@ -package com.zmops.zeus.iot.server.transfer.core.metrics; +package com.zmops.zeus.iot.server.transfer.metrics; -import com.zmops.zeus.iot.server.transfer.core.metrics.counter.CounterInt; -import com.zmops.zeus.iot.server.transfer.core.metrics.counter.CounterLong; -import com.zmops.zeus.iot.server.transfer.core.metrics.gauge.GaugeInt; -import com.zmops.zeus.iot.server.transfer.core.metrics.gauge.GaugeLong; -import com.zmops.zeus.iot.server.transfer.core.metrics.meta.MetricMeta; -import com.zmops.zeus.iot.server.transfer.core.metrics.meta.MetricsMeta; +import com.zmops.zeus.iot.server.transfer.metrics.counter.CounterInt; +import com.zmops.zeus.iot.server.transfer.metrics.counter.CounterLong; +import com.zmops.zeus.iot.server.transfer.metrics.gauge.GaugeInt; +import com.zmops.zeus.iot.server.transfer.metrics.gauge.GaugeLong; +import com.zmops.zeus.iot.server.transfer.metrics.meta.MetricMeta; +import com.zmops.zeus.iot.server.transfer.metrics.meta.MetricsMeta; import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MutableMetric.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MutableMetric.java similarity index 63% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MutableMetric.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MutableMetric.java index cefef8d6..f2f78b27 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/MutableMetric.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MutableMetric.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.metrics; +package com.zmops.zeus.iot.server.transfer.metrics; /** * Metric with number diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/PluginMetric.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/PluginMetric.java similarity index 81% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/PluginMetric.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/PluginMetric.java index 6c0cdf2a..e6dd7cee 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/PluginMetric.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/PluginMetric.java @@ -1,6 +1,6 @@ -package com.zmops.zeus.iot.server.transfer.core.metrics; +package com.zmops.zeus.iot.server.transfer.metrics; -import com.zmops.zeus.iot.server.transfer.core.metrics.counter.CounterLong; +import com.zmops.zeus.iot.server.transfer.metrics.counter.CounterLong; /** * Common plugin metrics diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Tag.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Tag.java similarity index 86% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Tag.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Tag.java index c3b8250c..304a0ceb 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/Tag.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Tag.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.metrics; +package com.zmops.zeus.iot.server.transfer.metrics; public class Tag implements MetricSnapshot { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/Counter.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/Counter.java similarity index 58% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/Counter.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/Counter.java index 9c64fc24..e4f8b1da 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/Counter.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/Counter.java @@ -1,7 +1,7 @@ -package com.zmops.zeus.iot.server.transfer.core.metrics.counter; +package com.zmops.zeus.iot.server.transfer.metrics.counter; -import com.zmops.zeus.iot.server.transfer.core.metrics.MutableMetric; +import com.zmops.zeus.iot.server.transfer.metrics.MutableMetric; public interface Counter extends MutableMetric { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterInt.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/CounterInt.java similarity index 86% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterInt.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/CounterInt.java index 8e0cc454..44dc09af 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterInt.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/CounterInt.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.metrics.counter; +package com.zmops.zeus.iot.server.transfer.metrics.counter; import java.util.concurrent.atomic.AtomicInteger; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterLong.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/CounterLong.java similarity index 87% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterLong.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/CounterLong.java index ba7fac22..47cb4761 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/counter/CounterLong.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/CounterLong.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.metrics.counter; +package com.zmops.zeus.iot.server.transfer.metrics.counter; import java.util.concurrent.atomic.AtomicLong; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/Gauge.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/Gauge.java similarity index 71% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/Gauge.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/Gauge.java index 0f4fc4e0..904e8530 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/Gauge.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/Gauge.java @@ -1,6 +1,6 @@ -package com.zmops.zeus.iot.server.transfer.core.metrics.gauge; +package com.zmops.zeus.iot.server.transfer.metrics.gauge; -import com.zmops.zeus.iot.server.transfer.core.metrics.MutableMetric; +import com.zmops.zeus.iot.server.transfer.metrics.MutableMetric; public interface Gauge extends MutableMetric { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeInt.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/GaugeInt.java similarity index 91% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeInt.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/GaugeInt.java index 9779bc88..82fb941e 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeInt.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/GaugeInt.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.metrics.gauge; +package com.zmops.zeus.iot.server.transfer.metrics.gauge; import java.util.concurrent.atomic.AtomicInteger; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeLong.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/GaugeLong.java similarity index 91% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeLong.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/GaugeLong.java index aa7a54da..f8e9c71c 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/gauge/GaugeLong.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/GaugeLong.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.metrics.gauge; +package com.zmops.zeus.iot.server.transfer.metrics.gauge; import java.util.concurrent.atomic.AtomicLong; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricMeta.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricMeta.java similarity index 72% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricMeta.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricMeta.java index 73be1dfc..43c2ae60 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricMeta.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricMeta.java @@ -1,15 +1,15 @@ -package com.zmops.zeus.iot.server.transfer.core.metrics.meta; +package com.zmops.zeus.iot.server.transfer.metrics.meta; -import com.zmops.zeus.iot.server.transfer.core.metrics.Metric; -import com.zmops.zeus.iot.server.transfer.core.metrics.counter.CounterInt; -import com.zmops.zeus.iot.server.transfer.core.metrics.counter.CounterLong; -import com.zmops.zeus.iot.server.transfer.core.metrics.gauge.GaugeInt; -import com.zmops.zeus.iot.server.transfer.core.metrics.gauge.GaugeLong; +import com.zmops.zeus.iot.server.transfer.metrics.Metric; +import com.zmops.zeus.iot.server.transfer.metrics.counter.CounterInt; +import com.zmops.zeus.iot.server.transfer.metrics.counter.CounterLong; +import com.zmops.zeus.iot.server.transfer.metrics.gauge.GaugeInt; +import com.zmops.zeus.iot.server.transfer.metrics.gauge.GaugeLong; import org.apache.commons.lang3.StringUtils; import java.lang.reflect.Field; -import static com.zmops.zeus.iot.server.transfer.core.metrics.Metric.Type.*; +import static com.zmops.zeus.iot.server.transfer.metrics.Metric.Type.*; /** * this class is related to {@link Metric} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricsMeta.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricsMeta.java similarity index 88% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricsMeta.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricsMeta.java index 20b58669..c4bf7ac3 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/metrics/meta/MetricsMeta.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricsMeta.java @@ -1,6 +1,6 @@ -package com.zmops.zeus.iot.server.transfer.core.metrics.meta; +package com.zmops.zeus.iot.server.transfer.metrics.meta; -import com.zmops.zeus.iot.server.transfer.core.metrics.Metrics; +import com.zmops.zeus.iot.server.transfer.metrics.Metrics; import java.util.List; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java index 6f3282eb..37ae8164 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java @@ -2,7 +2,7 @@ import com.zmops.zeus.iot.server.core.CoreModule; import com.zmops.zeus.iot.server.library.module.*; -import com.zmops.zeus.iot.server.transfer.core.manager.TransferManager; +import com.zmops.zeus.iot.server.transfer.core.TransferManager; import com.zmops.zeus.iot.server.transfer.module.ServerTransferModule; import org.slf4j.Logger; import org.slf4j.LoggerFactory; From 112f8ea62114b14780966c2bb2947fec64fa1440 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 12:49:36 +0800 Subject: [PATCH 279/763] [style]: optimize package structure --- .../zeus/iot/server/transfer/conf/AbstractConfiguration.java | 2 +- .../zmops/zeus/iot/server/transfer/conf/TransferConstants.java | 2 +- .../zeus/iot/server/transfer/core/filter/DateFormatRegex.java | 2 +- .../zmops/zeus/iot/server/transfer/core/job/JobManager.java | 2 +- .../zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java | 3 ++- .../zeus/iot/server/transfer/core/source/TextFileSource.java | 2 +- .../iot/server/transfer/core/source/reader/TextFileReader.java | 2 +- .../zmops/zeus/iot/server/transfer/core/task/TaskManager.java | 2 +- .../iot/server/transfer/core/trigger/DirectoryTrigger.java | 2 +- .../zeus/iot/server/transfer/metrics/MetricsRegister.java | 2 +- .../server/transfer/{core/sink => sender}/SenderManager.java | 2 +- .../iot/server/transfer/{core => }/utils/FileSearchUtils.java | 2 +- .../iot/server/transfer/{core => }/utils/TransferUtils.java | 2 +- 13 files changed, 14 insertions(+), 13 deletions(-) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core/sink => sender}/SenderManager.java (97%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/utils/FileSearchUtils.java (98%) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/{core => }/utils/TransferUtils.java (99%) diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java index 4dc89b39..47cf3d88 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java @@ -1,7 +1,7 @@ package com.zmops.zeus.iot.server.transfer.conf; import com.google.gson.*; -import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; +import com.zmops.zeus.iot.server.transfer.utils.TransferUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java index f43e6344..360189ec 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java @@ -1,6 +1,6 @@ package com.zmops.zeus.iot.server.transfer.conf; -import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; +import com.zmops.zeus.iot.server.transfer.utils.TransferUtils; public class TransferConstants { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java index 4e565fa3..fc84862a 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java @@ -1,7 +1,7 @@ package com.zmops.zeus.iot.server.transfer.core.filter; import com.zmops.zeus.iot.server.transfer.api.Filter; -import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; +import com.zmops.zeus.iot.server.transfer.utils.TransferUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java index de075b5b..933defda 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java @@ -9,7 +9,7 @@ import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; import com.zmops.zeus.iot.server.transfer.core.db.StateSearchKey; import com.zmops.zeus.iot.server.transfer.core.TransferManager; -import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; +import com.zmops.zeus.iot.server.transfer.utils.TransferUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java index 48e8075a..ca0fba1b 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java @@ -8,7 +8,8 @@ import com.zmops.zeus.iot.server.transfer.core.message.EndMessage; import com.zmops.zeus.iot.server.transfer.core.message.PackProxyMessage; import com.zmops.zeus.iot.server.transfer.core.message.ProxyMessage; -import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; +import com.zmops.zeus.iot.server.transfer.sender.SenderManager; +import com.zmops.zeus.iot.server.transfer.utils.TransferUtils; import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java index 39519189..831e012c 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java @@ -5,7 +5,7 @@ import com.zmops.zeus.iot.server.transfer.api.Reader; import com.zmops.zeus.iot.server.transfer.api.Source; import com.zmops.zeus.iot.server.transfer.core.source.reader.TextFileReader; -import com.zmops.zeus.iot.server.transfer.core.utils.FileSearchUtils; +import com.zmops.zeus.iot.server.transfer.utils.FileSearchUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java index 0d3be884..5fc2e7fd 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java @@ -7,7 +7,7 @@ import com.zmops.zeus.iot.server.transfer.core.FileException; import com.zmops.zeus.iot.server.transfer.core.message.DefaultMessage; import com.zmops.zeus.iot.server.transfer.metrics.PluginMetric; -import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; +import com.zmops.zeus.iot.server.transfer.utils.TransferUtils; import com.zmops.zeus.iot.server.transfer.core.validator.PatternValidator; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java index c1b48a17..2a4da702 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java @@ -7,7 +7,7 @@ import com.zmops.zeus.iot.server.transfer.common.TransferThreadFactory; import com.zmops.zeus.iot.server.transfer.core.job.JobManager; import com.zmops.zeus.iot.server.transfer.core.TransferManager; -import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; +import com.zmops.zeus.iot.server.transfer.utils.TransferUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java index 1f4fe564..2e4c7fd2 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java @@ -6,7 +6,7 @@ import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; import com.zmops.zeus.iot.server.transfer.api.Trigger; import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; -import com.zmops.zeus.iot.server.transfer.core.utils.FileSearchUtils; +import com.zmops.zeus.iot.server.transfer.utils.FileSearchUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricsRegister.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricsRegister.java index 649411be..d82b342c 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricsRegister.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricsRegister.java @@ -7,7 +7,7 @@ import com.zmops.zeus.iot.server.transfer.metrics.gauge.GaugeLong; import com.zmops.zeus.iot.server.transfer.metrics.meta.MetricMeta; import com.zmops.zeus.iot.server.transfer.metrics.meta.MetricsMeta; -import com.zmops.zeus.iot.server.transfer.core.utils.TransferUtils; +import com.zmops.zeus.iot.server.transfer.utils.TransferUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java similarity index 97% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java index b7765dae..4a0e1690 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/SenderManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.sink; +package com.zmops.zeus.iot.server.transfer.sender; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.metrics.PluginMetric; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/FileSearchUtils.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/FileSearchUtils.java similarity index 98% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/FileSearchUtils.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/FileSearchUtils.java index 14fa1863..2154bb5b 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/FileSearchUtils.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/FileSearchUtils.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.utils; +package com.zmops.zeus.iot.server.transfer.utils; import com.zmops.zeus.iot.server.transfer.conf.JobConstants; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/TransferUtils.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/TransferUtils.java similarity index 99% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/TransferUtils.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/TransferUtils.java index 19ea148d..7a2d5319 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/utils/TransferUtils.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/TransferUtils.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.transfer.core.utils; +package com.zmops.zeus.iot.server.transfer.utils; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.StringUtils; From 89c7c17b280320359af6d8a994d70a13431093f3 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 24 Sep 2021 13:45:08 +0800 Subject: [PATCH 280/763] [fix]: remove taos jdbc --- .../src/main/resources/application.yaml | 7 +--- .../tdengine/JdbcConnectionInitializer.java | 38 +++++++++---------- 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index dda39c76..a18e00f7 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -51,9 +51,4 @@ forest: zbxApiToken: 5376d4510465d6873d6c41076f26c58dae42701941e276971e8f068b76e660d0 nats: - url: nats://${NATS_HOST:127.0.0.1}:${NATS_PORT:4222} - -taos: - url: jdbc:TAOS://${TAOS_HOST:127.0.0.1}:${TAOS_PORT:6030}/zeus_data - username: root - password: taosdata \ No newline at end of file + url: nats://${NATS_HOST:127.0.0.1}:${NATS_PORT:4222} \ No newline at end of file diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionInitializer.java b/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionInitializer.java index 6371704f..dd73ba0d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionInitializer.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionInitializer.java @@ -9,27 +9,27 @@ @Component public class JdbcConnectionInitializer implements InitializingBean { - @Value("${taos.url}") - public String url; - @Value("${taos.username}") - public String username; - @Value("${taos.password}") - public String password; +// @Value("${taos.url}") +// public String url; +// @Value("${taos.username}") +// public String username; +// @Value("${taos.password}") +// public String password; @Override public void afterPropertiesSet() throws Exception { - DruidDataSource dataSource = new DruidDataSource(); - dataSource.setDriverClassName("com.taosdata.jdbc.TSDBDriver"); - dataSource.setUrl(url); - dataSource.setUsername(username); - dataSource.setPassword(password); - - dataSource.setInitialSize(10); - dataSource.setMinIdle(10); - dataSource.setMaxActive(10); - dataSource.setMaxWait(30000); - dataSource.setValidationQuery("select server_status()"); - JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); - JdbcConnectionHolder.INSTANCE.setConnection(new JdbcTemplateConnection(jdbcTemplate)); +// DruidDataSource dataSource = new DruidDataSource(); +// dataSource.setDriverClassName("com.taosdata.jdbc.TSDBDriver"); +// dataSource.setUrl(url); +// dataSource.setUsername(username); +// dataSource.setPassword(password); +// +// dataSource.setInitialSize(10); +// dataSource.setMinIdle(10); +// dataSource.setMaxActive(10); +// dataSource.setMaxWait(30000); +// dataSource.setValidationQuery("select server_status()"); +// JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); +// JdbcConnectionHolder.INSTANCE.setConnection(new JdbcTemplateConnection(jdbcTemplate)); } } From 90fed2eaaf17981e91e6c69cfc3a983264f90a9a Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 13:52:21 +0800 Subject: [PATCH 281/763] [fix]: remove unused code --- .../iot/web/tdengine/JdbcConnection.java | 15 ------ .../web/tdengine/JdbcConnectionHolder.java | 19 ------- .../tdengine/JdbcConnectionInitializer.java | 35 ------------- .../web/tdengine/JdbcTemplateConnection.java | 35 ------------- .../controller/EventTriggerController.java | 52 ------------------- .../iot/web/trigger/dto/TriggerStatusDto.java | 25 --------- 6 files changed, 181 deletions(-) delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnection.java delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionHolder.java delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionInitializer.java delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcTemplateConnection.java delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/trigger/controller/EventTriggerController.java delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/trigger/dto/TriggerStatusDto.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnection.java b/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnection.java deleted file mode 100644 index a8733418..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnection.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.zmops.iot.web.tdengine; - -import org.springframework.dao.DataAccessException; - -import java.util.List; -import java.util.Map; - -public interface JdbcConnection { - - - List> queryForList(String sql) throws DataAccessException; - - - void execute(final String sql) throws DataAccessException; -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionHolder.java b/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionHolder.java deleted file mode 100644 index b2bf2131..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionHolder.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.zmops.iot.web.tdengine; - -/** - * jdbcConnection singleton - **/ -public enum JdbcConnectionHolder { - - INSTANCE; - - private JdbcConnection connection; - - public JdbcConnection getConnection() { - return connection; - } - - public void setConnection(JdbcConnection connection) { - this.connection = connection; - } -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionInitializer.java b/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionInitializer.java deleted file mode 100644 index 6371704f..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionInitializer.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.zmops.iot.web.tdengine; - -import com.alibaba.druid.pool.DruidDataSource; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.stereotype.Component; - -@Component -public class JdbcConnectionInitializer implements InitializingBean { - - @Value("${taos.url}") - public String url; - @Value("${taos.username}") - public String username; - @Value("${taos.password}") - public String password; - - @Override - public void afterPropertiesSet() throws Exception { - DruidDataSource dataSource = new DruidDataSource(); - dataSource.setDriverClassName("com.taosdata.jdbc.TSDBDriver"); - dataSource.setUrl(url); - dataSource.setUsername(username); - dataSource.setPassword(password); - - dataSource.setInitialSize(10); - dataSource.setMinIdle(10); - dataSource.setMaxActive(10); - dataSource.setMaxWait(30000); - dataSource.setValidationQuery("select server_status()"); - JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); - JdbcConnectionHolder.INSTANCE.setConnection(new JdbcTemplateConnection(jdbcTemplate)); - } -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcTemplateConnection.java b/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcTemplateConnection.java deleted file mode 100644 index 3f975218..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcTemplateConnection.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.zmops.iot.web.tdengine; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.dao.DataAccessException; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.util.Assert; - -import java.util.List; -import java.util.Map; - -/** - * 只读的jdbcTemplate - * - * @author yefei - */ -@Slf4j -public class JdbcTemplateConnection implements JdbcConnection { - - private JdbcTemplate jdbcTemplate; - - public JdbcTemplateConnection(JdbcTemplate jdbcTemplate) { - Assert.state(jdbcTemplate != null, "jdbcTemplate could not be null"); - this.jdbcTemplate = jdbcTemplate; - } - - @Override - public List> queryForList(String sql) throws DataAccessException { - return jdbcTemplate.queryForList(sql); - } - - @Override - public void execute(String sql) throws DataAccessException { - jdbcTemplate.execute(sql); - } -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/controller/EventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/controller/EventTriggerController.java deleted file mode 100644 index 3971b1eb..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/controller/EventTriggerController.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.zmops.iot.web.trigger.controller; - -import com.alibaba.fastjson.JSON; -import com.zmops.iot.model.response.ResponseData; -import com.zmops.iot.web.trigger.dto.TriggerStatusDto; -import com.zmops.zeus.driver.service.ZbxTrigger; -import lombok.Getter; -import lombok.Setter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.validation.Valid; - -/** - * @author nantian created at 2021/9/20 14:53 - *

- * 通用触发器相关 - */ - -@RestController -@RequestMapping("/event/trigger") -public class EventTriggerController { - - - @Autowired - private ZbxTrigger zbxTrigger; - - /** - * 修改 设备 产品 告警规则启用禁用 - * - * @return - */ -// @RequestMapping("/status/update") -// public ResponseData updateTriggerStatus(@RequestBody @Valid TriggerStatusDto statusDto) { -// String res = zbxTrigger.triggerStatusUpdate(statusDto.getTriggerId(), statusDto.getStatus()); -// -//// DB.update(ProductEvent.class) -//// .where().eq("eventRuleId", statusDto.getEventRuleId()) -//// .asUpdate().set("status", statusDto.getStatus()).update(); // 0 启用,1 禁用 -// -// -// return ResponseData.success(JSON.parseObject(res, TriggerIds.class).getTriggerids()[0]); -// } - - @Getter - @Setter - static class TriggerIds { - private String[] triggerids; - } -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/dto/TriggerStatusDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/dto/TriggerStatusDto.java deleted file mode 100644 index 3c7915e5..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/trigger/dto/TriggerStatusDto.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.zmops.iot.web.trigger.dto; - -import lombok.Getter; -import lombok.Setter; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Pattern; - -/** - * @author nantian created at 2021/9/20 15:37 - */ - -@Getter -@Setter -public class TriggerStatusDto { - - @NotBlank - private String triggerId; - - @Pattern(regexp = "^[01]$") - private String status; - - @NotBlank - private String eventRuleId; -} From 21f65e2261ffd0862f260688890ad02e43af288e Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 13:53:19 +0800 Subject: [PATCH 282/763] [ftx]: delete unused code --- .../tdengine/JdbcConnectionInitializer.java | 35 ------------------- 1 file changed, 35 deletions(-) delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionInitializer.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionInitializer.java b/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionInitializer.java deleted file mode 100644 index dd73ba0d..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/tdengine/JdbcConnectionInitializer.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.zmops.iot.web.tdengine; - -import com.alibaba.druid.pool.DruidDataSource; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.stereotype.Component; - -@Component -public class JdbcConnectionInitializer implements InitializingBean { - -// @Value("${taos.url}") -// public String url; -// @Value("${taos.username}") -// public String username; -// @Value("${taos.password}") -// public String password; - - @Override - public void afterPropertiesSet() throws Exception { -// DruidDataSource dataSource = new DruidDataSource(); -// dataSource.setDriverClassName("com.taosdata.jdbc.TSDBDriver"); -// dataSource.setUrl(url); -// dataSource.setUsername(username); -// dataSource.setPassword(password); -// -// dataSource.setInitialSize(10); -// dataSource.setMinIdle(10); -// dataSource.setMaxActive(10); -// dataSource.setMaxWait(30000); -// dataSource.setValidationQuery("select server_status()"); -// JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); -// JdbcConnectionHolder.INSTANCE.setConnection(new JdbcTemplateConnection(jdbcTemplate)); - } -} From 0855f4c04bb231475996e505dc725b22b2456323 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 24 Sep 2021 14:03:50 +0800 Subject: [PATCH 283/763] [fix]: remove taos jdbc --- .../device/schedule/SyncTaosTagSchedule.java | 142 ++++++++---------- 1 file changed, 65 insertions(+), 77 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java index 72593abd..a2bb83b1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java @@ -1,23 +1,11 @@ package com.zmops.iot.web.device.schedule; -import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.domain.device.Tag; -import com.zmops.iot.domain.device.query.QDevice; -import com.zmops.iot.domain.device.query.QTag; -import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.tdengine.JdbcConnectionHolder; -import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.service.ZbxItem; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - /** * @author yefei **/ @@ -29,70 +17,70 @@ public class SyncTaosTagSchedule { @Autowired ZbxItem zbxItem; - @Scheduled(cron = "0 01 12 1/1 * ? ") - public void sync() { - List deviceIds = new QDevice().select(QDevice.alias().deviceId).findSingleAttributeList(); - List tagList = new QTag().sid.in(deviceIds).findList(); - if (ToolUtil.isEmpty(tagList)) { - return; - } - Map> tagMap = tagList.parallelStream().collect(Collectors.groupingBy(Tag::getSid)); - List> historyDesc = JdbcConnectionHolder.INSTANCE.getConnection().queryForList("DESCRIBE history"); - List taosTagNames = historyDesc.parallelStream().filter(o -> "TAG".equals(new String((byte[]) o.get("Note")))).map(o -> new String((byte[]) o.get("Field"))) - .collect(Collectors.toList()); - - if (ToolUtil.isEmpty(taosTagNames)) { - return; - } - List tagNames = tagList.parallelStream().map(Tag::getTag).collect(Collectors.toList()); - //新增taos没有的标签 - addTaosTag(tagNames, taosTagNames); - //删除taos标签 - delTaosTag(taosTagNames, tagNames); - - //更新子表 标签值 - tagMap.forEach((deviceId, tags) -> { - //根据deviceId 找到 设备下所有itemId - String hostid = new QDevice().select(QDevice.alias().zbxId).deviceId.eq(deviceId).findSingleAttribute(); - if (ToolUtil.isEmpty(hostid)) { - return; - } - List itemInfos = JSONObject.parseArray(zbxItem.getItemList(null, hostid), ZbxItemInfo.class); - List itemIds = itemInfos.parallelStream().map(ZbxItemInfo::getItemid).collect(Collectors.toList()); - - itemIds.forEach(itemId -> { - tags.forEach(tag -> { - JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER TABLE history_uint SET TAG " + tag.getTag() + "=" + tag.getValue()); - }); - }); - - }); - } - - private void delTaosTag(List list1, List list2) { - List tagNames = list2; - List taosTagNames = list1; - taosTagNames.removeAll(tagNames); - if (ToolUtil.isEmpty(taosTagNames)) { - return; - } - taosTagNames.forEach(tagName -> { - JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER STABLE history_uint DROP TAG " + tagName); - JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER STABLE history DROP TAG " + tagName); - }); - } - - private void addTaosTag(List list1, List list2) { - List tagNames = list1; - List taosTagNames = list2; - tagNames.removeAll(taosTagNames); - if (ToolUtil.isEmpty(tagNames)) { - return; - } - tagNames.forEach(tagName -> { - JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER STABLE history_uint ADD TAG " + tagName + " NCHAR(16)"); - JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER STABLE history ADD TAG " + tagName + " NCHAR(16)"); - }); - } +// @Scheduled(cron = "0 01 12 1/1 * ? ") +// public void sync() { +// List deviceIds = new QDevice().select(QDevice.alias().deviceId).findSingleAttributeList(); +// List tagList = new QTag().sid.in(deviceIds).findList(); +// if (ToolUtil.isEmpty(tagList)) { +// return; +// } +// Map> tagMap = tagList.parallelStream().collect(Collectors.groupingBy(Tag::getSid)); +// List> historyDesc = JdbcConnectionHolder.INSTANCE.getConnection().queryForList("DESCRIBE history"); +// List taosTagNames = historyDesc.parallelStream().filter(o -> "TAG".equals(new String((byte[]) o.get("Note")))).map(o -> new String((byte[]) o.get("Field"))) +// .collect(Collectors.toList()); +// +// if (ToolUtil.isEmpty(taosTagNames)) { +// return; +// } +// List tagNames = tagList.parallelStream().map(Tag::getTag).collect(Collectors.toList()); +// //新增taos没有的标签 +// addTaosTag(tagNames, taosTagNames); +// //删除taos标签 +// delTaosTag(taosTagNames, tagNames); +// +// //更新子表 标签值 +// tagMap.forEach((deviceId, tags) -> { +// //根据deviceId 找到 设备下所有itemId +// String hostid = new QDevice().select(QDevice.alias().zbxId).deviceId.eq(deviceId).findSingleAttribute(); +// if (ToolUtil.isEmpty(hostid)) { +// return; +// } +// List itemInfos = JSONObject.parseArray(zbxItem.getItemList(null, hostid), ZbxItemInfo.class); +// List itemIds = itemInfos.parallelStream().map(ZbxItemInfo::getItemid).collect(Collectors.toList()); +// +// itemIds.forEach(itemId -> { +// tags.forEach(tag -> { +// JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER TABLE history_uint SET TAG " + tag.getTag() + "=" + tag.getValue()); +// }); +// }); +// +// }); +// } +// +// private void delTaosTag(List list1, List list2) { +// List tagNames = list2; +// List taosTagNames = list1; +// taosTagNames.removeAll(tagNames); +// if (ToolUtil.isEmpty(taosTagNames)) { +// return; +// } +// taosTagNames.forEach(tagName -> { +// JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER STABLE history_uint DROP TAG " + tagName); +// JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER STABLE history DROP TAG " + tagName); +// }); +// } +// +// private void addTaosTag(List list1, List list2) { +// List tagNames = list1; +// List taosTagNames = list2; +// tagNames.removeAll(taosTagNames); +// if (ToolUtil.isEmpty(tagNames)) { +// return; +// } +// tagNames.forEach(tagName -> { +// JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER STABLE history_uint ADD TAG " + tagName + " NCHAR(16)"); +// JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER STABLE history ADD TAG " + tagName + " NCHAR(16)"); +// }); +// } } From 36fb26d049f210d0deff3c355248ad134cf9db9e Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 24 Sep 2021 14:29:45 +0800 Subject: [PATCH 284/763] [feat]: update transfer module --- .../server/transfer/sender/SenderManager.java | 52 ++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java index 4a0e1690..67b9c918 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java @@ -1,12 +1,21 @@ package com.zmops.zeus.iot.server.transfer.sender; +import com.google.gson.Gson; +import com.zmops.zeus.iot.server.core.analysis.manual.history.History; +import com.zmops.zeus.iot.server.core.analysis.manual.history.UIntHistory; +import com.zmops.zeus.iot.server.core.analysis.record.Record; +import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; +import com.zmops.zeus.iot.server.core.servlet.DataTransferHandler; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.metrics.PluginMetric; import com.zmops.zeus.iot.server.transfer.core.task.TaskPositionManager; +import lombok.Getter; +import lombok.Setter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; @@ -19,7 +28,8 @@ public class SenderManager { private final TaskPositionManager taskPositionManager; private final String sourceFilePath; - private final PluginMetric metric = new PluginMetric(); + private final PluginMetric metric = new PluginMetric(); + private final Gson gson = new Gson(); public SenderManager(JobProfile jobConf, String bid, String sourceFilePath) { taskPositionManager = TaskPositionManager.getTaskPositionManager(); @@ -36,7 +46,22 @@ public SenderManager(JobProfile jobConf, String bid, String sourceFilePath) { */ public void sendBatch(String jobId, String bid, String tid, List bodyList, int retry, long dataTime) { try { -// RecordStreamProcessor.getInstance().in(record); //TODO + bodyList.forEach(body->{ + ItemValue itemValue = gson.fromJson(new String(body), ItemValue.class); + + Record record; + + if (itemValue.getType() == 3) { //uint + record = new UIntHistory(); + } else { + record = new History(); + } + + record.setItemid(itemValue.itemid); + record.setValue(itemValue.getHost().get("host"), itemValue.value, itemValue.getTimestamp()); + + RecordStreamProcessor.getInstance().in(record); + }); metric.sendSuccessNum.incr(bodyList.size()); taskPositionManager.updateFileSinkPosition(jobId, sourceFilePath, bodyList.size()); @@ -52,4 +77,27 @@ public void sendBatch(String jobId, String bid, String tid, List bodyLis } } } + + @Setter + @Getter + static class ItemValue { + + private Integer type; + + private String name; + + private Long clock; + + private Integer itemid; + + private Long ns; + + private String value; + + private Map host; + + public Long getTimestamp() { + return Long.valueOf(clock + String.format("%09d", ns).substring(0, 3)); + } + } } From 3fdbc7e11d607f374904a92b6d65d1bb9035bb6f Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 24 Sep 2021 14:37:52 +0800 Subject: [PATCH 285/763] [fix]: update transfer module --- .../iot/server/transfer/sender/SenderManager.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java index 67b9c918..75f891fc 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java @@ -5,10 +5,9 @@ import com.zmops.zeus.iot.server.core.analysis.manual.history.UIntHistory; import com.zmops.zeus.iot.server.core.analysis.record.Record; import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; -import com.zmops.zeus.iot.server.core.servlet.DataTransferHandler; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.metrics.PluginMetric; import com.zmops.zeus.iot.server.transfer.core.task.TaskPositionManager; +import com.zmops.zeus.iot.server.transfer.metrics.PluginMetric; import lombok.Getter; import lombok.Setter; import org.slf4j.Logger; @@ -28,8 +27,8 @@ public class SenderManager { private final TaskPositionManager taskPositionManager; private final String sourceFilePath; - private final PluginMetric metric = new PluginMetric(); - private final Gson gson = new Gson(); + private final PluginMetric metric = new PluginMetric(); + private final Gson gson = new Gson(); public SenderManager(JobProfile jobConf, String bid, String sourceFilePath) { taskPositionManager = TaskPositionManager.getTaskPositionManager(); @@ -46,15 +45,17 @@ public SenderManager(JobProfile jobConf, String bid, String sourceFilePath) { */ public void sendBatch(String jobId, String bid, String tid, List bodyList, int retry, long dataTime) { try { - bodyList.forEach(body->{ + bodyList.forEach(body -> { ItemValue itemValue = gson.fromJson(new String(body), ItemValue.class); Record record; if (itemValue.getType() == 3) { //uint record = new UIntHistory(); - } else { + } else if (itemValue.getType() == 0) { record = new History(); + } else { + return; } record.setItemid(itemValue.itemid); From 838ff09cbfc177e6dfc8d3ae374b60720f7876f5 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 14:45:09 +0800 Subject: [PATCH 286/763] [style]: remove unused import class --- .../zmops/zeus/iot/server/transfer/sender/SenderManager.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java index 67b9c918..5944a528 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java @@ -5,10 +5,9 @@ import com.zmops.zeus.iot.server.core.analysis.manual.history.UIntHistory; import com.zmops.zeus.iot.server.core.analysis.record.Record; import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; -import com.zmops.zeus.iot.server.core.servlet.DataTransferHandler; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.metrics.PluginMetric; import com.zmops.zeus.iot.server.transfer.core.task.TaskPositionManager; +import com.zmops.zeus.iot.server.transfer.metrics.PluginMetric; import lombok.Getter; import lombok.Setter; import org.slf4j.Logger; From 04ecb7946ea0114a8c547aeb8d49a7ba51bd4397 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 15:08:38 +0800 Subject: [PATCH 287/763] [fix]: frontend-maven-plugin npm cache clean --- zeus-starter/pom.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index 374adceb..d0db3885 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -92,6 +92,15 @@ install --registry=https://registry.npm.taobao.org/ + + npm clean + + npm + + + cache clean --force + + npm run build From 4de260fd79b251a8d1486bbb8f4b57e0b3184b37 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 15:37:35 +0800 Subject: [PATCH 288/763] [style]: optimize imports global --- .../eventbus/core/EventControllerFactory.java | 2 -- .../iot/server/starter/IoTServerBootstrap.java | 2 +- .../starter/config/ApplicationConfigLoader.java | 5 ++--- .../com/zmops/zeus/iot/server/core/CoreModule.java | 1 - .../core/analysis/manual/history/History.java | 1 - .../core/analysis/manual/history/UIntHistory.java | 1 - .../server/core/servlet/DataTransferHandler.java | 1 - .../iot/server/core/worker/data/ItemValue.java | 5 ----- .../checker/provider/HealthCheckerProvider.java | 2 -- .../checker/provider/HealthQueryService.java | 1 - .../library/server/ssl/AbstractSslContext.java | 1 - .../receiver/tcp/provider/TcpRouteBuilder.java | 1 - .../server/sender/provider/ZabbixSenderClient.java | 1 - .../server-tdengine-plugin/pom.xml | 2 +- .../server/storage/plugin/jdbc/SQLExecutor.java | 1 - .../jdbc/tdengine/dao/TDEngineSqlExecutor.java | 2 -- .../zeus/iot/server/telemetry/TelemetryModule.java | 2 +- .../server/telemetry/prometheus/BaseMetrics.java | 2 +- .../prometheus/PrometheusCounterMetrics.java | 2 +- .../prometheus/PrometheusGaugeMetrics.java | 2 +- .../prometheus/PrometheusHistogramMetrics.java | 2 +- .../prometheus/PrometheusMetricsCollector.java | 4 ++-- .../prometheus/httpserver/HttpServer.java | 3 +-- .../iot/server/transfer/core/TransferManager.java | 2 +- .../transfer/core/channel/MemoryChannel.java | 4 ++-- .../zeus/iot/server/transfer/core/job/Job.java | 4 ++-- .../iot/server/transfer/core/job/JobManager.java | 6 +++--- .../iot/server/transfer/core/sink/NdjsonSink.java | 4 ++-- .../transfer/core/source/TextFileSource.java | 2 +- .../core/source/reader/TextFileReader.java | 4 ++-- .../zeus/iot/server/transfer/core/task/Task.java | 2 +- .../iot/server/transfer/core/task/TaskManager.java | 6 +++--- .../transfer/core/task/TaskPositionManager.java | 4 ++-- .../iot/server/transfer/core/task/TaskWrapper.java | 4 ++-- .../transfer/core/trigger/DirectoryTrigger.java | 4 ++-- .../transfer/core/trigger/TriggerManager.java | 6 +++--- .../com/zmops/iot/mediaType/WebhookCallback.java | 13 ------------- .../iot/mediaType/feishu/FeishuHookCallback.java | 7 +++++-- .../iot/mediaType/feishu/FeishuSettingService.java | 1 - .../iot/mediaType/wechat/WechatSettingService.java | 2 -- .../iot/mediaType/welink/WeLinkSettingService.java | 1 - .../com/zmops/iot/async/wrapper/WorkerWrapper.java | 14 +------------- .../main/java/com/zmops/iot/domain/device/Tag.java | 3 --- .../com/zmops/iot/domain/messages/Messages.java | 2 -- .../java/com/zmops/iot/domain/product/Product.java | 4 +++- .../iot/domain/product/ProductEventRelation.java | 3 ++- .../product/ProductStatusFunctionRelation.java | 1 - .../java/com/zmops/iot/domain/sys/SysDict.java | 1 - .../java/com/zmops/iot/util/DefinitionsUtil.java | 1 - .../zmops/iot/core/auth/context/LoginContext.java | 2 -- .../auth/filter/JwtAuthorizationTokenFilter.java | 1 - .../main/java/com/zmops/iot/core/util/RsaUtil.java | 1 - .../driver/service/ZbxDeviceStatusTrigger.java | 2 -- .../iot/config/security/WebSecurityConfig.java | 2 -- .../java/com/zmops/iot/config/web/WebConfig.java | 2 -- .../iot/config/zbxapi/ZbxApiInfoValidation.java | 1 - .../iot/web/device/dto/param/DeviceParam.java | 2 -- .../web/device/service/work/SaveOtherWorker.java | 1 - .../zmops/iot/web/log/factory/LogTaskFactory.java | 1 - .../ProductAttributeEventController.java | 3 --- .../controller/ProductStatusTriggerController.java | 1 - .../service/work/AsyncAttrEventZbxIdWorker.java | 1 - .../service/work/SaveProdStatusTriggerWorker.java | 1 - .../service/work/UpdateAttributeEventWorker.java | 1 - .../product/service/work/UpdateProdSvcWorker.java | 8 -------- .../iot/web/sys/controller/DictTypeController.java | 5 ++++- .../iot/web/sys/controller/LogController.java | 1 - .../iot/web/sys/controller/LoginController.java | 8 ++++---- .../iot/web/sys/controller/LoginLogController.java | 1 - .../com/zmops/iot/web/sys/dto/SysLoginLogDto.java | 5 ----- .../zmops/iot/web/sys/dto/SysOperationLogDto.java | 5 ----- .../zmops/iot/web/sys/service/DictTypeService.java | 1 - 72 files changed, 57 insertions(+), 150 deletions(-) diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java index 7434a937..60b9ad41 100644 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java @@ -3,8 +3,6 @@ import com.google.common.eventbus.AsyncEventBus; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.SubscriberExceptionHandler; - - import com.zmops.zeus.iot.server.eventbus.constant.EventConstant; import com.zmops.zeus.iot.server.eventbus.thread.ThreadPoolFactory; diff --git a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java index c5cf80bb..f31c85dc 100644 --- a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java +++ b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java @@ -19,9 +19,9 @@ package com.zmops.zeus.iot.server.starter; import com.zmops.zeus.iot.server.core.RunningMode; -import com.zmops.zeus.iot.server.starter.config.ApplicationConfigLoader; import com.zmops.zeus.iot.server.library.module.ApplicationConfiguration; import com.zmops.zeus.iot.server.library.module.ModuleManager; +import com.zmops.zeus.iot.server.starter.config.ApplicationConfigLoader; import com.zmops.zeus.iot.server.telemetry.TelemetryModule; import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; diff --git a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java index b8401390..d3cb5131 100644 --- a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java +++ b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java @@ -18,13 +18,12 @@ package com.zmops.zeus.iot.server.starter.config; -import com.zmops.zeus.iot.server.library.util.CollectionUtils; -import com.zmops.zeus.iot.server.library.util.ResourceUtils; import com.zmops.zeus.iot.server.library.module.ApplicationConfiguration; import com.zmops.zeus.iot.server.library.module.ProviderNotFoundException; +import com.zmops.zeus.iot.server.library.util.CollectionUtils; +import com.zmops.zeus.iot.server.library.util.ResourceUtils; import com.zmops.zeus.iot.server.util.PropertyPlaceholderHelper; import lombok.extern.slf4j.Slf4j; - import org.yaml.snakeyaml.Yaml; import java.io.FileNotFoundException; diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModule.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModule.java index 4ba8bfc5..75ae6962 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModule.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModule.java @@ -3,7 +3,6 @@ import com.zmops.zeus.iot.server.core.camel.CamelContextHolderService; import com.zmops.zeus.iot.server.core.eventbus.EventBusService; import com.zmops.zeus.iot.server.core.server.JettyHandlerRegister; -import com.zmops.zeus.iot.server.core.servlet.HttpItemTrapperHandler; import com.zmops.zeus.iot.server.library.module.ModuleDefine; import java.util.ArrayList; diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java index 1ccf63d5..7dc547f8 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java @@ -3,7 +3,6 @@ import com.zmops.zeus.iot.server.core.analysis.Stream; import com.zmops.zeus.iot.server.core.analysis.record.Record; import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; -import com.zmops.zeus.iot.server.core.storage.StorageData; import lombok.Getter; import lombok.Setter; diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java index 883114a5..e8978868 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java @@ -3,7 +3,6 @@ import com.zmops.zeus.iot.server.core.analysis.Stream; import com.zmops.zeus.iot.server.core.analysis.record.Record; import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; - import lombok.Getter; import lombok.Setter; diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java index abfc5709..143109c8 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java @@ -15,7 +15,6 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; -import java.util.Arrays; import java.util.Map; import java.util.zip.GZIPInputStream; diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ItemValue.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ItemValue.java index 1e767ea4..c0cd1d9a 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ItemValue.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ItemValue.java @@ -1,13 +1,8 @@ package com.zmops.zeus.iot.server.core.worker.data; -import afu.org.checkerframework.checker.igj.qual.I; -import com.zmops.zeus.iot.server.core.camel.IOTDeviceValue; import lombok.Getter; import lombok.Setter; -import java.util.ArrayList; -import java.util.List; - /** * @author nantian created at 2021/8/23 15:15 */ diff --git a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerProvider.java b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerProvider.java index 8a7faa6e..cf4834f2 100644 --- a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerProvider.java +++ b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerProvider.java @@ -21,14 +21,12 @@ import com.google.common.util.concurrent.AtomicDouble; import com.zmops.zeus.iot.server.health.checker.module.HealthCheckerModule; import com.zmops.zeus.iot.server.library.module.*; - import com.zmops.zeus.iot.server.telemetry.TelemetryModule; import com.zmops.zeus.iot.server.telemetry.api.MetricsCollector; import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; import io.vavr.collection.Stream; import lombok.extern.slf4j.Slf4j; - import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; diff --git a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthQueryService.java b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthQueryService.java index 46cfd820..14232807 100644 --- a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthQueryService.java +++ b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthQueryService.java @@ -24,7 +24,6 @@ import lombok.RequiredArgsConstructor; import lombok.Setter; - import java.util.concurrent.atomic.AtomicReference; @RequiredArgsConstructor diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/AbstractSslContext.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/AbstractSslContext.java index 466d5b31..cbb47fb8 100644 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/AbstractSslContext.java +++ b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/AbstractSslContext.java @@ -25,7 +25,6 @@ import lombok.AccessLevel; import lombok.Setter; - import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLSessionContext; import java.util.List; diff --git a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpRouteBuilder.java b/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpRouteBuilder.java index a0f45d22..b1a7a377 100644 --- a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpRouteBuilder.java +++ b/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpRouteBuilder.java @@ -1,6 +1,5 @@ package com.zmops.zeus.iot.server.receiver.tcp.provider; -import com.zmops.zeus.iot.server.core.camel.process.ByteArrayToItemValueProcess; import com.zmops.zeus.iot.server.core.camel.process.StringItemValueProcess; import org.apache.camel.builder.RouteBuilder; diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderClient.java b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderClient.java index 498c632e..ab708690 100644 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderClient.java +++ b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderClient.java @@ -1,6 +1,5 @@ package com.zmops.zeus.iot.server.sender.provider; -import com.zmops.zeus.iot.server.sender.provider.ZabbixSenderModuleConfig; import lombok.extern.slf4j.Slf4j; import java.net.InetSocketAddress; diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml index c0eff4b9..5573d5c3 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml @@ -20,7 +20,7 @@ com.taosdata.jdbc taos-jdbcdriver - 2.0.31 + 2.0.30 com.zmops diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java index 1e6931ad..2c9e0a34 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java @@ -19,7 +19,6 @@ package com.zmops.zeus.iot.server.storage.plugin.jdbc; import com.zmops.zeus.iot.server.library.client.request.InsertRequest; - import lombok.Getter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java index ad9fd779..0efa9263 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java @@ -2,7 +2,6 @@ import com.zmops.zeus.iot.server.core.analysis.manual.history.History; import com.zmops.zeus.iot.server.core.analysis.manual.history.UIntHistory; -import com.zmops.zeus.iot.server.core.analysis.record.Record; import com.zmops.zeus.iot.server.core.storage.StorageData; import com.zmops.zeus.iot.server.storage.plugin.jdbc.SQLBuilder; import com.zmops.zeus.iot.server.storage.plugin.jdbc.SQLExecutor; @@ -10,7 +9,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Map; /** * @author nantian created at 2021/9/5 0:29 diff --git a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/TelemetryModule.java b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/TelemetryModule.java index 2a48563b..a72a0bad 100644 --- a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/TelemetryModule.java +++ b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/TelemetryModule.java @@ -18,9 +18,9 @@ package com.zmops.zeus.iot.server.telemetry; +import com.zmops.zeus.iot.server.library.module.ModuleDefine; import com.zmops.zeus.iot.server.telemetry.api.MetricsCollector; import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; -import com.zmops.zeus.iot.server.library.module.ModuleDefine; /** * Telemetry module definition diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/BaseMetrics.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/BaseMetrics.java index cefd247c..82b22d3b 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/BaseMetrics.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/BaseMetrics.java @@ -18,9 +18,9 @@ package com.zmops.zeus.iot.server.telemetry.prometheus; -import io.prometheus.client.SimpleCollector; import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; import com.zmops.zeus.iot.server.telemetry.api.TelemetryRelatedContext; +import io.prometheus.client.SimpleCollector; import java.util.HashMap; import java.util.Map; diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusCounterMetrics.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusCounterMetrics.java index 42f814ef..42f580ee 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusCounterMetrics.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusCounterMetrics.java @@ -18,9 +18,9 @@ package com.zmops.zeus.iot.server.telemetry.prometheus; -import io.prometheus.client.Counter; import com.zmops.zeus.iot.server.telemetry.api.CounterMetrics; import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; +import io.prometheus.client.Counter; /** * Counter metrics in Prometheus implementor. diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusGaugeMetrics.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusGaugeMetrics.java index 11480d08..07004589 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusGaugeMetrics.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusGaugeMetrics.java @@ -18,9 +18,9 @@ package com.zmops.zeus.iot.server.telemetry.prometheus; -import io.prometheus.client.Gauge; import com.zmops.zeus.iot.server.telemetry.api.GaugeMetrics; import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; +import io.prometheus.client.Gauge; import java.util.Optional; diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusHistogramMetrics.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusHistogramMetrics.java index 3b4d8ccb..83d18ed3 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusHistogramMetrics.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusHistogramMetrics.java @@ -18,9 +18,9 @@ package com.zmops.zeus.iot.server.telemetry.prometheus; -import io.prometheus.client.Histogram; import com.zmops.zeus.iot.server.telemetry.api.HistogramMetrics; import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; +import io.prometheus.client.Histogram; /** * HistogramMetrics metrics in Prometheus implementor. diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCollector.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCollector.java index 34934e39..08d647a6 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCollector.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCollector.java @@ -18,10 +18,10 @@ package com.zmops.zeus.iot.server.telemetry.prometheus; -import io.prometheus.client.Collector; -import io.prometheus.client.CollectorRegistry; import com.zmops.zeus.iot.server.telemetry.api.MetricFamily; import com.zmops.zeus.iot.server.telemetry.api.MetricsCollector; +import io.prometheus.client.Collector; +import io.prometheus.client.CollectorRegistry; import java.util.ArrayList; import java.util.Enumeration; diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServer.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServer.java index 0ef00847..e38df0b2 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServer.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServer.java @@ -20,6 +20,7 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.zmops.zeus.iot.server.library.server.ssl.HttpDynamicSslContext; +import com.zmops.zeus.iot.server.telemetry.prometheus.PrometheusConfig; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; @@ -29,8 +30,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import com.zmops.zeus.iot.server.telemetry.prometheus.PrometheusConfig; - import java.util.Optional; import java.util.concurrent.ThreadFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/TransferManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/TransferManager.java index d6eeedac..bbffccdf 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/TransferManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/TransferManager.java @@ -1,10 +1,10 @@ package com.zmops.zeus.iot.server.transfer.core; +import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; -import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; import com.zmops.zeus.iot.server.transfer.core.db.Db; import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; import com.zmops.zeus.iot.server.transfer.core.db.TriggerProfileDb; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java index dac4fb98..bad87241 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java @@ -1,10 +1,10 @@ package com.zmops.zeus.iot.server.transfer.core.channel; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.api.Channel; import com.zmops.zeus.iot.server.transfer.api.Message; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; +import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.metrics.PluginMetric; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java index 6d6d6c3d..fbcc07bf 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java @@ -1,12 +1,12 @@ package com.zmops.zeus.iot.server.transfer.core.job; -import com.zmops.zeus.iot.server.transfer.conf.JobConstants; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.api.Channel; import com.zmops.zeus.iot.server.transfer.api.Reader; import com.zmops.zeus.iot.server.transfer.api.Sink; import com.zmops.zeus.iot.server.transfer.api.Source; +import com.zmops.zeus.iot.server.transfer.conf.JobConstants; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.core.channel.MemoryChannel; import com.zmops.zeus.iot.server.transfer.core.sink.NdjsonSink; import com.zmops.zeus.iot.server.transfer.core.source.TextFileSource; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java index 933defda..9221a64f 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java @@ -1,14 +1,14 @@ package com.zmops.zeus.iot.server.transfer.core.job; +import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; +import com.zmops.zeus.iot.server.transfer.common.TransferThreadFactory; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; -import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; -import com.zmops.zeus.iot.server.transfer.common.TransferThreadFactory; +import com.zmops.zeus.iot.server.transfer.core.TransferManager; import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; import com.zmops.zeus.iot.server.transfer.core.db.StateSearchKey; -import com.zmops.zeus.iot.server.transfer.core.TransferManager; import com.zmops.zeus.iot.server.transfer.utils.TransferUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java index ca0fba1b..2a206121 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java @@ -1,10 +1,10 @@ package com.zmops.zeus.iot.server.transfer.core.sink; -import com.zmops.zeus.iot.server.transfer.conf.CommonConstants; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.api.Message; import com.zmops.zeus.iot.server.transfer.api.Sink; import com.zmops.zeus.iot.server.transfer.common.TransferThreadFactory; +import com.zmops.zeus.iot.server.transfer.conf.CommonConstants; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.core.message.EndMessage; import com.zmops.zeus.iot.server.transfer.core.message.PackProxyMessage; import com.zmops.zeus.iot.server.transfer.core.message.ProxyMessage; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java index 831e012c..381ee0c5 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java @@ -1,9 +1,9 @@ package com.zmops.zeus.iot.server.transfer.core.source; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.api.Reader; import com.zmops.zeus.iot.server.transfer.api.Source; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.core.source.reader.TextFileReader; import com.zmops.zeus.iot.server.transfer.utils.FileSearchUtils; import org.slf4j.Logger; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java index 5fc2e7fd..3524cb73 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java @@ -1,14 +1,14 @@ package com.zmops.zeus.iot.server.transfer.core.source.reader; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.api.Message; import com.zmops.zeus.iot.server.transfer.api.Reader; import com.zmops.zeus.iot.server.transfer.api.Validator; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.core.FileException; import com.zmops.zeus.iot.server.transfer.core.message.DefaultMessage; +import com.zmops.zeus.iot.server.transfer.core.validator.PatternValidator; import com.zmops.zeus.iot.server.transfer.metrics.PluginMetric; import com.zmops.zeus.iot.server.transfer.utils.TransferUtils; -import com.zmops.zeus.iot.server.transfer.core.validator.PatternValidator; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java index e9bf734b..f8a8ee2d 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java @@ -1,9 +1,9 @@ package com.zmops.zeus.iot.server.transfer.core.task; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.api.Channel; import com.zmops.zeus.iot.server.transfer.api.Reader; import com.zmops.zeus.iot.server.transfer.api.Sink; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; /** diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java index 2a4da702..9a1f0df9 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java @@ -1,12 +1,12 @@ package com.zmops.zeus.iot.server.transfer.core.task; -import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; -import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; import com.zmops.zeus.iot.server.transfer.common.TransferThreadFactory; -import com.zmops.zeus.iot.server.transfer.core.job.JobManager; +import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; +import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.core.TransferManager; +import com.zmops.zeus.iot.server.transfer.core.job.JobManager; import com.zmops.zeus.iot.server.transfer.utils.TransferUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java index a1ac3c46..bda77d53 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java @@ -1,10 +1,10 @@ package com.zmops.zeus.iot.server.transfer.core.task; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; -import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; +import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.core.TransferManager; +import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java index 13de322c..2d90edc1 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java @@ -1,10 +1,10 @@ package com.zmops.zeus.iot.server.transfer.core.task; -import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; -import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.api.Message; import com.zmops.zeus.iot.server.transfer.common.TransferThreadFactory; +import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; +import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.core.TransferManager; import com.zmops.zeus.iot.server.transfer.core.message.EndMessage; import com.zmops.zeus.iot.server.transfer.core.state.AbstractStateWrapper; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java index 2e4c7fd2..f9403f63 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java @@ -1,11 +1,11 @@ package com.zmops.zeus.iot.server.transfer.core.trigger; +import com.zmops.zeus.iot.server.transfer.api.Trigger; +import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; import com.zmops.zeus.iot.server.transfer.conf.JobConstants; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; -import com.zmops.zeus.iot.server.transfer.api.Trigger; -import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; import com.zmops.zeus.iot.server.transfer.utils.FileSearchUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java index 2786814d..57976607 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java @@ -1,14 +1,14 @@ package com.zmops.zeus.iot.server.transfer.core.trigger; +import com.zmops.zeus.iot.server.transfer.api.Trigger; +import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; -import com.zmops.zeus.iot.server.transfer.api.Trigger; -import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; +import com.zmops.zeus.iot.server.transfer.core.TransferManager; import com.zmops.zeus.iot.server.transfer.core.db.TriggerProfileDb; import com.zmops.zeus.iot.server.transfer.core.job.JobWrapper; -import com.zmops.zeus.iot.server.transfer.core.TransferManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/WebhookCallback.java b/zeus-alarm/src/main/java/com/zmops/iot/mediaType/WebhookCallback.java index c9df1217..c4812b03 100644 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/WebhookCallback.java +++ b/zeus-alarm/src/main/java/com/zmops/iot/mediaType/WebhookCallback.java @@ -19,22 +19,9 @@ package com.zmops.iot.mediaType; import com.zmops.iot.domain.alarm.AlarmMessage; -import io.netty.handler.codec.http.HttpHeaderValues; import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpHeaders; -import org.apache.http.HttpStatus; -import org.apache.http.StatusLine; import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.charset.StandardCharsets; import java.util.List; /** diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuHookCallback.java b/zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuHookCallback.java index 623359b3..342c80de 100644 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuHookCallback.java +++ b/zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuHookCallback.java @@ -25,6 +25,7 @@ import com.zmops.iot.util.ToolUtil; import io.netty.handler.codec.http.HttpHeaderValues; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.Base64; import org.apache.http.HttpHeaders; import org.apache.http.HttpStatus; import org.apache.http.StatusLine; @@ -38,14 +39,16 @@ import org.apache.http.util.EntityUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.apache.commons.codec.binary.Base64; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.io.IOException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; -import java.util.*; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; /** diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettingService.java b/zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettingService.java index 05979b85..97953434 100644 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettingService.java +++ b/zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettingService.java @@ -3,7 +3,6 @@ import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.alarm.MediaTypeSetting; import com.zmops.iot.domain.alarm.query.QMediaTypeSetting; -import com.zmops.iot.mediaType.dingtalk.DingtalkSettings; import org.springframework.stereotype.Service; import java.util.Arrays; diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettingService.java b/zeus-alarm/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettingService.java index e0fae096..3eeb95b2 100644 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettingService.java +++ b/zeus-alarm/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettingService.java @@ -3,11 +3,9 @@ import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.alarm.MediaTypeSetting; import com.zmops.iot.domain.alarm.query.QMediaTypeSetting; -import com.zmops.iot.mediaType.dingtalk.DingtalkSettings; import org.springframework.stereotype.Service; import java.util.Arrays; -import java.util.Optional; /** * @author yefei diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettingService.java b/zeus-alarm/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettingService.java index 5541b056..f9508843 100644 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettingService.java +++ b/zeus-alarm/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettingService.java @@ -3,7 +3,6 @@ import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.alarm.MediaTypeSetting; import com.zmops.iot.domain.alarm.query.QMediaTypeSetting; -import com.zmops.iot.mediaType.wechat.WechatSettings; import org.springframework.stereotype.Service; import java.util.Arrays; diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapper.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapper.java index 9b5c1fd4..ec7c1998 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapper.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapper.java @@ -25,19 +25,7 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.AFTER_WORK; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.BUILDING; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.ERROR; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.INIT; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.SKIP; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.STARTED; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.SUCCESS; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.isState; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.of; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.setState; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.states_all; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.states_of_beforeWorkingEnd; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.states_of_notWorked; +import static com.zmops.iot.async.wrapper.WorkerWrapper.State.*; /** * 对每个worker及callback进行包装,一对一 diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/Tag.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/Tag.java index b2f2ef90..c2aac102 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/Tag.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/Tag.java @@ -1,14 +1,11 @@ package com.zmops.iot.domain.device; -import com.zmops.iot.constant.IdTypeConsts; import com.zmops.iot.domain.BaseEntity; import lombok.*; import javax.persistence.Entity; -import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; -import java.sql.PreparedStatement; /** * @author yefei diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/messages/Messages.java b/zeus-common/src/main/java/com/zmops/iot/domain/messages/Messages.java index fd2846da..279dc409 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/messages/Messages.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/messages/Messages.java @@ -1,12 +1,10 @@ package com.zmops.iot.domain.messages; -import com.zmops.iot.constant.IdTypeConsts; import lombok.Data; import lombok.EqualsAndHashCode; import javax.persistence.Entity; -import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/Product.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/Product.java index 7f793713..452d34e2 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/Product.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/Product.java @@ -4,7 +4,9 @@ import lombok.Data; import lombok.EqualsAndHashCode; -import javax.persistence.*; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; /** * @author nantian created at 2021/8/3 20:08 diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java index ada9ba2a..ffd7542d 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java @@ -1,6 +1,7 @@ package com.zmops.iot.domain.product; -import lombok.*; +import lombok.Getter; +import lombok.Setter; import javax.persistence.Entity; import javax.persistence.Id; diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java index cd225aeb..5dce86ff 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java @@ -1,6 +1,5 @@ package com.zmops.iot.domain.product; -import com.zmops.iot.domain.BaseEntity; import lombok.Getter; import lombok.Setter; diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysDict.java b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysDict.java index 197199ca..d6635b17 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysDict.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysDict.java @@ -1,6 +1,5 @@ package com.zmops.iot.domain.sys; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.zmops.iot.constant.IdTypeConsts; import com.zmops.iot.domain.BaseEntity; import lombok.Data; diff --git a/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java b/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java index 9c41a73a..5e2cffd2 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java @@ -1,7 +1,6 @@ package com.zmops.iot.util; import com.google.common.collect.Table; -import com.zmops.iot.domain.product.ProductType; import com.zmops.iot.domain.sys.SysUser; import com.zmops.iot.model.cache.DictionaryCache; import com.zmops.iot.model.cache.ProductTypeCache; diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/context/LoginContext.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/context/LoginContext.java index 16e2cb8b..c71eed99 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/context/LoginContext.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/context/LoginContext.java @@ -2,8 +2,6 @@ import com.zmops.iot.core.auth.model.LoginUser; -import java.util.List; - /** * 当前登录用户信息获取的接口 * diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/JwtAuthorizationTokenFilter.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/JwtAuthorizationTokenFilter.java index cda66bee..23341bfe 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/JwtAuthorizationTokenFilter.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/JwtAuthorizationTokenFilter.java @@ -5,7 +5,6 @@ import com.zmops.iot.core.auth.jwt.JwtTokenUtil; import com.zmops.iot.core.auth.util.TokenUtil; import com.zmops.iot.util.ToolUtil; - import io.jsonwebtoken.JwtException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; diff --git a/zeus-core/src/main/java/com/zmops/iot/core/util/RsaUtil.java b/zeus-core/src/main/java/com/zmops/iot/core/util/RsaUtil.java index 7d17670a..011b7ea3 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/util/RsaUtil.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/util/RsaUtil.java @@ -1,7 +1,6 @@ package com.zmops.iot.core.util; -import com.zmops.iot.util.ToolUtil; import org.apache.commons.codec.binary.Base64; import javax.crypto.Cipher; diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java index 89463188..9be26497 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java @@ -6,8 +6,6 @@ import com.zmops.zeus.driver.annotation.ParamName; import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; -import java.util.Map; - /** * @author nantian created at 2021/8/10 16:32 *

diff --git a/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java b/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java index 55baaf8a..1b05f61e 100644 --- a/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java +++ b/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java @@ -16,8 +16,6 @@ import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import java.util.List; - /** * @author nantian created at 2021/7/29 22:54 */ diff --git a/zeus-starter/src/main/java/com/zmops/iot/config/web/WebConfig.java b/zeus-starter/src/main/java/com/zmops/iot/config/web/WebConfig.java index 6d0469b7..4bb49796 100644 --- a/zeus-starter/src/main/java/com/zmops/iot/config/web/WebConfig.java +++ b/zeus-starter/src/main/java/com/zmops/iot/config/web/WebConfig.java @@ -2,13 +2,11 @@ import com.google.code.kaptcha.impl.DefaultKaptcha; import com.google.code.kaptcha.util.Config; -import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import java.util.Arrays; import java.util.Properties; /** diff --git a/zeus-starter/src/main/java/com/zmops/iot/config/zbxapi/ZbxApiInfoValidation.java b/zeus-starter/src/main/java/com/zmops/iot/config/zbxapi/ZbxApiInfoValidation.java index b2980ccd..041f01e3 100644 --- a/zeus-starter/src/main/java/com/zmops/iot/config/zbxapi/ZbxApiInfoValidation.java +++ b/zeus-starter/src/main/java/com/zmops/iot/config/zbxapi/ZbxApiInfoValidation.java @@ -4,7 +4,6 @@ import com.zmops.zeus.driver.service.ZbxApiInfo; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeansException; -import org.springframework.boot.ExitCodeGenerator; import org.springframework.boot.SpringApplication; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceParam.java index a9102f34..e821b397 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceParam.java @@ -3,8 +3,6 @@ import com.zmops.iot.web.sys.dto.param.BaseQueryParam; import lombok.Data; -import java.util.List; - /** * @author yefei **/ diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java index 5d24d3c6..78d7d46f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java @@ -21,7 +21,6 @@ import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.stream.Collectors; /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/log/factory/LogTaskFactory.java b/zeus-webapp/src/main/java/com/zmops/iot/web/log/factory/LogTaskFactory.java index 898ba8ff..e62c5d17 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/log/factory/LogTaskFactory.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/log/factory/LogTaskFactory.java @@ -16,7 +16,6 @@ package com.zmops.iot.web.log.factory; -import cn.hutool.core.util.IdUtil; import com.zmops.iot.domain.sys.SysLoginLog; import com.zmops.iot.domain.sys.SysOperationLog; import com.zmops.iot.util.ToolUtil; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java index d75afc88..94dba1a5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java @@ -3,18 +3,15 @@ import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSON; import com.zmops.iot.domain.BaseEntity; -import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.web.exception.enums.BizExceptionEnum; -import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.iot.web.product.dto.ProductAttrDto; import com.zmops.iot.web.product.dto.ProductAttrEvent; import com.zmops.iot.web.product.dto.param.ProductAttrParam; import com.zmops.iot.web.product.service.ProductAttributeEventService; -import com.zmops.iot.web.product.service.ProductModelService; import lombok.Data; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java index e64ee761..2812d32f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java @@ -7,7 +7,6 @@ import com.zmops.iot.domain.product.query.QProductStatusFunction; import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; import com.zmops.iot.model.exception.ServiceException; -import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductStatusJudgeRule; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java index 726b98e4..ec0f9736 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java @@ -7,7 +7,6 @@ import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.domain.product.query.QProductAttributeEvent; import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.iot.web.product.dto.ProductAttrEvent; import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.service.ZbxItem; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java index dd40a24f..f53b6c6d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java @@ -4,7 +4,6 @@ import com.zmops.iot.async.callback.IWorker; import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.query.QDevice; -import com.zmops.iot.domain.product.ProductServiceRelation; import com.zmops.iot.domain.product.ProductStatusFunctionRelation; import com.zmops.iot.web.product.dto.ProductServiceDto; import io.ebean.DB; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java index 38a56b6d..b918f0af 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java @@ -5,7 +5,6 @@ import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.domain.product.query.QProductAttributeEvent; -import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.iot.web.product.dto.ProductAttrEvent; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java index 66410bbb..53d4bd31 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java @@ -3,19 +3,11 @@ import com.zmops.iot.async.callback.IWorker; import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.product.ProductService; -import com.zmops.iot.domain.product.ProductServiceParam; -import com.zmops.iot.domain.product.query.QProductService; -import com.zmops.iot.domain.product.query.QProductServiceParam; -import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.product.dto.ProductServiceDto; -import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import java.util.List; import java.util.Map; -import java.util.stream.Collectors; /** * @author yefei diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictTypeController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictTypeController.java index 99c6c582..a4bbbbb0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictTypeController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictTypeController.java @@ -8,7 +8,10 @@ import com.zmops.iot.web.sys.service.DictTypeService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LogController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LogController.java index e21d3df9..dabb541f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LogController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LogController.java @@ -1,6 +1,5 @@ package com.zmops.iot.web.sys.controller; -import com.zmops.iot.domain.sys.SysOperationLog; import com.zmops.iot.model.page.Pager; import com.zmops.iot.web.sys.dto.SysOperationLogDto; import com.zmops.iot.web.sys.service.OperationLogService; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java index 9b683b22..7cdaa3c6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java @@ -4,7 +4,6 @@ import com.zmops.iot.constant.ConstantsContext; import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.core.web.base.BaseController; -import com.zmops.iot.domain.sys.SysUser; import com.zmops.iot.model.exception.InvalidKaptchaException; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.model.response.SuccessResponseData; @@ -15,11 +14,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; -import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; -import java.util.List; import java.util.Map; /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginLogController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginLogController.java index 9dbc203a..db7950f0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginLogController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginLogController.java @@ -1,6 +1,5 @@ package com.zmops.iot.web.sys.controller; -import com.zmops.iot.domain.sys.SysLoginLog; import com.zmops.iot.model.page.Pager; import com.zmops.iot.web.sys.dto.SysLoginLogDto; import com.zmops.iot.web.sys.service.LoginLogService; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysLoginLogDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysLoginLogDto.java index ec8d85bf..63227ae6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysLoginLogDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysLoginLogDto.java @@ -1,16 +1,11 @@ package com.zmops.iot.web.sys.dto; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.zmops.iot.constant.IdTypeConsts; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; import com.zmops.iot.model.cache.filter.DicType; import lombok.Data; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Table; import java.time.LocalDateTime; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysOperationLogDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysOperationLogDto.java index 8b77391e..25f3baff 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysOperationLogDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysOperationLogDto.java @@ -1,16 +1,11 @@ package com.zmops.iot.web.sys.dto; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.zmops.iot.constant.IdTypeConsts; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; import com.zmops.iot.model.cache.filter.DicType; import lombok.Data; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Table; import java.time.LocalDateTime; /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictTypeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictTypeService.java index 28d4c610..db4b237d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictTypeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictTypeService.java @@ -11,7 +11,6 @@ import com.zmops.iot.web.sys.dto.SysDictTypeDto; import com.zmops.iot.web.sys.dto.param.DictTypeParam; import io.ebean.DB; -import io.ebean.PagedList; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; From 4bfb7286b2f154caf652c63dddba8bf04453e08e Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 15:41:45 +0800 Subject: [PATCH 289/763] [feat]: update zeus-iot-ui submodule --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index 91e27b39..a1254de7 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit 91e27b391abd598e15a4ddad68db700f33760943 +Subproject commit a1254de7235a973b35ef86b05923dd327e583ba1 From dfb5b01957b99cced5c743eedcecdf67134a2957 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 15:55:30 +0800 Subject: [PATCH 290/763] [style]: update log level --- iot-server/server-bootstrap/src/main/resources/log4j2.xml | 2 +- .../iot/server/transfer/core/task/TaskPositionManager.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/iot-server/server-bootstrap/src/main/resources/log4j2.xml b/iot-server/server-bootstrap/src/main/resources/log4j2.xml index f197f205..a5f5ca68 100644 --- a/iot-server/server-bootstrap/src/main/resources/log4j2.xml +++ b/iot-server/server-bootstrap/src/main/resources/log4j2.xml @@ -11,7 +11,7 @@ - + diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java index bda77d53..91427dc9 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java @@ -20,8 +20,9 @@ */ public class TaskPositionManager extends AbstractDaemon { - private static final Logger LOGGER = LoggerFactory.getLogger(TaskPositionManager.class); - public static final int DEFAULT_FLUSH_TIMEOUT = 3; + private static final Logger LOGGER = LoggerFactory.getLogger(TaskPositionManager.class); + + public static final int DEFAULT_FLUSH_TIMEOUT = 3; private final TransferManager transferManager; private final JobProfileDb jobConfDb; @@ -101,7 +102,6 @@ private Runnable taskPositionFlushThread() { private void flushJobProfile(String jobId, JobProfile jobProfile) { jobTaskPositionMap.get(jobId).forEach( (fileName, position) -> { - LOGGER.info(" ==========> 写入本地存储行号:{}", position); jobProfile.setLong(fileName + POSITION_SUFFIX, position); } ); From 04a67460e082678dff32ca75a6f0128947443f61 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 15:58:02 +0800 Subject: [PATCH 291/763] [ftx]: update tdengine driver version --- iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml index 5573d5c3..c0eff4b9 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml @@ -20,7 +20,7 @@ com.taosdata.jdbc taos-jdbcdriver - 2.0.30 + 2.0.31 com.zmops From 8a0b0931253dcad5603fdbee180b0d722187cfaf Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 16:03:45 +0800 Subject: [PATCH 292/763] [fix]: remove npm clean cache --- zeus-starter/pom.xml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index d0db3885..374adceb 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -92,15 +92,6 @@ install --registry=https://registry.npm.taobao.org/ - - npm clean - - npm - - - cache clean --force - - npm run build From 2d434b37362957ad77ebc14ce421f8fe8857f7e8 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 24 Sep 2021 18:32:43 +0800 Subject: [PATCH 293/763] [feat]: synchronize taos tag --- .../TaosJsonBodyBuildInterceptor.java | 77 +++++++++ .../zeus/driver/service/TDEngineRest.java | 29 ++++ .../resources/api-json/tdengine/execute.ftl | 1 + zeus-starter/src/main/assembly/webapp.yml | 3 + .../src/main/resources/application.yaml | 3 + .../iot/web/device/dto/TaosResponseData.java | 21 +++ .../device/schedule/SyncTaosTagSchedule.java | 154 ++++++++++-------- 7 files changed, 223 insertions(+), 65 deletions(-) create mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/TaosJsonBodyBuildInterceptor.java create mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java create mode 100644 zeus-driver/src/main/resources/api-json/tdengine/execute.ftl create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/TaosResponseData.java diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/TaosJsonBodyBuildInterceptor.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/TaosJsonBodyBuildInterceptor.java new file mode 100644 index 00000000..94a94ab9 --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/TaosJsonBodyBuildInterceptor.java @@ -0,0 +1,77 @@ +package com.zmops.zeus.driver.inteceptor; + +import com.alibaba.fastjson.JSON; +import com.dtflys.forest.http.ForestRequest; +import com.dtflys.forest.http.ForestResponse; +import com.dtflys.forest.interceptor.Interceptor; +import com.dtflys.forest.reflection.ForestMethod; +import com.zmops.iot.core.auth.context.LoginContextHolder; +import com.zmops.zeus.driver.annotation.JsonPath; +import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.parser.JsonParseUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang.StringUtils; + +import java.lang.annotation.Annotation; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * Created by nantian on 2021-03-12 23:00 + * + * @version 1.0 拦截器 基于 JSON 文件构建 JSON String 参数 + */ +@Slf4j +public class TaosJsonBodyBuildInterceptor implements Interceptor { + + private static final String NO_AUTH_TAG = "authTag"; + + /** + * 方法调用之前获取 JSON path + */ + @Override + public void onInvokeMethod(ForestRequest request, ForestMethod method, Object[] args) { + Map paramMap = new HashMap<>(); + + if (null != args && args.length > 0) { + // 优先 Map 的处理 + if (args[0] instanceof Map) { + paramMap.putAll((Map) args[0]); + } else { + Annotation[][] paramAnnos = method.getMethod().getParameterAnnotations(); + for (int i = 0; i < args.length; i++) { + if (paramAnnos[i].length > 0 && paramAnnos[i][0] instanceof ParamName) { + ParamName paramAnno = (ParamName) paramAnnos[i][0]; + paramMap.put(paramAnno.value(), args[i]); + } + } + } + } + + JsonPath jsonPath = method.getMethod().getAnnotation(JsonPath.class); + if (null != jsonPath && StringUtils.isNotBlank(jsonPath.value())) { + String body = Objects.requireNonNull(JsonParseUtil.parse(jsonPath.value() + ".ftl", paramMap)); + String sendBody = StringEscapeUtils.unescapeJava(body); + log.debug("\n" + sendBody + "\n"); + request.replaceBody(sendBody); + request.setContentType("application/json"); + } + } + + /** + * Zabbix 接口异常返回异常信息捕捉 + */ + @Override + public void onSuccess(String data, ForestRequest request, ForestResponse response) { +// TaosResponseData responseData = JSON.parseObject(data, TaosResponseData.class); + +// if (null != responseData.getError()) { +// log.error(response.getContent()); +// throw new ZbxApiException(responseData.getError().getCode(), responseData.getError().getData()); +// } + response.setResult(data); + Interceptor.super.onSuccess(data, request, response); + } +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java new file mode 100644 index 00000000..46bd199d --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java @@ -0,0 +1,29 @@ +package com.zmops.zeus.driver.service; + +import com.dtflys.forest.annotation.BaseRequest; +import com.dtflys.forest.annotation.Post; +import com.dtflys.forest.extensions.BasicAuth; +import com.zmops.zeus.driver.annotation.JsonPath; +import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.TaosJsonBodyBuildInterceptor; + +/** + * @author yefei + **/ +@BaseRequest( + baseURL = "${taosUrl}", + interceptor = TaosJsonBodyBuildInterceptor.class +) +public interface TDEngineRest { + + /** + * 执行sql + * + * @param sql + * @return String + */ + @Post(headers = "authTag: noAuth") + @JsonPath("/tdengine/execute") + @BasicAuth(username = "${taosUser}", password = "${taosPwd}") + String executeSql(@ParamName("sql") String sql); +} diff --git a/zeus-driver/src/main/resources/api-json/tdengine/execute.ftl b/zeus-driver/src/main/resources/api-json/tdengine/execute.ftl new file mode 100644 index 00000000..c0a4f49a --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/tdengine/execute.ftl @@ -0,0 +1 @@ +${sql} \ No newline at end of file diff --git a/zeus-starter/src/main/assembly/webapp.yml b/zeus-starter/src/main/assembly/webapp.yml index aa376061..42a3643c 100644 --- a/zeus-starter/src/main/assembly/webapp.yml +++ b/zeus-starter/src/main/assembly/webapp.yml @@ -49,6 +49,9 @@ forest: zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:80} zbxApiToken: 3464dee6b3fa3ce4173972e0497d7b84a93bdf8477ff1bdd51a7719cc0db2cd9 + taosUrl: http://${ZEUS_TAOS_HOST:127.0.0.1}:${ZEUS_TAOS_REST_PORT:6041}/rest/sql/${ZEUS_TAOS_DB:} + taosUser: root + taosPwd: taosdata nats: url: nats://${NATS_HOST:127.0.0.1}:${NATS_PORT:4222} \ No newline at end of file diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index a18e00f7..cc490f13 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -49,6 +49,9 @@ forest: zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:80} zbxApiToken: 5376d4510465d6873d6c41076f26c58dae42701941e276971e8f068b76e660d0 + taosUrl: http://${ZEUS_TAOS_HOST:127.0.0.1}:${ZEUS_TAOS_REST_PORT:6041}/rest/sql/${ZEUS_TAOS_DB:zeus_data} + taosUser: root + taosPwd: taosdata nats: url: nats://${NATS_HOST:127.0.0.1}:${NATS_PORT:4222} \ No newline at end of file diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/TaosResponseData.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/TaosResponseData.java new file mode 100644 index 00000000..94396507 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/TaosResponseData.java @@ -0,0 +1,21 @@ +package com.zmops.iot.web.device.dto; + +import lombok.Data; + +/** + * @author nantian created at 2021/8/2 16:59 + */ + +@Data +public class TaosResponseData { + + private String status; + + private String[] head; + + private String[][] column_meta; + + private String[][] data; + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java index a2bb83b1..5cd39931 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java @@ -1,11 +1,25 @@ package com.zmops.iot.web.device.schedule; +import com.alibaba.fastjson.JSON; +import com.zmops.iot.domain.device.Tag; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.device.query.QTag; +import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.TaosResponseData; +import com.zmops.zeus.driver.service.TDEngineRest; import com.zmops.zeus.driver.service.ZbxItem; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + /** * @author yefei **/ @@ -17,70 +31,80 @@ public class SyncTaosTagSchedule { @Autowired ZbxItem zbxItem; -// @Scheduled(cron = "0 01 12 1/1 * ? ") -// public void sync() { -// List deviceIds = new QDevice().select(QDevice.alias().deviceId).findSingleAttributeList(); -// List tagList = new QTag().sid.in(deviceIds).findList(); -// if (ToolUtil.isEmpty(tagList)) { -// return; -// } -// Map> tagMap = tagList.parallelStream().collect(Collectors.groupingBy(Tag::getSid)); -// List> historyDesc = JdbcConnectionHolder.INSTANCE.getConnection().queryForList("DESCRIBE history"); -// List taosTagNames = historyDesc.parallelStream().filter(o -> "TAG".equals(new String((byte[]) o.get("Note")))).map(o -> new String((byte[]) o.get("Field"))) -// .collect(Collectors.toList()); -// -// if (ToolUtil.isEmpty(taosTagNames)) { -// return; -// } -// List tagNames = tagList.parallelStream().map(Tag::getTag).collect(Collectors.toList()); -// //新增taos没有的标签 -// addTaosTag(tagNames, taosTagNames); -// //删除taos标签 -// delTaosTag(taosTagNames, tagNames); -// -// //更新子表 标签值 -// tagMap.forEach((deviceId, tags) -> { -// //根据deviceId 找到 设备下所有itemId -// String hostid = new QDevice().select(QDevice.alias().zbxId).deviceId.eq(deviceId).findSingleAttribute(); -// if (ToolUtil.isEmpty(hostid)) { -// return; -// } -// List itemInfos = JSONObject.parseArray(zbxItem.getItemList(null, hostid), ZbxItemInfo.class); -// List itemIds = itemInfos.parallelStream().map(ZbxItemInfo::getItemid).collect(Collectors.toList()); -// -// itemIds.forEach(itemId -> { -// tags.forEach(tag -> { -// JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER TABLE history_uint SET TAG " + tag.getTag() + "=" + tag.getValue()); -// }); -// }); -// -// }); -// } -// -// private void delTaosTag(List list1, List list2) { -// List tagNames = list2; -// List taosTagNames = list1; -// taosTagNames.removeAll(tagNames); -// if (ToolUtil.isEmpty(taosTagNames)) { -// return; -// } -// taosTagNames.forEach(tagName -> { -// JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER STABLE history_uint DROP TAG " + tagName); -// JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER STABLE history DROP TAG " + tagName); -// }); -// } -// -// private void addTaosTag(List list1, List list2) { -// List tagNames = list1; -// List taosTagNames = list2; -// tagNames.removeAll(taosTagNames); -// if (ToolUtil.isEmpty(tagNames)) { -// return; -// } -// tagNames.forEach(tagName -> { -// JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER STABLE history_uint ADD TAG " + tagName + " NCHAR(16)"); -// JdbcConnectionHolder.INSTANCE.getConnection().execute("ALTER STABLE history ADD TAG " + tagName + " NCHAR(16)"); -// }); -// } + @Autowired + TDEngineRest tdEngineRest; + + @Scheduled(cron = "0 55 23 1/1 * ? ") +// @Scheduled(cron = "0 0/1 * * * ? ") + public void sync() { + List deviceIds = new QDevice().select(QDevice.alias().deviceId).findSingleAttributeList(); + List tagList = new QTag().sid.in(deviceIds).findList(); + if (ToolUtil.isEmpty(tagList)) { + return; + } + Map> tagMap = tagList.parallelStream().collect(Collectors.groupingBy(Tag::getSid)); + String describe = tdEngineRest.executeSql("DESCRIBE history;"); + TaosResponseData taosResponseData = JSON.parseObject(describe, TaosResponseData.class); + String[][] data = taosResponseData.getData(); + List taosTagNames = new ArrayList<>(); + for (String[] datum : data) { + if (ToolUtil.isNotEmpty(datum[3]) && "TAG".equals(datum[3])) { + taosTagNames.add(datum[0]); + } + } + + if (ToolUtil.isEmpty(taosTagNames)) { + return; + } + List tagNames = tagList.parallelStream().map(Tag::getTag).collect(Collectors.toList()); + //新增taos没有的标签 + addTaosTag(tagNames, taosTagNames); + //删除taos标签 + delTaosTag(taosTagNames, tagNames); + + //更新子表 标签值 + tagMap.forEach((deviceId, tags) -> { + //根据deviceId 找到 设备下所有itemId + List itemIds = new QProductAttribute().select(QProductAttribute.alias().zbxId).productId.eq(deviceId).findSingleAttributeList(); + if (ToolUtil.isEmpty(itemIds)) { + return; + } + itemIds.forEach(itemId -> { + tags.forEach(tag -> { + tdEngineRest.executeSql("ALTER TABLE h_" + itemId + " SET TAG " + tag.getTag() + "='" + tag.getValue() + "'"); + }); + }); + + }); + } + + private void delTaosTag(List list1, List list2) { + List tagNames = list2; + List taosTagNames = list1; + taosTagNames.removeAll(tagNames); + if (ToolUtil.isEmpty(taosTagNames)) { + return; + } + taosTagNames.forEach(tagName -> { + if ("deviceid".equals(tagName) || "itemid".equals(tagName)) { + return; + } + tdEngineRest.executeSql("ALTER STABLE history_uint DROP TAG '" + tagName + "'"); + tdEngineRest.executeSql("ALTER STABLE history DROP TAG '" + tagName + "'"); + }); + } + + private void addTaosTag(List list1, List list2) { + List tagNames = list1; + List taosTagNames = list2; + tagNames.removeAll(taosTagNames); + if (ToolUtil.isEmpty(tagNames)) { + return; + } + tagNames.forEach(tagName -> { + tdEngineRest.executeSql("ALTER STABLE history_uint ADD TAG " + tagName + " NCHAR(16)"); + tdEngineRest.executeSql("ALTER STABLE history ADD TAG " + tagName + " NCHAR(16)"); + }); + } } From e6467c5c6b185af9dd691d05f8603f6ef4de30c5 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 24 Sep 2021 19:21:40 +0800 Subject: [PATCH 294/763] [feat]: update global view --- .../analyse/controller/HomeController.java | 25 ++++ .../iot/web/analyse/service/HomeService.java | 114 ++++++++++++++++++ 2 files changed, 139 insertions(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java index 6011c1c2..23662184 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java @@ -53,6 +53,31 @@ public ResponseData collectonRate(@RequestParam("timeFrom") long timeFrom, @Requ return ResponseData.success(homeService.collectionRate(timeFrom, timeTill)); } + /** + * 事件数量统计 + */ + @RequestMapping("/eventNum") + public ResponseData getEventNum(@RequestParam("timeFrom") long timeFrom, @RequestParam("timeTill") long timeTill) { + return ResponseData.success(homeService.getEventNum(timeFrom, timeTill)); + } + + /** + * 告警TOP统计 + */ + @RequestMapping("/alarmTop") + public ResponseData getAlarmTop(@RequestParam("timeFrom") long timeFrom, @RequestParam("timeTill") long timeTill) { + return ResponseData.success(homeService.getAlarmTop(timeFrom, timeTill)); + } + + + /** + * 服务调用统计 + */ + @RequestMapping("/serviceExecuteNum") + public ResponseData serviceExecuteNum(@RequestParam("timeFrom") long timeFrom, @RequestParam("timeTill") long timeTill) { + return ResponseData.success(homeService.serviceExecuteNum(timeFrom, timeTill)); + } + /** * 获取 数据图形展示 * diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index 82bff248..83937923 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -4,19 +4,25 @@ import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.DeviceOnlineReport; +import com.zmops.iot.domain.device.ServiceExecuteRecord; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.device.query.QDeviceOnlineReport; +import com.zmops.iot.domain.device.query.QServiceExecuteRecord; import com.zmops.iot.domain.product.query.QProduct; import com.zmops.iot.enums.ValueType; import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.alarm.dto.AlarmDto; import com.zmops.iot.web.alarm.dto.param.AlarmParam; import com.zmops.iot.web.alarm.service.AlarmService; import com.zmops.iot.web.analyse.dto.LatestDto; +import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.entity.ZbxProblemInfo; import com.zmops.zeus.driver.service.ZbxHost; import com.zmops.zeus.driver.service.ZbxItem; +import io.ebean.DB; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -229,4 +235,112 @@ public Map getAlarmNum(long timeFrom, long timeTill) { return alarmMap; } + + public Map getEventNum(long timeFrom, long timeTill) { + AlarmParam alarmParam = new AlarmParam(); + List alarmList = alarmService.getEventProblem(alarmParam); + Map alarmMap = new ConcurrentHashMap<>(3); + + if (ToolUtil.isNotEmpty(alarmList)) { + + alarmMap.put("total", alarmList.size()); + Collections.reverse(alarmList); + //过滤出指定时间段内的告警 并顺序排序 + Map> tmpMap = alarmList.parallelStream() + .filter(o -> !o.getSeverity().equals("0") + && Long.parseLong(o.getClock()) >= timeFrom + && Long.parseLong(o.getClock()) < timeTill + ).collect( + Collectors.groupingBy(ZbxProblemInfo::getSeverity, + Collectors.groupingBy(o -> LocalDateTimeUtils.convertTimeToString(Integer.parseInt(o.getClock()), "yyyy-MM-dd"), Collectors.counting() + ) + ) + ); + List> trendsList = new ArrayList<>(); + tmpMap.forEach((key, value) -> { + Map trendsMap = new ConcurrentHashMap<>(2); + List list = new ArrayList<>(); + value.forEach((date, val) -> { + Map valMap = new ConcurrentHashMap<>(2); + valMap.put("date", date); + valMap.put("val", val); + list.add(valMap); + }); + trendsMap.put("name", severity[Integer.parseInt(key)]); + trendsMap.put("data", list); + trendsList.add(trendsMap); + }); + alarmMap.put("trends", trendsList); + } + + + //今日开始时间 + Long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); + AlarmParam todayParam = new AlarmParam(); + todayParam.setTimeFrom(timeStart); + List todayAlarmList = alarmService.getZbxAlarm(todayParam); + Long todayAlarmNum = todayAlarmList.parallelStream().count(); + alarmMap.put("today", todayAlarmNum); + + return alarmMap; + } + + public Map getAlarmTop(long timeFrom, long timeTill) { + AlarmParam alarmParam = new AlarmParam(); + alarmParam.setTimeTill(timeTill); + alarmParam.setTimeFrom(timeFrom); + List alarmList = alarmService.getZbxAlarm(alarmParam); + Map alarmMap = new ConcurrentHashMap<>(3); + + if (ToolUtil.isNotEmpty(alarmList)) { + + List triggerIds = alarmList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Integer::parseInt).collect(Collectors.toList()); + List deviceList = DB.findDto(DeviceDto.class, "select name,r.zbx_id from device d INNER JOIN (select relation_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.relation_id=d.device_id") + .setParameter("zbxIds", triggerIds).findList(); + Map deviceMap = deviceList.parallelStream().collect(Collectors.toMap(DeviceDto::getZbxId, DeviceDto::getName)); + + + List alarmDtoList = new ArrayList<>(); + alarmList.forEach(zbxProblemInfo -> { + AlarmDto alarmDto = new AlarmDto(); + BeanUtils.copyProperties(zbxProblemInfo, alarmDto); + alarmDto.setRClock(zbxProblemInfo.getR_clock()); + alarmDto.setDeviceName("未知设备"); + if (null != deviceMap.get(zbxProblemInfo.getObjectid())) { + alarmDto.setDeviceName(deviceMap.get(zbxProblemInfo.getObjectid())); + } + alarmDtoList.add(alarmDto); + }); + + alarmMap = alarmDtoList.parallelStream().collect(Collectors.groupingBy(AlarmDto::getDeviceName, Collectors.counting())); + } + return alarmMap; + } + + public Map serviceExecuteNum(long timeFrom, long timeTill) { + List list = new QServiceExecuteRecord().createTime.ge(LocalDateTimeUtils.getLDTBySeconds((int) timeFrom)) + .createTime.lt(LocalDateTimeUtils.getLDTBySeconds((int) timeTill)).orderBy().createTime.asc().findList(); + Map executeMap = new ConcurrentHashMap<>(3); + if (ToolUtil.isNotEmpty(list)) { + executeMap.put("total", list.size()); + + Map tmpMap = list.parallelStream().collect(Collectors.groupingBy(o -> LocalDateTimeUtils.formatTime(o.getCreateTime(), + "yyyy-MM-dd"), Collectors.counting())); + + List> trendsList = new ArrayList<>(); + tmpMap.forEach((key, value) -> { + Map valMap = new ConcurrentHashMap<>(2); + valMap.put("date", key); + valMap.put("val", value); + trendsList.add(valMap); + }); + executeMap.put("trends", trendsList); + } + //今日开始时间 + long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); + long todayNum = new QServiceExecuteRecord().createTime.ge(LocalDateTimeUtils.getLDTBySeconds((int) timeStart)).findCount(); + executeMap.put("today", todayNum); + + return executeMap; + } } From 5d7feb833f6ba72247d5874b08958f170d5d7324 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 24 Sep 2021 21:34:15 +0800 Subject: [PATCH 295/763] [fix]: update global view --- .../zmops/iot/util/LocalDateTimeUtils.java | 4 +- .../api-json/item/item.trapper.create.ftl | 2 + .../analyse/controller/HomeController.java | 9 +++ .../iot/web/analyse/service/HomeService.java | 79 ++++++++++++++++++- 4 files changed, 88 insertions(+), 6 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java b/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java index d274cdc4..91b8ad14 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java @@ -113,7 +113,7 @@ public static long betweenTwoTime(LocalDateTime startTime, LocalDateTime endTime // 获取一天的开始时间,2017,7,22 00:00 public static LocalDateTime getDayStart(LocalDateTime time) { - return time.withHour(0).withMinute(0).withSecond(0).withNano(0); + return time.withHour(0).withMinute(0).withSecond(1).withNano(0); } // 获取一天的结束时间,2017,7,22 23:59:59.999999999 @@ -193,6 +193,6 @@ public static LocalDateTime getThisWeekMonday() { } public static void main(String[] args) { - System.out.println(getSecondsByStr("2021-08-18T14:25:38.059")); + System.out.println(formatTime(getDayStart(LocalDateTime.now()))); } } diff --git a/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl b/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl index 537a8b2b..64fa0d4a 100644 --- a/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl +++ b/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl @@ -6,6 +6,8 @@ "key_": "${itemKey}", "hostid": "${hostId}", "type": ${source}, + "trends":"0", + "history":"30d" <#if source == '18'> "master_itemid":${masterItemid}, diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java index 23662184..41037e26 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java @@ -78,6 +78,15 @@ public ResponseData serviceExecuteNum(@RequestParam("timeFrom") long timeFrom, @ return ResponseData.success(homeService.serviceExecuteNum(timeFrom, timeTill)); } + /** + * 数据量统计 + */ + @RequestMapping("/dataLevel") + public ResponseData dataLevel() { + return ResponseData.success(homeService.dataLevel()); + } + + /** * 获取 数据图形展示 * diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index 83937923..db8a3f8f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -17,8 +17,10 @@ import com.zmops.iot.web.alarm.service.AlarmService; import com.zmops.iot.web.analyse.dto.LatestDto; import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.device.dto.TaosResponseData; import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.entity.ZbxProblemInfo; +import com.zmops.zeus.driver.service.TDEngineRest; import com.zmops.zeus.driver.service.ZbxHost; import com.zmops.zeus.driver.service.ZbxItem; import io.ebean.DB; @@ -51,6 +53,9 @@ public class HomeService { @Autowired AlarmService alarmService; + @Autowired + TDEngineRest tdEngineRest; + private static String hostId = ""; private static Map ITEM_Map = new ConcurrentHashMap<>(5); @@ -236,6 +241,9 @@ public Map getAlarmNum(long timeFrom, long timeTill) { return alarmMap; } + /** + * 事件数量统计 + */ public Map getEventNum(long timeFrom, long timeTill) { AlarmParam alarmParam = new AlarmParam(); List alarmList = alarmService.getEventProblem(alarmParam); @@ -285,12 +293,15 @@ public Map getEventNum(long timeFrom, long timeTill) { return alarmMap; } - public Map getAlarmTop(long timeFrom, long timeTill) { + /** + * 告警TOP统计 + */ + public List> getAlarmTop(long timeFrom, long timeTill) { AlarmParam alarmParam = new AlarmParam(); alarmParam.setTimeTill(timeTill); alarmParam.setTimeFrom(timeFrom); List alarmList = alarmService.getZbxAlarm(alarmParam); - Map alarmMap = new ConcurrentHashMap<>(3); + Map tmpMap = new ConcurrentHashMap<>(); if (ToolUtil.isNotEmpty(alarmList)) { @@ -312,11 +323,23 @@ public Map getAlarmTop(long timeFrom, long timeTill) { alarmDtoList.add(alarmDto); }); - alarmMap = alarmDtoList.parallelStream().collect(Collectors.groupingBy(AlarmDto::getDeviceName, Collectors.counting())); + tmpMap = alarmDtoList.parallelStream().collect(Collectors.groupingBy(AlarmDto::getDeviceName, Collectors.counting())); } - return alarmMap; + List> topList = new ArrayList<>(); + tmpMap.forEach((key, value) -> { + Map alarmMap = new ConcurrentHashMap<>(2); + alarmMap.put("name", key); + alarmMap.put("value", value); + topList.add(alarmMap); + }); + topList.sort(Comparator.comparing(o -> Integer.parseInt(o.get("value").toString()))); + topList.subList(0, Math.min(topList.size(), 5)); + return topList; } + /** + * 服务调用统计 + */ public Map serviceExecuteNum(long timeFrom, long timeTill) { List list = new QServiceExecuteRecord().createTime.ge(LocalDateTimeUtils.getLDTBySeconds((int) timeFrom)) .createTime.lt(LocalDateTimeUtils.getLDTBySeconds((int) timeTill)).orderBy().createTime.asc().findList(); @@ -343,4 +366,52 @@ public Map serviceExecuteNum(long timeFrom, long timeTill) { return executeMap; } + + /** + * 数据量统计 + */ + public Map dataLevel() { + + Map dataMap = new ConcurrentHashMap<>(4); + + dataMap.put("totalRecordNum", getRecordNum()); + dataMap.put("todayRecordNum", getTodayRecordNum(LocalDateTimeUtils.formatTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())))); + + int serviceExecuteNum = new QServiceExecuteRecord().findCount(); + dataMap.put("serviceExecuteNum", serviceExecuteNum); + + return dataMap; + } + + private int getRecordNum() { + int totalRecord = 0; + String sql = "select count(1) from history"; + totalRecord += getRecordNum(sql); + + sql = "select count(1) from history_uint"; + totalRecord += getRecordNum(sql); + + return totalRecord; + } + + private int getTodayRecordNum(String time) { + int totalRecord = 0; + String sql = "select count(1) from history where clock>'" + time + "'"; + totalRecord += getRecordNum(sql); + + sql = "select count(1) from history_uint where clock>'" + time + "'"; + totalRecord += getRecordNum(sql); + + return totalRecord; + } + + private int getRecordNum(String sql) { + String res_history = tdEngineRest.executeSql(sql); + TaosResponseData taosResponseData = JSON.parseObject(res_history, TaosResponseData.class); + String[][] data_history = taosResponseData.getData(); + if (data_history.length > 0) { + return Integer.parseInt(data_history[0][0]); + } + return 0; + } } From 590c955263f707ca2c9a0842d38561a254f217a6 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 21:45:27 +0800 Subject: [PATCH 296/763] [style]: rename to IoTServerStartUp --- dist-material/bin/IoTServer.bat | 2 +- dist-material/bin/IoTServer.sh | 2 +- .../starter/{IOTServerStartUp.java => IoTServerStartUp.java} | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/{IOTServerStartUp.java => IoTServerStartUp.java} (91%) diff --git a/dist-material/bin/IoTServer.bat b/dist-material/bin/IoTServer.bat index 4627b511..de0e032b 100644 --- a/dist-material/bin/IoTServer.bat +++ b/dist-material/bin/IoTServer.bat @@ -33,5 +33,5 @@ if not defined JAVA_HOME ( set _EXECJAVA=java ) -start "%OAP_PROCESS_TITLE%" %_EXECJAVA% "%OAP_OPTS%" -cp "%CLASSPATH%" com.zmops.zeus.iot.server.starter.IOTServerStartUp +start "%OAP_PROCESS_TITLE%" %_EXECJAVA% "%OAP_OPTS%" -cp "%CLASSPATH%" com.zmops.zeus.iot.server.starter.IoTServerStartUp endlocal diff --git a/dist-material/bin/IoTServer.sh b/dist-material/bin/IoTServer.sh index fe0ff2e6..cfe84f42 100644 --- a/dist-material/bin/IoTServer.sh +++ b/dist-material/bin/IoTServer.sh @@ -37,7 +37,7 @@ done IOT_OPTIONS=" -Doap.logDir=${IOT_LOG_DIR}" -eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${IOT_OPTIONS} -classpath $CLASSPATH com.zmops.zeus.iot.server.starter.IOTServerStartUp \ +eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${IOT_OPTIONS} -classpath $CLASSPATH com.zmops.zeus.iot.server.starter.IoTServerStartUp \ &> ${IOT_LOG_DIR}/zeus_iot.log &" if [ $? -eq 0 ]; then diff --git a/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerStartUp.java b/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerStartUp.java similarity index 91% rename from iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerStartUp.java rename to iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerStartUp.java index f2f422c7..3f16d36a 100644 --- a/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerStartUp.java +++ b/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerStartUp.java @@ -8,7 +8,7 @@ * 宙斯服务 协议层启动 */ @Slf4j -public class IOTServerStartUp { +public class IoTServerStartUp { public static void main(String[] args) { IoTServerBootstrap.start(); From b151af0882a1dfe3316310d70b6e5bad73819a90 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 21:45:55 +0800 Subject: [PATCH 297/763] [feat]: update zeus-iot-ui submodule --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index a1254de7..28d1eab5 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit a1254de7235a973b35ef86b05923dd327e583ba1 +Subproject commit 28d1eab52dcf4d63be7ca8465300480209281e34 From c1030b046d88d5c95dbb4fbedf78d4d727c764b3 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 24 Sep 2021 22:15:49 +0800 Subject: [PATCH 298/763] [feat]: number format --- .../java/com/zmops/iot/util/ParseUtil.java | 49 +++++++++++++++++++ .../iot/web/analyse/service/HomeService.java | 7 +-- 2 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/util/ParseUtil.java diff --git a/zeus-common/src/main/java/com/zmops/iot/util/ParseUtil.java b/zeus-common/src/main/java/com/zmops/iot/util/ParseUtil.java new file mode 100644 index 00000000..989a6c30 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/util/ParseUtil.java @@ -0,0 +1,49 @@ +package com.zmops.iot.util; + +import java.math.BigDecimal; +import java.text.CharacterIterator; +import java.text.DecimalFormat; +import java.text.StringCharacterIterator; + +/** + * @author yefei + **/ +public class ParseUtil { + + + public static void main(String[] args) { + System.out.println(getCommaFormat("2097180.19677")); + } + + //每3位中间添加逗号的格式化显示 + public static String getCommaFormat(String value) { + if (ToolUtil.isEmpty(value)) { + return "0"; + } + return getFormat(",###.##", new BigDecimal(value)); + } + + //自定义数字格式方法 + public static String getFormat(String style, BigDecimal value) { + DecimalFormat df = new DecimalFormat(); + df.applyPattern(style); + return df.format(value.doubleValue()); + } + + + public static String formatLagSize(String size) { + if (ToolUtil.isEmpty(size)) { + return "0"; + } + long bytes = Long.parseLong(size); + if (-1000 < bytes && bytes < 1000) { + return bytes + " B"; + } + CharacterIterator ci = new StringCharacterIterator("kMGTPE"); + while (bytes <= -999_950 || bytes >= 999_950) { + bytes /= 1000; + ci.next(); + } + return String.format("%.1f %cB", bytes / 1000.0, ci.current()); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index db8a3f8f..6ab3486e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -11,6 +11,7 @@ import com.zmops.iot.domain.product.query.QProduct; import com.zmops.iot.enums.ValueType; import com.zmops.iot.util.LocalDateTimeUtils; +import com.zmops.iot.util.ParseUtil; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.alarm.dto.AlarmDto; import com.zmops.iot.web.alarm.dto.param.AlarmParam; @@ -374,11 +375,11 @@ public Map dataLevel() { Map dataMap = new ConcurrentHashMap<>(4); - dataMap.put("totalRecordNum", getRecordNum()); - dataMap.put("todayRecordNum", getTodayRecordNum(LocalDateTimeUtils.formatTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())))); + dataMap.put("totalRecordNum", ParseUtil.getCommaFormat(getRecordNum() + "")); + dataMap.put("todayRecordNum", ParseUtil.getCommaFormat(getTodayRecordNum(LocalDateTimeUtils.formatTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now()))) + "")); int serviceExecuteNum = new QServiceExecuteRecord().findCount(); - dataMap.put("serviceExecuteNum", serviceExecuteNum); + dataMap.put("serviceExecuteNum", ParseUtil.getCommaFormat(serviceExecuteNum + "")); return dataMap; } From 27dfb0a2ff28262f36eacd64f4822be8b734d48c Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 23:25:27 +0800 Subject: [PATCH 299/763] [style]: change code style --- .../device/schedule/SyncTaosTagSchedule.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java index 5cd39931..37f95864 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java @@ -42,11 +42,13 @@ public void sync() { if (ToolUtil.isEmpty(tagList)) { return; } - Map> tagMap = tagList.parallelStream().collect(Collectors.groupingBy(Tag::getSid)); - String describe = tdEngineRest.executeSql("DESCRIBE history;"); - TaosResponseData taosResponseData = JSON.parseObject(describe, TaosResponseData.class); - String[][] data = taosResponseData.getData(); - List taosTagNames = new ArrayList<>(); + Map> tagMap = tagList.parallelStream().collect(Collectors.groupingBy(Tag::getSid)); + String describe = tdEngineRest.executeSql("DESCRIBE history;"); + + TaosResponseData taosResponseData = JSON.parseObject(describe, TaosResponseData.class); + String[][] data = taosResponseData.getData(); + + List taosTagNames = new ArrayList<>(); for (String[] datum : data) { if (ToolUtil.isNotEmpty(datum[3]) && "TAG".equals(datum[3])) { taosTagNames.add(datum[0]); @@ -56,6 +58,7 @@ public void sync() { if (ToolUtil.isEmpty(taosTagNames)) { return; } + List tagNames = tagList.parallelStream().map(Tag::getTag).collect(Collectors.toList()); //新增taos没有的标签 addTaosTag(tagNames, taosTagNames); @@ -81,10 +84,13 @@ public void sync() { private void delTaosTag(List list1, List list2) { List tagNames = list2; List taosTagNames = list1; + taosTagNames.removeAll(tagNames); + if (ToolUtil.isEmpty(taosTagNames)) { return; } + taosTagNames.forEach(tagName -> { if ("deviceid".equals(tagName) || "itemid".equals(tagName)) { return; @@ -97,10 +103,12 @@ private void delTaosTag(List list1, List list2) { private void addTaosTag(List list1, List list2) { List tagNames = list1; List taosTagNames = list2; + tagNames.removeAll(taosTagNames); if (ToolUtil.isEmpty(tagNames)) { return; } + tagNames.forEach(tagName -> { tdEngineRest.executeSql("ALTER STABLE history_uint ADD TAG " + tagName + " NCHAR(16)"); tdEngineRest.executeSql("ALTER STABLE history ADD TAG " + tagName + " NCHAR(16)"); From 2310ff327c750f18eb58aeb039b9c3a165323ce1 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 24 Sep 2021 23:25:54 +0800 Subject: [PATCH 300/763] [feat]: update zeus-iot-ui submodule --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index 28d1eab5..f7129d3a 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit 28d1eab52dcf4d63be7ca8465300480209281e34 +Subproject commit f7129d3a1e4d0c45e48faf95d4c15b7aa9b31418 From 69c0fadb197188b0309eaad4d403a65e8507a003 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 25 Sep 2021 11:26:36 +0800 Subject: [PATCH 301/763] [fix]: update product status trigger --- .../ProductStatusTriggerController.java | 2 +- .../product/service/ProductTriggerService.java | 16 ++++++++++++---- .../product/service/work/SaveProdAttrWorker.java | 12 ++++++++---- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java index 2812d32f..cd03ec30 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java @@ -58,7 +58,7 @@ public ResponseData createDeviceStatusTrigger(@RequestBody @Validated(BaseEntity ProductAttribute prodAttrSecond = new QProductAttribute().attrId.eq(rule.getAttrIdRecovery()).findOne(); if (null == prodAttr || null == prodAttrSecond) { - throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_NOT_EXISTS); } int count = new QProductStatusFunctionRelation().relationId.eq(rule.getRelationId()).findCount(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java index 499379ce..e0016f26 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java @@ -6,6 +6,7 @@ import com.zmops.iot.domain.product.ProductStatusFunctionRelation; import com.zmops.iot.domain.product.query.QProductStatusFunction; import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; +import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.iot.web.product.dto.ProductStatusFunctionDto; import com.zmops.iot.web.product.dto.ProductStatusJudgeRule; import com.zmops.zeus.driver.service.ZbxDeviceStatusTrigger; @@ -16,6 +17,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; import java.util.Map; /** @@ -59,28 +61,34 @@ public Long createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { long ruleId = IdUtil.getSnowflake().nextId(); judgeRule.setRuleId(ruleId); -// Map rule = new HashMap<>(); -// buildTriggerCreateMap(rule, judgeRule); - + //step 1:保存到zbx String res = deviceStatusTrigger.createDeviceStatusTrigger(judgeRule.getRuleId() + "", judgeRule.getRelationId(), judgeRule.getProductAttrKey(), judgeRule.getRuleCondition() + judgeRule.getUnit(), judgeRule.getRuleFunction(), judgeRule.getProductAttrKeyRecovery(), judgeRule.getRuleConditionRecovery() + judgeRule.getUnitRecovery(), judgeRule.getRuleFunctionRecovery()); String triggerId = getTriggerId(res); + //step 2:保存规则 ProductStatusFunction productStatusFunction = new ProductStatusFunction(); BeanUtils.copyProperties(judgeRule, productStatusFunction); productStatusFunction.setZbxId(triggerId); productStatusFunction.setRuleId(ruleId); DB.save(productStatusFunction); + //step 3:保存关联关系 ProductStatusFunctionRelation productStatusFunctionRelation = new ProductStatusFunctionRelation(); productStatusFunctionRelation.setRelationId(judgeRule.getRelationId()); productStatusFunctionRelation.setRuleId(ruleId); productStatusFunctionRelation.setRuleId(ruleId); DB.save(productStatusFunctionRelation); - + //step 4:同步到设备 + String sql = "select device_id from device where product_id = :productId and device_id not in (select relation_id from product_status_function_relation where inherit='0')"; + List deviceDtoList = DB.findDto(DeviceDto.class, sql).setParameter("productId", judgeRule.getRelationId()).findList(); + deviceDtoList.forEach(deviceDto -> { + DB.sqlUpdate("insert into product_status_function_relation (relation_id,rule_id,inherit) SELECT :deviceId,rule_id,1 from product_status_function_relation where relation_id=:relationId") + .setParameter("deviceId", deviceDto.getDeviceId()).setParameter("relationId", judgeRule.getRelationId() + "").execute(); + }); return productStatusFunction.getRuleId(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java index 1b8ca466..db90992a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java @@ -4,9 +4,9 @@ import cn.hutool.core.util.IdUtil; import com.zmops.iot.async.callback.IWorker; import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.iot.web.product.dto.ProductAttr; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; @@ -32,16 +32,20 @@ public Boolean action(ProductAttr productAttr, Map> String prodId = productAttr.getProductId(); - List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); + String sql = "select device_id from device " + + " where product_id = :productId and device_id not in (" + + " select product_id from product_attribute " + + " where template_id is null and key = :key)"; + List deviceDtoList = DB.findDto(DeviceDto.class, sql).setParameter("productId", productAttr.getProductId()).findList(); List productAttributeList = new ArrayList<>(); - for (String deviceId : deviceIds) { + for (DeviceDto deviceDto : deviceDtoList) { ProductAttribute productAttrbute = new ProductAttribute(); ToolUtil.copyProperties(productAttr, productAttrbute); productAttrbute.setAttrId(IdUtil.getSnowflake().nextId()); productAttrbute.setName(productAttr.getAttrName()); - productAttrbute.setProductId(deviceId); + productAttrbute.setProductId(deviceDto.getDeviceId()); productAttrbute.setTemplateId(productAttr.getAttrId()); productAttributeList.add(productAttrbute); } From 30165cfd4f19c5473d2777014846da3682837d5a Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 25 Sep 2021 16:51:46 +0800 Subject: [PATCH 302/763] [feat]: add data filter --- .../zmops/iot/core/auth/model/LoginUser.java | 4 ++ .../zeus/driver/service/TDEngineRest.java | 2 +- .../src/main/resources/application.yaml | 4 +- .../device/service/DeviceGroupService.java | 24 ++++++++++- .../iot/web/device/service/DeviceService.java | 43 ++++++++++++++++--- .../web/macro/controller/MacroController.java | 12 ++++-- .../iot/web/sys/factory/UserFactory.java | 1 + 7 files changed, 78 insertions(+), 12 deletions(-) diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java index 407cd6a3..53f25b01 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java @@ -56,6 +56,10 @@ public class LoginUser implements UserDetails, Serializable { */ private String email; + /** + * 用户组 + */ + private Long userGroupId; /** * 角色集 diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java index 46bd199d..6ad96b4f 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java @@ -22,7 +22,7 @@ public interface TDEngineRest { * @param sql * @return String */ - @Post(headers = "authTag: noAuth") + @Post @JsonPath("/tdengine/execute") @BasicAuth(username = "${taosUser}", password = "${taosPwd}") String executeSql(@ParamName("sql") String sql); diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index cc490f13..8ac5d3d1 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -41,14 +41,14 @@ spring: template-loader-path: classpath:/public/ forest: - log-enabled: false + log-enabled: true timeout: 5000 variables: ## Zabbix API IP And ServerIp and ServerPort zbxApiUrl: http://${ZEUS_ZABBIX_HOST:127.0.0.1}:${ZEUS_ZABBIX_PORT:80}/zabbix/api_jsonrpc.php zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:80} - zbxApiToken: 5376d4510465d6873d6c41076f26c58dae42701941e276971e8f068b76e660d0 + zbxApiToken: cf22b3b977bc47d0460e144ff7a817b584eb3f2d5e23dcf640a014c07d087adb taosUrl: http://${ZEUS_TAOS_HOST:127.0.0.1}:${ZEUS_TAOS_REST_PORT:6041}/rest/sql/${ZEUS_TAOS_DB:zeus_data} taosUser: root taosPwd: taosdata diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java index 1143146a..81d16846 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java @@ -3,6 +3,7 @@ import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.domain.device.DeviceGroup; import com.zmops.iot.domain.device.query.QDeviceGroup; import com.zmops.iot.domain.device.query.QDevicesGroups; @@ -21,6 +22,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -41,8 +43,15 @@ public class DeviceGroupService { * @return */ public Pager deviceGroupPageList(DeviceGroupParam devGroupParam) { + List devGroupIds = getDevGroupIds(); + if (ToolUtil.isEmpty(devGroupIds)) { + return new Pager<>(); + } QDeviceGroup qDeviceGroup = new QDeviceGroup(); + + qDeviceGroup.deviceGroupId.in(devGroupIds); + if (ToolUtil.isNotEmpty(devGroupParam.getName())) { qDeviceGroup.name.contains(devGroupParam.getName()); } @@ -60,8 +69,12 @@ public Pager deviceGroupPageList(DeviceGroupParam devGroupParam) { * @return */ public List deviceGroupList(DeviceGroupParam devGroupParam) { - + List devGroupIds = getDevGroupIds(); + if (ToolUtil.isEmpty(devGroupIds)) { + return Collections.emptyList(); + } QDeviceGroup qDeviceGroup = new QDeviceGroup(); + qDeviceGroup.deviceGroupId.in(devGroupIds); if (ToolUtil.isNotEmpty(devGroupParam.getName())) { qDeviceGroup.name.contains(devGroupParam.getName()); } @@ -69,6 +82,15 @@ public List deviceGroupList(DeviceGroupParam devGroupParam) { return qDeviceGroup.findList(); } + /** + * 获取当前登录用户绑定的主机组ID + * + * @return + */ + public List getDevGroupIds() { + Long curUserGrpId = LoginContextHolder.getContext().getUser().getUserGroupId(); + return new QSysUserGrpDevGrp().select(QSysUserGrpDevGrp.alias().deviceGroupId).userGroupId.eq(curUserGrpId).findSingleAttributeList(); + } /** * 添加设备組 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 704c22a6..cbd4701b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -65,6 +65,9 @@ public class DeviceService { @Autowired private ZbxValueMap zbxValueMap; + @Autowired + DeviceGroupService deviceGroupService; + /** * 设备列表 * @@ -72,13 +75,30 @@ public class DeviceService { * @return */ public List deviceList(DeviceParam deviceParam) { + List deviceIds = getDeviceIds(); + if (ToolUtil.isEmpty(deviceIds)) { + return Collections.emptyList(); + } QDevice qDevice = new QDevice(); + + qDevice.deviceId.in(deviceIds); + if (ToolUtil.isNotEmpty(deviceParam.getName())) { qDevice.name.contains(deviceParam.getName()); } return qDevice.findList(); } + /** + * 获取当前用户 绑定的设备ID + * + * @return + */ + public List getDeviceIds() { + List devGroupIds = deviceGroupService.getDevGroupIds(); + return new QDevicesGroups().select(QDevicesGroups.alias().deviceId).deviceGroupId.in(devGroupIds).findSingleAttributeList(); + } + /** * 设备分页列表 * @@ -86,13 +106,12 @@ public List deviceList(DeviceParam deviceParam) { * @return */ public Pager devicePageList(DeviceParam deviceParam) { + List devGroupIds = deviceGroupService.getDevGroupIds(); + if (ToolUtil.isEmpty(devGroupIds)) { + return new Pager<>(); + } StringBuilder sql = generateBaseSql(); - if (null != deviceParam.getDeviceGroupId()) { - sql.append(" where ds.groupIds like :deviceGroupId"); - } else { - sql.append(" where 1=1 "); - } List sids = new ArrayList<>(); if (ToolUtil.isNotEmpty(deviceParam.getTag())) { QTag qTag = new QTag().select(QTag.Alias.sid).templateId.isNull(); @@ -139,6 +158,18 @@ public Pager devicePageList(DeviceParam deviceParam) { dto.setParameter("name", "%" + deviceParam.getName() + "%"); count.setParameter("name", "%" + deviceParam.getName() + "%"); } + if (null != deviceParam.getDeviceGroupId()) { + if (devGroupIds.contains(deviceParam.getDeviceGroupId())) { + dto.setParameter("deviceGroupIds", deviceParam.getDeviceGroupId()); + count.setParameter("deviceGroupIds", deviceParam.getDeviceGroupId()); + } else { + return new Pager<>(); + } + } else { + dto.setParameter("deviceGroupIds", devGroupIds); + count.setParameter("deviceGroupIds", devGroupIds); + } + List list = dto.setFirstRow((deviceParam.getPage() - 1) * deviceParam.getMaxRow()) .setMaxRows(deviceParam.getMaxRow()).findList(); @@ -147,6 +178,7 @@ public Pager devicePageList(DeviceParam deviceParam) { } private StringBuilder generateBaseSql() { + return new StringBuilder("SELECT " + " d.device_id," + " d.NAME, " + @@ -175,6 +207,7 @@ private StringBuilder generateBaseSql() { " device d " + " LEFT JOIN devices_groups dgs ON dgs.device_id = d.device_id " + " LEFT JOIN device_group dg ON dg.device_group_id = dgs.device_group_id " + + " where dg.device_group_id in (:deviceGroupIds) " + " GROUP BY d.device_id " + " ) ds ON ds.device_id = d.device_id "); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java index 5fdd210c..13aeaaae 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java @@ -46,9 +46,9 @@ public class MacroController { @RequestMapping("/create") public ResponseData createUserMacro(@Validated(BaseEntity.Create.class) @RequestBody UserMacro userMacro) { // 获取 host id - String zbxId = new QProduct().select(QProduct.alias().zbxId).productId.eq(Long.parseLong(userMacro.getDeviceId())).findSingleAttribute(); + String zbxId = new QDevice().select(QDevice.alias().zbxId).deviceId.eq(userMacro.getDeviceId()).findSingleAttribute(); if (ToolUtil.isEmpty(zbxId)) { - zbxId = new QDevice().select(QDevice.alias().zbxId).deviceId.eq(userMacro.getDeviceId()).findSingleAttribute(); + zbxId = new QProduct().select(QProduct.alias().zbxId).productId.eq(Long.parseLong(userMacro.getDeviceId())).findSingleAttribute(); } if (ToolUtil.isEmpty(zbxId)) { @@ -86,7 +86,13 @@ public ResponseData updateUserMacro(@Validated(BaseEntity.Update.class) @Request public ResponseData getUserMacro(@Validated(BaseEntity.Get.class) @RequestBody UserMacro userMacro) { // 获取 模板ID 或者 设备ID - String zbxId = new QProduct().select(QProduct.alias().zbxId).productId.eq(Long.parseLong(userMacro.getDeviceId())).findSingleAttribute(); + String zbxId = new QDevice().select(QDevice.alias().zbxId).deviceId.eq(userMacro.getDeviceId()).findSingleAttribute(); + if (ToolUtil.isEmpty(zbxId)) { + zbxId = new QProduct().select(QProduct.alias().zbxId).productId.eq(Long.parseLong(userMacro.getDeviceId())).findSingleAttribute(); + } + if (ToolUtil.isEmpty(zbxId)) { + throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); + } // 模板ID if (ToolUtil.isNotEmpty(zbxId)) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/factory/UserFactory.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/factory/UserFactory.java index 67a9303d..535d8509 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/factory/UserFactory.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/factory/UserFactory.java @@ -107,6 +107,7 @@ public static LoginUser createLoginUser(SysUser user) { loginUser.setId(user.getUserId()); loginUser.setAccount(user.getAccount()); + loginUser.setUserGroupId(user.getUserGroupId()); // loginUser.setDeptId(user.getDeptId()); // loginUser.setDeptName(ConstantFactory.me().getDeptName(user.getDeptId())); loginUser.setName(user.getName()); From 4b15ebefb99a90bc22bc2cac360c3ecc36144197 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 25 Sep 2021 17:18:43 +0800 Subject: [PATCH 303/763] [feat]: add operational control --- .../iot/web/alarm/controller/AlarmController.java | 7 ++++--- .../web/analyse/controller/HistoryController.java | 2 ++ .../iot/web/analyse/controller/LatestController.java | 3 +++ .../iot/web/device/controller/DeviceController.java | 12 ++++++++++++ .../controller/DeviceEventTriggerController.java | 1 + .../web/product/controller/ProductController.java | 12 ++++++++++++ .../product/controller/ProductTypeController.java | 5 +++++ .../zmops/iot/web/sys/controller/DictController.java | 7 +++++++ .../iot/web/sys/controller/DictTypeController.java | 5 +++++ .../zmops/iot/web/sys/controller/LogController.java | 2 ++ .../iot/web/sys/controller/LoginLogController.java | 2 ++ .../iot/web/sys/controller/SysParamController.java | 3 +++ .../iot/web/sys/controller/SysRoleController.java | 7 +++++++ .../iot/web/sys/controller/SysUserController.java | 7 +++++++ .../web/sys/controller/SysUserGroupController.java | 7 +++++++ 15 files changed, 79 insertions(+), 3 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java index c7cf9dc6..2e7f2810 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java @@ -3,6 +3,7 @@ import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.web.alarm.dto.param.AlarmParam; import com.zmops.iot.web.alarm.service.AlarmService; +import com.zmops.iot.web.auth.Permission; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -18,13 +19,13 @@ public class AlarmController { @Autowired AlarmService alarmService; -// @RequestMapping("/test") + // @RequestMapping("/test") // public void test() { // alarmService.test(); // } - + @Permission(code = "alarmList") @RequestMapping("/getAlarmByPage") - public ResponseData getAlarmByPage(@RequestBody AlarmParam alarmParam){ + public ResponseData getAlarmByPage(@RequestBody AlarmParam alarmParam) { return ResponseData.success(alarmService.getAlarmByPage(alarmParam)); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HistoryController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HistoryController.java index 30bef652..e77e857b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HistoryController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HistoryController.java @@ -4,6 +4,7 @@ import com.zmops.iot.web.analyse.dto.LatestDto; import com.zmops.iot.web.analyse.dto.param.HistoryParam; import com.zmops.iot.web.analyse.service.HistoryService; +import com.zmops.iot.web.auth.Permission; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RequestBody; @@ -23,6 +24,7 @@ public class HistoryController { HistoryService historyService; @RequestMapping("/query") + @Permission(code = "latest") public Pager qeuryHistory(@Validated @RequestBody HistoryParam historyParam) { return historyService.queryHistory(historyParam); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java index 5f5a9436..f14e75b4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java @@ -5,6 +5,7 @@ import com.zmops.iot.web.analyse.dto.LatestDto; import com.zmops.iot.web.analyse.dto.param.LatestParam; import com.zmops.iot.web.analyse.service.LatestService; +import com.zmops.iot.web.auth.Permission; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RequestBody; @@ -25,11 +26,13 @@ public class LatestController { LatestService latestService; @RequestMapping("/query") + @Permission(code = "latest") public Pager qeuryLatest(@Validated @RequestBody LatestParam latestParam) { return latestService.qeuryLatest(latestParam); } @RequestMapping("/queryMap") + @Permission(code = "latest") public ResponseData queryMap(@RequestParam("deviceId") String deviceId) { return ResponseData.success(latestService.queryMap(deviceId)); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java index fe81b6af..c6b41c88 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java @@ -9,6 +9,7 @@ import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.iot.web.device.dto.param.DeviceParam; import com.zmops.iot.web.device.service.DeviceService; @@ -38,6 +39,7 @@ public class DeviceController { * * @return */ + @Permission(code = "dev") @PostMapping("/getDeviceByPage") public Pager devicePageList(@RequestBody DeviceParam deviceParam) { return deviceService.devicePageList(deviceParam); @@ -48,6 +50,7 @@ public Pager devicePageList(@RequestBody DeviceParam deviceParam) { * * @return */ + @Permission(code = "dev") @PostMapping("/list") public ResponseData deviceList(@RequestBody DeviceParam deviceParam) { return ResponseData.success(deviceService.deviceList(deviceParam)); @@ -56,6 +59,7 @@ public ResponseData deviceList(@RequestBody DeviceParam deviceParam) { /** * 设备创建 */ + @Permission(code = "dev") @RequestMapping("/create") public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody DeviceDto deviceDto) { QDevice qDevice = new QDevice().or().name.eq(deviceDto.getName()); @@ -78,6 +82,7 @@ public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody Devi /** * 设备创建 */ + @Permission(code = "dev") @RequestMapping("/update") public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody DeviceDto deviceDto) { int count = new QDevice().deviceId.ne(deviceDto.getDeviceId()).name.eq(deviceDto.getName()).findCount(); @@ -95,6 +100,7 @@ public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody Devi /** * 设备删除 */ + @Permission(code = "dev") @RequestMapping("/delete") public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody DeviceDto deviceDto) { return ResponseData.success(deviceService.delete(deviceDto)); @@ -103,6 +109,7 @@ public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody Devi /** * 设备详情 */ + @Permission(code = "dev") @GetMapping("/detail") public ResponseData prodDetail(@RequestParam("deviceId") String deviceId) { return ResponseData.success(deviceService.deviceDetail(deviceId)); @@ -111,6 +118,7 @@ public ResponseData prodDetail(@RequestParam("deviceId") String deviceId) { /** * 设备标签列表 */ + @Permission(code = "dev") @GetMapping("/tag/list") public ResponseData prodTagList(@RequestParam("deviceId") String deviceId) { return ResponseData.success(deviceService.deviceTagList(deviceId)); @@ -119,6 +127,7 @@ public ResponseData prodTagList(@RequestParam("deviceId") String deviceId) { /** * 设备值映射列表 */ + @Permission(code = "dev") @GetMapping("/valueMap/list") public ResponseData valueMapList(@RequestParam("deviceId") String deviceId) { return ResponseData.success(deviceService.valueMapList(deviceId)); @@ -129,6 +138,7 @@ public ResponseData valueMapList(@RequestParam("deviceId") String deviceId) { * * @return */ + @Permission(code = "dev") @PostMapping("/tag/update") public ResponseData deviceTagCreate(@RequestBody @Valid ProductTag productTag) { @@ -151,6 +161,7 @@ public ResponseData deviceTagCreate(@RequestBody @Valid ProductTag productTag) { * @param valueMap * @return */ + @Permission(code = "dev") @PostMapping("/valueMap/update") public ResponseData prodValueMapCreate(@RequestBody @Validated(BaseEntity.Create.class) ValueMap valueMap) { @@ -175,6 +186,7 @@ public ResponseData prodValueMapCreate(@RequestBody @Validated(BaseEntity.Create * @param valueMap * @return */ + @Permission(code = "dev") @PostMapping("/valuemap/delete") public ResponseData prodValueMapDelete(@RequestBody @Validated(BaseEntity.Delete.class) ValueMap valueMap) { String response = deviceService.valueMapDelete(valueMap.getValuemapid()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index 51eda656..7f32e517 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -55,6 +55,7 @@ public class DeviceEventTriggerController { * @param eventRuleId * @return */ + @GetMapping("/detail") public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId, @RequestParam("deviceId") String deviceId) { ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRuleId).findOne(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java index 4bf4a823..e2fb6804 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java @@ -12,6 +12,7 @@ import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductBasicInfo; import com.zmops.iot.web.product.dto.ProductDto; @@ -45,6 +46,7 @@ public class ProductController { /** * 产品分页列表 */ + @Permission(code = "product") @PostMapping("/getProductByPage") public Pager getProductByPage(@RequestBody ProductBasicInfo prodBasicInfo) { return productService.getProductByPage(prodBasicInfo); @@ -53,6 +55,7 @@ public Pager getProductByPage(@RequestBody ProductBasicInfo prodBasi /** * 产品列表 */ + @Permission(code = "product") @PostMapping("/list") public ResponseData prodList(@RequestBody ProductBasicInfo prodBasicInfo) { return ResponseData.success(productService.prodList(prodBasicInfo)); @@ -61,6 +64,7 @@ public ResponseData prodList(@RequestBody ProductBasicInfo prodBasicInfo) { /** * 产品详情 */ + @Permission(code = "product") @GetMapping("/detail") public ResponseData prodDetail(@RequestParam("productId") Long prodId) { return ResponseData.success(productService.prodDetail(prodId)); @@ -69,6 +73,7 @@ public ResponseData prodDetail(@RequestParam("productId") Long prodId) { /** * 产品标签列表 */ + @Permission(code = "product") @GetMapping("/tag/list") public ResponseData prodTagList(@RequestParam("productId") String prodId) { return ResponseData.success(productService.prodTagList(prodId)); @@ -77,6 +82,7 @@ public ResponseData prodTagList(@RequestParam("productId") String prodId) { /** * 值映射列表 */ + @Permission(code = "product") @GetMapping("/valueMap/list") public ResponseData valueMapList(@RequestParam("productId") Long prodId) { return ResponseData.success(productService.valueMapList(prodId)); @@ -88,6 +94,7 @@ public ResponseData valueMapList(@RequestParam("productId") Long prodId) { * @param prodBasicInfo 产品基本信息 * @return */ + @Permission(code = "product") @PostMapping("/create") public ResponseData prodCreate(@RequestBody @Validated(value = BaseEntity.Create.class) ProductBasicInfo prodBasicInfo) { @@ -113,6 +120,7 @@ public ResponseData prodCreate(@RequestBody @Validated(value = BaseEntity.Create * * @return */ + @Permission(code = "product") @PostMapping("/update") public ResponseData prodUpdate(@RequestBody @Validated(value = BaseEntity.Update.class) ProductBasicInfo prodBasicInfo) { @@ -135,6 +143,7 @@ public ResponseData prodUpdate(@RequestBody @Validated(value = BaseEntity.Update * @param prodBasicInfo 产品基础信息 * @return */ + @Permission(code = "product") @PostMapping("/delete") public ResponseData prodDelete(@RequestBody @Validated(value = BaseEntity.Delete.class) ProductBasicInfo prodBasicInfo) { @@ -168,6 +177,7 @@ public ResponseData prodDelete(@RequestBody @Validated(value = BaseEntity.Delete * * @return */ + @Permission(code = "product") @PostMapping("/tag/update") public ResponseData prodTagCreate(@RequestBody @Valid ProductTag productTag) { @@ -207,6 +217,7 @@ public ResponseData prodTagCreate(@RequestBody @Valid ProductTag productTag) { * @param valueMap * @return */ + @Permission(code = "product") @PostMapping("/valuemap/update") public ResponseData prodValueMapCreate(@RequestBody @Validated(BaseEntity.Create.class) ValueMap valueMap) { @@ -232,6 +243,7 @@ public ResponseData prodValueMapCreate(@RequestBody @Validated(BaseEntity.Create * @param valueMap * @return */ + @Permission(code = "product") @PostMapping("/valueMap/delete") public ResponseData prodValueMapDelete(@RequestBody @Validated(BaseEntity.Delete.class) ValueMap valueMap) { String response = productService.valueMapDelete(valueMap.getValuemapid()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductTypeController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductTypeController.java index 8a9ff2e1..77acb8cc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductTypeController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductTypeController.java @@ -3,6 +3,7 @@ import com.zmops.iot.core.log.BussinessLog; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.product.dto.param.ProductTypeParam; import com.zmops.iot.web.product.service.ProductTypeService; import lombok.extern.slf4j.Slf4j; @@ -28,6 +29,7 @@ public class ProductTypeController { /** * 产品分类树 */ + @Permission(code = "product_type") @RequestMapping("/tree") public ResponseData tree() { return ResponseData.success(productTypeService.tree()); @@ -36,6 +38,7 @@ public ResponseData tree() { /** * 新增产品分类 */ + @Permission(code = "product_type") @RequestMapping("/create") @BussinessLog("新增产品分类") public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody ProductTypeParam productType) { @@ -45,6 +48,7 @@ public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody Prod /** * 修改产品分类 */ + @Permission(code = "product_type") @RequestMapping("/update") @BussinessLog("修改产品分类") public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody ProductTypeParam productType) { @@ -54,6 +58,7 @@ public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody Prod /** * 删除产品分类 */ + @Permission(code = "product_type") @RequestMapping("/delete") @BussinessLog("删除产品分类") public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody ProductTypeParam productType) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictController.java index 538c4a24..1faa1577 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictController.java @@ -3,6 +3,7 @@ import com.zmops.iot.core.log.BussinessLog; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.sys.dto.param.DictParam; import com.zmops.iot.web.sys.service.DictService; import com.zmops.iot.web.sys.service.DictTypeService; @@ -28,6 +29,7 @@ public class DictController { /** * 新增字典项 */ + @Permission(code = "dict") @RequestMapping("/create") @BussinessLog("新增字典项") public ResponseData addItem(@Validated(BaseEntity.Create.class) @RequestBody DictParam dictParam) { @@ -37,6 +39,7 @@ public ResponseData addItem(@Validated(BaseEntity.Create.class) @RequestBody Dic /** * 编辑字典项 */ + @Permission(code = "dict") @RequestMapping("/update") @BussinessLog("编辑字典项") public ResponseData editItem(@Validated(BaseEntity.Update.class) @RequestBody DictParam dictParam) { @@ -48,6 +51,7 @@ public ResponseData editItem(@Validated(BaseEntity.Update.class) @RequestBody Di * * @author stylefeng */ + @Permission(code = "dict") @RequestMapping("/delete") @BussinessLog("删除字典项") public ResponseData delete(@Validated(BaseEntity.MassRemove.class) @RequestBody DictParam dictParam) { @@ -58,6 +62,7 @@ public ResponseData delete(@Validated(BaseEntity.MassRemove.class) @RequestBody /** * 获取某个字典类型下的所有字典 */ + @Permission(code = "dict") @ResponseBody @RequestMapping("/listDicts") public ResponseData listDicts(@RequestParam("dictTypeId") Long dictTypeId) { @@ -68,6 +73,7 @@ public ResponseData listDicts(@RequestParam("dictTypeId") Long dictTypeId) { * 获取某个字典类型下的所有字典 */ @ResponseBody + @Permission(code = "dict") @RequestMapping("/listDictByCode") public ResponseData listDictByCode(@RequestParam("dictTypeCode") String dictTypeCode) { return ResponseData.success(dictService.listDicts(dictTypeCode)); @@ -77,6 +83,7 @@ public ResponseData listDictByCode(@RequestParam("dictTypeCode") String dictType * 获取某个字典类型下的所有字典 */ @ResponseBody + @Permission(code = "dict") @RequestMapping("/groupDictByCode") public ResponseData groupDictByCode(@RequestParam("dictTypeCode") String dictTypeCode) { return ResponseData.success(dictService.groupDictByCode(dictTypeCode)); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictTypeController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictTypeController.java index a4bbbbb0..e5c6877a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictTypeController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictTypeController.java @@ -4,6 +4,7 @@ import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.sys.dto.param.DictTypeParam; import com.zmops.iot.web.sys.service.DictTypeService; import org.springframework.beans.factory.annotation.Autowired; @@ -27,6 +28,7 @@ public class DictTypeController { /** * 新增字典 */ + @Permission(code = "dict") @RequestMapping("/create") @BussinessLog("新增字典") public ResponseData addItem(@Validated(BaseEntity.Create.class) @RequestBody DictTypeParam dictTypeParam) { @@ -36,6 +38,7 @@ public ResponseData addItem(@Validated(BaseEntity.Create.class) @RequestBody Dic /** * 编辑字典 */ + @Permission(code = "dict") @RequestMapping("/update") @BussinessLog("编辑字典") public ResponseData editItem(@Validated(BaseEntity.Update.class) @RequestBody DictTypeParam dictTypeParam) { @@ -45,6 +48,7 @@ public ResponseData editItem(@Validated(BaseEntity.Update.class) @RequestBody Di /** * 删除字典 */ + @Permission(code = "dict") @RequestMapping("/delete") @BussinessLog("删除字典") public ResponseData delete(@Validated(BaseEntity.MassRemove.class) @RequestBody DictTypeParam dictTypeParam) { @@ -56,6 +60,7 @@ public ResponseData delete(@Validated(BaseEntity.MassRemove.class) @RequestBody /** * 查询列表 */ + @Permission(code = "dict") @PostMapping("/getDictTypeByPage") public Pager list(@RequestBody DictTypeParam dictTypeParam) { return dictTypeService.findPageBySpec(dictTypeParam); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LogController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LogController.java index dabb541f..71173dab 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LogController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LogController.java @@ -1,6 +1,7 @@ package com.zmops.iot.web.sys.controller; import com.zmops.iot.model.page.Pager; +import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.sys.dto.SysOperationLogDto; import com.zmops.iot.web.sys.service.OperationLogService; import org.springframework.beans.factory.annotation.Autowired; @@ -22,6 +23,7 @@ public class LogController { /** * 查询操作日志列表 */ + @Permission(code = "businessLog") @RequestMapping("/getOperationLogByPage") @ResponseBody public Pager list(@RequestParam(required = false) Long beginTime, diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginLogController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginLogController.java index db7950f0..05673912 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginLogController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginLogController.java @@ -1,6 +1,7 @@ package com.zmops.iot.web.sys.controller; import com.zmops.iot.model.page.Pager; +import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.sys.dto.SysLoginLogDto; import com.zmops.iot.web.sys.service.LoginLogService; import org.springframework.beans.factory.annotation.Autowired; @@ -22,6 +23,7 @@ public class LoginLogController { /** * 登录日志列表 */ + @Permission(code = "businessLog") @RequestMapping("/getLoginLogByPage") @ResponseBody public Pager list(@RequestParam(required = false) Long beginTime, diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysParamController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysParamController.java index 6bacc4c6..50ac7b2b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysParamController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysParamController.java @@ -2,6 +2,7 @@ import com.zmops.iot.core.log.BussinessLog; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.sys.dto.SysParamDto; import com.zmops.iot.web.sys.service.SysParamService; import org.springframework.beans.factory.annotation.Autowired; @@ -23,6 +24,7 @@ public class SysParamController { /** * 参数列表 */ + @Permission(code = "sysParam") @GetMapping("/list") public ResponseData list() { return ResponseData.success(sysParamService.list()); @@ -31,6 +33,7 @@ public ResponseData list() { /** * 参数修改 */ + @Permission(code = "sysParam") @PostMapping("/update") @BussinessLog(value = "系统参数修改") public ResponseData update(@Validated @RequestBody SysParamDto sysParamDto) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysRoleController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysRoleController.java index 3bfe6fdf..ca21f1eb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysRoleController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysRoleController.java @@ -3,6 +3,7 @@ import com.zmops.iot.core.log.BussinessLog; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.sys.dto.SysRoleDto; import com.zmops.iot.web.sys.dto.param.RoleParam; import com.zmops.iot.web.sys.service.SysRoleService; @@ -30,6 +31,7 @@ public class SysRoleController { /** * 角色列表 */ + @Permission(code = "role") @RequestMapping("/list") public ResponseData list(@RequestParam(value = "name", required = false) String name) { return ResponseData.success(sysRoleService.list(name)); @@ -38,6 +40,7 @@ public ResponseData list(@RequestParam(value = "name", required = false) String /** * 角色新增 */ + @Permission(code = "role") @RequestMapping("/create") @BussinessLog(value = "角色新增") public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody SysRoleDto sysRoleDto) { @@ -47,6 +50,7 @@ public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody SysR /** * 角色修改 */ + @Permission(code = "role") @RequestMapping("/update") @BussinessLog(value = "角色修改") public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody SysRoleDto sysRoleDto) { @@ -56,6 +60,7 @@ public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody SysR /** * 角色删除 */ + @Permission(code = "role") @RequestMapping("/delete") @BussinessLog(value = "角色删除") public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody RoleParam sysRoleParam) { @@ -68,6 +73,7 @@ public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody Role * * @return */ + @Permission(code = "role") @RequestMapping("/bindMenu") @BussinessLog(value = "角色绑定菜单") public ResponseData bindMenu(@Validated @RequestBody RoleParam roleParam) { @@ -78,6 +84,7 @@ public ResponseData bindMenu(@Validated @RequestBody RoleParam roleParam) { /** * 角色已绑定的菜单 */ + @Permission(code = "role") @RequestMapping("/bindedMenu") public ResponseData bindMenu(@RequestParam(value = "roleId") Long roleId) { return ResponseData.success(sysRoleService.bindedMenu(roleId)); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java index ef0ecebb..64b583c9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java @@ -8,6 +8,7 @@ import com.zmops.iot.domain.sys.query.QSysUser; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.sys.dto.UserDto; import com.zmops.iot.web.sys.dto.param.UserParam; import com.zmops.iot.web.sys.service.SysUserService; @@ -35,6 +36,7 @@ public class SysUserController { * * @return */ + @Permission(code = "mgr") @PostMapping("/getUserByPage") public Pager userList(@RequestBody UserParam userParam) { return sysUserService.userList(userParam); @@ -45,6 +47,7 @@ public Pager userList(@RequestBody UserParam userParam) { * * @return */ + @Permission(code = "mgr") @PostMapping("/create") @BussinessLog(value = "创建用户") public ResponseData createUser(@Validated(BaseEntity.Create.class) @RequestBody UserDto sysUser) { @@ -57,6 +60,7 @@ public ResponseData createUser(@Validated(BaseEntity.Create.class) @RequestBody * * @return */ + @Permission(code = "mgr") @PostMapping("/update") @BussinessLog(value = "更新用户") public ResponseData updateUser(@Validated(value = BaseEntity.Update.class) @RequestBody UserDto userDto) { @@ -68,6 +72,7 @@ public ResponseData updateUser(@Validated(value = BaseEntity.Update.class) @Requ * * @return */ + @Permission(code = "mgr") @PostMapping("/delete") @BussinessLog(value = "删除用户") public ResponseData deleteUser(@Validated(BaseEntity.Delete.class) @RequestBody UserParam user) { @@ -78,6 +83,7 @@ public ResponseData deleteUser(@Validated(BaseEntity.Delete.class) @RequestBody /** * 修改密码 */ + @Permission(code = "mgr") @PostMapping("/changePwd") @BussinessLog(value = "修改密码") public ResponseData changePwd(@Valid @RequestBody UserParam user) { @@ -88,6 +94,7 @@ public ResponseData changePwd(@Valid @RequestBody UserParam user) { /** * 重置管理员的密码 */ + @Permission(code = "mgr") @RequestMapping("/reset") @BussinessLog(value = "重置密码") public ResponseData reset(@RequestParam("userId") Long userId) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserGroupController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserGroupController.java index d4bdddad..f59f3c5f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserGroupController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserGroupController.java @@ -4,6 +4,7 @@ import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.sys.dto.UserGroupDto; import com.zmops.iot.web.sys.dto.param.UserGroupParam; import com.zmops.iot.web.sys.service.SysUserGroupService; @@ -31,6 +32,7 @@ public class SysUserGroupController { * * @return */ + @Permission(code = "usrGrp") @PostMapping("/getUsrGrpByPage") public Pager getUsrGrpByPage(@RequestBody UserGroupParam userGroupParam) { return sysUserGroupService.userGroupPageList(userGroupParam); @@ -41,6 +43,7 @@ public Pager getUsrGrpByPage(@RequestBody UserGroupParam userGroup * * @return */ + @Permission(code = "usrGrp") @PostMapping("/list") public ResponseData userGroupList() { return ResponseData.success(sysUserGroupService.userGroupList()); @@ -51,6 +54,7 @@ public ResponseData userGroupList() { * * @return */ + @Permission(code = "usrGrp") @PostMapping("/create") @BussinessLog(value = "创建用户组") public ResponseData createUserGroup(@Validated @RequestBody UserGroupDto userGroup) { @@ -63,6 +67,7 @@ public ResponseData createUserGroup(@Validated @RequestBody UserGroupDto userGro * * @return */ + @Permission(code = "usrGrp") @PostMapping("/update") @BussinessLog(value = "更新用户组") public ResponseData updateUserGroup(@Validated(BaseEntity.Update.class) @RequestBody UserGroupDto userGroup) { @@ -74,6 +79,7 @@ public ResponseData updateUserGroup(@Validated(BaseEntity.Update.class) @Request * * @return */ + @Permission(code = "usrGrp") @PostMapping("/delete") @BussinessLog(value = "删除用户组") public ResponseData deleteUserGroup(@Validated @RequestBody UserGroupParam userGroup) { @@ -86,6 +92,7 @@ public ResponseData deleteUserGroup(@Validated @RequestBody UserGroupParam userG * * @return */ + @Permission(code = "usrGrp") @PostMapping("/bindHostGrp") @BussinessLog(value = "用户组绑定主机组") public ResponseData bindHostGrp(@Validated(BaseEntity.BindDevice.class) @RequestBody UserGroupParam userGroup) { From a518722c2fb137001e352d34072c5a87c2b0bf4b Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 25 Sep 2021 17:28:11 +0800 Subject: [PATCH 304/763] [fix]: update device --- .../com/zmops/iot/web/device/service/DeviceService.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index cbd4701b..2d7fadf7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -462,9 +462,13 @@ public String valueMapDelete(String valueMapId) { * @return */ public DeviceDto deviceDetail(String deviceId) { + List devGroupIds = deviceGroupService.getDevGroupIds(); + if (ToolUtil.isEmpty(devGroupIds)) { + return new DeviceDto(); + } StringBuilder sql = generateBaseSql(); sql.append(" where d.device_id=:deviceId"); - DeviceDto deviceDto = DB.findDto(DeviceDto.class, sql.toString()).setParameter("deviceId", deviceId).findOne(); + DeviceDto deviceDto = DB.findDto(DeviceDto.class, sql.toString()).setParameter("deviceId", deviceId).setParameter("deviceGroupIds",devGroupIds).findOne(); return deviceDto; } From f3d90dd8d9ea3b2046ec345f62da41d8a19e97a7 Mon Sep 17 00:00:00 2001 From: yefei Date: Sun, 26 Sep 2021 09:23:07 +0800 Subject: [PATCH 305/763] [fix]: fix webapp config --- zeus-starter/src/main/assembly/webapp.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-starter/src/main/assembly/webapp.yml b/zeus-starter/src/main/assembly/webapp.yml index 42a3643c..e0135611 100644 --- a/zeus-starter/src/main/assembly/webapp.yml +++ b/zeus-starter/src/main/assembly/webapp.yml @@ -49,7 +49,7 @@ forest: zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:80} zbxApiToken: 3464dee6b3fa3ce4173972e0497d7b84a93bdf8477ff1bdd51a7719cc0db2cd9 - taosUrl: http://${ZEUS_TAOS_HOST:127.0.0.1}:${ZEUS_TAOS_REST_PORT:6041}/rest/sql/${ZEUS_TAOS_DB:} + taosUrl: http://${ZEUS_TAOS_HOST:127.0.0.1}:${ZEUS_TAOS_REST_PORT:6041}/rest/sql/${ZEUS_TAOS_DB:zeus_data} taosUser: root taosPwd: taosdata From c1004720ec2bbf0082d977802a91f9b509a343fd Mon Sep 17 00:00:00 2001 From: yefei Date: Sun, 26 Sep 2021 10:42:54 +0800 Subject: [PATCH 306/763] [fix]: zbx driver update --- .../src/main/resources/api-json/item/item.trapper.create.ftl | 2 +- .../com/zmops/iot/web/device/service/DeviceLogService.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl b/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl index 64fa0d4a..ee675899 100644 --- a/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl +++ b/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl @@ -7,7 +7,7 @@ "hostid": "${hostId}", "type": ${source}, "trends":"0", - "history":"30d" + "history":"30d", <#if source == '18'> "master_itemid":${masterItemid}, diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java index 6a1de007..ee415e9d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java @@ -64,10 +64,10 @@ public List getLogByPage(String deviceId, String logType, Long tim if (ToolUtil.isEmpty(logType) || (ToolUtil.isNotEmpty(logType) && LOG_TYPE_SERVICE.equals(logType))) { QServiceExecuteRecord query = new QServiceExecuteRecord().deviceId.eq(deviceId); if (null != timeFrom) { - query.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(timeFrom)); + query.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(timeFrom * 1000)); } if (null != timeTill) { - query.createTime.lt(LocalDateTimeUtils.getLDTByMilliSeconds(timeTill)); + query.createTime.lt(LocalDateTimeUtils.getLDTByMilliSeconds(timeTill * 1000)); } List list = query.findList(); if (ToolUtil.isNotEmpty(list)) { From 8b1a2b0ace9963a2d911922464469f19e7219f54 Mon Sep 17 00:00:00 2001 From: yefei Date: Sun, 26 Sep 2021 13:40:42 +0800 Subject: [PATCH 307/763] [fix]: update operational control --- .../iot/web/device/controller/DeviceController.java | 12 ++++++------ .../web/product/controller/ProductController.java | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java index c6b41c88..fe14f68b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java @@ -39,7 +39,7 @@ public class DeviceController { * * @return */ - @Permission(code = "dev") + @Permission(code = "dev_list") @PostMapping("/getDeviceByPage") public Pager devicePageList(@RequestBody DeviceParam deviceParam) { return deviceService.devicePageList(deviceParam); @@ -50,7 +50,7 @@ public Pager devicePageList(@RequestBody DeviceParam deviceParam) { * * @return */ - @Permission(code = "dev") + @Permission(code = "dev_list") @PostMapping("/list") public ResponseData deviceList(@RequestBody DeviceParam deviceParam) { return ResponseData.success(deviceService.deviceList(deviceParam)); @@ -59,7 +59,7 @@ public ResponseData deviceList(@RequestBody DeviceParam deviceParam) { /** * 设备创建 */ - @Permission(code = "dev") + @Permission(code = "dev_add") @RequestMapping("/create") public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody DeviceDto deviceDto) { QDevice qDevice = new QDevice().or().name.eq(deviceDto.getName()); @@ -82,7 +82,7 @@ public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody Devi /** * 设备创建 */ - @Permission(code = "dev") + @Permission(code = "dev_update") @RequestMapping("/update") public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody DeviceDto deviceDto) { int count = new QDevice().deviceId.ne(deviceDto.getDeviceId()).name.eq(deviceDto.getName()).findCount(); @@ -100,7 +100,7 @@ public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody Devi /** * 设备删除 */ - @Permission(code = "dev") + @Permission(code = "dev_delete") @RequestMapping("/delete") public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody DeviceDto deviceDto) { return ResponseData.success(deviceService.delete(deviceDto)); @@ -109,7 +109,7 @@ public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody Devi /** * 设备详情 */ - @Permission(code = "dev") + @Permission(code = "dev_detail") @GetMapping("/detail") public ResponseData prodDetail(@RequestParam("deviceId") String deviceId) { return ResponseData.success(deviceService.deviceDetail(deviceId)); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java index e2fb6804..19126340 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java @@ -46,7 +46,7 @@ public class ProductController { /** * 产品分页列表 */ - @Permission(code = "product") + @Permission(code = "product_list") @PostMapping("/getProductByPage") public Pager getProductByPage(@RequestBody ProductBasicInfo prodBasicInfo) { return productService.getProductByPage(prodBasicInfo); @@ -55,7 +55,7 @@ public Pager getProductByPage(@RequestBody ProductBasicInfo prodBasi /** * 产品列表 */ - @Permission(code = "product") + @Permission(code = "product_list") @PostMapping("/list") public ResponseData prodList(@RequestBody ProductBasicInfo prodBasicInfo) { return ResponseData.success(productService.prodList(prodBasicInfo)); @@ -64,7 +64,7 @@ public ResponseData prodList(@RequestBody ProductBasicInfo prodBasicInfo) { /** * 产品详情 */ - @Permission(code = "product") + @Permission(code = "product_detail") @GetMapping("/detail") public ResponseData prodDetail(@RequestParam("productId") Long prodId) { return ResponseData.success(productService.prodDetail(prodId)); @@ -94,7 +94,7 @@ public ResponseData valueMapList(@RequestParam("productId") Long prodId) { * @param prodBasicInfo 产品基本信息 * @return */ - @Permission(code = "product") + @Permission(code = "product_add") @PostMapping("/create") public ResponseData prodCreate(@RequestBody @Validated(value = BaseEntity.Create.class) ProductBasicInfo prodBasicInfo) { @@ -120,7 +120,7 @@ public ResponseData prodCreate(@RequestBody @Validated(value = BaseEntity.Create * * @return */ - @Permission(code = "product") + @Permission(code = "product_update") @PostMapping("/update") public ResponseData prodUpdate(@RequestBody @Validated(value = BaseEntity.Update.class) ProductBasicInfo prodBasicInfo) { @@ -143,7 +143,7 @@ public ResponseData prodUpdate(@RequestBody @Validated(value = BaseEntity.Update * @param prodBasicInfo 产品基础信息 * @return */ - @Permission(code = "product") + @Permission(code = "product_delete") @PostMapping("/delete") public ResponseData prodDelete(@RequestBody @Validated(value = BaseEntity.Delete.class) ProductBasicInfo prodBasicInfo) { From 8025aa3063ba0967c6964437efe669cd52768c52 Mon Sep 17 00:00:00 2001 From: nantian Date: Sun, 26 Sep 2021 15:20:33 +0800 Subject: [PATCH 308/763] [feat]: change timezone to +8 --- .../com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java index f31c85dc..23c793c1 100644 --- a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java +++ b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java @@ -27,6 +27,8 @@ import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; import lombok.extern.slf4j.Slf4j; +import java.util.TimeZone; + /** * Starter core. Load the core configuration file, and initialize the startup sequence through {@link ModuleManager}. @@ -36,6 +38,8 @@ @Slf4j public class IoTServerBootstrap { public static void start() { + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); + String mode = System.getProperty("mode"); RunningMode.setMode(mode); From 2bee856c11e00c9bd5e6ac1e0b69845766786c9e Mon Sep 17 00:00:00 2001 From: nantian Date: Sun, 26 Sep 2021 15:48:35 +0800 Subject: [PATCH 309/763] [ftx]: -Duser.timezone=GMT+08 --- dist-material/bin/IoTServer.bat | 2 +- dist-material/bin/IoTServer.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist-material/bin/IoTServer.bat b/dist-material/bin/IoTServer.bat index de0e032b..316d3780 100644 --- a/dist-material/bin/IoTServer.bat +++ b/dist-material/bin/IoTServer.bat @@ -19,7 +19,7 @@ setlocal set OAP_PROCESS_TITLE=Zeus-IoT-Server set OAP_HOME=%~dp0%.. -set OAP_OPTS="-Xms1024M -Xmx1024M -Doap.logDir=%OAP_HOME%\logs" +set OAP_OPTS="-Xms1024M -Xmx1024M -Doap.logDir=%OAP_HOME%\logs -Duser.timezone=GMT+08" set CLASSPATH=%OAP_HOME%\config;.; set CLASSPATH=%OAP_HOME%\iot-server-libs\*;%CLASSPATH% diff --git a/dist-material/bin/IoTServer.sh b/dist-material/bin/IoTServer.sh index cfe84f42..d7a011c8 100644 --- a/dist-material/bin/IoTServer.sh +++ b/dist-material/bin/IoTServer.sh @@ -35,7 +35,7 @@ do CLASSPATH="$i:$CLASSPATH" done -IOT_OPTIONS=" -Doap.logDir=${IOT_LOG_DIR}" +IOT_OPTIONS=" -Doap.logDir=${IOT_LOG_DIR} -Duser.timezone=GMT+08" eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${IOT_OPTIONS} -classpath $CLASSPATH com.zmops.zeus.iot.server.starter.IoTServerStartUp \ &> ${IOT_LOG_DIR}/zeus_iot.log &" From 10e10d2b59f50fb3948f26e574067f5e838700bd Mon Sep 17 00:00:00 2001 From: nantian Date: Sun, 26 Sep 2021 15:53:49 +0800 Subject: [PATCH 310/763] [fix]: json parse use fastjson --- .../server-bootstrap/src/main/resources/application.yml | 8 ++++---- iot-server/server-transfer/pom.xml | 5 +++++ .../zeus/iot/server/transfer/sender/SenderManager.java | 9 +++++++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/iot-server/server-bootstrap/src/main/resources/application.yml b/iot-server/server-bootstrap/src/main/resources/application.yml index 9ed8f512..437c40a8 100644 --- a/iot-server/server-bootstrap/src/main/resources/application.yml +++ b/iot-server/server-bootstrap/src/main/resources/application.yml @@ -44,17 +44,17 @@ core: # ndjson file read realtime server-transfer: - selector: ${ZS_SERVER_TRANSFER:-} + selector: ${ZS_SERVER_TRANSFER:default} default: name: ${ZS_TRANSFER_NAME:zeus-transfer} - pattern: ${ZS_TRANSFER_PATTERN:E:\data\history-history-syncer-[0-9]{1}.ndjson} - fileMaxWait: ${ZS_TRANSFER_FILE_MAXWAIT:5} + pattern: ${ZS_TRANSFER_PATTERN:/home/data/history-history-syncer-[0-9]{1}.ndjson} + fileMaxWait: ${ZS_TRANSFER_FILE_MAXWAIT:30} # tdengine storage realtime storage: selector: ${ZS_STORAGE:tdengine} tdengine: - url: ${ZS_STORAGE_TDENGINE_URL:jdbc:TAOS://192.168.1.1:6030/zeus_data} # TDEngine jdbcUrl + url: ${ZS_STORAGE_TDENGINE_URL:jdbc:TAOS://127.0.0.1:6030/zeus_data} # TDEngine jdbcUrl user: ${ZS_STORAGE_TDENGINE_USER:root} password: ${ZS_STORAGE_TDENGINE_PASSWORD:taosdata} diff --git a/iot-server/server-transfer/pom.xml b/iot-server/server-transfer/pom.xml index f664e57f..7e8296f5 100644 --- a/iot-server/server-transfer/pom.xml +++ b/iot-server/server-transfer/pom.xml @@ -43,6 +43,11 @@ com.sleepycat 18.3.12 + + com.alibaba + fastjson + 1.2.58 + org.eclipse.jetty diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java index 75f891fc..dd26891e 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java @@ -1,5 +1,6 @@ package com.zmops.zeus.iot.server.transfer.sender; +import com.alibaba.fastjson.JSON; import com.google.gson.Gson; import com.zmops.zeus.iot.server.core.analysis.manual.history.History; import com.zmops.zeus.iot.server.core.analysis.manual.history.UIntHistory; @@ -13,6 +14,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -28,7 +30,6 @@ public class SenderManager { private final TaskPositionManager taskPositionManager; private final String sourceFilePath; private final PluginMetric metric = new PluginMetric(); - private final Gson gson = new Gson(); public SenderManager(JobProfile jobConf, String bid, String sourceFilePath) { taskPositionManager = TaskPositionManager.getTaskPositionManager(); @@ -46,7 +47,7 @@ public SenderManager(JobProfile jobConf, String bid, String sourceFilePath) { public void sendBatch(String jobId, String bid, String tid, List bodyList, int retry, long dataTime) { try { bodyList.forEach(body -> { - ItemValue itemValue = gson.fromJson(new String(body), ItemValue.class); + ItemValue itemValue = JSON.parseObject(new String(body, StandardCharsets.UTF_8), ItemValue.class); Record record; @@ -91,6 +92,10 @@ static class ItemValue { private Integer itemid; + private List> item_tags; + + private List groups; + private Long ns; private String value; From 355cef5196aa4eb1388bb0ac56909fe0facfe9d2 Mon Sep 17 00:00:00 2001 From: nantian Date: Sun, 26 Sep 2021 19:27:50 +0800 Subject: [PATCH 311/763] [fix]: optimize file loop reading to prevent empty rotation --- .../java/com/zmops/zeus/iot/server/transfer/core/job/Job.java | 4 ++-- .../core/sink/{NdjsonSink.java => DataCarrierSink.java} | 4 ++-- .../server/transfer/core/source/reader/TextFileReader.java | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) rename iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/{NdjsonSink.java => DataCarrierSink.java} (98%) diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java index fbcc07bf..57c15671 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java @@ -8,7 +8,7 @@ import com.zmops.zeus.iot.server.transfer.conf.JobConstants; import com.zmops.zeus.iot.server.transfer.conf.JobProfile; import com.zmops.zeus.iot.server.transfer.core.channel.MemoryChannel; -import com.zmops.zeus.iot.server.transfer.core.sink.NdjsonSink; +import com.zmops.zeus.iot.server.transfer.core.sink.DataCarrierSink; import com.zmops.zeus.iot.server.transfer.core.source.TextFileSource; import com.zmops.zeus.iot.server.transfer.core.task.Task; import lombok.Getter; @@ -56,7 +56,7 @@ public List createTasks() { Source source = new TextFileSource(); for (Reader reader : source.split(jobConf)) { - Sink writer = new NdjsonSink(); + Sink writer = new DataCarrierSink(); writer.setSourceFile(reader.getReadFile()); Channel channel = new MemoryChannel(); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/DataCarrierSink.java similarity index 98% rename from iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java rename to iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/DataCarrierSink.java index 2a206121..0d857819 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/NdjsonSink.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/DataCarrierSink.java @@ -23,9 +23,9 @@ import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.*; -public class NdjsonSink implements Sink { +public class DataCarrierSink implements Sink { - private static final Logger LOGGER = LoggerFactory.getLogger(NdjsonSink.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DataCarrierSink.class); private SenderManager senderManager; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java index 3524cb73..e2a564ec 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java @@ -74,6 +74,7 @@ public Message read() { return new DefaultMessage(message.getBytes(StandardCharsets.UTF_8)); } } + TransferUtils.silenceSleepInMs(100); return null; } From e4205e9299fa1fcf4f61652ebf361ab5116e6d49 Mon Sep 17 00:00:00 2001 From: nantian Date: Sun, 26 Sep 2021 19:36:25 +0800 Subject: [PATCH 312/763] [style]: remove unused constants --- .../server/transfer/conf/CommonConstants.java | 25 -------- .../transfer/conf/TransferConstants.java | 62 +------------------ .../transfer/core/sink/DataCarrierSink.java | 1 - 3 files changed, 1 insertion(+), 87 deletions(-) diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java index 6e7b4427..46a22830 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java @@ -7,10 +7,6 @@ public class CommonConstants { public static final String PROXY_TID = "proxy.tid"; - public static final String PROXY_MAX_SENDER_PER_BID = "proxy.max.sender.per.pid"; - - public static final int DEFAULT_PROXY_MAX_SENDER_PER_PID = 10; - // max size of message list public static final String PROXY_PACKAGE_MAX_SIZE = "proxy.package.maxSize"; @@ -29,22 +25,6 @@ public class CommonConstants { public static final int DEFAULT_PROXY_BATCH_FLUSH_INTERVAL = 100; - public static final String PROXY_SENDER_MAX_TIMEOUT = "proxy.sender.maxTimeout"; - - // max timeout in seconds. - public static final int DEFAULT_PROXY_SENDER_MAX_TIMEOUT = 20; - - public static final String PROXY_SENDER_MAX_RETRY = "proxy.sender.maxRetry"; - - public static final int DEFAULT_PROXY_SENDER_MAX_RETRY = 5; - - public static final String PROXY_IS_FILE = "proxy.isFile"; - public static final boolean DEFAULT_IS_FILE = false; - - public static final String PROXY_RETRY_SLEEP = "proxy.retry.sleep"; - - public static final long DEFAULT_PROXY_RETRY_SLEEP = 500; - public static final String PROXY_KEY_BID = "bid"; public static final String PROXY_KEY_TID = "tid"; public static final String PROXY_KEY_ID = "id"; @@ -61,9 +41,4 @@ public class CommonConstants { public static final String COMMAND_STORE_INSTANCE_NAME = "commandStore"; - public static final String AGENT_OS_NAME = "os.name"; - public static final String AGENT_NIX_OS = "nix"; - public static final String AGENT_NUX_OS = "nux"; - public static final String AGENT_COLON = ":"; - } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java index 360189ec..7d489927 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java @@ -1,52 +1,26 @@ package com.zmops.zeus.iot.server.transfer.conf; -import com.zmops.zeus.iot.server.transfer.utils.TransferUtils; - public class TransferConstants { public static final String AGENT_HOME = "agent.home"; public static final String DEFAULT_AGENT_HOME = System.getProperty("agent.home"); - public static final String AGENT_LOCAL_CACHE = "agent.local.cache"; - public static final String DEFAULT_AGENT_LOCAL_CACHE = ".local"; - - public static final String AGENT_LOCAL_CACHE_TIMEOUT = "agent.local.cache.timeout"; - /** - * cache timeout in minutes. - **/ - public static final int DEFAULT_AGENT_LOCAL_CACHE_TIMEOUT = 30; public static final String AGENT_LOCAL_STORE_PATH = "agent.localStore.path"; public static final String DEFAULT_AGENT_LOCAL_STORE_PATH = ".bdb"; - public static final String AGENT_ROCKS_DB_PATH = "agent.rocks.db.path"; - public static final String DEFAULT_AGENT_ROCKS_DB_PATH = ".rocksdb"; - - public static final String AGENT_UNIQ_ID = "agent.uniq.id"; - // default use local ip as uniq id for agent. - public static final String DEFAULT_AGENT_UNIQ_ID = TransferUtils.getLocalIp(); - public static final String AGENT_DB_INSTANCE_NAME = "agent.db.instance.name"; public static final String DEFAULT_AGENT_DB_INSTANCE_NAME = "agent"; public static final String AGENT_DB_CLASSNAME = "agent.db.classname"; public static final String DEFAULT_AGENT_DB_CLASSNAME = "com.zmops.zeus.iot.server.transfer.core.db.BerkeleyDbImp"; - // default is empty. - public static final String AGENT_FETCHER_CLASSNAME = "agent.fetcher.classname"; - public static final String AGENT_CONF_PARENT = "agent.conf.parent"; public static final String DEFAULT_AGENT_CONF_PARENT = "conf"; public static final String AGENT_LOCAL_STORE_READONLY = "agent.localStore.readonly"; public static final boolean DEFAULT_AGENT_LOCAL_STORE_READONLY = false; - public static final String AGENT_HTTP_PORT = "agent.http.port"; - public static final int DEFAULT_AGENT_HTTP_PORT = 8008; - - public static final String AGENT_ENABLE_HTTP = "agent.http.enable"; - public static final boolean DEFAULT_AGENT_ENABLE_HTTP = true; - public static final String TRIGGER_FETCH_INTERVAL = "trigger.fetch.interval"; public static final int DEFAULT_TRIGGER_FETCH_INTERVAL = 1; @@ -62,52 +36,22 @@ public class TransferConstants { public static final String AGENT_LOCAL_STORE_NO_SYNC_VOID = "agent.localStore.noSyncVoid"; public static final boolean DEFAULT_AGENT_LOCAL_STORE_NO_SYNC_VOID = false; - public static final String AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID = - "agent.localStore.WriteNoSyncVoid"; + public static final String AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID = "agent.localStore.WriteNoSyncVoid"; public static final boolean DEFAULT_AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID = false; - public static final String AGENT_FETCH_CENTER_INTERVAL_SECONDS = "agent.fetchCenter.interval"; - public static final int DEFAULT_AGENT_FETCH_CENTER_INTERVAL_SECONDS = 5; - - public static final String AGENT_TRIGGER_CHECK_INTERVAL_SECONDS = "agent.trigger.check.interval"; - public static final int DEFAULT_AGENT_TRIGGER_CHECK_INTERVAL_SECONDS = 1; public static final String THREAD_POOL_AWAIT_TIME = "thread.pool.await.time"; // time in ms public static final long DEFAULT_THREAD_POOL_AWAIT_TIME = 300; - public static final String JOB_THREAD_PENDING_MAX = "job.thread.pending.max"; - public static final int DEFAULT_JOB_THREAD_PENDING_MAX = 40; - - public static final String JOB_THREAD_RUNNING_CORE = "job.thread.running.core"; - public static final int DEFAULT_JOB_THREAD_RUNNING_CORE = 4; - public static final String JOB_MONITOR_INTERVAL = "job.monitor.interval"; public static final int DEFAULT_JOB_MONITOR_INTERVAL = 5; - public static final String JOB_THREAD_RUNNING_MAX = "job.thread.running.max"; - public static final int DEFAULT_JOB_THREAD_RUNNING_MAX = 20; - - public static final String JOB_RUNNING_THREAD_KEEP_ALIVE = "job.running.thread.keepAlive"; - public static final long DEFAULT_JOB_RUNNING_THREAD_KEEP_ALIVE = 60L; public static final String JOB_FINISH_CHECK_INTERVAL = "job.finish.checkInterval"; public static final long DEFAULT_JOB_FINISH_CHECK_INTERVAL = 6L; - public static final String TASK_PENDING_MAX = "task.pending.max"; - public static final int DEFAULT_TASK_PENDING_MAX = 100; - - public static final String TASK_RUNNING_THREAD_CORE_SIZE = "task.running.thread.coreSize"; - public static final int DEFAULT_TASK_RUNNING_THREAD_CORE_SIZE = 4; - - public static final String TASK_RUNNING_THREAD_MAX_SIZE = "task.running.thread.maxSize"; - public static final int DEFAULT_TASK_RUNNING_THREAD_MAX_SIZE = - Runtime.getRuntime().availableProcessors() * 2; - - public static final String TASK_RUNNING_THREAD_KEEP_ALIVE = "task.running.thread.keepAlive"; - public static final long DEFAULT_TASK_RUNNING_THREAD_KEEP_ALIVE = 60L; - public static final String TASK_RETRY_MAX_CAPACITY = "task.retry.maxCapacity"; public static final int DEFAULT_TASK_RETRY_MAX_CAPACITY = 10000; @@ -132,9 +76,6 @@ public class TransferConstants { public static final String TRIGGER_CHECK_INTERVAL = "trigger.check.interval"; public static final int DEFAULT_TRIGGER_CHECK_INTERVAL = 2; - public static final String WORKER_POOL_AWAIT_TIME = "worker.pool.await.time"; - public static final long DEFAULT_WORKER_POOL_AWAIT_TIME = 10; - public static final String JOB_DB_CACHE_TIME = "job.db.cache.time"; // cache for 3 days. public static final long DEFAULT_JOB_DB_CACHE_TIME = 3 * 24 * 60 * 60 * 1000; @@ -142,6 +83,5 @@ public class TransferConstants { public static final String JOB_DB_CACHE_CHECK_INTERVAL = "job.db.cache.check.interval"; public static final int DEFAULT_JOB_DB_CACHE_CHECK_INTERVAL = 60 * 60; - public static final String AGENT_LOCAL_IP = "agent.local.ip"; } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/DataCarrierSink.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/DataCarrierSink.java index 0d857819..507b61c4 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/DataCarrierSink.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/DataCarrierSink.java @@ -22,7 +22,6 @@ import static com.zmops.zeus.iot.server.transfer.conf.CommonConstants.*; import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.*; - public class DataCarrierSink implements Sink { private static final Logger LOGGER = LoggerFactory.getLogger(DataCarrierSink.class); From ff6de6d40f338de2de225ffdef6fbf2fd41b84da Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Sun, 26 Sep 2021 20:54:15 +0800 Subject: [PATCH 313/763] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=BF=AB=E9=80=9F?= =?UTF-8?q?=E9=83=A8=E7=BD=B2=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dist-material/bin/sql/zeus-iot.sql | 2563 ++++++++++++++++++ docs/{quick-install.sh => centos/install.sh} | 157 +- 2 files changed, 2662 insertions(+), 58 deletions(-) create mode 100644 dist-material/bin/sql/zeus-iot.sql rename docs/{quick-install.sh => centos/install.sh} (71%) diff --git a/dist-material/bin/sql/zeus-iot.sql b/dist-material/bin/sql/zeus-iot.sql new file mode 100644 index 00000000..1b530a2b --- /dev/null +++ b/dist-material/bin/sql/zeus-iot.sql @@ -0,0 +1,2563 @@ +/* + Navicat Premium Data Transfer + + Source Server : 172.16.60.98-测试LOT + Source Server Type : PostgreSQL + Source Server Version : 120008 + Source Host : 172.16.60.98:5432 + Source Catalog : zeus-iot + Source Schema : public + + Target Server Type : PostgreSQL + Target Server Version : 120008 + File Encoding : 65001 + + Date: 23/09/2021 11:43:08 +*/ + + +-- ---------------------------- +-- Sequence structure for device_online_report_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."device_online_report_id_seq"; +CREATE SEQUENCE "public"."device_online_report_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for devices_groups_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."devices_groups_id_seq"; +CREATE SEQUENCE "public"."devices_groups_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for media_type_setting_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."media_type_setting_id_seq"; +CREATE SEQUENCE "public"."media_type_setting_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for messages_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."messages_id_seq"; +CREATE SEQUENCE "public"."messages_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for product_event_relation_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."product_event_relation_id_seq"; +CREATE SEQUENCE "public"."product_event_relation_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for product_event_tags_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."product_event_tags_id_seq"; +CREATE SEQUENCE "public"."product_event_tags_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for product_service_relation_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."product_service_relation_id_seq"; +CREATE SEQUENCE "public"."product_service_relation_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for product_status_function_relation_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."product_status_function_relation_id_seq"; +CREATE SEQUENCE "public"."product_status_function_relation_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for product_type_product_type_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."product_type_product_type_id_seq"; +CREATE SEQUENCE "public"."product_type_product_type_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for service_execute_record_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."service_execute_record_id_seq"; +CREATE SEQUENCE "public"."service_execute_record_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for service_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."service_id_seq"; +CREATE SEQUENCE "public"."service_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for service_param_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."service_param_id_seq"; +CREATE SEQUENCE "public"."service_param_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sys_user_group_user_group_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sys_user_group_user_group_id_seq"; +CREATE SEQUENCE "public"."sys_user_group_user_group_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sys_user_user_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sys_user_user_id_seq"; +CREATE SEQUENCE "public"."sys_user_user_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for tag_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."tag_id_seq"; +CREATE SEQUENCE "public"."tag_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + +-- ---------------------------- +-- Table structure for device +-- ---------------------------- +DROP TABLE IF EXISTS "public"."device"; +CREATE TABLE "public"."device" ( + "device_id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, + "name" varchar(255) COLLATE "pg_catalog"."default", + "product_id" int8, + "status" varchar(16) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "create_time" timestamp(6), + "create_user" int8, + "update_time" timestamp(6), + "update_user" int8, + "type" varchar(16) COLLATE "pg_catalog"."default", + "zbx_id" varchar(32) COLLATE "pg_catalog"."default", + "addr" varchar(255) COLLATE "pg_catalog"."default", + "position" varchar(64) COLLATE "pg_catalog"."default", + "online" int2 DEFAULT 1 +) +; +COMMENT ON COLUMN "public"."device"."device_id" IS '设备ID'; +COMMENT ON COLUMN "public"."device"."name" IS '设备名称'; +COMMENT ON COLUMN "public"."device"."product_id" IS '关联产品'; +COMMENT ON COLUMN "public"."device"."status" IS '状态'; +COMMENT ON COLUMN "public"."device"."remark" IS '备注'; +COMMENT ON COLUMN "public"."device"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."device"."create_user" IS '创建者'; +COMMENT ON COLUMN "public"."device"."update_time" IS '系统时间'; +COMMENT ON COLUMN "public"."device"."update_user" IS '修改者'; +COMMENT ON COLUMN "public"."device"."type" IS '设备类型'; +COMMENT ON COLUMN "public"."device"."zbx_id" IS 'zbx主机ID'; +COMMENT ON COLUMN "public"."device"."addr" IS '设备地址'; +COMMENT ON COLUMN "public"."device"."position" IS '地址坐标'; +COMMENT ON COLUMN "public"."device"."online" IS '是否在线 1是 0否'; + +-- ---------------------------- +-- Records of device +-- ---------------------------- +INSERT INTO "public"."device" VALUES ('101', '温度传感器', 1440880212866494464, 'ENABLE', '', '2021-09-23 11:27:40.882', 1, '2021-09-23 11:27:41.038', 1, '1', '10590', NULL, NULL, 1); + +-- ---------------------------- +-- Table structure for device_group +-- ---------------------------- +DROP TABLE IF EXISTS "public"."device_group"; +CREATE TABLE "public"."device_group" ( + "device_group_id" int8 NOT NULL, + "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "remark" varchar(255) COLLATE "pg_catalog"."default", + "zbx_id" varchar(32) COLLATE "pg_catalog"."default" NOT NULL, + "create_user" int8, + "create_time" timestamp(6), + "update_user" int8, + "update_time" timestamp(6) +) +; +COMMENT ON COLUMN "public"."device_group"."device_group_id" IS '主机组ID'; +COMMENT ON COLUMN "public"."device_group"."name" IS '主机组名称'; +COMMENT ON COLUMN "public"."device_group"."remark" IS '备注'; +COMMENT ON COLUMN "public"."device_group"."zbx_id" IS 'zabbix 主机组ID'; +COMMENT ON COLUMN "public"."device_group"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."device_group"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."device_group"."update_user" IS '更新人'; +COMMENT ON COLUMN "public"."device_group"."update_time" IS '更新时间'; + +-- ---------------------------- +-- Records of device_group +-- ---------------------------- +INSERT INTO "public"."device_group" VALUES (1440880403610857472, '我的设备组', '', '55', 1, '2021-09-23 11:27:13.22', 1, '2021-09-23 11:27:13.22'); + +-- ---------------------------- +-- Table structure for device_online_report +-- ---------------------------- +DROP TABLE IF EXISTS "public"."device_online_report"; +CREATE TABLE "public"."device_online_report" ( + "id" int8 NOT NULL DEFAULT nextval('device_online_report_id_seq'::regclass), + "create_time" varchar(10) COLLATE "pg_catalog"."default", + "online" int4, + "offline" int4, + "type" int2 +) +; +COMMENT ON COLUMN "public"."device_online_report"."online" IS '在线数'; +COMMENT ON COLUMN "public"."device_online_report"."offline" IS '离线数'; +COMMENT ON COLUMN "public"."device_online_report"."type" IS '设备类型'; + +-- ---------------------------- +-- Records of device_online_report +-- ---------------------------- + +-- ---------------------------- +-- Table structure for devices_groups +-- ---------------------------- +DROP TABLE IF EXISTS "public"."devices_groups"; +CREATE TABLE "public"."devices_groups" ( + "id" int8 NOT NULL DEFAULT nextval('devices_groups_id_seq'::regclass), + "device_id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, + "device_group_id" int8 NOT NULL +) +; +COMMENT ON COLUMN "public"."devices_groups"."id" IS 'ID'; +COMMENT ON COLUMN "public"."devices_groups"."device_id" IS '设备ID'; +COMMENT ON COLUMN "public"."devices_groups"."device_group_id" IS '设备组ID'; + +-- ---------------------------- +-- Records of devices_groups +-- ---------------------------- +INSERT INTO "public"."devices_groups" VALUES (170, '101', 1440880403610857472); + +-- ---------------------------- +-- Table structure for media_type_setting +-- ---------------------------- +DROP TABLE IF EXISTS "public"."media_type_setting"; +CREATE TABLE "public"."media_type_setting" ( + "id" int4 NOT NULL DEFAULT nextval('media_type_setting_id_seq'::regclass), + "type" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, + "template" text COLLATE "pg_catalog"."default", + "webhooks" text COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."media_type_setting"."type" IS '类型'; +COMMENT ON COLUMN "public"."media_type_setting"."template" IS '消息模板'; +COMMENT ON COLUMN "public"."media_type_setting"."webhooks" IS '推送配置'; + +-- ---------------------------- +-- Records of media_type_setting +-- ---------------------------- +INSERT INTO "public"."media_type_setting" VALUES (3, 'feishu', '{ + "msg_type":"text", + "content": { + "text":"%s" + } +}', '{"url":"https://open.feishu.cn/open-apis/bot/v2/hook/c43e56f3-bdc9-4abb-ba4c-17afc6147f73","secret":"xoaP9dPKLeQIeDk5jZnEdg"}'); +INSERT INTO "public"."media_type_setting" VALUES (1, 'wechat', ' +{ + "content": "广州今日天气:29度,大部分多云,降雨概率:80%", + "mentioned_list":["wangqing","@all"], + "mentioned_mobile_list":["13800001111","@all"] + } +', '{"url":"https://oapi.dingtalk.com/robot/send?access_token=dd0f8a3340c15ec0f1d54b91980584c1127abe6dd143a964d44385647bc15124"}'); +INSERT INTO "public"."media_type_setting" VALUES (2, 'dingtalk', '{ + "msgtype":"text", + "text": { + "content":"%s" + } +}', '{"url":"https://oapi.dingtalk.com/robot/send?access_token=dd0f8a3340c15ec0f1d54b91980584c1127abe6dd143a964d44385647bc15124","secret":"SEC9b9e759c78a216ddcbeb2612694dbd6e7420b75fe78ffe0de9fac0701e3d4d45"}'); + +-- ---------------------------- +-- Table structure for messages +-- ---------------------------- +DROP TABLE IF EXISTS "public"."messages"; +CREATE TABLE "public"."messages" ( + "classify" int4 NOT NULL, + "title" varchar(200) COLLATE "pg_catalog"."default" NOT NULL, + "content" text COLLATE "pg_catalog"."default", + "clock" int4 NOT NULL, + "module" varchar(100) COLLATE "pg_catalog"."default" DEFAULT NULL::character varying, + "readed" int2 DEFAULT 0, + "user_id" int8, + "id" int8 NOT NULL DEFAULT nextval('messages_id_seq'::regclass) +) +; +COMMENT ON COLUMN "public"."messages"."classify" IS '消息的类型'; +COMMENT ON COLUMN "public"."messages"."module" IS '消息跳转的模块'; +COMMENT ON COLUMN "public"."messages"."readed" IS '是否已读 1-是 0-否'; + +-- ---------------------------- +-- Records of messages +-- ---------------------------- +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630303245, NULL, NULL, 1, 55); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630303288, NULL, NULL, 1, 56); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630303362, NULL, NULL, 1, 57); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630303458, NULL, NULL, 1, 58); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630304019, NULL, NULL, 1, 59); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630304038, NULL, NULL, 1, 60); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630304155, NULL, NULL, 1, 61); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630304242, NULL, NULL, 1, 62); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919518, NULL, NULL, 1, 63); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919518, NULL, NULL, 1, 64); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919518, NULL, NULL, 1, 65); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919518, NULL, NULL, 1, 66); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919518, NULL, NULL, 1, 67); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919564, NULL, NULL, 1, 68); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919564, NULL, NULL, 1, 69); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919564, NULL, NULL, 1, 70); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919564, NULL, NULL, 1, 71); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919564, NULL, NULL, 1, 72); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630921533, NULL, NULL, 1, 73); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630921533, NULL, NULL, 1, 74); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630921533, NULL, NULL, 1, 75); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630921533, NULL, NULL, 1, 76); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630921533, NULL, NULL, 1, 77); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"{TRIGGER.DESCRIPTION","hostname":"1432636352419790848"}', 1631763023, NULL, NULL, 80, 78); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"{TRIGGER.DESCRIPTION","hostname":"1432636352419790848"}', 1631763023, NULL, NULL, 1, 79); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"{TRIGGER.DESCRIPTION","hostname":"1432636352419790848"}', 1631763023, NULL, NULL, 115, 80); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"{TRIGGER.DESCRIPTION","hostname":"1432636352419790848"}', 1631763023, NULL, NULL, 79, 81); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"","hostname":"1432636352419790848"}', 1631763230, NULL, NULL, 80, 82); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"","hostname":"1432636352419790848"}', 1631763230, NULL, NULL, 1, 83); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"","hostname":"1432636352419790848"}', 1631763230, NULL, NULL, 115, 84); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"","hostname":"1432636352419790848"}', 1631763230, NULL, NULL, 79, 85); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763232, NULL, NULL, 80, 86); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763232, NULL, NULL, 1, 87); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763232, NULL, NULL, 115, 88); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763232, NULL, NULL, 79, 89); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763259, NULL, NULL, 80, 90); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763259, NULL, NULL, 1, 91); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763259, NULL, NULL, 115, 92); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763259, NULL, NULL, 79, 93); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763260, NULL, NULL, 80, 94); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763260, NULL, NULL, 1, 95); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763260, NULL, NULL, 115, 96); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763260, NULL, NULL, 79, 97); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"{EVENT.OBJECTID}​"}', 1631763533, NULL, NULL, 80, 98); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"{EVENT.OBJECTID}​"}', 1631763533, NULL, NULL, 1, 99); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"{EVENT.OBJECTID}​"}', 1631763533, NULL, NULL, 115, 100); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"{EVENT.OBJECTID}​"}', 1631763533, NULL, NULL, 79, 101); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"{EVENT.OBJECTID}​"}', 1631763535, NULL, NULL, 80, 102); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"{EVENT.OBJECTID}​"}', 1631763535, NULL, NULL, 1, 103); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"{EVENT.OBJECTID}​"}', 1631763535, NULL, NULL, 115, 104); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"{EVENT.OBJECTID}​"}', 1631763535, NULL, NULL, 79, 105); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"​"}', 1631763972, NULL, NULL, 80, 106); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"​"}', 1631763972, NULL, NULL, 1, 107); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"​"}', 1631763972, NULL, NULL, 115, 108); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"​"}', 1631763972, NULL, NULL, 79, 109); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"​"}', 1631763973, NULL, NULL, 80, 110); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"​"}', 1631763973, NULL, NULL, 1, 111); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"​"}', 1631763973, NULL, NULL, 115, 112); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"​"}', 1631763973, NULL, NULL, 79, 113); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631764088, NULL, NULL, 80, 114); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631764088, NULL, NULL, 1, 115); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631764088, NULL, NULL, 115, 116); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631764088, NULL, NULL, 79, 117); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631764090, NULL, NULL, 80, 118); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631764090, NULL, NULL, 1, 119); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631764090, NULL, NULL, 115, 120); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631764090, NULL, NULL, 79, 121); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774313, NULL, NULL, 80, 122); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774313, NULL, NULL, 1, 123); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774313, NULL, NULL, 115, 124); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774313, NULL, NULL, 79, 125); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774326, NULL, NULL, 80, 126); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774327, NULL, NULL, 1, 127); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774327, NULL, NULL, 115, 128); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774327, NULL, NULL, 79, 129); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774425, NULL, NULL, 80, 130); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774425, NULL, NULL, 115, 131); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774425, NULL, NULL, 1, 132); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774425, NULL, NULL, 79, 133); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774451, NULL, NULL, 80, 134); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774451, NULL, NULL, 115, 135); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774451, NULL, NULL, 1, 136); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774451, NULL, NULL, 79, 137); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774484, NULL, NULL, 80, 138); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774484, NULL, NULL, 115, 139); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774484, NULL, NULL, 1, 140); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774484, NULL, NULL, 79, 141); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774505, NULL, NULL, 80, 142); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774505, NULL, NULL, 115, 143); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774505, NULL, NULL, 1, 144); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774505, NULL, NULL, 79, 145); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774729, NULL, NULL, 80, 146); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774729, NULL, NULL, 115, 147); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774729, NULL, NULL, 1, 148); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774729, NULL, NULL, 79, 149); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774749, NULL, NULL, 80, 150); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774749, NULL, NULL, 115, 151); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774749, NULL, NULL, 1, 152); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774749, NULL, NULL, 79, 153); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggername":"1436570370054893568​","triggerid":"20077​"}', 1631775655, NULL, NULL, 80, 154); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggername":"1436570370054893568​","triggerid":"20077​"}', 1631775655, NULL, NULL, 115, 155); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggername":"1436570370054893568​","triggerid":"20077​"}', 1631775655, NULL, NULL, 1, 156); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggername":"1436570370054893568​","triggerid":"20077​"}', 1631775655, NULL, NULL, 79, 157); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggername":"1436570370054893568​","triggerid":"20077​"}', 1631775672, NULL, NULL, 80, 158); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggername":"1436570370054893568​","triggerid":"20077​"}', 1631775672, NULL, NULL, 115, 159); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggername":"1436570370054893568​","triggerid":"20077​"}', 1631775673, NULL, NULL, 1, 160); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggername":"1436570370054893568​","triggerid":"20077​"}', 1631775673, NULL, NULL, 79, 161); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438757419495247872​","triggerid":"20106​"}', 1631861533, NULL, NULL, 1, 162); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438757419495247872​","triggerid":"20106​"}', 1631861533, NULL, NULL, 116, 163); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438757419495247872​","triggerid":"20106​"}', 1631861533, NULL, NULL, 79, 164); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438757739495477248​","triggerid":"20107​"}', 1631861635, NULL, NULL, 1, 165); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438757739495477248​","triggerid":"20107​"}', 1631861635, NULL, NULL, 116, 166); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438757739495477248​","triggerid":"20107​"}', 1631861635, NULL, NULL, 79, 167); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438758964660064256​","triggerid":"20108​"}', 1631861892, NULL, NULL, 1, 168); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438758964660064256​","triggerid":"20108​"}', 1631861892, NULL, NULL, 116, 169); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438758964660064256​","triggerid":"20108​"}', 1631861892, NULL, NULL, 79, 170); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438759211675209728​","triggerid":"20109​"}', 1631861959, NULL, NULL, 1, 171); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438759211675209728​","triggerid":"20109​"}', 1631861959, NULL, NULL, 116, 172); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438759211675209728​","triggerid":"20109​"}', 1631861959, NULL, NULL, 79, 173); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438759729210335232​","triggerid":"20110​"}', 1631862201, NULL, NULL, 1, 174); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438759729210335232​","triggerid":"20110​"}', 1631862201, NULL, NULL, 116, 175); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438759729210335232​","triggerid":"20110​"}', 1631862201, NULL, NULL, 79, 176); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438759844151042048​","triggerid":"20111​"}', 1631862205, NULL, NULL, 1, 177); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438759844151042048​","triggerid":"20111​"}', 1631862205, NULL, NULL, 116, 178); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438759844151042048​","triggerid":"20111​"}', 1631862205, NULL, NULL, 79, 179); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438762285726703616​","triggerid":"20112​"}', 1631862674, NULL, NULL, 1, 180); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438762285726703616​","triggerid":"20112​"}', 1631862674, NULL, NULL, 116, 181); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438762285726703616​","triggerid":"20112​"}', 1631862675, NULL, NULL, 79, 182); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438763312085536768​","triggerid":"20113​"}', 1631862918, NULL, NULL, 1, 183); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438763312085536768​","triggerid":"20113​"}', 1631862918, NULL, NULL, 116, 184); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438763312085536768​","triggerid":"20113​"}', 1631862918, NULL, NULL, 79, 185); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438773665242583040​","triggerid":"20115​"}', 1631865382, NULL, NULL, 1, 186); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438773665242583040​","triggerid":"20115​"}', 1631865382, NULL, NULL, 116, 187); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438773665242583040​","triggerid":"20115​"}', 1631865382, NULL, NULL, 79, 188); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438773665242583040​","triggerid":"20115​"}', 1631868823, NULL, NULL, 1, 189); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438773665242583040​","triggerid":"20115​"}', 1631868823, NULL, NULL, 116, 190); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438773665242583040​","triggerid":"20115​"}', 1631868823, NULL, NULL, 79, 191); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438773665242583040​","triggerid":"20115​"}', 1631868829, NULL, NULL, 1, 192); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438773665242583040​","triggerid":"20115​"}', 1631868829, NULL, NULL, 116, 193); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438773665242583040​","triggerid":"20115​"}', 1631868829, NULL, NULL, 79, 194); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299476, NULL, NULL, 1, 195); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299476, NULL, NULL, 116, 196); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299476, NULL, NULL, 79, 197); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299697, NULL, NULL, 1, 198); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299697, NULL, NULL, 116, 199); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299697, NULL, NULL, 79, 200); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299723, NULL, NULL, 1, 201); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299723, NULL, NULL, 116, 202); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299723, NULL, NULL, 79, 203); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299759, NULL, NULL, 1, 204); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299759, NULL, NULL, 116, 205); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299759, NULL, NULL, 79, 206); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299788, NULL, NULL, 1, 207); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299788, NULL, NULL, 116, 208); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299788, NULL, NULL, 79, 209); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299845, NULL, NULL, 1, 210); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299845, NULL, NULL, 116, 211); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299845, NULL, NULL, 79, 212); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299870, NULL, NULL, 1, 213); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299870, NULL, NULL, 116, 214); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299870, NULL, NULL, 79, 215); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632316171, NULL, NULL, 1, 216); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632316171, NULL, NULL, 116, 217); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632316171, NULL, NULL, 79, 218); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632316187, NULL, NULL, 1, 219); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632316187, NULL, NULL, 116, 220); +INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632316187, NULL, NULL, 79, 221); + +-- ---------------------------- +-- Table structure for product +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product"; +CREATE TABLE "public"."product" ( + "product_id" int8 NOT NULL, + "group_id" int8, + "name" varchar(255) COLLATE "pg_catalog"."default", + "type" varchar(64) COLLATE "pg_catalog"."default", + "manufacturer" varchar(255) COLLATE "pg_catalog"."default", + "model" varchar(255) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "create_time" timestamp(6), + "create_user" int8, + "update_time" timestamp(6), + "update_user" int8, + "product_code" varchar(255) COLLATE "pg_catalog"."default", + "zbx_id" varchar(32) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."product"."product_id" IS '产品ID'; +COMMENT ON COLUMN "public"."product"."group_id" IS '产品组ID'; +COMMENT ON COLUMN "public"."product"."name" IS '产品名称'; +COMMENT ON COLUMN "public"."product"."type" IS '设备类型'; +COMMENT ON COLUMN "public"."product"."manufacturer" IS '厂商'; +COMMENT ON COLUMN "public"."product"."model" IS '型号'; +COMMENT ON COLUMN "public"."product"."remark" IS '备注描述'; +COMMENT ON COLUMN "public"."product"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."product"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."product"."update_time" IS '更新时间'; +COMMENT ON COLUMN "public"."product"."update_user" IS '更新人'; +COMMENT ON COLUMN "public"."product"."product_code" IS '产品编号'; +COMMENT ON COLUMN "public"."product"."zbx_id" IS 'Zabbix对应模板ID'; + +-- ---------------------------- +-- Records of product +-- ---------------------------- +INSERT INTO "public"."product" VALUES (1440880212866494464, 214, '温度计', '1', '', '', '', '2021-09-23 11:26:27.74', 1, '2021-09-23 11:26:27.74', 1, 'wd0001', '10589'); + +-- ---------------------------- +-- Table structure for product_attribute +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_attribute"; +CREATE TABLE "public"."product_attribute" ( + "attr_id" int8 NOT NULL, + "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "key" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "units" varchar(16) COLLATE "pg_catalog"."default", + "source" varchar(16) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "product_id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, + "create_user" int8, + "create_time" timestamp(6), + "update_user" int8, + "update_time" timestamp(6), + "zbx_id" varchar(32) COLLATE "pg_catalog"."default", + "value_type" varchar(16) COLLATE "pg_catalog"."default", + "dep_attr_id" int8, + "template_id" int8 +) +; +COMMENT ON COLUMN "public"."product_attribute"."attr_id" IS '属性ID'; +COMMENT ON COLUMN "public"."product_attribute"."name" IS '属性名称'; +COMMENT ON COLUMN "public"."product_attribute"."key" IS '属性标识Key'; +COMMENT ON COLUMN "public"."product_attribute"."units" IS '数字类型单位'; +COMMENT ON COLUMN "public"."product_attribute"."source" IS '数据来源'; +COMMENT ON COLUMN "public"."product_attribute"."remark" IS '备注描述'; +COMMENT ON COLUMN "public"."product_attribute"."product_id" IS '产品ID'; +COMMENT ON COLUMN "public"."product_attribute"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."product_attribute"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."product_attribute"."update_user" IS '更新人'; +COMMENT ON COLUMN "public"."product_attribute"."update_time" IS '更新时间'; +COMMENT ON COLUMN "public"."product_attribute"."zbx_id" IS 'itemid'; +COMMENT ON COLUMN "public"."product_attribute"."value_type" IS '值类型'; +COMMENT ON COLUMN "public"."product_attribute"."dep_attr_id" IS '依赖属性ID'; +COMMENT ON COLUMN "public"."product_attribute"."template_id" IS '继承的属性ID'; + +-- ---------------------------- +-- Records of product_attribute +-- ---------------------------- +INSERT INTO "public"."product_attribute" VALUES (1440880744175759360, '温度', 'wd', NULL, '2', NULL, '1440880212866494464', 1, '2021-09-23 11:28:34.672', 1, '2021-09-23 11:28:34.672', '37912', '0', NULL, NULL); +INSERT INTO "public"."product_attribute" VALUES (1440880745664737280, '温度', 'wd', NULL, '2', NULL, '101', 1, '2021-09-23 11:28:34.693', 1, '2021-09-23 11:28:34.778', '37913', '0', NULL, 1440880744175759360); + +-- ---------------------------- +-- Table structure for product_attribute_event +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_attribute_event"; +CREATE TABLE "public"."product_attribute_event" ( + "attr_id" int8 NOT NULL, + "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "key" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "units" varchar(16) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "product_id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, + "create_user" int8, + "create_time" timestamp(6), + "update_user" int8, + "update_time" timestamp(6), + "zbx_id" varchar(32) COLLATE "pg_catalog"."default", + "value_type" varchar(16) COLLATE "pg_catalog"."default", + "template_id" int8, + "event_level" char(1) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."product_attribute_event"."attr_id" IS '属性ID'; +COMMENT ON COLUMN "public"."product_attribute_event"."name" IS '属性名称'; +COMMENT ON COLUMN "public"."product_attribute_event"."key" IS '属性标识Key'; +COMMENT ON COLUMN "public"."product_attribute_event"."units" IS '数字类型单位'; +COMMENT ON COLUMN "public"."product_attribute_event"."remark" IS '备注描述'; +COMMENT ON COLUMN "public"."product_attribute_event"."product_id" IS '产品ID'; +COMMENT ON COLUMN "public"."product_attribute_event"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."product_attribute_event"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."product_attribute_event"."update_user" IS '更新人'; +COMMENT ON COLUMN "public"."product_attribute_event"."update_time" IS '更新时间'; +COMMENT ON COLUMN "public"."product_attribute_event"."zbx_id" IS 'itemid'; +COMMENT ON COLUMN "public"."product_attribute_event"."value_type" IS '值类型'; +COMMENT ON COLUMN "public"."product_attribute_event"."template_id" IS '继承的属性ID'; +COMMENT ON COLUMN "public"."product_attribute_event"."event_level" IS '事件级别'; + +-- ---------------------------- +-- Records of product_attribute_event +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_event +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_event"; +CREATE TABLE "public"."product_event" ( + "event_rule_id" int8 NOT NULL, + "event_rule_name" varchar(255) COLLATE "pg_catalog"."default", + "event_level" varchar(1) COLLATE "pg_catalog"."default", + "exp_logic" varchar(10) COLLATE "pg_catalog"."default", + "create_time" timestamp(6), + "create_user" int8, + "update_time" timestamp(6), + "update_user" int8, + "event_notify" varchar(1) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."product_event"."event_rule_id" IS '告警规则ID'; +COMMENT ON COLUMN "public"."product_event"."event_rule_name" IS '告警规则名称'; +COMMENT ON COLUMN "public"."product_event"."event_level" IS '告警等级'; +COMMENT ON COLUMN "public"."product_event"."exp_logic" IS 'and 或者 or'; +COMMENT ON COLUMN "public"."product_event"."event_notify" IS '0 否 1 是'; + +-- ---------------------------- +-- Records of product_event +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_event_expression +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_event_expression"; +CREATE TABLE "public"."product_event_expression" ( + "event_exp_id" int8 NOT NULL, + "event_rule_id" int8, + "function" varchar(16) COLLATE "pg_catalog"."default", + "scope" varchar(10) COLLATE "pg_catalog"."default", + "condition" varchar(10) COLLATE "pg_catalog"."default", + "value" varchar(255) COLLATE "pg_catalog"."default", + "device_id" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "product_attr_key" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "unit" varchar(16) COLLATE "pg_catalog"."default", + "product_attr_id" int8, + "product_attr_type" varchar(4) COLLATE "pg_catalog"."default", + "period" varchar(8) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."product_event_expression"."event_exp_id" IS '告警函数ID'; +COMMENT ON COLUMN "public"."product_event_expression"."event_rule_id" IS '告警规则ID'; +COMMENT ON COLUMN "public"."product_event_expression"."device_id" IS '设备ID'; +COMMENT ON COLUMN "public"."product_event_expression"."product_attr_key" IS 'item key'; +COMMENT ON COLUMN "public"."product_event_expression"."product_attr_id" IS '属性ID'; +COMMENT ON COLUMN "public"."product_event_expression"."product_attr_type" IS '属性类型 属性 事件'; +COMMENT ON COLUMN "public"."product_event_expression"."period" IS '取值周期 时间 周期'; + +-- ---------------------------- +-- Records of product_event_expression +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_event_relation +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_event_relation"; +CREATE TABLE "public"."product_event_relation" ( + "id" int8 NOT NULL DEFAULT nextval('product_event_relation_id_seq'::regclass), + "event_rule_id" int8 NOT NULL, + "relation_id" varchar(64) COLLATE "pg_catalog"."default", + "zbx_id" int4, + "inherit" varchar(4) COLLATE "pg_catalog"."default" DEFAULT '0'::character varying, + "status" varchar(8) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."product_event_relation"."event_rule_id" IS '规则ID'; +COMMENT ON COLUMN "public"."product_event_relation"."relation_id" IS '关联产品或设备ID'; +COMMENT ON COLUMN "public"."product_event_relation"."zbx_id" IS 'trigger id'; +COMMENT ON COLUMN "public"."product_event_relation"."inherit" IS '是否来自产品'; +COMMENT ON COLUMN "public"."product_event_relation"."status" IS '状态'; +COMMENT ON COLUMN "public"."product_event_relation"."remark" IS '备注'; + +-- ---------------------------- +-- Records of product_event_relation +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_event_service +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_event_service"; +CREATE TABLE "public"."product_event_service" ( + "event_rule_id" int8, + "service_id" int8, + "device_id" varchar(64) COLLATE "pg_catalog"."default", + "execute_device_id" varchar(64) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."product_event_service"."event_rule_id" IS '告警规则ID'; +COMMENT ON COLUMN "public"."product_event_service"."service_id" IS '产品服务ID'; +COMMENT ON COLUMN "public"."product_event_service"."device_id" IS '关联产品或设备ID'; +COMMENT ON COLUMN "public"."product_event_service"."execute_device_id" IS '执行目标设备ID'; + +-- ---------------------------- +-- Records of product_event_service +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_event_tags +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_event_tags"; +CREATE TABLE "public"."product_event_tags" ( + "id" int4 NOT NULL DEFAULT nextval('product_event_tags_id_seq'::regclass), + "event_rule_id" int8 NOT NULL, + "tag_zbx_id" int4 NOT NULL +) +; +COMMENT ON COLUMN "public"."product_event_tags"."id" IS '自增ID'; +COMMENT ON COLUMN "public"."product_event_tags"."event_rule_id" IS '告警规则ID'; +COMMENT ON COLUMN "public"."product_event_tags"."tag_zbx_id" IS 'zabbix tag id'; + +-- ---------------------------- +-- Records of product_event_tags +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_group +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_group"; +CREATE TABLE "public"."product_group" ( + "product_group_id" int8 NOT NULL, + "pid" int8, + "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "remark" varchar(255) COLLATE "pg_catalog"."default", + "key" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "create_time" timestamp(6), + "create_user" int8, + "update_time" timestamp(6), + "update_user" int8 +) +; +COMMENT ON COLUMN "public"."product_group"."product_group_id" IS '产品分组ID'; +COMMENT ON COLUMN "public"."product_group"."pid" IS '父ID'; +COMMENT ON COLUMN "public"."product_group"."name" IS '分组名称'; +COMMENT ON COLUMN "public"."product_group"."remark" IS '备注'; +COMMENT ON COLUMN "public"."product_group"."key" IS '分组标识'; +COMMENT ON COLUMN "public"."product_group"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."product_group"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."product_group"."update_time" IS '更新时间'; +COMMENT ON COLUMN "public"."product_group"."update_user" IS '更新人'; + +-- ---------------------------- +-- Records of product_group +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_service +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_service"; +CREATE TABLE "public"."product_service" ( + "id" int8 NOT NULL DEFAULT nextval('service_id_seq'::regclass), + "name" varchar(64) COLLATE "pg_catalog"."default", + "mark" varchar(64) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "async" varchar(16) COLLATE "pg_catalog"."default" DEFAULT 1 +) +; +COMMENT ON COLUMN "public"."product_service"."name" IS '服务名称'; +COMMENT ON COLUMN "public"."product_service"."mark" IS '服务标识'; +COMMENT ON COLUMN "public"."product_service"."remark" IS '备注'; +COMMENT ON COLUMN "public"."product_service"."async" IS '执行方式 0-同步 1-异步'; + +-- ---------------------------- +-- Records of product_service +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_service_param +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_service_param"; +CREATE TABLE "public"."product_service_param" ( + "id" int8 NOT NULL DEFAULT nextval('service_param_id_seq'::regclass), + "service_id" int8, + "key" varchar(32) COLLATE "pg_catalog"."default", + "name" varchar(32) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."product_service_param"."service_id" IS '服务ID'; +COMMENT ON COLUMN "public"."product_service_param"."key" IS '参数标识'; +COMMENT ON COLUMN "public"."product_service_param"."name" IS '参数名称'; + +-- ---------------------------- +-- Records of product_service_param +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_service_relation +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_service_relation"; +CREATE TABLE "public"."product_service_relation" ( + "service_id" int8 NOT NULL, + "relation_id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, + "id" int8 NOT NULL DEFAULT nextval('product_service_relation_id_seq'::regclass), + "inherit" varchar(4) COLLATE "pg_catalog"."default" DEFAULT 0 +) +; +COMMENT ON COLUMN "public"."product_service_relation"."inherit" IS '是否继承'; + +-- ---------------------------- +-- Records of product_service_relation +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_status_function +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_status_function"; +CREATE TABLE "public"."product_status_function" ( + "rule_id" int8 NOT NULL, + "zbx_id" varchar(32) COLLATE "pg_catalog"."default", + "rule_function" varchar(10) COLLATE "pg_catalog"."default", + "rule_condition" varchar(255) COLLATE "pg_catalog"."default", + "rule_status" int2 DEFAULT 1, + "create_user" int8, + "update_user" int8, + "create_time" timestamp(6), + "update_time" timestamp(6), + "rule_function_recovery" varchar(10) COLLATE "pg_catalog"."default", + "rule_condition_recovery" varchar(255) COLLATE "pg_catalog"."default", + "attr_id" int8, + "attr_id_recovery" int8, + "unit" varchar(8) COLLATE "pg_catalog"."default", + "unit_recovery" varchar(8) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."product_status_function"."rule_id" IS '触发器ID,离线 上线'; +COMMENT ON COLUMN "public"."product_status_function"."zbx_id" IS 'zabbix trigger id'; +COMMENT ON COLUMN "public"."product_status_function"."rule_function" IS '''nodata'' or ''last'''; +COMMENT ON COLUMN "public"."product_status_function"."rule_condition" IS '''5m'' or ''4'''; +COMMENT ON COLUMN "public"."product_status_function"."rule_status" IS '0 or 1'; +COMMENT ON COLUMN "public"."product_status_function"."rule_function_recovery" IS '''nodata'' or ''last'''; +COMMENT ON COLUMN "public"."product_status_function"."rule_condition_recovery" IS '''5m'' or ''4'''; +COMMENT ON COLUMN "public"."product_status_function"."attr_id" IS 'trigger attrId'; +COMMENT ON COLUMN "public"."product_status_function"."attr_id_recovery" IS 'recovery attrId'; + +-- ---------------------------- +-- Records of product_status_function +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_status_function_relation +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_status_function_relation"; +CREATE TABLE "public"."product_status_function_relation" ( + "rule_id" int8 NOT NULL, + "relation_id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, + "id" int8 NOT NULL DEFAULT nextval('product_status_function_relation_id_seq'::regclass), + "inherit" varchar(4) COLLATE "pg_catalog"."default" DEFAULT 0 +) +; +COMMENT ON COLUMN "public"."product_status_function_relation"."inherit" IS '是否继承自产品 1是0否'; + +-- ---------------------------- +-- Records of product_status_function_relation +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_type +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_type"; +CREATE TABLE "public"."product_type" ( + "id" int4 NOT NULL DEFAULT nextval('product_type_product_type_id_seq'::regclass), + "pid" int4, + "name" varchar(32) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "pids" varchar(255) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."product_type"."name" IS '分类名称'; +COMMENT ON COLUMN "public"."product_type"."remark" IS '备注'; +COMMENT ON COLUMN "public"."product_type"."pids" IS '所有父ID'; + +-- ---------------------------- +-- Records of product_type +-- ---------------------------- +INSERT INTO "public"."product_type" VALUES (214, 0, '温控产品', NULL, '[0],'); + +-- ---------------------------- +-- Table structure for service_execute_record +-- ---------------------------- +DROP TABLE IF EXISTS "public"."service_execute_record"; +CREATE TABLE "public"."service_execute_record" ( + "id" int8 NOT NULL DEFAULT nextval('service_execute_record_id_seq'::regclass), + "create_time" timestamp(6), + "service_name" varchar(64) COLLATE "pg_catalog"."default", + "param" varchar(255) COLLATE "pg_catalog"."default", + "device_id" varchar(64) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."service_execute_record"."service_name" IS '服务名称'; +COMMENT ON COLUMN "public"."service_execute_record"."param" IS '执行参数'; +COMMENT ON COLUMN "public"."service_execute_record"."device_id" IS '设备ID'; + +-- ---------------------------- +-- Records of service_execute_record +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_config +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_config"; +CREATE TABLE "public"."sys_config" ( + "id" int8 NOT NULL, + "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "code" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "dict_flag" char(1) COLLATE "pg_catalog"."default" NOT NULL, + "dict_type_id" int8, + "value" varchar(255) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "create_user" int8, + "update_user" int8, + "create_time" timestamp(6), + "update_time" timestamp(6), + "status" varchar(8) COLLATE "pg_catalog"."default" DEFAULT 'ENABLE'::character varying +) +; +COMMENT ON COLUMN "public"."sys_config"."id" IS '主键ID'; +COMMENT ON COLUMN "public"."sys_config"."name" IS '名称'; +COMMENT ON COLUMN "public"."sys_config"."code" IS '属性编码标识'; +COMMENT ON COLUMN "public"."sys_config"."dict_flag" IS '是否是字典中的值'; +COMMENT ON COLUMN "public"."sys_config"."dict_type_id" IS '字典类型的编码'; +COMMENT ON COLUMN "public"."sys_config"."value" IS '属性值,如果是字典中的类型,则为dict的code'; +COMMENT ON COLUMN "public"."sys_config"."remark" IS '备注'; +COMMENT ON COLUMN "public"."sys_config"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."sys_config"."update_user" IS '更新人'; +COMMENT ON COLUMN "public"."sys_config"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."sys_config"."update_time" IS '修改时间'; +COMMENT ON COLUMN "public"."sys_config"."status" IS '是否可修改 ENABLE可以 DISABLE不可'; + +-- ---------------------------- +-- Records of sys_config +-- ---------------------------- +INSERT INTO "public"."sys_config" VALUES (1145915627211370496, '全局主机组Id', 'ZEUS_HOST_GROUP_ID', 'Y', NULL, '19', '全局主机和模板组ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468867767607298, '用户角色ID', 'ZEUS_ADMIN_ROLE_ID', 'N', NULL, '2', '用户角色ID', 1, 1, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370497, '离线回调ActionId', 'ZEUS_OFFLINE_ACTION_ID', 'Y', NULL, '20', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370503, '告警回调ActionId', 'ZEUS_ALARM_ACTION_ID', 'Y', NULL, '21', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370504, '动作回调ActionId', 'ZEUS_EXEC_ACTION_ID', 'Y', NULL, '22', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370505, '事件回调ActionId', 'ZEUS_EVENT_ACTION_ID', 'Y', NULL, '23', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370502, '获取token的header标识', 'ZEUS_TOKEN_HEADER_NAME', 'N', NULL, 'Authorization', '获取token的header标识', 1, 1, '2019-10-16 23:02:39', '2021-08-03 16:38:12.432', 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468689664876546, '管理系统名称', 'ZEUS_SYSTEM_NAME', 'N', NULL, 'ZEUS-IOT', '管理系统名称', 1, 1, '2019-06-25 18:39:15', '2021-08-09 17:17:30.189', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370501, '获取系统地密钥过期时间', 'ZEUS_JWT_SECRET_EXPIRE', 'N', NULL, '86400', '获取系统地密钥过期时间(单位:秒),默认1天', 1, 1, '2019-10-16 23:02:39', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1143469008025133058, 'OAuth2登录用户的账号标识', 'ZEUS_OAUTH2_PREFIX', 'N', NULL, 'oauth2', 'OAuth2登录用户的账号标识', 1, 1, '2019-06-25 18:40:31', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370499, '文件上传路径', 'ZEUS_FILE_UPLOAD_PATH', 'N', NULL, '/tmp', '文件上传默认目录', 1, 1, '2019-08-30 09:10:40', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1143324237579165697, '验证码开关', 'ZEUS_KAPTCHA_OPEN', 'Y', 1106120265689055233, 'DISABLE', '是否开启验证码', 1, 1, '2019-06-24 12:46:43', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370498, 'Zeus发布的编号', 'ZEUS_SYSTEM_RELEASE_VERSION', 'N', NULL, '10', '用于防止浏览器缓存相关的js和css', 1, 1, '2019-07-02 12:42:30', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468867767607297, '默认系统密码', 'ZEUS_DEFAULT_PASSWORD', 'N', NULL, '111111', '默认系统密码', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); + +-- ---------------------------- +-- Table structure for sys_dict +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_dict"; +CREATE TABLE "public"."sys_dict" ( + "dict_id" int8 NOT NULL, + "dict_type_id" int8 NOT NULL, + "code" varchar(50) COLLATE "pg_catalog"."default" NOT NULL, + "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "status" varchar(10) COLLATE "pg_catalog"."default" NOT NULL, + "sort" int4, + "remark" varchar(1000) COLLATE "pg_catalog"."default", + "create_time" timestamp(6), + "update_time" timestamp(6), + "create_user" int8, + "update_user" int8, + "groups" varchar(64) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."sys_dict"."dict_id" IS '字典id'; +COMMENT ON COLUMN "public"."sys_dict"."dict_type_id" IS '所属字典类型的id'; +COMMENT ON COLUMN "public"."sys_dict"."code" IS '字典编码'; +COMMENT ON COLUMN "public"."sys_dict"."name" IS '字典名称'; +COMMENT ON COLUMN "public"."sys_dict"."status" IS '状态(字典)'; +COMMENT ON COLUMN "public"."sys_dict"."sort" IS '排序'; +COMMENT ON COLUMN "public"."sys_dict"."remark" IS '字典的描述'; +COMMENT ON COLUMN "public"."sys_dict"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."sys_dict"."update_time" IS '更新时间'; +COMMENT ON COLUMN "public"."sys_dict"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."sys_dict"."update_user" IS '修改人'; +COMMENT ON COLUMN "public"."sys_dict"."groups" IS '分组'; +COMMENT ON TABLE "public"."sys_dict" IS '基础字典'; + +-- ---------------------------- +-- Records of sys_dict +-- ---------------------------- +INSERT INTO "public"."sys_dict" VALUES (1106120532442595330, 1106120208097067009, 'M', '男', 'ENABLE', NULL, '', '2019-03-14 17:11:00', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1106120574163337218, 1106120208097067009, 'F', '女', 'ENABLE', NULL, '', '2019-03-14 17:11:10', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1106120645697191938, 1106120265689055233, 'ENABLE', '启用', 'ENABLE', NULL, '', '2019-03-14 17:11:27', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1106120699468169217, 1106120265689055233, 'DISABLE', '禁用', 'ENABLE', NULL, '', '2019-03-14 17:11:40', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1106120784318939137, 1106120322450571266, 'ENABLE', '启用', 'ENABLE', NULL, '', '2019-03-14 17:12:00', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1106120825993543682, 1106120322450571266, 'FREEZE', '冻结', 'ENABLE', 1, '', '2019-03-14 17:12:10', '2019-03-16 10:56:36', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1106120875872206849, 1106120322450571266, 'DELETED', '已删除', 'ENABLE', -1221, '', '2019-03-14 17:12:22', '2019-03-16 10:56:53', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1106120935070613505, 1106120388036902914, 'Y', '删除', 'ENABLE', 23333, '', '2019-03-14 17:12:36', '2019-03-16 10:58:53', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1106120968910258177, 1106120388036902914, 'N', '未删除', 'ENABLE', 1212211221, '', '2019-03-14 17:12:44', '2019-03-16 10:59:03', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1149218674746355713, 1149217131989069826, 'BASE_SYSTEM', '基础功能', 'ENABLE', 1, '系统管理平台', '2019-07-11 15:27:38', '2020-01-01 17:14:45', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533174626959361, 1160532704105742337, '00101', '办公审批', 'ENABLE', 10, '', '2019-08-11 20:47:25', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533264645111810, 1160532704105742337, '00102', '行政审批', 'ENABLE', 20, '', '2019-08-11 20:47:47', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533377727741954, 1160532775455047681, 'KEY_LEAVE', '请假流程标识', 'ENABLE', 10, '', '2019-08-11 20:48:14', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533455343337474, 1160532775455047681, 'KEY_FINANCE', '财务流程标识', 'ENABLE', 20, '', '2019-08-11 20:48:32', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533574843252737, 1160532886713155585, '00401', '事假', 'ENABLE', 10, '', '2019-08-11 20:49:01', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533625615302658, 1160532886713155585, '00402', '婚假', 'ENABLE', 20, '', '2019-08-11 20:49:13', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533707215486977, 1160532886713155585, '00403', '产假', 'ENABLE', 30, '', '2019-08-11 20:49:32', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533765403066370, 1160532886713155585, '00404', '病假', 'ENABLE', 40, '', '2019-08-11 20:49:46', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533863834992641, 1160532886713155585, '00405', '公假', 'ENABLE', 50, '', '2019-08-11 20:50:09', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533945309347841, 1160532886713155585, '00406', '年假', 'ENABLE', 60, '', '2019-08-11 20:50:29', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160534007389241346, 1160532886713155585, '00407', '其他', 'ENABLE', 70, '', '2019-08-11 20:50:44', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1212300736972668929, 1149217131989069826, 'ENT_FUNC', '企业功能', 'ENABLE', 20, '企业功能', '2020-01-01 17:13:14', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423166477712343040, 1423160140530053120, 'DICTTYPE', '字典类型', 'ENABLE', 1, '测试', '2021-08-05 14:18:24.098', '2021-08-05 14:18:24.098', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423234510216499200, 1423160140530053120, 'DICTTYPE4', '字典类型4', 'ENABLE', 1, '测试', '2021-08-05 18:48:44.31', '2021-08-05 18:48:44.31', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423234906741895168, 1423160140530053120, 'DICTTYPE5', '字典类型5', 'ENABLE', 1, '测试', '2021-08-05 18:50:18.848', '2021-08-05 18:50:18.848', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423235174556626944, 1423160140530053120, 'DICTTYPE6', '字典类型6', 'ENABLE', 1, '测试', '2021-08-05 18:51:22.701', '2021-08-05 18:51:22.701', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423464964597334017, 1160532886713155586, '1', '直连设备', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423464964597334018, 1160532886713155586, '2', '网关子设备', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423464964597334019, 1160532886713155586, '3', '网关设备', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199424, 1423840415470653440, '凤飞飞', '凤飞飞', 'ENABLE', NULL, '凤飞飞', '2021-08-07 14:44:21.192', '2021-08-07 14:44:21.192', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199425, 1160532886713155587, 'wechat', '企业微信', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199426, 1160532886713155587, 'dingtalk', '钉钉', 'ENABLE', 2, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199427, 1160532886713155587, 'feishu', '飞书', 'ENABLE', 3, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199430, 1160532886713155588, '18', '根据单个属性预处理', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199428, 1160532886713155588, '2', '主动上报', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199435, 1160532886713155589, '%', '百分比', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199436, 1160532886713155589, 'count', '次', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199437, 1160532886713155589, 'r/min', '转每分钟', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199431, 1160532886713155590, '3', '整数', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199432, 1160532886713155590, '0', '小数', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199433, 1160532886713155590, '1', '字符', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199434, 1160532886713155590, '4', '文本', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199438, 1160532886713155589, 'nm', '纳米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199439, 1160532886713155589, 'μm', '微米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199440, 1160532886713155589, 'mm', '毫米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199441, 1160532886713155589, 'cm', '厘米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199442, 1160532886713155589, 'm', '米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199443, 1160532886713155589, 'km', '千米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199444, 1160532886713155589, 'mm²', '平方毫米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199445, 1160532886713155589, 'cm²', '平方厘米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199446, 1160532886713155589, 'm²', '平方米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199447, 1160532886713155589, 'km²', '平方千米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199448, 1160532886713155589, 'hm²', '公顷', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199449, 1160532886713155589, 'd', '天', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199450, 1160532886713155589, 'h', '小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199451, 1160532886713155589, 'min', '分钟', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199452, 1160532886713155589, 's', '秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199453, 1160532886713155589, 'ms', '毫秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199454, 1160532886713155589, 'μs', '微秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199455, 1160532886713155589, 'ns', '纳秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199456, 1160532886713155589, 'mm³', '立方毫米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '体积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199457, 1160532886713155589, 'cm³', '立方厘米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '体积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199458, 1160532886713155589, 'm³', '立方米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '体积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199459, 1160532886713155589, 'km³', '立方千米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '体积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199460, 1160532886713155589, 'm³/s', '立方米每秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199461, 1160532886713155589, 'km³/s', '立方千米每秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199462, 1160532886713155589, 'cm³/s', '立方厘米每秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199463, 1160532886713155589, 'l/s', '升每秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199464, 1160532886713155589, 'm³/h', '立方米每小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199465, 1160532886713155589, 'km³/h', '立方千米每小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199466, 1160532886713155589, 'cm³/h', '立方厘米每小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199467, 1160532886713155589, 'l/h', '升每小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199468, 1160532886713155589, 'mL', '毫升', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '容积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199469, 1160532886713155589, 'L', '升', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '容积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199470, 1160532886713155589, 'mg', '毫克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199471, 1160532886713155589, 'g', '克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1437341935102316544, 1437341934464782336, 'SSGrdr26', '三石TestKKRl7u', 'DISABLE', 99, NULL, '2021-09-13 17:06:36.507', '2021-09-13 17:06:36.641', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1428599180229115912, 1428599180229115904, '1', '是', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1428599180229115911, 1428599180229115904, '0', '', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199478, 1160532886713155589, 'K', '开尔文', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199479, 1160532886713155589, '℃', '摄氏度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199506, 1160532886713155591, '25', 'Replace', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199507, 1160532886713155591, '4', 'Trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199508, 1160532886713155591, '2', 'Right trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199509, 1160532886713155591, '3', 'Left trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199510, 1160532886713155591, '11', 'XML XPath', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '结构化数据'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199511, 1160532886713155591, '12', 'JSONPath', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '结构化数据'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199480, 1160532886713155589, '℉', '华氏度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199481, 1160532886713155589, 'J', '焦耳', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199514, 1160532886713155591, '1', '自定义倍数', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '自定义计算'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199482, 1160532886713155589, 'cal', '卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199483, 1160532886713155589, 'W', '瓦特', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '功率单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199517, 1160532886713155591, '7', '八进制转十进制', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '数制转换'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199518, 1160532886713155591, '8', '十六进制转十进制', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '数制转换'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199519, 1160532886713155591, '21', 'JavaScript', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '自定义脚本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199504, 1160532886713155589, 'kW·h', '千瓦·时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199484, 1160532886713155589, 'kW', '千瓦特', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '功率单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199485, 1160532886713155589, 'rad', '弧度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199486, 1160532886713155589, '°', '度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199487, 1160532886713155589, '′', '[角]分', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199488, 1160532886713155589, '″', '[角]秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199489, 1160532886713155589, 'Hz', '赫兹', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '频率单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199490, 1160532886713155589, 'MHz', '兆赫兹', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '频率单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199491, 1160532886713155589, 'GHz', 'G赫兹', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '频率单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199492, 1160532886713155589, 'm/s', '米每秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '速度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199493, 1160532886713155589, 'km/h', '千米每小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '速度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199494, 1160532886713155589, 'kn', '节', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '速度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199495, 1160532886713155589, 'V', '伏特', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199496, 1160532886713155589, 'kV', '千伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199497, 1160532886713155589, 'mV', '毫伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199498, 1160532886713155589, 'μV', '微伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199499, 1160532886713155589, 'A', '安培', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199505, 1160532886713155589, 'kgce', 'Kg标准煤', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能源单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199500, 1160532886713155589, 'Ω', '欧姆', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199501, 1160532886713155589, 'KΩ', '千欧', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199502, 1160532886713155589, 'MΩ', '兆欧', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199503, 1160532886713155589, 'eV', '电子伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199512, 1160532886713155591, '13', 'In range', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '验证'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199579, 1428599180229115905, '1', '信息', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199574, 1428599180229115905, '2', '低级', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199577, 1428599180229115905, '3', '中级', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199576, 1428599180229115905, '4', '高级', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199575, 1428599180229115905, '5', '紧急', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199578, 1428599180229115905, '0', '未定义', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1429987619034984449, 1142859918022911591, '1', '异步', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1429987619034984450, 1142859918022911591, '0', '同步', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199472, 1160532886713155589, 'kg', '千克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199473, 1160532886713155589, 't', '吨', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199474, 1160532886713155589, 'Pa', '帕斯卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '压力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199475, 1160532886713155589, 'kPa', '千帕斯卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '压力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199476, 1160532886713155589, 'N', '牛顿', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199477, 1160532886713155589, 'N.m', '牛·米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '力单位'); + +-- ---------------------------- +-- Table structure for sys_dict_type +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_dict_type"; +CREATE TABLE "public"."sys_dict_type" ( + "dict_type_id" int8 NOT NULL, + "code" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "remark" varchar(1000) COLLATE "pg_catalog"."default", + "system_flag" char(1) COLLATE "pg_catalog"."default" NOT NULL, + "status" varchar(10) COLLATE "pg_catalog"."default" NOT NULL, + "sort" int4, + "create_time" timestamp(6), + "create_user" int8, + "update_time" timestamp(6), + "update_user" int8 +) +; +COMMENT ON COLUMN "public"."sys_dict_type"."dict_type_id" IS '字典类型id'; +COMMENT ON COLUMN "public"."sys_dict_type"."code" IS '字典类型编码'; +COMMENT ON COLUMN "public"."sys_dict_type"."name" IS '字典类型名称'; +COMMENT ON COLUMN "public"."sys_dict_type"."remark" IS '字典描述'; +COMMENT ON COLUMN "public"."sys_dict_type"."system_flag" IS '是否是系统字典,Y-是,N-否'; +COMMENT ON COLUMN "public"."sys_dict_type"."status" IS '状态(字典)'; +COMMENT ON COLUMN "public"."sys_dict_type"."sort" IS '排序'; +COMMENT ON COLUMN "public"."sys_dict_type"."create_time" IS '添加时间'; +COMMENT ON COLUMN "public"."sys_dict_type"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."sys_dict_type"."update_time" IS '修改时间'; +COMMENT ON COLUMN "public"."sys_dict_type"."update_user" IS '修改人'; +COMMENT ON TABLE "public"."sys_dict_type" IS '字典类型表'; + +-- ---------------------------- +-- Records of sys_dict_type +-- ---------------------------- +INSERT INTO "public"."sys_dict_type" VALUES (1106120265689055233, 'STATUS', '状态', '', 'Y', 'ENABLE', 3, '2019-03-14 17:09:57', 1, NULL, NULL); +INSERT INTO "public"."sys_dict_type" VALUES (1106120322450571266, 'ACCOUNT_STATUS', '账号状态', '', 'Y', 'ENABLE', 40, '2019-03-14 17:10:10', 1, '2019-08-11 20:46:38', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1106120388036902914, 'DEL_FLAG', '是否删除', '', 'Y', 'ENABLE', 2, '2019-03-14 17:10:26', 1, '2019-03-27 16:26:31', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1149217131989069826, 'SYSTEM_TYPE', '系统分类', '系统所有分类的维护', 'Y', 'ENABLE', 50, '2019-07-11 15:21:30', 1, '2019-08-11 20:46:47', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1160532704105742337, 'FLOW_CATEGARY', '工作流分类', '工作流分类', 'Y', 'ENABLE', 60, '2019-08-11 20:45:33', 1, NULL, NULL); +INSERT INTO "public"."sys_dict_type" VALUES (1160532775455047681, 'FLOW_KEY', '工作流标识', '工作流标识', 'Y', 'ENABLE', 70, '2019-08-11 20:45:50', 1, NULL, NULL); +INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155585, 'LEAVE_TYPE', '请假类型', '请假类型', 'Y', 'ENABLE', 80, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1106120208097067009, 'SEX', '性别', '', 'Y', 'ENABLE', 4, '2019-03-14 17:09:43', 1, NULL, NULL); +INSERT INTO "public"."sys_dict_type" VALUES (1423160140530053120, 'DICTTYPE', '字典类型', '测试', 'N', 'ENABLE', NULL, '2021-08-05 13:53:13.196', 1, '2021-08-05 13:53:13.196', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155587, 'MEDIA_TYPE', '通知类型', '通知类型', 'N', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155586, 'DEVICE_TYPE', '设备类型', '设备类型', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155588, 'ATTR_TYPE', '产品属性类型', '产品属性类型', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155589, 'UNITS', '产品属性单位', '产品属性单位', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155590, 'DATA_TYPE', '产品属性值类型', '产品属性值类型', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155591, 'DATA_PRE_TYPE', '数据预处理方法名称', '数据预处理方法名称', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1142859918022911591, 'EXECUTE_TYPE', '服务执行方式', '服务执行方式', 'N', 'ENABLE', 1, NULL, NULL, '2021-09-10 15:56:14.127', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1437348629152780288, 'SShe06pqU', '三石TestcKA3qIU', '描述Test@123', 'N', 'ENABLE', NULL, '2021-09-13 17:33:12.493', 1, '2021-09-13 17:33:12.554', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1428599180229115904, 'WHETHER', '是否', '是否', 'N', 'ENABLE', NULL, '2021-08-20 14:06:01.311', 1, '2021-08-20 14:06:01.311', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1428599180229115905, 'EVENT_LEVEL', '告警级别', '告警级别', 'N', 'ENABLE', NULL, NULL, NULL, NULL, NULL); + +-- ---------------------------- +-- Table structure for sys_login_log +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_login_log"; +CREATE TABLE "public"."sys_login_log" ( + "log_name" varchar(255) COLLATE "pg_catalog"."default", + "user_id" int8, + "succeed" varchar(255) COLLATE "pg_catalog"."default", + "message" text COLLATE "pg_catalog"."default", + "ip_address" varchar(255) COLLATE "pg_catalog"."default", + "create_time" timestamp(6), + "login_log_id" int8 NOT NULL +) +; + +-- ---------------------------- +-- Records of sys_login_log +-- ---------------------------- +INSERT INTO "public"."sys_login_log" VALUES ('登录日志', 1, '成功', NULL, '172.16.3.33', '2021-09-23 11:35:36.879', 1440882516655042560); +INSERT INTO "public"."sys_login_log" VALUES ('登录日志', 1, '成功', NULL, '172.16.3.25', '2021-09-23 11:36:56.394', 1440882849955409920); +INSERT INTO "public"."sys_login_log" VALUES ('退出日志', 1, '成功', NULL, '172.16.3.25', '2021-09-23 11:42:26.181', 1440884233178148864); +INSERT INTO "public"."sys_login_log" VALUES ('登录日志', 117, '成功', NULL, '172.16.3.25', '2021-09-23 11:42:32.517', 1440884259753259008); + +-- ---------------------------- +-- Table structure for sys_menu +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_menu"; +CREATE TABLE "public"."sys_menu" ( + "menu_id" int8 NOT NULL, + "code" varchar(255) COLLATE "pg_catalog"."default", + "pcode" varchar(255) COLLATE "pg_catalog"."default", + "pcodes" varchar(255) COLLATE "pg_catalog"."default", + "name" varchar(255) COLLATE "pg_catalog"."default", + "icon" varchar(255) COLLATE "pg_catalog"."default", + "url" varchar(255) COLLATE "pg_catalog"."default", + "sort" int2, + "levels" int2, + "menu_flag" varchar(32) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "status" varchar(255) COLLATE "pg_catalog"."default", + "create_time" timestamp(6), + "update_time" timestamp(6), + "create_user" int8, + "update_user" int8 +) +; +COMMENT ON COLUMN "public"."sys_menu"."menu_id" IS '菜单ID'; +COMMENT ON COLUMN "public"."sys_menu"."code" IS '菜单编号'; +COMMENT ON COLUMN "public"."sys_menu"."pcode" IS '菜单父编号'; +COMMENT ON COLUMN "public"."sys_menu"."pcodes" IS '当前菜单的所有父菜单编号'; +COMMENT ON COLUMN "public"."sys_menu"."name" IS '菜单名称'; +COMMENT ON COLUMN "public"."sys_menu"."icon" IS '菜单图标'; +COMMENT ON COLUMN "public"."sys_menu"."url" IS 'URL地址'; +COMMENT ON COLUMN "public"."sys_menu"."sort" IS '菜单排序号'; +COMMENT ON COLUMN "public"."sys_menu"."levels" IS '菜单层级'; +COMMENT ON COLUMN "public"."sys_menu"."menu_flag" IS '是否是菜单(字典)'; +COMMENT ON COLUMN "public"."sys_menu"."remark" IS '备注'; +COMMENT ON COLUMN "public"."sys_menu"."status" IS '菜单状态(字典)'; +COMMENT ON COLUMN "public"."sys_menu"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."sys_menu"."update_time" IS '修改时间'; +COMMENT ON COLUMN "public"."sys_menu"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."sys_menu"."update_user" IS '修改人'; + +-- ---------------------------- +-- Records of sys_menu +-- ---------------------------- +INSERT INTO "public"."sys_menu" VALUES (107, 'mgr_add', 'mgr', '[0],[system],[mgr],', '添加用户', NULL, '/mgr/add', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (108, 'mgr_edit', 'mgr', '[0],[system],[mgr],', '修改用户', NULL, '/mgr/edit', 2, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (109, 'mgr_delete', 'mgr', '[0],[system],[mgr],', '删除用户', NULL, '/mgr/delete', 3, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (110, 'mgr_reset', 'mgr', '[0],[system],[mgr],', '重置密码', NULL, '/mgr/reset', 4, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (113, 'mgr_setRole', 'mgr', '[0],[system],[mgr],', '分配角色', NULL, '/mgr/setRole', 7, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (115, 'role_add', 'role', '[0],[system],[role],', '添加角色', NULL, '/role/add', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (116, 'role_edit', 'role', '[0],[system],[role],', '修改角色', NULL, '/role/edit', 2, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (117, 'role_remove', 'role', '[0],[system],[role],', '删除角色', NULL, '/role/remove', 3, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (130, 'druid', 'system', '[0],[system],', '监控管理', '', '/druid', 80, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:50:06', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (134, 'log_clean', 'log', '[0],[system],[log],', '清空日志', NULL, '/log/delLog', 3, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:39', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (138, 'dict_add', 'dict', '[0],[system],[dict],', '添加字典', NULL, '/dictType/addItem', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (139, 'dict_update', 'dict', '[0],[system],[dict],', '修改字典', NULL, '/dictType/editItem', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (140, 'dict_delete', 'dict', '[0],[system],[dict],', '删除字典', NULL, '/dictType/delete', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (128, 'businessLog', 'log', '[0],[log],', '业务日志', '', '/log/businessLog', 70, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:39', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (181, 'product_type', 'product_mgr', '[0],[product_mgr],', '产品分类', NULL, '/productMgr/productType', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (151, 'menu_list', 'menu', '[0],[system],[menu],', '菜单列表', '', '/menu/list', 5, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:25', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (156, 'dict_list', 'dict', '[0],[system],[dict],', '字典列表', '', '/dict/list', 5, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (157, 'dict_detail', 'dict', '[0],[system],[dict],', '字典详情', '', '/dict/detail', 6, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (158, 'log_list', 'log', '[0],[system],[log],', '日志列表', '', '/log/list', 2, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:39', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (159, 'log_detail', 'log', '[0],[system],[log],', '日志详情', '', '/log/detail', 3, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:39', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (160, 'del_login_log', 'loginLog', '[0],[system],[loginLog],', '清空登录日志', '', '/loginLog/delLoginLog', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:29', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (161, 'login_log_list', 'loginLog', '[0],[system],[loginLog],', '登录日志列表', '', '/loginLog/list', 2, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:29', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (133, 'loginLog', 'log', '[0],[log],', '登录日志', '', '/log/loginLog', 60, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:49:29', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (164, 'role_list', 'role', '[0],[system],[role],', '角色列表', '', '/role/list', 7, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (165, 'to_assign_role', 'mgr', '[0],[system],[mgr],', '分配角色跳转', '', '/mgr/role_assign', 8, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (166, 'to_user_edit', 'mgr', '[0],[system],[mgr],', '编辑用户跳转', '', '/mgr/user_edit', 9, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (167, 'mgr_list', 'mgr', '[0],[system],[mgr],', '用户列表', '', '/mgr/list', 10, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (114, 'role', 'system', '[0],[system],', '角色管理', '', '/system/role', 20, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (106, 'mgr', 'system', '[0],[system],', '用户管理', '', '/system/user', 10, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (111, 'mgr_freeze', 'mgr', '[0],[system],[mgr],', '冻结用户', NULL, '/mgr/freeze', 5, 3, 'N', NULL, 'DISABLE', NULL, '2019-06-30 13:48:07', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (112, 'mgr_unfreeze', 'mgr', '[0],[system],[mgr],', '解除冻结用户', NULL, '/mgr/unfreeze', 6, 3, 'N', NULL, 'DISABLE', NULL, '2019-06-30 13:48:07', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (118, 'role_setAuthority', 'role', '[0],[system],[role],', '配置菜单', NULL, '/role/setAuthority', 4, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (119, 'menu', 'system', '[0],[system],', '菜单管理', '', '/menu', 50, 2, 'Y', NULL, 'DISABLE', NULL, '2019-06-30 13:48:25', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (120, 'menu_add', 'menu', '[0],[system],[menu],', '添加菜单', NULL, '/menu/add', 1, 3, 'N', NULL, 'DISABLE', NULL, '2019-06-30 13:48:25', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (121, 'menu_edit', 'menu', '[0],[system],[menu],', '修改菜单', NULL, '/menu/edit', 2, 3, 'N', NULL, 'DISABLE', NULL, '2019-06-30 13:48:25', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (122, 'menu_remove', 'menu', '[0],[system],[menu],', '删除菜单', NULL, '/menu/remove', 3, 3, 'N', NULL, 'DISABLE', NULL, '2019-06-30 13:48:25', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (177, 'dev', 'dev_mgr', '[0],[dev_mgr],', '设备', NULL, '/deviceMgr/device', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (178, 'dev_group', 'dev_mgr', '[0],[dev_mgr],', '设备组', NULL, '/deviceMgr/deviceGroup', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (171, 'product_mgr', '0', '[0],', '产品管理', NULL, '/productMgr', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (132, 'dict', 'system', '[0],[system],', '字典管理', '', '/system/dictType', 40, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (186, 'sysParam', 'system', '[0],[system],', '系统参数', '', '/system/sysParam', 10, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (180, 'product', 'product_mgr', '[0],[product_mgr],', '产品', NULL, '/productMgr/product', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (168, 'usrGrp', 'system', '[0],[system],', '用户组管理', NULL, '/system/userGroup', 9, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (184, 'log', '0', '[0]', '日志管理', NULL, '/log', 4, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (105, 'system', '0', '[0],', '系统管理', 'layui-icon layui-icon-set', '/system', 20, 1, 'Y', NULL, 'ENABLE', NULL, '2019-03-29 16:32:27', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (170, 'dev_mgr', '0', '[0],', '设备管理', NULL, '/deviceMgr', 2, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (185, 'product_detail', 'product', '[0],[product_mgr],[product],', '产品详情', NULL, '/productMgr/product/detail', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (187, 'media', 'system', '[0],[system],', '通知配置', '', '/system/media', 80, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:50:06', NULL, 1); +INSERT INTO "public"."sys_menu" VALUES (189, 'home', 'analyse', '[0],[analyse],', '全局概览', NULL, '/analyse/home', 1, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (188, 'detail', 'dev', '[0],[dev_mgr],[dev],', '设备详情', '', '/deviceMgr/device/detail', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (179, 'alarmList', 'alarm', '[0],[alarm],', '告警记录', NULL, '/alarm/alarmList', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (190, 'latest', 'analyse', '[0],[analyse],', '最新数据', NULL, '/analyse/latest', 2, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (169, 'analyse', '0', '[0],', '统计分析', NULL, '/analyse', 1, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (191, 'alarmAnalyse', 'alarm', '[0],[alarm],', '告警分析', NULL, '/alarm/analyse', 3, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (174, 'auth', '0', '[0],', '平台授权', NULL, '/auth', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (173, 'view', '0', '[0],', '可视化', NULL, '/view', 3, 1, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (176, 'dev_log', 'analyse', '[0],[analyse],', '设备日志', NULL, '/analyse/devLog', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (183, 'grafana', 'view', '[0],[view],', 'Grafana配置', NULL, '/view/grafana', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (192, 'alarm', '0', '[0],', '告警管理', NULL, '/alarm', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (194, 'rule', '0', '[0],', '规则引擎', NULL, '/rule', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (196, 'api', 'dev_mgr', '[0],[dev_mgr],', '设备调试', NULL, '/deviceMgr/api', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (197, 'about', '0', '[0],', '关于我们', NULL, '/about', 2, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (195, 'nodeRed', 'rule', '[0],[rule],', 'Node-Red', NULL, '/rule/nodeRed', 3, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (193, 'scene ', 'rule', '[0],[rule],', '场景联动', NULL, '/rule/scene ', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (198, 'monitor', 'analyse', '[0],[analyse],', '平台监控', NULL, '/analyse/monitor', 4, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (199, 'weakMonitor', 'analyse', '[0],[analyse],', '弱电间监控', NULL, '/analyse/weakMonitor', 5, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); + +-- ---------------------------- +-- Table structure for sys_operation_log +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_operation_log"; +CREATE TABLE "public"."sys_operation_log" ( + "operation_log_id" int8 NOT NULL, + "log_type" varchar(32) COLLATE "pg_catalog"."default", + "log_name" varchar(255) COLLATE "pg_catalog"."default", + "user_id" int8, + "class_name" varchar(255) COLLATE "pg_catalog"."default", + "method" varchar(255) COLLATE "pg_catalog"."default", + "create_time" timestamp(6), + "succeed" varchar(32) COLLATE "pg_catalog"."default", + "message" text COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."sys_operation_log"."operation_log_id" IS '操作日志ID'; +COMMENT ON COLUMN "public"."sys_operation_log"."log_type" IS '日志类型【字典】'; +COMMENT ON COLUMN "public"."sys_operation_log"."log_name" IS '日志名称'; +COMMENT ON COLUMN "public"."sys_operation_log"."user_id" IS '用户ID'; +COMMENT ON COLUMN "public"."sys_operation_log"."class_name" IS '类名称'; +COMMENT ON COLUMN "public"."sys_operation_log"."method" IS '方法名称'; +COMMENT ON COLUMN "public"."sys_operation_log"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."sys_operation_log"."succeed" IS '是否成功【字典】'; +COMMENT ON COLUMN "public"."sys_operation_log"."message" IS '备注'; + +-- ---------------------------- +-- Records of sys_operation_log +-- ---------------------------- +INSERT INTO "public"."sys_operation_log" VALUES (1440880052786688000, '业务日志', '新增产品分类', 1, 'com.zmops.iot.web.product.controller.ProductTypeController', 'create', '2021-09-23 11:25:49.498', '成功', ''); +INSERT INTO "public"."sys_operation_log" VALUES (1440880404000927744, '业务日志', '创建设备组', 1, 'com.zmops.iot.web.device.controller.DeviceGroupController', 'createDeviceGroup', '2021-09-23 11:27:13.234', '成功', ''); +INSERT INTO "public"."sys_operation_log" VALUES (1440883048178216960, '异常日志', '', 1, NULL, NULL, '2021-09-23 11:37:43.655', '失败', 'com.zmops.iot.model.exception.ZbxApiException: User with username "Admin" already exists. + at com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor.onSuccess(JsonBodyBuildInterceptor.java:78) + at com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor.onSuccess(JsonBodyBuildInterceptor.java:28) + at com.dtflys.forest.interceptor.InterceptorChain.onSuccess(InterceptorChain.java:64) + at com.dtflys.forest.reflection.MethodLifeCycleHandler.handleSuccess(MethodLifeCycleHandler.java:111) + at com.dtflys.forest.reflection.MethodLifeCycleHandler.handleSyncWithException(MethodLifeCycleHandler.java:55) + at com.dtflys.forest.reflection.MethodLifeCycleHandler.handleSync(MethodLifeCycleHandler.java:46) + at com.dtflys.forest.backend.AbstractBackendResponseHandler.handleSync(AbstractBackendResponseHandler.java:36) + at com.dtflys.forest.backend.okhttp3.response.OkHttp3ResponseHandler.handleSync(OkHttp3ResponseHandler.java:29) + at com.dtflys.forest.backend.okhttp3.executor.AbstractOkHttp3Executor.execute(AbstractOkHttp3Executor.java:260) + at com.dtflys.forest.backend.okhttp3.executor.AbstractOkHttp3Executor.execute(AbstractOkHttp3Executor.java:288) + at com.dtflys.forest.http.ForestRequest.execute(ForestRequest.java:1731) + at com.dtflys.forest.http.ForestRequest.execute(ForestRequest.java:1748) + at com.dtflys.forest.reflection.ForestMethod.invoke(ForestMethod.java:1230) + at com.dtflys.forest.proxy.InterfaceProxyHandler.invoke(InterfaceProxyHandler.java:150) + at com.sun.proxy.TProxy127.userAdd(Unknown Source) + at com.zmops.iot.web.sys.service.SysUserService.createUser(SysUserService.java:132) + at com.zmops.iot.web.sys.service.SysUserServiceTTFastClassBySpringCGLIBTT5b7cfc4d.invoke() + at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) + at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367) + at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) + at org.springframework.aop.framework.CglibAopProxyTDynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) + at com.zmops.iot.web.sys.service.SysUserServiceTTEnhancerBySpringCGLIBTT9bb24deb.createUser() + at com.zmops.iot.web.sys.controller.SysUserController.createUser(SysUserController.java:51) + at com.zmops.iot.web.sys.controller.SysUserControllerTTFastClassBySpringCGLIBTT2e326b39.invoke() + at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) + at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88) + at com.zmops.iot.web.log.aop.LogAop.recordSysLog(LogAop.java:54) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644) + at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633) + at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70) + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) + at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95) + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) + at org.springframework.aop.framework.CglibAopProxyTDynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) + at com.zmops.iot.web.sys.controller.SysUserControllerTTEnhancerBySpringCGLIBTT2cad82eb.createUser() + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) + at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) + at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) + at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878) + at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792) + at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) + at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) + at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) + at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) + at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) + at javax.servlet.http.HttpServlet.service(HttpServlet.java:517) + at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) + at javax.servlet.http.HttpServlet.service(HttpServlet.java:584) + at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:129) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113) + at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:320) + at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126) + at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at com.zmops.iot.core.auth.filter.JwtAuthorizationTokenFilter.doFilterInternal(JwtAuthorizationTokenFilter.java:77) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92) + at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) + at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) + at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) + at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) + at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) + at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) + at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) + at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:97) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) + at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) + at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) + at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) + at io.undertow.servlet.handlers.ServletChainT1.handleRequest(ServletChain.java:68) + at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) + at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68) + at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:111) + at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) + at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) + at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) + at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) + at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) + at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) + at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) + at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) + at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) + at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269) + at io.undertow.servlet.handlers.ServletInitialHandler.accessT100(ServletInitialHandler.java:78) + at io.undertow.servlet.handlers.ServletInitialHandlerT2.call(ServletInitialHandler.java:133) + at io.undertow.servlet.handlers.ServletInitialHandlerT2.call(ServletInitialHandler.java:130) + at io.undertow.servlet.core.ServletRequestContextThreadSetupActionT1.call(ServletRequestContextThreadSetupAction.java:48) + at io.undertow.servlet.core.ContextClassLoaderSetupActionT1.call(ContextClassLoaderSetupAction.java:43) + at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249) + at io.undertow.servlet.handlers.ServletInitialHandler.accessT000(ServletInitialHandler.java:78) + at io.undertow.servlet.handlers.ServletInitialHandlerT1.handleRequest(ServletInitialHandler.java:99) + at io.undertow.server.Connectors.executeRootHandler(Connectors.java:390) + at io.undertow.server.HttpServerExchangeT1.run(HttpServerExchange.java:836) + at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) + at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019) + at org.jboss.threads.EnhancedQueueExecutorTThreadBody.doRunTask(EnhancedQueueExecutor.java:1558) + at org.jboss.threads.EnhancedQueueExecutorTThreadBody.run(EnhancedQueueExecutor.java:1449) + at java.lang.Thread.run(Thread.java:748) +'); +INSERT INTO "public"."sys_operation_log" VALUES (1440883284019736576, '异常日志', '', 1, NULL, NULL, '2021-09-23 11:38:39.884', '失败', 'com.zmops.iot.model.exception.ZbxApiException: User group with ID "107" is not available. + at com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor.onSuccess(JsonBodyBuildInterceptor.java:78) + at com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor.onSuccess(JsonBodyBuildInterceptor.java:28) + at com.dtflys.forest.interceptor.InterceptorChain.onSuccess(InterceptorChain.java:64) + at com.dtflys.forest.reflection.MethodLifeCycleHandler.handleSuccess(MethodLifeCycleHandler.java:111) + at com.dtflys.forest.reflection.MethodLifeCycleHandler.handleSyncWithException(MethodLifeCycleHandler.java:55) + at com.dtflys.forest.reflection.MethodLifeCycleHandler.handleSync(MethodLifeCycleHandler.java:46) + at com.dtflys.forest.backend.AbstractBackendResponseHandler.handleSync(AbstractBackendResponseHandler.java:36) + at com.dtflys.forest.backend.okhttp3.response.OkHttp3ResponseHandler.handleSync(OkHttp3ResponseHandler.java:29) + at com.dtflys.forest.backend.okhttp3.executor.AbstractOkHttp3Executor.execute(AbstractOkHttp3Executor.java:260) + at com.dtflys.forest.backend.okhttp3.executor.AbstractOkHttp3Executor.execute(AbstractOkHttp3Executor.java:288) + at com.dtflys.forest.http.ForestRequest.execute(ForestRequest.java:1731) + at com.dtflys.forest.http.ForestRequest.execute(ForestRequest.java:1748) + at com.dtflys.forest.reflection.ForestMethod.invoke(ForestMethod.java:1230) + at com.dtflys.forest.proxy.InterfaceProxyHandler.invoke(InterfaceProxyHandler.java:150) + at com.sun.proxy.TProxy127.userAdd(Unknown Source) + at com.zmops.iot.web.sys.service.SysUserService.createUser(SysUserService.java:132) + at com.zmops.iot.web.sys.service.SysUserServiceTTFastClassBySpringCGLIBTT5b7cfc4d.invoke() + at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) + at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367) + at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) + at org.springframework.aop.framework.CglibAopProxyTDynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) + at com.zmops.iot.web.sys.service.SysUserServiceTTEnhancerBySpringCGLIBTT9bb24deb.createUser() + at com.zmops.iot.web.sys.controller.SysUserController.createUser(SysUserController.java:51) + at com.zmops.iot.web.sys.controller.SysUserControllerTTFastClassBySpringCGLIBTT2e326b39.invoke() + at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) + at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88) + at com.zmops.iot.web.log.aop.LogAop.recordSysLog(LogAop.java:54) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644) + at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633) + at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70) + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) + at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95) + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) + at org.springframework.aop.framework.CglibAopProxyTDynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) + at com.zmops.iot.web.sys.controller.SysUserControllerTTEnhancerBySpringCGLIBTT2cad82eb.createUser() + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) + at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) + at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) + at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878) + at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792) + at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) + at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) + at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) + at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) + at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) + at javax.servlet.http.HttpServlet.service(HttpServlet.java:517) + at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) + at javax.servlet.http.HttpServlet.service(HttpServlet.java:584) + at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:129) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113) + at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:320) + at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126) + at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at com.zmops.iot.core.auth.filter.JwtAuthorizationTokenFilter.doFilterInternal(JwtAuthorizationTokenFilter.java:77) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92) + at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) + at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) + at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) + at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) + at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) + at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) + at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) + at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:97) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) + at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) + at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) + at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) + at io.undertow.servlet.handlers.ServletChainT1.handleRequest(ServletChain.java:68) + at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) + at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68) + at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:111) + at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) + at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) + at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) + at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) + at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) + at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) + at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) + at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) + at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) + at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269) + at io.undertow.servlet.handlers.ServletInitialHandler.accessT100(ServletInitialHandler.java:78) + at io.undertow.servlet.handlers.ServletInitialHandlerT2.call(ServletInitialHandler.java:133) + at io.undertow.servlet.handlers.ServletInitialHandlerT2.call(ServletInitialHandler.java:130) + at io.undertow.servlet.core.ServletRequestContextThreadSetupActionT1.call(ServletRequestContextThreadSetupAction.java:48) + at io.undertow.servlet.core.ContextClassLoaderSetupActionT1.call(ContextClassLoaderSetupAction.java:43) + at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249) + at io.undertow.servlet.handlers.ServletInitialHandler.accessT000(ServletInitialHandler.java:78) + at io.undertow.servlet.handlers.ServletInitialHandlerT1.handleRequest(ServletInitialHandler.java:99) + at io.undertow.server.Connectors.executeRootHandler(Connectors.java:390) + at io.undertow.server.HttpServerExchangeT1.run(HttpServerExchange.java:836) + at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) + at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019) + at org.jboss.threads.EnhancedQueueExecutorTThreadBody.doRunTask(EnhancedQueueExecutor.java:1558) + at org.jboss.threads.EnhancedQueueExecutorTThreadBody.run(EnhancedQueueExecutor.java:1449) + at java.lang.Thread.run(Thread.java:748) +'); +INSERT INTO "public"."sys_operation_log" VALUES (1440883334531739648, '异常日志', '', 1, NULL, NULL, '2021-09-23 11:38:51.926', '失败', 'com.zmops.iot.model.exception.ZbxApiException: User group with ID "107" is not available. + at com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor.onSuccess(JsonBodyBuildInterceptor.java:78) + at com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor.onSuccess(JsonBodyBuildInterceptor.java:28) + at com.dtflys.forest.interceptor.InterceptorChain.onSuccess(InterceptorChain.java:64) + at com.dtflys.forest.reflection.MethodLifeCycleHandler.handleSuccess(MethodLifeCycleHandler.java:111) + at com.dtflys.forest.reflection.MethodLifeCycleHandler.handleSyncWithException(MethodLifeCycleHandler.java:55) + at com.dtflys.forest.reflection.MethodLifeCycleHandler.handleSync(MethodLifeCycleHandler.java:46) + at com.dtflys.forest.backend.AbstractBackendResponseHandler.handleSync(AbstractBackendResponseHandler.java:36) + at com.dtflys.forest.backend.okhttp3.response.OkHttp3ResponseHandler.handleSync(OkHttp3ResponseHandler.java:29) + at com.dtflys.forest.backend.okhttp3.executor.AbstractOkHttp3Executor.execute(AbstractOkHttp3Executor.java:260) + at com.dtflys.forest.backend.okhttp3.executor.AbstractOkHttp3Executor.execute(AbstractOkHttp3Executor.java:288) + at com.dtflys.forest.http.ForestRequest.execute(ForestRequest.java:1731) + at com.dtflys.forest.http.ForestRequest.execute(ForestRequest.java:1748) + at com.dtflys.forest.reflection.ForestMethod.invoke(ForestMethod.java:1230) + at com.dtflys.forest.proxy.InterfaceProxyHandler.invoke(InterfaceProxyHandler.java:150) + at com.sun.proxy.TProxy127.userAdd(Unknown Source) + at com.zmops.iot.web.sys.service.SysUserService.createUser(SysUserService.java:132) + at com.zmops.iot.web.sys.service.SysUserServiceTTFastClassBySpringCGLIBTT5b7cfc4d.invoke() + at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) + at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367) + at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) + at org.springframework.aop.framework.CglibAopProxyTDynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) + at com.zmops.iot.web.sys.service.SysUserServiceTTEnhancerBySpringCGLIBTT9bb24deb.createUser() + at com.zmops.iot.web.sys.controller.SysUserController.createUser(SysUserController.java:51) + at com.zmops.iot.web.sys.controller.SysUserControllerTTFastClassBySpringCGLIBTT2e326b39.invoke() + at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) + at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88) + at com.zmops.iot.web.log.aop.LogAop.recordSysLog(LogAop.java:54) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644) + at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633) + at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70) + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) + at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95) + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) + at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) + at org.springframework.aop.framework.CglibAopProxyTDynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) + at com.zmops.iot.web.sys.controller.SysUserControllerTTEnhancerBySpringCGLIBTT2cad82eb.createUser() + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) + at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) + at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) + at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878) + at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792) + at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) + at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) + at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) + at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) + at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) + at javax.servlet.http.HttpServlet.service(HttpServlet.java:517) + at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) + at javax.servlet.http.HttpServlet.service(HttpServlet.java:584) + at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:129) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113) + at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:320) + at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126) + at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at com.zmops.iot.core.auth.filter.JwtAuthorizationTokenFilter.doFilterInternal(JwtAuthorizationTokenFilter.java:77) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92) + at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) + at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) + at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) + at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) + at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) + at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) + at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) + at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) + at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:97) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) + at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) + at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) + at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) + at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) + at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) + at io.undertow.servlet.handlers.ServletChainT1.handleRequest(ServletChain.java:68) + at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) + at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68) + at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:111) + at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) + at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) + at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) + at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) + at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) + at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) + at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) + at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) + at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) + at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269) + at io.undertow.servlet.handlers.ServletInitialHandler.accessT100(ServletInitialHandler.java:78) + at io.undertow.servlet.handlers.ServletInitialHandlerT2.call(ServletInitialHandler.java:133) + at io.undertow.servlet.handlers.ServletInitialHandlerT2.call(ServletInitialHandler.java:130) + at io.undertow.servlet.core.ServletRequestContextThreadSetupActionT1.call(ServletRequestContextThreadSetupAction.java:48) + at io.undertow.servlet.core.ContextClassLoaderSetupActionT1.call(ContextClassLoaderSetupAction.java:43) + at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249) + at io.undertow.servlet.handlers.ServletInitialHandler.accessT000(ServletInitialHandler.java:78) + at io.undertow.servlet.handlers.ServletInitialHandlerT1.handleRequest(ServletInitialHandler.java:99) + at io.undertow.server.Connectors.executeRootHandler(Connectors.java:390) + at io.undertow.server.HttpServerExchangeT1.run(HttpServerExchange.java:836) + at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) + at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019) + at org.jboss.threads.EnhancedQueueExecutorTThreadBody.doRunTask(EnhancedQueueExecutor.java:1558) + at org.jboss.threads.EnhancedQueueExecutorTThreadBody.run(EnhancedQueueExecutor.java:1449) + at java.lang.Thread.run(Thread.java:748) +'); +INSERT INTO "public"."sys_operation_log" VALUES (1440883824174788608, '业务日志', '创建用户', 1, 'com.zmops.iot.web.sys.controller.SysUserController', 'createUser', '2021-09-23 11:40:48.667', '成功', ''); + +-- ---------------------------- +-- Table structure for sys_role +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_role"; +CREATE TABLE "public"."sys_role" ( + "role_id" int8 NOT NULL, + "name" varchar(255) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "sort" int2, + "create_user" int8, + "update_user" int8, + "create_time" timestamp(6), + "update_time" timestamp(6) +) +; + +-- ---------------------------- +-- Records of sys_role +-- ---------------------------- +INSERT INTO "public"."sys_role" VALUES (1, '超级管理员', 'administrator', 1, NULL, 1, NULL, '2021-08-17 10:57:36.612'); +INSERT INTO "public"."sys_role" VALUES (1432233337871355904, '测试', '', NULL, 1, 1, '2021-08-30 14:46:52.014', '2021-08-30 14:46:52.014'); +INSERT INTO "public"."sys_role" VALUES (1437618920839958528, '三石TestgOtXD2', NULL, NULL, 1, 1, '2021-09-14 11:27:15.053', '2021-09-14 11:27:15.053'); + +-- ---------------------------- +-- Table structure for sys_role_menu +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_role_menu"; +CREATE TABLE "public"."sys_role_menu" ( + "role_id" int8, + "menu_id" int8 +) +; + +-- ---------------------------- +-- Records of sys_role_menu +-- ---------------------------- +INSERT INTO "public"."sys_role_menu" VALUES (1423482240088260608, 1); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 105); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 106); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 114); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 128); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 132); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 133); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 168); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 169); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 170); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 171); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 172); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 173); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 174); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 175); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 176); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 177); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 178); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 179); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 180); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 181); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 182); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 183); +INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 184); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 105); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 106); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 114); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 128); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 132); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 133); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 168); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 169); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 170); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 171); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 172); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 173); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 174); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 175); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 176); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 177); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 178); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 179); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 180); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 181); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 182); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 183); +INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 184); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 105); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 106); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 114); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 128); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 132); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 133); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 168); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 169); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 170); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 171); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 172); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 173); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 174); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 175); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 176); +INSERT INTO "public"."sys_role_menu" VALUES (1422463279817150464, 170); +INSERT INTO "public"."sys_role_menu" VALUES (1422463279817150464, 178); +INSERT INTO "public"."sys_role_menu" VALUES (1422463279817150464, 177); +INSERT INTO "public"."sys_role_menu" VALUES (1422463279817150464, 179); +INSERT INTO "public"."sys_role_menu" VALUES (1422463279817150464, 181); +INSERT INTO "public"."sys_role_menu" VALUES (1422463279817150464, 172); +INSERT INTO "public"."sys_role_menu" VALUES (1422463279817150464, 182); +INSERT INTO "public"."sys_role_menu" VALUES (1422463279817150464, 171); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 177); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 178); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 179); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 180); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 181); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 182); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 183); +INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 184); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 105); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 106); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 114); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 128); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 132); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 133); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 168); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 169); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 170); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 171); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 172); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 173); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 174); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 175); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 176); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 177); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 178); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 179); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 180); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 181); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 182); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 183); +INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 184); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 105); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 106); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 114); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 128); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 132); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 133); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 168); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 169); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 170); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 171); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 172); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 173); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 174); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 175); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 176); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 177); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 178); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 179); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 180); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 181); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 182); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 183); +INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 184); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 105); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 106); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 114); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 128); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 132); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 133); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 168); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 169); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 170); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 171); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 172); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 173); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 174); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 175); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 176); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 177); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 178); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 179); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 180); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 181); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 182); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 183); +INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 184); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 105); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 106); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 114); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 128); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 132); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 133); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 168); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 169); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 170); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 171); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 173); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 174); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 176); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 177); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 178); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 179); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 180); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 181); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 183); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 184); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 185); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 186); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 187); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 188); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 189); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 190); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 191); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 192); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 193); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 194); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 195); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 196); +INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 197); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 105); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 106); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 114); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 128); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 132); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 133); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 168); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 169); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 170); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 171); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 173); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 174); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 176); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 177); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 178); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 179); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 180); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 181); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 183); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 184); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 185); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 186); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 187); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 188); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 189); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 190); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 191); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 192); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 193); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 194); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 195); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 196); +INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 197); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 105); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 106); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 114); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 128); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 132); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 133); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 168); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 169); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 170); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 171); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 173); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 174); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 176); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 177); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 178); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 179); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 180); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 181); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 183); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 184); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 185); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 186); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 187); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 188); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 189); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 190); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 191); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 192); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 193); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 194); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 195); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 196); +INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 197); +INSERT INTO "public"."sys_role_menu" VALUES (1428553795793240064, 105); +INSERT INTO "public"."sys_role_menu" VALUES (1428555085013237760, 105); +INSERT INTO "public"."sys_role_menu" VALUES (1428555388848619520, 105); +INSERT INTO "public"."sys_role_menu" VALUES (1428559148366872576, 105); +INSERT INTO "public"."sys_role_menu" VALUES (1432233337871355904, 189); +INSERT INTO "public"."sys_role_menu" VALUES (1432233337871355904, 169); +INSERT INTO "public"."sys_role_menu" VALUES (1, 169); +INSERT INTO "public"."sys_role_menu" VALUES (1, 189); +INSERT INTO "public"."sys_role_menu" VALUES (1, 190); +INSERT INTO "public"."sys_role_menu" VALUES (1, 176); +INSERT INTO "public"."sys_role_menu" VALUES (1, 197); +INSERT INTO "public"."sys_role_menu" VALUES (1, 170); +INSERT INTO "public"."sys_role_menu" VALUES (1, 177); +INSERT INTO "public"."sys_role_menu" VALUES (1, 188); +INSERT INTO "public"."sys_role_menu" VALUES (1, 178); +INSERT INTO "public"."sys_role_menu" VALUES (1, 196); +INSERT INTO "public"."sys_role_menu" VALUES (1, 171); +INSERT INTO "public"."sys_role_menu" VALUES (1, 181); +INSERT INTO "public"."sys_role_menu" VALUES (1, 180); +INSERT INTO "public"."sys_role_menu" VALUES (1, 185); +INSERT INTO "public"."sys_role_menu" VALUES (1, 174); +INSERT INTO "public"."sys_role_menu" VALUES (1, 192); +INSERT INTO "public"."sys_role_menu" VALUES (1, 179); +INSERT INTO "public"."sys_role_menu" VALUES (1, 194); +INSERT INTO "public"."sys_role_menu" VALUES (1, 193); +INSERT INTO "public"."sys_role_menu" VALUES (1, 184); +INSERT INTO "public"."sys_role_menu" VALUES (1, 133); +INSERT INTO "public"."sys_role_menu" VALUES (1, 128); +INSERT INTO "public"."sys_role_menu" VALUES (1, 105); +INSERT INTO "public"."sys_role_menu" VALUES (1, 168); +INSERT INTO "public"."sys_role_menu" VALUES (1, 186); +INSERT INTO "public"."sys_role_menu" VALUES (1, 106); +INSERT INTO "public"."sys_role_menu" VALUES (1, 107); +INSERT INTO "public"."sys_role_menu" VALUES (1, 108); +INSERT INTO "public"."sys_role_menu" VALUES (1, 109); +INSERT INTO "public"."sys_role_menu" VALUES (1, 110); +INSERT INTO "public"."sys_role_menu" VALUES (1, 113); +INSERT INTO "public"."sys_role_menu" VALUES (1, 114); +INSERT INTO "public"."sys_role_menu" VALUES (1, 115); +INSERT INTO "public"."sys_role_menu" VALUES (1, 116); +INSERT INTO "public"."sys_role_menu" VALUES (1, 117); +INSERT INTO "public"."sys_role_menu" VALUES (1, 118); +INSERT INTO "public"."sys_role_menu" VALUES (1, 132); +INSERT INTO "public"."sys_role_menu" VALUES (1, 187); +INSERT INTO "public"."sys_role_menu" VALUES (1437255079924846592, 168); +INSERT INTO "public"."sys_role_menu" VALUES (1437255079924846592, 186); +INSERT INTO "public"."sys_role_menu" VALUES (1437255079924846592, 187); +INSERT INTO "public"."sys_role_menu" VALUES (1437255079924846592, 105); +INSERT INTO "public"."sys_role_menu" VALUES (1, 198); + +-- ---------------------------- +-- Table structure for sys_user +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_user"; +CREATE TABLE "public"."sys_user" ( + "account" varchar(255) COLLATE "pg_catalog"."default", + "password" varchar(255) COLLATE "pg_catalog"."default", + "salt" varchar(255) COLLATE "pg_catalog"."default", + "name" varchar(255) COLLATE "pg_catalog"."default", + "email" varchar(255) COLLATE "pg_catalog"."default", + "phone" varchar(255) COLLATE "pg_catalog"."default", + "role_id" int8, + "user_group_id" int8, + "status" varchar(32) COLLATE "pg_catalog"."default", + "create_user" int8, + "update_user" int8, + "create_time" timestamp(6), + "update_time" timestamp(6), + "user_id" int8 NOT NULL DEFAULT nextval('sys_user_user_id_seq'::regclass), + "zbx_token" varchar(255) COLLATE "pg_catalog"."default", + "zbx_id" varchar(64) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."sys_user"."account" IS '登陆账号名'; +COMMENT ON COLUMN "public"."sys_user"."password" IS '密码'; +COMMENT ON COLUMN "public"."sys_user"."salt" IS '密码盐'; +COMMENT ON COLUMN "public"."sys_user"."name" IS '用户名'; +COMMENT ON COLUMN "public"."sys_user"."email" IS '电子邮箱地址'; +COMMENT ON COLUMN "public"."sys_user"."phone" IS '手机号'; +COMMENT ON COLUMN "public"."sys_user"."role_id" IS '角色ID'; +COMMENT ON COLUMN "public"."sys_user"."user_group_id" IS '用户组ID'; +COMMENT ON COLUMN "public"."sys_user"."status" IS '状态'; +COMMENT ON COLUMN "public"."sys_user"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."sys_user"."update_user" IS '修改人'; +COMMENT ON COLUMN "public"."sys_user"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."sys_user"."update_time" IS '更新时间'; +COMMENT ON COLUMN "public"."sys_user"."user_id" IS '用户ID'; +COMMENT ON COLUMN "public"."sys_user"."zbx_token" IS 'zabbix 登陆 token'; +COMMENT ON COLUMN "public"."sys_user"."zbx_id" IS 'zabbix 用户ID'; + +-- ---------------------------- +-- Records of sys_user +-- ---------------------------- +INSERT INTO "public"."sys_user" VALUES ('root', '17db03c22596b7609c7c9704f16663e0', 'abcdef', '超级管理员', '888888@qq.com', '13812345678', 1, NULL, 'ENABLE', 1, 1, '2021-07-30 21:43:02.686', '2021-07-30 21:43:02.686', 1, '6828c069d5e939b384513d705a2b9ff4', '4'); +INSERT INTO "public"."sys_user" VALUES ('Admin', '897e47e15311c2fafa7408af5d33b76b', 'q4y9d', '超级管理员', '', '', 1, 1433259921541644288, 'ENABLE', 1, 1, '2021-09-23 11:40:48.622', '2021-09-23 11:40:48.622', 117, '7f7ae1a47db539231208c8e3b743059d', '1'); +INSERT INTO "public"."sys_user" VALUES ('zuolan', 'e1e874669f7b8d5d9c339abf919668e2', '2c6t3', '卓蓝', '', '', 1, 1435061972567298048, 'ENABLE', 1, 1, '2021-09-16 20:19:35.538', '2021-09-16 20:19:35.538', 116, NULL, '80'); +INSERT INTO "public"."sys_user" VALUES ('sanshi', '8368532ffd4039b103d1c71511671d99', 'j75bd', '三石', '', '', 1, 1435061972567298048, 'ENABLE', 1, 1, '2021-09-08 15:08:53.598', '2021-09-08 15:08:53.598', 79, NULL, '42'); + +-- ---------------------------- +-- Table structure for sys_user_group +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_user_group"; +CREATE TABLE "public"."sys_user_group" ( + "group_name" varchar(255) COLLATE "pg_catalog"."default", + "zbx_id" varchar(32) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "create_time" timestamp(0), + "create_user" int8, + "update_time" timestamp(0), + "update_user" int8, + "status" varchar(32) COLLATE "pg_catalog"."default" DEFAULT 1, + "user_group_id" int8 NOT NULL +) +; + +-- ---------------------------- +-- Records of sys_user_group +-- ---------------------------- +INSERT INTO "public"."sys_user_group" VALUES ('默认用户组', '7', '', '2021-09-02 10:46:09', 1, '2021-09-02 10:46:09', 1, 'ENABLE', 1433259921541644288); + +-- ---------------------------- +-- Table structure for sys_usrgrp_devicegrp +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_usrgrp_devicegrp"; +CREATE TABLE "public"."sys_usrgrp_devicegrp" ( + "user_group_id" int8, + "device_group_id" int8 +) +; + +-- ---------------------------- +-- Records of sys_usrgrp_devicegrp +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tag +-- ---------------------------- +DROP TABLE IF EXISTS "public"."tag"; +CREATE TABLE "public"."tag" ( + "sid" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, + "tag" varchar(64) COLLATE "pg_catalog"."default", + "value" varchar(64) COLLATE "pg_catalog"."default", + "id" int4 NOT NULL DEFAULT nextval('tag_id_seq'::regclass), + "template_id" int4, + "create_user" int8, + "update_user" int8, + "create_time" timestamp(6), + "update_time" timestamp(6) +) +; +COMMENT ON COLUMN "public"."tag"."sid" IS '所属ID'; +COMMENT ON COLUMN "public"."tag"."tag" IS '标签'; +COMMENT ON COLUMN "public"."tag"."value" IS '标签值'; +COMMENT ON COLUMN "public"."tag"."id" IS 'ID'; +COMMENT ON COLUMN "public"."tag"."template_id" IS '继承的ID'; +COMMENT ON COLUMN "public"."tag"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."tag"."update_user" IS '修改人'; +COMMENT ON COLUMN "public"."tag"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."tag"."update_time" IS '更新时间'; + +-- ---------------------------- +-- Records of tag +-- ---------------------------- +INSERT INTO "public"."tag" VALUES ('1432184478772101120', '位置', '位置', 157, NULL, 1, 1, '2021-08-30 11:35:29.303', '2021-08-30 11:35:29.303'); +INSERT INTO "public"."tag" VALUES ('1432254913865859072', '位置', '位置', 159, 157, NULL, NULL, NULL, NULL); +INSERT INTO "public"."tag" VALUES ('1432255618861240320', '位置', '位置', 160, 157, NULL, NULL, NULL, NULL); +INSERT INTO "public"."tag" VALUES ('1434043521937584128', '45646', '456456', 171, NULL, 1, 1, '2021-09-14 18:05:22.27', '2021-09-14 18:05:22.27'); +INSERT INTO "public"."tag" VALUES ('1434043521937584128', '1', '1', 172, NULL, 1, 1, '2021-09-14 18:05:22.27', '2021-09-14 18:05:22.27'); +INSERT INTO "public"."tag" VALUES ('1434043521937584128', '2', '3', 173, NULL, 1, 1, '2021-09-14 18:05:22.27', '2021-09-14 18:05:22.27'); +INSERT INTO "public"."tag" VALUES ('1437965905006678016', 'SSp7u9WF11', '三石TestHdF4i011', 174, NULL, 1, 1, '2021-09-15 10:26:02.639', '2021-09-15 10:26:02.639'); +INSERT INTO "public"."tag" VALUES ('1437966016684216320', 'SSLspEVQ11', '三石TestOwN6U311', 175, NULL, 1, 1, '2021-09-15 10:26:29.264', '2021-09-15 10:26:29.264'); +INSERT INTO "public"."tag" VALUES ('1437966016684216320', 'SSLspEVQ12', '三石TestOwN6U312', 176, NULL, 1, 1, '2021-09-15 10:26:29.264', '2021-09-15 10:26:29.264'); +INSERT INTO "public"."tag" VALUES ('1437966016684216320', 'SSLspEVQ13', '三石TestOwN6U313', 177, NULL, 1, 1, '2021-09-15 10:26:29.264', '2021-09-15 10:26:29.264'); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."device_online_report_id_seq" +OWNED BY "public"."device_online_report"."id"; +SELECT setval('"public"."device_online_report_id_seq"', 5, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."devices_groups_id_seq" +OWNED BY "public"."devices_groups"."id"; +SELECT setval('"public"."devices_groups_id_seq"', 171, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."media_type_setting_id_seq" +OWNED BY "public"."media_type_setting"."id"; +SELECT setval('"public"."media_type_setting_id_seq"', 2, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."messages_id_seq" +OWNED BY "public"."messages"."id"; +SELECT setval('"public"."messages_id_seq"', 222, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."product_event_relation_id_seq" +OWNED BY "public"."product_event_relation"."id"; +SELECT setval('"public"."product_event_relation_id_seq"', 43, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."product_event_tags_id_seq" +OWNED BY "public"."product_event_tags"."id"; +SELECT setval('"public"."product_event_tags_id_seq"', 3, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."product_service_relation_id_seq" +OWNED BY "public"."product_service_relation"."id"; +SELECT setval('"public"."product_service_relation_id_seq"', 24, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."product_status_function_relation_id_seq" +OWNED BY "public"."product_status_function_relation"."id"; +SELECT setval('"public"."product_status_function_relation_id_seq"', 8, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."product_type_product_type_id_seq" +OWNED BY "public"."product_type"."id"; +SELECT setval('"public"."product_type_product_type_id_seq"', 215, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."service_execute_record_id_seq" +OWNED BY "public"."service_execute_record"."id"; +SELECT setval('"public"."service_execute_record_id_seq"', 2, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."service_id_seq" +OWNED BY "public"."product_service"."id"; +SELECT setval('"public"."service_id_seq"', 33, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."service_param_id_seq" +OWNED BY "public"."product_service_param"."id"; +SELECT setval('"public"."service_param_id_seq"', 19, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."sys_user_group_user_group_id_seq" +OWNED BY "public"."sys_user_group"."user_group_id"; +SELECT setval('"public"."sys_user_group_user_group_id_seq"', 30, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."sys_user_user_id_seq" +OWNED BY "public"."sys_user"."user_id"; +SELECT setval('"public"."sys_user_user_id_seq"', 118, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."tag_id_seq" +OWNED BY "public"."tag"."id"; +SELECT setval('"public"."tag_id_seq"', 180, true); + +-- ---------------------------- +-- Primary Key structure for table device +-- ---------------------------- +ALTER TABLE "public"."device" ADD CONSTRAINT "device_pkey" PRIMARY KEY ("device_id"); + +-- ---------------------------- +-- Primary Key structure for table device_group +-- ---------------------------- +ALTER TABLE "public"."device_group" ADD CONSTRAINT "device_group_pkey" PRIMARY KEY ("device_group_id"); + +-- ---------------------------- +-- Primary Key structure for table device_online_report +-- ---------------------------- +ALTER TABLE "public"."device_online_report" ADD CONSTRAINT "device_online_report_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table devices_groups +-- ---------------------------- +ALTER TABLE "public"."devices_groups" ADD CONSTRAINT "devices_groups_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table media_type_setting +-- ---------------------------- +ALTER TABLE "public"."media_type_setting" ADD CONSTRAINT "media_type_setting_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table messages +-- ---------------------------- +ALTER TABLE "public"."messages" ADD CONSTRAINT "messages_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table product +-- ---------------------------- +ALTER TABLE "public"."product" ADD CONSTRAINT "product_pkey" PRIMARY KEY ("product_id"); + +-- ---------------------------- +-- Primary Key structure for table product_attribute +-- ---------------------------- +ALTER TABLE "public"."product_attribute" ADD CONSTRAINT "product_attribute_pkey" PRIMARY KEY ("attr_id"); + +-- ---------------------------- +-- Primary Key structure for table product_attribute_event +-- ---------------------------- +ALTER TABLE "public"."product_attribute_event" ADD CONSTRAINT "product_attribute_copy1_pkey" PRIMARY KEY ("attr_id"); + +-- ---------------------------- +-- Primary Key structure for table product_event +-- ---------------------------- +ALTER TABLE "public"."product_event" ADD CONSTRAINT "product_event_pkey" PRIMARY KEY ("event_rule_id"); + +-- ---------------------------- +-- Primary Key structure for table product_event_expression +-- ---------------------------- +ALTER TABLE "public"."product_event_expression" ADD CONSTRAINT "product_event_copy1_pkey1" PRIMARY KEY ("event_exp_id"); + +-- ---------------------------- +-- Primary Key structure for table product_event_relation +-- ---------------------------- +ALTER TABLE "public"."product_event_relation" ADD CONSTRAINT "product_event_relation_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table product_event_tags +-- ---------------------------- +ALTER TABLE "public"."product_event_tags" ADD CONSTRAINT "product_event_tags_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table product_group +-- ---------------------------- +ALTER TABLE "public"."product_group" ADD CONSTRAINT "product_group_pkey" PRIMARY KEY ("product_group_id"); + +-- ---------------------------- +-- Primary Key structure for table product_service +-- ---------------------------- +ALTER TABLE "public"."product_service" ADD CONSTRAINT "service_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table product_service_param +-- ---------------------------- +ALTER TABLE "public"."product_service_param" ADD CONSTRAINT "service_param_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table product_service_relation +-- ---------------------------- +ALTER TABLE "public"."product_service_relation" ADD CONSTRAINT "product_service_relation_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table product_status_function +-- ---------------------------- +ALTER TABLE "public"."product_status_function" ADD CONSTRAINT "product_status_function_pkey" PRIMARY KEY ("rule_id"); + +-- ---------------------------- +-- Primary Key structure for table product_status_function_relation +-- ---------------------------- +ALTER TABLE "public"."product_status_function_relation" ADD CONSTRAINT "product_status_function_relation_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table product_type +-- ---------------------------- +ALTER TABLE "public"."product_type" ADD CONSTRAINT "product_type_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table service_execute_record +-- ---------------------------- +ALTER TABLE "public"."service_execute_record" ADD CONSTRAINT "service_execute_record_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table sys_config +-- ---------------------------- +ALTER TABLE "public"."sys_config" ADD CONSTRAINT "sys_config_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table sys_dict +-- ---------------------------- +ALTER TABLE "public"."sys_dict" ADD CONSTRAINT "sys_dict_pkey" PRIMARY KEY ("dict_id"); + +-- ---------------------------- +-- Primary Key structure for table sys_dict_type +-- ---------------------------- +ALTER TABLE "public"."sys_dict_type" ADD CONSTRAINT "sys_dict_type_pkey" PRIMARY KEY ("dict_type_id"); + +-- ---------------------------- +-- Primary Key structure for table sys_login_log +-- ---------------------------- +ALTER TABLE "public"."sys_login_log" ADD CONSTRAINT "sys_login_log_pkey" PRIMARY KEY ("login_log_id"); + +-- ---------------------------- +-- Primary Key structure for table sys_menu +-- ---------------------------- +ALTER TABLE "public"."sys_menu" ADD CONSTRAINT "sys_menu_pkey" PRIMARY KEY ("menu_id"); + +-- ---------------------------- +-- Primary Key structure for table sys_operation_log +-- ---------------------------- +ALTER TABLE "public"."sys_operation_log" ADD CONSTRAINT "sys_operation_log_pkey" PRIMARY KEY ("operation_log_id"); + +-- ---------------------------- +-- Primary Key structure for table sys_role +-- ---------------------------- +ALTER TABLE "public"."sys_role" ADD CONSTRAINT "sys_role_pkey" PRIMARY KEY ("role_id"); + +-- ---------------------------- +-- Primary Key structure for table sys_user +-- ---------------------------- +ALTER TABLE "public"."sys_user" ADD CONSTRAINT "sys_user_pkey" PRIMARY KEY ("user_id"); + +-- ---------------------------- +-- Primary Key structure for table sys_user_group +-- ---------------------------- +ALTER TABLE "public"."sys_user_group" ADD CONSTRAINT "sys_user_group_pkey" PRIMARY KEY ("user_group_id"); + +-- ---------------------------- +-- Primary Key structure for table tag +-- ---------------------------- +ALTER TABLE "public"."tag" ADD CONSTRAINT "tag_pkey" PRIMARY KEY ("id"); diff --git a/docs/quick-install.sh b/docs/centos/install.sh similarity index 71% rename from docs/quick-install.sh rename to docs/centos/install.sh index fc3eb7f4..c773819e 100755 --- a/docs/quick-install.sh +++ b/docs/centos/install.sh @@ -1,9 +1,8 @@ #!/usr/bin/env bash + set -e ROOT_UID=0 -E_NOTROOT=67 -E_BADOD=68 release=Centos basename=$(pwd) zabbixsrc=$basename/zabbix-5.4.3 @@ -23,12 +22,12 @@ function logprint() { ## 系统环境检测 if [ "$(uname)" != Linux ]; then echo "该脚本只使用 Linux 系统" - exit $E_BADOD + exit fi if [ "$UID" -ne "$ROOT_UID" ]; then - echo "Must be root to install" - exit $E_NOTROOT + echo -e "Error: Must be root to install" + exit fi ### 操作系统 if [ ! -f /etc/redhat-release ]; then @@ -49,12 +48,12 @@ disks=$(df -T | awk '/(xfs|ext4|ext3)/{if($3/1024/1024 > 10)printf("%s\t%d\n",$7 if [ "$cores" -lt 0 ] || [ "$memstotal" -lt 0 ] || [ "$disks" -eq 0 ]; then echo "要求最低配置为 CPU 2核 内存 4GB 存储空间 100G" - exit 70 + exit fi ## 系统环境初始化 function InitSystem() { - echo "初始化系统环境" + echo -e -n "\033[32mStep1: 初始化系统安装环境。。。 \033[0m" if ! hostnamectl set-hostname zeus-server; then echo "主机名修改失败" exit @@ -85,11 +84,16 @@ function InitSystem() { ### 添加安装目录 [ ! -d /opt/zeus ] && mkdir -p /opt/zeus + echo -e "\033[32m [ OK ] \033[0m" } # 开始安装 ## 配置 YUM 源 function AddInstallRepo() { + + echo -e -n "\033[32mStep2: 配置安装 YUM 源 。。。 \033[0m" + ### 备份原有yum + mv /etc/yum.repos.d/* /tmp/ ### 基础 YUM 源 if ! curl -s -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo; then echo "YUM 仓库配置异常,请检查网络" @@ -104,12 +108,6 @@ failovermethod=priority enabled=1 gpgcheck=0 -[timescale_timescaledb] -name=timescale_timescaledb -baseurl=https://packagecloud.io/timescale/timescaledb/el/$(rpm -E %{rhel})/\$basearch -gpgcheck=0 -enabled=1 - [centos-sclo-rh] name=CentOS-7 - SCLo rh baseurl=https://mirrors.aliyun.com/centos/7/sclo/\$basearch/rh/ @@ -129,30 +127,25 @@ baseurl=https://download.postgresql.org/pub/repos/yum/13/redhat/rhel-\$releaseve enabled=1 gpgcheck=0 -[pgdg12] -name=PostgreSQL 12 for RHEL/CentOS \$releasever - \$basearch -baseurl=https://download.postgresql.org/pub/repos/yum/12/redhat/rhel-\$releasever-\$basearch -enabled=1 -gpgcheck=0 EOL - echo "配置安装 YUM 源 。。。" yum clean all 1>/dev/null && yum makecache 1>/dev/null logprint "yum 源配置失败详细看安装日志输出" + echo -e "\033[32m [ OK ] \033[0m" } ## 安装 PostgreSQL function PGInstall() { + echo -e -n "\033[32mStep3: 安装 PostgreSQL.... \033[0m" yum -y install postgresql13.x86_64 \ postgresql13-devel.x86_64 \ - postgresql13-plpython3.x86_64 \ - timescaledb-2-postgresql-13.x86_64 1>/dev/null + postgresql13-plpython3.x86_64 1>/dev/null logprint "yum 源配置失败详细看安装日志输出" ### 创建 PostgreSQL 用户 ### 修改启动文件 - echo "安装 PG-timescaledb " + [ ! -d $PGDATA ] && mkdir -p $PGDATA if ! chown postgres. $PGDATA; then echo "修改PGDATA用户失败" @@ -164,26 +157,27 @@ function PGInstall() { #sed -i 's/\(^Group\=\).*/\1zeus/g' $startfile sed -i 's/\(^Environment\=PGDATA\=\).*/\1\/opt\/zeus\/pgdata/g' $startfile ### 初始化数据库 - echo "开始初始化 PG" /usr/pgsql-13/bin/postgresql-13-setup initdb 1>/dev/null logprint "初始化错误" - echo "shared_preload_libraries = 'timescaledb'" >>/opt/zeus/pgdata/postgresql.conf +# echo "shared_preload_libraries = 'timescaledb'" >>/opt/zeus/pgdata/postgresql.conf ### 启动数据库 systemctl enable postgresql-13 &>/dev/null systemctl start postgresql-13 ### 修改数据库管理员密码 cd /tmp || exit - sudo -u postgres /usr/pgsql-13/bin/psql -c "ALTER USER postgres WITH PASSWORD 'zeusiot';" 2>/tmp/pg.log + sudo -u postgres /usr/pgsql-13/bin/psql -c "ALTER USER postgres WITH PASSWORD 'zeusiot';" 1> /dev/null + echo -e "\033[32m [ OK ] \033[0m" } ## 编译安装 zabbix 5.4 function ZbxInstall() { - echo "编译 zabbix" + echo -e -n "\033[32mStep4: 编译安装 zabbix 。。。 \033[0m" ### 安装编译依赖 cd "$basename" || exit yum -y install vim \ wget \ + expect \ gcc \ gcc-c++ \ net-snmp \ @@ -215,7 +209,7 @@ function ZbxInstall() { --with-openssl \ --with-ssh2 1>/dev/null logprint "zabbix 编译异常" - echo "安装 zabbix" + make install 1>/dev/null logprint "zabbix 编译异常" ### 前端内容部署 @@ -223,21 +217,23 @@ function ZbxInstall() { mv $ZABBIX_HOME/zabbix/conf/zabbix.conf.php.example $ZABBIX_HOME/zabbix/conf/zabbix.conf.php sed -i "s/\($DB\['PASSWORD'\]\s*=\).*/\1 'zabbix';/g" $ZABBIX_HOME/zabbix/conf/zabbix.conf.php sed -i "s/\($DB\['TYPE'\]\s*=\).*/\1 \'POSTGRESQL\';/g" $ZABBIX_HOME/zabbix/conf/zabbix.conf.php - + echo -e "\033[32m [ OK ] \033[0m" ### 数据初始化 - echo "初始化 zabbix 数据库" + echo -e -n "\033[32mStep5: 初始化 zabbix 数据库 。。。 \033[0m" cd /tmp/ || exit sudo -u postgres createuser zabbix - sudo -u postgres /usr/pgsql-13/bin/psql -c "ALTER USER zabbix WITH PASSWORD 'zabbix';" + sudo -u postgres /usr/pgsql-13/bin/psql -c "ALTER USER zabbix WITH PASSWORD 'zabbix';" 1> /dev/null sudo -u postgres createdb -O zabbix -E Unicode -T template0 zabbix cat $zabbixsrc/database/postgresql/schema.sql | sudo -u zabbix psql zabbix 1>/dev/null cat $zabbixsrc/database/postgresql/images.sql | sudo -u zabbix psql zabbix 1>/dev/null cat $zabbixsrc/database/postgresql/data.sql | sudo -u zabbix psql zabbix 1>/dev/null - echo "CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;" | sudo -u postgres psql zabbix &>/dev/null - cat $zabbixsrc/database/postgresql/timescaledb.sql | sudo -u zabbix psql zabbix 1>/dev/null +# echo "CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;" | sudo -u postgres psql zabbix &>/dev/null +# cat $zabbixsrc/database/postgresql/timescaledb.sql | sudo -u zabbix psql zabbix 1>/dev/null +# + echo -e "\033[32m [ OK ] \033[0m" cd "$basename" || exit ### 配置zabbix配置文件 - echo "启动zabbix" + echo -e -n "\033[32mStep6: 启动 zabbix .... \033[0m" sed -i 's/^# DBPassword=/DBPassword=zabbix/g' $ZABBIX_HOME/etc/zabbix_server.conf ### 配置启动文件 tee /usr/lib/systemd/system/zabbix-server.service </dev/null @@ -290,10 +286,11 @@ EOL systemctl enable zabbix-agent systemctl start zabbix-server systemctl start zabbix-agent + echo -e "\033[32m [ OK ] \033[0m" } ## 安装 php function PHPInstall() { - echo "安装 zabbix-web" + echo -e -n "\033[32mStep7: 安装 zabbix-web .... \033[0m" yum -y install rh-php73.x86_64 \ rh-php73-php-fpm.x86_64 \ rh-php73-php-bcmath.x86_64 \ @@ -313,47 +310,29 @@ function PHPInstall() { sed -i 's/;listen.owner = nobody/listen.owner = zeus/g' $PHP_CONF/php-fpm.d/www.conf sed -i 's/;listen.group = nobody/listen.group = zeus/g' $PHP_CONF/php-fpm.d/www.conf sed -i 's/\(^listen =\).*/\1\/var\/run\/php-fpm.sock/g' $PHP_CONF/php-fpm.d/www.conf + echo -e "\033[32m [ OK ] \033[0m" } -function ZeusInstall() { - +function WebInstall() { + echo -e -n "\033[32mStep8: 启动 zabbix-web .... \033[0m" ## 安装 nginx yum -y install nginx 1>/dev/null cd /opt/zeus - wget -c https://packages.zmops.cn/zeus-iot/app-1.0.tar.gz -o /dev/null -O - | tar -xz - wget -c https://packages.zmops.cn/zeus-iot/web-1.0.tar.gz -o /dev/null -O - | tar -xz - wget -c https://packages.zmops.cn/zeus-iot/zeus-iot.sql - sudo -u postgres createdb zeus-iot - cat zeus-iot.sql | sudo -u postgres psql zeus-iot ## 编辑 nginx 配置文件 tee /etc/nginx/conf.d/zabbix.conf </dev/null server { listen 80; - - location / { - root /opt/zeus/web; - index index.html; - try_files \$uri \$uri/ /index.html; - } - - location ^~/api/ { - client_body_buffer_size 10m; - proxy_set_header X-Real-IP \$remote_addr; - proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; - proxy_pass http://127.0.0.1:9090/; - } - - location /zabbix { + location /zabbix { alias $ZABBIX_HOME/zabbix; index index.html index.htm index.php; } location ~ ^/zabbix/.+\.php$ { - fastcgi_pass unix:/var/run/php/zabbix.sock; + fastcgi_pass unix:/var/run/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $ZABBIX_HOME\$fastcgi_script_name; include fastcgi_params; @@ -382,8 +361,67 @@ EOL systemctl enable nginx systemctl start rh-php73-php-fpm systemctl start nginx + echo -e "\033[32m [ OK ] \033[0m" +} + + + +function gettoken(){ + ## 获取 API 永久 token + local zabbix_api_url=http://127.0.0.1/zabbix/api_jsonrpc.php + local data='{"jsonrpc": "2.0","method": "user.login","params":{"user":"Admin","password":"zabbix"},"id":1,"auth":null}' + local res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $zabbix_api_url"` + local auth=`echo $res | python -c 'import sys, json; print(json.load(sys.stdin)["result"])'` + local data='{"jsonrpc": "2.0","method": "token.create","params":{"name":"zeus","userid":"1"},"id":1,"auth":"'${auth}'"}' + local res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $zabbix_api_url"` + local tokenid=`echo $res | python -c 'import sys, json; print(json.load(sys.stdin)["result"]["tokenids"][0])'` + local data='{"jsonrpc": "2.0","method": "token.generate","params":["'${tokenid}'"],"id":1,"auth":"'${auth}'"}' + local res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $zabbix_api_url"` + token=`echo $res | python -c 'import sys, json; print(json.load(sys.stdin)["result"][0]["token"])'` +} + + +function taosinstall() { + ### taos 数据安装 + echo -e -n "\033[32mStep9: 安装 taos 数据库。。。 \033[0m" + expect << EOF 1> /dev/null + spawn rpm -ivh https://www.taosdata.com/assets-download/TDengine-server-2.2.0.2-Linux-x64.rpm + expect { + "*one:" { send "\n";exp_continue} + "*skip:" { send "\n" } + } +EOF + ## 启动taos + systemctl enable taosd + systemctl start taosd + + echo -e "\033[32m [ OK ] \033[0m" +} + +function natsinstall() { + echo -e -n "\033[32mStep10: 安装 nats 服务。。。 \033[0m" + wget -c https://github.com/nats-io/nats-server/releases/download/v2.6.0/nats-server-v2.6.0-linux-amd64.tar.gz -o /dev/null -O - | tar -xz + mv ./nats-server-v2.6.0-linux-amd64/nats-server /usr/bin/nats-server + nohup nats-server &> /dev/null & + echo -e "\033[32m [ OK ] \033[0m" } -echo "安装完成。。。请访问 "http://localIP"" + +function ZeusInstall() { + echo -e -n "\033[32mStep11: 安装 Zeus-IoT 服务。。。 \033[0m" + cd /opt/zeus || exit + ## 创建taos 数据库 + taos -s "create database zeus_data" 1> /dev/null + wget -c https://packages.zmops.cn/zeus-iot/zeus-iot-bin.tar.gz -o /dev/null -O - | tar -xz + gettoken + ## 数据库导入 + cat ./zeus-iot-bin/bin/sql/zeus-iot.sql | sudo -u zabbix psql zabbix 1>/dev/null + + sed -i "s%\(zbxApiToken: \).*%\1$token%" ./zeus-iot-bin/webapp/webapp.yml + sed -i '19i export ZEUS_DB_PASSWORD=zeusiot' ./zeus-iot-bin/bin/startup.sh + ./zeus-iot-bin/bin/startup.sh + echo -e "\033[32m [ OK ] \033[0m" +} + ## InitSystem @@ -391,5 +429,8 @@ AddInstallRepo PGInstall ZbxInstall PHPInstall +WebInstall +taosinstall +natsinstall ZeusInstall # 安装结束 From ad52f7ade6a0f63fbfe90378829c8a92c0b79e85 Mon Sep 17 00:00:00 2001 From: nantian Date: Sun, 26 Sep 2021 21:09:52 +0800 Subject: [PATCH 314/763] [fix]: optimize log logic --- .../zeus/iot/server/transfer/core/sink/DataCarrierSink.java | 4 ---- .../zmops/zeus/iot/server/transfer/sender/SenderManager.java | 5 ++++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/DataCarrierSink.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/DataCarrierSink.java index 507b61c4..0b1769c2 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/DataCarrierSink.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/DataCarrierSink.java @@ -87,14 +87,10 @@ private Runnable flushCache() { while (!shutdown) { try { cache.forEach((s, packProxyMessage) -> { - Pair> result = packProxyMessage.fetchBatch(); if (result != null) { senderManager.sendBatch(jobInstanceId, bid, result.getKey(), result.getValue(), 0, dataTime); - - LOGGER.info("send bid {} with message size {}, the job id is {}, read file is {}" - + "dataTime is {}", bid, result.getRight().size(), jobInstanceId, sourceFile, dataTime); } }); TransferUtils.silenceSleepInMs(batchFlushInterval); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java index dd26891e..cd97187f 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java @@ -39,7 +39,7 @@ public SenderManager(JobProfile jobConf, String bid, String sourceFilePath) { /** * Send message to proxy by batch, use message cache. * - * @param bid - bid + * @param bid - bid 方便以后企业版 区分数据来源 * @param tid - tid * @param bodyList - body list * @param retry - retry time @@ -68,6 +68,9 @@ record = new History(); metric.sendSuccessNum.incr(bodyList.size()); taskPositionManager.updateFileSinkPosition(jobId, sourceFilePath, bodyList.size()); + LOGGER.info("send bid {} with message size {}, the job id is {},the tid is {}, read file is {}" + + "dataTime is {}", bid, bodyList.size(), jobId, tid, sourceFilePath, dataTime); + } catch (Exception exception) { LOGGER.error("Exception caught", exception); // retry time From 745466e755019a60eb55496427872393ae3115e6 Mon Sep 17 00:00:00 2001 From: nantian Date: Sun, 26 Sep 2021 21:19:36 +0800 Subject: [PATCH 315/763] [style]: optimize log style --- .../zmops/zeus/iot/server/transfer/sender/SenderManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java index cd97187f..8e201a31 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java @@ -68,7 +68,7 @@ record = new History(); metric.sendSuccessNum.incr(bodyList.size()); taskPositionManager.updateFileSinkPosition(jobId, sourceFilePath, bodyList.size()); - LOGGER.info("send bid {} with message size {}, the job id is {},the tid is {}, read file is {}" + LOGGER.info("send bid [{}] with message size [{}], the job id is [{}],the tid is [{}], read file is {}, " + "dataTime is {}", bid, bodyList.size(), jobId, tid, sourceFilePath, dataTime); } catch (Exception exception) { From 2e45f15818752a9ad0b171e3483a2b80fe6dcb3c Mon Sep 17 00:00:00 2001 From: nantian Date: Sun, 26 Sep 2021 21:40:32 +0800 Subject: [PATCH 316/763] [style]: optimize log style --- .../iot/server/transfer/sender/SenderManager.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java index 8e201a31..88d53965 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java @@ -1,7 +1,6 @@ package com.zmops.zeus.iot.server.transfer.sender; import com.alibaba.fastjson.JSON; -import com.google.gson.Gson; import com.zmops.zeus.iot.server.core.analysis.manual.history.History; import com.zmops.zeus.iot.server.core.analysis.manual.history.UIntHistory; import com.zmops.zeus.iot.server.core.analysis.record.Record; @@ -68,8 +67,16 @@ record = new History(); metric.sendSuccessNum.incr(bodyList.size()); taskPositionManager.updateFileSinkPosition(jobId, sourceFilePath, bodyList.size()); + String fileName; + if (!System.getProperty("os.name").toLowerCase().startsWith("win")) { + String[] i = sourceFilePath.split("/"); + fileName = i[i.length - 1]; + } else { + fileName = sourceFilePath; + } + LOGGER.info("send bid [{}] with message size [{}], the job id is [{}],the tid is [{}], read file is {}, " - + "dataTime is {}", bid, bodyList.size(), jobId, tid, sourceFilePath, dataTime); + + "dataTime is {}", bid, bodyList.size(), jobId, tid, fileName, dataTime); } catch (Exception exception) { LOGGER.error("Exception caught", exception); From 97b9095c513df9e91919d20d74a13d43be870fd7 Mon Sep 17 00:00:00 2001 From: nantian Date: Sun, 26 Sep 2021 22:34:09 +0800 Subject: [PATCH 317/763] [style]: rename zeus-alarm to zeus-message --- {zeus-alarm => zeus-message}/pom.xml | 2 +- .../main/java/com/zmops/iot/mediaType/AlarmCallback.java | 0 .../java/com/zmops/iot/mediaType/AlarmMessageFormatter.java | 0 .../main/java/com/zmops/iot/mediaType/WebhookCallback.java | 0 .../zmops/iot/mediaType/dingtalk/DingtalkHookCallback.java | 0 .../iot/mediaType/dingtalk/DingtalkSettingService.java | 0 .../com/zmops/iot/mediaType/dingtalk/DingtalkSettings.java | 0 .../com/zmops/iot/mediaType/feishu/FeishuHookCallback.java | 0 .../zmops/iot/mediaType/feishu/FeishuSettingService.java | 0 .../java/com/zmops/iot/mediaType/feishu/FeishuSettings.java | 0 .../com/zmops/iot/mediaType/wechat/WechatHookCallback.java | 0 .../zmops/iot/mediaType/wechat/WechatSettingService.java | 0 .../java/com/zmops/iot/mediaType/wechat/WechatSettings.java | 0 .../com/zmops/iot/mediaType/welink/WeLinkHookCallback.java | 0 .../zmops/iot/mediaType/welink/WeLinkSettingService.java | 0 .../java/com/zmops/iot/mediaType/welink/WeLinkSettings.java | 0 zeus-starter/pom.xml | 2 +- .../com/zmops/iot/config/security/WebSecurityConfig.java | 3 +-- zeus-webapp-bom/pom.xml | 2 +- zeus-webapp/pom.xml | 6 +----- 20 files changed, 5 insertions(+), 10 deletions(-) rename {zeus-alarm => zeus-message}/pom.xml (97%) rename {zeus-alarm => zeus-message}/src/main/java/com/zmops/iot/mediaType/AlarmCallback.java (100%) rename {zeus-alarm => zeus-message}/src/main/java/com/zmops/iot/mediaType/AlarmMessageFormatter.java (100%) rename {zeus-alarm => zeus-message}/src/main/java/com/zmops/iot/mediaType/WebhookCallback.java (100%) rename {zeus-alarm => zeus-message}/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkHookCallback.java (100%) rename {zeus-alarm => zeus-message}/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettingService.java (100%) rename {zeus-alarm => zeus-message}/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettings.java (100%) rename {zeus-alarm => zeus-message}/src/main/java/com/zmops/iot/mediaType/feishu/FeishuHookCallback.java (100%) rename {zeus-alarm => zeus-message}/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettingService.java (100%) rename {zeus-alarm => zeus-message}/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettings.java (100%) rename {zeus-alarm => zeus-message}/src/main/java/com/zmops/iot/mediaType/wechat/WechatHookCallback.java (100%) rename {zeus-alarm => zeus-message}/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettingService.java (100%) rename {zeus-alarm => zeus-message}/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettings.java (100%) rename {zeus-alarm => zeus-message}/src/main/java/com/zmops/iot/mediaType/welink/WeLinkHookCallback.java (100%) rename {zeus-alarm => zeus-message}/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettingService.java (100%) rename {zeus-alarm => zeus-message}/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettings.java (100%) diff --git a/zeus-alarm/pom.xml b/zeus-message/pom.xml similarity index 97% rename from zeus-alarm/pom.xml rename to zeus-message/pom.xml index cd2d207e..44e6bd07 100644 --- a/zeus-alarm/pom.xml +++ b/zeus-message/pom.xml @@ -10,7 +10,7 @@ 4.0.0 - zeus-alarm + zeus-message com.zmops diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/AlarmCallback.java b/zeus-message/src/main/java/com/zmops/iot/mediaType/AlarmCallback.java similarity index 100% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/AlarmCallback.java rename to zeus-message/src/main/java/com/zmops/iot/mediaType/AlarmCallback.java diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/AlarmMessageFormatter.java b/zeus-message/src/main/java/com/zmops/iot/mediaType/AlarmMessageFormatter.java similarity index 100% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/AlarmMessageFormatter.java rename to zeus-message/src/main/java/com/zmops/iot/mediaType/AlarmMessageFormatter.java diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/WebhookCallback.java b/zeus-message/src/main/java/com/zmops/iot/mediaType/WebhookCallback.java similarity index 100% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/WebhookCallback.java rename to zeus-message/src/main/java/com/zmops/iot/mediaType/WebhookCallback.java diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkHookCallback.java similarity index 100% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkHookCallback.java rename to zeus-message/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkHookCallback.java diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettingService.java b/zeus-message/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettingService.java similarity index 100% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettingService.java rename to zeus-message/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettingService.java diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettings.java b/zeus-message/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettings.java similarity index 100% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettings.java rename to zeus-message/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettings.java diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/mediaType/feishu/FeishuHookCallback.java similarity index 100% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuHookCallback.java rename to zeus-message/src/main/java/com/zmops/iot/mediaType/feishu/FeishuHookCallback.java diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettingService.java b/zeus-message/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettingService.java similarity index 100% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettingService.java rename to zeus-message/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettingService.java diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettings.java b/zeus-message/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettings.java similarity index 100% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettings.java rename to zeus-message/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettings.java diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/wechat/WechatHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/mediaType/wechat/WechatHookCallback.java similarity index 100% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/wechat/WechatHookCallback.java rename to zeus-message/src/main/java/com/zmops/iot/mediaType/wechat/WechatHookCallback.java diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettingService.java b/zeus-message/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettingService.java similarity index 100% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettingService.java rename to zeus-message/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettingService.java diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettings.java b/zeus-message/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettings.java similarity index 100% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettings.java rename to zeus-message/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettings.java diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/welink/WeLinkHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/mediaType/welink/WeLinkHookCallback.java similarity index 100% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/welink/WeLinkHookCallback.java rename to zeus-message/src/main/java/com/zmops/iot/mediaType/welink/WeLinkHookCallback.java diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettingService.java b/zeus-message/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettingService.java similarity index 100% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettingService.java rename to zeus-message/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettingService.java diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettings.java b/zeus-message/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettings.java similarity index 100% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettings.java rename to zeus-message/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettings.java diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index 374adceb..57aef2a6 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -47,7 +47,7 @@ com.zmops - zeus-alarm + zeus-message ${project.version} diff --git a/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java b/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java index 1b05f61e..7f077904 100644 --- a/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java +++ b/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java @@ -80,8 +80,7 @@ public void configure(WebSecurity web) throws Exception { // 静态资源放开过滤 .and().ignoring().antMatchers(HttpMethod.GET, "/static/**", - "/favicon.ico", - "/websocket/alarm/**" + "/favicon.ico" ); } diff --git a/zeus-webapp-bom/pom.xml b/zeus-webapp-bom/pom.xml index 980e2e88..890c2a5a 100644 --- a/zeus-webapp-bom/pom.xml +++ b/zeus-webapp-bom/pom.xml @@ -22,7 +22,7 @@ ../zeus-common - ../zeus-alarm + ../zeus-message ../zeus-core ../zeus-driver ../zeus-rest diff --git a/zeus-webapp/pom.xml b/zeus-webapp/pom.xml index 568d4561..c1beb5b1 100644 --- a/zeus-webapp/pom.xml +++ b/zeus-webapp/pom.xml @@ -24,7 +24,7 @@ com.zmops - zeus-alarm + zeus-message ${project.version} @@ -37,10 +37,6 @@ toolkit-async 1.0-beta - - org.springframework.boot - spring-boot-starter-websocket - commons-httpclient commons-httpclient From dde5dcbce24400303c881782187f36aaf7b2afae Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 27 Sep 2021 00:16:14 +0800 Subject: [PATCH 318/763] [feat]: use socket-io to send message --- zeus-message/pom.xml | 5 + .../com/zmops/iot/message/config/Event.java | 27 +++++ .../message/config/MessageServerConfig.java | 42 +++++++ .../iot/message/config/SocketIoConfig.java | 24 ++++ .../message/handler/MessageEventHandler.java | 113 ++++++++++++++++++ .../payload/BroadcastMessageRequest.java | 15 +++ .../message/payload/GroupMessageRequest.java | 24 ++++ .../iot/message/payload/JoinRequest.java | 19 +++ .../message/payload/SingleMessageRequest.java | 24 ++++ .../iot/message/server/SocketIoServer.java | 25 ++++ ...itional-spring-configuration-metadata.json | 14 +++ .../src/main/resources/application.yaml | 9 +- .../iot/web/alarm/service/AlarmService.java | 6 +- .../iot/web/alarm/service/MessageService.java | 7 +- .../zmops/iot/web/nats/NatsConnection.java | 8 -- .../iot/web/nats/NatsConnectionHolder.java | 20 ---- .../iot/web/nats/NatsConnectionImpl.java | 26 ---- .../web/nats/NatsConnectionInitializer.java | 25 ---- 18 files changed, 344 insertions(+), 89 deletions(-) create mode 100644 zeus-message/src/main/java/com/zmops/iot/message/config/Event.java create mode 100644 zeus-message/src/main/java/com/zmops/iot/message/config/MessageServerConfig.java create mode 100644 zeus-message/src/main/java/com/zmops/iot/message/config/SocketIoConfig.java create mode 100644 zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java create mode 100644 zeus-message/src/main/java/com/zmops/iot/message/payload/BroadcastMessageRequest.java create mode 100644 zeus-message/src/main/java/com/zmops/iot/message/payload/GroupMessageRequest.java create mode 100644 zeus-message/src/main/java/com/zmops/iot/message/payload/JoinRequest.java create mode 100644 zeus-message/src/main/java/com/zmops/iot/message/payload/SingleMessageRequest.java create mode 100644 zeus-message/src/main/java/com/zmops/iot/message/server/SocketIoServer.java create mode 100644 zeus-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnection.java delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionHolder.java delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionImpl.java delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionInitializer.java diff --git a/zeus-message/pom.xml b/zeus-message/pom.xml index 44e6bd07..373f7727 100644 --- a/zeus-message/pom.xml +++ b/zeus-message/pom.xml @@ -21,6 +21,11 @@ io.netty netty-codec-http + + com.corundumstudio.socketio + netty-socketio + 1.7.12 + com.zmops zeus-driver diff --git a/zeus-message/src/main/java/com/zmops/iot/message/config/Event.java b/zeus-message/src/main/java/com/zmops/iot/message/config/Event.java new file mode 100644 index 00000000..15aa7bfa --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/config/Event.java @@ -0,0 +1,27 @@ +package com.zmops.iot.message.config; + +/** + * @author nantian created at 2021/9/26 23:15 + */ +public interface Event { + + /** + * 聊天事件 + */ + String CHAT = "chat"; + + /** + * 广播消息 + */ + String BROADCAST = "broadcast"; + + /** + * 群聊 + */ + String GROUP = "group"; + + /** + * 加入群聊 + */ + String JOIN = "join"; +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/config/MessageServerConfig.java b/zeus-message/src/main/java/com/zmops/iot/message/config/MessageServerConfig.java new file mode 100644 index 00000000..806426d9 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/config/MessageServerConfig.java @@ -0,0 +1,42 @@ +package com.zmops.iot.message.config; + +import cn.hutool.core.util.StrUtil; +import com.corundumstudio.socketio.SocketIOServer; +import com.corundumstudio.socketio.annotation.SpringAnnotationScanner; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author nantian created at 2021/9/26 22:39 + */ + +@Configuration +@EnableConfigurationProperties({SocketIoConfig.class}) +public class MessageServerConfig { + + @Bean + public SocketIOServer server(SocketIoConfig socketIoConfig) { + com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration(); + + config.setHostname(socketIoConfig.getHost()); + config.setPort(socketIoConfig.getPort()); + + config.setAuthorizationListener(data -> { + String token = data.getSingleUrlParam("token"); + return StrUtil.isNotBlank(token); + }); + + return new SocketIOServer(config); + } + + + /** + * Spring 扫描自定义注解 + */ + @Bean + public SpringAnnotationScanner springAnnotationScanner(SocketIOServer server) { + return new SpringAnnotationScanner(server); + } + +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/config/SocketIoConfig.java b/zeus-message/src/main/java/com/zmops/iot/message/config/SocketIoConfig.java new file mode 100644 index 00000000..8d3d2d9f --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/config/SocketIoConfig.java @@ -0,0 +1,24 @@ +package com.zmops.iot.message.config; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * @author nantian created at 2021/9/26 22:47 + */ +@Getter +@Setter +@ConfigurationProperties(prefix = "socketio.server") +public class SocketIoConfig { + + /** + * 端口号 + */ + private Integer port; + + /** + * host + */ + private String host; +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java b/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java new file mode 100644 index 00000000..1cc8721a --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java @@ -0,0 +1,113 @@ +package com.zmops.iot.message.handler; + +import com.corundumstudio.socketio.AckRequest; +import com.corundumstudio.socketio.SocketIOClient; +import com.corundumstudio.socketio.SocketIOServer; +import com.corundumstudio.socketio.annotation.OnConnect; +import com.corundumstudio.socketio.annotation.OnDisconnect; +import com.corundumstudio.socketio.annotation.OnEvent; + +import com.zmops.iot.message.config.Event; +import com.zmops.iot.message.payload.BroadcastMessageRequest; +import com.zmops.iot.message.payload.GroupMessageRequest; +import com.zmops.iot.message.payload.JoinRequest; +import com.zmops.iot.message.payload.SingleMessageRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Collection; + +/** + * @author nantian created at 2021/9/26 23:13 + */ + +@Slf4j +@Component +public class MessageEventHandler { + + @Autowired + private SocketIOServer server; + + /** + * 添加connect事件,当客户端发起连接时调用 + * + * @param client 客户端对象 + */ + @OnConnect + public void onConnect(SocketIOClient client) { + if (client != null) { + + String token = client.getHandshakeData().getSingleUrlParam("token"); + + // 模拟用户id 和token一致 + String userId = client.getHandshakeData().getSingleUrlParam("token"); + + } else { + log.error("客户端为空"); + } + } + + /** + * 添加disconnect事件,客户端断开连接时调用,刷新客户端信息 + * + * @param client 客户端对象 + */ + @OnDisconnect + public void onDisconnect(SocketIOClient client) { + if (client != null) { + String token = client.getHandshakeData().getSingleUrlParam("token"); + + // 模拟用户id 和token一致 + String userId = client.getHandshakeData().getSingleUrlParam("token"); + + client.disconnect(); + } else { + log.error("客户端为空"); + } + } + + /** + * 加入群聊 + * + * @param client 客户端 + * @param request 请求 + * @param data 群聊 + */ + @OnEvent(value = Event.JOIN) + public void onJoinEvent(SocketIOClient client, AckRequest request, JoinRequest data) { + + log.info("用户:{} 已加入群聊:{}", data.getUserId(), data.getGroupId()); + client.joinRoom(data.getGroupId()); + + server.getRoomOperations(data.getGroupId()).sendEvent(Event.JOIN, data); + } + + + @OnEvent(value = Event.CHAT) + public void onChatEvent(SocketIOClient client, AckRequest request, SingleMessageRequest data) { + + } + + @OnEvent(value = Event.GROUP) + public void onGroupEvent(SocketIOClient client, AckRequest request, GroupMessageRequest data) { + Collection clients = server.getRoomOperations(data.getGroupId()).getClients(); + } + + + /** + * 广播 + */ + public void sendToBroadcast(BroadcastMessageRequest message) { + log.info("系统紧急广播一条通知:{}", message.getMessage()); + + + } + + /** + * 群聊 + */ + public void sendToGroup(GroupMessageRequest message) { + server.getRoomOperations(message.getGroupId()).sendEvent(Event.GROUP, message); + } +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/payload/BroadcastMessageRequest.java b/zeus-message/src/main/java/com/zmops/iot/message/payload/BroadcastMessageRequest.java new file mode 100644 index 00000000..79427994 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/payload/BroadcastMessageRequest.java @@ -0,0 +1,15 @@ +package com.zmops.iot.message.payload; + +import lombok.Data; + +/** + * @author nantian created at 2021/9/26 23:16 + */ +@Data +public class BroadcastMessageRequest { + + /** + * 消息内容 + */ + private String message; +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/payload/GroupMessageRequest.java b/zeus-message/src/main/java/com/zmops/iot/message/payload/GroupMessageRequest.java new file mode 100644 index 00000000..16d0398e --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/payload/GroupMessageRequest.java @@ -0,0 +1,24 @@ +package com.zmops.iot.message.payload; + +import lombok.Data; + +/** + * @author nantian created at 2021/9/26 23:16 + */ +@Data +public class GroupMessageRequest { + /** + * 消息发送方用户id + */ + private String fromUid; + + /** + * 群组id + */ + private String groupId; + + /** + * 消息内容 + */ + private String message; +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/payload/JoinRequest.java b/zeus-message/src/main/java/com/zmops/iot/message/payload/JoinRequest.java new file mode 100644 index 00000000..56b4390f --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/payload/JoinRequest.java @@ -0,0 +1,19 @@ +package com.zmops.iot.message.payload; + +import lombok.Data; + +/** + * @author nantian created at 2021/9/26 23:16 + */ +@Data +public class JoinRequest { + /** + * 用户id + */ + private String userId; + + /** + * 群名称 + */ + private String groupId; +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/payload/SingleMessageRequest.java b/zeus-message/src/main/java/com/zmops/iot/message/payload/SingleMessageRequest.java new file mode 100644 index 00000000..34706c34 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/payload/SingleMessageRequest.java @@ -0,0 +1,24 @@ +package com.zmops.iot.message.payload; + +import lombok.Data; + +/** + * @author nantian created at 2021/9/26 23:16 + */ +@Data +public class SingleMessageRequest { + /** + * 消息发送方用户id + */ + private String fromUid; + + /** + * 消息接收方用户id + */ + private String toUid; + + /** + * 消息内容 + */ + private String message; +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/server/SocketIoServer.java b/zeus-message/src/main/java/com/zmops/iot/message/server/SocketIoServer.java new file mode 100644 index 00000000..2d1973c2 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/server/SocketIoServer.java @@ -0,0 +1,25 @@ +package com.zmops.iot.message.server; + +import com.corundumstudio.socketio.SocketIOServer; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +/** + * @author nantian created at 2021/9/26 23:21 + */ + +@Slf4j +@Component +public class SocketIoServer implements CommandLineRunner { + + @Autowired + private SocketIOServer server; + + @Override + public void run(String... args) throws Exception { + server.start(); + } +} + diff --git a/zeus-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/zeus-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json new file mode 100644 index 00000000..0e2701a7 --- /dev/null +++ b/zeus-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -0,0 +1,14 @@ +{ + "properties": [ + { + "name": "socketio.server.host", + "type": "java.lang.String", + "description": "socketio host." + }, + { + "name": "socketio.server.port", + "type": "java.lang.String", + "description": "socketio port." + } + ] +} \ No newline at end of file diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index 8ac5d3d1..e1b8dddb 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -48,10 +48,13 @@ forest: zbxApiUrl: http://${ZEUS_ZABBIX_HOST:127.0.0.1}:${ZEUS_ZABBIX_PORT:80}/zabbix/api_jsonrpc.php zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:80} - zbxApiToken: cf22b3b977bc47d0460e144ff7a817b584eb3f2d5e23dcf640a014c07d087adb + zbxApiToken: 897e588c32f780f7134457e409ff37e84ea966ee20712dfacd22c8a968ce94d6 + taosUrl: http://${ZEUS_TAOS_HOST:127.0.0.1}:${ZEUS_TAOS_REST_PORT:6041}/rest/sql/${ZEUS_TAOS_DB:zeus_data} taosUser: root taosPwd: taosdata -nats: - url: nats://${NATS_HOST:127.0.0.1}:${NATS_PORT:4222} \ No newline at end of file +socketio: + server: + port: 9080 + host: 0.0.0.0 \ No newline at end of file diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index e4dddbcd..cb2c8931 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -110,7 +110,7 @@ public List getAlarmList(AlarmParam alarmParam) { } List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Integer::parseInt).collect(Collectors.toList()); List ruleList = DB.findDto(ProductEventRuleDto.class, "select d.event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id," + - "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") + "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") .setParameter("zbxIds", triggerIds).findList(); Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); @@ -151,9 +151,9 @@ public List getEventList(AlarmParam alarmParam) { if (ToolUtil.isEmpty(problemList)) { return Collections.emptyList(); } - List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Integer::parseInt).collect(Collectors.toList()); + List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Integer::parseInt).collect(Collectors.toList()); List ruleList = DB.findDto(ProductEventRuleDto.class, "select event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id," + - "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") + "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") .setParameter("zbxIds", triggerIds).findList(); Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java index 542df924..c3389f26 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java @@ -11,7 +11,6 @@ import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.alarm.dto.param.MessageParam; -import com.zmops.iot.web.nats.NatsConnectionHolder; import io.ebean.DB; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @@ -68,9 +67,9 @@ public void push(MessageBody body) { } body.addBody("classify", sys); - tos.forEach(to -> { - NatsConnectionHolder.INSTANCE.getConnection().publish(to + "", JSON.toJSONString(body)); - }); +// tos.forEach(to -> { +// NatsConnectionHolder.INSTANCE.getConnection().publish(to + "", JSON.toJSONString(body)); +// }); } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnection.java b/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnection.java deleted file mode 100644 index bfd67819..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnection.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.zmops.iot.web.nats; - -/** - * @author yefei - **/ -public interface NatsConnection { - void publish(String topic, String messageBody); -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionHolder.java b/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionHolder.java deleted file mode 100644 index c628ae5f..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionHolder.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.zmops.iot.web.nats; - -/** - * @author yefei - **/ -public enum NatsConnectionHolder { - - INSTANCE; - - private NatsConnection connection; - - public NatsConnection getConnection() { - return connection; - } - - public void setConnection(NatsConnection connection) { - this.connection = connection; - } - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionImpl.java b/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionImpl.java deleted file mode 100644 index 14678e22..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionImpl.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.zmops.iot.web.nats; - -import io.nats.client.Connection; -import lombok.extern.slf4j.Slf4j; -import org.springframework.util.Assert; - -import java.nio.charset.StandardCharsets; - -/** - * @author yefei - **/ -@Slf4j -public class NatsConnectionImpl implements NatsConnection { - - private Connection connection; - - public NatsConnectionImpl(Connection connection) { - Assert.state(connection != null, "connection could not be null"); - this.connection = connection; - } - - @Override - public void publish(String topic, String messageBody) { - connection.publish(topic, messageBody.getBytes(StandardCharsets.UTF_8)); - } -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionInitializer.java b/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionInitializer.java deleted file mode 100644 index 9eb41040..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/nats/NatsConnectionInitializer.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.zmops.iot.web.nats; - -import io.nats.client.Connection; -import io.nats.client.Nats; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -/** - * * @author yefei - *

- * 初始化 连接 - **/ -@Component -public class NatsConnectionInitializer implements InitializingBean { - @Value("${nats.url}") - private String url; - - - @Override - public void afterPropertiesSet() throws Exception { - Connection nc = Nats.connect(url); - NatsConnectionHolder.INSTANCE.setConnection(new NatsConnectionImpl(nc)); - } -} From f5098ef200bbac6034dd412d0878ffbc043f8ae4 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 27 Sep 2021 01:09:51 +0800 Subject: [PATCH 319/763] [style]: change package name mediaType to media --- .../{mediaType => media}/AlarmCallback.java | 2 +- .../AlarmMessageFormatter.java | 2 +- .../{mediaType => media}/WebhookCallback.java | 2 +- .../dingtalk/DingtalkHookCallback.java | 4 +- .../dingtalk/DingtalkSettingService.java | 2 +- .../dingtalk/DingtalkSettings.java | 2 +- .../feishu/FeishuHookCallback.java | 4 +- .../feishu/FeishuSettingService.java | 2 +- .../feishu/FeishuSettings.java | 2 +- .../wechat/WechatHookCallback.java | 4 +- .../wechat/WechatSettingService.java | 2 +- .../wechat/WechatSettings.java | 2 +- .../welink/WeLinkHookCallback.java | 4 +- .../welink/WeLinkSettingService.java | 2 +- .../welink/WeLinkSettings.java | 2 +- .../iot/message/config/UserClientMap.java | 35 +++++++++++ .../controller/SocketIoController.java | 33 +++++++++++ .../message/handler/MessageEventHandler.java | 59 +++++++------------ zeus-starter/src/main/assembly/webapp.yml | 6 +- .../src/main/resources/application.yaml | 2 +- .../iot/web/alarm/service/AlarmService.java | 2 +- 21 files changed, 114 insertions(+), 61 deletions(-) rename zeus-message/src/main/java/com/zmops/iot/{mediaType => media}/AlarmCallback.java (89%) rename zeus-message/src/main/java/com/zmops/iot/{mediaType => media}/AlarmMessageFormatter.java (98%) rename zeus-message/src/main/java/com/zmops/iot/{mediaType => media}/WebhookCallback.java (99%) rename zeus-message/src/main/java/com/zmops/iot/{mediaType => media}/dingtalk/DingtalkHookCallback.java (98%) rename zeus-message/src/main/java/com/zmops/iot/{mediaType => media}/dingtalk/DingtalkSettingService.java (96%) rename zeus-message/src/main/java/com/zmops/iot/{mediaType => media}/dingtalk/DingtalkSettings.java (91%) rename zeus-message/src/main/java/com/zmops/iot/{mediaType => media}/feishu/FeishuHookCallback.java (98%) rename zeus-message/src/main/java/com/zmops/iot/{mediaType => media}/feishu/FeishuSettingService.java (96%) rename zeus-message/src/main/java/com/zmops/iot/{mediaType => media}/feishu/FeishuSettings.java (96%) rename zeus-message/src/main/java/com/zmops/iot/{mediaType => media}/wechat/WechatHookCallback.java (98%) rename zeus-message/src/main/java/com/zmops/iot/{mediaType => media}/wechat/WechatSettingService.java (96%) rename zeus-message/src/main/java/com/zmops/iot/{mediaType => media}/wechat/WechatSettings.java (96%) rename zeus-message/src/main/java/com/zmops/iot/{mediaType => media}/welink/WeLinkHookCallback.java (98%) rename zeus-message/src/main/java/com/zmops/iot/{mediaType => media}/welink/WeLinkSettingService.java (97%) rename zeus-message/src/main/java/com/zmops/iot/{mediaType => media}/welink/WeLinkSettings.java (97%) create mode 100644 zeus-message/src/main/java/com/zmops/iot/message/config/UserClientMap.java create mode 100644 zeus-message/src/main/java/com/zmops/iot/message/controller/SocketIoController.java diff --git a/zeus-message/src/main/java/com/zmops/iot/mediaType/AlarmCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/AlarmCallback.java similarity index 89% rename from zeus-message/src/main/java/com/zmops/iot/mediaType/AlarmCallback.java rename to zeus-message/src/main/java/com/zmops/iot/media/AlarmCallback.java index 3b963355..8e3ed118 100644 --- a/zeus-message/src/main/java/com/zmops/iot/mediaType/AlarmCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/AlarmCallback.java @@ -1,5 +1,5 @@ -package com.zmops.iot.mediaType; +package com.zmops.iot.media; import com.zmops.iot.domain.alarm.AlarmMessage; diff --git a/zeus-message/src/main/java/com/zmops/iot/mediaType/AlarmMessageFormatter.java b/zeus-message/src/main/java/com/zmops/iot/media/AlarmMessageFormatter.java similarity index 98% rename from zeus-message/src/main/java/com/zmops/iot/mediaType/AlarmMessageFormatter.java rename to zeus-message/src/main/java/com/zmops/iot/media/AlarmMessageFormatter.java index 899775dc..831177ea 100644 --- a/zeus-message/src/main/java/com/zmops/iot/mediaType/AlarmMessageFormatter.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/AlarmMessageFormatter.java @@ -16,7 +16,7 @@ * */ -package com.zmops.iot.mediaType; +package com.zmops.iot.media; import java.util.ArrayList; diff --git a/zeus-message/src/main/java/com/zmops/iot/mediaType/WebhookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/WebhookCallback.java similarity index 99% rename from zeus-message/src/main/java/com/zmops/iot/mediaType/WebhookCallback.java rename to zeus-message/src/main/java/com/zmops/iot/media/WebhookCallback.java index c4812b03..e58ab2f0 100644 --- a/zeus-message/src/main/java/com/zmops/iot/mediaType/WebhookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/WebhookCallback.java @@ -16,7 +16,7 @@ * */ -package com.zmops.iot.mediaType; +package com.zmops.iot.media; import com.zmops.iot.domain.alarm.AlarmMessage; import lombok.extern.slf4j.Slf4j; diff --git a/zeus-message/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkHookCallback.java similarity index 98% rename from zeus-message/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkHookCallback.java rename to zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkHookCallback.java index 3355bc0a..0447b082 100644 --- a/zeus-message/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkHookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkHookCallback.java @@ -16,10 +16,10 @@ * */ -package com.zmops.iot.mediaType.dingtalk; +package com.zmops.iot.media.dingtalk; import com.zmops.iot.domain.alarm.AlarmMessage; -import com.zmops.iot.mediaType.AlarmCallback; +import com.zmops.iot.media.AlarmCallback; import io.netty.handler.codec.http.HttpHeaderValues; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; diff --git a/zeus-message/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettingService.java b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettingService.java similarity index 96% rename from zeus-message/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettingService.java rename to zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettingService.java index 800fe07c..18214ff5 100644 --- a/zeus-message/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettingService.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettingService.java @@ -1,4 +1,4 @@ -package com.zmops.iot.mediaType.dingtalk; +package com.zmops.iot.media.dingtalk; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.alarm.MediaTypeSetting; diff --git a/zeus-message/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettings.java b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettings.java similarity index 91% rename from zeus-message/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettings.java rename to zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettings.java index 8b7a48f2..eb0328f4 100644 --- a/zeus-message/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettings.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettings.java @@ -1,6 +1,6 @@ -package com.zmops.iot.mediaType.dingtalk; +package com.zmops.iot.media.dingtalk; import lombok.*; diff --git a/zeus-message/src/main/java/com/zmops/iot/mediaType/feishu/FeishuHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuHookCallback.java similarity index 98% rename from zeus-message/src/main/java/com/zmops/iot/mediaType/feishu/FeishuHookCallback.java rename to zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuHookCallback.java index 342c80de..403f7388 100644 --- a/zeus-message/src/main/java/com/zmops/iot/mediaType/feishu/FeishuHookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuHookCallback.java @@ -16,12 +16,12 @@ * */ -package com.zmops.iot.mediaType.feishu; +package com.zmops.iot.media.feishu; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.alarm.AlarmMessage; -import com.zmops.iot.mediaType.AlarmCallback; +import com.zmops.iot.media.AlarmCallback; import com.zmops.iot.util.ToolUtil; import io.netty.handler.codec.http.HttpHeaderValues; import lombok.extern.slf4j.Slf4j; diff --git a/zeus-message/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettingService.java b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettingService.java similarity index 96% rename from zeus-message/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettingService.java rename to zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettingService.java index 97953434..f132a08c 100644 --- a/zeus-message/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettingService.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettingService.java @@ -1,4 +1,4 @@ -package com.zmops.iot.mediaType.feishu; +package com.zmops.iot.media.feishu; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.alarm.MediaTypeSetting; diff --git a/zeus-message/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettings.java b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettings.java similarity index 96% rename from zeus-message/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettings.java rename to zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettings.java index 39a7c670..e819a128 100644 --- a/zeus-message/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettings.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettings.java @@ -16,7 +16,7 @@ * */ -package com.zmops.iot.mediaType.feishu; +package com.zmops.iot.media.feishu; import lombok.*; diff --git a/zeus-message/src/main/java/com/zmops/iot/mediaType/wechat/WechatHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatHookCallback.java similarity index 98% rename from zeus-message/src/main/java/com/zmops/iot/mediaType/wechat/WechatHookCallback.java rename to zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatHookCallback.java index 7f1c7343..afc623b5 100644 --- a/zeus-message/src/main/java/com/zmops/iot/mediaType/wechat/WechatHookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatHookCallback.java @@ -16,10 +16,10 @@ * */ -package com.zmops.iot.mediaType.wechat; +package com.zmops.iot.media.wechat; import com.zmops.iot.domain.alarm.AlarmMessage; -import com.zmops.iot.mediaType.AlarmCallback; +import com.zmops.iot.media.AlarmCallback; import io.netty.handler.codec.http.HttpHeaderValues; import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpHeaders; diff --git a/zeus-message/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettingService.java b/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatSettingService.java similarity index 96% rename from zeus-message/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettingService.java rename to zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatSettingService.java index 3eeb95b2..623a407e 100644 --- a/zeus-message/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettingService.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatSettingService.java @@ -1,4 +1,4 @@ -package com.zmops.iot.mediaType.wechat; +package com.zmops.iot.media.wechat; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.alarm.MediaTypeSetting; diff --git a/zeus-message/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettings.java b/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatSettings.java similarity index 96% rename from zeus-message/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettings.java rename to zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatSettings.java index 7f5f278c..0af12b56 100644 --- a/zeus-message/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettings.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatSettings.java @@ -16,7 +16,7 @@ * */ -package com.zmops.iot.mediaType.wechat; +package com.zmops.iot.media.wechat; import lombok.*; diff --git a/zeus-message/src/main/java/com/zmops/iot/mediaType/welink/WeLinkHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkHookCallback.java similarity index 98% rename from zeus-message/src/main/java/com/zmops/iot/mediaType/welink/WeLinkHookCallback.java rename to zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkHookCallback.java index 2b2a2743..56394803 100644 --- a/zeus-message/src/main/java/com/zmops/iot/mediaType/welink/WeLinkHookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkHookCallback.java @@ -16,13 +16,13 @@ * */ -package com.zmops.iot.mediaType.welink; +package com.zmops.iot.media.welink; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.alarm.AlarmMessage; -import com.zmops.iot.mediaType.AlarmCallback; +import com.zmops.iot.media.AlarmCallback; import io.netty.handler.codec.http.HttpHeaderValues; import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpHeaders; diff --git a/zeus-message/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettingService.java b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkSettingService.java similarity index 97% rename from zeus-message/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettingService.java rename to zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkSettingService.java index f9508843..0fda9ae5 100644 --- a/zeus-message/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettingService.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkSettingService.java @@ -1,4 +1,4 @@ -package com.zmops.iot.mediaType.welink; +package com.zmops.iot.media.welink; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.alarm.MediaTypeSetting; diff --git a/zeus-message/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettings.java b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkSettings.java similarity index 97% rename from zeus-message/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettings.java rename to zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkSettings.java index 272b757e..cabd67cd 100644 --- a/zeus-message/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettings.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkSettings.java @@ -1,5 +1,5 @@ -package com.zmops.iot.mediaType.welink; +package com.zmops.iot.media.welink; import lombok.*; diff --git a/zeus-message/src/main/java/com/zmops/iot/message/config/UserClientMap.java b/zeus-message/src/main/java/com/zmops/iot/message/config/UserClientMap.java new file mode 100644 index 00000000..a74f8380 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/config/UserClientMap.java @@ -0,0 +1,35 @@ +package com.zmops.iot.message.config; + +import cn.hutool.core.collection.CollUtil; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +@Component +public class UserClientMap { + + public static final ConcurrentHashMap DB = new ConcurrentHashMap<>(); + + public List findAll() { + return CollUtil.newArrayList(DB.values()); + } + + + public Optional findByUserId(String userId) { + return Optional.ofNullable(DB.get(userId)); + } + + + public void save(String userId, UUID sessionId) { + DB.put(userId, sessionId); + } + + + public void deleteByUserId(String userId) { + DB.remove(userId); + } + +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/controller/SocketIoController.java b/zeus-message/src/main/java/com/zmops/iot/message/controller/SocketIoController.java new file mode 100644 index 00000000..0586c2bf --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/controller/SocketIoController.java @@ -0,0 +1,33 @@ +package com.zmops.iot.message.controller; + +import com.zmops.iot.message.handler.MessageEventHandler; +import com.zmops.iot.message.payload.BroadcastMessageRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author nantian created at 2021/9/27 0:16 + */ + +@Slf4j +@RestController +@RequestMapping("/send") +public class SocketIoController { + + @Autowired + private MessageEventHandler messageHandler; + + /** + * just for test + * + * @param message + */ + @PostMapping("/broadcast") + public void broadcast(@RequestBody BroadcastMessageRequest message) { + messageHandler.sendToBroadcast(message); + } +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java b/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java index 1cc8721a..defd17eb 100644 --- a/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java +++ b/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java @@ -8,6 +8,7 @@ import com.corundumstudio.socketio.annotation.OnEvent; import com.zmops.iot.message.config.Event; +import com.zmops.iot.message.config.UserClientMap; import com.zmops.iot.message.payload.BroadcastMessageRequest; import com.zmops.iot.message.payload.GroupMessageRequest; import com.zmops.iot.message.payload.JoinRequest; @@ -17,6 +18,7 @@ import org.springframework.stereotype.Component; import java.util.Collection; +import java.util.UUID; /** * @author nantian created at 2021/9/26 23:13 @@ -29,55 +31,38 @@ public class MessageEventHandler { @Autowired private SocketIOServer server; - /** - * 添加connect事件,当客户端发起连接时调用 - * - * @param client 客户端对象 - */ + @Autowired + private UserClientMap userClient; + + @OnConnect public void onConnect(SocketIOClient client) { if (client != null) { - String token = client.getHandshakeData().getSingleUrlParam("token"); - - // 模拟用户id 和token一致 + String token = client.getHandshakeData().getSingleUrlParam("token"); String userId = client.getHandshakeData().getSingleUrlParam("token"); - } else { - log.error("客户端为空"); + UUID sessionId = client.getSessionId(); + + userClient.save(userId, sessionId); + + log.info("socketio connect successfully,【token】= {},【sessionId】= {}", token, sessionId); } } - /** - * 添加disconnect事件,客户端断开连接时调用,刷新客户端信息 - * - * @param client 客户端对象 - */ @OnDisconnect public void onDisconnect(SocketIOClient client) { if (client != null) { - String token = client.getHandshakeData().getSingleUrlParam("token"); - - // 模拟用户id 和token一致 String userId = client.getHandshakeData().getSingleUrlParam("token"); - + userClient.deleteByUserId(userId); client.disconnect(); - } else { - log.error("客户端为空"); } } - /** - * 加入群聊 - * - * @param client 客户端 - * @param request 请求 - * @param data 群聊 - */ @OnEvent(value = Event.JOIN) public void onJoinEvent(SocketIOClient client, AckRequest request, JoinRequest data) { - log.info("用户:{} 已加入群聊:{}", data.getUserId(), data.getGroupId()); + log.info("user:{} has join group chat:{}", data.getUserId(), data.getGroupId()); client.joinRoom(data.getGroupId()); server.getRoomOperations(data.getGroupId()).sendEvent(Event.JOIN, data); @@ -86,7 +71,7 @@ public void onJoinEvent(SocketIOClient client, AckRequest request, JoinRequest d @OnEvent(value = Event.CHAT) public void onChatEvent(SocketIOClient client, AckRequest request, SingleMessageRequest data) { - + System.out.println(data.getMessage()); } @OnEvent(value = Event.GROUP) @@ -95,18 +80,16 @@ public void onGroupEvent(SocketIOClient client, AckRequest request, GroupMessage } - /** - * 广播 - */ public void sendToBroadcast(BroadcastMessageRequest message) { - log.info("系统紧急广播一条通知:{}", message.getMessage()); - + for (UUID clientId : userClient.findAll()) { + if (server.getClient(clientId) == null) { + continue; + } + server.getClient(clientId).sendEvent(Event.BROADCAST, message); + } } - /** - * 群聊 - */ public void sendToGroup(GroupMessageRequest message) { server.getRoomOperations(message.getGroupId()).sendEvent(Event.GROUP, message); } diff --git a/zeus-starter/src/main/assembly/webapp.yml b/zeus-starter/src/main/assembly/webapp.yml index e0135611..c5f38c9a 100644 --- a/zeus-starter/src/main/assembly/webapp.yml +++ b/zeus-starter/src/main/assembly/webapp.yml @@ -53,5 +53,7 @@ forest: taosUser: root taosPwd: taosdata -nats: - url: nats://${NATS_HOST:127.0.0.1}:${NATS_PORT:4222} \ No newline at end of file +socketio: + server: + port: 9080 + host: 0.0.0.0 \ No newline at end of file diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index e1b8dddb..f8ffe17a 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -41,7 +41,7 @@ spring: template-loader-path: classpath:/public/ forest: - log-enabled: true + log-enabled: false timeout: 5000 variables: ## Zabbix API IP And ServerIp and ServerPort diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index cb2c8931..c274de76 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -6,7 +6,7 @@ import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.query.QProductEvent; -import com.zmops.iot.mediaType.AlarmCallback; +import com.zmops.iot.media.AlarmCallback; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.alarm.dto.AlarmDto; import com.zmops.iot.web.alarm.dto.param.AlarmParam; From add4965bd909cbe66ee44d5ccbf3d2d44c1453bd Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 27 Sep 2021 09:55:29 +0800 Subject: [PATCH 320/763] [fix]:fix bug --- .../com/zmops/iot/web/device/service/DeviceGroupService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java index 81d16846..655ab279 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java @@ -110,7 +110,6 @@ public DeviceGroup createDeviceGroup(DeviceGroupDto deviceGroup) { JSONArray grpids = result.getJSONArray("groupids"); newDeviceGroup.setZbxId(grpids.get(0).toString()); DB.save(newDeviceGroup); - return newDeviceGroup; } From 7c8e2142ebe83709d6ad90cb43c3cb9636719b5a Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 27 Sep 2021 11:02:55 +0800 Subject: [PATCH 321/763] [feat]: add sql file to package --- zeus-iot-dist/src/main/assembly/binary.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/zeus-iot-dist/src/main/assembly/binary.xml b/zeus-iot-dist/src/main/assembly/binary.xml index 5fc94844..70c7e121 100644 --- a/zeus-iot-dist/src/main/assembly/binary.xml +++ b/zeus-iot-dist/src/main/assembly/binary.xml @@ -31,6 +31,7 @@ *.sh *.bat + **/*.sql 0755 From 505fe23ae8dcbb1b67521e9dc062b5e5124fd843 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 27 Sep 2021 12:22:03 +0800 Subject: [PATCH 322/763] [feat]: optimize tdengine resetful execute sql --- .../server-tdengine-plugin/pom.xml | 2 +- .../TaosJsonBodyBuildInterceptor.java | 77 ------------------- .../zeus/driver/service/TDEngineRest.java | 11 +-- .../analyse/controller/LatestController.java | 11 +++ 4 files changed, 15 insertions(+), 86 deletions(-) delete mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/TaosJsonBodyBuildInterceptor.java diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml index c0eff4b9..d3e8e42a 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml @@ -20,7 +20,7 @@ com.taosdata.jdbc taos-jdbcdriver - 2.0.31 + 2.0.32 com.zmops diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/TaosJsonBodyBuildInterceptor.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/TaosJsonBodyBuildInterceptor.java deleted file mode 100644 index 94a94ab9..00000000 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/TaosJsonBodyBuildInterceptor.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.zmops.zeus.driver.inteceptor; - -import com.alibaba.fastjson.JSON; -import com.dtflys.forest.http.ForestRequest; -import com.dtflys.forest.http.ForestResponse; -import com.dtflys.forest.interceptor.Interceptor; -import com.dtflys.forest.reflection.ForestMethod; -import com.zmops.iot.core.auth.context.LoginContextHolder; -import com.zmops.zeus.driver.annotation.JsonPath; -import com.zmops.zeus.driver.annotation.ParamName; -import com.zmops.zeus.driver.parser.JsonParseUtil; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang.StringEscapeUtils; -import org.apache.commons.lang.StringUtils; - -import java.lang.annotation.Annotation; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - -/** - * Created by nantian on 2021-03-12 23:00 - * - * @version 1.0 拦截器 基于 JSON 文件构建 JSON String 参数 - */ -@Slf4j -public class TaosJsonBodyBuildInterceptor implements Interceptor { - - private static final String NO_AUTH_TAG = "authTag"; - - /** - * 方法调用之前获取 JSON path - */ - @Override - public void onInvokeMethod(ForestRequest request, ForestMethod method, Object[] args) { - Map paramMap = new HashMap<>(); - - if (null != args && args.length > 0) { - // 优先 Map 的处理 - if (args[0] instanceof Map) { - paramMap.putAll((Map) args[0]); - } else { - Annotation[][] paramAnnos = method.getMethod().getParameterAnnotations(); - for (int i = 0; i < args.length; i++) { - if (paramAnnos[i].length > 0 && paramAnnos[i][0] instanceof ParamName) { - ParamName paramAnno = (ParamName) paramAnnos[i][0]; - paramMap.put(paramAnno.value(), args[i]); - } - } - } - } - - JsonPath jsonPath = method.getMethod().getAnnotation(JsonPath.class); - if (null != jsonPath && StringUtils.isNotBlank(jsonPath.value())) { - String body = Objects.requireNonNull(JsonParseUtil.parse(jsonPath.value() + ".ftl", paramMap)); - String sendBody = StringEscapeUtils.unescapeJava(body); - log.debug("\n" + sendBody + "\n"); - request.replaceBody(sendBody); - request.setContentType("application/json"); - } - } - - /** - * Zabbix 接口异常返回异常信息捕捉 - */ - @Override - public void onSuccess(String data, ForestRequest request, ForestResponse response) { -// TaosResponseData responseData = JSON.parseObject(data, TaosResponseData.class); - -// if (null != responseData.getError()) { -// log.error(response.getContent()); -// throw new ZbxApiException(responseData.getError().getCode(), responseData.getError().getData()); -// } - response.setResult(data); - Interceptor.super.onSuccess(data, request, response); - } -} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java index 6ad96b4f..c5c7286a 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java @@ -3,27 +3,22 @@ import com.dtflys.forest.annotation.BaseRequest; import com.dtflys.forest.annotation.Post; import com.dtflys.forest.extensions.BasicAuth; -import com.zmops.zeus.driver.annotation.JsonPath; -import com.zmops.zeus.driver.annotation.ParamName; -import com.zmops.zeus.driver.inteceptor.TaosJsonBodyBuildInterceptor; /** * @author yefei **/ @BaseRequest( - baseURL = "${taosUrl}", - interceptor = TaosJsonBodyBuildInterceptor.class + baseURL = "${taosUrl}" ) public interface TDEngineRest { /** - * 执行sql + * TDEngine execute sql, 必须 2.2.0 以上版本 * * @param sql * @return String */ @Post - @JsonPath("/tdengine/execute") @BasicAuth(username = "${taosUser}", password = "${taosPwd}") - String executeSql(@ParamName("sql") String sql); + String executeSql(String sql); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java index f14e75b4..2afa0289 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java @@ -6,6 +6,8 @@ import com.zmops.iot.web.analyse.dto.param.LatestParam; import com.zmops.iot.web.analyse.service.LatestService; import com.zmops.iot.web.auth.Permission; +import com.zmops.zeus.driver.service.TDEngineRest; +import org.checkerframework.checker.units.qual.A; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RequestBody; @@ -25,6 +27,9 @@ public class LatestController { @Autowired LatestService latestService; + @Autowired + private TDEngineRest tdEngineRest; + @RequestMapping("/query") @Permission(code = "latest") public Pager qeuryLatest(@Validated @RequestBody LatestParam latestParam) { @@ -36,4 +41,10 @@ public Pager qeuryLatest(@Validated @RequestBody LatestParam latestPa public ResponseData queryMap(@RequestParam("deviceId") String deviceId) { return ResponseData.success(latestService.queryMap(deviceId)); } + + + @RequestMapping("/tdexecutesql") + public ResponseData getTdEngineData(@RequestParam String sql) { + return ResponseData.success(tdEngineRest.executeSql(sql)); + } } From d294fe13968926676e20e8792d8104c0a03c490c Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 27 Sep 2021 14:48:24 +0800 Subject: [PATCH 323/763] [style]: remove unused driver ftl file --- zeus-driver/src/main/resources/api-json/tdengine/execute.ftl | 1 - 1 file changed, 1 deletion(-) delete mode 100644 zeus-driver/src/main/resources/api-json/tdengine/execute.ftl diff --git a/zeus-driver/src/main/resources/api-json/tdengine/execute.ftl b/zeus-driver/src/main/resources/api-json/tdengine/execute.ftl deleted file mode 100644 index c0a4f49a..00000000 --- a/zeus-driver/src/main/resources/api-json/tdengine/execute.ftl +++ /dev/null @@ -1 +0,0 @@ -${sql} \ No newline at end of file From aa570e2eb4e28272eef40f7ec515fa8efd8d4f86 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 27 Sep 2021 16:01:48 +0800 Subject: [PATCH 324/763] [style]: format code style --- .../zeus/iot/server/transfer/core/task/TaskWrapper.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java index 2d90edc1..83fc1d06 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java @@ -21,8 +21,9 @@ */ public class TaskWrapper extends AbstractStateWrapper { - private static final Logger LOGGER = LoggerFactory.getLogger(TaskWrapper.class); - public static final int WAIT_FINISH_TIME_OUT = 1; + private static final Logger LOGGER = LoggerFactory.getLogger(TaskWrapper.class); + + public static final int WAIT_FINISH_TIME_OUT = 1; private final TaskManager taskManager; private final Task task; From ab0ab2980f6a2e62ea0155f4618ec825cb2e429d Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 27 Sep 2021 16:04:44 +0800 Subject: [PATCH 325/763] [fix]: fix default user role --- zeus-driver/src/main/resources/api-json/role/adminRole.get.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-driver/src/main/resources/api-json/role/adminRole.get.ftl b/zeus-driver/src/main/resources/api-json/role/adminRole.get.ftl index 60de160e..62fc5472 100644 --- a/zeus-driver/src/main/resources/api-json/role/adminRole.get.ftl +++ b/zeus-driver/src/main/resources/api-json/role/adminRole.get.ftl @@ -4,7 +4,7 @@ "params": { "output": "extend", "filter": { - "name":"Admin role" + "name":"Super admin role" } }, "auth": "${userAuth}", From 3e9e50f5fef78bea374fc707a4f46f9416445611 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Mon, 27 Sep 2021 16:57:27 +0800 Subject: [PATCH 326/763] [fix]: fix centos install script --- docs/centos/install.sh | 60 +++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/docs/centos/install.sh b/docs/centos/install.sh index c773819e..940c2eb0 100755 --- a/docs/centos/install.sh +++ b/docs/centos/install.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash + set -e ROOT_UID=0 @@ -13,7 +14,7 @@ PGDATA=/opt/zeus/pgdata function logprint() { if [ $? != 0 ]; then - echo "$1" + echo -e "\033[31m Error: $1 \033[0m" exit fi } @@ -95,41 +96,36 @@ function AddInstallRepo() { ### 备份原有yum mv /etc/yum.repos.d/* /tmp/ ### 基础 YUM 源 - if ! curl -s -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo; then - echo "YUM 仓库配置异常,请检查网络" - fi - sed -i '/mirrors.aliyuncs.com/,/mirrors.cloud.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo - ### Postgresql && timescaleDB - tee /etc/yum.repos.d/postgresql_timescaledb.repo </dev/null + ### Postgresql && php + tee /etc/yum.repos.d/Centos-Base.repo </dev/null +[base] +name=CentOS-\$releasever - Base +baseurl=http://mirrors.tuna.tsinghua.edu.cn/centos/\$releasever/os/\$basearch/ +gpgcheck=0 + [epel] name=Extra Packages for Enterprise Linux 7 - \$basearch -baseurl=http://mirrors.aliyun.com/epel/7/\$basearch +baseurl=https://mirrors.tuna.tsinghua.edu.cn/epel/7/\$basearch failovermethod=priority enabled=1 gpgcheck=0 [centos-sclo-rh] name=CentOS-7 - SCLo rh -baseurl=https://mirrors.aliyun.com/centos/7/sclo/\$basearch/rh/ +baseurl=http://mirrors.tuna.tsinghua.edu.cn/centos/7/sclo/\$basearch/rh/ gpgcheck=0 enabled=1 -[pgdg-common] -name=PostgreSQL common RPMs for RHEL/CentOS \$releasever - \$basearch -baseurl=https://download.postgresql.org/pub/repos/yum/common/redhat/rhel-\$releasever-\$basearch -enabled=1 -gpgcheck=0 - - [pgdg13] name=PostgreSQL 13 for RHEL/CentOS \$releasever - \$basearch -baseurl=https://download.postgresql.org/pub/repos/yum/13/redhat/rhel-\$releasever-\$basearch +baseurl=https://mirrors.tuna.tsinghua.edu.cn/postgresql/repos/yum/13/redhat/rhel-\$releasever-\$basearch enabled=1 gpgcheck=0 EOL yum clean all 1>/dev/null && yum makecache 1>/dev/null + yum -y install java-1.8.0-openjdk expect 1> /dev/null logprint "yum 源配置失败详细看安装日志输出" echo -e "\033[32m [ OK ] \033[0m" } @@ -166,7 +162,7 @@ function PGInstall() { systemctl start postgresql-13 ### 修改数据库管理员密码 cd /tmp || exit - sudo -u postgres /usr/pgsql-13/bin/psql -c "ALTER USER postgres WITH PASSWORD 'zeusiot';" 1> /dev/null + sudo -u postgres /usr/pgsql-13/bin/psql -c "ALTER USER postgres WITH PASSWORD 'postgres';" 1> /dev/null echo -e "\033[32m [ OK ] \033[0m" } @@ -177,7 +173,6 @@ function ZbxInstall() { cd "$basename" || exit yum -y install vim \ wget \ - expect \ gcc \ gcc-c++ \ net-snmp \ @@ -282,8 +277,8 @@ WantedBy=multi-user.target EOL systemctl daemon-reload - systemctl enable zabbix-server - systemctl enable zabbix-agent + systemctl enable zabbix-server &> /dev/null + systemctl enable zabbix-agent &> /dev/null systemctl start zabbix-server systemctl start zabbix-agent echo -e "\033[32m [ OK ] \033[0m" @@ -357,8 +352,8 @@ EOL ## 修改 nginx 配置用户 sed -i 's/user nginx;/user zeus;/g' /etc/nginx/nginx.conf - systemctl enable rh-php73-php-fpm - systemctl enable nginx + systemctl enable rh-php73-php-fpm &> /dev/null + systemctl enable nginx &> /dev/null systemctl start rh-php73-php-fpm systemctl start nginx echo -e "\033[32m [ OK ] \033[0m" @@ -392,19 +387,12 @@ function taosinstall() { } EOF ## 启动taos - systemctl enable taosd - systemctl start taosd + systemctl enable taosd &> /dev/null + systemctl start taosd echo -e "\033[32m [ OK ] \033[0m" } -function natsinstall() { - echo -e -n "\033[32mStep10: 安装 nats 服务。。。 \033[0m" - wget -c https://github.com/nats-io/nats-server/releases/download/v2.6.0/nats-server-v2.6.0-linux-amd64.tar.gz -o /dev/null -O - | tar -xz - mv ./nats-server-v2.6.0-linux-amd64/nats-server /usr/bin/nats-server - nohup nats-server &> /dev/null & - echo -e "\033[32m [ OK ] \033[0m" -} function ZeusInstall() { echo -e -n "\033[32mStep11: 安装 Zeus-IoT 服务。。。 \033[0m" @@ -414,11 +402,12 @@ function ZeusInstall() { wget -c https://packages.zmops.cn/zeus-iot/zeus-iot-bin.tar.gz -o /dev/null -O - | tar -xz gettoken ## 数据库导入 - cat ./zeus-iot-bin/bin/sql/zeus-iot.sql | sudo -u zabbix psql zabbix 1>/dev/null - + sudo -u postgres createdb -E Unicode -T template0 zeus-iot + cat ./zeus-iot-bin/bin/sql/zeus-iot.sql | sudo -u postgres psql zeus-iot &>/dev/null + logprint "文件未找到" sed -i "s%\(zbxApiToken: \).*%\1$token%" ./zeus-iot-bin/webapp/webapp.yml sed -i '19i export ZEUS_DB_PASSWORD=zeusiot' ./zeus-iot-bin/bin/startup.sh - ./zeus-iot-bin/bin/startup.sh + ./zeus-iot-bin/bin/startup.sh 1> /dev/null echo -e "\033[32m [ OK ] \033[0m" } @@ -431,6 +420,5 @@ ZbxInstall PHPInstall WebInstall taosinstall -natsinstall ZeusInstall # 安装结束 From ff586ed466dc27428c41b3bd46f2da909c35d74c Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Mon, 27 Sep 2021 19:39:28 +0800 Subject: [PATCH 327/763] [docs]: update install docs --- README.md | 4 +- docs/README.md | 324 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 248 insertions(+), 80 deletions(-) diff --git a/README.md b/README.md index aba7d1aa..9ca257dd 100644 --- a/README.md +++ b/README.md @@ -13,13 +13,13 @@ Zeus-IoT supports Linux operating systems based on the x86_64 platform, such as - Centos7、RedHat 7 ```shell - curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/rhel/quick-install.sh | bash + curl -sL https://github.com/zmops/zeus-iot/raw/develop/docs/centos/install.sh | bash ``` - Ubuntu 20.04 ```shell - curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/ubuntu/install.sh | bash + curl -sL https://github.com/zmops/zeus-iot/raw/develop/docs/ubuntu/install.sh | bash ``` 访问 `http://` 登录 Zeus-IOT 系统[快速开始](./docs/quick-start.rst) 。 diff --git a/docs/README.md b/docs/README.md index 734c4973..756d227b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,114 +1,282 @@ -### Zeus IOT Document +[toc] -#### 自定义安装 +# Zeus IoT Document +> Zeus IoT 基于 zabbix-5.4 安装。 + +## 环境要求 + +> 目前 ZEUS 支持 Linux x86_64 系统平台。 + +| 配置规格 | 操作系统 | CPU | 内存 | 存储 | +| :------: | :------------: | :--: | :--: | :---: | +| 最低配置 | Centos、Ubuntu | 2 核 | 4 GB | 100GB | +| 推荐配置 | Centos、Ubuntu | 4 核 | 8 GB | 500GB | + +## 快速安装 + +> 简化 zabbix 安装部署,方便客户快速使用 Zeus IoT 产品。 + +系统终端执行以下命令快速安装 + +- Centos7/Redhat7 + + ```shell + curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/centos/install.sh | bash + ``` + +- Ubuntu 20.04 + + ```shell + curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/ubuntu/install.sh | bash + ``` + +## 自定义安装 + +> 自定义安装是在本身已有 zabbix 或需要分开部署 zabbix 和 zeus-iot 服务。 + +### 安装 zabbix 服务 + +> **zabbix 安装可参照**[zabbix官网](https://www.zabbix.com/download) 。**这里就不做详细介绍**。 + +:bulb: **建议使用 PostgreSQL 数据库,因为 zeus-iot-ui 使用的是 PostgreSQL 数据库。** + + + +#### zabbix 系统优化 + +- **修改 zabbix 时区** + - 管理员用户登录 zabbix 管理界面进入 "**管理(Administrator)**" ----- "**一般()**" ----- "**Default time zone**" 选择 "(UTC+08:00) Asia/Shanghai" + - 普通用户登录 zabbix 管理界面进入 "**User settings**" ----- "**Profile**" ----- "**Time zone**" 选择 "(UTC+08:00) Asia/Shanghai" + +### 安装 zeus-iot 系统 + +#### 安装 PostgreSQL 数据库 + +- Centos/RedHat + + ```shell + # 安装 PostgreSQL 仓库源: + sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm + + # 安装 PostgreSQL: + sudo yum install -y postgresql13-server + + # 初始化数据库并启动: + sudo /usr/pgsql-13/bin/postgresql-13-setup initdb + sudo systemctl enable postgresql-13 + sudo systemctl start postgresql-13 + ``` + + +- Ubuntu + + ```shell + # 安装 PostgreSQL 仓库源: + sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' + wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - + + # 安装 PostgreSQL: + sudo apt-get update && sudo apt-get -y install postgresql + ``` + + + +#### 获取 zeus-iot 程序包 + +- 直接下载 release 包 + + ```shell +wget -c https://packages.zmops.cn/zeus-iot/zeus-iot-bin.tar.gz + ``` + +- 从源码编译 + + ```shell + git clone https://github.com/zmops/zeus-iot.git + cd zeus-iot && git submodule update --init --recursive + mvn clean package -U -Dmaven.test.skip=true + ``` + +#### 初始化系统服务 + +1、 创建数据库 + +```shell +sudo -u postgres createdb -E Unicode -T template0 zeus-iot ``` -⚠️ : 自定义安装是在本身已有 zabbix 或 分开部署zabbix 和 zeus。 + +2、 导入 SQL + +```shell +cat zeus-iot.sql | sudo -u postgres psql zeus-iot ``` -- **zabbix 安装可参照[zabbix官网](https://www.zabbix.com/download) 。或者[快速安装](../README.md)。这里就不做详细介绍。** +3、 安装 JDK 驱动 + +```shell +# Centos/Redhat 安装 +yum install java-1.8.0-openjdk.x86_64 -y +# Ubuntu 安装 +apt install openjdk-8-jdk -y +``` + +#### 服务启动配置 + +> zeus-iot 主要由 zeus-iot-server 和 webapp 两个服务组成,配置文件分别是 ``./zeus-iot-bin/conf/application.yml`` 和 ``./zeus-iot-bin/webapp/webapp.yml``。 + +##### 配置 zabbix token + +1、登录 zabbix 管理界面进入 "**User settings**" ----- "**API tokens**" ----- "**Create API token**" + +2、创建名为 zeus 的 API token, 取消 "**Set expiration date and time**" 的勾选项。确定后会生成 Auth token,点击 "**Copy to clipboard**" 复制token。 + +3、配置 zeus-iot 连接 zabbix token + + vim /opt/zeus/zeus-iot-bin/webapp/webapp.yml + + ... + forest: + log-enabled: false + timeout: 5000 + variables: + ... + zbxServerPort: ${ZEUS_ZABBIX_PORT:80} + zbxApiToken: 4d3ed2be23a3f325d6ccaaaeab76bbdc6a559f3c608e523f9906ea923f7d61c5 # 修改此处token信息 + ... + ... -- **zeus iot 安装** +##### 其它启动参数配置 - - **前端 UI 部署** +- 直接修改配置文件 + + 以修改 zabbix 信息为例: - 可采用 nginx 做为web服务器来部署 ui。 + ``` + vim /opt/zeus/zeus-iot-bin/webapp/webapp.yml + + forest: + log-enabled: false + timeout: 5000 + variables: + ## Zabbix API IP And ServerIp and ServerPort + zbxApiUrl: http://${ZEUS_ZABBIX_HOST:127.0.0.1}:${ZEUS_ZABBIX_PORT:80}/zabbix/api_jsonrpc.php + zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} + zbxServerPort: ${ZEUS_ZABBIX_PORT:80} + zbxApiToken: 4d3ed2be23a3f325d6ccaaaeab76bbdc6a559f3c608e523f9906ea923f7d61c5 + taosUrl: http://${ZEUS_TAOS_HOST:127.0.0.1}:${ZEUS_TAOS_REST_PORT:6041}/rest/sql/${ZEUS_TAOS_DB:zeus_data} + taosUser: root + taosPwd: taosdata + ``` + + - - Ubuntu 安装 nginx - ```shell - apt install nginx -y - ``` +- 通过配置环境变量的方式修改(临时修改) - - Centos/RedHat 安装 nginx + zeus-iot 支持环境变量配置启动,可以通过 ``export ZEUS_ZABBIX_HOST=127.0.0.1`` 申明环境变量。 - ```shell - yum install nginx -y - ``` +#### 启动服务 + +> zeus-iot 默认需要连接 taos 数据库,所以启动前请先[配置taos数据库](#配置 taos 数据库) + +```shell +# 启动 +/opt/zeus/zeus-iot-bin/bin/startup.sh + +# 停止 +/opt/zeus/zeus-iot-bin/bin/stop.sh +``` - - nginx 配置文件 - ```shell - tee /etc/nginx/conf.d/zabbix.conf < 可通过[涛思官网](https://www.taosdata.com/en/getting-started/)获取安装包 - - **zeus-iot 安装** +:bulb: zeus-iot 默认使用 **RESTful connector** 连接涛思数据库。 - > zeus server 是以 jar 包的形式部署在服务器上。 +### 安装 taos 数据库 - 需要安装 JDK 1.8 以上开发工具包。 +- **Centos/Redhat 安装** - - Ubuntu 安装 JDK 1.8 + ```shell +rpm -ivh TDengine-server-2.2.0.2-Linux-x64.rpm + ``` - ```shell - apt install openjdk-8-jdk -y - ``` +- **Ubuntu/Debain 安装** - - Centos/Redhat 安装 JDK 1.8 + ```shell + dpkg -i TDengine-server-2.2.0.2-Linux-x64.deb + ``` - ```shell - yum install java-1.8.0-openjdk.x86_64 -y - ``` +:bulb: 这里只介绍单机版涛思安装部署,安装时是以交互式安装,只需按回车。如要安装集群版涛思需要查阅 [涛思官网文档](https://www.taosdata.com/en/documentation/) - - 获取 zeus-iot.jar 包 +- **启动 taos** - - 直接下载 release 包 + ```shell +systemctl start taosd + ``` - - 从源码编译 +- **创建 zeus_data 数据库** - ```shell - git clone https://github.com/zmops/zeus-iot.git - cd zeus-iot/ && mvn clean package -U -Dmaven.test.skip=true - ``` + ```shell + # linux 命令行登录taos + taos + + # 创建 zeus_data 数据库 + taos> create database zeus_data; + ``` - - 启动服务 +启用 zabbix 导出功能 +--------------------- - ```shell - export ZEUS_DB_HOST=127.0.0.1 #zeus 数据库地址,默认: 127.0.0.1 - export ZEUS_DB_PORT=5432 #zeus 数据库端口,默认: 5432 - export ZEUS_DB_USERNAME=postgres #zeus 数据库用户名,默认: postgres - export ZEUS_DB_PASSWORD=postgres #zeus 数据库密码,默认: postgres - export ZEUS_ZABBIX_HOST=127.0.0.1 #zabbix server 地址,默认: 127.0.0.1 - export ZEUS_ZABBIX_API_PORT=80 #zabbix web 端口,默认: 80 - export ZEUS_ZABBIX_PORT=10051 #zabbix server 端口,默认: 10051 - export ZEUS_CALLBACK_HOST=127.0.0.1 #zeus-iot 地址,默认: 127.0.0.1 - export ZEUS_CALLBACK_PORT=9090 #zeus-iot 端口,默认: 9090 - ``` +修改 zabbix-server.conf 配置文件,如下: - 以上环境变量,根据服务架构环境,做相应修改。不设置即使用默认值 +- ExportDir=/data/zabbix_history 配置导出目录 +- ExportFileSize=1G 配置导出文件的大小 +- ExportType=history 配置导出的数据表 + + +创建导出的目录并重启 zabbix-server 使配置生效 + +```shell +mkdir -p /data/zabbix_history +systemctl restart zabbix-server +``` - ```shell - nohup java -jar zeus-iot.jar > /tmp/zeus-iot.log 2>&1 & - ``` - +修改 zeus-iot 数据库连接 +-------------------------- + +``` +# 停止 zeus-iot 服务 +/opt/zeus/zeus-iot-bin/bin/stop.sh + +# 修改数据连接配置如下 +vim /opt/zeus/zeus-iot-bin/conf/application.yml + ... + # tdengine storage realtime + storage: + selector: ${ZS_STORAGE:tdengine} + tdengine: + url: ${ZS_STORAGE_TDENGINE_URL:jdbc:TAOS://127.0.0.1:6030/zeus_data} # TDEngine jdbcUrl + user: ${ZS_STORAGE_TDENGINE_USER:root} + password: ${ZS_STORAGE_TDENGINE_PASSWORD:taosdata} + ... + +``` + +## 启动 zeus-iot 服务 + +```shell + /opt/zeus/zeus-iot-bin/bin/startup.sh +``` From e268988944e4199a68ea6b29d812c943b3c283b4 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Mon, 27 Sep 2021 19:41:48 +0800 Subject: [PATCH 328/763] [docs]: update readme file --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9ca257dd..e84dce81 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Zeus-IoT supports Linux operating systems based on the x86_64 platform, such as curl -sL https://github.com/zmops/zeus-iot/raw/develop/docs/ubuntu/install.sh | bash ``` -访问 `http://` 登录 Zeus-IOT 系统[快速开始](./docs/quick-start.rst) 。 +访问 `http://:9090` 登录 Zeus-IOT 系统[快速开始](./docs/quick-start.rst) 。 假如您已经有自己的 **zabbix** 且 **zabbix** 版本是 **5.4.0+**。可以选择[自定义安装 Zeus iot](./docs/README.md) From 677cef8c2b6f08bf201a16ca3d4cd727af244b1a Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 27 Sep 2021 20:05:07 +0800 Subject: [PATCH 329/763] [fix]: fix zbxId type --- .../iot/domain/product/ProductEventRelation.java | 2 +- .../com/zmops/zeus/driver/service/ZbxTrigger.java | 10 +++++----- .../iot/message/handler/MessageEventHandler.java | 8 +++++++- .../zmops/iot/web/alarm/service/AlarmService.java | 6 +++--- .../controller/DeviceEventTriggerController.java | 8 ++++---- .../zmops/iot/web/device/dto/DeviceEventRule.java | 2 +- .../web/device/service/DeviceEventRuleService.java | 12 ++++++------ .../iot/web/device/service/work/SaveOtherWorker.java | 2 +- .../controller/ProductEventTriggerController.java | 4 ++-- .../zmops/iot/web/product/dto/ProductEventRule.java | 2 +- .../iot/web/product/dto/ProductEventRuleDto.java | 2 +- .../web/product/service/ProductEventRuleService.java | 10 +++++----- .../service/work/SaveProductEventTriggerWorker.java | 2 +- 13 files changed, 38 insertions(+), 32 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java index ffd7542d..9ec8a1e1 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java @@ -24,7 +24,7 @@ public class ProductEventRelation { private String relationId; - private Integer zbxId; + private String zbxId; private String inherit; private String status; diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java index 7b4c1f88..0efbf104 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java @@ -40,7 +40,7 @@ String triggerCreate(@ParamName("triggerName") String triggerName, */ @Post @JsonPath("/trigger/trigger.update") - String triggerUpdate(@ParamName("triggerId") Integer triggerId, + String triggerUpdate(@ParamName("triggerId") String triggerId, @ParamName("expression") String expression, @ParamName("ruleLevel") Byte ruleLevel); @@ -54,7 +54,7 @@ String triggerUpdate(@ParamName("triggerId") Integer triggerId, */ @Post @JsonPath("/trigger/trigger.tags.update") - String triggerTagCreate(@ParamName("triggerId") Integer triggerId, + String triggerTagCreate(@ParamName("triggerId") String triggerId, @ParamName("tagMap") Map tags); /** @@ -74,7 +74,7 @@ String triggerTagCreate(@ParamName("triggerId") Integer triggerId, */ @Post @JsonPath("/trigger/triggerAndTags.get") - String triggerAndTagsGet(@ParamName("triggerIds") Integer triggerIds); + String triggerAndTagsGet(@ParamName("triggerIds") String triggerIds); /** @@ -105,7 +105,7 @@ String triggerTagCreate(@ParamName("triggerId") Integer triggerId, */ @Post @JsonPath("/trigger/trigger.status.update") - String triggerStatusUpdate(@ParamName("triggerid") Integer triggerId, + String triggerStatusUpdate(@ParamName("triggerid") String triggerId, @ParamName("status") String status); /** @@ -116,5 +116,5 @@ String triggerStatusUpdate(@ParamName("triggerid") Integer triggerId, */ @Post @JsonPath("/trigger/trigger.delete") - String triggerDelete(@ParamName("triggerid") Integer triggerId); + String triggerDelete(@ParamName("triggerid") String triggerId); } diff --git a/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java b/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java index defd17eb..9e2ef18b 100644 --- a/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java +++ b/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java @@ -40,7 +40,7 @@ public void onConnect(SocketIOClient client) { if (client != null) { String token = client.getHandshakeData().getSingleUrlParam("token"); - String userId = client.getHandshakeData().getSingleUrlParam("token"); + String userId = client.getHandshakeData().getSingleUrlParam("userId"); UUID sessionId = client.getSessionId(); @@ -79,6 +79,12 @@ public void onGroupEvent(SocketIOClient client, AckRequest request, GroupMessage Collection clients = server.getRoomOperations(data.getGroupId()).getClients(); } + public void sendDisconnectMsg(String userId) { + if (userClient.findByUserId(userId).isPresent()) { + UUID uuid = userClient.findByUserId(userId).get(); + server.getClient(uuid).sendEvent(Event.BROADCAST, "disconnect"); + } + } public void sendToBroadcast(BroadcastMessageRequest message) { for (UUID clientId : userClient.findAll()) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index c274de76..6a8c54ff 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -81,7 +81,7 @@ public List getAlarmByPage(AlarmParam alarmParam) { List ruleList = DB.findDto(ProductEventRuleDto.class, "select event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") .setParameter("zbxIds", triggerIds).findList(); - Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); + Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); List alarmDtoList = new ArrayList<>(); @@ -112,7 +112,7 @@ public List getAlarmList(AlarmParam alarmParam) { List ruleList = DB.findDto(ProductEventRuleDto.class, "select d.event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id," + "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") .setParameter("zbxIds", triggerIds).findList(); - Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); + Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); List alarmDtoList = new ArrayList<>(); problemList.forEach(zbxProblemInfo -> { @@ -155,7 +155,7 @@ public List getEventList(AlarmParam alarmParam) { List ruleList = DB.findDto(ProductEventRuleDto.class, "select event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id," + "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") .setParameter("zbxIds", triggerIds).findList(); - Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); + Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); List alarmDtoList = new ArrayList<>(); problemList.forEach(zbxProblemInfo -> { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index 7f32e517..fbc2c6cd 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -85,7 +85,7 @@ public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEn .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); //step 2: zbx 保存触发器 - Integer[] triggerIds = deviceEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); + String[] triggerIds = deviceEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); //step 4: zbx 触发器创建 Tag Map tags = new ConcurrentHashMap<>(3); @@ -103,7 +103,7 @@ public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEn if (any.isPresent()) { tags.put(EVENT_TAG_NAME, eventRuleId + ""); } - for (Integer triggerId : triggerIds) { + for (String triggerId : triggerIds) { zbxTrigger.triggerTagCreate(triggerId, tags); } @@ -164,7 +164,7 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); //step 2: zbx 保存触发器 - Integer[] triggerIds = deviceEventRuleService.updateZbxTrigger(eventRule.getZbxId(), expression, eventRule.getEventLevel()); + String[] triggerIds = deviceEventRuleService.updateZbxTrigger(eventRule.getZbxId(), expression, eventRule.getEventLevel()); //step 4: zbx 触发器创建 Tag Map tags = eventRule.getTags().stream() @@ -182,7 +182,7 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn if (any.isPresent()) { tags.put(EVENT_TAG_NAME, eventRule.getEventRuleId() + ""); } - for (Integer triggerId : triggerIds) { + for (String triggerId : triggerIds) { zbxTrigger.triggerTagCreate(triggerId, tags); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java index db3c3bc9..8f7305c4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java @@ -52,7 +52,7 @@ public class DeviceEventRule { private List tags; @NotNull(groups = BaseEntity.Update.class) - private Integer zbxId; + private String zbxId; @NotBlank(groups = {BaseEntity.Status.class, BaseEntity.Delete.class}) private String deviceId; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 304535da..a0f79f64 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -183,11 +183,11 @@ private ProductEventExpression initEventExpression(DeviceEventRule.Expression ex * @param triggerId 规则ID * @param zbxId triggerId */ - public void updateProductEventRuleZbxId(Long triggerId, Integer[] zbxId) { + public void updateProductEventRuleZbxId(Long triggerId, String[] zbxId) { List triggers = JSONObject.parseArray(zbxTrigger.triggerGet(Arrays.toString(zbxId)), Triggers.class); - Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.get(0).host, Triggers::getTriggerid)); + Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.get(0).host, Triggers::getTriggerid)); List productEventRelationList = new QProductEventRelation().eventRuleId.eq(triggerId).findList(); @@ -233,7 +233,7 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S * @param level 告警等级 * @return 触发器ID */ - public Integer[] createZbxTrigger(String triggerName, String expression, Byte level) { + public String[] createZbxTrigger(String triggerName, String expression, Byte level) { String res = zbxTrigger.triggerCreate(triggerName, expression, level); return JSON.parseObject(res, TriggerIds.class).getTriggerids(); } @@ -246,19 +246,19 @@ public Integer[] createZbxTrigger(String triggerName, String expression, Byte le * @param level * @return */ - public Integer[] updateZbxTrigger(Integer triggerId, String expression, Byte level) { + public String[] updateZbxTrigger(String triggerId, String expression, Byte level) { String res = zbxTrigger.triggerUpdate(triggerId, expression, level); return JSON.parseObject(res, TriggerIds.class).getTriggerids(); } @Data static class TriggerIds { - private Integer[] triggerids; + private String[] triggerids; } @Data public static class Triggers { - private Integer triggerid; + private String triggerid; private String description; private List hosts; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java index 78d7d46f..9d248acf 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java @@ -74,7 +74,7 @@ public Boolean action(DeviceDto deviceDto, Map> allW //告警规则关联 并 回填zbx triggerId List triggers = JSONObject.parseArray(zbxTrigger.triggerGetByHost(deviceId), ProductEventRuleService.Triggers.class); - Map map = triggers.parallelStream().collect(Collectors.toMap(ProductEventRuleService.Triggers::getDescription, ProductEventRuleService.Triggers::getTriggerid)); + Map map = triggers.parallelStream().collect(Collectors.toMap(ProductEventRuleService.Triggers::getDescription, ProductEventRuleService.Triggers::getTriggerid)); List productEventRelationList = new QProductEventRelation().relationId.eq(deviceDto.getProductId() + "").findList(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index 3ae68a07..8eb81fdd 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -106,7 +106,7 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); //step 2: zbx 保存触发器 - Integer[] triggerIds = productEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); + String[] triggerIds = productEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); //step 4: zbx 触发器创建 Tag Map tags = new ConcurrentHashMap<>(3); @@ -124,7 +124,7 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE if (any.isPresent()) { tags.put(EVENT_TAG_NAME, eventRuleId + ""); } - for (Integer triggerId : triggerIds) { + for (String triggerId : triggerIds) { zbxTrigger.triggerTagCreate(triggerId, tags); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java index 5a2eb9da..0277d867 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java @@ -52,7 +52,7 @@ public class ProductEventRule { private List tags; @NotNull(groups = BaseEntity.Update.class) - private Integer zbxId; + private String zbxId; @NotBlank(groups = BaseEntity.Create.class) private String productId; // 产品ID diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java index 4c8d3b2b..6fe4ee42 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java @@ -36,7 +36,7 @@ public class ProductEventRuleDto { private List tags; - private Integer zbxId; + private String zbxId; private String productId; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index e66f039b..10677f16 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -176,12 +176,12 @@ private ProductEventExpression initEventExpression(ProductEventRule.Expression e * @param eventRuleId 规则ID * @param zbxId triggerId */ - public void updateProductEventRuleZbxId(Long eventRuleId, Integer[] zbxId) { + public void updateProductEventRuleZbxId(Long eventRuleId, String[] zbxId) { String s = zbxTrigger.triggerGet(Arrays.toString(zbxId)); List triggers = JSONObject.parseArray(s, Triggers.class); - Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.get(0).host, Triggers::getTriggerid)); + Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.get(0).host, Triggers::getTriggerid)); List productEventRelationList = new QProductEventRelation().eventRuleId.eq(eventRuleId).findList(); @@ -203,7 +203,7 @@ public void updateProductEventRuleZbxId(Long eventRuleId, Integer[] zbxId) { * @param level 告警等级 * @return 触发器ID */ - public Integer[] createZbxTrigger(String triggerName, String expression, Byte level) { + public String[] createZbxTrigger(String triggerName, String expression, Byte level) { String res = zbxTrigger.triggerCreate(triggerName, expression, level); return JSON.parseObject(res, TriggerIds.class).getTriggerids(); } @@ -281,12 +281,12 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S @Data static class TriggerIds { - private Integer[] triggerids; + private String[] triggerids; } @Data public static class Triggers { - private Integer triggerid; + private String triggerid; private String description; private List hosts; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java index 6d700b60..05c9472d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java @@ -43,7 +43,7 @@ public Boolean action(ProductEventRule productEventRule, Map deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); List triggers = JSONObject.parseArray(zbxTrigger.triggerGetByName(productEventRule.getEventRuleId() + ""), ProductEventRuleService.Triggers.class); - Map treiggerMap = triggers.parallelStream().collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ProductEventRuleService.Triggers::getTriggerid)); + Map treiggerMap = triggers.parallelStream().collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ProductEventRuleService.Triggers::getTriggerid)); List productEventRelationList = new ArrayList<>(); for (String deviceId : deviceIds) { ProductEventRelation productEventRelation = new ProductEventRelation(); From 73da636824a6b8e3644613e3a821488f15543d47 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 27 Sep 2021 20:12:37 +0800 Subject: [PATCH 330/763] [fix]: fix bugs at camel zabbix sender --- .../zeus/iot/server/core/camel/ZabbixSenderEndpoint.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixSenderEndpoint.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixSenderEndpoint.java index 8457da64..0b23ff98 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixSenderEndpoint.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixSenderEndpoint.java @@ -12,21 +12,23 @@ */ public class ZabbixSenderEndpoint extends DefaultEndpoint { - private final ModuleManager moduleManager; + private final ModuleManager moduleManager; + private final ZabbixTrapperProducer producer; public ZabbixSenderEndpoint(String endpointUri, Component component, ModuleManager moduleManager) { super(endpointUri, component); this.moduleManager = moduleManager; + this.producer = new ZabbixTrapperProducer(this, moduleManager); } @Override public Producer createProducer() throws Exception { - return new ZabbixTrapperProducer(this, moduleManager); + return producer; // 每次 process 都会创建一个对象 } @Override public Consumer createConsumer(Processor processor) throws Exception { - return new ZabbixSenderConsumer(this, processor); + return new ZabbixSenderConsumer(this, processor); //TODO } @Override From e3c723fb4dc175ae2593a0add1c9ab9968bd96c9 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 27 Sep 2021 20:21:19 +0800 Subject: [PATCH 331/763] [fix]: fix zbxId type --- .../java/com/zmops/iot/web/analyse/service/HomeService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index 6ab3486e..26336e46 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -306,7 +306,7 @@ public List> getAlarmTop(long timeFrom, long timeTill) { if (ToolUtil.isNotEmpty(alarmList)) { - List triggerIds = alarmList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Integer::parseInt).collect(Collectors.toList()); + List triggerIds = alarmList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Objects::toString).collect(Collectors.toList()); List deviceList = DB.findDto(DeviceDto.class, "select name,r.zbx_id from device d INNER JOIN (select relation_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.relation_id=d.device_id") .setParameter("zbxIds", triggerIds).findList(); Map deviceMap = deviceList.parallelStream().collect(Collectors.toMap(DeviceDto::getZbxId, DeviceDto::getName)); From 5507318f19487e664b07684e17d40cd07746f92e Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 27 Sep 2021 21:07:34 +0800 Subject: [PATCH 332/763] [ftx]: forest http restful request tdengine --- .../java/com/zmops/zeus/driver/service/TDEngineRest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java index c5c7286a..a2456cb2 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java @@ -1,6 +1,7 @@ package com.zmops.zeus.driver.service; import com.dtflys.forest.annotation.BaseRequest; +import com.dtflys.forest.annotation.Body; import com.dtflys.forest.annotation.Post; import com.dtflys.forest.extensions.BasicAuth; @@ -18,7 +19,9 @@ public interface TDEngineRest { * @param sql * @return String */ - @Post + @Post( + contentType = "application/json;charset=utf-8" + ) @BasicAuth(username = "${taosUser}", password = "${taosPwd}") - String executeSql(String sql); + String executeSql(@Body String sql); } From 5304d606a6e201eccd3b79b1b8cf0e51896d5fe8 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 27 Sep 2021 21:39:41 +0800 Subject: [PATCH 333/763] [fix]: fix device list --- .../java/com/zmops/iot/web/device/service/DeviceService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 2d7fadf7..e0fc3f83 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -111,7 +111,7 @@ public Pager devicePageList(DeviceParam deviceParam) { return new Pager<>(); } StringBuilder sql = generateBaseSql(); - + sql.append(" where 1=1"); List sids = new ArrayList<>(); if (ToolUtil.isNotEmpty(deviceParam.getTag())) { QTag qTag = new QTag().select(QTag.Alias.sid).templateId.isNull(); @@ -468,7 +468,7 @@ public DeviceDto deviceDetail(String deviceId) { } StringBuilder sql = generateBaseSql(); sql.append(" where d.device_id=:deviceId"); - DeviceDto deviceDto = DB.findDto(DeviceDto.class, sql.toString()).setParameter("deviceId", deviceId).setParameter("deviceGroupIds",devGroupIds).findOne(); + DeviceDto deviceDto = DB.findDto(DeviceDto.class, sql.toString()).setParameter("deviceId", deviceId).setParameter("deviceGroupIds", devGroupIds).findOne(); return deviceDto; } From 1cb5388a79781fc4371f85e77ba2f732450d8517 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 27 Sep 2021 21:49:46 +0800 Subject: [PATCH 334/763] [style]: optimize code style --- .../zmops/zeus/iot/server/transfer/sender/SenderManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java index 88d53965..6d08dd51 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java @@ -28,7 +28,8 @@ public class SenderManager { private final TaskPositionManager taskPositionManager; private final String sourceFilePath; - private final PluginMetric metric = new PluginMetric(); + + private final PluginMetric metric = new PluginMetric(); public SenderManager(JobProfile jobConf, String bid, String sourceFilePath) { taskPositionManager = TaskPositionManager.getTaskPositionManager(); From 6435df6136ebc7843a862fc2bb49d4c8d3a2821f Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 27 Sep 2021 22:29:10 +0800 Subject: [PATCH 335/763] [fix]: fix alarm notice --- .../zmops/iot/message/handler/MessageEventHandler.java | 9 ++++++++- .../zmops/iot/web/alarm/service/MessageService.java | 10 +++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java b/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java index 9e2ef18b..9d3e137e 100644 --- a/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java +++ b/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java @@ -82,7 +82,14 @@ public void onGroupEvent(SocketIOClient client, AckRequest request, GroupMessage public void sendDisconnectMsg(String userId) { if (userClient.findByUserId(userId).isPresent()) { UUID uuid = userClient.findByUserId(userId).get(); - server.getClient(uuid).sendEvent(Event.BROADCAST, "disconnect"); + server.getClient(uuid).sendEvent(Event.CHAT, "disconnect"); + } + } + + public void sendToUser(String userId,String msg) { + if (userClient.findByUserId(userId).isPresent()) { + UUID uuid = userClient.findByUserId(userId).get(); + server.getClient(uuid).sendEvent(Event.CHAT, msg); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java index c3389f26..d951ea2f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java @@ -8,10 +8,12 @@ import com.zmops.iot.domain.messages.query.QMessages; import com.zmops.iot.domain.sys.SysUser; import com.zmops.iot.domain.sys.query.QSysUser; +import com.zmops.iot.message.handler.MessageEventHandler; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.alarm.dto.param.MessageParam; import io.ebean.DB; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @@ -31,6 +33,8 @@ public class MessageService { protected final static int sys = 1; + @Autowired + MessageEventHandler messageEventHandler; /** * 发送消息 * @@ -67,9 +71,9 @@ public void push(MessageBody body) { } body.addBody("classify", sys); -// tos.forEach(to -> { -// NatsConnectionHolder.INSTANCE.getConnection().publish(to + "", JSON.toJSONString(body)); -// }); + tos.forEach(to -> { + messageEventHandler.sendToUser(to + "", JSON.toJSONString(body)); + }); } /** From 083dbdf023cfd2df2a686fa5cb56ade209244d04 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:03:40 +0800 Subject: [PATCH 336/763] [style]: add logo image --- docs/images/zeus-iot-logo.png | Bin 0 -> 13183 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/zeus-iot-logo.png diff --git a/docs/images/zeus-iot-logo.png b/docs/images/zeus-iot-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..73bdf632926405be812ed9364f86ccde7fa909c2 GIT binary patch literal 13183 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 literal 0 HcmV?d00001 From 14364baf3f72802971dfdb45d39856c13c00c040 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:05:11 +0800 Subject: [PATCH 337/763] [doc]: update readme.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index e84dce81..de83859c 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,10 @@ ![Version](https://img.shields.io/badge/version-1.0.0--RELEASE-brightgreen) [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) +

+banner +

+ ### Quick install Zeus-IoT supports Linux operating systems based on the x86_64 platform, such as Centos 7, Ubuntu 20.04, Debain 10, Kylin, and UOS. From 1075e8f46a4955336cec989a31df2aaf8aefced2 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:05:49 +0800 Subject: [PATCH 338/763] [doc]: update readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index de83859c..d5b048b2 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi)

-banner +banner

### Quick install From e7a0a76c99c3df308fedc99a7c335ee05ccffacf Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:07:32 +0800 Subject: [PATCH 339/763] [doc]: update readme.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d5b048b2..eff61604 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +

+banner +

+ ## Zeus IoT distributed collection platform [![GitHub stars](https://img.shields.io/github/stars/zmops/zeus-iot.svg?label=Stars&logo=github)](https://github.com/zmops/zeus-iot) @@ -6,10 +10,6 @@ ![Version](https://img.shields.io/badge/version-1.0.0--RELEASE-brightgreen) [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) -

-banner -

- ### Quick install Zeus-IoT supports Linux operating systems based on the x86_64 platform, such as Centos 7, Ubuntu 20.04, Debain 10, Kylin, and UOS. From 636ca0bd56a1c293aef2260702beb43f9b03a03d Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:08:01 +0800 Subject: [PATCH 340/763] [doc]: update readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eff61604..a381d3ac 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

-banner +banner

## Zeus IoT distributed collection platform From 17fa8ad7c79f7df88bbb3c79f387780b655fb4ad Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:08:33 +0800 Subject: [PATCH 341/763] [doc]: update readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a381d3ac..88c7629b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

-banner +banner

## Zeus IoT distributed collection platform From a77eb9db3a1495d42e4d1c6f5d5c1c1c82128832 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:11:20 +0800 Subject: [PATCH 342/763] [doc]: update readme.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 88c7629b..cadc383d 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,10 @@ banner

+

+Zeus IoT is the world's first open source IoT distributed collection platform based on Zabbix +

+ ## Zeus IoT distributed collection platform [![GitHub stars](https://img.shields.io/github/stars/zmops/zeus-iot.svg?label=Stars&logo=github)](https://github.com/zmops/zeus-iot) From 3b80a2d43ab3b5488cd4f46c6af09d77be183b69 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:13:22 +0800 Subject: [PATCH 343/763] [doc]: update readme.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cadc383d..753aa796 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,13 @@ Zeus IoT is the world's first open source IoT distributed collection platform based on Zabbix

-## Zeus IoT distributed collection platform - +

[![GitHub stars](https://img.shields.io/github/stars/zmops/zeus-iot.svg?label=Stars&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub issues](https://img.shields.io/github/issues/zmops/zeus-iot?label=Issuess&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub forks](https://img.shields.io/github/forks/zmops/zeus-iot?label=Forks&logo=github)](https://github.com/zmops/zeus-iot) ![Version](https://img.shields.io/badge/version-1.0.0--RELEASE-brightgreen) [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) +

### Quick install From 1765b583f8668f22256d3d05c13362a7979fbf8e Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:14:45 +0800 Subject: [PATCH 344/763] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 753aa796..529b657d 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,11 @@ Zeus IoT is the world's first open source IoT distributed collection platform based on Zabbix

-

[![GitHub stars](https://img.shields.io/github/stars/zmops/zeus-iot.svg?label=Stars&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub issues](https://img.shields.io/github/issues/zmops/zeus-iot?label=Issuess&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub forks](https://img.shields.io/github/forks/zmops/zeus-iot?label=Forks&logo=github)](https://github.com/zmops/zeus-iot) ![Version](https://img.shields.io/badge/version-1.0.0--RELEASE-brightgreen) [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) -

### Quick install From 18f883b1edfaf06907d696b9765c53cbe5035887 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:17:53 +0800 Subject: [PATCH 345/763] [doc]: update readme.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 753aa796..a1e4f3ca 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ Zeus IoT is the world's first open source IoT distributed collection platform based on Zabbix

+---- +

[![GitHub stars](https://img.shields.io/github/stars/zmops/zeus-iot.svg?label=Stars&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub issues](https://img.shields.io/github/issues/zmops/zeus-iot?label=Issuess&logo=github)](https://github.com/zmops/zeus-iot) From d5a370f77373c09ab302c06b14d079d47506eb64 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:22:51 +0800 Subject: [PATCH 346/763] [doc]: update readme.md --- README.md | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 97e14b53..b646d563 100644 --- a/README.md +++ b/README.md @@ -14,23 +14,5 @@ ![Version](https://img.shields.io/badge/version-1.0.0--RELEASE-brightgreen) [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) -### Quick install - -Zeus-IoT supports Linux operating systems based on the x86_64 platform, such as Centos 7, Ubuntu 20.04, Debain 10, Kylin, and UOS. - -- Centos7、RedHat 7 - - ```shell - curl -sL https://github.com/zmops/zeus-iot/raw/develop/docs/centos/install.sh | bash - ``` - -- Ubuntu 20.04 - - ```shell - curl -sL https://github.com/zmops/zeus-iot/raw/develop/docs/ubuntu/install.sh | bash - ``` - -访问 `http://:9090` 登录 Zeus-IOT 系统[快速开始](./docs/quick-start.rst) 。 - -假如您已经有自己的 **zabbix** 且 **zabbix** 版本是 **5.4.0+**。可以选择[自定义安装 Zeus iot](./docs/README.md) - +## Abstract +[Zeus IoT](https://www.zmops.com/) \ No newline at end of file From 0df076d105d4ad7da32dd347d7f3d9951c25476d Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:26:40 +0800 Subject: [PATCH 347/763] [doc]: update readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b646d563..99ccd0e7 100644 --- a/README.md +++ b/README.md @@ -15,4 +15,4 @@ [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) ## Abstract -[Zeus IoT](https://www.zmops.com/) \ No newline at end of file +[Zeus IoT](https://www.zmops.com/) is a **distributed IoT collection, analysis, and storage platform**, \ No newline at end of file From a0e7e369915bc5081f5a902654eb88d9c179d7d0 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:33:01 +0800 Subject: [PATCH 348/763] [doc]: update readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 99ccd0e7..ad24fab3 100644 --- a/README.md +++ b/README.md @@ -15,4 +15,4 @@ [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) ## Abstract -[Zeus IoT](https://www.zmops.com/) is a **distributed IoT collection, analysis, and storage platform**, \ No newline at end of file +[Zeus IoT](https://www.zmops.com/) is a **distributed IoT collection, analysis, and storage platform**,It is the world's first IoT open source platform based on zabbix secondary development \ No newline at end of file From 0dab4c25c5becc1edccdb500489b89bf1b0212ca Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:33:32 +0800 Subject: [PATCH 349/763] [doc]: update readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ad24fab3..8a459355 100644 --- a/README.md +++ b/README.md @@ -15,4 +15,4 @@ [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) ## Abstract -[Zeus IoT](https://www.zmops.com/) is a **distributed IoT collection, analysis, and storage platform**,It is the world's first IoT open source platform based on zabbix secondary development \ No newline at end of file +[Zeus IoT](https://www.zmops.com/) is a **distributed IoT collection, analysis, and storage platform**,It is the world's first IoT open source platform based on zabbix secondary development, all this relies on a group of engineers with rich experience in zabbix development.It is hoped that through the community’s open source ecology, continuous improvement and continuous updates will make some contributions to the development of the Internet of Things industry. \ No newline at end of file From 4956a8e70e0945bab5b4c0d5f5c626ec7559e694 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:36:34 +0800 Subject: [PATCH 350/763] [doc]: add readme.md images --- docs/images/snapshot_1.jpg | Bin 0 -> 156699 bytes docs/images/snapshot_2.jpg | Bin 0 -> 107117 bytes docs/images/snapshot_3.jpg | Bin 0 -> 130327 bytes docs/images/snapshot_4.jpg | Bin 0 -> 109003 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/snapshot_1.jpg create mode 100644 docs/images/snapshot_2.jpg create mode 100644 docs/images/snapshot_3.jpg create mode 100644 docs/images/snapshot_4.jpg diff --git a/docs/images/snapshot_1.jpg b/docs/images/snapshot_1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..030a22ef13b228062afe42010218243db1569323 GIT binary patch literal 156699 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%0De>ym3UvK!C$bsLUzK8s4IC0t` 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

Ep+@m`=sxTU)PnPbZMH zqh!U4%joprc>$7mI7oLL^|{b0I1*&*Aokq;*80c-_R+C@d71509aziY^hws935G)k zTQ?oMHTPYt<)`m2Ol&d}tc3pG@b~z?&6ngNmGcMhezvLof_E?Xop;}DF>Ci{meO|? z4BJl@OyAK33r0KQpUx}KU$o#pOqD34KQ#oLv-X%U)lxA2dq!mcr}rg)+F|^~4&;A! z>F=??KoVDvZuoO#RO<$-qE?AvFCYEW)`&Y@>XJPfBhx?Jq4DpVaL73M-wMbzB6>mc z-yR-X4F+%Ek?@nX1APO<(Fc74O??B2xtcCD@Q7TG7kmep{-jpZGU1+rORJBUb@D;hCW6x6^dz1o--6uWuf y#E<_Qh(9DfE!CvMMb5e1DbhgCZxpDj%-1LVxR+}W@6_RxEBz+!_4De#&HgWM>iD$) literal 0 HcmV?d00001 diff --git a/docs/images/snapshot_2.jpg b/docs/images/snapshot_2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9f41a22f83208557460dd5a591f112c60cea3b39 GIT binary patch literal 107117 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 z z0nI(p*Hk;Cf`reu0lA%NtD-AC!KQsu6!q3h(e152jeN9d@- zQzwTiIn>vRx+r{iE2da{Ynk{hOv-Rra=+I}l9}TN9fBI%@gKn*nk=R)-%3;d-mVK? zFCQK#vtCWy>{<&7XgyNS_eqo8$i3bNmHT2S5DUeimJ^~HCIVy-8yIF?RX|aKj41xT z4byrlT6tcsir1RxCIt&Ui@z4mAexh%{T0Z`ci~(5tM~OWznpk$J>R@M|1eOQ9(-fN z(!Dj@Z(eaq~4j)hp#x>ba!|@9E=OI zvvgl78s!76NT&AB+6H8;UZ`pnlTH?~11cMb7LV?Iw}4Zb>&{xW-tcAF2(Zdh9w@~!`^^eJ zZkR-Uycz0vA0FzL=79?0UjVvKfcGQrsUZGO19U2g|49P>j|${MR1p7j!21#i{@uU( z1Be>|es&MTf`XPeDj6VsO^t+^AO%<;dF?VDKZHp!3|T`#5lWdCQ$NKw)(%Y5WFr@CkQR-s67*zx%q! literal 0 HcmV?d00001 diff --git a/docs/images/snapshot_3.jpg b/docs/images/snapshot_3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7eea22b9bd07f08112c3a458197b2bf59cf3edef GIT binary patch literal 130327 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 literal 0 HcmV?d00001 diff --git a/docs/images/snapshot_4.jpg b/docs/images/snapshot_4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..691ceb7ec51911404a1e414d8414a028e4fedc38 GIT binary patch literal 109003 zcmeFa2UJwcwkW!wfhGw8t)wPM&WJRUnj{jHoRo~9B+04CNkEYt70DS95Xk}pg5(SW zl5<9~WOxhqKKtx*?|JXO^Z&o&-uuVKv3gZk%~`9e)~uPUy%@Qe2CmCX%Si)hXlQ^T z_z$=k10(@#EG#G%CN>lb#lgYG#fM$P$HT)XCnh0;QBlxPQ&GU-vH#8b3<{_t1dR?r zCqjb|pwON4FW;OfM8-`V1Uq`U^{?8 zgh_mhM*@pP#Ry7g2fO1NnTAb&uejlcYTp(E?-P4J9Ne3vWaJc#Ow25-YzV%)`~reP zlJ}*gWn|^#)zmdKwH`gzHa2!oktW*#+h5=KmrfFzDs0;Hc=B*tqyNZxhlp zGPAOCa`WDQDk&{1uc)m0{I#*^TXRcmTYLY&;P;{7ksqTovvczci%ZKZtJ^!fd;7l* z4v&s6=YM5t=J)?-W`9iV@ADc3@F8g6%YzUBV!(km zOL{2-OL{QCk}bz!o93#gBBN>S!}i{iLiZC!xN3=u$PH6f?<78Q5mmhO4HzUcQi>Lr zCEe$*>;GqK@H~n`1sP_WoAqiBJxRUnrAcKU_sr`vlem65Px%PeZ_EsDl3#9n-$V`R z$tXMFZxEN$zfuIK&-b&^Q2M*NTStS_wx0qG=|r}dErR?@6_^elM~yv_tP1+s_S~a> zhkf+JhmFz`_42Y%<5yTWq&x}uVISi%q_n5(8l_Xpbo)(XmM3`z9bNHBNRTXJ+Jb~^ zGWwQ%rQXEmqwR!r$|WwZ4vq9xW~

i`~>0Zc-H-`Lx||P(Xu+a#yRV^ZSV~GYoAc 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°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 J2laFIe*hx|w&nl; literal 0 HcmV?d00001 From 77513e96ac5f668d63cee154683a8698c1679e27 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:39:43 +0800 Subject: [PATCH 351/763] [doc]: update readme.md --- README.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8a459355..cfb188ac 100644 --- a/README.md +++ b/README.md @@ -15,4 +15,24 @@ [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) ## Abstract -[Zeus IoT](https://www.zmops.com/) is a **distributed IoT collection, analysis, and storage platform**,It is the world's first IoT open source platform based on zabbix secondary development, all this relies on a group of engineers with rich experience in zabbix development.It is hoped that through the community’s open source ecology, continuous improvement and continuous updates will make some contributions to the development of the Internet of Things industry. \ No newline at end of file +[Zeus IoT](https://www.zmops.com/) is a **distributed IoT collection, analysis, and storage platform**,It is the world's first IoT open source platform based on zabbix secondary development, all this relies on a group of engineers with rich experience in zabbix development.It is hoped that through the community’s open source ecology, continuous improvement and continuous updates will make some contributions to the development of the Internet of Things industry. + +The following screenshots give a close insight into Zeus IoT. + + + + + + + + + + + + + + + + + +
Home ScreenDevice Resources
Realtime DataSystem Users
\ No newline at end of file From c5853fee62731a94bc7bf04486b42888b2137fa4 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:44:36 +0800 Subject: [PATCH 352/763] [doc]: update readme.md --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cfb188ac..f83f2121 100644 --- a/README.md +++ b/README.md @@ -35,4 +35,8 @@ The following screenshots give a close insight into Zeus IoT. - \ No newline at end of file + + +## Demo Environment + +Using the account `Admin / zeus123` to log in the [demo environment](https://zeusdemo.zmops.cn/). Please note the account is granted view access. \ No newline at end of file From 24f94b27f4bb2d086b4aba5cb0df03e24a3ef73c Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:54:49 +0800 Subject: [PATCH 353/763] [doc]: update readme.md --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index f83f2121..7d8a68f8 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,13 @@ The following screenshots give a close insight into Zeus IoT. +## Technology stack +- Basic components: Zabbix 5.4+ +- Database: Postgresql 12+ +- Webapp: SpringBoot 2 + [Ebean](https://ebean.io/) + Vue Element + Socket.IO +- IoT Server: Apache Camel 2.2 + Modular design +- Visualization: Grafana 8.0+ + ## Demo Environment Using the account `Admin / zeus123` to log in the [demo environment](https://zeusdemo.zmops.cn/). Please note the account is granted view access. \ No newline at end of file From 124d6508b8554b35364538d43d1009d74c8a7338 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:56:05 +0800 Subject: [PATCH 354/763] [doc]: update readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7d8a68f8..15387708 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ The following screenshots give a close insight into Zeus IoT. ## Technology stack - Basic components: Zabbix 5.4+ -- Database: Postgresql 12+ +- Database: PostgreSQL12+ - Webapp: SpringBoot 2 + [Ebean](https://ebean.io/) + Vue Element + Socket.IO - IoT Server: Apache Camel 2.2 + Modular design - Visualization: Grafana 8.0+ From 851fc5f1d46d0d250bfe363172b82fa7205571b1 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:58:02 +0800 Subject: [PATCH 355/763] [doc]: update readme.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 15387708..10ca4d98 100644 --- a/README.md +++ b/README.md @@ -39,9 +39,9 @@ The following screenshots give a close insight into Zeus IoT. ## Technology stack - Basic components: Zabbix 5.4+ -- Database: PostgreSQL12+ -- Webapp: SpringBoot 2 + [Ebean](https://ebean.io/) + Vue Element + Socket.IO -- IoT Server: Apache Camel 2.2 + Modular design +- Database: PostgreSQL12+ , TDEngine 2.2+ +- Webapp: SpringBoot 2 , [Ebean](https://ebean.io/) , Vue Element + Socket.IO +- IoT Server: Apache Camel 2.2 , Modular design - Visualization: Grafana 8.0+ ## Demo Environment From 3e51c7dacf9d54e79046b510d313787c7660c5a6 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 00:59:50 +0800 Subject: [PATCH 356/763] [doc]: update readme.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 10ca4d98..7f5fd206 100644 --- a/README.md +++ b/README.md @@ -38,11 +38,11 @@ The following screenshots give a close insight into Zeus IoT. ## Technology stack -- Basic components: Zabbix 5.4+ -- Database: PostgreSQL12+ , TDEngine 2.2+ -- Webapp: SpringBoot 2 , [Ebean](https://ebean.io/) , Vue Element + Socket.IO -- IoT Server: Apache Camel 2.2 , Modular design -- Visualization: Grafana 8.0+ +- Basic components: **Zabbix 5.4+** +- Database: **PostgreSQL12+ , TDEngine 2.2+** +- Webapp: **SpringBoot 2 , [Ebean](https://ebean.io/) , Vue Element + Socket.IO** +- IoT Server: **Apache Camel 2.2 , Modular design** +- Visualization: **Grafana 8.0+** ## Demo Environment From fc9500746eb5037f34216f185ccc4d258a0005f7 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 01:00:49 +0800 Subject: [PATCH 357/763] [doc]: update readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7f5fd206..2834fd51 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ The following screenshots give a close insight into Zeus IoT. ## Technology stack - Basic components: **Zabbix 5.4+** - Database: **PostgreSQL12+ , TDEngine 2.2+** -- Webapp: **SpringBoot 2 , [Ebean](https://ebean.io/) , Vue Element + Socket.IO** +- Webapp: **SpringBoot 2 , [Ebean](https://ebean.io/) , Vue Element , Socket.IO** - IoT Server: **Apache Camel 2.2 , Modular design** - Visualization: **Grafana 8.0+** From 6f4ae39ce2063a3407cc390711485aecad2a3b33 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 01:07:29 +0800 Subject: [PATCH 358/763] [doc]: update readme.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 2834fd51..4d68329d 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,12 @@ The following screenshots give a close insight into Zeus IoT. - IoT Server: **Apache Camel 2.2 , Modular design** - Visualization: **Grafana 8.0+** +## Features +

+ 🕸 Based on zabbix secondary development + Based on the powerful distributed capabilities of zabbix, cross-regional collection can be realized +
+ ## Demo Environment Using the account `Admin / zeus123` to log in the [demo environment](https://zeusdemo.zmops.cn/). Please note the account is granted view access. \ No newline at end of file From 2b7f8e567c2c01376ad3bdfdc3bc8079e1abdef7 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 09:39:25 +0800 Subject: [PATCH 359/763] [doc]: replace logo --- docs/images/zeus-iot-logo.png | Bin 13183 -> 32255 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/images/zeus-iot-logo.png b/docs/images/zeus-iot-logo.png index 73bdf632926405be812ed9364f86ccde7fa909c2..c7c554f0ce9cb1468a4d6ebb1d101a8b65293c49 100644 GIT binary patch literal 32255 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 From 26d59a088b117c86d68dd42ea9b213394885b884 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 09:44:13 +0800 Subject: [PATCH 360/763] [doc]: update readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4d68329d..c4355c41 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

-banner +banner

From 17530c2b03b44420212995ed826fe45ae0161ddd Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 09:47:09 +0800 Subject: [PATCH 361/763] [doc]: replace logo --- README.md | 2 +- docs/images/zeus-iot-logo-1.png | Bin 0 -> 54301 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 docs/images/zeus-iot-logo-1.png diff --git a/README.md b/README.md index c4355c41..8567a0c9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

-banner +banner

diff --git a/docs/images/zeus-iot-logo-1.png b/docs/images/zeus-iot-logo-1.png new file mode 100644 index 0000000000000000000000000000000000000000..c675c634ddd702b339e586b526d816d475e17803 GIT binary patch literal 54301 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 r% Date: Tue, 28 Sep 2021 09:49:47 +0800 Subject: [PATCH 362/763] [doc]: update readme.md --- README.md | 2 +- docs/images/zeus-iot-logo-1.png | Bin 54301 -> 61290 bytes ...{zeus-iot-logo.png => zeus-iot-logo-2.png} | Bin 3 files changed, 1 insertion(+), 1 deletion(-) rename docs/images/{zeus-iot-logo.png => zeus-iot-logo-2.png} (100%) diff --git a/README.md b/README.md index 8567a0c9..33dcd3e7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

-banner +banner

diff --git a/docs/images/zeus-iot-logo-1.png b/docs/images/zeus-iot-logo-1.png index c675c634ddd702b339e586b526d816d475e17803..b219ed98a82cc58482aff1e564db8dee861524bc 100644 GIT binary patch literal 61290 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≈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 L^GkucWyt>n9VL06 literal 54301 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 r% Date: Tue, 28 Sep 2021 09:51:57 +0800 Subject: [PATCH 363/763] [doc]: update readme.md --- README.md | 2 +- docs/images/zeus-iot-logo-2.png | Bin 32255 -> 0 bytes docs/images/zeus-iot-logo.png | Bin 0 -> 33191 bytes 3 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 docs/images/zeus-iot-logo-2.png create mode 100644 docs/images/zeus-iot-logo.png diff --git a/README.md b/README.md index 33dcd3e7..c4355c41 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

-banner +banner

diff --git a/docs/images/zeus-iot-logo-2.png b/docs/images/zeus-iot-logo-2.png deleted file mode 100644 index c7c554f0ce9cb1468a4d6ebb1d101a8b65293c49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32255 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 literal 0 HcmV?d00001 From e59bd46b2c7d88a584e345b79a5395e4cd4a3bc4 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 09:52:58 +0800 Subject: [PATCH 364/763] [doc]: update readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c4355c41..4d68329d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

-banner +banner

From 17e9ba218eebcdc14a7cb1cef2051accd8197669 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 28 Sep 2021 10:15:12 +0800 Subject: [PATCH 365/763] [fix]: fix role menu --- .../web/exception/enums/BizExceptionEnum.java | 1 + .../iot/web/sys/service/SysRoleService.java | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index d4927d4e..a21209c7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -54,6 +54,7 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { ROLE_HAS_BIND_USER(602, "角色绑定了用户,请先解除绑定!"), MENU_NOT_EXIST_OR_NO_PRERMISSION(603, "菜单不存在或无权授权此菜单"), ROLE_NOT_EXIST(604, "角色不存在"), + CANNOT_MODIFY_OWNER_MENUS(605,"不能修改自己所在角色的菜单"), /** * 账户问题 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java index f0427aa9..18767935 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java @@ -94,6 +94,7 @@ public void delete(RoleParam sysRoleParam) { */ @Transactional(rollbackFor = Exception.class) public void bindMenu(RoleParam roleParam) { + checkRoleId(roleParam.getRoleId()); checkMenuId(roleParam.getMenuIds()); new QSysRoleMenu().roleId.eq(roleParam.getRoleId()).delete(); List sysRoleMenuList = new ArrayList<>(); @@ -106,6 +107,16 @@ public void bindMenu(RoleParam roleParam) { DB.saveAll(sysRoleMenuList); } + private void checkRoleId(Long roleId) { + LoginUser user = LoginContextHolder.getContext().getUser(); + if (null == user) { + return; + } + if (user.getRoleList().contains(roleId)) { + throw new ServiceException(BizExceptionEnum.CANNOT_MODIFY_OWNER_MENUS); + } + } + /** * 检查授权的菜单 是否存在或是否有权授权此菜单 */ @@ -156,11 +167,11 @@ public List bindedMenu(Long roleId) { " LEFT JOIN sys_menu m2 ON m1.pcode = m2.CODE " + " WHERE" + " m1.status = 'ENABLE' " + -// " AND " + -// " m1.menu_id in (select menu_id from sys_role_menu where role_id in (:roleIds) )" + + " AND " + + " m1.menu_id in (select menu_id from sys_role_menu where role_id in (:roleIds) )" + " ORDER BY" + " m1.sort ASC"; - List allMenuList = DB.findDto(TreeNode.class, sql).findList(); + List allMenuList = DB.findDto(TreeNode.class, sql).setParameter("roleIds", user.getRoleList()).findList(); //取被授权用户 已授权的菜单 List selectMenuIdList = new QSysRoleMenu().select(QSysRoleMenu.Alias.menuId).roleId.eq(roleId).findSingleAttributeList(); From 243b95bb4d39973561ca33b9753cb8dadd01d3c7 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 10:26:33 +0800 Subject: [PATCH 366/763] [doc]: update readme.md --- README.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4d68329d..51f9e694 100644 --- a/README.md +++ b/README.md @@ -46,9 +46,25 @@ The following screenshots give a close insight into Zeus IoT. ## Features

- 🕸 Based on zabbix secondary development + Based on **zabbix** secondary development Based on the powerful distributed capabilities of zabbix, cross-regional collection can be realized
+
+ Based on **Apache Camel** as the pre-routing rule + Very powerful rule-based routing engine, supports 300+ module access, including IoT protocols, born for low code; one line of code can start the protocol service interface. +
+
+ Use [**TDEngine**](https://www.taosdata.com/) for time series data storage by default + An ultra-high performance distributed database designed and optimized for time series data. +
+
+ IoT Server is developed with a **modular architecture** + IoT Server adopts the [Skywalking](https://github.com/apache/skywalking) modular architecture design, which can dynamically configure and enable modules, which is very easy to expand; at the same time, combined with the multi-point collection of Zabbix Proxy, a modular cluster can be implemented well. +
+
+ Natural distributed collection architecture + Thanks to Zabbix's excellent architecture design, it has natural distributed collection capabilities, can be well horizontally expanded, and has the ability to cross-region and cross-network collection +
## Demo Environment From 9150c1f62aed9f6a42427caf251721a6e4f5d4f6 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 10:27:47 +0800 Subject: [PATCH 367/763] [doc]: update readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 51f9e694..fa37f9fe 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ The following screenshots give a close insight into Zeus IoT. Very powerful rule-based routing engine, supports 300+ module access, including IoT protocols, born for low code; one line of code can start the protocol service interface.
- Use [**TDEngine**](https://www.taosdata.com/) for time series data storage by default + Use **[TDEngine]**(https://www.taosdata.com/) for time series data storage by default An ultra-high performance distributed database designed and optimized for time series data.
From 78b6751544b5bee6def2c32efd53d029832ae3de Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 10:28:21 +0800 Subject: [PATCH 368/763] [doc]: update readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fa37f9fe..19eb238d 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ The following screenshots give a close insight into Zeus IoT. Very powerful rule-based routing engine, supports 300+ module access, including IoT protocols, born for low code; one line of code can start the protocol service interface.
- Use **[TDEngine]**(https://www.taosdata.com/) for time series data storage by default + Use **[TDEngine](https://www.taosdata.com/)** for time series data storage by default An ultra-high performance distributed database designed and optimized for time series data.
From 749f592bb3b9880bf0c328419aebcdd4a45d1e21 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 10:29:44 +0800 Subject: [PATCH 369/763] [doc]: update readme.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 19eb238d..12c0c565 100644 --- a/README.md +++ b/README.md @@ -46,19 +46,19 @@ The following screenshots give a close insight into Zeus IoT. ## Features
- Based on **zabbix** secondary development + Based on zabbix secondary development Based on the powerful distributed capabilities of zabbix, cross-regional collection can be realized
- Based on **Apache Camel** as the pre-routing rule + Based on Apache Camel as the pre-routing rule Very powerful rule-based routing engine, supports 300+ module access, including IoT protocols, born for low code; one line of code can start the protocol service interface.
- Use **[TDEngine](https://www.taosdata.com/)** for time series data storage by default + Use [TDEngine](https://www.taosdata.com/) for time series data storage by default An ultra-high performance distributed database designed and optimized for time series data.
- IoT Server is developed with a **modular architecture** + IoT Server is developed with a modular architecture IoT Server adopts the [Skywalking](https://github.com/apache/skywalking) modular architecture design, which can dynamically configure and enable modules, which is very easy to expand; at the same time, combined with the multi-point collection of Zabbix Proxy, a modular cluster can be implemented well.
From 65effb18a34cd9102499a60522ad31106cb71ef5 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 10:30:22 +0800 Subject: [PATCH 370/763] [doc]: update readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 12c0c565..ce70968c 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ The following screenshots give a close insight into Zeus IoT. Very powerful rule-based routing engine, supports 300+ module access, including IoT protocols, born for low code; one line of code can start the protocol service interface.
- Use [TDEngine](https://www.taosdata.com/) for time series data storage by default + Use [TDEngine](https://www.taosdata.com/) for time series data storage by default An ultra-high performance distributed database designed and optimized for time series data.
From a86e378a4b3263a7b06b93599560362c4815e05e Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 10:31:33 +0800 Subject: [PATCH 371/763] [doc]: update readme.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ce70968c..0a4be502 100644 --- a/README.md +++ b/README.md @@ -54,12 +54,12 @@ The following screenshots give a close insight into Zeus IoT. Very powerful rule-based routing engine, supports 300+ module access, including IoT protocols, born for low code; one line of code can start the protocol service interface.
- Use [TDEngine](https://www.taosdata.com/) for time series data storage by default + Use TDEngine for time series data storage by default An ultra-high performance distributed database designed and optimized for time series data.
IoT Server is developed with a modular architecture - IoT Server adopts the [Skywalking](https://github.com/apache/skywalking) modular architecture design, which can dynamically configure and enable modules, which is very easy to expand; at the same time, combined with the multi-point collection of Zabbix Proxy, a modular cluster can be implemented well. + IoT Server adopts the Skywalking modular architecture design, which can dynamically configure and enable modules, which is very easy to expand; at the same time, combined with the multi-point collection of Zabbix Proxy, a modular cluster can be implemented well.
Natural distributed collection architecture From c40f84137fe5c81aeca6060f7c4498efa5949c17 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 10:47:14 +0800 Subject: [PATCH 372/763] [doc]: update readme.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0a4be502..6dd3c401 100644 --- a/README.md +++ b/README.md @@ -46,23 +46,23 @@ The following screenshots give a close insight into Zeus IoT. ## Features
- Based on zabbix secondary development + 🏆Based on zabbix secondary development Based on the powerful distributed capabilities of zabbix, cross-regional collection can be realized
- Based on Apache Camel as the pre-routing rule + 🥇Based on Apache Camel as the pre-routing rule Very powerful rule-based routing engine, supports 300+ module access, including IoT protocols, born for low code; one line of code can start the protocol service interface.
- Use TDEngine for time series data storage by default + 🥉Use TDEngine for time series data storage by default An ultra-high performance distributed database designed and optimized for time series data.
- IoT Server is developed with a modular architecture + ⚔️IoT Server is developed with a modular architecture IoT Server adopts the Skywalking modular architecture design, which can dynamically configure and enable modules, which is very easy to expand; at the same time, combined with the multi-point collection of Zabbix Proxy, a modular cluster can be implemented well.
- Natural distributed collection architecture + 🏹Natural distributed collection architecture Thanks to Zabbix's excellent architecture design, it has natural distributed collection capabilities, can be well horizontally expanded, and has the ability to cross-region and cross-network collection
From 1192f3077874f1f9d23df89f4ef3b093039d63a2 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 10:49:38 +0800 Subject: [PATCH 373/763] [doc]: update readme --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 6dd3c401..b0bbf305 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,9 @@ The following screenshots give a close insight into Zeus IoT. Thanks to Zabbix's excellent architecture design, it has natural distributed collection capabilities, can be well horizontally expanded, and has the ability to cross-region and cross-network collection
+##Architecture + + ## Demo Environment Using the account `Admin / zeus123` to log in the [demo environment](https://zeusdemo.zmops.cn/). Please note the account is granted view access. \ No newline at end of file From 071dceadb8433b07e4b41bfe9bec9c2dc1b5ceee Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 10:51:07 +0800 Subject: [PATCH 374/763] [doc]: update readme.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b0bbf305..77889203 100644 --- a/README.md +++ b/README.md @@ -66,8 +66,11 @@ The following screenshots give a close insight into Zeus IoT. Thanks to Zabbix's excellent architecture design, it has natural distributed collection capabilities, can be well horizontally expanded, and has the ability to cross-region and cross-network collection
-##Architecture +## Architecture +## Installation + +## Latest Release ## Demo Environment From 3be1424a940994119fc8978db4db14e4d26a9a00 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 10:57:33 +0800 Subject: [PATCH 375/763] [doc]: update readme.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 77889203..ab33b279 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ The following screenshots give a close insight into Zeus IoT. ## Features
🏆Based on zabbix secondary development - Based on the powerful distributed capabilities of zabbix, cross-regional collection can be realized + Based on the powerful Zabbix for interface secondary development, with industrial-grade stability and powerful performance.
🥇Based on Apache Camel as the pre-routing rule @@ -55,11 +55,11 @@ The following screenshots give a close insight into Zeus IoT.
🥉Use TDEngine for time series data storage by default - An ultra-high performance distributed database designed and optimized for time series data. + TDEngine is an ultra-high performance distributed database designed and optimized for time series data.
⚔️IoT Server is developed with a modular architecture - IoT Server adopts the Skywalking modular architecture design, which can dynamically configure and enable modules, which is very easy to expand; at the same time, combined with the multi-point collection of Zabbix Proxy, a modular cluster can be implemented well. + IoT Server adopts the Skywalking modular architecture design, which can dynamically configure and enable modules, which is very easy to expand; at the same time, combined with the multi-point collection of Zabbix Proxy, a modular cluster can be implemented well.
🏹Natural distributed collection architecture From da161c5cc132aa12ff2f8251ead9a8eebf5f68a1 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 11:07:34 +0800 Subject: [PATCH 376/763] [doc]: update readme.md --- README.md | 6 ++++-- docs/images/arch.gif | Bin 0 -> 1422544 bytes 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 docs/images/arch.gif diff --git a/README.md b/README.md index ab33b279..aa57d803 100644 --- a/README.md +++ b/README.md @@ -68,9 +68,11 @@ The following screenshots give a close insight into Zeus IoT. ## Architecture -## Installation +![Architecture](docs/images/arch.gif) + +--- -## Latest Release +## Installation ## Demo Environment diff --git a/docs/images/arch.gif b/docs/images/arch.gif new file mode 100644 index 0000000000000000000000000000000000000000..3560508ab35ae7653a016c26125bbcba3f25b307 GIT binary patch literal 1422544 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%0DID{5FSb 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

pB4^#Y&$20gsaTcRu|tBzN! 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ϑ$KMhV}VW8wmCOP2dZCHDha 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

n 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

{}|O_nlJ)@ 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%0A7)X6=HCL+Z+!(tr~ib zALG@Fhik3;aA981zRcNN-ibsVdeHU6c2pq*|8ayKTHpH$4brpd=M-jal1IZ}V%eqW zjdC*UYCd$_(QK@9JBwh)cY$)T4EMwfD9R2KceWejlA$la;dobk**o=YVL!pom{XG} zB9k&Y1rU_d3o1`@VNf&dO;T|=(G4UYKCYFx`P9Tab+{lESf`@40u-=o2v-&J^=RY~0>8JdjJwxkBPxdUJ^8;*eG zg@QyW&QGQyo$ov@>z)rO#wjbiF~lJAjz2;%64^WD2c)^C`1^U?jzx9eJ)QQx)t)%- zvD>>#9P!~$-quWa)l+BXofClbXPfYWm4_Pw&A(IzEEanlV7K)~`j`eC)FGRdhvP&HoJ~E}) zoR2~#NN}f?`QDmxg&fe1q)S3YXJhD?B787b-0Pf#+z(+DRwge*16`sJ8b9=b7f=}S*a5z5h@y;=_pz!D)6u(O6jyyiOQtDA zUTiDML^tUdYOy8odZFYsA^%5};@3pu27KdJvR)tdF%WSw02tHfF$^ClUv7TIo*O;H zoFBu&LOmQZo$$A^OT`GIVI!xL3z+rJ#AP+%`DiBlvdB9dy?1M; z3r^mrD<=miw8z$k3?Jhilf}?VEvX+YqdsAuPSk2DWt^$th9bw3c(~6kL#OCeN0a=X zgjybbeKZHJHua->5uZ7^Qo&+P(J3?rL%A9y#mE9TRrOK5q|H@2E9yGKK`fOs(N)<| zxV98Cmrk>tcCK+!q1dtYoy_Hs)TOMn(D!5WGElNqtR7stuhxOmORljds@Y24(S3dV zWL0*(QmN41JT>HGc5%U&rAp?T6Q=o=d~> z_k?#HNFF5)3ybqPlkxTKsYg(4FQVl}y{t}2!!tp~r!}zKT{qdzo)1su*Jokp+Lv+G z!E(#GX#K3+m-(AYZoMIDEKF2A3#kp!+m>Xn z|9n&VjZsq%!I+?5WUMMqKyq6;#<^QD&)PnXew$dpWr$e%V`Tlv4x5kjK)Pj_ncEQx zbNoVAA)q?>c4QYEpjRk~R~;?lX7usbt1_1x+lhiaW>v?U9BQe3agB$`gt3}D zb`ohc-Is6~7_|kkmR0$Hq^Sbw+9H)vvs5}HBtA&wYYnMG^*@w=Bh7~O;V{phik+fvzrM_+xv)QN5K z2dY$zb?-IIylG9{JEai|Lfp{Q37M<;covqI4`1- zpSEaVlzOp4o;b-$@mi+Q>q{P zvY+oireKT~Xryi`^l#FZk2yq0=p$l6@*0|@Z$dx&%;~>1T$r;uSLt_+(KBvdCbIHH z)V%}>Cp52?YO@p^|2`FC*K5xK+(ElAe}4w8#REVFcYV;OPxzwT0I;>!F30l)H&g~; zD+<`B|9r{OkM)uT{4n_|1-a*A>w(Jn!)){Obwxz$k+IC<;u5U&X1w*pDgETjS_S~T z_S+H_;={Tbhm6kzIWy))B16-KcT;;-%bWlK!RzA5a zh*-DR{euk{&i>cqHajCZ85St5$Fn#As}rt*aZGYe7wF>XIdY8ztL_r7Ao@uS;a5WA zCj;NvSvV!V8PJFn<_k>e{!;~|RV zD|061&o3fE;Kz?EVrM{dl;by~=chWL>Fva%Lg3HN>QAKLzvJuQ|JA?pniy-ECvMl@ z_>S-C%@;EoX=~>IJJEm?N_cL-7xWIef%O2ETq3V|9^XBmy({7%B!G`K!ob5u8FSkLRZ~}zY5R5$odesqlnFB`%2x&+N zX=(^*nGb2Z3+W&Th3!rCsD}1AhYlo!4mE_1%!iKMg-#HJO>%@ytA@=whs`I1EjENL z&xftvg{={UZ*V}vw^YM-oWu7L!Ven4kLJTq?!wPtmOLdAIuj_cBTN_#~3grS>8v|fZ_H%1g!cp$5N zopHuA$;X^mMH9pF4xaT~JR^3fiJWrwdaxxXYWOjH=hf#$E|w>qB@#WT|NZU`QIZJ= z#{_uU0sf#G*2WeiW!$KAkA_@cKI}(OA5+J6bj(XG|BE4SA{yFKmm=ft{xZ;q3wJ%L43W&t4 zlWG-WH+quFXoJQ~fVkGl^)7I-08oZ04cZzcc>hyYbfOn+3c*HvpIDOHC-jw{PW~65 z9x<7MyD+)6=!zieZ0FRGK=e^lCPp%X6EHmH1pme!0AT1eJ&-Ejkvw#fEQ$qpL6Gj< zn<8_TnE5H`Lk8%gF@4AZfBp*0i|qF_nEw4!Dx7NuQc?y=QwG{%1_tb4C(Oj=%*0X8 z#BN1}E&A^Ng1xK$ydjpCjm+BTJYoPZyRT8_{H+n>qn} z>6J^`Ynm_t)KWC*5si`}qxsR33z;He49YvpH(fplo4ZC%&C8Gfhz9iJVNAt-ER1%h z%a0SzcXQ3pt%!fH1;Wb$@H;-Z)3N%w76geW%g+@Ax)LuYhRIt4zrF&*;-_9Z7A7_o zzS}KSM=n}3iC?^m0~!}C_!hm(FH#SRS))mKrYffC_g@!fb?h%Z_b)a`v~4LWwo@s* z5F)X?B!LQ-$m*BS29zjeml)#1<1&F(tqmAV!NM6{K$X(Dq7;h!()lLGaV%)*l&itQ zC+qD++uetf@s8NdB*PaF5F$PZpUjSo3}nlWj!jm&a+ck~fxgjHuC5$`fC#VNR6xC# z3tkdhqeH)6EE6(9QZ}p5P^`dy{1J1Li&9*+UQ|A8XpkTa>Q$+vQxtY4uX>kgIsY6pa zQ4n~4H*bw}br@f-_4lsx6=@|?7Ur|AzsG~;I;&yGC#s%m)eIn(3aQB{PFddz{LIt+#SehA+{kM=%K!t#GS*wA_=McM>Iz4^cQ*eCQ{=Js$L^^lYx3j@D=n^_`x>&=SCQXm+v189DCaQJ*YDr&vg~TT++P`>{~c|h zNTlC4)W!e%K=`d@P|1L6|G-91L%61M824aBK#Y{`V5Ko}V#%PVNShRFqUvdIw?{Uc zeaKCuZQFjRfZM5Pc__z1+Ie}fLesHabGR&2+W9-U;mO5kd00!NwH<9lg?eN~aJZ+% zzCLB7(_&;K)TR4rWQe|d8E15|#0drpz$k(J7#Ju3byy7@S)dsFr8zcuG`cfl6T9qL z6*{)RY{N+}Ta^;x&j%n+X8M2t&jkVC+Sr_<$uH24%?plw(Hy@Wd9Rr_{-lW|Qa@&u zfP6zQaPEiv*n)aWZ=8Vj)8*kSPU}Pz&;~j(c1tngDGRq$1BSPpczJ2$FZ&a7-3G%_ z=Hy9Av=Iz$b;EL>n2MS}Db;^aE+p5|#Z{V;#G1+oK$f2XNt{I!M~yE+zG)#(3R#yEzMDh$wV-3WIfM&md z4uwJDWOMeGbK;S3=Ek54!O4AtDK1*~@efcCf-VgL6KKxdGN^SPFfkv2Zm$$3<+~yk zT0Fyzhba_~=C?2}uDdv6e+)x)q)dO}4^h}7=KJ}~Dl?VpN0P3%dOQG1R6CWI_& z#t-y_tx%fR%DkG!cefUH|FzT8uvoZ)>R|&PF1_%(`emE#&2PlSQ7NHR#kI_}R}9v> z$Lj|?(qhRqen&L6xsXG5UsXo>eopaVtyBH^{;Kc-`(8s9nr3wQD(4dYo1-Z+FVe~dz~p2T7a&F zVaHY`Ww?l@AqF#4?M2l zm*w3tq>EOMaN`H1CTNCm(KW50$0UeHkTC%|44GAJ8_5n?rSLV7_6cSDv6iEu(%1=A z{4rwLNwd|@i)ZVTwvFzJCj7)xG?CN7XG6-+H2~D+k+&wv5DT&0`kMe6`p#Y`(mwj> z88U-a`j>NDsC8EO22tKQ(diNV=kxMaRB|2bv#wXSlrsb#7k~g^oL59ECl|Pg2QA?~ zSr`{A-^%chd|s7faiv>N8lHXmWkb=qil%kdAG~>9c16~&I8b^itz-S#Zs#}m^>4Og zukdRbMqJI)Z`#mnwec-IMq6pQn*_(33wvx6OxxGJXO`pNzA>WNVBVFZf_9Cyiaf6Am3dGL+_YO@6P=1pk;RteRq{7cNbK5F_`zg4EMJP$6^up4|S(h zFQjCMBn&hRJ5g$_2|v`uN7k z%@n8>>#P`Y<=YI)|pRAb%jv3Bn!y8k6+_XJeSs| zxfjPpb;lbM`9fjRzxOK@JTu6P##$4)6y%w_#`lQDZ!a6!vUSGWS|4GQz;L=ud)x2F zlbnOz@%BHI0B7zmMHnRjTiu|d3H3l>+k;U8!gq+G*vcmBegrT|0H(X{t#duP|3e8l zV|r2jzfuB`f_N}WK$NNwMhUR(Z^0-5+U*!cWf&!(YE-x#r)jIa8n5f$C>L)Kr*1Y06n730<)=*s4p4`xrQ{I_d(OFc}U0Od-*#w(T7;0$gY3dwp>i*;HG#nhZ zpPqGe5A+X@cl1xf?46#`g~9Rp(W&K$xs92nt@-86<+YvF%{`cnv%Pn;cW|<~d-gZT z`Pa!g|Ig~d)9?SktRDR9CF*D_chI@x%du2zuM<-`yl4chchsdax zeyy!lTg(Q^ivYPP7OFLh(u`>hNUQ1Ck<7ZOfhJ5 z-uQs(ETA((S~rNRV;r%jI=-NcAf<-ish2B%j1QmhPd^5 zRTh&Mh`7=2Ykl(PaXMZGQjFrSxu-c>-#H^x4WY#Yoj@3*1Mi}hL&3ynxy;R4u$ z)6fV`ltKgMDS`!xh?MIa617#OPqY5`9(I&mufu8bnBRmCPMVFh6J0yKs`R1_L?uS(`adiuZM6L>%7Rn^+t2jcTgw;3^vj(=_J{5ClO5kBlOP^SA z>ASLbj7ki3sC-pJgu}iterVXL`S-&+xmLjEVuQR`tPyiq$??Nrom{LLu`xi; z@}(+)(W~>Hlzsuqy|0G-Y^D}dibj&mH>#&R0!4rH3}aKAmlO;1x@FI5x*dPaZnG?{ zUSJmyxLH)JBavG)?Eh_^{|(WSttVA|=S7~f%cpa3NrAB0DSwr>4miiDZnodejO2;2 zMZqSUsV!34jic=5WxBg{a?g#+ST19ql#G-09@4ec3a>;lFfkqv--&$yzv!csCfsQH z2In$EH*||>m%ZzRvLp3^nq+?-$Jl9U2sfVdvYrOok~wd*{p8?@n6`hbW|oi%HL5Dt zUwT=)z3QgkQr_Op8qR*wL+WXv3;lh!TMm6DnjVM!E{%}>w)pTF3V#N<`A7!Br|I}S z@9lvW3Y&%I=s={i_9ht71(DnlBblA~5R~XL^R0iuO0xF4dfV?L?%aj<{0;K{>sM69 zy)K+FLz_MM8M3|p?$-}z0eom#SOKDfFS@bC zS-9)5DDPcg1or^YRog^`Df=oyO>o|rS_eia=bVRqws=FlOVj_UO%Bho<}KbOk_h+3 zdD#4rFhRh%2wz%Zq#^hPW+qdIkn)?rP(g!Nhctuq@>NkvS8u6m8~UZxv7xxh=M>aG z;#%JYF^3p)Q{v1OG`vygk2Pqap#MQLtcEQYT^Fi{XxAvHc~KRpIVf(Da4zxjbyb3( zK`u)PftUeCW!#v(0ezOsu&KO4U}}pIacSWwDIU5+%^?+*0oatdlYS7grq?3M_qLQ73IE|0_S85+hqoWrKy$Sdn7>;;5)PYYq<7y-+YUdpyw0 zF7xO2Z7L3Dp-TDd5)-LnirV1u;yC;GtE&Un&I8FxUip`Xt;OoMLvw8xKTC17=rlKJ zRs8YTN+`ZliZdR}^>N-*x{Mwu+W`{vXky-MuaZhCk>~nY}|X8ZlZ&%+zR^WBu^T3V&zQ z@KKp_zr^ar!%WkTRJrTi@aoN9C+GXF#IJ`%7&-pif9e_~*L6lqr5y6}s z=?ZWBku?OayH2d|3aBr&8Te}HEc3_~Yc<4~R-vMa7S7QE}Z5%7$0Lb``hjH13B~VNOo{ z$Tox9{je@Zbwa=74s&v1PyVOsq)KAHn`^64>u{z-+3Gf%p8GL)ZU1D4fL-3V&aVVG zydDlDB|j6nb_}ikxI$_T6X4=(?*a0o>A}1LCQg)yu^P{B9e{@qYY0gg*I}030Br|# zlq_k7P+Y2aj|C4i@AJ?>&VG=^j)z&=Iw=$*SW8Pz2U`P1U63gp9J&brp$@OEN(ib+ ze1&VgFoALY!U}L?qVc#mKUP=wkCXGb^e6B6kCW5f>g~*jlIMJ)$qz)pfLUId5L~$$ zjT9f*dh?U80r3uvRis>YBmT})^I5T9rL=cCze&C+T2y0SQ#Ev@iXr(n+ichyaCB(7 zyi(95P7Jq}vsA9_j`;O~P=qE@3G0A}h9k(AYB$%_0*-8x=FN`#lgvxr{+QQeD|H~xG{M2suaNB%0z)@RIi%Q6;(=KK4%JmJjBi`ohmW~_y#i?2M z?j+lbH6?J-u`@Hj_C<`$#gmSFeN;3{lyQ}JPnQSLhXoBOPs zr}zes7m}c;j)^H|@8vqLdu#sa>Bn(5nYt0aUZ~y`L_z3ql=nWX1Prf7X1}NM0RiVO z3$yCm?-MuZ;~HlBUBArpMKbhhPp17p^95%S?XU$I=))59`EI=Z`F0%o{0Msp6F@*5 z5U?r)!5LOL4?$^wpv^-t?jTqMUf3L7D{)qbMo6c(R_Oi6mv}abte*FdUW#u$2yFP@(NJ|3wZSs zDAHkn6kuxF;BR^NT@)N(c86%e;c$S6Z|%j!0J0CEhR^PIHM{jl770uf5eyJ@^-J&| zI17wGf)mE3=86jB?QxC^^hnqfOfK-4JfmvKq7kyEZv}bgn7mIBecv_dynh=cd4>r8 zF<4#~Scwh5D6 z9U2HN+YK591XsNY?hv%2qxQtc{_c4PwfL40CXY?gKqFYwN!)zvFB-{ff9JYu7j_&k zy$KsN;DC(zMBL9uJl{nCUPXdFMS|5L5nLjX5+hL>BheNjG43O=Uj4xS^aDrj2cF9h zg2W$PcoBsAK_vGc#P>gT@nzq93Z=aFr#6kEZH%H{h+?>pVtN(L{3&{`9>jv|@ya@y zvoTt%z-sz3x*Q8s3y2XA)riFcNs!xcsUq`=#Yoel@ZZOj&S=CzVj2J*)gL(JX=9}u zVzst3#w&P82|Pl#!qoR;r{6l>64;w8sOc8QvG&KYm^e?_QlL%6P1uEt>gh{*hm-Gn z$OGQ$^oOC~B^d8gXHzAZh$QIxLxI)3^gJx|=m?426p8G@i8{Bz*KxlJb$fp%Z<*+K z?k5*6co^O3j^*nQ7kXmpMq>+u!WZ-@tU=r^spffB*a+})LGiEgHANC*^u@fTCt_A< zV^>_#m~J(cXwzhgDw6GOR z@8u^(N=n}i(g+eJI&)Un$V0=a0Qpg=ADO^WTZ7m-!cpkh>pL@FqhygE__fa1Qaoff zsbvm9fZzkPGD`T56@aU1DB$B+GDtX^?E#UaD4V`7n>{JJpVn}MDTCyTy6i+Y`(ik_ zE{CTEAbp@GJ0u{FVl)ECUiQfft7QayOnmaz*KT4`Z9;=9dauB#RG$fG$pVa2>Y6X+ zeN)%Bp?hbgo+B5ROMB+yZbv9kud>m zm|@*y7W)RJ93oJnMY?xzvP8ouWw!`PdxUm%=YWb}phQ*(N$dYiW zlHj(o6qu7$Oxq5!KnwO}C zpQ}btqvqBTN%+x{HL^w$wnqF|BTG~(&sD3aQA-||r~GKvtb(MrRIB}13(w(ygix30 zUu*DaqTyDT8CPefQAaaVS9l|@&}46oYHTztkfc^`+*iqWW#?LKW-n3iDPiQ)Y%fXH z;PcMNNdo#gAi2T!P%!MUA^1@+@Li*}QJubdqi$UTw_;;bv0=(%V-{Ca&Y@+dMw6yv zQ^BJlEb^%^+f=4ult|R9jL=-;*4)4)Se@LgQ`gM1)!6dRux+W4FQ&fJtpy#m#t+=m z7t(@n)GVtc*e&t7%=^QTkQk!)U?kOS-$B2zR&~`uYrX-fW*2wbZGGJWC2tFc)AWC zTO_o}j|Ie=1Lo}klUX#yF#&K!axV;#Ka&Bdi|CtJ>sE)`MSD8p9c_Jo$_hKXa1Re+)sM+U|@ zOE(VftLg3ia@Ds!%iQz!<9RGoe|>)pP@|~0&tkdP`H-&{#Y#XIj*SWYn{_Z2&D>+T zPd&w~4G6}-qQ;OlJ>$}<0}f?rnnolUq*^pcxAIwWuVV&0}Ay`ilWEwh+c5|qo ztV!xzi(98Y`J^ePPCPC|(LgMxT({UkKdLXmE_dx~s{4KFQ(y0o5Go2vG+s-6CKACf zJmdCXehQ`P1r$#XHHk{DOcN=$%Alj$&l4%8>RT*>Q$Dyk;?imy>+v1WaF@VF`P z%o5#9$IOgi;`>;P>Tp?CO4l^Uy3O<^q1kEauOH5a;|%I7%;ELHk!rOV9YfiB_~v;L z=2@k%udjSVTlIcupj}KWD{wDR8Z~H-j=Xt4NshKKRgFcrW_ixEkttB$ydY7yc-s+{cRBdx~kqQ#oA@l`+`toaprOT3; z9+JT^so7^T{-0s!GwAwKki{%Zfe;7OrPQx0r85hqD;qqkc(W^~II6TbGySEjh{~(W z>rzPMzXly}6n&AHo5J_{oiY7 z%5T(Oh+xny;I-*ee;F@+(M7_mxAAPuSrEA`{ZONd!YQBT@V)s;N$1ZIO-eT7Z zHerCF>mt2t{k(f1w3E1m<@;LK>!j5pZO<=lJ7jFn=Vb4xb}vC|J?2DR>Wff_M?>l{ zYT}#>T~cn-n4uMZGWr%q(aovRh`1JgHfKtEyF#nlzNq*!$;hGbIH%e zt4nPdTAXBJpCXTj+Kxujj(VSuCSD&;@*YoXAJ2Lm&!-(PwjD38LXTIUkJnzGZ1A2m zQVwrPAL6*4K(F`LN=~+}_fHsh*+@=rw`Z;xcC}|?&({okDtJ~Y;(XrMVqb8HIve1) zHV{h@dnEH?u-8i3Ch_Yr$j+V$V!43UfLyyHw!1(OpR33GS(p|nCc0suZBkw3sYD&J z`o}=f8F0pkh;-t-WS5n!UH`3&;m{W+z#1#^#3e8E@^gg2XHTFU7Px}u9qI&FnD4Xj z1Q>OKp@kF3_xYL^s-L7rswo`I#RyM1aSgL^bRrCNPC@dzS1nOjDyLVnjPMMA8>`c6 z@^2;njbYT7pQQ3G#5yh*K07ioUgn5g_KfMPrk~1#&e`Ij_%DBP<6;8v)6Z#Z&Phmt z4bhx@{@3hK1MEqvI|&2CcDt*Bvli`39=1EJo$qE*7o%@^pbR{xYWMM;rx(``6`vn# zNNeJ>AMay#8_IR;+8)~?Y*rs18yWv^_6uVBiTrv0xBY_l-}t-LljFbFNS`-8KX2(g ziyqcaV*Wnz^E+r)+5h$Ie*Ju=qrIa8z43(Jr9+J$f8YOtK4T*Nq3`|t|5x7A-}6sL z-+!E(fAgNX|7f-_`o1hzwh~6)|KsGymcu&w{yI6meff>`!PNb{f7N}vFUo(~90gQeBy>Fg>iV!YN0_d!W)bwibbaIhv^jo*B-;D@ zX>C`=VMdZSA8op5luu0^wKRJ!cA8FN)oIh=jaapynN#w+wMp#rMBP%zn zv@Hi#-1v`#4@+oNH}zFD4>q<9mG_RfbdNW8|7`m?2Wx7qJUZwc{5x^H0NXd7m|dOv z)5y31n>C)@*je4!UEbVZ+uq;VKiWS$-97r##dv&n1q)+bUfrBuKmI9V{Qr%F|3Abw zVCufmzn>Hz5pR(Yzc3Mg1kTXNu-Le`gv7tu~(@K^bF3+1lIR6q-v23=bDN_dUN1 zh!6IT;!K6TVRsKeFkZ+Xb>9J|?w`d5tE0aaSL`*<5;BbQCI3iixmjuQGfwT0#&YYU z!>TLJ#;TG&4^qb2?~UI!N=OsK6dk232g(+w%Z}OVYlj=k zc4te2R4Urtf_C6FWA6JS`p(c$Nek+2Pk(v5|HzG@*~qvvm@0t@&og*sR1l{`efY!8 zM1rC_oPmglXz60Fzf<~D{pV_@v%}JsBJA%rtRt8Y0GdCulIr=gkuHC;o=@tTqJ=2o zb$^_n;9be&4D5MiD*vsqj}+9A&~+YI!=bb^nbZ zL~JK&*JwSBcU>k_*ouy_#1=MJrU?k zBJJ_iw=zRssOM*fdiMuqJA&}20^aZ#%{m)@oidd)EE?2H$_nqMV*a#{V9fKai`^LD zfMC4~fdcQ%N+N~DSFkEDXb-cRq=(*>bs!{9m$vPoEW{R)CI2edH{{HVFLFT;f ziUgnmnk1}T37wO|ougvce+;VEAK6G$LfP`Ee2ApOpVrS|$zb}60WuxFi$R(Q3yBxB z_1sm14E>T-@0sVG`r( zRof}Fh8b_n*AC16?~WZef+I#7CgbI~RyQN71@9;5i;mBKMUH&GpYZdvvfIlV4t3t= z5(s?QTX3m$op_;gxqryKE9Ex)U18I9w_e8G_0)(9<7u!R6Z2xDFGTbEg_+anAZZ*E z(w-pW1{4k^h_f?@eL^)`AXnx^bUl z)OGk)gsvAx6~4sWnMj`!_;K?p{BS}u(Tqg}V!xdEk!q5o*qQJXG<^$rvqg#_u-8pU zc>a&N4})*0VCueXXckUBOx;&M4^|z?!mA(XWpF(Y(M8K9=ojr{hAnHDNM;kx4fL@! zorhV6W)ts<_H!37aKKGzfAhCoJKxJzu1`V zpPYtdKIa@Pr_pqodIrmB?23)ME?%bHjpY9g24AKF&|$$~@d!b@u&uyaZeTib<#9oVbdle=GtO6A=A5a<=KAHVU$E zpa~V97dwG~ecqSo;SbOMQTHRmN(`taU~P^!RSBc8HpeCDFDwvn?K=IQbO%5Ne2mn^ zBqsc0o4*9?hYPLi(674o~Nv0akAyRi(dkhax!(<~zg zB8d!0QpwK|^e`1Sn!fAO@n=fh)2%oDd5!7>#co}(tZ%;9SaI5Aqecdk0k9jUTpj!q z$Q$t6q8HRh58Qs;fsERG?8^JsP<1nq?=Zn^)&K;0FVNwr8e(!N)JGp-U1y=B3p>qv zu?+=+W=>#8e8c4T^17hSgTuljh%fa`f_bbaFr(-$N`0{~iH(=!a$D2{O6{hYu)bYo(^&cX)h6Z&*6GwE%iX z5>>n(;PG?;sCT+~LodrQ>?gEP5k9pDs5&*zBr`h?Yv^93S$|N~1z=`y83Zl>lc8r2 z62PlbAgOa_gl01Z(y~4(=4IRuIXJi!E+T3-zEp%~qcF^%P0mYa4?bxlV-`O6Eu_kr z=O+|lwrtMUzvzkN-f3{*S2Jl|o3-_Y$!XidOkVKxy55uRyknk&rt9A#9*GE2ZaXmB z&H`kfHi)2i12SzF@#9ZBT+sUoOzNF%%(Z<5*gA22{<I^0D3L`c>$&SwF*nsrz%6 zBPah+_es6eD81Tm7=K{!`9i^&!eJA@vPeEcM>Ki}+z1GQ)_@|a3&&IeK_9R%H9%*x zh9izbZN$}Xir0R5=an@K|vBOOd6L>m6V+!6Zff^!b-XA!i zKCA^^x;3oqNIuM}_;zt%nlnXD2!Q6yIaSbCIM7$zSyB>7No>#cLJ+8F4;DsJGQSm5 zMPf#(@Ee@=Bfa#qzp;gQiyO^`nVDc4-1UN(iej19;0s{oz1SpD1IuHcd1-glK zfE*J5^c^bpcL81;fi4`99>BnR@<87^7tb>gITncVEYRK=93>j$jwBW66%>63`ibk| z81F4JFZQOuJIh2eUp3f(%CXcJ%+diW43zBUgJTImLt+iN6;XvnH9TfQgs;>}?ZMCW zKJZsUaHS6T$2*OuYAzX&;4-ueF~Y#Gm|P?s26g zf^;xkWJLIY4|A5nwAy=q;=8qO6E(3U3(}KhK&8ZQ!V3h&idu5}lE3mI_rS<{YT9iD zs@h*-Q?cXQ@5~j{VjE22or2=+8{@x=sYoK=2?;U%CPEu%eKq&*^Kn51ofbV5SgXJ`mIA$-|F$gn3wHbJ3GAGKJuO4Jh zW4FYgBB3(8<;Ya!@Xco(mG*wcz{9yL$gKQMD zY`z2OrNK-A*BrRuOi@m0p{ASz`veO89BFZBan9Tmid%!=T7xNK3#PT7osGG-HN)hb0!7QM$w#F6UFc z-;J@_BpX*zLgG`lfKqZuNGq$D(X+_RG?*D)s2B+}st5|M(Ph(y0$*PFbPlyBzpiLQ5ZgK}#rV1Gk(T~`vDrBuyakdfBNJ6jYW znyd?0k`*Nb?fQ#xk%2ZBg1aWN}E)nuJr{%2k#LXq|Tx zuN!X2mGJsiEV1;Cut=kA09^YsqrNM*t$w=c&3c=TK-(FYghq3VrrVd`{g&68t+&Hs z7tQ2bFO9HVP=NFjf@>LXfAT>OS&)gvO`AG`8{3y|+g^-_qdu9FR#zmWcD&*iB9mkz zI%*jtI zNl~yp6CsJvEi5SksI&**L!^$x>desE`&uQqd+QB~p-bUW%w6h|qNTQ_{4MQ$M19Ry ztP&}`@%yMIC1MF#+(aRr-!#RH&ylsznjN0R)hg>$o;uu!C1!}KbXr2aM#OfydlH0d z4a{p1#R-E=2gGsfjENdN6zgnM8}?ZG%Ivz6h3Wxhfwqq#8T3POPtx!seOaslo;BqB8WQDtG1Pu;oejS-)&%$@hh1Y=# zJA<=U=ySGVNGq0>u+3z#jJfZ}b4H^j(-d&`H8TPeGmBC)y2r1YQwaoQXYE?D7iede zTBMazUxlizA)HKOyryi5nk1HaXJ%tP^vOtzMgMQlEs5{oMR_op^PFm3K>)WDC@@ zB^@pz_U}6JTbi*gmA~u6(nxD+pO2rm|Ev=;Z0?(G8vnCSjLe%h_hS1)&W_ceb>f{% z)6IVcP=vn%r~*s?&G|D|&i_X2T|I zbn73CTA`4LT;Hg|ptzEMR%|Mw(yCw#^Iy^PpZ%KFxSIBi;?}&1_UuwvKTT&rRVR#I zhDo0=fVsMPu%L6OzGJMlqX*Vf15-a+Cg$sp4jT@SVDmH`{Zm~-f97dm{WL=piv#nk zFd1|bCW9_-!${_i)3ep}KQQz1!PENI!Os4lPMXb=-v=j`n-{mc=fD3iLN9exVV5f&PLB+>zl43Euw-pjpDPe+AG40-}EeP-@J- z0w@Y&Q(L2yR0<_M)=g{DY-^kF|z{J?_Oy@KVZ&-C<_v?rtQ8aOm#tZd3$RT2xTlp&RK2X@;S@k&^Ci5l~V}KtOQz=>Pw$ z^{i*FwfA-HbFH(_dCSZzcrncVyTA8`xT07uN+TMF+YatT8O8jQD#mUhW-;Z3pZOWv zQk{KrgVqQI9dnit^4WgoPZ7gO1!?*C_BNuikB_Yw*{&yj zK=i=HJx?9xARKMJzIH1Ug$3_udGDT#J}IlyoW^dtU|}T;KB=>8;+tAmX8`P>{&~Q@ z?0jesC1CU<#T8>(5Pc%G7=xS1EIOt_Zr)(^V%UXsT65BP$691oI&Ioxc(qXN&Fw}( zwv)ElR9@KIfZ7FrdVjS~{s^(W%}CDvO(ha;i7A`s?6qkt5eVPiyhwD5ug0(D*%k}L zzzK7?!D=eu+el4>%hg24nO$>uq};3?hzQd7Iw!oASfwc0Y*>ty=h4ITFKO^3YW9q} zQZM#QWtuJaaLYTagqO)r3U^?hz?SKFO^I+tP=F28-;n<@Js@PL;L4x*0i} z&z9}0dn8)z#j}Ym4{H-$5ec=UDo#8h&-7PwEdt>3M3&?!o=WeX1m6V2Uf%uc&(;VE>zHd6tHOM{+ zj_Bw8M7E>+-9QZLl3qp*U$-G9(*fQgw#=2Y4o+697o*5=t-4NzPg=+Q5<8iZ{?c2w zS}&C$r0$&@jCV&p^SKA%)8G}ni&g{OY}auU(b0$V#JxQiZ6VFKLhO%HT`reCcSc_} z8CR{jthlbUYOFdu*A`u=S(WBndYoDI;}dLUrFNMIlkbu{lu@SXv)RCy;6}{BU47}s zW%kvVfU+2`H7`Mi>*e+o^`m}*@>niCk7RxXfounR-tB;XGK zRg=%q&ov-}=VFKsb`wA4(d(VuaH@_-az#Za-) zJc2ia|D-qfvHbrCfU+MZ8F9YG`kn@K2J%O75!gx0yycO{6ntNu>+JDv4ZynJZv z=CNTWbgx+KGi5X-^<(7?=dWT5Lo)Q#Xev?~&%~D0bx-ff1Hq^iW`f>?|E8WY3F>(V zfCzwn+l~E8%O2+u+hhOw}95dS*942v|MKT7*Fy014NysVF;Fp4p*@9z%U1$n` zQZ>_kIda}SOlh+~4RehdbP4%lZbYdLr5HT>=Db7>AE6hfF`G|w0aw#T7(C*{!hl%| zYj#**Q*2-(_yff9km36uQK+=mf!tXu&C$5Z1gji)P=+lTZ1^m2zJpw$Je$eMydhz( zkwU9NH#zFTDTN6lKd{QQ=)nBP{(VKVO|;{H5oW9rQ&OQ|(w8m@_zaR}{YO!3{3I$; zJWdGqtVGpxrn1=GbL{b(!(4S3mz3$V<&_S#hUXC8(T6KRbHj}dCyqUg{u?l5@eR!8 zdz8=paIL)Ye-M7ackL0|p9+F3SdMzwKPPUj+$C^tow%b^=9SQke)>j#I_a-Fl*5! z>UnlQ%aS@fv7h_@q27EwYOhn5ac|fdzWEw~WWh+nteN*>ZmzPuS7!eFr)@h6@Wb;9 zZo4n7J5oQ=#~(c5enyYBAYV5^91`mkcUR7SLYE#S$t6TO zI@=9gI*!V`uKj3d-w#n-Tn41NzNm%;@BuKtbyY<+e{*pwYqr`t5&?96vpVMkt!(MV zw{|?(+!$WT$F&#r%7z|$97whuQ*>8RF)hY{c#a1I>~E z0_1N#-p@JRcU{e+dfV)fN{klq3}gjahJ8engW=E8HgP@j8hON5nMUaTm1W1d3)8d3Qz)|X?%;^;T4dqYintwiBs)GGcG77}z9)wcG4mO}UbjG!&&i?I zw&d{bb*_3O(M}1B0b8^aOQE2R_9W9IZBzg6vCn?BK+a&J($MP((#v8d&n^(^QP7N& z%t6tcyFCwBk$d-pOK87z;Pa}VSU=X+J|OvygZ>48zE7#~?>sNjz1z1$-q6_v8h-A( z>$Qi~u9>R+!pTE3Wn(K1S@geJm`FOV`^3EUOyOEm)l8M?^6n~Z5R)(NZDBhhH6sAn zYV6Ye1uuQ>EfyTNAcPe=4d=&<0>6UG2REY@70bps7*!ez1(hXrxY(s(K&i1Mo#*TM zui$|TOWkKm^e+Qt;{x6413N;jc*T5kDT6x6eWbRLV3BYuF?$t>MP5c>&+cTmuSH5q zp86i{!E1AG&Kn+nd!lswIK@RR^=jkHS63&~=5b6ge<-pJRnW62PyUHD1|Elg)YCdm4(qRwYSs_YL>cmy?J5DIi*=on5H$3Vh$XxVEG@F^asFF-e zBbc2Djl>$r_c}Vo({RQtW+6N#M@?s0EoOcf8JN=-xwHjlu?9rh09dL+tkPl+7GvLt zsqDgI-*&|w*_&%x11O#VG;@`HF1|ymsiN)a{aQqw?Rb5sQcMZ+a-EIC9a8%Wmxd$& zD3Sq46(w@7cH-!%Kmzs#@Om&#CoTchkid(r!daTYBc2d$ zl)&zlpyLL*rw0^;Ci3ki%5fzu3Rs6CYSjdvLn<BqQZ)iBmQl#1>EOVZ%;msckWtp6sqqZ$-iA;emyTE?Y$h>tHQ1K#0wfDF z?A+6B+XLV8c)&%T`q2yZwg()-$zu+hk1*qBN;5g1fiINx2)wcf+|tB3f0^|x6*TK>m_squ<#-^ z%8TfUTQvwQ@>+!QsJt~PTk{(0a~T}-J{veO-)P(i<=>OgyiLkS2xV{&=aV4#ZtcKO zZw=Up+E^oGxAJFCZjN0DUfZy@IAO_l?AK~ zDax3Q){iX8EG)93(J;Cxs;V!tiB#vbC@xVdw%1VCLliqf)F0jy!?%lH(x^YSC@EGd z@oZK1ZY@clE%8UFy@BwVMivBUB-4{hZ2;k6t;#>rO)eA)VwRQP4NGn-l!QP^6Ngow zE%Ty6HAyr=X*hftI0$d|*U^p$h-d0nLb{V7d|d&Ia8!j`@Vy`ARnkM$S*Sk1=5N6% zYs*lp-RD)211rItx@pwZGWaqa%QdiHnd9j`ilL)N|i~j@vh2OMowS%`C1@V=Qt`%`<0_NnAiKf@b~k8^KL)L6H^SQ%Ei1N=vxAI=M*RP_v;?Uar-<@U;q~X{JUP zpz#(^$0S*Ahs&{8m&@)`xl&u{Em^g8PUu?3={5oukZfuK%9%$Mtei!I;K)i}C++NM zFa!z)VP!5YfaP+53@jPJmSlH9^_#T~2u1w;{q!h-I44UvEa5mO_ts5?z>fXEwnjylCexaN?SXfv<1FyKB;Tnc$8l!O zSKJS}c6Arrct<`Gmzpg%w5pb6b%&OnLMb0WQc532crSj|ex~ToL=yhb(OsX zy{7HT$81$8GpUPZU5|N`Z0Sgy4?iUO;5xJ`Ti*8561z%9^}p~{vdoeKM0a?#tGqhw zC+6vCJ{d5s|2W7b+J`$3N~f&7Z(N$#MY1|*8$390%9|nCleDVzF0*>NS|Fi)=-GMm zz)MBzfPwsI1wxJfA3r-|GKcN!u{14*-Aa2~03({SsbT3uy3r%5Y$UZFitxh`i9*K6 z0|6DS(Z_auI_>1`c>O#FSgy2%OO#ESD`XgjBJw;&E-Te!Jjg~=wZ?cvI$nMdTvHPd z9ouxK4Qd|5wA+eGi?WiY=<8FBi$b&kyq&f8;Sut)DP}kEAt0>zR|I~e(+v?Cq zrkPmRXhqb>9kaRE!EWTfA{JY;{qb9-(Rf+=*_8r4eh1@&LOp%$Pfl@UYw{dp9iPi8 z%B-d*?6M(jGt>_T)EeTMxw5f>XZTBJV*BpzP|nKpE6Fq(9=q7)1bq^aS(ID1ku zDgbUie>oqbwV+A1@DhK@`%cNTBI2#Kyry>krs$#`8FDtfLLr2=(7$6*`&?%SZ|OT| z2Dw>buf4=&wCGzArX>-O@lDB_YB7Ui8PPtQ9b@yN0=Jl6R$m^f6}jX#vy8h9;v@wL z#I3Y;th86G)ZeXi(XaMMul@x<2eVg)J61>6R>$vFC+XLwrPpTZ*RoC4)V3)X$CMOn z*0c(1)?<`X=+;-WJ3Wj7>YqCJkOq9^&GlJTBX0%^d9x>+RB&$@r~u~U3MY%4)Wc}i zmcs#nH~@sHT_SIN${q;R*=V5v$JT=(O|D`aV2B=oci>ZGQXh?fW7sS+7t;p+HIQMN zFq4RnfnXEFx2e3LMlT0=yWt{z0=iZ~0_XwiwBw&c>w%guwABkVO(GyB(YAujwo>Jm zl&ii>EI2v|q)8M+K<>!D3($-M#cVIptgC7HZxdXgX#qfVCts`?zS`t`ksb$YbgIcs zZbzMMYY~0X1b}1hzKA_k<6uZ&@#o$D#_PebsZ+ffGrM`e)0JOlOZZ4l-TBK2{RZga zMrS?^9!CuB!wsE{jTrD}iXSdyuAgaPpQ*wbY`!fiV06X&dKk{Hx6c5h%r`!d~hE;!ns$9I)`7>|+ zSLgzTgdd_p7pQr2RJhzT(cUZ3^=;Z;)$%6^dH=$OZQJew<4Zyl|6;=xzn$3Z8dwnu z54R-e)u$IW{uW}(I!eo{vs*tF{%)6dm)7;5*f46(yr$(h8?O2|+15Lbid%F{{&r#! zo5=b<>*aM{kB-kXKS3Y80$~I z#1@<{WfgMd3<|ha(>WZoDnvIUSf7S%MlxiOQwZ|(dp`CTn7^`i0I`!k zCKtI}%;%B8NY4#bz$mqe7fDIOMkdHG4B169y?8~!ulpy0b9NP$VyUpnlxmivW|w9o zq5d@NY0h;)f@5*o@Ee!N!Gcu$3@TIv=WE1cPw(OMr|%#A!sd*SBY@;3_|o9y!~^m8Ahc(Btks&r9y+aQp#)$#c>LrgU~IN0Pre>A@4d<$ZU+Q=_DnE9QKP z{7CiA=_9$8Tr~|?t2*&?kS(?Sn*>7@1^|4Jc6c@dz3=mp6jFBEN6x=f{(Zb{oK9{G zZFThfq!Ojyz69|to*aO<-uZk+Pc>$zUssI@1|V6LdOvIR=9@=6zx0c`nLj+3*%dEh z(7x&0<%-(??~hgY1(zRdo;wvk)_s3`L-AltzN?L3O4qB;;T)A$o6(|2S6gwaeAnAa zrmojt(wo$IjU~YMn#W*^I((^`(NDHEcl&)9kBE2@)eKPWvb?v2V;qhx305lrO1PQOZlw|W64jy$=`xkSq4NlSSAW2eE_y$m)Zyl(Nhq`ML5*Dv}8p`2JHN7N|jl&xEGe?wLsjwN^HUVo>`Dg+n*dl`P8xsbyGfr56DZcJn+1XP&?wIX#92iV!RoqQo$b4X614Rf8i=8_C7)J|Z;@b3W$Ow(_C^ zw^B_D1Jv}+buS@}TPDUW6GLIvgh1x?XoZV?##=Xb0oD3gjM?aPMIk%U57%LC7WP>X z(2j^?VGntuUY5|S5^?U?@r;gF*_5q7atysXG`+_;cC#F^#$R<|Dr&iRw;VE}^|1ta z?f`l>8@Z~D$vHWre9WRB8(k+0tRm(oTq{yH z(;iBn-wS5jfuG;dysiww5gOvsX7oa5779pRsShLyo}8&43NGcNN98Uw<`5Pa2s7ju z!lY?R6*FmpEnUZI98K?0aXeKuBx1iae$8Xf{==cShKci5e2K7@UVWod5Q zmU)e+J(R~Wm;_l|zNDWns^m9q;5^i6YOSh2G}-}y&{tK^ps-@z5uf$*(D078a`(*^ z@?aV1O$AnkRemEwliahWPkvlDO1p%9;w4B6L3f=DKy%Zr*q;Fi3&M~J9M`C67qRz7 zujRm8E_^Z>ju=OU@6JHZk<2YY+bI6dRyQXfE?NPjB{dE+UnutwW&eX3O>xOM` zvdK1~*1&{umKY{VVYq5WMCV3}3Ce_TxiMC?cI{j6Nnhm&B;95(h26o)_;l zH8oQx^H6Dsc#v~qY9BaH^2n7D1$Du`Dz%&1fk|!tkRSfihLz|MucK04mmHI`ZS($I zH)Xr*6jkeSns|P6DG(r|r+Sk5JT6}&^SW!Y`9U2Kek9J4Cq(=mIM|C#CV#&=v zK&8Cft{*;EYBuzGROynS{%UNTdsjQ}A}>G4{#q@O&_nuKAhp(`c^;3xp-JjEE&n3%*Q_fvT+2CPk* z6d;~rTvy=QSAm1I1h{&FxNdKtipU_5@SuQ#AjqpA@8;u9K^Q)oPHXDSw~>C8=`M7N-Pxm=t{y2&Qnh&ul${+ zHc1Q~tg&axQ8~}ULIl#^0}Ar@BDU)yvN&aOt|E?l@A09(rDlm-P>g&Jd|Mt8Ia?69*d4j)5l{)2 zs^)~$dipe&NjHT@Rj8`gH%AT3M0Iki_fScr^5vUP=mxH&_QSAScGbqHq^nY}rxst# zgi8g5;jwH0cT;1=w>&8@k)a#SQU`9}mO=tl!F-^Of25vfygv9)OnMjm?uppDp z@OM2ydSH*oxAxNb4f;Q*;y!{5S(FXV?BhP$8-5;$TdLz%Arc_^NA7~ACBFPj#jP)% zi8`T!1&f7Rn$bLA{8a*{cr-UEcj3UJf08gtnkY~z#g82%>?I|to+z#^CApONu`W>x zJE`a|ng(wJWGV;7C;%sWr32#9O>@D6TW&CQ8F%cAG%s{R zYbb3&MqW!?yKM$~;X4f5%=e1n0xvU~n3GoubisOpOwI4U0ke9rrFc%wY(mbRt zmvuT9|13*KE-$43L>riky$L=Y$}1&(ue%ZdKZVN)IjQq-fylH@2WAe(0yc;k$8{p* zSr!M5qjaRG)D4qp3$qGW{wMRoP*AEkgjo_{spAc$h-BwUD5PQ$dD~TZ3dJ{e6xY9D zdKiiK7$R=b%KXH;*y~l{7kf(F8F zTP_=+m+aK>~q@aVE8o8l@i-v6pTve*|KW z?N^+%Mh^iI91uLqGp_EFqHKuNb#>+GjrZ|Q6&EJo)G!kqhxHW+O_{f-WHrl0WR;zK zA+C>@zC_U%@33l#nj#!#$qaIR;W8RYv2#Za>qz)_LN+*G;nW;@*Ly0~r%jO? zw2A2h*dIOC9&m5)P)yWkLbpY0C}OF4_*1xqx^alDtZ(1o6;0_gO;IsOW2XE)K4sYo zs;1|lAV=CV2?dU3lR9rps647~9tF2T$TGx>->aQ6O4dl2yxF=uqY;G(~E_Y8kawAS!GPf@cjQ+J_NV!>ANR zHQh+9)JVP6NTcsabJj>}`$+rhNayWH7u{%&)M%g8XsZEe*m0CSacDS8FlTiXe~WbT zaJ2uKIBl5V8+k(brpDqSmRB@Ve09}rRVynzu_K*TQ;^i3&4G5Ufj~ER9Bowmv0~!J zN~W!CZo>D`Fjh?+GXSfejx_OvqCf~>V*-$krB*F|0DT330%)O>-Atq&m;hqM$&6lp0y#apWNc8W0D)Y5CaZ{m3nBpoG@b-Dt_*4w}a<^J;$L9D3>6^yoTz^E%Ku?!t7AYH>mSnGDc0gmt>N zNX;~E>h0K6qTV#l*fp5TMV~tco414JzRMJhb+{la3+yt9RX7HJxrC&97&JMbS~tn{ zZIXx{pJYszJbNywLwxskysBpWX}R?g-o(PP_;+90>n34+w~3sBB==GAh1DUn4lA75 zA>f$!XDK}51#!W+Iv?pV2@qn^gq)|#&Plhx-RESsD;n-IQDckhJ%NF)Er zPBrvUvGhS5=KnpQ_$0{KKJ<5R_r+hq-8dA7boNa#kI3){&Os4K)M%nz+a2m2KQsw} z%Im(%MCEm><5Tib>@lpgDWa?iWv3?P)}eLLr9dM+R)sVT=$zp zqR#VCwSSbL+Sobr{u8pLd#nL9px8T^`{`HS1`=hbw(b7v>K*&zs806|&7eBFC`WZ- zdI2?~h=Pz~v#2kL8#BvWC=R){@pWx;?=vd6yMOd2wfp_xpGFgZ-|7F~gN^?SFZHjN zP&5*C(XOHK+fG&chn=bnmi^D|RC4M+cIw-|?NsdFcB-ak)_vUn+)mY`_%}OMfm=)K z%faC$%1=E#J4^kZmLwaM`7)IDWC@F-Q2vVHbc;-H=7T1g zF0t0Ikx^N(9=&+925RyJQLPl(8d^go5I3a}`X$_jdNG|{KOeQ*{Um{m49QstTWYKn zQILAEzCA$syf{B3Py*<^GA6-Ld+$!nG*X#kr zu$YARg~OZ_2gonG@WE_-Z;)+5--Xkn`^T#C7Uw1(b(!y%6v6j9Kjizzi`-vdWjg!S z%!9cBiANH7i6ih_q*@oNvlOnJOogcf&n|ZCP4KewAkH^SxDnyW67*>7X zwpMFLSZc)iY6&691$_~%98`hbHnwI~?JKufj`(VK!WK~eLQ@@+Tk73+rRD9y}~3D$34bIrWbp~S+867Vsb(ujwMaej{Btv z!0>$poCOP~tUA&n)}dy8m@EEZaTyN&n?}+)7rbU}?JEkALj+fjTHrX=O-kH2*G~>B z@HQYGTDmAMi#V}`%z3OFdT%aUlnaliSRU2y*ABb3RlLNlYP%c5Eo-=}jHFk8#g};> zvHeRD5;`rif4_LB7;;j2%;(G9Nf3tfqOWisb)H{RO2sqxv5-Z|ft@al=j9;nyXezC z_L9h#!^6WPFAJAC@#;ndnxdiXqKsDG$E9pn>iUI_SF1<47wBG1D6{e!_h2Ir&u8{% z%FAbE3GZs>csTqTJ{n`LU36>9(umC3(LNBVwRo2Ode|w`S7^ee>|0Gg zgCCFnMA@mbw;NF(hVM{zs_gzL>7#cFryqXXsmTTXxUO;O=1hO=)HRJwk~BDooMiO3 zomykd^%$LcunQ-}gNNX^of>T>q2~r$paY=qsr^3B?{(t;Ovo!Wf%eO-m*#hTmuwDo zhMqx){^vZuz%@;g@=OnPp1+AV6CX&&z=Y19ggVdX>`uAOL#N-B!}T;%;6t6~|8m0i z;xSVZLY?Oy84`h3u>QYyp1(AbUoVCxNm*1w zibH-ViVol5I8;rEHS)Z$h4r1+Lt8*v?s-w8ZH$*qqH@}@(Ch7hC@U-PnVg==K;es0 zJ@YrQxdeaNsj0)W#S*9={f_UVXk@+y5iaryP*5&WO3K+4ki&vunl2n(&TdnV@f~6& zd%;>2O<0jC5o}&jZ(Ky7P(hVtZn;Ha+~R1gdFqK^JsFM&BL}J-1UVG|rvn}q?v@8i zmy1f+F5bK9qJ6lv&oV79&o1?vNWaKhe&$7Yg1BZ(Pq?}bxsx9I3Ca%KKzsIid3m8f zr4DRlBH_$!IdP<0(|6O0PcjJyuWrzH(YwBQ=LGrktGl^N*;s;Pl6mvet$e29h*Uax z?Yo(1YXOTxm{#Nig5>koERw3QN!;~w_QwEv8h~!i?}5LCjuYv3zDq0Xnnk^!YkC-F zw8b0}!?WwQAt~Syt2OXPlL3Zy4-%8%1V-3p_rl0yB$!((RnH-LhVuV3zWbM*x`3Kd{C%FUB4E-0A*>{! zup?JIKt@yt#AafHW>N{aUQ@Nq5X$*e~yGy)c$jIe#XPJJ*fVTJ7vn&lN~V zM0N<^xA(vxuwInIE90S(lanvy_uHK>Uab3$Rbi=Oxm=@&cMql?-4W`f z=}X^FK~+DHOmkTkgXG=3XIi6g3O=rTkrrsEExD|D=}d~|1_ zw9mWQT$JGoh!gGjN`KrMWaUZ;d5q;oA4t;J(d(rd8S&W!NSxHJz}++XNtd@7myiJx z@+$MQ`jIe}GL>_^_lr$#rh>5N;V)viTN*;rDs1K!Iq9Cahp{8CgzTd&?4CR3GDX(? zo>A22Lj$tp+K=VY;AI{7?r0l_PBfsM=i*B5D1{}BMDa~O!IP%dKwZLS$DX^X`R%JB zucxaR3=qhy1I00ksV0KUV&r2?d1#8ju#C}kXK)zSGfAx>)<7)OM%s^LpOy3zG+=uu z;5NE#T~UJp`Qd#Sz>D!#d*#j*CC_39c;f@<4n32KdocnOVECMmt`m!GF*#3!b|jCz zKE>vob4sJV(nrlGiVBx;ws(PWN`rBm1E;Kbl}uLpd_E3#{)ivSW_5nPi;&0%vVuF$ z(gT4ZJRi7fX|;Dv?<@@x?p&EoF&*Ad_yxt8#H=AhPUh5>aU0*5YheZAI}?FdLy>p* z>ZtJUvE`NRH;;h?*`J0oFWC>R(PC-=l9SGavm{7L7|7Glb^9&g3KQt*jXn=U!wUG( z3ntlxku}38n*r3E#;0GIsm}wH!D=kKu6N1|z)5CcoF{s4AY?G`&352UO<*9U@t!pr z7Zwr#v__-9k`YY{l3Wb3IuEL<30e`>#8DI9j{m*8NDT-=Zc%9M2Gf64)m#kLRfE+e z1z#r-sCKDP2isU*soD&_t?CO&=>^NmfrSTUdHGR(SBU?4s3KEX<(shMpioaNJ#SBO zjcT7u%JA9~pFlH6t07ijDu3Q=Sc)wc%q%=E94DA6qS`GyJPi%xt`VIkhtUvvp&F69 zORWV6YoLhq6_yx>MtX?JwS=fkhx#PVm{;{j7GL>4F^g+QT_8O8-5|Nd9%_#g z2)iAW!Ay@+ZC1tiV!$blz)5_UXA8r^MlIM!d<}}Ps);ulgfWW4aK+WZL-C%81ac?9 z`$S>)hT^oU6L`5|Eecfx_7XVv)Hu8(_~k8V&;5j2l(&EQ71eu)r;DQ088SDZ>?DXb zDT&byO`A(i_5{Sp1T;2JN@M|2w1lBuL=sIVKa9}r1_;I);M;oXg40uQj8hDIQ*av+ z-AYr)&EsBS>%R0#-A_vOcF9Pa9=R3&+-rY(b{|m`#ht){Uc1 zcUMoh+v7o<$foRRS(;*{V@G8=Xl3uEGv=n}nQNz=r005Nj3s3hwPcj1r^V)Glv88| zh-X%b+c$D)S2|?0nWr_Qo}lk(jiZ()!I`}gTFn=6L*m+dFc6y@P>d*P>{@eg5}3XK zoHfsGPa=rt;FMR6S>@9DDJHg6nx$^-`F6l?(<`StiNNam4GWQCaWU5smlib?tPTUd z4g>O`M_+oq?+ykL7ds^ym;xbMa1X%*l3eUaO`Ql4u{twC)QsYd#5b?J-lV+PmtdM@ zO}b@H)r~wxgl3}(7pq48y+|$8c|Ny=Ci8OseQzz)k|J~%$%VF`FG8b9*J_L!Q>-G( zC%`GJoh^8GR-n|Xq2OJpPE)9|T-YO2sJE}7d&9{LEz8_=s>%GkB5PF z7R67!i|sRt9b1d-EhGg`irr{RUP_d>OMu|B1qQ>~{9QmFiDKs))L}mSiH4+y1w0g? z>D8(Yt%e6K!(&^E>uli(5~W2+c@e|f(8&_t8+g_-JXoSMceyB^6jVq9in2h!GZ6f7 z(z(lsN(*?dd+BO0Hc&2iHB~&e8iWC$)+5VbW+{sia9dC+YrOGow!ms#rcyBHZRja# zS|U-+wHSF*t_jVb_9hy+NtxO#y9)NFJ!3vvK>9S}yioyEzW01ffJ!_EDwNG$FqT<-`Tx z>xId=$-EE)3;WdZm#Tf&;8%uf*Lpm^QDLBRlcCB5aA1;p1|I*l;6q zgbIaeAS%^OzT6ttK3sv4&6#XPUff7XSX6WRb`yNMITjTdkjyWz0UJrS#DZJAeHt># z)RQfn<5*hWTdHUIw4__MMw7MX*fbz;HS%e>3V*g{)Hi1ep!&P&HMm?knQbY3tyzIB zow%AElI;z+&81H5;o$ZZ8!#!NJ+j`LbDygRx1-nxGUwEhY1fvR(6KzCCTz`BbI@*a z(-CY0WCd`qJ9Vb@b+l&+@{e@J2Dg0S{tyHPGU;(yYkoL&`mp<|DVwDuYqK-Pp#4{- zy6nxnJD;xT!Y9pruASDyDp^rkd54 zI7_H?+ownOaZ$0+08d@X3N@pcBA@lq72IWY`+G*Q+>pe^S=H9EKb(xuUQ6v^d%x># zznhf6Q`&(*_mA$*DuliRvPO-pH0&681GL)%o0x+%Y=f7X@=KkhE#8c5Z1#}l;p(%!(8QbHZ3(aYc+1VO+Bf1yV=!hbqf=EvGtJyBZl8n3KDD$`K3pgoT%R3X2wv+z&gc z@Uedw;671hZXCh=6E@gFbiCbwr=6avULBSs+8%V`T@U!a9|IcGjMmAsgg%=62mm%G z4hEGMn2Gj&dI|wiqLLB-Wt*d)%<9q48D!7ORnKbk&Y9h*@x_6O<&-#c!L+bBvko*3 z81U^RGjSZ4??mm(^1QH>8hh?6y#jz0feJ1!(8VoycP!8mEf`BLunsQ--l@rU%{{CD z^D!Y81HS>E_|5Oc&&vYTUGL_Dx2K`mGlJhpfqpY+Wiyt6xpCVwJ7}}byTrd#XH~R& zUB)J;rKjldosLck_I8%Z*9dd{Cby^F1PV-F9%8e{Of#oUSk^D!N=+ht@qFc7_v9u4 z5AN|uhw;TvmguRdOisoaRibMx)pJb5p+8=wcZwHE>cGd@ zN4%47%JaABZg0~KLXu6w(q8@J*52>$Tl=4=Tl>hk4A{Hkz_`EQW?5AFZ>usbrzAf6 z_t8Dds>~>A$|`BeMzkl?pqOS=F`_Q7yb}dCs~bB}WV4|1FSyxP+1y{%GW2IY>>~

wgOz|2y7*f|y2u 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 z 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

&fQ3%3-02Il-lB-ODu@eH;|Bju| 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 z zb0QBSHTz?{5v!F}Q(T%k{GVa{u`mspw?hV8P4?@dp6?k9i?K;%D%RY_lpk7sL?4f& z?%iDJ$dZ0?dt|ubQL0`JgqFfWltIX-*@|7w*+Zbmh+0lFmt~A=wsI`b_QTo1h7^KV zV@@;b$f~wp%(CXaHW%}T~;rA6lWrVoyyRw zv|hO_#dV;K6n&M*)NvtTxcl}ad(f*Db1-S+git8^eKTbU0UBjpbNFh-ZSgKTF04&s zh$aGOzF^?s6WDAMo<3%F zkb~s26wJNH72_Uxe?41d&Sfl7Z-I{+1e$PW&6C_?2Iarj1@r5L(vo%OCoK=z81?an zuZG;6O?J+YRe^1n7F${HmreR)381gWo5yK#4JpDSj2 z6EywWjkBxeo^Tyrlz!#lbAPY9X}rc>4pFV2(1@>{T*;(HJx+MNe5W?^tnw>8b=N3* z^aPjVHkxx`D%t}k<3`$!eJK>rFY;nrn*{MxONeUAT{eoQJuxY%bW1+q%jPMOa;g+5 zA3a*|X)RS7(-B(Z9?wL^--fte8-3|~l=`M>?v4;Xaox?8jiux4&%d+;ZnRg+iW4`(t&s@0C6K^UrrWSkG}r`o0<5w&OBY+)g*H&L3DL(4#nV zQ;gr~;w)4^H`WwdgfSr(h%O=vZbekuyPK(o>Z|Gop~QVRA#oE->$Hp8 zznBVbZFYiC@M$UQ1_DYC8=@LzQxFw2L-hkuXvzsEwKzESE3dsXERH@kt5F#&upJ&R z&~*(pL_Vxf!zf_SiJkay3zVnk%SV^}#C0NsDgZ?&IW!Uda;P_x$K$%{3^0Mh!nxLq zGI>g&{KFv)WHSgN=1+;N6g*sIDnlw3G)dQ7QlgNPcMvTRQUYBd zVndGHG~fEDU@ixND+Qwtd<6VE4X8({-ffDlUIFAlF{Ka@%Qv3PWq9F8|CIEu=Yk&0 z#EnyZZg+^m;YsomCZ3eCtBeq7lQO8r!Oy%qswUBpABo{!DVCYIryOIea;hbiNyP9l zIz_OFo=1krSNGA4A|3wBtCl%~cRX>Cc`bgCKkTN413HrOK@N`mM*B?8AERw%wUbX{ zOkz!*(iKp7?y8p1P73M%h{?w;y{O{TXiOc_PWi;*BSu`8R1q70YCou9-Wr`|_>-Cd z-z4ziEP1f^;z>ZV>$*@&`E;%qPtMAP0E0~5P<7pNRzbl`IqR_CN1Pl{2GvH?dDP(@ zN0LxAo6tw+t)@M{n=sKjpKS51X1%|>NkHgsYq;pb2-izeEsXo)uwY2H;9OnWhfhxT z<(97NH)HOYaX4op%%^@gHDnQq(7?!-rsiHYl*T`C$P5neRtYAEidT7Ld$80oK3Cr} zTkR~x8Zk}$s;T{oidTu&!shE>aA0oD%lPc&&yH_eSFYUj?tO3djclH#fA@g8mE8I} zr7iAo_KSZJ^#^{OREO$`Dw({{GH2Cs$FD0Yv?phe@JsVuzj=E?sH|3r-wZvcSa#1c+RUqK0VidV+a)RAyD0ghWzh1 zCl$PHZRm|3C?=6z4xY2gAP}gS`O=w>|7;2|&{%LKepkn6X(Axv1-HHf% z(8oAeRUzbT*3+LA4%Pb>dXsZ+BE1W|a}TUHvgTTeU)DNZx>=H2F7$7E*GJ*U+-$Vo zEDkHatPTM`aWu8W&W<-VrsaM%Irn|PWPQ7?P3P%TOaJ*u;$!T)_AgH=Eoa^i{HzJN zeEO1=b>0y36BUvB>;>@0Xix9)bMxut=eH$zb>l@Rc-$l6Ys(tdE1xdjJdYPQaqQ~L z*(<+`gjLWinjx0x9*G~Gp7pJW>njh2eUrTQ8?7vtWj<crbgOZCf#I+5=bHpU-uUw8m-L}d z6l>2k1)m4z9$IWV`?^!kCMO6>dL;U@K0|@VIvqZ*O53d@UzOld$@?nSzcF{2;5A41 z@u%P&c>%Iop9Q(7*T!UetL*USKHd_MUp8}E_fvh}nbw{RM3Edl@4G*94f0DuWXa65 z_LcINkNdtP44)ewpO@`XGh*=6b2w+;hKwKu*s9WzZ}i2_Ho_nCKJ?$y`pA{-SIpxw z7A`FxUCtjr!q*?Oos-C~XS{N_{#x|K%ifGTwaG8Vl3ss#6>!KD^7O$gYlm0uoUq@& zG}XK5F{wd_wP!0of_}dVTxJU98)D#67x}@h+Atqx`V*!;NbcpP{| zT}TQW_N_3?ZXv8*mDK+gEGAOXZ<9yenG^o%uEDPK^IbM?Y35hb%&FJI(34*GByZe` z)@>hrZi9YpCmpHa6MY)_!m0!sejJT}!IP!osb=tWA2@O$unz&xS%3pKb|`3!VNz5x zbxf&G3>q1eITUe+DKbVq0Dcm)iz2Nsiv^}n&1ecNHWs%Kn+BtixF3UFjqNjw8-OV# zK6w6eJ*Ix>sy#N$5lK2A9Y5m}+iDiSfQ-+B#__`dMV<2!EMXmnhi^@3>@ZQOkPzw4 z##MZalZM5Ey`US?i9gWrZvDg)^~7ap#7A|CRb(Q_JpLgxpn>*B!o^D~3L@kHt0g0lZxElRg}}g@oszwxlD{q>?x=G}x1{FsCuyIirtqgQ*{0~5 zr@g)pJjmu+CJD`E&u~S6rX;3qkwe41}-lFRgbM}qJ zTo&_echWqmQy(rLFZ2-js#2b_dG4pZoR!nOnU?equq#KT`P;s50M$hd=U!-Je>=_p zX_mdrk2;Zd&E3oIaQSm|`F$vdQa1jbOFqpRYBeLD;Vf_YJ49ubkbR$!BdcH#hT?LK z;{p-x*dXG$DY~J#VMd(nX9b)Vh3nXSi8Fj={Wgd4JVcDFP|>3Z2Q5&lhyldm{4t!Y z8{{IbBF!|{T*)0RnPOG@>07*k(eYy;?TUm8!>qe&L5MM3(KgpipP2u_};XVxS{%X$eb3|3pO@ z8hxFN2&hvhr3uo?kU`H!oD6Vt1*k_FI{<3xEGoO{#PC z4;G(#GQ#Gh(g1?;k77}#Qr=%%%a3Hsru}LSTuOG}7}4^QIMOm}!DYg|1vo;yZH9fFwGVyOR%Wkr0YqEO( zSGvyHZ1?|Oy8h3|Osh6@0(8wLD2%*`w+jy{*d@4vz&gr7Bi*2gO5hO@wj&FZ@U}2b zt0`Qx#ecD7eni>f?vwL3Eu$Q*TIVfMZm%Lxtv~$8kZt6oT4d-p3QTt68yj#Rk5tS1 znlc0d1BSVYl}N_pPUKk|{Q;S5?3DyGuIPY8SHBVF=eJM}NFLe+$ywEH2yX{xeX3}m z8EOAW-qDE&EHdv{kfT_ytUqlgOgtyKf+1v>?>Ii|_$Jr+Qx1O8=5$8x@r%5vc@orl zgzaPQ`XSpz#P%W`-PK~(1!ZgU_U)nxsHR))qU^m1*w?j%UJ!Cr?GJS`QV?CEsOGeS zU!~|_74Fe+V}n$UgDh#F$x^^VZYtihw?d1r^ZBHu}W> zij+R+%`#w$g#(nIg{J44c zGi?x2)o|D*Zd|X8RabQ2(dhV*aFfG5Fp)lx4{HC8d-tHNR!JcB+vq!j&kYVH!hwbF z2y-Vi{kzFNOh~sO<7Ij&6(%{|SXK42C`BQ(I+JYim}Z(mWzhk4g((XEcCgMA|CLHc z8v=n3Q#UTBMA@hRH`q??;mp0j8TH&5&Gs4X4>P)#Gy3eah6=NPP+j1xS?;Vw`>fT6 zS?kN$MKkO*8xwnWB4!ZSVXQ++lZ+V!F4vkVv%$Kw8#yV=mueN2P0SVfOy`QpzZ6j) zJD<-KDs&IYHAZ9P6!5M(XB?qd?h=zWXe=#UIHO_$5w9P%YgBWaPjM$-Dq9!wS_rr1 z>+qWBh=Vas5h~54@k^P7?Uk1#fNRcn;RZFH&wU4iC;=LnWbQF?#ylLW}h|a z?Xt66zMhL6dbo5eRN_dv*=&9JIYry#2MIO9rPh?(irf#Zmu)@MA0EW#I={#LdXJj} z%{j4xciTUH3LJ{8Y<7&F%MC2^c{2C(GADqY$V*}6!GrmWz>X_f^T!H{dV!RDC_;Ro zilGgmfX4!#>B_6^c7L-~jHkvy_G&cUfceFWTlLyu*g~d`>g{mVr1&)^?sX#5^@|Uv zNo5b7t4n$cMEt>ckbfkIAN0{$XhY&R$?b%V!paTF*Bis_GX@yoMW2P`X4^~C^~%kN zflZU#Zt&yxRMYP#gti!rmJC3KKQ~z(pBr>?8BUOIb8c;|DG+^spm!{>X)2`0;h?8z z-SV_%+f#SQka~PMF1s)D&+|wDo8?C}j{<-1xZl7|cJI8-Q;l=K;*&5sMw-*>(tK6% zLyO#==+m9Jj)NkTJZK|6 zsMkGce0t!UaDc5j$R0nyQI6Mj9CYO!1fd8M?tSY2xZmcf5&ZuU_tsx+_LZJw7R)PX36nAEumqmMy>XZO8z%4vX>41lft z{(1P?nU!dbvjHRy}H_b@->+X$bPD;4SKJ8io$+^f;o-0a;o!miZwEY zEp(=-eTE-8MVNY~+H^*$FhveMQzDy}WII>aKBu#uVn{ugl{;rionoV~Wfz)yEp(xx zeL-b?AsBqYOEJa2a-kr%&x3i%OE$mHdLgDT#hiL6{bVf*y;Ni$m7%!${PjxJ?P}c| zUdY;CIrNGFedEK)701yTCEGR4(WRPcjM3K#laVWPg$YY*TQlf2C)rKX?A6baVY{zI z4x!^tD>tHK*X}~s9`v_fLeMc^w_C>K+klnZ5a?|f#a)EZUDVgR7`MB))VqY1yQI(| z`;|Mmr@OR~kqn`G`=kra$D3UB`yA_@onU{6f^8Mpr{TK3h`p~Y^s*u~ciiD2FvX?3 zB;auVp}C|x5A(5}{n10>u`9HR3V~ieh5ykZXlc#%^lt0w?&f>kMCxJbut(cB zW{bUj>DgfT7gC#&j08*Pn4>@iVbw& zhyN&LzB3z>=GN0*x<^}&Ockk%iLk58pR4#AB8bWBmwSoepZsv*|F-lKO3=pAZ4`*Lw;YYT%y`0o!l& zKOq8L(YLza6JMRR(ILBG{#gbS?HN<~QTj5hf3!8^LiT-?leZpFk9PLr(|h&uReyh$ zw)J4{ZAny&F!#%JJ2w`Oj1Vz=QyLl^dCqUNaLDnSuv1IMY&#)A&-5@i$=9$@X7Q~7 z&3E)06l!(5KcP(Nx0^KbzR|E@@cKv%n%INiJCRBwDoU1+lY zd+NOOp!d=AC{^` zyDz9&ev>?V#hV!WM|HbKk-Kpk_e|zLw{w_J8hdaHkZ`h)X?EC10OQ@C{eA{@PS9{%83-8`UF;F$|4!s%RzcI6WZQ@l`?P1ly zYOm|_@`AdW_0_`Ua-)6p`!N8b;O%CSHce^ORpr4C!(xbb{YL9dbi zCk5x@wz8ZXsy**p7`H*+3qJ zY>LSf;`RzpbLK6{SwAmy;l`D=JiQiiy!)mL2ZSB5jzeB{Qj#~K%tG1nM7lf+<3PBG zqpd(;peF#E3i-xZ6xZ_<^OwHpJKbO0@NA+k>}YGaZ%f;OCTVU^B23Jdoez{|EXMwX zl45k->=K{Z{PM7E)6LHx=#?Z`c`lyCEG z`E_K|(D>}RW~#b^^5Z-)l3G6^N>L%NAG{)0sPZS&7wBng0FPoFrfaDMFW}Y zEhQ`UI#C{=;gZUeP6+(rCxc2aft)KX_?;A7p+_Xu*RSAk{;ijKne2;{4C7GoSLTbk zY;27Ios2#_F#KG9%JzW%{CCS<*&H=dhz#cWc--jWIJaHhfGqTxHenWR46VFx$jb2| zaTP6>yGLsHd%{K1u52#vOy96w{YCO=P%i(@|IJ%Vtl&H`dg)KUCPRXQKGAiup>USq zQXx{JLnK8K*xt5(`r3eFARe1Z&cJUY5Gq3VYIJve$?!7s)evL7om$!@sXkW27e*Oz zLQfDt7|2W+%1J~;&VYNBCxwnFW|N>Co`T9RX#)U&C_P>rn|oj*0RW`#@X;t!?^a)X zd}_&cC(Y`yg~*C&&NzOq;q=W{32u{5Pn$ZieV47blnPgDuR2!=K*5gFMb0P%!f{_i z%ff;W^>7wiyWUR&?2Gp6$T@tdWWxa7SnxnPZf{2Zw9>LYpgtan55C3f-%_TE%-j>} zbQMW&p?nj9=df!GvZBqN35mKURvLbhvf{z>Jd;ZBewSlkHuDci&cc$NjJL~DK0JVV z`UHL2rzcoeIW^#Oc7GH^?46lI;+LgxonI&#Q^jhqh)rw6RN>7GTSmiO6K zIz^6bDONqXzJUCf7tG61(kG3Q(vTR^8J(Nv-@ol5IlQuznnn{UKf*yAM+KgSGg~k4_hy}J~@r^3{AN(uj z{spy>X;m=!N)oI-{&&0rldlw(w?t&O$JexFmbAebd2VGNq@ul`X{NNMqpZHCqMQ9 z@ZwtE3Up#_9abf8+lTi5CFL+X%kuuiuj)Mb;ZsnR3m3{bjy!$fAlD`^r6J8sMB3+yC87Km~=#bWy2tK__X#}NUG=_i)#C`TH0HQA?;TeDFw@j6u>h@no2{{mx& z1RsQbOTsKIqDH2I-|X4@OQlO++Y=kncp2R4UQ6ju5zkE(KrMiyV@@};qvOIkY&hh^ zH4et`UJ?J0==y}(L22I64JDvD;pnezujMtJ}1d$3~=$kmlss6eHl>GBj+o z-&16oPB);5QEu*~4pftdY$Xs@#Tz=m%k{Bi8**t|%IwD4|$a@3n>=;2x#-BvIKI(aDB2!dibvBNs$%O$K`4P<3W`hMO z0SpCi2%_*(f)0*)<{j;yu0Oy@y+7>;2&6k0&QcfFgJjPe?kiM`&=D0?ihTNVR246a zIOf})?uhCO;cX}?s>#SZs+iCIGFU&FalrOE+5KXy#ACmAnER^lhNLX!J%^r7Khr=V zE|8zZ9XC!t5ECDXd9bu2>Z8RTv>jbRluCIlJU(7!8t-!s3l_ce>yC?jbK3~Q+((%{ z?16*t?D(7WpIny!Ur5p#`|(YJ7hBDXiVz4~&@0qG>wX8|NlL#KXki@sK0zepqA)3= zT!aJ()TUdC)rmBZ7SGfb_*MAkhw*!WY-aL%HuD9p_>w@v6rujH*Z#aHF zVUIhYX{A-h%_Xqhm`ZdFj)jb2Qt;6b>%_85zMOFc5VIB+3I%;pf&ofQ%dBYi2G9MRUjD(+A)<^c_PnwX+M5c zBBj6m=$+3Tf|n$m`!b`)i22h*kSbi|{TTwclKQCaqml5lE-J&zMR+VPd(13;*u&(V zCM0dVj7?5li!7_FS8JB2MDY{Bw>s)nGsIM(rY*wjfT599&@0b(dPx5JdSkAVxYQ_R z!B#98^kUm$ydRCc6hG^K=C~F6WFQ`xxrRh(8QvvQ?HSm>ytsUMBQDa0pm+`$A{y$6 z1m%~}j}z;Y(x&&x`L;vBB=hsQsY+qN;m1t+Uh6DodXghZ<I4c3p0WWfem zPB!tcqB>9ccq}l0tPXvKhS(t~n>3t}{{HS!=OM)Boi_O>FIxZ@rEvk&?YM|EBS0!33S5G*;2vbe@%|$9Y0_92W}Kt| ztRkL^wF?sLkHD19>2S0lBr54qpO3g{xI??RxSAtE@VZENKJ6b~*N^%~Or}a=nTSg{ zj)AS-WZVNU0PpN zBxcgif2286eO*4&{G>{Wgl?hU9q&}v z{Zwfp8I!R%$#j?9`$E~%LQ}u}xqA6EWEV>dQvxTSEqe3%3 zlEw96yV`bfQA@uE%}wH)6eZ!~?>>PHYcEIav6PBUWBHbjtzxTJ5K8Qeur!VWW*Ub- zv{S5}`7u7OH61^}VP^qWZmMUR&!UZ8Zk$%0h9g_fo?w6Nf>uBav8|8qY}_6SRuEp? zww=;~pl(IFtHE^YZ79B{9#G-68@t*T<*QOpp+!CHg_%xLRdzpx!FBXZ`z|)C*Fk!Z z`nWT-U0nFKLBIIF5$$mINN$~lx(u#sBi;2%b~8qp${LV!Idq>5y^f64TBlcw?gg~#-m}geVp^uyU6C_k-XvPzY(I@(dtWT($4TWiQrb-- z6=t^SoDUW_PG*?(*AYiggMQf#b`_KL^U^zYZwkGQi5mSxj2qUx9oOAss_Zl|>n?Vk zAPTiaH42rSGwo1j;cv`szA83u>O`f{E|PCQ@~;HGt#w%cn?d$OV*U@I%X`l;-Y?fAKcH?}3ouz;J8`1$w=s|mrU31KLWGBCb-nZG91ay+j&)(_CwYftBk;XW zykqP&U+sX((vg8)>O;x43&0*7w96CVZjBV@4)YPC&AMaUx?|0{_h5P8s(awWlH_0y zO`sb__U%SEO5zyItCQy2^%zCoTdUl<9!Xi&^89atct}3YK>! z+{GSdff1hc>h>URcZ4`(!CG(GUC-CE-im}i`1UWkd(rq9eAMH7kY=5WKicz-5sEX= zh}qjonaKI3`IyA{D(s+|&H9>3`gF&7HQV@Dsr$*!x;-el)B}C>W+}dL+ZjqC+i`;x zZ@sM-b9P+50csc>@T+Q@EVD>VbGB;Oe+QRKfuAPXYC}fzCZ29P(I-b^{oY0vGAs zgAtKiXM^Bo{D%pH+h<+|&f<>S2Oo3^HE;ZS`V`b%i{lpO5)Xz3kAVX>Zvz|ioH7aN zc6NhuwN7;a5%p~<__o9E@cwp%RM)Uy) z?J@T8u?_0cjvC;A+K`Xav6{CIl01>>SfHQC07NX1A|o`;(v(zAA3{_!b-u;f7+sM|C( z2?-5!@5wj{BpU@Ot-{Gc;;3~IJ^HewILRR9J6q#6bVoftCWDI&0rdeS;(j6`J6+W=XKGe4pv zV1cq?B0y~~6Du6D6z?NP-4VE%bfwBO)ki(00x~|2r+>Q7Hqjs@aEufj%@Rk+F{zJO za7REhV??9`1rvF;yv})?%RY+Fu{VoqwoRFgk2Jc^av;vL+)G|H1*|)evYMp8_B&~- z*`D`#ICqq7cL`}&iD8bAg1Vf&jzo5(q;{z!_W(#neJG~BpeILsWQ`(IE5!H zpSa+^i%$s!_4Ngf^99ZK1+Bz|?YxDZnuXntg}n)d{q==|^M%9rg`>npQi8OJVsMuNPO1Rhx+X>kDW(n8mLwjw4=*eps^jiSP)}LR60_|ek{kzWI`-T> z%o$xCYCKV5^!=f=HIQ1@0r!xBS_c#=_)`}6u!M-fEEUDNnD2F=57CL{e~c_&?@7p8 z>)=;`w$k;UruBIR^{EB!#fdbqa(AJ5mJsfn~^>cN3doiKoMb z=HrLvQ<9c*zLv``E!R#hw}~zH4Sy9Z4=n)FRuF$HyjClsb1PC(D@tQ48VrX&wqlXC zVe|h@k~_B%CbbbawvjHjkw3OkKGvvl0I6DWU>Pcpesr2c42H$_u>5vfEdnFAgN}WTQ9YFboGo8u@=k$N!~ZDO~I? ze(WzL9e{<#Vdj-;=YiU!0dEV0rvTGt3smA(qLxQkD-4CW6v%$in|TVL;}{&aKp;~D zj>wkT^PnIlpk_Q)e&QP{6(bi8gqo&7APcg=da`=n>s^ba&O42Qdy5varo-x^U58q6 zDTgEmk2=O^LPySmUA7}`VIv!;B~NI;+d^R=YrloFuJvPASHkFZ)#&y9=q-P5nymR~ zdm+9h>rKKKtetLO$l>H%Na6CDimc>SQ4bn=zZ+?-UYLHgM_}cE-{P2Y zH=wv=NVm}*nqGwyT!oU~70e9vCfI+hb}#xp#53&kG(0Xte?KrAj84Vk4kT;^Az;tF z>YPhKpT8d*N;6GKewyoTm?e#9DCUSdcsFbEwv9D=O@; z{Msc@()0A9PoSTaHK~7okwlx7%%#6=ENyR(q+fGsBm*!jS2BMTwWQtOG6s@^09a2K zT6mYYT$ZbfiuYY250A#&IN&Hwfo~`$*aTLtTvm>XikZY#uC=FfSs<9}g^^1u2aYfs zSQC|E4E-wHm?Hw$Ck#0!{ZL|s9mvzYd?Ti?`Cbo=+`+hENO9mqV zlv#{0cDxJW^+FInVA+~!rxC2+|Od`4|d%TPTJ4c=}BAOPkP)hE$%B9Jc#25 z=2#sh4(``ubXP4O^d}v(y7n~+9;!Vapn&(f1v`3=t6$X|ep)>If^;Oyax_`oJ?(n5 z#d0`L4(*v+J~GuhTy^bS7d#fxI+iy&rVl#aUp_v5K0YNsITt+1Eg`0RlWZLLrR!V3fNMklHh z&PZ0yz|GAo7~QrX-c>uE|9WnqW%ra=Xr&)|PfJ$tngZ~~x|vnMgMgyVTChOiYuO>W zu{?t{`$=nM`MHPVrR#IC$jCQ2x9@a)ZC!2fCY}rmZq;X6SFgS{^OSf{kW&8IN~%G* zmY}@GY&7JfXj?8UP)qxurckV~a)lXpP4EbZ!~x=MEnsd1IHca}GT-2F*FZzsezv#| z3qWtJAFg>vJpDp%zZBfQRKG=&{2Joc8d2gttb7-<;u&9ZhpiBzG1z zihB3M+9P}AHqWg*|HM7kP49XuAs2cN<$Jg_dZ@LoC}a0&TzLTSKQt3QwzHSFv;^X* zKf2jG^t7}9i9Cm)k1w?zClsD;3m(qt?q^F{I#;aHSDwf$9@kUbX1+dOJUpG-JyY@n zJWC3AC;{HA^K2b4(+VA)tIwA!OlK`n8xWG)zus*Bi;jCLDTYUd$HEp(iAl+SwAmS% zS=l+cc@UU3yQnx(HCw5q^1rm%jsJ*P{+o`ECaaAq`*(-LjQtlKUt2GZj8>f6 z_%AwsR2Dzw+x0IxzBCgydPgEzng*leiF2(q*?O%%KsbL*L|uWto5Caq8G8b4W{r%oAbK z$-y0mk$2SxXdPH0ontwj-09)PukC*$j*DPUQhRLu zNT#-QtwRH-91!>?BPT}m_5Oi@<8v=8BR9?Wdklxsjw_H{?mo>xT$*<55)F1uK3@85 zpc*>MGqzKy_#!oBsG-K%5&~6py_-C)%u_-}ThT(?Y!Y*D zQc@L2p^&op%H6IFm2IT?$^Jl&im2hiPtfY-_ToSYw^8p>G)C*X=WSV*#EL5tUG0jS zXQvq0Jk}>?)f+eEZ5-3-uNq?a86-O@O*mh*H8718KI!|ku8f!VJ!IQ|S2ZNiNZe(dfgr8IPqp0@zLsewU(@awKH@71k!7#-)C@^7aS-O$Fu|DGD9Wj8k+ z-HnW#p}SwVy%ldVpYe_JnM`!Uood}q%iF#vemmJdAuB6@vVCvI%g`up=e;u8=_jZu z4-&^Nqo-ZZnl@;iFfTc<{*8D#cNB6wovdXvkW4?2S}Nf zZ?Ggnz@gdiSgUt)3XY4h$Kn#f`Ryo7wd>%9xBZjibiC55BO&dig3gU zKIWng9ce?oZIsoMPTWk#$OuK3*pxOln9>)eHK(1NRZ3plT`#sfovv_Z=m%NmZ)sMI6ok;_LnEB2U{NsA@- zD7R~1H_@w@6zpEB^)LxnavA0uM#2`m_U1+hW{ce{ydk!4xo^^#nBg*7_h zz1Up2?fv2z*P4#nonoh{gFP~plj;}jkEfjk){kc}6Vc=OAlJ#`#i#`P(XpzTJ$qe!knyEqT5_tbvJ$PJ7s)kC!vn(5Ks-66o{e%?T_JjkbDm z?CAs2U&E|7_r^n07lz-)_^zf)i7!SgGLJmUf!f)Qm!=5y0dWrL1v9K7^5wNHISg69 z>=eZt#;$Lk^7Eo@Ts6YCM<8SX01%PdDCkVuUrbAQz3)uNppV0+m}m7=kpzMOVea@W zqsllIA|QafJMPa>PtM5!kgd%Jz^aX(nxrmuX{$K9YneC310_n?pD$Ujfp122HyoB&CHeHsd_y#bYs zA_C?kFpMbA6ZIO2i0HN~!V?YjLbb17wSGJ*@a;Dy?LO(2Gu?>jMjCXJI%(pc=aEKe zhM1BXY@BvyL3&!_FXU>wz7Ye0O!?P{7fe2KL;GJ#sOM!8o#jdBFQb6}u+~^pQBikg z@CF)@rm#I14O6(kd}EGd26q>e&RAkd-zt(oEsY(Us5b}88t2Q{cD()$;a*273C7hAEGpsuO^VM+OwZpuJnto3#CBw!)q2%4wE8&msRy&YSX@*om4ioMqS(aQ;rr4 zCF)z|m^8xkDE|R+eKdg55tAI2~|ye zH7x^lzlRvwg&X}1%EADyqg$YjTfA0K;&;!af5e0?L7Bgj3;x?m7*i0O@W)CRp7JLp z3*)&_>6Ou$wF!S@giRT+wR3e_e02wG?F{n~=2vu-)b^CXk{b0rl}!V=tpoLc2haah zW7A<5W~*7|iV)nC=*u?H!sP9AE64U4}8-iP`1Rnbpa^0C#b9due?a zrXgJ4+TYy!qaoZnxPUnb4^JXb!n*XOCU<_C8U!MoS(g4x_V7Lhi z_{4q+UJB`HSs9+0kgS42@BGXRNM4a|p#lSHb;*A(oLdlI|5-Q>upz+~&f}1jcEuLO zxtY#|%(;>!m??dEV+FFU$cwP4aI|-Nc7Abrm3R{tbNlcZcmD){6Fr}V$EWcM_?-Uz z-N7V_7ZR#y)RhfEu_^3WF3D(hq&t*Sf(KQK^IMg{&SEyp3#-^#E2gh8Uh(oO{Pdr` zH#<2Lr;MZuS0EqWSm%Ap2o7P|GTx`5RYukpu~hHJ{j8(ppv}@(RZ#g&rvnx{s%9yT z>@t~8s{3BV_0tk+Iqqf7W*kK$b%?k$5PLE%Ck{o4!L={dlY&Q3h}H~T7xQZovwSC0 zcaBpU^G1lOAf9GW&BVc{^=z^-k*jO=FmOB5{*01#J7)Bo;A!NWd=qrKAFax20U zhP;;Ix+m&O@xthL=KRsUM&f-vo3BP1Ot5nE&;`kJG-_Jt)x1*jqJ5+ zX7sP2rE#h(gIzDo3uR-o>U`MzJHUD53Z>QGX0R3KeG?k4yOE3o*+7a5tq-Gz>qFc( znHPabLR+P&quu8m6-{X86&B`>&P(I(l@EWiD{=``aZrXX4#d9d{;aRHG4_CgBj)?! z$Kadw19%`Cw!8AkjaZr8f^|po#o|dF*(Ke?>p+_C$oT$0D?Qd(6PML~({U|0Y(&+v z2TrhFZ8RDrC-mi1Z-zkFt>yRo3=-bJ0U0_v=;j;ONV*V%a7sN|?UW;M4*Xi0e;+0c zF4rH0ihbVw7AA1X^|MnZD&V-vShh~17jCuwd?0lE@gh<}0lh9I(wX=ztk-1;uKhfE?>n}W*aM7|s-FLy^IHBbe=uRdyg#ZlA{&SyG>dL&&XnII82Ks6i zH1OpD9JcTELFCZeS_Sbji=>BnW2G3Lk#rN%+Oqw{yiDa<{4O@EgBya=PYW2#G}db<|V-1zNfj7`s1 ze4My$v>eXZc-e37apHeJ0s+sf1JtA!3H_fvu}kj;sYpHI2EDi6H4qJdkEuYOMl-?! zQNr7@=_PKz-R7!e9H!=0PTJ`-<{Fb4F=vCtMv?%C5qI8v!*5dB8+XW1=M}!&T_Eq# zr09F%AI!!g9C0(KS@T{+*h)}yOlC3Cwo4joD#Z(W zWGI9&%K4wZAaJip6SINH|KNpbla=yBhD?>b>Ql3M@gSm>`^wP)lZp805OJt`zEXUe zccGFBgjQHsF<2VDP#O>NP?xWi?WhXQm?~mxGSk#{gsPX!-)!;EbP9@SFFv) z9=)5PRtLZtb{)Jt4VbB%zbXq3KGdc-n5BllE_2E*H1O+#@7I|w3*54B-n^e1h>5Ap ztFkatK~=A^i>@kdI>hEhg?D^RM|N`upxK~$P;&r5SSF&Flr{^C_ynM4cq<%NVXbBI zo9cct(I3GFi>8P-NE1WHwkr_ro%L(XRfLn@fy_Fm_vMYdwCoOU@yqnyHx0Y8*7j2m z%lG{RjmKRjE;pGg*S=gWcUQe`FAl@0FV$LK&~bPY6s`jJZd);rtzipiv{gjr*>+@K z4qy7Dl>oEb4pMR(4&fj@c!J9gIyPH(6^j)tnYb?8Wsaa7zO_5onJ&hUwm!cGH=aWX zdI(}{Lv0&35I%Uc3aOrk@0c6Vu29mm4EX=b zRE`L)hUIMH2hruI-+*t}ZJAiMJlMkaVqS|Xq6dGZC{dpz(c6t%IU#2C;5P-|1gi9? zh%|&n#DH%;M9(gzDA>%HAbj=9`gH-Hm(2kdwg(R-ML8_JQTexyq0s zS*l;d2_DTmuP^T1iFU0UNu*%f#Z?4jP8^lzbEz?BGv@iOA--4v~lv=^gpG<GAtR$;u2|NZ3yir>>gUHR=K zVg0auj^VW+{hiX$ea!1}{+(|$Tn#iXw_)8i?cO(5QQo zBfTjYV=KeTzd~EIOZ06htreN}I#F~7)JhlpN>l;6KY zg#*eZt&+H5^JW)HaG-{LV56jAI^27qSib^>ppIE_&e^~k^}ya;|1_|Ze{E33ti9c} zg^r&)DHdoHDVW*FW{x4Se>OO9HfWpyioPltkgeuO8;3rl9u$rgvY;N4a2tGz1YXa3 zc`@t1+iP?mXZFzRHeVWY*h|n0b`r4*^=1e~?DM4s`n86I1;vFH-Gl(RF#tqi&b@)y zdtqnXU}CAzIxu)_G#ryLc&axPDiKbl8xBzq!D5W~0S;qB_PMe*dmxCkG_k*(i8$lJ z;4Ot?atQA;iM;I%7wz+TW9lPr8bt?*oG@{p3&W9L6&2FJl+uXiMT%5~_*&-$zKV(d zoc9AB;x2Iw&w&M^0>B-=i>~$w*8s8Qtwt+@qisw*zrg9J!V1wyJl!`$KcxI*iQIX{ zK**FN$fKa}=~&J>PPR%TFf!Ep`&=9;1F_;9r@ezueO{a-e7uUi8OLvT7tXkoaDYcf zypTF0Zz%wv2%riR%8*R3ibE^b@M5FlqEZ9^N&&oK61#b5Jhlmtx`gS7@Ul6Nazr;b z2R90?q;l9$)jgs76W|p9K|nWVHZSR?RMfPFCrlPbH43N50jg#sL8XLmV?>+nkr<9o zc-5K&lStBrCBLyx!g5HunxTii{Ec8CoN9QAmJ+?Y0LYKRp>w1?Xrxi|q@j<($)5sN zugKYSNf2k@6<0yfJ$O+LAfZ`WZyXMjO)9`0z!Zi<-0y*hg@C(H4IqB|sy^ewo*#8S zt$gjJq^>(7M>-w~l#RtP&}ALu)(T|fNZ>K^plVIpLrwZ|^_nJt|TL~%PJ`ZIN!;Ucn&%}9) zF)1tol28vxnuny^L(+)zGkEi}H1l&D^Yaq&^Xu~q=kts2^GpAKV7Rh$NNB>KFv^mL zco4)pGL-=i4J+c7ILk}1B!svWkr(B@-Z+&TXTrj~)Gi)9Rc+Okq_t zRHMR$h+$t5L}C6a4yE$FISH?DC9iHJI^z%Nfl7JQL`n1H_aHbFfDQ@(4okDDmU)rFz*ncLQAZvCh%Q(B5a}(=d7`PP&*5@x&6@IDLlxC<&jQ&Ux%{vCJGjC{cDpjO}6SYC_ z7-$fngk#$XRkVR0{8H1$*EIR1Y1*l2HnC~Gp=oiUY5AdPm85x{ulfIdh8q-zdzwP> z*rtk#K*oYesnxCnL4VcwldiE{lm`Q^wVbWDof9pT4VINHF@wh*0t zutSi)bCer{c{TF2Y^U_1zXBtp?F&;G(ykirN^#~c)x|&_kE(Ky>UgIvokIWnxoUf- zxUX8>@r1QTN!>s1VO^3gv&U`|!g`APIvcGXQwFY*FAa8$J+>@dU;2C8Wqp20r+8@f z{x25JNtstDg=8GSgLxo%T5l$0S&m(Q%V}TUV}%M2N(R3>-64ASLV3aCFQL)ODi)t& zMu^ZUTyt-UnHFR77lFD$SfOCB(%B`8NUZk|we9hRd>V+*9hg55-POoH$}%*02oEz9 zwkAQNB=CnOw1&pN^n6kTk)6Fj6z-{U9Nudj&O|LfM$<;>=8y6z_f}JNf3bK~OFZ_|d}PsV%wA^9J*i8-vC6=r zfV`=T18e*ot(ro6obajp(?b~@>$qEKC0o<@g7g??5nQat-{sj2UCa!}6UP+nob=1@QJUO#!O*{ai2H8%=Q z8b~|1|JACPDeLsWA;v44a<+vg1F~St_(97d7pM4{71GKeM@TeJ)32l8@NM|tQKHV; zP|NQ>X6xss8nkAEqe-uaPdVkq8N4h|0XtF2mVQx4!84;r5j zTFDRF1rL>iFgsljds7bkn-2$<59@T`-U-9K1sqN498E1l-iIB{HyL}b5`DrE=Jm#p&;ArvVvm4P|!XtsxppI#BpJPNv%c~Vgr449z36qhxhoL! zrN{~yDGoike4-BsYPn&XqR&G?kP(J&k!c1id|l1H*l0ggp?FVQh3X@ z-WO3cr=M7qx!qN?H06#MWTifA-QV-5}iUf8=SR;A!pG!|KYinuGhw*XP}Z$Nki%b)l~_E6;N%@aH2v z9qbQR3aw|U(CLDmJ#X@dSqLBSLn{_KMUv6vtWKN?ud?r;Y`56j;v+92-HASO; z56|>ZO{Uw`GT#U*Qkt1da!Nw{K0$a7Qkg$hpkBdA?AP}#D^If{fJ~;EB_l1$H{g{SjN#VU zRFxHN;wjbZDyAp~57d;bw5*Q4uYZtO)M*9dFzYxEn2SrcZF9n6GT#mRqTt^!Rnwe* z9!UETNM4k8tOkjbD$p6yG~O4NP1O7W?aY6ZUS6oW ztBiELm0;zs{#4bw`sQbhlHeaLk6Ahj4#BtUA^hZi=~TohH)$@TS0hl(UKfBlTobZrg3+H{KtpH6#N!?h3n7tV{urtKa%J*e_V!Tave6(lvn!Vvq zvg7Pb*uvRAI@-tfoi>$~^xh6M9sK^=F2z|kPgIzGeVuVelxjUz!W)cVi8>v42`Sky zhC3R|>`9cKmzRSQW>glPke#~^VLB*Wmb_YYOhrUFaIC!EXMQ8gv76?OVKr+|)ap*JmxSx41C?R+IUeelt;& zl8<`Qr0r@hTRLXf3n@OV_djWcPkonGfgzo1-G;{H98(<*3M%cuRZEhr=y}gz*?O&U z_`1prPlKU`^!MXgU;jEC9hIYK;Q7D_C*-vYZ3XJZP}=$yRb=}jMn21X@a~|i%yu$w{#kb_K1USC#~4c6(n8QlWy$7 zh{fiZahURxPytvwv>gFMxD`Zv>i&4Kas%RSh2vG!kkkc%o^J%G#6&mp8CDx7kMFc z+k_?P>ut-p0>#H_UJ0jpDg8)})3ww2@yX2P$ejE!L!t$`#O@}!IdJ6L!?)685LD0n zZPT5;c$2lnVFXpXHA_O^K#x7hm62>$j6P(8RWvmBU_)}bi&wR_*q|(tjPQ)1yZ`ku zO`G$@P8WX;C%Q0?oI2*j-?wKkM}v$O z^ZMktG%7wx(1^XSn(Md4μW+Tr>i7S0nA@>#uE@gnJxyf2kTz7*pyJsi?6*Gnm0 zJzj{CujL9`Iw%^^T{5D&d=a6qkFj3A$Uq4;VP$pv6pZqNj-V@7;^}TE95EyV*K(KY zKliLQFc#|fFBbYwr0t(Q>t_R3xxbTEWg~Bx^I6^8U+1sz`PbejsY2NS*0OSsb1kZzOX`DOhI5=5sZaKC**`BmBc0Gge8~x<=6aUfsVt-7T+lfwSb{7EAcuk=H~t(?(Pu^Fr`ZPXcA5JB@Ye7S$yDg zn|i*wi1RF}S|x1H`tc2H&)TCn1lzN64<*!CEtLAe<(4niTKyl~y;V@#ZR4&RG)QrG zEncjK7AsmP(&8=!ic{R(Ex5Y|cY;fChvM$;?%C=4e&5<_&wuu;!#%Ten3LonGrv5~ zec#u$t59v>Vws-6qG~Z|0gQ!Zp_lL%myET0;}R0F$XE8D$= z8@8Jw#x|f>?db5+)f8anI^XmSr_*H*-Z%a{hQ(*p&ubXBR0gzi$D;Tp zpgwIn+oi*SX*`%9%( z$?VI?ChOw4+7M+IQmX(R&I-%7i|ppGa;?C{^k*c`JH^gXFHU&JH5%kmweJxhSbF00 z(caTjIL0eCpuZt-G~MDPq1?xT2Fb9*sxVRc(k+J2XH1iFo(}gWG9U7Er%b%Vo<>)ch0V%-m7j53M1Q1`@*pD(tw9`}_}`5(0# zS9lNc*IxrLi!NyeG!jU(QdRN>z=9c`O=FR^N<8pNYO5YXiSD)FC78gCk_6)*kt;q*;`S7w!Pfc2-!!+3idAs%cpk{wj1Go&+8^)2F6d{B;lFgIyneUr zi0Mmq(k&Sn^p+d5ScdE2(#5w0#Mms?_fpK&+GV0b#+wNe!E)hlE63#n`gox0j z55S&-6O_8c@&;g2!=W>UARya#s}nDNCpJv>g`i2{pU-qQWd}e7K@>-igM0!>9dJ1u z)^wk<;N_*-Vp@zkp4V~?UlY{c~S>wRaDrQSJ@xDk!i&phNV4XXD4=$T2}GD2FY)( zhpHh0h$wJyG?M7Tj+`ZF4ywdur*yzw^^I086~>BiF{~F-eSF4>VI=zW6x#Tr(kJK9 zE_8GW-q#=R^SYrN5erEP8yn5P^<`vj5EUX1lmLVT)QleQ5LvZRhtxLC(aO5VSP>d| zM`+mGW*gTyFp?Q*=t&Wxl5(0FQ}y+=vNmPr>R&Xcdh2WJdde)aJNy^9X&Sy1b>Vv+ zYD}ak3w=2|w$x2sYGS`_tSMtPH+)_V_y0_*_4X9E7 z3QGnUvH?i?)tr6fpnz?X)W!kz6Ye-e{*8C3^CN1eHR0>BJ3>bDqq5YO>Bm~Tg0aa+ zhk$Crye#-nv+83WU$3YP!uBM{7RKEoYjX|{Or@zFCZdfy@v6^$yrIvYj8&=4endM^ z(j@)kcoP5?xBLl7Ae}5_u&d^K_9sYl9V3&tF4pxhQ9UG`X=%I4t)UL!&|ODW?!PV* zgHjynHt@|vjMmiz9GjSOG*8ST!=hkp;P!kKoQ}@GG?QB-BYWSDV zJR6#~1y5a08<%0oScq~mFS=-c=7OOz(=U)L)%+2tM?eX)cy0Vo02V67DhaOdS`*!M zBatg*6jTe5AH8nGU}ansKM){_$Bbb^-M8L+=U4%))Xe2msPDAxBIvnFw)s`sF=HyzW#K1krI1}LUP8Z zcXWj5;UA%wgoZ^$rqkAZ>LK2I2-+~+uOs~g^>oU}!qiFoxcKd_2Ca+%$eCh`!CH?^19yzfN5cEpIc7slEl!@Q}F+0hx z61vvUwf^i8bHHjV^GgIPco%QS$&>vS7@I?eY2%Gj48~^}Gh49jY>- z($Pmt$c}aRWJNns5&K@6_{ypJPB^(r@DNg{%7tDyi80EkaC<+{DOM#ac5(Uf+!5V$ z(jrt6=>~ho%)UoA;0#bOQT{H1%*Za^?=H9JUX|njMT(WHo0QGOUajvJ;WxQkC2#E_ zzaM*44YpJ**=#?gf`4brhbTDxKWNWtAw&Ng?O8)VsNLHo`ybkKv06wQuAPor@Fztg zr)VN0lrR%1)RLsICP-LQ(yNxcunywz6k?2gAVvXGcz;rOM}Giaj)&1jXgw3w2O85* zNN@uW>R?jD0wk;r60vd@k>QNf!vpnSQ;Xb@3Q?y0s%2^yP8`vJgEX}nd3-qTeQlB{}p(4V`cRowzZE+a)B7)|rxooQ@=>4H(12 z6D5!&!o?da${T{i8z&(h2fJ9^a*mTF2|*h0SnrGFOV(Gq_dZ6k2_28qKy_wrjMoYA zr#g=jyNEXm(YLe@@Vz7A<&EF2On9dj^W#2VoFq|pK4u08vIoaA%z7+-47M1Eq}h)Z zltOoDjJH!y68)JdUKrPb4UG$SiJ999RlZN$T}udKO!{Q%6Xg;Y)R@cyP9j}T%1Dl; z4)!NXv@PUKDGrG&5cVobPSUpT6W09n9G)7GAM{WO% zQddb^Z%og2##ok4HcQU98VK7`&+L~TvV+B$0JHg+bWnYRX*PgxkrNJTIZl>MqWiYXP9vwe5}LEtpE2kXN-_9>N(Rf-1&@RpcIJW`P{Lpg%^h^klqnAN-u#IT z!)t-yUNztnN)st_=7~4C5ijK7-)CkvWGBq!3Zdo6HDZzq=QY8>eHTVz7KXPWE!0WL z#NaFJmx6yS49`4Xpjb=>p9P0@{k9;ez)U00k`#d%1kY4ice zV>H0tUx4ro0Lwxnn!+6(!0mHjLhMgQfmEm+Hry#`bvEGSVk9!oZ`FKoIcAxK>h^qQ z{>j9@u0_G;S@GqAwEb^6>q28#G)lh?q8B^>i;9cGNM3b@QvFUzhb>&`AZd*dOiMGo z>EclTP$~;EXpaAQ*??>57E9=$43Y;+zW0L7*V{648R;q5!j+{Unl#kK2o8Z0K)6P$ zAzYEel=s;z52ZL6;8xiojiJDj|9ucMEjV98rjpIS@@*q*9SLZ{0pM3+;xC3w+u+fY zW(!VM(KpAGt>wJxt4f#3rAZZk?H1$WUv-BAV85tNB8HdU<_p%V5nzp8#Lm{B{+OkP zIAxc8xljZD)2~UfM(RJb=kP;pI5u237P9})o}(d{io$gOY&b=mIxWq5W4C&_p(;b9 zTGPdPtH*kvdA1RHgS}>hV@VzjY>eI9;J(=4`7iC6AL6eG33P)5r$R!Tp|I!<68Q)L zku}EfH^yl;Cb<0_u%QmM;Dl24)mYZ}@287W4;rb=%tLU?l!Ezzn#>jt`|T zENtpAUFT2B3}Z+EcI%(iRvsCY*+-O()Qm;`SNAAwsm^VzGHw0MH7A-G1syFP4_a4Q zTaWqMF$dA!D=Yd=Coh;Ouxd=bd6g!$Q6q=1^$3SQo<*&v62@tBw>QDDd}(v!3yR?$%*TgOc{%Wdm@`LQL3t&9!=UOOf7r_o4|S*rCJP=9qS+WDf3qprSr|i$3k} zK1`M_UO*wQcbC6=s{J`INEV(KJNrFbNW@cr^ix+@S~hMPUU=+4i!_lia&4?YNb%;6 zw)Fv4QZz0=$4%&9Kr)gDHUh^*r8)?a%iFU&ZK$bbsAXxW?P;ike7H+sxLa$u*L}D@ zZFsO{cz9`e^l5mUd}LB!WJ+t~UrF0S%gEBw$jTFRWQ}}uLtu1EYZNAF+e;fgXc;|P z8a;U$JtH5x5E#4C8oO~HyGt8;Xc>E28hd#f1HhK_g5!wV?D&IHxz#s zc_ye^C%HZTAlw6my%EtuV3M{7A4eqXr$3)Drc|*JNI-C0AUyHqsd)${vtBnU2;TE( zN~JZ_LBG2x8X)U2ty31J^)zj8T;^2?V5!Upv=rI?Z4xI~aoih$Y>U;D79izjt=jf5Vg)k%vYE!;1k|}X;7@zRi7Lj^7 z(~depWdm);e4n0G`=%FKFu3F#mIgf9(a{ET0|q{pA?$d{)sFFw!G zMSKamk@06;agbOkH(!}~GbQva`Q;1bL|d|gY?UVLk6zxahuf-Oc+u&`MpZAyg9q^-c4v z0s@A>U|aY`c*GnFWnv!;dMDSMR0f?VEggFEH6c9$egtDar*(5wyZ^0KxvKl-FVxp> z*ET;V!jpS%X%A*DgNmAc2R~b7h0$fpe*F|_QmeYMHKx8zh_)2P*YV9N3x^a*TmjKA zY)KQ7>4)de&$gYEr5#hsqAtC0dmlt>VPkB7t>H_(Q^u}WAdzJO&?@1IC?RSKhwVD~W&B5Nm`8q}y6HUAXj7^^ zFdN1`t(SetWiC0Si%`*!h1iQgkqpU>a~6-u8#cCdPIf#`_A*Wm+D?xC-LqOX;!~Vn z>73sDch4&Q>g4I=6hL(bzuNruECeEOMk@%%t<)PGiObAxQ6?&}IeXRF-gk(N8wLh9*CAL5xJE)!zga&gso|xN8 z)_QMyv4+XzL%O5x`k6YW1OOsu_2M?9q(04K6;EBJSiR(EQ&_I9AxN`P8Tp#$qnS_F z3E?@YBL&zm$#IF<3NNJaO^YxFPQ^$W0BTPMy~IL6RrB)?fYF|Vy~4sHBL6Y;{oh$= zl6sU{cveQfmrB9Ed)B{MXaIspNCTu1_MED2OY;}^ZRzf5YX67!oSYYt6E-?r_-A_N zZx$L>Ti?67w!S#j`Fp+l@18Yn^04UW?|`LEO;}hQfmv8h;qDrq`*%=4fRE>$Hwr8Z zU8i%xq=W5QZ4-cm-(!TiVggW+UlE8|JtX~*#%0#<)a$3I&L47?Hd53_tWbFp>hsXP_8+XVzM*KC}YOyUE|1hhROrdq4QBE^RvAzF@T6 zX*EVfu+A>vp;`m5Kup?^W%rkRf57HMB%~)dr+gj~%u4j3W8k&K5JqcHhlgAARfZsW zuN=jE(ZiBT5a5|i4r)V>BsJmw~N*I|L26|56*@~88 zATbD&`2fp82?m|W;=Zf=eC;lw1BPXxlghbK+JVeFNtSZbFxqngb9RbF{eHn`Wt*h! zRQs8qySN2YQrYS5H~S`xN-KA}S^k84($KU(hT@`}?{Sd5To4~~H!YfCPGMNIaq)iq zg#&jF6}c5`&&nfCJQnC?b-@fStuM}|x0B)igP+}Gc36f$tASRga&>T6(Sgi*RM|~v zepJ=Z0HZw*|FdW13p=bGS;H@(ZxIzcu3sWGF=l9SWIchTXCFvIwhBtDOlC!6EPW4q zSu4Ko{PJaQx!fr^{hU}VgTxYe#Cq1D%$rlv4!|ot>$=#Rx1w8T={oC%r0|V(uDv`4 z)#E!IReiwX@MZr9=Vfs*P_E}b(7Y$;cQM3ixWUPAyMlW;!t*Vs`ZejdF56Mznx9;P zH0JKI<5Iax9Ann&F;{;mW{2KE2R?{dz8^lmAxE3O(>Z?MN#nO*Ppg~gu|0k?#TPQu zs9<@sxIfzB*tKv2f4jW@skClLa`V`!!Az{$X~2u5!s1z6I7+ub}>qo z{a`fWv(;OU1gFuRv67-z$ZnoI>zZtiJw?c${DuthPJk?C5A^J0`L(KN4yM}-po>5f~uNOd^;#oaW2mGgfhB3R;vucwLWKSku z^tdzxMrWF(Rt{g>+$>}QBdEx6XP6J!E1IYU#!u@ZXZ{E>+E=u}U4))}K=$zLS0+-h zEc7gpXE+%)O z*o5vphFGL2c}(Rv3c7q|MetyLr4o9%e?HsK{XbQAwhX&CGxS#|EJAIHwzgWtv;_CS zLcaXys9Iy?`JBFYxHW2#rX^&l;+4E9*UXN22O777vuzL872X)7dcZGpU8FZKLtm)@ z(a>Bk-%UP@_FQVj_+@@jr|TO8kF)KY7gj#7ICVVJSUH5nCllZ5LL$oT3%@MG zKE7!{hCMJ?Q)|;qwQ*v*+|KP$`%EINF@nb0#e-O9gWI?M@V#{{WtE1)^v5kn4?nvtu_QeC zZ{(bi`Zsd^cZ3@Rh6EQw(y~fmQ{3eI`jmgr$~gs91ts;_rLDe@hkxC}d2Iv5HC?3* z{S}Qc194wX%Rp?`Lvqh!TK`k=@8SB6(SOIet=;2)Rm8(jMWaup6E8JWFAa0hrWt7S z{7dV}Sy$i0@4>0=;f4O8$$_!??&-zh$wgQW4RaEAExk<4u1(Hw&M$BGu0e-3UjAL| zPVT(S>_O*tq4NhXuuOV$|9Jc0V*Tjl;N)uK{ATOy`S9%Ka}XdrsB;*ylbxVV5Tx7n5y zcS=?i4Ml?1fKp;x0QK8?`}z@bunY|s?d11A84#tNju7+%tc>E|v``l91FY;^YuVhH zW?ObWhLTXV564EyxC{WaMb^!C7G*Lq8Etsb3FHt zlA}1@?PNjTGOIU0=~aA{Jeb!|CSBHLC3-Mv`x#7nX4*N5EU0}=aDjpd08o>MJgF0~ zS9`;360Hv$dTp+Gq-3As^&94GasYm$_xvGTcwDdOx-C zJBTn~{`VIQT#?AT%hUn==U3wvkJsoXr^xq}bdHRJ5B1@8lxZ&7F5;tD0G^JN+-GkMM7ccsm5|4db76$HS$jERYP|9N z9zO)9LMVTo^<|P1T5T^xVf)7AMgq==wyjLoqL1Ja8N^<3ssqW%FERF4u2wSQh z5NSTDQ!;QNmgizd@2FhT+5N#=V9;PDxKBuM0P$auF#*>0O8d9S#CIlFxN2PIMu5ES z`*1i~Y(5wER-4So^_^TZb|O249>2jNa<_rj;JtlU*>i53mMKam`6|6nSecFc9WLq3 zh(2kGxpAPNNI?)**MlBy8xy6XbsBbuPtEt{PXUD{={@$q?D~1&mSV_D$h!f2er@(C zfj9Q{GT-qEK~r=lN0tUO+RN_^iA0r`f6c}pUwkMMb?n1tE#>^&B9uFqj>Rru(}3l0 z8q50OltgsX6=izw3yXDX1E>0($kdsa7*oc3HWv%7-K~6g#f{md*?6LnZ{Y^gf;^px(P6m;1hg5|(tDFCI%jeLz*W(uR=CU8v8a{wq0Kh%FiF;s^3a$$F!<%q@l1(ajF}Mx_KI;HiUh3=5yYYwMQrXfJJ$TK8VoIe#-zNw)P`#>o<+t^E4_G)f#%{=4xg|oaCJNiCc zVbnL{9~kP&xMGrNOn4K2jmj2W#y-oaJqhnOZ@%8NWwb9~IZhV;d0>~hynynK@@KIo zCBE#g!R%p9&UgS}em48a@@GRMSq9RR^hmc2)*aL&R}GvnPWx?1UIV!p+dt7C((>rP zsVYs=Ol85$&|eG(v69+woZdrwHmT|dr^{WhOY|^G)cRy*gzWQ5P31~7CS=0vny$;t z-ym!4%BWU;1(!RQm9P>g&$hM2Qx#p5=>2K>;`-{Q(vV#Ka!22X@Ng;rl(KEi5YSfZ*wUSHwV`bH-x zTeHOxD{*q)Qd^#Nsl7g=#5s%Y7YWYH79ml2jR(8F3#)d6QbUv3$Q#GP$5189kIn1& z%jE50DjPAXrNys-n#pcDhdK?dBOV;?H0F!``8wiEz9l(tbZ?CQ++)>Aow$|1g2I!|nFk-INAM(%+SlhM|OK z5-=T`Zo`hvD^h392m>Iya;Mr}i{+(l@2ZyNEFIh3@OR4_I)I*LE)@^MGv$uWw$V0T zx0);45ih(Vs_EAUF*P|`oZcjCK@-QoP z`L9YPQ(<()mV-BKj%-BFV-Xd#6U^;D@@rc6lUGr8qZ=MauXVQ1b>5$ZoH*8KdQ6s! z%Eg6O+)VRBn@2c24@chI>a3>j_w~A;RJ6JruL=$&uRP?5om!6DEgzt(#})On+w}=S zpXYuEH0YjgH*!4RYyw*z!Llc-)|ppYTVColZYzwgf+m`B0*WiA!(}ohEfvhj#V;W7jix04&Dih*!!VF9FR{O zY$_G%A@8(-{bg5+2}brhb)*iZMdMDrj}p((9#&^<6v=?)0S zj-d-d$LK(0OpfUxb_ON|hDh17C&N&h-h=UhCQh;F_pt`|AVJ;)<9(2bbo8FH{Rg!; z|3D8lRaDvexGIGhMR1I}QPnC$_X8a`JXg@k2q|{+W^Ioxz!xp*0Z%Xg zYm>2euW{gq0_>)U>Rl59mMjnBd{b|LBsEZl&-BM&fq7Fwoob;@AZ+=LY%2WL^8wjW zufVamz#+6y%q11~qj9iIkxQ{@h>U5uWZ~JJDOV+&1^_@(3Fo+m9KfLBIF3lF05Gya zNJ_~MdnmF37dsUfYHq_hgOJdK;hZ}V$SR8>9ul6Mipu#4$SdLaso}^fVecdPru7wk!U9MDG0bQ5;U1!Qe<)2@L*X}Q?Vs7 zxcQ*;B&9eSEz4a^OZ6a~K_gk05bTH@t#}vOyB{^$Q4wq(&54i5QEWA@N-gf7swxeN z6IXgJcFIt-t4#>?xsP=1)jlB23WLNDqtTeiIOI#e2Q=fZe5|%ttZwshN!hPNLrL0J z4MkRWy>fD_{q5@4GC-` z#((2ycc{>43K2;vp4&^SGf6|@t`%LZOTw$AUUU*VwBbP`raKHILJyNmN`0?h#dRML z5`>}h{&P%SwB%e6!b9Codc#BiA73EoG4-Q1&`6S+`g7Qgi#mvKF1-YZ=~B{g zvk+h?RbvobYjOyoGlc}9H#NpXat^r|`XR~E4Fn4{SJI7iK+K;VZ0e?Zb#;ETs$TA< zk$5aM8H>1unh;vD>H;_a0i2dszSUlbp+f^PWzD`7{5}ikjB0mZ=6h=VuS2~TbGrG% zp%blLn!K+%+EhqMZJkrAwKa))EP`|f z`tLLo0c3HIEIKU78rqWMndf3S2bz%g-7)Wg*lH%{!Bs)=mc&Oo!mO%fEt>C{efAld zj&3`J3hNn$I|H1vNYlDz7i%Jkx)2iGzidFeUI%r3Xwji&3VxIJ`<+YH9h!ZiY8Rna z#V3I_dADvMtw6S6YZ(FU;zn0LRp+2WpuDUNk9$w>;;WUS9$N?Z?K@9hB1c1$9v$~E zPN&}RArHAU*oxLQinVu&3^yXMnfs~NIjzq%&G08SqJ2xBH+jFWK)?V0aYg$-J;4_J zDz=0ErNO$xgT(>^Msb4`Prb(*nvy+@HN*W}*?84yLmF(D!L!&lb?=EgRokBWwYi9$ z&yYp19bw6FpL@?JIj_??kR5`o|5;{+RYAU~P`r;=1o4-S?b?>>#lxQ~|D zBI29@0i2^=r7G(Jv?b?=6riz((y@ahWfxB6I({sNdhDOvv{%t6&!ydt=YKP1FTLKY zCm<5V7+Q5r-z!X5x_r(#F4pzhbzB2A{r4*xpyu|3mH2O!jkeYB3F5qo_Yx+jlT3lw zlW1=^4}cul=_*`rxL7720YoF0@f=*=8uAcot>Y}m+LjNp7%&*VGgc@Mey zl-BvI?YTD*^OD{3If4r@4kCFT3q|P*#jOja%M0bt3zZa$)q;z)+Kcrbi;(oirq;!l z<;Aw=#SV(4F2SX4?WJCirT+A#!PceW<)zW*rE!YoNx|hQ?d2Jd<+=3bh1TVz<>i&< zIF4&)>1(){=HcUOf@QkcCu>BMdJkDh57l@Q zPwQ#<7`jnmh1gbE8^k-k3@=b^u-+^Q*JibGfRrJHf8F~kx=kL+A6~eKwAAn- zoXjGgI@DrY5|kWPbz9<|TU}{e5%mZdmC7)Q_jgQPmB?+4PpaB4K=rn5ryE9$EIJHf zCZkAg z^P+nJl=^7rh#OCc-(L1y%YiYUXyeNF3^m&vD%6^7|Wq(R}`Xq7+$UMWQvihC{+|)VQ zT{*_dJl{w-#vePzsyL@^x0s4Nr_sG&@VbCWf?3)x*j6vtp%j zUh=hH!X&|;pqIi_SE52!pLMS!yso5RlHm3$+10DBFi$YmwUW?(Ji%%eqb>k=_gGBz z_N%#$>+I)iNi0kQ-D#uK%T1e`ugF#^)W|j*$SO7iDmF+qUP!reNY)&;-z%5QSFbHs zEmX&mo0pL7v9!gsu#$U*Y+Dp|X2$cjm`k9Xh5?Z*Ei0og9MK@1THz{oGxSza-@M`%021-f%xq z1NNCO8PvMNwzC>VzG3C|MdiP1+DEC*leTl+dS}7Zw=wXKCs?`$MncZPmQ&;Hq!`T< z_CuriOG1_jZaYHcTn`(|jXL{2=TrF4iWa7?t1FqU(EDdaTdGD(FP57u=WyDzLRO(i*w=D5!+Of^GMuOkUrnT4;LbwPtlQkw@wr-f$5hQ^Z4H7 zo4^nHM*2u4;}9ZaMKflcL>)8&dE-xkKX(*4IBg3e#r7(V6~&$&I6J%u+Vy?rsmd+ka_u#-OS-NqgVyII^bda^hmY4dD`Ch z5Hpe_^2BEVuxumoGy&odaBa$E+AM)@}`8&=dyFhfWMuPf2X^2JHYkl50+UpZt zDGOI4@4ZL)*)K7(rSbZEClSgT904b{vh!IdoRxPFCC@Kg6&i0s;X-h+g+74b%j?@U zJc%z_lYYuoeoW1{OeJYb@sPZ2TMhLPRmU@y8d`}W6lJC|Jf)LDF zzGjp^fOrq@g88OI(n-5#eih^bf8@Y!hq8MqP+aBRBk@F`h)is$-U#IH^fO($5X9ev zPINic;^Jr*BID>IqF}?rOYBW%NSP@CvcBg>Kbq3HlPKaa?g$1$FGKw-wC)N(dyI<8!+hsNZK3_vHZy_M>-)yD}8nUv4jpO10LO5j02i$ZG zGakowi8vZw#<$H?*oPMB=qneZqNOia7(kMLb#=_?KP%Ur+FnK62k) z14=@-Bcp&M-s(jAH@VZ-DlK|Mi#P4LNoOLKvf|Aa8x6I~6}0wR7$X~VBB#?$#O5a|rA zu&|{K8;ko9TKXEgnO7mZD}`>-|?Bk6`8U9Afbt%+t2mnrZJFBO_g|=uo4#ORCw^ax@V>%NmHrCsHB^E z>);)0!v&lT$_9*fHsEqv^Vi86$)@S_--8RuD+5pGxyQwFA5{%j?l5VfATs?W3j~3+ zkELwFsS){pbZJWtup&2=m1YQE+Quhx^X_GjQwHdILJP&Ywq1WCgE%l=a zBR9(yTaHq4a;dL~>?`FLbeG?Cg>R*7DGP%gA((j~V;(ne3_7C})x^jaDg&DqpHG~} z_*bU00$FQ4f{j6sOV?lTx=QphJfUvb71Yj6L@(zqAN@A`)B<{kC@zw8f0M*<-cxT5I-dwWVcywX1t%lRgUs=U#KOZ3d|zd=ATh5n1ENpz$k!^ zrJlbYv5!^~;&&Tohg}cWSdw4;WC4m8O`Ph!@qyF@D8X4s{Q7_ueFaDQ5HotIh`Zo+ z5U{-vg_6g~%{1t$FF+82yiF7gJ4X<#p{)rMFRh^xoFNV3I1&>DxC$eGS;yw{Mp3Df zjpn4NpTkB5g_(Dt@azR>&4pNIA-fg%7zJ~Wdn1GIP_IRZ2e}XsvrqsEaO5;$_`3ku z+-HqAa-9dh_bm;v4N!+V@?bAw%NcRU8E9XG0+-~f$>f^?bOkrSCVud5F5z6Vknoh? z9I%lO)j&uj$PNl{;Q)XJ2uKAAj8#DRAdK*V8XAr75*=NM=&}~cY8&}e4}qE_hL$&m zbRZhTHu9V}ut_zF)YPZCFNQN19(|2lGz$o5#3ir+T64w-%)>5ik)5(YVI3e>YD8?8 zua-s%t!iNn#NojT0Xp4r9Zcb&An)przWqtA*(iQO9RQBY@Ch}PKRj;^Z6mxu5sS`o z4z+=ad)UzsS>#^S49s45&)P zXmcC-6{zSv5O-Iwj|?@EQWl~Nw&zR`)L&WQt+6vP5}bNT2-ZWQr&$)_&|IorkZY=Q z8rEkZd=WAU1jYmO5MfHkj{`bpd0W~b&ocW;6?vF+q%YmOy^plw-Rr~H>#f1P~?wS(8+GXo2xb1Cw(3e1bY8foZ`A{LItQrO89 z<`5`4g|fRo2zl~p8SPVj4aXdA2y=4kg z&G>)Gpanc=fk=z-=?gMl&5Kw*rLz=dEfm`h7S$=}R`Us0@D()hmE@A5J6r?*qZa@I zpnnzd{}!Wy2nYyhX=!=oe+hnriQ@m(qyCi)*xK53vP>d&3lXtK^?x>78ijmu``m|KDy@jzr?EeA=yS z>YZZxy=vB-R_?t{{k>yy*AMW$RmGEQ-BV&>Vsdh_FDO4CwkRaA^q-zoWpsKK49Ag? zQ<#zkj?b=5{A(&`NQE_|z|GN>ZQ1$YyrNQANvf!RQwho4Oyu@}xlY5@h2VUwshGFHY+Rn-5e~=w* zgY#J(ySXDTWuwr-acIc|v}J6!atzuwu~$9$w@%eEbJM)=(sF$IduaM^muh6@_xS42 z#Nt23gVo-t?e3|gv6=P3g`=*8+uutsqpKG~tIw0O>#!s5{PI@M8npNH3|6rEv$nOo zwgVH||Jiw&{@by7nmc%b84}jF{u&Zs+>f=R=fjiBo%5H!^pF2`to}+8{y%cs!}f0f ze|n)n0aU2uQkB%5Qpi}C;r^A>zXPL4rD5&#jjkXpB<^>?Fr-KnwOHs8Q)SM81d-%l zQrC}uA4XQQ|BJh`YKm)N!z>OB1PczqJwOQV8eD_BySux)G_C=HTX1)G5AN#5FMLh^GEBIOD?t(c@7 zIakOi+KF7q=rUHta-I2H*;}Mj#bAT|?r1|s^#yr28rw-n^J0}= z5y533jCH-aP!bB#XLczxhn<0Vo%a}-mYa!@lqlW(=h@4-T3vyt{?_|Em1(CQIJt1{ zhSNpMTgN2Cwm&O`x*)`bbu}i*Or68N5G;m`6XJEY%5k z*NV2eg=$r0f)-Zh>z|5>`GCb8ISel=@;OU6@_y$@&yO?jV>WIscCql=4VwBxv^U*E zMCYO;vLhZt!vUM3oIxn)iZ}!CSf;pmu_l%FI<{NWF-@r zpR8TPDTy6!zFa7snJvCb5pGR-@LelsDI=3UHjF%)bKy9H44qd$DBD{qUn_o)l$u5f zQjQrw5szDj@jV)9u`n+jUvoc=UlPh9-%4>Mu@LwzqqHbP)03tsQBJMQR7Ho5){B%M zPsOvk5wxJIQM({!_M@-EBWDt4ocRZAN)h?W@RCXO${U&I?c@F5T zhLv8du8=jY77Rs14}gIBMiQJqB$~x22Kcge)wd|8tu%nlgIqI6=im)~(O^bXJA~(U zTGdKz^orh5P=j07VLF0L&kJM0n;WX7V@@-G)6>E?f7#G^^sL?NoU}TZ$hn z<4>OTvv8U!j#VEx!hiLd9#OmDE`bh#3+k52=6o_;%=lFb0FSC zoc&56H>;~0zk=T-ah%gZK+b$Lpo9>*7vc*}FQ7-2@?>_+*sG_n}Izb<*^+^-n~R z+unLyMCj1I?hjfP1gb!%&%a(jqQ!~x{;V7nLz?r{7M4mruE|B|PnM~wrXMp^KW5sFA)d;GW9LqqfcX|n zoAA4V7@A`SNR&KWM$Jbu5(R)&_W|q6>75OjWHwPxQ*-yGXk zTU=f196adlUvO6h_*EoCF(vd)@m5mw*?7uet*pB^))$`(TJ!rXEGp^9mMolNkh0bA zDNo6^QQR00M9Z#XGZ)40?mMnxet92CZ$7U)bnrV|`aFznzHdCVzJI9pe|brSBzWw; z`9vRxn)jnvZmggZ7Fz*5$QYC9*wZ4{&r5`NnbA(HgQa35QS5iS5g($^hIjx=gH-Rf8E zk_j4e_aRjj`zi#UxuZ!A3=Q_Hgg$Qr%0#YiQ+}2Jwn9@7P!jabhRXii)JZbuEzX#0 z&ab$cC%wLd7XLa{Es>dqC;+`w6Bpri6@pNi<|g+rE3d+dL_y_ zwa(;F-4$e7TYTricgfFUiRFtqR7&NT(>q}HZ6mZ)`ra zA=SVRuT!7sPliv2h4yB~a-r#MwTsS?dd-Q8%6Hdtoa`T+Qku(Ks!p{D45#*SFKhcm z9L+Pbry5O}>xc|)t%sj3+`BS24hG$7x3lfMUNSfDQJTBqi# zH%o?*FRF%wLYr&22_Gv%T9GD!kGO*+sN@WzvZ$YkK$UcKW6#32O(M@K(Io%9XI*IF1jeE`iwmIUvRjr zsQDcXskgiNMZx-44g`EEaDPm7C(83@#c|0PG6*w-#!`S}pJqHA@@Jy4y=M!!WAj5B z_61RSk(=AKF8WfH1k4=~zQp{oy~wQ}@D#SK#BwA4@w zxo+|jNAO~K@Qt7j7CgcbGY5YKvg<5Zw5qv&Y4DOP!B9L55-`JxsD{Ve_xa);;z?tS z;vOJ-WXt33Owk;qweQVY;$p@bYLn&{jSyA_8uAM%@!)?5!{oG8?SX}hC-Q9$%Q|v- zDGcF%^h6AIzFhRBfABLb3ICiBuG$w_njBg4VBx?KsNWoHM(tJnsH+eVLCqTOu@up5 zZU7G-$!V^4QEacN?&`P{!dDV0wjD_V9fNNa9J1t>yyVB{7RARIq)7uvbJz98j@}tI zW($wD<%q1Iw3<}MoaOv_Zch1}8q1I4Kd}@#&td*p;@xf@N5L8Uj%%VN9x;F$HaKj4 zXzqjE9J{(0&X^oZh7g8h9+-)nFf<(e1HrxjF%JLOkZstTAuQn?$1xz>r@AEmekq=k zmW#eA)I=o;COv9Z-D$iz*tR)=9bhyFdI*7Cj?2XfSP2ghevFNzNm>_9S~5&Ze{i>J zPAUxxR#A`Sz)NOGNx;R4+&4FGFpp#TV?ibPQG(XyY0+ygEJjW}cEv6JFg1mjHrbli ziSIa!ohC|EG68KlIczW<$|OlQ)YYUk#hW&f)groiDJ6I$%)BuKeK|pU#8%2Yl{6ga zju*O=784~AI-MFb;uf?fksPv|P8k|)$7Sd%8L2>qxo86p((St>Q+3S~ zhD+o1TAZ0F{l5T zaF5h!PPu}26l^jDoTLXFC*()O^GXD)dE^vmq%%t8xme^G05ZLrVm!irXaLd#0e+t> zQ^=oxl5hu6uVhcQPLFF&!+Fl*i!^Np6#UjG3}4oV_Q=N)cc4Yg z(x>x#77I1RF9HSh!fJQrd$xtOgK1;E>DJr>!G7CDy{>5LYR9~RxI7JHW!TeW&P zTBfNYme8`7KrRI(l?Exzxrn(vJ#SPNZN63qFu0`75^h8jYK8bOBM z{DSkU7PO?XC#iI<7km{C9OY(PY@&k zinS%c1t5Sk6$%6misjJKJl;G^uuaNYi?{&mX&7OJhHMQqYkLSdeMlVpM)S-@{V`8$ zeF*q&xT2PHCy4JOnJ5rB&FX&z1Jx6K*Y9Wz=+~sqkvm z1h#%(hPgCptB>++MpA0~tlzQP)^ZwW{*w)#pgo79{m+WtuvYuv=h&Cg_K7j~DFXdD zf{vbM{v9LQg;n<@Y2lSqy>(C&-zrjc3NtK#6}FD2)7OmV;4}XbQpd|c=OI$f2|=sY z9yI^7=zUw~_uwvNR{e*}uB_TFFL%k50veb#xAYfOAhUkRH#&fJcS1LeeN-WOmV7du>4X zbwHnR(2#xr$^ep|3C)PtSXKd2$|Hfo(b0lXAKG9L27L%=5Y1|BFc1%5*Y4y>uMZa`7NcbSxik#2I;Dldwmlstp*y8R|F)m6zVJ%wNF>x@yM_vfkae-h=iOvMCLgJ|~u7*E6!x>lxT9(v>(prF1)WPB=}# z3$XK_#=3$#9-DsIoZ267)-DUBnay9#tDMZ z>P%^vF|e$;Js4D!YUkrp`Y?Y>HTJDaxvUt~u+f4Iyx9w8jWDdTV)25|aedGQKNp;{ zO{At5_MjF+$rs6V7Jb(Z-E6SH&vBNsi+(;!q}WS=+4E4<^G-2K@gI!bV~p5i<`R6C z8Q^B^Lzc7Fmvi2hb3d(sxv&DAm7@P+E^NjM?k^W6yI$?NZfakvKfS&I`Uec#@R?Yt zTwnHCH?CeMm4@3{-?%s*_q&1*(noM&f)8Or@QB}hdMmr;LkLmW4D#Q6=G%hN-FnWh zdgDWYVBCV+*jgM%i)7}J8f9zRl@PHAsg@B-tB=e z_dbp7v24tiT48;&#kLaXio0#Di`>s7uhsVDT#()uC5lyjm^>w%sn?wgcnoV*&} zwJOI_xsXyfqv6h-gwKUm>@0JQJ@iC5d|ElQdOw`_d}vffECO<);RADmk{h1Oz8DZO6`?t|*_V+PDD$`e8IywBBe4KXTfN z-fd>zW)!|2_BfsTz4oj>YkA`UOl5XVm7pO_QZcll-}+7kP#>@15I%?jb~SJdH}Co@-~Z_LoX55W5?0`O?rInIKse*dYX{Jan#c z1Wpm!uCad{_he3$@I%8rqQWsjzf_ea>fgYZ+|2m?VgUKw(01Ld^8>I3n07F4ncxA` ze*Rs&<@_MsJ?dJKO*K*Z%R~|ctPsdR{o8NiHx+dE2rv6ZMji3J@ZSEkQ8?AmRueTR z_ew^P`du}KQ%uHFw_*gdmLSIz40vQKNQbTK^5;Je0uT8_HK9-s<^m5kcJ<6xFmK5Z zjA}JD({Omw<)Lwp3Y)+30};Z0)C3dvCSE!!NIb+7&60aPG3xdvgB%k`pq0=nWEG%k zk+5X++kO!Dluw;Dtvy#=j#Lx>PezgU&6iI3ZoQY6UV+zsa96?ab@<2YXxHob=IbQr zb(;8XR^V-3?`^^FZRy9`O4r*OX!C7~`(*>Qe~b8?pZ9%ls_($>ox&RdKIQ!+uI~c$ z&Q1urk?*_H12M~h|AK*DH$h(!&=TH1P^eFD2?YbN7>$>vw?)FyDdh^(XLdxR@z`wl zmS%Rv<4HwhDKuvHB$E&+NioxA_odUmnoJgG%pJ&Pak*UVEj#S@q=0~Z zXE9%@f@GrMac{L$V?xjgI`#Zxv)1C`RmoR zSXZanc`u<_>u_Ve&HMAPi`gnhTdAND&>jwdi zSzQK#W4!{$F{JE;;0OwiIpE2Y?0X|f3a*5aS$O3{Pj z#ny7Z7R5EvrV+ris=pQ^beeY%C-O=v7bFhCyrDrt1zR;q6O}Q_$!(A#1}T3gDgLDL zA-9pDuiGmb{qSS{Mw;m}%&261F7mAmK@@AaG+V-F8u&mWA*V_FRf=0;3bt9>sldI0 zTX`HxbY}%&BsS$~(AP>B=kH?RSmJjH@|cpC;Mb%(MKR(5XQhwln376zA~BfC!Srn5 z=--vtrstSNgjH13y(sQUlu#WhRFjB2`u*9+X6|{|5tp3Q4Wrops2eA$xN4YYy8O{F zPnd}O9cRi`vJi;df~A(|yxyR8-a5yq&ij+?LECvw#ZAX`B4liZAH7vY%T|6RQSIEf z!B*Q~_5MN6ANn1q*`uj4l|sj7KutfCz;$U`pE$+cF!D_Yd4tpD)9_Z1_{#07_|1T8 z3mr`NO;WfXqrnuIAfAfxJSBh!RmmIYii|@U1&ws0>sJ&NU+M~NUaK?oX`;fGxxryZiYabegjl_ zr&e6{y`ab|1N0ykL6GP)Nu+)rdbWBp`s}wbOaroq9Cy*tyQxr^1d@+!!Js03Q!}SN<&ljNFW(lF{VX#8VO)Bln(+%(&~() ziZk!UCa90dTR%x@a}PwOV(#OJr%UU1Ql=nD7SslM$kZZV0n4lWWhki3Qb$5(0qdR!yB~@NoP5S>-h}8he4?@ z{<^Rlt54@8B8rPTtfmj;RCo=5X-(Z4x9Pr|Cppdb8Cdy3Geu)z!kWnvWYK*7dZN49 zCZz*REU!5c%d(^=X3eTOl09d`MM6^ko8=^K)q%3-JFa5Ocg(n-%4W)mE`5*dQ&xIx z6N~esGoCIATFcHeyLmZ5;%oJC>Dew6Ttu!m72<;9anxt8n!kxwIs~5|&x+Pp8rKYs~Fe ziQDcYWU5?LjgQ*8O=tlRc3iTiOcp)Xtr8AwQ>un$&b-b)V_Z!(RupvD`E^KZZ$1|_ zo!{F9d;o5)jizRuGTR5enUxy6)scAI7X~qmqrrR}m4Irq_xr8C@;O+&pB%demx>ty zvsitA<~=Ba$660#=n+xxG3XndP&n4F=7BGvHPPa)Av{aCLtJv##N!IEL~WqOApyCd z_=t)fRuZm}1D)FNu4&^4y0nUT>YlF-%{+n4+tN&k@Sjc(*_iF!_kB% z%@?jSmdACzPT@|XC9uRcRP21(^k~&XxCI7e?el|LhE37#a{IK8aP{zJeE4sF)T|wC zVPs76zeD}p%{t-&wTz{yRu!evhcf$d&o~nWXGmsS$clLO+vTv9K-wItEwV4fQC;Ia zE1asla80+ko>y_a?UIz^&*!l-*SOf6>FPa`j-j~LWv^=*WpejtQw7(S#_Y1HZ?7y( z{)rZew$%U9_FI?8%_2rNc1rRY1h>hpFB_=pB1)pxs(XUn7!DI#ff`CFB64{rasB(V#U%&nDBI+Q>-pk^9>-ZhuN&*(6*}Te~^)UkCvmxtYA@7Ry z-cE4@p0vz-#Y=wN^nwCsAo+LedHNCE)Y<1ns$k`zU96CDoyq z^B}|_g6~BHuF4~cal3Am3JI13QO*QW+XWv8KHWwIqhtwe*9pL?`+pwp3ay6vEYbO` z96BL0kOdbFRVEmUw_DOaFx);+(!P5kp!?fZ_lF9>6_(6Zf`Bz6-a#ZJiaS2atl(@G zp>1f+50AVd_C2f+Y`kb(gz?k812&DBK7D5IZojf zTD(7YMTDXIn@;P($)Qm7(aJ>#qJ~?gUOP2ek?AUUSrl4BnS$+3SrV-VwLQg*L^#58 z2QB++Ao|6$BVlZ!8$7)bEbqiD31BimiYpflp{O&a5KruA>G03=F z-0PLydu~V#@s}fVkgG9*7xJ)|6MrB*rQNo;5lfIQ^f1Voo-@o_LRPpfB1tSnTOw4Z z-fDhW3h~Ri`=FCELOjffinIifz92n9lJ0IOTzw=2hAq`wQrJ-VV}WFpv80PLTXqG7 zcJ%NQbPz*@WG3=R0HKtWaE5_L@Dn*pq4uahA$xJ~Nci5cd4*JYeY5@eC|`bGFkWy{ zmRLFRuuzFm&Ab#9W~T6?c(Tlx|M*BF4EcK0FrNm@uh&tY?%uY3vf4eaWfAFC>(TBc zfB;iQzV{eep0rp0Xn$~oSU6s zJN<+!-zHf#ZxEo%G8x zl1<)I$UhhhZxc?=Wyyo@*mCORX2#{;)^h&rO}%?hfPW4|4Au6lychz)KZ+)Ve@P@M zu%f9FGVH^L59sLV1Ox;;JUn0?NkG|ETwGjFPwzj{CJire@yE)_3XCK{+utEN-(h;* z0R+36tbNk#{n9`A|Dg;9BT0YgBmOW)KXAwY;YoOO z49v7mD{>9Zbq~$;iOToR{{;q<s~$T zU;LWif`fxoQc@C9e}GY?f2~fzz>@Hk%9xC**v!AQQdnuzzx^OEs+3vWl3m(XP+S3q zl!_~Ab1OQ*oYJqxuB^uSfR?w2j@QEKo}Zn=rC_U5<8W2;aBbTF7)*-keor2F&+flT z8+^|k0af&aTSDW_-IHy7e{(`$HmRa-KY#qaWa>X`Qs?AO?eD)-Qrils>g>1!92**% z?HgU_`zv_@$A*@B=T;`>{>Fv|=JzM&w?>!GdN)Ah>o? zgPl)*d8A{|zcr$*-Q&IE^P|(te~_e?|5hWqzPY=;f4TjCQ6u{Q2}1&Z7BGoK4knT8 zw+aGbQN=O}&d)An#jPXpcXu@k|lX4=Nu-7vOx1TBYLOYbUib!ANg#Gw?5o z^n*R0L`Y(#$$l3*BrV=nI12BJZoj!g?zc!hQMiS0j*@LjDq14l@mtE>p|3W=;AUXq z)F^p5RAnn>`Apo8IHEUitYh_jrQ*?Zd{;1uR30RerUTz-Qx9t9uU}RBVi)$oP5$|% zrb%o!&4Eg8QhP6sY~rUpkiO%2Z)_pR^3M_;+tG9mPX?%nThq)H+P*` zqP@JI)kS5O-=%8_@%CnqH*8wABlU-+H77VlF`Yo?Q={JdgbOfg>AhD`&hg-&6Lt`})hNuh>%8t1A&j5U{G6xuedQ53=NuacDT%V|F| zKj9@&h*;KgnJFZrcg?3Y+JV+()QT#y!@QSQ1l-9tWqI zs!$e@nbIB)1a*V6(+xr9(o6n7xV5Xt0x*7f{-iGgPPT8&5>~lR9RqRzJ{lTr>-AQp$%y&J=KWm zkPEY~Tg&RI&QKwJe1j0V&t>e(hNRnss}e}ZMcnJQvU}Z64by!ygu|_QA{g|xyc4tv z_&uQPDccfCn9BA?%cMA)Y$d0-;X>QCNm{)ePH2>4Gp@R&)}QXa?2){Dam{mwxK#J$ zy!n^p%Z2a5WZFgf?Zv5Sf8E8y-b(0;L({TnG|}>Is4si#!fq&Y1%ulr-&BxcH8)&P z=f&+49|7+BqdZcVDdo?w+GKb4_e_X&P_q-fK*mvWtG(TC%B?21r<3WB1@yZV+U9J+tW6eLUv z$r>(TA$sYJ;E^~Q5U?#L52%m9S4v*l3;Yyk~KC|sFWzBN8jCa3bk*4 z5G&Axjbf+yY*-W8d%A;FmnQJlx5n=aOe9{NdhedOHD%Wg839}4*H{fkrDF6Q%Q6=R zYla#=sn?%AjcTp$%4oK5T=Ty|Yk$!~Ap|40sx-_tCs@kfge*K`;nTJximH~!IQ1@3 zhp=^2L>F1|O5~0sQ=VJ}MPFa}>uswh^45=%s^%jgl`KO=ZVhR* z4yIhJ<$T$M9Z2nwAq9=#I4VGaMu@P?Gmrrolo2q~LnHvpqCFHig%Mf@M`>Pz7lWVv zG&oj;iFQb7CcOJl@|p*=IhPp20%B6Lz>K>B8gSf5ZFJUeivoiorc}lZUny()u86bH zLe6n?E+^kvj{ifMJUInM9zIsF#q#ub>65@BZkJNZ-@6*QQooZUX;P~rlO@VWRT5X~ z%k@7UtM#p@WOOH0Xv5NJmV3%1SFlx1-i|77X#Q57aVb^XN0g>^SZs=I_$B=ISwDrZUR{2`9YlWjQP*C zlR*iYdnZXzwW&DaCK`2GKNZT?NF7Z>>@l?g27ZSqwb$+I$>#pg*k7aF*0zaW9)|>p zDnl*2w+L<@`@YG2^@%y#p&EM}=3S^se8AtM(|Q_3f%|I5k*NVGp4PJp>y$=1z8tI0 zS%#I)oU%B6z+S8ZYO&z23x5DR#pWJ*#%1erb}Mu`7nUacQR;J1wYG)hQYVcseg&U< zAH~}*munH#7f{PuFy1zfnGZVujN04(dWbhQ!sZmxqxw<(MTZdlKWkBJs=g zE?*1dRB;ubq7;f&fuQO>a5E@rMEH!`>xvL8f$r?PlZ9A%hR!q^~JL1mRc|1 z$LPk!ripV~ub0)*oPg#b*$c>+ap_b-Vwc^&KZx=VuEG7L6U z0W)9sXh8BUqiT~kDSt_%xR!Af~J! z&)cy=T7QFmpF9Ffjr*#@e)G7A@9Lj4y>-N3$clR^e9E`-N*O^@# zj{&RqTM<90PptM&zx?0tIKMwrux9J|H!DEv^fSB)%$no zkfDXJSlDK2s6(0w&>n`c8&Vwn<<=PH7UJRa7#5I5z+n>Zix3_N3ik*`&%J|1&mBY!`MUGcT-QhM<+AI zuo=aS;wlC8#{71VnM#ZK#7X1p535c>Yi$^791?pn9Loh8clsD}5w3Y@gvI3)cS!@d zREph7WBD^2S2%zseD!fkEM6E3PN>>FQ3c*MFCGJIsM1Kl_DH}@Prz?UAY4u$dP?~B z*oi^|NaX>fNe9xk0O^;3j88x&yhLWML{^PNc8^3(5Li*wlK9WHQ=%YVk}y}&H;p7Q zk0gl^MW~)&gc)EWN$|H4eU)Jh7A`ay4GFEn1Z2o$V|69vW`&$ap!9IiIT=s^H!%KB za&8gO2!Q_CBSnWRD3K}I9FS%=J}aInyH6u~%ssn22x0{fScH*d01^bmcSE-wdrf;Nb{qjuN20ovc*jZ;sF;4- zSwOkkXU&yDwk;|4sd*o30N+M9@UMO}YXJJGb79I78UO%H1sES>ljUP%3`I-shgNP>O{E|VTHmWIEIJ_d2|R5^E^K7}lm)OM;s;dgkD@}! zV2s508%aKsOae`yw$SGTNr)r7ALg!5Q}y|j7O)id%J%k9pO>?`Z?YsZlK3@#Cg&nJ zfZf>7h5GnKhTKKqERm^ak$FauWowc3N|Ehz5x8yS$X)ELS?uar?4D8V*;?$qQtbO& z?2lg($XybwSrY155}r{K*;*0}S}BQrE{Vr4{rB35p9&#R5IkETcu$w+a66@ym8NmK z=CzjQfN`LVvQRDnkGewDGrExd$6uPM%c|%?B(eq(2>~-@bt~mHE9JI@HUtjkRN?8! z-vQCnoZX|6VNifd==8aIn>yiiBZ+cNuJq)Vimbi#c|@_5*0hC`^z~LrhvNh*C;%T5 z0iR&nW`@8-MioYN70HUrWm#1uMgfxs;DAdJp&Obh((ySG;`QX08l4LyPc_IAxHiJE zVc~=%oo(%_9C+U_W0}=7Fa7* zR;#yIi-B0jBKesSr0K`Z3Fwie4<)1TnJfmS-0dW> z1#K!05C;n%wA|(M>Se4-AJQ76qjZx7%Os|&AnwbJttzJn(fUUVyu`6IqX?{3(c3*6 zlZ+dkKU?;eH8x9GxgIv^tzsprqDw%)yJdSB8MZ{0hbg^aQeQQBvYB79z=P9OPTei(r}RPjtre%OZag+!WNno^ zztp8$i?pz9Q~?GGkmM?m2Hkb!@a?@XsQp&$vSICgTJ4mXZo1Mffhp~MQBDix?MA5` z%VX}M*Ny%l9&@}G$6W%y2BWBq;`%mI28?QM43a49&w%qWj!S|LxuMPrq^@Y{w9N=D zYjzq5rY;PBm~kXW2>Naq>#hkc0Hihxw05_%8pH0Wq8fqm0vRlgKa^r_*L746{&KzuU~2=K!F7?4LvQ{ry>ThuO{OTqp6g3 z4V#4r_V)S0({qe-0H(Vlha09jJ0*|@EIDh@WCr9oX>d>S0(W}V&qAmz;a!=2>Q%%y z9uJrhh6(D!TC5G)61vJ<4T1?HXYCR)4tyPc;uuNt_Dk^|xqraSu=WXO(#V$aPbVBb;utMJ_C@g+eWR{dEg8KZYOF%` zttK369vZE0AGs>jZ6fq-tQc#{@^&~I`|_v1>(#qMd%PrTtUr3Z$E;!0dUX8NBLj9~ zCd*?^d*aA#Vu^n2sd1v)ZCp)yVq>joig&UBoHsi2+{#j_%bIj9p12_Nz8crO=5?RT z8adaVvgeqpE}RM+ni4*k@`s;>VwhOho~{y~M)=^l(?0FHIE^ylhW2U3lVb+cX9hQW z2ESv5aD9g8ZHDC2)G6UC$a|WC&vm-J7SU(cv3QnBN0na3g^^*L3G``>FLhQ_Y|cJJ z5z%~(R=k6jZEmc6jygG+f1);*cO2VC$;@S5jCx+Wa-7O!UarzjS?9NY>J){`Z}qpi zM_gs?_21Muzl92almDJK%>Jz(qga=|pl-HcH@skTzMulXs3x24B)do?zQAX)XwIkT zp1tV#=IraEm^9)W#OD%XqX?E%MPxg8+o=1!p~k!|DVi;YzM+QOEGvX9M^`ROA}Aq3 zz$boibclzTJY1$s&WICS78pkR`DuZW15o_dD*Ds9Ojfbte1($}?I%O)NAVzl{wgxi zAYolixnng})*t42)&1H5>-%bdHvMJFS}xdGRY^X{u!@PZ-Us4a|3Fs3Z?aw)vktR_ zRg_Aa^v8wrU#|0ZFByK12 zIlD%a`(Bc#Y-%gQ8;Vi39+y(Ha&m*g+&J1f;MLmwui(a zfvNfBfROk)rpL6#$bOd1MFy#i4OT}j@^#Q`z) zKVk(uh~k!10x-wg-Iq2mm>v+!l8MYzdm>TMKrkr(OC*w{BXCeWo(zkZD`K`Q6+k@! zCXq}f|0R*;4&`%&LQp6*=V=rqK*|e*5)nYz5*EEd-v3S_{XSKzh9a(XMszA0Oa1=4 zDjV;=l1N&M7c(_bKjlJbtIu@017K09{*p))(yQ-3N7NZq`oSbpk@oV!Xw%sC8QhC1I!(&W)I z3*Q&9^zntduF0W3=ih-zB(AL4VLEtiW>KM5WG7knRcqVvyBz51=#NvZXhIyf^G@4f`zBhNz$U&>gI4eqhP9BqIZc$*CW~j58Ra6kcYM_(Z zoo7Xp*xhwhR@HK0D^`qQO`MZE^txBocIu#6xI2=$?}l-~a#c6{u#?=yxGG zCXpQYQU+ylm%%|ZQB~|mfp%#j#jLdjG=k$z$DTXoG^IZWmYf=*JcpVdC>Ll zu-4yn{n_oTYW0Ayixh~&$l1o%sc#tNP2kEY;rryH56duk=b|f;wPauv%QJa_LI~&X zZVVJS6AVQs3U7u)Fig9d38`Z0kEh~pONoS{D$sXYPd|}`^jOc(UAJL0z+-3v#e-dW z*jq&4BkedDN%RBAC=BR<=}>kV&U4?@I$Rbk7J2f0Opbc57!7khH+u<2jSkYSHu3;_ ziCw)s&ZvBC7(7fQf{-K^lUX*B{tEsO$Y%)n>@$6r5w-#{)LYIJOm04uL3Fer@4Meq ztNA_}G(iuH^^czdv4g2Q-7_7m0pI05=ce}fBy}^yMs<7$Zo!U3yC49w_cACL7Ye;q0){E{d-S(v zLu@`8fN=Ep7&Hq(?28961R(z)4t z+K0qv3J%j-A{}zH_lHnF@tDcfy=Q7_lrpyST7Sub4SJf4x|(owyDem~bBk}CxdrC( z;YLcM>Q^E^vTE{LKqe+V4TGU!9a_fXHm|rSLx@+?<)`QU%Nt_ zoz02)4n+8?YvH}Opi$i+Fj3&4f|&dD;l}bvF;tl-jP;cjN{_yMoSo|mu=^>}AdOcW z-@Mu2?8Zc(MsyoqDZCU}qEuL>x{(%w_G+t#HVvipaYwltJ1|a#(n=$YdE#Z6q#WG} zZ?}40x%xz*qKDZ^=e+D=eLfZcpvHD(vDUzHnK-iH#LNc%{E=yHZc~e0=ak zb1f9R(ZeQ7$kIxy^+2^bah*YP=1Of|xDjm;&(`UKmUcZidrJUAuyMARPMxq@M#jFi z<#~wCm7Gf3!!4b#uT}U|s9Fd9Cp$dj)%D2@*N)p5V=phQc#&7t&b$3fSfsDItP(h+ zPn9;I&tCe-Vmn>aHuNGW*IV{`YJ zz_4`BxG8Vb(S#SAY}TS%eA4{Wm<5VS&WD)K0&P{}F6=DHbKd3>9N|-ms$-(qd}ut< zT(g;`D*0GG7II-LLP=C?iG0~jT+&Zt`CwpEF2<7aN6YWJM)^{kw-Gf0o5@-t=1QNA zEUi@TMe)@JbzefX|5TR#k%`EIC;Sq~Fz||rgoFe@Mgv<#z(YPZAq64j7jgMXE8A`85tQ>RaISG-G2xEf3+hrMt=JG`rw)0#l;1@^aGslKYHHF z82r_aD4GN-T81fE{l`3_>-9t5G1lBQ#@Hpn%stW4E7`^;4LtT!hk!T!N9E8|JO6a2 zz)bhBAI8BYRzZ2@5x@S5NW${Gqw*b-x;%i@dQHz>`BVBuFIJVW#%=FDO>f|JKPU(+ zvJ8)ih)haKN=VHCZ~OtVg@N%!K}n_I$>4Gmc;l~0&CJcn`I(Si8&>vr>Ceh7NXo4T z&-}oeuH2tR|840ntnLh{+6?P>kLUt{XMS+Gsj_JpEFURppQ~;G&-`Q2-JqoY_q0J! z)(EKK@4!D%GqCa3KQgk|F|zz?^ek`euX&_pe7o-V-)X<|1O(podq)1*^~dLirop>XAVH~N1!>dTV(%a z|M>j)pDiEk7TLN7o&I%;JRLuRu5a(bbN*kw$lLq>XZ!m9g^vTC@M-_bMD%;4Q<3Su zl}wX}NPL2$EC>d(@BvuVreLeczcLX*jjxLTnedr^0;&I*@G+2)|DEt1UgSE6zwRH<2Sznk+m)Icg8 zhy}mV;Dz>OFanLzvcCD+PNGl9B?B|7`RjCQEcsMDZAZK@0H>;?69<+ z6h?`#RiTR*P-D@`KaqhEL5;k>CLIkNj&6ERzF+iBZ87?Ogi@(`;t3 z8?U!>bHt)%6TVn4F6Bi%b0AZlwsw!2+Np9J=~7#V&W_!ef#y{*AE^L=$*Gr4cd_kx z(qL`>iLc_hCI)NHTY)^XL;6OFI*Q6FWV9;D%7r@NDxu1i;v1eM3n{wc6pdl4LSEOd z#F6-T|AoD`3aX=j{50`%2pS}~LvVs6xZA-cxCeI#?(Po3-QC?K!S&$5-8DdPa^~cH ze>MA`+S$3;sja=3%f9I9s=n)fzR%|grFL*7~OWVr3P6c<~OC0dl|QstCy*lLs? zm58w%EG9)K$OW3%2koaP#!P-pm(B*sjDCw2T%j+_<9z$(C_h}LyeyxOC2cQBX^eX` zA%H!d&>}yi^h=^~jI^1iRf?y2M##_9+6x=YRs2duxZdWdY~yQaLlmMFpaggQz^@_ z&Z)Xu;3Cr}eWlq&Lu2g|hUXd?q4odtCu6Pa_eSQ2dT<3oUH1dKHmfuM1=_nr_>{%k zk7=!uFaU3UPvTDDVxC->hF|Kud|1|Hw0?v%48%TGoP&C&%hpELLBAT8v`+NSMr*W#|5+SCC`Shfoo8wT%$)~fL z-kRm}yVyfRY^Hh-8kWz7I+P~lDJi|)glqD3%T(N_ zN8EM0VeoG(+uQeCl*iQeG@se0_?Gq<nNIxe9okj_W0 z!OfKv(iVjk@(_mc9@PIv`zjEBA`gixt>5njo;K-<93Tbyj+F=w;(nWttTFN(tAI5G z%LZDywCKlUkq+UU_<~}qNs+Ln6ei410S^&tNhU-36;AR(ZWE0^fKQnaNQ(Lv-UGYw z!TsvLrY`xTk^iPH*%RM}n#mOsj)T5o*8GZbm@mlN0S$BS*wDC4>=GuFb`>4{iZj)v zBnK=@(5FlWbWjvg?t{Kb@Loq+co$I;(T_?@)hB+-LVk}s+IIDDiIquRL@ri7tSW*P z5-$$K6OkShl59wJ_NHOl290VBsmQcc?aDNL8`pFl|7Lt*N-RY`!AaNpcP2K>EI(MCPhD8h5|@g#D~z)@;^$-d5nGOK1Yk#n}$c z?kFf7>=dOLwf14s1ER=;)tE~jNy)zKA;Z*=nEdKZ%a5HgX2X6Pgl>AoPeV8pw!)fx zCSE4NWu+YBI3IQHYz|r~pYm1U%%>@)6K5M6iR-v6W{sgI7l<6o@WsjJWSc)o;8RdkmA4+F-%$_kAo28e>lJAmA68owKJDu zXs&phg)HlwXGsDxTVXD5NT9sEfO-UjYa)KC4`^G^ZtF*DBDXdmTJ2?TK!|tuIWxO# zeQRUb()fQz_|V8y8@+r4wvvd%uInC6ml7Pm**q_m^!-PGk)89nS3K|w7pRV&qA-4M zV~QHo?E&wganQL=R{mae>-ZR)NMXl$k9B;_r9LJ#9t$Qw{)h}}?mEavD5gmvhkMJ^kCle# zNy7FkE+6mp$eGP-F2c^ah(qsqFew3xZcF41-8Na_&=Xnf#_!tRgfqxh$IsMdt2dl6 zaD)0@#H)Yq+P)=R@CAAO+!q}G+-iI2ZBV#*j`YBWF1Qd7RvfJWZo&rf{j${c-X*ht zkYn{VkNv>E$GBW1qWcFS2snGN@bhsx?9Yj5Qo`XmqUTtgej>Y7FzGEgT&!F0Iz3+C zT+hH`eM$eORiiaG9>@FRQ@B!JFW>bygBLl{0MvO~UxHBw`1#?t7*g>)cdgT}7haI( zEsS2s!?5C?>rBYYkz()D()6FZPRQ$3T<^=F;{P1sBWU_VcS?b2{%_j+QGfcQKll^B z$9zlsbzS4@bErJ(64o)-TWk>KwwnW9_}AAK%`IAoLo@qHjkixJ4wT%1boD+?`4aET zFv);{OlfiisaUga=Io%i9D%%?v_A6Nz+^{3`Y>u*x37bT?+p9_6>PlDf%NH^!SrQx zDi4~|CLzJsPOTd7`rL3N4)77I?+|d2S-~)9Fz^X=YTLukX5pb$_%3F9q2_6!))qb+ zZn!33SViGbZE7m>BN0oW>mDE+jXa!HINZ!6JiIJ?3(|_~?*Jc9{!ZtXR%8w)oYptx zCuiD-w{BB})VGLDH(bz&SMmc_*+ImLn|sAWSlNTyPAU$&DA1-4DR?VfpPK3enDc{S zi0@*Ir%@rU?7ms-6 z2IrRqcSK922#&+KLf8cc94}dY_J^ZmMI1kfzmcLFyNi7%?UybLWNY|;iSW~tWZILU zu_%Sdq$OA6gLguz%lLA6Un5nhGAB# z)0h*aGAPpsI|@1y1U7x7wX;km40p-H3DI#+4V2dOPv;A2|JwXJ)z2{m1=m{%3z-WF z=^fw$oYLHuspIL>lgeYLLemp?(lrWv(=p-09x%`_;n5!T3$-#z(=!NKG6KUhjz)YE zlrjR_LZ8(#HG?B)OENVEGBF+_gG&v5fs6({eAx@&O z@Nk?>-je$w?aQ!*2=@t*3v2}S!<9@FertQYL@lW^NQ0C zitn_(eCa6Gdn#UaL)OW#G?Fl|iIkwcDj|JWs=-;R5{mpW9x>@b>w84z)9=!5EiV5R z6Y2U=pA$vD1uHTLn3L=(?)P9>?3;43_s~2+ndypg7&LU3AOS&EW8XoH8G|9)LbR&T z&*!Zu_N>53skm#XNbfM#2q-h7(5n7~B$J0=EL@&oh1^zA*>&=T;l8pnBUk!UW!4)D zWpS-h^@NvwS^~=|3Z!bDdy|os(jy+Nv^=DstMc0rWbZztjg>E;et>s;b!bO<5_ioT zE1RW^vhxmG=`Zl3kruz8VsM+Uk;3KS;a_CxDqXYQWZI&x z)-9RU@deevqts{J)jEXJzpJ!;)~+X7wH&#xr{rs()@gW;V)xPE|9MP=x3iIV2+053 zC`{BO%GZP`St^cVCh66rpVA~VZYsChq#des_NMvs`({->Gj*?KgOq0NRa4#7W}Ulc z!%R~nz7`Gj7Bd}F=$?q0m&E7s7U`B22NY9BzE%bGR@ZS8=$?p7ORIO3i6Wz--?OnV zqg2qTaY&R}*s5{FxLQ=FaSUTyoUCyIUwiavOA3*xeP+8*OM6yjdG4u6j&)nUPDhDX zM_FYnXmLYuIuCtxrFnd<`dQ=a(H=j#M zGj%bZO-^*w7KZqqesoVr^fnnASDtohzVWyz6gmj%x)2k39yk7l;*i1)3^JrUO726k z>HW_8IgL-&&e`TUqJnFwhu5`_8^5jT06=+#=+UQdYzXJ&k4z=kirppsExz+vt&gS3 zjFkAtAH*M6Hd35bMjT8*JTKMrO+U0$`!!X|1SY-+qe>kGYM&3T8-$z*nvSkIeqzPg;b-#FE(GaUNA(xB}~1C@KT1X&qPvphU~Kj zzeY=#$qm0v8PaPC^{5(N|2V{@E9Hwif;}{>cRL&k>Cy}IR&a10ZYv*&sxngJA7w)t zT9brz1M9o9!hVqj*-qHP<&P?Bvu5j#4F>AE@eik<8i%Zng~^RLqKV)nPzw83>6hi2T81bY70`h^JVda{WsrW!V`NTQD&Tf{Rzv`3~=k$^8^hNW8 ziE7zRbj=?d{nv@1U(pgbx?tFM!%xK1FI94=w%}M4sm&}fX%krN>oj(^9=iOrE+2(tb|$4XMxB1HAAT<466jeDYo3N?mXtS| zbvEkXDedC85*aC4K51I$4RA-+Pjwh8n-HvQUapU!iKkgwRDY{G9P+t)6&t)7bX@Ag zkF51&CAOJFaK)NHWNadat}A<8?v1uDWO7iEdDS^~^&6jgi zr;tA<_4>dmmaC!WOAAa9B)_X3-}C*cs~^pmW_cHX{#@QET)Z>TeHOfY`{7sa#V;}; zU32ow5kX1n&C?>5Gg>lTdPwf|;Kn7D;x#PUO`i)AKiN5A?iustaevJX`}7TG?TN+J zIW#&I=8uG{c-!rQWC6ZutNF#{cZGxTyVvxVqxOWd_m-Iqz*_seljgT>?a3#MJ8B_- zvEp5O2-0VJ*cSGC=UjM33`t9v)3I29$$N?r$=poo1Cfx4<)*sgF77&w*G=}~p$@&;l2a{?q{ZKw+_kHh?8(%eC z+Ck{|=Q#M5ICxHS=4L>(g zLNKH>J;6m-*@`9|bLk=x(m~pac=BscE@yuczFpmz*-;y=go9OgOg2>@3)97NwRHeG#3{;(~> zP{B?R#T3ZdgusA~hmBG>Y`7}ivfMIq2}{fWWGuN+uTQc*}NZQ zw>$%pep7XnexHdjS|mppU{wLKd%BXLE51DmWng;*fB31*TG-Q!3L_j4z-v{O&xpfo zG8qc}5R~R+8#^vaQnxxTPBW`GE}E2 zZv;%@jKhfMoV>La{p;;9EmdE@w3xW&Q&F-38$TZqlU(|9NbJcYm|ClPxIi%Xs z!vO~F6-vB((|F6vzzaqAHw$hCz9BjqTD&;F=r%ljP!M8#vDMwb{2dd?^W(}E+lmFU zXy%Jz`np3A{@uea3DtY2STUp?`~tD9Iy{pU9oI+Gv}COI9&VY75BgF2F~<98UU!e? zd0shM%-l9L_=i!4TRavenXXUAUSaB|>yUs1mbQ)J{6$aen$82|6aPwmYIDdD_Ydo) zIp~o<=L+5hUHCct3-{~MLjMBpJ_J=*Nejd+6muIZyYI~Lj!IE z)z>k`)-3BDJdJm;qFX*MU$Z~p`8dz&O|6~#9bdiNwBu&%p3NGk`rP?&9P+tD@)*53 z_2U+Z8LtH4`96r*E_v^*ajlRz2cEwF<8f3t41QSUvemuc7tx?LKJL8#<8@l*r*l&P zyQ$~!yJkcNYNte{*3yOiH2>#HO zI7Js0vXq5rR2i6!W$z1yaacj#7A6I+ZXQOA`@nO+0j0RO5q5Ss7hxbKMIPH1ToL1P zS~KOSqQ-5+Y6}TmJLPC&8*LoFg+Z(whwxN#W1{soDuSV}fx;qG$i3m;xek=$FgSJz zY%RW{Tqwr}?HQ8^%@0c84nzifaih}h&fXvTO zkXiH($V5g#BP1k*@=IbGRvH=_W@cs@HX&YKUK%!GhEEdQ(gytUMo^Z?ui`8&E-t5_ z3}u;`nwlc&_E4NDs^KA_BWvVmZtp4kAAT96W)Z4x6|QX)p=uuwm6i4WBFs2r z=LBo-6kFfFva(K8=2!m=v&bgfZ@vH8$zGB9e|6;KKF_@A@bK`&#KgZyGOjo%p#&O9 z2v4buN~?k*$$z!uu!^>S%;U!N;?|ss?!1EH!qTeZiiZ5Ep326qfU3>3mj3AW%ZMIG zde?qYU4Lcs02E2qw*5^a)OQRw^^C{%L!e0nD3Z(^fmDBAZSS9i^2nZ%g|4yH-kGJs z$-lyJ{^lPjm26mmwEQC+7i>YG8HDbmKLdYD2+L66czkvZytwgwcE4}_Ox z`?>a4FP_}{v$%5rEgr1zp8U%r*UtW97(=P#F4QnS`5Qery|_NOdi_f!uODx2@BTrO zum1;0{(pcl|9u1$WCD?;Y%Sbx_B5q+nb4z|G3Bqs>(&9 z-=Hq?K)CVn7__|T>6|DEEiZCAIie;=lul=bqJEta4J=d&lL}&xA8R82T&$2F>eA6< zrBtEbX!S8^cX;vN@}et!28QWe1#yr!T;m^GeMc9BlNb0x1Lm~w` zDbzX^+@{-&M- zs=|~)pI~>@PFG0gJ90#p@$q7KH^X+wy-3k{%)M0JW2OBt$7kx{P?`@Za{n`~q(yeJ zrh0mDO66CAgCeZ}X-g|(2A51x%j=NT^j;D;&>J+)c(?@b0P4eR?pW=Ua$a-@Ls3~# zhD_1723N_`%GQH1usSNM>+RCC+zffN3A8e^X^)HNwPnt&83Uj2N*z6T zLD9`UCx?-~upsib;z-7_T88{gyEncKjES8mW1ZyPB}3L9-0-(iE;}|5QMHrbu~ga= zW>Y+^G%YDu+5Rv!^~7y;My4JX!Z-h?y!i5cnA{CoUZh;*1dh@?u?)XV zkCBZN-^hO|l)FLU+4MG_roKdV9(&Kj(=;MVCg7+=%5csJ4y*ZnJI~%qTTda5*HFKx z>UQ2BuOBAB{?jP6nr*_YwA*~eYIvY!c}lQie$}*6((R|ZP6+#w+a^TbbyF3B_AqCG zq3|#rN{0S%5L%?!K_vTz_G?|Rq{qU0?ddGBBT+Yo(Nm#5(uy^U7 z-$Ds)SqZ02OLlxinVU5os~z8%JTJ{}(7VpUF{Zz650TY=l&U+-dAR{Mu0P%M5*fT+ zjflm0-cF`Y`CKIolRn??rB3r)=oC)B{_bns^tzkJBNKQzjT7>{IykKD{^K=g-wpYR zz45YFDgf*I!8;?9^a5w37m4>O05d5YVZmH*^2Yw{fhHPEg}agw>Hc`ytHaf2Vbe-CVTEZG8Jz+$6 zlQtq(!k#)hVa9ut4vsG2ER~+L(!R;~IZ^Vdb#&6s^Coi(wUm2Udde~5ChJJ9ly_-# z%C+Mr`zpGW|4@3`bLA%IVWL#72C8d)WR zBDQc1j{Kx7fR#q0J`gAQ=H0gr&Twu@@wd8Lfs|!Q z#mqkC3T|Vcok#;Q2|*h0oO!c3gle$`SXSlX&hsT5Y?5S{Cjg_p`HBiQNv&`zctOlr zG0oqV=Ftg+8DNBuO1M=PG=+I4NsBG9Z_)X#Ds&EImO55`*SJqs>feto_51~yXiUP0 zqJiXfpgIHN??9Dn_K9$WdP^eE7Yr1wOQi^P2F%_+PAFBrZy2Xr#LJ`unMw!u7SxYSo_pLkx7`8)I@Lc8I@!Qf7kAKLE2IvXuN<+^uhYCY;h z^=k)55YhY6;B~Js+85o7?A zgQ?D%iWppe5Z~1)iL9}|EsYu=M$(R!A)m*}`Z&mF_bZCc8~Cntd=O884eT%gAWHSe z;GO-dgFdsX^2$A;M%54(AZI{Py^#pB>HJ3@rpQucKs|!t5^f4XR+$p}J@=md- zSnje?pKEDB^!Vs>v$mp&AwFD`&3xmKZGDcPxRv3X0QV>E^v@Su!$#h_aHnZIk}d8NtQ-Cz8jro0hppQ1p*OvAFjhwh)4^{Y4-PBX^%T z7w>q8!uBh}>%JhKhq?(Z1D<9d+%Hrp65hJliufv>`<=S+FQOl3ew??3fv?(j{1HTv0R(CxH}<;R0`%GCjAvM9H=hj zAJQ(?a{vKbl?z@yjFXXI%BVe#3S6$|ItrH&(=i-Z>juwp`NK=py_^I*&%OWIha|7` zdPc=mnDpJ}oUg#lSm?L+XNRl6& zd)S92~NM?Ts8{on67PM!E{)jn&BJY#L?OO>yT`UAQXsJ{vX4+BP0WmG|3~9 z!m(t7Y0Mqm@&n9}9zNfvM0`7<>d~+(`e`L{t6TaI5x`BQQU}jRj_8#d=>?2x07bzV zM`2lrbE^RBxuaM`-9=r2@?co}IaqmckdI09$OFdMNOb95^k`eOS)0{#TD14QR7iXb zxGko9K8A1(c1u%Xz(N#M<|u;ic_1Ns{4@5_IhKZ#iiBKs&ppOdJnjxi#rrenIXrHQ zI_}0DsHhZ&24%D4F^`~lq=@)8(lTr+@x?pwFw%PZA&5d(@S2z*LCy&T?FqO%GQHsm zggnvb)bVr(rdlPS5|AlfxeW8N>)CB0ttzIe#J2#53DBGzksJ9NuLqI{g#wdsm@O`j zd6=8{ql$7^lC+izE5KRaQbm!+MVUTX7CBjMRQYqdt5$ikARdC;axyyNSHp;8qemr~ z1o#uP6!T*xp6htqM@6b%8lYU{mvQaBkWX^o>9@BF}?(? z#>;!L^3?KVHhGBGXl33wXSR*Xd)66uK4$hsh;+dRySJZ#<^ zT+e)bt54$b`NS*vq!n^M9`h-A3#hdV1jLX`t`H6U3z$|4m{%mtFbmmv3puq5KY12% z^A^5;!;St0)&lI$q>5?P2Md@Dyd}`Y-!2rc5JhJzLNF@2r`MEzDnxD*m6s{{WiF%2 z!-@4q{c}eVy>oFeh1|f;V*QmuRnIU?>Jo1F&>j!|x)2<>K0p<`pSld8t6>akTJblW z0@FyHs-r}Rc`;i=BuSdAUt|uS1W*MM56?r67;Gq|`QtCkM8}i!B`hw$rIO$BBsPq3 z9w^UwQ?Zy-mh8kHCJn67U?}Ix_+sK&R_Zl}Q=m!(6i`b8{f@1vP%N`j*58K}-G?O} zmFy*~`e7y8r2PqLrLxBpr~*@kwgs!AlwNyM1!kz8f1_ZwqO6~cC=7!jP#@LxK)e1_ zt>sX4(o{`?NF_8_;}%R6idoJ+DmzN}>EsEc#Y(y87rd)dtuYQjf4jDnx-OuQb0U)M zv7@lbxfZ#yuA!-l*tqiQsIC^Fo@lNPr&9_+mK#Zy9Y3>v8~;K8 zX^M8LBPfLW$1*1wb+UZTR(nkmKN_i{npM3xb)y>eiDaa_>WxojL94MEUM;E4wJPH+ z-6qWrr?Pr{t$8LT){N{%)~zu~ND755>^A^!J{ilXTK2})AZrP2K5a4VmWWDOvFEl% zgl6i@R{Ws0L`Kk`HNnQW{!G4R-njor}unuBN4|H5ZGzmm6_B**VviA-{le9m0a1C z%GYHpLOA~nO0wp-g8b}KnCVVR>f&)?znAIJGbsUAwjSwpoe)VMRCWzy_WbIUI78{# zTB!4P?~UN>rKf7^3c-Co?v0x7A#~CUbimaVGeEcLv!~97iDvh&>%-s8!CVt7lH~#t zH@7@#5>$awbovP!sfmcclRj`#S#vy&b+hpI&=G?+i8vm$yAs>Fp@oD%&VCZH?^}%& ztCc@kKXTvku?w#8Uv&y|>kf!!NpQ&Zqjd478B?r!eV0Fz;Lqwq=HnWlBhWYl;jWp? z%=Q^{N$O>E__GpAGYzTh4k<9PbLsTM{pjAB8?sxIV6++NqQNnW7H)GK{%A7%C8*u< zOh5l^k`sJyAOv;9Flk6{;v)rcW}wOlFA1ySxtC^QjtlbRJEW?TW(U z0cv#7icHvvH`GMaOma+6HjYeXiD6{a1`2mQk9NbAM=VW9t};2`=`xuRPq}hVg|GDq zXJH>@Nv=jmsCrLHzf8GvPEj=RWZO)822Ti|^%Z%Sy%0;9)>(XZ00XnZ0C_|n4gmTq z81ogZ#|k#&L{!ZK;|m~t!k!^M2OA2{7>Fa{#mpd+AQ7$4yk$lrKbN4iouT#tlljcj zorCQltcZ-05|rz+9|UID1?HUkz+BZ5JU%m2)nIj2fPlc9I_A6%=e$HVSal0YI%bxC za$a+9o&{}zkeNg970hP4ps_d48v|A~oP|osPKJwywh~72^CqtgEJ2G-bqm&d61D=1 zpOqHaf)+pOE!nIuYUv?@d=~Z4=6wYu+^Xl41r|uU=fh&4wc;67;UyL)fJOCE+^cwm zz`T{-vIW{w`nh;!_FP^zdy4HcNA+wznnWS~;1Z0)PRunKauq5H%d74+41}?4r;5VzwdM4U!Hy;@>KQ zN*$s;+PWM941jzVN_bAXH%@F}J~bk8Vs2hDZ;Ee$N98vpi#D*yX90a1r_3PEC--Juo) z*nwBgP=CBl3*T+sf~Rm_Q=_7W-(^b#U~O>W*lpvX!-&Z*kNE(^gyBW&)-cY0+6Ln& zA;pEROzgLAr8Vk&6ow_y0Ms|&y;&3^`OV zS0#nFe%T_}UaeUM?*+pk;DKQ%9FQcgu?`M*;NDVwBHxz`W$2;6^l$?PKzxlY&-N|h z4~zs4&SGFbiNRa@0&KPpI9cH_{X6sV5#00{DC&^>hIh7GVM}~Z%5qLBHUNQj6~*k{ zba^KYb|+OACupqR_pkdf1h+}Siza_o*qn}&1lPvT zcWqTKoVU&(Fz1LOfWtqRFp3vGIh0LEM}Zq(%XYTHa*l!of$bYd2r%$i81Qilh_56t zB&3&GtY;naJ5;`i4CGSiZ>e%}Sn>r=yf^lI(W$gp_GyIorSd5^AV_>l7uTvA`~JI| zr!la2EU@1NHKjmLO6-^(Ja6ESi03_|6MdzQ| z6dzM^=ky!^q!-UlBQ^6J%Sh$Y2P7g?{%1KJ~ac05;2H{KfR#xA-1TSfR_w)V4r zq}LkFn7T^o${1Qjus>K^ZX6#`In?h8Ds3QQ$W^N~TVMHY-JNgg+7F4G;oQ!xbGbZN zU%kIfXfPieb?3XtV(I%^MOgDV6rCx?Bjf~iV-3MqWHbAQSLL zo4!xaSHGZD1dNwgpO?qqm$|WyK3>8I1Vw^S?-*J|U?jAMy2vI<1rQiwR*`=|X5GV_ z!w)o)Td>&e6cL^1{nn4Gzg2`^br?Fjtl~G4a?^Rp8vj%gU<-= z)pmw86u20CqriW2E2n@rr>cm_`WpvYMbO&25knA?M*VlB7U|!ST6HKG%Krxp5mA32 zf+8UX76wKp8WwJ9Rv{=7g7Toho3(28P#&bFrUqp|Vp<-u27byqmY?+;rM~!qzWAws zu~RegH8iuev9)(}boB7>fcCT%EkdAfo3crel5HF`sjcr2ZRivSRocwl6Ro{c?EErx zqB87)GN6OCz9EU$3BCWuw4qeUA+E(ap%Kc4?7sE+R&JVhK|;c#qoQMClX4SNpp59h zZqq`&wd$D6y5x+K?A-jsoW`J%#_)=^to*8^{N|Lxw)CQwjN-O`ff2N)U0m4+?P*sw zbjMXqLzz)}^+0M%Ka?Ehw#)=pZ->_HhPGS=cR`>Osi+RBv<*TLQcc@16d~1h3^sO; zxAjgy#kT)Yq)|xc_o;?KaP#OUbiB56da-+Ay?6=&U9N>9B&gN)?`Cb+#l?@&xxese za(;Yv6$+2$es1>9>`%;ZLHW_h>h;*>BUEWy`DdYaa`(^t*8ax!!TQb-c>ixJd-vdE z|McSc^e;L3@58j$|CnshVcP$Ljs7=cBPbXmLiWA|<%t9#Vlarivwjf^#Ke~LE&>JR zhQrfhO@!AcNJfx}MG{M2?@~t5{2i%nFcl{i(H+Z@=Ag#I`3N1U9sNud&M6Qy8;oE{ zUBpQl8L29RLpf7Ik;@(eJ@Btqq0wkXvr;(nFBl?9nF2Ie%*DPMyW~rSqL6f`(Jk#t zwjnU;zl1B5Z6?#+{~?*ce!u;L-JVi^;^+SKkXYfAxXhL1d_{7xLQw`m<>Hi8t1Fs( zN0ViNnPR2nbM5)sQXP?C6^e5H#}!`pfx+|j;1>}#D$ITlU)xM+TH&E>bl zkMqmGI1mpdLO>xF#5mWC^i+)|E^|R0>5-Ej8OsLM2r% zBwO!&z7;`i*}gg%@AWVlX=q!q<*DU?dZYvF^)#wY%ke>`!w~&pmh;%-v=GlnNAqm& zyJPcQw}Ym`+~9X7=6QiNmPZBAJrNf1L7y1P^Wz9VsuX=Qdt;IQMLN8^ByS~xHa#+w z_lFQ`+R8!p@mHC7@Ahs8EjSy>*iNh44k}J-y3`py*Y+VX+SEm$Tc6c`Uo4_+nE2#X znGna#Sl#qd-kP}q$F-D1dC8TLseB_e)4Edq7h!eV5xR~|$63udOUFXbYE8oR6yN9W zW4lz`5QOb0mbO3oeDA9dbE3?9+X#uTnlD)7Y`f5PP`(aeh{^nFVp8*D8v-2i&J2-< zF*USd#xVUFc#j?BIM!V=aa{xM$zqacuOzCL1W@VTOz~eX4y4_dioDSOmD;O#h2FQQ|32*a&$=Sl<@d(&7P3m!AQ6PKhCqTkp{v10{%s5E7 zK$?@9!z)Z z4up_1B*XZWj$3W@ajSLAbJ4G;`J+wtVwh5VcjMx>YOnKCp+AIGeZ14P9?9=MR(i>F8v&!JoQ{&)i()>)H<|W)Xa7)e7ItXNSGYEISygiw z$ZDHGEM4A~$}`{AY0utmyTW#$CDeOo>flV&woJ?#s7P1pV(Kj>k4x0pMnvj@$SG4M zt@i1Q|92T~Fg62{?Tj;a5#&9Dwnq&hqM3*q1S?j=V|NbkxxxmV3OOialNHs+BBHKm z{LLCUxiE)opxQ-X35#zus2=VgAk8e#CUO)HpSPpQr@&kxV=t@vjw>cd50}xsnJ_}^ zXFqz_5ks_)i7AtmhZXDYb#fyyGQD4_uP=Uow&WI|>i`!rY4rz?xo%U%S=&B&{t5;* zl$!laQJwZCwXwWE>k@2qYnZ-ql6q?^FL4+-gN$#huK^DJ;xYoe?BpMY<#jA)zcL%! z*L1^qeiVxpGOOLc5av#91-LS7&Wb^(%sjNx99Cbf_H`*IdrHE6xTZ%wRl*Rw3Lte4 zZ!LNEsXm5z?F*X2&p{SLqvG#@@8gRhjvUK@DnEmXX+ba5{N>ArMC?rOcw6wAEyxsq@jc^hcQ zZAeldLULw^lAF>dCo~_7&RGjDU)MZ@u|g5YR|`)7A$t^~V75#q;`AgN*#J;pTnGEo zp|UCV0lt%8XJBx8I$4Nf9|$|;u6Bv3etOF76b{p4{9lgL+EsTX3b@4?(lsqkxyC$f zaocJr?E`m$(grwdG3f)|?M%5@5ac8J(4rrbs~}Jlo8`*Km~P<-k)Jap|B7BF7Rh^2 zHK}y2i^U%x|BmoD1rNB%IP5w^rt$#W{~71FuuYbBpv5xr*!XR|NudeBSaRwNX(;VJ z|B}08yEvAq0Li(uM0~+V@BJ-6c4|!T)weIC7&_JZ-c78sJEb=6Dc6VMu3AX_SN>gE z|78y3J{#E=KepFf!u*1A15fCpa=P^_b@N;c==U(1d+#4|(FO}W>Qq<<*>3$Bou~GO zQ+W217!tRidFx-pE$^GFG^-~Tkl3CpAdJgBPRXqtV2o)IKpKvZ`w$Q#!h@L~K*X({ z`~}HZScvjxAU`a!D=UEMD3FiB1LSHNXYQdTVTus!$@vf@HA{1W6l{Xc1G;l4Ey5y6 zw!?M%IxHEi#EnHV8;q}ErhJ5z$sw%j?mvQyOyWjMe&~0!8$tpTN`dE3As%W*7itvj z=e!Fv1u@dO2|H*qI^m1C(1l?xNv?h8n!&T2)R6bb7xQZadLMC7Bsxtxy|dsJh=9;J zog4ec=Y{j)MOf{Hx;Q!Uv^v=w31qZ|^Dl*y-bV1^MW*6&Q(!rZnMb?;kSpkd3XVh) z9wLK6BJ@q7+~#Pc!-VyIE3nVYe4~B8fruDF(oum&Musj`O<3kq1Zrv55DYSG&cILZz1?a|9T|K&`2Ww^~wU z>;Q5wKRGJ^I#`QEfJ}1CPmY;Li7dq=r8$7NZfTp5^Ws;r=FvJCLG{7K-9QRo|P7N6(>yfP8o~&!BueF?P z5gcKFoT5#gVlo>WUeH6D%Pc>;u^Pcy$w<{e3s+e?eLlt|=BS5-|u$dKmD zDDn^wd`v4H6)S1a5TDPeA;@fif+4NU7LQEb_Ov!j@s9S)T7tA5OR+lS%>H&!OZpEL z$e_3_80V`1pBtbn7?zV=#K0p99`WtOah8`D=1c@Wk4g5DH0CnIGQb=D?Ybo!;t12$ zG3$FrOlO?8yYvCmquI0V_#dI1NE#H!3UD$6ptCy1IRIZg_+K7@3QDj}b-D0QAfiv8 zxGVTiTe#41*;zw2xb(bU>E+}VdB&Vsi^~8gw0~zfl$5eD?(ALN>R|f zpgTF-Bo&-{o_~*6v3drKW<{|jLUD_cYWOXMo@X%~51(0v0A+m1_z1hv3S&1Xh%tiS zWkvF<45LJaZScHhq2#yT-O?tcGV`QTPftdtmC`mz>kf!nX;cPGGg5+vNtv5yp;Ja# zK$0DJ$VQZqce=$!H(WC52_xkRBh&&^U1YnO%wK+D$2DKhF~{U(RgqSao3I54w&IV^ z1Nzogd|_bezLja#&f0>n#B(Yi;1x@fDRC>Xoyw>>HLhajfMSsNC-Tb%q)SgqpR;n)=}yKhBEnCz*>3@qW)5=$_Gu4C9?=ZPm)BgR$D% zjvAP8F%{mrO|hB{l?q5*EfSF!)Vo8g6m?-`flQKjvXf#`xRi~N;GS0-z*GQmRKb+Xeiz4hn*vPKKDEQon zeOoIr-q2(e9tF-(cy9We%jRoV)oF(6ZJL=XdSP|iK}@1ijig_i$eS9-WSe5PqK&MD zM64U7y%_OUn=HM=o*T)&R<9dro%WJN&G) zjV-fA;SqcczT<749PPu7Z9|D|5+d!cUTjgA?c(1GvMPns7?~naXfQu^(9Ac})0c^S8_3fo$@GzS*0{OTOx==A7h8tm)}w(bHnb#}nD zo>C;w>=37%cGY8dmBLWKRrXRJeUM-6MkJtvp!8LKZi4qFxxDKE5(__f^bJ1K9h`Pz z5DPn;cC4TFI=b}Xt?|NVakTQ;o89&EdNMP2_DzAXNNv6s&Q(*$aaweKX6X`SAf}jB z{((LKM6>F43<=@Q60DLXxzJ%HdpEE})m_8KV2xx zoZqHzEs*sAZ%|u~`^vMtCFyLb*{bVWhAAV-;1SUVTV4(R}%+qdjt?#xQ^u z@A33AB+a_<7WnZ3rg7sdq*S?yv=<~T|B2?piP)F%c$?85auW{ZNb_=hi{6t-x=2>+ zOyG&poR`T4?5Q5&(UPvoR$@SP)l@z9)DrP%6Y6xu#MrIw^qu$gWYu&zD$vGZ;`N0W z;ynp#J9S759P$POU#H`lkZdr4aNVQ!Ta%dUyvRP2mlI&{+9=WF3<)!msnR&P`~;=I zY~|-!qxflhpYfN8*$N01k}-G&g_#L0dz`bImn$1=yoL0xdJe66QXrf6Q#KgaXC{Mb zQYxF*_-gL%Wk#H2_V{JK1bac6WQuljKD}#JQ;(MrbAde%me2ul>+!QBZ2cM0z97Tn#Tr^&m& zEw%SdP1XD}H3xqmbv*}t*j3NH?zOJ)J|iy#$&7)3Av$S)ii$P*ltZw88`AS!HuXGN zHhclml%CfNplvo{5Xl%k7xQw~-3vit6^Y=HJ));A#XX)gNuend{AZlJ%>taMG2hF@ zP*ge(>(?p}eJN%Ot9X z@YajHQuFU@0cY+2)V9S?i*ZVgsT9sRNiR4hFvlSyXmJw229OZ^Dakep*kS@%5=0zM z0M`$r9kl%$=@-G4F|X3VM~}-%FB$ALW{|X3N>eA=d=OZpkjGxm;`0J3t0Xt$053BT zE^-i1mpR`9q$CTGBHEPast_YdfP~-;e(nvyvOk!dAk!W!!z zj(}7x$Y2tV4_3ufIdEZKprAGo<`HMJDZC^Vh(l9K9e`p)2ef?JvUq=FYxlSKNuvgJvZi#KmS9N_>QKjM0j+SI+ z#3KNU=x~O$@JH)MyItJ#n7)7>j{{i^B-z!25z7U)sD5iYKy5aUt*QSVfrg@(!NTP} zb=4f`bT{LO7D5My+IoUUJT?6JGY)V*c09qa5}>qxNWS(@*e8*~^czv=8V?OEX>5}oH6L;1YM<0%WznUuv6M=KlG z@%b(F4j(aypBSXAaq+|U0-fhG-^!Vm`xNBch1~J!7p+Ul$UgG)%Ve@ky*8xHk_$zQ zGi~UZt|yzm%(+7P6{*aqMJt;=$tBOqrOolEeL0(>=Y@0Rm23K#dpeuv$~i{)wGH&b zUxrQJ>V|UU(x>(2^~z1c`HddnmeKR7ne_TI@l^sXTV&)dCB`-H@vR;4T?Efva^!{e z@vU3=U913-0q=dz$hN@=5=r@uX8KJfFioq;K-s}Z2Je2nH@ZICRUeP_{(NTkOB;&z~~8|l9Pan3(TMq*7npebv86Kgb@>0S64x8uV-jt9w}oU z^$#~uG6{s3hr^s2m{6nSl&)?Uqvn#X?3|(MoB`_t!sHq~*Lc_%pruEWmS4GtPk^0Y znvP$&QDm!0)PKMf7)CLTZgb9GaV=cYuD#Q1d~~ma!cu_o@$vuYHn0NVU)`n%Mp9t9 zP1KKa7)gN@0AadKeCDrz11N=!u~p5m0$^rdQEu_GbW>8@T3y!|T0EBUbHex6v41l( zs0EtRvYS=jmRr$Q{Hycd?VE~*ZkT-o<0jFa(4_YB?>*3zK4?+rKtsoHP3Hs*oiq$j zH}o(3BjCW$NyFfu*0Ifh2Pn-)M;-lBu(`j1v4y_b<+icS&Z&d``PJ_EGuY5y-^%Ue z-0DB{WbhAkadm5S^Iy`<#@^Pyq?`W%ojm;S2;l!Rc=8vW5Q;{vX8Rz&K$R@0z!V5X zA*NUGTa)SXe?e|KSU|rn97ObtPAYTyB0@i=!O%(WK;j2qJa4h8yrKB7YKx0~Rrw>a zB;yZ+{a7&)qQV?`Y-99P<2jK(#QloKb|>=XqYay3`+hU!+V!Y>Sbz8ZCek$QDCOQ) zTm9+xXM*So1Uh08D6qz43x>SriMcSt)fedyw8%sIQD?39J%a3f@Hq~c#z$*bCa(BC zCpT3E|#^($)4L77opl zrd#pe;cST<*uLM^;B;tmO+EHyZ&|UB1T;J(o^y7p{$0KFNDJ5dc|LYKknTdWyC~EN zd4>34t*4<21(?Ja2)C1>Jy+fJ)n}Zq2X@(P=VH~5M@J-6Cer{hSur>DgQjAZ)FzRM zR&>&W%XKbZqB<|&kDMsJ>3z%@qBUWH7e19!fVYlIO~K#rpM|^JAbg83I9f zwgf-7@kVR}c^`$W)DxAlh%CB`Tq2n&zM?#-kF!BSu8v8X31NWPbaIjlP9LdpR(-Gf z_hExSCRSGz5EAG{#$HiL&E8%y+b9&UU-GNrZiI)Ed0e=t`l_L*qy_1IkH_ys5LDjr zp}3^H_R4O*a#YytQ<)q0r^8~_uj*!1pQNawtLFpW9F&@tB9+zc49|Zy-wu)JY;4O* zL8!k9zr*%~8=mVeeYn~`ZUrEJK4}Bmy2`hMC`zn4IH?a#I?<1R(RN`gKOCpOHu`ZY zP2h<3(@86N`?MFeO5&^!e#MAZ4#?wkHh^i1c0P!-Ajmkxu=2pr&3^1=HA0zKOK!3P z?_Sv_>>5VZO7o}RZVZ<~%BEA!RnmTnU^}e(H|MvZOIZcyX8LNl!1q^k#`zY^lcvgU z_6ulcFCE)$M!2kI9BLnImqDJ;PgvFF=hQc=7A#UXzwL=NZKXmGe$=fyv9z#C#=Ka> zoJ&%Mp%YBT!*3G-%1<>rk;IzpYta%OE`JEP4xM&>^t7-YRI0Z$tY#Ot)NU14wQy{E zym`x7Tm2WEP?SHM4YC}=oEnj5bfWz2@p9Iv{PAk>8J(;K(mvg6Bz}9kg`tzDyMx-} zr~8v0TIj>YGdj81E{8rnTtA}|v6aF@? z4&Sg(f1MhDVJ^D;D5{6rvr_~1lC=&cBc#txT>R_Q+(1wMfMAypLE2V=9)8bG4ZWM? z96YjSmp66YX0Xa&*6VCs6cI^GDZ(tN?ot;p}!JHbD;5bHBn}C%6 ze>gS&flj0f_;LG31K2Mz!Qln34^O-yYrSFS6$sjDf3wV zHF5F()u}1bMwXcEAb9O8!CKNGNmu!bGQkj@tsTq7ZdSy&9r#`~Nf6s0rib60BxWec zh{s5EFhWp=V9ne}B!$k$uZE;#s@H&Vp>`6=;7?v+K`p3O;qP|3T}}`jg(3DSnq9Ql zu>LSnz+t{~1=ZnW`rg{6>A+$w2}}Ku%>e1sN#M@7^iRemY{%w>h87dYCQGq*4vDNm z1$o+F=>ckw`4oj49|oOs`*Qag3Hn-294S$QedEU$iX7}=ZGbOyp2SL1(i-vAFR$Xf zFkkC1OFOk=8~P!zZvx7<62809kPn}f9BM%kAyo>^Hp#xOt70%xg#Cwr>f76 zqvKi^zN{WtVu;x<44PYz4{o?&fc4_8xVy}{C< z^f$5Puyl61E8-6YomfBjkJS;IbPQ6g9c6;xAv1nHJ`A?XYrjk6c|9Hf{Gy|zw{lovfmaR+LF zHn_C)h8&^lc`wQ=7p5$?>IML)+PA;v-dSHa?Jrfx1j8){-d(q73Y~b+HfdwM1#5+E0!o9hP*DyFwf+CZkuQ~Vmwv<-QWfJLmxHLInqELy#VbRRp zwKe<(v9a*anaRw2Z*AIY+Wyq1O6*o4&H1O1_DOZg201Kc6}?ZnMRf^2i17y;cr5Yh zVue)s5UPk0anbUh;($DB@Atdk{nAbppyN*=Csh@g^Mo9=dfM+%MBg00S;l&Y(46ZD zbb2pw!iP9Zc)^Gx;pMoqr7F)SKbzo%ZH#ZD?0uil%_b;6ZO@^-$*?}9aTnnI-WXpr zQ1e2`Czzgxq)vkr02%p5*?8$?q`+ zUf5V%w3k*K&(9yx2K|e$+zwT>g1>2;?uQS$lvjf4L3$cD;##u+vH%^+Qv~WO1e|UE zXs-a)yZ{KR_;VSsPV*NWkOv8 zKt;1AQ1#+%=m}NutZ#~L@Lp~3kJ(_n3(#f0PnHw@ElWs5yJzI8=SH{IMJ+JzCL}^O zq=FUu#jGdesi_|`j(x?Os@YIZOcYOmd&|zN&q)G{Q{F8f%oCV=I%mTIE5mws!nz8) zjd~nrrj#X+5gF+aAOOShn{d)Gq50nMWl#hSJ7llJI0*Iw0C79MHn9n6xQb|Hi5^UHK?Nk#ToM9?WqDwuDnXTwnAaVHL6YFKZn|x21lSwUfPRExC z;H6VOO-f@+ez?GfLcV{^Oiofwa2&;{z=tH{XzQt_tSf*J$>fc^fTC7NjPWTAbJCWl zh@O*hT3+$LgQXcRMQG(jMCX1Ce~*TLZ8*6Ldm^NuU_JXiwHqHr4k{?5WGAwMlGc3- z(&hyU0+2fKwRW6kMuUh01b&=SNk>^Bt3~NwI;S6FCvL2>KIo=DnMgmXX583ifKa31 z2{K-o%3O+NV4zB)vS;owIbxb-?)zmT6lK1d&-k*Qxr-fz^)YLrD-+!`Ys)VSAwTO> zA&bUE3ZEc*Um=qzL>i{mAkAm8Crh)zN0pMC&l&E@ z*+$7#P|H8B+q%&qFm(m>6teV?a4FL7m(XVf53&h~|>Ay1Zo`5S8f z;G~0)c>Yi9*LhU=)FJr;`uUuD`87;=M&}kjYErMVA>h^c&rp423~fo+aA<=X z{skz)G$Oen#OhU{W^4gUE@r%G0oi-Z?+t}RNxT^$5X_$i0nrxNIhgq&MFj+I{<4Ko z+~T}Dz^`O4x_HjwWC)PHsC>Toilw-loss~%q=Ow?mkiErDDGn~Rs2(^{;DMGBo~;A z8Epk(L@XUcMRC9hpD6M~^DB*af`nTIDSh$Y6n|GtVL)|L26W<`b@>$L1>w5Vllqd2 z@k{?fEePRv$?Y8mq8WrmIDko*A0CU0h>kCT_7`Bf?Q_ogztnU+L&7VCc#yyg)10SUcQR?V~Pf{HezO zUcmhxBjkj^^V83p&#X;6Jq$glcIrZcn)Z?R4IXU8|cX2i~JRX#Pnuiva5 z1UWy`t>1TdkP+xLbvY06{v7Bo*=5M1?@fVD_E-!i`;_#e{_26Qx7!mIP@wg_IiNd{ zz%diWGZOs_`AvR&qGKBS#%6U6Sh`}Ux@gXy(ZpjAh`o3 zxVXmMNs!pVlLU5%5UEKe5~O#{bYdFg2BVYG;d~ITNkJkc#i0phu5ok7gt`=;2K5xJ z#gra3h|+!fYw9%X5)wx$odwr~;maA!$tj!1F>|X)U9M@K(wSFXGqOYD!b8(~&69rA zd;#vWZ>6S0QzyNnrovzHDT9$BAIEgS$g!!D2JUmcUY*tXfTgiuqFH4kWL}Mhn$)?D)CKvMvkptswqT?-i-lUQ#YpP8%B6|0 z=EWCw3q#=x8i#XZOA`iBGm}sY-sz>q+~(<~m-EYyOF-=9j_{?Q8q0<5%RAJ(G*)nQ z+Dl(};c=r@Zo}bKE9i_XkX(4j-P$aH=tu&qaHsCPEU?2U61duCc=)zeENQ^&3OcS6 zpp4a;2MNf z!AL%?=DLemtG9tpnr6ELXRXEtr6mC7wLlJ$EDmYSz!S2g2;^Lda8aA=zd%&xSX50Q zbI0$UC`iP8aBA8jFsDSl?(DVSG9Vyg$7XyWTyM$LW8nqK8fpc?>tSU2mq=UyWU@mf z=8Wx#3`F@0IBhS(ujmQ>Wr&;`o3Yn#?ZL4T%ZT6JZ2-vje+|RcNaI@Qa;|CY3J$L# zL)K6y5FD0w(~qWGEqIQ{5EpOZ?0L%+F;S|}g_~)qG0+D$gl!#o%;yp)GRC? zrk)+HX&$X>a#E&kQ7kWhiUQ!AtUIKx{jeNQLr1pBSiI3giU0sjegPxefUr>D_7lb~ z`cX_FQl!_B@!6r16%bqN^tIsq2=_#((>CxMRQ_Cf55)kSipw9^+7v1)U)V01+ z9w+b#0u*El9X-WPKSd=zji^A5Dcqm+*a!b4=9Cd?9wzIa*dm7@h?c{>BSw-cqZ86T z^RQa`P>Re2K-8_^8F_m+!A;JmwJ(#B=)1fZG;A62`HGSoF8S!< z11%^`dXo@+U9XL2*LaWN``+YmY01$}+0&&q51E(c78>7HVB{5sET;|~yhZCeJ{X2S zuN@vQ-Zvw0jRNtO5v08k&l|Vh%epoyZz|ATrf@bavaU#e+!+nC>4K41R^hN9_cgR| zio8hO;dEq=h+2?ww+f_#1Z2zAak5eqWho3%WG0o?>!gwh>*L>|G>XTnmv9P z<~cipQcqBSdqnVi94vpVeYw3rG%@k=3GV&VoXpc9^<$g{(w^tz0Ws1L@v;GArfFr` zoDO<{0oDbEpvaGABymHrY4m4L(n(-Wjj)~V?=_(?d}hmy*|9$&uyvJ)_p0L?V*id# zlIRWoqLY4agibIgtH@|iFyFgw6x)gaj80^8rE`<%jih}M|2$k!G8O#DQv8=wV=`4{ zP<&P-ou;#Bb+}`{PDpP7b7~f5jehY4))g&prB!|KWv5qJI9tZ5}upr=sw@?`N@CZx1zCQX5nn@zHg)f8}ruLnkn&CZfK!tv(Iq zC9e3d+rM!@mdCFoZyE^mJ@aTVX&oEsc56PU zIbn~e&rVIf>v1*g1k1DrNEQc+1B$s~uts*LlsBz^yf_g63n=VkVo5Ol6pSL3wHA7< z>?bIQr)Z`xOknoQT3Fa-lD@~&NxvZal}wnmC}}7YL++bc1*{$-+pqeV!fA0fm?XaM zPenghP1+22CR~gQ2ja;Z_fr(3#YiwsDA-B`W)Q|oGD_*&O0(~897%A#F=6PZfWC|E zXFPm%YF@gHiy5=}f3}kqev@l19DBv7Fc`3IcOfUqICMD51J^7k58L-sEaGfktP%?> zBD7ajQm-ylpq0t}B~PO990!!~u@_Uty|Y!;_I=*>3uV4i(T}D6qHKt0KQY3S67Qg9 z8p&mksnz#iy&X9ie9HX`pHN<6z5wIk;^Kl|6XKG5!Y8ABN6SM+&+(B%hCxJ&QB)g7 zo;YM}<>cf5H+f!28)4=$7kV-(y3&x+M{?^REa0QVaF0hyFvJydrV~;);S3io=tiu~T$fWnf`#cvd3}JEdpk!pKu{ zZcR$wv%2#aI5qqJqve#h!QyTiO+A^-y+yw|V12jp`rgW>{(sDzm`>=AuII_A+O{E> zoCE8-)%DD^_D*O0hGq{!3;LeToW|je$`NSm=w{{Q-^$zH`KhMkV;E%W8l3MPo*5cn z_`5o_(mr)CGQIwL?yM6g>MTD_&acfbJr7R}tUq(6rM2Dhji=e|r}^DyQD<#qcjI5f zQ|m`i7;xG;`MW)JcKaX0Q~#Se{VzjK|M5dG_=H2HD+qykJ7K^N3Qpk6&VZLMxIf3i zVYG*0;iJbn$-Wbg`0MRd=JX2SNIiQyxdSmgeoa4M@TvdfM{}6BQNkI z;&MNhT90`5d%jUl7Kag3le+TL?fG}bY>z|s+WTvTr5c@%oFVg@oAjgQJC5@1hUUxa zXc44G`ybZC)VQ-Y3z&8)zN7R=nfg&u#yT?d8U=EWNCzRf7QD6L^MN!lbftbFtTm@_TSTtfP{?fvIashG; z8#+d!)~w5lavI;?h7_mb7@B`tHvXV$`J3`j*mWwt`r9VB>y?Pd+eE_DHz@dW5sEcA z`ssemC_B;+bW=()1@^*C6I$;iMQ8Q!TTBz3h`#vT`uN?gyi=met>nPPZj-O~vWnY< zHb}ME8X@4Ge2rdwXmCz|=iB+%jGAG6jWVwf{btUK%rOQglr{ybj$}Sxc2zVQ@^=eT zU>YTIx`lP(&dj!ulZuge|4>@Np!hi;D=&cT#SiQlwOQW zvK(IUa8R9HOe!dIF=r|nmD*2nS{z=^h+m^z&1y3$V$B(wrA{ZA)Joa6&NpaWy!UIRSh(6tw8a5pKU0^v2z3J!l`cBBsl;TqhMHvs~hGrzq`Yo;HSPT2K388w^6v; z*;nPhrZZ~io2IGsF&Znf3FRT@D;dw0si}5bjOM*{77e#s5!y(P@zU}U?%Sh4E+f^YT^M|dOL=&R3*)~W4N+tIju}rWMB6_WF^`prYEU2|A}*&eoR`jkTA(i8Kb{c4 zka`Zo1V-ZWQuE!y%tOyXw~4g7i+tXfMUX)8$t;4)0#T_Vxy1g-Jod}NzspqOQ$=c* zF!)rYRNFsQ=5krA{jyl4M|`?6`Le|Ld6}vo2A?iVt-_1H{!c--e}hj~6+u!Zy0`V{&F`HaBEW>FgKZ2ge(98H?RBGvak%LRq`2 zxr;d#pr7HZBOugf7AkW>lHO`075w~4jq1hWaNw{C{xJ4Y#`y-zFD-~=Rycf%>kJhy zLo4_@3^x!(038jg@(5&286W&rbucYPQ{TiiYJlyo8~yANK>fY`LJz!IqS}7%+RT_a z=-^SX9@|M9GB{{waa-@m&B-?I8Rgui)UF>DVAEAvMYp(Z=~#5;-;i~H@~jo&I##|b za$iJ@9i@&gE&U5WXr7f7A}CoM?HStY;^*SEc)5!c>xPwLcKVyK#U5EHb5{TP;8;II zWPFfuzkn}Q+u*J!uKt={op?X53+5!n1vfDk;D7KJWR9wr0w2MTu^}rg~y^iHbN%_ z$+$)C#)JJ1-S%F|NV=*;{|ep?;E^&FDEmF0D_vcrJhZ3OcsErMQC(srwXe2tH(fV; zDUZkxPoA+yQWwwx8V|tMP#z{}UJm*RM`3RLg;uNStHT6(%mF)o3dzuGvGeW$d|dGb zskR6-BlLETDM6NLIm_IDkY zKCGmeERVgXpVdcqmkmxk{vHo&p>vwbj7i(08@q4IO zr=@UFkpP1`iJKAES;xbh#H7!E)bZu>J?o+fGzE%}iuB)c?6f^AJkrUJL8Z@DsY zyE3-y2;gwLELu|d^pLh{6&mW2aX{cVwonp zx_0TnD>eaaO5WJ?sbL>m&Hh4;NUh|%GkhON`k9AQE6@|}Pm~tA~ z30=@)ax5J(!3OE136?qL2 zzl}^-6pRnXmI<;1^1*8Z{3>R^A6MbTR}o*aSYxmd6NB+plYDU3klvnPXabOJC_VUQ z!6FqJSk)i8^XMkt*>F2y+GW5KMZx*01O*s-vj*8R7x;_cxU@obe2l6r!t1=^RDu(n zf|HVhlk1-0Q`${%23|-OYlzo1yd;<<=f+eb#Y~|+q>?qXN-6ZG z)9bok(}vj)Gks()*ezNB$iYjhLo}>=N4~=t6i^YSe;HbvB#n}`Un@UMuW1t4Jy zYakX08I~1r1X&V}EeZ`1g)AnAA{K>2<*4D$Rk_LX-B)-#D+;LUFcKG?P6|gTCjYkn z0|`~MI_%U)KgRIAy+WXDT9)j`UD?n0vC5lHT(Ctb=qSSQwXg*}d^!XC%Uubs+gLuT z*of6wGx#_r6GaP5gqI{_uwf`6HsPuBRClkKmCvq6Pu|!GCzE)(!7rA`zH9bkEy(?Su&OmKW(Lx74 zT^HV0OqhQaaYX@99H1c1hp2SIqCfT8JtGNC8{U01saeHTJ^|U8PTg+OYy}(m5v&jf z1~RODqu5ooVG~v_0KT_PNz6>H>mziv^DCcYhWuu17X%;Iq;wbJLBPPC+xI?pI5Gf4 zC2z+aeboWgRE~Ekghr{9`XbWasgE^5I)eF?%M$O^QmKVIs=9^E)pl}|h$mrR~xnh&wjROrkW});W zQ{zij(Su+(ie@S|6*(_cHP6r`4<{GYjFfIZkJT`jxBo>HxR%`2WmAok?<9`(EjhpK zyGToYYLNq`S%1DCd%mek!Rnj{-deI3RLvBRz91+$-<6;+8YCKem%@FjsP7^WX_^uj zk{^3lXtpDgNRVz=UHIc;LE6V6bAqChgLVh6&gyQ1CQqPjar7lk70k4gn0 z0)5uSjcTb4A;m+t`D%R1?P_X{Y9;f|CFRK_m3vr5QzheFpf1$XZmQD7242UU5{4V4 z*&?BWIjK_Tf>CkNDfVFFyRs94@-z1G3$^mA5CuuA^1Fuehk4lbq;kNU3V4nRpn3(8 zYXvB!0=2OMHcN$mUjfr~usD7iD3)P2s=Rjn>3s>$W*mviXMlZtJx{ zed{6?6vGCXV_lWvU(`!D)f>jw|KLzgyRWy#X~^PG_EK-y2x{;sZg3*c$RB8^c+*(P z(fCW9-SZQRKcrE_zOf;t!D@h|dB4#oyT1K}Qjy_E>eMnAYlS;MI(0-E=VsqE0 z=Es{xeY0lu%ZB;ToI$dBd1!3YI!DWfddrq;%T7wmUSkXPK=U9O^Ad;j(Ez(1LhI>( z!YYTw^@76f0Mk`ttJqX4;JOuHt^i-c1pL}I&D2^h@CD@uDEc=Da};T{NIYy634Br- zXv2&4^$YqBCh&vGZ~AtEujF`NJL>t1h{Kqa2s*+Q!LK+;P$b1IlG-UH8A6#lgRMZ& z)s9d_!VqxhpAcB#sq^hQC(!{j@((8V!OkduFh82Ppd^^Wyz7`jL}IXugi|Iuo{%1` z3!eTru6d^tCuQ_So6w(5T0$#H63~^LxY`&p+IgzM;E(rlUC|P(U^kHIq6z}NL6xG9 zpt*XUP>=lsp@&*436xO1B>pR`E!c4>9)Z^9>)Qi~|1B!eMzh!xKJ{8Ek4_$(ow(75 z()l&(0Ftm+r|sL#IoOx_fZ;R?$KfJgfiqA=sDd&0yKJ%VExWynshInmQqor@9XBS9 z#r_gR^|vQf-);uta|Q?920U~7gsTQ3rd}&m45F>Van^{>mJBVr^(!$CN=@`nm$b>- z4{nDI*TwZGXZLY54Ig}!+bCgjDmnNtQ%V^lzB z2v|BwBQ%V>G>TrT!1$y4m6Uwvj{z=oW@)#v+>PPjS7UF($1H3I-;^>Fag86wjfsCs18BmNJhekCraLF;64^yVXW}_x{)W*L)F#B79_ERRsnSksp)`l83(B;d4$>UCD~w& zDSxiHX}`Y6)X_vKwKroR3pAW!>>gY5-oS&vScN%74IR&>@Ez6m%*oVox!!yW%5T5s zScYa}nfsy##b-MgjJOn%QYkhdv*{mxjPUD1eoMFe3rWEvzo zicGR3>g)wfQdM>=T}$GUqa0qNLZANhc9Gf=fG?F{Iq}S87P1%l;?M`4BvT?;u>*S6X4U#|2u2UJZSq4JFvP9C;wp+{Y56x|d zRbXa>ME22^N(M5l@8%GNSUkK}I=p2D-iMW`b2ay??e@(zccVS_g35MVp7z_&cNGN= zg31nhmc`qafz8s)gDuD|QAlhj2W8lYzqk(uEs<@@4ok2PrLDr2J@#C@5ZBQU+tT*8 zTlSY)j*74khq;-jhWF1}#K$ZT28It@Ajh|w;$z&0SDJ?%Z%^{O4jYDd&A>+>+LN{; z;L-ANSK1y%`bnF|$)xmw5(Meg<1~8%*w=F6sEK4>f$#}%mg@(HO9CJ60f##Ze1J+b ze=|WeBH87HAfacRAFwlmR_GD&3RR7b>t)<0-5hVQC>gu!CE-(sS$redP<^VzmaJab4(|Bw1)f}yR@c3U<_ zRF8&v7a01g0D=Nw9qsz~nuGM(e91N-5U1?x7#+F#>ufT90YrB3`RP)!00FY({|LG* zu#l69_=s|bk#t3q2?gU&41-kYbUK4@7}XAN%U=*M8IDGI!vhqHrKf{(u% zxHH@>OzlP|YdB2S{DvDu6Iz|~?c>eWX95)l#5R+Z*Y1laicAW8tFP3yzcK87J+k{E>xgv?ghl~uu0FP;9r5hT}yI6$&X?PX2|J~5t zDIJQsx%I$ZCAO_3Ea-MV*b<^JQCN`G&yP`>6IUs~wEycl=r(C9vo`s;a;TsJkNQ1Z zE>oloRPdGJGkp3zA@e2O)b=y~iIUiIN~5gbnB&!9%T(8kLd`hwqtE}BaOCQJekHszl+*HiCk0U9h zgN!SLwIk||kG2!C7aZpTO0|dfi?$St7lJf0L??@Ouw|-p=fp?HAyow>?C76~3@a`4}_ixF*|3H5rR5TRyS1|O4^Og#q=p7!+JEQyr z`;gE)FFKLX@_u9!XX2Nm7uKQ|dB%Wja^JY*?VcSpRToJud(p4%Fa{`R;HqwDt7qY2 zYH4d^<@Q|gbA>(k5;KVuGkuoPmhy87Om_}S|0m_=5tak9&ve7vOp->dQpa60hODz!oXU<}D~@fepe{AgXA>~GNT83qP?FAs`;*3iOJe#WO{N2mRSA;EumU}|P@LRR%ZGFob3V^&@Xj0$FyG#8ZD z7gaUGOti3q{-B((@3rkPPWWu1Rj($tLX%pdxfLD7)tzPazhRItvvobR4H^R*fogw- zgn4bf|8T-z?c=rGb4^{N^#dy{W3w6UyM;Z6**#F0l2$eZEg!uq9)~s!Z&r*zt4EKU zM>kt14l2k0!ozuJN8huX);loSJ2Klnv(!DiGzhEwO)a%e9&|pF!>8Wmr?KhP$+@-J z#Xm53*uVY+gNMuOJM%lRxZnQ9&f(7fF)Z%4as12-|CxpQ-@x!c=-&V3HyHY3vp)Na z{?h&v`s=!A$NcZ;PgLsP(VuYKKj_bs?%&Ygt8dTf@AOqS%O`Fa`kRdXAJCtSNZP-n zKU9Y3no{*&KkE1gK|hZ=g9y23>_o@1mSa4FQJ;dw*H=6F^++`(Us3$&i86u@m&DJW z%KpU9AMO%gG@Yl!=eo6szdtkbEj>VLsG-^{*Gy}`@?NHFX`zm6?|1mmW8Ux=9G2$z zb!UBX-LaueXM*)MJ;T{NX`kIU4AWAgJ*Lg^t9#3qJJq4w8p)S?b2}5Z;iWBHGxO@U zD^sl3SIgmVUtYaLf6zN^{jDeh(SiS%ui_oa7r5%fA={H7J`-<;&o_@l{?=H{T3OSW zu)%2B`E5Wifh%c30XF|NQCybBbt$Es_B{&AxM!yhc7`308#L$5j+&<($y>Cc9YrHm zfG>yX;25tU95M6G)QE4FAn1dVY67{R7ko&36_;*`UKOi_IawlXTb zNXw%Oy&u--b9ym3%?dh7D;DIiATJ*kxw7xDFnMAScP=?)s$HdVR!O_aR8pKzeM*R( z^?FLO9g6awaEuzUd>N~Vc@^orX?%quu-Y|BOqM+qZ_QvvXBIz0k3M)gGs>o~0GqCj z#6P>ag?v~3^K^Vx{-=IiLcaS=WxeEyajK8SU+4o53m33VwtbzZ^%ea8SR}3mc(9ug zsP6T5oBbp=z4b$cKIpZ-QtQ|!_#SUa@IjLr^;co|V=1u6YsTR|rUtc^$*2?LQB0Rk z7Tx&0RB|1)pk88m-Y8Q(B)2?1ObyW92Ug)d=rts2jH|4tRyZDHnlV2gV%;t|AHF>5 zLK)#jre+$oL5HC~{&PPV`deu-oPe+lDTv7`yW6SBsg>G~?&MY5H-GV?zM8po**T-& ze5FuDpTPnX~%@ba`^yLsbR9m*ewaGG9_OhjV?s#{wX3ceCh;=f8 zXZT_%Mx@knQ|>z4dBV-b-%LKmc3Evl!j|oPJ#?hBW+I1{$a!B-9{ql_a%7k}x@KZ| z+^?R3$gIIDdx>MzAET9VUHx}j!>QQJaMQ#vPixKAxB#*KC96o}R;YFoLS>#iuwFl;%m0UN~JRRlJHbY0$)9>bIcy8v7Nf&+JKE0-F zIinvn1n6r5!ztRJm{x8$`ssUEAU;FSMt}cvvhTlmXMz;sVRfzoUbP zH6<#d!p-q{#wZyG*FgGKaj)JF%niH97P-Puq6mi&1iTK;Bri2p9+;nQxT>xQFEuxk zSeS>-U)9tNm0CIuEG*w$)waDXvkH`0Tqn4$>y;|ANgP<*V!y5*4KK6Hmsr|UyKa~r zDs!m)KTY;sMUaHTBT|sIgYFpCTaGLiaCb6r3@uS?Cka2eABL_xgp4LSED3&MZYg=Gj*ea(7B&ix%2K(c~?T>o1_pfhwAf&xLy?55D; zqo8@`-|o-%N>q3*Cgni?Obx4D$PbS4t+z7hD+%=X=Kz}t%_glETC2oP?m$XyI#$w> z`k`+~LO*^NlZ!-oqeZlxfVlb$n~>)FFcNIz$R&{>=Ig`G(xr<}2RqmT$)gz{KUC>F zA6`m!zcjR}nD3k`7!t`Qc4fcff12xc5Jbp|eW5S*Cfq$SHJPN8Z!e6j`-7Fv`aACC zqB!z{0n;d7H&YFLL?c11?lsM~xidRXWu02f}`z zgwWErg}Y344d|Xm@SIYq^v`swZ=J?`I;DCKC1C538a^ZK2%!EbBQ;<&+$K}9X-+Rg zIOO=$9=E;ti4&t?G*J2?>&@eis7%9n;_yWt$A3@uc`$mH@S?^SNlbNSz!w=tehpt^ zA3;02Tqw{;(I*Z*8s(0y-9I3)7zv+8!E%gdI*$2HpRr^T;8;Pde{#0pcpZm)gI2Ue zCZiHRyW$be5)?*GWG7CR0j9|!Z81c^|G=DL5LGIom?SSmGFD&`H`%&z4xSu;*9FV| zkiI%?`Qd&TSa|oVFYT&EhU35}poaHHh9(6_&>}#K_79oXt%U6pPt1s0fypk=iL0f# z*5mP@$KH5JGs?c72I3y}ZjSir z)R9pQ3-JOOju?#CY3PWc;)R^##Zl!&G2sQk^D^tCR0MxkT%{y3ut#_Fri=1s`@lpL zo4!AJ^x@4u>}h%8sB%`Y0&xgRk(pWP-No{Ka)l-j5mvwfTFC zdfOod1VDp=Lh6D}DGan$gEA@tRUJ^GDTAkGf`6hf7FJhfFVgn@aVHL5H6tRsbySIZJXn=fz7kS1Sd4U(HHWP8! z8?je_e6*wN0*M6RN2%t2i?agv30tBIMIoV>pv^@!2gswEfRT5jkc{kQ4NRti^aOo) zbV<7EmC?RGh0PJvQbm}5U7|2TWOylr3iE&;GvLKDyh+$%`PZyyP-4lUy~@m;7)d;LsOBal*G4qJ?oY992E{xHTRdclWP(*=P)O+~jBs%*i@D?VpBMYfj!aG&Nui(nM&Lw)X zDSHPqc-$sb#3%4m361!H+)&^?MFsICLBem7qIY9WbIBu|84`n&%5#&9#{|_FP`tq) z)~)YPOv$;<$sR&dIVQ=sa$hs*69nqX_YGy$gOYjtzx^~xOot%oR3s@10`&oMx+lQs zTx^{R=~&f>VKGr-MU?n9NsSA85`Ul@k}A*}$dKvNo=cuE3Qqx@fKLF#%LszCL}K^Y z@Mi1N1lxsi+f%tu)znDSC@0{z<^*xAfo7{|PjmkVdv6&R<^Sk!4luwBAT6PYLx?m8 zh=3s7HKdeCHwcJGOE)-lH_{;8-Q5jR(p@S&d-L`8KYPx;&Ytss{r9!|V0WL+%)@zb z-=FLAzAhpId~_sln#DPJrQ{3mS6YXkIriU*XP726zDg&oC;Up7K_ru|?+|hF(7(g@ zZKa990~v9eONdn~MwU|s{qAQ=^~~pqnI>@(W)+!q^GQ#zuwHl?6XK&?I@_h&LKxv} zjGkIU&hU}-EFs2hkEtxdD?H))teS7n5@Be>LMR-z`kG)YS*&aYEx3jZXM0Z4tEq3C zXWzQN>62pQJQa(>(NeOQxBl2?o#?64C?>C^%HgE;fyg-by!wm%x7_DGxhJ{LWY|BD zq=U8j;NCKM{=qry$e6q@1z;ad_s~-?b1SN1YcAe~ZL~!`uk_nQt^By)gi=f&Rw<=y znJhl(ND&BDAl#U&$}osK`+b$+#P8&4m%{rcRDEG1kZrmuY<&a_&5Am;in?8jdJ~KK z>x%~Gi-xa?MjsWA^A%5O6$7TeSz!59U%WV9ymVE(@~C8uuVh`TWYeW&JF#T9zC?|t zaDP|l@Tz3+;rG)59dDKI)8gMRTyy~XSHAQ8603B|Sn)A^X_s0l#%mpb{R%>sg;XG(Rq(rN1G2s*zw+nwl?CFJm4=nsewET$m04YtPp-KYn6%)s zTq=8-YOYn~F;(J)RUTbcx|T8eNfl~8OAQxPU%OWO$5dM^RNGuvUlCW@4rtoHuIY2G zaJ*I}(XMfBsCHVYk*uouf?ccnxXRa6;{;r-#t8`sQ4X@K4I9u5eq0ybP-KGbq90e6 z*ie_ePzP|o^v3}AtB+|fMOCU(`&9Sqlr!&Iwcr{rccEVXSA8i{Lk0HBBFhE|@rJs> z2Ei(R+=T{%?S_|K4V~Dk-YN1$;jr1{%{R54IdyUVH8(-2i4aqjajGMSR8XsdA zqauY-y!0Y3*P-6*D6I7?e~6oq$4x9I_-lJ9H)8l(*8)2YsfN*w+!Kv+*!sD9&=V$3 zq*%+gYs-%{iN%J-32b9ms^(Y9&0womOq{e@rpCF27JPpK6dmQW$8CiCZ6>tPmz7-m zuN&?CpFWmraC0Eox^6pkmL%clB%?4OD?<(Nbgp+G2*7t@-OpqWYM5DQMzVKsQK%Ko zbQBp#qxg4bol5RM&Yjn85^8M0rsyK`L$@>37qjY;P;1v7>>~PB{|u*F{afP?*>1gW zdUjV`W{axh3*8FFZ6p{yWY4;Vak@l&dK{SHt=KO~8+*i!yDj;-TyT2P7P;(ox`dEf zP(Q0)qK6$}jhvx_z2R=Xv~E43$vrU?aK^@#BsWzHD=s)iUs|Yq+~W>OmEL%GKdx~% zU1M*w4qLoXf03M2N;06-?^0pwOSZ}3~~hxcE8N(sjwQvM(@ky z=WJkZ8OD)nyy@rn=^3&j?$R0ZBkoV+A1s&{TH2Q^DH?n=F*u_$jPBBBnmoYm(_`oI za9;<$mE2FGGvYnjw?Z+9934Cr9lC04=J6Tk%z{oVlFxIEqE3y3G!7}0xe>|_PocN| zWE$OAXqO9x89NMNuna$w6*)w2A#HNH5^Me4Ft)oRj@#7BaPXNt8K0qO+zy#J##PL2 zaXxm?z_%(gHujPN*Ujm+vmM=Sf^$y#P>%DsaZn&iO>^q~Q6b+6)8rGYW^wCDJ`PE~ zcWiJ9e@(T=;sgeeh<3F7HjO7wz8H-r!j*rbOyjr_aJx<0ly}&NvB+k(v!rm&U6W6s zP5;c+MQige2^fn8zkj4P0~?gUnifF$@qQ7ypo zV0p}7WE~PqUWnwH|He`<6f=`bG3xzuVoohS**VXLb^#&1Ap4ppX>{8E@mOSa`VW)2 z&)`L>0-ZlPqt5p7`nMLLA}CJJV%x1Hhi(_+6LtEN1{!W>kI?3ynd@mG4Zy<>P>A)w zwNIp$pDg`+x76Cz{g`Bo)Q9_fm~830ccJ!RIz3cL_>aqV+uvc!DfRCTZUv}PYH3mQ zCp#PS<`ppyBhCcgHu87O4Q0@ct(4tDknZz|2(y9%oiK`(#f}U%`DUCjMX|-DO2T=X zJ2>Ux%z5Jv+^Ds?^=7V(wY;-6_EbfS#)U(HSMOQm&zbp&J$_oQ_a7AMRb_II6Z`Wp zulua`C$`pO4NdS8t;>arr%>d!F9;kL^T_IMEH~Cu;5?P18q-};RK$I1Haw(Q%w>$* zD|EbRd$%bF0t>Qlnd@;O5L+(ITP}B)CZn5Qh_~$CY<;>zGX+7Mki%QSxDZp&wg>Gt zLU+q#^s7kLc1SA5o0V-h@Q#nd);mv3Q6gyU@Ky*MGofV1rE|yo4owG+8T4k?B^*=8 zbJw*Ky?}K~2Z4dW-_69`L#$xx2<=sQ?0xXS2x;AGdb8_syw#p6siU`7V}lXM%5{YS z?Q7l+TiSOz-|u|0)9Z2IHoQIGd@zE0fEY$kS2(z;K8$UKe13E2sCu~QaaeM9Fjcbc zbc}YaD|!0n$S!rSr{r)S_ppU>|5`!vc6cYi=IBrJmd7YM=GWs}o5K$_7++eC_m{Q? zDNpRUPVR8QORUFxZ%$oU4=I*UC_fyg*>KS)o;Kk^jyz63Afrz=mv)(#PigU>-%5@+ zjwHB74s`VP$(BzMuss36GeJBs_Q;;|3I@;j53L^OZ;)p?_@}}&V59U8Z%4sAcu-|e zkn*y`#uC~qd{hQcw2fx8XK=8D&#$X#uqp!6p6!o22*QW|+fod)afgbE4}u~`p0iYN`(8U}ugfH=dzK)Fc-0XFmeV?hgY89|4EK)CQjemxNCC|W%$mmBC(l^tCk zabcT&A)Su06#Ahwsm{0}15fGFWf=_>0lIBQ19_rMP;wc;z!9Fm@{ceK+0jE_VCNN7 zoE0%`jYzJxq*jZZ5Y+4O@6XbdU5t$`b?{L@$YWF@01)8sz7;}mOZ#Pw4>+eW!UQoN zjEXs6nHX~tw@*Or5?5+>r4vDD&(Y9aenD$d?v;HvU>PDD2)>>f>aRYc=Ya&g53>Iq z`ZJVZMTOW(gY+;-qv?lWm-Ot)wBixI2U_s^G!-i{BN5S=R22KKmJ^`tGvq>U z1Lr0F)DD2MPg~4-p;q{kPQk5uFWOr+RZjEyiEOewSw|VQ*cc^x&$Z1CxQpADCS{WN zxuULoE)CL3bf;4M+V$eT<@7#{#8H2B_8s$PK97$ z$wVoDugb?|Ms9M6K^^=RmCxDARP`zwcn$zhq|JXIO%y~bJrHJp1#Bhg9`4}hzO1I zI2i;pRbLpm5UIyw(_bEZj&OfL;%pQt%kA9Esyt0L&3SWtp)Pg2vSyTMSq-4S24zis zPJCB#B|($nd-TU$Zxr)Zp?u5!`j+O$Kj;rxkS4EX-ZAdEz6ETsuPjSDNE*5eRqmqn zOQ<9at*RFsuK^MMU4>!5Qx9{3pw(&D56#z``BoJVEP1WFVEJf}7NWOqCru6PqBeH! zzk6-Ej7)Cq2RXma+qJ$tq+ai1_>+Y_B>U>tA@b>$n_b9b+#fdImEznT=MP>Qe(D_y zEVr3ODY^Z;;`2xK)37F6^l`%(34s2R(oP)L1}KyN1PD9cx$IX6;$AI;yiG9Qy$;hf zI~aI{bgQU6y0hREIto0M@|O7GakckH+I`sWNJM0vMtH{K9{mwBsLQT=YISa5pPKuz`t+aK;r{qZeSzPHud81D19s25X^Q-rJ= zVMjk1E3W+OE3OMZ7st9j-j1;djIfZIchVO-X-$-tj=*a1DhNxhw~gYF9fM4^!NVsH z#hCrOr3CD#F+w0+xH1uJ>a>RB<`@xlj%9(mp=$&~7ZN<`@?no@GYNh=N%9kh`aA5d z(b-6KQY*ap>O*T}S?<)EyFVsLdTID1Mp;TqB2qIrTK4H}JhPAlJThrLTLb@6I>)Lj z60Ofj2=woX=KmfcgJR*}kvt_KAt4~ABBf>nh$a~g`%@M{R#sL3YBIjyrD7AJ=aFHT zxX+UDD18uAb9|%oMN(2yU0wYz*978ZdU|?RR#vvQc7i&dLhtUyn*UO2n)w4hO#opk zeM)=(Ir?vq%+x6g&}ixgw|w+THuNjh3u!Tr$pR4Om#}Yd16tpQw!e=WeP440fK0Qv z5rAbH#*8^;Oam;_u>RJj6lqs*1VBxP3Z(NtMAI)UE<8FVGBPqDF%cL!`bOsZN9PB| z{wq`lKuzzQ3V>?{o{_q?p^CN% z0BtsPjWv!;*Yz(Ib!-4o^KYUI7(zA!Aam*-WY*6kOV*K%2ZxoL$d+9IYEA-M$id-> z-r?DSv3Vd`2H?!LnbY>!)6S*4zU8~o>D7Cp`Qx5wcJCwmR`2=`kW)anZ1o;(PHZ8U z_HM_Hk#i?^YXIZi+27th+S)t&d2q9PaJmVEhK|n<&#n$Hk$+2O=NC8EH@E*K>HGi6 zmjKa}gmM|n{2wA@TpRg5S$`vBcG3SMLPkUXZxJ$D*?%Hr>w*veM#!=tyg-DE|C7Z! z125fw8X-%h?f+MV%n=T`kC3?={XY;POUC(6BV_XbAwtIW^72d>xJv&jShG{>E z9ZB=PVbJ()Sdl`S_%4hAW5tu7MRLVN_@Vfmi3%_Jyc&+ybCS=?egR8<*G<&)}Pk3f(oC0#ntm?*o-%d&F{c5$;qcnK;A@6&|8-< ztyTj{>zJ9J-NN&0g#Em38ZBZ!{$Z)bn3mY(*BR4&L* za88V6_?G6K_{=%$&BOOLr_jmGzb4JnZY1MgQTVXfeS|F7GQIxyu4T!~w#&WJ&iei= zhAz4!EBSuzYfIlB*2DjwS%eJteLz1Nj430 zHgRgcfJNr8>bJ7%M!~X&YhFt+YVwDQP29%)1`MVU+x9L>;1P#u>Z-Iop#9NKCz)x{ zi)wspoEP$x*IKr{OWtxErTeLFd+m&IHy?Tks+i9Pxv=Fp3u%^hEDiWt`t3*9W+0Vi zba)4xgSYcm0MYzD_@ULAJEdY+W%=gg2(Iiqhl%jhLWd@u0G8jgMse2nCe8mFBV;94 zIF&PZjtA8PVXqHrj&v^%IXfRT?spY<6$vcK27649cVeYIU6e!XgVDf^$<9p zdxh73wn&QiI)IA*DQdt_ma@m`*5?uK%gwA0O;;xk%RD#x18H|xy)|rid$~e>6w{=r zybfm8C=_}~93GaMX9!Omxir+LaG_h?a8aV7^xIK?VTji8mjX`o030fe7i4QbrbJYX zQf4B!3=gasjaH#bCnDuxrM{fWix0GG+bR#(17Hp*SV&m{p-0u$f#O9}IPdaAp3RpM zGw!dVn`?ApR2K&`RvO@IVrEfWp;}22`;oRmUU>(u;uskvQDlSi4WH~0OPl$UEIVR} zGV6zH118Nsy*+QPPQH5LWWz9}?@gMBK)Gyc(!O2^zS9WAKPJsS8LiXEc)+Cjs;^JM zo4|Wun@9X@1)-b=j2TUAw7#*U5hC>bm2V7*mgI8z zXnLq#xPhFX;&%u_%7$I$iR|*|yIx2AL3&v&ouz?p7k*R1n>>LCnL`#8lAd0~7cgmB z{~RTUIAIWroM)0*KYFmi?#BQU4<>(*FJ&#re`e7Myx>+FuI~7zqZ%Pk8f{?!4 zxz$k``rYM;`1_WADkc6k0yR|gSuu@ZT8$MHIv%lrH&jrGo0sps#Ji~EjzQS8R7p;q z>L4c9xj}oWveW~{07fs=b!0|5A<4re8hDxS0QCqs7KHwU6`MKTNc|)l++H<(I1DZG!Yi|%%kRi&Uya8PSLVDL+EH-5nn=g3%9E7eRZhB^%=Vel$^b0RVPx1O6)fjLhkJ6$d3e@jWfo3(kTO_ZcD_^h}{T9l1bdjWVo zeOLn5rQv?PdTinZGORAg6>nU{{NM;0!}sR)13eJ`{gM$dX(D7v)M=1M7lLm}46K)T ziLnJj2DFLJ*ha86H!Cg&&0oSnXZ2gpKR+D(d{^jp2y`V#>fWTyjHK7}Z_6q2jeYFO zVA?-Jdu!%gT%*^K=n{Z@J~;gJM!Sem!C&TZ?4DQ z3mgu8xGX>bu=8un&6XnaY5{q7G17APX9Rh74fu@7JW+W(!5W?zf5(iq_YpGO3r~D9 zFG3zKVht}6Coi&iuSd0B6tiBG7hW(jZ)zTIS`BYHC-1jYZ$H5?Q@S9m+uots-psW| zi?lv07v4PaK0HpA_+?rc@6iD%&%wI{v-5-r84Sgj}Je>E?twMy2TRQI; zl31mHa;`CJrlPnSx>){@-pO3KEKGAOJmq)z3CUMCBCD8e@KTKeI0O8m>@&Og*TuY7 zU;--(Cq!SySBSZP5E{W0I+@mSXQs#M_UVVK#uXW$IQ7Z9)G@mCsSFZ*te$<9AO(+sya}9>4@h|X z`lW+=2i5aq{^#)cVA_Oe^MnE4gg%voj|ocf9>pHBS19X{s7uiEQf;kENdRi*JBPP- zQso5kf4@v1d+3Pg`N=xrO|l-uzZKe$FG(?;)Iy$|&6V5?O|FI}euH61=z%|x^4Ov$ z1sJJ!OUq1XhJ8)=tjxi~CWH}ljxK}LQ_QtRe_xu&QKi@L?Cbtq>fvQ-qEG6vwD~D- zTBLf~Z>af2LRxTj+Ksf?-DMgoUpiPT9m6FZl9-NFpI-bY6z3`(|4{}ZUk0&O28l}s zSz^Yc`V5Ns49cqv*rQBpzD!!JOgfiL`g+SmL?-imChJuu`@AI6qbx41EI^~llbFR< zpT$3)_2vrDXl4T%O);%(372fCL_niy?q8a%V3Cb-m8~3{sl@k<1s$R8qKu#Ljot5? z&Ld^rt8Ziva}2PQjI?sh5_2r-a}JzxtQd1V@F5ZSP_GqCcVcKlIy4ahjaV_Y30Ct= zhstF@Jxe8{@Ui3wu%eE0jFD)NKt_nF5c z3T{=D26pnvCa7M1F389#;O!~M>t{!hi&Z=-lqE`(!YoYlDXim7ggkTh>7mlI{iFvg zC=SNzz*6igD6HmVzvRL&dxg>b=yf4_u_UZ`5(+<%NhLH>^a&f>) z(kobcRI)!`0^rPJ7tXz1<}Z)FyK#L78-BlH^t?#?e%&v1EAs+*rTB}l6h>V7z_2vL zx3p8a6l*~S_nI;MvNV~vtc0VC*p(0Gnwh*%0hOqXY@uxV5eErVdAe#j-2mU?q;kXl z@<}i|{a$%iMfn28|0yU#TmbVf-Rv}gx{ne*J@LKYb5C>I5 zWw>ue`f(+^ftO3W>UVaf#-3En3Z3?2so3Kx74a$qZ5b8qYO`x+_5pUIr0TMYY8zKY z>&G=wAFIkUs~lwIKPJ`aM86}RVFXD zl$LgG@P7S*NV_4Uu;HU&4GRrcAZBA0b|ufp7u|(Y7bnC#6^(&hRh`RJs}iy=p)|OYRCkQvFS6k*@nIJ@Tn?ssu{M|h7&996@~V2v9`C&@+cPE4 zXeWODMq{u|%gQ(7taB2(I{-CG8%rH3+-+{hDtF@@bVj9ug!+K~gR zT#l6#2<@RnLU|Q$*nVht_F1;3sr7o>_PY4CniciRYI6Gwbhlp7pEO8@?Z4cd_szKB zOWlV(bL)4b?ck(neLWFX)W}D*Posy!ox?wn_p^U$kM0+CU-RNXYtcZ7%7COuo6@3C zuh?MD&;D`c7abH`gGJ4g)L4txTxEqH2{?x`4Tr+57;FdCeFlfT&M==}plv4)Z||eM z0fF7wnGqmp2>Zx6|A^xX+WH{xZu0P(W3)G(m?6hZCykI(=8^MI%!}la#EOyKeKafl z(PqLCH0#l`Moeh&XgnGir)k&%G}c5thW>8Ey%qhn=NNg@*mg1oL`}d=j0pi2UcvM+!IWV~*d(+3B)AFk zCwVdk4J6jVTh8su)WB@^<81&V;LT@_2|Lkeu6jw$MP% z6+_)km;&mVJQLg#9oJ^(xdNCNA0+LeFt`yTou1IyP8D0lNGIfWvx8F5yj!%iTQUsJ zVaHg>LjA^$S>mx*fV)?I$6tA8;{S8o$YvAm7+qKa++mEqHni!4k7hZ6nhS>%6QX7c zL5D@4nd$b0%8=Yq)SFAN!ZBEWZ} zvTfpWS<^kj@wJyWG<2yeIL_4-#PnEso_ztKz*fLEn9j#cfuL3QDhMYYCR7MC&bei2 zzO~}Lg-qY-uJ>{frp7pNpy1HhO2V(T|4F6J0}=w^w1Pl-AYR)eOTEQ9?_X-A5Ib88 zyb?^r3OfHWw@fo*egC>$Rfi((>3Ov> za=!NTdST?&5q7hKe6==$-h+3w_!aZ`Dbk%28GUd)j)(7BdqbmfKW2nJ1WcNvtD=BO zQ{mqe&3|vwB&aJg0(yb8!I40OY%XBnYc%htLx5;*DW(hmjgXD`v&7gdp>fj5Cx(pQ zv<6M?sugMe52E=bu3By)ms&N?($m*?VfsM(p9opuN9F+m)3M=7mA@uUJUX4(pFd)p z&JSZ8OpEndky`Tq7nnzoLGLv6G;+lE6MQQ6P$-POF ziK0Ld=Y`dA3nmp;mk7Qnv7J~r2bWUI19a8i4m@dx6LGTlhWBGeUv^qtykIs7O4oA& zv0FaWXOcdSHz!iGQRf2^bVssFew2?+@)Sp?bG z*m!t&o^uG%@hb9&DzJ*{@hX@D{D)uJK|uS9kem(xf9~6AZ=J*ex8-|}w>k#EuFcfa zPQk!S-aJ^`^nS%A|1nM3_eg0RFAVA_U=PESZqk4U{QtO5KdIioN-qbeq= z_I}-#Qc%x~2 zuV(5GP+J2iP{TYjV+Gl8c-Xjo*V;4Q-Z#-XIM+8aJ2<`wEZT-ASB4f>0SeSMd)l#d zH$Jm6J-;^hV;w+1y{pI{E1Qd}+sixqQ=2zSyVrmbbLHpu`rhI8?%~${+3vyFKEQnb zgA4Qj2R{Ej)BiG&2b?H=9 z%I=GzS1B00_};VTkIdp67QCoM#jh8lS+!3$S6q!&1d*g{i?4e}nJc2+rzKx#j7oM?q~THUSzMk?O?+Oy+S$vsp(1{))A`VB#S220 zx8jY%ZMGzfD?z{NOK2du>PMzPui{VPn78s7--SLi;BmMawf`e8^!XrW1*i8R?A;KW z=N!{{`a#_DX8PeAYrTe{Fz-KxUxOax(}Y1SR98eKxOdj0;M74zc5-ykjiA@MbNaDb zCfkN_x)=$B@wAynlnG`z`J0JW)jOL>w%rU{$qv)zTPaSP`CF-OzjwCMJTZV<9KIwL z+Zlm$1>2dS+`HRZ2noiW>}Yk1op13b1v@#(j=MX#>HdtndD*cRyZL!J1^)`G{l!6* z(-!wQs9>+8@%QfD_f`z1{nAbn%l)!my2AbPLGHc%ictxsgUU&DOP2WasUDN+wx+&= zkJcUoN!e?-TPAe_??MXblAYG1>5^(6YkQtgTOKuCl<%=N9y&%I0bw<_QSU^DwL`iS zm$mOrE_78N+P8xkUMOI+V4rj%)EcGfZVhfy>OYLvN)uA~B0A~1o-lIs(Pi;J%Vdgk zv+wusUOcrdc03*F<;W`H%;YD$E1-J4ih0F#at5#G{NUn zWi~7?Cqi8WK8W8Jl^Hm2+eijU5pVF;N40fZ7yt}YJK9}py;YxKc5?r zTCLPI`zQR6cLdwdOzdXJm6f z;}vbWIv*yr5ICzw4i`3r-<$-{thVUhUGC7xG+%DJp4$IREqaP9JgPXlKK#|O+lR&Bedf*nJfNdv? zC4bt*kr?rokRU5^7znHF1`~Y^%)<6v3B>IlyAP`s@lZhs*}WjoU?`7y#?S-+98@qb z^Y*HvSArWIz(Ga<#5=t*za{T+kWaFKuejD}RQ6aly`*M(4n15yUGAHuRG*A|{QzNX zx*n6M^nlP4R&;Y&;Vp~40p01oceSe8Sa(|k29KiTl2jI0zxEB9yxFnE_FO=X-5Ipd zQjus4%|QjyZV=tGq?N`|7SdLE3;(m^?Pvt*i!vUAoU@c;{!xaX(jzYO|J}gNK;N72 z&?-;tdtR%YEpsN(5Iym-xbFiiPYA_Co>bv>36&7c8lMbR;v`zg`NcX9%>#0kL^@fk z)JV=3F{X411>6u{E;t%LMgO`aBDow&k7@ZFMG-74hoiE-(|>rArk;L3digV|tkTytF{Agmu(c?+MDH1bd$21L{KaEFmcRm~V49N|D}f zAyFbMPywD%WPa8Pi)Ezt`Jra*a?lCO#7AdzKq*CPfZrisc#GroQyWR?U~yAH2;zTZ z#ZN_=%QFSaXL~wX(4ZL(5Np*U!_@H^dabdtv|h;J7~mhM8e39;JLa)Cb+X`G`gkiCj~=Vz(#mAWMfEAAz(h4*vHq_>RpR2lCap(1hSKM$+@qDSD1W$1p~M1^#pXY>=BkD#4YXm2;-3y)-rV87s!`+bAw zP0y!iZgZag+MY&1icid?`aBKO+cbzLae_6rH`kBY!qF}h$H&P$bYqZMI2t9!h=0_C zQpvwB&v*QaL%ZFe!wiMG$dJ#mtedram%nCjN}OJVJoP}B2fGw!EcLh5V}}E)8Ychf zaD*E+myJN&_0z59(YlEzHlOSb&}L%E$%B+5#01kRe<#lQ7MHcntA(0oa37w?` zO)5SFI5_cQ_j(lX4VmSlHS?y=^Nxt%WY+M0UTgh%6KXSx(m94=Bjh6P$G`2P z3if?H>ysa6l8W#9TFQ5~+!tdUMS)%%t^rey_ci;?+utdw1>`g*{SXs2CWa`shA5sN zMS-M}shNa%9=A!LpUJeYQ67lI^F1GJfVoP5O080=5c0vy zKc_&iSur7`WS~D8o9G|g_UeF{a;w`&$#^p#=V|DdQb?4UXet8YIT{FG*9dM6`dJfP zG#d<@IvivAlxukXdKDsk%DCI(fu|wIEQGG9&wxV^Qq2?k`)x=kguEp4OZ|mqj{|Yj zMMw;xmqLtJk46~GfIXpO4EraFrhObAXp9|weUVXXtoGly9X29{GowF#`)CY~kzuL{X5%U|xZOAWww0KV$jjGNm_V`3^11FvEUwczY{w|g2R+eq#uiDcGEYJt zW19cL^t^o9QfEXqo7A&o^uAT3zb<){JY}3WWl}R``cgsCHf6ppWpOTL=`v-7JarAp zo4T%6R4>9y8t@NJipy+ZDcj3g=cQ~qr6DI z{OE#QpMt#j#JrdDd9I`R_AtzpM+KRT1w)bfIW7fxE_uB3#^eMjp0)@`CB8T8!-=H$ zZBVx3m0|H!0S0-Yn^@uFJW1vL0>agT(tdiv7lmPE*^0Zy3Z=!atBZ(hFe0n%lRR`nVBF3%YaP`l^Hh$q6mz{b)?zj2 zgteU+<-SaO9(x8a43y$aYeKL&!V2}B3t^G3>$JHlNeOGY6Y3I^#QS2YQUMjuNkg5DE35+8yJ>rg8hMO5`5xH>SoVS#f{u`c>^_=gP+3!sf`z zn(@76f8v%?SLUfg%bJ14b?p}G%BCL!Eea0JqYKT1kQbLc(V(w zlh|~qRxq3*7zT5j%z3M~EERcC8>d)JU{V;V4s4&e5vC*h(5mriayu@6>-Ao{IBh$$ zy@}Ed#=_hos@nd*8>(>KAwM$J2QO)7Bnd=Pwx{)GE9K~c|41C;?Wi>1{-Y0NHKolmyTRuYch>-BdSYCNU zLMv;ST$iuJI1Ft(HiDX&MKs85{5P_35HHg51q(}BVIT2t*sBMGyzf|ALpkeovbzYL zK6)}araXpo;3=g)3I9we^Mr-Veey)hAwJF^SnbqcJ7!A|npw)U zMas0MCsp9_wC$6b55<@!LepL4(@tS%e4d!3)H5DoKy3`eQJ&ekX_}86)BSeFt{Bq} zj^@L{%nP42PeC(B%mzQ0`RIxE^$BwX%N!2^&2(it?snPkM%_WSwPEOK5qgcquJqy0vNf=YwT?fklw+^6%n#zVt~Pac zRVLblH!FPbRl@dV!lh-~2dg9sOk_(d`R*9SEK8KEs~#zHG`dW5sq-~YRw;3p*HbY0 zj@M{QmT+uQE8S6_rZ2BqV>*_u5#cWIyk3-mEq_YxZ>0kjNtr$BcN0|w&72T8y;ZUoR(O4sU}(KwFxJ~l#SHj?NzDZfsq z;7-I~9fL&Rh>#ph)4s#QH~10wn7=)aE^LmnQ4gFI7B~^;xapgra18KMz|@FgKfJ8N z4q7>6Px9ni`RQ~>C?HD{bkUQ7TN%AqqMTYv`mOJdSa_|beVdT-441b+3jgs zwV(utrtc&nOEBq6pYLx#peKJ6HH{`uxjL7V5@L^DY@B8l@-r`W+_w$g*|mM%~h)>*={40xFos?J){v6QW`p zg?b=(s1Q)U<8wJ=iiX~~)CVOQ{0nbEz-{?Q`N-ds?Lz&_FX}r6laf>I_iKzRXz{}k z13ZkmX7IetkFc-Lees}4qrb6MFjH61iOVrk;eT=}pa`K0ulM^@-??dySaDP+%F?(i zmQVIGp&=s|8K)N!iVK(WRLbd>+Tj}kE1Qn^UrJ-qh&JrpAmK8!*1Dy>B{#IK#@F09>f_5^2 zX8#Zk-&=$}5N;HetB_30x_&)mnsJ8)aR`*XULFs!tE%}2v;U;6=YTi%D&hz9c- zw`?pe%6D(hNtT`Jm2<9s7U_wSrHAzC#rAuiLUsWulRJSWm2Cht;MsWGl!fYLe<|!p$CKqpP`9?Z$m&Mq;l1X!)xkuBJh71mL#hdYeS2VNmp}S(7?4 z|M!)pK}9#;TFgU?YpcpVZI^@aV#-?TR zf03J8NamNQLbuHCN_qYHy#0l(xugo{bcx%W#J)P$#3hosj7 zC@wYQTXI$rfa0RF>i`r746*>xWK?WL8ZD8-2?9%pviuR(~E&#uk z*7a02_J{p5ze?yqCIOkb&Y_yN;fA)s^477+uDP1N<;Kpj!u~^Gdj%Befb*`pp^e6I zKqC43@BFG|`V?SqjfaN-b?fY(=op;q9hvW#oF5sR9sp`|0DGHSX$9t2OTh4IWnvDX zZui40fVwUHv$vW#zMH)-(Cuz)-!H8Io8;c%zj)if4Xkc%@BVw-^#9&p03b~fN+DI6 zF6@^UBydsuUEvObuF_axOKhCyW%9qVb(OI3#T0+$fvQL)8T-tKD8SGF{Z$%6CUo)2k? zPml6X3uW}bur&$7Z?3$ymOYVFZ~H&rn7@55*+pLa)a^tZLT-O~5SQ#*rQ`(jBRj2L z34nD+_Y3BzmbGE1#h;D@QkifW1U=8GH3)gyWJVp#ST2<%&fOhv7$8*s4J+tXKhJtN z*#js|IFcd=0BI7^g!cS$>7!u&n~LCQd?oV@K@E#OV{u*GgpF83ZdJN?(;VlSME%Si zI#F8_UI3&?nEwD1oRhbKXE*9{)4pINZi)C@LGzM7(#>yW2F$OUWrQyAGGs@X6foFc z63lOX_KsaM2dA6N=jVRYVq`3cu_+kO_su~DKQHp=-`y>)UGk;C@oo1^PA@#(&HY}i z^~mab%dpFSY2Rkzcu6lw5?$q>%-(+0Y_Mv|bM_k|6r5DrI8*0E7wkjV#7L(7I)&kU zo3wos*YSpB|AoVp^KPc2<{KAZ3dTe;Z<&gIRA%Yw;N^kJKrozu6Dn;4)gAo_WW<`-St5v)5T?o%7rCKg?oXT(9f>`Lf&| ze66y+J#=b%g>l$?`O|H`9+UNMA-(PQ?Q#FutGkooNWHtC1Cp$Qdm|b)Ewf{aW%m~{ z2EXnvWj%ieQ7^@(3ta7fHQ@N1&uRJlwz-HEd3TrB*+=~D2=B%H-DM0Y^$d#BBL2?-NE13?4b>|SBv{AqZp*wCK`J1j^k zEUOz)g@GS!h{F>L9EmeyP)jIReD>+-qduwE>fwWLOysgjb`ciclIFL@02xCW=Tgd0{KKsI3Qa6??n?@-{f5_j#fkD@rxbAoVox z3n7k{*)xL5XS7X~1FH@{1@qe@pXI)c+E2)mS=|?ZqNh3-0ktDcT_gNbKGpI}3-b#b zVw=kIjqKPb7X0@?Ta0w`x$0`(ibpSc=tsTUEFv-!$jQ)1dTj%g6GSyV3q^?-d{Rtt zhoV1T^^uOYD_D|N*++V9zE};ER`qLFP15wo(QikNeQs1Wy07kFTKqbH*{?U^dG-eC+>vh$y7y8HFr zNB2^09k+dVCqd2MW-L5v+zifd>Znl}BB(j>(lW>ssMM6vX~{(@%Xyx47QxZ|1FOGa z+WYYc4@U$tOj4>>KM)WXWW8PbwvLzX{Px2d%7a<9^81Das%;U8FjIl@X3=MT{CUS} zHYw2@yUbuyN;`?LV)(N_zX7CeWwcHuTWo|{nCfc+#$s}BxFHF(I&EycXOc;%5<<;* z^jG49RGxYdBXY!qdyjEx_bYzbX-9viefk0RcY(I!(T}B4E~Fyg@i~q9WnSZEUb^qT zDl?kEW8=&~lOI)=dy4y!C#wrJJVn;jb<&}dGmq==olM)6C?$tu4ADh}3X-_znJU-5 zc4Ej29-oB5-}T^dG#GwjCI>P zLQo#%TOC^0ZP`acI;thVAKDdx9as{44~9pqBi$8%s}=f9-zgq8CB>~=VdQ$VK=<8m z$&{}vI)FtVH1PfHn&B*6CKzVwH{~{hwKbZF04n+_Pv1~U zW?cB)mNqh4t6SOnCq?<)Hd|!Fu&Kgn(&F6?&sf8#^XO^X?cI0b|0he4dlY)JxuRIy zkm$KRH?Bf6Z>)&pU(S7_7qwy-2i7)j^CJ;XwVx7L5XA47E=Qe9^HJfB<8G@x9G9ag zKJGs0p>_o)to}H^k0UX)x+tHdS8fI#Yds(Gm5dE}ozQ_Dz9z6ODRe>T^7t%^uEj5{ zcYP|bRk}xCg5u{@B>s}^ws(x+p%ts$`QGEmI#wq}vq(uYG3zUAUhiYppgVth&w1-o z!ksK61CdI)TE(RiW*c^czsIrPQd;eR%5NweM_L2y6$fSwv*RVu1HE5Rq+mXv`6> zPTilbYB&Zqk?Z=j-^uo+&to4hhnHkS{)AL!J}mT9G*>?Rcv1{fPTsSW1)ORx>V2y^ z9t-yRCMti*r~ULY!Hx{|g>Zsj)LTEMY(H5uF6v4fa-R>eZzyuT(1^WIc#bF(=KMb@ zKh{X_*WvLZN_e7~@4u?-{jwJJ@`wiC7Of@T&FT}4ZN1k@SAex3%s0-p5O%R(%2+OGtYno$aKf+dh>}!`;sl-?rb6vuQScU6Y zC6YLm0d0BSxHm3wnhoCSiE;MmFkKg2o$I(*!Y@V)TE<#mbk3nHzF!I*zgS*>v7HZl z@K*ohfYy*ke5zyorv@$8hWNx>YU{mti5WpJhJ-kYgk7_Qcf9ez1qts55@2`<5!Z@A zB#AL3T5(Xf_-oBXhQwqo+0^UA2*RYS0nHq(q!7oX{9w((hNOU*r0~6@0QH2*Yt3q{ z7oSYT`p zw#fk{K9VYc!!}P}ZpOeY$5HCIUqyh@p46aQD#2nhpwStyG&XeAqnCVzuq0uqO%JAO zh9uh{Yuwf=?{_cq+KrCpb5NZkvAX^OaC_7zj%WFlxoRP>B(0ozA95{36fpvwE|J@i zG0)f{=C^99qX?z-O`a|3SG0#uiKXeu3i95mekC=}`G7vcAhvmS_`d2CLexnA)Ileun@nv)1ugms~D>z zb&!#_pA^5#Li*;o_#sybrb_WFti;-SaC!E7qmoi;eW zDS;=y-XAO_ERtA(m6OQ6{?!P7uvlRpTk^DsXJTIuSEQ1L|Mip53MPK>UxnpVx0UZW ztKi6vGEO%UcG(Kz^-5k@0rQhGAtnj_p$hW#DzVU4U9QsH$<_SevM1iv3Od|$WDg}4 zt8qkvc=&5hx{Bq<9_CQi=r##RVAbYQel<(3wP>o9`538QWPtBo^U|%>gSXar5kAdW z_W-YU*rINay81~+-RGiLvLC8RI_em>>t|JKA5+yciTZ~O3HTS)VN=x~lQgWL)sw$% zNRSmWSj02Et&d-9sPC!|Bx`h(Z5%#rAYQMB9p@B&;Lmfz3u-EY6E)=~R|d%9McfkB zHwhqR8Zve83T~SsI2uU28(ZHt7pc|{d?;!iYEHzjk_^osVroh9Z6;!Gess~89omwB zM5|fEYH@(J#%?xm{$QW@(6p1xTa1O5&riML)^aGzyTOmQrR$bQ?z{^_@c39)q<=eEG0&(g zCBB>*26tyDer298Ih^(p;}XwO!ILj|T~T6PI29z^!#q6}ux{ffrd${PC7$Q*?FgL? zBld0|)%u&aE!<|^M8(~{UDc>g-74<;O$d>S7Z!yai#!Hl;Z^3fffFCM9C9$c~P^8pR5lfUe<#B2}4>vV^jr;P3|4GoYF zm&y&F+;R804@@)n2d`mV7mu|tk1Sh`&A4OEk&j#24{uqHN2Flp6^~n1p|&iI|70Fs zW1jc`Bt2gJ1RxM)D(Fc&o|@7mt=^=)aId{E`eQE;X$!Xk8wdshb0X!ZM8?6KY#=m4 z)Hm&T_D55~_fu+!$#^A*aRw@D3AdOM8s+jdr3XmI9fadGKwJThr^NJE>b1{+hP%^4;^j- z+gWN53VJyhq=bf9K1&KmClNunKwvm5W2z}Zm^`3jRwH=N$+a`>N-tjUNp(nTNz2cD zD|=6on@Vho1|nDkQ^KbR+NZ_K=j07B`ETZ&C@|D)p&x|N&C4+o1TjfQ=7V)$Qhay^ zr-8wk?c!SM?PqWH*eOOm)W=K6H8Z8(Z-R>t!3youVn`4Q$~ZXmzVB7bq94MxrUn_(TZl{ z=!SonBHdWNJ3K~l8vX93&rQt+g10Y-A&<5&;ULL1Fd+z&L}Xh%V&2m5+h_PUm39=Y z%I~h@UQcJ}OnyS)>rji)ox%)EpV9BqBx{f~={MN6n7^Mx(+thJma$hBn8(3>%V1{^ zI*BqQx^>b{7(E2B^0plE`Ur%jvO%Y?%D5u;{3jh7%ckPeQk(d4RX0J=d-YY7<}X*iSCr`~qtl;Ayv=>3Twk z@6HVs&&3qa4g^k36}L?Uepw1}tFd0ZF&I-9ymYXc>GHTVjJb4ayChCK|2%fa$9nZv z?26IgymoXXD(%W4eJG5T+wa!}VrAdP1FSZtEg%jaD&y5b#RHYoCnX_A#zbp|j{nycERE zm$thO);ny^8+ZqFLh(8isd%sT?jFlvhy?F`@z-ULA?Av~eW&8ec-ejIgMqy=E~{~j z*|uB4%=;@~kMjvqivxM~0ImqeC8yt=6#COuZB3W2(+1&D!R#u>|K}rd>?Wf*T2pxg z+`NnMtwhra$-oqDXdL9@cucZ%+@Gb$J=J{WT!mcinSJ%}f@i#na zTGi&tX-0p$Dogp1T%C~8PF1~gS9M@1(xBZN{ZCiLHe4T!uT%Y@aC)=P<#-yiWIlu|A^oi4a>Z<{;6#2KSGMIF7e`I65J`l%h zy0UaVT}u-@))MY^Vt+7S13((Zx=z$o!77XV{H@Cw&{bW^H+?*u*uJj(YOwm-P8OWhDH8myFjDbZw39Uaxl&YScs_`dh zXXlSjZl6DY=GF2NG7J zz0Wy%SBU&jihSRK1e^vCn$K0o0MfYEBSS+&!y}_2V$-9dWB)k<<{On45K|ERr8qL_ zE8sK%$yE`_712rAh}3^if&D?6%;MOL>V&_sRBB;!MqWvF;h)L8f~vNd%5Q+sgg2i7 zdwJP^k*2t&y98Lu`-3#S)h&bNZIfXg$k_h~q)NI+%Q|L(K&rNVys~?~xoi9%p#ga2 zpCYPt_M~O;ck{1b?OnZHgEPP=UjOKP$JG4r)Z)bK%GBKI*z7u>GE?)L3oBbaYsmTa z?~5CI>)ZQVdxt>z^jBg|){gJ~x$E`6G3I{;CID%K{zaO&-waxRkp><|9|j;zmnRa} zVku}Mt1kdwD8xPJW45#pg=C>FL#1)AA}e}px0EUnYcewh4DTK1{fjgNbYnsMkx!ow za^|W;D>87Kkk(iX6-WRM5?u37?L;A4TRaccPKA0ywIz#n0Mew&*8QB5QWxJ_F8Wpq zAPpMUV*qK^yMpkU^oQ#!0HmP?rezx{w}%oqK49FMtNKgRiG@CvZ*&kD%aAY9AGx7a z@_tq7C)&WfOGc7u2h>hYb-w_l!Fr<5Tz|YmcSmk8+U#=5$CM(QuAt|9_#**5%X*}R z|Ht7Vv*7*sli6WV64^SeCy}t&=`(KtH;InQ_07W&&^2W{XJcVXJ)MFip$)SBH8TsRi>fU@2j0i!;1m(RN))mCmHTA zzU71<7NS9+q%|)*+@!mz{Li6)ZRf=Nq=#ik{6;ItA-1+C_!?!Ml&_uTbW>1}Y3I5p zRGju_{Lbn=NDRIH&Dt(K@j_BjDe`DAyR6~o!Vmg7A~NO@Q@qfk3KBl7;_~4)A4)W{ zZBLj=)h-GTYnO3v56jkf;ty*HW8I!>e)o|r`Ft3C`?K+EmQ1ad=+45sac;ecwe83* z+NSh&)Gf6QjAqHI3fa^?ionr0I_e})wfxaew05*v!DCol(XsRN$8qmb$iYz`;XB9U zfoJvtFZvn!n2VxP98%ch5}ziNjPR^6zyHFeV|z+pVT8#!rbhJKUP%&bnPVd9=Yhkd ztcHA1e2Nm(F+lSJj(z{UE6#DG7Mi)EvhbH>yK3W5kBh}1(s|=i;=z&c1@d{<_O$wp zNSr!FE$+R#&-$diSF1sErB@qaFMnQbA|zR^w_-J{{~%52^-hZOe?yx5uK>~%*ZsWt z@fT^TzX3>7|Go6~CxA4!zuEz$IqH67b9dZNR|X)>%U^e=My1fa&_%q_@VriH8kMV8kLY*CXFOER_{bsm_Ot0lt)SnV6nu zL44Eecpo@2u}wAOTY}i+8Hd-ApL2p9t?i?S1X1AtwUc;l^@!!W)3>Gil-*DHj)UJ0 ze0jh(j`D=Q*Z^3xAk6IVVS#N+^0g=6CVgU4`n0C;7}WEv83>qOTN?2{^~Ge{KzUJp z9Pz1Hy1Bak^@uT);C(v^?r_Fy3Lmz}An;101$^21V)9!gFSkBg#?&o%hNNwJ z&PkP`?VViWU^8KLT3EuqnqO;y`OZauN#dkhK6?`bo!wwxDV$4B_z*{hm2QCW&H~*+ zU|cQ6;+c{rmxkscwRDTCIv1*GQQWOEX=|g8f3J9vS;1wCA?5gmiD3W9PfHX3Mfb-Op;z z=Ieqx@$e6^G|zmX!uhq;|NorxYP@VY3NLg2F1vcOaM^k_Qug_BX!ZBaWg7^$+zV6p zmG^KvHsez^Wlgw2uAK@9m}@?y#usrtty-f}5$ zWNVH1ofjw1bHP|0K-3gRos}2l1VU)q(F z+_O@*`yYmnOy=qtYt!uYVri98;a(ZyCieH)rjl;6uH@)6zdu^N<8bTJ+Sf^D5QHg; zzX&m(T&(MhCS#tadif(ynxgb*VTKPCYbc_w^>XCb=iA%W+9|9DljEFY|o>#;|N86R>5)}kf6fJJ38I1eI!%Epnv6YXxZJi z7yl|b5AI*25vN+Dew@jbve~?lTJ2r^@z6eiwK8gsrLjZ0#33O*8Le%@i!Ny8%oEuU zQz`>t79-9IZ=04hG&^9WY>s7Zk?DtWSV)MqMv8!GnaYC?ec;iT156T8&@szu#KaMA3`Q$AE8Xei< zQoNZ&Vw~pHJ^U`V?n2zBDdT7hym?i08woYS^GNVGY&he7$LNFSdTd*0qrEM9`1?u& z#xa3l&FuBQmP}2J^xS@f$@*!1S=prZf{7q!-@w3n5mOMkiTd5+;Je#cc2F0Ltlc<`4lh{=ag2T&kxtaMPSn>~0$6ii z52VEK5}0uFJI<*&eJ#T%1dO^ZR&2p6Ziv9dPp)*Uz1Dz zf@b#EDm07EG1}u3Pf!mYb9OnMk5tgRULH>%ctS#Kj-5CoeK$%Q3A?C_(FBOT@uD;;zM}9h`&t; zH`fXyNgU=%j4jap;*!`OmzZR(8$6$w41H_U%L#n5o1&G}>6rAKC_Z0HJ8?3scs?op zJjnnrxspVyxeP+kgcWJiZF8Ni#I$Iaw7G#a%j&eFc?}?VGE+~# zV9@ym)mK@AP$1A$K==*#F!Lke9VE;QuGcNC-#CF1QVy(~k%hLSe9_EogYsexW>l?b z?40p6vS$*JW_5m-Kdm7n=Y!XtW)d)F5e~YX(LBps%b@QxD$mYhcFnfQ4>X~o`)B;F z2#=({JJV>6k2@rL*pwf&P!H=VOxF;~;FGgpD$+rhTkxHi7S6_DW-cB zf0ixur-n^yToDNhK~qwC)ph|=sd&0jX569#H?gDuTrvrK993OXDudt4Sn4cZ`l_Pn zdq}BSPs#FrDRC^sGc&Jwq4Xp~&D#|p7{5~jmrmXk{D$dtFO;GE5O1(3nR6}IK`+C; zE&ah)@?cQ{^r3Xeq8y(|jBuz7HMxRI{VV#93fXSs#lAGTucNn$Oy!Bs>L}AWQVFr9IEdu zDhw;2O8jEC3zg!>mB~ld8cc#@KdOx;YJ|0G-@DbCVbSy_R&#n+>V>8mxCy>>tCC-@ z)hDYXepYMH0W}V-o3E-Q?x-b>;vyEQO|DG;TqNMCQ|AZ#6PR3&7F*-<13v{(gTNAu z8my9~smHvky|HiL;B4@BtD8U9@aEF2bLFjZZ44vSNYts!al@D0ZonojE*#_)ztV{g zC9LKb+Mt2;ht$VZ6^}4BFIU&I+|~w$rsWwmXUOuE@e{S&Hq-buv&gnca5kiXf&(|3 z=Wcn)kYr6({7I2NT2`C*vlgogdl(PgT2Z@e7u_<`KeYY~%{6)3B6?goD${yiB=|*# zprWbyY_YAls!2?_VY;EsORRm>w@s*``jn#`yP4O^t^K94O~um={ANB3Yy#Q1j+};$ zt<9PzclB7zomr1vZltuxvgq-XnOZK zBi$h`&3)bou&024)l#qjUGFEae$~wWPtARSln?~@KnKTww{E|)*MNNHKuB?){~Gu+ z_FxKak?5oTZ%h1gY@@)Vcl^@G^ufUTF#qPk&^&Yhk-*Td z<*;8n_{Y-l;oWG=9k^PTV8wk%(RS=gZggxI?862e0mDEo;lGv}&te`qwH*3%G=OEr zk8?QMmV$XNM}TC8x(ZJa%JV-u9JkaR#0wu>BcH6{n7m;gOS~KNDF-vQOfn-=M-+sI zYYs;I*1#O{Q`E~tEzA%K!D;7V48iAk>Q;7}i-yx@M*U{7xBr>3-KeZ@{Jbyp_Z5h12O!uBo4gm@( znY#{Kkps=_9xQksExC|mPzuj@R*;!}=Qc+x3ZBd4pI3ip`&zhKzB)?Yly)uG!KD8g z|7HpZLm2g8`P?I6)Mr3Zq=e=wNNAtY?+aQSU&fFWCZ0WnYJQg%!*tL#MOXc1B3m1y zWrSgRCWa6;rV~lc25ri6ZuXxo7viJfL@da8EnvZCRgV{<4QEYCP*5p1t^{Ek2*

zu9R_UZD(}5xecy)NCtwr;lx@9fok}8$LQ6L_ULx~#`e3k9is?7DCpbw)Rj=dQF$^s)}V>VjGd4)R0(saPU~~odQ3yMJ>WX3 zAtgcl(Qezrz1Wq#G=;sdU10Fq&Oyl>0oy1pC8{YK;add8>(T);IBJbNaax*_cLbBK z{;o!xQ~Jt}jMn9sk2eXAQ2DGi*TOenC~R5`@`>Pn6ZZmPjDs`|XT%XG?uY^342-hU ze!UD(UoKw6|ql;MYg9av7+=Z{xw*Y*;vo zDjOk%b>CuZKN*6UT7N@Sl9RsGk?AwJ^uV(Bi9s4WK19Lq+7benPhhp;7Dd2~qFchR8vuvD+Mu+sM^XMI{Jy zf}s1?O^7?DPvl)%_TATC=V?L&6UecfmB>C9wwu{D-nq8xRL|RG*841>-?>QeT-&8f z`F+=u`yS7}^0D9Po8X@YzvXN(Paga^=S847uqNUgO~Cl9+i&fE9KT~wFEyT@+?Gus zPZjv6GPNU5Yl&+j9;Bp_n;wl@5v(=6tDN)Skmky7N4{7QqP{VIYN#abOs+zsGy4Z= zW=etayXVqLA1fBHy9u+ul?l_Vlibe!C(;}ZDFqX_TR@Ih(!{WE-zeIEj2j)+VPk?6&mX>oqDsh_;2lWn{?W~ zmKKO_s=s{W2q2BAL+ka+qunV<8#;rPJC`$(;4;(IR_^|vWhP~cf05=|;QT{41Ox;` zB#&{4{#6{}XB=cqLe$jM^z`)P&xN0ID>8~22uZ(T6f1Du%WOmafK@fZ#a0xVZ3YdkY#xioXl`$8Y35{290d*6q~I0<5d__gbX^=L(oDTj{hAjb4! zCjO*0$*bl`(;t&Z-sk+X$XEwB=R^Ll_r*x7f+LI4zm`+^Z*Ak{<>eO;6c-owH?_$D z6vscN0Pq_CZxE@Kz_Fv?KY2}FVrF4nW_5gaJ#go2PA0!|(Q_l~NX2EyC_RUDwUscrvr>F5vP zbj?@yuQqi}Gz?9*PRti|um9zo-?c+q6+?UV;|Eo<$U0!=Zsw$Z=Bo9t>vaA>o%x>G z<>9GiVB-!Doz7(>Fl{$Ew+Tcx^Q*f<8^8ZKYBaNpoZm+RyLNwcXZK+5$FJ>wJDYQ0 z*Y5P};`sa)IArv{JDdOLY>*Eb|LJVt)H45eHXIg9|Jm6{SN=0tr<-UOG!)PLADs=4 z{r=KG)mMOU#7ecfvVA6C903@5gVhC7UzM_DQe|oi)q}(&2qhS00G0jQ+590KlfXh4 z;eNVC^*@9IbT-NwnWQ&FW&aY+oaHk@|NkT$n>SbdE^I{2AN9pA%zP9LyOYJ3UP%<9 z=K1EU0)*38^T9h;u`Nx$srFD6ivF`bno)gOEz#{C!rAPPVFC!J!G4qWP5>CJb3Ny0 zEdH=Ms#m}J3-&e{*(%@Kd_A`_RaDpF*0P`a)vIk+p{@1)=ftlctE*)ENaUC|P!OO+ zokUvxq{+|lh5++$K8I8U@wOc(X6yb-+kxu=qt|`wfrB{2+TKiNCu_kwaVkcP^tDp@ zHacNcx)w%IjX+$=o&0Ru7s8dBkuB&i&=5i)^@+lT#nCy@EZhUy(XxdbTd|n_@q^J8 z74(@}Ed?qtgF-mNj)x{AFKs|!Y{Ot8IVs6JgIKsIlqMTnVmlSJhu1Xq!|y!0RIzIe z4MxwCft}20LQ?vyTZTs3Y-9s8(I&AUfxu3@qo&s`yi?uFO>~mc_?rIPcTXtGZoeQm zFMzQ?G^Y~jYEfw017j>K+kwq0y&zZj&MoThDJpB92xes9%yYmD6<|px2$S> z!!*N~du1^l-}%1id7Z=CA}jQ@ESjHn9l$~9vTep6&zttNnSQAjC1iP*ktRI+rFFjI zrq+53`@q_I13M^F2K`uI?Lax@KWalCV`5hodz;xIL}=zEVenqv{bMiLOUs{(MAYP! z<}^JBPb?DI~u{TOGAdfB+t)c*VE z*AGgzbd@+t%BHwY!>6M2cKK^`b=|@pb>9|AoGa-i>siekr0bP^lm76$POilydTR{7 z(8xLc6CRRLrpey%A#Avec78zr-M7MTYr$iO{~r?$>)bOop1*{X^T^<%20%DHMLl11 z=IvR3Up1K4%wX&JD*}Ym^lJLeYnt58w`boJZyF_0tO3G_jChXG+UfQCMzS3hRf13p zB$h-35DwoF(AfZlBP9Z%-NGQ2f?!x1w&S{%(_zUOqDumVlceMWW$3}>F88L0-SA}# zqmmcRZ^!>LSm#b@AahJpvvm|m6AN@UiG9L&sK8)diebyeM%OdG32(8mrzatrU3A*) z!BK`Cgmpop46aemYFk;v9}{}m^^Zf%z>m>x;Si3-C_fYTcMqqeB-vOBUdqR2KPDmW z6Z~Bs;WeGgNa>BiDV+7u8@OL2Ig3dI9Fq2+)ZN3b?C+<+q(;dyC?|IzAQJ!Jh(0mt z#;8@Yt?9=Htn=0GeB<@?%fdAb0`3<KJ8Y{gc=+ATDzVm7wDps256z+XNW{+;Y-=bcn3%a zRmx1btJ{F1{8@8@dFGl`qA5Qj16BO!-}yua}dZw!!iDA+=HPKvlVijFl8itq-ty~2~h$7`(i*Etlj-`$z`+D}< z6R)}}A3UQd4)QV4WIO99`EW1!?g^G^&nQkN8BVN;L~KsDk4^4_25Nkfrg@k10NkJ5 zI_7QoP`;c2YFGP13sc#}1?0j-ZT(1zwe!&8%FRVxJ5H%>pzP8H>1BPte5qah(9#ay zWy5%Qsl!*<<$dkT#<`JFr@Eo#pRSipYdB?}`eav5k}jKf<;z^Z4Xs@K&x9klhDvtT zPKyV@?q?$dOFkpCONg|8{O}pEWnae=l764{;C1)cS3F;fkNo+Y@qF%lJ8GyZ@?1~f zZf$t|{_v`z<6iA)Bz0Ey$d3k^~sK60Dqg zOAvxLDh?nmnwZpGYN$U;?{y6^x8;c#29)~ zT=TUhG2P}$-}hHAOmrD|=45HvIf*v=2}Z>3)l6PUF**qct{C%EIhKn^QC9fcB;PLW zD%3T88~N$fbh~^MQP=!kZc`Iv!f`Q~_yJ-AcS$pj?J)La&^;n%g&l(dhG3VadV;FIQJ_@c^=C0CM zt$zQw{0jlWAE!IA?<;VfN(_u_O%$6Jz5$(0)BXRMaGVEojXDsp=Czt^bTaJUM?EWY zHr3_+vcDT&dPz2K(J7{Ms-{Wh>bh^Dh_A7nqu{4DHt(XBg-DaX=*_mlfBS?lSUMrN zudFv);z``i0=~KQyZFk(=Q%|oJD-PrXw`(vZ2f&EKVSBLN9gYgyKmANNTTjDpN2-( zXJ?~uGV+)XsnRJNd@u-DR+K_s47_@$=Jon6ACz|eD9h(;$o3v)F4QO?&$2dw^ncNe zoKWu=kfa@OmYMV<%#c{r5JcH!0-ITjO-Mx&NTZwaVf9NR#6K_Md*euXKg)aOXDo%h zVpD$H4N5uc#LO0vK`%bt|7ghH$NVkq9ic#~x`)_V_yE1`0=?g}HxWBQZ+8ZIKYfJ&mpL_($-70d_1JCNBb- zXn+;`QRxf;GejFqA1J_u&UAQK+#k#(ewi$A3BMc5~6Rp2z>gP zeW}A)8uSX@#9Sl&9eB(QN;E@?>SKO#5%92u@)!mS&+GN_gmJpWesc_eJrKK;t4z@k z{|Slvt_~26K0r8|0O2&~W*Ax-xESd3epylf@_se7RG?ntFm=Ucz!u!iT+tF7(9c>x9qd32_a2 zz_)c)E{Wj-iQj4xaqto|q;;~il4gL;hF7mJSiY!0H@Pyx?K-KIFqxD+xq3jSHZggj zCOM%yxpzDHkvBj%I-LV}-C8Nhjwyo-dKJ=1BLg~s-!yThPV;J(xTN;Pr7i@g8Zjg! z%%|oe)#H{J(u^h2(#%tLNYu9*(pqNHerl!ek)(H{r;|o8oN1|qC8poar_*Gn)$OGZ z#igKX3xksIfGb9WSNPDvj9dGRwgv;#3KZIUnj(BCsaGH{IeN_vCs;5poFXGG%zVaY z6gH8uPecBskfw+_i$pu?JrDazFJ3*n{=Nf@36?Fxlf}mum^*F2A)0yIk(EzP4v3Bv zDFK`><*{=17U2_o7*vce`|GwMgmz^8F^QIv?v&(q5LnkoTo_?nn}5s-5DUF zCnjb_c~dlUIRU18{;z$q2)sSl)C0*0v)twa6?rwCNFP7&{%TqfR6iS(|1RhSZ^UC{ zbuROI4lbVQs$pOe3svE|lM^z^*HlP&l-mRPF1{gS49m_1dt;8@-`=H1c+o z{``Uu_+b-#C0&li1C7Psw__`13de)O^A>V(I>ZL|Gk9}L(k)6yLQ0znO&j)0X&eg| z3*m>1WxZl0(ArYy$FeI@slI*q!A)7cdf9iG^4gk`P4N1K zGW=wLn?X2X6C5qMqCT#WvPjCiu$;O`fUGE<8l?==tBPTSY=GU53#);TbVr-jr! z%&etstedQ=HAu#@BcoMhs&C({6EA|>Ez*QAN%*_rMUpivy!+~rjQ8nA^yVzb!y<4M z7)tvQXwOG$7*$_4SpBG@LBl*hG^8*g+oJW@p-Jn5OsF}4Yhl5#wmDMW#f6qn{Mn6?)OQ~H*Nbm!u?paP?Q!3 zc7t~CbBiuM{YkO=#TpT&8XVJvRw@%b%Z6%>X85||3OjijAuZ{!0O3$;#sZDPrj-hJ zrx}51YXw8k1VhkJCwg~BI*h68yt6l|gL8>5tf-KZyi-uF^F>E^XHyOa=Uy zWUCd)BM0C1+Fu%aP^*n6noawxrhsHK^|?QXF00PJr&JP5jMCkCz;P-MsLym&YTHM&S4S50?i? zt?;ltCf0Q!vgH%4QxozaOd>1jQ@xRZaWL)SkOJj|64G!CYh?0y_)y3Zn0=X_!(+Us zd6N10xbpZ^Gsl#W)hP7&G*#+wXvXC05`G1?nfp7iE0Cw84nLuospFWDvKm!58mA1O zG7cXm9GR)#oKdqHwK1F`6qz*%A9@x(t0zBWa6haB8h?rNErN2AU;dk8$?PKewA;ue z5PNDJLawprYVA=#M{@{@c|d3cyk-KG(9OK2BFZ7)k-6$kaD)d+*7F4-r3E53R1&Y5 zFeP*VUA`cI3b7Y4g)HLVDftXTf2)TLT^aO88ajy&FF%g)*T!tFi!V}3?{YCff`2l3u|Rdl(QEX7=plaSwZnbkKP1_IG(JA) ze09(m!G|Rb!de5t6?Q%R*9J>+SCmCi`1!31}cXI2c5^_v+^yP>e~fjS_yuP!~R=P(Zf=O>wh-cU+PF z#InsYPx!=f^YJ<9d z(#o&axC++L(@Y4Eg!GuNHnojbDt(VBkYH&q5SlP}&}xQA@C2j?!O6g33g8Fr2S)d^Uxd%3enMWikjY3vt)$jQ?3W%=o)Q{Pz_?VvH}k?BbIl)b+_lYU*`i)%B46So+vEd)Aw;VmFE)bRUE3u(8WRp_`ls z=u~Z2e!n0gLbrKcH;U!A58qx#C_%tuw=H8gu}|>6cwP%w-SsKn*m~`ir{78(-i@(d zD`$MuPruDX+T3S%-6$X3bUe8&_;sJ&byMqkW8yKhgS@YKa5wnmwr=%zIvRSh!EboQ zUBLL=nE|r+0o;cC{?GlQ4$m(HEXMgtcm#g`!~LTFBpljwVHbdKM(9I0xwp&*CXy5W zy~j8d+ih^# zpxp%Jk$BOY61{GKaNaM?9dCAf&|IREUllX>`s1kjFU_C+bHC_bxm>FwnK%CZzxRt| zQ(|@bStX`T)n!xv>1_O|OYiDp#YX}H|8_R^bxpa7@z#q@A2;J4&?;j6xnH#2<6PVN zsHtG8p`q;Y>dL*_)$x29U66i@-SwaQMXRfZ*9+wwL$9W1WqX8x`$e`LU-RvcL<&JE za_yDB2juH&h=IX6Tz&^R(E)hjc<1fh>Cqp;QLZ?RxW&rcLPh<*ZfyXl0h9&@cpSvX zCm|srpkyVWVk2P`qT*J3`cjEr#DG=KhDFZyAC}>K)VF?T|J93bBP5IM$xBD$+zuo zWSXN_n7vQ3Q$U7YM43xqrh90P3!=y^v(!DiLL*{KGjdEXVfBBp_f|n|Fz~)D1P#TC z7k7u!mg4T-;I75pt+>0pyIWh_-QC?Cio4~c-?#U@`<&TxX3osLZzq$d@WA9HGs*h@ z)-udLH!KH3U<+hBV^ssT`^WnS5@obtBf-yL<0t!a%tzO`2n*b>_D?`o#2 ztgg4Bez3Z+zoL1#x?>u$TWxIV{jX)A@*W6pnP~1BhftT_0~^gflZC@~`D1SoyIK9n zUgN~+U)b_bQ>c0N>R-~**)s@P&_L8?Lla97wb|J8Dr7+ena^~sfv5gT&2|>n4;R;V zRyX%oc8=E%Pp0?53rFC^BQV5nw!MG4cX)Pma<+GTb^KRt_7}NaUfuqST%KS4Z%XKY zKdkw0{tDUJF#N~X2K;uU_V3ol>EEqQ0Kyk@8PlKNdqRnY`Fcx!?g~VaE0!ULUXlp; zF++5~p|<;@iP(bMr>6ga8i)|h-N8g8Q!E-oJM8n3L@`z>bD&gWp;Dgm@BP-{|IOCs zo}tJ)74@gS1Fa&pjL-Qz(f_iw`2a&68v~m&2-(`K{}rN5nh z=ua&QDGOn#s9_)r&)#U_CeS^6L$G2Mhesq%dQhW6!!g(jW30#14`c49-3enu3CI*yG24xmpaxQgNc}AfeTzceOHfi-$`2g_!tO+9Ijc`6=>*a3 z3-GMd<{Jb4nC?N!Lh4kIp)1`1mBP5$L7Ex{dkiJGgkwMZ%heH0PQbXSad`S|$$n-8 zo0JiP1qXd;oRge6U91~wgGqLvvw3b#R#5YHE_GxPEik#L%skq*>e#%nstlY~Y6~OV z-A%z0R#q;U4C)plZ#tv56y$Nf6s^Irr=Fy;p?rVxI}#Ndu{Ie1kNDn4-r}gDOW7Vs zovKB?N!4@wWYxHn#9h(2l_=w)yF+`Lr5h=Dq^1k&fZ(EERPM#Ljj-Acx1S`K@u0I~t#1IaII?qqA7;4d z^9Wia@)z4L4KMbiKlik*M_`}oevP|6QnQY+eF?srHhC0v7`Y$YceJJuSzDPcQLc2f zR1q{yFec&b!Gxjii_8EPb;ID2+o^2Al;rX+6JLiiZz|xSR-We1lW629j#Q)fM5~I zL52wrO5fQa;2qfXTif+3nXlyCjCl8NOCynw?R~ui{8%jm&&C}U>`CAr>;XxSPMEj>KgjCFPAo&e8aLu0HEc-lkjk-q z8D&eDs`Ege)A?{2?SouEiXb^C^!7eFM26BAO7Y_p-W8-Qv`dODIV5#Q!xD(+N69`k zB%yH?pX2dO?}^k;F6}BI8o7{O^)W*}2_vzFl?qZ8l0JY6O87atM{NNq3l$+JHzOC3 zc}k8N;9sW<$`pN09+D}->H>~M6tQl>q?jOGr!C%WvNjCKrYO$G+O&5TgpDIw<|nJR}0pr4N~W6ZDW|$4ce4W+*=9&`Zc% zP7z26D1n}+(5X0Nf%Nl2emscMM%(pehe$LO+{tp|5JAk>Lto9E|=)`i8VADu=(Pq#kpXQ7-3 z*OSez`T(*Els#oZt4% zq_xz;8lr8T4N1#2O~m1qszjEF&1sc(Oj*_O+LkrQ++`okoQ0fGEVMroEKa`-|1y?h zMlpJ>*;pPk@#Qi1{^TsN;moFEO>ripR=Jhijh!*B#PRH-sh($7D3^1HD|db_Zey zw}$jRxni{GKB4ODYC_CERaT(U%G=T(Z46Wo&5HwacfZnKPfh=OP-7$gt|I2XeFX>e zM|Q!+0dYzvg5!nVef}0q=tD2=I+CAF>k2m7V~=$EpM>a_y@f2dZ`SLl(F-pJGsNyA z(OK8w2)jpX%y4WKS!aN_r<0AdWZ~8=6wj%L(|c`$nS!9c7S(5bd0{{ig7+ppKi^V= zE9YMJ8rQGBq|{iWEqOIhZCZ zNG)pC2M>`+E7>=0n}mf;ac;-y6yvXYD>mm7VTxbeHtxS=A(|Ny3P@Q9@iWNYeA6D0 zItHD35?7l>n6uFzJn4@vCL=iL&qwQ=N*ch!;l)@Rz@`t73lRr#U@9DXrq0_L?uux* z+V;-|N=X2*V+gPXfNG{fsiZ-Mra>=-K_&8##E_ZSC)n=~P}nT6iYY=4YQZik!FIL5 z#Z$p{w804iuw>`}kuboS+vJqb8D45}HJ->J=OM zi{1IPFytGo(Dr?34y=&4i&s^n>9;-6GhEpl7v~3dIF^*~q-pPFQ<^ImAfSZuD2d^5 zA-tc1rqwmV8sKxC4EyY7eUGd5<2GVgEmAoSh->ISkLPdh#2mQkUnFM1GS9!F7A3i@ zeqbCWx9xi<5h)vIu}!YoR7ZHM7A>qm+}NkFY#KevCh)+anO@>BJ_ikq)$$4vf>DoA zu#K@zh#~nE-hyvl|k73r2NjCFI zww%e3p^dX!vTJHG#D?avl==iyoO?>1kxj62L@1$}G zG)yp?HA(1Ae5TBix$^9A^6=c3**Pa~d~Nq4a)%QnRs$d!d?po<^Cm$`iKwav{Nf zzW)0ngJwNL_aX^+X|A#&UL+i|<03YsVk`P$9h_okt|CYCJmR!st)OBr4I>{UoIt%I zUr1R9i6AJgL=jwH65(zX^;DvaQyRDYEkdv~(OgE69y-efP2T~T2q5w9Rs#96! zrp(mi5z{poTi3#z1uAB?=P3RPo!TL3F& zAZXW=qN(6F(vt(J^Db+1IztP0e{)d_)^$=# zeT!^3w@nfQcI!$@8Ef+~eoOC&R=8%9>ZjJBXUW?1y2|nv-dOpG5t;U|)>#Y8xXspu zA3~hqmAdJZHtDIh?dP^o*p{vltfG~+&tdH@SZ%=cYTd2&i*lI`>2_iL_76WgXcL<8 zS1^~Qv2+gGp8=h3(jt#5tq2G0zKNavj;$w}&7PVjqzu1b2`Z<#ekv1qQ)71m-?esg zV*>7(5E;Lpg>_ju34LAZnt#Bd@xaDFZchBst}{>Z>7*NxqngX|SFe7}JD%=4ZYzF( z3EE0^KN2Q>YZtFa#P+8i)vgW*vuCq35=X9*lKBn2(o5|?DmdB>e_HGJsb8#>kxaAi z_jI?`DLoouHziNk%5!@kj0qn%lSQkS@Q(p(ZoE&Y*p1R%FpV`7U#xfgyA`De-A}!@ zz|eiC($;4W6rM7AjChE?Apftaz*WVevnCnkiVgsemCIHwx`c_KE4~QcP+kHqwcfBK zqEW|6E0$D0hHzwwrLNb{;S#&RZ;b&>xg)ACO$u_t3n?lIwhkE^S(U?(>0G1#L=I2sV%Is40d&L*aa|lk1cW#@j&~pr z@YyvYQjH5LjKs+Rg>6HGW5(!uL!Jo%uY@t*_D5lhYkIXt;qk+=4uvvJ6U~fzo>qPW ztuSG>Yu%E7A*9R?GP3bLi0EU65j+zK7fij#)_5pgL%VHQR^uX;6Va{R^h^*?$%|D% zfW?IJ1v?T%wOssVOa{x!vP!g{7Ud_ur|2QqG;nH~muXf=VMbh5xRqdbcz#xnXi#2O zQf6cp-E~5}Ql?3Ij*Dn)m^wn2SK42C?4zu;vFChF?QbfketPWT&*t4NaC6p7!tS6_ zj>!eD*9D(Q7)?EnFUpHSkqd5_Y`$%aUSlx!G4?@3OJtdgdcBJgV=#75OL3ly37KL^ zZHwG7@G?_~>0?Woo?_WVi=4LbGO-8++RKA(%f<=IzHM-BwkwU9E6snFYk0$cX)o3O zS>V+}koH}Pm|TH84u#MEd$S1Iha<;kmXXUe;2)*2vFVW^lxlR1>ab8p|C@AP_ z6lkc)UAebiC=e6_%P#EOGL6^nW7n=!77Q&Ew9eTcOw6v%IP|9)EL8ynuB?>;&pkC} z5Jr7X{;jx~_2n zBk~E+4TK;Fg7fxT@p)&3so*s6U=0TP1-=N&WWj{+Z6K0DvB$tfp22`>ummrTtNGx~ zvfxvBaR?B7Kk?-;LabZ!R-f!J_`6OX#Y6zMP(XoW&8$PHP3Q$7d|3XZM{!vQj+3ws0-N@oFoyEO*rc$DgCRmJK_aHRzLIA+0A>Xr4oU&R!MHA* zKUz4^mwZYvoH@`?pz{#aJ;-1Ovj$7K=891lPIq(DeiOz5`~}$fGX5oTyvQR9t{IwS z@|q8PEpUGAtp}u;WHYn{en!8M+PD_hy=k($`8+8MZwtk)2L&ODw(WbmXL}z=p#=o6 zm?o|gMJ@FG0PQ94pbrEmZmMN^wfEp_XQ7oKUHi1QU zwQV*5Qal_1{pA$SDd9H{ymM8S>!)J7%UgS4wi=jgJ}Ax@z&p_6HPf!}dsv5@$G0qm z%<2_W9~fETYn#ULvll4poNMUeCoF@r^C(>8cc*{A)4Sq&-=BnUA18Tkk3JCZoU=TGsk5Y1#` zopj|G0LsKODv$X+n5hF*O zv$o?H)^uf&w%Uqd{3As39cJN!6<-mmi{#T9M_BZcG&()~l+1;1PV%~ROZ$MxXr<0i>7>7kb)2AUq%AX<(bvFt! zbsDqZnmwRCDtrzfbyQN2{`xgvwu7}4;nUZ+1PO+3iB2jSD6)w&MD8iTS+eWHauq#) zY?TqscdVttg6AW`9s21`cS~3{xA6$fdXBfsLb-F!n%2+>cO&BQZPC-#BVX^eP6-uV zw4JElg)zGBIN@qT&;7dBk-C~=r^}qMn zbykPR82C8Wpf5#ioNN#yjMG#aE?q_W-TT_Ai_bmGFkp#|-d(wvUZU-?v zNTK^d_^6FWSrGfup|`1A>V~(v7oJ&3zE?d4s3?KDtR#^)$=#yL?CYaJc`Bs$P&LA) zDU>mzqIpu*EB9gh_fFCewFJfb$9<=R`5)&u^LNkZwe9r{XOhhJ%SP>(sveSMg;y@Q zEodE-r2jxR;J<4qF-Udj=RegU2xNnQhmMR*f{aayLGlrklm(ZbAMfu|fSC0g6~8W} zfF8Z%-{I3|Wp5q@$G?*&HFrr>TM2DXkiM6OzP-Mw8=G!4hi){dUNoP1HorxVtey{q zut|Bx{_CrQWQHJ+O~|oY#HmKyt3%SO0|MM^+`_&)L9BIgkkXK~SE_?skc&sCn`fA` zPlu;pq+>vqcR=iaE}-&cLnc6B6DkQCnpx+%x#wC%V4V`MZo`va?m5I=2WbpJ;G1{z zn{QBTU|5n*RDoYiQE*~KXi|AZY9(ajl$2fs5!68vLXf7&Uo~BRZCc@9&X!kLl3Vl> zQVuGr>BwyE`PWF7*VYdiGF3GWR5lJmq;$U^Y^`H7WEz|?^j63d!L7eyS?r7Qih92?ZrRy_T~nG&aC z?bB4V<6O`lELbw|*cbwjHzl62AY15j(m?Tui6b=n0 z;EXici$-lvP`_ⅆ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 J*Nts){{e<`GBW@G literal 0 HcmV?d00001 From 9d790252ffca0c9c51b29e3402b41245ebfcae4a Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 28 Sep 2021 11:14:43 +0800 Subject: [PATCH 377/763] [fix]: fix deviceGrp list --- .../iot/web/device/service/DeviceGroupService.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java index 655ab279..e2b917c8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java @@ -22,6 +22,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -89,7 +90,17 @@ public List deviceGroupList(DeviceGroupParam devGroupParam) { */ public List getDevGroupIds() { Long curUserGrpId = LoginContextHolder.getContext().getUser().getUserGroupId(); - return new QSysUserGrpDevGrp().select(QSysUserGrpDevGrp.alias().deviceGroupId).userGroupId.eq(curUserGrpId).findSingleAttributeList(); + + List devGroupIds = new ArrayList<>(); + if (null != curUserGrpId) { + devGroupIds = new QSysUserGrpDevGrp().select(QSysUserGrpDevGrp.alias().deviceGroupId).userGroupId.eq(curUserGrpId).findSingleAttributeList(); + } + + if (ToolUtil.isEmpty(devGroupIds) && null != curUserGrpId) { + QDeviceGroup qDeviceGroup = new QDeviceGroup().select(QDeviceGroup.alias().deviceGroupId); + devGroupIds = qDeviceGroup.findSingleAttributeList(); + } + return devGroupIds; } /** From fb86b10de355d4c4a330230be1e9e0c01562c1a1 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 11:16:03 +0800 Subject: [PATCH 378/763] [doc]: update readme.md --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index aa57d803..962157a1 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,20 @@ The following screenshots give a close insight into Zeus IoT. --- ## Installation +The Zeus IoT production environment can only be installed on a Linux system, either Centos7 or Ubuntu 18.04. In the development and test environment: The IoT Server service can be developed and debugged in the Windows environment. + +### Quick Start +- Centos7/Redhat7 + + ```shell + curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/centos/install.sh | bash + ``` + +- Ubuntu 18.04 + + ```shell + curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/ubuntu/install.sh | bash + ``` ## Demo Environment From 3ffcd290790d17555786ee0aac1796f54e273c05 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 11:37:43 +0800 Subject: [PATCH 379/763] [doc]: update readme.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 962157a1..f790cb1f 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,9 @@ The Zeus IoT production environment can only be installed on a Linux system, eit ```shell curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/ubuntu/install.sh | bash ``` +After Zeus IoT is successfully installed, you can use http://IP:9090 to access the ZeusIoT Console with the default account and password (Admin/zabbix). +> ## Demo Environment Using the account `Admin / zeus123` to log in the [demo environment](https://zeusdemo.zmops.cn/). Please note the account is granted view access. \ No newline at end of file From 56a8b393ec9ea76924850dd9a845381df8a0a8a8 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 11:39:12 +0800 Subject: [PATCH 380/763] [doc]: update readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f790cb1f..556f6764 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ The Zeus IoT production environment can only be installed on a Linux system, eit ``` After Zeus IoT is successfully installed, you can use http://IP:9090 to access the ZeusIoT Console with the default account and password (Admin/zabbix). -> +> For more detailed installation and deployment instructions, please visit our official website document center ## Demo Environment Using the account `Admin / zeus123` to log in the [demo environment](https://zeusdemo.zmops.cn/). Please note the account is granted view access. \ No newline at end of file From 2652fc9610bd3298f9e5699889299e94e3f689a8 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 28 Sep 2021 12:12:39 +0800 Subject: [PATCH 381/763] [fix]:fix product event trigger --- .../iot/web/product/service/ProductEventRuleService.java | 5 +++-- .../iot/web/product/service/work/SaveProdAttrWorker.java | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index 10677f16..45e2f545 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -221,8 +221,9 @@ public Pager getEventByPage(EventParm eventParm) { if (ToolUtil.isNotEmpty(eventParm.getEventRuleName())) { query.eventRuleName.contains(eventParm.getEventRuleName()); } - - + if (ToolUtil.isNotEmpty(eventParm.getClassify())) { + query.classify.eq(eventParm.getClassify()); + } List productEventRelationList = new QProductEventRelation().select(QProductEventRelation.alias().eventRuleId) .relationId.eq(eventParm.getProdId()).findList(); if (ToolUtil.isEmpty(productEventRelationList)) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java index db90992a..b06008ef 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java @@ -37,7 +37,8 @@ public Boolean action(ProductAttr productAttr, Map> " select product_id from product_attribute " + " where template_id is null and key = :key)"; - List deviceDtoList = DB.findDto(DeviceDto.class, sql).setParameter("productId", productAttr.getProductId()).findList(); + List deviceDtoList = DB.findDto(DeviceDto.class, sql).setParameter("productId", productAttr.getProductId()) + .setParameter("key",productAttr.getKey()).findList(); List productAttributeList = new ArrayList<>(); for (DeviceDto deviceDto : deviceDtoList) { From b246c8df96e9c26583addcefdb32fc3fa2159f29 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 28 Sep 2021 13:38:39 +0800 Subject: [PATCH 382/763] [fix]: fix product event trigger --- .../zmops/iot/web/product/service/work/SaveProdAttrWorker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java index b06008ef..7e7d9611 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java @@ -37,7 +37,7 @@ public Boolean action(ProductAttr productAttr, Map> " select product_id from product_attribute " + " where template_id is null and key = :key)"; - List deviceDtoList = DB.findDto(DeviceDto.class, sql).setParameter("productId", productAttr.getProductId()) + List deviceDtoList = DB.findDto(DeviceDto.class, sql).setParameter("productId", Long.parseLong(productAttr.getProductId())) .setParameter("key",productAttr.getKey()).findList(); List productAttributeList = new ArrayList<>(); From fb1dac487a08f5d3aba436221a1077cd1518f342 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 28 Sep 2021 13:46:19 +0800 Subject: [PATCH 383/763] [fix]:fix alarm list --- .../main/java/com/zmops/iot/web/alarm/service/AlarmService.java | 2 +- .../com/zmops/iot/web/product/service/ProductModelService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 6a8c54ff..67a5e56b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -131,7 +131,7 @@ public List getAlarmList(AlarmParam alarmParam) { public List getZbxAlarm(AlarmParam alarmParam) { String hostId = null; - if (null != alarmParam.getDeviceId()) { + if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { Device one = new QDevice().deviceId.eq(alarmParam.getDeviceId()).findOne(); if (null == one) { return Collections.EMPTY_LIST; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index e2f731e9..67254c29 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -67,7 +67,7 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr List pagedList = qProductAttribute .setFirstRow((productAttr.getPage() - 1) * productAttr.getMaxRow()) - .setMaxRows(productAttr.getMaxRow()) + .setMaxRows(productAttr.getMaxRow()).orderBy(" create_time desc ") .asDto(ProductAttrDto.class).findList(); int count = qProductAttribute.findCount(); From 98548b374d06fa9e577f9e300e60c00ac06bb011 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 15:03:57 +0800 Subject: [PATCH 384/763] [feat]: update submodule version --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index f7129d3a..c5c8041c 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit f7129d3a1e4d0c45e48faf95d4c15b7aa9b31418 +Subproject commit c5c8041c87a66ff920c7575d679f73c4ecf8d676 From 0d122a7391c601c1fc6079606e1535b156c4bf2b Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 28 Sep 2021 15:10:49 +0800 Subject: [PATCH 385/763] [fix]: add admin dedicated menu --- .../src/main/java/com/zmops/iot/domain/sys/SysMenu.java | 5 +++++ .../java/com/zmops/iot/web/alarm/service/AlarmService.java | 2 +- .../com/zmops/iot/web/sys/controller/SysRoleController.java | 1 - .../java/com/zmops/iot/web/sys/service/SysRoleService.java | 5 ++++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysMenu.java b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysMenu.java index 4778e3eb..45ba9964 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysMenu.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysMenu.java @@ -77,4 +77,9 @@ public class SysMenu extends BaseEntity { * 菜单状态(字典) */ private String status; + + /** + * 是否超级管理员菜单 + */ + private String adminFlag; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 67a5e56b..dc266236 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -151,7 +151,7 @@ public List getEventList(AlarmParam alarmParam) { if (ToolUtil.isEmpty(problemList)) { return Collections.emptyList(); } - List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Integer::parseInt).collect(Collectors.toList()); + List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Objects::toString).collect(Collectors.toList()); List ruleList = DB.findDto(ProductEventRuleDto.class, "select event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id," + "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") .setParameter("zbxIds", triggerIds).findList(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysRoleController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysRoleController.java index ca21f1eb..75bdf134 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysRoleController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysRoleController.java @@ -31,7 +31,6 @@ public class SysRoleController { /** * 角色列表 */ - @Permission(code = "role") @RequestMapping("/list") public ResponseData list(@RequestParam(value = "name", required = false) String name) { return ResponseData.success(sysRoleService.list(name)); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java index 18767935..aadb25d0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java @@ -6,6 +6,7 @@ import com.zmops.iot.core.tree.DefaultTreeBuildFactory; import com.zmops.iot.domain.sys.SysRole; import com.zmops.iot.domain.sys.SysRoleMenu; +import com.zmops.iot.domain.sys.query.QSysMenu; import com.zmops.iot.domain.sys.query.QSysRole; import com.zmops.iot.domain.sys.query.QSysRoleMenu; import com.zmops.iot.domain.sys.query.QSysUser; @@ -126,6 +127,8 @@ private void checkMenuId(List menuIds) { if (null == user) { throw new ServiceException(AuthExceptionEnum.NOT_LOGIN_ERROR); } + List adminMenuIds = new QSysMenu().select(QSysMenu.alias().menuId).adminFlag.eq("Y").findSingleAttributeList(); + menuIds.removeAll(adminMenuIds); List lists = new QSysRoleMenu().select(QSysRoleMenu.Alias.menuId).menuId.in(menuIds).roleId.in(user.getRoleList()).findSingleAttributeList(); paramMuenuIds.removeAll(lists); if (ToolUtil.isNotEmpty(paramMuenuIds)) { @@ -168,7 +171,7 @@ public List bindedMenu(Long roleId) { " WHERE" + " m1.status = 'ENABLE' " + " AND " + - " m1.menu_id in (select menu_id from sys_role_menu where role_id in (:roleIds) )" + + " m1.menu_id in (select menu_id from sys_role_menu where role_id in (:roleIds) and admin_flag ='N' )" + " ORDER BY" + " m1.sort ASC"; List allMenuList = DB.findDto(TreeNode.class, sql).setParameter("roleIds", user.getRoleList()).findList(); From 0c4c72dd5ae2ca2fd6ea9bda3b65f3fb30f77a72 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 28 Sep 2021 16:14:47 +0800 Subject: [PATCH 386/763] [feat]: add problem acknowledement --- .../zmops/zeus/driver/service/ZbxProblem.java | 4 +++ .../problem/problem.acknowledgement.ftl | 10 +++++++ .../api-json/trigger/trigger.create.ftl | 3 ++- .../web/alarm/controller/AlarmController.java | 18 +++++++++++++ .../iot/web/alarm/service/AlarmService.java | 26 +++++++++++++++---- 5 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 zeus-driver/src/main/resources/api-json/problem/problem.acknowledgement.ftl diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java index 0cc780a7..93f59598 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java @@ -33,4 +33,8 @@ String getEventProblem(@ParamName("hostId") String hostId, @ParamName("timeFrom") Long timeFrom, @ParamName("timeTill") Long timeTill, @ParamName("recent") String recent); + + @Post + @JsonPath("/problem/problem.acknowledgement") + void acknowledgement(@ParamName("eventId") String eventId,@ParamName("action") int action); } diff --git a/zeus-driver/src/main/resources/api-json/problem/problem.acknowledgement.ftl b/zeus-driver/src/main/resources/api-json/problem/problem.acknowledgement.ftl new file mode 100644 index 00000000..02966716 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/problem/problem.acknowledgement.ftl @@ -0,0 +1,10 @@ +{ + "jsonrpc": "2.0", + "method": "event.acknowledge", + "params": { + "eventids": "${eventId}", + "action": ${action} + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.create.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.create.ftl index d338ad2b..f37650fa 100644 --- a/zeus-driver/src/main/resources/api-json/trigger/trigger.create.ftl +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.create.ftl @@ -4,7 +4,8 @@ "params": { "description": "${triggerName}", "expression": "${expression}", - "priority" : ${ruleLevel} + "priority" : ${ruleLevel}, + "manual_close":1 }, "auth": "${userAuth}", "id": 1 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java index 2e7f2810..ed9b9ef6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java @@ -7,6 +7,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** @@ -23,9 +24,26 @@ public class AlarmController { // public void test() { // alarmService.test(); // } + @Permission(code = "alarmList") @RequestMapping("/getAlarmByPage") public ResponseData getAlarmByPage(@RequestBody AlarmParam alarmParam) { return ResponseData.success(alarmService.getAlarmByPage(alarmParam)); } + + @Permission(code = "alarmList") + @RequestMapping("/acknowledgement") + public ResponseData acknowledgement(@RequestParam String eventId) { + alarmService.acknowledgement(eventId); + return ResponseData.success(); + } + + + @Permission(code = "alarmList") + @RequestMapping("/resolve") + public ResponseData resolve(@RequestParam String eventId) { + alarmService.resolve(eventId); + return ResponseData.success(); + } + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index dc266236..6f533b1b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -11,6 +11,7 @@ import com.zmops.iot.web.alarm.dto.AlarmDto; import com.zmops.iot.web.alarm.dto.param.AlarmParam; import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.device.service.DeviceService; import com.zmops.iot.web.product.dto.ProductEventRuleDto; import com.zmops.zeus.driver.entity.ZbxProblemInfo; import com.zmops.zeus.driver.service.ZbxProblem; @@ -35,6 +36,9 @@ public class AlarmService { @Autowired ZbxProblem zbxProblem; + @Autowired + DeviceService deviceService; + public void alarm(Map alarmInfo) { String deviceId = alarmInfo.get("hostname"); @@ -131,13 +135,18 @@ public List getAlarmList(AlarmParam alarmParam) { public List getZbxAlarm(AlarmParam alarmParam) { String hostId = null; + List deviceIds ; if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { - Device one = new QDevice().deviceId.eq(alarmParam.getDeviceId()).findOne(); - if (null == one) { - return Collections.EMPTY_LIST; - } - hostId = one.getZbxId(); + deviceIds = Collections.singletonList(alarmParam.getDeviceId()); + } else { + deviceIds = deviceService.getDeviceIds(); + } + + List zbxIds = new QDevice().select(QDevice.alias().zbxId).deviceId.in(deviceIds).findSingleAttributeList(); + if (ToolUtil.isEmpty(zbxIds)) { + return Collections.EMPTY_LIST; } + hostId = zbxIds.toString(); //从zbx取告警记录 String problem = zbxProblem.getProblem(hostId, alarmParam.getTimeFrom(), alarmParam.getTimeTill(), alarmParam.getRecent()); return JSONObject.parseArray(problem, ZbxProblemInfo.class); @@ -187,4 +196,11 @@ public List getEventProblem(AlarmParam alarmParam) { } + public void acknowledgement(String eventId) { + zbxProblem.acknowledgement(eventId,2); + } + + public void resolve(String eventId) { + zbxProblem.acknowledgement(eventId,1); + } } From 6244fa8ca9bede024ff55300465b9bedb372b344 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 28 Sep 2021 16:21:51 +0800 Subject: [PATCH 387/763] [feat]: add problem status --- .../src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java | 4 ++++ .../java/com/zmops/iot/web/alarm/service/AlarmService.java | 2 ++ 2 files changed, 6 insertions(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java index e4bbecbd..b5340d84 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java @@ -24,4 +24,8 @@ public class AlarmDto { private String severity; private String deviceName; + + private String status; + + private String acknowledged; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 6f533b1b..c84b463b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -93,6 +93,8 @@ public List getAlarmByPage(AlarmParam alarmParam) { AlarmDto alarmDto = new AlarmDto(); BeanUtils.copyProperties(zbxProblemInfo, alarmDto); alarmDto.setRClock(zbxProblemInfo.getR_clock()); + alarmDto.setStatus("0".equals(zbxProblemInfo.getR_clock()) ? "未解决" : "已解决"); + alarmDto.setAcknowledged("0".equals(zbxProblemInfo.getAcknowledged()) ? "未确认" : "已确认"); if (null != deviceMap.get(zbxProblemInfo.getObjectid())) { alarmDto.setDeviceName(deviceMap.get(zbxProblemInfo.getObjectid())); } From ae23371b7d88be6da2eac12d882f9c2ff59f697c Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 28 Sep 2021 16:31:12 +0800 Subject: [PATCH 388/763] [fix]: fix user menu --- .../java/com/zmops/iot/web/sys/service/SysRoleService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java index aadb25d0..9d8d7b8b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java @@ -170,8 +170,9 @@ public List bindedMenu(Long roleId) { " LEFT JOIN sys_menu m2 ON m1.pcode = m2.CODE " + " WHERE" + " m1.status = 'ENABLE' " + + " AND m1.admin_flag = 'N' " + " AND " + - " m1.menu_id in (select menu_id from sys_role_menu where role_id in (:roleIds) and admin_flag ='N' )" + + " m1.menu_id in (select menu_id from sys_role_menu where role_id in (:roleIds))" + " ORDER BY" + " m1.sort ASC"; List allMenuList = DB.findDto(TreeNode.class, sql).setParameter("roleIds", user.getRoleList()).findList(); From 540fb1e798a530ab2421958b965b016cad55e51f Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 28 Sep 2021 16:44:29 +0800 Subject: [PATCH 389/763] [fix]:fix problem list --- .../java/com/zmops/iot/web/alarm/service/AlarmService.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index c84b463b..6997576d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -7,6 +7,7 @@ import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.query.QProductEvent; import com.zmops.iot.media.AlarmCallback; +import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.alarm.dto.AlarmDto; import com.zmops.iot.web.alarm.dto.param.AlarmParam; @@ -93,6 +94,9 @@ public List getAlarmByPage(AlarmParam alarmParam) { AlarmDto alarmDto = new AlarmDto(); BeanUtils.copyProperties(zbxProblemInfo, alarmDto); alarmDto.setRClock(zbxProblemInfo.getR_clock()); + alarmDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(zbxProblemInfo.getClock()), "yyyy-MM-dd HH:mm:ss")); + alarmDto.setRClock("0".equals(zbxProblemInfo.getR_clock()) ? "0" : + LocalDateTimeUtils.convertTimeToString(Integer.parseInt(zbxProblemInfo.getR_clock()), "yyyy-MM-dd HH:mm:ss")); alarmDto.setStatus("0".equals(zbxProblemInfo.getR_clock()) ? "未解决" : "已解决"); alarmDto.setAcknowledged("0".equals(zbxProblemInfo.getAcknowledged()) ? "未确认" : "已确认"); if (null != deviceMap.get(zbxProblemInfo.getObjectid())) { From 96445b1de36d2fc6bfd163eee42c74954b35b23b Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 28 Sep 2021 16:52:21 +0800 Subject: [PATCH 390/763] [fix]: fix device online default value --- .../src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java index 84d79105..52d2ffdb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java @@ -66,6 +66,6 @@ public class DeviceDto { private String position; - private Integer online = 1; + private Integer online; } From aff37e41145867568837bfd17b6a9a20d894589c Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 28 Sep 2021 17:05:59 +0800 Subject: [PATCH 391/763] [fix]: fix product event trigger --- .../main/java/com/zmops/iot/util/ToolUtil.java | 2 +- .../iot/web/alarm/service/AlarmService.java | 13 ++++++------- .../product/service/ProductTriggerService.java | 16 ++++++++++------ 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java b/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java index 321313be..67135fe7 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java @@ -225,7 +225,7 @@ public static Integer toInt(Object val) { */ public static boolean isNum(Object obj) { try { - Integer.parseInt(obj.toString()); + Long.parseLong(obj.toString()); } catch (Exception e) { return false; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 6997576d..4e574335 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -120,7 +120,7 @@ public List getAlarmList(AlarmParam alarmParam) { } List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Integer::parseInt).collect(Collectors.toList()); List ruleList = DB.findDto(ProductEventRuleDto.class, "select d.event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id," + - "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") + "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") .setParameter("zbxIds", triggerIds).findList(); Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); @@ -140,8 +140,8 @@ public List getAlarmList(AlarmParam alarmParam) { } public List getZbxAlarm(AlarmParam alarmParam) { - String hostId = null; - List deviceIds ; + String hostId = null; + List deviceIds; if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { deviceIds = Collections.singletonList(alarmParam.getDeviceId()); } else { @@ -168,7 +168,7 @@ public List getEventList(AlarmParam alarmParam) { } List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Objects::toString).collect(Collectors.toList()); List ruleList = DB.findDto(ProductEventRuleDto.class, "select event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id," + - "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") + "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") .setParameter("zbxIds", triggerIds).findList(); Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); @@ -201,12 +201,11 @@ public List getEventProblem(AlarmParam alarmParam) { return JSONObject.parseArray(problem, ZbxProblemInfo.class); } - public void acknowledgement(String eventId) { - zbxProblem.acknowledgement(eventId,2); + zbxProblem.acknowledgement(eventId, 2); } public void resolve(String eventId) { - zbxProblem.acknowledgement(eventId,1); + zbxProblem.acknowledgement(eventId, 1); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java index e0016f26..f4827270 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java @@ -6,6 +6,7 @@ import com.zmops.iot.domain.product.ProductStatusFunctionRelation; import com.zmops.iot.domain.product.query.QProductStatusFunction; import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; +import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.iot.web.product.dto.ProductStatusFunctionDto; import com.zmops.iot.web.product.dto.ProductStatusJudgeRule; @@ -83,12 +84,15 @@ public Long createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { DB.save(productStatusFunctionRelation); //step 4:同步到设备 - String sql = "select device_id from device where product_id = :productId and device_id not in (select relation_id from product_status_function_relation where inherit='0')"; - List deviceDtoList = DB.findDto(DeviceDto.class, sql).setParameter("productId", judgeRule.getRelationId()).findList(); - deviceDtoList.forEach(deviceDto -> { - DB.sqlUpdate("insert into product_status_function_relation (relation_id,rule_id,inherit) SELECT :deviceId,rule_id,1 from product_status_function_relation where relation_id=:relationId") - .setParameter("deviceId", deviceDto.getDeviceId()).setParameter("relationId", judgeRule.getRelationId() + "").execute(); - }); + String relationId = judgeRule.getRelationId(); + if (ToolUtil.isNum(relationId)) { + String sql = "select device_id from device where product_id = :productId and device_id not in (select relation_id from product_status_function_relation where inherit='0')"; + List deviceDtoList = DB.findDto(DeviceDto.class, sql).setParameter("productId", Long.parseLong(relationId)).findList(); + deviceDtoList.forEach(deviceDto -> { + DB.sqlUpdate("insert into product_status_function_relation (relation_id,rule_id,inherit) SELECT :deviceId,rule_id,1 from product_status_function_relation where relation_id=:relationId") + .setParameter("deviceId", deviceDto.getDeviceId()).setParameter("relationId", judgeRule.getRelationId() + "").execute(); + }); + } return productStatusFunction.getRuleId(); } From 3e0c74c80202cd153fe7400fef64c848c23b0544 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 17:56:34 +0800 Subject: [PATCH 392/763] [feat]: url / redirect to /index --- .../core/auth/filter/NoneAuthedResources.java | 1 + .../web/sys/controller/LoginController.java | 24 +++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java index 884271cf..b4546091 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java @@ -38,6 +38,7 @@ public class NoneAuthedResources { public static final String[] BACKEND_RESOURCES = { //主页 "/", + "/index", //获取验证码 "/kaptcha", diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java index 7cdaa3c6..b356107d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java @@ -14,10 +14,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.util.Map; @@ -36,25 +33,32 @@ public class LoginController extends BaseController { @Autowired private SysUserService userService; + /** - * 跳转到主页 + * 重定向到 /index + * + * @param model + * @return */ - @RequestMapping(value = "/", method = RequestMethod.GET) + @GetMapping("/") public String index(Model model) { + return "redirect:/index"; + } - //判断用户是否登录 + /** + * 跳转到主页 + */ + @RequestMapping(value = "/index", method = RequestMethod.GET) + public String reindex(Model model) { if (LoginContextHolder.getContext().hasLogin()) { Map userIndexInfo = userService.getUserIndexInfo(); - //用户信息为空,提示账号没分配角色登录不进去 if (userIndexInfo == null) { - model.addAttribute("tips", "该用户没有角色,无法登陆"); return "/login"; } else { model.addAllAttributes(userIndexInfo); return "/index"; } - } else { return "/index"; } From a6929e1b7e773b9b5ff4b3de6fe1308d4edfa9fa Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 18:21:31 +0800 Subject: [PATCH 393/763] [fix]: remove / url redirect --- .../iot/core/auth/filter/NoneAuthedResources.java | 1 - .../iot/web/sys/controller/LoginController.java | 14 +------------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java index b4546091..884271cf 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java @@ -38,7 +38,6 @@ public class NoneAuthedResources { public static final String[] BACKEND_RESOURCES = { //主页 "/", - "/index", //获取验证码 "/kaptcha", diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java index b356107d..2296f353 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java @@ -33,22 +33,10 @@ public class LoginController extends BaseController { @Autowired private SysUserService userService; - - /** - * 重定向到 /index - * - * @param model - * @return - */ - @GetMapping("/") - public String index(Model model) { - return "redirect:/index"; - } - /** * 跳转到主页 */ - @RequestMapping(value = "/index", method = RequestMethod.GET) + @RequestMapping(value = "/", method = RequestMethod.GET) public String reindex(Model model) { if (LoginContextHolder.getContext().hasLogin()) { Map userIndexInfo = userService.getUserIndexInfo(); From 076b9f033161b7da1123c3d26e480a970e8e54c5 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 22:27:58 +0800 Subject: [PATCH 394/763] [feat]: update zeus-iot-ui submodule --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index c5c8041c..1ff4f759 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit c5c8041c87a66ff920c7575d679f73c4ecf8d676 +Subproject commit 1ff4f7594885b1cb9e789ff48732c9d955d9ec4f From 92d734c88772cf4c2e110a3013db427a8350af19 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 23:02:00 +0800 Subject: [PATCH 395/763] [style]: update start shell script --- dist-material/bin/IoTServer.bat | 12 ++++++------ dist-material/bin/IoTServer.sh | 4 ++-- dist-material/bin/IoTServerInit.bat | 12 ++++++------ dist-material/bin/IoTServerInit.sh | 22 +++++++++++----------- dist-material/bin/IoTServerNoInit.bat | 12 ++++++------ dist-material/bin/IoTServerNoInit.sh | 24 ++++++++++++------------ dist-material/bin/startup.bat | 2 +- dist-material/bin/webappService.bat | 4 ++-- dist-material/bin/webappService.sh | 2 +- dist-material/log4j2.xml | 6 +++--- 10 files changed, 50 insertions(+), 50 deletions(-) diff --git a/dist-material/bin/IoTServer.bat b/dist-material/bin/IoTServer.bat index 316d3780..76473277 100644 --- a/dist-material/bin/IoTServer.bat +++ b/dist-material/bin/IoTServer.bat @@ -17,12 +17,12 @@ @echo off setlocal -set OAP_PROCESS_TITLE=Zeus-IoT-Server -set OAP_HOME=%~dp0%.. -set OAP_OPTS="-Xms1024M -Xmx1024M -Doap.logDir=%OAP_HOME%\logs -Duser.timezone=GMT+08" +set IOT_PROCESS_TITLE=Zeus-IoT-Server +set IOT_SERVER_HOME=%~dp0%.. +set IOT_OPTS="-Xms1024M -Xmx1024M -Diot.logDir=%IOT_SERVER_HOME%\logs -Duser.timezone=GMT+08" -set CLASSPATH=%OAP_HOME%\config;.; -set CLASSPATH=%OAP_HOME%\iot-server-libs\*;%CLASSPATH% +set CLASSPATH=%IOT_SERVER_HOME%\config;.; +set CLASSPATH=%IOT_SERVER_HOME%\iot-server-libs\*;%CLASSPATH% if defined JAVA_HOME ( set _EXECJAVA="%JAVA_HOME%\bin\java" @@ -33,5 +33,5 @@ if not defined JAVA_HOME ( set _EXECJAVA=java ) -start "%OAP_PROCESS_TITLE%" %_EXECJAVA% "%OAP_OPTS%" -cp "%CLASSPATH%" com.zmops.zeus.iot.server.starter.IoTServerStartUp +start "%IOT_PROCESS_TITLE%" %_EXECJAVA% "%IOT_OPTS%" -cp "%CLASSPATH%" com.zmops.zeus.iot.server.starter.IoTServerStartUp endlocal diff --git a/dist-material/bin/IoTServer.sh b/dist-material/bin/IoTServer.sh index d7a011c8..4e9ecd48 100644 --- a/dist-material/bin/IoTServer.sh +++ b/dist-material/bin/IoTServer.sh @@ -35,7 +35,7 @@ do CLASSPATH="$i:$CLASSPATH" done -IOT_OPTIONS=" -Doap.logDir=${IOT_LOG_DIR} -Duser.timezone=GMT+08" +IOT_OPTIONS=" -Diot.logDir=${IOT_LOG_DIR} -Duser.timezone=GMT+08" eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${IOT_OPTIONS} -classpath $CLASSPATH com.zmops.zeus.iot.server.starter.IoTServerStartUp \ &> ${IOT_LOG_DIR}/zeus_iot.log &" @@ -44,6 +44,6 @@ if [ $? -eq 0 ]; then sleep 1 echo "Zeus IOT started successfully!" else - echo "Zeus IOT OAP started failure!" + echo "Zeus IoT Server started failure!" exit 1 fi diff --git a/dist-material/bin/IoTServerInit.bat b/dist-material/bin/IoTServerInit.bat index 69e453e2..36a68e61 100644 --- a/dist-material/bin/IoTServerInit.bat +++ b/dist-material/bin/IoTServerInit.bat @@ -17,12 +17,12 @@ @echo off setlocal -set OAP_PROCESS_TITLE=Skywalking-Collector -set OAP_HOME=%~dp0%.. -set OAP_OPTS="-Xms256M -Xmx512M -Doap.logDir=%OAP_HOME%\logs" +set IOT_PROCESS_TITLE=IoT-Server-Collector +set IOT_SERVER_HOME=%~dp0%.. +set IOT_OPTS="-Xms256M -Xmx512M -Diot.logDir=%IOT_SERVER_HOME%\logs" -set CLASSPATH=%OAP_HOME%\config;.; -set CLASSPATH=%OAP_HOME%\oap-libs\*;%CLASSPATH% +set CLASSPATH=%IOT_SERVER_HOME%\config;.; +set CLASSPATH=%IOT_SERVER_HOME%\iot-server-libs\*;%CLASSPATH% if defined JAVA_HOME ( set _EXECJAVA="%JAVA_HOME%\bin\java" @@ -33,5 +33,5 @@ if not defined JAVA_HOME ( set _EXECJAVA=java ) -start "%OAP_PROCESS_TITLE%" %_EXECJAVA% "%OAP_OPTS%" -cp "%CLASSPATH%" -Dmode=init org.apache.skywalking.oap.server.starter.OAPServerStartUp +start "%IOT_PROCESS_TITLE%" %_EXECJAVA% "%IOT_OPTS%" -cp "%CLASSPATH%" -Dmode=init com.zmops.zeus.iot.server.starter.IoTServerStartUp endlocal diff --git a/dist-material/bin/IoTServerInit.sh b/dist-material/bin/IoTServerInit.sh index cd2db309..5a047c87 100644 --- a/dist-material/bin/IoTServerInit.sh +++ b/dist-material/bin/IoTServerInit.sh @@ -17,33 +17,33 @@ PRG="$0" PRGDIR=$(dirname "$PRG") -[ -z "$OAP_HOME" ] && OAP_HOME=$(cd "$PRGDIR/.." > /dev/null || exit 1; pwd) +[ -z "$IOT_SERVER_HOME" ] && IOT_SERVER_HOME=$(cd "$PRGDIR/.." > /dev/null || exit 1; pwd) -OAP_LOG_DIR="${OAP_HOME}/logs" +IOT_LOG_DIR="${IOT_SERVER_HOME}/logs" JAVA_OPTS="${JAVA_OPTS:- -Xms256M -Xmx512M}" -if [ ! -d "${OAP_HOME}/logs" ]; then - mkdir -p "${OAP_LOG_DIR}" +if [ ! -d "${IOT_SERVER_HOME}/logs" ]; then + mkdir -p "${IOT_LOG_DIR}" fi _RUNJAVA=${JAVA_HOME}/bin/java [ -z "$JAVA_HOME" ] && _RUNJAVA=java -CLASSPATH="$OAP_HOME/config:$CLASSPATH" -for i in "$OAP_HOME"/oap-libs/*.jar +CLASSPATH="$IOT_SERVER_HOME/config:$CLASSPATH" +for i in "$IOT_SERVER_HOME"/iot-server-libs/*.jar do CLASSPATH="$i:$CLASSPATH" done -OAP_OPTIONS=" -Doap.logDir=${OAP_LOG_DIR}" +IOT_OPTIONS=" -Diot.logDir=${IOT_LOG_DIR}" -eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${OAP_OPTIONS} -classpath $CLASSPATH -Dmode=init org.apache.skywalking.oap.server.starter.OAPServerStartUp \ - 2>${OAP_LOG_DIR}/oap.log 1> /dev/null &" +eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${IOT_OPTIONS} -classpath $CLASSPATH -Dmode=init com.zmops.zeus.iot.server.starter.IoTServerStartUp \ + 2>${IOT_LOG_DIR}/iot_server.log 1> /dev/null &" if [ $? -eq 0 ]; then sleep 1 - echo "SkyWalking OAP started successfully!" + echo "Zeus IoT Server started successfully!" else - echo "SkyWalking OAP started failure!" + echo "Zeus IoT Server started failure!" exit 1 fi diff --git a/dist-material/bin/IoTServerNoInit.bat b/dist-material/bin/IoTServerNoInit.bat index 47175c53..97e7322f 100644 --- a/dist-material/bin/IoTServerNoInit.bat +++ b/dist-material/bin/IoTServerNoInit.bat @@ -17,12 +17,12 @@ @echo off setlocal -set OAP_PROCESS_TITLE=Skywalking-Collector -set OAP_HOME=%~dp0%.. -set OAP_OPTS="-Xms256M -Xmx512M -Doap.logDir=%OAP_HOME%\logs" +set IOT_PROCESS_TITLE=IoT-Server-Collector +set IOT_SERVER_HOME=%~dp0%.. +set IOT_OPTS="-Xms256M -Xmx512M -Diot.logDir=%IOT_SERVER_HOME%\logs" -set CLASSPATH=%OAP_HOME%\config;.; -set CLASSPATH=%OAP_HOME%\oap-libs\*;%CLASSPATH% +set CLASSPATH=%IOT_SERVER_HOME%\config;.; +set CLASSPATH=%IOT_SERVER_HOME%\iot-server-libs\*;%CLASSPATH% if defined JAVA_HOME ( set _EXECJAVA="%JAVA_HOME%\bin\java" @@ -33,5 +33,5 @@ if not defined JAVA_HOME ( set _EXECJAVA=java ) -start "%OAP_PROCESS_TITLE%" %_EXECJAVA% "%OAP_OPTS%" -cp "%CLASSPATH%" -Dmode=no-init org.apache.skywalking.oap.server.starter.OAPServerStartUp +start "%IOT_PROCESS_TITLE%" %_EXECJAVA% "%IOT_OPTS%" -cp "%CLASSPATH%" -Dmode=no-init com.zmops.zeus.iot.server.starter.IoTServerStartUp endlocal diff --git a/dist-material/bin/IoTServerNoInit.sh b/dist-material/bin/IoTServerNoInit.sh index 42c54e60..a7e17b73 100644 --- a/dist-material/bin/IoTServerNoInit.sh +++ b/dist-material/bin/IoTServerNoInit.sh @@ -17,33 +17,33 @@ PRG="$0" PRGDIR=$(dirname "$PRG") -[ -z "$OAP_HOME" ] && OAP_HOME=$(cd "$PRGDIR/.." > /dev/null || exit 1; pwd) +[ -z "$IOT_SERVER_HOME" ] && IOT_SERVER_HOME=$(cd "$PRGDIR/.." > /dev/null || exit 1; pwd) -OAP_LOG_DIR=${OAP_LOG_DIR:-"${OAP_HOME}/logs"} -JAVA_OPTS="${JAVA_OPTS:- -Xms256M -Xmx512M}" +IOT_LOG_DIR=${IOT_LOG_DIR:-"${IOT_SERVER_HOME}/logs"} +JAVA_OPTS="${JAVA_OPTS:- -Xms512M -Xmx1024M}" -if [ ! -d "${OAP_HOME}/logs" ]; then - mkdir -p "${OAP_LOG_DIR}" +if [ ! -d "${IOT_SERVER_HOME}/logs" ]; then + mkdir -p "${IOT_LOG_DIR}" fi _RUNJAVA=${JAVA_HOME}/bin/java [ -z "$JAVA_HOME" ] && _RUNJAVA=java -CLASSPATH="$OAP_HOME/config:$CLASSPATH" -for i in "$OAP_HOME"/oap-libs/*.jar +CLASSPATH="$IOT_SERVER_HOME/config:$CLASSPATH" +for i in "$IOT_SERVER_HOME"/iot-server-libs/*.jar do CLASSPATH="$i:$CLASSPATH" done -OAP_OPTIONS=" -Doap.logDir=${OAP_LOG_DIR}" +IOT_OPTIONS=" -Diot.logDir=${IOT_LOG_DIR}" -eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${OAP_OPTIONS} -classpath $CLASSPATH -Dmode=no-init org.apache.skywalking.oap.server.starter.OAPServerStartUp \ - 2>${OAP_LOG_DIR}/oap.log 1> /dev/null &" +eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${IOT_OPTIONS} -classpath $CLASSPATH -Dmode=no-init com.zmops.zeus.iot.server.starter.IoTServerStartUp \ + 2>${IOT_LOG_DIR}/iot_server.log 1> /dev/null &" if [ $? -eq 0 ]; then sleep 1 - echo "SkyWalking OAP started successfully!" + echo "Zeus IoT Server started successfully!" else - echo "SkyWalking OAP started failure!" + echo "Zeus IoT Server started failure!" exit 1 fi diff --git a/dist-material/bin/startup.bat b/dist-material/bin/startup.bat index f9d27473..611631e0 100644 --- a/dist-material/bin/startup.bat +++ b/dist-material/bin/startup.bat @@ -17,6 +17,6 @@ @echo off setlocal -call "%~dp0"\oapService.bat start +call "%~dp0"\IoTServer.bat start call "%~dp0"\webappService.bat start endlocal diff --git a/dist-material/bin/webappService.bat b/dist-material/bin/webappService.bat index a1ca98c0..33879bbf 100644 --- a/dist-material/bin/webappService.bat +++ b/dist-material/bin/webappService.bat @@ -17,7 +17,7 @@ @echo off setlocal -set WEBAPP_PROCESS_TITLE=Skywalking-Webapp +set WEBAPP_PROCESS_TITLE=Zeus-Webapp set WEBAPP_HOME=%~dp0%.. set JARPATH=%WEBAPP_HOME%\webapp set WEBAPP_LOG_DIR=%WEBAPP_HOME%\logs @@ -37,5 +37,5 @@ if not defined JAVA_HOME ( set _EXECJAVA=java ) -start "%WEBAPP_PROCESS_TITLE%" %_EXECJAVA% -jar %JARPATH%/skywalking-webapp.jar --spring.config.location=%JARPATH%/webapp.yml --logging.file=%LOG_FILE_LOCATION% +start "%WEBAPP_PROCESS_TITLE%" %_EXECJAVA% -jar %JARPATH%/zeus-webapp.jar --spring.config.location=%JARPATH%/webapp.yml --logging.file=%LOG_FILE_LOCATION% endlocal diff --git a/dist-material/bin/webappService.sh b/dist-material/bin/webappService.sh index 965940c8..235fd0de 100644 --- a/dist-material/bin/webappService.sh +++ b/dist-material/bin/webappService.sh @@ -20,7 +20,7 @@ PRGDIR=$(dirname "$PRG") [ -z "$WEBAPP_HOME" ] && WEBAPP_HOME=$(cd "$PRGDIR/.." > /dev/null || exit 1; pwd) WEBAPP_LOG_DIR="${WEBAPP_LOG_DIR:-${WEBAPP_HOME}/logs}" -JAVA_OPTS="${JAVA_OPTS:- -Xms256M -Xmx512M}" +JAVA_OPTS="${JAVA_OPTS:- -Xms512M -Xmx1024M}" JAR_PATH="${WEBAPP_HOME}/webapp" if [ ! -d "${WEBAPP_LOG_DIR}" ]; then diff --git a/dist-material/log4j2.xml b/dist-material/log4j2.xml index 0ce331bf..094421a4 100644 --- a/dist-material/log4j2.xml +++ b/dist-material/log4j2.xml @@ -19,11 +19,10 @@ - ${sys:oap.logDir} + ${sys:iot.logDir} - + %d - %c - %L [%t] %-5p %x - %m%n @@ -37,6 +36,7 @@ + From 3a265c58dbe4672315e4960f4376343c12873130 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 23:02:47 +0800 Subject: [PATCH 396/763] [style]: optimize code style --- .../iot/server/core/servlet/DeviceTriggerActionHandler.java | 1 + .../src/main/java/com/zmops/iot/media/WebhookCallback.java | 3 --- .../com/zmops/iot/media/dingtalk/DingtalkHookCallback.java | 3 --- .../java/com/zmops/iot/media/feishu/FeishuHookCallback.java | 3 --- .../java/com/zmops/iot/media/wechat/WechatHookCallback.java | 3 --- .../java/com/zmops/iot/media/welink/WeLinkHookCallback.java | 3 --- 6 files changed, 1 insertion(+), 15 deletions(-) diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java index f1096fb8..047ce8c3 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java @@ -52,6 +52,7 @@ protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseExcept ActionParam actionParam = new ActionParam(); actionParam.setTriggerDevice("10084"); + eventBusService.postExecuteActionMsg(ActionRouteIdentifier.helloworld, actionParam); return null; diff --git a/zeus-message/src/main/java/com/zmops/iot/media/WebhookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/WebhookCallback.java index e58ab2f0..eac5607f 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/WebhookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/WebhookCallback.java @@ -24,9 +24,6 @@ import java.util.List; -/** - * Use SkyWalking alarm webhook API call a remote endpoints. - */ @Slf4j public class WebhookCallback implements AlarmCallback { private static final int HTTP_CONNECT_TIMEOUT = 1000; diff --git a/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkHookCallback.java index 0447b082..29da47be 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkHookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkHookCallback.java @@ -48,9 +48,6 @@ import java.util.Base64; import java.util.List; -/** - * Use SkyWalking alarm dingtalk webhook API. - */ @Slf4j @Service public class DingtalkHookCallback implements AlarmCallback { diff --git a/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuHookCallback.java index 403f7388..45ad4cb3 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuHookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuHookCallback.java @@ -51,9 +51,6 @@ import java.util.Map; import java.util.stream.Collectors; -/** - * Use SkyWalking alarm feishu webhook API. - */ @Slf4j @Service public class FeishuHookCallback implements AlarmCallback { diff --git a/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatHookCallback.java index afc623b5..29ecf380 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatHookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatHookCallback.java @@ -38,9 +38,6 @@ import java.io.IOException; import java.util.List; -/** - * Use SkyWalking alarm wechat webhook API. - */ @Slf4j @Service public class WechatHookCallback implements AlarmCallback { diff --git a/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkHookCallback.java index 56394803..6ae52b42 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkHookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkHookCallback.java @@ -43,9 +43,6 @@ import java.nio.charset.StandardCharsets; import java.util.*; -/** - * Use SkyWalking alarm WeLink webhook API. - */ @Slf4j @Service public class WeLinkHookCallback implements AlarmCallback { From b9a7bd9283247debf66810cf4d044af8032ed4b2 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 28 Sep 2021 23:14:41 +0800 Subject: [PATCH 397/763] [style]: format code --- .../starter/config/ApplicationConfigLoader.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java index d3cb5131..86de2f9d 100644 --- a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java +++ b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java @@ -72,7 +72,7 @@ private void loadConfig(ApplicationConfiguration configuration) throws ConfigFil log.info("Get a provider define belong to {} module, provider name: {}", moduleName, providerName); final Map propertiesConfig = (Map) config; - final Properties properties = new Properties(); + final Properties properties = new Properties(); if (propertiesConfig != null) { propertiesConfig.forEach((propertyName, propertyValue) -> { @@ -136,7 +136,7 @@ private void selectConfig(final Map> moduleConfigura while (moduleIterator.hasNext()) { Map.Entry> entry = moduleIterator.next(); - final String moduleName = entry.getKey(); + final String moduleName = entry.getKey(); final Map providerConfig = entry.getValue(); if (!providerConfig.containsKey(SELECTOR)) { @@ -173,7 +173,7 @@ private void overrideModuleSettings(ApplicationConfiguration configuration, Stri if (moduleAndConfigSeparator <= 0) { return; } - String moduleName = key.substring(0, moduleAndConfigSeparator); + String moduleName = key.substring(0, moduleAndConfigSeparator); String providerSettingSubKey = key.substring(moduleAndConfigSeparator + 1); ApplicationConfiguration.ModuleConfiguration moduleConfiguration = configuration.getModuleConfiguration(moduleName); @@ -187,7 +187,7 @@ private void overrideModuleSettings(ApplicationConfiguration configuration, Stri } String providerName = providerSettingSubKey.substring(0, providerAndConfigSeparator); - String settingKey = providerSettingSubKey.substring(providerAndConfigSeparator + 1); + String settingKey = providerSettingSubKey.substring(providerAndConfigSeparator + 1); if (!moduleConfiguration.has(providerName)) { return; } @@ -197,8 +197,8 @@ private void overrideModuleSettings(ApplicationConfiguration configuration, Stri return; } - Object originValue = providerSettings.get(settingKey); - Class type = originValue.getClass(); + Object originValue = providerSettings.get(settingKey); + Class type = originValue.getClass(); if (type.equals(int.class) || type.equals(Integer.class)) providerSettings.put(settingKey, Integer.valueOf(value)); else if (type.equals(String.class)) From a53924cf0a6f623835997cdf7555637c93577a97 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 29 Sep 2021 15:57:58 +0800 Subject: [PATCH 398/763] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 556f6764..32b7e6b2 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ The following screenshots give a close insight into Zeus IoT. ## Technology stack -- Basic components: **Zabbix 5.4+** +- Basic components: **[Zabbix 5.4+](https://www.zabbix.com)** - Database: **PostgreSQL12+ , TDEngine 2.2+** - Webapp: **SpringBoot 2 , [Ebean](https://ebean.io/) , Vue Element , Socket.IO** - IoT Server: **Apache Camel 2.2 , Modular design** @@ -92,4 +92,4 @@ After Zeus IoT is successfully installed, you can use http://IP:9090 to access t > For more detailed installation and deployment instructions, please visit our official website document center ## Demo Environment -Using the account `Admin / zeus123` to log in the [demo environment](https://zeusdemo.zmops.cn/). Please note the account is granted view access. \ No newline at end of file +Using the account `Admin / zeus123` to log in the [demo environment](https://zeusdemo.zmops.cn/). Please note the account is granted view access. From 3d5c2e1afe7b94d5bd4c567ec36609b1d3814b95 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 29 Sep 2021 16:00:54 +0800 Subject: [PATCH 399/763] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 32b7e6b2..c2b11775 100644 --- a/README.md +++ b/README.md @@ -39,10 +39,10 @@ The following screenshots give a close insight into Zeus IoT. ## Technology stack - Basic components: **[Zabbix 5.4+](https://www.zabbix.com)** -- Database: **PostgreSQL12+ , TDEngine 2.2+** +- Database: **PostgreSQL12+ , [TDEngine 2.2+](https://www.taosdata.com)** - Webapp: **SpringBoot 2 , [Ebean](https://ebean.io/) , Vue Element , Socket.IO** -- IoT Server: **Apache Camel 2.2 , Modular design** -- Visualization: **Grafana 8.0+** +- IoT Server: **[Apache Camel 2.2](https://camel.apache.org/) , Modular design** +- Visualization: **[Grafana 8.0+](https://grafana.com/grafana/)** ## Features

From bac8485f597e3b6ab4075a9b123324269317936c Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 29 Sep 2021 18:12:56 +0800 Subject: [PATCH 400/763] [fix]: fix trends img --- .../iot/web/analyse/service/ZbxChartsService.java | 11 +++++++++++ .../device/schedule/DeviceOnlineReprotSchedule.java | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java index 2dc25bde..6509fb4b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java @@ -1,13 +1,17 @@ package com.zmops.iot.web.analyse.service; +import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.zeus.driver.entity.ZbxItemInfo; +import com.zmops.zeus.driver.service.ZbxItem; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.methods.PostMethod; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -38,6 +42,8 @@ public class ZbxChartsService { private static LocalDateTime COOKIE_TIME; + @Autowired + ZbxItem zbxItem; /** * 获取 数据图形展示 @@ -63,6 +69,11 @@ public void getCharts(HttpServletResponse response, throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_NOT_EXISTS); } + List itemInfos = JSONObject.parseArray(zbxItem.getItemInfo(itemids.toString(), null), ZbxItemInfo.class); + if (ToolUtil.isEmpty(itemInfos)) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_NOT_EXISTS); + } + HttpClient client = new HttpClient(); PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort + "/zabbix/chart.php?type=0&profileIdx=web.item.graph.filter"); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java index 6922e024..465556f5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java @@ -33,7 +33,7 @@ public void report() { List deviceList = new QDevice().findList(); Map> onLinemap = deviceList.parallelStream() - .collect(Collectors.groupingBy(Device::getType, Collectors.groupingBy(Device::getOnline, Collectors.counting()))); + .collect(Collectors.groupingBy(Device::getType, Collectors.groupingBy(o -> Optional.ofNullable(o.getOnline()).orElse(0), Collectors.counting()))); List list = new ArrayList<>(); From b87a34672498bfa36abcfc6659c658618b95acec Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 29 Sep 2021 18:13:18 +0800 Subject: [PATCH 401/763] [fix]: fix forest version --- zeus-webapp-bom/pom.xml | 2 +- .../java/com/zmops/iot/web/init/BasicSettingsInit.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/zeus-webapp-bom/pom.xml b/zeus-webapp-bom/pom.xml index 890c2a5a..abdaa460 100644 --- a/zeus-webapp-bom/pom.xml +++ b/zeus-webapp-bom/pom.xml @@ -140,7 +140,7 @@ com.dtflys.forest forest-spring-boot-starter - 1.5.1 + 1.5.3 commons-logging diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java index a647e881..2d8f2480 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java @@ -42,7 +42,7 @@ public class BasicSettingsInit { @PostConstruct public void init() { - zbxApiToken = configuration.getVariables().get("zbxApiToken").toString(); + zbxApiToken = configuration.getVariableValue("zbxApiToken").toString(); } /** @@ -166,14 +166,14 @@ public Map getOfflineStatusScript() { } - public String createAction(String name,String tagName,String scriptId, String groupId) { - String response = zbxAction.createOfflineStatusAction(zbxApiToken,name,tagName, scriptId, groupId); + public String createAction(String name, String tagName, String scriptId, String groupId) { + String response = zbxAction.createOfflineStatusAction(zbxApiToken, name, tagName, scriptId, groupId); return JSON.parseObject(response, ZbxResponseIds.class).getActionids()[0]; } public String getAction(String name) { - String response = zbxAction.getOfflineStatusAction(zbxApiToken,name); + String response = zbxAction.getOfflineStatusAction(zbxApiToken, name); List> ids = JSON.parseObject(response, List.class); if (null != ids && ids.size() > 0) { return ids.get(0).get("actionid"); From a23bdea9bbd38b8ca89af457ca9170e9f549e49e Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 29 Sep 2021 18:28:32 +0800 Subject: [PATCH 402/763] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c2b11775..17bd80b7 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ [![GitHub stars](https://img.shields.io/github/stars/zmops/zeus-iot.svg?label=Stars&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub issues](https://img.shields.io/github/issues/zmops/zeus-iot?label=Issuess&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub forks](https://img.shields.io/github/forks/zmops/zeus-iot?label=Forks&logo=github)](https://github.com/zmops/zeus-iot) -![Version](https://img.shields.io/badge/version-1.0.0--RELEASE-brightgreen) +![Version](https://img.shields.io/badge/version-1.0-beta-brightgreen) [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) ## Abstract From dfcbd8c6e62c63d45f6fb649f9575fad6737ae55 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 29 Sep 2021 18:28:53 +0800 Subject: [PATCH 403/763] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 17bd80b7..30b1ea57 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ [![GitHub stars](https://img.shields.io/github/stars/zmops/zeus-iot.svg?label=Stars&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub issues](https://img.shields.io/github/issues/zmops/zeus-iot?label=Issuess&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub forks](https://img.shields.io/github/forks/zmops/zeus-iot?label=Forks&logo=github)](https://github.com/zmops/zeus-iot) -![Version](https://img.shields.io/badge/version-1.0-beta-brightgreen) +![Version](https://img.shields.io/badge/version-1.0.0-beta-brightgreen) [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) ## Abstract From dd32bf8890f06bb83337d084ee0c5b1d684439f1 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 29 Sep 2021 18:29:21 +0800 Subject: [PATCH 404/763] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 30b1ea57..9f1c99a2 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ [![GitHub stars](https://img.shields.io/github/stars/zmops/zeus-iot.svg?label=Stars&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub issues](https://img.shields.io/github/issues/zmops/zeus-iot?label=Issuess&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub forks](https://img.shields.io/github/forks/zmops/zeus-iot?label=Forks&logo=github)](https://github.com/zmops/zeus-iot) -![Version](https://img.shields.io/badge/version-1.0.0-beta-brightgreen) +![Version](https://img.shields.io/badge/version-1.0.0-snapshot-brightgreen) [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) ## Abstract From a15f11a7c78c1f6acc235dc8e936271f7c669b31 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 29 Sep 2021 18:29:37 +0800 Subject: [PATCH 405/763] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9f1c99a2..1f599dc2 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ [![GitHub stars](https://img.shields.io/github/stars/zmops/zeus-iot.svg?label=Stars&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub issues](https://img.shields.io/github/issues/zmops/zeus-iot?label=Issuess&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub forks](https://img.shields.io/github/forks/zmops/zeus-iot?label=Forks&logo=github)](https://github.com/zmops/zeus-iot) -![Version](https://img.shields.io/badge/version-1.0.0-snapshot-brightgreen) +![Version](https://img.shields.io/badge/version-1.0.0-release-brightgreen) [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) ## Abstract From 92d43e6ef1d7b2aed042ec4439d34b09e520e956 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 29 Sep 2021 18:30:12 +0800 Subject: [PATCH 406/763] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1f599dc2..e61a0f68 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ [![GitHub stars](https://img.shields.io/github/stars/zmops/zeus-iot.svg?label=Stars&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub issues](https://img.shields.io/github/issues/zmops/zeus-iot?label=Issuess&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub forks](https://img.shields.io/github/forks/zmops/zeus-iot?label=Forks&logo=github)](https://github.com/zmops/zeus-iot) -![Version](https://img.shields.io/badge/version-1.0.0-release-brightgreen) +![Version](https://img.shields.io/badge/version-1.0.0-BETA-brightgreen) [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) ## Abstract From 405b414d04dd003b7413e6536f1abf8a79d5df84 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 29 Sep 2021 18:30:29 +0800 Subject: [PATCH 407/763] Create README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e61a0f68..aacc64b3 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ [![GitHub stars](https://img.shields.io/github/stars/zmops/zeus-iot.svg?label=Stars&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub issues](https://img.shields.io/github/issues/zmops/zeus-iot?label=Issuess&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub forks](https://img.shields.io/github/forks/zmops/zeus-iot?label=Forks&logo=github)](https://github.com/zmops/zeus-iot) -![Version](https://img.shields.io/badge/version-1.0.0-BETA-brightgreen) +![Version](https://img.shields.io/badge/version-1.0.0-RELEASE-brightgreen) [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) ## Abstract From b15590e2fc013a60e74e47c1cf83cdd45af43349 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 29 Sep 2021 18:31:03 +0800 Subject: [PATCH 408/763] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aacc64b3..20a2f49f 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ [![GitHub stars](https://img.shields.io/github/stars/zmops/zeus-iot.svg?label=Stars&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub issues](https://img.shields.io/github/issues/zmops/zeus-iot?label=Issuess&logo=github)](https://github.com/zmops/zeus-iot) [![GitHub forks](https://img.shields.io/github/forks/zmops/zeus-iot?label=Forks&logo=github)](https://github.com/zmops/zeus-iot) -![Version](https://img.shields.io/badge/version-1.0.0-RELEASE-brightgreen) +![Version](https://img.shields.io/badge/version-1.0.0--BETA-brightgreen) [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) ## Abstract From cce0de14f814ac6ee63efdd6482e75d20f462b53 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 29 Sep 2021 19:24:19 +0800 Subject: [PATCH 409/763] [fix]: fix device attribute --- .../com/zmops/iot/web/device/service/DeviceModelService.java | 3 +++ .../java/com/zmops/iot/web/device/service/DeviceService.java | 1 + 2 files changed, 4 insertions(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index f9081613..4a75a0c8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -109,6 +109,9 @@ public ProductAttrDto detail(Long attrId) { return attr; } JSONArray itemInfo = JSONObject.parseArray(zbxItem.getItemInfo(attr.getZbxId(), null)); + if (itemInfo.size() == 0) { + return attr; + } attr.setTags(JSONObject.parseArray(itemInfo.getJSONObject(0).getString("tags"), ProductTag.Tag.class)); attr.setProcessStepList(formatProcessStep(itemInfo.getJSONObject(0).getString("preprocessing"))); String valuemap = itemInfo.getJSONObject(0).getString("valuemap"); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index e0fc3f83..feaf5b04 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -192,6 +192,7 @@ private StringBuilder generateBaseSql() { " d.TYPE, " + " d.addr, " + " d.position, " + + " d.online," + " P.NAME product_name, " + " ds.group_name, " + " ds.groupIds " + From b44d01deeac2107431fcbf6016a64e732774bec2 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 29 Sep 2021 20:23:58 +0800 Subject: [PATCH 410/763] [fix]: fix problem list --- zeus-driver/src/main/resources/api-json/problem/problem.get.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl index e0421621..6086b28e 100644 --- a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl +++ b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl @@ -9,7 +9,7 @@ "recent": ${recent}, "sortfield": ["eventid"], <#if hostId??> - "hostids":"${hostId}", + "hostids":${hostId}, <#if timeFrom??> "time_from":${timeFrom}, From fcdca6e6f7124113c75cbd1a4904bd528e733551 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 29 Sep 2021 20:34:58 +0800 Subject: [PATCH 411/763] [fix]: fix alarm list --- .../java/com/zmops/iot/web/alarm/service/AlarmService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 4e574335..c507e1ea 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -177,8 +177,8 @@ public List getEventList(AlarmParam alarmParam) { AlarmDto alarmDto = new AlarmDto(); BeanUtils.copyProperties(zbxProblemInfo, alarmDto); alarmDto.setRClock(zbxProblemInfo.getR_clock()); - if (null != ruleMap.get(Integer.parseInt(zbxProblemInfo.getObjectid()))) { - alarmDto.setName(ruleMap.get(Integer.parseInt(zbxProblemInfo.getObjectid()))); + if (null != ruleMap.get(zbxProblemInfo.getObjectid())) { + alarmDto.setName(ruleMap.get(zbxProblemInfo.getObjectid())); } alarmDtoList.add(alarmDto); }); From cb96c8e05532660928d06ceeb4e44521769cadf1 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 30 Sep 2021 09:11:39 +0800 Subject: [PATCH 412/763] [fix]: fix alarm list --- .../src/main/java/com/zmops/iot/web/auth/AuthService.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java index 236a8599..cbe2c1fb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java @@ -13,6 +13,7 @@ import com.zmops.iot.core.util.SaltUtil; import com.zmops.iot.domain.sys.SysUser; import com.zmops.iot.domain.sys.query.QSysUser; +import com.zmops.iot.message.handler.MessageEventHandler; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.web.constant.state.ManagerStatus; import com.zmops.iot.web.exception.enums.BizExceptionEnum; @@ -50,6 +51,8 @@ public class AuthService { @Autowired private ZbxUser zbxUser; + @Autowired + MessageEventHandler messageEventHandler; /** * 用户名 和 密码 登陆 @@ -94,6 +97,7 @@ public LoginUserDto login(String username, String password) { throw new ServiceException(BizExceptionEnum.ZBX_TOKEN_SAVE_ERROR); } + messageEventHandler.sendDisconnectMsg(user.getUserId() + ""); return LoginUserDto.buildLoginUser(user, login(user)); } From 103ca71a2e2ab6a542c2bb6446a6a8e68c25deba Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 30 Sep 2021 09:23:38 +0800 Subject: [PATCH 413/763] [fix]: fix alarm list --- .../com/zmops/iot/web/alarm/service/AlarmService.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index c507e1ea..99ef44ce 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -102,8 +102,8 @@ public List getAlarmByPage(AlarmParam alarmParam) { if (null != deviceMap.get(zbxProblemInfo.getObjectid())) { alarmDto.setDeviceName(deviceMap.get(zbxProblemInfo.getObjectid())); } - if (null != ruleMap.get(Integer.parseInt(zbxProblemInfo.getObjectid()))) { - alarmDto.setName(ruleMap.get(Integer.parseInt(zbxProblemInfo.getObjectid()))); + if (null != ruleMap.get(zbxProblemInfo.getObjectid())) { + alarmDto.setName(ruleMap.get(zbxProblemInfo.getObjectid())); } alarmDtoList.add(alarmDto); }); @@ -129,8 +129,8 @@ public List getAlarmList(AlarmParam alarmParam) { AlarmDto alarmDto = new AlarmDto(); BeanUtils.copyProperties(zbxProblemInfo, alarmDto); alarmDto.setRClock(zbxProblemInfo.getR_clock()); - if (null != ruleMap.get(Integer.parseInt(zbxProblemInfo.getObjectid()))) { - alarmDto.setName(ruleMap.get(Integer.parseInt(zbxProblemInfo.getObjectid()))); + if (null != ruleMap.get(zbxProblemInfo.getObjectid())) { + alarmDto.setName(ruleMap.get(zbxProblemInfo.getObjectid())); } alarmDtoList.add(alarmDto); }); From 92cc6b8e848e1c92e5b8f0af49954229b47e3389 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 30 Sep 2021 09:33:42 +0800 Subject: [PATCH 414/763] [feat]: add sign in --- .../src/main/java/com/zmops/iot/web/auth/AuthService.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java index cbe2c1fb..30e55e6c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java @@ -2,6 +2,7 @@ import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.convert.Convert; +import com.zmops.iot.constant.ConstantsContext; import com.zmops.iot.core.auth.cache.SessionManager; import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.core.auth.exception.AuthException; @@ -13,6 +14,7 @@ import com.zmops.iot.core.util.SaltUtil; import com.zmops.iot.domain.sys.SysUser; import com.zmops.iot.domain.sys.query.QSysUser; +import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.message.handler.MessageEventHandler; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.web.constant.state.ManagerStatus; @@ -96,8 +98,10 @@ public LoginUserDto login(String username, String password) { if (i == 0) { throw new ServiceException(BizExceptionEnum.ZBX_TOKEN_SAVE_ERROR); } - - messageEventHandler.sendDisconnectMsg(user.getUserId() + ""); + //单点登录 + if (CommonStatus.ENABLE.getCode().equals(ConstantsContext.getConstntsMap().get("ZEUS_SIGN_IN"))) { + messageEventHandler.sendDisconnectMsg(user.getUserId() + ""); + } return LoginUserDto.buildLoginUser(user, login(user)); } From dd26b13dec44c8a794c730c7db2a9c7750bb0d65 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 30 Sep 2021 10:37:08 +0800 Subject: [PATCH 415/763] [fix]: fix alarm --- .../src/main/resources/api-json/item/item.get.ftl | 4 ++-- .../iot/web/alarm/controller/AlarmController.java | 6 ++++-- .../zmops/iot/web/alarm/service/AlarmService.java | 13 ++++++++----- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/zeus-driver/src/main/resources/api-json/item/item.get.ftl b/zeus-driver/src/main/resources/api-json/item/item.get.ftl index 7f5c8d2f..768f3f94 100644 --- a/zeus-driver/src/main/resources/api-json/item/item.get.ftl +++ b/zeus-driver/src/main/resources/api-json/item/item.get.ftl @@ -11,10 +11,10 @@ }, <#if itemId??> - "itemids": "${itemId}", + "itemids": ${itemId}, <#if hostid??> - "hostids": "${hostid}", + "hostids": ${hostid}, "output": [ "itemid", diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java index ed9b9ef6..691ec90d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java @@ -1,6 +1,8 @@ package com.zmops.iot.web.alarm.controller; +import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.alarm.dto.AlarmDto; import com.zmops.iot.web.alarm.dto.param.AlarmParam; import com.zmops.iot.web.alarm.service.AlarmService; import com.zmops.iot.web.auth.Permission; @@ -27,8 +29,8 @@ public class AlarmController { @Permission(code = "alarmList") @RequestMapping("/getAlarmByPage") - public ResponseData getAlarmByPage(@RequestBody AlarmParam alarmParam) { - return ResponseData.success(alarmService.getAlarmByPage(alarmParam)); + public Pager getAlarmByPage(@RequestBody AlarmParam alarmParam) { + return alarmService.getAlarmByPage(alarmParam); } @Permission(code = "alarmList") diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 99ef44ce..03383464 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -7,6 +7,7 @@ import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.query.QProductEvent; import com.zmops.iot.media.AlarmCallback; +import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.alarm.dto.AlarmDto; @@ -43,7 +44,7 @@ public class AlarmService { public void alarm(Map alarmInfo) { String deviceId = alarmInfo.get("hostname"); - String eventRuleId = alarmInfo.get("triggername"); + String eventRuleId = alarmInfo.get("triggerName"); if (ToolUtil.isEmpty(deviceId) || ToolUtil.isEmpty(eventRuleId)) { return; @@ -67,17 +68,19 @@ public void alarm(Map alarmInfo) { } - public List getAlarmByPage(AlarmParam alarmParam) { + public Pager getAlarmByPage(AlarmParam alarmParam) { List zbxProblemInfos = getZbxAlarm(alarmParam); if (ToolUtil.isEmpty(zbxProblemInfos)) { - return Collections.emptyList(); + return new Pager<>(); } //分页 List problemList = zbxProblemInfos.stream() .skip((alarmParam.getPage() - 1) * alarmParam.getMaxRow()) .limit(alarmParam.getMaxRow()).collect(Collectors.toList()); - + if (ToolUtil.isEmpty(problemList)) { + return new Pager<>(Collections.emptyList(),zbxProblemInfos.size()); + } //根据triggerid查询出 所属设备 List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).collect(Collectors.toList()); List deviceList = DB.findDto(DeviceDto.class, "select name,r.zbx_id from device d INNER JOIN (select relation_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.relation_id=d.device_id") @@ -108,7 +111,7 @@ public List getAlarmByPage(AlarmParam alarmParam) { alarmDtoList.add(alarmDto); }); - return alarmDtoList; + return new Pager<>(Collections.emptyList(),zbxProblemInfos.size()); } public List getAlarmList(AlarmParam alarmParam) { From 819587103cac0a1e02f700e474442d8c6a4e4b28 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 30 Sep 2021 11:19:29 +0800 Subject: [PATCH 416/763] [fix]: fix url --- .../com/zmops/iot/web/device/controller/DeviceController.java | 2 +- .../com/zmops/iot/web/product/controller/ProductController.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java index fe14f68b..522adc77 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java @@ -187,7 +187,7 @@ public ResponseData prodValueMapCreate(@RequestBody @Validated(BaseEntity.Create * @return */ @Permission(code = "dev") - @PostMapping("/valuemap/delete") + @PostMapping("/valueMap/delete") public ResponseData prodValueMapDelete(@RequestBody @Validated(BaseEntity.Delete.class) ValueMap valueMap) { String response = deviceService.valueMapDelete(valueMap.getValuemapid()); return ResponseData.success(JSONObject.parseObject(response).getJSONArray("valuemapids").get(0)); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java index 19126340..a9032edd 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java @@ -218,7 +218,7 @@ public ResponseData prodTagCreate(@RequestBody @Valid ProductTag productTag) { * @return */ @Permission(code = "product") - @PostMapping("/valuemap/update") + @PostMapping("/valueMap/update") public ResponseData prodValueMapCreate(@RequestBody @Validated(BaseEntity.Create.class) ValueMap valueMap) { Product product = new QProduct().productId.eq(Long.parseLong(valueMap.getProductId())).findOne(); From 6818428a3a2324e41d3b623ecf11d75e7e35c8e0 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 30 Sep 2021 11:19:55 +0800 Subject: [PATCH 417/763] [fix]: fix nodata img --- .../web/analyse/service/ZbxChartsService.java | 53 ++++++++++++++----- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java index 6509fb4b..e1a399c8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java @@ -2,10 +2,8 @@ import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.product.query.QProductAttribute; -import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.service.ZbxItem; import org.apache.commons.httpclient.HttpClient; @@ -13,6 +11,7 @@ import org.apache.commons.httpclient.methods.PostMethod; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.ClassPathResource; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletResponse; @@ -58,20 +57,36 @@ public class ZbxChartsService { public void getCharts(HttpServletResponse response, String from, String to, List attrIds, String width, String height) { - + OutputStream out = null; if (ToolUtil.isEmpty(COOKIE) || LocalDateTimeUtils.betweenTwoTime(COOKIE_TIME, LocalDateTime.now(), ChronoUnit.DAYS) >= 30) { getCookie(); } List itemids = getItemIds(attrIds); - if (ToolUtil.isEmpty(itemids)) { - throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_NOT_EXISTS); - } - - List itemInfos = JSONObject.parseArray(zbxItem.getItemInfo(itemids.toString(), null), ZbxItemInfo.class); - if (ToolUtil.isEmpty(itemInfos)) { - throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_NOT_EXISTS); + if (!validItemInfo(itemids)) { + try { + ClassPathResource classPathResource = new ClassPathResource("/nodata.jpg"); + InputStream inputStream = classPathResource.getInputStream(); + + response.setContentType("image/jpeg"); + + out = response.getOutputStream(); + out.write(toByteArray(inputStream)); + + out.flush(); + } catch (IOException ioException) { + ioException.printStackTrace(); + } finally { + try { + if (null != out) { + out.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + return; } HttpClient client = new HttpClient(); @@ -84,7 +99,8 @@ public void getCharts(HttpServletResponse response, nameValuePairs[2] = new NameValuePair("width", width); nameValuePairs[3] = new NameValuePair("height", height); - for (int index = 0; index < itemids.size(); index++) { + for ( + int index = 0; index < itemids.size(); index++) { nameValuePairs[4 + index] = new NameValuePair("itemids[" + index + "]", itemids.get(index)); } @@ -92,7 +108,6 @@ public void getCharts(HttpServletResponse response, postMethod.setRequestHeader("Content_Type", "application/json-rpc"); postMethod.setRequestHeader("Cookie", COOKIE); - OutputStream out = null; try { client.executeMethod(postMethod); InputStream responseBody = postMethod.getResponseBodyAsStream(); @@ -102,7 +117,8 @@ public void getCharts(HttpServletResponse response, out.write(toByteArray(responseBody)); out.flush(); - } catch (IOException ioException) { + } catch ( + IOException ioException) { ioException.printStackTrace(); } finally { try { @@ -113,7 +129,18 @@ public void getCharts(HttpServletResponse response, e.printStackTrace(); } } + } + private boolean validItemInfo(List itemids) { + if (ToolUtil.isEmpty(itemids)) { + return false; + } + + List itemInfos = JSONObject.parseArray(zbxItem.getItemInfo(itemids.toString(), null), ZbxItemInfo.class); + if (ToolUtil.isEmpty(itemInfos)) { + return false; + } + return true; } private static byte[] toByteArray(InputStream input) throws IOException { From 5459b6b17d7936d6077114377923ad556b99c544 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 30 Sep 2021 11:37:59 +0800 Subject: [PATCH 418/763] [fix]: fix bug --- .../iot/web/product/service/ProductAttributeEventService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java index b5ee6e7f..aaaf2e68 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -106,7 +106,7 @@ public List list(ProductAttrParam productAttr) { public ProductAttrDto detail(Long attrId) { ProductAttrDto attr = new QProductAttributeEvent().attrId.eq(attrId).asDto(ProductAttrDto.class).findOne(); - if (null == attr.getZbxId()) { + if (attr == null || null == attr.getZbxId()) { return attr; } JSONArray itemInfo = JSONObject.parseArray(zbxItem.getItemInfo(attr.getZbxId(), null)); From d8f5541d0f3fe01198f4cf32eb70d9b296b8943c Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 30 Sep 2021 11:49:12 +0800 Subject: [PATCH 419/763] [style]: optimize variable assignment --- .../com/zmops/iot/web/device/controller/DeviceController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java index 522adc77..48535112 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java @@ -169,7 +169,7 @@ public ResponseData prodValueMapCreate(@RequestBody @Validated(BaseEntity.Create if (null == device) { throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); } - String response = ""; + String response; if (ToolUtil.isEmpty(valueMap.getValuemapid())) { response = deviceService.valueMapCreate(device.getZbxId(), valueMap.getValueMapName(), valueMap.getValueMaps()); } else { From 73e4bb062bfa40ccad3c3a78bc764346680e5495 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 30 Sep 2021 11:49:59 +0800 Subject: [PATCH 420/763] [style]: format code style --- .../com/zmops/iot/web/device/controller/DeviceController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java index 48535112..f7ccd905 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java @@ -142,8 +142,8 @@ public ResponseData valueMapList(@RequestParam("deviceId") String deviceId) { @PostMapping("/tag/update") public ResponseData deviceTagCreate(@RequestBody @Valid ProductTag productTag) { - String deviceId = productTag.getProductId(); - Device device = new QDevice().deviceId.eq(deviceId).findOne(); + String deviceId = productTag.getProductId(); + Device device = new QDevice().deviceId.eq(deviceId).findOne(); if (null == device) { throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); From 2f5233feda4cd929402ea14ad16450f3c8cb72bd Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 30 Sep 2021 13:48:32 +0800 Subject: [PATCH 421/763] [feat]: add nodata img --- zeus-starter/src/main/resources/nodata.jpg | Bin 0 -> 141991 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 zeus-starter/src/main/resources/nodata.jpg diff --git a/zeus-starter/src/main/resources/nodata.jpg b/zeus-starter/src/main/resources/nodata.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b8e6e87e42879c4b3e47a471990359965e2cd460 GIT binary patch literal 141991 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

g6kQPud)-Flbg_{SKF^vLsLU^`#DIrReBdppZO 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 Date: Thu, 30 Sep 2021 14:03:43 +0800 Subject: [PATCH 422/763] [fix]:fix nodata path --- .../src/main/resources/nodata.jpg | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename {zeus-starter => zeus-webapp}/src/main/resources/nodata.jpg (100%) diff --git a/zeus-starter/src/main/resources/nodata.jpg b/zeus-webapp/src/main/resources/nodata.jpg similarity index 100% rename from zeus-starter/src/main/resources/nodata.jpg rename to zeus-webapp/src/main/resources/nodata.jpg From 121b37dfade66de4c7e59f75521fd7fe9c4c9894 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 30 Sep 2021 14:22:01 +0800 Subject: [PATCH 423/763] [style]: format code style --- .../web/analyse/service/ZbxChartsService.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java index e1a399c8..eca08b42 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java @@ -67,7 +67,7 @@ public void getCharts(HttpServletResponse response, if (!validItemInfo(itemids)) { try { ClassPathResource classPathResource = new ClassPathResource("/nodata.jpg"); - InputStream inputStream = classPathResource.getInputStream(); + InputStream inputStream = classPathResource.getInputStream(); response.setContentType("image/jpeg"); @@ -99,8 +99,7 @@ public void getCharts(HttpServletResponse response, nameValuePairs[2] = new NameValuePair("width", width); nameValuePairs[3] = new NameValuePair("height", height); - for ( - int index = 0; index < itemids.size(); index++) { + for (int index = 0; index < itemids.size(); index++) { nameValuePairs[4 + index] = new NameValuePair("itemids[" + index + "]", itemids.get(index)); } @@ -117,8 +116,7 @@ public void getCharts(HttpServletResponse response, out.write(toByteArray(responseBody)); out.flush(); - } catch ( - IOException ioException) { + } catch (IOException ioException) { ioException.printStackTrace(); } finally { try { @@ -147,7 +145,7 @@ private static byte[] toByteArray(InputStream input) throws IOException { ByteArrayOutputStream output = new ByteArrayOutputStream(); byte[] buffer = new byte[4096]; - int n = 0; + int n = 0; while (-1 != (n = input.read(buffer))) { output.write(buffer, 0, n); @@ -165,14 +163,14 @@ private List getItemIds(List attrIds) { * 用户访客 获取cookie */ private void getCookie() { - HttpClient client = new HttpClient(); + HttpClient client = new HttpClient(); PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort + "/zabbix/index.php"); //TODO 使用了一个只读权限的访客用户 - NameValuePair namePair = new NameValuePair("name", "cookie"); - NameValuePair pwdPair = new NameValuePair("password", "cookie"); + NameValuePair namePair = new NameValuePair("name", "cookie"); + NameValuePair pwdPair = new NameValuePair("password", "cookie"); NameValuePair autologinPair = new NameValuePair("autologin", "1"); - NameValuePair enterPair = new NameValuePair("enter", "Sign in"); + NameValuePair enterPair = new NameValuePair("enter", "Sign in"); postMethod.setRequestBody(new NameValuePair[]{namePair, pwdPair, autologinPair, enterPair}); postMethod.setRequestHeader("Content_Type", "application/json"); From 38e07b033ac49fba5bd0b1bde7cc11ce78c2503c Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 30 Sep 2021 14:42:24 +0800 Subject: [PATCH 424/763] [fix]: stop SocketIoServer when springboot is stoped --- .../com/zmops/iot/message/server/SocketIoServer.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/zeus-message/src/main/java/com/zmops/iot/message/server/SocketIoServer.java b/zeus-message/src/main/java/com/zmops/iot/message/server/SocketIoServer.java index 2d1973c2..6d6c515c 100644 --- a/zeus-message/src/main/java/com/zmops/iot/message/server/SocketIoServer.java +++ b/zeus-message/src/main/java/com/zmops/iot/message/server/SocketIoServer.java @@ -6,6 +6,8 @@ import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; +import javax.annotation.PreDestroy; + /** * @author nantian created at 2021/9/26 23:21 */ @@ -21,5 +23,15 @@ public class SocketIoServer implements CommandLineRunner { public void run(String... args) throws Exception { server.start(); } + + /** + * 退出时 销毁 SocketIOServer + * + * @throws Exception + */ + @PreDestroy + public void stop() throws Exception { + server.stop(); + } } From b5847f75b7b4aadf2f0c3820cce7e244b78267a1 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 30 Sep 2021 15:03:06 +0800 Subject: [PATCH 425/763] [fix]: fix product event trigger tag --- .../zmops/iot/web/device/service/DeviceEventRuleService.java | 2 +- .../zmops/iot/web/product/service/ProductEventRuleService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index a0f79f64..2888a65f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -218,7 +218,7 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S productEventRuleDto.setZbxId(productEventRelation.getZbxId()); productEventRuleDto.setTags(tagList.stream() - .filter(s -> s.getTag().equals("__execute__") || s.getTag().equals("__alarm__")) + .filter(s ->!s.getTag().equals("__execute__") && !s.getTag().equals("__alarm__") && !s.getTag().equals("__event__")) .collect(Collectors.toList())); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index 45e2f545..ee8e32de 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -273,7 +273,7 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S productEventRuleDto.setZbxId(productEventRelation.getZbxId()); productEventRuleDto.setTags(tagList.stream() - .filter(s -> s.getTag().equals("__execute__") || s.getTag().equals("__alarm__")) + .filter(s -> !s.getTag().equals("__execute__") && !s.getTag().equals("__alarm__") && !s.getTag().equals("__event__")) .collect(Collectors.toList())); return productEventRuleDto; From e486471547777d740a2becde0b66d4bc0c9d3de1 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 30 Sep 2021 15:39:19 +0800 Subject: [PATCH 426/763] [style]: edit started notice info --- zeus-starter/src/main/java/com/zmops/iot/IoTApplication.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-starter/src/main/java/com/zmops/iot/IoTApplication.java b/zeus-starter/src/main/java/com/zmops/iot/IoTApplication.java index 7d645c88..6867f69d 100644 --- a/zeus-starter/src/main/java/com/zmops/iot/IoTApplication.java +++ b/zeus-starter/src/main/java/com/zmops/iot/IoTApplication.java @@ -22,6 +22,6 @@ public class IoTApplication { public static void main(String[] args) { TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); SpringApplication.run(IoTApplication.class, args); - logger.info(IoTApplication.class.getSimpleName() + " is success!"); + logger.info(IoTApplication.class.getSimpleName() + " webapp started successfully!"); } } From 2881eb3b6003530841a42481cf934faafb8da318 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Thu, 30 Sep 2021 16:45:53 +0800 Subject: [PATCH 427/763] [fix]: update install scripts --- docs/centos/install.sh | 33 ++++----- docs/ubuntu/install.sh | 148 +++++++++++++++++++++++------------------ 2 files changed, 102 insertions(+), 79 deletions(-) diff --git a/docs/centos/install.sh b/docs/centos/install.sh index 940c2eb0..39014c83 100755 --- a/docs/centos/install.sh +++ b/docs/centos/install.sh @@ -1,8 +1,6 @@ #!/usr/bin/env bash -set -e - ROOT_UID=0 release=Centos basename=$(pwd) @@ -22,12 +20,12 @@ function logprint() { # 安装前准备 ## 系统环境检测 if [ "$(uname)" != Linux ]; then - echo "该脚本只使用 Linux 系统" + echo "Error: 该脚本只适用 Linux 系统" exit fi if [ "$UID" -ne "$ROOT_UID" ]; then - echo -e "Error: Must be root to install" + echo -e "Error: 请使用root账户执行安装" exit fi ### 操作系统 @@ -37,8 +35,8 @@ if [ ! -f /etc/redhat-release ]; then fi fi ### 网络 -if ! ping -c 3 mirrors.aliyun.com &>/dev/null; then - echo "网络异常。。。" +if ! ping -c 3 mirrors.tuna.tsinghua.edu.cn &>/dev/null; then + echo "Error: 无法访问外网 。。。" exit fi @@ -48,21 +46,21 @@ memstotal=$(grep 10)printf("%s\t%d\n",$7,$3/1024/1024)}' | grep -v -c "/boot") if [ "$cores" -lt 0 ] || [ "$memstotal" -lt 0 ] || [ "$disks" -eq 0 ]; then - echo "要求最低配置为 CPU 2核 内存 4GB 存储空间 100G" + echo "Error: 要求系统最低配置为 CPU 2核 内存 4GB 存储空间 100G" exit fi ## 系统环境初始化 function InitSystem() { - echo -e -n "\033[32mStep1: 初始化系统安装环境。。。 \033[0m" + echo -e -n "\033[32mStep1: 初始化系统安装环境... \033[0m" if ! hostnamectl set-hostname zeus-server; then - echo "主机名修改失败" + echo "Error: 主机名修改失败" exit fi ### 修改时区 if ! ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime; then - echo "时区修改失败" + echo "Error: 时区修改失败" exit 0 fi @@ -126,7 +124,7 @@ EOL yum clean all 1>/dev/null && yum makecache 1>/dev/null yum -y install java-1.8.0-openjdk expect 1> /dev/null - logprint "yum 源配置失败详细看安装日志输出" + logprint "yum源配置失败" echo -e "\033[32m [ OK ] \033[0m" } @@ -137,7 +135,7 @@ function PGInstall() { postgresql13-devel.x86_64 \ postgresql13-plpython3.x86_64 1>/dev/null - logprint "yum 源配置失败详细看安装日志输出" + logprint "yum安装postgresql失败" ### 创建 PostgreSQL 用户 ### 修改启动文件 @@ -154,7 +152,7 @@ function PGInstall() { sed -i 's/\(^Environment\=PGDATA\=\).*/\1\/opt\/zeus\/pgdata/g' $startfile ### 初始化数据库 /usr/pgsql-13/bin/postgresql-13-setup initdb 1>/dev/null - logprint "初始化错误" + logprint "初始化PG错误" # echo "shared_preload_libraries = 'timescaledb'" >>/opt/zeus/pgdata/postgresql.conf ### 启动数据库 @@ -203,10 +201,10 @@ function ZbxInstall() { --with-openipmi \ --with-openssl \ --with-ssh2 1>/dev/null - logprint "zabbix 编译异常" + logprint "zabbix编译异常" make install 1>/dev/null - logprint "zabbix 编译异常" + logprint "zabbix编译异常" ### 前端内容部署 mv ui $ZABBIX_HOME/zabbix && chown zeus. $ZABBIX_HOME/zabbix -R mv $ZABBIX_HOME/zabbix/conf/zabbix.conf.php.example $ZABBIX_HOME/zabbix/conf/zabbix.conf.php @@ -321,6 +319,10 @@ function WebInstall() { server { listen 80; + location / { + rewrite ^/(.*) http://$host:9090/$1 permanent; + } + location /zabbix { alias $ZABBIX_HOME/zabbix; index index.html index.htm index.php; @@ -406,7 +408,6 @@ function ZeusInstall() { cat ./zeus-iot-bin/bin/sql/zeus-iot.sql | sudo -u postgres psql zeus-iot &>/dev/null logprint "文件未找到" sed -i "s%\(zbxApiToken: \).*%\1$token%" ./zeus-iot-bin/webapp/webapp.yml - sed -i '19i export ZEUS_DB_PASSWORD=zeusiot' ./zeus-iot-bin/bin/startup.sh ./zeus-iot-bin/bin/startup.sh 1> /dev/null echo -e "\033[32m [ OK ] \033[0m" } diff --git a/docs/ubuntu/install.sh b/docs/ubuntu/install.sh index 9f0b60b3..2742cd53 100644 --- a/docs/ubuntu/install.sh +++ b/docs/ubuntu/install.sh @@ -16,7 +16,7 @@ if [ "$(uname)" != Linux ]; then exit $E_BADOD fi -if [ "$UID" -ne "$ROOT_UID" ]; then +if [ "$UID" -ne 0 ]; then echo "Must be root to install" exit $E_NOTROOT fi @@ -45,6 +45,7 @@ fi function InitSystem() { + echo -e -n "\033[32mStep1: 初始化系统安装环境。。。 \033[0m" ## 修改主机名 if ! hostnamectl set-hostname zeus-server; then echo "主机名修改失败" @@ -56,58 +57,48 @@ function InitSystem() { exit 0 fi ## 更新下载源 - mv /etc/apt/sources.list /etc/apt/sources.listbak - tee /etc/apt/sources.list </dev/null -deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse -deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse - -deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse -deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse - -deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse -deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse - -deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse -deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse - -deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse -deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse -EOL + cp /etc/apt/sources.list /etc/apt/sources.listbak + sed -i 's%\(^deb https\:\/\/\).*\(/ubuntu.*\)%\1mirrors.tuna.tsinghua.edu.cn\2%g' /etc/apt/sources.list + echo -e "\033[32m [ OK ] \033[0m" } function AddInstallRepo() { + echo -e -n "\033[32mStep2: 配置安装 YUM 源 。。。 \033[0m" ## 安装PGsql源 - echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -c -s)-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list - wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - - sudo sh -c "echo 'deb https://packagecloud.io/timescale/timescaledb/ubuntu/ $(lsb_release -c -s) main' > /etc/apt/sources.list.d/timescaledb.list" - wget --quiet -O - https://packagecloud.io/timescale/timescaledb/gpgkey | sudo apt-key add - + echo "deb https://mirrors.tuna.tsinghua.edu.cn/postgresql/repos/apt/ $(lsb_release -c -s)-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list &> /dev/null + wget --quiet -O - https://mirrors.tuna.tsinghua.edu.cn/postgresql/repos/apt/ACCC4CF8.asc | sudo apt-key add - + #sudo sh -c "echo 'deb https://packagecloud.io/timescale/timescaledb/ubuntu/ $(lsb_release -c -s) main' > /etc/apt/sources.list.d/timescaledb.list" + #wget --quiet -O - https://packagecloud.io/timescale/timescaledb/gpgkey | sudo apt-key add - ## 安装zabbix 5.4 源 - wget https://repo.zabbix.com/zabbix/5.4/ubuntu/pool/main/z/zabbix-release/zabbix-release_5.4-1+ubuntu20.04_all.deb - dpkg -i zabbix-release_5.4-1+ubuntu20.04_all.deb - apt update - + wget -q https://repo.zabbix.com/zabbix/5.4/ubuntu/pool/main/z/zabbix-release/zabbix-release_5.4-1+ubuntu20.04_all.deb + dpkg -i zabbix-release_5.4-1+ubuntu20.04_all.deb 1> /dev/null + apt update 1> /dev/null && apt install -y openjdk-8-jdk expect 1> /dev/null + echo -e "\033[32m [ OK ] \033[0m" } function PGInstall() { + echo -e -n "\033[32mStep3: 安装 PostgreSQL.... \033[0m" # PG 安装 - apt install timescaledb-2-postgresql-13 -y - echo "shared_preload_libraries = 'timescaledb'" >> /etc/postgresql/13/main/postgresql.conf + apt install postgresql-13 -y 1> /dev/null + #echo "shared_preload_libraries = 'timescaledb'" >> /etc/postgresql/13/main/postgresql.conf cd /tmp || exit - sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD 'zeusiot';" 2> /tmp/pg.log + sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD 'postgres';" 2> /tmp/pg.log systemctl restart postgresql + echo -e "\033[32m [ OK ] \033[0m" } function ZbxInstall() { + echo -e -n "\033[32mStep4: 编译安装 zabbix 。。。 \033[0m" # zabbix 安装 - apt install zabbix-server-pgsql zabbix-frontend-php php7.4-pgsql zabbix-nginx-conf zabbix-sql-scripts zabbix-agent -y + apt install zabbix-server-pgsql zabbix-frontend-php php7.4-pgsql zabbix-nginx-conf zabbix-sql-scripts zabbix-agent -y 1> /dev/null # 初始化 zabbix 配置 cd /tmp || exit sudo -u postgres createuser zabbix sudo -u postgres psql -c "ALTER USER zabbix WITH PASSWORD 'zabbix';" sudo -u postgres createdb -O zabbix zabbix - zcat /usr/share/doc/zabbix-sql-scripts/postgresql/create.sql.gz | sudo -u zabbix psql zabbix - echo "CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;" | sudo -u postgres psql zabbix - cat /usr/share/doc/zabbix-sql-scripts/postgresql/timescaledb.sql | sudo -u zabbix psql zabbix 1>/dev/null + zcat /usr/share/doc/zabbix-sql-scripts/postgresql/create.sql.gz | sudo -u zabbix psql zabbix 1> /dev/null + #echo "CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;" | sudo -u postgres psql zabbix + #cat /usr/share/doc/zabbix-sql-scripts/postgresql/timescaledb.sql | sudo -u zabbix psql zabbix 1>/dev/null sed -i 's/^# DBPassword=/DBPassword=zabbix/g' /etc/zabbix/zabbix_server.conf mv /usr/share/zabbix/conf/zabbix.conf.php.example /usr/share/zabbix/conf/zabbix.conf.php @@ -123,37 +114,13 @@ function ZbxInstall() { sed -i '/sites-enabled/d' /etc/nginx/nginx.conf sed -i '/listen/s/#//' /etc/nginx/conf.d/zabbix.conf sed -i '/listen/s/80/8871/' /etc/nginx/conf.d/zabbix.conf - systemctl restart zabbix-server zabbix-agent nginx php7.4-fpm -} -function ZeusInstall() { - ## 安装web - [ ! -d /opt/zeus ] && mkdir -p /opt/zeus - cd /opt/zeus - wget -c https://packages.zmops.cn/zeus-iot/app-1.0.tar.gz -o /dev/null -O - | tar -xz - wget -c https://packages.zmops.cn/zeus-iot/web-1.0.tar.gz -o /dev/null -O - | tar -xz - wget -c https://packages.zmops.cn/zeus-iot/zeus-iot.sql - sudo -u postgres createdb zeus-iot - cat zeus-iot.sql | sudo -u postgres psql zeus-iot - - # 配置 nginx + # 配置 zabbix web + tee /etc/nginx/conf.d/zeus.conf </dev/null server { listen 80; - - location / { - root /opt/zeus/web; - index index.html; - try_files \$uri \$uri/ /index.html; - } - - location ^~/api/ { - client_body_buffer_size 10m; - proxy_set_header X-Real-IP \$remote_addr; - proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; - proxy_pass http://127.0.0.1:9090/; - } location /zabbix { alias /usr/share/zabbix; index index.html index.htm index.php; @@ -184,13 +151,68 @@ server { } EOL - # 启动 - systemctl restart nginx - cd /opt/zeus/app && ./start.sh + systemctl restart zabbix-server zabbix-agent nginx php7.4-fpm + echo -e "\033[32m [ OK ] \033[0m" +} + + +function gettoken(){ + ## 获取 API 永久 token + local zabbix_api_url=http://127.0.0.1/zabbix/api_jsonrpc.php + local data='{"jsonrpc": "2.0","method": "user.login","params":{"user":"Admin","password":"zabbix"},"id":1,"auth":null}' + local res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $zabbix_api_url"` + local auth=`echo $res | python3 -c 'import sys, json; print(json.load(sys.stdin)["result"])'` + local data='{"jsonrpc": "2.0","method": "token.create","params":{"name":"zeus","userid":"1"},"id":1,"auth":"'${auth}'"}' + local res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $zabbix_api_url"` + local tokenid=`echo $res | python3 -c 'import sys, json; print(json.load(sys.stdin)["result"]["tokenids"][0])'` + local data='{"jsonrpc": "2.0","method": "token.generate","params":["'${tokenid}'"],"id":1,"auth":"'${auth}'"}' + local res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $zabbix_api_url"` + token=`echo $res | python3 -c 'import sys, json; print(json.load(sys.stdin)["result"][0]["token"])'` +} + +function taosinstall() { + ### taos 数据安装 + echo -e -n "\033[32mStep5: 安装 taos 数据库。。。 \033[0m" + wget https://www.taosdata.com/assets-download/TDengine-server-2.2.0.2-Linux-x64.deb + expect << EOF 1> /dev/null + spawn dpkg -i TDengine-server-2.2.0.2-Linux-x64.deb + expect { + "*one:" { send "\n";exp_continue} + "*skip:" { send "\n" } + } +EOF + systemctl enable taosd + systemctl start taosd + echo -e "\033[32m [ OK ] \033[0m" } + + +function ZeusInstall() { + echo -e -n "\033[32mStep6: 安装 Zeus-IoT 服务。。。 \033[0m" + [ ! -d /opt/zeus ] && mkdir -p /opt/zeus + cd /opt/zeus || exit + ## 创建taos 数据库 + taos -s "create database zeus_data" 1> /dev/null + wget -c https://packages.zmops.cn/zeus-iot/zeus-iot-bin.tar.gz -o /dev/null -O - | tar -xz + gettoken + ## 数据库导入 + sudo -u postgres createdb -E Unicode -T template0 zeus-iot + cat ./zeus-iot-bin/bin/sql/zeus-iot.sql | sudo -u postgres psql zeus-iot &>/dev/null + logprint "文件未找到" + sed -i "s%\(zbxApiToken: \).*%\1$token%" ./zeus-iot-bin/webapp/webapp.yml + #sed -i '19i export ZEUS_DB_PASSWORD=zeusiot' ./zeus-iot-bin/bin/startup.sh + ./zeus-iot-bin/bin/startup.sh 1> /dev/null + echo -e "\033[32m [ OK ] \033[0m" +} + + + + InitSystem AddInstallRepo PGInstall ZbxInstall -ZeusInstall \ No newline at end of file +taosinstall +ZeusInstall + From 864d6633d8671ca3598159a3af57bfc23894cb27 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 30 Sep 2021 17:04:53 +0800 Subject: [PATCH 428/763] [fix]: fix bug --- .../service/DeviceEventRuleService.java | 8 +++++++- .../iot/web/device/service/DeviceService.java | 8 ++++---- .../device/service/work/SaveOtherWorker.java | 19 +++++++++++++------ .../device/service/work/SaveTagWorker.java | 2 +- .../web/macro/controller/MacroController.java | 16 ++++++++-------- .../service/ProductEventRuleService.java | 9 +++++++-- 6 files changed, 40 insertions(+), 22 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 2888a65f..7b8c52eb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -205,7 +205,13 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S ProductEventRuleDto productEventRuleDto = new ProductEventRuleDto(); ToolUtil.copyProperties(productEvent, productEventRuleDto); - productEventRuleDto.setExpList(new QProductEventExpression().eventRuleId.eq(eventRuleId).findList()); + List expList = new QProductEventExpression().eventRuleId.eq(eventRuleId).findList(); + expList.forEach(productEventExpression -> { + if (ToolUtil.isEmpty(productEventExpression.getDeviceId())) { + productEventExpression.setDeviceId(deviceId); + } + }); + productEventRuleDto.setExpList(expList); productEventRuleDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).deviceId.eq(deviceId).findList()); ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(deviceId).eventRuleId.eq(eventRuleId).findOne(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index feaf5b04..2a72c459 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -245,12 +245,12 @@ public String create(DeviceDto deviceDto) { WorkerWrapper saveZbxHostWork = WorkerWrapper.builder().id("saveZbxHostWork") .worker(saveZbxHostWorker).param(deviceDto) - .nextOf(updateAttrZbxIdWork, updateDeviceZbxIdWork) + .nextOf(updateAttrZbxIdWork, updateDeviceZbxIdWork,saveOtherWork) .build(); WorkerWrapper deviceWork = WorkerWrapper.builder().id("saveDvice") .worker(saveDeviceWorker).param(deviceDto) - .nextOf(saveTagWork, saveAttributeWork, saveDeviceGrpWork, saveOtherWork, saveZbxHostWork) + .nextOf(saveTagWork, saveAttributeWork, saveDeviceGrpWork, saveZbxHostWork) .build(); try { @@ -297,12 +297,12 @@ public String update(DeviceDto deviceDto) { WorkerWrapper saveZbxHostWork = WorkerWrapper.builder().id("saveZbxHostWork") .worker(saveZbxHostWorker).param(deviceDto) - .nextOf(updateAttrZbxIdWork) + .nextOf(updateAttrZbxIdWork, saveOtherWork) .build(); WorkerWrapper deviceWork = WorkerWrapper.builder().id("saveDvice") .worker(saveDeviceWorker).param(deviceDto) - .nextOf(saveTagWork, saveAttributeWork, saveDeviceGrpWork, saveOtherWork, saveZbxHostWork) + .nextOf(saveTagWork, saveAttributeWork, saveDeviceGrpWork, saveZbxHostWork) .build(); try { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java index 9d248acf..0e62b2eb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java @@ -10,6 +10,7 @@ import com.zmops.iot.domain.product.query.QProductEventService; import com.zmops.iot.domain.product.query.QProductServiceRelation; import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; +import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.iot.web.product.service.ProductEventRuleService; @@ -19,6 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -76,14 +78,19 @@ public Boolean action(DeviceDto deviceDto, Map> allW Map map = triggers.parallelStream().collect(Collectors.toMap(ProductEventRuleService.Triggers::getDescription, ProductEventRuleService.Triggers::getTriggerid)); - List productEventRelationList = new QProductEventRelation().relationId.eq(deviceDto.getProductId() + "").findList(); - + List productEventRelationList = new QProductEventRelation().status.eq(CommonStatus.ENABLE.getCode()).relationId.eq(deviceDto.getProductId() + "").findList(); + List newRelationList = new ArrayList<>(); for (ProductEventRelation productEventRelation : productEventRelationList) { - productEventRelation.setId(null); - productEventRelation.setRelationId(deviceId); - productEventRelation.setInherit("1"); - productEventRelation.setZbxId(productEventRelation.getZbxId()); + ProductEventRelation newEventRelation = new ProductEventRelation(); + newEventRelation.setRelationId(deviceId); + newEventRelation.setInherit("1"); + newEventRelation.setZbxId(map.get(productEventRelation.getEventRuleId() + "")); + newEventRelation.setRemark(productEventRelation.getRemark()); + newEventRelation.setStatus(productEventRelation.getStatus()); + newEventRelation.setEventRuleId(productEventRelation.getEventRuleId()); + newRelationList.add(newEventRelation); } + DB.saveAll(newRelationList); DB.saveAll(productEventRelationList); //告警执行动作关联 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java index a261755a..4c30b2b8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java @@ -43,7 +43,7 @@ public Boolean action(DeviceDto deviceDto, Map> allW } DB.sqlUpdate("insert into tag (sid,tag,value,template_id) SELECT :deviceId,tag,value,id template_id from tag where sid=:sid") - .setParameter("deviceId", deviceId).setParameter("sid", deviceDto.getProductId()).execute(); + .setParameter("deviceId", deviceId).setParameter("sid", deviceDto.getProductId() + "").execute(); return true; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java index 13aeaaae..5f76761f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java @@ -3,6 +3,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.query.QProduct; import com.zmops.iot.model.exception.ServiceException; @@ -86,25 +87,24 @@ public ResponseData updateUserMacro(@Validated(BaseEntity.Update.class) @Request public ResponseData getUserMacro(@Validated(BaseEntity.Get.class) @RequestBody UserMacro userMacro) { // 获取 模板ID 或者 设备ID - String zbxId = new QDevice().select(QDevice.alias().zbxId).deviceId.eq(userMacro.getDeviceId()).findSingleAttribute(); - if (ToolUtil.isEmpty(zbxId)) { + String zbxId = ""; + Device device = new QDevice().deviceId.eq(userMacro.getDeviceId()).findOne(); + if (device != null) { + zbxId = device.getZbxId(); + } else { zbxId = new QProduct().select(QProduct.alias().zbxId).productId.eq(Long.parseLong(userMacro.getDeviceId())).findSingleAttribute(); } + if (ToolUtil.isEmpty(zbxId)) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } // 模板ID - if (ToolUtil.isNotEmpty(zbxId)) { + if (device == null) { List tempMacroList = JSONObject.parseArray(zbxMacro.macroGet(zbxId + ""), UserMacro.class); return ResponseData.success(tempMacroList); } - // 主机ID - if (ToolUtil.isEmpty(zbxId)) { - zbxId = new QDevice().select(QDevice.alias().zbxId).deviceId.eq(userMacro.getDeviceId()).findSingleAttribute(); - } - // 模板IDs List tempListObject = JSON.parseArray(zbxHost.hostTempidGet(userMacro.getDeviceId()), HostQueryTempObject.class); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index ee8e32de..ac4ebcf6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -160,7 +160,7 @@ private ProductEventExpression initEventExpression(ProductEventRule.Expression e eventExpression.setFunction(exp.getFunction()); eventExpression.setScope(exp.getScope()); eventExpression.setValue(exp.getValue()); - eventExpression.setDeviceId(exp.getProductId()); +// eventExpression.setDeviceId(exp.getProductId()); eventExpression.setProductAttrKey(exp.getProductAttrKey()); eventExpression.setProductAttrId(exp.getProductAttrId()); eventExpression.setProductAttrType(exp.getProductAttrType()); @@ -261,7 +261,12 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S ProductEventRuleDto productEventRuleDto = new ProductEventRuleDto(); ToolUtil.copyProperties(productEvent, productEventRuleDto); - productEventRuleDto.setExpList(new QProductEventExpression().eventRuleId.eq(eventRuleId).findList()); + List expList = new QProductEventExpression().eventRuleId.eq(eventRuleId).findList(); + expList.forEach(productEventExpression -> { + if (ToolUtil.isEmpty(productEventExpression.getDeviceId())) { + productEventExpression.setDeviceId(prodId); + } + }); productEventRuleDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).deviceId.isNull().findList()); ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(prodId).eventRuleId.eq(eventRuleId).findOne(); From 937971c500306132090fbd5d56612464b0ac9925 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Thu, 30 Sep 2021 17:05:22 +0800 Subject: [PATCH 429/763] [fix]: fix install script --- docs/centos/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/centos/install.sh b/docs/centos/install.sh index 39014c83..49ab904a 100755 --- a/docs/centos/install.sh +++ b/docs/centos/install.sh @@ -320,7 +320,7 @@ server { listen 80; location / { - rewrite ^/(.*) http://$host:9090/$1 permanent; + rewrite ^/(.*) http://\$host:9090/$1 permanent; } location /zabbix { From 26b4819ee39bed388d55698328359f1fb9bd5b35 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 30 Sep 2021 17:42:40 +0800 Subject: [PATCH 430/763] [fix]: add product attrubite update interval --- .../iot/domain/product/ProductAttribute.java | 4 ++ .../com/zmops/iot/enums/CommonTimeUnit.java | 54 +++++++++++++++++++ .../device/service/DeviceModelService.java | 4 ++ .../iot/web/product/dto/ProductAttr.java | 4 ++ .../iot/web/product/dto/ProductAttrDto.java | 5 +- 5 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/enums/CommonTimeUnit.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java index 9ce8dbdc..b9d7b2c3 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java @@ -42,4 +42,8 @@ public class ProductAttribute extends BaseEntity { private String zbxId; // Zabbix itemId private Long templateId;//继承的ID + + private Integer delay; + + private String unit; } diff --git a/zeus-common/src/main/java/com/zmops/iot/enums/CommonTimeUnit.java b/zeus-common/src/main/java/com/zmops/iot/enums/CommonTimeUnit.java new file mode 100644 index 00000000..1bbff6fe --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/enums/CommonTimeUnit.java @@ -0,0 +1,54 @@ +/** + * Copyright 2018-2020 stylefeng & fengshuonan (https://gitee.com/stylefeng) + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.zmops.iot.enums; + +import lombok.Getter; + +/** + * 公共状态 + * + * @author fengshuonan + */ +public enum CommonTimeUnit { + + S("s", "秒"), + M("m", "分"), + H("h", "小时"), + D("d", "天"); + + @Getter + String code; + @Getter + String message; + + CommonTimeUnit(String code, String message) { + this.code = code; + this.message = message; + } + + public static String getDescription(String status) { + if (status == null) { + return ""; + } else { + for (CommonTimeUnit s : CommonTimeUnit.values()) { + if (s.getCode().equals(status)) { + return s.getMessage(); + } + } + return ""; + } + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index 4a75a0c8..68ea147f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -6,6 +6,7 @@ import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.enums.CommonTimeUnit; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; @@ -69,6 +70,7 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr if (null != map.get(productAttrDto.getAttrId())) { productAttrDto.setClock(map.get(productAttrDto.getAttrId()).getClock()); productAttrDto.setValue(map.get(productAttrDto.getAttrId()).getValue()); + productAttrDto.setDelayName(productAttrDto.getDelay() + CommonTimeUnit.getDescription(productAttrDto.getUnit())); } }); @@ -157,6 +159,8 @@ private ProductAttribute buildProdAttribute(ProductAttribute prodAttribute, Prod prodAttribute.setUnits(productAttr.getUnits()); prodAttribute.setDepAttrId(productAttr.getDepAttrId()); prodAttribute.setValueType(productAttr.getValueType()); + prodAttribute.setDelay(prodAttribute.getDelay()); + prodAttribute.setUnit(prodAttribute.getUnit()); } prodAttribute.setProductId(productAttr.getProductId()); prodAttribute.setRemark(productAttr.getRemark()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java index ef37ed4e..5757ed4d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java @@ -64,6 +64,10 @@ public class ProductAttr { @NotEmpty(groups = BaseEntity.Delete.class) private List attrIds; + private Integer delay; + //取数间隔单位 + private String unit; + LocalDateTime createTime; LocalDateTime updateTime; Long createUser; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java index 1ff13421..90876829 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java @@ -70,5 +70,8 @@ public class ProductAttrDto { private String value; - + private Integer delay; + private String delayName; + //取数间隔单位 + private String unit; } From 5c0e5563528eb0bb8fe80b21f27b389d476d97df Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 30 Sep 2021 18:33:52 +0800 Subject: [PATCH 431/763] [fix]: fix bug --- .../service/DeviceEventRuleService.java | 26 +++++++++++-------- .../iot/web/product/dto/ProductEventDto.java | 3 +++ .../web/product/dto/ProductEventRuleDto.java | 2 ++ .../service/ProductEventRuleService.java | 1 + 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 7b8c52eb..93bc1de3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -123,13 +123,16 @@ public void updateDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { //step 5: 保存触发器 调用 本产品方法 if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { - eventRule.getDeviceServices().forEach(i -> { - DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id, service_id) values (:eventRuleId, :deviceId, :serviceId)") - .setParameter("eventRuleId", eventRuleId) - .setParameter("deviceId", eventRule.getDeviceId()) - .setParameter("executeDeviceId", i.getExecuteDeviceId()) - .setParameter("serviceId", i.getServiceId()) - .execute(); + List deviceIds = eventRule.getExpList().parallelStream().map(DeviceEventRule.Expression::getDeviceId).collect(Collectors.toList()); + deviceIds.forEach(deviceId -> { + eventRule.getDeviceServices().forEach(i -> { + DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id, service_id) values (:eventRuleId, :deviceId, :serviceId)") + .setParameter("eventRuleId", eventRuleId) + .setParameter("deviceId", deviceId) + .setParameter("executeDeviceId", i.getExecuteDeviceId()) + .setParameter("serviceId", i.getServiceId()) + .execute(); + }); }); } @@ -217,14 +220,15 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(deviceId).eventRuleId.eq(eventRuleId).findOne(); productEventRuleDto.setStatus(productEventRelation.getStatus()); productEventRuleDto.setRemark(productEventRelation.getRemark()); + productEventRuleDto.setInherit(productEventRelation.getInherit()); if (null != productEventRelation) { - JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); - List tagList = JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class); + JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); + List tagList = JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class); productEventRuleDto.setZbxId(productEventRelation.getZbxId()); productEventRuleDto.setTags(tagList.stream() - .filter(s ->!s.getTag().equals("__execute__") && !s.getTag().equals("__alarm__") && !s.getTag().equals("__event__")) + .filter(s -> !s.getTag().equals("__execute__") && !s.getTag().equals("__alarm__") && !s.getTag().equals("__event__")) .collect(Collectors.toList())); } @@ -264,7 +268,7 @@ static class TriggerIds { @Data public static class Triggers { - private String triggerid; + private String triggerid; private String description; private List hosts; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java index a5965acc..4f03aed6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java @@ -25,6 +25,9 @@ public class ProductEventDto { @CachedValue(value = "STATUS") private String status; + @CachedValue(value = "WHETHER") + private String inherit; + private String remark; private String classify; private String expLogic; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java index 6fe4ee42..263eb5be 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java @@ -42,6 +42,8 @@ public class ProductEventRuleDto { private String status; + private String inherit; + @Data public static class Tag { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index ac4ebcf6..bbd1763e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -243,6 +243,7 @@ public Pager getEventByPage(EventParm eventParm) { if (null != productEventRelationMap.get(productEventDto.getEventRuleId())) { productEventDto.setStatus(productEventRelationMap.get(productEventDto.getEventRuleId()).getStatus()); productEventDto.setRemark(productEventRelationMap.get(productEventDto.getEventRuleId()).getRemark()); + productEventDto.setIn(productEventRelationMap.get(productEventDto.getEventRuleId()).getStatus()); } }); From eb5d3bdbe509392c79afcd9b624e91c2c1bd9a6b Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 30 Sep 2021 18:46:27 +0800 Subject: [PATCH 432/763] [fix]: fix bug --- .../iot/web/product/service/ProductEventRuleService.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index bbd1763e..5ca976fa 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -47,7 +47,7 @@ public class ProductEventRuleService { /** * 保存触发器 * - * @param eventRule 告警规则 + * @param eventRule 告警规则 */ public void createProductEventRule(ProductEventRule eventRule) { // step 1: 保存产品告警规则 @@ -243,7 +243,7 @@ public Pager getEventByPage(EventParm eventParm) { if (null != productEventRelationMap.get(productEventDto.getEventRuleId())) { productEventDto.setStatus(productEventRelationMap.get(productEventDto.getEventRuleId()).getStatus()); productEventDto.setRemark(productEventRelationMap.get(productEventDto.getEventRuleId()).getRemark()); - productEventDto.setIn(productEventRelationMap.get(productEventDto.getEventRuleId()).getStatus()); + productEventDto.setInherit(productEventRelationMap.get(productEventDto.getEventRuleId()).getInherit()); } }); @@ -268,6 +268,7 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S productEventExpression.setDeviceId(prodId); } }); + productEventRuleDto.setExpList(expList); productEventRuleDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).deviceId.isNull().findList()); ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(prodId).eventRuleId.eq(eventRuleId).findOne(); @@ -293,7 +294,7 @@ static class TriggerIds { @Data public static class Triggers { - private String triggerid; + private String triggerid; private String description; private List hosts; } From ec52dc2a62b78d4709b586d1de2e8df5565b7d1d Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 30 Sep 2021 19:50:43 +0800 Subject: [PATCH 433/763] [fix]: add inherit productId --- .../service/DeviceEventRuleService.java | 19 +++++++++++++------ .../web/product/dto/ProductEventRuleDto.java | 2 ++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 93bc1de3..1b6bbc21 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -63,12 +63,15 @@ public void createDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { //step 3: 保存触发器 调用 本产品方法 if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { - eventRule.getDeviceServices().forEach(i -> { - DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") - .setParameter("eventRuleId", eventRuleId) - .setParameter("executeDeviceId", i.getExecuteDeviceId()) - .setParameter("serviceId", i.getServiceId()) - .execute(); + List deviceIds = eventRule.getExpList().parallelStream().map(DeviceEventRule.Expression::getDeviceId).collect(Collectors.toList()); + deviceIds.forEach(deviceId -> { + eventRule.getDeviceServices().forEach(i -> { + DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") + .setParameter("eventRuleId", eventRuleId) + .setParameter("executeDeviceId", i.getExecuteDeviceId()) + .setParameter("serviceId", i.getServiceId()) + .execute(); + }); }); } @@ -221,6 +224,10 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S productEventRuleDto.setStatus(productEventRelation.getStatus()); productEventRuleDto.setRemark(productEventRelation.getRemark()); productEventRuleDto.setInherit(productEventRelation.getInherit()); + if (InheritStatus.YES.getCode().equals(productEventRelation.getInherit())) { + ProductEventRelation one = new QProductEventRelation().eventRuleId.eq(eventRuleId).inherit.eq(InheritStatus.NO.getCode()).findOne(); + productEventRuleDto.setInheritProductId(one.getRelationId()); + } if (null != productEventRelation) { JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java index 263eb5be..bf2fb074 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java @@ -44,6 +44,8 @@ public class ProductEventRuleDto { private String inherit; + private String inheritProductId; + @Data public static class Tag { From afbc87c908d004eecf4e01f1a722c28deba614ad Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 30 Sep 2021 20:05:16 +0800 Subject: [PATCH 434/763] [fix]: fix bug --- .../zmops/iot/web/device/service/DeviceEventRuleService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 1b6bbc21..3d3a3e0f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -63,7 +63,7 @@ public void createDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { //step 3: 保存触发器 调用 本产品方法 if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { - List deviceIds = eventRule.getExpList().parallelStream().map(DeviceEventRule.Expression::getDeviceId).collect(Collectors.toList()); + List deviceIds = eventRule.getExpList().parallelStream().map(DeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); deviceIds.forEach(deviceId -> { eventRule.getDeviceServices().forEach(i -> { DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") @@ -126,7 +126,7 @@ public void updateDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { //step 5: 保存触发器 调用 本产品方法 if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { - List deviceIds = eventRule.getExpList().parallelStream().map(DeviceEventRule.Expression::getDeviceId).collect(Collectors.toList()); + List deviceIds = eventRule.getExpList().parallelStream().map(DeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); deviceIds.forEach(deviceId -> { eventRule.getDeviceServices().forEach(i -> { DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id, service_id) values (:eventRuleId, :deviceId, :serviceId)") From 10783351207d8f1278d4076aeb16ca3938831d4c Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 30 Sep 2021 20:08:51 +0800 Subject: [PATCH 435/763] [fix]: fix bug --- .../zmops/iot/web/device/service/DeviceEventRuleService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 3d3a3e0f..68027a0c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -18,6 +18,7 @@ import com.zmops.iot.web.product.dto.ProductEventRuleDto; import com.zmops.zeus.driver.service.ZbxTrigger; import io.ebean.DB; +import io.ebean.annotation.Transactional; import lombok.Data; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -44,6 +45,7 @@ public class DeviceEventRuleService { * @param eventRuleId 触发器ID * @param eventRule 告警规则 */ + @Transactional(rollbackFor = Exception.class) public void createDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { // step 1: 保存产品告警规则 ProductEvent event = initEventRule(eventRule); @@ -93,6 +95,7 @@ public void createDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { DB.saveAll(productEventRelationList); } + @Transactional(rollbackFor = Exception.class) public void updateDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { //step 1: 函数表达式 From a619a73b3f747ef06eed179f143d83a529ad2ace Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 30 Sep 2021 20:10:54 +0800 Subject: [PATCH 436/763] [style]: format code style --- .../service/DeviceEventRuleService.java | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 1b6bbc21..85895257 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -66,7 +66,8 @@ public void createDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { List deviceIds = eventRule.getExpList().parallelStream().map(DeviceEventRule.Expression::getDeviceId).collect(Collectors.toList()); deviceIds.forEach(deviceId -> { eventRule.getDeviceServices().forEach(i -> { - DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") + DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) " + + "values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") .setParameter("eventRuleId", eventRuleId) .setParameter("executeDeviceId", i.getExecuteDeviceId()) .setParameter("serviceId", i.getServiceId()) @@ -203,10 +204,16 @@ public void updateProductEventRuleZbxId(Long triggerId, String[] zbxId) { .asUpdate().set("zbxId", map.get(productEventRelation.getRelationId())).update(); } }); - } - + /** + * 获取产品事件规则详情 + * + * @param productEvent + * @param eventRuleId + * @param deviceId + * @return + */ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, String deviceId) { ProductEventRuleDto productEventRuleDto = new ProductEventRuleDto(); ToolUtil.copyProperties(productEvent, productEventRuleDto); @@ -229,15 +236,13 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S productEventRuleDto.setInheritProductId(one.getRelationId()); } - if (null != productEventRelation) { - JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); - List tagList = JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class); + JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); + List tagList = JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class); - productEventRuleDto.setZbxId(productEventRelation.getZbxId()); - productEventRuleDto.setTags(tagList.stream() - .filter(s -> !s.getTag().equals("__execute__") && !s.getTag().equals("__alarm__") && !s.getTag().equals("__event__")) - .collect(Collectors.toList())); - } + productEventRuleDto.setZbxId(productEventRelation.getZbxId()); + productEventRuleDto.setTags(tagList.stream() + .filter(s -> !s.getTag().equals("__execute__") && !s.getTag().equals("__alarm__") && !s.getTag().equals("__event__")) + .collect(Collectors.toList())); return productEventRuleDto; } From eba19cf780cd6b77aaad42b67bbd0d7d065560dc Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 1 Oct 2021 00:47:22 +0800 Subject: [PATCH 437/763] [doc]: edit method doc --- .../zmops/iot/web/macro/controller/MacroController.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java index 5f76761f..6283dcc4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java @@ -42,7 +42,7 @@ public class MacroController { /** * 创建 变量 * - * @return + * @return ResponseData */ @RequestMapping("/create") public ResponseData createUserMacro(@Validated(BaseEntity.Create.class) @RequestBody UserMacro userMacro) { @@ -68,7 +68,7 @@ public ResponseData createUserMacro(@Validated(BaseEntity.Create.class) @Request * 变量更新 * * @param userMacro - * @return + * @return ResponseData */ @RequestMapping("/update") public ResponseData updateUserMacro(@Validated(BaseEntity.Update.class) @RequestBody UserMacro userMacro) { @@ -81,7 +81,7 @@ public ResponseData updateUserMacro(@Validated(BaseEntity.Update.class) @Request * 变量列表 * * @param userMacro - * @return + * @return ResponseData */ @RequestMapping("/list") public ResponseData getUserMacro(@Validated(BaseEntity.Get.class) @RequestBody UserMacro userMacro) { @@ -130,7 +130,7 @@ public ResponseData getUserMacro(@Validated(BaseEntity.Get.class) @RequestBody U * 变量删除 * * @param userMacro - * @return + * @return ResponseData */ @RequestMapping("/delete") public ResponseData deleteUserMacro(@Validated(BaseEntity.Delete.class) @RequestBody UserMacro userMacro) { From cb7daa85ee596b730c76dd56e9a26bdfd6c50130 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 1 Oct 2021 01:00:01 +0800 Subject: [PATCH 438/763] [feat]: updata submodule zeus-iot-ui --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index 1ff4f759..fbbc9353 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit 1ff4f7594885b1cb9e789ff48732c9d955d9ec4f +Subproject commit fbbc93536ea296b77d9934d89dc9614e4d4750d9 From b9b5c6916118f94d9dc017f7a5d0edbafc3fde87 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 1 Oct 2021 21:02:11 +0800 Subject: [PATCH 439/763] [fix]:fix bug --- .../java/com/zmops/iot/web/alarm/service/AlarmService.java | 2 +- .../zmops/iot/web/device/service/DeviceEventRuleService.java | 1 + .../com/zmops/iot/web/device/service/DeviceModelService.java | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 03383464..2b9ac807 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -121,7 +121,7 @@ public List getAlarmList(AlarmParam alarmParam) { if (ToolUtil.isEmpty(problemList)) { return Collections.emptyList(); } - List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Integer::parseInt).collect(Collectors.toList()); + List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Objects::toString).collect(Collectors.toList()); List ruleList = DB.findDto(ProductEventRuleDto.class, "select d.event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id," + "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") .setParameter("zbxIds", triggerIds).findList(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 68027a0c..abf214f5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -70,6 +70,7 @@ public void createDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { eventRule.getDeviceServices().forEach(i -> { DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") .setParameter("eventRuleId", eventRuleId) + .setParameter("deviceId", deviceId) .setParameter("executeDeviceId", i.getExecuteDeviceId()) .setParameter("serviceId", i.getServiceId()) .execute(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index 68ea147f..0d9b1b47 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -66,6 +66,10 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr List latestDtos = latestService.qeuryLatest(productAttr.getProdId(), attrIds); Map map = latestDtos.parallelStream().distinct().collect(Collectors.toMap(LatestDto::getAttrId, o -> o, (a, b) -> b)); + //查询zbx item 信息 + List zbxIds = pagedList.parallelStream().map(ProductAttrDto::getZbxId).collect(Collectors.toList()); +// TODO ERRO zbxItem.getItemInfo(zbxIds.toString()); + pagedList.forEach(productAttrDto -> { if (null != map.get(productAttrDto.getAttrId())) { productAttrDto.setClock(map.get(productAttrDto.getAttrId()).getClock()); From f7b2caaf1205d5b7ca2b90e3f65e295fb15b9b99 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 1 Oct 2021 22:51:10 +0800 Subject: [PATCH 440/763] [fix]: add item unsupport error info --- .../com/zmops/zeus/driver/entity/ZbxItemInfo.java | 2 ++ .../iot/web/device/service/DeviceModelService.java | 13 ++++++++++++- .../zmops/iot/web/product/dto/ProductAttrDto.java | 2 ++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxItemInfo.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxItemInfo.java index 24104465..8d8afbef 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxItemInfo.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxItemInfo.java @@ -28,6 +28,8 @@ public class ZbxItemInfo { private String interfaceid; + private String error; + private List hosts; @Data diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index 0d9b1b47..98a618c5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -17,6 +17,7 @@ import com.zmops.iot.web.product.dto.ProductAttrDto; import com.zmops.iot.web.product.dto.ProductTag; import com.zmops.iot.web.product.dto.param.ProductAttrParam; +import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.entity.ZbxProcessingStep; import com.zmops.zeus.driver.service.ZbxItem; import io.ebean.DB; @@ -61,6 +62,9 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr List pagedList = qProductAttribute.setFirstRow((productAttr.getPage() - 1) * productAttr.getMaxRow()) .setMaxRows(productAttr.getMaxRow()).orderBy(" create_time desc").asDto(ProductAttrDto.class).findList(); + if(ToolUtil.isEmpty(pagedList)){ + return new Pager<>(); + } //查询最新数据 List attrIds = pagedList.parallelStream().map(ProductAttrDto::getAttrId).collect(Collectors.toList()); List latestDtos = latestService.qeuryLatest(productAttr.getProdId(), attrIds); @@ -68,7 +72,11 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr //查询zbx item 信息 List zbxIds = pagedList.parallelStream().map(ProductAttrDto::getZbxId).collect(Collectors.toList()); -// TODO ERRO zbxItem.getItemInfo(zbxIds.toString()); + + String itemInfo = zbxItem.getItemInfo(zbxIds.toString(),null); + List itemInfos = JSONObject.parseArray(itemInfo, ZbxItemInfo.class); + Map errorMap = itemInfos.parallelStream().collect(Collectors.toMap(ZbxItemInfo::getItemid, ZbxItemInfo::getError)); + pagedList.forEach(productAttrDto -> { if (null != map.get(productAttrDto.getAttrId())) { @@ -76,6 +84,9 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr productAttrDto.setValue(map.get(productAttrDto.getAttrId()).getValue()); productAttrDto.setDelayName(productAttrDto.getDelay() + CommonTimeUnit.getDescription(productAttrDto.getUnit())); } + if(null != errorMap.get(productAttrDto.getZbxId())){ + productAttrDto.setError(errorMap.get(productAttrDto.getZbxId())); + } }); int count = qProductAttribute.findCount(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java index 90876829..eb951955 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java @@ -74,4 +74,6 @@ public class ProductAttrDto { private String delayName; //取数间隔单位 private String unit; + + private String error; } From 05c8396931572c3e0e57c5c9bc2aeab9beb098cd Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 1 Oct 2021 23:27:09 +0800 Subject: [PATCH 441/763] [fix]: fix item info --- .../src/main/resources/api-json/item/item.get.ftl | 3 ++- .../iot/web/device/service/DeviceModelService.java | 13 ++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/zeus-driver/src/main/resources/api-json/item/item.get.ftl b/zeus-driver/src/main/resources/api-json/item/item.get.ftl index 768f3f94..7177c6b1 100644 --- a/zeus-driver/src/main/resources/api-json/item/item.get.ftl +++ b/zeus-driver/src/main/resources/api-json/item/item.get.ftl @@ -25,7 +25,8 @@ "value_type", "units", "valuemapid", - "interfaceid" + "interfaceid", + "error" ] }, "auth": "${userAuth}", diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index 98a618c5..6d838b8f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -62,7 +62,7 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr List pagedList = qProductAttribute.setFirstRow((productAttr.getPage() - 1) * productAttr.getMaxRow()) .setMaxRows(productAttr.getMaxRow()).orderBy(" create_time desc").asDto(ProductAttrDto.class).findList(); - if(ToolUtil.isEmpty(pagedList)){ + if (ToolUtil.isEmpty(pagedList)) { return new Pager<>(); } //查询最新数据 @@ -71,12 +71,11 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr Map map = latestDtos.parallelStream().distinct().collect(Collectors.toMap(LatestDto::getAttrId, o -> o, (a, b) -> b)); //查询zbx item 信息 - List zbxIds = pagedList.parallelStream().map(ProductAttrDto::getZbxId).collect(Collectors.toList()); - - String itemInfo = zbxItem.getItemInfo(zbxIds.toString(),null); - List itemInfos = JSONObject.parseArray(itemInfo, ZbxItemInfo.class); - Map errorMap = itemInfos.parallelStream().collect(Collectors.toMap(ZbxItemInfo::getItemid, ZbxItemInfo::getError)); + List zbxIds = pagedList.parallelStream().map(ProductAttrDto::getZbxId).collect(Collectors.toList()); + String itemInfo = zbxItem.getItemInfo(zbxIds.toString(), null); + List itemInfos = JSONObject.parseArray(itemInfo, ZbxItemInfo.class); + Map errorMap = itemInfos.parallelStream().collect(Collectors.toMap(ZbxItemInfo::getItemid, o -> Optional.ofNullable(o.getError()).orElse(""))); pagedList.forEach(productAttrDto -> { if (null != map.get(productAttrDto.getAttrId())) { @@ -84,7 +83,7 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr productAttrDto.setValue(map.get(productAttrDto.getAttrId()).getValue()); productAttrDto.setDelayName(productAttrDto.getDelay() + CommonTimeUnit.getDescription(productAttrDto.getUnit())); } - if(null != errorMap.get(productAttrDto.getZbxId())){ + if (null != errorMap.get(productAttrDto.getZbxId())) { productAttrDto.setError(errorMap.get(productAttrDto.getZbxId())); } }); From 221e82190c95a70d480d9c30a8d463faf82d53e0 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 2 Oct 2021 21:42:36 +0800 Subject: [PATCH 442/763] [fix]: fix tag regexp pattern --- .../java/com/zmops/iot/web/product/dto/ProductTag.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductTag.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductTag.java index b76030d5..1bc0dffe 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductTag.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductTag.java @@ -2,8 +2,11 @@ import lombok.Data; +import javax.validation.Valid; import javax.validation.constraints.Max; import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; import java.util.List; /** @@ -18,15 +21,18 @@ public class ProductTag { @NotNull private String productId; + @Valid private List productTag; @Data public static class Tag { - @Max(20) + @Size(max = 20) + @Pattern(regexp = "^[A-Za-z0-9]+$", + message = "标签名称不能包含中文、特殊字符") private String tag; - @Max(50) + @Size(max = 50) private String value; } } From f6ddb2530a3dc22bff8e0a33f9acb3966b7a9db9 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 2 Oct 2021 22:22:41 +0800 Subject: [PATCH 443/763] [fix]: handle tdengine rest execute error --- .../zeus/driver/service/TDEngineRest.java | 3 +- .../iot/web/analyse/service/HomeService.java | 107 +++++++++++------- .../device/schedule/SyncTaosTagSchedule.java | 31 ++--- 3 files changed, 84 insertions(+), 57 deletions(-) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java index a2456cb2..5907097b 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java @@ -4,6 +4,7 @@ import com.dtflys.forest.annotation.Body; import com.dtflys.forest.annotation.Post; import com.dtflys.forest.extensions.BasicAuth; +import com.dtflys.forest.http.ForestResponse; /** * @author yefei @@ -23,5 +24,5 @@ public interface TDEngineRest { contentType = "application/json;charset=utf-8" ) @BasicAuth(username = "${taosUser}", password = "${taosPwd}") - String executeSql(@Body String sql); + ForestResponse executeSql(@Body String sql); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index 26336e46..e315bb78 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -2,6 +2,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import com.dtflys.forest.http.ForestResponse; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.DeviceOnlineReport; import com.zmops.iot.domain.device.ServiceExecuteRecord; @@ -59,7 +60,7 @@ public class HomeService { private static String hostId = ""; - private static Map ITEM_Map = new ConcurrentHashMap<>(5); + private static final Map ITEM_Map = new ConcurrentHashMap<>(5); //Zbx 指标取数速率 key private static final String KEY = "zabbix[wcache,values"; @@ -80,6 +81,7 @@ public List> collectionRate(long timeFrom, long timeTill) { return Collections.emptyList(); } } + List latestDtos = new ArrayList<>(); ITEM_Map.forEach((key, value) -> { latestDtos.addAll(historyService.queryHitoryData(hostId, Collections.singletonList(key), 10000, 0, timeFrom, timeTill)); @@ -91,20 +93,25 @@ public List> collectionRate(long timeFrom, long timeTill) { latestDto.setName(ITEM_Map.get(latestDto.getItemid())); } }); + Map> collect = latestDtos.parallelStream().collect( - Collectors.groupingBy(LatestDto::getName, Collectors.groupingBy(LatestDto::getClock, Collectors.averagingDouble(o -> Double.parseDouble(o.getValue())))) + Collectors.groupingBy(LatestDto::getName, Collectors.groupingBy( + LatestDto::getClock, Collectors.averagingDouble(o -> Double.parseDouble(o.getValue())))) ); + List> collectList = new ArrayList<>(); collect.forEach((key, value) -> { - Map collectMap = new HashMap<>(2); - List> tmpList = new ArrayList<>(); + Map collectMap = new HashMap<>(2); + List> tmpList = new ArrayList<>(); value.forEach((date, val) -> { Map valMap = new HashMap<>(2); valMap.put("date", date); valMap.put("val", val); tmpList.add(valMap); }); - List> dataList = tmpList.parallelStream().sorted(Comparator.comparing(o -> o.get("date").toString())).collect(Collectors.toList()); + List> dataList = tmpList.parallelStream().sorted( + Comparator.comparing(o -> o.get("date").toString())).collect(Collectors.toList()); + collectMap.put("name", ValueType.getVal(key)); collectMap.put("data", dataList); collectList.add(collectMap); @@ -119,8 +126,8 @@ public List> collectionRate(long timeFrom, long timeTill) { * @return */ private String getZbxServerId() { - String response = zbxHost.hostGet("Zabbix server"); - List> ids = JSON.parseObject(response, List.class); + String response = zbxHost.hostGet("Zabbix server"); + List> ids = JSON.parseObject(response, List.class); if (null != ids && ids.size() > 0) { hostId = ids.get(0).get("hostid"); return hostId; @@ -134,7 +141,7 @@ private String getZbxServerId() { * @return */ private Map getItemMap() { - String itemList = zbxItem.getItemList(KEY, hostId); + String itemList = zbxItem.getItemList(KEY, hostId); List itemInfos = JSONObject.parseArray(itemList, ZbxItemInfo.class); for (ZbxItemInfo itemInfo : itemInfos) { ITEM_Map.put(itemInfo.getItemid(), formatName(itemInfo.getName())); @@ -168,9 +175,12 @@ public Map getDeviceNum(Integer timeFrom, Integer timeTill) { deviceNumMap.put("disable", (int) list.parallelStream().filter(o -> "DISABLE".equals(o.getStatus())).count()); deviceNumMap.put("product", new QProduct().findCount()); - List onLineList = new QDeviceOnlineReport().createTime.ge(LocalDateTimeUtils.convertTimeToString(timeFrom, "yyyy-MM-dd")).createTime.lt(LocalDateTimeUtils.convertTimeToString(timeTill, "yyyy-MM-dd")).findList(); + List onLineList = new QDeviceOnlineReport() + .createTime.ge(LocalDateTimeUtils.convertTimeToString(timeFrom, "yyyy-MM-dd")) + .createTime.lt(LocalDateTimeUtils.convertTimeToString(timeTill, "yyyy-MM-dd")).findList(); - Map collect = onLineList.parallelStream().collect(Collectors.groupingBy(DeviceOnlineReport::getCreateTime, Collectors.summingLong(DeviceOnlineReport::getOnline))); + Map collect = onLineList.parallelStream() + .collect(Collectors.groupingBy(DeviceOnlineReport::getCreateTime, Collectors.summingLong(DeviceOnlineReport::getOnline))); List> trendsList = new ArrayList<>(); @@ -196,7 +206,7 @@ public Map getAlarmNum(long timeFrom, long timeTill) { AlarmParam alarmParam = new AlarmParam(); alarmParam.setRecent("false"); List alarmList = alarmService.getZbxAlarm(alarmParam); - Map alarmMap = new ConcurrentHashMap<>(3); + Map alarmMap = new ConcurrentHashMap<>(3); if (ToolUtil.isNotEmpty(alarmList)) { @@ -208,21 +218,21 @@ public Map getAlarmNum(long timeFrom, long timeTill) { && Long.parseLong(o.getClock()) >= timeFrom && Long.parseLong(o.getClock()) < timeTill ).collect( - Collectors.groupingBy(ZbxProblemInfo::getSeverity, - Collectors.groupingBy(o -> LocalDateTimeUtils.convertTimeToString(Integer.parseInt(o.getClock()), "yyyy-MM-dd"), Collectors.counting() - ) - ) - ); + Collectors.groupingBy(ZbxProblemInfo::getSeverity, Collectors.groupingBy( + o -> LocalDateTimeUtils.convertTimeToString(Integer.parseInt(o.getClock()), "yyyy-MM-dd"), Collectors.counting()))); + List> trendsList = new ArrayList<>(); tmpMap.forEach((key, value) -> { Map trendsMap = new ConcurrentHashMap<>(2); - List list = new ArrayList<>(); + + List list = new ArrayList<>(); value.forEach((date, val) -> { Map valMap = new ConcurrentHashMap<>(2); valMap.put("date", date); valMap.put("val", val); list.add(valMap); }); + trendsMap.put("name", severity[Integer.parseInt(key)]); trendsMap.put("data", list); trendsList.add(trendsMap); @@ -232,11 +242,11 @@ public Map getAlarmNum(long timeFrom, long timeTill) { //今日开始时间 - Long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); + Long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); AlarmParam todayParam = new AlarmParam(); todayParam.setTimeFrom(timeStart); List todayAlarmList = alarmService.getZbxAlarm(todayParam); - Long todayAlarmNum = todayAlarmList.parallelStream().filter(o -> !o.getSeverity().equals("0")).count(); + Long todayAlarmNum = todayAlarmList.parallelStream().filter(o -> !o.getSeverity().equals("0")).count(); alarmMap.put("today", todayAlarmNum); return alarmMap; @@ -246,9 +256,9 @@ public Map getAlarmNum(long timeFrom, long timeTill) { * 事件数量统计 */ public Map getEventNum(long timeFrom, long timeTill) { - AlarmParam alarmParam = new AlarmParam(); - List alarmList = alarmService.getEventProblem(alarmParam); - Map alarmMap = new ConcurrentHashMap<>(3); + AlarmParam alarmParam = new AlarmParam(); + List alarmList = alarmService.getEventProblem(alarmParam); + Map alarmMap = new ConcurrentHashMap<>(3); if (ToolUtil.isNotEmpty(alarmList)) { @@ -260,35 +270,36 @@ public Map getEventNum(long timeFrom, long timeTill) { && Long.parseLong(o.getClock()) >= timeFrom && Long.parseLong(o.getClock()) < timeTill ).collect( - Collectors.groupingBy(ZbxProblemInfo::getSeverity, - Collectors.groupingBy(o -> LocalDateTimeUtils.convertTimeToString(Integer.parseInt(o.getClock()), "yyyy-MM-dd"), Collectors.counting() - ) - ) - ); + Collectors.groupingBy(ZbxProblemInfo::getSeverity, Collectors.groupingBy( + o -> LocalDateTimeUtils.convertTimeToString(Integer.parseInt(o.getClock()), "yyyy-MM-dd"), Collectors.counting()))); + List> trendsList = new ArrayList<>(); + tmpMap.forEach((key, value) -> { Map trendsMap = new ConcurrentHashMap<>(2); - List list = new ArrayList<>(); + List list = new ArrayList<>(); value.forEach((date, val) -> { Map valMap = new ConcurrentHashMap<>(2); valMap.put("date", date); valMap.put("val", val); list.add(valMap); }); + trendsMap.put("name", severity[Integer.parseInt(key)]); trendsMap.put("data", list); trendsList.add(trendsMap); }); + alarmMap.put("trends", trendsList); } //今日开始时间 - Long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); + Long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); AlarmParam todayParam = new AlarmParam(); todayParam.setTimeFrom(timeStart); List todayAlarmList = alarmService.getZbxAlarm(todayParam); - Long todayAlarmNum = todayAlarmList.parallelStream().count(); + Long todayAlarmNum = todayAlarmList.parallelStream().count(); alarmMap.put("today", todayAlarmNum); return alarmMap; @@ -302,13 +313,17 @@ public List> getAlarmTop(long timeFrom, long timeTill) { alarmParam.setTimeTill(timeTill); alarmParam.setTimeFrom(timeFrom); List alarmList = alarmService.getZbxAlarm(alarmParam); - Map tmpMap = new ConcurrentHashMap<>(); + Map tmpMap = new ConcurrentHashMap<>(); if (ToolUtil.isNotEmpty(alarmList)) { - List triggerIds = alarmList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Objects::toString).collect(Collectors.toList()); - List deviceList = DB.findDto(DeviceDto.class, "select name,r.zbx_id from device d INNER JOIN (select relation_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.relation_id=d.device_id") + List triggerIds = alarmList.parallelStream() + .map(ZbxProblemInfo::getObjectid).map(Objects::toString).collect(Collectors.toList()); + + List deviceList = DB.findDto(DeviceDto.class, + "select name,r.zbx_id from device d INNER JOIN (select relation_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.relation_id=d.device_id") .setParameter("zbxIds", triggerIds).findList(); + Map deviceMap = deviceList.parallelStream().collect(Collectors.toMap(DeviceDto::getZbxId, DeviceDto::getName)); @@ -362,7 +377,7 @@ public Map serviceExecuteNum(long timeFrom, long timeTill) { } //今日开始时间 long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); - long todayNum = new QServiceExecuteRecord().createTime.ge(LocalDateTimeUtils.getLDTBySeconds((int) timeStart)).findCount(); + long todayNum = new QServiceExecuteRecord().createTime.ge(LocalDateTimeUtils.getLDTBySeconds((int) timeStart)).findCount(); executeMap.put("today", todayNum); return executeMap; @@ -376,7 +391,8 @@ public Map dataLevel() { Map dataMap = new ConcurrentHashMap<>(4); dataMap.put("totalRecordNum", ParseUtil.getCommaFormat(getRecordNum() + "")); - dataMap.put("todayRecordNum", ParseUtil.getCommaFormat(getTodayRecordNum(LocalDateTimeUtils.formatTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now()))) + "")); + dataMap.put("todayRecordNum", ParseUtil.getCommaFormat(getTodayRecordNum( + LocalDateTimeUtils.formatTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now()))) + "")); int serviceExecuteNum = new QServiceExecuteRecord().findCount(); dataMap.put("serviceExecuteNum", ParseUtil.getCommaFormat(serviceExecuteNum + "")); @@ -385,8 +401,8 @@ public Map dataLevel() { } private int getRecordNum() { - int totalRecord = 0; - String sql = "select count(1) from history"; + int totalRecord = 0; + String sql = "select count(1) from history"; totalRecord += getRecordNum(sql); sql = "select count(1) from history_uint"; @@ -396,8 +412,8 @@ private int getRecordNum() { } private int getTodayRecordNum(String time) { - int totalRecord = 0; - String sql = "select count(1) from history where clock>'" + time + "'"; + int totalRecord = 0; + String sql = "select count(1) from history where clock>'" + time + "'"; totalRecord += getRecordNum(sql); sql = "select count(1) from history_uint where clock>'" + time + "'"; @@ -407,9 +423,16 @@ private int getTodayRecordNum(String time) { } private int getRecordNum(String sql) { - String res_history = tdEngineRest.executeSql(sql); - TaosResponseData taosResponseData = JSON.parseObject(res_history, TaosResponseData.class); - String[][] data_history = taosResponseData.getData(); + ForestResponse res_history = tdEngineRest.executeSql(sql); + + if (res_history.isError()) { + return 0; + } + + String res = res_history.getContent(); + + TaosResponseData taosResponseData = JSON.parseObject(res, TaosResponseData.class); + String[][] data_history = taosResponseData.getData(); if (data_history.length > 0) { return Integer.parseInt(data_history[0][0]); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java index 37f95864..1527fd29 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java @@ -1,6 +1,7 @@ package com.zmops.iot.web.device.schedule; import com.alibaba.fastjson.JSON; +import com.dtflys.forest.http.ForestResponse; import com.zmops.iot.domain.device.Tag; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.device.query.QTag; @@ -38,15 +39,21 @@ public class SyncTaosTagSchedule { // @Scheduled(cron = "0 0/1 * * * ? ") public void sync() { List deviceIds = new QDevice().select(QDevice.alias().deviceId).findSingleAttributeList(); - List tagList = new QTag().sid.in(deviceIds).findList(); + List tagList = new QTag().sid.in(deviceIds).findList(); if (ToolUtil.isEmpty(tagList)) { return; } - Map> tagMap = tagList.parallelStream().collect(Collectors.groupingBy(Tag::getSid)); - String describe = tdEngineRest.executeSql("DESCRIBE history;"); + Map> tagMap = tagList.parallelStream().collect(Collectors.groupingBy(Tag::getSid)); + + ForestResponse res_history = tdEngineRest.executeSql("DESCRIBE history;"); + if (res_history.isError()) { + return; + } + + String describe = res_history.getContent(); TaosResponseData taosResponseData = JSON.parseObject(describe, TaosResponseData.class); - String[][] data = taosResponseData.getData(); + String[][] data = taosResponseData.getData(); List taosTagNames = new ArrayList<>(); for (String[] datum : data) { @@ -82,16 +89,14 @@ public void sync() { } private void delTaosTag(List list1, List list2) { - List tagNames = list2; - List taosTagNames = list1; - taosTagNames.removeAll(tagNames); + list1.removeAll(list2); - if (ToolUtil.isEmpty(taosTagNames)) { + if (ToolUtil.isEmpty(list1)) { return; } - taosTagNames.forEach(tagName -> { + list1.forEach(tagName -> { if ("deviceid".equals(tagName) || "itemid".equals(tagName)) { return; } @@ -101,15 +106,13 @@ private void delTaosTag(List list1, List list2) { } private void addTaosTag(List list1, List list2) { - List tagNames = list1; - List taosTagNames = list2; - tagNames.removeAll(taosTagNames); - if (ToolUtil.isEmpty(tagNames)) { + list1.removeAll(list2); + if (ToolUtil.isEmpty(list1)) { return; } - tagNames.forEach(tagName -> { + list1.forEach(tagName -> { tdEngineRest.executeSql("ALTER STABLE history_uint ADD TAG " + tagName + " NCHAR(16)"); tdEngineRest.executeSql("ALTER STABLE history ADD TAG " + tagName + " NCHAR(16)"); }); From b2c96c07052487d441eda7e433e6cd4c1e1b0bb3 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 2 Oct 2021 23:24:15 +0800 Subject: [PATCH 444/763] [fix]: fix ftl --- zeus-driver/src/main/resources/api-json/host/host.get.ftl | 2 +- zeus-driver/src/main/resources/api-json/host/host.update.ftl | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/zeus-driver/src/main/resources/api-json/host/host.get.ftl b/zeus-driver/src/main/resources/api-json/host/host.get.ftl index 46db7fa3..dddb023e 100644 --- a/zeus-driver/src/main/resources/api-json/host/host.get.ftl +++ b/zeus-driver/src/main/resources/api-json/host/host.get.ftl @@ -2,7 +2,7 @@ "jsonrpc": "2.0", "method": "host.get", "params": { - <#if groupids??> + <#if host??> "filter": { "host":${host} }, diff --git a/zeus-driver/src/main/resources/api-json/host/host.update.ftl b/zeus-driver/src/main/resources/api-json/host/host.update.ftl index 946f3787..1a9eb0db 100644 --- a/zeus-driver/src/main/resources/api-json/host/host.update.ftl +++ b/zeus-driver/src/main/resources/api-json/host/host.update.ftl @@ -2,8 +2,7 @@ "jsonrpc": "2.0", "method": "host.update", "params": { - "hostid":"${hostid}" - "host": "${hostName}", + "hostid":"${hostid}", "groups": [ <#if groupids??> <#list groupids as groupid> From 62bba262e4cc74726c1c83263bbab5890c281419 Mon Sep 17 00:00:00 2001 From: nantian Date: Sun, 3 Oct 2021 00:17:15 +0800 Subject: [PATCH 445/763] [fix]: update host.get ftl format --- .../src/main/resources/api-json/host/host.get.ftl | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/zeus-driver/src/main/resources/api-json/host/host.get.ftl b/zeus-driver/src/main/resources/api-json/host/host.get.ftl index 46db7fa3..771b6dde 100644 --- a/zeus-driver/src/main/resources/api-json/host/host.get.ftl +++ b/zeus-driver/src/main/resources/api-json/host/host.get.ftl @@ -2,19 +2,20 @@ "jsonrpc": "2.0", "method": "host.get", "params": { - <#if groupids??> - "filter": { - "host":${host} - }, + <#if host??> + "filter": { + "host": "${host}" + }, <#if hostid??> - "hostids":${hostid}, + "hostids": "${hostid}", "output": "extend", "selectTags":"extend", "selectMacros":"extend", - "selectValueMaps":"extend" - }, + "selectValueMaps":"extend", + "selectInterface":"extend" + }, "auth": "${userAuth}", "id": 1 } \ No newline at end of file From a765c1446542a06180064968a12b377a414c0ef9 Mon Sep 17 00:00:00 2001 From: yefei Date: Sun, 3 Oct 2021 00:47:15 +0800 Subject: [PATCH 446/763] [fix]: fix user reset pwd --- .../com/zmops/zeus/driver/service/ZbxUser.java | 11 +++++++++++ .../resources/api-json/user/userUpdatePwd.ftl | 10 ++++++++++ .../iot/web/sys/controller/SysUserController.java | 5 +---- .../zmops/iot/web/sys/service/SysUserService.java | 15 ++++++++++++++- 4 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 zeus-driver/src/main/resources/api-json/user/userUpdatePwd.ftl diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java index 97697261..69b58d64 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java @@ -69,4 +69,15 @@ String userUpdate(@ParamName("userId") String userId, @Post @JsonPath("/user/userDelete") String userDelete(@ParamName("usrids") List usrids); + + /** + * 用户修改密码 + * + * @param userId 用户id + * @param passwd 用户组ID + * @return 用户信息 + */ + @Post + @JsonPath("/user/userUpdatePwd") + String updatePwd(@ParamName("userId") String userId, @ParamName("passwd") String passwd); } diff --git a/zeus-driver/src/main/resources/api-json/user/userUpdatePwd.ftl b/zeus-driver/src/main/resources/api-json/user/userUpdatePwd.ftl new file mode 100644 index 00000000..c2730823 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/user/userUpdatePwd.ftl @@ -0,0 +1,10 @@ +{ + "jsonrpc": "2.0", + "method": "user.update", + "params": { + "userid": "${userId}", + "passwd": "${passwd}" + }, + "id": 1, + "auth": "${userAuth}" +} \ No newline at end of file diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java index 64b583c9..9ee976d1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java @@ -98,10 +98,7 @@ public ResponseData changePwd(@Valid @RequestBody UserParam user) { @RequestMapping("/reset") @BussinessLog(value = "重置密码") public ResponseData reset(@RequestParam("userId") Long userId) { - SysUser user = new QSysUser().userId.eq(userId).findOne(); - user.setSalt(SaltUtil.getRandomSalt()); - user.setPassword(SaltUtil.md5Encrypt(ConstantsContext.getDefaultPassword(), user.getSalt())); - DB.update(user); + sysUserService.reset(userId); return ResponseData.success(); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java index 907d5300..250ab1fd 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java @@ -220,10 +220,11 @@ public void changePwd(String oldPassword, String newPassword) { throw new ServiceException(AuthExceptionEnum.NOT_LOGIN_ERROR); } SysUser user = new QSysUser().userId.eq(loginUser.getId()).findOne(); - + String rawNewPasswd=""; try { oldPassword = new String(Hex.decodeHex(oldPassword)); newPassword = new String(Hex.decodeHex(newPassword)); + rawNewPasswd = newPassword; } catch (Exception e) { throw new ServiceException(BizExceptionEnum.PWD_DECRYPT_ERR); } @@ -234,6 +235,8 @@ public void changePwd(String oldPassword, String newPassword) { newPassword = SaltUtil.md5Encrypt(newPassword, user.getSalt()); user.setPassword(newPassword); DB.update(user); + + zbxUser.updatePwd(user.getZbxId(),rawNewPasswd); } else { throw new ServiceException(BizExceptionEnum.OLD_PWD_NOT_RIGHT); } @@ -247,4 +250,14 @@ public void updateUserCache() { public void run(String... args) throws Exception { updateUserCache(); } + + + public void reset(Long userId) { + SysUser user = new QSysUser().userId.eq(userId).findOne(); + user.setSalt(SaltUtil.getRandomSalt()); + user.setPassword(SaltUtil.md5Encrypt(ConstantsContext.getDefaultPassword(), user.getSalt())); + DB.update(user); + + zbxUser.updatePwd(user.getZbxId(),ConstantsContext.getDefaultPassword()); + } } From bfc1cd5d845574459777630245dd0043c472a7de Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 7 Oct 2021 19:43:11 +0800 Subject: [PATCH 447/763] [feat]: update zeus-iot-ui module --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index fbbc9353..c458b02a 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit fbbc93536ea296b77d9934d89dc9614e4d4750d9 +Subproject commit c458b02a9ea1c1583925fce1b439509a78102824 From 3ab0bfa565699ab65e99fe24957136701336f30d Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 8 Oct 2021 12:10:59 +0800 Subject: [PATCH 448/763] [fix]: get zbx data before delete zbx data --- .../zeus/driver/entity/ZbxHostGrpInfo.java | 14 ++++++++++++++ .../zeus/driver/entity/ZbxUserGrpInfo.java | 14 ++++++++++++++ .../zmops/zeus/driver/entity/ZbxUserInfo.java | 17 +++++++++++++++++ .../zmops/zeus/driver/service/ZbxHostGroup.java | 11 ++++++++++- .../zmops/zeus/driver/service/ZbxTemplate.java | 11 ++++++++++- .../com/zmops/zeus/driver/service/ZbxUser.java | 9 +++++++++ .../zmops/zeus/driver/service/ZbxUserGroup.java | 4 ++++ .../api-json/hostgroup/hostgroup.delete.ftl | 2 +- .../api-json/hostgroup/hostgroup.get.ftl | 10 ++++++++++ .../api-json/problem/problem.event.get.ftl | 2 +- .../api-json/role/superAdminRole.get.ftl | 12 ++++++++++++ .../api-json/template/template.detail.get.ftl | 13 +++++++++++++ .../api-json/template/template.get.ftl | 3 --- .../main/resources/api-json/user/userGet.ftl | 10 ++++++++++ .../api-json/usergroup/userGroupGet.ftl | 10 ++++++++++ .../iot/web/alarm/service/AlarmService.java | 17 +++++++++++------ .../iot/web/analyse/service/HomeService.java | 3 +-- .../DeviceEventTriggerController.java | 16 +++++++++++----- .../web/device/service/DeviceGroupService.java | 8 +++++++- .../web/device/service/DeviceModelService.java | 7 ++++++- .../iot/web/device/service/DeviceService.java | 9 +++++++-- .../ProductEventTriggerController.java | 15 +++++++++------ .../service/ProductAttributeEventService.java | 8 +++++++- .../product/service/ProductModelService.java | 8 +++++++- .../iot/web/product/service/ProductService.java | 7 ++++++- .../web/sys/service/SysUserGroupService.java | 11 +++++++++-- .../iot/web/sys/service/SysUserService.java | 17 ++++++++++++----- 27 files changed, 228 insertions(+), 40 deletions(-) create mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxHostGrpInfo.java create mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxUserGrpInfo.java create mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxUserInfo.java create mode 100644 zeus-driver/src/main/resources/api-json/hostgroup/hostgroup.get.ftl create mode 100644 zeus-driver/src/main/resources/api-json/role/superAdminRole.get.ftl create mode 100644 zeus-driver/src/main/resources/api-json/template/template.detail.get.ftl create mode 100644 zeus-driver/src/main/resources/api-json/user/userGet.ftl diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxHostGrpInfo.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxHostGrpInfo.java new file mode 100644 index 00000000..1189309c --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxHostGrpInfo.java @@ -0,0 +1,14 @@ +package com.zmops.zeus.driver.entity; + +import lombok.Data; + +/** + * @author yefei + */ +@Data +public class ZbxHostGrpInfo { + + private String groupid; + private String name; + +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxUserGrpInfo.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxUserGrpInfo.java new file mode 100644 index 00000000..f3f283b5 --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxUserGrpInfo.java @@ -0,0 +1,14 @@ +package com.zmops.zeus.driver.entity; + +import lombok.Data; + +/** + * @author yefei + */ +@Data +public class ZbxUserGrpInfo { + + private String usrgrpid; + private String name; + +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxUserInfo.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxUserInfo.java new file mode 100644 index 00000000..543e19e2 --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxUserInfo.java @@ -0,0 +1,17 @@ +package com.zmops.zeus.driver.entity; + +import lombok.Data; + +/** + * @author yefei + */ +@Data +public class ZbxUserInfo { + + private String userid; + private String username; + private String name; + private String surname; + private String roleid; + +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java index 2061088e..bd54a0ff 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java @@ -59,5 +59,14 @@ public interface ZbxHostGroup { */ @Post @JsonPath("/hostgroup/hostgroup.delete") - String hostGroupDelete(@ParamName("hostgGroupIds") List hostGrpIds); + String hostGroupDelete(@ParamName("hostGroupIds") List hostGrpIds); + + /** + * 获取 主机组 + * + * @return String + */ + @Post + @JsonPath("/hostgroup/hostgroup.get") + String getHostGroup(@ParamName("groupids") String groupids); } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java index 41a4d2cf..f39b44ef 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java @@ -59,6 +59,15 @@ String templateTagUpdate(@ParamName("templateId") String templateId, * @param templateid 模板ID */ @Post - @JsonPath("/template/template.get") + @JsonPath("/template/template.detail.get") String templateDetail(@ParamName("templateid") String templateid); + + /** + * 查询模板信息 + * + * @param templateid 模板ID + */ + @Post + @JsonPath("/template/template.get") + String templateGet(@ParamName("templateid") String templateid); } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java index 69b58d64..bb7d3ef1 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java @@ -80,4 +80,13 @@ String userUpdate(@ParamName("userId") String userId, @Post @JsonPath("/user/userUpdatePwd") String updatePwd(@ParamName("userId") String userId, @ParamName("passwd") String passwd); + + /** + * 用户查询 + * + * @return + */ + @Post + @JsonPath("/user/getUser") + String getUser(@ParamName("userIds") String userIds); } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java index 271881c2..6bb08bd8 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java @@ -53,4 +53,8 @@ public interface ZbxUserGroup { @JsonPath("/usergroup/userGroupBindHostGroup") String userGrpBindHostGroup(@ParamName("hostGroupIds") List hostGroupIds, @ParamName("userGroupId") String userGroupId); + + @Post + @JsonPath("/usergroup/userGroupGet") + String getUserGrp(@ParamName("usrgrpids") String usrgrpids); } diff --git a/zeus-driver/src/main/resources/api-json/hostgroup/hostgroup.delete.ftl b/zeus-driver/src/main/resources/api-json/hostgroup/hostgroup.delete.ftl index e180a868..ac62e0a4 100644 --- a/zeus-driver/src/main/resources/api-json/hostgroup/hostgroup.delete.ftl +++ b/zeus-driver/src/main/resources/api-json/hostgroup/hostgroup.delete.ftl @@ -3,7 +3,7 @@ "method": "hostgroup.delete", "params": [ <#if hostgGroupIds??> - <#list hostgGroupIds as hostgroupid> + <#list hostGroupIds as hostgroupid> "${hostgroupid}"<#if hostgroupid_has_next>, diff --git a/zeus-driver/src/main/resources/api-json/hostgroup/hostgroup.get.ftl b/zeus-driver/src/main/resources/api-json/hostgroup/hostgroup.get.ftl new file mode 100644 index 00000000..b4b18385 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/hostgroup/hostgroup.get.ftl @@ -0,0 +1,10 @@ +{ + "jsonrpc": "2.0", + "method": "hostgroup.get", + "params": { + "output": "extend", + "groupids": ${groupids} + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/problem/problem.event.get.ftl b/zeus-driver/src/main/resources/api-json/problem/problem.event.get.ftl index 9b0b0692..e56b375f 100644 --- a/zeus-driver/src/main/resources/api-json/problem/problem.event.get.ftl +++ b/zeus-driver/src/main/resources/api-json/problem/problem.event.get.ftl @@ -7,7 +7,7 @@ "recent": ${recent}, "sortfield": ["eventid"], <#if hostId??> - "hostids":"${hostId}", + "hostids":${hostId}, <#if timeFrom??> "time_from":${timeFrom}, diff --git a/zeus-driver/src/main/resources/api-json/role/superAdminRole.get.ftl b/zeus-driver/src/main/resources/api-json/role/superAdminRole.get.ftl new file mode 100644 index 00000000..62fc5472 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/role/superAdminRole.get.ftl @@ -0,0 +1,12 @@ +{ + "jsonrpc": "2.0", + "method": "role.get", + "params": { + "output": "extend", + "filter": { + "name":"Super admin role" + } + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/template/template.detail.get.ftl b/zeus-driver/src/main/resources/api-json/template/template.detail.get.ftl new file mode 100644 index 00000000..5620acb4 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/template/template.detail.get.ftl @@ -0,0 +1,13 @@ +{ + "jsonrpc": "2.0", + "method": "template.get", + "params": { + "output": "extend", + "selectTags":"extend", + "selectMacros":"extend", + "selectValueMaps":"extend", + "templateids":${templateid} + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/template/template.get.ftl b/zeus-driver/src/main/resources/api-json/template/template.get.ftl index 5620acb4..82809eb9 100644 --- a/zeus-driver/src/main/resources/api-json/template/template.get.ftl +++ b/zeus-driver/src/main/resources/api-json/template/template.get.ftl @@ -3,9 +3,6 @@ "method": "template.get", "params": { "output": "extend", - "selectTags":"extend", - "selectMacros":"extend", - "selectValueMaps":"extend", "templateids":${templateid} }, "auth": "${userAuth}", diff --git a/zeus-driver/src/main/resources/api-json/user/userGet.ftl b/zeus-driver/src/main/resources/api-json/user/userGet.ftl new file mode 100644 index 00000000..8571ef25 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/user/userGet.ftl @@ -0,0 +1,10 @@ +{ + "jsonrpc": "2.0", + "method": "user.get", + "params": { + "output": "extend", + "userids": ${userids} + }, + "id": 1, + "auth": "${userAuth}" +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/usergroup/userGroupGet.ftl b/zeus-driver/src/main/resources/api-json/usergroup/userGroupGet.ftl index e69de29b..575304a7 100644 --- a/zeus-driver/src/main/resources/api-json/usergroup/userGroupGet.ftl +++ b/zeus-driver/src/main/resources/api-json/usergroup/userGroupGet.ftl @@ -0,0 +1,10 @@ +{ + "jsonrpc": "2.0", + "method": "usergroup.get", + "params": { + "output": "extend", + "usrgrpids": ${usrgrpids} + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 2b9ac807..d2e8e32e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -192,13 +192,18 @@ public List getEventList(AlarmParam alarmParam) { public List getEventProblem(AlarmParam alarmParam) { String hostId = null; - if (null != alarmParam.getDeviceId()) { - Device one = new QDevice().deviceId.eq(alarmParam.getDeviceId()).findOne(); - if (null == one) { - return Collections.EMPTY_LIST; - } - hostId = one.getZbxId(); + List deviceIds; + if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { + deviceIds = Collections.singletonList(alarmParam.getDeviceId()); + } else { + deviceIds = deviceService.getDeviceIds(); } + + List zbxIds = new QDevice().select(QDevice.alias().zbxId).deviceId.in(deviceIds).findSingleAttributeList(); + if (ToolUtil.isEmpty(zbxIds)) { + return Collections.EMPTY_LIST; + } + hostId = zbxIds.toString(); //从zbx取告警记录 String problem = zbxProblem.getEventProblem(hostId, alarmParam.getTimeFrom(), alarmParam.getTimeTill(), alarmParam.getRecent()); return JSONObject.parseArray(problem, ZbxProblemInfo.class); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index e315bb78..2ef5873b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -168,11 +168,10 @@ private static String formatName(String name) { public Map getDeviceNum(Integer timeFrom, Integer timeTill) { Map deviceNumMap = new HashMap<>(4); - deviceNumMap.put("online", 0); - List list = new QDevice().findList(); deviceNumMap.put("total", list.size()); deviceNumMap.put("disable", (int) list.parallelStream().filter(o -> "DISABLE".equals(o.getStatus())).count()); + deviceNumMap.put("online", (int) list.parallelStream().filter(o -> "1".equals(o.getOnline())).count()); deviceNumMap.put("product", new QProduct().findCount()); List onLineList = new QDeviceOnlineReport() diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index fbc2c6cd..4cc0da0c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -1,6 +1,7 @@ package com.zmops.iot.web.device.controller; import cn.hutool.core.util.IdUtil; +import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.ProductEventRelation; @@ -23,9 +24,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -210,6 +209,14 @@ public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseE if (InheritStatus.YES.getCode().equals(productEventRelation.getInherit())) { throw new ServiceException(BizExceptionEnum.EVENT_PRODUCT_CANNOT_DELETE); } + //step 01:删除 zbx触发器 + if(ToolUtil.isNotEmpty(productEventRelation.getZbxId())){ + List triggers = JSONObject.parseArray(zbxTrigger.triggerGet(productEventRelation.getZbxId()), DeviceEventRuleService.Triggers.class); + if(ToolUtil.isNotEmpty(triggers)) { + zbxTrigger.triggerDelete(productEventRelation.getZbxId()); + } + } + //step 1:删除 与设备的关联 new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); @@ -223,8 +230,7 @@ public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseE //step 4:删除 触发器 new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).delete(); - //step 5:删除 zbx触发器 - zbxTrigger.triggerDelete(productEventRelation.getZbxId()); + return ResponseData.success(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java index e2b917c8..2f5843bb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java @@ -14,6 +14,7 @@ import com.zmops.iot.web.device.dto.DeviceGroupDto; import com.zmops.iot.web.device.dto.param.DeviceGroupParam; import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.zeus.driver.entity.ZbxHostGrpInfo; import com.zmops.zeus.driver.service.ZbxHostGroup; import io.ebean.DB; import io.ebean.PagedList; @@ -178,7 +179,12 @@ public void deleteDeviceGroup(DeviceGroupParam deviceGroupParam) { //删除ZBX中主机组 List zbxHostGrpIds = list.parallelStream().map(DeviceGroup::getZbxId).collect(Collectors.toList()); - zbxHostGroup.hostGroupDelete(zbxHostGrpIds); + if (ToolUtil.isNotEmpty(zbxHostGrpIds)) { + List zbxHostGrpInfos = JSONObject.parseArray(zbxHostGroup.getHostGroup(zbxHostGrpIds.toString()), ZbxHostGrpInfo.class); + if (ToolUtil.isNotEmpty(zbxHostGrpInfos)) { + zbxHostGroup.hostGroupDelete(zbxHostGrpInfos.parallelStream().map(ZbxHostGrpInfo::getGroupid).collect(Collectors.toList())); + } + } // 删除 与用户组关联 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index 6d838b8f..bb712789 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -270,7 +270,12 @@ public void deleteTrapperItem(ProductAttr productAttr) { List zbxIds = new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(productAttr.getAttrIds()).findSingleAttributeList(); //删除zbx item - zbxItem.deleteTrapperItem(zbxIds); + if (ToolUtil.isNotEmpty(zbxIds)) { + List itemInfos = JSONObject.parseArray(zbxItem.getItemInfo(zbxIds.toString(), null), ZbxItemInfo.class); + if (ToolUtil.isNotEmpty(itemInfos)) { + zbxItem.deleteTrapperItem(itemInfos.parallelStream().map(ZbxItemInfo::getItemid).collect(Collectors.toList())); + } + } //删除 属性 new QProductAttribute().attrId.in(productAttr.getAttrIds()).delete(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 2a72c459..b49b66da 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -245,7 +245,7 @@ public String create(DeviceDto deviceDto) { WorkerWrapper saveZbxHostWork = WorkerWrapper.builder().id("saveZbxHostWork") .worker(saveZbxHostWorker).param(deviceDto) - .nextOf(updateAttrZbxIdWork, updateDeviceZbxIdWork,saveOtherWork) + .nextOf(updateAttrZbxIdWork, updateDeviceZbxIdWork, saveOtherWork) .build(); WorkerWrapper deviceWork = WorkerWrapper.builder().id("saveDvice") @@ -354,7 +354,12 @@ public String delete(DeviceDto deviceDto) { WorkerWrapper delZbxWork = WorkerWrapper.builder().id("delZbxWork") .worker((zbxid, allWrappers) -> { - zbxHost.hostDelete(Collections.singletonList(zbxid)); + if (ToolUtil.isNotEmpty(zbxid)) { + JSONArray jsonArray = JSONObject.parseArray(zbxHost.hostDetail(zbxId)); + if (jsonArray.size() > 0) { + zbxHost.hostDelete(Collections.singletonList(zbxid)); + } + } return true; }).param(zbxId).build(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index 8eb81fdd..0718a0f8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -1,6 +1,7 @@ package com.zmops.iot.web.product.controller; import cn.hutool.core.util.IdUtil; +import com.alibaba.fastjson.JSONObject; import com.zmops.iot.async.executor.Async; import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.BaseEntity; @@ -28,10 +29,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -231,6 +229,13 @@ public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseE if (null == productEventRelation) { return ResponseData.success(); } + //step 01:删除 zbx触发器 + String s = zbxTrigger.triggerGet(productEventRelation.getZbxId()); + List triggers = JSONObject.parseArray(s, ProductEventRuleService.Triggers.class); + if(ToolUtil.isNotEmpty(triggers)){ + zbxTrigger.triggerDelete(productEventRelation.getZbxId()); + } + //step 1:删除 与产品 设备的关联 new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); @@ -243,9 +248,7 @@ public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseE //step 4:删除 触发器 new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).delete(); - //step 5:删除 zbx触发器 - zbxTrigger.triggerDelete(productEventRelation.getZbxId()); return ResponseData.success(); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java index aaaf2e68..be9f826e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -23,6 +23,7 @@ import com.zmops.iot.web.product.service.work.SaveProdAttrEventTriggerWorker; import com.zmops.iot.web.product.service.work.SaveProdAttrEventWorker; import com.zmops.iot.web.product.service.work.UpdateAttributeEventWorker; +import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.entity.ZbxProcessingStep; import com.zmops.zeus.driver.service.ZbxItem; import io.ebean.DB; @@ -280,7 +281,12 @@ public void deleteTrapperItem(ProductAttrEvent productAttr) { List zbxIds = new QProductAttributeEvent().select(QProductAttributeEvent.alias().zbxId).attrId.in(productAttr.getAttrIds()).findSingleAttributeList(); //删除zbx item - zbxItem.deleteTrapperItem(zbxIds); + if (ToolUtil.isNotEmpty(zbxIds)) { + List itemInfos = JSONObject.parseArray(zbxItem.getItemInfo(zbxIds.toString(), null), ZbxItemInfo.class); + if (ToolUtil.isNotEmpty(itemInfos)) { + zbxItem.deleteTrapperItem(itemInfos.parallelStream().map(ZbxItemInfo::getItemid).collect(Collectors.toList())); + } + } //删除 属性 new QProductAttributeEvent().attrId.in(productAttr.getAttrIds()).delete(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index 67254c29..a570cb92 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -19,6 +19,7 @@ import com.zmops.iot.web.product.service.work.AsyncAttrZbxIdWorker; import com.zmops.iot.web.product.service.work.SaveProdAttrWorker; import com.zmops.iot.web.product.service.work.UpdateAttributeWorker; +import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.entity.ZbxProcessingStep; import com.zmops.zeus.driver.service.ZbxItem; import io.ebean.DB; @@ -268,7 +269,12 @@ public void deleteTrapperItem(ProductAttr productAttr) { List zbxIds = new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(productAttr.getAttrIds()).findSingleAttributeList(); //删除zbx item - zbxItem.deleteTrapperItem(zbxIds); + if (ToolUtil.isNotEmpty(zbxIds)) { + List itemInfos = JSONObject.parseArray(zbxItem.getItemInfo(zbxIds.toString(), null), ZbxItemInfo.class); + if (ToolUtil.isNotEmpty(itemInfos)) { + zbxItem.deleteTrapperItem(itemInfos.parallelStream().map(ZbxItemInfo::getItemid).collect(Collectors.toList())); + } + } //删除 属性 new QProductAttribute().attrId.in(productAttr.getAttrIds()).delete(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java index f5f3fb29..47249b7f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java @@ -120,7 +120,12 @@ public String zbxTemplateCreate(String templateName) { * @return */ public String zbxTemplateDelete(String templdateId) { - return zbxTemplate.templateDelete(templdateId); + + JSONArray jsonArray = JSONObject.parseArray(zbxTemplate.templateGet(templdateId)); + if (jsonArray.size() > 0) { + zbxTemplate.templateDelete(templdateId); + } + return templdateId; } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java index 282a4e64..21dcc00f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java @@ -17,6 +17,7 @@ import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.sys.dto.UserGroupDto; import com.zmops.iot.web.sys.dto.param.UserGroupParam; +import com.zmops.zeus.driver.entity.ZbxUserGrpInfo; import com.zmops.zeus.driver.service.ZbxUserGroup; import io.ebean.DB; import io.ebean.DtoQuery; @@ -164,8 +165,14 @@ public void deleteUserGroup(UserGroupParam userGroupParam) { } List zbxUsrGrpIds = list.parallelStream().map(SysUserGroup::getZbxId).collect(Collectors.toList()); - zbxUserGroup.userGrpDelete(zbxUsrGrpIds); + //删除 zbx 用户组数据 + if (ToolUtil.isNotEmpty(zbxUsrGrpIds)) { + List zbxUserGrpList = JSONObject.parseArray(zbxUserGroup.getUserGrp(zbxUsrGrpIds.toString()), ZbxUserGrpInfo.class); + if (ToolUtil.isNotEmpty(zbxUserGrpList)) { + zbxUserGroup.userGrpDelete(zbxUserGrpList.parallelStream().map(ZbxUserGrpInfo::getUsrgrpid).collect(Collectors.toList())); + } + } // 删除 与设备组关联 new QSysUserGrpDevGrp().userGroupId.in(userGroupParam.getUserGroupIds()).delete(); new QSysUserGroup().userGroupId.in(userGroupParam.getUserGroupIds()).delete(); @@ -181,7 +188,7 @@ public String getZabUsrGrpId(Long usrGrpId) { } return usrGrp.getZbxId(); } - + /** * 用户组绑定设备组 * diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java index 250ab1fd..4be219dc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java @@ -18,6 +18,7 @@ import com.zmops.iot.web.sys.dto.UserDto; import com.zmops.iot.web.sys.dto.param.UserParam; import com.zmops.iot.web.sys.factory.UserFactory; +import com.zmops.zeus.driver.entity.ZbxUserInfo; import com.zmops.zeus.driver.service.ZbxUser; import io.ebean.DB; import io.ebean.DtoQuery; @@ -177,8 +178,14 @@ public void deleteUser(UserParam user) { throw new ServiceException(BizExceptionEnum.USER_NOT_EXIST); } List zbxIds = list.parallelStream().map(SysUser::getZbxId).collect(Collectors.toList()); - zbxUser.userDelete(zbxIds); + //删除 zbx 用户数据 + if (ToolUtil.isNotEmpty(zbxIds)) { + List zbxUserList = JSONObject.parseArray(zbxUser.getUser(zbxIds.toString()), ZbxUserInfo.class); + if (ToolUtil.isNotEmpty(zbxUserList)) { + zbxUser.userDelete(zbxUserList.parallelStream().map(ZbxUserInfo::getUserid).collect(Collectors.toList())); + } + } new QSysUser().userId.in(user.getUserIds()).delete(); updateUserCache(); } @@ -219,8 +226,8 @@ public void changePwd(String oldPassword, String newPassword) { if (null == loginUser) { throw new ServiceException(AuthExceptionEnum.NOT_LOGIN_ERROR); } - SysUser user = new QSysUser().userId.eq(loginUser.getId()).findOne(); - String rawNewPasswd=""; + SysUser user = new QSysUser().userId.eq(loginUser.getId()).findOne(); + String rawNewPasswd = ""; try { oldPassword = new String(Hex.decodeHex(oldPassword)); newPassword = new String(Hex.decodeHex(newPassword)); @@ -236,7 +243,7 @@ public void changePwd(String oldPassword, String newPassword) { user.setPassword(newPassword); DB.update(user); - zbxUser.updatePwd(user.getZbxId(),rawNewPasswd); + zbxUser.updatePwd(user.getZbxId(), rawNewPasswd); } else { throw new ServiceException(BizExceptionEnum.OLD_PWD_NOT_RIGHT); } @@ -258,6 +265,6 @@ public void reset(Long userId) { user.setPassword(SaltUtil.md5Encrypt(ConstantsContext.getDefaultPassword(), user.getSalt())); DB.update(user); - zbxUser.updatePwd(user.getZbxId(),ConstantsContext.getDefaultPassword()); + zbxUser.updatePwd(user.getZbxId(), ConstantsContext.getDefaultPassword()); } } From b9684e6fd86c42c267152aaaff17195282f60f33 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 8 Oct 2021 15:06:40 +0800 Subject: [PATCH 449/763] [fix]: fix alarm --- .../com/zmops/iot/web/alarm/service/AlarmService.java | 9 ++++----- .../iot/web/device/service/work/DeviceOnlineWorker.java | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index d2e8e32e..e988460c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -58,13 +58,12 @@ public void alarm(Map alarmInfo) { if (null != device && null != productEvent) { String alarmmessage = "设备:" + device.getName() + "发生告警,告警内容:" + productEvent.getEventRuleName(); alarmMessages.add(AlarmMessage.builder().alarmMessage(alarmmessage).build()); - } - - alarmCallbacks.forEach(alarmCallback -> { + alarmCallbacks.forEach(alarmCallback -> { // if (alarmCallback.getType().equals("welink")) { - alarmCallback.doAlarm(alarmMessages); + alarmCallback.doAlarm(alarmMessages); // } - }); + }); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java index bc5231cc..8920c995 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java @@ -29,7 +29,7 @@ public Boolean action(Map param, Map if (ToolUtil.isEmpty(deviceId)) { return false; } - Device device = new QDevice().deviceId.eq(deviceId).findSingleAttribute(); + Device device = new QDevice().deviceId.eq(deviceId).findOne(); if (null == device) { return false; } @@ -38,8 +38,8 @@ public Boolean action(Map param, Map if (ToolUtil.isNotEmpty(recovery) && "RESOLVED".equals(recovery)) { status = 1; } - device.setOnline(status); - DB.update(device); + DB.update(Device.class).where().eq("deviceId", device.getDeviceId()).asUpdate() + .set("online", status).update(); return true; } From df607454e8cdc813c117f1d78bdd22483a9ff183 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 8 Oct 2021 16:26:44 +0800 Subject: [PATCH 450/763] [feat]: add device latest online time --- .../src/main/java/com/zmops/iot/domain/device/Device.java | 3 +++ zeus-driver/src/main/resources/api-json/user/userAdd.ftl | 1 + .../src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java | 2 ++ .../java/com/zmops/iot/web/device/service/DeviceService.java | 2 ++ .../zmops/iot/web/device/service/work/DeviceOnlineWorker.java | 3 ++- 5 files changed, 10 insertions(+), 1 deletion(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java index 75fba808..e3905e38 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java @@ -8,6 +8,7 @@ import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; +import java.time.LocalDateTime; /** * @author yefei @@ -39,6 +40,8 @@ public class Device extends BaseEntity { private Integer online; + private LocalDateTime latestOnline; + @Aggregation("count(*)") Long totalCount; } diff --git a/zeus-driver/src/main/resources/api-json/user/userAdd.ftl b/zeus-driver/src/main/resources/api-json/user/userAdd.ftl index 940b08be..7f122bc1 100644 --- a/zeus-driver/src/main/resources/api-json/user/userAdd.ftl +++ b/zeus-driver/src/main/resources/api-json/user/userAdd.ftl @@ -5,6 +5,7 @@ "username": "${name}", "passwd": "${password}", "roleid": "${roleId}", + "autologout":"0s", "usrgrps": [ { "usrgrpid": "${usrGrpId}" diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java index 52d2ffdb..d0bace1e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java @@ -68,4 +68,6 @@ public class DeviceDto { private Integer online; + private LocalDateTime latestOnline; + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index b49b66da..1f19ba41 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -193,6 +193,8 @@ private StringBuilder generateBaseSql() { " d.addr, " + " d.position, " + " d.online," + + " d.zbx_id," + + " d.latest_online," + " P.NAME product_name, " + " ds.group_name, " + " ds.groupIds " + diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java index 8920c995..44dc2b6a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java @@ -10,6 +10,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import java.time.LocalDateTime; import java.util.Map; /** @@ -39,7 +40,7 @@ public Boolean action(Map param, Map status = 1; } DB.update(Device.class).where().eq("deviceId", device.getDeviceId()).asUpdate() - .set("online", status).update(); + .set("online", status).set("latestOnline", LocalDateTime.now()).update(); return true; } From 3ea8c08ef18c74729bf23700a1c55f135e081e0e Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 8 Oct 2021 16:30:20 +0800 Subject: [PATCH 451/763] [fix]: fix product service filter --- .../iot/web/product/controller/ProductServiceController.java | 4 ++-- .../com/zmops/iot/web/product/dto/param/ProductSvcParam.java | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java index 15ad33f6..9ce78322 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java @@ -30,7 +30,7 @@ public class ProductServiceController { * 服务分页列表 */ @RequestMapping("/getServiceByPage") - public Pager getServiceByPage(@RequestBody ProductSvcParam productSvcParam) { + public Pager getServiceByPage(@Validated @RequestBody ProductSvcParam productSvcParam) { return productSvcService.getServiceByPage(productSvcParam); } @@ -38,7 +38,7 @@ public Pager getServiceByPage(@RequestBody ProductSvcParam pr * 服务列表 */ @RequestMapping("/list") - public ResponseData list(@RequestBody ProductSvcParam productSvcParam) { + public ResponseData list(@Validated @RequestBody ProductSvcParam productSvcParam) { return ResponseData.success(productSvcService.list(productSvcParam)); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductSvcParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductSvcParam.java index 5bd81535..05788077 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductSvcParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductSvcParam.java @@ -3,6 +3,8 @@ import com.zmops.iot.web.sys.dto.param.BaseQueryParam; import lombok.Data; +import javax.validation.constraints.NotBlank; + /** * @author yefei **/ @@ -13,5 +15,6 @@ public class ProductSvcParam extends BaseQueryParam { private String mark; + @NotBlank private String prodId; } From b018bdf3dedcd058547404220a61c143220cb7b8 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 8 Oct 2021 18:51:42 +0800 Subject: [PATCH 452/763] [fix]: fix bug --- .../java/com/zmops/zeus/driver/service/ZbxUser.java | 4 ++-- .../api-json/hostgroup/hostgroup.delete.ftl | 2 +- .../zmops/iot/web/alarm/service/AlarmService.java | 2 +- .../web/product/controller/ProductController.java | 7 ++----- .../controller/ProductEventTriggerController.java | 12 ++++++++---- .../web/product/service/ProductEventRuleService.java | 2 +- .../iot/web/product/service/ProductService.java | 3 +-- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java index bb7d3ef1..a40f6de8 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java @@ -87,6 +87,6 @@ String userUpdate(@ParamName("userId") String userId, * @return */ @Post - @JsonPath("/user/getUser") - String getUser(@ParamName("userIds") String userIds); + @JsonPath("/user/userGet") + String getUser(@ParamName("userids") String userIds); } diff --git a/zeus-driver/src/main/resources/api-json/hostgroup/hostgroup.delete.ftl b/zeus-driver/src/main/resources/api-json/hostgroup/hostgroup.delete.ftl index ac62e0a4..dff9fab3 100644 --- a/zeus-driver/src/main/resources/api-json/hostgroup/hostgroup.delete.ftl +++ b/zeus-driver/src/main/resources/api-json/hostgroup/hostgroup.delete.ftl @@ -2,7 +2,7 @@ "jsonrpc": "2.0", "method": "hostgroup.delete", "params": [ - <#if hostgGroupIds??> + <#if hostGroupIds??> <#list hostGroupIds as hostgroupid> "${hostgroupid}"<#if hostgroupid_has_next>, diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index e988460c..c79f8184 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -110,7 +110,7 @@ public Pager getAlarmByPage(AlarmParam alarmParam) { alarmDtoList.add(alarmDto); }); - return new Pager<>(Collections.emptyList(),zbxProblemInfos.size()); + return new Pager<>(alarmDtoList,zbxProblemInfos.size()); } public List getAlarmList(AlarmParam alarmParam) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java index a9032edd..fc4716d8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java @@ -159,11 +159,8 @@ public ResponseData prodDelete(@RequestBody @Validated(value = BaseEntity.Delete //第二步:删除Zabbix对应的模板 - String response = productService.zbxTemplateDelete(product.getZbxId() + ""); - String templateId = JSON.parseObject(response, TemplateIds.class).getTemplateids()[0]; - if (templateId.equals(product.getZbxId())) { - log.info("产品模板删除成功,ID:{}", templateId); - } + productService.zbxTemplateDelete(product.getZbxId() + ""); + //第三步:删除产品 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index 0718a0f8..d25a53de 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -12,6 +12,7 @@ import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventService; import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.enums.InheritStatus; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; @@ -29,7 +30,10 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -165,7 +169,7 @@ public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseE throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); } - List list = new QProductEventRelation().eventRuleId.eq(event.getEventRuleId()).findList(); + List list = new QProductEventRelation().eventRuleId.eq(event.getEventRuleId()).inherit.eq(InheritStatus.NO.getCode()).findList(); if (list.isEmpty()) { throw new ServiceException(BizExceptionEnum.EVENT_EXPRESSION_NOT_EXISTS); } @@ -230,9 +234,9 @@ public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseE return ResponseData.success(); } //step 01:删除 zbx触发器 - String s = zbxTrigger.triggerGet(productEventRelation.getZbxId()); + String s = zbxTrigger.triggerGet(productEventRelation.getZbxId()); List triggers = JSONObject.parseArray(s, ProductEventRuleService.Triggers.class); - if(ToolUtil.isNotEmpty(triggers)){ + if (ToolUtil.isNotEmpty(triggers)) { zbxTrigger.triggerDelete(productEventRelation.getZbxId()); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index 5ca976fa..074d6a16 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -135,7 +135,7 @@ public void updateProductEventRule(Long eventRuleId, ProductEventRule eventRule) //step 6:保存备注 if (null != eventRule.getRemark()) { - DB.update(QProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).eq("relationId", eventRule.getProductId()) + DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).eq("relationId", eventRule.getProductId()) .asUpdate().set("remark", eventRule.getRemark()).update(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java index 47249b7f..bf2a66eb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java @@ -119,13 +119,12 @@ public String zbxTemplateCreate(String templateName) { * @param templdateId 模板ID * @return */ - public String zbxTemplateDelete(String templdateId) { + public void zbxTemplateDelete(String templdateId) { JSONArray jsonArray = JSONObject.parseArray(zbxTemplate.templateGet(templdateId)); if (jsonArray.size() > 0) { zbxTemplate.templateDelete(templdateId); } - return templdateId; } /** From 94bf237bba9fafcdbea88146b042c6a59264b0c0 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 8 Oct 2021 19:36:03 +0800 Subject: [PATCH 453/763] [fix]:fix bug --- .../main/java/com/zmops/iot/web/alarm/service/AlarmService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index c79f8184..e68448c9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -164,7 +164,7 @@ public List getZbxAlarm(AlarmParam alarmParam) { public List getEventList(AlarmParam alarmParam) { String hostId = null; Assert.state(ToolUtil.isNotEmpty(alarmParam.getDeviceId()), "设备ID不能为空"); - List problemList = getZbxAlarm(alarmParam); + List problemList = getEventProblem(alarmParam); if (ToolUtil.isEmpty(problemList)) { return Collections.emptyList(); } From d21cb26afbcc4929c45cc7ecfe6660fc073e77b2 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 8 Oct 2021 21:44:42 +0800 Subject: [PATCH 454/763] [feat]: alarm list add deviceId --- .../java/com/zmops/iot/web/alarm/dto/AlarmDto.java | 2 ++ .../zmops/iot/web/alarm/service/AlarmService.java | 13 +++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java index b5340d84..5448c8db 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java @@ -28,4 +28,6 @@ public class AlarmDto { private String status; private String acknowledged; + + private String deviceId; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index e68448c9..ac103cce 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -78,13 +78,13 @@ public Pager getAlarmByPage(AlarmParam alarmParam) { .skip((alarmParam.getPage() - 1) * alarmParam.getMaxRow()) .limit(alarmParam.getMaxRow()).collect(Collectors.toList()); if (ToolUtil.isEmpty(problemList)) { - return new Pager<>(Collections.emptyList(),zbxProblemInfos.size()); + return new Pager<>(Collections.emptyList(), zbxProblemInfos.size()); } //根据triggerid查询出 所属设备 List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).collect(Collectors.toList()); - List deviceList = DB.findDto(DeviceDto.class, "select name,r.zbx_id from device d INNER JOIN (select relation_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.relation_id=d.device_id") + List deviceList = DB.findDto(DeviceDto.class, "select name,device_id,r.zbx_id from device d INNER JOIN (select relation_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.relation_id=d.device_id") .setParameter("zbxIds", triggerIds).findList(); - Map deviceMap = deviceList.parallelStream().collect(Collectors.toMap(DeviceDto::getZbxId, DeviceDto::getName)); + Map deviceMap = deviceList.parallelStream().collect(Collectors.toMap(DeviceDto::getZbxId, o -> o)); List ruleList = DB.findDto(ProductEventRuleDto.class, "select event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") .setParameter("zbxIds", triggerIds).findList(); @@ -102,7 +102,8 @@ public Pager getAlarmByPage(AlarmParam alarmParam) { alarmDto.setStatus("0".equals(zbxProblemInfo.getR_clock()) ? "未解决" : "已解决"); alarmDto.setAcknowledged("0".equals(zbxProblemInfo.getAcknowledged()) ? "未确认" : "已确认"); if (null != deviceMap.get(zbxProblemInfo.getObjectid())) { - alarmDto.setDeviceName(deviceMap.get(zbxProblemInfo.getObjectid())); + alarmDto.setDeviceName(deviceMap.get(zbxProblemInfo.getObjectid()).getName()); + alarmDto.setDeviceId(deviceMap.get(zbxProblemInfo.getObjectid()).getDeviceId()); } if (null != ruleMap.get(zbxProblemInfo.getObjectid())) { alarmDto.setName(ruleMap.get(zbxProblemInfo.getObjectid())); @@ -110,7 +111,7 @@ public Pager getAlarmByPage(AlarmParam alarmParam) { alarmDtoList.add(alarmDto); }); - return new Pager<>(alarmDtoList,zbxProblemInfos.size()); + return new Pager<>(alarmDtoList, zbxProblemInfos.size()); } public List getAlarmList(AlarmParam alarmParam) { @@ -190,7 +191,7 @@ public List getEventList(AlarmParam alarmParam) { } public List getEventProblem(AlarmParam alarmParam) { - String hostId = null; + String hostId = null; List deviceIds; if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { deviceIds = Collections.singletonList(alarmParam.getDeviceId()); From 6b505cda10ec07d29821209e109ac43d6f173213 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 8 Oct 2021 21:45:22 +0800 Subject: [PATCH 455/763] [feat]: device log add page list --- .../controller/DeviceLogController.java | 12 +++- .../web/device/dto/param/DeviceLogParam.java | 16 +++++ .../web/device/service/DeviceLogService.java | 60 ++++++++++++++++++- 3 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceLogParam.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java index 1180ea41..47414228 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java @@ -1,8 +1,10 @@ package com.zmops.iot.web.device.controller; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.device.dto.param.DeviceLogParam; import com.zmops.iot.web.device.service.DeviceLogService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -18,11 +20,17 @@ public class DeviceLogController { DeviceLogService deviceLogService; @RequestMapping("list") - public ResponseData getLogByPage(@RequestParam(value = "deviceId") String deviceId, + public ResponseData list(@RequestParam(value = "deviceId") String deviceId, @RequestParam(value = "logType", required = false) String logType, @RequestParam(value = "timeFrom", required = false) Long timeFrom, @RequestParam(value = "timeTill", required = false) Long timeTill) { - return ResponseData.success(deviceLogService.getLogByPage(deviceId, logType, timeFrom, timeTill)); + return ResponseData.success(deviceLogService.list(deviceId, logType, timeFrom, timeTill)); + } + + @RequestMapping("getLogByPage") + public ResponseData getLogByPage(@RequestBody DeviceLogParam deviceLogParam) { + + return ResponseData.success(deviceLogService.getLogByPage(deviceLogParam.getDeviceId(), deviceLogParam.getLogType(), deviceLogParam.getTimeFrom(), deviceLogParam.getTimeTill(),deviceLogParam.getPage(),deviceLogParam.getMaxRow())); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceLogParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceLogParam.java new file mode 100644 index 00000000..c585a660 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceLogParam.java @@ -0,0 +1,16 @@ +package com.zmops.iot.web.device.dto.param; + +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class DeviceLogParam extends BaseQueryParam { + private String logType; + private String deviceId; + private Long timeFrom; + private Long timeTill; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java index ee415e9d..1f00591c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java @@ -2,6 +2,7 @@ import com.zmops.iot.domain.device.ServiceExecuteRecord; import com.zmops.iot.domain.device.query.QServiceExecuteRecord; +import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.alarm.dto.AlarmDto; @@ -29,7 +30,7 @@ public class DeviceLogService { @Autowired AlarmService alarmService; - public List getLogByPage(String deviceId, String logType, Long timeFrom, Long timeTill) { + public List list(String deviceId, String logType, Long timeFrom, Long timeTill) { List deviceLogDtoList = new ArrayList<>(); if (ToolUtil.isEmpty(logType) || (ToolUtil.isNotEmpty(logType) && LOG_TYPE_ALARM.equals(logType))) { AlarmParam alarmParam = new AlarmParam(); @@ -82,4 +83,61 @@ public List getLogByPage(String deviceId, String logType, Long tim .sorted((o1, o2) -> (int) LocalDateTimeUtils.betweenTwoTime(o1.getTriggerTime(), o2.getTriggerTime(), ChronoUnit.SECONDS)).collect(Collectors.toList()); return deviceLogDtoList; } + + + public Pager getLogByPage(String deviceId, String logType, Long timeFrom, Long timeTill, int page, int maxSize) { + List deviceLogDtoList = new ArrayList<>(); + if (ToolUtil.isNotEmpty(logType) && LOG_TYPE_ALARM.equals(logType)) { + AlarmParam alarmParam = new AlarmParam(); + alarmParam.setDeviceId(deviceId); + alarmParam.setTimeFrom(timeFrom); + alarmParam.setTimeTill(timeTill); + List alarmList = alarmService.getAlarmList(alarmParam); + if (ToolUtil.isNotEmpty(alarmList)) { + alarmList.forEach(alarm -> { + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_ALARM).content(alarm.getName()) + .triggerTime(LocalDateTimeUtils.convertDateToLocalDateTime(Integer.parseInt(alarm.getClock()))) + .status("0".equals(alarm.getRClock()) ? "已解决" : "未解决").build()); + }); + } + } + + if (ToolUtil.isNotEmpty(logType) && LOG_TYPE_SERVICE.equals(logType)) { + QServiceExecuteRecord query = new QServiceExecuteRecord().deviceId.eq(deviceId); + if (null != timeFrom) { + query.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(timeFrom * 1000)); + } + if (null != timeTill) { + query.createTime.lt(LocalDateTimeUtils.getLDTByMilliSeconds(timeTill * 1000)); + } + query.orderBy().createTime.desc(); + List list = query.findList(); + if (ToolUtil.isNotEmpty(list)) { + list.forEach(service -> { + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_SERVICE).content(service.getServiceName()) + .triggerTime(service.getCreateTime()) + .param(service.getParam()).build()); + }); + } + } + + if (ToolUtil.isEmpty(logType) || (ToolUtil.isNotEmpty(logType) && LOG_TYPE_EVENT.equals(logType))) { + AlarmParam alarmParam = new AlarmParam(); + alarmParam.setDeviceId(deviceId); + alarmParam.setTimeFrom(timeFrom); + alarmParam.setTimeTill(timeTill); + List alarmList = alarmService.getEventList(alarmParam); + if (ToolUtil.isNotEmpty(alarmList)) { + alarmList.forEach(alarm -> { + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_ALARM).content(alarm.getName()) + .triggerTime(LocalDateTimeUtils.convertDateToLocalDateTime(Integer.parseInt(alarm.getClock()))) + .status("0".equals(alarm.getRClock()) ? "已解决" : "未解决").build()); + }); + } + } + + List res = deviceLogDtoList.parallelStream().skip((page - 1) * maxSize) + .limit(maxSize).collect(Collectors.toList()); + return new Pager<>(res, deviceLogDtoList.size()); + } } From f3bf49892b14108b007a7e2563f76739df3f3447 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 8 Oct 2021 21:45:42 +0800 Subject: [PATCH 456/763] [fix]: fix bug --- .../zmops/iot/web/product/service/ProductEventRuleService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index 074d6a16..ac2a1886 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -155,7 +155,6 @@ private ProductEvent initEventRule(ProductEventRule eventRule) { private ProductEventExpression initEventExpression(ProductEventRule.Expression exp) { ProductEventExpression eventExpression = new ProductEventExpression(); - eventExpression.setEventExpId(exp.getEventExpId()); eventExpression.setCondition(exp.getCondition()); eventExpression.setFunction(exp.getFunction()); eventExpression.setScope(exp.getScope()); From 68f5a06d4d87e5dfbcd6033b9ad44dfe6bc0eef2 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 8 Oct 2021 21:50:18 +0800 Subject: [PATCH 457/763] [fix]: fix websocket notice --- .../zmops/iot/message/handler/MessageEventHandler.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java b/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java index 9d3e137e..4ef551b0 100644 --- a/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java +++ b/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java @@ -82,14 +82,18 @@ public void onGroupEvent(SocketIOClient client, AckRequest request, GroupMessage public void sendDisconnectMsg(String userId) { if (userClient.findByUserId(userId).isPresent()) { UUID uuid = userClient.findByUserId(userId).get(); - server.getClient(uuid).sendEvent(Event.CHAT, "disconnect"); + BroadcastMessageRequest message = new BroadcastMessageRequest(); + message.setMessage("disconnect"); + server.getClient(uuid).sendEvent(Event.CHAT, message); } } public void sendToUser(String userId,String msg) { if (userClient.findByUserId(userId).isPresent()) { UUID uuid = userClient.findByUserId(userId).get(); - server.getClient(uuid).sendEvent(Event.CHAT, msg); + BroadcastMessageRequest message = new BroadcastMessageRequest(); + message.setMessage(msg); + server.getClient(uuid).sendEvent(Event.CHAT, message); } } From ed7b241bdf877af6d27fa9d43369705b32bb16e0 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 8 Oct 2021 21:58:45 +0800 Subject: [PATCH 458/763] [fix]: fix bug --- .../zmops/zeus/driver/service/ZbxProblem.java | 2 +- .../iot/message/handler/MessageEventHandler.java | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java index 93f59598..fe0c0291 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java @@ -36,5 +36,5 @@ String getEventProblem(@ParamName("hostId") String hostId, @Post @JsonPath("/problem/problem.acknowledgement") - void acknowledgement(@ParamName("eventId") String eventId,@ParamName("action") int action); + String acknowledgement(@ParamName("eventId") String eventId,@ParamName("action") int action); } diff --git a/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java b/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java index 4ef551b0..9090eb63 100644 --- a/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java +++ b/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java @@ -82,18 +82,22 @@ public void onGroupEvent(SocketIOClient client, AckRequest request, GroupMessage public void sendDisconnectMsg(String userId) { if (userClient.findByUserId(userId).isPresent()) { UUID uuid = userClient.findByUserId(userId).get(); - BroadcastMessageRequest message = new BroadcastMessageRequest(); - message.setMessage("disconnect"); - server.getClient(uuid).sendEvent(Event.CHAT, message); + if (null != server.getClient(uuid)) { + BroadcastMessageRequest message = new BroadcastMessageRequest(); + message.setMessage("disconnect"); + server.getClient(uuid).sendEvent(Event.CHAT, message); + } } } public void sendToUser(String userId,String msg) { if (userClient.findByUserId(userId).isPresent()) { UUID uuid = userClient.findByUserId(userId).get(); - BroadcastMessageRequest message = new BroadcastMessageRequest(); - message.setMessage(msg); - server.getClient(uuid).sendEvent(Event.CHAT, message); + if (null != server.getClient(uuid)) { + BroadcastMessageRequest message = new BroadcastMessageRequest(); + message.setMessage(msg); + server.getClient(uuid).sendEvent(Event.CHAT, message); + } } } From 1423025d24cae5c76b218cbe9b746e8c94c0ad3e Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 9 Oct 2021 09:25:34 +0800 Subject: [PATCH 459/763] [fix]: update alarm list param --- .../java/com/zmops/zeus/driver/service/ZbxProblem.java | 3 ++- .../src/main/resources/api-json/problem/problem.get.ftl | 3 +++ .../com/zmops/iot/web/alarm/dto/param/AlarmParam.java | 3 ++- .../com/zmops/iot/web/alarm/service/AlarmService.java | 9 ++++++++- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java index fe0c0291..4dc49a9f 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java @@ -25,7 +25,8 @@ public interface ZbxProblem { String getProblem(@ParamName("hostId") String hostId, @ParamName("timeFrom") Long timeFrom, @ParamName("timeTill") Long timeTill, - @ParamName("recent") String recent); + @ParamName("recent") String recent, + @ParamName("severity") String severity); @Post @JsonPath("/problem/problem.event.get") diff --git a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl index 6086b28e..7666c997 100644 --- a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl +++ b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl @@ -17,6 +17,9 @@ <#if timeTill??> "time_till":${timeTill}, + <#if severity??> + "severities":${severity}, + "evaltype":2, "tags":[{"tag": "__alarm__"},{"tag": "__execute__"}], "filter":{ diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/AlarmParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/AlarmParam.java index df4780ad..66e55fe1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/AlarmParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/AlarmParam.java @@ -12,6 +12,7 @@ public class AlarmParam extends BaseQueryParam { private Long timeFrom; private Long timeTill; - + private String statusName; private String recent = "true"; + private String severity; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index ac103cce..760ab7d7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -73,6 +73,13 @@ public Pager getAlarmByPage(AlarmParam alarmParam) { if (ToolUtil.isEmpty(zbxProblemInfos)) { return new Pager<>(); } + if (ToolUtil.isNotEmpty(alarmParam.getStatusName()) && "已解决".equals(alarmParam.getStatusName())) { + zbxProblemInfos = zbxProblemInfos.parallelStream().filter(o -> !"0".equals(o.getR_clock())).collect(Collectors.toList()); + } + + if (ToolUtil.isNotEmpty(alarmParam.getStatusName()) && "未解决".equals(alarmParam.getStatusName())) { + zbxProblemInfos = zbxProblemInfos.parallelStream().filter(o -> "0".equals(o.getR_clock())).collect(Collectors.toList()); + } //分页 List problemList = zbxProblemInfos.stream() .skip((alarmParam.getPage() - 1) * alarmParam.getMaxRow()) @@ -157,7 +164,7 @@ public List getZbxAlarm(AlarmParam alarmParam) { } hostId = zbxIds.toString(); //从zbx取告警记录 - String problem = zbxProblem.getProblem(hostId, alarmParam.getTimeFrom(), alarmParam.getTimeTill(), alarmParam.getRecent()); + String problem = zbxProblem.getProblem(hostId, alarmParam.getTimeFrom(), alarmParam.getTimeTill(), alarmParam.getRecent(), alarmParam.getSeverity()); return JSONObject.parseArray(problem, ZbxProblemInfo.class); } From 2c79633ef6c60dbb9c47dd44bebbcfdb09bd2006 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 9 Oct 2021 10:00:44 +0800 Subject: [PATCH 460/763] [fix]: fix alarm param --- zeus-driver/src/main/resources/api-json/problem/problem.get.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl index 7666c997..e781c814 100644 --- a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl +++ b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl @@ -17,7 +17,7 @@ <#if timeTill??> "time_till":${timeTill}, - <#if severity??> + <#if severity?? && severity != ''> "severities":${severity}, "evaltype":2, From 903bc21a5373e4a3dce79d5415d81494994f13db Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 9 Oct 2021 10:51:45 +0800 Subject: [PATCH 461/763] [fix]: fix global view --- .../java/com/zmops/iot/web/analyse/service/HomeService.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index 2ef5873b..ddf892a9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -171,7 +171,7 @@ public Map getDeviceNum(Integer timeFrom, Integer timeTill) { List list = new QDevice().findList(); deviceNumMap.put("total", list.size()); deviceNumMap.put("disable", (int) list.parallelStream().filter(o -> "DISABLE".equals(o.getStatus())).count()); - deviceNumMap.put("online", (int) list.parallelStream().filter(o -> "1".equals(o.getOnline())).count()); + deviceNumMap.put("online", (int) list.parallelStream().filter(o -> null != o.getOnline() && 1 == o.getOnline()).count()); deviceNumMap.put("product", new QProduct().findCount()); List onLineList = new QDeviceOnlineReport() @@ -189,7 +189,9 @@ public Map getDeviceNum(Integer timeFrom, Integer timeTill) { map.put("val", value); trendsList.add(map); }); - deviceNumMap.put("trends", trendsList); + List> result = trendsList.parallelStream() + .sorted(Comparator.comparing(o -> o.get("date").toString())).collect(Collectors.toList()); + deviceNumMap.put("trends", result); return deviceNumMap; } From f6aff1033a7c3aa4ad233c50bf9745f7cc5e584a Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 9 Oct 2021 16:15:48 +0800 Subject: [PATCH 462/763] [fix]: fix bug --- .../iot/media/wechat/WechatHookCallback.java | 42 +++++++++---------- .../iot/media/welink/WeLinkHookCallback.java | 30 ++++++------- .../message/handler/MessageEventHandler.java | 4 +- .../service/ProductEventRuleService.java | 1 + .../service/work/UpdateAttributeWorker.java | 19 +++++---- 5 files changed, 51 insertions(+), 45 deletions(-) diff --git a/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatHookCallback.java index 29ecf380..2a817dc5 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatHookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatHookCallback.java @@ -64,27 +64,27 @@ public WechatHookCallback() { @Override public void doAlarm(List alarmMessages) { - WechatSettings wechatSettings = wechatSettingService.get(); - if (wechatSettings == null || wechatSettings.getWebhooks().isEmpty()) { - return; - } - CloseableHttpClient httpClient = HttpClients.custom().build(); - try { - wechatSettings.getWebhooks().forEach(url -> { - alarmMessages.forEach(alarmMessage -> { - String requestBody = String.format( - wechatSettings.getTextTemplate(), alarmMessage.getAlarmMessage() - ); - sendAlarmMessage(httpClient, url, requestBody); - }); - }); - } finally { - try { - httpClient.close(); - } catch (IOException e) { - log.error(e.getMessage(), e); - } - } +// WechatSettings wechatSettings = wechatSettingService.get(); +// if (wechatSettings == null || wechatSettings.getWebhooks().isEmpty()) { +// return; +// } +// CloseableHttpClient httpClient = HttpClients.custom().build(); +// try { +// wechatSettings.getWebhooks().forEach(url -> { +// alarmMessages.forEach(alarmMessage -> { +// String requestBody = String.format( +// wechatSettings.getTextTemplate(), alarmMessage.getAlarmMessage() +// ); +// sendAlarmMessage(httpClient, url, requestBody); +// }); +// }); +// } finally { +// try { +// httpClient.close(); +// } catch (IOException e) { +// log.error(e.getMessage(), e); +// } +// } } private void sendAlarmMessage(CloseableHttpClient httpClient, String url, String requestBody) { diff --git a/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkHookCallback.java index 6ae52b42..8fd7bbfa 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkHookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkHookCallback.java @@ -68,21 +68,21 @@ public WeLinkHookCallback() { */ @Override public void doAlarm(List alarmMessages) { - WeLinkSettings weLinkSettings = weLinkSettingService.get(); - if (weLinkSettings == null || weLinkSettings.getWebhooks().isEmpty()) { - return; - } - weLinkSettings.getWebhooks().forEach(webHookUrl -> { - String accessToken = getAccessToken(webHookUrl); - alarmMessages.forEach(alarmMessage -> { - String content = String.format( - Locale.US, - weLinkSettings.getTextTemplate(), - alarmMessage.getAlarmMessage() - ); - sendAlarmMessage(webHookUrl, accessToken, content); - }); - }); +// WeLinkSettings weLinkSettings = weLinkSettingService.get(); +// if (weLinkSettings == null || weLinkSettings.getWebhooks().isEmpty()) { +// return; +// } +// weLinkSettings.getWebhooks().forEach(webHookUrl -> { +// String accessToken = getAccessToken(webHookUrl); +// alarmMessages.forEach(alarmMessage -> { +// String content = String.format( +// Locale.US, +// weLinkSettings.getTextTemplate(), +// alarmMessage.getAlarmMessage() +// ); +// sendAlarmMessage(webHookUrl, accessToken, content); +// }); +// }); } /** diff --git a/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java b/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java index 9090eb63..54495d22 100644 --- a/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java +++ b/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java @@ -85,7 +85,7 @@ public void sendDisconnectMsg(String userId) { if (null != server.getClient(uuid)) { BroadcastMessageRequest message = new BroadcastMessageRequest(); message.setMessage("disconnect"); - server.getClient(uuid).sendEvent(Event.CHAT, message); + server.getClient(uuid).sendEvent(Event.BROADCAST, message); } } } @@ -96,7 +96,7 @@ public void sendToUser(String userId,String msg) { if (null != server.getClient(uuid)) { BroadcastMessageRequest message = new BroadcastMessageRequest(); message.setMessage(msg); - server.getClient(uuid).sendEvent(Event.CHAT, message); + server.getClient(uuid).sendEvent(Event.BROADCAST, message); } } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index ac2a1886..b3a2a4f8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -73,6 +73,7 @@ public void createProductEventRule(ProductEventRule eventRule) { .setParameter("eventRuleId", eventRule.getEventRuleId()) .setParameter("executeDeviceId", i.getExecuteDeviceId()) .setParameter("serviceId", i.getServiceId()) + .setParameter("deviceId", eventRule.getProductId()) .execute(); }); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java index 10f29167..47fde1d9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java @@ -5,11 +5,13 @@ import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.product.dto.ProductAttr; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -30,15 +32,18 @@ public Boolean action(ProductAttr productAttr, Map> Long attrId = productAttr.getAttrId(); List list = new QProductAttribute().templateId.eq(attrId).findList(); - + List newList = new ArrayList<>(); for (ProductAttribute productAttribute : list) { - productAttribute.setName(productAttr.getAttrName()); - productAttribute.setKey(productAttr.getKey()); - productAttribute.setUnits(productAttr.getUnits()); - productAttribute.setSource(productAttr.getSource()); - productAttribute.setValueType(productAttr.getValueType()); + ProductAttribute newProductAttribute = new ProductAttribute(); + ToolUtil.copyProperties(productAttribute,newProductAttribute); + newProductAttribute.setName(productAttr.getAttrName()); + newProductAttribute.setKey(productAttr.getKey()); + newProductAttribute.setUnits(productAttr.getUnits()); + newProductAttribute.setSource(productAttr.getSource()); + newProductAttribute.setValueType(productAttr.getValueType()); + newList.add(newProductAttribute); } - DB.updateAll(list); + DB.updateAll(newList); return true; } From d34abe2ad20d61de39c36ee3fd82624362135bd7 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 9 Oct 2021 17:23:58 +0800 Subject: [PATCH 463/763] [fix]: update user info --- .../java/com/zmops/zeus/driver/service/ZbxUser.java | 3 ++- .../src/main/resources/api-json/user/userUpdate.ftl | 2 +- .../com/zmops/iot/web/sys/service/SysUserService.java | 10 ++++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java index a40f6de8..ab361a3d 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java @@ -58,7 +58,8 @@ String userAdd(@ParamName("name") String name, @Post @JsonPath("/user/userUpdate") String userUpdate(@ParamName("userId") String userId, - @ParamName("usrGrpId") String usrGrpId); + @ParamName("usrGrpId") String usrGrpId, + @ParamName("roleId") String roleId); /** * 用户删除 diff --git a/zeus-driver/src/main/resources/api-json/user/userUpdate.ftl b/zeus-driver/src/main/resources/api-json/user/userUpdate.ftl index c9e517bf..221bc7de 100644 --- a/zeus-driver/src/main/resources/api-json/user/userUpdate.ftl +++ b/zeus-driver/src/main/resources/api-json/user/userUpdate.ftl @@ -3,7 +3,7 @@ "method": "user.update", "params": { "userid": "${userId}", - "roleid": "2", + "roleid": "${roleId}", "usrgrps": [ { "usrgrpid": "${usrGrpId}" diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java index 4be219dc..f98d86c2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java @@ -157,10 +157,12 @@ public SysUser updateUser(UserDto user) { checkByRole(user.getRoleId()); SysUser sysUser = UserFactory.editUser(user, oldUser); - //取对应的ZBX用户组ID - String usrZbxId = sysUserGroupService.getZabUsrGrpId(user.getUserGroupId()); - zbxUser.userUpdate(oldUser.getZbxId(), usrZbxId); - + //取对应的ZBX用户组ID 修改自己的信息 不更新zbx + Long id = LoginContextHolder.getContext().getUser().getId(); + if (!user.getUserId().equals(id)) { + String usrZbxId = sysUserGroupService.getZabUsrGrpId(user.getUserGroupId()); + zbxUser.userUpdate(oldUser.getZbxId(), usrZbxId, ConstantsContext.getConstntsMap().get(GLOBAL_ADMIN_ROLE_CODE).toString()); + } DB.save(sysUser); updateUserCache(); return sysUser; From b8aa0ccbebefc329f3b12a8703855cc1ce9cc9d7 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 9 Oct 2021 21:18:45 +0800 Subject: [PATCH 464/763] [style]: remove unused code --- .../com/zmops/iot/web/alarm/controller/AlarmController.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java index 691ec90d..437d73b4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java @@ -22,11 +22,6 @@ public class AlarmController { @Autowired AlarmService alarmService; - // @RequestMapping("/test") -// public void test() { -// alarmService.test(); -// } - @Permission(code = "alarmList") @RequestMapping("/getAlarmByPage") public Pager getAlarmByPage(@RequestBody AlarmParam alarmParam) { From cfc7713a58cf14f3d7378ae1dd961b40bd587051 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 9 Oct 2021 21:23:09 +0800 Subject: [PATCH 465/763] [style]: formate code --- .../iot/web/analyse/service/HistoryService.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java index 6d98c3df..cebdaf09 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java @@ -34,22 +34,27 @@ public class HistoryService { ZbxHistoryGet zbxHistoryGet; public Pager queryHistory(HistoryParam historyParam) { + List latestDtos = queryHistory(historyParam.getDeviceId(), historyParam.getAttrIds(), dateTransfer(historyParam.getTimeFrom()), dateTransfer(historyParam.getTimeTill())); + List collect = latestDtos.stream().skip((historyParam.getPage() - 1) * historyParam.getMaxRow()) .limit(historyParam.getMaxRow()).collect(Collectors.toList()); + return new Pager<>(collect, latestDtos.size()); } private long dateTransfer(String date) { + LocalDateTime now = LocalDateTime.now(); if (ToolUtil.isEmpty(date) || date.equals("now")) { return LocalDateTimeUtils.getSecondsByTime(now); } + if (date.startsWith("now-")) { String value = date.substring(date.indexOf("-") + 1, date.length() - 1); - String unit = date.substring(date.length() - 1); + String unit = date.substring(date.length() - 1); switch (unit) { case "m": return LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.minu(now, Integer.valueOf(value), ChronoUnit.MINUTES)); @@ -75,23 +80,27 @@ public List queryHistory(String deviceId, List attrIds, Long ti if (null == one || ToolUtil.isEmpty(one.getZbxId())) { return Collections.emptyList(); } + //查询设备属性 QProductAttribute query = new QProductAttribute().productId.eq(deviceId); if (ToolUtil.isNotEmpty(attrIds)) { query.attrId.in(attrIds); } + List list = query.findList(); if (ToolUtil.isEmpty(list)) { return Collections.emptyList(); } + //取出属性对应的ItemID - List zbxIds = list.parallelStream().map(ProductAttribute::getZbxId).collect(Collectors.toList()); + List zbxIds = list.parallelStream().map(ProductAttribute::getZbxId).collect(Collectors.toList()); Map> valueTypeMap = list.parallelStream().collect(Collectors.groupingBy(ProductAttribute::getValueType)); - Map itemIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getZbxId, o -> o)); - List latestDtos = new ArrayList<>(); + Map itemIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getZbxId, o -> o)); + List latestDtos = new ArrayList<>(); if (null == timeFrom) { timeFrom = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); } + //根据属性值类型 分组查询历史数据 for (Map.Entry> map : valueTypeMap.entrySet()) { latestDtos.addAll(queryHitoryData(one.getZbxId(), zbxIds, 1000, Integer.parseInt(map.getKey()), timeFrom, timeTill)); From 737ab6f79d669e098e56250230b0e56dcd3d7c7d Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 9 Oct 2021 21:29:10 +0800 Subject: [PATCH 466/763] [style]: format code --- .../zmops/iot/web/analyse/service/LatestService.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java index 82b8e183..8e8219c9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java @@ -42,25 +42,30 @@ public Pager qeuryLatest(LatestParam latestParam) { } public List qeuryLatest(String deviceId, List attrIds) { + //查询出设备 Device one = new QDevice().deviceId.eq(deviceId).findOne(); if (null == one || ToolUtil.isEmpty(one.getZbxId())) { return Collections.emptyList(); } + //查询设备属性 QProductAttribute query = new QProductAttribute().productId.eq(deviceId); if (ToolUtil.isNotEmpty(attrIds)) { query.attrId.in(attrIds); } + List list = query.findList(); if (ToolUtil.isEmpty(list)) { return Collections.emptyList(); } + //取出属性对应的ItemID - List zbxIds = list.parallelStream().map(ProductAttribute::getZbxId).collect(Collectors.toList()); + List zbxIds = list.parallelStream().map(ProductAttribute::getZbxId).collect(Collectors.toList()); Map> valueTypeMap = list.parallelStream().collect(Collectors.groupingBy(ProductAttribute::getValueType)); - Map itemIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getZbxId, o -> o)); - List latestDtos = new ArrayList<>(); + Map itemIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getZbxId, o -> o)); + List latestDtos = new ArrayList<>(); + //根据属性值类型 分组查询最新数据 for (Map.Entry> map : valueTypeMap.entrySet()) { String res = zbxHistoryGet.historyGet(one.getZbxId(), zbxIds, map.getValue().size(), Integer.parseInt(map.getKey()), null, null); From 7a2de6dab13aa209e637c8d2537c442e3e8dfb6f Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 9 Oct 2021 21:32:10 +0800 Subject: [PATCH 467/763] [style]: format code --- .../zmops/iot/web/analyse/service/HomeService.java | 14 +++++++++++--- .../iot/web/analyse/service/LatestService.java | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index ddf892a9..bd28afd1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -299,6 +299,7 @@ public Map getEventNum(long timeFrom, long timeTill) { Long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); AlarmParam todayParam = new AlarmParam(); todayParam.setTimeFrom(timeStart); + List todayAlarmList = alarmService.getZbxAlarm(todayParam); Long todayAlarmNum = todayAlarmList.parallelStream().count(); alarmMap.put("today", todayAlarmNum); @@ -313,7 +314,9 @@ public List> getAlarmTop(long timeFrom, long timeTill) { AlarmParam alarmParam = new AlarmParam(); alarmParam.setTimeTill(timeTill); alarmParam.setTimeFrom(timeFrom); + List alarmList = alarmService.getZbxAlarm(alarmParam); + Map tmpMap = new ConcurrentHashMap<>(); if (ToolUtil.isNotEmpty(alarmList)) { @@ -327,7 +330,6 @@ public List> getAlarmTop(long timeFrom, long timeTill) { Map deviceMap = deviceList.parallelStream().collect(Collectors.toMap(DeviceDto::getZbxId, DeviceDto::getName)); - List alarmDtoList = new ArrayList<>(); alarmList.forEach(zbxProblemInfo -> { AlarmDto alarmDto = new AlarmDto(); @@ -342,6 +344,7 @@ public List> getAlarmTop(long timeFrom, long timeTill) { tmpMap = alarmDtoList.parallelStream().collect(Collectors.groupingBy(AlarmDto::getDeviceName, Collectors.counting())); } + List> topList = new ArrayList<>(); tmpMap.forEach((key, value) -> { Map alarmMap = new ConcurrentHashMap<>(2); @@ -349,8 +352,10 @@ public List> getAlarmTop(long timeFrom, long timeTill) { alarmMap.put("value", value); topList.add(alarmMap); }); + topList.sort(Comparator.comparing(o -> Integer.parseInt(o.get("value").toString()))); topList.subList(0, Math.min(topList.size(), 5)); + return topList; } @@ -360,12 +365,13 @@ public List> getAlarmTop(long timeFrom, long timeTill) { public Map serviceExecuteNum(long timeFrom, long timeTill) { List list = new QServiceExecuteRecord().createTime.ge(LocalDateTimeUtils.getLDTBySeconds((int) timeFrom)) .createTime.lt(LocalDateTimeUtils.getLDTBySeconds((int) timeTill)).orderBy().createTime.asc().findList(); + Map executeMap = new ConcurrentHashMap<>(3); if (ToolUtil.isNotEmpty(list)) { executeMap.put("total", list.size()); - Map tmpMap = list.parallelStream().collect(Collectors.groupingBy(o -> LocalDateTimeUtils.formatTime(o.getCreateTime(), - "yyyy-MM-dd"), Collectors.counting())); + Map tmpMap = list.parallelStream().collect( + Collectors.groupingBy(o -> LocalDateTimeUtils.formatTime(o.getCreateTime(), "yyyy-MM-dd"), Collectors.counting())); List> trendsList = new ArrayList<>(); tmpMap.forEach((key, value) -> { @@ -376,9 +382,11 @@ public Map serviceExecuteNum(long timeFrom, long timeTill) { }); executeMap.put("trends", trendsList); } + //今日开始时间 long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); long todayNum = new QServiceExecuteRecord().createTime.ge(LocalDateTimeUtils.getLDTBySeconds((int) timeStart)).findCount(); + executeMap.put("today", todayNum); return executeMap; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java index 8e8219c9..f8d88187 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java @@ -64,6 +64,7 @@ public List qeuryLatest(String deviceId, List attrIds) { List zbxIds = list.parallelStream().map(ProductAttribute::getZbxId).collect(Collectors.toList()); Map> valueTypeMap = list.parallelStream().collect(Collectors.groupingBy(ProductAttribute::getValueType)); Map itemIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getZbxId, o -> o)); + List latestDtos = new ArrayList<>(); //根据属性值类型 分组查询最新数据 From 27caf8d003d91be2f2a5e6d2500d9cfd2c5d0fd7 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 9 Oct 2021 21:33:56 +0800 Subject: [PATCH 468/763] [style]: remove unused code --- .../controller/DeviceEventController.java | 21 ------------------- .../DeviceEventTriggerController.java | 15 ++++++------- 2 files changed, 8 insertions(+), 28 deletions(-) delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java deleted file mode 100644 index 61f03e74..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventController.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.zmops.iot.web.device.controller; - -import com.zmops.iot.model.response.ResponseData; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author nantian created at 2021/9/20 14:30 - *

- * 设备物模型: 事件 - */ -@RestController -@RequestMapping("/device/event") -public class DeviceEventController { - - - @RequestMapping("/create") - public ResponseData createDeviceEvent() { - return ResponseData.success(); - } -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index 4cc0da0c..dccd064f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -43,10 +43,10 @@ public class DeviceEventTriggerController { @Autowired private ZbxTrigger zbxTrigger; - private static final String ALARM_TAG_NAME = "__alarm__"; + private static final String ALARM_TAG_NAME = "__alarm__"; private static final String EXECUTE_TAG_NAME = "__execute__"; - private static final String EVENT_TAG_NAME = "__event__"; - private static final String EVENT_TYPE_NAME = "事件"; + private static final String EVENT_TAG_NAME = "__event__"; + private static final String EVENT_TYPE_NAME = "事件"; /** * 触发器 详情 @@ -152,6 +152,7 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn if (count > 1) { DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).eq("relationId", eventRule.getDeviceId()) .asUpdate().set("remark", eventRule.getRemark()).update(); + return ResponseData.success(eventRule.getEventRuleId()); } @@ -203,16 +204,18 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn @PostMapping("/delete") public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseEntity.Delete.class) DeviceEventRule eventRule) { + ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(eventRule.getDeviceId()) .eventRuleId.eq(eventRule.getEventRuleId()).findOne(); if (InheritStatus.YES.getCode().equals(productEventRelation.getInherit())) { throw new ServiceException(BizExceptionEnum.EVENT_PRODUCT_CANNOT_DELETE); } + //step 01:删除 zbx触发器 - if(ToolUtil.isNotEmpty(productEventRelation.getZbxId())){ + if (ToolUtil.isNotEmpty(productEventRelation.getZbxId())) { List triggers = JSONObject.parseArray(zbxTrigger.triggerGet(productEventRelation.getZbxId()), DeviceEventRuleService.Triggers.class); - if(ToolUtil.isNotEmpty(triggers)) { + if (ToolUtil.isNotEmpty(triggers)) { zbxTrigger.triggerDelete(productEventRelation.getZbxId()); } } @@ -230,8 +233,6 @@ public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseE //step 4:删除 触发器 new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).delete(); - - return ResponseData.success(); } From 38e202fb792e84910fe637610e4efffb01513144 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 9 Oct 2021 21:51:33 +0800 Subject: [PATCH 469/763] [style]: global code formatting --- .../iot/server/datacarrier/DataCarrier.java | 4 +- .../zeus/iot/server/datacarrier/EnvUtil.java | 4 +- .../buffer/ArrayBlockingQueueBuffer.java | 4 +- .../iot/server/datacarrier/buffer/Buffer.java | 4 +- .../server/datacarrier/buffer/Channels.java | 10 +-- .../common/AtomicRangeInteger.java | 4 +- .../datacarrier/consumer/BulkConsumePool.java | 8 +- .../datacarrier/consumer/ConsumeDriver.java | 6 +- .../datacarrier/consumer/ConsumerThread.java | 8 +- .../consumer/MultipleChannelsConsumer.java | 8 +- .../eventbus/core/EventControllerFactory.java | 2 +- .../eventbus/thread/ThreadPoolFactory.java | 30 +++---- .../thread/constant/ThreadConstant.java | 22 ++--- .../thread/entity/ThreadCustomization.java | 6 +- .../thread/entity/ThreadParameter.java | 12 +-- .../server/eventbus/thread/util/NetUtil.java | 1 + .../util/PropertyPlaceholderHelper.java | 7 +- .../config/ApplicationConfigLoader.java | 2 +- .../src/main/resources/application.yml | 2 +- .../iot/server/core/CoreModuleConfig.java | 12 +-- .../iot/server/core/CoreModuleProvider.java | 8 +- .../worker/RecordStreamProcessor.java | 2 +- .../core/annotation/AnnotationScan.java | 6 +- .../core/camel/CamelContextHolderService.java | 2 +- .../core/camel/ZabbixSenderEndpoint.java | 2 +- .../core/camel/ZabbixTrapperProducer.java | 8 +- .../process/ByteArrayToItemValueProcess.java | 14 ++-- .../camel/process/JsonToItemValueProcess.java | 12 +-- .../core/servlet/DataTransferHandler.java | 4 +- .../servlet/DeviceTriggerActionHandler.java | 6 +- .../core/servlet/HttpItemTrapperHandler.java | 2 +- .../core/worker/ItemDataTransferWorker.java | 10 +-- .../provider/HealthCheckerProvider.java | 12 +-- .../checker/provider/HealthQueryService.java | 4 +- .../jdbc/hikaricp/JDBCHikariCPClient.java | 8 +- .../server/library/module/BootstrapFlow.java | 6 +- .../server/library/module/ModuleDefine.java | 4 +- .../server/library/module/ModuleManager.java | 8 +- .../server/library/module/ModuleProvider.java | 4 +- .../server/jetty/JettyJsonHandler.java | 6 +- .../library/server/jetty/JettyServer.java | 6 +- .../server/jetty/JettyServerConfig.java | 14 ++-- .../server/pool/CustomThreadFactory.java | 6 +- .../library/server/ssl/PrivateKeyUtil.java | 2 +- .../util/MultipleFilesChangeMonitor.java | 20 ++--- .../mqtt/provider/MqttRouteBuilder.java | 2 +- .../sender/service/ZabbixSenderService.java | 26 +++--- .../storage/plugin/jdbc/SQLExecutor.java | 2 +- .../jdbc/tdengine/TDEngineBatchDAO.java | 4 +- .../tdengine/TDEngineDatabaseInstaller.java | 10 +-- .../jdbc/tdengine/TDEngineStorageConfig.java | 10 +-- .../tdengine/TDEngineStorageProvider.java | 4 +- .../jdbc/tdengine/dao/TDEngineStorageDAO.java | 2 +- .../telemetry/none/MetricsCollectorNoop.java | 1 - .../PrometheusHistogramMetrics.java | 2 +- .../PrometheusMetricsCollector.java | 5 +- .../prometheus/PrometheusMetricsCreator.java | 4 +- .../prometheus/httpserver/HttpServer.java | 8 +- .../httpserver/HttpServerHandler.java | 4 +- .../transfer/conf/AbstractConfiguration.java | 2 +- .../server/transfer/conf/CommonConstants.java | 12 +-- .../server/transfer/conf/JobConstants.java | 18 ++-- .../transfer/conf/TransferConfiguration.java | 8 +- .../transfer/conf/TransferConstants.java | 82 +++++++++---------- .../transfer/core/db/BerkeleyDbImp.java | 6 +- .../server/transfer/core/db/JobProfileDb.java | 14 ++-- .../transfer/core/filter/DateFormatRegex.java | 18 ++-- .../server/transfer/core/job/CommandDb.java | 2 +- .../iot/server/transfer/core/job/Job.java | 2 +- .../server/transfer/core/job/JobManager.java | 18 ++-- .../server/transfer/core/job/JobMetrics.java | 2 +- .../server/transfer/core/job/JobWrapper.java | 6 +- .../transfer/core/message/DefaultMessage.java | 2 +- .../transfer/core/message/ProxyMessage.java | 6 +- .../transfer/core/source/TextFileSource.java | 2 +- .../core/source/reader/TextFileReader.java | 8 +- .../iot/server/transfer/core/task/Task.java | 8 +- .../transfer/core/task/TaskManager.java | 12 +-- .../transfer/core/task/TaskMetrics.java | 2 +- .../core/task/TaskPositionManager.java | 2 +- .../transfer/core/task/TaskWrapper.java | 2 +- .../core/trigger/DirectoryTrigger.java | 14 ++-- .../transfer/core/trigger/PathPattern.java | 4 +- .../transfer/core/trigger/TriggerManager.java | 8 +- .../transfer/metrics/AgentDynamicMBean.java | 12 +-- .../transfer/metrics/MetricsRegister.java | 10 +-- .../transfer/metrics/meta/MetricMeta.java | 2 +- .../transfer/metrics/meta/MetricsMeta.java | 6 +- .../server/transfer/sender/SenderManager.java | 2 +- .../server/transfer/utils/TransferUtils.java | 34 ++++---- .../com/zmops/iot/async/executor/Async.java | 4 +- .../java/com/zmops/iot/async/util/BiInt.java | 26 +++--- .../util/collection/AbstractArray2D.java | 4 +- .../collection/AbstractDirectedGraph.java | 2 +- .../util/collection/CommonDirectedGraph.java | 8 +- .../async/util/collection/CommonStoreArk.java | 4 +- .../async/util/collection/DirectedGraph.java | 2 +- .../async/util/collection/SparseArray2D.java | 6 +- .../async/util/timer/AbstractWheelTimer.java | 4 +- .../async/util/timer/HashedWheelTimer.java | 38 ++++----- .../com/zmops/iot/async/worker/OnceWork.java | 4 +- .../zmops/iot/async/worker/WorkResult.java | 4 +- .../wrapper/StableWorkerWrapperBuilder.java | 34 ++++---- .../iot/async/wrapper/WorkerWrapper.java | 38 ++++----- .../iot/async/wrapper/WorkerWrapperGroup.java | 24 +++--- .../depend/DependOnUpWrapperStrategy.java | 2 +- .../strategy/depend/DependenceAction.java | 2 +- .../strategy/depend/DependenceStrategy.java | 6 +- .../zmops/iot/constant/ConstantsContext.java | 2 +- .../com/zmops/iot/dict/AbstractDictMap.java | 2 +- .../zmops/iot/domain/alarm/AlarmMessage.java | 19 ++--- .../iot/domain/messages/MessageBody.java | 8 +- .../zmops/iot/domain/messages/Messages.java | 10 +-- .../product/ProductEventExpression.java | 4 +- .../domain/product/ProductEventService.java | 4 +- .../model/cache/filter/CachedValueFilter.java | 6 +- .../zmops/iot/model/cache/filter/DicType.java | 4 +- .../java/com/zmops/iot/model/page/Pager.java | 2 +- .../com/zmops/iot/util/DefinitionsUtil.java | 2 +- .../java/com/zmops/iot/util/ToolUtil.java | 20 ++--- .../JwtAuthenticationEntryPoint.java | 3 +- .../core/auth/exception/AuthException.java | 2 +- .../auth/exception/PermissionException.java | 2 +- .../zmops/iot/core/auth/jwt/JwtTokenUtil.java | 4 +- .../zmops/iot/core/auth/model/LoginUser.java | 2 +- .../zmops/iot/core/auth/util/TokenUtil.java | 4 +- .../com/zmops/iot/core/util/FileUtil.java | 4 +- .../com/zmops/iot/core/util/HttpContext.java | 6 +- .../java/com/zmops/iot/core/util/RsaUtil.java | 4 +- .../iot/core/web/base/BaseController.java | 6 +- .../inteceptor/JsonBodyBuildInterceptor.java | 2 +- .../zmops/zeus/driver/service/ZbxAction.java | 2 +- .../zmops/zeus/driver/service/ZbxProblem.java | 8 +- .../zmops/zeus/driver/service/ZbxScript.java | 2 +- .../zmops/zeus/driver/service/ZbxUser.java | 2 +- .../zeus/driver/service/ZbxUserGroup.java | 2 +- .../com/zmops/iot/media/AlarmCallback.java | 1 - .../iot/media/AlarmMessageFormatter.java | 4 +- .../com/zmops/iot/media/WebhookCallback.java | 4 +- .../media/dingtalk/DingtalkHookCallback.java | 10 +-- .../dingtalk/DingtalkSettingService.java | 4 +- .../iot/media/dingtalk/DingtalkSettings.java | 4 +- .../iot/media/feishu/FeishuHookCallback.java | 12 +-- .../media/feishu/FeishuSettingService.java | 4 +- .../iot/media/feishu/FeishuSettings.java | 2 +- .../iot/media/wechat/WechatHookCallback.java | 9 +- .../iot/media/welink/WeLinkHookCallback.java | 12 +-- .../iot/media/welink/WeLinkSettings.java | 13 ++- .../message/handler/MessageEventHandler.java | 5 +- .../com/zmops/iot/config/web/WebConfig.java | 2 +- .../config/zbxapi/ZbxApiInfoValidation.java | 4 +- .../web/alarm/service/AlarmNoticeWorker.java | 2 - .../iot/web/alarm/service/AlarmService.java | 12 +-- .../iot/web/alarm/service/MessageService.java | 7 +- .../analyse/controller/LatestController.java | 1 - .../web/analyse/dto/param/LatestParam.java | 2 +- .../com/zmops/iot/web/auth/AuthService.java | 8 +- .../com/zmops/iot/web/auth/PermissionAop.java | 10 +-- .../DeviceEventTriggerController.java | 5 +- .../controller/DeviceLogController.java | 8 +- .../controller/DeviceModelController.java | 2 +- .../iot/web/device/dto/DeviceLogDto.java | 8 +- .../web/device/dto/param/DeviceLogParam.java | 4 +- .../service/DeviceEventRuleService.java | 4 +- .../device/service/DeviceGroupService.java | 2 +- .../web/device/service/DeviceLogService.java | 4 +- .../device/service/DeviceModelService.java | 14 ++-- .../service/work/DeviceOnlineWorker.java | 2 +- .../service/work/SaveAttributeWorker.java | 4 +- .../service/work/SaveDeviceGrpWorker.java | 4 +- .../device/service/work/SaveOtherWorker.java | 2 +- .../service/work/SaveZbxHostWorker.java | 4 +- .../service/work/UpdateAttrZbxIdWorker.java | 2 +- .../service/work/UpdateDeviceZbxIdWorker.java | 6 +- .../service/work/UpdateZbxTagWorker.java | 8 +- .../exception/aop/GlobalExceptionHandler.java | 12 +-- .../web/exception/enums/BizExceptionEnum.java | 2 +- .../zmops/iot/web/init/BasicSettingsInit.java | 30 +++---- .../iot/web/init/DeviceSatusScriptInit.java | 18 ++-- .../com/zmops/iot/web/log/aop/LogAop.java | 18 ++-- .../web/macro/controller/MacroController.java | 4 +- .../ProductAttributeEventController.java | 6 +- .../product/controller/ProductController.java | 11 ++- .../ProductEventTriggerController.java | 8 +- .../controller/ProductModelController.java | 14 ++-- .../ProductStatusTriggerController.java | 4 +- .../iot/web/product/dto/ProductAttr.java | 6 +- .../iot/web/product/dto/ProductAttrDto.java | 2 +- .../iot/web/product/dto/ProductAttrEvent.java | 4 +- .../iot/web/product/dto/ProductEventDto.java | 2 +- .../iot/web/product/dto/ProductEventRule.java | 4 +- .../zmops/iot/web/product/dto/ProductTag.java | 1 - .../product/dto/param/ProductAttrParam.java | 2 +- .../service/ProductAttributeEventService.java | 8 +- .../service/ProductEventRuleService.java | 4 +- .../product/service/ProductModelService.java | 4 +- .../web/product/service/ProductService.java | 6 +- .../product/service/ProductSvcService.java | 8 +- .../service/ProductTriggerService.java | 2 +- .../product/service/ProductTypeService.java | 6 +- .../service/work/AsyncAttrZbxIdWorker.java | 2 +- .../work/SaveProdAttrEventTriggerWorker.java | 2 +- .../service/work/SaveProdAttrWorker.java | 4 +- .../work/SaveProdStatusTriggerWorker.java | 2 +- .../service/work/SaveProdSvcWorker.java | 2 +- .../work/SaveProductEventTriggerWorker.java | 6 +- .../service/work/UpdateAttributeWorker.java | 2 +- .../web/sys/controller/KaptchaController.java | 2 +- .../web/sys/controller/LoginController.java | 7 +- .../web/sys/controller/SysMenuController.java | 6 +- .../web/sys/controller/SysUserController.java | 5 -- .../iot/web/sys/dto/param/BaseQueryParam.java | 2 +- .../iot/web/sys/service/DictService.java | 12 +-- .../iot/web/sys/service/SysParamService.java | 4 +- .../iot/web/sys/service/SysRoleService.java | 2 +- .../web/sys/service/SysUserGroupService.java | 10 +-- .../iot/web/sys/service/SysUserService.java | 8 +- 217 files changed, 782 insertions(+), 789 deletions(-) diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/DataCarrier.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/DataCarrier.java index 6a33305b..f072a2d9 100644 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/DataCarrier.java +++ b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/DataCarrier.java @@ -33,8 +33,8 @@ */ public class DataCarrier { private final Channels channels; - private IDriver driver; - private final String name; + private IDriver driver; + private final String name; public DataCarrier(int channelSize, int bufferSize) { this("DEFAULT", channelSize, bufferSize); diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/EnvUtil.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/EnvUtil.java index a94dcdbe..ac9ca760 100644 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/EnvUtil.java +++ b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/EnvUtil.java @@ -23,7 +23,7 @@ */ public class EnvUtil { public static int getInt(String envName, int defaultValue) { - int value = defaultValue; + int value = defaultValue; String envValue = System.getenv(envName); if (envValue != null) { try { @@ -36,7 +36,7 @@ public static int getInt(String envName, int defaultValue) { } public static long getLong(String envName, long defaultValue) { - long value = defaultValue; + long value = defaultValue; String envValue = System.getenv(envName); if (envValue != null) { try { diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/ArrayBlockingQueueBuffer.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/ArrayBlockingQueueBuffer.java index 8cdfbc62..08c1db7d 100644 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/ArrayBlockingQueueBuffer.java +++ b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/ArrayBlockingQueueBuffer.java @@ -28,9 +28,9 @@ * for agent side, which is more sensitive about blocks. */ public class ArrayBlockingQueueBuffer implements QueueBuffer { - private BufferStrategy strategy; + private BufferStrategy strategy; private ArrayBlockingQueue queue; - private int bufferSize; + private int bufferSize; ArrayBlockingQueueBuffer(int bufferSize, BufferStrategy strategy) { this.strategy = strategy; diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Buffer.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Buffer.java index 8cf6b233..64490321 100644 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Buffer.java +++ b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Buffer.java @@ -27,8 +27,8 @@ * Self implementation ring queue. */ public class Buffer implements QueueBuffer { - private final Object[] buffer; - private BufferStrategy strategy; + private final Object[] buffer; + private BufferStrategy strategy; private final AtomicRangeInteger index; Buffer(int bufferSize, BufferStrategy strategy) { diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Channels.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Channels.java index cb24ec37..72850cca 100644 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Channels.java +++ b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Channels.java @@ -26,10 +26,10 @@ * buffer is full. The Default is BLOCKING

Created by wusheng on 2016/10/25. */ public class Channels { - private final QueueBuffer[] bufferChannels; - private IDataPartitioner dataPartitioner; - private final BufferStrategy strategy; - private final long size; + private final QueueBuffer[] bufferChannels; + private IDataPartitioner dataPartitioner; + private final BufferStrategy strategy; + private final long size; public Channels(int channelSize, int bufferSize, IDataPartitioner partitioner, BufferStrategy strategy) { this.dataPartitioner = partitioner; @@ -47,7 +47,7 @@ public Channels(int channelSize, int bufferSize, IDataPartitioner partitioner } public boolean save(T data) { - int index = dataPartitioner.partition(bufferChannels.length, data); + int index = dataPartitioner.partition(bufferChannels.length, data); int retryCountDown = 1; if (BufferStrategy.IF_POSSIBLE.equals(strategy)) { int maxRetryCount = dataPartitioner.maxRetryCount(); diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/common/AtomicRangeInteger.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/common/AtomicRangeInteger.java index dac9a527..b47f8726 100644 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/common/AtomicRangeInteger.java +++ b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/common/AtomicRangeInteger.java @@ -22,8 +22,8 @@ import java.util.concurrent.atomic.AtomicIntegerArray; public class AtomicRangeInteger extends Number implements Serializable { - private static final long serialVersionUID = -4099792402691141643L; - private AtomicIntegerArray values; + private static final long serialVersionUID = -4099792402691141643L; + private AtomicIntegerArray values; private static final int VALUE_OFFSET = 15; diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/BulkConsumePool.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/BulkConsumePool.java index 2c5131ee..6aa8e2f8 100644 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/BulkConsumePool.java +++ b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/BulkConsumePool.java @@ -33,8 +33,8 @@ * In typical case, the number of {@link MultipleChannelsConsumer} should be less than the number of channels. */ public class BulkConsumePool implements ConsumerPool { - private List allConsumers; - private volatile boolean isStarted = false; + private List allConsumers; + private volatile boolean isStarted = false; public BulkConsumePool(String name, int size, long consumeCycle) { size = EnvUtil.getInt(name + "_THREAD", size); @@ -99,8 +99,8 @@ public void begin(Channels channels) { */ public static class Creator implements Callable { private String name; - private int size; - private long consumeCycle; + private int size; + private long consumeCycle; public Creator(String name, int poolSize, long consumeCycle) { this.name = name; diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumeDriver.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumeDriver.java index d84c4c53..11153a14 100644 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumeDriver.java +++ b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumeDriver.java @@ -28,10 +28,10 @@ * Pool of consumers

Created by wusheng on 2016/10/25. */ public class ConsumeDriver implements IDriver { - private boolean running; + private boolean running; private ConsumerThread[] consumerThreads; - private Channels channels; - private ReentrantLock lock; + private Channels channels; + private ReentrantLock lock; public ConsumeDriver(String name, Channels channels, Class> consumerClass, int num, long consumeCycle) { diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerThread.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerThread.java index f22d9284..d18d44d6 100644 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerThread.java +++ b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerThread.java @@ -26,10 +26,10 @@ import java.util.List; public class ConsumerThread extends Thread { - private volatile boolean running; - private IConsumer consumer; - private List dataSources; - private long consumeCycle; + private volatile boolean running; + private IConsumer consumer; + private List dataSources; + private long consumeCycle; ConsumerThread(String threadName, IConsumer consumer, long consumeCycle) { super(threadName); diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/MultipleChannelsConsumer.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/MultipleChannelsConsumer.java index ff66d9b1..089da23c 100644 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/MultipleChannelsConsumer.java +++ b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/MultipleChannelsConsumer.java @@ -30,11 +30,11 @@ * IConsumer}s */ public class MultipleChannelsConsumer extends Thread { - private volatile boolean running; + private volatile boolean running; private volatile ArrayList consumeTargets; @SuppressWarnings("NonAtomicVolatileUpdate") - private volatile long size; - private final long consumeCycle; + private volatile long size; + private final long consumeCycle; public MultipleChannelsConsumer(String threadName, long consumeCycle) { super(threadName); @@ -114,7 +114,7 @@ void shutdown() { } private static class Group { - private Channels channels; + private Channels channels; private IConsumer consumer; public Group(Channels channels, IConsumer consumer) { diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java index 60b9ad41..10765b92 100644 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java @@ -23,7 +23,7 @@ public EventControllerFactory(ThreadPoolFactory threadPoolFactory) { this.threadPoolFactory = threadPoolFactory; } - private final Map syncControllerMap = new ConcurrentHashMap(); + private final Map syncControllerMap = new ConcurrentHashMap(); private final Map asyncControllerMap = new ConcurrentHashMap(); public EventController getAsyncController() { diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/ThreadPoolFactory.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/ThreadPoolFactory.java index ffb49ffe..134afe69 100644 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/ThreadPoolFactory.java +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/ThreadPoolFactory.java @@ -27,10 +27,10 @@ public class ThreadPoolFactory { private static final Logger LOG = LoggerFactory.getLogger(ThreadPoolFactory.class); private final Map threadPoolExecutorMap = new ConcurrentHashMap<>(); - private ThreadPoolExecutor threadPoolExecutor; + private ThreadPoolExecutor threadPoolExecutor; private final ThreadCustomization threadCustomization; - private final ThreadParameter threadParameter; + private final ThreadParameter threadParameter; public ThreadPoolFactory(ThreadCustomization threadCustomization, ThreadParameter threadParameter) { this.threadCustomization = threadCustomization; @@ -39,7 +39,7 @@ public ThreadPoolFactory(ThreadCustomization threadCustomization, ThreadParamete public ThreadPoolExecutor getThreadPoolExecutor(String threadPoolName) { boolean threadPoolMultiMode = threadCustomization.isThreadPoolMultiMode(); - String poolName = createThreadPoolName(threadPoolName); + String poolName = createThreadPoolName(threadPoolName); if (threadPoolMultiMode) { ThreadPoolExecutor threadPoolExecutor = threadPoolExecutorMap.get(poolName); @@ -88,13 +88,13 @@ private ThreadPoolExecutor createThreadPoolExecutor(String threadPoolName) { } public static ThreadPoolExecutor createThreadPoolExecutor(String threadPoolName, ThreadParameter threadParameter) { - int corePoolSize = threadParameter.getThreadPoolCorePoolSize(); - int maximumPoolSize = threadParameter.getThreadPoolMaximumPoolSize(); - long keepAliveTime = threadParameter.getThreadPoolKeepAliveTime(); + int corePoolSize = threadParameter.getThreadPoolCorePoolSize(); + int maximumPoolSize = threadParameter.getThreadPoolMaximumPoolSize(); + long keepAliveTime = threadParameter.getThreadPoolKeepAliveTime(); boolean allowCoreThreadTimeout = threadParameter.isThreadPoolAllowCoreThreadTimeout(); - String queue = threadParameter.getThreadPoolQueue(); - int queueCapacity = threadParameter.getThreadPoolQueueCapacity(); - String rejectedPolicy = threadParameter.getThreadPoolRejectedPolicy(); + String queue = threadParameter.getThreadPoolQueue(); + int queueCapacity = threadParameter.getThreadPoolQueueCapacity(); + String rejectedPolicy = threadParameter.getThreadPoolRejectedPolicy(); LOG.info("Thread pool executor is created, threadPoolName={}, threadParameter={}", threadPoolName, threadParameter); @@ -118,13 +118,13 @@ public Thread newThread(Runnable runnable) { } public static ThreadPoolExecutor createThreadPoolExecutor(ThreadParameter threadParameter) { - int corePoolSize = threadParameter.getThreadPoolCorePoolSize(); - int maximumPoolSize = threadParameter.getThreadPoolMaximumPoolSize(); - long keepAliveTime = threadParameter.getThreadPoolKeepAliveTime(); + int corePoolSize = threadParameter.getThreadPoolCorePoolSize(); + int maximumPoolSize = threadParameter.getThreadPoolMaximumPoolSize(); + long keepAliveTime = threadParameter.getThreadPoolKeepAliveTime(); boolean allowCoreThreadTimeout = threadParameter.isThreadPoolAllowCoreThreadTimeout(); - String queue = threadParameter.getThreadPoolQueue(); - int queueCapacity = threadParameter.getThreadPoolQueueCapacity(); - String rejectedPolicy = threadParameter.getThreadPoolRejectedPolicy(); + String queue = threadParameter.getThreadPoolQueue(); + int queueCapacity = threadParameter.getThreadPoolQueueCapacity(); + String rejectedPolicy = threadParameter.getThreadPoolRejectedPolicy(); LOG.info("Thread pool executor is created, threadParameter={}", threadParameter); diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/constant/ThreadConstant.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/constant/ThreadConstant.java index 42d6eaa2..2d4f8934 100644 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/constant/ThreadConstant.java +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/constant/ThreadConstant.java @@ -3,17 +3,17 @@ public class ThreadConstant { public static final int CPUS = Math.max(2, Runtime.getRuntime().availableProcessors()); - public static final String THREAD_POOL_MULTI_MODE = "threadpool.multi.mode"; - public static final String THREAD_POOL_SHARED_NAME = "threadpool.shared.name"; - public static final String THREAD_POOL_NAME_CUSTOMIZED = "threadpool.name.customized"; - public static final String THREAD_POOL_NAME_IP_SHOWN = "threadpool.name.ipshown"; - public static final String THREAD_POOL_CORE_POOL_SIZE = "threadpool.core.pool.size"; - public static final String THREAD_POOL_MAXIMUM_POOL_SIZE = "threadpool.maximum.pool.size"; - public static final String THREAD_POOL_KEEP_ALIVE_TIME = "threadpool.keep.alive.time"; + public static final String THREAD_POOL_MULTI_MODE = "threadpool.multi.mode"; + public static final String THREAD_POOL_SHARED_NAME = "threadpool.shared.name"; + public static final String THREAD_POOL_NAME_CUSTOMIZED = "threadpool.name.customized"; + public static final String THREAD_POOL_NAME_IP_SHOWN = "threadpool.name.ipshown"; + public static final String THREAD_POOL_CORE_POOL_SIZE = "threadpool.core.pool.size"; + public static final String THREAD_POOL_MAXIMUM_POOL_SIZE = "threadpool.maximum.pool.size"; + public static final String THREAD_POOL_KEEP_ALIVE_TIME = "threadpool.keep.alive.time"; public static final String THREAD_POOL_ALLOW_CORE_THREAD_TIMEOUT = "threadpool.allow.core.thread.timeout"; - public static final String THREAD_POOL_QUEUE = "threadpool.queue"; - public static final String THREAD_POOL_QUEUE_CAPACITY = "threadpool.queue.capacity"; - public static final String THREAD_POOL_REJECTED_POLICY = "threadpool.rejected.policy"; + public static final String THREAD_POOL_QUEUE = "threadpool.queue"; + public static final String THREAD_POOL_QUEUE_CAPACITY = "threadpool.queue.capacity"; + public static final String THREAD_POOL_REJECTED_POLICY = "threadpool.rejected.policy"; - public static final String DEFAULT_THREADPOOL_SHARED_NAME = "SharedThreadPool"; + public static final String DEFAULT_THREADPOOL_SHARED_NAME = "SharedThreadPool"; } \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadCustomization.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadCustomization.java index 35492bda..3c84e597 100644 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadCustomization.java +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadCustomization.java @@ -16,10 +16,10 @@ public class ThreadCustomization implements Serializable { private static final long serialVersionUID = -927120657442228832L; - private boolean threadPoolMultiMode = false; - private String threadPoolSharedName = ThreadConstant.DEFAULT_THREADPOOL_SHARED_NAME; + private boolean threadPoolMultiMode = false; + private String threadPoolSharedName = ThreadConstant.DEFAULT_THREADPOOL_SHARED_NAME; private boolean threadPoolNameCustomized = true; - private boolean threadPoolNameIPShown = true; + private boolean threadPoolNameIPShown = true; public boolean isThreadPoolMultiMode() { return threadPoolMultiMode; diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadParameter.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadParameter.java index 244e12f2..96019089 100644 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadParameter.java +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadParameter.java @@ -16,13 +16,13 @@ public class ThreadParameter implements Serializable { private static final long serialVersionUID = 6869706244434951605L; - private int threadPoolCorePoolSize = ThreadConstant.CPUS; - private int threadPoolMaximumPoolSize = ThreadConstant.CPUS * 2; - private long threadPoolKeepAliveTime = 900000; + private int threadPoolCorePoolSize = ThreadConstant.CPUS; + private int threadPoolMaximumPoolSize = ThreadConstant.CPUS * 2; + private long threadPoolKeepAliveTime = 900000; private boolean threadPoolAllowCoreThreadTimeout = false; - private String threadPoolQueue = "LinkedBlockingQueue"; - private int threadPoolQueueCapacity = ThreadConstant.CPUS * 128; - private String threadPoolRejectedPolicy = "BlockingPolicyWithReport"; + private String threadPoolQueue = "LinkedBlockingQueue"; + private int threadPoolQueueCapacity = ThreadConstant.CPUS * 128; + private String threadPoolRejectedPolicy = "BlockingPolicyWithReport"; @Override diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/NetUtil.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/NetUtil.java index bcd7e9cc..f11e0dfc 100644 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/NetUtil.java +++ b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/NetUtil.java @@ -121,6 +121,7 @@ public static String getLocalHost() { /** * Find first valid IP from local network card + * * @return first valid local IP */ public static InetAddress getLocalAddress() { diff --git a/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/PropertyPlaceholderHelper.java b/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/PropertyPlaceholderHelper.java index a6fcbff7..373a5af2 100644 --- a/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/PropertyPlaceholderHelper.java +++ b/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/PropertyPlaceholderHelper.java @@ -55,6 +55,7 @@ public enum PropertyPlaceholderHelper { */ PropertyPlaceholderHelper(String placeholderPrefix, String placeholderSuffix, String valueSeparator, boolean ignoreUnresolvablePlaceholders) { + if (StringUtil.isEmpty(placeholderPrefix) || StringUtil.isEmpty(placeholderSuffix)) { throw new UnsupportedOperationException("'placeholderPrefix or placeholderSuffix' must not be null"); } @@ -125,7 +126,7 @@ protected String parseStringValue(String value, PlaceholderResolver placeholderR while (startIndex != -1) { int endIndex = findPlaceholderEndIndex(result, startIndex); if (endIndex != -1) { - String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex); + String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex); String originalPlaceholder = placeholder; if (!visitedPlaceholders.add(originalPlaceholder)) { throw new IllegalArgumentException("Circular placeholder reference '" + originalPlaceholder + "' in property definitions"); @@ -139,7 +140,7 @@ protected String parseStringValue(String value, PlaceholderResolver placeholderR int separatorIndex = placeholder.indexOf(this.valueSeparator); if (separatorIndex != -1) { String actualPlaceholder = placeholder.substring(0, separatorIndex); - String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length()); + String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length()); propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder); if (propVal == null) { propVal = defaultValue; @@ -169,7 +170,7 @@ protected String parseStringValue(String value, PlaceholderResolver placeholderR } private int findPlaceholderEndIndex(CharSequence buf, int startIndex) { - int index = startIndex + this.placeholderPrefix.length(); + int index = startIndex + this.placeholderPrefix.length(); int withinNestedPlaceholder = 0; while (index < buf.length()) { if (StringUtil.substringMatch(buf, index, this.placeholderSuffix)) { diff --git a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java index 86de2f9d..c4860d8d 100644 --- a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java +++ b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java @@ -43,7 +43,7 @@ @Slf4j public class ApplicationConfigLoader implements ConfigLoader { private static final String DISABLE_SELECTOR = "-"; - private static final String SELECTOR = "selector"; + private static final String SELECTOR = "selector"; private final Yaml yaml = new Yaml(); diff --git a/iot-server/server-bootstrap/src/main/resources/application.yml b/iot-server/server-bootstrap/src/main/resources/application.yml index 437c40a8..33786125 100644 --- a/iot-server/server-bootstrap/src/main/resources/application.yml +++ b/iot-server/server-bootstrap/src/main/resources/application.yml @@ -44,7 +44,7 @@ core: # ndjson file read realtime server-transfer: - selector: ${ZS_SERVER_TRANSFER:default} + selector: ${ZS_SERVER_TRANSFER:-} default: name: ${ZS_TRANSFER_NAME:zeus-transfer} pattern: ${ZS_TRANSFER_PATTERN:/home/data/history-history-syncer-[0-9]{1}.ndjson} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java index f60c3931..50e2ff39 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java @@ -16,13 +16,13 @@ public class CoreModuleConfig extends ModuleConfig { private String nameSpace; private String restHost; - private int restPort; + private int restPort; private String restContextPath; - private int restMinThreads = 1; - private int restMaxThreads = 200; - private long restIdleTimeOut = 30000; - private int restAcceptorPriorityDelta = 0; - private int restAcceptQueueSize = 0; + private int restMinThreads = 1; + private int restMaxThreads = 200; + private long restIdleTimeOut = 30000; + private int restAcceptorPriorityDelta = 0; + private int restAcceptQueueSize = 0; /** diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java index 22c40d9d..da4b435d 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java @@ -32,11 +32,11 @@ */ public class CoreModuleProvider extends ModuleProvider { - private final CoreModuleConfig moduleConfig; - private ModelCamelContext camelContext; + private final CoreModuleConfig moduleConfig; + private ModelCamelContext camelContext; - private JettyServer jettyServer; - private ThreadPoolFactory threadPoolFactory; + private JettyServer jettyServer; + private ThreadPoolFactory threadPoolFactory; private EventControllerFactory eventControllerFactory; private final AnnotationScan annotationScan; diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordStreamProcessor.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordStreamProcessor.java index 8be2b52a..8488a4e2 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordStreamProcessor.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordStreamProcessor.java @@ -36,7 +36,7 @@ public void in(Record record) { public void create(ModuleDefineHolder moduleDefineHolder, Stream stream, Class recordClass) { StorageDAO storageDAO = moduleDefineHolder.find(StorageModule.NAME).provider().getService(StorageDAO.class); - IRecordDAO recordDAO = storageDAO.newRecordDao(); + IRecordDAO recordDAO = storageDAO.newRecordDao(); Model model = new Model(stream.name()); diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationScan.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationScan.java index 4382947a..c1ac3901 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationScan.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationScan.java @@ -52,8 +52,8 @@ public void registerListener(AnnotationListener listener) { * Begin to scan classes. */ public void scan() throws IOException, StorageException { - ClassPath classpath = ClassPath.from(this.getClass().getClassLoader()); - ImmutableSet classes = classpath.getTopLevelClassesRecursive("com.zmops.zeus.iot"); + ClassPath classpath = ClassPath.from(this.getClass().getClassLoader()); + ImmutableSet classes = classpath.getTopLevelClassesRecursive("com.zmops.zeus.iot"); for (ClassPath.ClassInfo classInfo : classes) { Class aClass = classInfo.load(); @@ -71,7 +71,7 @@ public void scan() throws IOException, StorageException { private class AnnotationListenerCache { private AnnotationListener listener; - private List> matchedClass; + private List> matchedClass; private AnnotationListenerCache(AnnotationListener listener) { this.listener = listener; diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/CamelContextHolderService.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/CamelContextHolderService.java index c9d19164..002a4e3a 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/CamelContextHolderService.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/CamelContextHolderService.java @@ -12,7 +12,7 @@ */ public class CamelContextHolderService implements Service { - private final CamelContext camelContext; + private final CamelContext camelContext; private final ModuleManager moduleManager; public CamelContextHolderService(CamelContext camelContext, ModuleManager moduleManager) { diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixSenderEndpoint.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixSenderEndpoint.java index 0b23ff98..327cd76a 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixSenderEndpoint.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixSenderEndpoint.java @@ -12,7 +12,7 @@ */ public class ZabbixSenderEndpoint extends DefaultEndpoint { - private final ModuleManager moduleManager; + private final ModuleManager moduleManager; private final ZabbixTrapperProducer producer; public ZabbixSenderEndpoint(String endpointUri, Component component, ModuleManager moduleManager) { diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java index d40facab..d2b90fdc 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java @@ -21,9 +21,9 @@ */ public class ZabbixTrapperProducer extends DefaultProducer { - private final ModuleManager moduleManager; + private final ModuleManager moduleManager; private final ItemDataTransferWorker itemDataTransferWorker; - private final ExecutorService itemValueThread = Executors.newFixedThreadPool(20); + private final ExecutorService itemValueThread = Executors.newFixedThreadPool(20); public ZabbixTrapperProducer(Endpoint endpoint, ModuleManager moduleManager) { @@ -39,8 +39,8 @@ public ZabbixTrapperProducer(Endpoint endpoint, ModuleManager moduleManager) { */ @Override public void process(Exchange exchange) { - Message message = exchange.getIn(); - List values = (List) message.getBody(); + Message message = exchange.getIn(); + List values = (List) message.getBody(); for (ItemValue itemValue : values) { if (StringUtil.isEmpty(itemValue.getHost()) diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java index 8dc5435e..37963e98 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/ByteArrayToItemValueProcess.java @@ -23,22 +23,22 @@ public class ByteArrayToItemValueProcess implements Processor { @Override public void process(Exchange exchange) throws Exception { - Message message = exchange.getIn(); - byte[] messageBytes = (byte[]) message.getBody(); + Message message = exchange.getIn(); + byte[] messageBytes = (byte[]) message.getBody(); String inputContext = new String(messageBytes, StandardCharsets.UTF_8); Map jsonMap = gson.fromJson(inputContext, Map.class); - String key = jsonMap.get("key"); - String value = jsonMap.get("value"); + String key = jsonMap.get("key"); + String value = jsonMap.get("value"); if (StringUtils.isBlank(key)) { return; } - String deviceId = key.substring(0, key.indexOf(".")); - String attributeKey = key.substring(key.indexOf(".") + 1); + String deviceId = key.substring(0, key.indexOf(".")); + String attributeKey = key.substring(key.indexOf(".") + 1); List itemValueList = new ArrayList<>(); - ItemValue item = new ItemValue(deviceId, System.currentTimeMillis()/1000); + ItemValue item = new ItemValue(deviceId, System.currentTimeMillis() / 1000); item.setKey(attributeKey); item.setValue(value); diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/JsonToItemValueProcess.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/JsonToItemValueProcess.java index 9490903f..43827796 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/JsonToItemValueProcess.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/process/JsonToItemValueProcess.java @@ -24,9 +24,9 @@ public class JsonToItemValueProcess implements Processor { @Override public void process(Exchange exchange) throws Exception { - Message message = exchange.getIn(); - InputStream bodyStream = (InputStream) message.getBody(); - String inputContext = this.analysisMessage(bodyStream); + Message message = exchange.getIn(); + InputStream bodyStream = (InputStream) message.getBody(); + String inputContext = this.analysisMessage(bodyStream); IOTDeviceValue iotValue = gson.fromJson(inputContext, IOTDeviceValue.class); @@ -46,9 +46,9 @@ public void process(Exchange exchange) throws Exception { private String analysisMessage(InputStream bodyStream) throws IOException { - ByteArrayOutputStream outStream = new ByteArrayOutputStream(); - byte[] contextBytes = new byte[4096]; - int realLen; + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + byte[] contextBytes = new byte[4096]; + int realLen; while ((realLen = bodyStream.read(contextBytes, 0, 4096)) != -1) { outStream.write(contextBytes, 0, realLen); } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java index 143109c8..9973e595 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java @@ -40,8 +40,8 @@ public String pathSpec() { */ @Override protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException, IOException { - GZIPInputStream gzin = new GZIPInputStream(req.getInputStream()); - BufferedReader reader = new BufferedReader(new InputStreamReader(gzin)); + GZIPInputStream gzin = new GZIPInputStream(req.getInputStream()); + BufferedReader reader = new BufferedReader(new InputStreamReader(gzin)); String line; while ((line = reader.readLine()) != null) { diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java index 047ce8c3..82657c1f 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java @@ -60,9 +60,9 @@ protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseExcept public String getJsonBody(HttpServletRequest req) throws IOException { - StringBuffer stringBuffer = new StringBuffer(); - String line = null; - BufferedReader reader = req.getReader(); + StringBuffer stringBuffer = new StringBuffer(); + String line = null; + BufferedReader reader = req.getReader(); while ((line = reader.readLine()) != null) { stringBuffer.append(line); } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/HttpItemTrapperHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/HttpItemTrapperHandler.java index 48c28549..95279b73 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/HttpItemTrapperHandler.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/HttpItemTrapperHandler.java @@ -29,7 +29,7 @@ public String pathSpec() { protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException, IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(req.getInputStream())); - String line; + String line; StringBuilder request = new StringBuilder(); while ((line = reader.readLine()) != null) { request.append(line); diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/ItemDataTransferWorker.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/ItemDataTransferWorker.java index fa7f2fe7..6008c1a8 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/ItemDataTransferWorker.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/ItemDataTransferWorker.java @@ -32,8 +32,8 @@ public class ItemDataTransferWorker extends TransferWorker { private final DataCarrier dataCarrier; - private final CounterMetrics iotDataTransferCounter; - private final Gson gson = new Gson(); + private final CounterMetrics iotDataTransferCounter; + private final Gson gson = new Gson(); public ItemDataTransferWorker(ModuleManager moduleManager) { super(moduleManager); @@ -80,9 +80,9 @@ public void prepareBatch(Collection lastCollection) { return; } - int maxBatchGetSize = 500; - final int batchSize = Math.min(maxBatchGetSize, lastCollection.size()); - List valueList = new ArrayList<>(); + int maxBatchGetSize = 500; + final int batchSize = Math.min(maxBatchGetSize, lastCollection.size()); + List valueList = new ArrayList<>(); for (ItemValue data : lastCollection) { valueList.add(data); diff --git a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerProvider.java b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerProvider.java index cf4834f2..41ea6e26 100644 --- a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerProvider.java +++ b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerProvider.java @@ -39,12 +39,12 @@ */ @Slf4j public class HealthCheckerProvider extends ModuleProvider { - private final AtomicDouble score = new AtomicDouble(); - private final AtomicReference details = new AtomicReference<>(); - private final HealthCheckerConfig config = new HealthCheckerConfig(); - private MetricsCollector collector; - private MetricsCreator metricsCreator; - private ScheduledExecutorService ses; + private final AtomicDouble score = new AtomicDouble(); + private final AtomicReference details = new AtomicReference<>(); + private final HealthCheckerConfig config = new HealthCheckerConfig(); + private MetricsCollector collector; + private MetricsCreator metricsCreator; + private ScheduledExecutorService ses; @Override public String name() { diff --git a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthQueryService.java b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthQueryService.java index 14232807..f64cedba 100644 --- a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthQueryService.java +++ b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthQueryService.java @@ -28,7 +28,7 @@ @RequiredArgsConstructor public class HealthQueryService implements Service { - private final AtomicDouble score; + private final AtomicDouble score; private final AtomicReference details; public HealthStatus checkHealth() { @@ -43,7 +43,7 @@ public HealthStatus checkHealth() { @Setter static class HealthStatus { // score == 0 means healthy, otherwise it's unhealthy. - private int score; + private int score; private String details; } } diff --git a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/hikaricp/JDBCHikariCPClient.java b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/hikaricp/JDBCHikariCPClient.java index 770242f2..687b5b0b 100644 --- a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/hikaricp/JDBCHikariCPClient.java +++ b/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/hikaricp/JDBCHikariCPClient.java @@ -38,9 +38,9 @@ public class JDBCHikariCPClient implements Client, HealthCheckable { private static final Logger LOGGER = LoggerFactory.getLogger(JDBCHikariCPClient.class); - private final HikariConfig hikariConfig; + private final HikariConfig hikariConfig; private final DelegatedHealthChecker healthChecker; - private HikariDataSource dataSource; + private HikariDataSource dataSource; public JDBCHikariCPClient(Properties properties) { hikariConfig = new HikariConfig(); @@ -95,7 +95,7 @@ public void execute(Connection connection, String sql) throws JDBCClientExceptio public int executeUpdate(Connection connection, String sql, Object... params) throws JDBCClientException { LOGGER.debug("execute query with result: {}", sql); - int result; + int result; PreparedStatement statement = null; try { statement = connection.prepareStatement(sql); @@ -119,7 +119,7 @@ public int executeUpdate(Connection connection, String sql, Object... params) th public ResultSet executeQuery(Connection connection, String sql, Object... params) throws JDBCClientException { LOGGER.debug("execute query with result: {}", sql); - ResultSet rs; + ResultSet rs; PreparedStatement statement = null; try { statement = connection.prepareStatement(sql); diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/BootstrapFlow.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/BootstrapFlow.java index 2ce3d1ab..2be6a541 100644 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/BootstrapFlow.java +++ b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/BootstrapFlow.java @@ -34,7 +34,7 @@ class BootstrapFlow { private static final Logger LOGGER = LoggerFactory.getLogger(BootstrapFlow.class); private Map loadedModules; - private List startupSequence; + private List startupSequence; BootstrapFlow(Map loadedModules) throws CycleDependencyException, ModuleNotFoundException { this.loadedModules = loadedModules; @@ -78,8 +78,8 @@ private void makeSequence() throws CycleDependencyException, ModuleNotFoundExcep do { int numOfToBeSequenced = allProviders.size(); for (int i = 0; i < allProviders.size(); i++) { - ModuleProvider provider = allProviders.get(i); - String[] requiredModules = provider.requiredModules(); + ModuleProvider provider = allProviders.get(i); + String[] requiredModules = provider.requiredModules(); if (CollectionUtils.isNotEmpty(requiredModules)) { boolean isAllRequiredModuleStarted = true; for (String module : requiredModules) { diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefine.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefine.java index 3c414354..25252b37 100644 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefine.java +++ b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefine.java @@ -105,8 +105,8 @@ private void copyProperties(ModuleConfig dest, Properties src, String moduleName } Enumeration propertyNames = src.propertyNames(); while (propertyNames.hasMoreElements()) { - String propertyName = (String) propertyNames.nextElement(); - Class destClass = dest.getClass(); + String propertyName = (String) propertyNames.nextElement(); + Class destClass = dest.getClass(); try { Field field = getDeclaredField(destClass, propertyName); field.setAccessible(true); diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleManager.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleManager.java index cc5f86b3..b12db3bb 100644 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleManager.java +++ b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleManager.java @@ -27,8 +27,8 @@ * TODO 使用 google guice @Inject 实现 */ public class ModuleManager implements ModuleDefineHolder { - private boolean isInPrepareStage = true; - private final Map loadedModules = new HashMap<>(); + private boolean isInPrepareStage = true; + private final Map loadedModules = new HashMap<>(); /** * Init the given modules @@ -36,8 +36,8 @@ public class ModuleManager implements ModuleDefineHolder { public void init(ApplicationConfiguration applicationConfiguration) throws ModuleNotFoundException, ProviderNotFoundException, ServiceNotProvidedException, CycleDependencyException, ModuleConfigException, ModuleStartException { - String[] moduleNames = applicationConfiguration.moduleList(); - ServiceLoader moduleServiceLoader = ServiceLoader.load(ModuleDefine.class); + String[] moduleNames = applicationConfiguration.moduleList(); + ServiceLoader moduleServiceLoader = ServiceLoader.load(ModuleDefine.class); ServiceLoader moduleProviderLoader = ServiceLoader.load(ModuleProvider.class); HashSet moduleSet = new HashSet<>(Arrays.asList(moduleNames)); diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleProvider.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleProvider.java index 5eb42d49..c47f121b 100644 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleProvider.java +++ b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleProvider.java @@ -30,9 +30,9 @@ */ public abstract class ModuleProvider implements ModuleServiceHolder { @Setter - private ModuleManager manager; + private ModuleManager manager; @Setter - private ModuleDefine moduleDefine; + private ModuleDefine moduleDefine; private final Map, Service> services = new HashMap<>(); public ModuleProvider() { diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyJsonHandler.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyJsonHandler.java index d9326ed9..fdc258d1 100644 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyJsonHandler.java +++ b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyJsonHandler.java @@ -76,9 +76,9 @@ private void replyError(HttpServletResponse response, String errorMessage, int s } public String getJsonBody(HttpServletRequest req) throws IOException { - StringBuffer stringBuffer = new StringBuffer(); - String line = null; - BufferedReader reader = req.getReader(); + StringBuffer stringBuffer = new StringBuffer(); + String line = null; + BufferedReader reader = req.getReader(); while ((line = reader.readLine()) != null) { stringBuffer.append(line); } diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServer.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServer.java index e1368b67..b57aca1c 100644 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServer.java +++ b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServer.java @@ -40,8 +40,8 @@ public class JettyServer implements Server { private static final Logger LOGGER = LoggerFactory.getLogger(JettyServer.class); private org.eclipse.jetty.server.Server server; - private ServletContextHandler servletContextHandler; - private JettyServerConfig jettyServerConfig; + private ServletContextHandler servletContextHandler; + private JettyServerConfig jettyServerConfig; public JettyServer(JettyServerConfig config) { this.jettyServerConfig = config; @@ -88,7 +88,7 @@ public void initialize() { server.setHandler(servletContextHandler); JettyDefaultHandler defaultHandler = new JettyDefaultHandler(); - ServletHolder defaultHolder = new ServletHolder(); + ServletHolder defaultHolder = new ServletHolder(); defaultHolder.setServlet(defaultHandler); servletContextHandler.addServlet(defaultHolder, defaultHandler.pathSpec()); diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServerConfig.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServerConfig.java index 7aa2f177..03b6ad0b 100644 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServerConfig.java +++ b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServerConfig.java @@ -28,19 +28,19 @@ public class JettyServerConfig { private String host; - private int port; + private int port; private String contextPath; @Builder.Default - private int jettyMinThreads = 1; + private int jettyMinThreads = 1; @Builder.Default - private int jettyMaxThreads = 200; + private int jettyMaxThreads = 200; @Builder.Default - private long jettyIdleTimeOut = 30000; + private long jettyIdleTimeOut = 30000; @Builder.Default - private int jettyAcceptorPriorityDelta = 0; + private int jettyAcceptorPriorityDelta = 0; @Builder.Default - private int jettyAcceptQueueSize = 0; + private int jettyAcceptQueueSize = 0; @Builder.Default - private int jettyHttpMaxRequestHeaderSize = 8192; + private int jettyHttpMaxRequestHeaderSize = 8192; } diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/pool/CustomThreadFactory.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/pool/CustomThreadFactory.java index 7cafdebf..38262b7d 100644 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/pool/CustomThreadFactory.java +++ b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/pool/CustomThreadFactory.java @@ -22,10 +22,10 @@ import java.util.concurrent.atomic.AtomicInteger; public class CustomThreadFactory implements ThreadFactory { - private final AtomicInteger poolNumber = new AtomicInteger(1); - private final ThreadGroup group; + private final AtomicInteger poolNumber = new AtomicInteger(1); + private final ThreadGroup group; private final AtomicInteger threadNumber = new AtomicInteger(1); - private final String namePrefix; + private final String namePrefix; public CustomThreadFactory(String name) { SecurityManager s = System.getSecurityManager(); diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/PrivateKeyUtil.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/PrivateKeyUtil.java index fa9b5fa3..12550638 100644 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/PrivateKeyUtil.java +++ b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/PrivateKeyUtil.java @@ -40,7 +40,7 @@ public class PrivateKeyUtil { * Load a RSA decryption key from a file (PEM or DER). */ public static InputStream loadDecryptionKey(String keyFilePath) throws GeneralSecurityException, IOException { - byte[] keyDataBytes = Files.readAllBytes(Paths.get(keyFilePath)); + byte[] keyDataBytes = Files.readAllBytes(Paths.get(keyFilePath)); String keyDataString = new String(keyDataBytes, StandardCharsets.UTF_8); if (keyDataString.contains(PKCS_1_PEM_HEADER)) { diff --git a/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/MultipleFilesChangeMonitor.java b/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/MultipleFilesChangeMonitor.java index 71f90d3a..a2260330 100644 --- a/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/MultipleFilesChangeMonitor.java +++ b/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/MultipleFilesChangeMonitor.java @@ -43,22 +43,22 @@ public class MultipleFilesChangeMonitor { /** * The backend scheduler to trigger all file monitoring. */ - private static ScheduledFuture FILE_MONITOR_TASK_SCHEDULER; - private static final ReentrantLock SCHEDULER_CHANGE_LOCK = new ReentrantLock(); + private static ScheduledFuture FILE_MONITOR_TASK_SCHEDULER; + private static final ReentrantLock SCHEDULER_CHANGE_LOCK = new ReentrantLock(); /** * The list contains all monitors. */ - private static final List MONITOR_INSTANCES = new ArrayList<>(); + private static final List MONITOR_INSTANCES = new ArrayList<>(); /** * The timestamp when last time do status checked. */ - private long lastCheckTimestamp = 0; + private long lastCheckTimestamp = 0; /** * The period of watching thread checking the file status. Unit is the second. */ - private final long watchingPeriodInSec; - private final List watchedFiles; + private final long watchingPeriodInSec; + private final List watchedFiles; private final FilesChangedNotifier notifier; /** @@ -195,11 +195,11 @@ private static class WatchedFile { /** * The last modify time of the {@link #filePath} */ - private long lastModifiedTimestamp = 0; + private long lastModifiedTimestamp = 0; /** * File content at the latest status. */ - private byte[] fileContent; + private byte[] fileContent; /** * Detect the file content change, if yes, reload the file content into the memory as cached data. @@ -222,9 +222,9 @@ boolean detectContentChanged() { if (lastModified != lastModifiedTimestamp) { // File modified timestamp changed. Need to read the file content. try (FileInputStream fileInputStream = new FileInputStream(targetFile)) { - byte[] b = new byte[1024]; + byte[] b = new byte[1024]; ByteArrayOutputStream os = new ByteArrayOutputStream(); - int c; + int c; while ((c = fileInputStream.read(b)) != -1) { os.write(b, 0, c); } diff --git a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttRouteBuilder.java b/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttRouteBuilder.java index c452f409..b3711b41 100644 --- a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttRouteBuilder.java +++ b/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttRouteBuilder.java @@ -17,7 +17,7 @@ public MqttRouteBuilder(MqttReceiverConfig mqttReceiverConfig) { @Override public void configure() throws Exception { - fromF("mqtt:zeus-iot-mqtt?host=tcp://%s:%d&subscribeTopicNames=34EAE784BC4A/up", mqttReceiverConfig.getHost(),mqttReceiverConfig.getPort()) + fromF("mqtt:zeus-iot-mqtt?host=tcp://%s:%d&subscribeTopicNames=34EAE784BC4A/up", mqttReceiverConfig.getHost(), mqttReceiverConfig.getPort()) .process(new ByteArrayToItemValueProcess()) .to("Zabbix"); } diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/service/ZabbixSenderService.java b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/service/ZabbixSenderService.java index 2c285f35..53678a0b 100644 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/service/ZabbixSenderService.java +++ b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/service/ZabbixSenderService.java @@ -36,17 +36,17 @@ public ZabbixSenderService(ModuleManager moduleManager) { * * @param message see * https://www.zabbix.com/documentation/current/manual/appendix/items/trapper - * - * { - * "request":"sender data", - * "data":[ - * { - * "host":"device.info", - * "key":"device.temp", - * "value":"86" - * } - * ] - * } + *

+ * { + * "request":"sender data", + * "data":[ + * { + * "host":"device.info", + * "key":"device.temp", + * "value":"86" + * } + * ] + * } * @return String * @throws IOException ex */ @@ -80,7 +80,7 @@ public String sendData(String message) throws IOException { StringBuilder resp = new StringBuilder(); int headLength = 13; - int bRead = 0; + int bRead = 0; while (true) { bRead = resStream.read(response); if (bRead <= 0) break; @@ -108,7 +108,7 @@ public String sendData(String message) throws IOException { private String zabbixResponseToMap(String resp) { Map result = gson.fromJson(resp, Map.class); - String[] infos = result.get("info").split(";"); + String[] infos = result.get("info").split(";"); Map resultMap = new HashMap<>(); diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java index 2c9e0a34..e8234106 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java @@ -36,7 +36,7 @@ public class SQLExecutor implements InsertRequest { private static final Logger LOGGER = LoggerFactory.getLogger(SQLExecutor.class); @Getter - private final String sql; + private final String sql; private final List param; public SQLExecutor(String sql, List param) { diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineBatchDAO.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineBatchDAO.java index 7557a041..bc929d37 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineBatchDAO.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineBatchDAO.java @@ -28,7 +28,7 @@ @Slf4j public class TDEngineBatchDAO implements IBatchDAO { - private final JDBCHikariCPClient tdengineClient; + private final JDBCHikariCPClient tdengineClient; private final DataCarrier dataCarrier; private final ExecutorService executor = Executors.newFixedThreadPool(10); @@ -69,7 +69,7 @@ public void flush(List prepareRequests) { executor.submit(() -> { PreparedStatement preparedStatement; - Connection connection = null; + Connection connection = null; try { connection = tdengineClient.getConnection(); preparedStatement = connection.prepareStatement(execSql.toString()); diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java index da7dae1e..091cdcfa 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java @@ -14,14 +14,14 @@ */ public class TDEngineDatabaseInstaller { - protected final Client client; - private final ModuleManager moduleManager; - private final TDEngineStorageConfig config; + protected final Client client; + private final ModuleManager moduleManager; + private final TDEngineStorageConfig config; - private static final String CREATE_ZEUS_STABLE_HISTORY = "create stable if not exists history(clock TIMESTAMP, value DOUBLE) tags (deviceid BINARY(20), itemid BINARY(20))"; + private static final String CREATE_ZEUS_STABLE_HISTORY = "create stable if not exists history(clock TIMESTAMP, value DOUBLE) tags (deviceid BINARY(20), itemid BINARY(20))"; private static final String CREATE_ZEUS_STABLE_HISTORY_UINT = "create stable if not exists history_uint(clock TIMESTAMP, value BIGINT) tags (deviceid BINARY(20), itemid BINARY(20))"; - private static final String CREATE_ZEUS_STABLE_TRENDS = "create stable if not exists trends(clock TIMESTAMP, value_min DOUBLE, value_avg DOUBLE, value_max DOUBLE) tags (hostid BINARY(20), itemid BINARY(20))"; + private static final String CREATE_ZEUS_STABLE_TRENDS = "create stable if not exists trends(clock TIMESTAMP, value_min DOUBLE, value_avg DOUBLE, value_max DOUBLE) tags (hostid BINARY(20), itemid BINARY(20))"; private static final String CREATE_ZEUS_STABLE_TRENDS_UINT = "create stable if not exists trends_uint(clock TIMESTAMP, value_min BIGINT, value_avg BIGINT, value_max BIGINT) tags (hostid BINARY(20), itemid BINARY(20))"; public TDEngineDatabaseInstaller(Client client, ModuleManager moduleManager, TDEngineStorageConfig config) { diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageConfig.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageConfig.java index f18b8ab8..1f4776bd 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageConfig.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageConfig.java @@ -13,12 +13,12 @@ public class TDEngineStorageConfig extends ModuleConfig { private final String driver = "com.taosdata.jdbc.TSDBDriver"; - private String url = ""; - private String user = ""; + private String url = ""; + private String user = ""; private String password = ""; - private int dataKeep = 365; //数据保留天数 - private int oneFileDays = 10; // 每多少天一个数据文件 + private int dataKeep = 365; //数据保留天数 + private int oneFileDays = 10; // 每多少天一个数据文件 private int memoryBlocks = 6; // 内存块数 - private int dataUpdate = 1; // 是否允许更新数据,1 允许 + private int dataUpdate = 1; // 是否允许更新数据,1 允许 } diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java index d837df38..ac244dba 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java @@ -21,7 +21,7 @@ public class TDEngineStorageProvider extends ModuleProvider { private final TDEngineStorageConfig config; - private JDBCHikariCPClient client; + private JDBCHikariCPClient client; public TDEngineStorageProvider() { this.config = new TDEngineStorageConfig(); @@ -59,7 +59,7 @@ public void prepare() throws ServiceNotProvidedException, ModuleStartException { @Override public void start() throws ServiceNotProvidedException, ModuleStartException { - MetricsCreator metricCreator = getManager().find(TelemetryModule.NAME).provider().getService(MetricsCreator.class); + MetricsCreator metricCreator = getManager().find(TelemetryModule.NAME).provider().getService(MetricsCreator.class); HealthCheckMetrics healthChecker = metricCreator.createHealthCheckerGauge("storage_tdengine", MetricsTag.EMPTY_KEY, MetricsTag.EMPTY_VALUE); client.registerChecker(healthChecker); diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineStorageDAO.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineStorageDAO.java index 2dd64348..d3a8d79a 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineStorageDAO.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineStorageDAO.java @@ -12,7 +12,7 @@ @RequiredArgsConstructor public class TDEngineStorageDAO implements StorageDAO { - private final ModuleManager manager; + private final ModuleManager manager; private final JDBCHikariCPClient client; diff --git a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/none/MetricsCollectorNoop.java b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/none/MetricsCollectorNoop.java index 0fc4b586..43da813d 100644 --- a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/none/MetricsCollectorNoop.java +++ b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/none/MetricsCollectorNoop.java @@ -19,7 +19,6 @@ package com.zmops.zeus.iot.server.telemetry.none; - import com.zmops.zeus.iot.server.telemetry.api.MetricFamily; import com.zmops.zeus.iot.server.telemetry.api.MetricsCollector; diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusHistogramMetrics.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusHistogramMetrics.java index 83d18ed3..53cada9f 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusHistogramMetrics.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusHistogramMetrics.java @@ -30,7 +30,7 @@ public class PrometheusHistogramMetrics extends HistogramMetrics { private final double[] buckets; public PrometheusHistogramMetrics(String name, String tips, MetricsTag.Keys labels, MetricsTag.Values values, - double... buckets) { + double... buckets) { inner = new InnerMetricObject(name, tips, labels, values); this.buckets = buckets; } diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCollector.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCollector.java index 08d647a6..d9e76f2f 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCollector.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCollector.java @@ -29,14 +29,15 @@ import java.util.List; public class PrometheusMetricsCollector implements MetricsCollector { - @Override public Iterable collect() { + @Override + public Iterable collect() { Enumeration mfs = CollectorRegistry.defaultRegistry.metricFamilySamples(); List result = new LinkedList<>(); while (mfs.hasMoreElements()) { Collector.MetricFamilySamples metricFamilySamples = mfs.nextElement(); List samples = new ArrayList<>(metricFamilySamples.samples.size()); MetricFamily m = new MetricFamily(metricFamilySamples.name, MetricFamily.Type.valueOf(metricFamilySamples.type - .name()), metricFamilySamples.help, samples); + .name()), metricFamilySamples.help, samples); result.add(m); for (Collector.MetricFamilySamples.Sample sample : metricFamilySamples.samples) { samples.add(new MetricFamily.Sample(sample.name, sample.labelNames, sample.labelValues, sample.value, sample.timestampMs)); diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCreator.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCreator.java index 355316f0..39150caf 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCreator.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCreator.java @@ -26,7 +26,7 @@ public class PrometheusMetricsCreator implements MetricsCreator { @Override public CounterMetrics createCounter(String name, String tips, MetricsTag.Keys tagKeys, - MetricsTag.Values tagValues) { + MetricsTag.Values tagValues) { return new PrometheusCounterMetrics(name, tips, tagKeys, tagValues); } @@ -37,7 +37,7 @@ public GaugeMetrics createGauge(String name, String tips, MetricsTag.Keys tagKey @Override public HistogramMetrics createHistogramMetric(String name, String tips, MetricsTag.Keys tagKeys, - MetricsTag.Values tagValues, double... buckets) { + MetricsTag.Values tagValues, double... buckets) { return new PrometheusHistogramMetrics(name, tips, tagKeys, tagValues, buckets); } } diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServer.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServer.java index e38df0b2..623e9612 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServer.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServer.java @@ -53,10 +53,10 @@ public void start() throws InterruptedException { } // Configure the server. - ThreadFactory tf = new ThreadFactoryBuilder().setDaemon(true).build(); - EventLoopGroup bossGroup = new NioEventLoopGroup(1, tf); - EventLoopGroup workerGroup = new NioEventLoopGroup(0, tf); - ServerBootstrap b = new ServerBootstrap(); + ThreadFactory tf = new ThreadFactoryBuilder().setDaemon(true).build(); + EventLoopGroup bossGroup = new NioEventLoopGroup(1, tf); + EventLoopGroup workerGroup = new NioEventLoopGroup(0, tf); + ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)) diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServerHandler.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServerHandler.java index c063c1a6..382e9b86 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServerHandler.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServerHandler.java @@ -42,8 +42,8 @@ @Slf4j public class HttpServerHandler extends SimpleChannelInboundHandler { - private final CollectorRegistry registry = CollectorRegistry.defaultRegistry; - private final StringBuilderWriter buf = new StringBuilderWriter(); + private final CollectorRegistry registry = CollectorRegistry.defaultRegistry; + private final StringBuilderWriter buf = new StringBuilderWriter(); @Override public void channelReadComplete(ChannelHandlerContext ctx) { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java index 47cf3d88..39884351 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java @@ -106,7 +106,7 @@ void updateConfig(HashMap keyDeptPath, int dept, JsonElement tm } } else if (tmpElement instanceof JsonArray) { JsonArray tmpJsonArray = tmpElement.getAsJsonArray(); - String lastKey = keyDeptPath.getOrDefault(dept - 1, ""); + String lastKey = keyDeptPath.getOrDefault(dept - 1, ""); for (int index = 0; index < tmpJsonArray.size(); index++) { keyDeptPath.put(dept - 1, lastKey + "[" + index + "]"); updateConfig(keyDeptPath, dept, tmpJsonArray.get(index)); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java index 46a22830..af24042b 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java @@ -2,7 +2,7 @@ public class CommonConstants { - public static final String PROXY_BID = "proxy.bid"; + public static final String PROXY_BID = "proxy.bid"; public static final String POSITION_SUFFIX = ".position"; public static final String PROXY_TID = "proxy.tid"; @@ -25,12 +25,12 @@ public class CommonConstants { public static final int DEFAULT_PROXY_BATCH_FLUSH_INTERVAL = 100; - public static final String PROXY_KEY_BID = "bid"; - public static final String PROXY_KEY_TID = "tid"; - public static final String PROXY_KEY_ID = "id"; + public static final String PROXY_KEY_BID = "bid"; + public static final String PROXY_KEY_TID = "tid"; + public static final String PROXY_KEY_ID = "id"; public static final String PROXY_KEY_AGENT_IP = "agentip"; - public static final String PROXY_OCEANUS_F = "f"; - public static final String PROXY_OCEANUS_BL = "bl"; + public static final String PROXY_OCEANUS_F = "f"; + public static final String PROXY_OCEANUS_BL = "bl"; public static final String FILE_MAX_NUM = "file.max.num"; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java index ee9e5846..1e21fbdc 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java @@ -7,16 +7,16 @@ public class JobConstants extends CommonConstants { // job id - public static final String JOB_ID = "job.id"; + public static final String JOB_ID = "job.id"; public static final String JOB_INSTANCE_ID = "job.instance.id"; - public static final String JOB_IP = "job.ip"; - public static final String JOB_RETRY = "job.retry"; + public static final String JOB_IP = "job.ip"; + public static final String JOB_RETRY = "job.retry"; - public static final String JOB_TRIGGER = "job.trigger"; - public static final String JOB_NAME = "job.name"; + public static final String JOB_TRIGGER = "job.trigger"; + public static final String JOB_NAME = "job.name"; public static final String JOB_LINE_FILTER_PATTERN = "job.pattern"; - public static final String DEFAULT_JOB_NAME = "default"; - public static final String JOB_DESCRIPTION = "job.description"; + public static final String DEFAULT_JOB_NAME = "default"; + public static final String JOB_DESCRIPTION = "job.description"; public static final String DEFAULT_JOB_DESCRIPTION = "default job description"; public static final String DEFAULT_JOB_LINE_FILTER = ""; @@ -30,9 +30,9 @@ public class JobConstants extends CommonConstants { public static final String DEFAULT_JOB_FILE_TIME_OFFSET = "0d"; - public static final String JOB_FILE_MAX_WAIT = "job.file.max.wait"; + public static final String JOB_FILE_MAX_WAIT = "job.file.max.wait"; // time in min - public static final int DEFAULT_JOB_FILE_MAX_WAIT = 1; + public static final int DEFAULT_JOB_FILE_MAX_WAIT = 1; public static final String JOB_DIR_FILTER_PATTERN = "job.dir.pattern"; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConfiguration.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConfiguration.java index ffd1e810..f12321f7 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConfiguration.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConfiguration.java @@ -21,7 +21,7 @@ public class TransferConfiguration extends AbstractConfiguration { private static final Logger LOGGER = LoggerFactory.getLogger(TransferConfiguration.class); private static final String DEFAULT_CONFIG_FILE = "tansfer.properties"; - private static final String TMP_CONFIG_FILE = ".tmp.agent.properties"; + private static final String TMP_CONFIG_FILE = ".tmp.agent.properties"; private static final ArrayList LOCAL_RESOURCES = new ArrayList<>(); @@ -59,8 +59,8 @@ public static TransferConfiguration getAgentConf() { } private String getNextBackupFileName() { - SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); - String dateStr = format.format(new Date(System.currentTimeMillis())); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); + String dateStr = format.format(new Date(System.currentTimeMillis())); return DEFAULT_CONFIG_FILE + "." + dateStr; } @@ -75,7 +75,7 @@ public void flushToLocalPropertiesFile() { File sourceFile = new File(agentConfParent, DEFAULT_CONFIG_FILE); File targetFile = new File(agentConfParent, getNextBackupFileName()); - File tmpFile = new File(agentConfParent, TMP_CONFIG_FILE); + File tmpFile = new File(agentConfParent, TMP_CONFIG_FILE); if (sourceFile.exists()) { FileUtils.copyFile(sourceFile, targetFile); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java index 7d489927..78334d88 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java @@ -2,86 +2,86 @@ public class TransferConstants { - public static final String AGENT_HOME = "agent.home"; + public static final String AGENT_HOME = "agent.home"; public static final String DEFAULT_AGENT_HOME = System.getProperty("agent.home"); - public static final String AGENT_LOCAL_STORE_PATH = "agent.localStore.path"; + public static final String AGENT_LOCAL_STORE_PATH = "agent.localStore.path"; public static final String DEFAULT_AGENT_LOCAL_STORE_PATH = ".bdb"; - public static final String AGENT_DB_INSTANCE_NAME = "agent.db.instance.name"; + public static final String AGENT_DB_INSTANCE_NAME = "agent.db.instance.name"; public static final String DEFAULT_AGENT_DB_INSTANCE_NAME = "agent"; - public static final String AGENT_DB_CLASSNAME = "agent.db.classname"; + public static final String AGENT_DB_CLASSNAME = "agent.db.classname"; public static final String DEFAULT_AGENT_DB_CLASSNAME = "com.zmops.zeus.iot.server.transfer.core.db.BerkeleyDbImp"; - public static final String AGENT_CONF_PARENT = "agent.conf.parent"; + public static final String AGENT_CONF_PARENT = "agent.conf.parent"; public static final String DEFAULT_AGENT_CONF_PARENT = "conf"; - public static final String AGENT_LOCAL_STORE_READONLY = "agent.localStore.readonly"; + public static final String AGENT_LOCAL_STORE_READONLY = "agent.localStore.readonly"; public static final boolean DEFAULT_AGENT_LOCAL_STORE_READONLY = false; - public static final String TRIGGER_FETCH_INTERVAL = "trigger.fetch.interval"; - public static final int DEFAULT_TRIGGER_FETCH_INTERVAL = 1; + public static final String TRIGGER_FETCH_INTERVAL = "trigger.fetch.interval"; + public static final int DEFAULT_TRIGGER_FETCH_INTERVAL = 1; - public static final String TRIGGER_MAX_RUNNING_NUM = "trigger.max.running.num"; - public static final int DEFAULT_TRIGGER_MAX_RUNNING_NUM = 4096; + public static final String TRIGGER_MAX_RUNNING_NUM = "trigger.max.running.num"; + public static final int DEFAULT_TRIGGER_MAX_RUNNING_NUM = 4096; - public static final String AGENT_LOCAL_STORE_TRANSACTIONAL = "agent.localStore.transactional"; + public static final String AGENT_LOCAL_STORE_TRANSACTIONAL = "agent.localStore.transactional"; public static final boolean DEFAULT_AGENT_LOCAL_STORE_TRANSACTIONAL = true; - public static final String AGENT_LOCAL_STORE_LOCK_TIMEOUT = "agent.localStore.lockTimeout"; - public static final int DEFAULT_AGENT_LOCAL_STORE_LOCK_TIMEOUT = 10000; + public static final String AGENT_LOCAL_STORE_LOCK_TIMEOUT = "agent.localStore.lockTimeout"; + public static final int DEFAULT_AGENT_LOCAL_STORE_LOCK_TIMEOUT = 10000; - public static final String AGENT_LOCAL_STORE_NO_SYNC_VOID = "agent.localStore.noSyncVoid"; + public static final String AGENT_LOCAL_STORE_NO_SYNC_VOID = "agent.localStore.noSyncVoid"; public static final boolean DEFAULT_AGENT_LOCAL_STORE_NO_SYNC_VOID = false; - public static final String AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID = "agent.localStore.WriteNoSyncVoid"; + public static final String AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID = "agent.localStore.WriteNoSyncVoid"; public static final boolean DEFAULT_AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID = false; - public static final String THREAD_POOL_AWAIT_TIME = "thread.pool.await.time"; + public static final String THREAD_POOL_AWAIT_TIME = "thread.pool.await.time"; // time in ms - public static final long DEFAULT_THREAD_POOL_AWAIT_TIME = 300; + public static final long DEFAULT_THREAD_POOL_AWAIT_TIME = 300; - public static final String JOB_MONITOR_INTERVAL = "job.monitor.interval"; - public static final int DEFAULT_JOB_MONITOR_INTERVAL = 5; + public static final String JOB_MONITOR_INTERVAL = "job.monitor.interval"; + public static final int DEFAULT_JOB_MONITOR_INTERVAL = 5; - public static final String JOB_FINISH_CHECK_INTERVAL = "job.finish.checkInterval"; - public static final long DEFAULT_JOB_FINISH_CHECK_INTERVAL = 6L; + public static final String JOB_FINISH_CHECK_INTERVAL = "job.finish.checkInterval"; + public static final long DEFAULT_JOB_FINISH_CHECK_INTERVAL = 6L; - public static final String TASK_RETRY_MAX_CAPACITY = "task.retry.maxCapacity"; - public static final int DEFAULT_TASK_RETRY_MAX_CAPACITY = 10000; + public static final String TASK_RETRY_MAX_CAPACITY = "task.retry.maxCapacity"; + public static final int DEFAULT_TASK_RETRY_MAX_CAPACITY = 10000; - public static final String TASK_MONITOR_INTERVAL = "task.monitor.interval"; - public static final int DEFAULT_TASK_MONITOR_INTERVAL = 6; + public static final String TASK_MONITOR_INTERVAL = "task.monitor.interval"; + public static final int DEFAULT_TASK_MONITOR_INTERVAL = 6; - public static final String TASK_RETRY_SUBMIT_WAIT_SECONDS = "task.retry.submit.waitSeconds"; - public static final int DEFAULT_TASK_RETRY_SUBMIT_WAIT_SECONDS = 5; + public static final String TASK_RETRY_SUBMIT_WAIT_SECONDS = "task.retry.submit.waitSeconds"; + public static final int DEFAULT_TASK_RETRY_SUBMIT_WAIT_SECONDS = 5; - public static final String TASK_MAX_RETRY_TIME = "task.maxRetry.time"; - public static final int DEFAULT_TASK_MAX_RETRY_TIME = 3; + public static final String TASK_MAX_RETRY_TIME = "task.maxRetry.time"; + public static final int DEFAULT_TASK_MAX_RETRY_TIME = 3; - public static final String TASK_PUSH_MAX_SECOND = "task.push.maxSecond"; - public static final int DEFAULT_TASK_PUSH_MAX_SECOND = 2; + public static final String TASK_PUSH_MAX_SECOND = "task.push.maxSecond"; + public static final int DEFAULT_TASK_PUSH_MAX_SECOND = 2; - public static final String TASK_PULL_MAX_SECOND = "task.pull.maxSecond"; - public static final int DEFAULT_TASK_PULL_MAX_SECOND = 2; + public static final String TASK_PULL_MAX_SECOND = "task.pull.maxSecond"; + public static final int DEFAULT_TASK_PULL_MAX_SECOND = 2; - public static final String CHANNEL_MEMORY_CAPACITY = "channel.memory.capacity"; - public static final int DEFAULT_CHANNEL_MEMORY_CAPACITY = 10000; + public static final String CHANNEL_MEMORY_CAPACITY = "channel.memory.capacity"; + public static final int DEFAULT_CHANNEL_MEMORY_CAPACITY = 10000; - public static final String TRIGGER_CHECK_INTERVAL = "trigger.check.interval"; - public static final int DEFAULT_TRIGGER_CHECK_INTERVAL = 2; + public static final String TRIGGER_CHECK_INTERVAL = "trigger.check.interval"; + public static final int DEFAULT_TRIGGER_CHECK_INTERVAL = 2; - public static final String JOB_DB_CACHE_TIME = "job.db.cache.time"; + public static final String JOB_DB_CACHE_TIME = "job.db.cache.time"; // cache for 3 days. - public static final long DEFAULT_JOB_DB_CACHE_TIME = 3 * 24 * 60 * 60 * 1000; + public static final long DEFAULT_JOB_DB_CACHE_TIME = 3 * 24 * 60 * 60 * 1000; - public static final String JOB_DB_CACHE_CHECK_INTERVAL = "job.db.cache.check.interval"; - public static final int DEFAULT_JOB_DB_CACHE_CHECK_INTERVAL = 60 * 60; + public static final String JOB_DB_CACHE_CHECK_INTERVAL = "job.db.cache.check.interval"; + public static final int DEFAULT_JOB_DB_CACHE_CHECK_INTERVAL = 60 * 60; } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java index 7942f067..a83c1f91 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java @@ -27,9 +27,9 @@ public class BerkeleyDbImp implements Db { private final EntityStore jobStore; private final EntityStore commandStore; - private final PrimaryIndex primaryIndex; + private final PrimaryIndex primaryIndex; private final SecondaryIndex secondaryIndex; - private final PrimaryIndex commandPrimaryIndex; + private final PrimaryIndex commandPrimaryIndex; private final SecondaryIndex fileNameSecondaryIndex; private final SecondaryIndex commandSecondaryIndex; @@ -76,7 +76,7 @@ private StoreConfig initStoreConfig() { * @return local path. */ private File tryToInitAndGetPath() { - String storePath = transferConfig.get(TransferConstants.AGENT_LOCAL_STORE_PATH, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_PATH); + String storePath = transferConfig.get(TransferConstants.AGENT_LOCAL_STORE_PATH, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_PATH); String parentPath = transferConfig.get(TransferConstants.AGENT_HOME, TransferConstants.DEFAULT_AGENT_HOME); File finalPath = new File(parentPath, storePath); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java index 03a45d0d..4ceaf5be 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java @@ -31,7 +31,7 @@ */ public class JobProfileDb { private static final Logger LOGGER = LoggerFactory.getLogger(JobProfileDb.class); - private final Db db; + private final Db db; public JobProfileDb(Db db) { this.db = db; @@ -87,8 +87,8 @@ public void storeJobFirstTime(JobProfile jobProfile) { * @param jobProfile */ public void updateJobProfile(JobProfile jobProfile) { - String instanceId = jobProfile.getInstanceId(); - KeyValueEntity entity = db.get(instanceId); + String instanceId = jobProfile.getInstanceId(); + KeyValueEntity entity = db.get(instanceId); if (entity == null) { LOGGER.warn("job profile {} doesn't exist, update job profile fail {}", instanceId, jobProfile.toJsonStr()); return; @@ -127,7 +127,7 @@ public JobProfile getJobProfile(String jobId) { public void removeExpireJobs(long expireTime) { // remove finished tasks List successEntityList = db.search(StateSearchKey.SUCCESS); - List failedEntityList = db.search(StateSearchKey.FAILED); + List failedEntityList = db.search(StateSearchKey.FAILED); List entityList = new ArrayList<>(successEntityList); @@ -137,7 +137,7 @@ public void removeExpireJobs(long expireTime) { if (entity.getKey().startsWith(JobConstants.JOB_ID_PREFIX)) { JobProfile profile = entity.getAsJobProfile(); - long storeTime = profile.getLong(JobConstants.JOB_STORE_TIME, 0); + long storeTime = profile.getLong(JobConstants.JOB_STORE_TIME, 0); long currentTime = System.currentTimeMillis(); if (storeTime == 0 || currentTime - storeTime > expireTime) { @@ -184,8 +184,8 @@ public JobProfile getJob(String fileName) { * @return - list of job profile. */ public List getJobs(StateSearchKey stateSearchKey) { - List entityList = db.search(stateSearchKey); - List profileList = new ArrayList<>(); + List entityList = db.search(stateSearchKey); + List profileList = new ArrayList<>(); for (KeyValueEntity entity : entityList) { if (entity.getKey().startsWith(JobConstants.JOB_ID_PREFIX)) { profileList.add(entity.getAsJobProfile()); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java index fc84862a..7c100db1 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java @@ -16,24 +16,24 @@ public class DateFormatRegex implements Filter { private static final Logger LOGGER = LoggerFactory.getLogger(DateFormatRegex.class); - private static final String YEAR = "YYYY"; + private static final String YEAR = "YYYY"; private static final String MONTH = "MM"; - private static final String DAY = "DD"; - private static final String HOUR = "HH"; + private static final String DAY = "DD"; + private static final String HOUR = "HH"; private static final String NORMAL_FORMATTER = "yyyyMMddHHmm"; - private static final String OFFSET_DAY = "d"; - private static final String OFFSET_MIN = "m"; + private static final String OFFSET_DAY = "d"; + private static final String OFFSET_MIN = "m"; private static final String OFFSET_HOUR = "h"; - private int dayOffset = 0; - private int hourOffset = 0; + private int dayOffset = 0; + private int hourOffset = 0; private int minuteOffset = 0; private String formattedTime = ""; private String formattedRegex; - private File file; + private File file; /** * set regex with current time @@ -55,7 +55,7 @@ public boolean match() { public DateFormatRegex withOffset(String timeOffset) { String number = StringUtils.substring(timeOffset, 0, timeOffset.length() - 1); - String mark = StringUtils.substring(timeOffset, timeOffset.length() - 1); + String mark = StringUtils.substring(timeOffset, timeOffset.length() - 1); switch (mark) { case OFFSET_DAY: diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java index bf021f85..7ff534e0 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java @@ -13,7 +13,7 @@ public class CommandDb { private static final Logger LOGGER = LoggerFactory.getLogger(CommandDb.class); public static final int MANAGER_SUCCESS_CODE = 0; - public static final int MANAGER_FAIL_CODE = 1; + public static final int MANAGER_FAIL_CODE = 1; private final Db db; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java index 57c15671..e88d6e55 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java @@ -49,7 +49,7 @@ public Job(JobProfile jobConf) { public List createTasks() { List taskList = new ArrayList<>(); - int index = 0; + int index = 0; try { LOGGER.info("job id: {}, job name {} ", getJobInstanceId(), getName()); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java index 9221a64f..892cd0e8 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java @@ -32,20 +32,20 @@ public class JobManager extends AbstractDaemon { private static final Logger LOGGER = LoggerFactory.getLogger(JobManager.class); // key is job instance id. - private ConcurrentHashMap jobs; + private ConcurrentHashMap jobs; // jobs which are not accepted by running pool. - private final ConcurrentHashMap pendingJobs; + private final ConcurrentHashMap pendingJobs; // job thread pool - private final ThreadPoolExecutor runningPool; - private final TransferManager transferManager; - private final int monitorInterval; - private final long jobDbCacheTime; - private final long jobDbCacheCheckInterval; + private final ThreadPoolExecutor runningPool; + private final TransferManager transferManager; + private final int monitorInterval; + private final long jobDbCacheTime; + private final long jobDbCacheCheckInterval; // job profile db is only used to recover instance which is not finished running. private final JobProfileDb jobConfDB; - private final JobMetrics jobMetrics; - private final AtomicLong index = new AtomicLong(0); + private final JobMetrics jobMetrics; + private final AtomicLong index = new AtomicLong(0); /** * init job manager diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java index 064c0dbd..6d679a0e 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java @@ -10,7 +10,7 @@ @Metrics public class JobMetrics { - private static final JobMetrics JOB_METRICS = new JobMetrics(); + private static final JobMetrics JOB_METRICS = new JobMetrics(); private static final AtomicBoolean REGISTER_ONCE = new AtomicBoolean(false); @Metric diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java index 6daff282..ee83abeb 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java @@ -24,9 +24,9 @@ public class JobWrapper extends AbstractStateWrapper { private static final Logger LOGGER = LoggerFactory.getLogger(JobWrapper.class); private final TransferConfiguration transferConfig; - private final TaskManager taskManager; - private final JobManager jobManager; - private final Job job; + private final TaskManager taskManager; + private final JobManager jobManager; + private final Job job; private final List allTasks; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/DefaultMessage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/DefaultMessage.java index 2d6dfd0b..d0943184 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/DefaultMessage.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/DefaultMessage.java @@ -8,7 +8,7 @@ public class DefaultMessage implements Message { - private final byte[] body; + private final byte[] body; private final Map header; public DefaultMessage(byte[] body, Map header) { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java index ab860371..f12012db 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java @@ -11,10 +11,10 @@ public class ProxyMessage implements Message { private static final String DEFAULT_TID = "__"; - private final byte[] body; + private final byte[] body; private final Map header; - private final String bid; - private final String tid; + private final String bid; + private final String tid; public ProxyMessage(byte[] body, Map header) { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java index 381ee0c5..f318fb36 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java @@ -32,7 +32,7 @@ public class TextFileSource implements Source { public List split(JobProfile jobConf) { Collection allFiles = FileSearchUtils.findSuitFiles(jobConf); - List result = new ArrayList<>(); + List result = new ArrayList<>(); String filterPattern = jobConf.get(JOB_LINE_FILTER_PATTERN, DEFAULT_JOB_LINE_FILTER); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java index e2a564ec..d0bb639c 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java @@ -36,17 +36,17 @@ public class TextFileReader implements Reader { public static final int NEVER_STOP_SIGN = -1; - private final File file; - private final int position; + private final File file; + private final int position; private final String md5; private Iterator iterator; - private Stream stream; + private Stream stream; private long timeout; private long lastTime = 0; - private final PluginMetric textFileMetric; + private final PluginMetric textFileMetric; private final List validators = new ArrayList<>(); public TextFileReader(File file, int position) { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java index f8a8ee2d..ff999175 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java @@ -11,10 +11,10 @@ */ public class Task { - private final String taskId; - private final Reader reader; - private final Sink sink; - private final Channel channel; + private final String taskId; + private final Reader reader; + private final Sink sink; + private final Channel channel; private final JobProfile jobConf; public Task(String taskId, Reader reader, Sink sink, Channel channel, JobProfile jobConf) { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java index 9a1f0df9..270f2d39 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java @@ -23,15 +23,15 @@ public class TaskManager extends AbstractDaemon { // task thread pool; private final ThreadPoolExecutor runningPool; - private final TransferManager transferManager; - private final TaskMetrics taskMetrics; + private final TransferManager transferManager; + private final TaskMetrics taskMetrics; private final ConcurrentHashMap tasks; - private final BlockingQueue retryTasks; + private final BlockingQueue retryTasks; - private final int monitorInterval; - private final int taskMaxCapacity; - private final int taskRetryMaxTime; + private final int monitorInterval; + private final int taskMaxCapacity; + private final int taskRetryMaxTime; private final long waitTime; /** diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java index 2ae4a896..c59b16fc 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java @@ -14,7 +14,7 @@ @Metrics public class TaskMetrics { - private static final TaskMetrics TASK_METRICS = new TaskMetrics(); + private static final TaskMetrics TASK_METRICS = new TaskMetrics(); private static final AtomicBoolean REGISTER_ONCE = new AtomicBoolean(false); @Metric diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java index 91427dc9..c060b836 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java @@ -25,7 +25,7 @@ public class TaskPositionManager extends AbstractDaemon { public static final int DEFAULT_FLUSH_TIMEOUT = 3; private final TransferManager transferManager; - private final JobProfileDb jobConfDb; + private final JobProfileDb jobConfDb; private final ConcurrentHashMap> jobTaskPositionMap; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java index 83fc1d06..2f691e07 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java @@ -26,7 +26,7 @@ public class TaskWrapper extends AbstractStateWrapper { public static final int WAIT_FINISH_TIME_OUT = 1; private final TaskManager taskManager; - private final Task task; + private final Task task; private final AtomicInteger retryTime = new AtomicInteger(0); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java index f9403f63..83814870 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java @@ -28,14 +28,14 @@ */ public class DirectoryTrigger extends AbstractDaemon implements Trigger { - private static final Logger LOGGER = LoggerFactory.getLogger(DirectoryTrigger.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DirectoryTrigger.class); private static volatile WatchService watchService; private final ConcurrentHashMap> allWatchers = new ConcurrentHashMap<>(); - private final LinkedBlockingQueue queue = new LinkedBlockingQueue<>(); + private final LinkedBlockingQueue queue = new LinkedBlockingQueue<>(); private TriggerProfile profile; - private int interval; + private int interval; private static void initWatchService() { try { @@ -163,7 +163,7 @@ private Runnable watchEventHandler() { try { TimeUnit.SECONDS.sleep(interval); allWatchers.forEach((pathPattern, watchKeys) -> { - List tmpWatchers = new ArrayList<>(); + List tmpWatchers = new ArrayList<>(); List tmpDeletedWatchers = new ArrayList<>(); pathPattern.cleanup(); @@ -208,7 +208,7 @@ public void register(String pathPattern, String offset) throws IOException { private void innerRegister(String pathPattern, PathPattern entity) throws IOException { List tmpKeyList = new ArrayList<>(); - List keyList = allWatchers.putIfAbsent(entity, tmpKeyList); + List keyList = allWatchers.putIfAbsent(entity, tmpKeyList); if (keyList == null) { Path rootPath = Paths.get(entity.getRootDir()); @@ -221,7 +221,7 @@ private void innerRegister(String pathPattern, PathPattern entity) throws IOExce } public void unregister(String pathPattern) { - PathPattern entity = new PathPattern(pathPattern); + PathPattern entity = new PathPattern(pathPattern); Collection allKeys = allWatchers.remove(entity); if (allKeys != null) { LOGGER.info("unregister pattern {}, total size of path {}", pathPattern, allKeys.size()); @@ -243,7 +243,7 @@ public void init(TriggerProfile profile) throws IOException { if (this.profile.hasKey(JobConstants.JOB_DIR_FILTER_PATTERN)) { String pathPattern = this.profile.get(JobConstants.JOB_DIR_FILTER_PATTERN); - String timeOffset = this.profile.get(JobConstants.JOB_FILE_TIME_OFFSET, ""); + String timeOffset = this.profile.get(JobConstants.JOB_FILE_TIME_OFFSET, ""); if (timeOffset.isEmpty()) { register(pathPattern); } diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/PathPattern.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/PathPattern.java index b38c0a90..86152b88 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/PathPattern.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/PathPattern.java @@ -26,8 +26,8 @@ public class PathPattern { private final DateFormatRegex dateFormatRegex; - private final String watchDir; - private final String rootDir; + private final String watchDir; + private final String rootDir; private final Set subDirs; public PathPattern(String watchDir) { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java index 57976607..0c9f5c43 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java @@ -33,7 +33,7 @@ public class TriggerManager extends AbstractDaemon { public static final int JOB_CHECK_INTERVAL = 1; - private final TransferManager manager; + private final TransferManager manager; private final TriggerProfileDb triggerProfileDB; private final ConcurrentHashMap triggerMap; @@ -62,8 +62,8 @@ public TriggerManager(TransferManager manager, TriggerProfileDb triggerProfileDb */ public boolean addTrigger(TriggerProfile triggerProfile) { try { - Trigger trigger = new DirectoryTrigger(); - String triggerId = triggerProfile.get(JOB_ID); + Trigger trigger = new DirectoryTrigger(); + String triggerId = triggerProfile.get(JOB_ID); if (triggerMap.containsKey(triggerId)) { deleteTrigger(triggerId); @@ -174,7 +174,7 @@ private Runnable jobCheckThread() { * @param profile */ private void addToTriggerMap(String triggerId, JobProfile profile) { - ConcurrentHashMap tmpList = new ConcurrentHashMap<>(); + ConcurrentHashMap tmpList = new ConcurrentHashMap<>(); ConcurrentHashMap jobWrappers = triggerJobMap.putIfAbsent(triggerId, tmpList); if (jobWrappers == null) { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/AgentDynamicMBean.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/AgentDynamicMBean.java index 4838b3ed..83be0dee 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/AgentDynamicMBean.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/AgentDynamicMBean.java @@ -19,12 +19,12 @@ public class AgentDynamicMBean implements DynamicMBean { private final ConcurrentHashMap> snapshotAttrs = new ConcurrentHashMap<>(); - private final MBeanInfo mBeanInfo; + private final MBeanInfo mBeanInfo; private final List attrs; - private final MetricsMeta metricsMeta; - private final String module; - private final String aspect; - private final String desc; + private final MetricsMeta metricsMeta; + private final String module; + private final String aspect; + private final String desc; public AgentDynamicMBean(String module, String aspect, String desc, MetricsMeta metricsMeta, Object source) { this.module = module; @@ -50,7 +50,7 @@ private void formatSnapshotList(Object source) { private MBeanInfo metricsMetaToInfo() { // overwrite name, desc from MetricsMeta if not null. - String name = this.module == null ? metricsMeta.getName() : this.module; + String name = this.module == null ? metricsMeta.getName() : this.module; String description = this.desc == null ? metricsMeta.getDesc() : this.desc; for (MetricMeta fieldMetricMeta : metricsMeta.getMetricMetaList()) { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricsRegister.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricsRegister.java index d82b342c..bb10537f 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricsRegister.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricsRegister.java @@ -26,9 +26,9 @@ public class MetricsRegister { private static final Logger LOGGER = LoggerFactory.getLogger(MetricsRegister.class); - private static final String DOMAIN_PREFIX = "Agent:"; - private static final String MODULE_PREFIX = "module="; - private static final String ASPECT_PREFIX = "aspect="; + private static final String DOMAIN_PREFIX = "Agent:"; + private static final String MODULE_PREFIX = "module="; + private static final String ASPECT_PREFIX = "aspect="; private static final String COMMA_SPLITTER = ","; // object name should be uniq @@ -47,7 +47,7 @@ private static void innerRegister(AgentDynamicMBean agentDynamicMBean) { String nameStr = DOMAIN_PREFIX + MODULE_PREFIX + agentDynamicMBean.getModule() + COMMA_SPLITTER + ASPECT_PREFIX + agentDynamicMBean.getAspect(); try { - ObjectName tmpName = new ObjectName(nameStr); + ObjectName tmpName = new ObjectName(nameStr); ObjectName objectName = CACHED_NAME.putIfAbsent(nameStr, tmpName); if (objectName == null) { mbs.registerMBean(agentDynamicMBean, tmpName); @@ -59,7 +59,7 @@ private static void innerRegister(AgentDynamicMBean agentDynamicMBean) { public static void register(String module, String aspect, String desc, Object source) { List metricMetaList = handleFieldAnnotation(source); - MetricsMeta metricsMeta = handleClassAnnotation(source, metricMetaList); + MetricsMeta metricsMeta = handleClassAnnotation(source, metricMetaList); if (metricsMeta != null) { innerRegister(new AgentDynamicMBean(module, aspect, desc, metricsMeta, source)); } else { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricMeta.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricMeta.java index 43c2ae60..0900368b 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricMeta.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricMeta.java @@ -19,7 +19,7 @@ public class MetricMeta { private String name; private String type; private String desc; - private Field field; + private Field field; public static MetricMeta build(Metric annotation, Field field) { MetricMeta metricMeta = new MetricMeta(); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricsMeta.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricsMeta.java index c4bf7ac3..6181b479 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricsMeta.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricsMeta.java @@ -9,9 +9,9 @@ */ public class MetricsMeta { - private String context; - private String desc; - private String name; + private String context; + private String desc; + private String name; private List metricMetaList; private MetricsMeta() { diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java index 6d08dd51..47cb86c1 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java @@ -27,7 +27,7 @@ public class SenderManager { private static final Logger LOGGER = LoggerFactory.getLogger(SenderManager.class); private final TaskPositionManager taskPositionManager; - private final String sourceFilePath; + private final String sourceFilePath; private final PluginMetric metric = new PluginMetric(); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/TransferUtils.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/TransferUtils.java index 7a2d5319..8d80b016 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/TransferUtils.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/TransferUtils.java @@ -30,20 +30,20 @@ public class TransferUtils { - private static final Logger LOGGER = LoggerFactory.getLogger(TransferUtils.class); - private static final AtomicLong INDEX = new AtomicLong(0); - private static final String HEX_PREFIX = "0x"; - public static final String EQUAL = "="; - public static final String M_VALUE = "m"; - public static final String ADDITION_SPLITTER = "&"; - public static final String BEIJING_TIME_ZONE = "GMT+8:00"; - public static final String HOUR_PATTERN = "yyyyMMddHH"; - public static final String DAY_PATTERN = "yyyyMMdd"; - public static final String DEFAULT_PATTERN = "yyyyMMddHHmm"; - public static final String DAY = "D"; - public static final String HOUR = "H"; - public static final String HOUR_LOW_CASE = "h"; - public static final String MINUTE = "m"; + private static final Logger LOGGER = LoggerFactory.getLogger(TransferUtils.class); + private static final AtomicLong INDEX = new AtomicLong(0); + private static final String HEX_PREFIX = "0x"; + public static final String EQUAL = "="; + public static final String M_VALUE = "m"; + public static final String ADDITION_SPLITTER = "&"; + public static final String BEIJING_TIME_ZONE = "GMT+8:00"; + public static final String HOUR_PATTERN = "yyyyMMddHH"; + public static final String DAY_PATTERN = "yyyyMMdd"; + public static final String DEFAULT_PATTERN = "yyyyMMddHHmm"; + public static final String DAY = "D"; + public static final String HOUR = "H"; + public static final String HOUR_LOW_CASE = "h"; + public static final String MINUTE = "m"; /** @@ -245,9 +245,9 @@ public static boolean regexMatch(String pathStr, String patternStr) { * @return */ public static Pair> parseAddAttr(String additionStr) { - Map attr = new HashMap<>(); - String[] split = additionStr.split(ADDITION_SPLITTER); - String mValue = ""; + Map attr = new HashMap<>(); + String[] split = additionStr.split(ADDITION_SPLITTER); + String mValue = ""; for (String s : split) { if (!s.contains(EQUAL)) { continue; diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/Async.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/Async.java index e8cb8a23..1fbd1d0d 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/Async.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/Async.java @@ -81,8 +81,8 @@ public static OnceWork work(long timeout, } //保存上次执行的线程池变量(为了兼容以前的旧功能) Async.lastExecutorService.set(Objects.requireNonNull(executorService, "ExecutorService is null ! ")); - final WorkerWrapperGroup group = new WorkerWrapperGroup(SystemClock.now(), timeout); - final OnceWork.Impl onceWork = new OnceWork.Impl(group, workId); + final WorkerWrapperGroup group = new WorkerWrapperGroup(SystemClock.now(), timeout); + final OnceWork.Impl onceWork = new OnceWork.Impl(group, workId); group.addWrapper(workerWrappers); workerWrappers.forEach(wrapper -> { if (wrapper == null) { diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/BiInt.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/BiInt.java index a33ef921..bdc9952d 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/BiInt.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/BiInt.java @@ -13,23 +13,23 @@ public final class BiInt { private final int m; private final int n; - public static final Comparator cmp_m_asc = Comparator.comparingInt(BiInt::getM); - public static final Comparator cmp_n_asc = Comparator.comparingInt(BiInt::getN); - public static final Comparator cmp_m_desc = cmp_m_asc.reversed(); - public static final Comparator cmp_n_desc = cmp_n_asc.reversed(); - public static final Comparator cmp_m_asc_n_asc = + public static final Comparator cmp_m_asc = Comparator.comparingInt(BiInt::getM); + public static final Comparator cmp_n_asc = Comparator.comparingInt(BiInt::getN); + public static final Comparator cmp_m_desc = cmp_m_asc.reversed(); + public static final Comparator cmp_n_desc = cmp_n_asc.reversed(); + public static final Comparator cmp_m_asc_n_asc = cmp_m_asc.thenComparing(cmp_n_asc); - public static final Comparator cmp_m_asc_n_desc = + public static final Comparator cmp_m_asc_n_desc = cmp_m_asc.thenComparing(cmp_n_desc); - public static final Comparator cmp_m_desc_n_asc = + public static final Comparator cmp_m_desc_n_asc = cmp_m_desc.thenComparing(cmp_n_asc); public static final Comparator cmp_m_desc_n_desc = cmp_m_desc.thenComparing(cmp_n_desc); - public static final Comparator cmp_n_asc_m_asc = + public static final Comparator cmp_n_asc_m_asc = cmp_n_asc.thenComparing(cmp_m_asc); - public static final Comparator cmp_n_asc_m_desc = + public static final Comparator cmp_n_asc_m_desc = cmp_n_asc.thenComparing(cmp_m_desc); - public static final Comparator cmp_n_desc_m_asc = + public static final Comparator cmp_n_desc_m_asc = cmp_n_desc.thenComparing(cmp_m_asc); public static final Comparator cmp_n_desc_m_desc = cmp_n_desc.thenComparing(cmp_m_desc); @@ -93,10 +93,10 @@ public static BiInt of(int m, int n) { // 缓存区间 - private static final BiInt MIN_TO_MAX = new BiInt(Integer.MIN_VALUE, Integer.MAX_VALUE); + private static final BiInt MIN_TO_MAX = new BiInt(Integer.MIN_VALUE, Integer.MAX_VALUE); private static final BiInt[] cache; // m from 0 to 31 , n from 0 to 31 , total 1023 . - private static final int CACHE_RANGE_M = 32; // 0 to 31 - private static final int CACHE_RANGE_N = 32; // 0 to 31 + private static final int CACHE_RANGE_M = 32; // 0 to 31 + private static final int CACHE_RANGE_N = 32; // 0 to 31 static { cache = new BiInt[CACHE_RANGE_M * CACHE_RANGE_N]; diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractArray2D.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractArray2D.java index a6d30a2d..0f728cd6 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractArray2D.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractArray2D.java @@ -32,7 +32,7 @@ public boolean equals(Object obj) { @Override public String toString() { - StringBuilder sb = new StringBuilder(64).append(this.getClass().getSimpleName()).append('{'); + StringBuilder sb = new StringBuilder(64).append(this.getClass().getSimpleName()).append('{'); Iterator> it = iterator(); if (it.hasNext()) { while (true) { @@ -49,7 +49,7 @@ public String toString() { public static class PointImpl implements Point { private final BiInt idx; - private final E element; + private final E element; public PointImpl(BiInt idx, E element) { this.idx = idx; diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractDirectedGraph.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractDirectedGraph.java index ae17f647..48a5b7f0 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractDirectedGraph.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractDirectedGraph.java @@ -14,7 +14,7 @@ public abstract class AbstractDirectedGraph implements DirectedGraph @Override public String toString() { - Set nv = nodesView(); + Set nv = nodesView(); Set> rSet = getRelations(); StringBuilder sb = new StringBuilder(nv.size() * 10 + rSet.size() * 20) .append(this.getClass().getSimpleName()).append("{nodes=["); diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonDirectedGraph.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonDirectedGraph.java index 89050cff..e7870275 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonDirectedGraph.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonDirectedGraph.java @@ -16,7 +16,7 @@ public class CommonDirectedGraph extends AbstractDirectedGraph { // ========== properties ========== private final StoreArk nodes = new CachedStoreArk<>(); - private final Array2D arr = new SparseArray2D<>(); + private final Array2D arr = new SparseArray2D<>(); // ========== methods ========== @@ -36,7 +36,7 @@ public boolean containsNode(N node) { @Override public Set> removeNode(N node) { - int id = findNodeId(Objects.requireNonNull(node), true); + int id = findNodeId(Objects.requireNonNull(node), true); LinkedHashSet> res = new LinkedHashSet<>(); // 查找node为from的键 arr.fullLine(id).forEach((toNodeId, relation) -> { @@ -67,7 +67,7 @@ public R putRelation(N fromNode, R relation, N toNode) { @Override public Set> getRelationFrom(N from) { - int id = findNodeId(Objects.requireNonNull(from), true); + int id = findNodeId(Objects.requireNonNull(from), true); LinkedHashSet> res = new LinkedHashSet<>(); // 查找node为from的键 arr.fullLine(id).forEach((toNodeId, relation) -> res.add(new OuterEntry<>(from, nodes.peek(toNodeId), relation))); @@ -76,7 +76,7 @@ public Set> getRelationFrom(N from) { @Override public Set> getRelationTo(N to) { - int id = findNodeId(Objects.requireNonNull(to), true); + int id = findNodeId(Objects.requireNonNull(to), true); LinkedHashSet> res = new LinkedHashSet<>(); // 查找node为to的键 arr.fullColumn(id).forEach((fromNodeId, relation) -> diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonStoreArk.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonStoreArk.java index fec1dbe6..d7e9e2f5 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonStoreArk.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonStoreArk.java @@ -81,7 +81,7 @@ public Iterator> iterator() { { //noinspection unchecked items = new Map.Entry[size()]; - int itemsIdx = 0; + int itemsIdx = 0; Iterator emptyPointItr = emptyPoints.iterator(); for (int i = 0; i < allocSize; i++) { Object element = elements[i]; @@ -148,7 +148,7 @@ private int pollId() { if (!emptyPoints.isEmpty()) { return emptyPoints.poll(); } - int id = allocSize++; + int id = allocSize++; int length = elements.length; if (id >= length) { // 扩容 diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/DirectedGraph.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/DirectedGraph.java index eb066627..ddd2dea9 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/DirectedGraph.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/DirectedGraph.java @@ -119,7 +119,7 @@ public Set> getRelations() { class SyncDirectedGraph extends AbstractDirectedGraph { private final DirectedGraph source; - private final Object mutex; + private final Object mutex; public SyncDirectedGraph(DirectedGraph source, Object mutex) { this.source = source; diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/SparseArray2D.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/SparseArray2D.java index 42a1b0b4..3befc13e 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/SparseArray2D.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/SparseArray2D.java @@ -19,8 +19,8 @@ public class SparseArray2D extends AbstractArray2D { /** * 限制长宽,默认为Integer.MAX_VALUE。稀疏数组不在乎这些。 */ - private final int maxLineLength; - private final int maxColumnLength; + private final int maxLineLength; + private final int maxColumnLength; private final boolean allowNull; private final Map items = new HashMap<>(); @@ -77,7 +77,7 @@ public E add(int line, int column, E element) { @Override public E remove(int line, int column) { - BiInt idx = BiInt.of(checkLine(line), checkColumn(column)); + BiInt idx = BiInt.of(checkLine(line), checkColumn(column)); Object get = items.get(idx); if (get == null) { throw new IllegalArgumentException("There is no element in line " + line + " column " + column); diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/AbstractWheelTimer.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/AbstractWheelTimer.java index 3886e879..e3197b83 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/AbstractWheelTimer.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/AbstractWheelTimer.java @@ -4,8 +4,8 @@ * @author create by TcSnZh on 2021/5/12-下午6:36 */ public abstract class AbstractWheelTimer implements Timer, AutoCloseable { - public static final int WORKER_STATE_INIT = 0; - public static final int WORKER_STATE_STARTED = 1; + public static final int WORKER_STATE_INIT = 0; + public static final int WORKER_STATE_STARTED = 1; public static final int WORKER_STATE_SHUTDOWN = 2; public abstract void start(); diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/HashedWheelTimer.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/HashedWheelTimer.java index 9d5b2840..2678e49b 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/HashedWheelTimer.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/HashedWheelTimer.java @@ -20,19 +20,19 @@ public class HashedWheelTimer extends AbstractWheelTimer { private static final long MILLISECOND_NANOS = TimeUnit.MILLISECONDS.toNanos(1); - private final Worker worker = new Worker(); - private final Thread workerThread; + private final Worker worker = new Worker(); + private final Thread workerThread; @SuppressWarnings({"unused", "FieldMayBeFinal"}) private final AtomicInteger workerState = new AtomicInteger(WORKER_STATE_INIT); // 0 - init, 1 - started, 2 - shut down - private final long tickDuration; - private final HashedWheelBucket[] wheel; - private final int mask; - private final CountDownLatch startTimeInitialized = new CountDownLatch(1); - private final Queue timeouts = new ConcurrentLinkedDeque<>(); - private final Queue cancelledTimeouts = new ConcurrentLinkedDeque<>(); - private final AtomicLong pendingTimeouts = new AtomicLong(0); - private final long maxPendingTimeouts; + private final long tickDuration; + private final HashedWheelBucket[] wheel; + private final int mask; + private final CountDownLatch startTimeInitialized = new CountDownLatch(1); + private final Queue timeouts = new ConcurrentLinkedDeque<>(); + private final Queue cancelledTimeouts = new ConcurrentLinkedDeque<>(); + private final AtomicLong pendingTimeouts = new AtomicLong(0); + private final long maxPendingTimeouts; private volatile long startTime; @@ -360,8 +360,8 @@ private void transferTimeoutsToBuckets() { long calculated = timeout.deadline / tickDuration; timeout.remainingRounds = (calculated - tick) / wheel.length; - final long ticks = Math.max(calculated, tick); // Ensure we don't schedule for past. - int stopIndex = (int) (ticks & mask); + final long ticks = Math.max(calculated, tick); // Ensure we don't schedule for past. + int stopIndex = (int) (ticks & mask); HashedWheelBucket bucket = wheel[stopIndex]; bucket.addTimeout(timeout); @@ -395,7 +395,7 @@ private long waitForNextTick() { for (; ; ) { final long currentTime = System.nanoTime() - startTime; - long sleepTimeMs = (deadline - currentTime + 999999) / 1000000; + long sleepTimeMs = (deadline - currentTime + 999999) / 1000000; if (sleepTimeMs <= 0) { if (currentTime == Long.MIN_VALUE) { @@ -423,15 +423,15 @@ public Set unprocessedTimeouts() { private static final class HashedWheelTimeout implements Timeout { - private static final int ST_INIT = 0; - private static final int ST_CANCELLED = 1; - private static final int ST_EXPIRED = 2; + private static final int ST_INIT = 0; + private static final int ST_CANCELLED = 1; + private static final int ST_EXPIRED = 2; private static final AtomicIntegerFieldUpdater STATE_UPDATER = AtomicIntegerFieldUpdater.newUpdater(HashedWheelTimeout.class, "state"); private final HashedWheelTimer timer; - private final TimerTask task; - private final long deadline; + private final TimerTask task; + private final long deadline; @SuppressWarnings({"unused", "FieldMayBeFinal", "RedundantFieldInitialization"}) private volatile int state = ST_INIT; @@ -519,7 +519,7 @@ public void expire() { @Override public String toString() { final long currentTime = System.nanoTime(); - long remaining = deadline - currentTime + timer.startTime; + long remaining = deadline - currentTime + timer.startTime; StringBuilder buf = new StringBuilder(192) .append("HashedWheelTimer(deadline: "); diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/OnceWork.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/OnceWork.java index 56fb53ab..021afb70 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/OnceWork.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/OnceWork.java @@ -151,7 +151,7 @@ static OnceWork emptyWork(String workId) { // class class AsFuture implements Future>> { - private final OnceWork onceWork; + private final OnceWork onceWork; private final Function sleepCheckInterval; private AsFuture(OnceWork onceWork, Function sleepCheckInterval) { @@ -202,7 +202,7 @@ public boolean isDone() { public Map> get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - final long millis = Objects.requireNonNull(unit).toMillis(timeout); + final long millis = Objects.requireNonNull(unit).toMillis(timeout); final long interval = Math.max(1, Math.min(millis, sleepCheckInterval.apply(millis))); for (int i = 0; interval * i < millis; i++) { if (onceWork.isFinish()) { diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/WorkResult.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/WorkResult.java index 48e5b5d7..567f1ebd 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/WorkResult.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/WorkResult.java @@ -7,12 +7,12 @@ public class WorkResult { /** * 执行的结果 */ - private final V result; + private final V result; /** * 结果状态 */ private final ResultState resultState; - private final Exception ex; + private final Exception ex; public WorkResult(V result, ResultState resultState) { this(result, resultState, null); diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/StableWorkerWrapperBuilder.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/StableWorkerWrapperBuilder.java index b6bd7b53..3795eca6 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/StableWorkerWrapperBuilder.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/StableWorkerWrapperBuilder.java @@ -30,36 +30,36 @@ class StableWorkerWrapperBuilder worker; - private ICallback callback; + private T param; + private IWorker worker; + private ICallback callback; /** * 自己后面的所有 */ - private Set> nextWrappers; + private Set> nextWrappers; /** * 自己依赖的所有 */ - private Set> dependWrappers; + private Set> dependWrappers; /** * 旧版本的检查是否跳过的开关 */ - private Boolean needCheckNextWrapperResult = null; + private Boolean needCheckNextWrapperResult = null; /** * 新版本的检查是否跳过的策略。 */ - private SkipStrategy skipStrategy; + private SkipStrategy skipStrategy; /** * 基本依赖策略。 *

* 如果在{@link #build()}调用时,{@code dependenceStrategy==null}, * 则会给WorkerWrapper设置默认策略{@link DependenceStrategy#ALL_DEPENDENCIES_ALL_SUCCESS}。 */ - private DependenceStrategy dependenceStrategy; + private DependenceStrategy dependenceStrategy; /** * 存储自己需要特殊对待的dependWrapper集合 */ @@ -73,34 +73,34 @@ class StableWorkerWrapperBuilder * 该Set将会加入到{@link WorkerWrapper.StableWrapperStrategy#getDependMustStrategyMapper().mustDependSet}之中 */ - private Set> mustDependSet; + private Set> mustDependSet; /** * 存储强依赖于自己的wrapper集合 */ - private Set> selfIsMustSet; + private Set> selfIsMustSet; /** * 是否使用了旧的编排模式(Must开关) *

* 之所以需要以下两个属性,是为了隔离旧api与新api的策略不兼容的情况。建议早日替换旧方法 * 例如旧代码里调用{@link WorkerWrapper.Builder#depend(WorkerWrapper, boolean)},参数传入了false。 */ - private boolean useV15DeprecatedMustDependApi = false; + private boolean useV15DeprecatedMustDependApi = false; /** * 是否使用了新的编排模式。 *

* {@link #useV15DeprecatedMustDependApi} */ - private boolean useV15NewDependApi = false; + private boolean useV15NewDependApi = false; /** * 单个Wrapper超时相关属性 */ - private boolean enableTimeOut = false; - private long time = -1; - private TimeUnit unit = null; + private boolean enableTimeOut = false; + private long time = -1; + private TimeUnit unit = null; /** * 是否允许被打断 */ - private boolean allowInterrupt = false; + private boolean allowInterrupt = false; /** * 标记自己正在building diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapper.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapper.java index ec7c1998..72246cf3 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapper.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapper.java @@ -41,50 +41,50 @@ public abstract class WorkerWrapper { /** * 该wrapper的唯一标识 */ - protected final String id; - protected final IWorker worker; + protected final String id; + protected final IWorker worker; protected final ICallback callback; /** * 各种策略的封装类。 */ - private final WrapperStrategy wrapperStrategy; + private final WrapperStrategy wrapperStrategy; /** * 是否允许被打断 */ - protected final boolean allowInterrupt; + protected final boolean allowInterrupt; /** * 是否启动超时检查 */ - final boolean enableTimeout; + final boolean enableTimeout; /** * 超时时间长度 */ - final long timeoutLength; + final long timeoutLength; /** * 超时时间单位 */ - final TimeUnit timeoutUnit; + final TimeUnit timeoutUnit; // ========== 临时属性 ========== /** * worker将来要处理的param */ - protected volatile T param; + protected volatile T param; /** * 原子设置wrapper的状态 *

* {@link State}此枚举类枚举了state值所代表的状态枚举。 */ - protected final AtomicInteger state = new AtomicInteger(State.BUILDING.id); + protected final AtomicInteger state = new AtomicInteger(State.BUILDING.id); /** * 该值将在{@link IWorker#action(Object, Map)}进行时设为当前线程,在任务开始前或结束后都为null。 */ - protected final AtomicReference doWorkingThread = new AtomicReference<>(); + protected final AtomicReference doWorkingThread = new AtomicReference<>(); /** * 也是个钩子变量,用来存临时的结果 */ - protected final AtomicReference> workResult = new AtomicReference<>(null); + protected final AtomicReference> workResult = new AtomicReference<>(null); WorkerWrapper(String id, IWorker worker, @@ -430,9 +430,9 @@ protected void fastFail(boolean isTimeout, Exception e, boolean isEndsNormally) */ protected void beginNext(ExecutorService executorService, long now, long remainTime, WorkerWrapperGroup group) { //花费的时间 - final long costTime = SystemClock.now() - now; - final long nextRemainTIme = remainTime - costTime; - Set> nextWrappers = getNextWrappers(); + final long costTime = SystemClock.now() - now; + final long nextRemainTIme = remainTime - costTime; + Set> nextWrappers = getNextWrappers(); if (nextWrappers == null) { PollingCenter.getInstance().checkGroup(group.new CheckFinishTask()); return; @@ -549,9 +549,9 @@ public String toString() { */ public static class StableWrapperStrategy extends WrapperStrategy.AbstractWrapperStrategy { private DependOnUpWrapperStrategyMapper dependOnUpWrapperStrategyMapper; - private DependMustStrategyMapper dependMustStrategyMapper; - private DependenceStrategy dependenceStrategy; - private SkipStrategy skipStrategy; + private DependMustStrategyMapper dependMustStrategyMapper; + private DependenceStrategy dependenceStrategy; + private SkipStrategy skipStrategy; @Override public DependOnUpWrapperStrategyMapper getDependWrapperStrategyMapper() { @@ -671,7 +671,7 @@ static boolean setState(AtomicInteger state, State[] exceptValues, State newValue, Consumer withOperate) { - int current; + int current; boolean inExcepts; while (true) { // 判断当前值是否在exceptValues范围内 @@ -727,7 +727,7 @@ static boolean setState(AtomicInteger state, */ @SuppressWarnings("unused") static boolean inStates(AtomicInteger state, State... excepts) { - int current; + int current; boolean inExcepts; while (true) { current = state.get(); diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapperGroup.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapperGroup.java index c77bc285..f89ed240 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapperGroup.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapperGroup.java @@ -22,36 +22,36 @@ public class WorkerWrapperGroup { /** * 任务开始时间 */ - private final long groupStartTime; + private final long groupStartTime; /** * 任务限时 */ - private final long timeoutLength; + private final long timeoutLength; /** * 该map存放所有wrapper的id和wrapper映射 *

* 需要线程安全。 */ - private final Map> forParamUseWrappers = new ConcurrentHashMap<>(); + private final Map> forParamUseWrappers = new ConcurrentHashMap<>(); /** * 当全部wrapper都调用结束,它会countDown */ - private final CountDownLatch endCDL = new CountDownLatch(1); + private final CountDownLatch endCDL = new CountDownLatch(1); /** * 检测到超时,此标记变量将为true。 */ - private final AtomicBoolean anyTimeout = new AtomicBoolean(false); + private final AtomicBoolean anyTimeout = new AtomicBoolean(false); /** * 结束时间 */ - private volatile long finishTime = -1L; + private volatile long finishTime = -1L; /** * 取消任务状态 * 0 - not cancel , 1 - waiting cancel , 2 - already cancel */ - private final AtomicInteger cancelState = new AtomicInteger(); + private final AtomicInteger cancelState = new AtomicInteger(); - public static final int NOT_CANCEL = 0; + public static final int NOT_CANCEL = 0; public static final int WAITING_CANCEL = 1; public static final int ALREADY_CANCEL = 2; @@ -120,10 +120,10 @@ public void run(Timeout timeout) throws Exception { } AtomicBoolean hasTimeout = new AtomicBoolean(false); // 记录正在运行中的wrapper里,最近的限时时间。 - final AtomicLong minDaley = new AtomicLong(Long.MAX_VALUE); - final Collection> values = forParamUseWrappers.values(); - final Stream> stream = values.size() > 128 ? values.parallelStream() : values.stream(); - final boolean needCancel = cancelState.get() == WAITING_CANCEL; + final AtomicLong minDaley = new AtomicLong(Long.MAX_VALUE); + final Collection> values = forParamUseWrappers.values(); + final Stream> stream = values.size() > 128 ? values.parallelStream() : values.stream(); + final boolean needCancel = cancelState.get() == WAITING_CANCEL; boolean allFinish_and_notNeedCancel = stream // 需要取消的话就取消 .peek(wrapper -> { diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependOnUpWrapperStrategy.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependOnUpWrapperStrategy.java index fc6e4703..f9ad807e 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependOnUpWrapperStrategy.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependOnUpWrapperStrategy.java @@ -24,7 +24,7 @@ public interface DependOnUpWrapperStrategy { * 未运行时,休息。 * 失败时,失败。 */ - DependOnUpWrapperStrategy SUCCESS_CONTINUE = new DependOnUpWrapperStrategy() { + DependOnUpWrapperStrategy SUCCESS_CONTINUE = new DependOnUpWrapperStrategy() { @Override public DependenceAction.WithProperty judge(WorkerWrapper ww) { switch (ww.getWorkResult().getResultState()) { diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceAction.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceAction.java index dd4fb70d..211e17f7 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceAction.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceAction.java @@ -76,7 +76,7 @@ public class WithProperty { * 以下两个属性用于设置fastFail的属性 */ private ResultState resultState; - private Exception fastFailException; + private Exception fastFailException; // getter setter diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceStrategy.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceStrategy.java index 06350337..f60a40a5 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceStrategy.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceStrategy.java @@ -123,9 +123,9 @@ public String toString() { public DependenceAction.WithProperty judgeAction(Set> dependWrappers, WorkerWrapper thisWrapper, WorkerWrapper fromWrapper) { - boolean hasFailed = false; - Exception fastFailException = null; - ResultState resultState = null; + boolean hasFailed = false; + Exception fastFailException = null; + ResultState resultState = null; for (final WorkerWrapper dependWrapper : dependWrappers) { WorkResult workResult = dependWrapper.getWorkResult(); switch (workResult.getResultState()) { diff --git a/zeus-common/src/main/java/com/zmops/iot/constant/ConstantsContext.java b/zeus-common/src/main/java/com/zmops/iot/constant/ConstantsContext.java index 4c5aeb7d..d809174c 100644 --- a/zeus-common/src/main/java/com/zmops/iot/constant/ConstantsContext.java +++ b/zeus-common/src/main/java/com/zmops/iot/constant/ConstantsContext.java @@ -199,7 +199,7 @@ public static String getJwtSecret() { * 获取系统地密钥过期时间(单位:秒) */ public static Long getJwtSecretExpireSec() { - Long defaultSecs = 86400L; + Long defaultSecs = 86400L; String systemReleaseVersion = (String) CONSTNTS_HOLDER.get("ZEUS_JWT_SECRET_EXPIRE"); if (ToolUtil.isEmpty(systemReleaseVersion)) { log.error("jwt密钥存在空值!常量名称:ZEUS_JWT_SECRET_EXPIRE,采用默认值:1天" + TIPS_END); diff --git a/zeus-common/src/main/java/com/zmops/iot/dict/AbstractDictMap.java b/zeus-common/src/main/java/com/zmops/iot/dict/AbstractDictMap.java index b24252e9..e6ce667a 100644 --- a/zeus-common/src/main/java/com/zmops/iot/dict/AbstractDictMap.java +++ b/zeus-common/src/main/java/com/zmops/iot/dict/AbstractDictMap.java @@ -24,7 +24,7 @@ */ public abstract class AbstractDictMap { - protected HashMap dictory = new HashMap<>(); + protected HashMap dictory = new HashMap<>(); protected HashMap fieldWarpperDictory = new HashMap<>(); public AbstractDictMap() { diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/alarm/AlarmMessage.java b/zeus-common/src/main/java/com/zmops/iot/domain/alarm/AlarmMessage.java index fcb1d01e..b75ebacb 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/alarm/AlarmMessage.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/alarm/AlarmMessage.java @@ -1,4 +1,3 @@ - package com.zmops.iot.domain.alarm; import lombok.AllArgsConstructor; @@ -14,14 +13,14 @@ @NoArgsConstructor @AllArgsConstructor public class AlarmMessage { - private int scopeId; - private String scope; - private String name; - private String id0; - private String id1; - private String ruleName; - private String alarmMessage; - private long startTime; - private transient int period; + private int scopeId; + private String scope; + private String name; + private String id0; + private String id1; + private String ruleName; + private String alarmMessage; + private long startTime; + private transient int period; private transient boolean onlyAsCondition; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/messages/MessageBody.java b/zeus-common/src/main/java/com/zmops/iot/domain/messages/MessageBody.java index 6d8e881b..0574c523 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/messages/MessageBody.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/messages/MessageBody.java @@ -17,11 +17,11 @@ @NoArgsConstructor @AllArgsConstructor public class MessageBody { - private String msg; - private String type; - private List to; + private String msg; + private String type; + private List to; private Map body; - private boolean persist = false; + private boolean persist = false; public void addBody(String k, Object v) { diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/messages/Messages.java b/zeus-common/src/main/java/com/zmops/iot/domain/messages/Messages.java index 279dc409..964e531b 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/messages/Messages.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/messages/Messages.java @@ -20,10 +20,10 @@ public class Messages { @Id private Integer id; private Integer classify; - private String title; - private String content; - private Long clock; - private String module; + private String title; + private String content; + private Long clock; + private String module; private Integer readed; - private Long userId; + private Long userId; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java index f98ccc75..f25d0d7f 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java @@ -24,7 +24,7 @@ public class ProductEventExpression extends Model { @GeneratedValue(generator = IdTypeConsts.ID_SNOW) private Long eventExpId; - private Long eventRuleId; + private Long eventRuleId; private String function; private String scope; private String condition; @@ -32,7 +32,7 @@ public class ProductEventExpression extends Model { private String deviceId; private String productAttrKey; private String unit; - private Long productAttrId; + private Long productAttrId; private String productAttrType; private String period; diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventService.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventService.java index 5b051b4c..79468965 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventService.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventService.java @@ -15,8 +15,8 @@ @Table(name = "product_event_service") public class ProductEventService { - private Long eventRuleId; - private Long serviceId; + private Long eventRuleId; + private Long serviceId; private String deviceId; private String executeDeviceId; } diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java index 87167741..897ab054 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java @@ -38,9 +38,9 @@ public void serialize(Object object, JsonGenerator jsonGenerator, SerializerProv if (value == null) { continue; } - CachedValue[] cachedValues = field.getAnnotationsByType(CachedValue.class); - JsonProperty jsonProperties = field.getDeclaredAnnotation(JsonProperty.class); - String fieldName = field.getName(); + CachedValue[] cachedValues = field.getAnnotationsByType(CachedValue.class); + JsonProperty jsonProperties = field.getDeclaredAnnotation(JsonProperty.class); + String fieldName = field.getName(); if (null != jsonProperties) { fieldName = jsonProperties.value(); } diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/DicType.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/DicType.java index df0f08ae..4aa1dd54 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/DicType.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/DicType.java @@ -16,11 +16,11 @@ public enum DicType { @Getter private boolean nullable; - DicType(){ + DicType() { this.nullable = true; } - DicType(boolean nullable){ + DicType(boolean nullable) { this.nullable = nullable; } } diff --git a/zeus-common/src/main/java/com/zmops/iot/model/page/Pager.java b/zeus-common/src/main/java/com/zmops/iot/model/page/Pager.java index d48c7f0d..d740e13d 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/page/Pager.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/page/Pager.java @@ -16,7 +16,7 @@ @Data public class Pager { - private Integer code = 200; + private Integer code = 200; /** * 请求是否成功 */ diff --git a/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java b/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java index 5e2cffd2..0e016d12 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java @@ -56,7 +56,7 @@ public static SysUser getSysUser(Long sysUserId) { return sysUserCache.getSysUser(sysUserId); } - public static void updateProductType(Map map) { + public static void updateProductType(Map map) { productTypeCache.updateProductType(map); } diff --git a/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java b/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java index 67135fe7..eae3b696 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java @@ -34,9 +34,9 @@ public class ToolUtil { * @author fengshuonan */ public static String getRandomString(int length) { - String base = "abcdefghijklmnopqrstuvwxyz0123456789"; - Random random = new Random(); - StringBuffer sb = new StringBuffer(); + String base = "abcdefghijklmnopqrstuvwxyz0123456789"; + Random random = new Random(); + StringBuffer sb = new StringBuffer(); for (int i = 0; i < length; i++) { int number = random.nextInt(base.length()); sb.append(base.charAt(number)); @@ -60,9 +60,9 @@ public static String md5Hex(String password, String salt) { */ public static String md5Hex(String str) { try { - MessageDigest md5 = MessageDigest.getInstance("MD5"); - byte[] bs = md5.digest(str.getBytes()); - StringBuffer md5StrBuff = new StringBuffer(); + MessageDigest md5 = MessageDigest.getInstance("MD5"); + byte[] bs = md5.digest(str.getBytes()); + StringBuffer md5StrBuff = new StringBuffer(); for (int i = 0; i < bs.length; i++) { if (Integer.toHexString(0xFF & bs[i]).length() == 1) md5StrBuff.append("0").append(Integer.toHexString(0xFF & bs[i])); @@ -94,9 +94,9 @@ public static String removeWhiteSpace(String value) { * @author stylefeng */ public static String getCreateTimeBefore(int seconds) { - long currentTimeInMillis = Calendar.getInstance().getTimeInMillis(); - Date date = new Date(currentTimeInMillis - seconds * 1000); - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + long currentTimeInMillis = Calendar.getInstance().getTimeInMillis(); + Date date = new Date(currentTimeInMillis - seconds * 1000); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return sdf.format(date); } @@ -127,7 +127,7 @@ public static String getExceptionMsg(Throwable e) { public static String getApplicationName() { try { Environment environment = SpringContextHolder.getApplicationContext().getEnvironment(); - String property = environment.getProperty("spring.application.name"); + String property = environment.getProperty("spring.application.name"); if (ToolUtil.isNotEmpty(property)) { return property; } else { diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/entrypoint/JwtAuthenticationEntryPoint.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/entrypoint/JwtAuthenticationEntryPoint.java index d91ffb20..e5deff52 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/entrypoint/JwtAuthenticationEntryPoint.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/entrypoint/JwtAuthenticationEntryPoint.java @@ -42,7 +42,8 @@ public void commence(HttpServletRequest request, response.setContentType("application/json"); ErrorResponseData errorResponseData = new ErrorResponseData( - AuthExceptionEnum.NO_PAGE_ERROR.getCode(), AuthExceptionEnum.NO_PAGE_ERROR.getMessage()); + AuthExceptionEnum.NO_PAGE_ERROR.getCode(), + AuthExceptionEnum.NO_PAGE_ERROR.getMessage()); response.getWriter().write(JSON.toJSONString(errorResponseData)); } diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/exception/AuthException.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/exception/AuthException.java index b97baf19..7ff97b38 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/exception/AuthException.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/exception/AuthException.java @@ -13,7 +13,7 @@ public class AuthException extends RuntimeException { private Integer code; - private String errorMessage; + private String errorMessage; public AuthException() { super("认证失败!"); diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/exception/PermissionException.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/exception/PermissionException.java index 1a875e86..384d7ef1 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/exception/PermissionException.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/exception/PermissionException.java @@ -14,7 +14,7 @@ public class PermissionException extends RuntimeException { private Integer code; - private String errorMessage; + private String errorMessage; public PermissionException() { super(NO_PERMISSION.getMessage()); diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/jwt/JwtTokenUtil.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/jwt/JwtTokenUtil.java index b53c40ca..3854fe24 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/jwt/JwtTokenUtil.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/jwt/JwtTokenUtil.java @@ -45,7 +45,7 @@ public class JwtTokenUtil { * 生成token,根据userId和默认过期时间 */ public static String generateToken(JwtPayLoad jwtPayLoad) { - Long expiredSeconds = getExpireSeconds(); + Long expiredSeconds = getExpireSeconds(); final Date expirationDate = new Date(System.currentTimeMillis() + expiredSeconds * 1000); return generateToken(String.valueOf(jwtPayLoad.getUserId()), expirationDate, jwtPayLoad.toMap()); } @@ -96,7 +96,7 @@ public static Date getExpirationDateFromToken(String token) { public static String generateToken(String userId, Date exppiredDate, Map claims) { final Date createdDate = new Date(); - String secret = getJwtSecret(); + String secret = getJwtSecret(); if (claims == null) { return Jwts.builder() diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java index 53f25b01..e465f7d5 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java @@ -59,7 +59,7 @@ public class LoginUser implements UserDetails, Serializable { /** * 用户组 */ - private Long userGroupId; + private Long userGroupId; /** * 角色集 diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/util/TokenUtil.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/util/TokenUtil.java index 0ef37120..5a025f51 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/util/TokenUtil.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/util/TokenUtil.java @@ -22,8 +22,8 @@ public class TokenUtil { */ public static String getToken() { - String authToken = null; - HttpServletRequest request = HttpContext.getRequest(); + String authToken = null; + HttpServletRequest request = HttpContext.getRequest(); //权限校验的头部 String tokenHeader = getTokenHeaderName(); diff --git a/zeus-core/src/main/java/com/zmops/iot/core/util/FileUtil.java b/zeus-core/src/main/java/com/zmops/iot/core/util/FileUtil.java index e571b591..824e4904 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/util/FileUtil.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/util/FileUtil.java @@ -25,8 +25,8 @@ public static byte[] toByteArray(String filename) { log.error("文件未找到!" + filename); throw new ServiceException(CoreExceptionEnum.FILE_NOT_FOUND); } - FileChannel channel = null; - FileInputStream fs = null; + FileChannel channel = null; + FileInputStream fs = null; try { fs = new FileInputStream(f); channel = fs.getChannel(); diff --git a/zeus-core/src/main/java/com/zmops/iot/core/util/HttpContext.java b/zeus-core/src/main/java/com/zmops/iot/core/util/HttpContext.java index adead48d..85b4d9d8 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/util/HttpContext.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/util/HttpContext.java @@ -63,14 +63,14 @@ public static HttpServletResponse getResponse() { * @author fengshuonan */ public static Map getRequestParameters() { - HashMap values = new HashMap<>(); - HttpServletRequest request = HttpContext.getRequest(); + HashMap values = new HashMap<>(); + HttpServletRequest request = HttpContext.getRequest(); if (request == null) { return values; } Enumeration enums = request.getParameterNames(); while (enums.hasMoreElements()) { - String paramName = (String) enums.nextElement(); + String paramName = (String) enums.nextElement(); String paramValue = request.getParameter(paramName); values.put(paramName, paramValue); } diff --git a/zeus-core/src/main/java/com/zmops/iot/core/util/RsaUtil.java b/zeus-core/src/main/java/com/zmops/iot/core/util/RsaUtil.java index 011b7ea3..a4f19435 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/util/RsaUtil.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/util/RsaUtil.java @@ -23,8 +23,8 @@ public static String decrypt(String str, String privateKey) throws Exception { //64位解码加密后的字符串 byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8)); //base64编码的私钥 - byte[] decoded = Base64.decodeBase64(privateKey); - RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded)); + byte[] decoded = Base64.decodeBase64(privateKey); + RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded)); //RSA解密 Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, priKey); diff --git a/zeus-core/src/main/java/com/zmops/iot/core/web/base/BaseController.java b/zeus-core/src/main/java/com/zmops/iot/core/web/base/BaseController.java index ab23672d..2cf7d6fd 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/web/base/BaseController.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/web/base/BaseController.java @@ -23,7 +23,7 @@ public class BaseController { protected final String REDIRECT = "redirect:"; - protected final String FORWARD = "forward:"; + protected final String FORWARD = "forward:"; protected static SuccessResponseData SUCCESS_TIP = new SuccessResponseData(); @@ -109,8 +109,8 @@ protected ResponseEntity renderFile(String fileName, byte[] * @author 0x0001 */ protected ResponseEntity renderFile(String fileName, InputStream inputStream) { - InputStreamResource resource = new InputStreamResource(inputStream); - String dfileName = null; + InputStreamResource resource = new InputStreamResource(inputStream); + String dfileName = null; try { dfileName = new String(fileName.getBytes("gb2312"), "iso8859-1"); } catch (UnsupportedEncodingException e) { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/JsonBodyBuildInterceptor.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/JsonBodyBuildInterceptor.java index fc4b6fb4..8b3e27eb 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/JsonBodyBuildInterceptor.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/JsonBodyBuildInterceptor.java @@ -58,7 +58,7 @@ public void onInvokeMethod(ForestRequest request, ForestMethod method, Object[] JsonPath jsonPath = method.getMethod().getAnnotation(JsonPath.class); if (null != jsonPath && StringUtils.isNotBlank(jsonPath.value())) { - String body = Objects.requireNonNull(JsonParseUtil.parse(jsonPath.value() + ".ftl", paramMap)); + String body = Objects.requireNonNull(JsonParseUtil.parse(jsonPath.value() + ".ftl", paramMap)); String sendBody = StringEscapeUtils.unescapeJava(body); log.debug("\n" + sendBody + "\n"); request.replaceBody(sendBody); diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java index 8bbeb36f..de88339d 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java @@ -42,5 +42,5 @@ String createOfflineStatusAction(@ParamName("userAuth") String userAuth, */ @Post(headers = "authTag: noAuth") @JsonPath("/action/action.offline.get") - String getOfflineStatusAction(@ParamName("userAuth") String userAuth,@ParamName("name") String name); + String getOfflineStatusAction(@ParamName("userAuth") String userAuth, @ParamName("name") String name); } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java index 4dc49a9f..70557efb 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java @@ -31,11 +31,11 @@ String getProblem(@ParamName("hostId") String hostId, @Post @JsonPath("/problem/problem.event.get") String getEventProblem(@ParamName("hostId") String hostId, - @ParamName("timeFrom") Long timeFrom, - @ParamName("timeTill") Long timeTill, - @ParamName("recent") String recent); + @ParamName("timeFrom") Long timeFrom, + @ParamName("timeTill") Long timeTill, + @ParamName("recent") String recent); @Post @JsonPath("/problem/problem.acknowledgement") - String acknowledgement(@ParamName("eventId") String eventId,@ParamName("action") int action); + String acknowledgement(@ParamName("eventId") String eventId, @ParamName("action") int action); } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java index b9224aaa..8261ecd2 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java @@ -19,7 +19,7 @@ public interface ZbxScript { /** * 创建 在线状态 回调地址 * - * @param userApiToken apiToekn + * @param userApiToken apiToekn * @return String */ @Post(headers = "authTag: noAuth") diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java index ab361a3d..5708a72d 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java @@ -74,7 +74,7 @@ String userUpdate(@ParamName("userId") String userId, /** * 用户修改密码 * - * @param userId 用户id + * @param userId 用户id * @param passwd 用户组ID * @return 用户信息 */ diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java index 6bb08bd8..8c2dc7b7 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java @@ -56,5 +56,5 @@ String userGrpBindHostGroup(@ParamName("hostGroupIds") List hostGroupIds @Post @JsonPath("/usergroup/userGroupGet") - String getUserGrp(@ParamName("usrgrpids") String usrgrpids); + String getUserGrp(@ParamName("usrgrpids") String usrgrpids); } diff --git a/zeus-message/src/main/java/com/zmops/iot/media/AlarmCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/AlarmCallback.java index 8e3ed118..89f64e92 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/AlarmCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/AlarmCallback.java @@ -1,4 +1,3 @@ - package com.zmops.iot.media; import com.zmops.iot.domain.alarm.AlarmMessage; diff --git a/zeus-message/src/main/java/com/zmops/iot/media/AlarmMessageFormatter.java b/zeus-message/src/main/java/com/zmops/iot/media/AlarmMessageFormatter.java index 831177ea..0ca7cc6d 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/AlarmMessageFormatter.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/AlarmMessageFormatter.java @@ -30,7 +30,7 @@ * - Successful rate of endpoint {name} is lower than 75% */ public class AlarmMessageFormatter { - private List formatSegments; + private List formatSegments; private List valueFroms; public AlarmMessageFormatter(String format) { @@ -40,7 +40,7 @@ public AlarmMessageFormatter(String format) { formatSegments = new ArrayList<>(); this.valueFroms = new ArrayList<>(); boolean match = false; - int idx = 0; + int idx = 0; do { match = false; int start = format.indexOf("{", idx); diff --git a/zeus-message/src/main/java/com/zmops/iot/media/WebhookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/WebhookCallback.java index eac5607f..c8a233a1 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/WebhookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/WebhookCallback.java @@ -26,9 +26,9 @@ @Slf4j public class WebhookCallback implements AlarmCallback { - private static final int HTTP_CONNECT_TIMEOUT = 1000; + private static final int HTTP_CONNECT_TIMEOUT = 1000; private static final int HTTP_CONNECTION_REQUEST_TIMEOUT = 1000; - private static final int HTTP_SOCKET_TIMEOUT = 10000; + private static final int HTTP_SOCKET_TIMEOUT = 10000; private RequestConfig requestConfig; diff --git a/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkHookCallback.java index 29da47be..66315802 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkHookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkHookCallback.java @@ -52,10 +52,10 @@ @Service public class DingtalkHookCallback implements AlarmCallback { - private static final int HTTP_CONNECT_TIMEOUT = 1000; - private static final int HTTP_CONNECTION_REQUEST_TIMEOUT = 1000; - private static final int HTTP_SOCKET_TIMEOUT = 10000; - private RequestConfig requestConfig; + private static final int HTTP_CONNECT_TIMEOUT = 1000; + private static final int HTTP_CONNECTION_REQUEST_TIMEOUT = 1000; + private static final int HTTP_SOCKET_TIMEOUT = 10000; + private RequestConfig requestConfig; @Autowired DingtalkSettingService dingtalkSettingService; @@ -120,7 +120,7 @@ private String getSignUrl(DingtalkSettings.WebHookUrl webHookUrl) { */ private String sign(final Long timestamp, String secret) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException { String stringToSign = timestamp + "\n" + secret; - Mac mac = Mac.getInstance("HmacSHA256"); + Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256")); byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8)); return URLEncoder.encode(new String(Base64.getEncoder().encode(signData)), StandardCharsets.UTF_8.name()); diff --git a/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettingService.java b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettingService.java index 18214ff5..7c6a6196 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettingService.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettingService.java @@ -31,8 +31,8 @@ private DingtalkSettings getOne() { private DingtalkSettings buildDingdingSetting(MediaTypeSetting setting) { JSONObject jsonObject = JSONObject.parseObject(setting.getWebhooks()); - String secret = Optional.ofNullable(jsonObject.getString("secret")).orElse(""); - String url = Optional.ofNullable(jsonObject.getString("url")).orElse(""); + String secret = Optional.ofNullable(jsonObject.getString("secret")).orElse(""); + String url = Optional.ofNullable(jsonObject.getString("url")).orElse(""); return DingtalkSettings.builder().textTemplate(setting.getTemplate()) .webhooks(Arrays.asList(new DingtalkSettings.WebHookUrl(secret, url))).build(); } diff --git a/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettings.java b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettings.java index eb0328f4..1132b449 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettings.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettings.java @@ -1,5 +1,3 @@ - - package com.zmops.iot.media.dingtalk; import lombok.*; @@ -14,7 +12,7 @@ @Data public class DingtalkSettings { - private String textTemplate; + private String textTemplate; @Builder.Default private List webhooks = new ArrayList<>(); diff --git a/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuHookCallback.java index 45ad4cb3..3fd7d3f3 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuHookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuHookCallback.java @@ -55,9 +55,9 @@ @Service public class FeishuHookCallback implements AlarmCallback { - private static final int HTTP_CONNECT_TIMEOUT = 1000; + private static final int HTTP_CONNECT_TIMEOUT = 1000; private static final int HTTP_CONNECTION_REQUEST_TIMEOUT = 1000; - private static final int HTTP_SOCKET_TIMEOUT = 10000; + private static final int HTTP_SOCKET_TIMEOUT = 10000; @Autowired FeishuSettingService feishuSettingService; @@ -111,8 +111,8 @@ public void doAlarm(List alarmMessages) { */ private String getRequestBody(FeishuSettings.WebHookUrl webHookUrl, AlarmMessage alarmMessage, String requestBody) { - JSONObject jsonObject = JSONObject.parseObject(requestBody); - Map content = buildContent(jsonObject); + JSONObject jsonObject = JSONObject.parseObject(requestBody); + Map content = buildContent(jsonObject); if (ToolUtil.isNotEmpty(webHookUrl.getSecret())) { Long timestamp = System.currentTimeMillis() / 1000; content.put("timestamp", timestamp); @@ -132,7 +132,7 @@ private Map buildContent(JSONObject jsonObject) { Map content = new HashMap<>(); content.put("msg_type", jsonObject.getString("msg_type")); if (jsonObject.get("ats") != null) { - String ats = jsonObject.getString("ats"); + String ats = jsonObject.getString("ats"); String text = jsonObject.getJSONObject("content").getString("text"); List collect = Arrays.stream(ats.split(",")) .map(String::trim).collect(Collectors.toList()); @@ -150,7 +150,7 @@ private Map buildContent(JSONObject jsonObject) { */ private String sign(final Long timestamp, String secret) throws NoSuchAlgorithmException, InvalidKeyException { String stringToSign = timestamp + "\n" + secret; - Mac mac = Mac.getInstance("HmacSHA256"); + Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(stringToSign.getBytes(), "HmacSHA256")); byte[] signData = mac.doFinal(); return Base64.encodeBase64String(signData); diff --git a/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettingService.java b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettingService.java index f132a08c..0517c425 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettingService.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettingService.java @@ -31,8 +31,8 @@ private FeishuSettings getOne() { private FeishuSettings buildFeishuSetting(MediaTypeSetting setting) { JSONObject jsonObject = JSONObject.parseObject(setting.getWebhooks()); - String secret = Optional.ofNullable(jsonObject.getString("secret")).orElse(""); - String url = Optional.ofNullable(jsonObject.getString("url")).orElse(""); + String secret = Optional.ofNullable(jsonObject.getString("secret")).orElse(""); + String url = Optional.ofNullable(jsonObject.getString("url")).orElse(""); return FeishuSettings.builder().textTemplate(setting.getTemplate()) .webhooks(Arrays.asList(new FeishuSettings.WebHookUrl(secret, url))).build(); } diff --git a/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettings.java b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettings.java index e819a128..4667f5e0 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettings.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettings.java @@ -31,7 +31,7 @@ @ToString public class FeishuSettings { - private String textTemplate; + private String textTemplate; @Builder.Default private List webhooks = new ArrayList<>(); diff --git a/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatHookCallback.java index 2a817dc5..ca127d29 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatHookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatHookCallback.java @@ -31,7 +31,6 @@ import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -41,10 +40,10 @@ @Slf4j @Service public class WechatHookCallback implements AlarmCallback { - private static final int HTTP_CONNECT_TIMEOUT = 1000; - private static final int HTTP_CONNECTION_REQUEST_TIMEOUT = 1000; - private static final int HTTP_SOCKET_TIMEOUT = 10000; - private RequestConfig requestConfig; + private static final int HTTP_CONNECT_TIMEOUT = 1000; + private static final int HTTP_CONNECTION_REQUEST_TIMEOUT = 1000; + private static final int HTTP_SOCKET_TIMEOUT = 10000; + private RequestConfig requestConfig; @Autowired WechatSettingService wechatSettingService; diff --git a/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkHookCallback.java index 8fd7bbfa..b97e7e33 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkHookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkHookCallback.java @@ -50,10 +50,10 @@ public class WeLinkHookCallback implements AlarmCallback { @Autowired WeLinkSettingService weLinkSettingService; - private static final int HTTP_CONNECT_TIMEOUT = 1000; - private static final int HTTP_CONNECTION_REQUEST_TIMEOUT = 1000; - private static final int HTTP_SOCKET_TIMEOUT = 10000; - private final RequestConfig requestConfig; + private static final int HTTP_CONNECT_TIMEOUT = 1000; + private static final int HTTP_CONNECTION_REQUEST_TIMEOUT = 1000; + private static final int HTTP_SOCKET_TIMEOUT = 10000; + private final RequestConfig requestConfig; public WeLinkHookCallback() { this.requestConfig = RequestConfig.custom() @@ -114,8 +114,8 @@ private void sendAlarmMessage(WeLinkSettings.WebHookUrl webHookUrl, String acces */ private String getAccessToken(WeLinkSettings.WebHookUrl webHookUrl) { String accessTokenUrl = webHookUrl.getAccessTokenUrl(); - String clientId = webHookUrl.getClientId(); - String clientSecret = webHookUrl.getClientSecret(); + String clientId = webHookUrl.getClientId(); + String clientSecret = webHookUrl.getClientSecret(); String response = sendPostRequest( accessTokenUrl, Collections.emptyMap(), String.format(Locale.US, "{\"client_id\":%s,\"client_secret\":%s}", clientId, clientSecret) diff --git a/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkSettings.java b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkSettings.java index cabd67cd..04d06869 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkSettings.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkSettings.java @@ -1,4 +1,3 @@ - package com.zmops.iot.media.welink; import lombok.*; @@ -14,7 +13,7 @@ @ToString public class WeLinkSettings { - private String textTemplate; + private String textTemplate; @Builder.Default private List webhooks = new ArrayList<>(); @@ -36,12 +35,12 @@ public static class WebHookUrl { private final String groupIds; public static WebHookUrl generateFromMap(Map params) { - String clientId = params.get("clientId"); - String clientSecret = params.get("clientSecret"); + String clientId = params.get("clientId"); + String clientSecret = params.get("clientSecret"); String accessTokenUrl = params.get("accessTokenUrl"); - String messageUrl = params.get("messageUrl"); - String groupIds = params.get("groupIds"); - String robotName = params.getOrDefault("robotName", "robot"); + String messageUrl = params.get("messageUrl"); + String groupIds = params.get("groupIds"); + String robotName = params.getOrDefault("robotName", "robot"); return new WebHookUrl(clientId, clientSecret, accessTokenUrl, messageUrl, robotName, groupIds ); diff --git a/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java b/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java index 54495d22..81177e7c 100644 --- a/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java +++ b/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java @@ -6,7 +6,6 @@ import com.corundumstudio.socketio.annotation.OnConnect; import com.corundumstudio.socketio.annotation.OnDisconnect; import com.corundumstudio.socketio.annotation.OnEvent; - import com.zmops.iot.message.config.Event; import com.zmops.iot.message.config.UserClientMap; import com.zmops.iot.message.payload.BroadcastMessageRequest; @@ -39,7 +38,7 @@ public class MessageEventHandler { public void onConnect(SocketIOClient client) { if (client != null) { - String token = client.getHandshakeData().getSingleUrlParam("token"); + String token = client.getHandshakeData().getSingleUrlParam("token"); String userId = client.getHandshakeData().getSingleUrlParam("userId"); UUID sessionId = client.getSessionId(); @@ -90,7 +89,7 @@ public void sendDisconnectMsg(String userId) { } } - public void sendToUser(String userId,String msg) { + public void sendToUser(String userId, String msg) { if (userClient.findByUserId(userId).isPresent()) { UUID uuid = userClient.findByUserId(userId).get(); if (null != server.getClient(uuid)) { diff --git a/zeus-starter/src/main/java/com/zmops/iot/config/web/WebConfig.java b/zeus-starter/src/main/java/com/zmops/iot/config/web/WebConfig.java index 4bb49796..516ebd86 100644 --- a/zeus-starter/src/main/java/com/zmops/iot/config/web/WebConfig.java +++ b/zeus-starter/src/main/java/com/zmops/iot/config/web/WebConfig.java @@ -39,7 +39,7 @@ public DefaultKaptcha kaptcha() { properties.put("kaptcha.textproducer.char.length", "4"); properties.put("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑"); - Config config = new Config(properties); + Config config = new Config(properties); DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); defaultKaptcha.setConfig(config); diff --git a/zeus-starter/src/main/java/com/zmops/iot/config/zbxapi/ZbxApiInfoValidation.java b/zeus-starter/src/main/java/com/zmops/iot/config/zbxapi/ZbxApiInfoValidation.java index 041f01e3..f770af3c 100644 --- a/zeus-starter/src/main/java/com/zmops/iot/config/zbxapi/ZbxApiInfoValidation.java +++ b/zeus-starter/src/main/java/com/zmops/iot/config/zbxapi/ZbxApiInfoValidation.java @@ -19,8 +19,8 @@ public class ZbxApiInfoValidation implements ApplicationContextAware { @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - ZbxApiInfo apiInfo = applicationContext.getBean(ZbxApiInfo.class); - String response = apiInfo.getApiInfo(); + ZbxApiInfo apiInfo = applicationContext.getBean(ZbxApiInfo.class); + String response = apiInfo.getApiInfo(); int version = NumberUtil.parseInt(response.replaceAll("\\.", "")); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java index e8cd9f95..9d0f161b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java @@ -35,6 +35,4 @@ private MessageBody buildMessage(Map alarmInfo) { } - - } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 760ab7d7..73cf9c61 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -43,14 +43,14 @@ public class AlarmService { public void alarm(Map alarmInfo) { - String deviceId = alarmInfo.get("hostname"); + String deviceId = alarmInfo.get("hostname"); String eventRuleId = alarmInfo.get("triggerName"); if (ToolUtil.isEmpty(deviceId) || ToolUtil.isEmpty(eventRuleId)) { return; } - Device device = new QDevice().deviceId.eq(deviceId).findOne(); + Device device = new QDevice().deviceId.eq(deviceId).findOne(); ProductEvent productEvent = new QProductEvent().eventRuleId.eq(Long.parseLong(eventRuleId)).findOne(); List alarmMessages = new ArrayList<>(); @@ -130,7 +130,7 @@ public List getAlarmList(AlarmParam alarmParam) { } List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Objects::toString).collect(Collectors.toList()); List ruleList = DB.findDto(ProductEventRuleDto.class, "select d.event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id," + - "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") + "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") .setParameter("zbxIds", triggerIds).findList(); Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); @@ -150,7 +150,7 @@ public List getAlarmList(AlarmParam alarmParam) { } public List getZbxAlarm(AlarmParam alarmParam) { - String hostId = null; + String hostId = null; List deviceIds; if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { deviceIds = Collections.singletonList(alarmParam.getDeviceId()); @@ -178,7 +178,7 @@ public List getEventList(AlarmParam alarmParam) { } List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Objects::toString).collect(Collectors.toList()); List ruleList = DB.findDto(ProductEventRuleDto.class, "select event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id," + - "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") + "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") .setParameter("zbxIds", triggerIds).findList(); Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); @@ -198,7 +198,7 @@ public List getEventList(AlarmParam alarmParam) { } public List getEventProblem(AlarmParam alarmParam) { - String hostId = null; + String hostId = null; List deviceIds; if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { deviceIds = Collections.singletonList(alarmParam.getDeviceId()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java index d951ea2f..c6dc4231 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java @@ -35,6 +35,7 @@ public class MessageService { @Autowired MessageEventHandler messageEventHandler; + /** * 发送消息 * @@ -83,7 +84,7 @@ public void push(MessageBody body) { * @return */ public Pager list(MessageParam messageParam) { - LoginUser user = LoginContextHolder.getContext().getUser(); + LoginUser user = LoginContextHolder.getContext().getUser(); QMessages qMessages = new QMessages(); qMessages.userId.eq(user.getId()); @@ -105,8 +106,8 @@ public Pager list(MessageParam messageParam) { * @return */ public List read(MessageParam messageParam) { - LoginUser user = LoginContextHolder.getContext().getUser(); - Messages messages = new Messages(); + LoginUser user = LoginContextHolder.getContext().getUser(); + Messages messages = new Messages(); messages.setReaded(1); QMessages qMessages = new QMessages(); if (!CollectionUtils.isEmpty(messageParam.getIds())) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java index 2afa0289..1193b0ff 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java @@ -7,7 +7,6 @@ import com.zmops.iot.web.analyse.service.LatestService; import com.zmops.iot.web.auth.Permission; import com.zmops.zeus.driver.service.TDEngineRest; -import org.checkerframework.checker.units.qual.A; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RequestBody; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/LatestParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/LatestParam.java index f3404d8e..1554a3a1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/LatestParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/LatestParam.java @@ -10,7 +10,7 @@ * @author yefei **/ @Data -public class LatestParam extends BaseQueryParam{ +public class LatestParam extends BaseQueryParam { @NotNull(message = "请选择一个设备再查询") private String deviceId; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java index 30e55e6c..a18b04db 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java @@ -85,7 +85,7 @@ public LoginUserDto login(String username, String password) { } String requestMd5 = SaltUtil.md5Encrypt(password, user.getSalt()); - String dbMd5 = user.getPassword(); + String dbMd5 = user.getPassword(); if (dbMd5 == null || !dbMd5.equalsIgnoreCase(requestMd5)) { throw new AuthException(AuthExceptionEnum.USERNAME_PWD_ERROR); } @@ -253,7 +253,7 @@ public boolean check(String[] roleNames) { return false; } ArrayList objects = CollectionUtil.newArrayList(roleNames); - String join = CollectionUtil.join(objects, ","); + String join = CollectionUtil.join(objects, ","); if (LoginContextHolder.getContext().hasAnyRoles(join)) { return true; } @@ -263,11 +263,11 @@ public boolean check(String[] roleNames) { public boolean checkAll(String code) { HttpServletRequest request = HttpContext.getRequest(); - LoginUser user = LoginContextHolder.getContext().getUser(); + LoginUser user = LoginContextHolder.getContext().getUser(); if (null == user) { return false; } - String sql = "select * from sys_menu where code = :code and menu_id in (SELECT menu_id from sys_role_menu where role_id = :roleId)"; + String sql = "select * from sys_menu where code = :code and menu_id in (SELECT menu_id from sys_role_menu where role_id = :roleId)"; List list = DB.sqlQuery(sql).setParameter("code", code).setParameter("roleId", user.getRoleList().get(0)).findList(); if (list.size() > 0) { return true; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/PermissionAop.java b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/PermissionAop.java index dac8d361..1cc3d57f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/PermissionAop.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/PermissionAop.java @@ -47,11 +47,11 @@ private void cutPermission() { @Around("cutPermission()") public Object doPermission(ProceedingJoinPoint point) throws Throwable { - MethodSignature ms = (MethodSignature) point.getSignature(); - Method method = ms.getMethod(); - Permission permission = method.getAnnotation(Permission.class); - String[] permissions = permission.value(); - String code = permission.code(); + MethodSignature ms = (MethodSignature) point.getSignature(); + Method method = ms.getMethod(); + Permission permission = method.getAnnotation(Permission.class); + String[] permissions = permission.value(); + String code = permission.code(); if (permissions.length == 0 && StringUtils.isNotBlank(code)) { //检查全体角色 boolean result = authService.checkAll(code); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index dccd064f..84ea484d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -24,7 +24,10 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java index 47414228..8f84aff7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java @@ -21,9 +21,9 @@ public class DeviceLogController { @RequestMapping("list") public ResponseData list(@RequestParam(value = "deviceId") String deviceId, - @RequestParam(value = "logType", required = false) String logType, - @RequestParam(value = "timeFrom", required = false) Long timeFrom, - @RequestParam(value = "timeTill", required = false) Long timeTill) { + @RequestParam(value = "logType", required = false) String logType, + @RequestParam(value = "timeFrom", required = false) Long timeFrom, + @RequestParam(value = "timeTill", required = false) Long timeTill) { return ResponseData.success(deviceLogService.list(deviceId, logType, timeFrom, timeTill)); } @@ -31,6 +31,6 @@ public ResponseData list(@RequestParam(value = "deviceId") String deviceId, @RequestMapping("getLogByPage") public ResponseData getLogByPage(@RequestBody DeviceLogParam deviceLogParam) { - return ResponseData.success(deviceLogService.getLogByPage(deviceLogParam.getDeviceId(), deviceLogParam.getLogType(), deviceLogParam.getTimeFrom(), deviceLogParam.getTimeTill(),deviceLogParam.getPage(),deviceLogParam.getMaxRow())); + return ResponseData.success(deviceLogService.getLogByPage(deviceLogParam.getDeviceId(), deviceLogParam.getLogType(), deviceLogParam.getTimeFrom(), deviceLogParam.getTimeTill(), deviceLogParam.getPage(), deviceLogParam.getMaxRow())); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java index 84346feb..3e92bba1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java @@ -95,7 +95,7 @@ public ResponseData prodModelAttributeCreate(@RequestBody @Validated(BaseEntity. productAttr.setAttrId(attrId); String response = deviceModelService.createTrapperItem(productAttr); - String zbxId = JSON.parseObject(response, TemplateIds.class).getItemids()[0]; + String zbxId = JSON.parseObject(response, TemplateIds.class).getItemids()[0]; deviceModelService.createProductAttr(productAttr, zbxId); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java index 98dd6894..bf449906 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java @@ -15,9 +15,9 @@ @NoArgsConstructor @AllArgsConstructor public class DeviceLogDto { - private String logType; + private String logType; private LocalDateTime triggerTime; - private String content; - private String param; - private String status; + private String content; + private String param; + private String status; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceLogParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceLogParam.java index c585a660..cd8be13c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceLogParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceLogParam.java @@ -10,7 +10,7 @@ public class DeviceLogParam extends BaseQueryParam { private String logType; private String deviceId; - private Long timeFrom; - private Long timeTill; + private Long timeFrom; + private Long timeTill; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 7a2cacaa..1665d038 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -284,8 +284,8 @@ static class TriggerIds { @Data public static class Triggers { - private String triggerid; - private String description; + private String triggerid; + private String description; private List hosts; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java index 2f5843bb..e1a49ab9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java @@ -119,7 +119,7 @@ public DeviceGroup createDeviceGroup(DeviceGroupDto deviceGroup) { newDeviceGroup.setDeviceGroupId(devGrpId); //回填 ZBX主机组ID JSONObject result = JSONObject.parseObject(zbxHostGroup.hostGroupCreate(String.valueOf(devGrpId))); - JSONArray grpids = result.getJSONArray("groupids"); + JSONArray grpids = result.getJSONArray("groupids"); newDeviceGroup.setZbxId(grpids.get(0).toString()); DB.save(newDeviceGroup); return newDeviceGroup; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java index 1f00591c..4dcab43d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java @@ -23,8 +23,8 @@ @Service public class DeviceLogService { - private static final String LOG_TYPE_ALARM = "告警日志"; - private static final String LOG_TYPE_EVENT = "事件日志"; + private static final String LOG_TYPE_ALARM = "告警日志"; + private static final String LOG_TYPE_EVENT = "事件日志"; private static final String LOG_TYPE_SERVICE = "服务日志"; @Autowired diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index bb712789..79937817 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -66,16 +66,16 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr return new Pager<>(); } //查询最新数据 - List attrIds = pagedList.parallelStream().map(ProductAttrDto::getAttrId).collect(Collectors.toList()); - List latestDtos = latestService.qeuryLatest(productAttr.getProdId(), attrIds); - Map map = latestDtos.parallelStream().distinct().collect(Collectors.toMap(LatestDto::getAttrId, o -> o, (a, b) -> b)); + List attrIds = pagedList.parallelStream().map(ProductAttrDto::getAttrId).collect(Collectors.toList()); + List latestDtos = latestService.qeuryLatest(productAttr.getProdId(), attrIds); + Map map = latestDtos.parallelStream().distinct().collect(Collectors.toMap(LatestDto::getAttrId, o -> o, (a, b) -> b)); //查询zbx item 信息 List zbxIds = pagedList.parallelStream().map(ProductAttrDto::getZbxId).collect(Collectors.toList()); - String itemInfo = zbxItem.getItemInfo(zbxIds.toString(), null); - List itemInfos = JSONObject.parseArray(itemInfo, ZbxItemInfo.class); - Map errorMap = itemInfos.parallelStream().collect(Collectors.toMap(ZbxItemInfo::getItemid, o -> Optional.ofNullable(o.getError()).orElse(""))); + String itemInfo = zbxItem.getItemInfo(zbxIds.toString(), null); + List itemInfos = JSONObject.parseArray(itemInfo, ZbxItemInfo.class); + Map errorMap = itemInfos.parallelStream().collect(Collectors.toMap(ZbxItemInfo::getItemid, o -> Optional.ofNullable(o.getError()).orElse(""))); pagedList.forEach(productAttrDto -> { if (null != map.get(productAttrDto.getAttrId())) { @@ -142,7 +142,7 @@ private List formatProcessStep(String preprocessing) return Collections.emptyList(); } List processingSteps = new ArrayList<>(); - JSONArray jsonArray = JSONObject.parseArray(preprocessing); + JSONArray jsonArray = JSONObject.parseArray(preprocessing); for (Object object : jsonArray) { ProductAttr.ProcessingStep processingStep = new ProductAttr.ProcessingStep(); processingStep.setType(((JSONObject) object).getString("type")); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java index 44dc2b6a..78df33c8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java @@ -34,7 +34,7 @@ public Boolean action(Map param, Map if (null == device) { return false; } - int status = 0; + int status = 0; String recovery = param.get("recovery"); if (ToolUtil.isNotEmpty(recovery) && "RESOLVED".equals(recovery)) { status = 1; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java index 625e944c..aa0bc7e5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java @@ -50,7 +50,7 @@ public Boolean action(DeviceDto deviceDto, Map> map) } //属性 - List productAttributeList = new QProductAttribute().productId.eq(deviceDto.getProductId() + "").findList(); + List productAttributeList = new QProductAttribute().productId.eq(deviceDto.getProductId() + "").findList(); List newProductAttributeList = new ArrayList<>(); for (ProductAttribute productAttribute : productAttributeList) { @@ -65,7 +65,7 @@ public Boolean action(DeviceDto deviceDto, Map> map) DB.saveAll(newProductAttributeList); //属性事件 - List productAttributeEventList = new QProductAttributeEvent().productId.eq(deviceDto.getProductId() + "").findList(); + List productAttributeEventList = new QProductAttributeEvent().productId.eq(deviceDto.getProductId() + "").findList(); List newProductAttributeEventList = new ArrayList<>(); for (ProductAttributeEvent productAttributeEvent : productAttributeEventList) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java index 33bcaeec..39257247 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java @@ -17,7 +17,7 @@ /** * @author yefei - * + *

* 处理设备与设备组关系处理步骤 */ @Slf4j @@ -35,7 +35,7 @@ public Boolean action(DeviceDto deviceDto, Map> map) } //保存设备与设备组关系 - Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); + Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); List devicesGroupsList = new ArrayList<>(); for (Long deviceGroupId : deviceDto.getDeviceGroupIds()) { devicesGroupsList.add(DevicesGroups.builder().deviceId(device.getDeviceId()).deviceGroupId(deviceGroupId).build()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java index 0e62b2eb..1572ecc2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java @@ -79,7 +79,7 @@ public Boolean action(DeviceDto deviceDto, Map> allW Map map = triggers.parallelStream().collect(Collectors.toMap(ProductEventRuleService.Triggers::getDescription, ProductEventRuleService.Triggers::getTriggerid)); List productEventRelationList = new QProductEventRelation().status.eq(CommonStatus.ENABLE.getCode()).relationId.eq(deviceDto.getProductId() + "").findList(); - List newRelationList = new ArrayList<>(); + List newRelationList = new ArrayList<>(); for (ProductEventRelation productEventRelation : productEventRelationList) { ProductEventRelation newEventRelation = new ProductEventRelation(); newEventRelation.setRelationId(deviceId); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java index c071ed43..de2dc940 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java @@ -36,11 +36,11 @@ public String action(DeviceDto deviceDto, Map> map) log.debug("处理Zbx host工作…………"); //设备ID 作为zbx HOST name Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); - String host = device.getDeviceId() + ""; + String host = device.getDeviceId() + ""; //取出 设备对应的 zbx主机组ID,模板ID List hostGrpIds = new QDeviceGroup().select(QDeviceGroup.alias().zbxId).deviceGroupId.in(deviceDto.getDeviceGroupIds()).findSingleAttributeList(); - String templateId = new QProduct().select(QProduct.alias().zbxId).productId.eq(deviceDto.getProductId()).findSingleAttribute(); + String templateId = new QProduct().select(QProduct.alias().zbxId).productId.eq(deviceDto.getProductId()).findSingleAttribute(); hostGrpIds.add(ConstantsContext.getConstntsMap().get(GLOBAL_HOST_GROUP_CODE).toString()); //保存 zbx主机 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java index 1572b2a0..d01da6e3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java @@ -52,7 +52,7 @@ public Boolean action(DeviceDto deviceDto, Map> map) } //取出 ZBX hostid - Object result = map.get("saveZbxHostWork").getWorkResult().getResult(); + Object result = map.get("saveZbxHostWork").getWorkResult().getResult(); JSONArray hostid = JSONObject.parseObject(result.toString()).getJSONArray("hostids"); //根据hostid 取出监控项 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java index 1a02e28e..8f14ce7f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java @@ -14,7 +14,7 @@ /** * @author yefei - * + *

* 更新设备中zbxID */ @Slf4j @@ -26,9 +26,9 @@ public class UpdateDeviceZbxIdWorker implements IWorker { public Boolean action(String deviceDto, Map> map) { log.debug("处理 zbxID 回填工作…………"); - Object result = map.get("saveZbxHostWork").getWorkResult().getResult(); + Object result = map.get("saveZbxHostWork").getWorkResult().getResult(); JSONArray hostid = JSONObject.parseObject(result.toString()).getJSONArray("hostids"); - Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); + Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); device.setZbxId(hostid.get(0).toString()); DB.update(device); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java index 19962cb0..8329cb80 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java @@ -34,15 +34,15 @@ public class UpdateZbxTagWorker implements IWorker { public Boolean action(DeviceDto deviceDto, Map> map) { log.debug("同步 zbx tag 工作……"); //取出 ZBX hostid - Object result = map.get("saveZbxHostWork").getWorkResult().getResult(); + Object result = map.get("saveZbxHostWork").getWorkResult().getResult(); JSONArray hostid = JSONObject.parseObject(result.toString()).getJSONArray("hostids"); //取 设备ID - Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); - String deviceId = device.getDeviceId(); + Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); + String deviceId = device.getDeviceId(); //查询出本地tag - List list = new QTag().sid.eq(deviceId).findList(); + List list = new QTag().sid.eq(deviceId).findList(); Map tagMap = new HashMap<>(list.size()); for (Tag tag : list) { tagMap.put(tag.getTag(), tag.getValue()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/aop/GlobalExceptionHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/aop/GlobalExceptionHandler.java index e6da81b1..fbb2d62c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/aop/GlobalExceptionHandler.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/aop/GlobalExceptionHandler.java @@ -94,7 +94,7 @@ public ErrorResponseData handleError(MethodArgumentTypeMismatchException e) { public ErrorResponseData handleError(MethodArgumentNotValidException e) { log.warn("Method Argument Not Valid", e); BindingResult result = e.getBindingResult(); - FieldError error = result.getFieldError(); + FieldError error = result.getFieldError(); String message = String.format("%s:%s", error.getField(), error.getDefaultMessage()); return new ErrorResponseData(400, message); @@ -108,8 +108,8 @@ public ErrorResponseData handleError(MethodArgumentNotValidException e) { @ResponseBody public ErrorResponseData handleError(BindException e) { log.warn("Bind Exception", e); - FieldError error = e.getFieldError(); - String message = String.format("%s:%s", error.getField(), error.getDefaultMessage()); + FieldError error = e.getFieldError(); + String message = String.format("%s:%s", error.getField(), error.getDefaultMessage()); return new ErrorResponseData(400, message); } @@ -122,9 +122,9 @@ public ErrorResponseData handleError(BindException e) { public ErrorResponseData handleError(ConstraintViolationException e) { log.warn("Constraint Violation", e); Set> violations = e.getConstraintViolations(); - ConstraintViolation violation = violations.iterator().next(); - String path = ((PathImpl) violation.getPropertyPath()).getLeafNode().getName(); - String message = String.format("%s:%s", path, violation.getMessage()); + ConstraintViolation violation = violations.iterator().next(); + String path = ((PathImpl) violation.getPropertyPath()).getLeafNode().getName(); + String message = String.format("%s:%s", path, violation.getMessage()); return new ErrorResponseData(400, message); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index a21209c7..57cad79d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -54,7 +54,7 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { ROLE_HAS_BIND_USER(602, "角色绑定了用户,请先解除绑定!"), MENU_NOT_EXIST_OR_NO_PRERMISSION(603, "菜单不存在或无权授权此菜单"), ROLE_NOT_EXIST(604, "角色不存在"), - CANNOT_MODIFY_OWNER_MENUS(605,"不能修改自己所在角色的菜单"), + CANNOT_MODIFY_OWNER_MENUS(605, "不能修改自己所在角色的菜单"), /** * 账户问题 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java index 2d8f2480..87f37c6a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java @@ -51,8 +51,8 @@ public void init() { * @return String */ public String getGlobalHostGroup() { - String response = zbxHostGroup.getGlobalHostGroup(zbxApiToken); - List> ids = JSON.parseObject(response, List.class); + String response = zbxHostGroup.getGlobalHostGroup(zbxApiToken); + List> ids = JSON.parseObject(response, List.class); if (null != ids && ids.size() > 0) { return ids.get(0).get("groupid"); } @@ -75,8 +75,8 @@ public String createGlobalHostGroup() { * @return String */ public String getCookieUserGroup() { - String response = zbxInitService.getCookieUserGroup(zbxApiToken); - List> ids = JSON.parseObject(response, List.class); + String response = zbxInitService.getCookieUserGroup(zbxApiToken); + List> ids = JSON.parseObject(response, List.class); if (null != ids && ids.size() > 0) { return ids.get(0).get("usrgrpid"); } @@ -100,8 +100,8 @@ public String createCookieUserGroup(String globalHostGroupId) { * @return String */ public String getCookieUser() { - String response = zbxInitService.getCookieUser(zbxApiToken); - List> ids = JSON.parseObject(response, List.class); + String response = zbxInitService.getCookieUser(zbxApiToken); + List> ids = JSON.parseObject(response, List.class); if (null != ids && ids.size() > 0) { return ids.get(0).get("userid"); } @@ -125,8 +125,8 @@ public String createCookieUser(String groupId, String roleId) { * @return String */ public String getAdminRoleId() { - String response = zbxInitService.getAdminRole(zbxApiToken); - List> ids = JSON.parseObject(response, List.class); + String response = zbxInitService.getAdminRole(zbxApiToken); + List> ids = JSON.parseObject(response, List.class); if (null != ids && ids.size() > 0) { return ids.get(0).get("roleid"); } @@ -139,8 +139,8 @@ public String getAdminRoleId() { * @return String */ public String getGuestRoleId() { - String response = zbxInitService.getGuestRole(zbxApiToken); - List> ids = JSON.parseObject(response, List.class); + String response = zbxInitService.getGuestRole(zbxApiToken); + List> ids = JSON.parseObject(response, List.class); if (null != ids && ids.size() > 0) { return ids.get(0).get("roleid"); } @@ -154,9 +154,9 @@ public Map createOfflineStatusScript() { } public Map getOfflineStatusScript() { - String response = zbxScript.getOfflineStatusScript(zbxApiToken); - List> ids = JSON.parseObject(response, List.class); - Map map = new HashMap<>(3); + String response = zbxScript.getOfflineStatusScript(zbxApiToken); + List> ids = JSON.parseObject(response, List.class); + Map map = new HashMap<>(3); if (null != ids && ids.size() > 0) { ids.forEach(script -> { map.put(script.get("name"), script.get("scriptid")); @@ -173,8 +173,8 @@ public String createAction(String name, String tagName, String scriptId, String public String getAction(String name) { - String response = zbxAction.getOfflineStatusAction(zbxApiToken, name); - List> ids = JSON.parseObject(response, List.class); + String response = zbxAction.getOfflineStatusAction(zbxApiToken, name); + List> ids = JSON.parseObject(response, List.class); if (null != ids && ids.size() > 0) { return ids.get(0).get("actionid"); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java index c18bb91b..c92c9bdb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java @@ -19,22 +19,22 @@ public class DeviceSatusScriptInit implements CommandLineRunner { - public static final String GLOBAL_HOST_GROUP_CODE = "ZEUS_HOST_GROUP_ID"; + public static final String GLOBAL_HOST_GROUP_CODE = "ZEUS_HOST_GROUP_ID"; public static final String GLOBAL_OFFLINE_ACTION_CODE = "ZEUS_OFFLINE_ACTION_ID"; - public static final String GLOBAL_ALARM_ACTION_CODE = "ZEUS_ALARM_ACTION_ID"; - public static final String GLOBAL_EXEC_ACTION_CODE = "ZEUS_EXEC_ACTION_ID"; - public static final String GLOBAL_ADMIN_ROLE_CODE = "ZEUS_ADMIN_ROLE_ID"; - public static final String GLOBAL_EVENT_ACTION_CODE = "ZEUS_EVENT_ACTION_ID"; + public static final String GLOBAL_ALARM_ACTION_CODE = "ZEUS_ALARM_ACTION_ID"; + public static final String GLOBAL_EXEC_ACTION_CODE = "ZEUS_EXEC_ACTION_ID"; + public static final String GLOBAL_ADMIN_ROLE_CODE = "ZEUS_ADMIN_ROLE_ID"; + public static final String GLOBAL_EVENT_ACTION_CODE = "ZEUS_EVENT_ACTION_ID"; public static final String SCRIPT_OFFLINE = "__offline_status__"; - public static final String SCRIPT_ALARM = "__trigger_webhook__"; + public static final String SCRIPT_ALARM = "__trigger_webhook__"; public static final String SCRIPT_EXECUTE = "__trigger_execute__"; - public static final String SCRIPT_EVENT = "__attr_event__"; + public static final String SCRIPT_EVENT = "__attr_event__"; public static final String ACTION_TAG_OFFLINE = "__offline__"; - public static final String ACTION_TAG_ALARM = "__alarm__"; + public static final String ACTION_TAG_ALARM = "__alarm__"; public static final String ACTION_TAG_EXECUTE = "__execute__"; - public static final String ACTION_TAG_EXENT = "__event__"; + public static final String ACTION_TAG_EXENT = "__event__"; @Autowired diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/log/aop/LogAop.java b/zeus-webapp/src/main/java/com/zmops/iot/web/log/aop/LogAop.java index 52d6a862..a1abaea1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/log/aop/LogAop.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/log/aop/LogAop.java @@ -65,15 +65,15 @@ public Object recordSysLog(ProceedingJoinPoint point) throws Throwable { private void handle(ProceedingJoinPoint point) throws Exception { //获取拦截的方法名 - Signature sig = point.getSignature(); + Signature sig = point.getSignature(); MethodSignature msig = null; if (!(sig instanceof MethodSignature)) { throw new IllegalArgumentException("该注解只能用于方法"); } msig = (MethodSignature) sig; - Object target = point.getTarget(); + Object target = point.getTarget(); Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes()); - String methodName = currentMethod.getName(); + String methodName = currentMethod.getName(); //如果当前用户未登录,不做日志 LoginUser user = LoginContextHolder.getContext().getUser(); @@ -82,14 +82,14 @@ private void handle(ProceedingJoinPoint point) throws Exception { } //获取拦截方法的参数 - String className = point.getTarget().getClass().getName(); - Object[] params = point.getArgs(); + String className = point.getTarget().getClass().getName(); + Object[] params = point.getArgs(); //获取操作名称 - BussinessLog annotation = currentMethod.getAnnotation(BussinessLog.class); - String bussinessName = annotation.value(); - String key = annotation.key(); - Class dictClass = annotation.dict(); + BussinessLog annotation = currentMethod.getAnnotation(BussinessLog.class); + String bussinessName = annotation.value(); + String key = annotation.key(); + Class dictClass = annotation.dict(); StringBuilder sb = new StringBuilder(); for (Object param : params) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java index 6283dcc4..5bac65b6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java @@ -87,7 +87,7 @@ public ResponseData updateUserMacro(@Validated(BaseEntity.Update.class) @Request public ResponseData getUserMacro(@Validated(BaseEntity.Get.class) @RequestBody UserMacro userMacro) { // 获取 模板ID 或者 设备ID - String zbxId = ""; + String zbxId = ""; Device device = new QDevice().deviceId.eq(userMacro.getDeviceId()).findOne(); if (device != null) { zbxId = device.getZbxId(); @@ -148,7 +148,7 @@ static class Macroids { @Getter @Setter static class HostQueryTempObject { - private String hostid; + private String hostid; private List parentTemplates; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java index 94dba1a5..1bc3f90e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java @@ -80,10 +80,10 @@ public ResponseData prodModelAttributeCreate(@RequestBody @Validated(BaseEntity. Long attrId = IdUtil.getSnowflake().nextId(); productAttr.setAttrId(attrId); - String response = productAttributeEventService.createTrapperItem(productAttr); - String zbxId = JSON.parseObject(response, TemplateIds.class).getItemids()[0]; + String response = productAttributeEventService.createTrapperItem(productAttr); + String zbxId = JSON.parseObject(response, TemplateIds.class).getItemids()[0]; - productAttributeEventService.createProductAttr(productAttr,zbxId); + productAttributeEventService.createProductAttr(productAttr, zbxId); return ResponseData.success(productAttr); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java index fc4716d8..71a19c54 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java @@ -104,7 +104,7 @@ public ResponseData prodCreate(@RequestBody @Validated(value = BaseEntity.Create } // 第一步:创建模板 - Long prodId = IdUtil.getSnowflake().nextId(); + Long prodId = IdUtil.getSnowflake().nextId(); String result = productService.zbxTemplateCreate(prodId + ""); // 第二步:创建产品 @@ -162,7 +162,6 @@ public ResponseData prodDelete(@RequestBody @Validated(value = BaseEntity.Delete productService.zbxTemplateDelete(product.getZbxId() + ""); - //第三步:删除产品 boolean del = product.delete(); return ResponseData.success(del); @@ -178,8 +177,8 @@ public ResponseData prodDelete(@RequestBody @Validated(value = BaseEntity.Delete @PostMapping("/tag/update") public ResponseData prodTagCreate(@RequestBody @Valid ProductTag productTag) { - String productId = productTag.getProductId(); - Product product = new QProduct().productId.eq(Long.parseLong(productId)).findOne(); + String productId = productTag.getProductId(); + Product product = new QProduct().productId.eq(Long.parseLong(productId)).findOne(); if (null == product) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); @@ -198,7 +197,7 @@ public ResponseData prodTagCreate(@RequestBody @Valid ProductTag productTag) { DB.saveAll(tags); - String response = productService.updateTemplateTags(product.getZbxId(), productTag); + String response = productService.updateTemplateTags(product.getZbxId(), productTag); String templateId = JSON.parseObject(response, TemplateIds.class).getTemplateids()[0]; if (templateId.equals(product.getZbxId())) { log.info("产品标签修改成功,ID:{}", templateId); @@ -243,7 +242,7 @@ public ResponseData prodValueMapCreate(@RequestBody @Validated(BaseEntity.Create @Permission(code = "product") @PostMapping("/valueMap/delete") public ResponseData prodValueMapDelete(@RequestBody @Validated(BaseEntity.Delete.class) ValueMap valueMap) { - String response = productService.valueMapDelete(valueMap.getValuemapid()); + String response = productService.valueMapDelete(valueMap.getValuemapid()); String valuemapid = JSON.parseObject(response, TemplateIds.class).getValuemapids()[0]; return ResponseData.success(valuemapid); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index d25a53de..a16e05ab 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -54,10 +54,10 @@ public class ProductEventTriggerController { @Autowired private ZbxTrigger zbxTrigger; - private static final String ALARM_TAG_NAME = "__alarm__"; + private static final String ALARM_TAG_NAME = "__alarm__"; private static final String EXECUTE_TAG_NAME = "__execute__"; - private static final String EVENT_TAG_NAME = "__event__"; - private static final String EVENT_TYPE_NAME = "事件"; + private static final String EVENT_TAG_NAME = "__event__"; + private static final String EVENT_TYPE_NAME = "事件"; @Autowired SaveProductEventTriggerWorker saveProductEventTriggerWorker; @@ -234,7 +234,7 @@ public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseE return ResponseData.success(); } //step 01:删除 zbx触发器 - String s = zbxTrigger.triggerGet(productEventRelation.getZbxId()); + String s = zbxTrigger.triggerGet(productEventRelation.getZbxId()); List triggers = JSONObject.parseArray(s, ProductEventRuleService.Triggers.class); if (ToolUtil.isNotEmpty(triggers)) { zbxTrigger.triggerDelete(productEventRelation.getZbxId()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java index 38f2aa29..8742e991 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java @@ -81,11 +81,11 @@ public ResponseData prodModelAttributeCreate(@RequestBody @Validated(BaseEntity. } if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { - if(productAttr.getDepAttrId() == null){ + if (productAttr.getDepAttrId() == null) { throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NULL); } ProductAttribute productAttribute = new QProductAttribute().attrId.eq(productAttr.getDepAttrId()).findOne(); - if(null == productAttribute){ + if (null == productAttribute) { throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); } productAttr.setMasterItemId(productAttribute.getZbxId()); @@ -94,10 +94,10 @@ public ResponseData prodModelAttributeCreate(@RequestBody @Validated(BaseEntity. Long attrId = IdUtil.getSnowflake().nextId(); productAttr.setAttrId(attrId); - String response = productModelService.createTrapperItem(productAttr); - String zbxId = JSON.parseObject(response, TemplateIds.class).getItemids()[0]; + String response = productModelService.createTrapperItem(productAttr); + String zbxId = JSON.parseObject(response, TemplateIds.class).getItemids()[0]; - productModelService.createProductAttr(productAttr,zbxId); + productModelService.createProductAttr(productAttr, zbxId); return ResponseData.success(productAttr); } @@ -116,11 +116,11 @@ public ResponseData prodModelAttributeUpdate(@RequestBody @Validated(BaseEntity. } if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { - if(productAttr.getDepAttrId() == null){ + if (productAttr.getDepAttrId() == null) { throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NULL); } ProductAttribute productAttribute = new QProductAttribute().attrId.eq(productAttr.getDepAttrId()).findOne(); - if(null == productAttribute){ + if (null == productAttribute) { throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); } productAttr.setMasterItemId(productAttribute.getZbxId()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java index cd03ec30..09286dac 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java @@ -54,7 +54,7 @@ public ResponseData getRule(@RequestParam("relationId") String relationId) { @PostMapping("/create") public ResponseData createDeviceStatusTrigger(@RequestBody @Validated(BaseEntity.Create.class) ProductStatusJudgeRule rule) { - ProductAttribute prodAttr = new QProductAttribute().attrId.eq(rule.getAttrId()).findOne(); + ProductAttribute prodAttr = new QProductAttribute().attrId.eq(rule.getAttrId()).findOne(); ProductAttribute prodAttrSecond = new QProductAttribute().attrId.eq(rule.getAttrIdRecovery()).findOne(); if (null == prodAttr || null == prodAttrSecond) { @@ -78,7 +78,7 @@ public ResponseData createDeviceStatusTrigger(@RequestBody @Validated(BaseEntity @PostMapping("/update") public ResponseData updateDeviceStatusTrigger(@RequestBody @Validated(BaseEntity.Update.class) ProductStatusJudgeRule rule) { - ProductAttribute prodAttr = new QProductAttribute().attrId.eq(rule.getAttrId()).findOne(); + ProductAttribute prodAttr = new QProductAttribute().attrId.eq(rule.getAttrId()).findOne(); ProductAttribute prodAttrSecond = new QProductAttribute().attrId.eq(rule.getAttrIdRecovery()).findOne(); if (null == prodAttr || null == prodAttrSecond) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java index 5757ed4d..d8d59298 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java @@ -66,12 +66,12 @@ public class ProductAttr { private Integer delay; //取数间隔单位 - private String unit; + private String unit; LocalDateTime createTime; LocalDateTime updateTime; - Long createUser; - Long updateUser; + Long createUser; + Long updateUser; /** * 预处理步骤 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java index eb951955..d07bda20 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java @@ -73,7 +73,7 @@ public class ProductAttrDto { private Integer delay; private String delayName; //取数间隔单位 - private String unit; + private String unit; private String error; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrEvent.java index d90fa160..216dfdc7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrEvent.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrEvent.java @@ -57,8 +57,8 @@ public class ProductAttrEvent { LocalDateTime createTime; LocalDateTime updateTime; - Long createUser; - Long updateUser; + Long createUser; + Long updateUser; /** * 预处理步骤 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java index 4f03aed6..7d2bc304 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java @@ -30,7 +30,7 @@ public class ProductEventDto { private String remark; private String classify; - private String expLogic; + private String expLogic; @CachedValue(type = DicType.SysUserName) private String createUser; private String createTime; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java index 0277d867..d3ecf485 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java @@ -61,7 +61,7 @@ public class ProductEventRule { private String status; private String classify = "0"; - + @Data public static class Tag { @@ -98,7 +98,7 @@ public static class Expression { private String unit; - private Long productAttrId; + private Long productAttrId; private String productAttrType; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductTag.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductTag.java index 1bc0dffe..67a3dd06 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductTag.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductTag.java @@ -3,7 +3,6 @@ import lombok.Data; import javax.validation.Valid; -import javax.validation.constraints.Max; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java index f1e8c612..d46232a5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java @@ -14,7 +14,7 @@ @Data public class ProductAttrParam extends BaseQueryParam { - @NotNull(groups = BaseEntity.Get.class,message = "请选择一个设备再查询") + @NotNull(groups = BaseEntity.Get.class, message = "请选择一个设备再查询") private String prodId; private String attrName; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java index be9f826e..cbd50c78 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -74,7 +74,7 @@ public Pager prodAttributeEventList(ProductAttrParam productAttr } List pagedList = qProductAttribute.setFirstRow((productAttr.getPage() - 1) * productAttr.getMaxRow()).setMaxRows(productAttr.getMaxRow()).asDto(ProductAttrDto.class).findList(); - int count = qProductAttribute.findCount(); + int count = qProductAttribute.findCount(); return new Pager<>(pagedList, count); } @@ -125,7 +125,7 @@ private List formatProcessStep(String preprocessing) return Collections.emptyList(); } List processingSteps = new ArrayList<>(); - JSONArray jsonArray = JSONObject.parseArray(preprocessing); + JSONArray jsonArray = JSONObject.parseArray(preprocessing); for (Object object : jsonArray) { ProductAttr.ProcessingStep processingStep = new ProductAttr.ProcessingStep(); processingStep.setType(((JSONObject) object).getString("type")); @@ -185,8 +185,8 @@ private ProductAttributeEvent buildProdAttribute(ProductAttributeEvent prodAttri public String createTrapperItem(ProductAttrEvent productAttr) { String itemName = productAttr.getAttrId() + ""; - String hostId = ""; - Device device = new QDevice().deviceId.eq(productAttr.getProductId()).findOne(); + String hostId = ""; + Device device = new QDevice().deviceId.eq(productAttr.getProductId()).findOne(); if (null == device) { Product prod = new QProduct().productId.eq(Long.parseLong(productAttr.getProductId())).findOne(); if (null == prod) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index b3a2a4f8..e0f054ea 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -294,8 +294,8 @@ static class TriggerIds { @Data public static class Triggers { - private String triggerid; - private String description; + private String triggerid; + private String description; private List hosts; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index a570cb92..4a7e3fe8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -124,7 +124,7 @@ private List formatProcessStep(String preprocessing) return Collections.emptyList(); } List processingSteps = new ArrayList<>(); - JSONArray jsonArray = JSONObject.parseArray(preprocessing); + JSONArray jsonArray = JSONObject.parseArray(preprocessing); for (Object object : jsonArray) { ProductAttr.ProcessingStep processingStep = new ProductAttr.ProcessingStep(); processingStep.setType(((JSONObject) object).getString("type")); @@ -223,7 +223,7 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { if (null == prod) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } - String hostId = prod.getZbxId(); + String hostId = prod.getZbxId(); List processingSteps = new ArrayList<>(); if (ToolUtil.isNotEmpty(productAttr.getProcessStepList())) { productAttr.getProcessStepList().forEach(i -> { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java index bf2a66eb..b3cbb838 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java @@ -88,9 +88,9 @@ public Pager getProductByPage(ProductBasicInfo prodBasicInfo) { .setMaxRows(prodBasicInfo.getMaxRow()).orderBy(" create_time desc").asDto(ProductDto.class).findList(); if (ToolUtil.isNotEmpty(list)) { - List productIds = list.parallelStream().map(ProductDto::getProductId).collect(Collectors.toList()); - List deviceList = new QDevice().select(QDevice.alias().productId, QDevice.alias().totalCount).productId.in(productIds).findList(); - Map map = deviceList.parallelStream().collect(Collectors.toMap(Device::getProductId, Device::getTotalCount)); + List productIds = list.parallelStream().map(ProductDto::getProductId).collect(Collectors.toList()); + List deviceList = new QDevice().select(QDevice.alias().productId, QDevice.alias().totalCount).productId.in(productIds).findList(); + Map map = deviceList.parallelStream().collect(Collectors.toMap(Device::getProductId, Device::getTotalCount)); for (ProductDto productDto : list) { productDto.setDeviceNum(Optional.ofNullable(map.get(productDto.getProductId())).orElse(0L)); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index 4b48e3a8..8a3a3421 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -48,7 +48,7 @@ public class ProductSvcService { * @return */ public Pager getServiceByPage(ProductSvcParam productSvcParam) { - StringBuilder sql = new StringBuilder("SELECT s.*,r.inherit from product_service s LEFT JOIN product_service_relation r on r.service_id=s.id where 1=1 "); + StringBuilder sql = new StringBuilder("SELECT s.*,r.inherit from product_service s LEFT JOIN product_service_relation r on r.service_id=s.id where 1=1 "); QProductService qProductService = new QProductService(); if (ToolUtil.isNotEmpty(productSvcParam.getName())) { sql.append(" and s.name like :name"); @@ -84,9 +84,9 @@ public Pager getServiceByPage(ProductSvcParam productSvcParam return new Pager<>(productServiceDtoList, 0); } //查询关联的参数 - List sids = productServiceDtoList.parallelStream().map(ProductServiceDto::getId).collect(Collectors.toList()); - List serviceParamList = new QProductServiceParam().serviceId.in(sids).findList(); - Map> map = serviceParamList.parallelStream().collect(Collectors.groupingBy(ProductServiceParam::getServiceId)); + List sids = productServiceDtoList.parallelStream().map(ProductServiceDto::getId).collect(Collectors.toList()); + List serviceParamList = new QProductServiceParam().serviceId.in(sids).findList(); + Map> map = serviceParamList.parallelStream().collect(Collectors.groupingBy(ProductServiceParam::getServiceId)); productServiceDtoList.forEach(productServiceDto -> { if (null != map.get(productServiceDto.getId())) { productServiceDto.setProductServiceParamList(map.get(productServiceDto.getId())); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java index f4827270..dc4bdae6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java @@ -86,7 +86,7 @@ public Long createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { //step 4:同步到设备 String relationId = judgeRule.getRelationId(); if (ToolUtil.isNum(relationId)) { - String sql = "select device_id from device where product_id = :productId and device_id not in (select relation_id from product_status_function_relation where inherit='0')"; + String sql = "select device_id from device where product_id = :productId and device_id not in (select relation_id from product_status_function_relation where inherit='0')"; List deviceDtoList = DB.findDto(DeviceDto.class, sql).setParameter("productId", Long.parseLong(relationId)).findList(); deviceDtoList.forEach(deviceDto -> { DB.sqlUpdate("insert into product_status_function_relation (relation_id,rule_id,inherit) SELECT :deviceId,rule_id,1 from product_status_function_relation where relation_id=:relationId") diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTypeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTypeService.java index ef09c156..0eeb2233 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTypeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTypeService.java @@ -29,8 +29,8 @@ public class ProductTypeService implements CommandLineRunner { * 产品分类树 */ public List tree() { - String sql = "select id,pid pId,name,pids from product_type"; - List list = DB.findDto(TreeNode.class, sql).findList(); + String sql = "select id,pid pId,name,pids from product_type"; + List list = DB.findDto(TreeNode.class, sql).findList(); DefaultTreeBuildFactory treeBuildFactory = new DefaultTreeBuildFactory<>(); treeBuildFactory.setRootParentId("0"); return treeBuildFactory.doTreeBuild(list); @@ -109,7 +109,7 @@ private void setPids(ProductType productType) { if (productType.getPid().equals(0L)) { productType.setPids("[0],"); } else { - Long pid = productType.getPid(); + Long pid = productType.getPid(); ProductType temp = new QProductType().id.eq(pid).findOne(); if (null == temp) { throw new ServiceException(BizExceptionEnum.PRODUCT_TYPE_PID_NOT_EXIST); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java index ded8c4b2..4d2058fa 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java @@ -46,7 +46,7 @@ public Boolean action(ProductAttr productAttr, Map> //取出继承的属性 并塞入对应的 itemId List productAttributeList = new QProductAttribute().templateId.eq(attrId).findList(); for (ProductAttribute productAttribute : productAttributeList) { - productAttribute.setZbxId(itemMap.get(productAttribute.getProductId()+"").getItemid()); + productAttribute.setZbxId(itemMap.get(productAttribute.getProductId() + "").getItemid()); } DB.updateAll(productAttributeList); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java index 8cab5df3..5f83a806 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java @@ -27,7 +27,7 @@ public class SaveProdAttrEventTriggerWorker implements IWorker> map) { log.debug("处理产品 新增Attr事件 告警工作…………"); - String prodId = productAttr.getProductId(); + String prodId = productAttr.getProductId(); StringBuilder expression = new StringBuilder(); expression.append("count(/"); expression.append(prodId); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java index 7e7d9611..3b5483ad 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java @@ -37,8 +37,8 @@ public Boolean action(ProductAttr productAttr, Map> " select product_id from product_attribute " + " where template_id is null and key = :key)"; - List deviceDtoList = DB.findDto(DeviceDto.class, sql).setParameter("productId", Long.parseLong(productAttr.getProductId())) - .setParameter("key",productAttr.getKey()).findList(); + List deviceDtoList = DB.findDto(DeviceDto.class, sql).setParameter("productId", Long.parseLong(productAttr.getProductId())) + .setParameter("key", productAttr.getKey()).findList(); List productAttributeList = new ArrayList<>(); for (DeviceDto deviceDto : deviceDtoList) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java index f53b6c6d..20aae235 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java @@ -30,7 +30,7 @@ public Boolean action(ProductServiceDto productServiceDto, Map deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); + List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); List productStatusFunctionRelationList = new ArrayList<>(); for (String deviceId : deviceIds) { ProductStatusFunctionRelation productStatusFunctionRelation = new ProductStatusFunctionRelation(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java index e79bcf6d..8597a57b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java @@ -30,7 +30,7 @@ public Boolean action(ProductServiceDto productServiceDto, Map deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); + List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); List productServiceRelationList = new ArrayList<>(); for (String deviceId : deviceIds) { ProductServiceRelation productServiceRelation = new ProductServiceRelation(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java index 05c9472d..0e234b43 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java @@ -40,10 +40,10 @@ public Boolean action(ProductEventRule productEventRule, Map deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); - List triggers = JSONObject.parseArray(zbxTrigger.triggerGetByName(productEventRule.getEventRuleId() + ""), ProductEventRuleService.Triggers.class); + List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); + List triggers = JSONObject.parseArray(zbxTrigger.triggerGetByName(productEventRule.getEventRuleId() + ""), ProductEventRuleService.Triggers.class); - Map treiggerMap = triggers.parallelStream().collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ProductEventRuleService.Triggers::getTriggerid)); + Map treiggerMap = triggers.parallelStream().collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ProductEventRuleService.Triggers::getTriggerid)); List productEventRelationList = new ArrayList<>(); for (String deviceId : deviceIds) { ProductEventRelation productEventRelation = new ProductEventRelation(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java index 47fde1d9..5b777669 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java @@ -35,7 +35,7 @@ public Boolean action(ProductAttr productAttr, Map> List newList = new ArrayList<>(); for (ProductAttribute productAttribute : list) { ProductAttribute newProductAttribute = new ProductAttribute(); - ToolUtil.copyProperties(productAttribute,newProductAttribute); + ToolUtil.copyProperties(productAttribute, newProductAttribute); newProductAttribute.setName(productAttr.getAttrName()); newProductAttribute.setKey(productAttr.getKey()); newProductAttribute.setUnits(productAttr.getUnits()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/KaptchaController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/KaptchaController.java index e691e208..523f106f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/KaptchaController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/KaptchaController.java @@ -55,7 +55,7 @@ public void index(HttpServletRequest request, HttpServletResponse response) { session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText); // create the image with the text - BufferedImage bi = producer.createImage(capText); + BufferedImage bi = producer.createImage(capText); ServletOutputStream out = null; try { out = response.getOutputStream(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java index 2296f353..f3b48ed9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java @@ -14,7 +14,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; import javax.validation.Valid; import java.util.Map; @@ -79,7 +82,7 @@ public ResponseData loginVali(@Valid @RequestBody LoginParam loginParam) { if (ConstantsContext.getKaptchaOpen()) { String kaptcha = super.getPara("kaptcha").trim(); - String code = (String) super.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY); + String code = (String) super.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY); if (ToolUtil.isEmpty(kaptcha) || !kaptcha.equalsIgnoreCase(code)) { throw new InvalidKaptchaException(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysMenuController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysMenuController.java index aea1ebb6..95c6d3c0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysMenuController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysMenuController.java @@ -33,7 +33,7 @@ public class SysMenuController { */ @RequestMapping("/list") public ResponseData getMenuList() { - LoginUser user = LoginContextHolder.getContext().getUser(); + LoginUser user = LoginContextHolder.getContext().getUser(); List roleList = user.getRoleList(); if (ToolUtil.isEmpty(roleList)) { throw new ServiceException(BizExceptionEnum.USER_NOT_BIND_ROLE); @@ -54,8 +54,8 @@ public ResponseData getMenuList() { " ORDER BY" + " m1.menu_id ASC"; - List menuList = DB.sqlQuery(sql).setParameter("roleIds", roleList).findList(); - Map map = new HashMap<>(2); + List menuList = DB.sqlQuery(sql).setParameter("roleIds", roleList).findList(); + Map map = new HashMap<>(2); map.put("menu", menuList.parallelStream().filter(x -> "Y".equals(x.getString("menu_flag"))).collect(Collectors.toList())); map.put("button", menuList.parallelStream().filter(x -> "N".equals(x.getString("menu_flag"))).map(x -> x.getString("url")).collect(Collectors.toList())); return ResponseData.success(map); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java index 9ee976d1..7ee4bc34 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java @@ -1,18 +1,13 @@ package com.zmops.iot.web.sys.controller; -import com.zmops.iot.constant.ConstantsContext; import com.zmops.iot.core.log.BussinessLog; -import com.zmops.iot.core.util.SaltUtil; import com.zmops.iot.domain.BaseEntity; -import com.zmops.iot.domain.sys.SysUser; -import com.zmops.iot.domain.sys.query.QSysUser; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.sys.dto.UserDto; import com.zmops.iot.web.sys.dto.param.UserParam; import com.zmops.iot.web.sys.service.SysUserService; -import io.ebean.DB; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/BaseQueryParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/BaseQueryParam.java index 2aa50804..4f614a21 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/BaseQueryParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/BaseQueryParam.java @@ -7,6 +7,6 @@ **/ @Data public class BaseQueryParam { - private int page = 1; + private int page = 1; private int maxRow = 10; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictService.java index f2eead06..064163a7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictService.java @@ -129,8 +129,8 @@ public List listDicts(String dictTypeCode) { * 分组查询字典列表,通过字典编码 */ public Map> groupDictByCode(String dictTypeCode) { - Long dictTypeId = new QSysDictType().select(QSysDictType.alias().dictTypeId).code.eq(dictTypeCode).findSingleAttribute(); - List sysDicts = listDicts(dictTypeId); + Long dictTypeId = new QSysDictType().select(QSysDictType.alias().dictTypeId).code.eq(dictTypeCode).findSingleAttribute(); + List sysDicts = listDicts(dictTypeId); if (ToolUtil.isEmpty(sysDicts)) { return new HashMap<>(); } @@ -138,10 +138,10 @@ public Map> groupDictByCode(String dictTypeCode) { } private void updateDictionaries() { - List dictTypes = new QSysDictType().findList(); - Map map = dictTypes.parallelStream().collect(Collectors.toMap(SysDictType::getDictTypeId, SysDictType::getCode)); - List collect = dictTypes.stream().map(SysDictType::getDictTypeId).collect(Collectors.toList()); - List dictList = new QSysDict().dictTypeId.in(collect).findList(); + List dictTypes = new QSysDictType().findList(); + Map map = dictTypes.parallelStream().collect(Collectors.toMap(SysDictType::getDictTypeId, SysDictType::getCode)); + List collect = dictTypes.stream().map(SysDictType::getDictTypeId).collect(Collectors.toList()); + List dictList = new QSysDict().dictTypeId.in(collect).findList(); Table dictionaryValues = HashBasedTable.create(); for (SysDict dict : dictList) { dictionaryValues.put(map.get(dict.getDictTypeId()), dict.getCode(), dict.getName()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysParamService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysParamService.java index 34facecc..50c452f3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysParamService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysParamService.java @@ -22,8 +22,8 @@ public List list() { } public void update(SysParamDto sysParamDto) { - Map sysParamMap = sysParamDto.getSysParamList().parallelStream().collect(Collectors.toMap(SysParamDto.SysParam::getId, o -> o)); - List sysParamList = list(); + Map sysParamMap = sysParamDto.getSysParamList().parallelStream().collect(Collectors.toMap(SysParamDto.SysParam::getId, o -> o)); + List sysParamList = list(); for (SysConfig sysConfig : sysParamList) { SysParamDto.SysParam sysParam = sysParamMap.get(sysConfig.getId()); sysConfig.setName(sysParam.getName()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java index 9d8d7b8b..c0e8bd91 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java @@ -123,7 +123,7 @@ private void checkRoleId(Long roleId) { */ private void checkMenuId(List menuIds) { List paramMuenuIds = new ArrayList<>(menuIds); - LoginUser user = LoginContextHolder.getContext().getUser(); + LoginUser user = LoginContextHolder.getContext().getUser(); if (null == user) { throw new ServiceException(AuthExceptionEnum.NOT_LOGIN_ERROR); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java index 21dcc00f..d378eafa 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java @@ -97,8 +97,8 @@ public SysUserGroup createUserGroup(UserGroupDto userGroup) { newUserGroup.setUserGroupId(usrGrpId); newUserGroup.setStatus(CommonStatus.ENABLE.getCode()); //回填 ZBX用户组ID - JSONObject result = JSONObject.parseObject(zbxUserGroup.userGrpAdd(String.valueOf(usrGrpId))); - JSONArray userGrpids = result.getJSONArray("usrgrpids"); + JSONObject result = JSONObject.parseObject(zbxUserGroup.userGrpAdd(String.valueOf(usrGrpId))); + JSONArray userGrpids = result.getJSONArray("usrgrpids"); newUserGroup.setZbxId(userGrpids.get(0).toString()); DB.save(newUserGroup); @@ -196,9 +196,9 @@ public String getZabUsrGrpId(Long usrGrpId) { */ public void bindHostGrp(UserGroupParam userGroup) { //修改ZBX 用户组绑定主机组 - String usrGrpZbxId = getZabUsrGrpId(userGroup.getUserGroupId()); - List list = new QDeviceGroup().deviceGroupId.in(userGroup.getDeviceGroupIds()).findList(); - List hostGrpZbxIds = list.parallelStream().map(DeviceGroup::getZbxId).collect(Collectors.toList()); + String usrGrpZbxId = getZabUsrGrpId(userGroup.getUserGroupId()); + List list = new QDeviceGroup().deviceGroupId.in(userGroup.getDeviceGroupIds()).findList(); + List hostGrpZbxIds = list.parallelStream().map(DeviceGroup::getZbxId).collect(Collectors.toList()); zbxUserGroup.userGrpBindHostGroup(hostGrpZbxIds, usrGrpZbxId); List lists = new ArrayList<>(); for (Long deviceGroupId : userGroup.getDeviceGroupIds()) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java index f98d86c2..23597976 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java @@ -55,7 +55,7 @@ public class SysUserService implements CommandLineRunner { public Map getUserIndexInfo() { //获取当前用户角色列表 - LoginUser user = LoginContextHolder.getContext().getUser(); + LoginUser user = LoginContextHolder.getContext().getUser(); List roleList = user.getRoleList(); //用户没有角色无法显示首页信息 @@ -113,7 +113,7 @@ public SysUser createUser(UserDto user) { checkByRole(user.getRoleId()); // 完善账号信息 - String password = user.getPassword(); + String password = user.getPassword(); String decryptPwd = ""; try { password = new String(Hex.decodeHex(password)); @@ -228,8 +228,8 @@ public void changePwd(String oldPassword, String newPassword) { if (null == loginUser) { throw new ServiceException(AuthExceptionEnum.NOT_LOGIN_ERROR); } - SysUser user = new QSysUser().userId.eq(loginUser.getId()).findOne(); - String rawNewPasswd = ""; + SysUser user = new QSysUser().userId.eq(loginUser.getId()).findOne(); + String rawNewPasswd = ""; try { oldPassword = new String(Hex.decodeHex(oldPassword)); newPassword = new String(Hex.decodeHex(newPassword)); From 6100718bacb4fbea9dfb549b3286d81a4263a326 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 9 Oct 2021 21:57:15 +0800 Subject: [PATCH 470/763] [fix]: fix product event trigger valid --- .../main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java | 1 - .../java/com/zmops/iot/web/product/dto/ProductEventRule.java | 1 - 2 files changed, 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java index 8f7305c4..48c99114 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java @@ -77,7 +77,6 @@ public static class Tag { // 告警表达式 构成 public static class Expression { - @NotNull(groups = BaseEntity.Update.class) private Long eventExpId; @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java index d3ecf485..163b022c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java @@ -77,7 +77,6 @@ public static class Tag { // 告警表达式 构成 public static class Expression { - @NotNull(groups = BaseEntity.Update.class) private Long eventExpId; @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) From 9c4344bf83df93713443a191ea19ace51d023816 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 9 Oct 2021 21:58:45 +0800 Subject: [PATCH 471/763] [style]: code format --- .../DeviceEventTriggerController.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index 84ea484d..c36bbea4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -46,10 +46,10 @@ public class DeviceEventTriggerController { @Autowired private ZbxTrigger zbxTrigger; - private static final String ALARM_TAG_NAME = "__alarm__"; + private static final String ALARM_TAG_NAME = "__alarm__"; private static final String EXECUTE_TAG_NAME = "__execute__"; - private static final String EVENT_TAG_NAME = "__event__"; - private static final String EVENT_TYPE_NAME = "事件"; + private static final String EVENT_TAG_NAME = "__event__"; + private static final String EVENT_TYPE_NAME = "事件"; /** * 触发器 详情 @@ -205,25 +205,25 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn */ @Transactional @PostMapping("/delete") - public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseEntity.Delete.class) - DeviceEventRule eventRule) { + public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseEntity.Delete.class) DeviceEventRule eventRule) { ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(eventRule.getDeviceId()) .eventRuleId.eq(eventRule.getEventRuleId()).findOne(); - if (InheritStatus.YES.getCode().equals(productEventRelation.getInherit())) { + if (productEventRelation != null && productEventRelation.getInherit().equals(InheritStatus.YES.getCode())) { throw new ServiceException(BizExceptionEnum.EVENT_PRODUCT_CANNOT_DELETE); } //step 01:删除 zbx触发器 - if (ToolUtil.isNotEmpty(productEventRelation.getZbxId())) { - List triggers = JSONObject.parseArray(zbxTrigger.triggerGet(productEventRelation.getZbxId()), DeviceEventRuleService.Triggers.class); + if (productEventRelation != null && ToolUtil.isNotEmpty(productEventRelation.getZbxId())) { + List triggers = JSONObject.parseArray( + zbxTrigger.triggerGet(productEventRelation.getZbxId()), DeviceEventRuleService.Triggers.class); + if (ToolUtil.isNotEmpty(triggers)) { zbxTrigger.triggerDelete(productEventRelation.getZbxId()); } } - //step 1:删除 与设备的关联 new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); From a6b0fd025d8890e3bc1491bb1cc2fb5122e6ffe9 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 9 Oct 2021 22:11:46 +0800 Subject: [PATCH 472/763] [style]: code format --- .../sender/service/ZabbixSenderService.java | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/service/ZabbixSenderService.java b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/service/ZabbixSenderService.java index 53678a0b..8969c39f 100644 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/service/ZabbixSenderService.java +++ b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/service/ZabbixSenderService.java @@ -36,17 +36,17 @@ public ZabbixSenderService(ModuleManager moduleManager) { * * @param message see * https://www.zabbix.com/documentation/current/manual/appendix/items/trapper - *

- * { - * "request":"sender data", - * "data":[ - * { - * "host":"device.info", - * "key":"device.temp", - * "value":"86" - * } - * ] - * } + * + * { + * "request":"sender data", + * "data":[ + * { + * "host":"device.info", + * "key":"device.temp", + * "value":"86" + * } + * ] + * } * @return String * @throws IOException ex */ @@ -81,6 +81,7 @@ public String sendData(String message) throws IOException { int headLength = 13; int bRead = 0; + while (true) { bRead = resStream.read(response); if (bRead <= 0) break; @@ -106,19 +107,22 @@ public String sendData(String message) throws IOException { * @return String */ private String zabbixResponseToMap(String resp) { - Map result = gson.fromJson(resp, Map.class); - String[] infos = result.get("info").split(";"); - Map resultMap = new HashMap<>(); + String info = result.get("info"); + if (info == null) { + return resp; + } + + String[] infos = info.split(";"); + Map resultMap = new HashMap<>(); for (String i : infos) { String[] ii = i.split(":"); resultMap.put(ii[0].trim(), ii[1]); } resultMap.put("response", result.get("response")); - return gson.toJson(resultMap); } } From bbdcc07e4b6ece1de71492aa87a30ae4f8cb48c1 Mon Sep 17 00:00:00 2001 From: yefei Date: Sun, 10 Oct 2021 09:59:47 +0800 Subject: [PATCH 473/763] [fix]: media type settig list sort --- .../iot/web/alarm/controller/MediaTypeSettingController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MediaTypeSettingController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MediaTypeSettingController.java index bf0e9e40..53d524b2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MediaTypeSettingController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MediaTypeSettingController.java @@ -27,7 +27,8 @@ public ResponseData list(@RequestParam(value = "type", required = false) String if (ToolUtil.isNotEmpty(type)) { qMediaTypeSetting.type.eq(type); } - return new SuccessResponseData(qMediaTypeSetting.findList()); + + return new SuccessResponseData(qMediaTypeSetting.orderBy().id.asc().findList()); } @PostMapping("update") From 63cb3742da043a89c8b3ecbbf5e22abae168bd22 Mon Sep 17 00:00:00 2001 From: yefei Date: Sun, 10 Oct 2021 10:30:07 +0800 Subject: [PATCH 474/763] [feat]: product service param add remark --- .../com/zmops/iot/domain/product/ProductServiceParam.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceParam.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceParam.java index cb9ed60e..9f6d8a4d 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceParam.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceParam.java @@ -17,9 +17,9 @@ public class ProductServiceParam { @Id - private Long id; - private Long serviceId; + private Long id; + private Long serviceId; private String name; private String key; - + private String remark; } From fc35126a107886ff6a9da6f03d5bf163cb431c3e Mon Sep 17 00:00:00 2001 From: yefei Date: Sun, 10 Oct 2021 11:22:48 +0800 Subject: [PATCH 475/763] [fix]: fix product dto --- .../java/com/zmops/iot/web/product/dto/ProductDto.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java index 8ec60953..3e1482ea 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java @@ -7,6 +7,8 @@ import com.zmops.iot.model.cache.filter.DicType; import lombok.Data; +import java.time.LocalDateTime; + /** * @author yefei **/ @@ -38,12 +40,12 @@ public class ProductDto { private String zbxId; + private LocalDateTime createTime; + private LocalDateTime updateTime; @CachedValue(type = DicType.SysUserName) - private String createUser; - private String createTime; + private Long createUser; @CachedValue(type = DicType.SysUserName) - private String updateUser; - private String updateTime; + private Long updateUser; private Long deviceNum; From 196519a3be25db89c4fbfc6da0f2141134b5476c Mon Sep 17 00:00:00 2001 From: yefei Date: Sun, 10 Oct 2021 20:05:40 +0800 Subject: [PATCH 476/763] [fix]: macro list add inherit flag --- .../com/zmops/iot/web/macro/controller/MacroController.java | 4 +++- .../src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java index 5bac65b6..bfb92d5d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java @@ -112,7 +112,9 @@ public ResponseData getUserMacro(@Validated(BaseEntity.Get.class) @RequestBody U if (ToolUtil.isNotEmpty(tempId)) { // 模板宏 List tempMacroList = JSONObject.parseArray(zbxMacro.macroGet(tempId.getTemplateid()), UserMacro.class); - + tempMacroList.forEach(macro -> { + macro.setInherit("1"); + }); // 主机宏 List hostMacroList = JSONObject.parseArray(zbxMacro.macroGet(zbxId + ""), UserMacro.class); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java index 8a94cce4..a4ad5fb4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java @@ -23,6 +23,8 @@ public class UserMacro { private String description; + private String inherit; + @NotBlank(groups = {BaseEntity.Delete.class, BaseEntity.Update.class}) private String hostmacroid; } From 2d29aa3894facaa6ac2d294dbe36583d6d2cafa4 Mon Sep 17 00:00:00 2001 From: yefei Date: Sun, 10 Oct 2021 21:31:31 +0800 Subject: [PATCH 477/763] [fix]: fix product event trigger --- .../src/main/java/com/zmops/iot/util/ToolUtil.java | 10 ++++++++++ .../com/zmops/iot/web/device/dto/DeviceEventRule.java | 3 ++- .../zmops/iot/web/product/dto/ProductEventRule.java | 3 ++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java b/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java index eae3b696..52065070 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java @@ -23,6 +23,16 @@ */ public class ToolUtil { + /** + * 如果对象不是数字类型 就加上双引号返回 + */ + public static String addQuotes(String value){ + if(isNum(value)){ + return value; + } + return "\\\\\"" + value + "\\\\\""; + } + /** * 默认密码盐长度 */ diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java index 48c99114..1b7d251c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java @@ -1,6 +1,7 @@ package com.zmops.iot.web.device.dto; import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.util.ToolUtil; import lombok.Data; import lombok.Getter; import lombok.Setter; @@ -116,7 +117,7 @@ public String toString() { expression.append(", "); expression.append(scope); } - expression.append(") ").append(condition).append(" ").append(value); + expression.append(") ").append(condition).append(" ").append(ToolUtil.addQuotes(value)); return expression.toString(); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java index 163b022c..1eb927c2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java @@ -1,6 +1,7 @@ package com.zmops.iot.web.product.dto; import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.util.ToolUtil; import lombok.Data; import lombok.Getter; import lombok.Setter; @@ -116,7 +117,7 @@ public String toString() { expression.append(", "); expression.append(scope); } - expression.append(") ").append(condition).append(" ").append(value); + expression.append(") ").append(condition).append(" ").append(ToolUtil.addQuotes(value)); return expression.toString(); } } From d3ab85ed2a8a0246f4f3c946daa61ad0f54fe690 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 11 Oct 2021 09:44:56 +0800 Subject: [PATCH 478/763] [feat]: update zeus-iot-ui submodule --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index c458b02a..1aed7fbe 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit c458b02a9ea1c1583925fce1b439509a78102824 +Subproject commit 1aed7fbe950f13de832ccbb4f7f9d26c163a8763 From e0dfde8db67ecedfcd160f1e5391633982d18229 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 11 Oct 2021 09:46:02 +0800 Subject: [PATCH 479/763] [feat]: add freemarker setting --- zeus-starter/src/main/assembly/webapp.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/zeus-starter/src/main/assembly/webapp.yml b/zeus-starter/src/main/assembly/webapp.yml index c5f38c9a..6e8d573a 100644 --- a/zeus-starter/src/main/assembly/webapp.yml +++ b/zeus-starter/src/main/assembly/webapp.yml @@ -39,6 +39,7 @@ spring: freemarker: suffix: .html template-loader-path: classpath:/public/ + checkTemplateLocation: false forest: log-enabled: false From 4f479733eff6dba647b9b9e72ad578149582e010 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 11 Oct 2021 10:00:05 +0800 Subject: [PATCH 480/763] [fix]: update init sql --- dist-material/bin/sql/zeus-iot.sql | 1383 +++++----------------------- 1 file changed, 242 insertions(+), 1141 deletions(-) diff --git a/dist-material/bin/sql/zeus-iot.sql b/dist-material/bin/sql/zeus-iot.sql index 1b530a2b..33677cbd 100644 --- a/dist-material/bin/sql/zeus-iot.sql +++ b/dist-material/bin/sql/zeus-iot.sql @@ -3,16 +3,16 @@ Source Server : 172.16.60.98-测试LOT Source Server Type : PostgreSQL - Source Server Version : 120008 + Source Server Version : 130004 Source Host : 172.16.60.98:5432 Source Catalog : zeus-iot Source Schema : public Target Server Type : PostgreSQL - Target Server Version : 120008 + Target Server Version : 130004 File Encoding : 65001 - Date: 23/09/2021 11:43:08 + Date: 11/10/2021 09:58:57 */ @@ -199,7 +199,8 @@ CREATE TABLE "public"."device" ( "zbx_id" varchar(32) COLLATE "pg_catalog"."default", "addr" varchar(255) COLLATE "pg_catalog"."default", "position" varchar(64) COLLATE "pg_catalog"."default", - "online" int2 DEFAULT 1 + "online" int2, + "latest_online" timestamp(6) ) ; COMMENT ON COLUMN "public"."device"."device_id" IS '设备ID'; @@ -216,11 +217,11 @@ COMMENT ON COLUMN "public"."device"."zbx_id" IS 'zbx主机ID'; COMMENT ON COLUMN "public"."device"."addr" IS '设备地址'; COMMENT ON COLUMN "public"."device"."position" IS '地址坐标'; COMMENT ON COLUMN "public"."device"."online" IS '是否在线 1是 0否'; +COMMENT ON COLUMN "public"."device"."latest_online" IS '最近在线时间'; -- ---------------------------- -- Records of device -- ---------------------------- -INSERT INTO "public"."device" VALUES ('101', '温度传感器', 1440880212866494464, 'ENABLE', '', '2021-09-23 11:27:40.882', 1, '2021-09-23 11:27:41.038', 1, '1', '10590', NULL, NULL, 1); -- ---------------------------- -- Table structure for device_group @@ -249,7 +250,6 @@ COMMENT ON COLUMN "public"."device_group"."update_time" IS '更新时间'; -- ---------------------------- -- Records of device_group -- ---------------------------- -INSERT INTO "public"."device_group" VALUES (1440880403610857472, '我的设备组', '', '55', 1, '2021-09-23 11:27:13.22', 1, '2021-09-23 11:27:13.22'); -- ---------------------------- -- Table structure for device_online_report @@ -288,7 +288,6 @@ COMMENT ON COLUMN "public"."devices_groups"."device_group_id" IS '设备组ID'; -- ---------------------------- -- Records of devices_groups -- ---------------------------- -INSERT INTO "public"."devices_groups" VALUES (170, '101', 1440880403610857472); -- ---------------------------- -- Table structure for media_type_setting @@ -298,35 +297,37 @@ CREATE TABLE "public"."media_type_setting" ( "id" int4 NOT NULL DEFAULT nextval('media_type_setting_id_seq'::regclass), "type" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, "template" text COLLATE "pg_catalog"."default", - "webhooks" text COLLATE "pg_catalog"."default" + "webhooks" text COLLATE "pg_catalog"."default", + "tenant_id" int8 ) ; COMMENT ON COLUMN "public"."media_type_setting"."type" IS '类型'; COMMENT ON COLUMN "public"."media_type_setting"."template" IS '消息模板'; COMMENT ON COLUMN "public"."media_type_setting"."webhooks" IS '推送配置'; +COMMENT ON COLUMN "public"."media_type_setting"."tenant_id" IS '租户ID'; -- ---------------------------- -- Records of media_type_setting -- ---------------------------- -INSERT INTO "public"."media_type_setting" VALUES (3, 'feishu', '{ - "msg_type":"text", - "content": { - "text":"%s" - } -}', '{"url":"https://open.feishu.cn/open-apis/bot/v2/hook/c43e56f3-bdc9-4abb-ba4c-17afc6147f73","secret":"xoaP9dPKLeQIeDk5jZnEdg"}'); -INSERT INTO "public"."media_type_setting" VALUES (1, 'wechat', ' -{ - "content": "广州今日天气:29度,大部分多云,降雨概率:80%", - "mentioned_list":["wangqing","@all"], - "mentioned_mobile_list":["13800001111","@all"] - } -', '{"url":"https://oapi.dingtalk.com/robot/send?access_token=dd0f8a3340c15ec0f1d54b91980584c1127abe6dd143a964d44385647bc15124"}'); +INSERT INTO "public"."media_type_setting" VALUES (1, 'wechat', ' +{ + "content": "广州今日天气:29度,大部分多云,降雨概率:80%", + "mentioned_list":["wangqing","@all"], + "mentioned_mobile_list":["13800001111","@all"] + } +', '{"url":"https://oapi.dingtalk.com/robot/send?access_token=dd0f8a3340c15ec0f1d54b91980584c1127abe6dd143a964d44385647bc15124"}', NULL); INSERT INTO "public"."media_type_setting" VALUES (2, 'dingtalk', '{ "msgtype":"text", "text": { "content":"%s" } -}', '{"url":"https://oapi.dingtalk.com/robot/send?access_token=dd0f8a3340c15ec0f1d54b91980584c1127abe6dd143a964d44385647bc15124","secret":"SEC9b9e759c78a216ddcbeb2612694dbd6e7420b75fe78ffe0de9fac0701e3d4d45"}'); +}', '{"url":"https://oapi.dingtalk.com/robot/send?access_token=dd","secret":"5c60"}', NULL); +INSERT INTO "public"."media_type_setting" VALUES (3, 'feishu', '{ + "msg_type":"text", + "content": { + "text":"%s" + } +}', '{"url":"https://open.feishu.cn/open-apis/bot/v2/hook/c43e56f","secret":"xoaP"}', NULL); -- ---------------------------- -- Table structure for messages @@ -350,173 +351,6 @@ COMMENT ON COLUMN "public"."messages"."readed" IS '是否已读 1-是 0-否'; -- ---------------------------- -- Records of messages -- ---------------------------- -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630303245, NULL, NULL, 1, 55); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630303288, NULL, NULL, 1, 56); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630303362, NULL, NULL, 1, 57); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630303458, NULL, NULL, 1, 58); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630304019, NULL, NULL, 1, 59); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630304038, NULL, NULL, 1, 60); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630304155, NULL, NULL, 1, 61); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630304242, NULL, NULL, 1, 62); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919518, NULL, NULL, 1, 63); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919518, NULL, NULL, 1, 64); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919518, NULL, NULL, 1, 65); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919518, NULL, NULL, 1, 66); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919518, NULL, NULL, 1, 67); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919564, NULL, NULL, 1, 68); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919564, NULL, NULL, 1, 69); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919564, NULL, NULL, 1, 70); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919564, NULL, NULL, 1, 71); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630919564, NULL, NULL, 1, 72); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630921533, NULL, NULL, 1, 73); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630921533, NULL, NULL, 1, 74); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630921533, NULL, NULL, 1, 75); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630921533, NULL, NULL, 1, 76); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432185862590431232","triggername":"test","deviceStatus":"{EVENT.TAGS.OFFLINE}"}', 1630921533, NULL, NULL, 1, 77); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"{TRIGGER.DESCRIPTION","hostname":"1432636352419790848"}', 1631763023, NULL, NULL, 80, 78); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"{TRIGGER.DESCRIPTION","hostname":"1432636352419790848"}', 1631763023, NULL, NULL, 1, 79); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"{TRIGGER.DESCRIPTION","hostname":"1432636352419790848"}', 1631763023, NULL, NULL, 115, 80); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"{TRIGGER.DESCRIPTION","hostname":"1432636352419790848"}', 1631763023, NULL, NULL, 79, 81); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"","hostname":"1432636352419790848"}', 1631763230, NULL, NULL, 80, 82); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"","hostname":"1432636352419790848"}', 1631763230, NULL, NULL, 1, 83); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"","hostname":"1432636352419790848"}', 1631763230, NULL, NULL, 115, 84); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"","hostname":"1432636352419790848"}', 1631763230, NULL, NULL, 79, 85); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763232, NULL, NULL, 80, 86); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763232, NULL, NULL, 1, 87); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763232, NULL, NULL, 115, 88); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763232, NULL, NULL, 79, 89); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763259, NULL, NULL, 80, 90); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763259, NULL, NULL, 1, 91); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763259, NULL, NULL, 115, 92); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763259, NULL, NULL, 79, 93); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763260, NULL, NULL, 80, 94); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763260, NULL, NULL, 1, 95); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763260, NULL, NULL, 115, 96); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"0​"}', 1631763260, NULL, NULL, 79, 97); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"{EVENT.OBJECTID}​"}', 1631763533, NULL, NULL, 80, 98); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"{EVENT.OBJECTID}​"}', 1631763533, NULL, NULL, 1, 99); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"{EVENT.OBJECTID}​"}', 1631763533, NULL, NULL, 115, 100); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"{EVENT.OBJECTID}​"}', 1631763533, NULL, NULL, 79, 101); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"{EVENT.OBJECTID}​"}', 1631763535, NULL, NULL, 80, 102); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"{EVENT.OBJECTID}​"}', 1631763535, NULL, NULL, 1, 103); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"{EVENT.OBJECTID}​"}', 1631763535, NULL, NULL, 115, 104); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"{EVENT.OBJECTID}​"}', 1631763535, NULL, NULL, 79, 105); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"​"}', 1631763972, NULL, NULL, 80, 106); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"​"}', 1631763972, NULL, NULL, 1, 107); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"​"}', 1631763972, NULL, NULL, 115, 108); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"​"}', 1631763972, NULL, NULL, 79, 109); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"​"}', 1631763973, NULL, NULL, 80, 110); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"​"}', 1631763973, NULL, NULL, 1, 111); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"​"}', 1631763973, NULL, NULL, 115, 112); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"​"}', 1631763973, NULL, NULL, 79, 113); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631764088, NULL, NULL, 80, 114); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631764088, NULL, NULL, 1, 115); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631764088, NULL, NULL, 115, 116); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631764088, NULL, NULL, 79, 117); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631764090, NULL, NULL, 80, 118); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631764090, NULL, NULL, 1, 119); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631764090, NULL, NULL, 115, 120); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631764090, NULL, NULL, 79, 121); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774313, NULL, NULL, 80, 122); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774313, NULL, NULL, 1, 123); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774313, NULL, NULL, 115, 124); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774313, NULL, NULL, 79, 125); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774326, NULL, NULL, 80, 126); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774327, NULL, NULL, 1, 127); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774327, NULL, NULL, 115, 128); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774327, NULL, NULL, 79, 129); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774425, NULL, NULL, 80, 130); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774425, NULL, NULL, 115, 131); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774425, NULL, NULL, 1, 132); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774425, NULL, NULL, 79, 133); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774451, NULL, NULL, 80, 134); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774451, NULL, NULL, 115, 135); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774451, NULL, NULL, 1, 136); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774451, NULL, NULL, 79, 137); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774484, NULL, NULL, 80, 138); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774484, NULL, NULL, 115, 139); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774484, NULL, NULL, 1, 140); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774484, NULL, NULL, 79, 141); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774505, NULL, NULL, 80, 142); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774505, NULL, NULL, 115, 143); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774505, NULL, NULL, 1, 144); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774505, NULL, NULL, 79, 145); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774729, NULL, NULL, 80, 146); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774729, NULL, NULL, 115, 147); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774729, NULL, NULL, 1, 148); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774729, NULL, NULL, 79, 149); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774749, NULL, NULL, 80, 150); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774749, NULL, NULL, 115, 151); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774749, NULL, NULL, 1, 152); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggerid":"1436570370054893568​"}', 1631774749, NULL, NULL, 79, 153); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggername":"1436570370054893568​","triggerid":"20077​"}', 1631775655, NULL, NULL, 80, 154); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggername":"1436570370054893568​","triggerid":"20077​"}', 1631775655, NULL, NULL, 115, 155); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggername":"1436570370054893568​","triggerid":"20077​"}', 1631775655, NULL, NULL, 1, 156); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggername":"1436570370054893568​","triggerid":"20077​"}', 1631775655, NULL, NULL, 79, 157); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggername":"1436570370054893568​","triggerid":"20077​"}', 1631775672, NULL, NULL, 80, 158); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggername":"1436570370054893568​","triggerid":"20077​"}', 1631775672, NULL, NULL, 115, 159); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggername":"1436570370054893568​","triggerid":"20077​"}', 1631775673, NULL, NULL, 1, 160); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"1432636352419790848","triggername":"1436570370054893568​","triggerid":"20077​"}', 1631775673, NULL, NULL, 79, 161); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438757419495247872​","triggerid":"20106​"}', 1631861533, NULL, NULL, 1, 162); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438757419495247872​","triggerid":"20106​"}', 1631861533, NULL, NULL, 116, 163); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438757419495247872​","triggerid":"20106​"}', 1631861533, NULL, NULL, 79, 164); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438757739495477248​","triggerid":"20107​"}', 1631861635, NULL, NULL, 1, 165); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438757739495477248​","triggerid":"20107​"}', 1631861635, NULL, NULL, 116, 166); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438757739495477248​","triggerid":"20107​"}', 1631861635, NULL, NULL, 79, 167); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438758964660064256​","triggerid":"20108​"}', 1631861892, NULL, NULL, 1, 168); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438758964660064256​","triggerid":"20108​"}', 1631861892, NULL, NULL, 116, 169); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438758964660064256​","triggerid":"20108​"}', 1631861892, NULL, NULL, 79, 170); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438759211675209728​","triggerid":"20109​"}', 1631861959, NULL, NULL, 1, 171); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438759211675209728​","triggerid":"20109​"}', 1631861959, NULL, NULL, 116, 172); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438759211675209728​","triggerid":"20109​"}', 1631861959, NULL, NULL, 79, 173); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438759729210335232​","triggerid":"20110​"}', 1631862201, NULL, NULL, 1, 174); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438759729210335232​","triggerid":"20110​"}', 1631862201, NULL, NULL, 116, 175); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438759729210335232​","triggerid":"20110​"}', 1631862201, NULL, NULL, 79, 176); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438759844151042048​","triggerid":"20111​"}', 1631862205, NULL, NULL, 1, 177); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438759844151042048​","triggerid":"20111​"}', 1631862205, NULL, NULL, 116, 178); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438759844151042048​","triggerid":"20111​"}', 1631862205, NULL, NULL, 79, 179); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438762285726703616​","triggerid":"20112​"}', 1631862674, NULL, NULL, 1, 180); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438762285726703616​","triggerid":"20112​"}', 1631862674, NULL, NULL, 116, 181); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438762285726703616​","triggerid":"20112​"}', 1631862675, NULL, NULL, 79, 182); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438763312085536768​","triggerid":"20113​"}', 1631862918, NULL, NULL, 1, 183); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438763312085536768​","triggerid":"20113​"}', 1631862918, NULL, NULL, 116, 184); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438763312085536768​","triggerid":"20113​"}', 1631862918, NULL, NULL, 79, 185); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438773665242583040​","triggerid":"20115​"}', 1631865382, NULL, NULL, 1, 186); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438773665242583040​","triggerid":"20115​"}', 1631865382, NULL, NULL, 116, 187); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438773665242583040​","triggerid":"20115​"}', 1631865382, NULL, NULL, 79, 188); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438773665242583040​","triggerid":"20115​"}', 1631868823, NULL, NULL, 1, 189); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438773665242583040​","triggerid":"20115​"}', 1631868823, NULL, NULL, 116, 190); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438773665242583040​","triggerid":"20115​"}', 1631868823, NULL, NULL, 79, 191); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438773665242583040​","triggerid":"20115​"}', 1631868829, NULL, NULL, 1, 192); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438773665242583040​","triggerid":"20115​"}', 1631868829, NULL, NULL, 116, 193); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"hostname":"dfd","triggername":"1438773665242583040​","triggerid":"20115​"}', 1631868829, NULL, NULL, 79, 194); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299476, NULL, NULL, 1, 195); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299476, NULL, NULL, 116, 196); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299476, NULL, NULL, 79, 197); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299697, NULL, NULL, 1, 198); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299697, NULL, NULL, 116, 199); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299697, NULL, NULL, 79, 200); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299723, NULL, NULL, 1, 201); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299723, NULL, NULL, 116, 202); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299723, NULL, NULL, 79, 203); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299759, NULL, NULL, 1, 204); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299759, NULL, NULL, 116, 205); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299759, NULL, NULL, 79, 206); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299788, NULL, NULL, 1, 207); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299788, NULL, NULL, 116, 208); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299788, NULL, NULL, 79, 209); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299845, NULL, NULL, 1, 210); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299845, NULL, NULL, 116, 211); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299845, NULL, NULL, 79, 212); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299870, NULL, NULL, 1, 213); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299870, NULL, NULL, 116, 214); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632299870, NULL, NULL, 79, 215); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632316171, NULL, NULL, 1, 216); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632316171, NULL, NULL, 116, 217); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632316171, NULL, NULL, 79, 218); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632316187, NULL, NULL, 1, 219); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632316187, NULL, NULL, 116, 220); -INSERT INTO "public"."messages" VALUES (1, '告警消息', '{"triggerName":"1438773665242583040","hostname":"dfd"}', 1632316187, NULL, NULL, 79, 221); -- ---------------------------- -- Table structure for product @@ -555,7 +389,6 @@ COMMENT ON COLUMN "public"."product"."zbx_id" IS 'Zabbix对应模板ID'; -- ---------------------------- -- Records of product -- ---------------------------- -INSERT INTO "public"."product" VALUES (1440880212866494464, 214, '温度计', '1', '', '', '', '2021-09-23 11:26:27.74', 1, '2021-09-23 11:26:27.74', 1, 'wd0001', '10589'); -- ---------------------------- -- Table structure for product_attribute @@ -576,7 +409,9 @@ CREATE TABLE "public"."product_attribute" ( "zbx_id" varchar(32) COLLATE "pg_catalog"."default", "value_type" varchar(16) COLLATE "pg_catalog"."default", "dep_attr_id" int8, - "template_id" int8 + "template_id" int8, + "delay" int2, + "unit" varchar(4) COLLATE "pg_catalog"."default" ) ; COMMENT ON COLUMN "public"."product_attribute"."attr_id" IS '属性ID'; @@ -594,12 +429,12 @@ COMMENT ON COLUMN "public"."product_attribute"."zbx_id" IS 'itemid'; COMMENT ON COLUMN "public"."product_attribute"."value_type" IS '值类型'; COMMENT ON COLUMN "public"."product_attribute"."dep_attr_id" IS '依赖属性ID'; COMMENT ON COLUMN "public"."product_attribute"."template_id" IS '继承的属性ID'; +COMMENT ON COLUMN "public"."product_attribute"."delay" IS '取数间隔'; +COMMENT ON COLUMN "public"."product_attribute"."unit" IS '取数间隔单位 s m h '; -- ---------------------------- -- Records of product_attribute -- ---------------------------- -INSERT INTO "public"."product_attribute" VALUES (1440880744175759360, '温度', 'wd', NULL, '2', NULL, '1440880212866494464', 1, '2021-09-23 11:28:34.672', 1, '2021-09-23 11:28:34.672', '37912', '0', NULL, NULL); -INSERT INTO "public"."product_attribute" VALUES (1440880745664737280, '温度', 'wd', NULL, '2', NULL, '101', 1, '2021-09-23 11:28:34.693', 1, '2021-09-23 11:28:34.778', '37913', '0', NULL, 1440880744175759360); -- ---------------------------- -- Table structure for product_attribute_event @@ -649,19 +484,24 @@ CREATE TABLE "public"."product_event" ( "event_rule_id" int8 NOT NULL, "event_rule_name" varchar(255) COLLATE "pg_catalog"."default", "event_level" varchar(1) COLLATE "pg_catalog"."default", - "exp_logic" varchar(10) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", "create_time" timestamp(6), "create_user" int8, "update_time" timestamp(6), "update_user" int8, - "event_notify" varchar(1) COLLATE "pg_catalog"."default" + "exp_logic" varchar(10) COLLATE "pg_catalog"."default", + "event_notify" varchar(1) COLLATE "pg_catalog"."default", + "status" char(1) COLLATE "pg_catalog"."default", + "classify" varchar(2) COLLATE "pg_catalog"."default" ) ; COMMENT ON COLUMN "public"."product_event"."event_rule_id" IS '告警规则ID'; COMMENT ON COLUMN "public"."product_event"."event_rule_name" IS '告警规则名称'; COMMENT ON COLUMN "public"."product_event"."event_level" IS '告警等级'; +COMMENT ON COLUMN "public"."product_event"."remark" IS '备注'; COMMENT ON COLUMN "public"."product_event"."exp_logic" IS 'and 或者 or'; COMMENT ON COLUMN "public"."product_event"."event_notify" IS '0 否 1 是'; +COMMENT ON COLUMN "public"."product_event"."classify" IS '0 告警 1场景联动'; -- ---------------------------- -- Records of product_event @@ -678,8 +518,8 @@ CREATE TABLE "public"."product_event_expression" ( "scope" varchar(10) COLLATE "pg_catalog"."default", "condition" varchar(10) COLLATE "pg_catalog"."default", "value" varchar(255) COLLATE "pg_catalog"."default", - "device_id" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, "product_attr_key" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "device_id" varchar(255) COLLATE "pg_catalog"."default", "unit" varchar(16) COLLATE "pg_catalog"."default", "product_attr_id" int8, "product_attr_type" varchar(4) COLLATE "pg_catalog"."default", @@ -688,8 +528,8 @@ CREATE TABLE "public"."product_event_expression" ( ; COMMENT ON COLUMN "public"."product_event_expression"."event_exp_id" IS '告警函数ID'; COMMENT ON COLUMN "public"."product_event_expression"."event_rule_id" IS '告警规则ID'; -COMMENT ON COLUMN "public"."product_event_expression"."device_id" IS '设备ID'; COMMENT ON COLUMN "public"."product_event_expression"."product_attr_key" IS 'item key'; +COMMENT ON COLUMN "public"."product_event_expression"."device_id" IS '设备ID'; COMMENT ON COLUMN "public"."product_event_expression"."product_attr_id" IS '属性ID'; COMMENT ON COLUMN "public"."product_event_expression"."product_attr_type" IS '属性类型 属性 事件'; COMMENT ON COLUMN "public"."product_event_expression"."period" IS '取值周期 时间 周期'; @@ -706,7 +546,7 @@ CREATE TABLE "public"."product_event_relation" ( "id" int8 NOT NULL DEFAULT nextval('product_event_relation_id_seq'::regclass), "event_rule_id" int8 NOT NULL, "relation_id" varchar(64) COLLATE "pg_catalog"."default", - "zbx_id" int4, + "zbx_id" varchar(32) COLLATE "pg_catalog"."default", "inherit" varchar(4) COLLATE "pg_catalog"."default" DEFAULT '0'::character varying, "status" varchar(8) COLLATE "pg_catalog"."default", "remark" varchar(255) COLLATE "pg_catalog"."default" @@ -761,36 +601,6 @@ COMMENT ON COLUMN "public"."product_event_tags"."tag_zbx_id" IS 'zabbix tag id'; -- Records of product_event_tags -- ---------------------------- --- ---------------------------- --- Table structure for product_group --- ---------------------------- -DROP TABLE IF EXISTS "public"."product_group"; -CREATE TABLE "public"."product_group" ( - "product_group_id" int8 NOT NULL, - "pid" int8, - "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, - "remark" varchar(255) COLLATE "pg_catalog"."default", - "key" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, - "create_time" timestamp(6), - "create_user" int8, - "update_time" timestamp(6), - "update_user" int8 -) -; -COMMENT ON COLUMN "public"."product_group"."product_group_id" IS '产品分组ID'; -COMMENT ON COLUMN "public"."product_group"."pid" IS '父ID'; -COMMENT ON COLUMN "public"."product_group"."name" IS '分组名称'; -COMMENT ON COLUMN "public"."product_group"."remark" IS '备注'; -COMMENT ON COLUMN "public"."product_group"."key" IS '分组标识'; -COMMENT ON COLUMN "public"."product_group"."create_time" IS '创建时间'; -COMMENT ON COLUMN "public"."product_group"."create_user" IS '创建人'; -COMMENT ON COLUMN "public"."product_group"."update_time" IS '更新时间'; -COMMENT ON COLUMN "public"."product_group"."update_user" IS '更新人'; - --- ---------------------------- --- Records of product_group --- ---------------------------- - -- ---------------------------- -- Table structure for product_service -- ---------------------------- @@ -820,12 +630,14 @@ CREATE TABLE "public"."product_service_param" ( "id" int8 NOT NULL DEFAULT nextval('service_param_id_seq'::regclass), "service_id" int8, "key" varchar(32) COLLATE "pg_catalog"."default", - "name" varchar(32) COLLATE "pg_catalog"."default" + "name" varchar(32) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default" ) ; COMMENT ON COLUMN "public"."product_service_param"."service_id" IS '服务ID'; COMMENT ON COLUMN "public"."product_service_param"."key" IS '参数标识'; COMMENT ON COLUMN "public"."product_service_param"."name" IS '参数名称'; +COMMENT ON COLUMN "public"."product_service_param"."remark" IS '备注'; -- ---------------------------- -- Records of product_service_param @@ -853,15 +665,15 @@ COMMENT ON COLUMN "public"."product_service_relation"."inherit" IS '是否继承 -- ---------------------------- DROP TABLE IF EXISTS "public"."product_status_function"; CREATE TABLE "public"."product_status_function" ( - "rule_id" int8 NOT NULL, "zbx_id" varchar(32) COLLATE "pg_catalog"."default", "rule_function" varchar(10) COLLATE "pg_catalog"."default", - "rule_condition" varchar(255) COLLATE "pg_catalog"."default", "rule_status" int2 DEFAULT 1, "create_user" int8, "update_user" int8, "create_time" timestamp(6), "update_time" timestamp(6), + "rule_id" int8 NOT NULL, + "rule_condition" varchar(255) COLLATE "pg_catalog"."default", "rule_function_recovery" varchar(10) COLLATE "pg_catalog"."default", "rule_condition_recovery" varchar(255) COLLATE "pg_catalog"."default", "attr_id" int8, @@ -870,11 +682,11 @@ CREATE TABLE "public"."product_status_function" ( "unit_recovery" varchar(8) COLLATE "pg_catalog"."default" ) ; -COMMENT ON COLUMN "public"."product_status_function"."rule_id" IS '触发器ID,离线 上线'; COMMENT ON COLUMN "public"."product_status_function"."zbx_id" IS 'zabbix trigger id'; COMMENT ON COLUMN "public"."product_status_function"."rule_function" IS '''nodata'' or ''last'''; -COMMENT ON COLUMN "public"."product_status_function"."rule_condition" IS '''5m'' or ''4'''; COMMENT ON COLUMN "public"."product_status_function"."rule_status" IS '0 or 1'; +COMMENT ON COLUMN "public"."product_status_function"."rule_id" IS '触发器ID,离线 上线'; +COMMENT ON COLUMN "public"."product_status_function"."rule_condition" IS '''5m'' or ''4'''; COMMENT ON COLUMN "public"."product_status_function"."rule_function_recovery" IS '''nodata'' or ''last'''; COMMENT ON COLUMN "public"."product_status_function"."rule_condition_recovery" IS '''5m'' or ''4'''; COMMENT ON COLUMN "public"."product_status_function"."attr_id" IS 'trigger attrId'; @@ -920,7 +732,7 @@ COMMENT ON COLUMN "public"."product_type"."pids" IS '所有父ID'; -- ---------------------------- -- Records of product_type -- ---------------------------- -INSERT INTO "public"."product_type" VALUES (214, 0, '温控产品', NULL, '[0],'); +INSERT INTO "public"."product_type" VALUES (1, 0, '默认产品分组', NULL, '[0],'); -- ---------------------------- -- Table structure for service_execute_record @@ -977,12 +789,6 @@ COMMENT ON COLUMN "public"."sys_config"."status" IS '是否可修改 ENABLE可 -- ---------------------------- -- Records of sys_config -- ---------------------------- -INSERT INTO "public"."sys_config" VALUES (1145915627211370496, '全局主机组Id', 'ZEUS_HOST_GROUP_ID', 'Y', NULL, '19', '全局主机和模板组ID', NULL, NULL, NULL, NULL, 'DISABLE'); -INSERT INTO "public"."sys_config" VALUES (1143468867767607298, '用户角色ID', 'ZEUS_ADMIN_ROLE_ID', 'N', NULL, '2', '用户角色ID', 1, 1, NULL, NULL, 'DISABLE'); -INSERT INTO "public"."sys_config" VALUES (1145915627211370497, '离线回调ActionId', 'ZEUS_OFFLINE_ACTION_ID', 'Y', NULL, '20', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); -INSERT INTO "public"."sys_config" VALUES (1145915627211370503, '告警回调ActionId', 'ZEUS_ALARM_ACTION_ID', 'Y', NULL, '21', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); -INSERT INTO "public"."sys_config" VALUES (1145915627211370504, '动作回调ActionId', 'ZEUS_EXEC_ACTION_ID', 'Y', NULL, '22', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); -INSERT INTO "public"."sys_config" VALUES (1145915627211370505, '事件回调ActionId', 'ZEUS_EVENT_ACTION_ID', 'Y', NULL, '23', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); INSERT INTO "public"."sys_config" VALUES (1145915627211370502, '获取token的header标识', 'ZEUS_TOKEN_HEADER_NAME', 'N', NULL, 'Authorization', '获取token的header标识', 1, 1, '2019-10-16 23:02:39', '2021-08-03 16:38:12.432', 'DISABLE'); INSERT INTO "public"."sys_config" VALUES (1143468689664876546, '管理系统名称', 'ZEUS_SYSTEM_NAME', 'N', NULL, 'ZEUS-IOT', '管理系统名称', 1, 1, '2019-06-25 18:39:15', '2021-08-09 17:17:30.189', 'ENABLE'); INSERT INTO "public"."sys_config" VALUES (1145915627211370501, '获取系统地密钥过期时间', 'ZEUS_JWT_SECRET_EXPIRE', 'N', NULL, '86400', '获取系统地密钥过期时间(单位:秒),默认1天', 1, 1, '2019-10-16 23:02:39', '2021-08-03 16:38:12.432', 'ENABLE'); @@ -991,6 +797,14 @@ INSERT INTO "public"."sys_config" VALUES (1145915627211370499, '文件上传路 INSERT INTO "public"."sys_config" VALUES (1143324237579165697, '验证码开关', 'ZEUS_KAPTCHA_OPEN', 'Y', 1106120265689055233, 'DISABLE', '是否开启验证码', 1, 1, '2019-06-24 12:46:43', '2021-08-03 16:38:12.432', 'ENABLE'); INSERT INTO "public"."sys_config" VALUES (1145915627211370498, 'Zeus发布的编号', 'ZEUS_SYSTEM_RELEASE_VERSION', 'N', NULL, '10', '用于防止浏览器缓存相关的js和css', 1, 1, '2019-07-02 12:42:30', '2021-08-03 16:38:12.432', 'ENABLE'); INSERT INTO "public"."sys_config" VALUES (1143468867767607297, '默认系统密码', 'ZEUS_DEFAULT_PASSWORD', 'N', NULL, '111111', '默认系统密码', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370503, '告警回调ActionId', 'ZEUS_ALARM_ACTION_ID', 'Y', NULL, '8', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370504, '动作回调ActionId', 'ZEUS_EXEC_ACTION_ID', 'Y', NULL, '9', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370505, '事件回调ActionId', 'ZEUS_EVENT_ACTION_ID', 'Y', NULL, '10', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468867767607208, '单点登录开关', 'ZEUS_SIGN_IN', 'N', NULL, 'DISABLE', '是否启用单点登录', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468867767607207, '默认租户角色ID', 'ZEUS_TENANT_ROLE_ID', 'N', NULL, '1', '默认租户角色ID', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370496, '全局主机组Id', 'ZEUS_HOST_GROUP_ID', 'Y', NULL, '19', '全局主机和模板组ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468867767607298, '用户角色ID', 'ZEUS_ADMIN_ROLE_ID', 'N', NULL, '3', '用户角色ID', 1, 1, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370497, '离线回调ActionId', 'ZEUS_OFFLINE_ACTION_ID', 'Y', NULL, '7', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); -- ---------------------------- -- Table structure for sys_dict @@ -1061,29 +875,16 @@ INSERT INTO "public"."sys_dict" VALUES (1423897784372199424, 1423840415470653440 INSERT INTO "public"."sys_dict" VALUES (1423897784372199425, 1160532886713155587, 'wechat', '企业微信', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199426, 1160532886713155587, 'dingtalk', '钉钉', 'ENABLE', 2, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199427, 1160532886713155587, 'feishu', '飞书', 'ENABLE', 3, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199430, 1160532886713155588, '18', '根据单个属性预处理', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199428, 1160532886713155588, '2', '主动上报', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199435, 1160532886713155589, '%', '百分比', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199436, 1160532886713155589, 'count', '次', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199437, 1160532886713155589, 'r/min', '转每分钟', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199431, 1160532886713155590, '3', '整数', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199432, 1160532886713155590, '0', '小数', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199433, 1160532886713155590, '1', '字符', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199434, 1160532886713155590, '4', '文本', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199438, 1160532886713155589, 'nm', '纳米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199439, 1160532886713155589, 'μm', '微米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199440, 1160532886713155589, 'mm', '毫米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199441, 1160532886713155589, 'cm', '厘米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199442, 1160532886713155589, 'm', '米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199443, 1160532886713155589, 'km', '千米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199444, 1160532886713155589, 'mm²', '平方毫米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199445, 1160532886713155589, 'cm²', '平方厘米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199446, 1160532886713155589, 'm²', '平方米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199447, 1160532886713155589, 'km²', '平方千米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199448, 1160532886713155589, 'hm²', '公顷', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199449, 1160532886713155589, 'd', '天', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199450, 1160532886713155589, 'h', '小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199451, 1160532886713155589, 'min', '分钟', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199470, 1160532886713155589, 'mg', '毫克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199471, 1160532886713155589, 'g', '克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199472, 1160532886713155589, 'kg', '千克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199473, 1160532886713155589, 't', '吨', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199474, 1160532886713155589, 'Pa', '帕斯卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '压力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199475, 1160532886713155589, 'kPa', '千帕斯卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '压力单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199452, 1160532886713155589, 's', '秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199453, 1160532886713155589, 'ms', '毫秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199454, 1160532886713155589, 'μs', '微秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); @@ -1101,31 +902,41 @@ INSERT INTO "public"."sys_dict" VALUES (1423897784372199465, 1160532886713155589 INSERT INTO "public"."sys_dict" VALUES (1423897784372199466, 1160532886713155589, 'cm³/h', '立方厘米每小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199467, 1160532886713155589, 'l/h', '升每小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199468, 1160532886713155589, 'mL', '毫升', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '容积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199469, 1160532886713155589, 'L', '升', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '容积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199470, 1160532886713155589, 'mg', '毫克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199471, 1160532886713155589, 'g', '克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); -INSERT INTO "public"."sys_dict" VALUES (1437341935102316544, 1437341934464782336, 'SSGrdr26', '三石TestKKRl7u', 'DISABLE', 99, NULL, '2021-09-13 17:06:36.507', '2021-09-13 17:06:36.641', 1, 1, NULL); -INSERT INTO "public"."sys_dict" VALUES (1428599180229115912, 1428599180229115904, '1', '是', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1428599180229115911, 1428599180229115904, '0', '', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199478, 1160532886713155589, 'K', '开尔文', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199479, 1160532886713155589, '℃', '摄氏度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199435, 1160532886713155589, '%', '百分比', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199437, 1160532886713155589, 'r/min', '转每分钟', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199438, 1160532886713155589, 'nm', '纳米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199439, 1160532886713155589, 'μm', '微米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199440, 1160532886713155589, 'mm', '毫米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199441, 1160532886713155589, 'cm', '厘米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199442, 1160532886713155589, 'm', '米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199443, 1160532886713155589, 'km', '千米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199444, 1160532886713155589, 'mm²', '平方毫米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199445, 1160532886713155589, 'cm²', '平方厘米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199446, 1160532886713155589, 'm²', '平方米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199447, 1160532886713155589, 'km²', '平方千米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199448, 1160532886713155589, 'hm²', '公顷', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199449, 1160532886713155589, 'd', '天', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199450, 1160532886713155589, 'h', '小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199451, 1160532886713155589, 'min', '分钟', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199428, 1160532886713155588, '2', '主动上报', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199430, 1160532886713155588, '18', '根据单个属性预处理', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199436, 1160532886713155589, 'count', '次', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199506, 1160532886713155591, '25', 'Replace', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199507, 1160532886713155591, '4', 'Trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199508, 1160532886713155591, '2', 'Right trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199509, 1160532886713155591, '3', 'Left trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199510, 1160532886713155591, '11', 'XML XPath', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '结构化数据'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199511, 1160532886713155591, '12', 'JSONPath', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '结构化数据'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199480, 1160532886713155589, '℉', '华氏度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199481, 1160532886713155589, 'J', '焦耳', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能量单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199514, 1160532886713155591, '1', '自定义倍数', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '自定义计算'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199482, 1160532886713155589, 'cal', '卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能量单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199483, 1160532886713155589, 'W', '瓦特', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '功率单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199517, 1160532886713155591, '7', '八进制转十进制', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '数制转换'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199518, 1160532886713155591, '8', '十六进制转十进制', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '数制转换'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199519, 1160532886713155591, '21', 'JavaScript', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '自定义脚本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199500, 1160532886713155589, 'Ω', '欧姆', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199501, 1160532886713155589, 'KΩ', '千欧', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199502, 1160532886713155589, 'MΩ', '兆欧', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199503, 1160532886713155589, 'eV', '电子伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199504, 1160532886713155589, 'kW·h', '千瓦·时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199484, 1160532886713155589, 'kW', '千瓦特', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '功率单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199485, 1160532886713155589, 'rad', '弧度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199505, 1160532886713155589, 'kgce', 'Kg标准煤', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能源单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199486, 1160532886713155589, '°', '度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199487, 1160532886713155589, '′', '[角]分', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199488, 1160532886713155589, '″', '[角]秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); @@ -1140,26 +951,29 @@ INSERT INTO "public"."sys_dict" VALUES (1423897784372199496, 1160532886713155589 INSERT INTO "public"."sys_dict" VALUES (1423897784372199497, 1160532886713155589, 'mV', '毫伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199498, 1160532886713155589, 'μV', '微伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199499, 1160532886713155589, 'A', '安培', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199505, 1160532886713155589, 'kgce', 'Kg标准煤', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能源单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199500, 1160532886713155589, 'Ω', '欧姆', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199501, 1160532886713155589, 'KΩ', '千欧', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199502, 1160532886713155589, 'MΩ', '兆欧', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199503, 1160532886713155589, 'eV', '电子伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199512, 1160532886713155591, '13', 'In range', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '验证'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199579, 1428599180229115905, '1', '信息', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199574, 1428599180229115905, '2', '低级', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199577, 1428599180229115905, '3', '中级', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199576, 1428599180229115905, '4', '高级', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199575, 1428599180229115905, '5', '紧急', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199578, 1428599180229115905, '0', '未定义', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1429987619034984449, 1142859918022911591, '1', '异步', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1429987619034984450, 1142859918022911591, '0', '同步', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199472, 1160532886713155589, 'kg', '千克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199473, 1160532886713155589, 't', '吨', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199474, 1160532886713155589, 'Pa', '帕斯卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '压力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199475, 1160532886713155589, 'kPa', '千帕斯卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '压力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199469, 1160532886713155589, 'L', '升', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '容积单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199476, 1160532886713155589, 'N', '牛顿', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '力单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199477, 1160532886713155589, 'N.m', '牛·米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199478, 1160532886713155589, 'K', '开尔文', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199479, 1160532886713155589, '℃', '摄氏度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199480, 1160532886713155589, '℉', '华氏度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199481, 1160532886713155589, 'J', '焦耳', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199482, 1160532886713155589, 'cal', '卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199483, 1160532886713155589, 'W', '瓦特', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '功率单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199484, 1160532886713155589, 'kW', '千瓦特', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '功率单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199485, 1160532886713155589, 'rad', '弧度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); +INSERT INTO "public"."sys_dict" VALUES (1428599180229115911, 1428599180229115904, '0', '', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1428599180229115912, 1428599180229115904, '1', '是', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1429987619034984449, 1142859918022911591, '1', '异步', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1429987619034984450, 1142859918022911591, '0', '同步', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199512, 1160532886713155591, '13', 'In range', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '验证'); +INSERT INTO "public"."sys_dict" VALUES (1440492197892923392, 1440492197679013888, 'SSm5lxzi', '三石Test3OrlDb', 'DISABLE', 99, NULL, '2021-09-22 09:44:37.685', '2021-09-22 09:44:37.755', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199531, 1160532886713155588, '0', 'Agent 采集', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199528, 1440492220332449792, '1', '信息', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199529, 1440492220332449792, '2', '低级', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199527, 1440492220332449792, '3', '中级', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199526, 1440492220332449792, '4', '高级', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199525, 1440492220332449792, '5', '紧急', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -- ---------------------------- -- Table structure for sys_dict_type @@ -1210,10 +1024,9 @@ INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155588, 'ATTR_TYPE', ' INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155589, 'UNITS', '产品属性单位', '产品属性单位', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155590, 'DATA_TYPE', '产品属性值类型', '产品属性值类型', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155591, 'DATA_PRE_TYPE', '数据预处理方法名称', '数据预处理方法名称', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1440492220332449792, 'EVENT_LEVEL', '告警级别', '告警级别', 'N', 'ENABLE', NULL, '2021-09-22 09:44:43.035', 1, '2021-09-22 09:44:43.102', 1); INSERT INTO "public"."sys_dict_type" VALUES (1142859918022911591, 'EXECUTE_TYPE', '服务执行方式', '服务执行方式', 'N', 'ENABLE', 1, NULL, NULL, '2021-09-10 15:56:14.127', 1); -INSERT INTO "public"."sys_dict_type" VALUES (1437348629152780288, 'SShe06pqU', '三石TestcKA3qIU', '描述Test@123', 'N', 'ENABLE', NULL, '2021-09-13 17:33:12.493', 1, '2021-09-13 17:33:12.554', 1); INSERT INTO "public"."sys_dict_type" VALUES (1428599180229115904, 'WHETHER', '是否', '是否', 'N', 'ENABLE', NULL, '2021-08-20 14:06:01.311', 1, '2021-08-20 14:06:01.311', 1); -INSERT INTO "public"."sys_dict_type" VALUES (1428599180229115905, 'EVENT_LEVEL', '告警级别', '告警级别', 'N', 'ENABLE', NULL, NULL, NULL, NULL, NULL); -- ---------------------------- -- Table structure for sys_login_log @@ -1233,10 +1046,6 @@ CREATE TABLE "public"."sys_login_log" ( -- ---------------------------- -- Records of sys_login_log -- ---------------------------- -INSERT INTO "public"."sys_login_log" VALUES ('登录日志', 1, '成功', NULL, '172.16.3.33', '2021-09-23 11:35:36.879', 1440882516655042560); -INSERT INTO "public"."sys_login_log" VALUES ('登录日志', 1, '成功', NULL, '172.16.3.25', '2021-09-23 11:36:56.394', 1440882849955409920); -INSERT INTO "public"."sys_login_log" VALUES ('退出日志', 1, '成功', NULL, '172.16.3.25', '2021-09-23 11:42:26.181', 1440884233178148864); -INSERT INTO "public"."sys_login_log" VALUES ('登录日志', 117, '成功', NULL, '172.16.3.25', '2021-09-23 11:42:32.517', 1440884259753259008); -- ---------------------------- -- Table structure for sys_menu @@ -1258,7 +1067,8 @@ CREATE TABLE "public"."sys_menu" ( "create_time" timestamp(6), "update_time" timestamp(6), "create_user" int8, - "update_user" int8 + "update_user" int8, + "admin_flag" varchar(32) COLLATE "pg_catalog"."default" ) ; COMMENT ON COLUMN "public"."sys_menu"."menu_id" IS '菜单ID'; @@ -1277,76 +1087,79 @@ COMMENT ON COLUMN "public"."sys_menu"."create_time" IS '创建时间'; COMMENT ON COLUMN "public"."sys_menu"."update_time" IS '修改时间'; COMMENT ON COLUMN "public"."sys_menu"."create_user" IS '创建人'; COMMENT ON COLUMN "public"."sys_menu"."update_user" IS '修改人'; +COMMENT ON COLUMN "public"."sys_menu"."admin_flag" IS '是否是超级管理员菜单'; -- ---------------------------- -- Records of sys_menu -- ---------------------------- -INSERT INTO "public"."sys_menu" VALUES (107, 'mgr_add', 'mgr', '[0],[system],[mgr],', '添加用户', NULL, '/mgr/add', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (108, 'mgr_edit', 'mgr', '[0],[system],[mgr],', '修改用户', NULL, '/mgr/edit', 2, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (109, 'mgr_delete', 'mgr', '[0],[system],[mgr],', '删除用户', NULL, '/mgr/delete', 3, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (110, 'mgr_reset', 'mgr', '[0],[system],[mgr],', '重置密码', NULL, '/mgr/reset', 4, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (113, 'mgr_setRole', 'mgr', '[0],[system],[mgr],', '分配角色', NULL, '/mgr/setRole', 7, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (115, 'role_add', 'role', '[0],[system],[role],', '添加角色', NULL, '/role/add', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (116, 'role_edit', 'role', '[0],[system],[role],', '修改角色', NULL, '/role/edit', 2, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (117, 'role_remove', 'role', '[0],[system],[role],', '删除角色', NULL, '/role/remove', 3, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (130, 'druid', 'system', '[0],[system],', '监控管理', '', '/druid', 80, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:50:06', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (134, 'log_clean', 'log', '[0],[system],[log],', '清空日志', NULL, '/log/delLog', 3, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:39', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (138, 'dict_add', 'dict', '[0],[system],[dict],', '添加字典', NULL, '/dictType/addItem', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (139, 'dict_update', 'dict', '[0],[system],[dict],', '修改字典', NULL, '/dictType/editItem', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (140, 'dict_delete', 'dict', '[0],[system],[dict],', '删除字典', NULL, '/dictType/delete', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (128, 'businessLog', 'log', '[0],[log],', '业务日志', '', '/log/businessLog', 70, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:39', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (181, 'product_type', 'product_mgr', '[0],[product_mgr],', '产品分类', NULL, '/productMgr/productType', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (151, 'menu_list', 'menu', '[0],[system],[menu],', '菜单列表', '', '/menu/list', 5, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:25', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (156, 'dict_list', 'dict', '[0],[system],[dict],', '字典列表', '', '/dict/list', 5, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (157, 'dict_detail', 'dict', '[0],[system],[dict],', '字典详情', '', '/dict/detail', 6, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (158, 'log_list', 'log', '[0],[system],[log],', '日志列表', '', '/log/list', 2, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:39', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (159, 'log_detail', 'log', '[0],[system],[log],', '日志详情', '', '/log/detail', 3, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:39', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (160, 'del_login_log', 'loginLog', '[0],[system],[loginLog],', '清空登录日志', '', '/loginLog/delLoginLog', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:29', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (161, 'login_log_list', 'loginLog', '[0],[system],[loginLog],', '登录日志列表', '', '/loginLog/list', 2, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:29', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (133, 'loginLog', 'log', '[0],[log],', '登录日志', '', '/log/loginLog', 60, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:49:29', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (164, 'role_list', 'role', '[0],[system],[role],', '角色列表', '', '/role/list', 7, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (165, 'to_assign_role', 'mgr', '[0],[system],[mgr],', '分配角色跳转', '', '/mgr/role_assign', 8, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (166, 'to_user_edit', 'mgr', '[0],[system],[mgr],', '编辑用户跳转', '', '/mgr/user_edit', 9, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (167, 'mgr_list', 'mgr', '[0],[system],[mgr],', '用户列表', '', '/mgr/list', 10, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (114, 'role', 'system', '[0],[system],', '角色管理', '', '/system/role', 20, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (106, 'mgr', 'system', '[0],[system],', '用户管理', '', '/system/user', 10, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (111, 'mgr_freeze', 'mgr', '[0],[system],[mgr],', '冻结用户', NULL, '/mgr/freeze', 5, 3, 'N', NULL, 'DISABLE', NULL, '2019-06-30 13:48:07', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (112, 'mgr_unfreeze', 'mgr', '[0],[system],[mgr],', '解除冻结用户', NULL, '/mgr/unfreeze', 6, 3, 'N', NULL, 'DISABLE', NULL, '2019-06-30 13:48:07', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (118, 'role_setAuthority', 'role', '[0],[system],[role],', '配置菜单', NULL, '/role/setAuthority', 4, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (119, 'menu', 'system', '[0],[system],', '菜单管理', '', '/menu', 50, 2, 'Y', NULL, 'DISABLE', NULL, '2019-06-30 13:48:25', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (120, 'menu_add', 'menu', '[0],[system],[menu],', '添加菜单', NULL, '/menu/add', 1, 3, 'N', NULL, 'DISABLE', NULL, '2019-06-30 13:48:25', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (121, 'menu_edit', 'menu', '[0],[system],[menu],', '修改菜单', NULL, '/menu/edit', 2, 3, 'N', NULL, 'DISABLE', NULL, '2019-06-30 13:48:25', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (122, 'menu_remove', 'menu', '[0],[system],[menu],', '删除菜单', NULL, '/menu/remove', 3, 3, 'N', NULL, 'DISABLE', NULL, '2019-06-30 13:48:25', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (177, 'dev', 'dev_mgr', '[0],[dev_mgr],', '设备', NULL, '/deviceMgr/device', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (178, 'dev_group', 'dev_mgr', '[0],[dev_mgr],', '设备组', NULL, '/deviceMgr/deviceGroup', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (171, 'product_mgr', '0', '[0],', '产品管理', NULL, '/productMgr', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (132, 'dict', 'system', '[0],[system],', '字典管理', '', '/system/dictType', 40, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (186, 'sysParam', 'system', '[0],[system],', '系统参数', '', '/system/sysParam', 10, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (180, 'product', 'product_mgr', '[0],[product_mgr],', '产品', NULL, '/productMgr/product', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (168, 'usrGrp', 'system', '[0],[system],', '用户组管理', NULL, '/system/userGroup', 9, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (184, 'log', '0', '[0]', '日志管理', NULL, '/log', 4, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (105, 'system', '0', '[0],', '系统管理', 'layui-icon layui-icon-set', '/system', 20, 1, 'Y', NULL, 'ENABLE', NULL, '2019-03-29 16:32:27', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (170, 'dev_mgr', '0', '[0],', '设备管理', NULL, '/deviceMgr', 2, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (185, 'product_detail', 'product', '[0],[product_mgr],[product],', '产品详情', NULL, '/productMgr/product/detail', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (187, 'media', 'system', '[0],[system],', '通知配置', '', '/system/media', 80, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:50:06', NULL, 1); -INSERT INTO "public"."sys_menu" VALUES (189, 'home', 'analyse', '[0],[analyse],', '全局概览', NULL, '/analyse/home', 1, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (188, 'detail', 'dev', '[0],[dev_mgr],[dev],', '设备详情', '', '/deviceMgr/device/detail', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (179, 'alarmList', 'alarm', '[0],[alarm],', '告警记录', NULL, '/alarm/alarmList', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (190, 'latest', 'analyse', '[0],[analyse],', '最新数据', NULL, '/analyse/latest', 2, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (169, 'analyse', '0', '[0],', '统计分析', NULL, '/analyse', 1, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (191, 'alarmAnalyse', 'alarm', '[0],[alarm],', '告警分析', NULL, '/alarm/analyse', 3, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (174, 'auth', '0', '[0],', '平台授权', NULL, '/auth', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (173, 'view', '0', '[0],', '可视化', NULL, '/view', 3, 1, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (176, 'dev_log', 'analyse', '[0],[analyse],', '设备日志', NULL, '/analyse/devLog', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (183, 'grafana', 'view', '[0],[view],', 'Grafana配置', NULL, '/view/grafana', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (192, 'alarm', '0', '[0],', '告警管理', NULL, '/alarm', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (194, 'rule', '0', '[0],', '规则引擎', NULL, '/rule', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (196, 'api', 'dev_mgr', '[0],[dev_mgr],', '设备调试', NULL, '/deviceMgr/api', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (197, 'about', '0', '[0],', '关于我们', NULL, '/about', 2, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (195, 'nodeRed', 'rule', '[0],[rule],', 'Node-Red', NULL, '/rule/nodeRed', 3, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (193, 'scene ', 'rule', '[0],[rule],', '场景联动', NULL, '/rule/scene ', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (198, 'monitor', 'analyse', '[0],[analyse],', '平台监控', NULL, '/analyse/monitor', 4, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_menu" VALUES (199, 'weakMonitor', 'analyse', '[0],[analyse],', '弱电间监控', NULL, '/analyse/weakMonitor', 5, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_menu" VALUES (113, 'mgr_setRole', 'mgr', '[0],[system],[mgr],', '分配角色', NULL, '/mgr/setRole', 7, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (139, 'dict_update', 'dict', '[0],[system],[dict],', '修改字典', NULL, '/dictType/editItem', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (140, 'dict_delete', 'dict', '[0],[system],[dict],', '删除字典', NULL, '/dictType/delete', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (151, 'menu_list', 'menu', '[0],[system],[menu],', '菜单列表', '', '/menu/list', 5, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:25', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (115, 'role_add', 'role', '[0],[system],[role],', '添加角色', NULL, '/role/add', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (116, 'role_edit', 'role', '[0],[system],[role],', '修改角色', NULL, '/role/edit', 2, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (107, 'mgr_add', 'mgr', '[0],[system],[mgr],', '添加用户', NULL, '/mgr/add', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (108, 'mgr_edit', 'mgr', '[0],[system],[mgr],', '修改用户', NULL, '/mgr/edit', 2, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (109, 'mgr_delete', 'mgr', '[0],[system],[mgr],', '删除用户', NULL, '/mgr/delete', 3, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (117, 'role_remove', 'role', '[0],[system],[role],', '删除角色', NULL, '/role/remove', 3, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (156, 'dict_list', 'dict', '[0],[system],[dict],', '字典列表', '', '/dict/list', 5, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (164, 'role_list', 'role', '[0],[system],[role],', '角色列表', '', '/role/list', 7, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (114, 'role', 'system', '[0],[system],', '角色管理', '', '/system/role', 20, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (128, 'businessLog', 'log', '[0],[log],', '业务日志', '', '/log/businessLog', 70, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:39', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (181, 'product_type', 'product_mgr', '[0],[product_mgr],', '产品分类', NULL, '/productMgr/productType', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (119, 'menu', 'system', '[0],[system],', '菜单管理', '', '/menu', 50, 2, 'Y', NULL, 'DISABLE', NULL, '2019-06-30 13:48:25', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (132, 'dict', 'system', '[0],[system],', '字典管理', '', '/system/dictType', 40, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (158, 'log_list', 'log', '[0],[system],[log],', '日志列表', '', '/log/list', 2, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:39', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (133, 'loginLog', 'log', '[0],[log],', '登录日志', '', '/log/loginLog', 60, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:49:29', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (186, 'sysParam', 'system', '[0],[system],', '系统参数', '', '/system/sysParam', 10, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (167, 'mgr_list', 'mgr', '[0],[system],[mgr],', '用户列表', '', '/mgr/list', 10, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (174, 'auth', '0', '[0],', '平台授权', NULL, '/auth', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (196, 'api', 'dev_mgr', '[0],[dev_mgr],', '设备调试', NULL, '/deviceMgr/debug', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (110, 'reset', 'mgr', '[0],[system],[mgr],', '重置密码', NULL, '/mgr/reset', 4, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (177, 'dev', 'dev_mgr', '[0],[dev_mgr],', '设备', NULL, '/deviceMgr/device', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (178, 'dev_group', 'dev_mgr', '[0],[dev_mgr],', '设备组', NULL, '/deviceMgr/deviceGroup', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (171, 'product_mgr', '0', '[0],', '产品管理', NULL, '/productMgr', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (180, 'product', 'product_mgr', '[0],[product_mgr],', '产品', NULL, '/productMgr/product', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (184, 'log', '0', '[0]', '日志管理', NULL, '/log', 4, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (105, 'system', '0', '[0],', '系统管理', 'layui-icon layui-icon-set', '/system', 20, 1, 'Y', NULL, 'ENABLE', NULL, '2019-03-29 16:32:27', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (170, 'dev_mgr', '0', '[0],', '设备管理', NULL, '/deviceMgr', 2, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (187, 'media', 'system', '[0],[system],', '通知配置', '', '/system/media', 80, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:50:06', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (189, 'home', 'analyse', '[0],[analyse],', '全局概览', NULL, '/analyse/home', 1, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (179, 'alarmList', 'alarm', '[0],[alarm],', '告警记录', NULL, '/alarm/alarmList', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (169, 'analyse', '0', '[0],', '统计分析', NULL, '/analyse', 1, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (190, 'latest', 'analyse', '[0],[analyse],', '最新数据', NULL, '/analyse/latest', 1, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (191, 'alarmAnalyse', 'alarm', '[0],[alarm],', '告警分析', NULL, '/alarm/analyse', 3, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (173, 'view', '0', '[0],', '可视化', NULL, '/view', 3, 1, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (176, 'dev_log', 'analyse', '[0],[analyse],', '设备日志', NULL, '/analyse/devLog', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (183, 'grafana', 'view', '[0],[view],', 'Grafana配置', NULL, '/view/grafana', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (192, 'alarm', '0', '[0],', '告警管理', NULL, '/alarm', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (194, 'rule', '0', '[0],', '规则引擎', NULL, '/rule', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (197, 'about', '0', '[0],', '关于我们', NULL, '/about', 2, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (106, 'userMgr', '0', '[0],', '用户管理', '', '/userMgr', 10, 1, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (168, 'usrGrp', 'userMgr', '[0],[userMgr],', '用户组管理', NULL, '/userMgr/userGroup', 9, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (138, 'dict_add', 'dict', '[0],[system],[dict],', '添加字典', NULL, '/dictType/addItem', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (206, 'dev_detail', 'dev', '[0],[dev_mgr],[dev]', '设备详情', NULL, '/deviceMgr/device/detail', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (205, 'dev_list', 'dev', '[0],[dev_mgr],[dev]', '设备列表', NULL, '/deviceMgr/device/list', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (204, 'dev_delete', 'dev', '[0],[dev_mgr],[dev]', '删除设备', NULL, '/deviceMgr/device/delete', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (207, 'product_add', 'product', '[0],[product_mgr],[product]', '增加产品', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (208, 'product_update', 'product', '[0],[product_mgr],[product]', '修改产品', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (209, 'product_delete', 'product', '[0],[product_mgr],[product]', '删除产品', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (210, 'product_list', 'product', '[0],[product_mgr],[product]', '产品列表', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (211, 'product_detail', 'product', '[0],[product_mgr],[product]', '产品详情', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (212, 'tenant', 'system', '[0],[system],', '租户管理', '', '/system/tenant', 10, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (213, 'tenant_add', 'tenant', '[0],[system],', '租户增加', '', '/system/tenant', 10, 3, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (214, 'tenant_update', 'tenant', '[0],[system],', '租户修改', '', '/system/tenant', 10, 3, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (215, 'tenant_list', 'tenant', '[0],[system],', '租户列表', '', '/system/tenant', 10, 3, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (216, 'tenant_delete', 'tenant', '[0],[system],', '租户删除', '', '/system/tenant', 10, 3, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (217, 'mgr', 'userMgr', '[0],[userMgr],', '用户', '', '/userMgr/user', 10, 1, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (195, 'nodeRed', 'rule', '[0],[rule],', 'Node-Red', NULL, '/rule/nodeRed', 3, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (199, 'proxyInfo', 'system', '[0],[proxy],', '代理管理', '', '/proxy/proxyInfo', 20, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (200, 'proxyMonitor', 'system', '[0],[proxy],', '代理监控', '', '/proxy/proxyMonitor', 20, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (198, 'proxy', 'system', '[0],', '边缘采集', '', '/proxy', 20, 1, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (201, 'grafana', 'analyse', '[0],[analyse],', 'Grafana 演示大屏', NULL, '/analyse/grafana', 5, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (203, 'dev_update', 'dev', '[0],[dev_mgr],[dev]', '修改设备', NULL, '/deviceMgr/device/update', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (202, 'dev_add', 'dev', '[0],[dev_mgr],[dev]', '增加设备', NULL, '/deviceMgr/device/add', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (193, 'scene ', 'rule', '[0],[rule],', '场景联动', NULL, '/rule/scene', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -- ---------------------------- -- Table structure for sys_operation_log @@ -1377,474 +1190,6 @@ COMMENT ON COLUMN "public"."sys_operation_log"."message" IS '备注'; -- ---------------------------- -- Records of sys_operation_log -- ---------------------------- -INSERT INTO "public"."sys_operation_log" VALUES (1440880052786688000, '业务日志', '新增产品分类', 1, 'com.zmops.iot.web.product.controller.ProductTypeController', 'create', '2021-09-23 11:25:49.498', '成功', ''); -INSERT INTO "public"."sys_operation_log" VALUES (1440880404000927744, '业务日志', '创建设备组', 1, 'com.zmops.iot.web.device.controller.DeviceGroupController', 'createDeviceGroup', '2021-09-23 11:27:13.234', '成功', ''); -INSERT INTO "public"."sys_operation_log" VALUES (1440883048178216960, '异常日志', '', 1, NULL, NULL, '2021-09-23 11:37:43.655', '失败', 'com.zmops.iot.model.exception.ZbxApiException: User with username "Admin" already exists. - at com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor.onSuccess(JsonBodyBuildInterceptor.java:78) - at com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor.onSuccess(JsonBodyBuildInterceptor.java:28) - at com.dtflys.forest.interceptor.InterceptorChain.onSuccess(InterceptorChain.java:64) - at com.dtflys.forest.reflection.MethodLifeCycleHandler.handleSuccess(MethodLifeCycleHandler.java:111) - at com.dtflys.forest.reflection.MethodLifeCycleHandler.handleSyncWithException(MethodLifeCycleHandler.java:55) - at com.dtflys.forest.reflection.MethodLifeCycleHandler.handleSync(MethodLifeCycleHandler.java:46) - at com.dtflys.forest.backend.AbstractBackendResponseHandler.handleSync(AbstractBackendResponseHandler.java:36) - at com.dtflys.forest.backend.okhttp3.response.OkHttp3ResponseHandler.handleSync(OkHttp3ResponseHandler.java:29) - at com.dtflys.forest.backend.okhttp3.executor.AbstractOkHttp3Executor.execute(AbstractOkHttp3Executor.java:260) - at com.dtflys.forest.backend.okhttp3.executor.AbstractOkHttp3Executor.execute(AbstractOkHttp3Executor.java:288) - at com.dtflys.forest.http.ForestRequest.execute(ForestRequest.java:1731) - at com.dtflys.forest.http.ForestRequest.execute(ForestRequest.java:1748) - at com.dtflys.forest.reflection.ForestMethod.invoke(ForestMethod.java:1230) - at com.dtflys.forest.proxy.InterfaceProxyHandler.invoke(InterfaceProxyHandler.java:150) - at com.sun.proxy.TProxy127.userAdd(Unknown Source) - at com.zmops.iot.web.sys.service.SysUserService.createUser(SysUserService.java:132) - at com.zmops.iot.web.sys.service.SysUserServiceTTFastClassBySpringCGLIBTT5b7cfc4d.invoke() - at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) - at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) - at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367) - at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) - at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) - at org.springframework.aop.framework.CglibAopProxyTDynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) - at com.zmops.iot.web.sys.service.SysUserServiceTTEnhancerBySpringCGLIBTT9bb24deb.createUser() - at com.zmops.iot.web.sys.controller.SysUserController.createUser(SysUserController.java:51) - at com.zmops.iot.web.sys.controller.SysUserControllerTTFastClassBySpringCGLIBTT2e326b39.invoke() - at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) - at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) - at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88) - at com.zmops.iot.web.log.aop.LogAop.recordSysLog(LogAop.java:54) - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.lang.reflect.Method.invoke(Method.java:498) - at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644) - at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633) - at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70) - at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) - at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95) - at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) - at org.springframework.aop.framework.CglibAopProxyTDynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) - at com.zmops.iot.web.sys.controller.SysUserControllerTTEnhancerBySpringCGLIBTT2cad82eb.createUser() - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.lang.reflect.Method.invoke(Method.java:498) - at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) - at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) - at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792) - at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) - at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) - at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) - at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) - at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) - at javax.servlet.http.HttpServlet.service(HttpServlet.java:517) - at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) - at javax.servlet.http.HttpServlet.service(HttpServlet.java:584) - at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:129) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113) - at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:320) - at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126) - at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at com.zmops.iot.core.auth.filter.JwtAuthorizationTokenFilter.doFilterInternal(JwtAuthorizationTokenFilter.java:77) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92) - at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) - at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) - at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) - at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) - at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) - at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) - at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) - at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:97) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) - at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) - at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) - at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) - at io.undertow.servlet.handlers.ServletChainT1.handleRequest(ServletChain.java:68) - at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) - at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68) - at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:111) - at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) - at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) - at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) - at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) - at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) - at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) - at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) - at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) - at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) - at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269) - at io.undertow.servlet.handlers.ServletInitialHandler.accessT100(ServletInitialHandler.java:78) - at io.undertow.servlet.handlers.ServletInitialHandlerT2.call(ServletInitialHandler.java:133) - at io.undertow.servlet.handlers.ServletInitialHandlerT2.call(ServletInitialHandler.java:130) - at io.undertow.servlet.core.ServletRequestContextThreadSetupActionT1.call(ServletRequestContextThreadSetupAction.java:48) - at io.undertow.servlet.core.ContextClassLoaderSetupActionT1.call(ContextClassLoaderSetupAction.java:43) - at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249) - at io.undertow.servlet.handlers.ServletInitialHandler.accessT000(ServletInitialHandler.java:78) - at io.undertow.servlet.handlers.ServletInitialHandlerT1.handleRequest(ServletInitialHandler.java:99) - at io.undertow.server.Connectors.executeRootHandler(Connectors.java:390) - at io.undertow.server.HttpServerExchangeT1.run(HttpServerExchange.java:836) - at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) - at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019) - at org.jboss.threads.EnhancedQueueExecutorTThreadBody.doRunTask(EnhancedQueueExecutor.java:1558) - at org.jboss.threads.EnhancedQueueExecutorTThreadBody.run(EnhancedQueueExecutor.java:1449) - at java.lang.Thread.run(Thread.java:748) -'); -INSERT INTO "public"."sys_operation_log" VALUES (1440883284019736576, '异常日志', '', 1, NULL, NULL, '2021-09-23 11:38:39.884', '失败', 'com.zmops.iot.model.exception.ZbxApiException: User group with ID "107" is not available. - at com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor.onSuccess(JsonBodyBuildInterceptor.java:78) - at com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor.onSuccess(JsonBodyBuildInterceptor.java:28) - at com.dtflys.forest.interceptor.InterceptorChain.onSuccess(InterceptorChain.java:64) - at com.dtflys.forest.reflection.MethodLifeCycleHandler.handleSuccess(MethodLifeCycleHandler.java:111) - at com.dtflys.forest.reflection.MethodLifeCycleHandler.handleSyncWithException(MethodLifeCycleHandler.java:55) - at com.dtflys.forest.reflection.MethodLifeCycleHandler.handleSync(MethodLifeCycleHandler.java:46) - at com.dtflys.forest.backend.AbstractBackendResponseHandler.handleSync(AbstractBackendResponseHandler.java:36) - at com.dtflys.forest.backend.okhttp3.response.OkHttp3ResponseHandler.handleSync(OkHttp3ResponseHandler.java:29) - at com.dtflys.forest.backend.okhttp3.executor.AbstractOkHttp3Executor.execute(AbstractOkHttp3Executor.java:260) - at com.dtflys.forest.backend.okhttp3.executor.AbstractOkHttp3Executor.execute(AbstractOkHttp3Executor.java:288) - at com.dtflys.forest.http.ForestRequest.execute(ForestRequest.java:1731) - at com.dtflys.forest.http.ForestRequest.execute(ForestRequest.java:1748) - at com.dtflys.forest.reflection.ForestMethod.invoke(ForestMethod.java:1230) - at com.dtflys.forest.proxy.InterfaceProxyHandler.invoke(InterfaceProxyHandler.java:150) - at com.sun.proxy.TProxy127.userAdd(Unknown Source) - at com.zmops.iot.web.sys.service.SysUserService.createUser(SysUserService.java:132) - at com.zmops.iot.web.sys.service.SysUserServiceTTFastClassBySpringCGLIBTT5b7cfc4d.invoke() - at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) - at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) - at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367) - at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) - at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) - at org.springframework.aop.framework.CglibAopProxyTDynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) - at com.zmops.iot.web.sys.service.SysUserServiceTTEnhancerBySpringCGLIBTT9bb24deb.createUser() - at com.zmops.iot.web.sys.controller.SysUserController.createUser(SysUserController.java:51) - at com.zmops.iot.web.sys.controller.SysUserControllerTTFastClassBySpringCGLIBTT2e326b39.invoke() - at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) - at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) - at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88) - at com.zmops.iot.web.log.aop.LogAop.recordSysLog(LogAop.java:54) - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.lang.reflect.Method.invoke(Method.java:498) - at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644) - at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633) - at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70) - at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) - at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95) - at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) - at org.springframework.aop.framework.CglibAopProxyTDynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) - at com.zmops.iot.web.sys.controller.SysUserControllerTTEnhancerBySpringCGLIBTT2cad82eb.createUser() - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.lang.reflect.Method.invoke(Method.java:498) - at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) - at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) - at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792) - at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) - at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) - at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) - at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) - at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) - at javax.servlet.http.HttpServlet.service(HttpServlet.java:517) - at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) - at javax.servlet.http.HttpServlet.service(HttpServlet.java:584) - at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:129) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113) - at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:320) - at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126) - at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at com.zmops.iot.core.auth.filter.JwtAuthorizationTokenFilter.doFilterInternal(JwtAuthorizationTokenFilter.java:77) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92) - at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) - at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) - at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) - at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) - at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) - at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) - at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) - at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:97) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) - at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) - at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) - at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) - at io.undertow.servlet.handlers.ServletChainT1.handleRequest(ServletChain.java:68) - at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) - at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68) - at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:111) - at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) - at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) - at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) - at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) - at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) - at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) - at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) - at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) - at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) - at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269) - at io.undertow.servlet.handlers.ServletInitialHandler.accessT100(ServletInitialHandler.java:78) - at io.undertow.servlet.handlers.ServletInitialHandlerT2.call(ServletInitialHandler.java:133) - at io.undertow.servlet.handlers.ServletInitialHandlerT2.call(ServletInitialHandler.java:130) - at io.undertow.servlet.core.ServletRequestContextThreadSetupActionT1.call(ServletRequestContextThreadSetupAction.java:48) - at io.undertow.servlet.core.ContextClassLoaderSetupActionT1.call(ContextClassLoaderSetupAction.java:43) - at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249) - at io.undertow.servlet.handlers.ServletInitialHandler.accessT000(ServletInitialHandler.java:78) - at io.undertow.servlet.handlers.ServletInitialHandlerT1.handleRequest(ServletInitialHandler.java:99) - at io.undertow.server.Connectors.executeRootHandler(Connectors.java:390) - at io.undertow.server.HttpServerExchangeT1.run(HttpServerExchange.java:836) - at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) - at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019) - at org.jboss.threads.EnhancedQueueExecutorTThreadBody.doRunTask(EnhancedQueueExecutor.java:1558) - at org.jboss.threads.EnhancedQueueExecutorTThreadBody.run(EnhancedQueueExecutor.java:1449) - at java.lang.Thread.run(Thread.java:748) -'); -INSERT INTO "public"."sys_operation_log" VALUES (1440883334531739648, '异常日志', '', 1, NULL, NULL, '2021-09-23 11:38:51.926', '失败', 'com.zmops.iot.model.exception.ZbxApiException: User group with ID "107" is not available. - at com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor.onSuccess(JsonBodyBuildInterceptor.java:78) - at com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor.onSuccess(JsonBodyBuildInterceptor.java:28) - at com.dtflys.forest.interceptor.InterceptorChain.onSuccess(InterceptorChain.java:64) - at com.dtflys.forest.reflection.MethodLifeCycleHandler.handleSuccess(MethodLifeCycleHandler.java:111) - at com.dtflys.forest.reflection.MethodLifeCycleHandler.handleSyncWithException(MethodLifeCycleHandler.java:55) - at com.dtflys.forest.reflection.MethodLifeCycleHandler.handleSync(MethodLifeCycleHandler.java:46) - at com.dtflys.forest.backend.AbstractBackendResponseHandler.handleSync(AbstractBackendResponseHandler.java:36) - at com.dtflys.forest.backend.okhttp3.response.OkHttp3ResponseHandler.handleSync(OkHttp3ResponseHandler.java:29) - at com.dtflys.forest.backend.okhttp3.executor.AbstractOkHttp3Executor.execute(AbstractOkHttp3Executor.java:260) - at com.dtflys.forest.backend.okhttp3.executor.AbstractOkHttp3Executor.execute(AbstractOkHttp3Executor.java:288) - at com.dtflys.forest.http.ForestRequest.execute(ForestRequest.java:1731) - at com.dtflys.forest.http.ForestRequest.execute(ForestRequest.java:1748) - at com.dtflys.forest.reflection.ForestMethod.invoke(ForestMethod.java:1230) - at com.dtflys.forest.proxy.InterfaceProxyHandler.invoke(InterfaceProxyHandler.java:150) - at com.sun.proxy.TProxy127.userAdd(Unknown Source) - at com.zmops.iot.web.sys.service.SysUserService.createUser(SysUserService.java:132) - at com.zmops.iot.web.sys.service.SysUserServiceTTFastClassBySpringCGLIBTT5b7cfc4d.invoke() - at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) - at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) - at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367) - at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) - at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) - at org.springframework.aop.framework.CglibAopProxyTDynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) - at com.zmops.iot.web.sys.service.SysUserServiceTTEnhancerBySpringCGLIBTT9bb24deb.createUser() - at com.zmops.iot.web.sys.controller.SysUserController.createUser(SysUserController.java:51) - at com.zmops.iot.web.sys.controller.SysUserControllerTTFastClassBySpringCGLIBTT2e326b39.invoke() - at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) - at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) - at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88) - at com.zmops.iot.web.log.aop.LogAop.recordSysLog(LogAop.java:54) - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.lang.reflect.Method.invoke(Method.java:498) - at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644) - at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633) - at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70) - at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) - at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95) - at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) - at org.springframework.aop.framework.CglibAopProxyTCglibMethodInvocation.proceed(CglibAopProxy.java:750) - at org.springframework.aop.framework.CglibAopProxyTDynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) - at com.zmops.iot.web.sys.controller.SysUserControllerTTEnhancerBySpringCGLIBTT2cad82eb.createUser() - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.lang.reflect.Method.invoke(Method.java:498) - at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) - at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) - at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878) - at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792) - at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) - at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) - at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) - at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) - at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) - at javax.servlet.http.HttpServlet.service(HttpServlet.java:517) - at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) - at javax.servlet.http.HttpServlet.service(HttpServlet.java:584) - at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:129) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113) - at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:320) - at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126) - at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at com.zmops.iot.core.auth.filter.JwtAuthorizationTokenFilter.doFilterInternal(JwtAuthorizationTokenFilter.java:77) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92) - at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at org.springframework.security.web.FilterChainProxyTVirtualFilterChain.doFilter(FilterChainProxy.java:334) - at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) - at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) - at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) - at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) - at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) - at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) - at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) - at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:97) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) - at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) - at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) - at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) - at io.undertow.servlet.handlers.FilterHandlerTFilterChainImpl.doFilter(FilterHandler.java:131) - at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) - at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) - at io.undertow.servlet.handlers.ServletChainT1.handleRequest(ServletChain.java:68) - at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) - at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68) - at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:111) - at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) - at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) - at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) - at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) - at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) - at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) - at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) - at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) - at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) - at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269) - at io.undertow.servlet.handlers.ServletInitialHandler.accessT100(ServletInitialHandler.java:78) - at io.undertow.servlet.handlers.ServletInitialHandlerT2.call(ServletInitialHandler.java:133) - at io.undertow.servlet.handlers.ServletInitialHandlerT2.call(ServletInitialHandler.java:130) - at io.undertow.servlet.core.ServletRequestContextThreadSetupActionT1.call(ServletRequestContextThreadSetupAction.java:48) - at io.undertow.servlet.core.ContextClassLoaderSetupActionT1.call(ContextClassLoaderSetupAction.java:43) - at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249) - at io.undertow.servlet.handlers.ServletInitialHandler.accessT000(ServletInitialHandler.java:78) - at io.undertow.servlet.handlers.ServletInitialHandlerT1.handleRequest(ServletInitialHandler.java:99) - at io.undertow.server.Connectors.executeRootHandler(Connectors.java:390) - at io.undertow.server.HttpServerExchangeT1.run(HttpServerExchange.java:836) - at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) - at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019) - at org.jboss.threads.EnhancedQueueExecutorTThreadBody.doRunTask(EnhancedQueueExecutor.java:1558) - at org.jboss.threads.EnhancedQueueExecutorTThreadBody.run(EnhancedQueueExecutor.java:1449) - at java.lang.Thread.run(Thread.java:748) -'); -INSERT INTO "public"."sys_operation_log" VALUES (1440883824174788608, '业务日志', '创建用户', 1, 'com.zmops.iot.web.sys.controller.SysUserController', 'createUser', '2021-09-23 11:40:48.667', '成功', ''); -- ---------------------------- -- Table structure for sys_role @@ -1866,8 +1211,6 @@ CREATE TABLE "public"."sys_role" ( -- Records of sys_role -- ---------------------------- INSERT INTO "public"."sys_role" VALUES (1, '超级管理员', 'administrator', 1, NULL, 1, NULL, '2021-08-17 10:57:36.612'); -INSERT INTO "public"."sys_role" VALUES (1432233337871355904, '测试', '', NULL, 1, 1, '2021-08-30 14:46:52.014', '2021-08-30 14:46:52.014'); -INSERT INTO "public"."sys_role" VALUES (1437618920839958528, '三石TestgOtXD2', NULL, NULL, 1, 1, '2021-09-14 11:27:15.053', '2021-09-14 11:27:15.053'); -- ---------------------------- -- Table structure for sys_role_menu @@ -1882,313 +1225,89 @@ CREATE TABLE "public"."sys_role_menu" ( -- ---------------------------- -- Records of sys_role_menu -- ---------------------------- -INSERT INTO "public"."sys_role_menu" VALUES (1423482240088260608, 1); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 105); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 106); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 114); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 128); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 132); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 133); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 168); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 169); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 170); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 171); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 172); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 173); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 174); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 175); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 176); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 177); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 178); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 179); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 180); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 181); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 182); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 183); -INSERT INTO "public"."sys_role_menu" VALUES (1423549393533521920, 184); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 105); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 106); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 114); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 128); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 132); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 133); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 168); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 169); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 170); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 171); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 172); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 173); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 174); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 175); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 176); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 177); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 178); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 179); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 180); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 181); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 182); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 183); -INSERT INTO "public"."sys_role_menu" VALUES (1423551494242271232, 184); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 105); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 106); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 114); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 128); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 132); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 133); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 168); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 169); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 170); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 171); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 172); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 173); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 174); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 175); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 176); -INSERT INTO "public"."sys_role_menu" VALUES (1422463279817150464, 170); -INSERT INTO "public"."sys_role_menu" VALUES (1422463279817150464, 178); -INSERT INTO "public"."sys_role_menu" VALUES (1422463279817150464, 177); -INSERT INTO "public"."sys_role_menu" VALUES (1422463279817150464, 179); -INSERT INTO "public"."sys_role_menu" VALUES (1422463279817150464, 181); -INSERT INTO "public"."sys_role_menu" VALUES (1422463279817150464, 172); -INSERT INTO "public"."sys_role_menu" VALUES (1422463279817150464, 182); -INSERT INTO "public"."sys_role_menu" VALUES (1422463279817150464, 171); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 177); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 178); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 179); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 180); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 181); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 182); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 183); -INSERT INTO "public"."sys_role_menu" VALUES (1423551559929266176, 184); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 105); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 106); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 114); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 128); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 132); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 133); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 168); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 169); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 170); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 171); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 172); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 173); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 174); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 175); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 176); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 177); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 178); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 179); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 180); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 181); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 182); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 183); -INSERT INTO "public"."sys_role_menu" VALUES (1423551670717612032, 184); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 105); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 106); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 114); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 128); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 132); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 133); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 168); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 169); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 170); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 171); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 172); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 173); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 174); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 175); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 176); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 177); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 178); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 179); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 180); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 181); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 182); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 183); -INSERT INTO "public"."sys_role_menu" VALUES (1423552915037523968, 184); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 105); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 106); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 114); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 128); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 132); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 133); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 168); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 169); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 170); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 171); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 172); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 173); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 174); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 175); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 176); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 177); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 178); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 179); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 180); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 181); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 182); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 183); -INSERT INTO "public"."sys_role_menu" VALUES (1423840436349898752, 184); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 105); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 106); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 114); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 128); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 132); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 133); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 168); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 169); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 170); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 171); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 173); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 174); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 176); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 177); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 178); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 179); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 180); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 181); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 183); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 184); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 185); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 186); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 187); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 188); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 189); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 190); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 191); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 192); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 193); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 194); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 195); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 196); -INSERT INTO "public"."sys_role_menu" VALUES (1428542898655903744, 197); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 105); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 106); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 114); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 128); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 132); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 133); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 168); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 169); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 170); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 171); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 173); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 174); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 176); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 177); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 178); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 179); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 180); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 181); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 183); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 184); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 185); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 186); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 187); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 188); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 189); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 190); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 191); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 192); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 193); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 194); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 195); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 196); -INSERT INTO "public"."sys_role_menu" VALUES (1428552324309762048, 197); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 105); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 106); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 114); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 128); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 132); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 133); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 168); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 169); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 170); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 171); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 173); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 174); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 176); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 177); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 178); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 179); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 180); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 181); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 183); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 184); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 185); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 186); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 187); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 188); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 189); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 190); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 191); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 192); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 193); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 194); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 195); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 196); -INSERT INTO "public"."sys_role_menu" VALUES (1428552760613847040, 197); -INSERT INTO "public"."sys_role_menu" VALUES (1428553795793240064, 105); -INSERT INTO "public"."sys_role_menu" VALUES (1428555085013237760, 105); -INSERT INTO "public"."sys_role_menu" VALUES (1428555388848619520, 105); -INSERT INTO "public"."sys_role_menu" VALUES (1428559148366872576, 105); -INSERT INTO "public"."sys_role_menu" VALUES (1432233337871355904, 189); -INSERT INTO "public"."sys_role_menu" VALUES (1432233337871355904, 169); INSERT INTO "public"."sys_role_menu" VALUES (1, 169); -INSERT INTO "public"."sys_role_menu" VALUES (1, 189); -INSERT INTO "public"."sys_role_menu" VALUES (1, 190); -INSERT INTO "public"."sys_role_menu" VALUES (1, 176); -INSERT INTO "public"."sys_role_menu" VALUES (1, 197); INSERT INTO "public"."sys_role_menu" VALUES (1, 170); -INSERT INTO "public"."sys_role_menu" VALUES (1, 177); -INSERT INTO "public"."sys_role_menu" VALUES (1, 188); -INSERT INTO "public"."sys_role_menu" VALUES (1, 178); -INSERT INTO "public"."sys_role_menu" VALUES (1, 196); INSERT INTO "public"."sys_role_menu" VALUES (1, 171); -INSERT INTO "public"."sys_role_menu" VALUES (1, 181); -INSERT INTO "public"."sys_role_menu" VALUES (1, 180); -INSERT INTO "public"."sys_role_menu" VALUES (1, 185); +INSERT INTO "public"."sys_role_menu" VALUES (1, 172); +INSERT INTO "public"."sys_role_menu" VALUES (1, 173); INSERT INTO "public"."sys_role_menu" VALUES (1, 174); -INSERT INTO "public"."sys_role_menu" VALUES (1, 192); +INSERT INTO "public"."sys_role_menu" VALUES (1, 175); +INSERT INTO "public"."sys_role_menu" VALUES (1, 176); +INSERT INTO "public"."sys_role_menu" VALUES (1, 177); +INSERT INTO "public"."sys_role_menu" VALUES (1, 178); INSERT INTO "public"."sys_role_menu" VALUES (1, 179); -INSERT INTO "public"."sys_role_menu" VALUES (1, 194); -INSERT INTO "public"."sys_role_menu" VALUES (1, 193); +INSERT INTO "public"."sys_role_menu" VALUES (1, 180); +INSERT INTO "public"."sys_role_menu" VALUES (1, 181); +INSERT INTO "public"."sys_role_menu" VALUES (1, 182); +INSERT INTO "public"."sys_role_menu" VALUES (1, 183); +INSERT INTO "public"."sys_role_menu" VALUES (1, 168); INSERT INTO "public"."sys_role_menu" VALUES (1, 184); -INSERT INTO "public"."sys_role_menu" VALUES (1, 133); INSERT INTO "public"."sys_role_menu" VALUES (1, 128); +INSERT INTO "public"."sys_role_menu" VALUES (1, 133); +INSERT INTO "public"."sys_role_menu" VALUES (1, 132); +INSERT INTO "public"."sys_role_menu" VALUES (1, 201); +INSERT INTO "public"."sys_role_menu" VALUES (1, 202); +INSERT INTO "public"."sys_role_menu" VALUES (1, 203); +INSERT INTO "public"."sys_role_menu" VALUES (1, 204); +INSERT INTO "public"."sys_role_menu" VALUES (1, 205); +INSERT INTO "public"."sys_role_menu" VALUES (1, 206); +INSERT INTO "public"."sys_role_menu" VALUES (1, 207); +INSERT INTO "public"."sys_role_menu" VALUES (1, 208); +INSERT INTO "public"."sys_role_menu" VALUES (1, 209); +INSERT INTO "public"."sys_role_menu" VALUES (1, 211); +INSERT INTO "public"."sys_role_menu" VALUES (1, 210); +INSERT INTO "public"."sys_role_menu" VALUES (1, 212); +INSERT INTO "public"."sys_role_menu" VALUES (1, 217); INSERT INTO "public"."sys_role_menu" VALUES (1, 105); -INSERT INTO "public"."sys_role_menu" VALUES (1, 168); -INSERT INTO "public"."sys_role_menu" VALUES (1, 186); INSERT INTO "public"."sys_role_menu" VALUES (1, 106); INSERT INTO "public"."sys_role_menu" VALUES (1, 107); INSERT INTO "public"."sys_role_menu" VALUES (1, 108); INSERT INTO "public"."sys_role_menu" VALUES (1, 109); INSERT INTO "public"."sys_role_menu" VALUES (1, 110); +INSERT INTO "public"."sys_role_menu" VALUES (1, 111); +INSERT INTO "public"."sys_role_menu" VALUES (1, 112); INSERT INTO "public"."sys_role_menu" VALUES (1, 113); INSERT INTO "public"."sys_role_menu" VALUES (1, 114); INSERT INTO "public"."sys_role_menu" VALUES (1, 115); INSERT INTO "public"."sys_role_menu" VALUES (1, 116); INSERT INTO "public"."sys_role_menu" VALUES (1, 117); INSERT INTO "public"."sys_role_menu" VALUES (1, 118); -INSERT INTO "public"."sys_role_menu" VALUES (1, 132); +INSERT INTO "public"."sys_role_menu" VALUES (1, 119); +INSERT INTO "public"."sys_role_menu" VALUES (1, 120); +INSERT INTO "public"."sys_role_menu" VALUES (1, 121); +INSERT INTO "public"."sys_role_menu" VALUES (1, 122); +INSERT INTO "public"."sys_role_menu" VALUES (1, 185); +INSERT INTO "public"."sys_role_menu" VALUES (1, 186); INSERT INTO "public"."sys_role_menu" VALUES (1, 187); -INSERT INTO "public"."sys_role_menu" VALUES (1437255079924846592, 168); -INSERT INTO "public"."sys_role_menu" VALUES (1437255079924846592, 186); -INSERT INTO "public"."sys_role_menu" VALUES (1437255079924846592, 187); -INSERT INTO "public"."sys_role_menu" VALUES (1437255079924846592, 105); +INSERT INTO "public"."sys_role_menu" VALUES (1, 188); +INSERT INTO "public"."sys_role_menu" VALUES (1, 189); +INSERT INTO "public"."sys_role_menu" VALUES (1, 190); +INSERT INTO "public"."sys_role_menu" VALUES (1, 191); +INSERT INTO "public"."sys_role_menu" VALUES (1, 192); +INSERT INTO "public"."sys_role_menu" VALUES (1, 193); +INSERT INTO "public"."sys_role_menu" VALUES (1, 194); +INSERT INTO "public"."sys_role_menu" VALUES (1, 195); +INSERT INTO "public"."sys_role_menu" VALUES (1, 196); +INSERT INTO "public"."sys_role_menu" VALUES (1, 197); +INSERT INTO "public"."sys_role_menu" VALUES (1, 213); +INSERT INTO "public"."sys_role_menu" VALUES (1, 214); +INSERT INTO "public"."sys_role_menu" VALUES (1, 215); +INSERT INTO "public"."sys_role_menu" VALUES (1, 216); INSERT INTO "public"."sys_role_menu" VALUES (1, 198); +INSERT INTO "public"."sys_role_menu" VALUES (1, 199); +INSERT INTO "public"."sys_role_menu" VALUES (1, 200); -- ---------------------------- -- Table structure for sys_user -- ---------------------------- DROP TABLE IF EXISTS "public"."sys_user"; CREATE TABLE "public"."sys_user" ( - "account" varchar(255) COLLATE "pg_catalog"."default", - "password" varchar(255) COLLATE "pg_catalog"."default", - "salt" varchar(255) COLLATE "pg_catalog"."default", - "name" varchar(255) COLLATE "pg_catalog"."default", - "email" varchar(255) COLLATE "pg_catalog"."default", - "phone" varchar(255) COLLATE "pg_catalog"."default", + "account" varchar(32) COLLATE "pg_catalog"."default", + "password" varchar(32) COLLATE "pg_catalog"."default", + "salt" varchar(32) COLLATE "pg_catalog"."default", + "name" varchar(64) COLLATE "pg_catalog"."default", + "email" varchar(64) COLLATE "pg_catalog"."default", + "phone" varchar(16) COLLATE "pg_catalog"."default", "role_id" int8, "user_group_id" int8, "status" varchar(32) COLLATE "pg_catalog"."default", @@ -2221,10 +1340,8 @@ COMMENT ON COLUMN "public"."sys_user"."zbx_id" IS 'zabbix 用户ID'; -- ---------------------------- -- Records of sys_user -- ---------------------------- -INSERT INTO "public"."sys_user" VALUES ('root', '17db03c22596b7609c7c9704f16663e0', 'abcdef', '超级管理员', '888888@qq.com', '13812345678', 1, NULL, 'ENABLE', 1, 1, '2021-07-30 21:43:02.686', '2021-07-30 21:43:02.686', 1, '6828c069d5e939b384513d705a2b9ff4', '4'); -INSERT INTO "public"."sys_user" VALUES ('Admin', '897e47e15311c2fafa7408af5d33b76b', 'q4y9d', '超级管理员', '', '', 1, 1433259921541644288, 'ENABLE', 1, 1, '2021-09-23 11:40:48.622', '2021-09-23 11:40:48.622', 117, '7f7ae1a47db539231208c8e3b743059d', '1'); -INSERT INTO "public"."sys_user" VALUES ('zuolan', 'e1e874669f7b8d5d9c339abf919668e2', '2c6t3', '卓蓝', '', '', 1, 1435061972567298048, 'ENABLE', 1, 1, '2021-09-16 20:19:35.538', '2021-09-16 20:19:35.538', 116, NULL, '80'); -INSERT INTO "public"."sys_user" VALUES ('sanshi', '8368532ffd4039b103d1c71511671d99', 'j75bd', '三石', '', '', 1, 1435061972567298048, 'ENABLE', 1, 1, '2021-09-08 15:08:53.598', '2021-09-08 15:08:53.598', 79, NULL, '42'); +INSERT INTO "public"."sys_user" VALUES ('Admin', 'cbde417443393372dbac9c185a6ec159', 'gt3zs', '超级管理员', '', '', 1, 1437232484602372096, 'ENABLE', 1, 1, '2021-09-28 09:38:33.668', '2021-09-28 09:38:33.668', 122, '712e512d1dfe13319e15bf5050a81ace', '1'); +INSERT INTO "public"."sys_user" VALUES ('root', '17db03c22596b7609c7c9704f16663e0', 'abcdef', '超级管理员', '888888@qq.com', '13812345678', 1, 1437232484602372096, 'ENABLE', 1, 1, '2021-07-30 21:43:02.686', '2021-07-30 21:43:02.686', 1, '5859e004e8d2a23e6c330c3f9cd277e2', '4'); -- ---------------------------- -- Table structure for sys_user_group @@ -2246,7 +1363,6 @@ CREATE TABLE "public"."sys_user_group" ( -- ---------------------------- -- Records of sys_user_group -- ---------------------------- -INSERT INTO "public"."sys_user_group" VALUES ('默认用户组', '7', '', '2021-09-02 10:46:09', 1, '2021-09-02 10:46:09', 1, 'ENABLE', 1433259921541644288); -- ---------------------------- -- Table structure for sys_usrgrp_devicegrp @@ -2291,30 +1407,20 @@ COMMENT ON COLUMN "public"."tag"."update_time" IS '更新时间'; -- ---------------------------- -- Records of tag -- ---------------------------- -INSERT INTO "public"."tag" VALUES ('1432184478772101120', '位置', '位置', 157, NULL, 1, 1, '2021-08-30 11:35:29.303', '2021-08-30 11:35:29.303'); -INSERT INTO "public"."tag" VALUES ('1432254913865859072', '位置', '位置', 159, 157, NULL, NULL, NULL, NULL); -INSERT INTO "public"."tag" VALUES ('1432255618861240320', '位置', '位置', 160, 157, NULL, NULL, NULL, NULL); -INSERT INTO "public"."tag" VALUES ('1434043521937584128', '45646', '456456', 171, NULL, 1, 1, '2021-09-14 18:05:22.27', '2021-09-14 18:05:22.27'); -INSERT INTO "public"."tag" VALUES ('1434043521937584128', '1', '1', 172, NULL, 1, 1, '2021-09-14 18:05:22.27', '2021-09-14 18:05:22.27'); -INSERT INTO "public"."tag" VALUES ('1434043521937584128', '2', '3', 173, NULL, 1, 1, '2021-09-14 18:05:22.27', '2021-09-14 18:05:22.27'); -INSERT INTO "public"."tag" VALUES ('1437965905006678016', 'SSp7u9WF11', '三石TestHdF4i011', 174, NULL, 1, 1, '2021-09-15 10:26:02.639', '2021-09-15 10:26:02.639'); -INSERT INTO "public"."tag" VALUES ('1437966016684216320', 'SSLspEVQ11', '三石TestOwN6U311', 175, NULL, 1, 1, '2021-09-15 10:26:29.264', '2021-09-15 10:26:29.264'); -INSERT INTO "public"."tag" VALUES ('1437966016684216320', 'SSLspEVQ12', '三石TestOwN6U312', 176, NULL, 1, 1, '2021-09-15 10:26:29.264', '2021-09-15 10:26:29.264'); -INSERT INTO "public"."tag" VALUES ('1437966016684216320', 'SSLspEVQ13', '三石TestOwN6U313', 177, NULL, 1, 1, '2021-09-15 10:26:29.264', '2021-09-15 10:26:29.264'); -- ---------------------------- -- Alter sequences owned by -- ---------------------------- ALTER SEQUENCE "public"."device_online_report_id_seq" OWNED BY "public"."device_online_report"."id"; -SELECT setval('"public"."device_online_report_id_seq"', 5, true); +SELECT setval('"public"."device_online_report_id_seq"', 7, true); -- ---------------------------- -- Alter sequences owned by -- ---------------------------- ALTER SEQUENCE "public"."devices_groups_id_seq" OWNED BY "public"."devices_groups"."id"; -SELECT setval('"public"."devices_groups_id_seq"', 171, true); +SELECT setval('"public"."devices_groups_id_seq"', 182, true); -- ---------------------------- -- Alter sequences owned by @@ -2328,14 +1434,14 @@ SELECT setval('"public"."media_type_setting_id_seq"', 2, false); -- ---------------------------- ALTER SEQUENCE "public"."messages_id_seq" OWNED BY "public"."messages"."id"; -SELECT setval('"public"."messages_id_seq"', 222, true); +SELECT setval('"public"."messages_id_seq"', 234, true); -- ---------------------------- -- Alter sequences owned by -- ---------------------------- ALTER SEQUENCE "public"."product_event_relation_id_seq" OWNED BY "public"."product_event_relation"."id"; -SELECT setval('"public"."product_event_relation_id_seq"', 43, true); +SELECT setval('"public"."product_event_relation_id_seq"', 62, true); -- ---------------------------- -- Alter sequences owned by @@ -2363,7 +1469,7 @@ SELECT setval('"public"."product_status_function_relation_id_seq"', 8, true); -- ---------------------------- ALTER SEQUENCE "public"."product_type_product_type_id_seq" OWNED BY "public"."product_type"."id"; -SELECT setval('"public"."product_type_product_type_id_seq"', 215, true); +SELECT setval('"public"."product_type_product_type_id_seq"', 226, true); -- ---------------------------- -- Alter sequences owned by @@ -2398,14 +1504,14 @@ SELECT setval('"public"."sys_user_group_user_group_id_seq"', 30, true); -- ---------------------------- ALTER SEQUENCE "public"."sys_user_user_id_seq" OWNED BY "public"."sys_user"."user_id"; -SELECT setval('"public"."sys_user_user_id_seq"', 118, true); +SELECT setval('"public"."sys_user_user_id_seq"', 123, true); -- ---------------------------- -- Alter sequences owned by -- ---------------------------- ALTER SEQUENCE "public"."tag_id_seq" OWNED BY "public"."tag"."id"; -SELECT setval('"public"."tag_id_seq"', 180, true); +SELECT setval('"public"."tag_id_seq"', 196, true); -- ---------------------------- -- Primary Key structure for table device @@ -2472,11 +1578,6 @@ ALTER TABLE "public"."product_event_relation" ADD CONSTRAINT "product_event_rela -- ---------------------------- ALTER TABLE "public"."product_event_tags" ADD CONSTRAINT "product_event_tags_pkey" PRIMARY KEY ("id"); --- ---------------------------- --- Primary Key structure for table product_group --- ---------------------------- -ALTER TABLE "public"."product_group" ADD CONSTRAINT "product_group_pkey" PRIMARY KEY ("product_group_id"); - -- ---------------------------- -- Primary Key structure for table product_service -- ---------------------------- From 46f9f92bc9df6af1529cd3682b603fe0cc9b85be Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 11 Oct 2021 10:26:59 +0800 Subject: [PATCH 481/763] [fix]: fix action ftl --- .../zmops/zeus/driver/service/ZbxAction.java | 15 ++++++++ .../api-json/action/action.create.ftl | 35 +++++++++++++++++++ .../zmops/iot/web/init/BasicSettingsInit.java | 7 +++- .../iot/web/init/DeviceSatusScriptInit.java | 2 +- 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java index de88339d..8c6cad5d 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java @@ -33,6 +33,21 @@ String createOfflineStatusAction(@ParamName("userAuth") String userAuth, @ParamName("scriptId") String scriptId, @ParamName("groupId") String groupId); + /** + * 创建默认 告警通知 Action + * + * @param userAuth api token + * @param scriptId 脚本ID + * @param groupId 全局主机组ID + * @return String + */ + @Post(headers = "authTag: noAuth") + @JsonPath("/action/action.create") + String createAlarmAction(@ParamName("userAuth") String userAuth, + @ParamName("name") String name, + @ParamName("tagName") String tagName, + @ParamName("scriptId") String scriptId, + @ParamName("groupId") String groupId); /** * 获取 在线状态 Action diff --git a/zeus-driver/src/main/resources/api-json/action/action.create.ftl b/zeus-driver/src/main/resources/api-json/action/action.create.ftl index e69de29b..4ab8c3dc 100644 --- a/zeus-driver/src/main/resources/api-json/action/action.create.ftl +++ b/zeus-driver/src/main/resources/api-json/action/action.create.ftl @@ -0,0 +1,35 @@ +{ + "jsonrpc": "2.0", + "method": "action.create", + "params": { + "name": "${name}", + "eventsource": 0, + "status": 0, + "esc_period": "2m", + "filter": { + "evaltype": 0, + "conditions": [ + { + "conditiontype": 25, + "operator": 0, + "value": "${tagName}" + } + ] + }, + "operations": [ + { + "operationtype": 1, + "opcommand_hst": [ + { + "hostid": "0" + } + ], + "opcommand": { + "scriptid": "${scriptId}" + } + } + ] + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java index 87f37c6a..aad92f1b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java @@ -166,11 +166,16 @@ public Map getOfflineStatusScript() { } - public String createAction(String name, String tagName, String scriptId, String groupId) { + public String createOffLineAction(String name, String tagName, String scriptId, String groupId) { String response = zbxAction.createOfflineStatusAction(zbxApiToken, name, tagName, scriptId, groupId); return JSON.parseObject(response, ZbxResponseIds.class).getActionids()[0]; } + public String createAction(String name, String tagName, String scriptId, String groupId) { + String response = zbxAction.createAlarmAction(zbxApiToken, name, tagName, scriptId, groupId); + return JSON.parseObject(response, ZbxResponseIds.class).getActionids()[0]; + } + public String getAction(String name) { String response = zbxAction.getOfflineStatusAction(zbxApiToken, name); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java index c92c9bdb..a9f33bea 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java @@ -74,7 +74,7 @@ public void run(String... args) throws Exception { String offLineActionId = basicSettingsInit.getAction(SCRIPT_OFFLINE); if (offLineActionId == null) { - offLineActionId = basicSettingsInit.createAction(SCRIPT_OFFLINE, ACTION_TAG_OFFLINE, script.get(SCRIPT_OFFLINE), groupId); + offLineActionId = basicSettingsInit.createOffLineAction(SCRIPT_OFFLINE, ACTION_TAG_OFFLINE, script.get(SCRIPT_OFFLINE), groupId); } DB.update(SysConfig.class).where().eq("code", GLOBAL_OFFLINE_ACTION_CODE).asUpdate().set("value", offLineActionId).update(); From c9c7ec30c04667cbb835542c974a67aba2712cfb Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 11 Oct 2021 10:30:55 +0800 Subject: [PATCH 482/763] [feat]: add product service param --- .../java/com/zmops/iot/domain/product/ProductServiceParam.java | 1 + 1 file changed, 1 insertion(+) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceParam.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceParam.java index 9f6d8a4d..f94b7a24 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceParam.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceParam.java @@ -22,4 +22,5 @@ public class ProductServiceParam { private String name; private String key; private String remark; + private String value; } From fe8845325f60db6b2f3db23fff6f94560a9b8440 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 11 Oct 2021 15:31:45 +0800 Subject: [PATCH 483/763] [feat]: fix bug --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index 1aed7fbe..76853841 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit 1aed7fbe950f13de832ccbb4f7f9d26c163a8763 +Subproject commit 768538410237f2da7f2963cb9e370bfdf1dc66de From b624c3091650fea5c1dded24373b302d6a14b83c Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 11 Oct 2021 17:03:21 +0800 Subject: [PATCH 484/763] [feat]: add product attr value type --- .../com/zmops/iot/domain/product/ProductEventExpression.java | 2 +- .../main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java | 2 ++ .../zmops/iot/web/device/service/DeviceEventRuleService.java | 1 + .../java/com/zmops/iot/web/product/dto/ProductEventRule.java | 2 ++ .../zmops/iot/web/product/service/ProductEventRuleService.java | 1 + 5 files changed, 7 insertions(+), 1 deletion(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java index f25d0d7f..fbf61f7c 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java @@ -35,5 +35,5 @@ public class ProductEventExpression extends Model { private Long productAttrId; private String productAttrType; private String period; - + private String attrValueType; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java index 1b7d251c..0f3a8305 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java @@ -102,6 +102,8 @@ public static class Expression { private String productAttrType; + private String attrValueType; + private String period; @Override diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 1665d038..beb96d24 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -185,6 +185,7 @@ private ProductEventExpression initEventExpression(DeviceEventRule.Expression ex eventExpression.setProductAttrType(exp.getProductAttrType()); eventExpression.setPeriod(exp.getPeriod()); eventExpression.setUnit(exp.getUnit()); + eventExpression.setAttrValueType(exp.getAttrValueType()); return eventExpression; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java index 1eb927c2..2065aa7f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java @@ -102,6 +102,8 @@ public static class Expression { private String productAttrType; + private String attrValueType; + private String period; @Override diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index e0f054ea..f2d6a531 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -166,6 +166,7 @@ private ProductEventExpression initEventExpression(ProductEventRule.Expression e eventExpression.setProductAttrType(exp.getProductAttrType()); eventExpression.setPeriod(exp.getPeriod()); eventExpression.setUnit(exp.getUnit()); + eventExpression.setAttrValueType(exp.getAttrValueType()); return eventExpression; } From 3f74b30ef1ff8de2df632a5d538e70e394242639 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 11 Oct 2021 18:43:03 +0800 Subject: [PATCH 485/763] [fix]: fix product event trigger --- .../ProductEventTriggerController.java | 22 +++++-- .../service/ProductEventRuleService.java | 2 +- .../work/SaveProductEventTriggerWorker.java | 15 +++++ .../work/UpdateProductEventTriggerWorker.java | 64 +++++++++++++++++++ 4 files changed, 98 insertions(+), 5 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index a16e05ab..91af9650 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -23,6 +23,7 @@ import com.zmops.iot.web.product.dto.param.EventParm; import com.zmops.iot.web.product.service.ProductEventRuleService; import com.zmops.iot.web.product.service.work.SaveProductEventTriggerWorker; +import com.zmops.iot.web.product.service.work.UpdateProductEventTriggerWorker; import com.zmops.zeus.driver.service.ZbxTrigger; import io.ebean.DB; import io.ebean.annotation.Transactional; @@ -54,14 +55,17 @@ public class ProductEventTriggerController { @Autowired private ZbxTrigger zbxTrigger; - private static final String ALARM_TAG_NAME = "__alarm__"; + private static final String ALARM_TAG_NAME = "__alarm__"; private static final String EXECUTE_TAG_NAME = "__execute__"; - private static final String EVENT_TAG_NAME = "__event__"; - private static final String EVENT_TYPE_NAME = "事件"; + private static final String EVENT_TAG_NAME = "__event__"; + private static final String EVENT_TYPE_NAME = "事件"; @Autowired SaveProductEventTriggerWorker saveProductEventTriggerWorker; + @Autowired + UpdateProductEventTriggerWorker updateProductEventTriggerWorker; + /** * 触发器 分页列表 * @@ -137,7 +141,7 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE WorkerWrapper saveProductEventTriggerWork = WorkerWrapper.builder().worker(saveProductEventTriggerWorker).param(eventRule).build(); try { - Async.work(100, saveProductEventTriggerWork).awaitFinish(); + Async.work(1000, saveProductEventTriggerWork).awaitFinish(); } catch (InterruptedException e) { e.printStackTrace(); } @@ -197,6 +201,16 @@ public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseE zbxTrigger.triggerTagCreate(list.get(0).getZbxId(), tags); + + //step 4: 同步到产品下的设备 + WorkerWrapper updateProductEventTriggerWork = WorkerWrapper.builder().worker(updateProductEventTriggerWorker).param(eventRule).build(); + + try { + Async.work(1000, updateProductEventTriggerWork).awaitFinish(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return ResponseData.success(eventRule.getEventRuleId()); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index f2d6a531..e2dfad33 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -270,7 +270,7 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S } }); productEventRuleDto.setExpList(expList); - productEventRuleDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).deviceId.isNull().findList()); + productEventRuleDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).deviceId.eq(prodId).findList()); ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(prodId).eventRuleId.eq(eventRuleId).findOne(); productEventRuleDto.setStatus(productEventRelation.getStatus()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java index 0e234b43..fb4de139 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java @@ -6,6 +6,7 @@ import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.ProductEventService; import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.enums.InheritStatus; import com.zmops.iot.web.product.dto.ProductEventRule; @@ -44,7 +45,10 @@ public Boolean action(ProductEventRule productEventRule, Map triggers = JSONObject.parseArray(zbxTrigger.triggerGetByName(productEventRule.getEventRuleId() + ""), ProductEventRuleService.Triggers.class); Map treiggerMap = triggers.parallelStream().collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ProductEventRuleService.Triggers::getTriggerid)); + List productEventRelationList = new ArrayList<>(); + List addProductEventServiceList = new ArrayList<>(); + for (String deviceId : deviceIds) { ProductEventRelation productEventRelation = new ProductEventRelation(); productEventRelation.setRelationId(deviceId); @@ -56,9 +60,20 @@ public Boolean action(ProductEventRule productEventRule, Map { + ProductEventService newProductEventService = new ProductEventService(); + newProductEventService.setDeviceId(deviceId); + newProductEventService.setExecuteDeviceId(deviceId); + newProductEventService.setEventRuleId(productEventRule.getEventRuleId()); + newProductEventService.setServiceId(productEventService.getServiceId()); + addProductEventServiceList.add(newProductEventService); + }); } DB.saveAll(productEventRelationList); + DB.saveAll(addProductEventServiceList); + return true; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java new file mode 100644 index 00000000..f7be62a7 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java @@ -0,0 +1,64 @@ +package com.zmops.iot.web.product.service.work; + + +import com.zmops.iot.async.callback.IWorker; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductEventService; +import com.zmops.iot.web.product.dto.ProductEventRule; +import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author yefei + *

+ * 产品服务创建 同步到设备 步骤 + */ +@Slf4j +@Component +public class UpdateProductEventTriggerWorker implements IWorker { + + + @Autowired + ZbxTrigger zbxTrigger; + + @Override + public Boolean action(ProductEventRule productEventRule, Map> map) { + log.debug("处理产品 修改告警规则 同步到设备工作…………"); + + String prodId = productEventRule.getProductId(); + + List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); + + List addProductEventServiceList = new ArrayList<>(); + + for (String deviceId : deviceIds) { + productEventRule.getDeviceServices().forEach(productEventService -> { + ProductEventService newProductEventService = new ProductEventService(); + newProductEventService.setDeviceId(deviceId); + newProductEventService.setExecuteDeviceId(deviceId); + newProductEventService.setEventRuleId(productEventRule.getEventRuleId()); + newProductEventService.setServiceId(productEventService.getServiceId()); + addProductEventServiceList.add(newProductEventService); + }); + } + + DB.saveAll(addProductEventServiceList); + + return true; + } + + + @Override + public Boolean defaultValue() { + return true; + } + +} From 38db8949bcc403ac888a625b79256d5da7608a99 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 11 Oct 2021 19:34:48 +0800 Subject: [PATCH 486/763] [feat]: add device status enable/disable --- .../web/device/controller/DeviceController.java | 14 ++++++++++++++ .../com/zmops/iot/web/device/dto/DeviceDto.java | 3 ++- .../web/device/service/DeviceEventRuleService.java | 9 ++++----- .../iot/web/device/service/DeviceService.java | 10 ++++++++++ .../zmops/iot/web/sys/service/SysRoleService.java | 6 +++--- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java index f7ccd905..58ab992f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java @@ -106,6 +106,20 @@ public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody Devi return ResponseData.success(deviceService.delete(deviceDto)); } + /** + * 设备启用、禁用 + */ + @Permission(code = "dev_update") + @RequestMapping("/status") + public ResponseData status(@Validated(BaseEntity.Status.class) @RequestBody DeviceDto deviceDto) { + int count = new QDevice().deviceId.eq(deviceDto.getDeviceId()).findCount(); + if (count <= 0) { + throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); + } + deviceService.status(deviceDto.getStatus(),deviceDto.getDeviceId()); + return ResponseData.success(); + } + /** * 设备详情 */ diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java index d0bace1e..2a882bca 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java @@ -20,7 +20,7 @@ @JsonSerialize(using = CachedValueFilter.class) public class DeviceDto { - @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Delete.class}) + @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Delete.class,BaseEntity.Status.class}) private String deviceId; private String edit; @@ -37,6 +37,7 @@ public class DeviceDto { private List deviceGroupIds; @CachedValue(value = "STATUS") + @NotBlank(groups = {BaseEntity.Status.class}) private String status; @CachedValue(value = "DEVICE_TYPE") diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index beb96d24..43c7b3da 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -69,7 +69,7 @@ public void createDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { deviceIds.forEach(deviceId -> { eventRule.getDeviceServices().forEach(i -> { DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) " + - "values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") + "values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") .setParameter("eventRuleId", eventRuleId) .setParameter("deviceId", deviceId) .setParameter("executeDeviceId", i.getExecuteDeviceId()) @@ -134,8 +134,7 @@ public void updateDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { List deviceIds = eventRule.getExpList().parallelStream().map(DeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); deviceIds.forEach(deviceId -> { eventRule.getDeviceServices().forEach(i -> { - DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id, service_id) values (:eventRuleId, :deviceId, :serviceId)") - .setParameter("eventRuleId", eventRuleId) + DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)").setParameter("eventRuleId", eventRuleId) .setParameter("deviceId", deviceId) .setParameter("executeDeviceId", i.getExecuteDeviceId()) .setParameter("serviceId", i.getServiceId()) @@ -285,8 +284,8 @@ static class TriggerIds { @Data public static class Triggers { - private String triggerid; - private String description; + private String triggerid; + private String description; private List hosts; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 1f19ba41..28b36a53 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -514,4 +514,14 @@ private JSONArray getZbxHostInfo(String deviceId) { return JSONObject.parseArray(zbxHost.hostDetail(zbxId)); } + /** + * 修改设备状态 + * + * @param status + * @param deviceId + * @return + */ + public void status(String status, String deviceId) { + DB.update(Device.class).where().eq("device_id", deviceId).asUpdate().set("status", status).setNull("online").update(); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java index c0e8bd91..140eeff3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java @@ -41,7 +41,7 @@ public List list(String name) { if (ToolUtil.isNotEmpty(name)) { qSysRole.name.contains(name); } - return qSysRole.orderBy("create_time desc").findList(); + return qSysRole.roleId.ne(1L).orderBy("create_time desc").findList(); } /** @@ -84,8 +84,8 @@ public void delete(RoleParam sysRoleParam) { if (count > 0) { throw new ServiceException(BizExceptionEnum.ROLE_HAS_BIND_USER); } - new QSysRoleMenu().roleId.in(sysRoleParam.getRoleIds()).delete(); - new QSysRole().roleId.in(sysRoleParam.getRoleIds()).delete(); + new QSysRoleMenu().roleId.in(sysRoleParam.getRoleIds()).roleId.ne(1L).delete(); + new QSysRole().roleId.in(sysRoleParam.getRoleIds()).roleId.ne(1L).delete(); } /** From bdb931be7dca8b02e940aff5058d521ae5ec0178 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 11 Oct 2021 20:20:29 +0800 Subject: [PATCH 487/763] [fix]: fix event list --- .../java/com/zmops/iot/web/alarm/service/AlarmService.java | 5 ++--- .../zmops/iot/web/device/controller/DeviceController.java | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 73cf9c61..3da2f1d1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -123,7 +123,7 @@ public Pager getAlarmByPage(AlarmParam alarmParam) { public List getAlarmList(AlarmParam alarmParam) { String hostId = null; - Assert.state(ToolUtil.isNotEmpty(alarmParam.getDeviceId()), "设备ID不能为空"); +// Assert.state(ToolUtil.isNotEmpty(alarmParam.getDeviceId()), "设备ID不能为空"); List problemList = getZbxAlarm(alarmParam); if (ToolUtil.isEmpty(problemList)) { return Collections.emptyList(); @@ -170,8 +170,7 @@ public List getZbxAlarm(AlarmParam alarmParam) { public List getEventList(AlarmParam alarmParam) { - String hostId = null; - Assert.state(ToolUtil.isNotEmpty(alarmParam.getDeviceId()), "设备ID不能为空"); +// Assert.state(ToolUtil.isNotEmpty(alarmParam.getDeviceId()), "设备ID不能为空"); List problemList = getEventProblem(alarmParam); if (ToolUtil.isEmpty(problemList)) { return Collections.emptyList(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java index 58ab992f..48644925 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java @@ -110,7 +110,7 @@ public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody Devi * 设备启用、禁用 */ @Permission(code = "dev_update") - @RequestMapping("/status") + @RequestMapping("/status/update") public ResponseData status(@Validated(BaseEntity.Status.class) @RequestBody DeviceDto deviceDto) { int count = new QDevice().deviceId.eq(deviceDto.getDeviceId()).findCount(); if (count <= 0) { From 29e94923991163d51a6b51aaeda7f33927714c5a Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 11 Oct 2021 20:26:43 +0800 Subject: [PATCH 488/763] [fix]: fix device log --- .../zmops/iot/web/device/service/DeviceLogService.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java index 4dcab43d..12bac932 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java @@ -42,7 +42,7 @@ public List list(String deviceId, String logType, Long timeFrom, L alarmList.forEach(alarm -> { deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_ALARM).content(alarm.getName()) .triggerTime(LocalDateTimeUtils.convertDateToLocalDateTime(Integer.parseInt(alarm.getClock()))) - .status("0".equals(alarm.getRClock()) ? "已解决" : "未解决").build()); + .status("0".equals(alarm.getRClock()) ? "未解决" : "已解决").build()); }); } } @@ -57,7 +57,7 @@ public List list(String deviceId, String logType, Long timeFrom, L alarmList.forEach(alarm -> { deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_ALARM).content(alarm.getName()) .triggerTime(LocalDateTimeUtils.convertDateToLocalDateTime(Integer.parseInt(alarm.getClock()))) - .status("0".equals(alarm.getRClock()) ? "已解决" : "未解决").build()); + .status("0".equals(alarm.getRClock()) ? "未解决" : "已解决").build()); }); } } @@ -97,7 +97,7 @@ public Pager getLogByPage(String deviceId, String logType, Long ti alarmList.forEach(alarm -> { deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_ALARM).content(alarm.getName()) .triggerTime(LocalDateTimeUtils.convertDateToLocalDateTime(Integer.parseInt(alarm.getClock()))) - .status("0".equals(alarm.getRClock()) ? "已解决" : "未解决").build()); + .status("0".equals(alarm.getRClock()) ? "未解决" : "已解决").build()); }); } } @@ -131,7 +131,7 @@ public Pager getLogByPage(String deviceId, String logType, Long ti alarmList.forEach(alarm -> { deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_ALARM).content(alarm.getName()) .triggerTime(LocalDateTimeUtils.convertDateToLocalDateTime(Integer.parseInt(alarm.getClock()))) - .status("0".equals(alarm.getRClock()) ? "已解决" : "未解决").build()); + .status("0".equals(alarm.getRClock()) ? "未解决" : "已解决").build()); }); } } From 68ec1300b267d6be738cf773338d1aecad5fa675 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 11 Oct 2021 21:56:48 +0800 Subject: [PATCH 489/763] [feat]: add device service execute log --- .../rest/DeviceStatusWebhookController.java | 71 ++++++++++++++++++- .../zmops/iot/rest/ProductionController.java | 9 --- .../iot/web/alarm/service/AlarmService.java | 29 +++++++- .../service/work/DeviceEventLogWorker.java | 46 ++++++++++++ .../service/work/DeviceServiceLogWorker.java | 62 ++++++++++++++++ 5 files changed, 203 insertions(+), 14 deletions(-) delete mode 100644 zeus-rest/src/main/java/com/zmops/iot/rest/ProductionController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceEventLogWorker.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java index 71ac5d96..940cd878 100644 --- a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java @@ -3,15 +3,22 @@ import com.alibaba.fastjson.JSON; import com.zmops.iot.async.executor.Async; import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.web.alarm.service.AlarmNoticeWorker; +import com.zmops.iot.web.alarm.service.AlarmService; import com.zmops.iot.web.device.service.work.DeviceOnlineWorker; +import com.zmops.iot.web.device.service.work.DeviceServiceLogWorker; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * @author nantian created at 2021/8/7 14:56 @@ -21,6 +28,7 @@ @RestController @RequestMapping("/device") +@Slf4j public class DeviceStatusWebhookController { @Autowired @@ -29,6 +37,12 @@ public class DeviceStatusWebhookController { @Autowired DeviceOnlineWorker deviceOnlineWorker; + @Autowired + AlarmService alarmService; + + @Autowired + DeviceServiceLogWorker deviceServiceLogWorker; + /** * 在线状态 回调 * @@ -39,7 +53,7 @@ public class DeviceStatusWebhookController { public ResponseData deviceStatusWebhook(@RequestBody Map params) { - System.out.println(JSON.toJSONString(params)); + log.debug("--------设备上下线规则触发----------" + JSON.toJSONString(params)); WorkerWrapper, Boolean> deviceOnlineWork = WorkerWrapper., Boolean>builder().id("deviceOnlineWork") .worker(deviceOnlineWorker).param(params) @@ -64,7 +78,7 @@ public ResponseData deviceStatusWebhook(@RequestBody Map params) public ResponseData deviceProblemWebhook(@RequestBody Map params) { - System.out.println(JSON.toJSONString(params)); + log.debug("--------设备告警触发----------" + JSON.toJSONString(params)); WorkerWrapper, Boolean> alarmNoticeWork = WorkerWrapper., Boolean>builder().id("alarmNoticeWork") .worker(alarmNoticeWorker).param(params) @@ -76,6 +90,59 @@ public ResponseData deviceProblemWebhook(@RequestBody Map params e.printStackTrace(); } + return ResponseData.success("OK"); + } + + /** + * 设备服务 回调 + * + * @param triggerId webhook 回调参数 + * @return ResponseData + */ + @RequestMapping("/service") + public ResponseData deviceServiceWebhook(@RequestParam("triggerId") String triggerId) { + + + log.debug("--------设备联动触发----------" + triggerId); + Map alarmInfo = new ConcurrentHashMap<>(3); + + ProductEventRelation productEventRelation = new QProductEventRelation().zbxId.eq(triggerId).findOne(); + if (productEventRelation == null) { + return ResponseData.success("OK"); + } + + alarmInfo.put("eventRuleId", productEventRelation.getEventRuleId()); + alarmInfo.put("relationId", productEventRelation.getRelationId()); + +// alarmService.action(alarmInfo); + + WorkerWrapper, Boolean> deviceServiceLogWork = WorkerWrapper., Boolean>builder().id("deviceServiceLogWorker") + .worker(deviceServiceLogWorker).param(alarmInfo) + .build(); + + try { + Async.work(1000, deviceServiceLogWork).awaitFinish(); + } catch (Exception e) { + e.printStackTrace(); + } + + + return ResponseData.success("OK"); + } + + /** + * 设备服务 回调 + * + * @param params webhook 回调参数 + * @return ResponseData + */ + @RequestMapping("/event") + public ResponseData deviceEventWebhook(@RequestBody Map params) { + + + log.debug("--------设备事件触发----------" + params); + + return ResponseData.success("OK"); } } diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/ProductionController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/ProductionController.java deleted file mode 100644 index f1cca95a..00000000 --- a/zeus-rest/src/main/java/com/zmops/iot/rest/ProductionController.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.zmops.iot.rest; - -/** - * @author nantian created at 2021/7/23 23:55 - *

- * 产品管理 Controller - */ -public class ProductionController { -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 3da2f1d1..3bda9268 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -1,6 +1,7 @@ package com.zmops.iot.web.alarm.service; import com.alibaba.fastjson.JSONObject; +import com.google.common.base.Joiner; import com.zmops.iot.domain.alarm.AlarmMessage; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.query.QDevice; @@ -21,7 +22,6 @@ import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.util.Assert; import java.util.*; import java.util.stream.Collectors; @@ -66,6 +66,29 @@ public void alarm(Map alarmInfo) { } } + public void action(Map alarmInfo) { + List deviceIds = (List) alarmInfo.get("hostname"); + String serviceName = (String) alarmInfo.get("serviceName"); + + if (ToolUtil.isEmpty(deviceIds) || ToolUtil.isEmpty(serviceName)) { + return; + } + + List deviceList = new QDevice().deviceId.in(deviceIds).findList(); + List deviceName = deviceList.parallelStream().map(Device::getName).collect(Collectors.toList()); + + List alarmMessages = new ArrayList<>(); + + if (ToolUtil.isNotEmpty(deviceList)) { + String alarmmessage = "设备:" + Joiner.on(",").join(deviceName) + "触发联动服务,服务名称:" + serviceName; + alarmMessages.add(AlarmMessage.builder().alarmMessage(alarmmessage).build()); + alarmCallbacks.forEach(alarmCallback -> { +// if (alarmCallback.getType().equals("welink")) { + alarmCallback.doAlarm(alarmMessages); +// } + }); + } + } public Pager getAlarmByPage(AlarmParam alarmParam) { @@ -130,7 +153,7 @@ public List getAlarmList(AlarmParam alarmParam) { } List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Objects::toString).collect(Collectors.toList()); List ruleList = DB.findDto(ProductEventRuleDto.class, "select d.event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id," + - "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") + "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") .setParameter("zbxIds", triggerIds).findList(); Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); @@ -177,7 +200,7 @@ public List getEventList(AlarmParam alarmParam) { } List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Objects::toString).collect(Collectors.toList()); List ruleList = DB.findDto(ProductEventRuleDto.class, "select event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id," + - "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") + "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") .setParameter("zbxIds", triggerIds).findList(); Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceEventLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceEventLogWorker.java new file mode 100644 index 00000000..242a2ae2 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceEventLogWorker.java @@ -0,0 +1,46 @@ +package com.zmops.iot.web.device.service.work; + + +import com.zmops.iot.async.callback.IWorker; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.util.ToolUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author yefei + *

+ * 更新设备 在线状态 + */ +@Slf4j +@Component +public class DeviceEventLogWorker implements IWorker, Boolean> { + + @Override + public Boolean action(Map param, Map> allWrappers) { + log.debug("插入 事件 日志…………"); + + String deviceId = param.get("hostname"); + if (ToolUtil.isEmpty(deviceId)) { + return false; + } + Device device = new QDevice().deviceId.eq(deviceId).findOne(); + if (null == device) { + return false; + } + + + return true; + } + + + @Override + public Boolean defaultValue() { + return true; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java new file mode 100644 index 00000000..c43fecad --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java @@ -0,0 +1,62 @@ +package com.zmops.iot.web.device.service.work; + + +import com.zmops.iot.async.callback.IWorker; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.device.ServiceExecuteRecord; +import com.zmops.iot.domain.product.ProductEventService; +import com.zmops.iot.domain.product.ProductService; +import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.domain.product.query.QProductService; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 更新设备 在线状态 + */ +@Slf4j +@Component +public class DeviceServiceLogWorker implements IWorker, Boolean> { + + @Override + public Boolean action(Map param, Map> allWrappers) { + log.debug("插入 服务 日志…………"); + + long eventRuleId = (long) param.get("eventRuleId"); + String relationId = (String) param.get("relationId"); + + List productEventServiceList = new QProductEventService().eventRuleId.eq(eventRuleId).deviceId.eq(relationId).findList(); + List serviceIds = productEventServiceList.parallelStream().map(ProductEventService::getServiceId).collect(Collectors.toList()); + + List productServiceList = new QProductService().id.in(serviceIds).findList(); + Map productServiceMap = productServiceList.parallelStream().collect(Collectors.toMap(ProductService::getId, o -> o)); + + List serviceExecuteRecordList = new ArrayList<>(); + productEventServiceList.forEach(productEventService -> { + ServiceExecuteRecord serviceExecuteRecord = new ServiceExecuteRecord(); + serviceExecuteRecord.setDeviceId(productEventService.getDeviceId()); + //TODO 执行的参数 + serviceExecuteRecord.setServiceName(Optional.ofNullable(productServiceMap.get(productEventService.getServiceId())).map(ProductService::getName).orElse("")); + serviceExecuteRecordList.add(serviceExecuteRecord); + }); + DB.saveAll(serviceExecuteRecordList); + + return true; + } + + + @Override + public Boolean defaultValue() { + return true; + } + +} From bc9a31e2bc0e4fe54a38d4b029478fd8cb6e005e Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 12 Oct 2021 09:14:17 +0800 Subject: [PATCH 490/763] [fix]: fix device log list --- .../iot/web/device/controller/DeviceLogController.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java index 8f84aff7..a452b93e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java @@ -1,6 +1,8 @@ package com.zmops.iot.web.device.controller; +import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.device.dto.DeviceLogDto; import com.zmops.iot.web.device.dto.param.DeviceLogParam; import com.zmops.iot.web.device.service.DeviceLogService; import org.springframework.beans.factory.annotation.Autowired; @@ -29,8 +31,9 @@ public ResponseData list(@RequestParam(value = "deviceId") String deviceId, } @RequestMapping("getLogByPage") - public ResponseData getLogByPage(@RequestBody DeviceLogParam deviceLogParam) { + public Pager getLogByPage(@RequestBody DeviceLogParam deviceLogParam) { - return ResponseData.success(deviceLogService.getLogByPage(deviceLogParam.getDeviceId(), deviceLogParam.getLogType(), deviceLogParam.getTimeFrom(), deviceLogParam.getTimeTill(), deviceLogParam.getPage(), deviceLogParam.getMaxRow())); + return deviceLogService.getLogByPage(deviceLogParam.getDeviceId(), deviceLogParam.getLogType(), deviceLogParam.getTimeFrom(), + deviceLogParam.getTimeTill(), deviceLogParam.getPage(), deviceLogParam.getMaxRow()); } } From 6b5eb6765898cf1f3b2b340a1cf775c74bf07f8b Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 12 Oct 2021 09:39:36 +0800 Subject: [PATCH 491/763] [feat]: product attribute add valuemapid --- .../java/com/zmops/iot/domain/product/ProductAttribute.java | 2 ++ .../main/java/com/zmops/iot/web/product/dto/ProductAttr.java | 2 ++ .../main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java | 2 ++ 3 files changed, 6 insertions(+) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java index b9d7b2c3..6cf7dcb5 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java @@ -46,4 +46,6 @@ public class ProductAttribute extends BaseEntity { private Integer delay; private String unit; + + private String valuemapId; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java index d8d59298..834c5b1f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java @@ -68,6 +68,8 @@ public class ProductAttr { //取数间隔单位 private String unit; + private String valuemapId; + LocalDateTime createTime; LocalDateTime updateTime; Long createUser; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java index d07bda20..c0fedd8a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java @@ -76,4 +76,6 @@ public class ProductAttrDto { private String unit; private String error; + + private String valuemapId; } From 801482bec77794ab7d03cdd8884101f65c9bcf09 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 12 Oct 2021 10:42:11 +0800 Subject: [PATCH 492/763] [feat]: add product attribute valuemapid --- .../java/com/zmops/iot/domain/product/ProductAttribute.java | 2 +- .../com/zmops/iot/web/device/service/DeviceModelService.java | 5 +++-- .../iot/web/device/service/work/DeviceServiceLogWorker.java | 2 ++ .../main/java/com/zmops/iot/web/product/dto/ProductAttr.java | 2 -- .../java/com/zmops/iot/web/product/dto/ProductAttrDto.java | 2 -- .../zmops/iot/web/product/service/ProductModelService.java | 1 + 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java index 6cf7dcb5..096fae11 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java @@ -47,5 +47,5 @@ public class ProductAttribute extends BaseEntity { private String unit; - private String valuemapId; + private String valuemapid; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index 79937817..e0bb38d9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -173,8 +173,9 @@ private ProductAttribute buildProdAttribute(ProductAttribute prodAttribute, Prod prodAttribute.setUnits(productAttr.getUnits()); prodAttribute.setDepAttrId(productAttr.getDepAttrId()); prodAttribute.setValueType(productAttr.getValueType()); - prodAttribute.setDelay(prodAttribute.getDelay()); - prodAttribute.setUnit(prodAttribute.getUnit()); + prodAttribute.setDelay(productAttr.getDelay()); + prodAttribute.setUnit(productAttr.getUnit()); + prodAttribute.setValuemapid(productAttr.getValuemapid()); } prodAttribute.setProductId(productAttr.getProductId()); prodAttribute.setRemark(productAttr.getRemark()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java index c43fecad..95acdb2e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java @@ -12,6 +12,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -46,6 +47,7 @@ public Boolean action(Map param, Map serviceExecuteRecord.setDeviceId(productEventService.getDeviceId()); //TODO 执行的参数 serviceExecuteRecord.setServiceName(Optional.ofNullable(productServiceMap.get(productEventService.getServiceId())).map(ProductService::getName).orElse("")); + serviceExecuteRecord.setCreateTime(LocalDateTime.now()); serviceExecuteRecordList.add(serviceExecuteRecord); }); DB.saveAll(serviceExecuteRecordList); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java index 834c5b1f..d8d59298 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java @@ -68,8 +68,6 @@ public class ProductAttr { //取数间隔单位 private String unit; - private String valuemapId; - LocalDateTime createTime; LocalDateTime updateTime; Long createUser; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java index c0fedd8a..d07bda20 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java @@ -76,6 +76,4 @@ public class ProductAttrDto { private String unit; private String error; - - private String valuemapId; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index 4a7e3fe8..066cd9c8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -170,6 +170,7 @@ private ProductAttribute buildProdAttribute(ProductAttribute prodAttribute, Prod prodAttribute.setValueType(productAttr.getValueType()); prodAttribute.setAttrId(productAttr.getAttrId()); prodAttribute.setDepAttrId(productAttr.getDepAttrId()); + prodAttribute.setValuemapid(productAttr.getValuemapid()); return prodAttribute; } From 91e69a5bfbfe5a41e5856a599ab8f0184a024684 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 12 Oct 2021 12:13:56 +0800 Subject: [PATCH 493/763] [fix]: fix device event trigger --- .../web/device/controller/DeviceEventTriggerController.java | 3 +++ .../iot/web/product/service/ProductAttributeEventService.java | 3 ++- .../com/zmops/iot/web/product/service/ProductModelService.java | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index c36bbea4..83ce617c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -151,7 +151,10 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn if (count == 0) { throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); } + //来自产品的告警规则 只能修改备注 + count = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).inherit.eq(InheritStatus.YES.getCode()) + .findCount(); if (count > 1) { DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).eq("relationId", eventRule.getDeviceId()) .asUpdate().set("remark", eventRule.getRemark()).update(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java index cbd50c78..5421b63a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -105,7 +105,8 @@ public List list(ProductAttrParam productAttr) { * @return */ public ProductAttrDto detail(Long attrId) { - ProductAttrDto attr = new QProductAttributeEvent().attrId.eq(attrId).asDto(ProductAttrDto.class).findOne(); +// ProductAttrDto attr = new QProductAttributeEvent().attrId.eq(attrId).asDto(ProductAttrDto.class).findOne(); + ProductAttrDto attr = DB.findDto(ProductAttrDto.class, "select * from product_attribute_event where attr_id=:attrId").setParameter("attrId", attrId).findOne(); if (attr == null || null == attr.getZbxId()) { return attr; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index 066cd9c8..32395e45 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -102,7 +102,8 @@ public List list(ProductAttrParam productAttr) { * @return */ public ProductAttrDto detail(Long attrId) { - ProductAttrDto attr = new QProductAttribute().attrId.eq(attrId).asDto(ProductAttrDto.class).findOne(); +// ProductAttrDto attr = new QProductAttribute().attrId.eq(attrId).asDto(ProductAttrDto.class).findOne(); + ProductAttrDto attr = DB.findDto(ProductAttrDto.class, "select * from product_attribute where attr_id=:attrId").setParameter("attrId", attrId).findOne(); if (null == attr.getZbxId()) { return attr; From 5b30372408c2ac1e93f9074c7cc19b83f6f79d89 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 12 Oct 2021 12:21:42 +0800 Subject: [PATCH 494/763] [fix]: fix item ftl --- .../src/main/resources/api-json/item/item.trapper.update.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl b/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl index 8d786913..94db969e 100644 --- a/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl +++ b/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl @@ -11,7 +11,7 @@ "master_itemid":${masterItemid}, "value_type": ${valueType}, - <#if valuemapid??> + <#if valuemapid?? && valuemapid != ''> "valuemapid":${valuemapid}, <#if valueType == '0' || valueType == '3'> From b80e081900644362bb1f2086ba9fbabfae0690df Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 12 Oct 2021 12:58:30 +0800 Subject: [PATCH 495/763] [fix]: fix product attribute list --- .../device/service/DeviceModelService.java | 35 ++++++++++++++++--- .../service/ProductAttributeEventService.java | 35 ++++++++++++++++--- .../product/service/ProductModelService.java | 35 ++++++++++++++++--- .../service/work/UpdateAttributeWorker.java | 1 + 4 files changed, 91 insertions(+), 15 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index e0bb38d9..f421b137 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -21,6 +21,7 @@ import com.zmops.zeus.driver.entity.ZbxProcessingStep; import com.zmops.zeus.driver.service.ZbxItem; import io.ebean.DB; +import io.ebean.DtoQuery; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -99,17 +100,41 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr * @return */ public List list(ProductAttrParam productAttr) { - QProductAttribute qProductAttribute = new QProductAttribute(); +// QProductAttribute qProductAttribute = new QProductAttribute(); +// if (null != productAttr.getProdId()) { +// qProductAttribute.productId.eq(productAttr.getProdId()); +// } +// if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { +// qProductAttribute.name.contains(productAttr.getAttrName()); +// } +// if (ToolUtil.isNotEmpty(productAttr.getKey())) { +// qProductAttribute.key.contains(productAttr.getKey()); +// } +// return qProductAttribute.asDto(ProductAttrDto.class).findList(); + StringBuilder sql = new StringBuilder("select * from product_attribute where 1=1"); if (null != productAttr.getProdId()) { - qProductAttribute.productId.eq(productAttr.getProdId()); + sql.append(" and product_id = :productId"); } if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { - qProductAttribute.name.contains(productAttr.getAttrName()); + sql.append(" and name like :attrName"); } if (ToolUtil.isNotEmpty(productAttr.getKey())) { - qProductAttribute.key.contains(productAttr.getKey()); + sql.append(" and key like :key"); + } + sql.append(" order by create_time desc"); + DtoQuery dto = DB.findDto(ProductAttrDto.class, sql.toString()); + + if (null != productAttr.getProdId()) { + dto.setParameter("productId", productAttr.getProdId()); } - return qProductAttribute.asDto(ProductAttrDto.class).findList(); + if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { + dto.setParameter("attrName", "%" + productAttr.getAttrName() + "%"); + } + if (ToolUtil.isNotEmpty(productAttr.getKey())) { + dto.setParameter("key", "%" + productAttr.getKey() + "%"); + } + + return dto.findList(); } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java index 5421b63a..90bafa80 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -27,6 +27,7 @@ import com.zmops.zeus.driver.entity.ZbxProcessingStep; import com.zmops.zeus.driver.service.ZbxItem; import io.ebean.DB; +import io.ebean.DtoQuery; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -85,17 +86,41 @@ public Pager prodAttributeEventList(ProductAttrParam productAttr * @return */ public List list(ProductAttrParam productAttr) { - QProductAttributeEvent qProductAttribute = new QProductAttributeEvent(); +// QProductAttributeEvent qProductAttribute = new QProductAttributeEvent(); +// if (null != productAttr.getProdId()) { +// qProductAttribute.productId.eq(productAttr.getProdId()); +// } +// if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { +// qProductAttribute.name.contains(productAttr.getAttrName()); +// } +// if (ToolUtil.isNotEmpty(productAttr.getKey())) { +// qProductAttribute.key.contains(productAttr.getKey()); +// } +// return qProductAttribute.orderBy(" create_time desc").asDto(ProductAttrDto.class).findList(); + StringBuilder sql = new StringBuilder("select * from product_attribute_event where 1=1"); if (null != productAttr.getProdId()) { - qProductAttribute.productId.eq(productAttr.getProdId()); + sql.append(" and product_id = :productId"); } if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { - qProductAttribute.name.contains(productAttr.getAttrName()); + sql.append(" and name like :attrName"); } if (ToolUtil.isNotEmpty(productAttr.getKey())) { - qProductAttribute.key.contains(productAttr.getKey()); + sql.append(" and key like :key"); + } + sql.append(" order by create_time desc"); + DtoQuery dto = DB.findDto(ProductAttrDto.class, sql.toString()); + + if (null != productAttr.getProdId()) { + dto.setParameter("productId", productAttr.getProdId()); + } + if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { + dto.setParameter("attrName", "%" + productAttr.getAttrName() + "%"); } - return qProductAttribute.orderBy(" create_time desc").asDto(ProductAttrDto.class).findList(); + if (ToolUtil.isNotEmpty(productAttr.getKey())) { + dto.setParameter("key", "%" + productAttr.getKey() + "%"); + } + + return dto.findList(); } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index 32395e45..3c787250 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -23,6 +23,7 @@ import com.zmops.zeus.driver.entity.ZbxProcessingStep; import com.zmops.zeus.driver.service.ZbxItem; import io.ebean.DB; +import io.ebean.DtoQuery; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -82,17 +83,41 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr * @return */ public List list(ProductAttrParam productAttr) { - QProductAttribute qProductAttribute = new QProductAttribute(); +// QProductAttribute qProductAttribute = new QProductAttribute(); +// if (null != productAttr.getProdId()) { +// qProductAttribute.productId.eq(productAttr.getProdId()); +// } +// if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { +// qProductAttribute.name.contains(productAttr.getAttrName()); +// } +// if (ToolUtil.isNotEmpty(productAttr.getKey())) { +// qProductAttribute.key.contains(productAttr.getKey()); +// } +// return qProductAttribute.orderBy(" create_time desc").asDto(ProductAttrDto.class).findList(); + StringBuilder sql = new StringBuilder("select * from product_attribute where 1=1"); if (null != productAttr.getProdId()) { - qProductAttribute.productId.eq(productAttr.getProdId()); + sql.append(" and product_id = :productId"); } if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { - qProductAttribute.name.contains(productAttr.getAttrName()); + sql.append(" and name like :attrName"); } if (ToolUtil.isNotEmpty(productAttr.getKey())) { - qProductAttribute.key.contains(productAttr.getKey()); + sql.append(" and key like :key"); + } + sql.append(" order by create_time desc"); + DtoQuery dto = DB.findDto(ProductAttrDto.class, sql.toString()); + + if (null != productAttr.getProdId()) { + dto.setParameter("productId", productAttr.getProdId()); + } + if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { + dto.setParameter("attrName", "%" + productAttr.getAttrName() + "%"); } - return qProductAttribute.orderBy(" create_time desc").asDto(ProductAttrDto.class).findList(); + if (ToolUtil.isNotEmpty(productAttr.getKey())) { + dto.setParameter("key", "%" + productAttr.getKey() + "%"); + } + + return dto.findList(); } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java index 5b777669..703d4bb5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java @@ -41,6 +41,7 @@ public Boolean action(ProductAttr productAttr, Map> newProductAttribute.setUnits(productAttr.getUnits()); newProductAttribute.setSource(productAttr.getSource()); newProductAttribute.setValueType(productAttr.getValueType()); + newProductAttribute.setValuemapid(productAttr.getValuemapid()); newList.add(newProductAttribute); } DB.updateAll(newList); From c28e134a67b947939cec3a8ec80adc6c25e1cb39 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 12 Oct 2021 14:00:40 +0800 Subject: [PATCH 496/763] [fix]: fix init sql --- dist-material/bin/sql/zeus-iot.sql | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/dist-material/bin/sql/zeus-iot.sql b/dist-material/bin/sql/zeus-iot.sql index 33677cbd..4056dbed 100644 --- a/dist-material/bin/sql/zeus-iot.sql +++ b/dist-material/bin/sql/zeus-iot.sql @@ -12,7 +12,7 @@ Target Server Version : 130004 File Encoding : 65001 - Date: 11/10/2021 09:58:57 + Date: 12/10/2021 10:04:27 */ @@ -411,7 +411,8 @@ CREATE TABLE "public"."product_attribute" ( "dep_attr_id" int8, "template_id" int8, "delay" int2, - "unit" varchar(4) COLLATE "pg_catalog"."default" + "unit" varchar(4) COLLATE "pg_catalog"."default", + "valuemapid" varchar(8) COLLATE "pg_catalog"."default" ) ; COMMENT ON COLUMN "public"."product_attribute"."attr_id" IS '属性ID'; @@ -431,6 +432,7 @@ COMMENT ON COLUMN "public"."product_attribute"."dep_attr_id" IS '依赖属性ID' COMMENT ON COLUMN "public"."product_attribute"."template_id" IS '继承的属性ID'; COMMENT ON COLUMN "public"."product_attribute"."delay" IS '取数间隔'; COMMENT ON COLUMN "public"."product_attribute"."unit" IS '取数间隔单位 s m h '; +COMMENT ON COLUMN "public"."product_attribute"."valuemapid" IS '值映射ID'; -- ---------------------------- -- Records of product_attribute @@ -523,7 +525,8 @@ CREATE TABLE "public"."product_event_expression" ( "unit" varchar(16) COLLATE "pg_catalog"."default", "product_attr_id" int8, "product_attr_type" varchar(4) COLLATE "pg_catalog"."default", - "period" varchar(8) COLLATE "pg_catalog"."default" + "period" varchar(8) COLLATE "pg_catalog"."default", + "attr_value_type" varchar(8) COLLATE "pg_catalog"."default" ) ; COMMENT ON COLUMN "public"."product_event_expression"."event_exp_id" IS '告警函数ID'; @@ -533,6 +536,7 @@ COMMENT ON COLUMN "public"."product_event_expression"."device_id" IS '设备ID'; COMMENT ON COLUMN "public"."product_event_expression"."product_attr_id" IS '属性ID'; COMMENT ON COLUMN "public"."product_event_expression"."product_attr_type" IS '属性类型 属性 事件'; COMMENT ON COLUMN "public"."product_event_expression"."period" IS '取值周期 时间 周期'; +COMMENT ON COLUMN "public"."product_event_expression"."attr_value_type" IS '属性值类型'; -- ---------------------------- -- Records of product_event_expression @@ -631,13 +635,15 @@ CREATE TABLE "public"."product_service_param" ( "service_id" int8, "key" varchar(32) COLLATE "pg_catalog"."default", "name" varchar(32) COLLATE "pg_catalog"."default", - "remark" varchar(255) COLLATE "pg_catalog"."default" + "remark" varchar(255) COLLATE "pg_catalog"."default", + "value" varchar(255) COLLATE "pg_catalog"."default" ) ; COMMENT ON COLUMN "public"."product_service_param"."service_id" IS '服务ID'; COMMENT ON COLUMN "public"."product_service_param"."key" IS '参数标识'; COMMENT ON COLUMN "public"."product_service_param"."name" IS '参数名称'; COMMENT ON COLUMN "public"."product_service_param"."remark" IS '备注'; +COMMENT ON COLUMN "public"."product_service_param"."value" IS '参数值'; -- ---------------------------- -- Records of product_service_param @@ -797,14 +803,14 @@ INSERT INTO "public"."sys_config" VALUES (1145915627211370499, '文件上传路 INSERT INTO "public"."sys_config" VALUES (1143324237579165697, '验证码开关', 'ZEUS_KAPTCHA_OPEN', 'Y', 1106120265689055233, 'DISABLE', '是否开启验证码', 1, 1, '2019-06-24 12:46:43', '2021-08-03 16:38:12.432', 'ENABLE'); INSERT INTO "public"."sys_config" VALUES (1145915627211370498, 'Zeus发布的编号', 'ZEUS_SYSTEM_RELEASE_VERSION', 'N', NULL, '10', '用于防止浏览器缓存相关的js和css', 1, 1, '2019-07-02 12:42:30', '2021-08-03 16:38:12.432', 'ENABLE'); INSERT INTO "public"."sys_config" VALUES (1143468867767607297, '默认系统密码', 'ZEUS_DEFAULT_PASSWORD', 'N', NULL, '111111', '默认系统密码', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370496, '全局主机组Id', 'ZEUS_HOST_GROUP_ID', 'Y', NULL, '19', '全局主机和模板组ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468867767607298, '用户角色ID', 'ZEUS_ADMIN_ROLE_ID', 'N', NULL, '3', '用户角色ID', 1, 1, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370497, '离线回调ActionId', 'ZEUS_OFFLINE_ACTION_ID', 'Y', NULL, '7', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); INSERT INTO "public"."sys_config" VALUES (1145915627211370503, '告警回调ActionId', 'ZEUS_ALARM_ACTION_ID', 'Y', NULL, '8', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468867767607208, '单点登录开关', 'ZEUS_SIGN_IN', 'N', NULL, 'DISABLE', '是否启用单点登录', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); INSERT INTO "public"."sys_config" VALUES (1145915627211370504, '动作回调ActionId', 'ZEUS_EXEC_ACTION_ID', 'Y', NULL, '9', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); INSERT INTO "public"."sys_config" VALUES (1145915627211370505, '事件回调ActionId', 'ZEUS_EVENT_ACTION_ID', 'Y', NULL, '10', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); -INSERT INTO "public"."sys_config" VALUES (1143468867767607208, '单点登录开关', 'ZEUS_SIGN_IN', 'N', NULL, 'DISABLE', '是否启用单点登录', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); INSERT INTO "public"."sys_config" VALUES (1143468867767607207, '默认租户角色ID', 'ZEUS_TENANT_ROLE_ID', 'N', NULL, '1', '默认租户角色ID', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); -INSERT INTO "public"."sys_config" VALUES (1145915627211370496, '全局主机组Id', 'ZEUS_HOST_GROUP_ID', 'Y', NULL, '19', '全局主机和模板组ID', NULL, NULL, NULL, NULL, 'DISABLE'); -INSERT INTO "public"."sys_config" VALUES (1143468867767607298, '用户角色ID', 'ZEUS_ADMIN_ROLE_ID', 'N', NULL, '3', '用户角色ID', 1, 1, NULL, NULL, 'DISABLE'); -INSERT INTO "public"."sys_config" VALUES (1145915627211370497, '离线回调ActionId', 'ZEUS_OFFLINE_ACTION_ID', 'Y', NULL, '7', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); -- ---------------------------- -- Table structure for sys_dict From db6a65e97767ae74dbe19c85cfa9f18b1584098a Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 12 Oct 2021 14:49:45 +0800 Subject: [PATCH 497/763] [fix]: async zbx device status --- .../java/com/zmops/zeus/driver/service/ZbxHost.java | 11 +++++++++++ .../resources/api-json/host/host.status.update.ftl | 10 ++++++++++ .../iot/web/device/controller/DeviceController.java | 6 +++--- .../zmops/iot/web/device/service/DeviceService.java | 5 ++++- 4 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 zeus-driver/src/main/resources/api-json/host/host.status.update.ftl diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java index 908b8f0a..bb06ab1c 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java @@ -48,6 +48,17 @@ String hostCreate(@ParamName("hostName") String hostName, String hostUpdate(@ParamName("hostid") String hostid, @ParamName("groupids") List groupids, @ParamName("templateid") String templateid); + /** + * 修改主机状态 + * + * @param hostid 主机ID + * @param status 主机状态 + * @return + */ + @Post + @JsonPath("/host/host.status.update") + String hostStatusUpdate(@ParamName("hostid") String hostid, + @ParamName("status") String status); /** * 删除主机 diff --git a/zeus-driver/src/main/resources/api-json/host/host.status.update.ftl b/zeus-driver/src/main/resources/api-json/host/host.status.update.ftl new file mode 100644 index 00000000..49ad4bdd --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/host/host.status.update.ftl @@ -0,0 +1,10 @@ +{ + "jsonrpc": "2.0", + "method": "host.update", + "params": { + "hostid":"${hostid}", + "status":"${status}" + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java index 48644925..a5f500fc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java @@ -112,11 +112,11 @@ public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody Devi @Permission(code = "dev_update") @RequestMapping("/status/update") public ResponseData status(@Validated(BaseEntity.Status.class) @RequestBody DeviceDto deviceDto) { - int count = new QDevice().deviceId.eq(deviceDto.getDeviceId()).findCount(); - if (count <= 0) { + Device device = new QDevice().deviceId.eq(deviceDto.getDeviceId()).findOne(); + if (null == device) { throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); } - deviceService.status(deviceDto.getStatus(),deviceDto.getDeviceId()); + deviceService.status(deviceDto.getStatus(),deviceDto.getDeviceId(),device.getZbxId()); return ResponseData.success(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 28b36a53..d7596eb0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -521,7 +521,10 @@ private JSONArray getZbxHostInfo(String deviceId) { * @param deviceId * @return */ - public void status(String status, String deviceId) { + public void status(String status, String deviceId, String zbxId) { + if (ToolUtil.isNotEmpty(zbxId)) { + zbxHost.hostStatusUpdate(zbxId, "ENABLE".equals(status) ? "0" : "1"); + } DB.update(Device.class).where().eq("device_id", deviceId).asUpdate().set("status", status).setNull("online").update(); } } From b4f47fabaa664efdbc117793a90f5061512460f0 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Tue, 12 Oct 2021 15:06:11 +0800 Subject: [PATCH 498/763] [docs]: only install zabbix server --- docs/centos/install.sh | 129 ++++++++++++++++++++++++++--------------- docs/ubuntu/install.sh | 37 ++++++++---- 2 files changed, 107 insertions(+), 59 deletions(-) diff --git a/docs/centos/install.sh b/docs/centos/install.sh index 49ab904a..e4d2fe9c 100755 --- a/docs/centos/install.sh +++ b/docs/centos/install.sh @@ -5,10 +5,12 @@ ROOT_UID=0 release=Centos basename=$(pwd) zabbixsrc=$basename/zabbix-5.4.3 -ZABBIX_HOME=/opt/zeus/zabbix +INSTALLDIR=/opt/zeus +ZABBIX_HOME=$INSTALLDIR/zabbix PHP_CONF=/etc/opt/rh/rh-php73 sqldir=$basename/zabbix-5.4.3/database/postgresql -PGDATA=/opt/zeus/pgdata +PGDATA=$INSTALLDIR/pgdata +zeusurl=https://packages.zmops.cn/zeus-iot/zeus-iot-bin.tar.gz function logprint() { if [ $? != 0 ]; then @@ -17,50 +19,54 @@ function logprint() { fi } -# 安装前准备 -## 系统环境检测 -if [ "$(uname)" != Linux ]; then - echo "Error: 该脚本只适用 Linux 系统" - exit -fi - -if [ "$UID" -ne "$ROOT_UID" ]; then - echo -e "Error: 请使用root账户执行安装" - exit -fi -### 操作系统 -if [ ! -f /etc/redhat-release ]; then - if [[ "$(cat /etc/issue)" =~ ^Ubuntu* ]]; then - release=Ubuntu +function syscheck() { + # 安装前准备 + ## 系统环境检测 + # + + if [ "$(uname)" != Linux ]; then + echo -e "\033[31m Error: 该脚本只适用 Linux 系统 \033[0m" + exit + fi + + if [ "$UID" -ne "$ROOT_UID" ]; then + echo -e "\033[31m Error: 请使用root账户执行安装 \033[0m" + exit + fi + ### 操作系统 + if [ ! -f /etc/redhat-release ]; then + if [[ "$(cat /etc/issue)" =~ ^Ubuntu* ]]; then + release=Ubuntu + fi fi -fi -### 网络 -if ! ping -c 3 mirrors.tuna.tsinghua.edu.cn &>/dev/null; then - echo "Error: 无法访问外网 。。。" - exit -fi - -### cpu、mem、disk -cores=$(grep 10)printf("%s\t%d\n",$7,$3/1024/1024)}' | grep -v -c "/boot") - -if [ "$cores" -lt 0 ] || [ "$memstotal" -lt 0 ] || [ "$disks" -eq 0 ]; then - echo "Error: 要求系统最低配置为 CPU 2核 内存 4GB 存储空间 100G" - exit -fi + ### 网络 + if ! ping -c 3 mirrors.tuna.tsinghua.edu.cn &>/dev/null; then + echo -e "\033[31m Error: 无法访问外网 。。。 \033[0m" + exit + fi + + ### cpu、mem、disk + cores=$(grep 10)printf("%s\t%d\n",$7,$3/1024/1024)}' | grep -v -c "/boot") + + if [ "$cores" -lt 2 ] || [ "$memstotal" -lt 4 ] || [ "$disks" -eq 100 ]; then + echo -e "\033[31m Error: 要求系统最低配置为 CPU 2核 内存 4GB 存储空间 100G \033[0m" + exit + fi +} ## 系统环境初始化 function InitSystem() { echo -e -n "\033[32mStep1: 初始化系统安装环境... \033[0m" if ! hostnamectl set-hostname zeus-server; then - echo "Error: 主机名修改失败" + echo -e "\033[31m Error: 主机名修改失败\033[0m" exit fi ### 修改时区 if ! ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime; then - echo "Error: 时区修改失败" + echo -e "\033[31m Error: 时区修改失败\033[0m" exit 0 fi @@ -78,11 +84,13 @@ function InitSystem() { echo "ulimit -SHn 65535" >>/etc/rc.local ### 添加用户 - groupadd --system zeus || true - useradd --system -g zeus zeus || true - + if ! id zeus; then + groupadd --system zeus || true + useradd --system -g zeus zeus || true + fi + ### 添加安装目录 - [ ! -d /opt/zeus ] && mkdir -p /opt/zeus + [ ! -d $INSTALLDIR ] && mkdir -p $INSTALLDIR echo -e "\033[32m [ OK ] \033[0m" } @@ -149,12 +157,12 @@ function PGInstall() { startfile=/usr/lib/systemd/system/postgresql-13.service #sed -i 's/\(^User\=\).*/\1zeus/g' $startfile #sed -i 's/\(^Group\=\).*/\1zeus/g' $startfile - sed -i 's/\(^Environment\=PGDATA\=\).*/\1\/opt\/zeus\/pgdata/g' $startfile + sed -i "s#\(^Environment\=PGDATA\=\).*#\1$INSTALLDIR\/pgdata#g" $startfile ### 初始化数据库 /usr/pgsql-13/bin/postgresql-13-setup initdb 1>/dev/null logprint "初始化PG错误" -# echo "shared_preload_libraries = 'timescaledb'" >>/opt/zeus/pgdata/postgresql.conf + #echo "shared_preload_libraries = 'timescaledb'" >>/opt/zeus/pgdata/postgresql.conf ### 启动数据库 systemctl enable postgresql-13 &>/dev/null systemctl start postgresql-13 @@ -186,7 +194,7 @@ function ZbxInstall() { ### 创建 zabbix 用户 groupadd --system zabbix || true - useradd --system -g zabbix -d /opt/zeus/zabbix -s /sbin/nologin -c "Zabbix Monitoring System" zabbix || true + useradd --system -g zabbix -d $INSTALLDIR/zabbix -s /sbin/nologin -c "Zabbix Monitoring System" zabbix || true wget -c https://cdn.zabbix.com/zabbix/sources/stable/5.4/zabbix-5.4.3.tar.gz -o /dev/null -O - | tar -xz logprint "下载zabbix源码失败,请检查网络。。。" @@ -312,7 +320,7 @@ function WebInstall() { yum -y install nginx 1>/dev/null - cd /opt/zeus + cd $INSTALLDIR ## 编辑 nginx 配置文件 tee /etc/nginx/conf.d/zabbix.conf </dev/null @@ -390,7 +398,8 @@ function taosinstall() { EOF ## 启动taos systemctl enable taosd &> /dev/null - systemctl start taosd + systemctl start taosd + logprint "taos安装失败" echo -e "\033[32m [ OK ] \033[0m" } @@ -398,13 +407,16 @@ EOF function ZeusInstall() { echo -e -n "\033[32mStep11: 安装 Zeus-IoT 服务。。。 \033[0m" - cd /opt/zeus || exit + cd $INSTALLDIR || exit ## 创建taos 数据库 taos -s "create database zeus_data" 1> /dev/null - wget -c https://packages.zmops.cn/zeus-iot/zeus-iot-bin.tar.gz -o /dev/null -O - | tar -xz + wget -c $zeusurl -o /dev/null -O - | tar -xz + logprint "zeusiot下载失败,检查网络" gettoken + logprint "zabbix-token获取失败" ## 数据库导入 sudo -u postgres createdb -E Unicode -T template0 zeus-iot + logprint "数据库创建失败" cat ./zeus-iot-bin/bin/sql/zeus-iot.sql | sudo -u postgres psql zeus-iot &>/dev/null logprint "文件未找到" sed -i "s%\(zbxApiToken: \).*%\1$token%" ./zeus-iot-bin/webapp/webapp.yml @@ -412,8 +424,30 @@ function ZeusInstall() { echo -e "\033[32m [ OK ] \033[0m" } +function clear() { + # 清理用户 + if ! id zeus; then + userdell zeus + fi + + # 清理应用 + ## 清理 zeus + status=`ps -ef | grep zeus-iot-bin | grep java | grep -v grep | awk '{print $2}' | wc -l` + + if [ $status -ne 0 ] + then + for i in `ps -ef | grep zeus-iot-bin | grep java | grep -v grep | awk '{print $2}'` + do + kill -9 $i + done + fi + + +} + ## +syscheck InitSystem AddInstallRepo PGInstall @@ -421,5 +455,6 @@ ZbxInstall PHPInstall WebInstall taosinstall -ZeusInstall +echo "zabbix 部分已安装成功,zeus iot 可以参照 www.zmops.com 官方文档自定义安装。" +# ZeusInstall # 安装结束 diff --git a/docs/ubuntu/install.sh b/docs/ubuntu/install.sh index 2742cd53..2a699dc6 100644 --- a/docs/ubuntu/install.sh +++ b/docs/ubuntu/install.sh @@ -51,6 +51,16 @@ function InitSystem() { echo "主机名修改失败" exit fi + + ## 关闭 IPV6 监听 + + echo " ">>/etc/sysctl.conf + echo "# made for disabled IPv6 in $(date +%F)">>/etc/sysctl.conf + echo 'net.ipv6.conf.all.disable_ipv6 = 1'>>/etc/sysctl.conf + echo 'net.ipv6.conf.default.disable_ipv6 = 1'>>/etc/sysctl.conf + echo 'net.ipv6.conf.lo.disable_ipv6 = 1'>>/etc/sysctl.conf + sysctl -p + ## 修改时区 if ! ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime; then echo "时区修改失败" @@ -58,7 +68,7 @@ function InitSystem() { fi ## 更新下载源 cp /etc/apt/sources.list /etc/apt/sources.listbak - sed -i 's%\(^deb https\:\/\/\).*\(/ubuntu.*\)%\1mirrors.tuna.tsinghua.edu.cn\2%g' /etc/apt/sources.list + sed -i 's%\(^deb http\{0,1\}\:\/\/\).*\(/ubuntu.*\)%\1mirrors.tuna.tsinghua.edu.cn\2%g' /etc/apt/sources.list echo -e "\033[32m [ OK ] \033[0m" } @@ -70,8 +80,8 @@ function AddInstallRepo() { #sudo sh -c "echo 'deb https://packagecloud.io/timescale/timescaledb/ubuntu/ $(lsb_release -c -s) main' > /etc/apt/sources.list.d/timescaledb.list" #wget --quiet -O - https://packagecloud.io/timescale/timescaledb/gpgkey | sudo apt-key add - ## 安装zabbix 5.4 源 - wget -q https://repo.zabbix.com/zabbix/5.4/ubuntu/pool/main/z/zabbix-release/zabbix-release_5.4-1+ubuntu20.04_all.deb - dpkg -i zabbix-release_5.4-1+ubuntu20.04_all.deb 1> /dev/null + wget -q https://repo.zabbix.com/zabbix/5.4/ubuntu/pool/main/z/zabbix-release/zabbix-release_5.4-1+ubuntu$(lsb_release -r -s)_all.deb + dpkg -i zabbix-release_5.4-1+ubuntu$(lsb_release -r -s)_all.deb 1> /dev/null apt update 1> /dev/null && apt install -y openjdk-8-jdk expect 1> /dev/null echo -e "\033[32m [ OK ] \033[0m" } @@ -90,7 +100,10 @@ function PGInstall() { function ZbxInstall() { echo -e -n "\033[32mStep4: 编译安装 zabbix 。。。 \033[0m" # zabbix 安装 - apt install zabbix-server-pgsql zabbix-frontend-php php7.4-pgsql zabbix-nginx-conf zabbix-sql-scripts zabbix-agent -y 1> /dev/null + apt install zabbix-server-pgsql zabbix-frontend-php php-pgsql zabbix-nginx-conf zabbix-sql-scripts zabbix-agent -y 1> /dev/null + + PHPCONF=/etc/php/$(ls /etc/php/)/fpm/php.ini + # 初始化 zabbix 配置 cd /tmp || exit sudo -u postgres createuser zabbix @@ -105,11 +118,11 @@ function ZbxInstall() { sed -i "s/\($DB\['PASSWORD'\]\s*=\).*/\1 'zabbix';/g" /usr/share/zabbix/conf/zabbix.conf.php sed -i "s/\($DB\['TYPE'\]\s*=\).*/\1 \'POSTGRESQL\';/g" /usr/share/zabbix/conf/zabbix.conf.php # 修改 php 配置 - sed -i 's/post_max_size = 8M/post_max_size = 16M/' /etc/php/7.4/fpm/php.ini - sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 20M/' /etc/php/7.4/fpm/php.ini - sed -i 's/max_execution_time = 30/max_execution_time = 300/' /etc/php/7.4/fpm/php.ini - sed -i 's/max_input_time = 60/max_input_time = 300/' /etc/php/7.4/fpm/php.ini - sed -i 's/; date.timezone =/date.timezone = "Asia\/Shanghai"/' /etc/php/7.4/fpm/php.ini + sed -i 's/post_max_size = 8M/post_max_size = 16M/' $PHPCONF + sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 20M/' $PHPCONF + sed -i 's/max_execution_time = 30/max_execution_time = 300/' $PHPCONF + sed -i 's/max_input_time = 60/max_input_time = 300/' $PHPCONF + sed -i 's/; date.timezone =/date.timezone = "Asia\/Shanghai"/' $PHPCONF # 修改 nginx 配置 sed -i '/sites-enabled/d' /etc/nginx/nginx.conf sed -i '/listen/s/#//' /etc/nginx/conf.d/zabbix.conf @@ -151,7 +164,7 @@ server { } EOL - systemctl restart zabbix-server zabbix-agent nginx php7.4-fpm + systemctl restart zabbix-server zabbix-agent nginx php$(ls /etc/php/)-fpm echo -e "\033[32m [ OK ] \033[0m" } @@ -214,5 +227,5 @@ AddInstallRepo PGInstall ZbxInstall taosinstall -ZeusInstall - +#ZeusInstall +echo "zabbix 部分已安装成功,zeus iot 可以参照 www.zmops.com 官方文档自定义安装。" From 52d2d95a8a645dffcb3d22a07773122e5ff480e0 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 12 Oct 2021 15:51:53 +0800 Subject: [PATCH 499/763] [fix]: remove camel agent dependcy --- iot-server-bom/pom.xml | 2 ++ iot-server/server-bootstrap/pom.xml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/iot-server-bom/pom.xml b/iot-server-bom/pom.xml index 749b410b..32f6a269 100644 --- a/iot-server-bom/pom.xml +++ b/iot-server-bom/pom.xml @@ -74,11 +74,13 @@ gson ${gson.version} + org.apache.camel camel-netty4-http diff --git a/iot-server/server-bootstrap/pom.xml b/iot-server/server-bootstrap/pom.xml index f9890b0f..01490ea2 100644 --- a/iot-server/server-bootstrap/pom.xml +++ b/iot-server/server-bootstrap/pom.xml @@ -71,10 +71,12 @@ server-transfer ${project.version} + From a2eced0a7551b603f2a518a9c535b299627cba2d Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 12 Oct 2021 15:52:53 +0800 Subject: [PATCH 500/763] [fix]: update zeus-iot-ui submodule --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index 76853841..ffbdf3cb 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit 768538410237f2da7f2963cb9e370bfdf1dc66de +Subproject commit ffbdf3cbe54fa263f177e8a4b4d1361ad694d611 From 3d59b6299f476dbfe8f6451f53859aaad6a93323 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 12 Oct 2021 16:26:28 +0800 Subject: [PATCH 501/763] [fix]:fix global view --- .../iot/web/analyse/service/HomeService.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index bd28afd1..f52eb714 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -325,21 +325,23 @@ public List> getAlarmTop(long timeFrom, long timeTill) { .map(ZbxProblemInfo::getObjectid).map(Objects::toString).collect(Collectors.toList()); List deviceList = DB.findDto(DeviceDto.class, - "select name,r.zbx_id from device d INNER JOIN (select relation_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.relation_id=d.device_id") + "select name,r.zbx_id from device d INNER JOIN (select relation_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.relation_id=d.device_id") .setParameter("zbxIds", triggerIds).findList(); - Map deviceMap = deviceList.parallelStream().collect(Collectors.toMap(DeviceDto::getZbxId, DeviceDto::getName)); + Map> deviceMap = deviceList.parallelStream().collect(Collectors.groupingBy(DeviceDto::getZbxId)); + List alarmDtoList = new ArrayList<>(); alarmList.forEach(zbxProblemInfo -> { - AlarmDto alarmDto = new AlarmDto(); - BeanUtils.copyProperties(zbxProblemInfo, alarmDto); - alarmDto.setRClock(zbxProblemInfo.getR_clock()); - alarmDto.setDeviceName("未知设备"); - if (null != deviceMap.get(zbxProblemInfo.getObjectid())) { - alarmDto.setDeviceName(deviceMap.get(zbxProblemInfo.getObjectid())); + if (ToolUtil.isNotEmpty(deviceMap.get(zbxProblemInfo.getObjectid()))) { + deviceMap.get(zbxProblemInfo.getObjectid()).forEach(deviceDto -> { + AlarmDto alarmDto = new AlarmDto(); + BeanUtils.copyProperties(zbxProblemInfo, alarmDto); + alarmDto.setRClock(zbxProblemInfo.getR_clock()); + alarmDto.setDeviceName(deviceDto.getName()); + alarmDtoList.add(alarmDto); + }); } - alarmDtoList.add(alarmDto); }); tmpMap = alarmDtoList.parallelStream().collect(Collectors.groupingBy(AlarmDto::getDeviceName, Collectors.counting())); @@ -354,6 +356,7 @@ public List> getAlarmTop(long timeFrom, long timeTill) { }); topList.sort(Comparator.comparing(o -> Integer.parseInt(o.get("value").toString()))); + Collections.reverse(topList); topList.subList(0, Math.min(topList.size(), 5)); return topList; From 8d1265a0fa9508af7c446616f20ef101a2718d4e Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 12 Oct 2021 17:29:30 +0800 Subject: [PATCH 502/763] [fix]: fix async product dependent attribute --- .../service/work/SaveAttributeWorker.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java index aa0bc7e5..c957738a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * @author yefei @@ -28,6 +29,7 @@ @Component public class SaveAttributeWorker implements IWorker { + private static final String ATTR_TYPE_RELY = "18"; @Override public Boolean action(DeviceDto deviceDto, Map> map) { @@ -50,16 +52,30 @@ public Boolean action(DeviceDto deviceDto, Map> map) } //属性 - List productAttributeList = new QProductAttribute().productId.eq(deviceDto.getProductId() + "").findList(); + List productAttributeList = new QProductAttribute().productId.eq(deviceDto.getProductId() + "").orderBy().source.asc().findList(); + List newProductAttributeList = new ArrayList<>(); + Map attrKeyMap = new ConcurrentHashMap<>(productAttributeList.size()); + Map attrIdMap = new ConcurrentHashMap<>(productAttributeList.size()); + for (ProductAttribute productAttribute : productAttributeList) { ProductAttribute newProductAttrbute = new ProductAttribute(); ToolUtil.copyProperties(productAttribute, newProductAttrbute); newProductAttrbute.setTemplateId(productAttribute.getAttrId()); newProductAttrbute.setZbxId(""); - newProductAttrbute.setAttrId(IdUtil.getSnowflake().nextId()); + Long attrId = IdUtil.getSnowflake().nextId(); + newProductAttrbute.setAttrId(attrId); newProductAttrbute.setProductId(deviceId); + //处理依赖属性 + if(ATTR_TYPE_RELY.equals(productAttribute.getSource())){ + String key = attrKeyMap.get(productAttribute.getDepAttrId()); + Long deptAttrId = attrIdMap.get(key); + newProductAttrbute.setDepAttrId(deptAttrId); + }else { + attrKeyMap.put(productAttribute.getAttrId(), productAttribute.getKey()); + attrIdMap.put(productAttribute.getKey(), attrId); + } newProductAttributeList.add(newProductAttrbute); } DB.saveAll(newProductAttributeList); From 840b48dceed6ad47b39b5441ad5dfc2c7b4fac6d Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 12 Oct 2021 18:23:24 +0800 Subject: [PATCH 503/763] [fix]: fix async product dependent attribute --- .../service/work/SaveAttributeWorker.java | 8 ++++--- .../service/work/SaveProdAttrWorker.java | 21 +++++++++++++++++-- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java index c957738a..2b5b1611 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java @@ -52,7 +52,7 @@ public Boolean action(DeviceDto deviceDto, Map> map) } //属性 - List productAttributeList = new QProductAttribute().productId.eq(deviceDto.getProductId() + "").orderBy().source.asc().findList(); + List productAttributeList = new QProductAttribute().productId.eq(deviceDto.getProductId() + "").orderBy(" source::int ").findList(); List newProductAttributeList = new ArrayList<>(); @@ -70,8 +70,10 @@ public Boolean action(DeviceDto deviceDto, Map> map) //处理依赖属性 if(ATTR_TYPE_RELY.equals(productAttribute.getSource())){ String key = attrKeyMap.get(productAttribute.getDepAttrId()); - Long deptAttrId = attrIdMap.get(key); - newProductAttrbute.setDepAttrId(deptAttrId); + if(ToolUtil.isNotEmpty(key)) { + Long deptAttrId = attrIdMap.get(key); + newProductAttrbute.setDepAttrId(deptAttrId); + } }else { attrKeyMap.put(productAttribute.getAttrId(), productAttribute.getKey()); attrIdMap.put(productAttribute.getKey(), attrId); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java index 3b5483ad..0b5637a5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java @@ -5,6 +5,7 @@ import com.zmops.iot.async.callback.IWorker; import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductAttribute; +import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.iot.web.product.dto.ProductAttr; @@ -15,6 +16,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; /** * @author yefei @@ -25,13 +28,12 @@ @Component public class SaveProdAttrWorker implements IWorker { + private static final String ATTR_SOURCE_DEPEND = "18"; @Override public Boolean action(ProductAttr productAttr, Map> map) { log.debug("处理产品 新增Attr 同步到设备工作…………"); - String prodId = productAttr.getProductId(); - String sql = "select device_id from device " + " where product_id = :productId and device_id not in (" + " select product_id from product_attribute " + @@ -41,6 +43,18 @@ public Boolean action(ProductAttr productAttr, Map> .setParameter("key", productAttr.getKey()).findList(); List productAttributeList = new ArrayList<>(); + if (ToolUtil.isEmpty(deviceDtoList)) { + return true; + } + + //处理依赖属性 + Map attrIdMap = new ConcurrentHashMap<>(deviceDtoList.size()); + if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { + List deviceIds = deviceDtoList.parallelStream().map(DeviceDto::getDeviceId).collect(Collectors.toList()); + List list = new QProductAttribute().productId.in(deviceIds).templateId.eq(productAttr.getDepAttrId()).findList(); + attrIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getProductId, ProductAttribute::getAttrId)); + } + for (DeviceDto deviceDto : deviceDtoList) { ProductAttribute productAttrbute = new ProductAttribute(); ToolUtil.copyProperties(productAttr, productAttrbute); @@ -48,6 +62,9 @@ public Boolean action(ProductAttr productAttr, Map> productAttrbute.setName(productAttr.getAttrName()); productAttrbute.setProductId(deviceDto.getDeviceId()); productAttrbute.setTemplateId(productAttr.getAttrId()); + if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource()) && null != attrIdMap.get(deviceDto.getDeviceId())) { + productAttrbute.setDepAttrId(attrIdMap.get(deviceDto.getDeviceId())); + } productAttributeList.add(productAttrbute); } DB.saveAll(productAttributeList); From 7ee1db56de2fd15cf9ba504727985f5882fdf79a Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 12 Oct 2021 19:13:38 +0800 Subject: [PATCH 504/763] [fix]: fix alarm list --- .../iot/web/alarm/service/AlarmService.java | 51 ++++++++++++------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 3bda9268..d32bf661 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -19,6 +19,7 @@ import com.zmops.zeus.driver.entity.ZbxProblemInfo; import com.zmops.zeus.driver.service.ZbxProblem; import io.ebean.DB; +import io.ebean.DtoQuery; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -112,33 +113,45 @@ public Pager getAlarmByPage(AlarmParam alarmParam) { } //根据triggerid查询出 所属设备 List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).collect(Collectors.toList()); - List deviceList = DB.findDto(DeviceDto.class, "select name,device_id,r.zbx_id from device d INNER JOIN (select relation_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.relation_id=d.device_id") - .setParameter("zbxIds", triggerIds).findList(); - Map deviceMap = deviceList.parallelStream().collect(Collectors.toMap(DeviceDto::getZbxId, o -> o)); + String sql = "select distinct name,device_id,r.zbx_id from device d INNER JOIN (select relation_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.relation_id=d.device_id"; + if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { + sql += " where d.device_id = :deviceId"; + } + DtoQuery dtoQuery = DB.findDto(DeviceDto.class, sql).setParameter("zbxIds", triggerIds); + if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { + dtoQuery.setParameter("deviceId", alarmParam.getDeviceId()); + } + List deviceList = dtoQuery.findList(); + Map> deviceMap = deviceList.parallelStream().collect(Collectors.groupingBy(DeviceDto::getZbxId)); - List ruleList = DB.findDto(ProductEventRuleDto.class, "select event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") + List ruleList = DB.findDto(ProductEventRuleDto.class, "select distinct event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id") .setParameter("zbxIds", triggerIds).findList(); Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); List alarmDtoList = new ArrayList<>(); problemList.forEach(zbxProblemInfo -> { - AlarmDto alarmDto = new AlarmDto(); - BeanUtils.copyProperties(zbxProblemInfo, alarmDto); - alarmDto.setRClock(zbxProblemInfo.getR_clock()); - alarmDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(zbxProblemInfo.getClock()), "yyyy-MM-dd HH:mm:ss")); - alarmDto.setRClock("0".equals(zbxProblemInfo.getR_clock()) ? "0" : - LocalDateTimeUtils.convertTimeToString(Integer.parseInt(zbxProblemInfo.getR_clock()), "yyyy-MM-dd HH:mm:ss")); - alarmDto.setStatus("0".equals(zbxProblemInfo.getR_clock()) ? "未解决" : "已解决"); - alarmDto.setAcknowledged("0".equals(zbxProblemInfo.getAcknowledged()) ? "未确认" : "已确认"); - if (null != deviceMap.get(zbxProblemInfo.getObjectid())) { - alarmDto.setDeviceName(deviceMap.get(zbxProblemInfo.getObjectid()).getName()); - alarmDto.setDeviceId(deviceMap.get(zbxProblemInfo.getObjectid()).getDeviceId()); - } - if (null != ruleMap.get(zbxProblemInfo.getObjectid())) { - alarmDto.setName(ruleMap.get(zbxProblemInfo.getObjectid())); + if (ToolUtil.isNotEmpty(deviceMap.get(zbxProblemInfo.getObjectid()))) { + deviceMap.get(zbxProblemInfo.getObjectid()).forEach(deviceDto -> { + AlarmDto alarmDto = new AlarmDto(); + BeanUtils.copyProperties(zbxProblemInfo, alarmDto); + + alarmDto.setRClock(zbxProblemInfo.getR_clock()); + alarmDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(zbxProblemInfo.getClock()), "yyyy-MM-dd HH:mm:ss")); + alarmDto.setRClock("0".equals(zbxProblemInfo.getR_clock()) ? "0" : + LocalDateTimeUtils.convertTimeToString(Integer.parseInt(zbxProblemInfo.getR_clock()), "yyyy-MM-dd HH:mm:ss")); + alarmDto.setStatus("0".equals(zbxProblemInfo.getR_clock()) ? "未解决" : "已解决"); + alarmDto.setAcknowledged("0".equals(zbxProblemInfo.getAcknowledged()) ? "未确认" : "已确认"); + + alarmDto.setDeviceName(deviceDto.getName()); + alarmDto.setDeviceId(deviceDto.getDeviceId()); + + if (null != ruleMap.get(zbxProblemInfo.getObjectid())) { + alarmDto.setName(ruleMap.get(zbxProblemInfo.getObjectid())); + } + alarmDtoList.add(alarmDto); + }); } - alarmDtoList.add(alarmDto); }); return new Pager<>(alarmDtoList, zbxProblemInfos.size()); From 4fcfe31f7d0df90fdf775482cbdabdc7e907a1fe Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 12 Oct 2021 20:27:51 +0800 Subject: [PATCH 505/763] [fix]: fix zbx url config --- docs/README.md | 3 +-- .../com/zmops/zeus/driver/service/ZbxAction.java | 2 +- .../com/zmops/zeus/driver/service/ZbxApiInfo.java | 2 +- .../zeus/driver/service/ZbxDeviceStatusTrigger.java | 2 +- .../com/zmops/zeus/driver/service/ZbxHistoryGet.java | 2 +- .../java/com/zmops/zeus/driver/service/ZbxHost.java | 2 +- .../com/zmops/zeus/driver/service/ZbxHostGroup.java | 2 +- .../zmops/zeus/driver/service/ZbxInitService.java | 12 ++++++------ .../java/com/zmops/zeus/driver/service/ZbxItem.java | 2 +- .../java/com/zmops/zeus/driver/service/ZbxMacro.java | 2 +- .../com/zmops/zeus/driver/service/ZbxProblem.java | 2 +- .../com/zmops/zeus/driver/service/ZbxScript.java | 2 +- .../com/zmops/zeus/driver/service/ZbxTemplate.java | 2 +- .../com/zmops/zeus/driver/service/ZbxTrigger.java | 2 +- .../java/com/zmops/zeus/driver/service/ZbxUser.java | 2 +- .../com/zmops/zeus/driver/service/ZbxUserGroup.java | 2 +- .../com/zmops/zeus/driver/service/ZbxValueMap.java | 2 +- zeus-starter/src/main/assembly/webapp.yml | 1 - zeus-starter/src/main/resources/application.yaml | 1 - .../zmops/iot/web/analyse/service/HomeService.java | 1 - 20 files changed, 22 insertions(+), 26 deletions(-) diff --git a/docs/README.md b/docs/README.md index 756d227b..d6983ff3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -159,8 +159,7 @@ apt install openjdk-8-jdk -y log-enabled: false timeout: 5000 variables: - ## Zabbix API IP And ServerIp and ServerPort - zbxApiUrl: http://${ZEUS_ZABBIX_HOST:127.0.0.1}:${ZEUS_ZABBIX_PORT:80}/zabbix/api_jsonrpc.php + ## Zabbix API IP And ServerIp and ServerPort zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:80} zbxApiToken: 4d3ed2be23a3f325d6ccaaaeab76bbdc6a559f3c608e523f9906ea923f7d61c5 diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java index 8c6cad5d..e4e205fd 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java @@ -11,7 +11,7 @@ */ @BaseRequest( - baseURL = "${zbxApiUrl}", + baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxAction { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxApiInfo.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxApiInfo.java index 340fb0c1..5458badc 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxApiInfo.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxApiInfo.java @@ -10,7 +10,7 @@ */ @BaseRequest( - baseURL = "${zbxApiUrl}", + baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxApiInfo { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java index 9be26497..b4a78667 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java @@ -12,7 +12,7 @@ * 设备离线 在线触发器,判断设备 在线,离线 状态 */ @BaseRequest( - baseURL = "${zbxApiUrl}", + baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxDeviceStatusTrigger { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java index 203b2b84..318c13c2 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java @@ -13,7 +13,7 @@ */ @BaseRequest( - baseURL = "${zbxApiUrl}", + baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxHistoryGet { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java index bb06ab1c..aa1c41a3 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java @@ -16,7 +16,7 @@ * 主机驱动 */ @BaseRequest( - baseURL = "${zbxApiUrl}", + baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxHost { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java index bd54a0ff..da222487 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java @@ -13,7 +13,7 @@ */ @BaseRequest( - baseURL = "${zbxApiUrl}", + baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxHostGroup { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java index 98307926..71e07216 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java @@ -12,7 +12,7 @@ public interface ZbxInitService { @Post( - url = "${zbxApiUrl}", + url = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", headers = "authTag: noAuth", interceptor = JsonBodyBuildInterceptor.class ) @@ -20,7 +20,7 @@ public interface ZbxInitService { String createCookieUserGroup(@ParamName("hostGroupId") String hostGroupId, @ParamName("userAuth") String userAuth); @Post( - url = "${zbxApiUrl}", + url = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", headers = "authTag: noAuth", interceptor = JsonBodyBuildInterceptor.class ) @@ -28,7 +28,7 @@ public interface ZbxInitService { String getCookieUserGroup(@ParamName("userAuth") String userAuth); @Post( - url = "${zbxApiUrl}", + url = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", headers = "authTag: noAuth", interceptor = JsonBodyBuildInterceptor.class ) @@ -36,7 +36,7 @@ public interface ZbxInitService { String getCookieUser(@ParamName("userAuth") String userAuth); @Post( - url = "${zbxApiUrl}", + url = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", headers = "authTag: noAuth", interceptor = JsonBodyBuildInterceptor.class ) @@ -46,7 +46,7 @@ String createCookieUser(@ParamName("usrGrpId") String usrGrpId, @ParamName("roleId") String roleId); @Post( - url = "${zbxApiUrl}", + url = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", headers = "authTag: noAuth", interceptor = JsonBodyBuildInterceptor.class ) @@ -54,7 +54,7 @@ String createCookieUser(@ParamName("usrGrpId") String usrGrpId, String getAdminRole(@ParamName("userAuth") String zbxApiToken); @Post( - url = "${zbxApiUrl}", + url = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", headers = "authTag: noAuth", interceptor = JsonBodyBuildInterceptor.class ) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java index 9e1bb4eb..c84e34b4 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java @@ -15,7 +15,7 @@ */ @BaseRequest( - baseURL = "${zbxApiUrl}", + baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxItem { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java index 23754296..15fc6cac 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java @@ -13,7 +13,7 @@ * 宏定义接口 */ @BaseRequest( - baseURL = "${zbxApiUrl}", + baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxMacro { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java index 70557efb..9d494ded 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java @@ -10,7 +10,7 @@ * @author nantian created at 2021/8/7 23:27 */ -@BaseRequest(baseURL = "${zbxApiUrl}", interceptor = JsonBodyBuildInterceptor.class) +@BaseRequest(baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", interceptor = JsonBodyBuildInterceptor.class) public interface ZbxProblem { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java index 8261ecd2..08d9c355 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java @@ -10,7 +10,7 @@ * @author nantian created at 2021/8/7 20:42 */ @BaseRequest( - baseURL = "${zbxApiUrl}", + baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxScript { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java index f39b44ef..7b192615 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java @@ -13,7 +13,7 @@ */ @BaseRequest( - baseURL = "${zbxApiUrl}", + baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxTemplate { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java index 0efbf104..97db7da4 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java @@ -10,7 +10,7 @@ import java.util.Map; @BaseRequest( - baseURL = "${zbxApiUrl}", + baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxTrigger { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java index 5708a72d..ccc21bc0 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java @@ -15,7 +15,7 @@ */ @BaseRequest( - baseURL = "${zbxApiUrl}", + baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxUser { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java index 8c2dc7b7..39f943bc 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java @@ -15,7 +15,7 @@ */ @BaseRequest( - baseURL = "${zbxApiUrl}", + baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxUserGroup { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxValueMap.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxValueMap.java index 37378b6d..19108810 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxValueMap.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxValueMap.java @@ -14,7 +14,7 @@ * 值映射设置 */ @BaseRequest( - baseURL = "${zbxApiUrl}", + baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxValueMap { diff --git a/zeus-starter/src/main/assembly/webapp.yml b/zeus-starter/src/main/assembly/webapp.yml index 6e8d573a..19cd868a 100644 --- a/zeus-starter/src/main/assembly/webapp.yml +++ b/zeus-starter/src/main/assembly/webapp.yml @@ -46,7 +46,6 @@ forest: timeout: 5000 variables: ## Zabbix API IP And ServerIp and ServerPort - zbxApiUrl: http://${ZEUS_ZABBIX_HOST:127.0.0.1}:${ZEUS_ZABBIX_PORT:80}/zabbix/api_jsonrpc.php zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:80} zbxApiToken: 3464dee6b3fa3ce4173972e0497d7b84a93bdf8477ff1bdd51a7719cc0db2cd9 diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index f8ffe17a..169087ed 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -45,7 +45,6 @@ forest: timeout: 5000 variables: ## Zabbix API IP And ServerIp and ServerPort - zbxApiUrl: http://${ZEUS_ZABBIX_HOST:127.0.0.1}:${ZEUS_ZABBIX_PORT:80}/zabbix/api_jsonrpc.php zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:80} zbxApiToken: 897e588c32f780f7134457e409ff37e84ea966ee20712dfacd22c8a968ce94d6 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index f52eb714..a8169b21 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -356,7 +356,6 @@ public List> getAlarmTop(long timeFrom, long timeTill) { }); topList.sort(Comparator.comparing(o -> Integer.parseInt(o.get("value").toString()))); - Collections.reverse(topList); topList.subList(0, Math.min(topList.size(), 5)); return topList; From f4da8d2bc8f1fe51acd7735fbe3f0568ac31cea8 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 12 Oct 2021 20:40:58 +0800 Subject: [PATCH 506/763] [feat]: use default tdengine database name as zeus_data --- zeus-starter/src/main/assembly/webapp.yml | 4 +++- zeus-starter/src/main/resources/application.yaml | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/zeus-starter/src/main/assembly/webapp.yml b/zeus-starter/src/main/assembly/webapp.yml index 19cd868a..450d0a01 100644 --- a/zeus-starter/src/main/assembly/webapp.yml +++ b/zeus-starter/src/main/assembly/webapp.yml @@ -49,7 +49,9 @@ forest: zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:80} zbxApiToken: 3464dee6b3fa3ce4173972e0497d7b84a93bdf8477ff1bdd51a7719cc0db2cd9 - taosUrl: http://${ZEUS_TAOS_HOST:127.0.0.1}:${ZEUS_TAOS_REST_PORT:6041}/rest/sql/${ZEUS_TAOS_DB:zeus_data} + + ## tdengine http request address + taosUrl: http://${ZEUS_TAOS_HOST:127.0.0.1}:${ZEUS_TAOS_REST_PORT:6041}/rest/sql/zeus_data taosUser: root taosPwd: taosdata diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index 169087ed..1abbbfe7 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -49,7 +49,8 @@ forest: zbxServerPort: ${ZEUS_ZABBIX_PORT:80} zbxApiToken: 897e588c32f780f7134457e409ff37e84ea966ee20712dfacd22c8a968ce94d6 - taosUrl: http://${ZEUS_TAOS_HOST:127.0.0.1}:${ZEUS_TAOS_REST_PORT:6041}/rest/sql/${ZEUS_TAOS_DB:zeus_data} + ## tdengine http request address + taosUrl: http://${ZEUS_TAOS_HOST:127.0.0.1}:${ZEUS_TAOS_REST_PORT:6041}/rest/sql/zeus_data taosUser: root taosPwd: taosdata From 6bad52b54dc73fafdd50a3d283a9d4bf39063417 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 12 Oct 2021 20:41:20 +0800 Subject: [PATCH 507/763] [feat]: update zeus-iot-ui submodule --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index ffbdf3cb..e7fe8e96 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit ffbdf3cbe54fa263f177e8a4b4d1361ad694d611 +Subproject commit e7fe8e9628263ba4b4a4b8d1c3a93704f6700a65 From 3ed1615cf860f4c8e0bd0a2e047e3659d47a1cb5 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 12 Oct 2021 21:16:43 +0800 Subject: [PATCH 508/763] [fix]: fix async product dependent attribute --- .../product/service/work/SaveProdAttrWorker.java | 3 +-- .../service/work/UpdateAttributeWorker.java | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java index 0b5637a5..8772e7db 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java @@ -50,8 +50,7 @@ public Boolean action(ProductAttr productAttr, Map> //处理依赖属性 Map attrIdMap = new ConcurrentHashMap<>(deviceDtoList.size()); if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { - List deviceIds = deviceDtoList.parallelStream().map(DeviceDto::getDeviceId).collect(Collectors.toList()); - List list = new QProductAttribute().productId.in(deviceIds).templateId.eq(productAttr.getDepAttrId()).findList(); + List list = new QProductAttribute().templateId.eq(productAttr.getDepAttrId()).findList(); attrIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getProductId, ProductAttribute::getAttrId)); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java index 703d4bb5..03c78107 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java @@ -6,6 +6,7 @@ import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.iot.web.product.dto.ProductAttr; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; @@ -14,6 +15,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; /** * @author yefei @@ -24,6 +27,7 @@ @Component public class UpdateAttributeWorker implements IWorker { + private static final String ATTR_SOURCE_DEPEND = "18"; @Override public Boolean action(ProductAttr productAttr, Map> map) { @@ -32,6 +36,14 @@ public Boolean action(ProductAttr productAttr, Map> Long attrId = productAttr.getAttrId(); List list = new QProductAttribute().templateId.eq(attrId).findList(); + + //处理依赖属性 + Map attrIdMap = new ConcurrentHashMap<>(list.size()); + if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { + List productAttributeList = new QProductAttribute().templateId.eq(productAttr.getDepAttrId()).findList(); + attrIdMap = productAttributeList.parallelStream().collect(Collectors.toMap(ProductAttribute::getProductId, ProductAttribute::getAttrId)); + } + List newList = new ArrayList<>(); for (ProductAttribute productAttribute : list) { ProductAttribute newProductAttribute = new ProductAttribute(); @@ -42,6 +54,9 @@ public Boolean action(ProductAttr productAttr, Map> newProductAttribute.setSource(productAttr.getSource()); newProductAttribute.setValueType(productAttr.getValueType()); newProductAttribute.setValuemapid(productAttr.getValuemapid()); + if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource()) && null != attrIdMap.get(productAttribute.getProductId())) { + newProductAttribute.setDepAttrId(attrIdMap.get(productAttribute.getProductId())); + } newList.add(newProductAttribute); } DB.updateAll(newList); From f09eda36850332fbf111989d9ba1d718985cabb1 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 12 Oct 2021 21:47:49 +0800 Subject: [PATCH 509/763] [fix]: fix product attribute --- .../service/work/UpdateAttributeWorker.java | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java index 03c78107..3564a78e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java @@ -44,22 +44,18 @@ public Boolean action(ProductAttr productAttr, Map> attrIdMap = productAttributeList.parallelStream().collect(Collectors.toMap(ProductAttribute::getProductId, ProductAttribute::getAttrId)); } - List newList = new ArrayList<>(); for (ProductAttribute productAttribute : list) { - ProductAttribute newProductAttribute = new ProductAttribute(); - ToolUtil.copyProperties(productAttribute, newProductAttribute); - newProductAttribute.setName(productAttr.getAttrName()); - newProductAttribute.setKey(productAttr.getKey()); - newProductAttribute.setUnits(productAttr.getUnits()); - newProductAttribute.setSource(productAttr.getSource()); - newProductAttribute.setValueType(productAttr.getValueType()); - newProductAttribute.setValuemapid(productAttr.getValuemapid()); + productAttribute.setName(productAttr.getAttrName()); + productAttribute.setKey(productAttr.getKey()); + productAttribute.setUnits(productAttr.getUnits()); + productAttribute.setSource(productAttr.getSource()); + productAttribute.setValueType(productAttr.getValueType()); + productAttribute.setValuemapid(productAttr.getValuemapid()); if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource()) && null != attrIdMap.get(productAttribute.getProductId())) { - newProductAttribute.setDepAttrId(attrIdMap.get(productAttribute.getProductId())); + productAttribute.setDepAttrId(attrIdMap.get(productAttribute.getProductId())); } - newList.add(newProductAttribute); } - DB.updateAll(newList); + DB.updateAll(list); return true; } From da9bc8045cb28bcdf34c34a9e9cdfac0a1723a79 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 13 Oct 2021 12:02:04 +0800 Subject: [PATCH 510/763] [feat]: add multiple device event --- .../com/zmops/iot/core/util/HttpContext.java | 28 +- .../MultipleDeviceEventTriggerController.java | 243 +++++++++++++ .../device/dto/MultipleDeviceEventRule.java | 140 ++++++++ .../dto/param/MultipleDeviceEventParm.java | 17 + .../MultipleDeviceEventRuleService.java | 331 ++++++++++++++++++ .../service/ProductEventRuleService.java | 3 +- .../service/work/UpdateAttributeWorker.java | 3 - 7 files changed, 759 insertions(+), 6 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/MultipleDeviceEventParm.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java diff --git a/zeus-core/src/main/java/com/zmops/iot/core/util/HttpContext.java b/zeus-core/src/main/java/com/zmops/iot/core/util/HttpContext.java index 85b4d9d8..dce2d93e 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/util/HttpContext.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/util/HttpContext.java @@ -5,6 +5,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.net.InetAddress; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; @@ -14,6 +15,7 @@ */ public class HttpContext { + private static final String LOCALHOST = "127.0.0.1"; /** * 获取请求的ip地址 @@ -25,7 +27,31 @@ public static String getIp() { if (request == null) { return "127.0.0.1"; } else { - return request.getRemoteHost(); + String ipAddress; + try { + ipAddress = request.getHeader("x-forwarded-for"); + if (ipAddress == null || ipAddress.length() == 0 ) { + ipAddress = request.getHeader("Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.length() == 0 ) { + ipAddress = request.getHeader("WL-Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.length() == 0 ) { + ipAddress = request.getRemoteAddr(); + if (LOCALHOST.equals(ipAddress)) { + InetAddress inet = null; + try { + inet = InetAddress.getLocalHost(); + } catch (Exception e) { + e.printStackTrace(); + } + ipAddress = inet.getHostAddress(); + } + } + } catch (Exception e) { + ipAddress = ""; + } + return ipAddress; } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java new file mode 100644 index 00000000..9a634d81 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java @@ -0,0 +1,243 @@ +package com.zmops.iot.web.device.controller; + +import cn.hutool.core.util.IdUtil; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEvent; +import com.zmops.iot.domain.product.query.QProductEventExpression; +import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.enums.InheritStatus; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.MultipleDeviceEventRule; +import com.zmops.iot.web.device.dto.param.MultipleDeviceEventParm; +import com.zmops.iot.web.device.service.MultipleDeviceEventRuleService; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.product.dto.ProductEventDto; +import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; +import io.ebean.annotation.Transactional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 设备联动 + **/ +@RestController +@RequestMapping("/multiple/device/event/trigger") +public class MultipleDeviceEventTriggerController { + + @Autowired + MultipleDeviceEventRuleService multipleDeviceEventRuleService; + + @Autowired + private ZbxTrigger zbxTrigger; + + private static final String EXECUTE_TAG_NAME = "__execute__"; + + /** + * 触发器 分页列表 + * + * @param eventParm + * @return + */ + @PostMapping("/getEventByPage") + public Pager getEventByPage(@RequestBody MultipleDeviceEventParm eventParm) { + return multipleDeviceEventRuleService.getEventByPage(eventParm); + } + + /** + * 设备联动 详情 + * + * @param eventRuleId + * @return + */ + + @GetMapping("/detail") + public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId, @RequestParam("deviceId") String deviceId) { + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRuleId).findOne(); + if (null == productEvent) { + throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); + } + return ResponseData.success(multipleDeviceEventRuleService.detail(productEvent, eventRuleId, deviceId)); + } + + /** + * 创建 设备联动 + * + * @param eventRule 设备联动规则 + * @return 设备联动ID + */ + @Transactional + @PostMapping("/create") + public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Create.class) + MultipleDeviceEventRule eventRule) { + + Long eventRuleId = IdUtil.getSnowflake().nextId(); // ruleId, trigger name + + multipleDeviceEventRuleService.createDeviceEventRule(eventRuleId, eventRule); + + //step 1: 先创建 zbx 触发器 + String expression = eventRule.getExpList() + .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); + + //step 2: zbx 保存触发器 + String[] triggerIds = multipleDeviceEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); + + //step 4: zbx 触发器创建 Tag + Map tags = new ConcurrentHashMap<>(3); + if (ToolUtil.isNotEmpty(eventRule.getTags())) { + tags = eventRule.getTags().stream() + .collect(Collectors.toMap(MultipleDeviceEventRule.Tag::getTag, MultipleDeviceEventRule.Tag::getValue, (k1, k2) -> k2)); + } + + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { + tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); + } + + for (String triggerId : triggerIds) { + zbxTrigger.triggerTagCreate(triggerId, tags); + } + + //step 5: 更新 zbxId + multipleDeviceEventRuleService.updateProductEventRuleZbxId(eventRuleId, triggerIds); + + // 返回触发器ID + return ResponseData.success(eventRuleId); + } + + /** + * 修改 设备联动 状态 + * + * @param eventRule 设备联动规则 + */ + @PostMapping("/status") + public ResponseData updateProductEventStatus(@RequestBody @Validated(value = BaseEntity.Status.class) MultipleDeviceEventRule eventRule) { + DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).eq("relationId", eventRule.getDeviceId()).asUpdate() + .set("status", eventRule.getStatus()).update(); + + ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()) + .relationId.eq(eventRule.getDeviceId()).findOne(); + + if (null != productEventRelation && null != productEventRelation.getZbxId()) { + zbxTrigger.triggerStatusUpdate(productEventRelation.getZbxId(), eventRule.getStatus().equals(CommonStatus.ENABLE.getCode()) ? "0" : "1"); + } + + return ResponseData.success(); + } + + /** + * 修改 设备联动 + * + * @param eventRule 设备联动规则 + * @return 设备联动ID + */ + @Transactional + @PostMapping("/update") + public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) MultipleDeviceEventRule eventRule) { + int count = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()) + .findCount(); + if (count == 0) { + throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); + } + + //来自产品的告警规则 只能修改备注 + count = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).inherit.eq(InheritStatus.YES.getCode()) + .findCount(); + if (count > 1) { + DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).eq("relationId", eventRule.getDeviceId()) + .asUpdate().set("remark", eventRule.getRemark()).update(); + + return ResponseData.success(eventRule.getEventRuleId()); + } + + //step 1: 删除原有的 关联关系 + multipleDeviceEventRuleService.updateDeviceEventRule(eventRule.getEventRuleId(), eventRule); + + //step 1: 先创建 zbx 触发器 + String expression = eventRule.getExpList() + .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); + + //step 2: zbx 保存触发器 + String[] triggerIds = multipleDeviceEventRuleService.updateZbxTrigger(eventRule.getZbxId(), expression, eventRule.getEventLevel()); + + //step 4: zbx 触发器创建 Tag + Map tags = eventRule.getTags().stream() + .collect(Collectors.toMap(MultipleDeviceEventRule.Tag::getTag, MultipleDeviceEventRule.Tag::getValue, (k1, k2) -> k2)); + if (ToolUtil.isEmpty(tags)) { + tags = new HashMap<>(2); + } + + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { + tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); + } + + for (String triggerId : triggerIds) { + zbxTrigger.triggerTagCreate(triggerId, tags); + } + + //step 5: 更新 zbxId 反写 + multipleDeviceEventRuleService.updateProductEventRuleZbxId(eventRule.getEventRuleId(), triggerIds); + + // 返回触发器ID + return ResponseData.success(eventRule.getEventRuleId()); + } + + + /** + * 删除 设备联动 + * + * @param eventRule 设备联动规则 + */ + @Transactional + @PostMapping("/delete") + public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseEntity.Delete.class) MultipleDeviceEventRule eventRule) { + + ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(eventRule.getDeviceId()) + .eventRuleId.eq(eventRule.getEventRuleId()).findOne(); + + if (productEventRelation != null && productEventRelation.getInherit().equals(InheritStatus.YES.getCode())) { + throw new ServiceException(BizExceptionEnum.EVENT_PRODUCT_CANNOT_DELETE); + } + + //step 01:删除 zbx触发器 + if (productEventRelation != null && ToolUtil.isNotEmpty(productEventRelation.getZbxId())) { + List triggers = JSONObject.parseArray( + zbxTrigger.triggerGet(productEventRelation.getZbxId()), MultipleDeviceEventRuleService.Triggers.class); + + if (ToolUtil.isNotEmpty(triggers)) { + zbxTrigger.triggerDelete(productEventRelation.getZbxId()); + } + } + + //step 1:删除 与设备的关联 + new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 2:删除 关联的执行服务 + new QProductEventService().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 3:删除 关联的表达式 + new QProductEventExpression().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 4:删除 触发器 + new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + return ResponseData.success(); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java new file mode 100644 index 00000000..61386c9f --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java @@ -0,0 +1,140 @@ +package com.zmops.iot.web.device.dto; + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.util.ToolUtil; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang.StringUtils; + +import javax.validation.Valid; +import javax.validation.constraints.Max; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author nantian created at 2021/9/14 14:47 + *

+ * 告警规则 + */ + +@Getter +@Setter +public class MultipleDeviceEventRule { + + @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Delete.class, BaseEntity.Status.class}) + private Long eventRuleId; + + private Byte eventNotify = 0; + + // 名称 + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String eventRuleName; + + private Byte eventLevel = 1; + + // 表达式列表 + @Valid + @NotEmpty(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private List expList; + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String expLogic; // and or + + private String remark; + + @NotEmpty(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private List deviceServices; + + private List tags; + + private String zbxId; + + private String deviceId; + + @NotBlank(groups = BaseEntity.Status.class) + private String status; + + private String classify = "1"; + + @Data + public static class Tag { + + @Max(20) + private String tag; + + @Max(50) + private String value; + } + + @Getter + @Setter + // 告警表达式 构成 + public static class Expression { + + private Long eventExpId; + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String function; // last avg max min sum change nodata + + private String scope; // s m h T + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String condition; // > < = <> >= <= + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String value; + + @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String productAttrKey; // 产品属性 Key + + private String deviceId; // 设备ID + + private String unit; + + private Long productAttrId; + + private String productAttrType; + + private String attrValueType; + + private String period; + + @Override + public String toString() { + StringBuilder expression = new StringBuilder(); + expression.append(function); + expression.append("(/"); + expression.append(deviceId); + expression.append("/"); + expression.append(productAttrKey); + + if (StringUtils.isNotBlank(scope)) { + expression.append(", "); + expression.append(scope); + } + expression.append(") ").append(condition).append(" ").append(ToolUtil.addQuotes(value)); + return expression.toString(); + } + } + + + @Setter + @Getter + public static class DeviceService { + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String executeDeviceId; + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private Long serviceId; + + } + +} + + + + diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/MultipleDeviceEventParm.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/MultipleDeviceEventParm.java new file mode 100644 index 00000000..ce6e1c43 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/MultipleDeviceEventParm.java @@ -0,0 +1,17 @@ +package com.zmops.iot.web.device.dto.param; + +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class MultipleDeviceEventParm extends BaseQueryParam { + + private String eventRuleName; + + + + private String classify = "1"; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java new file mode 100644 index 00000000..c6b49151 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -0,0 +1,331 @@ +package com.zmops.iot.web.device.service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.ProductEventExpression; +import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEvent; +import com.zmops.iot.domain.product.query.QProductEventExpression; +import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.enums.InheritStatus; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.MultipleDeviceEventRule; +import com.zmops.iot.web.device.dto.param.MultipleDeviceEventParm; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.product.dto.ProductEventDto; +import com.zmops.iot.web.product.dto.ProductEventRuleDto; +import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; +import io.ebean.annotation.Transactional; +import lombok.Data; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + **/ +@Service +public class MultipleDeviceEventRuleService { + + @Autowired + private ZbxTrigger zbxTrigger; + + /** + * 设备联动 分页列表 + * + * @param eventParm + * @return + */ + public Pager getEventByPage(MultipleDeviceEventParm eventParm) { + QProductEvent query = new QProductEvent(); + + if (ToolUtil.isNotEmpty(eventParm.getEventRuleName())) { + query.eventRuleName.contains(eventParm.getEventRuleName()); + } + if (ToolUtil.isNotEmpty(eventParm.getClassify())) { + query.classify.eq(eventParm.getClassify()); + } + + List list = query.setFirstRow((eventParm.getPage() - 1) * eventParm.getMaxRow()) + .setMaxRows(eventParm.getMaxRow()).orderBy(" create_time desc").asDto(ProductEventDto.class).findList(); + + if (ToolUtil.isEmpty(list)) { + new Pager<>(list, 0); + } + + //查询状态 备注 + List eventRuleIds = list.parallelStream().map(ProductEventDto::getEventRuleId).collect(Collectors.toList()); + List productEventRelationList = new QProductEventRelation().eventRuleId.in(eventRuleIds) + .findList(); + Map productEventRelationMap = productEventRelationList.parallelStream().collect(Collectors.toMap(ProductEventRelation::getEventRuleId, o -> o, (v1, v2) -> v2)); + + list.forEach(productEventDto -> { + if (null != productEventRelationMap.get(productEventDto.getEventRuleId())) { + productEventDto.setStatus(productEventRelationMap.get(productEventDto.getEventRuleId()).getStatus()); + productEventDto.setRemark(productEventRelationMap.get(productEventDto.getEventRuleId()).getRemark()); + } + }); + + return new Pager<>(list, query.findCount()); + } + + /** + * 保存设备联动 + * + * @param eventRuleId 设备联动ID + * @param eventRule 设备联动规则 + */ + @Transactional(rollbackFor = Exception.class) + public void createDeviceEventRule(Long eventRuleId, MultipleDeviceEventRule eventRule) { + // step 1: 保存产品告警规则 + ProductEvent event = initEventRule(eventRule); + event.setEventRuleId(eventRuleId); + DB.save(event); + + //step 2: 保存 表达式,方便回显 + List expList = new ArrayList<>(); + + eventRule.getExpList().forEach(i -> { + ProductEventExpression exp = initEventExpression(i); + exp.setEventRuleId(eventRuleId); + expList.add(exp); + }); + + DB.saveAll(expList); + + //step 3: 保存触发器 调用 本产品方法 + if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { + eventRule.getDeviceServices().forEach(i -> { + DB.sqlUpdate("insert into product_event_service(event_rule_id, execute_device_id, service_id) " + + "values (:eventRuleId, :executeDeviceId, :serviceId)") + .setParameter("eventRuleId", eventRuleId) + .setParameter("executeDeviceId", i.getExecuteDeviceId()) + .setParameter("serviceId", i.getServiceId()) + .execute(); + }); + } + + //step 4: 保存关联关系 + List relationIds = eventRule.getExpList().parallelStream().map(MultipleDeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); + if (ToolUtil.isEmpty(relationIds)) { + throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); + } + List productEventRelationList = new ArrayList<>(); + relationIds.forEach(relationId -> { + ProductEventRelation productEventRelation = new ProductEventRelation(); + productEventRelation.setEventRuleId(eventRuleId); + productEventRelation.setRelationId(relationId); + productEventRelation.setInherit(InheritStatus.NO.getCode()); + productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); + productEventRelation.setRemark(eventRule.getRemark()); + productEventRelationList.add(productEventRelation); + }); + DB.saveAll(productEventRelationList); + } + + @Transactional(rollbackFor = Exception.class) + public void updateDeviceEventRule(Long eventRuleId, MultipleDeviceEventRule eventRule) { + + //step 1: 函数表达式 + DB.sqlUpdate("delete from product_event_expression where event_rule_id = :eventRuleId") + .setParameter("eventRuleId", eventRule.getEventRuleId()) + .execute(); + + //step 2: 删除服务方法调用 + DB.sqlUpdate("delete from product_event_service where event_rule_id = :eventRuleId") + .setParameter("eventRuleId", eventRule.getEventRuleId()) + .execute(); + + // 删除和所有设备的关联关系 + new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + // step 3: 保存产品告警规则 + ProductEvent event = initEventRule(eventRule); + event.setEventRuleId(eventRuleId); + event.update(); + + //step 4: 保存 表达式,方便回显 + List expList = new ArrayList<>(); + + eventRule.getExpList().forEach(i -> { + ProductEventExpression exp = initEventExpression(i); + exp.setEventRuleId(eventRuleId); + expList.add(exp); + }); + + DB.saveAll(expList); + + //step 5: 保存触发器 调用 本产品方法 + if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { + eventRule.getDeviceServices().forEach(i -> { + DB.sqlUpdate("insert into product_event_service(event_rule_id,execute_device_id, service_id) values (:eventRuleId, :executeDeviceId, :serviceId)") + .setParameter("eventRuleId", eventRuleId) + .setParameter("executeDeviceId", i.getExecuteDeviceId()) + .setParameter("serviceId", i.getServiceId()) + .execute(); + }); + } + + // step 6: 保存关联关系 + List relationIds = eventRule.getExpList().parallelStream().map(MultipleDeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); + if (ToolUtil.isEmpty(relationIds)) { + throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); + } + List productEventRelationList = new ArrayList<>(); + relationIds.forEach(relationId -> { + ProductEventRelation productEventRelation = new ProductEventRelation(); + productEventRelation.setEventRuleId(eventRuleId); + productEventRelation.setRelationId(relationId); + productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); + productEventRelation.setRemark(eventRule.getRemark()); + productEventRelationList.add(productEventRelation); + }); + DB.saveAll(productEventRelationList); + } + + + private ProductEvent initEventRule(MultipleDeviceEventRule eventRule) { + ProductEvent event = new ProductEvent(); + event.setEventLevel(eventRule.getEventLevel().toString()); + event.setExpLogic(eventRule.getExpLogic()); + event.setEventNotify(eventRule.getEventNotify().toString()); + event.setClassify(eventRule.getClassify()); + event.setEventRuleName(eventRule.getEventRuleName()); + return event; + } + + private ProductEventExpression initEventExpression(MultipleDeviceEventRule.Expression exp) { + ProductEventExpression eventExpression = new ProductEventExpression(); + eventExpression.setEventExpId(exp.getEventExpId()); + eventExpression.setCondition(exp.getCondition()); + eventExpression.setFunction(exp.getFunction()); + eventExpression.setScope(exp.getScope()); + eventExpression.setValue(exp.getValue()); + eventExpression.setDeviceId(exp.getDeviceId()); + eventExpression.setProductAttrKey(exp.getProductAttrKey()); + eventExpression.setProductAttrId(exp.getProductAttrId()); + eventExpression.setProductAttrType(exp.getProductAttrType()); + eventExpression.setPeriod(exp.getPeriod()); + eventExpression.setUnit(exp.getUnit()); + eventExpression.setAttrValueType(exp.getAttrValueType()); + return eventExpression; + } + + /** + * 更新 设备联动规则 zbxId + * + * @param triggerId 设备联动ID + * @param zbxId triggerId + */ + public void updateProductEventRuleZbxId(Long triggerId, String[] zbxId) { + + List triggers = JSONObject.parseArray(zbxTrigger.triggerGet(Arrays.toString(zbxId)), Triggers.class); + + Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.get(0).host, Triggers::getTriggerid)); + + List productEventRelationList = new QProductEventRelation().eventRuleId.eq(triggerId).findList(); + + productEventRelationList.forEach(productEventRelation -> { + if (null != map.get(productEventRelation.getRelationId())) { + DB.update(ProductEventRelation.class).where().eq("eventRuleId", triggerId).eq("relationId", productEventRelation.getRelationId()) + .asUpdate().set("zbxId", map.get(productEventRelation.getRelationId())).update(); + } + }); + } + + /** + * 获取设备联动详情 + * + * @param productEvent + * @param eventRuleId + * @param deviceId + * @return + */ + public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, String deviceId) { + ProductEventRuleDto productEventRuleDto = new ProductEventRuleDto(); + ToolUtil.copyProperties(productEvent, productEventRuleDto); + + List expList = new QProductEventExpression().eventRuleId.eq(eventRuleId).findList(); + expList.forEach(productEventExpression -> { + if (ToolUtil.isEmpty(productEventExpression.getDeviceId())) { + productEventExpression.setDeviceId(deviceId); + } + }); + productEventRuleDto.setExpList(expList); + productEventRuleDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).deviceId.eq(deviceId).findList()); + + ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(deviceId).eventRuleId.eq(eventRuleId).findOne(); + productEventRuleDto.setStatus(productEventRelation.getStatus()); + productEventRuleDto.setRemark(productEventRelation.getRemark()); + productEventRuleDto.setInherit(productEventRelation.getInherit()); + if (InheritStatus.YES.getCode().equals(productEventRelation.getInherit())) { + ProductEventRelation one = new QProductEventRelation().eventRuleId.eq(eventRuleId).inherit.eq(InheritStatus.NO.getCode()).findOne(); + productEventRuleDto.setInheritProductId(one.getRelationId()); + } + + JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); + List tagList = JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class); + + productEventRuleDto.setZbxId(productEventRelation.getZbxId()); + productEventRuleDto.setTags(tagList.stream() + .filter(s -> !s.getTag().equals("__execute__") && !s.getTag().equals("__alarm__") && !s.getTag().equals("__event__")) + .collect(Collectors.toList())); + + return productEventRuleDto; + } + + /** + * 创建 设备联动 + * + * @param triggerName 设备联动名称 + * @param expression 表达式 + * @return 触发器ID + */ + public String[] createZbxTrigger(String triggerName, String expression, Byte level) { + String res = zbxTrigger.triggerCreate(triggerName, expression, level); + return JSON.parseObject(res, TriggerIds.class).getTriggerids(); + } + + /** + * 更新 设备联动 + * + * @param triggerId + * @param expression + * @param level + * @return + */ + public String[] updateZbxTrigger(String triggerId, String expression, Byte level) { + String res = zbxTrigger.triggerUpdate(triggerId, expression, level); + return JSON.parseObject(res, TriggerIds.class).getTriggerids(); + } + + @Data + static class TriggerIds { + private String[] triggerids; + } + + @Data + public static class Triggers { + private String triggerid; + private String description; + private List hosts; + } + + @Data + static class Hosts { + private String hostid; + private String host; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index e2dfad33..860021a5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -225,8 +225,7 @@ public Pager getEventByPage(EventParm eventParm) { if (ToolUtil.isNotEmpty(eventParm.getClassify())) { query.classify.eq(eventParm.getClassify()); } - List productEventRelationList = new QProductEventRelation().select(QProductEventRelation.alias().eventRuleId) - .relationId.eq(eventParm.getProdId()).findList(); + List productEventRelationList = new QProductEventRelation().relationId.eq(eventParm.getProdId()).findList(); if (ToolUtil.isEmpty(productEventRelationList)) { return new Pager<>(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java index 3564a78e..9de1c8ea 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java @@ -5,14 +5,11 @@ import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; -import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.iot.web.product.dto.ProductAttr; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; From aec8f9691ef551fbbbe25882ac9a1ac616a906fd Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Wed, 13 Oct 2021 13:40:25 +0800 Subject: [PATCH 511/763] [fix]: fix pginstall bug --- docs/centos/install.sh | 126 +++++++++++++++++++------ docs/ubuntu/install.sh | 204 +++++++++++++++++++++++++++++------------ 2 files changed, 242 insertions(+), 88 deletions(-) diff --git a/docs/centos/install.sh b/docs/centos/install.sh index e4d2fe9c..2d01bd94 100755 --- a/docs/centos/install.sh +++ b/docs/centos/install.sh @@ -58,7 +58,7 @@ function syscheck() { ## 系统环境初始化 function InitSystem() { - echo -e -n "\033[32mStep1: 初始化系统安装环境... \033[0m" + echo -e -n "\033[32mStep1: 初始化系统安装环境 .... \033[0m" if ! hostnamectl set-hostname zeus-server; then echo -e "\033[31m Error: 主机名修改失败\033[0m" exit @@ -84,7 +84,7 @@ function InitSystem() { echo "ulimit -SHn 65535" >>/etc/rc.local ### 添加用户 - if ! id zeus; then + if ! id zeus &> /dev/null; then groupadd --system zeus || true useradd --system -g zeus zeus || true fi @@ -98,7 +98,7 @@ function InitSystem() { ## 配置 YUM 源 function AddInstallRepo() { - echo -e -n "\033[32mStep2: 配置安装 YUM 源 。。。 \033[0m" + echo -e -n "\033[32mStep2: 配置安装 YUM 源 .... \033[0m" ### 备份原有yum mv /etc/yum.repos.d/* /tmp/ ### 基础 YUM 源 @@ -138,7 +138,7 @@ EOL ## 安装 PostgreSQL function PGInstall() { - echo -e -n "\033[32mStep3: 安装 PostgreSQL.... \033[0m" + echo -e -n "\033[32mStep3: 安装 PostgreSQL .... \033[0m" yum -y install postgresql13.x86_64 \ postgresql13-devel.x86_64 \ postgresql13-plpython3.x86_64 1>/dev/null @@ -174,7 +174,7 @@ function PGInstall() { ## 编译安装 zabbix 5.4 function ZbxInstall() { - echo -e -n "\033[32mStep4: 编译安装 zabbix 。。。 \033[0m" + echo -e -n "\033[32mStep4: 编译安装 zabbix .... \033[0m" ### 安装编译依赖 cd "$basename" || exit yum -y install vim \ @@ -220,7 +220,7 @@ function ZbxInstall() { sed -i "s/\($DB\['TYPE'\]\s*=\).*/\1 \'POSTGRESQL\';/g" $ZABBIX_HOME/zabbix/conf/zabbix.conf.php echo -e "\033[32m [ OK ] \033[0m" ### 数据初始化 - echo -e -n "\033[32mStep5: 初始化 zabbix 数据库 。。。 \033[0m" + echo -e -n "\033[32mStep5: 初始化 zabbix 数据库 .... \033[0m" cd /tmp/ || exit sudo -u postgres createuser zabbix sudo -u postgres /usr/pgsql-13/bin/psql -c "ALTER USER zabbix WITH PASSWORD 'zabbix';" 1> /dev/null @@ -388,7 +388,7 @@ function gettoken(){ function taosinstall() { ### taos 数据安装 - echo -e -n "\033[32mStep9: 安装 taos 数据库。。。 \033[0m" + echo -e -n "\033[32mStep9: 安装 taos 数据库 .... \033[0m" expect << EOF 1> /dev/null spawn rpm -ivh https://www.taosdata.com/assets-download/TDengine-server-2.2.0.2-Linux-x64.rpm expect { @@ -406,7 +406,7 @@ EOF function ZeusInstall() { - echo -e -n "\033[32mStep11: 安装 Zeus-IoT 服务。。。 \033[0m" + echo -e -n "\033[32mStep11: 安装 Zeus-IoT 服务 .... \033[0m" cd $INSTALLDIR || exit ## 创建taos 数据库 taos -s "create database zeus_data" 1> /dev/null @@ -424,37 +424,105 @@ function ZeusInstall() { echo -e "\033[32m [ OK ] \033[0m" } -function clear() { +function clearsys() { + + # 清理用户 if ! id zeus; then userdell zeus fi + function kill9() { + status=`ps -ef | grep $1 | grep -v grep | awk '{print $2}' | wc -l` + + if [ $status -ne 0 ] + then + for i in `ps -ef | grep $1 | grep -v grep | awk '{print $2}'` + do + kill -9 $i + done + fi + } + # 清理应用 ## 清理 zeus - status=`ps -ef | grep zeus-iot-bin | grep java | grep -v grep | awk '{print $2}' | wc -l` - - if [ $status -ne 0 ] - then - for i in `ps -ef | grep zeus-iot-bin | grep java | grep -v grep | awk '{print $2}'` - do - kill -9 $i - done - fi + kill9 zeus-iot-bin + + [ -d /opt/zeus/zeus-iot-bin ] && rm -rf /opt/zeus/zeus-iot-bin + + ## 清理 taos + systemctl stop taosd &> /dev/null + + kill9 taosd + + rpm -e tdengine-2.2.0.2-3.x86_64 &> /dev/null + + [ -d /usr/local/taos ] && rm -rf /usr/local/taos + + ## 清理 zabbix + systemctl stop zabbix-server zabbix-agent &> /dev/null + + kill9 zabbix_server + kill9 zabbix_agent + [ -d /opt/zeus/zabbix ] && rm -rf /opt/zeus/zabbix + [ -f /usr/lib/systemd/system/zabbix-server.service ] && rm -rf /usr/lib/systemd/system/zabbix-server.service + [ -f /usr/lib/systemd/system/zabbix-agent.service ] && rm -rf /usr/lib/systemd/system/zabbix-agent.service + ## 清理 postgresql 数据库 + systemctl stop postgresql-13 &> /dev/null + + kill9 postmaster + + yum remove postgresql13 -y &> /dev/null + + [ -d /opt/zeus/pgdata ] && rm -rf /opt/zeus/pgdata + [ -f /usr/lib/systemd/system/postgresql-13.service ] && rm -rf /usr/lib/systemd/system/postgresql-13.service + + ## 清理 nginx + systemctl stop nginx &> nginx + + kill9 nginx + yum remove nginx -y &> /dev/null + [ -f /usr/lib/systemd/system/nginx ] && rm -rf /usr/lib/systemd/system/nginx } +function sendmsg() { + echo "zabbix 部分已安装成功,zeus iot 可以参照 www.zmops.com 官方文档自定义安装。" + echo "" + echo "zabbix server 访问地址: http:///zabbix" + echo "" + echo "登录用户名:Admin" + echo "登录密 码:zabbix" +} + ## -syscheck -InitSystem -AddInstallRepo -PGInstall -ZbxInstall -PHPInstall -WebInstall -taosinstall -echo "zabbix 部分已安装成功,zeus iot 可以参照 www.zmops.com 官方文档自定义安装。" -# ZeusInstall -# 安装结束 + +function main() { + case $1 in + install) + syscheck + InitSystem + AddInstallRepo + PGInstall + ZbxInstall + PHPInstall + WebInstall + taosinstall + ;; + clear) + clearsys + ;; + *) + echo "请输入 install|clear" + exit 1 + ;; + esac +} + +if main $1 ;then + sendmsg +fi + + diff --git a/docs/ubuntu/install.sh b/docs/ubuntu/install.sh index 2a699dc6..07058dd6 100644 --- a/docs/ubuntu/install.sh +++ b/docs/ubuntu/install.sh @@ -11,55 +11,49 @@ function logprint() { # 安装前准备 ## 系统环境检测 -if [ "$(uname)" != Linux ]; then - echo "该脚本只使用 Linux 系统" - exit $E_BADOD -fi +function syscheck() { -if [ "$UID" -ne 0 ]; then - echo "Must be root to install" - exit $E_NOTROOT -fi -### 操作系统 -if [ ! -f /etc/redhat-release ]; then - if [[ "$(cat /etc/issue)" =~ ^Ubuntu* ]]; then - release=Ubuntu - fi -fi -### 网络 -if ! ping -c 3 mirrors.aliyun.com &>/dev/null; then - echo "网络异常。。。" - exit -fi + if [ "$(uname)" != Linux ]; then + echo "该脚本只使用 Linux 系统" + exit 1 + fi -### cpu、mem、disk -cores=$(grep 10)printf("%s\t%d\n",$7,$3/1024/1024)}' | grep -v -c "/boot") + if [ "$UID" -ne 0 ]; then + echo "Must be root to install" + exit 1 + fi + ### 操作系统 + if [ ! -f /etc/redhat-release ]; then + if [[ "$(cat /etc/issue)" =~ ^Ubuntu* ]]; then + release=Ubuntu + fi + fi + ### 网络 + if ! ping -c 3 mirrors.tuna.tsinghua.edu.cn &>/dev/null; then + echo "网络异常。。。" + exit + fi -if [ "$cores" -lt 0 ] || [ "$memstotal" -lt 0 ] || [ "$disks" -eq 0 ]; then - echo "要求最低配置为 CPU 2核 内存 4GB 存储空间 100G" - exit 70 -fi + ### cpu、mem、disk + cores=$(grep 10)printf("%s\t%d\n",$7,$3/1024/1024)}' | grep -v -c "/boot") + if [ "$cores" -lt 0 ] || [ "$memstotal" -lt 0 ] || [ "$disks" -eq 0 ]; then + echo "要求最低配置为 CPU 2核 内存 4GB 存储空间 100G" + exit 70 + fi +} function InitSystem() { - echo -e -n "\033[32mStep1: 初始化系统安装环境。。。 \033[0m" + echo -e -n "\033[32mStep1: 初始化系统安装环境 .... \033[0m" ## 修改主机名 if ! hostnamectl set-hostname zeus-server; then echo "主机名修改失败" exit fi - ## 关闭 IPV6 监听 - - echo " ">>/etc/sysctl.conf - echo "# made for disabled IPv6 in $(date +%F)">>/etc/sysctl.conf - echo 'net.ipv6.conf.all.disable_ipv6 = 1'>>/etc/sysctl.conf - echo 'net.ipv6.conf.default.disable_ipv6 = 1'>>/etc/sysctl.conf - echo 'net.ipv6.conf.lo.disable_ipv6 = 1'>>/etc/sysctl.conf - sysctl -p ## 修改时区 if ! ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime; then @@ -69,45 +63,47 @@ function InitSystem() { ## 更新下载源 cp /etc/apt/sources.list /etc/apt/sources.listbak sed -i 's%\(^deb http\{0,1\}\:\/\/\).*\(/ubuntu.*\)%\1mirrors.tuna.tsinghua.edu.cn\2%g' /etc/apt/sources.list + apt-get update 1> /dev/null && apt-get install -y ca-certificates 1> /dev/null + #sed -i 's/http/https/g' /etc/apt/sources.list echo -e "\033[32m [ OK ] \033[0m" } function AddInstallRepo() { - echo -e -n "\033[32mStep2: 配置安装 YUM 源 。。。 \033[0m" + echo -e -n "\033[32mStep2: 配置安装 YUM 源 .... \033[0m" ## 安装PGsql源 echo "deb https://mirrors.tuna.tsinghua.edu.cn/postgresql/repos/apt/ $(lsb_release -c -s)-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list &> /dev/null - wget --quiet -O - https://mirrors.tuna.tsinghua.edu.cn/postgresql/repos/apt/ACCC4CF8.asc | sudo apt-key add - + wget --quiet -O - https://mirrors.tuna.tsinghua.edu.cn/postgresql/repos/apt/ACCC4CF8.asc | sudo apt-key add - 1> /dev/null #sudo sh -c "echo 'deb https://packagecloud.io/timescale/timescaledb/ubuntu/ $(lsb_release -c -s) main' > /etc/apt/sources.list.d/timescaledb.list" #wget --quiet -O - https://packagecloud.io/timescale/timescaledb/gpgkey | sudo apt-key add - ## 安装zabbix 5.4 源 - wget -q https://repo.zabbix.com/zabbix/5.4/ubuntu/pool/main/z/zabbix-release/zabbix-release_5.4-1+ubuntu$(lsb_release -r -s)_all.deb + wget --quiet -c https://repo.zabbix.com/zabbix/5.4/ubuntu/pool/main/z/zabbix-release/zabbix-release_5.4-1+ubuntu$(lsb_release -r -s)_all.deb 1> /dev/null dpkg -i zabbix-release_5.4-1+ubuntu$(lsb_release -r -s)_all.deb 1> /dev/null - apt update 1> /dev/null && apt install -y openjdk-8-jdk expect 1> /dev/null + apt-get update 1> /dev/null && apt-get install -y openjdk-8-jdk expect 1> /dev/null echo -e "\033[32m [ OK ] \033[0m" } function PGInstall() { - echo -e -n "\033[32mStep3: 安装 PostgreSQL.... \033[0m" + echo -e -n "\033[32mStep3: 安装 PostgreSQL .... \033[0m" # PG 安装 - apt install postgresql-13 -y 1> /dev/null + apt-get install postgresql-13 -y 1> /dev/null #echo "shared_preload_libraries = 'timescaledb'" >> /etc/postgresql/13/main/postgresql.conf cd /tmp || exit - sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD 'postgres';" 2> /tmp/pg.log - systemctl restart postgresql + sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD 'postgres';" 1> /dev/null + systemctl restart postgresql 1> /dev/null echo -e "\033[32m [ OK ] \033[0m" } function ZbxInstall() { - echo -e -n "\033[32mStep4: 编译安装 zabbix 。。。 \033[0m" + echo -e -n "\033[32mStep4: 编译安装 zabbix .... \033[0m" # zabbix 安装 - apt install zabbix-server-pgsql zabbix-frontend-php php-pgsql zabbix-nginx-conf zabbix-sql-scripts zabbix-agent -y 1> /dev/null + apt-get install zabbix-server-pgsql zabbix-frontend-php php-pgsql zabbix-nginx-conf zabbix-sql-scripts zabbix-agent -y 1> /dev/null PHPCONF=/etc/php/$(ls /etc/php/)/fpm/php.ini # 初始化 zabbix 配置 cd /tmp || exit sudo -u postgres createuser zabbix - sudo -u postgres psql -c "ALTER USER zabbix WITH PASSWORD 'zabbix';" + sudo -u postgres psql -c "ALTER USER zabbix WITH PASSWORD 'zabbix';" 1> /dev/null sudo -u postgres createdb -O zabbix zabbix zcat /usr/share/doc/zabbix-sql-scripts/postgresql/create.sql.gz | sudo -u zabbix psql zabbix 1> /dev/null #echo "CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;" | sudo -u postgres psql zabbix @@ -186,8 +182,8 @@ function gettoken(){ function taosinstall() { ### taos 数据安装 - echo -e -n "\033[32mStep5: 安装 taos 数据库。。。 \033[0m" - wget https://www.taosdata.com/assets-download/TDengine-server-2.2.0.2-Linux-x64.deb + echo -e -n "\033[32mStep5: 安装 taos 数据库 .... \033[0m" + wget --quiet -c https://www.taosdata.com/assets-download/TDengine-server-2.2.0.2-Linux-x64.deb 1> /dev/null expect << EOF 1> /dev/null spawn dpkg -i TDengine-server-2.2.0.2-Linux-x64.deb expect { @@ -195,14 +191,14 @@ function taosinstall() { "*skip:" { send "\n" } } EOF - systemctl enable taosd - systemctl start taosd + systemctl enable taosd 1> /dev/null + systemctl start taosd 1> /dev/null echo -e "\033[32m [ OK ] \033[0m" } function ZeusInstall() { - echo -e -n "\033[32mStep6: 安装 Zeus-IoT 服务。。。 \033[0m" + echo -e -n "\033[32mStep6: 安装 Zeus-IoT 服务 .... \033[0m" [ ! -d /opt/zeus ] && mkdir -p /opt/zeus cd /opt/zeus || exit ## 创建taos 数据库 @@ -220,12 +216,102 @@ function ZeusInstall() { } +function sendmsg() { + echo "zabbix 部分已安装成功,zeus iot 可以参照 www.zmops.com 官方文档自定义安装。" + echo "" + echo "zabbix server 访问地址: http:///zabbix" + echo "" + echo "登录用户名:Admin" + echo "登录密 码:zabbix" +} + + +function clearsys() { + + + # 清理用户 + if ! id zeus; then + userdell zeus + fi + + function kill9() { + status=`ps -ef | grep $1 | grep -v grep | awk '{print $2}' | wc -l` + + if [ $status -ne 0 ] + then + for i in `ps -ef | grep $1 | grep -v grep | awk '{print $2}'` + do + kill -9 $i + done + fi + } + + # 清理应用 + ## 清理 zeus + kill9 zeus-iot-bin + + [ -d /opt/zeus/zeus-iot-bin ] && rm -rf /opt/zeus/zeus-iot-bin + + ## 清理 taos + systemctl stop taosd &> /dev/null + + kill9 taosd + + apt-get remove tdengine-2.2.0.2-3.x86_64 &> /dev/null + + [ -d /usr/local/taos ] && rm -rf /usr/local/taos + + ## 清理 zabbix + systemctl stop zabbix-server zabbix-agent &> /dev/null + + kill9 zabbix_server + kill9 zabbix_agent + + [ -d /opt/zeus/zabbix ] && rm -rf /opt/zeus/zabbix + [ -f /usr/lib/systemd/system/zabbix-server.service ] && rm -rf /usr/lib/systemd/system/zabbix-server.service + [ -f /usr/lib/systemd/system/zabbix-agent.service ] && rm -rf /usr/lib/systemd/system/zabbix-agent.service + + ## 清理 postgresql 数据库 + systemctl stop postgresql &> /dev/null + + kill9 postmaster + + apt-get remove postgresql-13 -y &> /dev/null + + [ -d /opt/zeus/pgdata ] && rm -rf /opt/zeus/pgdata + [ -f /usr/lib/systemd/system/postgresql.service ] && rm -rf /usr/lib/systemd/system/postgresql.service + + ## 清理 nginx + systemctl stop nginx &> nginx + + kill9 nginx + apt-get remove nginx -y &> /dev/null + [ -f /usr/lib/systemd/system/nginx ] && rm -rf /usr/lib/systemd/system/nginx +} + + +function main() { + case $1 in + install) + syscheck + InitSystem + AddInstallRepo + PGInstall + ZbxInstall + taosinstall + ZeusInstall + ;; + clear) + clearsys + ;; + *) + echo "请输入 install|clear" + exit 1 + ;; + esac +} +if main $1 ;then + sendmsg +fi -InitSystem -AddInstallRepo -PGInstall -ZbxInstall -taosinstall -#ZeusInstall -echo "zabbix 部分已安装成功,zeus iot 可以参照 www.zmops.com 官方文档自定义安装。" From e853214b2cd56095ef3a22369114594dc7ecc896 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Wed, 13 Oct 2021 13:58:40 +0800 Subject: [PATCH 512/763] [fix]: fix install script --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 20a2f49f..6d1bd9f2 100644 --- a/README.md +++ b/README.md @@ -79,13 +79,13 @@ The Zeus IoT production environment can only be installed on a Linux system, eit - Centos7/Redhat7 ```shell - curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/centos/install.sh | bash + curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/centos/install.sh | bash install ``` - Ubuntu 18.04 ```shell - curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/ubuntu/install.sh | bash + curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/ubuntu/install.sh | bash install ``` After Zeus IoT is successfully installed, you can use http://IP:9090 to access the ZeusIoT Console with the default account and password (Admin/zabbix). @@ -93,3 +93,4 @@ After Zeus IoT is successfully installed, you can use http://IP:9090 to access t ## Demo Environment Using the account `Admin / zeus123` to log in the [demo environment](https://zeusdemo.zmops.cn/). Please note the account is granted view access. + From 812267e2bfe52788b1f75f4640c56f43efff184d Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Wed, 13 Oct 2021 14:20:41 +0800 Subject: [PATCH 513/763] [fix]: fix install script --- README.md | 4 ++-- docs/centos/install.sh | 15 +++------------ docs/ubuntu/install.sh | 22 +++------------------- 3 files changed, 8 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 6d1bd9f2..8ad27335 100644 --- a/README.md +++ b/README.md @@ -79,13 +79,13 @@ The Zeus IoT production environment can only be installed on a Linux system, eit - Centos7/Redhat7 ```shell - curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/centos/install.sh | bash install + curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/centos/install.sh | bash ``` - Ubuntu 18.04 ```shell - curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/ubuntu/install.sh | bash install + curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/ubuntu/install.sh | bash ``` After Zeus IoT is successfully installed, you can use http://IP:9090 to access the ZeusIoT Console with the default account and password (Admin/zabbix). diff --git a/docs/centos/install.sh b/docs/centos/install.sh index 2d01bd94..c266fec7 100755 --- a/docs/centos/install.sh +++ b/docs/centos/install.sh @@ -500,8 +500,7 @@ function sendmsg() { ## function main() { - case $1 in - install) + syscheck InitSystem AddInstallRepo @@ -510,18 +509,10 @@ function main() { PHPInstall WebInstall taosinstall - ;; - clear) - clearsys - ;; - *) - echo "请输入 install|clear" - exit 1 - ;; - esac + } -if main $1 ;then +if main;then sendmsg fi diff --git a/docs/ubuntu/install.sh b/docs/ubuntu/install.sh index 07058dd6..01fd6d13 100644 --- a/docs/ubuntu/install.sh +++ b/docs/ubuntu/install.sh @@ -228,12 +228,6 @@ function sendmsg() { function clearsys() { - - # 清理用户 - if ! id zeus; then - userdell zeus - fi - function kill9() { status=`ps -ef | grep $1 | grep -v grep | awk '{print $2}' | wc -l` @@ -291,27 +285,17 @@ function clearsys() { function main() { - case $1 in - install) syscheck InitSystem AddInstallRepo PGInstall ZbxInstall taosinstall - ZeusInstall - ;; - clear) - clearsys - ;; - *) - echo "请输入 install|clear" - exit 1 - ;; - esac + #ZeusInstall + } -if main $1 ;then +if main;then sendmsg fi From ea87d06f20c67f04b126a9931e9a98fb2071fbcb Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Wed, 13 Oct 2021 14:24:42 +0800 Subject: [PATCH 514/763] [fix]: fix install script --- docs/centos/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/centos/install.sh b/docs/centos/install.sh index c266fec7..549ab706 100755 --- a/docs/centos/install.sh +++ b/docs/centos/install.sh @@ -50,7 +50,7 @@ function syscheck() { memstotal=$(grep 10)printf("%s\t%d\n",$7,$3/1024/1024)}' | grep -v -c "/boot") - if [ "$cores" -lt 2 ] || [ "$memstotal" -lt 4 ] || [ "$disks" -eq 100 ]; then + if [ "$cores" -lt 2 ] || [ "$memstotal" -lt 4 ] || [ "$disks" -eq 0 ]; then echo -e "\033[31m Error: 要求系统最低配置为 CPU 2核 内存 4GB 存储空间 100G \033[0m" exit fi From 744fcdb9a117ae5ae7ad2d6681bd0be07b99bb54 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Wed, 13 Oct 2021 14:32:03 +0800 Subject: [PATCH 515/763] [fix]: fix install script --- docs/centos/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/centos/install.sh b/docs/centos/install.sh index 549ab706..cc869d53 100755 --- a/docs/centos/install.sh +++ b/docs/centos/install.sh @@ -50,7 +50,7 @@ function syscheck() { memstotal=$(grep 10)printf("%s\t%d\n",$7,$3/1024/1024)}' | grep -v -c "/boot") - if [ "$cores" -lt 2 ] || [ "$memstotal" -lt 4 ] || [ "$disks" -eq 0 ]; then + if [ "$cores" -lt 0 ] || [ "$memstotal" -lt 0 ] || [ "$disks" -eq 0 ]; then echo -e "\033[31m Error: 要求系统最低配置为 CPU 2核 内存 4GB 存储空间 100G \033[0m" exit fi From 5bd4b11f805df00f61ee66f387791148272d7ca9 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Wed, 13 Oct 2021 15:58:29 +0800 Subject: [PATCH 516/763] [fix]: fix postgresql install faile --- docs/centos/install.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/centos/install.sh b/docs/centos/install.sh index cc869d53..97304b39 100755 --- a/docs/centos/install.sh +++ b/docs/centos/install.sh @@ -109,6 +109,18 @@ name=CentOS-\$releasever - Base baseurl=http://mirrors.tuna.tsinghua.edu.cn/centos/\$releasever/os/\$basearch/ gpgcheck=0 +[updates] +name=CentOS-\$releasever - Updates +baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/\$releasever/updates/\$basearch/ +gpgcheck=0 +enabled=1 + +[extras] +name=CentOS-\$releasever - Extras +baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/\$releasever/extras/\$basearch/ +gpgcheck=0 +enabled=1 + [epel] name=Extra Packages for Enterprise Linux 7 - \$basearch baseurl=https://mirrors.tuna.tsinghua.edu.cn/epel/7/\$basearch From 9ea8496b3520c0b7221d32114a11c5331078db0d Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 13 Oct 2021 16:01:35 +0800 Subject: [PATCH 517/763] [fix]: fix multiplue device event --- .../MultipleDeviceEventTriggerController.java | 32 +++----- .../device/dto/DeviceEventRelationDto.java | 18 +++++ .../device/dto/MultipleDeviceEventDto.java | 44 +++++++++++ .../device/dto/MultipleDeviceServiceDto.java | 15 ++++ .../MultipleDeviceEventRuleService.java | 78 ++++++++++++------- .../iot/web/product/dto/ProductEventDto.java | 4 +- 6 files changed, 142 insertions(+), 49 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRelationDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceServiceDto.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java index 9a634d81..f2c83e31 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java @@ -15,11 +15,11 @@ import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.MultipleDeviceEventDto; import com.zmops.iot.web.device.dto.MultipleDeviceEventRule; import com.zmops.iot.web.device.dto.param.MultipleDeviceEventParm; import com.zmops.iot.web.device.service.MultipleDeviceEventRuleService; import com.zmops.iot.web.exception.enums.BizExceptionEnum; -import com.zmops.iot.web.product.dto.ProductEventDto; import com.zmops.zeus.driver.service.ZbxTrigger; import io.ebean.DB; import io.ebean.annotation.Transactional; @@ -57,7 +57,7 @@ public class MultipleDeviceEventTriggerController { * @return */ @PostMapping("/getEventByPage") - public Pager getEventByPage(@RequestBody MultipleDeviceEventParm eventParm) { + public Pager getEventByPage(@RequestBody MultipleDeviceEventParm eventParm) { return multipleDeviceEventRuleService.getEventByPage(eventParm); } @@ -100,7 +100,7 @@ public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEn String[] triggerIds = multipleDeviceEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); //step 4: zbx 触发器创建 Tag - Map tags = new ConcurrentHashMap<>(3); + Map tags = new ConcurrentHashMap<>(1); if (ToolUtil.isNotEmpty(eventRule.getTags())) { tags = eventRule.getTags().stream() .collect(Collectors.toMap(MultipleDeviceEventRule.Tag::getTag, MultipleDeviceEventRule.Tag::getValue, (k1, k2) -> k2)); @@ -150,22 +150,12 @@ public ResponseData updateProductEventStatus(@RequestBody @Validated(value = Bas @Transactional @PostMapping("/update") public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) MultipleDeviceEventRule eventRule) { - int count = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()) - .findCount(); - if (count == 0) { + ProductEventRelation productEventRelation = new QProductEventRelation().setMaxRows(1).eventRuleId.eq(eventRule.getEventRuleId()) + .findOne(); + if (null == productEventRelation) { throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); } - //来自产品的告警规则 只能修改备注 - count = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).inherit.eq(InheritStatus.YES.getCode()) - .findCount(); - if (count > 1) { - DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).eq("relationId", eventRule.getDeviceId()) - .asUpdate().set("remark", eventRule.getRemark()).update(); - - return ResponseData.success(eventRule.getEventRuleId()); - } - //step 1: 删除原有的 关联关系 multipleDeviceEventRuleService.updateDeviceEventRule(eventRule.getEventRuleId(), eventRule); @@ -174,13 +164,13 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); //step 2: zbx 保存触发器 - String[] triggerIds = multipleDeviceEventRuleService.updateZbxTrigger(eventRule.getZbxId(), expression, eventRule.getEventLevel()); + String[] triggerIds = multipleDeviceEventRuleService.updateZbxTrigger(productEventRelation.getZbxId(), expression, eventRule.getEventLevel()); //step 4: zbx 触发器创建 Tag - Map tags = eventRule.getTags().stream() - .collect(Collectors.toMap(MultipleDeviceEventRule.Tag::getTag, MultipleDeviceEventRule.Tag::getValue, (k1, k2) -> k2)); - if (ToolUtil.isEmpty(tags)) { - tags = new HashMap<>(2); + Map tags = new ConcurrentHashMap<>(1); + if (ToolUtil.isNotEmpty(eventRule.getTags())) { + tags = eventRule.getTags().stream() + .collect(Collectors.toMap(MultipleDeviceEventRule.Tag::getTag, MultipleDeviceEventRule.Tag::getValue, (k1, k2) -> k2)); } if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRelationDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRelationDto.java new file mode 100644 index 00000000..4435e582 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRelationDto.java @@ -0,0 +1,18 @@ +package com.zmops.iot.web.device.dto; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class DeviceEventRelationDto { + private Long id; + private Long eventRuleId; + private String relationId; + private String zbxId; + private String inherit; + private String status; + private String remark; + private String triggerDevice; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java new file mode 100644 index 00000000..1c93a3d4 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java @@ -0,0 +1,44 @@ +package com.zmops.iot.web.device.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +/** + * @author yefei + **/ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class MultipleDeviceEventDto { + + private Long eventRuleId; + + private Byte eventNotify; + + private String eventRuleName; + + @CachedValue(value = "EVENT_LEVEL") + private String eventLevel; + + @CachedValue(value = "STATUS") + private String status; + + @CachedValue(value = "WHETHER") + private String inherit; + + private String remark; + private String classify; + private String expLogic; + @CachedValue(type = DicType.SysUserName) + private Long createUser; + private String createTime; + @CachedValue(type = DicType.SysUserName) + private Long updateUser; + private String updateTime; + + private String triggerDevice; + + private String executeDevice; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceServiceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceServiceDto.java new file mode 100644 index 00000000..afb49721 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceServiceDto.java @@ -0,0 +1,15 @@ +package com.zmops.iot.web.device.dto; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class MultipleDeviceServiceDto { + + private Long eventRuleId; + + private String executeDevice; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index c6b49151..5fde1f21 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -15,10 +15,12 @@ import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.DeviceEventRelationDto; +import com.zmops.iot.web.device.dto.MultipleDeviceEventDto; import com.zmops.iot.web.device.dto.MultipleDeviceEventRule; +import com.zmops.iot.web.device.dto.MultipleDeviceServiceDto; import com.zmops.iot.web.device.dto.param.MultipleDeviceEventParm; import com.zmops.iot.web.exception.enums.BizExceptionEnum; -import com.zmops.iot.web.product.dto.ProductEventDto; import com.zmops.iot.web.product.dto.ProductEventRuleDto; import com.zmops.zeus.driver.service.ZbxTrigger; import io.ebean.DB; @@ -28,7 +30,6 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -48,7 +49,7 @@ public class MultipleDeviceEventRuleService { * @param eventParm * @return */ - public Pager getEventByPage(MultipleDeviceEventParm eventParm) { + public Pager getEventByPage(MultipleDeviceEventParm eventParm) { QProductEvent query = new QProductEvent(); if (ToolUtil.isNotEmpty(eventParm.getEventRuleName())) { @@ -58,23 +59,59 @@ public Pager getEventByPage(MultipleDeviceEventParm eventParm) query.classify.eq(eventParm.getClassify()); } - List list = query.setFirstRow((eventParm.getPage() - 1) * eventParm.getMaxRow()) - .setMaxRows(eventParm.getMaxRow()).orderBy(" create_time desc").asDto(ProductEventDto.class).findList(); + List list = query.setFirstRow((eventParm.getPage() - 1) * eventParm.getMaxRow()) + .setMaxRows(eventParm.getMaxRow()).orderBy(" create_time desc").asDto(MultipleDeviceEventDto.class).findList(); if (ToolUtil.isEmpty(list)) { new Pager<>(list, 0); } - //查询状态 备注 - List eventRuleIds = list.parallelStream().map(ProductEventDto::getEventRuleId).collect(Collectors.toList()); - List productEventRelationList = new QProductEventRelation().eventRuleId.in(eventRuleIds) - .findList(); - Map productEventRelationMap = productEventRelationList.parallelStream().collect(Collectors.toMap(ProductEventRelation::getEventRuleId, o -> o, (v1, v2) -> v2)); + //关联状态 备注 触发设备 + List eventRuleIds = list.parallelStream().map(MultipleDeviceEventDto::getEventRuleId).collect(Collectors.toList()); + String sql = "SELECT " + + " pr.event_rule_id, " + + " array_to_string( ARRAY_AGG ( d.NAME ), ',' ) triggerDevice, " + + " pr.status," + + " pr.remark " + + "FROM " + + " product_event_relation pr " + + " LEFT JOIN device d ON pr.relation_id = d.device_id " + + "WHERE " + + " pr.event_rule_id IN (:eventRuleIds) " + + "GROUP BY " + + " pr.event_rule_id,pr.status,pr.remark"; + List deviceEventRelationDtos = DB.findDto(DeviceEventRelationDto.class, sql).setParameter("eventRuleIds", eventRuleIds).findList(); + Map productEventRelationMap = deviceEventRelationDtos.parallelStream() + .collect(Collectors.toConcurrentMap(DeviceEventRelationDto::getEventRuleId, o -> o)); + + //关联 执行设备 + sql = "SELECT " + + " ps.event_rule_id, " + + " array_to_string( ARRAY_AGG ( d.NAME ), ',' ) executeDevice " + + "FROM " + + " product_event_service ps " + + " LEFT JOIN device d ON ps.execute_device_id = d.device_id " + + "WHERE " + + " ps.event_rule_id IN (:eventRuleIds) " + + "GROUP BY " + + " ps.event_rule_id"; + List deviceServiceDtos = DB.findDto(MultipleDeviceServiceDto.class, sql).setParameter("eventRuleIds", eventRuleIds).findList(); + Map deviceServiceMap = deviceServiceDtos.parallelStream() + .collect(Collectors.toConcurrentMap(MultipleDeviceServiceDto::getEventRuleId, o -> o)); list.forEach(productEventDto -> { - if (null != productEventRelationMap.get(productEventDto.getEventRuleId())) { - productEventDto.setStatus(productEventRelationMap.get(productEventDto.getEventRuleId()).getStatus()); - productEventDto.setRemark(productEventRelationMap.get(productEventDto.getEventRuleId()).getRemark()); + DeviceEventRelationDto deviceEventRelationDto = productEventRelationMap.get(productEventDto.getEventRuleId()); + if (null != deviceEventRelationDto) { + String status = deviceEventRelationDto.getStatus(); + String remark = deviceEventRelationDto.getRemark(); + String triggerDevice = deviceEventRelationDto.getTriggerDevice(); + productEventDto.setStatus(status); + productEventDto.setRemark(remark); + productEventDto.setTriggerDevice(triggerDevice); + } + MultipleDeviceServiceDto deviceServiceDto = deviceServiceMap.get(productEventDto.getEventRuleId()); + if (null != deviceServiceDto) { + productEventDto.setExecuteDevice(deviceServiceDto.getExecuteDevice()); } }); @@ -230,19 +267,8 @@ private ProductEventExpression initEventExpression(MultipleDeviceEventRule.Expre * @param zbxId triggerId */ public void updateProductEventRuleZbxId(Long triggerId, String[] zbxId) { - - List triggers = JSONObject.parseArray(zbxTrigger.triggerGet(Arrays.toString(zbxId)), Triggers.class); - - Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.get(0).host, Triggers::getTriggerid)); - - List productEventRelationList = new QProductEventRelation().eventRuleId.eq(triggerId).findList(); - - productEventRelationList.forEach(productEventRelation -> { - if (null != map.get(productEventRelation.getRelationId())) { - DB.update(ProductEventRelation.class).where().eq("eventRuleId", triggerId).eq("relationId", productEventRelation.getRelationId()) - .asUpdate().set("zbxId", map.get(productEventRelation.getRelationId())).update(); - } - }); + DB.update(ProductEventRelation.class).where().eq("eventRuleId", triggerId) + .asUpdate().set("zbxId", zbxId[0]).update(); } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java index 7d2bc304..ee9548e1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java @@ -32,9 +32,9 @@ public class ProductEventDto { private String classify; private String expLogic; @CachedValue(type = DicType.SysUserName) - private String createUser; + private Long createUser; private String createTime; @CachedValue(type = DicType.SysUserName) - private String updateUser; + private Long updateUser; private String updateTime; } From 8ff1ce8339f9d95f248a5855e1385ac2e3b85509 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 13 Oct 2021 16:19:15 +0800 Subject: [PATCH 518/763] [fix]:fix problem list --- .../src/main/resources/api-json/problem/problem.get.ftl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl index e781c814..fc505bf6 100644 --- a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl +++ b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl @@ -20,8 +20,7 @@ <#if severity?? && severity != ''> "severities":${severity}, - "evaltype":2, - "tags":[{"tag": "__alarm__"},{"tag": "__execute__"}], + "tags":[{"tag": "__alarm__"}], "filter":{ "source":"0" }, From c18b1c440349b6bb8b742bfcad5706c773745407 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Wed, 13 Oct 2021 16:37:19 +0800 Subject: [PATCH 519/763] [fix]: fix install script --- README.md | 4 ++-- docs/README.md | 4 ++-- docs/centos/install.sh | 18 +++++++++++++----- docs/ubuntu/install.sh | 16 +++++++++++++--- 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 8ad27335..f3d6448b 100644 --- a/README.md +++ b/README.md @@ -79,13 +79,13 @@ The Zeus IoT production environment can only be installed on a Linux system, eit - Centos7/Redhat7 ```shell - curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/centos/install.sh | bash + curl -sL https://github.com/zmops/zeus-iot/raw/develop/docs/centos/install.sh | bash -s install ``` - Ubuntu 18.04 ```shell - curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/ubuntu/install.sh | bash + curl -sL https://github.com/zmops/zeus-iot/raw/develop/docs/ubuntu/install.sh | bash -s install ``` After Zeus IoT is successfully installed, you can use http://IP:9090 to access the ZeusIoT Console with the default account and password (Admin/zabbix). diff --git a/docs/README.md b/docs/README.md index d6983ff3..8ab2f8f3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -22,13 +22,13 @@ - Centos7/Redhat7 ```shell - curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/centos/install.sh | bash + curl -sL https://github.com/zmops/zeus-iot/raw/develop/docs/centos/install.sh | bash -s install ``` - Ubuntu 20.04 ```shell - curl -L https://github.com/zmops/zeus-iot/raw/develop/docs/ubuntu/install.sh | bash + curl -sL https://github.com/zmops/zeus-iot/raw/develop/docs/ubuntu/install.sh | bash -s install ``` ## 自定义安装 diff --git a/docs/centos/install.sh b/docs/centos/install.sh index 97304b39..ae848a59 100755 --- a/docs/centos/install.sh +++ b/docs/centos/install.sh @@ -511,8 +511,10 @@ function sendmsg() { ## -function main() { +function main() { + case $1 in + install) syscheck InitSystem AddInstallRepo @@ -521,11 +523,17 @@ function main() { PHPInstall WebInstall taosinstall - + ;; + clear) + clearsys + ;; + *) + echo "请输入 install|clear" + exit 1 + ;; + esac } -if main;then +if main $1 ;then sendmsg fi - - diff --git a/docs/ubuntu/install.sh b/docs/ubuntu/install.sh index 01fd6d13..2bfc5173 100644 --- a/docs/ubuntu/install.sh +++ b/docs/ubuntu/install.sh @@ -284,18 +284,28 @@ function clearsys() { } + function main() { + case $1 in + install) syscheck InitSystem AddInstallRepo PGInstall ZbxInstall taosinstall - #ZeusInstall - + ;; + clear) + clearsys + ;; + *) + echo "请输入 install|clear" + exit 1 + ;; + esac } -if main;then +if main $1 ;then sendmsg fi From 7dd50e80ffabbda354cd0c034b1c9641507c87f2 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Wed, 13 Oct 2021 17:34:44 +0800 Subject: [PATCH 520/763] [fix]: fix install doc --- docs/README.md | 2 +- docs/centos/install.sh | 2 +- docs/ubuntu/install.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index 8ab2f8f3..c83dd96f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -87,7 +87,7 @@ - 直接下载 release 包 ```shell -wget -c https://packages.zmops.cn/zeus-iot/zeus-iot-bin.tar.gz + ``` - 从源码编译 diff --git a/docs/centos/install.sh b/docs/centos/install.sh index ae848a59..c74d732a 100755 --- a/docs/centos/install.sh +++ b/docs/centos/install.sh @@ -10,7 +10,7 @@ ZABBIX_HOME=$INSTALLDIR/zabbix PHP_CONF=/etc/opt/rh/rh-php73 sqldir=$basename/zabbix-5.4.3/database/postgresql PGDATA=$INSTALLDIR/pgdata -zeusurl=https://packages.zmops.cn/zeus-iot/zeus-iot-bin.tar.gz +zeusurl= function logprint() { if [ $? != 0 ]; then diff --git a/docs/ubuntu/install.sh b/docs/ubuntu/install.sh index 2bfc5173..5ed0f6bb 100644 --- a/docs/ubuntu/install.sh +++ b/docs/ubuntu/install.sh @@ -203,7 +203,7 @@ function ZeusInstall() { cd /opt/zeus || exit ## 创建taos 数据库 taos -s "create database zeus_data" 1> /dev/null - wget -c https://packages.zmops.cn/zeus-iot/zeus-iot-bin.tar.gz -o /dev/null -O - | tar -xz + wget -c https:///zeus-iot/zeus-iot-bin.tar.gz -o /dev/null -O - | tar -xz gettoken ## 数据库导入 sudo -u postgres createdb -E Unicode -T template0 zeus-iot From 2ebed254dfc011e8f9ade14c4243244b0cce9c14 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 13 Oct 2021 18:10:52 +0800 Subject: [PATCH 521/763] [fix]: fix service param --- .../domain/product/ProductServiceParam.java | 1 + .../device/service/work/SaveOtherWorker.java | 3 +++ .../product/service/ProductSvcService.java | 10 +++++++++ .../service/work/SaveProdSvcWorker.java | 13 +++++++++++ .../service/work/UpdateProdSvcWorker.java | 22 +++++++++++++++++++ 5 files changed, 49 insertions(+) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceParam.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceParam.java index f94b7a24..857bd45d 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceParam.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceParam.java @@ -23,4 +23,5 @@ public class ProductServiceParam { private String key; private String remark; private String value; + private String deviceId; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java index 1572ecc2..a9ba4c01 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java @@ -68,6 +68,9 @@ public Boolean action(DeviceDto deviceDto, Map> allW //服务关联 DB.sqlUpdate("insert into product_service_relation (relation_id,service_id,inherit) SELECT :deviceId,service_id,1 from product_service_relation where relation_id=:relationId") .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "").execute(); + //服务参数 + DB.sqlUpdate("insert into product_service_param (device_id,service_id,key,name,value,remark) SELECT :deviceId,service_id,key,name,value,remark from product_service_param where device_id=:relationId") + .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "").execute(); //上下线规则关联 DB.sqlUpdate("insert into product_status_function_relation (relation_id,rule_id,inherit) SELECT :deviceId,rule_id,1 from product_status_function_relation where relation_id=:relationId") diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index 8a3a3421..748dcd07 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -149,6 +149,7 @@ public ProductServiceDto create(ProductServiceDto productServiceDto) { if (ToolUtil.isNotEmpty(productServiceDto.getProductServiceParamList())) { for (ProductServiceParam productServiceParam : productServiceDto.getProductServiceParamList()) { productServiceParam.setServiceId(serviceId); + productServiceParam.setDeviceId(productServiceDto.getRelationId()); } DB.saveAll(productServiceDto.getProductServiceParamList()); } @@ -192,6 +193,15 @@ public ProductServiceDto update(ProductServiceDto productServiceDto) { DB.saveAll(productServiceDto.getProductServiceParamList()); } + //同步到设备 + WorkerWrapper updateProdSvcWork = WorkerWrapper.builder().worker(updateProdSvcWorker).param(productServiceDto).build(); + + try { + Async.work(1000, updateProdSvcWork).awaitFinish(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return productServiceDto; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java index 8597a57b..c8cf83a6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java @@ -4,7 +4,9 @@ import com.zmops.iot.async.callback.IWorker; import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.product.ProductServiceRelation; +import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.product.dto.ProductServiceDto; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; @@ -31,15 +33,26 @@ public Boolean action(ProductServiceDto productServiceDto, Map deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); + List productServiceRelationList = new ArrayList<>(); + List productServiceParamList = new ArrayList<>(); for (String deviceId : deviceIds) { ProductServiceRelation productServiceRelation = new ProductServiceRelation(); productServiceRelation.setRelationId(deviceId); productServiceRelation.setServiceId(productServiceDto.getId()); productServiceRelation.setInherit("1"); productServiceRelationList.add(productServiceRelation); + + productServiceDto.getProductServiceParamList().forEach(productServiceParam -> { + ProductServiceParam param = new ProductServiceParam(); + ToolUtil.copyProperties(productServiceParam,param); + param.setDeviceId(deviceId); + param.setServiceId(productServiceDto.getId()); + productServiceParamList.add(param); + }); } DB.saveAll(productServiceRelationList); + DB.saveAll(productServiceParamList); return true; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java index 53d4bd31..cbc4e2f2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java @@ -3,10 +3,17 @@ import com.zmops.iot.async.callback.IWorker; import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductServiceParam; +import com.zmops.iot.domain.product.query.QProductServiceParam; +import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.product.dto.ProductServiceDto; +import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import java.util.ArrayList; +import java.util.List; import java.util.Map; /** @@ -23,6 +30,21 @@ public class UpdateProdSvcWorker implements IWorker public Boolean action(ProductServiceDto productServiceDto, Map> map) { log.debug("处理产品服务修改 同步到设备工作…………"); + String prodId = productServiceDto.getRelationId(); + + List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); + + List productServiceParamList = new ArrayList<>(); + for (String deviceId : deviceIds) { + productServiceDto.getProductServiceParamList().forEach(productServiceParam -> { + ProductServiceParam param = new ProductServiceParam(); + ToolUtil.copyProperties(productServiceParam, param); + param.setDeviceId(deviceId); + param.setServiceId(productServiceDto.getId()); + productServiceParamList.add(param); + }); + } + DB.saveAll(productServiceParamList); return true; } From a116fa47eec3af2a9fc776e88e646f100d7d8ad4 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 13 Oct 2021 20:19:43 +0800 Subject: [PATCH 522/763] [fix]: exclude camel-netty4 dependcy netty-all --- iot-server-bom/pom.xml | 6 ++++++ iot-server/pom.xml | 4 ++++ .../server-receiver-plugin/tcp-receiver-plugin/pom.xml | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/iot-server-bom/pom.xml b/iot-server-bom/pom.xml index 32f6a269..6991d4a7 100644 --- a/iot-server-bom/pom.xml +++ b/iot-server-bom/pom.xml @@ -90,6 +90,12 @@ org.apache.camel camel-netty4 ${camel.version} + + + io.netty + netty-all + + org.apache.camel diff --git a/iot-server/pom.xml b/iot-server/pom.xml index 37f6c8ab..8cc25301 100644 --- a/iot-server/pom.xml +++ b/iot-server/pom.xml @@ -103,6 +103,10 @@ io.netty netty-example + + io.netty + netty-all + diff --git a/iot-server/server-receiver-plugin/tcp-receiver-plugin/pom.xml b/iot-server/server-receiver-plugin/tcp-receiver-plugin/pom.xml index 11a79cc6..dcff3069 100644 --- a/iot-server/server-receiver-plugin/tcp-receiver-plugin/pom.xml +++ b/iot-server/server-receiver-plugin/tcp-receiver-plugin/pom.xml @@ -21,6 +21,10 @@ io.netty netty-example + + io.netty + netty-all + From 88d7fd1867ed31c430021dada4ad95d917dfb9d0 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 13 Oct 2021 20:23:24 +0800 Subject: [PATCH 523/763] [fix]: edit node.js version --- zeus-starter/pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index 57aef2a6..a3bfeb37 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -73,8 +73,7 @@ ${frontend-maven-plugin.version} ${ui.path} - v14.17.6 - 6.14.15 + v8.17.0 From 0985091a93cf93c5159e20e97c4da96e19d6d059 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 13 Oct 2021 20:26:18 +0800 Subject: [PATCH 524/763] [fix]: node.js --unsafe-perm --- zeus-starter/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index a3bfeb37..cc80f247 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -88,7 +88,7 @@ npm - install --registry=https://registry.npm.taobao.org/ + install --registry=https://registry.npm.taobao.org/ --unsafe-perm From 58048b54f0afbfdd7f0584ef0d62a367485d95fa Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 13 Oct 2021 20:45:11 +0800 Subject: [PATCH 525/763] [fix]: fix bug --- .../iot/web/device/service/MultipleDeviceEventRuleService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index 5fde1f21..63fcb5a4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -63,7 +63,7 @@ public Pager getEventByPage(MultipleDeviceEventParm even .setMaxRows(eventParm.getMaxRow()).orderBy(" create_time desc").asDto(MultipleDeviceEventDto.class).findList(); if (ToolUtil.isEmpty(list)) { - new Pager<>(list, 0); + return new Pager<>(list, 0); } //关联状态 备注 触发设备 From 94206ae783a6a6c1e71edc40575e1c927157f61e Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 13 Oct 2021 20:56:44 +0800 Subject: [PATCH 526/763] [fix]: fix init sql --- dist-material/bin/sql/zeus-iot.sql | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/dist-material/bin/sql/zeus-iot.sql b/dist-material/bin/sql/zeus-iot.sql index 4056dbed..975ec7e8 100644 --- a/dist-material/bin/sql/zeus-iot.sql +++ b/dist-material/bin/sql/zeus-iot.sql @@ -12,7 +12,7 @@ Target Server Version : 130004 File Encoding : 65001 - Date: 12/10/2021 10:04:27 + Date: 13/10/2021 20:52:05 */ @@ -636,7 +636,8 @@ CREATE TABLE "public"."product_service_param" ( "key" varchar(32) COLLATE "pg_catalog"."default", "name" varchar(32) COLLATE "pg_catalog"."default", "remark" varchar(255) COLLATE "pg_catalog"."default", - "value" varchar(255) COLLATE "pg_catalog"."default" + "value" varchar(255) COLLATE "pg_catalog"."default", + "device_id" varchar(64) COLLATE "pg_catalog"."default" ) ; COMMENT ON COLUMN "public"."product_service_param"."service_id" IS '服务ID'; @@ -644,6 +645,7 @@ COMMENT ON COLUMN "public"."product_service_param"."key" IS '参数标识'; COMMENT ON COLUMN "public"."product_service_param"."name" IS '参数名称'; COMMENT ON COLUMN "public"."product_service_param"."remark" IS '备注'; COMMENT ON COLUMN "public"."product_service_param"."value" IS '参数值'; +COMMENT ON COLUMN "public"."product_service_param"."device_id" IS '关联设备ID'; -- ---------------------------- -- Records of product_service_param @@ -803,14 +805,14 @@ INSERT INTO "public"."sys_config" VALUES (1145915627211370499, '文件上传路 INSERT INTO "public"."sys_config" VALUES (1143324237579165697, '验证码开关', 'ZEUS_KAPTCHA_OPEN', 'Y', 1106120265689055233, 'DISABLE', '是否开启验证码', 1, 1, '2019-06-24 12:46:43', '2021-08-03 16:38:12.432', 'ENABLE'); INSERT INTO "public"."sys_config" VALUES (1145915627211370498, 'Zeus发布的编号', 'ZEUS_SYSTEM_RELEASE_VERSION', 'N', NULL, '10', '用于防止浏览器缓存相关的js和css', 1, 1, '2019-07-02 12:42:30', '2021-08-03 16:38:12.432', 'ENABLE'); INSERT INTO "public"."sys_config" VALUES (1143468867767607297, '默认系统密码', 'ZEUS_DEFAULT_PASSWORD', 'N', NULL, '111111', '默认系统密码', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468867767607208, '单点登录开关', 'ZEUS_SIGN_IN', 'N', NULL, 'DISABLE', '是否启用单点登录', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468867767607207, '默认租户角色ID', 'ZEUS_TENANT_ROLE_ID', 'N', NULL, '1', '默认租户角色ID', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); INSERT INTO "public"."sys_config" VALUES (1145915627211370496, '全局主机组Id', 'ZEUS_HOST_GROUP_ID', 'Y', NULL, '19', '全局主机和模板组ID', NULL, NULL, NULL, NULL, 'DISABLE'); INSERT INTO "public"."sys_config" VALUES (1143468867767607298, '用户角色ID', 'ZEUS_ADMIN_ROLE_ID', 'N', NULL, '3', '用户角色ID', 1, 1, NULL, NULL, 'DISABLE'); INSERT INTO "public"."sys_config" VALUES (1145915627211370497, '离线回调ActionId', 'ZEUS_OFFLINE_ACTION_ID', 'Y', NULL, '7', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); INSERT INTO "public"."sys_config" VALUES (1145915627211370503, '告警回调ActionId', 'ZEUS_ALARM_ACTION_ID', 'Y', NULL, '8', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); -INSERT INTO "public"."sys_config" VALUES (1143468867767607208, '单点登录开关', 'ZEUS_SIGN_IN', 'N', NULL, 'DISABLE', '是否启用单点登录', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); INSERT INTO "public"."sys_config" VALUES (1145915627211370504, '动作回调ActionId', 'ZEUS_EXEC_ACTION_ID', 'Y', NULL, '9', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); INSERT INTO "public"."sys_config" VALUES (1145915627211370505, '事件回调ActionId', 'ZEUS_EVENT_ACTION_ID', 'Y', NULL, '10', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); -INSERT INTO "public"."sys_config" VALUES (1143468867767607207, '默认租户角色ID', 'ZEUS_TENANT_ROLE_ID', 'N', NULL, '1', '默认租户角色ID', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); -- ---------------------------- -- Table structure for sys_dict @@ -1346,7 +1348,7 @@ COMMENT ON COLUMN "public"."sys_user"."zbx_id" IS 'zabbix 用户ID'; -- ---------------------------- -- Records of sys_user -- ---------------------------- -INSERT INTO "public"."sys_user" VALUES ('Admin', 'cbde417443393372dbac9c185a6ec159', 'gt3zs', '超级管理员', '', '', 1, 1437232484602372096, 'ENABLE', 1, 1, '2021-09-28 09:38:33.668', '2021-09-28 09:38:33.668', 122, '712e512d1dfe13319e15bf5050a81ace', '1'); +INSERT INTO "public"."sys_user" VALUES ('Admin', 'cbde417443393372dbac9c185a6ec159', 'gt3zs', '超级管理员', '', '', 1, 1437232484602372096, 'ENABLE', 1, 1, '2021-09-28 09:38:33.668', '2021-09-28 09:38:33.668', 122, 'f93a1bea2549f93fad75bdde71e6b4fe', '1'); INSERT INTO "public"."sys_user" VALUES ('root', '17db03c22596b7609c7c9704f16663e0', 'abcdef', '超级管理员', '888888@qq.com', '13812345678', 1, 1437232484602372096, 'ENABLE', 1, 1, '2021-07-30 21:43:02.686', '2021-07-30 21:43:02.686', 1, '5859e004e8d2a23e6c330c3f9cd277e2', '4'); -- ---------------------------- @@ -1426,7 +1428,7 @@ SELECT setval('"public"."device_online_report_id_seq"', 7, true); -- ---------------------------- ALTER SEQUENCE "public"."devices_groups_id_seq" OWNED BY "public"."devices_groups"."id"; -SELECT setval('"public"."devices_groups_id_seq"', 182, true); +SELECT setval('"public"."devices_groups_id_seq"', 183, true); -- ---------------------------- -- Alter sequences owned by From b74fb87e79d7ea43def9101680bc9e3cdb74d51a Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 14 Oct 2021 11:54:38 +0800 Subject: [PATCH 527/763] [fix]: update demo login password --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f3d6448b..2e85535d 100644 --- a/README.md +++ b/README.md @@ -92,5 +92,5 @@ After Zeus IoT is successfully installed, you can use http://IP:9090 to access t > For more detailed installation and deployment instructions, please visit our official website document center ## Demo Environment -Using the account `Admin / zeus123` to log in the [demo environment](https://zeusdemo.zmops.cn/). Please note the account is granted view access. +Using the account `Admin / zabbix` to log in the [demo environment](https://zeusdemo.zmops.cn/). Please note the account is granted view access. From 4d9a1dc1b1e58d4c1a58fe130f563deab34de0f3 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 14 Oct 2021 11:55:14 +0800 Subject: [PATCH 528/763] [feat]: update zeus-iot-ui version --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index e7fe8e96..80f56849 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit e7fe8e9628263ba4b4a4b8d1c3a93704f6700a65 +Subproject commit 80f56849f22bf0c32041aee575a5d083a6044224 From 292c3a3123d1e23424b98bb5a2a78af8ca11e8e9 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 14 Oct 2021 17:36:09 +0800 Subject: [PATCH 529/763] [feat]: update forest version to 1.5.8 --- zeus-webapp-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp-bom/pom.xml b/zeus-webapp-bom/pom.xml index abdaa460..d5bd8a8d 100644 --- a/zeus-webapp-bom/pom.xml +++ b/zeus-webapp-bom/pom.xml @@ -140,7 +140,7 @@ com.dtflys.forest forest-spring-boot-starter - 1.5.3 + 1.5.8 commons-logging From 6e7fe2de4b6ff67ea09d228e50ba05daa37e8074 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 14 Oct 2021 18:31:38 +0800 Subject: [PATCH 530/763] [fix]: fix device list --- .../zmops/iot/web/device/service/DeviceService.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index d7596eb0..256e3ab8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -86,6 +86,16 @@ public List deviceList(DeviceParam deviceParam) { if (ToolUtil.isNotEmpty(deviceParam.getName())) { qDevice.name.contains(deviceParam.getName()); } + if (ToolUtil.isNotEmpty(deviceParam.getProductId())) { + qDevice.productId.eq(deviceParam.getProductId()); + } + if (ToolUtil.isNotEmpty(deviceParam.getProdType())) { + qDevice.type.contains(deviceParam.getProdType()); + } + if (ToolUtil.isNotEmpty(deviceParam.getDeviceGroupId())) { + List deviceList = new QDevicesGroups().select(QDevicesGroups.Alias.deviceId).deviceGroupId.eq(deviceParam.getDeviceGroupId()).findSingleAttributeList(); + qDevice.deviceId.in(deviceList); + } return qDevice.findList(); } From 2961a1b745cbba085d556f7e0dacdd70f430c4ae Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 18 Oct 2021 14:04:13 +0800 Subject: [PATCH 531/763] [fix]: fix multiple device event --- .../com/zmops/zeus/driver/service/ZbxTrigger.java | 13 +++++++++++++ .../api-json/trigger/trigger.execute.create.ftl | 14 ++++++++++++++ .../MultipleDeviceEventTriggerController.java | 4 ++-- .../service/MultipleDeviceEventRuleService.java | 15 +++++---------- 4 files changed, 34 insertions(+), 12 deletions(-) create mode 100644 zeus-driver/src/main/resources/api-json/trigger/trigger.execute.create.ftl diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java index 97db7da4..e3948890 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java @@ -29,6 +29,19 @@ String triggerCreate(@ParamName("triggerName") String triggerName, @ParamName("expression") String expression, @ParamName("ruleLevel") Byte ruleLevel); + /** + * 创建场景联动触发器 + * + * @param triggerName 触发器名称 + * @param expression 触发器 表达式 + * @param ruleLevel 告警等级 + * @return + */ + @Post + @JsonPath("/trigger/trigger.execute.create") + String executeTriggerCreate(@ParamName("triggerName") String triggerName, + @ParamName("expression") String expression, + @ParamName("ruleLevel") Byte ruleLevel); /** * 更新告警触发器 diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.execute.create.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.execute.create.ftl new file mode 100644 index 00000000..edd139e2 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.execute.create.ftl @@ -0,0 +1,14 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.create", + "params": { + "description": "${triggerName}", + "expression": "${expression}", + "priority" : ${ruleLevel}, + "manual_close":1, + "recovery_mode":2, + "type":1 + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java index f2c83e31..af8c911f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java @@ -69,12 +69,12 @@ public Pager getEventByPage(@RequestBody MultipleDeviceE */ @GetMapping("/detail") - public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId, @RequestParam("deviceId") String deviceId) { + public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId) { ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRuleId).findOne(); if (null == productEvent) { throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); } - return ResponseData.success(multipleDeviceEventRuleService.detail(productEvent, eventRuleId, deviceId)); + return ResponseData.success(multipleDeviceEventRuleService.detail(productEvent, eventRuleId)); } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index 63fcb5a4..cb702ff4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -276,23 +276,18 @@ public void updateProductEventRuleZbxId(Long triggerId, String[] zbxId) { * * @param productEvent * @param eventRuleId - * @param deviceId * @return */ - public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, String deviceId) { + public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId) { ProductEventRuleDto productEventRuleDto = new ProductEventRuleDto(); ToolUtil.copyProperties(productEvent, productEventRuleDto); List expList = new QProductEventExpression().eventRuleId.eq(eventRuleId).findList(); - expList.forEach(productEventExpression -> { - if (ToolUtil.isEmpty(productEventExpression.getDeviceId())) { - productEventExpression.setDeviceId(deviceId); - } - }); + productEventRuleDto.setExpList(expList); - productEventRuleDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).deviceId.eq(deviceId).findList()); + productEventRuleDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).findList()); - ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(deviceId).eventRuleId.eq(eventRuleId).findOne(); + ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRuleId).findOne(); productEventRuleDto.setStatus(productEventRelation.getStatus()); productEventRuleDto.setRemark(productEventRelation.getRemark()); productEventRuleDto.setInherit(productEventRelation.getInherit()); @@ -320,7 +315,7 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S * @return 触发器ID */ public String[] createZbxTrigger(String triggerName, String expression, Byte level) { - String res = zbxTrigger.triggerCreate(triggerName, expression, level); + String res = zbxTrigger.executeTriggerCreate(triggerName, expression, level); return JSON.parseObject(res, TriggerIds.class).getTriggerids(); } From 5920d6f7616aa87e81a1a4382373bf24c621d64c Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 18 Oct 2021 14:29:56 +0800 Subject: [PATCH 532/763] [fix]: fix service trigger demo --- .../iot/rest/DeviceStatusWebhookController.java | 9 ++++++++- .../main/java/com/zmops/iot/rest/dto/ParamDto.java | 12 ++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 zeus-rest/src/main/java/com/zmops/iot/rest/dto/ParamDto.java diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java index 940cd878..e7632a0f 100644 --- a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java @@ -5,7 +5,10 @@ import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.domain.product.query.QProductServiceParam; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.rest.dto.ParamDto; import com.zmops.iot.web.alarm.service.AlarmNoticeWorker; import com.zmops.iot.web.alarm.service.AlarmService; import com.zmops.iot.web.device.service.work.DeviceOnlineWorker; @@ -17,6 +20,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -126,8 +130,11 @@ public ResponseData deviceServiceWebhook(@RequestParam("triggerId") String trigg e.printStackTrace(); } + List serviceIds = new QProductEventService().select(QProductEventService.alias().serviceId).eventRuleId.eq(productEventRelation.getEventRuleId()).findSingleAttributeList(); - return ResponseData.success("OK"); + List list = new QProductServiceParam().select(QProductServiceParam.alias().key, QProductServiceParam.alias().value).serviceId.in(serviceIds).asDto(ParamDto.class).findList(); + + return ResponseData.success(list); } /** diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/dto/ParamDto.java b/zeus-rest/src/main/java/com/zmops/iot/rest/dto/ParamDto.java new file mode 100644 index 00000000..999c08c9 --- /dev/null +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/dto/ParamDto.java @@ -0,0 +1,12 @@ +package com.zmops.iot.rest.dto; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class ParamDto { + private String key; + private String value; +} From 98af47058e25ba7e009d3a143e486e93c344a4fe Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 18 Oct 2021 14:53:21 +0800 Subject: [PATCH 533/763] [fix]: fix service trigger --- .../iot/rest/DeviceStatusWebhookController.java | 13 +++++++++---- .../main/java/com/zmops/iot/rest/dto/ParamDto.java | 12 ------------ 2 files changed, 9 insertions(+), 16 deletions(-) delete mode 100644 zeus-rest/src/main/java/com/zmops/iot/rest/dto/ParamDto.java diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java index e7632a0f..bc1081bc 100644 --- a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java @@ -4,11 +4,12 @@ import com.zmops.iot.async.executor.Async; import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventService; import com.zmops.iot.domain.product.query.QProductServiceParam; import com.zmops.iot.model.response.ResponseData; -import com.zmops.iot.rest.dto.ParamDto; +import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.alarm.service.AlarmNoticeWorker; import com.zmops.iot.web.alarm.service.AlarmService; import com.zmops.iot.web.device.service.work.DeviceOnlineWorker; @@ -23,6 +24,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; /** * @author nantian created at 2021/8/7 14:56 @@ -132,9 +134,12 @@ public ResponseData deviceServiceWebhook(@RequestParam("triggerId") String trigg List serviceIds = new QProductEventService().select(QProductEventService.alias().serviceId).eventRuleId.eq(productEventRelation.getEventRuleId()).findSingleAttributeList(); - List list = new QProductServiceParam().select(QProductServiceParam.alias().key, QProductServiceParam.alias().value).serviceId.in(serviceIds).asDto(ParamDto.class).findList(); - - return ResponseData.success(list); + List list = new QProductServiceParam().select(QProductServiceParam.alias().key, QProductServiceParam.alias().value).serviceId.in(serviceIds).findList(); + Map map = new ConcurrentHashMap<>(list.size()); + if (ToolUtil.isNotEmpty(list)) { + map = list.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue)); + } + return ResponseData.success(map); } /** diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/dto/ParamDto.java b/zeus-rest/src/main/java/com/zmops/iot/rest/dto/ParamDto.java deleted file mode 100644 index 999c08c9..00000000 --- a/zeus-rest/src/main/java/com/zmops/iot/rest/dto/ParamDto.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.zmops.iot.rest.dto; - -import lombok.Data; - -/** - * @author yefei - **/ -@Data -public class ParamDto { - private String key; - private String value; -} From 72dd7d80335f752228bd86e8b3a4c57cd8ebfc2e Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 18 Oct 2021 16:25:20 +0800 Subject: [PATCH 534/763] [fix]: fix service trigger param --- .../rest/DeviceStatusWebhookController.java | 49 +++++++++++++++---- .../MultipleDeviceEventTriggerController.java | 14 ++---- 2 files changed, 44 insertions(+), 19 deletions(-) diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java index bc1081bc..ac9ad2f5 100644 --- a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java @@ -3,10 +3,15 @@ import com.alibaba.fastjson.JSON; import com.zmops.iot.async.executor.Async; import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.ProductEventService; +import com.zmops.iot.domain.product.ProductService; import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.domain.product.query.QProductService; import com.zmops.iot.domain.product.query.QProductServiceParam; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.util.ToolUtil; @@ -21,6 +26,8 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -106,7 +113,7 @@ public ResponseData deviceProblemWebhook(@RequestBody Map params * @return ResponseData */ @RequestMapping("/service") - public ResponseData deviceServiceWebhook(@RequestParam("triggerId") String triggerId) { + public List> deviceServiceWebhook(@RequestParam("triggerId") String triggerId) { log.debug("--------设备联动触发----------" + triggerId); @@ -114,7 +121,7 @@ public ResponseData deviceServiceWebhook(@RequestParam("triggerId") String trigg ProductEventRelation productEventRelation = new QProductEventRelation().zbxId.eq(triggerId).findOne(); if (productEventRelation == null) { - return ResponseData.success("OK"); + return Collections.emptyList(); } alarmInfo.put("eventRuleId", productEventRelation.getEventRuleId()); @@ -132,14 +139,36 @@ public ResponseData deviceServiceWebhook(@RequestParam("triggerId") String trigg e.printStackTrace(); } - List serviceIds = new QProductEventService().select(QProductEventService.alias().serviceId).eventRuleId.eq(productEventRelation.getEventRuleId()).findSingleAttributeList(); - - List list = new QProductServiceParam().select(QProductServiceParam.alias().key, QProductServiceParam.alias().value).serviceId.in(serviceIds).findList(); - Map map = new ConcurrentHashMap<>(list.size()); - if (ToolUtil.isNotEmpty(list)) { - map = list.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue)); - } - return ResponseData.success(map); + List productEventServiceList = new QProductEventService().eventRuleId.eq(productEventRelation.getEventRuleId()).or().deviceId.isNull().deviceId.eq(productEventRelation.getRelationId()).endOr().findList(); + List> list = new ArrayList<>(); + Map> collect = productEventServiceList.parallelStream().collect(Collectors.groupingBy(ProductEventService::getExecuteDeviceId)); + collect.forEach((key, value) -> { + Map map = new ConcurrentHashMap<>(); + Device device = new QDevice().deviceId.eq(key).findOne(); + if (null == device) { + return; + } + map.put("device", device); + List> serviceList = new ArrayList<>(); + value.forEach(val -> { + Map serviceMap = new ConcurrentHashMap<>(); + ProductService productService = new QProductService().id.eq(val.getServiceId()).findOne(); + if (null == productService) { + return; + } + serviceMap.put("name", productService.getName()); + + List paramList = new QProductServiceParam().serviceId.eq(val.getServiceId()).findList(); + if (ToolUtil.isNotEmpty(paramList)) { + serviceMap.put("param", paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue))); + } + serviceList.add(serviceMap); + }); + map.put("service", serviceList); + list.add(map); + }); + + return list; } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java index af8c911f..67f0173e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java @@ -198,20 +198,16 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn @PostMapping("/delete") public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseEntity.Delete.class) MultipleDeviceEventRule eventRule) { - ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(eventRule.getDeviceId()) - .eventRuleId.eq(eventRule.getEventRuleId()).findOne(); - - if (productEventRelation != null && productEventRelation.getInherit().equals(InheritStatus.YES.getCode())) { - throw new ServiceException(BizExceptionEnum.EVENT_PRODUCT_CANNOT_DELETE); - } + List productEventRelationList = new QProductEventRelation() + .eventRuleId.eq(eventRule.getEventRuleId()).findList(); //step 01:删除 zbx触发器 - if (productEventRelation != null && ToolUtil.isNotEmpty(productEventRelation.getZbxId())) { + if (ToolUtil.isNotEmpty(productEventRelationList) && ToolUtil.isNotEmpty(productEventRelationList.get(0).getZbxId())) { List triggers = JSONObject.parseArray( - zbxTrigger.triggerGet(productEventRelation.getZbxId()), MultipleDeviceEventRuleService.Triggers.class); + zbxTrigger.triggerGet(productEventRelationList.get(0).getZbxId()), MultipleDeviceEventRuleService.Triggers.class); if (ToolUtil.isNotEmpty(triggers)) { - zbxTrigger.triggerDelete(productEventRelation.getZbxId()); + zbxTrigger.triggerDelete(productEventRelationList.get(0).getZbxId()); } } From 345e330d39383ec32fbf7b67b693ab65b9b311a6 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Mon, 18 Oct 2021 17:01:58 +0800 Subject: [PATCH 535/763] [doc]: update docs --- docs/README.md | 73 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 14 deletions(-) diff --git a/docs/README.md b/docs/README.md index c83dd96f..94fb7d69 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,14 +4,26 @@ > Zeus IoT 基于 zabbix-5.4 安装。 -## 环境要求 +## Zeus IoT 系统安装配置要求 -> 目前 ZEUS 支持 Linux x86_64 系统平台。 +- **硬件依赖** -| 配置规格 | 操作系统 | CPU | 内存 | 存储 | -| :------: | :------------: | :--: | :--: | :---: | -| 最低配置 | Centos、Ubuntu | 2 核 | 4 GB | 100GB | -| 推荐配置 | Centos、Ubuntu | 4 核 | 8 GB | 500GB | + 目前 Zeus IoT 支持 Linux x86_64 系统平台,其它系统平台测试中。 + + | 配置规格 | 系统平台 | CPU | 内存 | 存储 | + | -------- | ------------ | ---- | ---- | ------ | + | 最低配置 | Linux x86_64 | 2 核 | 4 GB | 100 GB | + | 推荐配置 | Linux x86_64 | 4 核 | 8 GB | 500 GB | + +- **软件依赖** + + | 操作系统 | Centos 7.0+/Redhat 7.0+/Ubuntu 18.04+ | + | -------- | ------------------------------------- | + | JDK | 1.8 | + | 数据库 | PostgreSQL 12+/InfluxDB/TDengine-2.2x | + | 数据采集 | Zabbix Server 5.4.x | + | 数据代理 | Zabbix Proxy 5.4.x | + | 可视化 | Grafana 7.x | ## 快速安装 @@ -97,6 +109,8 @@ cd zeus-iot && git submodule update --init --recursive mvn clean package -U -Dmaven.test.skip=true ``` + + 💡 编译好的安装包在 dist 目录下。文件名为 `zeus-iot-bin.tar.gz` 。部署时只需解压即可。 #### 初始化系统服务 @@ -109,6 +123,7 @@ sudo -u postgres createdb -E Unicode -T template0 zeus-iot 2、 导入 SQL ```shell +# 解压安装包,初始化 sql 在安装目录下。 cat zeus-iot.sql | sudo -u postgres psql zeus-iot ``` @@ -133,7 +148,7 @@ apt install openjdk-8-jdk -y 3、配置 zeus-iot 连接 zabbix token - vim /opt/zeus/zeus-iot-bin/webapp/webapp.yml + vim ./zeus-iot-bin/webapp/webapp.yml ... forest: @@ -153,7 +168,7 @@ apt install openjdk-8-jdk -y 以修改 zabbix 信息为例: ``` - vim /opt/zeus/zeus-iot-bin/webapp/webapp.yml + vim ./zeus-iot-bin/webapp/webapp.yml forest: log-enabled: false @@ -181,10 +196,10 @@ apt install openjdk-8-jdk -y ```shell # 启动 -/opt/zeus/zeus-iot-bin/bin/startup.sh +./zeus-iot-bin/bin/startup.sh # 停止 -/opt/zeus/zeus-iot-bin/bin/stop.sh +./zeus-iot-bin/bin/stop.sh ``` @@ -237,7 +252,37 @@ systemctl start taosd 启用 zabbix 导出功能 --------------------- -修改 zabbix-server.conf 配置文件,如下: +修改 zabbix-server.conf 配置文件,找到如下配置项: + +```bash +### Option: ExportDir +# Directory for real time export of events, history and trends in newline delimited JSON format. +# If set, enables real time export. +# +# Mandatory: no +# Default: +ExportDir=/data + +### Option: ExportFileSize +# Maximum size per export file in bytes. +# Only used for rotation if ExportDir is set. +# +# Mandatory: no +# Range: 1M-1G +# Default: +ExportFileSize=1G + +### Option: ExportType +# List of comma delimited types of real time export - allows to control export entities by their +# type (events, history, trends) individually. +# Valid only if ExportDir is set. +# +# Mandatory: no +# Default: +ExportType=history +``` + + - ExportDir=/data/zabbix_history 配置导出目录 - ExportFileSize=1G 配置导出文件的大小 @@ -257,10 +302,10 @@ systemctl restart zabbix-server ``` # 停止 zeus-iot 服务 -/opt/zeus/zeus-iot-bin/bin/stop.sh +./zeus-iot-bin/bin/stop.sh # 修改数据连接配置如下 -vim /opt/zeus/zeus-iot-bin/conf/application.yml +vim ./zeus-iot-bin/conf/application.yml ... # tdengine storage realtime storage: @@ -276,6 +321,6 @@ vim /opt/zeus/zeus-iot-bin/conf/application.yml ## 启动 zeus-iot 服务 ```shell - /opt/zeus/zeus-iot-bin/bin/startup.sh + ./zeus-iot-bin/bin/startup.sh ``` From e868ef54dbb0e6f0ba7f8bd2ae824e64c66fe007 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 18 Oct 2021 17:25:23 +0800 Subject: [PATCH 536/763] [fix]: fix service param --- .../iot/rest/DeviceStatusWebhookController.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java index ac9ad2f5..87db216d 100644 --- a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java @@ -115,17 +115,16 @@ public ResponseData deviceProblemWebhook(@RequestBody Map params @RequestMapping("/service") public List> deviceServiceWebhook(@RequestParam("triggerId") String triggerId) { - log.debug("--------设备联动触发----------" + triggerId); Map alarmInfo = new ConcurrentHashMap<>(3); - ProductEventRelation productEventRelation = new QProductEventRelation().zbxId.eq(triggerId).findOne(); - if (productEventRelation == null) { + List productEventRelationList = new QProductEventRelation().zbxId.eq(triggerId).findList(); + if (ToolUtil.isEmpty(productEventRelationList)) { return Collections.emptyList(); } - alarmInfo.put("eventRuleId", productEventRelation.getEventRuleId()); - alarmInfo.put("relationId", productEventRelation.getRelationId()); + alarmInfo.put("eventRuleId", productEventRelationList.get(0).getEventRuleId()); + alarmInfo.put("relationId", productEventRelationList.get(0).getRelationId()); // alarmService.action(alarmInfo); @@ -139,7 +138,8 @@ public List> deviceServiceWebhook(@RequestParam("triggerId") e.printStackTrace(); } - List productEventServiceList = new QProductEventService().eventRuleId.eq(productEventRelation.getEventRuleId()).or().deviceId.isNull().deviceId.eq(productEventRelation.getRelationId()).endOr().findList(); + List productEventServiceList = new QProductEventService().eventRuleId.eq(productEventRelationList.get(0).getEventRuleId()) + .or().deviceId.isNull().deviceId.eq(productEventRelationList.get(0).getRelationId()).endOr().findList(); List> list = new ArrayList<>(); Map> collect = productEventServiceList.parallelStream().collect(Collectors.groupingBy(ProductEventService::getExecuteDeviceId)); collect.forEach((key, value) -> { From 20b7ac702b67bddb0140a72b0ff7e147e1b0207f Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 20 Oct 2021 09:23:44 +0800 Subject: [PATCH 537/763] [fix]: fix device name validate --- .../device/controller/DeviceController.java | 19 +++++++++++-------- .../web/exception/enums/BizExceptionEnum.java | 1 + 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java index a5f500fc..51ebdbb7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java @@ -62,16 +62,19 @@ public ResponseData deviceList(@RequestBody DeviceParam deviceParam) { @Permission(code = "dev_add") @RequestMapping("/create") public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody DeviceDto deviceDto) { - QDevice qDevice = new QDevice().or().name.eq(deviceDto.getName()); + int count = new QDevice().name.eq(deviceDto.getName()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.DEVICE_EXISTS); + } if (ToolUtil.isNotEmpty(deviceDto.getDeviceId())) { - qDevice.deviceId.eq(deviceDto.getDeviceId()); + count = new QDevice().deviceId.eq(deviceDto.getDeviceId()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.DEVICE_ID_EXISTS); + } } else { deviceDto.setDeviceId(IdUtil.getSnowflake().nextId() + ""); } - int count = qDevice.findCount(); - if (count > 0) { - throw new ServiceException(BizExceptionEnum.DEVICE_EXISTS); - } + deviceDto.setEdit("false"); deviceService.checkProductExist(deviceDto); String deviceId = deviceService.create(deviceDto); @@ -112,11 +115,11 @@ public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody Devi @Permission(code = "dev_update") @RequestMapping("/status/update") public ResponseData status(@Validated(BaseEntity.Status.class) @RequestBody DeviceDto deviceDto) { - Device device = new QDevice().deviceId.eq(deviceDto.getDeviceId()).findOne(); + Device device = new QDevice().deviceId.eq(deviceDto.getDeviceId()).findOne(); if (null == device) { throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); } - deviceService.status(deviceDto.getStatus(),deviceDto.getDeviceId(),device.getZbxId()); + deviceService.status(deviceDto.getStatus(), deviceDto.getDeviceId(), device.getZbxId()); return ResponseData.success(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index 57cad79d..50dcf9f3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -148,6 +148,7 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { * 设备相关 */ DEVICE_EXISTS(1501, "设备名称已存在"), + DEVICE_ID_EXISTS(1503, "设备ID已存在"), DEVICE_NOT_EXISTS(1502, "设备不存在"), /** From 5e34c8f9c98bb2be4d6e1ad2c167233341010f49 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 20 Oct 2021 15:43:48 +0800 Subject: [PATCH 538/763] [feat]: update zeus-iot-ui version --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index 80f56849..fe13223b 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit 80f56849f22bf0c32041aee575a5d083a6044224 +Subproject commit fe13223be1a943a97514e7d09a8535f45c0bc4a6 From 0216c003207eeb4c1ab73395eb87e802f9e05123 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Wed, 20 Oct 2021 18:05:18 +0800 Subject: [PATCH 539/763] [fix]: fix clear install path --- docs/ubuntu/install.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/ubuntu/install.sh b/docs/ubuntu/install.sh index 5ed0f6bb..51a7ba8a 100644 --- a/docs/ubuntu/install.sh +++ b/docs/ubuntu/install.sh @@ -251,7 +251,7 @@ function clearsys() { kill9 taosd - apt-get remove tdengine-2.2.0.2-3.x86_64 &> /dev/null + apt-get remove tdengine &> /dev/null [ -d /usr/local/taos ] && rm -rf /usr/local/taos @@ -261,9 +261,8 @@ function clearsys() { kill9 zabbix_server kill9 zabbix_agent - [ -d /opt/zeus/zabbix ] && rm -rf /opt/zeus/zabbix - [ -f /usr/lib/systemd/system/zabbix-server.service ] && rm -rf /usr/lib/systemd/system/zabbix-server.service - [ -f /usr/lib/systemd/system/zabbix-agent.service ] && rm -rf /usr/lib/systemd/system/zabbix-agent.service + [ -f /lib/systemd/system/zabbix-server.service ] && rm -rf /lib/systemd/system/zabbix-server.service + [ -f /lib/systemd/system/zabbix-agent.service ] && rm -rf /lib/systemd/system/zabbix-agent.service ## 清理 postgresql 数据库 systemctl stop postgresql &> /dev/null @@ -273,14 +272,14 @@ function clearsys() { apt-get remove postgresql-13 -y &> /dev/null [ -d /opt/zeus/pgdata ] && rm -rf /opt/zeus/pgdata - [ -f /usr/lib/systemd/system/postgresql.service ] && rm -rf /usr/lib/systemd/system/postgresql.service + [ -f /lib/systemd/system/postgresql.service ] && rm -rf /lib/systemd/system/postgresql.service ## 清理 nginx systemctl stop nginx &> nginx kill9 nginx apt-get remove nginx -y &> /dev/null - [ -f /usr/lib/systemd/system/nginx ] && rm -rf /usr/lib/systemd/system/nginx + [ -f /lib/systemd/system/nginx ] && rm -rf /lib/systemd/system/nginx } From c5a459502aec4b7d20bd0d302f51d320ae0553c6 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 21 Oct 2021 15:48:47 +0800 Subject: [PATCH 540/763] [fix]: fix global view --- .../main/java/com/zmops/iot/web/analyse/service/HomeService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index a8169b21..bfbc161f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -382,6 +382,7 @@ public Map serviceExecuteNum(long timeFrom, long timeTill) { valMap.put("val", value); trendsList.add(valMap); }); + trendsList.sort(Comparator.comparing(o -> o.get("date").toString())); executeMap.put("trends", trendsList); } From f6486d4ab5a97cac07dccf2204896af0b1e42d4c Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 21 Oct 2021 16:12:09 +0800 Subject: [PATCH 541/763] [feat]: add none storage --- iot-server/server-bootstrap/pom.xml | 5 ++ .../src/main/resources/application.yml | 3 +- iot-server/server-storage-plugin/pom.xml | 1 + .../server-none-storage/pom.xml | 31 +++++++++++ .../storage/plugin/none/BatchDaoNoop.java | 23 ++++++++ .../plugin/none/NoneStorageProvider.java | 52 +++++++++++++++++++ .../storage/plugin/none/StorageDAONoop.java | 15 ++++++ ...s.iot.server.library.module.ModuleProvider | 19 +++++++ 8 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 iot-server/server-storage-plugin/server-none-storage/pom.xml create mode 100644 iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/BatchDaoNoop.java create mode 100644 iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/NoneStorageProvider.java create mode 100644 iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/StorageDAONoop.java create mode 100644 iot-server/server-storage-plugin/server-none-storage/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider diff --git a/iot-server/server-bootstrap/pom.xml b/iot-server/server-bootstrap/pom.xml index 01490ea2..ae0ae74b 100644 --- a/iot-server/server-bootstrap/pom.xml +++ b/iot-server/server-bootstrap/pom.xml @@ -71,6 +71,11 @@ server-transfer ${project.version} + + com.zmops + server-none-storage + ${project.version} + + } + ] + }, + { + "description": "${ruleId}", <#--trigger name--> + "recovery_mode": 2, + "type": 1, <#if ruleFunctionRecovery == "nodata"> - "recovery_expression": "nodata(/${deviceId}/${itemKeyRecovery},${ruleConditionRecovery}) = 0", <#-- 上线规则 nodata = 0 --> + "expression": "nodata(/${deviceId}/${itemKeyRecovery},${ruleConditionRecovery}) = 0", <#-- 上线规则 nodata = 0 --> <#else> - "recovery_expression": "last(/${deviceId}/${itemKeyRecovery}) ${ruleFunctionRecovery} ${ruleConditionRecovery}", + "expression": "last(/${deviceId}/${itemKeyRecovery}) ${ruleFunctionRecovery} ${ruleConditionRecovery}", "tags": [ { - "tag": "__offline__", + "tag": "__online__", "value": "{HOST.HOST}" <#--device id--> } ] diff --git a/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl index 728d6734..0f221ed4 100644 --- a/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl +++ b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl @@ -10,11 +10,13 @@ <#else> "expression": "last(/${deviceId}/${itemKey}) ${ruleFunction} ${ruleCondition}", - "recovery_mode": 1, + },{ + "triggerid": "${recoveryTriggerId}", + "description": "${ruleId}", <#--trigger name--> <#if ruleFunctionRecovery == "nodata"> - "recovery_expression": "nodata(/${deviceId}/${itemKeyRecovery},${ruleConditionRecovery}) = 0" <#-- 上线规则 nodata = 0 --> + "expression": "nodata(/${deviceId}/${itemKeyRecovery},${ruleConditionRecovery}) = 0" <#-- 上线规则 nodata = 0 --> <#else> - "recovery_expression": "last(/${deviceId}/${itemKeyRecovery}) ${ruleFunctionRecovery} ${ruleConditionRecovery}" + "expression": "last(/${deviceId}/${itemKeyRecovery}) ${ruleFunctionRecovery} ${ruleConditionRecovery}" } <#-- nodata(/Zabbix server/system.cpu.util[,nice],20s)=0 --> diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl index 211674fe..80a71344 100644 --- a/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl @@ -3,6 +3,7 @@ "method": "trigger.get", "params": { "selectHosts":["host"], + "selectTags":["tag"], <#if triggerIds??> "triggerids":${triggerIds}, diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java index daa12064..84420b97 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java @@ -6,6 +6,7 @@ import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.ProductStatusFunctionRelation; import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventService; import com.zmops.iot.domain.product.query.QProductServiceRelation; @@ -13,6 +14,7 @@ import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.product.dto.ZbxTriggerInfo; import com.zmops.iot.web.product.service.ProductEventRuleService; import com.zmops.zeus.driver.service.ZbxTrigger; import io.ebean.DB; @@ -23,6 +25,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; /** @@ -39,7 +42,7 @@ public class SaveOtherWorker implements IWorker { @Override public Boolean action(DeviceDto deviceDto, Map> allWrappers) { - log.debug("step 8:处理 其它 工作----DEVICEID:"+deviceDto.getDeviceId()+"…………"); + log.debug("step 8:处理 其它 工作----DEVICEID:" + deviceDto.getDeviceId() + "…………"); String deviceId = deviceDto.getDeviceId(); @@ -73,8 +76,22 @@ public Boolean action(DeviceDto deviceDto, Map> allW .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "").execute(); //上下线规则关联 - DB.sqlUpdate("insert into product_status_function_relation (relation_id,rule_id,inherit) SELECT :deviceId,rule_id,1 from product_status_function_relation where relation_id=:relationId") - .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "").execute(); + ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().relationId.eq(deviceDto.getProductId() + "").findOne(); + if (null != relation) { + String triggerRes = zbxTrigger.triggerGetByName(relation.getRuleId() + ""); + + List zbxTriggerInfoList = JSONObject.parseArray(triggerRes, ZbxTriggerInfo.class); + Map hostTriggerMap = zbxTriggerInfoList.parallelStream().filter(o -> o.getTags().parallelStream().anyMatch(t -> "__offline__".equals(t.getTag()))) + .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid)); + Map hostRecoveryTriggerMap = zbxTriggerInfoList.parallelStream().filter(o -> o.getTags().parallelStream().anyMatch(t -> "__online__".equals(t.getTag()))) + .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid)); + + DB.sqlUpdate("insert into product_status_function_relation (relation_id,rule_id,inherit,zbx_id,zbx_id_recovery) SELECT :deviceId,rule_id,1,:zbxId,:zbxIdRecovery from product_status_function_relation where relation_id=:relationId") + .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "") + .setParameter("zbxId", Optional.ofNullable(hostTriggerMap.get(deviceDto.getDeviceId()))) + .setParameter("zbxIdRecovery", Optional.ofNullable(hostRecoveryTriggerMap.get(deviceDto.getDeviceId()))).execute(); + + } //告警规则关联 并 回填zbx triggerId List triggers = JSONObject.parseArray(zbxTrigger.triggerGetByHost(deviceId), ProductEventRuleService.Triggers.class); @@ -100,7 +117,7 @@ public Boolean action(DeviceDto deviceDto, Map> allW DB.sqlUpdate("insert into product_event_service (service_id,device_id,execute_device_id,event_rule_id,inherit) SELECT service_id,:deviceId,:executeDeviceId,event_rule_id,1 from product_event_service where relation_id=:relationId") .setParameter("deviceId", deviceId).setParameter("executeDeviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "").execute(); - log.debug("step 8:处理 其它 工作----DEVICEID:"+deviceDto.getDeviceId()+"完成"); + log.debug("step 8:处理 其它 工作----DEVICEID:" + deviceDto.getDeviceId() + "完成"); return true; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java index 09286dac..81ae77a1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java @@ -90,7 +90,6 @@ public ResponseData updateDeviceStatusTrigger(@RequestBody @Validated(BaseEntity if (null == productStatusFunction) { throw new ServiceException(BizExceptionEnum.RULE_NOT_EXISTS); } - rule.setTriggerId(productStatusFunction.getZbxId()); return ResponseData.success(productTriggerService.updateDeviceStatusJudgeTrigger(rule)); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusFunctionDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusFunctionDto.java index e3a2999f..b7a54023 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusFunctionDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusFunctionDto.java @@ -53,14 +53,12 @@ public class ProductStatusFunctionDto { private String attrName; - private String zbxId; - private String attrNameRecovery; @CachedValue(type = DicType.SysUserName) - private String createUser; + private Long createUser; private String createTime; @CachedValue(type = DicType.SysUserName) - private String updateUser; + private Long updateUser; private String updateTime; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java index 379d7a72..82c84943 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java @@ -24,8 +24,6 @@ public class ProductStatusJudgeRule { private String ruleName; - private String triggerId; // zbxId - //##################### 下线规则 @NotNull(groups = {BaseEntity.Create.class}) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ZbxTriggerInfo.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ZbxTriggerInfo.java new file mode 100644 index 00000000..5508384b --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ZbxTriggerInfo.java @@ -0,0 +1,29 @@ +package com.zmops.iot.web.product.dto; + +import lombok.Data; + +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class ZbxTriggerInfo { + private List hosts; + private List tags; + private String triggerid; + private String description; + + + @Data + public static class Host{ + private String hostid; + private String host; + } + + @Data + public static class Tag{ + private String tag; + private String value; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java index dc4bdae6..6bf2b9e7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java @@ -2,6 +2,7 @@ import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.product.ProductStatusFunction; import com.zmops.iot.domain.product.ProductStatusFunctionRelation; import com.zmops.iot.domain.product.query.QProductStatusFunction; @@ -10,7 +11,9 @@ import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.iot.web.product.dto.ProductStatusFunctionDto; import com.zmops.iot.web.product.dto.ProductStatusJudgeRule; +import com.zmops.iot.web.product.dto.ZbxTriggerInfo; import com.zmops.zeus.driver.service.ZbxDeviceStatusTrigger; +import com.zmops.zeus.driver.service.ZbxTrigger; import io.ebean.DB; import lombok.Data; import org.springframework.beans.BeanUtils; @@ -20,6 +23,8 @@ import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; /** * @author nantian created at 2021/8/10 17:55 @@ -35,6 +40,9 @@ public class ProductTriggerService { @Autowired private ZbxDeviceStatusTrigger deviceStatusTrigger; + @Autowired + private ZbxTrigger zbxTrigger; + /** * 离线 或者 在线触发器 信息 * @@ -67,12 +75,12 @@ public Long createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { judgeRule.getProductAttrKey(), judgeRule.getRuleCondition() + judgeRule.getUnit(), judgeRule.getRuleFunction(), judgeRule.getProductAttrKeyRecovery(), judgeRule.getRuleConditionRecovery() + judgeRule.getUnitRecovery(), judgeRule.getRuleFunctionRecovery()); - String triggerId = getTriggerId(res); + String[] triggerIds = getTriggerId(res); //step 2:保存规则 ProductStatusFunction productStatusFunction = new ProductStatusFunction(); BeanUtils.copyProperties(judgeRule, productStatusFunction); - productStatusFunction.setZbxId(triggerId); + productStatusFunction.setRuleId(ruleId); DB.save(productStatusFunction); @@ -80,17 +88,32 @@ public Long createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { ProductStatusFunctionRelation productStatusFunctionRelation = new ProductStatusFunctionRelation(); productStatusFunctionRelation.setRelationId(judgeRule.getRelationId()); productStatusFunctionRelation.setRuleId(ruleId); - productStatusFunctionRelation.setRuleId(ruleId); + productStatusFunctionRelation.setZbxId(triggerIds[0]); + productStatusFunctionRelation.setZbxIdRecovery(triggerIds[1]); DB.save(productStatusFunctionRelation); //step 4:同步到设备 String relationId = judgeRule.getRelationId(); if (ToolUtil.isNum(relationId)) { + + String triggerRes = zbxTrigger.triggerGetByName(judgeRule.getRuleId() + ""); + if (ToolUtil.isEmpty(triggerRes)) { + return productStatusFunction.getRuleId(); + } + List zbxTriggerInfoList = JSONObject.parseArray(triggerRes, ZbxTriggerInfo.class); + Map hostTriggerMap = zbxTriggerInfoList.parallelStream().filter(o->o.getTags().parallelStream().anyMatch(t->"__offline__".equals(t.getTag()))) + .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid)); + Map hostRecoveryTriggerMap = zbxTriggerInfoList.parallelStream().filter(o->o.getTags().parallelStream().anyMatch(t->"__online__".equals(t.getTag()))) + .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid)); + String sql = "select device_id from device where product_id = :productId and device_id not in (select relation_id from product_status_function_relation where inherit='0')"; List deviceDtoList = DB.findDto(DeviceDto.class, sql).setParameter("productId", Long.parseLong(relationId)).findList(); deviceDtoList.forEach(deviceDto -> { - DB.sqlUpdate("insert into product_status_function_relation (relation_id,rule_id,inherit) SELECT :deviceId,rule_id,1 from product_status_function_relation where relation_id=:relationId") - .setParameter("deviceId", deviceDto.getDeviceId()).setParameter("relationId", judgeRule.getRelationId() + "").execute(); + DB.sqlUpdate("insert into product_status_function_relation (relation_id,rule_id,inherit,zbx_id,zbx_id_recovery) SELECT :deviceId,rule_id,1,:zbxId,:zbxIdRecovery from product_status_function_relation where relation_id=:relationId") + .setParameter("deviceId", deviceDto.getDeviceId()).setParameter("relationId", judgeRule.getRelationId() + "") + .setParameter("zbxId", Optional.ofNullable(hostTriggerMap.get(deviceDto.getDeviceId()))) + .setParameter("zbxIdRecovery",Optional.ofNullable(hostRecoveryTriggerMap.get(deviceDto.getDeviceId()))) + .execute(); }); } @@ -106,10 +129,11 @@ public Long createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { public Long updateDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { // Map rule = new HashMap<>(); // buildTriggerCreateMap(rule, judgeRule); + ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().ruleId.eq(judgeRule.getRuleId()).relationId.eq(judgeRule.getRelationId()).findOne(); - deviceStatusTrigger.updateDeviceStatusTrigger(judgeRule.getTriggerId(), judgeRule.getRuleId() + "", judgeRule.getRelationId(), + deviceStatusTrigger.updateDeviceStatusTrigger(relation.getZbxId(), judgeRule.getRuleId() + "", judgeRule.getRelationId(), judgeRule.getProductAttrKey(), judgeRule.getRuleCondition() + judgeRule.getUnit(), judgeRule.getRuleFunction(), judgeRule.getProductAttrKeyRecovery(), - judgeRule.getRuleConditionRecovery() + judgeRule.getUnitRecovery(), judgeRule.getRuleFunctionRecovery()); + judgeRule.getRuleConditionRecovery() + judgeRule.getUnitRecovery(), judgeRule.getRuleFunctionRecovery(), relation.getZbxIdRecovery()); ProductStatusFunction productStatusFunction = new ProductStatusFunction(); BeanUtils.copyProperties(judgeRule, productStatusFunction); @@ -138,10 +162,10 @@ private void buildTriggerCreateMap(Map rule, ProductStatusJudgeR } - private String getTriggerId(String responseStr) { + private String[] getTriggerId(String responseStr) { TriggerIds ids = JSON.parseObject(responseStr, TriggerIds.class); if (null != ids && ids.getTriggerids().length > 0) { - return ids.getTriggerids()[0]; + return ids.getTriggerids(); } return null; } @@ -161,4 +185,6 @@ public void deleteDeviceStatusTrigger(Long ruleId) { static class TriggerIds { String[] triggerids; } + + } From 9a15432b26dfb78a970a1d3781a23428f47e21c1 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 27 Oct 2021 14:14:25 +0800 Subject: [PATCH 570/763] [feat]: fix trigger event --- .../java/com/zmops/iot/util/SpringUtils.java | 72 +++++++ .../rest/DeviceStatusWebhookController.java | 176 ------------------ zeus-starter/pom.xml | 10 + zeus-webapp/pom.xml | 6 + .../iot/web/alarm/service/AlarmService.java | 17 +- .../service/work/DeviceOnlineWorker.java | 54 ------ .../device/service/work/SaveOtherWorker.java | 7 +- .../zmops/iot/web/event/EventDataProcess.java | 44 +++++ .../com/zmops/iot/web/event/EventProcess.java | 11 ++ .../iot/web/event/EventProcessFactory.java | 20 ++ .../com/zmops/iot/web/event/SyncZbxEvent.java | 26 +++ .../zmops/iot/web/event/dto/EventDataDto.java | 19 ++ .../web/event/service/AlarmEventProcess.java | 60 ++++++ .../event/service/OfflineEventProcess.java | 47 +++++ .../web/event/service/OnlineEventProcess.java | 48 +++++ .../event/service/ServiceEventProcess.java | 108 +++++++++++ .../service/ProductTriggerService.java | 11 +- 17 files changed, 491 insertions(+), 245 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/util/SpringUtils.java delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/event/EventDataProcess.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/event/EventProcess.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/event/EventProcessFactory.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/event/SyncZbxEvent.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/event/dto/EventDataDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OnlineEventProcess.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java diff --git a/zeus-common/src/main/java/com/zmops/iot/util/SpringUtils.java b/zeus-common/src/main/java/com/zmops/iot/util/SpringUtils.java new file mode 100644 index 00000000..034243b3 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/util/SpringUtils.java @@ -0,0 +1,72 @@ +package com.zmops.iot.util; + + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.stereotype.Component; + +/** + * @Author nantian + * @Date 2/20/2020 0020 11:09 AM + * @Email nantian@zmops.com + * @Version 1.0 + */ +@Component +public class SpringUtils implements BeanFactoryPostProcessor { + + private static ConfigurableListableBeanFactory beanFactory; + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + SpringUtils.beanFactory = beanFactory; + } + + /** + * 获取对象 + */ + public static Object getBean(String name) { + return beanFactory.getBean(name); + } + + /** + * 获取对象 + */ + @SuppressWarnings("unchecked") + public static T getBean(String name, Class clz) { + T result = (T) beanFactory.getBean(name); + return result; + } + + /** + * 获取对象 + */ + public static T getBean(Class clz) { + T result = (T) beanFactory.getBean(clz); + return result; + } + + /** + * 判断是否包含对象 + */ + public static boolean containsBean(String name) { + return beanFactory.containsBean(name); + } + + /** + * 创建对象到spring context + */ + @SuppressWarnings("unchecked") + public static T createBean(Class clz) { + T result = (T) beanFactory.createBean(clz, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true); + return result; + } + + /** + * 删除对象 + */ + public static void destroyBean(String beanName) { + beanFactory.destroyScopedBean(beanName); + } +} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java index 5d63cfd7..9a6dbc21 100644 --- a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java @@ -1,39 +1,9 @@ package com.zmops.iot.rest; -import com.alibaba.fastjson.JSON; -import com.zmops.iot.async.executor.Async; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.device.Device; -import com.zmops.iot.domain.device.query.QDevice; -import com.zmops.iot.domain.product.ProductEventRelation; -import com.zmops.iot.domain.product.ProductEventService; -import com.zmops.iot.domain.product.ProductService; -import com.zmops.iot.domain.product.ProductServiceParam; -import com.zmops.iot.domain.product.query.QProductEventRelation; -import com.zmops.iot.domain.product.query.QProductEventService; -import com.zmops.iot.domain.product.query.QProductService; -import com.zmops.iot.domain.product.query.QProductServiceParam; -import com.zmops.iot.model.response.ResponseData; -import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.alarm.service.AlarmNoticeWorker; -import com.zmops.iot.web.alarm.service.AlarmService; -import com.zmops.iot.web.device.service.work.DeviceOnlineWorker; -import com.zmops.iot.web.device.service.work.DeviceServiceLogWorker; -import com.zmops.iot.web.device.service.work.ScenesLogWorker; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - /** * @author nantian created at 2021/8/7 14:56 *

@@ -45,151 +15,5 @@ @Slf4j public class DeviceStatusWebhookController { - @Autowired - private AlarmNoticeWorker alarmNoticeWorker; - - @Autowired - DeviceOnlineWorker deviceOnlineWorker; - - @Autowired - AlarmService alarmService; - - @Autowired - DeviceServiceLogWorker deviceServiceLogWorker; - - @Autowired - ScenesLogWorker scenesLogWorker; - /** - * 在线状态 回调 - * - * @param params webhook 回调参数 - * @return ResponseData - */ - @RequestMapping("/status") - public ResponseData deviceStatusWebhook(@RequestBody Map params) { - - - log.debug("--------设备上下线规则触发----------" + JSON.toJSONString(params)); - - WorkerWrapper, Boolean> deviceOnlineWork = WorkerWrapper., Boolean>builder().id("deviceOnlineWork") - .worker(deviceOnlineWorker).param(params) - .build(); - - try { - Async.work(3000, deviceOnlineWork).awaitFinish(); - } catch (Exception e) { - e.printStackTrace(); - } - - return ResponseData.success("OK"); - } - - /** - * 设备告警 回调 - * - * @param params webhook 回调参数 - * @return ResponseData - */ - @RequestMapping("/problem") - public ResponseData deviceProblemWebhook(@RequestBody Map params) { - - - log.debug("--------设备告警触发----------" + JSON.toJSONString(params)); - - WorkerWrapper, Boolean> alarmNoticeWork = WorkerWrapper., Boolean>builder().id("alarmNoticeWork") - .worker(alarmNoticeWorker).param(params) - .build(); - - try { - Async.work(3000, alarmNoticeWork).awaitFinish(); - } catch (Exception e) { - e.printStackTrace(); - } - - return ResponseData.success("OK"); - } - - /** - * 设备服务 回调 - * - * @param triggerId webhook 回调参数 - * @return ResponseData - */ - @RequestMapping("/service") - public List> deviceServiceWebhook(@RequestParam("triggerId") String triggerId) { - - log.debug("--------设备联动触发----------" + triggerId); - Map alarmInfo = new ConcurrentHashMap<>(3); - - List productEventRelationList = new QProductEventRelation().zbxId.eq(triggerId).findList(); - if (ToolUtil.isEmpty(productEventRelationList)) { - return Collections.emptyList(); - } - - alarmInfo.put("eventRuleId", productEventRelationList.get(0).getEventRuleId()); - alarmInfo.put("relationId", productEventRelationList.get(0).getRelationId()); - -// alarmService.action(alarmInfo); - - WorkerWrapper, Boolean> deviceServiceLogWork = WorkerWrapper., Boolean>builder().id("deviceServiceLogWorker") - .worker(deviceServiceLogWorker).param(alarmInfo) - .build(); - WorkerWrapper, Boolean> scenesLogWork = WorkerWrapper., Boolean>builder().id("scenesLogWorker") - .worker(scenesLogWorker).param(alarmInfo) - .build(); - - try { - Async.work(1000, deviceServiceLogWork,scenesLogWork).awaitFinish(); - } catch (Exception e) { - e.printStackTrace(); - } - - List productEventServiceList = new QProductEventService().eventRuleId.eq(productEventRelationList.get(0).getEventRuleId()) - .or().deviceId.isNull().deviceId.eq(productEventRelationList.get(0).getRelationId()).endOr().findList(); - List> list = new ArrayList<>(); - Map> collect = productEventServiceList.parallelStream().collect(Collectors.groupingBy(ProductEventService::getExecuteDeviceId)); - collect.forEach((key, value) -> { - Map map = new ConcurrentHashMap<>(); - Device device = new QDevice().deviceId.eq(key).findOne(); - if (null == device) { - return; - } - map.put("device", device); - List> serviceList = new ArrayList<>(); - value.forEach(val -> { - Map serviceMap = new ConcurrentHashMap<>(); - ProductService productService = new QProductService().id.eq(val.getServiceId()).findOne(); - if (null == productService) { - return; - } - serviceMap.put("name", productService.getName()); - - List paramList = new QProductServiceParam().serviceId.eq(val.getServiceId()).findList(); - if (ToolUtil.isNotEmpty(paramList)) { - serviceMap.put("param", paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue))); - } - serviceList.add(serviceMap); - }); - map.put("service", serviceList); - list.add(map); - }); - - return list; - } - - /** - * 设备服务 回调 - * - * @param params webhook 回调参数 - * @return ResponseData - */ - @RequestMapping("/event") - public ResponseData deviceEventWebhook(@RequestBody Map params) { - - - log.debug("--------设备事件触发----------" + params); - - return ResponseData.success("OK"); - } } diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index cc80f247..f9b4e0a3 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -50,6 +50,16 @@ zeus-message ${project.version} + + org.apache.camel + camel-http-starter + 2.25.4 + + + org.apache.camel + camel-pgevent + 2.25.4 + diff --git a/zeus-webapp/pom.xml b/zeus-webapp/pom.xml index c1beb5b1..e51dbd6a 100644 --- a/zeus-webapp/pom.xml +++ b/zeus-webapp/pom.xml @@ -52,6 +52,12 @@ taos-jdbcdriver 2.0.31 + + org.apache.camel + camel-core + 2.25.4 + compile + diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 6cb43499..bbb9fddf 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -43,26 +43,25 @@ public class AlarmService { DeviceService deviceService; - public void alarm(Map alarmInfo) { - String deviceId = alarmInfo.get("hostname"); - String eventRuleId = alarmInfo.get("triggerName"); + public void alarm(Map alarmInfo) { + List deviceIds = (List) alarmInfo.get("hostname"); + String eventRuleId = (String) alarmInfo.get("triggerName"); - if (ToolUtil.isEmpty(deviceId) || ToolUtil.isEmpty(eventRuleId)) { + if (ToolUtil.isEmpty(deviceIds) || ToolUtil.isEmpty(eventRuleId)) { return; } - Device device = new QDevice().deviceId.eq(deviceId).findOne(); + List deviceList = new QDevice().deviceId.in(deviceIds).findList(); ProductEvent productEvent = new QProductEvent().eventRuleId.eq(Long.parseLong(eventRuleId)).findOne(); List alarmMessages = new ArrayList<>(); - if (null != device && null != productEvent) { - String alarmmessage = "设备:" + device.getName() + "发生告警,告警内容:" + productEvent.getEventRuleName(); + if (ToolUtil.isNotEmpty(deviceList) && null != productEvent) { + String deviceName = deviceList.parallelStream().map(Device::getName).collect(Collectors.joining(",")); + String alarmmessage = "设备:" + deviceName + "发生告警,告警内容:" + productEvent.getEventRuleName(); alarmMessages.add(AlarmMessage.builder().alarmMessage(alarmmessage).build()); alarmCallbacks.forEach(alarmCallback -> { -// if (alarmCallback.getType().equals("welink")) { alarmCallback.doAlarm(alarmMessages); -// } }); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java deleted file mode 100644 index 78df33c8..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceOnlineWorker.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.zmops.iot.web.device.service.work; - - -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.device.Device; -import com.zmops.iot.domain.device.query.QDevice; -import com.zmops.iot.util.ToolUtil; -import io.ebean.DB; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.time.LocalDateTime; -import java.util.Map; - -/** - * @author yefei - *

- * 更新设备 在线状态 - */ -@Slf4j -@Component -public class DeviceOnlineWorker implements IWorker, Boolean> { - - @Override - public Boolean action(Map param, Map> allWrappers) { - log.debug("更新设备 在线状态…………"); - - String deviceId = param.get("hostname"); - if (ToolUtil.isEmpty(deviceId)) { - return false; - } - Device device = new QDevice().deviceId.eq(deviceId).findOne(); - if (null == device) { - return false; - } - int status = 0; - String recovery = param.get("recovery"); - if (ToolUtil.isNotEmpty(recovery) && "RESOLVED".equals(recovery)) { - status = 1; - } - DB.update(Device.class).where().eq("deviceId", device.getDeviceId()).asUpdate() - .set("online", status).set("latestOnline", LocalDateTime.now()).update(); - - return true; - } - - - @Override - public Boolean defaultValue() { - return true; - } - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java index 84420b97..61d31e5e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java @@ -86,10 +86,13 @@ public Boolean action(DeviceDto deviceDto, Map> allW Map hostRecoveryTriggerMap = zbxTriggerInfoList.parallelStream().filter(o -> o.getTags().parallelStream().anyMatch(t -> "__online__".equals(t.getTag()))) .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid)); + String zbxId = Optional.ofNullable(hostTriggerMap.get(deviceDto.getDeviceId())).orElse(""); + String zbxIdRecovery = Optional.ofNullable(hostRecoveryTriggerMap.get(deviceDto.getDeviceId())).orElse(""); + DB.sqlUpdate("insert into product_status_function_relation (relation_id,rule_id,inherit,zbx_id,zbx_id_recovery) SELECT :deviceId,rule_id,1,:zbxId,:zbxIdRecovery from product_status_function_relation where relation_id=:relationId") .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "") - .setParameter("zbxId", Optional.ofNullable(hostTriggerMap.get(deviceDto.getDeviceId()))) - .setParameter("zbxIdRecovery", Optional.ofNullable(hostRecoveryTriggerMap.get(deviceDto.getDeviceId()))).execute(); + .setParameter("zbxId", zbxId) + .setParameter("zbxIdRecovery", zbxIdRecovery).execute(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventDataProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventDataProcess.java new file mode 100644 index 00000000..6d0bcfe1 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventDataProcess.java @@ -0,0 +1,44 @@ +package com.zmops.iot.web.event; + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.web.event.dto.EventDataDto; +import lombok.extern.slf4j.Slf4j; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Collection; + +/** + * @author yefei + **/ +@Slf4j +@Component(value = "EventDataProcess") +public class EventDataProcess implements Processor { + + @Autowired + Collection eventProcessList; + + @Override + public void process(Exchange exchange) throws Exception { + String inputContext = exchange.getIn().getBody().toString(); + String[] split = inputContext.split("分隔线"); + if (split.length != 2) { + return; + } + + System.out.println("-------------------" + split[1]); + EventDataDto eventData = JSONObject.parseObject(split[1], EventDataDto.class); + + String objectid = eventData.getObjectid(); + + eventProcessList.forEach(eventProcess -> { + if(eventProcess.checkTag(eventData.getTag())){ + eventProcess.process(objectid,eventData.getName()); + } + }); + + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventProcess.java new file mode 100644 index 00000000..cbcb6e1b --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventProcess.java @@ -0,0 +1,11 @@ +package com.zmops.iot.web.event; + +/** + * @author yefei + **/ +public interface EventProcess { + + void process(String triggerId,String triggerName); + + boolean checkTag(String tag); +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventProcessFactory.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventProcessFactory.java new file mode 100644 index 00000000..a4438101 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventProcessFactory.java @@ -0,0 +1,20 @@ +package com.zmops.iot.web.event; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author yefei + **/ +public class EventProcessFactory { + + private static final Map EVENT_PROCESS_MAP = new HashMap<>(); + + public static void register(String tag, EventProcess eventProcess) { + EVENT_PROCESS_MAP.put(tag, eventProcess); + } + + public static EventProcess getExecuteService(String key) { + return EVENT_PROCESS_MAP.get(key); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/SyncZbxEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/SyncZbxEvent.java new file mode 100644 index 00000000..9e57e0fc --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/SyncZbxEvent.java @@ -0,0 +1,26 @@ +package com.zmops.iot.web.event; + +import com.zmops.iot.util.SpringUtils; +import org.apache.camel.LoggingLevel; +import org.apache.camel.builder.RouteBuilder; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * @author yefei + **/ +@Component +public class SyncZbxEvent extends RouteBuilder { + + @Value("${forest.variables.zbxServerIp}") + public String host; + + @Override + public void configure() throws Exception { + fromF("pgevent:%s:5432/zabbix/zabbix_pg_event?pass=postgres&user=postgres", host) + .process(SpringUtils.getBean(EventDataProcess.class)) + + .log(LoggingLevel.DEBUG, log, ">>> PgEvent received from Zabbix Events : ${body}"); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/dto/EventDataDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/dto/EventDataDto.java new file mode 100644 index 00000000..9f16b204 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/dto/EventDataDto.java @@ -0,0 +1,19 @@ +package com.zmops.iot.web.event.dto; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class EventDataDto { + private String eventid; + + private String objectid; + + private String name; + + private String tag; + + private String tagValue; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java new file mode 100644 index 00000000..ffc3ee5d --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java @@ -0,0 +1,60 @@ +package com.zmops.iot.web.event.service; + +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.messages.MessageBody; +import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.sys.query.QSysUser; +import com.zmops.iot.web.alarm.service.AlarmService; +import com.zmops.iot.web.alarm.service.MessageService; +import com.zmops.iot.web.event.EventProcess; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @author yefei + **/ +@Slf4j +@Component +public class AlarmEventProcess implements EventProcess { + + @Autowired + MessageService messageService; + + @Autowired + AlarmService alarmService; + + @Override + public void process(String triggerId,String triggerName) { + log.debug("--------设备告警触发----------" + triggerId); + + List list = new QProductEventRelation().zbxId.eq(triggerId).findList(); + Map params = new ConcurrentHashMap<>(2); + List deviceIds = list.parallelStream().map(ProductEventRelation::getRelationId).collect(Collectors.toList()); + params.put("hostname", deviceIds); + params.put("triggerName", triggerName); + + List userIds = new QSysUser().select(QSysUser.alias().userId).findSingleAttributeList(); + + messageService.push(buildMessage(params, userIds)); + alarmService.alarm(params); + } + + private MessageBody buildMessage(Map alarmInfo, List userIds) { + + return MessageBody.builder().msg("告警消息").persist(true).to(userIds).body(alarmInfo).build(); + } + + + @Override + public boolean checkTag(String tag) { + return "__alarm__".equals(tag); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java new file mode 100644 index 00000000..5d9173ef --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java @@ -0,0 +1,47 @@ +package com.zmops.iot.web.event.service; + +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductStatusFunctionRelation; +import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.EventProcess; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * @author yefei + **/ +@Slf4j +@Component +public class OfflineEventProcess implements EventProcess{ + + @Override + public void process(String triggerId,String triggerName) { + log.debug("更新设备 离线状态…………"); + + ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().zbxIdRecovery.eq(triggerId).findOne(); + if (null == relation) { + return; + } + String deviceId = relation.getRelationId(); + if (ToolUtil.isEmpty(deviceId)) { + return; + } + Device device = new QDevice().deviceId.eq(deviceId).findOne(); + if (null == device) { + return; + } + + DB.update(Device.class).where().eq("deviceId", device.getDeviceId()).asUpdate() + .set("online", 0).set("latestOnline", LocalDateTime.now()).update(); + } + + @Override + public boolean checkTag(String tag) { + return "__offline__".equals(tag); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OnlineEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OnlineEventProcess.java new file mode 100644 index 00000000..6692fd2b --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OnlineEventProcess.java @@ -0,0 +1,48 @@ +package com.zmops.iot.web.event.service; + +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductStatusFunctionRelation; +import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.EventProcess; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * @author yefei + **/ +@Slf4j +@Component +public class OnlineEventProcess implements EventProcess { + + @Override + public void process(String triggerId,String triggerName) { + log.debug("更新设备 在线状态…………"); + + ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().zbxIdRecovery.eq(triggerId).findOne(); + if (null == relation) { + return; + } + String deviceId = relation.getRelationId(); + if (ToolUtil.isEmpty(deviceId)) { + return; + } + Device device = new QDevice().deviceId.eq(deviceId).findOne(); + if (null == device) { + return; + } + + DB.update(Device.class).where().eq("deviceId", device.getDeviceId()).asUpdate() + .set("online", 1).set("latestOnline", LocalDateTime.now()).update(); + } + + @Override + public boolean checkTag(String tag) { + return "__online__".equals(tag); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java new file mode 100644 index 00000000..4bb37fd5 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java @@ -0,0 +1,108 @@ +package com.zmops.iot.web.event.service; + +import com.alibaba.fastjson.JSON; +import com.dtflys.forest.Forest; +import com.zmops.iot.async.executor.Async; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.ProductEventService; +import com.zmops.iot.domain.product.ProductService; +import com.zmops.iot.domain.product.ProductServiceParam; +import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.domain.product.query.QProductService; +import com.zmops.iot.domain.product.query.QProductServiceParam; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.service.work.DeviceServiceLogWorker; +import com.zmops.iot.web.device.service.work.ScenesLogWorker; +import com.zmops.iot.web.event.EventProcess; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @author yefei + **/ +@Slf4j +@Component +public class ServiceEventProcess implements EventProcess { + + @Autowired + DeviceServiceLogWorker deviceServiceLogWorker; + + @Autowired + ScenesLogWorker scenesLogWorker; + + @Override + public void process(String triggerId,String triggerName) { + log.debug("--------设备联动触发----------" + triggerId); + Map alarmInfo = new ConcurrentHashMap<>(3); + + List productEventRelationList = new QProductEventRelation().zbxId.eq(triggerId).findList(); + if (ToolUtil.isEmpty(productEventRelationList)) { + return; + } + + alarmInfo.put("eventRuleId", productEventRelationList.get(0).getEventRuleId()); + alarmInfo.put("relationId", productEventRelationList.get(0).getRelationId()); + + WorkerWrapper, Boolean> deviceServiceLogWork = WorkerWrapper., Boolean>builder().id("deviceServiceLogWorker") + .worker(deviceServiceLogWorker).param(alarmInfo) + .build(); + WorkerWrapper, Boolean> scenesLogWork = WorkerWrapper., Boolean>builder().id("scenesLogWorker") + .worker(scenesLogWorker).param(alarmInfo) + .build(); + + try { + Async.work(1000, deviceServiceLogWork, scenesLogWork).awaitFinish(); + } catch (Exception e) { + e.printStackTrace(); + } + + List productEventServiceList = new QProductEventService().eventRuleId.eq(productEventRelationList.get(0).getEventRuleId()) + .or().deviceId.isNull().deviceId.eq(productEventRelationList.get(0).getRelationId()).endOr().findList(); + List> list = new ArrayList<>(); + Map> collect = productEventServiceList.parallelStream().collect(Collectors.groupingBy(ProductEventService::getExecuteDeviceId)); + collect.forEach((key, value) -> { + Map map = new ConcurrentHashMap<>(); + Device device = new QDevice().deviceId.eq(key).findOne(); + if (null == device) { + return; + } + map.put("device", device); + List> serviceList = new ArrayList<>(); + value.forEach(val -> { + Map serviceMap = new ConcurrentHashMap<>(); + ProductService productService = new QProductService().id.eq(val.getServiceId()).findOne(); + if (null == productService) { + return; + } + serviceMap.put("name", productService.getName()); + + List paramList = new QProductServiceParam().serviceId.eq(val.getServiceId()).findList(); + if (ToolUtil.isNotEmpty(paramList)) { + serviceMap.put("param", paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue))); + } + serviceList.add(serviceMap); + }); + map.put("service", serviceList); + list.add(map); + }); + + Forest.post("/device/action/exec").host("127.0.0.1").port(12800).contentTypeJson().addBody(JSON.toJSON(list)).execute(); + } + + @Override + public boolean checkTag(String tag) { + return "__execute__".equals(tag); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java index 6bf2b9e7..61fc4b30 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java @@ -101,18 +101,21 @@ public Long createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { return productStatusFunction.getRuleId(); } List zbxTriggerInfoList = JSONObject.parseArray(triggerRes, ZbxTriggerInfo.class); - Map hostTriggerMap = zbxTriggerInfoList.parallelStream().filter(o->o.getTags().parallelStream().anyMatch(t->"__offline__".equals(t.getTag()))) + Map hostTriggerMap = zbxTriggerInfoList.parallelStream().filter(o -> o.getTags().parallelStream().anyMatch(t -> "__offline__".equals(t.getTag()))) .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid)); - Map hostRecoveryTriggerMap = zbxTriggerInfoList.parallelStream().filter(o->o.getTags().parallelStream().anyMatch(t->"__online__".equals(t.getTag()))) + Map hostRecoveryTriggerMap = zbxTriggerInfoList.parallelStream().filter(o -> o.getTags().parallelStream().anyMatch(t -> "__online__".equals(t.getTag()))) .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid)); String sql = "select device_id from device where product_id = :productId and device_id not in (select relation_id from product_status_function_relation where inherit='0')"; List deviceDtoList = DB.findDto(DeviceDto.class, sql).setParameter("productId", Long.parseLong(relationId)).findList(); deviceDtoList.forEach(deviceDto -> { + String zbxId = Optional.ofNullable(hostTriggerMap.get(deviceDto.getDeviceId())).orElse(""); + String zbxIdRecovery = Optional.ofNullable(hostRecoveryTriggerMap.get(deviceDto.getDeviceId())).orElse(""); + DB.sqlUpdate("insert into product_status_function_relation (relation_id,rule_id,inherit,zbx_id,zbx_id_recovery) SELECT :deviceId,rule_id,1,:zbxId,:zbxIdRecovery from product_status_function_relation where relation_id=:relationId") .setParameter("deviceId", deviceDto.getDeviceId()).setParameter("relationId", judgeRule.getRelationId() + "") - .setParameter("zbxId", Optional.ofNullable(hostTriggerMap.get(deviceDto.getDeviceId()))) - .setParameter("zbxIdRecovery",Optional.ofNullable(hostRecoveryTriggerMap.get(deviceDto.getDeviceId()))) + .setParameter("zbxId", zbxId) + .setParameter("zbxIdRecovery", zbxIdRecovery) .execute(); }); } From 2f229c3808515747800043f42ddcdefacb6ef3b6 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 27 Oct 2021 14:38:13 +0800 Subject: [PATCH 571/763] [doc]: add field desc --- .../zmops/zeus/iot/server/h2/dao/InsertDAO.java | 15 --------------- .../product/ProductStatusFunctionRelation.java | 2 ++ 2 files changed, 2 insertions(+), 15 deletions(-) delete mode 100644 iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/dao/InsertDAO.java diff --git a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/dao/InsertDAO.java b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/dao/InsertDAO.java deleted file mode 100644 index 3fe78b8e..00000000 --- a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/dao/InsertDAO.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.zmops.zeus.iot.server.h2.dao; - -import com.zmops.zeus.iot.server.library.module.Service; - -import java.sql.ResultSet; - -/** - * @author yefei - **/ -public interface InsertDAO extends Service { - - void insert(String sql); - - ResultSet queryRes(String sql); -} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java index 425e9a9e..6ff7f206 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java @@ -26,8 +26,10 @@ public class ProductStatusFunctionRelation { private String inherit; + // 离线触发器ID private String zbxId; + // 上线触发器ID private String zbxIdRecovery; } From a4741fe9411ac77cb40e76e2d819970e5e840cf2 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 27 Oct 2021 15:15:16 +0800 Subject: [PATCH 572/763] [fix]:code format --- .../iot/web/device/service/work/DeviceEventLogWorker.java | 2 +- .../iot/web/device/service/work/DeviceServiceLogWorker.java | 2 +- .../iot/web/device/service/work/SaveAttributeWorker.java | 4 ++-- .../iot/web/device/service/work/SaveDeviceGrpWorker.java | 4 ++-- .../zmops/iot/web/device/service/work/SaveDeviceWorker.java | 4 ++-- .../zmops/iot/web/device/service/work/SaveOtherWorker.java | 4 ++-- .../com/zmops/iot/web/device/service/work/SaveTagWorker.java | 4 ++-- .../zmops/iot/web/device/service/work/SaveZbxHostWorker.java | 4 ++-- .../zmops/iot/web/device/service/work/ScenesLogWorker.java | 2 +- .../iot/web/device/service/work/UpdateAttrZbxIdWorker.java | 4 ++-- .../iot/web/device/service/work/UpdateDeviceZbxIdWorker.java | 4 ++-- .../zmops/iot/web/device/service/work/UpdateZbxTagWorker.java | 2 +- .../main/java/com/zmops/iot/web/event/EventDataProcess.java | 3 +-- .../com/zmops/iot/web/event/service/AlarmEventProcess.java | 2 +- .../com/zmops/iot/web/event/service/OfflineEventProcess.java | 2 +- .../com/zmops/iot/web/event/service/OnlineEventProcess.java | 2 +- .../com/zmops/iot/web/event/service/ServiceEventProcess.java | 2 +- .../web/product/service/work/AsyncAttrEventZbxIdWorker.java | 2 +- .../iot/web/product/service/work/AsyncAttrZbxIdWorker.java | 2 +- .../product/service/work/SaveProdAttrEventTriggerWorker.java | 2 +- .../iot/web/product/service/work/SaveProdAttrEventWorker.java | 3 ++- .../iot/web/product/service/work/SaveProdAttrWorker.java | 2 +- .../web/product/service/work/SaveProdStatusTriggerWorker.java | 1 - .../zmops/iot/web/product/service/work/SaveProdSvcWorker.java | 1 - .../product/service/work/SaveProductEventTriggerWorker.java | 2 +- .../web/product/service/work/UpdateAttributeEventWorker.java | 2 +- .../iot/web/product/service/work/UpdateAttributeWorker.java | 2 +- .../iot/web/product/service/work/UpdateProdSvcWorker.java | 2 +- .../product/service/work/UpdateProductEventTriggerWorker.java | 2 +- 29 files changed, 36 insertions(+), 38 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceEventLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceEventLogWorker.java index 242a2ae2..a95f0109 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceEventLogWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceEventLogWorker.java @@ -22,7 +22,7 @@ public class DeviceEventLogWorker implements IWorker, Boolea @Override public Boolean action(Map param, Map> allWrappers) { - log.debug("插入 事件 日志…………"); + log.debug("insert into event log…………"); String deviceId = param.get("hostname"); if (ToolUtil.isEmpty(deviceId)) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java index 28da46b0..3ec2c418 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java @@ -30,7 +30,7 @@ public class DeviceServiceLogWorker implements IWorker, Bool @Override public Boolean action(Map param, Map> allWrappers) { - log.debug("插入 服务 日志…………"); + log.debug("insert into service log…………"); long eventRuleId = (long) param.get("eventRuleId"); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java index 766d05aa..ad90fdbc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java @@ -33,7 +33,7 @@ public class SaveAttributeWorker implements IWorker { @Override public Boolean action(DeviceDto deviceDto, Map> map) { - log.debug("step 3:处理Attr 及Attr事件 工作----DEVICEID:"+deviceDto.getDeviceId()+"…………"); + log.debug("step 3:saveAttributeWorker----DEVICEID:{}…………",deviceDto.getDeviceId()); String deviceId = deviceDto.getDeviceId(); @@ -97,7 +97,7 @@ public Boolean action(DeviceDto deviceDto, Map> map) } DB.saveAll(newProductAttributeEventList); - log.debug("step 3:处理Attr 及Attr事件 工作----DEVICEID:"+deviceDto.getDeviceId()+"完成"); + log.debug("step 3:saveAttributeWorker----DEVICEID:{}…………",deviceDto.getDeviceId()); return true; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java index fb932635..e6dc218a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java @@ -27,7 +27,7 @@ public class SaveDeviceGrpWorker implements IWorker { @Override public Boolean action(DeviceDto deviceDto, Map> map) { - log.debug("step 4:处理设备与设备组关系工作----DEVICEID:"+deviceDto.getDeviceId()+"…………"); + log.debug("step 4:SaveDeviceGrpWorker----DEVICEID:{}…………",deviceDto.getDeviceId()); //修改模式 先清空关联关系 if (null != deviceDto.getDeviceId()) { @@ -41,7 +41,7 @@ public Boolean action(DeviceDto deviceDto, Map> map) devicesGroupsList.add(DevicesGroups.builder().deviceId(device.getDeviceId()).deviceGroupId(deviceGroupId).build()); } DB.saveAll(devicesGroupsList); - log.debug("step 4:处理设备与设备组关系工作----DEVICEID:"+deviceDto.getDeviceId()+"完成"); + log.debug("step 4:SaveDeviceGrpWorker----DEVICEID:{}…………",deviceDto.getDeviceId()); return true; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java index 2f6e9f80..142058cc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java @@ -24,7 +24,7 @@ public class SaveDeviceWorker implements IWorker { @Override public Device action(DeviceDto deviceDto, Map> allWrappers) { - log.debug("step 1:处理device工作----DEVICEID:"+deviceDto.getDeviceId()+"…………"); + log.debug("step 1:SaveDeviceWorker----DEVICEID:{}…………",deviceDto.getDeviceId()); Device device = new Device(); ToolUtil.copyProperties(deviceDto, device); @@ -35,7 +35,7 @@ public Device action(DeviceDto deviceDto, Map> allWr device.setStatus(CommonStatus.ENABLE.getCode()); DB.save(device); } - log.debug("step 1:处理device工作----DEVICEID:"+deviceDto.getDeviceId()+"完成"); + log.debug("step 1:SaveDeviceWorker----DEVICEID:{} complete",deviceDto.getDeviceId()); return device; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java index 61d31e5e..9e9af6ef 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java @@ -42,7 +42,7 @@ public class SaveOtherWorker implements IWorker { @Override public Boolean action(DeviceDto deviceDto, Map> allWrappers) { - log.debug("step 8:处理 其它 工作----DEVICEID:" + deviceDto.getDeviceId() + "…………"); + log.debug("step 8:SaveOtherWorker----DEVICEID:{}…………", deviceDto.getDeviceId()); String deviceId = deviceDto.getDeviceId(); @@ -120,7 +120,7 @@ public Boolean action(DeviceDto deviceDto, Map> allW DB.sqlUpdate("insert into product_event_service (service_id,device_id,execute_device_id,event_rule_id,inherit) SELECT service_id,:deviceId,:executeDeviceId,event_rule_id,1 from product_event_service where relation_id=:relationId") .setParameter("deviceId", deviceId).setParameter("executeDeviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "").execute(); - log.debug("step 8:处理 其它 工作----DEVICEID:" + deviceDto.getDeviceId() + "完成"); + log.debug("step 8:SaveOtherWorker----DEVICEID:{}…………", deviceDto.getDeviceId()); return true; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java index 9d303e8b..3a7f2747 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java @@ -24,7 +24,7 @@ public class SaveTagWorker implements IWorker { @Override public Boolean action(DeviceDto deviceDto, Map> allWrappers) { - log.debug("step 2:处理tag工作----DEVICEID:"+deviceDto.getDeviceId()+"…………"); + log.debug("step 2:SaveTagWorker----DEVICEID:{}…………",deviceDto.getDeviceId()); String deviceId = deviceDto.getDeviceId(); @@ -44,7 +44,7 @@ public Boolean action(DeviceDto deviceDto, Map> allW DB.sqlUpdate("insert into tag (sid,tag,value,template_id) SELECT :deviceId,tag,value,id template_id from tag where sid=:sid") .setParameter("deviceId", deviceId).setParameter("sid", deviceDto.getProductId() + "").execute(); - log.debug("step 2:处理tag工作----DEVICEID:"+deviceDto.getDeviceId()+"完成"); + log.debug("step 2:SaveTagWorker----DEVICEID:{} complete",deviceDto.getDeviceId()); return true; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java index b4b8b7b1..01f20a7c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java @@ -33,7 +33,7 @@ public class SaveZbxHostWorker implements IWorker { @Override public String action(DeviceDto deviceDto, Map> map) { - log.debug("step 5:处理Zbx host工作----DEVICEID:"+deviceDto.getDeviceId()+"…………"); + log.debug("step 5:SaveZbxHostWorker----DEVICEID:{}…………",deviceDto.getDeviceId()); //设备ID 作为zbx HOST name Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); String host = device.getDeviceId() + ""; @@ -50,7 +50,7 @@ public String action(DeviceDto deviceDto, Map> map) } else { s = zbxHost.hostCreate(host, hostGrpIds, templateId); } - log.debug("step 5:处理Zbx host工作----DEVICEID:"+deviceDto.getDeviceId()+"完成"); + log.debug("step 5:SaveZbxHostWorker----DEVICEID:{} complete",deviceDto.getDeviceId()); return s; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java index b0d16456..bfc8c831 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java @@ -24,7 +24,7 @@ public class ScenesLogWorker implements IWorker, Boolean> { @Override public Boolean action(Map param, Map> allWrappers) { - log.debug("插入 场景 日志…………"); + log.debug("insert into ScenesLogWorker…………"); long eventRuleId = (long) param.get("eventRuleId"); ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRuleId).findOne(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java index c2c88101..dcb16672 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java @@ -37,7 +37,7 @@ public class UpdateAttrZbxIdWorker implements IWorker { @Override public Boolean action(DeviceDto deviceDto, Map> map) { - log.debug("step 6:处理Attr zbx回填工作----DEVICEID:"+deviceDto.getDeviceId()+"…………"); + log.debug("step 6:resolve Attr zbxID async----deviceid: {} …………",deviceDto.getDeviceId()); String deviceId = deviceDto.getDeviceId(); if (ToolUtil.isNotEmpty(deviceDto.getEdit()) && "true".equals(deviceDto.getEdit())) { @@ -80,7 +80,7 @@ public Boolean action(DeviceDto deviceDto, Map> map) } DB.updateAll(productAttributeEventList); - log.debug("step 6:处理Attr zbx回填工作----DEVICEID:"+deviceDto.getDeviceId()+"完成"); + log.debug("step 6:resolve Attr zbxID async----deviceid: {} complete",deviceDto.getDeviceId()); return true; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java index d2c0bcac..811d9709 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java @@ -28,10 +28,10 @@ public Boolean action(String deviceDto, Map> map) { Object result = map.get("saveZbxHostWork").getWorkResult().getResult(); JSONArray hostid = JSONObject.parseObject(result.toString()).getJSONArray("hostids"); Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); - log.debug("step 7:处理 zbxID 回填工作----DEVICEID:"+device.getDeviceId()+"HOSTID:"+hostid.get(0).toString()+"…………"); + log.debug("step 7:resolve zbxID async----DEVICEID:{}, HOSTID:{}…………",device.getDeviceId(),hostid.get(0).toString()); device.setZbxId(hostid.get(0).toString()); DB.update(device); - log.debug("step 7:处理 zbxID 回填工作----DEVICEID:"+device.getDeviceId()+"HOSTID:"+hostid.get(0).toString()+"完成"); + log.debug("step 7:resolve zbxID async----DEVICEID:{}, HOSTID:{} 完成",device.getDeviceId(),hostid.get(0).toString()); return true; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java index 8329cb80..ef0c02a6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java @@ -32,7 +32,7 @@ public class UpdateZbxTagWorker implements IWorker { @Override public Boolean action(DeviceDto deviceDto, Map> map) { - log.debug("同步 zbx tag 工作……"); + log.debug("UpdateZbxTagWorker……"); //取出 ZBX hostid Object result = map.get("saveZbxHostWork").getWorkResult().getResult(); JSONArray hostid = JSONObject.parseObject(result.toString()).getJSONArray("hostids"); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventDataProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventDataProcess.java index 6d0bcfe1..229939f4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventDataProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventDataProcess.java @@ -23,12 +23,11 @@ public class EventDataProcess implements Processor { @Override public void process(Exchange exchange) throws Exception { String inputContext = exchange.getIn().getBody().toString(); - String[] split = inputContext.split("分隔线"); + String[] split = inputContext.split("\\$\\$"); if (split.length != 2) { return; } - System.out.println("-------------------" + split[1]); EventDataDto eventData = JSONObject.parseObject(split[1], EventDataDto.class); String objectid = eventData.getObjectid(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java index ffc3ee5d..c560225e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java @@ -33,7 +33,7 @@ public class AlarmEventProcess implements EventProcess { @Override public void process(String triggerId,String triggerName) { - log.debug("--------设备告警触发----------" + triggerId); + log.debug("--------alarm event----------{}" , triggerId); List list = new QProductEventRelation().zbxId.eq(triggerId).findList(); Map params = new ConcurrentHashMap<>(2); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java index 5d9173ef..a834e0be 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java @@ -21,7 +21,7 @@ public class OfflineEventProcess implements EventProcess{ @Override public void process(String triggerId,String triggerName) { - log.debug("更新设备 离线状态…………"); + log.debug("update device offline status…………"); ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().zbxIdRecovery.eq(triggerId).findOne(); if (null == relation) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OnlineEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OnlineEventProcess.java index 6692fd2b..a5bc0de1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OnlineEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OnlineEventProcess.java @@ -21,7 +21,7 @@ public class OnlineEventProcess implements EventProcess { @Override public void process(String triggerId,String triggerName) { - log.debug("更新设备 在线状态…………"); + log.debug("update device online status…………"); ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().zbxIdRecovery.eq(triggerId).findOne(); if (null == relation) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java index 4bb37fd5..8b040701 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java @@ -43,7 +43,7 @@ public class ServiceEventProcess implements EventProcess { @Override public void process(String triggerId,String triggerName) { - log.debug("--------设备联动触发----------" + triggerId); + log.debug("--------service event----------{}" , triggerId); Map alarmInfo = new ConcurrentHashMap<>(3); List productEventRelationList = new QProductEventRelation().zbxId.eq(triggerId).findList(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java index ec0f9736..33c7102d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java @@ -33,7 +33,7 @@ public class AsyncAttrEventZbxIdWorker implements IWorker> map) { - log.debug("处理Attr zbx回填工作……"); + log.debug("AsyncAttrEventZbxIdWorker……"); Long attrId = productAttr.getAttrId(); //根据name 取出监控项 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java index 4d2058fa..c2dbc78c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java @@ -33,7 +33,7 @@ public class AsyncAttrZbxIdWorker implements IWorker { @Override public Boolean action(ProductAttr productAttr, Map> map) { - log.debug("处理Attr zbx回填工作……"); + log.debug("AsyncAttrZbxIdWorker……"); Long attrId = productAttr.getAttrId(); //根据name 取出监控项 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java index ef267e94..3d4312e4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java @@ -29,7 +29,7 @@ public class SaveProdAttrEventTriggerWorker implements IWorker> map) { - log.debug("处理产品 新增Attr事件 告警工作…………"); + log.debug("SaveProdAttrEventTriggerWorker…………"); String prodId = productAttr.getProductId(); StringBuilder expression = new StringBuilder(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java index f5e3911e..fed0932c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java @@ -28,7 +28,8 @@ public class SaveProdAttrEventWorker implements IWorker> map) { - log.debug("处理产品 新增Attr 同步到设备工作…………"); + log.debug("SaveProdAttrEventTriggerWorker…………"); + String prodId = productAttr.getProductId(); int count = new QDevice().deviceId.eq(prodId).findCount(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java index 8772e7db..37c57095 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java @@ -32,7 +32,7 @@ public class SaveProdAttrWorker implements IWorker { @Override public Boolean action(ProductAttr productAttr, Map> map) { - log.debug("处理产品 新增Attr 同步到设备工作…………"); + log.debug("SaveProdAttrWorker…………"); String sql = "select device_id from device " + " where product_id = :productId and device_id not in (" + diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java index 20aae235..04bf979c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java @@ -26,7 +26,6 @@ public class SaveProdStatusTriggerWorker implements IWorker> map) { - log.debug("处理产品 新增上下线规则 同步到设备工作…………"); String prodId = productServiceDto.getRelationId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java index c8cf83a6..4ad29f66 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java @@ -28,7 +28,6 @@ public class SaveProdSvcWorker implements IWorker { @Override public Boolean action(ProductServiceDto productServiceDto, Map> map) { - log.debug("处理产品 新增服务 同步到设备工作…………"); String prodId = productServiceDto.getRelationId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java index fb4de139..d7586925 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java @@ -37,7 +37,7 @@ public class SaveProductEventTriggerWorker implements IWorker> map) { - log.debug("处理产品 新增告警规则 同步到设备工作…………"); + log.debug("SaveProductEventTriggerWorker…………"); String prodId = productEventRule.getProductId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java index b918f0af..9f643e44 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java @@ -25,7 +25,7 @@ public class UpdateAttributeEventWorker implements IWorker> map) { - log.debug("处理产品属性事件修改 同步到设备工作…………"); + log.debug("UpdateAttributeEventWorker…………"); Long attrId = productAttr.getAttrId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java index 9de1c8ea..0d2d7bf3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java @@ -28,7 +28,7 @@ public class UpdateAttributeWorker implements IWorker { @Override public Boolean action(ProductAttr productAttr, Map> map) { - log.debug("处理产品属性修改 同步到设备工作…………"); + log.debug("UpdateAttributeWorker…………"); Long attrId = productAttr.getAttrId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java index cbc4e2f2..bae3a1de 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java @@ -28,7 +28,7 @@ public class UpdateProdSvcWorker implements IWorker @Override public Boolean action(ProductServiceDto productServiceDto, Map> map) { - log.debug("处理产品服务修改 同步到设备工作…………"); + log.debug("UpdateProdSvcWorker…………"); String prodId = productServiceDto.getRelationId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java index f7be62a7..d1c14f30 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java @@ -31,7 +31,7 @@ public class UpdateProductEventTriggerWorker implements IWorker> map) { - log.debug("处理产品 修改告警规则 同步到设备工作…………"); + log.debug("UpdateProductEventTriggerWorker…………"); String prodId = productEventRule.getProductId(); From 47bee11619c9462f01383f4050e41fbd2308d0a4 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 27 Oct 2021 15:32:57 +0800 Subject: [PATCH 573/763] [fix]: add service execute --- .../controller/DeviceServiceController.java | 26 +++++++++ .../web/device/service/DeviceSvrService.java | 58 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceServiceController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceServiceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceServiceController.java new file mode 100644 index 00000000..0042909a --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceServiceController.java @@ -0,0 +1,26 @@ +package com.zmops.iot.web.device.controller; + +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.device.service.DeviceSvrService; +import org.apache.camel.spi.AsEndpointUri; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + **/ +@RestController +@RequestMapping("/device/service") +public class DeviceServiceController { + + @Autowired + DeviceSvrService deviceSvrService; + + @RequestMapping("/execute") + public ResponseData execute(@RequestParam("deviceId") String deviceId,@RequestParam("serviceId") Long serviceId){ + deviceSvrService.execute(deviceId,serviceId); + return ResponseData.success(); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java new file mode 100644 index 00000000..7acdd269 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java @@ -0,0 +1,58 @@ +package com.zmops.iot.web.device.service; + +import com.alibaba.fastjson.JSON; +import com.dtflys.forest.Forest; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductService; +import com.zmops.iot.domain.product.ProductServiceParam; +import com.zmops.iot.domain.product.query.QProductService; +import com.zmops.iot.domain.product.query.QProductServiceParam; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @author yefei + **/ +@Service +public class DeviceSvrService { + + public void execute(String deviceId, Long serviceId) { + + List> list = new ArrayList<>(); + + Map map = new ConcurrentHashMap<>(2); + Device device = new QDevice().deviceId.eq(deviceId).findOne(); + if (null == device) { + throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); + } + map.put("device", device); + + List> serviceList = new ArrayList<>(); + Map serviceMap = new ConcurrentHashMap<>(); + ProductService productService = new QProductService().id.eq(serviceId).findOne(); + if (null == productService) { + throw new ServiceException(BizExceptionEnum.SERVICE_NOT_EXISTS); + } + serviceMap.put("name", productService.getName()); + + List paramList = new QProductServiceParam().serviceId.eq(serviceId).findList(); + if (ToolUtil.isNotEmpty(paramList)) { + serviceMap.put("param", paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue))); + } + serviceList.add(serviceMap); + + map.put("service", serviceList); + list.add(map); + + Forest.post("/device/action/exec").host("127.0.0.1").port(12800).contentTypeJson().addBody(JSON.toJSON(list)).execute(); + } +} From 237865a81a6c2d1aadbd6a9f5e919da1fb7b4c43 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 27 Oct 2021 17:14:46 +0800 Subject: [PATCH 574/763] [fix]: fix local db --- .../iot/server/h2/module/LocalH2Module.java | 2 +- .../server/h2/provider/LocalH2InsertDAO.java | 2 +- .../server/h2/provider/LocalH2Provider.java | 3 +- .../zeus/iot/server/h2/service/InsertDAO.java | 15 ++++++++ .../web/alarm/service/AlarmNoticeWorker.java | 38 ------------------- .../com/zmops/iot/web/event/SyncZbxEvent.java | 16 ++++++-- 6 files changed, 31 insertions(+), 45 deletions(-) create mode 100644 iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/service/InsertDAO.java delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java diff --git a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/module/LocalH2Module.java b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/module/LocalH2Module.java index acf26ec7..5b466fd7 100644 --- a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/module/LocalH2Module.java +++ b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/module/LocalH2Module.java @@ -1,6 +1,6 @@ package com.zmops.zeus.iot.server.h2.module; -import com.zmops.zeus.iot.server.h2.dao.InsertDAO; +import com.zmops.zeus.iot.server.h2.service.InsertDAO; import com.zmops.zeus.iot.server.library.module.ModuleDefine; /** diff --git a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2InsertDAO.java b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2InsertDAO.java index 6c0bb9cf..cd219eb2 100644 --- a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2InsertDAO.java +++ b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2InsertDAO.java @@ -1,6 +1,6 @@ package com.zmops.zeus.iot.server.h2.provider; -import com.zmops.zeus.iot.server.h2.dao.InsertDAO; +import com.zmops.zeus.iot.server.h2.service.InsertDAO; import com.zmops.zeus.iot.server.library.client.jdbc.JDBCClientException; import com.zmops.zeus.iot.server.library.client.jdbc.hikaricp.JDBCHikariCPClient; diff --git a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2Provider.java b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2Provider.java index 82d95a7f..eb665f6c 100644 --- a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2Provider.java +++ b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2Provider.java @@ -1,14 +1,13 @@ package com.zmops.zeus.iot.server.h2.provider; -import com.zmops.zeus.iot.server.h2.dao.InsertDAO; import com.zmops.zeus.iot.server.h2.module.LocalH2Module; +import com.zmops.zeus.iot.server.h2.service.InsertDAO; import com.zmops.zeus.iot.server.library.client.jdbc.JDBCClientException; import com.zmops.zeus.iot.server.library.client.jdbc.hikaricp.JDBCHikariCPClient; import com.zmops.zeus.iot.server.library.module.*; import java.sql.Connection; import java.sql.ResultSet; -import java.sql.SQLException; import java.util.Properties; /** diff --git a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/service/InsertDAO.java b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/service/InsertDAO.java new file mode 100644 index 00000000..b7b33a5e --- /dev/null +++ b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/service/InsertDAO.java @@ -0,0 +1,15 @@ +package com.zmops.zeus.iot.server.h2.service; + +import com.zmops.zeus.iot.server.library.module.Service; + +import java.sql.ResultSet; + +/** + * @author yefei + **/ +public interface InsertDAO extends Service { + + void insert(String sql); + + ResultSet queryRes(String sql); +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java deleted file mode 100644 index 9d0f161b..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmNoticeWorker.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.zmops.iot.web.alarm.service; - -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.messages.MessageBody; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author yefei - **/ -@Service -public class AlarmNoticeWorker implements IWorker, Boolean> { - - @Autowired - MessageService messageService; - - @Autowired - AlarmService alarmService; - - @Override - public Boolean action(Map alarmInfo, Map> allWrappers) { - Map alarmInfo2 = new HashMap<>(alarmInfo); - messageService.push(buildMessage(alarmInfo2)); - alarmService.alarm(alarmInfo); - return null; - } - - private MessageBody buildMessage(Map alarmInfo) { - - return MessageBody.builder().msg("告警消息").persist(true).body(alarmInfo).build(); - } - - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/SyncZbxEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/SyncZbxEvent.java index 9e57e0fc..15be446c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/SyncZbxEvent.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/SyncZbxEvent.java @@ -6,18 +6,28 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import java.util.Optional; + /** * @author yefei **/ @Component public class SyncZbxEvent extends RouteBuilder { - @Value("${forest.variables.zbxServerIp}") - public String host; + @Value("${spring.datasource.druid.url}") + private String url; + @Value("${spring.datasource.druid.username}") + private String username; + @Value("${spring.datasource.druid.password}") + private String password; @Override public void configure() throws Exception { - fromF("pgevent:%s:5432/zabbix/zabbix_pg_event?pass=postgres&user=postgres", host) + url = url.substring(url.indexOf("//") + 2); + String host = url.substring(0, url.indexOf(":")); + int port = Optional.of(url.substring(url.indexOf(":") + 1, url.indexOf("/"))).map(Integer::parseInt).orElse(5432); + + fromF("pgevent:%s:%d/zabbix/zabbix_pg_event?pass=%s&user=%s", host, port, password, username) .process(SpringUtils.getBean(EventDataProcess.class)) .log(LoggingLevel.DEBUG, log, ">>> PgEvent received from Zabbix Events : ${body}"); From 04f6cc4000f7838835dd7980026b0d4c3617da44 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 27 Oct 2021 17:27:13 +0800 Subject: [PATCH 575/763] [fix]: fix init setting --- .../zmops/zeus/driver/service/ZbxAction.java | 61 ------------------- .../zmops/zeus/driver/service/ZbxScript.java | 39 ------------ .../zmops/iot/web/init/BasicSettingsInit.java | 51 ---------------- .../iot/web/init/DeviceSatusScriptInit.java | 50 --------------- 4 files changed, 201 deletions(-) delete mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java delete mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java deleted file mode 100644 index e4e205fd..00000000 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.zmops.zeus.driver.service; - -import com.dtflys.forest.annotation.BaseRequest; -import com.dtflys.forest.annotation.Post; -import com.zmops.zeus.driver.annotation.JsonPath; -import com.zmops.zeus.driver.annotation.ParamName; -import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; - -/** - * @author nantian created at 2021/8/7 23:27 - */ - -@BaseRequest( - baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", - interceptor = JsonBodyBuildInterceptor.class -) -public interface ZbxAction { - - - /** - * 创建默认 在线状态 Action - * - * @param userAuth api token - * @param scriptId 脚本ID - * @param groupId 全局主机组ID - * @return String - */ - @Post(headers = "authTag: noAuth") - @JsonPath("/action/action.init.create") - String createOfflineStatusAction(@ParamName("userAuth") String userAuth, - @ParamName("name") String name, - @ParamName("tagName") String tagName, - @ParamName("scriptId") String scriptId, - @ParamName("groupId") String groupId); - - /** - * 创建默认 告警通知 Action - * - * @param userAuth api token - * @param scriptId 脚本ID - * @param groupId 全局主机组ID - * @return String - */ - @Post(headers = "authTag: noAuth") - @JsonPath("/action/action.create") - String createAlarmAction(@ParamName("userAuth") String userAuth, - @ParamName("name") String name, - @ParamName("tagName") String tagName, - @ParamName("scriptId") String scriptId, - @ParamName("groupId") String groupId); - - /** - * 获取 在线状态 Action - * - * @param userAuth api token - * @return String - */ - @Post(headers = "authTag: noAuth") - @JsonPath("/action/action.offline.get") - String getOfflineStatusAction(@ParamName("userAuth") String userAuth, @ParamName("name") String name); -} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java deleted file mode 100644 index 08d9c355..00000000 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.zmops.zeus.driver.service; - -import com.dtflys.forest.annotation.BaseRequest; -import com.dtflys.forest.annotation.Post; -import com.zmops.zeus.driver.annotation.JsonPath; -import com.zmops.zeus.driver.annotation.ParamName; -import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; - -/** - * @author nantian created at 2021/8/7 20:42 - */ -@BaseRequest( - baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", - interceptor = JsonBodyBuildInterceptor.class -) -public interface ZbxScript { - - - /** - * 创建 在线状态 回调地址 - * - * @param userApiToken apiToekn - * @return String - */ - @Post(headers = "authTag: noAuth") - @JsonPath("/script/script.init.create") - String createOfflineStatusScript(@ParamName("userAuth") String userApiToken); - - - /** - * 获取 在线状态 回调脚本 ID - * - * @param userAuth 授权Token - * @return String - */ - @Post(headers = "authTag: noAuth") - @JsonPath("/script/script.offline.get") - String getOfflineStatusScript(@ParamName("userAuth") String userAuth); -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java index aad92f1b..2690fbeb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java @@ -2,16 +2,13 @@ import com.alibaba.fastjson.JSON; import com.dtflys.forest.config.ForestConfiguration; -import com.zmops.zeus.driver.service.ZbxAction; import com.zmops.zeus.driver.service.ZbxHostGroup; import com.zmops.zeus.driver.service.ZbxInitService; -import com.zmops.zeus.driver.service.ZbxScript; import lombok.Data; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -28,18 +25,11 @@ public class BasicSettingsInit { @Autowired private ZbxHostGroup zbxHostGroup; - @Autowired - private ZbxScript zbxScript; - - @Autowired - private ZbxAction zbxAction; - @Autowired private ZbxInitService zbxInitService; private String zbxApiToken; - @PostConstruct public void init() { zbxApiToken = configuration.getVariableValue("zbxApiToken").toString(); @@ -147,51 +137,10 @@ public String getGuestRoleId() { return null; } - public Map createOfflineStatusScript() { - zbxScript.createOfflineStatusScript(zbxApiToken); - - return getOfflineStatusScript(); - } - - public Map getOfflineStatusScript() { - String response = zbxScript.getOfflineStatusScript(zbxApiToken); - List> ids = JSON.parseObject(response, List.class); - Map map = new HashMap<>(3); - if (null != ids && ids.size() > 0) { - ids.forEach(script -> { - map.put(script.get("name"), script.get("scriptid")); - }); - } - return map; - } - - - public String createOffLineAction(String name, String tagName, String scriptId, String groupId) { - String response = zbxAction.createOfflineStatusAction(zbxApiToken, name, tagName, scriptId, groupId); - return JSON.parseObject(response, ZbxResponseIds.class).getActionids()[0]; - } - - public String createAction(String name, String tagName, String scriptId, String groupId) { - String response = zbxAction.createAlarmAction(zbxApiToken, name, tagName, scriptId, groupId); - return JSON.parseObject(response, ZbxResponseIds.class).getActionids()[0]; - } - - - public String getAction(String name) { - String response = zbxAction.getOfflineStatusAction(zbxApiToken, name); - List> ids = JSON.parseObject(response, List.class); - if (null != ids && ids.size() > 0) { - return ids.get(0).get("actionid"); - } - return null; - } - @Data static class ZbxResponseIds { String[] groupids; - String[] scriptids; - String[] actionids; String[] userids; String[] usrgrpids; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java index a9f33bea..8423a30e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java @@ -1,15 +1,12 @@ package com.zmops.iot.web.init; import com.zmops.iot.domain.sys.SysConfig; -import com.zmops.iot.util.ToolUtil; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; -import java.util.Map; - /** * @author nantian created at 2021/8/7 20:25 */ @@ -20,22 +17,7 @@ public class DeviceSatusScriptInit implements CommandLineRunner { public static final String GLOBAL_HOST_GROUP_CODE = "ZEUS_HOST_GROUP_ID"; - public static final String GLOBAL_OFFLINE_ACTION_CODE = "ZEUS_OFFLINE_ACTION_ID"; - public static final String GLOBAL_ALARM_ACTION_CODE = "ZEUS_ALARM_ACTION_ID"; - public static final String GLOBAL_EXEC_ACTION_CODE = "ZEUS_EXEC_ACTION_ID"; public static final String GLOBAL_ADMIN_ROLE_CODE = "ZEUS_ADMIN_ROLE_ID"; - public static final String GLOBAL_EVENT_ACTION_CODE = "ZEUS_EVENT_ACTION_ID"; - - public static final String SCRIPT_OFFLINE = "__offline_status__"; - public static final String SCRIPT_ALARM = "__trigger_webhook__"; - public static final String SCRIPT_EXECUTE = "__trigger_execute__"; - public static final String SCRIPT_EVENT = "__attr_event__"; - - public static final String ACTION_TAG_OFFLINE = "__offline__"; - public static final String ACTION_TAG_ALARM = "__alarm__"; - public static final String ACTION_TAG_EXECUTE = "__execute__"; - public static final String ACTION_TAG_EXENT = "__event__"; - @Autowired private BasicSettingsInit basicSettingsInit; @@ -65,37 +47,5 @@ public void run(String... args) throws Exception { basicSettingsInit.createCookieUser(userGroupId, guestRoleId); } - - // 第二步:创建全局回调脚本 - Map script = basicSettingsInit.getOfflineStatusScript(); - if (ToolUtil.isEmpty(script)) { - script = basicSettingsInit.createOfflineStatusScript(); - } - - String offLineActionId = basicSettingsInit.getAction(SCRIPT_OFFLINE); - if (offLineActionId == null) { - offLineActionId = basicSettingsInit.createOffLineAction(SCRIPT_OFFLINE, ACTION_TAG_OFFLINE, script.get(SCRIPT_OFFLINE), groupId); - } - DB.update(SysConfig.class).where().eq("code", GLOBAL_OFFLINE_ACTION_CODE).asUpdate().set("value", offLineActionId).update(); - - String alarmActionId = basicSettingsInit.getAction(SCRIPT_ALARM); - if (alarmActionId == null) { - alarmActionId = basicSettingsInit.createAction(SCRIPT_ALARM, ACTION_TAG_ALARM, script.get(SCRIPT_ALARM), groupId); - } - DB.update(SysConfig.class).where().eq("code", GLOBAL_ALARM_ACTION_CODE).asUpdate().set("value", alarmActionId).update(); - - String execActionId = basicSettingsInit.getAction(SCRIPT_EXECUTE); - if (execActionId == null) { - execActionId = basicSettingsInit.createAction(SCRIPT_EXECUTE, ACTION_TAG_EXECUTE, script.get(SCRIPT_EXECUTE), groupId); - } - DB.update(SysConfig.class).where().eq("code", GLOBAL_EXEC_ACTION_CODE).asUpdate().set("value", execActionId).update(); - - String eventActionId = basicSettingsInit.getAction(SCRIPT_EVENT); - if (eventActionId == null) { - eventActionId = basicSettingsInit.createAction(SCRIPT_EVENT, ACTION_TAG_EXENT, script.get(SCRIPT_EVENT), groupId); - } - DB.update(SysConfig.class).where().eq("code", GLOBAL_EVENT_ACTION_CODE).asUpdate().set("value", eventActionId).update(); - - log.info("全局主机组ID:{},在线触发动作ID:{},告警触发动作ID:{},命令执行触发动作ID:{},事件触发动作ID:{}", groupId, offLineActionId, alarmActionId, execActionId, eventActionId); } } From 2875ce8c4f5969b96f07b6b9cc20c30aac01f0dd Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 27 Oct 2021 18:31:23 +0800 Subject: [PATCH 576/763] [fix]: code format --- .../java/com/zmops/iot/web/alarm/service/AlarmService.java | 4 ++-- .../com/zmops/iot/web/analyse/service/ZbxChartsService.java | 2 +- .../zmops/iot/web/device/schedule/SyncTaosTagSchedule.java | 2 +- .../com/zmops/iot/web/device/service/DeviceModelService.java | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index bbb9fddf..1c8d48e1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -189,7 +189,7 @@ public List getZbxAlarm(AlarmParam alarmParam) { deviceIds = deviceService.getDeviceIds(); } - List zbxIds = new QDevice().select(QDevice.alias().zbxId).deviceId.in(deviceIds).findSingleAttributeList(); + List zbxIds = new QDevice().select(QDevice.alias().zbxId).deviceId.in(deviceIds).zbxId.isNotNull().findSingleAttributeList(); if (ToolUtil.isEmpty(zbxIds)) { return Collections.EMPTY_LIST; } @@ -244,7 +244,7 @@ public List getEventProblem(AlarmParam alarmParam) { deviceIds = deviceService.getDeviceIds(); } - List zbxIds = new QDevice().select(QDevice.alias().zbxId).deviceId.in(deviceIds).findSingleAttributeList(); + List zbxIds = new QDevice().select(QDevice.alias().zbxId).deviceId.in(deviceIds).zbxId.isNotNull().findSingleAttributeList(); if (ToolUtil.isEmpty(zbxIds)) { return Collections.EMPTY_LIST; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java index eca08b42..0f39cc84 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java @@ -156,7 +156,7 @@ private static byte[] toByteArray(InputStream input) throws IOException { private List getItemIds(List attrIds) { - return new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(attrIds).findSingleAttributeList(); + return new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(attrIds).zbxId.isNotNull().findSingleAttributeList(); } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java index 1527fd29..c3c12114 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java @@ -75,7 +75,7 @@ public void sync() { //更新子表 标签值 tagMap.forEach((deviceId, tags) -> { //根据deviceId 找到 设备下所有itemId - List itemIds = new QProductAttribute().select(QProductAttribute.alias().zbxId).productId.eq(deviceId).findSingleAttributeList(); + List itemIds = new QProductAttribute().select(QProductAttribute.alias().zbxId).productId.eq(deviceId).zbxId.isNotNull().findSingleAttributeList(); if (ToolUtil.isEmpty(itemIds)) { return; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index caaf5734..a9abbe29 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -295,7 +295,7 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { */ public void deleteTrapperItem(ProductAttr productAttr) { - List zbxIds = new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(productAttr.getAttrIds()).findSingleAttributeList(); + List zbxIds = new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(productAttr.getAttrIds()).zbxId.isNotNull().findSingleAttributeList(); //删除zbx item if (ToolUtil.isNotEmpty(zbxIds)) { List itemInfos = JSONObject.parseArray(zbxItem.getItemInfo(zbxIds.toString(), null), ZbxItemInfo.class); From cbd09a296247a0eb8cd01e48c10f06df60ad55d7 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 27 Oct 2021 21:19:02 +0800 Subject: [PATCH 577/763] [fix]: fix offline status --- .../iot/web/device/service/DeviceSvrService.java | 12 +++++------- .../web/event/service/OfflineEventProcess.java | 2 +- .../web/event/service/ServiceEventProcess.java | 16 +++++++--------- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java index 7acdd269..d91f1757 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java @@ -2,8 +2,6 @@ import com.alibaba.fastjson.JSON; import com.dtflys.forest.Forest; -import com.zmops.iot.domain.device.Device; -import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductService; import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.product.query.QProductService; @@ -30,11 +28,11 @@ public void execute(String deviceId, Long serviceId) { List> list = new ArrayList<>(); Map map = new ConcurrentHashMap<>(2); - Device device = new QDevice().deviceId.eq(deviceId).findOne(); - if (null == device) { - throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); - } - map.put("device", device); +// Device device = new QDevice().deviceId.eq(deviceId).findOne(); +// if (null == device) { +// throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); +// } + map.put("device", deviceId); List> serviceList = new ArrayList<>(); Map serviceMap = new ConcurrentHashMap<>(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java index a834e0be..1868b062 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java @@ -23,7 +23,7 @@ public class OfflineEventProcess implements EventProcess{ public void process(String triggerId,String triggerName) { log.debug("update device offline status…………"); - ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().zbxIdRecovery.eq(triggerId).findOne(); + ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().zbxId.eq(triggerId).findOne(); if (null == relation) { return; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java index 8b040701..3ebf6406 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java @@ -4,8 +4,6 @@ import com.dtflys.forest.Forest; import com.zmops.iot.async.executor.Async; import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.device.Device; -import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductEventRelation; import com.zmops.iot.domain.product.ProductEventService; import com.zmops.iot.domain.product.ProductService; @@ -42,8 +40,8 @@ public class ServiceEventProcess implements EventProcess { ScenesLogWorker scenesLogWorker; @Override - public void process(String triggerId,String triggerName) { - log.debug("--------service event----------{}" , triggerId); + public void process(String triggerId, String triggerName) { + log.debug("--------service event----------{}", triggerId); Map alarmInfo = new ConcurrentHashMap<>(3); List productEventRelationList = new QProductEventRelation().zbxId.eq(triggerId).findList(); @@ -73,11 +71,11 @@ public void process(String triggerId,String triggerName) { Map> collect = productEventServiceList.parallelStream().collect(Collectors.groupingBy(ProductEventService::getExecuteDeviceId)); collect.forEach((key, value) -> { Map map = new ConcurrentHashMap<>(); - Device device = new QDevice().deviceId.eq(key).findOne(); - if (null == device) { - return; - } - map.put("device", device); +// Device device = new QDevice().deviceId.eq(key).findOne(); +// if (null == device) { +// return; +// } + map.put("device", key); List> serviceList = new ArrayList<>(); value.forEach(val -> { Map serviceMap = new ConcurrentHashMap<>(); From 7668f34b230f42210120f9a4353a321be6313b11 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 28 Oct 2021 10:43:30 +0800 Subject: [PATCH 578/763] [fix]: fix ftl --- .../api-json/trigger/device.status.trigger.update.ftl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl index 0f221ed4..3bb7fef6 100644 --- a/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl +++ b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl @@ -6,9 +6,9 @@ "triggerid": "${triggerId}", "description": "${ruleId}", <#--trigger name--> <#if ruleFunction == "nodata"> - "expression": "nodata(/${deviceId}/${itemKey},${ruleCondition}) = 1", <#--下线规则,nodata = 1 --> + "expression": "nodata(/${deviceId}/${itemKey},${ruleCondition}) = 1" <#--下线规则,nodata = 1 --> <#else> - "expression": "last(/${deviceId}/${itemKey}) ${ruleFunction} ${ruleCondition}", + "expression": "last(/${deviceId}/${itemKey}) ${ruleFunction} ${ruleCondition}" },{ "triggerid": "${recoveryTriggerId}", From 5ee4220729f80f06c17849e27df357052ccff605 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 28 Oct 2021 15:52:56 +0800 Subject: [PATCH 579/763] [feat]: add email notice type --- .../zmops/iot/domain/messages/MailParam.java | 50 +++++++++ .../iot/domain/messages/MailSetting.java | 40 +++++++ .../iot/domain/messages/NoticeRecord.java | 34 ++++++ .../iot/domain/messages/NoticeResult.java | 63 +++++++++++ zeus-message/pom.xml | 5 + .../main/java/com/zmops/iot/media/Notice.java | 27 +++++ .../com/zmops/iot/media/NoticeService.java | 49 ++++++++ .../com/zmops/iot/media/mail/MailMessage.java | 53 +++++++++ .../com/zmops/iot/media/mail/MailNotice.java | 11 ++ .../com/zmops/iot/media/mail/MailNoticer.java | 106 ++++++++++++++++++ .../iot/media/mail/MailSettingService.java | 19 ++++ .../com/zmops/iot/media/mail/MailUtils.java | 96 ++++++++++++++++ .../controller/MailSettingController.java | 42 +++++++ .../alarm/service/MailSettingServiceImpl.java | 74 ++++++++++++ .../zmops/iot/web/event/EventDataProcess.java | 2 +- .../com/zmops/iot/web/event/EventProcess.java | 4 +- .../zmops/iot/web/event/dto/EventDataDto.java | 4 + .../web/event/service/AlarmEventProcess.java | 76 ++++++++++++- .../event/service/OfflineEventProcess.java | 5 +- .../web/event/service/OnlineEventProcess.java | 5 +- .../event/service/ServiceEventProcess.java | 7 +- 21 files changed, 759 insertions(+), 13 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/messages/MailParam.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/messages/MailSetting.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/messages/NoticeRecord.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/messages/NoticeResult.java create mode 100644 zeus-message/src/main/java/com/zmops/iot/media/Notice.java create mode 100644 zeus-message/src/main/java/com/zmops/iot/media/NoticeService.java create mode 100644 zeus-message/src/main/java/com/zmops/iot/media/mail/MailMessage.java create mode 100644 zeus-message/src/main/java/com/zmops/iot/media/mail/MailNotice.java create mode 100644 zeus-message/src/main/java/com/zmops/iot/media/mail/MailNoticer.java create mode 100644 zeus-message/src/main/java/com/zmops/iot/media/mail/MailSettingService.java create mode 100644 zeus-message/src/main/java/com/zmops/iot/media/mail/MailUtils.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MailSettingController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MailSettingServiceImpl.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/messages/MailParam.java b/zeus-common/src/main/java/com/zmops/iot/domain/messages/MailParam.java new file mode 100644 index 00000000..9cc60950 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/messages/MailParam.java @@ -0,0 +1,50 @@ +package com.zmops.iot.domain.messages; + + +import com.zmops.iot.domain.messages.MailSetting; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author yefei + **/ +@Data +public class MailParam { + @NotNull + private String host; + @NotNull + private Integer port; + @NotNull + private String account; + @NotNull + private String password; + @NotNull + private String sender; + private Integer ssl; + private Integer tls; + @NotNull(groups = Test.class) + private String receiver; + @NotNull + private String severity; + @NotNull + private Integer silent; + + public interface Test { + } + + + public MailSetting getSettings() { + return MailSetting.builder() + .host(host) + .password(password) + .port(port) + .account(account) + .sender(sender) + .ssl(ssl) + .tls(tls) + .severity(severity) + .silent(silent) + .build(); + } +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/messages/MailSetting.java b/zeus-common/src/main/java/com/zmops/iot/domain/messages/MailSetting.java new file mode 100644 index 00000000..9df28e57 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/messages/MailSetting.java @@ -0,0 +1,40 @@ +package com.zmops.iot.domain.messages; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "mail_setting") +public class MailSetting { + + @Id + private Integer id; + private String host; + private Integer port; + private String account; + private String password; + private String sender; + private Integer ssl; + private Integer tls; + private String severity; + private Integer silent; + + + public boolean sslAvailable() { + return ssl != null && ssl == 1; + } + + public boolean tlsAvailable() { + return tls != null && tls == 1; + } +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/messages/NoticeRecord.java b/zeus-common/src/main/java/com/zmops/iot/domain/messages/NoticeRecord.java new file mode 100644 index 00000000..65947ae4 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/messages/NoticeRecord.java @@ -0,0 +1,34 @@ +package com.zmops.iot.domain.messages; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.time.LocalDateTime; + +/** + * @author yefei + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "notice_record") +public class NoticeRecord { + @Id + private Integer recordId; + private Long userId; + private String problemId; + private Integer noticeType; + private String noticeStatus; + private String noticeMsg; + private LocalDateTime creatTime; + private String alarmInfo; + private String receiveAccount; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/messages/NoticeResult.java b/zeus-common/src/main/java/com/zmops/iot/domain/messages/NoticeResult.java new file mode 100644 index 00000000..0d4e24bf --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/messages/NoticeResult.java @@ -0,0 +1,63 @@ +package com.zmops.iot.domain.messages; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author yefei + **/ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class NoticeResult { + private NoticeStatus status; + private String msg; + + /** + * 告警信息 + */ + private String alarmInfo; + /** + * 接收账号 + */ + private String receiveAccount; + + + public static NoticeResult skipped() { + return NoticeResult.builder() + .status(NoticeStatus.skipped).build(); + } + + public static NoticeResult success() { + return NoticeResult.builder() + .status(NoticeStatus.success).build(); + } + + public static NoticeResult success(String alarmInfo, String receiveAccount) { + return NoticeResult.builder() + .status(NoticeStatus.success). + alarmInfo(alarmInfo). + receiveAccount(receiveAccount).build(); + } + + public static NoticeResult failed(String error) { + return NoticeResult.builder() + .status(NoticeStatus.failed) + .msg(error).build(); + } + + public static NoticeResult failed(String error, String alarmInfo, String receiveAccount) { + return NoticeResult.builder() + .status(NoticeStatus.failed). + alarmInfo(alarmInfo). + receiveAccount(receiveAccount) + .msg(error).build(); + } + + public enum NoticeStatus { + skipped, success, failed; + } +} diff --git a/zeus-message/pom.xml b/zeus-message/pom.xml index 373f7727..35ae3ae6 100644 --- a/zeus-message/pom.xml +++ b/zeus-message/pom.xml @@ -31,6 +31,11 @@ zeus-driver 1.0-beta + + com.sun.mail + javax.mail + 1.6.2 + diff --git a/zeus-message/src/main/java/com/zmops/iot/media/Notice.java b/zeus-message/src/main/java/com/zmops/iot/media/Notice.java new file mode 100644 index 00000000..04bcc343 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/media/Notice.java @@ -0,0 +1,27 @@ +package com.zmops.iot.media; + + +import com.zmops.iot.domain.messages.NoticeResult; +import com.zmops.iot.domain.sys.SysUser; + +import java.util.Map; + +public interface Notice { + int sms = 1; + int email = 2; + int wechat = 3; + int dingtalk = 4; + + /** + * 发送通知 + * + * @param receiver + * @param macroMap + * @return + */ + NoticeResult send(SysUser receiver, Map macroMap); + + int getType(); + + int getSilent(); +} diff --git a/zeus-message/src/main/java/com/zmops/iot/media/NoticeService.java b/zeus-message/src/main/java/com/zmops/iot/media/NoticeService.java new file mode 100644 index 00000000..d2f97863 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/media/NoticeService.java @@ -0,0 +1,49 @@ +package com.zmops.iot.media; + + +import com.zmops.iot.domain.messages.NoticeResult; +import com.zmops.iot.domain.messages.query.QNoticeRecord; +import com.zmops.iot.domain.sys.SysUser; +import com.zmops.iot.util.LocalDateTimeUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +@Service +public class NoticeService { + + + @Autowired + Collection notices; + + public Map notice(SysUser sysUser, Map macroMap,String triggerId) { +// Problem problem = problemMapper.selectById(Integer.parseInt(macroMap.get("${eventId}"))); + Map res = new HashMap<>(); + notices.forEach(notice -> { + int type = notice.getType(); + + QNoticeRecord eq = new QNoticeRecord().noticeType + .eq(type).creatTime + .ge(LocalDateTimeUtils.minu(LocalDateTime.now(), notice.getSilent(), ChronoUnit.MINUTES)) + .problemId.eq(triggerId); + + if (eq.findCount() > 0) { + return; + } + try { + NoticeResult send = notice.send(sysUser, macroMap); + if (send.getStatus() != NoticeResult.NoticeStatus.skipped) { + res.put(notice.getType(), send); + } + } catch (Exception e) { + e.printStackTrace(); + } + }); + return res; + } +} diff --git a/zeus-message/src/main/java/com/zmops/iot/media/mail/MailMessage.java b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailMessage.java new file mode 100644 index 00000000..2bfe74aa --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailMessage.java @@ -0,0 +1,53 @@ +package com.zmops.iot.media.mail; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 邮件内容 + * @author yefei + * + **/ +@Data +@NoArgsConstructor +public class MailMessage { + /** + * 收件人名称 + */ + private String user; + /** + * 告警信息 + */ + private String message; + /** + * 服务 + */ + private String server; + /** + * 对象类型 + */ + private String objectType; + /** + * 告警规则 + */ + private String alarmRule; + /** + * 告警等级 + */ + private String level; + + /** + * 告警时间 + */ + private String time; + + /** + * ip + */ + private String ip; + + /** + * 指标值 + */ + private String table; +} diff --git a/zeus-message/src/main/java/com/zmops/iot/media/mail/MailNotice.java b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailNotice.java new file mode 100644 index 00000000..0cd705d2 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailNotice.java @@ -0,0 +1,11 @@ +package com.zmops.iot.media.mail; + + +import com.zmops.iot.domain.messages.MailSetting; +import com.zmops.iot.domain.messages.NoticeResult; +import com.zmops.iot.media.Notice; + +public interface MailNotice extends Notice { + + NoticeResult test(MailSetting setting, String receiver); +} diff --git a/zeus-message/src/main/java/com/zmops/iot/media/mail/MailNoticer.java b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailNoticer.java new file mode 100644 index 00000000..bd84c62a --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailNoticer.java @@ -0,0 +1,106 @@ +package com.zmops.iot.media.mail; + + +import com.zmops.iot.domain.messages.MailSetting; +import com.zmops.iot.domain.messages.NoticeResult; +import com.zmops.iot.domain.sys.SysUser; +import com.zmops.iot.util.ToolUtil; +import freemarker.template.Template; +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Service; +import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; +import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +/** + * @author yefei + **/ +@Service +public class MailNoticer implements MailNotice { + + @Autowired + MailSettingService mailSettingService; + @Autowired + private FreeMarkerConfigurer configurer; + + @Override + public NoticeResult test(MailSetting setting, String receiver) { + return MailUtils.test(setting, receiver); + } + + + @Override + public NoticeResult send(SysUser receiver, Map macroMap) { + if (ToolUtil.isEmpty(receiver.getEmail())) { + return NoticeResult.skipped(); + } + MailSetting setting = mailSettingService.get(); + if (setting == null) { + return NoticeResult.skipped(); + } + if (!setting.getSeverity().contains(macroMap.get("${severity}"))) { + return NoticeResult.skipped(); + } + Integer problemId = Integer.parseInt(macroMap.get("${problemId}")); + + String alarmInfo = "【Zeus】 触发[${level}]告警“[${context}]”,[${time}]。请及时处理。"; + for (Map.Entry entry : macroMap.entrySet()) { + String value = Optional.ofNullable(entry.getValue()).orElse(""); + alarmInfo = alarmInfo.replace(entry.getKey(), value); + } + + try { + MailUtils.send(setting, mimeMessage -> { + try { + String subject = "触发${level}告警", + content = "【Zeus】 触发[${level}]告警“[${context}]”,[${time}]。请及时处理。\n"; + for (Map.Entry entry : macroMap.entrySet()) { + String value = Optional.ofNullable(entry.getValue()).orElse(""); + subject = subject.replace(entry.getKey(), value); + content = content.replace(entry.getKey(), value); + } + MailMessage message = new MailMessage(); + message.setUser(receiver.getName()); + message.setMessage(content); + message.setAlarmRule(macroMap.get("${metricName}")); + message.setLevel(macroMap.get("${level}")); + message.setObjectType(macroMap.get("${typeName}")); + message.setServer(macroMap.get("${topMoType}")); + message.setTime(macroMap.get("${time}")); +// message.setTable(values.toString()); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); + helper.setFrom(setting.getSender());//发送者 + helper.setTo(receiver.getEmail());//接收者 + helper.setSubject(subject);//邮件标题 + Map model = new HashMap<>(); + model.put("params", message); + Template template = configurer.getConfiguration().getTemplate("argusAlarmEmailTemplate.html", "UTF-8"); + String text = FreeMarkerTemplateUtils.processTemplateIntoString(template, model); + helper.setText(text, true); + } catch (Exception e) { + e.printStackTrace(); + } + }); + } catch (Exception e) { + e.printStackTrace(); + return NoticeResult.failed("发送失败: " + StringUtils.left(e.getMessage(), 100), alarmInfo, receiver.getEmail()); + } + return NoticeResult.success(alarmInfo, receiver.getEmail()); + } + + @Override + public int getType() { + return email; + } + + @Override + public int getSilent() { + MailSetting setting = mailSettingService.get(); + return Optional.ofNullable(setting.getSilent()).orElse(3); + } +} diff --git a/zeus-message/src/main/java/com/zmops/iot/media/mail/MailSettingService.java b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailSettingService.java new file mode 100644 index 00000000..006f0178 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailSettingService.java @@ -0,0 +1,19 @@ +package com.zmops.iot.media.mail; + + +import com.zmops.iot.domain.messages.MailParam; +import com.zmops.iot.domain.messages.MailSetting; +import com.zmops.iot.domain.messages.NoticeResult; + +/** + * @author yefei + * @email yefei@zmops.com + * @date Created in 2020/11/10 18:58 + * @Description + */ +public interface MailSettingService { + + MailSetting get(); + NoticeResult test(MailParam mailTestVo); + Integer updateSettings(MailSetting mailTestVo); +} diff --git a/zeus-message/src/main/java/com/zmops/iot/media/mail/MailUtils.java b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailUtils.java new file mode 100644 index 00000000..f1f31a41 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailUtils.java @@ -0,0 +1,96 @@ +package com.zmops.iot.media.mail; + + + +import com.sun.mail.util.MailSSLSocketFactory; +import com.zmops.iot.domain.messages.MailSetting; +import com.zmops.iot.domain.messages.NoticeResult; +import org.springframework.mail.javamail.MimeMessageHelper; + + +import javax.mail.Authenticator; +import javax.mail.PasswordAuthentication; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.MimeMessage; +import java.security.GeneralSecurityException; +import java.util.Properties; +import java.util.function.Consumer; + +/** + * @author yefei + * + **/ +public class MailUtils { + + public static void send(MailSetting setting, Consumer consumer) throws GeneralSecurityException, javax.mail.MessagingException { + Properties prop = new Properties(); + prop.setProperty("mail.smtp.host", setting.getHost()); //设置QQ邮件服务器 + prop.setProperty("mail.smtp.port", setting.getPort().toString()); //设置QQ邮件服务器 + prop.setProperty("mail.transport.protocol", "smtp"); // 邮件发送协议 + prop.setProperty("mail.smtp.auth", "true"); // 需要验证用户名密码 + prop.setProperty("mail.smtp.connectiontimeout", "2000"); // 超时 + prop.setProperty("mail.smtp.writetimeout", "5000"); + // QQ邮箱设置SSL加密 + if (setting.sslAvailable()) { + MailSSLSocketFactory sf = new MailSSLSocketFactory(); + sf.setTrustAllHosts(true); + prop.put("mail.smtp.ssl.enable", "true"); + prop.put("mail.smtp.ssl.socketFactory", sf); + } + if (setting.tlsAvailable()) { + //不做服务器证书校验 + prop.put("mail.smtp.ssl.checkserveridentity", "false"); + //添加信任的服务器地址,多个地址之间用空格分开 + prop.put("mail.smtp.ssl.trust", setting.getHost()); + prop.put("mail.smtp.host", setting.getHost()); + prop.put("mail.smtp.starttls.enable", "true"); + } + //1、创建定义整个应用程序所需的环境信息的 Session 对象 + Session session = Session.getInstance(prop, new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + //传入发件人的姓名和授权码 + return new PasswordAuthentication(setting.getAccount(), setting.getPassword()); + } + }); + //2、通过session获取transport对象 + Transport transport = session.getTransport(); + + //3、通过transport对象邮箱用户名和授权码连接邮箱服务器 + transport.connect(setting.getHost(), setting.getAccount(), setting.getPassword()); + + //4、创建邮件,传入session对象 + MimeMessage mimeMessage = new MimeMessage(session); // 创建邮件对象 + consumer.accept(mimeMessage); + //5、发送邮件 + transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients()); + + //6、关闭连接 + transport.close(); + } + + + public static NoticeResult test(MailSetting setting, String receiver) { + try { + send(setting, mimeMessage -> { + try { + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); + helper.setFrom(setting.getSender());//发送者 + helper.setTo(receiver);//接收者 + helper.setSubject("Zesu-iot邮件测试");//邮件标题 + helper.setText("这是一封Zesu-iot测试邮件,请不要回复。", false); + } catch (javax.mail.MessagingException e) { + e.printStackTrace(); + } + }); + return NoticeResult.success(); + } catch (Exception e) { + e.printStackTrace(); + return NoticeResult.failed(e.getMessage()); + } + } + + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MailSettingController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MailSettingController.java new file mode 100644 index 00000000..583e6fac --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MailSettingController.java @@ -0,0 +1,42 @@ +package com.zmops.iot.web.alarm.controller; + + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.messages.MailSetting; +import com.zmops.iot.domain.messages.NoticeResult; +import com.zmops.iot.domain.messages.MailParam; +import com.zmops.iot.web.alarm.service.MailSettingServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + * + **/ +@RestController +@RequestMapping("mailSetting") +public class MailSettingController { + + @Autowired + MailSettingServiceImpl settingService; + + @RequestMapping("get") + public MailSetting get() { + return settingService.get(); + } + + @PostMapping("test") + public NoticeResult test(@Validated(MailParam.Test.class) @RequestBody MailParam mailParam) { + return settingService.test(mailParam); + } + + @PostMapping("update") + public Integer update(@Validated(BaseEntity.Update.class) @RequestBody MailParam mailParam) { + return settingService.updateSettings(mailParam.getSettings()); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MailSettingServiceImpl.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MailSettingServiceImpl.java new file mode 100644 index 00000000..1c1497bc --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MailSettingServiceImpl.java @@ -0,0 +1,74 @@ +package com.zmops.iot.web.alarm.service; + + +import com.zmops.iot.domain.messages.MailParam; +import com.zmops.iot.domain.messages.MailSetting; +import com.zmops.iot.domain.messages.NoticeResult; +import com.zmops.iot.domain.messages.query.QMailSetting; +import com.zmops.iot.media.mail.MailNotice; +import com.zmops.iot.media.mail.MailSettingService; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Optional; + +/** + * @author yefei + **/ +@Service +@Slf4j +public class MailSettingServiceImpl implements MailSettingService { + + @Autowired + MailNotice mailNotice; + + private volatile MailSetting instance; + + @Override + public MailSetting get() { + return Optional.ofNullable(getOne()).orElse(new MailSetting()); + } + + private MailSetting getOne() { + if (instance != null) { + return instance; + } + return instance = Optional.of(new QMailSetting().findList()) + .map(Collection::iterator) + .filter(Iterator::hasNext) + .map(Iterator::next).orElse(null); + } + + + @Override + public NoticeResult test(MailParam mailParam) { + MailSetting mailSetting = mailParam.getSettings(); + NoticeResult noticeResult = mailNotice.test(mailSetting, mailParam.getReceiver()); + //updateSettings(noticeResult, mailSetting); + return noticeResult; + } + + @Override + public Integer updateSettings(MailSetting mailSetting) { + if (mailSetting.getTls() == null) { + mailSetting.setTls(0); + } + if (mailSetting.getSsl() == null) { + mailSetting.setSsl(0); + } + MailSetting dbSetting = getOne(); + if (dbSetting == null) { + DB.insert(mailSetting); + } else { + mailSetting.setId(dbSetting.getId()); + DB.update(mailSetting); + } + instance = mailSetting; + return mailSetting.getId(); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventDataProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventDataProcess.java index 229939f4..43077b32 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventDataProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventDataProcess.java @@ -34,7 +34,7 @@ public void process(Exchange exchange) throws Exception { eventProcessList.forEach(eventProcess -> { if(eventProcess.checkTag(eventData.getTag())){ - eventProcess.process(objectid,eventData.getName()); + eventProcess.process(eventData); } }); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventProcess.java index cbcb6e1b..24b77eeb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventProcess.java @@ -1,11 +1,13 @@ package com.zmops.iot.web.event; +import com.zmops.iot.web.event.dto.EventDataDto; + /** * @author yefei **/ public interface EventProcess { - void process(String triggerId,String triggerName); + void process(EventDataDto eventData); boolean checkTag(String tag); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/dto/EventDataDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/dto/EventDataDto.java index 9f16b204..d7068879 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/dto/EventDataDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/dto/EventDataDto.java @@ -16,4 +16,8 @@ public class EventDataDto { private String tag; private String tagValue; + + private String recoveryValue; + + private String acknowledged; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java index c560225e..35144549 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java @@ -1,18 +1,31 @@ package com.zmops.iot.web.event.service; -import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.messages.MessageBody; +import com.zmops.iot.domain.messages.NoticeRecord; +import com.zmops.iot.domain.messages.NoticeResult; +import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEvent; import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.sys.SysUser; import com.zmops.iot.domain.sys.query.QSysUser; +import com.zmops.iot.media.NoticeService; +import com.zmops.iot.util.DefinitionsUtil; +import com.zmops.iot.util.LocalDateTimeUtils; +import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.alarm.service.AlarmService; import com.zmops.iot.web.alarm.service.MessageService; import com.zmops.iot.web.event.EventProcess; +import com.zmops.iot.web.event.dto.EventDataDto; +import com.zmops.iot.web.sys.dto.UserGroupDto; +import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.springframework.util.CollectionUtils; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -31,11 +44,21 @@ public class AlarmEventProcess implements EventProcess { @Autowired AlarmService alarmService; + + @Autowired + NoticeService noticeService; + @Override - public void process(String triggerId,String triggerName) { - log.debug("--------alarm event----------{}" , triggerId); + public void process(EventDataDto eventData) { + String triggerId = eventData.getObjectid(); + String triggerName = eventData.getName(); + + log.debug("--------alarm event----------{}", triggerId); List list = new QProductEventRelation().zbxId.eq(triggerId).findList(); + if(ToolUtil.isEmpty(list)){ + return; + } Map params = new ConcurrentHashMap<>(2); List deviceIds = list.parallelStream().map(ProductEventRelation::getRelationId).collect(Collectors.toList()); params.put("hostname", deviceIds); @@ -45,6 +68,51 @@ public void process(String triggerId,String triggerName) { messageService.push(buildMessage(params, userIds)); alarmService.alarm(params); + + //发送消息 + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(Long.parseLong(triggerName)).findOne(); + Map macros = createMacroMap(triggerId,eventData.getRecoveryValue(),eventData.getAcknowledged(),productEvent); + + String sql = "select user_group_id from sys_usrgrp_devicegrp where device_group_id in (select device_group_id from devices_groups where device_id in (:deviceIds))"; + List userGroups = DB.findNative(UserGroupDto.class, sql).setParameter("deviceIds", deviceIds).findList(); + QSysUser qSysUser = new QSysUser(); + + if (ToolUtil.isNotEmpty(userGroups)) { + qSysUser.userGroupId.in(userGroups.parallelStream().map(UserGroupDto::getUserGroupId).collect(Collectors.toList())); + } + List sysUserList = qSysUser.findList(); + List noticeRecords = new ArrayList<>(); + sysUserList.forEach(sysUser -> { + Map notice = noticeService.notice(sysUser, macros,triggerId); + for (Map.Entry en : notice.entrySet()) { + noticeRecords.add(NoticeRecord.builder() + .userId(sysUser.getUserId()) + .problemId(triggerId) + .noticeType(en.getKey()) + .noticeStatus(en.getValue().getStatus().name()) + .noticeMsg(en.getValue().getMsg()) + .creatTime(LocalDateTime.now()) + .alarmInfo(en.getValue().getAlarmInfo()) + .receiveAccount(en.getValue().getReceiveAccount()) + .build()); + } + }); + DB.saveAll(noticeRecords); + } + + private Map createMacroMap(String triggerId,String value,String acknowledged,ProductEvent productEvent) { + boolean isnew = "1".equals(value); + Map macroMap = new HashMap(); + macroMap.put("${time}", LocalDateTimeUtils.formatTime(LocalDateTime.now())); + + macroMap.put("${level}", DefinitionsUtil.getNameByVal("EVENT_LEVEL", productEvent.getEventLevel())); + macroMap.put("${severity}", productEvent.getEventLevel()); + macroMap.put("${metricName}", productEvent.getEventRuleName()); + macroMap.put("${context}", productEvent.getEventRuleName()); + macroMap.put("${alarmStatus}", isnew ? "告警触发" : "撤销告警"); + macroMap.put("${confirmStatus}", "1".equals(acknowledged) ? "已确认" : "未确认"); + macroMap.put("${problemId}", triggerId); + return macroMap; } private MessageBody buildMessage(Map alarmInfo, List userIds) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java index 1868b062..b95fb37b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java @@ -6,6 +6,7 @@ import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.event.EventProcess; +import com.zmops.iot.web.event.dto.EventDataDto; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -20,10 +21,10 @@ public class OfflineEventProcess implements EventProcess{ @Override - public void process(String triggerId,String triggerName) { + public void process(EventDataDto eventData) { log.debug("update device offline status…………"); - ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().zbxId.eq(triggerId).findOne(); + ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().zbxId.eq(eventData.getObjectid()).findOne(); if (null == relation) { return; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OnlineEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OnlineEventProcess.java index a5bc0de1..19e9a253 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OnlineEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OnlineEventProcess.java @@ -6,6 +6,7 @@ import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.event.EventProcess; +import com.zmops.iot.web.event.dto.EventDataDto; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -20,10 +21,10 @@ public class OnlineEventProcess implements EventProcess { @Override - public void process(String triggerId,String triggerName) { + public void process(EventDataDto eventData) { log.debug("update device online status…………"); - ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().zbxIdRecovery.eq(triggerId).findOne(); + ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().zbxIdRecovery.eq(eventData.getObjectid()).findOne(); if (null == relation) { return; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java index 3ebf6406..71038b36 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java @@ -16,6 +16,7 @@ import com.zmops.iot.web.device.service.work.DeviceServiceLogWorker; import com.zmops.iot.web.device.service.work.ScenesLogWorker; import com.zmops.iot.web.event.EventProcess; +import com.zmops.iot.web.event.dto.EventDataDto; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -40,11 +41,11 @@ public class ServiceEventProcess implements EventProcess { ScenesLogWorker scenesLogWorker; @Override - public void process(String triggerId, String triggerName) { - log.debug("--------service event----------{}", triggerId); + public void process(EventDataDto eventData) { + log.debug("--------service event----------{}", eventData.getObjectid()); Map alarmInfo = new ConcurrentHashMap<>(3); - List productEventRelationList = new QProductEventRelation().zbxId.eq(triggerId).findList(); + List productEventRelationList = new QProductEventRelation().zbxId.eq(eventData.getObjectid()).findList(); if (ToolUtil.isEmpty(productEventRelationList)) { return; } From 4854725bcdcbd103633f24b4c178e6c2e0218f8b Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 28 Oct 2021 16:26:17 +0800 Subject: [PATCH 580/763] [fix]: fix product attribute event --- .../domain/product/ProductAttributeEvent.java | 8 ++ .../ProductAttributeEventController.java | 36 ++++++- .../iot/web/product/dto/ProductAttrEvent.java | 94 ------------------- .../service/ProductAttributeEventService.java | 23 +++-- .../work/AsyncAttrEventZbxIdWorker.java | 6 +- .../work/SaveProdAttrEventTriggerWorker.java | 6 +- .../service/work/SaveProdAttrEventWorker.java | 6 +- .../work/UpdateAttributeEventWorker.java | 6 +- 8 files changed, 62 insertions(+), 123 deletions(-) delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrEvent.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttributeEvent.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttributeEvent.java index 046a043b..25cb8841 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttributeEvent.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttributeEvent.java @@ -41,4 +41,12 @@ public class ProductAttributeEvent extends BaseEntity { private Long templateId;//继承的ID + private String source; // 来源 + + private Integer delay; + + private String unit; + + private String valuemapid; + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java index 1bc3f90e..3f65d972 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java @@ -3,13 +3,16 @@ import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSON; import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.product.ProductAttribute; +import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.domain.product.query.QProductAttributeEvent; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.iot.web.product.dto.ProductAttrDto; -import com.zmops.iot.web.product.dto.ProductAttrEvent; import com.zmops.iot.web.product.dto.param.ProductAttrParam; import com.zmops.iot.web.product.service.ProductAttributeEventService; import lombok.Data; @@ -30,10 +33,11 @@ @RequestMapping("/product/attribute/event") public class ProductAttributeEventController { - @Autowired private ProductAttributeEventService productAttributeEventService; + //依赖属性类型 + private static final String ATTR_SOURCE_DEPEND = "18"; /** * 产品属性事件 分页列表 @@ -71,12 +75,23 @@ public ResponseData detail(@RequestParam(value = "attrId") Long attrId) { * @return ResponseData */ @RequestMapping("/create") - public ResponseData prodModelAttributeCreate(@RequestBody @Validated(BaseEntity.Create.class) ProductAttrEvent productAttr) { + public ResponseData prodModelAttributeCreate(@RequestBody @Validated(BaseEntity.Create.class) ProductAttr productAttr) { int i = new QProductAttribute().productId.eq(productAttr.getProductId()).key.eq(productAttr.getKey()).findCount(); if (i > 0) { throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_EXISTS); } + if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { + if (productAttr.getDepAttrId() == null) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NULL); + } + ProductAttributeEvent productAttributeEvent = new QProductAttributeEvent().attrId.eq(productAttr.getDepAttrId()).findOne(); + if (null == productAttributeEvent) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); + } + productAttr.setMasterItemId(productAttributeEvent.getZbxId()); + } + Long attrId = IdUtil.getSnowflake().nextId(); productAttr.setAttrId(attrId); @@ -94,13 +109,24 @@ public ResponseData prodModelAttributeCreate(@RequestBody @Validated(BaseEntity. * @return ResponseData */ @RequestMapping("/update") - public ResponseData prodModelAttributeUpdate(@RequestBody @Validated(BaseEntity.Update.class) ProductAttrEvent productAttr) { + public ResponseData prodModelAttributeUpdate(@RequestBody @Validated(BaseEntity.Update.class) ProductAttr productAttr) { int i = new QProductAttribute().productId.eq(productAttr.getProductId()).key.eq(productAttr.getKey()) .attrId.ne(productAttr.getAttrId()).findCount(); if (i > 0) { throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_EXISTS); } + if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { + if (productAttr.getDepAttrId() == null) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NULL); + } + ProductAttributeEvent productAttributeEvent = new QProductAttributeEvent().attrId.eq(productAttr.getDepAttrId()).findOne(); + if (null == productAttributeEvent) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); + } + productAttr.setMasterItemId(productAttributeEvent.getZbxId()); + } + return ResponseData.success(productAttributeEventService.updateTrapperItem(productAttr)); } @@ -110,7 +136,7 @@ public ResponseData prodModelAttributeUpdate(@RequestBody @Validated(BaseEntity. * @return ResponseData */ @RequestMapping("/delete") - public ResponseData prodModelAttributeDelete(@RequestBody @Validated(BaseEntity.Delete.class) ProductAttrEvent productAttr) { + public ResponseData prodModelAttributeDelete(@RequestBody @Validated(BaseEntity.Delete.class) ProductAttr productAttr) { productAttributeEventService.deleteTrapperItem(productAttr); return ResponseData.success(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrEvent.java deleted file mode 100644 index 216dfdc7..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrEvent.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.zmops.iot.web.product.dto; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.zmops.iot.domain.BaseEntity; -import lombok.Data; -import lombok.Getter; -import lombok.Setter; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; -import java.util.List; - -/** - * @author nantian created at 2021/8/5 13:53 - *

- * dto for product attribute - */ - -@Data -public class ProductAttrEvent { - - @NotNull(groups = BaseEntity.Update.class) - private Long attrId; - - //属性名 非 item name - @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) - private String attrName; - - @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) - private String key; - - private String units; - - private Byte eventLevel = 1; - - private String remark; - - @JsonIgnore - private String zbxId; - - @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) - private String productId; - - @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) - private String valueType; - - private String valuemapid; - - private List tags; - - //预处理 - private List processStepList; - - @NotEmpty(groups = BaseEntity.Delete.class) - private List attrIds; - - LocalDateTime createTime; - LocalDateTime updateTime; - Long createUser; - Long updateUser; - - /** - * 预处理步骤 - */ - public static class ProcessingStep { - - @Getter - @Setter - private String type; - - @Setter - private String[] params; - - @Getter - @Setter - private String errorHandler; - - @Getter - @Setter - private String errorHandlerParams; - - public String getParams() { - StringBuilder paramStr = new StringBuilder(); - if (null != params && params.length > 0) { - for (String param : params) { - paramStr.append(param).append("\\\\n"); - } - return paramStr.substring(0, paramStr.length() - 3); - } - return ""; - } - } -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java index 6abb5c51..96953b09 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -16,7 +16,6 @@ import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.iot.web.product.dto.ProductAttrDto; -import com.zmops.iot.web.product.dto.ProductAttrEvent; import com.zmops.iot.web.product.dto.ProductTag; import com.zmops.iot.web.product.dto.param.ProductAttrParam; import com.zmops.iot.web.product.service.work.AsyncAttrEventZbxIdWorker; @@ -167,19 +166,19 @@ private List formatProcessStep(String preprocessing) * * @param productAttr 产品属性DTO */ - public void createProductAttr(ProductAttrEvent productAttr, String zbxId) { + public void createProductAttr(ProductAttr productAttr, String zbxId) { ProductAttributeEvent productAttributeEvent = new ProductAttributeEvent(); buildProdAttribute(productAttributeEvent, productAttr); productAttributeEvent.setZbxId(zbxId); productAttributeEvent.save(); - WorkerWrapper saveProdAttrEventTriggerWork = WorkerWrapper.builder() + WorkerWrapper saveProdAttrEventTriggerWork = WorkerWrapper.builder() .worker(saveProdAttrEventTriggerWorker).param(productAttr).build(); - WorkerWrapper asyncAttrEventZbxIdWork = WorkerWrapper.builder() + WorkerWrapper asyncAttrEventZbxIdWork = WorkerWrapper.builder() .worker(asyncAttrEventZbxIdWorker).param(productAttr).build(); - WorkerWrapper saveProdAttrEventWork = WorkerWrapper.builder() + WorkerWrapper saveProdAttrEventWork = WorkerWrapper.builder() .worker(saveProdAttrEventWorker).param(productAttr).nextOf(asyncAttrEventZbxIdWork).build(); try { @@ -190,7 +189,7 @@ public void createProductAttr(ProductAttrEvent productAttr, String zbxId) { } - private ProductAttributeEvent buildProdAttribute(ProductAttributeEvent prodAttribute, ProductAttrEvent productAttr) { + private ProductAttributeEvent buildProdAttribute(ProductAttributeEvent prodAttribute, ProductAttr productAttr) { prodAttribute.setProductId(productAttr.getProductId()); prodAttribute.setName(productAttr.getAttrName()); prodAttribute.setKey(productAttr.getKey()); @@ -208,7 +207,7 @@ private ProductAttributeEvent buildProdAttribute(ProductAttributeEvent prodAttri * @param productAttr 属性 * @return String */ - public String createTrapperItem(ProductAttrEvent productAttr) { + public String createTrapperItem(ProductAttr productAttr) { String itemName = productAttr.getAttrId() + ""; String hostId = ""; @@ -239,7 +238,7 @@ public String createTrapperItem(ProductAttrEvent productAttr) { } return zbxItem.createTrapperItem(itemName, productAttr.getKey(), - hostId, "2", null, productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(), productAttr.getDepAttrId()+"", productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); } /** @@ -248,7 +247,7 @@ public String createTrapperItem(ProductAttrEvent productAttr) { * @param productAttr 属性 * @return String */ - public ProductAttrEvent updateTrapperItem(ProductAttrEvent productAttr) { + public ProductAttr updateTrapperItem(ProductAttr productAttr) { ProductAttributeEvent productAttributeEvent = new QProductAttributeEvent().attrId.eq(productAttr.getAttrId()).findOne(); buildProdAttribute(productAttributeEvent, productAttr); String hostId = ""; @@ -282,11 +281,11 @@ public ProductAttrEvent updateTrapperItem(ProductAttrEvent productAttr) { zbxItem.updateTrapperItem(productAttributeEvent.getZbxId(), productAttr.getAttrId() + "", productAttr.getKey(), - hostId, "2", null, productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(), productAttr.getDepAttrId()+"", productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); DB.update(productAttributeEvent); - WorkerWrapper updateProdAttrWork = WorkerWrapper.builder().worker(updateAttributeEventWorker).param(productAttr).build(); + WorkerWrapper updateProdAttrWork = WorkerWrapper.builder().worker(updateAttributeEventWorker).param(productAttr).build(); try { Async.work(100, updateProdAttrWork).awaitFinish(); @@ -303,7 +302,7 @@ public ProductAttrEvent updateTrapperItem(ProductAttrEvent productAttr) { * @param productAttr 属性 * @return String */ - public void deleteTrapperItem(ProductAttrEvent productAttr) { + public void deleteTrapperItem(ProductAttr productAttr) { List zbxIds = new QProductAttributeEvent().select(QProductAttributeEvent.alias().zbxId).attrId.in(productAttr.getAttrIds()).findSingleAttributeList(); //删除zbx item diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java index 33c7102d..531bc113 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java @@ -7,7 +7,7 @@ import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.domain.product.query.QProductAttributeEvent; import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.product.dto.ProductAttrEvent; +import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.service.ZbxItem; import io.ebean.DB; @@ -26,13 +26,13 @@ */ @Slf4j @Component -public class AsyncAttrEventZbxIdWorker implements IWorker { +public class AsyncAttrEventZbxIdWorker implements IWorker { @Autowired ZbxItem zbxItem; @Override - public Boolean action(ProductAttrEvent productAttr, Map> map) { + public Boolean action(ProductAttr productAttr, Map> map) { log.debug("AsyncAttrEventZbxIdWorker……"); Long attrId = productAttr.getAttrId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java index 3d4312e4..f71af462 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java @@ -4,7 +4,7 @@ import com.alibaba.fastjson.JSON; import com.zmops.iot.async.callback.IWorker; import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.web.product.dto.ProductAttrEvent; +import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.zeus.driver.service.ZbxTrigger; import lombok.Data; import lombok.extern.slf4j.Slf4j; @@ -21,14 +21,14 @@ */ @Slf4j @Component -public class SaveProdAttrEventTriggerWorker implements IWorker { +public class SaveProdAttrEventTriggerWorker implements IWorker { @Autowired private ZbxTrigger zbxTrigger; private static final String EVENT_TAG_NAME = "__event__"; @Override - public Boolean action(ProductAttrEvent productAttr, Map> map) { + public Boolean action(ProductAttr productAttr, Map> map) { log.debug("SaveProdAttrEventTriggerWorker…………"); String prodId = productAttr.getProductId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java index fed0932c..59c20c26 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java @@ -7,7 +7,7 @@ import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.product.dto.ProductAttrEvent; +import com.zmops.iot.web.product.dto.ProductAttr; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -23,11 +23,11 @@ */ @Slf4j @Component -public class SaveProdAttrEventWorker implements IWorker { +public class SaveProdAttrEventWorker implements IWorker { @Override - public Boolean action(ProductAttrEvent productAttr, Map> map) { + public Boolean action(ProductAttr productAttr, Map> map) { log.debug("SaveProdAttrEventTriggerWorker…………"); String prodId = productAttr.getProductId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java index 9f643e44..c894e2bf 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java @@ -5,7 +5,7 @@ import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.domain.product.query.QProductAttributeEvent; -import com.zmops.iot.web.product.dto.ProductAttrEvent; +import com.zmops.iot.web.product.dto.ProductAttr; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -20,11 +20,11 @@ */ @Slf4j @Component -public class UpdateAttributeEventWorker implements IWorker { +public class UpdateAttributeEventWorker implements IWorker { @Override - public Boolean action(ProductAttrEvent productAttr, Map> map) { + public Boolean action(ProductAttr productAttr, Map> map) { log.debug("UpdateAttributeEventWorker…………"); Long attrId = productAttr.getAttrId(); From 964c5048a3cf23919763b8294f1f7169a3fd86e5 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 29 Oct 2021 10:02:26 +0800 Subject: [PATCH 581/763] [fix]: fix event log --- .../iot/web/alarm/service/AlarmService.java | 18 +----------------- .../web/device/service/DeviceLogService.java | 9 ++++----- .../work/SaveProdAttrEventTriggerWorker.java | 2 +- 3 files changed, 6 insertions(+), 23 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 1c8d48e1..8b3094d2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -206,29 +206,13 @@ public List getEventList(AlarmParam alarmParam) { if (ToolUtil.isEmpty(problemList)) { return Collections.emptyList(); } - List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Objects::toString).collect(Collectors.toList()); - String sql = "select d.event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id," + - "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id"; - if (ToolUtil.isNotEmpty(alarmParam.getName())) { - sql += " where d.event_rule_name like :eventRuleName"; - } - DtoQuery dtoQuery = DB.findDto(ProductEventRuleDto.class, sql) - .setParameter("zbxIds", triggerIds); - if (ToolUtil.isNotEmpty(alarmParam.getName())) { - dtoQuery.setParameter("eventRuleName", "%" + alarmParam.getName() + "%"); - } - List ruleList = dtoQuery.findList(); - Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); List alarmDtoList = new ArrayList<>(); problemList.forEach(zbxProblemInfo -> { - if (null == ruleMap.get(zbxProblemInfo.getObjectid())) { - return; - } AlarmDto alarmDto = new AlarmDto(); BeanUtils.copyProperties(zbxProblemInfo, alarmDto); alarmDto.setRClock(zbxProblemInfo.getR_clock()); - alarmDto.setName(ruleMap.get(zbxProblemInfo.getObjectid())); + alarmDto.setName(zbxProblemInfo.getName()); alarmDtoList.add(alarmDto); }); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java index 2f63f52f..3978bac9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java @@ -58,7 +58,7 @@ public List list(String deviceId, String logType, Long timeFrom, L List alarmList = alarmService.getEventList(alarmParam); if (ToolUtil.isNotEmpty(alarmList)) { alarmList.forEach(alarm -> { - deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_ALARM).content(alarm.getName()) + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_EVENT).content(alarm.getName()) .triggerTime(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(alarm.getClock()), "yyyy-MM-dd HH:ss:mm")) .status("0".equals(alarm.getRClock()) ? "未解决" : "已解决").build()); }); @@ -99,7 +99,7 @@ public Pager getLogByPage(String deviceId, String logType, Long ti } else if (ToolUtil.isNotEmpty(logType) && LOG_TYPE_SCENES.equals(logType)) { - deviceLogDtoList = getScenesLog(deviceId, timeFrom, timeTill, content); + deviceLogDtoList = getScenesLog(timeFrom, timeTill, content); } else { @@ -161,7 +161,7 @@ private List getEventLog(String deviceId, Long timeFrom, Long time List alarmList = alarmService.getEventList(alarmParam); if (ToolUtil.isNotEmpty(alarmList)) { alarmList.forEach(alarm -> { - deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_ALARM).content(alarm.getName()) + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_EVENT).content(alarm.getName()) .triggerTime(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(alarm.getClock()), "yyyy-MM-dd HH:ss:mm")) .status("0".equals(alarm.getRClock()) ? "未解决" : "已解决").build()); }); @@ -208,13 +208,12 @@ private List getServiceLog(String deviceId, Long timeFrom, Long ti /** * 场景日志 * - * @param deviceId * @param timeFrom * @param timeTill * @param content * @return */ - private List getScenesLog(String deviceId, Long timeFrom, Long timeTill, String content) { + private List getScenesLog(Long timeFrom, Long timeTill, String content) { List deviceLogDtoList = new ArrayList<>(); QScenesTriggerRecord query = new QScenesTriggerRecord(); if (ToolUtil.isNotEmpty(content)) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java index f71af462..aa67ab81 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java @@ -39,7 +39,7 @@ public Boolean action(ProductAttr productAttr, Map> expression.append(productAttr.getKey()); expression.append(",#1"); expression.append(") >0 "); - String res = zbxTrigger.triggerCreate(productAttr.getProductId(), expression.toString(), productAttr.getEventLevel()); + String res = zbxTrigger.executeTriggerCreate(productAttr.getAttrName(), expression.toString(), productAttr.getEventLevel()); String[] triggerids = JSON.parseObject(res, TriggerIds.class).getTriggerids(); Map tags = new ConcurrentHashMap<>(1); From 8a546e82746875f5ebd18f94889a77ccee644925 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 29 Oct 2021 10:46:38 +0800 Subject: [PATCH 582/763] [fix]: fix bug --- .../iot/web/product/service/ProductAttributeEventService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java index 96953b09..8a751367 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -238,7 +238,7 @@ public String createTrapperItem(ProductAttr productAttr) { } return zbxItem.createTrapperItem(itemName, productAttr.getKey(), - hostId, productAttr.getSource(), productAttr.getDepAttrId()+"", productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(), productAttr.getMasterItemId(), productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); } /** @@ -281,7 +281,7 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { zbxItem.updateTrapperItem(productAttributeEvent.getZbxId(), productAttr.getAttrId() + "", productAttr.getKey(), - hostId, productAttr.getSource(), productAttr.getDepAttrId()+"", productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(), productAttr.getMasterItemId(), productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); DB.update(productAttributeEvent); From ba1afb8bac58b17f5f374746926b856d20b95414 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 29 Oct 2021 11:20:51 +0800 Subject: [PATCH 583/763] [fix]: fix product attribute event field --- .../com/zmops/iot/domain/product/ProductAttributeEvent.java | 2 ++ .../web/product/service/ProductAttributeEventService.java | 5 +++++ .../zmops/iot/web/product/service/ProductModelService.java | 2 ++ 3 files changed, 9 insertions(+) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttributeEvent.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttributeEvent.java index 25cb8841..2ecfc4aa 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttributeEvent.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttributeEvent.java @@ -49,4 +49,6 @@ public class ProductAttributeEvent extends BaseEntity { private String valuemapid; + private Long depAttrId; + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java index 8a751367..b2ae10af 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -198,6 +198,11 @@ private ProductAttributeEvent buildProdAttribute(ProductAttributeEvent prodAttri prodAttribute.setValueType(productAttr.getValueType()); prodAttribute.setAttrId(productAttr.getAttrId()); prodAttribute.setEventLevel(productAttr.getEventLevel()); + prodAttribute.setSource(productAttr.getSource()); + prodAttribute.setDepAttrId(productAttr.getDepAttrId()); + prodAttribute.setValuemapid(productAttr.getValuemapid()); + prodAttribute.setUnit(productAttr.getUnit()); + return prodAttribute; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index 3c787250..34388db3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -197,6 +197,8 @@ private ProductAttribute buildProdAttribute(ProductAttribute prodAttribute, Prod prodAttribute.setAttrId(productAttr.getAttrId()); prodAttribute.setDepAttrId(productAttr.getDepAttrId()); prodAttribute.setValuemapid(productAttr.getValuemapid()); + prodAttribute.setUnit(productAttr.getUnit()); + return prodAttribute; } From 0b7a888fc516b4e7f084857b2d5f26dc4bcdd142 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 29 Oct 2021 20:43:10 +0800 Subject: [PATCH 584/763] [feat]: tdengine fix --- .../analysis/manual/history/StrHistory.java | 43 +++++++++++++++++++ .../analysis/manual/history/TextHistory.java | 43 +++++++++++++++++++ .../core/servlet/DataTransferHandler.java | 9 +++- .../tdengine/TDEngineDatabaseInstaller.java | 13 ++++-- .../tdengine/dao/TDEngineSqlExecutor.java | 21 +++++++++ .../server/transfer/sender/SenderManager.java | 6 +++ .../device/service/work/SaveDeviceWorker.java | 2 +- 7 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/StrHistory.java create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/TextHistory.java diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/StrHistory.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/StrHistory.java new file mode 100644 index 00000000..3a6d6498 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/StrHistory.java @@ -0,0 +1,43 @@ +package com.zmops.zeus.iot.server.core.analysis.manual.history; + +import com.zmops.zeus.iot.server.core.analysis.Stream; +import com.zmops.zeus.iot.server.core.analysis.record.Record; +import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; +import java.util.Map; + +/** + * @author nantian created at 2021/9/6 17:07 + */ +@Getter +@Setter +@Stream(name = "history_str", processor = RecordStreamProcessor.class) +public class StrHistory extends Record { + + private Long clock; + + private Long ns; + + private String value; // 浮点数 + + private String deviceId; // host + + private Map itemTags; + + private List hostGroups; + + @Override + public Integer itemid() { + return getItemid(); + } + + @Override + public void setValue(String deviceId, String value, Long clock) { + this.deviceId = deviceId; + this.value = value; + this.clock = clock; + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/TextHistory.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/TextHistory.java new file mode 100644 index 00000000..06d6e1c9 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/TextHistory.java @@ -0,0 +1,43 @@ +package com.zmops.zeus.iot.server.core.analysis.manual.history; + +import com.zmops.zeus.iot.server.core.analysis.Stream; +import com.zmops.zeus.iot.server.core.analysis.record.Record; +import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; +import java.util.Map; + +/** + * @author nantian created at 2021/9/6 17:07 + */ +@Getter +@Setter +@Stream(name = "history_text", processor = RecordStreamProcessor.class) +public class TextHistory extends Record { + + private Long clock; + + private Long ns; + + private String value; // 浮点数 + + private String deviceId; // host + + private Map itemTags; + + private List hostGroups; + + @Override + public Integer itemid() { + return getItemid(); + } + + @Override + public void setValue(String deviceId, String value, Long clock) { + this.deviceId = deviceId; + this.value = value; + this.clock = clock; + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java index 1bcf301b..5279c7b2 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java @@ -3,6 +3,8 @@ import com.google.gson.Gson; import com.google.gson.JsonElement; import com.zmops.zeus.iot.server.core.analysis.manual.history.History; +import com.zmops.zeus.iot.server.core.analysis.manual.history.StrHistory; +import com.zmops.zeus.iot.server.core.analysis.manual.history.TextHistory; import com.zmops.zeus.iot.server.core.analysis.manual.history.UIntHistory; import com.zmops.zeus.iot.server.core.analysis.record.Record; import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; @@ -60,8 +62,13 @@ private void insert(String itemRecord) { if (itemValue.getType() == 3) { //uint record = new UIntHistory(); - } else { + } else if (itemValue.getType() == 0) { //float record = new History(); + } else if (itemValue.getType() == 4) { //text + record = new TextHistory(); + } else { + record = new StrHistory(); + } record.setItemid(itemValue.itemid); diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java index 091cdcfa..7658507c 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java @@ -18,11 +18,14 @@ public class TDEngineDatabaseInstaller { private final ModuleManager moduleManager; private final TDEngineStorageConfig config; - private static final String CREATE_ZEUS_STABLE_HISTORY = "create stable if not exists history(clock TIMESTAMP, value DOUBLE) tags (deviceid BINARY(20), itemid BINARY(20))"; - private static final String CREATE_ZEUS_STABLE_HISTORY_UINT = "create stable if not exists history_uint(clock TIMESTAMP, value BIGINT) tags (deviceid BINARY(20), itemid BINARY(20))"; + private static final String CREATE_ZEUS_STABLE_HISTORY = "create stable if not exists history(clock TIMESTAMP, value DOUBLE) tags (deviceid BINARY(64), itemid BINARY(20))"; + private static final String CREATE_ZEUS_STABLE_HISTORY_UINT = "create stable if not exists history_uint(clock TIMESTAMP, value BIGINT) tags (deviceid BINARY(64), itemid BINARY(20))"; + private static final String CREATE_ZEUS_STABLE_HISTORY_TEXT = "create stable if not exists history_text(clock TIMESTAMP, value NCHAR(255)) tags (deviceid BINARY(64), itemid BINARY(20))"; + private static final String CREATE_ZEUS_STABLE_HISTORY_STR = "create stable if not exists history_str(clock TIMESTAMP, value NCHAR(255)) tags (deviceid BINARY(64), itemid BINARY(20))"; - private static final String CREATE_ZEUS_STABLE_TRENDS = "create stable if not exists trends(clock TIMESTAMP, value_min DOUBLE, value_avg DOUBLE, value_max DOUBLE) tags (hostid BINARY(20), itemid BINARY(20))"; - private static final String CREATE_ZEUS_STABLE_TRENDS_UINT = "create stable if not exists trends_uint(clock TIMESTAMP, value_min BIGINT, value_avg BIGINT, value_max BIGINT) tags (hostid BINARY(20), itemid BINARY(20))"; + + private static final String CREATE_ZEUS_STABLE_TRENDS = "create stable if not exists trends(clock TIMESTAMP, value_min DOUBLE, value_avg DOUBLE, value_max DOUBLE) tags (hostid BINARY(64), itemid BINARY(20))"; + private static final String CREATE_ZEUS_STABLE_TRENDS_UINT = "create stable if not exists trends_uint(clock TIMESTAMP, value_min BIGINT, value_avg BIGINT, value_max BIGINT) tags (hostid BINARY(64), itemid BINARY(20))"; public TDEngineDatabaseInstaller(Client client, ModuleManager moduleManager, TDEngineStorageConfig config) { this.config = config; @@ -36,6 +39,8 @@ protected void createDatabase() throws StorageException { jdbcHikariCPClient.execute(connection, CREATE_ZEUS_STABLE_HISTORY); jdbcHikariCPClient.execute(connection, CREATE_ZEUS_STABLE_HISTORY_UINT); + jdbcHikariCPClient.execute(connection, CREATE_ZEUS_STABLE_HISTORY_TEXT); + jdbcHikariCPClient.execute(connection, CREATE_ZEUS_STABLE_HISTORY_STR); jdbcHikariCPClient.execute(connection, CREATE_ZEUS_STABLE_TRENDS); jdbcHikariCPClient.execute(connection, CREATE_ZEUS_STABLE_TRENDS_UINT); diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java index 0efa9263..7f46d118 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java @@ -1,6 +1,8 @@ package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine.dao; import com.zmops.zeus.iot.server.core.analysis.manual.history.History; +import com.zmops.zeus.iot.server.core.analysis.manual.history.StrHistory; +import com.zmops.zeus.iot.server.core.analysis.manual.history.TextHistory; import com.zmops.zeus.iot.server.core.analysis.manual.history.UIntHistory; import com.zmops.zeus.iot.server.core.storage.StorageData; import com.zmops.zeus.iot.server.storage.plugin.jdbc.SQLBuilder; @@ -38,6 +40,25 @@ protected SQLExecutor getInsertExecutor(String modelName .append(",").append(uihistory.getItemid() + " )") .append(" VALUES (") .append(uihistory.getClock() + "").append(",").append(uihistory.getValue()).append(")"); + } else if (modelName.equals("history_text")) { + + TextHistory textHistory = (TextHistory) metrics; + String value = textHistory.getValue().replaceAll(",", "\\,"); + + sqlBuilder.append("history_text (deviceid, itemid) TAGS") + .append(" ('").append(textHistory.getDeviceId()).append("'") + .append(",").append(textHistory.getItemid() + " )") + .append(" VALUES (") + .append(textHistory.getClock() + "").append(",'").append(value).append("')"); + } else if (modelName.equals("history_str")) { + + StrHistory strHistory = (StrHistory) metrics; + String value = strHistory.getValue().replaceAll(",", "\\,"); + sqlBuilder.append("history_str (deviceid, itemid) TAGS") + .append(" ('").append(strHistory.getDeviceId()).append("'") + .append(",").append(strHistory.getItemid() + " )") + .append(" VALUES (") + .append(strHistory.getClock() + "").append(",'").append(value).append("')"); } List param = new ArrayList<>(); diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java index 47cb86c1..c4271176 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java @@ -2,6 +2,8 @@ import com.alibaba.fastjson.JSON; import com.zmops.zeus.iot.server.core.analysis.manual.history.History; +import com.zmops.zeus.iot.server.core.analysis.manual.history.StrHistory; +import com.zmops.zeus.iot.server.core.analysis.manual.history.TextHistory; import com.zmops.zeus.iot.server.core.analysis.manual.history.UIntHistory; import com.zmops.zeus.iot.server.core.analysis.record.Record; import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; @@ -55,6 +57,10 @@ public void sendBatch(String jobId, String bid, String tid, List bodyLis record = new UIntHistory(); } else if (itemValue.getType() == 0) { record = new History(); + } else if (itemValue.getType() == 4) { //text + record = new TextHistory(); + } else if (itemValue.getType() == 1) { + record = new StrHistory(); } else { return; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java index 142058cc..51abbb7c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java @@ -33,7 +33,7 @@ public Device action(DeviceDto deviceDto, Map> allWr DB.update(device); } else { device.setStatus(CommonStatus.ENABLE.getCode()); - DB.save(device); + DB.insert(device); } log.debug("step 1:SaveDeviceWorker----DEVICEID:{} complete",deviceDto.getDeviceId()); return device; From aeff7fc38ef5cac0d214f953ed1b25ab6d030665 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 30 Oct 2021 10:22:36 +0800 Subject: [PATCH 585/763] [fi]: fix device add --- .../zmops/iot/web/device/service/work/SaveZbxHostWorker.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java index 01f20a7c..780f085c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java @@ -35,8 +35,7 @@ public class SaveZbxHostWorker implements IWorker { public String action(DeviceDto deviceDto, Map> map) { log.debug("step 5:SaveZbxHostWorker----DEVICEID:{}…………",deviceDto.getDeviceId()); //设备ID 作为zbx HOST name - Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); - String host = device.getDeviceId() + ""; + String host = deviceDto.getDeviceId(); //取出 设备对应的 zbx主机组ID,模板ID List hostGrpIds = new QDeviceGroup().select(QDeviceGroup.alias().zbxId).deviceGroupId.in(deviceDto.getDeviceGroupIds()).findSingleAttributeList(); From 5bdd6f9c2b3381e266bf7686def0a80c21c860fd Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 30 Oct 2021 16:38:59 +0800 Subject: [PATCH 586/763] [fix]: fix event log --- .../iot/domain/device/EventTriggerRecord.java | 27 +++++++++ .../domain/device/ScenesTriggerRecord.java | 1 - .../iot/web/alarm/service/AlarmService.java | 39 ------------ .../iot/web/analyse/service/HomeService.java | 57 ++++++++---------- .../web/device/service/DeviceLogService.java | 53 ++++++++++------- .../event/service/IncidentEventProcess.java | 59 +++++++++++++++++++ .../work/SaveProdAttrEventTriggerWorker.java | 4 +- 7 files changed, 145 insertions(+), 95 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/device/EventTriggerRecord.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/EventTriggerRecord.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/EventTriggerRecord.java new file mode 100644 index 00000000..d550ceee --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/EventTriggerRecord.java @@ -0,0 +1,27 @@ +package com.zmops.iot.domain.device; + +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.time.LocalDateTime; + +/** + * @author yefei + **/ +@Data +@Table(name = "service_execute_record") +@Entity +public class EventTriggerRecord { + @Id + private Long id; + + private LocalDateTime createTime; + + private String eventName; + + private String eventValue; + + private String deviceId; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/ScenesTriggerRecord.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/ScenesTriggerRecord.java index 86b60f77..113750af 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/ScenesTriggerRecord.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/ScenesTriggerRecord.java @@ -23,5 +23,4 @@ public class ScenesTriggerRecord { private Long ruleId; - private Long tenantId; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 8b3094d2..ebbf5829 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -199,45 +199,6 @@ public List getZbxAlarm(AlarmParam alarmParam) { return JSONObject.parseArray(problem, ZbxProblemInfo.class); } - - public List getEventList(AlarmParam alarmParam) { -// Assert.state(ToolUtil.isNotEmpty(alarmParam.getDeviceId()), "设备ID不能为空"); - List problemList = getEventProblem(alarmParam); - if (ToolUtil.isEmpty(problemList)) { - return Collections.emptyList(); - } - - List alarmDtoList = new ArrayList<>(); - problemList.forEach(zbxProblemInfo -> { - AlarmDto alarmDto = new AlarmDto(); - BeanUtils.copyProperties(zbxProblemInfo, alarmDto); - alarmDto.setRClock(zbxProblemInfo.getR_clock()); - alarmDto.setName(zbxProblemInfo.getName()); - alarmDtoList.add(alarmDto); - }); - - return alarmDtoList; - } - - public List getEventProblem(AlarmParam alarmParam) { - String hostId = null; - List deviceIds; - if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { - deviceIds = Collections.singletonList(alarmParam.getDeviceId()); - } else { - deviceIds = deviceService.getDeviceIds(); - } - - List zbxIds = new QDevice().select(QDevice.alias().zbxId).deviceId.in(deviceIds).zbxId.isNotNull().findSingleAttributeList(); - if (ToolUtil.isEmpty(zbxIds)) { - return Collections.EMPTY_LIST; - } - hostId = zbxIds.toString(); - //从zbx取告警记录 - String problem = zbxProblem.getEventProblem(hostId, alarmParam.getTimeFrom(), alarmParam.getTimeTill(), alarmParam.getRecent()); - return JSONObject.parseArray(problem, ZbxProblemInfo.class); - } - public void acknowledgement(String eventId) { zbxProblem.acknowledgement(eventId, 2); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index 5620312f..a0a725ab 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -5,9 +5,11 @@ import com.dtflys.forest.http.ForestResponse; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.DeviceOnlineReport; +import com.zmops.iot.domain.device.EventTriggerRecord; import com.zmops.iot.domain.device.ServiceExecuteRecord; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.device.query.QDeviceOnlineReport; +import com.zmops.iot.domain.device.query.QEventTriggerRecord; import com.zmops.iot.domain.device.query.QServiceExecuteRecord; import com.zmops.iot.domain.product.query.QProduct; import com.zmops.iot.enums.SeverityEnum; @@ -264,45 +266,34 @@ public Map getAlarmNum(long timeFrom, long timeTill) { * 事件数量统计 */ public Map getEventNum(long timeFrom, long timeTill) { - AlarmParam alarmParam = new AlarmParam(); - alarmParam.setTimeTill(timeTill); - alarmParam.setTimeFrom(timeFrom); - - List alarmList = alarmService.getEventProblem(alarmParam); - Map alarmMap = new ConcurrentHashMap<>(3); - - alarmMap.put("total", alarmList.size()); - Collections.reverse(alarmList); - //过滤出指定时间段内的告警 并顺序排序 - Map tmpMap = alarmList.parallelStream() - .filter(o -> !o.getSeverity().equals("0")).collect( - Collectors.groupingBy( - o -> LocalDateTimeUtils.convertTimeToString(Integer.parseInt(o.getClock()), "yyyy-MM-dd"), Collectors.counting())); - - List> trendsList = new ArrayList<>(); - Map initMap = initMap(timeFrom, timeTill); - - initMap.forEach((date, val) -> { - Map valMap = new ConcurrentHashMap<>(2); - valMap.put("date", date); + List list = new QEventTriggerRecord().createTime.ge(LocalDateTimeUtils.getLDTBySeconds((int) timeFrom)) + .createTime.lt(LocalDateTimeUtils.getLDTBySeconds((int) timeTill)).orderBy().createTime.asc().findList(); - valMap.put("val", Optional.ofNullable(tmpMap.get(date)).orElse(val)); - trendsList.add(valMap); - }); - trendsList.sort(Comparator.comparing(o -> o.get("date").toString())); - alarmMap.put("trends", trendsList); + Map eventMap = new HashMap<>(3); + if (ToolUtil.isNotEmpty(list)) { + eventMap.put("total", list.size()); + Map initMap = initMap(timeFrom, timeTill); + Map tmpMap = list.parallelStream().collect( + Collectors.groupingBy(o -> LocalDateTimeUtils.formatTime(o.getCreateTime(), "yyyy-MM-dd"), Collectors.counting())); + List> trendsList = new ArrayList<>(); + initMap.forEach((key, value) -> { + Map valMap = new ConcurrentHashMap<>(2); + valMap.put("date", key); + valMap.put("val", Optional.ofNullable(tmpMap.get(key)).orElse(value)); + trendsList.add(valMap); + }); + trendsList.sort(Comparator.comparing(o -> o.get("date").toString())); + eventMap.put("trends", trendsList); + } //今日开始时间 - Long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); - AlarmParam todayParam = new AlarmParam(); - todayParam.setTimeFrom(timeStart); + long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); + long todayNum = new QEventTriggerRecord().createTime.ge(LocalDateTimeUtils.getLDTBySeconds((int) timeStart)).findCount(); - List todayAlarmList = alarmService.getZbxAlarm(todayParam); - Long todayAlarmNum = todayAlarmList.parallelStream().count(); - alarmMap.put("today", todayAlarmNum); + eventMap.put("today", todayNum); - return alarmMap; + return eventMap; } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java index 3978bac9..d8a2bbac 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java @@ -1,7 +1,9 @@ package com.zmops.iot.web.device.service; +import com.zmops.iot.domain.device.EventTriggerRecord; import com.zmops.iot.domain.device.ScenesTriggerRecord; import com.zmops.iot.domain.device.ServiceExecuteRecord; +import com.zmops.iot.domain.device.query.QEventTriggerRecord; import com.zmops.iot.domain.device.query.QScenesTriggerRecord; import com.zmops.iot.domain.device.query.QServiceExecuteRecord; import com.zmops.iot.model.page.Pager; @@ -51,16 +53,19 @@ public List list(String deviceId, String logType, Long timeFrom, L } if (ToolUtil.isEmpty(logType) || (ToolUtil.isNotEmpty(logType) && LOG_TYPE_EVENT.equals(logType))) { - AlarmParam alarmParam = new AlarmParam(); - alarmParam.setDeviceId(deviceId); - alarmParam.setTimeFrom(timeFrom); - alarmParam.setTimeTill(timeTill); - List alarmList = alarmService.getEventList(alarmParam); - if (ToolUtil.isNotEmpty(alarmList)) { - alarmList.forEach(alarm -> { - deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_EVENT).content(alarm.getName()) - .triggerTime(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(alarm.getClock()), "yyyy-MM-dd HH:ss:mm")) - .status("0".equals(alarm.getRClock()) ? "未解决" : "已解决").build()); + QEventTriggerRecord query = new QEventTriggerRecord().deviceId.eq(deviceId); + if (null != timeFrom) { + query.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(timeFrom * 1000)); + } + if (null != timeTill) { + query.createTime.lt(LocalDateTimeUtils.getLDTByMilliSeconds(timeTill * 1000)); + } + List list = query.findList(); + if (ToolUtil.isNotEmpty(list)) { + list.forEach(service -> { + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_EVENT).content(service.getEventName()) + .triggerTime(LocalDateTimeUtils.formatTime(service.getCreateTime())) + .param(service.getEventName()).build()); }); } } @@ -152,18 +157,26 @@ private List getAlarmLog(String deviceId, Long timeFrom, Long time */ private List getEventLog(String deviceId, Long timeFrom, Long timeTill, String content) { List deviceLogDtoList = new ArrayList<>(); - AlarmParam alarmParam = new AlarmParam(); + QEventTriggerRecord query = new QEventTriggerRecord(); if (ToolUtil.isNotEmpty(deviceId)) { - alarmParam.setDeviceId(deviceId); + query.deviceId.eq(deviceId); } - alarmParam.setTimeFrom(timeFrom); - alarmParam.setTimeTill(timeTill); - List alarmList = alarmService.getEventList(alarmParam); - if (ToolUtil.isNotEmpty(alarmList)) { - alarmList.forEach(alarm -> { - deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_EVENT).content(alarm.getName()) - .triggerTime(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(alarm.getClock()), "yyyy-MM-dd HH:ss:mm")) - .status("0".equals(alarm.getRClock()) ? "未解决" : "已解决").build()); + if (ToolUtil.isNotEmpty(content)) { + query.eventName.contains(content); + } + if (null != timeFrom) { + query.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(timeFrom * 1000)); + } + if (null != timeTill) { + query.createTime.lt(LocalDateTimeUtils.getLDTByMilliSeconds(timeTill * 1000)); + } + query.orderBy().createTime.desc(); + List list = query.findList(); + if (ToolUtil.isNotEmpty(list)) { + list.forEach(service -> { + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_EVENT).content(service.getEventName()) + .triggerTime(LocalDateTimeUtils.formatTime(service.getCreateTime())) + .param(service.getEventValue()).build()); }); } return deviceLogDtoList; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java new file mode 100644 index 00000000..826b530e --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java @@ -0,0 +1,59 @@ +package com.zmops.iot.web.event.service; + +import com.zmops.iot.domain.device.EventTriggerRecord; +import com.zmops.iot.domain.product.ProductAttributeEvent; +import com.zmops.iot.domain.product.query.QProductAttributeEvent; +import com.zmops.iot.web.analyse.dto.LatestDto; +import com.zmops.iot.web.analyse.service.LatestService; +import com.zmops.iot.web.event.EventProcess; +import com.zmops.iot.web.event.dto.EventDataDto; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; + +/** + * @author yefei + **/ +@Slf4j +@Component +public class IncidentEventProcess implements EventProcess { + + @Autowired + LatestService latestService; + + @Override + public void process(EventDataDto eventData) { + String triggerId = eventData.getObjectid(); + String tagValue = eventData.getTagValue(); + + log.debug("-------- event----------triggerId:{},tagValue:{}", triggerId, tagValue); + + String[] split = tagValue.split("\\$\\$"); + if (split.length != 2) { + return; + } + String deviceId = split[0]; + String key = split[1]; + + ProductAttributeEvent productAttributeEvent = new QProductAttributeEvent().productId.eq(deviceId).key.eq(key).findOne(); + + List latestDtos = latestService.qeuryLatest(deviceId, Collections.singletonList(productAttributeEvent.getAttrId())); + + EventTriggerRecord eventTriggerRecord = new EventTriggerRecord(); + eventTriggerRecord.setCreateTime(LocalDateTime.now()); + eventTriggerRecord.setDeviceId(deviceId); + eventTriggerRecord.setEventName(productAttributeEvent.getName()); + eventTriggerRecord.setEventValue(latestDtos.get(0).getOriginalValue()); + DB.insert(eventTriggerRecord); + } + + @Override + public boolean checkTag(String tag) { + return "__event__".equals(tag); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java index aa67ab81..de52f39a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java @@ -39,11 +39,11 @@ public Boolean action(ProductAttr productAttr, Map> expression.append(productAttr.getKey()); expression.append(",#1"); expression.append(") >0 "); - String res = zbxTrigger.executeTriggerCreate(productAttr.getAttrName(), expression.toString(), productAttr.getEventLevel()); + String res = zbxTrigger.triggerCreate(productAttr.getAttrName(), expression.toString(), productAttr.getEventLevel()); String[] triggerids = JSON.parseObject(res, TriggerIds.class).getTriggerids(); Map tags = new ConcurrentHashMap<>(1); - tags.put(EVENT_TAG_NAME, prodId + ""); + tags.put(EVENT_TAG_NAME, "{HOST.HOST}$$"+productAttr.getKey()); zbxTrigger.triggerTagCreate(triggerids[0], tags); return true; From 8f77bf50a92b8a066172b252ba1ee7847b58eb10 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 30 Oct 2021 16:41:52 +0800 Subject: [PATCH 587/763] [fix]: fix event recrod table name --- .../java/com/zmops/iot/domain/device/EventTriggerRecord.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/EventTriggerRecord.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/EventTriggerRecord.java index d550ceee..b16e1677 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/EventTriggerRecord.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/EventTriggerRecord.java @@ -11,7 +11,7 @@ * @author yefei **/ @Data -@Table(name = "service_execute_record") +@Table(name = "event_trigger_record") @Entity public class EventTriggerRecord { @Id From 97b89422f9b501e3368f07eb50632bce543dbaa8 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 30 Oct 2021 17:17:07 +0800 Subject: [PATCH 588/763] [fix]:fix split charactor --- .../com/zmops/iot/web/event/service/IncidentEventProcess.java | 2 +- .../product/service/work/SaveProdAttrEventTriggerWorker.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java index 826b530e..7f49cbf8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java @@ -33,7 +33,7 @@ public void process(EventDataDto eventData) { log.debug("-------- event----------triggerId:{},tagValue:{}", triggerId, tagValue); - String[] split = tagValue.split("\\$\\$"); + String[] split = tagValue.split("##"); if (split.length != 2) { return; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java index de52f39a..7815f361 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java @@ -43,7 +43,7 @@ public Boolean action(ProductAttr productAttr, Map> String[] triggerids = JSON.parseObject(res, TriggerIds.class).getTriggerids(); Map tags = new ConcurrentHashMap<>(1); - tags.put(EVENT_TAG_NAME, "{HOST.HOST}$$"+productAttr.getKey()); + tags.put(EVENT_TAG_NAME, "{HOST.HOST}##"+productAttr.getKey()); zbxTrigger.triggerTagCreate(triggerids[0], tags); return true; From 8423839e2c947abaa9064156d31253bba059ff40 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 30 Oct 2021 18:08:27 +0800 Subject: [PATCH 589/763] [fix]: fix alarm log --- .../main/java/com/zmops/iot/web/alarm/service/AlarmService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index ebbf5829..d417a94a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -128,7 +128,7 @@ private List formatAlarmList(List problemList, AlarmPa List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Objects::toString).collect(Collectors.toList()); //根据triggerid查询出 规则名称 - String sql = "select d.event_rule_name,r.zbx_id from product_event d INNER JOIN (select event_rule_id," + + String sql = "select d.event_rule_name,r.zbx_id from product_event d INNER JOIN (select distinct event_rule_id," + "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id"; if (ToolUtil.isNotEmpty(alarmParam.getName())) { sql += " where d.event_rule_name like :eventRuleName"; From 6c045e84f72354bf68e3ae5caf112e084703997f Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 1 Nov 2021 10:39:36 +0800 Subject: [PATCH 590/763] [fix]: fix event --- .../zeus/driver/service/ZbxHistoryGet.java | 9 ++++++++ .../web/analyse/service/LatestService.java | 21 +++++++++++++++++++ .../event/service/IncidentEventProcess.java | 6 +++++- .../zmops/iot/web/init/BasicSettingsInit.java | 2 +- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java index 318c13c2..f092c7b4 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java @@ -26,4 +26,13 @@ String historyGet(@ParamName("hostid") String hostid, @ParamName("valueType") Integer valueType, @ParamName("timeFrom") Long timeFrom, @ParamName("timeTill") Long timeTill); + + + @Post(headers = "authTag: noAuth") + @JsonPath("/history/history.get") + String historyGetWithNoAuth(@ParamName("hostid") String hostid, + @ParamName("itemids") List itemids, + @ParamName("hisNum") Integer hisNum, + @ParamName("valueType") Integer valueType, + @ParamName("userAuth") String zbxApiToken); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java index 450507d3..6f1edcfc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java @@ -12,6 +12,7 @@ import com.zmops.iot.web.analyse.dto.Mapping; import com.zmops.iot.web.analyse.dto.ValueMap; import com.zmops.iot.web.analyse.dto.param.LatestParam; +import com.zmops.iot.web.init.BasicSettingsInit; import com.zmops.zeus.driver.service.ZbxHistoryGet; import com.zmops.zeus.driver.service.ZbxValueMap; import org.springframework.beans.factory.annotation.Autowired; @@ -123,6 +124,26 @@ public List qeuryLatest(String deviceId, List attrIds) { return latestDtos; } + /** + * 取事件属性 最新数据 + * @return + */ + public List queryEventLatest(String hostid,List zbxIds, int valueType) { + + //根据属性值类型 查询最新数据 + + String res = zbxHistoryGet.historyGetWithNoAuth(hostid, zbxIds, 1, valueType, BasicSettingsInit.zbxApiToken); + List latestDtos = JSONObject.parseArray(res, LatestDto.class); + + latestDtos.forEach(latestDto -> { + latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); + latestDto.setOriginalValue(latestDto.getValue()); + }); + + return latestDtos; + } + + public Map queryMap(String deviceId) { List latestDtos = qeuryLatest(deviceId, Collections.emptyList()); if (ToolUtil.isEmpty(latestDtos)) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java index 7f49cbf8..5ba14553 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java @@ -1,6 +1,8 @@ package com.zmops.iot.web.event.service; +import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.EventTriggerRecord; +import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.domain.product.query.QProductAttributeEvent; import com.zmops.iot.web.analyse.dto.LatestDto; @@ -40,9 +42,11 @@ public void process(EventDataDto eventData) { String deviceId = split[0]; String key = split[1]; + Device device = new QDevice().deviceId.eq(deviceId).findOne(); ProductAttributeEvent productAttributeEvent = new QProductAttributeEvent().productId.eq(deviceId).key.eq(key).findOne(); - List latestDtos = latestService.qeuryLatest(deviceId, Collections.singletonList(productAttributeEvent.getAttrId())); + List latestDtos = latestService.queryEventLatest(device.getZbxId(), Collections.singletonList(productAttributeEvent.getZbxId()), + Integer.parseInt(productAttributeEvent.getValueType())); EventTriggerRecord eventTriggerRecord = new EventTriggerRecord(); eventTriggerRecord.setCreateTime(LocalDateTime.now()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java index 2690fbeb..4f16a274 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java @@ -28,7 +28,7 @@ public class BasicSettingsInit { @Autowired private ZbxInitService zbxInitService; - private String zbxApiToken; + public static String zbxApiToken; @PostConstruct public void init() { From 51896180a6a54b2b00c12e8962589068b6bc8e27 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 1 Nov 2021 11:27:51 +0800 Subject: [PATCH 591/763] [fix]: fix device list query param --- .../device/controller/DeviceController.java | 5 ++-- .../web/device/dto/param/DeviceParams.java | 27 +++++++++++++++++++ .../iot/web/device/service/DeviceService.java | 24 ++++++++++------- .../zmops/iot/web/event/EventDataProcess.java | 2 -- 4 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceParams.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java index 51ebdbb7..6ee33fb3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java @@ -12,6 +12,7 @@ import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.iot.web.device.dto.param.DeviceParam; +import com.zmops.iot.web.device.dto.param.DeviceParams; import com.zmops.iot.web.device.service.DeviceService; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductTag; @@ -52,8 +53,8 @@ public Pager devicePageList(@RequestBody DeviceParam deviceParam) { */ @Permission(code = "dev_list") @PostMapping("/list") - public ResponseData deviceList(@RequestBody DeviceParam deviceParam) { - return ResponseData.success(deviceService.deviceList(deviceParam)); + public ResponseData deviceList(@RequestBody DeviceParams deviceParams) { + return ResponseData.success(deviceService.deviceList(deviceParams)); } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceParams.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceParams.java new file mode 100644 index 00000000..9ca8c15b --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceParams.java @@ -0,0 +1,27 @@ +package com.zmops.iot.web.device.dto.param; + +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class DeviceParams extends BaseQueryParam { + + private String name; + private String deviceId; + + private List productIds; + + private List deviceGroupIds; + + private List prodTypes; + + private String tag; + + private String tagVal; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 256e3ab8..865d2b7b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -16,6 +16,7 @@ import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.iot.web.device.dto.param.DeviceParam; +import com.zmops.iot.web.device.dto.param.DeviceParams; import com.zmops.iot.web.device.service.work.*; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductTag; @@ -71,10 +72,10 @@ public class DeviceService { /** * 设备列表 * - * @param deviceParam + * @param deviceParams * @return */ - public List deviceList(DeviceParam deviceParam) { + public List deviceList(DeviceParams deviceParams) { List deviceIds = getDeviceIds(); if (ToolUtil.isEmpty(deviceIds)) { return Collections.emptyList(); @@ -83,17 +84,20 @@ public List deviceList(DeviceParam deviceParam) { qDevice.deviceId.in(deviceIds); - if (ToolUtil.isNotEmpty(deviceParam.getName())) { - qDevice.name.contains(deviceParam.getName()); + if (ToolUtil.isNotEmpty(deviceParams.getName())) { + qDevice.name.contains(deviceParams.getName()); } - if (ToolUtil.isNotEmpty(deviceParam.getProductId())) { - qDevice.productId.eq(deviceParam.getProductId()); + if (ToolUtil.isNotEmpty(deviceParams.getDeviceId())) { + qDevice.deviceId.eq(deviceParams.getDeviceId()); } - if (ToolUtil.isNotEmpty(deviceParam.getProdType())) { - qDevice.type.contains(deviceParam.getProdType()); + if (ToolUtil.isNotEmpty(deviceParams.getProductIds())) { + qDevice.productId.in(deviceParams.getProductIds()); + } + if (ToolUtil.isNotEmpty(deviceParams.getProdTypes())) { + qDevice.type.in(deviceParams.getProdTypes()); } - if (ToolUtil.isNotEmpty(deviceParam.getDeviceGroupId())) { - List deviceList = new QDevicesGroups().select(QDevicesGroups.Alias.deviceId).deviceGroupId.eq(deviceParam.getDeviceGroupId()).findSingleAttributeList(); + if (ToolUtil.isNotEmpty(deviceParams.getDeviceGroupIds())) { + List deviceList = new QDevicesGroups().select(QDevicesGroups.Alias.deviceId).deviceGroupId.in(deviceParams.getDeviceGroupIds()).findSingleAttributeList(); qDevice.deviceId.in(deviceList); } return qDevice.findList(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventDataProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventDataProcess.java index 43077b32..d4df90d3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventDataProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventDataProcess.java @@ -30,8 +30,6 @@ public void process(Exchange exchange) throws Exception { EventDataDto eventData = JSONObject.parseObject(split[1], EventDataDto.class); - String objectid = eventData.getObjectid(); - eventProcessList.forEach(eventProcess -> { if(eventProcess.checkTag(eventData.getTag())){ eventProcess.process(eventData); From c9a75de89f8231cfe1653039fa57e14af4c5fc14 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 1 Nov 2021 11:35:21 +0800 Subject: [PATCH 592/763] [fix]:fix device list --- .../com/zmops/iot/web/analyse/service/HomeService.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index a0a725ab..638112e2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -23,6 +23,8 @@ import com.zmops.iot.web.analyse.dto.LatestDto; import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.iot.web.device.dto.TaosResponseData; +import com.zmops.iot.web.device.dto.param.DeviceParams; +import com.zmops.iot.web.device.service.DeviceService; import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.entity.ZbxProblemInfo; import com.zmops.zeus.driver.service.TDEngineRest; @@ -62,6 +64,9 @@ public class HomeService { @Autowired TDEngineRest tdEngineRest; + @Autowired + DeviceService deviceService; + private static String hostId = ""; private static final Map ITEM_Map = new ConcurrentHashMap<>(5); @@ -172,7 +177,7 @@ private static String formatName(String name) { public Map getDeviceNum(Integer timeFrom, Integer timeTill) { Map deviceNumMap = new HashMap<>(4); - List list = new QDevice().findList(); + List list = deviceService.deviceList(new DeviceParams()); deviceNumMap.put("total", list.size()); deviceNumMap.put("disable", (int) list.parallelStream().filter(o -> "DISABLE".equals(o.getStatus())).count()); deviceNumMap.put("online", (int) list.parallelStream().filter(o -> null != o.getOnline() && 1 == o.getOnline()).count()); From 13c59bb2931f37c98b8f38dca03a3e47d1c9f023 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 1 Nov 2021 14:41:06 +0800 Subject: [PATCH 593/763] [fix]: add product service cache --- .../iot/model/cache/ProductServiceCache.java | 24 +++++++++++++++ .../model/cache/ProductServiceParamCache.java | 27 +++++++++++++++++ .../com/zmops/iot/util/DefinitionsUtil.java | 30 ++++++++++++++++--- .../event/service/ServiceEventProcess.java | 18 ++++------- .../product/service/ProductSvcService.java | 25 +++++++++++++++- 5 files changed, 106 insertions(+), 18 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/model/cache/ProductServiceCache.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/model/cache/ProductServiceParamCache.java diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/ProductServiceCache.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/ProductServiceCache.java new file mode 100644 index 00000000..0c7fd827 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/ProductServiceCache.java @@ -0,0 +1,24 @@ +package com.zmops.iot.model.cache; + + +import java.util.Map; +import java.util.Optional; + +/** + * @author yefei + **/ +public class ProductServiceCache extends AbstractCache { + + public ProductServiceCache() { + super(); + } + + public void updateProductService(Map map) { + update(map); + } + + public String getServiceName(Long id) { + return Optional.ofNullable(get(id)).orElse(null); + } + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/ProductServiceParamCache.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/ProductServiceParamCache.java new file mode 100644 index 00000000..5ef6c053 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/ProductServiceParamCache.java @@ -0,0 +1,27 @@ +package com.zmops.iot.model.cache; + + +import com.zmops.iot.domain.product.ProductServiceParam; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * @author yefei + **/ +public class ProductServiceParamCache extends AbstractCache> { + + public ProductServiceParamCache() { + super(); + } + + public void updateProductServiceParam(Map> map) { + update(map); + } + + public List getServiceParam(Long id) { + return Optional.ofNullable(get(id)).orElse(null); + } + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java b/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java index 0e016d12..7a611f07 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java @@ -1,11 +1,9 @@ package com.zmops.iot.util; import com.google.common.collect.Table; +import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.sys.SysUser; -import com.zmops.iot.model.cache.DictionaryCache; -import com.zmops.iot.model.cache.ProductTypeCache; -import com.zmops.iot.model.cache.SysRoleCache; -import com.zmops.iot.model.cache.SysUserCache; +import com.zmops.iot.model.cache.*; import lombok.Getter; import lombok.Setter; @@ -35,6 +33,14 @@ public class DefinitionsUtil { @Setter private static ProductTypeCache productTypeCache = new ProductTypeCache(); + @Getter + @Setter + private static ProductServiceCache productServiceCache = new ProductServiceCache(); + + @Getter + @Setter + private static ProductServiceParamCache productServiceParamCache = new ProductServiceParamCache(); + public static void updateDictionaries(Table dictionarys) { dictionaryCache.updateDictionaries(dictionarys); } @@ -63,4 +69,20 @@ public static void updateProductType(Map map) { public static String getTypeName(long value) { return productTypeCache.getTypeName(value); } + + public static void updateServiceCache(Map map) { + productServiceCache.updateProductService(map); + } + + public static String getServiceName(long value) { + return productServiceCache.getServiceName(value); + } + + public static void updateServiceParamCache(Map> paramMap) { + productServiceParamCache.updateProductServiceParam(paramMap); + } + + public static List getServiceParam(long value) { + return productServiceParamCache.getServiceParam(value); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java index 71038b36..45326eef 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java @@ -6,12 +6,10 @@ import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductEventRelation; import com.zmops.iot.domain.product.ProductEventService; -import com.zmops.iot.domain.product.ProductService; import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventService; -import com.zmops.iot.domain.product.query.QProductService; -import com.zmops.iot.domain.product.query.QProductServiceParam; +import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.service.work.DeviceServiceLogWorker; import com.zmops.iot.web.device.service.work.ScenesLogWorker; @@ -70,23 +68,17 @@ public void process(EventDataDto eventData) { .or().deviceId.isNull().deviceId.eq(productEventRelationList.get(0).getRelationId()).endOr().findList(); List> list = new ArrayList<>(); Map> collect = productEventServiceList.parallelStream().collect(Collectors.groupingBy(ProductEventService::getExecuteDeviceId)); + collect.forEach((key, value) -> { Map map = new ConcurrentHashMap<>(); -// Device device = new QDevice().deviceId.eq(key).findOne(); -// if (null == device) { -// return; -// } map.put("device", key); + List> serviceList = new ArrayList<>(); value.forEach(val -> { Map serviceMap = new ConcurrentHashMap<>(); - ProductService productService = new QProductService().id.eq(val.getServiceId()).findOne(); - if (null == productService) { - return; - } - serviceMap.put("name", productService.getName()); + serviceMap.put("name", DefinitionsUtil.getServiceName(val.getServiceId())); - List paramList = new QProductServiceParam().serviceId.eq(val.getServiceId()).findList(); + List paramList = DefinitionsUtil.getServiceParam(val.getServiceId()); if (ToolUtil.isNotEmpty(paramList)) { serviceMap.put("param", paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue))); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index 748dcd07..f4ce1f27 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -1,5 +1,7 @@ package com.zmops.iot.web.product.service; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; import com.zmops.iot.async.executor.Async; import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductService; @@ -8,8 +10,13 @@ import com.zmops.iot.domain.product.query.QProductService; import com.zmops.iot.domain.product.query.QProductServiceParam; import com.zmops.iot.domain.product.query.QProductServiceRelation; +import com.zmops.iot.domain.sys.SysDict; +import com.zmops.iot.domain.sys.SysDictType; +import com.zmops.iot.domain.sys.query.QSysDict; +import com.zmops.iot.domain.sys.query.QSysDictType; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductServiceDto; @@ -19,6 +26,7 @@ import io.ebean.DB; import io.ebean.DtoQuery; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -33,7 +41,7 @@ * 产品 物模型 服务 **/ @Service -public class ProductSvcService { +public class ProductSvcService implements CommandLineRunner{ @Autowired SaveProdSvcWorker saveProdSvcWorker; @@ -229,4 +237,19 @@ public void delete(List ids) { public List paramList(long serviceId) { return new QProductServiceParam().serviceId.eq(serviceId).findList(); } + + private void updateService() { + List serviceList = new QProductService().findList(); + Map map = serviceList.parallelStream().collect(Collectors.toMap(ProductService::getId, ProductService::getName)); + DefinitionsUtil.updateServiceCache(map); + + List serviceParamList = new QProductServiceParam().findList(); + Map> paramMap = serviceParamList.parallelStream().collect(Collectors.groupingBy(ProductServiceParam::getServiceId)); + DefinitionsUtil.updateServiceParamCache(paramMap); + } + + @Override + public void run(String... args) throws Exception { + updateService(); + } } From 80c6a225e23d3a0ab2a018656e68338ca0a99da8 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 1 Nov 2021 15:18:03 +0800 Subject: [PATCH 594/763] [fix]:fix device list --- .../com/zmops/iot/web/device/dto/param/DeviceParams.java | 2 +- .../java/com/zmops/iot/web/device/service/DeviceService.java | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceParams.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceParams.java index 9ca8c15b..561cbc16 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceParams.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceParams.java @@ -18,7 +18,7 @@ public class DeviceParams extends BaseQueryParam { private List deviceGroupIds; - private List prodTypes; + private List prodTypes; private String tag; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 865d2b7b..a31464e1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -93,8 +93,9 @@ public List deviceList(DeviceParams deviceParams) { if (ToolUtil.isNotEmpty(deviceParams.getProductIds())) { qDevice.productId.in(deviceParams.getProductIds()); } - if (ToolUtil.isNotEmpty(deviceParams.getProdTypes())) { - qDevice.type.in(deviceParams.getProdTypes()); + if (ToolUtil.isEmpty(deviceParams.getProductIds()) && ToolUtil.isNotEmpty(deviceParams.getProdTypes())) { + List productIdList = new QProduct().select(QProduct.Alias.productId).groupId.in(deviceParams.getProdTypes()).findSingleAttributeList(); + qDevice.productId.in(productIdList); } if (ToolUtil.isNotEmpty(deviceParams.getDeviceGroupIds())) { List deviceList = new QDevicesGroups().select(QDevicesGroups.Alias.deviceId).deviceGroupId.in(deviceParams.getDeviceGroupIds()).findSingleAttributeList(); From a4c970e206a569d9d13eef08c4eb70bdfd70df82 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 1 Nov 2021 19:14:56 +0800 Subject: [PATCH 595/763] [fix]: fix problem list --- .../com/zmops/iot/domain/alarm/Problem.java | 37 +++ .../zmops/iot/model/cache/DeviceCache.java | 24 ++ .../model/cache/filter/CachedValueFilter.java | 5 + .../zmops/iot/model/cache/filter/DicType.java | 1 + .../com/zmops/iot/util/DefinitionsUtil.java | 12 + .../com/zmops/iot/web/alarm/dto/AlarmDto.java | 21 +- .../iot/web/alarm/dto/param/AlarmParam.java | 3 +- .../iot/web/alarm/service/AlarmService.java | 215 ++++++++++-------- .../iot/web/analyse/service/HomeService.java | 53 +---- .../DeviceEventTriggerController.java | 36 +-- .../iot/web/device/dto/DeviceLogDto.java | 3 +- .../web/device/service/DeviceLogService.java | 10 +- .../iot/web/device/service/DeviceService.java | 18 +- .../zmops/iot/web/event/dto/EventDataDto.java | 8 +- .../web/event/service/AlarmEventProcess.java | 50 ++-- .../ProductEventTriggerController.java | 4 +- .../product/service/ProductSvcService.java | 4 +- 17 files changed, 310 insertions(+), 194 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/alarm/Problem.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/model/cache/DeviceCache.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/alarm/Problem.java b/zeus-common/src/main/java/com/zmops/iot/domain/alarm/Problem.java new file mode 100644 index 00000000..fa86ffa5 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/alarm/Problem.java @@ -0,0 +1,37 @@ +package com.zmops.iot.domain.alarm; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.time.LocalDateTime; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Table(name = "problem") +@Entity +public class Problem { + + @Id + private Long eventId; + + private Long objectId; + + private LocalDateTime clock; + + private LocalDateTime rClock; + + private String name; + + private Integer acknowledged; + + private Integer severity; + + private String deviceId; + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/DeviceCache.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/DeviceCache.java new file mode 100644 index 00000000..fe27d503 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/DeviceCache.java @@ -0,0 +1,24 @@ +package com.zmops.iot.model.cache; + + +import java.util.Map; +import java.util.Optional; + +/** + * @author yefei + **/ +public class DeviceCache extends AbstractCache { + + public DeviceCache() { + super(); + } + + public void updateDeviceName(Map map) { + update(map); + } + + public String getDeviceName(String id) { + return Optional.ofNullable(get(id)).orElse(null); + } + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java index 897ab054..239231da 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java @@ -107,6 +107,11 @@ private String getCachedValue(CachedValue cachedValue, Object value) { return DefinitionsUtil.getTypeName((long) value); } break; + case Device: + if (value instanceof String) { + return DefinitionsUtil.getDeviceName((String) value); + } + break; default: return null; } diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/DicType.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/DicType.java index 4aa1dd54..1c1a4f26 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/DicType.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/DicType.java @@ -10,6 +10,7 @@ public enum DicType { SysUserName(false), SysRole, ProdType, + Device, Dictionary; diff --git a/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java b/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java index 7a611f07..73bbeb3d 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java @@ -41,6 +41,10 @@ public class DefinitionsUtil { @Setter private static ProductServiceParamCache productServiceParamCache = new ProductServiceParamCache(); + @Getter + @Setter + private static DeviceCache deviceCache = new DeviceCache(); + public static void updateDictionaries(Table dictionarys) { dictionaryCache.updateDictionaries(dictionarys); } @@ -85,4 +89,12 @@ public static void updateServiceParamCache(Map> public static List getServiceParam(long value) { return productServiceParamCache.getServiceParam(value); } + + public static void updateDeviceCache(Map map) { + deviceCache.updateDeviceName(map); + } + + public static String getDeviceName(String value) { + return deviceCache.getDeviceName(value); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java index 5448c8db..06df8ae1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java @@ -3,8 +3,11 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; import lombok.Data; +import java.time.LocalDateTime; + /** * @author yefei **/ @@ -12,22 +15,24 @@ @JsonSerialize(using = CachedValueFilter.class) public class AlarmDto { - private String eventid; + private Long eventId; + + private Long objectId; - private String clock; + private LocalDateTime clock; - private String rClock; + private LocalDateTime rClock; private String name; + private Integer acknowledged; + + @CachedValue(type = DicType.Device) + private String deviceId; + @CachedValue(value = "EVENT_LEVEL") private String severity; - private String deviceName; - private String status; - private String acknowledged; - - private String deviceId; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/AlarmParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/AlarmParam.java index 3f3810c2..a2c7a013 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/AlarmParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/AlarmParam.java @@ -14,6 +14,5 @@ public class AlarmParam extends BaseQueryParam { private Long timeTill; private String name; private String statusName; - private String recent = "true"; - private String severity; + private Integer severity; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index d417a94a..d64d61ce 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -1,8 +1,9 @@ package com.zmops.iot.web.alarm.service; -import com.alibaba.fastjson.JSONObject; import com.google.common.base.Joiner; import com.zmops.iot.domain.alarm.AlarmMessage; +import com.zmops.iot.domain.alarm.Problem; +import com.zmops.iot.domain.alarm.query.QProblem; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductEvent; @@ -13,18 +14,17 @@ import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.alarm.dto.AlarmDto; import com.zmops.iot.web.alarm.dto.param.AlarmParam; -import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.iot.web.device.service.DeviceService; -import com.zmops.iot.web.product.dto.ProductEventRuleDto; -import com.zmops.zeus.driver.entity.ZbxProblemInfo; import com.zmops.zeus.driver.service.ZbxProblem; -import io.ebean.DB; -import io.ebean.DtoQuery; +import io.ebean.PagedList; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; /** @@ -42,6 +42,8 @@ public class AlarmService { @Autowired DeviceService deviceService; + private static final String PROBLEM_RESOLVE = "已解決"; + public void alarm(Map alarmInfo) { List deviceIds = (List) alarmInfo.get("hostname"); @@ -92,112 +94,131 @@ public void action(Map alarmInfo) { public Pager getAlarmByPage(AlarmParam alarmParam) { - List zbxProblemInfos = getZbxAlarm(alarmParam); - if (ToolUtil.isEmpty(zbxProblemInfos)) { - return new Pager<>(); - } - if (ToolUtil.isNotEmpty(alarmParam.getStatusName()) && "已解决".equals(alarmParam.getStatusName())) { - zbxProblemInfos = zbxProblemInfos.parallelStream().filter(o -> !"0".equals(o.getR_clock())).collect(Collectors.toList()); - } + QProblem query = buildQproblem(alarmParam); - if (ToolUtil.isNotEmpty(alarmParam.getStatusName()) && "未解决".equals(alarmParam.getStatusName())) { - zbxProblemInfos = zbxProblemInfos.parallelStream().filter(o -> "0".equals(o.getR_clock())).collect(Collectors.toList()); - } - //分页 - List problemList = zbxProblemInfos.stream() - .skip((alarmParam.getPage() - 1) * alarmParam.getMaxRow()) - .limit(alarmParam.getMaxRow()).collect(Collectors.toList()); - if (ToolUtil.isEmpty(problemList)) { - return new Pager<>(Collections.emptyList(), zbxProblemInfos.size()); - } - List alarmDtoList = formatAlarmList(problemList, alarmParam); + PagedList problemList = query.setFirstRow((alarmParam.getPage() - 1) * alarmParam.getMaxRow()) + .setMaxRows(alarmParam.getMaxRow()).findPagedList(); - return new Pager<>(alarmDtoList, zbxProblemInfos.size()); + return new Pager<>(formatAlarmList(problemList.getList()), problemList.getTotalCount()); } public List getAlarmList(AlarmParam alarmParam) { - List problemList = getZbxAlarm(alarmParam); - if (ToolUtil.isEmpty(problemList)) { - return Collections.emptyList(); - } - return formatAlarmList(problemList, alarmParam); - } + QProblem query = buildQproblem(alarmParam); - private List formatAlarmList(List problemList, AlarmParam alarmParam) { - List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Objects::toString).collect(Collectors.toList()); + return formatAlarmList(query.findList()); + } - //根据triggerid查询出 规则名称 - String sql = "select d.event_rule_name,r.zbx_id from product_event d INNER JOIN (select distinct event_rule_id," + - "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id"; - if (ToolUtil.isNotEmpty(alarmParam.getName())) { - sql += " where d.event_rule_name like :eventRuleName"; + private QProblem buildQproblem(AlarmParam alarmParam) { + QProblem query = new QProblem(); + if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { + query.deviceId.eq(alarmParam.getDeviceId()); } - DtoQuery dtoQuery = DB.findDto(ProductEventRuleDto.class, sql).setParameter("zbxIds", triggerIds); - if (ToolUtil.isNotEmpty(alarmParam.getName())) { - dtoQuery.setParameter("eventRuleName", "%" + alarmParam.getName() + "%"); + if (ToolUtil.isNotEmpty(alarmParam.getTimeFrom())) { + query.clock.ge(LocalDateTimeUtils.getLDTByMilliSeconds(alarmParam.getTimeFrom() * 1000)); } - List ruleList = dtoQuery.findList(); - Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); - - //根据triggerid查询出 所属设备 - sql = "select distinct name,device_id,r.zbx_id from device d INNER JOIN (select relation_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.relation_id=d.device_id"; - if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { - sql += " where d.device_id = :deviceId"; + if (ToolUtil.isNotEmpty(alarmParam.getTimeTill())) { + query.clock.lt(LocalDateTimeUtils.getLDTByMilliSeconds(alarmParam.getTimeTill() * 1000)); } - DtoQuery deviceQuery = DB.findDto(DeviceDto.class, sql).setParameter("zbxIds", triggerIds); - if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { - deviceQuery.setParameter("deviceId", alarmParam.getDeviceId()); + if (ToolUtil.isNotEmpty(alarmParam.getStatusName())) { + if (PROBLEM_RESOLVE.equals(alarmParam.getStatusName())) { + query.rClock.isNotNull(); + } else { + query.rClock.isNull(); + } } - List deviceList = deviceQuery.findList(); - Map> deviceMap = deviceList.parallelStream().collect(Collectors.groupingBy(DeviceDto::getZbxId)); + if (ToolUtil.isNotEmpty(alarmParam.getSeverity())) { + query.severity.eq(alarmParam.getSeverity()); + } + query.orderBy().clock.desc(); + return query; + } - List alarmDtoList = new ArrayList<>(); - problemList.forEach(zbxProblemInfo -> { - if (null == ruleMap.get(zbxProblemInfo.getObjectid())) { - return; - } - if (ToolUtil.isNotEmpty(deviceMap.get(zbxProblemInfo.getObjectid()))) { - deviceMap.get(zbxProblemInfo.getObjectid()).forEach(deviceDto -> { - AlarmDto alarmDto = new AlarmDto(); - BeanUtils.copyProperties(zbxProblemInfo, alarmDto); - alarmDto.setRClock(zbxProblemInfo.getR_clock()); - alarmDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(zbxProblemInfo.getClock()), "yyyy-MM-dd HH:mm:ss")); - alarmDto.setRClock("0".equals(zbxProblemInfo.getR_clock()) ? "0" : - LocalDateTimeUtils.convertTimeToString(Integer.parseInt(zbxProblemInfo.getR_clock()), "yyyy-MM-dd HH:mm:ss")); - alarmDto.setStatus("0".equals(zbxProblemInfo.getR_clock()) ? "未解决" : "已解决"); - alarmDto.setAcknowledged("0".equals(zbxProblemInfo.getAcknowledged()) ? "未确认" : "已确认"); - - alarmDto.setDeviceName(deviceDto.getName()); - alarmDto.setDeviceId(deviceDto.getDeviceId()); - - alarmDto.setName(ruleMap.get(zbxProblemInfo.getObjectid())); - alarmDtoList.add(alarmDto); - }); - } + private List formatAlarmList(List problemList) { + List list = new ArrayList<>(); + problemList.forEach(problem -> { + AlarmDto alarmDto = new AlarmDto(); + BeanUtils.copyProperties(problem, alarmDto); + alarmDto.setSeverity(problem.getSeverity() + ""); + list.add(alarmDto); }); - - return alarmDtoList; + return list; } - public List getZbxAlarm(AlarmParam alarmParam) { - String hostId; - List deviceIds; - if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { - deviceIds = Collections.singletonList(alarmParam.getDeviceId()); - } else { - deviceIds = deviceService.getDeviceIds(); - } - - List zbxIds = new QDevice().select(QDevice.alias().zbxId).deviceId.in(deviceIds).zbxId.isNotNull().findSingleAttributeList(); - if (ToolUtil.isEmpty(zbxIds)) { - return Collections.EMPTY_LIST; - } - hostId = zbxIds.toString(); - //从zbx取告警记录 - String problem = zbxProblem.getProblem(hostId, alarmParam.getTimeFrom(), alarmParam.getTimeTill(), alarmParam.getRecent(), alarmParam.getSeverity()); - return JSONObject.parseArray(problem, ZbxProblemInfo.class); - } +// private List formatAlarmList(List problemList, AlarmParam alarmParam) { +// List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Objects::toString).collect(Collectors.toList()); +// +// //根据triggerid查询出 规则名称 +// String sql = "select d.event_rule_name,r.zbx_id from product_event d INNER JOIN (select distinct event_rule_id," + +// "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id"; +// if (ToolUtil.isNotEmpty(alarmParam.getName())) { +// sql += " where d.event_rule_name like :eventRuleName"; +// } +// DtoQuery dtoQuery = DB.findDto(ProductEventRuleDto.class, sql).setParameter("zbxIds", triggerIds); +// if (ToolUtil.isNotEmpty(alarmParam.getName())) { +// dtoQuery.setParameter("eventRuleName", "%" + alarmParam.getName() + "%"); +// } +// List ruleList = dtoQuery.findList(); +// Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); +// +// //根据triggerid查询出 所属设备 +// sql = "select distinct name,device_id,r.zbx_id from device d INNER JOIN (select relation_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.relation_id=d.device_id"; +// if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { +// sql += " where d.device_id = :deviceId"; +// } +// DtoQuery deviceQuery = DB.findDto(DeviceDto.class, sql).setParameter("zbxIds", triggerIds); +// if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { +// deviceQuery.setParameter("deviceId", alarmParam.getDeviceId()); +// } +// List deviceList = deviceQuery.findList(); +// Map> deviceMap = deviceList.parallelStream().collect(Collectors.groupingBy(DeviceDto::getZbxId)); +// +// List alarmDtoList = new ArrayList<>(); +// problemList.forEach(zbxProblemInfo -> { +// if (null == ruleMap.get(zbxProblemInfo.getObjectid())) { +// return; +// } +// if (ToolUtil.isNotEmpty(deviceMap.get(zbxProblemInfo.getObjectid()))) { +// deviceMap.get(zbxProblemInfo.getObjectid()).forEach(deviceDto -> { +// AlarmDto alarmDto = new AlarmDto(); +// BeanUtils.copyProperties(zbxProblemInfo, alarmDto); +// alarmDto.setRClock(zbxProblemInfo.getR_clock()); +// alarmDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(zbxProblemInfo.getClock()), "yyyy-MM-dd HH:mm:ss")); +// alarmDto.setRClock("0".equals(zbxProblemInfo.getR_clock()) ? "0" : +// LocalDateTimeUtils.convertTimeToString(Integer.parseInt(zbxProblemInfo.getR_clock()), "yyyy-MM-dd HH:mm:ss")); +// alarmDto.setStatus("0".equals(zbxProblemInfo.getR_clock()) ? "未解决" : "已解决"); +// alarmDto.setAcknowledged("0".equals(zbxProblemInfo.getAcknowledged()) ? "未确认" : "已确认"); +// +// alarmDto.setDeviceName(deviceDto.getName()); +// alarmDto.setDeviceId(deviceDto.getDeviceId()); +// +// alarmDto.setName(ruleMap.get(zbxProblemInfo.getObjectid())); +// alarmDtoList.add(alarmDto); +// }); +// } +// }); +// +// return alarmDtoList; +// } + +// public List getZbxAlarm(AlarmParam alarmParam) { +// String hostId; +// List deviceIds; +// if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { +// deviceIds = Collections.singletonList(alarmParam.getDeviceId()); +// } else { +// deviceIds = deviceService.getDeviceIds(); +// } +// +// List zbxIds = new QDevice().select(QDevice.alias().zbxId).deviceId.in(deviceIds).zbxId.isNotNull().findSingleAttributeList(); +// if (ToolUtil.isEmpty(zbxIds)) { +// return Collections.EMPTY_LIST; +// } +// hostId = zbxIds.toString(); +// //从zbx取告警记录 +// String problem = zbxProblem.getProblem(hostId, alarmParam.getTimeFrom(), alarmParam.getTimeTill(), alarmParam.getRecent(), alarmParam.getSeverity()); +// return JSONObject.parseArray(problem, ZbxProblemInfo.class); +// } public void acknowledgement(String eventId) { zbxProblem.acknowledgement(eventId, 2); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index 638112e2..65d67ef4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -3,17 +3,19 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.dtflys.forest.http.ForestResponse; +import com.zmops.iot.domain.alarm.Problem; +import com.zmops.iot.domain.alarm.query.QProblem; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.DeviceOnlineReport; import com.zmops.iot.domain.device.EventTriggerRecord; import com.zmops.iot.domain.device.ServiceExecuteRecord; -import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.device.query.QDeviceOnlineReport; import com.zmops.iot.domain.device.query.QEventTriggerRecord; import com.zmops.iot.domain.device.query.QServiceExecuteRecord; import com.zmops.iot.domain.product.query.QProduct; import com.zmops.iot.enums.SeverityEnum; import com.zmops.iot.enums.ValueType; +import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ParseUtil; import com.zmops.iot.util.ToolUtil; @@ -21,17 +23,13 @@ import com.zmops.iot.web.alarm.dto.param.AlarmParam; import com.zmops.iot.web.alarm.service.AlarmService; import com.zmops.iot.web.analyse.dto.LatestDto; -import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.iot.web.device.dto.TaosResponseData; import com.zmops.iot.web.device.dto.param.DeviceParams; import com.zmops.iot.web.device.service.DeviceService; import com.zmops.zeus.driver.entity.ZbxItemInfo; -import com.zmops.zeus.driver.entity.ZbxProblemInfo; import com.zmops.zeus.driver.service.TDEngineRest; import com.zmops.zeus.driver.service.ZbxHost; import com.zmops.zeus.driver.service.ZbxItem; -import io.ebean.DB; -import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -213,11 +211,8 @@ public Map getDeviceNum(Integer timeFrom, Integer timeTill) { private static final String[] severity = {"", "信息", "低级", "中级", "高级", "紧急"}; public Map getAlarmNum(long timeFrom, long timeTill) { - AlarmParam alarmParam = new AlarmParam(); - alarmParam.setTimeTill(timeTill); - alarmParam.setTimeFrom(timeFrom); - alarmParam.setRecent("false"); - List alarmList = alarmService.getZbxAlarm(alarmParam); + List alarmList = new QProblem().clock.ge(LocalDateTimeUtils.getLDTBySeconds((int) timeFrom)) + .clock.lt(LocalDateTimeUtils.getLDTBySeconds((int) timeTill)).orderBy().clock.asc().findList(); Map alarmMap = new ConcurrentHashMap<>(3); Map> initMap = new ConcurrentHashMap<>(5); @@ -232,9 +227,9 @@ public Map getAlarmNum(long timeFrom, long timeTill) { Collections.reverse(alarmList); //过滤出指定时间段内的告警 并顺序排序 Map> tmpMap = alarmList.parallelStream() - .filter(o -> !o.getSeverity().equals("0")).collect( - Collectors.groupingBy(ZbxProblemInfo::getSeverity, Collectors.groupingBy( - o -> LocalDateTimeUtils.convertTimeToString(Integer.parseInt(o.getClock()), "yyyy-MM-dd"), Collectors.counting()))); + .filter(o -> o.getSeverity() > 0).collect( + Collectors.groupingBy(o -> o.getSeverity() + "", Collectors.groupingBy( + o -> LocalDateTimeUtils.formatTime(o.getClock(), "yyyy-MM-dd"), Collectors.counting()))); List> trendsList = new ArrayList<>(); initMap.forEach((key, value) -> { @@ -260,7 +255,7 @@ public Map getAlarmNum(long timeFrom, long timeTill) { Long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); AlarmParam todayParam = new AlarmParam(); todayParam.setTimeFrom(timeStart); - List todayAlarmList = alarmService.getZbxAlarm(todayParam); + List todayAlarmList = alarmService.getAlarmList(todayParam); Long todayAlarmNum = todayAlarmList.parallelStream().filter(o -> !o.getSeverity().equals("0")).count(); alarmMap.put("today", todayAlarmNum); @@ -309,42 +304,18 @@ public List> getAlarmTop(long timeFrom, long timeTill) { alarmParam.setTimeTill(timeTill); alarmParam.setTimeFrom(timeFrom); - List alarmList = alarmService.getZbxAlarm(alarmParam); + List alarmList = alarmService.getAlarmList(alarmParam); Map tmpMap = new ConcurrentHashMap<>(); if (ToolUtil.isNotEmpty(alarmList)) { - - List triggerIds = alarmList.parallelStream() - .map(ZbxProblemInfo::getObjectid).map(Objects::toString).collect(Collectors.toList()); - - List deviceList = DB.findDto(DeviceDto.class, - "select name,r.zbx_id from device d INNER JOIN (select relation_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.relation_id=d.device_id") - .setParameter("zbxIds", triggerIds).findList(); - - Map> deviceMap = deviceList.parallelStream().collect(Collectors.groupingBy(DeviceDto::getZbxId)); - - - List alarmDtoList = new ArrayList<>(); - alarmList.forEach(zbxProblemInfo -> { - if (ToolUtil.isNotEmpty(deviceMap.get(zbxProblemInfo.getObjectid()))) { - deviceMap.get(zbxProblemInfo.getObjectid()).forEach(deviceDto -> { - AlarmDto alarmDto = new AlarmDto(); - BeanUtils.copyProperties(zbxProblemInfo, alarmDto); - alarmDto.setRClock(zbxProblemInfo.getR_clock()); - alarmDto.setDeviceName(deviceDto.getName()); - alarmDtoList.add(alarmDto); - }); - } - }); - - tmpMap = alarmDtoList.parallelStream().collect(Collectors.groupingBy(AlarmDto::getDeviceName, Collectors.counting())); + tmpMap = alarmList.parallelStream().collect(Collectors.groupingBy(AlarmDto::getDeviceId, Collectors.counting())); } List> topList = new ArrayList<>(); tmpMap.forEach((key, value) -> { Map alarmMap = new ConcurrentHashMap<>(2); - alarmMap.put("name", key); + alarmMap.put("name", DefinitionsUtil.getDeviceName(key)); alarmMap.put("value", value); topList.add(alarmMap); }); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index 83ce617c..bf6c7935 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -96,15 +96,15 @@ public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEn .collect(Collectors.toMap(DeviceEventRule.Tag::getTag, DeviceEventRule.Tag::getValue, (k1, k2) -> k2)); } if (!tags.containsKey(ALARM_TAG_NAME)) { - tags.put(ALARM_TAG_NAME, eventRuleId + ""); - } - if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { - tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); - } - Optional any = eventRule.getExpList().parallelStream().filter(o -> EVENT_TYPE_NAME.equals(o.getProductAttrType())).findAny(); - if (any.isPresent()) { - tags.put(EVENT_TAG_NAME, eventRuleId + ""); - } + tags.put(ALARM_TAG_NAME, "{HOST.HOST}"); + } +// if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { +// tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); +// } +// Optional any = eventRule.getExpList().parallelStream().filter(o -> EVENT_TYPE_NAME.equals(o.getProductAttrType())).findAny(); +// if (any.isPresent()) { +// tags.put(EVENT_TAG_NAME, eventRuleId + ""); +// } for (String triggerId : triggerIds) { zbxTrigger.triggerTagCreate(triggerId, tags); } @@ -179,15 +179,15 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn tags = new HashMap<>(2); } if (!tags.containsKey(ALARM_TAG_NAME)) { - tags.put(ALARM_TAG_NAME, eventRule.getEventRuleId() + ""); - } - if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { - tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); - } - Optional any = eventRule.getExpList().parallelStream().filter(o -> EVENT_TYPE_NAME.equals(o.getProductAttrType())).findAny(); - if (any.isPresent()) { - tags.put(EVENT_TAG_NAME, eventRule.getEventRuleId() + ""); - } + tags.put(ALARM_TAG_NAME, "{HOST.HOST}"); + } +// if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { +// tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); +// } +// Optional any = eventRule.getExpList().parallelStream().filter(o -> EVENT_TYPE_NAME.equals(o.getProductAttrType())).findAny(); +// if (any.isPresent()) { +// tags.put(EVENT_TAG_NAME, eventRule.getEventRuleId() + ""); +// } for (String triggerId : triggerIds) { zbxTrigger.triggerTagCreate(triggerId, tags); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java index fdc451cf..5bcf551b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -20,8 +21,8 @@ public class DeviceLogDto { private String logType; private String triggerTime; private String content; + @CachedValue(type = DicType.Device) private String deviceId; - private String deviceName; @CachedValue(value = "EVENT_LEVEL") private String severity; private String param; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java index d8a2bbac..56d24d2b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java @@ -46,8 +46,8 @@ public List list(String deviceId, String logType, Long timeFrom, L if (ToolUtil.isNotEmpty(alarmList)) { alarmList.forEach(alarm -> { deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_ALARM).content(alarm.getName()) - .triggerTime(alarm.getClock()) - .status("0".equals(alarm.getRClock()) ? "未解决" : "已解决").build()); + .triggerTime(LocalDateTimeUtils.formatTime(alarm.getClock())) + .status(null == alarm.getRClock() ? "未解决" : "已解决").build()); }); } } @@ -138,9 +138,9 @@ private List getAlarmLog(String deviceId, Long timeFrom, Long time if (ToolUtil.isNotEmpty(alarmList)) { alarmList.forEach(alarm -> { deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_ALARM).content(alarm.getName()) - .triggerTime(alarm.getClock()) - .status("0".equals(alarm.getRClock()) ? "未解决" : "已解决").severity(alarm.getSeverity()) - .deviceId(alarm.getDeviceId()).deviceName(alarm.getDeviceName()).build()); + .triggerTime(LocalDateTimeUtils.formatTime(alarm.getClock())) + .status(null == alarm.getRClock() ? "未解决" : "已解决").severity(alarm.getSeverity()) + .deviceId(alarm.getDeviceId()).build()); }); } return deviceLogDtoList; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index a31464e1..27e7a913 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -10,9 +10,12 @@ import com.zmops.iot.domain.device.query.QDevicesGroups; import com.zmops.iot.domain.device.query.QTag; import com.zmops.iot.domain.product.Product; +import com.zmops.iot.domain.product.ProductService; +import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.product.query.*; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.iot.web.device.dto.param.DeviceParam; @@ -26,15 +29,17 @@ import io.ebean.DtoQuery; import io.ebean.Query; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Service; import java.util.*; +import java.util.stream.Collectors; /** * @author yefei **/ @Service -public class DeviceService { +public class DeviceService implements CommandLineRunner{ @Autowired private SaveDeviceWorker saveDeviceWorker; @@ -542,4 +547,15 @@ public void status(String status, String deviceId, String zbxId) { } DB.update(Device.class).where().eq("device_id", deviceId).asUpdate().set("status", status).setNull("online").update(); } + + private void updateDevice() { + List deviceList = new QDevice().findList(); + Map map = deviceList.parallelStream().collect(Collectors.toMap(Device::getDeviceId, Device::getName)); + DefinitionsUtil.updateDeviceCache(map); + } + + @Override + public void run(String... args) throws Exception { + updateDevice(); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/dto/EventDataDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/dto/EventDataDto.java index d7068879..e0470648 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/dto/EventDataDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/dto/EventDataDto.java @@ -19,5 +19,11 @@ public class EventDataDto { private String recoveryValue; - private String acknowledged; + private Integer acknowledged; + + private Integer clock; + + private Integer rClock; + + private Integer severity; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java index 35144549..79401fa0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java @@ -1,5 +1,6 @@ package com.zmops.iot.web.event.service; +import com.zmops.iot.domain.alarm.Problem; import com.zmops.iot.domain.messages.MessageBody; import com.zmops.iot.domain.messages.NoticeRecord; import com.zmops.iot.domain.messages.NoticeResult; @@ -20,6 +21,7 @@ import com.zmops.iot.web.sys.dto.UserGroupDto; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -55,35 +57,51 @@ public void process(EventDataDto eventData) { log.debug("--------alarm event----------{}", triggerId); - List list = new QProductEventRelation().zbxId.eq(triggerId).findList(); - if(ToolUtil.isEmpty(list)){ + //step 1:插入problem + Problem problem = new Problem(); + problem.setEventId(Long.parseLong(eventData.getEventid())); + problem.setObjectId(Long.parseLong(eventData.getObjectid())); + problem.setAcknowledged(eventData.getAcknowledged()); + problem.setSeverity(eventData.getSeverity()); + problem.setName(eventData.getName()); + problem.setDeviceId(eventData.getTagValue()); + problem.setClock(LocalDateTimeUtils.getLDTBySeconds(eventData.getClock())); + problem.setRClock(eventData.getRClock() == 0 ? null : LocalDateTimeUtils.getLDTBySeconds(eventData.getRClock())); + if (eventData.getRClock() == 0 && eventData.getAcknowledged() == 0) { + DB.insert(problem); + } else { + DB.update(problem); + } + + //step 2:找出需要通知的用户ID 推送通知 + List deviceIds = new QProductEventRelation().select(QProductEventRelation.alias().relationId).zbxId.eq(triggerId).findSingleAttributeList(); + if (ToolUtil.isEmpty(deviceIds)) { return; } Map params = new ConcurrentHashMap<>(2); - List deviceIds = list.parallelStream().map(ProductEventRelation::getRelationId).collect(Collectors.toList()); params.put("hostname", deviceIds); params.put("triggerName", triggerName); - List userIds = new QSysUser().select(QSysUser.alias().userId).findSingleAttributeList(); - - messageService.push(buildMessage(params, userIds)); - alarmService.alarm(params); - - //发送消息 - ProductEvent productEvent = new QProductEvent().eventRuleId.eq(Long.parseLong(triggerName)).findOne(); - Map macros = createMacroMap(triggerId,eventData.getRecoveryValue(),eventData.getAcknowledged(),productEvent); - String sql = "select user_group_id from sys_usrgrp_devicegrp where device_group_id in (select device_group_id from devices_groups where device_id in (:deviceIds))"; List userGroups = DB.findNative(UserGroupDto.class, sql).setParameter("deviceIds", deviceIds).findList(); - QSysUser qSysUser = new QSysUser(); + QSysUser qSysUser = new QSysUser(); if (ToolUtil.isNotEmpty(userGroups)) { qSysUser.userGroupId.in(userGroups.parallelStream().map(UserGroupDto::getUserGroupId).collect(Collectors.toList())); } List sysUserList = qSysUser.findList(); + List userIds = sysUserList.parallelStream().map(SysUser::getUserId).collect(Collectors.toList()); + + messageService.push(buildMessage(params, userIds)); + alarmService.alarm(params); + + //发送Email消息 + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(Long.parseLong(triggerName)).findOne(); + Map macros = createMacroMap(triggerId, eventData.getRClock()+"", eventData.getAcknowledged()+"", productEvent); + List noticeRecords = new ArrayList<>(); sysUserList.forEach(sysUser -> { - Map notice = noticeService.notice(sysUser, macros,triggerId); + Map notice = noticeService.notice(sysUser, macros, triggerId); for (Map.Entry en : notice.entrySet()) { noticeRecords.add(NoticeRecord.builder() .userId(sysUser.getUserId()) @@ -100,8 +118,8 @@ public void process(EventDataDto eventData) { DB.saveAll(noticeRecords); } - private Map createMacroMap(String triggerId,String value,String acknowledged,ProductEvent productEvent) { - boolean isnew = "1".equals(value); + private Map createMacroMap(String triggerId, String rclock, String acknowledged, ProductEvent productEvent) { + boolean isnew = "0".equals(rclock); Map macroMap = new HashMap(); macroMap.put("${time}", LocalDateTimeUtils.formatTime(LocalDateTime.now())); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index 9eabf7a8..a0bbf22f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -118,7 +118,7 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE .collect(Collectors.toMap(ProductEventRule.Tag::getTag, ProductEventRule.Tag::getValue, (k1, k2) -> k2)); } if (!tags.containsKey(ALARM_TAG_NAME)) { - tags.put(ALARM_TAG_NAME, eventRuleId + ""); + tags.put(ALARM_TAG_NAME, "{HOST.HOST}"); } // if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { // tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); @@ -186,7 +186,7 @@ public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseE tags = new HashMap<>(2); } if (!tags.containsKey(ALARM_TAG_NAME)) { - tags.put(ALARM_TAG_NAME, eventRule.getEventRuleId() + ""); + tags.put(ALARM_TAG_NAME, "{HOST.HOST}"); } // if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { // tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index f4ce1f27..24f7f9dc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -170,7 +170,7 @@ public ProductServiceDto create(ProductServiceDto productServiceDto) { } catch (InterruptedException e) { e.printStackTrace(); } - + updateService(); return productServiceDto; } @@ -209,7 +209,7 @@ public ProductServiceDto update(ProductServiceDto productServiceDto) { } catch (InterruptedException e) { e.printStackTrace(); } - + updateService(); return productServiceDto; } From 32611f981f3f4bd6dce79a7c6957f7d1fbbdea42 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 1 Nov 2021 20:10:54 +0800 Subject: [PATCH 596/763] [fix]:fix alarm name --- .../iot/model/cache/ProductEventCache.java | 24 +++++++++++++++++++ .../com/zmops/iot/util/DefinitionsUtil.java | 12 ++++++++++ .../service/DeviceEventRuleService.java | 9 +++++++ .../web/event/service/AlarmEventProcess.java | 6 ++--- .../service/ProductEventRuleService.java | 24 ++++++++++++++++--- 5 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/model/cache/ProductEventCache.java diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/ProductEventCache.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/ProductEventCache.java new file mode 100644 index 00000000..68e087fb --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/ProductEventCache.java @@ -0,0 +1,24 @@ +package com.zmops.iot.model.cache; + + +import java.util.Map; +import java.util.Optional; + +/** + * @author yefei + **/ +public class ProductEventCache extends AbstractCache { + + public ProductEventCache() { + super(); + } + + public void updateTriggerName(Map map) { + update(map); + } + + public String getTriggerName(Long id) { + return Optional.ofNullable(get(id)).orElse(null); + } + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java b/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java index 73bbeb3d..b26eff51 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java @@ -45,6 +45,10 @@ public class DefinitionsUtil { @Setter private static DeviceCache deviceCache = new DeviceCache(); + @Getter + @Setter + private static ProductEventCache productEventCache = new ProductEventCache(); + public static void updateDictionaries(Table dictionarys) { dictionaryCache.updateDictionaries(dictionarys); } @@ -97,4 +101,12 @@ public static void updateDeviceCache(Map map) { public static String getDeviceName(String value) { return deviceCache.getDeviceName(value); } + + public static void updateProductEventCache(Map map) { + productEventCache.updateTriggerName(map); + } + + public static String getTriggerName(Long value) { + return productEventCache.getTriggerName(value); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 43c7b3da..5efe944e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -16,6 +16,7 @@ import com.zmops.iot.web.device.dto.DeviceEventRule; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductEventRuleDto; +import com.zmops.iot.web.product.service.ProductEventRuleService; import com.zmops.zeus.driver.service.ZbxTrigger; import io.ebean.DB; import io.ebean.annotation.Transactional; @@ -38,6 +39,8 @@ public class DeviceEventRuleService { @Autowired private ZbxTrigger zbxTrigger; + @Autowired + ProductEventRuleService productEventRuleService; /** * 保存触发器 @@ -95,6 +98,9 @@ public void createDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { productEventRelationList.add(productEventRelation); }); DB.saveAll(productEventRelationList); + + //更新缓存 + productEventRuleService.updateProductEvent(); } @Transactional(rollbackFor = Exception.class) @@ -158,6 +164,9 @@ public void updateDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { productEventRelationList.add(productEventRelation); }); DB.saveAll(productEventRelationList); + + //更新缓存 + productEventRuleService.updateProductEvent(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java index 79401fa0..65c5ff3d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java @@ -5,7 +5,6 @@ import com.zmops.iot.domain.messages.NoticeRecord; import com.zmops.iot.domain.messages.NoticeResult; import com.zmops.iot.domain.product.ProductEvent; -import com.zmops.iot.domain.product.ProductEventRelation; import com.zmops.iot.domain.product.query.QProductEvent; import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.domain.sys.SysUser; @@ -21,7 +20,6 @@ import com.zmops.iot.web.sys.dto.UserGroupDto; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -63,7 +61,7 @@ public void process(EventDataDto eventData) { problem.setObjectId(Long.parseLong(eventData.getObjectid())); problem.setAcknowledged(eventData.getAcknowledged()); problem.setSeverity(eventData.getSeverity()); - problem.setName(eventData.getName()); + problem.setName(DefinitionsUtil.getTriggerName(Long.parseLong(eventData.getName()))); problem.setDeviceId(eventData.getTagValue()); problem.setClock(LocalDateTimeUtils.getLDTBySeconds(eventData.getClock())); problem.setRClock(eventData.getRClock() == 0 ? null : LocalDateTimeUtils.getLDTBySeconds(eventData.getRClock())); @@ -97,7 +95,7 @@ public void process(EventDataDto eventData) { //发送Email消息 ProductEvent productEvent = new QProductEvent().eventRuleId.eq(Long.parseLong(triggerName)).findOne(); - Map macros = createMacroMap(triggerId, eventData.getRClock()+"", eventData.getAcknowledged()+"", productEvent); + Map macros = createMacroMap(triggerId, eventData.getRClock() + "", eventData.getAcknowledged() + "", productEvent); List noticeRecords = new ArrayList<>(); sysUserList.forEach(sysUser -> { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index 860021a5..118bec4c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -13,6 +13,7 @@ import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.enums.InheritStatus; import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.product.dto.ProductEventDto; import com.zmops.iot.web.product.dto.ProductEventRule; @@ -23,6 +24,7 @@ import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -39,7 +41,7 @@ @Slf4j @Service -public class ProductEventRuleService { +public class ProductEventRuleService implements CommandLineRunner { @Autowired private ZbxTrigger zbxTrigger; @@ -86,6 +88,9 @@ public void createProductEventRule(ProductEventRule eventRule) { productEventRelation.setInherit(InheritStatus.NO.getCode()); productEventRelation.setRemark(eventRule.getRemark()); DB.save(productEventRelation); + + //更新緩存 + updateProductEvent(); } /** @@ -140,6 +145,8 @@ public void updateProductEventRule(Long eventRuleId, ProductEventRule eventRule) .asUpdate().set("remark", eventRule.getRemark()).update(); } + //更新緩存 + updateProductEvent(); } @@ -286,6 +293,17 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S return productEventRuleDto; } + public void updateProductEvent() { + List deviceList = new QProductEvent().findList(); + Map map = deviceList.parallelStream().collect(Collectors.toMap(ProductEvent::getEventRuleId, ProductEvent::getEventRuleName)); + DefinitionsUtil.updateProductEventCache(map); + } + + @Override + public void run(String... args) throws Exception { + updateProductEvent(); + } + @Data static class TriggerIds { @@ -294,8 +312,8 @@ static class TriggerIds { @Data public static class Triggers { - private String triggerid; - private String description; + private String triggerid; + private String description; private List hosts; } From 03107632e592bbf7047a7f8040c1f7ee733f6ed1 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 1 Nov 2021 20:21:41 +0800 Subject: [PATCH 597/763] [fix]:fix alarm list --- .../src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java | 2 +- .../main/java/com/zmops/iot/web/alarm/service/AlarmService.java | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java index 06df8ae1..db500988 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java @@ -25,7 +25,7 @@ public class AlarmDto { private String name; - private Integer acknowledged; + private String acknowledged; @CachedValue(type = DicType.Device) private String deviceId; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index d64d61ce..f8f8528e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -140,6 +140,8 @@ private List formatAlarmList(List problemList) { AlarmDto alarmDto = new AlarmDto(); BeanUtils.copyProperties(problem, alarmDto); alarmDto.setSeverity(problem.getSeverity() + ""); + alarmDto.setStatus(problem.getRClock() == null ? "未解决" : "已解决"); + alarmDto.setAcknowledged(problem.getAcknowledged() == 0 ? "未确认" : "已确认"); list.add(alarmDto); }); return list; From c5599c59a1221353d26b0cc0b5980846af813e40 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 2 Nov 2021 10:23:01 +0800 Subject: [PATCH 598/763] [fix]: fix devicegroup list --- .../java/com/zmops/iot/util/ToolUtil.java | 34 ++++++++- .../iot/web/alarm/service/AlarmService.java | 75 ------------------- .../controller/DeviceGroupController.java | 8 +- .../iot/web/device/dto/DeviceGroupDto.java | 10 ++- .../device/dto/param/DeviceGroupParam.java | 10 ++- .../device/service/DeviceGroupService.java | 9 ++- 6 files changed, 58 insertions(+), 88 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java b/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java index 52065070..c9eb496b 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java @@ -7,6 +7,7 @@ import com.zmops.iot.model.exception.enums.CoreExceptionEnum; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; import org.springframework.core.env.Environment; import java.io.IOException; @@ -26,8 +27,8 @@ public class ToolUtil { /** * 如果对象不是数字类型 就加上双引号返回 */ - public static String addQuotes(String value){ - if(isNum(value)){ + public static String addQuotes(String value) { + if (isNum(value)) { return value; } return "\\\\\"" + value + "\\\\\""; @@ -408,4 +409,33 @@ public static boolean isAllEmpty(Object... os) { return true; } + + /** + * 将一个对象转换为另一个对象 + * + * @param 要转换的对象 + * @param 转换后的类 + * @param oriList 要转换的对象 + * @param castClass 转换后的对象 + * @return 转换后的对象 + */ + public static List convertBean(List oriList, Class castClass) { + if (isEmpty(oriList)) { + return Collections.emptyList(); + } + List resList = new ArrayList<>(); + oriList.forEach(orimodel -> { + try { + T2 returnModel = castClass.newInstance(); + copyProperties(orimodel, returnModel); + resList.add(returnModel); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + }); + return resList; + } + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index f8f8528e..f05cd4d4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -147,81 +147,6 @@ private List formatAlarmList(List problemList) { return list; } -// private List formatAlarmList(List problemList, AlarmParam alarmParam) { -// List triggerIds = problemList.parallelStream().map(ZbxProblemInfo::getObjectid).map(Objects::toString).collect(Collectors.toList()); -// -// //根据triggerid查询出 规则名称 -// String sql = "select d.event_rule_name,r.zbx_id from product_event d INNER JOIN (select distinct event_rule_id," + -// "zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.event_rule_id=d.event_rule_id"; -// if (ToolUtil.isNotEmpty(alarmParam.getName())) { -// sql += " where d.event_rule_name like :eventRuleName"; -// } -// DtoQuery dtoQuery = DB.findDto(ProductEventRuleDto.class, sql).setParameter("zbxIds", triggerIds); -// if (ToolUtil.isNotEmpty(alarmParam.getName())) { -// dtoQuery.setParameter("eventRuleName", "%" + alarmParam.getName() + "%"); -// } -// List ruleList = dtoQuery.findList(); -// Map ruleMap = ruleList.parallelStream().collect(Collectors.toMap(ProductEventRuleDto::getZbxId, ProductEventRuleDto::getEventRuleName)); -// -// //根据triggerid查询出 所属设备 -// sql = "select distinct name,device_id,r.zbx_id from device d INNER JOIN (select relation_id,zbx_id from product_event_relation where zbx_id in (:zbxIds)) r on r.relation_id=d.device_id"; -// if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { -// sql += " where d.device_id = :deviceId"; -// } -// DtoQuery deviceQuery = DB.findDto(DeviceDto.class, sql).setParameter("zbxIds", triggerIds); -// if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { -// deviceQuery.setParameter("deviceId", alarmParam.getDeviceId()); -// } -// List deviceList = deviceQuery.findList(); -// Map> deviceMap = deviceList.parallelStream().collect(Collectors.groupingBy(DeviceDto::getZbxId)); -// -// List alarmDtoList = new ArrayList<>(); -// problemList.forEach(zbxProblemInfo -> { -// if (null == ruleMap.get(zbxProblemInfo.getObjectid())) { -// return; -// } -// if (ToolUtil.isNotEmpty(deviceMap.get(zbxProblemInfo.getObjectid()))) { -// deviceMap.get(zbxProblemInfo.getObjectid()).forEach(deviceDto -> { -// AlarmDto alarmDto = new AlarmDto(); -// BeanUtils.copyProperties(zbxProblemInfo, alarmDto); -// alarmDto.setRClock(zbxProblemInfo.getR_clock()); -// alarmDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(zbxProblemInfo.getClock()), "yyyy-MM-dd HH:mm:ss")); -// alarmDto.setRClock("0".equals(zbxProblemInfo.getR_clock()) ? "0" : -// LocalDateTimeUtils.convertTimeToString(Integer.parseInt(zbxProblemInfo.getR_clock()), "yyyy-MM-dd HH:mm:ss")); -// alarmDto.setStatus("0".equals(zbxProblemInfo.getR_clock()) ? "未解决" : "已解决"); -// alarmDto.setAcknowledged("0".equals(zbxProblemInfo.getAcknowledged()) ? "未确认" : "已确认"); -// -// alarmDto.setDeviceName(deviceDto.getName()); -// alarmDto.setDeviceId(deviceDto.getDeviceId()); -// -// alarmDto.setName(ruleMap.get(zbxProblemInfo.getObjectid())); -// alarmDtoList.add(alarmDto); -// }); -// } -// }); -// -// return alarmDtoList; -// } - -// public List getZbxAlarm(AlarmParam alarmParam) { -// String hostId; -// List deviceIds; -// if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { -// deviceIds = Collections.singletonList(alarmParam.getDeviceId()); -// } else { -// deviceIds = deviceService.getDeviceIds(); -// } -// -// List zbxIds = new QDevice().select(QDevice.alias().zbxId).deviceId.in(deviceIds).zbxId.isNotNull().findSingleAttributeList(); -// if (ToolUtil.isEmpty(zbxIds)) { -// return Collections.EMPTY_LIST; -// } -// hostId = zbxIds.toString(); -// //从zbx取告警记录 -// String problem = zbxProblem.getProblem(hostId, alarmParam.getTimeFrom(), alarmParam.getTimeTill(), alarmParam.getRecent(), alarmParam.getSeverity()); -// return JSONObject.parseArray(problem, ZbxProblemInfo.class); -// } - public void acknowledgement(String eventId) { zbxProblem.acknowledgement(eventId, 2); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceGroupController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceGroupController.java index a18ffd42..eda11759 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceGroupController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceGroupController.java @@ -34,7 +34,7 @@ public class DeviceGroupController { * @return */ @PostMapping("/getDeviceGrpByPage") - public Pager getDeviceGrpByPage(@RequestBody DeviceGroupParam devGroupParam) { + public Pager getDeviceGrpByPage(@RequestBody DeviceGroupParam devGroupParam) { return deviceGroupService.deviceGroupPageList(devGroupParam); } @@ -55,7 +55,7 @@ public ResponseData deviceGroupList(@RequestBody DeviceGroupParam devGroupParam) */ @PostMapping("/create") @BussinessLog(value = "创建设备组") - public ResponseData createDeviceGroup(@Valid @RequestBody DeviceGroupDto deviceGroupDto) { + public ResponseData createDeviceGroup(@Validated(BaseEntity.Create.class) @RequestBody DeviceGroupParam deviceGroupDto) { return ResponseData.success(deviceGroupService.createDeviceGroup(deviceGroupDto)); } @@ -67,7 +67,7 @@ public ResponseData createDeviceGroup(@Valid @RequestBody DeviceGroupDto deviceG */ @PostMapping("/update") @BussinessLog(value = "更新设备组") - public ResponseData updateDeviceGroup(@Validated(BaseEntity.Update.class) @RequestBody DeviceGroupDto deviceGroupDto) { + public ResponseData updateDeviceGroup(@Validated(BaseEntity.Update.class) @RequestBody DeviceGroupParam deviceGroupDto) { return ResponseData.success(deviceGroupService.updateDeviceGroup(deviceGroupDto)); } @@ -78,7 +78,7 @@ public ResponseData updateDeviceGroup(@Validated(BaseEntity.Update.class) @Reque */ @PostMapping("/delete") @BussinessLog(value = "删除设备组") - public ResponseData deleteDeviceGroup(@Valid @RequestBody DeviceGroupParam deviceGroupParam) { + public ResponseData deleteDeviceGroup(@Validated(BaseEntity.Delete.class) @RequestBody DeviceGroupParam deviceGroupParam) { deviceGroupService.deleteDeviceGroup(deviceGroupParam); return ResponseData.success(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java index 6a3b495d..1cdd725e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java @@ -16,6 +16,8 @@ package com.zmops.iot.web.device.dto; import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.DicType; import lombok.Data; import javax.validation.constraints.NotBlank; @@ -29,12 +31,16 @@ @Data public class DeviceGroupDto { - @NotNull(groups = BaseEntity.Update.class) private Long deviceGroupId; - @NotBlank private String name; private String remark; + @CachedValue(type = DicType.SysUserName) + private Long createUser; + private String createTime; + @CachedValue(type = DicType.SysUserName) + private Long updateUser; + private String updateTime; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceGroupParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceGroupParam.java index f99bc958..704ce0cd 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceGroupParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceGroupParam.java @@ -15,9 +15,11 @@ */ package com.zmops.iot.web.device.dto.param; +import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.web.sys.dto.param.BaseQueryParam; import lombok.Data; +import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import java.util.List; @@ -29,8 +31,14 @@ @Data public class DeviceGroupParam extends BaseQueryParam { + @NotNull(groups = BaseEntity.Update.class) + private Long deviceGroupId; + + @NotBlank(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) private String name; - @NotNull + private String remark; + + @NotNull(groups = BaseEntity.Delete.class) private List deviceGroupIds; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java index e1a49ab9..09faed18 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java @@ -44,7 +44,7 @@ public class DeviceGroupService { * @param devGroupParam * @return */ - public Pager deviceGroupPageList(DeviceGroupParam devGroupParam) { + public Pager deviceGroupPageList(DeviceGroupParam devGroupParam) { List devGroupIds = getDevGroupIds(); if (ToolUtil.isEmpty(devGroupIds)) { return new Pager<>(); @@ -61,7 +61,8 @@ public Pager deviceGroupPageList(DeviceGroupParam devGroupParam) { .setFirstRow((devGroupParam.getPage() - 1) * devGroupParam.getMaxRow()) .setMaxRows(devGroupParam.getMaxRow()); PagedList pagedList = qDeviceGroup.orderBy(" create_time desc").findPagedList(); - return new Pager<>(pagedList.getList(), pagedList.getTotalCount()); + List deviceGroupDtos = ToolUtil.convertBean(pagedList.getList(), DeviceGroupDto.class); + return new Pager<>(deviceGroupDtos, pagedList.getTotalCount()); } /** @@ -107,7 +108,7 @@ public List getDevGroupIds() { /** * 添加设备組 */ - public DeviceGroup createDeviceGroup(DeviceGroupDto deviceGroup) { + public DeviceGroup createDeviceGroup(DeviceGroupParam deviceGroup) { // 判断设备组是否重复 checkByGroupName(deviceGroup.getName(), -1L); //获取ID @@ -131,7 +132,7 @@ public DeviceGroup createDeviceGroup(DeviceGroupDto deviceGroup) { * @param deviceGroup * @return DeviceGroup */ - public DeviceGroup updateDeviceGroup(DeviceGroupDto deviceGroup) { + public DeviceGroup updateDeviceGroup(DeviceGroupParam deviceGroup) { // 判断设备组是否重复 checkByGroupName(deviceGroup.getName(), deviceGroup.getDeviceGroupId()); From f6f2292c4f0e17e880882a7951e6aa6643c1fcfc Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 2 Nov 2021 10:29:53 +0800 Subject: [PATCH 599/763] [fix]: fix devicegroup list --- .../main/java/com/zmops/iot/domain/product/ProductType.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductType.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductType.java index a21abeaa..b1df6b10 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductType.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductType.java @@ -1,5 +1,6 @@ package com.zmops.iot.domain.product; +import com.zmops.iot.domain.BaseEntity; import lombok.Data; import lombok.EqualsAndHashCode; @@ -14,7 +15,7 @@ @Data @Entity @Table(name = "product_type") -public class ProductType { +public class ProductType extends BaseEntity { @Id private Long id; From eba3716df85d3cd9a578fc8f2e9bcfb6cb583e75 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 2 Nov 2021 13:47:56 +0800 Subject: [PATCH 600/763] [fix]: fix devicegroup list --- zeus-common/src/main/java/com/zmops/iot/domain/BaseEntity.java | 2 ++ .../main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java | 3 +++ 2 files changed, 5 insertions(+) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/BaseEntity.java b/zeus-common/src/main/java/com/zmops/iot/domain/BaseEntity.java index c2f242fa..dcd82267 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/BaseEntity.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/BaseEntity.java @@ -5,6 +5,7 @@ import io.ebean.annotation.WhenModified; import io.ebean.annotation.WhoCreated; import io.ebean.annotation.WhoModified; +import lombok.Data; import javax.persistence.MappedSuperclass; import java.time.LocalDateTime; @@ -13,6 +14,7 @@ * @author nantian created at 2021/7/30 20:37 */ @MappedSuperclass +@Data public abstract class BaseEntity extends Model { @WhenCreated diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java index 1cdd725e..dda36c80 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java @@ -15,8 +15,10 @@ */ package com.zmops.iot.web.device.dto; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; import com.zmops.iot.model.cache.filter.DicType; import lombok.Data; @@ -29,6 +31,7 @@ * @author yefei */ @Data +@JsonSerialize(using = CachedValueFilter.class) public class DeviceGroupDto { private Long deviceGroupId; From 32a4ed4330714e142a80695f248d17430a5b35ab Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 2 Nov 2021 14:03:47 +0800 Subject: [PATCH 601/763] [fix]: fix devicegroup list --- .../iot/web/device/dto/DeviceGroupDto.java | 27 ++++--------------- .../device/dto/param/DeviceGroupParam.java | 17 +----------- 2 files changed, 6 insertions(+), 38 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java index dda36c80..aa47712a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java @@ -1,29 +1,12 @@ -/** - * Copyright 2018-2020 stylefeng & fengshuonan (https://gitee.com/stylefeng) - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ package com.zmops.iot.web.device.dto; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; import com.zmops.iot.model.cache.filter.DicType; import lombok.Data; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; /** * 设备组传输bean @@ -41,9 +24,9 @@ public class DeviceGroupDto { private String remark; @CachedValue(type = DicType.SysUserName) - private Long createUser; - private String createTime; + private Long createUser; @CachedValue(type = DicType.SysUserName) - private Long updateUser; - private String updateTime; + private Long updateUser; + private LocalDateTime createTime; + private LocalDateTime updateTime; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceGroupParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceGroupParam.java index 704ce0cd..1d99c9eb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceGroupParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceGroupParam.java @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2020 stylefeng & fengshuonan (https://gitee.com/stylefeng) - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ package com.zmops.iot.web.device.dto.param; import com.zmops.iot.domain.BaseEntity; @@ -34,7 +19,7 @@ public class DeviceGroupParam extends BaseQueryParam { @NotNull(groups = BaseEntity.Update.class) private Long deviceGroupId; - @NotBlank(groups = {BaseEntity.Update.class,BaseEntity.Create.class}) + @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) private String name; private String remark; From 7242bbcfddb8e18f40dabba25cc2c910ce7cee9d Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 2 Nov 2021 16:48:17 +0800 Subject: [PATCH 602/763] [fix]: fix scene log name --- .../java/com/zmops/iot/web/device/service/DeviceLogService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java index 56d24d2b..7716f584 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java @@ -30,7 +30,7 @@ public class DeviceLogService { private static final String LOG_TYPE_ALARM = "告警日志"; private static final String LOG_TYPE_EVENT = "事件日志"; private static final String LOG_TYPE_SERVICE = "服务日志"; - private static final String LOG_TYPE_SCENES = "场景日志"; + private static final String LOG_TYPE_SCENES = "联动日志"; @Autowired AlarmService alarmService; From b0f1d6ae126dae200ecb54ba7557b92311bf3225 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 2 Nov 2021 20:03:43 +0800 Subject: [PATCH 603/763] [fix]: fix macro --- .../java/com/zmops/iot/domain/device/ScenesTriggerRecord.java | 2 +- .../src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/ScenesTriggerRecord.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/ScenesTriggerRecord.java index 113750af..eae448f4 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/ScenesTriggerRecord.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/ScenesTriggerRecord.java @@ -11,7 +11,7 @@ * @author yefei **/ @Data -@Table(name = "service_execute_record") +@Table(name = "scenes_trigger_record") @Entity public class ScenesTriggerRecord { @Id diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java index b211f05d..836d1c29 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java @@ -24,8 +24,8 @@ public class UserMacro { private String description; @NotBlank(groups = BaseEntity.Update.class) - private String inherit; - private String inheritName="否"; + private String inherit = "0"; + private String inheritName = "否"; @NotBlank(groups = {BaseEntity.Delete.class, BaseEntity.Update.class}) private String hostmacroid; From 66d55046f3afbec78b510b5f52dae7f429d59339 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 2 Nov 2021 20:39:33 +0800 Subject: [PATCH 604/763] [feat]: service log add param --- .../web/device/service/work/DeviceServiceLogWorker.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java index 3ec2c418..3bb70a56 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java @@ -1,13 +1,17 @@ package com.zmops.iot.web.device.service.work; +import com.alibaba.fastjson.JSONObject; import com.zmops.iot.async.callback.IWorker; import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.ServiceExecuteRecord; import com.zmops.iot.domain.product.ProductEventService; import com.zmops.iot.domain.product.ProductService; +import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.product.query.QProductEventService; import com.zmops.iot.domain.product.query.QProductService; +import com.zmops.iot.util.DefinitionsUtil; +import com.zmops.iot.util.ToolUtil; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -44,7 +48,10 @@ public Boolean action(Map param, Map productEventServiceList.forEach(productEventService -> { ServiceExecuteRecord serviceExecuteRecord = new ServiceExecuteRecord(); serviceExecuteRecord.setDeviceId(productEventService.getExecuteDeviceId()); - //TODO 执行的参数 + List paramList = DefinitionsUtil.getServiceParam(productEventService.getServiceId()); + if (ToolUtil.isNotEmpty(paramList)) { + serviceExecuteRecord.setParam(JSONObject.toJSONString(paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue)))); + } serviceExecuteRecord.setServiceName(Optional.ofNullable(productServiceMap.get(productEventService.getServiceId())).map(ProductService::getName).orElse("")); serviceExecuteRecord.setCreateTime(LocalDateTime.now()); serviceExecuteRecordList.add(serviceExecuteRecord); From 8e7b29edf62137f864de2cbaadf79aa066e27262 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 3 Nov 2021 09:49:49 +0800 Subject: [PATCH 605/763] [feat]: product type list add field --- .../src/main/java/com/zmops/iot/model/node/TreeNode.java | 5 +++++ .../zmops/iot/web/product/service/ProductTypeService.java | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/model/node/TreeNode.java b/zeus-common/src/main/java/com/zmops/iot/model/node/TreeNode.java index 4795f6f6..4748431d 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/node/TreeNode.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/node/TreeNode.java @@ -3,6 +3,7 @@ import com.zmops.iot.util.ToolUtil; import lombok.Data; +import java.time.LocalDateTime; import java.util.List; /** @@ -46,6 +47,10 @@ public class TreeNode implements Tree { */ private Boolean isChecked; + private LocalDateTime createTime; + + private String createUserName; + /** * 子节点 */ diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTypeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTypeService.java index 0eeb2233..afeb6295 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTypeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTypeService.java @@ -29,7 +29,7 @@ public class ProductTypeService implements CommandLineRunner { * 产品分类树 */ public List tree() { - String sql = "select id,pid pId,name,pids from product_type"; + String sql = "select p.id,p.pid pId,p.name,p.pids,p.create_time,u.name createUserName from product_type p LEFT JOIN sys_user u on u.user_id = p.create_user"; List list = DB.findDto(TreeNode.class, sql).findList(); DefaultTreeBuildFactory treeBuildFactory = new DefaultTreeBuildFactory<>(); treeBuildFactory.setRootParentId("0"); From e2133aa4c0c58b5a825ea809f0e8cbf589a67b31 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 3 Nov 2021 11:32:42 +0800 Subject: [PATCH 606/763] [feat]:add scene process --- .../DeviceEventTriggerController.java | 6 +- .../MultipleDeviceEventTriggerController.java | 2 +- .../web/event/service/SceneEventProcess.java | 97 +++++++++++++++++++ .../event/service/ServiceEventProcess.java | 6 +- .../ProductEventTriggerController.java | 7 +- 5 files changed, 106 insertions(+), 12 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index bf6c7935..49887f11 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -98,9 +98,9 @@ public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEn if (!tags.containsKey(ALARM_TAG_NAME)) { tags.put(ALARM_TAG_NAME, "{HOST.HOST}"); } -// if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { -// tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); -// } + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { + tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); + } // Optional any = eventRule.getExpList().parallelStream().filter(o -> EVENT_TYPE_NAME.equals(o.getProductAttrType())).findAny(); // if (any.isPresent()) { // tags.put(EVENT_TAG_NAME, eventRuleId + ""); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java index 67f0173e..ed6df160 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java @@ -48,7 +48,7 @@ public class MultipleDeviceEventTriggerController { @Autowired private ZbxTrigger zbxTrigger; - private static final String EXECUTE_TAG_NAME = "__execute__"; + private static final String EXECUTE_TAG_NAME = "__scene__"; /** * 触发器 分页列表 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java new file mode 100644 index 00000000..1690b947 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java @@ -0,0 +1,97 @@ +package com.zmops.iot.web.event.service; + +import com.alibaba.fastjson.JSON; +import com.dtflys.forest.Forest; +import com.zmops.iot.async.executor.Async; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.product.ProductEventService; +import com.zmops.iot.domain.product.ProductServiceParam; +import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.util.DefinitionsUtil; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.service.work.DeviceServiceLogWorker; +import com.zmops.iot.web.device.service.work.ScenesLogWorker; +import com.zmops.iot.web.event.EventProcess; +import com.zmops.iot.web.event.dto.EventDataDto; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @author yefei + **/ +@Slf4j +@Component +public class SceneEventProcess implements EventProcess { + + @Autowired + DeviceServiceLogWorker deviceServiceLogWorker; + + @Autowired + ScenesLogWorker scenesLogWorker; + + @Override + public void process(EventDataDto eventData) { + log.debug("--------scene event----------{}", eventData.getObjectid()); + Map alarmInfo = new ConcurrentHashMap<>(3); + + String productEventRuleId = eventData.getName(); + if (ToolUtil.isEmpty(productEventRuleId)) { + return; + } + long eventRuleId = Long.parseLong(productEventRuleId); + + alarmInfo.put("eventRuleId", eventRuleId); + + WorkerWrapper, Boolean> deviceServiceLogWork = WorkerWrapper., Boolean>builder().id("deviceServiceLogWorker") + .worker(deviceServiceLogWorker).param(alarmInfo) + .build(); + WorkerWrapper, Boolean> scenesLogWork = WorkerWrapper., Boolean>builder().id("scenesLogWorker") + .worker(scenesLogWorker).param(alarmInfo) + .build(); + + try { + Async.work(1000, deviceServiceLogWork, scenesLogWork).awaitFinish(); + } catch (Exception e) { + e.printStackTrace(); + } + + List productEventServiceList = new QProductEventService().eventRuleId.eq(eventRuleId) + .deviceId.isNull().findList(); + List> list = new ArrayList<>(); + Map> collect = productEventServiceList.parallelStream().collect(Collectors.groupingBy(ProductEventService::getExecuteDeviceId)); + + collect.forEach((key, value) -> { + Map map = new ConcurrentHashMap<>(); + map.put("device", key); + + List> serviceList = new ArrayList<>(); + value.forEach(val -> { + Map serviceMap = new ConcurrentHashMap<>(); + serviceMap.put("name", DefinitionsUtil.getServiceName(val.getServiceId())); + + List paramList = DefinitionsUtil.getServiceParam(val.getServiceId()); + if (ToolUtil.isNotEmpty(paramList)) { + serviceMap.put("param", paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue))); + } + serviceList.add(serviceMap); + }); + map.put("service", serviceList); + list.add(map); + }); + + Forest.post("/device/action/exec").host("127.0.0.1").port(12800).contentTypeJson().addBody(JSON.toJSON(list)).execute(); + } + + @Override + public boolean checkTag(String tag) { + return "__execute__".equals(tag); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java index 45326eef..cc3128bc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java @@ -54,12 +54,8 @@ public void process(EventDataDto eventData) { WorkerWrapper, Boolean> deviceServiceLogWork = WorkerWrapper., Boolean>builder().id("deviceServiceLogWorker") .worker(deviceServiceLogWorker).param(alarmInfo) .build(); - WorkerWrapper, Boolean> scenesLogWork = WorkerWrapper., Boolean>builder().id("scenesLogWorker") - .worker(scenesLogWorker).param(alarmInfo) - .build(); - try { - Async.work(1000, deviceServiceLogWork, scenesLogWork).awaitFinish(); + Async.work(1000, deviceServiceLogWork).awaitFinish(); } catch (Exception e) { e.printStackTrace(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index a0bbf22f..f1c01db7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -56,6 +56,7 @@ public class ProductEventTriggerController { private ZbxTrigger zbxTrigger; private static final String ALARM_TAG_NAME = "__alarm__"; + private static final String EXECUTE_TAG_NAME = "__execute__"; @Autowired SaveProductEventTriggerWorker saveProductEventTriggerWorker; @@ -120,9 +121,9 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE if (!tags.containsKey(ALARM_TAG_NAME)) { tags.put(ALARM_TAG_NAME, "{HOST.HOST}"); } -// if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { -// tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); -// } + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { + tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); + } // Optional any = eventRule.getExpList().parallelStream().filter(o -> EVENT_TYPE_NAME.equals(o.getProductAttrType())).findAny(); // if (any.isPresent()) { // tags.put(EVENT_TAG_NAME, eventRuleId + ""); From bd60170e12e86c2211f15fe8d801e5a33b3792fd Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 3 Nov 2021 11:46:01 +0800 Subject: [PATCH 607/763] [fix]:fix scene tag --- .../java/com/zmops/iot/web/event/service/SceneEventProcess.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java index 1690b947..09faf9a9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java @@ -91,7 +91,7 @@ public void process(EventDataDto eventData) { @Override public boolean checkTag(String tag) { - return "__execute__".equals(tag); + return "__scene__".equals(tag); } } From 6fb9237578b3b29c2b1756c1bee87b7ebc50794b Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 3 Nov 2021 13:57:27 +0800 Subject: [PATCH 608/763] [fix]:fix bug --- .../com/zmops/iot/web/device/service/DeviceModelService.java | 2 +- .../iot/web/product/service/ProductAttributeEventService.java | 2 +- .../com/zmops/iot/web/product/service/ProductModelService.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index a9abbe29..cc14b131 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -147,7 +147,7 @@ public List list(ProductAttrParam productAttr) { public ProductAttrDto detail(Long attrId) { ProductAttrDto attr = new QProductAttribute().attrId.eq(attrId).asDto(ProductAttrDto.class).findOne(); - if (null == attr.getZbxId()) { + if (attr == null || ToolUtil.isEmpty(attr.getZbxId())) { return attr; } JSONArray itemInfo = JSONObject.parseArray(zbxItem.getItemInfo(attr.getZbxId(), null)); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java index b2ae10af..94a61bde 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -132,7 +132,7 @@ public ProductAttrDto detail(Long attrId) { // ProductAttrDto attr = new QProductAttributeEvent().attrId.eq(attrId).asDto(ProductAttrDto.class).findOne(); ProductAttrDto attr = DB.findDto(ProductAttrDto.class, "select * from product_attribute_event where attr_id=:attrId").setParameter("attrId", attrId).findOne(); - if (attr == null || null == attr.getZbxId()) { + if (attr == null || ToolUtil.isEmpty(attr.getZbxId())) { return attr; } JSONArray itemInfo = JSONObject.parseArray(zbxItem.getItemInfo(attr.getZbxId(), null)); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index 34388db3..db97ab47 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -130,7 +130,7 @@ public ProductAttrDto detail(Long attrId) { // ProductAttrDto attr = new QProductAttribute().attrId.eq(attrId).asDto(ProductAttrDto.class).findOne(); ProductAttrDto attr = DB.findDto(ProductAttrDto.class, "select * from product_attribute where attr_id=:attrId").setParameter("attrId", attrId).findOne(); - if (null == attr.getZbxId()) { + if (attr == null || ToolUtil.isEmpty(attr.getZbxId())) { return attr; } JSONArray itemInfo = JSONObject.parseArray(zbxItem.getItemInfo(attr.getZbxId(), null)); From 37d72d205792ef3e9a7a4ce39a0f9c6bf6266b05 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 3 Nov 2021 14:28:25 +0800 Subject: [PATCH 609/763] [feat]:add global runtime exception process --- .../exception/aop/GlobalExceptionHandler.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/aop/GlobalExceptionHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/aop/GlobalExceptionHandler.java index fbb2d62c..f3bd0e97 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/aop/GlobalExceptionHandler.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/aop/GlobalExceptionHandler.java @@ -219,4 +219,20 @@ public ErrorResponseData notFount(Throwable e) { getRequest().setAttribute("tip", message); return new ErrorResponseData(BizExceptionEnum.SERVER_ERROR.getCode(), message); } + + /** + * 拦截运行时异常 + */ + @ExceptionHandler(RuntimeException.class) + @ResponseStatus(HttpStatus.OK) + @ResponseBody + public ErrorResponseData runtime(RuntimeException e) { + log.error("运行时异常:", e); + if (LoginContextHolder.getContext().hasLogin()) { + LogManager.me().executeLog(LogTaskFactory.exceptionLog(LoginContextHolder.getContext().getUserId(), e)); + } + String message = String.format("服务器运行异常请联系管理员"); + getRequest().setAttribute("tip", message); + return new ErrorResponseData(BizExceptionEnum.SERVER_ERROR.getCode(), message); + } } From 37199466fc2dc19efc7e7489942d2f820265b137 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 3 Nov 2021 15:08:50 +0800 Subject: [PATCH 610/763] [feat]: add product icon --- .../src/main/java/com/zmops/iot/domain/product/Product.java | 2 ++ .../java/com/zmops/iot/web/product/dto/ProductBasicInfo.java | 3 +++ .../main/java/com/zmops/iot/web/product/dto/ProductDto.java | 2 ++ .../java/com/zmops/iot/web/product/service/ProductService.java | 2 +- 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/Product.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/Product.java index 452d34e2..a636c94c 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/Product.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/Product.java @@ -39,4 +39,6 @@ public class Product extends BaseEntity { private String zbxId; + private String icon; + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductBasicInfo.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductBasicInfo.java index e029100f..495c4859 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductBasicInfo.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductBasicInfo.java @@ -39,4 +39,7 @@ public class ProductBasicInfo extends BaseQueryParam { private String tag; private String tagVal; + + private String icon; + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java index 3e1482ea..a071757c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java @@ -49,6 +49,8 @@ public class ProductDto { private Long deviceNum; + private String icon; + // private List productTag; // private JSONArray valueMaps; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java index b3cbb838..6f3396a6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java @@ -223,7 +223,7 @@ private static Product buildPord(ProductBasicInfo prodBasicInfo) { product.setRemark(prodBasicInfo.getRemark()); product.setType(prodBasicInfo.getProdType()); product.setGroupId(prodBasicInfo.getGroupId()); - + product.setIcon(prodBasicInfo.getIcon()); return product; } From 07263f7cc00f222d9112da200b6dcd2247a0fc7b Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Wed, 3 Nov 2021 16:09:27 +0800 Subject: [PATCH 611/763] [feat]: run zeus iot use docker --- docker/docker-entrypoint.sh | 378 ++++++++++++++++++++++++++++++++++++ docker/dockerfile | 18 ++ docker/log4j2.xml | 19 ++ 3 files changed, 415 insertions(+) create mode 100755 docker/docker-entrypoint.sh create mode 100644 docker/dockerfile create mode 100644 docker/log4j2.xml diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh new file mode 100755 index 00000000..48e3f85b --- /dev/null +++ b/docker/docker-entrypoint.sh @@ -0,0 +1,378 @@ +#!/bin/bash + +set -o pipefail + +set +e +set -x +# Script trace mode +if [ "${DEBUG_MODE,,}" == "true" ]; then + set -o xtrace +fi + +#Enable PostgreSQL timescaleDB feature: +: ${ENABLE_TIMESCALEDB:="false"} + +# Default directories +# User 'zabbix' home directory +ZABBIX_USER_HOME_DIR="/var/lib/zabbix" +# Configuration files directory +ZABBIX_ETC_DIR="/etc/zabbix" + +# usage: file_env VAR [DEFAULT] +# as example: file_env 'MYSQL_PASSWORD' 'zabbix' +# (will allow for "$MYSQL_PASSWORD_FILE" to fill in the value of "$MYSQL_PASSWORD" from a file) +# unsets the VAR_FILE afterwards and just leaving VAR +file_env() { + local var="$1" + local fileVar="${var}_FILE" + local defaultValue="${2:-}" + + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + echo "**** Both variables $var and $fileVar are set (but are exclusive)" + exit 1 + fi + + local val="$defaultValue" + + if [ "${!var:-}" ]; then + val="${!var}" + echo "** Using ${var} variable from ENV" + elif [ "${!fileVar:-}" ]; then + if [ ! -f "${!fileVar}" ]; then + echo "**** Secret file \"${!fileVar}\" is not found" + exit 1 + fi + val="$(< "${!fileVar}")" + echo "** Using ${var} variable from secret file" + fi + export "$var"="$val" + unset "$fileVar" +} + +escape_spec_char() { + local var_value=$1 + + var_value="${var_value//\\/\\\\}" + var_value="${var_value//[$'\n']/}" + var_value="${var_value//\//\\/}" + var_value="${var_value//./\\.}" + var_value="${var_value//\*/\\*}" + var_value="${var_value//^/\\^}" + var_value="${var_value//\$/\\\$}" + var_value="${var_value//\&/\\\&}" + var_value="${var_value//\[/\\[}" + var_value="${var_value//\]/\\]}" + + echo "$var_value" +} + +update_config_var() { + local config_path=$1 + local var_name=$2 + local var_value=$3 + local is_multiple=$4 + + local masklist=("DBPassword TLSPSKIdentity") + + if [ ! -f "$config_path" ]; then + echo "**** Configuration file '$config_path' does not exist" + return + fi + + if [[ " ${masklist[@]} " =~ " $var_name " ]] && [ ! -z "$var_value" ]; then + echo -n "** Updating '$config_path' parameter \"$var_name\": '****'. Enable DEBUG_MODE to view value ..." + else + echo -n "** Updating '$config_path' parameter \"$var_name\": '$var_value'..." + fi + + # Remove configuration parameter definition in case of unset parameter value + if [ -z "$var_value" ]; then + sed -i -e "/^$var_name=/d" "$config_path" + echo "removed" + return + fi + + # Remove value from configuration parameter in case of double quoted parameter value + if [ "$var_value" == '""' ]; then + sed -i -e "/^$var_name=/s/=.*/=/" "$config_path" + echo "undefined" + return + fi + + # Use full path to a file for TLS related configuration parameters + if [[ $var_name =~ ^TLS.*File$ ]]; then + var_value=$ZABBIX_USER_HOME_DIR/enc/$var_value + fi + + # Escaping characters in parameter value and name + var_value=$(escape_spec_char "$var_value") + var_name=$(escape_spec_char "$var_name") + + if [ "$(grep -E "^$var_name=" $config_path)" ] && [ "$is_multiple" != "true" ]; then + sed -i -e "/^$var_name=/s/=.*/=$var_value/" "$config_path" + echo "updated" + elif [ "$(grep -Ec "^# $var_name=" $config_path)" -gt 1 ]; then + sed -i -e "/^[#;] $var_name=$/i\\$var_name=$var_value" "$config_path" + echo "added first occurrence" + else + sed -i -e "/^[#;] $var_name=/s/.*/&\n$var_name=$var_value/" "$config_path" + echo "added" + fi + +} + +update_config_multiple_var() { + local config_path=$1 + local var_name=$2 + local var_value=$3 + + var_value="${var_value%\"}" + var_value="${var_value#\"}" + + local IFS=, + local OPT_LIST=($var_value) + + for value in "${OPT_LIST[@]}"; do + update_config_var $config_path $var_name $value true + done +} + +# Check prerequisites for PostgreSQL database +check_variables_postgresql() { + file_env POSTGRES_USER + file_env POSTGRES_PASSWORD + + : ${DB_SERVER_HOST:="postgres-server"} + : ${DB_SERVER_PORT:="5432"} + + DB_SERVER_ROOT_USER=${POSTGRES_USER:-"postgres"} + DB_SERVER_ROOT_PASS=${POSTGRES_PASSWORD:-""} + + DB_SERVER_ZEUS_USER=${POSTGRES_USER:-"postgres"} + DB_SERVER_ZEUS_PASS=${POSTGRES_PASSWORD:-"postgres"} + + : ${DB_SERVER_SCHEMA:="public"} + + DB_SERVER_DBNAME=${POSTGRES_DB:-"zeus-iot"} + + : ${POSTGRES_USE_IMPLICIT_SEARCH_PATH:="false"} +} + +check_db_connect_postgresql() { + echo "********************" + echo "* DB_SERVER_HOST: ${DB_SERVER_HOST}" + echo "* DB_SERVER_PORT: ${DB_SERVER_PORT}" + echo "* DB_SERVER_DBNAME: ${DB_SERVER_DBNAME}" + echo "* DB_SERVER_SCHEMA: ${DB_SERVER_SCHEMA}" + if [ "${DEBUG_MODE,,}" == "true" ]; then + echo "* DB_SERVER_ZEUS_USER: ${DB_SERVER_ZEUS_USER}" + echo "* DB_SERVER_ZEUS_PASS: ${DB_SERVER_ZEUS_PASS}" + fi + echo "********************" + + if [ -n "${DB_SERVER_ZEUS_PASS}" ]; then + export PGPASSWORD="${DB_SERVER_ZEUS_PASS}" + fi + + WAIT_TIMEOUT=5 + + if [ "${POSTGRES_USE_IMPLICIT_SEARCH_PATH,,}" == "false" ] && [ -n "${DB_SERVER_SCHEMA}" ]; then + PGOPTIONS="--search_path=${DB_SERVER_SCHEMA}" + export PGOPTIONS + fi + + if [ -n "${ZEUS_DBTLSCONNECT}" ]; then + export PGSSLMODE=${ZEUS_DBTLSCONNECT//_/-} + export PGSSLROOTCERT=${ZEUS_DBTLSCAFILE} + export PGSSLCERT=${ZEUS_DBTLSCERTFILE} + export PGSSLKEY=${ZEUS_DBTLSKEYFILE} + fi + + while true : + do + psql --host ${DB_SERVER_HOST} --port ${DB_SERVER_PORT} --username ${DB_SERVER_ROOT_USER} --list --quiet 1>/dev/null 2>&1 && break + psql --host ${DB_SERVER_HOST} --port ${DB_SERVER_PORT} --username ${DB_SERVER_ROOT_USER} --list --dbname ${DB_SERVER_DBNAME} --quiet 1>/dev/null 2>&1 && break + + echo "**** PostgreSQL server is not available. Waiting $WAIT_TIMEOUT seconds..." + sleep $WAIT_TIMEOUT + done + + unset PGPASSWORD + unset PGOPTIONS + unset PGSSLMODE + unset PGSSLROOTCERT + unset PGSSLCERT + unset PGSSLKEY +} + +psql_query() { + query=$1 + db=$2 + + local result="" + + if [ -n "${DB_SERVER_ZBX_PASS}" ]; then + export PGPASSWORD="${DB_SERVER_ZBX_PASS}" + fi + + if [ "${POSTGRES_USE_IMPLICIT_SEARCH_PATH,,}" == "false" ] && [ -n "${DB_SERVER_SCHEMA}" ]; then + PGOPTIONS="--search_path=${DB_SERVER_SCHEMA}" + export PGOPTIONS + fi + + if [ -n "${ZBX_DBTLSCONNECT}" ]; then + export PGSSLMODE=${ZBX_DBTLSCONNECT//_/-} + export PGSSLROOTCERT=${ZBX_DBTLSCAFILE} + export PGSSLCERT=${ZBX_DBTLSCERTFILE} + export PGSSLKEY=${ZBX_DBTLSKEYFILE} + fi + + result=$(psql --no-align --quiet --tuples-only --host "${DB_SERVER_HOST}" --port "${DB_SERVER_PORT}" \ + --username "${DB_SERVER_ROOT_USER}" --command "$query" --dbname "$db" 2>/dev/null); + + unset PGPASSWORD + unset PGOPTIONS + unset PGSSLMODE + unset PGSSLROOTCERT + unset PGSSLCERT + unset PGSSLKEY + + echo $result +} + +create_db_database_postgresql() { + DB_EXISTS=$(psql_query "SELECT 1 AS result FROM pg_database WHERE datname='${DB_SERVER_DBNAME}'" "${DB_SERVER_DBNAME}") + + if [ -z ${DB_EXISTS} ]; then + echo "** Database '${DB_SERVER_DBNAME}' does not exist. Creating..." + + if [ -n "${DB_SERVER_ZEUS_PASS}" ]; then + export PGPASSWORD="${DB_SERVER_ZEUS_PASS}" + fi + + if [ "${POSTGRES_USE_IMPLICIT_SEARCH_PATH,,}" == "false" ] && [ -n "${DB_SERVER_SCHEMA}" ]; then + PGOPTIONS="--search_path=${DB_SERVER_SCHEMA}" + export PGOPTIONS + fi + + if [ -n "${ZBX_DBTLSCONNECT}" ]; then + export PGSSLMODE=${ZBX_DBTLSCONNECT//_/-} + export PGSSLROOTCERT=${ZBX_DBTLSCAFILE} + export PGSSLCERT=${ZBX_DBTLSCERTFILE} + export PGSSLKEY=${ZBX_DBTLSKEYFILE} + fi + + createdb --host "${DB_SERVER_HOST}" --port "${DB_SERVER_PORT}" --username "${DB_SERVER_ROOT_USER}" \ + --owner "${DB_SERVER_ZEUS_USER}" "${DB_SERVER_DBNAME}" + + unset PGPASSWORD + unset PGOPTIONS + unset PGSSLMODE + unset PGSSLROOTCERT + unset PGSSLCERT + unset PGSSLKEY + else + echo "** Database '${DB_SERVER_DBNAME}' already exists. Please be careful with database owner!" + fi + + psql_query "CREATE SCHEMA IF NOT EXISTS ${DB_SERVER_SCHEMA}" "${DB_SERVER_DBNAME}" 1>/dev/null +} + +create_db_schema_postgresql() { + DBVERSION_TABLE_EXISTS=$(psql_query "SELECT 1 FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = + c.relnamespace WHERE n.nspname = '$DB_SERVER_SCHEMA' AND c.relname = 'dbversion'" "${DB_SERVER_DBNAME}") + + if [ -n "${DBVERSION_TABLE_EXISTS}" ]; then + echo "** Table '${DB_SERVER_DBNAME}.dbversion' already exists." + ZEUS_DB_VERSION=$(psql_query "SELECT mandatory FROM ${DB_SERVER_SCHEMA}.dbversion" "${DB_SERVER_DBNAME}") + fi + + if [ -z "${ZEUS_DB_VERSION}" ]; then + echo "** Creating '${DB_SERVER_DBNAME}' schema in PostgreSQL" + + if [ "${ENABLE_TIMESCALEDB,,}" == "true" ]; then + psql_query "CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;" "${DB_SERVER_DBNAME}" + fi + + if [ -n "${DB_SERVER_ZEUS_PASS}" ]; then + export PGPASSWORD="${DB_SERVER_ZBX_PASS}" + fi + + if [ "${POSTGRES_USE_IMPLICIT_SEARCH_PATH,,}" == "false" ] && [ -n "${DB_SERVER_SCHEMA}" ]; then + PGOPTIONS="--search_path=${DB_SERVER_SCHEMA}" + export PGOPTIONS + fi + + if [ -n "${ZBX_DBTLSCONNECT}" ]; then + export PGSSLMODE=${ZBX_DBTLSCONNECT//_/-} + export PGSSLROOTCERT=${ZBX_DBTLSCAFILE} + export PGSSLCERT=${ZBX_DBTLSCERTFILE} + export PGSSLKEY=${ZBX_DBTLSKEYFILE} + fi + + cat /zeus-iot-bin/bin/sql/zeus-iot.sql | psql --quiet \ + --host "${DB_SERVER_HOST}" --port "${DB_SERVER_PORT}" \ + --username "${DB_SERVER_ZEUS_USER}" --dbname "${DB_SERVER_DBNAME}" 1>/dev/null || exit 1 + + unset PGPASSWORD + unset PGOPTIONS + unset PGSSLMODE + unset PGSSLROOTCERT + unset PGSSLCERT + unset PGSSLKEY + fi +} + + +prepare_server() { + echo "** Preparing Zeus IoT Server" + + check_variables_postgresql + check_db_connect_postgresql + create_db_database_postgresql + create_db_schema_postgresql + +} + +################################################# +startiot() { + + [ -z "$IOT_HOME" ] && IOT_HOME=/zeus-iot-bin + JAVA_OPTS="${JAVA_OPTS:- -Xms256M -Xmx512M}" + _RUNJAVA=${JAVA_HOME}/bin/java + [ -z "$JAVA_HOME" ] && _RUNJAVA=java + + CLASSPATH="$IOT_HOME/config" + for i in "$IOT_HOME"/iot-server-libs/*.jar + do + CLASSPATH="$i:$CLASSPATH" + done + + IOT_OPTIONS=" -Duser.timezone=GMT+08" + + eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${IOT_OPTIONS} -classpath $CLASSPATH com.zmops.zeus.iot.server.starter.IoTServerStartUp &> /dev/stdout &" +} + +startwebapp() { + + [ -z "$WEBAPP_HOME" ] && WEBAPP_HOME=/zeus-iot-bin + + JAVA_OPTS="${JAVA_OPTS:- -Xms512M -Xmx1024M}" + JAR_PATH="${WEBAPP_HOME}/webapp" + + _RUNJAVA=${JAVA_HOME}/bin/java + [ -z "$JAVA_HOME" ] && _RUNJAVA=java + + sed -i "s%\(zbxApiToken: \).*%\1${ZBXAPITOKEN}%g" ${JAR_PATH}/webapp.yml + + eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} -jar ${JAR_PATH}/zeus-webapp.jar \ + --spring.config.location=${JAR_PATH}/webapp.yml" + +} + + +prepare_server +startiot +startwebapp + +################################################# diff --git a/docker/dockerfile b/docker/dockerfile new file mode 100644 index 00000000..1c96108f --- /dev/null +++ b/docker/dockerfile @@ -0,0 +1,18 @@ +FROM alpine:latest + +RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories + +RUN apk update \ + && apk add --no-cache tzdata openjdk8-jre bash postgresql-client \ + && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ + && echo Asia/Shanghai > /etc/timezone \ + && rm -rf /var/cache/apk/* + +ADD https://packages.zmops.cn/zeus-iot/zeus-iot-bin.tar.gz / +RUN tar -xf zeus-iot-bin.tar.gz +COPY log4j2.xml /zeus-iot-bin/config/log4j2.xml +COPY docker-entrypoint.sh /usr/bin/docker-entrypoint.sh +EXPOSE 9090 9080 12800 +ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"] + + diff --git a/docker/log4j2.xml b/docker/log4j2.xml new file mode 100644 index 00000000..ddb7b819 --- /dev/null +++ b/docker/log4j2.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + From f7a9a338c39b5e87ff9f3bee14c0ba2acce500b7 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 3 Nov 2021 17:14:55 +0800 Subject: [PATCH 612/763] [feat]: add scene execute --- .../MultipleDeviceEventTriggerController.java | 6 ++ .../MultipleDeviceEventRuleService.java | 60 ++++++++++++++++++- .../web/event/service/SceneEventProcess.java | 54 ++--------------- 3 files changed, 68 insertions(+), 52 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java index ed6df160..341a8c40 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java @@ -226,4 +226,10 @@ public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseE return ResponseData.success(); } + @RequestMapping("/execute") + public ResponseData execute(@RequestParam("eventRuleId") Long eventRuleId){ + multipleDeviceEventRuleService.execute(eventRuleId); + return ResponseData.success(); + } + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index cb702ff4..da45102a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -3,9 +3,10 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.domain.product.ProductEvent; -import com.zmops.iot.domain.product.ProductEventExpression; -import com.zmops.iot.domain.product.ProductEventRelation; +import com.dtflys.forest.Forest; +import com.zmops.iot.async.executor.Async; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.domain.product.*; import com.zmops.iot.domain.product.query.QProductEvent; import com.zmops.iot.domain.product.query.QProductEventExpression; import com.zmops.iot.domain.product.query.QProductEventRelation; @@ -14,12 +15,15 @@ import com.zmops.iot.enums.InheritStatus; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceEventRelationDto; import com.zmops.iot.web.device.dto.MultipleDeviceEventDto; import com.zmops.iot.web.device.dto.MultipleDeviceEventRule; import com.zmops.iot.web.device.dto.MultipleDeviceServiceDto; import com.zmops.iot.web.device.dto.param.MultipleDeviceEventParm; +import com.zmops.iot.web.device.service.work.DeviceServiceLogWorker; +import com.zmops.iot.web.device.service.work.ScenesLogWorker; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductEventRuleDto; import com.zmops.zeus.driver.service.ZbxTrigger; @@ -32,6 +36,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; /** @@ -43,6 +48,11 @@ public class MultipleDeviceEventRuleService { @Autowired private ZbxTrigger zbxTrigger; + @Autowired + DeviceServiceLogWorker deviceServiceLogWorker; + + @Autowired + ScenesLogWorker scenesLogWorker; /** * 设备联动 分页列表 * @@ -332,6 +342,50 @@ public String[] updateZbxTrigger(String triggerId, String expression, Byte level return JSON.parseObject(res, TriggerIds.class).getTriggerids(); } + public void execute(Long eventRuleId) { + Map alarmInfo = new ConcurrentHashMap<>(3); + alarmInfo.put("eventRuleId", eventRuleId); + + WorkerWrapper, Boolean> deviceServiceLogWork = WorkerWrapper., Boolean>builder().id("deviceServiceLogWorker") + .worker(deviceServiceLogWorker).param(alarmInfo) + .build(); + WorkerWrapper, Boolean> scenesLogWork = WorkerWrapper., Boolean>builder().id("scenesLogWorker") + .worker(scenesLogWorker).param(alarmInfo) + .build(); + + try { + Async.work(1000, deviceServiceLogWork, scenesLogWork).awaitFinish(); + } catch (Exception e) { + e.printStackTrace(); + } + + List productEventServiceList = new QProductEventService().eventRuleId.eq(eventRuleId) + .deviceId.isNull().findList(); + List> list = new ArrayList<>(); + Map> collect = productEventServiceList.parallelStream().collect(Collectors.groupingBy(ProductEventService::getExecuteDeviceId)); + + collect.forEach((key, value) -> { + Map map = new ConcurrentHashMap<>(); + map.put("device", key); + + List> serviceList = new ArrayList<>(); + value.forEach(val -> { + Map serviceMap = new ConcurrentHashMap<>(); + serviceMap.put("name", DefinitionsUtil.getServiceName(val.getServiceId())); + + List paramList = DefinitionsUtil.getServiceParam(val.getServiceId()); + if (ToolUtil.isNotEmpty(paramList)) { + serviceMap.put("param", paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue))); + } + serviceList.add(serviceMap); + }); + map.put("service", serviceList); + list.add(map); + }); + + Forest.post("/device/action/exec").host("127.0.0.1").port(12800).contentTypeJson().addBody(JSON.toJSON(list)).execute(); + } + @Data static class TriggerIds { private String[] triggerids; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java index 09faf9a9..8d4e3765 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java @@ -9,6 +9,7 @@ import com.zmops.iot.domain.product.query.QProductEventService; import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.service.MultipleDeviceEventRuleService; import com.zmops.iot.web.device.service.work.DeviceServiceLogWorker; import com.zmops.iot.web.device.service.work.ScenesLogWorker; import com.zmops.iot.web.event.EventProcess; @@ -31,62 +32,17 @@ public class SceneEventProcess implements EventProcess { @Autowired - DeviceServiceLogWorker deviceServiceLogWorker; - - @Autowired - ScenesLogWorker scenesLogWorker; + MultipleDeviceEventRuleService eventRuleService; @Override public void process(EventDataDto eventData) { - log.debug("--------scene event----------{}", eventData.getObjectid()); - Map alarmInfo = new ConcurrentHashMap<>(3); + log.debug("--------scene event----------ruleId:{}", eventData.getName()); - String productEventRuleId = eventData.getName(); - if (ToolUtil.isEmpty(productEventRuleId)) { + if (ToolUtil.isEmpty(eventData.getName())) { return; } - long eventRuleId = Long.parseLong(productEventRuleId); - - alarmInfo.put("eventRuleId", eventRuleId); - - WorkerWrapper, Boolean> deviceServiceLogWork = WorkerWrapper., Boolean>builder().id("deviceServiceLogWorker") - .worker(deviceServiceLogWorker).param(alarmInfo) - .build(); - WorkerWrapper, Boolean> scenesLogWork = WorkerWrapper., Boolean>builder().id("scenesLogWorker") - .worker(scenesLogWorker).param(alarmInfo) - .build(); - - try { - Async.work(1000, deviceServiceLogWork, scenesLogWork).awaitFinish(); - } catch (Exception e) { - e.printStackTrace(); - } - - List productEventServiceList = new QProductEventService().eventRuleId.eq(eventRuleId) - .deviceId.isNull().findList(); - List> list = new ArrayList<>(); - Map> collect = productEventServiceList.parallelStream().collect(Collectors.groupingBy(ProductEventService::getExecuteDeviceId)); - - collect.forEach((key, value) -> { - Map map = new ConcurrentHashMap<>(); - map.put("device", key); - - List> serviceList = new ArrayList<>(); - value.forEach(val -> { - Map serviceMap = new ConcurrentHashMap<>(); - serviceMap.put("name", DefinitionsUtil.getServiceName(val.getServiceId())); - - List paramList = DefinitionsUtil.getServiceParam(val.getServiceId()); - if (ToolUtil.isNotEmpty(paramList)) { - serviceMap.put("param", paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue))); - } - serviceList.add(serviceMap); - }); - map.put("service", serviceList); - list.add(map); - }); - Forest.post("/device/action/exec").host("127.0.0.1").port(12800).contentTypeJson().addBody(JSON.toJSON(list)).execute(); + eventRuleService.execute(Long.parseLong(eventData.getName())); } @Override From a91aa02bea24cf0fc3a6792d2a08a619416f4ffb Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 3 Nov 2021 20:58:38 +0800 Subject: [PATCH 613/763] [feat]: global view add scene trigger num --- .../java/com/zmops/iot/web/analyse/service/HomeService.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index 65d67ef4..504eb71e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -11,6 +11,7 @@ import com.zmops.iot.domain.device.ServiceExecuteRecord; import com.zmops.iot.domain.device.query.QDeviceOnlineReport; import com.zmops.iot.domain.device.query.QEventTriggerRecord; +import com.zmops.iot.domain.device.query.QScenesTriggerRecord; import com.zmops.iot.domain.device.query.QServiceExecuteRecord; import com.zmops.iot.domain.product.query.QProduct; import com.zmops.iot.enums.SeverityEnum; @@ -374,6 +375,9 @@ public Map dataLevel() { int serviceExecuteNum = new QServiceExecuteRecord().findCount(); dataMap.put("serviceExecuteNum", ParseUtil.getCommaFormat(serviceExecuteNum + "")); + int sceneTriggerNum = new QScenesTriggerRecord().findCount(); + dataMap.put("sceneTriggerNum", ParseUtil.getCommaFormat(sceneTriggerNum + "")); + return dataMap; } From 617b876f93ac9f66d2c946daa57cfa10c71bb2ea Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 4 Nov 2021 16:16:07 +0800 Subject: [PATCH 614/763] [feat]:add rest api --- .../rest/DeviceStatusWebhookController.java | 19 -------- .../rest/controller/AlarmRestController.java | 30 +++++++++++++ .../controller/DeviceLogRestController.java | 32 ++++++++++++++ .../rest/controller/DeviceRestController.java | 44 +++++++++++++++++++ .../rest/controller/LoginRestController.java | 31 +++++++++++++ .../controller/ProductRestController.java | 16 +++++++ .../rest/controller/SceneRestController.java | 16 +++++++ .../iot/rest/service/DeviceRestService.java | 13 ++++++ .../iot/rest/service/ProductRestService.java | 13 ++++++ .../iot/rest/service/SceneRestService.java | 13 ++++++ 10 files changed, 208 insertions(+), 19 deletions(-) delete mode 100644 zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java create mode 100644 zeus-rest/src/main/java/com/zmops/iot/rest/controller/AlarmRestController.java create mode 100644 zeus-rest/src/main/java/com/zmops/iot/rest/controller/DeviceLogRestController.java create mode 100644 zeus-rest/src/main/java/com/zmops/iot/rest/controller/DeviceRestController.java create mode 100644 zeus-rest/src/main/java/com/zmops/iot/rest/controller/LoginRestController.java create mode 100644 zeus-rest/src/main/java/com/zmops/iot/rest/controller/ProductRestController.java create mode 100644 zeus-rest/src/main/java/com/zmops/iot/rest/controller/SceneRestController.java create mode 100644 zeus-rest/src/main/java/com/zmops/iot/rest/service/DeviceRestService.java create mode 100644 zeus-rest/src/main/java/com/zmops/iot/rest/service/ProductRestService.java create mode 100644 zeus-rest/src/main/java/com/zmops/iot/rest/service/SceneRestService.java diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java deleted file mode 100644 index 9a6dbc21..00000000 --- a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.zmops.iot.rest; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author nantian created at 2021/8/7 14:56 - *

- * 设备在线状态 回调接口 - */ - -@RestController -@RequestMapping("/device") -@Slf4j -public class DeviceStatusWebhookController { - - -} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/controller/AlarmRestController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/AlarmRestController.java new file mode 100644 index 00000000..fd8b5057 --- /dev/null +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/AlarmRestController.java @@ -0,0 +1,30 @@ +package com.zmops.iot.rest.controller; + +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.device.dto.param.DeviceParams; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + *

+ * 告警记录接口 + **/ +@RestController +@RequestMapping("/rest/alarm") +public class AlarmRestController { + + /** + * 告警列表 + * + * @return + */ + @PostMapping("/list") + public ResponseData deviceList(@RequestBody DeviceParams deviceParams) { + + return ResponseData.success(); + } + +} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/controller/DeviceLogRestController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/DeviceLogRestController.java new file mode 100644 index 00000000..710d7124 --- /dev/null +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/DeviceLogRestController.java @@ -0,0 +1,32 @@ +package com.zmops.iot.rest.controller; + +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.web.device.dto.param.DeviceParam; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + *

+ * 设备日志接口 + **/ +@RestController +@RequestMapping("/rest/deviceLog") +public class DeviceLogRestController { + + /** + * 服务日志分页列表 + * + * @return + */ + @PostMapping("/getDeviceByPage") + public Pager devicePageList(@RequestBody DeviceParam deviceParam) { + + return new Pager<>(); + } + + +} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/controller/DeviceRestController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/DeviceRestController.java new file mode 100644 index 00000000..0f848991 --- /dev/null +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/DeviceRestController.java @@ -0,0 +1,44 @@ +package com.zmops.iot.rest.controller; + +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.device.dto.param.DeviceParam; +import com.zmops.iot.web.device.dto.param.DeviceParams; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + *

+ * 设备接口 + **/ +@RestController +@RequestMapping("/rest/device") +public class DeviceRestController { + + /** + * 设备分页列表 + * + * @return + */ + @PostMapping("/getDeviceByPage") + public Pager devicePageList(@RequestBody DeviceParam deviceParam) { + + return new Pager<>(); + } + + /** + * 设备列表 + * + * @return + */ + @PostMapping("/list") + public ResponseData deviceList(@RequestBody DeviceParams deviceParams) { + + return ResponseData.success(); + } + +} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/controller/LoginRestController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/LoginRestController.java new file mode 100644 index 00000000..da0f470b --- /dev/null +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/LoginRestController.java @@ -0,0 +1,31 @@ +package com.zmops.iot.rest.controller; + +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.device.dto.param.DeviceParams; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + *

+ * 登录接口 + **/ +@RestController +@RequestMapping("/rest/login") +public class LoginRestController { + + + /** + * 登录 + * + * @return + */ + @PostMapping("/list") + public ResponseData deviceList(@RequestBody DeviceParams deviceParams) { + + return ResponseData.success(); + } + +} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/controller/ProductRestController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/ProductRestController.java new file mode 100644 index 00000000..4c1c3174 --- /dev/null +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/ProductRestController.java @@ -0,0 +1,16 @@ +package com.zmops.iot.rest.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + * + * 产品接口 + **/ +@RestController +@RequestMapping("/rest/product") +public class ProductRestController { + + +} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/controller/SceneRestController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/SceneRestController.java new file mode 100644 index 00000000..dfa31824 --- /dev/null +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/SceneRestController.java @@ -0,0 +1,16 @@ +package com.zmops.iot.rest.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + *

+ * 场景接口 + **/ +@RestController +@RequestMapping("/rest/scene") +public class SceneRestController { + + +} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/service/DeviceRestService.java b/zeus-rest/src/main/java/com/zmops/iot/rest/service/DeviceRestService.java new file mode 100644 index 00000000..29df4e89 --- /dev/null +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/service/DeviceRestService.java @@ -0,0 +1,13 @@ +package com.zmops.iot.rest.service; + +import org.springframework.stereotype.Service; + +/** + * @author yefei + * + * 设备 rest 服务 + **/ +@Service +public class DeviceRestService { + +} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/service/ProductRestService.java b/zeus-rest/src/main/java/com/zmops/iot/rest/service/ProductRestService.java new file mode 100644 index 00000000..66f43755 --- /dev/null +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/service/ProductRestService.java @@ -0,0 +1,13 @@ +package com.zmops.iot.rest.service; + +import org.springframework.stereotype.Service; + +/** + * @author yefei + * + * 产品 rest 服务 + **/ +@Service +public class ProductRestService { + +} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/service/SceneRestService.java b/zeus-rest/src/main/java/com/zmops/iot/rest/service/SceneRestService.java new file mode 100644 index 00000000..284ca906 --- /dev/null +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/service/SceneRestService.java @@ -0,0 +1,13 @@ +package com.zmops.iot.rest.service; + +import org.springframework.stereotype.Service; + +/** + * @author yefei + * + * 场景 rest 服务 + **/ +@Service +public class SceneRestService { + +} From 76ab8c34b7c8f2df52e279b9bd3c2a2fe4f237fb Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 4 Nov 2021 16:44:44 +0800 Subject: [PATCH 615/763] [fix]:fix zbx url config --- .../com/zmops/zeus/driver/service/ZbxApiInfo.java | 2 +- .../zeus/driver/service/ZbxDeviceStatusTrigger.java | 2 +- .../com/zmops/zeus/driver/service/ZbxHistoryGet.java | 2 +- .../java/com/zmops/zeus/driver/service/ZbxHost.java | 2 +- .../com/zmops/zeus/driver/service/ZbxHostGroup.java | 2 +- .../zmops/zeus/driver/service/ZbxInitService.java | 12 ++++++------ .../java/com/zmops/zeus/driver/service/ZbxItem.java | 2 +- .../java/com/zmops/zeus/driver/service/ZbxMacro.java | 2 +- .../com/zmops/zeus/driver/service/ZbxProblem.java | 2 +- .../com/zmops/zeus/driver/service/ZbxTemplate.java | 2 +- .../com/zmops/zeus/driver/service/ZbxTrigger.java | 2 +- .../java/com/zmops/zeus/driver/service/ZbxUser.java | 2 +- .../com/zmops/zeus/driver/service/ZbxUserGroup.java | 2 +- .../com/zmops/zeus/driver/service/ZbxValueMap.java | 2 +- zeus-starter/src/main/resources/application.yaml | 3 ++- 15 files changed, 21 insertions(+), 20 deletions(-) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxApiInfo.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxApiInfo.java index 5458badc..5c9ca0f6 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxApiInfo.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxApiInfo.java @@ -10,7 +10,7 @@ */ @BaseRequest( - baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxApiInfo { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java index 052fd31c..d2784e7b 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java @@ -12,7 +12,7 @@ * 设备离线 在线触发器,判断设备 在线,离线 状态 */ @BaseRequest( - baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxDeviceStatusTrigger { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java index f092c7b4..a530608a 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java @@ -13,7 +13,7 @@ */ @BaseRequest( - baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxHistoryGet { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java index aa1c41a3..8f95dcab 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java @@ -16,7 +16,7 @@ * 主机驱动 */ @BaseRequest( - baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxHost { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java index da222487..22b11d98 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java @@ -13,7 +13,7 @@ */ @BaseRequest( - baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxHostGroup { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java index 71e07216..0e017377 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java @@ -12,7 +12,7 @@ public interface ZbxInitService { @Post( - url = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + url = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", headers = "authTag: noAuth", interceptor = JsonBodyBuildInterceptor.class ) @@ -20,7 +20,7 @@ public interface ZbxInitService { String createCookieUserGroup(@ParamName("hostGroupId") String hostGroupId, @ParamName("userAuth") String userAuth); @Post( - url = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + url = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", headers = "authTag: noAuth", interceptor = JsonBodyBuildInterceptor.class ) @@ -28,7 +28,7 @@ public interface ZbxInitService { String getCookieUserGroup(@ParamName("userAuth") String userAuth); @Post( - url = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + url = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", headers = "authTag: noAuth", interceptor = JsonBodyBuildInterceptor.class ) @@ -36,7 +36,7 @@ public interface ZbxInitService { String getCookieUser(@ParamName("userAuth") String userAuth); @Post( - url = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + url = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", headers = "authTag: noAuth", interceptor = JsonBodyBuildInterceptor.class ) @@ -46,7 +46,7 @@ String createCookieUser(@ParamName("usrGrpId") String usrGrpId, @ParamName("roleId") String roleId); @Post( - url = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + url = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", headers = "authTag: noAuth", interceptor = JsonBodyBuildInterceptor.class ) @@ -54,7 +54,7 @@ String createCookieUser(@ParamName("usrGrpId") String usrGrpId, String getAdminRole(@ParamName("userAuth") String zbxApiToken); @Post( - url = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + url = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", headers = "authTag: noAuth", interceptor = JsonBodyBuildInterceptor.class ) diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java index c84e34b4..03ece8e2 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java @@ -15,7 +15,7 @@ */ @BaseRequest( - baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxItem { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java index 15fc6cac..bbe05cbc 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java @@ -13,7 +13,7 @@ * 宏定义接口 */ @BaseRequest( - baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxMacro { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java index 9d494ded..10bc1c01 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java @@ -10,7 +10,7 @@ * @author nantian created at 2021/8/7 23:27 */ -@BaseRequest(baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", interceptor = JsonBodyBuildInterceptor.class) +@BaseRequest(baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", interceptor = JsonBodyBuildInterceptor.class) public interface ZbxProblem { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java index 7b192615..f5ed77aa 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java @@ -13,7 +13,7 @@ */ @BaseRequest( - baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxTemplate { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java index e3948890..bccf3b38 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java @@ -10,7 +10,7 @@ import java.util.Map; @BaseRequest( - baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxTrigger { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java index ccc21bc0..cff9626f 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java @@ -15,7 +15,7 @@ */ @BaseRequest( - baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxUser { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java index 39f943bc..4694c9bf 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java @@ -15,7 +15,7 @@ */ @BaseRequest( - baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxUserGroup { diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxValueMap.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxValueMap.java index e0ec1ecc..0517bfcb 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxValueMap.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxValueMap.java @@ -14,7 +14,7 @@ * 值映射设置 */ @BaseRequest( - baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", interceptor = JsonBodyBuildInterceptor.class ) public interface ZbxValueMap { diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index 1abbbfe7..35b4e46b 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -47,7 +47,8 @@ forest: ## Zabbix API IP And ServerIp and ServerPort zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:80} - zbxApiToken: 897e588c32f780f7134457e409ff37e84ea966ee20712dfacd22c8a968ce94d6 + zbxApiUrl: ${ZEUS_ZABBIX_API_URL:/zabbix/api_jsonrpc.php} + zbxApiToken: 28345fb4147761a6e955e7c3aada52fe032678fe8360f131f5acc7a25b8af755 ## tdengine http request address taosUrl: http://${ZEUS_TAOS_HOST:127.0.0.1}:${ZEUS_TAOS_REST_PORT:6041}/rest/sql/zeus_data From afa6ed67939733666f1ec568bd4e01783abb780f Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 4 Nov 2021 17:03:30 +0800 Subject: [PATCH 616/763] [fix]: fix zbx url config --- zeus-starter/src/main/assembly/webapp.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/zeus-starter/src/main/assembly/webapp.yml b/zeus-starter/src/main/assembly/webapp.yml index 450d0a01..650e57c8 100644 --- a/zeus-starter/src/main/assembly/webapp.yml +++ b/zeus-starter/src/main/assembly/webapp.yml @@ -48,6 +48,7 @@ forest: ## Zabbix API IP And ServerIp and ServerPort zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:80} + zbxApiUrl: ${ZEUS_ZABBIX_API_URL:/zabbix/api_jsonrpc.php} zbxApiToken: 3464dee6b3fa3ce4173972e0497d7b84a93bdf8477ff1bdd51a7719cc0db2cd9 ## tdengine http request address From 386140c9f3acbcc7b889e7cee4a391005f8c0723 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 4 Nov 2021 21:53:09 +0800 Subject: [PATCH 617/763] [feat]: scene log add trigger type --- .../iot/domain/device/ScenesTriggerRecord.java | 3 +++ .../domain/device/ServiceExecuteRecord.java | 6 ++++++ .../MultipleDeviceEventTriggerController.java | 7 +++---- .../MultipleDeviceEventRuleService.java | 6 +++++- .../service/work/DeviceServiceLogWorker.java | 6 ++++++ .../device/service/work/ScenesLogWorker.java | 7 +++++++ .../web/event/service/SceneEventProcess.java | 18 +----------------- .../web/event/service/ServiceEventProcess.java | 5 +---- 8 files changed, 32 insertions(+), 26 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/ScenesTriggerRecord.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/ScenesTriggerRecord.java index eae448f4..f71fd097 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/ScenesTriggerRecord.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/ScenesTriggerRecord.java @@ -23,4 +23,7 @@ public class ScenesTriggerRecord { private Long ruleId; + private String triggerType; + + private Long triggerUser; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/ServiceExecuteRecord.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/ServiceExecuteRecord.java index 4bcf4936..91114ffc 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/ServiceExecuteRecord.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/ServiceExecuteRecord.java @@ -27,4 +27,10 @@ public class ServiceExecuteRecord { private String deviceId; private String param; + + private String executeType; + + private Long executeUser; + + private Long executeRuleId; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java index 341a8c40..427652fc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java @@ -2,6 +2,7 @@ import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.ProductEventRelation; @@ -10,7 +11,6 @@ import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventService; import com.zmops.iot.enums.CommonStatus; -import com.zmops.iot.enums.InheritStatus; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; @@ -27,7 +27,6 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -227,8 +226,8 @@ public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseE } @RequestMapping("/execute") - public ResponseData execute(@RequestParam("eventRuleId") Long eventRuleId){ - multipleDeviceEventRuleService.execute(eventRuleId); + public ResponseData execute(@RequestParam("eventRuleId") Long eventRuleId) { + multipleDeviceEventRuleService.execute(eventRuleId, "手动", LoginContextHolder.getContext().getUser().getId()); return ResponseData.success(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index da45102a..d0028e68 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -6,6 +6,7 @@ import com.dtflys.forest.Forest; import com.zmops.iot.async.executor.Async; import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.domain.product.*; import com.zmops.iot.domain.product.query.QProductEvent; import com.zmops.iot.domain.product.query.QProductEventExpression; @@ -53,6 +54,7 @@ public class MultipleDeviceEventRuleService { @Autowired ScenesLogWorker scenesLogWorker; + /** * 设备联动 分页列表 * @@ -342,9 +344,11 @@ public String[] updateZbxTrigger(String triggerId, String expression, Byte level return JSON.parseObject(res, TriggerIds.class).getTriggerids(); } - public void execute(Long eventRuleId) { + public void execute(Long eventRuleId,String type,Long userId) { Map alarmInfo = new ConcurrentHashMap<>(3); alarmInfo.put("eventRuleId", eventRuleId); + alarmInfo.put("triggerType", type); + alarmInfo.put("triggerUser", userId); WorkerWrapper, Boolean> deviceServiceLogWork = WorkerWrapper., Boolean>builder().id("deviceServiceLogWorker") .worker(deviceServiceLogWorker).param(alarmInfo) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java index 3bb70a56..95a363eb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java @@ -37,6 +37,8 @@ public Boolean action(Map param, Map log.debug("insert into service log…………"); long eventRuleId = (long) param.get("eventRuleId"); + String executeType = (String) param.get("triggerType"); + Long executeUser = Optional.ofNullable(param.get("triggerUser")).map(Object::toString).map(Long::parseLong).orElse(null); List productEventServiceList = new QProductEventService().eventRuleId.eq(eventRuleId).findList(); List serviceIds = productEventServiceList.parallelStream().map(ProductEventService::getServiceId).collect(Collectors.toList()); @@ -54,6 +56,10 @@ public Boolean action(Map param, Map } serviceExecuteRecord.setServiceName(Optional.ofNullable(productServiceMap.get(productEventService.getServiceId())).map(ProductService::getName).orElse("")); serviceExecuteRecord.setCreateTime(LocalDateTime.now()); + serviceExecuteRecord.setExecuteRuleId(eventRuleId); + serviceExecuteRecord.setExecuteType(executeType); + serviceExecuteRecord.setExecuteUser(executeUser); + serviceExecuteRecordList.add(serviceExecuteRecord); }); DB.saveAll(serviceExecuteRecordList); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java index bfc8c831..6fdd18cc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java @@ -12,6 +12,7 @@ import java.time.LocalDateTime; import java.util.Map; +import java.util.Optional; /** * @author yefei @@ -27,6 +28,9 @@ public Boolean action(Map param, Map log.debug("insert into ScenesLogWorker…………"); long eventRuleId = (long) param.get("eventRuleId"); + String triggerType = (String) param.get("triggerType"); + Long triggerUser = Optional.ofNullable(param.get("triggerUser")).map(Object::toString).map(Long::parseLong).orElse(null); + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRuleId).findOne(); if (productEvent == null) { return true; @@ -35,6 +39,9 @@ public Boolean action(Map param, Map scenesTriggerRecord.setRuleId(eventRuleId); scenesTriggerRecord.setRuleName(productEvent.getEventRuleName()); scenesTriggerRecord.setCreateTime(LocalDateTime.now()); + scenesTriggerRecord.setTriggerType(triggerType); + scenesTriggerRecord.setTriggerUser(triggerUser); + DB.save(scenesTriggerRecord); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java index 8d4e3765..d6ca6681 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java @@ -1,29 +1,13 @@ package com.zmops.iot.web.event.service; -import com.alibaba.fastjson.JSON; -import com.dtflys.forest.Forest; -import com.zmops.iot.async.executor.Async; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.product.ProductEventService; -import com.zmops.iot.domain.product.ProductServiceParam; -import com.zmops.iot.domain.product.query.QProductEventService; -import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.service.MultipleDeviceEventRuleService; -import com.zmops.iot.web.device.service.work.DeviceServiceLogWorker; -import com.zmops.iot.web.device.service.work.ScenesLogWorker; import com.zmops.iot.web.event.EventProcess; import com.zmops.iot.web.event.dto.EventDataDto; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - /** * @author yefei **/ @@ -42,7 +26,7 @@ public void process(EventDataDto eventData) { return; } - eventRuleService.execute(Long.parseLong(eventData.getName())); + eventRuleService.execute(Long.parseLong(eventData.getName()), "自动", null); } @Override diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java index cc3128bc..b140ecec 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java @@ -12,7 +12,6 @@ import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.service.work.DeviceServiceLogWorker; -import com.zmops.iot.web.device.service.work.ScenesLogWorker; import com.zmops.iot.web.event.EventProcess; import com.zmops.iot.web.event.dto.EventDataDto; import lombok.extern.slf4j.Slf4j; @@ -35,9 +34,6 @@ public class ServiceEventProcess implements EventProcess { @Autowired DeviceServiceLogWorker deviceServiceLogWorker; - @Autowired - ScenesLogWorker scenesLogWorker; - @Override public void process(EventDataDto eventData) { log.debug("--------service event----------{}", eventData.getObjectid()); @@ -50,6 +46,7 @@ public void process(EventDataDto eventData) { alarmInfo.put("eventRuleId", productEventRelationList.get(0).getEventRuleId()); alarmInfo.put("relationId", productEventRelationList.get(0).getRelationId()); + alarmInfo.put("triggerType", "自动"); WorkerWrapper, Boolean> deviceServiceLogWork = WorkerWrapper., Boolean>builder().id("deviceServiceLogWorker") .worker(deviceServiceLogWorker).param(alarmInfo) From 363a904eb97908724d7999d86431d4f73f32caf2 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 5 Nov 2021 10:09:30 +0800 Subject: [PATCH 618/763] [fix]: fix bug --- .../web/device/service/MultipleDeviceEventRuleService.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index d0028e68..cc2d5786 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -6,7 +6,6 @@ import com.dtflys.forest.Forest; import com.zmops.iot.async.executor.Async; import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.domain.product.*; import com.zmops.iot.domain.product.query.QProductEvent; import com.zmops.iot.domain.product.query.QProductEventExpression; @@ -344,11 +343,13 @@ public String[] updateZbxTrigger(String triggerId, String expression, Byte level return JSON.parseObject(res, TriggerIds.class).getTriggerids(); } - public void execute(Long eventRuleId,String type,Long userId) { + public void execute(Long eventRuleId, String type, Long userId) { Map alarmInfo = new ConcurrentHashMap<>(3); alarmInfo.put("eventRuleId", eventRuleId); alarmInfo.put("triggerType", type); - alarmInfo.put("triggerUser", userId); + if (null != userId) { + alarmInfo.put("triggerUser", userId); + } WorkerWrapper, Boolean> deviceServiceLogWork = WorkerWrapper., Boolean>builder().id("deviceServiceLogWorker") .worker(deviceServiceLogWorker).param(alarmInfo) From 9392573ecbb130584b6d79cfa92485ca05de2dfe Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 5 Nov 2021 17:47:49 +0800 Subject: [PATCH 619/763] [fix]: fix scene execute validate --- .../controller/MultipleDeviceEventTriggerController.java | 4 ++++ .../com/zmops/iot/web/exception/enums/BizExceptionEnum.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java index 427652fc..007e6534 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java @@ -227,6 +227,10 @@ public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseE @RequestMapping("/execute") public ResponseData execute(@RequestParam("eventRuleId") Long eventRuleId) { + int count = new QProductEvent().eventRuleId.eq(eventRuleId).classify.eq("1").findCount(); + if (count <= 0) { + throw new ServiceException(BizExceptionEnum.SCENE_NOT_EXISTS); + } multipleDeviceEventRuleService.execute(eventRuleId, "手动", LoginContextHolder.getContext().getUser().getId()); return ResponseData.success(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index 50dcf9f3..ba48f9d2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -168,7 +168,7 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { EVENT_EXPRESSION_NOT_EXISTS(1705, "告警表达式关联关系不存在"), EVENT_PRODUCT_CANNOT_DELETE(1706, "来自产品的触发器不能删除"), - + SCENE_NOT_EXISTS(1707, "场景不存在"), /** * 租户相关的异常 From e5d73f6aba2e867bc19839b8c90c8e7b6c496655 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Fri, 5 Nov 2021 18:47:54 +0800 Subject: [PATCH 620/763] =?UTF-8?q?[feat]:=20support=20docker-compose=20st?= =?UTF-8?q?art=20zabbix=E3=80=81pg=E3=80=81zeus-iot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/docker-compose.yaml | 237 +++++++++++++++++++++++++++++ docker/docker-entrypoint.sh | 146 +++++++----------- docker/dockerfile | 4 +- docker/env_vars/.POSTGRES_PASSWORD | 1 + docker/env_vars/.POSTGRES_USER | 1 + docker/env_vars/.env_agent | 37 +++++ docker/env_vars/.env_db_pgsql | 11 ++ docker/env_vars/.env_pg_db | 10 ++ docker/env_vars/.env_srv | 62 ++++++++ docker/env_vars/.env_web | 27 ++++ docker/env_vars/.env_web_service | 9 ++ docker/env_vars/.env_zeus_iot | 5 + 12 files changed, 457 insertions(+), 93 deletions(-) create mode 100644 docker/docker-compose.yaml create mode 100644 docker/env_vars/.POSTGRES_PASSWORD create mode 100644 docker/env_vars/.POSTGRES_USER create mode 100644 docker/env_vars/.env_agent create mode 100644 docker/env_vars/.env_db_pgsql create mode 100644 docker/env_vars/.env_pg_db create mode 100644 docker/env_vars/.env_srv create mode 100644 docker/env_vars/.env_web create mode 100644 docker/env_vars/.env_web_service create mode 100644 docker/env_vars/.env_zeus_iot diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml new file mode 100644 index 00000000..740e9b7a --- /dev/null +++ b/docker/docker-compose.yaml @@ -0,0 +1,237 @@ +version: '3.5' +services: + zabbix-server: + image: zabbix/zabbix-server-pgsql:alpine-5.4-latest + ports: + - "10051:10051" + volumes: + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + - ./zbx_env/usr/lib/zabbix/alertscripts:/usr/lib/zabbix/alertscripts:ro + - ./zbx_env/usr/lib/zabbix/externalscripts:/usr/lib/zabbix/externalscripts:ro + - ./zbx_env/var/lib/zabbix/export:/var/lib/zabbix/export:rw + - ./zbx_env/var/lib/zabbix/modules:/var/lib/zabbix/modules:ro + - ./zbx_env/var/lib/zabbix/enc:/var/lib/zabbix/enc:ro + - ./zbx_env/var/lib/zabbix/ssh_keys:/var/lib/zabbix/ssh_keys:ro + - ./zbx_env/var/lib/zabbix/mibs:/var/lib/zabbix/mibs:ro + - ./zbx_env/var/lib/zabbix/snmptraps:/var/lib/zabbix/snmptraps:ro + ulimits: + nproc: 65535 + nofile: + soft: 20000 + hard: 40000 + deploy: + resources: + limits: + cpus: '0.70' + memory: 1G + reservations: + cpus: '0.5' + memory: 512M + env_file: + - ./env_vars/.env_db_pgsql + - ./env_vars/.env_srv + secrets: + - POSTGRES_USER + - POSTGRES_PASSWORD + depends_on: + - postgres-server + networks: + zbx_net_backend: + aliases: + - zabbix-server + - zabbix-server-pgsql + - zabbix-server-alpine-pgsql + - zabbix-server-pgsql-alpine + zbx_net_frontend: +# devices: +# - "/dev/ttyUSB0:/dev/ttyUSB0" + stop_grace_period: 30s + sysctls: + - net.ipv4.ip_local_port_range=1024 65000 + - net.ipv4.conf.all.accept_redirects=0 + - net.ipv4.conf.all.secure_redirects=0 + - net.ipv4.conf.all.send_redirects=0 + labels: + com.zabbix.description: "Zabbix server with PostgreSQL database support" + com.zabbix.company: "Zabbix LLC" + com.zabbix.component: "zabbix-server" + com.zabbix.dbtype: "pgsql" + com.zabbix.os: "alpine" + + + zabbix-web-nginx-pgsql: + image: zabbix/zabbix-web-nginx-pgsql:alpine-5.4-latest + ports: + - "80:8080" + - "443:8443" + volumes: + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + - ./zbx_env/etc/ssl/nginx:/etc/ssl/nginx:ro + - ./zbx_env/usr/share/zabbix/modules/:/usr/share/zabbix/modules/:ro +# - ./env_vars/.ZBX_DB_CA_FILE:/run/secrets/root-ca.pem:ro +# - ./env_vars/.ZBX_DB_CERT_FILE:/run/secrets/client-cert.pem:ro +# - ./env_vars/.ZBX_DB_KEY_FILE:/run/secrets/client-key.pem:ro + deploy: + resources: + limits: + cpus: '0.70' + memory: 512M + reservations: + cpus: '0.5' + memory: 256M + env_file: + - ./env_vars/.env_db_pgsql + - ./env_vars/.env_web + secrets: + - POSTGRES_USER + - POSTGRES_PASSWORD + depends_on: + - postgres-server + - zabbix-server + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/"] + interval: 10s + timeout: 5s + retries: 3 + start_period: 30s + networks: + zbx_net_backend: + aliases: + - zabbix-web-nginx-pgsql + - zabbix-web-nginx-alpine-pgsql + - zabbix-web-nginx-pgsql-alpine + zbx_net_frontend: + stop_grace_period: 10s + sysctls: + - net.core.somaxconn=65535 + labels: + com.zabbix.description: "Zabbix frontend on Nginx web-server with PostgreSQL database support" + com.zabbix.company: "Zabbix LLC" + com.zabbix.component: "zabbix-frontend" + com.zabbix.webserver: "nginx" + com.zabbix.dbtype: "pgsql" + com.zabbix.os: "alpine" + + zabbix-agent: + image: zabbix/zabbix-agent:alpine-5.4-latest + ports: + - "10050:10050" + volumes: + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + - ./zbx_env/etc/zabbix/zabbix_agentd.d:/etc/zabbix/zabbix_agentd.d:ro + - ./zbx_env/var/lib/zabbix/modules:/var/lib/zabbix/modules:ro + - ./zbx_env/var/lib/zabbix/enc:/var/lib/zabbix/enc:ro + - ./zbx_env/var/lib/zabbix/ssh_keys:/var/lib/zabbix/ssh_keys:ro + deploy: + resources: + limits: + cpus: '0.2' + memory: 128M + reservations: + cpus: '0.1' + memory: 64M + mode: global + env_file: + - ./env_vars/.env_agent + privileged: true + pid: "host" + networks: + zbx_net_backend: + aliases: + - zabbix-agent + - zabbix-agent-passive + - zabbix-agent-alpine + stop_grace_period: 5s + labels: + com.zabbix.description: "Zabbix agent" + com.zabbix.company: "Zabbix LLC" + com.zabbix.component: "zabbix-agentd" + com.zabbix.os: "alpine" + + + postgres-server: + image: postgres:13-alpine +# command: -c ssl=on -c ssl_cert_file=/run/secrets/server-cert.pem -c ssl_key_file=/run/secrets/server-key.pem -c ssl_ca_file=/run/secrets/root-ca.pem + volumes: + - ./zbx_env/var/lib/postgresql/data:/var/lib/postgresql/data:rw + - ./env_vars/.ZBX_DB_CA_FILE:/run/secrets/root-ca.pem:ro + - ./env_vars/.ZBX_DB_CERT_FILE:/run/secrets/server-cert.pem:ro + - ./env_vars/.ZBX_DB_KEY_FILE:/run/secrets/server-key.pem:ro + env_file: + - ./env_vars/.env_pg_db + secrets: + - POSTGRES_USER + - POSTGRES_PASSWORD + stop_grace_period: 1m + networks: + zbx_net_backend: + aliases: + - postgres-server + - pgsql-server + - pgsql-database + + + zeus-iot-server: + build: . + ports: + - "9090:9090" + - "9080:9080" + - "12800:12800" + - "12900:12900" + env_file: + - ./env_vars/.env_zeus_iot + - ./env_vars/.env_pg_db + stop_grace_period: 1m + depends_on: + - postgres-server + - zabbix-server + - zabbix-web-nginx-pgsql + networks: + zeus_net: + aliases: + - zeus-iot-server + - zeus-iot-web + zbx_net_frontend: + zbx_net_backend: + db_data_pgsql: + image: busybox + volumes: + - ./zbx_env/var/lib/postgresql/data:/var/lib/postgresql/data:rw + + +networks: + zbx_net_frontend: + driver: bridge + driver_opts: + com.docker.network.enable_ipv6: "false" + ipam: + driver: default + config: + - subnet: 172.16.238.0/24 + zbx_net_backend: + driver: bridge + driver_opts: + com.docker.network.enable_ipv6: "false" + internal: true + ipam: + driver: default + config: + - subnet: 172.16.239.0/24 + zeus_net: + driver: bridge + driver_opts: + com.docker.network.enable_ipv6: "false" + internal: true + ipam: + driver: default + config: + - subnet: 172.16.240.0/24 + +secrets: + POSTGRES_USER: + file: ./env_vars/.POSTGRES_USER + POSTGRES_PASSWORD: + file: ./env_vars/.POSTGRES_PASSWORD diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh index 48e3f85b..e7a84abb 100755 --- a/docker/docker-entrypoint.sh +++ b/docker/docker-entrypoint.sh @@ -9,15 +9,6 @@ if [ "${DEBUG_MODE,,}" == "true" ]; then set -o xtrace fi -#Enable PostgreSQL timescaleDB feature: -: ${ENABLE_TIMESCALEDB:="false"} - -# Default directories -# User 'zabbix' home directory -ZABBIX_USER_HOME_DIR="/var/lib/zabbix" -# Configuration files directory -ZABBIX_ETC_DIR="/etc/zabbix" - # usage: file_env VAR [DEFAULT] # as example: file_env 'MYSQL_PASSWORD' 'zabbix' # (will allow for "$MYSQL_PASSWORD_FILE" to fill in the value of "$MYSQL_PASSWORD" from a file) @@ -66,76 +57,7 @@ escape_spec_char() { echo "$var_value" } -update_config_var() { - local config_path=$1 - local var_name=$2 - local var_value=$3 - local is_multiple=$4 - - local masklist=("DBPassword TLSPSKIdentity") - - if [ ! -f "$config_path" ]; then - echo "**** Configuration file '$config_path' does not exist" - return - fi - - if [[ " ${masklist[@]} " =~ " $var_name " ]] && [ ! -z "$var_value" ]; then - echo -n "** Updating '$config_path' parameter \"$var_name\": '****'. Enable DEBUG_MODE to view value ..." - else - echo -n "** Updating '$config_path' parameter \"$var_name\": '$var_value'..." - fi - - # Remove configuration parameter definition in case of unset parameter value - if [ -z "$var_value" ]; then - sed -i -e "/^$var_name=/d" "$config_path" - echo "removed" - return - fi - - # Remove value from configuration parameter in case of double quoted parameter value - if [ "$var_value" == '""' ]; then - sed -i -e "/^$var_name=/s/=.*/=/" "$config_path" - echo "undefined" - return - fi - - # Use full path to a file for TLS related configuration parameters - if [[ $var_name =~ ^TLS.*File$ ]]; then - var_value=$ZABBIX_USER_HOME_DIR/enc/$var_value - fi - - # Escaping characters in parameter value and name - var_value=$(escape_spec_char "$var_value") - var_name=$(escape_spec_char "$var_name") - - if [ "$(grep -E "^$var_name=" $config_path)" ] && [ "$is_multiple" != "true" ]; then - sed -i -e "/^$var_name=/s/=.*/=$var_value/" "$config_path" - echo "updated" - elif [ "$(grep -Ec "^# $var_name=" $config_path)" -gt 1 ]; then - sed -i -e "/^[#;] $var_name=$/i\\$var_name=$var_value" "$config_path" - echo "added first occurrence" - else - sed -i -e "/^[#;] $var_name=/s/.*/&\n$var_name=$var_value/" "$config_path" - echo "added" - fi - -} - -update_config_multiple_var() { - local config_path=$1 - local var_name=$2 - local var_value=$3 - - var_value="${var_value%\"}" - var_value="${var_value#\"}" - - local IFS=, - local OPT_LIST=($var_value) - for value in "${OPT_LIST[@]}"; do - update_config_var $config_path $var_name $value true - done -} # Check prerequisites for PostgreSQL database check_variables_postgresql() { @@ -211,8 +133,8 @@ psql_query() { local result="" - if [ -n "${DB_SERVER_ZBX_PASS}" ]; then - export PGPASSWORD="${DB_SERVER_ZBX_PASS}" + if [ -n "${DB_SERVER_ZEUS_PASS}" ]; then + export PGPASSWORD="${DB_SERVER_ZEUS_PASS}" fi if [ "${POSTGRES_USE_IMPLICIT_SEARCH_PATH,,}" == "false" ] && [ -n "${DB_SERVER_SCHEMA}" ]; then @@ -279,23 +201,20 @@ create_db_database_postgresql() { } create_db_schema_postgresql() { - DBVERSION_TABLE_EXISTS=$(psql_query "SELECT 1 FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = - c.relnamespace WHERE n.nspname = '$DB_SERVER_SCHEMA' AND c.relname = 'dbversion'" "${DB_SERVER_DBNAME}") + ZEUS_TABLE_EXISTS=$(psql_query "SELECT 1 FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = + c.relnamespace WHERE n.nspname = '$DB_SERVER_SCHEMA' AND c.relname = 'tag'" "${DB_SERVER_DBNAME}") - if [ -n "${DBVERSION_TABLE_EXISTS}" ]; then - echo "** Table '${DB_SERVER_DBNAME}.dbversion' already exists." - ZEUS_DB_VERSION=$(psql_query "SELECT mandatory FROM ${DB_SERVER_SCHEMA}.dbversion" "${DB_SERVER_DBNAME}") - fi +# if [ -n "${DBVERSION_TABLE_EXISTS}" ]; then +# echo "** Table '${DB_SERVER_DBNAME}.dbversion' already exists." +# ZEUS_DB_VERSION=$(psql_query "SELECT mandatory FROM ${DB_SERVER_SCHEMA}.dbversion" "${DB_SERVER_DBNAME}") +# fi - if [ -z "${ZEUS_DB_VERSION}" ]; then + if [ -z "${ZEUS_TABLE_EXISTS}" ]; then echo "** Creating '${DB_SERVER_DBNAME}' schema in PostgreSQL" - if [ "${ENABLE_TIMESCALEDB,,}" == "true" ]; then - psql_query "CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;" "${DB_SERVER_DBNAME}" - fi if [ -n "${DB_SERVER_ZEUS_PASS}" ]; then - export PGPASSWORD="${DB_SERVER_ZBX_PASS}" + export PGPASSWORD="${DB_SERVER_ZEUS_PASS}" fi if [ "${POSTGRES_USE_IMPLICIT_SEARCH_PATH,,}" == "false" ] && [ -n "${DB_SERVER_SCHEMA}" ]; then @@ -324,6 +243,50 @@ create_db_schema_postgresql() { } +# Get zabbix api token + +get_zbx_apitoken() { + + WAIT_TIMEOUT=5 + + ZBX_API_URL="http://${ZEUS_ZABBIX_HOST}:${ZEUS_ZABBIX_PORT}/api_jsonrpc.php" + + data='{"jsonrpc": "2.0","method": "user.login","params":{"user":"Admin","password":"zabbix"},"id":1,"auth":null}' + + # Check zbx ui is ok + + while true : + do + + res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $ZBX_API_URL"` + + if auth=`echo $res | python -c 'import sys, json; print(json.load(sys.stdin)["result"])' 2> /dev/null`;then + break + fi + echo "**** zabbix-web-nginx-pgsql is not available. Waiting $WAIT_TIMEOUT seconds..." + sleep $WAIT_TIMEOUT + done + + + # Check token + data='{"jsonrpc": "2.0","method": "token.get","params":{"output": ["tokenid"], "filter": {"name": "zeus"}},"id":1,"auth":"'${auth}'"}' + res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $ZBX_API_URL"` + if ! tokenid=`echo $res | python -c 'import sys, json; print(json.load(sys.stdin)["result"][0]["tokenid"])' 2> /dev/null`;then + data='{"jsonrpc": "2.0","method": "token.create","params":{"name":"zeus","userid":"1"},"id":1,"auth":"'${auth}'"}' + res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $ZBX_API_URL"` + tokenid=`echo $res | python -c 'import sys, json; print(json.load(sys.stdin)["result"]["tokenids"][0])'` + fi + + # Get API token + data='{"jsonrpc": "2.0","method": "token.generate","params":["'${tokenid}'"],"id":1,"auth":"'${auth}'"}' + res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $ZBX_API_URL"` + token=`echo $res | python -c 'import sys, json; print(json.load(sys.stdin)["result"][0]["token"])'` + export ZBXAPITOKEN=$token + +} + + + prepare_server() { echo "** Preparing Zeus IoT Server" @@ -331,6 +294,7 @@ prepare_server() { check_db_connect_postgresql create_db_database_postgresql create_db_schema_postgresql + get_zbx_apitoken } diff --git a/docker/dockerfile b/docker/dockerfile index 1c96108f..00b0ca41 100644 --- a/docker/dockerfile +++ b/docker/dockerfile @@ -3,7 +3,7 @@ FROM alpine:latest RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories RUN apk update \ - && apk add --no-cache tzdata openjdk8-jre bash postgresql-client \ + && apk add --no-cache tzdata curl python2 openjdk8-jre bash postgresql-client \ && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ && echo Asia/Shanghai > /etc/timezone \ && rm -rf /var/cache/apk/* @@ -12,7 +12,7 @@ ADD https://packages.zmops.cn/zeus-iot/zeus-iot-bin.tar.gz / RUN tar -xf zeus-iot-bin.tar.gz COPY log4j2.xml /zeus-iot-bin/config/log4j2.xml COPY docker-entrypoint.sh /usr/bin/docker-entrypoint.sh -EXPOSE 9090 9080 12800 +EXPOSE 9090 ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"] diff --git a/docker/env_vars/.POSTGRES_PASSWORD b/docker/env_vars/.POSTGRES_PASSWORD new file mode 100644 index 00000000..f1349944 --- /dev/null +++ b/docker/env_vars/.POSTGRES_PASSWORD @@ -0,0 +1 @@ +postgres diff --git a/docker/env_vars/.POSTGRES_USER b/docker/env_vars/.POSTGRES_USER new file mode 100644 index 00000000..f1349944 --- /dev/null +++ b/docker/env_vars/.POSTGRES_USER @@ -0,0 +1 @@ +postgres diff --git a/docker/env_vars/.env_agent b/docker/env_vars/.env_agent new file mode 100644 index 00000000..a2f9be2a --- /dev/null +++ b/docker/env_vars/.env_agent @@ -0,0 +1,37 @@ +# ZBX_SOURCEIP= +# ZBX_DEBUGLEVEL=3 +# ZBX_ENABLEREMOTECOMMANDS=0 # Deprecated since 5.0.0 +# ZBX_LOGREMOTECOMMANDS=0 +# ZBX_HOSTINTERFACE= # Available since 4.4.0 +# ZBX_HOSTINTERFACEITEM= # Available since 4.4.0 +# ZBX_SERVER_HOST=zabbix-server +# ZBX_PASSIVE_ALLOW=true +# ZBX_PASSIVESERVERS= +# ZBX_ACTIVE_ALLOW=true +# ZBX_ACTIVESERVERS= +# ZBX_LISTENIP= +# ZBX_STARTAGENTS=3 +# ZBX_HOSTNAME= +# ZBX_HOSTNAMEITEM=system.hostname +# ZBX_METADATA= +# ZBX_METADATAITEM= +# ZBX_REFRESHACTIVECHECKS=120 +# ZBX_BUFFERSEND=5 +# ZBX_BUFFERSIZE=100 +# ZBX_MAXLINESPERSECOND=20 +# ZBX_ALIAS="" +# ZBX_TIMEOUT=3 +# ZBX_UNSAFEUSERPARAMETERS=0 +# ZBX_LOADMODULE="dummy1.so,dummy2.so,dummy10.so" +# ZBX_TLSCONNECT=unencrypted +# ZBX_TLSACCEPT=unencrypted +# ZBX_TLSCAFILE= +# ZBX_TLSCRLFILE= +# ZBX_TLSSERVERCERTISSUER= +# ZBX_TLSSERVERCERTSUBJECT= +# ZBX_TLSCERTFILE= +# ZBX_TLSKEYFILE= +# ZBX_TLSPSKIDENTITY= +# ZBX_TLSPSKFILE= +# ZBX_DENYKEY=system.run[*] +# ZBX_ALLOWKEY= diff --git a/docker/env_vars/.env_db_pgsql b/docker/env_vars/.env_db_pgsql new file mode 100644 index 00000000..30be4ad2 --- /dev/null +++ b/docker/env_vars/.env_db_pgsql @@ -0,0 +1,11 @@ +# DB_SERVER_HOST=postgres-server +# DB_SERVER_PORT=5432 +# POSTGRES_USER=zabbix +POSTGRES_USER_FILE=/run/secrets/POSTGRES_USER +# POSTGRES_PASSWORD=zabbix +POSTGRES_PASSWORD_FILE=/run/secrets/POSTGRES_PASSWORD +# POSTGRES_DB=zabbix +POSTGRES_DB=zabbix +# DB_SERVER_SCHEMA=public +# ENABLE_TIMESCALEDB=true +# POSTGRES_USE_IMPLICIT_SEARCH_PATH=false diff --git a/docker/env_vars/.env_pg_db b/docker/env_vars/.env_pg_db new file mode 100644 index 00000000..e1d285ef --- /dev/null +++ b/docker/env_vars/.env_pg_db @@ -0,0 +1,10 @@ +# DB_SERVER_HOST=postgres-server +# DB_SERVER_PORT=5432 +POSTGRES_USER=postgres +# POSTGRES_USER_FILE=/run/secrets/POSTGRES_USER +POSTGRES_PASSWORD=postgres +# POSTGRES_PASSWORD_FILE=/run/secrets/POSTGRES_PASSWORD +# POSTGRES_DB=zabbix +# DB_SERVER_SCHEMA=public +# ENABLE_TIMESCALEDB=true +# POSTGRES_USE_IMPLICIT_SEARCH_PATH=false diff --git a/docker/env_vars/.env_srv b/docker/env_vars/.env_srv new file mode 100644 index 00000000..35c1ce6e --- /dev/null +++ b/docker/env_vars/.env_srv @@ -0,0 +1,62 @@ +# ZBX_LISTENIP= +# ZBX_HISTORYSTORAGEURL=http://elasticsearch:9200/ # Available since 3.4.5 +# ZBX_HISTORYSTORAGETYPES=uint,dbl,str,log,text # Available since 3.4.5 +# ZBX_DBTLSCONNECT=required # Available since 5.0.0 +# ZBX_DBTLSCAFILE=/run/secrets/root-ca.pem # Available since 5.0.0 +# ZBX_DBTLSCERTFILE=/run/secrets/client-cert.pem # Available since 5.0.0 +# ZBX_DBTLSKEYFILE=/run/secrets/client-key.pem # Available since 5.0.0 +# ZBX_DBTLSCIPHER= # Available since 5.0.0 +# ZBX_DBTLSCIPHER13= # Available since 5.0.0 +# ZBX_DEBUGLEVEL=3 +# ZBX_STARTPOLLERS=5 +# ZBX_IPMIPOLLERS=0 +# ZBX_STARTPREPROCESSORS=3 # Available since 3.4.0 +# ZBX_STARTPOLLERSUNREACHABLE=1 +# ZBX_STARTTRAPPERS=5 +# ZBX_STARTPINGERS=1 +# ZBX_STARTDISCOVERERS=1 +# ZBX_STARTHTTPPOLLERS=1 +# ZBX_STARTTIMERS=1 +# ZBX_STARTESCALATORS=1 +# ZBX_STARTALERTERS=3 # Available since 3.4.0 +ZBX_JAVAGATEWAY_ENABLE=true +# ZBX_JAVAGATEWAY=zabbix-java-gateway +# ZBX_JAVAGATEWAYPORT=10052 +ZBX_STARTJAVAPOLLERS=5 +# ZBX_STARTVMWARECOLLECTORS=0 +# ZBX_VMWAREFREQUENCY=60 +# ZBX_VMWAREPERFFREQUENCY=60 +# ZBX_VMWARECACHESIZE=8M +# ZBX_VMWARETIMEOUT=10 +ZBX_ENABLE_SNMP_TRAPS=true +# ZBX_SOURCEIP= +# ZBX_HOUSEKEEPINGFREQUENCY=1 +# ZBX_MAXHOUSEKEEPERDELETE=5000 +# ZBX_SENDERFREQUENCY=30 +# ZBX_CACHESIZE=8M +# ZBX_CACHEUPDATEFREQUENCY=60 +# ZBX_STARTDBSYNCERS=4 +# ZBX_HISTORYCACHESIZE=16M +# ZBX_HISTORYINDEXCACHESIZE=4M +# ZBX_TRENDCACHESIZE=4M +# ZBX_VALUECACHESIZE=8M +# ZBX_TIMEOUT=4 +# ZBX_TRAPPERTIMEOUT=300 +# ZBX_UNREACHABLEPERIOD=45 +# ZBX_UNAVAILABLEDELAY=60 +# ZBX_UNREACHABLEDELAY=15 +# ZBX_LOGSLOWQUERIES=3000 +# ZBX_EXPORTFILESIZE= +# ZBX_STARTPROXYPOLLERS=1 +# ZBX_PROXYCONFIGFREQUENCY=3600 +# ZBX_PROXYDATAFREQUENCY=1 +# ZBX_LOADMODULE="dummy1.so,dummy2.so,dummy10.so" +# ZBX_TLSCAFILE= +# ZBX_TLSCRLFILE= +# ZBX_TLSCERTFILE= +# ZBX_TLSKEYFILE= +# ZBX_VAULTDBPATH= +# ZBX_VAULTURL=https://127.0.0.1:8200 +# VAULT_TOKEN= +# ZBX_STARTREPORTWRITERS=0 +# ZBX_WEBSERVICEURL=http://zabbix-web-service:10053/report diff --git a/docker/env_vars/.env_web b/docker/env_vars/.env_web new file mode 100644 index 00000000..ae96d1ad --- /dev/null +++ b/docker/env_vars/.env_web @@ -0,0 +1,27 @@ +# ZBX_SERVER_HOST=zabbix-server +# ZBX_SERVER_PORT=10051 +ZBX_SERVER_NAME=Composed installation +# ZBX_DB_ENCRYPTION=true # Available since 5.0.0 +# ZBX_DB_KEY_FILE=/run/secrets/client-key.pem # Available since 5.0.0 +# ZBX_DB_CERT_FILE=/run/secrets/client-cert.pem # Available since 5.0.0 +# ZBX_DB_CA_FILE=/run/secrets/root-ca.pem # Available since 5.0.0 +# ZBX_DB_VERIFY_HOST=false # Available since 5.0.0 +# ZBX_DB_CIPHER_LIST= # Available since 5.0.0 +# ZBX_VAULTDBPATH= +# ZBX_VAULTURL=https://127.0.0.1:8200 +# VAULT_TOKEN= +# ZBX_HISTORYSTORAGEURL=http://elasticsearch:9200/ # Available since 3.4.5 +# ZBX_HISTORYSTORAGETYPES=['uint', 'dbl', 'str', 'text', 'log'] # Available since 3.4.5 +# ZBX_SSO_SETTINGS=[] # Available since 5.0.0 +# ENABLE_WEB_ACCESS_LOG=true +# ZBX_MAXEXECUTIONTIME=600 +# ZBX_MEMORYLIMIT=128M +# ZBX_POSTMAXSIZE=16M +# ZBX_UPLOADMAXFILESIZE=2M +# ZBX_MAXINPUTTIME=300 +# ZBX_SESSION_NAME=zbx_sessionid +# Timezone one of: http://php.net/manual/en/timezones.php +# PHP_TZ=Europe/Riga +# ZBX_DENY_GUI_ACCESS=false +# ZBX_GUI_ACCESS_IP_RANGE=['127.0.0.1'] +# ZBX_GUI_WARNING_MSG=Zabbix is under maintenance. diff --git a/docker/env_vars/.env_web_service b/docker/env_vars/.env_web_service new file mode 100644 index 00000000..1d473f10 --- /dev/null +++ b/docker/env_vars/.env_web_service @@ -0,0 +1,9 @@ +# ZBX_DEBUGLEVEL=3 +ZBX_ALLOWEDIP=zabbix-server +# ZBX_LISTENPORT=10053 +# ZBX_LISTENIP= +# ZBX_TIMEOUT=3 +# ZBX_TLSACCEPT=unencrypted +# ZBX_TLSCAFILE= +# ZBX_TLSCERTFILE= +# ZBX_TLSKEYFILE= diff --git a/docker/env_vars/.env_zeus_iot b/docker/env_vars/.env_zeus_iot new file mode 100644 index 00000000..e4251021 --- /dev/null +++ b/docker/env_vars/.env_zeus_iot @@ -0,0 +1,5 @@ +ZEUS_ZABBIX_HOST=zabbix-web-nginx-pgsql +ZEUS_ZABBIX_PORT=8080 +ZEUS_ZABBIX_API_URL=/api_jsonrpc.php +ZEUS_DB_HOST=postgres-server + From 09ba0a3f375206f26400183df4082348fef42205 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 6 Nov 2021 14:07:48 +0800 Subject: [PATCH 621/763] [fix]: fix cannot update admin user --- .../zmops/iot/web/exception/enums/BizExceptionEnum.java | 1 + .../zmops/iot/web/sys/controller/SysUserController.java | 5 +++++ .../com/zmops/iot/web/sys/service/SysUserService.java | 9 +++++++++ 3 files changed, 15 insertions(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index ba48f9d2..3e3164c7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -50,6 +50,7 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { CANT_DELETE_ADMIN(600, "不能删除超级管理员"), CANT_FREEZE_ADMIN(600, "不能冻结超级管理员"), CANT_CHANGE_ADMIN(600, "不能修改超级管理员角色"), + CANT_CHANGE_ADMIN_PWD(600, "不能修改超级管理员密码"), ROLE_HAS_EXIST(601, "角色已存在"), ROLE_HAS_BIND_USER(602, "角色绑定了用户,请先解除绑定!"), MENU_NOT_EXIST_OR_NO_PRERMISSION(603, "菜单不存在或无权授权此菜单"), diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java index 7ee4bc34..bb966069 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java @@ -2,9 +2,11 @@ import com.zmops.iot.core.log.BussinessLog; import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.web.auth.Permission; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.sys.dto.UserDto; import com.zmops.iot.web.sys.dto.param.UserParam; import com.zmops.iot.web.sys.service.SysUserService; @@ -93,6 +95,9 @@ public ResponseData changePwd(@Valid @RequestBody UserParam user) { @RequestMapping("/reset") @BussinessLog(value = "重置密码") public ResponseData reset(@RequestParam("userId") Long userId) { + if(userId==1){ + throw new ServiceException(BizExceptionEnum.CANT_CHANGE_ADMIN_PWD); + } sysUserService.reset(userId); return ResponseData.success(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java index 23597976..1fabd982 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java @@ -153,6 +153,9 @@ public SysUser updateUser(UserDto user) { if (null == oldUser) { throw new ServiceException(BizExceptionEnum.USER_NOT_EXIST); } + if (user.getUserId() == 1) { + throw new ServiceException(BizExceptionEnum.CANT_CHANGE_ADMIN); + } //判断角色是否存在 checkByRole(user.getRoleId()); @@ -175,6 +178,9 @@ public SysUser updateUser(UserDto user) { * @return */ public void deleteUser(UserParam user) { + if (user.getUserIds().contains(1)) { + throw new ServiceException(BizExceptionEnum.CANT_DELETE_ADMIN); + } List list = new QSysUser().userId.in(user.getUserIds()).findList(); if (ToolUtil.isEmpty(list)) { throw new ServiceException(BizExceptionEnum.USER_NOT_EXIST); @@ -228,6 +234,9 @@ public void changePwd(String oldPassword, String newPassword) { if (null == loginUser) { throw new ServiceException(AuthExceptionEnum.NOT_LOGIN_ERROR); } + if (loginUser.getId() == 1) { + throw new ServiceException(BizExceptionEnum.CANT_CHANGE_ADMIN_PWD); + } SysUser user = new QSysUser().userId.eq(loginUser.getId()).findOne(); String rawNewPasswd = ""; try { From b699f28a95bae1b852187ca6fce5d79353c49959 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 6 Nov 2021 17:15:05 +0800 Subject: [PATCH 622/763] [fix]: fix device cache --- .../zmops/iot/model/cache/AbstractCache.java | 3 +- .../iot/web/device/service/DeviceService.java | 33 ++++++++++++++----- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/AbstractCache.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/AbstractCache.java index 1e7eda51..9fcb9782 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/cache/AbstractCache.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/AbstractCache.java @@ -4,6 +4,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -66,7 +67,7 @@ public void update(Map values) { try { cache.clear(); cache.putAll(values); - view = Collections.unmodifiableMap(cache); + view = new ConcurrentHashMap<>(cache); } finally { writeLock.unlock(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 27e7a913..50f9aa6a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -10,8 +10,6 @@ import com.zmops.iot.domain.device.query.QDevicesGroups; import com.zmops.iot.domain.device.query.QTag; import com.zmops.iot.domain.product.Product; -import com.zmops.iot.domain.product.ProductService; -import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.product.query.*; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; @@ -39,7 +37,7 @@ * @author yefei **/ @Service -public class DeviceService implements CommandLineRunner{ +public class DeviceService implements CommandLineRunner { @Autowired private SaveDeviceWorker saveDeviceWorker; @@ -281,8 +279,8 @@ public String create(DeviceDto deviceDto) { } catch (Exception e) { e.printStackTrace(); } - - return deviceWork.getWorkResult().getResult().getDeviceId(); + updateDeviceNameCache(deviceDto.getDeviceId(), deviceDto.getName()); + return deviceDto.getDeviceId(); } /** @@ -333,7 +331,7 @@ public String update(DeviceDto deviceDto) { } catch (Exception e) { e.printStackTrace(); } - + updateDeviceNameCache(deviceDto.getDeviceId(), deviceDto.getName()); return deviceWork.getWorkResult().getResult().getDeviceId(); } @@ -408,6 +406,7 @@ public String delete(DeviceDto deviceDto) { e.printStackTrace(); } + removeDeviceNameCache(deviceDto.getDeviceId()); return deviceDto.getDeviceId(); } @@ -548,14 +547,30 @@ public void status(String status, String deviceId, String zbxId) { DB.update(Device.class).where().eq("device_id", deviceId).asUpdate().set("status", status).setNull("online").update(); } - private void updateDevice() { - List deviceList = new QDevice().findList(); + /** + * 更新设备名称缓存 + */ + private void updateDeviceCache() { + List deviceList = new QDevice().select(QDevice.Alias.deviceId, QDevice.Alias.name).findList(); Map map = deviceList.parallelStream().collect(Collectors.toMap(Device::getDeviceId, Device::getName)); DefinitionsUtil.updateDeviceCache(map); } + private void updateDeviceNameCache(String deviceId, String name) { + Map all = DefinitionsUtil.getDeviceCache().getAll(); + all.put(deviceId, name); + DefinitionsUtil.updateDeviceCache(all); + } + + private void removeDeviceNameCache(String deviceId) { + Map all = DefinitionsUtil.getDeviceCache().getAll(); + all.remove(deviceId); + DefinitionsUtil.updateDeviceCache(all); + } + + @Override public void run(String... args) throws Exception { - updateDevice(); + updateDeviceCache(); } } From d0175166a4170db514cd3cda255d8dc28406ae11 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 6 Nov 2021 17:40:40 +0800 Subject: [PATCH 623/763] [fix]: fix reload sys param --- .../main/java/com/zmops/iot/web/init/SysConfigInit.java | 6 +++++- .../com/zmops/iot/web/sys/service/SysParamService.java | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/SysConfigInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/SysConfigInit.java index e62037af..e45c468a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/SysConfigInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/SysConfigInit.java @@ -20,6 +20,11 @@ public class SysConfigInit implements CommandLineRunner { @Override public void run(String... args) { + initConfigConst(); + + } + + public void initConfigConst(){ //初始化所有的常量 List list = DB.find(SysConfig.class).findList(); @@ -30,6 +35,5 @@ public void run(String... args) { log.info("初始化常量" + list.size() + "条!"); } - } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysParamService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysParamService.java index 50c452f3..2412afdb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysParamService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysParamService.java @@ -3,8 +3,10 @@ import com.zmops.iot.domain.sys.SysConfig; import com.zmops.iot.domain.sys.query.QSysConfig; import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.web.init.SysConfigInit; import com.zmops.iot.web.sys.dto.SysParamDto; import io.ebean.DB; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @@ -17,6 +19,9 @@ @Service public class SysParamService { + @Autowired + SysConfigInit sysConfigInit; + public List list() { return new QSysConfig().status.eq(CommonStatus.ENABLE.getCode()).orderBy().id.desc().findList(); } @@ -31,5 +36,7 @@ public void update(SysParamDto sysParamDto) { sysConfig.setRemark(sysParam.getRemark()); } DB.saveAll(sysParamList); + + sysConfigInit.initConfigConst(); } } From 77d7f98e07551292a6fb4903a0836e25fa65867e Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 8 Nov 2021 20:32:42 +0800 Subject: [PATCH 624/763] [fix]: code format --- .../web/product/controller/ProductServiceController.java | 1 + .../zmops/iot/web/product/service/ProductSvcService.java | 9 ++------- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java index 9ce78322..922e9bf9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java @@ -55,6 +55,7 @@ public ResponseData paramList(@RequestParam("serviceId") long serviceId) { */ @RequestMapping("/create") public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody ProductServiceDto productServiceDto) { + productServiceDto.setId(null); return ResponseData.success(productSvcService.create(productServiceDto)); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index 24f7f9dc..020eaab2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -1,7 +1,5 @@ package com.zmops.iot.web.product.service; -import com.google.common.collect.HashBasedTable; -import com.google.common.collect.Table; import com.zmops.iot.async.executor.Async; import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductService; @@ -10,10 +8,6 @@ import com.zmops.iot.domain.product.query.QProductService; import com.zmops.iot.domain.product.query.QProductServiceParam; import com.zmops.iot.domain.product.query.QProductServiceRelation; -import com.zmops.iot.domain.sys.SysDict; -import com.zmops.iot.domain.sys.SysDictType; -import com.zmops.iot.domain.sys.query.QSysDict; -import com.zmops.iot.domain.sys.query.QSysDictType; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.DefinitionsUtil; @@ -41,7 +35,7 @@ * 产品 物模型 服务 **/ @Service -public class ProductSvcService implements CommandLineRunner{ +public class ProductSvcService implements CommandLineRunner { @Autowired SaveProdSvcWorker saveProdSvcWorker; @@ -156,6 +150,7 @@ public ProductServiceDto create(ProductServiceDto productServiceDto) { if (ToolUtil.isNotEmpty(productServiceDto.getProductServiceParamList())) { for (ProductServiceParam productServiceParam : productServiceDto.getProductServiceParamList()) { + productServiceParam.setServiceId(null); productServiceParam.setServiceId(serviceId); productServiceParam.setDeviceId(productServiceDto.getRelationId()); } From 02084e340848d4ffde8cd43007d9700b5b252b0e Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 9 Nov 2021 14:44:25 +0800 Subject: [PATCH 625/763] [fix]: fix device log list field --- .../controller/DeviceLogController.java | 3 +- .../MultipleDeviceEventTriggerController.java | 13 +- .../iot/web/device/dto/DeviceLogDto.java | 18 ++ .../iot/web/device/dto/DeviceRelationDto.java | 17 ++ .../web/device/dto/param/DeviceLogParam.java | 13 ++ .../dto/param/MultipleDeviceEventParm.java | 3 - .../web/device/service/DeviceLogService.java | 192 +++++++++++------- .../MultipleDeviceEventRuleService.java | 25 ++- 8 files changed, 207 insertions(+), 77 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceRelationDto.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java index 10191e98..85383e53 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java @@ -33,7 +33,6 @@ public ResponseData list(@RequestParam(value = "deviceId") String deviceId, @RequestMapping("getLogByPage") public Pager getLogByPage(@RequestBody DeviceLogParam deviceLogParam) { - return deviceLogService.getLogByPage(deviceLogParam.getDeviceId(), deviceLogParam.getLogType(), deviceLogParam.getTimeFrom(), - deviceLogParam.getTimeTill(),deviceLogParam.getContent(), deviceLogParam.getPage(), deviceLogParam.getMaxRow()); + return deviceLogService.getLogByPage(deviceLogParam); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java index 007e6534..fbacb4d7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java @@ -50,7 +50,7 @@ public class MultipleDeviceEventTriggerController { private static final String EXECUTE_TAG_NAME = "__scene__"; /** - * 触发器 分页列表 + * 场景 分页列表 * * @param eventParm * @return @@ -60,6 +60,17 @@ public Pager getEventByPage(@RequestBody MultipleDeviceE return multipleDeviceEventRuleService.getEventByPage(eventParm); } + /** + * 场景 列表 + * + * @param eventParm + * @return + */ + @PostMapping("/list") + public ResponseData list(@RequestBody MultipleDeviceEventParm eventParm) { + return ResponseData.success(multipleDeviceEventRuleService.list(eventParm)); + } + /** * 设备联动 详情 * diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java index 5bcf551b..faa9f202 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java @@ -9,6 +9,8 @@ import lombok.Data; import lombok.NoArgsConstructor; +import java.util.List; + /** * @author yefei **/ @@ -18,13 +20,29 @@ @AllArgsConstructor @JsonSerialize(using = CachedValueFilter.class) public class DeviceLogDto { + private String logType; + private String triggerTime; + private String content; + @CachedValue(type = DicType.Device) private String deviceId; + @CachedValue(value = "EVENT_LEVEL") private String severity; + private String param; + private String status; + + private String triggerType; + + private String triggerBody; + + private List triggerDevice; + + private List executeDevice; + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceRelationDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceRelationDto.java new file mode 100644 index 00000000..932ee553 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceRelationDto.java @@ -0,0 +1,17 @@ +package com.zmops.iot.web.device.dto; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class DeviceRelationDto { + + private String deviceId; + + private String name; + + private Long eventRuleId; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceLogParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceLogParam.java index 47e56b1a..f442b06e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceLogParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceLogParam.java @@ -8,10 +8,23 @@ **/ @Data public class DeviceLogParam extends BaseQueryParam { + private String logType; + private String deviceId; + private String content; + private Long timeFrom; + private Long timeTill; + private String triggerType; + + private Long triggerUser; + + private Long eventRuleId; + + private String triggerDeviceId; + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/MultipleDeviceEventParm.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/MultipleDeviceEventParm.java index ce6e1c43..a9265514 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/MultipleDeviceEventParm.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/MultipleDeviceEventParm.java @@ -11,7 +11,4 @@ public class MultipleDeviceEventParm extends BaseQueryParam { private String eventRuleName; - - - private String classify = "1"; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java index 7716f584..93deb189 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java @@ -6,19 +6,24 @@ import com.zmops.iot.domain.device.query.QEventTriggerRecord; import com.zmops.iot.domain.device.query.QScenesTriggerRecord; import com.zmops.iot.domain.device.query.QServiceExecuteRecord; +import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventService; import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.alarm.dto.AlarmDto; import com.zmops.iot.web.alarm.dto.param.AlarmParam; import com.zmops.iot.web.alarm.service.AlarmService; import com.zmops.iot.web.device.dto.DeviceLogDto; +import com.zmops.iot.web.device.dto.DeviceRelationDto; +import com.zmops.iot.web.device.dto.param.DeviceLogParam; +import io.ebean.DB; +import io.ebean.PagedList; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; /** @@ -92,29 +97,24 @@ public List list(String deviceId, String logType, Long timeFrom, L } - public Pager getLogByPage(String deviceId, String logType, Long timeFrom, Long timeTill, String content, int page, int maxSize) { - List deviceLogDtoList; - if (ToolUtil.isNotEmpty(logType) && LOG_TYPE_ALARM.equals(logType)) { + public Pager getLogByPage(DeviceLogParam deviceLogParam) { - deviceLogDtoList = getAlarmLog(deviceId, timeFrom, timeTill, content); + String logType = deviceLogParam.getLogType(); - } else if (ToolUtil.isNotEmpty(logType) && LOG_TYPE_SERVICE.equals(logType)) { + if (ToolUtil.isNotEmpty(logType) && LOG_TYPE_SERVICE.equals(logType)) { - deviceLogDtoList = getServiceLog(deviceId, timeFrom, timeTill, content); + return getServiceLog(deviceLogParam); } else if (ToolUtil.isNotEmpty(logType) && LOG_TYPE_SCENES.equals(logType)) { - deviceLogDtoList = getScenesLog(timeFrom, timeTill, content); + return getScenesLog(deviceLogParam); } else { - deviceLogDtoList = getEventLog(deviceId, timeFrom, timeTill, content); + return getEventLog(deviceLogParam); } - List res = deviceLogDtoList.parallelStream().skip((page - 1) * maxSize) - .limit(maxSize).collect(Collectors.toList()); - return new Pager<>(res, deviceLogDtoList.size()); } /** @@ -149,104 +149,160 @@ private List getAlarmLog(String deviceId, Long timeFrom, Long time /** * 事件日志 * - * @param deviceId - * @param timeFrom - * @param timeTill - * @param content + * @param deviceLogParam * @return */ - private List getEventLog(String deviceId, Long timeFrom, Long timeTill, String content) { + private Pager getEventLog(DeviceLogParam deviceLogParam) { List deviceLogDtoList = new ArrayList<>(); + QEventTriggerRecord query = new QEventTriggerRecord(); - if (ToolUtil.isNotEmpty(deviceId)) { - query.deviceId.eq(deviceId); + if (ToolUtil.isNotEmpty(deviceLogParam.getDeviceId())) { + query.deviceId.eq(deviceLogParam.getDeviceId()); } - if (ToolUtil.isNotEmpty(content)) { - query.eventName.contains(content); + if (ToolUtil.isNotEmpty(deviceLogParam.getContent())) { + query.eventName.eq(deviceLogParam.getContent()); } - if (null != timeFrom) { - query.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(timeFrom * 1000)); + if (null != deviceLogParam.getTimeFrom()) { + query.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(deviceLogParam.getTimeFrom() * 1000)); } - if (null != timeTill) { - query.createTime.lt(LocalDateTimeUtils.getLDTByMilliSeconds(timeTill * 1000)); + if (null != deviceLogParam.getTimeTill()) { + query.createTime.lt(LocalDateTimeUtils.getLDTByMilliSeconds(deviceLogParam.getTimeTill() * 1000)); } query.orderBy().createTime.desc(); - List list = query.findList(); - if (ToolUtil.isNotEmpty(list)) { - list.forEach(service -> { + + PagedList pagedList = query.setFirstRow((deviceLogParam.getPage() - 1) * deviceLogParam.getMaxRow()) + .setMaxRows(deviceLogParam.getMaxRow()).findPagedList(); + + if (ToolUtil.isNotEmpty(pagedList.getList())) { + pagedList.getList().forEach(service -> { deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_EVENT).content(service.getEventName()) - .triggerTime(LocalDateTimeUtils.formatTime(service.getCreateTime())) + .triggerTime(LocalDateTimeUtils.formatTime(service.getCreateTime())).deviceId(service.getDeviceId()) .param(service.getEventValue()).build()); }); } - return deviceLogDtoList; + return new Pager<>(deviceLogDtoList, pagedList.getTotalCount()); } /** * 服务日志 * - * @param deviceId - * @param timeFrom - * @param timeTill - * @param content + * @param deviceLogParam * @return */ - private List getServiceLog(String deviceId, Long timeFrom, Long timeTill, String content) { + private Pager getServiceLog(DeviceLogParam deviceLogParam) { List deviceLogDtoList = new ArrayList<>(); + QServiceExecuteRecord query = new QServiceExecuteRecord(); - if (ToolUtil.isNotEmpty(deviceId)) { - query.deviceId.eq(deviceId); + if (ToolUtil.isNotEmpty(deviceLogParam.getDeviceId())) { + query.deviceId.eq(deviceLogParam.getDeviceId()); + } + if (ToolUtil.isNotEmpty(deviceLogParam.getContent())) { + query.serviceName.eq(deviceLogParam.getContent()); } - if (ToolUtil.isNotEmpty(content)) { - query.serviceName.contains(content); + if (ToolUtil.isNotEmpty(deviceLogParam.getTriggerType())) { + query.executeType.eq(deviceLogParam.getTriggerType()); } - if (null != timeFrom) { - query.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(timeFrom * 1000)); + if (ToolUtil.isNotEmpty(deviceLogParam.getTriggerUser())) { + query.executeUser.eq(deviceLogParam.getTriggerUser()); } - if (null != timeTill) { - query.createTime.lt(LocalDateTimeUtils.getLDTByMilliSeconds(timeTill * 1000)); + if (ToolUtil.isNotEmpty(deviceLogParam.getEventRuleId())) { + query.executeRuleId.eq(deviceLogParam.getEventRuleId()); + } + if (null != deviceLogParam.getTimeFrom()) { + query.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(deviceLogParam.getTimeFrom() * 1000)); + } + if (null != deviceLogParam.getTimeTill()) { + query.createTime.lt(LocalDateTimeUtils.getLDTByMilliSeconds(deviceLogParam.getTimeTill() * 1000)); } query.orderBy().createTime.desc(); - List list = query.findList(); - if (ToolUtil.isNotEmpty(list)) { - list.forEach(service -> { + + PagedList pagedList = query.setFirstRow((deviceLogParam.getPage() - 1) * deviceLogParam.getMaxRow()) + .setMaxRows(deviceLogParam.getMaxRow()).findPagedList(); + + if (ToolUtil.isNotEmpty(pagedList.getList())) { + pagedList.getList().forEach(service -> { + + String triggerBody = null != service.getExecuteUser() ? + DefinitionsUtil.getSysUserName(service.getExecuteUser()) : DefinitionsUtil.getTriggerName(service.getExecuteRuleId()); + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_SERVICE).content(service.getServiceName()) .triggerTime(LocalDateTimeUtils.formatTime(service.getCreateTime())) - .param(service.getParam()).build()); + .param(service.getParam()).triggerType(service.getExecuteType()).triggerBody(triggerBody).build()); }); } - return deviceLogDtoList; + return new Pager<>(deviceLogDtoList, pagedList.getTotalCount()); } /** * 场景日志 * - * @param timeFrom - * @param timeTill - * @param content + * @param deviceLogParam * @return */ - private List getScenesLog(Long timeFrom, Long timeTill, String content) { + private Pager getScenesLog(DeviceLogParam deviceLogParam) { List deviceLogDtoList = new ArrayList<>(); + QScenesTriggerRecord query = new QScenesTriggerRecord(); - if (ToolUtil.isNotEmpty(content)) { - query.ruleName.contains(content); + if (null != deviceLogParam.getEventRuleId()) { + query.ruleId.eq(deviceLogParam.getEventRuleId()); } - if (null != timeFrom) { - query.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(timeFrom * 1000)); + if (ToolUtil.isNotEmpty(deviceLogParam.getTriggerType())) { + query.triggerType.eq(deviceLogParam.getTriggerType()); + } + if (null != deviceLogParam.getTriggerUser()) { + query.triggerUser.eq(deviceLogParam.getTriggerUser()); + } + if (null != deviceLogParam.getTimeFrom()) { + query.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(deviceLogParam.getTimeFrom() * 1000)); + } + if (null != deviceLogParam.getTimeTill()) { + query.createTime.lt(LocalDateTimeUtils.getLDTByMilliSeconds(deviceLogParam.getTimeTill() * 1000)); + } + + if (ToolUtil.isNotEmpty(deviceLogParam.getTriggerDeviceId())) { + List triggerRuleIds = new QProductEventRelation().select(QProductEventRelation.alias().eventRuleId).relationId.eq(deviceLogParam.getTriggerDeviceId()).findSingleAttributeList(); + if (ToolUtil.isEmpty(triggerRuleIds)) { + return new Pager<>(Collections.emptyList(), 0); + } + query.ruleId.in(triggerRuleIds); } - if (null != timeTill) { - query.createTime.lt(LocalDateTimeUtils.getLDTByMilliSeconds(timeTill * 1000)); + + if (ToolUtil.isNotEmpty(deviceLogParam.getDeviceId())) { + List executeRuleIds = new QProductEventService().select(QProductEventService.alias().eventRuleId).executeDeviceId.eq(deviceLogParam.getTriggerDeviceId()).findSingleAttributeList(); + if (ToolUtil.isEmpty(executeRuleIds)) { + return new Pager<>(Collections.emptyList(), 0); + } + query.ruleId.in(executeRuleIds); } + query.orderBy().createTime.desc(); - List list = query.findList(); - if (ToolUtil.isNotEmpty(list)) { - list.forEach(service -> { - deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_SCENES).content(service.getRuleName()) - .triggerTime(LocalDateTimeUtils.formatTime(service.getCreateTime())) - .build()); - }); + PagedList pagedList = query.setFirstRow((deviceLogParam.getPage() - 1) * deviceLogParam.getMaxRow()) + .setMaxRows(deviceLogParam.getMaxRow()).findPagedList(); + + if (ToolUtil.isEmpty(pagedList.getList())) { + return new Pager<>(deviceLogDtoList, pagedList.getTotalCount()); } - return deviceLogDtoList; + //关联触发设备 + List eventRuleIds = pagedList.getList().parallelStream().map(ScenesTriggerRecord::getRuleId).collect(Collectors.toList()); + String sql = "select d.device_id,d.name,p.event_rule_id from product_event_relation p LEFT JOIN device d on d.device_id = p.relation_id where p.event_rule_id in (:eventRuleIds)"; + + List triggerDeviceDtos = DB.findDto(DeviceRelationDto.class, sql).setParameter("eventRuleIds", eventRuleIds).findList(); + Map> triggerDeviceMap = triggerDeviceDtos.parallelStream() + .collect(Collectors.groupingBy(DeviceRelationDto::getEventRuleId)); + + //关联 执行设备 + sql = "select d.device_id,d.name,p.event_rule_id from product_event_service p LEFT JOIN device d on d.device_id = p.execute_device_id where p.event_rule_id in (:eventRuleIds)"; + List executeDeviceDtos = DB.findDto(DeviceRelationDto.class, sql).setParameter("eventRuleIds", eventRuleIds).findList(); + Map> executeDeviceMap = executeDeviceDtos.parallelStream() + .collect(Collectors.groupingBy(DeviceRelationDto::getEventRuleId)); + + pagedList.getList().forEach(service -> { + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_SCENES).content(service.getRuleName()) + .triggerTime(LocalDateTimeUtils.formatTime(service.getCreateTime())).triggerType(service.getTriggerType()) + .triggerBody(Optional.ofNullable(service.getTriggerUser()).map(DefinitionsUtil::getSysUserName).orElse("-")) + .triggerDevice(triggerDeviceMap.get(service.getRuleId())).executeDevice(executeDeviceMap.get(service.getRuleId())) + .build()); + }); + return new Pager<>(deviceLogDtoList, pagedList.getTotalCount()); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index cc2d5786..aa7d0907 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -54,6 +54,27 @@ public class MultipleDeviceEventRuleService { @Autowired ScenesLogWorker scenesLogWorker; + private static final String EVENT_CLASSIFY = "1"; + + /** + * 场景列表 + * + * @param eventParm + * @return + */ + public List list(MultipleDeviceEventParm eventParm) { + QProductEvent query = new QProductEvent(); + + if (ToolUtil.isNotEmpty(eventParm.getEventRuleName())) { + query.eventRuleName.contains(eventParm.getEventRuleName()); + } + query.classify.eq(EVENT_CLASSIFY); + + List list = query.orderBy(" create_time desc").asDto(MultipleDeviceEventDto.class).findList(); + + return list; + } + /** * 设备联动 分页列表 * @@ -66,9 +87,7 @@ public Pager getEventByPage(MultipleDeviceEventParm even if (ToolUtil.isNotEmpty(eventParm.getEventRuleName())) { query.eventRuleName.contains(eventParm.getEventRuleName()); } - if (ToolUtil.isNotEmpty(eventParm.getClassify())) { - query.classify.eq(eventParm.getClassify()); - } + query.classify.eq(EVENT_CLASSIFY); List list = query.setFirstRow((eventParm.getPage() - 1) * eventParm.getMaxRow()) .setMaxRows(eventParm.getMaxRow()).orderBy(" create_time desc").asDto(MultipleDeviceEventDto.class).findList(); From 2d791464d9fc5531b6deb8f564dea7af738d63bf Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 9 Nov 2021 14:58:20 +0800 Subject: [PATCH 626/763] [style]: code format --- .../com/zmops/iot/media/mail/MailUtils.java | 53 +++++++++---------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/zeus-message/src/main/java/com/zmops/iot/media/mail/MailUtils.java b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailUtils.java index f1f31a41..ef3fc77f 100644 --- a/zeus-message/src/main/java/com/zmops/iot/media/mail/MailUtils.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailUtils.java @@ -1,13 +1,10 @@ package com.zmops.iot.media.mail; - - import com.sun.mail.util.MailSSLSocketFactory; import com.zmops.iot.domain.messages.MailSetting; import com.zmops.iot.domain.messages.NoticeResult; import org.springframework.mail.javamail.MimeMessageHelper; - import javax.mail.Authenticator; import javax.mail.PasswordAuthentication; import javax.mail.Session; @@ -19,66 +16,69 @@ /** * @author yefei - * + *

+ * 邮件发送工具类 **/ public class MailUtils { - public static void send(MailSetting setting, Consumer consumer) throws GeneralSecurityException, javax.mail.MessagingException { + public static void send(MailSetting setting, Consumer consumer) + throws GeneralSecurityException, javax.mail.MessagingException { + Properties prop = new Properties(); - prop.setProperty("mail.smtp.host", setting.getHost()); //设置QQ邮件服务器 - prop.setProperty("mail.smtp.port", setting.getPort().toString()); //设置QQ邮件服务器 - prop.setProperty("mail.transport.protocol", "smtp"); // 邮件发送协议 - prop.setProperty("mail.smtp.auth", "true"); // 需要验证用户名密码 - prop.setProperty("mail.smtp.connectiontimeout", "2000"); // 超时 + prop.setProperty("mail.smtp.host", setting.getHost()); + prop.setProperty("mail.smtp.port", setting.getPort().toString()); + prop.setProperty("mail.transport.protocol", "smtp"); + prop.setProperty("mail.smtp.auth", "true"); + prop.setProperty("mail.smtp.connectiontimeout", "2000"); prop.setProperty("mail.smtp.writetimeout", "5000"); - // QQ邮箱设置SSL加密 + if (setting.sslAvailable()) { MailSSLSocketFactory sf = new MailSSLSocketFactory(); sf.setTrustAllHosts(true); prop.put("mail.smtp.ssl.enable", "true"); prop.put("mail.smtp.ssl.socketFactory", sf); } + if (setting.tlsAvailable()) { - //不做服务器证书校验 prop.put("mail.smtp.ssl.checkserveridentity", "false"); - //添加信任的服务器地址,多个地址之间用空格分开 prop.put("mail.smtp.ssl.trust", setting.getHost()); prop.put("mail.smtp.host", setting.getHost()); prop.put("mail.smtp.starttls.enable", "true"); } - //1、创建定义整个应用程序所需的环境信息的 Session 对象 + Session session = Session.getInstance(prop, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { - //传入发件人的姓名和授权码 return new PasswordAuthentication(setting.getAccount(), setting.getPassword()); } }); - //2、通过session获取transport对象 - Transport transport = session.getTransport(); - //3、通过transport对象邮箱用户名和授权码连接邮箱服务器 + Transport transport = session.getTransport(); transport.connect(setting.getHost(), setting.getAccount(), setting.getPassword()); - //4、创建邮件,传入session对象 - MimeMessage mimeMessage = new MimeMessage(session); // 创建邮件对象 + MimeMessage mimeMessage = new MimeMessage(session); consumer.accept(mimeMessage); - //5、发送邮件 - transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients()); - //6、关闭连接 + transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients()); transport.close(); } + /** + * 仅限于页面测试功能调用 + * + * @param setting + * @param receiver + * @return + */ public static NoticeResult test(MailSetting setting, String receiver) { try { send(setting, mimeMessage -> { try { MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); - helper.setFrom(setting.getSender());//发送者 - helper.setTo(receiver);//接收者 - helper.setSubject("Zesu-iot邮件测试");//邮件标题 + helper.setFrom(setting.getSender()); + helper.setTo(receiver); + helper.setSubject("Zesu-iot邮件测试"); helper.setText("这是一封Zesu-iot测试邮件,请不要回复。", false); } catch (javax.mail.MessagingException e) { e.printStackTrace(); @@ -92,5 +92,4 @@ public static NoticeResult test(MailSetting setting, String receiver) { } - } From 1e47e77a5aa3375610e672a4fb43a717d6aa7668 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 9 Nov 2021 15:00:15 +0800 Subject: [PATCH 627/763] [fix]: add private --- .../com/zmops/iot/web/macro/controller/MacroController.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java index 9fe1ce4a..3ae0e840 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java @@ -37,13 +37,13 @@ public class MacroController { @Autowired - ZbxMacro zbxMacro; + private ZbxMacro zbxMacro; @Autowired - ZbxHost zbxHost; + private ZbxHost zbxHost; @Autowired - MacroService macroService; + private MacroService macroService; /** * 创建 变量 From 03b023513bf754c3b89d7a85712c75164de042a5 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 9 Nov 2021 15:11:35 +0800 Subject: [PATCH 628/763] [fix]: fix device log list --- .../com/zmops/iot/web/device/service/DeviceLogService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java index 93deb189..6940545c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java @@ -284,14 +284,14 @@ private Pager getScenesLog(DeviceLogParam deviceLogParam) { } //关联触发设备 List eventRuleIds = pagedList.getList().parallelStream().map(ScenesTriggerRecord::getRuleId).collect(Collectors.toList()); - String sql = "select d.device_id,d.name,p.event_rule_id from product_event_relation p LEFT JOIN device d on d.device_id = p.relation_id where p.event_rule_id in (:eventRuleIds)"; + String sql = "select distinct d.device_id,d.name,p.event_rule_id from product_event_relation p LEFT JOIN device d on d.device_id = p.relation_id where p.event_rule_id in (:eventRuleIds)"; List triggerDeviceDtos = DB.findDto(DeviceRelationDto.class, sql).setParameter("eventRuleIds", eventRuleIds).findList(); Map> triggerDeviceMap = triggerDeviceDtos.parallelStream() .collect(Collectors.groupingBy(DeviceRelationDto::getEventRuleId)); //关联 执行设备 - sql = "select d.device_id,d.name,p.event_rule_id from product_event_service p LEFT JOIN device d on d.device_id = p.execute_device_id where p.event_rule_id in (:eventRuleIds)"; + sql = "select distinct d.device_id,d.name,p.event_rule_id from product_event_service p LEFT JOIN device d on d.device_id = p.execute_device_id where p.event_rule_id in (:eventRuleIds)"; List executeDeviceDtos = DB.findDto(DeviceRelationDto.class, sql).setParameter("eventRuleIds", eventRuleIds).findList(); Map> executeDeviceMap = executeDeviceDtos.parallelStream() .collect(Collectors.groupingBy(DeviceRelationDto::getEventRuleId)); From b152694c43ec2d7ace45120dff8f45852ef1348e Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 9 Nov 2021 16:39:46 +0800 Subject: [PATCH 629/763] [feat]: add sysUser list --- .../web/sys/controller/SysUserController.java | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java index bb966069..0e8b9eef 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java @@ -2,9 +2,12 @@ import com.zmops.iot.core.log.BussinessLog; import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.sys.SysUser; +import com.zmops.iot.domain.sys.query.QSysUser; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.sys.dto.UserDto; @@ -15,6 +18,7 @@ import org.springframework.web.bind.annotation.*; import javax.validation.Valid; +import java.util.List; /** * @author nantian created at 2021/8/1 21:56 @@ -29,7 +33,7 @@ public class SysUserController { SysUserService sysUserService; /** - * 用户列表 + * 用户分页列表 * * @return */ @@ -39,6 +43,21 @@ public Pager userList(@RequestBody UserParam userParam) { return sysUserService.userList(userParam); } + /** + * 用户列表 + * + * @return + */ + @Permission(code = "mgr") + @PostMapping("/list") + public List list(@RequestBody UserParam userParam) { + QSysUser qSysUser = new QSysUser(); + if (ToolUtil.isNotEmpty(userParam.getName())) { + qSysUser.name.contains(userParam.getName()); + } + return qSysUser.findList(); + } + /** * 创建用户 * @@ -95,7 +114,7 @@ public ResponseData changePwd(@Valid @RequestBody UserParam user) { @RequestMapping("/reset") @BussinessLog(value = "重置密码") public ResponseData reset(@RequestParam("userId") Long userId) { - if(userId==1){ + if (userId == 1) { throw new ServiceException(BizExceptionEnum.CANT_CHANGE_ADMIN_PWD); } sysUserService.reset(userId); From d9da7cc5c4c26400dc13ffa57a35dd521606f712 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 9 Nov 2021 17:49:10 +0800 Subject: [PATCH 630/763] [fix]: fix user list --- .../com/zmops/iot/web/sys/controller/SysUserController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java index 0e8b9eef..a3b2d67f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java @@ -50,12 +50,12 @@ public Pager userList(@RequestBody UserParam userParam) { */ @Permission(code = "mgr") @PostMapping("/list") - public List list(@RequestBody UserParam userParam) { + public ResponseData list(@RequestBody UserParam userParam) { QSysUser qSysUser = new QSysUser(); if (ToolUtil.isNotEmpty(userParam.getName())) { qSysUser.name.contains(userParam.getName()); } - return qSysUser.findList(); + return ResponseData.success(qSysUser.findList()); } /** From cd9c6d2b566f8dd4b781ac87a42aa1fcdbb88b2c Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 9 Nov 2021 18:13:52 +0800 Subject: [PATCH 631/763] [feat]: event log add key --- .../java/com/zmops/iot/domain/device/EventTriggerRecord.java | 2 ++ .../main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java | 4 ++++ .../com/zmops/iot/web/device/service/DeviceLogService.java | 5 +++-- .../zmops/iot/web/event/service/IncidentEventProcess.java | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/EventTriggerRecord.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/EventTriggerRecord.java index b16e1677..52024117 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/EventTriggerRecord.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/EventTriggerRecord.java @@ -24,4 +24,6 @@ public class EventTriggerRecord { private String eventValue; private String deviceId; + + private String key; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java index faa9f202..a6508a58 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java @@ -41,6 +41,10 @@ public class DeviceLogDto { private String triggerBody; + private String key; + + private Long eventRuleId; + private List triggerDevice; private List executeDevice; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java index 6940545c..f536bd39 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java @@ -177,6 +177,7 @@ private Pager getEventLog(DeviceLogParam deviceLogParam) { pagedList.getList().forEach(service -> { deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_EVENT).content(service.getEventName()) .triggerTime(LocalDateTimeUtils.formatTime(service.getCreateTime())).deviceId(service.getDeviceId()) + .key(service.getKey()) .param(service.getEventValue()).build()); }); } @@ -226,7 +227,7 @@ private Pager getServiceLog(DeviceLogParam deviceLogParam) { DefinitionsUtil.getSysUserName(service.getExecuteUser()) : DefinitionsUtil.getTriggerName(service.getExecuteRuleId()); deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_SERVICE).content(service.getServiceName()) - .triggerTime(LocalDateTimeUtils.formatTime(service.getCreateTime())) + .triggerTime(LocalDateTimeUtils.formatTime(service.getCreateTime())).deviceId(service.getDeviceId()) .param(service.getParam()).triggerType(service.getExecuteType()).triggerBody(triggerBody).build()); }); } @@ -297,7 +298,7 @@ private Pager getScenesLog(DeviceLogParam deviceLogParam) { .collect(Collectors.groupingBy(DeviceRelationDto::getEventRuleId)); pagedList.getList().forEach(service -> { - deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_SCENES).content(service.getRuleName()) + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_SCENES).content(service.getRuleName()).eventRuleId(service.getRuleId()) .triggerTime(LocalDateTimeUtils.formatTime(service.getCreateTime())).triggerType(service.getTriggerType()) .triggerBody(Optional.ofNullable(service.getTriggerUser()).map(DefinitionsUtil::getSysUserName).orElse("-")) .triggerDevice(triggerDeviceMap.get(service.getRuleId())).executeDevice(executeDeviceMap.get(service.getRuleId())) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java index 5ba14553..794c503c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java @@ -53,6 +53,7 @@ public void process(EventDataDto eventData) { eventTriggerRecord.setDeviceId(deviceId); eventTriggerRecord.setEventName(productAttributeEvent.getName()); eventTriggerRecord.setEventValue(latestDtos.get(0).getOriginalValue()); + eventTriggerRecord.setKey(productAttributeEvent.getKey()); DB.insert(eventTriggerRecord); } From 97eb1c0b9d7df85d6e504bb7be92925fdf212d54 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 9 Nov 2021 18:23:14 +0800 Subject: [PATCH 632/763] [fix]: fix scene status --- .../controller/MultipleDeviceEventTriggerController.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java index fbacb4d7..02535a01 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java @@ -98,7 +98,7 @@ public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId) { public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Create.class) MultipleDeviceEventRule eventRule) { - Long eventRuleId = IdUtil.getSnowflake().nextId(); // ruleId, trigger name + Long eventRuleId = IdUtil.getSnowflake().nextId(); multipleDeviceEventRuleService.createDeviceEventRule(eventRuleId, eventRule); @@ -138,11 +138,10 @@ public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEn */ @PostMapping("/status") public ResponseData updateProductEventStatus(@RequestBody @Validated(value = BaseEntity.Status.class) MultipleDeviceEventRule eventRule) { - DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).eq("relationId", eventRule.getDeviceId()).asUpdate() + DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).asUpdate() .set("status", eventRule.getStatus()).update(); - ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()) - .relationId.eq(eventRule.getDeviceId()).findOne(); + ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).findOne(); if (null != productEventRelation && null != productEventRelation.getZbxId()) { zbxTrigger.triggerStatusUpdate(productEventRelation.getZbxId(), eventRule.getStatus().equals(CommonStatus.ENABLE.getCode()) ? "0" : "1"); From f890338b0b2cb1099b945085d981984f5bff4750 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 10 Nov 2021 10:35:37 +0800 Subject: [PATCH 633/763] [fix]: fix async tool --- .../async/callback/DefaultGroupCallback.java | 25 --- .../iot/async/callback/IGroupCallback.java | 38 ----- .../iot/async/callback/ITimeoutWorker.java | 28 ---- .../com/zmops/iot/async/executor/Async.java | 158 +----------------- .../iot/web/device/service/DeviceService.java | 2 + .../service/work/SaveZbxHostWorker.java | 5 +- 6 files changed, 9 insertions(+), 247 deletions(-) delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultGroupCallback.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IGroupCallback.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ITimeoutWorker.java diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultGroupCallback.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultGroupCallback.java deleted file mode 100644 index 349569ce..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultGroupCallback.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.zmops.iot.async.callback; - - -import com.zmops.iot.async.wrapper.WorkerWrapper; - -import java.util.List; - -/** - * @author wuweifeng wrote on 2019-12-27 - * @version 1.0 - * @deprecated deprecate at version 1.5.1 , see {@link IGroupCallback} . - */ -@SuppressWarnings("DeprecatedIsStillUsed") -@Deprecated -public class DefaultGroupCallback implements IGroupCallback { - @Override - public void success(List workerWrappers) { - // do nothing - } - - @Override - public void failure(List workerWrappers, Exception e) { - // do nothing - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IGroupCallback.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IGroupCallback.java deleted file mode 100644 index c11787c7..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IGroupCallback.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.zmops.iot.async.callback; - -import com.zmops.iot.async.executor.Async; -import com.zmops.iot.async.worker.OnceWork; -import com.zmops.iot.async.wrapper.WorkerWrapper; - -import java.util.Collection; -import java.util.List; -import java.util.concurrent.ExecutorService; - -/** - * 如果是异步执行整组的话,可以用这个组回调。已经废弃 - * - * @author wuweifeng wrote on 2019-11-19. - * @deprecated deprecate at version 1.5.1 - *

- * please use {@link Async#work(long, ExecutorService, Collection, String)}. - *

- * 该方法返回的{@link OnceWork}句柄,默认不会同步等待结束, - * 这便替代了原先的 - * {@link Async#beginWorkAsync(long, ExecutorService, IGroupCallback, WorkerWrapper[])} - *

- * 需要同步等待的话调用{@link OnceWork#awaitFinish()}即可。 - *

- */ -@SuppressWarnings("DeprecatedIsStillUsed") -@Deprecated -public interface IGroupCallback { - /** - * 成功后,可以从wrapper里去getWorkResult - */ - void success(List workerWrappers); - - /** - * 失败了,也可以从wrapper里去getWorkResult - */ - void failure(List workerWrappers, Exception e); -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ITimeoutWorker.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ITimeoutWorker.java deleted file mode 100644 index 8c074a3b..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ITimeoutWorker.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.zmops.iot.async.callback; - -/** - * @author wuweifeng wrote on 2019-12-20 - * @author tcsnzh - * 远古时期的代码,估计也没人会使用。但我也不确定,因此标注废弃。 - *

- * 难受的一比,为了屎山的兼容性要在代码里保留这么多屎盆。 - * @version 1.0 - * @deprecated deprecated by version 1.5.1--SNAPSHOT - */ -@Deprecated -public interface ITimeoutWorker extends IWorker { - /** - * 每个worker都可以设置超时时间 - * - * @return 毫秒超时时间 - */ - long timeOut(); - - /** - * 是否开启单个执行单元的超时功能(有时是一个group设置个超时,而不具备关心单个worker的超时) - *

注意,如果开启了单个执行单元的超时检测,将使线程池数量多出一倍

- * - * @return 是否开启 - */ - boolean enableTimeOut(); -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/Async.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/Async.java index 1fbd1d0d..4e39b2be 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/Async.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/Async.java @@ -1,18 +1,17 @@ package com.zmops.iot.async.executor; -import com.zmops.iot.async.callback.DefaultGroupCallback; -import com.zmops.iot.async.callback.IGroupCallback; import com.zmops.iot.async.executor.timer.SystemClock; import com.zmops.iot.async.worker.OnceWork; import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.async.wrapper.WorkerWrapperGroup; -import java.util.*; +import java.util.Arrays; +import java.util.Collection; +import java.util.Objects; +import java.util.UUID; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; /** * 核心工具类。 @@ -79,8 +78,7 @@ public static OnceWork work(long timeout, if (workerWrappers == null || workerWrappers.isEmpty()) { return OnceWork.emptyWork(workId); } - //保存上次执行的线程池变量(为了兼容以前的旧功能) - Async.lastExecutorService.set(Objects.requireNonNull(executorService, "ExecutorService is null ! ")); + final WorkerWrapperGroup group = new WorkerWrapperGroup(SystemClock.now(), timeout); final OnceWork.Impl onceWork = new OnceWork.Impl(group, workId); group.addWrapper(workerWrappers); @@ -111,17 +109,6 @@ public static OnceWork work(long timeout, */ private static volatile ThreadPoolExecutor COMMON_POOL; - /** - * 在以前(及现在)的版本中: - * 当执行{@link #beginWork(long, ExecutorService, Collection)}方法时,ExecutorService将会被记录下来。 - *

- * 注意,这里是个static,也就是只能有一个线程池。用户自定义线程池时,也只能定义一个 - * - * @deprecated 不明意义、毫无用处的字段。记录之前使用的线程池没啥意义。 - */ - @SuppressWarnings("DeprecatedIsStillUsed") - @Deprecated - private static final AtomicReference lastExecutorService = new AtomicReference<>(null); /** * 该方法将会返回{@link #COMMON_POOL},如果还未初始化则会懒加载初始化后再返回。 @@ -165,15 +152,6 @@ public String toString() { return COMMON_POOL; } - /** - * @deprecated 不明意义的输出信息的方法 - */ - @Deprecated - public static String getThreadCount() { - return "activeCount=" + COMMON_POOL.getActiveCount() + - ",completedCount=" + COMMON_POOL.getCompletedTaskCount() + - ",largestCount=" + COMMON_POOL.getLargestPoolSize(); - } /** * @param now 是否立即关闭 @@ -194,130 +172,4 @@ public static synchronized boolean shutDownCommonPool(boolean now) { return true; } - // ========================= deprecated ========================= - - /** - * 同步执行一次任务。 - * - * @return 只要执行未超时,就返回true。 - * @deprecated 已经被 {@link #work(long, ExecutorService, Collection, String)}方法取代。 - */ - @Deprecated - public static boolean beginWork(long timeout, - ExecutorService executorService, - Collection> workerWrappers) - throws InterruptedException { - final OnceWork work = work(timeout, executorService, workerWrappers); - work.awaitFinish(); - return work.hasTimeout(); - } - - /** - * 同步执行一次任务。 - * 如果想自定义线程池,请传pool。不自定义的话,就走默认的COMMON_POOL - * - * @deprecated 已经被 {@link #work(long, ExecutorService, Collection, String)}方法取代。 - */ - @Deprecated - public static boolean beginWork(long timeout, ExecutorService executorService, WorkerWrapper... workerWrapper) - throws ExecutionException, InterruptedException { - if (workerWrapper == null || workerWrapper.length == 0) { - return false; - } - Set workerWrappers = Arrays.stream(workerWrapper).collect(Collectors.toSet()); - //noinspection unchecked - return beginWork(timeout, executorService, workerWrappers); - } - - /** - * 同步阻塞,直到所有都完成,或失败 - * - * @deprecated 已经被 {@link #work(long, ExecutorService, Collection, String)}方法取代。 - */ - @Deprecated - public static boolean beginWork(long timeout, WorkerWrapper... workerWrapper) throws ExecutionException, InterruptedException { - return beginWork(timeout, getCommonPool(), workerWrapper); - } - - /** - * @deprecated 已经被 {@link #work(long, ExecutorService, Collection, String)}方法取代。 - */ - @Deprecated - public static void beginWorkAsync(long timeout, IGroupCallback groupCallback, WorkerWrapper... workerWrapper) { - beginWorkAsync(timeout, getCommonPool(), groupCallback, workerWrapper); - } - - /** - * 异步执行,直到所有都完成,或失败后,发起回调 - * - * @deprecated 已经被 {@link #work(long, ExecutorService, Collection, String)}方法取代。 - */ - @Deprecated - public static void beginWorkAsync(long timeout, ExecutorService executorService, IGroupCallback groupCallback, WorkerWrapper... workerWrapper) { - if (groupCallback == null) { - groupCallback = new DefaultGroupCallback(); - } - IGroupCallback finalGroupCallback = groupCallback; - if (executorService != null) { - executorService.submit(() -> { - try { - boolean success = beginWork(timeout, executorService, workerWrapper); - if (success) { - finalGroupCallback.success(Arrays.asList(workerWrapper)); - } else { - finalGroupCallback.failure(Arrays.asList(workerWrapper), new TimeoutException()); - } - } catch (ExecutionException | InterruptedException e) { - e.printStackTrace(); - finalGroupCallback.failure(Arrays.asList(workerWrapper), e); - } - }); - } else { - final ExecutorService commonPool = getCommonPool(); - commonPool.submit(() -> { - try { - boolean success = beginWork(timeout, commonPool, workerWrapper); - if (success) { - finalGroupCallback.success(Arrays.asList(workerWrapper)); - } else { - finalGroupCallback.failure(Arrays.asList(workerWrapper), new TimeoutException()); - } - } catch (ExecutionException | InterruptedException e) { - e.printStackTrace(); - finalGroupCallback.failure(Arrays.asList(workerWrapper), e); - } - }); - } - - } - - /** - * 关闭上次使用的线程池 - * - * @deprecated 因此在v1.5时加上了废弃注解。 - *

- * 这是一个很迷的方法,多线程时调用该方法的{@link #lastExecutorService}可能会被别的线程修改而引发不必要、不可控的错误。仅建议用来测试。 - * 另外,该方法现在不会关闭默认线程池。 - *

- */ - @Deprecated - public static void shutDown() { - final ExecutorService last = lastExecutorService.get(); - if (last != COMMON_POOL) { - shutDown(last); - } - } - - /** - * 关闭指定的线程池 - * - * @param executorService 指定的线程池。传入null则会关闭默认线程池。 - * @deprecated 没啥用的方法,要关闭线程池还不如直接调用线程池的关闭方法,避免歧义。 - */ - @Deprecated - public static void shutDown(ExecutorService executorService) { - if (executorService != null) { - executorService.shutdown(); - } - } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 50f9aa6a..fbef862e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -2,6 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.async.callback.ICallback; import com.zmops.iot.async.executor.Async; import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.Device; @@ -266,6 +267,7 @@ public String create(DeviceDto deviceDto) { WorkerWrapper saveZbxHostWork = WorkerWrapper.builder().id("saveZbxHostWork") .worker(saveZbxHostWorker).param(deviceDto) .nextOf(updateAttrZbxIdWork, updateDeviceZbxIdWork, saveOtherWork) + .callback(ICallback.PRINT_EXCEPTION_STACK_TRACE) .build(); WorkerWrapper deviceWork = WorkerWrapper.builder().id("saveDvice") diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java index 780f085c..f3820079 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java @@ -4,7 +4,6 @@ import com.zmops.iot.async.callback.IWorker; import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.constant.ConstantsContext; -import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.query.QDeviceGroup; import com.zmops.iot.domain.product.query.QProduct; import com.zmops.iot.util.ToolUtil; @@ -33,7 +32,7 @@ public class SaveZbxHostWorker implements IWorker { @Override public String action(DeviceDto deviceDto, Map> map) { - log.debug("step 5:SaveZbxHostWorker----DEVICEID:{}…………",deviceDto.getDeviceId()); + log.debug("step 5:SaveZbxHostWorker----DEVICEID:{}…………", deviceDto.getDeviceId()); //设备ID 作为zbx HOST name String host = deviceDto.getDeviceId(); @@ -49,7 +48,7 @@ public String action(DeviceDto deviceDto, Map> map) } else { s = zbxHost.hostCreate(host, hostGrpIds, templateId); } - log.debug("step 5:SaveZbxHostWorker----DEVICEID:{} complete",deviceDto.getDeviceId()); + log.debug("step 5:SaveZbxHostWorker----DEVICEID:{} complete", deviceDto.getDeviceId()); return s; } From 47929a939e314c781243494e363384a94832422e Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 10 Nov 2021 11:33:45 +0800 Subject: [PATCH 634/763] [fix]: asynctool update --- .../iot/async/callback/DefaultCallback.java | 20 +- .../async/callback/DefaultGroupCallback.java | 9 +- .../zmops/iot/async/callback/ICallback.java | 25 +- .../iot/async/callback/IGroupCallback.java | 20 +- .../iot/async/callback/ITimeoutWorker.java | 8 - .../com/zmops/iot/async/callback/IWorker.java | 7 +- .../iot/async/exception/CancelException.java | 15 - .../exception/EndsNormallyException.java | 27 - .../iot/async/exception/SkippedException.java | 5 +- .../com/zmops/iot/async/executor/Async.java | 285 +---- .../iot/async/executor/PollingCenter.java | 87 -- .../java/com/zmops/iot/async/util/BiInt.java | 109 -- .../util/collection/AbstractArray2D.java | 74 -- .../collection/AbstractDirectedGraph.java | 88 -- .../util/collection/AbstractStoreArk.java | 22 - .../iot/async/util/collection/Array2D.java | 169 --- .../async/util/collection/CachedStoreArk.java | 60 - .../util/collection/CommonDirectedGraph.java | 145 --- .../async/util/collection/CommonStoreArk.java | 159 --- .../async/util/collection/DirectedGraph.java | 185 --- .../iot/async/util/collection/Graph.java | 106 -- .../async/util/collection/SparseArray2D.java | 229 ---- .../iot/async/util/collection/StoreArk.java | 69 -- .../async/util/timer/AbstractWheelTimer.java | 18 - .../async/util/timer/HashedWheelTimer.java | 665 ---------- .../zmops/iot/async/util/timer/Timeout.java | 37 - .../com/zmops/iot/async/util/timer/Timer.java | 43 - .../zmops/iot/async/util/timer/TimerTask.java | 10 - .../zmops/iot/async/worker/DependWrapper.java | 59 + .../com/zmops/iot/async/worker/OnceWork.java | 386 ------ .../zmops/iot/async/worker/ResultState.java | 1 - .../zmops/iot/async/worker/WorkResult.java | 26 +- .../wrapper/QuickBuildWorkerWrapper.java | 100 -- .../async/wrapper/StableWorkerWrapper.java | 72 -- .../wrapper/StableWorkerWrapperBuilder.java | 504 -------- .../iot/async/wrapper/WorkerWrapper.java | 1069 +++++++---------- .../async/wrapper/WorkerWrapperBuilder.java | 291 ----- .../iot/async/wrapper/WorkerWrapperGroup.java | 211 ---- .../wrapper/strategy/WrapperStrategy.java | 159 --- .../depend/DependMustStrategyMapper.java | 100 -- .../depend/DependOnUpWrapperStrategy.java | 74 -- .../DependOnUpWrapperStrategyMapper.java | 68 -- .../strategy/depend/DependenceAction.java | 108 -- .../strategy/depend/DependenceStrategy.java | 270 ----- .../wrapper/strategy/skip/SkipStrategy.java | 54 - .../iot/web/device/service/DeviceService.java | 69 +- .../MultipleDeviceEventRuleService.java | 22 +- .../service/work/DeviceEventLogWorker.java | 6 +- .../service/work/DeviceServiceLogWorker.java | 2 +- .../service/work/SaveAttributeWorker.java | 2 +- .../service/work/SaveDeviceGrpWorker.java | 2 +- .../device/service/work/SaveDeviceWorker.java | 2 +- .../device/service/work/SaveOtherWorker.java | 2 +- .../device/service/work/SaveTagWorker.java | 2 +- .../service/work/SaveZbxHostWorker.java | 2 +- .../device/service/work/ScenesLogWorker.java | 2 +- .../service/work/UpdateAttrZbxIdWorker.java | 2 +- .../service/work/UpdateDeviceZbxIdWorker.java | 2 +- .../service/work/UpdateZbxTagWorker.java | 2 +- .../event/service/ServiceEventProcess.java | 28 +- .../ProductEventTriggerController.java | 22 +- .../service/ProductAttributeEventService.java | 16 +- .../service/ProductEventRuleService.java | 4 +- .../product/service/ProductModelService.java | 17 +- .../product/service/ProductSvcService.java | 15 +- .../work/AsyncAttrEventZbxIdWorker.java | 2 +- .../service/work/AsyncAttrZbxIdWorker.java | 2 +- .../work/SaveProdAttrEventTriggerWorker.java | 2 +- .../service/work/SaveProdAttrEventWorker.java | 2 +- .../service/work/SaveProdAttrWorker.java | 2 +- .../work/SaveProdStatusTriggerWorker.java | 2 +- .../service/work/SaveProdSvcWorker.java | 2 +- .../work/SaveProductEventTriggerWorker.java | 2 +- .../work/UpdateAttributeEventWorker.java | 2 +- .../service/work/UpdateAttributeWorker.java | 2 +- .../service/work/UpdateProdSvcWorker.java | 2 +- .../work/UpdateProductEventTriggerWorker.java | 2 +- 77 files changed, 740 insertions(+), 5753 deletions(-) delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/CancelException.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/EndsNormallyException.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/PollingCenter.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/BiInt.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractArray2D.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractDirectedGraph.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractStoreArk.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/Array2D.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CachedStoreArk.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonDirectedGraph.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonStoreArk.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/DirectedGraph.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/Graph.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/SparseArray2D.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/StoreArk.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/AbstractWheelTimer.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/HashedWheelTimer.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/Timeout.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/Timer.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/TimerTask.java create mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/DependWrapper.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/OnceWork.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/QuickBuildWorkerWrapper.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/StableWorkerWrapper.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/StableWorkerWrapperBuilder.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapperBuilder.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapperGroup.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/WrapperStrategy.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependMustStrategyMapper.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependOnUpWrapperStrategy.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependOnUpWrapperStrategyMapper.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceAction.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceStrategy.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/skip/SkipStrategy.java diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultCallback.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultCallback.java index 5a9e98e5..77878866 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultCallback.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultCallback.java @@ -5,31 +5,17 @@ /** * 默认回调类,如果不设置的话,会默认给这个回调 - * * @author wuweifeng wrote on 2019-11-19. */ public class DefaultCallback implements ICallback { - private static final DefaultCallback instance = new DefaultCallback() { - @Override - public String toString() { - return "(DefaultCallback instance)"; - } - }; - - public static DefaultCallback getInstance() { - return instance; - } - @Override public void begin() { - // do nothing + } - /** - * 默认情况啥回调都没有,而且将吞掉所有异常显示(只保存在{@link WorkResult}中) - */ @Override public void result(boolean success, T param, WorkResult workResult) { - // do nothing + } + } diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultGroupCallback.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultGroupCallback.java index 349569ce..af85cfc4 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultGroupCallback.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultGroupCallback.java @@ -1,6 +1,5 @@ package com.zmops.iot.async.callback; - import com.zmops.iot.async.wrapper.WorkerWrapper; import java.util.List; @@ -8,18 +7,16 @@ /** * @author wuweifeng wrote on 2019-12-27 * @version 1.0 - * @deprecated deprecate at version 1.5.1 , see {@link IGroupCallback} . */ -@SuppressWarnings("DeprecatedIsStillUsed") -@Deprecated public class DefaultGroupCallback implements IGroupCallback { + @Override public void success(List workerWrappers) { - // do nothing + } @Override public void failure(List workerWrappers, Exception e) { - // do nothing + } } diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ICallback.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ICallback.java index 03cccd68..0eaf131f 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ICallback.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ICallback.java @@ -1,7 +1,6 @@ package com.zmops.iot.async.callback; -import com.zmops.iot.async.exception.EndsNormallyException; import com.zmops.iot.async.worker.WorkResult; /** @@ -12,6 +11,7 @@ */ @FunctionalInterface public interface ICallback { + /** * 任务开始的监听 */ @@ -21,29 +21,6 @@ default void begin() { /** * 耗时操作执行完毕后,就给value注入值 - *

- * 只要Wrapper被调用后成功或失败/超时,该方法都会被执行。 */ void result(boolean success, T param, WorkResult workResult); - - /** - * 提供常量选项: - *

- * 如果发生了异常,则打印异常信息。 - * 正常结束(例如取消、跳过)的异常{@link com.zmops.iot.async.exception.EndsNormallyException}不会打印。 - */ - ICallback PRINT_EXCEPTION_STACK_TRACE = new ICallback() { - @Override - public void result(boolean success, Object param, WorkResult workResult) { - Exception ex = workResult.getEx(); - if (ex != null && !(ex instanceof EndsNormallyException)) { - ex.printStackTrace(); - } - } - - @Override - public String toString() { - return "PRINT_EXCEPTION_STACK_TRACE"; - } - }; } diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IGroupCallback.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IGroupCallback.java index c11787c7..a756022d 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IGroupCallback.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IGroupCallback.java @@ -1,36 +1,18 @@ package com.zmops.iot.async.callback; -import com.zmops.iot.async.executor.Async; -import com.zmops.iot.async.worker.OnceWork; import com.zmops.iot.async.wrapper.WorkerWrapper; -import java.util.Collection; import java.util.List; -import java.util.concurrent.ExecutorService; /** - * 如果是异步执行整组的话,可以用这个组回调。已经废弃 - * + * 如果是异步执行整组的话,可以用这个组回调。不推荐使用 * @author wuweifeng wrote on 2019-11-19. - * @deprecated deprecate at version 1.5.1 - *

- * please use {@link Async#work(long, ExecutorService, Collection, String)}. - *

- * 该方法返回的{@link OnceWork}句柄,默认不会同步等待结束, - * 这便替代了原先的 - * {@link Async#beginWorkAsync(long, ExecutorService, IGroupCallback, WorkerWrapper[])} - *

- * 需要同步等待的话调用{@link OnceWork#awaitFinish()}即可。 - *

*/ -@SuppressWarnings("DeprecatedIsStillUsed") -@Deprecated public interface IGroupCallback { /** * 成功后,可以从wrapper里去getWorkResult */ void success(List workerWrappers); - /** * 失败了,也可以从wrapper里去getWorkResult */ diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ITimeoutWorker.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ITimeoutWorker.java index 8c074a3b..4190efa3 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ITimeoutWorker.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ITimeoutWorker.java @@ -2,18 +2,11 @@ /** * @author wuweifeng wrote on 2019-12-20 - * @author tcsnzh - * 远古时期的代码,估计也没人会使用。但我也不确定,因此标注废弃。 - *

- * 难受的一比,为了屎山的兼容性要在代码里保留这么多屎盆。 * @version 1.0 - * @deprecated deprecated by version 1.5.1--SNAPSHOT */ -@Deprecated public interface ITimeoutWorker extends IWorker { /** * 每个worker都可以设置超时时间 - * * @return 毫秒超时时间 */ long timeOut(); @@ -21,7 +14,6 @@ public interface ITimeoutWorker extends IWorker { /** * 是否开启单个执行单元的超时功能(有时是一个group设置个超时,而不具备关心单个worker的超时) *

注意,如果开启了单个执行单元的超时检测,将使线程池数量多出一倍

- * * @return 是否开启 */ boolean enableTimeOut(); diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IWorker.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IWorker.java index 00b4d2a6..5cf2e8c8 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IWorker.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IWorker.java @@ -1,10 +1,9 @@ package com.zmops.iot.async.callback; +import java.util.Map; import com.zmops.iot.async.wrapper.WorkerWrapper; -import java.util.Map; - /** * 每个最小执行单元需要实现该接口 * @@ -18,10 +17,10 @@ public interface IWorker { * @param object object * @param allWrappers 任务包装 */ - V action(T object, Map> allWrappers); + V action(T object, Map allWrappers); /** - * 超时、异常、跳过时,返回的默认值 + * 超时、异常时,返回的默认值 * * @return 默认值 */ diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/CancelException.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/CancelException.java deleted file mode 100644 index 6e5b4617..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/CancelException.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.zmops.iot.async.exception; - -/** - * 整组取消,设置该异常。 - * - * @author tcsnzh[zh.jobs@foxmail.com] create this in 2021/5/25-下午6:12 - */ -public class CancelException extends EndsNormallyException { - public CancelException() { - } - - public CancelException(String message) { - super(message); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/EndsNormallyException.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/EndsNormallyException.java deleted file mode 100644 index 336b495c..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/EndsNormallyException.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.zmops.iot.async.exception; - -/** - * 该异常表示此任务单元是正常结束的。 - * - * @author tcsnzh[zh.jobs@foxmail.com] create this in 2021/6/5-下午11:57 - */ -public abstract class EndsNormallyException extends RuntimeException { - public EndsNormallyException() { - } - - public EndsNormallyException(String message) { - super(message); - } - - public EndsNormallyException(String message, Throwable cause) { - super(message, cause); - } - - public EndsNormallyException(Throwable cause) { - super(cause); - } - - public EndsNormallyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/SkippedException.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/SkippedException.java index 03520d72..cf8dbf24 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/SkippedException.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/SkippedException.java @@ -2,13 +2,12 @@ /** * 如果任务在执行之前,自己后面的任务已经执行完或正在被执行,则抛该exception - * * @author wuweifeng wrote on 2020-02-18 * @version 1.0 */ -public class SkippedException extends EndsNormallyException { +public class SkippedException extends RuntimeException { public SkippedException() { - this(null); + super(); } public SkippedException(String message) { diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/Async.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/Async.java index 1fbd1d0d..bd6b3d16 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/Async.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/Async.java @@ -3,256 +3,86 @@ import com.zmops.iot.async.callback.DefaultGroupCallback; import com.zmops.iot.async.callback.IGroupCallback; -import com.zmops.iot.async.executor.timer.SystemClock; -import com.zmops.iot.async.worker.OnceWork; import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.async.wrapper.WorkerWrapperGroup; import java.util.*; import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; /** - * 核心工具类。 + * 类入口,可以根据自己情况调整core线程的数量 * * @author wuweifeng wrote on 2019-12-18 * @version 1.0 */ public class Async { - - // ========================= 任务执行核心代码 ========================= - - /** - * {@link #work(long, ExecutorService, Collection, String)}方法的简易封装。 - * 使用uuid作为工作id。使用{@link #getCommonPool()}作为线程池。 - */ - public static OnceWork work(long timeout, - Collection> workerWrappers) { - return work(timeout, getCommonPool(), workerWrappers); - } - - /** - * {@link #work(long, ExecutorService, Collection, String)}方法的简易封装。 - * 可变参式传入。使用uuid作为工作id。使用{@link #getCommonPool()}作为线程池。 - */ - public static OnceWork work(long timeout, - WorkerWrapper... workerWrappers) { - return work(timeout, getCommonPool(), workerWrappers); - } - - /** - * {@link #work(long, ExecutorService, Collection, String)}方法的简易封装。 - * 可变参式传入。使用uuid作为工作id。 - */ - public static OnceWork work(long timeout, - ExecutorService executorService, - WorkerWrapper... workerWrappers) { - return work(timeout, executorService, Arrays.asList( - Objects.requireNonNull(workerWrappers, "workerWrappers array is null"))); - } - - /** - * {@link #work(long, ExecutorService, Collection, String)}方法的简易封装。 - * 省略工作id,使用uuid。 - */ - public static OnceWork work(long timeout, - ExecutorService executorService, - Collection> workerWrappers) { - return work(timeout, executorService, workerWrappers, UUID.randomUUID().toString()); - } - - /** - * 核心方法。该方法不是同步阻塞执行的。如果想要同步阻塞执行,则调用返回值的{@link OnceWork#awaitFinish()}即可。 - * - * @param timeout 全组超时时间 - * @param executorService 执行线程池 - * @param workerWrappers 任务容器集合 - * @param workId 本次工作id - * @return 返回 {@link OnceWork}任务句柄对象。 - */ - public static OnceWork work(long timeout, - ExecutorService executorService, - Collection> workerWrappers, - String workId) { - if (workerWrappers == null || workerWrappers.isEmpty()) { - return OnceWork.emptyWork(workId); - } - //保存上次执行的线程池变量(为了兼容以前的旧功能) - Async.lastExecutorService.set(Objects.requireNonNull(executorService, "ExecutorService is null ! ")); - final WorkerWrapperGroup group = new WorkerWrapperGroup(SystemClock.now(), timeout); - final OnceWork.Impl onceWork = new OnceWork.Impl(group, workId); - group.addWrapper(workerWrappers); - workerWrappers.forEach(wrapper -> { - if (wrapper == null) { - return; - } - executorService.submit(() -> wrapper.work(executorService, timeout, group)); - }); - return onceWork; - } - - // ========================= 设置/属性选项 ========================= - /** - * 默认线程池。 - *

- * 在v1.4及之前,该COMMON_POLL是被写死的。 - *

- * 自v1.5后: - * 该线程池将会在第一次调用{@link #getCommonPool()}时懒加载。 - * tip: - * 要注意,{@link #work(long, WorkerWrapper[])}、{@link #work(long, Collection)}这些方法, - * 不传入线程池就会默认调用{@link #getCommonPool()},就会初始化线程池。 - *

- * 该线程池将会给线程取名为asyncTool-commonPool-thread-0(数字不重复)。 - *

+ * 默认线程池 */ - private static volatile ThreadPoolExecutor COMMON_POOL; - + private static final ThreadPoolExecutor COMMON_POOL = + new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors() * 2, 1024, + 15L, TimeUnit.SECONDS, + new LinkedBlockingQueue<>(), + (ThreadFactory) Thread::new); /** - * 在以前(及现在)的版本中: - * 当执行{@link #beginWork(long, ExecutorService, Collection)}方法时,ExecutorService将会被记录下来。 - *

* 注意,这里是个static,也就是只能有一个线程池。用户自定义线程池时,也只能定义一个 - * - * @deprecated 不明意义、毫无用处的字段。记录之前使用的线程池没啥意义。 */ - @SuppressWarnings("DeprecatedIsStillUsed") - @Deprecated - private static final AtomicReference lastExecutorService = new AtomicReference<>(null); + private static ExecutorService executorService; /** - * 该方法将会返回{@link #COMMON_POOL},如果还未初始化则会懒加载初始化后再返回。 - * 详情参考{@link #COMMON_POOL}上的注解 + * 出发点 */ - public static ThreadPoolExecutor getCommonPool() { - if (COMMON_POOL == null) { - synchronized (Async.class) { - if (COMMON_POOL == null) { - COMMON_POOL = new ThreadPoolExecutor( - Runtime.getRuntime().availableProcessors() * 2, - 1024, - 15L, - TimeUnit.SECONDS, - new LinkedBlockingQueue<>(), - new ThreadFactory() { - private final AtomicLong threadCount = new AtomicLong(0); - - @Override - public Thread newThread(Runnable r) { - Thread t = new Thread(r, - "asyncTool-commonPool-thread-" + threadCount.getAndIncrement()); - t.setDaemon(true); - return t; - } - - @Override - public String toString() { - return "asyncTool-commonPool-threadFactory"; - } - } - ) { - @Override - public String toString() { - return "asyncTool-commonPool"; - } - }; - } - } - } - return COMMON_POOL; - } - - /** - * @deprecated 不明意义的输出信息的方法 - */ - @Deprecated - public static String getThreadCount() { - return "activeCount=" + COMMON_POOL.getActiveCount() + - ",completedCount=" + COMMON_POOL.getCompletedTaskCount() + - ",largestCount=" + COMMON_POOL.getLargestPoolSize(); - } - - /** - * @param now 是否立即关闭 - * @return 如果尚未调用过{@link #getCommonPool()},即没有初始化默认线程池,返回false。否则返回true。 - */ - @SuppressWarnings("unused") - public static synchronized boolean shutDownCommonPool(boolean now) { - if (COMMON_POOL == null) { + public static boolean beginWork(long timeout, ExecutorService executorService, List workerWrappers) throws ExecutionException, InterruptedException { + if (workerWrappers == null || workerWrappers.size() == 0) { return false; } - if (!COMMON_POOL.isShutdown()) { - if (now) { - COMMON_POOL.shutdownNow(); - } else { - COMMON_POOL.shutdown(); + //保存线程池变量 + Async.executorService = executorService; + //定义一个map,存放所有的wrapper,key为wrapper的唯一id,value是该wrapper,可以从value中获取wrapper的result + Map forParamUseWrappers = new ConcurrentHashMap<>(); + CompletableFuture[] futures = new CompletableFuture[workerWrappers.size()]; + for (int i = 0; i < workerWrappers.size(); i++) { + WorkerWrapper wrapper = workerWrappers.get(i); + futures[i] = CompletableFuture.runAsync(() -> wrapper.work(executorService, timeout, forParamUseWrappers), executorService); + } + try { + CompletableFuture.allOf(futures).get(timeout, TimeUnit.MILLISECONDS); + return true; + } catch (TimeoutException e) { + Set set = new HashSet<>(); + totalWorkers(workerWrappers, set); + for (WorkerWrapper wrapper : set) { + wrapper.stopNow(); } + return false; } - return true; - } - - // ========================= deprecated ========================= - - /** - * 同步执行一次任务。 - * - * @return 只要执行未超时,就返回true。 - * @deprecated 已经被 {@link #work(long, ExecutorService, Collection, String)}方法取代。 - */ - @Deprecated - public static boolean beginWork(long timeout, - ExecutorService executorService, - Collection> workerWrappers) - throws InterruptedException { - final OnceWork work = work(timeout, executorService, workerWrappers); - work.awaitFinish(); - return work.hasTimeout(); } /** - * 同步执行一次任务。 * 如果想自定义线程池,请传pool。不自定义的话,就走默认的COMMON_POOL - * - * @deprecated 已经被 {@link #work(long, ExecutorService, Collection, String)}方法取代。 */ - @Deprecated - public static boolean beginWork(long timeout, ExecutorService executorService, WorkerWrapper... workerWrapper) - throws ExecutionException, InterruptedException { + public static boolean beginWork(long timeout, ExecutorService executorService, WorkerWrapper... workerWrapper) throws ExecutionException, InterruptedException { if (workerWrapper == null || workerWrapper.length == 0) { return false; } - Set workerWrappers = Arrays.stream(workerWrapper).collect(Collectors.toSet()); - //noinspection unchecked + List workerWrappers = Arrays.stream(workerWrapper).collect(Collectors.toList()); return beginWork(timeout, executorService, workerWrappers); } /** * 同步阻塞,直到所有都完成,或失败 - * - * @deprecated 已经被 {@link #work(long, ExecutorService, Collection, String)}方法取代。 */ - @Deprecated public static boolean beginWork(long timeout, WorkerWrapper... workerWrapper) throws ExecutionException, InterruptedException { - return beginWork(timeout, getCommonPool(), workerWrapper); + return beginWork(timeout, COMMON_POOL, workerWrapper); } - /** - * @deprecated 已经被 {@link #work(long, ExecutorService, Collection, String)}方法取代。 - */ - @Deprecated public static void beginWorkAsync(long timeout, IGroupCallback groupCallback, WorkerWrapper... workerWrapper) { - beginWorkAsync(timeout, getCommonPool(), groupCallback, workerWrapper); + beginWorkAsync(timeout, COMMON_POOL, groupCallback, workerWrapper); } /** * 异步执行,直到所有都完成,或失败后,发起回调 - * - * @deprecated 已经被 {@link #work(long, ExecutorService, Collection, String)}方法取代。 */ - @Deprecated public static void beginWorkAsync(long timeout, ExecutorService executorService, IGroupCallback groupCallback, WorkerWrapper... workerWrapper) { if (groupCallback == null) { groupCallback = new DefaultGroupCallback(); @@ -273,10 +103,9 @@ public static void beginWorkAsync(long timeout, ExecutorService executorService, } }); } else { - final ExecutorService commonPool = getCommonPool(); - commonPool.submit(() -> { + COMMON_POOL.submit(() -> { try { - boolean success = beginWork(timeout, commonPool, workerWrapper); + boolean success = beginWork(timeout, COMMON_POOL, workerWrapper); if (success) { finalGroupCallback.success(Arrays.asList(workerWrapper)); } else { @@ -292,32 +121,42 @@ public static void beginWorkAsync(long timeout, ExecutorService executorService, } /** - * 关闭上次使用的线程池 - * - * @deprecated 因此在v1.5时加上了废弃注解。 - *

- * 这是一个很迷的方法,多线程时调用该方法的{@link #lastExecutorService}可能会被别的线程修改而引发不必要、不可控的错误。仅建议用来测试。 - * 另外,该方法现在不会关闭默认线程池。 - *

+ * total work units */ - @Deprecated - public static void shutDown() { - final ExecutorService last = lastExecutorService.get(); - if (last != COMMON_POOL) { - shutDown(last); + @SuppressWarnings("unchecked") + private static void totalWorkers(List workerWrappers, Set set) { + set.addAll(workerWrappers); + for (WorkerWrapper wrapper : workerWrappers) { + if (wrapper.getNextWrappers() == null) { + continue; + } + List wrappers = wrapper.getNextWrappers(); + totalWorkers(wrappers, set); } + } /** - * 关闭指定的线程池 - * - * @param executorService 指定的线程池。传入null则会关闭默认线程池。 - * @deprecated 没啥用的方法,要关闭线程池还不如直接调用线程池的关闭方法,避免歧义。 + * close thread pool + */ + public static void shutDown() { + shutDown(executorService); + } + + /** + * close thread pool */ - @Deprecated public static void shutDown(ExecutorService executorService) { if (executorService != null) { executorService.shutdown(); + } else { + COMMON_POOL.shutdown(); } } + + public static String getThreadCount() { + return "activeCount=" + COMMON_POOL.getActiveCount() + + " completedCount " + COMMON_POOL.getCompletedTaskCount() + + " largestCount " + COMMON_POOL.getLargestPoolSize(); + } } diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/PollingCenter.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/PollingCenter.java deleted file mode 100644 index ebb3710e..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/PollingCenter.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.zmops.iot.async.executor; - -import com.zmops.iot.async.util.timer.HashedWheelTimer; -import com.zmops.iot.async.util.timer.Timeout; -import com.zmops.iot.async.util.timer.Timer; -import com.zmops.iot.async.util.timer.TimerTask; -import com.zmops.iot.async.wrapper.WorkerWrapperGroup; - -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; - -/** - * 检查{@link WorkerWrapperGroup}是否调用完成的轮询中心。 - * 内部使用时间轮进行轮询。 - *

- * =========================================================================================== - *

- * 在v1.4及以前的版本,存在如下问题: - * > - * 在使用线程数量较少的线程池进行beginWork时,调用WorkerWrapper#beginNext方法时, - * 会因为本线程等待下游Wrapper执行完成而存在线程耗尽bug。线程池会死翘翘的僵住、动弹不得。 - * > - * 例如仅有2个线程的线程池,执行以下任务: - * {@code - *

- * 这是旧版本(v1.4及以前)中可能会引发线程耗尽bug的情况,在test/v15.wrappertest中示例testThreadPolling_V14Bug说明了这个bug - * 线程数:2 - * A(5ms)--B1(10ms) ---|--> C1(5ms) - * . \ | (B1、B2任一完成可执行C1、C2) - * . ---> B2(20ms) --|--> C2(5ms) - *

- * } - * 线程1执行了A,然后在{@link CompletableFuture#allOf(CompletableFuture[])}等待B1与B2执行完成。 - * 线程2执行了B1或B2中的一个,也在allOf方法等待C1、C2完成。 - * 结果没有线程执行C和B2了,导致超时而死,并且这个线程池线程有可能被耗尽。 - * > - * - * @author create by TcSnZh on 2021/5/9-下午9:22 - */ -public class PollingCenter { - - // ========== singleton instance ========== - - private static final PollingCenter instance = new PollingCenter(); - - public static PollingCenter getInstance() { - return instance; - } - - // ========== fields and methods ========== - - public void checkGroup(WorkerWrapperGroup.CheckFinishTask task) { - checkGroup(task, 0); - } - - public void checkGroup(WorkerWrapperGroup.CheckFinishTask task, long daley) { - timer.newTimeout(task, daley, TimeUnit.MILLISECONDS); - } - - private final Timer timer = new Timer() { - private final HashedWheelTimer hashedWheelTimer = new HashedWheelTimer( - r -> { - Thread thread = new Thread(r, "asyncTool-pollingThread"); - thread.setDaemon(true); - return thread; - }, - 1, - TimeUnit.MILLISECONDS, - 1024); - - @Override - public Timeout newTimeout(TimerTask task, long delay, TimeUnit unit) { - return hashedWheelTimer.newTimeout(task, delay, unit); - } - - @Override - public Set stop() { - return hashedWheelTimer.stop(); - } - - @Override - public String toString() { - return "PollingCenter.timer"; - } - }; -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/BiInt.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/BiInt.java deleted file mode 100644 index bdc9952d..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/BiInt.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.zmops.iot.async.util; - -import java.util.Comparator; - -/** - * 两个int值包装类。重写了{@link #hashCode()}与{@link #equals(Object)} - * - * @author create by TcSnZh on 2021/5/16-上午1:50 - */ -public final class BiInt { - // properties - - private final int m; - private final int n; - - public static final Comparator cmp_m_asc = Comparator.comparingInt(BiInt::getM); - public static final Comparator cmp_n_asc = Comparator.comparingInt(BiInt::getN); - public static final Comparator cmp_m_desc = cmp_m_asc.reversed(); - public static final Comparator cmp_n_desc = cmp_n_asc.reversed(); - public static final Comparator cmp_m_asc_n_asc = - cmp_m_asc.thenComparing(cmp_n_asc); - public static final Comparator cmp_m_asc_n_desc = - cmp_m_asc.thenComparing(cmp_n_desc); - public static final Comparator cmp_m_desc_n_asc = - cmp_m_desc.thenComparing(cmp_n_asc); - public static final Comparator cmp_m_desc_n_desc = - cmp_m_desc.thenComparing(cmp_n_desc); - public static final Comparator cmp_n_asc_m_asc = - cmp_n_asc.thenComparing(cmp_m_asc); - public static final Comparator cmp_n_asc_m_desc = - cmp_n_asc.thenComparing(cmp_m_desc); - public static final Comparator cmp_n_desc_m_asc = - cmp_n_desc.thenComparing(cmp_m_asc); - public static final Comparator cmp_n_desc_m_desc = - cmp_n_desc.thenComparing(cmp_m_desc); - - /** - * private constructor , please use {@link #of(int, int)} to build Idx object. - */ - private BiInt(int m, int n) { - this.m = m; - this.n = n; - } - - // getter - - public int getM() { - return m; - } - - public int getN() { - return n; - } - - // hashcode and equals - - @Override - public int hashCode() { - return m ^ n; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (!(o instanceof BiInt)) - return false; - BiInt idx = (BiInt) o; - return m == idx.m && n == idx.n; - } - - // toString - - @Override - public String toString() { - return "(" + m + ',' + n + ')'; - } - - // ========== static ========== - - - // 工厂方法 - - public static BiInt of(int m, int n) { - if (m == Integer.MIN_VALUE && n == Integer.MAX_VALUE) { - return MIN_TO_MAX; - } - if (m >= 0 && m < CACHE_RANGE_M && n >= 0 && n < CACHE_RANGE_M) { - return cache[m * CACHE_RANGE_M + n]; - } - return new BiInt(m, n); - } - - // 缓存区间 - - private static final BiInt MIN_TO_MAX = new BiInt(Integer.MIN_VALUE, Integer.MAX_VALUE); - private static final BiInt[] cache; // m from 0 to 31 , n from 0 to 31 , total 1023 . - private static final int CACHE_RANGE_M = 32; // 0 to 31 - private static final int CACHE_RANGE_N = 32; // 0 to 31 - - static { - cache = new BiInt[CACHE_RANGE_M * CACHE_RANGE_N]; - for (int i = 0; i < CACHE_RANGE_M; i++) { - for (int j = 0; j < CACHE_RANGE_N; j++) { - cache[i * CACHE_RANGE_M + j] = new BiInt(i, j); - } - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractArray2D.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractArray2D.java deleted file mode 100644 index 0f728cd6..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractArray2D.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import com.zmops.iot.async.util.BiInt; - -import java.util.Iterator; - -/** - * @author create by TcSnZh on 2021/5/14-下午9:51 - */ -public abstract class AbstractArray2D implements Array2D { - /** - * 用于代替null - */ - protected static final Object NULL = new Object() { - @Override - public String toString() { - return "null"; - } - - @Override - public int hashCode() { - return 0; - } - - @SuppressWarnings("EqualsDoesntCheckParameterClass") - @Override - public boolean equals(Object obj) { - //noinspection ConstantConditions - return obj == null || obj == NULL || obj.equals(null); - } - }; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(64).append(this.getClass().getSimpleName()).append('{'); - Iterator> it = iterator(); - if (it.hasNext()) { - while (true) { - Point point = it.next(); - sb.append('{').append(point.getIdx()).append(':').append(point.getElement()).append('}'); - if (!it.hasNext()) { - break; - } - sb.append(", "); - } - } - return sb.append('}').toString(); - } - - public static class PointImpl implements Point { - private final BiInt idx; - private final E element; - - public PointImpl(BiInt idx, E element) { - this.idx = idx; - this.element = element; - } - - @Override - public BiInt getIdx() { - return idx; - } - - @Override - public E getElement() { - return element; - } - - @Override - public String toString() { - return "{" + idx + ":" + element + "}"; - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractDirectedGraph.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractDirectedGraph.java deleted file mode 100644 index 48a5b7f0..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractDirectedGraph.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import java.util.AbstractSet; -import java.util.Iterator; -import java.util.Objects; -import java.util.Set; - -/** - * 抽象有向图 - * - * @author create by TcSnZh on 2021/5/13-上午11:37 - */ -public abstract class AbstractDirectedGraph implements DirectedGraph { - - @Override - public String toString() { - Set nv = nodesView(); - Set> rSet = getRelations(); - StringBuilder sb = new StringBuilder(nv.size() * 10 + rSet.size() * 20) - .append(this.getClass().getSimpleName()).append("{nodes=["); - Iterator nit = nodesView().iterator(); - if (nit.hasNext()) { - for (; ; ) { - sb.append(nit.next()); - if (!nit.hasNext()) { - break; - } - sb.append(", "); - } - } - sb.append("], relations=["); - Iterator> eit = rSet.iterator(); - if (eit.hasNext()) { - for (; ; ) { - sb.append(eit.next()); - if (!eit.hasNext()) { - break; - } - sb.append(", "); - } - } - return sb.append("]}").toString(); - } - - public abstract class AbstractNodesView extends AbstractSet { - @Override - public boolean add(N n) { - return AbstractDirectedGraph.this.addNode(n); - } - - @Override - public boolean remove(Object o) { - N o1; - //noinspection unchecked - if (!AbstractDirectedGraph.this.containsNode(o1 = (N) o)) { - return false; - } - AbstractDirectedGraph.this.removeNode(o1); - return true; - } - } - - public static abstract class AbstractEntry implements Graph.Entry { - @Override - public int hashCode() { - return this.getFrom().hashCode() ^ this.getTo().hashCode() ^ this.getRelation().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof Graph.Entry)) { - return false; - } - Graph.Entry obj1 = (Graph.Entry) obj; - return Objects.equals(this.getFrom(), obj1.getFrom()) - && Objects.equals(this.getTo(), obj1.getTo()) - && Objects.equals(this.getRelation(), obj1.getRelation()); - } - - @Override - public String toString() { - return "{from=" + getFrom() + ", relation=" + getRelation() + ", to=" + getTo() + "]"; - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractStoreArk.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractStoreArk.java deleted file mode 100644 index 24c4ac2a..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractStoreArk.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.zmops.iot.async.util.collection; - -/** - * @author create by TcSnZh on 2021/5/14-上午2:33 - */ -public abstract class AbstractStoreArk implements StoreArk { - - @Override - public boolean isEmpty() { - return size() <= 0; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(size() * 10).append(this.getClass().getSimpleName()).append("{"); - if (!isEmpty()) { - stream().forEach(entry -> sb.append(entry.getKey()).append(":").append(entry.getValue()).append(", ")); - sb.delete(sb.length() - 2, sb.length()); - } - return sb.append("}").toString(); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/Array2D.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/Array2D.java deleted file mode 100644 index 88434c79..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/Array2D.java +++ /dev/null @@ -1,169 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import com.zmops.iot.async.util.BiInt; - -import java.util.*; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -/** - * 二维数组 - * - * @author create by TcSnZh on 2021/5/14-下午9:50 - */ -@SuppressWarnings("unused") -public interface Array2D extends Iterable> { - /** - * 有多少行 - */ - int lineLength(); - - /** - * 有多少列 - */ - int columnLength(); - - /** - * 添加元素到指定位置 - * - * @param line 行 - * @param column 列 - * @param element 元素 - * @return 如果之前添加过元素,将返回替换掉的之前的元素 - * @throws IndexOutOfBoundsException 行列超出范围 - */ - E add(int line, int column, E element); - - /** - * 如果不存在的话则添加元素 - *

- * {@link #add(int, int, Object)} - * - * @return 不存在且成功添加,返回true。 - */ - default boolean addIfAbsent(int line, int column, E element) { - if (get(line, column) != null) { - return false; - } - add(line, column, element); - return true; - } - - /** - * 删除元素 - * - * @param line 行 - * @param column 列 - * @return 返回移出的元素 - * @throws IndexOutOfBoundsException 行列超出返回 - * @throws IllegalArgumentException 如果原本不存在元素 - */ - E remove(int line, int column); - - /** - * 存在则移除,不存在则返回null - * - * @param line 行 - * @param column 列 - * @return 如果不存在,返回null。存在则返回被移出的元素。 - * @throws IndexOutOfBoundsException 行列超出范围 - */ - default E removeIfAbsent(int line, int column) { - if (get(line, column) == null) { - return null; - } - return remove(line, column); - } - - /** - * 获取元素 - * - * @param line 行 - * @param column 列 - * @return 如果存在,返回该元素。不存在则返回null。 - * @throws IndexOutOfBoundsException 行列超出范围 - */ - E get(int line, int column); - - /** - * 是否包含元素 - * - * @param element 元素 - * @return 有这个元素就返回true。 - */ - boolean containsElement(E element); - - /** - * 获取整行的元素 - * - * @param line 行号 - * @return 返回key为列号,value为元素的Map - * @throws IndexOutOfBoundsException 行号超出范围 - */ - Map fullLine(int line); - - /** - * 获取整列的元素 - * - * @param column 列号 - * @return 返回key为行号,value为元素的Map - * @throws IndexOutOfBoundsException 列号超出范围 - */ - Map fullColumn(int column); - - /** - * 迭代器 - * - * @param foreachOrder 遍历顺序 - * @return 如果本容器不允许null值存在,只需返回存在的元素的键即可。如果允许null值存在,仅需返回包括人工放入的null值的键即可。 - */ - Iterator> iterator(Comparator foreachOrder); - - @Override - default Iterator> iterator() { - //noinspection unchecked - return (Iterator) iterator(BiInt.cmp_m_asc_n_asc); - } - - /** - * 流 - */ - default Stream> stream() { - return StreamSupport.stream(spliterator(), false); - } - - default Stream> parallelStream() { - return StreamSupport.stream(spliterator(), true); - } - - default Spliterator> spliterator(Comparator foreachOrder) { - return Spliterators.spliteratorUnknownSize(iterator(foreachOrder), 0); - } - - default Stream> stream(Comparator foreachOrder) { - return StreamSupport.stream(spliterator(foreachOrder), false); - } - - default Stream> parallelStream(Comparator foreachOrder) { - return StreamSupport.stream(spliterator(foreachOrder), true); - } - - /** - * 端点 - * - * @param 元素泛型 - */ - interface Point { - BiInt getIdx(); - - default int getLine() { - return getIdx().getM(); - } - - default int getColumn() { - return getIdx().getN(); - } - - E getElement(); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CachedStoreArk.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CachedStoreArk.java deleted file mode 100644 index 90fbc18f..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CachedStoreArk.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.function.Supplier; - -/** - * 一个缓存元素位置的储存柜。 - * - * @author create by TcSnZh on 2021/5/14-上午2:37 - */ -public class CachedStoreArk extends AbstractStoreArk { - private final StoreArk inner; - - private final Map cacheMap = new HashMap<>(); - - public CachedStoreArk() { - this(CommonStoreArk::new); - } - - private CachedStoreArk(Supplier> sup) { - this.inner = sup.get(); - } - - @Override - public int store(E element) { - int id = inner.store(element); - cacheMap.put(element, id); - return id; - } - - @Override - public E peek(int id) { - return inner.peek(id); - } - - @Override - public E takeOut(int id) { - E e = inner.takeOut(id); - cacheMap.remove(e); - return e; - } - - @Override - public int size() { - return inner.size(); - } - - @Override - public Iterator> iterator() { - return inner.iterator(); - } - - @Override - public int findId(E element) { - Integer idNullable = cacheMap.get(element); - return idNullable == null ? -1 : idNullable; - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonDirectedGraph.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonDirectedGraph.java deleted file mode 100644 index e7870275..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonDirectedGraph.java +++ /dev/null @@ -1,145 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; - -/** - * 线程不安全的有向图。 - *

- * 不允许放入null。 - * - * @author create by TcSnZh on 2021/5/14-上午2:22 - */ -public class CommonDirectedGraph extends AbstractDirectedGraph { - - // ========== properties ========== - - private final StoreArk nodes = new CachedStoreArk<>(); - private final Array2D arr = new SparseArray2D<>(); - - // ========== methods ========== - - @Override - public boolean addNode(N node) { - if (containsNode(Objects.requireNonNull(node))) { - return false; - } - nodes.store(node); - return true; - } - - @Override - public boolean containsNode(N node) { - return node != null && findNodeId(node, false) >= 0; - } - - @Override - public Set> removeNode(N node) { - int id = findNodeId(Objects.requireNonNull(node), true); - LinkedHashSet> res = new LinkedHashSet<>(); - // 查找node为from的键 - arr.fullLine(id).forEach((toNodeId, relation) -> { - res.add(new OuterEntry<>(node, nodes.peek(toNodeId), relation)); - arr.remove(id, toNodeId); - }); - // 查找node为to的键 - arr.fullColumn(id).forEach((fromNodeId, relation) -> { - // 在上一次遍历中,fromNodeId为id, - if (fromNodeId == id) { - return; - } - res.add(new OuterEntry<>(nodes.peek(fromNodeId), node, relation)); - arr.remove(fromNodeId, id); - }); - nodes.takeOut(id); - return res; - } - - @Override - public R putRelation(N fromNode, R relation, N toNode) { - return arr.add( - findNodeId(Objects.requireNonNull(fromNode), true), - findNodeId(Objects.requireNonNull(toNode), true), - Objects.requireNonNull(relation) - ); - } - - @Override - public Set> getRelationFrom(N from) { - int id = findNodeId(Objects.requireNonNull(from), true); - LinkedHashSet> res = new LinkedHashSet<>(); - // 查找node为from的键 - arr.fullLine(id).forEach((toNodeId, relation) -> res.add(new OuterEntry<>(from, nodes.peek(toNodeId), relation))); - return res; - } - - @Override - public Set> getRelationTo(N to) { - int id = findNodeId(Objects.requireNonNull(to), true); - LinkedHashSet> res = new LinkedHashSet<>(); - // 查找node为to的键 - arr.fullColumn(id).forEach((fromNodeId, relation) -> - res.add(new OuterEntry<>(nodes.peek(fromNodeId), to, relation))); - return res; - } - - @Override - public Set nodesView() { - return new AbstractNodesView() { - @Override - public Iterator iterator() { - return nodes.stream().map(Map.Entry::getValue).iterator(); - } - - @Override - public int size() { - return nodes.size(); - } - }; - } - - @Override - public Set> getRelations() { - return arr.stream().map((Function, Graph.Entry>) rPoint -> new OuterEntry<>( - nodes.peek(rPoint.getLine()), - nodes.peek(rPoint.getColumn()), - rPoint.getElement() - )).collect(Collectors.toSet()); - } - - private int findNodeId(N node, boolean mustExistElseThrowEx) { - int id = nodes.findId(Objects.requireNonNull(node)); - if (mustExistElseThrowEx && id < 0) { - throw new IllegalArgumentException("No node exists : " + node); - } - return id; - } - - private static class OuterEntry extends AbstractDirectedGraph.AbstractEntry { - private final N from; - private final N to; - private final R relation; - - public OuterEntry(N from, N to, R relation) { - this.from = from; - this.to = to; - this.relation = relation; - } - - @Override - public N getFrom() { - return from; - } - - @Override - public N getTo() { - return to; - } - - @Override - public R getRelation() { - return relation; - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonStoreArk.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonStoreArk.java deleted file mode 100644 index d7e9e2f5..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonStoreArk.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import java.util.*; - -/** - * 自动扩容的id储物柜,线程不安全。 - * - * @author create by TcSnZh on 2021/5/13-下午1:24 - */ -public class CommonStoreArk extends AbstractStoreArk { - private Object[] elements; - - /** - * 已经分配的下标数 - */ - private int allocSize = 0; - - /** - * 保存着最小空元素的队列 - */ - private final Queue emptyPoints = new PriorityQueue<>(Integer::compareTo); - - public CommonStoreArk(int initialCapacity) { - elements = new Object[initialCapacity]; - } - - public CommonStoreArk() { - this(10); - } - - @Override - public int store(E element) { - int id; - elements[id = pollId()] = element; - return id; - } - - @Override - public E peek(int id) { - if (id < 0) { - throw new IllegalArgumentException("id " + id + " can't be negative"); - } - if (id >= elements.length) { - return null; - } - //noinspection unchecked - return (E) elements[id]; - } - - @Override - public E takeOut(int id) { - if (id < 0) { - throw new IllegalArgumentException("id " + id + " can't be negative"); - } - if (id >= elements.length) { - return null; - } - //noinspection unchecked - E out = (E) elements[id]; - elements[id] = null; - if (id == allocSize - 1) { - allocSize--; - } else { - emptyPoints.add(id); - } - return out; - } - - @Override - public int size() { - return allocSize - emptyPoints.size(); - } - - @Override - public Iterator> iterator() { - return new Iterator>() { - private final Map.Entry[] items; - - private int idx = 0; - - { - //noinspection unchecked - items = new Map.Entry[size()]; - int itemsIdx = 0; - Iterator emptyPointItr = emptyPoints.iterator(); - for (int i = 0; i < allocSize; i++) { - Object element = elements[i]; - if (element == null) { - continue; - } - final int _i = i; - //noinspection unchecked - items[itemsIdx++] = new Map.Entry() { - private final int k = _i; - private E v = (E) element; - - @Override - public Integer getKey() { - return k; - } - - @Override - public E getValue() { - return v; - } - - @Override - public E setValue(E value) { - E _v = this.v; - this.v = value; - return _v; - } - - @Override - public String toString() { - return "{" + k + ':' + v + '}'; - } - }; - } - } - - - @Override - public boolean hasNext() { - return idx < items.length; - } - - @Override - public Map.Entry next() { - return items[idx++]; - } - }; - } - - @Override - public int findId(E element) { - int i = 0; - for (Object o : elements) { - if (Objects.equals(o, element)) { - return i; - } - i++; - } - return -1; - } - - private int pollId() { - if (!emptyPoints.isEmpty()) { - return emptyPoints.poll(); - } - int id = allocSize++; - int length = elements.length; - if (id >= length) { - // 扩容 - elements = Arrays.copyOf(elements, Math.max(length + 1, length + (length >> 1))); - } - return id; - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/DirectedGraph.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/DirectedGraph.java deleted file mode 100644 index ddd2dea9..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/DirectedGraph.java +++ /dev/null @@ -1,185 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import java.util.AbstractSet; -import java.util.Collections; -import java.util.Iterator; -import java.util.Set; - -/** - * @author create by TcSnZh on 2021/5/16-下午11:27 - */ -public interface DirectedGraph extends Graph { - @Override - default boolean isDirected() { - return true; - } - - static DirectedGraph readOnlyDigraph(DirectedGraph source) { - return new ReadOnlyDirectedGraph<>(source); - } - - static DirectedGraph synchronizedDigraph(DirectedGraph source) { - return synchronizedDigraph(source, new Object()); - } - - static DirectedGraph synchronizedDigraph(DirectedGraph source, Object mutex) { - return new SyncDirectedGraph<>(source, mutex); - } - - class ReadOnlyDirectedGraph extends AbstractDirectedGraph { - private final DirectedGraph source; - - public ReadOnlyDirectedGraph(DirectedGraph source) { - this.source = source; - } - - private static UnsupportedOperationException readOnlyGraph() { - return new UnsupportedOperationException("readOnly graph"); - } - - @Override - public boolean addNode(N node) { - throw readOnlyGraph(); - } - - @Override - public boolean containsNode(N node) { - return source.containsNode(node); - } - - @Override - public Set> removeNode(N node) { - throw readOnlyGraph(); - } - - @Override - public R putRelation(N fromNode, R relation, N toNode) { - throw readOnlyGraph(); - } - - @Override - public Set> getRelationFrom(N from) { - return source.getRelationFrom(from); - } - - @Override - public Set> getRelationTo(N to) { - return source.getRelationTo(to); - } - - @Override - public Set nodesView() { - return new AbstractSet() { - private final Set nodesViewSource = source.nodesView(); - - @Override - public Iterator iterator() { - return new Iterator() { - private final Iterator iteratorSource = nodesViewSource.iterator(); - - @Override - public boolean hasNext() { - return iteratorSource.hasNext(); - } - - @Override - public N next() { - return iteratorSource.next(); - } - - @Override - public void remove() { - throw readOnlyGraph(); - } - }; - } - - @Override - public int size() { - return nodesViewSource.size(); - } - - @Override - public boolean add(N n) { - throw readOnlyGraph(); - } - - @Override - public boolean remove(Object o) { - throw readOnlyGraph(); - } - }; - } - - @Override - public Set> getRelations() { - return source.getRelations(); - } - } - - class SyncDirectedGraph extends AbstractDirectedGraph { - private final DirectedGraph source; - private final Object mutex; - - public SyncDirectedGraph(DirectedGraph source, Object mutex) { - this.source = source; - this.mutex = mutex; - } - - @Override - public boolean addNode(N node) { - synchronized (mutex) { - return source.addNode(node); - } - } - - @Override - public boolean containsNode(N node) { - synchronized (mutex) { - return source.containsNode(node); - } - } - - @Override - public Set> removeNode(N node) { - synchronized (mutex) { - return source.removeNode(node); - } - } - - @Override - public R putRelation(N fromNode, R relation, N toNode) { - synchronized (mutex) { - return source.putRelation(fromNode, relation, toNode); - } - } - - @Override - public Set> getRelationFrom(N from) { - synchronized (mutex) { - return source.getRelationFrom(from); - } - } - - @Override - public Set> getRelationTo(N to) { - synchronized (mutex) { - return source.getRelationTo(to); - } - } - - @Override - public Set nodesView() { - synchronized (mutex) { - return Collections.synchronizedSet(source.nodesView()); - } - } - - @Override - public Set> getRelations() { - synchronized (mutex) { - return source.getRelations(); - } - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/Graph.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/Graph.java deleted file mode 100644 index 4bcb98c7..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/Graph.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import java.util.Set; - -/** - * 图数据结构 - * - * @author create by TcSnZh on 2021/5/13-上午11:37 - */ -@SuppressWarnings("unused") -public interface Graph { - /** - * 添加节点。 - * 如果节点已经存在,则不会添加。 - * - * @param node 添加进图的节点 - * @return 添加成功返回true,如果节点已经存在返回false。 - */ - boolean addNode(N node); - - /** - * 添加一堆Node,任一成功返回true - */ - default boolean addNode(N... nodes) { - boolean success = false; - for (N node : nodes) { - if (addNode(node)) { - success = true; - } - } - return success; - } - - /** - * 是否存在节点 - * - * @param node 节点。 - * @return 存在返回true,否则返回false。 - */ - boolean containsNode(N node); - - /** - * 移除节点。 - * 返回与该节点有关系的,被一并移出的键。 - * - * @param node 节点 - * @return 返回值不会为null。 - * @throws IllegalArgumentException 如果两个节点任一不存在本图中,抛出异常。 - */ - Set> removeNode(N node); - - /** - * 添加关系 - * 在无向图中fromNode与toNode参数的位置调换没有影响。 - * - * @param fromNode 从这个节点开始 - * @param relation 关系 - * @param toNode 以那个节点为目标 - * @return 如果之前存在关系,则会替换之前的关系,返回出被替换的之前存在的关系。如果之前没有关系,返回null。 - * @throws IllegalArgumentException 如果两个节点任一不存在本图中,抛出该异常。 - */ - R putRelation(N fromNode, R relation, N toNode); - - /** - * 获取“从这个节点开始”的所有关系 - * - * @param from 关系开始的节点 - * @return 返回 {@link Entry}键。 - */ - Set> getRelationFrom(N from); - - /** - * 获取“以这个节点为目标”的所有关系 - * - * @param to 被关系的节点 - * @return 返回 {@link Entry}键。 - */ - Set> getRelationTo(N to); - - /** - * 返回全部节点视图 - * - * @return 视图 - */ - Set nodesView(); - - /** - * 返回全部关系,返回的是新Set - * - * @return 与本类无关的Set - */ - Set> getRelations(); - - /** - * 是否有向 - */ - boolean isDirected(); - - interface Entry { - N getFrom(); - - N getTo(); - - R getRelation(); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/SparseArray2D.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/SparseArray2D.java deleted file mode 100644 index 3befc13e..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/SparseArray2D.java +++ /dev/null @@ -1,229 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import com.zmops.iot.async.util.BiInt; - -import java.util.*; -import java.util.stream.Collectors; - -/** - * 稀疏二维数组。 - *

- * 可以设置是否允许存入null。 - * - * @author create by TcSnZh on 2021/5/14-下午9:45 - */ -public class SparseArray2D extends AbstractArray2D { - - // ========== properties ========== - - /** - * 限制长宽,默认为Integer.MAX_VALUE。稀疏数组不在乎这些。 - */ - private final int maxLineLength; - private final int maxColumnLength; - private final boolean allowNull; - - private final Map items = new HashMap<>(); - - // ========== index cache properties ========== - - /** - * 缓存行列索引 - */ - private final NavigableMap> indexOfLine2columns = new TreeMap<>(Integer::compareTo); - private final NavigableMap> indexOfColumn2lines = new TreeMap<>(Integer::compareTo); - - // ========== constructor ========== - - public SparseArray2D() { - this(Integer.MAX_VALUE, Integer.MAX_VALUE); - } - - public SparseArray2D(boolean allowNull) { - this(Integer.MAX_VALUE, Integer.MAX_VALUE, allowNull); - } - - public SparseArray2D(int maxLineCapacity, int maxColumnCapacity) { - this(maxLineCapacity, maxColumnCapacity, false); - } - - public SparseArray2D(int maxLineCapacity, int maxColumnCapacity, boolean allowNull) { - this.maxLineLength = maxLineCapacity; - this.maxColumnLength = maxColumnCapacity; - this.allowNull = allowNull; - } - - // ========== public methods ========== - @Override - public int lineLength() { - return maxLineLength; - } - - @Override - public int columnLength() { - return maxColumnLength; - } - - @Override - public E add(int line, int column, E element) { - if (!allowNull && element == null) { - throw new NullPointerException("null is not allowed"); - } - Object put = items.put(BiInt.of(checkLine(line), checkColumn(column)), element == null ? NULL : element); - addIndex(line, column); - //noinspection unchecked - return NULL.equals(put) ? null : (E) put; - } - - @Override - public E remove(int line, int column) { - BiInt idx = BiInt.of(checkLine(line), checkColumn(column)); - Object get = items.get(idx); - if (get == null) { - throw new IllegalArgumentException("There is no element in line " + line + " column " + column); - } - items.remove(idx); - removeIndex(line, column); - //noinspection unchecked - return NULL.equals(get) ? null : (E) get; - } - - /** - * 该方法如果返回null,则分不清 之前存入了null 还是 没有存入过 - *

- * {@inheritDoc} - */ - @Override - public E get(int line, int column) { - Object get = items.get(BiInt.of(checkLine(line), checkColumn(column))); - //noinspection unchecked - return NULL.equals(get) ? null : (E) get; - } - - @Override - public boolean containsElement(E element) { - if (NULL.equals(element)) { - if (!allowNull) { - return false; - } - return items.values().stream().anyMatch(v -> NULL.equals(element)); - } - return items.values().stream().anyMatch(element::equals); - } - - @Override - public Map fullLine(int line) { - return Optional.ofNullable(indexOfLine2columns.get(line)) - .map(set -> set.stream() - .collect(Collectors.toMap(column -> column, column -> { - //noinspection unchecked - return (E) items.get(BiInt.of(line, column)); - }))) - .orElse(Collections.emptyMap()); - } - - @Override - public Map fullColumn(int column) { - return Optional.ofNullable(indexOfColumn2lines.get(column)) - .map(set -> set.stream() - .collect(Collectors.toMap(line -> line, line -> { - //noinspection unchecked - return (E) items.get(BiInt.of(line, column)); - }))) - .orElse(Collections.emptyMap()); - } - - @Override - public Iterator> iterator(Comparator foreachOrder) { - return new Iterator>() { - private final Iterator> it; - private Point last = null; - private boolean removed = false; - - { - it = items.entrySet().stream() - .sorted((o1, o2) -> foreachOrder.compare(o1.getKey(), o2.getKey())) - .iterator(); - } - - @Override - public boolean hasNext() { - return it.hasNext(); - } - - @Override - public Point next() { - Map.Entry next = it.next(); - removed = false; - Object v = next.getValue(); - //noinspection unchecked - return last = new PointImpl<>(next.getKey(), NULL.equals(v) ? null : (E) v); - } - - @Override - public void remove() { - if (last == null || removed) { - throw new IllegalStateException(last == null - ? "Iterator has not yet been called .next() ." - : "Iterator item already removed : " + last); - } - BiInt idx = last.getIdx(); - SparseArray2D.this.remove(idx.getM(), idx.getN()); - } - }; - } - - // ========== private methods ========== - - private int checkLine(int line) { - int len = lineLength(); - if (line < 0 || line >= len) { - throw new IndexOutOfBoundsException("Line " + line + " out of bound [0," + (len - 1) + "]"); - } - return line; - } - - private int checkColumn(int column) { - int len = columnLength(); - if (column < 0 || column >= len) { - throw new IndexOutOfBoundsException("Column " + column + " out of bound [0," + (len - 1) + "]"); - } - return column; - } - - private void addIndex(int line, int column) { - indexOfLine2columns.computeIfAbsent(line, line1 -> new TreeSet<>(Integer::compareTo)).add(column); - indexOfColumn2lines.computeIfAbsent(column, column1 -> new TreeSet<>(Integer::compareTo)).add(line); - - } - - private void removeIndex(int line, int column) { - // remove line index - { - NavigableSet columns = indexOfLine2columns.get(line); - if (columns == null || !columns.contains(column)) { - throw new ConcurrentModificationException( - "线程不安全导致索引异常 : lines " + columns + " is null or not contain line " + line); - - } - if (columns.size() == 1) { - indexOfLine2columns.remove(line); - } else { - columns.remove(column); - } - } - // remove column index - { - NavigableSet lines = indexOfColumn2lines.get(column); - if (lines == null || !lines.contains(line)) { - throw new ConcurrentModificationException( - "线程不安全导致索引异常 : lines " + lines + " is null or not contain column " + column); - } - if (lines.size() == 1) { - indexOfColumn2lines.remove(column); - } else { - lines.remove(column); - } - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/StoreArk.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/StoreArk.java deleted file mode 100644 index 423ac083..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/StoreArk.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import java.util.Map; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -/** - * id存储柜。 - * 每个元素的id是固定的(除非取出后重新加入),且id是大于等于0,且分配到的id必须是未分配的id中最小的。 - *

- * 类似于我们去游泳馆,里面的存放个人物品的柜子。 - * 放进去元素后,会分配一个id。然后凭借该id取出元素。 - * 不过不同于这些现实中的柜子的是,这个存储柜必定会提供最小的id,并且必定>0。 - *

- * - * @author create by TcSnZh on 2021/5/14-上午2:29 - */ -public interface StoreArk extends Iterable> { - /** - * 存入元素 - * - * @param element 元素。 - * @return 返回最小的id。从0开始。 - */ - int store(E element); - - /** - * 查看元素 - * - * @param id id; - * @return 返回存在的元素。如果本id未被占用 或 原先存入null,返回null。 - * @throws IllegalArgumentException id为负数时抛出该异常 - */ - E peek(int id); - - /** - * 取出元素 - * - * @param id id - * @return 返回被取出的元素。如果本id未被占用 或 原先存入null,返回null。 - * @throws IllegalArgumentException id为负数时抛出该异常 - */ - E takeOut(int id); - - /** - * 元素个数 - */ - int size(); - - /** - * 是否为空 - */ - boolean isEmpty(); - - /** - * 查找元素的id - * - * @param element 元素 - * @return 如果存在,返回id。不存在返回-1 - */ - int findId(E element); - - /** - * 返回流 - */ - default Stream> stream() { - return StreamSupport.stream(spliterator(), false); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/AbstractWheelTimer.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/AbstractWheelTimer.java deleted file mode 100644 index e3197b83..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/AbstractWheelTimer.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.zmops.iot.async.util.timer; - -/** - * @author create by TcSnZh on 2021/5/12-下午6:36 - */ -public abstract class AbstractWheelTimer implements Timer, AutoCloseable { - public static final int WORKER_STATE_INIT = 0; - public static final int WORKER_STATE_STARTED = 1; - public static final int WORKER_STATE_SHUTDOWN = 2; - - public abstract void start(); - - @SuppressWarnings("RedundantThrows") - @Override - public void close() throws Exception { - stop(); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/HashedWheelTimer.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/HashedWheelTimer.java deleted file mode 100644 index 2678e49b..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/HashedWheelTimer.java +++ /dev/null @@ -1,665 +0,0 @@ -package com.zmops.iot.async.util.timer; - -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; -import java.util.concurrent.atomic.AtomicLong; - -/** - * 从netty里抄来的,删去了一些功能。 - *

- * - * 如果违反开源协议,请联系作者: zh.jobs@foxmail.com - * If violate the open source agreement, please contact the author : zh0u.he@qq.com - * - * - * @author create by TcSnZh on 2021/5/12-下午7:16 - */ -public class HashedWheelTimer extends AbstractWheelTimer { - - private static final long MILLISECOND_NANOS = TimeUnit.MILLISECONDS.toNanos(1); - - private final Worker worker = new Worker(); - private final Thread workerThread; - @SuppressWarnings({"unused", "FieldMayBeFinal"}) - private final AtomicInteger workerState = new AtomicInteger(WORKER_STATE_INIT); // 0 - init, 1 - started, 2 - shut down - - private final long tickDuration; - private final HashedWheelBucket[] wheel; - private final int mask; - private final CountDownLatch startTimeInitialized = new CountDownLatch(1); - private final Queue timeouts = new ConcurrentLinkedDeque<>(); - private final Queue cancelledTimeouts = new ConcurrentLinkedDeque<>(); - private final AtomicLong pendingTimeouts = new AtomicLong(0); - private final long maxPendingTimeouts; - - private volatile long startTime; - - /** - * Creates a new timer with the default thread factory - * ({@link Executors#defaultThreadFactory()}), default tick duration, and - * default number of ticks per wheel. - */ - @SuppressWarnings("unused") - public HashedWheelTimer() { - this(Executors.defaultThreadFactory()); - } - - /** - * Creates a new timer with the default thread factory - * ({@link Executors#defaultThreadFactory()}) and default number of ticks - * per wheel. - * - * @param tickDuration the duration between tick - * @param unit the time unit of the {@code tickDuration} - * @throws NullPointerException if {@code unit} is {@code null} - * @throws IllegalArgumentException if {@code tickDuration} is <= 0 - */ - @SuppressWarnings("unused") - public HashedWheelTimer(long tickDuration, TimeUnit unit) { - this(Executors.defaultThreadFactory(), tickDuration, unit); - } - - /** - * Creates a new timer with the default thread factory - * ({@link Executors#defaultThreadFactory()}). - * - * @param tickDuration the duration between tick - * @param unit the time unit of the {@code tickDuration} - * @param ticksPerWheel the size of the wheel - * @throws NullPointerException if {@code unit} is {@code null} - * @throws IllegalArgumentException if either of {@code tickDuration} and {@code ticksPerWheel} is <= 0 - */ - @SuppressWarnings("unused") - public HashedWheelTimer(long tickDuration, TimeUnit unit, int ticksPerWheel) { - this(Executors.defaultThreadFactory(), tickDuration, unit, ticksPerWheel); - } - - /** - * Creates a new timer with the default tick duration and default number of - * ticks per wheel. - * - * @param threadFactory a {@link ThreadFactory} that creates a - * background {@link Thread} which is dedicated to - * {@link TimerTask} execution. - * @throws NullPointerException if {@code threadFactory} is {@code null} - */ - public HashedWheelTimer(ThreadFactory threadFactory) { - this(threadFactory, 100, TimeUnit.MILLISECONDS); - } - - /** - * Creates a new timer with the default number of ticks per wheel. - * - * @param threadFactory a {@link ThreadFactory} that creates a - * background {@link Thread} which is dedicated to - * {@link TimerTask} execution. - * @param tickDuration the duration between tick - * @param unit the time unit of the {@code tickDuration} - * @throws NullPointerException if either of {@code threadFactory} and {@code unit} is {@code null} - * @throws IllegalArgumentException if {@code tickDuration} is <= 0 - */ - public HashedWheelTimer( - ThreadFactory threadFactory, long tickDuration, TimeUnit unit) { - this(threadFactory, tickDuration, unit, 512); - } - - /** - * Creates a new timer. - * - * @param threadFactory a {@link ThreadFactory} that creates a - * background {@link Thread} which is dedicated to - * {@link TimerTask} execution. - * @param tickDuration the duration between tick - * @param unit the time unit of the {@code tickDuration} - * @param ticksPerWheel the size of the wheel - * @throws NullPointerException if either of {@code threadFactory} and {@code unit} is {@code null} - * @throws IllegalArgumentException if either of {@code tickDuration} and {@code ticksPerWheel} is <= 0 - */ - public HashedWheelTimer( - ThreadFactory threadFactory, - long tickDuration, TimeUnit unit, int ticksPerWheel) { - this(threadFactory, tickDuration, unit, ticksPerWheel, -1); - } - - /** - * Creates a new timer. - * - * @param threadFactory a {@link ThreadFactory} that creates a - * background {@link Thread} which is dedicated to - * {@link TimerTask} execution. - * @param tickDuration the duration between tick - * @param unit the time unit of the {@code tickDuration} - * @param ticksPerWheel the size of the wheel - * @param maxPendingTimeouts The maximum number of pending timeouts after which call to - * {@code newTimeout} will result in - * {@link RejectedExecutionException} - * being thrown. No maximum pending timeouts limit is assumed if - * this value is 0 or negative. - * @throws NullPointerException if either of {@code threadFactory} and {@code unit} is {@code null} - * @throws IllegalArgumentException if either of {@code tickDuration} and {@code ticksPerWheel} is <= 0 - */ - public HashedWheelTimer(ThreadFactory threadFactory, - long tickDuration, - TimeUnit unit, - int ticksPerWheel, - long maxPendingTimeouts) { - - Objects.requireNonNull(threadFactory, "threadFactory must not null !"); - Objects.requireNonNull(threadFactory, "unit must not null !"); - if (tickDuration <= 0) { - throw new IllegalArgumentException("tickDuration should > 0 !"); - } - if (ticksPerWheel <= 0) { - throw new IllegalArgumentException("ticksPerWheel should > 0 !"); - } - - wheel = createWheel(ticksPerWheel); - mask = wheel.length - 1; - - long duration = unit.toNanos(tickDuration); - - // 检查一个周期是否比Long.MAX_VALUE还长 - if (duration >= Long.MAX_VALUE / wheel.length) { - throw new IllegalArgumentException(String.format( - "tickDuration: %d (expected: 0 < tickDuration in nanos < %d", - tickDuration, Long.MAX_VALUE / wheel.length)); - } - - this.tickDuration = Math.max(duration, MILLISECOND_NANOS); - workerThread = threadFactory.newThread(worker); - this.maxPendingTimeouts = maxPendingTimeouts; - } - - private static HashedWheelBucket[] createWheel(int ticksPerWheel) { - if (ticksPerWheel <= 0) { - throw new IllegalArgumentException( - "ticksPerWheel must be greater than 0: " + ticksPerWheel); - } - if (ticksPerWheel > 1073741824) { - throw new IllegalArgumentException( - "ticksPerWheel may not be greater than 2^30: " + ticksPerWheel); - } - - ticksPerWheel = normalizeTicksPerWheel(ticksPerWheel); - HashedWheelBucket[] wheel = new HashedWheelBucket[ticksPerWheel]; - for (int i = 0; i < wheel.length; i++) { - wheel[i] = new HashedWheelBucket(); - } - return wheel; - } - - private static int normalizeTicksPerWheel(int ticksPerWheel) { - int normalizedTicksPerWheel = 1; - while (normalizedTicksPerWheel < ticksPerWheel) { - normalizedTicksPerWheel <<= 1; - } - return normalizedTicksPerWheel; - } - - /** - * 显式启动后台线程。即使您没有调用此方法,后台线程也将根据需要自动启动。 - * - * @throws IllegalStateException 如果此计时器已停止{@link #stop()} - */ - @Override - public void start() { - switch (workerState.get()) { - case WORKER_STATE_INIT: - if (workerState.compareAndSet(WORKER_STATE_INIT, WORKER_STATE_STARTED)) { - workerThread.start(); - } - break; - case WORKER_STATE_STARTED: - break; - case WORKER_STATE_SHUTDOWN: - throw new IllegalStateException("cannot be started once stopped"); - default: - throw new Error("Invalid WorkerState"); - } - - // Wait until the startTime is initialized by the worker. - while (startTime == 0) { - try { - startTimeInitialized.await(); - } catch (InterruptedException ignore) { - // Ignore - it will be ready very soon. - } - } - } - - @Override - public Set stop() { - if (Thread.currentThread() == workerThread) { - throw new IllegalStateException( - HashedWheelTimer.class.getSimpleName() + - ".stop() cannot be called from " + - TimerTask.class.getSimpleName()); - } - - if (!workerState.compareAndSet(WORKER_STATE_STARTED, WORKER_STATE_SHUTDOWN)) { - // state is init or shutdown . - return Collections.emptySet(); - } - - - boolean interrupted = false; - while (workerThread.isAlive()) { - workerThread.interrupt(); - try { - workerThread.join(100); - } catch (InterruptedException ignored) { - interrupted = true; - } - } - - if (interrupted) { - Thread.currentThread().interrupt(); - } - - return worker.unprocessedTimeouts(); - } - - @Override - public Timeout newTimeout(TimerTask task, long delay, TimeUnit unit) { - Objects.requireNonNull(task, "task require not null !"); - Objects.requireNonNull(unit, "unit require not null !"); - - long pendingTimeoutsCount = pendingTimeouts.incrementAndGet(); - - if (maxPendingTimeouts > 0 && pendingTimeoutsCount > maxPendingTimeouts) { - pendingTimeouts.decrementAndGet(); - throw new RejectedExecutionException("Number of pending timeouts (" - + pendingTimeoutsCount + ") is greater than or equal to maximum allowed pending " - + "timeouts (" + maxPendingTimeouts + ")"); - } - - start(); - - // Add the timeout to the timeout queue which will be processed on the next tick. - // During processing all the queued HashedWheelTimeouts will be added to the correct HashedWheelBucket. - long deadline = System.nanoTime() + unit.toNanos(delay) - startTime; - - // Guard against overflow. - if (delay > 0 && deadline < 0) { - deadline = Long.MAX_VALUE; - } - HashedWheelTimeout timeout = new HashedWheelTimeout(this, task, deadline); - timeouts.add(timeout); - return timeout; - } - - /** - * Returns the number of pending timeouts of this {@link Timer}. - */ - public long pendingTimeouts() { - return pendingTimeouts.get(); - } - - private final class Worker implements Runnable { - private final Set unprocessedTimeouts = new HashSet(); - - private long tick; - - @Override - public void run() { - // Initialize the startTime. - startTime = System.nanoTime(); - if (startTime == 0) { - // We use 0 as an indicator for the uninitialized value here, so make sure it's not 0 when initialized. - startTime = 1; - } - - // Notify the other threads waiting for the initialization at start(). - startTimeInitialized.countDown(); - - do { - final long deadline = waitForNextTick(); - if (deadline > 0) { - int idx = (int) (tick & mask); - processCancelledTasks(); - HashedWheelBucket bucket = - wheel[idx]; - transferTimeoutsToBuckets(); - bucket.expireTimeouts(deadline); - tick++; - } - } while (workerState.get() == WORKER_STATE_STARTED); - - // Fill the unprocessedTimeouts so we can return them from stop() method. - for (HashedWheelBucket bucket : wheel) { - bucket.clearTimeouts(unprocessedTimeouts); - } - for (; ; ) { - HashedWheelTimeout timeout = timeouts.poll(); - if (timeout == null) { - break; - } - if (!timeout.isCancelled()) { - unprocessedTimeouts.add(timeout); - } - } - processCancelledTasks(); - } - - private void transferTimeoutsToBuckets() { - // transfer only max. 100000 timeouts per tick to prevent a thread to stale the workerThread when it just - // adds new timeouts in a loop. - for (int i = 0; i < 100000; i++) { - HashedWheelTimeout timeout = timeouts.poll(); - if (timeout == null) { - // all processed - break; - } - if (timeout.state() == HashedWheelTimeout.ST_CANCELLED) { - // Was cancelled in the meantime. - continue; - } - - long calculated = timeout.deadline / tickDuration; - timeout.remainingRounds = (calculated - tick) / wheel.length; - - final long ticks = Math.max(calculated, tick); // Ensure we don't schedule for past. - int stopIndex = (int) (ticks & mask); - - HashedWheelBucket bucket = wheel[stopIndex]; - bucket.addTimeout(timeout); - } - } - - private void processCancelledTasks() { - for (; ; ) { - HashedWheelTimeout timeout = cancelledTimeouts.poll(); - if (timeout == null) { - // all processed - break; - } - try { - timeout.remove(); - } catch (Throwable e) { - e.printStackTrace(); - } - } - } - - /** - * calculate goal nanoTime from startTime and current tick number, - * then wait until that goal has been reached. - * - * @return Long.MIN_VALUE if received a shutdown request, - * current time otherwise (with Long.MIN_VALUE changed by +1) - */ - private long waitForNextTick() { - long deadline = tickDuration * (tick + 1); - - for (; ; ) { - final long currentTime = System.nanoTime() - startTime; - long sleepTimeMs = (deadline - currentTime + 999999) / 1000000; - - if (sleepTimeMs <= 0) { - if (currentTime == Long.MIN_VALUE) { - return -Long.MAX_VALUE; - } else { - return currentTime; - } - } - - try { - //noinspection BusyWait - Thread.sleep(sleepTimeMs); - } catch (InterruptedException ignored) { - if (workerState.get() == WORKER_STATE_SHUTDOWN) { - return Long.MIN_VALUE; - } - } - } - } - - public Set unprocessedTimeouts() { - return Collections.unmodifiableSet(unprocessedTimeouts); - } - } - - private static final class HashedWheelTimeout implements Timeout { - - private static final int ST_INIT = 0; - private static final int ST_CANCELLED = 1; - private static final int ST_EXPIRED = 2; - private static final AtomicIntegerFieldUpdater STATE_UPDATER = - AtomicIntegerFieldUpdater.newUpdater(HashedWheelTimeout.class, "state"); - - private final HashedWheelTimer timer; - private final TimerTask task; - private final long deadline; - - @SuppressWarnings({"unused", "FieldMayBeFinal", "RedundantFieldInitialization"}) - private volatile int state = ST_INIT; - - // remainingRounds will be calculated and set by Worker.transferTimeoutsToBuckets() before the - // HashedWheelTimeout will be added to the correct HashedWheelBucket. - long remainingRounds; - - // This will be used to chain timeouts in HashedWheelTimerBucket via a double-linked-list. - // As only the workerThread will act on it there is no need for synchronization / volatile. - HashedWheelTimeout next; - HashedWheelTimeout prev; - - // The bucket to which the timeout was added - HashedWheelBucket bucket; - - HashedWheelTimeout(HashedWheelTimer timer, TimerTask task, long deadline) { - this.timer = timer; - this.task = task; - this.deadline = deadline; - } - - @Override - public Timer timer() { - return timer; - } - - @Override - public TimerTask task() { - return task; - } - - @Override - public boolean cancel() { - // only update the state it will be removed from HashedWheelBucket on next tick. - if (!compareAndSetState(ST_INIT, ST_CANCELLED)) { - return false; - } - // If a task should be canceled we put this to another queue which will be processed on each tick. - // So this means that we will have a GC latency of max. 1 tick duration which is good enough. This way - // we can make again use of our MpscLinkedQueue and so minimize the locking / overhead as much as possible. - timer.cancelledTimeouts.add(this); - return true; - } - - void remove() { - HashedWheelBucket bucket = this.bucket; - if (bucket != null) { - bucket.remove(this); - } else { - timer.pendingTimeouts.decrementAndGet(); - } - } - - public boolean compareAndSetState(int expected, int state) { - return STATE_UPDATER.compareAndSet(this, expected, state); - } - - public int state() { - return state; - } - - @Override - public boolean isCancelled() { - return state() == ST_CANCELLED; - } - - @Override - public boolean isExpired() { - return state() == ST_EXPIRED; - } - - public void expire() { - if (!compareAndSetState(ST_INIT, ST_EXPIRED)) { - return; - } - - try { - task.run(this); - } catch (Throwable t) { - t.printStackTrace(); - } - } - - @Override - public String toString() { - final long currentTime = System.nanoTime(); - long remaining = deadline - currentTime + timer.startTime; - - StringBuilder buf = new StringBuilder(192) - .append("HashedWheelTimer(deadline: "); - if (remaining > 0) { - buf.append(remaining) - .append(" ns later"); - } else if (remaining < 0) { - buf.append(-remaining) - .append(" ns ago"); - } else { - buf.append("now"); - } - - if (isCancelled()) { - buf.append(", cancelled"); - } - - return buf.append(", task: ") - .append(task()) - .append(')') - .toString(); - } - } - - /** - * Bucket that stores HashedWheelTimeouts. These are stored in a linked-list like datastructure to allow easy - * removal of HashedWheelTimeouts in the middle. Also the HashedWheelTimeout act as nodes themself and so no - * extra object creation is needed. - */ - private static final class HashedWheelBucket { - // Used for the linked-list datastructure - private HashedWheelTimeout head; - private HashedWheelTimeout tail; - - /** - * Add {@link HashedWheelTimeout} to this bucket. - */ - public void addTimeout(HashedWheelTimeout timeout) { - assert timeout.bucket == null; - timeout.bucket = this; - if (head == null) { - head = tail = timeout; - } else { - tail.next = timeout; - timeout.prev = tail; - tail = timeout; - } - } - - /** - * Expire all {@link HashedWheelTimeout}s for the given {@code deadline}. - */ - public void expireTimeouts(long deadline) { - HashedWheelTimeout timeout = head; - - // process all timeouts - while (timeout != null) { - HashedWheelTimeout next = timeout.next; - if (timeout.remainingRounds <= 0) { - next = remove(timeout); - if (timeout.deadline <= deadline) { - timeout.expire(); - } else { - // The timeout was placed into a wrong slot. This should never happen. - throw new IllegalStateException(String.format( - "timeout.deadline (%d) > deadline (%d)", timeout.deadline, deadline)); - } - } else if (timeout.isCancelled()) { - next = remove(timeout); - } else { - timeout.remainingRounds--; - } - timeout = next; - } - } - - public HashedWheelTimeout remove(HashedWheelTimeout timeout) { - HashedWheelTimeout next = timeout.next; - // remove timeout that was either processed or cancelled by updating the linked-list - if (timeout.prev != null) { - timeout.prev.next = next; - } - if (timeout.next != null) { - timeout.next.prev = timeout.prev; - } - - if (timeout == head) { - // if timeout is also the tail we need to adjust the entry too - if (timeout == tail) { - tail = null; - head = null; - } else { - head = next; - } - } else if (timeout == tail) { - // if the timeout is the tail modify the tail to be the prev node. - tail = timeout.prev; - } - // null out prev, next and bucket to allow for GC. - timeout.prev = null; - timeout.next = null; - timeout.bucket = null; - timeout.timer.pendingTimeouts.decrementAndGet(); - return next; - } - - /** - * Clear this bucket and return all not expired / cancelled {@link Timeout}s. - */ - public void clearTimeouts(Set set) { - for (; ; ) { - HashedWheelTimeout timeout = pollTimeout(); - if (timeout == null) { - return; - } - if (timeout.isExpired() || timeout.isCancelled()) { - continue; - } - set.add(timeout); - } - } - - private HashedWheelTimeout pollTimeout() { - HashedWheelTimeout head = this.head; - if (head == null) { - return null; - } - HashedWheelTimeout next = head.next; - if (next == null) { - tail = this.head = null; - } else { - this.head = next; - next.prev = null; - } - - // null out prev and next to allow for GC. - head.next = null; - head.prev = null; - head.bucket = null; - return head; - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/Timeout.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/Timeout.java deleted file mode 100644 index 0812e5ba..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/Timeout.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.zmops.iot.async.util.timer; - -/** - * 借鉴netty。 - * 一个连接着{@link Timer}和{@link TimerTask},表示着任务状态的“关系类” - * - * @author create by TcSnZh on 2021/5/9-下午6:33 - */ -public interface Timeout { - /** - * 返回对应的{@link Timer}。 - */ - Timer timer(); - - /** - * 返回对应的{@link TimerTask} - */ - TimerTask task(); - - /** - * 当且仅当关联的{@link TimerTask}已超时时,才返回{@code true}。 - */ - boolean isExpired(); - - /** - * 当且仅当关联的{@link TimerTask}被取消时,才返回{@code true}。 - */ - boolean isCancelled(); - - /** - * 尝试取消关联的{@link TimerTask}。如果任务已经执行或已取消,它将无副作用地返回。 - * - * @return 如果取消成功完成,则为true,否则为false - */ - @SuppressWarnings("unused") - boolean cancel(); -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/Timer.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/Timer.java deleted file mode 100644 index e834ec62..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/Timer.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.zmops.iot.async.util.timer; - -import java.util.Set; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -/** - * 照抄netty - * 让{@link TimerTask}在后台线程中执行。 - * - * @author create by TcSnZh on 2021/5/9-下午6:33 - */ -public interface Timer { - - /** - * 使{@link TimerTask}在指定的延迟后执行一次。 - * - * @param delay 延时长度 - * @param unit 延时单位 - * @return 返回 {@link Timeout}关系类 - * @throws IllegalStateException 如果此计时器已经已停止 - * @throws RejectedExecutionException 如果挂起的超时太多,则创建新的超时会导致系统不稳定。 - */ - Timeout newTimeout(TimerTask task, long delay, TimeUnit unit); - - @SuppressWarnings("unused") - default Timeout newTimeout(Runnable runnable, long delay, TimeUnit unit) { - AtomicReference timeoutRef = new AtomicReference<>(); - newTimeout(timeout -> { - timeoutRef.set(timeout); - runnable.run(); - }, delay, unit); - return timeoutRef.get(); - } - - /** - * 释放此{@link Timer}所有资源(例如线程),并取消所有尚未执行的任务。 - * - * @return 与被该方法取消的任务相关联的 {@link Timeout} - */ - Set stop(); -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/TimerTask.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/TimerTask.java deleted file mode 100644 index a552ba2f..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/TimerTask.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.zmops.iot.async.util.timer; - -/** - * 类似于netty的TimerTask。 - * - * @author create by TcSnZh on 2021/5/9-下午5:17 - */ -public interface TimerTask { - void run(Timeout timeout) throws Exception; -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/DependWrapper.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/DependWrapper.java new file mode 100644 index 00000000..1028c9a9 --- /dev/null +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/DependWrapper.java @@ -0,0 +1,59 @@ +package com.zmops.iot.async.worker; + + +import com.zmops.iot.async.wrapper.WorkerWrapper; + +/** + * 对依赖的wrapper的封装 + * @author wuweifeng wrote on 2019-12-20 + * @version 1.0 + */ +public class DependWrapper { + private WorkerWrapper dependWrapper; + /** + * 是否该依赖必须完成后才能执行自己.

+ * 因为存在一个任务,依赖于多个任务,是让这多个任务全部完成后才执行自己,还是某几个执行完毕就可以执行自己 + * 如 + * 1 + * ---3 + * 2 + * 或 + * 1---3 + * 2---3 + * 这两种就不一样,上面的就是必须12都完毕,才能3 + * 下面的就是1完毕就可以3 + */ + private boolean must = true; + + public DependWrapper(WorkerWrapper dependWrapper, boolean must) { + this.dependWrapper = dependWrapper; + this.must = must; + } + + public DependWrapper() { + } + + public WorkerWrapper getDependWrapper() { + return dependWrapper; + } + + public void setDependWrapper(WorkerWrapper dependWrapper) { + this.dependWrapper = dependWrapper; + } + + public boolean isMust() { + return must; + } + + public void setMust(boolean must) { + this.must = must; + } + + @Override + public String toString() { + return "DependWrapper{" + + "dependWrapper=" + dependWrapper + + ", must=" + must + + '}'; + } +} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/OnceWork.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/OnceWork.java deleted file mode 100644 index 021afb70..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/OnceWork.java +++ /dev/null @@ -1,386 +0,0 @@ -package com.zmops.iot.async.worker; - -import com.zmops.iot.async.executor.timer.SystemClock; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.async.wrapper.WorkerWrapperGroup; - -import java.util.*; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.function.Function; -import java.util.stream.Collectors; - -/** - * 一次工作结果的总接口。 - * - * @author tcsnzh[zh.jobs@foxmail.com] create this in 2021/5/25-下午3:22 - */ -public interface OnceWork { - /** - * 返回唯一的workId - */ - String workId(); - - /** - * 判断是否结束。因超时而结束也算结束。 - */ - boolean isFinish(); - - /** - * 同步等待到结束。 - */ - void awaitFinish() throws InterruptedException; - - /** - * 判断是否超时 - * - * @return 如果尚未结束或已结束但未超时,返回false。已结束且已经超时返回true。 - */ - boolean hasTimeout(); - - /** - * 判断是否全部wrapper都处于 执行成功 或 跳过。 - * - * @return 如果已经结束,所有wrapper都成功或跳过返回true,否则返回false。如果尚未结束,返回false。 - */ - default boolean allSuccess() { - if (!isFinish()) { - return false; - } - return getWrappers().values().stream().allMatch(wrapper -> { - final ResultState state = wrapper.getWorkResult().getResultState(); - return state == ResultState.SUCCESS || state == ResultState.DEFAULT; - }); - } - - /** - * 获取全部参与到工作中的wrapper。 - */ - Map> getWrappers(); - - /** - * 获取{@link WorkResult#getResultState()}为{@link ResultState#SUCCESS}的wrapper。 - */ - default Map> getSuccessWrappers() { - return getWrappersOfState(ResultState.SUCCESS); - } - - /** - * 获取状态于这些state中的wrapper。 - * - * @param ofState 状态列表 - * @return 返回Map - */ - default Map> getWrappersOfState(ResultState... ofState) { - final HashSet states = new HashSet<>(Arrays.asList(ofState)); - if (states.isEmpty()) { - return new HashMap<>(1); - } - return getWrappers().entrySet().stream() - .filter(entry -> states.contains(entry.getValue().getWorkResult().getResultState())) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - } - - /** - * 获取启动时间 - */ - long getStartTime(); - - /** - * 获取结束时间 - * - * @return 如果超时,返回超时的时刻。如果尚未结束,则抛出异常。 - * @throws IllegalStateException 尚未结束,抛出异常。 - */ - long getFinishTime(); - - /** - * @return 已经取消完成 - */ - boolean isCancelled(); - - /** - * @return 是否正在取消中 - */ - boolean isWaitingCancel(); - - /** - * 请求异步取消。 - */ - void pleaseCancel(); - - /** - * 同步等待取消完成。 - */ - default void pleaseCancelAndAwaitFinish() throws InterruptedException { - if (!isCancelled() && !isWaitingCancel()) { - pleaseCancel(); - } - awaitFinish(); - } - - /** - * @return 返回 {@link AsFuture}封装对象。 - */ - default AsFuture asFuture() { - return new AsFuture(this, limitTime -> limitTime / 16); - } - - /** - * 返回{@link Future}视图。 - * - * @param sleepCheckInterval 为防止线程爆炸,在{@link Future#get(long, TimeUnit)}方法时使用隔一段时间检查一次。 - * 该Function的参数为总超时毫秒值,返回值为检查时间间隔。 - * @return 返回 {@link AsFuture}封装对象。 - */ - default AsFuture asFuture(Function sleepCheckInterval) { - return new AsFuture(this, sleepCheckInterval); - } - - // static - - /** - * 空任务 - */ - static OnceWork emptyWork(String workId) { - return new EmptyWork(workId); - } - - // class - - class AsFuture implements Future>> { - private final OnceWork onceWork; - private final Function sleepCheckInterval; - - private AsFuture(OnceWork onceWork, Function sleepCheckInterval) { - this.onceWork = onceWork; - this.sleepCheckInterval = sleepCheckInterval; - } - - /** - * 同步等待取消。 - * - * @param ignore 该参数将被无视。因为暂未实现“修改允许打断属性”功能。todo : await implement - */ - @Override - public boolean cancel(boolean ignore) { - try { - if (onceWork.isFinish()) { - return false; - } - onceWork.pleaseCancelAndAwaitFinish(); - } catch (InterruptedException e) { - throw new RuntimeException("interrupted when await finish in : " + this, e); - } - return true; - } - - @Override - public boolean isCancelled() { - return onceWork.isCancelled(); - } - - @Override - public boolean isDone() { - return onceWork.isFinish(); - } - - @Override - public Map> get() throws InterruptedException, ExecutionException { - if (!onceWork.isFinish()) { - onceWork.awaitFinish(); - } - return onceWork.getWrappers(); - } - - /** - * 避免线程爆炸,该方法不予单独开线程,而是单线程{@link Thread#sleep(long)}每睡一段时间检查一次。 - */ - @Override - public Map> get(long timeout, - TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException { - final long millis = Objects.requireNonNull(unit).toMillis(timeout); - final long interval = Math.max(1, Math.min(millis, sleepCheckInterval.apply(millis))); - for (int i = 0; interval * i < millis; i++) { - if (onceWork.isFinish()) { - return onceWork.getWrappers(); - } - Thread.sleep(interval); - } - throw new TimeoutException( - "onceWork.asFuture.get(long,TimeUnit) out of time limit(" + - timeout + "," + unit + ") , this is " + this); - } - - @Override - public String toString() { - return "(asFuture from " + onceWork + ")@" + Integer.toHexString(this.hashCode()); - } - } - - abstract class AbstractOnceWork implements OnceWork { - protected final String workId; - - public AbstractOnceWork(String workId) { - this.workId = workId; - } - - @Override - public String workId() { - return workId; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof OnceWork)) { - return false; - } - OnceWork _o = (OnceWork) o; - return Objects.equals(_o.workId(), this.workId()); - } - - @Override - public int hashCode() { - return workId().hashCode(); - } - - @Override - public String toString() { - final boolean finish; - final StringBuilder sb = new StringBuilder(48) - .append(this.getClass().getSimpleName()) - .append("{isFinish=").append(finish = isFinish()) - .append(", hasTimeout=").append(hasTimeout()) - .append(", allSuccess=").append(allSuccess()) - .append(", getStartTime=").append(getStartTime()) - .append(", isCancelled=").append(isCancelled()) - .append(", isWaitingCancel=").append(isWaitingCancel()); - if (finish) { - sb.append(", getFinishTime=").append(getFinishTime()); - } - return sb - .append(", wrappers::getId=").append(getWrappers().keySet()) - .append('}').toString(); - } - } - - class Impl extends AbstractOnceWork { - protected final WorkerWrapperGroup group; - - public Impl(WorkerWrapperGroup group, String workId) { - super(workId); - this.group = group; - } - - @Override - public boolean isFinish() { - return group.getEndCDL().getCount() > 0; - } - - @Override - public void awaitFinish() throws InterruptedException { - group.getEndCDL().await(); - } - - @Override - public boolean hasTimeout() { - return group.getAnyTimeout().get(); - } - - @Override - public Map> getWrappers() { - return group.getForParamUseWrappers(); - } - - @Override - public long getStartTime() { - return group.getGroupStartTime(); - } - - @Override - public long getFinishTime() { - if (isFinish()) { - throw new IllegalStateException("work not finish."); - } - return group.getFinishTime(); - } - - @Override - public boolean isCancelled() { - return group.isCancelled(); - } - - @Override - public boolean isWaitingCancel() { - return group.isWaitingCancel(); - } - - @Override - public void pleaseCancel() { - group.pleaseCancel(); - } - } - - class EmptyWork extends AbstractOnceWork { - private final long initTime = SystemClock.now(); - - public EmptyWork(String workId) { - super(workId); - } - - @Override - public boolean isFinish() { - return true; - } - - @Override - public void awaitFinish() { - // do nothing - } - - @Override - public boolean hasTimeout() { - return false; - } - - @Override - public Map> getWrappers() { - return Collections.emptyMap(); - } - - @Override - public long getStartTime() { - return initTime; - } - - @Override - public long getFinishTime() { - return initTime; - } - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public boolean isWaitingCancel() { - return false; - } - - @Override - public void pleaseCancel() { - } - - @Override - public String toString() { - return "(it's empty work)"; - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/ResultState.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/ResultState.java index dacde052..6d1b42e9 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/ResultState.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/ResultState.java @@ -2,7 +2,6 @@ /** * 结果状态 - * * @author wuweifeng wrote on 2019-11-19. */ public enum ResultState { diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/WorkResult.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/WorkResult.java index 567f1ebd..ed557769 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/WorkResult.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/WorkResult.java @@ -7,12 +7,12 @@ public class WorkResult { /** * 执行的结果 */ - private final V result; + private V result; /** * 结果状态 */ - private final ResultState resultState; - private final Exception ex; + private ResultState resultState; + private Exception ex; public WorkResult(V result, ResultState resultState) { this(result, resultState, null); @@ -24,16 +24,10 @@ public WorkResult(V result, ResultState resultState, Exception ex) { this.ex = ex; } - /** - * 返回不可修改的DEFAULT单例。 - */ public static WorkResult defaultResult() { - //noinspection unchecked - return (WorkResult) DEFAULT; + return new WorkResult<>(null, ResultState.DEFAULT); } - private static final WorkResult DEFAULT = new WorkResult<>(null, ResultState.DEFAULT); - @Override public String toString() { return "WorkResult{" + @@ -47,11 +41,23 @@ public Exception getEx() { return ex; } + public void setEx(Exception ex) { + this.ex = ex; + } + public V getResult() { return result; } + public void setResult(V result) { + this.result = result; + } + public ResultState getResultState() { return resultState; } + + public void setResultState(ResultState resultState) { + this.resultState = resultState; + } } diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/QuickBuildWorkerWrapper.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/QuickBuildWorkerWrapper.java deleted file mode 100644 index df21cb6c..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/QuickBuildWorkerWrapper.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.zmops.iot.async.wrapper; - -import com.zmops.iot.async.callback.ICallback; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.util.collection.DirectedGraph; -import com.zmops.iot.async.util.collection.Graph; -import com.zmops.iot.async.wrapper.strategy.WrapperStrategy; - -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -/** - * 快速构造{@link WorkerWrapper},少废话! - *

- * 直接设置属性,不用麻烦Builder设置来设置去, - * 请 注 意:构造方法不会检查参数合法性,请程序员自己保证参数合法。 - *

- * 将关系存储于有向图中{@link DirectedGraph}以节省每个wrapper都要保存节点数据的开销。 - *

- * - * @author create by TcSnZh on 2021/5/13-上午11:54 - */ -public class QuickBuildWorkerWrapper extends WorkerWrapper { - private final DirectedGraph, Object> graph; - - private volatile Set> nextWrappersCache; - private volatile Set> dependWrappersCache; - - /** - * 构造函数,传入所有属性 - * - * @param id {@link WorkerWrapper#id} - * @param param {@link WorkerWrapper#param} - * @param worker {@link WorkerWrapper#worker} - * @param callback {@link WorkerWrapper#callback} - * @param allowInterrupt {@link WorkerWrapper#allowInterrupt} - * @param enableTimeout {@link WorkerWrapper#enableTimeout} - * @param timeoutLength {@link WorkerWrapper#timeoutLength} - * @param timeoutUnit {@link WorkerWrapper#timeoutLength} - * @param wrapperStrategy {@link WorkerWrapper#timeoutUnit} - * @param wrapperGraph 将节点信息保存在图中,而不是如{@link StableWorkerWrapper}在每个wrapper中都保存节点信息。 - *

- * {@link WorkerWrapper#getDependWrappers()}与{@link WorkerWrapper#getNextWrappers()}方法 - * 将从本图中读取依赖顺序。除此之外,本类不会对本图进行任何修改操作。 - * 因此,传入的此图应当保证读取时的线程安全。 - *

- */ - public QuickBuildWorkerWrapper(String id, - T param, - IWorker worker, - ICallback callback, - boolean allowInterrupt, - boolean enableTimeout, - long timeoutLength, - TimeUnit timeoutUnit, - WrapperStrategy wrapperStrategy, - DirectedGraph, Object> wrapperGraph) { - super(id, worker, callback, allowInterrupt, enableTimeout, timeoutLength, timeoutUnit, wrapperStrategy); - graph = wrapperGraph; - super.param = param; - State.setState(state, State.BUILDING, State.INIT); - } - - @Override - public Set> getNextWrappers() { - if (nextWrappersCache == null) { - synchronized (this) { - if (nextWrappersCache == null) { - nextWrappersCache = graph.getRelationFrom(this).stream() - .map(Graph.Entry::getTo).collect(Collectors.toSet()); - } - } - } - return nextWrappersCache; - } - - @Override - public Set> getDependWrappers() { - if (dependWrappersCache == null) { - synchronized (this) { - if (dependWrappersCache == null) { - dependWrappersCache = graph.getRelationTo(this).stream() - .map(Graph.Entry::getFrom).collect(Collectors.toSet()); - } - } - } - return dependWrappersCache; - } - - @Override - void setNextWrappers(Set> nextWrappers) { - throw new UnsupportedOperationException(); - } - - @Override - void setDependWrappers(Set> dependWrappers) { - throw new UnsupportedOperationException(); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/StableWorkerWrapper.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/StableWorkerWrapper.java deleted file mode 100644 index 4622a4af..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/StableWorkerWrapper.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.zmops.iot.async.wrapper; - -import com.zmops.iot.async.callback.ICallback; -import com.zmops.iot.async.callback.IWorker; - -import java.util.Set; -import java.util.concurrent.TimeUnit; - -/** - * {@link WorkerWrapper}默认实现类,将上下游Wrapper保存在自己的Set中。 - * - * @author create by TcSnZh on 2021/5/6-下午2:41 - */ -public class StableWorkerWrapper extends WorkerWrapper { - public StableWorkerWrapper(String id, - IWorker worker, - ICallback callback, - boolean allowInterrupt, - boolean enableTimeout, - long timeoutLength, - TimeUnit timeoutUnit) { - super(id, worker, callback, allowInterrupt, enableTimeout, timeoutLength, timeoutUnit); - } - - /** - * 依赖的wrappers,其dependType字段决定了依赖策略。 - * - *

- * v1.5时将其抽取到本子类。 - * 且修改List为Set,并默认使用LinkedHashSet,以提高id索引效率且保持有序(虽然有序也没什么用)。 - *

- */ - private Set> dependWrappers; - /** - * 在自己后面的wrapper,如果没有,自己就是末尾;如果有一个,就是串行;如果有多个,有几个就需要开几个线程

- * -------2 - * 1 - * -------3 - * 如1后面有2、3 - * - *

- * v1.5时将其抽取到本子类。 - * 且修改List为Set,并在{@link StableWorkerWrapperBuilder}中默认使用LinkedHashSet,以提高id索引效率且保持有序(虽然有序也没什么用)。 - *

- */ - private Set> nextWrappers; - - // ========== public impl ========== - - @Override - public Set> getNextWrappers() { - return nextWrappers; - } - - // ========== package impl ========== - - @Override - void setNextWrappers(Set> nextWrappers) { - this.nextWrappers = nextWrappers; - } - - @Override - public Set> getDependWrappers() { - return dependWrappers; - } - - @Override - void setDependWrappers(Set> dependWrappers) { - this.dependWrappers = dependWrappers; - } - -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/StableWorkerWrapperBuilder.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/StableWorkerWrapperBuilder.java deleted file mode 100644 index 3795eca6..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/StableWorkerWrapperBuilder.java +++ /dev/null @@ -1,504 +0,0 @@ -package com.zmops.iot.async.wrapper; - -import com.zmops.iot.async.callback.ICallback; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.exception.SkippedException; -import com.zmops.iot.async.worker.WorkResult; -import com.zmops.iot.async.wrapper.strategy.depend.DependMustStrategyMapper; -import com.zmops.iot.async.wrapper.strategy.depend.DependOnUpWrapperStrategy; -import com.zmops.iot.async.wrapper.strategy.depend.DependOnUpWrapperStrategyMapper; -import com.zmops.iot.async.wrapper.strategy.depend.DependenceStrategy; -import com.zmops.iot.async.wrapper.strategy.skip.SkipStrategy; - -import java.util.*; -import java.util.concurrent.TimeUnit; - -/** - * 一个稳定的Builder,兼容1.4版本之前的代码。 - *

- * 效果等同于v1.4及之前的{@link WorkerWrapper.Builder}。 - *

- * 考虑到由于废弃了must方式编排、needCheckNextWrapperResult判断跳过,转用策略器方式,导致本类为了向上兼容保留了一些低效的功能。 - *

- * 权限修饰符为default,表示暂不对外开放。 - * - * @author create by TcSnZh on 2021/5/3-上午12:36 - */ -class StableWorkerWrapperBuilder> - implements WorkerWrapperBuilder { - /** - * 该wrapper的唯一标识。 - * 如果不设置则使用{@code UUID.randomUUID().toString()} - */ - private String id; - /** - * worker将来要处理的param - */ - private T param; - private IWorker worker; - private ICallback callback; - /** - * 自己后面的所有 - */ - private Set> nextWrappers; - /** - * 自己依赖的所有 - */ - private Set> dependWrappers; - /** - * 旧版本的检查是否跳过的开关 - */ - private Boolean needCheckNextWrapperResult = null; - /** - * 新版本的检查是否跳过的策略。 - */ - private SkipStrategy skipStrategy; - /** - * 基本依赖策略。 - *

- * 如果在{@link #build()}调用时,{@code dependenceStrategy==null}, - * 则会给WorkerWrapper设置默认策略{@link DependenceStrategy#ALL_DEPENDENCIES_ALL_SUCCESS}。 - */ - private DependenceStrategy dependenceStrategy; - /** - * 存储自己需要特殊对待的dependWrapper集合 - */ - private Map, DependOnUpWrapperStrategy> dependWrapperActionStrategyMap; - /** - * 存储需要特殊对待自己的nextWrapper集合。 - */ - private Map, DependOnUpWrapperStrategy> selfIsSpecialMap; - /** - * 一个保存以must=true方式传入的WorkerWrapper的集合。 - *

- * 该Set将会加入到{@link WorkerWrapper.StableWrapperStrategy#getDependMustStrategyMapper().mustDependSet}之中 - */ - private Set> mustDependSet; - /** - * 存储强依赖于自己的wrapper集合 - */ - private Set> selfIsMustSet; - /** - * 是否使用了旧的编排模式(Must开关) - *

- * 之所以需要以下两个属性,是为了隔离旧api与新api的策略不兼容的情况。建议早日替换旧方法 - * 例如旧代码里调用{@link WorkerWrapper.Builder#depend(WorkerWrapper, boolean)},参数传入了false。 - */ - private boolean useV15DeprecatedMustDependApi = false; - /** - * 是否使用了新的编排模式。 - *

- * {@link #useV15DeprecatedMustDependApi} - */ - private boolean useV15NewDependApi = false; - /** - * 单个Wrapper超时相关属性 - */ - private boolean enableTimeOut = false; - private long time = -1; - private TimeUnit unit = null; - /** - * 是否允许被打断 - */ - private boolean allowInterrupt = false; - - /** - * 标记自己正在building - */ - private boolean isBuilding = false; - - @Override - public BUILDER_SUB_CLASS worker(IWorker worker) { - this.worker = worker; - return returnThisBuilder(); - } - - @Override - public BUILDER_SUB_CLASS param(T t) { - this.param = t; - return returnThisBuilder(); - } - - @Override - public BUILDER_SUB_CLASS id(String id) { - if (id != null) { - this.id = id; - } - return returnThisBuilder(); - } - - @Override - public BUILDER_SUB_CLASS setSkipStrategy(SkipStrategy strategy) { - this.skipStrategy = strategy; - return returnThisBuilder(); - } - - @Override - public BUILDER_SUB_CLASS callback(ICallback callback) { - this.callback = callback; - return returnThisBuilder(); - } - - @Override - public SetDependImpl setDepend() { - useV15NewDependApi = true; - checkCanNotCompatibleDeprecateMustDependApi(false); - return new SetDependImpl(); - } - - public class SetDependImpl implements SetDepend { - @Override - public SetDependImpl wrapper(WorkerWrapper wrapper) { - if (wrapper == null) { - return this; - } - if (dependWrappers == null) { - dependWrappers = new LinkedHashSet<>(); - } - dependWrappers.add(wrapper); - return this; - } - - @Override - public SetDependImpl mustRequireWrapper(WorkerWrapper wrapper) { - if (wrapper == null) { - return this; - } - wrapper(wrapper); - if (mustDependSet == null) { - mustDependSet = new LinkedHashSet<>(); - } - mustDependSet.add(wrapper); - return this; - } - - @Override - public SetDependImpl specialDependWrapper(DependOnUpWrapperStrategy strategy, WorkerWrapper wrapper) { - if (strategy == null || wrapper == null) { - return this; - } - if (dependWrapperActionStrategyMap == null) { - dependWrapperActionStrategyMap = new LinkedHashMap<>(); - } - dependWrapperActionStrategyMap.put(wrapper, strategy); - return this; - } - - @Override - public SetDependImpl strategy(DependenceStrategy dependenceStrategy) { - if (dependenceStrategy == null) { - return this; - } - StableWorkerWrapperBuilder.this.dependenceStrategy = dependenceStrategy; - return this; - } - - @Override - public BUILDER_SUB_CLASS end() { - return returnThisBuilder(); - } - } - - @Override - public SetNextImpl setNext() { - useV15NewDependApi = true; - checkCanNotCompatibleDeprecateMustDependApi(false); - return new SetNextImpl(); - } - - public class SetNextImpl implements SetNext { - @Override - public SetNextImpl wrapper(WorkerWrapper wrapper) { - if (wrapper == null) { - return this; - } - if (nextWrappers == null) { - nextWrappers = new LinkedHashSet<>(); - } - nextWrappers.add(wrapper); - return this; - } - - @Override - public SetNextImpl mustToNextWrapper(WorkerWrapper wrapper) { - if (wrapper == null) { - return this; - } - wrapper(wrapper); - if (selfIsMustSet == null) { - selfIsMustSet = new LinkedHashSet<>(); - } - selfIsMustSet.add(wrapper); - return this; - } - - @Override - public SetNextImpl specialToNextWrapper(DependOnUpWrapperStrategy strategy, WorkerWrapper wrapper) { - if (strategy == null || wrapper == null) { - return this; - } - wrapper(wrapper); - if (selfIsSpecialMap == null) { - selfIsSpecialMap = new LinkedHashMap<>(); - } - selfIsSpecialMap.put(wrapper, strategy); - return this; - } - - @Override - public BUILDER_SUB_CLASS end() { - return returnThisBuilder(); - } - } - - @Override - public SetTimeOut setTimeOut() { - return new SetTimeOutImpl(); - } - - public class SetTimeOutImpl implements SetTimeOut { - @Override - public SetTimeOutImpl enableTimeOut(boolean enableElseDisable) { - StableWorkerWrapperBuilder.this.enableTimeOut = enableElseDisable; - return this; - } - - @Override - public SetTimeOutImpl setTime(long time, TimeUnit unit) { - if (time <= 0 || unit == null) { - throw new IllegalStateException("Illegal argument : time=" + time + " must > 0, unit=" + unit + " require not null"); - } - StableWorkerWrapperBuilder.this.time = time; - StableWorkerWrapperBuilder.this.unit = unit; - return this; - } - - @Override - public BUILDER_SUB_CLASS end() { - return returnThisBuilder(); - } - } - - @Override - public WorkerWrapperBuilder allowInterrupt(boolean allow) { - allowInterrupt = allow; - return returnThisBuilder(); - } - - @Override - public WorkerWrapper build() { - isBuilding = true; - // ========== 设置单wrapper超时检查 ========== - { - if (enableTimeOut) { - if (time <= 0) { - throw new IllegalArgumentException("timeout time " + time + " must > 0"); - } - if (unit == null) { - throw new IllegalArgumentException(new NullPointerException("timeout unit require not null")); - } - } - } - // ========== 构造wrapper ========== - WorkerWrapper wrapper = new StableWorkerWrapper<>( - id == null ? UUID.randomUUID().toString() : id, - worker, - callback, - allowInterrupt, - enableTimeOut, - time, - unit - ); - wrapper.setDependWrappers(new LinkedHashSet<>()); - wrapper.setNextWrappers(new LinkedHashSet<>()); - // ========== 设置依赖关系/策略 ========== - { - if (dependWrappers != null && dependWrappers.size() > 0) { - dependWrappers.forEach(dependWrapper -> { - wrapper.getDependWrappers().add(dependWrapper); - dependWrapper.getNextWrappers().add(wrapper); - }); - } - if (nextWrappers != null && nextWrappers.size() > 0) { - nextWrappers.forEach(next -> { - wrapper.getNextWrappers().add(next); - next.getDependWrappers().add(wrapper); - }); - } - if (useV15DeprecatedMustDependApi) { - // 适配旧api的must开关 - if (mustDependSet != null && mustDependSet.size() > 0) { - wrapper.getWrapperStrategy().setDependMustStrategyMapper(new DependMustStrategyMapper() - .addDependMust(mustDependSet)); - } - //noinspection deprecation - wrapper.getWrapperStrategy().setDependenceStrategy(DependenceStrategy.IF_MUST_SET_NOT_EMPTY_ALL_SUCCESS_ELSE_ANY); - } else { - if (mustDependSet != null && mustDependSet.size() > 0) { - wrapper.getWrapperStrategy().setDependMustStrategyMapper(new DependMustStrategyMapper().addDependMust(mustDependSet)); - } - if (dependenceStrategy == null) { - setDepend().defaultStrategy(); - } - wrapper.getWrapperStrategy().setDependenceStrategy(dependenceStrategy); - } - if (dependWrapperActionStrategyMap != null && dependWrapperActionStrategyMap.size() > 0) { - DependOnUpWrapperStrategyMapper mapper = new DependOnUpWrapperStrategyMapper(); - dependWrapperActionStrategyMap.forEach(mapper::putMapping); - wrapper.getWrapperStrategy().setDependWrapperStrategyMapper(mapper); - } - if (selfIsMustSet != null && selfIsMustSet.size() > 0) { - //noinspection deprecation - selfIsMustSet.forEach(next -> Optional.ofNullable(next.getWrapperStrategy().getDependMustStrategyMapper()) - .ifPresent(mustMapper -> mustMapper.addDependMust(wrapper))); - } - if (selfIsSpecialMap != null && selfIsSpecialMap.size() > 0) { - selfIsSpecialMap.forEach((next, strategy) -> { - DependOnUpWrapperStrategyMapper dependOnUpWrapperStrategyMapper = next.getWrapperStrategy().getDependWrapperStrategyMapper(); - if (dependOnUpWrapperStrategyMapper == null) { - next.getWrapperStrategy().setDependWrapperStrategyMapper( - dependOnUpWrapperStrategyMapper = new DependOnUpWrapperStrategyMapper()); - } - dependOnUpWrapperStrategyMapper.putMapping(wrapper, strategy); - }); - } - } - // ========== 设置检查是否跳过策略 ========== - { - if (skipStrategy == null) { - wrapper.getWrapperStrategy().setSkipStrategy(needCheckNextWrapperResult != null && !needCheckNextWrapperResult ? - SkipStrategy.NOT_SKIP - : SkipStrategy.CHECK_ONE_LEVEL - ); - } else { - wrapper.getWrapperStrategy().setSkipStrategy(skipStrategy); - } - } - // ========== end ========== - wrapper.state.set(WorkerWrapper.State.INIT.id); - wrapper.setParam(param); - return wrapper; - } - - // ========== deprecated methods ========== - - /** - * @deprecated 建议使用 {@link WorkerWrapperBuilder#depends(WorkerWrapper[])} - * 或{@link WorkerWrapperBuilder#setDepend()}设置更多选项,例如{@link SetDepend#wrapper(WorkerWrapper[])} - * 如果是想要“必须依赖”的功能,则使用{@link SetDepend#mustRequireWrapper(WorkerWrapper[])} - */ - @Deprecated - public BUILDER_SUB_CLASS depend(WorkerWrapper... wrappers) { - if (wrappers == null) { - return returnThisBuilder(); - } - for (WorkerWrapper wrapper : wrappers) { - depend(wrapper); - } - return returnThisBuilder(); - } - - /** - * @deprecated 建议使用 {@link WorkerWrapperBuilder#depends(WorkerWrapper[])}。 - * 或{@link WorkerWrapperBuilder#setDepend()}设置更多选项,例如{@link SetDepend#wrapper(WorkerWrapper)} - * 如果是想要“必须依赖”的功能,则使用{@link SetDepend#mustRequireWrapper(WorkerWrapper[])} - */ - @Deprecated - public BUILDER_SUB_CLASS depend(WorkerWrapper wrapper) { - return depend(wrapper, true); - } - - /** - * @deprecated 建议使用 {@link SetDepend#requireWrapper(WorkerWrapper, boolean)}} - */ - @Deprecated - public BUILDER_SUB_CLASS depend(WorkerWrapper wrapper, boolean isMust) { - if (wrapper == null) { - return returnThisBuilder(); - } - useV15DeprecatedMustDependApi = true; - checkCanNotCompatibleDeprecateMustDependApi(true); - if (dependWrappers == null) { - dependWrappers = new LinkedHashSet<>(); - } - dependWrappers.add(wrapper); - if (isMust) { - if (mustDependSet == null) { - mustDependSet = new LinkedHashSet<>(); - } - mustDependSet.add(wrapper); - } - return returnThisBuilder(); - } - - @Deprecated - public BUILDER_SUB_CLASS next(WorkerWrapper... wrappers) { - if (wrappers == null) { - return returnThisBuilder(); - } - for (WorkerWrapper wrapper : wrappers) { - next(wrapper); - } - return returnThisBuilder(); - } - - @Deprecated - public BUILDER_SUB_CLASS next(WorkerWrapper wrapper) { - return next(wrapper, true); - } - - /** - * 会将wrapper增加到{@link #nextWrappers}。 - * 如果selfIsMust为true,还会将wrapper额外增加到{@link #selfIsMustSet}。 - * - * @param wrapper WorkerWrapper instance - * @param selfIsMust 是否强依赖自己(“强依赖”是旧版本的叫法。即是否必须在自己执行后才能执行。) - * @return 返回Builder。 - * @deprecated 不推荐使用Must开关去设置之后的Wrapper。 - */ - @Deprecated - public BUILDER_SUB_CLASS next(WorkerWrapper wrapper, boolean selfIsMust) { - useV15DeprecatedMustDependApi = true; - checkCanNotCompatibleDeprecateMustDependApi(true); - if (nextWrappers == null) { - nextWrappers = new LinkedHashSet<>(); - } - nextWrappers.add(wrapper); - //强依赖自己 - if (selfIsMust) { - if (selfIsMustSet == null) { - selfIsMustSet = new LinkedHashSet<>(); - } - selfIsMustSet.add(wrapper); - } - return returnThisBuilder(); - } - - /** - * 设置是否要检查之后的Wrapper是否已经执行完毕。 - *

- * 默认为true。 - * - * @param needCheckNextWrapperResult 设为true后,如果之后的Wrapper已经执行完毕。 - * 则跳过本Wrapper并设置{@link WorkResult#getEx()}为{@link SkippedException}。 - * @deprecated v1.5中已经废弃。请使用 - */ - @Deprecated - public BUILDER_SUB_CLASS needCheckNextWrapperResult(boolean needCheckNextWrapperResult) { - this.needCheckNextWrapperResult = needCheckNextWrapperResult; - return returnThisBuilder(); - } - - // util method - - private BUILDER_SUB_CLASS returnThisBuilder() { - //noinspection unchecked - return (BUILDER_SUB_CLASS) this; - } - - private void checkCanNotCompatibleDeprecateMustDependApi(boolean isOld) { - if (!isBuilding && (!isOld && useV15DeprecatedMustDependApi || isOld && useV15NewDependApi)) { - throw new UnsupportedOperationException("新旧api之间不可兼容,请将v1.5之前废弃的方法升级为注释中建议的方法后再调用v1.5之后的新api"); - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapper.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapper.java index 72246cf3..2da373a5 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapper.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapper.java @@ -3,777 +3,616 @@ import com.zmops.iot.async.callback.DefaultCallback; import com.zmops.iot.async.callback.ICallback; import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.exception.CancelException; -import com.zmops.iot.async.exception.EndsNormallyException; import com.zmops.iot.async.exception.SkippedException; -import com.zmops.iot.async.executor.PollingCenter; import com.zmops.iot.async.executor.timer.SystemClock; +import com.zmops.iot.async.worker.DependWrapper; import com.zmops.iot.async.worker.ResultState; import com.zmops.iot.async.worker.WorkResult; -import com.zmops.iot.async.wrapper.strategy.WrapperStrategy; -import com.zmops.iot.async.wrapper.strategy.depend.DependMustStrategyMapper; -import com.zmops.iot.async.wrapper.strategy.depend.DependOnUpWrapperStrategyMapper; -import com.zmops.iot.async.wrapper.strategy.depend.DependenceAction; -import com.zmops.iot.async.wrapper.strategy.depend.DependenceStrategy; -import com.zmops.iot.async.wrapper.strategy.skip.SkipStrategy; import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.*; /** * 对每个worker及callback进行包装,一对一 - *

- * v1.5时将其抽取为抽象类,以解耦并提高扩展性。 * * @author wuweifeng wrote on 2019-11-19. */ -@SuppressWarnings("AlibabaAbstractClassShouldStartWithAbstractNaming") -public abstract class WorkerWrapper { - // ========== 固定属性 ========== +public class WorkerWrapper { /** * 该wrapper的唯一标识 */ - protected final String id; - protected final IWorker worker; - protected final ICallback callback; - /** - * 各种策略的封装类。 - */ - private final WrapperStrategy wrapperStrategy; - /** - * 是否允许被打断 - */ - protected final boolean allowInterrupt; - /** - * 是否启动超时检查 - */ - final boolean enableTimeout; + private final String id; + /** - * 超时时间长度 + * worker将来要处理的param */ - final long timeoutLength; + private T param; + private final IWorker worker; + private final ICallback callback; + + /** - * 超时时间单位 + * 在自己后面的wrapper,如果没有,自己就是末尾;如果有一个,就是串行;如果有多个,有几个就需要开几个线程

+ * -------2 + * 1 + * -------3 + * 如1后面有2、3 */ - final TimeUnit timeoutUnit; - - // ========== 临时属性 ========== + private List> nextWrappers; /** - * worker将来要处理的param + * 依赖的wrappers,有2种情况,1:必须依赖的全部完成后,才能执行自己 2:依赖的任何一个、多个完成了,就可以执行自己 + * 通过must字段来控制是否依赖项必须完成 + * 1 + * -------3 + * 2 + * 1、2执行完毕后才能执行3 */ - protected volatile T param; + private List dependWrappers; + /** - * 原子设置wrapper的状态 + * 标记该事件是否已经被处理过了,譬如已经超时返回false了,后续rpc又收到返回值了,则不再二次回调 + * 经试验,volatile并不能保证"同一毫秒"内,多线程对该值的修改和拉取 *

- * {@link State}此枚举类枚举了state值所代表的状态枚举。 + * 1-finish, 2-error, 3-working */ - protected final AtomicInteger state = new AtomicInteger(State.BUILDING.id); + private final AtomicInteger state = new AtomicInteger(0); + /** - * 该值将在{@link IWorker#action(Object, Map)}进行时设为当前线程,在任务开始前或结束后都为null。 + * 该map存放所有wrapper的id和wrapper映射 */ - protected final AtomicReference doWorkingThread = new AtomicReference<>(); + private Map forParamUseWrappers; + /** * 也是个钩子变量,用来存临时的结果 */ - protected final AtomicReference> workResult = new AtomicReference<>(null); - - WorkerWrapper(String id, - IWorker worker, - ICallback callback, - boolean allowInterrupt, - boolean enableTimeout, - long timeoutLength, - TimeUnit timeoutUnit, - WrapperStrategy wrapperStrategy - ) { + private volatile WorkResult workResult = WorkResult.defaultResult(); + + /** + * 是否在执行自己前,去校验nextWrapper的执行结果

+ * 1 4 + * -------3 + * 2 + * 如这种在4执行前,可能3已经执行完毕了(被2执行完后触发的),那么4就没必要执行了。 + * 注意,该属性仅在nextWrapper数量<=1时有效,>1时的情况是不存在的 + */ + private volatile boolean needCheckNextWrapperResult = true; + + private static final int FINISH = 1; + private static final int ERROR = 2; + private static final int WORKING = 3; + private static final int INIT = 0; + + private WorkerWrapper(String id, IWorker worker, T param, ICallback callback) { if (worker == null) { throw new NullPointerException("async.worker is null"); } this.worker = worker; + this.param = param; this.id = id; //允许不设置回调 if (callback == null) { - //noinspection unchecked - callback = (ICallback) DefaultCallback.getInstance(); + callback = new DefaultCallback<>(); } this.callback = callback; - this.allowInterrupt = allowInterrupt; - this.enableTimeout = enableTimeout; - this.timeoutLength = timeoutLength; - this.timeoutUnit = timeoutUnit; - this.wrapperStrategy = wrapperStrategy; - } - - WorkerWrapper(String id, - IWorker worker, - ICallback callback, - boolean allowInterrupt, - boolean enableTimeout, - long timeoutLength, - TimeUnit timeoutUnit) { - this(id, worker, callback, allowInterrupt, enableTimeout, timeoutLength, timeoutUnit, new StableWrapperStrategy()); } - // ========== public ========== - /** - * 外部调用本线程运行此wrapper的入口方法。 - * 该方法将会确定这组wrapper所属的group。 - * - * @param executorService 该ExecutorService将成功运行后,在nextWrapper有多个时被使用于多线程调用。 - * @param remainTime 剩下的时间 - * @param group wrapper组 - * @throws IllegalStateException 当wrapper正在building状态时被启动,则会抛出该异常。 + * 开始工作 + * fromWrapper代表这次work是由哪个上游wrapper发起的 */ - public void work(ExecutorService executorService, - long remainTime, - WorkerWrapperGroup group) { - work(executorService, null, remainTime, group); - } + private void work(ExecutorService executorService, WorkerWrapper fromWrapper, long remainTime, Map forParamUseWrappers) { + this.forParamUseWrappers = forParamUseWrappers; + //将自己放到所有wrapper的集合里去 + forParamUseWrappers.put(id, this); + long now = SystemClock.now(); + //总的已经超时了,就快速失败,进行下一个 + if (remainTime <= 0) { + fastFail(INIT, null); + beginNext(executorService, now, remainTime); + return; + } + //如果自己已经执行过了。 + //可能有多个依赖,其中的一个依赖已经执行完了,并且自己也已开始执行或执行完毕。当另一个依赖执行完毕,又进来该方法时,就不重复处理了 + if (getState() == FINISH || getState() == ERROR) { + beginNext(executorService, now, remainTime); + return; + } - public String getId() { - return id; - } + //如果在执行前需要校验nextWrapper的状态 + if (needCheckNextWrapperResult) { + //如果自己的next链上有已经出结果或已经开始执行的任务了,自己就不用继续了 + if (!checkNextWrapperResult()) { + fastFail(INIT, new SkippedException()); + beginNext(executorService, now, remainTime); + return; + } + } - /** - * 返回{@link #workResult}的值。 - * 若调用此方法时workResult还未设置,将会返回{@link WorkResult#defaultResult()}。 - */ - public WorkResult getWorkResult() { - WorkResult res = workResult.get(); - return res == null ? WorkResult.defaultResult() : res; - } + //如果没有任何依赖,说明自己就是第一批要执行的 + if (dependWrappers == null || dependWrappers.size() == 0) { + fire(); + beginNext(executorService, now, remainTime); + return; + } - public void setParam(T param) { - this.param = param; - } + /*如果有前方依赖,存在两种情况 + 一种是前面只有一个wrapper。即 A -> B + 一种是前面有多个wrapper。A C D -> B。需要A、C、D都完成了才能轮到B。但是无论是A执行完,还是C执行完,都会去唤醒B。 + 所以需要B来做判断,必须A、C、D都完成,自己才能执行 */ + + //只有一个依赖 + if (dependWrappers.size() == 1) { + doDependsOneJob(fromWrapper); + beginNext(executorService, now, remainTime); + } else { + //有多个依赖时 + doDependsJobs(executorService, dependWrappers, fromWrapper, now, remainTime); + } - public State getState() { - return of(state.get()); } - /** - * 获取下游Wrapper - */ - public abstract Set> getNextWrappers(); + + public void work(ExecutorService executorService, long remainTime, Map forParamUseWrappers) { + work(executorService, null, remainTime, forParamUseWrappers); + } /** - * 获取上游wrapper + * 总控制台超时,停止所有任务 */ - public abstract Set> getDependWrappers(); + public void stopNow() { + if (getState() == INIT || getState() == WORKING) { + fastFail(getState(), null); + } + } /** - * 获取本wrapper的超时情况。如有必要还会修改wrapper状态。 - * - * @param withEndIt 如果为true,在检查出已经超时的时候,会将其快速结束。 - * @param startTime 起始时间 - * @param totalTimeLength 总任务时长 - * @return 超时返回-1L,结束但未超时返回0L,尚未结束且未超时返回与deadline的差值 - *

- * 当没有超时,若该wrapper已经结束但没有超时,返回 0L 。 - *

- * 如果该wrapper单独了设置超时策略并正在运行,返回距离超时策略限时相差的毫秒值。 - * 例如设置10ms超时,此时已经开始3ms,则返回 7L。 - * 如果此差值<1,则返回 1L。 - *

- * 如果已经超时,则返回 -1L。 - *

+ * 判断自己下游链路上,是否存在已经出结果的或已经开始执行的 + * 如果没有返回true,如果有返回false */ - public long checkTimeout(boolean withEndIt, long startTime, long totalTimeLength) { - do { - WorkResult _workResult = workResult.get(); - // 如果已经有结果了,就根据结果值判断 - if (_workResult != null) { - return _workResult.getResultState() == ResultState.TIMEOUT ? -1L : 0L; - } - // 如果还没有出结果 - // 判断是否超时 - long now = SystemClock.now(); - if (totalTimeLength < now - startTime - || enableTimeout && timeoutUnit.toMillis(timeoutLength) < now - startTime) { - // 如果需要处理该wrapper的状态 - if (withEndIt) { - // CAS一个超时的结果 - if (!workResult.compareAndSet( - null, - new WorkResult<>(null, ResultState.TIMEOUT, null)) - ) { - // 就在想CAS的时候,出结果了,就采用新的结果重新判断一次 - continue; - } - fastFail(true, null, false); - } - return -1L; - } - // 正在运行,尚未超时 - else { - return Math.max(1, startTime + totalTimeLength - now); - } - } while (true); + private boolean checkNextWrapperResult() { + //如果自己就是最后一个,或者后面有并行的多个,就返回true + if (nextWrappers == null || nextWrappers.size() != 1) { + return getState() == INIT; + } + WorkerWrapper nextWrapper = nextWrappers.get(0); + boolean state = nextWrapper.getState() == INIT; + //继续校验自己的next的状态 + return state && nextWrapper.checkNextWrapperResult(); } /** - * 直接取消wrapper运行。 - * 如果状态在 {@link State#states_of_beforeWorkingEnd}中,则调用 {@link #fastFail(boolean, Exception, boolean)}。 + * 进行下一个任务 */ - public void cancel() { - if (State.setState(state, State.states_of_beforeWorkingEnd, State.SKIP, null)) { - fastFail(false, new CancelException(), true); + private void beginNext(ExecutorService executorService, long now, long remainTime) { + //花费的时间 + long costTime = SystemClock.now() - now; + if (nextWrappers == null) { + return; + } + if (nextWrappers.size() == 1) { + nextWrappers.get(0).work(executorService, WorkerWrapper.this, remainTime - costTime, forParamUseWrappers); + return; + } + CompletableFuture[] futures = new CompletableFuture[nextWrappers.size()]; + for (int i = 0; i < nextWrappers.size(); i++) { + int finalI = i; + futures[i] = CompletableFuture.runAsync(() -> nextWrappers.get(finalI) + .work(executorService, WorkerWrapper.this, remainTime - costTime, forParamUseWrappers), executorService); + } + try { + CompletableFuture.allOf(futures).get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); } } - public WrapperStrategy getWrapperStrategy() { - return wrapperStrategy; + private void doDependsOneJob(WorkerWrapper dependWrapper) { + if (ResultState.TIMEOUT == dependWrapper.getWorkResult().getResultState()) { + workResult = defaultResult(); + fastFail(INIT, null); + } else if (ResultState.EXCEPTION == dependWrapper.getWorkResult().getResultState()) { + workResult = defaultExResult(dependWrapper.getWorkResult().getEx()); + fastFail(INIT, null); + } else { + //前面任务正常完毕了,该自己了 + fire(); + } } - // ========== protected ========== - - /** - * 工作的核心方法。 - * - * @param fromWrapper 代表这次work是由哪个上游wrapper发起的。如果是首个Wrapper则为null。 - * @param remainTime 剩余时间。 - * @throws IllegalStateException 当wrapper正在building状态时被启动,则会抛出该异常。 - */ - protected void work(ExecutorService executorService, - WorkerWrapper fromWrapper, - long remainTime, - WorkerWrapperGroup group - ) { - long now = SystemClock.now(); - // ================================================ - // 以下是一些lambda。 - // 因为抽取成方法反而不好传参、污染类方法,所以就这么干了 - final Consumer __function__callbackResult = - success -> { - WorkResult _workResult = getWorkResult(); - try { - callback.result(success, param, _workResult); - } catch (Exception e) { - if (setState(state, State.states_of_skipOrAfterWork, State.ERROR, null)) { - fastFail(false, e, _workResult.getEx() instanceof EndsNormallyException); - } - } - }; - final Runnable __function__callbackResultOfFalse_beginNext = - () -> { - __function__callbackResult.accept(false); - beginNext(executorService, now, remainTime, group); - }; - final BiConsumer __function__fastFail_callbackResult$false_beginNext = - (fastFail_isTimeout, fastFail_exception) -> { - boolean isEndsNormally = fastFail_exception instanceof EndsNormallyException; - fastFail(fastFail_isTimeout && !isEndsNormally, fastFail_exception, isEndsNormally); - __function__callbackResultOfFalse_beginNext.run(); - }; - final Runnable __function__doWork = - () -> { - if (setState(state, State.STARTED, State.WORKING)) { - try { - fire(group); - } catch (Exception e) { - if (setState(state, State.WORKING, State.ERROR)) { - __function__fastFail_callbackResult$false_beginNext.accept(false, e); - } - return; - } - } - if (setState(state, State.WORKING, State.AFTER_WORK)) { - __function__callbackResult.accept(true); - beginNext(executorService, now, remainTime, group); - } - }; - // ================================================ - // 开始执行 - try { - if (isState(state, BUILDING)) { - throw new IllegalStateException("wrapper can't work because state is BUILDING ! wrapper is " + this); + private synchronized void doDependsJobs(ExecutorService executorService, List dependWrappers, WorkerWrapper fromWrapper, long now, long remainTime) { + boolean nowDependIsMust = false; + //创建必须完成的上游wrapper集合 + Set mustWrapper = new HashSet<>(); + for (DependWrapper dependWrapper : dependWrappers) { + if (dependWrapper.isMust()) { + mustWrapper.add(dependWrapper); } - // 判断是否整组取消 - if (group.isWaitingCancel() || group.isCancelled()) { - cancel(); - return; + if (dependWrapper.getDependWrapper().equals(fromWrapper)) { + nowDependIsMust = dependWrapper.isMust(); } - // 总的已经超时了,就快速失败,进行下一个 - if (remainTime <= 0) { - if (setState(state, states_of_beforeWorkingEnd, ERROR, null)) { - __function__fastFail_callbackResult$false_beginNext.accept(true, null); - } - return; + } + + //如果全部是不必须的条件,那么只要到了这里,就执行自己。 + if (mustWrapper.size() == 0) { + if (ResultState.TIMEOUT == fromWrapper.getWorkResult().getResultState()) { + fastFail(INIT, null); + } else { + fire(); } - // 如果自己已经执行过了。 - // 可能有多个依赖,其中的一个依赖已经执行完了,并且自己也已开始执行或执行完毕。当另一个依赖执行完毕,又进来该方法时,就不重复处理了 - final AtomicReference oldStateRef = new AtomicReference<>(null); - if (!setState(state, states_of_notWorked, STARTED, oldStateRef::set)) { - return; + beginNext(executorService, now, remainTime); + return; + } + + //如果存在需要必须完成的,且fromWrapper不是必须的,就什么也不干 + if (!nowDependIsMust) { + return; + } + + //如果fromWrapper是必须的 + boolean existNoFinish = false; + boolean hasError = false; + //先判断前面必须要执行的依赖任务的执行结果,如果有任何一个失败,那就不用走action了,直接给自己设置为失败,进行下一步就是了 + for (DependWrapper dependWrapper : mustWrapper) { + WorkerWrapper workerWrapper = dependWrapper.getDependWrapper(); + WorkResult tempWorkResult = workerWrapper.getWorkResult(); + //为null或者isWorking,说明它依赖的某个任务还没执行到或没执行完 + if (workerWrapper.getState() == INIT || workerWrapper.getState() == WORKING) { + existNoFinish = true; + break; } - // 如果wrapper是第一次,要调用callback.begin - if (oldStateRef.get() == INIT) { - try { - callback.begin(); - } catch (Exception e) { - // callback.begin 发生异常 - if (setState(state, states_of_beforeWorkingEnd, ERROR, null)) { - __function__fastFail_callbackResult$false_beginNext.accept(false, e); - } - return; - } + if (ResultState.TIMEOUT == tempWorkResult.getResultState()) { + workResult = defaultResult(); + hasError = true; + break; } - - //如果fromWrapper为null,说明自己就是第一批要执行的 - if (fromWrapper == null) { - // 首当其冲,开始工作 - __function__doWork.run(); - return; + if (ResultState.EXCEPTION == tempWorkResult.getResultState()) { + workResult = defaultExResult(workerWrapper.getWorkResult().getEx()); + hasError = true; + break; } - // 每个线程都需要判断是否要跳过自己,该方法可能会跳过正在工作的自己。 - final WrapperStrategy wrapperStrategy = getWrapperStrategy(); - if (wrapperStrategy.shouldSkip(getNextWrappers(), this, fromWrapper)) { - if (setState(state, STARTED, SKIP)) { - __function__fastFail_callbackResult$false_beginNext.accept(false, new SkippedException()); - } - return; - } + } + //只要有失败的 + if (hasError) { + fastFail(INIT, null); + beginNext(executorService, now, remainTime); + return; + } - // 如果是由其他wrapper调用而运行至此,则使用策略器决定自己的行为 - DependenceAction.WithProperty judge = - wrapperStrategy.judgeAction(getDependWrappers(), this, fromWrapper); - switch (judge.getDependenceAction()) { - case TAKE_REST: - return; - case FAST_FAIL: - if (setState(state, STARTED, ERROR)) { - // 根据FAST_FAIL.fastFailException()设置的属性值来设置fastFail方法的参数 - ResultState resultState = judge.getResultState(); - __function__fastFail_callbackResult$false_beginNext.accept( - resultState == ResultState.TIMEOUT, - judge.getFastFailException() - ); - } - return; - case START_WORK: - __function__doWork.run(); - return; - case JUDGE_BY_AFTER: - default: - throw new IllegalStateException( - "策略配置错误,不应当在WorkerWrapper中返回JUDGE_BY_AFTER或其他无效值 : this=" + this + - ",fromWrapper=" + fromWrapper); - } - } catch (Exception e) { - // wrapper本身抛出了不该有的异常 - setState(state, states_all, ERROR, null); - NotExpectedException ex = new NotExpectedException(e, this); - workResult.set(new WorkResult<>(null, ResultState.EXCEPTION, ex)); - __function__fastFail_callbackResult$false_beginNext.accept(false, ex); + //如果上游都没有失败,分为两种情况,一种是都finish了,一种是有的在working + //都finish的话 + if (!existNoFinish) { + //上游都finish了,进行自己 + fire(); + beginNext(executorService, now, remainTime); + return; } } - /** - * 本工作线程执行自己的job. - *

- * 本方法不负责校验状态。请在调用前自行检验 + * 执行自己的job.具体的执行是在另一个线程里,但判断阻塞超时是在work线程 */ - protected void fire(WorkerWrapperGroup group) { - try { - doWorkingThread.set(Thread.currentThread()); - //执行耗时操作 - V result = worker.action(param, group.getForParamUseWrappers()); - workResult.compareAndSet( - null, - new WorkResult<>(result, ResultState.SUCCESS) - ); - } finally { - doWorkingThread.set(null); - } + private void fire() { + //阻塞取结果 + workResult = workerDoJob(); } /** - * 快速失败。 - * 该方法不负责检查状态,请自行控制。 - * - * @param isTimeout 是否是因为超时而快速失败 - * @param e 设置异常信息到{@link WorkResult#getEx()} - * @param isEndsNormally 是否是因正常情况正常而结束,例如跳过{@link SkippedException}、取消{@link CancelException}。 + * 快速失败 */ - protected void fastFail(boolean isTimeout, Exception e, boolean isEndsNormally) { - // 试图打断正在执行{@link IWorker#action(Object, Map)}的线程 - Thread _doWorkingThread; - if ((_doWorkingThread = this.doWorkingThread.get()) != null - // 不会打断自己 - && !Objects.equals(Thread.currentThread(), _doWorkingThread)) { - _doWorkingThread.interrupt(); - } - // 尚未处理过结果则设置 - workResult.compareAndSet(null, new WorkResult<>( - worker.defaultValue(), - isTimeout ? ResultState.TIMEOUT : (isEndsNormally ? ResultState.DEFAULT : ResultState.EXCEPTION), - e - )); + private boolean fastFail(int expect, Exception e) { + //试图将它从expect状态,改成Error + if (!compareAndSetState(expect, ERROR)) { + return false; + } + + //尚未处理过结果 + if (checkIsNullResult()) { + if (e == null) { + workResult = defaultResult(); + } else { + workResult = defaultExResult(e); + } + } + + callback.result(false, param, workResult); + return true; } /** - * 进行下一个任务 - *

- * 本方法不负责校验状态。请在调用前自行检验 + * 具体的单个worker执行任务 */ - protected void beginNext(ExecutorService executorService, long now, long remainTime, WorkerWrapperGroup group) { - //花费的时间 - final long costTime = SystemClock.now() - now; - final long nextRemainTIme = remainTime - costTime; - Set> nextWrappers = getNextWrappers(); - if (nextWrappers == null) { - PollingCenter.getInstance().checkGroup(group.new CheckFinishTask()); - return; + private WorkResult workerDoJob() { + //避免重复执行 + if (!checkIsNullResult()) { + return workResult; } - // nextWrappers只有一个,就用本线程继续跑。 - if (nextWrappers.size() == 1) { - WorkerWrapper next = null; - try { - next = nextWrappers.stream().findFirst().get(); - group.addWrapper(next); - setState(state, AFTER_WORK, SUCCESS); - } finally { - PollingCenter.getInstance().checkGroup(group.new CheckFinishTask()); - if (next != null) { - next.work(executorService, this, nextRemainTIme, group); - } + try { + //如果已经不是init状态了,说明正在被执行或已执行完毕。这一步很重要,可以保证任务不被重复执行 + if (!compareAndSetState(INIT, WORKING)) { + return workResult; } - } - // nextWrappers有多个 - else { - try { - group.addWrapper(nextWrappers); - nextWrappers.forEach(next -> executorService.submit(() -> - next.work(executorService, this, nextRemainTIme, group)) - ); - setState(state, AFTER_WORK, SUCCESS); - } finally { - PollingCenter.getInstance().checkGroup(group.new CheckFinishTask()); + + callback.begin(); + + //执行耗时操作 + V resultValue = worker.action(param, forParamUseWrappers); + + //如果状态不是在working,说明别的地方已经修改了 + if (!compareAndSetState(WORKING, FINISH)) { + return workResult; } - } + workResult.setResultState(ResultState.SUCCESS); + workResult.setResult(resultValue); + //回调成功 + callback.result(true, param, workResult); + + return workResult; + } catch (Exception e) { + //避免重复回调 + if (!checkIsNullResult()) { + return workResult; + } + fastFail(WORKING, e); + return workResult; + } } - // ========== hashcode and equals ========== + public WorkResult getWorkResult() { + return workResult; + } - @Override - public boolean equals(Object o) { - return super.equals(o); + public List> getNextWrappers() { + return nextWrappers; } - /** - * {@code return id.hashCode();}返回id值的hashcode - */ - @Override - public int hashCode() { - // final String id can use to .hashcode() . - return id.hashCode(); + public void setParam(T param) { + this.param = param; } - // ========== builder ========== + private boolean checkIsNullResult() { + return ResultState.DEFAULT == workResult.getResultState(); + } - public static WorkerWrapperBuilder builder() { - return new Builder<>(); + private void addDepend(WorkerWrapper workerWrapper, boolean must) { + addDepend(new DependWrapper(workerWrapper, must)); } - /** - * 自v1.5,该类被抽取到{@link StableWorkerWrapperBuilder}抽象类,兼容之前的版本。 - */ - public static class Builder extends StableWorkerWrapperBuilder> { - /** - * @deprecated 建议使用 {@link #builder()}返回{@link WorkerWrapperBuilder}接口,以调用v1.5之后的规范api - */ - @SuppressWarnings("DeprecatedIsStillUsed") - @Deprecated - public Builder() { + private void addDepend(DependWrapper dependWrapper) { + if (dependWrappers == null) { + dependWrappers = new ArrayList<>(); } + //如果依赖的是重复的同一个,就不重复添加了 + for (DependWrapper wrapper : dependWrappers) { + if (wrapper.equals(dependWrapper)) { + return; + } + } + dependWrappers.add(dependWrapper); } - // ========== package access methods ========== - - abstract void setNextWrappers(Set> nextWrappers); + private void addNext(WorkerWrapper workerWrapper) { + if (nextWrappers == null) { + nextWrappers = new ArrayList<>(); + } + //避免添加重复 + for (WorkerWrapper wrapper : nextWrappers) { + if (workerWrapper.equals(wrapper)) { + return; + } + } + nextWrappers.add(workerWrapper); + } - abstract void setDependWrappers(Set> dependWrappers); + private void addNextWrappers(List> wrappers) { + if (wrappers == null) { + return; + } + for (WorkerWrapper wrapper : wrappers) { + addNext(wrapper); + } + } - // ========== toString ========== + private void addDependWrappers(List dependWrappers) { + if (dependWrappers == null) { + return; + } + for (DependWrapper wrapper : dependWrappers) { + addDepend(wrapper); + } + } - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(256) - .append(this.getClass().getSimpleName()) - .append("{id=").append(id) - .append(", state=").append(of(state.get())) - .append(", param=").append(param) - .append(", workResult=").append(workResult) - .append(", allowInterrupt=").append(allowInterrupt) - .append(", enableTimeout=").append(enableTimeout) - .append(", timeoutLength=").append(timeoutLength) - .append(", timeoutUnit=").append(timeoutUnit) - // 防止循环引用,这里只输出相关Wrapper的id - .append(", dependWrappers::getId=["); - final Set> dependWrappers = getDependWrappers(); - dependWrappers.stream().map(WorkerWrapper::getId).forEach(wrapperId -> sb.append(wrapperId).append(", ")); - if (dependWrappers.size() > 0) { - sb.delete(sb.length() - 2, sb.length()); - } - sb - .append("], nextWrappers::getId=["); - final Set> nextWrappers = getNextWrappers(); - nextWrappers.stream().map(WorkerWrapper::getId).forEach(wrapperId -> sb.append(wrapperId).append(", ")); - if (nextWrappers.size() > 0) { - sb.delete(sb.length() - 2, sb.length()); - } - sb - .append("], doWorkingThread=").append(doWorkingThread.get()) - .append(", worker=").append(worker) - .append(", callback=").append(callback) - .append(", wrapperStrategy=").append(wrapperStrategy) - .append('}'); - return sb.toString(); + private WorkResult defaultResult() { + workResult.setResultState(ResultState.TIMEOUT); + workResult.setResult(worker.defaultValue()); + return workResult; } - /** - * 一个通用的策略器实现类,提供了修改的功能。并兼容之前的代码。 - */ - public static class StableWrapperStrategy extends WrapperStrategy.AbstractWrapperStrategy { - private DependOnUpWrapperStrategyMapper dependOnUpWrapperStrategyMapper; - private DependMustStrategyMapper dependMustStrategyMapper; - private DependenceStrategy dependenceStrategy; - private SkipStrategy skipStrategy; + private WorkResult defaultExResult(Exception ex) { + workResult.setResultState(ResultState.EXCEPTION); + workResult.setResult(worker.defaultValue()); + workResult.setEx(ex); + return workResult; + } - @Override - public DependOnUpWrapperStrategyMapper getDependWrapperStrategyMapper() { - return dependOnUpWrapperStrategyMapper; - } - @Override - public void setDependWrapperStrategyMapper(DependOnUpWrapperStrategyMapper dependOnUpWrapperStrategyMapper) { - this.dependOnUpWrapperStrategyMapper = dependOnUpWrapperStrategyMapper; - } + private int getState() { + return state.get(); + } - @SuppressWarnings("deprecation") - @Override - public DependMustStrategyMapper getDependMustStrategyMapper() { - return dependMustStrategyMapper; - } + public String getId() { + return id; + } - @Override - public void setDependMustStrategyMapper(DependMustStrategyMapper dependMustStrategyMapper) { - this.dependMustStrategyMapper = dependMustStrategyMapper; - } + private boolean compareAndSetState(int expect, int update) { + return this.state.compareAndSet(expect, update); + } - @Override - public DependenceStrategy getDependenceStrategy() { - return dependenceStrategy; - } + private void setNeedCheckNextWrapperResult(boolean needCheckNextWrapperResult) { + this.needCheckNextWrapperResult = needCheckNextWrapperResult; + } - @Override - public void setDependenceStrategy(DependenceStrategy dependenceStrategy) { - this.dependenceStrategy = dependenceStrategy; + @Override + public boolean equals(Object o) { + if (this == o) { + return true; } - - @Override - public SkipStrategy getSkipStrategy() { - return skipStrategy; + if (o == null || getClass() != o.getClass()) { + return false; } + WorkerWrapper that = (WorkerWrapper) o; + return needCheckNextWrapperResult == that.needCheckNextWrapperResult && + Objects.equals(param, that.param) && + Objects.equals(worker, that.worker) && + Objects.equals(callback, that.callback) && + Objects.equals(nextWrappers, that.nextWrappers) && + Objects.equals(dependWrappers, that.dependWrappers) && + Objects.equals(state, that.state) && + Objects.equals(workResult, that.workResult); + } - @Override - public void setSkipStrategy(SkipStrategy skipStrategy) { - this.skipStrategy = skipStrategy; - } + @Override + public int hashCode() { + return Objects.hash(param, worker, callback, nextWrappers, dependWrappers, state, workResult, needCheckNextWrapperResult); } - /** - * state状态枚举工具类 - */ - public enum State { - /** - * 初始化中,builder正在设置其数值 - */ - BUILDING(-1), - /** - * 初始化完成,但是还未执行过。 - */ - INIT(0), - /** - * 执行过。 - * 即至少进行了一次各种判定,例如判断 是否跳过/是否启动工作 - */ - STARTED(1), + public static class Builder { /** - * 工作状态 + * 该wrapper的唯一标识 */ - WORKING(2), + private String id = UUID.randomUUID().toString(); /** - * 工作完成后的收尾工作,例如调用下游wrapper + * worker将来要处理的param */ - AFTER_WORK(3), + private W param; + private IWorker worker; + private ICallback callback; /** - * wrapper成功执行结束 + * 自己后面的所有 */ - SUCCESS(4), + private List> nextWrappers; /** - * wrapper失败了 + * 自己依赖的所有 */ - ERROR(5), + private List dependWrappers; /** - * wrapper被跳过 + * 存储强依赖于自己的wrapper集合 */ - SKIP(6); + private Set> selfIsMustSet; - // public + private boolean needCheckNextWrapperResult = true; - public boolean finished() { - return this == SUCCESS || this == ERROR || this == SKIP; + public Builder worker(IWorker worker) { + this.worker = worker; + return this; } - // package - - State(int id) { - this.id = id; + public Builder param(W w) { + this.param = w; + return this; } - final int id; - - // package-static - - static final State[] states_of_notWorked = new State[]{INIT, STARTED}; - - static final State[] states_of_skipOrAfterWork = new State[]{SKIP, AFTER_WORK}; - - static final State[] states_of_beforeWorkingEnd = new State[]{INIT, STARTED, WORKING}; + public Builder id(String id) { + if (id != null) { + this.id = id; + } + return this; + } - static final State[] states_all = new State[]{BUILDING, INIT, STARTED, WORKING, AFTER_WORK, SUCCESS, ERROR, SKIP}; + public Builder needCheckNextWrapperResult(boolean needCheckNextWrapperResult) { + this.needCheckNextWrapperResult = needCheckNextWrapperResult; + return this; + } - /** - * 自旋+CAS的设置状态,如果状态不在exceptValues返回内 或 没有设置成功,则返回false。 - * - * @param state {@link WorkerWrapper#state} 要被修改的AtomicInteger引用 - * @param exceptValues 期望的值数组,任何满足该值的state都会被修改 - * @param newValue 新值 - * @param withOperate 如果该参数不为null并且成功设置,该函数将会被执行,其参数为wrapper原子设置之前的旧状态。 - * 之所以需要这个参数,是因为当except值有多个时,无法确定是哪个值被原子修改了。 - * @return 返回是否成功设置。 - */ - static boolean setState(AtomicInteger state, - State[] exceptValues, - State newValue, - Consumer withOperate) { - int current; - boolean inExcepts; - while (true) { - // 判断当前值是否在exceptValues范围内 - current = state.get(); - inExcepts = false; - for (State exceptValue : exceptValues) { - if (inExcepts = current == exceptValue.id) { - break; - } - } - // 如果不在 exceptValues 范围内,直接返回false。 - if (!inExcepts) { - return false; - } - // 如果在 exceptValues 范围,cas成功返回true,失败(即当前值被修改)则自旋。 - if (state.compareAndSet(current, newValue.id)) { - if (withOperate != null) { - withOperate.accept(of(current)); - } - return true; - } - } + public Builder callback(ICallback callback) { + this.callback = callback; + return this; } - /** - * 自旋+CAS的设置状态,如果状态不在exceptValues返回内 或 没有设置成功自旋后不在范围内,则返回false。 - * - * @param state {@link WorkerWrapper#state} 要被修改的AtomicInteger引用 - * @param exceptValue 期望的值 - * @param newValue 新值 - * @return 返回是否成功设置。 - */ - static boolean setState(AtomicInteger state, - State exceptValue, - State newValue) { - int current; - // 如果当前值与期望值相同 - while ((current = state.get()) == exceptValue.id) { - // 则尝试CAS设置新值 - if (state.compareAndSet(current, newValue.id)) { - return true; - } - // 如果当前值被改变,则尝试自旋 + public Builder depend(WorkerWrapper... wrappers) { + if (wrappers == null) { + return this; } - // 如果当前值与期望值不相同了,就直接返回false - return false; + for (WorkerWrapper wrapper : wrappers) { + depend(wrapper); + } + return this; } - /** - * 自旋+CAS的判断是否在这些excepts范围内 - * - * @param excepts 范围。 - */ - @SuppressWarnings("unused") - static boolean inStates(AtomicInteger state, State... excepts) { - int current; - boolean inExcepts; - while (true) { - current = state.get(); - inExcepts = false; - for (State except : excepts) { - if (current == except.id) { - inExcepts = true; - break; - } - } - if (state.get() == current) { - return inExcepts; - } - } + public Builder depend(WorkerWrapper wrapper) { + return depend(wrapper, true); } - /** - * CAS的判断是否是某个状态 - */ - static boolean isState(AtomicInteger state, @SuppressWarnings("SameParameterValue") State except) { - return state.compareAndSet(except.id, except.id); + public Builder depend(WorkerWrapper wrapper, boolean isMust) { + if (wrapper == null) { + return this; + } + DependWrapper dependWrapper = new DependWrapper(wrapper, isMust); + if (dependWrappers == null) { + dependWrappers = new ArrayList<>(); + } + dependWrappers.add(dependWrapper); + return this; } - static State of(int id) { - return id2state.get(id); + public Builder next(WorkerWrapper wrapper) { + return next(wrapper, true); } - static final Map id2state; + public Builder next(WorkerWrapper wrapper, boolean selfIsMust) { + if (nextWrappers == null) { + nextWrappers = new ArrayList<>(); + } + nextWrappers.add(wrapper); - static { - HashMap map = new HashMap<>(); - for (State s : State.values()) { - map.put(s.id, s); + //强依赖自己 + if (selfIsMust) { + if (selfIsMustSet == null) { + selfIsMustSet = new HashSet<>(); + } + selfIsMustSet.add(wrapper); } - id2state = Collections.unmodifiableMap(map); + return this; } + public Builder next(WorkerWrapper... wrappers) { + if (wrappers == null) { + return this; + } + for (WorkerWrapper wrapper : wrappers) { + next(wrapper); + } + return this; + } - } + public WorkerWrapper build() { + WorkerWrapper wrapper = new WorkerWrapper<>(id, worker, param, callback); + wrapper.setNeedCheckNextWrapperResult(needCheckNextWrapperResult); + if (dependWrappers != null) { + for (DependWrapper workerWrapper : dependWrappers) { + workerWrapper.getDependWrapper().addNext(wrapper); + wrapper.addDepend(workerWrapper); + } + } + if (nextWrappers != null) { + for (WorkerWrapper workerWrapper : nextWrappers) { + boolean must = false; + if (selfIsMustSet != null && selfIsMustSet.contains(workerWrapper)) { + must = true; + } + workerWrapper.addDepend(wrapper, must); + wrapper.addNext(workerWrapper); + } + } - /** - * 这是因未知错误而引发的异常 - */ - public static class NotExpectedException extends Exception { - public NotExpectedException(Throwable cause, WorkerWrapper wrapper) { - super("It's should not happened Exception . wrapper is " + wrapper, cause); + return wrapper; } + } } diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapperBuilder.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapperBuilder.java deleted file mode 100644 index 424f766c..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapperBuilder.java +++ /dev/null @@ -1,291 +0,0 @@ -package com.zmops.iot.async.wrapper; - -import com.zmops.iot.async.callback.ICallback; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.strategy.depend.DependOnUpWrapperStrategy; -import com.zmops.iot.async.wrapper.strategy.depend.DependenceStrategy; -import com.zmops.iot.async.wrapper.strategy.skip.SkipStrategy; - -import java.util.Collection; -import java.util.concurrent.TimeUnit; - -/** - * 作为优化编排依赖策略后,新增的Builder接口。 - *

- * 该接口中不再开放很多过时的api。 - * - * @author create by TcSnZh on 2021/5/4-下午1:26 - */ -@SuppressWarnings("unused") -public interface WorkerWrapperBuilder { - /** - * 设置唯一id。 - * 如果不设置,{@link StableWorkerWrapperBuilder}会使用UUID - */ - WorkerWrapperBuilder id(String id); - - /** - * 设置{@link IWorker}执行方法。 - * - * @param worker 传入接口实现类/lambda - */ - WorkerWrapperBuilder worker(IWorker worker); - - /** - * wrapper启动后的传入参数。 - * - * @param t 参数 - */ - WorkerWrapperBuilder param(T t); - - /** - * 设置{@link ICallback}回调方法。 - */ - WorkerWrapperBuilder callback(ICallback callback); - - /** - * 设置跳过策略。通常用于检查下游Wrapper是否已经完成。 - *

- * 允许不设置。{@link StableWorkerWrapperBuilder}将会默认设置为检查深度为1的下游Wrapper是否执行完成。 - * - * @param strategy 跳过策略函数。 - */ - WorkerWrapperBuilder setSkipStrategy(SkipStrategy strategy); - - /** - * 设置上游Wrapper依赖关系的选项。 - */ - SetDepend setDepend(); - - @SuppressWarnings({"UnusedReturnValue"}) - interface SetDepend { - /** - * 设置在本Wrapper之前的上游Wrapper。 - * - * @param wrapper 允许传入null。 - */ - SetDepend wrapper(WorkerWrapper wrapper); - - default SetDepend wrapper(WorkerWrapper... wrappers) { - if (wrappers == null) { - return this; - } - for (WorkerWrapper wrapper : wrappers) { - wrapper(wrapper); - } - return this; - } - - default SetDepend wrapper(Collection wrappers) { - if (wrappers == null) { - return this; - } - wrappers.forEach(this::wrapper); - return this; - } - - /** - * 设置必须要执行成功的Wrapper,当所有被该方法设为的上游Wrapper执行成功时,本Wrapper才能执行 - */ - SetDepend mustRequireWrapper(WorkerWrapper wrapper); - - default SetDepend mustRequireWrapper(WorkerWrapper... wrappers) { - if (wrappers == null) { - return this; - } - for (WorkerWrapper wrapper : wrappers) { - mustRequireWrapper(wrapper); - } - return this; - } - - /** - * 一个用于动态判断是否must的方法,与旧的{@code .depend(WorkerWrapper,boolean)}效果相同。 - * - * @param must 如果为true,则等同于{@link #mustRequireWrapper(WorkerWrapper)},否则等同于{@link #wrapper(WorkerWrapper)} - */ - default SetDepend requireWrapper(WorkerWrapper wrapper, boolean must) { - return must ? mustRequireWrapper(wrapper) : wrapper(wrapper); - } - - /** - * 对单个Wrapper设置特殊策略。 - * - * @param wrapper 需要设置特殊策略的Wrapper。 - * @param strategy 特殊策略。 - */ - SetDepend specialDependWrapper(DependOnUpWrapperStrategy strategy, WorkerWrapper wrapper); - - default SetDepend specialDependWrapper(DependOnUpWrapperStrategy strategy, WorkerWrapper... wrappers) { - if (strategy == null || wrappers == null) { - return this; - } - for (WorkerWrapper workerWrapper : wrappers) { - specialDependWrapper(strategy, workerWrapper); - } - return this; - } - - /** - * 设置基本策略并返回。 - *

- * 如果从未调用该方法,则在{@link #build()}时使用{@link #defaultStrategy()}作为默认策略。 - *

- * - * @param dependenceStrategy 根据上游Wrapper判断本Wrapper是否启动的最终策略。 - */ - SetDepend strategy(DependenceStrategy dependenceStrategy); - - /** - * 默认策略为{@link DependenceStrategy#ALL_DEPENDENCIES_ALL_SUCCESS} - */ - default SetDepend defaultStrategy() { - return strategy(DependenceStrategy.ALL_DEPENDENCIES_ALL_SUCCESS); - } - - /** - * 结束依赖关系设置。返回到所属的{@link WorkerWrapperBuilder} - */ - WorkerWrapperBuilder end(); - } - - /** - * 便捷式设置依赖的上游Wrapper。 - * - * @param wrappers 上游Wrapper - */ - default WorkerWrapperBuilder depends(WorkerWrapper... wrappers) { - return setDepend().wrapper(wrappers).end(); - } - - default WorkerWrapperBuilder depends(Collection wrappers) { - return setDepend().wrapper(wrappers).end(); - } - - default WorkerWrapperBuilder depends(DependenceStrategy strategy, WorkerWrapper... wrappers) { - return setDepend().wrapper(wrappers).strategy(strategy).end(); - } - - default WorkerWrapperBuilder depends(DependenceStrategy strategy, Collection wrappers) { - return setDepend().wrapper(wrappers).strategy(strategy).end(); - } - - /** - * 设置下游Wrapper依赖关系的选项。 - */ - SetNext setNext(); - - interface SetNext { - /** - * 设置在本Wrapper之后的下游Wrapper。 - */ - SetNext wrapper(WorkerWrapper wrapper); - - default SetNext wrapper(WorkerWrapper... wrappers) { - if (wrappers == null) { - return this; - } - for (WorkerWrapper wrapper : wrappers) { - wrapper(wrapper); - } - return this; - } - - default SetNext wrapper(Collection wrappers) { - if (wrappers == null) { - return this; - } - wrappers.forEach(this::wrapper); - return this; - } - - /** - * 调用该方法将会让传入的此下游workerWrappers对本Wrapper强依赖(must) - * - * @param wrapper 下游Wrapper - */ - SetNext mustToNextWrapper(WorkerWrapper wrapper); - - default SetNext requireToNextWrapper(WorkerWrapper wrapper, boolean must) { - return must ? mustToNextWrapper(wrapper) : wrapper(wrapper); - } - - /** - * 调用该方法将会让传入的此下游workerWrappers对本Wrapper进行特殊策略判断, - * - * @param strategy 对本Wrapper的特殊策略。 - * @param wrapper 依赖本Wrapper的下游Wrapper。 - * @return 返回Builder自身。 - */ - SetNext specialToNextWrapper(DependOnUpWrapperStrategy strategy, WorkerWrapper wrapper); - - WorkerWrapperBuilder end(); - } - - /** - * 便捷式设置本Wrapper被依赖的下游Wrapper。 - * - * @param wrappers 下游Wrapper - */ - default WorkerWrapperBuilder nextOf(WorkerWrapper... wrappers) { - return setNext().wrapper(wrappers).end(); - } - - default WorkerWrapperBuilder nextOf(Collection wrappers) { - return setNext().wrapper(wrappers).end(); - } - - /** - * 设置超时时间的具体属性 - */ - SetTimeOut setTimeOut(); - - interface SetTimeOut { - /** - * 是否启动超时判断。 - *

- * 默认为true - * - * @param enableElseDisable 是则true - */ - SetTimeOut enableTimeOut(boolean enableElseDisable); - - /** - * 设置单个WorkerWrapper的超时时间。若不设置则不进行超时判断 - * - * @param time 时间数值 - * @param unit 时间单位 - */ - SetTimeOut setTime(long time, TimeUnit unit); - - WorkerWrapperBuilder end(); - } - - /** - * 便携式设置单个WorkerWrapper的超时时间。若不设置则不进行超时判断 - * - * @param time 时间数值 - * @param unit 时间单位 - */ - default WorkerWrapperBuilder timeout(long time, TimeUnit unit) { - return timeout(true, time, unit); - } - - default WorkerWrapperBuilder timeout(boolean enableTimeOut, long time, TimeUnit unit) { - return setTimeOut().enableTimeOut(enableTimeOut).setTime(time, unit).end(); - } - - /** - * 是否允许被试图中断线程 - * - * @param allow 是则true - */ - WorkerWrapperBuilder allowInterrupt(boolean allow); - - /** - * 构建Wrapper。 - * - * @return 返回WorkerWrapper - */ - WorkerWrapper build(); -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapperGroup.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapperGroup.java deleted file mode 100644 index f89ed240..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapperGroup.java +++ /dev/null @@ -1,211 +0,0 @@ -package com.zmops.iot.async.wrapper; - -import com.zmops.iot.async.executor.PollingCenter; -import com.zmops.iot.async.executor.timer.SystemClock; -import com.zmops.iot.async.util.timer.Timeout; -import com.zmops.iot.async.util.timer.TimerTask; - -import java.util.Collection; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.stream.Stream; - -/** - * @author create by TcSnZh on 2021/5/9-下午7:21 - */ -public class WorkerWrapperGroup { - /** - * 任务开始时间 - */ - private final long groupStartTime; - /** - * 任务限时 - */ - private final long timeoutLength; - /** - * 该map存放所有wrapper的id和wrapper映射 - *

- * 需要线程安全。 - */ - private final Map> forParamUseWrappers = new ConcurrentHashMap<>(); - /** - * 当全部wrapper都调用结束,它会countDown - */ - private final CountDownLatch endCDL = new CountDownLatch(1); - /** - * 检测到超时,此标记变量将为true。 - */ - private final AtomicBoolean anyTimeout = new AtomicBoolean(false); - /** - * 结束时间 - */ - private volatile long finishTime = -1L; - /** - * 取消任务状态 - * 0 - not cancel , 1 - waiting cancel , 2 - already cancel - */ - private final AtomicInteger cancelState = new AtomicInteger(); - - public static final int NOT_CANCEL = 0; - public static final int WAITING_CANCEL = 1; - public static final int ALREADY_CANCEL = 2; - - public WorkerWrapperGroup(long groupStartTime, long timeoutLength) { - this.groupStartTime = groupStartTime; - this.timeoutLength = timeoutLength; - } - - public void addWrapper(Collection> wrapper) { - Objects.requireNonNull(wrapper).forEach(this::addWrapper); - } - - public void addWrapper(WorkerWrapper... wrappers) { - for (WorkerWrapper wrapper : Objects.requireNonNull(wrappers)) { - addWrapper(wrapper); - } - } - - public void addWrapper(WorkerWrapper wrapper) { - if (wrapper != null) { - forParamUseWrappers.put(wrapper.id, wrapper); - } - } - - public Map> getForParamUseWrappers() { - return forParamUseWrappers; - } - - public CountDownLatch getEndCDL() { - return endCDL; - } - - public long getGroupStartTime() { - return groupStartTime; - } - - public AtomicBoolean getAnyTimeout() { - return anyTimeout; - } - - public long getFinishTime() { - return finishTime; - } - - public boolean isCancelled() { - return cancelState.get() == ALREADY_CANCEL; - } - - public boolean isWaitingCancel() { - return cancelState.get() == WAITING_CANCEL; - } - - @SuppressWarnings("UnusedReturnValue") - public boolean pleaseCancel() { - return cancelState.compareAndSet(NOT_CANCEL, WAITING_CANCEL); - } - - public class CheckFinishTask implements TimerTask { - - @SuppressWarnings("RedundantThrows") - @Override - public void run(Timeout timeout) throws Exception { - // 已经完成了 - if (endCDL.getCount() < 1) { - return; - } - AtomicBoolean hasTimeout = new AtomicBoolean(false); - // 记录正在运行中的wrapper里,最近的限时时间。 - final AtomicLong minDaley = new AtomicLong(Long.MAX_VALUE); - final Collection> values = forParamUseWrappers.values(); - final Stream> stream = values.size() > 128 ? values.parallelStream() : values.stream(); - final boolean needCancel = cancelState.get() == WAITING_CANCEL; - boolean allFinish_and_notNeedCancel = stream - // 需要取消的话就取消 - .peek(wrapper -> { - if (needCancel) { - wrapper.cancel(); - } - }) - // 检查超时并保存最近一次限时时间 - // 当需要取消时,才会不断遍历。如果不需要取消,则计算一次(或并行流中多次)就因allMatch不满足而退出了。 - .peek(wrapper -> { - // time_diff : - // -1 -> already timeout ; - // 0 -> finish but not timeout ; - // X>0 -> is running , may timeout in X seconds . - long time_diff = wrapper.checkTimeout(true, groupStartTime, timeoutLength); - if (time_diff < 0) { - hasTimeout.set(true); - } - if (time_diff == 0) { - return; - } - // use CAS and SPIN for thread safety in parallelStream . - do { - long getMinDaley = minDaley.get(); - // 需要设置最小时间,但是cas失败,则自旋 - if (getMinDaley <= time_diff && !minDaley.compareAndSet(getMinDaley, time_diff)) { - continue; - } - return; - } while (true); - }) - // 判断是否不需要取消且全部结束 - // 在不需要取消时,这里如果还有未结束的wrapper则会提前结束流并返回false - // 在需要取消时,会全部遍历一遍并取消掉已经进入链路的wrapper - .allMatch(wrapper -> !needCancel && wrapper.getState().finished()); - long getMinDaley = minDaley.get(); - // 如果本次取消掉了任务,或是所有wrapper都已经完成 - // ( ps : 前后两条件在这里是必定 一真一假 或 两者全假 ) - if (needCancel || allFinish_and_notNeedCancel) { - // 如果这次进行了取消,则设置取消状态为已完成 - if (needCancel) { - cancelState.set(ALREADY_CANCEL); - } - anyTimeout.set(hasTimeout.get()); - finishTime = SystemClock.now(); - endCDL.countDown(); - } - // 如果有正在运行的wrapper - else { - // 如果有正在WORKING的wrapper,则计算一下限时时间,限时完成后轮询它。 - if (getMinDaley != Long.MAX_VALUE) { - PollingCenter.getInstance().checkGroup(this, getMinDaley); - } - } - } - - // hashCode and equals will called WorkerWrapperGroup.this - - /** - * 将会调用{@link WorkerWrapperGroup#hashCode()} - */ - @Override - public int hashCode() { - return WorkerWrapperGroup.this.hashCode(); - } - - /** - * 将会调用{@link WorkerWrapperGroup#equals(Object)} - */ - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof CheckFinishTask)) { - return false; - } - return Objects.equals(WorkerWrapperGroup.this, ((CheckFinishTask) obj).getParent()); - } - - private WorkerWrapperGroup getParent() { - return WorkerWrapperGroup.this; - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/WrapperStrategy.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/WrapperStrategy.java deleted file mode 100644 index d94a076b..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/WrapperStrategy.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.zmops.iot.async.wrapper.strategy; - - -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.async.wrapper.strategy.depend.DependMustStrategyMapper; -import com.zmops.iot.async.wrapper.strategy.depend.DependOnUpWrapperStrategyMapper; -import com.zmops.iot.async.wrapper.strategy.depend.DependenceAction; -import com.zmops.iot.async.wrapper.strategy.depend.DependenceStrategy; -import com.zmops.iot.async.wrapper.strategy.skip.SkipStrategy; - -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * @author create by TcSnZh on 2021/5/17-下午6:23 - */ -public interface WrapperStrategy extends DependenceStrategy, SkipStrategy { - // ========== 这三个策略器用于链式判断是否要开始工作 ========== - - // 从前往后依次判断的顺序为 dependWrapperStrategyMapper -> dependMustStrategyMapper -> dependenceStrategy - - /** - * 设置对特殊Wrapper专用的依赖响应策略。 - * - * @return 该值允许为null - */ - DependOnUpWrapperStrategyMapper getDependWrapperStrategyMapper(); - - /** - * 对必须完成的(must的)Wrapper的依赖响应策略。 - * 这是一个不得不向历史妥协的属性。用于适配must开关方式。 - * - * @return 该值允许为null - * @deprecated 不推荐使用,很有可能被遗弃 - */ - @SuppressWarnings("DeprecatedIsStillUsed") - @Deprecated - default DependMustStrategyMapper getDependMustStrategyMapper() { - return null; - } - - /** - * 底层全局策略。 - * - * @return 该值不允许为null - */ - DependenceStrategy getDependenceStrategy(); - - // ========== 这是跳过策略 ========== - - /** - * 跳过策略 - * - * @return 不允许为null - */ - SkipStrategy getSkipStrategy(); - - @Override - default DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper) { - // 如果存在依赖,则调用三层依赖响应策略进行判断 - - DependenceStrategy strategy = getDependWrapperStrategyMapper(); - if (getDependMustStrategyMapper() != null) { - strategy = strategy == null ? getDependMustStrategyMapper() : strategy.thenJudge(getDependenceStrategy()); - } - if (getDependenceStrategy() != null) { - strategy = strategy == null ? getDependenceStrategy() : strategy.thenJudge(getDependenceStrategy()); - } - if (strategy == null) { - throw new IllegalStateException("配置无效,三层判断策略均为null,请开发者检查自己的Builder是否逻辑错误!"); - } - return strategy.judgeAction(dependWrappers, thisWrapper, fromWrapper); - } - - @Override - default boolean shouldSkip(Set> nextWrappers, WorkerWrapper thisWrapper, WorkerWrapper fromWrapper) { - return getSkipStrategy() != null && getSkipStrategy().shouldSkip(nextWrappers, thisWrapper, fromWrapper); - } - - default void setDependWrapperStrategyMapper(DependOnUpWrapperStrategyMapper dependOnUpWrapperStrategyMapper) { - throw new UnsupportedOperationException(); - } - - default void setDependMustStrategyMapper(DependMustStrategyMapper dependMustStrategyMapper) { - throw new UnsupportedOperationException(); - } - - default void setDependenceStrategy(DependenceStrategy dependenceStrategy) { - throw new UnsupportedOperationException(); - } - - default void setSkipStrategy(SkipStrategy skipStrategy) { - throw new UnsupportedOperationException(); - } - - /** - * 抽象策略器,实现了toString - */ - abstract class AbstractWrapperStrategy implements WrapperStrategy { - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(128) - .append(this.getClass().getSimpleName()).append('{'); - final AtomicBoolean needAppendSplit = new AtomicBoolean(); - appendNotNullProperty(sb, "dependWrapperStrategyMapper=", - getDependWrapperStrategyMapper(), needAppendSplit, ", "); - appendNotNullProperty(sb, "dependMustStrategyMapper=", - getDependMustStrategyMapper(), needAppendSplit, ", "); - appendNotNullProperty(sb, "dependenceStrategy=", - getDependenceStrategy(), needAppendSplit, ", "); - appendNotNullProperty(sb, "skipStrategy=", - getSkipStrategy(), needAppendSplit, ", "); - return sb.append('}').toString(); - } - - private static void appendNotNullProperty(StringBuilder sb, - String propPrefix, - Object prop, - AtomicBoolean needAppendSplit, - @SuppressWarnings("SameParameterValue") String split) { - if (prop == null) { - return; - } - if (needAppendSplit.get()) { - sb.append(split); - } - sb.append(propPrefix).append(prop); - needAppendSplit.set(true); - } - } - - /** - * 默认策略器,用默认值实现了所有属性。 - */ - class DefaultWrapperStrategy extends AbstractWrapperStrategy { - @Override - public DependOnUpWrapperStrategyMapper getDependWrapperStrategyMapper() { - return null; - } - - @SuppressWarnings("deprecation") - @Override - public DependMustStrategyMapper getDependMustStrategyMapper() { - return null; - } - - @Override - public DependenceStrategy getDependenceStrategy() { - return DependenceStrategy.ALL_DEPENDENCIES_ALL_SUCCESS; - } - - @Override - public SkipStrategy getSkipStrategy() { - return SkipStrategy.CHECK_ONE_LEVEL; - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependMustStrategyMapper.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependMustStrategyMapper.java deleted file mode 100644 index 3eb19deb..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependMustStrategyMapper.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.zmops.iot.async.wrapper.strategy.depend; - -import com.zmops.iot.async.worker.ResultState; -import com.zmops.iot.async.wrapper.WorkerWrapper; - -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * 这是一个“向历史妥协”的策略器。以兼容must开关模式。 - * - * @author create by TcSnZh on 2021/5/4-下午1:24 - */ -@SuppressWarnings("UnusedReturnValue") -public class DependMustStrategyMapper implements DependenceStrategy { - - private final Set> mustDependSet = new LinkedHashSet<>(); - - /** - * 在{@link #mustDependSet} 中的must依赖。 - *

- * 如果{@code mustDependSet == null || mustDependSet.size() < 1},返回{@link DependenceAction#JUDGE_BY_AFTER} - *

- * 如果所有的Wrapper已经完成,本Wrapper将会开始工作。 - *

- * 如果任一{@link #mustDependSet}中的Wrapper失败,则返回{@link DependenceAction#FAST_FAIL}。 - * 具体超时/异常则根据{@link ResultState}的值进行判断。 - *

- * 如果存在Wrapper未完成 且 所有的Wrapper都未失败,则返回{@link DependenceAction#JUDGE_BY_AFTER}。 - *

- */ - @Override - public DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper) { - if (mustDependSet.size() < 1) { - return DependenceAction.JUDGE_BY_AFTER.emptyProperty(); - } - boolean allSuccess = true; - for (WorkerWrapper wrapper : mustDependSet) { - switch (wrapper.getWorkResult().getResultState()) { - case TIMEOUT: - return DependenceAction.FAST_FAIL.fastFailException(ResultState.TIMEOUT, null); - case EXCEPTION: - return DependenceAction.FAST_FAIL.fastFailException(ResultState.EXCEPTION, wrapper.getWorkResult().getEx()); - case DEFAULT: - allSuccess = false; - case SUCCESS: - default: - } - } - if (allSuccess) { - return DependenceAction.START_WORK.emptyProperty(); - } - return DependenceAction.JUDGE_BY_AFTER.emptyProperty(); - } - - /** - * 新增must依赖。 - * - * @param mustDependWrapper WorkerWrapper - * @return 返回自身 - */ - public DependMustStrategyMapper addDependMust(WorkerWrapper mustDependWrapper) { - if (mustDependWrapper == null) { - return this; - } - mustDependSet.add(mustDependWrapper); - return this; - } - - public DependMustStrategyMapper addDependMust(Collection> wrappers) { - if (wrappers == null) { - return this; - } - mustDependSet.addAll(wrappers); - return this; - } - - public DependMustStrategyMapper addDependMust(WorkerWrapper... wrappers) { - if (wrappers == null) { - return this; - } - return addDependMust(Arrays.asList(wrappers)); - } - - public Set> getMustDependSet() { - return mustDependSet; - } - - @Override - public String toString() { - return "DependMustStrategyMapper{" + - "mustDependSet::getId=" + mustDependSet.stream().map(WorkerWrapper::getId).collect(Collectors.toList()) + - '}'; - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependOnUpWrapperStrategy.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependOnUpWrapperStrategy.java deleted file mode 100644 index f9ad807e..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependOnUpWrapperStrategy.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.zmops.iot.async.wrapper.strategy.depend; - -import com.zmops.iot.async.wrapper.WorkerWrapper; - -/** - * 由上游wrapper决定本wrapper行为的单参数策略。 - * - * @author create by TcSnZh on 2021/5/1-下午11:16 - */ -@FunctionalInterface -public interface DependOnUpWrapperStrategy { - /** - * 仅使用一个参数(即调用自身的上游wrapper)的判断方法 - * - * @param fromWrapper 调用本Wrapper的上游Wrapper - * @return 返回 {@link DependenceAction.WithProperty} - */ - DependenceAction.WithProperty judge(WorkerWrapper fromWrapper); - - // ========== 送几个供链式调用的默认值 ========== - - /** - * 成功时,交给下一个策略器判断。 - * 未运行时,休息。 - * 失败时,失败。 - */ - DependOnUpWrapperStrategy SUCCESS_CONTINUE = new DependOnUpWrapperStrategy() { - @Override - public DependenceAction.WithProperty judge(WorkerWrapper ww) { - switch (ww.getWorkResult().getResultState()) { - case SUCCESS: - return DependenceAction.JUDGE_BY_AFTER.emptyProperty(); - case DEFAULT: - return DependenceAction.TAKE_REST.emptyProperty(); - case EXCEPTION: - case TIMEOUT: - return DependenceAction.FAST_FAIL.fastFailException(ww.getWorkResult().getResultState(), ww.getWorkResult().getEx()); - default: - } - throw new RuntimeException("不该执行到的代码 workResult.getResultState()=" + ww.getWorkResult().getResultState()); - } - - @Override - public String toString() { - return "SUCCESS_CONTINUE"; - } - }; - /** - * 成功时,开始工作。 - * 未运行时,交给下一个策略器判断。 - * 失败时,失败。 - */ - DependOnUpWrapperStrategy SUCCESS_START_INIT_CONTINUE = new DependOnUpWrapperStrategy() { - @Override - public DependenceAction.WithProperty judge(WorkerWrapper ww) { - switch (ww.getWorkResult().getResultState()) { - case SUCCESS: - return DependenceAction.START_WORK.emptyProperty(); - case DEFAULT: - return DependenceAction.JUDGE_BY_AFTER.emptyProperty(); - case EXCEPTION: - case TIMEOUT: - return DependenceAction.FAST_FAIL.fastFailException(ww.getWorkResult().getResultState(), ww.getWorkResult().getEx()); - default: - } - throw new RuntimeException("不该执行到的代码 workResult.getResultState()=" + ww.getWorkResult().getResultState()); - } - - @Override - public String toString() { - return "SUCCESS_START_INIT_CONTINUE"; - } - }; -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependOnUpWrapperStrategyMapper.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependOnUpWrapperStrategyMapper.java deleted file mode 100644 index 2b0740f0..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependOnUpWrapperStrategyMapper.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.zmops.iot.async.wrapper.strategy.depend; - - -import com.zmops.iot.async.wrapper.WorkerWrapper; - -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 对不同的{@link WorkerWrapper}调用者实行个性化依赖响应策略。 - *

- * 使用{@link DependOnUpWrapperStrategyMapper}本实现类对{@link DependenceStrategy}进行增强, - * - * @author create by TcSnZh on 2021/5/1-下午11:12 - */ -public class DependOnUpWrapperStrategyMapper implements DependenceStrategy { - private final Map, DependOnUpWrapperStrategy> mapper = new ConcurrentHashMap<>(4); - - /** - * 设置对应策略 - * - * @param targetWrapper 要设置策略的WorkerWrapper - * @param strategy 要设置的策略 - * @return 返回this,链式调用。 - */ - @SuppressWarnings("UnusedReturnValue") - public DependOnUpWrapperStrategyMapper putMapping(WorkerWrapper targetWrapper, DependOnUpWrapperStrategy strategy) { - mapper.put(targetWrapper, strategy); - return this; - } - - /** - * 判断方法。 - *

- * 如果fromWrapper在{@link #mapper}中,则返回{@link DependOnUpWrapperStrategy}的判断返回值。否则返回{@link DependenceAction#JUDGE_BY_AFTER} - * - * @param dependWrappers (这里不会使用该值)thisWrapper.dependWrappers的属性值。 - * @param thisWrapper (这里不会使用该值)thisWrapper,即为“被催促”的WorkerWrapper - * @param fromWrapper 调用来源Wrapper。 - * @return 如果在mapper中有对fromWrapper的处理策略,则使用其进行判断。否则返回JUDGE_BY_AFTER交给下一个进行判断。 - */ - @Override - public DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper) { - DependOnUpWrapperStrategy strategy = mapper.get(fromWrapper); - if (strategy == null) { - return DependenceAction.JUDGE_BY_AFTER.emptyProperty(); - } - return strategy.judge(fromWrapper); - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(64) - .append(this.getClass().getSimpleName()).append("{mapper="); - final Set, DependOnUpWrapperStrategy>> entrySet = mapper.entrySet(); - entrySet.forEach(entry -> { - sb.append(entry.getKey().getId()).append(':').append(entry.getValue()).append(", "); - }); - if (entrySet.size() > 0) { - final int length = sb.length(); - sb.delete(length - 2, length); - } - return sb.append('}').toString(); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceAction.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceAction.java deleted file mode 100644 index 211e17f7..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceAction.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.zmops.iot.async.wrapper.strategy.depend; - -import com.zmops.iot.async.worker.ResultState; - -/** - * 返回执行工作类型的枚举。 - * - * @author create by TcSnZh on 2021/5/1-下午10:47 - */ -public enum DependenceAction { - /** - * 开始工作。WorkerWrapper会执行工作方法。 - */ - START_WORK, - /** - * 还没轮到,休息一下。WorkerWrapper中的调用栈会返回,以等待其他上游wrapper调用它,或是会一生无缘被调用。 - */ - TAKE_REST, - /** - * 立即失败。WorkerWrapper会去执行快速失败的方法。 - */ - FAST_FAIL, - /** - * 交给下层{@link DependenceStrategy}进行判断。 - * 由于{@link DependenceStrategy#thenJudge(DependenceStrategy)}的责任链设计模式,该返回值的意义就是调用责任链上下一个策略。 - *

- * 在WorkerWrapper中不需要考虑此值,因为配置正常的情况下不会返回这个值。 - */ - JUDGE_BY_AFTER; - - // 空值单例 - - public WithProperty emptyProperty() { - if (this == FAST_FAIL) { - throw new UnsupportedOperationException( - "配置错误: FAST_FAIL 不能使用该方法,请使用fastFailException(ResultState, Exception)具体设置fastFail的参数。"); - } - return empty; - } - - private final WithProperty empty = new WithProperty() { - @Override - public void setResultState(ResultState resultState) { - throw new UnsupportedOperationException("empty not support modify"); - } - - @Override - public void setFastFailException(Exception fastFailException) { - throw new UnsupportedOperationException("empty not support modify"); - } - - private final String toString = getDependenceAction() + ".empty"; - - @Override - public String toString() { - return toString; - } - }; - - // 携带异常信息、ResultState的返回值 - - public WithProperty fastFailException(ResultState resultState, Exception e) { - WithProperty withProperty = this.new WithProperty(); - withProperty.setResultState(resultState); - withProperty.setFastFailException(e); - return withProperty; - } - - /** - * 有时需要封装一些参数来返回,则使用本内部类进行返回。 - *

- * 所有的构造方法权限均为private,请在父枚举类{@link DependenceAction}的方法中选择合适的模板生成内部类WithProperty。 - */ - public class WithProperty { - /** - * 以下两个属性用于设置fastFail的属性 - */ - private ResultState resultState; - private Exception fastFailException; - - // getter setter - - public ResultState getResultState() { - return resultState; - } - - public void setResultState(ResultState resultState) { - this.resultState = resultState; - } - - public Exception getFastFailException() { - return fastFailException; - } - - public void setFastFailException(Exception fastFailException) { - this.fastFailException = fastFailException; - } - - public DependenceAction getDependenceAction() { - return DependenceAction.this; - } - - // constructor always private. - - private WithProperty() { - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceStrategy.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceStrategy.java deleted file mode 100644 index f60a40a5..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceStrategy.java +++ /dev/null @@ -1,270 +0,0 @@ -package com.zmops.iot.async.wrapper.strategy.depend; - -import com.zmops.iot.async.worker.ResultState; -import com.zmops.iot.async.worker.WorkResult; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.async.wrapper.WorkerWrapperGroup; - -import java.util.Collections; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.stream.Collectors; - -/** - * 依赖策略接口。 - *

- * 提供了多个默认值可以作为单例模式使用。 - *

- * 工作原理示例: - *

- * ==== 一个简单示例 ==== - * 现有三个WorkerWrapper:A、B、C,其中 {@code A{dependWrappers=[B,C],} } - * 当B执行完成后调用A时,根据依赖关系ALL_DEPENDENCIES_ALL_SUCCESS,还需等待C的结果。 - * 然后,当C执行完成后调用A时,根据依赖关系ALL_DEPENDENCIES_ALL_SUCCESS: 此时如果C成功了,A就开工,此时如果C失败了,A就失败。 - * ==== 简单示例2 ==== - * - *

- * - * @author create by TcSnZh on 2021/5/1-下午10:48 - */ -@FunctionalInterface -public interface DependenceStrategy { - /** - * 核心判断策略 - * - * @param dependWrappers thisWrapper.dependWrappers的属性值。 - * @param thisWrapper thisWrapper,即为“被催促”的WorkerWrapper - * @param fromWrapper 调用来源Wrapper。 - *

- * 该参数不会为null。 - * 因为在{@link WorkerWrapper#work(ExecutorService, long, WorkerWrapperGroup)}方法中传入的的第一批无依赖的Wrapper, - * 不会被该策略器所判断,而是不论如何直接执行。 - *

- * @return 返回枚举值内部类,WorkerWrapper将会根据其值来决定自己如何响应这次调用。 {@link DependenceAction.WithProperty} - */ - DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper); - - /** - * 如果本策略器的judge方法返回了JUDGE_BY_AFTER,则交给下一个策略器来判断。 - * - * @param after 下层策略器 - * @return 返回一个“封装的多层策略器” - */ - default DependenceStrategy thenJudge(DependenceStrategy after) { - DependenceStrategy that = this; - return new DependenceStrategy() { - @Override - public DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper) { - DependenceAction.WithProperty judge = that.judgeAction(dependWrappers, thisWrapper, fromWrapper); - if (judge.getDependenceAction() == DependenceAction.JUDGE_BY_AFTER) { - return after.judgeAction(dependWrappers, thisWrapper, fromWrapper); - } - return judge; - } - - @Override - public String toString() { - return that + " ----> " + after; - } - }; - } - - // ========== 以下是一些默认实现 ========== - - /** - * 被依赖的所有Wrapper都必须成功才能开始工作。 - * 如果其中任一Wrapper还没有执行且不存在失败,则休息。 - * 如果其中任一Wrapper失败则立即失败。 - */ - DependenceStrategy ALL_DEPENDENCIES_ALL_SUCCESS = new DependenceStrategy() { - @Override - public DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper) { - boolean hasWaiting = false; - for (final WorkerWrapper dependWrapper : dependWrappers) { - WorkResult workResult = dependWrapper.getWorkResult(); - switch (workResult.getResultState()) { - case DEFAULT: - hasWaiting = true; - break; - case SUCCESS: - break; - case TIMEOUT: - case EXCEPTION: - return DependenceAction.FAST_FAIL.fastFailException(workResult.getResultState(), workResult.getEx()); - default: - throw new RuntimeException("不该执行到的代码 workResult.getResultState()=" + workResult.getResultState()); - } - } - if (hasWaiting) { - return DependenceAction.TAKE_REST.emptyProperty(); - } - return DependenceAction.START_WORK.emptyProperty(); - } - - @Override - public String toString() { - return "ALL_DEPENDENCIES_ALL_SUCCESS"; - } - }; - - /** - * 被依赖的Wrapper中任意一个成功了就可以开始工作。 - * 如果其中所有Wrapper还没有执行,则休息。 - * 如果其中一个Wrapper失败且不存在成功则立即失败。 - */ - DependenceStrategy ALL_DEPENDENCIES_ANY_SUCCESS = new DependenceStrategy() { - @Override - public DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper) { - boolean hasFailed = false; - Exception fastFailException = null; - ResultState resultState = null; - for (final WorkerWrapper dependWrapper : dependWrappers) { - WorkResult workResult = dependWrapper.getWorkResult(); - switch (workResult.getResultState()) { - case DEFAULT: - break; - case SUCCESS: - return DependenceAction.START_WORK.emptyProperty(); - case TIMEOUT: - case EXCEPTION: - resultState = !hasFailed ? workResult.getResultState() : resultState; - fastFailException = !hasFailed ? workResult.getEx() : fastFailException; - // 跳过不算失败 - hasFailed = true; - break; - default: - throw new RuntimeException("不该执行到的代码 workResult.getResultState()=" + workResult.getResultState()); - } - } - if (hasFailed) { - return DependenceAction.FAST_FAIL.fastFailException(resultState, fastFailException); - } - return DependenceAction.TAKE_REST.emptyProperty(); - } - - @Override - public String toString() { - return "ALL_DEPENDENCIES_ANY_SUCCESS"; - } - }; - - /** - * 如果被依赖的工作中任一失败,则立即失败。 - * 否则就开始工作(不论之前的工作有没有开始)。 - */ - @SuppressWarnings("unused") - DependenceStrategy ALL_DEPENDENCIES_NONE_FAILED = new DependenceStrategy() { - @Override - public DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper) { - for (WorkerWrapper dependWrapper : dependWrappers) { - WorkResult workResult = dependWrapper.getWorkResult(); - switch (workResult.getResultState()) { - case TIMEOUT: - case EXCEPTION: - return DependenceAction.FAST_FAIL.fastFailException(workResult.getResultState(), workResult.getEx()); - default: - } - } - return DependenceAction.START_WORK.emptyProperty(); - } - - @Override - public String toString() { - return "ALL_DEPENDENCIES_NONE_FAILED"; - } - }; - - /** - * 只有当指定的这些Wrapper都成功时,才会开始工作。 - * 任一失败会快速失败。 - * 任一还没有执行且不存在失败,则休息。 - * - * @param theseWrapper 该方法唯一有效参数。 - * @return 返回生成的 {@link DependenceAction.WithProperty) - */ - @SuppressWarnings("unused") - static DependenceStrategy theseWrapperAllSuccess(Set> theseWrapper) { - return new DependenceStrategy() { - private final Set> theseWrappers; - private final String toString; - - { - theseWrappers = Collections.unmodifiableSet(theseWrapper); - toString = "THESE_WRAPPER_MUST_SUCCESS:" + theseWrappers.stream().map(WorkerWrapper::getId).collect(Collectors.toList()); - } - - @Override - public DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper) { - boolean hasWaiting = false; - for (WorkerWrapper wrapper : theseWrappers) { - ResultState resultState = wrapper.getWorkResult().getResultState(); - switch (resultState) { - case DEFAULT: - hasWaiting = true; - break; - case SUCCESS: - break; - case TIMEOUT: - case EXCEPTION: - return DependenceAction.FAST_FAIL.fastFailException(resultState, wrapper.getWorkResult().getEx()); - default: - throw new RuntimeException("不该执行到的代码 workResult.getResultState()=" + resultState); - } - } - if (hasWaiting) { - return DependenceAction.TAKE_REST.emptyProperty(); - } - return DependenceAction.START_WORK.emptyProperty(); - } - - - @Override - public String toString() { - return toString; - } - }; - } - - /** - * 此值用于适配v1.4及之前的must开关模式, - * 当`wrapperStrategy`的`dependMustStrategyMapper`的`mustDependSet`不为空时, - * 则休息(因为能判断到这个责任链说明set中存在不满足的值L)。 - * 为空时,则任一成功则执行。 - * - * @deprecated 不推荐使用must开关 - */ - @SuppressWarnings("DeprecatedIsStillUsed") - @Deprecated - DependenceStrategy IF_MUST_SET_NOT_EMPTY_ALL_SUCCESS_ELSE_ANY = new DependenceStrategy() { - @Override - public DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper) { - DependMustStrategyMapper mustMapper = thisWrapper.getWrapperStrategy().getDependMustStrategyMapper(); - if (mustMapper != null && !mustMapper.getMustDependSet().isEmpty()) { - // 至少有一个must,则因为must未完全完成而等待。 - return DependenceAction.TAKE_REST.emptyProperty(); - } - // 如果一个must也没有,则认为应该是ANY模式。 - return DependenceStrategy.ALL_DEPENDENCIES_ANY_SUCCESS.judgeAction(dependWrappers, thisWrapper, fromWrapper); - } - - @Override - public String toString() { - return "IF_MUST_SET_NOT_EMPTY_ALL_SUCCESS_ELSE_ANY"; - } - }; - -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/skip/SkipStrategy.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/skip/SkipStrategy.java deleted file mode 100644 index 72fef2cf..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/skip/SkipStrategy.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.zmops.iot.async.wrapper.strategy.skip; - - -import com.zmops.iot.async.wrapper.WorkerWrapper; - -import java.util.Set; - -/** - * @author create by TcSnZh on 2021/5/6-下午3:02 - */ -@FunctionalInterface -public interface SkipStrategy { - /** - * 跳过策略函数。返回true将会使WorkerWrapper跳过执行。 - * - * @param nextWrappers 下游WrapperSet - * @param thisWrapper 本WorkerWrapper - * @param fromWrapper 呼叫本Wrapper的上游Wrapper - * @return 返回true将会使WorkerWrapper跳过执行。 - */ - boolean shouldSkip(Set> nextWrappers, WorkerWrapper thisWrapper, WorkerWrapper fromWrapper); - - /** - * 不跳过 - */ - SkipStrategy NOT_SKIP = new SkipStrategy() { - @Override - public boolean shouldSkip(Set> nextWrappers, WorkerWrapper thisWrapper, WorkerWrapper fromWrapper) { - return false; - } - - @Override - public String toString() { - return "NOT_SKIP"; - } - }; - - /** - * 距离为1的wrapper都不在初始化状态 - */ - SkipStrategy CHECK_ONE_LEVEL = new SkipStrategy() { - - @Override - public boolean shouldSkip(Set> nextWrappers, WorkerWrapper thisWrapper, WorkerWrapper fromWrapper) { - return nextWrappers != null && !nextWrappers.isEmpty() - && nextWrappers.stream().allMatch(workerWrapper -> workerWrapper.getState().finished()); - } - - @Override - public String toString() { - return "CHECK_ONE_LEVEL"; - } - }; -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 50f9aa6a..aebd39ee 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -31,6 +31,7 @@ import org.springframework.stereotype.Service; import java.util.*; +import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; /** @@ -241,42 +242,42 @@ private StringBuilder generateBaseSql() { */ public String create(DeviceDto deviceDto) { - WorkerWrapper saveTagWork = WorkerWrapper.builder().id("saveTagWork") + WorkerWrapper saveTagWork = new WorkerWrapper.Builder().id("saveTagWork") .worker(saveTagWorker).param(deviceDto).build(); - WorkerWrapper saveAttributeWork = WorkerWrapper.builder().id("saveAttributeWork") + WorkerWrapper saveAttributeWork = new WorkerWrapper.Builder().id("saveAttributeWork") .worker(saveAttributeWorker).param(deviceDto).build(); - WorkerWrapper saveDeviceGrpWork = WorkerWrapper.builder().id("saveDeviceGrpWork") + WorkerWrapper saveDeviceGrpWork = new WorkerWrapper.Builder().id("saveDeviceGrpWork") .worker(saveDeviceGrpWorker).param(deviceDto) .build(); - WorkerWrapper updateAttrZbxIdWork = WorkerWrapper.builder().id("updateAttrZbxIdWork") + WorkerWrapper updateAttrZbxIdWork = new WorkerWrapper.Builder().id("updateAttrZbxIdWork") .worker(updateAttrZbxIdWorker).param(deviceDto) .build(); - WorkerWrapper updateDeviceZbxIdWork = WorkerWrapper.builder().id("updateDeviceZbxIdWork") + WorkerWrapper updateDeviceZbxIdWork = new WorkerWrapper.Builder().id("updateDeviceZbxIdWork") .worker(updateDeviceZbxIdWorker) .build(); - WorkerWrapper saveOtherWork = WorkerWrapper.builder().id("saveOtherWork") + WorkerWrapper saveOtherWork = new WorkerWrapper.Builder().id("saveOtherWork") .worker(saveOtherWorker).param(deviceDto) .build(); - WorkerWrapper saveZbxHostWork = WorkerWrapper.builder().id("saveZbxHostWork") + WorkerWrapper saveZbxHostWork = new WorkerWrapper.Builder().id("saveZbxHostWork") .worker(saveZbxHostWorker).param(deviceDto) - .nextOf(updateAttrZbxIdWork, updateDeviceZbxIdWork, saveOtherWork) + .next(updateAttrZbxIdWork, updateDeviceZbxIdWork, saveOtherWork) .build(); - WorkerWrapper deviceWork = WorkerWrapper.builder().id("saveDvice") + WorkerWrapper deviceWork = new WorkerWrapper.Builder().id("saveDvice") .worker(saveDeviceWorker).param(deviceDto) - .nextOf(saveTagWork, saveAttributeWork, saveDeviceGrpWork, saveZbxHostWork) + .next(saveTagWork, saveAttributeWork, saveDeviceGrpWork, saveZbxHostWork) .build(); try { - Async.work(10000, deviceWork).awaitFinish(); - } catch (Exception e) { + Async.beginWork(10000, deviceWork); + } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } updateDeviceNameCache(deviceDto.getDeviceId(), deviceDto.getName()); @@ -297,38 +298,38 @@ public String update(DeviceDto deviceDto) { deviceDto.setOldProductId(device.getProductId()); deviceDto.setZbxId(device.getZbxId()); - WorkerWrapper saveTagWork = WorkerWrapper.builder().id("saveTagWork") + WorkerWrapper saveTagWork = new WorkerWrapper.Builder().id("saveTagWork") .worker(saveTagWorker).param(deviceDto).build(); - WorkerWrapper saveAttributeWork = WorkerWrapper.builder().id("saveAttributeWork") + WorkerWrapper saveAttributeWork = new WorkerWrapper.Builder().id("saveAttributeWork") .worker(saveAttributeWorker).param(deviceDto).build(); - WorkerWrapper saveDeviceGrpWork = WorkerWrapper.builder().id("saveDeviceGrpWork") + WorkerWrapper saveDeviceGrpWork = new WorkerWrapper.Builder().id("saveDeviceGrpWork") .worker(saveDeviceGrpWorker).param(deviceDto) .build(); - WorkerWrapper updateAttrZbxIdWork = WorkerWrapper.builder().id("updateAttrZbxIdWork") + WorkerWrapper updateAttrZbxIdWork = new WorkerWrapper.Builder().id("updateAttrZbxIdWork") .worker(updateAttrZbxIdWorker) .build(); - WorkerWrapper saveOtherWork = WorkerWrapper.builder().id("saveOtherWork") + WorkerWrapper saveOtherWork = new WorkerWrapper.Builder().id("saveOtherWork") .worker(saveOtherWorker).param(deviceDto) .build(); - WorkerWrapper saveZbxHostWork = WorkerWrapper.builder().id("saveZbxHostWork") + WorkerWrapper saveZbxHostWork = new WorkerWrapper.Builder().id("saveZbxHostWork") .worker(saveZbxHostWorker).param(deviceDto) - .nextOf(updateAttrZbxIdWork, saveOtherWork) + .next(updateAttrZbxIdWork, saveOtherWork) .build(); - WorkerWrapper deviceWork = WorkerWrapper.builder().id("saveDvice") + WorkerWrapper deviceWork = new WorkerWrapper.Builder().id("saveDvice") .worker(saveDeviceWorker).param(deviceDto) - .nextOf(saveTagWork, saveAttributeWork, saveDeviceGrpWork, saveZbxHostWork) + .next(saveTagWork, saveAttributeWork, saveDeviceGrpWork, saveZbxHostWork) .build(); try { - Async.work(10000, deviceWork).awaitFinish(); - } catch (Exception e) { + Async.beginWork(10000, deviceWork); + } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } updateDeviceNameCache(deviceDto.getDeviceId(), deviceDto.getName()); @@ -354,25 +355,25 @@ public String delete(DeviceDto deviceDto) { return deviceDto.getDeviceId(); } String zbxId = device.getZbxId(); - WorkerWrapper delTagWork = WorkerWrapper.builder().id("delTagWork") + WorkerWrapper delTagWork = new WorkerWrapper.Builder().id("delTagWork") .worker((deviceId, allWrappers) -> { new QTag().sid.eq(deviceId).delete(); return true; }).param(deviceDto.getDeviceId()).build(); - WorkerWrapper delAttrWork = WorkerWrapper.builder().id("delAttrWork") + WorkerWrapper delAttrWork = new WorkerWrapper.Builder().id("delAttrWork") .worker((deviceId, allWrappers) -> { new QProductAttribute().productId.eq(deviceId).delete(); return true; }).param(deviceDto.getDeviceId()).build(); - WorkerWrapper delGropusWork = WorkerWrapper.builder().id("delGropusWork") + WorkerWrapper delGropusWork = new WorkerWrapper.Builder().id("delGropusWork") .worker((deviceId, allWrappers) -> { new QDevicesGroups().deviceId.eq(deviceId).delete(); return true; }).param(deviceDto.getDeviceId()).build(); - WorkerWrapper delZbxWork = WorkerWrapper.builder().id("delZbxWork") + WorkerWrapper delZbxWork = new WorkerWrapper.Builder().id("delZbxWork") .worker((zbxid, allWrappers) -> { if (ToolUtil.isNotEmpty(zbxid)) { JSONArray jsonArray = JSONObject.parseArray(zbxHost.hostDetail(zbxId)); @@ -383,7 +384,7 @@ public String delete(DeviceDto deviceDto) { return true; }).param(zbxId).build(); - WorkerWrapper delOtherWork = WorkerWrapper.builder().id("delOtherWork") + WorkerWrapper delOtherWork = new WorkerWrapper.Builder().id("delOtherWork") .worker((deviceId, allWrappers) -> { new QProductStatusFunctionRelation().relationId.eq(deviceId).delete(); new QProductServiceRelation().relationId.eq(deviceId).delete(); @@ -392,17 +393,19 @@ public String delete(DeviceDto deviceDto) { return true; }).param(deviceDto.getDeviceId()).build(); - WorkerWrapper delDeviceWork = WorkerWrapper.builder().id("delDeviceWork") + WorkerWrapper delDeviceWork = new WorkerWrapper.Builder() + .id("delDeviceWork") .worker((deviceId, allWrappers) -> { new QDevice().deviceId.eq(deviceId).delete(); return true; - }).param(deviceDto.getDeviceId()) - .nextOf(delTagWork, delAttrWork, delGropusWork, delZbxWork, delOtherWork).build(); + }) + .param(deviceDto.getDeviceId()) + .next(delTagWork, delAttrWork, delGropusWork, delZbxWork, delOtherWork).build(); try { - Async.work(5000, delDeviceWork).awaitFinish(); - } catch (Exception e) { + Async.beginWork(5000, delDeviceWork); + } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index aa7d0907..cc2fa7cd 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -37,6 +37,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; /** @@ -68,11 +69,10 @@ public List list(MultipleDeviceEventParm eventParm) { if (ToolUtil.isNotEmpty(eventParm.getEventRuleName())) { query.eventRuleName.contains(eventParm.getEventRuleName()); } - query.classify.eq(EVENT_CLASSIFY); - List list = query.orderBy(" create_time desc").asDto(MultipleDeviceEventDto.class).findList(); + query.classify.eq(EVENT_CLASSIFY); - return list; + return query.orderBy(" create_time desc").asDto(MultipleDeviceEventDto.class).findList(); } /** @@ -125,7 +125,9 @@ public Pager getEventByPage(MultipleDeviceEventParm even " ps.event_rule_id IN (:eventRuleIds) " + "GROUP BY " + " ps.event_rule_id"; + List deviceServiceDtos = DB.findDto(MultipleDeviceServiceDto.class, sql).setParameter("eventRuleIds", eventRuleIds).findList(); + Map deviceServiceMap = deviceServiceDtos.parallelStream() .collect(Collectors.toConcurrentMap(MultipleDeviceServiceDto::getEventRuleId, o -> o)); @@ -176,7 +178,7 @@ public void createDeviceEventRule(Long eventRuleId, MultipleDeviceEventRule even if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { eventRule.getDeviceServices().forEach(i -> { DB.sqlUpdate("insert into product_event_service(event_rule_id, execute_device_id, service_id) " + - "values (:eventRuleId, :executeDeviceId, :serviceId)") + "values (:eventRuleId, :executeDeviceId, :serviceId)") .setParameter("eventRuleId", eventRuleId) .setParameter("executeDeviceId", i.getExecuteDeviceId()) .setParameter("serviceId", i.getServiceId()) @@ -370,16 +372,16 @@ public void execute(Long eventRuleId, String type, Long userId) { alarmInfo.put("triggerUser", userId); } - WorkerWrapper, Boolean> deviceServiceLogWork = WorkerWrapper., Boolean>builder().id("deviceServiceLogWorker") + WorkerWrapper, Boolean> deviceServiceLogWork = new WorkerWrapper.Builder, Boolean>().id("deviceServiceLogWorker") .worker(deviceServiceLogWorker).param(alarmInfo) .build(); - WorkerWrapper, Boolean> scenesLogWork = WorkerWrapper., Boolean>builder().id("scenesLogWorker") + WorkerWrapper, Boolean> scenesLogWork = new WorkerWrapper.Builder, Boolean>().id("scenesLogWorker") .worker(scenesLogWorker).param(alarmInfo) .build(); try { - Async.work(1000, deviceServiceLogWork, scenesLogWork).awaitFinish(); - } catch (Exception e) { + Async.beginWork(1000, deviceServiceLogWork, scenesLogWork); + } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } @@ -417,8 +419,8 @@ static class TriggerIds { @Data public static class Triggers { - private String triggerid; - private String description; + private String triggerid; + private String description; private List hosts; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceEventLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceEventLogWorker.java index a95f0109..adcffb48 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceEventLogWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceEventLogWorker.java @@ -20,11 +20,12 @@ @Component public class DeviceEventLogWorker implements IWorker, Boolean> { + @Override - public Boolean action(Map param, Map> allWrappers) { + public Boolean action(Map object, Map allWrappers) { log.debug("insert into event log…………"); - String deviceId = param.get("hostname"); + String deviceId = object.get("hostname"); if (ToolUtil.isEmpty(deviceId)) { return false; } @@ -33,7 +34,6 @@ public Boolean action(Map param, Map return false; } - return true; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java index 95a363eb..a014a70d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java @@ -33,7 +33,7 @@ public class DeviceServiceLogWorker implements IWorker, Boolean> { @Override - public Boolean action(Map param, Map> allWrappers) { + public Boolean action(Map param, Map allWrappers) { log.debug("insert into service log…………"); long eventRuleId = (long) param.get("eventRuleId"); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java index ad90fdbc..5f50ea17 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java @@ -32,7 +32,7 @@ public class SaveAttributeWorker implements IWorker { private static final String ATTR_TYPE_RELY = "18"; @Override - public Boolean action(DeviceDto deviceDto, Map> map) { + public Boolean action(DeviceDto deviceDto, Map map) { log.debug("step 3:saveAttributeWorker----DEVICEID:{}…………",deviceDto.getDeviceId()); String deviceId = deviceDto.getDeviceId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java index e6dc218a..e008993b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java @@ -26,7 +26,7 @@ public class SaveDeviceGrpWorker implements IWorker { @Override - public Boolean action(DeviceDto deviceDto, Map> map) { + public Boolean action(DeviceDto deviceDto, Map map) { log.debug("step 4:SaveDeviceGrpWorker----DEVICEID:{}…………",deviceDto.getDeviceId()); //修改模式 先清空关联关系 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java index 51abbb7c..c42b11d3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java @@ -23,7 +23,7 @@ public class SaveDeviceWorker implements IWorker { @Override - public Device action(DeviceDto deviceDto, Map> allWrappers) { + public Device action(DeviceDto deviceDto, Map allWrappers) { log.debug("step 1:SaveDeviceWorker----DEVICEID:{}…………",deviceDto.getDeviceId()); Device device = new Device(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java index 9e9af6ef..6b600cf3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java @@ -41,7 +41,7 @@ public class SaveOtherWorker implements IWorker { ZbxTrigger zbxTrigger; @Override - public Boolean action(DeviceDto deviceDto, Map> allWrappers) { + public Boolean action(DeviceDto deviceDto, Map allWrappers) { log.debug("step 8:SaveOtherWorker----DEVICEID:{}…………", deviceDto.getDeviceId()); String deviceId = deviceDto.getDeviceId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java index 3a7f2747..d6ec5d51 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java @@ -23,7 +23,7 @@ public class SaveTagWorker implements IWorker { @Override - public Boolean action(DeviceDto deviceDto, Map> allWrappers) { + public Boolean action(DeviceDto deviceDto, Map allWrappers) { log.debug("step 2:SaveTagWorker----DEVICEID:{}…………",deviceDto.getDeviceId()); String deviceId = deviceDto.getDeviceId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java index 780f085c..ab6b2ede 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java @@ -32,7 +32,7 @@ public class SaveZbxHostWorker implements IWorker { ZbxHost zbxHost; @Override - public String action(DeviceDto deviceDto, Map> map) { + public String action(DeviceDto deviceDto, Map map) { log.debug("step 5:SaveZbxHostWorker----DEVICEID:{}…………",deviceDto.getDeviceId()); //设备ID 作为zbx HOST name String host = deviceDto.getDeviceId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java index 6fdd18cc..738268cf 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java @@ -24,7 +24,7 @@ public class ScenesLogWorker implements IWorker, Boolean> { @Override - public Boolean action(Map param, Map> allWrappers) { + public Boolean action(Map param, Map allWrappers) { log.debug("insert into ScenesLogWorker…………"); long eventRuleId = (long) param.get("eventRuleId"); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java index dcb16672..7dfbf73e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java @@ -36,7 +36,7 @@ public class UpdateAttrZbxIdWorker implements IWorker { ZbxItem zbxItem; @Override - public Boolean action(DeviceDto deviceDto, Map> map) { + public Boolean action(DeviceDto deviceDto, Map map) { log.debug("step 6:resolve Attr zbxID async----deviceid: {} …………",deviceDto.getDeviceId()); String deviceId = deviceDto.getDeviceId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java index 811d9709..265d1124 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java @@ -23,7 +23,7 @@ public class UpdateDeviceZbxIdWorker implements IWorker { @Override - public Boolean action(String deviceDto, Map> map) { + public Boolean action(String deviceDto, Map map) { Object result = map.get("saveZbxHostWork").getWorkResult().getResult(); JSONArray hostid = JSONObject.parseObject(result.toString()).getJSONArray("hostids"); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java index ef0c02a6..490c3429 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java @@ -31,7 +31,7 @@ public class UpdateZbxTagWorker implements IWorker { ZbxHost zbxHost; @Override - public Boolean action(DeviceDto deviceDto, Map> map) { + public Boolean action(DeviceDto deviceDto, Map map) { log.debug("UpdateZbxTagWorker……"); //取出 ZBX hostid Object result = map.get("saveZbxHostWork").getWorkResult().getResult(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java index b140ecec..2d8d8e7c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java @@ -22,6 +22,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; /** @@ -48,19 +49,29 @@ public void process(EventDataDto eventData) { alarmInfo.put("relationId", productEventRelationList.get(0).getRelationId()); alarmInfo.put("triggerType", "自动"); - WorkerWrapper, Boolean> deviceServiceLogWork = WorkerWrapper., Boolean>builder().id("deviceServiceLogWorker") - .worker(deviceServiceLogWorker).param(alarmInfo) + WorkerWrapper, Boolean> deviceServiceLogWork = new WorkerWrapper.Builder, Boolean>() + .id("deviceServiceLogWorker") + .worker(deviceServiceLogWorker) + .param(alarmInfo) .build(); + try { - Async.work(1000, deviceServiceLogWork).awaitFinish(); - } catch (Exception e) { + Async.beginWork(1000, deviceServiceLogWork); + } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } - List productEventServiceList = new QProductEventService().eventRuleId.eq(productEventRelationList.get(0).getEventRuleId()) - .or().deviceId.isNull().deviceId.eq(productEventRelationList.get(0).getRelationId()).endOr().findList(); + List productEventServiceList = new QProductEventService() + .eventRuleId.eq(productEventRelationList.get(0).getEventRuleId()) + .or() + .deviceId.isNull() + .deviceId.eq(productEventRelationList.get(0).getRelationId()) + .endOr() + .findList(); + List> list = new ArrayList<>(); - Map> collect = productEventServiceList.parallelStream().collect(Collectors.groupingBy(ProductEventService::getExecuteDeviceId)); + Map> collect = productEventServiceList.parallelStream() + .collect(Collectors.groupingBy(ProductEventService::getExecuteDeviceId)); collect.forEach((key, value) -> { Map map = new ConcurrentHashMap<>(); @@ -73,7 +84,8 @@ public void process(EventDataDto eventData) { List paramList = DefinitionsUtil.getServiceParam(val.getServiceId()); if (ToolUtil.isNotEmpty(paramList)) { - serviceMap.put("param", paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue))); + serviceMap.put("param", paramList.parallelStream() + .collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue))); } serviceList.add(serviceMap); }); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index f1c01db7..a87a88e2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -34,8 +34,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; /** @@ -55,8 +55,8 @@ public class ProductEventTriggerController { @Autowired private ZbxTrigger zbxTrigger; - private static final String ALARM_TAG_NAME = "__alarm__"; - private static final String EXECUTE_TAG_NAME = "__execute__"; + private static final String ALARM_TAG_NAME = "__alarm__"; + private static final String EXECUTE_TAG_NAME = "__execute__"; @Autowired SaveProductEventTriggerWorker saveProductEventTriggerWorker; @@ -136,10 +136,15 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE productEventRuleService.updateProductEventRuleZbxId(eventRuleId, triggerIds); //step 6: 同步到产品下的设备 - WorkerWrapper saveProductEventTriggerWork = WorkerWrapper.builder().worker(saveProductEventTriggerWorker).param(eventRule).build(); + WorkerWrapper saveProductEventTriggerWork = + new WorkerWrapper.Builder().worker(saveProductEventTriggerWorker).param(eventRule).build(); try { - Async.work(1000, saveProductEventTriggerWork).awaitFinish(); + try { + Async.beginWork(1000, saveProductEventTriggerWork); + } catch (ExecutionException e) { + e.printStackTrace(); + } } catch (InterruptedException e) { e.printStackTrace(); } @@ -201,11 +206,12 @@ public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseE //step 4: 同步到产品下的设备 - WorkerWrapper updateProductEventTriggerWork = WorkerWrapper.builder().worker(updateProductEventTriggerWorker).param(eventRule).build(); + WorkerWrapper updateProductEventTriggerWork = + new WorkerWrapper.Builder().worker(updateProductEventTriggerWorker).param(eventRule).build(); try { - Async.work(1000, updateProductEventTriggerWork).awaitFinish(); - } catch (InterruptedException e) { + Async.beginWork(1000, updateProductEventTriggerWork); + } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java index 94a61bde..9c954db7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -173,16 +173,16 @@ public void createProductAttr(ProductAttr productAttr, String zbxId) { productAttributeEvent.save(); - WorkerWrapper saveProdAttrEventTriggerWork = WorkerWrapper.builder() + WorkerWrapper saveProdAttrEventTriggerWork = new WorkerWrapper.Builder() .worker(saveProdAttrEventTriggerWorker).param(productAttr).build(); - WorkerWrapper asyncAttrEventZbxIdWork = WorkerWrapper.builder() + WorkerWrapper asyncAttrEventZbxIdWork = new WorkerWrapper.Builder() .worker(asyncAttrEventZbxIdWorker).param(productAttr).build(); - WorkerWrapper saveProdAttrEventWork = WorkerWrapper.builder() - .worker(saveProdAttrEventWorker).param(productAttr).nextOf(asyncAttrEventZbxIdWork).build(); + WorkerWrapper saveProdAttrEventWork = new WorkerWrapper.Builder() + .worker(saveProdAttrEventWorker).param(productAttr).next(asyncAttrEventZbxIdWork).build(); try { - Async.work(10000, saveProdAttrEventWork,saveProdAttrEventTriggerWork).awaitFinish(); + Async.beginWork(10000, saveProdAttrEventWork, saveProdAttrEventTriggerWork); } catch (Exception e) { e.printStackTrace(); } @@ -290,11 +290,11 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { DB.update(productAttributeEvent); - WorkerWrapper updateProdAttrWork = WorkerWrapper.builder().worker(updateAttributeEventWorker).param(productAttr).build(); + WorkerWrapper updateProdAttrWork = new WorkerWrapper.Builder().worker(updateAttributeEventWorker).param(productAttr).build(); try { - Async.work(100, updateProdAttrWork).awaitFinish(); - } catch (InterruptedException e) { + Async.beginWork(100, updateProdAttrWork); + } catch (Exception e) { e.printStackTrace(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index 118bec4c..e5c15204 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -312,8 +312,8 @@ static class TriggerIds { @Data public static class Triggers { - private String triggerid; - private String description; + private String triggerid; + private String description; private List hosts; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index db97ab47..273b471c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -28,6 +28,7 @@ import org.springframework.stereotype.Service; import java.util.*; +import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; /** @@ -173,14 +174,14 @@ public void createProductAttr(ProductAttr productAttr, String zbxId) { productAttribute.save(); - WorkerWrapper asyncAttrZbxIdWork = WorkerWrapper.builder() + WorkerWrapper asyncAttrZbxIdWork = new WorkerWrapper.Builder() .worker(asyncAttrZbxIdWorker).param(productAttr).build(); - WorkerWrapper saveProdAttrWork = WorkerWrapper.builder() - .worker(saveProdAttrWorker).param(productAttr).nextOf(asyncAttrZbxIdWork).build(); + WorkerWrapper saveProdAttrWork = new WorkerWrapper.Builder() + .worker(saveProdAttrWorker).param(productAttr).next(asyncAttrZbxIdWork).build(); try { - Async.work(10000, saveProdAttrWork).awaitFinish(); - } catch (Exception e) { + Async.beginWork(10000, saveProdAttrWork); + } catch (ExecutionException | InterruptedException e) { e.printStackTrace(); } @@ -277,11 +278,11 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { DB.update(productAttribute); - WorkerWrapper updateProdAttrWork = WorkerWrapper.builder().worker(updateProdAttrWorker).param(productAttr).build(); + WorkerWrapper updateProdAttrWork = new WorkerWrapper.Builder().worker(updateProdAttrWorker).param(productAttr).build(); try { - Async.work(100, updateProdAttrWork).awaitFinish(); - } catch (InterruptedException e) { + Async.beginWork(100, updateProdAttrWork); + } catch (ExecutionException | InterruptedException e) { e.printStackTrace(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index 020eaab2..78d5b9ad 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -27,6 +27,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; /** @@ -158,11 +159,12 @@ public ProductServiceDto create(ProductServiceDto productServiceDto) { } //同步到设备 - WorkerWrapper saveProdAttrWork = WorkerWrapper.builder().worker(saveProdSvcWorker).param(productServiceDto).build(); + WorkerWrapper saveProdAttrWork = + new WorkerWrapper.Builder().worker(saveProdSvcWorker).param(productServiceDto).build(); try { - Async.work(100, saveProdAttrWork).awaitFinish(); - } catch (InterruptedException e) { + Async.beginWork(100, saveProdAttrWork); + } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } updateService(); @@ -197,11 +199,12 @@ public ProductServiceDto update(ProductServiceDto productServiceDto) { } //同步到设备 - WorkerWrapper updateProdSvcWork = WorkerWrapper.builder().worker(updateProdSvcWorker).param(productServiceDto).build(); + WorkerWrapper updateProdSvcWork = + new WorkerWrapper.Builder().worker(updateProdSvcWorker).param(productServiceDto).build(); try { - Async.work(1000, updateProdSvcWork).awaitFinish(); - } catch (InterruptedException e) { + Async.beginWork(1000, updateProdSvcWork); + } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } updateService(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java index 531bc113..999317f4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java @@ -32,7 +32,7 @@ public class AsyncAttrEventZbxIdWorker implements IWorker ZbxItem zbxItem; @Override - public Boolean action(ProductAttr productAttr, Map> map) { + public Boolean action(ProductAttr productAttr, Map map) { log.debug("AsyncAttrEventZbxIdWorker……"); Long attrId = productAttr.getAttrId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java index c2dbc78c..34bfff5a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java @@ -32,7 +32,7 @@ public class AsyncAttrZbxIdWorker implements IWorker { ZbxItem zbxItem; @Override - public Boolean action(ProductAttr productAttr, Map> map) { + public Boolean action(ProductAttr productAttr, Map map) { log.debug("AsyncAttrZbxIdWorker……"); Long attrId = productAttr.getAttrId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java index 7815f361..547db7b8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java @@ -28,7 +28,7 @@ public class SaveProdAttrEventTriggerWorker implements IWorker> map) { + public Boolean action(ProductAttr productAttr, Map map) { log.debug("SaveProdAttrEventTriggerWorker…………"); String prodId = productAttr.getProductId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java index 59c20c26..32feffbf 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java @@ -27,7 +27,7 @@ public class SaveProdAttrEventWorker implements IWorker { @Override - public Boolean action(ProductAttr productAttr, Map> map) { + public Boolean action(ProductAttr productAttr, Map map) { log.debug("SaveProdAttrEventTriggerWorker…………"); String prodId = productAttr.getProductId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java index 37c57095..7c5a5626 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java @@ -31,7 +31,7 @@ public class SaveProdAttrWorker implements IWorker { private static final String ATTR_SOURCE_DEPEND = "18"; @Override - public Boolean action(ProductAttr productAttr, Map> map) { + public Boolean action(ProductAttr productAttr, Map map) { log.debug("SaveProdAttrWorker…………"); String sql = "select device_id from device " + diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java index 04bf979c..4cefb599 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java @@ -25,7 +25,7 @@ public class SaveProdStatusTriggerWorker implements IWorker> map) { + public Boolean action(ProductServiceDto productServiceDto, Map map) { String prodId = productServiceDto.getRelationId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java index 4ad29f66..fcd16fc0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java @@ -27,7 +27,7 @@ public class SaveProdSvcWorker implements IWorker { @Override - public Boolean action(ProductServiceDto productServiceDto, Map> map) { + public Boolean action(ProductServiceDto productServiceDto, Map map) { String prodId = productServiceDto.getRelationId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java index d7586925..f0da993e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java @@ -36,7 +36,7 @@ public class SaveProductEventTriggerWorker implements IWorker> map) { + public Boolean action(ProductEventRule productEventRule, Map map) { log.debug("SaveProductEventTriggerWorker…………"); String prodId = productEventRule.getProductId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java index c894e2bf..c1f11084 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java @@ -24,7 +24,7 @@ public class UpdateAttributeEventWorker implements IWorker @Override - public Boolean action(ProductAttr productAttr, Map> map) { + public Boolean action(ProductAttr productAttr, Map map) { log.debug("UpdateAttributeEventWorker…………"); Long attrId = productAttr.getAttrId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java index 0d2d7bf3..c24df591 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java @@ -27,7 +27,7 @@ public class UpdateAttributeWorker implements IWorker { private static final String ATTR_SOURCE_DEPEND = "18"; @Override - public Boolean action(ProductAttr productAttr, Map> map) { + public Boolean action(ProductAttr productAttr, Map map) { log.debug("UpdateAttributeWorker…………"); Long attrId = productAttr.getAttrId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java index bae3a1de..a5342392 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java @@ -27,7 +27,7 @@ public class UpdateProdSvcWorker implements IWorker @Override - public Boolean action(ProductServiceDto productServiceDto, Map> map) { + public Boolean action(ProductServiceDto productServiceDto, Map map) { log.debug("UpdateProdSvcWorker…………"); String prodId = productServiceDto.getRelationId(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java index d1c14f30..887cf937 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java @@ -30,7 +30,7 @@ public class UpdateProductEventTriggerWorker implements IWorker> map) { + public Boolean action(ProductEventRule productEventRule, Map map) { log.debug("UpdateProductEventTriggerWorker…………"); String prodId = productEventRule.getProductId(); From 85068ebdb7036aa40cf5e409f58addcdd3c2d82b Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 10 Nov 2021 11:53:00 +0800 Subject: [PATCH 635/763] [feat]: update ebean version to 12.13.0 --- zeus-common/pom.xml | 2 +- zeus-webapp-bom/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zeus-common/pom.xml b/zeus-common/pom.xml index f1b97d4d..b536fb02 100644 --- a/zeus-common/pom.xml +++ b/zeus-common/pom.xml @@ -31,7 +31,7 @@ io.ebean querybean-generator - 12.11.3 + 12.13.0 com.google.guava diff --git a/zeus-webapp-bom/pom.xml b/zeus-webapp-bom/pom.xml index d5bd8a8d..32b6a12b 100644 --- a/zeus-webapp-bom/pom.xml +++ b/zeus-webapp-bom/pom.xml @@ -151,7 +151,7 @@ io.ebean ebean - 12.11.3 + 12.13.0 From efc0041dd0dc3db1aee8b1e153b0c6d58fa6e2a5 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 10 Nov 2021 12:06:08 +0800 Subject: [PATCH 636/763] [fix]: fix async tool --- .../zmops/iot/async/callback/ICallback.java | 21 +++++++++++++++++++ .../iot/web/device/service/DeviceService.java | 2 ++ 2 files changed, 23 insertions(+) diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ICallback.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ICallback.java index 0eaf131f..9937a969 100644 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ICallback.java +++ b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ICallback.java @@ -23,4 +23,25 @@ default void begin() { * 耗时操作执行完毕后,就给value注入值 */ void result(boolean success, T param, WorkResult workResult); + + /** + * 提供常量选项: + *

+ * 如果发生了异常,则打印异常信息。 + * 正常结束(例如取消、跳过)的异常不会打印。 + */ + ICallback PRINT_EXCEPTION_STACK_TRACE = new ICallback() { + @Override + public void result(boolean success, Object param, WorkResult workResult) { + Exception ex = workResult.getEx(); + if (ex != null) { + ex.printStackTrace(); + } + } + + @Override + public String toString() { + return "PRINT_EXCEPTION_STACK_TRACE"; + } + }; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index aebd39ee..f2c357a5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -2,6 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.async.callback.ICallback; import com.zmops.iot.async.executor.Async; import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.Device; @@ -319,6 +320,7 @@ public String update(DeviceDto deviceDto) { WorkerWrapper saveZbxHostWork = new WorkerWrapper.Builder().id("saveZbxHostWork") .worker(saveZbxHostWorker).param(deviceDto) .next(updateAttrZbxIdWork, saveOtherWork) + .callback(ICallback.PRINT_EXCEPTION_STACK_TRACE) .build(); WorkerWrapper deviceWork = new WorkerWrapper.Builder().id("saveDvice") From e69872916cca459e6d56cc575409bb67a15cd7f5 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 10 Nov 2021 12:11:21 +0800 Subject: [PATCH 637/763] [fix] fix device save callback --- .../java/com/zmops/iot/web/device/service/DeviceService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index f2c357a5..5f1725a3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -268,6 +268,7 @@ public String create(DeviceDto deviceDto) { WorkerWrapper saveZbxHostWork = new WorkerWrapper.Builder().id("saveZbxHostWork") .worker(saveZbxHostWorker).param(deviceDto) .next(updateAttrZbxIdWork, updateDeviceZbxIdWork, saveOtherWork) + .callback(ICallback.PRINT_EXCEPTION_STACK_TRACE) .build(); WorkerWrapper deviceWork = new WorkerWrapper.Builder().id("saveDvice") @@ -320,7 +321,6 @@ public String update(DeviceDto deviceDto) { WorkerWrapper saveZbxHostWork = new WorkerWrapper.Builder().id("saveZbxHostWork") .worker(saveZbxHostWorker).param(deviceDto) .next(updateAttrZbxIdWork, saveOtherWork) - .callback(ICallback.PRINT_EXCEPTION_STACK_TRACE) .build(); WorkerWrapper deviceWork = new WorkerWrapper.Builder().id("saveDvice") From 15d8a8974a1e177df9289fd73cd618925d5e82e5 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 10 Nov 2021 16:20:24 +0800 Subject: [PATCH 638/763] [fix]: fix device service log --- .../main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java | 2 ++ .../com/zmops/iot/web/device/service/DeviceLogService.java | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java index a6508a58..32bb7c27 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java @@ -45,6 +45,8 @@ public class DeviceLogDto { private Long eventRuleId; + private Long userId; + private List triggerDevice; private List executeDevice; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java index f536bd39..3d75c7aa 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java @@ -226,8 +226,8 @@ private Pager getServiceLog(DeviceLogParam deviceLogParam) { String triggerBody = null != service.getExecuteUser() ? DefinitionsUtil.getSysUserName(service.getExecuteUser()) : DefinitionsUtil.getTriggerName(service.getExecuteRuleId()); - deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_SERVICE).content(service.getServiceName()) - .triggerTime(LocalDateTimeUtils.formatTime(service.getCreateTime())).deviceId(service.getDeviceId()) + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_SERVICE).content(service.getServiceName()).eventRuleId(service.getExecuteRuleId()) + .triggerTime(LocalDateTimeUtils.formatTime(service.getCreateTime())).deviceId(service.getDeviceId()).userId(service.getExecuteUser()) .param(service.getParam()).triggerType(service.getExecuteType()).triggerBody(triggerBody).build()); }); } From e1426c6b7c9f3a86a457dc7fb3d58782f4b122c9 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 11 Nov 2021 11:21:37 +0800 Subject: [PATCH 639/763] [fix]: verify before product attribute delete --- .../web/device/service/DeviceModelService.java | 13 +++++++++++++ .../iot/web/exception/enums/BizExceptionEnum.java | 7 +++++++ .../service/ProductAttributeEventService.java | 15 +++++++++++++++ .../web/product/service/ProductModelService.java | 14 ++++++++++++++ .../web/product/service/ProductSvcService.java | 7 +++++++ 5 files changed, 56 insertions(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index cc14b131..8608e232 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -6,6 +6,7 @@ import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.domain.product.query.QProductEventExpression; import com.zmops.iot.enums.CommonTimeUnit; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; @@ -295,6 +296,18 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { */ public void deleteTrapperItem(ProductAttr productAttr) { + //检查是否有属性依赖 + int count = new QProductAttribute().depAttrId.in(productAttr.getAttrIds()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED); + } + + //检查属性是否被告警规则引入 + count = new QProductEventExpression().productAttrId.in(productAttr.getAttrIds()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PRODUCT_EVENT_HASDEPTED); + } + List zbxIds = new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(productAttr.getAttrIds()).zbxId.isNotNull().findSingleAttributeList(); //删除zbx item if (ToolUtil.isNotEmpty(zbxIds)) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index 3e3164c7..5e50cf8a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -144,6 +144,8 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { PRODUCT_ATTR_KEY_NOT_EXISTS(1404, "该属性Key不存在"), PRODUCT_ATTR_DEPTED_NULL(1402, "依赖的属性不能为空"), PRODUCT_ATTR_DEPTED_NOT_EXIST(1403, "依赖的属性不能为空"), + PRODUCT_ATTR_DEPTED(1404, "属性被依赖不能删除"), + PRODUCT_EVENT_HASDEPTED(1405,"属性已用于告警规则,不能删除"), /** * 设备相关 @@ -157,6 +159,7 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { */ SERVICE_EXISTS(1601, "服务已存在"), SERVICE_NOT_EXISTS(1602, "服务不存在"), + PRODUCT_EVENT_HAS_DEPTED(1605,"服务已用于告警规则或场景联动,不能删除"), /** * 触发规则相关 @@ -171,12 +174,16 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { EVENT_PRODUCT_CANNOT_DELETE(1706, "来自产品的触发器不能删除"), SCENE_NOT_EXISTS(1707, "场景不存在"), + + /** * 租户相关的异常 */ AUTH_REQUEST_ERROR(400, "账号密码错误"); + + BizExceptionEnum(int code, String message) { this.code = code; this.message = message; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java index 9c954db7..dc9fdf33 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -9,7 +9,9 @@ import com.zmops.iot.domain.product.Product; import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.domain.product.query.QProduct; +import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.domain.product.query.QProductAttributeEvent; +import com.zmops.iot.domain.product.query.QProductEventExpression; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; @@ -309,6 +311,19 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { */ public void deleteTrapperItem(ProductAttr productAttr) { + //检查是否有属性依赖 + int count = new QProductAttributeEvent().depAttrId.in(productAttr.getAttrIds()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED); + } + + //检查属性是否被告警规则引入 + List attrIds = new QProductAttributeEvent().select(QProductAttributeEvent.alias().attrId).templateId.in(productAttr.getAttrIds()).findSingleAttributeList(); + count = new QProductEventExpression().productAttrId.in(productAttr.getAttrIds()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PRODUCT_EVENT_HASDEPTED); + } + List zbxIds = new QProductAttributeEvent().select(QProductAttributeEvent.alias().zbxId).attrId.in(productAttr.getAttrIds()).findSingleAttributeList(); //删除zbx item if (ToolUtil.isNotEmpty(zbxIds)) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index 273b471c..2170f41b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -8,6 +8,7 @@ import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProduct; import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.domain.product.query.QProductEventExpression; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; @@ -297,6 +298,19 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { */ public void deleteTrapperItem(ProductAttr productAttr) { + //检查是否有属性依赖 + int count = new QProductAttribute().depAttrId.in(productAttr.getAttrIds()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED); + } + + //检查属性是否被告警规则引入 + List attrIds = new QProductAttribute().select(QProductAttribute.alias().attrId).templateId.in(productAttr.getAttrIds()).findSingleAttributeList(); + count = new QProductEventExpression().productAttrId.in(attrIds).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PRODUCT_EVENT_HASDEPTED); + } + List zbxIds = new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(productAttr.getAttrIds()).findSingleAttributeList(); //删除zbx item if (ToolUtil.isNotEmpty(zbxIds)) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index 78d5b9ad..de20ad5d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -5,6 +5,7 @@ import com.zmops.iot.domain.product.ProductService; import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.product.ProductServiceRelation; +import com.zmops.iot.domain.product.query.QProductEventService; import com.zmops.iot.domain.product.query.QProductService; import com.zmops.iot.domain.product.query.QProductServiceParam; import com.zmops.iot.domain.product.query.QProductServiceRelation; @@ -224,6 +225,12 @@ private List getServiceIdList(String relationId) { */ public void delete(List ids) { + //检查服务是否被 告警 联动规则引用 + int count = new QProductEventService().serviceId.in(ids).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PRODUCT_EVENT_HAS_DEPTED); + } + new QProductServiceParam().serviceId.in(ids).delete(); new QProductServiceRelation().serviceId.in(ids).delete(); new QProductService().id.in(ids).delete(); From c69ee038cd764ca30b8de3d8964b75e53c3e403e Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 11 Nov 2021 19:06:34 +0800 Subject: [PATCH 640/763] [fix]: fix init sql --- dist-material/bin/sql/zeus-iot.sql | 499 ++++++++++++++++++++++------- 1 file changed, 376 insertions(+), 123 deletions(-) diff --git a/dist-material/bin/sql/zeus-iot.sql b/dist-material/bin/sql/zeus-iot.sql index 975ec7e8..f24d740c 100644 --- a/dist-material/bin/sql/zeus-iot.sql +++ b/dist-material/bin/sql/zeus-iot.sql @@ -1,18 +1,18 @@ /* Navicat Premium Data Transfer - Source Server : 172.16.60.98-测试LOT + Source Server : 172.16.60.130-专业演示LOT Source Server Type : PostgreSQL Source Server Version : 130004 - Source Host : 172.16.60.98:5432 - Source Catalog : zeus-iot + Source Host : 172.16.60.130:5432 + Source Catalog : zeus-iot-开源空库不要删 Source Schema : public Target Server Type : PostgreSQL Target Server Version : 130004 File Encoding : 65001 - Date: 13/10/2021 20:52:05 + Date: 11/11/2021 19:00:16 */ @@ -38,6 +38,28 @@ MAXVALUE 9223372036854775807 START 1 CACHE 1; +-- ---------------------------- +-- Sequence structure for event_trigger_record_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."event_trigger_record_id_seq"; +CREATE SEQUENCE "public"."event_trigger_record_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for mail_setting_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."mail_setting_id_seq"; +CREATE SEQUENCE "public"."mail_setting_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + -- ---------------------------- -- Sequence structure for media_type_setting_id_seq -- ---------------------------- @@ -60,6 +82,17 @@ MAXVALUE 9223372036854775807 START 1 CACHE 1; +-- ---------------------------- +-- Sequence structure for notice_record_record_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."notice_record_record_id_seq"; +CREATE SEQUENCE "public"."notice_record_record_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + -- ---------------------------- -- Sequence structure for product_event_relation_id_seq -- ---------------------------- @@ -115,6 +148,17 @@ MAXVALUE 2147483647 START 1 CACHE 1; +-- ---------------------------- +-- Sequence structure for scenes_trigger_record_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."scenes_trigger_record_id_seq"; +CREATE SEQUENCE "public"."scenes_trigger_record_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + -- ---------------------------- -- Sequence structure for service_execute_record_id_seq -- ---------------------------- @@ -289,6 +333,59 @@ COMMENT ON COLUMN "public"."devices_groups"."device_group_id" IS '设备组ID'; -- Records of devices_groups -- ---------------------------- +-- ---------------------------- +-- Table structure for event_trigger_record +-- ---------------------------- +DROP TABLE IF EXISTS "public"."event_trigger_record"; +CREATE TABLE "public"."event_trigger_record" ( + "id" int4 NOT NULL DEFAULT nextval('event_trigger_record_id_seq'::regclass), + "event_name" varchar(128) COLLATE "pg_catalog"."default", + "event_value" varchar(255) COLLATE "pg_catalog"."default", + "device_id" varchar(64) COLLATE "pg_catalog"."default", + "create_time" timestamp(6), + "key" varchar(64) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."event_trigger_record"."event_name" IS '事件名称'; +COMMENT ON COLUMN "public"."event_trigger_record"."event_value" IS '事件发生时的值'; +COMMENT ON COLUMN "public"."event_trigger_record"."device_id" IS '设备ID'; +COMMENT ON COLUMN "public"."event_trigger_record"."create_time" IS '发生时间'; +COMMENT ON COLUMN "public"."event_trigger_record"."key" IS '事件标识'; + +-- ---------------------------- +-- Records of event_trigger_record +-- ---------------------------- + +-- ---------------------------- +-- Table structure for mail_setting +-- ---------------------------- +DROP TABLE IF EXISTS "public"."mail_setting"; +CREATE TABLE "public"."mail_setting" ( + "host" varchar(100) COLLATE "pg_catalog"."default" NOT NULL, + "port" int4 NOT NULL, + "account" varchar(100) COLLATE "pg_catalog"."default" NOT NULL, + "password" varchar(100) COLLATE "pg_catalog"."default" NOT NULL, + "sender" varchar(100) COLLATE "pg_catalog"."default" NOT NULL, + "ssl" int4 NOT NULL DEFAULT 0, + "tls" int4 NOT NULL DEFAULT 0, + "severity" varchar(255) COLLATE "pg_catalog"."default" NOT NULL DEFAULT ''::character varying, + "silent" int2 NOT NULL DEFAULT 3, + "id" int4 NOT NULL DEFAULT nextval('mail_setting_id_seq'::regclass) +) +; +COMMENT ON COLUMN "public"."mail_setting"."host" IS 'smtp服务器地址'; +COMMENT ON COLUMN "public"."mail_setting"."port" IS 'smtp服务器端口'; +COMMENT ON COLUMN "public"."mail_setting"."account" IS 'smtp登陆账号'; +COMMENT ON COLUMN "public"."mail_setting"."password" IS 'smtp密码'; +COMMENT ON COLUMN "public"."mail_setting"."sender" IS '发送邮箱'; +COMMENT ON COLUMN "public"."mail_setting"."ssl" IS '1-是 0-否'; +COMMENT ON COLUMN "public"."mail_setting"."tls" IS '1-是 0-否'; + +-- ---------------------------- +-- Records of mail_setting +-- ---------------------------- +INSERT INTO "public"."mail_setting" VALUES ('172.16.2.221', 587, 'sanshi@zmops.cn', 'Zmops@0610', 'sanshi@zmops.cn', 0, 1, '54', 3, 1); + -- ---------------------------- -- Table structure for media_type_setting -- ---------------------------- @@ -352,6 +449,56 @@ COMMENT ON COLUMN "public"."messages"."readed" IS '是否已读 1-是 0-否'; -- Records of messages -- ---------------------------- +-- ---------------------------- +-- Table structure for notice_record +-- ---------------------------- +DROP TABLE IF EXISTS "public"."notice_record"; +CREATE TABLE "public"."notice_record" ( + "record_id" int4 NOT NULL DEFAULT nextval('notice_record_record_id_seq'::regclass), + "user_id" int4, + "problem_id" varchar(32) COLLATE "pg_catalog"."default", + "notice_type" int4, + "notice_status" varchar(255) COLLATE "pg_catalog"."default", + "notice_msg" varchar(2550) COLLATE "pg_catalog"."default", + "alarm_info" varchar(255) COLLATE "pg_catalog"."default" DEFAULT NULL::character varying, + "receive_account" varchar(255) COLLATE "pg_catalog"."default" DEFAULT NULL::character varying, + "creat_time" timestamp(6) NOT NULL +) +; +COMMENT ON COLUMN "public"."notice_record"."record_id" IS '通知记录表主键id'; +COMMENT ON COLUMN "public"."notice_record"."user_id" IS '用户id'; +COMMENT ON COLUMN "public"."notice_record"."problem_id" IS '告警id'; +COMMENT ON COLUMN "public"."notice_record"."notice_type" IS '通知类型(1:sms 2:email 3:wechat 4:dingtalk)'; +COMMENT ON COLUMN "public"."notice_record"."notice_status" IS '通知状态'; +COMMENT ON COLUMN "public"."notice_record"."notice_msg" IS '通知消息'; +COMMENT ON COLUMN "public"."notice_record"."alarm_info" IS '告警信息'; +COMMENT ON COLUMN "public"."notice_record"."receive_account" IS '接收账号'; +COMMENT ON COLUMN "public"."notice_record"."creat_time" IS '创建时间'; + +-- ---------------------------- +-- Records of notice_record +-- ---------------------------- + +-- ---------------------------- +-- Table structure for problem +-- ---------------------------- +DROP TABLE IF EXISTS "public"."problem"; +CREATE TABLE "public"."problem" ( + "event_id" int8 NOT NULL, + "object_id" int8 NOT NULL DEFAULT '0'::bigint, + "name" varchar(2048) COLLATE "pg_catalog"."default" NOT NULL DEFAULT ''::character varying, + "acknowledged" int4 NOT NULL DEFAULT 0, + "severity" int4 NOT NULL DEFAULT 0, + "clock" timestamp(6), + "r_clock" timestamp(6), + "device_id" varchar(64) COLLATE "pg_catalog"."default" +) +; + +-- ---------------------------- +-- Records of problem +-- ---------------------------- + -- ---------------------------- -- Table structure for product -- ---------------------------- @@ -369,7 +516,8 @@ CREATE TABLE "public"."product" ( "update_time" timestamp(6), "update_user" int8, "product_code" varchar(255) COLLATE "pg_catalog"."default", - "zbx_id" varchar(32) COLLATE "pg_catalog"."default" + "zbx_id" varchar(32) COLLATE "pg_catalog"."default", + "icon" text COLLATE "pg_catalog"."default" ) ; COMMENT ON COLUMN "public"."product"."product_id" IS '产品ID'; @@ -385,6 +533,7 @@ COMMENT ON COLUMN "public"."product"."update_time" IS '更新时间'; COMMENT ON COLUMN "public"."product"."update_user" IS '更新人'; COMMENT ON COLUMN "public"."product"."product_code" IS '产品编号'; COMMENT ON COLUMN "public"."product"."zbx_id" IS 'Zabbix对应模板ID'; +COMMENT ON COLUMN "public"."product"."icon" IS '图片'; -- ---------------------------- -- Records of product @@ -456,7 +605,12 @@ CREATE TABLE "public"."product_attribute_event" ( "zbx_id" varchar(32) COLLATE "pg_catalog"."default", "value_type" varchar(16) COLLATE "pg_catalog"."default", "template_id" int8, - "event_level" char(1) COLLATE "pg_catalog"."default" + "event_level" char(1) COLLATE "pg_catalog"."default", + "source" varchar(16) COLLATE "pg_catalog"."default", + "delay" int2, + "unit" varchar(4) COLLATE "pg_catalog"."default", + "valuemapid" varchar(8) COLLATE "pg_catalog"."default", + "dep_attr_id" int8 ) ; COMMENT ON COLUMN "public"."product_attribute_event"."attr_id" IS '属性ID'; @@ -473,6 +627,11 @@ COMMENT ON COLUMN "public"."product_attribute_event"."zbx_id" IS 'itemid'; COMMENT ON COLUMN "public"."product_attribute_event"."value_type" IS '值类型'; COMMENT ON COLUMN "public"."product_attribute_event"."template_id" IS '继承的属性ID'; COMMENT ON COLUMN "public"."product_attribute_event"."event_level" IS '事件级别'; +COMMENT ON COLUMN "public"."product_attribute_event"."source" IS '数据来源'; +COMMENT ON COLUMN "public"."product_attribute_event"."delay" IS '取数间隔'; +COMMENT ON COLUMN "public"."product_attribute_event"."unit" IS '取数间隔单位 s m h '; +COMMENT ON COLUMN "public"."product_attribute_event"."valuemapid" IS '值映射ID'; +COMMENT ON COLUMN "public"."product_attribute_event"."dep_attr_id" IS '依赖属性ID'; -- ---------------------------- -- Records of product_attribute_event @@ -673,7 +832,6 @@ COMMENT ON COLUMN "public"."product_service_relation"."inherit" IS '是否继承 -- ---------------------------- DROP TABLE IF EXISTS "public"."product_status_function"; CREATE TABLE "public"."product_status_function" ( - "zbx_id" varchar(32) COLLATE "pg_catalog"."default", "rule_function" varchar(10) COLLATE "pg_catalog"."default", "rule_status" int2 DEFAULT 1, "create_user" int8, @@ -690,7 +848,6 @@ CREATE TABLE "public"."product_status_function" ( "unit_recovery" varchar(8) COLLATE "pg_catalog"."default" ) ; -COMMENT ON COLUMN "public"."product_status_function"."zbx_id" IS 'zabbix trigger id'; COMMENT ON COLUMN "public"."product_status_function"."rule_function" IS '''nodata'' or ''last'''; COMMENT ON COLUMN "public"."product_status_function"."rule_status" IS '0 or 1'; COMMENT ON COLUMN "public"."product_status_function"."rule_id" IS '触发器ID,离线 上线'; @@ -712,10 +869,14 @@ CREATE TABLE "public"."product_status_function_relation" ( "rule_id" int8 NOT NULL, "relation_id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, "id" int8 NOT NULL DEFAULT nextval('product_status_function_relation_id_seq'::regclass), - "inherit" varchar(4) COLLATE "pg_catalog"."default" DEFAULT 0 + "inherit" varchar(4) COLLATE "pg_catalog"."default" DEFAULT 0, + "zbx_id" varchar(32) COLLATE "pg_catalog"."default", + "zbx_id_recovery" varchar(32) COLLATE "pg_catalog"."default" ) ; COMMENT ON COLUMN "public"."product_status_function_relation"."inherit" IS '是否继承自产品 1是0否'; +COMMENT ON COLUMN "public"."product_status_function_relation"."zbx_id" IS 'zabbix trigger id'; +COMMENT ON COLUMN "public"."product_status_function_relation"."zbx_id_recovery" IS 'zbx recovery trigger id'; -- ---------------------------- -- Records of product_status_function_relation @@ -730,17 +891,48 @@ CREATE TABLE "public"."product_type" ( "pid" int4, "name" varchar(32) COLLATE "pg_catalog"."default", "remark" varchar(255) COLLATE "pg_catalog"."default", - "pids" varchar(255) COLLATE "pg_catalog"."default" + "pids" varchar(255) COLLATE "pg_catalog"."default", + "create_user" int8, + "create_time" timestamp(6), + "update_user" int8, + "update_time" timestamp(6) ) ; COMMENT ON COLUMN "public"."product_type"."name" IS '分类名称'; COMMENT ON COLUMN "public"."product_type"."remark" IS '备注'; COMMENT ON COLUMN "public"."product_type"."pids" IS '所有父ID'; +COMMENT ON COLUMN "public"."product_type"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."product_type"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."product_type"."update_user" IS '更新人'; +COMMENT ON COLUMN "public"."product_type"."update_time" IS '更新时间'; -- ---------------------------- -- Records of product_type -- ---------------------------- -INSERT INTO "public"."product_type" VALUES (1, 0, '默认产品分组', NULL, '[0],'); +INSERT INTO "public"."product_type" VALUES (1, 0, '默认产品分组', NULL, '[0],', NULL, NULL, NULL, NULL); + +-- ---------------------------- +-- Table structure for scenes_trigger_record +-- ---------------------------- +DROP TABLE IF EXISTS "public"."scenes_trigger_record"; +CREATE TABLE "public"."scenes_trigger_record" ( + "id" int8 NOT NULL DEFAULT nextval('scenes_trigger_record_id_seq'::regclass), + "create_time" timestamp(6), + "rule_name" varchar(64) COLLATE "pg_catalog"."default", + "rule_id" int8, + "trigger_type" varchar(16) COLLATE "pg_catalog"."default", + "trigger_user" int8 +) +; +COMMENT ON COLUMN "public"."scenes_trigger_record"."create_time" IS '触发时间'; +COMMENT ON COLUMN "public"."scenes_trigger_record"."rule_name" IS '场景联动名称'; +COMMENT ON COLUMN "public"."scenes_trigger_record"."rule_id" IS '场景联动ID'; +COMMENT ON COLUMN "public"."scenes_trigger_record"."trigger_type" IS '触发类型 手动 自动'; +COMMENT ON COLUMN "public"."scenes_trigger_record"."trigger_user" IS '触发人'; + +-- ---------------------------- +-- Records of scenes_trigger_record +-- ---------------------------- -- ---------------------------- -- Table structure for service_execute_record @@ -751,12 +943,18 @@ CREATE TABLE "public"."service_execute_record" ( "create_time" timestamp(6), "service_name" varchar(64) COLLATE "pg_catalog"."default", "param" varchar(255) COLLATE "pg_catalog"."default", - "device_id" varchar(64) COLLATE "pg_catalog"."default" + "device_id" varchar(64) COLLATE "pg_catalog"."default", + "execute_type" varchar(16) COLLATE "pg_catalog"."default", + "execute_user" int8, + "execute_rule_id" int8 ) ; COMMENT ON COLUMN "public"."service_execute_record"."service_name" IS '服务名称'; COMMENT ON COLUMN "public"."service_execute_record"."param" IS '执行参数'; COMMENT ON COLUMN "public"."service_execute_record"."device_id" IS '设备ID'; +COMMENT ON COLUMN "public"."service_execute_record"."execute_type" IS '执行方式 手动触发 场景触发'; +COMMENT ON COLUMN "public"."service_execute_record"."execute_user" IS '执行人 执行方式未手动触发时有值'; +COMMENT ON COLUMN "public"."service_execute_record"."execute_rule_id" IS '执行场景ID'; -- ---------------------------- -- Records of service_execute_record @@ -797,19 +995,19 @@ COMMENT ON COLUMN "public"."sys_config"."status" IS '是否可修改 ENABLE可 -- ---------------------------- -- Records of sys_config -- ---------------------------- -INSERT INTO "public"."sys_config" VALUES (1145915627211370502, '获取token的header标识', 'ZEUS_TOKEN_HEADER_NAME', 'N', NULL, 'Authorization', '获取token的header标识', 1, 1, '2019-10-16 23:02:39', '2021-08-03 16:38:12.432', 'DISABLE'); -INSERT INTO "public"."sys_config" VALUES (1143468689664876546, '管理系统名称', 'ZEUS_SYSTEM_NAME', 'N', NULL, 'ZEUS-IOT', '管理系统名称', 1, 1, '2019-06-25 18:39:15', '2021-08-09 17:17:30.189', 'ENABLE'); -INSERT INTO "public"."sys_config" VALUES (1145915627211370501, '获取系统地密钥过期时间', 'ZEUS_JWT_SECRET_EXPIRE', 'N', NULL, '86400', '获取系统地密钥过期时间(单位:秒),默认1天', 1, 1, '2019-10-16 23:02:39', '2021-08-03 16:38:12.432', 'ENABLE'); -INSERT INTO "public"."sys_config" VALUES (1143469008025133058, 'OAuth2登录用户的账号标识', 'ZEUS_OAUTH2_PREFIX', 'N', NULL, 'oauth2', 'OAuth2登录用户的账号标识', 1, 1, '2019-06-25 18:40:31', '2021-08-03 16:38:12.432', 'ENABLE'); -INSERT INTO "public"."sys_config" VALUES (1145915627211370499, '文件上传路径', 'ZEUS_FILE_UPLOAD_PATH', 'N', NULL, '/tmp', '文件上传默认目录', 1, 1, '2019-08-30 09:10:40', '2021-08-03 16:38:12.432', 'ENABLE'); INSERT INTO "public"."sys_config" VALUES (1143324237579165697, '验证码开关', 'ZEUS_KAPTCHA_OPEN', 'Y', 1106120265689055233, 'DISABLE', '是否开启验证码', 1, 1, '2019-06-24 12:46:43', '2021-08-03 16:38:12.432', 'ENABLE'); -INSERT INTO "public"."sys_config" VALUES (1145915627211370498, 'Zeus发布的编号', 'ZEUS_SYSTEM_RELEASE_VERSION', 'N', NULL, '10', '用于防止浏览器缓存相关的js和css', 1, 1, '2019-07-02 12:42:30', '2021-08-03 16:38:12.432', 'ENABLE'); -INSERT INTO "public"."sys_config" VALUES (1143468867767607297, '默认系统密码', 'ZEUS_DEFAULT_PASSWORD', 'N', NULL, '111111', '默认系统密码', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); -INSERT INTO "public"."sys_config" VALUES (1143468867767607208, '单点登录开关', 'ZEUS_SIGN_IN', 'N', NULL, 'DISABLE', '是否启用单点登录', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468689664876546, '管理系统名称', 'ZEUS_SYSTEM_NAME', 'N', NULL, 'ZEUS-IOT', '管理系统名称', 1, 1, '2019-06-25 18:39:15', '2021-08-09 17:17:30.189', 'ENABLE'); INSERT INTO "public"."sys_config" VALUES (1143468867767607207, '默认租户角色ID', 'ZEUS_TENANT_ROLE_ID', 'N', NULL, '1', '默认租户角色ID', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); -INSERT INTO "public"."sys_config" VALUES (1145915627211370496, '全局主机组Id', 'ZEUS_HOST_GROUP_ID', 'Y', NULL, '19', '全局主机和模板组ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468867767607208, '单点登录开关', 'ZEUS_SIGN_IN', 'N', NULL, 'DISABLE', '是否启用单点登录', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468867767607297, '默认系统密码', 'ZEUS_DEFAULT_PASSWORD', 'N', NULL, '111111', '默认系统密码', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); INSERT INTO "public"."sys_config" VALUES (1143468867767607298, '用户角色ID', 'ZEUS_ADMIN_ROLE_ID', 'N', NULL, '3', '用户角色ID', 1, 1, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1143469008025133058, 'OAuth2登录用户的账号标识', 'ZEUS_OAUTH2_PREFIX', 'N', NULL, 'oauth2', 'OAuth2登录用户的账号标识', 1, 1, '2019-06-25 18:40:31', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370496, '全局主机组Id', 'ZEUS_HOST_GROUP_ID', 'Y', NULL, '19', '全局主机和模板组ID', NULL, NULL, NULL, NULL, 'DISABLE'); INSERT INTO "public"."sys_config" VALUES (1145915627211370497, '离线回调ActionId', 'ZEUS_OFFLINE_ACTION_ID', 'Y', NULL, '7', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370498, 'Zeus发布的编号', 'ZEUS_SYSTEM_RELEASE_VERSION', 'N', NULL, '10', '用于防止浏览器缓存相关的js和css', 1, 1, '2019-07-02 12:42:30', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370499, '文件上传路径', 'ZEUS_FILE_UPLOAD_PATH', 'N', NULL, '/tmp', '文件上传默认目录', 1, 1, '2019-08-30 09:10:40', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370501, '获取系统地密钥过期时间', 'ZEUS_JWT_SECRET_EXPIRE', 'N', NULL, '86400', '获取系统地密钥过期时间(单位:秒),默认1天', 1, 1, '2019-10-16 23:02:39', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370502, '获取token的header标识', 'ZEUS_TOKEN_HEADER_NAME', 'N', NULL, 'Authorization', '获取token的header标识', 1, 1, '2019-10-16 23:02:39', '2021-08-03 16:38:12.432', 'DISABLE'); INSERT INTO "public"."sys_config" VALUES (1145915627211370503, '告警回调ActionId', 'ZEUS_ALARM_ACTION_ID', 'Y', NULL, '8', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); INSERT INTO "public"."sys_config" VALUES (1145915627211370504, '动作回调ActionId', 'ZEUS_EXEC_ACTION_ID', 'Y', NULL, '9', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); INSERT INTO "public"."sys_config" VALUES (1145915627211370505, '事件回调ActionId', 'ZEUS_EVENT_ACTION_ID', 'Y', NULL, '10', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); @@ -883,16 +1081,29 @@ INSERT INTO "public"."sys_dict" VALUES (1423897784372199424, 1423840415470653440 INSERT INTO "public"."sys_dict" VALUES (1423897784372199425, 1160532886713155587, 'wechat', '企业微信', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199426, 1160532886713155587, 'dingtalk', '钉钉', 'ENABLE', 2, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199427, 1160532886713155587, 'feishu', '飞书', 'ENABLE', 3, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199428, 1160532886713155588, '2', '主动上报', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199430, 1160532886713155588, '18', '根据单个属性预处理', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199431, 1160532886713155590, '3', '整数', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199432, 1160532886713155590, '0', '小数', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199433, 1160532886713155590, '1', '字符', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199434, 1160532886713155590, '4', '文本', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199470, 1160532886713155589, 'mg', '毫克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199471, 1160532886713155589, 'g', '克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199472, 1160532886713155589, 'kg', '千克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199473, 1160532886713155589, 't', '吨', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199474, 1160532886713155589, 'Pa', '帕斯卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '压力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199475, 1160532886713155589, 'kPa', '千帕斯卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '压力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199435, 1160532886713155589, '%', '百分比', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199436, 1160532886713155589, 'count', '次', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199437, 1160532886713155589, 'r/min', '转每分钟', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199438, 1160532886713155589, 'nm', '纳米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199439, 1160532886713155589, 'μm', '微米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199440, 1160532886713155589, 'mm', '毫米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199441, 1160532886713155589, 'cm', '厘米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199442, 1160532886713155589, 'm', '米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199443, 1160532886713155589, 'km', '千米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199444, 1160532886713155589, 'mm²', '平方毫米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199445, 1160532886713155589, 'cm²', '平方厘米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199446, 1160532886713155589, 'm²', '平方米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199447, 1160532886713155589, 'km²', '平方千米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199448, 1160532886713155589, 'hm²', '公顷', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199449, 1160532886713155589, 'd', '天', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199450, 1160532886713155589, 'h', '小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199451, 1160532886713155589, 'min', '分钟', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199452, 1160532886713155589, 's', '秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199453, 1160532886713155589, 'ms', '毫秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199454, 1160532886713155589, 'μs', '微秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); @@ -910,41 +1121,23 @@ INSERT INTO "public"."sys_dict" VALUES (1423897784372199465, 1160532886713155589 INSERT INTO "public"."sys_dict" VALUES (1423897784372199466, 1160532886713155589, 'cm³/h', '立方厘米每小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199467, 1160532886713155589, 'l/h', '升每小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199468, 1160532886713155589, 'mL', '毫升', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '容积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199435, 1160532886713155589, '%', '百分比', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199437, 1160532886713155589, 'r/min', '转每分钟', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199438, 1160532886713155589, 'nm', '纳米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199439, 1160532886713155589, 'μm', '微米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199440, 1160532886713155589, 'mm', '毫米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199441, 1160532886713155589, 'cm', '厘米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199442, 1160532886713155589, 'm', '米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199443, 1160532886713155589, 'km', '千米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199444, 1160532886713155589, 'mm²', '平方毫米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199445, 1160532886713155589, 'cm²', '平方厘米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199446, 1160532886713155589, 'm²', '平方米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199447, 1160532886713155589, 'km²', '平方千米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199448, 1160532886713155589, 'hm²', '公顷', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199449, 1160532886713155589, 'd', '天', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199450, 1160532886713155589, 'h', '小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199451, 1160532886713155589, 'min', '分钟', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199428, 1160532886713155588, '2', '主动上报', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199430, 1160532886713155588, '18', '根据单个属性预处理', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199436, 1160532886713155589, 'count', '次', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199506, 1160532886713155591, '25', 'Replace', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199507, 1160532886713155591, '4', 'Trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199508, 1160532886713155591, '2', 'Right trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199509, 1160532886713155591, '3', 'Left trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199510, 1160532886713155591, '11', 'XML XPath', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '结构化数据'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199511, 1160532886713155591, '12', 'JSONPath', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '结构化数据'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199514, 1160532886713155591, '1', '自定义倍数', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '自定义计算'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199517, 1160532886713155591, '7', '八进制转十进制', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '数制转换'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199518, 1160532886713155591, '8', '十六进制转十进制', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '数制转换'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199519, 1160532886713155591, '21', 'JavaScript', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '自定义脚本'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199500, 1160532886713155589, 'Ω', '欧姆', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199501, 1160532886713155589, 'KΩ', '千欧', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199502, 1160532886713155589, 'MΩ', '兆欧', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199503, 1160532886713155589, 'eV', '电子伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199504, 1160532886713155589, 'kW·h', '千瓦·时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199505, 1160532886713155589, 'kgce', 'Kg标准煤', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能源单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199469, 1160532886713155589, 'L', '升', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '容积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199470, 1160532886713155589, 'mg', '毫克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199471, 1160532886713155589, 'g', '克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199472, 1160532886713155589, 'kg', '千克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199473, 1160532886713155589, 't', '吨', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199474, 1160532886713155589, 'Pa', '帕斯卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '压力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199475, 1160532886713155589, 'kPa', '千帕斯卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '压力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199476, 1160532886713155589, 'N', '牛顿', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199477, 1160532886713155589, 'N.m', '牛·米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199478, 1160532886713155589, 'K', '开尔文', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199479, 1160532886713155589, '℃', '摄氏度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199480, 1160532886713155589, '℉', '华氏度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199481, 1160532886713155589, 'J', '焦耳', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199482, 1160532886713155589, 'cal', '卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199483, 1160532886713155589, 'W', '瓦特', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '功率单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199484, 1160532886713155589, 'kW', '千瓦特', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '功率单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199485, 1160532886713155589, 'rad', '弧度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199486, 1160532886713155589, '°', '度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199487, 1160532886713155589, '′', '[角]分', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199488, 1160532886713155589, '″', '[角]秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); @@ -959,29 +1152,34 @@ INSERT INTO "public"."sys_dict" VALUES (1423897784372199496, 1160532886713155589 INSERT INTO "public"."sys_dict" VALUES (1423897784372199497, 1160532886713155589, 'mV', '毫伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199498, 1160532886713155589, 'μV', '微伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199499, 1160532886713155589, 'A', '安培', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199469, 1160532886713155589, 'L', '升', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '容积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199476, 1160532886713155589, 'N', '牛顿', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199477, 1160532886713155589, 'N.m', '牛·米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199478, 1160532886713155589, 'K', '开尔文', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199479, 1160532886713155589, '℃', '摄氏度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199480, 1160532886713155589, '℉', '华氏度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199481, 1160532886713155589, 'J', '焦耳', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能量单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199482, 1160532886713155589, 'cal', '卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能量单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199483, 1160532886713155589, 'W', '瓦特', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '功率单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199484, 1160532886713155589, 'kW', '千瓦特', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '功率单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199485, 1160532886713155589, 'rad', '弧度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199500, 1160532886713155589, 'Ω', '欧姆', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199501, 1160532886713155589, 'KΩ', '千欧', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199502, 1160532886713155589, 'MΩ', '兆欧', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199503, 1160532886713155589, 'eV', '电子伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199504, 1160532886713155589, 'kW·h', '千瓦·时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199505, 1160532886713155589, 'kgce', 'Kg标准煤', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能源单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199506, 1160532886713155591, '25', 'Replace', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199507, 1160532886713155591, '4', 'Trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199508, 1160532886713155591, '2', 'Right trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199509, 1160532886713155591, '3', 'Left trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199510, 1160532886713155591, '11', 'XML XPath', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '结构化数据'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199511, 1160532886713155591, '12', 'JSONPath', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '结构化数据'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199512, 1160532886713155591, '13', 'In range', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '验证'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199514, 1160532886713155591, '1', '自定义倍数', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '自定义计算'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199517, 1160532886713155591, '7', '八进制转十进制', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '数制转换'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199518, 1160532886713155591, '8', '十六进制转十进制', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '数制转换'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199519, 1160532886713155591, '21', 'JavaScript', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '自定义脚本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199525, 1440492220332449792, '5', '紧急', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199526, 1440492220332449792, '4', '高级', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199527, 1440492220332449792, '3', '中级', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199528, 1440492220332449792, '1', '信息', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199529, 1440492220332449792, '2', '低级', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199531, 1160532886713155588, '0', 'Agent 采集', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1428599180229115911, 1428599180229115904, '0', '', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1428599180229115912, 1428599180229115904, '1', '是', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1429987619034984449, 1142859918022911591, '1', '异步', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1429987619034984450, 1142859918022911591, '0', '同步', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199512, 1160532886713155591, '13', 'In range', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '验证'); INSERT INTO "public"."sys_dict" VALUES (1440492197892923392, 1440492197679013888, 'SSm5lxzi', '三石Test3OrlDb', 'DISABLE', 99, NULL, '2021-09-22 09:44:37.685', '2021-09-22 09:44:37.755', 1, 1, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199531, 1160532886713155588, '0', 'Agent 采集', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199528, 1440492220332449792, '1', '信息', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199529, 1440492220332449792, '2', '低级', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199527, 1440492220332449792, '3', '中级', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199526, 1440492220332449792, '4', '高级', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199525, 1440492220332449792, '5', '紧急', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -- ---------------------------- -- Table structure for sys_dict_type @@ -1017,24 +1215,24 @@ COMMENT ON TABLE "public"."sys_dict_type" IS '字典类型表'; -- ---------------------------- -- Records of sys_dict_type -- ---------------------------- +INSERT INTO "public"."sys_dict_type" VALUES (1106120208097067009, 'SEX', '性别', '', 'Y', 'ENABLE', 4, '2019-03-14 17:09:43', 1, NULL, NULL); INSERT INTO "public"."sys_dict_type" VALUES (1106120265689055233, 'STATUS', '状态', '', 'Y', 'ENABLE', 3, '2019-03-14 17:09:57', 1, NULL, NULL); INSERT INTO "public"."sys_dict_type" VALUES (1106120322450571266, 'ACCOUNT_STATUS', '账号状态', '', 'Y', 'ENABLE', 40, '2019-03-14 17:10:10', 1, '2019-08-11 20:46:38', 1); INSERT INTO "public"."sys_dict_type" VALUES (1106120388036902914, 'DEL_FLAG', '是否删除', '', 'Y', 'ENABLE', 2, '2019-03-14 17:10:26', 1, '2019-03-27 16:26:31', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1142859918022911591, 'EXECUTE_TYPE', '服务执行方式', '服务执行方式', 'N', 'ENABLE', 1, NULL, NULL, '2021-09-10 15:56:14.127', 1); INSERT INTO "public"."sys_dict_type" VALUES (1149217131989069826, 'SYSTEM_TYPE', '系统分类', '系统所有分类的维护', 'Y', 'ENABLE', 50, '2019-07-11 15:21:30', 1, '2019-08-11 20:46:47', 1); INSERT INTO "public"."sys_dict_type" VALUES (1160532704105742337, 'FLOW_CATEGARY', '工作流分类', '工作流分类', 'Y', 'ENABLE', 60, '2019-08-11 20:45:33', 1, NULL, NULL); INSERT INTO "public"."sys_dict_type" VALUES (1160532775455047681, 'FLOW_KEY', '工作流标识', '工作流标识', 'Y', 'ENABLE', 70, '2019-08-11 20:45:50', 1, NULL, NULL); INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155585, 'LEAVE_TYPE', '请假类型', '请假类型', 'Y', 'ENABLE', 80, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); -INSERT INTO "public"."sys_dict_type" VALUES (1106120208097067009, 'SEX', '性别', '', 'Y', 'ENABLE', 4, '2019-03-14 17:09:43', 1, NULL, NULL); -INSERT INTO "public"."sys_dict_type" VALUES (1423160140530053120, 'DICTTYPE', '字典类型', '测试', 'N', 'ENABLE', NULL, '2021-08-05 13:53:13.196', 1, '2021-08-05 13:53:13.196', 1); -INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155587, 'MEDIA_TYPE', '通知类型', '通知类型', 'N', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155586, 'DEVICE_TYPE', '设备类型', '设备类型', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155587, 'MEDIA_TYPE', '通知类型', '通知类型', 'N', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155588, 'ATTR_TYPE', '产品属性类型', '产品属性类型', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155589, 'UNITS', '产品属性单位', '产品属性单位', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155590, 'DATA_TYPE', '产品属性值类型', '产品属性值类型', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155591, 'DATA_PRE_TYPE', '数据预处理方法名称', '数据预处理方法名称', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); -INSERT INTO "public"."sys_dict_type" VALUES (1440492220332449792, 'EVENT_LEVEL', '告警级别', '告警级别', 'N', 'ENABLE', NULL, '2021-09-22 09:44:43.035', 1, '2021-09-22 09:44:43.102', 1); -INSERT INTO "public"."sys_dict_type" VALUES (1142859918022911591, 'EXECUTE_TYPE', '服务执行方式', '服务执行方式', 'N', 'ENABLE', 1, NULL, NULL, '2021-09-10 15:56:14.127', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1423160140530053120, 'DICTTYPE', '字典类型', '测试', 'N', 'ENABLE', NULL, '2021-08-05 13:53:13.196', 1, '2021-08-05 13:53:13.196', 1); INSERT INTO "public"."sys_dict_type" VALUES (1428599180229115904, 'WHETHER', '是否', '是否', 'N', 'ENABLE', NULL, '2021-08-20 14:06:01.311', 1, '2021-08-20 14:06:01.311', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1440492220332449792, 'EVENT_LEVEL', '告警级别', '告警级别', 'N', 'ENABLE', NULL, '2021-09-22 09:44:43.035', 1, '2021-09-22 09:44:43.102', 1); -- ---------------------------- -- Table structure for sys_login_log @@ -1100,55 +1298,63 @@ COMMENT ON COLUMN "public"."sys_menu"."admin_flag" IS '是否是超级管理员 -- ---------------------------- -- Records of sys_menu -- ---------------------------- -INSERT INTO "public"."sys_menu" VALUES (113, 'mgr_setRole', 'mgr', '[0],[system],[mgr],', '分配角色', NULL, '/mgr/setRole', 7, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (139, 'dict_update', 'dict', '[0],[system],[dict],', '修改字典', NULL, '/dictType/editItem', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (140, 'dict_delete', 'dict', '[0],[system],[dict],', '删除字典', NULL, '/dictType/delete', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (151, 'menu_list', 'menu', '[0],[system],[menu],', '菜单列表', '', '/menu/list', 5, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:25', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (115, 'role_add', 'role', '[0],[system],[role],', '添加角色', NULL, '/role/add', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (116, 'role_edit', 'role', '[0],[system],[role],', '修改角色', NULL, '/role/edit', 2, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (105, 'system', '0', '[0],', '系统管理', 'layui-icon layui-icon-set', '/system', 20, 1, 'Y', NULL, 'ENABLE', NULL, '2019-03-29 16:32:27', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (106, 'userMgr', '0', '[0],', '用户管理', '', '/userMgr', 10, 1, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); INSERT INTO "public"."sys_menu" VALUES (107, 'mgr_add', 'mgr', '[0],[system],[mgr],', '添加用户', NULL, '/mgr/add', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); INSERT INTO "public"."sys_menu" VALUES (108, 'mgr_edit', 'mgr', '[0],[system],[mgr],', '修改用户', NULL, '/mgr/edit', 2, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); INSERT INTO "public"."sys_menu" VALUES (109, 'mgr_delete', 'mgr', '[0],[system],[mgr],', '删除用户', NULL, '/mgr/delete', 3, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (117, 'role_remove', 'role', '[0],[system],[role],', '删除角色', NULL, '/role/remove', 3, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (156, 'dict_list', 'dict', '[0],[system],[dict],', '字典列表', '', '/dict/list', 5, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (164, 'role_list', 'role', '[0],[system],[role],', '角色列表', '', '/role/list', 7, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (110, 'reset', 'mgr', '[0],[system],[mgr],', '重置密码', NULL, '/mgr/reset', 4, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (113, 'mgr_setRole', 'mgr', '[0],[system],[mgr],', '分配角色', NULL, '/mgr/setRole', 7, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'Y'); INSERT INTO "public"."sys_menu" VALUES (114, 'role', 'system', '[0],[system],', '角色管理', '', '/system/role', 20, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (128, 'businessLog', 'log', '[0],[log],', '业务日志', '', '/log/businessLog', 70, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:39', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (181, 'product_type', 'product_mgr', '[0],[product_mgr],', '产品分类', NULL, '/productMgr/productType', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (115, 'role_add', 'role', '[0],[system],[role],', '添加角色', NULL, '/role/add', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (116, 'role_edit', 'role', '[0],[system],[role],', '修改角色', NULL, '/role/edit', 2, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (117, 'role_remove', 'role', '[0],[system],[role],', '删除角色', NULL, '/role/remove', 3, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'N'); INSERT INTO "public"."sys_menu" VALUES (119, 'menu', 'system', '[0],[system],', '菜单管理', '', '/menu', 50, 2, 'Y', NULL, 'DISABLE', NULL, '2019-06-30 13:48:25', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (128, 'businessLog', 'log', '[0],[log],', '业务日志', '', '/log/businessLog', 70, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:39', NULL, 1, 'N'); INSERT INTO "public"."sys_menu" VALUES (132, 'dict', 'system', '[0],[system],', '字典管理', '', '/system/dictType', 40, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (158, 'log_list', 'log', '[0],[system],[log],', '日志列表', '', '/log/list', 2, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:39', NULL, 1, 'N'); INSERT INTO "public"."sys_menu" VALUES (133, 'loginLog', 'log', '[0],[log],', '登录日志', '', '/log/loginLog', 60, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:49:29', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (186, 'sysParam', 'system', '[0],[system],', '系统参数', '', '/system/sysParam', 10, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (138, 'dict_add', 'dict', '[0],[system],[dict],', '添加字典', NULL, '/dictType/addItem', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (139, 'dict_update', 'dict', '[0],[system],[dict],', '修改字典', NULL, '/dictType/editItem', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (140, 'dict_delete', 'dict', '[0],[system],[dict],', '删除字典', NULL, '/dictType/delete', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (151, 'menu_list', 'menu', '[0],[system],[menu],', '菜单列表', '', '/menu/list', 5, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:25', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (156, 'dict_list', 'dict', '[0],[system],[dict],', '字典列表', '', '/dict/list', 5, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (158, 'log_list', 'log', '[0],[system],[log],', '日志列表', '', '/log/list', 2, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:39', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (164, 'role_list', 'role', '[0],[system],[role],', '角色列表', '', '/role/list', 7, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'Y'); INSERT INTO "public"."sys_menu" VALUES (167, 'mgr_list', 'mgr', '[0],[system],[mgr],', '用户列表', '', '/mgr/list', 10, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (168, 'usrGrp', 'userMgr', '[0],[userMgr],', '用户组管理', NULL, '/userMgr/userGroup', 9, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (169, 'analyse', '0', '[0],', '统计分析', NULL, '/analyse', 1, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (170, 'dev_mgr', '0', '[0],', '设备管理', NULL, '/deviceMgr', 2, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (171, 'product_mgr', '0', '[0],', '产品管理', NULL, '/productMgr', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (173, 'view', '0', '[0],', '可视化', NULL, '/view', 3, 1, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); INSERT INTO "public"."sys_menu" VALUES (174, 'auth', '0', '[0],', '平台授权', NULL, '/auth', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (196, 'api', 'dev_mgr', '[0],[dev_mgr],', '设备调试', NULL, '/deviceMgr/debug', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (110, 'reset', 'mgr', '[0],[system],[mgr],', '重置密码', NULL, '/mgr/reset', 4, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (176, 'dev_log', 'analyse', '[0],[analyse],', '设备日志', NULL, '/analyse/devLog', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); INSERT INTO "public"."sys_menu" VALUES (177, 'dev', 'dev_mgr', '[0],[dev_mgr],', '设备', NULL, '/deviceMgr/device', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); INSERT INTO "public"."sys_menu" VALUES (178, 'dev_group', 'dev_mgr', '[0],[dev_mgr],', '设备组', NULL, '/deviceMgr/deviceGroup', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (171, 'product_mgr', '0', '[0],', '产品管理', NULL, '/productMgr', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (179, 'alarmList', 'alarm', '[0],[alarm],', '告警记录', NULL, '/alarm/alarmList', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); INSERT INTO "public"."sys_menu" VALUES (180, 'product', 'product_mgr', '[0],[product_mgr],', '产品', NULL, '/productMgr/product', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (181, 'product_type', 'product_mgr', '[0],[product_mgr],', '产品分类', NULL, '/productMgr/productType', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (183, 'grafana', 'view', '[0],[view],', 'Grafana配置', NULL, '/view/grafana', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); INSERT INTO "public"."sys_menu" VALUES (184, 'log', '0', '[0]', '日志管理', NULL, '/log', 4, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (105, 'system', '0', '[0],', '系统管理', 'layui-icon layui-icon-set', '/system', 20, 1, 'Y', NULL, 'ENABLE', NULL, '2019-03-29 16:32:27', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (170, 'dev_mgr', '0', '[0],', '设备管理', NULL, '/deviceMgr', 2, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (186, 'sysParam', 'system', '[0],[system],', '系统参数', '', '/system/sysParam', 10, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'Y'); INSERT INTO "public"."sys_menu" VALUES (187, 'media', 'system', '[0],[system],', '通知配置', '', '/system/media', 80, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:50:06', NULL, 1, 'N'); INSERT INTO "public"."sys_menu" VALUES (189, 'home', 'analyse', '[0],[analyse],', '全局概览', NULL, '/analyse/home', 1, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (179, 'alarmList', 'alarm', '[0],[alarm],', '告警记录', NULL, '/alarm/alarmList', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (169, 'analyse', '0', '[0],', '统计分析', NULL, '/analyse', 1, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); INSERT INTO "public"."sys_menu" VALUES (190, 'latest', 'analyse', '[0],[analyse],', '最新数据', NULL, '/analyse/latest', 1, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); INSERT INTO "public"."sys_menu" VALUES (191, 'alarmAnalyse', 'alarm', '[0],[alarm],', '告警分析', NULL, '/alarm/analyse', 3, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (173, 'view', '0', '[0],', '可视化', NULL, '/view', 3, 1, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (176, 'dev_log', 'analyse', '[0],[analyse],', '设备日志', NULL, '/analyse/devLog', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (183, 'grafana', 'view', '[0],[view],', 'Grafana配置', NULL, '/view/grafana', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); INSERT INTO "public"."sys_menu" VALUES (192, 'alarm', '0', '[0],', '告警管理', NULL, '/alarm', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (193, 'scene ', 'rule', '[0],[rule],', '场景联动', NULL, '/rule/scene', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); INSERT INTO "public"."sys_menu" VALUES (194, 'rule', '0', '[0],', '规则引擎', NULL, '/rule', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (195, 'nodeRed', 'rule', '[0],[rule],', 'Node-Red', NULL, '/rule/nodeRed', 3, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (196, 'api', 'dev_mgr', '[0],[dev_mgr],', '设备调试', NULL, '/deviceMgr/debug', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); INSERT INTO "public"."sys_menu" VALUES (197, 'about', '0', '[0],', '关于我们', NULL, '/about', 2, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (106, 'userMgr', '0', '[0],', '用户管理', '', '/userMgr', 10, 1, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (168, 'usrGrp', 'userMgr', '[0],[userMgr],', '用户组管理', NULL, '/userMgr/userGroup', 9, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (138, 'dict_add', 'dict', '[0],[system],[dict],', '添加字典', NULL, '/dictType/addItem', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (206, 'dev_detail', 'dev', '[0],[dev_mgr],[dev]', '设备详情', NULL, '/deviceMgr/device/detail', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (205, 'dev_list', 'dev', '[0],[dev_mgr],[dev]', '设备列表', NULL, '/deviceMgr/device/list', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (198, 'proxy', 'system', '[0],', '边缘采集', '', '/proxy', 20, 1, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (199, 'proxyInfo', 'system', '[0],[proxy],', '代理管理', '', '/proxy/proxyInfo', 20, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (200, 'proxyMonitor', 'system', '[0],[proxy],', '代理监控', '', '/proxy/proxyMonitor', 20, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'N'); +INSERT INTO "public"."sys_menu" VALUES (201, 'grafana', 'analyse', '[0],[analyse],', 'Grafana 演示大屏', NULL, '/analyse/grafana', 5, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (202, 'dev_add', 'dev', '[0],[dev_mgr],[dev]', '增加设备', NULL, '/deviceMgr/device/add', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (203, 'dev_update', 'dev', '[0],[dev_mgr],[dev]', '修改设备', NULL, '/deviceMgr/device/update', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); INSERT INTO "public"."sys_menu" VALUES (204, 'dev_delete', 'dev', '[0],[dev_mgr],[dev]', '删除设备', NULL, '/deviceMgr/device/delete', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (205, 'dev_list', 'dev', '[0],[dev_mgr],[dev]', '设备列表', NULL, '/deviceMgr/device/list', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (206, 'dev_detail', 'dev', '[0],[dev_mgr],[dev]', '设备详情', NULL, '/deviceMgr/device/detail', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); INSERT INTO "public"."sys_menu" VALUES (207, 'product_add', 'product', '[0],[product_mgr],[product]', '增加产品', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); INSERT INTO "public"."sys_menu" VALUES (208, 'product_update', 'product', '[0],[product_mgr],[product]', '修改产品', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); INSERT INTO "public"."sys_menu" VALUES (209, 'product_delete', 'product', '[0],[product_mgr],[product]', '删除产品', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); @@ -1160,14 +1366,7 @@ INSERT INTO "public"."sys_menu" VALUES (214, 'tenant_update', 'tenant', '[0],[sy INSERT INTO "public"."sys_menu" VALUES (215, 'tenant_list', 'tenant', '[0],[system],', '租户列表', '', '/system/tenant', 10, 3, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); INSERT INTO "public"."sys_menu" VALUES (216, 'tenant_delete', 'tenant', '[0],[system],', '租户删除', '', '/system/tenant', 10, 3, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); INSERT INTO "public"."sys_menu" VALUES (217, 'mgr', 'userMgr', '[0],[userMgr],', '用户', '', '/userMgr/user', 10, 1, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (195, 'nodeRed', 'rule', '[0],[rule],', 'Node-Red', NULL, '/rule/nodeRed', 3, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (199, 'proxyInfo', 'system', '[0],[proxy],', '代理管理', '', '/proxy/proxyInfo', 20, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (200, 'proxyMonitor', 'system', '[0],[proxy],', '代理监控', '', '/proxy/proxyMonitor', 20, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (198, 'proxy', 'system', '[0],', '边缘采集', '', '/proxy', 20, 1, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (201, 'grafana', 'analyse', '[0],[analyse],', 'Grafana 演示大屏', NULL, '/analyse/grafana', 5, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (203, 'dev_update', 'dev', '[0],[dev_mgr],[dev]', '修改设备', NULL, '/deviceMgr/device/update', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (202, 'dev_add', 'dev', '[0],[dev_mgr],[dev]', '增加设备', NULL, '/deviceMgr/device/add', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (193, 'scene ', 'rule', '[0],[rule],', '场景联动', NULL, '/rule/scene', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (218, 'distributed', 'dev_mgr', '[0],[dev_mgr],', '设备分布', NULL, '/deviceMgr/distributed', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -- ---------------------------- -- Table structure for sys_operation_log @@ -1266,6 +1465,7 @@ INSERT INTO "public"."sys_role_menu" VALUES (1, 211); INSERT INTO "public"."sys_role_menu" VALUES (1, 210); INSERT INTO "public"."sys_role_menu" VALUES (1, 212); INSERT INTO "public"."sys_role_menu" VALUES (1, 217); +INSERT INTO "public"."sys_role_menu" VALUES (1, 219); INSERT INTO "public"."sys_role_menu" VALUES (1, 105); INSERT INTO "public"."sys_role_menu" VALUES (1, 106); INSERT INTO "public"."sys_role_menu" VALUES (1, 107); @@ -1348,8 +1548,8 @@ COMMENT ON COLUMN "public"."sys_user"."zbx_id" IS 'zabbix 用户ID'; -- ---------------------------- -- Records of sys_user -- ---------------------------- -INSERT INTO "public"."sys_user" VALUES ('Admin', 'cbde417443393372dbac9c185a6ec159', 'gt3zs', '超级管理员', '', '', 1, 1437232484602372096, 'ENABLE', 1, 1, '2021-09-28 09:38:33.668', '2021-09-28 09:38:33.668', 122, 'f93a1bea2549f93fad75bdde71e6b4fe', '1'); INSERT INTO "public"."sys_user" VALUES ('root', '17db03c22596b7609c7c9704f16663e0', 'abcdef', '超级管理员', '888888@qq.com', '13812345678', 1, 1437232484602372096, 'ENABLE', 1, 1, '2021-07-30 21:43:02.686', '2021-07-30 21:43:02.686', 1, '5859e004e8d2a23e6c330c3f9cd277e2', '4'); +INSERT INTO "public"."sys_user" VALUES ('Admin', 'cbde417443393372dbac9c185a6ec159', 'gt3zs', '超级管理员', '', '', 1, 1437232484602372096, 'ENABLE', 1, 1, '2021-09-28 09:38:33.668', '2021-09-28 09:38:33.668', 122, 'f6ce31c5f70bf40fae2067087254202c', '1'); -- ---------------------------- -- Table structure for sys_user_group @@ -1421,7 +1621,7 @@ COMMENT ON COLUMN "public"."tag"."update_time" IS '更新时间'; -- ---------------------------- ALTER SEQUENCE "public"."device_online_report_id_seq" OWNED BY "public"."device_online_report"."id"; -SELECT setval('"public"."device_online_report_id_seq"', 7, true); +SELECT setval('"public"."device_online_report_id_seq"', 21, true); -- ---------------------------- -- Alter sequences owned by @@ -1430,6 +1630,20 @@ ALTER SEQUENCE "public"."devices_groups_id_seq" OWNED BY "public"."devices_groups"."id"; SELECT setval('"public"."devices_groups_id_seq"', 183, true); +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."event_trigger_record_id_seq" +OWNED BY "public"."event_trigger_record"."id"; +SELECT setval('"public"."event_trigger_record_id_seq"', 2, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."mail_setting_id_seq" +OWNED BY "public"."mail_setting"."id"; +SELECT setval('"public"."mail_setting_id_seq"', 2, false); + -- ---------------------------- -- Alter sequences owned by -- ---------------------------- @@ -1444,6 +1658,13 @@ ALTER SEQUENCE "public"."messages_id_seq" OWNED BY "public"."messages"."id"; SELECT setval('"public"."messages_id_seq"', 234, true); +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."notice_record_record_id_seq" +OWNED BY "public"."notice_record"."record_id"; +SELECT setval('"public"."notice_record_record_id_seq"', 2, false); + -- ---------------------------- -- Alter sequences owned by -- ---------------------------- @@ -1479,6 +1700,13 @@ ALTER SEQUENCE "public"."product_type_product_type_id_seq" OWNED BY "public"."product_type"."id"; SELECT setval('"public"."product_type_product_type_id_seq"', 226, true); +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."scenes_trigger_record_id_seq" +OWNED BY "public"."scenes_trigger_record"."id"; +SELECT setval('"public"."scenes_trigger_record_id_seq"', 3, false); + -- ---------------------------- -- Alter sequences owned by -- ---------------------------- @@ -1541,6 +1769,16 @@ ALTER TABLE "public"."device_online_report" ADD CONSTRAINT "device_online_report -- ---------------------------- ALTER TABLE "public"."devices_groups" ADD CONSTRAINT "devices_groups_pkey" PRIMARY KEY ("id"); +-- ---------------------------- +-- Primary Key structure for table event_trigger_record +-- ---------------------------- +ALTER TABLE "public"."event_trigger_record" ADD CONSTRAINT "event_trigger_record_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table mail_setting +-- ---------------------------- +ALTER TABLE "public"."mail_setting" ADD CONSTRAINT "mail_setting_pkey" PRIMARY KEY ("id"); + -- ---------------------------- -- Primary Key structure for table media_type_setting -- ---------------------------- @@ -1551,6 +1789,16 @@ ALTER TABLE "public"."media_type_setting" ADD CONSTRAINT "media_type_setting_pke -- ---------------------------- ALTER TABLE "public"."messages" ADD CONSTRAINT "messages_pkey" PRIMARY KEY ("id"); +-- ---------------------------- +-- Primary Key structure for table notice_record +-- ---------------------------- +ALTER TABLE "public"."notice_record" ADD CONSTRAINT "notice_record_pkey" PRIMARY KEY ("record_id"); + +-- ---------------------------- +-- Primary Key structure for table problem +-- ---------------------------- +ALTER TABLE "public"."problem" ADD CONSTRAINT "problem_pkey" PRIMARY KEY ("event_id"); + -- ---------------------------- -- Primary Key structure for table product -- ---------------------------- @@ -1616,6 +1864,11 @@ ALTER TABLE "public"."product_status_function_relation" ADD CONSTRAINT "product_ -- ---------------------------- ALTER TABLE "public"."product_type" ADD CONSTRAINT "product_type_pkey" PRIMARY KEY ("id"); +-- ---------------------------- +-- Primary Key structure for table scenes_trigger_record +-- ---------------------------- +ALTER TABLE "public"."scenes_trigger_record" ADD CONSTRAINT "scenes_trigger_record_pkey" PRIMARY KEY ("id"); + -- ---------------------------- -- Primary Key structure for table service_execute_record -- ---------------------------- From 32f2d909631673d9d39e3bc62672c2ddab63dfeb Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 11 Nov 2021 20:16:16 +0800 Subject: [PATCH 641/763] [fix]: fix init sql --- dist-material/bin/sql/zabbix_event.sql | 104 +++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 dist-material/bin/sql/zabbix_event.sql diff --git a/dist-material/bin/sql/zabbix_event.sql b/dist-material/bin/sql/zabbix_event.sql new file mode 100644 index 00000000..072aa7d7 --- /dev/null +++ b/dist-material/bin/sql/zabbix_event.sql @@ -0,0 +1,104 @@ +CREATE OR REPLACE FUNCTION "public"."event_notify"("channel" text, "routing_key" text, "message" text) + RETURNS "pg_catalog"."void" AS $BODY$ + select pg_notify(channel, routing_key || '$$' || message); +$BODY$ + LANGUAGE sql STABLE + COST 100; + + + + + + + CREATE OR REPLACE FUNCTION "public"."events_problem_trace"() + RETURNS "pg_catalog"."trigger" AS $BODY$ +DECLARE + v_eventid INT; + v_event_json TEXT; +BEGIN + CASE TG_OP + WHEN 'INSERT' THEN v_eventid := NEW.eventid; + select row_to_json(x) + into v_event_json + from (SELECT p."eventid", p."objectid", p."clock", p."r_clock", p."name", p."acknowledged", p."severity",tag.tag,tag."value" tagValue from problem p Inner JOIN (select eventid,tag,value from event_tag where tag ='__alarm__' ) tag on tag.eventid=p.eventid where p.source=0 and p.eventid = v_eventid) x; + WHEN 'UPDATE' THEN v_eventid := NEW.eventid; + select row_to_json(x) + into v_event_json + from (SELECT p."eventid", p."objectid", p."clock", p."r_clock", p."name", p."acknowledged", p."severity",tag.tag,tag."value" tagValue from problem p Inner JOIN (select eventid,tag,value from event_tag where tag ='__alarm__' ) tag on tag.eventid=p.eventid where p.source=0 and p.eventid = v_eventid) x; + ELSE RETURN NULL; + END CASE; + + perform event_notify('zabbix_pg_event', 'events', v_event_json); + + RETURN NULL; +END; +$BODY$ + LANGUAGE plpgsql VOLATILE STRICT + COST 100; + + + + + + + + + CREATE OR REPLACE FUNCTION "public"."events_tag_trace"() + RETURNS "pg_catalog"."trigger" AS $BODY$ +DECLARE + v_eventid INT; + v_event_json TEXT; +BEGIN + CASE TG_OP + WHEN 'INSERT' THEN v_eventid := NEW.eventid; + select row_to_json(x) + into v_event_json + from (select e.eventid,e.objectid,e.name,tag.tag,tag.value tagValue from events e LEFT JOIN (select eventid,tag,value from event_tag where tag = '__event__' ) tag on tag.eventid=e.eventid where e.source=0 and e.eventid = v_eventid) x; + ELSE RETURN NULL; + END CASE; + + perform event_notify('zabbix_pg_event', 'events', v_event_json); + + RETURN NULL; +END; +$BODY$ + LANGUAGE plpgsql VOLATILE STRICT + COST 100; + + + + + + + CREATE OR REPLACE FUNCTION "public"."events_trace"() + RETURNS "pg_catalog"."trigger" AS $BODY$ +DECLARE + v_eventid INT; + v_event_json TEXT; +BEGIN + CASE TG_OP + WHEN 'INSERT' THEN v_eventid := NEW.eventid; + select row_to_json(x) + into v_event_json + from (select e.eventid,e.objectid,e.name,tag.tag,tag.value tagValue from events e Inner JOIN (select triggerid,tag,value from trigger_tag where tag in ('__online__','__offline__','__execute__','__scene__') ) tag on tag.triggerid=e.objectid where e.source=0 and e.eventid = v_eventid) x; + ELSE RETURN NULL; + END CASE; + + perform event_notify('zabbix_pg_event', 'events', v_event_json); + + RETURN NULL; +END; +$BODY$ + LANGUAGE plpgsql VOLATILE STRICT + COST 100; + + + + CREATE TRIGGER "events_trigger" AFTER INSERT ON "public"."events" +FOR EACH ROW +EXECUTE PROCEDURE "public"."events_trace"(); + + +CREATE TRIGGER "events_problem_trigger" AFTER INSERT OR UPDATE OF "r_clock", "acknowledged" ON "public"."problem" +FOR EACH ROW +EXECUTE PROCEDURE "public"."events_problem_trace"(); From 468de258a6b0d6dca642e60131681278d8930472 Mon Sep 17 00:00:00 2001 From: nantian Date: Fri, 12 Nov 2021 23:24:18 +0800 Subject: [PATCH 642/763] [feat]: add task schedule --- .../iot/web/schedule/MisfireStrategyEnum.java | 34 + .../iot/web/schedule/ScheduleTypeEnum.java | 34 + .../java/com/zmops/iot/web/schedule/Task.java | 28 + .../iot/web/schedule/TaskScheduleImpl.java | 269 +++ .../zmops/iot/web/schedule/TaskStarter.java | 35 + .../iot/web/schedule/TaskTriggerPool.java | 100 + .../iot/web/schedule/TriggerTypeEnum.java | 24 + .../web/schedule/config/ScheduleConfig.java | 40 + .../iot/web/schedule/cron/CronExpression.java | 1657 +++++++++++++++++ 9 files changed, 2221 insertions(+) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/schedule/MisfireStrategyEnum.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/schedule/ScheduleTypeEnum.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/schedule/Task.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskStarter.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TriggerTypeEnum.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/schedule/config/ScheduleConfig.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/schedule/cron/CronExpression.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/MisfireStrategyEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/MisfireStrategyEnum.java new file mode 100644 index 00000000..f99213b8 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/MisfireStrategyEnum.java @@ -0,0 +1,34 @@ +package com.zmops.iot.web.schedule; + +public enum MisfireStrategyEnum { + + /** + * do nothing + */ + DO_NOTHING("Do nothing"), + + /** + * fire once now + */ + FIRE_ONCE_NOW("Fire once now"); + + private final String title; + + MisfireStrategyEnum(String title) { + this.title = title; + } + + public String getTitle() { + return title; + } + + public static MisfireStrategyEnum match(String name, MisfireStrategyEnum defaultItem) { + for (MisfireStrategyEnum item : MisfireStrategyEnum.values()) { + if (item.name().equals(name)) { + return item; + } + } + return defaultItem; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/ScheduleTypeEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/ScheduleTypeEnum.java new file mode 100644 index 00000000..ac1a9475 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/ScheduleTypeEnum.java @@ -0,0 +1,34 @@ +package com.zmops.iot.web.schedule; + +/** + * 调度任务类型 + */ +public enum ScheduleTypeEnum { + + NONE("None"), + + /** + * schedule by cron + */ + CRON("Cron"); + + private final String title; + + ScheduleTypeEnum(String title) { + this.title = title; + } + + public String getTitle() { + return title; + } + + public static ScheduleTypeEnum match(String name, ScheduleTypeEnum defaultItem) { + for (ScheduleTypeEnum item : ScheduleTypeEnum.values()) { + if (item.name().equals(name)) { + return item; + } + } + return defaultItem; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/Task.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/Task.java new file mode 100644 index 00000000..c0a5ec2e --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/Task.java @@ -0,0 +1,28 @@ +package com.zmops.iot.web.schedule; + +import lombok.Data; + +/** + * @author nantian created at 2021/11/12 19:11 + */ + +@Data +public class Task { + + private Integer id; + + private String scheduleType; // 调度类型 + private String scheduleConf; // 调度配置,值含义取决于调度类型 + private String misfireStrategy; // 调度过期策略 + + private Integer taskTimeout; + + private Integer taskFailRetryCount; + + private Integer triggerStatus; // 调度状态:0-停止,1-运行 + private Long triggerLastTime; // 上次调度时间 + private Long triggerNextTime; + + private String remark; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java new file mode 100644 index 00000000..45ab09c6 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java @@ -0,0 +1,269 @@ +package com.zmops.iot.web.schedule; + +import com.zmops.iot.schedule.config.ScheduleConfig; +import com.zmops.iot.schedule.cron.CronExpression; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +/** + * @author nantian created at 2021/11/12 10:54 + */ + +@Slf4j +public class TaskScheduleImpl { + + private final ScheduleConfig scheduleConfig; + + public TaskScheduleImpl(ScheduleConfig scheduleConfig) { + this.scheduleConfig = scheduleConfig; + } + + public static final long PRE_READ_MS = 5000; // pre read + + private Thread scheduleThread; + private Thread ringThread; + private volatile boolean scheduleThreadToStop = false; + private volatile boolean ringThreadToStop = false; + private static final Map> ringData = new ConcurrentHashMap<>(); + + + public void start() { + scheduleThread = new Thread(() -> { + try { + TimeUnit.MILLISECONDS.sleep(5000 - System.currentTimeMillis() % 1000); + } catch (InterruptedException e) { + if (!scheduleThreadToStop) { + log.error(e.getMessage(), e); + } + } + + int preReadCount = (scheduleConfig.getTriggerPoolFastMax() + scheduleConfig.getTriggerPoolSlowMax()) * 20; + + while (!scheduleThreadToStop) { + long start = System.currentTimeMillis(); + boolean preReadSuc = true; + + try { + DB.beginTransaction(); + + long nowTime = System.currentTimeMillis(); + List taskList = DB.findDto(Task.class, + "SELECT T.ID, T.remark, T.trigger_status, T.trigger_next_time, T.schedule_type, T.schedule_conf " + + " FROM task_info AS T " + + " WHERE T.trigger_status = 1 " + + " and t.trigger_next_time <= :nextTime " + + " ORDER BY ID ASC " + + " LIMIT :preReadCount") + .setParameter("nextTime", nowTime + PRE_READ_MS) + .setParameter("preReadCount", preReadCount) + .findList(); + + if (taskList.size() > 0) { + for (Task task : taskList) { + + if (nowTime > task.getTriggerNextTime() + PRE_READ_MS) { + MisfireStrategyEnum misfireStrategyEnum = MisfireStrategyEnum.match(task.getMisfireStrategy(), MisfireStrategyEnum.DO_NOTHING); + + if (MisfireStrategyEnum.FIRE_ONCE_NOW == misfireStrategyEnum) { + TaskTriggerPool.trigger(task.getId(), TriggerTypeEnum.MISFIRE, -1, null, null, null); + log.debug("schedule push trigger : taskId = {}", task.getId()); + } + refreshNextValidTime(task, new Date()); + } else if (nowTime > task.getTriggerNextTime()) { + TaskTriggerPool.trigger(task.getId(), TriggerTypeEnum.CRON, -1, null, null, null); + refreshNextValidTime(task, new Date()); + + if (task.getTriggerStatus() == 1 && nowTime + PRE_READ_MS > task.getTriggerNextTime()) { + int ringSecond = (int) ((task.getTriggerNextTime() / 1000) % 60); + pushTimeRing(ringSecond, task.getId()); + refreshNextValidTime(task, new Date(task.getTriggerNextTime())); + } + + } else { + int ringSecond = (int) ((task.getTriggerNextTime() / 1000) % 60); + pushTimeRing(ringSecond, task.getId()); + refreshNextValidTime(task, new Date(task.getTriggerNextTime())); + } + } + + for (Task task : taskList) { + DB.sqlUpdate("update task_info set " + + " trigger_last_time = :lastTime, " + + " trigger_next_time = :nextTime, " + + " trigger_status = :status " + + "where id = :id ") + .setParameter("lastTime", task.getTriggerLastTime()) + .setParameter("nextTime", task.getTriggerNextTime()) + .setParameter("status", task.getTriggerStatus()) + .setParameter("id", task.getId()) + .execute(); + } + } else { + preReadSuc = false; + } + } catch (Exception e) { + if (!scheduleThreadToStop) { + log.error("JobScheduleHelper error: {}", e.getMessage()); + } + } finally { + DB.commitTransaction(); + } + + long cost = System.currentTimeMillis() - start; + + if (cost < 1000) { // scan-overtime, not wait + try { + TimeUnit.MILLISECONDS.sleep((preReadSuc ? 1000 : PRE_READ_MS) - System.currentTimeMillis() % 1000); + } catch (InterruptedException e) { + if (!scheduleThreadToStop) { + log.error(e.getMessage(), e); + } + } + } + } + log.info("JobScheduleHelper#scheduleThread stop"); + }); + + scheduleThread.setDaemon(true); + scheduleThread.setName("JobScheduleHelper#scheduleThread"); + scheduleThread.start(); + + ringThread = new Thread(() -> { + while (!ringThreadToStop) { + + try { + TimeUnit.MILLISECONDS.sleep(1000 - System.currentTimeMillis() % 1000); + } catch (InterruptedException e) { + if (!ringThreadToStop) { + log.error(e.getMessage(), e); + } + } + + try { + List ringItemData = new ArrayList<>(); + int nowSecond = Calendar.getInstance().get(Calendar.SECOND); // 避免处理耗时太长,跨过刻度,向前校验一个刻度; + for (int i = 0; i < 2; i++) { + List tmpData = ringData.remove((nowSecond + 60 - i) % 60); + if (tmpData != null) { + ringItemData.addAll(tmpData); + } + } + + log.debug("time-ring beat : " + nowSecond + " = " + Collections.singletonList(ringItemData)); + if (ringItemData.size() > 0) { + + for (int jobId : ringItemData) { + TaskTriggerPool.trigger(jobId, TriggerTypeEnum.CRON, -1, null, null, null); + } + ringItemData.clear(); + } + } catch (Exception e) { + if (!ringThreadToStop) { + log.error("JobScheduleHelper#ringThread error:{}", e.getMessage()); + } + } + } + log.info("JobScheduleHelper#ringThread stop"); + }); + ringThread.setDaemon(true); + ringThread.setName("admin JobScheduleHelper#ringThread"); + ringThread.start(); + } + + private void refreshNextValidTime(Task task, Date fromTime) throws Exception { + Date nextValidTime = generateNextValidTime(task, fromTime); + if (nextValidTime != null) { + task.setTriggerLastTime(task.getTriggerNextTime()); + task.setTriggerNextTime(nextValidTime.getTime()); + } else { + task.setTriggerStatus(0); + task.setTriggerLastTime(0L); + task.setTriggerNextTime(0L); + log.warn("refreshNextValidTime fail for job: jobId={}, scheduleType={}, scheduleConf={}", task.getId(), task.getScheduleType(), task.getScheduleConf()); + } + } + + private void pushTimeRing(int ringSecond, int jobId) { + List ringItemData = ringData.computeIfAbsent(ringSecond, k -> new ArrayList()); + ringItemData.add(jobId); + } + + + /** + * 停止任务调度 + */ + public void toStop() { + + scheduleThreadToStop = true; + try { + TimeUnit.SECONDS.sleep(1); // wait + } catch (InterruptedException e) { + log.error(e.getMessage(), e); + } + if (scheduleThread.getState() != Thread.State.TERMINATED) { + scheduleThread.interrupt(); + try { + scheduleThread.join(); + } catch (InterruptedException e) { + log.error(e.getMessage(), e); + } + } + + boolean hasRingData = false; + if (!ringData.isEmpty()) { + for (int second : ringData.keySet()) { + List tmpData = ringData.get(second); + if (tmpData != null && tmpData.size() > 0) { + hasRingData = true; + break; + } + } + } + if (hasRingData) { + try { + TimeUnit.SECONDS.sleep(8); + } catch (InterruptedException e) { + log.error(e.getMessage(), e); + } + } + + ringThreadToStop = true; + try { + TimeUnit.SECONDS.sleep(1); + } catch (InterruptedException e) { + log.error(e.getMessage(), e); + } + if (ringThread.getState() != Thread.State.TERMINATED) { + ringThread.interrupt(); + try { + ringThread.join(); + } catch (InterruptedException e) { + log.error(e.getMessage(), e); + } + } + + log.info("JobScheduleHelper stop"); + } + + /** + * 根据表达式,获取下次任务调度执行时间 + * + * @param task + * @param fromTime + * @return + * @throws Exception + */ + public static Date generateNextValidTime(Task task, Date fromTime) throws Exception { + ScheduleTypeEnum scheduleTypeEnum = ScheduleTypeEnum.match(task.getScheduleType(), null); + if (ScheduleTypeEnum.CRON == scheduleTypeEnum) { + return new CronExpression(task.getScheduleConf()).getNextValidTimeAfter(fromTime); + } + + return null; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskStarter.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskStarter.java new file mode 100644 index 00000000..046d88ab --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskStarter.java @@ -0,0 +1,35 @@ +package com.zmops.iot.web.schedule; + +import com.zmops.iot.schedule.config.ScheduleConfig; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.stereotype.Component; + +/** + * @author nantian created at 2021/11/12 22:35 + */ + +@Component +public class TaskStarter implements InitializingBean, DisposableBean { + + private TaskTriggerPool triggerPool; + private TaskScheduleImpl schedule; + + @Override + public void destroy() throws Exception { + schedule.toStop(); + triggerPool.stop(); + } + + @Override + public void afterPropertiesSet() throws Exception { + + ScheduleConfig scheduleConfig = new ScheduleConfig(); + + triggerPool = new TaskTriggerPool(scheduleConfig); + triggerPool.start(); + + schedule = new TaskScheduleImpl(scheduleConfig); + schedule.start(); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java new file mode 100644 index 00000000..e4fc6e8a --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java @@ -0,0 +1,100 @@ +package com.zmops.iot.web.schedule; + +import com.zmops.iot.schedule.config.ScheduleConfig; +import lombok.extern.slf4j.Slf4j; + +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author nantian created at 2021/11/12 22:10 + */ + +@Slf4j +public class TaskTriggerPool { + + private ThreadPoolExecutor fastTriggerPool = null; + private ThreadPoolExecutor slowTriggerPool = null; + + + private final ScheduleConfig scheduleConfig; + + public TaskTriggerPool(ScheduleConfig scheduleConfig) { + this.scheduleConfig = scheduleConfig; + helper = this; + } + + public void start() { + fastTriggerPool = new ThreadPoolExecutor( + 10, + scheduleConfig.getTriggerPoolFastMax(), + 60L, + TimeUnit.SECONDS, + new LinkedBlockingQueue<>(1000), + r -> new Thread(r, "JobTriggerPoolHelper-fastTriggerPool-" + r.hashCode())); + + slowTriggerPool = new ThreadPoolExecutor( + 10, + scheduleConfig.getTriggerPoolSlowMax(), + 60L, + TimeUnit.SECONDS, + new LinkedBlockingQueue<>(2000), + r -> new Thread(r, "JobTriggerPoolHelper-slowTriggerPool-" + r.hashCode())); + } + + + public void stop() { + fastTriggerPool.shutdownNow(); + slowTriggerPool.shutdownNow(); + } + + private volatile long minTim = System.currentTimeMillis() / 60000; + private final ConcurrentMap jobTimeoutCountMap = new ConcurrentHashMap<>(); + + + public void addTrigger(final int jobId, + final TriggerTypeEnum triggerType, + final int failRetryCount, + final String executorShardingParam, + final String executorParam, + final String addressList) { + + ThreadPoolExecutor triggerPool_ = fastTriggerPool; + AtomicInteger jobTimeoutCount = jobTimeoutCountMap.get(jobId); + if (jobTimeoutCount != null && jobTimeoutCount.get() > 10) { // job-timeout 10 times in 1 min + triggerPool_ = slowTriggerPool; + } + + triggerPool_.execute(() -> { + long start = System.currentTimeMillis(); + + try { + System.out.println(123); + + } catch (Exception e) { + log.error(e.getMessage(), e); + } finally { + + long minTim_now = System.currentTimeMillis() / 60000; + if (minTim != minTim_now) { + minTim = minTim_now; + jobTimeoutCountMap.clear(); + } + + long cost = System.currentTimeMillis() - start; + if (cost > 500) { + AtomicInteger timeoutCount = jobTimeoutCountMap.putIfAbsent(jobId, new AtomicInteger(1)); + if (timeoutCount != null) { + timeoutCount.incrementAndGet(); + } + } + } + }); + } + + private static TaskTriggerPool helper; + + public static void trigger(int jobId, TriggerTypeEnum triggerType, int failRetryCount, String executorShardingParam, String executorParam, String addressList) { + helper.addTrigger(jobId, triggerType, failRetryCount, executorShardingParam, executorParam, addressList); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TriggerTypeEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TriggerTypeEnum.java new file mode 100644 index 00000000..57f365bd --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TriggerTypeEnum.java @@ -0,0 +1,24 @@ +package com.zmops.iot.web.schedule; + +/** + * 触发类型 + */ +public enum TriggerTypeEnum { + + MANUAL("Manual trigger"), + CRON("Cron trigger"), + RETRY("Fail retry trigger"), + PARENT("Parent job trigger"), + MISFIRE("Misfire compensation trigger"); + + private TriggerTypeEnum(String title) { + this.title = title; + } + + private final String title; + + public String getTitle() { + return title; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/config/ScheduleConfig.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/config/ScheduleConfig.java new file mode 100644 index 00000000..21e8936a --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/config/ScheduleConfig.java @@ -0,0 +1,40 @@ +package com.zmops.iot.schedule.config; + +import lombok.Data; + +/** + * @author nantian created at 2021/11/12 12:07 + */ + +@Data +public class ScheduleConfig { + + private int triggerPoolFastMax = 200; + + private int triggerPoolSlowMax = 100; + + private int logretentiondays = 30; + + + public int getTriggerPoolFastMax() { + if (triggerPoolFastMax < 200) { + return 200; + } + return triggerPoolFastMax; + } + + public int getTriggerPoolSlowMax() { + if (triggerPoolSlowMax < 100) { + return 100; + } + return triggerPoolSlowMax; + } + + + public int getLogretentiondays() { + if (logretentiondays < 7) { + return -1; // Limit greater than or equal to 7, otherwise close + } + return logretentiondays; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/cron/CronExpression.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/cron/CronExpression.java new file mode 100644 index 00000000..12739cc3 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/cron/CronExpression.java @@ -0,0 +1,1657 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +package com.zmops.iot.schedule.cron; + +import java.io.Serializable; +import java.text.ParseException; +import java.util.*; + +/** + * Provides a parser and evaluator for unix-like cron expressions. Cron + * expressions provide the ability to specify complex time combinations such as + * "At 8:00am every Monday through Friday" or "At 1:30am every + * last Friday of the month". + *

+ * Cron expressions are comprised of 6 required fields and one optional field + * separated by white space. The fields respectively are described as follows: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Field Name Allowed Values Allowed Special Characters
Seconds  + * 0-59  + * , - * /
Minutes  + * 0-59  + * , - * /
Hours  + * 0-23  + * , - * /
Day-of-month  + * 1-31  + * , - * ? / L W
Month  + * 0-11 or JAN-DEC  + * , - * /
Day-of-Week  + * 1-7 or SUN-SAT  + * , - * ? / L #
Year (Optional)  + * empty, 1970-2199  + * , - * /
+ *

+ * The '*' character is used to specify all values. For example, "*" + * in the minute field means "every minute". + *

+ * The '?' character is allowed for the day-of-month and day-of-week fields. It + * is used to specify 'no specific value'. This is useful when you need to + * specify something in one of the two fields, but not the other. + *

+ * The '-' character is used to specify ranges For example "10-12" in + * the hour field means "the hours 10, 11 and 12". + *

+ * The ',' character is used to specify additional values. For example + * "MON,WED,FRI" in the day-of-week field means "the days Monday, + * Wednesday, and Friday". + *

+ * The '/' character is used to specify increments. For example "0/15" + * in the seconds field means "the seconds 0, 15, 30, and 45". And + * "5/15" in the seconds field means "the seconds 5, 20, 35, and + * 50". Specifying '*' before the '/' is equivalent to specifying 0 is + * the value to start with. Essentially, for each field in the expression, there + * is a set of numbers that can be turned on or off. For seconds and minutes, + * the numbers range from 0 to 59. For hours 0 to 23, for days of the month 0 to + * 31, and for months 0 to 11 (JAN to DEC). The "/" character simply helps you turn + * on every "nth" value in the given set. Thus "7/6" in the + * month field only turns on month "7", it does NOT mean every 6th + * month, please note that subtlety. + *

+ * The 'L' character is allowed for the day-of-month and day-of-week fields. + * This character is short-hand for "last", but it has different + * meaning in each of the two fields. For example, the value "L" in + * the day-of-month field means "the last day of the month" - day 31 + * for January, day 28 for February on non-leap years. If used in the + * day-of-week field by itself, it simply means "7" or + * "SAT". But if used in the day-of-week field after another value, it + * means "the last xxx day of the month" - for example "6L" + * means "the last friday of the month". You can also specify an offset + * from the last day of the month, such as "L-3" which would mean the third-to-last + * day of the calendar month. When using the 'L' option, it is important not to + * specify lists, or ranges of values, as you'll get confusing/unexpected results. + *

+ * The 'W' character is allowed for the day-of-month field. This character + * is used to specify the weekday (Monday-Friday) nearest the given day. As an + * example, if you were to specify "15W" as the value for the + * day-of-month field, the meaning is: "the nearest weekday to the 15th of + * the month". So if the 15th is a Saturday, the trigger will fire on + * Friday the 14th. If the 15th is a Sunday, the trigger will fire on Monday the + * 16th. If the 15th is a Tuesday, then it will fire on Tuesday the 15th. + * However if you specify "1W" as the value for day-of-month, and the + * 1st is a Saturday, the trigger will fire on Monday the 3rd, as it will not + * 'jump' over the boundary of a month's days. The 'W' character can only be + * specified when the day-of-month is a single day, not a range or list of days. + *

+ * The 'L' and 'W' characters can also be combined for the day-of-month + * expression to yield 'LW', which translates to "last weekday of the + * month". + *

+ * The '#' character is allowed for the day-of-week field. This character is + * used to specify "the nth" XXX day of the month. For example, the + * value of "6#3" in the day-of-week field means the third Friday of + * the month (day 6 = Friday and "#3" = the 3rd one in the month). + * Other examples: "2#1" = the first Monday of the month and + * "4#5" = the fifth Wednesday of the month. Note that if you specify + * "#5" and there is not 5 of the given day-of-week in the month, then + * no firing will occur that month. If the '#' character is used, there can + * only be one expression in the day-of-week field ("3#1,6#3" is + * not valid, since there are two expressions). + *

+ * + *

+ * The legal characters and the names of months and days of the week are not + * case sensitive. + * + *

+ * NOTES: + *

    + *
  • Support for specifying both a day-of-week and a day-of-month value is + * not complete (you'll need to use the '?' character in one of these fields). + *
  • + *
  • Overflowing ranges is supported - that is, having a larger number on + * the left hand side than the right. You might do 22-2 to catch 10 o'clock + * at night until 2 o'clock in the morning, or you might have NOV-FEB. It is + * very important to note that overuse of overflowing ranges creates ranges + * that don't make sense and no effort has been made to determine which + * interpretation CronExpression chooses. An example would be + * "0 0 14-6 ? * FRI-MON".
  • + *
+ *

+ * + * + * @author Sharada Jambula, James House + * @author Contributions from Mads Henderson + * @author Refactoring from CronTrigger to CronExpression by Aaron Craven + * + * Borrowed from quartz v2.3.1 + * + */ +public final class CronExpression implements Serializable, Cloneable { + + private static final long serialVersionUID = 12423409423L; + + protected static final int SECOND = 0; + protected static final int MINUTE = 1; + protected static final int HOUR = 2; + protected static final int DAY_OF_MONTH = 3; + protected static final int MONTH = 4; + protected static final int DAY_OF_WEEK = 5; + protected static final int YEAR = 6; + protected static final int ALL_SPEC_INT = 99; // '*' + protected static final int NO_SPEC_INT = 98; // '?' + protected static final Integer ALL_SPEC = ALL_SPEC_INT; + protected static final Integer NO_SPEC = NO_SPEC_INT; + + protected static final Map monthMap = new HashMap(20); + protected static final Map dayMap = new HashMap(60); + static { + monthMap.put("JAN", 0); + monthMap.put("FEB", 1); + monthMap.put("MAR", 2); + monthMap.put("APR", 3); + monthMap.put("MAY", 4); + monthMap.put("JUN", 5); + monthMap.put("JUL", 6); + monthMap.put("AUG", 7); + monthMap.put("SEP", 8); + monthMap.put("OCT", 9); + monthMap.put("NOV", 10); + monthMap.put("DEC", 11); + + dayMap.put("SUN", 1); + dayMap.put("MON", 2); + dayMap.put("TUE", 3); + dayMap.put("WED", 4); + dayMap.put("THU", 5); + dayMap.put("FRI", 6); + dayMap.put("SAT", 7); + } + + private final String cronExpression; + private TimeZone timeZone = null; + protected transient TreeSet seconds; + protected transient TreeSet minutes; + protected transient TreeSet hours; + protected transient TreeSet daysOfMonth; + protected transient TreeSet months; + protected transient TreeSet daysOfWeek; + protected transient TreeSet years; + + protected transient boolean lastdayOfWeek = false; + protected transient int nthdayOfWeek = 0; + protected transient boolean lastdayOfMonth = false; + protected transient boolean nearestWeekday = false; + protected transient int lastdayOffset = 0; + protected transient boolean expressionParsed = false; + + public static final int MAX_YEAR = Calendar.getInstance().get(Calendar.YEAR) + 100; + + /** + * Constructs a new CronExpression based on the specified + * parameter. + * + * @param cronExpression String representation of the cron expression the + * new object should represent + * @throws ParseException + * if the string expression cannot be parsed into a valid + * CronExpression + */ + public CronExpression(String cronExpression) throws ParseException { + if (cronExpression == null) { + throw new IllegalArgumentException("cronExpression cannot be null"); + } + + this.cronExpression = cronExpression.toUpperCase(Locale.US); + + buildExpression(this.cronExpression); + } + + /** + * Constructs a new {@code CronExpression} as a copy of an existing + * instance. + * + * @param expression + * The existing cron expression to be copied + */ + public CronExpression(CronExpression expression) { + /* + * We don't call the other constructor here since we need to swallow the + * ParseException. We also elide some of the sanity checking as it is + * not logically trippable. + */ + this.cronExpression = expression.getCronExpression(); + try { + buildExpression(cronExpression); + } catch (ParseException ex) { + throw new AssertionError(); + } + if (expression.getTimeZone() != null) { + setTimeZone((TimeZone) expression.getTimeZone().clone()); + } + } + + /** + * Indicates whether the given date satisfies the cron expression. Note that + * milliseconds are ignored, so two Dates falling on different milliseconds + * of the same second will always have the same result here. + * + * @param date the date to evaluate + * @return a boolean indicating whether the given date satisfies the cron + * expression + */ + public boolean isSatisfiedBy(Date date) { + Calendar testDateCal = Calendar.getInstance(getTimeZone()); + testDateCal.setTime(date); + testDateCal.set(Calendar.MILLISECOND, 0); + Date originalDate = testDateCal.getTime(); + + testDateCal.add(Calendar.SECOND, -1); + + Date timeAfter = getTimeAfter(testDateCal.getTime()); + + return ((timeAfter != null) && (timeAfter.equals(originalDate))); + } + + /** + * Returns the next date/time after the given date/time which + * satisfies the cron expression. + * + * @param date the date/time at which to begin the search for the next valid + * date/time + * @return the next valid date/time + */ + public Date getNextValidTimeAfter(Date date) { + return getTimeAfter(date); + } + + /** + * Returns the next date/time after the given date/time which does + * not satisfy the expression + * + * @param date the date/time at which to begin the search for the next + * invalid date/time + * @return the next valid date/time + */ + public Date getNextInvalidTimeAfter(Date date) { + long difference = 1000; + + //move back to the nearest second so differences will be accurate + Calendar adjustCal = Calendar.getInstance(getTimeZone()); + adjustCal.setTime(date); + adjustCal.set(Calendar.MILLISECOND, 0); + Date lastDate = adjustCal.getTime(); + + Date newDate; + + //FUTURE_TODO: (QUARTZ-481) IMPROVE THIS! The following is a BAD solution to this problem. Performance will be very bad here, depending on the cron expression. It is, however A solution. + + //keep getting the next included time until it's farther than one second + // apart. At that point, lastDate is the last valid fire time. We return + // the second immediately following it. + while (difference == 1000) { + newDate = getTimeAfter(lastDate); + if(newDate == null) + break; + + difference = newDate.getTime() - lastDate.getTime(); + + if (difference == 1000) { + lastDate = newDate; + } + } + + return new Date(lastDate.getTime() + 1000); + } + + /** + * Returns the time zone for which this CronExpression + * will be resolved. + */ + public TimeZone getTimeZone() { + if (timeZone == null) { + timeZone = TimeZone.getDefault(); + } + + return timeZone; + } + + /** + * Sets the time zone for which this CronExpression + * will be resolved. + */ + public void setTimeZone(TimeZone timeZone) { + this.timeZone = timeZone; + } + + /** + * Returns the string representation of the CronExpression + * + * @return a string representation of the CronExpression + */ + @Override + public String toString() { + return cronExpression; + } + + /** + * Indicates whether the specified cron expression can be parsed into a + * valid cron expression + * + * @param cronExpression the expression to evaluate + * @return a boolean indicating whether the given expression is a valid cron + * expression + */ + public static boolean isValidExpression(String cronExpression) { + + try { + new CronExpression(cronExpression); + } catch (ParseException pe) { + return false; + } + + return true; + } + + public static void validateExpression(String cronExpression) throws ParseException { + + new CronExpression(cronExpression); + } + + + //////////////////////////////////////////////////////////////////////////// + // + // Expression Parsing Functions + // + //////////////////////////////////////////////////////////////////////////// + + protected void buildExpression(String expression) throws ParseException { + expressionParsed = true; + + try { + + if (seconds == null) { + seconds = new TreeSet(); + } + if (minutes == null) { + minutes = new TreeSet(); + } + if (hours == null) { + hours = new TreeSet(); + } + if (daysOfMonth == null) { + daysOfMonth = new TreeSet(); + } + if (months == null) { + months = new TreeSet(); + } + if (daysOfWeek == null) { + daysOfWeek = new TreeSet(); + } + if (years == null) { + years = new TreeSet(); + } + + int exprOn = SECOND; + + StringTokenizer exprsTok = new StringTokenizer(expression, " \t", + false); + + while (exprsTok.hasMoreTokens() && exprOn <= YEAR) { + String expr = exprsTok.nextToken().trim(); + + // throw an exception if L is used with other days of the month + if(exprOn == DAY_OF_MONTH && expr.indexOf('L') != -1 && expr.length() > 1 && expr.contains(",")) { + throw new ParseException("Support for specifying 'L' and 'LW' with other days of the month is not implemented", -1); + } + // throw an exception if L is used with other days of the week + if(exprOn == DAY_OF_WEEK && expr.indexOf('L') != -1 && expr.length() > 1 && expr.contains(",")) { + throw new ParseException("Support for specifying 'L' with other days of the week is not implemented", -1); + } + if(exprOn == DAY_OF_WEEK && expr.indexOf('#') != -1 && expr.indexOf('#', expr.indexOf('#') +1) != -1) { + throw new ParseException("Support for specifying multiple \"nth\" days is not implemented.", -1); + } + + StringTokenizer vTok = new StringTokenizer(expr, ","); + while (vTok.hasMoreTokens()) { + String v = vTok.nextToken(); + storeExpressionVals(0, v, exprOn); + } + + exprOn++; + } + + if (exprOn <= DAY_OF_WEEK) { + throw new ParseException("Unexpected end of expression.", + expression.length()); + } + + if (exprOn <= YEAR) { + storeExpressionVals(0, "*", YEAR); + } + + TreeSet dow = getSet(DAY_OF_WEEK); + TreeSet dom = getSet(DAY_OF_MONTH); + + // Copying the logic from the UnsupportedOperationException below + boolean dayOfMSpec = !dom.contains(NO_SPEC); + boolean dayOfWSpec = !dow.contains(NO_SPEC); + + if (!dayOfMSpec || dayOfWSpec) { + if (!dayOfWSpec || dayOfMSpec) { + throw new ParseException( + "Support for specifying both a day-of-week AND a day-of-month parameter is not implemented.", 0); + } + } + } catch (ParseException pe) { + throw pe; + } catch (Exception e) { + throw new ParseException("Illegal cron expression format (" + + e.toString() + ")", 0); + } + } + + protected int storeExpressionVals(int pos, String s, int type) + throws ParseException { + + int incr = 0; + int i = skipWhiteSpace(pos, s); + if (i >= s.length()) { + return i; + } + char c = s.charAt(i); + if ((c >= 'A') && (c <= 'Z') && (!s.equals("L")) && (!s.equals("LW")) && (!s.matches("^L-[0-9]*[W]?"))) { + String sub = s.substring(i, i + 3); + int sval = -1; + int eval = -1; + if (type == MONTH) { + sval = getMonthNumber(sub) + 1; + if (sval <= 0) { + throw new ParseException("Invalid Month value: '" + sub + "'", i); + } + if (s.length() > i + 3) { + c = s.charAt(i + 3); + if (c == '-') { + i += 4; + sub = s.substring(i, i + 3); + eval = getMonthNumber(sub) + 1; + if (eval <= 0) { + throw new ParseException("Invalid Month value: '" + sub + "'", i); + } + } + } + } else if (type == DAY_OF_WEEK) { + sval = getDayOfWeekNumber(sub); + if (sval < 0) { + throw new ParseException("Invalid Day-of-Week value: '" + + sub + "'", i); + } + if (s.length() > i + 3) { + c = s.charAt(i + 3); + if (c == '-') { + i += 4; + sub = s.substring(i, i + 3); + eval = getDayOfWeekNumber(sub); + if (eval < 0) { + throw new ParseException( + "Invalid Day-of-Week value: '" + sub + + "'", i); + } + } else if (c == '#') { + try { + i += 4; + nthdayOfWeek = Integer.parseInt(s.substring(i)); + if (nthdayOfWeek < 1 || nthdayOfWeek > 5) { + throw new Exception(); + } + } catch (Exception e) { + throw new ParseException( + "A numeric value between 1 and 5 must follow the '#' option", + i); + } + } else if (c == 'L') { + lastdayOfWeek = true; + i++; + } + } + + } else { + throw new ParseException( + "Illegal characters for this position: '" + sub + "'", + i); + } + if (eval != -1) { + incr = 1; + } + addToSet(sval, eval, incr, type); + return (i + 3); + } + + if (c == '?') { + i++; + if ((i + 1) < s.length() + && (s.charAt(i) != ' ' && s.charAt(i + 1) != '\t')) { + throw new ParseException("Illegal character after '?': " + + s.charAt(i), i); + } + if (type != DAY_OF_WEEK && type != DAY_OF_MONTH) { + throw new ParseException( + "'?' can only be specified for Day-of-Month or Day-of-Week.", + i); + } + if (type == DAY_OF_WEEK && !lastdayOfMonth) { + int val = daysOfMonth.last(); + if (val == NO_SPEC_INT) { + throw new ParseException( + "'?' can only be specified for Day-of-Month -OR- Day-of-Week.", + i); + } + } + + addToSet(NO_SPEC_INT, -1, 0, type); + return i; + } + + if (c == '*' || c == '/') { + if (c == '*' && (i + 1) >= s.length()) { + addToSet(ALL_SPEC_INT, -1, incr, type); + return i + 1; + } else if (c == '/' + && ((i + 1) >= s.length() || s.charAt(i + 1) == ' ' || s + .charAt(i + 1) == '\t')) { + throw new ParseException("'/' must be followed by an integer.", i); + } else if (c == '*') { + i++; + } + c = s.charAt(i); + if (c == '/') { // is an increment specified? + i++; + if (i >= s.length()) { + throw new ParseException("Unexpected end of string.", i); + } + + incr = getNumericValue(s, i); + + i++; + if (incr > 10) { + i++; + } + checkIncrementRange(incr, type, i); + } else { + incr = 1; + } + + addToSet(ALL_SPEC_INT, -1, incr, type); + return i; + } else if (c == 'L') { + i++; + if (type == DAY_OF_MONTH) { + lastdayOfMonth = true; + } + if (type == DAY_OF_WEEK) { + addToSet(7, 7, 0, type); + } + if(type == DAY_OF_MONTH && s.length() > i) { + c = s.charAt(i); + if(c == '-') { + ValueSet vs = getValue(0, s, i+1); + lastdayOffset = vs.value; + if(lastdayOffset > 30) + throw new ParseException("Offset from last day must be <= 30", i+1); + i = vs.pos; + } + if(s.length() > i) { + c = s.charAt(i); + if(c == 'W') { + nearestWeekday = true; + i++; + } + } + } + return i; + } else if (c >= '0' && c <= '9') { + int val = Integer.parseInt(String.valueOf(c)); + i++; + if (i >= s.length()) { + addToSet(val, -1, -1, type); + } else { + c = s.charAt(i); + if (c >= '0' && c <= '9') { + ValueSet vs = getValue(val, s, i); + val = vs.value; + i = vs.pos; + } + i = checkNext(i, s, val, type); + return i; + } + } else { + throw new ParseException("Unexpected character: " + c, i); + } + + return i; + } + + private void checkIncrementRange(int incr, int type, int idxPos) throws ParseException { + if (incr > 59 && (type == SECOND || type == MINUTE)) { + throw new ParseException("Increment > 60 : " + incr, idxPos); + } else if (incr > 23 && (type == HOUR)) { + throw new ParseException("Increment > 24 : " + incr, idxPos); + } else if (incr > 31 && (type == DAY_OF_MONTH)) { + throw new ParseException("Increment > 31 : " + incr, idxPos); + } else if (incr > 7 && (type == DAY_OF_WEEK)) { + throw new ParseException("Increment > 7 : " + incr, idxPos); + } else if (incr > 12 && (type == MONTH)) { + throw new ParseException("Increment > 12 : " + incr, idxPos); + } + } + + protected int checkNext(int pos, String s, int val, int type) + throws ParseException { + + int end = -1; + int i = pos; + + if (i >= s.length()) { + addToSet(val, end, -1, type); + return i; + } + + char c = s.charAt(pos); + + if (c == 'L') { + if (type == DAY_OF_WEEK) { + if(val < 1 || val > 7) + throw new ParseException("Day-of-Week values must be between 1 and 7", -1); + lastdayOfWeek = true; + } else { + throw new ParseException("'L' option is not valid here. (pos=" + i + ")", i); + } + TreeSet set = getSet(type); + set.add(val); + i++; + return i; + } + + if (c == 'W') { + if (type == DAY_OF_MONTH) { + nearestWeekday = true; + } else { + throw new ParseException("'W' option is not valid here. (pos=" + i + ")", i); + } + if(val > 31) + throw new ParseException("The 'W' option does not make sense with values larger than 31 (max number of days in a month)", i); + TreeSet set = getSet(type); + set.add(val); + i++; + return i; + } + + if (c == '#') { + if (type != DAY_OF_WEEK) { + throw new ParseException("'#' option is not valid here. (pos=" + i + ")", i); + } + i++; + try { + nthdayOfWeek = Integer.parseInt(s.substring(i)); + if (nthdayOfWeek < 1 || nthdayOfWeek > 5) { + throw new Exception(); + } + } catch (Exception e) { + throw new ParseException( + "A numeric value between 1 and 5 must follow the '#' option", + i); + } + + TreeSet set = getSet(type); + set.add(val); + i++; + return i; + } + + if (c == '-') { + i++; + c = s.charAt(i); + int v = Integer.parseInt(String.valueOf(c)); + end = v; + i++; + if (i >= s.length()) { + addToSet(val, end, 1, type); + return i; + } + c = s.charAt(i); + if (c >= '0' && c <= '9') { + ValueSet vs = getValue(v, s, i); + end = vs.value; + i = vs.pos; + } + if (i < s.length() && ((c = s.charAt(i)) == '/')) { + i++; + c = s.charAt(i); + int v2 = Integer.parseInt(String.valueOf(c)); + i++; + if (i >= s.length()) { + addToSet(val, end, v2, type); + return i; + } + c = s.charAt(i); + if (c >= '0' && c <= '9') { + ValueSet vs = getValue(v2, s, i); + int v3 = vs.value; + addToSet(val, end, v3, type); + i = vs.pos; + return i; + } else { + addToSet(val, end, v2, type); + return i; + } + } else { + addToSet(val, end, 1, type); + return i; + } + } + + if (c == '/') { + if ((i + 1) >= s.length() || s.charAt(i + 1) == ' ' || s.charAt(i + 1) == '\t') { + throw new ParseException("'/' must be followed by an integer.", i); + } + + i++; + c = s.charAt(i); + int v2 = Integer.parseInt(String.valueOf(c)); + i++; + if (i >= s.length()) { + checkIncrementRange(v2, type, i); + addToSet(val, end, v2, type); + return i; + } + c = s.charAt(i); + if (c >= '0' && c <= '9') { + ValueSet vs = getValue(v2, s, i); + int v3 = vs.value; + checkIncrementRange(v3, type, i); + addToSet(val, end, v3, type); + i = vs.pos; + return i; + } else { + throw new ParseException("Unexpected character '" + c + "' after '/'", i); + } + } + + addToSet(val, end, 0, type); + i++; + return i; + } + + public String getCronExpression() { + return cronExpression; + } + + public String getExpressionSummary() { + StringBuilder buf = new StringBuilder(); + + buf.append("seconds: "); + buf.append(getExpressionSetSummary(seconds)); + buf.append("\n"); + buf.append("minutes: "); + buf.append(getExpressionSetSummary(minutes)); + buf.append("\n"); + buf.append("hours: "); + buf.append(getExpressionSetSummary(hours)); + buf.append("\n"); + buf.append("daysOfMonth: "); + buf.append(getExpressionSetSummary(daysOfMonth)); + buf.append("\n"); + buf.append("months: "); + buf.append(getExpressionSetSummary(months)); + buf.append("\n"); + buf.append("daysOfWeek: "); + buf.append(getExpressionSetSummary(daysOfWeek)); + buf.append("\n"); + buf.append("lastdayOfWeek: "); + buf.append(lastdayOfWeek); + buf.append("\n"); + buf.append("nearestWeekday: "); + buf.append(nearestWeekday); + buf.append("\n"); + buf.append("NthDayOfWeek: "); + buf.append(nthdayOfWeek); + buf.append("\n"); + buf.append("lastdayOfMonth: "); + buf.append(lastdayOfMonth); + buf.append("\n"); + buf.append("years: "); + buf.append(getExpressionSetSummary(years)); + buf.append("\n"); + + return buf.toString(); + } + + protected String getExpressionSetSummary(java.util.Set set) { + + if (set.contains(NO_SPEC)) { + return "?"; + } + if (set.contains(ALL_SPEC)) { + return "*"; + } + + StringBuilder buf = new StringBuilder(); + + Iterator itr = set.iterator(); + boolean first = true; + while (itr.hasNext()) { + Integer iVal = itr.next(); + String val = iVal.toString(); + if (!first) { + buf.append(","); + } + buf.append(val); + first = false; + } + + return buf.toString(); + } + + protected String getExpressionSetSummary(java.util.ArrayList list) { + + if (list.contains(NO_SPEC)) { + return "?"; + } + if (list.contains(ALL_SPEC)) { + return "*"; + } + + StringBuilder buf = new StringBuilder(); + + Iterator itr = list.iterator(); + boolean first = true; + while (itr.hasNext()) { + Integer iVal = itr.next(); + String val = iVal.toString(); + if (!first) { + buf.append(","); + } + buf.append(val); + first = false; + } + + return buf.toString(); + } + + protected int skipWhiteSpace(int i, String s) { + for (; i < s.length() && (s.charAt(i) == ' ' || s.charAt(i) == '\t'); i++) { + } + + return i; + } + + protected int findNextWhiteSpace(int i, String s) { + for (; i < s.length() && (s.charAt(i) != ' ' || s.charAt(i) != '\t'); i++) { + } + + return i; + } + + protected void addToSet(int val, int end, int incr, int type) + throws ParseException { + + TreeSet set = getSet(type); + + if (type == SECOND || type == MINUTE) { + if ((val < 0 || val > 59 || end > 59) && (val != ALL_SPEC_INT)) { + throw new ParseException( + "Minute and Second values must be between 0 and 59", + -1); + } + } else if (type == HOUR) { + if ((val < 0 || val > 23 || end > 23) && (val != ALL_SPEC_INT)) { + throw new ParseException( + "Hour values must be between 0 and 23", -1); + } + } else if (type == DAY_OF_MONTH) { + if ((val < 1 || val > 31 || end > 31) && (val != ALL_SPEC_INT) + && (val != NO_SPEC_INT)) { + throw new ParseException( + "Day of month values must be between 1 and 31", -1); + } + } else if (type == MONTH) { + if ((val < 1 || val > 12 || end > 12) && (val != ALL_SPEC_INT)) { + throw new ParseException( + "Month values must be between 1 and 12", -1); + } + } else if (type == DAY_OF_WEEK) { + if ((val == 0 || val > 7 || end > 7) && (val != ALL_SPEC_INT) + && (val != NO_SPEC_INT)) { + throw new ParseException( + "Day-of-Week values must be between 1 and 7", -1); + } + } + + if ((incr == 0 || incr == -1) && val != ALL_SPEC_INT) { + if (val != -1) { + set.add(val); + } else { + set.add(NO_SPEC); + } + + return; + } + + int startAt = val; + int stopAt = end; + + if (val == ALL_SPEC_INT && incr <= 0) { + incr = 1; + set.add(ALL_SPEC); // put in a marker, but also fill values + } + + if (type == SECOND || type == MINUTE) { + if (stopAt == -1) { + stopAt = 59; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 0; + } + } else if (type == HOUR) { + if (stopAt == -1) { + stopAt = 23; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 0; + } + } else if (type == DAY_OF_MONTH) { + if (stopAt == -1) { + stopAt = 31; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1; + } + } else if (type == MONTH) { + if (stopAt == -1) { + stopAt = 12; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1; + } + } else if (type == DAY_OF_WEEK) { + if (stopAt == -1) { + stopAt = 7; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1; + } + } else if (type == YEAR) { + if (stopAt == -1) { + stopAt = MAX_YEAR; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1970; + } + } + + // if the end of the range is before the start, then we need to overflow into + // the next day, month etc. This is done by adding the maximum amount for that + // type, and using modulus max to determine the value being added. + int max = -1; + if (stopAt < startAt) { + switch (type) { + case SECOND : max = 60; break; + case MINUTE : max = 60; break; + case HOUR : max = 24; break; + case MONTH : max = 12; break; + case DAY_OF_WEEK : max = 7; break; + case DAY_OF_MONTH : max = 31; break; + case YEAR : throw new IllegalArgumentException("Start year must be less than stop year"); + default : throw new IllegalArgumentException("Unexpected type encountered"); + } + stopAt += max; + } + + for (int i = startAt; i <= stopAt; i += incr) { + if (max == -1) { + // ie: there's no max to overflow over + set.add(i); + } else { + // take the modulus to get the real value + int i2 = i % max; + + // 1-indexed ranges should not include 0, and should include their max + if (i2 == 0 && (type == MONTH || type == DAY_OF_WEEK || type == DAY_OF_MONTH) ) { + i2 = max; + } + + set.add(i2); + } + } + } + + TreeSet getSet(int type) { + switch (type) { + case SECOND: + return seconds; + case MINUTE: + return minutes; + case HOUR: + return hours; + case DAY_OF_MONTH: + return daysOfMonth; + case MONTH: + return months; + case DAY_OF_WEEK: + return daysOfWeek; + case YEAR: + return years; + default: + return null; + } + } + + protected ValueSet getValue(int v, String s, int i) { + char c = s.charAt(i); + StringBuilder s1 = new StringBuilder(String.valueOf(v)); + while (c >= '0' && c <= '9') { + s1.append(c); + i++; + if (i >= s.length()) { + break; + } + c = s.charAt(i); + } + ValueSet val = new ValueSet(); + + val.pos = (i < s.length()) ? i : i + 1; + val.value = Integer.parseInt(s1.toString()); + return val; + } + + protected int getNumericValue(String s, int i) { + int endOfVal = findNextWhiteSpace(i, s); + String val = s.substring(i, endOfVal); + return Integer.parseInt(val); + } + + protected int getMonthNumber(String s) { + Integer integer = monthMap.get(s); + + if (integer == null) { + return -1; + } + + return integer; + } + + protected int getDayOfWeekNumber(String s) { + Integer integer = dayMap.get(s); + + if (integer == null) { + return -1; + } + + return integer; + } + + //////////////////////////////////////////////////////////////////////////// + // + // Computation Functions + // + //////////////////////////////////////////////////////////////////////////// + + public Date getTimeAfter(Date afterTime) { + + // Computation is based on Gregorian year only. + Calendar cl = new java.util.GregorianCalendar(getTimeZone()); + + // move ahead one second, since we're computing the time *after* the + // given time + afterTime = new Date(afterTime.getTime() + 1000); + // CronTrigger does not deal with milliseconds + cl.setTime(afterTime); + cl.set(Calendar.MILLISECOND, 0); + + boolean gotOne = false; + // loop until we've computed the next time, or we've past the endTime + while (!gotOne) { + + //if (endTime != null && cl.getTime().after(endTime)) return null; + if(cl.get(Calendar.YEAR) > 2999) { // prevent endless loop... + return null; + } + + SortedSet st = null; + int t = 0; + + int sec = cl.get(Calendar.SECOND); + int min = cl.get(Calendar.MINUTE); + + // get second................................................. + st = seconds.tailSet(sec); + if (st != null && st.size() != 0) { + sec = st.first(); + } else { + sec = seconds.first(); + min++; + cl.set(Calendar.MINUTE, min); + } + cl.set(Calendar.SECOND, sec); + + min = cl.get(Calendar.MINUTE); + int hr = cl.get(Calendar.HOUR_OF_DAY); + t = -1; + + // get minute................................................. + st = minutes.tailSet(min); + if (st != null && st.size() != 0) { + t = min; + min = st.first(); + } else { + min = minutes.first(); + hr++; + } + if (min != t) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, min); + setCalendarHour(cl, hr); + continue; + } + cl.set(Calendar.MINUTE, min); + + hr = cl.get(Calendar.HOUR_OF_DAY); + int day = cl.get(Calendar.DAY_OF_MONTH); + t = -1; + + // get hour................................................... + st = hours.tailSet(hr); + if (st != null && st.size() != 0) { + t = hr; + hr = st.first(); + } else { + hr = hours.first(); + day++; + } + if (hr != t) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.DAY_OF_MONTH, day); + setCalendarHour(cl, hr); + continue; + } + cl.set(Calendar.HOUR_OF_DAY, hr); + + day = cl.get(Calendar.DAY_OF_MONTH); + int mon = cl.get(Calendar.MONTH) + 1; + // '+ 1' because calendar is 0-based for this field, and we are + // 1-based + t = -1; + int tmon = mon; + + // get day................................................... + boolean dayOfMSpec = !daysOfMonth.contains(NO_SPEC); + boolean dayOfWSpec = !daysOfWeek.contains(NO_SPEC); + if (dayOfMSpec && !dayOfWSpec) { // get day by day of month rule + st = daysOfMonth.tailSet(day); + if (lastdayOfMonth) { + if(!nearestWeekday) { + t = day; + day = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + day -= lastdayOffset; + if(t > day) { + mon++; + if(mon > 12) { + mon = 1; + tmon = 3333; // ensure test of mon != tmon further below fails + cl.add(Calendar.YEAR, 1); + } + day = 1; + } + } else { + t = day; + day = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + day -= lastdayOffset; + + Calendar tcal = Calendar.getInstance(getTimeZone()); + tcal.set(Calendar.SECOND, 0); + tcal.set(Calendar.MINUTE, 0); + tcal.set(Calendar.HOUR_OF_DAY, 0); + tcal.set(Calendar.DAY_OF_MONTH, day); + tcal.set(Calendar.MONTH, mon - 1); + tcal.set(Calendar.YEAR, cl.get(Calendar.YEAR)); + + int ldom = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + int dow = tcal.get(Calendar.DAY_OF_WEEK); + + if(dow == Calendar.SATURDAY && day == 1) { + day += 2; + } else if(dow == Calendar.SATURDAY) { + day -= 1; + } else if(dow == Calendar.SUNDAY && day == ldom) { + day -= 2; + } else if(dow == Calendar.SUNDAY) { + day += 1; + } + + tcal.set(Calendar.SECOND, sec); + tcal.set(Calendar.MINUTE, min); + tcal.set(Calendar.HOUR_OF_DAY, hr); + tcal.set(Calendar.DAY_OF_MONTH, day); + tcal.set(Calendar.MONTH, mon - 1); + Date nTime = tcal.getTime(); + if(nTime.before(afterTime)) { + day = 1; + mon++; + } + } + } else if(nearestWeekday) { + t = day; + day = daysOfMonth.first(); + + Calendar tcal = Calendar.getInstance(getTimeZone()); + tcal.set(Calendar.SECOND, 0); + tcal.set(Calendar.MINUTE, 0); + tcal.set(Calendar.HOUR_OF_DAY, 0); + tcal.set(Calendar.DAY_OF_MONTH, day); + tcal.set(Calendar.MONTH, mon - 1); + tcal.set(Calendar.YEAR, cl.get(Calendar.YEAR)); + + int ldom = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + int dow = tcal.get(Calendar.DAY_OF_WEEK); + + if(dow == Calendar.SATURDAY && day == 1) { + day += 2; + } else if(dow == Calendar.SATURDAY) { + day -= 1; + } else if(dow == Calendar.SUNDAY && day == ldom) { + day -= 2; + } else if(dow == Calendar.SUNDAY) { + day += 1; + } + + + tcal.set(Calendar.SECOND, sec); + tcal.set(Calendar.MINUTE, min); + tcal.set(Calendar.HOUR_OF_DAY, hr); + tcal.set(Calendar.DAY_OF_MONTH, day); + tcal.set(Calendar.MONTH, mon - 1); + Date nTime = tcal.getTime(); + if(nTime.before(afterTime)) { + day = daysOfMonth.first(); + mon++; + } + } else if (st != null && st.size() != 0) { + t = day; + day = st.first(); + // make sure we don't over-run a short month, such as february + int lastDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + if (day > lastDay) { + day = daysOfMonth.first(); + mon++; + } + } else { + day = daysOfMonth.first(); + mon++; + } + + if (day != t || mon != tmon) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, day); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' because calendar is 0-based for this field, and we + // are 1-based + continue; + } + } else if (dayOfWSpec && !dayOfMSpec) { // get day by day of week rule + if (lastdayOfWeek) { // are we looking for the last XXX day of + // the month? + int dow = daysOfWeek.first(); // desired + // d-o-w + int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w + int daysToAdd = 0; + if (cDow < dow) { + daysToAdd = dow - cDow; + } + if (cDow > dow) { + daysToAdd = dow + (7 - cDow); + } + + int lDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + + if (day + daysToAdd > lDay) { // did we already miss the + // last one? + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, mon); + // no '- 1' here because we are promoting the month + continue; + } + + // find date of last occurrence of this day in this month... + while ((day + daysToAdd + 7) <= lDay) { + daysToAdd += 7; + } + + day += daysToAdd; + + if (daysToAdd > 0) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, day); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' here because we are not promoting the month + continue; + } + + } else if (nthdayOfWeek != 0) { + // are we looking for the Nth XXX day in the month? + int dow = daysOfWeek.first(); // desired + // d-o-w + int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w + int daysToAdd = 0; + if (cDow < dow) { + daysToAdd = dow - cDow; + } else if (cDow > dow) { + daysToAdd = dow + (7 - cDow); + } + + boolean dayShifted = false; + if (daysToAdd > 0) { + dayShifted = true; + } + + day += daysToAdd; + int weekOfMonth = day / 7; + if (day % 7 > 0) { + weekOfMonth++; + } + + daysToAdd = (nthdayOfWeek - weekOfMonth) * 7; + day += daysToAdd; + if (daysToAdd < 0 + || day > getLastDayOfMonth(mon, cl + .get(Calendar.YEAR))) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, mon); + // no '- 1' here because we are promoting the month + continue; + } else if (daysToAdd > 0 || dayShifted) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, day); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' here because we are NOT promoting the month + continue; + } + } else { + int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w + int dow = daysOfWeek.first(); // desired + // d-o-w + st = daysOfWeek.tailSet(cDow); + if (st != null && st.size() > 0) { + dow = st.first(); + } + + int daysToAdd = 0; + if (cDow < dow) { + daysToAdd = dow - cDow; + } + if (cDow > dow) { + daysToAdd = dow + (7 - cDow); + } + + int lDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + + if (day + daysToAdd > lDay) { // will we pass the end of + // the month? + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, mon); + // no '- 1' here because we are promoting the month + continue; + } else if (daysToAdd > 0) { // are we swithing days? + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, day + daysToAdd); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' because calendar is 0-based for this field, + // and we are 1-based + continue; + } + } + } else { // dayOfWSpec && !dayOfMSpec + throw new UnsupportedOperationException( + "Support for specifying both a day-of-week AND a day-of-month parameter is not implemented."); + } + cl.set(Calendar.DAY_OF_MONTH, day); + + mon = cl.get(Calendar.MONTH) + 1; + // '+ 1' because calendar is 0-based for this field, and we are + // 1-based + int year = cl.get(Calendar.YEAR); + t = -1; + + // test for expressions that never generate a valid fire date, + // but keep looping... + if (year > MAX_YEAR) { + return null; + } + + // get month................................................... + st = months.tailSet(mon); + if (st != null && st.size() != 0) { + t = mon; + mon = st.first(); + } else { + mon = months.first(); + year++; + } + if (mon != t) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' because calendar is 0-based for this field, and we are + // 1-based + cl.set(Calendar.YEAR, year); + continue; + } + cl.set(Calendar.MONTH, mon - 1); + // '- 1' because calendar is 0-based for this field, and we are + // 1-based + + year = cl.get(Calendar.YEAR); + t = -1; + + // get year................................................... + st = years.tailSet(year); + if (st != null && st.size() != 0) { + t = year; + year = st.first(); + } else { + return null; // ran out of years... + } + + if (year != t) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, 0); + // '- 1' because calendar is 0-based for this field, and we are + // 1-based + cl.set(Calendar.YEAR, year); + continue; + } + cl.set(Calendar.YEAR, year); + + gotOne = true; + } // while( !done ) + + return cl.getTime(); + } + + /** + * Advance the calendar to the particular hour paying particular attention + * to daylight saving problems. + * + * @param cal the calendar to operate on + * @param hour the hour to set + */ + protected void setCalendarHour(Calendar cal, int hour) { + cal.set(Calendar.HOUR_OF_DAY, hour); + if (cal.get(Calendar.HOUR_OF_DAY) != hour && hour != 24) { + cal.set(Calendar.HOUR_OF_DAY, hour + 1); + } + } + + /** + * NOT YET IMPLEMENTED: Returns the time before the given time + * that the CronExpression matches. + */ + public Date getTimeBefore(Date endTime) { + // FUTURE_TODO: implement QUARTZ-423 + return null; + } + + /** + * NOT YET IMPLEMENTED: Returns the final time that the + * CronExpression will match. + */ + public Date getFinalFireTime() { + // FUTURE_TODO: implement QUARTZ-423 + return null; + } + + protected boolean isLeapYear(int year) { + return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)); + } + + protected int getLastDayOfMonth(int monthNum, int year) { + + switch (monthNum) { + case 1: + return 31; + case 2: + return (isLeapYear(year)) ? 29 : 28; + case 3: + return 31; + case 4: + return 30; + case 5: + return 31; + case 6: + return 30; + case 7: + return 31; + case 8: + return 31; + case 9: + return 30; + case 10: + return 31; + case 11: + return 30; + case 12: + return 31; + default: + throw new IllegalArgumentException("Illegal month number: " + + monthNum); + } + } + + + private void readObject(java.io.ObjectInputStream stream) + throws java.io.IOException, ClassNotFoundException { + + stream.defaultReadObject(); + try { + buildExpression(cronExpression); + } catch (Exception ignore) { + } // never happens + } + + @Override + @Deprecated + public Object clone() { + return new CronExpression(this); + } +} + +class ValueSet { + public int value; + + public int pos; +} From 804b535de01e5d5f62854877a5364dea97dc16bb Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 13 Nov 2021 12:04:24 +0800 Subject: [PATCH 643/763] [fix]: optimize schedule task info --- .../com/zmops/iot/domain}/schedule/Task.java | 25 +++++++++++++---- .../auth/LoginContextSpringSecutiryImpl.java | 5 ++++ .../iot/web/schedule/TaskScheduleImpl.java | 27 +++++++------------ .../iot/web/schedule/TaskTriggerPool.java | 7 +++-- 4 files changed, 37 insertions(+), 27 deletions(-) rename {zeus-webapp/src/main/java/com/zmops/iot/web => zeus-common/src/main/java/com/zmops/iot/domain}/schedule/Task.java (52%) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/Task.java b/zeus-common/src/main/java/com/zmops/iot/domain/schedule/Task.java similarity index 52% rename from zeus-webapp/src/main/java/com/zmops/iot/web/schedule/Task.java rename to zeus-common/src/main/java/com/zmops/iot/domain/schedule/Task.java index c0a5ec2e..368988d4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/Task.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/schedule/Task.java @@ -1,16 +1,30 @@ -package com.zmops.iot.web.schedule; +package com.zmops.iot.domain.schedule; -import lombok.Data; +import com.zmops.iot.domain.BaseEntity; +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; /** - * @author nantian created at 2021/11/12 19:11 + * @author nantian created at 2021/11/13 11:23 */ -@Data -public class Task { +@Getter +@Setter +@Table(name = "task_info") +@Entity +public class Task extends BaseEntity { + + @Id + @Column(name = "id", nullable = false) private Integer id; + private String scheduleType; // 调度类型 private String scheduleConf; // 调度配置,值含义取决于调度类型 private String misfireStrategy; // 调度过期策略 @@ -25,4 +39,5 @@ public class Task { private String remark; + private String executorParam; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/LoginContextSpringSecutiryImpl.java b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/LoginContextSpringSecutiryImpl.java index 4384c0ad..c5ae9643 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/LoginContextSpringSecutiryImpl.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/LoginContextSpringSecutiryImpl.java @@ -21,6 +21,11 @@ public class LoginContextSpringSecutiryImpl implements LoginContext { @Override public LoginUser getUser() { + + if (null == SecurityContextHolder.getContext().getAuthentication()) { + return new LoginUser(1L); //默认 Admin + } + if (SecurityContextHolder.getContext().getAuthentication().getPrincipal() instanceof String) { throw new AuthException(AuthExceptionEnum.NOT_LOGIN_ERROR); } else { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java index 45ab09c6..af4ac685 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java @@ -1,5 +1,6 @@ package com.zmops.iot.web.schedule; +import com.zmops.iot.domain.schedule.Task; import com.zmops.iot.schedule.config.ScheduleConfig; import com.zmops.iot.schedule.cron.CronExpression; import io.ebean.DB; @@ -51,7 +52,7 @@ public void start() { DB.beginTransaction(); long nowTime = System.currentTimeMillis(); - List taskList = DB.findDto(Task.class, + List taskList = DB.findNative(Task.class, "SELECT T.ID, T.remark, T.trigger_status, T.trigger_next_time, T.schedule_type, T.schedule_conf " + " FROM task_info AS T " + " WHERE T.trigger_status = 1 " + @@ -69,12 +70,13 @@ public void start() { MisfireStrategyEnum misfireStrategyEnum = MisfireStrategyEnum.match(task.getMisfireStrategy(), MisfireStrategyEnum.DO_NOTHING); if (MisfireStrategyEnum.FIRE_ONCE_NOW == misfireStrategyEnum) { - TaskTriggerPool.trigger(task.getId(), TriggerTypeEnum.MISFIRE, -1, null, null, null); - log.debug("schedule push trigger : taskId = {}", task.getId()); + TaskTriggerPool.trigger(task.getId(), TriggerTypeEnum.MISFIRE, -1, null, null); } refreshNextValidTime(task, new Date()); + } else if (nowTime > task.getTriggerNextTime()) { - TaskTriggerPool.trigger(task.getId(), TriggerTypeEnum.CRON, -1, null, null, null); + + TaskTriggerPool.trigger(task.getId(), TriggerTypeEnum.CRON, -1, null, null); refreshNextValidTime(task, new Date()); if (task.getTriggerStatus() == 1 && nowTime + PRE_READ_MS > task.getTriggerNextTime()) { @@ -82,29 +84,18 @@ public void start() { pushTimeRing(ringSecond, task.getId()); refreshNextValidTime(task, new Date(task.getTriggerNextTime())); } - } else { int ringSecond = (int) ((task.getTriggerNextTime() / 1000) % 60); pushTimeRing(ringSecond, task.getId()); refreshNextValidTime(task, new Date(task.getTriggerNextTime())); } } + DB.updateAll(taskList); - for (Task task : taskList) { - DB.sqlUpdate("update task_info set " + - " trigger_last_time = :lastTime, " + - " trigger_next_time = :nextTime, " + - " trigger_status = :status " + - "where id = :id ") - .setParameter("lastTime", task.getTriggerLastTime()) - .setParameter("nextTime", task.getTriggerNextTime()) - .setParameter("status", task.getTriggerStatus()) - .setParameter("id", task.getId()) - .execute(); - } } else { preReadSuc = false; } + } catch (Exception e) { if (!scheduleThreadToStop) { log.error("JobScheduleHelper error: {}", e.getMessage()); @@ -157,7 +148,7 @@ public void start() { if (ringItemData.size() > 0) { for (int jobId : ringItemData) { - TaskTriggerPool.trigger(jobId, TriggerTypeEnum.CRON, -1, null, null, null); + TaskTriggerPool.trigger(jobId, TriggerTypeEnum.CRON, -1, null, null); } ringItemData.clear(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java index e4fc6e8a..cf790a48 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java @@ -55,7 +55,6 @@ public void stop() { public void addTrigger(final int jobId, final TriggerTypeEnum triggerType, final int failRetryCount, - final String executorShardingParam, final String executorParam, final String addressList) { @@ -69,7 +68,7 @@ public void addTrigger(final int jobId, long start = System.currentTimeMillis(); try { - System.out.println(123); + log.info("jobid : {}", jobId); } catch (Exception e) { log.error(e.getMessage(), e); @@ -94,7 +93,7 @@ public void addTrigger(final int jobId, private static TaskTriggerPool helper; - public static void trigger(int jobId, TriggerTypeEnum triggerType, int failRetryCount, String executorShardingParam, String executorParam, String addressList) { - helper.addTrigger(jobId, triggerType, failRetryCount, executorShardingParam, executorParam, addressList); + public static void trigger(int jobId, TriggerTypeEnum triggerType, int failRetryCount, String executorParam, String addressList) { + helper.addTrigger(jobId, triggerType, failRetryCount, executorParam, addressList); } } From 6d1a244b4c2686dafdccd1af15dc9e60edb42eb6 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 13 Nov 2021 12:05:52 +0800 Subject: [PATCH 644/763] [fix]: fix package path --- .../main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java | 2 +- .../src/main/java/com/zmops/iot/web/schedule/TaskStarter.java | 2 +- .../main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java | 2 +- .../java/com/zmops/iot/web/schedule/config/ScheduleConfig.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java index af4ac685..c91cecf9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java @@ -1,7 +1,7 @@ package com.zmops.iot.web.schedule; import com.zmops.iot.domain.schedule.Task; -import com.zmops.iot.schedule.config.ScheduleConfig; +import com.zmops.iot.web.schedule.config.ScheduleConfig; import com.zmops.iot.schedule.cron.CronExpression; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskStarter.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskStarter.java index 046d88ab..03766bb2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskStarter.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskStarter.java @@ -1,6 +1,6 @@ package com.zmops.iot.web.schedule; -import com.zmops.iot.schedule.config.ScheduleConfig; +import com.zmops.iot.web.schedule.config.ScheduleConfig; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Component; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java index cf790a48..d3c7121e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java @@ -1,6 +1,6 @@ package com.zmops.iot.web.schedule; -import com.zmops.iot.schedule.config.ScheduleConfig; +import com.zmops.iot.web.schedule.config.ScheduleConfig; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.*; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/config/ScheduleConfig.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/config/ScheduleConfig.java index 21e8936a..98b24386 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/config/ScheduleConfig.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/config/ScheduleConfig.java @@ -1,4 +1,4 @@ -package com.zmops.iot.schedule.config; +package com.zmops.iot.web.schedule.config; import lombok.Data; From b11e2973bb1905def2ae3db9958fbffa7cca6a77 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 13 Nov 2021 12:33:18 +0800 Subject: [PATCH 645/763] [fix]: add loginuser constructor methoh --- .../java/com/zmops/iot/core/auth/model/LoginUser.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java index e465f7d5..f1852367 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java @@ -36,6 +36,15 @@ public class LoginUser implements UserDetails, Serializable { private static final long serialVersionUID = 1L; + public LoginUser() { + super(); + } + + public LoginUser(Long id) { + super(); + this.id = id; + } + /** * 用户主键ID */ From 11c9a0fee8ef37b26750ccf6850e35d4995d92c0 Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 13 Nov 2021 15:49:12 +0800 Subject: [PATCH 646/763] [feat]: add task schedule --- .../iot/domain/product/ProductEvent.java | 15 +-- .../com/zmops/iot/domain/schedule/Task.java | 2 +- .../com/zmops/iot/domain/sys/Session.java | 30 ++++++ .../java/com/zmops/iot/domain/sys/Token.java | 39 +++++++ .../MultipleDeviceEventTriggerController.java | 10 +- .../device/dto/MultipleDeviceEventDto.java | 2 + .../device/dto/MultipleDeviceEventRule.java | 10 +- .../MultipleDeviceEventRuleService.java | 101 +++++++++++++++--- .../web/exception/enums/BizExceptionEnum.java | 8 +- .../iot/web/schedule/TaskScheduleImpl.java | 7 +- .../web/task/controller/taskController.java | 95 ++++++++++++++++ .../com/zmops/iot/web/task/dto/TaskDto.java | 50 +++++++++ .../zmops/iot/web/task/param/TaskParam.java | 14 +++ .../iot/web/task/service/TaskService.java | 72 +++++++++++++ 14 files changed, 423 insertions(+), 32 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/sys/Session.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/sys/Token.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/task/controller/taskController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/task/dto/TaskDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/task/param/TaskParam.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/task/service/TaskService.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java index 9e586e3b..e321350a 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java @@ -21,10 +21,13 @@ public class ProductEvent extends BaseEntity { @Id private Long eventRuleId; - private String eventRuleName; - private String eventLevel; - private String expLogic; - private String classify; - private String eventNotify; - + private String eventRuleName; + private String eventLevel; + private String expLogic; + private String classify; + private String eventNotify; + private String status; + private String remark; + private Integer taskId; + private Integer triggerType; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/schedule/Task.java b/zeus-common/src/main/java/com/zmops/iot/domain/schedule/Task.java index 368988d4..05cac402 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/schedule/Task.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/schedule/Task.java @@ -33,7 +33,7 @@ public class Task extends BaseEntity { private Integer taskFailRetryCount; - private Integer triggerStatus; // 调度状态:0-停止,1-运行 + private String triggerStatus; // 调度状态:DISABLE-停止,ENABLE-运行 private Long triggerLastTime; // 上次调度时间 private Long triggerNextTime; diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/sys/Session.java b/zeus-common/src/main/java/com/zmops/iot/domain/sys/Session.java new file mode 100644 index 00000000..2f7ffb23 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/sys/Session.java @@ -0,0 +1,30 @@ +package com.zmops.iot.domain.sys; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@Data +@Table(name = "session") +@Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Session { + + @Id + private Integer id; + + private String key; + + private String value; + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/sys/Token.java b/zeus-common/src/main/java/com/zmops/iot/domain/sys/Token.java new file mode 100644 index 00000000..d2400e21 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/sys/Token.java @@ -0,0 +1,39 @@ +package com.zmops.iot.domain.sys; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@Data +@Table(name = "token") +@Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Token { + + @Id + private Integer tokenId; + + private String name; + + private String description; + + private Long userId; + + private String token; + + private String status; + + private Long expiresAt; + + private String account; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java index 02535a01..7a9da4fd 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java @@ -98,9 +98,12 @@ public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId) { public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Create.class) MultipleDeviceEventRule eventRule) { + multipleDeviceEventRuleService.checkParam(eventRule); + Long eventRuleId = IdUtil.getSnowflake().nextId(); - multipleDeviceEventRuleService.createDeviceEventRule(eventRuleId, eventRule); + eventRule.setEventRuleId(eventRuleId); + multipleDeviceEventRuleService.createDeviceEventRule(eventRule); //step 1: 先创建 zbx 触发器 String expression = eventRule.getExpList() @@ -165,8 +168,11 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); } + //检查参数 + multipleDeviceEventRuleService.checkParam(eventRule); + //step 1: 删除原有的 关联关系 - multipleDeviceEventRuleService.updateDeviceEventRule(eventRule.getEventRuleId(), eventRule); + multipleDeviceEventRuleService.updateDeviceEventRule(eventRule); //step 1: 先创建 zbx 触发器 String expression = eventRule.getExpList() diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java index 1c93a3d4..82923976 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java @@ -41,4 +41,6 @@ public class MultipleDeviceEventDto { private String triggerDevice; private String executeDevice; + + private Integer taskId; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java index 61386c9f..eaf6ad9c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java @@ -36,12 +36,9 @@ public class MultipleDeviceEventRule { private Byte eventLevel = 1; // 表达式列表 - @Valid - @NotEmpty(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private List expList; - @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) - private String expLogic; // and or + private String expLogic="and"; // and or private String remark; @@ -59,6 +56,11 @@ public class MultipleDeviceEventRule { private String classify = "1"; + private String scheduleConf; + + @NotNull + private Integer triggerType; + @Data public static class Tag { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index cc2fa7cd..377c6cb1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -26,6 +26,8 @@ import com.zmops.iot.web.device.service.work.ScenesLogWorker; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductEventRuleDto; +import com.zmops.iot.web.task.dto.TaskDto; +import com.zmops.iot.web.task.service.TaskService; import com.zmops.zeus.driver.service.ZbxTrigger; import io.ebean.DB; import io.ebean.annotation.Transactional; @@ -34,6 +36,7 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -57,6 +60,9 @@ public class MultipleDeviceEventRuleService { private static final String EVENT_CLASSIFY = "1"; + @Autowired + TaskService taskService; + /** * 场景列表 * @@ -150,17 +156,56 @@ public Pager getEventByPage(MultipleDeviceEventParm even return new Pager<>(list, query.findCount()); } + private String generateExecuteParam(MultipleDeviceEventRule eventRule) { + Map param = new HashMap<>(2); + param.put("eventRuleId", eventRule.getEventRuleId()); + + List> list = new ArrayList<>(); + Map> collect = eventRule.getDeviceServices().parallelStream().collect(Collectors.groupingBy(MultipleDeviceEventRule.DeviceService::getExecuteDeviceId)); + + collect.forEach((key, value) -> { + Map map = new ConcurrentHashMap<>(); + map.put("device", key); + + List> serviceList = new ArrayList<>(); + value.forEach(val -> { + Map serviceMap = new ConcurrentHashMap<>(2); + serviceMap.put("name", DefinitionsUtil.getServiceName(val.getServiceId())); + + List paramList = DefinitionsUtil.getServiceParam(val.getServiceId()); + if (ToolUtil.isNotEmpty(paramList)) { + serviceMap.put("param", paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue))); + } + serviceList.add(serviceMap); + }); + map.put("service", serviceList); + list.add(map); + }); + param.put("executeParam", list); + return JSON.toJSONString(param); + } + /** * 保存设备联动 * - * @param eventRuleId 设备联动ID - * @param eventRule 设备联动规则 + * @param eventRule 设备联动规则 */ @Transactional(rollbackFor = Exception.class) - public void createDeviceEventRule(Long eventRuleId, MultipleDeviceEventRule eventRule) { + public void createDeviceEventRule(MultipleDeviceEventRule eventRule) { + + //setp 0: 创建任务 + Integer taskId = null; + if (eventRule.getTriggerType() == 1) { + TaskDto taskDto = new TaskDto(); + taskDto.setScheduleConf(eventRule.getScheduleConf()); + taskDto.setExecutorParam(generateExecuteParam(eventRule)); + taskId = taskService.createTask(taskDto); + } + // step 1: 保存产品告警规则 ProductEvent event = initEventRule(eventRule); - event.setEventRuleId(eventRuleId); + event.setEventRuleId(eventRule.getEventRuleId()); + event.setTaskId(taskId); DB.save(event); //step 2: 保存 表达式,方便回显 @@ -168,7 +213,7 @@ public void createDeviceEventRule(Long eventRuleId, MultipleDeviceEventRule even eventRule.getExpList().forEach(i -> { ProductEventExpression exp = initEventExpression(i); - exp.setEventRuleId(eventRuleId); + exp.setEventRuleId(eventRule.getEventRuleId()); expList.add(exp); }); @@ -178,8 +223,8 @@ public void createDeviceEventRule(Long eventRuleId, MultipleDeviceEventRule even if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { eventRule.getDeviceServices().forEach(i -> { DB.sqlUpdate("insert into product_event_service(event_rule_id, execute_device_id, service_id) " + - "values (:eventRuleId, :executeDeviceId, :serviceId)") - .setParameter("eventRuleId", eventRuleId) + "values (:eventRuleId, :executeDeviceId, :serviceId)") + .setParameter("eventRuleId", eventRule.getEventRuleId()) .setParameter("executeDeviceId", i.getExecuteDeviceId()) .setParameter("serviceId", i.getServiceId()) .execute(); @@ -194,7 +239,7 @@ public void createDeviceEventRule(Long eventRuleId, MultipleDeviceEventRule even List productEventRelationList = new ArrayList<>(); relationIds.forEach(relationId -> { ProductEventRelation productEventRelation = new ProductEventRelation(); - productEventRelation.setEventRuleId(eventRuleId); + productEventRelation.setEventRuleId(eventRule.getEventRuleId()); productEventRelation.setRelationId(relationId); productEventRelation.setInherit(InheritStatus.NO.getCode()); productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); @@ -205,7 +250,16 @@ public void createDeviceEventRule(Long eventRuleId, MultipleDeviceEventRule even } @Transactional(rollbackFor = Exception.class) - public void updateDeviceEventRule(Long eventRuleId, MultipleDeviceEventRule eventRule) { + public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { + + //setp 0: 创建任务 + Integer taskId = null; + if (eventRule.getTriggerType() == 1) { + TaskDto taskDto = new TaskDto(); + taskDto.setScheduleConf(eventRule.getScheduleConf()); + taskDto.setExecutorParam(generateExecuteParam(eventRule)); + taskId = taskService.createTask(taskDto); + } //step 1: 函数表达式 DB.sqlUpdate("delete from product_event_expression where event_rule_id = :eventRuleId") @@ -222,7 +276,8 @@ public void updateDeviceEventRule(Long eventRuleId, MultipleDeviceEventRule even // step 3: 保存产品告警规则 ProductEvent event = initEventRule(eventRule); - event.setEventRuleId(eventRuleId); + event.setEventRuleId(eventRule.getEventRuleId()); + event.setTaskId(taskId); event.update(); //step 4: 保存 表达式,方便回显 @@ -230,7 +285,7 @@ public void updateDeviceEventRule(Long eventRuleId, MultipleDeviceEventRule even eventRule.getExpList().forEach(i -> { ProductEventExpression exp = initEventExpression(i); - exp.setEventRuleId(eventRuleId); + exp.setEventRuleId(eventRule.getEventRuleId()); expList.add(exp); }); @@ -240,7 +295,7 @@ public void updateDeviceEventRule(Long eventRuleId, MultipleDeviceEventRule even if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { eventRule.getDeviceServices().forEach(i -> { DB.sqlUpdate("insert into product_event_service(event_rule_id,execute_device_id, service_id) values (:eventRuleId, :executeDeviceId, :serviceId)") - .setParameter("eventRuleId", eventRuleId) + .setParameter("eventRuleId", eventRule.getEventRuleId()) .setParameter("executeDeviceId", i.getExecuteDeviceId()) .setParameter("serviceId", i.getServiceId()) .execute(); @@ -255,7 +310,7 @@ public void updateDeviceEventRule(Long eventRuleId, MultipleDeviceEventRule even List productEventRelationList = new ArrayList<>(); relationIds.forEach(relationId -> { ProductEventRelation productEventRelation = new ProductEventRelation(); - productEventRelation.setEventRuleId(eventRuleId); + productEventRelation.setEventRuleId(eventRule.getEventRuleId()); productEventRelation.setRelationId(relationId); productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); productEventRelation.setRemark(eventRule.getRemark()); @@ -272,6 +327,9 @@ private ProductEvent initEventRule(MultipleDeviceEventRule eventRule) { event.setEventNotify(eventRule.getEventNotify().toString()); event.setClassify(eventRule.getClassify()); event.setEventRuleName(eventRule.getEventRuleName()); + event.setStatus(CommonStatus.ENABLE.getCode()); + event.setRemark(eventRule.getRemark()); + event.setTriggerType(eventRule.getTriggerType()); return event; } @@ -412,6 +470,19 @@ public void execute(Long eventRuleId, String type, Long userId) { Forest.post("/device/action/exec").host("127.0.0.1").port(12800).contentTypeJson().addBody(JSON.toJSON(list)).execute(); } + + public void checkParam(MultipleDeviceEventRule eventRule) { + if (eventRule.getTriggerType() == 0) { + if (ToolUtil.isEmpty(eventRule.getExpList())) { + throw new ServiceException(BizExceptionEnum.SCENE_EXPRESSION_NOT_EXISTS); + } + } else { + if (ToolUtil.isEmpty(eventRule.getScheduleConf())) { + throw new ServiceException(BizExceptionEnum.SCENE_EXPRESSION_NOT_EXISTS); + } + } + } + @Data static class TriggerIds { private String[] triggerids; @@ -419,8 +490,8 @@ static class TriggerIds { @Data public static class Triggers { - private String triggerid; - private String description; + private String triggerid; + private String description; private List hosts; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index 5e50cf8a..bedaa2d4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -173,8 +173,15 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { EVENT_PRODUCT_CANNOT_DELETE(1706, "来自产品的触发器不能删除"), SCENE_NOT_EXISTS(1707, "场景不存在"), + SCENE_EXPRESSION_NOT_EXISTS(1708, "场景触发条件不能为空"), + /** + * 任务相关 + * @param code + * @param message + */ + TASK_NOT_SCHEDULE_CONF(2201,"任务调度配置不能为空"), /** * 租户相关的异常 @@ -183,7 +190,6 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { - BizExceptionEnum(int code, String message) { this.code = code; this.message = message; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java index c91cecf9..d62f7b0c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java @@ -1,6 +1,7 @@ package com.zmops.iot.web.schedule; import com.zmops.iot.domain.schedule.Task; +import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.web.schedule.config.ScheduleConfig; import com.zmops.iot.schedule.cron.CronExpression; import io.ebean.DB; @@ -55,7 +56,7 @@ public void start() { List taskList = DB.findNative(Task.class, "SELECT T.ID, T.remark, T.trigger_status, T.trigger_next_time, T.schedule_type, T.schedule_conf " + " FROM task_info AS T " + - " WHERE T.trigger_status = 1 " + + " WHERE T.trigger_status = '"+ CommonStatus.ENABLE.getCode() +"' " + " and t.trigger_next_time <= :nextTime " + " ORDER BY ID ASC " + " LIMIT :preReadCount") @@ -79,7 +80,7 @@ public void start() { TaskTriggerPool.trigger(task.getId(), TriggerTypeEnum.CRON, -1, null, null); refreshNextValidTime(task, new Date()); - if (task.getTriggerStatus() == 1 && nowTime + PRE_READ_MS > task.getTriggerNextTime()) { + if (CommonStatus.ENABLE.getCode().equals(task.getTriggerStatus()) && nowTime + PRE_READ_MS > task.getTriggerNextTime()) { int ringSecond = (int) ((task.getTriggerNextTime() / 1000) % 60); pushTimeRing(ringSecond, task.getId()); refreshNextValidTime(task, new Date(task.getTriggerNextTime())); @@ -171,7 +172,7 @@ private void refreshNextValidTime(Task task, Date fromTime) throws Exception { task.setTriggerLastTime(task.getTriggerNextTime()); task.setTriggerNextTime(nextValidTime.getTime()); } else { - task.setTriggerStatus(0); + task.setTriggerStatus(CommonStatus.DISABLE.getCode()); task.setTriggerLastTime(0L); task.setTriggerNextTime(0L); log.warn("refreshNextValidTime fail for job: jobId={}, scheduleType={}, scheduleConf={}", task.getId(), task.getScheduleType(), task.getScheduleConf()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/task/controller/taskController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/task/controller/taskController.java new file mode 100644 index 00000000..3528e1c5 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/task/controller/taskController.java @@ -0,0 +1,95 @@ +package com.zmops.iot.web.task.controller; + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.device.dto.DeviceGroupDto; +import com.zmops.iot.web.task.dto.TaskDto; +import com.zmops.iot.web.task.param.TaskParam; +import com.zmops.iot.web.task.service.TaskService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + *

+ * 任务管理 + **/ +@RestController +@RequestMapping("/task") +public class taskController { + + @Autowired + TaskService taskService; + +// /** +// * 任务分页列表 +// * +// * @return +// */ +// @PostMapping("/getTaskByPage") +// public Pager getTaskByPage(@RequestBody TaskParam taskParam) { +// return taskService.getTaskByPage(taskParam); +// } +// +// /** +// * 设任务列表 +// * +// * @return +// */ +// @PostMapping("/list") +// public ResponseData list(@RequestBody TaskParam taskParam) { +// return ResponseData.success(taskService.list(taskParam)); +// } + + /** + * 创建任务 + * + * @return + */ + @PostMapping("/create") +// @BussinessLog(value = "创建任务") + public ResponseData createTask(@Validated(BaseEntity.Create.class) @RequestBody TaskDto taskDto) { + return ResponseData.success(taskService.createTask(taskDto)); + } + + + /** + * 更新任务 + * + * @return + */ + @PostMapping("/update") +// @BussinessLog(value = "更新任务") + public ResponseData updateTask(@Validated(BaseEntity.Update.class) @RequestBody TaskDto taskDto) { + return ResponseData.success(taskService.updateTask(taskDto)); + } + + /** + * 删除任务 + * + * @return + */ + @PostMapping("/delete") +// @BussinessLog(value = "删除任务") + public ResponseData deleteTask(@Validated(BaseEntity.Delete.class) @RequestBody TaskDto taskParam) { + taskService.deleteTask(taskParam); + return ResponseData.success(); + } + + /** + * 启动 停止任务 + * + * @return + */ + @PostMapping("/status") +// @BussinessLog(value = "启动 停止任务") + public ResponseData status(@Validated(BaseEntity.Delete.class) @RequestBody TaskDto taskDto) { + taskService.status(taskDto); + return ResponseData.success(); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/task/dto/TaskDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/task/dto/TaskDto.java new file mode 100644 index 00000000..a89381e0 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/task/dto/TaskDto.java @@ -0,0 +1,50 @@ +package com.zmops.iot.web.task.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author yefei + **/ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class TaskDto { + + private Integer id; + + private String scheduleType = "CRON"; + + private String scheduleConf; + + private String misfireStrategy = "DO_NOTHING"; + + private Integer taskTimeout = 0; + + private Integer taskFailRetryCount = 0; + + @CachedValue(value = "STATUS") + private String triggerStatus = "ENABLE"; + + private Long triggerLastTime; + + private Long triggerNextTime; + + private String remark; + + private String executorParam; + + LocalDateTime createTime; + + LocalDateTime updateTime; + + @CachedValue(type = DicType.SysUserName) + private Long createUser; + + @CachedValue(type = DicType.SysUserName) + private Long updateUser; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/task/param/TaskParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/task/param/TaskParam.java new file mode 100644 index 00000000..ce17e0a3 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/task/param/TaskParam.java @@ -0,0 +1,14 @@ +package com.zmops.iot.web.task.param; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class TaskParam { + + private Integer id; + + private String triggerStatus; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/task/service/TaskService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/task/service/TaskService.java new file mode 100644 index 00000000..500e42c3 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/task/service/TaskService.java @@ -0,0 +1,72 @@ +package com.zmops.iot.web.task.service; + +import cn.hutool.core.bean.BeanUtil; +import com.zmops.iot.domain.schedule.Task; +import com.zmops.iot.domain.schedule.query.QTask; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.task.dto.TaskDto; +import io.ebean.DB; +import org.springframework.stereotype.Service; + +/** + * @author yefei + **/ +@Service +public class TaskService { + + /** + * 创建任务 + * + * @param taskDto + * @return + */ + public Integer createTask(TaskDto taskDto) { + Task task = new Task(); + BeanUtil.copyProperties(taskDto, task); + DB.insert(task); + return task.getId(); + } + + /** + * 修改任务 + * + * @param taskDto + * @return + */ + public TaskDto updateTask(TaskDto taskDto) { + Task task = new Task(); + BeanUtil.copyProperties(taskDto, task); + DB.update(task); + return taskDto; + } + + /** + * 删除任务 + * + * @param taskParam + */ + public void deleteTask(TaskDto taskParam) { + if (taskParam.getId() == null) { + return; + } + new QTask().id.eq(taskParam.getId()).delete(); + } + + /** + * 启用 禁用任务 + * 默认启用 + * + * @param taskParam + */ + public void status(TaskDto taskParam) { + if (taskParam.getId() == null) { + return; + } + String triggerStatus = taskParam.getTriggerStatus(); + if (ToolUtil.isEmpty(triggerStatus)) { + triggerStatus = CommonStatus.DISABLE.getCode(); + } + DB.update(Task.class).where().eq("id", taskParam.getId()).asUpdate().set("trigger_status", triggerStatus).update(); + } +} From 7bd080a86719b8e3797c7b2fdff9b519f4ee450d Mon Sep 17 00:00:00 2001 From: yefei Date: Sat, 13 Nov 2021 16:32:57 +0800 Subject: [PATCH 647/763] [fix] fix scene trigger trype --- .../MultipleDeviceEventTriggerController.java | 86 ++++++++--------- .../MultipleDeviceEventRuleService.java | 92 ++++++++++--------- .../web/exception/enums/BizExceptionEnum.java | 2 +- .../com/zmops/iot/web/task/dto/TaskDto.java | 4 +- 4 files changed, 97 insertions(+), 87 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java index 7a9da4fd..3f4865bc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java @@ -105,31 +105,32 @@ public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEn eventRule.setEventRuleId(eventRuleId); multipleDeviceEventRuleService.createDeviceEventRule(eventRule); - //step 1: 先创建 zbx 触发器 - String expression = eventRule.getExpList() - .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); - - //step 2: zbx 保存触发器 - String[] triggerIds = multipleDeviceEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); - - //step 4: zbx 触发器创建 Tag - Map tags = new ConcurrentHashMap<>(1); - if (ToolUtil.isNotEmpty(eventRule.getTags())) { - tags = eventRule.getTags().stream() - .collect(Collectors.toMap(MultipleDeviceEventRule.Tag::getTag, MultipleDeviceEventRule.Tag::getValue, (k1, k2) -> k2)); - } - - if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { - tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); - } + if(ToolUtil.isNotEmpty(eventRule.getExpList())) { + //step 1: 先创建 zbx 触发器 + String expression = eventRule.getExpList() + .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); + + //step 2: zbx 保存触发器 + String[] triggerIds = multipleDeviceEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); + + //step 4: zbx 触发器创建 Tag + Map tags = new ConcurrentHashMap<>(1); + if (ToolUtil.isNotEmpty(eventRule.getTags())) { + tags = eventRule.getTags().stream() + .collect(Collectors.toMap(MultipleDeviceEventRule.Tag::getTag, MultipleDeviceEventRule.Tag::getValue, (k1, k2) -> k2)); + } - for (String triggerId : triggerIds) { - zbxTrigger.triggerTagCreate(triggerId, tags); - } + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { + tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); + } - //step 5: 更新 zbxId - multipleDeviceEventRuleService.updateProductEventRuleZbxId(eventRuleId, triggerIds); + for (String triggerId : triggerIds) { + zbxTrigger.triggerTagCreate(triggerId, tags); + } + //step 5: 更新 zbxId + multipleDeviceEventRuleService.updateProductEventRuleZbxId(eventRuleId, triggerIds); + } // 返回触发器ID return ResponseData.success(eventRuleId); } @@ -174,31 +175,32 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn //step 1: 删除原有的 关联关系 multipleDeviceEventRuleService.updateDeviceEventRule(eventRule); - //step 1: 先创建 zbx 触发器 - String expression = eventRule.getExpList() - .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); + if(ToolUtil.isNotEmpty(eventRule.getExpList())) { + //step 1: 先创建 zbx 触发器 + String expression = eventRule.getExpList() + .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); - //step 2: zbx 保存触发器 - String[] triggerIds = multipleDeviceEventRuleService.updateZbxTrigger(productEventRelation.getZbxId(), expression, eventRule.getEventLevel()); + //step 2: zbx 保存触发器 + String[] triggerIds = multipleDeviceEventRuleService.updateZbxTrigger(productEventRelation.getZbxId(), expression, eventRule.getEventLevel()); - //step 4: zbx 触发器创建 Tag - Map tags = new ConcurrentHashMap<>(1); - if (ToolUtil.isNotEmpty(eventRule.getTags())) { - tags = eventRule.getTags().stream() - .collect(Collectors.toMap(MultipleDeviceEventRule.Tag::getTag, MultipleDeviceEventRule.Tag::getValue, (k1, k2) -> k2)); - } - - if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { - tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); - } + //step 4: zbx 触发器创建 Tag + Map tags = new ConcurrentHashMap<>(1); + if (ToolUtil.isNotEmpty(eventRule.getTags())) { + tags = eventRule.getTags().stream() + .collect(Collectors.toMap(MultipleDeviceEventRule.Tag::getTag, MultipleDeviceEventRule.Tag::getValue, (k1, k2) -> k2)); + } - for (String triggerId : triggerIds) { - zbxTrigger.triggerTagCreate(triggerId, tags); - } + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { + tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); + } - //step 5: 更新 zbxId 反写 - multipleDeviceEventRuleService.updateProductEventRuleZbxId(eventRule.getEventRuleId(), triggerIds); + for (String triggerId : triggerIds) { + zbxTrigger.triggerTagCreate(triggerId, tags); + } + //step 5: 更新 zbxId 反写 + multipleDeviceEventRuleService.updateProductEventRuleZbxId(eventRule.getEventRuleId(), triggerIds); + } // 返回触发器ID return ResponseData.success(eventRule.getEventRuleId()); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index 377c6cb1..7ddfe6ad 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -209,15 +209,17 @@ public void createDeviceEventRule(MultipleDeviceEventRule eventRule) { DB.save(event); //step 2: 保存 表达式,方便回显 - List expList = new ArrayList<>(); + if (ToolUtil.isNotEmpty(eventRule.getExpList())) { + List expList = new ArrayList<>(); - eventRule.getExpList().forEach(i -> { - ProductEventExpression exp = initEventExpression(i); - exp.setEventRuleId(eventRule.getEventRuleId()); - expList.add(exp); - }); + eventRule.getExpList().forEach(i -> { + ProductEventExpression exp = initEventExpression(i); + exp.setEventRuleId(eventRule.getEventRuleId()); + expList.add(exp); + }); - DB.saveAll(expList); + DB.saveAll(expList); + } //step 3: 保存触发器 调用 本产品方法 if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { @@ -232,21 +234,23 @@ public void createDeviceEventRule(MultipleDeviceEventRule eventRule) { } //step 4: 保存关联关系 - List relationIds = eventRule.getExpList().parallelStream().map(MultipleDeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); - if (ToolUtil.isEmpty(relationIds)) { - throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); + if (ToolUtil.isNotEmpty(eventRule.getExpList())) { + List relationIds = eventRule.getExpList().parallelStream().map(MultipleDeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); + if (ToolUtil.isEmpty(relationIds)) { + throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); + } + List productEventRelationList = new ArrayList<>(); + relationIds.forEach(relationId -> { + ProductEventRelation productEventRelation = new ProductEventRelation(); + productEventRelation.setEventRuleId(eventRule.getEventRuleId()); + productEventRelation.setRelationId(relationId); + productEventRelation.setInherit(InheritStatus.NO.getCode()); + productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); + productEventRelation.setRemark(eventRule.getRemark()); + productEventRelationList.add(productEventRelation); + }); + DB.saveAll(productEventRelationList); } - List productEventRelationList = new ArrayList<>(); - relationIds.forEach(relationId -> { - ProductEventRelation productEventRelation = new ProductEventRelation(); - productEventRelation.setEventRuleId(eventRule.getEventRuleId()); - productEventRelation.setRelationId(relationId); - productEventRelation.setInherit(InheritStatus.NO.getCode()); - productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); - productEventRelation.setRemark(eventRule.getRemark()); - productEventRelationList.add(productEventRelation); - }); - DB.saveAll(productEventRelationList); } @Transactional(rollbackFor = Exception.class) @@ -281,15 +285,17 @@ public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { event.update(); //step 4: 保存 表达式,方便回显 - List expList = new ArrayList<>(); + if (ToolUtil.isNotEmpty(eventRule.getExpList())) { + List expList = new ArrayList<>(); - eventRule.getExpList().forEach(i -> { - ProductEventExpression exp = initEventExpression(i); - exp.setEventRuleId(eventRule.getEventRuleId()); - expList.add(exp); - }); + eventRule.getExpList().forEach(i -> { + ProductEventExpression exp = initEventExpression(i); + exp.setEventRuleId(eventRule.getEventRuleId()); + expList.add(exp); + }); - DB.saveAll(expList); + DB.saveAll(expList); + } //step 5: 保存触发器 调用 本产品方法 if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { @@ -303,20 +309,22 @@ public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { } // step 6: 保存关联关系 - List relationIds = eventRule.getExpList().parallelStream().map(MultipleDeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); - if (ToolUtil.isEmpty(relationIds)) { - throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); + if (ToolUtil.isNotEmpty(eventRule.getExpList())) { + List relationIds = eventRule.getExpList().parallelStream().map(MultipleDeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); + if (ToolUtil.isEmpty(relationIds)) { + throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); + } + List productEventRelationList = new ArrayList<>(); + relationIds.forEach(relationId -> { + ProductEventRelation productEventRelation = new ProductEventRelation(); + productEventRelation.setEventRuleId(eventRule.getEventRuleId()); + productEventRelation.setRelationId(relationId); + productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); + productEventRelation.setRemark(eventRule.getRemark()); + productEventRelationList.add(productEventRelation); + }); + DB.saveAll(productEventRelationList); } - List productEventRelationList = new ArrayList<>(); - relationIds.forEach(relationId -> { - ProductEventRelation productEventRelation = new ProductEventRelation(); - productEventRelation.setEventRuleId(eventRule.getEventRuleId()); - productEventRelation.setRelationId(relationId); - productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); - productEventRelation.setRemark(eventRule.getRemark()); - productEventRelationList.add(productEventRelation); - }); - DB.saveAll(productEventRelationList); } @@ -478,7 +486,7 @@ public void checkParam(MultipleDeviceEventRule eventRule) { } } else { if (ToolUtil.isEmpty(eventRule.getScheduleConf())) { - throw new ServiceException(BizExceptionEnum.SCENE_EXPRESSION_NOT_EXISTS); + throw new ServiceException(BizExceptionEnum.TASK_NOT_SCHEDULE_CONF); } } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index bedaa2d4..f9bf70b1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -174,7 +174,7 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { EVENT_PRODUCT_CANNOT_DELETE(1706, "来自产品的触发器不能删除"), SCENE_NOT_EXISTS(1707, "场景不存在"), SCENE_EXPRESSION_NOT_EXISTS(1708, "场景触发条件不能为空"), - + SCENE_EXISTED(1709, "场景名称已存在"), /** * 任务相关 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/task/dto/TaskDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/task/dto/TaskDto.java index a89381e0..ed74cda3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/task/dto/TaskDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/task/dto/TaskDto.java @@ -30,9 +30,9 @@ public class TaskDto { @CachedValue(value = "STATUS") private String triggerStatus = "ENABLE"; - private Long triggerLastTime; + private Long triggerLastTime=0L; - private Long triggerNextTime; + private Long triggerNextTime=0L; private String remark; From f90f9e70bf8a004ce20ce5d717b01eb4620052bf Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 15 Nov 2021 11:23:04 +0800 Subject: [PATCH 648/763] [fix]: fix scene trigger type --- zeus-webapp/pom.xml | 6 + .../MultipleDeviceEventTriggerController.java | 80 ++++++++---- .../device/dto/MultipleDeviceEventDto.java | 4 +- .../device/dto/MultipleDeviceEventRule.java | 2 + .../MultipleDeviceEventRuleService.java | 119 ++++++++++-------- .../service/SceneScheduleProcessor.java | 61 +++++++++ .../web/product/dto/ProductEventRuleDto.java | 7 ++ .../iot/web/schedule/TaskScheduleImpl.java | 26 ++-- .../zmops/iot/web/schedule/TaskStarter.java | 20 ++- .../iot/web/schedule/TaskTriggerPool.java | 13 +- .../iot/web/task/service/TaskService.java | 15 ++- 11 files changed, 251 insertions(+), 102 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java diff --git a/zeus-webapp/pom.xml b/zeus-webapp/pom.xml index e51dbd6a..7969fc18 100644 --- a/zeus-webapp/pom.xml +++ b/zeus-webapp/pom.xml @@ -58,6 +58,12 @@ 2.25.4 compile + + com.zmops + iot-eventbus + 1.0-beta + compile + diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java index 3f4865bc..1fd02af2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java @@ -10,6 +10,8 @@ import com.zmops.iot.domain.product.query.QProductEventExpression; import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.domain.schedule.Task; +import com.zmops.iot.domain.schedule.query.QTask; import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; @@ -32,6 +34,9 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; +import static com.zmops.iot.web.device.service.MultipleDeviceEventRuleService.TRIGGER_TYPE_CONDITION; +import static com.zmops.iot.web.device.service.MultipleDeviceEventRuleService.TRIGGER_TYPE_SCHEDULE; + /** * @author yefei *

@@ -105,7 +110,7 @@ public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEn eventRule.setEventRuleId(eventRuleId); multipleDeviceEventRuleService.createDeviceEventRule(eventRule); - if(ToolUtil.isNotEmpty(eventRule.getExpList())) { + if (TRIGGER_TYPE_CONDITION == eventRule.getTriggerType()) { //step 1: 先创建 zbx 触发器 String expression = eventRule.getExpList() .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); @@ -142,13 +147,25 @@ public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEn */ @PostMapping("/status") public ResponseData updateProductEventStatus(@RequestBody @Validated(value = BaseEntity.Status.class) MultipleDeviceEventRule eventRule) { - DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).asUpdate() - .set("status", eventRule.getStatus()).update(); - ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).findOne(); + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).findOne(); + if (null == productEvent) { + throw new ServiceException(BizExceptionEnum.SCENE_NOT_EXISTS); + } + + if (TRIGGER_TYPE_SCHEDULE == productEvent.getTriggerType()) { + DB.update(Task.class).where().eq("taskId", productEvent.getTaskId()).asUpdate() + .set("triggerStatus", eventRule.getStatus()).update(); + } else { - if (null != productEventRelation && null != productEventRelation.getZbxId()) { - zbxTrigger.triggerStatusUpdate(productEventRelation.getZbxId(), eventRule.getStatus().equals(CommonStatus.ENABLE.getCode()) ? "0" : "1"); + DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).asUpdate() + .set("status", eventRule.getStatus()).update(); + + ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).findOne(); + + if (null != productEventRelation && null != productEventRelation.getZbxId()) { + zbxTrigger.triggerStatusUpdate(productEventRelation.getZbxId(), eventRule.getStatus().equals(CommonStatus.ENABLE.getCode()) ? "0" : "1"); + } } return ResponseData.success(); @@ -163,9 +180,9 @@ public ResponseData updateProductEventStatus(@RequestBody @Validated(value = Bas @Transactional @PostMapping("/update") public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) MultipleDeviceEventRule eventRule) { - ProductEventRelation productEventRelation = new QProductEventRelation().setMaxRows(1).eventRuleId.eq(eventRule.getEventRuleId()) + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()) .findOne(); - if (null == productEventRelation) { + if (null == productEvent) { throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); } @@ -173,9 +190,12 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn multipleDeviceEventRuleService.checkParam(eventRule); //step 1: 删除原有的 关联关系 + eventRule.setTaskId(productEvent.getTaskId()); multipleDeviceEventRuleService.updateDeviceEventRule(eventRule); - if(ToolUtil.isNotEmpty(eventRule.getExpList())) { + if (TRIGGER_TYPE_CONDITION == eventRule.getTriggerType()) { + ProductEventRelation productEventRelation = new QProductEventRelation().setMaxRows(1).eventRuleId.eq(eventRule.getEventRuleId()) + .findOne(); //step 1: 先创建 zbx 触发器 String expression = eventRule.getExpList() .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); @@ -215,28 +235,38 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn @PostMapping("/delete") public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseEntity.Delete.class) MultipleDeviceEventRule eventRule) { - List productEventRelationList = new QProductEventRelation() - .eventRuleId.eq(eventRule.getEventRuleId()).findList(); + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).findOne(); + if (null == productEvent) { + throw new ServiceException(BizExceptionEnum.SCENE_NOT_EXISTS); + } + if (TRIGGER_TYPE_CONDITION == eventRule.getTriggerType()) { + List productEventRelationList = new QProductEventRelation() + .eventRuleId.eq(eventRule.getEventRuleId()).findList(); + + //step 01:删除 zbx触发器 + if (ToolUtil.isNotEmpty(productEventRelationList) && ToolUtil.isNotEmpty(productEventRelationList.get(0).getZbxId())) { + List triggers = JSONObject.parseArray( + zbxTrigger.triggerGet(productEventRelationList.get(0).getZbxId()), MultipleDeviceEventRuleService.Triggers.class); + + if (ToolUtil.isNotEmpty(triggers)) { + zbxTrigger.triggerDelete(productEventRelationList.get(0).getZbxId()); + } + } - //step 01:删除 zbx触发器 - if (ToolUtil.isNotEmpty(productEventRelationList) && ToolUtil.isNotEmpty(productEventRelationList.get(0).getZbxId())) { - List triggers = JSONObject.parseArray( - zbxTrigger.triggerGet(productEventRelationList.get(0).getZbxId()), MultipleDeviceEventRuleService.Triggers.class); + //step 1:删除 与设备的关联 + new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); - if (ToolUtil.isNotEmpty(triggers)) { - zbxTrigger.triggerDelete(productEventRelationList.get(0).getZbxId()); - } - } + //step 2:删除 关联的表达式 + new QProductEventExpression().eventRuleId.eq(eventRule.getEventRuleId()).delete(); - //step 1:删除 与设备的关联 - new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + } else { + //step 1:删除 定时器 + new QTask().id.eq(productEvent.getTaskId()).delete(); + } - //step 2:删除 关联的执行服务 + //step 3:删除 关联的执行服务 new QProductEventService().eventRuleId.eq(eventRule.getEventRuleId()).delete(); - //step 3:删除 关联的表达式 - new QProductEventExpression().eventRuleId.eq(eventRule.getEventRuleId()).delete(); - //step 4:删除 触发器 new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).delete(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java index 82923976..526e1981 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java @@ -25,7 +25,6 @@ public class MultipleDeviceEventDto { @CachedValue(value = "STATUS") private String status; - @CachedValue(value = "WHETHER") private String inherit; private String remark; @@ -43,4 +42,7 @@ public class MultipleDeviceEventDto { private String executeDevice; private Integer taskId; + + @CachedValue(value = "triggerType") + private String triggerType; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java index eaf6ad9c..457d1652 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java @@ -61,6 +61,8 @@ public class MultipleDeviceEventRule { @NotNull private Integer triggerType; + private Integer taskId; + @Data public static class Tag { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index 7ddfe6ad..21deb9ca 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -11,6 +11,8 @@ import com.zmops.iot.domain.product.query.QProductEventExpression; import com.zmops.iot.domain.product.query.QProductEventRelation; import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.domain.schedule.Task; +import com.zmops.iot.domain.schedule.query.QTask; import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.enums.InheritStatus; import com.zmops.iot.model.exception.ServiceException; @@ -60,6 +62,10 @@ public class MultipleDeviceEventRuleService { private static final String EVENT_CLASSIFY = "1"; + public static final int TRIGGER_TYPE_SCHEDULE = 1; + + public static final int TRIGGER_TYPE_CONDITION = 0; + @Autowired TaskService taskService; @@ -195,10 +201,11 @@ public void createDeviceEventRule(MultipleDeviceEventRule eventRule) { //setp 0: 创建任务 Integer taskId = null; - if (eventRule.getTriggerType() == 1) { + if (eventRule.getTriggerType() == TRIGGER_TYPE_SCHEDULE) { TaskDto taskDto = new TaskDto(); taskDto.setScheduleConf(eventRule.getScheduleConf()); taskDto.setExecutorParam(generateExecuteParam(eventRule)); + taskDto.setRemark(eventRule.getRemark()); taskId = taskService.createTask(taskDto); } @@ -209,7 +216,7 @@ public void createDeviceEventRule(MultipleDeviceEventRule eventRule) { DB.save(event); //step 2: 保存 表达式,方便回显 - if (ToolUtil.isNotEmpty(eventRule.getExpList())) { + if (TRIGGER_TYPE_CONDITION == eventRule.getTriggerType()) { List expList = new ArrayList<>(); eventRule.getExpList().forEach(i -> { @@ -219,22 +226,8 @@ public void createDeviceEventRule(MultipleDeviceEventRule eventRule) { }); DB.saveAll(expList); - } - - //step 3: 保存触发器 调用 本产品方法 - if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { - eventRule.getDeviceServices().forEach(i -> { - DB.sqlUpdate("insert into product_event_service(event_rule_id, execute_device_id, service_id) " + - "values (:eventRuleId, :executeDeviceId, :serviceId)") - .setParameter("eventRuleId", eventRule.getEventRuleId()) - .setParameter("executeDeviceId", i.getExecuteDeviceId()) - .setParameter("serviceId", i.getServiceId()) - .execute(); - }); - } - //step 4: 保存关联关系 - if (ToolUtil.isNotEmpty(eventRule.getExpList())) { + //step 3: 保存关联关系 List relationIds = eventRule.getExpList().parallelStream().map(MultipleDeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); if (ToolUtil.isEmpty(relationIds)) { throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); @@ -251,21 +244,35 @@ public void createDeviceEventRule(MultipleDeviceEventRule eventRule) { }); DB.saveAll(productEventRelationList); } + + //step 4: 保存触发器 调用 本产品方法 + if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { + eventRule.getDeviceServices().forEach(i -> { + DB.sqlUpdate("insert into product_event_service(event_rule_id, execute_device_id, service_id) " + + "values (:eventRuleId, :executeDeviceId, :serviceId)") + .setParameter("eventRuleId", eventRule.getEventRuleId()) + .setParameter("executeDeviceId", i.getExecuteDeviceId()) + .setParameter("serviceId", i.getServiceId()) + .execute(); + }); + } + } @Transactional(rollbackFor = Exception.class) public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { //setp 0: 创建任务 - Integer taskId = null; - if (eventRule.getTriggerType() == 1) { + if (TRIGGER_TYPE_SCHEDULE == eventRule.getTriggerType()) { TaskDto taskDto = new TaskDto(); + taskDto.setId(eventRule.getTaskId()); taskDto.setScheduleConf(eventRule.getScheduleConf()); taskDto.setExecutorParam(generateExecuteParam(eventRule)); - taskId = taskService.createTask(taskDto); + taskDto.setRemark(eventRule.getRemark()); + taskService.updateTask(taskDto); } - //step 1: 函数表达式 + //step 1: 删除函数表达式 DB.sqlUpdate("delete from product_event_expression where event_rule_id = :eventRuleId") .setParameter("eventRuleId", eventRule.getEventRuleId()) .execute(); @@ -281,11 +288,11 @@ public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { // step 3: 保存产品告警规则 ProductEvent event = initEventRule(eventRule); event.setEventRuleId(eventRule.getEventRuleId()); - event.setTaskId(taskId); + event.setTaskId(eventRule.getTaskId()); event.update(); //step 4: 保存 表达式,方便回显 - if (ToolUtil.isNotEmpty(eventRule.getExpList())) { + if (TRIGGER_TYPE_CONDITION == eventRule.getTriggerType()) { List expList = new ArrayList<>(); eventRule.getExpList().forEach(i -> { @@ -295,21 +302,8 @@ public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { }); DB.saveAll(expList); - } - - //step 5: 保存触发器 调用 本产品方法 - if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { - eventRule.getDeviceServices().forEach(i -> { - DB.sqlUpdate("insert into product_event_service(event_rule_id,execute_device_id, service_id) values (:eventRuleId, :executeDeviceId, :serviceId)") - .setParameter("eventRuleId", eventRule.getEventRuleId()) - .setParameter("executeDeviceId", i.getExecuteDeviceId()) - .setParameter("serviceId", i.getServiceId()) - .execute(); - }); - } - // step 6: 保存关联关系 - if (ToolUtil.isNotEmpty(eventRule.getExpList())) { + // step 5: 保存关联关系 List relationIds = eventRule.getExpList().parallelStream().map(MultipleDeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); if (ToolUtil.isEmpty(relationIds)) { throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); @@ -325,6 +319,18 @@ public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { }); DB.saveAll(productEventRelationList); } + + //step 6: 保存触发器 调用 本产品方法 + if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { + eventRule.getDeviceServices().forEach(i -> { + DB.sqlUpdate("insert into product_event_service(event_rule_id,execute_device_id, service_id) values (:eventRuleId, :executeDeviceId, :serviceId)") + .setParameter("eventRuleId", eventRule.getEventRuleId()) + .setParameter("executeDeviceId", i.getExecuteDeviceId()) + .setParameter("serviceId", i.getServiceId()) + .execute(); + }); + } + } @@ -380,27 +386,32 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId) { ProductEventRuleDto productEventRuleDto = new ProductEventRuleDto(); ToolUtil.copyProperties(productEvent, productEventRuleDto); - List expList = new QProductEventExpression().eventRuleId.eq(eventRuleId).findList(); - - productEventRuleDto.setExpList(expList); productEventRuleDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).findList()); - ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRuleId).findOne(); - productEventRuleDto.setStatus(productEventRelation.getStatus()); - productEventRuleDto.setRemark(productEventRelation.getRemark()); - productEventRuleDto.setInherit(productEventRelation.getInherit()); - if (InheritStatus.YES.getCode().equals(productEventRelation.getInherit())) { - ProductEventRelation one = new QProductEventRelation().eventRuleId.eq(eventRuleId).inherit.eq(InheritStatus.NO.getCode()).findOne(); - productEventRuleDto.setInheritProductId(one.getRelationId()); - } + if (TRIGGER_TYPE_CONDITION == productEvent.getTriggerType()) { + List expList = new QProductEventExpression().eventRuleId.eq(eventRuleId).findList(); + productEventRuleDto.setExpList(expList); + + ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRuleId).findOne(); + productEventRuleDto.setStatus(productEventRelation.getStatus()); + productEventRuleDto.setRemark(productEventRelation.getRemark()); + productEventRuleDto.setInherit(productEventRelation.getInherit()); + if (InheritStatus.YES.getCode().equals(productEventRelation.getInherit())) { + ProductEventRelation one = new QProductEventRelation().eventRuleId.eq(eventRuleId).inherit.eq(InheritStatus.NO.getCode()).findOne(); + productEventRuleDto.setInheritProductId(one.getRelationId()); + } - JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); - List tagList = JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class); + JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); + List tagList = JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class); - productEventRuleDto.setZbxId(productEventRelation.getZbxId()); - productEventRuleDto.setTags(tagList.stream() - .filter(s -> !s.getTag().equals("__execute__") && !s.getTag().equals("__alarm__") && !s.getTag().equals("__event__")) - .collect(Collectors.toList())); + productEventRuleDto.setZbxId(productEventRelation.getZbxId()); + productEventRuleDto.setTags(tagList.stream() + .filter(s -> !s.getTag().equals("__execute__") && !s.getTag().equals("__alarm__") && !s.getTag().equals("__event__")) + .collect(Collectors.toList())); + } else { + Task task = new QTask().id.eq(productEvent.getTaskId()).findOne(); + productEventRuleDto.setScheduleConf(task.getScheduleConf()); + } return productEventRuleDto; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java new file mode 100644 index 00000000..550f4186 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java @@ -0,0 +1,61 @@ +package com.zmops.iot.web.device.service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.dtflys.forest.Forest; +import com.google.common.eventbus.Subscribe; +import com.zmops.iot.async.executor.Async; +import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.service.work.DeviceServiceLogWorker; +import com.zmops.iot.web.device.service.work.ScenesLogWorker; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; + +/** + * @author yefei + **/ +@Slf4j +@Service +public class SceneScheduleProcessor { + + @Autowired + DeviceServiceLogWorker deviceServiceLogWorker; + + @Autowired + ScenesLogWorker scenesLogWorker; + + @Subscribe + public void subscribe(String event) { + log.info("子线程接收异步事件 - {},String类型", event); + if(ToolUtil.isEmpty(event)){ + return; + } + Map eventMap = JSONObject.parseObject(event,Map.class); + Long eventRuleId = Long.parseLong(eventMap.get("eventRuleId").toString()); + + Map alarmInfo = new ConcurrentHashMap<>(3); + alarmInfo.put("eventRuleId", eventRuleId); + alarmInfo.put("triggerType", "定时"); + + WorkerWrapper, Boolean> deviceServiceLogWork = new WorkerWrapper.Builder, Boolean>().id("deviceServiceLogWorker") + .worker(deviceServiceLogWorker).param(alarmInfo) + .build(); + WorkerWrapper, Boolean> scenesLogWork = new WorkerWrapper.Builder, Boolean>().id("scenesLogWorker") + .worker(scenesLogWorker).param(alarmInfo) + .build(); + + try { + Async.beginWork(1000, deviceServiceLogWork, scenesLogWork); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + + Forest.post("/device/action/exec").host("127.0.0.1").port(12800).contentTypeJson().addBody(JSON.toJSON(eventMap.get("executeParam"))).execute(); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java index bf2fb074..d75f8792 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java @@ -2,11 +2,13 @@ import com.zmops.iot.domain.product.ProductEventExpression; import com.zmops.iot.domain.product.ProductEventService; +import com.zmops.iot.model.cache.filter.CachedValue; import lombok.Data; import lombok.Getter; import lombok.Setter; import javax.validation.constraints.Max; +import javax.validation.constraints.NotNull; import java.util.List; /** @@ -46,6 +48,11 @@ public class ProductEventRuleDto { private String inheritProductId; + private String scheduleConf; + + @CachedValue(value = "triggerType") + private Integer triggerType; + @Data public static class Tag { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java index d62f7b0c..475d46bf 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java @@ -30,7 +30,7 @@ public TaskScheduleImpl(ScheduleConfig scheduleConfig) { private Thread ringThread; private volatile boolean scheduleThreadToStop = false; private volatile boolean ringThreadToStop = false; - private static final Map> ringData = new ConcurrentHashMap<>(); + private static final Map> ringData = new ConcurrentHashMap<>(); public void start() { @@ -71,23 +71,23 @@ public void start() { MisfireStrategyEnum misfireStrategyEnum = MisfireStrategyEnum.match(task.getMisfireStrategy(), MisfireStrategyEnum.DO_NOTHING); if (MisfireStrategyEnum.FIRE_ONCE_NOW == misfireStrategyEnum) { - TaskTriggerPool.trigger(task.getId(), TriggerTypeEnum.MISFIRE, -1, null, null); + TaskTriggerPool.trigger(task.getId(), TriggerTypeEnum.MISFIRE, -1, task.getExecutorParam(), null); } refreshNextValidTime(task, new Date()); } else if (nowTime > task.getTriggerNextTime()) { - TaskTriggerPool.trigger(task.getId(), TriggerTypeEnum.CRON, -1, null, null); + TaskTriggerPool.trigger(task.getId(), TriggerTypeEnum.CRON, -1, task.getExecutorParam(), null); refreshNextValidTime(task, new Date()); if (CommonStatus.ENABLE.getCode().equals(task.getTriggerStatus()) && nowTime + PRE_READ_MS > task.getTriggerNextTime()) { int ringSecond = (int) ((task.getTriggerNextTime() / 1000) % 60); - pushTimeRing(ringSecond, task.getId()); + pushTimeRing(ringSecond, task.getExecutorParam()); refreshNextValidTime(task, new Date(task.getTriggerNextTime())); } } else { int ringSecond = (int) ((task.getTriggerNextTime() / 1000) % 60); - pushTimeRing(ringSecond, task.getId()); + pushTimeRing(ringSecond, task.getExecutorParam()); refreshNextValidTime(task, new Date(task.getTriggerNextTime())); } } @@ -136,10 +136,10 @@ public void start() { } try { - List ringItemData = new ArrayList<>(); + List ringItemData = new ArrayList<>(); int nowSecond = Calendar.getInstance().get(Calendar.SECOND); // 避免处理耗时太长,跨过刻度,向前校验一个刻度; for (int i = 0; i < 2; i++) { - List tmpData = ringData.remove((nowSecond + 60 - i) % 60); + List tmpData = ringData.remove((nowSecond + 60 - i) % 60); if (tmpData != null) { ringItemData.addAll(tmpData); } @@ -148,8 +148,8 @@ public void start() { log.debug("time-ring beat : " + nowSecond + " = " + Collections.singletonList(ringItemData)); if (ringItemData.size() > 0) { - for (int jobId : ringItemData) { - TaskTriggerPool.trigger(jobId, TriggerTypeEnum.CRON, -1, null, null); + for (String param : ringItemData) { + TaskTriggerPool.trigger(0, TriggerTypeEnum.CRON, -1, param, null); } ringItemData.clear(); } @@ -179,9 +179,9 @@ private void refreshNextValidTime(Task task, Date fromTime) throws Exception { } } - private void pushTimeRing(int ringSecond, int jobId) { - List ringItemData = ringData.computeIfAbsent(ringSecond, k -> new ArrayList()); - ringItemData.add(jobId); + private void pushTimeRing(int ringSecond, String executeParam) { + List ringItemData = ringData.computeIfAbsent(ringSecond, k -> new ArrayList()); + ringItemData.add(executeParam); } @@ -208,7 +208,7 @@ public void toStop() { boolean hasRingData = false; if (!ringData.isEmpty()) { for (int second : ringData.keySet()) { - List tmpData = ringData.get(second); + List tmpData = ringData.get(second); if (tmpData != null && tmpData.size() > 0) { hasRingData = true; break; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskStarter.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskStarter.java index 03766bb2..67848839 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskStarter.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskStarter.java @@ -1,8 +1,15 @@ package com.zmops.iot.web.schedule; + +import com.zmops.iot.web.device.service.SceneScheduleProcessor; import com.zmops.iot.web.schedule.config.ScheduleConfig; +import com.zmops.zeus.iot.server.eventbus.core.EventControllerFactory; +import com.zmops.zeus.iot.server.eventbus.thread.ThreadPoolFactory; +import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadCustomization; +import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadParameter; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** @@ -12,9 +19,12 @@ @Component public class TaskStarter implements InitializingBean, DisposableBean { - private TaskTriggerPool triggerPool; + private TaskTriggerPool triggerPool; private TaskScheduleImpl schedule; + @Autowired + SceneScheduleProcessor sceneScheduleProcessor; + @Override public void destroy() throws Exception { schedule.toStop(); @@ -26,9 +36,15 @@ public void afterPropertiesSet() throws Exception { ScheduleConfig scheduleConfig = new ScheduleConfig(); - triggerPool = new TaskTriggerPool(scheduleConfig); + ThreadPoolFactory threadPoolFactory = new ThreadPoolFactory(new ThreadCustomization(), new ThreadParameter()); + + EventControllerFactory eventControllerFactory = new EventControllerFactory(threadPoolFactory); + + triggerPool = new TaskTriggerPool(scheduleConfig,eventControllerFactory); triggerPool.start(); + eventControllerFactory.getAsyncController("scene").register(sceneScheduleProcessor); + schedule = new TaskScheduleImpl(scheduleConfig); schedule.start(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java index d3c7121e..e0ca70db 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java @@ -1,6 +1,7 @@ package com.zmops.iot.web.schedule; import com.zmops.iot.web.schedule.config.ScheduleConfig; +import com.zmops.zeus.iot.server.eventbus.core.EventControllerFactory; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.*; @@ -16,11 +17,13 @@ public class TaskTriggerPool { private ThreadPoolExecutor fastTriggerPool = null; private ThreadPoolExecutor slowTriggerPool = null; + private EventControllerFactory eventControllerFactory; private final ScheduleConfig scheduleConfig; - public TaskTriggerPool(ScheduleConfig scheduleConfig) { + public TaskTriggerPool(ScheduleConfig scheduleConfig,EventControllerFactory eventControllerFactory) { this.scheduleConfig = scheduleConfig; + this.eventControllerFactory = eventControllerFactory; helper = this; } @@ -48,8 +51,8 @@ public void stop() { slowTriggerPool.shutdownNow(); } - private volatile long minTim = System.currentTimeMillis() / 60000; - private final ConcurrentMap jobTimeoutCountMap = new ConcurrentHashMap<>(); + private volatile long minTim = System.currentTimeMillis() / 60000; + private final ConcurrentMap jobTimeoutCountMap = new ConcurrentHashMap<>(); public void addTrigger(final int jobId, @@ -68,7 +71,9 @@ public void addTrigger(final int jobId, long start = System.currentTimeMillis(); try { - log.info("jobid : {}", jobId); + log.info("jobid : {},executeParam : {}", jobId,executorParam); + + eventControllerFactory.getAsyncController("scene").post(executorParam); } catch (Exception e) { log.error(e.getMessage(), e); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/task/service/TaskService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/task/service/TaskService.java index 500e42c3..01fe4147 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/task/service/TaskService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/task/service/TaskService.java @@ -35,9 +35,18 @@ public Integer createTask(TaskDto taskDto) { * @return */ public TaskDto updateTask(TaskDto taskDto) { - Task task = new Task(); - BeanUtil.copyProperties(taskDto, task); - DB.update(task); + Task task = new QTask().id.eq(taskDto.getId()).findOne(); + if (task == null) { + task = new Task(); + BeanUtil.copyProperties(taskDto, task); + DB.insert(task); + } else { + task.setExecutorParam(taskDto.getExecutorParam()); + task.setScheduleConf(taskDto.getScheduleConf()); + task.setRemark(taskDto.getRemark()); + DB.update(task); + } + return taskDto; } From b08a7fe2878f5e25aea65f73a99ae2e89b5a78bb Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 15 Nov 2021 11:59:32 +0800 Subject: [PATCH 649/763] [fix]: fix service log --- .../web/device/service/DeviceSvrService.java | 23 +++++++++++++++---- .../MultipleDeviceEventRuleService.java | 5 ++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java index d91f1757..1d4611c7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java @@ -1,16 +1,23 @@ package com.zmops.iot.web.device.service; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.dtflys.forest.Forest; +import com.zmops.iot.core.auth.context.LoginContextHolder; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.ServiceExecuteRecord; +import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductService; import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.product.query.QProductService; import com.zmops.iot.domain.product.query.QProductServiceParam; import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import org.springframework.stereotype.Service; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -28,10 +35,7 @@ public void execute(String deviceId, Long serviceId) { List> list = new ArrayList<>(); Map map = new ConcurrentHashMap<>(2); -// Device device = new QDevice().deviceId.eq(deviceId).findOne(); -// if (null == device) { -// throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); -// } + map.put("device", deviceId); List> serviceList = new ArrayList<>(); @@ -52,5 +56,16 @@ public void execute(String deviceId, Long serviceId) { list.add(map); Forest.post("/device/action/exec").host("127.0.0.1").port(12800).contentTypeJson().addBody(JSON.toJSON(list)).execute(); + + ServiceExecuteRecord serviceExecuteRecord = new ServiceExecuteRecord(); + serviceExecuteRecord.setDeviceId(deviceId); + if (ToolUtil.isNotEmpty(paramList)) { + serviceExecuteRecord.setParam(JSONObject.toJSONString(paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue)))); + } + serviceExecuteRecord.setServiceName(DefinitionsUtil.getServiceName(serviceId)); + + serviceExecuteRecord.setCreateTime(LocalDateTime.now()); + serviceExecuteRecord.setExecuteType("手动"); + serviceExecuteRecord.setExecuteUser(LoginContextHolder.getContext().getUserId()); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index 21deb9ca..ef03b6cf 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.dtflys.forest.Forest; +import com.zmops.iot.async.callback.ICallback; import com.zmops.iot.async.executor.Async; import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.*; @@ -450,10 +451,10 @@ public void execute(Long eventRuleId, String type, Long userId) { } WorkerWrapper, Boolean> deviceServiceLogWork = new WorkerWrapper.Builder, Boolean>().id("deviceServiceLogWorker") - .worker(deviceServiceLogWorker).param(alarmInfo) + .worker(deviceServiceLogWorker).param(alarmInfo).callback(ICallback.PRINT_EXCEPTION_STACK_TRACE) .build(); WorkerWrapper, Boolean> scenesLogWork = new WorkerWrapper.Builder, Boolean>().id("scenesLogWorker") - .worker(scenesLogWorker).param(alarmInfo) + .worker(scenesLogWorker).param(alarmInfo).callback(ICallback.PRINT_EXCEPTION_STACK_TRACE) .build(); try { From 48524e3af09a86c4d75f5afbc6fb873bd42e9acf Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 15 Nov 2021 12:01:51 +0800 Subject: [PATCH 650/763] [fix]: fix service log --- .../java/com/zmops/iot/web/device/service/DeviceSvrService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java index 1d4611c7..44baee2d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java @@ -46,7 +46,7 @@ public void execute(String deviceId, Long serviceId) { } serviceMap.put("name", productService.getName()); - List paramList = new QProductServiceParam().serviceId.eq(serviceId).findList(); + List paramList = DefinitionsUtil.getServiceParam(serviceId); if (ToolUtil.isNotEmpty(paramList)) { serviceMap.put("param", paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue))); } From e50ebb03342889058e10c5f6ecfb1b46942c03ab Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 15 Nov 2021 12:42:18 +0800 Subject: [PATCH 651/763] [fix]: fix trigger type default value --- .../zmops/iot/web/device/dto/MultipleDeviceEventRule.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java index 457d1652..073567fc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java @@ -7,7 +7,6 @@ import lombok.Setter; import org.apache.commons.lang.StringUtils; -import javax.validation.Valid; import javax.validation.constraints.Max; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; @@ -38,7 +37,7 @@ public class MultipleDeviceEventRule { // 表达式列表 private List expList; - private String expLogic="and"; // and or + private String expLogic = "and"; // and or private String remark; @@ -59,7 +58,7 @@ public class MultipleDeviceEventRule { private String scheduleConf; @NotNull - private Integer triggerType; + private Integer triggerType = 0; private Integer taskId; From 1ab783a843dac2037cf199ad44ed482cbcb49e9c Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 15 Nov 2021 13:09:10 +0800 Subject: [PATCH 652/763] [fix]:fix product event trigger --- .../com/zmops/iot/web/product/dto/ProductEventDto.java | 1 + .../com/zmops/iot/web/product/dto/param/EventParm.java | 2 -- .../iot/web/product/service/ProductEventRuleService.java | 7 ++++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java index ee9548e1..2d8d9f5d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java @@ -37,4 +37,5 @@ public class ProductEventDto { @CachedValue(type = DicType.SysUserName) private Long updateUser; private String updateTime; + private Integer taskId; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/EventParm.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/EventParm.java index 835d7f0e..f5a13ec3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/EventParm.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/EventParm.java @@ -16,6 +16,4 @@ public class EventParm extends BaseQueryParam { @NotBlank private String prodId; - @NotBlank - private String classify; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index e5c15204..e578ebe5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -46,6 +46,7 @@ public class ProductEventRuleService implements CommandLineRunner { @Autowired private ZbxTrigger zbxTrigger; + private static final String TRIGGER_CLASSIFY = "0"; /** * 保存触发器 * @@ -229,9 +230,9 @@ public Pager getEventByPage(EventParm eventParm) { if (ToolUtil.isNotEmpty(eventParm.getEventRuleName())) { query.eventRuleName.contains(eventParm.getEventRuleName()); } - if (ToolUtil.isNotEmpty(eventParm.getClassify())) { - query.classify.eq(eventParm.getClassify()); - } + + query.classify.eq(TRIGGER_CLASSIFY); + List productEventRelationList = new QProductEventRelation().relationId.eq(eventParm.getProdId()).findList(); if (ToolUtil.isEmpty(productEventRelationList)) { return new Pager<>(); From 2a1fd3a68c7a855cd4f0dd8bf534ff16e15abf09 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 15 Nov 2021 13:37:06 +0800 Subject: [PATCH 653/763] [fix]: fix product event trigger --- .../java/com/zmops/iot/web/product/dto/ProductEventDto.java | 2 ++ .../java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java index 2d8d9f5d..49f1384e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java @@ -38,4 +38,6 @@ public class ProductEventDto { private Long updateUser; private String updateTime; private Integer taskId; + @CachedValue(value = "triggerType") + private String triggerType; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java index d75f8792..62162e30 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java @@ -53,6 +53,8 @@ public class ProductEventRuleDto { @CachedValue(value = "triggerType") private Integer triggerType; + private Integer taskId; + @Data public static class Tag { From 0594d91768a195f6ad08ad7602aed127357e614a Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 15 Nov 2021 16:33:31 +0800 Subject: [PATCH 654/763] [fix]: fix product delete --- .../iot/web/device/service/DeviceService.java | 1 + .../product/controller/ProductController.java | 26 ++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 5f1725a3..a3d92f66 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -392,6 +392,7 @@ public String delete(DeviceDto deviceDto) { new QProductServiceRelation().relationId.eq(deviceId).delete(); new QProductEventRelation().relationId.eq(deviceId).delete(); new QProductEventService().deviceId.eq(deviceId).delete(); + new QProductServiceParam().deviceId.eq(deviceId).delete(); return true; }).param(deviceDto.getDeviceId()).build(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java index 71a19c54..8dc72d97 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java @@ -7,7 +7,7 @@ import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.device.query.QTag; import com.zmops.iot.domain.product.Product; -import com.zmops.iot.domain.product.query.QProduct; +import com.zmops.iot.domain.product.query.*; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; @@ -161,6 +161,30 @@ public ResponseData prodDelete(@RequestBody @Validated(value = BaseEntity.Delete //第二步:删除Zabbix对应的模板 productService.zbxTemplateDelete(product.getZbxId() + ""); + //删除关联信息 + List statusFunctionRuleIds = new QProductStatusFunctionRelation().select(QProductStatusFunctionRelation.alias().ruleId).relationId.eq(product.getProductId() + "").findSingleAttributeList(); + if (ToolUtil.isNotEmpty(statusFunctionRuleIds)) { + new QProductStatusFunction().ruleId.in(statusFunctionRuleIds).delete(); + new QProductStatusFunctionRelation().relationId.eq(product.getProductId() + "").delete(); + } + + List serviceIds = new QProductServiceRelation().select(QProductServiceRelation.alias().serviceId).relationId.eq(product.getProductId() + "").findSingleAttributeList(); + if (ToolUtil.isNotEmpty(serviceIds)) { + new QProductService().id.in(serviceIds).delete(); + new QProductServiceParam().serviceId.in(serviceIds).delete(); + new QProductServiceRelation().relationId.eq(product.getProductId() + "").delete(); + } + + List eventIds = new QProductEventRelation().select(QProductEventRelation.alias().eventRuleId).relationId.eq(product.getProductId() + "").findSingleAttributeList(); + if (ToolUtil.isNotEmpty(eventIds)) { + new QProductEvent().eventRuleId.in(eventIds).delete(); + new QProductEventExpression().eventRuleId.in(eventIds).delete(); + new QProductEventService().eventRuleId.in(eventIds).delete(); + new QProductEventRelation().relationId.eq(product.getProductId() + "").delete(); + } + + new QProductAttribute().productId.eq(product.getProductId() + "").delete(); + new QProductAttributeEvent().productId.eq(product.getProductId() + "").delete(); //第三步:删除产品 boolean del = product.delete(); From 93272366f583016e3044a94a3cbc882c5d742153 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 15 Nov 2021 16:50:15 +0800 Subject: [PATCH 655/763] [fix]: fix init sql --- dist-material/bin/sql/zeus-iot.sql | 81 ++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 3 deletions(-) diff --git a/dist-material/bin/sql/zeus-iot.sql b/dist-material/bin/sql/zeus-iot.sql index f24d740c..5f69e99b 100644 --- a/dist-material/bin/sql/zeus-iot.sql +++ b/dist-material/bin/sql/zeus-iot.sql @@ -12,7 +12,7 @@ Target Server Version : 130004 File Encoding : 65001 - Date: 11/11/2021 19:00:16 + Date: 15/11/2021 16:48:12 */ @@ -225,6 +225,17 @@ MAXVALUE 2147483647 START 1 CACHE 1; +-- ---------------------------- +-- Sequence structure for task_info_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."task_info_id_seq"; +CREATE SEQUENCE "public"."task_info_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + -- ---------------------------- -- Table structure for device -- ---------------------------- @@ -652,8 +663,10 @@ CREATE TABLE "public"."product_event" ( "update_user" int8, "exp_logic" varchar(10) COLLATE "pg_catalog"."default", "event_notify" varchar(1) COLLATE "pg_catalog"."default", - "status" char(1) COLLATE "pg_catalog"."default", - "classify" varchar(2) COLLATE "pg_catalog"."default" + "status" varchar(8) COLLATE "pg_catalog"."default", + "classify" varchar(2) COLLATE "pg_catalog"."default", + "task_id" int4, + "trigger_type" int2 ) ; COMMENT ON COLUMN "public"."product_event"."event_rule_id" IS '告警规则ID'; @@ -663,6 +676,8 @@ COMMENT ON COLUMN "public"."product_event"."remark" IS '备注'; COMMENT ON COLUMN "public"."product_event"."exp_logic" IS 'and 或者 or'; COMMENT ON COLUMN "public"."product_event"."event_notify" IS '0 否 1 是'; COMMENT ON COLUMN "public"."product_event"."classify" IS '0 告警 1场景联动'; +COMMENT ON COLUMN "public"."product_event"."task_id" IS '任务ID'; +COMMENT ON COLUMN "public"."product_event"."trigger_type" IS '触发类型 0-条件触发 1-定时触发'; -- ---------------------------- -- Records of product_event @@ -1616,6 +1631,44 @@ COMMENT ON COLUMN "public"."tag"."update_time" IS '更新时间'; -- Records of tag -- ---------------------------- +-- ---------------------------- +-- Table structure for task_info +-- ---------------------------- +DROP TABLE IF EXISTS "public"."task_info"; +CREATE TABLE "public"."task_info" ( + "id" int4 NOT NULL DEFAULT nextval('task_info_id_seq'::regclass), + "remark" varchar(255) COLLATE "pg_catalog"."default", + "task_timeout" int4 NOT NULL, + "task_fail_retry_count" int4 NOT NULL, + "trigger_status" varchar(8) COLLATE "pg_catalog"."default" NOT NULL, + "trigger_last_time" int8 NOT NULL, + "trigger_next_time" int8 NOT NULL, + "misfire_strategy" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "schedule_type" varchar(255) COLLATE "pg_catalog"."default", + "schedule_conf" varchar(255) COLLATE "pg_catalog"."default", + "executor_param" text COLLATE "pg_catalog"."default", + "create_time" timestamp(0), + "create_user" int8, + "update_time" timestamp(0), + "update_user" int8 +) +; +COMMENT ON COLUMN "public"."task_info"."id" IS '任务ID'; +COMMENT ON COLUMN "public"."task_info"."remark" IS '任务描述'; +COMMENT ON COLUMN "public"."task_info"."task_timeout" IS '任务执行超时时间'; +COMMENT ON COLUMN "public"."task_info"."task_fail_retry_count" IS '失败重试次数'; +COMMENT ON COLUMN "public"."task_info"."trigger_status" IS '调度状态:DISABLE-停止,ENABLE-运行'; +COMMENT ON COLUMN "public"."task_info"."trigger_last_time" IS '上次调度时间'; +COMMENT ON COLUMN "public"."task_info"."trigger_next_time" IS '下次调度时间'; +COMMENT ON COLUMN "public"."task_info"."misfire_strategy" IS '调度过期策略'; +COMMENT ON COLUMN "public"."task_info"."schedule_type" IS '调度类型'; +COMMENT ON COLUMN "public"."task_info"."schedule_conf" IS '调度配置,值含义取决于调度类型'; +COMMENT ON COLUMN "public"."task_info"."executor_param" IS '任务执行参数'; + +-- ---------------------------- +-- Records of task_info +-- ---------------------------- + -- ---------------------------- -- Alter sequences owned by -- ---------------------------- @@ -1749,6 +1802,13 @@ ALTER SEQUENCE "public"."tag_id_seq" OWNED BY "public"."tag"."id"; SELECT setval('"public"."tag_id_seq"', 196, true); +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."task_info_id_seq" +OWNED BY "public"."task_info"."id"; +SELECT setval('"public"."task_info_id_seq"', 3, true); + -- ---------------------------- -- Primary Key structure for table device -- ---------------------------- @@ -1829,6 +1889,16 @@ ALTER TABLE "public"."product_event_expression" ADD CONSTRAINT "product_event_co -- ---------------------------- ALTER TABLE "public"."product_event_relation" ADD CONSTRAINT "product_event_relation_pkey" PRIMARY KEY ("id"); +-- ---------------------------- +-- Indexes structure for table product_event_service +-- ---------------------------- +CREATE INDEX "eventRuleId" ON "public"."product_event_service" USING btree ( + "event_rule_id" "pg_catalog"."int8_ops" ASC NULLS LAST +); +CREATE INDEX "serviceId" ON "public"."product_event_service" USING btree ( + "service_id" "pg_catalog"."int8_ops" ASC NULLS LAST +); + -- ---------------------------- -- Primary Key structure for table product_event_tags -- ---------------------------- @@ -1923,3 +1993,8 @@ ALTER TABLE "public"."sys_user_group" ADD CONSTRAINT "sys_user_group_pkey" PRIMA -- Primary Key structure for table tag -- ---------------------------- ALTER TABLE "public"."tag" ADD CONSTRAINT "tag_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table task_info +-- ---------------------------- +ALTER TABLE "public"."task_info" ADD CONSTRAINT "task_info_pkey" PRIMARY KEY ("id"); From 388702cbedeb5a6da10316597147aef8cdf03621 Mon Sep 17 00:00:00 2001 From: nantian Date: Mon, 15 Nov 2021 17:34:24 +0800 Subject: [PATCH 656/763] [doc]: update iot-server readme --- iot-server/readme.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/iot-server/readme.md b/iot-server/readme.md index a76b5c9b..ae925293 100644 --- a/iot-server/readme.md +++ b/iot-server/readme.md @@ -1,2 +1 @@ -#### 宙斯协议层服务 - - 基于Skywalking改造 \ No newline at end of file +#### 宙斯多协议网关 V1.0 \ No newline at end of file From ed2d8b73ef592b0b813e0ef848835c3edc290b9e Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 15 Nov 2021 20:42:34 +0800 Subject: [PATCH 657/763] [fix]: fix default user --- .../main/java/com/zmops/iot/core/auth/model/LoginUser.java | 3 ++- .../zmops/iot/web/auth/LoginContextSpringSecutiryImpl.java | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java index f1852367..691db99f 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java @@ -40,9 +40,10 @@ public LoginUser() { super(); } - public LoginUser(Long id) { + public LoginUser(Long id, String token) { super(); this.id = id; + this.zbxToken = token; } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/LoginContextSpringSecutiryImpl.java b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/LoginContextSpringSecutiryImpl.java index c5ae9643..57eb1d76 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/LoginContextSpringSecutiryImpl.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/LoginContextSpringSecutiryImpl.java @@ -6,6 +6,7 @@ import com.zmops.iot.core.auth.exception.enums.AuthExceptionEnum; import com.zmops.iot.core.auth.model.LoginUser; import com.zmops.iot.core.auth.util.TokenUtil; +import com.zmops.iot.web.init.BasicSettingsInit; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; @@ -23,7 +24,8 @@ public class LoginContextSpringSecutiryImpl implements LoginContext { public LoginUser getUser() { if (null == SecurityContextHolder.getContext().getAuthentication()) { - return new LoginUser(1L); //默认 Admin + //默认 Admin + return new LoginUser(1L, BasicSettingsInit.zbxApiToken); } if (SecurityContextHolder.getContext().getAuthentication().getPrincipal() instanceof String) { From 9af776584e6acd3ea2a909fa5177f9248269a402 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 16 Nov 2021 14:14:00 +0800 Subject: [PATCH 658/763] [fix]: fix check repeat service --- .../controller/DeviceEventTriggerController.java | 5 +++++ .../device/service/DeviceEventRuleService.java | 15 +++++++++++++++ .../service/MultipleDeviceEventRuleService.java | 6 ++++++ .../iot/web/exception/enums/BizExceptionEnum.java | 1 + 4 files changed, 27 insertions(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index 49887f11..01e0acc5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -77,6 +77,8 @@ public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId, @Reque @PostMapping("/create") public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Create.class) DeviceEventRule eventRule) { + //检查是否有重复动作服务 + deviceEventRuleService.checkService(eventRule.getDeviceServices()); Long eventRuleId = IdUtil.getSnowflake().nextId(); // ruleId, trigger name @@ -152,6 +154,9 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); } + //检查是否有重复动作服务 + deviceEventRuleService.checkService(eventRule.getDeviceServices()); + //来自产品的告警规则 只能修改备注 count = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).inherit.eq(InheritStatus.YES.getCode()) .findCount(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 5efe944e..000f79bf 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -286,6 +286,21 @@ public String[] updateZbxTrigger(String triggerId, String expression, Byte level return JSON.parseObject(res, TriggerIds.class).getTriggerids(); } + /** + * 检查动作服务是否重复 + * + * @param deviceServices + */ + public void checkService(List deviceServices) { + if (ToolUtil.isEmpty(deviceServices)) { + return; + } + long count = deviceServices.parallelStream().map(DeviceEventRule.DeviceService::getServiceId).distinct().count(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.SERVICE_HAS_DUPLICATE); + } + } + @Data static class TriggerIds { private String[] triggerids; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index ef03b6cf..42edf4be 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -501,6 +501,12 @@ public void checkParam(MultipleDeviceEventRule eventRule) { throw new ServiceException(BizExceptionEnum.TASK_NOT_SCHEDULE_CONF); } } + + long count = eventRule.getDeviceServices().parallelStream().map(MultipleDeviceEventRule.DeviceService::getServiceId).distinct().count(); + if (count < eventRule.getDeviceServices().size()) { + throw new ServiceException(BizExceptionEnum.SERVICE_HAS_DUPLICATE); + } + } @Data diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index f9bf70b1..af0c0fa2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -160,6 +160,7 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { SERVICE_EXISTS(1601, "服务已存在"), SERVICE_NOT_EXISTS(1602, "服务不存在"), PRODUCT_EVENT_HAS_DEPTED(1605,"服务已用于告警规则或场景联动,不能删除"), + SERVICE_HAS_DUPLICATE(1606,"存在相同的动作服务"), /** * 触发规则相关 From 4fda797d1f23e847156065b32a500d29f7e3a803 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 16 Nov 2021 16:34:57 +0800 Subject: [PATCH 659/763] [feat]: add validated schdule conf --- zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java | 6 ++++++ .../web/device/service/MultipleDeviceEventRuleService.java | 4 ++++ .../com/zmops/iot/web/exception/enums/BizExceptionEnum.java | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java b/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java index c9eb496b..0589fae1 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java @@ -5,6 +5,7 @@ import cn.hutool.core.date.DateUtil; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.exception.enums.CoreExceptionEnum; +import org.apache.logging.log4j.core.util.CronExpression; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; @@ -438,4 +439,9 @@ public static List convertBean(List oriList, Class castClas return resList; } + public static boolean validCron(String cron){ + //String regEx = "(((^([0-9]|[0-5][0-9])(\\,|\\-|\\/){1}([0-9]|[0-5][0-9]))|^([0-9]|[0-5][0-9])|^(\\* ))((([0-9]|[0-5][0-9])(\\,|\\-|\\/){1}([0-9]|[0-5][0-9]) )|([0-9]|[0-5][0-9]) |(\\* ))((([0-9]|[01][0-9]|2[0-3])(\\,|\\-|\\/){1}([0-9]|[01][0-9]|2[0-3]) )|([0-9]|[01][0-9]|2[0-3]) |(\\* ))((([0-9]|[0-2][0-9]|3[01])(\\,|\\-|\\/){1}([0-9]|[0-2][0-9]|3[01]) )|(([0-9]|[0-2][0-9]|3[01]) )|(\\? )|(\\* )|(([1-9]|[0-2][0-9]|3[01])L )|([1-7]W )|(LW )|([1-7]\\#[1-4] ))((([1-9]|0[1-9]|1[0-2])(\\,|\\-|\\/){1}([1-9]|0[1-9]|1[0-2]) )|([1-9]|0[1-9]|1[0-2]) |(\\* ))(([1-7](\\,|\\-|\\/){1}[1-7])|([1-7])|(\\?)|(\\*)|(([1-7]L)|([1-7]\\#[1-4]))))|(((^([0-9]|[0-5][0-9])(\\,|\\-|\\/){1}([0-9]|[0-5][0-9]) )|^([0-9]|[0-5][0-9]) |^(\\* ))((([0-9]|[0-5][0-9])(\\,|\\-|\\/){1}([0-9]|[0-5][0-9]) )|([0-9]|[0-5][0-9]) |(\\* ))((([0-9]|[01][0-9]|2[0-3])(\\,|\\-|\\/){1}([0-9]|[01][0-9]|2[0-3]) )|([0-9]|[01][0-9]|2[0-3]) |(\\* ))((([0-9]|[0-2][0-9]|3[01])(\\,|\\-|\\/){1}([0-9]|[0-2][0-9]|3[01]) )|(([0-9]|[0-2][0-9]|3[01]) )|(\\? )|(\\* )|(([1-9]|[0-2][0-9]|3[01])L )|([1-7]W )|(LW )|([1-7]\\#[1-4] ))((([1-9]|0[1-9]|1[0-2])(\\,|\\-|\\/){1}([1-9]|0[1-9]|1[0-2]) )|([1-9]|0[1-9]|1[0-2]) |(\\* ))(([1-7](\\,|\\-|\\/){1}[1-7] )|([1-7] )|(\\? )|(\\* )|(([1-7]L )|([1-7]\\#[1-4]) ))((19[789][0-9]|20[0-9][0-9])\\-(19[789][0-9]|20[0-9][0-9])))"; + //String tests = "0 0 0 L * ?"; + return CronExpression.isValidExpression(cron); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index 42edf4be..007dd18c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -500,6 +500,10 @@ public void checkParam(MultipleDeviceEventRule eventRule) { if (ToolUtil.isEmpty(eventRule.getScheduleConf())) { throw new ServiceException(BizExceptionEnum.TASK_NOT_SCHEDULE_CONF); } + + if (ToolUtil.validCron(eventRule.getScheduleConf())) { + throw new ServiceException(BizExceptionEnum.TASK_SCHEDULE_CONF_NOT_MATCH); + } } long count = eventRule.getDeviceServices().parallelStream().map(MultipleDeviceEventRule.DeviceService::getServiceId).distinct().count(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index af0c0fa2..376b500b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -183,7 +183,7 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { * @param message */ TASK_NOT_SCHEDULE_CONF(2201,"任务调度配置不能为空"), - + TASK_SCHEDULE_CONF_NOT_MATCH(2202,"任务调度配置不正确"), /** * 租户相关的异常 */ From b586be8f3188bfcb67eeca51a115402b7c0e9c2b Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 16 Nov 2021 18:10:58 +0800 Subject: [PATCH 660/763] [fix]: fix scene --- .../iot/web/analyse/service/HomeService.java | 3 +++ .../MultipleDeviceEventTriggerController.java | 12 ++++++++---- .../service/MultipleDeviceEventRuleService.java | 17 +++++++++++------ 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index 504eb71e..5a9ebeac 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -315,6 +315,9 @@ public List> getAlarmTop(long timeFrom, long timeTill) { List> topList = new ArrayList<>(); tmpMap.forEach((key, value) -> { + if (DefinitionsUtil.getDeviceName(key) == null) { + return; + } Map alarmMap = new ConcurrentHashMap<>(2); alarmMap.put("name", DefinitionsUtil.getDeviceName(key)); alarmMap.put("value", value); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java index 1fd02af2..31d70ff2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java @@ -189,19 +189,23 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn //检查参数 multipleDeviceEventRuleService.checkParam(eventRule); - //step 1: 删除原有的 关联关系 + //step 1: 删除原有的 关联关系 并重新建立 关联关系 + ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()) + .findOne(); eventRule.setTaskId(productEvent.getTaskId()); + if (null != productEventRelation) { + eventRule.setZbxId(productEventRelation.getZbxId()); + } multipleDeviceEventRuleService.updateDeviceEventRule(eventRule); if (TRIGGER_TYPE_CONDITION == eventRule.getTriggerType()) { - ProductEventRelation productEventRelation = new QProductEventRelation().setMaxRows(1).eventRuleId.eq(eventRule.getEventRuleId()) - .findOne(); + //step 1: 先创建 zbx 触发器 String expression = eventRule.getExpList() .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); //step 2: zbx 保存触发器 - String[] triggerIds = multipleDeviceEventRuleService.updateZbxTrigger(productEventRelation.getZbxId(), expression, eventRule.getEventLevel()); + String[] triggerIds = multipleDeviceEventRuleService.createZbxTrigger(eventRule.getEventRuleId() + "", expression, eventRule.getEventLevel()); //step 4: zbx 触发器创建 Tag Map tags = new ConcurrentHashMap<>(1); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index 007dd18c..f3e376d8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -273,12 +273,17 @@ public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { taskService.updateTask(taskDto); } - //step 1: 删除函数表达式 + //setp 1: 删除zbx触发器 + if (ToolUtil.isNotEmpty(eventRule.getZbxId())) { + zbxTrigger.triggerDelete(eventRule.getZbxId()); + } + + //step 2: 删除函数表达式 DB.sqlUpdate("delete from product_event_expression where event_rule_id = :eventRuleId") .setParameter("eventRuleId", eventRule.getEventRuleId()) .execute(); - //step 2: 删除服务方法调用 + //step 3: 删除服务方法调用 DB.sqlUpdate("delete from product_event_service where event_rule_id = :eventRuleId") .setParameter("eventRuleId", eventRule.getEventRuleId()) .execute(); @@ -286,13 +291,13 @@ public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { // 删除和所有设备的关联关系 new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); - // step 3: 保存产品告警规则 + // step 4: 保存产品告警规则 ProductEvent event = initEventRule(eventRule); event.setEventRuleId(eventRule.getEventRuleId()); event.setTaskId(eventRule.getTaskId()); event.update(); - //step 4: 保存 表达式,方便回显 + //step 5: 保存 表达式,方便回显 if (TRIGGER_TYPE_CONDITION == eventRule.getTriggerType()) { List expList = new ArrayList<>(); @@ -304,7 +309,7 @@ public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { DB.saveAll(expList); - // step 5: 保存关联关系 + // step 6: 保存关联关系 List relationIds = eventRule.getExpList().parallelStream().map(MultipleDeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); if (ToolUtil.isEmpty(relationIds)) { throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); @@ -321,7 +326,7 @@ public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { DB.saveAll(productEventRelationList); } - //step 6: 保存触发器 调用 本产品方法 + //step 7: 保存触发器 调用 本产品方法 if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { eventRule.getDeviceServices().forEach(i -> { DB.sqlUpdate("insert into product_event_service(event_rule_id,execute_device_id, service_id) values (:eventRuleId, :executeDeviceId, :serviceId)") From c0d4e89b23834fc2df709c82a4830137f797b250 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 16 Nov 2021 18:28:19 +0800 Subject: [PATCH 661/763] [fix]: fix bug --- .../iot/web/device/service/MultipleDeviceEventRuleService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index f3e376d8..a83a4cb7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -506,7 +506,7 @@ public void checkParam(MultipleDeviceEventRule eventRule) { throw new ServiceException(BizExceptionEnum.TASK_NOT_SCHEDULE_CONF); } - if (ToolUtil.validCron(eventRule.getScheduleConf())) { + if (!ToolUtil.validCron(eventRule.getScheduleConf())) { throw new ServiceException(BizExceptionEnum.TASK_SCHEDULE_CONF_NOT_MATCH); } } From 61c24a96da75d8c033d7852648ab64f26d551fe1 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 16 Nov 2021 19:21:11 +0800 Subject: [PATCH 662/763] [fix]: fix scene --- .../controller/MultipleDeviceEventTriggerController.java | 3 +-- .../web/device/service/MultipleDeviceEventRuleService.java | 6 +----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java index 31d70ff2..a1358396 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java @@ -190,8 +190,7 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn multipleDeviceEventRuleService.checkParam(eventRule); //step 1: 删除原有的 关联关系 并重新建立 关联关系 - ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()) - .findOne(); + ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).setMaxRows(1).findOne(); eventRule.setTaskId(productEvent.getTaskId()); if (null != productEventRelation) { eventRule.setZbxId(productEventRelation.getZbxId()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index a83a4cb7..15ccf352 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -398,14 +398,10 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId) { List expList = new QProductEventExpression().eventRuleId.eq(eventRuleId).findList(); productEventRuleDto.setExpList(expList); - ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRuleId).findOne(); + ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRuleId).setMaxRows(1).findOne(); productEventRuleDto.setStatus(productEventRelation.getStatus()); productEventRuleDto.setRemark(productEventRelation.getRemark()); productEventRuleDto.setInherit(productEventRelation.getInherit()); - if (InheritStatus.YES.getCode().equals(productEventRelation.getInherit())) { - ProductEventRelation one = new QProductEventRelation().eventRuleId.eq(eventRuleId).inherit.eq(InheritStatus.NO.getCode()).findOne(); - productEventRuleDto.setInheritProductId(one.getRelationId()); - } JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); List tagList = JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class); From 53af700bf3d3ecc6516f23e080937c1dbb95001b Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 16 Nov 2021 19:49:38 +0800 Subject: [PATCH 663/763] [fix]: fix bug --- .../device/service/MultipleDeviceEventRuleService.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index 15ccf352..5a164821 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -266,11 +266,15 @@ public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { //setp 0: 创建任务 if (TRIGGER_TYPE_SCHEDULE == eventRule.getTriggerType()) { TaskDto taskDto = new TaskDto(); - taskDto.setId(eventRule.getTaskId()); taskDto.setScheduleConf(eventRule.getScheduleConf()); taskDto.setExecutorParam(generateExecuteParam(eventRule)); taskDto.setRemark(eventRule.getRemark()); - taskService.updateTask(taskDto); + if (ToolUtil.isEmpty(eventRule.getTaskId())) { + taskService.createTask(taskDto); + } else { + taskDto.setId(eventRule.getTaskId()); + taskService.updateTask(taskDto); + } } //setp 1: 删除zbx触发器 From fb961aa057c62ebecce49d2053a0de19cf6fce66 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 16 Nov 2021 20:07:27 +0800 Subject: [PATCH 664/763] [fix]: fix scene --- .../iot/web/device/service/MultipleDeviceEventRuleService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index 5a164821..9a9b31d8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -270,7 +270,8 @@ public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { taskDto.setExecutorParam(generateExecuteParam(eventRule)); taskDto.setRemark(eventRule.getRemark()); if (ToolUtil.isEmpty(eventRule.getTaskId())) { - taskService.createTask(taskDto); + int taskId = taskService.createTask(taskDto); + eventRule.setTaskId(taskId); } else { taskDto.setId(eventRule.getTaskId()); taskService.updateTask(taskDto); From 79490888c6cdc39fff7aa6a76494bd376e1a6cfa Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 17 Nov 2021 09:46:57 +0800 Subject: [PATCH 665/763] [fix]: fix scene detail --- .../device/service/MultipleDeviceEventRuleService.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index 9a9b31d8..b72cc8fa 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -38,10 +38,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; @@ -417,7 +414,8 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId) { .collect(Collectors.toList())); } else { Task task = new QTask().id.eq(productEvent.getTaskId()).findOne(); - productEventRuleDto.setScheduleConf(task.getScheduleConf()); + productEventRuleDto.setScheduleConf(Optional.ofNullable(task).map(Task::getScheduleConf).orElse("")); + productEventRuleDto.setExpList(Collections.emptyList()); } return productEventRuleDto; From 2db0e157b83255ad4e8448606c473177402558a0 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 17 Nov 2021 14:49:14 +0800 Subject: [PATCH 666/763] [feat]: scene add time interval --- .../product/ProductEventTimeInterval.java | 28 ++++++ .../MultipleDeviceEventTriggerController.java | 25 +++--- .../device/dto/MultipleDeviceEventDto.java | 16 ++++ .../device/dto/MultipleDeviceEventRule.java | 14 +++ .../MultipleDeviceEventRuleService.java | 89 +++++++++++++------ .../service/SceneScheduleProcessor.java | 15 ++-- 6 files changed, 146 insertions(+), 41 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventTimeInterval.java diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventTimeInterval.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventTimeInterval.java new file mode 100644 index 00000000..9d494083 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventTimeInterval.java @@ -0,0 +1,28 @@ +package com.zmops.iot.domain.product; + +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + *

+ * 触发器 时间 表达式 函数 + */ + +@Data +@Entity +@Table(name = "product_event_time_interval") +public class ProductEventTimeInterval { + + @Id + private Long eventTimeId; + + private Long eventRuleId; + + private Integer startTime; + + private Integer endTime; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java index a1358396..a66cd1a2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java @@ -6,10 +6,7 @@ import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.ProductEventRelation; -import com.zmops.iot.domain.product.query.QProductEvent; -import com.zmops.iot.domain.product.query.QProductEventExpression; -import com.zmops.iot.domain.product.query.QProductEventRelation; -import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.domain.product.query.*; import com.zmops.iot.domain.schedule.Task; import com.zmops.iot.domain.schedule.query.QTask; import com.zmops.iot.enums.CommonStatus; @@ -31,11 +28,11 @@ import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; -import static com.zmops.iot.web.device.service.MultipleDeviceEventRuleService.TRIGGER_TYPE_CONDITION; -import static com.zmops.iot.web.device.service.MultipleDeviceEventRuleService.TRIGGER_TYPE_SCHEDULE; +import static com.zmops.iot.web.device.service.MultipleDeviceEventRuleService.*; /** * @author yefei @@ -52,8 +49,6 @@ public class MultipleDeviceEventTriggerController { @Autowired private ZbxTrigger zbxTrigger; - private static final String EXECUTE_TAG_NAME = "__scene__"; - /** * 场景 分页列表 * @@ -114,7 +109,11 @@ public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEn //step 1: 先创建 zbx 触发器 String expression = eventRule.getExpList() .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); - + //时间区间表达式 + if (ToolUtil.isNotEmpty(eventRule.getTimeIntervals())) { + String timeExpression = eventRule.getTimeIntervals().parallelStream().map(Objects::toString).collect(Collectors.joining(" or ")); + expression = "(" + expression + ") and (" + timeExpression + ")"; + } //step 2: zbx 保存触发器 String[] triggerIds = multipleDeviceEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); @@ -202,7 +201,11 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn //step 1: 先创建 zbx 触发器 String expression = eventRule.getExpList() .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); - + //时间区间表达式 + if (ToolUtil.isNotEmpty(eventRule.getTimeIntervals())) { + String timeExpression = eventRule.getTimeIntervals().parallelStream().map(Objects::toString).collect(Collectors.joining(" or ")); + expression = "(" + expression + ") and (" + timeExpression + ")"; + } //step 2: zbx 保存触发器 String[] triggerIds = multipleDeviceEventRuleService.createZbxTrigger(eventRule.getEventRuleId() + "", expression, eventRule.getEventLevel()); @@ -262,6 +265,8 @@ public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseE //step 2:删除 关联的表达式 new QProductEventExpression().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + //step 3:删除 关联的时间表达式 + new QProductEventTimeInterval().eventRuleId.eq(eventRule.getEventRuleId()).delete(); } else { //step 1:删除 定时器 new QTask().id.eq(productEvent.getTaskId()).delete(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java index 526e1981..2d605350 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java @@ -1,11 +1,17 @@ package com.zmops.iot.web.device.dto; import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.domain.product.ProductEventExpression; +import com.zmops.iot.domain.product.ProductEventService; +import com.zmops.iot.domain.product.ProductEventTimeInterval; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; import com.zmops.iot.model.cache.filter.DicType; +import com.zmops.iot.web.product.dto.ProductEventRuleDto; import lombok.Data; +import java.util.List; + /** * @author yefei **/ @@ -45,4 +51,14 @@ public class MultipleDeviceEventDto { @CachedValue(value = "triggerType") private String triggerType; + + private String scheduleConf; + + private List expList; + + private List deviceServices; + + private List tags; + + private List timeExpList; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java index 073567fc..58e07e03 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java @@ -62,6 +62,8 @@ public class MultipleDeviceEventRule { private Integer taskId; + private List timeIntervals; + @Data public static class Tag { @@ -136,6 +138,18 @@ public static class DeviceService { } + @Getter + @Setter + public static class TimeInterval { + private Integer startTime; + private Integer endTime; + + @Override + public String toString() { + return "(time()>= " + startTime + " and " + " time()< " + endTime + " )"; + } + } + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index b72cc8fa..310c84d7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -8,10 +8,7 @@ import com.zmops.iot.async.executor.Async; import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.*; -import com.zmops.iot.domain.product.query.QProductEvent; -import com.zmops.iot.domain.product.query.QProductEventExpression; -import com.zmops.iot.domain.product.query.QProductEventRelation; -import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.domain.product.query.*; import com.zmops.iot.domain.schedule.Task; import com.zmops.iot.domain.schedule.query.QTask; import com.zmops.iot.enums.CommonStatus; @@ -28,7 +25,6 @@ import com.zmops.iot.web.device.service.work.DeviceServiceLogWorker; import com.zmops.iot.web.device.service.work.ScenesLogWorker; import com.zmops.iot.web.exception.enums.BizExceptionEnum; -import com.zmops.iot.web.product.dto.ProductEventRuleDto; import com.zmops.iot.web.task.dto.TaskDto; import com.zmops.iot.web.task.service.TaskService; import com.zmops.zeus.driver.service.ZbxTrigger; @@ -64,6 +60,8 @@ public class MultipleDeviceEventRuleService { public static final int TRIGGER_TYPE_CONDITION = 0; + public static final String EXECUTE_TAG_NAME = "__scene__"; + @Autowired TaskService taskService; @@ -241,9 +239,20 @@ public void createDeviceEventRule(MultipleDeviceEventRule eventRule) { productEventRelationList.add(productEventRelation); }); DB.saveAll(productEventRelationList); + + //step 4: 保存时间区间 + List timeExpList = new ArrayList<>(); + eventRule.getTimeIntervals().forEach(i -> { + ProductEventTimeInterval timeExp = new ProductEventTimeInterval(); + timeExp.setEventRuleId(eventRule.getEventRuleId()); + timeExp.setStartTime(i.getStartTime()); + timeExp.setEndTime(i.getEndTime()); + timeExpList.add(timeExp); + }); + DB.insertAll(timeExpList); } - //step 4: 保存触发器 调用 本产品方法 + //step 5: 保存触发器 调用 本产品方法 if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { eventRule.getDeviceServices().forEach(i -> { DB.sqlUpdate("insert into product_event_service(event_rule_id, execute_device_id, service_id) " + @@ -290,6 +299,11 @@ public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { .setParameter("eventRuleId", eventRule.getEventRuleId()) .execute(); + //step : 删除时间区间函数表达式 + DB.sqlUpdate("delete from product_event_time_interval where event_rule_id = :eventRuleId") + .setParameter("eventRuleId", eventRule.getEventRuleId()) + .execute(); + // 删除和所有设备的关联关系 new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); @@ -326,9 +340,20 @@ public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { productEventRelationList.add(productEventRelation); }); DB.saveAll(productEventRelationList); + + //step 7: 保存时间区间 + List timeExpList = new ArrayList<>(); + eventRule.getTimeIntervals().forEach(i -> { + ProductEventTimeInterval timeExp = new ProductEventTimeInterval(); + timeExp.setEventRuleId(eventRule.getEventRuleId()); + timeExp.setStartTime(i.getStartTime()); + timeExp.setEndTime(i.getEndTime()); + timeExpList.add(timeExp); + }); + DB.insertAll(timeExpList); } - //step 7: 保存触发器 调用 本产品方法 + //step 8: 保存触发器 调用 本产品方法 if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { eventRule.getDeviceServices().forEach(i -> { DB.sqlUpdate("insert into product_event_service(event_rule_id,execute_device_id, service_id) values (:eventRuleId, :executeDeviceId, :serviceId)") @@ -390,35 +415,40 @@ public void updateProductEventRuleZbxId(Long triggerId, String[] zbxId) { * @param eventRuleId * @return */ - public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId) { - ProductEventRuleDto productEventRuleDto = new ProductEventRuleDto(); - ToolUtil.copyProperties(productEvent, productEventRuleDto); + public MultipleDeviceEventDto detail(ProductEvent productEvent, long eventRuleId) { + MultipleDeviceEventDto multipleDeviceEventDto = new MultipleDeviceEventDto(); + ToolUtil.copyProperties(productEvent, multipleDeviceEventDto); - productEventRuleDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).findList()); + multipleDeviceEventDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).findList()); if (TRIGGER_TYPE_CONDITION == productEvent.getTriggerType()) { List expList = new QProductEventExpression().eventRuleId.eq(eventRuleId).findList(); - productEventRuleDto.setExpList(expList); + multipleDeviceEventDto.setExpList(expList); + + List timeExpList = new QProductEventTimeInterval().eventRuleId.eq(eventRuleId).findList(); + multipleDeviceEventDto.setTimeExpList(timeExpList); ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRuleId).setMaxRows(1).findOne(); - productEventRuleDto.setStatus(productEventRelation.getStatus()); - productEventRuleDto.setRemark(productEventRelation.getRemark()); - productEventRuleDto.setInherit(productEventRelation.getInherit()); + if (null == productEventRelation) { + return multipleDeviceEventDto; + } + multipleDeviceEventDto.setStatus(productEventRelation.getStatus()); + multipleDeviceEventDto.setRemark(productEventRelation.getRemark()); + multipleDeviceEventDto.setInherit(productEventRelation.getInherit()); JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); - List tagList = JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class); + List tagList = JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), MultipleDeviceEventRule.Tag.class); - productEventRuleDto.setZbxId(productEventRelation.getZbxId()); - productEventRuleDto.setTags(tagList.stream() - .filter(s -> !s.getTag().equals("__execute__") && !s.getTag().equals("__alarm__") && !s.getTag().equals("__event__")) + multipleDeviceEventDto.setTags(tagList.stream() + .filter(s -> !s.getTag().equals(EXECUTE_TAG_NAME)) .collect(Collectors.toList())); } else { Task task = new QTask().id.eq(productEvent.getTaskId()).findOne(); - productEventRuleDto.setScheduleConf(Optional.ofNullable(task).map(Task::getScheduleConf).orElse("")); - productEventRuleDto.setExpList(Collections.emptyList()); + multipleDeviceEventDto.setScheduleConf(Optional.ofNullable(task).map(Task::getScheduleConf).orElse("")); + multipleDeviceEventDto.setExpList(Collections.emptyList()); } - return productEventRuleDto; + return multipleDeviceEventDto; } /** @@ -447,16 +477,23 @@ public String[] updateZbxTrigger(String triggerId, String expression, Byte level } public void execute(Long eventRuleId, String type, Long userId) { + Map serviceLogInfo = new ConcurrentHashMap<>(3); + serviceLogInfo.put("eventRuleId", eventRuleId); + serviceLogInfo.put("triggerType", "自动".equals(type) ? "场景联动" : type); + if (null != userId) { + serviceLogInfo.put("triggerUser", userId); + } + + WorkerWrapper, Boolean> deviceServiceLogWork = new WorkerWrapper.Builder, Boolean>().id("deviceServiceLogWorker") + .worker(deviceServiceLogWorker).param(serviceLogInfo).callback(ICallback.PRINT_EXCEPTION_STACK_TRACE) + .build(); + Map alarmInfo = new ConcurrentHashMap<>(3); alarmInfo.put("eventRuleId", eventRuleId); alarmInfo.put("triggerType", type); if (null != userId) { alarmInfo.put("triggerUser", userId); } - - WorkerWrapper, Boolean> deviceServiceLogWork = new WorkerWrapper.Builder, Boolean>().id("deviceServiceLogWorker") - .worker(deviceServiceLogWorker).param(alarmInfo).callback(ICallback.PRINT_EXCEPTION_STACK_TRACE) - .build(); WorkerWrapper, Boolean> scenesLogWork = new WorkerWrapper.Builder, Boolean>().id("scenesLogWorker") .worker(scenesLogWorker).param(alarmInfo).callback(ICallback.PRINT_EXCEPTION_STACK_TRACE) .build(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java index 550f4186..b5eb9fef 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java @@ -39,15 +39,20 @@ public void subscribe(String event) { Map eventMap = JSONObject.parseObject(event,Map.class); Long eventRuleId = Long.parseLong(eventMap.get("eventRuleId").toString()); - Map alarmInfo = new ConcurrentHashMap<>(3); - alarmInfo.put("eventRuleId", eventRuleId); - alarmInfo.put("triggerType", "定时"); + Map serviceLogInfo = new ConcurrentHashMap<>(3); + serviceLogInfo.put("eventRuleId", eventRuleId); + serviceLogInfo.put("triggerType", "场景联动"); WorkerWrapper, Boolean> deviceServiceLogWork = new WorkerWrapper.Builder, Boolean>().id("deviceServiceLogWorker") - .worker(deviceServiceLogWorker).param(alarmInfo) + .worker(deviceServiceLogWorker).param(serviceLogInfo) .build(); + + Map sceneLogInfo = new ConcurrentHashMap<>(3); + sceneLogInfo.put("eventRuleId", eventRuleId); + sceneLogInfo.put("triggerType", "自动"); + WorkerWrapper, Boolean> scenesLogWork = new WorkerWrapper.Builder, Boolean>().id("scenesLogWorker") - .worker(scenesLogWorker).param(alarmInfo) + .worker(scenesLogWorker).param(sceneLogInfo) .build(); try { From 390a30822e70a851a2d1260a767ab82f7c08393d Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 17 Nov 2021 14:56:07 +0800 Subject: [PATCH 667/763] [fix]:fix init sql --- dist-material/bin/sql/zeus-iot.sql | 45 +++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/dist-material/bin/sql/zeus-iot.sql b/dist-material/bin/sql/zeus-iot.sql index 5f69e99b..b593eea3 100644 --- a/dist-material/bin/sql/zeus-iot.sql +++ b/dist-material/bin/sql/zeus-iot.sql @@ -12,7 +12,7 @@ Target Server Version : 130004 File Encoding : 65001 - Date: 15/11/2021 16:48:12 + Date: 17/11/2021 14:53:58 */ @@ -115,6 +115,17 @@ MAXVALUE 2147483647 START 1 CACHE 1; +-- ---------------------------- +-- Sequence structure for product_event_time_interval_event_time_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."product_event_time_interval_event_time_id_seq"; +CREATE SEQUENCE "public"."product_event_time_interval_event_time_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + -- ---------------------------- -- Sequence structure for product_service_relation_id_seq -- ---------------------------- @@ -779,6 +790,26 @@ COMMENT ON COLUMN "public"."product_event_tags"."tag_zbx_id" IS 'zabbix tag id'; -- Records of product_event_tags -- ---------------------------- +-- ---------------------------- +-- Table structure for product_event_time_interval +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_event_time_interval"; +CREATE TABLE "public"."product_event_time_interval" ( + "event_time_id" int4 NOT NULL DEFAULT nextval('product_event_time_interval_event_time_id_seq'::regclass), + "event_rule_id" int8 NOT NULL, + "start_time" int2, + "end_time" int2 +) +; +COMMENT ON COLUMN "public"."product_event_time_interval"."event_time_id" IS '告警函数ID'; +COMMENT ON COLUMN "public"."product_event_time_interval"."event_rule_id" IS '告警规则ID'; +COMMENT ON COLUMN "public"."product_event_time_interval"."start_time" IS '开始时间'; +COMMENT ON COLUMN "public"."product_event_time_interval"."end_time" IS '结束时间'; + +-- ---------------------------- +-- Records of product_event_time_interval +-- ---------------------------- + -- ---------------------------- -- Table structure for product_service -- ---------------------------- @@ -1732,6 +1763,13 @@ ALTER SEQUENCE "public"."product_event_tags_id_seq" OWNED BY "public"."product_event_tags"."id"; SELECT setval('"public"."product_event_tags_id_seq"', 3, true); +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."product_event_time_interval_event_time_id_seq" +OWNED BY "public"."product_event_time_interval"."event_time_id"; +SELECT setval('"public"."product_event_time_interval_event_time_id_seq"', 9, true); + -- ---------------------------- -- Alter sequences owned by -- ---------------------------- @@ -1904,6 +1942,11 @@ CREATE INDEX "serviceId" ON "public"."product_event_service" USING btree ( -- ---------------------------- ALTER TABLE "public"."product_event_tags" ADD CONSTRAINT "product_event_tags_pkey" PRIMARY KEY ("id"); +-- ---------------------------- +-- Primary Key structure for table product_event_time_interval +-- ---------------------------- +ALTER TABLE "public"."product_event_time_interval" ADD CONSTRAINT "product_event_time_interval_pkey" PRIMARY KEY ("event_time_id"); + -- ---------------------------- -- Primary Key structure for table product_service -- ---------------------------- From d34f134efedf0eff1f70a503d7190ea17b27f778 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 17 Nov 2021 15:29:04 +0800 Subject: [PATCH 668/763] [fix]:fix scene log list --- .../java/com/zmops/iot/web/device/service/DeviceLogService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java index 3d75c7aa..8fb16d1b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java @@ -269,7 +269,7 @@ private Pager getScenesLog(DeviceLogParam deviceLogParam) { } if (ToolUtil.isNotEmpty(deviceLogParam.getDeviceId())) { - List executeRuleIds = new QProductEventService().select(QProductEventService.alias().eventRuleId).executeDeviceId.eq(deviceLogParam.getTriggerDeviceId()).findSingleAttributeList(); + List executeRuleIds = new QProductEventService().select(QProductEventService.alias().eventRuleId).executeDeviceId.eq(deviceLogParam.getDeviceId()).findSingleAttributeList(); if (ToolUtil.isEmpty(executeRuleIds)) { return new Pager<>(Collections.emptyList(), 0); } From cd620446c539f8e1f53da06829d035e106bdb57c Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 17 Nov 2021 21:02:51 +0800 Subject: [PATCH 669/763] [fix]: code format --- .../iot/web/device/service/DeviceService.java | 27 +++++++++++++++++-- .../service/work/SaveAttributeWorker.java | 19 ++++++------- .../service/work/SaveDeviceGrpWorker.java | 3 +-- .../device/service/work/SaveOtherWorker.java | 15 +++-------- .../device/service/work/SaveTagWorker.java | 5 +--- .../service/work/UpdateAttrZbxIdWorker.java | 4 --- .../service/work/UpdateDeviceZbxIdWorker.java | 14 +++++----- 7 files changed, 49 insertions(+), 38 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index a3d92f66..8708ac41 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -126,12 +126,16 @@ public List getDeviceIds() { * @return */ public Pager devicePageList(DeviceParam deviceParam) { + //根据当前用户所属用户组 取出绑定的主机组 List devGroupIds = deviceGroupService.getDevGroupIds(); if (ToolUtil.isEmpty(devGroupIds)) { return new Pager<>(); } + //组装查询SQL StringBuilder sql = generateBaseSql(); sql.append(" where 1=1"); + + //根据标签过滤 List sids = new ArrayList<>(); if (ToolUtil.isNotEmpty(deviceParam.getTag())) { QTag qTag = new QTag().select(QTag.Alias.sid).templateId.isNull(); @@ -144,6 +148,7 @@ public Pager devicePageList(DeviceParam deviceParam) { sql.append(" and d.device_id in ( :deviceIds )"); } } + if (ToolUtil.isNotEmpty(deviceParam.getProdType())) { sql.append(" and d.type = :prodType "); } @@ -153,6 +158,7 @@ public Pager devicePageList(DeviceParam deviceParam) { if (ToolUtil.isNotEmpty(deviceParam.getName())) { sql.append(" and d.name like :name "); } + //用于查询总记录数 Query count = DB.findNative(Device.class, sql.toString()); sql.append(" order by d.create_time desc "); @@ -258,7 +264,7 @@ public String create(DeviceDto deviceDto) { .build(); WorkerWrapper updateDeviceZbxIdWork = new WorkerWrapper.Builder().id("updateDeviceZbxIdWork") - .worker(updateDeviceZbxIdWorker) + .worker(updateDeviceZbxIdWorker).param(deviceDto.getDeviceId()) .build(); WorkerWrapper saveOtherWork = new WorkerWrapper.Builder().id("saveOtherWork") @@ -282,6 +288,7 @@ public String create(DeviceDto deviceDto) { } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } + updateDeviceNameCache(deviceDto.getDeviceId(), deviceDto.getName()); return deviceDto.getDeviceId(); } @@ -357,24 +364,28 @@ public String delete(DeviceDto deviceDto) { return deviceDto.getDeviceId(); } String zbxId = device.getZbxId(); + //删除标签 WorkerWrapper delTagWork = new WorkerWrapper.Builder().id("delTagWork") .worker((deviceId, allWrappers) -> { new QTag().sid.eq(deviceId).delete(); return true; }).param(deviceDto.getDeviceId()).build(); + //删除属性 WorkerWrapper delAttrWork = new WorkerWrapper.Builder().id("delAttrWork") .worker((deviceId, allWrappers) -> { new QProductAttribute().productId.eq(deviceId).delete(); return true; }).param(deviceDto.getDeviceId()).build(); + //删除设备组关联关系 WorkerWrapper delGropusWork = new WorkerWrapper.Builder().id("delGropusWork") .worker((deviceId, allWrappers) -> { new QDevicesGroups().deviceId.eq(deviceId).delete(); return true; }).param(deviceDto.getDeviceId()).build(); + //删除Zbx主机 WorkerWrapper delZbxWork = new WorkerWrapper.Builder().id("delZbxWork") .worker((zbxid, allWrappers) -> { if (ToolUtil.isNotEmpty(zbxid)) { @@ -386,6 +397,7 @@ public String delete(DeviceDto deviceDto) { return true; }).param(zbxId).build(); + //删除其它关联信息 WorkerWrapper delOtherWork = new WorkerWrapper.Builder().id("delOtherWork") .worker((deviceId, allWrappers) -> { new QProductStatusFunctionRelation().relationId.eq(deviceId).delete(); @@ -396,6 +408,7 @@ public String delete(DeviceDto deviceDto) { return true; }).param(deviceDto.getDeviceId()).build(); + //删除设备 WorkerWrapper delDeviceWork = new WorkerWrapper.Builder() .id("delDeviceWork") .worker((deviceId, allWrappers) -> { @@ -412,6 +425,7 @@ public String delete(DeviceDto deviceDto) { e.printStackTrace(); } + //更新设备名称缓存 removeDeviceNameCache(deviceDto.getDeviceId()); return deviceDto.getDeviceId(); @@ -428,7 +442,9 @@ public void deviceTagCreate(ProductTag productTag, String zbxId) { return; } + //先删除 之前的标签 new QTag().sid.eq(productTag.getProductId()).delete(); + List tags = new ArrayList<>(); for (ProductTag.Tag tag : productTag.getProductTag()) { @@ -440,7 +456,8 @@ public void deviceTagCreate(ProductTag productTag, String zbxId) { if (ToolUtil.isEmpty(zbxId)) { return; } - + + //同步到Zbx List list = new QTag().sid.eq(productTag.getProductId()).findList(); Map tagMap = new HashMap<>(list.size()); @@ -562,12 +579,18 @@ private void updateDeviceCache() { DefinitionsUtil.updateDeviceCache(map); } + /** + * 更新设备名称缓存 + */ private void updateDeviceNameCache(String deviceId, String name) { Map all = DefinitionsUtil.getDeviceCache().getAll(); all.put(deviceId, name); DefinitionsUtil.updateDeviceCache(all); } + /** + * 更新设备名称缓存 + */ private void removeDeviceNameCache(String deviceId) { Map all = DefinitionsUtil.getDeviceCache().getAll(); all.remove(deviceId); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java index 5f50ea17..597aa6b2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java @@ -33,7 +33,7 @@ public class SaveAttributeWorker implements IWorker { @Override public Boolean action(DeviceDto deviceDto, Map map) { - log.debug("step 3:saveAttributeWorker----DEVICEID:{}…………",deviceDto.getDeviceId()); + log.debug("step 3:saveAttributeWorker----DEVICEID:{}…………", deviceDto.getDeviceId()); String deviceId = deviceDto.getDeviceId(); @@ -45,10 +45,6 @@ public Boolean action(DeviceDto deviceDto, Map map) { } new QProductAttribute().productId.eq(deviceId).templateId.isNotNull().delete(); new QProductAttributeEvent().productId.eq(deviceId).templateId.isNotNull().delete(); - } else { - //创建 - Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); - deviceId = device.getDeviceId(); } //属性 @@ -56,6 +52,11 @@ public Boolean action(DeviceDto deviceDto, Map map) { List newProductAttributeList = new ArrayList<>(); + /** + * 处理依赖属性用 + * 遍历属性时 attrKeyMap保存 继承的属性ID 对应的 key + * attrIdMap 保存 key 对应的 新的属性ID + */ Map attrKeyMap = new ConcurrentHashMap<>(productAttributeList.size()); Map attrIdMap = new ConcurrentHashMap<>(productAttributeList.size()); @@ -68,13 +69,13 @@ public Boolean action(DeviceDto deviceDto, Map map) { newProductAttrbute.setAttrId(attrId); newProductAttrbute.setProductId(deviceId); //处理依赖属性 - if(ATTR_TYPE_RELY.equals(productAttribute.getSource())){ + if (ATTR_TYPE_RELY.equals(productAttribute.getSource())) { String key = attrKeyMap.get(productAttribute.getDepAttrId()); - if(ToolUtil.isNotEmpty(key)) { + if (ToolUtil.isNotEmpty(key)) { Long deptAttrId = attrIdMap.get(key); newProductAttrbute.setDepAttrId(deptAttrId); } - }else { + } else { attrKeyMap.put(productAttribute.getAttrId(), productAttribute.getKey()); attrIdMap.put(productAttribute.getKey(), attrId); } @@ -97,7 +98,7 @@ public Boolean action(DeviceDto deviceDto, Map map) { } DB.saveAll(newProductAttributeEventList); - log.debug("step 3:saveAttributeWorker----DEVICEID:{}…………",deviceDto.getDeviceId()); + log.debug("step 3:saveAttributeWorker----DEVICEID:{}…………", deviceDto.getDeviceId()); return true; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java index e008993b..bb272df3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java @@ -35,10 +35,9 @@ public Boolean action(DeviceDto deviceDto, Map map) { } //保存设备与设备组关系 - Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); List devicesGroupsList = new ArrayList<>(); for (Long deviceGroupId : deviceDto.getDeviceGroupIds()) { - devicesGroupsList.add(DevicesGroups.builder().deviceId(device.getDeviceId()).deviceGroupId(deviceGroupId).build()); + devicesGroupsList.add(DevicesGroups.builder().deviceId(deviceDto.getDeviceId()).deviceGroupId(deviceGroupId).build()); } DB.saveAll(devicesGroupsList); log.debug("step 4:SaveDeviceGrpWorker----DEVICEID:{}…………",deviceDto.getDeviceId()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java index 6b600cf3..68602dc6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java @@ -7,10 +7,7 @@ import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.product.ProductEventRelation; import com.zmops.iot.domain.product.ProductStatusFunctionRelation; -import com.zmops.iot.domain.product.query.QProductEventRelation; -import com.zmops.iot.domain.product.query.QProductEventService; -import com.zmops.iot.domain.product.query.QProductServiceRelation; -import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; +import com.zmops.iot.domain.product.query.*; import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; @@ -31,7 +28,7 @@ /** * @author yefei *

- * 设备标签处理步骤 + * 其它处理步骤 */ @Slf4j @Component @@ -55,17 +52,14 @@ public Boolean action(DeviceDto deviceDto, Map allWrapper } //删除服务关联 new QProductServiceRelation().relationId.eq(deviceId).delete(); + //删除服务参数 + new QProductServiceParam().deviceId.eq(deviceId).delete(); //删除 上下线规则关联 new QProductStatusFunctionRelation().relationId.eq(deviceId).delete(); //删除 告警规则关联 new QProductEventRelation().relationId.eq(deviceId).delete(); //删除 告警执行动作关联 new QProductEventService().deviceId.eq(deviceId).delete(); - - } else { - //创建 - Device device = (Device) allWrappers.get("saveDvice").getWorkResult().getResult(); - deviceId = device.getDeviceId(); } //服务关联 @@ -115,7 +109,6 @@ public Boolean action(DeviceDto deviceDto, Map allWrapper } DB.saveAll(newRelationList); - DB.saveAll(productEventRelationList); //告警执行动作关联 DB.sqlUpdate("insert into product_event_service (service_id,device_id,execute_device_id,event_rule_id,inherit) SELECT service_id,:deviceId,:executeDeviceId,event_rule_id,1 from product_event_service where relation_id=:relationId") .setParameter("deviceId", deviceId).setParameter("executeDeviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "").execute(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java index d6ec5d51..35d76dc2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java @@ -36,12 +36,9 @@ public Boolean action(DeviceDto deviceDto, Map allWrapper return true; } new QTag().sid.eq(deviceId).delete(); - } else { - //创建 - Device device = (Device) allWrappers.get("saveDvice").getWorkResult().getResult(); - deviceId = device.getDeviceId(); } + //继承产品中的标签 DB.sqlUpdate("insert into tag (sid,tag,value,template_id) SELECT :deviceId,tag,value,id template_id from tag where sid=:sid") .setParameter("deviceId", deviceId).setParameter("sid", deviceDto.getProductId() + "").execute(); log.debug("step 2:SaveTagWorker----DEVICEID:{} complete",deviceDto.getDeviceId()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java index 7dfbf73e..647f1dae 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java @@ -47,10 +47,6 @@ public Boolean action(DeviceDto deviceDto, Map map) { if (deviceDto.getProductId().equals(deviceDto.getOldProductId())) { return true; } - } else { - //创建 - Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); - deviceId = device.getDeviceId(); } //取出 ZBX hostid diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java index 265d1124..ca4f8d34 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java @@ -23,15 +23,17 @@ public class UpdateDeviceZbxIdWorker implements IWorker { @Override - public Boolean action(String deviceDto, Map map) { + public Boolean action(String deviceId, Map map) { Object result = map.get("saveZbxHostWork").getWorkResult().getResult(); + JSONArray hostid = JSONObject.parseObject(result.toString()).getJSONArray("hostids"); - Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); - log.debug("step 7:resolve zbxID async----DEVICEID:{}, HOSTID:{}…………",device.getDeviceId(),hostid.get(0).toString()); - device.setZbxId(hostid.get(0).toString()); - DB.update(device); - log.debug("step 7:resolve zbxID async----DEVICEID:{}, HOSTID:{} 完成",device.getDeviceId(),hostid.get(0).toString()); + + log.debug("step 7:resolve zbxID async----DEVICEID:{}, HOSTID:{}…………",deviceId,hostid.get(0).toString()); + + DB.update(Device.class).where().eq("deviceId",deviceId).asUpdate().set("zbxId",hostid.get(0).toString()).update(); + + log.debug("step 7:resolve zbxID async----DEVICEID:{}, HOSTID:{} 完成",deviceId,hostid.get(0).toString()); return true; } From f28a28f6be4dec5217b7aae80a47268759aee3b0 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 17 Nov 2021 21:49:04 +0800 Subject: [PATCH 670/763] [fix]: code format --- .../web/device/controller/DeviceEventTriggerController.java | 6 +++--- .../iot/web/device/controller/DeviceModelController.java | 2 +- .../iot/web/device/service/DeviceEventRuleService.java | 3 +-- .../java/com/zmops/iot/web/task/service/TaskService.java | 1 + 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index 01e0acc5..830c89c7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -186,9 +186,9 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn if (!tags.containsKey(ALARM_TAG_NAME)) { tags.put(ALARM_TAG_NAME, "{HOST.HOST}"); } -// if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { -// tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); -// } + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { + tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); + } // Optional any = eventRule.getExpList().parallelStream().filter(o -> EVENT_TYPE_NAME.equals(o.getProductAttrType())).findAny(); // if (any.isPresent()) { // tags.put(EVENT_TAG_NAME, eventRule.getEventRuleId() + ""); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java index 3e92bba1..1350f03b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java @@ -24,7 +24,7 @@ /** * @author yefei *

- * 设备物模型 + * 设备属性 */ @RestController diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 000f79bf..23b0d9e4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -63,10 +63,9 @@ public void createDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { exp.setEventRuleId(eventRuleId); expList.add(exp); }); - DB.saveAll(expList); - //step 3: 保存触发器 调用 本产品方法 + //step 3: 保存触发器 调用 动作服务 if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { List deviceIds = eventRule.getExpList().parallelStream().map(DeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); deviceIds.forEach(deviceId -> { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/task/service/TaskService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/task/service/TaskService.java index 01fe4147..2a3066b3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/task/service/TaskService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/task/service/TaskService.java @@ -43,6 +43,7 @@ public TaskDto updateTask(TaskDto taskDto) { } else { task.setExecutorParam(taskDto.getExecutorParam()); task.setScheduleConf(taskDto.getScheduleConf()); + task.setTriggerNextTime(0L); task.setRemark(taskDto.getRemark()); DB.update(task); } From 7cbfb9d1ca4ed26b2273b2172ec3cdd86379a8b3 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 18 Nov 2021 14:10:02 +0800 Subject: [PATCH 671/763] [fix]: fix scene time interval --- .../MultipleDeviceEventRuleService.java | 41 +++++++++++-------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index 310c84d7..30c7cb65 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -241,15 +241,17 @@ public void createDeviceEventRule(MultipleDeviceEventRule eventRule) { DB.saveAll(productEventRelationList); //step 4: 保存时间区间 - List timeExpList = new ArrayList<>(); - eventRule.getTimeIntervals().forEach(i -> { - ProductEventTimeInterval timeExp = new ProductEventTimeInterval(); - timeExp.setEventRuleId(eventRule.getEventRuleId()); - timeExp.setStartTime(i.getStartTime()); - timeExp.setEndTime(i.getEndTime()); - timeExpList.add(timeExp); - }); - DB.insertAll(timeExpList); + if(ToolUtil.isNotEmpty(eventRule.getTimeIntervals())) { + List timeExpList = new ArrayList<>(); + eventRule.getTimeIntervals().forEach(i -> { + ProductEventTimeInterval timeExp = new ProductEventTimeInterval(); + timeExp.setEventRuleId(eventRule.getEventRuleId()); + timeExp.setStartTime(i.getStartTime()); + timeExp.setEndTime(i.getEndTime()); + timeExpList.add(timeExp); + }); + DB.insertAll(timeExpList); + } } //step 5: 保存触发器 调用 本产品方法 @@ -342,15 +344,17 @@ public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { DB.saveAll(productEventRelationList); //step 7: 保存时间区间 - List timeExpList = new ArrayList<>(); - eventRule.getTimeIntervals().forEach(i -> { - ProductEventTimeInterval timeExp = new ProductEventTimeInterval(); - timeExp.setEventRuleId(eventRule.getEventRuleId()); - timeExp.setStartTime(i.getStartTime()); - timeExp.setEndTime(i.getEndTime()); - timeExpList.add(timeExp); - }); - DB.insertAll(timeExpList); + if(ToolUtil.isNotEmpty(eventRule.getTimeIntervals())) { + List timeExpList = new ArrayList<>(); + eventRule.getTimeIntervals().forEach(i -> { + ProductEventTimeInterval timeExp = new ProductEventTimeInterval(); + timeExp.setEventRuleId(eventRule.getEventRuleId()); + timeExp.setStartTime(i.getStartTime()); + timeExp.setEndTime(i.getEndTime()); + timeExpList.add(timeExp); + }); + DB.insertAll(timeExpList); + } } //step 8: 保存触发器 调用 本产品方法 @@ -446,6 +450,7 @@ public MultipleDeviceEventDto detail(ProductEvent productEvent, long eventRuleId Task task = new QTask().id.eq(productEvent.getTaskId()).findOne(); multipleDeviceEventDto.setScheduleConf(Optional.ofNullable(task).map(Task::getScheduleConf).orElse("")); multipleDeviceEventDto.setExpList(Collections.emptyList()); + multipleDeviceEventDto.setTimeExpList(Collections.emptyList()); } return multipleDeviceEventDto; From 761eaff44802e9c67b1f5fff91b9338d81979eab Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 18 Nov 2021 15:21:47 +0800 Subject: [PATCH 672/763] [fix]: code format --- .../web/device/service/DeviceLogService.java | 45 ++++++++++++ .../web/device/service/DeviceSvrService.java | 24 ++++-- .../MultipleDeviceEventRuleService.java | 73 +++++++------------ .../service/SceneScheduleProcessor.java | 42 ++--------- .../service/work/DeviceServiceLogWorker.java | 2 +- .../device/service/work/ScenesLogWorker.java | 2 +- .../event/service/IncidentEventProcess.java | 3 + .../event/service/OfflineEventProcess.java | 4 +- .../web/event/service/OnlineEventProcess.java | 2 + .../web/event/service/SceneEventProcess.java | 2 + .../event/service/ServiceEventProcess.java | 5 ++ 11 files changed, 115 insertions(+), 89 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java index 8fb16d1b..ad972444 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java @@ -1,5 +1,8 @@ package com.zmops.iot.web.device.service; +import com.zmops.iot.async.callback.ICallback; +import com.zmops.iot.async.executor.Async; +import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.EventTriggerRecord; import com.zmops.iot.domain.device.ScenesTriggerRecord; import com.zmops.iot.domain.device.ServiceExecuteRecord; @@ -18,12 +21,16 @@ import com.zmops.iot.web.device.dto.DeviceLogDto; import com.zmops.iot.web.device.dto.DeviceRelationDto; import com.zmops.iot.web.device.dto.param.DeviceLogParam; +import com.zmops.iot.web.device.service.work.DeviceServiceLogWorker; +import com.zmops.iot.web.device.service.work.ScenesLogWorker; import io.ebean.DB; import io.ebean.PagedList; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; /** @@ -40,6 +47,12 @@ public class DeviceLogService { @Autowired AlarmService alarmService; + @Autowired + DeviceServiceLogWorker deviceServiceLogWorker; + + @Autowired + ScenesLogWorker scenesLogWorker; + public List list(String deviceId, String logType, Long timeFrom, Long timeTill) { List deviceLogDtoList = new ArrayList<>(); if (ToolUtil.isEmpty(logType) || (ToolUtil.isNotEmpty(logType) && LOG_TYPE_ALARM.equals(logType))) { @@ -306,4 +319,36 @@ private Pager getScenesLog(DeviceLogParam deviceLogParam) { }); return new Pager<>(deviceLogDtoList, pagedList.getTotalCount()); } + + /** + * 记录场景日志 + */ + public void recordSceneLog(Long eventRuleId, String type, Long userId) { + Map serviceLogInfo = new ConcurrentHashMap<>(3); + serviceLogInfo.put("eventRuleId", eventRuleId); + serviceLogInfo.put("triggerType", "自动".equals(type) ? "场景联动" : type); + if (null != userId) { + serviceLogInfo.put("triggerUser", userId); + } + + WorkerWrapper, Boolean> deviceServiceLogWork = new WorkerWrapper.Builder, Boolean>().id("deviceServiceLogWorker") + .worker(deviceServiceLogWorker).param(serviceLogInfo).callback(ICallback.PRINT_EXCEPTION_STACK_TRACE) + .build(); + + Map scenesLogInfo = new ConcurrentHashMap<>(3); + scenesLogInfo.put("eventRuleId", eventRuleId); + scenesLogInfo.put("triggerType", type); + if (null != userId) { + scenesLogInfo.put("triggerUser", userId); + } + WorkerWrapper, Boolean> scenesLogWork = new WorkerWrapper.Builder, Boolean>().id("scenesLogWorker") + .worker(scenesLogWorker).param(scenesLogInfo).callback(ICallback.PRINT_EXCEPTION_STACK_TRACE) + .build(); + + try { + Async.beginWork(1000, deviceServiceLogWork, scenesLogWork); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java index 44baee2d..be19936f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java @@ -4,17 +4,15 @@ import com.alibaba.fastjson.JSONObject; import com.dtflys.forest.Forest; import com.zmops.iot.core.auth.context.LoginContextHolder; -import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.ServiceExecuteRecord; -import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductService; import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.product.query.QProductService; -import com.zmops.iot.domain.product.query.QProductServiceParam; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import io.ebean.DB; import org.springframework.stereotype.Service; import java.time.LocalDateTime; @@ -26,13 +24,22 @@ /** * @author yefei + *

+ * 设备服务 **/ @Service public class DeviceSvrService { + /** + * 执行指定设备的某个服务 + * + * @param deviceId 设备ID + * @param serviceId 服务ID + */ public void execute(String deviceId, Long serviceId) { - List> list = new ArrayList<>(); + //封装执行参数 + List> body = new ArrayList<>(); Map map = new ConcurrentHashMap<>(2); @@ -53,19 +60,22 @@ public void execute(String deviceId, Long serviceId) { serviceList.add(serviceMap); map.put("service", serviceList); - list.add(map); + body.add(map); - Forest.post("/device/action/exec").host("127.0.0.1").port(12800).contentTypeJson().addBody(JSON.toJSON(list)).execute(); + //下发命令 执行 + Forest.post("/device/action/exec").host("127.0.0.1").port(12800).contentTypeJson().addBody(JSON.toJSON(body)).execute(); + //记录服务日志 ServiceExecuteRecord serviceExecuteRecord = new ServiceExecuteRecord(); serviceExecuteRecord.setDeviceId(deviceId); if (ToolUtil.isNotEmpty(paramList)) { serviceExecuteRecord.setParam(JSONObject.toJSONString(paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue)))); } serviceExecuteRecord.setServiceName(DefinitionsUtil.getServiceName(serviceId)); - serviceExecuteRecord.setCreateTime(LocalDateTime.now()); serviceExecuteRecord.setExecuteType("手动"); serviceExecuteRecord.setExecuteUser(LoginContextHolder.getContext().getUserId()); + + DB.insert(serviceExecuteRecord); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index 30c7cb65..439ea788 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -4,9 +4,6 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.dtflys.forest.Forest; -import com.zmops.iot.async.callback.ICallback; -import com.zmops.iot.async.executor.Async; -import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.*; import com.zmops.iot.domain.product.query.*; import com.zmops.iot.domain.schedule.Task; @@ -22,8 +19,6 @@ import com.zmops.iot.web.device.dto.MultipleDeviceEventRule; import com.zmops.iot.web.device.dto.MultipleDeviceServiceDto; import com.zmops.iot.web.device.dto.param.MultipleDeviceEventParm; -import com.zmops.iot.web.device.service.work.DeviceServiceLogWorker; -import com.zmops.iot.web.device.service.work.ScenesLogWorker; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.task.dto.TaskDto; import com.zmops.iot.web.task.service.TaskService; @@ -36,7 +31,6 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; /** @@ -48,12 +42,6 @@ public class MultipleDeviceEventRuleService { @Autowired private ZbxTrigger zbxTrigger; - @Autowired - DeviceServiceLogWorker deviceServiceLogWorker; - - @Autowired - ScenesLogWorker scenesLogWorker; - private static final String EVENT_CLASSIFY = "1"; public static final int TRIGGER_TYPE_SCHEDULE = 1; @@ -65,6 +53,9 @@ public class MultipleDeviceEventRuleService { @Autowired TaskService taskService; + @Autowired + DeviceLogService deviceLogService; + /** * 场景列表 * @@ -241,7 +232,7 @@ public void createDeviceEventRule(MultipleDeviceEventRule eventRule) { DB.saveAll(productEventRelationList); //step 4: 保存时间区间 - if(ToolUtil.isNotEmpty(eventRule.getTimeIntervals())) { + if (ToolUtil.isNotEmpty(eventRule.getTimeIntervals())) { List timeExpList = new ArrayList<>(); eventRule.getTimeIntervals().forEach(i -> { ProductEventTimeInterval timeExp = new ProductEventTimeInterval(); @@ -344,7 +335,7 @@ public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { DB.saveAll(productEventRelationList); //step 7: 保存时间区间 - if(ToolUtil.isNotEmpty(eventRule.getTimeIntervals())) { + if (ToolUtil.isNotEmpty(eventRule.getTimeIntervals())) { List timeExpList = new ArrayList<>(); eventRule.getTimeIntervals().forEach(i -> { ProductEventTimeInterval timeExp = new ProductEventTimeInterval(); @@ -481,40 +472,27 @@ public String[] updateZbxTrigger(String triggerId, String expression, Byte level return JSON.parseObject(res, TriggerIds.class).getTriggerids(); } + /** + * 执行动作服务 + * + * @param eventRuleId 场景ID + * @param type 执行方式 + * @param userId 执行人 + */ public void execute(Long eventRuleId, String type, Long userId) { - Map serviceLogInfo = new ConcurrentHashMap<>(3); - serviceLogInfo.put("eventRuleId", eventRuleId); - serviceLogInfo.put("triggerType", "自动".equals(type) ? "场景联动" : type); - if (null != userId) { - serviceLogInfo.put("triggerUser", userId); - } - WorkerWrapper, Boolean> deviceServiceLogWork = new WorkerWrapper.Builder, Boolean>().id("deviceServiceLogWorker") - .worker(deviceServiceLogWorker).param(serviceLogInfo).callback(ICallback.PRINT_EXCEPTION_STACK_TRACE) - .build(); - - Map alarmInfo = new ConcurrentHashMap<>(3); - alarmInfo.put("eventRuleId", eventRuleId); - alarmInfo.put("triggerType", type); - if (null != userId) { - alarmInfo.put("triggerUser", userId); - } - WorkerWrapper, Boolean> scenesLogWork = new WorkerWrapper.Builder, Boolean>().id("scenesLogWorker") - .worker(scenesLogWorker).param(alarmInfo).callback(ICallback.PRINT_EXCEPTION_STACK_TRACE) - .build(); - - try { - Async.beginWork(1000, deviceServiceLogWork, scenesLogWork); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } + //先异步 执行记录日志 + deviceLogService.recordSceneLog(eventRuleId, type, userId); + //根据场景ID 找出需要执行的服务 List productEventServiceList = new QProductEventService().eventRuleId.eq(eventRuleId) .deviceId.isNull().findList(); - List> list = new ArrayList<>(); - Map> collect = productEventServiceList.parallelStream().collect(Collectors.groupingBy(ProductEventService::getExecuteDeviceId)); - collect.forEach((key, value) -> { + Map> deviceServiceMap = productEventServiceList.parallelStream().collect(Collectors.groupingBy(ProductEventService::getExecuteDeviceId)); + + //封装执行的参数 + List> body = new ArrayList<>(); + deviceServiceMap.forEach((key, value) -> { Map map = new ConcurrentHashMap<>(); map.put("device", key); @@ -530,13 +508,18 @@ public void execute(Long eventRuleId, String type, Long userId) { serviceList.add(serviceMap); }); map.put("service", serviceList); - list.add(map); + body.add(map); }); - Forest.post("/device/action/exec").host("127.0.0.1").port(12800).contentTypeJson().addBody(JSON.toJSON(list)).execute(); + //提交IOT SERVER执行命令下发 + Forest.post("/device/action/exec").host("127.0.0.1").port(12800).contentTypeJson().addBody(JSON.toJSON(body)).execute(); } - + /** + * 场景 参数 检查 + * + * @param eventRule + */ public void checkParam(MultipleDeviceEventRule eventRule) { if (eventRule.getTriggerType() == 0) { if (ToolUtil.isEmpty(eventRule.getExpList())) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java index b5eb9fef..945dbd79 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java @@ -4,63 +4,37 @@ import com.alibaba.fastjson.JSONObject; import com.dtflys.forest.Forest; import com.google.common.eventbus.Subscribe; -import com.zmops.iot.async.executor.Async; -import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.device.service.work.DeviceServiceLogWorker; -import com.zmops.iot.web.device.service.work.ScenesLogWorker; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutionException; /** * @author yefei + *

+ * 定时 触发场景 处理 **/ @Slf4j @Service public class SceneScheduleProcessor { @Autowired - DeviceServiceLogWorker deviceServiceLogWorker; - - @Autowired - ScenesLogWorker scenesLogWorker; + DeviceLogService deviceLogService; @Subscribe public void subscribe(String event) { log.info("子线程接收异步事件 - {},String类型", event); - if(ToolUtil.isEmpty(event)){ + if (ToolUtil.isEmpty(event)) { return; } - Map eventMap = JSONObject.parseObject(event,Map.class); + Map eventMap = JSONObject.parseObject(event, Map.class); Long eventRuleId = Long.parseLong(eventMap.get("eventRuleId").toString()); + //记录日志 + deviceLogService.recordSceneLog(eventRuleId, "自动", null); - Map serviceLogInfo = new ConcurrentHashMap<>(3); - serviceLogInfo.put("eventRuleId", eventRuleId); - serviceLogInfo.put("triggerType", "场景联动"); - - WorkerWrapper, Boolean> deviceServiceLogWork = new WorkerWrapper.Builder, Boolean>().id("deviceServiceLogWorker") - .worker(deviceServiceLogWorker).param(serviceLogInfo) - .build(); - - Map sceneLogInfo = new ConcurrentHashMap<>(3); - sceneLogInfo.put("eventRuleId", eventRuleId); - sceneLogInfo.put("triggerType", "自动"); - - WorkerWrapper, Boolean> scenesLogWork = new WorkerWrapper.Builder, Boolean>().id("scenesLogWorker") - .worker(scenesLogWorker).param(sceneLogInfo) - .build(); - - try { - Async.beginWork(1000, deviceServiceLogWork, scenesLogWork); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - + //提交IOT SERVER 下发命令 Forest.post("/device/action/exec").host("127.0.0.1").port(12800).contentTypeJson().addBody(JSON.toJSON(eventMap.get("executeParam"))).execute(); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java index a014a70d..de6e9337 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java @@ -26,7 +26,7 @@ /** * @author yefei *

- * 更新设备 在线状态 + * 记录服务执行日志 */ @Slf4j @Component diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java index 738268cf..3b17c776 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java @@ -17,7 +17,7 @@ /** * @author yefei *

- * 场景 日志 + * 记录 场景 日志 */ @Slf4j @Component diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java index 794c503c..0e7a1470 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java @@ -20,6 +20,8 @@ /** * @author yefei + * + * 事件处理 **/ @Slf4j @Component @@ -45,6 +47,7 @@ public void process(EventDataDto eventData) { Device device = new QDevice().deviceId.eq(deviceId).findOne(); ProductAttributeEvent productAttributeEvent = new QProductAttributeEvent().productId.eq(deviceId).key.eq(key).findOne(); + //取事件属性最新值 List latestDtos = latestService.queryEventLatest(device.getZbxId(), Collections.singletonList(productAttributeEvent.getZbxId()), Integer.parseInt(productAttributeEvent.getValueType())); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java index b95fb37b..c9bed02a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java @@ -15,10 +15,12 @@ /** * @author yefei + *

+ * 设备离线处理 **/ @Slf4j @Component -public class OfflineEventProcess implements EventProcess{ +public class OfflineEventProcess implements EventProcess { @Override public void process(EventDataDto eventData) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OnlineEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OnlineEventProcess.java index 19e9a253..96cbad01 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OnlineEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OnlineEventProcess.java @@ -15,6 +15,8 @@ /** * @author yefei + *

+ * 设备上线处理 **/ @Slf4j @Component diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java index d6ca6681..88998bed 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java @@ -10,6 +10,8 @@ /** * @author yefei + * + * 场景触发 **/ @Slf4j @Component diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java index 2d8d8e7c..facbf1a1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java @@ -27,6 +27,8 @@ /** * @author yefei + * + * 告警执行服务 **/ @Slf4j @Component @@ -40,6 +42,7 @@ public void process(EventDataDto eventData) { log.debug("--------service event----------{}", eventData.getObjectid()); Map alarmInfo = new ConcurrentHashMap<>(3); + //查询 告警规则 List productEventRelationList = new QProductEventRelation().zbxId.eq(eventData.getObjectid()).findList(); if (ToolUtil.isEmpty(productEventRelationList)) { return; @@ -49,6 +52,7 @@ public void process(EventDataDto eventData) { alarmInfo.put("relationId", productEventRelationList.get(0).getRelationId()); alarmInfo.put("triggerType", "自动"); + //记录服务日志 WorkerWrapper, Boolean> deviceServiceLogWork = new WorkerWrapper.Builder, Boolean>() .id("deviceServiceLogWorker") .worker(deviceServiceLogWorker) @@ -61,6 +65,7 @@ public void process(EventDataDto eventData) { e.printStackTrace(); } + //查询 告警规则 关联的 服务 List productEventServiceList = new QProductEventService() .eventRuleId.eq(productEventRelationList.get(0).getEventRuleId()) .or() From b3e5f054fed0c3471a87d0af5ad738a269bb2c2a Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 18 Nov 2021 20:10:34 +0800 Subject: [PATCH 673/763] [fix]: code format --- .../ProductStatusTriggerController.java | 2 +- .../product/service/ProductSvcService.java | 42 ++++++++++++------- .../service/ProductTriggerService.java | 34 +++++++++------ .../service/work/SaveProdSvcWorker.java | 6 +++ .../service/work/UpdateProdSvcWorker.java | 5 +++ 5 files changed, 62 insertions(+), 27 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java index 81ae77a1..8a965eef 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java @@ -82,7 +82,7 @@ public ResponseData updateDeviceStatusTrigger(@RequestBody @Validated(BaseEntity ProductAttribute prodAttrSecond = new QProductAttribute().attrId.eq(rule.getAttrIdRecovery()).findOne(); if (null == prodAttr || null == prodAttrSecond) { - throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_NOT_EXISTS); } // 数据库查询 triggerId 并且赋值 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index de20ad5d..32ca0146 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -132,6 +132,7 @@ public List list(ProductSvcParam productSvcParam) { */ @Transactional(rollbackFor = Exception.class) public ProductServiceDto create(ProductServiceDto productServiceDto) { + //查询 是否已存在同名服务 List serviceIds = getServiceIdList(productServiceDto.getRelationId()); if (ToolUtil.isNotEmpty(serviceIds)) { int count = new QProductService().name.eq(productServiceDto.getName()).id.in(serviceIds).findCount(); @@ -139,17 +140,20 @@ public ProductServiceDto create(ProductServiceDto productServiceDto) { throw new ServiceException(BizExceptionEnum.SERVICE_EXISTS); } } + //保存服务 ProductService productService = new ProductService(); ToolUtil.copyProperties(productServiceDto, productService); DB.save(productService); Long serviceId = productService.getId(); productServiceDto.setId(serviceId); + //保存服务与产品 关联关系 ProductServiceRelation productServiceRelation = new ProductServiceRelation(); productServiceRelation.setServiceId(productService.getId()); productServiceRelation.setRelationId(productServiceDto.getRelationId()); DB.save(productServiceRelation); + //保存服务参数 if (ToolUtil.isNotEmpty(productServiceDto.getProductServiceParamList())) { for (ProductServiceParam productServiceParam : productServiceDto.getProductServiceParamList()) { productServiceParam.setServiceId(null); @@ -160,13 +164,14 @@ public ProductServiceDto create(ProductServiceDto productServiceDto) { } //同步到设备 - WorkerWrapper saveProdAttrWork = - new WorkerWrapper.Builder().worker(saveProdSvcWorker).param(productServiceDto).build(); - - try { - Async.beginWork(100, saveProdAttrWork); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); + if (ToolUtil.isNum(productServiceDto.getRelationId())) { + WorkerWrapper saveProdAttrWork = + new WorkerWrapper.Builder().worker(saveProdSvcWorker).param(productServiceDto).build(); + try { + Async.beginWork(100, saveProdAttrWork); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } } updateService(); return productServiceDto; @@ -179,6 +184,7 @@ public ProductServiceDto create(ProductServiceDto productServiceDto) { * @return */ public ProductServiceDto update(ProductServiceDto productServiceDto) { + //查询 是否已存在同名服务 List serviceIds = getServiceIdList(productServiceDto.getRelationId()); if (ToolUtil.isNotEmpty(serviceIds)) { int count = new QProductService().name.eq(productServiceDto.getName()).id.in(serviceIds) @@ -187,10 +193,13 @@ public ProductServiceDto update(ProductServiceDto productServiceDto) { throw new ServiceException(BizExceptionEnum.SERVICE_EXISTS); } } + + //保存服务 ProductService productService = new ProductService(); ToolUtil.copyProperties(productServiceDto, productService); DB.update(productService); + //重新保存服务参数 new QProductServiceParam().serviceId.eq(productServiceDto.getId()).delete(); if (ToolUtil.isNotEmpty(productServiceDto.getProductServiceParamList())) { for (ProductServiceParam productServiceParam : productServiceDto.getProductServiceParamList()) { @@ -200,13 +209,14 @@ public ProductServiceDto update(ProductServiceDto productServiceDto) { } //同步到设备 - WorkerWrapper updateProdSvcWork = - new WorkerWrapper.Builder().worker(updateProdSvcWorker).param(productServiceDto).build(); - - try { - Async.beginWork(1000, updateProdSvcWork); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); + if (ToolUtil.isNum(productServiceDto.getRelationId())) { + WorkerWrapper updateProdSvcWork = + new WorkerWrapper.Builder().worker(updateProdSvcWorker).param(productServiceDto).build(); + try { + Async.beginWork(1000, updateProdSvcWork); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } } updateService(); return productServiceDto; @@ -243,6 +253,10 @@ public List paramList(long serviceId) { return new QProductServiceParam().serviceId.eq(serviceId).findList(); } + /** + * 更新服务名称 服务参数 缓存 + * + */ private void updateService() { List serviceList = new QProductService().findList(); Map map = serviceList.parallelStream().collect(Collectors.toMap(ProductService::getId, ProductService::getName)); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java index 61fc4b30..1f41a2a1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java @@ -7,8 +7,10 @@ import com.zmops.iot.domain.product.ProductStatusFunctionRelation; import com.zmops.iot.domain.product.query.QProductStatusFunction; import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; +import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductStatusFunctionDto; import com.zmops.iot.web.product.dto.ProductStatusJudgeRule; import com.zmops.iot.web.product.dto.ZbxTriggerInfo; @@ -70,7 +72,7 @@ public Long createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { long ruleId = IdUtil.getSnowflake().nextId(); judgeRule.setRuleId(ruleId); - //step 1:保存到zbx + //step 1:保存到zbx 建立上线及下线规则 String res = deviceStatusTrigger.createDeviceStatusTrigger(judgeRule.getRuleId() + "", judgeRule.getRelationId(), judgeRule.getProductAttrKey(), judgeRule.getRuleCondition() + judgeRule.getUnit(), judgeRule.getRuleFunction(), judgeRule.getProductAttrKeyRecovery(), judgeRule.getRuleConditionRecovery() + judgeRule.getUnitRecovery(), judgeRule.getRuleFunctionRecovery()); @@ -80,22 +82,30 @@ public Long createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { //step 2:保存规则 ProductStatusFunction productStatusFunction = new ProductStatusFunction(); BeanUtils.copyProperties(judgeRule, productStatusFunction); - productStatusFunction.setRuleId(ruleId); DB.save(productStatusFunction); - //step 3:保存关联关系 + //step 3:保存规则与产品的关联关系 ProductStatusFunctionRelation productStatusFunctionRelation = new ProductStatusFunctionRelation(); productStatusFunctionRelation.setRelationId(judgeRule.getRelationId()); productStatusFunctionRelation.setRuleId(ruleId); + //对应zbx下线规则ID productStatusFunctionRelation.setZbxId(triggerIds[0]); + //对应zbx上线规则ID productStatusFunctionRelation.setZbxIdRecovery(triggerIds[1]); DB.save(productStatusFunctionRelation); //step 4:同步到设备 String relationId = judgeRule.getRelationId(); if (ToolUtil.isNum(relationId)) { + //查询出继承了此产品的设备 + String sql = "select device_id from device where product_id = :productId and device_id not in (select relation_id from product_status_function_relation where inherit='0')"; + List deviceDtoList = DB.findDto(DeviceDto.class, sql).setParameter("productId", Long.parseLong(relationId)).findList(); + if (ToolUtil.isEmpty(deviceDtoList)) { + return productStatusFunction.getRuleId(); + } + //从Zbx 查询出所有设备的 名称是 judgeRule.getRuleId() 的触发器 String triggerRes = zbxTrigger.triggerGetByName(judgeRule.getRuleId() + ""); if (ToolUtil.isEmpty(triggerRes)) { return productStatusFunction.getRuleId(); @@ -106,8 +116,7 @@ public Long createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { Map hostRecoveryTriggerMap = zbxTriggerInfoList.parallelStream().filter(o -> o.getTags().parallelStream().anyMatch(t -> "__online__".equals(t.getTag()))) .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid)); - String sql = "select device_id from device where product_id = :productId and device_id not in (select relation_id from product_status_function_relation where inherit='0')"; - List deviceDtoList = DB.findDto(DeviceDto.class, sql).setParameter("productId", Long.parseLong(relationId)).findList(); + //保存 设备与规则的关系 deviceDtoList.forEach(deviceDto -> { String zbxId = Optional.ofNullable(hostTriggerMap.get(deviceDto.getDeviceId())).orElse(""); String zbxIdRecovery = Optional.ofNullable(hostRecoveryTriggerMap.get(deviceDto.getDeviceId())).orElse(""); @@ -124,16 +133,17 @@ public Long createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { } /** - * 修改 设备状态 触发器 + * 修改 触发器 * * @param judgeRule 判断规则 * @return Integer */ public Long updateDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { -// Map rule = new HashMap<>(); -// buildTriggerCreateMap(rule, judgeRule); - ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().ruleId.eq(judgeRule.getRuleId()).relationId.eq(judgeRule.getRelationId()).findOne(); + ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().ruleId.eq(judgeRule.getRuleId()).relationId.eq(judgeRule.getRelationId()).findOne(); + if (null == relation) { + return judgeRule.getRuleId(); + } deviceStatusTrigger.updateDeviceStatusTrigger(relation.getZbxId(), judgeRule.getRuleId() + "", judgeRule.getRelationId(), judgeRule.getProductAttrKey(), judgeRule.getRuleCondition() + judgeRule.getUnit(), judgeRule.getRuleFunction(), judgeRule.getProductAttrKeyRecovery(), judgeRule.getRuleConditionRecovery() + judgeRule.getUnitRecovery(), judgeRule.getRuleFunctionRecovery(), relation.getZbxIdRecovery()); @@ -167,10 +177,10 @@ private void buildTriggerCreateMap(Map rule, ProductStatusJudgeR private String[] getTriggerId(String responseStr) { TriggerIds ids = JSON.parseObject(responseStr, TriggerIds.class); - if (null != ids && ids.getTriggerids().length > 0) { - return ids.getTriggerids(); + if (null == ids || ids.getTriggerids().length != 2) { + throw new ServiceException(BizExceptionEnum.ZBX_CALL_ERR); } - return null; + return ids.getTriggerids(); } /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java index fcd16fc0..ff2acfb9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java @@ -31,17 +31,23 @@ public Boolean action(ProductServiceDto productServiceDto, Map deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); + if (ToolUtil.isEmpty(deviceIds)) { + return true; + } List productServiceRelationList = new ArrayList<>(); List productServiceParamList = new ArrayList<>(); for (String deviceId : deviceIds) { + //保存设备与服务的关联关系 ProductServiceRelation productServiceRelation = new ProductServiceRelation(); productServiceRelation.setRelationId(deviceId); productServiceRelation.setServiceId(productServiceDto.getId()); productServiceRelation.setInherit("1"); productServiceRelationList.add(productServiceRelation); + //保存设备与服务参数的关联关系 productServiceDto.getProductServiceParamList().forEach(productServiceParam -> { ProductServiceParam param = new ProductServiceParam(); ToolUtil.copyProperties(productServiceParam,param); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java index a5342392..ee540f78 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java @@ -32,8 +32,13 @@ public Boolean action(ProductServiceDto productServiceDto, Map deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); + if (ToolUtil.isEmpty(deviceIds)) { + return true; + } + //保存设备与服务参数的 关联关系 List productServiceParamList = new ArrayList<>(); for (String deviceId : deviceIds) { productServiceDto.getProductServiceParamList().forEach(productServiceParam -> { From 8714878db777ff69ee5f866e9df58dd164e9afab Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 18 Nov 2021 21:17:51 +0800 Subject: [PATCH 674/763] [fix]: use spring applicationEvent --- zeus-webapp/pom.xml | 6 ------ .../device/service/SceneScheduleProcessor.java | 12 ++++++++---- .../com/zmops/iot/web/schedule/TaskStarter.java | 16 +++++----------- .../zmops/iot/web/schedule/TaskTriggerPool.java | 10 +++++----- 4 files changed, 18 insertions(+), 26 deletions(-) diff --git a/zeus-webapp/pom.xml b/zeus-webapp/pom.xml index 7969fc18..e51dbd6a 100644 --- a/zeus-webapp/pom.xml +++ b/zeus-webapp/pom.xml @@ -58,12 +58,6 @@ 2.25.4 compile - - com.zmops - iot-eventbus - 1.0-beta - compile - diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java index 945dbd79..ae143571 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java @@ -3,11 +3,13 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.dtflys.forest.Forest; -import com.google.common.eventbus.Subscribe; import com.zmops.iot.util.ToolUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.stereotype.Component; import java.util.Map; @@ -17,13 +19,15 @@ * 定时 触发场景 处理 **/ @Slf4j -@Service +@Component +@EnableAsync public class SceneScheduleProcessor { @Autowired DeviceLogService deviceLogService; - @Subscribe + @EventListener + @Async public void subscribe(String event) { log.info("子线程接收异步事件 - {},String类型", event); if (ToolUtil.isEmpty(event)) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskStarter.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskStarter.java index 67848839..9d8ddc56 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskStarter.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskStarter.java @@ -3,13 +3,10 @@ import com.zmops.iot.web.device.service.SceneScheduleProcessor; import com.zmops.iot.web.schedule.config.ScheduleConfig; -import com.zmops.zeus.iot.server.eventbus.core.EventControllerFactory; -import com.zmops.zeus.iot.server.eventbus.thread.ThreadPoolFactory; -import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadCustomization; -import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadParameter; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Component; /** @@ -25,6 +22,9 @@ public class TaskStarter implements InitializingBean, DisposableBean { @Autowired SceneScheduleProcessor sceneScheduleProcessor; + @Autowired + private ApplicationEventPublisher publisher; + @Override public void destroy() throws Exception { schedule.toStop(); @@ -36,15 +36,9 @@ public void afterPropertiesSet() throws Exception { ScheduleConfig scheduleConfig = new ScheduleConfig(); - ThreadPoolFactory threadPoolFactory = new ThreadPoolFactory(new ThreadCustomization(), new ThreadParameter()); - - EventControllerFactory eventControllerFactory = new EventControllerFactory(threadPoolFactory); - - triggerPool = new TaskTriggerPool(scheduleConfig,eventControllerFactory); + triggerPool = new TaskTriggerPool(scheduleConfig, publisher); triggerPool.start(); - eventControllerFactory.getAsyncController("scene").register(sceneScheduleProcessor); - schedule = new TaskScheduleImpl(scheduleConfig); schedule.start(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java index e0ca70db..b6b2302e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java @@ -1,8 +1,8 @@ package com.zmops.iot.web.schedule; import com.zmops.iot.web.schedule.config.ScheduleConfig; -import com.zmops.zeus.iot.server.eventbus.core.EventControllerFactory; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationEventPublisher; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; @@ -17,13 +17,13 @@ public class TaskTriggerPool { private ThreadPoolExecutor fastTriggerPool = null; private ThreadPoolExecutor slowTriggerPool = null; - private EventControllerFactory eventControllerFactory; + private ApplicationEventPublisher publisher; private final ScheduleConfig scheduleConfig; - public TaskTriggerPool(ScheduleConfig scheduleConfig,EventControllerFactory eventControllerFactory) { + public TaskTriggerPool(ScheduleConfig scheduleConfig, ApplicationEventPublisher publisher) { this.scheduleConfig = scheduleConfig; - this.eventControllerFactory = eventControllerFactory; + this.publisher = publisher; helper = this; } @@ -73,7 +73,7 @@ public void addTrigger(final int jobId, try { log.info("jobid : {},executeParam : {}", jobId,executorParam); - eventControllerFactory.getAsyncController("scene").post(executorParam); + publisher.publishEvent(executorParam); } catch (Exception e) { log.error(e.getMessage(), e); From f6827b8b7e39f45b5671a635c3081b1f6a250ba8 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 19 Nov 2021 10:53:05 +0800 Subject: [PATCH 675/763] [fix]: fix application event --- .../service/SceneScheduleProcessor.java | 11 +++++----- .../iot/web/event/EventProcessFactory.java | 20 ------------------- .../web/event/applicationEvent/BaseEvent.java | 20 +++++++++++++++++++ .../event/applicationEvent/SceneEvent.java | 12 +++++++++++ .../applicationEvent/dto/SceneEventData.java | 17 ++++++++++++++++ .../event/{ => pgEvent}/EventDataProcess.java | 4 ++-- .../web/event/{ => pgEvent}/EventProcess.java | 4 ++-- .../web/event/{ => pgEvent}/SyncZbxEvent.java | 2 +- .../event/{ => pgEvent}/dto/EventDataDto.java | 2 +- .../service/AlarmEventProcess.java | 6 +++--- .../service/IncidentEventProcess.java | 6 +++--- .../service/OfflineEventProcess.java | 6 +++--- .../service/OnlineEventProcess.java | 6 +++--- .../service/SceneEventProcess.java | 6 +++--- .../service/ServiceEventProcess.java | 6 +++--- .../iot/web/schedule/TaskTriggerPool.java | 4 +++- 16 files changed, 82 insertions(+), 50 deletions(-) delete mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/event/EventProcessFactory.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/BaseEvent.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/SceneEvent.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/dto/SceneEventData.java rename zeus-webapp/src/main/java/com/zmops/iot/web/event/{ => pgEvent}/EventDataProcess.java (91%) rename zeus-webapp/src/main/java/com/zmops/iot/web/event/{ => pgEvent}/EventProcess.java (58%) rename zeus-webapp/src/main/java/com/zmops/iot/web/event/{ => pgEvent}/SyncZbxEvent.java (96%) rename zeus-webapp/src/main/java/com/zmops/iot/web/event/{ => pgEvent}/dto/EventDataDto.java (89%) rename zeus-webapp/src/main/java/com/zmops/iot/web/event/{ => pgEvent}/service/AlarmEventProcess.java (97%) rename zeus-webapp/src/main/java/com/zmops/iot/web/event/{ => pgEvent}/service/IncidentEventProcess.java (93%) rename zeus-webapp/src/main/java/com/zmops/iot/web/event/{ => pgEvent}/service/OfflineEventProcess.java (89%) rename zeus-webapp/src/main/java/com/zmops/iot/web/event/{ => pgEvent}/service/OnlineEventProcess.java (89%) rename zeus-webapp/src/main/java/com/zmops/iot/web/event/{ => pgEvent}/service/SceneEventProcess.java (84%) rename zeus-webapp/src/main/java/com/zmops/iot/web/event/{ => pgEvent}/service/ServiceEventProcess.java (96%) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java index ae143571..a8a91e37 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject; import com.dtflys.forest.Forest; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.SceneEvent; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.event.EventListener; @@ -26,14 +27,14 @@ public class SceneScheduleProcessor { @Autowired DeviceLogService deviceLogService; - @EventListener + @EventListener(classes = {SceneEvent.class}) @Async - public void subscribe(String event) { - log.info("子线程接收异步事件 - {},String类型", event); - if (ToolUtil.isEmpty(event)) { + public void subscribe(SceneEvent event) { + log.info("子线程接收异步事件 - {},String类型,执行顺序{}", event.getEventData().getExecuteParam(), 2); + if (ToolUtil.isEmpty(event.getEventData().getExecuteParam())) { return; } - Map eventMap = JSONObject.parseObject(event, Map.class); + Map eventMap = JSONObject.parseObject(event.getEventData().getExecuteParam(), Map.class); Long eventRuleId = Long.parseLong(eventMap.get("eventRuleId").toString()); //记录日志 deviceLogService.recordSceneLog(eventRuleId, "自动", null); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventProcessFactory.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventProcessFactory.java deleted file mode 100644 index a4438101..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventProcessFactory.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.zmops.iot.web.event; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author yefei - **/ -public class EventProcessFactory { - - private static final Map EVENT_PROCESS_MAP = new HashMap<>(); - - public static void register(String tag, EventProcess eventProcess) { - EVENT_PROCESS_MAP.put(tag, eventProcess); - } - - public static EventProcess getExecuteService(String key) { - return EVENT_PROCESS_MAP.get(key); - } -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/BaseEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/BaseEvent.java new file mode 100644 index 00000000..e9fad34e --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/BaseEvent.java @@ -0,0 +1,20 @@ +package com.zmops.iot.web.event.applicationEvent; + +import org.springframework.context.ApplicationEvent; + +/** + * @author yefei + **/ +public abstract class BaseEvent extends ApplicationEvent { + + private T eventData; + + public BaseEvent(Object source, T eventData) { + super(source); + this.eventData = eventData; + } + + public T getEventData() { + return eventData; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/SceneEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/SceneEvent.java new file mode 100644 index 00000000..8037b735 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/SceneEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.event.applicationEvent.dto.SceneEventData; + +/** + * @author yefei + **/ +public class SceneEvent extends BaseEvent { + public SceneEvent(Object source, SceneEventData eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/dto/SceneEventData.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/dto/SceneEventData.java new file mode 100644 index 00000000..8be68af4 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/dto/SceneEventData.java @@ -0,0 +1,17 @@ +package com.zmops.iot.web.event.applicationEvent.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author yefei + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class SceneEventData { + + private String executeParam; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventDataProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/EventDataProcess.java similarity index 91% rename from zeus-webapp/src/main/java/com/zmops/iot/web/event/EventDataProcess.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/EventDataProcess.java index d4df90d3..9c083c72 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventDataProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/EventDataProcess.java @@ -1,7 +1,7 @@ -package com.zmops.iot.web.event; +package com.zmops.iot.web.event.pgEvent; import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.web.event.dto.EventDataDto; +import com.zmops.iot.web.event.pgEvent.dto.EventDataDto; import lombok.extern.slf4j.Slf4j; import org.apache.camel.Exchange; import org.apache.camel.Processor; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/EventProcess.java similarity index 58% rename from zeus-webapp/src/main/java/com/zmops/iot/web/event/EventProcess.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/EventProcess.java index 24b77eeb..aee831cc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/EventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/EventProcess.java @@ -1,6 +1,6 @@ -package com.zmops.iot.web.event; +package com.zmops.iot.web.event.pgEvent; -import com.zmops.iot.web.event.dto.EventDataDto; +import com.zmops.iot.web.event.pgEvent.dto.EventDataDto; /** * @author yefei diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/SyncZbxEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/SyncZbxEvent.java similarity index 96% rename from zeus-webapp/src/main/java/com/zmops/iot/web/event/SyncZbxEvent.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/SyncZbxEvent.java index 15be446c..fb31373b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/SyncZbxEvent.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/SyncZbxEvent.java @@ -1,4 +1,4 @@ -package com.zmops.iot.web.event; +package com.zmops.iot.web.event.pgEvent; import com.zmops.iot.util.SpringUtils; import org.apache.camel.LoggingLevel; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/dto/EventDataDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/dto/EventDataDto.java similarity index 89% rename from zeus-webapp/src/main/java/com/zmops/iot/web/event/dto/EventDataDto.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/dto/EventDataDto.java index e0470648..7eaa2463 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/dto/EventDataDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/dto/EventDataDto.java @@ -1,4 +1,4 @@ -package com.zmops.iot.web.event.dto; +package com.zmops.iot.web.event.pgEvent.dto; import lombok.Data; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/AlarmEventProcess.java similarity index 97% rename from zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/AlarmEventProcess.java index 65c5ff3d..1e8dbb29 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/AlarmEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/AlarmEventProcess.java @@ -1,4 +1,4 @@ -package com.zmops.iot.web.event.service; +package com.zmops.iot.web.event.pgEvent.service; import com.zmops.iot.domain.alarm.Problem; import com.zmops.iot.domain.messages.MessageBody; @@ -15,8 +15,8 @@ import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.alarm.service.AlarmService; import com.zmops.iot.web.alarm.service.MessageService; -import com.zmops.iot.web.event.EventProcess; -import com.zmops.iot.web.event.dto.EventDataDto; +import com.zmops.iot.web.event.pgEvent.EventProcess; +import com.zmops.iot.web.event.pgEvent.dto.EventDataDto; import com.zmops.iot.web.sys.dto.UserGroupDto; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/IncidentEventProcess.java similarity index 93% rename from zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/IncidentEventProcess.java index 0e7a1470..124d97a9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/IncidentEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/IncidentEventProcess.java @@ -1,4 +1,4 @@ -package com.zmops.iot.web.event.service; +package com.zmops.iot.web.event.pgEvent.service; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.EventTriggerRecord; @@ -7,8 +7,8 @@ import com.zmops.iot.domain.product.query.QProductAttributeEvent; import com.zmops.iot.web.analyse.dto.LatestDto; import com.zmops.iot.web.analyse.service.LatestService; -import com.zmops.iot.web.event.EventProcess; -import com.zmops.iot.web.event.dto.EventDataDto; +import com.zmops.iot.web.event.pgEvent.EventProcess; +import com.zmops.iot.web.event.pgEvent.dto.EventDataDto; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/OfflineEventProcess.java similarity index 89% rename from zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/OfflineEventProcess.java index c9bed02a..c59a4357 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OfflineEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/OfflineEventProcess.java @@ -1,12 +1,12 @@ -package com.zmops.iot.web.event.service; +package com.zmops.iot.web.event.pgEvent.service; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductStatusFunctionRelation; import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.event.EventProcess; -import com.zmops.iot.web.event.dto.EventDataDto; +import com.zmops.iot.web.event.pgEvent.EventProcess; +import com.zmops.iot.web.event.pgEvent.dto.EventDataDto; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OnlineEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/OnlineEventProcess.java similarity index 89% rename from zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OnlineEventProcess.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/OnlineEventProcess.java index 96cbad01..1971fbff 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/OnlineEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/OnlineEventProcess.java @@ -1,12 +1,12 @@ -package com.zmops.iot.web.event.service; +package com.zmops.iot.web.event.pgEvent.service; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductStatusFunctionRelation; import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.event.EventProcess; -import com.zmops.iot.web.event.dto.EventDataDto; +import com.zmops.iot.web.event.pgEvent.EventProcess; +import com.zmops.iot.web.event.pgEvent.dto.EventDataDto; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/SceneEventProcess.java similarity index 84% rename from zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/SceneEventProcess.java index 88998bed..297d13c5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/SceneEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/SceneEventProcess.java @@ -1,9 +1,9 @@ -package com.zmops.iot.web.event.service; +package com.zmops.iot.web.event.pgEvent.service; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.service.MultipleDeviceEventRuleService; -import com.zmops.iot.web.event.EventProcess; -import com.zmops.iot.web.event.dto.EventDataDto; +import com.zmops.iot.web.event.pgEvent.EventProcess; +import com.zmops.iot.web.event.pgEvent.dto.EventDataDto; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/ServiceEventProcess.java similarity index 96% rename from zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/ServiceEventProcess.java index facbf1a1..3868e88d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/service/ServiceEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/ServiceEventProcess.java @@ -1,4 +1,4 @@ -package com.zmops.iot.web.event.service; +package com.zmops.iot.web.event.pgEvent.service; import com.alibaba.fastjson.JSON; import com.dtflys.forest.Forest; @@ -12,8 +12,8 @@ import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.service.work.DeviceServiceLogWorker; -import com.zmops.iot.web.event.EventProcess; -import com.zmops.iot.web.event.dto.EventDataDto; +import com.zmops.iot.web.event.pgEvent.EventProcess; +import com.zmops.iot.web.event.pgEvent.dto.EventDataDto; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java index b6b2302e..eb735e19 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java @@ -1,5 +1,7 @@ package com.zmops.iot.web.schedule; +import com.zmops.iot.web.event.applicationEvent.SceneEvent; +import com.zmops.iot.web.event.applicationEvent.dto.SceneEventData; import com.zmops.iot.web.schedule.config.ScheduleConfig; import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationEventPublisher; @@ -73,7 +75,7 @@ public void addTrigger(final int jobId, try { log.info("jobid : {},executeParam : {}", jobId,executorParam); - publisher.publishEvent(executorParam); + publisher.publishEvent(new SceneEvent(this,new SceneEventData(executorParam))); } catch (Exception e) { log.error(e.getMessage(), e); From 570dc289645fdb7ad695e8299e8e364b66580306 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 22 Nov 2021 09:40:12 +0800 Subject: [PATCH 676/763] [fix]: code format --- .../MultipleDeviceEventTriggerController.java | 10 +++++----- .../web/device/service/DeviceEventRuleService.java | 2 +- .../service/MultipleDeviceEventRuleService.java | 12 +++++++----- .../web/device/service/SceneScheduleProcessor.java | 2 +- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java index a66cd1a2..35333b56 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java @@ -37,7 +37,7 @@ /** * @author yefei *

- * 设备联动 + * 设备 场景 联动 **/ @RestController @RequestMapping("/multiple/device/event/trigger") @@ -124,8 +124,8 @@ public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEn .collect(Collectors.toMap(MultipleDeviceEventRule.Tag::getTag, MultipleDeviceEventRule.Tag::getValue, (k1, k2) -> k2)); } - if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { - tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(SCENE_TAG_NAME)) { + tags.put(SCENE_TAG_NAME, eventRuleId + ""); } for (String triggerId : triggerIds) { @@ -216,8 +216,8 @@ public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEn .collect(Collectors.toMap(MultipleDeviceEventRule.Tag::getTag, MultipleDeviceEventRule.Tag::getValue, (k1, k2) -> k2)); } - if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { - tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(SCENE_TAG_NAME)) { + tags.put(SCENE_TAG_NAME, eventRule.getEventRuleId() + ""); } for (String triggerId : triggerIds) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index 23b0d9e4..443db38e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -295,7 +295,7 @@ public void checkService(List deviceServices) { return; } long count = deviceServices.parallelStream().map(DeviceEventRule.DeviceService::getServiceId).distinct().count(); - if (count > 0) { + if (count < deviceServices.size()) { throw new ServiceException(BizExceptionEnum.SERVICE_HAS_DUPLICATE); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index 439ea788..b73f59e2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -35,6 +35,8 @@ /** * @author yefei + * + * 设备 场景 联动 服务 **/ @Service public class MultipleDeviceEventRuleService { @@ -48,7 +50,7 @@ public class MultipleDeviceEventRuleService { public static final int TRIGGER_TYPE_CONDITION = 0; - public static final String EXECUTE_TAG_NAME = "__scene__"; + public static final String SCENE_TAG_NAME = "__scene__"; @Autowired TaskService taskService; @@ -77,8 +79,8 @@ public List list(MultipleDeviceEventParm eventParm) { /** * 设备联动 分页列表 * - * @param eventParm - * @return + * @param eventParm 查询参数 + * @return MultipleDeviceEventDto */ public Pager getEventByPage(MultipleDeviceEventParm eventParm) { QProductEvent query = new QProductEvent(); @@ -157,7 +159,7 @@ private String generateExecuteParam(MultipleDeviceEventRule eventRule) { Map> collect = eventRule.getDeviceServices().parallelStream().collect(Collectors.groupingBy(MultipleDeviceEventRule.DeviceService::getExecuteDeviceId)); collect.forEach((key, value) -> { - Map map = new ConcurrentHashMap<>(); + Map map = new ConcurrentHashMap<>(2); map.put("device", key); List> serviceList = new ArrayList<>(); @@ -435,7 +437,7 @@ public MultipleDeviceEventDto detail(ProductEvent productEvent, long eventRuleId List tagList = JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), MultipleDeviceEventRule.Tag.class); multipleDeviceEventDto.setTags(tagList.stream() - .filter(s -> !s.getTag().equals(EXECUTE_TAG_NAME)) + .filter(s -> !s.getTag().equals(SCENE_TAG_NAME)) .collect(Collectors.toList())); } else { Task task = new QTask().id.eq(productEvent.getTaskId()).findOne(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java index a8a91e37..5eb13c25 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java @@ -30,7 +30,7 @@ public class SceneScheduleProcessor { @EventListener(classes = {SceneEvent.class}) @Async public void subscribe(SceneEvent event) { - log.info("子线程接收异步事件 - {},String类型,执行顺序{}", event.getEventData().getExecuteParam(), 2); + log.info("子线程接收异步事件 - {},String类型", event.getEventData().getExecuteParam()); if (ToolUtil.isEmpty(event.getEventData().getExecuteParam())) { return; } From 6629c49dde5095682fe32757e585ab4c06f3571f Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Tue, 23 Nov 2021 10:14:25 +0800 Subject: [PATCH 677/763] [fix]: fix start script --- dist-material/bin/startup.sh | 16 ---------------- dist-material/bin/stop.sh | 16 +++++++++------- docker/dockerfile | 2 +- 3 files changed, 10 insertions(+), 24 deletions(-) diff --git a/dist-material/bin/startup.sh b/dist-material/bin/startup.sh index 274eeffa..0ff60e71 100644 --- a/dist-material/bin/startup.sh +++ b/dist-material/bin/startup.sh @@ -1,19 +1,3 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - #!/usr/bin/env bash source /etc/profile PRG="$0" diff --git a/dist-material/bin/stop.sh b/dist-material/bin/stop.sh index f8efec7c..45134e12 100755 --- a/dist-material/bin/stop.sh +++ b/dist-material/bin/stop.sh @@ -3,10 +3,12 @@ set -x status=`ps -ef | grep zeus-iot-bin | grep java | grep -v grep | awk '{print $2}' | wc -l` -if [ $status -ne 0 ] -then - for i in `ps -ef | grep zeus-iot-bin | grep java | grep -v grep | awk '{print $2}'` - do - kill -9 $i - done -fi +while [ $status -ne 0 ] +do + for i in `ps -ef | grep zeus-iot-bin | grep java | grep -v grep | awk '{print $2}'` + do + kill $i + done + sleep 5 + status=`ps -ef | grep zeus-iot-bin | grep java | grep -v grep | awk '{print $2}' | wc -l` +done \ No newline at end of file diff --git a/docker/dockerfile b/docker/dockerfile index 00b0ca41..5d17aec1 100644 --- a/docker/dockerfile +++ b/docker/dockerfile @@ -8,7 +8,7 @@ RUN apk update \ && echo Asia/Shanghai > /etc/timezone \ && rm -rf /var/cache/apk/* -ADD https://packages.zmops.cn/zeus-iot/zeus-iot-bin.tar.gz / +ADD https://xxxxx/zeus-iot/zeus-iot-bin.tar.gz / RUN tar -xf zeus-iot-bin.tar.gz COPY log4j2.xml /zeus-iot-bin/config/log4j2.xml COPY docker-entrypoint.sh /usr/bin/docker-entrypoint.sh From 388fd792bda9de4804fb84a130382ed07838ae9b Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 23 Nov 2021 11:08:58 +0800 Subject: [PATCH 678/763] [fix]: fix mail setting response --- .../controller/MailSettingController.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MailSettingController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MailSettingController.java index 583e6fac..5745ca03 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MailSettingController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MailSettingController.java @@ -5,6 +5,7 @@ import com.zmops.iot.domain.messages.MailSetting; import com.zmops.iot.domain.messages.NoticeResult; import com.zmops.iot.domain.messages.MailParam; +import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.web.alarm.service.MailSettingServiceImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; @@ -25,18 +26,23 @@ public class MailSettingController { MailSettingServiceImpl settingService; @RequestMapping("get") - public MailSetting get() { - return settingService.get(); + public ResponseData get() { + return ResponseData.success(settingService.get()); } @PostMapping("test") - public NoticeResult test(@Validated(MailParam.Test.class) @RequestBody MailParam mailParam) { - return settingService.test(mailParam); + public ResponseData test(@Validated(MailParam.Test.class) @RequestBody MailParam mailParam) { + NoticeResult test = settingService.test(mailParam); + if(test.getStatus().equals(NoticeResult.NoticeStatus.success)){ + return ResponseData.success(test.getMsg()); + }else{ + return ResponseData.error(test.getMsg()); + } } @PostMapping("update") - public Integer update(@Validated(BaseEntity.Update.class) @RequestBody MailParam mailParam) { - return settingService.updateSettings(mailParam.getSettings()); + public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody MailParam mailParam) { + return ResponseData.success(settingService.updateSettings(mailParam.getSettings())); } } From f9c2b79f558b813a365c33ca1affd95779e61e7d Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 23 Nov 2021 15:12:52 +0800 Subject: [PATCH 679/763] [fix]: fix init sql --- dist-material/bin/sql/zeus-iot.sql | 6 +++--- .../iot/web/event/pgEvent/service/AlarmEventProcess.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dist-material/bin/sql/zeus-iot.sql b/dist-material/bin/sql/zeus-iot.sql index b593eea3..3ca1da35 100644 --- a/dist-material/bin/sql/zeus-iot.sql +++ b/dist-material/bin/sql/zeus-iot.sql @@ -12,7 +12,7 @@ Target Server Version : 130004 File Encoding : 65001 - Date: 17/11/2021 14:53:58 + Date: 23/11/2021 14:28:57 */ @@ -387,10 +387,10 @@ CREATE TABLE "public"."mail_setting" ( "port" int4 NOT NULL, "account" varchar(100) COLLATE "pg_catalog"."default" NOT NULL, "password" varchar(100) COLLATE "pg_catalog"."default" NOT NULL, - "sender" varchar(100) COLLATE "pg_catalog"."default" NOT NULL, + "sender" varchar(100) COLLATE "pg_catalog"."default", "ssl" int4 NOT NULL DEFAULT 0, "tls" int4 NOT NULL DEFAULT 0, - "severity" varchar(255) COLLATE "pg_catalog"."default" NOT NULL DEFAULT ''::character varying, + "severity" varchar(255) COLLATE "pg_catalog"."default" DEFAULT ''::character varying, "silent" int2 NOT NULL DEFAULT 3, "id" int4 NOT NULL DEFAULT nextval('mail_setting_id_seq'::regclass) ) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/AlarmEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/AlarmEventProcess.java index 1e8dbb29..16fbfdb3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/AlarmEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/AlarmEventProcess.java @@ -81,8 +81,8 @@ public void process(EventDataDto eventData) { params.put("triggerName", triggerName); String sql = "select user_group_id from sys_usrgrp_devicegrp where device_group_id in (select device_group_id from devices_groups where device_id in (:deviceIds))"; - List userGroups = DB.findNative(UserGroupDto.class, sql).setParameter("deviceIds", deviceIds).findList(); - + List userGroups = DB.findDto(UserGroupDto.class, sql).setParameter("deviceIds", deviceIds).findList(); + QSysUser qSysUser = new QSysUser(); if (ToolUtil.isNotEmpty(userGroups)) { qSysUser.userGroupId.in(userGroups.parallelStream().map(UserGroupDto::getUserGroupId).collect(Collectors.toList())); From e7cd85b77617cc11d3593b6663109ca2e3c6c7c5 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 23 Nov 2021 17:08:19 +0800 Subject: [PATCH 680/763] [fix]: valid device name --- zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java | 4 ++++ .../zmops/iot/web/device/controller/DeviceController.java | 6 ++++++ .../main/java/com/zmops/iot/web/device/dto/DeviceDto.java | 1 + .../com/zmops/iot/web/exception/enums/BizExceptionEnum.java | 1 + .../web/product/service/work/AsyncAttrEventZbxIdWorker.java | 3 +++ 5 files changed, 15 insertions(+) diff --git a/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java b/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java index 0589fae1..a518b506 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java @@ -444,4 +444,8 @@ public static boolean validCron(String cron){ //String tests = "0 0 0 L * ?"; return CronExpression.isValidExpression(cron); } + + public static boolean validDeviceName(String content){ + return content.contains("\\") || content.contains("/"); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java index 6ee33fb3..d78095f5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java @@ -63,6 +63,9 @@ public ResponseData deviceList(@RequestBody DeviceParams deviceParams) { @Permission(code = "dev_add") @RequestMapping("/create") public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody DeviceDto deviceDto) { + if (ToolUtil.validDeviceName(deviceDto.getName())) { + throw new ServiceException(BizExceptionEnum.DEVICE_NAME_HAS_INCOREECT_CHARACTER); + } int count = new QDevice().name.eq(deviceDto.getName()).findCount(); if (count > 0) { throw new ServiceException(BizExceptionEnum.DEVICE_EXISTS); @@ -89,6 +92,9 @@ public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody Devi @Permission(code = "dev_update") @RequestMapping("/update") public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody DeviceDto deviceDto) { + if (ToolUtil.validDeviceName(deviceDto.getName())) { + throw new ServiceException(BizExceptionEnum.DEVICE_NAME_HAS_INCOREECT_CHARACTER); + } int count = new QDevice().deviceId.ne(deviceDto.getDeviceId()).name.eq(deviceDto.getName()).findCount(); if (count > 0) { throw new ServiceException(BizExceptionEnum.DEVICE_EXISTS); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java index 2a882bca..17aaca46 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java @@ -10,6 +10,7 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; import java.time.LocalDateTime; import java.util.List; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index 376b500b..921066c3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -153,6 +153,7 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { DEVICE_EXISTS(1501, "设备名称已存在"), DEVICE_ID_EXISTS(1503, "设备ID已存在"), DEVICE_NOT_EXISTS(1502, "设备不存在"), + DEVICE_NAME_HAS_INCOREECT_CHARACTER(1504,"设备名称不能包含\\或\\/字符"), /** * 服务相关 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java index 999317f4..ee24b0e7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java @@ -46,6 +46,9 @@ public Boolean action(ProductAttr productAttr, Map map) { //取出继承的属性 并塞入对应的 itemId List productAttributeEventList = new QProductAttributeEvent().templateId.eq(attrId).findList(); for (ProductAttributeEvent productAttributeEvent : productAttributeEventList) { + if (itemMap.get(productAttributeEvent.getProductId() + "") == null) { + continue; + } productAttributeEvent.setZbxId(itemMap.get(productAttributeEvent.getProductId() + "").getItemid()); } From 25cd6ff5be5f7e918d9ac9615f83b16d4c9cdaf6 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Tue, 23 Nov 2021 17:59:00 +0800 Subject: [PATCH 681/763] [fix]: fix stop script --- dist-material/bin/stop.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dist-material/bin/stop.sh b/dist-material/bin/stop.sh index 45134e12..05cf8120 100755 --- a/dist-material/bin/stop.sh +++ b/dist-material/bin/stop.sh @@ -7,8 +7,6 @@ while [ $status -ne 0 ] do for i in `ps -ef | grep zeus-iot-bin | grep java | grep -v grep | awk '{print $2}'` do - kill $i + kill -9 $i done - sleep 5 - status=`ps -ef | grep zeus-iot-bin | grep java | grep -v grep | awk '{print $2}' | wc -l` done \ No newline at end of file From c6d79d6db6b4fe727a71df26fae6d8fccee63d98 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 23 Nov 2021 18:02:30 +0800 Subject: [PATCH 682/763] [fix]: fix socketio --- .../com/zmops/iot/message/config/MessageServerConfig.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zeus-message/src/main/java/com/zmops/iot/message/config/MessageServerConfig.java b/zeus-message/src/main/java/com/zmops/iot/message/config/MessageServerConfig.java index 806426d9..439df834 100644 --- a/zeus-message/src/main/java/com/zmops/iot/message/config/MessageServerConfig.java +++ b/zeus-message/src/main/java/com/zmops/iot/message/config/MessageServerConfig.java @@ -1,6 +1,7 @@ package com.zmops.iot.message.config; import cn.hutool.core.util.StrUtil; +import com.corundumstudio.socketio.SocketConfig; import com.corundumstudio.socketio.SocketIOServer; import com.corundumstudio.socketio.annotation.SpringAnnotationScanner; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -19,6 +20,9 @@ public class MessageServerConfig { public SocketIOServer server(SocketIoConfig socketIoConfig) { com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration(); + SocketConfig socketConfig = new SocketConfig(); + socketConfig.setReuseAddress(true); + config.setSocketConfig(socketConfig); config.setHostname(socketIoConfig.getHost()); config.setPort(socketIoConfig.getPort()); From 32517a07af7e9e4413a24f867e1ae0e6f39e7f68 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Tue, 23 Nov 2021 18:21:13 +0800 Subject: [PATCH 683/763] [fix]: fix stop script --- dist-material/bin/stop.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/dist-material/bin/stop.sh b/dist-material/bin/stop.sh index 05cf8120..a8c8db0f 100755 --- a/dist-material/bin/stop.sh +++ b/dist-material/bin/stop.sh @@ -9,4 +9,5 @@ do do kill -9 $i done + status=`ps -ef | grep zeus-iot-bin | grep java | grep -v grep | awk '{print $2}' | wc -l` done \ No newline at end of file From 3a3639b34759579f1b16d8d6d2e879fa12b26fc1 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 23 Nov 2021 19:39:05 +0800 Subject: [PATCH 684/763] [fix]: fix alarm message --- .../web/event/pgEvent/service/AlarmEventProcess.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/AlarmEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/AlarmEventProcess.java index 16fbfdb3..d54def40 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/AlarmEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/AlarmEventProcess.java @@ -82,7 +82,7 @@ public void process(EventDataDto eventData) { String sql = "select user_group_id from sys_usrgrp_devicegrp where device_group_id in (select device_group_id from devices_groups where device_id in (:deviceIds))"; List userGroups = DB.findDto(UserGroupDto.class, sql).setParameter("deviceIds", deviceIds).findList(); - + QSysUser qSysUser = new QSysUser(); if (ToolUtil.isNotEmpty(userGroups)) { qSysUser.userGroupId.in(userGroups.parallelStream().map(UserGroupDto::getUserGroupId).collect(Collectors.toList())); @@ -90,12 +90,13 @@ public void process(EventDataDto eventData) { List sysUserList = qSysUser.findList(); List userIds = sysUserList.parallelStream().map(SysUser::getUserId).collect(Collectors.toList()); - messageService.push(buildMessage(params, userIds)); + alarmService.alarm(params); //发送Email消息 ProductEvent productEvent = new QProductEvent().eventRuleId.eq(Long.parseLong(triggerName)).findOne(); Map macros = createMacroMap(triggerId, eventData.getRClock() + "", eventData.getAcknowledged() + "", productEvent); + messageService.push(buildMessage(macros, userIds)); List noticeRecords = new ArrayList<>(); sysUserList.forEach(sysUser -> { @@ -131,9 +132,9 @@ private Map createMacroMap(String triggerId, String rclock, Stri return macroMap; } - private MessageBody buildMessage(Map alarmInfo, List userIds) { - - return MessageBody.builder().msg("告警消息").persist(true).to(userIds).body(alarmInfo).build(); + private MessageBody buildMessage(Map alarmInfo, List userIds) { + Map params = new HashMap<>(alarmInfo); + return MessageBody.builder().msg("发生告警:" + alarmInfo.get("${metricName}")).persist(true).to(userIds).body(params).build(); } From a135fc90a944fb46357a1169e5099641890daee6 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 23 Nov 2021 23:40:05 +0800 Subject: [PATCH 685/763] [fix]: Iot server architecture adjustment --- iot-common/iot-datacarrier/pom.xml | 22 - .../iot/server/datacarrier/DataCarrier.java | 162 ----- .../zeus/iot/server/datacarrier/EnvUtil.java | 50 -- .../buffer/ArrayBlockingQueueBuffer.java | 67 -- .../iot/server/datacarrier/buffer/Buffer.java | 76 --- .../datacarrier/buffer/BufferStrategy.java | 23 - .../server/datacarrier/buffer/Channels.java | 94 --- .../datacarrier/buffer/QueueBuffer.java | 46 -- .../common/AtomicRangeInteger.java | 76 --- .../datacarrier/consumer/BulkConsumePool.java | 120 ---- .../datacarrier/consumer/ConsumeDriver.java | 131 ---- .../ConsumerCannotBeCreatedException.java | 25 - .../datacarrier/consumer/ConsumerPool.java | 31 - .../consumer/ConsumerPoolFactory.java | 50 -- .../datacarrier/consumer/ConsumerThread.java | 106 --- .../datacarrier/consumer/IConsumer.java | 31 - .../server/datacarrier/consumer/IDriver.java | 33 - .../consumer/MultipleChannelsConsumer.java | 125 ---- .../partition/IDataPartitioner.java | 34 - .../partition/ProducerThreadPartitioner.java | 37 -- .../partition/SimpleRollingPartitioner.java | 37 -- iot-common/iot-eventbus/pom.xml | 49 -- .../eventbus/constant/EventConstant.java | 15 - .../zeus/iot/server/eventbus/core/Event.java | 41 -- .../server/eventbus/core/EventController.java | 23 - .../eventbus/core/EventControllerFactory.java | 101 --- .../eventbus/core/EventControllerImpl.java | 46 -- .../iot/server/eventbus/core/EventType.java | 31 - .../eventbus/thread/ThreadPoolFactory.java | 193 ------ .../thread/constant/ThreadConstant.java | 19 - .../thread/entity/ThreadCustomization.java | 70 -- .../thread/entity/ThreadParameter.java | 42 -- .../thread/entity/ThreadQueueType.java | 32 - .../entity/ThreadRejectedPolicyType.java | 34 - .../thread/policy/AbortPolicyWithReport.java | 31 - .../policy/BlockingPolicyWithReport.java | 47 -- .../policy/CallerRunsPolicyWithReport.java | 30 - .../policy/DiscardedPolicyWithReport.java | 43 -- .../policy/RejectedPolicyWithReport.java | 51 -- .../thread/policy/RejectedRunnable.java | 6 - .../server/eventbus/thread/util/NetUtil.java | 205 ------ .../eventbus/thread/util/StringUtil.java | 15 - iot-common/iot-util/pom.xml | 19 - .../util/PlaceholderConfigurerSupport.java | 38 -- .../util/PropertyPlaceholderHelper.java | 206 ------ .../zeus/iot/server/util/StringUtil.java | 110 ---- iot-common/pom.xml | 25 - iot-server/pom.xml | 13 +- iot-server/server-action/pom.xml | 19 - .../server/action/ActionRouteIdentifier.java | 9 - .../iot/server/action/HelloWorldAction.java | 22 - .../iot/server/action/bean/ActionParam.java | 15 - iot-server/server-bootstrap/pom.xml | 15 +- .../server/starter/IoTServerBootstrap.java | 4 +- .../config/ApplicationConfigLoader.java | 13 +- iot-server/server-camel-receiver/pom.xml | 16 +- .../receiver/module/CamelReceiverModule.java | 2 +- .../provider/CamelReceiverConfig.java | 2 +- .../provider/CamelReceiverProvider.java | 9 +- .../routes/MqttClientRouteBuilder.java | 9 + .../receiver/routes/PgEventRouteBuilder.java | 17 + .../service/CamelContextHolderService.java | 10 +- ...OTDeviceValue.java => IoTDeviceValue.java} | 2 +- .../tozabbix/ZabbixSenderComponent.java | 2 +- .../tozabbix/ZabbixSenderEndpoint.java | 4 +- .../tozabbix/ZabbixTrapperProducer.java | 9 +- .../process/JsonToItemValueProcess.java | 4 +- .../tozabbix/worker/AbstractWorker.java | 2 +- .../worker/ItemDataTransferWorker.java | 14 +- .../tozabbix/worker/TransferWorker.java | 2 +- ...s.zeus.server.library.module.ModuleDefine} | 0 ...zeus.server.library.module.ModuleProvider} | 0 .../library-client => server-client}/pom.xml | 17 +- .../zmops/zeus/iot/server}/client/Client.java | 2 +- .../iot/server}/client/ClientException.java | 2 +- .../healthcheck/DelegatedHealthChecker.java | 4 +- .../client/healthcheck/HealthCheckable.java | 4 +- .../client/jdbc/JDBCClientException.java | 2 +- .../jdbc/hikaricp/JDBCHikariCPClient.java | 19 +- .../server}/client/request/InsertRequest.java | 2 +- .../client/request/PrepareRequest.java | 2 +- iot-server/server-core/pom.xml | 28 +- .../zeus/iot/server/core/CoreModule.java | 6 +- .../iot/server/core/CoreModuleConfig.java | 2 +- .../iot/server/core/CoreModuleProvider.java | 42 +- .../analysis/StreamAnnotationListener.java | 3 +- .../worker/RecordPersistentWorker.java | 4 +- .../worker/RecordStreamProcessor.java | 2 +- .../core/annotation/AnnotationScan.java | 7 +- .../server/core/eventbus/EventBusService.java | 23 - .../core/server/JettyHandlerRegister.java | 27 - .../core/server/JettyHandlerRegisterImpl.java | 36 - .../servlet/CamelReceiverRouteHandler.java | 122 ---- .../core/servlet/DataTransferHandler.java | 103 --- .../servlet/DeviceTriggerActionHandler.java | 71 -- .../core/servlet/HttpItemTrapperHandler.java | 42 -- .../zeus/iot/server/core/storage/DAO.java | 2 +- .../iot/server/core/storage/IBatchDAO.java | 4 +- .../iot/server/core/storage/IRecordDAO.java | 2 +- .../iot/server/core/storage/StorageDAO.java | 3 +- .../server/core/storage/StorageModule.java | 3 +- .../server/core/worker/AbstractWorker.java | 2 +- .../core/worker/ItemDataTransferWorker.java | 10 +- .../server/core/worker/TransferWorker.java | 2 +- ...s.zeus.server.library.module.ModuleDefine} | 0 ...zeus.server.library.module.ModuleProvider} | 0 iot-server/server-health-checker/pom.xml | 2 +- .../checker/module/HealthCheckerModule.java | 2 +- .../checker/provider/HealthCheckerConfig.java | 2 +- .../provider/HealthCheckerProvider.java | 2 +- .../checker/provider/HealthQueryService.java | 2 +- ...s.zeus.server.library.module.ModuleDefine} | 0 ...zeus.server.library.module.ModuleProvider} | 0 .../server-library/library-module/pom.xml | 29 - .../module/ApplicationConfiguration.java | 86 --- .../server/library/module/BootstrapFlow.java | 121 ---- .../module/CycleDependencyException.java | 25 - .../module/DuplicateProviderException.java | 30 - .../server/library/module/ModuleConfig.java | 22 - .../library/module/ModuleConfigException.java | 30 - .../server/library/module/ModuleDefine.java | 142 ---- .../library/module/ModuleDefineHolder.java | 26 - .../server/library/module/ModuleManager.java | 83 --- .../module/ModuleNotFoundException.java | 30 - .../ModuleNotFoundRuntimeException.java | 30 - .../server/library/module/ModuleProvider.java | 131 ---- .../library/module/ModuleProviderHolder.java | 24 - .../library/module/ModuleServiceHolder.java | 26 - .../library/module/ModuleStartException.java | 29 - .../module/ProviderNotFoundException.java | 30 - .../iot/server/library/module/Service.java | 27 - .../module/ServiceNotProvidedException.java | 25 - .../server-library/library-server/pom.xml | 38 -- .../iot/server/library/server/Server.java | 34 - .../library/server/ServerException.java | 30 - .../server/library/server/ServerHandler.java | 22 - .../server/jetty/ArgumentsParseException.java | 30 - .../server/jetty/JettyDefaultHandler.java | 35 - .../library/server/jetty/JettyHandler.java | 80 --- .../server/jetty/JettyJsonHandler.java | 87 --- .../library/server/jetty/JettyServer.java | 154 ----- .../server/jetty/JettyServerConfig.java | 46 -- .../server/jetty/JettyServerException.java | 32 - .../server/pool/CustomThreadFactory.java | 45 -- .../server/ssl/AbstractSslContext.java | 102 --- .../server/ssl/HttpDynamicSslContext.java | 67 -- .../library/server/ssl/PrivateKeyUtil.java | 82 --- .../server/library/util/CollectionUtils.java | 62 -- .../server/library/util/HealthChecker.java | 44 -- .../util/MultipleFilesChangeMonitor.java | 264 -------- .../server/library/util/ResourceUtils.java | 65 -- iot-server/server-library/pom.xml | 26 - iot-server/server-localdb/pom.xml | 4 +- .../iot/server/h2/module/LocalH2Module.java | 2 +- .../iot/server/h2/provider/LocalH2Config.java | 8 +- .../server/h2/provider/LocalH2InsertDAO.java | 4 +- .../server/h2/provider/LocalH2Provider.java | 10 +- .../zeus/iot/server/h2/service/InsertDAO.java | 2 +- ...s.zeus.server.library.module.ModuleDefine} | 0 ...zeus.server.library.module.ModuleProvider} | 0 iot-server/server-sender/pom.xml | 2 +- .../sender/module/ZabbixSenderModule.java | 2 +- .../provider/ZabbixSenderModuleConfig.java | 2 +- .../sender/provider/ZabbixSenderProvider.java | 2 +- .../sender/service/ZabbixSenderService.java | 4 +- ...s.zeus.server.library.module.ModuleDefine} | 0 ...zeus.server.library.module.ModuleProvider} | 0 .../conf/ark/bootstrap.properties | 5 + iot-server/server-starter/pom.xml | 58 ++ .../iot/server/starter/IoTServerStartUp.java | 2 + .../server-none-storage/pom.xml | 2 +- .../storage/plugin/none/BatchDaoNoop.java | 4 +- .../plugin/none/NoneStorageProvider.java | 4 +- ...zeus.server.library.module.ModuleProvider} | 0 .../server-tdengine-plugin/pom.xml | 2 +- .../storage/plugin/jdbc/SQLExecutor.java | 2 +- .../jdbc/tdengine/TDEngineBatchDAO.java | 18 +- .../tdengine/TDEngineDatabaseInstaller.java | 8 +- .../jdbc/tdengine/TDEngineStorageConfig.java | 2 +- .../tdengine/TDEngineStorageProvider.java | 5 +- .../jdbc/tdengine/dao/TDEngineRecordDAO.java | 4 +- .../jdbc/tdengine/dao/TDEngineStorageDAO.java | 4 +- ...zeus.server.library.module.ModuleProvider} | 0 .../server-telemetry/telemetry-api/pom.xml | 2 +- .../iot/server/telemetry/TelemetryModule.java | 2 +- .../telemetry/api/HealthCheckMetrics.java | 2 +- .../telemetry/api/MetricsCollector.java | 2 +- .../server/telemetry/api/MetricsCreator.java | 2 +- .../telemetry/none/NoneTelemetryProvider.java | 2 +- ...s.zeus.server.library.module.ModuleDefine} | 0 ...zeus.server.library.module.ModuleProvider} | 0 .../telemetry-prometheus/pom.xml | 4 +- .../prometheus/PrometheusConfig.java | 2 +- .../PrometheusTelemetryProvider.java | 2 +- .../prometheus/httpserver/HttpServer.java | 2 +- ...zeus.server.library.module.ModuleProvider} | 0 iot-server/server-transfer/pom.xml | 82 ++- .../zeus/iot/server/transfer/api/Channel.java | 37 -- .../zeus/iot/server/transfer/api/Filter.java | 14 - .../zeus/iot/server/transfer/api/Message.java | 25 - .../zeus/iot/server/transfer/api/Reader.java | 34 - .../zeus/iot/server/transfer/api/Sink.java | 22 - .../zeus/iot/server/transfer/api/Source.java | 19 - .../zeus/iot/server/transfer/api/Stage.java | 21 - .../zeus/iot/server/transfer/api/Trigger.java | 44 -- .../iot/server/transfer/api/Validator.java | 14 - .../transfer/common/AbstractDaemon.java | 84 --- .../iot/server/transfer/common/Service.java | 28 - .../common/TransferThreadFactory.java | 28 - .../transfer/conf/AbstractConfiguration.java | 247 ------- .../server/transfer/conf/CommonConstants.java | 44 -- .../server/transfer/conf/JobConstants.java | 67 -- .../iot/server/transfer/conf/JobProfile.java | 66 -- .../transfer/conf/TransferConfiguration.java | 104 --- .../transfer/conf/TransferConstants.java | 87 --- .../server/transfer/conf/TriggerProfile.java | 36 - .../server/transfer/core/FileException.java | 8 - .../server/transfer/core/TransferManager.java | 125 ---- .../transfer/core/channel/MemoryChannel.java | 97 --- .../transfer/core/db/BerkeleyDbImp.java | 204 ------ .../zeus/iot/server/transfer/core/db/Db.java | 100 --- .../server/transfer/core/db/JobProfileDb.java | 196 ------ .../transfer/core/db/KeyValueEntity.java | 89 --- .../transfer/core/db/StateSearchKey.java | 15 - .../transfer/core/db/TriggerProfileDb.java | 72 -- .../transfer/core/filter/DateFormatRegex.java | 120 ---- .../server/transfer/core/job/CommandDb.java | 74 --- .../transfer/core/job/CommandEntity.java | 33 - .../iot/server/transfer/core/job/Job.java | 77 --- .../server/transfer/core/job/JobManager.java | 237 ------- .../server/transfer/core/job/JobMetrics.java | 31 - .../server/transfer/core/job/JobWrapper.java | 120 ---- .../transfer/core/message/DefaultMessage.java | 37 -- .../transfer/core/message/EndMessage.java | 23 - .../core/message/PackProxyMessage.java | 131 ---- .../transfer/core/message/ProxyMessage.java | 58 -- .../transfer/core/sink/DataCarrierSink.java | 164 ----- .../transfer/core/source/TextFileSource.java | 57 -- .../core/source/reader/TextFileReader.java | 159 ----- .../core/state/AbstractStateWrapper.java | 80 --- .../iot/server/transfer/core/state/State.java | 19 - .../transfer/core/state/StateCallback.java | 9 - .../iot/server/transfer/core/task/Task.java | 59 -- .../transfer/core/task/TaskManager.java | 235 ------- .../transfer/core/task/TaskMetrics.java | 39 -- .../core/task/TaskPositionManager.java | 156 ----- .../transfer/core/task/TaskWrapper.java | 182 ------ .../core/trigger/DirectoryTrigger.java | 262 -------- .../transfer/core/trigger/PathPattern.java | 178 ----- .../transfer/core/trigger/TriggerManager.java | 241 ------- .../core/validator/PatternValidator.java | 18 - .../core/validator/PrefixValidator.java | 17 - .../transfer/metrics/AgentDynamicMBean.java | 109 --- .../iot/server/transfer/metrics/Metric.java | 46 -- .../transfer/metrics/MetricException.java | 12 - .../transfer/metrics/MetricSnapshot.java | 5 - .../iot/server/transfer/metrics/Metrics.java | 35 - .../transfer/metrics/MetricsRegister.java | 132 ---- .../transfer/metrics/MutableMetric.java | 8 - .../server/transfer/metrics/PluginMetric.java | 36 - .../zeus/iot/server/transfer/metrics/Tag.java | 24 - .../transfer/metrics/counter/Counter.java | 20 - .../transfer/metrics/counter/CounterInt.java | 24 - .../transfer/metrics/counter/CounterLong.java | 27 - .../server/transfer/metrics/gauge/Gauge.java | 32 - .../transfer/metrics/gauge/GaugeInt.java | 40 -- .../transfer/metrics/gauge/GaugeLong.java | 40 -- .../transfer/metrics/meta/MetricMeta.java | 59 -- .../transfer/metrics/meta/MetricsMeta.java | 44 -- .../transfer/module/ServerTransferModule.java | 2 +- .../provider/ServerTransferConfig.java | 2 +- .../provider/ServerTransferProvider.java | 21 +- .../server/transfer/sender/SenderManager.java | 6 +- .../transfer/utils/FileSearchUtils.java | 74 --- .../server/transfer/utils/TransferUtils.java | 348 ---------- ...s.zeus.server.library.module.ModuleDefine} | 0 ...zeus.server.library.module.ModuleProvider} | 0 .../library-util => server-web}/pom.xml | 9 +- .../zmops/zeus/iot/web/config/IoTConfig.java | 30 + .../iot/web/controller/IndexController.java | 16 + pom.xml | 6 - zeus-application-toolkit/pom.xml | 24 - .../toolkit-async/pom.xml | 19 - .../iot/async/callback/DefaultCallback.java | 21 - .../async/callback/DefaultGroupCallback.java | 22 - .../zmops/iot/async/callback/ICallback.java | 47 -- .../iot/async/callback/IGroupCallback.java | 20 - .../iot/async/callback/ITimeoutWorker.java | 20 - .../com/zmops/iot/async/callback/IWorker.java | 30 - .../iot/async/exception/SkippedException.java | 16 - .../com/zmops/iot/async/executor/Async.java | 162 ----- .../iot/async/executor/timer/SystemClock.java | 52 -- .../zmops/iot/async/worker/DependWrapper.java | 59 -- .../zmops/iot/async/worker/ResultState.java | 12 - .../zmops/iot/async/worker/WorkResult.java | 63 -- .../iot/async/wrapper/WorkerWrapper.java | 618 ------------------ .../toolkit-eventbus/pom.xml | 19 - zeus-starter/pom.xml | 5 - .../src/main/resources/application.yaml | 2 +- zeus-webapp/pom.xml | 2 +- .../web/device/service/DeviceLogService.java | 6 +- .../iot/web/device/service/DeviceService.java | 6 +- .../service/work/DeviceEventLogWorker.java | 4 +- .../service/work/DeviceServiceLogWorker.java | 4 +- .../service/work/SaveAttributeWorker.java | 5 +- .../service/work/SaveDeviceGrpWorker.java | 5 +- .../device/service/work/SaveDeviceWorker.java | 4 +- .../device/service/work/SaveOtherWorker.java | 5 +- .../device/service/work/SaveTagWorker.java | 5 +- .../service/work/SaveZbxHostWorker.java | 5 +- .../device/service/work/ScenesLogWorker.java | 4 +- .../service/work/UpdateAttrZbxIdWorker.java | 5 +- .../service/work/UpdateDeviceZbxIdWorker.java | 4 +- .../service/work/UpdateZbxTagWorker.java | 4 +- .../pgEvent/service/ServiceEventProcess.java | 4 +- .../ProductEventTriggerController.java | 4 +- .../service/ProductAttributeEventService.java | 5 +- .../product/service/ProductModelService.java | 4 +- .../product/service/ProductSvcService.java | 4 +- .../work/AsyncAttrEventZbxIdWorker.java | 4 +- .../service/work/AsyncAttrZbxIdWorker.java | 4 +- .../work/SaveProdAttrEventTriggerWorker.java | 4 +- .../service/work/SaveProdAttrEventWorker.java | 4 +- .../service/work/SaveProdAttrWorker.java | 4 +- .../work/SaveProdStatusTriggerWorker.java | 4 +- .../service/work/SaveProdSvcWorker.java | 4 +- .../work/SaveProductEventTriggerWorker.java | 4 +- .../work/UpdateAttributeEventWorker.java | 4 +- .../service/work/UpdateAttributeWorker.java | 4 +- .../service/work/UpdateProdSvcWorker.java | 5 +- .../work/UpdateProductEventTriggerWorker.java | 4 +- .../com/zmops/iot/web/task/dto/TaskDto.java | 4 +- 332 files changed, 485 insertions(+), 13097 deletions(-) delete mode 100644 iot-common/iot-datacarrier/pom.xml delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/DataCarrier.java delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/EnvUtil.java delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/ArrayBlockingQueueBuffer.java delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Buffer.java delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/BufferStrategy.java delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Channels.java delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/QueueBuffer.java delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/common/AtomicRangeInteger.java delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/BulkConsumePool.java delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumeDriver.java delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerCannotBeCreatedException.java delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerPool.java delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerPoolFactory.java delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerThread.java delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/IConsumer.java delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/IDriver.java delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/MultipleChannelsConsumer.java delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/IDataPartitioner.java delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/ProducerThreadPartitioner.java delete mode 100644 iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/SimpleRollingPartitioner.java delete mode 100644 iot-common/iot-eventbus/pom.xml delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/constant/EventConstant.java delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/Event.java delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventController.java delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerImpl.java delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventType.java delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/ThreadPoolFactory.java delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/constant/ThreadConstant.java delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadCustomization.java delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadParameter.java delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadQueueType.java delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadRejectedPolicyType.java delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/AbortPolicyWithReport.java delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/BlockingPolicyWithReport.java delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/CallerRunsPolicyWithReport.java delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/DiscardedPolicyWithReport.java delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/RejectedPolicyWithReport.java delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/RejectedRunnable.java delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/NetUtil.java delete mode 100644 iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/StringUtil.java delete mode 100644 iot-common/iot-util/pom.xml delete mode 100644 iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/PlaceholderConfigurerSupport.java delete mode 100644 iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/PropertyPlaceholderHelper.java delete mode 100644 iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/StringUtil.java delete mode 100644 iot-common/pom.xml delete mode 100644 iot-server/server-action/pom.xml delete mode 100644 iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/ActionRouteIdentifier.java delete mode 100644 iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/HelloWorldAction.java delete mode 100644 iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/bean/ActionParam.java create mode 100644 iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/PgEventRouteBuilder.java rename iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/{IOTDeviceValue.java => IoTDeviceValue.java} (93%) rename iot-server/server-camel-receiver/src/main/resources/META-INF/services/{com.zmops.zeus.iot.server.library.module.ModuleDefine => com.zmops.zeus.server.library.module.ModuleDefine} (100%) rename iot-server/server-camel-receiver/src/main/resources/META-INF/services/{com.zmops.zeus.iot.server.library.module.ModuleProvider => com.zmops.zeus.server.library.module.ModuleProvider} (100%) rename iot-server/{server-library/library-client => server-client}/pom.xml (87%) rename iot-server/{server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library => server-client/src/main/java/com/zmops/zeus/iot/server}/client/Client.java (94%) rename iot-server/{server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library => server-client/src/main/java/com/zmops/zeus/iot/server}/client/ClientException.java (95%) rename iot-server/{server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library => server-client/src/main/java/com/zmops/zeus/iot/server}/client/healthcheck/DelegatedHealthChecker.java (92%) rename iot-server/{server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library => server-client/src/main/java/com/zmops/zeus/iot/server}/client/healthcheck/HealthCheckable.java (90%) rename iot-server/{server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library => server-client/src/main/java/com/zmops/zeus/iot/server}/client/jdbc/JDBCClientException.java (95%) rename iot-server/{server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library => server-client/src/main/java/com/zmops/zeus/iot/server}/client/jdbc/hikaricp/JDBCHikariCPClient.java (87%) rename iot-server/{server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library => server-client/src/main/java/com/zmops/zeus/iot/server}/client/request/InsertRequest.java (93%) rename iot-server/{server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library => server-client/src/main/java/com/zmops/zeus/iot/server}/client/request/PrepareRequest.java (93%) delete mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/eventbus/EventBusService.java delete mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/server/JettyHandlerRegister.java delete mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/server/JettyHandlerRegisterImpl.java delete mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/CamelReceiverRouteHandler.java delete mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java delete mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java delete mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/HttpItemTrapperHandler.java rename iot-server/server-core/src/main/resources/META-INF/services/{com.zmops.zeus.iot.server.library.module.ModuleDefine => com.zmops.zeus.server.library.module.ModuleDefine} (100%) rename iot-server/server-core/src/main/resources/META-INF/services/{com.zmops.zeus.iot.server.library.module.ModuleProvider => com.zmops.zeus.server.library.module.ModuleProvider} (100%) rename iot-server/server-health-checker/src/main/resources/META-INF/services/{com.zmops.zeus.iot.server.library.module.ModuleDefine => com.zmops.zeus.server.library.module.ModuleDefine} (100%) rename iot-server/server-health-checker/src/main/resources/META-INF/services/{com.zmops.zeus.iot.server.library.module.ModuleProvider => com.zmops.zeus.server.library.module.ModuleProvider} (100%) delete mode 100644 iot-server/server-library/library-module/pom.xml delete mode 100644 iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ApplicationConfiguration.java delete mode 100644 iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/BootstrapFlow.java delete mode 100644 iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/CycleDependencyException.java delete mode 100644 iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/DuplicateProviderException.java delete mode 100644 iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleConfig.java delete mode 100644 iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleConfigException.java delete mode 100644 iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefine.java delete mode 100644 iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefineHolder.java delete mode 100644 iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleManager.java delete mode 100644 iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleNotFoundException.java delete mode 100644 iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleNotFoundRuntimeException.java delete mode 100644 iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleProvider.java delete mode 100644 iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleProviderHolder.java delete mode 100644 iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleServiceHolder.java delete mode 100644 iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleStartException.java delete mode 100644 iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ProviderNotFoundException.java delete mode 100644 iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/Service.java delete mode 100644 iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ServiceNotProvidedException.java delete mode 100644 iot-server/server-library/library-server/pom.xml delete mode 100644 iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/Server.java delete mode 100644 iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ServerException.java delete mode 100644 iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ServerHandler.java delete mode 100644 iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/ArgumentsParseException.java delete mode 100644 iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyDefaultHandler.java delete mode 100644 iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyHandler.java delete mode 100644 iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyJsonHandler.java delete mode 100644 iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServer.java delete mode 100644 iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServerConfig.java delete mode 100644 iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServerException.java delete mode 100644 iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/pool/CustomThreadFactory.java delete mode 100644 iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/AbstractSslContext.java delete mode 100644 iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/HttpDynamicSslContext.java delete mode 100644 iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/PrivateKeyUtil.java delete mode 100644 iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/CollectionUtils.java delete mode 100644 iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/HealthChecker.java delete mode 100644 iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/MultipleFilesChangeMonitor.java delete mode 100644 iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/ResourceUtils.java delete mode 100644 iot-server/server-library/pom.xml rename iot-server/server-localdb/src/main/resources/META-INF/services/{com.zmops.zeus.iot.server.library.module.ModuleDefine => com.zmops.zeus.server.library.module.ModuleDefine} (100%) rename iot-server/server-localdb/src/main/resources/META-INF/services/{com.zmops.zeus.iot.server.library.module.ModuleProvider => com.zmops.zeus.server.library.module.ModuleProvider} (100%) rename iot-server/server-sender/src/main/resources/META-INF/services/{com.zmops.zeus.iot.server.library.module.ModuleDefine => com.zmops.zeus.server.library.module.ModuleDefine} (100%) rename iot-server/server-sender/src/main/resources/META-INF/services/{com.zmops.zeus.iot.server.library.module.ModuleProvider => com.zmops.zeus.server.library.module.ModuleProvider} (100%) create mode 100644 iot-server/server-starter/conf/ark/bootstrap.properties rename iot-server/server-storage-plugin/server-none-storage/src/main/resources/META-INF/services/{com.zmops.zeus.iot.server.library.module.ModuleProvider => com.zmops.zeus.server.library.module.ModuleProvider} (100%) rename iot-server/server-storage-plugin/server-tdengine-plugin/src/main/resources/META-INF/services/{com.zmops.zeus.iot.server.library.module.ModuleProvider => com.zmops.zeus.server.library.module.ModuleProvider} (100%) rename iot-server/server-telemetry/telemetry-api/src/main/resources/META-INF/services/{com.zmops.zeus.iot.server.library.module.ModuleDefine => com.zmops.zeus.server.library.module.ModuleDefine} (100%) rename iot-server/server-telemetry/telemetry-api/src/main/resources/META-INF/services/{com.zmops.zeus.iot.server.library.module.ModuleProvider => com.zmops.zeus.server.library.module.ModuleProvider} (100%) rename iot-server/server-telemetry/telemetry-prometheus/src/main/resources/META-INF/services/{com.zmops.zeus.iot.server.library.module.ModuleProvider => com.zmops.zeus.server.library.module.ModuleProvider} (100%) delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Channel.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Filter.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Message.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Reader.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Sink.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Source.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Stage.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Trigger.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Validator.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/AbstractDaemon.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/Service.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/TransferThreadFactory.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobProfile.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConfiguration.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TriggerProfile.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/FileException.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/TransferManager.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/Db.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/KeyValueEntity.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/StateSearchKey.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/TriggerProfileDb.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandEntity.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/DefaultMessage.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/EndMessage.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/PackProxyMessage.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/DataCarrierSink.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/AbstractStateWrapper.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/State.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateCallback.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/PathPattern.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PatternValidator.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PrefixValidator.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/AgentDynamicMBean.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Metric.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricException.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricSnapshot.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Metrics.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricsRegister.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MutableMetric.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/PluginMetric.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Tag.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/Counter.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/CounterInt.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/CounterLong.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/Gauge.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/GaugeInt.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/GaugeLong.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricMeta.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricsMeta.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/FileSearchUtils.java delete mode 100644 iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/TransferUtils.java rename iot-server/server-transfer/src/main/resources/META-INF/services/{com.zmops.zeus.iot.server.library.module.ModuleDefine => com.zmops.zeus.server.library.module.ModuleDefine} (100%) rename iot-server/server-transfer/src/main/resources/META-INF/services/{com.zmops.zeus.iot.server.library.module.ModuleProvider => com.zmops.zeus.server.library.module.ModuleProvider} (100%) rename iot-server/{server-library/library-util => server-web}/pom.xml (74%) create mode 100644 iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/config/IoTConfig.java create mode 100644 iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/IndexController.java delete mode 100644 zeus-application-toolkit/pom.xml delete mode 100644 zeus-application-toolkit/toolkit-async/pom.xml delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultCallback.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultGroupCallback.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ICallback.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IGroupCallback.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ITimeoutWorker.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IWorker.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/SkippedException.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/Async.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/timer/SystemClock.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/DependWrapper.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/ResultState.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/WorkResult.java delete mode 100644 zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapper.java delete mode 100644 zeus-application-toolkit/toolkit-eventbus/pom.xml diff --git a/iot-common/iot-datacarrier/pom.xml b/iot-common/iot-datacarrier/pom.xml deleted file mode 100644 index ebc60bb8..00000000 --- a/iot-common/iot-datacarrier/pom.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - 4.0.0 - - - iot-common - com.zmops - 1.0-beta - - - iot-datacarrier - 1.0-beta - - iot-datacarrier - - - 8 - 8 - - diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/DataCarrier.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/DataCarrier.java deleted file mode 100644 index f072a2d9..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/DataCarrier.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier; - - -import com.zmops.zeus.iot.server.datacarrier.buffer.BufferStrategy; -import com.zmops.zeus.iot.server.datacarrier.buffer.Channels; -import com.zmops.zeus.iot.server.datacarrier.consumer.ConsumeDriver; -import com.zmops.zeus.iot.server.datacarrier.consumer.ConsumerPool; -import com.zmops.zeus.iot.server.datacarrier.consumer.IConsumer; -import com.zmops.zeus.iot.server.datacarrier.consumer.IDriver; -import com.zmops.zeus.iot.server.datacarrier.partition.IDataPartitioner; -import com.zmops.zeus.iot.server.datacarrier.partition.SimpleRollingPartitioner; - -/** - * DataCarrier main class. use this instance to set Producer/Consumer Model. - */ -public class DataCarrier { - private final Channels channels; - private IDriver driver; - private final String name; - - public DataCarrier(int channelSize, int bufferSize) { - this("DEFAULT", channelSize, bufferSize); - } - - public DataCarrier(String name, int channelSize, int bufferSize) { - this(name, name, channelSize, bufferSize); - } - - public DataCarrier(String name, String envPrefix, int channelSize, int bufferSize) { - this(name, envPrefix, channelSize, bufferSize, BufferStrategy.BLOCKING); - } - - public DataCarrier(String name, String envPrefix, int channelSize, int bufferSize, BufferStrategy strategy) { - this.name = name; - bufferSize = EnvUtil.getInt(envPrefix + "_BUFFER_SIZE", bufferSize); - channelSize = EnvUtil.getInt(envPrefix + "_CHANNEL_SIZE", channelSize); - channels = new Channels<>(channelSize, bufferSize, new SimpleRollingPartitioner(), strategy); - } - - public DataCarrier(int channelSize, int bufferSize, BufferStrategy strategy) { - this("DEFAULT", "DEFAULT", channelSize, bufferSize, strategy); - } - - /** - * set a new IDataPartitioner. It will cover the current one or default one.(Default is {@link - * SimpleRollingPartitioner} - * - * @param dataPartitioner to partition data into different channel by some rules. - * @return DataCarrier instance for chain - */ - public DataCarrier setPartitioner(IDataPartitioner dataPartitioner) { - this.channels.setPartitioner(dataPartitioner); - return this; - } - - /** - * produce data to buffer, using the given {@link BufferStrategy}. - * - * @return false means produce data failure. The data will not be consumed. - */ - public boolean produce(T data) { - if (driver != null) { - if (!driver.isRunning(channels)) { - return false; - } - } - - return this.channels.save(data); - } - - /** - * set consumeDriver to this Carrier. consumer begin to run when {@link DataCarrier#produce} begin to work. - * - * @param consumerClass class of consumer - * @param num number of consumer threads - */ - public DataCarrier consume(Class> consumerClass, int num, long consumeCycle) { - if (driver != null) { - driver.close(channels); - } - driver = new ConsumeDriver(this.name, this.channels, consumerClass, num, consumeCycle); - driver.begin(channels); - return this; - } - - /** - * set consumeDriver to this Carrier. consumer begin to run when {@link DataCarrier#produce} begin to work with 20 - * millis consume cycle. - * - * @param consumerClass class of consumer - * @param num number of consumer threads - */ - public DataCarrier consume(Class> consumerClass, int num) { - return this.consume(consumerClass, num, 20); - } - - /** - * set consumeDriver to this Carrier. consumer begin to run when {@link DataCarrier#produce} begin to work. - * - * @param consumer single instance of consumer, all consumer threads will all use this instance. - * @param num number of consumer threads - */ - public DataCarrier consume(IConsumer consumer, int num, long consumeCycle) { - if (driver != null) { - driver.close(channels); - } - driver = new ConsumeDriver(this.name, this.channels, consumer, num, consumeCycle); - driver.begin(channels); - return this; - } - - /** - * set consumeDriver to this Carrier. consumer begin to run when {@link DataCarrier#produce} begin to work with 20 - * millis consume cycle. - * - * @param consumer single instance of consumer, all consumer threads will all use this instance. - * @param num number of consumer threads - */ - public DataCarrier consume(IConsumer consumer, int num) { - return this.consume(consumer, num, 20); - } - - /** - * Set a consumer pool to manage the channels of this DataCarrier. Then consumerPool could use its own consuming - * model to adjust the consumer thread and throughput. - */ - public DataCarrier consume(ConsumerPool consumerPool, IConsumer consumer) { - driver = consumerPool; - consumerPool.add(this.name, channels, consumer); - driver.begin(channels); - return this; - } - - /** - * shutdown all consumer threads, if consumer threads are running. Notice {@link BufferStrategy}: if {@link - * BufferStrategy} == {@link BufferStrategy#BLOCKING}, shutdown consumeDriver maybe cause blocking when producing. - * Better way to change consumeDriver are use {@link DataCarrier#consume} - */ - public void shutdownConsumers() { - if (driver != null) { - driver.close(channels); - } - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/EnvUtil.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/EnvUtil.java deleted file mode 100644 index ac9ca760..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/EnvUtil.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier; - -/** - * Read value from system env. - */ -public class EnvUtil { - public static int getInt(String envName, int defaultValue) { - int value = defaultValue; - String envValue = System.getenv(envName); - if (envValue != null) { - try { - value = Integer.parseInt(envValue); - } catch (NumberFormatException e) { - - } - } - return value; - } - - public static long getLong(String envName, long defaultValue) { - long value = defaultValue; - String envValue = System.getenv(envName); - if (envValue != null) { - try { - value = Long.parseLong(envValue); - } catch (NumberFormatException e) { - - } - } - return value; - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/ArrayBlockingQueueBuffer.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/ArrayBlockingQueueBuffer.java deleted file mode 100644 index 08c1db7d..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/ArrayBlockingQueueBuffer.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier.buffer; - -import java.util.List; -import java.util.concurrent.ArrayBlockingQueue; - -/** - * The buffer implementation based on JDK ArrayBlockingQueue. - *

- * This implementation has better performance in server side. We are still trying to research whether this is suitable - * for agent side, which is more sensitive about blocks. - */ -public class ArrayBlockingQueueBuffer implements QueueBuffer { - private BufferStrategy strategy; - private ArrayBlockingQueue queue; - private int bufferSize; - - ArrayBlockingQueueBuffer(int bufferSize, BufferStrategy strategy) { - this.strategy = strategy; - this.queue = new ArrayBlockingQueue(bufferSize); - this.bufferSize = bufferSize; - } - - @Override - public boolean save(T data) { - //only BufferStrategy.BLOCKING - try { - queue.put(data); - } catch (InterruptedException e) { - // Ignore the error - return false; - } - return true; - } - - @Override - public void setStrategy(BufferStrategy strategy) { - this.strategy = strategy; - } - - @Override - public void obtain(List consumeList) { - queue.drainTo(consumeList); - } - - @Override - public int getBufferSize() { - return bufferSize; - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Buffer.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Buffer.java deleted file mode 100644 index 64490321..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Buffer.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier.buffer; - - -import com.zmops.zeus.iot.server.datacarrier.common.AtomicRangeInteger; - -import java.util.List; - -/** - * Self implementation ring queue. - */ -public class Buffer implements QueueBuffer { - private final Object[] buffer; - private BufferStrategy strategy; - private final AtomicRangeInteger index; - - Buffer(int bufferSize, BufferStrategy strategy) { - buffer = new Object[bufferSize]; - this.strategy = strategy; - index = new AtomicRangeInteger(0, bufferSize); - } - - @Override - public void setStrategy(BufferStrategy strategy) { - this.strategy = strategy; - } - - @Override - public boolean save(T data) { - int i = index.getAndIncrement(); - if (buffer[i] != null) { - if (strategy == BufferStrategy.IF_POSSIBLE) { - return false; - } - } - buffer[i] = data; - return true; - } - - @Override - public int getBufferSize() { - return buffer.length; - } - - @Override - public void obtain(List consumeList) { - this.obtain(consumeList, 0, buffer.length); - } - - void obtain(List consumeList, int start, int end) { - for (int i = start; i < end; i++) { - if (buffer[i] != null) { - consumeList.add((T) buffer[i]); - buffer[i] = null; - } - } - } - -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/BufferStrategy.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/BufferStrategy.java deleted file mode 100644 index 37b775f4..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/BufferStrategy.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier.buffer; - -public enum BufferStrategy { - BLOCKING, IF_POSSIBLE -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Channels.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Channels.java deleted file mode 100644 index 72850cca..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Channels.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier.buffer; - - -import com.zmops.zeus.iot.server.datacarrier.partition.IDataPartitioner; - -/** - * Channels of Buffer It contains all buffer data which belongs to this channel. It supports several strategy when - * buffer is full. The Default is BLOCKING

Created by wusheng on 2016/10/25. - */ -public class Channels { - private final QueueBuffer[] bufferChannels; - private IDataPartitioner dataPartitioner; - private final BufferStrategy strategy; - private final long size; - - public Channels(int channelSize, int bufferSize, IDataPartitioner partitioner, BufferStrategy strategy) { - this.dataPartitioner = partitioner; - this.strategy = strategy; - bufferChannels = new QueueBuffer[channelSize]; - for (int i = 0; i < channelSize; i++) { - if (BufferStrategy.BLOCKING.equals(strategy)) { - bufferChannels[i] = new ArrayBlockingQueueBuffer<>(bufferSize, strategy); - } else { - bufferChannels[i] = new Buffer<>(bufferSize, strategy); - } - } - // noinspection PointlessArithmeticExpression - size = 1L * channelSize * bufferSize; // it's not pointless, it prevents numeric overflow before assigning an integer to a long - } - - public boolean save(T data) { - int index = dataPartitioner.partition(bufferChannels.length, data); - int retryCountDown = 1; - if (BufferStrategy.IF_POSSIBLE.equals(strategy)) { - int maxRetryCount = dataPartitioner.maxRetryCount(); - if (maxRetryCount > 1) { - retryCountDown = maxRetryCount; - } - } - for (; retryCountDown > 0; retryCountDown--) { - if (bufferChannels[index].save(data)) { - return true; - } - } - return false; - } - - public void setPartitioner(IDataPartitioner dataPartitioner) { - this.dataPartitioner = dataPartitioner; - } - - /** - * override the strategy at runtime. Notice, this will override several channels one by one. So, when running - * setStrategy, each channel may use different BufferStrategy - */ - public void setStrategy(BufferStrategy strategy) { - for (QueueBuffer buffer : bufferChannels) { - buffer.setStrategy(strategy); - } - } - - /** - * get channelSize - */ - public int getChannelSize() { - return this.bufferChannels.length; - } - - public long size() { - return size; - } - - public QueueBuffer getBuffer(int index) { - return this.bufferChannels[index]; - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/QueueBuffer.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/QueueBuffer.java deleted file mode 100644 index 25d944a8..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/QueueBuffer.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier.buffer; - -import java.util.List; - -/** - * Queue buffer interface. - */ -public interface QueueBuffer { - /** - * Save data into the queue; - * - * @param data to add. - * @return true if saved - */ - boolean save(T data); - - /** - * Set different strategy when queue is full. - */ - void setStrategy(BufferStrategy strategy); - - /** - * Obtain the existing data from the queue - */ - void obtain(List consumeList); - - int getBufferSize(); -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/common/AtomicRangeInteger.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/common/AtomicRangeInteger.java deleted file mode 100644 index b47f8726..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/common/AtomicRangeInteger.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier.common; - -import java.io.Serializable; -import java.util.concurrent.atomic.AtomicIntegerArray; - -public class AtomicRangeInteger extends Number implements Serializable { - private static final long serialVersionUID = -4099792402691141643L; - private AtomicIntegerArray values; - - private static final int VALUE_OFFSET = 15; - - private int startValue; - private int endValue; - - public AtomicRangeInteger(int startValue, int maxValue) { - this.values = new AtomicIntegerArray(31); - this.values.set(VALUE_OFFSET, startValue); - this.startValue = startValue; - this.endValue = maxValue - 1; - } - - public final int getAndIncrement() { - int next; - do { - next = this.values.incrementAndGet(VALUE_OFFSET); - if (next > endValue && this.values.compareAndSet(VALUE_OFFSET, next, startValue)) { - return endValue; - } - } - while (next > endValue); - - return next - 1; - } - - public final int get() { - return this.values.get(VALUE_OFFSET); - } - - @Override - public int intValue() { - return this.values.get(VALUE_OFFSET); - } - - @Override - public long longValue() { - return this.values.get(VALUE_OFFSET); - } - - @Override - public float floatValue() { - return this.values.get(VALUE_OFFSET); - } - - @Override - public double doubleValue() { - return this.values.get(VALUE_OFFSET); - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/BulkConsumePool.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/BulkConsumePool.java deleted file mode 100644 index 6aa8e2f8..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/BulkConsumePool.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier.consumer; - - -import com.zmops.zeus.iot.server.datacarrier.EnvUtil; -import com.zmops.zeus.iot.server.datacarrier.buffer.Channels; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; - -/** - * BulkConsumePool works for consuming data from multiple channels(DataCarrier instances), with multiple {@link - * MultipleChannelsConsumer}s. - *

- * In typical case, the number of {@link MultipleChannelsConsumer} should be less than the number of channels. - */ -public class BulkConsumePool implements ConsumerPool { - private List allConsumers; - private volatile boolean isStarted = false; - - public BulkConsumePool(String name, int size, long consumeCycle) { - size = EnvUtil.getInt(name + "_THREAD", size); - allConsumers = new ArrayList(size); - for (int i = 0; i < size; i++) { - MultipleChannelsConsumer multipleChannelsConsumer = new MultipleChannelsConsumer("DataCarrier." + name + ".BulkConsumePool." + i + ".Thread", consumeCycle); - multipleChannelsConsumer.setDaemon(true); - allConsumers.add(multipleChannelsConsumer); - } - } - - @Override - synchronized public void add(String name, Channels channels, IConsumer consumer) { - MultipleChannelsConsumer multipleChannelsConsumer = getLowestPayload(); - multipleChannelsConsumer.addNewTarget(channels, consumer); - } - - /** - * Get the lowest payload consumer thread based on current allocate status. - * - * @return the lowest consumer. - */ - private MultipleChannelsConsumer getLowestPayload() { - MultipleChannelsConsumer winner = allConsumers.get(0); - for (int i = 1; i < allConsumers.size(); i++) { - MultipleChannelsConsumer option = allConsumers.get(i); - if (option.size() < winner.size()) { - winner = option; - } - } - return winner; - } - - /** - * - */ - @Override - public boolean isRunning(Channels channels) { - return isStarted; - } - - @Override - public void close(Channels channels) { - for (MultipleChannelsConsumer consumer : allConsumers) { - consumer.shutdown(); - } - } - - @Override - public void begin(Channels channels) { - if (isStarted) { - return; - } - for (MultipleChannelsConsumer consumer : allConsumers) { - consumer.start(); - } - isStarted = true; - } - - /** - * The creator for {@link BulkConsumePool}. - */ - public static class Creator implements Callable { - private String name; - private int size; - private long consumeCycle; - - public Creator(String name, int poolSize, long consumeCycle) { - this.name = name; - this.size = poolSize; - this.consumeCycle = consumeCycle; - } - - @Override - public ConsumerPool call() { - return new BulkConsumePool(name, size, consumeCycle); - } - - public static int recommendMaxSize() { - return Runtime.getRuntime().availableProcessors() * 2; - } - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumeDriver.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumeDriver.java deleted file mode 100644 index 11153a14..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumeDriver.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier.consumer; - - -import com.zmops.zeus.iot.server.datacarrier.buffer.Channels; - -import java.lang.reflect.InvocationTargetException; -import java.util.concurrent.locks.ReentrantLock; - -/** - * Pool of consumers

Created by wusheng on 2016/10/25. - */ -public class ConsumeDriver implements IDriver { - private boolean running; - private ConsumerThread[] consumerThreads; - private Channels channels; - private ReentrantLock lock; - - public ConsumeDriver(String name, Channels channels, Class> consumerClass, int num, - long consumeCycle) { - this(channels, num); - for (int i = 0; i < num; i++) { - consumerThreads[i] = new ConsumerThread("DataCarrier." + name + ".Consumer." + i + ".Thread", getNewConsumerInstance(consumerClass), consumeCycle); - consumerThreads[i].setDaemon(true); - } - } - - public ConsumeDriver(String name, Channels channels, IConsumer prototype, int num, long consumeCycle) { - this(channels, num); - prototype.init(); - for (int i = 0; i < num; i++) { - consumerThreads[i] = new ConsumerThread("DataCarrier." + name + ".Consumer." + i + ".Thread", prototype, consumeCycle); - consumerThreads[i].setDaemon(true); - } - - } - - private ConsumeDriver(Channels channels, int num) { - running = false; - this.channels = channels; - consumerThreads = new ConsumerThread[num]; - lock = new ReentrantLock(); - } - - private IConsumer getNewConsumerInstance(Class> consumerClass) { - try { - IConsumer inst = consumerClass.getDeclaredConstructor().newInstance(); - inst.init(); - return inst; - } catch (InstantiationException e) { - throw new ConsumerCannotBeCreatedException(e); - } catch (IllegalAccessException e) { - throw new ConsumerCannotBeCreatedException(e); - } catch (NoSuchMethodException e) { - throw new ConsumerCannotBeCreatedException(e); - } catch (InvocationTargetException e) { - throw new ConsumerCannotBeCreatedException(e); - } - } - - @Override - public void begin(Channels channels) { - if (running) { - return; - } - lock.lock(); - try { - this.allocateBuffer2Thread(); - for (ConsumerThread consumerThread : consumerThreads) { - consumerThread.start(); - } - running = true; - } finally { - lock.unlock(); - } - } - - @Override - public boolean isRunning(Channels channels) { - return running; - } - - private void allocateBuffer2Thread() { - int channelSize = this.channels.getChannelSize(); - /** - * if consumerThreads.length < channelSize - * each consumer will process several channels. - * - * if consumerThreads.length == channelSize - * each consumer will process one channel. - * - * if consumerThreads.length > channelSize - * there will be some threads do nothing. - */ - for (int channelIndex = 0; channelIndex < channelSize; channelIndex++) { - int consumerIndex = channelIndex % consumerThreads.length; - consumerThreads[consumerIndex].addDataSource(channels.getBuffer(channelIndex)); - } - - } - - @Override - public void close(Channels channels) { - lock.lock(); - try { - this.running = false; - for (ConsumerThread consumerThread : consumerThreads) { - consumerThread.shutdown(); - } - } finally { - lock.unlock(); - } - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerCannotBeCreatedException.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerCannotBeCreatedException.java deleted file mode 100644 index 726feec2..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerCannotBeCreatedException.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier.consumer; - -public class ConsumerCannotBeCreatedException extends RuntimeException { - ConsumerCannotBeCreatedException(Throwable t) { - super(t); - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerPool.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerPool.java deleted file mode 100644 index bbeb4b08..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerPool.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier.consumer; - - -import com.zmops.zeus.iot.server.datacarrier.DataCarrier; -import com.zmops.zeus.iot.server.datacarrier.buffer.Channels; - -/** - * The Consumer pool could support data consumer from multiple {@link DataCarrier}s, by using different consume thread - * management models. - */ -public interface ConsumerPool extends IDriver { - void add(String name, Channels channels, IConsumer consumer); -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerPoolFactory.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerPoolFactory.java deleted file mode 100644 index af114378..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerPoolFactory.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier.consumer; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.Callable; - -/** - * Consumer Pool Factory provides global management for all Consumer Pool. - */ -public enum ConsumerPoolFactory { - INSTANCE; - - private final Map pools; - - ConsumerPoolFactory() { - pools = new HashMap<>(); - } - - public synchronized boolean createIfAbsent(String poolName, Callable creator) throws Exception { - if (pools.containsKey(poolName)) { - return false; - } else { - pools.put(poolName, creator.call()); - return true; - } - } - - public ConsumerPool get(String poolName) { - return pools.get(poolName); - } - -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerThread.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerThread.java deleted file mode 100644 index d18d44d6..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerThread.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier.consumer; - - -import com.zmops.zeus.iot.server.datacarrier.buffer.Buffer; -import com.zmops.zeus.iot.server.datacarrier.buffer.QueueBuffer; - -import java.util.ArrayList; -import java.util.List; - -public class ConsumerThread extends Thread { - private volatile boolean running; - private IConsumer consumer; - private List dataSources; - private long consumeCycle; - - ConsumerThread(String threadName, IConsumer consumer, long consumeCycle) { - super(threadName); - this.consumer = consumer; - running = false; - dataSources = new ArrayList(1); - this.consumeCycle = consumeCycle; - } - - /** - * add whole buffer to consume - */ - void addDataSource(QueueBuffer sourceBuffer) { - this.dataSources.add(new DataSource(sourceBuffer)); - } - - @Override - public void run() { - running = true; - - final List consumeList = new ArrayList(1500); - while (running) { - if (!consume(consumeList)) { - try { - Thread.sleep(consumeCycle); - } catch (InterruptedException e) { - } - } - } - - // consumer thread is going to stop - // consume the last time - consume(consumeList); - - consumer.onExit(); - } - - private boolean consume(List consumeList) { - for (DataSource dataSource : dataSources) { - dataSource.obtain(consumeList); - } - - if (!consumeList.isEmpty()) { - try { - consumer.consume(consumeList); - } catch (Throwable t) { - consumer.onError(consumeList, t); - } finally { - consumeList.clear(); - } - return true; - } - return false; - } - - void shutdown() { - running = false; - } - - /** - * DataSource is a refer to {@link Buffer}. - */ - class DataSource { - private QueueBuffer sourceBuffer; - - DataSource(QueueBuffer sourceBuffer) { - this.sourceBuffer = sourceBuffer; - } - - void obtain(List consumeList) { - sourceBuffer.obtain(consumeList); - } - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/IConsumer.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/IConsumer.java deleted file mode 100644 index 964edbf8..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/IConsumer.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier.consumer; - -import java.util.List; - -public interface IConsumer { - void init(); - - void consume(List data); - - void onError(List data, Throwable t); - - void onExit(); -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/IDriver.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/IDriver.java deleted file mode 100644 index ced1c6e0..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/IDriver.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier.consumer; - - -import com.zmops.zeus.iot.server.datacarrier.buffer.Channels; - -/** - * The driver of consumer. - */ -public interface IDriver { - boolean isRunning(Channels channels); - - void close(Channels channels); - - void begin(Channels channels); -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/MultipleChannelsConsumer.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/MultipleChannelsConsumer.java deleted file mode 100644 index 089da23c..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/MultipleChannelsConsumer.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier.consumer; - - -import com.zmops.zeus.iot.server.datacarrier.buffer.Channels; -import com.zmops.zeus.iot.server.datacarrier.buffer.QueueBuffer; - -import java.util.ArrayList; -import java.util.List; - -/** - * MultipleChannelsConsumer represent a single consumer thread, but support multiple channels with their {@link - * IConsumer}s - */ -public class MultipleChannelsConsumer extends Thread { - private volatile boolean running; - private volatile ArrayList consumeTargets; - @SuppressWarnings("NonAtomicVolatileUpdate") - private volatile long size; - private final long consumeCycle; - - public MultipleChannelsConsumer(String threadName, long consumeCycle) { - super(threadName); - this.consumeTargets = new ArrayList(); - this.consumeCycle = consumeCycle; - } - - @Override - public void run() { - running = true; - - final List consumeList = new ArrayList(2000); - while (running) { - boolean hasData = false; - for (Group target : consumeTargets) { - boolean consume = consume(target, consumeList); - hasData = hasData || consume; - } - - if (!hasData) { - try { - Thread.sleep(consumeCycle); - } catch (InterruptedException e) { - } - } - } - - // consumer thread is going to stop - // consume the last time - for (Group target : consumeTargets) { - consume(target, consumeList); - - target.consumer.onExit(); - } - } - - private boolean consume(Group target, List consumeList) { - for (int i = 0; i < target.channels.getChannelSize(); i++) { - QueueBuffer buffer = target.channels.getBuffer(i); - buffer.obtain(consumeList); - } - - if (!consumeList.isEmpty()) { - try { - target.consumer.consume(consumeList); - } catch (Throwable t) { - target.consumer.onError(consumeList, t); - } finally { - consumeList.clear(); - } - return true; - } - return false; - } - - /** - * Add a new target channels. - */ - public void addNewTarget(Channels channels, IConsumer consumer) { - Group group = new Group(channels, consumer); - // Recreate the new list to avoid change list while the list is used in consuming. - ArrayList newList = new ArrayList(); - for (Group target : consumeTargets) { - newList.add(target); - } - newList.add(group); - consumeTargets = newList; - size += channels.size(); - } - - public long size() { - return size; - } - - void shutdown() { - running = false; - } - - private static class Group { - private Channels channels; - private IConsumer consumer; - - public Group(Channels channels, IConsumer consumer) { - this.channels = channels; - this.consumer = consumer; - } - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/IDataPartitioner.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/IDataPartitioner.java deleted file mode 100644 index 1dfe31c5..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/IDataPartitioner.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier.partition; - - -import com.zmops.zeus.iot.server.datacarrier.buffer.BufferStrategy; - -public interface IDataPartitioner { - - int partition(int total, T data); - - /** - * @return an integer represents how many times should retry when {@link BufferStrategy#IF_POSSIBLE}. - *

- * Less or equal 1, means not support retry. - */ - int maxRetryCount(); -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/ProducerThreadPartitioner.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/ProducerThreadPartitioner.java deleted file mode 100644 index 80a5a08c..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/ProducerThreadPartitioner.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier.partition; - -/** - * use threadid % total to partition - */ -public class ProducerThreadPartitioner implements IDataPartitioner { - public ProducerThreadPartitioner() { - } - - @Override - public int partition(int total, T data) { - return (int) Thread.currentThread().getId() % total; - } - - @Override - public int maxRetryCount() { - return 1; - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/SimpleRollingPartitioner.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/SimpleRollingPartitioner.java deleted file mode 100644 index c69041e8..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/SimpleRollingPartitioner.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.datacarrier.partition; - -/** - * use normal int to rolling. - */ -public class SimpleRollingPartitioner implements IDataPartitioner { - @SuppressWarnings("NonAtomicVolatileUpdate") - private volatile int i = 0; - - @Override - public int partition(int total, T data) { - return Math.abs(i++ % total); - } - - @Override - public int maxRetryCount() { - return 3; - } -} diff --git a/iot-common/iot-eventbus/pom.xml b/iot-common/iot-eventbus/pom.xml deleted file mode 100644 index d2072cd8..00000000 --- a/iot-common/iot-eventbus/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - iot-common - com.zmops - 1.0-beta - - 4.0.0 - - - iot-eventbus - - - 8 - 8 - - - - - org.apache.commons - commons-lang3 - 3.4 - - - com.google.guava - guava - 25.1-jre - - - org.projectlombok - lombok - 1.18.20 - - - - org.apache.logging.log4j - log4j-api - 2.13.3 - - - org.apache.logging.log4j - log4j-slf4j-impl - 2.13.3 - - - - \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/constant/EventConstant.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/constant/EventConstant.java deleted file mode 100644 index a08b0887..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/constant/EventConstant.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.constant; - -/** - * Created by nantian on 2021-03-11 0:25 - * - * @version 1.0 - */ -public class EventConstant { - - public static final String EVENTBUS_VERSION = "2.0.13"; - - public static final String EVENTBUS_ENABLED = "eventbus.enabled"; - - public static final String SHARED_CONTROLLER = "SharedController"; -} diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/Event.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/Event.java deleted file mode 100644 index c5567f30..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/Event.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.core; - -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -import java.io.Serializable; - -public class Event implements Serializable { - private static final long serialVersionUID = 7090050666419528496L; - - protected Object source; - - public Event() { - this(null); - } - - public Event(Object source) { - this.source = source; - } - - public Object getSource() { - return source; - } - - @Override - public int hashCode() { - return HashCodeBuilder.reflectionHashCode(this); - } - - @Override - public boolean equals(Object object) { - return EqualsBuilder.reflectionEquals(this, object); - } - - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); - } -} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventController.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventController.java deleted file mode 100644 index 62312777..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventController.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.core; - -import java.util.Collection; - -/** - * EventBus 控制器 - * - * @author nantian - */ -public interface EventController { - - void register(Object object); - - void unregister(Object object); - - void post(Object event); - - void post(Collection event); - - void postEvent(Event event); - - void postEvent(Collection events); -} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java deleted file mode 100644 index 10765b92..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerFactory.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.core; - -import com.google.common.eventbus.AsyncEventBus; -import com.google.common.eventbus.EventBus; -import com.google.common.eventbus.SubscriberExceptionHandler; -import com.zmops.zeus.iot.server.eventbus.constant.EventConstant; -import com.zmops.zeus.iot.server.eventbus.thread.ThreadPoolFactory; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executor; - -/** - * 事件控制器 工厂类 - * - * @author nantian - */ -public final class EventControllerFactory { - - private final ThreadPoolFactory threadPoolFactory; - - public EventControllerFactory(ThreadPoolFactory threadPoolFactory) { - this.threadPoolFactory = threadPoolFactory; - } - - private final Map syncControllerMap = new ConcurrentHashMap(); - private final Map asyncControllerMap = new ConcurrentHashMap(); - - public EventController getAsyncController() { - return getAsyncController(EventConstant.SHARED_CONTROLLER); - } - - public EventController getAsyncController(String identifier) { - return getController(identifier, true); - } - - public EventController getSyncController() { - return getSyncController(EventConstant.SHARED_CONTROLLER); - } - - public EventController getSyncController(String identifier) { - return getController(identifier, false); - } - - public EventController getController(String identifier, boolean async) { - return getController(identifier, async ? EventType.ASYNC : EventType.SYNC); - } - - public EventController getController(String identifier, EventType type) { - switch (type) { - case SYNC: - EventController syncEventController = syncControllerMap.get(identifier); - if (syncEventController == null) { - EventController newEventController = createSyncController(identifier); - syncEventController = syncControllerMap.putIfAbsent(identifier, newEventController); - if (syncEventController == null) { - syncEventController = newEventController; - } - } - - return syncEventController; - case ASYNC: - EventController asyncEventController = asyncControllerMap.get(identifier); - if (asyncEventController == null) { - EventController newEventController = createAsyncController(identifier, threadPoolFactory.getThreadPoolExecutor(identifier)); - asyncEventController = asyncControllerMap.putIfAbsent(identifier, newEventController); - if (asyncEventController == null) { - asyncEventController = newEventController; - } - } - - return asyncEventController; - } - - return null; - } - - public EventController createSyncController() { - return new EventControllerImpl(new EventBus()); - } - - public EventController createSyncController(String identifier) { - return new EventControllerImpl(new EventBus(identifier)); - } - - public EventController createSyncController(SubscriberExceptionHandler subscriberExceptionHandler) { - return new EventControllerImpl(new EventBus(subscriberExceptionHandler)); - } - - public EventController createAsyncController(String identifier, Executor executor) { - return new EventControllerImpl(new AsyncEventBus(identifier, executor)); - } - - public EventController createAsyncController(Executor executor, SubscriberExceptionHandler subscriberExceptionHandler) { - return new EventControllerImpl(new AsyncEventBus(executor, subscriberExceptionHandler)); - } - - public EventController createAsyncController(Executor executor) { - return new EventControllerImpl(new AsyncEventBus(executor)); - } -} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerImpl.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerImpl.java deleted file mode 100644 index 58b186c3..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventControllerImpl.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.core; - -import com.google.common.eventbus.EventBus; - -import java.util.Collection; - -public class EventControllerImpl implements EventController { - - private final EventBus eventBus; - - public EventControllerImpl(EventBus eventBus) { - this.eventBus = eventBus; - } - - @Override - public void register(Object object) { - eventBus.register(object); - } - - @Override - public void unregister(Object object) { - eventBus.unregister(object); - } - - @Override - public void post(Object event) { - eventBus.post(event); - } - - @Override - public void post(Collection events) { - for (Object event : events) { - eventBus.post(event); - } - } - - @Override - public void postEvent(Event event) { - post(event); - } - - @Override - public void postEvent(Collection events) { - post(events); - } -} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventType.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventType.java deleted file mode 100644 index 1f8fd650..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/core/EventType.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.core; - -public enum EventType { - SYNC("Sync"), - ASYNC("Async"); - - private final String value; - - private EventType(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - - public static EventType fromString(String value) { - for (EventType type : EventType.values()) { - if (type.getValue().equalsIgnoreCase(value.trim())) { - return type; - } - } - - throw new IllegalArgumentException("Mismatched type with value=" + value); - } - - @Override - public String toString() { - return value; - } -} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/ThreadPoolFactory.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/ThreadPoolFactory.java deleted file mode 100644 index 134afe69..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/ThreadPoolFactory.java +++ /dev/null @@ -1,193 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.thread; - - -import com.zmops.zeus.iot.server.eventbus.thread.constant.ThreadConstant; -import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadCustomization; -import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadParameter; -import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadQueueType; -import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadRejectedPolicyType; -import com.zmops.zeus.iot.server.eventbus.thread.policy.*; -import com.zmops.zeus.iot.server.eventbus.thread.util.NetUtil; -import com.zmops.zeus.iot.server.eventbus.thread.util.StringUtil; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * 线程池工厂类 - * - * @author nantian - */ -public class ThreadPoolFactory { - private static final Logger LOG = LoggerFactory.getLogger(ThreadPoolFactory.class); - - private final Map threadPoolExecutorMap = new ConcurrentHashMap<>(); - private ThreadPoolExecutor threadPoolExecutor; - - private final ThreadCustomization threadCustomization; - private final ThreadParameter threadParameter; - - public ThreadPoolFactory(ThreadCustomization threadCustomization, ThreadParameter threadParameter) { - this.threadCustomization = threadCustomization; - this.threadParameter = threadParameter; - } - - public ThreadPoolExecutor getThreadPoolExecutor(String threadPoolName) { - boolean threadPoolMultiMode = threadCustomization.isThreadPoolMultiMode(); - String poolName = createThreadPoolName(threadPoolName); - - if (threadPoolMultiMode) { - ThreadPoolExecutor threadPoolExecutor = threadPoolExecutorMap.get(poolName); - if (threadPoolExecutor == null) { - ThreadPoolExecutor newThreadPoolExecutor = createThreadPoolExecutor(poolName); - threadPoolExecutor = threadPoolExecutorMap.putIfAbsent(poolName, newThreadPoolExecutor); - if (threadPoolExecutor == null) { - threadPoolExecutor = newThreadPoolExecutor; - } - } - - return threadPoolExecutor; - } else { - return createSharedThreadPoolExecutor(); - } - } - - private ThreadPoolExecutor createSharedThreadPoolExecutor() { - String threadPoolSharedName = threadCustomization.getThreadPoolSharedName(); - if (StringUtils.isEmpty(threadPoolSharedName)) { - threadPoolSharedName = ThreadConstant.DEFAULT_THREADPOOL_SHARED_NAME; - } - - String poolName = createThreadPoolName(threadPoolSharedName); - if (threadPoolExecutor == null) { - synchronized (ThreadPoolFactory.class) { - if (threadPoolExecutor == null) { - threadPoolExecutor = createThreadPoolExecutor(poolName); - } - } - } - - return threadPoolExecutor; - } - - private String createThreadPoolName(String threadPoolName) { - boolean threadPoolNameIPShown = threadCustomization.isThreadPoolNameIPShown(); - - return threadPoolNameIPShown ? StringUtil.firstLetterToUpper(threadPoolName) + "-" + NetUtil.getLocalHost() + "-thread" : StringUtil.firstLetterToUpper(threadPoolName) + "-thread"; - } - - private ThreadPoolExecutor createThreadPoolExecutor(String threadPoolName) { - boolean threadPoolNameCustomized = threadCustomization.isThreadPoolNameCustomized(); - - return threadPoolNameCustomized ? createThreadPoolExecutor(threadPoolName, threadParameter) : createThreadPoolExecutor(threadParameter); - } - - public static ThreadPoolExecutor createThreadPoolExecutor(String threadPoolName, ThreadParameter threadParameter) { - int corePoolSize = threadParameter.getThreadPoolCorePoolSize(); - int maximumPoolSize = threadParameter.getThreadPoolMaximumPoolSize(); - long keepAliveTime = threadParameter.getThreadPoolKeepAliveTime(); - boolean allowCoreThreadTimeout = threadParameter.isThreadPoolAllowCoreThreadTimeout(); - String queue = threadParameter.getThreadPoolQueue(); - int queueCapacity = threadParameter.getThreadPoolQueueCapacity(); - String rejectedPolicy = threadParameter.getThreadPoolRejectedPolicy(); - - LOG.info("Thread pool executor is created, threadPoolName={}, threadParameter={}", threadPoolName, threadParameter); - - ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, - maximumPoolSize, - keepAliveTime, - TimeUnit.MILLISECONDS, - Objects.requireNonNull(createBlockingQueue(queue, queueCapacity)), - new ThreadFactory() { - private final AtomicInteger number = new AtomicInteger(0); - - @Override - public Thread newThread(Runnable runnable) { - return new Thread(runnable, threadPoolName + "-" + number.getAndIncrement()); - } - }, - Objects.requireNonNull(createRejectedPolicy(rejectedPolicy))); - threadPoolExecutor.allowCoreThreadTimeOut(allowCoreThreadTimeout); - - return threadPoolExecutor; - } - - public static ThreadPoolExecutor createThreadPoolExecutor(ThreadParameter threadParameter) { - int corePoolSize = threadParameter.getThreadPoolCorePoolSize(); - int maximumPoolSize = threadParameter.getThreadPoolMaximumPoolSize(); - long keepAliveTime = threadParameter.getThreadPoolKeepAliveTime(); - boolean allowCoreThreadTimeout = threadParameter.isThreadPoolAllowCoreThreadTimeout(); - String queue = threadParameter.getThreadPoolQueue(); - int queueCapacity = threadParameter.getThreadPoolQueueCapacity(); - String rejectedPolicy = threadParameter.getThreadPoolRejectedPolicy(); - - LOG.info("Thread pool executor is created, threadParameter={}", threadParameter); - - ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, - maximumPoolSize, - keepAliveTime, - TimeUnit.MILLISECONDS, - Objects.requireNonNull(createBlockingQueue(queue, queueCapacity)), - Objects.requireNonNull(createRejectedPolicy(rejectedPolicy))); - threadPoolExecutor.allowCoreThreadTimeOut(allowCoreThreadTimeout); - - return threadPoolExecutor; - } - - private static BlockingQueue createBlockingQueue(String queue, int queueCapacity) { - ThreadQueueType queueType = ThreadQueueType.fromString(queue); - - switch (queueType) { - case LINKED_BLOCKING_QUEUE: - return new LinkedBlockingQueue(queueCapacity); - case ARRAY_BLOCKING_QUEUE: - return new ArrayBlockingQueue(queueCapacity); - case SYNCHRONOUS_QUEUE: - return new SynchronousQueue(); - } - - return null; - } - - private static RejectedExecutionHandler createRejectedPolicy(String rejectedPolicy) { - ThreadRejectedPolicyType rejectedPolicyType = ThreadRejectedPolicyType.fromString(rejectedPolicy); - - switch (rejectedPolicyType) { - case BLOCKING_POLICY_WITH_REPORT: - return new BlockingPolicyWithReport(); - case CALLER_RUNS_POLICY_WITH_REPORT: - return new CallerRunsPolicyWithReport(); - case ABORT_POLICY_WITH_REPORT: - return new AbortPolicyWithReport(); - case REJECTED_POLICY_WITH_REPORT: - return new RejectedPolicyWithReport(); - case DISCARDED_POLICY_WITH_REPORT: - return new DiscardedPolicyWithReport(); - } - - return null; - } - - public void shutdown() { - if (threadPoolExecutor != null && !threadPoolExecutor.isShutdown()) { - LOG.info("Shutting down thread pool executor [{}]...", threadPoolExecutor); - - threadPoolExecutor.shutdown(); - } - - for (Map.Entry entry : threadPoolExecutorMap.entrySet()) { - ThreadPoolExecutor executor = entry.getValue(); - - if (executor != null && !executor.isShutdown()) { - LOG.info("Shutting down thread pool executor [{}] ...", threadPoolExecutor); - - executor.shutdown(); - } - } - } -} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/constant/ThreadConstant.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/constant/ThreadConstant.java deleted file mode 100644 index 2d4f8934..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/constant/ThreadConstant.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.thread.constant; - -public class ThreadConstant { - public static final int CPUS = Math.max(2, Runtime.getRuntime().availableProcessors()); - - public static final String THREAD_POOL_MULTI_MODE = "threadpool.multi.mode"; - public static final String THREAD_POOL_SHARED_NAME = "threadpool.shared.name"; - public static final String THREAD_POOL_NAME_CUSTOMIZED = "threadpool.name.customized"; - public static final String THREAD_POOL_NAME_IP_SHOWN = "threadpool.name.ipshown"; - public static final String THREAD_POOL_CORE_POOL_SIZE = "threadpool.core.pool.size"; - public static final String THREAD_POOL_MAXIMUM_POOL_SIZE = "threadpool.maximum.pool.size"; - public static final String THREAD_POOL_KEEP_ALIVE_TIME = "threadpool.keep.alive.time"; - public static final String THREAD_POOL_ALLOW_CORE_THREAD_TIMEOUT = "threadpool.allow.core.thread.timeout"; - public static final String THREAD_POOL_QUEUE = "threadpool.queue"; - public static final String THREAD_POOL_QUEUE_CAPACITY = "threadpool.queue.capacity"; - public static final String THREAD_POOL_REJECTED_POLICY = "threadpool.rejected.policy"; - - public static final String DEFAULT_THREADPOOL_SHARED_NAME = "SharedThreadPool"; -} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadCustomization.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadCustomization.java deleted file mode 100644 index 3c84e597..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadCustomization.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.thread.entity; - - -import com.zmops.zeus.iot.server.eventbus.thread.constant.ThreadConstant; -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -import java.io.Serializable; - - -/** - * - */ -public class ThreadCustomization implements Serializable { - private static final long serialVersionUID = -927120657442228832L; - - private boolean threadPoolMultiMode = false; - private String threadPoolSharedName = ThreadConstant.DEFAULT_THREADPOOL_SHARED_NAME; - private boolean threadPoolNameCustomized = true; - private boolean threadPoolNameIPShown = true; - - public boolean isThreadPoolMultiMode() { - return threadPoolMultiMode; - } - - public void setThreadPoolMultiMode(boolean threadPoolMultiMode) { - this.threadPoolMultiMode = threadPoolMultiMode; - } - - public String getThreadPoolSharedName() { - return threadPoolSharedName; - } - - public void setThreadPoolSharedName(String threadPoolSharedName) { - this.threadPoolSharedName = threadPoolSharedName; - } - - public boolean isThreadPoolNameCustomized() { - return threadPoolNameCustomized; - } - - public void setThreadPoolNameCustomized(boolean threadPoolNameCustomized) { - this.threadPoolNameCustomized = threadPoolNameCustomized; - } - - public boolean isThreadPoolNameIPShown() { - return threadPoolNameIPShown; - } - - public void setThreadPoolNameIPShown(boolean threadPoolNameIPShown) { - this.threadPoolNameIPShown = threadPoolNameIPShown; - } - - @Override - public int hashCode() { - return HashCodeBuilder.reflectionHashCode(this); - } - - @Override - public boolean equals(Object object) { - return EqualsBuilder.reflectionEquals(this, object); - } - - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); - } -} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadParameter.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadParameter.java deleted file mode 100644 index 96019089..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadParameter.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.thread.entity; - - -import com.zmops.zeus.iot.server.eventbus.thread.constant.ThreadConstant; -import lombok.Getter; -import lombok.Setter; -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -import java.io.Serializable; - -@Getter -@Setter -public class ThreadParameter implements Serializable { - private static final long serialVersionUID = 6869706244434951605L; - - private int threadPoolCorePoolSize = ThreadConstant.CPUS; - private int threadPoolMaximumPoolSize = ThreadConstant.CPUS * 2; - private long threadPoolKeepAliveTime = 900000; - private boolean threadPoolAllowCoreThreadTimeout = false; - private String threadPoolQueue = "LinkedBlockingQueue"; - private int threadPoolQueueCapacity = ThreadConstant.CPUS * 128; - private String threadPoolRejectedPolicy = "BlockingPolicyWithReport"; - - - @Override - public int hashCode() { - return HashCodeBuilder.reflectionHashCode(this); - } - - @Override - public boolean equals(Object object) { - return EqualsBuilder.reflectionEquals(this, object); - } - - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); - } -} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadQueueType.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadQueueType.java deleted file mode 100644 index e6c13050..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadQueueType.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.thread.entity; - -public enum ThreadQueueType { - LINKED_BLOCKING_QUEUE("LinkedBlockingQueue"), - ARRAY_BLOCKING_QUEUE("ArrayBlockingQueue"), - SYNCHRONOUS_QUEUE("SynchronousQueue"); - - private final String value; - - private ThreadQueueType(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - - public static ThreadQueueType fromString(String value) { - for (ThreadQueueType type : ThreadQueueType.values()) { - if (type.getValue().equalsIgnoreCase(value.trim())) { - return type; - } - } - - throw new IllegalArgumentException("Mismatched type with value=" + value); - } - - @Override - public String toString() { - return value; - } -} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadRejectedPolicyType.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadRejectedPolicyType.java deleted file mode 100644 index c329d831..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/entity/ThreadRejectedPolicyType.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.thread.entity; - -public enum ThreadRejectedPolicyType { - BLOCKING_POLICY_WITH_REPORT("BlockingPolicyWithReport"), - CALLER_RUNS_POLICY_WITH_REPORT("CallerRunsPolicyWithReport"), - ABORT_POLICY_WITH_REPORT("AbortPolicyWithReport"), - REJECTED_POLICY_WITH_REPORT("RejectedPolicyWithReport"), - DISCARDED_POLICY_WITH_REPORT("DiscardedPolicyWithReport"); - - private final String value; - - private ThreadRejectedPolicyType(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - - public static ThreadRejectedPolicyType fromString(String value) { - for (ThreadRejectedPolicyType type : ThreadRejectedPolicyType.values()) { - if (type.getValue().equalsIgnoreCase(value.trim())) { - return type; - } - } - - throw new IllegalArgumentException("Mismatched type with value=" + value); - } - - @Override - public String toString() { - return value; - } -} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/AbortPolicyWithReport.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/AbortPolicyWithReport.java deleted file mode 100644 index 12fb2cc9..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/AbortPolicyWithReport.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.thread.policy; - - -import lombok.extern.slf4j.Slf4j; - -import java.util.concurrent.ThreadPoolExecutor; - -// 任务饱和时, 抛弃任务,抛出异常 -@Slf4j -public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy { - - - private final String threadName; - - public AbortPolicyWithReport() { - this(null); - } - - public AbortPolicyWithReport(String threadName) { - this.threadName = threadName; - } - - @Override - public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) { - if (threadName != null) { - log.error("Thread pool [{}] is exhausted, executor={}", threadName, executor.toString()); - } - - super.rejectedExecution(runnable, executor); - } -} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/BlockingPolicyWithReport.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/BlockingPolicyWithReport.java deleted file mode 100644 index 8af23ad8..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/BlockingPolicyWithReport.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.thread.policy; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.RejectedExecutionHandler; -import java.util.concurrent.ThreadPoolExecutor; - -// 使用阻塞生产者的饱和策略,不抛弃任务,也不抛出异常,当队列满时改为调用BlockingQueue.put来实现生产者的阻塞 -public class BlockingPolicyWithReport implements RejectedExecutionHandler { - private static final Logger LOG = LoggerFactory.getLogger(BlockingPolicyWithReport.class); - - private final String threadName; - - public BlockingPolicyWithReport() { - this(null); - } - - public BlockingPolicyWithReport(String threadName) { - this.threadName = threadName; - } - - // 队列用法: - // 1.add 增加一个元素,如果队列已满,则抛出一个IIIegaISlabEepeplian异常 - // 2.remove 移除并返回队列头部的元素,如果队列为空,则抛出一个NoSuchElementException异常 - // 3.element 返回队列头部的元素,如果队列为空,则抛出一个NoSuchElementException异常 - // 4.offer 添加一个元素并返回true,如果队列已满,则返回false - // 5.poll 移除并返问队列头部的元素,如果队列为空,则返回null - // 6.peek 返回队列头部的元,如果队列为空,则返回null - // 7.put 添加一个元素,如果队列已满,则阻塞 - // 8.take 移除并返回队列头部的元素,如果队列为空,则阻塞 - @Override - public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) { - if (threadName != null) { - LOG.error("Thread pool [{}] is exhausted, executor={}", threadName, executor.toString()); - } - - if (!executor.isShutdown()) { - try { - // 添加一个元素, 如果队列满,则阻塞 - executor.getQueue().put(runnable); - } catch (InterruptedException e) { - // should not be interrupted - } - } - } -} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/CallerRunsPolicyWithReport.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/CallerRunsPolicyWithReport.java deleted file mode 100644 index 88817867..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/CallerRunsPolicyWithReport.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.thread.policy; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.ThreadPoolExecutor; - -// 使用Caller-Runs(调用者执行)饱和策略,不抛弃任务,也不抛出异常,而是将当前任务回退到发起这个调用者执行的线程所在的上级线程去执行 -public class CallerRunsPolicyWithReport extends ThreadPoolExecutor.CallerRunsPolicy { - private static final Logger LOG = LoggerFactory.getLogger(CallerRunsPolicyWithReport.class); - - private final String threadName; - - public CallerRunsPolicyWithReport() { - this(null); - } - - public CallerRunsPolicyWithReport(String threadName) { - this.threadName = threadName; - } - - @Override - public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) { - if (threadName != null) { - LOG.error("Thread pool [{}] is exhausted, executor={}", threadName, executor.toString()); - } - - super.rejectedExecution(runnable, executor); - } -} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/DiscardedPolicyWithReport.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/DiscardedPolicyWithReport.java deleted file mode 100644 index 93d5b333..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/DiscardedPolicyWithReport.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.thread.policy; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.RejectedExecutionHandler; -import java.util.concurrent.ThreadPoolExecutor; - -// 任务饱和时以FIFO的方式抛弃队列中一部分现有任务,再添加新任务 -public class DiscardedPolicyWithReport implements RejectedExecutionHandler { - private static final Logger LOG = LoggerFactory.getLogger(DiscardedPolicyWithReport.class); - - private final String threadName; - - public DiscardedPolicyWithReport() { - this(null); - } - - public DiscardedPolicyWithReport(String threadName) { - this.threadName = threadName; - } - - @Override - public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) { - if (threadName != null) { - LOG.error("Thread pool [{}] is exhausted, executor={}", threadName, executor.toString()); - } - - if (!executor.isShutdown()) { - BlockingQueue queue = executor.getQueue(); - // 舍弃1/2队列元素,例如7个单位的元素,舍弃3个 - int discardSize = queue.size() >> 1; - for (int i = 0; i < discardSize; i++) { - // 从头部移除并返问队列头部的元素 - queue.poll(); - } - - // 添加元素,如果队列满,不阻塞,返回false - queue.offer(runnable); - } - } -} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/RejectedPolicyWithReport.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/RejectedPolicyWithReport.java deleted file mode 100644 index da7cbb9c..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/RejectedPolicyWithReport.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.thread.policy; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.RejectedExecutionHandler; -import java.util.concurrent.ThreadPoolExecutor; - -// 如果该任务实现了RejectedRunnable接口,那么交给用户去实现拒绝服务的逻辑,否则以FIFO的方式抛弃队列中一部分现有任务,再添加新任务 -public class RejectedPolicyWithReport implements RejectedExecutionHandler { - private static final Logger LOG = LoggerFactory.getLogger(RejectedPolicyWithReport.class); - - private final String threadName; - - public RejectedPolicyWithReport() { - this(null); - } - - public RejectedPolicyWithReport(String threadName) { - this.threadName = threadName; - } - - @Override - public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) { - if (threadName != null) { - LOG.error("Thread pool [{}] is exhausted, executor={}", threadName, executor.toString()); - } - - if (runnable instanceof RejectedRunnable) { - ((RejectedRunnable) runnable).rejected(); // 交给用户来处理 - } else { - if (!executor.isShutdown()) { - BlockingQueue queue = executor.getQueue(); - // 舍弃1/2队列元素,例如7个单位的元素,舍弃3个 - int discardSize = queue.size() >> 1; - for (int i = 0; i < discardSize; i++) { - // 从头部移除并返问队列头部的元素 - queue.poll(); - } - - try { - // 添加一个元素, 如果队列满,则阻塞 - queue.put(runnable); - } catch (InterruptedException e) { - // should not be interrupted - } - } - } - } -} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/RejectedRunnable.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/RejectedRunnable.java deleted file mode 100644 index 64b9ce1c..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/policy/RejectedRunnable.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.thread.policy; - -public interface RejectedRunnable extends Runnable { - // 如果任务被拒绝,用户自行处理 - void rejected(); -} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/NetUtil.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/NetUtil.java deleted file mode 100644 index f11e0dfc..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/NetUtil.java +++ /dev/null @@ -1,205 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.thread.util; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.net.*; -import java.util.Enumeration; -import java.util.Random; -import java.util.regex.Pattern; - -public class NetUtil { - private static final Logger LOG = LoggerFactory.getLogger(NetUtil.class); - - public static final String LOCALHOST = "localhost"; - public static final String LOCALHOST_IP = "127.0.0.1"; - public static final String ANYHOST_IP = "0.0.0.0"; - - private static final Random RANDOM = new Random(System.currentTimeMillis()); - private static final int RND_PORT_START = 30000; - private static final int RND_PORT_RANGE = 10000; - private static final int MIN_PORT = 0; - private static final int MAX_PORT = 65535; - - private static final Pattern ADDRESS_PATTERN = Pattern.compile("^\\d{1,3}(\\.\\d{1,3}){3}\\:\\d{1,5}$"); - private static final Pattern LOCAL_IP_PATTERN = Pattern.compile("127(\\.\\d{1,3}){3}$"); - private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$"); - - private static volatile InetAddress LOCAL_ADDRESS = null; - - public static int getRandomPort() { - return RND_PORT_START + RANDOM.nextInt(RND_PORT_RANGE); - } - - public static int getAvailablePort() { - ServerSocket serverSocket = null; - try { - serverSocket = new ServerSocket(); - serverSocket.bind(null); - - return serverSocket.getLocalPort(); - } catch (IOException e) { - return getRandomPort(); - } finally { - if (serverSocket != null) { - try { - serverSocket.close(); - } catch (IOException e) { - } - } - } - } - - public static int getAvailablePort(int port) { - if (port <= 0) { - return getAvailablePort(); - } - - for (int i = port; i < MAX_PORT; i++) { - ServerSocket serverSocket = null; - try { - serverSocket = new ServerSocket(i); - return i; - } catch (IOException e) { - } finally { - if (serverSocket != null) { - try { - serverSocket.close(); - } catch (IOException e) { - } - } - } - } - - return port; - } - - public static boolean isInvalidPort(int port) { - return port <= MIN_PORT || port > MAX_PORT; - } - - public static boolean isValidAddress(String address) { - return ADDRESS_PATTERN.matcher(address).matches(); - } - - public static boolean isLocalHost(String host) { - return host != null && (LOCAL_IP_PATTERN.matcher(host).matches() || host.equalsIgnoreCase(LOCALHOST)); - } - - public static boolean isAnyHost(String host) { - return ANYHOST_IP.equals(host); - } - - public static boolean isInvalidLocalHost(String host) { - return host == null || host.length() == 0 || host.equalsIgnoreCase(LOCALHOST) || host.equals(ANYHOST_IP) || (LOCAL_IP_PATTERN.matcher(host).matches()); - } - - public static boolean isValidLocalHost(String host) { - return !isInvalidLocalHost(host); - } - - public static InetSocketAddress getLocalSocketAddress(String host, int port) { - return isInvalidLocalHost(host) ? new InetSocketAddress(port) : new InetSocketAddress(host, port); - } - - static boolean isValidAddress(InetAddress address) { - if (address == null || address.isLoopbackAddress()) { - return false; - } - - String name = address.getHostAddress(); - - return (name != null && !ANYHOST_IP.equals(name) && !LOCALHOST_IP.equals(name) && IP_PATTERN.matcher(name).matches()); - } - - public static String getLocalHost() { - InetAddress address = getLocalAddress(); - - return address == null ? LOCALHOST_IP : address.getHostAddress(); - } - - /** - * Find first valid IP from local network card - * - * @return first valid local IP - */ - public static InetAddress getLocalAddress() { - if (LOCAL_ADDRESS != null) { - return LOCAL_ADDRESS; - } - - InetAddress localAddress = getLocalAddress0(); - LOCAL_ADDRESS = localAddress; - - return localAddress; - } - - private static InetAddress getLocalAddress0() { - InetAddress localAddress = null; - try { - localAddress = InetAddress.getLocalHost(); - if (isValidAddress(localAddress)) { - return localAddress; - } - } catch (Throwable e) { - LOG.warn("Get local address0 failed", e); - } - try { - Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); - if (interfaces != null) { - while (interfaces.hasMoreElements()) { - try { - NetworkInterface network = interfaces.nextElement(); - Enumeration addresses = network.getInetAddresses(); - if (addresses != null) { - while (addresses.hasMoreElements()) { - try { - InetAddress address = addresses.nextElement(); - if (isValidAddress(address)) { - return address; - } - } catch (Throwable e) { - LOG.warn("Get local address0 failed", e); - } - } - } - } catch (Throwable e) { - LOG.warn("Get local address0 failed", e); - } - } - } - } catch (Throwable e) { - LOG.warn("Get local address0 failed", e); - } - - return localAddress; - } - - public static String getIpByHost(String hostName) { - try { - return InetAddress.getByName(hostName).getHostAddress(); - } catch (UnknownHostException e) { - return hostName; - } - } - - public static String toAddressString(InetSocketAddress address) { - return address.getAddress().getHostAddress() + ":" + address.getPort(); - } - - public static InetSocketAddress toAddress(String address) { - int i = address.indexOf(':'); - String host; - int port; - if (i > -1) { - host = address.substring(0, i); - port = Integer.parseInt(address.substring(i + 1)); - } else { - host = address; - port = 0; - } - - return new InetSocketAddress(host, port); - } -} \ No newline at end of file diff --git a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/StringUtil.java b/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/StringUtil.java deleted file mode 100644 index 762d39f7..00000000 --- a/iot-common/iot-eventbus/src/main/java/com/zmops/zeus/iot/server/eventbus/thread/util/StringUtil.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.zmops.zeus.iot.server.eventbus.thread.util; - -public class StringUtil { - public static String firstLetterToUpper(String value) { - Character character = Character.toUpperCase(value.charAt(0)); - - return character.toString().concat(value.substring(1)); - } - - public static String firstLetterToLower(String value) { - Character character = Character.toLowerCase(value.charAt(0)); - - return character.toString().concat(value.substring(1)); - } -} \ No newline at end of file diff --git a/iot-common/iot-util/pom.xml b/iot-common/iot-util/pom.xml deleted file mode 100644 index d1bdc7a4..00000000 --- a/iot-common/iot-util/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - iot-common - com.zmops - 1.0-beta - - 4.0.0 - - iot-util - - - 8 - 8 - - - \ No newline at end of file diff --git a/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/PlaceholderConfigurerSupport.java b/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/PlaceholderConfigurerSupport.java deleted file mode 100644 index 359502aa..00000000 --- a/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/PlaceholderConfigurerSupport.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.util; - -public class PlaceholderConfigurerSupport { - - /** - * Default placeholder prefix: {@value} - */ - public static final String DEFAULT_PLACEHOLDER_PREFIX = "${"; - - /** - * Default placeholder suffix: {@value} - */ - public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}"; - - /** - * Default value separator: {@value} - */ - public static final String DEFAULT_VALUE_SEPARATOR = ":"; - -} diff --git a/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/PropertyPlaceholderHelper.java b/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/PropertyPlaceholderHelper.java deleted file mode 100644 index 373a5af2..00000000 --- a/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/PropertyPlaceholderHelper.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.util; - -import java.util.*; - -/** - * Utility class for working with Strings that have placeholder values in them. A placeholder takes the form {@code - * ${name}}. Using {@code PropertyPlaceholderHelper} these placeholders can be substituted for user-supplied values.

- * Values for substitution can be supplied using a {@link Properties} instance or using a {@link PlaceholderResolver}. - */ -public enum PropertyPlaceholderHelper { - - INSTANCE( - PlaceholderConfigurerSupport.DEFAULT_PLACEHOLDER_PREFIX, - PlaceholderConfigurerSupport.DEFAULT_PLACEHOLDER_SUFFIX, PlaceholderConfigurerSupport.DEFAULT_VALUE_SEPARATOR, - true - ); - - private final String placeholderPrefix; - - private final String placeholderSuffix; - - private final String simplePrefix; - - private final String valueSeparator; - - private final boolean ignoreUnresolvablePlaceholders; - - /** - * Creates a new {@code PropertyPlaceholderHelper} that uses the supplied prefix and suffix. - * - * @param placeholderPrefix the prefix that denotes the start of a placeholder - * @param placeholderSuffix the suffix that denotes the end of a placeholder - * @param valueSeparator the separating character between the placeholder variable and the - * associated default value, if any - * @param ignoreUnresolvablePlaceholders indicates whether unresolvable placeholders should be ignored ({@code - * true}) or cause an exception ({@code false}) - */ - PropertyPlaceholderHelper(String placeholderPrefix, String placeholderSuffix, String valueSeparator, - boolean ignoreUnresolvablePlaceholders) { - - if (StringUtil.isEmpty(placeholderPrefix) || StringUtil.isEmpty(placeholderSuffix)) { - throw new UnsupportedOperationException("'placeholderPrefix or placeholderSuffix' must not be null"); - } - - final Map wellKnownSimplePrefixes = new HashMap(4); - - wellKnownSimplePrefixes.put("}", "{"); - wellKnownSimplePrefixes.put("]", "["); - wellKnownSimplePrefixes.put(")", "("); - - this.placeholderPrefix = placeholderPrefix; - this.placeholderSuffix = placeholderSuffix; - String simplePrefixForSuffix = wellKnownSimplePrefixes.get(this.placeholderSuffix); - if (simplePrefixForSuffix != null && this.placeholderPrefix.endsWith(simplePrefixForSuffix)) { - this.simplePrefix = simplePrefixForSuffix; - } else { - this.simplePrefix = this.placeholderPrefix; - } - this.valueSeparator = valueSeparator; - this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders; - } - - /** - * Replaces all placeholders of format {@code ${name}} with the corresponding property from the supplied {@link - * Properties}. - * - * @param value the value containing the placeholders to be replaced - * @param properties the {@code Properties} to use for replacement - * @return the supplied value with placeholders replaced inline - */ - public String replacePlaceholders(String value, final Properties properties) { - return replacePlaceholders(value, new PlaceholderResolver() { - @Override - public String resolvePlaceholder(String placeholderName) { - return getConfigValue(placeholderName, properties); - } - }); - } - - private String getConfigValue(String key, final Properties properties) { - String value = System.getProperty(key); - if (value == null) { - value = System.getenv(key); - } - if (value == null) { - value = properties.getProperty(key); - } - return value; - } - - /** - * Replaces all placeholders of format {@code ${name}} with the value returned from the supplied {@link - * PlaceholderResolver}. - * - * @param value the value containing the placeholders to be replaced - * @param placeholderResolver the {@code PlaceholderResolver} to use for replacement - * @return the supplied value with placeholders replaced inline - */ - public String replacePlaceholders(String value, PlaceholderResolver placeholderResolver) { - return parseStringValue(value, placeholderResolver, new HashSet()); - } - - protected String parseStringValue(String value, PlaceholderResolver placeholderResolver, Set visitedPlaceholders) { - - StringBuilder result = new StringBuilder(value); - - int startIndex = value.indexOf(this.placeholderPrefix); - while (startIndex != -1) { - int endIndex = findPlaceholderEndIndex(result, startIndex); - if (endIndex != -1) { - String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex); - String originalPlaceholder = placeholder; - if (!visitedPlaceholders.add(originalPlaceholder)) { - throw new IllegalArgumentException("Circular placeholder reference '" + originalPlaceholder + "' in property definitions"); - } - // Recursive invocation, parsing placeholders contained in the placeholder key. - placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders); - // Now obtain the value for the fully resolved key... - String propVal = placeholderResolver.resolvePlaceholder(placeholder); - - if (propVal == null && this.valueSeparator != null) { - int separatorIndex = placeholder.indexOf(this.valueSeparator); - if (separatorIndex != -1) { - String actualPlaceholder = placeholder.substring(0, separatorIndex); - String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length()); - propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder); - if (propVal == null) { - propVal = defaultValue; - } - } - } - - if (propVal != null) { - // Recursive invocation, parsing placeholders contained in the - // previously resolved placeholder value. - propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders); - result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal); - startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length()); - } else if (this.ignoreUnresolvablePlaceholders) { - // Proceed with unprocessed value. - startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length()); - } else { - throw new IllegalArgumentException( - "Could not resolve placeholder '" + placeholder + "'" + " in value \"" + value + "\""); - } - visitedPlaceholders.remove(originalPlaceholder); - } else { - startIndex = -1; - } - } - return result.toString(); - } - - private int findPlaceholderEndIndex(CharSequence buf, int startIndex) { - int index = startIndex + this.placeholderPrefix.length(); - int withinNestedPlaceholder = 0; - while (index < buf.length()) { - if (StringUtil.substringMatch(buf, index, this.placeholderSuffix)) { - if (withinNestedPlaceholder > 0) { - withinNestedPlaceholder--; - index = index + this.placeholderSuffix.length(); - } else { - return index; - } - } else if (StringUtil.substringMatch(buf, index, this.simplePrefix)) { - withinNestedPlaceholder++; - index = index + this.simplePrefix.length(); - } else { - index++; - } - } - return -1; - } - - /** - * Strategy interface used to resolve replacement values for placeholders contained in Strings. - */ - public interface PlaceholderResolver { - - /** - * Resolve the supplied placeholder name to the replacement value. - * - * @param placeholderName the name of the placeholder to resolve - * @return the replacement value, or {@code null} if no replacement is to be made - */ - String resolvePlaceholder(String placeholderName); - } -} diff --git a/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/StringUtil.java b/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/StringUtil.java deleted file mode 100644 index ba296aee..00000000 --- a/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/StringUtil.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.util; - -import java.util.function.Consumer; - -public final class StringUtil { - public static boolean isEmpty(String str) { - return str == null || str.length() == 0; - } - - public static boolean isNotEmpty(String str) { - return !isEmpty(str); - } - - public static boolean isBlank(String str) { - return str == null || isEmpty(str.trim()); - } - - public static boolean isNotBlank(String str) { - return !isBlank(str); - } - - public static void setIfPresent(String value, Consumer setter) { - if (isNotEmpty(value)) { - setter.accept(value); - } - } - - public static String join(final char delimiter, final String... strings) { - if (strings.length == 0) { - return null; - } - if (strings.length == 1) { - return strings[0]; - } - int length = strings.length - 1; - for (final String s : strings) { - if (s == null) { - continue; - } - length += s.length(); - } - final StringBuilder sb = new StringBuilder(length); - if (strings[0] != null) { - sb.append(strings[0]); - } - for (int i = 1; i < strings.length; ++i) { - if (!isEmpty(strings[i])) { - sb.append(delimiter).append(strings[i]); - } else { - sb.append(delimiter); - } - } - return sb.toString(); - } - - public static boolean substringMatch(CharSequence str, int index, CharSequence substring) { - if (index + substring.length() > str.length()) { - return false; - } - for (int i = 0; i < substring.length(); i++) { - if (str.charAt(index + i) != substring.charAt(i)) { - return false; - } - } - return true; - } - - public static String cut(String str, int threshold) { - if (isEmpty(str) || str.length() <= threshold) { - return str; - } - return str.substring(0, threshold); - } - - public static String trim(final String str, final char ch) { - if (isEmpty(str)) { - return null; - } - - final char[] chars = str.toCharArray(); - - int i = 0, j = chars.length - 1; - // noinspection StatementWithEmptyBody - for (; i < chars.length && chars[i] == ch; i++) { - } - // noinspection StatementWithEmptyBody - for (; j > 0 && chars[j] == ch; j--) { - } - - return new String(chars, i, j - i + 1); - } -} diff --git a/iot-common/pom.xml b/iot-common/pom.xml deleted file mode 100644 index 84d2aa1d..00000000 --- a/iot-common/pom.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - zeus-iot - com.zmops - 1.0-beta - - 4.0.0 - - iot-common - pom - - iot-datacarrier - iot-util - iot-eventbus - - - - 8 - 8 - - - \ No newline at end of file diff --git a/iot-server/pom.xml b/iot-server/pom.xml index 24910675..cfd01210 100644 --- a/iot-server/pom.xml +++ b/iot-server/pom.xml @@ -20,18 +20,18 @@ - server-library server-core server-starter server-bootstrap server-health-checker server-telemetry server-sender - server-action server-storage-plugin server-transfer server-localdb server-camel-receiver + server-web + server-client @@ -87,6 +87,12 @@ org.apache.camel camel-core + + + org.slf4j + slf4j-api + + org.apache.camel @@ -96,6 +102,9 @@ com.google.code.gson gson + + + org.apache.camel camel-netty4 diff --git a/iot-server/server-action/pom.xml b/iot-server/server-action/pom.xml deleted file mode 100644 index 01060167..00000000 --- a/iot-server/server-action/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - iot-server - com.zmops - 1.0-beta - - 4.0.0 - - server-action - - - 8 - 8 - - - \ No newline at end of file diff --git a/iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/ActionRouteIdentifier.java b/iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/ActionRouteIdentifier.java deleted file mode 100644 index d40b1ba7..00000000 --- a/iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/ActionRouteIdentifier.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.zmops.zeus.iot.server.action; - -/** - * @author nantian created at 2021/8/24 0:33 - */ -public interface ActionRouteIdentifier { - - String helloworld = "HelloWorld"; -} diff --git a/iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/HelloWorldAction.java b/iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/HelloWorldAction.java deleted file mode 100644 index 48071801..00000000 --- a/iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/HelloWorldAction.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.zmops.zeus.iot.server.action; - -import com.google.common.eventbus.Subscribe; -import com.zmops.zeus.iot.server.action.bean.ActionParam; -import lombok.extern.slf4j.Slf4j; - -/** - * @author nantian created at 2021/8/24 0:07 - *

- * 动作触发示例,基于 Camel 动态执行 - */ - -@Slf4j -public class HelloWorldAction { - - - @Subscribe - public void subscribe(ActionParam event) { - log.info("Device ID - {} ", event.getTriggerDevice()); - } - -} diff --git a/iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/bean/ActionParam.java b/iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/bean/ActionParam.java deleted file mode 100644 index 77035afc..00000000 --- a/iot-server/server-action/src/main/java/com/zmops/zeus/iot/server/action/bean/ActionParam.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.zmops.zeus.iot.server.action.bean; - -import lombok.Getter; -import lombok.Setter; - -/** - * @author nantian created at 2021/8/24 0:16 - */ -@Getter -@Setter -public class ActionParam { - - - private String triggerDevice; -} diff --git a/iot-server/server-bootstrap/pom.xml b/iot-server/server-bootstrap/pom.xml index 8ebf5ec3..fdd7b78c 100644 --- a/iot-server/server-bootstrap/pom.xml +++ b/iot-server/server-bootstrap/pom.xml @@ -16,10 +16,23 @@ server-core ${project.version} + + + com.zmops + toolkit-util + 1.0-SNAPSHOT + + + + com.zmops + server-web + 1.0-beta + + com.zmops library-module - ${project.version} + 1.0-SNAPSHOT org.yaml diff --git a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java index 23c793c1..f31ee7a7 100644 --- a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java +++ b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java @@ -19,12 +19,12 @@ package com.zmops.zeus.iot.server.starter; import com.zmops.zeus.iot.server.core.RunningMode; -import com.zmops.zeus.iot.server.library.module.ApplicationConfiguration; -import com.zmops.zeus.iot.server.library.module.ModuleManager; import com.zmops.zeus.iot.server.starter.config.ApplicationConfigLoader; import com.zmops.zeus.iot.server.telemetry.TelemetryModule; import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; +import com.zmops.zeus.server.library.module.ApplicationConfiguration; +import com.zmops.zeus.server.library.module.ModuleManager; import lombok.extern.slf4j.Slf4j; import java.util.TimeZone; diff --git a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java index c4860d8d..cd1ff672 100644 --- a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java +++ b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java @@ -18,12 +18,15 @@ package com.zmops.zeus.iot.server.starter.config; -import com.zmops.zeus.iot.server.library.module.ApplicationConfiguration; -import com.zmops.zeus.iot.server.library.module.ProviderNotFoundException; -import com.zmops.zeus.iot.server.library.util.CollectionUtils; -import com.zmops.zeus.iot.server.library.util.ResourceUtils; -import com.zmops.zeus.iot.server.util.PropertyPlaceholderHelper; + + +import com.zmops.zeus.server.util.PropertyPlaceholderHelper; +import com.zmops.zeus.server.library.module.ApplicationConfiguration; +import com.zmops.zeus.server.library.module.ProviderNotFoundException; +import com.zmops.zeus.server.library.util.CollectionUtils; +import com.zmops.zeus.server.library.util.ResourceUtils; import lombok.extern.slf4j.Slf4j; + import org.yaml.snakeyaml.Yaml; import java.io.FileNotFoundException; diff --git a/iot-server/server-camel-receiver/pom.xml b/iot-server/server-camel-receiver/pom.xml index 49fa7a25..b4aabf08 100644 --- a/iot-server/server-camel-receiver/pom.xml +++ b/iot-server/server-camel-receiver/pom.xml @@ -16,7 +16,7 @@ com.zmops library-module - 1.0-beta + 1.0-SNAPSHOT com.zmops @@ -30,14 +30,24 @@ com.zmops - iot-datacarrier - 1.0-beta + toolkit-datacarrier + 1.0-SNAPSHOT org.apache.camel camel-netty4-http + + org.apache.camel + camel-pgevent + 2.25.4 + + + org.postgresql + postgresql + 42.2.20 + diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/module/CamelReceiverModule.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/module/CamelReceiverModule.java index 4b64425d..70365a11 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/module/CamelReceiverModule.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/module/CamelReceiverModule.java @@ -1,7 +1,7 @@ package com.zmops.zeus.iot.server.receiver.module; -import com.zmops.zeus.iot.server.library.module.ModuleDefine; import com.zmops.zeus.iot.server.receiver.service.CamelContextHolderService; +import com.zmops.zeus.server.library.module.ModuleDefine; import java.util.ArrayList; import java.util.List; diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverConfig.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverConfig.java index 09f64c79..29616403 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverConfig.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverConfig.java @@ -1,6 +1,6 @@ package com.zmops.zeus.iot.server.receiver.provider; -import com.zmops.zeus.iot.server.library.module.ModuleConfig; +import com.zmops.zeus.server.library.module.ModuleConfig; import lombok.Getter; import lombok.Setter; diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverProvider.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverProvider.java index 819a236c..336b81c1 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverProvider.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverProvider.java @@ -1,11 +1,12 @@ package com.zmops.zeus.iot.server.receiver.provider; -import com.zmops.zeus.iot.server.library.module.*; import com.zmops.zeus.iot.server.receiver.Const; import com.zmops.zeus.iot.server.receiver.module.CamelReceiverModule; +import com.zmops.zeus.iot.server.receiver.routes.PgEventRouteBuilder; import com.zmops.zeus.iot.server.receiver.service.CamelContextHolderService; import com.zmops.zeus.iot.server.receiver.tozabbix.ZabbixSenderComponent; import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; +import com.zmops.zeus.server.library.module.*; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.model.ModelCamelContext; @@ -48,6 +49,12 @@ public void start() throws ServiceNotProvidedException, ModuleStartException { camelContext.addComponent(Const.CAMEL_ZABBIX_COMPONENT_NAME, new ZabbixSenderComponent(getManager())); + try { + camelContext.addRoutes(new PgEventRouteBuilder()); + } catch (Exception e) { + e.printStackTrace(); + } + try { camelContext.start(); } catch (Exception e) { diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttClientRouteBuilder.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttClientRouteBuilder.java index 03316d32..a9a5fecf 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttClientRouteBuilder.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttClientRouteBuilder.java @@ -1,7 +1,9 @@ package com.zmops.zeus.iot.server.receiver.routes; import com.zmops.zeus.iot.server.receiver.ReceiverServerRoute; +import org.apache.camel.Exchange; import org.apache.camel.LoggingLevel; +import org.apache.camel.Processor; import java.util.Map; @@ -20,5 +22,12 @@ public MqttClientRouteBuilder(String routeId, Map options) { public void configure() throws Exception { fromF("mqtt:zeus-iot-mqtt?host=tcp://%s:%s&subscribeTopicNames=123/up", options.get("hostIp"), options.get("port")) .routeId(routeId).log(LoggingLevel.DEBUG, log, ">>> Message received from Mqtt Client : ${body}"); + + from("direct:foo").process(new Processor() { + @Override + public void process(Exchange exchange) throws Exception { + exchange.getIn().setBody("123"); + } + }).to("mqtt:zeus-iot-mqtt"); } } diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/PgEventRouteBuilder.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/PgEventRouteBuilder.java new file mode 100644 index 00000000..75eb50df --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/PgEventRouteBuilder.java @@ -0,0 +1,17 @@ +package com.zmops.zeus.iot.server.receiver.routes; + +import org.apache.camel.LoggingLevel; +import org.apache.camel.builder.RouteBuilder; + +/** + * @author nantian created at 2021/10/26 0:28 + */ +public class PgEventRouteBuilder extends RouteBuilder { + + + @Override + public void configure() throws Exception { +// from("pgevent:172.16.60.99:5432/zabbix/zabbix_pg_event?pass=postgres&user=postgres") +// .log(LoggingLevel.DEBUG, log, ">>> PgEvent received from Zabbix Events : ${body}"); + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/CamelContextHolderService.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/CamelContextHolderService.java index 8f1539e8..6b9f4934 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/CamelContextHolderService.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/CamelContextHolderService.java @@ -1,10 +1,11 @@ package com.zmops.zeus.iot.server.receiver.service; -import com.zmops.zeus.iot.server.library.module.ModuleManager; -import com.zmops.zeus.iot.server.library.module.Service; +import com.zmops.zeus.server.library.module.ModuleManager; +import com.zmops.zeus.server.library.module.Service; import org.apache.camel.CamelContext; import org.apache.camel.Route; import org.apache.camel.RoutesBuilder; +import org.apache.camel.impl.EventDrivenConsumerRoute; /** * @author nantian created at 2021/8/17 0:24 @@ -13,7 +14,7 @@ */ public class CamelContextHolderService implements Service { - private final CamelContext camelContext; + private final CamelContext camelContext; private final ModuleManager moduleManager; public CamelContextHolderService(CamelContext camelContext, ModuleManager moduleManager) { @@ -42,7 +43,8 @@ public void addRoutes(RoutesBuilder builder) { * @param routeId 路由ID */ public void routeShutDown(String routeId) { - Route route = camelContext.getRoute(routeId); + EventDrivenConsumerRoute route = (EventDrivenConsumerRoute) camelContext.getRoute(routeId); + try { route.getEndpoint().stop(); route.getConsumer().stop(); diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/IOTDeviceValue.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/IoTDeviceValue.java similarity index 93% rename from iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/IOTDeviceValue.java rename to iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/IoTDeviceValue.java index 84eb8f68..8646307d 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/IOTDeviceValue.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/IoTDeviceValue.java @@ -13,7 +13,7 @@ @Getter @Setter -public class IOTDeviceValue { +public class IoTDeviceValue { private String deviceId; // 设备ID diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixSenderComponent.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixSenderComponent.java index 126d2369..4cf93b32 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixSenderComponent.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixSenderComponent.java @@ -1,6 +1,6 @@ package com.zmops.zeus.iot.server.receiver.tozabbix; -import com.zmops.zeus.iot.server.library.module.ModuleManager; +import com.zmops.zeus.server.library.module.ModuleManager; import org.apache.camel.Endpoint; import org.apache.camel.impl.DefaultComponent; diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixSenderEndpoint.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixSenderEndpoint.java index 63b17500..495cf8f4 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixSenderEndpoint.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixSenderEndpoint.java @@ -1,6 +1,6 @@ package com.zmops.zeus.iot.server.receiver.tozabbix; -import com.zmops.zeus.iot.server.library.module.ModuleManager; +import com.zmops.zeus.server.library.module.ModuleManager; import org.apache.camel.Component; import org.apache.camel.Consumer; import org.apache.camel.Processor; @@ -12,7 +12,7 @@ */ public class ZabbixSenderEndpoint extends DefaultEndpoint { - private final ModuleManager moduleManager; + private final ModuleManager moduleManager; private final ZabbixTrapperProducer producer; public ZabbixSenderEndpoint(String endpointUri, Component component, ModuleManager moduleManager) { diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixTrapperProducer.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixTrapperProducer.java index 5a6533f4..44ce527e 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixTrapperProducer.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixTrapperProducer.java @@ -1,10 +1,9 @@ package com.zmops.zeus.iot.server.receiver.tozabbix; import com.google.gson.Gson; - -import com.zmops.zeus.iot.server.library.module.ModuleManager; import com.zmops.zeus.iot.server.receiver.tozabbix.worker.ItemDataTransferWorker; -import com.zmops.zeus.iot.server.util.StringUtil; +import com.zmops.zeus.server.library.module.ModuleManager; +import com.zmops.zeus.server.library.util.StringUtil; import org.apache.camel.Endpoint; import org.apache.camel.Exchange; import org.apache.camel.Message; @@ -21,9 +20,9 @@ */ public class ZabbixTrapperProducer extends DefaultProducer { - private final ModuleManager moduleManager; + private final ModuleManager moduleManager; private final ItemDataTransferWorker itemDataTransferWorker; - private final ExecutorService itemValueThread = Executors.newFixedThreadPool(20); + private final ExecutorService itemValueThread = Executors.newFixedThreadPool(20); public ZabbixTrapperProducer(Endpoint endpoint, ModuleManager moduleManager) { diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/process/JsonToItemValueProcess.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/process/JsonToItemValueProcess.java index 4fb2e754..39fdd7dd 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/process/JsonToItemValueProcess.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/process/JsonToItemValueProcess.java @@ -1,7 +1,7 @@ package com.zmops.zeus.iot.server.receiver.tozabbix.process; import com.google.gson.Gson; -import com.zmops.zeus.iot.server.receiver.tozabbix.IOTDeviceValue; +import com.zmops.zeus.iot.server.receiver.tozabbix.IoTDeviceValue; import com.zmops.zeus.iot.server.receiver.tozabbix.ItemValue; import org.apache.camel.Exchange; import org.apache.camel.Message; @@ -29,7 +29,7 @@ public void process(Exchange exchange) throws Exception { String inputContext = this.analysisMessage(bodyStream); - IOTDeviceValue iotValue = gson.fromJson(inputContext, IOTDeviceValue.class); + IoTDeviceValue iotValue = gson.fromJson(inputContext, IoTDeviceValue.class); List itemValueList = new ArrayList<>(); diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/worker/AbstractWorker.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/worker/AbstractWorker.java index d7b50be6..b7c7fd9c 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/worker/AbstractWorker.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/worker/AbstractWorker.java @@ -18,7 +18,7 @@ package com.zmops.zeus.iot.server.receiver.tozabbix.worker; -import com.zmops.zeus.iot.server.library.module.ModuleDefineHolder; +import com.zmops.zeus.server.library.module.ModuleDefineHolder; import lombok.Getter; diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/worker/ItemDataTransferWorker.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/worker/ItemDataTransferWorker.java index 6661e9c8..a3296d50 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/worker/ItemDataTransferWorker.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/worker/ItemDataTransferWorker.java @@ -1,11 +1,6 @@ package com.zmops.zeus.iot.server.receiver.tozabbix.worker; import com.google.gson.Gson; -import com.zmops.zeus.iot.server.datacarrier.DataCarrier; -import com.zmops.zeus.iot.server.datacarrier.consumer.BulkConsumePool; -import com.zmops.zeus.iot.server.datacarrier.consumer.ConsumerPoolFactory; -import com.zmops.zeus.iot.server.datacarrier.consumer.IConsumer; -import com.zmops.zeus.iot.server.library.module.ModuleManager; import com.zmops.zeus.iot.server.receiver.tozabbix.ItemValue; import com.zmops.zeus.iot.server.receiver.tozabbix.ZabbixTrapper; import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; @@ -14,6 +9,11 @@ import com.zmops.zeus.iot.server.telemetry.api.CounterMetrics; import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; +import com.zmops.zeus.server.datacarrier.DataCarrier; +import com.zmops.zeus.server.datacarrier.consumer.BulkConsumePool; +import com.zmops.zeus.server.datacarrier.consumer.ConsumerPoolFactory; +import com.zmops.zeus.server.datacarrier.consumer.IConsumer; +import com.zmops.zeus.server.library.module.ModuleManager; import lombok.extern.slf4j.Slf4j; import java.io.IOException; @@ -31,8 +31,8 @@ public class ItemDataTransferWorker extends TransferWorker { private final DataCarrier dataCarrier; - private final CounterMetrics iotDataTransferCounter; - private final Gson gson = new Gson(); + private final CounterMetrics iotDataTransferCounter; + private final Gson gson = new Gson(); public ItemDataTransferWorker(ModuleManager moduleManager) { super(moduleManager); diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/worker/TransferWorker.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/worker/TransferWorker.java index a2d835c2..444341e7 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/worker/TransferWorker.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/worker/TransferWorker.java @@ -19,8 +19,8 @@ package com.zmops.zeus.iot.server.receiver.tozabbix.worker; -import com.zmops.zeus.iot.server.library.module.ModuleDefineHolder; import com.zmops.zeus.iot.server.receiver.tozabbix.Item; +import com.zmops.zeus.server.library.module.ModuleDefineHolder; import lombok.extern.slf4j.Slf4j; import java.util.Collection; diff --git a/iot-server/server-camel-receiver/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine b/iot-server/server-camel-receiver/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine similarity index 100% rename from iot-server/server-camel-receiver/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine rename to iot-server/server-camel-receiver/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine diff --git a/iot-server/server-camel-receiver/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-camel-receiver/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider similarity index 100% rename from iot-server/server-camel-receiver/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider rename to iot-server/server-camel-receiver/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider diff --git a/iot-server/server-library/library-client/pom.xml b/iot-server/server-client/pom.xml similarity index 87% rename from iot-server/server-library/library-client/pom.xml rename to iot-server/server-client/pom.xml index 11216847..5dc285fc 100644 --- a/iot-server/server-library/library-client/pom.xml +++ b/iot-server/server-client/pom.xml @@ -3,18 +3,24 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - server-library + iot-server com.zmops 1.0-beta 4.0.0 - library-client + server-client + + + 8 + 8 + + com.zmops library-util - 1.0-beta + 1.0-SNAPSHOT com.zaxxer @@ -23,9 +29,4 @@ - - 8 - 8 - - \ No newline at end of file diff --git a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/Client.java b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/Client.java similarity index 94% rename from iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/Client.java rename to iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/Client.java index d65ad5f3..60d0f920 100644 --- a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/Client.java +++ b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/Client.java @@ -16,7 +16,7 @@ * */ -package com.zmops.zeus.iot.server.library.client; +package com.zmops.zeus.iot.server.client; import java.io.IOException; diff --git a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/ClientException.java b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/ClientException.java similarity index 95% rename from iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/ClientException.java rename to iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/ClientException.java index 3b90fb73..f9a93279 100644 --- a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/ClientException.java +++ b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/ClientException.java @@ -16,7 +16,7 @@ * */ -package com.zmops.zeus.iot.server.library.client; +package com.zmops.zeus.iot.server.client; public abstract class ClientException extends Exception { public ClientException(String message) { diff --git a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/healthcheck/DelegatedHealthChecker.java b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/healthcheck/DelegatedHealthChecker.java similarity index 92% rename from iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/healthcheck/DelegatedHealthChecker.java rename to iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/healthcheck/DelegatedHealthChecker.java index 7723fdcf..7f889116 100644 --- a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/healthcheck/DelegatedHealthChecker.java +++ b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/healthcheck/DelegatedHealthChecker.java @@ -16,10 +16,10 @@ * */ -package com.zmops.zeus.iot.server.library.client.healthcheck; +package com.zmops.zeus.iot.server.client.healthcheck; -import com.zmops.zeus.iot.server.library.util.HealthChecker; +import com.zmops.zeus.server.library.util.HealthChecker; import java.util.Optional; import java.util.concurrent.atomic.AtomicReference; diff --git a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/healthcheck/HealthCheckable.java b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/healthcheck/HealthCheckable.java similarity index 90% rename from iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/healthcheck/HealthCheckable.java rename to iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/healthcheck/HealthCheckable.java index 043eebe9..651a5134 100644 --- a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/healthcheck/HealthCheckable.java +++ b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/healthcheck/HealthCheckable.java @@ -16,9 +16,9 @@ * */ -package com.zmops.zeus.iot.server.library.client.healthcheck; +package com.zmops.zeus.iot.server.client.healthcheck; -import com.zmops.zeus.iot.server.library.util.HealthChecker; +import com.zmops.zeus.server.library.util.HealthChecker; /** * HealthCheckable indicate the client has the capacity of health check and need to register healthChecker. diff --git a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/JDBCClientException.java b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/jdbc/JDBCClientException.java similarity index 95% rename from iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/JDBCClientException.java rename to iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/jdbc/JDBCClientException.java index 4c8866f5..d85b2382 100644 --- a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/JDBCClientException.java +++ b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/jdbc/JDBCClientException.java @@ -16,7 +16,7 @@ * */ -package com.zmops.zeus.iot.server.library.client.jdbc; +package com.zmops.zeus.iot.server.client.jdbc; import java.io.IOException; diff --git a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/hikaricp/JDBCHikariCPClient.java b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/jdbc/hikaricp/JDBCHikariCPClient.java similarity index 87% rename from iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/hikaricp/JDBCHikariCPClient.java rename to iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/jdbc/hikaricp/JDBCHikariCPClient.java index 129821ac..3615e779 100644 --- a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/jdbc/hikaricp/JDBCHikariCPClient.java +++ b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/jdbc/hikaricp/JDBCHikariCPClient.java @@ -16,16 +16,16 @@ * */ -package com.zmops.zeus.iot.server.library.client.jdbc.hikaricp; +package com.zmops.zeus.iot.server.client.jdbc.hikaricp; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; -import com.zmops.zeus.iot.server.library.client.Client; -import com.zmops.zeus.iot.server.library.client.healthcheck.DelegatedHealthChecker; -import com.zmops.zeus.iot.server.library.client.healthcheck.HealthCheckable; -import com.zmops.zeus.iot.server.library.client.jdbc.JDBCClientException; -import com.zmops.zeus.iot.server.library.util.HealthChecker; +import com.zmops.zeus.iot.server.client.Client; +import com.zmops.zeus.iot.server.client.healthcheck.DelegatedHealthChecker; +import com.zmops.zeus.iot.server.client.healthcheck.HealthCheckable; +import com.zmops.zeus.iot.server.client.jdbc.JDBCClientException; +import com.zmops.zeus.server.library.util.HealthChecker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,12 +43,7 @@ public class JDBCHikariCPClient implements Client, HealthCheckable { private HikariDataSource dataSource; public JDBCHikariCPClient(Properties properties) { - hikariConfig = new HikariConfig(); - hikariConfig.setJdbcUrl(properties.getProperty("dataSource.url")); - hikariConfig.setUsername(properties.getProperty("dataSource.user")); - hikariConfig.setPassword(properties.getProperty("dataSource.password")); -// hikariConfig.setConnectionTestQuery("select server_status()"); - + hikariConfig = new HikariConfig(properties); this.healthChecker = new DelegatedHealthChecker(); } diff --git a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/request/InsertRequest.java b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/request/InsertRequest.java similarity index 93% rename from iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/request/InsertRequest.java rename to iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/request/InsertRequest.java index 720db6a7..4d48f0c7 100644 --- a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/request/InsertRequest.java +++ b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/request/InsertRequest.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.library.client.request; +package com.zmops.zeus.iot.server.client.request; public interface InsertRequest extends PrepareRequest { } diff --git a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/request/PrepareRequest.java b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/request/PrepareRequest.java similarity index 93% rename from iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/request/PrepareRequest.java rename to iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/request/PrepareRequest.java index f9a6a368..d608d264 100644 --- a/iot-server/server-library/library-client/src/main/java/com/zmops/zeus/iot/server/library/client/request/PrepareRequest.java +++ b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/request/PrepareRequest.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.zmops.zeus.iot.server.library.client.request; +package com.zmops.zeus.iot.server.client.request; public interface PrepareRequest { } diff --git a/iot-server/server-core/pom.xml b/iot-server/server-core/pom.xml index 48f3c6b2..9145b57a 100644 --- a/iot-server/server-core/pom.xml +++ b/iot-server/server-core/pom.xml @@ -14,7 +14,7 @@ com.zmops library-module - 1.0-beta + 1.0-SNAPSHOT com.zmops @@ -28,29 +28,16 @@ com.zmops - library-server - 1.0-beta - - - com.zmops - library-client - 1.0-beta - - - com.zmops - iot-datacarrier - 1.0-beta - - - com.zmops - iot-eventbus - 1.0-beta + zeus-server-jetty + 1.0-SNAPSHOT + com.zmops - server-action - 1.0-beta + toolkit-datacarrier + 1.0-SNAPSHOT + com.zmops server-camel-receiver @@ -60,7 +47,6 @@ com.zmops server-localdb 1.0-beta - compile diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModule.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModule.java index de83455f..cc396cd4 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModule.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModule.java @@ -1,8 +1,6 @@ package com.zmops.zeus.iot.server.core; -import com.zmops.zeus.iot.server.core.eventbus.EventBusService; -import com.zmops.zeus.iot.server.core.server.JettyHandlerRegister; -import com.zmops.zeus.iot.server.library.module.ModuleDefine; +import com.zmops.zeus.server.library.module.ModuleDefine; import java.util.ArrayList; import java.util.List; @@ -21,8 +19,6 @@ public CoreModule() { @Override public Class[] services() { List> classes = new ArrayList<>(); - classes.add(JettyHandlerRegister.class); - classes.add(EventBusService.class); return classes.toArray(new Class[]{}); } } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java index 50e2ff39..24da2f6b 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java @@ -1,6 +1,6 @@ package com.zmops.zeus.iot.server.core; -import com.zmops.zeus.iot.server.library.module.ModuleConfig; +import com.zmops.zeus.server.library.module.ModuleConfig; import lombok.Getter; import lombok.Setter; diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java index 37566e92..2266a7e1 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java @@ -1,26 +1,13 @@ package com.zmops.zeus.iot.server.core; -import com.zmops.zeus.iot.server.action.ActionRouteIdentifier; -import com.zmops.zeus.iot.server.action.HelloWorldAction; import com.zmops.zeus.iot.server.core.analysis.StreamAnnotationListener; import com.zmops.zeus.iot.server.core.annotation.AnnotationScan; -import com.zmops.zeus.iot.server.core.eventbus.EventBusService; -import com.zmops.zeus.iot.server.core.server.JettyHandlerRegister; -import com.zmops.zeus.iot.server.core.server.JettyHandlerRegisterImpl; -import com.zmops.zeus.iot.server.core.servlet.CamelReceiverRouteHandler; -import com.zmops.zeus.iot.server.core.servlet.DataTransferHandler; -import com.zmops.zeus.iot.server.core.servlet.DeviceTriggerActionHandler; -import com.zmops.zeus.iot.server.core.servlet.HttpItemTrapperHandler; import com.zmops.zeus.iot.server.core.storage.StorageException; -import com.zmops.zeus.iot.server.eventbus.core.EventControllerFactory; -import com.zmops.zeus.iot.server.eventbus.thread.ThreadPoolFactory; -import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadCustomization; -import com.zmops.zeus.iot.server.eventbus.thread.entity.ThreadParameter; -import com.zmops.zeus.iot.server.library.module.*; -import com.zmops.zeus.iot.server.library.server.jetty.JettyServer; -import com.zmops.zeus.iot.server.library.server.jetty.JettyServerConfig; import com.zmops.zeus.iot.server.receiver.module.CamelReceiverModule; import com.zmops.zeus.iot.server.telemetry.TelemetryModule; +import com.zmops.zeus.server.jetty.JettyServer; +import com.zmops.zeus.server.jetty.JettyServerConfig; +import com.zmops.zeus.server.library.module.*; import java.io.IOException; @@ -31,9 +18,7 @@ public class CoreModuleProvider extends ModuleProvider { private final CoreModuleConfig moduleConfig; - private JettyServer jettyServer; - private ThreadPoolFactory threadPoolFactory; - private EventControllerFactory eventControllerFactory; + private JettyServer jettyServer; private final AnnotationScan annotationScan; @@ -63,9 +48,6 @@ public ModuleConfig createConfigBeanIfAbsent() { @Override public void prepare() throws ServiceNotProvidedException, ModuleStartException { - threadPoolFactory = new ThreadPoolFactory(new ThreadCustomization(), new ThreadParameter()); - eventControllerFactory = new EventControllerFactory(threadPoolFactory); - annotationScan.registerListener(new StreamAnnotationListener(getManager())); JettyServerConfig jettyServerConfig = JettyServerConfig.builder() @@ -84,8 +66,8 @@ public void prepare() throws ServiceNotProvidedException, ModuleStartException { jettyServer = new JettyServer(jettyServerConfig); jettyServer.initialize(); - this.registerServiceImplementation(JettyHandlerRegister.class, new JettyHandlerRegisterImpl(jettyServer)); - this.registerServiceImplementation(EventBusService.class, new EventBusService(eventControllerFactory)); + jettyServer.setFilterInitParameter("configClass", "com.zmops.zeus.iot.web.config.IoTConfig"); + } @Override @@ -98,7 +80,7 @@ public void start() throws ServiceNotProvidedException, ModuleStartException { } public void shutdown() { - threadPoolFactory.shutdown(); + } @Override @@ -110,16 +92,6 @@ public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleSta throw new ModuleStartException(e.getMessage(), e); } - JettyHandlerRegister service = getManager().find(CoreModule.NAME).provider().getService(JettyHandlerRegister.class); - service.addHandler(new HttpItemTrapperHandler()); - service.addHandler(new DeviceTriggerActionHandler(getManager())); - service.addHandler(new DataTransferHandler()); - service.addHandler(new CamelReceiverRouteHandler(getManager())); - - - // ### 可以自定义添加 Action 的动作异步处理,指定 ID - eventControllerFactory.getAsyncController(ActionRouteIdentifier.helloworld).register(new HelloWorldAction()); - } @Override diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamAnnotationListener.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamAnnotationListener.java index de67faea..0570e515 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamAnnotationListener.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamAnnotationListener.java @@ -4,7 +4,7 @@ import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; import com.zmops.zeus.iot.server.core.annotation.AnnotationListener; import com.zmops.zeus.iot.server.core.storage.StorageException; -import com.zmops.zeus.iot.server.library.module.ModuleDefineHolder; +import com.zmops.zeus.server.library.module.ModuleDefineHolder; import java.lang.annotation.Annotation; @@ -25,6 +25,7 @@ public Class annotation() { } @Override + @SuppressWarnings("unchecked") public void notify(Class aClass) throws StorageException { if (aClass.isAnnotationPresent(Stream.class)) { Stream stream = (Stream) aClass.getAnnotation(Stream.class); diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordPersistentWorker.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordPersistentWorker.java index bdf393de..81c5a93f 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordPersistentWorker.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordPersistentWorker.java @@ -6,8 +6,8 @@ import com.zmops.zeus.iot.server.core.storage.StorageModule; import com.zmops.zeus.iot.server.core.storage.model.Model; import com.zmops.zeus.iot.server.core.worker.AbstractWorker; -import com.zmops.zeus.iot.server.library.client.request.InsertRequest; -import com.zmops.zeus.iot.server.library.module.ModuleDefineHolder; +import com.zmops.zeus.iot.server.client.request.InsertRequest; +import com.zmops.zeus.server.library.module.ModuleDefineHolder; import lombok.extern.slf4j.Slf4j; import java.io.IOException; diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordStreamProcessor.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordStreamProcessor.java index 8488a4e2..5708191d 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordStreamProcessor.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordStreamProcessor.java @@ -7,7 +7,7 @@ import com.zmops.zeus.iot.server.core.storage.StorageDAO; import com.zmops.zeus.iot.server.core.storage.StorageModule; import com.zmops.zeus.iot.server.core.storage.model.Model; -import com.zmops.zeus.iot.server.library.module.ModuleDefineHolder; +import com.zmops.zeus.server.library.module.ModuleDefineHolder; import java.util.HashMap; import java.util.Map; diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationScan.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationScan.java index c1ac3901..c979bbb8 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationScan.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationScan.java @@ -69,9 +69,10 @@ public void scan() throws IOException, StorageException { } } - private class AnnotationListenerCache { - private AnnotationListener listener; - private List> matchedClass; + private static class AnnotationListenerCache { + + private final AnnotationListener listener; + private final List> matchedClass; private AnnotationListenerCache(AnnotationListener listener) { this.listener = listener; diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/eventbus/EventBusService.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/eventbus/EventBusService.java deleted file mode 100644 index f7e4b7ae..00000000 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/eventbus/EventBusService.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.zmops.zeus.iot.server.core.eventbus; - -import com.zmops.zeus.iot.server.action.bean.ActionParam; -import com.zmops.zeus.iot.server.eventbus.core.EventControllerFactory; -import com.zmops.zeus.iot.server.library.module.Service; - -/** - * @author nantian created at 2021/8/24 0:12 - *

- * EventBus post service - */ -public class EventBusService implements Service { - - private final EventControllerFactory eventControllerFactory; - - public EventBusService(EventControllerFactory eventControllerFactory) { - this.eventControllerFactory = eventControllerFactory; - } - - public void postExecuteActionMsg(String identifier, ActionParam param) { - eventControllerFactory.getAsyncController(identifier).post(param); - } -} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/server/JettyHandlerRegister.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/server/JettyHandlerRegister.java deleted file mode 100644 index 322fd7da..00000000 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/server/JettyHandlerRegister.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.core.server; - -import com.zmops.zeus.iot.server.library.module.Service; -import com.zmops.zeus.iot.server.library.server.jetty.JettyHandler; - -public interface JettyHandlerRegister extends Service { - - void addHandler(JettyHandler serverHandler); -} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/server/JettyHandlerRegisterImpl.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/server/JettyHandlerRegisterImpl.java deleted file mode 100644 index 24709ad6..00000000 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/server/JettyHandlerRegisterImpl.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.core.server; - -import com.zmops.zeus.iot.server.library.server.jetty.JettyHandler; -import com.zmops.zeus.iot.server.library.server.jetty.JettyServer; - -public class JettyHandlerRegisterImpl implements JettyHandlerRegister { - - private final JettyServer server; - - public JettyHandlerRegisterImpl(JettyServer server) { - this.server = server; - } - - @Override - public void addHandler(JettyHandler serverHandler) { - server.addHandler(serverHandler); - } -} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/CamelReceiverRouteHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/CamelReceiverRouteHandler.java deleted file mode 100644 index 3aae183c..00000000 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/CamelReceiverRouteHandler.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.zmops.zeus.iot.server.core.servlet; - -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.zmops.zeus.iot.server.library.module.ModuleManager; -import com.zmops.zeus.iot.server.library.server.jetty.ArgumentsParseException; -import com.zmops.zeus.iot.server.library.server.jetty.JettyJsonHandler; -import com.zmops.zeus.iot.server.receiver.ProtocolAction; -import com.zmops.zeus.iot.server.receiver.ProtocolEnum; -import com.zmops.zeus.iot.server.receiver.module.CamelReceiverModule; -import com.zmops.zeus.iot.server.receiver.routes.*; -import com.zmops.zeus.iot.server.receiver.service.CamelContextHolderService; -import lombok.Getter; -import lombok.Setter; -import org.apache.camel.builder.RouteBuilder; - -import javax.servlet.http.HttpServletRequest; -import java.io.BufferedReader; -import java.io.IOException; -import java.util.Map; - -/** - * @author nantian created at 2021/10/23 21:38 - *

- * 动态创建 Camel 路由 Jetty 入口 - */ -public class CamelReceiverRouteHandler extends JettyJsonHandler { - - private final ModuleManager moduleManager; - - private final Gson gson = new Gson(); - - public CamelReceiverRouteHandler(ModuleManager moduleManager) { - this.moduleManager = moduleManager; - } - - @Override - public String pathSpec() { - return "/camel/route"; - } - - @Override - protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException, IOException { - CamelContextHolderService camelService = moduleManager.find(CamelReceiverModule.NAME).provider().getService(CamelContextHolderService.class); - - String request = getJsonBody(req); - ProtocolService protocol = gson.fromJson(request, ProtocolService.class); - - String routeId = protocol.getRouteId(); - Map options = protocol.getOptions(); - - if (protocol.getAction() != null) { - switch (protocol.getAction()) { - case start: - camelService.routeStartUp(routeId); - break; - case stop: - camelService.routeShutDown(routeId); - break; - default: - break; - } - - return null; - } - - - RouteBuilder route = null; - switch (protocol.getProtocol()) { - case HttpServer: - route = new HttpRouteBuilder(routeId, options); - break; - case MqttClient: - route = new MqttClientRouteBuilder(routeId, options); - break; - case TcpServer: - route = new TcpServerRouteBuilder(routeId, options); - break; - case UdpServer: - route = new UdpServerRouteBuilder(routeId, options); - break; - case CoapServer: - route = new CoapServerRouteBuilder(routeId, options); - break; - case WebSocketServer: - route = new WebSocketServerRouteBuilder(routeId, options); - break; - default: - break; - } - - if (route != null) { - camelService.addRoutes(route); - } - - return null; - } - - - public String getJsonBody(HttpServletRequest req) throws IOException { - StringBuilder stringBuffer = new StringBuilder(); - String line = null; - BufferedReader reader = req.getReader(); - while ((line = reader.readLine()) != null) { - stringBuffer.append(line); - } - return stringBuffer.toString(); - } - - @Getter - @Setter - static class ProtocolService { - - private String routeId; - - private ProtocolEnum protocol; - - private ProtocolAction action; - - private Map options; - } -} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java deleted file mode 100644 index 5279c7b2..00000000 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DataTransferHandler.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.zmops.zeus.iot.server.core.servlet; - -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.zmops.zeus.iot.server.core.analysis.manual.history.History; -import com.zmops.zeus.iot.server.core.analysis.manual.history.StrHistory; -import com.zmops.zeus.iot.server.core.analysis.manual.history.TextHistory; -import com.zmops.zeus.iot.server.core.analysis.manual.history.UIntHistory; -import com.zmops.zeus.iot.server.core.analysis.record.Record; -import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; -import com.zmops.zeus.iot.server.library.server.jetty.ArgumentsParseException; -import com.zmops.zeus.iot.server.library.server.jetty.JettyJsonHandler; -import lombok.Getter; -import lombok.Setter; - -import javax.servlet.http.HttpServletRequest; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.Map; -import java.util.zip.GZIPInputStream; - -/** - * @author nantian created at 2021/9/2 12:58 - *

- * 适用于 Logkit - */ -public class DataTransferHandler extends JettyJsonHandler { - - private final Gson gson = new Gson(); - - @Override - public String pathSpec() { - return "/zabbix/data-transfer"; - } - - /** - * 接收来自 zeus_transfer 数据, 写入时序库 - * - * @param req request - * @return NULL - * @throws ArgumentsParseException - * @throws IOException - */ - @Override - protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException, IOException { - GZIPInputStream gzin = new GZIPInputStream(req.getInputStream()); - BufferedReader reader = new BufferedReader(new InputStreamReader(gzin)); - - String line; - while ((line = reader.readLine()) != null) { - insert(line); - } - - return null; - } - - private void insert(String itemRecord) { - ItemValue itemValue = gson.fromJson(itemRecord, ItemValue.class); - - Record record; - - if (itemValue.getType() == 3) { //uint - record = new UIntHistory(); - } else if (itemValue.getType() == 0) { //float - record = new History(); - } else if (itemValue.getType() == 4) { //text - record = new TextHistory(); - } else { - record = new StrHistory(); - - } - - record.setItemid(itemValue.itemid); - record.setValue(itemValue.getHost().get("host"), itemValue.value, itemValue.getTimestamp()); - - RecordStreamProcessor.getInstance().in(record); - } - - - @Setter - @Getter - static class ItemValue { - - private Integer type; - - private String name; - - private Long clock; - - private Integer itemid; - - private Long ns; - - private String value; - - private Map host; - - public Long getTimestamp() { - return Long.valueOf(clock + String.format("%09d", ns).substring(0, 3)); - } - } -} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java deleted file mode 100644 index 83732bae..00000000 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.zmops.zeus.iot.server.core.servlet; - -import com.google.gson.JsonElement; -import com.zmops.zeus.iot.server.action.ActionRouteIdentifier; -import com.zmops.zeus.iot.server.action.bean.ActionParam; -import com.zmops.zeus.iot.server.core.CoreModule; -import com.zmops.zeus.iot.server.core.eventbus.EventBusService; -import com.zmops.zeus.iot.server.library.module.ModuleManager; -import com.zmops.zeus.iot.server.library.server.jetty.ArgumentsParseException; -import com.zmops.zeus.iot.server.library.server.jetty.JettyJsonHandler; -import lombok.extern.slf4j.Slf4j; - -import javax.servlet.http.HttpServletRequest; -import java.io.BufferedReader; -import java.io.IOException; - -/** - * @author nantian created at 2021/8/20 1:04 - *

- * 设备 告警规则 触发动作,Http 统一入口 - */ -@Slf4j -public class DeviceTriggerActionHandler extends JettyJsonHandler { - - private final ModuleManager moduleManager; - - public DeviceTriggerActionHandler(ModuleManager moduleManager) { - this.moduleManager = moduleManager; - } - - @Override - public String pathSpec() { - return "/device/action/exec"; - } - - - /** - * 动作触发Http入口,可在设备 上面设置 宏 定义,动态传入 identifier - * - * @param req - * @return JsonElement - * @throws ArgumentsParseException ex - * @throws IOException ex - */ - @Override - protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException, IOException { - - String request = getJsonBody(req); - log.info("action command : {}", request); - - EventBusService eventBusService = moduleManager.find(CoreModule.NAME).provider().getService(EventBusService.class); - - ActionParam actionParam = new ActionParam(); - actionParam.setTriggerDevice("10084"); - - eventBusService.postExecuteActionMsg(ActionRouteIdentifier.helloworld, actionParam); - - return null; - } - - - public String getJsonBody(HttpServletRequest req) throws IOException { - StringBuffer stringBuffer = new StringBuffer(); - String line = null; - BufferedReader reader = req.getReader(); - while ((line = reader.readLine()) != null) { - stringBuffer.append(line); - } - return stringBuffer.toString(); - } -} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/HttpItemTrapperHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/HttpItemTrapperHandler.java deleted file mode 100644 index 95279b73..00000000 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/HttpItemTrapperHandler.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.zmops.zeus.iot.server.core.servlet; - -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.zmops.zeus.iot.server.library.server.jetty.ArgumentsParseException; -import com.zmops.zeus.iot.server.library.server.jetty.JettyJsonHandler; - -import javax.servlet.http.HttpServletRequest; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; - -/** - * @author nantian created at 2021/8/20 0:51 - *

- * Http Trapper 的方式给指定设备的指定属性 发送数据,方便手动调试 - */ -public class HttpItemTrapperHandler extends JettyJsonHandler { - - private final Gson gson = new Gson(); - - @Override - public String pathSpec() { - return "/device/attr/send"; - } - - @Override - protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException, IOException { - BufferedReader reader = new BufferedReader(new InputStreamReader(req.getInputStream())); - - String line; - StringBuilder request = new StringBuilder(); - while ((line = reader.readLine()) != null) { - request.append(line); - } - - JsonObject requestJson = gson.fromJson(request.toString(), JsonObject.class); - - return requestJson; - } -} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/DAO.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/DAO.java index 03fba9b8..da60f993 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/DAO.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/DAO.java @@ -19,7 +19,7 @@ package com.zmops.zeus.iot.server.core.storage; -import com.zmops.zeus.iot.server.library.module.Service; +import com.zmops.zeus.server.library.module.Service; /** * A specific interface for storage layer services. diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IBatchDAO.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IBatchDAO.java index 5c1c6f42..a7d63e27 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IBatchDAO.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IBatchDAO.java @@ -19,8 +19,8 @@ package com.zmops.zeus.iot.server.core.storage; -import com.zmops.zeus.iot.server.library.client.request.InsertRequest; -import com.zmops.zeus.iot.server.library.client.request.PrepareRequest; +import com.zmops.zeus.iot.server.client.request.InsertRequest; +import com.zmops.zeus.iot.server.client.request.PrepareRequest; import java.util.List; diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IRecordDAO.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IRecordDAO.java index 5aec851c..02850810 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IRecordDAO.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IRecordDAO.java @@ -21,7 +21,7 @@ import com.zmops.zeus.iot.server.core.analysis.record.Record; import com.zmops.zeus.iot.server.core.storage.model.Model; -import com.zmops.zeus.iot.server.library.client.request.InsertRequest; +import com.zmops.zeus.iot.server.client.request.InsertRequest; import java.io.IOException; diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageDAO.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageDAO.java index bbc21ff7..5307a0fe 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageDAO.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageDAO.java @@ -18,7 +18,8 @@ package com.zmops.zeus.iot.server.core.storage; -import com.zmops.zeus.iot.server.library.module.Service; + +import com.zmops.zeus.server.library.module.Service; /** * StorageDAO is a DAO factory for storage layer. Provide the implementations of typical DAO interfaces. diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageModule.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageModule.java index 8a8bc83a..6a7727ce 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageModule.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageModule.java @@ -18,7 +18,8 @@ package com.zmops.zeus.iot.server.core.storage; -import com.zmops.zeus.iot.server.library.module.ModuleDefine; + +import com.zmops.zeus.server.library.module.ModuleDefine; /** * StorageModule provides the capabilities(services) to interact with the database. With different databases, this diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/AbstractWorker.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/AbstractWorker.java index 0536f05a..3b25872b 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/AbstractWorker.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/AbstractWorker.java @@ -18,7 +18,7 @@ package com.zmops.zeus.iot.server.core.worker; -import com.zmops.zeus.iot.server.library.module.ModuleDefineHolder; +import com.zmops.zeus.server.library.module.ModuleDefineHolder; import lombok.Getter; diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/ItemDataTransferWorker.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/ItemDataTransferWorker.java index 6008c1a8..9024fd78 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/ItemDataTransferWorker.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/ItemDataTransferWorker.java @@ -4,17 +4,17 @@ import com.zmops.zeus.iot.server.core.UnexpectedException; import com.zmops.zeus.iot.server.core.worker.data.ItemValue; import com.zmops.zeus.iot.server.core.worker.data.ZabbixTrapper; -import com.zmops.zeus.iot.server.datacarrier.DataCarrier; -import com.zmops.zeus.iot.server.datacarrier.consumer.BulkConsumePool; -import com.zmops.zeus.iot.server.datacarrier.consumer.ConsumerPoolFactory; -import com.zmops.zeus.iot.server.datacarrier.consumer.IConsumer; -import com.zmops.zeus.iot.server.library.module.ModuleManager; import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; import com.zmops.zeus.iot.server.sender.service.ZabbixSenderService; import com.zmops.zeus.iot.server.telemetry.TelemetryModule; import com.zmops.zeus.iot.server.telemetry.api.CounterMetrics; import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; +import com.zmops.zeus.server.datacarrier.DataCarrier; +import com.zmops.zeus.server.datacarrier.consumer.BulkConsumePool; +import com.zmops.zeus.server.datacarrier.consumer.ConsumerPoolFactory; +import com.zmops.zeus.server.datacarrier.consumer.IConsumer; +import com.zmops.zeus.server.library.module.ModuleManager; import lombok.extern.slf4j.Slf4j; import java.io.IOException; diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/TransferWorker.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/TransferWorker.java index a652611f..4fbba12d 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/TransferWorker.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/TransferWorker.java @@ -19,7 +19,7 @@ package com.zmops.zeus.iot.server.core.worker; import com.zmops.zeus.iot.server.core.worker.data.Item; -import com.zmops.zeus.iot.server.library.module.ModuleDefineHolder; +import com.zmops.zeus.server.library.module.ModuleDefineHolder; import lombok.extern.slf4j.Slf4j; import java.util.Collection; diff --git a/iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine b/iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine similarity index 100% rename from iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine rename to iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine diff --git a/iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider similarity index 100% rename from iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider rename to iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider diff --git a/iot-server/server-health-checker/pom.xml b/iot-server/server-health-checker/pom.xml index 99a1701e..5c868de9 100644 --- a/iot-server/server-health-checker/pom.xml +++ b/iot-server/server-health-checker/pom.xml @@ -15,7 +15,7 @@ com.zmops library-module - 1.0-beta + 1.0-SNAPSHOT compile diff --git a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/module/HealthCheckerModule.java b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/module/HealthCheckerModule.java index 7a9da970..1dbc5dd8 100644 --- a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/module/HealthCheckerModule.java +++ b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/module/HealthCheckerModule.java @@ -19,7 +19,7 @@ package com.zmops.zeus.iot.server.health.checker.module; import com.zmops.zeus.iot.server.health.checker.provider.HealthQueryService; -import com.zmops.zeus.iot.server.library.module.ModuleDefine; +import com.zmops.zeus.server.library.module.ModuleDefine; /** * HealthCheckerModule intends to provide a channel to expose the healthy status of modules to external. diff --git a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerConfig.java b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerConfig.java index 1b15ef8b..84c30b82 100644 --- a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerConfig.java +++ b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerConfig.java @@ -18,7 +18,7 @@ package com.zmops.zeus.iot.server.health.checker.provider; -import com.zmops.zeus.iot.server.library.module.ModuleConfig; +import com.zmops.zeus.server.library.module.ModuleConfig; import lombok.Getter; diff --git a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerProvider.java b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerProvider.java index 41ea6e26..54aec501 100644 --- a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerProvider.java +++ b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerProvider.java @@ -20,10 +20,10 @@ import com.google.common.util.concurrent.AtomicDouble; import com.zmops.zeus.iot.server.health.checker.module.HealthCheckerModule; -import com.zmops.zeus.iot.server.library.module.*; import com.zmops.zeus.iot.server.telemetry.TelemetryModule; import com.zmops.zeus.iot.server.telemetry.api.MetricsCollector; import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; +import com.zmops.zeus.server.library.module.*; import io.vavr.collection.Stream; import lombok.extern.slf4j.Slf4j; diff --git a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthQueryService.java b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthQueryService.java index f64cedba..7db5b1e1 100644 --- a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthQueryService.java +++ b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthQueryService.java @@ -19,7 +19,7 @@ package com.zmops.zeus.iot.server.health.checker.provider; import com.google.common.util.concurrent.AtomicDouble; -import com.zmops.zeus.iot.server.library.module.Service; +import com.zmops.zeus.server.library.module.Service; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; diff --git a/iot-server/server-health-checker/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine b/iot-server/server-health-checker/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine similarity index 100% rename from iot-server/server-health-checker/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine rename to iot-server/server-health-checker/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine diff --git a/iot-server/server-health-checker/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-health-checker/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider similarity index 100% rename from iot-server/server-health-checker/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider rename to iot-server/server-health-checker/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider diff --git a/iot-server/server-library/library-module/pom.xml b/iot-server/server-library/library-module/pom.xml deleted file mode 100644 index 04d87d24..00000000 --- a/iot-server/server-library/library-module/pom.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - server-library - com.zmops - 1.0-beta - - 4.0.0 - - jar - - library-module - - - com.zmops - library-util - ${project.version} - compile - - - - - 8 - 8 - - - \ No newline at end of file diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ApplicationConfiguration.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ApplicationConfiguration.java deleted file mode 100644 index 0d205b67..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ApplicationConfiguration.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.module; - -import java.util.HashMap; -import java.util.Properties; - -/** - * Modulization configurations. The {@link ModuleManager} is going to start, lookup, start modules based on this. - */ -public class ApplicationConfiguration { - private HashMap modules = new HashMap<>(); - - public String[] moduleList() { - return modules.keySet().toArray(new String[0]); - } - - public ModuleConfiguration addModule(String moduleName) { - ModuleConfiguration newModule = new ModuleConfiguration(); - modules.put(moduleName, newModule); - return newModule; - } - - public boolean has(String moduleName) { - return modules.containsKey(moduleName); - } - - public ModuleConfiguration getModuleConfiguration(String name) { - return modules.get(name); - } - - /** - * The configurations about a certain module. - */ - public static class ModuleConfiguration { - private HashMap providers = new HashMap<>(); - - private ModuleConfiguration() { - } - - public Properties getProviderConfiguration(String name) { - return providers.get(name).getProperties(); - } - - public boolean has(String name) { - return providers.containsKey(name); - } - - public ModuleConfiguration addProviderConfiguration(String name, Properties properties) { - ProviderConfiguration newProvider = new ProviderConfiguration(properties); - providers.put(name, newProvider); - return this; - } - } - - /** - * The configuration about a certain provider of a module. - */ - public static class ProviderConfiguration { - private Properties properties; - - ProviderConfiguration(Properties properties) { - this.properties = properties; - } - - private Properties getProperties() { - return properties; - } - } -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/BootstrapFlow.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/BootstrapFlow.java deleted file mode 100644 index 2be6a541..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/BootstrapFlow.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.module; - -import com.zmops.zeus.iot.server.library.util.CollectionUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -/** - * 模块化依赖管理,被依赖模块要优先启动 - */ -class BootstrapFlow { - private static final Logger LOGGER = LoggerFactory.getLogger(BootstrapFlow.class); - - private Map loadedModules; - private List startupSequence; - - BootstrapFlow(Map loadedModules) throws CycleDependencyException, ModuleNotFoundException { - this.loadedModules = loadedModules; - startupSequence = new LinkedList<>(); - - makeSequence(); - } - - @SuppressWarnings("unchecked") - void start(ModuleManager moduleManager) throws ModuleNotFoundException, ServiceNotProvidedException, ModuleStartException { - for (ModuleProvider provider : startupSequence) { - LOGGER.info("start the provider {} in {} module.", provider.name(), provider.getModuleName()); - provider.requiredCheck(provider.getModule().services()); - provider.start(); - } - } - - void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { - for (ModuleProvider provider : startupSequence) { - provider.notifyAfterCompleted(); - } - } - - private void makeSequence() throws CycleDependencyException, ModuleNotFoundException { - List allProviders = new ArrayList<>(); - for (final ModuleDefine module : loadedModules.values()) { - String[] requiredModules = module.provider().requiredModules(); - if (requiredModules != null) { - for (String requiredModule : requiredModules) { - if (!loadedModules.containsKey(requiredModule)) { - throw new ModuleNotFoundException( - requiredModule + " module is required by " - + module.provider().getModuleName() + "." - + module.provider().name() + ", but not found."); - } - } - } - allProviders.add(module.provider()); - } - - do { - int numOfToBeSequenced = allProviders.size(); - for (int i = 0; i < allProviders.size(); i++) { - ModuleProvider provider = allProviders.get(i); - String[] requiredModules = provider.requiredModules(); - if (CollectionUtils.isNotEmpty(requiredModules)) { - boolean isAllRequiredModuleStarted = true; - for (String module : requiredModules) { - // find module in all ready existed startupSequence - boolean exist = false; - for (ModuleProvider moduleProvider : startupSequence) { - if (moduleProvider.getModuleName().equals(module)) { - exist = true; - break; - } - } - if (!exist) { - isAllRequiredModuleStarted = false; - break; - } - } - if (isAllRequiredModuleStarted) { - startupSequence.add(provider); - allProviders.remove(i); - i--; - } - } else { - startupSequence.add(provider); - allProviders.remove(i); - i--; - } - } - - if (numOfToBeSequenced == allProviders.size()) { - StringBuilder unSequencedProviders = new StringBuilder(); - allProviders.forEach(provider -> unSequencedProviders.append(provider.getModuleName()).append("[provider=").append(provider.getClass().getName()).append("]\n")); - if (unSequencedProviders.length() > 0) { - throw new CycleDependencyException("Exist cycle module dependencies in \n" + unSequencedProviders.substring(0, unSequencedProviders.length() - 1)); - } - } - } - while (allProviders.size() != 0); - } -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/CycleDependencyException.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/CycleDependencyException.java deleted file mode 100644 index 8f7e2aa9..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/CycleDependencyException.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.module; - -public class CycleDependencyException extends RuntimeException { - public CycleDependencyException(String message) { - super(message); - } -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/DuplicateProviderException.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/DuplicateProviderException.java deleted file mode 100644 index 221f5a65..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/DuplicateProviderException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.module; - - -/** - * @author nantian 重复的 Provider - */ -public class DuplicateProviderException extends RuntimeException { - - public DuplicateProviderException(String message) { - super(message); - } -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleConfig.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleConfig.java deleted file mode 100644 index bd5f8bec..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleConfig.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.module; - -public abstract class ModuleConfig { -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleConfigException.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleConfigException.java deleted file mode 100644 index 7c03bba6..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleConfigException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.module; - -public class ModuleConfigException extends Exception { - - public ModuleConfigException(String message) { - super(message); - } - - public ModuleConfigException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefine.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefine.java deleted file mode 100644 index 25252b37..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefine.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.module; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Field; -import java.util.Enumeration; -import java.util.Properties; -import java.util.ServiceLoader; - -/** - * A module definition. - * 模块定义,需要被继承,实现模块化定义 - *

- * TODO 基于页面的配置,实现模块化动态的加载 - */ -public abstract class ModuleDefine implements ModuleProviderHolder { - - private static final Logger LOGGER = LoggerFactory.getLogger(ModuleDefine.class); - - private ModuleProvider loadedProvider = null; - - private final String name; - - public ModuleDefine(String name) { - this.name = name; - } - - /** - * @return the module name - */ - public final String name() { - return name; - } - - /** - * @return the {@link Service} provided by this module. - */ - public abstract Class[] services(); - - /** - * Run the prepare stage for the module, including finding all potential providers, and asking them to prepare. - * - * @param moduleManager of this module - * @param configuration of this module - * @throws ProviderNotFoundException when even don't find a single one providers. - */ - void prepare(ModuleManager moduleManager, ApplicationConfiguration.ModuleConfiguration configuration, - ServiceLoader moduleProviderLoader) throws ProviderNotFoundException, ServiceNotProvidedException, ModuleConfigException, ModuleStartException { - for (ModuleProvider provider : moduleProviderLoader) { - if (!configuration.has(provider.name())) { - continue; - } - - if (provider.module().equals(getClass())) { - if (loadedProvider == null) { - loadedProvider = provider; - loadedProvider.setManager(moduleManager); - loadedProvider.setModuleDefine(this); - } else { - throw new DuplicateProviderException(this.name() + " module has one " + loadedProvider.name() + "[" + loadedProvider - .getClass() - .getName() + "] provider already, " + provider.name() + "[" + provider.getClass() - .getName() + "] is defined as 2nd provider."); - } - } - - } - - if (loadedProvider == null) { - throw new ProviderNotFoundException(this.name() + " module no provider found."); - } - - LOGGER.info("Prepare the {} provider in {} module.", loadedProvider.name(), this.name()); - try { - copyProperties(loadedProvider.createConfigBeanIfAbsent(), configuration.getProviderConfiguration(loadedProvider.name()), this.name(), loadedProvider.name()); - } catch (IllegalAccessException e) { - throw new ModuleConfigException(this.name() + " module config transport to config bean failure.", e); - } - loadedProvider.prepare(); - } - - private void copyProperties(ModuleConfig dest, Properties src, String moduleName, - String providerName) throws IllegalAccessException { - if (dest == null) { - return; - } - Enumeration propertyNames = src.propertyNames(); - while (propertyNames.hasMoreElements()) { - String propertyName = (String) propertyNames.nextElement(); - Class destClass = dest.getClass(); - try { - Field field = getDeclaredField(destClass, propertyName); - field.setAccessible(true); - field.set(dest, src.get(propertyName)); - } catch (NoSuchFieldException e) { - LOGGER.warn(propertyName + " setting is not supported in " + providerName + " provider of " + moduleName + " module"); - } - } - } - - private Field getDeclaredField(Class destClass, String fieldName) throws NoSuchFieldException { - if (destClass != null) { - Field[] fields = destClass.getDeclaredFields(); - for (Field field : fields) { - if (field.getName().equals(fieldName)) { - return field; - } - } - return getDeclaredField(destClass.getSuperclass(), fieldName); - } - - throw new NoSuchFieldException(); - } - - @Override - public final ModuleProvider provider() throws DuplicateProviderException, ProviderNotFoundException { - if (loadedProvider == null) { - throw new ProviderNotFoundException("There is no module provider in " + this.name() + " module!"); - } - - return loadedProvider; - } -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefineHolder.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefineHolder.java deleted file mode 100644 index 3021a6d2..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefineHolder.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.module; - -public interface ModuleDefineHolder { - - boolean has(String moduleName); - - ModuleProviderHolder find(String moduleName) throws ModuleNotFoundRuntimeException; -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleManager.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleManager.java deleted file mode 100644 index b12db3bb..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleManager.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.module; - -import java.util.*; - -/** - * The ModuleManager takes charge of all {@link ModuleDefine}s in collector. - *

- * 实现模块之间的 Service 发布调用 - * TODO 使用 google guice @Inject 实现 - */ -public class ModuleManager implements ModuleDefineHolder { - private boolean isInPrepareStage = true; - private final Map loadedModules = new HashMap<>(); - - /** - * Init the given modules - */ - public void init(ApplicationConfiguration applicationConfiguration) - throws ModuleNotFoundException, ProviderNotFoundException, ServiceNotProvidedException, CycleDependencyException, ModuleConfigException, ModuleStartException { - - String[] moduleNames = applicationConfiguration.moduleList(); - ServiceLoader moduleServiceLoader = ServiceLoader.load(ModuleDefine.class); - ServiceLoader moduleProviderLoader = ServiceLoader.load(ModuleProvider.class); - - HashSet moduleSet = new HashSet<>(Arrays.asList(moduleNames)); - for (ModuleDefine module : moduleServiceLoader) { - if (moduleSet.contains(module.name())) { - module.prepare(this, applicationConfiguration.getModuleConfiguration(module.name()), moduleProviderLoader); - loadedModules.put(module.name(), module); - moduleSet.remove(module.name()); - } - } - // Finish prepare stage - isInPrepareStage = false; - - if (moduleSet.size() > 0) { - throw new ModuleNotFoundException(moduleSet.toString() + " missing."); - } - - BootstrapFlow bootstrapFlow = new BootstrapFlow(loadedModules); - - bootstrapFlow.start(this); - bootstrapFlow.notifyAfterCompleted(); - } - - @Override - public boolean has(String moduleName) { - return loadedModules.get(moduleName) != null; - } - - @Override - public ModuleProviderHolder find(String moduleName) throws ModuleNotFoundRuntimeException { - assertPreparedStage(); - ModuleDefine module = loadedModules.get(moduleName); - if (module != null) - return module; - throw new ModuleNotFoundRuntimeException(moduleName + " missing."); - } - - private void assertPreparedStage() { - if (isInPrepareStage) { - throw new AssertionError("Still in preparing stage."); - } - } -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleNotFoundException.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleNotFoundException.java deleted file mode 100644 index bf06561b..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleNotFoundException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.module; - -public class ModuleNotFoundException extends Exception { - - public ModuleNotFoundException(Throwable cause) { - super(cause); - } - - public ModuleNotFoundException(String message) { - super(message); - } -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleNotFoundRuntimeException.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleNotFoundRuntimeException.java deleted file mode 100644 index a01cb99b..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleNotFoundRuntimeException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.module; - -public class ModuleNotFoundRuntimeException extends RuntimeException { - - public ModuleNotFoundRuntimeException(Throwable cause) { - super(cause); - } - - public ModuleNotFoundRuntimeException(String message) { - super(message); - } -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleProvider.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleProvider.java deleted file mode 100644 index c47f121b..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleProvider.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.module; - -import lombok.Setter; - -import java.util.HashMap; -import java.util.Map; - -/** - * The ModuleProvider is an implementation of a {@link ModuleDefine}. - *

- * And each moduleDefine can have one or more implementation, which depends on `application.yml` - */ -public abstract class ModuleProvider implements ModuleServiceHolder { - @Setter - private ModuleManager manager; - @Setter - private ModuleDefine moduleDefine; - private final Map, Service> services = new HashMap<>(); - - public ModuleProvider() { - } - - protected final ModuleManager getManager() { - return manager; - } - - /** - * @return the name of this provider. - */ - public abstract String name(); - - /** - * @return the moduleDefine name - */ - public abstract Class module(); - - /** - * - */ - public abstract ModuleConfig createConfigBeanIfAbsent(); - - /** - * In prepare stage, the moduleDefine should initialize things which are irrelative other modules. - */ - public abstract void prepare() throws ServiceNotProvidedException, ModuleStartException; - - /** - * In start stage, the moduleDefine has been ready for interop. - */ - public abstract void start() throws ServiceNotProvidedException, ModuleStartException; - - /** - * This callback executes after all modules start up successfully. - */ - public abstract void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException; - - /** - * @return moduleDefine names which does this moduleDefine require? - */ - public abstract String[] requiredModules(); - - /** - * Register an implementation for the service of this moduleDefine provider. - */ - @Override - public final void registerServiceImplementation(Class serviceType, Service service) throws ServiceNotProvidedException { - if (serviceType.isInstance(service)) { - this.services.put(serviceType, service); - } else { - throw new ServiceNotProvidedException(serviceType + " is not implemented by " + service); - } - } - - /** - * Make sure all required services have been implemented. - * - * @param requiredServices must be implemented by the moduleDefine. - * @throws ServiceNotProvidedException when exist unimplemented service. - */ - void requiredCheck(Class[] requiredServices) throws ServiceNotProvidedException { - if (requiredServices == null) - return; - - for (Class service : requiredServices) { - if (!services.containsKey(service)) { - throw new ServiceNotProvidedException("Service:" + service.getName() + " not provided"); - } - } - - if (requiredServices.length != services.size()) { - throw new ServiceNotProvidedException("The " + this.name() + " provider in " + moduleDefine.name() + " moduleDefine provide more service implementations than ModuleDefine requirements."); - } - } - - @Override - public @SuppressWarnings("unchecked") - T getService(Class serviceType) throws ServiceNotProvidedException { - Service serviceImpl = services.get(serviceType); - if (serviceImpl != null) { - return (T) serviceImpl; - } - - throw new ServiceNotProvidedException("Service " + serviceType.getName() + " should not be provided, based on moduleDefine define."); - } - - ModuleDefine getModule() { - return moduleDefine; - } - - String getModuleName() { - return moduleDefine.name(); - } -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleProviderHolder.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleProviderHolder.java deleted file mode 100644 index dc379f9c..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleProviderHolder.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.module; - -public interface ModuleProviderHolder { - - ModuleServiceHolder provider() throws DuplicateProviderException, ProviderNotFoundException; -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleServiceHolder.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleServiceHolder.java deleted file mode 100644 index d7a2865e..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleServiceHolder.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.module; - -public interface ModuleServiceHolder { - - void registerServiceImplementation(Class serviceType, Service service) throws ServiceNotProvidedException; - - T getService(Class serviceType) throws ServiceNotProvidedException; -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleStartException.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleStartException.java deleted file mode 100644 index 7d068a0c..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleStartException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.module; - -public class ModuleStartException extends Exception { - public ModuleStartException(String message) { - super(message); - } - - public ModuleStartException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ProviderNotFoundException.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ProviderNotFoundException.java deleted file mode 100644 index 8877a1a5..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ProviderNotFoundException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.module; - -public class ProviderNotFoundException extends RuntimeException { - - public ProviderNotFoundException(String message) { - super(message); - } - - public ProviderNotFoundException(Throwable e) { - super(e); - } -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/Service.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/Service.java deleted file mode 100644 index 4315fe5c..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/Service.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.module; - -/** - * The Service implementation is a service provided by its own modules. - *

- * And every {@link ModuleProvider} must provide all the given services of the {@link ModuleDefine}. - */ -public interface Service { -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ServiceNotProvidedException.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ServiceNotProvidedException.java deleted file mode 100644 index 31b189bb..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ServiceNotProvidedException.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.module; - -public class ServiceNotProvidedException extends RuntimeException { - public ServiceNotProvidedException(String message) { - super(message); - } -} diff --git a/iot-server/server-library/library-server/pom.xml b/iot-server/server-library/library-server/pom.xml deleted file mode 100644 index 9d91331a..00000000 --- a/iot-server/server-library/library-server/pom.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - server-library - com.zmops - 1.0-beta - - 4.0.0 - - library-server - - - 8 - 8 - 9.4.40.v20210413 - - - - - com.zmops - library-util - 1.0-beta - - - org.eclipse.jetty - jetty-server - ${jetty.version} - - - org.eclipse.jetty - jetty-servlet - ${jetty.version} - - - - \ No newline at end of file diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/Server.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/Server.java deleted file mode 100644 index 2e7a465d..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/Server.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.server; - -public interface Server { - - String hostPort(); - - String serverClassify(); - - void initialize(); - - void start() throws ServerException; - - boolean isSSLOpen(); - - boolean isStatusEqual(Server target); -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ServerException.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ServerException.java deleted file mode 100644 index 1f7e15ec..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ServerException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.server; - -public abstract class ServerException extends Exception { - - public ServerException(String message) { - super(message); - } - - public ServerException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ServerHandler.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ServerHandler.java deleted file mode 100644 index 0547f581..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ServerHandler.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.server; - -public interface ServerHandler { -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/ArgumentsParseException.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/ArgumentsParseException.java deleted file mode 100644 index dbdb5d92..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/ArgumentsParseException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.server.jetty; - -public class ArgumentsParseException extends Exception { - - public ArgumentsParseException(String message) { - super(message); - } - - public ArgumentsParseException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyDefaultHandler.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyDefaultHandler.java deleted file mode 100644 index ae9a3d3d..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyDefaultHandler.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.server.jetty; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -public class JettyDefaultHandler extends JettyHandler { - @Override - public String pathSpec() { - return "/"; - } - - @Override - protected final void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { - resp.sendError(HttpServletResponse.SC_NOT_FOUND); - } -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyHandler.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyHandler.java deleted file mode 100644 index e8c61858..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyHandler.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.server.jetty; - -import com.zmops.zeus.iot.server.library.server.ServerHandler; - -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -public abstract class JettyHandler extends HttpServlet implements ServerHandler { - - public abstract String pathSpec(); - - @Override - protected final void service(HttpServletRequest req, - HttpServletResponse resp) throws ServletException, IOException { - String method = req.getMethod(); - - // 只支持 Post 和 Get - if (method.equals("POST") || method.equals("GET")) { - super.service(req, resp); - } else { - resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED); - } - } - - @Override - public final void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { - super.service(req, res); - } - - @Override - protected final void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - super.doHead(req, resp); - } - - @Override - protected final void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - super.doPut(req, resp); - } - - @Override - protected final void doDelete(HttpServletRequest req, - HttpServletResponse resp) throws ServletException, IOException { - super.doDelete(req, resp); - } - - @Override - protected final void doOptions(HttpServletRequest req, - HttpServletResponse resp) throws ServletException, IOException { - super.doOptions(req, resp); - } - - @Override - protected final void doTrace(HttpServletRequest req, - HttpServletResponse resp) throws ServletException, IOException { - super.doTrace(req, resp); - } -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyJsonHandler.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyJsonHandler.java deleted file mode 100644 index fdc258d1..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyJsonHandler.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.server.jetty; - -import com.google.gson.JsonElement; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.PrintWriter; - -import static java.util.Objects.nonNull; - -/** - * @author nantian Jetty JSON 处理逻辑 - */ -public abstract class JettyJsonHandler extends JettyHandler { - private static final Logger LOGGER = LoggerFactory.getLogger(JettyJsonHandler.class); - - @Override - protected final void doPost(HttpServletRequest req, HttpServletResponse resp) { - try { - reply(resp, doPost(req)); - } catch (ArgumentsParseException | IOException e) { - try { - replyError(resp, e.getMessage(), HttpServletResponse.SC_BAD_REQUEST); - } catch (IOException replyException) { - LOGGER.error(replyException.getMessage(), e); - } - } - } - - protected abstract JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException, IOException; - - private void reply(HttpServletResponse response, JsonElement resJson) throws IOException { - response.setContentType("application/json"); - response.setCharacterEncoding("utf-8"); - response.setStatus(HttpServletResponse.SC_OK); - - PrintWriter out = response.getWriter(); - if (nonNull(resJson)) { - out.print(resJson); - } - out.flush(); - out.close(); - } - - private void replyError(HttpServletResponse response, String errorMessage, int status) throws IOException { - response.setContentType("application/json"); - response.setCharacterEncoding("utf-8"); - response.setStatus(status); - response.setHeader("error-message", errorMessage); - - PrintWriter out = response.getWriter(); - out.flush(); - out.close(); - } - - public String getJsonBody(HttpServletRequest req) throws IOException { - StringBuffer stringBuffer = new StringBuffer(); - String line = null; - BufferedReader reader = req.getReader(); - while ((line = reader.readLine()) != null) { - stringBuffer.append(line); - } - return stringBuffer.toString(); - } -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServer.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServer.java deleted file mode 100644 index b57aca1c..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServer.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.server.jetty; - - -import com.zmops.zeus.iot.server.library.server.Server; -import com.zmops.zeus.iot.server.library.server.ServerException; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.HttpConfiguration; -import org.eclipse.jetty.server.HttpConnectionFactory; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.server.handler.gzip.GzipHandler; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.servlet.ServletMapping; -import org.eclipse.jetty.util.thread.QueuedThreadPool; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Objects; - -public class JettyServer implements Server { - - private static final Logger LOGGER = LoggerFactory.getLogger(JettyServer.class); - - private org.eclipse.jetty.server.Server server; - private ServletContextHandler servletContextHandler; - private JettyServerConfig jettyServerConfig; - - public JettyServer(JettyServerConfig config) { - this.jettyServerConfig = config; - } - - @Override - public String hostPort() { - return jettyServerConfig.getHost() + ":" + jettyServerConfig.getPort(); - } - - @Override - public String serverClassify() { - return "Jetty"; - } - - @Override - public void initialize() { - QueuedThreadPool threadPool = new QueuedThreadPool(); - threadPool.setMinThreads(jettyServerConfig.getJettyMinThreads()); - threadPool.setMaxThreads(jettyServerConfig.getJettyMaxThreads()); - - server = new org.eclipse.jetty.server.Server(threadPool); - - HttpConfiguration httpConfiguration = new HttpConfiguration(); - - GzipHandler gzipHandler = new GzipHandler(); - server.setHandler(gzipHandler); - - - httpConfiguration.setRequestHeaderSize(jettyServerConfig.getJettyHttpMaxRequestHeaderSize()); - - ServerConnector connector = new ServerConnector(server, new HttpConnectionFactory(httpConfiguration)); - connector.setHost(jettyServerConfig.getHost()); - connector.setPort(jettyServerConfig.getPort()); - connector.setIdleTimeout(jettyServerConfig.getJettyIdleTimeOut()); - connector.setAcceptorPriorityDelta(jettyServerConfig.getJettyAcceptorPriorityDelta()); - connector.setAcceptQueueSize(jettyServerConfig.getJettyAcceptQueueSize()); - server.setConnectors(new Connector[]{connector}); - - servletContextHandler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS); - servletContextHandler.setContextPath(jettyServerConfig.getContextPath()); - LOGGER.info("http server root context path: {}", jettyServerConfig.getContextPath()); - - server.setHandler(servletContextHandler); - - JettyDefaultHandler defaultHandler = new JettyDefaultHandler(); - ServletHolder defaultHolder = new ServletHolder(); - defaultHolder.setServlet(defaultHandler); - - servletContextHandler.addServlet(defaultHolder, defaultHandler.pathSpec()); - } - - public void addHandler(JettyHandler handler) { - LOGGER.info( - "Bind handler {} into jetty server {}:{}", - handler.getClass().getSimpleName(), jettyServerConfig.getHost(), jettyServerConfig.getPort() - ); - - ServletHolder servletHolder = new ServletHolder(); - servletHolder.setServlet(handler); - servletContextHandler.addServlet(servletHolder, handler.pathSpec()); - } - - @Override - public boolean isSSLOpen() { - return false; - } - - @Override - public boolean isStatusEqual(Server target) { - return equals(target); - } - - @Override - public void start() throws ServerException { - LOGGER.info("start server, host: {}, port: {}", jettyServerConfig.getHost(), jettyServerConfig.getPort()); - try { - if (LOGGER.isDebugEnabled()) { - if (servletContextHandler.getServletHandler() != null && servletContextHandler.getServletHandler().getServletMappings() != null) { - - for (ServletMapping servletMapping : servletContextHandler.getServletHandler().getServletMappings()) { - LOGGER.debug("jetty servlet mappings: {} register by {}", servletMapping.getPathSpecs(), servletMapping.getServletName()); - } - - } - } - - server.start(); - } catch (Exception e) { - throw new JettyServerException(e.getMessage(), e); - } - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - JettyServer that = (JettyServer) o; - return jettyServerConfig.getPort() == that.jettyServerConfig.getPort() - && Objects.equals(jettyServerConfig.getHost(), that.jettyServerConfig.getHost()); - } - - @Override - public int hashCode() { - return Objects.hash(jettyServerConfig.getHost(), jettyServerConfig.getPort()); - } - -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServerConfig.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServerConfig.java deleted file mode 100644 index 03b6ad0b..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServerConfig.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.server.jetty; - -import lombok.Builder; -import lombok.Getter; -import lombok.Setter; - -@Setter -@Getter -@Builder -public class JettyServerConfig { - - private String host; - private int port; - private String contextPath; - - @Builder.Default - private int jettyMinThreads = 1; - @Builder.Default - private int jettyMaxThreads = 200; - @Builder.Default - private long jettyIdleTimeOut = 30000; - @Builder.Default - private int jettyAcceptorPriorityDelta = 0; - @Builder.Default - private int jettyAcceptQueueSize = 0; - @Builder.Default - private int jettyHttpMaxRequestHeaderSize = 8192; -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServerException.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServerException.java deleted file mode 100644 index 5d809d1b..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServerException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.server.jetty; - -import com.zmops.zeus.iot.server.library.server.ServerException; - -public class JettyServerException extends ServerException { - - public JettyServerException(String message) { - super(message); - } - - public JettyServerException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/pool/CustomThreadFactory.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/pool/CustomThreadFactory.java deleted file mode 100644 index 38262b7d..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/pool/CustomThreadFactory.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.server.pool; - -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -public class CustomThreadFactory implements ThreadFactory { - private final AtomicInteger poolNumber = new AtomicInteger(1); - private final ThreadGroup group; - private final AtomicInteger threadNumber = new AtomicInteger(1); - private final String namePrefix; - - public CustomThreadFactory(String name) { - SecurityManager s = System.getSecurityManager(); - group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); - namePrefix = name + "-" + poolNumber.getAndIncrement() + "-thread-"; - } - - @Override - public Thread newThread(Runnable r) { - Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); - if (t.isDaemon()) - t.setDaemon(false); - if (t.getPriority() != Thread.NORM_PRIORITY) - t.setPriority(Thread.NORM_PRIORITY); - return t; - } -} \ No newline at end of file diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/AbstractSslContext.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/AbstractSslContext.java deleted file mode 100644 index cbb47fb8..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/AbstractSslContext.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.server.ssl; - -import com.zmops.zeus.iot.server.library.util.MultipleFilesChangeMonitor; -import io.netty.buffer.ByteBufAllocator; -import io.netty.handler.ssl.ApplicationProtocolNegotiator; -import io.netty.handler.ssl.SslContext; -import lombok.AccessLevel; -import lombok.Setter; - -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLSessionContext; -import java.util.List; - -public abstract class AbstractSslContext extends SslContext { - private final MultipleFilesChangeMonitor monitor; - - @Setter(AccessLevel.PROTECTED) - private volatile SslContext ctx; - - protected AbstractSslContext(final String privateKeyFile, final String certChainFile) { - updateContext(privateKeyFile, certChainFile); - monitor = new MultipleFilesChangeMonitor( - 10, - readableContents -> updateContext(privateKeyFile, certChainFile), - certChainFile, - privateKeyFile); - } - - protected AbstractSslContext(final String caFile) { - updateContext(caFile); - monitor = new MultipleFilesChangeMonitor( - 10, - readableContents -> updateContext(caFile), - caFile); - } - - protected abstract void updateContext(String caFile); - - protected abstract void updateContext(final String privateKeyFile, final String certChainFile); - - public void start() { - monitor.start(); - } - - @Override - public final boolean isClient() { - return ctx.isClient(); - } - - @Override - public final List cipherSuites() { - return ctx.cipherSuites(); - } - - @Override - public final long sessionCacheSize() { - return ctx.sessionCacheSize(); - } - - @Override - public final long sessionTimeout() { - return ctx.sessionTimeout(); - } - - @Override - public final ApplicationProtocolNegotiator applicationProtocolNegotiator() { - return ctx.applicationProtocolNegotiator(); - } - - @Override - public final SSLEngine newEngine(ByteBufAllocator alloc) { - return ctx.newEngine(alloc); - } - - @Override - public final SSLEngine newEngine(ByteBufAllocator alloc, String peerHost, int peerPort) { - return ctx.newEngine(alloc, peerHost, peerPort); - } - - @Override - public final SSLSessionContext sessionContext() { - return ctx.sessionContext(); - } -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/HttpDynamicSslContext.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/HttpDynamicSslContext.java deleted file mode 100644 index 2fe8cd76..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/HttpDynamicSslContext.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.server.ssl; - -import io.netty.handler.ssl.SslContextBuilder; - -import javax.net.ssl.SSLException; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.file.Paths; -import java.security.GeneralSecurityException; - -public class HttpDynamicSslContext extends AbstractSslContext { - - public static HttpDynamicSslContext forServer(String privateKeyFile, String certChainFile) { - return new HttpDynamicSslContext(privateKeyFile, certChainFile); - } - - public static HttpDynamicSslContext forClient(String caFile) { - return new HttpDynamicSslContext(caFile); - } - - protected HttpDynamicSslContext(String privateKeyFile, String certChainFile) { - super(privateKeyFile, certChainFile); - } - - protected HttpDynamicSslContext(String caFile) { - super(caFile); - } - - @Override - protected void updateContext(String caFile) { - try { - setCtx(SslContextBuilder.forClient().trustManager(Paths.get(caFile).toFile()).build()); - } catch (SSLException e) { - throw new IllegalArgumentException(e); - } - } - - @Override - protected void updateContext(final String privateKeyFile, final String certChainFile) { - try { - setCtx(SslContextBuilder - .forServer( - new FileInputStream(Paths.get(certChainFile).toFile()), - PrivateKeyUtil.loadDecryptionKey(privateKeyFile)).build()); - } catch (GeneralSecurityException | IOException e) { - throw new IllegalArgumentException(e); - } - } -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/PrivateKeyUtil.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/PrivateKeyUtil.java deleted file mode 100644 index 12550638..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/PrivateKeyUtil.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.server.ssl; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.GeneralSecurityException; -import java.util.Base64; - -/** - * Util intends to parse PKCS#1 and PKCS#8 at same time. - */ -public class PrivateKeyUtil { - private static final String PKCS_1_PEM_HEADER = "-----BEGIN RSA PRIVATE KEY-----"; - private static final String PKCS_1_PEM_FOOTER = "-----END RSA PRIVATE KEY-----"; - private static final String PKCS_8_PEM_HEADER = "-----BEGIN PRIVATE KEY-----"; - private static final String PKCS_8_PEM_FOOTER = "-----END PRIVATE KEY-----"; - - /** - * Load a RSA decryption key from a file (PEM or DER). - */ - public static InputStream loadDecryptionKey(String keyFilePath) throws GeneralSecurityException, IOException { - byte[] keyDataBytes = Files.readAllBytes(Paths.get(keyFilePath)); - String keyDataString = new String(keyDataBytes, StandardCharsets.UTF_8); - - if (keyDataString.contains(PKCS_1_PEM_HEADER)) { - // OpenSSL / PKCS#1 Base64 PEM encoded file - keyDataString = keyDataString.replace(PKCS_1_PEM_HEADER, ""); - keyDataString = keyDataString.replace(PKCS_1_PEM_FOOTER, ""); - keyDataString = keyDataString.replace("\n", ""); - return readPkcs1PrivateKey(Base64.getDecoder().decode(keyDataString)); - } - - return new ByteArrayInputStream(keyDataString.getBytes()); - } - - /** - * Create a InputStream instance from raw PKCS#1 bytes. Raw Java API can't recognize ASN.1 format, so we should - * convert it into a pkcs#8 format Java can understand. - */ - private static InputStream readPkcs1PrivateKey(byte[] pkcs1Bytes) throws GeneralSecurityException { - int pkcs1Length = pkcs1Bytes.length; - int totalLength = pkcs1Length + 22; - byte[] pkcs8Header = new byte[]{ - 0x30, (byte) 0x82, (byte) ((totalLength >> 8) & 0xff), (byte) (totalLength & 0xff), // Sequence + total length - 0x2, 0x1, 0x0, // Integer (0) - 0x30, 0xD, 0x6, 0x9, 0x2A, (byte) 0x86, 0x48, (byte) 0x86, (byte) 0xF7, 0xD, 0x1, 0x1, 0x1, 0x5, 0x0, // Sequence: 1.2.840.113549.1.1.1, NULL - 0x4, (byte) 0x82, (byte) ((pkcs1Length >> 8) & 0xff), (byte) (pkcs1Length & 0xff) // Octet string + length - }; - StringBuilder pkcs8 = new StringBuilder(PKCS_8_PEM_HEADER); - pkcs8.append("\n").append(new String(Base64.getEncoder().encode(join(pkcs8Header, pkcs1Bytes)))); - pkcs8.append("\n").append(PKCS_8_PEM_FOOTER); - return new ByteArrayInputStream(pkcs8.toString().getBytes()); - } - - private static byte[] join(byte[] byteArray1, byte[] byteArray2) { - byte[] bytes = new byte[byteArray1.length + byteArray2.length]; - System.arraycopy(byteArray1, 0, bytes, 0, byteArray1.length); - System.arraycopy(byteArray2, 0, bytes, byteArray1.length, byteArray2.length); - return bytes; - } -} diff --git a/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/CollectionUtils.java b/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/CollectionUtils.java deleted file mode 100644 index 855f093e..00000000 --- a/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/CollectionUtils.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.util; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -public class CollectionUtils { - - public static boolean isEmpty(Map map) { - return map == null || map.size() == 0; - } - - public static boolean isEmpty(List list) { - return list == null || list.size() == 0; - } - - public static boolean isEmpty(Set set) { - return set == null || set.size() == 0; - } - - public static boolean isNotEmpty(List list) { - return !isEmpty(list); - } - - public static boolean isNotEmpty(Set set) { - return !isEmpty(set); - } - - public static boolean isNotEmpty(Map map) { - return !isEmpty(map); - } - - public static boolean isNotEmpty(T[] array) { - return array != null && array.length > 0; - } - - public static boolean isEmpty(byte[] array) { - return array == null || array.length == 0; - } - - public static boolean isNotEmpty(byte[] array) { - return !isEmpty(array); - } -} diff --git a/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/HealthChecker.java b/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/HealthChecker.java deleted file mode 100644 index 45c80f92..00000000 --- a/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/HealthChecker.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.util; - -/** - * Health checker provides methods to register the health status. - */ -public interface HealthChecker { - - /** - * It's health. - */ - void health(); - - /** - * It's unHealth. - * - * @param t details of unhealthy status - */ - void unHealth(Throwable t); - - /** - * It's unHealth. - * - * @param reason details reason of unhealthy status - */ - void unHealth(String reason); -} diff --git a/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/MultipleFilesChangeMonitor.java b/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/MultipleFilesChangeMonitor.java deleted file mode 100644 index a2260330..00000000 --- a/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/MultipleFilesChangeMonitor.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.util; - -import com.zmops.zeus.iot.server.util.StringUtil; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -import java.io.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.ReentrantLock; - -/** - * MultipleFilesChangeMonitor provides the capability to detect file or multiple files changed. It provide second level - * change detection and feedback mechanism. - *

- * Due to memory cost, this monitor mechanism is not suitable for small files and usually being changed on the runtime - * by user manually or 3rd party tool. Typical, these files are config information or authentication files. - */ -@Slf4j -public class MultipleFilesChangeMonitor { - /** - * The backend scheduler to trigger all file monitoring. - */ - private static ScheduledFuture FILE_MONITOR_TASK_SCHEDULER; - private static final ReentrantLock SCHEDULER_CHANGE_LOCK = new ReentrantLock(); - /** - * The list contains all monitors. - */ - private static final List MONITOR_INSTANCES = new ArrayList<>(); - - /** - * The timestamp when last time do status checked. - */ - private long lastCheckTimestamp = 0; - /** - * The period of watching thread checking the file status. Unit is the second. - */ - private final long watchingPeriodInSec; - private final List watchedFiles; - private final FilesChangedNotifier notifier; - - /** - * Create a new monitor for the given files - * - * @param watchingPeriodInSec The check period. - * @param notifier to accept the file changed notification. - * @param files to be monitored. If an element of list is NULL, the virtual(NULL) file is treated - * unchangeable. - */ - public MultipleFilesChangeMonitor(long watchingPeriodInSec, - FilesChangedNotifier notifier, - String... files) { - watchedFiles = new ArrayList<>(); - this.watchingPeriodInSec = watchingPeriodInSec; - this.notifier = notifier; - for (final String file : files) { - WatchedFile monitor; - if (StringUtil.isEmpty(file)) { - monitor = new NoopWatchedFile(); - } else { - monitor = new WatchedFile(file); - } - watchedFiles.add(monitor); - } - } - - /** - * Check file changed status, if so, send the notification. - */ - private void checkAndNotify() { - if (System.currentTimeMillis() - lastCheckTimestamp < watchingPeriodInSec * 1000) { - // Don't reach the period threshold, ignore this check. - return; - } - - boolean isChanged = false; - for (final WatchedFile watchedFile : watchedFiles) { - isChanged = isChanged || watchedFile.detectContentChanged(); - } - if (isChanged) { - List contents = new ArrayList<>(watchedFiles.size()); - watchedFiles.forEach(file -> { - contents.add(file.fileContent); - }); - try { - notifier.filesChanged(contents); - } catch (Exception e) { - log.error("Files=" + this + " notification process failure.", e); - } - } - } - - /** - * One file changed will cause all related files loaded from the disk again with lastModifiedTimestamp updated. - */ - public static void scanChanges() { - MONITOR_INSTANCES.forEach(group -> { - try { - group.checkAndNotify(); - } catch (Throwable t) { - log.error("Files change detection failure, gourp = ", t); - } - }); - } - - /** - * Start the change monitoring. - */ - public void start() { - SCHEDULER_CHANGE_LOCK.lock(); - try { - if (FILE_MONITOR_TASK_SCHEDULER == null) { - FILE_MONITOR_TASK_SCHEDULER = Executors.newSingleThreadScheduledExecutor() - .scheduleAtFixedRate( - MultipleFilesChangeMonitor::scanChanges, 1, 200, - TimeUnit.MILLISECONDS - ); - } - - if (MONITOR_INSTANCES.contains(this)) { - throw new IllegalStateException("This FileChangeMonitor has been started."); - } - - this.checkAndNotify(); - MONITOR_INSTANCES.add(this); - } finally { - SCHEDULER_CHANGE_LOCK.unlock(); - } - } - - /** - * Stop the change monitoring. - */ - public void stop() { - SCHEDULER_CHANGE_LOCK.lock(); - try { - MONITOR_INSTANCES.remove(this); - } finally { - SCHEDULER_CHANGE_LOCK.unlock(); - } - } - - @Override - public String toString() { - return "MultipleFilesChangeMonitor{" + - "watchedFiles=" + watchedFiles + - '}'; - } - - /** - * The callback when files changed. - */ - public interface FilesChangedNotifier { - /** - * Notify the new content by providing the file input stream for all files in this group. - * - * @param readableContents include the new contents. NULL if the file doesn't exist. - */ - void filesChanged(List readableContents) throws Exception; - } - - /** - * WatchedFile represents a file change detector. It could detect the file changed based on modified time and file - * content at the binary level. It load the file content into the memory as cache to do the comparison. - */ - @RequiredArgsConstructor - @Slf4j - private static class WatchedFile { - /** - * The absolute path of the monitored file. - */ - private final String filePath; - /** - * The last modify time of the {@link #filePath} - */ - private long lastModifiedTimestamp = 0; - /** - * File content at the latest status. - */ - private byte[] fileContent; - - /** - * Detect the file content change, if yes, reload the file content into the memory as cached data. - * - * @return true if file content changed. - */ - boolean detectContentChanged() { - File targetFile = new File(filePath); - if (!targetFile.exists()) { - if (lastModifiedTimestamp == 0) { - //File doesn't exist before, no change detected. - return false; - } else { - // File has been deleted. Reset the modified timestamp. - lastModifiedTimestamp = 0; - return true; - } - } else { - long lastModified = targetFile.lastModified(); - if (lastModified != lastModifiedTimestamp) { - // File modified timestamp changed. Need to read the file content. - try (FileInputStream fileInputStream = new FileInputStream(targetFile)) { - byte[] b = new byte[1024]; - ByteArrayOutputStream os = new ByteArrayOutputStream(); - int c; - while ((c = fileInputStream.read(b)) != -1) { - os.write(b, 0, c); - } - byte[] newContent = os.toByteArray(); - if (!Arrays.equals(newContent, fileContent)) { - fileContent = newContent; - return true; - } else { - return false; - } - } catch (FileNotFoundException e) { - log.error("The existed file turns to missing, watch file=" + filePath, e); - } catch (IOException e) { - log.error("Read file failure, watch file=" + filePath, e); - } finally { - lastModifiedTimestamp = lastModified; - } - } - return false; - } - } - } - - private static class NoopWatchedFile extends WatchedFile { - public NoopWatchedFile() { - super(null); - } - - /** - * @return false, as an noop file never changes. - */ - @Override - boolean detectContentChanged() { - return false; - } - } -} diff --git a/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/ResourceUtils.java b/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/ResourceUtils.java deleted file mode 100644 index 6addb0be..00000000 --- a/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/ResourceUtils.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.zmops.zeus.iot.server.library.util; - -import java.io.*; -import java.net.URL; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -public class ResourceUtils { - - public static Reader read(String fileName) throws FileNotFoundException { - return new InputStreamReader(readToStream(fileName)); - } - - public static InputStream readToStream(String fileName) throws FileNotFoundException { - URL url = ResourceUtils.class.getClassLoader().getResource(fileName); - if (url == null) { - throw new FileNotFoundException("file not found: " + fileName); - } - return ResourceUtils.class.getClassLoader().getResourceAsStream(fileName); - } - - public static File[] getPathFiles(String path) throws FileNotFoundException { - URL url = ResourceUtils.class.getClassLoader().getResource(path); - if (url == null) { - throw new FileNotFoundException("path not found: " + path); - } - return Arrays.stream(Objects.requireNonNull(new File(url.getPath()).listFiles(), "No files in " + path)) - .filter(File::isFile).toArray(File[]::new); - } - - public static File[] getPathFiles(String parentPath, String[] fileNames) throws FileNotFoundException { - URL url = ResourceUtils.class.getClassLoader().getResource(parentPath); - if (url == null) { - throw new FileNotFoundException("path not found: " + parentPath); - } - final Set nameSet = new HashSet<>(Arrays.asList(fileNames)); - final File[] listFiles = Objects.requireNonNull(new File(url.getPath()) - .listFiles((dir, name) -> nameSet.contains(name)), "No files in " + parentPath); - - if (listFiles.length == 0) { - throw new FileNotFoundException("files not found:" + nameSet); - } - return listFiles; - } -} diff --git a/iot-server/server-library/pom.xml b/iot-server/server-library/pom.xml deleted file mode 100644 index a117a798..00000000 --- a/iot-server/server-library/pom.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - iot-server - com.zmops - 1.0-beta - - 4.0.0 - - server-library - pom - - library-module - library-util - library-server - library-client - - - - 8 - 8 - - - \ No newline at end of file diff --git a/iot-server/server-localdb/pom.xml b/iot-server/server-localdb/pom.xml index c890083b..5ed9a7b1 100644 --- a/iot-server/server-localdb/pom.xml +++ b/iot-server/server-localdb/pom.xml @@ -16,11 +16,11 @@ com.zmops library-module - 1.0-beta + 1.0-SNAPSHOT com.zmops - library-client + server-client 1.0-beta diff --git a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/module/LocalH2Module.java b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/module/LocalH2Module.java index 5b466fd7..4f879c0d 100644 --- a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/module/LocalH2Module.java +++ b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/module/LocalH2Module.java @@ -1,7 +1,7 @@ package com.zmops.zeus.iot.server.h2.module; import com.zmops.zeus.iot.server.h2.service.InsertDAO; -import com.zmops.zeus.iot.server.library.module.ModuleDefine; +import com.zmops.zeus.server.library.module.ModuleDefine; /** * @author nantian created at 2021/10/24 16:56 diff --git a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2Config.java b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2Config.java index 828c2110..3b814a89 100644 --- a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2Config.java +++ b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2Config.java @@ -1,6 +1,6 @@ package com.zmops.zeus.iot.server.h2.provider; -import com.zmops.zeus.iot.server.library.module.ModuleConfig; +import com.zmops.zeus.server.library.module.ModuleConfig; import lombok.Getter; import lombok.Setter; @@ -14,9 +14,9 @@ @Setter public class LocalH2Config extends ModuleConfig { - private String driver = "org.h2.jdbcx.JdbcDataSource"; - private String url = "jdbc:h2:mem:skywalking-oap-db;DB_CLOSE_DELAY=-1"; - private String user = "sa"; + private String driver = "org.h2.jdbcx.JdbcDataSource"; + private String url = "jdbc:h2:mem:skywalking-oap-db;DB_CLOSE_DELAY=-1"; + private String user = "sa"; private String password = "sa"; /** diff --git a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2InsertDAO.java b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2InsertDAO.java index cd219eb2..5aad2a13 100644 --- a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2InsertDAO.java +++ b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2InsertDAO.java @@ -1,8 +1,8 @@ package com.zmops.zeus.iot.server.h2.provider; import com.zmops.zeus.iot.server.h2.service.InsertDAO; -import com.zmops.zeus.iot.server.library.client.jdbc.JDBCClientException; -import com.zmops.zeus.iot.server.library.client.jdbc.hikaricp.JDBCHikariCPClient; +import com.zmops.zeus.iot.server.client.jdbc.JDBCClientException; +import com.zmops.zeus.iot.server.client.jdbc.hikaricp.JDBCHikariCPClient; import java.sql.ResultSet; diff --git a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2Provider.java b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2Provider.java index eb665f6c..127c88c3 100644 --- a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2Provider.java +++ b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2Provider.java @@ -2,9 +2,9 @@ import com.zmops.zeus.iot.server.h2.module.LocalH2Module; import com.zmops.zeus.iot.server.h2.service.InsertDAO; -import com.zmops.zeus.iot.server.library.client.jdbc.JDBCClientException; -import com.zmops.zeus.iot.server.library.client.jdbc.hikaricp.JDBCHikariCPClient; -import com.zmops.zeus.iot.server.library.module.*; +import com.zmops.zeus.iot.server.client.jdbc.JDBCClientException; +import com.zmops.zeus.iot.server.client.jdbc.hikaricp.JDBCHikariCPClient; +import com.zmops.zeus.server.library.module.*; import java.sql.Connection; import java.sql.ResultSet; @@ -15,8 +15,8 @@ */ public class LocalH2Provider extends ModuleProvider { - private final LocalH2Config localH2Config; - private JDBCHikariCPClient h2Client; + private final LocalH2Config localH2Config; + private JDBCHikariCPClient h2Client; public LocalH2Provider() { this.localH2Config = new LocalH2Config(); diff --git a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/service/InsertDAO.java b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/service/InsertDAO.java index b7b33a5e..6db0c69c 100644 --- a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/service/InsertDAO.java +++ b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/service/InsertDAO.java @@ -1,6 +1,6 @@ package com.zmops.zeus.iot.server.h2.service; -import com.zmops.zeus.iot.server.library.module.Service; +import com.zmops.zeus.server.library.module.Service; import java.sql.ResultSet; diff --git a/iot-server/server-localdb/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine b/iot-server/server-localdb/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine similarity index 100% rename from iot-server/server-localdb/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine rename to iot-server/server-localdb/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine diff --git a/iot-server/server-localdb/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-localdb/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider similarity index 100% rename from iot-server/server-localdb/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider rename to iot-server/server-localdb/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider diff --git a/iot-server/server-sender/pom.xml b/iot-server/server-sender/pom.xml index e915df85..3487d785 100644 --- a/iot-server/server-sender/pom.xml +++ b/iot-server/server-sender/pom.xml @@ -15,7 +15,7 @@ com.zmops library-module - 1.0-beta + 1.0-SNAPSHOT diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/module/ZabbixSenderModule.java b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/module/ZabbixSenderModule.java index 5dd90d24..565e538f 100644 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/module/ZabbixSenderModule.java +++ b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/module/ZabbixSenderModule.java @@ -1,7 +1,7 @@ package com.zmops.zeus.iot.server.sender.module; -import com.zmops.zeus.iot.server.library.module.ModuleDefine; import com.zmops.zeus.iot.server.sender.service.ZabbixSenderService; +import com.zmops.zeus.server.library.module.ModuleDefine; /** * @author nantian created at 2021/8/14 14:35 diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderModuleConfig.java b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderModuleConfig.java index 187e5aba..ea64e47b 100644 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderModuleConfig.java +++ b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderModuleConfig.java @@ -1,6 +1,6 @@ package com.zmops.zeus.iot.server.sender.provider; -import com.zmops.zeus.iot.server.library.module.ModuleConfig; +import com.zmops.zeus.server.library.module.ModuleConfig; import lombok.Getter; import lombok.Setter; diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderProvider.java b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderProvider.java index b73ffc19..22ef3ba6 100644 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderProvider.java +++ b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderProvider.java @@ -1,8 +1,8 @@ package com.zmops.zeus.iot.server.sender.provider; -import com.zmops.zeus.iot.server.library.module.*; import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; import com.zmops.zeus.iot.server.sender.service.ZabbixSenderService; +import com.zmops.zeus.server.library.module.*; import lombok.extern.slf4j.Slf4j; /** diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/service/ZabbixSenderService.java b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/service/ZabbixSenderService.java index 8969c39f..6b3ed731 100644 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/service/ZabbixSenderService.java +++ b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/service/ZabbixSenderService.java @@ -1,9 +1,9 @@ package com.zmops.zeus.iot.server.sender.service; import com.google.gson.Gson; -import com.zmops.zeus.iot.server.library.module.ModuleManager; -import com.zmops.zeus.iot.server.library.module.Service; import com.zmops.zeus.iot.server.sender.provider.ZabbixSenderClient; +import com.zmops.zeus.server.library.module.ModuleManager; +import com.zmops.zeus.server.library.module.Service; import lombok.extern.slf4j.Slf4j; import java.io.IOException; diff --git a/iot-server/server-sender/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine b/iot-server/server-sender/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine similarity index 100% rename from iot-server/server-sender/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine rename to iot-server/server-sender/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine diff --git a/iot-server/server-sender/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-sender/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider similarity index 100% rename from iot-server/server-sender/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider rename to iot-server/server-sender/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider diff --git a/iot-server/server-starter/conf/ark/bootstrap.properties b/iot-server/server-starter/conf/ark/bootstrap.properties new file mode 100644 index 00000000..c3d121ec --- /dev/null +++ b/iot-server/server-starter/conf/ark/bootstrap.properties @@ -0,0 +1,5 @@ +logging.path=./logs + +#com.alipay.sofa.ark.master.biz=server-starter + +com.alipay.sofa.ark.master.biz=Startup In IDE \ No newline at end of file diff --git a/iot-server/server-starter/pom.xml b/iot-server/server-starter/pom.xml index ca60b017..6a24ceac 100644 --- a/iot-server/server-starter/pom.xml +++ b/iot-server/server-starter/pom.xml @@ -22,6 +22,46 @@ server-health-checker 1.0-beta + + + + + + + + + + + + + + + @@ -45,6 +85,24 @@ + + + com.alipay.sofa + sofa-ark-maven-plugin + 1.1.6 + + + + repackage + + + server-starter + ./target + executable-ark + + + + diff --git a/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerStartUp.java b/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerStartUp.java index 3f16d36a..fbd0699a 100644 --- a/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerStartUp.java +++ b/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerStartUp.java @@ -11,7 +11,9 @@ public class IoTServerStartUp { public static void main(String[] args) { +// SofaArkBootstrap.launch(args); IoTServerBootstrap.start(); + log.info("IoT Server Platform start successfully ..."); } } diff --git a/iot-server/server-storage-plugin/server-none-storage/pom.xml b/iot-server/server-storage-plugin/server-none-storage/pom.xml index a5b50141..a2cfe458 100644 --- a/iot-server/server-storage-plugin/server-none-storage/pom.xml +++ b/iot-server/server-storage-plugin/server-none-storage/pom.xml @@ -14,7 +14,7 @@ com.zmops library-module - ${project.version} + 1.0-SNAPSHOT com.zmops diff --git a/iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/BatchDaoNoop.java b/iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/BatchDaoNoop.java index a5408d23..8b54a14c 100644 --- a/iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/BatchDaoNoop.java +++ b/iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/BatchDaoNoop.java @@ -1,8 +1,8 @@ package com.zmops.zeus.iot.server.storage.plugin.none; import com.zmops.zeus.iot.server.core.storage.IBatchDAO; -import com.zmops.zeus.iot.server.library.client.request.InsertRequest; -import com.zmops.zeus.iot.server.library.client.request.PrepareRequest; +import com.zmops.zeus.iot.server.client.request.InsertRequest; +import com.zmops.zeus.iot.server.client.request.PrepareRequest; import java.util.List; diff --git a/iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/NoneStorageProvider.java b/iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/NoneStorageProvider.java index 79ccc37c..a5259673 100644 --- a/iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/NoneStorageProvider.java +++ b/iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/NoneStorageProvider.java @@ -3,11 +3,11 @@ import com.zmops.zeus.iot.server.core.storage.IBatchDAO; import com.zmops.zeus.iot.server.core.storage.StorageDAO; import com.zmops.zeus.iot.server.core.storage.StorageModule; -import com.zmops.zeus.iot.server.library.module.*; +import com.zmops.zeus.server.library.module.*; /** * @author nantian created at 2021/9/27 21:18 - * + *

* Proxy 模式下,或者 不使用默认的 TDEngine 时 */ public class NoneStorageProvider extends ModuleProvider { diff --git a/iot-server/server-storage-plugin/server-none-storage/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-storage-plugin/server-none-storage/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider similarity index 100% rename from iot-server/server-storage-plugin/server-none-storage/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider rename to iot-server/server-storage-plugin/server-none-storage/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml index d3e8e42a..8a835dd2 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml @@ -25,7 +25,7 @@ com.zmops library-module - 1.0-beta + 1.0-SNAPSHOT com.zmops diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java index e8234106..9eefa240 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java @@ -18,7 +18,7 @@ package com.zmops.zeus.iot.server.storage.plugin.jdbc; -import com.zmops.zeus.iot.server.library.client.request.InsertRequest; +import com.zmops.zeus.iot.server.client.request.InsertRequest; import lombok.Getter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineBatchDAO.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineBatchDAO.java index bc929d37..796a42c9 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineBatchDAO.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineBatchDAO.java @@ -2,17 +2,17 @@ import com.zmops.zeus.iot.server.core.UnexpectedException; import com.zmops.zeus.iot.server.core.storage.IBatchDAO; -import com.zmops.zeus.iot.server.datacarrier.DataCarrier; -import com.zmops.zeus.iot.server.datacarrier.consumer.BulkConsumePool; -import com.zmops.zeus.iot.server.datacarrier.consumer.ConsumerPoolFactory; -import com.zmops.zeus.iot.server.datacarrier.consumer.IConsumer; -import com.zmops.zeus.iot.server.library.client.jdbc.JDBCClientException; -import com.zmops.zeus.iot.server.library.client.jdbc.hikaricp.JDBCHikariCPClient; -import com.zmops.zeus.iot.server.library.client.request.InsertRequest; -import com.zmops.zeus.iot.server.library.client.request.PrepareRequest; -import com.zmops.zeus.iot.server.library.util.CollectionUtils; +import com.zmops.zeus.iot.server.client.jdbc.JDBCClientException; +import com.zmops.zeus.iot.server.client.jdbc.hikaricp.JDBCHikariCPClient; +import com.zmops.zeus.iot.server.client.request.InsertRequest; +import com.zmops.zeus.iot.server.client.request.PrepareRequest; import com.zmops.zeus.iot.server.storage.plugin.jdbc.SQLBuilder; import com.zmops.zeus.iot.server.storage.plugin.jdbc.SQLExecutor; +import com.zmops.zeus.server.datacarrier.DataCarrier; +import com.zmops.zeus.server.datacarrier.consumer.BulkConsumePool; +import com.zmops.zeus.server.datacarrier.consumer.ConsumerPoolFactory; +import com.zmops.zeus.server.datacarrier.consumer.IConsumer; +import com.zmops.zeus.server.library.util.CollectionUtils; import lombok.extern.slf4j.Slf4j; import java.sql.Connection; diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java index 7658507c..0a9ee06c 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java @@ -1,10 +1,10 @@ package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine; import com.zmops.zeus.iot.server.core.storage.StorageException; -import com.zmops.zeus.iot.server.library.client.Client; -import com.zmops.zeus.iot.server.library.client.jdbc.JDBCClientException; -import com.zmops.zeus.iot.server.library.client.jdbc.hikaricp.JDBCHikariCPClient; -import com.zmops.zeus.iot.server.library.module.ModuleManager; +import com.zmops.zeus.iot.server.client.Client; +import com.zmops.zeus.iot.server.client.jdbc.JDBCClientException; +import com.zmops.zeus.iot.server.client.jdbc.hikaricp.JDBCHikariCPClient; +import com.zmops.zeus.server.library.module.ModuleManager; import java.sql.Connection; import java.sql.SQLException; diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageConfig.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageConfig.java index 1f4776bd..16ef582c 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageConfig.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageConfig.java @@ -1,6 +1,6 @@ package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine; -import com.zmops.zeus.iot.server.library.module.ModuleConfig; +import com.zmops.zeus.server.library.module.ModuleConfig; import lombok.Getter; import lombok.Setter; diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java index ac244dba..b6c280b0 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java @@ -5,13 +5,14 @@ import com.zmops.zeus.iot.server.core.storage.StorageDAO; import com.zmops.zeus.iot.server.core.storage.StorageException; import com.zmops.zeus.iot.server.core.storage.StorageModule; -import com.zmops.zeus.iot.server.library.client.jdbc.hikaricp.JDBCHikariCPClient; -import com.zmops.zeus.iot.server.library.module.*; +import com.zmops.zeus.iot.server.client.jdbc.hikaricp.JDBCHikariCPClient; + import com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine.dao.TDEngineStorageDAO; import com.zmops.zeus.iot.server.telemetry.TelemetryModule; import com.zmops.zeus.iot.server.telemetry.api.HealthCheckMetrics; import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; +import com.zmops.zeus.server.library.module.*; import java.util.Properties; diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineRecordDAO.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineRecordDAO.java index 9339f5ef..146ac37b 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineRecordDAO.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineRecordDAO.java @@ -3,8 +3,8 @@ import com.zmops.zeus.iot.server.core.analysis.record.Record; import com.zmops.zeus.iot.server.core.storage.IRecordDAO; import com.zmops.zeus.iot.server.core.storage.model.Model; -import com.zmops.zeus.iot.server.library.client.jdbc.hikaricp.JDBCHikariCPClient; -import com.zmops.zeus.iot.server.library.client.request.InsertRequest; +import com.zmops.zeus.iot.server.client.jdbc.hikaricp.JDBCHikariCPClient; +import com.zmops.zeus.iot.server.client.request.InsertRequest; import java.io.IOException; diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineStorageDAO.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineStorageDAO.java index d3a8d79a..f309abb9 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineStorageDAO.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineStorageDAO.java @@ -2,8 +2,8 @@ import com.zmops.zeus.iot.server.core.storage.IRecordDAO; import com.zmops.zeus.iot.server.core.storage.StorageDAO; -import com.zmops.zeus.iot.server.library.client.jdbc.hikaricp.JDBCHikariCPClient; -import com.zmops.zeus.iot.server.library.module.ModuleManager; +import com.zmops.zeus.iot.server.client.jdbc.hikaricp.JDBCHikariCPClient; +import com.zmops.zeus.server.library.module.ModuleManager; import lombok.RequiredArgsConstructor; /** diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider similarity index 100% rename from iot-server/server-storage-plugin/server-tdengine-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider rename to iot-server/server-storage-plugin/server-tdengine-plugin/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider diff --git a/iot-server/server-telemetry/telemetry-api/pom.xml b/iot-server/server-telemetry/telemetry-api/pom.xml index d914f617..f3ccf88a 100644 --- a/iot-server/server-telemetry/telemetry-api/pom.xml +++ b/iot-server/server-telemetry/telemetry-api/pom.xml @@ -14,7 +14,7 @@ com.zmops library-module - 1.0-beta + 1.0-SNAPSHOT compile diff --git a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/TelemetryModule.java b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/TelemetryModule.java index a72a0bad..d522619e 100644 --- a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/TelemetryModule.java +++ b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/TelemetryModule.java @@ -18,9 +18,9 @@ package com.zmops.zeus.iot.server.telemetry; -import com.zmops.zeus.iot.server.library.module.ModuleDefine; import com.zmops.zeus.iot.server.telemetry.api.MetricsCollector; import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; +import com.zmops.zeus.server.library.module.ModuleDefine; /** * Telemetry module definition diff --git a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/HealthCheckMetrics.java b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/HealthCheckMetrics.java index bb52a83d..26cbeb64 100644 --- a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/HealthCheckMetrics.java +++ b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/HealthCheckMetrics.java @@ -18,7 +18,7 @@ package com.zmops.zeus.iot.server.telemetry.api; -import com.zmops.zeus.iot.server.library.util.HealthChecker; +import com.zmops.zeus.server.library.util.HealthChecker; import lombok.extern.slf4j.Slf4j; diff --git a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/MetricsCollector.java b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/MetricsCollector.java index 200c2475..dba11614 100644 --- a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/MetricsCollector.java +++ b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/MetricsCollector.java @@ -19,7 +19,7 @@ package com.zmops.zeus.iot.server.telemetry.api; -import com.zmops.zeus.iot.server.library.module.Service; +import com.zmops.zeus.server.library.module.Service; /** * Collect all metrics from telemetry. diff --git a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/MetricsCreator.java b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/MetricsCreator.java index 1c3d264d..728d7b3f 100644 --- a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/MetricsCreator.java +++ b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/MetricsCreator.java @@ -20,7 +20,7 @@ import com.google.common.base.Preconditions; import com.google.common.base.Strings; -import com.zmops.zeus.iot.server.library.module.Service; +import com.zmops.zeus.server.library.module.Service; /** diff --git a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/none/NoneTelemetryProvider.java b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/none/NoneTelemetryProvider.java index 8139008d..1a638bc3 100644 --- a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/none/NoneTelemetryProvider.java +++ b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/none/NoneTelemetryProvider.java @@ -19,10 +19,10 @@ package com.zmops.zeus.iot.server.telemetry.none; -import com.zmops.zeus.iot.server.library.module.*; import com.zmops.zeus.iot.server.telemetry.TelemetryModule; import com.zmops.zeus.iot.server.telemetry.api.MetricsCollector; import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; +import com.zmops.zeus.server.library.module.*; /** * A nutshell telemetry implementor. diff --git a/iot-server/server-telemetry/telemetry-api/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine b/iot-server/server-telemetry/telemetry-api/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine similarity index 100% rename from iot-server/server-telemetry/telemetry-api/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine rename to iot-server/server-telemetry/telemetry-api/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine diff --git a/iot-server/server-telemetry/telemetry-api/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-telemetry/telemetry-api/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider similarity index 100% rename from iot-server/server-telemetry/telemetry-api/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider rename to iot-server/server-telemetry/telemetry-api/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider diff --git a/iot-server/server-telemetry/telemetry-prometheus/pom.xml b/iot-server/server-telemetry/telemetry-prometheus/pom.xml index f809ee3b..df5561bd 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/pom.xml +++ b/iot-server/server-telemetry/telemetry-prometheus/pom.xml @@ -42,8 +42,8 @@ com.zmops - library-server - 1.0-beta + zeus-server-jetty + 1.0-SNAPSHOT compile diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusConfig.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusConfig.java index eacd1f51..e4fb6fea 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusConfig.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusConfig.java @@ -18,7 +18,7 @@ package com.zmops.zeus.iot.server.telemetry.prometheus; -import com.zmops.zeus.iot.server.library.module.ModuleConfig; +import com.zmops.zeus.server.library.module.ModuleConfig; import lombok.Getter; import lombok.Setter; diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusTelemetryProvider.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusTelemetryProvider.java index 43909f36..d93fa0b1 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusTelemetryProvider.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusTelemetryProvider.java @@ -18,11 +18,11 @@ package com.zmops.zeus.iot.server.telemetry.prometheus; -import com.zmops.zeus.iot.server.library.module.*; import com.zmops.zeus.iot.server.telemetry.TelemetryModule; import com.zmops.zeus.iot.server.telemetry.api.MetricsCollector; import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; import com.zmops.zeus.iot.server.telemetry.prometheus.httpserver.HttpServer; +import com.zmops.zeus.server.library.module.*; import io.prometheus.client.hotspot.DefaultExports; /** diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServer.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServer.java index 623e9612..807b64ea 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServer.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServer.java @@ -19,8 +19,8 @@ package com.zmops.zeus.iot.server.telemetry.prometheus.httpserver; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import com.zmops.zeus.iot.server.library.server.ssl.HttpDynamicSslContext; import com.zmops.zeus.iot.server.telemetry.prometheus.PrometheusConfig; +import com.zmops.zeus.server.ssl.HttpDynamicSslContext; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-telemetry/telemetry-prometheus/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider similarity index 100% rename from iot-server/server-telemetry/telemetry-prometheus/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider rename to iot-server/server-telemetry/telemetry-prometheus/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider diff --git a/iot-server/server-transfer/pom.xml b/iot-server/server-transfer/pom.xml index 7e8296f5..7292f127 100644 --- a/iot-server/server-transfer/pom.xml +++ b/iot-server/server-transfer/pom.xml @@ -18,52 +18,64 @@ - - org.apache.commons - commons-lang3 - 3.12.0 - - - commons-codec - commons-codec - 1.15 - - - org.apache.commons - commons-io - 1.3.2 - com.zmops - library-module - 1.0-beta - - - je - com.sleepycat - 18.3.12 - - - com.alibaba - fastjson - 1.2.58 + zeus-transfer-tailx + 1.0-SNAPSHOT + + + + + + + + + + + + + + + - org.eclipse.jetty - jetty-server - 9.4.34.v20201102 - - - org.eclipse.jetty - jetty-servlet - 9.4.34.v20201102 + com.zmops + library-module + 1.0-SNAPSHOT com.zmops server-core 1.0-beta + compile + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Channel.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Channel.java deleted file mode 100644 index 98a197e4..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Channel.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.api; - -import java.util.concurrent.TimeUnit; - -/** - * Channel is used as data buffer between source and sink. - */ -public interface Channel extends Stage { - - - /** - * write message - * - * @param message - message - */ - void push(Message message); - - /** - * write message with timeout - * - * @param message - * @param timeout - * @param unit - * @return - */ - boolean push(Message message, long timeout, TimeUnit unit); - - /** - * read message with timeout - * - * @param timeout - * @param unit - * @return - */ - Message pull(long timeout, TimeUnit unit); - -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Filter.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Filter.java deleted file mode 100644 index f7b23f39..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Filter.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.api; - -/** - * filter for source split - */ -public interface Filter { - - /** - * whether reader is legal. - * - * @return true if reader is legal else false. - */ - boolean match(); -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Message.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Message.java deleted file mode 100644 index 67d5db84..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Message.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.api; - -import java.util.Map; - -/** - * Message used in inner-data transfer, message is divided into - * two parts, header and body. header is the attributes of message - * and body is the content of message. - */ -public interface Message { - - /** - * Data content of message. - * - * @return bytes body - */ - byte[] getBody(); - - /** - * Data attribute of message - * - * @return map header - */ - Map getHeader(); -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Reader.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Reader.java deleted file mode 100644 index 0e651ae6..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Reader.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.api; - -/** - * Reader reads data and provides condition whether the reading action is finished. It's called at - * Task level. - */ -public interface Reader extends Stage { - - /** - * Read message - * - * @return - message - */ - Message read(); - - /** - * Whether finish reading - * - * @return - */ - boolean isFinished(); - - /** - * Return the reader's reading file name - * - * @return - */ - String getReadFile(); - - /** - * set readTimeout - */ - void setReadTimeout(long mill); -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Sink.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Sink.java deleted file mode 100644 index 3ac66655..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Sink.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.api; - -/** - * Sink data to remote data center - */ -public interface Sink extends Stage { - - /** - * Write data into data center - * - * @param message - message - */ - void write(Message message); - - - /** - * set source file name where the message is generated - * - * @param sourceFileName - */ - void setSourceFile(String sourceFileName); -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Source.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Source.java deleted file mode 100644 index 2393a38e..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Source.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.api; - -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; - -import java.util.List; - -/** - * Source can be split into multiple reader. - */ -public interface Source { - - /** - * Split source into a list of readers. - * - * @param conf job conf - * @return - list of reader - */ - List split(JobProfile conf); -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Stage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Stage.java deleted file mode 100644 index 160e859a..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Stage.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.api; - -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; - -/** - * Stage definition. - */ -public interface Stage { - - /** - * Init job. - * - * @param jobConf - job config - */ - void init(JobProfile jobConf); - - /** - * Destroy job. - */ - void destroy(); -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Trigger.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Trigger.java deleted file mode 100644 index a744a0d6..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Trigger.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.api; - -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; - -import java.io.IOException; - -/** - * Trigger interface, which generates job in condition. - */ -public interface Trigger { - - /** - * init trigger by trigger profile - * - * @param profile - * @throws IOException - */ - void init(TriggerProfile profile) throws IOException; - - /** - * run trigger. - */ - void run(); - - /** - * destroy trigger. - */ - void destroy(); - - /** - * fetch job profile from trigger - * - * @return - job profile - */ - JobProfile fetchJobProfile(); - - /** - * get trigger profile - * - * @return - */ - TriggerProfile getTriggerProfile(); -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Validator.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Validator.java deleted file mode 100644 index 25af38e8..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/api/Validator.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.api; - -/** - * For every message, there might be validators to filter required ones - */ -public interface Validator { - - /** - * @param messageLine - * @return - */ - boolean validate(String messageLine); - -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/AbstractDaemon.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/AbstractDaemon.java deleted file mode 100644 index 7bcdcdcc..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/AbstractDaemon.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.common; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.*; - -/** - * Providing work threads management, those threads run - * periodically until agent is stopped. - */ -public abstract class AbstractDaemon implements Service { - - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractDaemon.class); - - /** - * worker thread pool, share it - **/ - private static final ExecutorService WORKER_SERVICES = new ThreadPoolExecutor( - 0, - Integer.MAX_VALUE, - 60L, - TimeUnit.SECONDS, - new SynchronousQueue(), - new TransferThreadFactory("AbstractDaemon") - ); - - private final List> workerFutures; - - private boolean runnable = true; - - public AbstractDaemon() { - this.workerFutures = new ArrayList<>(); - } - - /** - * Whether threads can in running state with while loop. - * - * @return - true if threads can run - */ - public boolean isRunnable() { - return runnable; - } - - /** - * Stop running threads. - */ - public void stopRunningThreads() { - runnable = false; - } - - /** - * Submit work thread to thread pool. - * - * @param worker - work thread - */ - public void submitWorker(Runnable worker) { - CompletableFuture future = CompletableFuture.runAsync(worker, WORKER_SERVICES); - workerFutures.add(future); - LOGGER.info("{} running worker number is {}", this.getClass().getName(), workerFutures.size()); - } - - /** - * Wait for threads finish. - */ - @Override - public void join() { - for (CompletableFuture future : workerFutures) { - future.join(); - } - } - - /** - * Stop thread pool and running threads if they're in the running state. - */ - public void waitForTerminate() { - // stop running threads. - if (isRunnable()) { - stopRunningThreads(); - } - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/Service.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/Service.java deleted file mode 100644 index ae278dd6..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/Service.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.common; - -/** - * Service lifecycle interface. - */ -public interface Service { - - /** - * start service - * - * @throws Exception - */ - void start() throws Exception; - - /** - * stop service - * - * @throws Exception - */ - void stop() throws Exception; - - /** - * join and wait until getting signal - * - * @throws Exception - */ - void join() throws Exception; -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/TransferThreadFactory.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/TransferThreadFactory.java deleted file mode 100644 index e98925c9..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/common/TransferThreadFactory.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.common; - - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -public class TransferThreadFactory implements ThreadFactory { - - private static final Logger LOGGER = LoggerFactory.getLogger(TransferThreadFactory.class); - - private final AtomicInteger mThreadNum = new AtomicInteger(1); - - private final String threadType; - - public TransferThreadFactory(String threadType) { - this.threadType = threadType; - } - - @Override - public Thread newThread(Runnable r) { - Thread t = new Thread(r, threadType + "-running-thread-" + mThreadNum.getAndIncrement()); - LOGGER.debug("{} created", t.getName()); - return t; - } -} \ No newline at end of file diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java deleted file mode 100644 index 39884351..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/AbstractConfiguration.java +++ /dev/null @@ -1,247 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.conf; - -import com.google.gson.*; -import com.zmops.zeus.iot.server.transfer.utils.TransferUtils; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.StandardCharsets; -import java.util.*; - -public abstract class AbstractConfiguration { - - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractConfiguration.class); - - private static final JsonParser JSON_PARSER = new JsonParser(); - - private final Map configStorage = new HashMap<>(); - - /** - * get config file by class loader - **/ - private ClassLoader classLoader; - - public AbstractConfiguration() { - classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = TransferConfiguration.class.getClassLoader(); - } - } - - /** - * Check whether all required keys exist - * - * @return true if all key exist else false. - */ - public abstract boolean allRequiredKeyExist(); - - /** - * support load config file from json/properties file. - * - * @param fileName - file name - * @param isJson - whether is json file - */ - private void loadResource(String fileName, boolean isJson) { - Reader reader = null; - try { - InputStream inputStream = classLoader.getResourceAsStream(fileName); - if (inputStream != null) { - reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); - if (isJson) { - JsonElement tmpElement = JSON_PARSER.parse(reader).getAsJsonObject(); - updateConfig(new HashMap<>(10), 0, tmpElement); - } else { - Properties properties = new Properties(); - properties.load(reader); - properties.forEach((key, value) -> configStorage.put((String) key, new JsonPrimitive((String) value))); - } - } - } catch (Exception ioe) { - LOGGER.error("error init {}", fileName, ioe); - } finally { - TransferUtils.finallyClose(reader); - } - } - - /** - * load config from json string. - * - * @param jsonStr - json string - */ - public void loadJsonStrResource(String jsonStr) { - JsonElement tmpElement = JSON_PARSER.parse(jsonStr); - updateConfig(new HashMap<>(10), 0, tmpElement); - } - - /** - * load config file from CLASS_PATH. config file is json file. - * - * @param fileName - file name - */ - void loadJsonResource(String fileName) { - loadResource(fileName, true); - } - - void loadPropertiesResource(String fileName) { - loadResource(fileName, false); - } - - /** - * Convert json string to map - * - * @param keyDeptPath - map - * @param dept - json dept - * @param tmpElement - json element - */ - void updateConfig(HashMap keyDeptPath, int dept, JsonElement tmpElement) { - if (tmpElement instanceof JsonObject) { - JsonObject tmpJsonObject = tmpElement.getAsJsonObject(); - for (String key : tmpJsonObject.keySet()) { - keyDeptPath.put(dept, key); - updateConfig(keyDeptPath, dept + 1, tmpJsonObject.get(key)); - } - } else if (tmpElement instanceof JsonArray) { - JsonArray tmpJsonArray = tmpElement.getAsJsonArray(); - String lastKey = keyDeptPath.getOrDefault(dept - 1, ""); - for (int index = 0; index < tmpJsonArray.size(); index++) { - keyDeptPath.put(dept - 1, lastKey + "[" + index + "]"); - updateConfig(keyDeptPath, dept, tmpJsonArray.get(index)); - } - } else if (tmpElement instanceof JsonPrimitive) { - List builder = new ArrayList<>(); - for (int index = 0; index < dept; index++) { - builder.add(keyDeptPath.getOrDefault(index, "")); - } - String keyChain = StringUtils.join(builder, "."); - if (!StringUtils.isBlank(keyChain)) { - configStorage.put(keyChain, tmpElement.getAsJsonPrimitive()); - } - } - } - - /** - * get int from config - * - * @param key - key - * @param defaultValue - default value - * @return value - */ - public int getInt(String key, int defaultValue) { - JsonElement value = configStorage.get(key); - return value == null ? defaultValue : value.getAsInt(); - } - - /** - * get int from config - * - * @param key - key - * @return value - * @throws NullPointerException npe - */ - public int getInt(String key) { - JsonElement value = configStorage.get(key); - if (value == null) { - throw new NullPointerException("null value for key " + key); - } - return value.getAsInt(); - } - - /** - * get long - * - * @param key - key - * @param defaultValue - default value - * @return long - */ - public long getLong(String key, long defaultValue) { - JsonElement value = configStorage.get(key); - return value == null ? defaultValue : value.getAsLong(); - } - - /** - * get boolean - * - * @param key - key - * @param defaultValue - default value - * @return boolean - */ - public boolean getBoolean(String key, boolean defaultValue) { - JsonElement value = configStorage.get(key); - return value == null ? defaultValue : value.getAsBoolean(); - } - - /** - * get string - * - * @param key - key - * @param defaultValue - default value - * @return string - */ - public String get(String key, String defaultValue) { - JsonElement value = configStorage.get(key); - return value == null ? defaultValue : value.getAsString(); - } - - /** - * get string or throw npe - * - * @param key - key - * @return string - * @throws NullPointerException if value is null, throw npe - */ - public String get(String key) { - JsonElement value = configStorage.get(key); - if (value == null) { - throw new NullPointerException("null value for key " + key); - } - return value.getAsString(); - } - - /** - * whether key exists - * - * @param key - key - * @return - true if key exists else not - */ - public boolean hasKey(String key) { - return configStorage.containsKey(key); - } - - /** - * set key/value - * - * @param key - key - * @param value - value - */ - public void set(String key, String value) { - configStorage.put(key, new JsonPrimitive(value)); - } - - public void setInt(String key, int value) { - configStorage.put(key, new JsonPrimitive(value)); - } - - public void setLong(String key, long value) { - configStorage.put(key, new JsonPrimitive(value)); - } - - public void setBoolean(String key, boolean value) { - configStorage.put(key, new JsonPrimitive(value)); - } - - Map getConfigStorage() { - return configStorage; - } - - List getStorageList() { - List result = new ArrayList<>(); - for (Map.Entry entry : configStorage.entrySet()) { - result.add(entry.getKey() + "=" + entry.getValue().getAsString()); - } - return result; - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java deleted file mode 100644 index af24042b..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/CommonConstants.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.conf; - -public class CommonConstants { - - public static final String PROXY_BID = "proxy.bid"; - public static final String POSITION_SUFFIX = ".position"; - - public static final String PROXY_TID = "proxy.tid"; - - // max size of message list - public static final String PROXY_PACKAGE_MAX_SIZE = "proxy.package.maxSize"; - - // max size of single batch in bytes, default is 200KB. - public static final int DEFAULT_PROXY_PACKAGE_MAX_SIZE = 2000000; - - public static final String PROXY_TID_QUEUE_MAX_NUMBER = "proxy.tid.queue.maxNumber"; - - public static final int DEFAULT_PROXY_TID_QUEUE_MAX_NUMBER = 10000; - - public static final String PROXY_PACKAGE_MAX_TIMEOUT_MS = "proxy.package.maxTimeout.ms"; - - public static final int DEFAULT_PROXY_PACKAGE_MAX_TIMEOUT_MS = 4 * 1000; - - public static final String PROXY_BATCH_FLUSH_INTERVAL = "proxy.batch.flush.interval"; - - public static final int DEFAULT_PROXY_BATCH_FLUSH_INTERVAL = 100; - - public static final String PROXY_KEY_BID = "bid"; - public static final String PROXY_KEY_TID = "tid"; - public static final String PROXY_KEY_ID = "id"; - public static final String PROXY_KEY_AGENT_IP = "agentip"; - public static final String PROXY_OCEANUS_F = "f"; - public static final String PROXY_OCEANUS_BL = "bl"; - - - public static final String FILE_MAX_NUM = "file.max.num"; - - public static final int DEFAULT_FILE_MAX_NUM = 4096; - - public static final String TRIGGER_ID_PREFIX = "trigger_"; - - public static final String COMMAND_STORE_INSTANCE_NAME = "commandStore"; - -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java deleted file mode 100644 index 1e21fbdc..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobConstants.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.conf; - - -/** - * Basic config for a single job - */ -public class JobConstants extends CommonConstants { - - // job id - public static final String JOB_ID = "job.id"; - public static final String JOB_INSTANCE_ID = "job.instance.id"; - public static final String JOB_IP = "job.ip"; - public static final String JOB_RETRY = "job.retry"; - - public static final String JOB_TRIGGER = "job.trigger"; - public static final String JOB_NAME = "job.name"; - public static final String JOB_LINE_FILTER_PATTERN = "job.pattern"; - public static final String DEFAULT_JOB_NAME = "default"; - public static final String JOB_DESCRIPTION = "job.description"; - public static final String DEFAULT_JOB_DESCRIPTION = "default job description"; - public static final String DEFAULT_JOB_LINE_FILTER = ""; - - // job type, delete/add - public static final String JOB_TYPE = "job.type"; - - public static final String JOB_CHECKPOINT = "job.checkpoint"; - - // offset for time - public static final String JOB_FILE_TIME_OFFSET = "job.timeOffset"; - - public static final String DEFAULT_JOB_FILE_TIME_OFFSET = "0d"; - - public static final String JOB_FILE_MAX_WAIT = "job.file.max.wait"; - // time in min - public static final int DEFAULT_JOB_FILE_MAX_WAIT = 1; - - public static final String JOB_DIR_FILTER_PATTERN = "job.dir.pattern"; - - public static final String JOB_DIR_FILTER_PATH = "job.dir.path"; - - public static final String JOB_ID_PREFIX = "job_"; - - public static final String JOB_STORE_TIME = "job.store.time"; - - public static final String JOB_OP = "job.op"; - - public static final String TRIGGER_ONLY_ONE_JOB = "job.standalone"; - - // field splitter - public static final String JOB_FIELD_SPLITTER = "job.splitter"; - - public static final String JOB_ADDITION_STR = "job.additionStr"; - - // job delivery time - public static final String JOB_DELIVERY_TIME = "job.deliveryTime"; - - // job time reading file - public static final String JOB_DATA_TIME = "job.dataTime"; - - public static final String JOB_CYCLE_UNIT = "job.cycleUnit"; - - /** - * when job is retried, the retry time should be provided - */ - public static final String JOB_RETRY_TIME = "job.retryTime"; - -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobProfile.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobProfile.java deleted file mode 100644 index 61f022cb..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/JobProfile.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.conf; - -import com.google.gson.Gson; - - -/** - * job profile which contains details describing properties of one job. - */ -public class JobProfile extends AbstractConfiguration { - - private final Gson gson = new Gson(); - - /** - * parse json string to configuration instance。 - * - * @param jsonStr - * @return job configuration - */ - public static JobProfile parseJsonStr(String jsonStr) { - JobProfile conf = new JobProfile(); - conf.loadJsonStrResource(jsonStr); - return conf; - } - - /** - * parse properties file - * - * @param fileName - file name. - * @return jobConfiguration. - */ - public static JobProfile parsePropertiesFile(String fileName) { - JobProfile conf = new JobProfile(); - conf.loadPropertiesResource(fileName); - return conf; - } - - /** - * pase json file. - * - * @param fileName - json file name. - * @return jobConfiguration. - */ - public static JobProfile parseJsonFile(String fileName) { - JobProfile conf = new JobProfile(); - conf.loadJsonResource(fileName); - return conf; - } - - /** - * check whether required keys exists. - * - * @return return true if all required keys exists else false. - */ - @Override - public boolean allRequiredKeyExist() { - return hasKey(JobConstants.JOB_ID); - } - - public String toJsonStr() { - return gson.toJson(getConfigStorage()); - } - - public String getInstanceId() { - return get(JobConstants.JOB_INSTANCE_ID); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConfiguration.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConfiguration.java deleted file mode 100644 index f12321f7..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConfiguration.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.conf; - -import org.apache.commons.io.FileUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -/** - * agent configuration. Only one instance in the process. - * Basically it use properties file to store configurations. - */ -public class TransferConfiguration extends AbstractConfiguration { - - private static final Logger LOGGER = LoggerFactory.getLogger(TransferConfiguration.class); - - private static final String DEFAULT_CONFIG_FILE = "tansfer.properties"; - private static final String TMP_CONFIG_FILE = ".tmp.agent.properties"; - - private static final ArrayList LOCAL_RESOURCES = new ArrayList<>(); - - private static final ReadWriteLock LOCK = new ReentrantReadWriteLock(); - - static { - LOCAL_RESOURCES.add(DEFAULT_CONFIG_FILE); - } - - private static volatile TransferConfiguration transferConfig = null; - - /** - * load config from agent file. - */ - private TransferConfiguration() { - for (String fileName : LOCAL_RESOURCES) { - super.loadPropertiesResource(fileName); - } - } - - /** - * singleton for agent configuration. - * - * @return - static instance of AgentConfiguration - */ - public static TransferConfiguration getAgentConf() { - if (transferConfig == null) { - synchronized (TransferConfiguration.class) { - if (transferConfig == null) { - transferConfig = new TransferConfiguration(); - } - } - } - return transferConfig; - } - - private String getNextBackupFileName() { - SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); - String dateStr = format.format(new Date(System.currentTimeMillis())); - return DEFAULT_CONFIG_FILE + "." + dateStr; - } - - /** - * flush config to local files. - */ - public void flushToLocalPropertiesFile() { - LOCK.writeLock().lock(); - // TODO: flush to local file as properties file. - try { - String agentConfParent = get(TransferConstants.AGENT_CONF_PARENT, TransferConstants.DEFAULT_AGENT_CONF_PARENT); - - File sourceFile = new File(agentConfParent, DEFAULT_CONFIG_FILE); - File targetFile = new File(agentConfParent, getNextBackupFileName()); - File tmpFile = new File(agentConfParent, TMP_CONFIG_FILE); - - if (sourceFile.exists()) { - FileUtils.copyFile(sourceFile, targetFile); - } - - List tmpCache = getStorageList(); - FileUtils.writeLines(tmpFile, tmpCache); - - FileUtils.copyFile(tmpFile, sourceFile); - boolean result = tmpFile.delete(); - if (!result) { - LOGGER.warn("cannot delete file {}", tmpFile); - } - } catch (Exception ex) { - LOGGER.error("error while flush agent conf to local", ex); - } finally { - LOCK.writeLock().unlock(); - } - - } - - @Override - public boolean allRequiredKeyExist() { - return true; - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java deleted file mode 100644 index 78334d88..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TransferConstants.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.conf; - -public class TransferConstants { - - public static final String AGENT_HOME = "agent.home"; - public static final String DEFAULT_AGENT_HOME = System.getProperty("agent.home"); - - - public static final String AGENT_LOCAL_STORE_PATH = "agent.localStore.path"; - public static final String DEFAULT_AGENT_LOCAL_STORE_PATH = ".bdb"; - - public static final String AGENT_DB_INSTANCE_NAME = "agent.db.instance.name"; - public static final String DEFAULT_AGENT_DB_INSTANCE_NAME = "agent"; - - public static final String AGENT_DB_CLASSNAME = "agent.db.classname"; - public static final String DEFAULT_AGENT_DB_CLASSNAME = "com.zmops.zeus.iot.server.transfer.core.db.BerkeleyDbImp"; - - public static final String AGENT_CONF_PARENT = "agent.conf.parent"; - public static final String DEFAULT_AGENT_CONF_PARENT = "conf"; - - public static final String AGENT_LOCAL_STORE_READONLY = "agent.localStore.readonly"; - public static final boolean DEFAULT_AGENT_LOCAL_STORE_READONLY = false; - - public static final String TRIGGER_FETCH_INTERVAL = "trigger.fetch.interval"; - public static final int DEFAULT_TRIGGER_FETCH_INTERVAL = 1; - - public static final String TRIGGER_MAX_RUNNING_NUM = "trigger.max.running.num"; - public static final int DEFAULT_TRIGGER_MAX_RUNNING_NUM = 4096; - - public static final String AGENT_LOCAL_STORE_TRANSACTIONAL = "agent.localStore.transactional"; - public static final boolean DEFAULT_AGENT_LOCAL_STORE_TRANSACTIONAL = true; - - public static final String AGENT_LOCAL_STORE_LOCK_TIMEOUT = "agent.localStore.lockTimeout"; - public static final int DEFAULT_AGENT_LOCAL_STORE_LOCK_TIMEOUT = 10000; - - public static final String AGENT_LOCAL_STORE_NO_SYNC_VOID = "agent.localStore.noSyncVoid"; - public static final boolean DEFAULT_AGENT_LOCAL_STORE_NO_SYNC_VOID = false; - - public static final String AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID = "agent.localStore.WriteNoSyncVoid"; - public static final boolean DEFAULT_AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID = false; - - - public static final String THREAD_POOL_AWAIT_TIME = "thread.pool.await.time"; - // time in ms - public static final long DEFAULT_THREAD_POOL_AWAIT_TIME = 300; - - - public static final String JOB_MONITOR_INTERVAL = "job.monitor.interval"; - public static final int DEFAULT_JOB_MONITOR_INTERVAL = 5; - - - public static final String JOB_FINISH_CHECK_INTERVAL = "job.finish.checkInterval"; - public static final long DEFAULT_JOB_FINISH_CHECK_INTERVAL = 6L; - - public static final String TASK_RETRY_MAX_CAPACITY = "task.retry.maxCapacity"; - public static final int DEFAULT_TASK_RETRY_MAX_CAPACITY = 10000; - - public static final String TASK_MONITOR_INTERVAL = "task.monitor.interval"; - public static final int DEFAULT_TASK_MONITOR_INTERVAL = 6; - - public static final String TASK_RETRY_SUBMIT_WAIT_SECONDS = "task.retry.submit.waitSeconds"; - public static final int DEFAULT_TASK_RETRY_SUBMIT_WAIT_SECONDS = 5; - - public static final String TASK_MAX_RETRY_TIME = "task.maxRetry.time"; - public static final int DEFAULT_TASK_MAX_RETRY_TIME = 3; - - public static final String TASK_PUSH_MAX_SECOND = "task.push.maxSecond"; - public static final int DEFAULT_TASK_PUSH_MAX_SECOND = 2; - - public static final String TASK_PULL_MAX_SECOND = "task.pull.maxSecond"; - public static final int DEFAULT_TASK_PULL_MAX_SECOND = 2; - - public static final String CHANNEL_MEMORY_CAPACITY = "channel.memory.capacity"; - public static final int DEFAULT_CHANNEL_MEMORY_CAPACITY = 10000; - - public static final String TRIGGER_CHECK_INTERVAL = "trigger.check.interval"; - public static final int DEFAULT_TRIGGER_CHECK_INTERVAL = 2; - - public static final String JOB_DB_CACHE_TIME = "job.db.cache.time"; - // cache for 3 days. - public static final long DEFAULT_JOB_DB_CACHE_TIME = 3 * 24 * 60 * 60 * 1000; - - public static final String JOB_DB_CACHE_CHECK_INTERVAL = "job.db.cache.check.interval"; - public static final int DEFAULT_JOB_DB_CACHE_CHECK_INTERVAL = 60 * 60; - - -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TriggerProfile.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TriggerProfile.java deleted file mode 100644 index 4facae51..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/conf/TriggerProfile.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.conf; - -/** - * profile used in trigger. Trigger profile is a special job profile - */ -public class TriggerProfile extends JobProfile { - - @Override - public boolean allRequiredKeyExist() { - return hasKey(JobConstants.JOB_NAME) && super.allRequiredKeyExist(); - } - - public static TriggerProfile parseJsonStr(String jsonStr) { - TriggerProfile conf = new TriggerProfile(); - conf.loadJsonStrResource(jsonStr); - return conf; - } - - public String getTriggerId() { - return get(JobConstants.JOB_ID); - } - - public static TriggerProfile parseJobProfile(JobProfile jobProfile) { - TriggerProfile conf = new TriggerProfile(); - conf.loadJsonStrResource(jobProfile.toJsonStr()); - return conf; - } - - public Integer getOpType() { - return getInt(JobConstants.JOB_OP); - } - - public String getDeliveryTime() { - return get(JobConstants.JOB_DELIVERY_TIME); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/FileException.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/FileException.java deleted file mode 100644 index b88603ab..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/FileException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core; - -public class FileException extends RuntimeException { - - public FileException(String message, Throwable ex) { - super(message, ex); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/TransferManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/TransferManager.java deleted file mode 100644 index bbffccdf..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/TransferManager.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core; - -import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; -import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; -import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; -import com.zmops.zeus.iot.server.transfer.core.db.Db; -import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; -import com.zmops.zeus.iot.server.transfer.core.db.TriggerProfileDb; -import com.zmops.zeus.iot.server.transfer.core.job.CommandDb; -import com.zmops.zeus.iot.server.transfer.core.job.JobManager; -import com.zmops.zeus.iot.server.transfer.core.task.TaskManager; -import com.zmops.zeus.iot.server.transfer.core.task.TaskPositionManager; -import com.zmops.zeus.iot.server.transfer.core.trigger.TriggerManager; -import com.zmops.zeus.iot.server.transfer.provider.ServerTransferConfig; -import lombok.Getter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.*; - -/** - * Zabbix History Data Transfer - */ -public class TransferManager extends AbstractDaemon { - - private static final Logger LOGGER = LoggerFactory.getLogger(TransferManager.class); - - @Getter - private final JobManager jobManager; - - @Getter - private final TaskManager taskManager; - - @Getter - private final TriggerManager triggerManager; - - @Getter - private final TaskPositionManager taskPositionManager; - - private final TransferConfiguration conf; - - @Getter - private final Db db; - - @Getter - private final CommandDb commandDb; - - @Getter - private final ServerTransferConfig moduleConfig; - - public TransferManager(ServerTransferConfig config) { - moduleConfig = config; - - conf = TransferConfiguration.getAgentConf(); - this.db = initDb(); - commandDb = new CommandDb(db); - - triggerManager = new TriggerManager(this, new TriggerProfileDb(db)); - jobManager = new JobManager(this, new JobProfileDb(db)); - taskManager = new TaskManager(this); - taskPositionManager = TaskPositionManager.getTaskPositionManager(this); - } - - /** - * init db by class name - * - * @return db - */ - private Db initDb() { - try { - // db is a required component, so if not init correctly, throw exception and stop running. - return (Db) Class.forName(conf.get(TransferConstants.AGENT_DB_CLASSNAME, TransferConstants.DEFAULT_AGENT_DB_CLASSNAME)).newInstance(); - } catch (Exception ex) { - throw new UnsupportedClassVersionError(ex.getMessage()); - } - } - - @Override - public void join() { - super.join(); - jobManager.join(); - taskManager.join(); - } - - @Override - public void start() throws Exception { - LOGGER.info("starting zeus-transfer manager"); - - triggerManager.start(); - jobManager.start(); - taskManager.start(); - taskPositionManager.start(); - - JobProfile profile = JobProfile.parseJsonFile("job.json"); - profile.setInt(JOB_FILE_MAX_WAIT, moduleConfig.getFileMaxWait()); - profile.set(JOB_NAME, moduleConfig.getName()); - profile.set(JOB_DIR_FILTER_PATTERN, moduleConfig.getPattern()); - - TriggerProfile triggerProfile = TriggerProfile.parseJobProfile(profile); - triggerManager.addTrigger(triggerProfile); - -// jobManager.submitJobProfile(profile); - } - - /** - * It should guarantee thread-safe, and can be invoked many times. - * - * @throws Exception exceptions - */ - @Override - public void stop() throws Exception { - - // TODO: change job state which is in running state. - LOGGER.info("stopping agent manager"); - - // close in order: trigger -> job -> task - triggerManager.stop(); - jobManager.stop(); - taskManager.stop(); - taskPositionManager.stop(); - this.db.close(); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java deleted file mode 100644 index bad87241..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/channel/MemoryChannel.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.channel; - - -import com.zmops.zeus.iot.server.transfer.api.Channel; -import com.zmops.zeus.iot.server.transfer.api.Message; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; -import com.zmops.zeus.iot.server.transfer.metrics.PluginMetric; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; - -public class MemoryChannel implements Channel { - - private static final Logger LOGGER = LoggerFactory.getLogger(MemoryChannel.class); - - private LinkedBlockingQueue queue; - - private final PluginMetric metric = new PluginMetric(); - - /** - * {@inheritDoc} - */ - @Override - public void push(Message message) { - try { - if (message != null) { - metric.readNum.incr(); - queue.put(message); - metric.readSuccessNum.incr(); - } - } catch (InterruptedException ex) { - metric.readFailedNum.incr(); - Thread.currentThread().interrupt(); - } - } - - @Override - public boolean push(Message message, long timeout, TimeUnit unit) { - try { - if (message != null) { - metric.readNum.incr(); - boolean result = queue.offer(message, timeout, unit); - if (result) { - metric.readSuccessNum.incr(); - } else { - metric.readFailedNum.incr(); - } - return result; - } - } catch (InterruptedException ex) { - metric.readFailedNum.incr(); - Thread.currentThread().interrupt(); - } - return false; - } - - /** - * {@inheritDoc} - */ - @Override - public Message pull(long timeout, TimeUnit unit) { - try { - Message message = queue.poll(timeout, unit); - if (message != null) { - metric.sendSuccessNum.incr(); - } - return message; - } catch (InterruptedException ex) { - metric.sendFailedNum.incr(); - Thread.currentThread().interrupt(); - throw new IllegalStateException(ex); - } - } - - @Override - public void init(JobProfile jobConf) { - queue = new LinkedBlockingQueue<>(jobConf.getInt(TransferConstants.CHANNEL_MEMORY_CAPACITY, - TransferConstants.DEFAULT_CHANNEL_MEMORY_CAPACITY)); - } - - @Override - public void destroy() { - if (queue != null) { - queue.clear(); - } - LOGGER.info("destroy channel, memory channel metric, readNum: {}, readSuccessNum: {}, " - + "readFailedNum: {}, sendSuccessNum: {}, sendFailedNum: {}", - metric.readNum.snapshot(), - metric.readSuccessNum.snapshot(), - metric.readFailedNum.snapshot(), - metric.sendSuccessNum.snapshot(), - metric.sendFailedNum.snapshot()); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java deleted file mode 100644 index a83c1f91..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/BerkeleyDbImp.java +++ /dev/null @@ -1,204 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.db; - -import com.sleepycat.je.Environment; -import com.sleepycat.je.EnvironmentConfig; -import com.sleepycat.persist.*; -import com.zmops.zeus.iot.server.transfer.conf.CommonConstants; -import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; -import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; -import com.zmops.zeus.iot.server.transfer.core.job.CommandEntity; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import static java.util.Objects.requireNonNull; - -/** - * DB implement based on berkeley db. - */ -public class BerkeleyDbImp implements Db { - - private static final Logger LOGGER = LoggerFactory.getLogger(BerkeleyDbImp.class); - - private final EntityStore jobStore; - private final EntityStore commandStore; - - private final PrimaryIndex primaryIndex; - private final SecondaryIndex secondaryIndex; - private final PrimaryIndex commandPrimaryIndex; - - private final SecondaryIndex fileNameSecondaryIndex; - private final SecondaryIndex commandSecondaryIndex; - - private final TransferConfiguration transferConfig; - - public BerkeleyDbImp() { - - this.transferConfig = TransferConfiguration.getAgentConf(); - - StoreConfig storeConfig = initStoreConfig(); - Environment environment = initEnv(); - - String instanceName = transferConfig.get(TransferConstants.AGENT_DB_INSTANCE_NAME, TransferConstants.DEFAULT_AGENT_DB_INSTANCE_NAME); - - this.jobStore = new EntityStore(environment, instanceName, storeConfig); - this.commandStore = new EntityStore(environment, CommonConstants.COMMAND_STORE_INSTANCE_NAME, storeConfig); - - commandPrimaryIndex = this.commandStore.getPrimaryIndex(String.class, CommandEntity.class); - - commandSecondaryIndex = commandStore.getSecondaryIndex(commandPrimaryIndex, Boolean.class, "isAcked"); - - primaryIndex = this.jobStore.getPrimaryIndex(String.class, KeyValueEntity.class); - secondaryIndex = this.jobStore.getSecondaryIndex(primaryIndex, StateSearchKey.class, "stateSearchKey"); - - fileNameSecondaryIndex = this.jobStore.getSecondaryIndex(primaryIndex, String.class, "fileName"); - } - - /** - * init store by config - * - * @return store config - */ - private StoreConfig initStoreConfig() { - return new StoreConfig() - .setReadOnly(transferConfig.getBoolean(TransferConstants.AGENT_LOCAL_STORE_READONLY, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_READONLY)) - .setAllowCreate(!transferConfig.getBoolean(TransferConstants.AGENT_LOCAL_STORE_READONLY, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_READONLY)) - .setTransactional(transferConfig.getBoolean(TransferConstants.AGENT_LOCAL_STORE_TRANSACTIONAL, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_TRANSACTIONAL)); - } - - /** - * init local bdb path and get it. - * - * @return local path. - */ - private File tryToInitAndGetPath() { - String storePath = transferConfig.get(TransferConstants.AGENT_LOCAL_STORE_PATH, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_PATH); - String parentPath = transferConfig.get(TransferConstants.AGENT_HOME, TransferConstants.DEFAULT_AGENT_HOME); - - File finalPath = new File(parentPath, storePath); - try { - boolean result = finalPath.mkdirs(); - LOGGER.info("try to create local path {}, result is {}", finalPath, result); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - return finalPath; - } - - /** - * init env by config - * - * @return env config - */ - private Environment initEnv() { - EnvironmentConfig envConfig = new EnvironmentConfig() - .setReadOnly(transferConfig.getBoolean(TransferConstants.AGENT_LOCAL_STORE_READONLY, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_READONLY)) - .setAllowCreate(!transferConfig.getBoolean(TransferConstants.AGENT_LOCAL_STORE_READONLY, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_READONLY)) - .setTransactional(transferConfig.getBoolean(TransferConstants.AGENT_LOCAL_STORE_TRANSACTIONAL, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_TRANSACTIONAL)) - .setLockTimeout(transferConfig.getInt(TransferConstants.AGENT_LOCAL_STORE_LOCK_TIMEOUT, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_LOCK_TIMEOUT), TimeUnit.MILLISECONDS); - - envConfig.setTxnNoSyncVoid(transferConfig.getBoolean(TransferConstants.AGENT_LOCAL_STORE_NO_SYNC_VOID, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_NO_SYNC_VOID)); - envConfig.setTxnWriteNoSyncVoid(transferConfig.getBoolean(TransferConstants.AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID, TransferConstants.DEFAULT_AGENT_LOCAL_STORE_WRITE_NO_SYNC_VOID)); - return new Environment(tryToInitAndGetPath(), envConfig); - } - - @Override - public KeyValueEntity get(String key) { - requireNonNull(key); - return primaryIndex.get(key); - } - - - @Override - public CommandEntity getCommand(String commandId) { - requireNonNull(commandId); - return commandPrimaryIndex.get(commandId); - } - - - @Override - public CommandEntity putCommand(CommandEntity entity) { - requireNonNull(entity); - return commandPrimaryIndex.put(entity); - } - - @Override - public void set(KeyValueEntity entity) { - requireNonNull(entity); - primaryIndex.put(entity); - } - - @Override - public KeyValueEntity put(KeyValueEntity entity) { - requireNonNull(entity); - return primaryIndex.put(entity); - } - - @Override - public KeyValueEntity remove(String key) { - requireNonNull(key); - KeyValueEntity entity = primaryIndex.get(key); - primaryIndex.delete(key); - return entity; - } - - @Override - public List search(StateSearchKey searchKey) { - requireNonNull(searchKey); - List ret = new ArrayList<>(); - - try (EntityCursor children = secondaryIndex.subIndex(searchKey).entities()) { - for (KeyValueEntity entity : children) { - ret.add(entity); - } - } - return ret; - } - - @Override - public List searchCommands(boolean isAcked) { - requireNonNull(isAcked); - List ret = new ArrayList<>(); - try (EntityCursor children = commandSecondaryIndex.subIndex(isAcked).entities()) { - for (CommandEntity entity : children) { - ret.add(entity); - } - } - return ret; - } - - @Override - public KeyValueEntity searchOne(StateSearchKey searchKey) { - requireNonNull(searchKey); - return secondaryIndex.get(searchKey); - } - - @Override - public KeyValueEntity searchOne(String fileName) { - requireNonNull(fileName); - return fileNameSecondaryIndex.get(fileName); - } - - @Override - public List findAll(String prefix) { - requireNonNull(prefix); - List ret = new ArrayList<>(); - try (EntityCursor children = primaryIndex.entities()) { - for (KeyValueEntity entity : children) { - if (entity.getKey().startsWith(prefix)) { - ret.add(entity); - } - } - } - return ret; - } - - @Override - public void close() { - jobStore.close(); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/Db.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/Db.java deleted file mode 100644 index 8a250cfb..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/Db.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.db; - -import com.zmops.zeus.iot.server.transfer.core.job.CommandEntity; - -import javax.management.openmbean.KeyAlreadyExistsException; -import java.io.Closeable; -import java.util.List; - -/** - * local storage for key/value. - */ -public interface Db extends Closeable { - - - abstract KeyValueEntity get(String key); - - /** - * get command by command id - * - * @param commandId - * @return - */ - CommandEntity getCommand(String commandId); - - /** - * put command entity in db - * - * @param entity - * @return - */ - CommandEntity putCommand(CommandEntity entity); - - /** - * store keyValue, if key has exists, throw exception. - * - * @param entity - key/value - * @throws NullPointerException key should not be null - * @throws KeyAlreadyExistsException key already exists - */ - void set(KeyValueEntity entity); - - /** - * store keyValue, if key has exists, overwrite it. - * - * @param entity - key/value - * @return null or old value which is overwritten. - * @throws NullPointerException key should not be null. - */ - KeyValueEntity put(KeyValueEntity entity); - - /** - * remove keyValue by key. - * - * @param key - key - * @return key/value - * @throws NullPointerException key should not be null. - */ - KeyValueEntity remove(String key); - - /** - * search keyValue list by search key. - * - * @param searchKey - search keys. - * @return key/value list - * @throws NullPointerException search key should not be null. - */ - List search(StateSearchKey searchKey); - - /** - * search commands using ack status - * - * @param isAcked - * @return - */ - List searchCommands(boolean isAcked); - - /** - * search one keyValue by search key - * - * @param searchKey - search key - * @return null or keyValue - */ - KeyValueEntity searchOne(StateSearchKey searchKey); - - /** - * search one keyValue by fileName - * - * @param fileName - * @return - */ - KeyValueEntity searchOne(String fileName); - - /** - * find all by prefix key. - * - * @param prefix - prefix string - * @return list of k/v - */ - List findAll(String prefix); -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java deleted file mode 100644 index 4ceaf5be..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/JobProfileDb.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - - */ -package com.zmops.zeus.iot.server.transfer.core.db; - - -import com.zmops.zeus.iot.server.transfer.conf.JobConstants; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; - -/** - * Wrapper for job conf persistence. - */ -public class JobProfileDb { - private static final Logger LOGGER = LoggerFactory.getLogger(JobProfileDb.class); - private final Db db; - - public JobProfileDb(Db db) { - this.db = db; - } - - /** - * get job which in accepted state - * - * @return null or job conf - */ - public JobProfile getAcceptedJob() { - return getJob(StateSearchKey.ACCEPTED); - } - - public List getAcceptedJobs() { - return getJobs(StateSearchKey.ACCEPTED); - } - - /** - * update job state and search it by key name - * - * @param jobInstanceId - job key name - * @param stateSearchKey - job state - */ - public void updateJobState(String jobInstanceId, StateSearchKey stateSearchKey) { - KeyValueEntity entity = db.get(jobInstanceId); - if (entity != null) { - entity.setStateSearchKey(stateSearchKey); - db.put(entity); - } - } - - /** - * store job profile - * - * @param jobProfile - job profile - */ - public void storeJobFirstTime(JobProfile jobProfile) { - if (jobProfile.allRequiredKeyExist()) { - - String keyName = jobProfile.get(JobConstants.JOB_INSTANCE_ID); - jobProfile.setLong(JobConstants.JOB_STORE_TIME, System.currentTimeMillis()); - - KeyValueEntity entity = new KeyValueEntity(keyName, jobProfile.toJsonStr(), jobProfile.get(JobConstants.JOB_DIR_FILTER_PATTERN)); - entity.setStateSearchKey(StateSearchKey.ACCEPTED); - db.put(entity); - } - } - - /** - * update job profile - * - * @param jobProfile - */ - public void updateJobProfile(JobProfile jobProfile) { - String instanceId = jobProfile.getInstanceId(); - KeyValueEntity entity = db.get(instanceId); - if (entity == null) { - LOGGER.warn("job profile {} doesn't exist, update job profile fail {}", instanceId, jobProfile.toJsonStr()); - return; - } - entity.setJsonValue(jobProfile.toJsonStr()); - db.put(entity); - } - - /** - * check whether job is finished, note that non-exist job is regarded as finished. - * - * @param jobProfile - * @return - */ - public boolean checkJobfinished(JobProfile jobProfile) { - KeyValueEntity entity = db.get(jobProfile.getInstanceId()); - if (entity == null) { - LOGGER.info("job profile {} doesn't exist", jobProfile.getInstanceId()); - return true; - } - return entity.checkFinished(); - } - - public void deleteJob(String keyName) { - db.remove(keyName); - } - - public JobProfile getJobProfile(String jobId) { - KeyValueEntity keyValueEntity = db.get(jobId); - if (keyValueEntity != null) { - return keyValueEntity.getAsJobProfile(); - } - return null; - } - - public void removeExpireJobs(long expireTime) { - // remove finished tasks - List successEntityList = db.search(StateSearchKey.SUCCESS); - List failedEntityList = db.search(StateSearchKey.FAILED); - - List entityList = new ArrayList<>(successEntityList); - - entityList.addAll(failedEntityList); - - for (KeyValueEntity entity : entityList) { - if (entity.getKey().startsWith(JobConstants.JOB_ID_PREFIX)) { - JobProfile profile = entity.getAsJobProfile(); - - long storeTime = profile.getLong(JobConstants.JOB_STORE_TIME, 0); - long currentTime = System.currentTimeMillis(); - - if (storeTime == 0 || currentTime - storeTime > expireTime) { - LOGGER.info("delete job {} because of timeout store time: {}, expire time: {}", entity.getKey(), storeTime, expireTime); - deleteJob(entity.getKey()); - } - } - } - } - - /** - * get job conf by state - * - * @param stateSearchKey - state index for searching. - * @return - */ - public JobProfile getJob(StateSearchKey stateSearchKey) { - KeyValueEntity entity = db.searchOne(stateSearchKey); - if (entity != null && entity.getKey().startsWith(JobConstants.JOB_ID_PREFIX)) { - return entity.getAsJobProfile(); - } - return null; - } - - - /** - * get job reading specific file - * - * @param fileName - * @return - */ - public JobProfile getJob(String fileName) { - KeyValueEntity entity = db.searchOne(fileName); - if (entity != null && entity.getKey().startsWith(JobConstants.JOB_ID_PREFIX)) { - return entity.getAsJobProfile(); - } - return null; - } - - /** - * get list of job profiles. - * - * @param stateSearchKey - state search key. - * @return - list of job profile. - */ - public List getJobs(StateSearchKey stateSearchKey) { - List entityList = db.search(stateSearchKey); - List profileList = new ArrayList<>(); - for (KeyValueEntity entity : entityList) { - if (entity.getKey().startsWith(JobConstants.JOB_ID_PREFIX)) { - profileList.add(entity.getAsJobProfile()); - } - } - return profileList; - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/KeyValueEntity.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/KeyValueEntity.java deleted file mode 100644 index c423c264..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/KeyValueEntity.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.db; - -import com.sleepycat.persist.model.Entity; -import com.sleepycat.persist.model.PrimaryKey; -import com.sleepycat.persist.model.Relationship; -import com.sleepycat.persist.model.SecondaryKey; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; - -/** - * key value entity. key is string and value is a json - */ -@Entity(version = 1) -public class KeyValueEntity { - - @PrimaryKey - private String key; - - @SecondaryKey(relate = Relationship.MANY_TO_ONE) - private StateSearchKey stateSearchKey; - - /** - * stores the file name that the jsonValue refers - */ - @SecondaryKey(relate = Relationship.MANY_TO_ONE) - private String fileName; - - private String jsonValue; - - public KeyValueEntity() { - } - - public KeyValueEntity(String key, String jsonValue, String fileName) { - this.key = key; - this.jsonValue = jsonValue; - this.stateSearchKey = StateSearchKey.ACCEPTED; - this.fileName = fileName; - } - - public String getKey() { - return key; - } - - public StateSearchKey getStateSearchKey() { - return stateSearchKey; - } - - public KeyValueEntity setStateSearchKey(StateSearchKey stateSearchKey) { - this.stateSearchKey = stateSearchKey; - return this; - } - - public String getJsonValue() { - return jsonValue; - } - - public KeyValueEntity setJsonValue(String jsonValue) { - this.jsonValue = jsonValue; - return this; - } - - /** - * convert keyValue to job profile - * - * @return JobConfiguration - */ - public JobProfile getAsJobProfile() { - // convert jsonValue to jobConfiguration - return JobProfile.parseJsonStr(getJsonValue()); - } - - /** - * convert keyValue to trigger profile - * - * @return - */ - public TriggerProfile getAsTriggerProfile() { - return TriggerProfile.parseJsonStr(getJsonValue()); - } - - /** - * check whether the entity is finished - * - * @return - */ - public boolean checkFinished() { - return stateSearchKey.equals(StateSearchKey.SUCCESS) || stateSearchKey.equals(StateSearchKey.FAILED); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/StateSearchKey.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/StateSearchKey.java deleted file mode 100644 index efdf1dda..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/StateSearchKey.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.db; - -/** - * search key for state. - */ -public enum StateSearchKey { - // success state - SUCCESS, - // fail state - FAILED, - // accepted state - ACCEPTED, - // running state - RUNNING -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/TriggerProfileDb.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/TriggerProfileDb.java deleted file mode 100644 index 958e15f7..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/db/TriggerProfileDb.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.db; - -import com.zmops.zeus.iot.server.transfer.conf.CommonConstants; -import com.zmops.zeus.iot.server.transfer.conf.JobConstants; -import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; - -/** - * db interface for trigger profile. - *

- * 保存 文件夹触发器 配置文件 - */ -public class TriggerProfileDb { - - private static final Logger LOGGER = LoggerFactory.getLogger(TriggerProfileDb.class); - - private final Db db; - - public TriggerProfileDb(Db db) { - this.db = db; - } - - /** - * get trigger list from db. - * - * @return - list of trigger - */ - public List getTriggers() { - // potential performance issue, needs to find out the speed. - List result = this.db.findAll(CommonConstants.TRIGGER_ID_PREFIX); - - List triggerList = new ArrayList<>(); - - for (KeyValueEntity entity : result) { - triggerList.add(entity.getAsTriggerProfile()); - } - - return triggerList; - } - - /** - * store trigger profile. - * - * @param trigger - trigger - */ - public void storeTrigger(TriggerProfile trigger) { - if (trigger.allRequiredKeyExist()) { - String keyName = CommonConstants.TRIGGER_ID_PREFIX + trigger.get(JobConstants.JOB_ID); - - KeyValueEntity entity = new KeyValueEntity(keyName, trigger.toJsonStr(), trigger.get(JobConstants.JOB_DIR_FILTER_PATTERN)); - - KeyValueEntity oldEntity = db.put(entity); - - if (oldEntity != null) { - LOGGER.warn("trigger profile {} has been replaced", oldEntity.getKey()); - } - } - } - - /** - * delete trigger by id. - * - * @param id - */ - public void deleteTrigger(String id) { - db.remove(CommonConstants.TRIGGER_ID_PREFIX + id); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java deleted file mode 100644 index 7c100db1..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/filter/DateFormatRegex.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.filter; - -import com.zmops.zeus.iot.server.transfer.api.Filter; -import com.zmops.zeus.iot.server.transfer.utils.TransferUtils; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -/** - * date format with regex string for absolute file path. - */ -public class DateFormatRegex implements Filter { - private static final Logger LOGGER = LoggerFactory.getLogger(DateFormatRegex.class); - - private static final String YEAR = "YYYY"; - private static final String MONTH = "MM"; - private static final String DAY = "DD"; - private static final String HOUR = "HH"; - - private static final String NORMAL_FORMATTER = "yyyyMMddHHmm"; - - private static final String OFFSET_DAY = "d"; - private static final String OFFSET_MIN = "m"; - private static final String OFFSET_HOUR = "h"; - - private int dayOffset = 0; - private int hourOffset = 0; - private int minuteOffset = 0; - - private String formattedTime = ""; - private String formattedRegex; - private File file; - - /** - * set regex with current time - * - * @param regex - * @return - */ - public static DateFormatRegex ofRegex(String regex) { - DateFormatRegex dateFormatRegex = new DateFormatRegex(); - dateFormatRegex.setRegexWithCurrentTime(regex); - return dateFormatRegex; - } - - @Override - public boolean match() { - // TODO: check with more regex - return TransferUtils.regexMatch(file.getAbsolutePath(), formattedRegex); - } - - public DateFormatRegex withOffset(String timeOffset) { - String number = StringUtils.substring(timeOffset, 0, timeOffset.length() - 1); - String mark = StringUtils.substring(timeOffset, timeOffset.length() - 1); - - switch (mark) { - case OFFSET_DAY: - dayOffset = Integer.parseInt(number); - break; - case OFFSET_HOUR: - hourOffset = Integer.parseInt(number); - break; - case OFFSET_MIN: - minuteOffset = Integer.parseInt(number); - break; - default: - LOGGER.warn("time offset is invalid, please check {}", timeOffset); - break; - } - return this; - } - - public DateFormatRegex withFile(File file) { - this.file = file; - return this; - } - - /** - * set regex with given time, replace the YYYYDDMM pattern with given time - * - * @param regex - * @param time - */ - public void setRegexWithTime(String regex, String time) { - String[] regexList = StringUtils.splitByWholeSeparatorPreserveAllTokens(regex, File.separator, 0); - - List formattedList = new ArrayList<>(); - for (String regexStr : regexList) { - if (regexStr.contains(YEAR)) { - String tmpRegexStr = regexStr.replace(YEAR, time.substring(0, 4)) - .replace(MONTH, time.substring(4, 6)) - .replace(DAY, time.substring(6, 8)) - .replace(HOUR, time.substring(8, 10)); - formattedList.add(tmpRegexStr); - formattedTime = time; - } else { - formattedList.add(regexStr); - } - } - this.formattedRegex = StringUtils.join(formattedList, File.separatorChar); - LOGGER.info("updated formatted regex is {}", this.formattedRegex); - } - - public void setRegexWithCurrentTime(String regex) { - String currentTime = TransferUtils.formatCurrentTimeWithOffset(NORMAL_FORMATTER, dayOffset, hourOffset, minuteOffset); - setRegexWithTime(regex, currentTime); - } - - public String getFormattedRegex() { - return formattedRegex; - } - - public String getFormattedTime() { - return formattedTime; - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java deleted file mode 100644 index 7ff534e0..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandDb.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.job; - - -import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; -import com.zmops.zeus.iot.server.transfer.core.db.Db; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; - -public class CommandDb { - - private static final Logger LOGGER = LoggerFactory.getLogger(CommandDb.class); - - public static final int MANAGER_SUCCESS_CODE = 0; - public static final int MANAGER_FAIL_CODE = 1; - - private final Db db; - - public CommandDb(Db db) { - this.db = db; - } - - /** - * store manager command to db - * - * @param commandEntity - */ - public void storeCommand(CommandEntity commandEntity) { - db.putCommand(commandEntity); - } - - /** - * get those commands not ack to manager - * - * @return - */ - public List getUnackedCommands() { - return db.searchCommands(false); - } - - - /** - * save normal command result for trigger - * - * @param profile - * @param success - */ - public void saveNormalCmds(TriggerProfile profile, boolean success) { - CommandEntity entity = new CommandEntity(); - entity.setId(CommandEntity.generateCommanid(profile.getTriggerId(), profile.getOpType())); - entity.setTaskId(profile.getTriggerId()); - entity.setDeliveryTime(profile.getDeliveryTime()); - entity.setCommandResult(success ? MANAGER_SUCCESS_CODE : MANAGER_FAIL_CODE); - entity.setAcked(false); - storeCommand(entity); - } - - /** - * save special command result for trigger (retry\makeup\check) - * - * @param id - * @param taskId - * @param success - */ - public void saveSpecialCmds(Integer id, Integer taskId, boolean success) { - CommandEntity entity = new CommandEntity(); - entity.setId(String.valueOf(id)); - entity.setTaskId(String.valueOf(taskId)); - entity.setAcked(false); - entity.setCommandResult(success ? MANAGER_SUCCESS_CODE : MANAGER_FAIL_CODE); - storeCommand(entity); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandEntity.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandEntity.java deleted file mode 100644 index eef18705..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/CommandEntity.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.job; - -import com.sleepycat.persist.model.Entity; -import com.sleepycat.persist.model.PrimaryKey; -import com.sleepycat.persist.model.Relationship; -import com.sleepycat.persist.model.SecondaryKey; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - - -@Entity(version = 1) -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CommandEntity { - - @PrimaryKey - private String id; - - private int commandResult; - - @SecondaryKey(relate = Relationship.MANY_TO_ONE) - private boolean isAcked; - - private String taskId; - - private String deliveryTime; - - public static String generateCommanid(String taskId, int opType) { - return taskId + opType; - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java deleted file mode 100644 index e88d6e55..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/Job.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.job; - - -import com.zmops.zeus.iot.server.transfer.api.Channel; -import com.zmops.zeus.iot.server.transfer.api.Reader; -import com.zmops.zeus.iot.server.transfer.api.Sink; -import com.zmops.zeus.iot.server.transfer.api.Source; -import com.zmops.zeus.iot.server.transfer.conf.JobConstants; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.core.channel.MemoryChannel; -import com.zmops.zeus.iot.server.transfer.core.sink.DataCarrierSink; -import com.zmops.zeus.iot.server.transfer.core.source.TextFileSource; -import com.zmops.zeus.iot.server.transfer.core.task.Task; -import lombok.Getter; -import lombok.Setter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; - -/** - * job meta definition, job will be split into several tasks. - */ -public class Job { - - private static final Logger LOGGER = LoggerFactory.getLogger(Job.class); - - private final JobProfile jobConf; - - @Getter - @Setter - private String name; - - @Getter - @Setter - private String description; - - @Getter - @Setter - private String jobInstanceId; - - public Job(JobProfile jobConf) { - this.jobConf = jobConf; - this.name = jobConf.get(JobConstants.JOB_NAME, JobConstants.DEFAULT_JOB_NAME); - this.description = jobConf.get(JobConstants.JOB_DESCRIPTION, JobConstants.DEFAULT_JOB_DESCRIPTION); - this.jobInstanceId = jobConf.get(JobConstants.JOB_INSTANCE_ID); - } - - public List createTasks() { - List taskList = new ArrayList<>(); - int index = 0; - try { - LOGGER.info("job id: {}, job name {} ", getJobInstanceId(), getName()); - - Source source = new TextFileSource(); - - for (Reader reader : source.split(jobConf)) { - Sink writer = new DataCarrierSink(); - writer.setSourceFile(reader.getReadFile()); - - Channel channel = new MemoryChannel(); - - String taskId = String.format("%s_%d", jobInstanceId, index++); - taskList.add(new Task(taskId, reader, writer, channel, getJobConf())); - } - } catch (Exception ex) { - throw new RuntimeException(ex); - } - return taskList; - } - - public JobProfile getJobConf() { - return this.jobConf; - } - -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java deleted file mode 100644 index 892cd0e8..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobManager.java +++ /dev/null @@ -1,237 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.job; - - -import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; -import com.zmops.zeus.iot.server.transfer.common.TransferThreadFactory; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; -import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; -import com.zmops.zeus.iot.server.transfer.core.TransferManager; -import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; -import com.zmops.zeus.iot.server.transfer.core.db.StateSearchKey; -import com.zmops.zeus.iot.server.transfer.utils.TransferUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.*; -import static com.zmops.zeus.iot.server.transfer.conf.TransferConstants.*; - -/** - * JobManager maintains lots of jobs, and communicate between server and task manager. - */ -public class JobManager extends AbstractDaemon { - - private static final Logger LOGGER = LoggerFactory.getLogger(JobManager.class); - - // key is job instance id. - private ConcurrentHashMap jobs; - // jobs which are not accepted by running pool. - private final ConcurrentHashMap pendingJobs; - // job thread pool - private final ThreadPoolExecutor runningPool; - private final TransferManager transferManager; - private final int monitorInterval; - private final long jobDbCacheTime; - private final long jobDbCacheCheckInterval; - - // job profile db is only used to recover instance which is not finished running. - private final JobProfileDb jobConfDB; - private final JobMetrics jobMetrics; - private final AtomicLong index = new AtomicLong(0); - - /** - * init job manager - * - * @param transferManager - agent manager - */ - public JobManager(TransferManager transferManager, JobProfileDb jobConfDb) { - this.jobConfDB = jobConfDb; - this.transferManager = transferManager; - - // job thread pool for running - this.runningPool = new ThreadPoolExecutor( - 0, Integer.MAX_VALUE, - 60L, TimeUnit.SECONDS, - new SynchronousQueue<>(), - new TransferThreadFactory("job")); - - this.jobs = new ConcurrentHashMap<>(); - this.pendingJobs = new ConcurrentHashMap<>(); - - TransferConfiguration conf = TransferConfiguration.getAgentConf(); - - this.monitorInterval = conf.getInt(TransferConstants.JOB_MONITOR_INTERVAL, TransferConstants.DEFAULT_JOB_MONITOR_INTERVAL); - this.jobDbCacheTime = conf.getLong(JOB_DB_CACHE_TIME, DEFAULT_JOB_DB_CACHE_TIME); - this.jobDbCacheCheckInterval = conf.getLong(JOB_DB_CACHE_CHECK_INTERVAL, DEFAULT_JOB_DB_CACHE_CHECK_INTERVAL); - this.jobMetrics = JobMetrics.create(); - } - - /** - * submit job to work thread. - * - * @param job - job - */ - public void addJob(Job job) { - try { - JobWrapper jobWrapper = new JobWrapper(transferManager, job); - this.runningPool.execute(jobWrapper); - JobWrapper jobWrapperRet = jobs.putIfAbsent(jobWrapper.getJob().getJobInstanceId(), jobWrapper); - if (jobWrapperRet != null) { - LOGGER.warn("{} has been added to running pool, " - + "cannot be added repeatedly", job.getJobInstanceId()); - } else { - jobMetrics.runningJobs.incr(); - } - } catch (Exception rje) { - LOGGER.debug("reject job {}", job.getJobInstanceId(), rje); - pendingJobs.putIfAbsent(job.getJobInstanceId(), job); - } - } - - /** - * add job profile - * - * @param profile - job profile. - */ - public boolean submitJobProfile(JobProfile profile) { - if (profile == null || !profile.allRequiredKeyExist()) { - LOGGER.error("profile is null or not all required key exists {}", profile == null ? null : profile.toJsonStr()); - return false; - } - String jobId = profile.get(JOB_ID); - - profile.set(JOB_INSTANCE_ID, TransferUtils.getUniqId(JOB_ID_PREFIX, jobId, index.incrementAndGet())); - LOGGER.info("submit job profile {}", profile.toJsonStr()); - - getJobConfDb().storeJobFirstTime(profile); - addJob(new Job(profile)); - - return true; - } - - /** - * delete job profile and stop job thread - * - * @param jobInstancId - */ - public void deleteJob(String jobInstancId) { - JobWrapper jobWrapper = jobs.remove(jobInstancId); - if (jobWrapper != null) { - LOGGER.info("delete job instance with job id {}", jobInstancId); - jobWrapper.cleanup(); - getJobConfDb().deleteJob(jobInstancId); - } - } - - /** - * start all accepted jobs. - */ - private void startJobs() { - List profileList = getJobConfDb().getAcceptedJobs(); - for (JobProfile profile : profileList) { - LOGGER.info("init starting job from db {}", profile.toJsonStr()); - addJob(new Job(profile)); - } - } - - public Runnable jobStateCheckThread() { - return () -> { - while (isRunnable()) { - try { - // check pending jobs and try to submit again. - for (String jobId : pendingJobs.keySet()) { - Job job = pendingJobs.remove(jobId); - if (job != null) { - addJob(job); - } - } - TimeUnit.SECONDS.sleep(monitorInterval); - } catch (Exception ex) { - LOGGER.error("error caught", ex); - } - } - }; - } - - /** - * check local db and delete old tasks. - * - * @return - */ - public Runnable dbStorageCheckThread() { - return () -> { - while (isRunnable()) { - try { - jobConfDB.removeExpireJobs(jobDbCacheTime); - TimeUnit.SECONDS.sleep(jobDbCacheCheckInterval); - } catch (Exception ex) { - LOGGER.error("error caught", ex); - } - } - }; - } - - /** - * mark job as success by job id. - * - * @param jobId - job id - */ - public void markJobAsSuccess(String jobId) { - JobWrapper wrapper = jobs.remove(jobId); - if (wrapper != null) { - jobMetrics.runningJobs.decr(); - LOGGER.info("job instance {} is success", jobId); - // mark job as success. - jobConfDB.updateJobState(jobId, StateSearchKey.SUCCESS); - } - } - - public void markJobAsFailed(String jobId) { - JobWrapper wrapper = jobs.remove(jobId); - if (wrapper != null) { - LOGGER.info("job instance {} is failed", jobId); - jobMetrics.runningJobs.decr(); - jobMetrics.fatalJobs.incr(); - // mark job as success. - jobConfDB.updateJobState(jobId, StateSearchKey.FAILED); - } - } - - public JobProfileDb getJobConfDb() { - return jobConfDB; - } - - /** - * check job existence using job file name - * - * @return - */ - public boolean checkJobExsit(String fileName) { - return jobConfDB.getJob(fileName) != null; - } - - public Map getJobs() { - return jobs; - } - - @Override - public void start() { - submitWorker(jobStateCheckThread()); - submitWorker(dbStorageCheckThread()); - startJobs(); - } - - @Override - public void stop() throws Exception { - waitForTerminate(); - this.runningPool.shutdown(); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java deleted file mode 100644 index 6d679a0e..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobMetrics.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.job; - - -import com.zmops.zeus.iot.server.transfer.metrics.Metric; -import com.zmops.zeus.iot.server.transfer.metrics.Metrics; -import com.zmops.zeus.iot.server.transfer.metrics.MetricsRegister; -import com.zmops.zeus.iot.server.transfer.metrics.gauge.GaugeInt; - -import java.util.concurrent.atomic.AtomicBoolean; - -@Metrics -public class JobMetrics { - private static final JobMetrics JOB_METRICS = new JobMetrics(); - private static final AtomicBoolean REGISTER_ONCE = new AtomicBoolean(false); - - @Metric - GaugeInt runningJobs; - - @Metric - GaugeInt fatalJobs; - - private JobMetrics() { - } - - static JobMetrics create() { - if (REGISTER_ONCE.compareAndSet(false, true)) { - MetricsRegister.register("Job", "STateSummary", null, JOB_METRICS); - } - return JOB_METRICS; - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java deleted file mode 100644 index ee83abeb..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/job/JobWrapper.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.job; - - -import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; -import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; -import com.zmops.zeus.iot.server.transfer.core.TransferManager; -import com.zmops.zeus.iot.server.transfer.core.state.AbstractStateWrapper; -import com.zmops.zeus.iot.server.transfer.core.state.State; -import com.zmops.zeus.iot.server.transfer.core.task.Task; -import com.zmops.zeus.iot.server.transfer.core.task.TaskManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -/** - * JobWrapper is used in JobManager, it defines the life cycle of - * running job and maintains the state of job. - */ -public class JobWrapper extends AbstractStateWrapper { - - private static final Logger LOGGER = LoggerFactory.getLogger(JobWrapper.class); - - private final TransferConfiguration transferConfig; - private final TaskManager taskManager; - private final JobManager jobManager; - private final Job job; - - private final List allTasks; - - public JobWrapper(TransferManager manager, Job job) { - super(); - this.transferConfig = TransferConfiguration.getAgentConf(); - this.taskManager = manager.getTaskManager(); - this.jobManager = manager.getJobManager(); - this.job = job; - this.allTasks = new ArrayList<>(); - doChangeState(State.ACCEPTED); - } - - /** - * check states of all tasks, wait if one of them not finished. - */ - private void checkAllTasksStateAndWait() throws Exception { - boolean isFinished = false; - - long checkInterval = transferConfig.getLong(TransferConstants.JOB_FINISH_CHECK_INTERVAL, TransferConstants.DEFAULT_JOB_FINISH_CHECK_INTERVAL); - do { - // check whether all tasks have finished. - isFinished = allTasks.stream().allMatch(task -> taskManager.isTaskFinished(task.getTaskId())); - TimeUnit.SECONDS.sleep(checkInterval); - } while (!isFinished); - - LOGGER.info("all tasks of {} has been checked", job.getJobInstanceId()); - boolean isSuccess = allTasks.stream().allMatch(task -> taskManager.isTaskSuccess(task.getTaskId())); - - if (isSuccess) { - doChangeState(State.SUCCEEDED); - } else { - doChangeState(State.FAILED); - } - } - - /** - * submit all tasks - */ - private void submitAllTasks() { - List tasks = job.createTasks(); - - tasks.forEach(task -> { - allTasks.add(task); - taskManager.submitTask(task); - }); - } - - /** - * get job - * - * @return job - */ - public Job getJob() { - return job; - } - - /** - * cleanup job - */ - public void cleanup() { - allTasks.forEach(task -> taskManager.removeTask(task.getTaskId())); - } - - @Override - public void run() { - try { - doChangeState(State.RUNNING); - - submitAllTasks(); - - checkAllTasksStateAndWait(); - - cleanup(); - } catch (Exception ex) { - doChangeState(State.FAILED); - LOGGER.error("error caught: {}, message: {}", job.getJobConf().toJsonStr(), ex.getMessage()); - } - } - - @Override - public void addCallbacks() { - this.addCallback(State.ACCEPTED, State.RUNNING, (before, after) -> { - - }).addCallback(State.RUNNING, State.FAILED, (before, after) -> { - jobManager.markJobAsFailed(job.getJobInstanceId()); - }).addCallback(State.RUNNING, State.SUCCEEDED, ((before, after) -> { - jobManager.markJobAsSuccess(job.getJobInstanceId()); - })); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/DefaultMessage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/DefaultMessage.java deleted file mode 100644 index d0943184..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/DefaultMessage.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.message; - -import com.zmops.zeus.iot.server.transfer.api.Message; - -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; - -public class DefaultMessage implements Message { - - private final byte[] body; - private final Map header; - - public DefaultMessage(byte[] body, Map header) { - this.body = body; - this.header = header; - } - - public DefaultMessage(byte[] body) { - this(body, new HashMap<>()); - } - - @Override - public byte[] getBody() { - return body; - } - - @Override - public Map getHeader() { - return header; - } - - @Override - public String toString() { - return new String(body, StandardCharsets.UTF_8); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/EndMessage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/EndMessage.java deleted file mode 100644 index 5b702d5e..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/EndMessage.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.message; - -import com.zmops.zeus.iot.server.transfer.api.Message; - -import java.util.HashMap; -import java.util.Map; - -/** - * End message, this is an empty message only indicate - * that source data have been completely consumed. - */ -public class EndMessage implements Message { - - @Override - public byte[] getBody() { - return null; - } - - @Override - public Map getHeader() { - return new HashMap<>(10); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/PackProxyMessage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/PackProxyMessage.java deleted file mode 100644 index 3fcd1892..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/PackProxyMessage.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.message; - -import org.apache.commons.lang3.tuple.Pair; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.atomic.AtomicLong; - -/** - * Handle List of BusMessage, which belong to the same tid. - */ -public class PackProxyMessage { - - private static final Logger LOGGER = LoggerFactory.getLogger(PackProxyMessage.class); - - private final String tid; - - private int currentSize; - - private final int maxPackSize; - - private final int maxQueueNumber; - // ms - private final int cacheTimeout; - - // tid -> list of proxyMessage - private final LinkedBlockingQueue messageQueue; - - private volatile long currentCacheTime = System.currentTimeMillis(); - - private final AtomicLong queueSize = new AtomicLong(0); - - /** - * Init PackBusMessage - * - * @param maxPackSize - max pack size for one bid - * @param cacheTimeout - cache timeout for one proxy message - * @param tid - tid - */ - public PackProxyMessage(int maxPackSize, int maxQueueNumber, int cacheTimeout, String tid) { - this.maxPackSize = maxPackSize; - this.maxQueueNumber = maxPackSize * 10; - this.cacheTimeout = cacheTimeout; - - // double size of package - this.messageQueue = new LinkedBlockingQueue<>(maxQueueNumber); - this.tid = tid; - } - - /** - * Check whether queue is nearly full - * - * @return true if is nearly full else false. - */ - private boolean queueIsFull() { - return messageQueue.size() >= maxQueueNumber - 1; - } - - /** - * Add proxy message to cache, proxy message should belong to the same tid. - */ - public void addProxyMessage(ProxyMessage message) { - assert tid.equals(message.getTid()); - try { - if (queueIsFull()) { - LOGGER.warn("message queue is greater than {}, stop adding message, maybe proxy get stuck", maxQueueNumber); - } - messageQueue.put(message); - queueSize.addAndGet(message.getBody().length); - } catch (Exception ex) { - LOGGER.error("exception caught", ex); - } -// messageQueue.offer(message); - } - - /** - * check message queue is empty or not - * - * @return - */ - public boolean isEmpty() { - return messageQueue.isEmpty(); - } - - /** - * Fetch batch of proxy message, timeout message or max number of list satisfied. - * - * @return map of message list, key is tid for the batch. - * return null if there are no valid messages. - */ - public Pair> fetchBatch() { - // if queue is nearly full or package size is satisfied or timeout - long currentTime = System.currentTimeMillis(); - - if (queueSize.get() > maxPackSize || queueIsFull() || currentTime - currentCacheTime > cacheTimeout) { - // refresh cache time. - currentCacheTime = currentTime; - - long resultBatchSize = 0; - - List result = new ArrayList<>(); - - while (!messageQueue.isEmpty()) { - // pre check message size - ProxyMessage peekMessage = messageQueue.peek(); - if (peekMessage == null || resultBatchSize + peekMessage.getBody().length > maxPackSize) { - break; - } - - ProxyMessage message = messageQueue.remove(); - if (message != null) { - int bodySize = message.getBody().length; - resultBatchSize += bodySize; - - // decrease queue size. - queueSize.addAndGet(-bodySize); - result.add(message.getBody()); - } - - } - // make sure result is not empty. - if (!result.isEmpty()) { - return Pair.of(tid, result); - } - } - return null; - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java deleted file mode 100644 index f12012db..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/message/ProxyMessage.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.message; - -import com.zmops.zeus.iot.server.transfer.api.Message; - -import java.util.Map; - -/** - * Bus message with body, header, bid and tid. - */ -public class ProxyMessage implements Message { - - private static final String DEFAULT_TID = "__"; - - private final byte[] body; - private final Map header; - private final String bid; - private final String tid; - - - public ProxyMessage(byte[] body, Map header) { - this.body = body; - this.header = header; - this.bid = header.get("bid"); - this.tid = header.getOrDefault("tid", DEFAULT_TID); - } - - /** - * Get first line of body list - * - * @return first line of body list - */ - @Override - public byte[] getBody() { - return body; - } - - /** - * Get header of message - * - * @return header - */ - @Override - public Map getHeader() { - return header; - } - - public String getBid() { - return bid; - } - - public String getTid() { - return tid; - } - - public static ProxyMessage parse(Message message) { - return new ProxyMessage(message.getBody(), message.getHeader()); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/DataCarrierSink.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/DataCarrierSink.java deleted file mode 100644 index 0b1769c2..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/sink/DataCarrierSink.java +++ /dev/null @@ -1,164 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.sink; - -import com.zmops.zeus.iot.server.transfer.api.Message; -import com.zmops.zeus.iot.server.transfer.api.Sink; -import com.zmops.zeus.iot.server.transfer.common.TransferThreadFactory; -import com.zmops.zeus.iot.server.transfer.conf.CommonConstants; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.core.message.EndMessage; -import com.zmops.zeus.iot.server.transfer.core.message.PackProxyMessage; -import com.zmops.zeus.iot.server.transfer.core.message.ProxyMessage; -import com.zmops.zeus.iot.server.transfer.sender.SenderManager; -import com.zmops.zeus.iot.server.transfer.utils.TransferUtils; -import org.apache.commons.lang3.tuple.Pair; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.*; - -import static com.zmops.zeus.iot.server.transfer.conf.CommonConstants.*; -import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.*; - -public class DataCarrierSink implements Sink { - - private static final Logger LOGGER = LoggerFactory.getLogger(DataCarrierSink.class); - - private SenderManager senderManager; - - private String bid; - private String tid; - private String sourceFile; - private String jobInstanceId; - - private int maxBatchSize; - private int maxBatchTimeoutMs; - private int batchFlushInterval; - private int maxQueueNumber; - - private final ExecutorService executorService = - new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new TransferThreadFactory("ProxySink")); - - private volatile boolean shutdown = false; - - // key is tid, value is a batch of messages belong to the same tid - private ConcurrentHashMap cache; - - private long dataTime; - - - @Override - public void write(Message message) { - if (message != null && message.getBody().length > 0) { - message.getHeader().put(CommonConstants.PROXY_KEY_BID, bid); - message.getHeader().put(CommonConstants.PROXY_KEY_TID, tid); - if (!(message instanceof EndMessage)) { - - ProxyMessage proxyMessage = ProxyMessage.parse(message); - - // add proxy message to cache. - cache.compute(proxyMessage.getTid(), (s, packProxyMessage) -> { - if (packProxyMessage == null) { - packProxyMessage = new PackProxyMessage(maxBatchSize, maxQueueNumber, maxBatchTimeoutMs, proxyMessage.getTid()); - } - // add message to package proxy - packProxyMessage.addProxyMessage(proxyMessage); - return packProxyMessage; - }); - } - } - } - - @Override - public void setSourceFile(String sourceFileName) { - this.sourceFile = sourceFileName; - } - - /** - * flush cache by batch - * - * @return - thread runner - */ - private Runnable flushCache() { - return () -> { - LOGGER.info("start flush cache thread for {} TDBusSink", bid); - while (!shutdown) { - try { - cache.forEach((s, packProxyMessage) -> { - Pair> result = packProxyMessage.fetchBatch(); - - if (result != null) { - senderManager.sendBatch(jobInstanceId, bid, result.getKey(), result.getValue(), 0, dataTime); - } - }); - TransferUtils.silenceSleepInMs(batchFlushInterval); - } catch (Exception ex) { - LOGGER.error("error caught", ex); - } - } - }; - } - - @Override - public void init(JobProfile jobConf) { - maxBatchSize = jobConf.getInt(CommonConstants.PROXY_PACKAGE_MAX_SIZE, CommonConstants.DEFAULT_PROXY_PACKAGE_MAX_SIZE); - maxQueueNumber = jobConf.getInt(CommonConstants.PROXY_TID_QUEUE_MAX_NUMBER, CommonConstants.DEFAULT_PROXY_TID_QUEUE_MAX_NUMBER); - maxBatchTimeoutMs = jobConf.getInt(CommonConstants.PROXY_PACKAGE_MAX_TIMEOUT_MS, CommonConstants.DEFAULT_PROXY_PACKAGE_MAX_TIMEOUT_MS); - - jobInstanceId = jobConf.get(JOB_INSTANCE_ID); - - batchFlushInterval = jobConf.getInt(CommonConstants.PROXY_BATCH_FLUSH_INTERVAL, CommonConstants.DEFAULT_PROXY_BATCH_FLUSH_INTERVAL); - - cache = new ConcurrentHashMap<>(10); - - bid = jobConf.get(PROXY_BID); - dataTime = TransferUtils.timeStrConvertToMillSec(jobConf.get(JOB_DATA_TIME, ""), jobConf.get(JOB_CYCLE_UNIT, "")); - - bid = jobConf.get(PROXY_BID); - tid = jobConf.get(PROXY_TID); - - executorService.execute(flushCache()); - senderManager = new SenderManager(jobConf, bid, sourceFile); - } - - private HashMap parseAttrFromJobProfile(JobProfile jobProfile) { - HashMap attr = new HashMap<>(); - - String additionStr = jobProfile.get(JOB_ADDITION_STR, ""); - if (!additionStr.isEmpty()) { - Map addAttr = TransferUtils.getAdditionAttr(additionStr); - attr.putAll(addAttr); - } - - if (jobProfile.getBoolean(JOB_RETRY, false)) { - // used for online compute filter consume - attr.put(PROXY_OCEANUS_F, PROXY_OCEANUS_BL); - } - attr.put(PROXY_KEY_ID, jobProfile.get(JOB_ID)); - attr.put(PROXY_KEY_AGENT_IP, jobProfile.get(JOB_IP)); - - return attr; - } - - @Override - public void destroy() { - LOGGER.info("destroy sink which sink from source file {}", sourceFile); - while (!sinkFinish()) { - LOGGER.info("job {} wait until cache all flushed to proxy", jobInstanceId); - TransferUtils.silenceSleepInMs(batchFlushInterval); - } - shutdown = true; - executorService.shutdown(); - } - - /** - * check whether all tid messages finished - * - * @return - */ - private boolean sinkFinish() { - return cache.values().stream().allMatch(PackProxyMessage::isEmpty); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java deleted file mode 100644 index f318fb36..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/TextFileSource.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.source; - - -import com.zmops.zeus.iot.server.transfer.api.Reader; -import com.zmops.zeus.iot.server.transfer.api.Source; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.core.source.reader.TextFileReader; -import com.zmops.zeus.iot.server.transfer.utils.FileSearchUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import static com.zmops.zeus.iot.server.transfer.conf.CommonConstants.POSITION_SUFFIX; -import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.DEFAULT_JOB_LINE_FILTER; -import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_LINE_FILTER_PATTERN; - -/** - * Read text files - */ -public class TextFileSource implements Source { - - private static final Logger LOGGER = LoggerFactory.getLogger(TextFileSource.class); - - // path + suffix - public static final String MD5_SUFFIX = ".md5"; - - @Override - public List split(JobProfile jobConf) { - - Collection allFiles = FileSearchUtils.findSuitFiles(jobConf); - List result = new ArrayList<>(); - - String filterPattern = jobConf.get(JOB_LINE_FILTER_PATTERN, DEFAULT_JOB_LINE_FILTER); - - for (File file : allFiles) { - int seekPosition = jobConf.getInt(file.getAbsolutePath() + POSITION_SUFFIX, 0); - - LOGGER.info("read from history position {} with job profile {}", seekPosition, jobConf.getInstanceId()); - String md5 = jobConf.get(file.getAbsolutePath() + MD5_SUFFIX, ""); - - TextFileReader textFileReader = new TextFileReader(file, seekPosition); - addValidator(filterPattern, textFileReader); - result.add(textFileReader); - } - - return result; - } - - - private void addValidator(String filterPattern, TextFileReader textFileReader) { - textFileReader.addPatternValidator(filterPattern); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java deleted file mode 100644 index d0bb639c..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/source/reader/TextFileReader.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.source.reader; - -import com.zmops.zeus.iot.server.transfer.api.Message; -import com.zmops.zeus.iot.server.transfer.api.Reader; -import com.zmops.zeus.iot.server.transfer.api.Validator; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.core.FileException; -import com.zmops.zeus.iot.server.transfer.core.message.DefaultMessage; -import com.zmops.zeus.iot.server.transfer.core.validator.PatternValidator; -import com.zmops.zeus.iot.server.transfer.metrics.PluginMetric; -import com.zmops.zeus.iot.server.transfer.utils.TransferUtils; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.stream.Stream; - -import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.DEFAULT_JOB_FILE_MAX_WAIT; -import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_FILE_MAX_WAIT; - -/** - * ndjson 文件读取 - * - * @editor nantian - */ -public class TextFileReader implements Reader { - - private static final Logger LOGGER = LoggerFactory.getLogger(TextFileReader.class); - - public static final int NEVER_STOP_SIGN = -1; - - private final File file; - private final int position; - private final String md5; - - private Iterator iterator; - private Stream stream; - - private long timeout; - private long lastTime = 0; - - private final PluginMetric textFileMetric; - private final List validators = new ArrayList<>(); - - public TextFileReader(File file, int position) { - this(file, position, ""); - } - - public TextFileReader(File file, int position, String md5) { - this.file = file; - this.position = position; - this.md5 = md5; - textFileMetric = new PluginMetric(); - textFileMetric.tagName.setName(file.getAbsolutePath()); - } - - public TextFileReader(File file) { - this(file, 0); - } - - @Override - public Message read() { - if (iterator != null && iterator.hasNext()) { - String message = iterator.next(); - if (validateMessage(message)) { - textFileMetric.readNum.incr(); - return new DefaultMessage(message.getBytes(StandardCharsets.UTF_8)); - } - } - TransferUtils.silenceSleepInMs(100); - return null; - } - - - private boolean validateMessage(String message) { - if (validators.isEmpty()) { - return true; - } - return validators.stream().allMatch(v -> v.validate(message)); - } - - @Override - public boolean isFinished() { - if (timeout == NEVER_STOP_SIGN) { - return false; - } - if (iterator == null) { - return true; - } - if (iterator.hasNext()) { - lastTime = 0; - return false; - } else { - if (lastTime == 0) { - lastTime = System.currentTimeMillis(); - } - return System.currentTimeMillis() - lastTime > timeout; - } - } - - @Override - public String getReadFile() { - return file.getAbsolutePath(); - } - - @Override - public void setReadTimeout(long millis) { - timeout = millis; - } - - public void addPatternValidator(String pattern) { - if (pattern.isEmpty()) { - return; - } - validators.add(new PatternValidator(pattern)); - } - - - @Override - public void init(JobProfile jobConf) { - try { - initReadTimeout(jobConf); - String md5 = TransferUtils.getFileMd5(file); - - if (StringUtils.isNotBlank(this.md5) && !this.md5.equals(md5)) { - LOGGER.warn("md5 is differ from origin, origin: {}, new {}", this.md5, md5); - } - - LOGGER.info("file name for task is {}, md5 is {}", file, md5); - - stream = Files.newBufferedReader(file.toPath()).lines().skip(position); - iterator = stream.iterator(); - } catch (Exception ex) { - throw new FileException("error init stream for " + file.getPath(), ex); - } - } - - private void initReadTimeout(JobProfile jobConf) { - int waitTime = jobConf.getInt(JOB_FILE_MAX_WAIT, DEFAULT_JOB_FILE_MAX_WAIT); - if (waitTime == NEVER_STOP_SIGN) { - timeout = NEVER_STOP_SIGN; - } else { - timeout = TimeUnit.MINUTES.toMillis(waitTime); - } - } - - @Override - public void destroy() { - TransferUtils.finallyClose(stream); - LOGGER.info("destroy reader with read {} num {}", textFileMetric.tagName.getName(), textFileMetric.readNum.snapshot()); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/AbstractStateWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/AbstractStateWrapper.java deleted file mode 100644 index cb8f84dc..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/AbstractStateWrapper.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.state; - -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashMap; -import java.util.Map; - -public abstract class AbstractStateWrapper implements Runnable { - - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractStateWrapper.class); - - private final Map, StateCallback> callBacks = new HashMap<>(); - - private volatile State currentState = State.ACCEPTED; - - public AbstractStateWrapper() { - addCallbacks(); - } - - /** - * add callback for state change - */ - public abstract void addCallbacks(); - - - public AbstractStateWrapper addCallback(State begin, State end, StateCallback callback) { - callBacks.put(new ImmutablePair<>(begin, end), callback); - return this; - } - - /** - * change state and execute callback functions - * - * @param nextState - next state - */ - public synchronized void doChangeState(State nextState) { - LOGGER.debug("state change, current state is {}, next state is {}", currentState, nextState); - Pair statePair = new ImmutablePair<>(currentState, nextState); - - StateCallback callback = callBacks.get(statePair); - - // change state before callback. - currentState = nextState; - if (callback != null) { - callback.call(currentState, nextState); - } - } - - /** - * determine the exception - * - * @return - */ - public boolean isException() { - State tmpState = currentState; - return State.KILLED.equals(tmpState) || State.FAILED.equals(tmpState) || State.FATAL.equals(tmpState); - } - - public boolean isFinished() { - State tmpState = currentState; - return State.FATAL.equals(tmpState) || State.SUCCEEDED.equals(tmpState) || State.KILLED.equals(tmpState); - } - - public boolean isSuccess() { - return State.SUCCEEDED.equals(currentState); - } - - public boolean isFailed() { - return State.FAILED.equals(currentState); - } - - public boolean isFatal() { - State tmpState = currentState; - return State.FATAL.equals(tmpState) || State.KILLED.equals(tmpState); - } - -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/State.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/State.java deleted file mode 100644 index 8ad02019..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/State.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.state; - -/** - * job/task state - */ -public enum State { - // accepted state - ACCEPTED, - // running - RUNNING, - // succeeded - SUCCEEDED, - // failed - FAILED, - // killed - KILLED, - // fatal after retry failed - FATAL -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateCallback.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateCallback.java deleted file mode 100644 index 328afaf8..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/state/StateCallback.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.state; - -/** - * callbacks - */ -public interface StateCallback { - - void call(State before, State after); -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java deleted file mode 100644 index ff999175..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/Task.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.task; - -import com.zmops.zeus.iot.server.transfer.api.Channel; -import com.zmops.zeus.iot.server.transfer.api.Reader; -import com.zmops.zeus.iot.server.transfer.api.Sink; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; - - -/** - * task meta definition which contains reader -> channel -> sink and job config information - */ -public class Task { - - private final String taskId; - private final Reader reader; - private final Sink sink; - private final Channel channel; - private final JobProfile jobConf; - - public Task(String taskId, Reader reader, Sink sink, Channel channel, JobProfile jobConf) { - this.reader = reader; - this.sink = sink; - this.taskId = taskId; - this.channel = channel; - this.jobConf = jobConf; - } - - public boolean isReadFinished() { - return reader.isFinished(); - } - - public String getTaskId() { - return taskId; - } - - public Reader getReader() { - return reader; - } - - public Sink getSink() { - return sink; - } - - public Channel getChannel() { - return channel; - } - - public void init() { - this.channel.init(jobConf); - this.sink.init(jobConf); - this.reader.init(jobConf); - } - - public void destroy() { - this.reader.destroy(); - this.sink.destroy(); - this.channel.destroy(); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java deleted file mode 100644 index 270f2d39..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskManager.java +++ /dev/null @@ -1,235 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.task; - - -import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; -import com.zmops.zeus.iot.server.transfer.common.TransferThreadFactory; -import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; -import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; -import com.zmops.zeus.iot.server.transfer.core.TransferManager; -import com.zmops.zeus.iot.server.transfer.core.job.JobManager; -import com.zmops.zeus.iot.server.transfer.utils.TransferUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.*; - -/** - * Task manager maintains lots of tasks and communicate with job level components. - * It also provide functions to execute commands from job level like killing/submit tasks. - */ -public class TaskManager extends AbstractDaemon { - - private static final Logger LOGGER = LoggerFactory.getLogger(JobManager.class); - - // task thread pool; - private final ThreadPoolExecutor runningPool; - private final TransferManager transferManager; - private final TaskMetrics taskMetrics; - - private final ConcurrentHashMap tasks; - private final BlockingQueue retryTasks; - - private final int monitorInterval; - private final int taskMaxCapacity; - private final int taskRetryMaxTime; - private final long waitTime; - - /** - * Init task manager. - * - * @param transferManager - agent manager - */ - public TaskManager(TransferManager transferManager) { - this.transferManager = transferManager; - this.runningPool = new ThreadPoolExecutor( - 0, Integer.MAX_VALUE, - 60L, TimeUnit.SECONDS, - new SynchronousQueue<>(), - new TransferThreadFactory("task")); - - // metric for task level - taskMetrics = TaskMetrics.create(); - tasks = new ConcurrentHashMap<>(); - - TransferConfiguration conf = TransferConfiguration.getAgentConf(); - - retryTasks = new LinkedBlockingQueue<>(conf.getInt(TransferConstants.TASK_RETRY_MAX_CAPACITY, TransferConstants.DEFAULT_TASK_RETRY_MAX_CAPACITY)); - - monitorInterval = conf.getInt(TransferConstants.TASK_MONITOR_INTERVAL, TransferConstants.DEFAULT_TASK_MONITOR_INTERVAL); - taskRetryMaxTime = conf.getInt(TransferConstants.TASK_RETRY_SUBMIT_WAIT_SECONDS, TransferConstants.DEFAULT_TASK_RETRY_SUBMIT_WAIT_SECONDS); - taskMaxCapacity = conf.getInt(TransferConstants.TASK_RETRY_MAX_CAPACITY, TransferConstants.DEFAULT_TASK_RETRY_MAX_CAPACITY); - waitTime = conf.getLong(TransferConstants.THREAD_POOL_AWAIT_TIME, TransferConstants.DEFAULT_THREAD_POOL_AWAIT_TIME); - } - - /** - * Get task metrics - * - * @return task metrics - */ - public TaskMetrics getTaskMetrics() { - return taskMetrics; - } - - public TaskWrapper getTaskWrapper(String taskId) { - return tasks.get(taskId); - } - - /** - * submit task, wait if task queue is full. - * - * @param task - task - */ - public void submitTask(Task task) { - TaskWrapper taskWrapper = new TaskWrapper(transferManager, task); - submitTask(taskWrapper); - - } - - public void submitTask(TaskWrapper wrapper) { - TaskWrapper retTaskWrapper = tasks.putIfAbsent(wrapper.getTask().getTaskId(), wrapper); - - if (retTaskWrapper == null) { - // pool may be full - boolean notSubmitted = true; - while (notSubmitted) { - try { - this.runningPool.submit(wrapper); - notSubmitted = false; - } catch (Exception ex) { - TransferUtils.silenceSleepInMs(waitTime); - LOGGER.warn("reject task {}", wrapper.getTask().getTaskId(), ex); - } - } - - taskMetrics.runningTasks.incr(); - } - } - - /** - * retry task. - * - * @param wrapper - task wrapper - */ - private boolean addRetryTask(TaskWrapper wrapper) { - LOGGER.info("retry submit task {}", wrapper.getTask().getTaskId()); - try { - boolean success = retryTasks.offer(wrapper, taskRetryMaxTime, TimeUnit.SECONDS); - if (!success) { - LOGGER.error("cannot submit to retry queue, max {}, current {}", taskMaxCapacity, retryTasks.size()); - } else { - taskMetrics.retryingTasks.incr(); - } - return success; - } catch (Exception ex) { - LOGGER.error("error while offer task", ex); - } - return false; - } - - /** - * Check whether task is finished - * - * @param taskId - task id - * @return - true if task is finished otherwise false - */ - public boolean isTaskFinished(String taskId) { - TaskWrapper wrapper = tasks.get(taskId); - if (wrapper != null) { - return wrapper.isFinished(); - } - return false; - } - - /** - * Check if task is success - * - * @param taskId task id - * @return true if task is success otherwise false - */ - public boolean isTaskSuccess(String taskId) { - TaskWrapper wrapper = tasks.get(taskId); - if (wrapper != null) { - return wrapper.isSuccess(); - } - return false; - } - - /** - * Remove task and wait task to finish by task id - * - * @param taskId - task id - */ - public void removeTask(String taskId) { - taskMetrics.runningTasks.decr(); - TaskWrapper taskWrapper = tasks.remove(taskId); - if (taskWrapper != null) { - taskWrapper.waitForFinish(); - } - } - - /** - * kill task - * - * @param task task - * @return - */ - public boolean killTask(Task task) { - // kill running tasks. - TaskWrapper taskWrapper = tasks.get(task.getTaskId()); - if (taskWrapper != null) { - taskWrapper.kill(); - return true; - } - return false; - } - - /** - * Thread for checking whether task should retry. - * - * @return - runnable thread - */ - public Runnable createTaskMonitorThread() { - return () -> { - while (isRunnable()) { - try { - for (String taskId : tasks.keySet()) { - TaskWrapper wrapper = tasks.get(taskId); - if (wrapper != null && wrapper.isFailed() && wrapper.shouldRetry()) { - boolean success = addRetryTask(wrapper); - if (success) { - removeTask(taskId); - } - } - } - while (!retryTasks.isEmpty()) { - TaskWrapper taskWrapper = retryTasks.poll(); - if (taskWrapper != null) { - taskMetrics.retryingTasks.decr(); - submitTask(taskWrapper); - } - } - TimeUnit.SECONDS.sleep(monitorInterval); - } catch (Exception ex) { - LOGGER.error("Exception caught", ex); - } - } - }; - } - - /** - * start service. - */ - @Override - public void start() { - submitWorker(createTaskMonitorThread()); - } - - /** - * stop service. - */ - @Override - public void stop() throws Exception { - waitForTerminate(); - this.runningPool.shutdown(); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java deleted file mode 100644 index c59b16fc..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskMetrics.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.task; - -import com.zmops.zeus.iot.server.transfer.metrics.Metric; -import com.zmops.zeus.iot.server.transfer.metrics.Metrics; -import com.zmops.zeus.iot.server.transfer.metrics.MetricsRegister; -import com.zmops.zeus.iot.server.transfer.metrics.counter.CounterLong; -import com.zmops.zeus.iot.server.transfer.metrics.gauge.GaugeInt; - -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Metric collector for task level. - */ -@Metrics -public class TaskMetrics { - - private static final TaskMetrics TASK_METRICS = new TaskMetrics(); - private static final AtomicBoolean REGISTER_ONCE = new AtomicBoolean(false); - - @Metric - GaugeInt runningTasks; - - @Metric - GaugeInt retryingTasks; - - @Metric - CounterLong fatalTasks; - - private TaskMetrics() { - } - - public static TaskMetrics create() { - // register one time. - if (REGISTER_ONCE.compareAndSet(false, true)) { - MetricsRegister.register("Task", "StateSummary", null, TASK_METRICS); - } - return TASK_METRICS; - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java deleted file mode 100644 index c060b836..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskPositionManager.java +++ /dev/null @@ -1,156 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.task; - - -import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.core.TransferManager; -import com.zmops.zeus.iot.server.transfer.core.db.JobProfileDb; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; - -import static com.zmops.zeus.iot.server.transfer.conf.CommonConstants.POSITION_SUFFIX; - -/** - * used to store task position to db, task position is stored as properties in JobProfile. - * where key is task read file name and value is task sink position - * note that this class is generated - */ -public class TaskPositionManager extends AbstractDaemon { - - private static final Logger LOGGER = LoggerFactory.getLogger(TaskPositionManager.class); - - public static final int DEFAULT_FLUSH_TIMEOUT = 3; - - private final TransferManager transferManager; - private final JobProfileDb jobConfDb; - - private final ConcurrentHashMap> jobTaskPositionMap; - - private static volatile TaskPositionManager taskPositionManager = null; - - private TaskPositionManager(TransferManager transferManager) { - this.transferManager = transferManager; - this.jobConfDb = transferManager.getJobManager().getJobConfDb(); - this.jobTaskPositionMap = new ConcurrentHashMap<>(); - } - - /** - * task position manager singleton, can only generated by agent manager - * - * @param transferManager - * @return - */ - public static TaskPositionManager getTaskPositionManager(TransferManager transferManager) { - if (taskPositionManager == null) { - synchronized (TaskPositionManager.class) { - if (taskPositionManager == null) { - taskPositionManager = new TaskPositionManager(transferManager); - } - } - } - return taskPositionManager; - } - - /** - * get taskPositionManager singleton - * - * @return - */ - public static TaskPositionManager getTaskPositionManager() { - if (taskPositionManager == null) { - throw new RuntimeException("task position manager has not been initialized by agentManager"); - } - return taskPositionManager; - } - - @Override - public void start() throws Exception { - submitWorker(taskPositionFlushThread()); - } - - /** - * 定时存储到本地DB - * - * @return - */ - private Runnable taskPositionFlushThread() { - return () -> { - while (isRunnable()) { - try { - // check pending jobs and try to submit again. - for (String jobId : jobTaskPositionMap.keySet()) { - JobProfile jobProfile = jobConfDb.getJobProfile(jobId); - if (jobProfile == null) { - LOGGER.warn("jobProfile {} cannot be found in db, " - + "might be deleted by standalone mode, now delete job position in memory", jobId); - deleteJobPosition(jobId); - continue; - } - flushJobProfile(jobId, jobProfile); - } - TimeUnit.SECONDS.sleep(DEFAULT_FLUSH_TIMEOUT); - } catch (Exception ex) { - LOGGER.error("error caught", ex); - } - } - }; - } - - private void flushJobProfile(String jobId, JobProfile jobProfile) { - jobTaskPositionMap.get(jobId).forEach( - (fileName, position) -> { - jobProfile.setLong(fileName + POSITION_SUFFIX, position); - } - ); - if (jobConfDb.checkJobfinished(jobProfile)) { - LOGGER.info("Cannot update job profile {}, delete memory job in jobTaskPosition", jobId); - deleteJobPosition(jobId); - } else { - jobConfDb.updateJobProfile(jobProfile); - } - } - - private void deleteJobPosition(String jobId) { - jobTaskPositionMap.remove(jobId); - } - - @Override - public void stop() throws Exception { - waitForTerminate(); - } - - /** - * 更新 文件读取位置 - * - * @param jobInstanceId 任务实例ID - * @param sourceFilePath 源文件路径 - * @param size position - */ - public void updateFileSinkPosition(String jobInstanceId, String sourceFilePath, long size) { - ConcurrentHashMap filePositionTemp = new ConcurrentHashMap<>(); - - ConcurrentHashMap filePosition = jobTaskPositionMap.putIfAbsent(jobInstanceId, filePositionTemp); - - long beforePosition; - - if (filePosition == null) { - filePosition = filePositionTemp; - beforePosition = jobConfDb.getJobProfile(jobInstanceId).getLong(sourceFilePath + POSITION_SUFFIX, 0); - } else { - beforePosition = filePosition.getOrDefault(sourceFilePath, 1L); - } - - filePosition.put(sourceFilePath, beforePosition + size); - } - - public ConcurrentHashMap getTaskPositionMap(String jobId) { - return jobTaskPositionMap.get(jobId); - } - - public ConcurrentHashMap> getJobTaskPosition() { - return jobTaskPositionMap; - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java deleted file mode 100644 index 2f691e07..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/task/TaskWrapper.java +++ /dev/null @@ -1,182 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.task; - - -import com.zmops.zeus.iot.server.transfer.api.Message; -import com.zmops.zeus.iot.server.transfer.common.TransferThreadFactory; -import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; -import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; -import com.zmops.zeus.iot.server.transfer.core.TransferManager; -import com.zmops.zeus.iot.server.transfer.core.message.EndMessage; -import com.zmops.zeus.iot.server.transfer.core.state.AbstractStateWrapper; -import com.zmops.zeus.iot.server.transfer.core.state.State; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * TaskWrapper is used in taskManager, it maintains the life cycle of - * running task. - */ -public class TaskWrapper extends AbstractStateWrapper { - - private static final Logger LOGGER = LoggerFactory.getLogger(TaskWrapper.class); - - public static final int WAIT_FINISH_TIME_OUT = 1; - - private final TaskManager taskManager; - private final Task task; - - private final AtomicInteger retryTime = new AtomicInteger(0); - - private final int maxRetryTime; - private final int pushMaxWaitTime; - private final int pullMaxWaitTime; - - private ExecutorService executorService; - - public TaskWrapper(TransferManager manager, Task task) { - super(); - this.taskManager = manager.getTaskManager(); - this.task = task; - - TransferConfiguration conf = TransferConfiguration.getAgentConf(); - - maxRetryTime = conf.getInt(TransferConstants.TASK_MAX_RETRY_TIME, TransferConstants.DEFAULT_TASK_MAX_RETRY_TIME); - pushMaxWaitTime = conf.getInt(TransferConstants.TASK_PUSH_MAX_SECOND, TransferConstants.DEFAULT_TASK_PUSH_MAX_SECOND); - pullMaxWaitTime = conf.getInt(TransferConstants.TASK_PULL_MAX_SECOND, TransferConstants.DEFAULT_TASK_PULL_MAX_SECOND); - - if (executorService == null) { - executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, - 60L, TimeUnit.SECONDS, - new SynchronousQueue(), - new TransferThreadFactory("task-reader-writer")); - } - - doChangeState(State.ACCEPTED); - } - - /** - * submit read thread - * - * @return CompletableFuture - */ - private CompletableFuture submitReadThread() { - return CompletableFuture.runAsync(() -> { - Message message = null; - while (!isException() && !task.isReadFinished()) { - if (message == null || task.getChannel().push(message, pushMaxWaitTime, TimeUnit.SECONDS)) { - message = task.getReader().read(); - } - } - LOGGER.info("read end, task exception status is {}, read finish status is {}", isException(), task.isReadFinished()); - // write end message - task.getChannel().push(new EndMessage()); - }, executorService); - } - - /** - * submit write thread - * - * @return CompletableFuture - */ - private CompletableFuture submitWriteThread() { - return CompletableFuture.runAsync(() -> { - while (!isException()) { - Message message = task.getChannel().pull(pullMaxWaitTime, TimeUnit.SECONDS); - if (message instanceof EndMessage) { - break; - } - task.getSink().write(message); - } - }, executorService); - } - - /** - * submit reader/writer - */ - private void submitThreadsAndWait() { - CompletableFuture reader = submitReadThread(); - CompletableFuture writer = submitWriteThread(); - - CompletableFuture.allOf(reader, writer).exceptionally(ex -> { - doChangeState(State.FAILED); - LOGGER.error("exception caught", ex); - return null; - }).join(); - } - - /** - * kill task - */ - void kill() { - LOGGER.info("task id {} is killed", task.getTaskId()); - doChangeState(State.KILLED); - } - - /** - * In standalone mode, the job to be removed should wait until the read is finished, set - * timeout to WAIT_FINISH_TIME_OUT minute to wait for finishing - */ - void waitForFinish() { - LOGGER.info("set readTime out to 1 minute task id is {}", task.getTaskId()); - task.getReader().setReadTimeout(TimeUnit.MINUTES.toMillis(WAIT_FINISH_TIME_OUT)); - } - - /** - * whether task retry times exceed max retry time. - * - * @return - whether should retry - */ - boolean shouldRetry() { - return retryTime.get() < maxRetryTime; - } - - Task getTask() { - return task; - } - - @Override - public void addCallbacks() { - this.addCallback(State.ACCEPTED, State.RUNNING, (before, after) -> { - - }).addCallback(State.RUNNING, State.FAILED, (before, after) -> { - LOGGER.info("task {} is failed, please check it", task.getTaskId()); - retryTime.incrementAndGet(); - if (!shouldRetry()) { - doChangeState(State.FATAL); - taskManager.getTaskMetrics().fatalTasks.incr(); - } - }).addCallback(State.FAILED, State.FATAL, (before, after) -> { - - }).addCallback(State.FAILED, State.ACCEPTED, (before, after) -> { - - }).addCallback(State.FAILED, State.RUNNING, ((before, after) -> { - - })).addCallback(State.RUNNING, State.SUCCEEDED, (before, after) -> { - - }); - } - - - @Override - public void run() { - try { - LOGGER.info("start to run {}, retry time is {}", task.getTaskId(), retryTime.get()); - doChangeState(State.RUNNING); - task.init(); - - submitThreadsAndWait(); - if (!isException()) { - doChangeState(State.SUCCEEDED); - } - - LOGGER.info("start to destroy task {}", task.getTaskId()); - task.destroy(); - } catch (Exception ex) { - LOGGER.error("error while running wrapper", ex); - doChangeState(State.FAILED); - } - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java deleted file mode 100644 index 83814870..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/DirectoryTrigger.java +++ /dev/null @@ -1,262 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.trigger; - -import com.zmops.zeus.iot.server.transfer.api.Trigger; -import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; -import com.zmops.zeus.iot.server.transfer.conf.JobConstants; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; -import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; -import com.zmops.zeus.iot.server.transfer.utils.FileSearchUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.nio.file.*; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.stream.Stream; - - -/** - * Watch directory, if new valid files are created, create - * jobs correspondingly. - */ -public class DirectoryTrigger extends AbstractDaemon implements Trigger { - - private static final Logger LOGGER = LoggerFactory.getLogger(DirectoryTrigger.class); - private static volatile WatchService watchService; - - private final ConcurrentHashMap> allWatchers = new ConcurrentHashMap<>(); - private final LinkedBlockingQueue queue = new LinkedBlockingQueue<>(); - - private TriggerProfile profile; - private int interval; - - private static void initWatchService() { - try { - if (watchService == null) { - synchronized (DirectoryTrigger.class) { - if (watchService == null) { - watchService = FileSystems.getDefault().newWatchService(); - LOGGER.info("init watch service {}", watchService); - } - } - } - } catch (Exception ex) { - LOGGER.warn("error while init watch service", ex); - } - } - - public TriggerProfile getProfile() { - return profile; - } - - @Override - public void destroy() { - try { - stop(); - } catch (Exception ex) { - LOGGER.error("exception while stopping threads", ex); - } - } - - @Override - public JobProfile fetchJobProfile() { - return queue.poll(); - } - - @Override - public TriggerProfile getTriggerProfile() { - return profile; - } - - @Override - public void stop() { - waitForTerminate(); - releaseResource(); - } - - /** - * register all sub-directory - * - * @param entity - entity - * @param path - path - * @param tmpWatchers - watchers - */ - private void registerAllSubDir(PathPattern entity, - Path path, - List tmpWatchers) throws Exception { - // check regex - LOGGER.info("check whether path {} is suitable", path); - - if (entity.suitForWatch(path.toString())) { - - if (path.toFile().isDirectory()) { - WatchKey watchKey = path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE); - tmpWatchers.add(watchKey); - - try (Stream stream = Files.list(path)) { - Iterator iterator = stream.iterator(); - while (iterator.hasNext()) { - registerAllSubDir(entity, iterator.next().toAbsolutePath(), tmpWatchers); - } - } - - } else { - JobProfile copiedJobProfile = FileSearchUtils.copyJobProfile(profile, entity.getSuitTime(), path.toFile()); - LOGGER.info("trigger {} generate job profile to read file {}", getTriggerProfile().getTriggerId(), path.toString()); - queue.offer(copiedJobProfile); - } - } - } - - /** - * if directory has created, then check whether directory is valid - * - * @param entity - entity - * @param watchKey - watch key - * @param tmpWatchers - watchers - */ - private void registerNewDir(PathPattern entity, WatchKey watchKey, List tmpWatchers, List tmpDeletedWatchers) throws Exception { - - Path parentPath = (Path) watchKey.watchable(); - - for (WatchEvent event : watchKey.pollEvents()) { - // if watch event is too much, then event would be overflow. - if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE) { - // only watch create event, so else is create-event. - entity.updateDateFormatRegex(); - Path createdPath = (Path) event.context(); - if (createdPath != null) { - registerAllSubDir(entity, parentPath.resolve(createdPath), tmpWatchers); - } - } else if (event.kind() == StandardWatchEventKinds.OVERFLOW) { - LOGGER.info("overflow got {}", parentPath); - // check whether parent path is valid. - if (Files.isDirectory(parentPath)) { - for (Iterator it = Files.list(parentPath).iterator(); it.hasNext(); ) { - Path childPath = it.next(); - registerAllSubDir(entity, parentPath.resolve(childPath), tmpWatchers); - } - } - } - } - if (!Files.exists(parentPath)) { - LOGGER.warn("{} not exist, add watcher to pending delete list", parentPath); - tmpDeletedWatchers.add(watchKey); - } - } - - /** - * handler watchers - * - * @return runnable - */ - private Runnable watchEventHandler() { - return () -> { - while (isRunnable()) { - try { - TimeUnit.SECONDS.sleep(interval); - allWatchers.forEach((pathPattern, watchKeys) -> { - List tmpWatchers = new ArrayList<>(); - List tmpDeletedWatchers = new ArrayList<>(); - - pathPattern.cleanup(); - try { - for (WatchKey watchKey : watchKeys) { - registerNewDir(pathPattern, watchKey, tmpWatchers, tmpDeletedWatchers); - } - } catch (Exception ex) { - LOGGER.error("error caught", ex); - } - watchKeys.addAll(tmpWatchers); - watchKeys.removeAll(tmpDeletedWatchers); - }); - } catch (Exception ex) { - LOGGER.error("error caught", ex); - } - } - }; - } - - private void releaseResource() { - allWatchers.forEach((absoluteFilePath, watchKeys) -> { - watchKeys.forEach(WatchKey::cancel); - }); - allWatchers.clear(); - } - - @Override - public void start() throws Exception { - submitWorker(watchEventHandler()); - } - - public void register(String pathPattern) throws IOException { - PathPattern entity = new PathPattern(pathPattern); - innerRegister(pathPattern, entity); - } - - public void register(String pathPattern, String offset) throws IOException { - PathPattern entity = new PathPattern(pathPattern, offset); - innerRegister(pathPattern, entity); - } - - private void innerRegister(String pathPattern, PathPattern entity) throws IOException { - List tmpKeyList = new ArrayList<>(); - List keyList = allWatchers.putIfAbsent(entity, tmpKeyList); - - if (keyList == null) { - Path rootPath = Paths.get(entity.getRootDir()); - LOGGER.info("watch root path is {}", rootPath); - WatchKey key = rootPath.register(watchService, StandardWatchEventKinds.ENTRY_CREATE); - tmpKeyList.add(key); - } else { - LOGGER.error("{} exists in watcher list, please check it", pathPattern); - } - } - - public void unregister(String pathPattern) { - PathPattern entity = new PathPattern(pathPattern); - Collection allKeys = allWatchers.remove(entity); - if (allKeys != null) { - LOGGER.info("unregister pattern {}, total size of path {}", pathPattern, allKeys.size()); - for (WatchKey key : allKeys) { - key.cancel(); - } - } - } - - ConcurrentHashMap> getAllWatchers() { - return allWatchers; - } - - @Override - public void init(TriggerProfile profile) throws IOException { - initWatchService(); - interval = profile.getInt(TransferConstants.TRIGGER_CHECK_INTERVAL, TransferConstants.DEFAULT_TRIGGER_CHECK_INTERVAL); - this.profile = profile; - - if (this.profile.hasKey(JobConstants.JOB_DIR_FILTER_PATTERN)) { - String pathPattern = this.profile.get(JobConstants.JOB_DIR_FILTER_PATTERN); - String timeOffset = this.profile.get(JobConstants.JOB_FILE_TIME_OFFSET, ""); - if (timeOffset.isEmpty()) { - register(pathPattern); - } - register(pathPattern, timeOffset); - } - } - - @Override - public void run() { - try { - start(); - } catch (Exception exception) { - throw new IllegalStateException(exception); - } - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/PathPattern.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/PathPattern.java deleted file mode 100644 index 86152b88..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/PathPattern.java +++ /dev/null @@ -1,178 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.trigger; - -import com.zmops.zeus.iot.server.transfer.core.filter.DateFormatRegex; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - -/** - * path pattern for file filter. 文件匹配 - * - * @editor nantian - */ -public class PathPattern { - - private static final Logger LOGGER = LoggerFactory.getLogger(PathPattern.class); - - private final DateFormatRegex dateFormatRegex; - - private final String watchDir; - private final String rootDir; - private final Set subDirs; - - public PathPattern(String watchDir) { - this.watchDir = watchDir; - rootDir = findRoot(watchDir); - subDirs = new HashSet<>(); - dateFormatRegex = DateFormatRegex.ofRegex(watchDir); - } - - public PathPattern(String watchDir, String offset) { - this.watchDir = watchDir; - rootDir = findRoot(watchDir); - subDirs = new HashSet<>(); - dateFormatRegex = DateFormatRegex.ofRegex(watchDir).withOffset(offset); - } - - /** - * find last existing path by pattern. - * - * @param watchDir - * @return - */ - private String findRoot(String watchDir) { - Path currentPath = Paths.get(watchDir); - if (!Files.exists(currentPath)) { - Path parentPath = currentPath.getParent(); - if (parentPath != null) { - return findRoot(parentPath.toString()); - } - } - if (Files.isDirectory(currentPath)) { - return watchDir; - } - return currentPath.getParent().toString(); - } - - /** - * walk all suitable files under directory. - * - * @param collectResult - * @param maxNum - */ - private void walkAllSuitableFiles(File dirPath, final Collection collectResult, int maxNum) throws IOException { - if (collectResult.size() > maxNum) { - LOGGER.warn("max num of files is {}, please check", maxNum); - return; - } - - if (dirPath.isFile() && dateFormatRegex.withFile(dirPath).match()) { - collectResult.add(dirPath); - } else if (dirPath.isDirectory()) { - Files.list(dirPath.toPath()).forEach(path -> { - try { - walkAllSuitableFiles(path.toFile(), collectResult, maxNum); - } catch (IOException ex) { - LOGGER.warn("cannot add {}, please check it", path, ex); - } - }); - } - } - - /** - * walk root directory - * - * @param collectResult - * @param maxNum - * @throws IOException - */ - public void walkAllSuitableFiles(final Collection collectResult, int maxNum) throws IOException { - walkAllSuitableFiles(new File(rootDir), collectResult, maxNum); - } - - /** - * cleanup local cache, subDirs is only used to filter duplicated directories - * in one term watch key check. - */ - public void cleanup() { - subDirs.clear(); - } - - /** - * whether path is suitable - * - * @param pathStr - pathString - * @return true if suit else false. - */ - public boolean suitForWatch(String pathStr) { - // remove common root dir - String briefSubDir = StringUtils.substringAfter(pathStr, rootDir); - // if already watched, then stop deep find - if (subDirs.contains(briefSubDir)) { - LOGGER.info("already watched {}", pathStr); - return false; - } - boolean matched = dateFormatRegex.withFile(new File(pathStr)).match(); - if (matched) { - LOGGER.info("add path {}", pathStr); - subDirs.add(briefSubDir); - } - return matched; - } - - /** - * when a new file is found, update regex since time may change. - * - * @param - */ - public void updateDateFormatRegex() { - dateFormatRegex.setRegexWithCurrentTime(this.watchDir); - } - - /** - * when job is retry job, the time for searching file should be specified. - * - * @param time - */ - public void updateDateFormatRegex(String time) { - dateFormatRegex.setRegexWithTime(this.watchDir, time); - } - - @Override - public String toString() { - return watchDir; - } - - @Override - public int hashCode() { - return HashCodeBuilder.reflectionHashCode(watchDir, false); - } - - @Override - public boolean equals(Object object) { - if (object instanceof PathPattern) { - PathPattern entity = (PathPattern) object; - return entity.watchDir.equals(this.watchDir); - } else { - return false; - } - } - - public String getRootDir() { - return rootDir; - } - - public String getSuitTime() { - return dateFormatRegex.getFormattedTime(); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java deleted file mode 100644 index 0c9f5c43..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/trigger/TriggerManager.java +++ /dev/null @@ -1,241 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.trigger; - -import com.zmops.zeus.iot.server.transfer.api.Trigger; -import com.zmops.zeus.iot.server.transfer.common.AbstractDaemon; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.conf.TransferConfiguration; -import com.zmops.zeus.iot.server.transfer.conf.TransferConstants; -import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; -import com.zmops.zeus.iot.server.transfer.core.TransferManager; -import com.zmops.zeus.iot.server.transfer.core.db.TriggerProfileDb; -import com.zmops.zeus.iot.server.transfer.core.job.JobWrapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; - -import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_ID; -import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.TRIGGER_ONLY_ONE_JOB; -import static com.zmops.zeus.iot.server.transfer.conf.TransferConstants.DEFAULT_TRIGGER_MAX_RUNNING_NUM; -import static com.zmops.zeus.iot.server.transfer.conf.TransferConstants.TRIGGER_MAX_RUNNING_NUM; - -/** - * 文件变动监听触发器管理 - * - * @editor nantian - */ -public class TriggerManager extends AbstractDaemon { - - private static final Logger LOGGER = LoggerFactory.getLogger(TriggerManager.class); - - public static final int JOB_CHECK_INTERVAL = 1; - - private final TransferManager manager; - private final TriggerProfileDb triggerProfileDB; - - private final ConcurrentHashMap triggerMap; - - private final ConcurrentHashMap> triggerJobMap; - - private final int triggerFetchInterval; - private final int maxRunningNum; - - public TriggerManager(TransferManager manager, TriggerProfileDb triggerProfileDb) { - - TransferConfiguration conf = TransferConfiguration.getAgentConf(); - - this.manager = manager; - this.triggerProfileDB = triggerProfileDb; - this.triggerMap = new ConcurrentHashMap<>(); - this.triggerJobMap = new ConcurrentHashMap<>(); - this.triggerFetchInterval = conf.getInt(TransferConstants.TRIGGER_FETCH_INTERVAL, TransferConstants.DEFAULT_TRIGGER_FETCH_INTERVAL); - this.maxRunningNum = conf.getInt(TRIGGER_MAX_RUNNING_NUM, DEFAULT_TRIGGER_MAX_RUNNING_NUM); - } - - /** - * submit trigger profile. - * - * @param triggerProfile - trigger profile - */ - public boolean addTrigger(TriggerProfile triggerProfile) { - try { - Trigger trigger = new DirectoryTrigger(); - String triggerId = triggerProfile.get(JOB_ID); - - if (triggerMap.containsKey(triggerId)) { - deleteTrigger(triggerId); - LOGGER.warn("trigger {} is running, stop it", triggerId); - } - - triggerMap.put(triggerId, trigger); - trigger.init(triggerProfile); - trigger.run(); - - } catch (Exception ex) { - LOGGER.error("exception caught", ex); - return false; - } - return true; - } - - - public Trigger getTrigger(String triggerId) { - return triggerMap.get(triggerId); - } - - public boolean submitTrigger(TriggerProfile triggerProfile) { - // make sure all required key exists. - if (!triggerProfile.allRequiredKeyExist() || this.triggerMap.size() > maxRunningNum) { - LOGGER.error("trigger {} not all required key exists or size {} exceed {}", triggerProfile.toJsonStr(), this.triggerMap.size(), maxRunningNum); - return false; - } - triggerProfileDB.storeTrigger(triggerProfile); - addTrigger(triggerProfile); - return true; - } - - - private Runnable jobFetchThread() { - return () -> { - while (isRunnable()) { - try { - triggerMap.forEach((s, trigger) -> { - JobProfile profile = trigger.fetchJobProfile(); - - if (profile != null) { - TriggerProfile triggerProfile = trigger.getTriggerProfile(); - - if (triggerProfile.getBoolean(TRIGGER_ONLY_ONE_JOB, false)) { - deleteRelatedJobs(triggerProfile.getTriggerId()); - } - - manager.getJobManager().submitJobProfile(profile); - addToTriggerMap(profile.get(JOB_ID), profile); - } - }); - TimeUnit.SECONDS.sleep(triggerFetchInterval); - } catch (Exception ignored) { - LOGGER.info("ignored Exception ", ignored); - } - } - - }; - } - - /** - * delete jobs generated by the trigger - * - * @param triggerId - */ - private void deleteRelatedJobs(String triggerId) { - LOGGER.info("start to delete related jobs in triggerId {}", triggerId); - ConcurrentHashMap jobProfiles = triggerJobMap.get(triggerId); - - if (jobProfiles != null) { - LOGGER.info("trigger can only run one job, stop the others {}", jobProfiles.keySet()); - jobProfiles.keySet().forEach(this::deleteJob); - triggerJobMap.remove(triggerId); - } - } - - private void deleteJob(String jobInstanceId) { - manager.getJobManager().deleteJob(jobInstanceId); - } - - - private Runnable jobCheckThread() { - return () -> { - while (isRunnable()) { - try { - triggerJobMap.forEach((s, jobProfiles) -> { - for (String jobId : jobProfiles.keySet()) { - Map jobs = manager.getJobManager().getJobs(); - if (jobs.get(jobId) == null) { - triggerJobMap.remove(jobId); - } - } - }); - TimeUnit.MINUTES.sleep(JOB_CHECK_INTERVAL); - } catch (Exception ignored) { - LOGGER.info("ignored Exception ", ignored); - } - } - - }; - } - - /** - * need to put profile in triggerJobMap - * - * @param triggerId - * @param profile - */ - private void addToTriggerMap(String triggerId, JobProfile profile) { - ConcurrentHashMap tmpList = new ConcurrentHashMap<>(); - ConcurrentHashMap jobWrappers = triggerJobMap.putIfAbsent(triggerId, tmpList); - - if (jobWrappers == null) { - jobWrappers = tmpList; - } - - jobWrappers.putIfAbsent(profile.getInstanceId(), profile); - } - - /** - * delete trigger by trigger profile. - * - * @param triggerId - trigger profile. - */ - public boolean deleteTrigger(String triggerId) { - LOGGER.info("delete trigger {}", triggerId); - Trigger trigger = triggerMap.remove(triggerId); - - if (trigger != null) { - deleteRelatedJobs(triggerId); - trigger.destroy(); - // delete trigger from db - triggerProfileDB.deleteTrigger(triggerId); - return true; - } - LOGGER.warn("cannot find trigger {}", triggerId); - return false; - } - - - /** - * init all triggers when daemon started. - */ - private void initTriggers() throws Exception { - // fetch all triggers from db - List profileList = triggerProfileDB.getTriggers(); - - for (TriggerProfile profile : profileList) { - addTrigger(profile); - } - } - - private void stopTriggers() { - triggerMap.forEach((s, trigger) -> { - trigger.destroy(); - }); - } - - @Override - public void start() throws Exception { - initTriggers(); - submitWorker(jobFetchThread()); - submitWorker(jobCheckThread()); - } - - - @Override - public void stop() { - // stop all triggers - stopTriggers(); - } - - -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PatternValidator.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PatternValidator.java deleted file mode 100644 index 67b87b9f..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PatternValidator.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.validator; - - -import com.zmops.zeus.iot.server.transfer.api.Validator; - -public class PatternValidator implements Validator { - - public PatternValidator(String pattern) { - this.pattern = pattern; - } - - private String pattern; - - @Override - public boolean validate(String messageLine) { - return messageLine.contains(pattern); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PrefixValidator.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PrefixValidator.java deleted file mode 100644 index b349dd2a..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/core/validator/PrefixValidator.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.core.validator; - -import com.zmops.zeus.iot.server.transfer.api.Validator; - -public class PrefixValidator implements Validator { - - public PrefixValidator(String prefix) { - this.prefix = prefix; - } - - private String prefix; - - @Override - public boolean validate(String messageLine) { - return messageLine.startsWith(prefix); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/AgentDynamicMBean.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/AgentDynamicMBean.java deleted file mode 100644 index 83be0dee..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/AgentDynamicMBean.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.metrics; - -import com.zmops.zeus.iot.server.transfer.metrics.meta.MetricMeta; -import com.zmops.zeus.iot.server.transfer.metrics.meta.MetricsMeta; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.management.*; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Dynamic MBean for agent - */ -public class AgentDynamicMBean implements DynamicMBean { - - private static final Logger LOGGER = LoggerFactory.getLogger(AgentDynamicMBean.class); - - private final ConcurrentHashMap> snapshotAttrs = new ConcurrentHashMap<>(); - - private final MBeanInfo mBeanInfo; - private final List attrs; - private final MetricsMeta metricsMeta; - private final String module; - private final String aspect; - private final String desc; - - public AgentDynamicMBean(String module, String aspect, String desc, MetricsMeta metricsMeta, Object source) { - this.module = module; - this.aspect = aspect; - this.desc = desc; - this.metricsMeta = metricsMeta; - this.attrs = new ArrayList<>(); - this.mBeanInfo = metricsMetaToInfo(); - - formatSnapshotList(source); - } - - private void formatSnapshotList(Object source) { - for (MetricMeta metricMeta : this.metricsMeta.getMetricMetaList()) { - try { - snapshotAttrs.put(metricMeta.getName(), (MetricSnapshot) metricMeta.getField().get(source)); - } catch (Exception ex) { - LOGGER.error("exception while adding snapshot list", ex); - } - } - } - - - private MBeanInfo metricsMetaToInfo() { - // overwrite name, desc from MetricsMeta if not null. - String name = this.module == null ? metricsMeta.getName() : this.module; - String description = this.desc == null ? metricsMeta.getDesc() : this.desc; - - for (MetricMeta fieldMetricMeta : metricsMeta.getMetricMetaList()) { - attrs.add(new MBeanAttributeInfo(fieldMetricMeta.getName(), - fieldMetricMeta.getType(), fieldMetricMeta.getDesc(), true, false, false)); - } - return new MBeanInfo(name, description, attrs.toArray(new MBeanAttributeInfo[0]), - null, null, null); - } - - @Override - public Object getAttribute(String attribute) { - MetricSnapshot snapshot = snapshotAttrs.get(attribute); - return new Attribute(attribute, snapshot.snapshot()); - } - - @Override - public void setAttribute(Attribute attribute) { - throw new UnsupportedOperationException("Metrics are read-only."); - } - - @Override - public AttributeList getAttributes(String[] attributes) { - AttributeList attributeList = new AttributeList(); - for (String attrKey : attributes) { - MetricSnapshot snapshot = snapshotAttrs.get(attrKey); - if (snapshot != null) { - attributeList.add(new Attribute(attrKey, snapshot.snapshot())); - } - } - return attributeList; - } - - @Override - public AttributeList setAttributes(AttributeList attributes) { - throw new UnsupportedOperationException("Metrics are read-only."); - } - - @Override - public Object invoke(String actionName, Object[] params, String[] signature) { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public MBeanInfo getMBeanInfo() { - return mBeanInfo; - } - - public String getModule() { - return module; - } - - public String getAspect() { - return aspect; - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Metric.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Metric.java deleted file mode 100644 index dc57eb64..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Metric.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.metrics; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * metric for field - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.FIELD, ElementType.METHOD}) -public @interface Metric { - - /** - * Type of metric - * - * @return metric type - */ - Type type() default Type.DEFAULT; - - /** - * Doc of metric - * - * @return metric doc - */ - String desc() default ""; - - enum Type { - DEFAULT("java.lang.String"), - COUNTER_INT("java.lang.Integer"), - COUNTER_LONG("java.lang.Long"), - GAUGE_INT("java.lang.Integer"), - GAUGE_LONG("java.lang.Long"), - TAG("java.lang.String"); - private final String value; - - private Type(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricException.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricException.java deleted file mode 100644 index b6c5705b..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricException.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.metrics; - -public class MetricException extends RuntimeException { - - public MetricException(String message, Exception ex) { - super(message, ex); - } - - public MetricException(String message) { - super(message); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricSnapshot.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricSnapshot.java deleted file mode 100644 index 9eb658c9..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricSnapshot.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.metrics; - -public interface MetricSnapshot { - T snapshot(); -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Metrics.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Metrics.java deleted file mode 100644 index 2e71f1ff..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Metrics.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.metrics; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * metric - */ -@Target({ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -public @interface Metrics { - - /** - * Metrics name - * - * @return - */ - String name() default ""; - - /** - * Metrics context - * - * @return - */ - String context() default ""; - - /** - * Metrics description - * - * @return - */ - String desc() default ""; -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricsRegister.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricsRegister.java deleted file mode 100644 index bb10537f..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MetricsRegister.java +++ /dev/null @@ -1,132 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.metrics; - - -import com.zmops.zeus.iot.server.transfer.metrics.counter.CounterInt; -import com.zmops.zeus.iot.server.transfer.metrics.counter.CounterLong; -import com.zmops.zeus.iot.server.transfer.metrics.gauge.GaugeInt; -import com.zmops.zeus.iot.server.transfer.metrics.gauge.GaugeLong; -import com.zmops.zeus.iot.server.transfer.metrics.meta.MetricMeta; -import com.zmops.zeus.iot.server.transfer.metrics.meta.MetricsMeta; -import com.zmops.zeus.iot.server.transfer.utils.TransferUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.management.MBeanServer; -import javax.management.ObjectName; -import java.lang.annotation.Annotation; -import java.lang.management.ManagementFactory; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; - -/** - * register for metrics. - */ -public class MetricsRegister { - private static final Logger LOGGER = LoggerFactory.getLogger(MetricsRegister.class); - - private static final String DOMAIN_PREFIX = "Agent:"; - private static final String MODULE_PREFIX = "module="; - private static final String ASPECT_PREFIX = "aspect="; - private static final String COMMA_SPLITTER = ","; - - // object name should be uniq - private static final ConcurrentHashMap CACHED_NAME = new ConcurrentHashMap<>(); - - private MetricsRegister() { - } - - /** - * register object name for metric - * - * @param agentDynamicMBean agent mbean - */ - private static void innerRegister(AgentDynamicMBean agentDynamicMBean) { - final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - String nameStr = DOMAIN_PREFIX + MODULE_PREFIX + agentDynamicMBean.getModule() - + COMMA_SPLITTER + ASPECT_PREFIX + agentDynamicMBean.getAspect(); - try { - ObjectName tmpName = new ObjectName(nameStr); - ObjectName objectName = CACHED_NAME.putIfAbsent(nameStr, tmpName); - if (objectName == null) { - mbs.registerMBean(agentDynamicMBean, tmpName); - } - } catch (Exception ex) { - LOGGER.error("exception while register mbean", ex); - } - } - - public static void register(String module, String aspect, String desc, Object source) { - List metricMetaList = handleFieldAnnotation(source); - MetricsMeta metricsMeta = handleClassAnnotation(source, metricMetaList); - if (metricsMeta != null) { - innerRegister(new AgentDynamicMBean(module, aspect, desc, metricsMeta, source)); - } else { - LOGGER.error("Cannot find Metrics annotation in {}, invalid metric", source); - } - } - - - /** - * handle class level annotation - */ - private static MetricsMeta handleClassAnnotation(Object source, - List metricMetaList) { - for (Annotation annotation : source.getClass().getAnnotations()) { - if (annotation instanceof Metrics) { - return MetricsMeta.build((Metrics) annotation, metricMetaList); - } - } - return null; - } - - - private static boolean initFieldByType(Object source, Field field) { - try { - if (field.getType() == CounterInt.class) { - field.set(source, new CounterInt()); - return true; - } else if (field.getType() == CounterLong.class) { - field.set(source, new CounterLong()); - return true; - } else if (field.getType() == GaugeInt.class) { - field.set(source, new GaugeInt()); - return true; - } else if (field.getType() == GaugeLong.class) { - field.set(source, new GaugeLong()); - return true; - } else if (field.getType() == Tag.class) { - field.set(source, new Tag()); - return true; - } else { - throw new MetricException("field type error " + field.getType().toString()); - } - } catch (MetricException ex) { - throw ex; - } catch (Exception ex) { - throw new MetricException("Error setting field " + field - + " annotated with metric", ex); - } - } - - /** - * handle field annotation - */ - private static List handleFieldAnnotation(Object source) { - List result = new ArrayList<>(); - for (Field field : TransferUtils.getDeclaredFieldsIncludingInherited(source.getClass())) { - field.setAccessible(true); - for (Annotation fieldAnnotation : field.getAnnotations()) { - if (fieldAnnotation instanceof Metric) { - if (initFieldByType(source, field)) { - result.add(MetricMeta.build((Metric) fieldAnnotation, field)); - } - break; - } - } - } - return result; - } -} - diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MutableMetric.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MutableMetric.java deleted file mode 100644 index f2f78b27..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/MutableMetric.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.metrics; - -/** - * Metric with number - */ -public interface MutableMetric extends MetricSnapshot { - -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/PluginMetric.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/PluginMetric.java deleted file mode 100644 index e6dd7cee..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/PluginMetric.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.metrics; - -import com.zmops.zeus.iot.server.transfer.metrics.counter.CounterLong; - -/** - * Common plugin metrics - */ -@Metrics -public class PluginMetric { - - @Metric - public Tag tagName; - - @Metric - public CounterLong readNum; - - @Metric - public CounterLong sendNum; - - @Metric - public CounterLong sendFailedNum; - - @Metric - public CounterLong readFailedNum; - - @Metric - public CounterLong readSuccessNum; - - @Metric - public CounterLong sendSuccessNum; - - public PluginMetric() { - // every metric should register, otherwise not working. - MetricsRegister.register("Plugin", "PluginSummary", null, this); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Tag.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Tag.java deleted file mode 100644 index 304a0ceb..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/Tag.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.metrics; - -public class Tag implements MetricSnapshot { - - private String name; - - /** - * set string name for tag. - * - * @param name - tag name - */ - public void setName(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - @Override - public String snapshot() { - return name; - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/Counter.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/Counter.java deleted file mode 100644 index e4f8b1da..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/Counter.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.metrics.counter; - - -import com.zmops.zeus.iot.server.transfer.metrics.MutableMetric; - -public interface Counter extends MutableMetric { - - /** - * +1 - */ - void incr(); - - /** - * +delta - * - * @param delta > 0 - */ - void incr(int delta); - -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/CounterInt.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/CounterInt.java deleted file mode 100644 index 44dc09af..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/CounterInt.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.metrics.counter; - -import java.util.concurrent.atomic.AtomicInteger; - -public class CounterInt implements Counter { - - private AtomicInteger value = new AtomicInteger(0); - - @Override - public void incr() { - value.incrementAndGet(); - } - - @Override - public void incr(int delta) { - assert delta > 0; - value.getAndAdd(delta); - } - - @Override - public Integer snapshot() { - return value.get(); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/CounterLong.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/CounterLong.java deleted file mode 100644 index 47cb4761..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/counter/CounterLong.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.metrics.counter; - -import java.util.concurrent.atomic.AtomicLong; - -/** - * atomic long for counter - */ -public class CounterLong implements Counter { - - private final AtomicLong value = new AtomicLong(); - - @Override - public void incr() { - value.incrementAndGet(); - } - - @Override - public void incr(int delta) { - assert delta > 0; - value.getAndAdd(delta); - } - - @Override - public Long snapshot() { - return value.get(); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/Gauge.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/Gauge.java deleted file mode 100644 index 904e8530..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/Gauge.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.metrics.gauge; - -import com.zmops.zeus.iot.server.transfer.metrics.MutableMetric; - -public interface Gauge extends MutableMetric { - - void set(T num); - - /** - * +1 - */ - void incr(); - - /** - * + delt - * - * @param delta > 0 - */ - void incr(int delta); - - /** - * -1 - */ - void decr(); - - /** - * -delta - * - * @param delta > 0 - */ - void decr(int delta); -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/GaugeInt.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/GaugeInt.java deleted file mode 100644 index 82fb941e..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/GaugeInt.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.metrics.gauge; - -import java.util.concurrent.atomic.AtomicInteger; - -public class GaugeInt implements Gauge { - - private final AtomicInteger value = new AtomicInteger(0); - - @Override - public void set(Integer num) { - value.set(num); - } - - @Override - public void incr() { - value.incrementAndGet(); - } - - @Override - public void incr(int delta) { - assert delta > 0; - value.getAndAdd(delta); - } - - @Override - public void decr() { - value.decrementAndGet(); - } - - @Override - public void decr(int delta) { - assert delta > 0; - value.getAndAdd(-delta); - } - - @Override - public Integer snapshot() { - return value.get(); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/GaugeLong.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/GaugeLong.java deleted file mode 100644 index f8e9c71c..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/gauge/GaugeLong.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.metrics.gauge; - -import java.util.concurrent.atomic.AtomicLong; - -public class GaugeLong implements Gauge { - - private final AtomicLong value = new AtomicLong(0); - - @Override - public void set(Long num) { - value.set(num); - } - - @Override - public void incr() { - value.incrementAndGet(); - } - - @Override - public void incr(int delta) { - assert delta > 0; - value.getAndAdd(delta); - } - - @Override - public void decr() { - value.decrementAndGet(); - } - - @Override - public void decr(int delta) { - assert delta > 0; - value.getAndAdd(-delta); - } - - @Override - public Long snapshot() { - return value.get(); - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricMeta.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricMeta.java deleted file mode 100644 index 0900368b..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricMeta.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.metrics.meta; - -import com.zmops.zeus.iot.server.transfer.metrics.Metric; -import com.zmops.zeus.iot.server.transfer.metrics.counter.CounterInt; -import com.zmops.zeus.iot.server.transfer.metrics.counter.CounterLong; -import com.zmops.zeus.iot.server.transfer.metrics.gauge.GaugeInt; -import com.zmops.zeus.iot.server.transfer.metrics.gauge.GaugeLong; -import org.apache.commons.lang3.StringUtils; - -import java.lang.reflect.Field; - -import static com.zmops.zeus.iot.server.transfer.metrics.Metric.Type.*; - -/** - * this class is related to {@link Metric} - */ -public class MetricMeta { - - private String name; - private String type; - private String desc; - private Field field; - - public static MetricMeta build(Metric annotation, Field field) { - MetricMeta metricMeta = new MetricMeta(); - metricMeta.name = StringUtils.capitalize(field.getName()); - metricMeta.desc = annotation.desc(); - metricMeta.type = DEFAULT.getValue(); - metricMeta.field = field; - Class clz = field.getType(); - if (clz.isAssignableFrom(CounterLong.class)) { - metricMeta.type = COUNTER_LONG.getValue(); - } else if (clz.isAssignableFrom(CounterInt.class)) { - metricMeta.type = COUNTER_INT.getValue(); - } else if (clz.isAssignableFrom(GaugeInt.class)) { - metricMeta.type = GAUGE_INT.getValue(); - } else if (clz.isAssignableFrom(GaugeLong.class)) { - metricMeta.type = GAUGE_LONG.getValue(); - } - return metricMeta; - } - - public String getType() { - return type; - } - - public String getName() { - return name; - } - - public String getDesc() { - return desc; - } - - public Field getField() { - return field; - } -} - diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricsMeta.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricsMeta.java deleted file mode 100644 index 6181b479..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/metrics/meta/MetricsMeta.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.metrics.meta; - -import com.zmops.zeus.iot.server.transfer.metrics.Metrics; - -import java.util.List; - -/** - * This class is related to {@link Metrics} - */ -public class MetricsMeta { - - private String context; - private String desc; - private String name; - private List metricMetaList; - - private MetricsMeta() { - } - - public static MetricsMeta build(Metrics metrics, List metricMetaList) { - MetricsMeta metricsMeta = new MetricsMeta(); - metricsMeta.context = metrics.context(); - metricsMeta.desc = metrics.desc(); - metricsMeta.name = metrics.name(); - metricsMeta.metricMetaList = metricMetaList; - return metricsMeta; - } - - public String getContext() { - return context; - } - - public String getDesc() { - return desc; - } - - public List getMetricMetaList() { - return metricMetaList; - } - - public String getName() { - return name; - } -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/module/ServerTransferModule.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/module/ServerTransferModule.java index 2b40d290..5f06b94f 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/module/ServerTransferModule.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/module/ServerTransferModule.java @@ -1,6 +1,6 @@ package com.zmops.zeus.iot.server.transfer.module; -import com.zmops.zeus.iot.server.library.module.ModuleDefine; +import com.zmops.zeus.server.library.module.ModuleDefine; /** * @author nantian created at 2021/9/22 16:39 diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferConfig.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferConfig.java index 89697a6d..49918e81 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferConfig.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferConfig.java @@ -1,6 +1,6 @@ package com.zmops.zeus.iot.server.transfer.provider; -import com.zmops.zeus.iot.server.library.module.ModuleConfig; +import com.zmops.zeus.server.library.module.ModuleConfig; import lombok.Getter; import lombok.Setter; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java index 37ae8164..c3471da0 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java @@ -1,9 +1,10 @@ package com.zmops.zeus.iot.server.transfer.provider; + import com.zmops.zeus.iot.server.core.CoreModule; -import com.zmops.zeus.iot.server.library.module.*; -import com.zmops.zeus.iot.server.transfer.core.TransferManager; import com.zmops.zeus.iot.server.transfer.module.ServerTransferModule; +import com.zmops.zeus.server.library.module.*; +import com.zmops.zeus.server.transfer.core.TransferManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -59,14 +60,14 @@ private static void stopManagerIfKilled(TransferManager manager) { @Override public void start() throws ServiceNotProvidedException, ModuleStartException { - TransferManager manager = new TransferManager(config); - try { - manager.start(); - stopManagerIfKilled(manager); -// manager.join(); - } catch (Exception e) { - e.printStackTrace(); - } +// TransferManager manager = new TransferManager(config); +// try { +// manager.start(); +// stopManagerIfKilled(manager); +//// manager.join(); +// } catch (Exception e) { +// e.printStackTrace(); +// } } @Override diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java index c4271176..0eef9ed6 100644 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java @@ -7,9 +7,9 @@ import com.zmops.zeus.iot.server.core.analysis.manual.history.UIntHistory; import com.zmops.zeus.iot.server.core.analysis.record.Record; import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.core.task.TaskPositionManager; -import com.zmops.zeus.iot.server.transfer.metrics.PluginMetric; +import com.zmops.zeus.server.transfer.conf.JobProfile; +import com.zmops.zeus.server.transfer.core.task.TaskPositionManager; +import com.zmops.zeus.server.transfer.metrics.PluginMetric; import lombok.Getter; import lombok.Setter; import org.slf4j.Logger; diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/FileSearchUtils.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/FileSearchUtils.java deleted file mode 100644 index 2154bb5b..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/FileSearchUtils.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.utils; - -import com.zmops.zeus.iot.server.transfer.conf.JobConstants; -import com.zmops.zeus.iot.server.transfer.conf.JobProfile; -import com.zmops.zeus.iot.server.transfer.conf.TriggerProfile; -import com.zmops.zeus.iot.server.transfer.core.trigger.PathPattern; -import lombok.extern.slf4j.Slf4j; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; - -import static com.zmops.zeus.iot.server.transfer.conf.CommonConstants.DEFAULT_FILE_MAX_NUM; -import static com.zmops.zeus.iot.server.transfer.conf.CommonConstants.FILE_MAX_NUM; -import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_DIR_FILTER_PATTERN; -import static com.zmops.zeus.iot.server.transfer.conf.JobConstants.JOB_RETRY_TIME; - -/** - * Utils for plugin package. - */ -@Slf4j -public class FileSearchUtils { - - private static final Logger LOGGER = LoggerFactory.getLogger(FileSearchUtils.class); - - public static Collection findSuitFiles(JobProfile jobConf) { - String dirPattern = jobConf.get(JOB_DIR_FILTER_PATTERN); - LOGGER.info("start to find files with dir pattern {}", dirPattern); - - PathPattern pattern = new PathPattern(dirPattern); - updateRetryTime(jobConf, pattern); - - int maxFileNum = jobConf.getInt(FILE_MAX_NUM, DEFAULT_FILE_MAX_NUM); - LOGGER.info("dir pattern {}, max file num {}", dirPattern, maxFileNum); - - Collection allFiles = new ArrayList<>(); - try { - pattern.walkAllSuitableFiles(allFiles, maxFileNum); - } catch (IOException ex) { - LOGGER.warn("cannot get all files from {}", dirPattern, ex); - } - return allFiles; - } - - /** - * if the job is retry job, the date is determined - * - * @param jobConf - * @param pattern - */ - public static void updateRetryTime(JobProfile jobConf, PathPattern pattern) { - if (jobConf.hasKey(JOB_RETRY_TIME)) { - LOGGER.info("job {} is retry job with specific time, update file time to {}" + "", jobConf.toJsonStr(), jobConf.get(JOB_RETRY_TIME)); - pattern.updateDateFormatRegex(jobConf.get(JOB_RETRY_TIME)); - } - } - - public static JobProfile copyJobProfile(TriggerProfile triggerProfile, String dataTime, File pendingFile) { - JobProfile copiedProfile = TriggerProfile.parseJsonStr(triggerProfile.toJsonStr()); - - String md5 = TransferUtils.getFileMd5(pendingFile); - - copiedProfile.set(pendingFile.getAbsolutePath() + ".md5", md5); - copiedProfile.set(JobConstants.JOB_DIR_FILTER_PATTERN, pendingFile.getAbsolutePath()); - - // the time suit for file name is just the data time - copiedProfile.set(JobConstants.JOB_DATA_TIME, dataTime); - return copiedProfile; - } - -} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/TransferUtils.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/TransferUtils.java deleted file mode 100644 index 8d80b016..00000000 --- a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/utils/TransferUtils.java +++ /dev/null @@ -1,348 +0,0 @@ -package com.zmops.zeus.iot.server.transfer.utils; - -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.Pair; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.Closeable; -import java.io.File; -import java.io.InputStream; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.nio.charset.StandardCharsets; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.*; -import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class TransferUtils { - - private static final Logger LOGGER = LoggerFactory.getLogger(TransferUtils.class); - private static final AtomicLong INDEX = new AtomicLong(0); - private static final String HEX_PREFIX = "0x"; - public static final String EQUAL = "="; - public static final String M_VALUE = "m"; - public static final String ADDITION_SPLITTER = "&"; - public static final String BEIJING_TIME_ZONE = "GMT+8:00"; - public static final String HOUR_PATTERN = "yyyyMMddHH"; - public static final String DAY_PATTERN = "yyyyMMdd"; - public static final String DEFAULT_PATTERN = "yyyyMMddHHmm"; - public static final String DAY = "D"; - public static final String HOUR = "H"; - public static final String HOUR_LOW_CASE = "h"; - public static final String MINUTE = "m"; - - - /** - * get md5 of file. - * - * @param file - file name - * @return - */ - public static String getFileMd5(File file) { - try (InputStream is = Files.newInputStream(Paths.get(file.getAbsolutePath()))) { - return DigestUtils.md5Hex(is); - } catch (Exception ex) { - LOGGER.warn("cannot get md5 of {}", file, ex); - } - return ""; - } - - /** - * finally close resources - * - * @param resource - resource which is closable. - */ - public static void finallyClose(Closeable resource) { - if (resource != null) { - try { - resource.close(); - } catch (Exception ex) { - LOGGER.info("error while closing", ex); - } - } - } - - /** - * finally close resources. - * - * @param resource - resource which is closable. - */ - public static void finallyClose(AutoCloseable resource) { - if (resource != null) { - try { - resource.close(); - } catch (Exception ex) { - LOGGER.error("error while closing", ex); - } - } - } - - /** - * Get declare fields. - */ - public static List getDeclaredFieldsIncludingInherited(Class clazz) { - List fields = new ArrayList(); - // check whether parent exists - while (clazz != null) { - fields.addAll(Arrays.asList(clazz.getDeclaredFields())); - clazz = clazz.getSuperclass(); - } - return fields; - } - - /** - * Get declare methods. - * - * @param clazz - class of field from method return - * @return list of methods - */ - public static List getDeclaredMethodsIncludingInherited(Class clazz) { - List methods = new ArrayList(); - while (clazz != null) { - methods.addAll(Arrays.asList(clazz.getDeclaredMethods())); - clazz = clazz.getSuperclass(); - } - return methods; - } - - /** - * get random int of [seed, seed * 2] - * - * @param seed - * @return - */ - public static int getRandomBySeed(int seed) { - return ThreadLocalRandom.current().nextInt(0, seed) + seed; - } - - public static String getLocalIp() { - String ip = "127.0.0.1"; - try (DatagramSocket socket = new DatagramSocket()) { - socket.connect(InetAddress.getByName("8.8.8.8"), 10002); - ip = socket.getLocalAddress().getHostAddress(); - } catch (Exception ex) { - LOGGER.error("error while get local ip", ex); - } - return ip; - } - - /** - * Get uniq id with timestamp. - * - * @return uniq id. - */ - public static String getUniqId(String prefix, String id) { - return getUniqId(prefix, id, 0L); - } - - /** - * Get uniq id with timestamp and index. - * - * @param id - job id - * @param index - job index - * @return uniq id - */ - public static String getUniqId(String prefix, String id, long index) { - long currentTime = System.currentTimeMillis() / 1000; - return prefix + currentTime + "_" + id + "_" + index; - } - - public static void silenceSleepInMs(long millisecond) { - try { - TimeUnit.MILLISECONDS.sleep(millisecond); - } catch (Exception ignored) { - LOGGER.warn("silenceSleepInMs ", ignored); - } - } - - public static String parseHexStr(String delimiter) throws IllegalArgumentException { - if (delimiter.trim().toLowerCase().startsWith(HEX_PREFIX)) { - //only one char - byte[] byteArr = new byte[1]; - byteArr[0] = Byte.decode(delimiter.trim()); - return new String(byteArr, StandardCharsets.UTF_8); - } else { - throw new IllegalArgumentException("delimiter not start with " + HEX_PREFIX); - } - } - - /** - * formatter for current time - * - * @param formatter - * @return - */ - public static String formatCurrentTime(String formatter) { - return formatCurrentTime(formatter, Locale.getDefault()); - } - - public static String formatCurrentTime(String formatter, Locale locale) { - ZonedDateTime zoned = ZonedDateTime.now(); - // TODO: locale seems not working - return DateTimeFormatter.ofPattern(formatter).withLocale(locale).format(zoned); - } - - /** - * formatter with time offset - * - * @param formatter - formatter string - * @param day - day offset - * @param hour - hour offset - * @param min - min offset - * @return current time with offset - */ - public static String formatCurrentTimeWithOffset(String formatter, int day, int hour, int min) { - ZonedDateTime zoned = ZonedDateTime.now().plusDays(day).plusHours(hour).plusMinutes(min); - return DateTimeFormatter.ofPattern(formatter).withLocale(Locale.getDefault()).format(zoned); - } - - - public static String formatCurrentTimeWithoutOffset(String formatter) { - ZonedDateTime zoned = ZonedDateTime.now().plusDays(0).plusHours(0).plusMinutes(0); - return DateTimeFormatter.ofPattern(formatter).withLocale(Locale.getDefault()).format(zoned); - } - - /** - * whether all class of path name are matched - * - * @param pathStr - path string - * @param patternStr - regex pattern - * @return true if all match - */ - public static boolean regexMatch(String pathStr, String patternStr) { - String[] pathNames = StringUtils.split(pathStr, FileSystems.getDefault().getSeparator()); - String[] patternNames = StringUtils - .split(patternStr, FileSystems.getDefault().getSeparator()); - for (int i = 0; i < pathNames.length && i < patternNames.length; i++) { - if (!pathNames[i].equals(patternNames[i])) { - Matcher matcher = Pattern.compile(patternNames[i]).matcher(pathNames[i]); - if (!matcher.matches()) { - return false; - } - } - } - return true; - } - - /** - * parse addition attr, the attributes must be send in proxy sender - * - * @param additionStr - * @return - */ - public static Pair> parseAddAttr(String additionStr) { - Map attr = new HashMap<>(); - String[] split = additionStr.split(ADDITION_SPLITTER); - String mValue = ""; - for (String s : split) { - if (!s.contains(EQUAL)) { - continue; - } - String[] pairs = s.split(EQUAL); - if (pairs[0].equalsIgnoreCase(M_VALUE)) { - mValue = pairs[1]; - continue; - } - getAttrs(attr, s, pairs); - } - return Pair.of(mValue, attr); - } - - /** - * the attrs in pairs can be complicated in online env - * - * @param attr - * @param s - * @param pairs - */ - private static void getAttrs(Map attr, String s, String[] pairs) { - // when addiction attr be like "m=10&__addcol1__worldid=" - if (s.endsWith(EQUAL) && pairs.length == 1) { - attr.put(pairs[0], ""); - } else { - attr.put(pairs[0], pairs[1]); - } - } - - /** - * get addition attributes in additionStr - * - * @param additionStr - * @return - */ - public static Map getAdditionAttr(String additionStr) { - Pair> mValueAttrs = parseAddAttr(additionStr); - return mValueAttrs.getRight(); - } - - - /** - * get m value in additionStr - * - * @param addictiveAttr - * @return - */ - public static String getmValue(String addictiveAttr) { - Pair> mValueAttrs = parseAddAttr(addictiveAttr); - return mValueAttrs.getLeft(); - } - - /** - * time str convert to mill sec - * - * @param time - * @param cycleUnit - * @return - */ - public static long timeStrConvertToMillSec(String time, String cycleUnit) { - long defaultTime = System.currentTimeMillis(); - if (time.isEmpty() || cycleUnit.isEmpty()) { - return defaultTime; - } - String pattern = DEFAULT_PATTERN; - switch (cycleUnit) { - case DAY: - pattern = DAY_PATTERN; - time = time.substring(0, 8); - break; - case HOUR: - case HOUR_LOW_CASE: - pattern = HOUR_PATTERN; - time = time.substring(0, 10); - break; - case MINUTE: - break; - default: - LOGGER.error("cycle unit {} is illegal, please check!", cycleUnit); - break; - } - return parseTimeToMillSec(time, pattern); - } - - private static long parseTimeToMillSec(String time, String pattern) { - try { - SimpleDateFormat df = new SimpleDateFormat(pattern); - df.setTimeZone(TimeZone.getTimeZone(BEIJING_TIME_ZONE)); - return df.parse(time).getTime(); - } catch (ParseException e) { - LOGGER.error("convert time string {} to millSec error", time); - } - return System.currentTimeMillis(); - } - - -} diff --git a/iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine b/iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine similarity index 100% rename from iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine rename to iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine diff --git a/iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider similarity index 100% rename from iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider rename to iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider diff --git a/iot-server/server-library/library-util/pom.xml b/iot-server/server-web/pom.xml similarity index 74% rename from iot-server/server-library/library-util/pom.xml rename to iot-server/server-web/pom.xml index 4e9c86fb..94385dc6 100644 --- a/iot-server/server-library/library-util/pom.xml +++ b/iot-server/server-web/pom.xml @@ -3,14 +3,13 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - server-library + iot-server com.zmops 1.0-beta - ../pom.xml 4.0.0 - library-util + server-web 8 @@ -20,8 +19,8 @@ com.zmops - iot-util - ${project.version} + library-web + 1.0-SNAPSHOT diff --git a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/config/IoTConfig.java b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/config/IoTConfig.java new file mode 100644 index 00000000..c35c776f --- /dev/null +++ b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/config/IoTConfig.java @@ -0,0 +1,30 @@ +package com.zmops.zeus.iot.web.config; + +import com.zmops.zeus.server.library.web.config.*; + +/** + * @author nantian created at 2021/11/22 20:48 + */ +public class IoTConfig extends WebConfig { + + @Override + public void configConstant(Constants constants) { + constants.setDevMode(true); + } + + @Override + public void configRoute(Routes routes) { + routes.setBaseViewPath("/pages"); + routes.scan("com.zmops.zeus.iot.web.controller."); + } + + @Override + public void configHandler(Handlers handlers) { + + } + + @Override + public void configInterceptor(Interceptors interceptors) { + + } +} diff --git a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/IndexController.java b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/IndexController.java new file mode 100644 index 00000000..2b8df1da --- /dev/null +++ b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/IndexController.java @@ -0,0 +1,16 @@ +package com.zmops.zeus.iot.web.controller; + +import com.zmops.zeus.server.library.web.core.Controller; +import com.zmops.zeus.server.library.web.core.Path; + +/** + * @author nantian created at 2021/11/23 23:24 + */ + +@Path(value = "/123", viewPath = "/") +public class IndexController extends Controller { + + public void hello() { + renderJson("hello", "world"); + } +} diff --git a/pom.xml b/pom.xml index e5b6245d..07d2a6aa 100644 --- a/pom.xml +++ b/pom.xml @@ -10,10 +10,6 @@ 1.0-beta Zeus IoT 物联网分布式采集平台 - - iot-common - - UTF-8 UTF-8 @@ -69,7 +65,6 @@ zeus-webapp-bom - zeus-application-toolkit @@ -92,7 +87,6 @@ iot-server iot-server-bom zeus-webapp-bom - zeus-application-toolkit zeus-iot-dist diff --git a/zeus-application-toolkit/pom.xml b/zeus-application-toolkit/pom.xml deleted file mode 100644 index 5773a0a6..00000000 --- a/zeus-application-toolkit/pom.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - zeus-iot - com.zmops - 1.0-beta - - 4.0.0 - - zeus-application-toolkit - pom - - toolkit-async - toolkit-eventbus - - - - 8 - 8 - - - \ No newline at end of file diff --git a/zeus-application-toolkit/toolkit-async/pom.xml b/zeus-application-toolkit/toolkit-async/pom.xml deleted file mode 100644 index cbfd9db9..00000000 --- a/zeus-application-toolkit/toolkit-async/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - zeus-application-toolkit - com.zmops - 1.0-beta - - 4.0.0 - - toolkit-async - - - 8 - 8 - - - \ No newline at end of file diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultCallback.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultCallback.java deleted file mode 100644 index 77878866..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultCallback.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.zmops.iot.async.callback; - - -import com.zmops.iot.async.worker.WorkResult; - -/** - * 默认回调类,如果不设置的话,会默认给这个回调 - * @author wuweifeng wrote on 2019-11-19. - */ -public class DefaultCallback implements ICallback { - @Override - public void begin() { - - } - - @Override - public void result(boolean success, T param, WorkResult workResult) { - - } - -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultGroupCallback.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultGroupCallback.java deleted file mode 100644 index af85cfc4..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultGroupCallback.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.zmops.iot.async.callback; - -import com.zmops.iot.async.wrapper.WorkerWrapper; - -import java.util.List; - -/** - * @author wuweifeng wrote on 2019-12-27 - * @version 1.0 - */ -public class DefaultGroupCallback implements IGroupCallback { - - @Override - public void success(List workerWrappers) { - - } - - @Override - public void failure(List workerWrappers, Exception e) { - - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ICallback.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ICallback.java deleted file mode 100644 index 9937a969..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ICallback.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.zmops.iot.async.callback; - - -import com.zmops.iot.async.worker.WorkResult; - -/** - * 每个执行单元执行完毕后,会回调该接口

- * 需要监听执行结果的,实现该接口即可 - * - * @author wuweifeng wrote on 2019-11-19. - */ -@FunctionalInterface -public interface ICallback { - - /** - * 任务开始的监听 - */ - default void begin() { - - } - - /** - * 耗时操作执行完毕后,就给value注入值 - */ - void result(boolean success, T param, WorkResult workResult); - - /** - * 提供常量选项: - *

- * 如果发生了异常,则打印异常信息。 - * 正常结束(例如取消、跳过)的异常不会打印。 - */ - ICallback PRINT_EXCEPTION_STACK_TRACE = new ICallback() { - @Override - public void result(boolean success, Object param, WorkResult workResult) { - Exception ex = workResult.getEx(); - if (ex != null) { - ex.printStackTrace(); - } - } - - @Override - public String toString() { - return "PRINT_EXCEPTION_STACK_TRACE"; - } - }; -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IGroupCallback.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IGroupCallback.java deleted file mode 100644 index a756022d..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IGroupCallback.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.zmops.iot.async.callback; - -import com.zmops.iot.async.wrapper.WorkerWrapper; - -import java.util.List; - -/** - * 如果是异步执行整组的话,可以用这个组回调。不推荐使用 - * @author wuweifeng wrote on 2019-11-19. - */ -public interface IGroupCallback { - /** - * 成功后,可以从wrapper里去getWorkResult - */ - void success(List workerWrappers); - /** - * 失败了,也可以从wrapper里去getWorkResult - */ - void failure(List workerWrappers, Exception e); -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ITimeoutWorker.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ITimeoutWorker.java deleted file mode 100644 index 4190efa3..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ITimeoutWorker.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.zmops.iot.async.callback; - -/** - * @author wuweifeng wrote on 2019-12-20 - * @version 1.0 - */ -public interface ITimeoutWorker extends IWorker { - /** - * 每个worker都可以设置超时时间 - * @return 毫秒超时时间 - */ - long timeOut(); - - /** - * 是否开启单个执行单元的超时功能(有时是一个group设置个超时,而不具备关心单个worker的超时) - *

注意,如果开启了单个执行单元的超时检测,将使线程池数量多出一倍

- * @return 是否开启 - */ - boolean enableTimeOut(); -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IWorker.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IWorker.java deleted file mode 100644 index 5cf2e8c8..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IWorker.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.zmops.iot.async.callback; - -import java.util.Map; - -import com.zmops.iot.async.wrapper.WorkerWrapper; - -/** - * 每个最小执行单元需要实现该接口 - * - * @author wuweifeng wrote on 2019-11-19. - */ -@FunctionalInterface -public interface IWorker { - /** - * 在这里做耗时操作,如rpc请求、IO等 - * - * @param object object - * @param allWrappers 任务包装 - */ - V action(T object, Map allWrappers); - - /** - * 超时、异常时,返回的默认值 - * - * @return 默认值 - */ - default V defaultValue() { - return null; - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/SkippedException.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/SkippedException.java deleted file mode 100644 index cf8dbf24..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/SkippedException.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.zmops.iot.async.exception; - -/** - * 如果任务在执行之前,自己后面的任务已经执行完或正在被执行,则抛该exception - * @author wuweifeng wrote on 2020-02-18 - * @version 1.0 - */ -public class SkippedException extends RuntimeException { - public SkippedException() { - super(); - } - - public SkippedException(String message) { - super(message); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/Async.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/Async.java deleted file mode 100644 index bd6b3d16..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/Async.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.zmops.iot.async.executor; - - -import com.zmops.iot.async.callback.DefaultGroupCallback; -import com.zmops.iot.async.callback.IGroupCallback; -import com.zmops.iot.async.wrapper.WorkerWrapper; - -import java.util.*; -import java.util.concurrent.*; -import java.util.stream.Collectors; - -/** - * 类入口,可以根据自己情况调整core线程的数量 - * - * @author wuweifeng wrote on 2019-12-18 - * @version 1.0 - */ -public class Async { - /** - * 默认线程池 - */ - private static final ThreadPoolExecutor COMMON_POOL = - new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors() * 2, 1024, - 15L, TimeUnit.SECONDS, - new LinkedBlockingQueue<>(), - (ThreadFactory) Thread::new); - /** - * 注意,这里是个static,也就是只能有一个线程池。用户自定义线程池时,也只能定义一个 - */ - private static ExecutorService executorService; - - /** - * 出发点 - */ - public static boolean beginWork(long timeout, ExecutorService executorService, List workerWrappers) throws ExecutionException, InterruptedException { - if (workerWrappers == null || workerWrappers.size() == 0) { - return false; - } - //保存线程池变量 - Async.executorService = executorService; - //定义一个map,存放所有的wrapper,key为wrapper的唯一id,value是该wrapper,可以从value中获取wrapper的result - Map forParamUseWrappers = new ConcurrentHashMap<>(); - CompletableFuture[] futures = new CompletableFuture[workerWrappers.size()]; - for (int i = 0; i < workerWrappers.size(); i++) { - WorkerWrapper wrapper = workerWrappers.get(i); - futures[i] = CompletableFuture.runAsync(() -> wrapper.work(executorService, timeout, forParamUseWrappers), executorService); - } - try { - CompletableFuture.allOf(futures).get(timeout, TimeUnit.MILLISECONDS); - return true; - } catch (TimeoutException e) { - Set set = new HashSet<>(); - totalWorkers(workerWrappers, set); - for (WorkerWrapper wrapper : set) { - wrapper.stopNow(); - } - return false; - } - } - - /** - * 如果想自定义线程池,请传pool。不自定义的话,就走默认的COMMON_POOL - */ - public static boolean beginWork(long timeout, ExecutorService executorService, WorkerWrapper... workerWrapper) throws ExecutionException, InterruptedException { - if (workerWrapper == null || workerWrapper.length == 0) { - return false; - } - List workerWrappers = Arrays.stream(workerWrapper).collect(Collectors.toList()); - return beginWork(timeout, executorService, workerWrappers); - } - - /** - * 同步阻塞,直到所有都完成,或失败 - */ - public static boolean beginWork(long timeout, WorkerWrapper... workerWrapper) throws ExecutionException, InterruptedException { - return beginWork(timeout, COMMON_POOL, workerWrapper); - } - - public static void beginWorkAsync(long timeout, IGroupCallback groupCallback, WorkerWrapper... workerWrapper) { - beginWorkAsync(timeout, COMMON_POOL, groupCallback, workerWrapper); - } - - /** - * 异步执行,直到所有都完成,或失败后,发起回调 - */ - public static void beginWorkAsync(long timeout, ExecutorService executorService, IGroupCallback groupCallback, WorkerWrapper... workerWrapper) { - if (groupCallback == null) { - groupCallback = new DefaultGroupCallback(); - } - IGroupCallback finalGroupCallback = groupCallback; - if (executorService != null) { - executorService.submit(() -> { - try { - boolean success = beginWork(timeout, executorService, workerWrapper); - if (success) { - finalGroupCallback.success(Arrays.asList(workerWrapper)); - } else { - finalGroupCallback.failure(Arrays.asList(workerWrapper), new TimeoutException()); - } - } catch (ExecutionException | InterruptedException e) { - e.printStackTrace(); - finalGroupCallback.failure(Arrays.asList(workerWrapper), e); - } - }); - } else { - COMMON_POOL.submit(() -> { - try { - boolean success = beginWork(timeout, COMMON_POOL, workerWrapper); - if (success) { - finalGroupCallback.success(Arrays.asList(workerWrapper)); - } else { - finalGroupCallback.failure(Arrays.asList(workerWrapper), new TimeoutException()); - } - } catch (ExecutionException | InterruptedException e) { - e.printStackTrace(); - finalGroupCallback.failure(Arrays.asList(workerWrapper), e); - } - }); - } - - } - - /** - * total work units - */ - @SuppressWarnings("unchecked") - private static void totalWorkers(List workerWrappers, Set set) { - set.addAll(workerWrappers); - for (WorkerWrapper wrapper : workerWrappers) { - if (wrapper.getNextWrappers() == null) { - continue; - } - List wrappers = wrapper.getNextWrappers(); - totalWorkers(wrappers, set); - } - - } - - /** - * close thread pool - */ - public static void shutDown() { - shutDown(executorService); - } - - /** - * close thread pool - */ - public static void shutDown(ExecutorService executorService) { - if (executorService != null) { - executorService.shutdown(); - } else { - COMMON_POOL.shutdown(); - } - } - - public static String getThreadCount() { - return "activeCount=" + COMMON_POOL.getActiveCount() + - " completedCount " + COMMON_POOL.getCompletedTaskCount() + - " largestCount " + COMMON_POOL.getLargestPoolSize(); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/timer/SystemClock.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/timer/SystemClock.java deleted file mode 100644 index 36db5476..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/timer/SystemClock.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.zmops.iot.async.executor.timer; - -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -/** - * 用于解决高并发下System.currentTimeMillis卡顿 - * - * @author lry - */ -public class SystemClock { - - private final int period; - - private final AtomicLong now; - - private static class InstanceHolder { - private static final SystemClock INSTANCE = new SystemClock(1); - } - - private SystemClock(int period) { - this.period = period; - this.now = new AtomicLong(System.currentTimeMillis()); - scheduleClockUpdating(); - } - - private static SystemClock instance() { - return InstanceHolder.INSTANCE; - } - - private void scheduleClockUpdating() { - ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(runnable -> { - Thread thread = new Thread(runnable, "System Clock"); - thread.setDaemon(true); - return thread; - }); - scheduler.scheduleAtFixedRate(() -> now.set(System.currentTimeMillis()), period, period, TimeUnit.MILLISECONDS); - } - - private long currentTimeMillis() { - return now.get(); - } - - /** - * 用来替换原来的System.currentTimeMillis() - */ - public static long now() { - return instance().currentTimeMillis(); - } -} \ No newline at end of file diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/DependWrapper.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/DependWrapper.java deleted file mode 100644 index 1028c9a9..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/DependWrapper.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.zmops.iot.async.worker; - - -import com.zmops.iot.async.wrapper.WorkerWrapper; - -/** - * 对依赖的wrapper的封装 - * @author wuweifeng wrote on 2019-12-20 - * @version 1.0 - */ -public class DependWrapper { - private WorkerWrapper dependWrapper; - /** - * 是否该依赖必须完成后才能执行自己.

- * 因为存在一个任务,依赖于多个任务,是让这多个任务全部完成后才执行自己,还是某几个执行完毕就可以执行自己 - * 如 - * 1 - * ---3 - * 2 - * 或 - * 1---3 - * 2---3 - * 这两种就不一样,上面的就是必须12都完毕,才能3 - * 下面的就是1完毕就可以3 - */ - private boolean must = true; - - public DependWrapper(WorkerWrapper dependWrapper, boolean must) { - this.dependWrapper = dependWrapper; - this.must = must; - } - - public DependWrapper() { - } - - public WorkerWrapper getDependWrapper() { - return dependWrapper; - } - - public void setDependWrapper(WorkerWrapper dependWrapper) { - this.dependWrapper = dependWrapper; - } - - public boolean isMust() { - return must; - } - - public void setMust(boolean must) { - this.must = must; - } - - @Override - public String toString() { - return "DependWrapper{" + - "dependWrapper=" + dependWrapper + - ", must=" + must + - '}'; - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/ResultState.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/ResultState.java deleted file mode 100644 index 6d1b42e9..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/ResultState.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.zmops.iot.async.worker; - -/** - * 结果状态 - * @author wuweifeng wrote on 2019-11-19. - */ -public enum ResultState { - SUCCESS, - TIMEOUT, - EXCEPTION, - DEFAULT //默认状态 -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/WorkResult.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/WorkResult.java deleted file mode 100644 index ed557769..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/WorkResult.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.zmops.iot.async.worker; - -/** - * 执行结果 - */ -public class WorkResult { - /** - * 执行的结果 - */ - private V result; - /** - * 结果状态 - */ - private ResultState resultState; - private Exception ex; - - public WorkResult(V result, ResultState resultState) { - this(result, resultState, null); - } - - public WorkResult(V result, ResultState resultState, Exception ex) { - this.result = result; - this.resultState = resultState; - this.ex = ex; - } - - public static WorkResult defaultResult() { - return new WorkResult<>(null, ResultState.DEFAULT); - } - - @Override - public String toString() { - return "WorkResult{" + - "result=" + result + - ", resultState=" + resultState + - ", ex=" + ex + - '}'; - } - - public Exception getEx() { - return ex; - } - - public void setEx(Exception ex) { - this.ex = ex; - } - - public V getResult() { - return result; - } - - public void setResult(V result) { - this.result = result; - } - - public ResultState getResultState() { - return resultState; - } - - public void setResultState(ResultState resultState) { - this.resultState = resultState; - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapper.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapper.java deleted file mode 100644 index 2da373a5..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapper.java +++ /dev/null @@ -1,618 +0,0 @@ -package com.zmops.iot.async.wrapper; - -import com.zmops.iot.async.callback.DefaultCallback; -import com.zmops.iot.async.callback.ICallback; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.exception.SkippedException; -import com.zmops.iot.async.executor.timer.SystemClock; -import com.zmops.iot.async.worker.DependWrapper; -import com.zmops.iot.async.worker.ResultState; -import com.zmops.iot.async.worker.WorkResult; - -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * 对每个worker及callback进行包装,一对一 - * - * @author wuweifeng wrote on 2019-11-19. - */ -public class WorkerWrapper { - - /** - * 该wrapper的唯一标识 - */ - private final String id; - - /** - * worker将来要处理的param - */ - private T param; - private final IWorker worker; - private final ICallback callback; - - - /** - * 在自己后面的wrapper,如果没有,自己就是末尾;如果有一个,就是串行;如果有多个,有几个就需要开几个线程

- * -------2 - * 1 - * -------3 - * 如1后面有2、3 - */ - private List> nextWrappers; - - /** - * 依赖的wrappers,有2种情况,1:必须依赖的全部完成后,才能执行自己 2:依赖的任何一个、多个完成了,就可以执行自己 - * 通过must字段来控制是否依赖项必须完成 - * 1 - * -------3 - * 2 - * 1、2执行完毕后才能执行3 - */ - private List dependWrappers; - - /** - * 标记该事件是否已经被处理过了,譬如已经超时返回false了,后续rpc又收到返回值了,则不再二次回调 - * 经试验,volatile并不能保证"同一毫秒"内,多线程对该值的修改和拉取 - *

- * 1-finish, 2-error, 3-working - */ - private final AtomicInteger state = new AtomicInteger(0); - - /** - * 该map存放所有wrapper的id和wrapper映射 - */ - private Map forParamUseWrappers; - - /** - * 也是个钩子变量,用来存临时的结果 - */ - private volatile WorkResult workResult = WorkResult.defaultResult(); - - /** - * 是否在执行自己前,去校验nextWrapper的执行结果

- * 1 4 - * -------3 - * 2 - * 如这种在4执行前,可能3已经执行完毕了(被2执行完后触发的),那么4就没必要执行了。 - * 注意,该属性仅在nextWrapper数量<=1时有效,>1时的情况是不存在的 - */ - private volatile boolean needCheckNextWrapperResult = true; - - private static final int FINISH = 1; - private static final int ERROR = 2; - private static final int WORKING = 3; - private static final int INIT = 0; - - private WorkerWrapper(String id, IWorker worker, T param, ICallback callback) { - if (worker == null) { - throw new NullPointerException("async.worker is null"); - } - this.worker = worker; - this.param = param; - this.id = id; - //允许不设置回调 - if (callback == null) { - callback = new DefaultCallback<>(); - } - this.callback = callback; - } - - /** - * 开始工作 - * fromWrapper代表这次work是由哪个上游wrapper发起的 - */ - private void work(ExecutorService executorService, WorkerWrapper fromWrapper, long remainTime, Map forParamUseWrappers) { - this.forParamUseWrappers = forParamUseWrappers; - //将自己放到所有wrapper的集合里去 - forParamUseWrappers.put(id, this); - long now = SystemClock.now(); - //总的已经超时了,就快速失败,进行下一个 - if (remainTime <= 0) { - fastFail(INIT, null); - beginNext(executorService, now, remainTime); - return; - } - //如果自己已经执行过了。 - //可能有多个依赖,其中的一个依赖已经执行完了,并且自己也已开始执行或执行完毕。当另一个依赖执行完毕,又进来该方法时,就不重复处理了 - if (getState() == FINISH || getState() == ERROR) { - beginNext(executorService, now, remainTime); - return; - } - - //如果在执行前需要校验nextWrapper的状态 - if (needCheckNextWrapperResult) { - //如果自己的next链上有已经出结果或已经开始执行的任务了,自己就不用继续了 - if (!checkNextWrapperResult()) { - fastFail(INIT, new SkippedException()); - beginNext(executorService, now, remainTime); - return; - } - } - - //如果没有任何依赖,说明自己就是第一批要执行的 - if (dependWrappers == null || dependWrappers.size() == 0) { - fire(); - beginNext(executorService, now, remainTime); - return; - } - - /*如果有前方依赖,存在两种情况 - 一种是前面只有一个wrapper。即 A -> B - 一种是前面有多个wrapper。A C D -> B。需要A、C、D都完成了才能轮到B。但是无论是A执行完,还是C执行完,都会去唤醒B。 - 所以需要B来做判断,必须A、C、D都完成,自己才能执行 */ - - //只有一个依赖 - if (dependWrappers.size() == 1) { - doDependsOneJob(fromWrapper); - beginNext(executorService, now, remainTime); - } else { - //有多个依赖时 - doDependsJobs(executorService, dependWrappers, fromWrapper, now, remainTime); - } - - } - - - public void work(ExecutorService executorService, long remainTime, Map forParamUseWrappers) { - work(executorService, null, remainTime, forParamUseWrappers); - } - - /** - * 总控制台超时,停止所有任务 - */ - public void stopNow() { - if (getState() == INIT || getState() == WORKING) { - fastFail(getState(), null); - } - } - - /** - * 判断自己下游链路上,是否存在已经出结果的或已经开始执行的 - * 如果没有返回true,如果有返回false - */ - private boolean checkNextWrapperResult() { - //如果自己就是最后一个,或者后面有并行的多个,就返回true - if (nextWrappers == null || nextWrappers.size() != 1) { - return getState() == INIT; - } - WorkerWrapper nextWrapper = nextWrappers.get(0); - boolean state = nextWrapper.getState() == INIT; - //继续校验自己的next的状态 - return state && nextWrapper.checkNextWrapperResult(); - } - - /** - * 进行下一个任务 - */ - private void beginNext(ExecutorService executorService, long now, long remainTime) { - //花费的时间 - long costTime = SystemClock.now() - now; - if (nextWrappers == null) { - return; - } - if (nextWrappers.size() == 1) { - nextWrappers.get(0).work(executorService, WorkerWrapper.this, remainTime - costTime, forParamUseWrappers); - return; - } - CompletableFuture[] futures = new CompletableFuture[nextWrappers.size()]; - for (int i = 0; i < nextWrappers.size(); i++) { - int finalI = i; - futures[i] = CompletableFuture.runAsync(() -> nextWrappers.get(finalI) - .work(executorService, WorkerWrapper.this, remainTime - costTime, forParamUseWrappers), executorService); - } - try { - CompletableFuture.allOf(futures).get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - } - - private void doDependsOneJob(WorkerWrapper dependWrapper) { - if (ResultState.TIMEOUT == dependWrapper.getWorkResult().getResultState()) { - workResult = defaultResult(); - fastFail(INIT, null); - } else if (ResultState.EXCEPTION == dependWrapper.getWorkResult().getResultState()) { - workResult = defaultExResult(dependWrapper.getWorkResult().getEx()); - fastFail(INIT, null); - } else { - //前面任务正常完毕了,该自己了 - fire(); - } - } - - private synchronized void doDependsJobs(ExecutorService executorService, List dependWrappers, WorkerWrapper fromWrapper, long now, long remainTime) { - boolean nowDependIsMust = false; - //创建必须完成的上游wrapper集合 - Set mustWrapper = new HashSet<>(); - for (DependWrapper dependWrapper : dependWrappers) { - if (dependWrapper.isMust()) { - mustWrapper.add(dependWrapper); - } - if (dependWrapper.getDependWrapper().equals(fromWrapper)) { - nowDependIsMust = dependWrapper.isMust(); - } - } - - //如果全部是不必须的条件,那么只要到了这里,就执行自己。 - if (mustWrapper.size() == 0) { - if (ResultState.TIMEOUT == fromWrapper.getWorkResult().getResultState()) { - fastFail(INIT, null); - } else { - fire(); - } - beginNext(executorService, now, remainTime); - return; - } - - //如果存在需要必须完成的,且fromWrapper不是必须的,就什么也不干 - if (!nowDependIsMust) { - return; - } - - //如果fromWrapper是必须的 - boolean existNoFinish = false; - boolean hasError = false; - //先判断前面必须要执行的依赖任务的执行结果,如果有任何一个失败,那就不用走action了,直接给自己设置为失败,进行下一步就是了 - for (DependWrapper dependWrapper : mustWrapper) { - WorkerWrapper workerWrapper = dependWrapper.getDependWrapper(); - WorkResult tempWorkResult = workerWrapper.getWorkResult(); - //为null或者isWorking,说明它依赖的某个任务还没执行到或没执行完 - if (workerWrapper.getState() == INIT || workerWrapper.getState() == WORKING) { - existNoFinish = true; - break; - } - if (ResultState.TIMEOUT == tempWorkResult.getResultState()) { - workResult = defaultResult(); - hasError = true; - break; - } - if (ResultState.EXCEPTION == tempWorkResult.getResultState()) { - workResult = defaultExResult(workerWrapper.getWorkResult().getEx()); - hasError = true; - break; - } - - } - //只要有失败的 - if (hasError) { - fastFail(INIT, null); - beginNext(executorService, now, remainTime); - return; - } - - //如果上游都没有失败,分为两种情况,一种是都finish了,一种是有的在working - //都finish的话 - if (!existNoFinish) { - //上游都finish了,进行自己 - fire(); - beginNext(executorService, now, remainTime); - return; - } - } - - /** - * 执行自己的job.具体的执行是在另一个线程里,但判断阻塞超时是在work线程 - */ - private void fire() { - //阻塞取结果 - workResult = workerDoJob(); - } - - /** - * 快速失败 - */ - private boolean fastFail(int expect, Exception e) { - //试图将它从expect状态,改成Error - if (!compareAndSetState(expect, ERROR)) { - return false; - } - - //尚未处理过结果 - if (checkIsNullResult()) { - if (e == null) { - workResult = defaultResult(); - } else { - workResult = defaultExResult(e); - } - } - - callback.result(false, param, workResult); - return true; - } - - /** - * 具体的单个worker执行任务 - */ - private WorkResult workerDoJob() { - //避免重复执行 - if (!checkIsNullResult()) { - return workResult; - } - try { - //如果已经不是init状态了,说明正在被执行或已执行完毕。这一步很重要,可以保证任务不被重复执行 - if (!compareAndSetState(INIT, WORKING)) { - return workResult; - } - - callback.begin(); - - //执行耗时操作 - V resultValue = worker.action(param, forParamUseWrappers); - - //如果状态不是在working,说明别的地方已经修改了 - if (!compareAndSetState(WORKING, FINISH)) { - return workResult; - } - - workResult.setResultState(ResultState.SUCCESS); - workResult.setResult(resultValue); - //回调成功 - callback.result(true, param, workResult); - - return workResult; - } catch (Exception e) { - //避免重复回调 - if (!checkIsNullResult()) { - return workResult; - } - fastFail(WORKING, e); - return workResult; - } - } - - public WorkResult getWorkResult() { - return workResult; - } - - public List> getNextWrappers() { - return nextWrappers; - } - - public void setParam(T param) { - this.param = param; - } - - private boolean checkIsNullResult() { - return ResultState.DEFAULT == workResult.getResultState(); - } - - private void addDepend(WorkerWrapper workerWrapper, boolean must) { - addDepend(new DependWrapper(workerWrapper, must)); - } - - private void addDepend(DependWrapper dependWrapper) { - if (dependWrappers == null) { - dependWrappers = new ArrayList<>(); - } - //如果依赖的是重复的同一个,就不重复添加了 - for (DependWrapper wrapper : dependWrappers) { - if (wrapper.equals(dependWrapper)) { - return; - } - } - dependWrappers.add(dependWrapper); - } - - private void addNext(WorkerWrapper workerWrapper) { - if (nextWrappers == null) { - nextWrappers = new ArrayList<>(); - } - //避免添加重复 - for (WorkerWrapper wrapper : nextWrappers) { - if (workerWrapper.equals(wrapper)) { - return; - } - } - nextWrappers.add(workerWrapper); - } - - private void addNextWrappers(List> wrappers) { - if (wrappers == null) { - return; - } - for (WorkerWrapper wrapper : wrappers) { - addNext(wrapper); - } - } - - private void addDependWrappers(List dependWrappers) { - if (dependWrappers == null) { - return; - } - for (DependWrapper wrapper : dependWrappers) { - addDepend(wrapper); - } - } - - private WorkResult defaultResult() { - workResult.setResultState(ResultState.TIMEOUT); - workResult.setResult(worker.defaultValue()); - return workResult; - } - - private WorkResult defaultExResult(Exception ex) { - workResult.setResultState(ResultState.EXCEPTION); - workResult.setResult(worker.defaultValue()); - workResult.setEx(ex); - return workResult; - } - - - private int getState() { - return state.get(); - } - - public String getId() { - return id; - } - - private boolean compareAndSetState(int expect, int update) { - return this.state.compareAndSet(expect, update); - } - - private void setNeedCheckNextWrapperResult(boolean needCheckNextWrapperResult) { - this.needCheckNextWrapperResult = needCheckNextWrapperResult; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - WorkerWrapper that = (WorkerWrapper) o; - return needCheckNextWrapperResult == that.needCheckNextWrapperResult && - Objects.equals(param, that.param) && - Objects.equals(worker, that.worker) && - Objects.equals(callback, that.callback) && - Objects.equals(nextWrappers, that.nextWrappers) && - Objects.equals(dependWrappers, that.dependWrappers) && - Objects.equals(state, that.state) && - Objects.equals(workResult, that.workResult); - } - - @Override - public int hashCode() { - return Objects.hash(param, worker, callback, nextWrappers, dependWrappers, state, workResult, needCheckNextWrapperResult); - } - - public static class Builder { - /** - * 该wrapper的唯一标识 - */ - private String id = UUID.randomUUID().toString(); - /** - * worker将来要处理的param - */ - private W param; - private IWorker worker; - private ICallback callback; - /** - * 自己后面的所有 - */ - private List> nextWrappers; - /** - * 自己依赖的所有 - */ - private List dependWrappers; - /** - * 存储强依赖于自己的wrapper集合 - */ - private Set> selfIsMustSet; - - private boolean needCheckNextWrapperResult = true; - - public Builder worker(IWorker worker) { - this.worker = worker; - return this; - } - - public Builder param(W w) { - this.param = w; - return this; - } - - public Builder id(String id) { - if (id != null) { - this.id = id; - } - return this; - } - - public Builder needCheckNextWrapperResult(boolean needCheckNextWrapperResult) { - this.needCheckNextWrapperResult = needCheckNextWrapperResult; - return this; - } - - public Builder callback(ICallback callback) { - this.callback = callback; - return this; - } - - public Builder depend(WorkerWrapper... wrappers) { - if (wrappers == null) { - return this; - } - for (WorkerWrapper wrapper : wrappers) { - depend(wrapper); - } - return this; - } - - public Builder depend(WorkerWrapper wrapper) { - return depend(wrapper, true); - } - - public Builder depend(WorkerWrapper wrapper, boolean isMust) { - if (wrapper == null) { - return this; - } - DependWrapper dependWrapper = new DependWrapper(wrapper, isMust); - if (dependWrappers == null) { - dependWrappers = new ArrayList<>(); - } - dependWrappers.add(dependWrapper); - return this; - } - - public Builder next(WorkerWrapper wrapper) { - return next(wrapper, true); - } - - public Builder next(WorkerWrapper wrapper, boolean selfIsMust) { - if (nextWrappers == null) { - nextWrappers = new ArrayList<>(); - } - nextWrappers.add(wrapper); - - //强依赖自己 - if (selfIsMust) { - if (selfIsMustSet == null) { - selfIsMustSet = new HashSet<>(); - } - selfIsMustSet.add(wrapper); - } - return this; - } - - public Builder next(WorkerWrapper... wrappers) { - if (wrappers == null) { - return this; - } - for (WorkerWrapper wrapper : wrappers) { - next(wrapper); - } - return this; - } - - public WorkerWrapper build() { - WorkerWrapper wrapper = new WorkerWrapper<>(id, worker, param, callback); - wrapper.setNeedCheckNextWrapperResult(needCheckNextWrapperResult); - if (dependWrappers != null) { - for (DependWrapper workerWrapper : dependWrappers) { - workerWrapper.getDependWrapper().addNext(wrapper); - wrapper.addDepend(workerWrapper); - } - } - if (nextWrappers != null) { - for (WorkerWrapper workerWrapper : nextWrappers) { - boolean must = false; - if (selfIsMustSet != null && selfIsMustSet.contains(workerWrapper)) { - must = true; - } - workerWrapper.addDepend(wrapper, must); - wrapper.addNext(workerWrapper); - } - } - - return wrapper; - } - - } -} diff --git a/zeus-application-toolkit/toolkit-eventbus/pom.xml b/zeus-application-toolkit/toolkit-eventbus/pom.xml deleted file mode 100644 index 2c2fcb98..00000000 --- a/zeus-application-toolkit/toolkit-eventbus/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - zeus-application-toolkit - com.zmops - 1.0-beta - - 4.0.0 - - toolkit-eventbus - - - 8 - 8 - - - \ No newline at end of file diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index f9b4e0a3..1bcfd9a8 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -50,11 +50,6 @@ zeus-message ${project.version} - - org.apache.camel - camel-http-starter - 2.25.4 - org.apache.camel camel-pgevent diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index 35b4e46b..1b7ba894 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -48,7 +48,7 @@ forest: zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:80} zbxApiUrl: ${ZEUS_ZABBIX_API_URL:/zabbix/api_jsonrpc.php} - zbxApiToken: 28345fb4147761a6e955e7c3aada52fe032678fe8360f131f5acc7a25b8af755 + zbxApiToken: da839aa4f6ce3c45e331a92571d9c2a0d435f4b8f7aa5f5edff92ccf633ee568 ## tdengine http request address taosUrl: http://${ZEUS_TAOS_HOST:127.0.0.1}:${ZEUS_TAOS_REST_PORT:6041}/rest/sql/zeus_data diff --git a/zeus-webapp/pom.xml b/zeus-webapp/pom.xml index e51dbd6a..69faa674 100644 --- a/zeus-webapp/pom.xml +++ b/zeus-webapp/pom.xml @@ -35,7 +35,7 @@ com.zmops toolkit-async - 1.0-beta + 1.0-SNAPSHOT commons-httpclient diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java index ad972444..d1265b7d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java @@ -1,8 +1,8 @@ package com.zmops.iot.web.device.service; -import com.zmops.iot.async.callback.ICallback; -import com.zmops.iot.async.executor.Async; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.ICallback; +import com.zmops.zeus.server.async.executor.Async; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.EventTriggerRecord; import com.zmops.iot.domain.device.ScenesTriggerRecord; import com.zmops.iot.domain.device.ServiceExecuteRecord; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 8708ac41..087bc8b0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -2,9 +2,9 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.async.callback.ICallback; -import com.zmops.iot.async.executor.Async; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.ICallback; +import com.zmops.zeus.server.async.executor.Async; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.Tag; import com.zmops.iot.domain.device.query.QDevice; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceEventLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceEventLogWorker.java index adcffb48..01624ad5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceEventLogWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceEventLogWorker.java @@ -1,8 +1,8 @@ package com.zmops.iot.web.device.service.work; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.util.ToolUtil; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java index de6e9337..d1a9359b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java @@ -2,8 +2,8 @@ import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.ServiceExecuteRecord; import com.zmops.iot.domain.product.ProductEventService; import com.zmops.iot.domain.product.ProductService; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java index 597aa6b2..16765acd 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java @@ -2,9 +2,8 @@ import cn.hutool.core.util.IdUtil; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.device.Device; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.domain.product.query.QProductAttribute; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java index bb272df3..98635a77 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java @@ -1,9 +1,8 @@ package com.zmops.iot.web.device.service.work; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.device.Device; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.DevicesGroups; import com.zmops.iot.domain.device.query.QDevicesGroups; import com.zmops.iot.web.device.dto.DeviceDto; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java index c42b11d3..9b647e7d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java @@ -1,8 +1,8 @@ package com.zmops.iot.web.device.service.work; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.Device; import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.util.ToolUtil; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java index 68602dc6..26332f57 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java @@ -2,9 +2,8 @@ import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.device.Device; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductEventRelation; import com.zmops.iot.domain.product.ProductStatusFunctionRelation; import com.zmops.iot.domain.product.query.*; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java index 35d76dc2..2dc5dc8e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java @@ -1,9 +1,8 @@ package com.zmops.iot.web.device.service.work; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.device.Device; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.query.QTag; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java index ab6b2ede..1937e2b1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java @@ -1,10 +1,9 @@ package com.zmops.iot.web.device.service.work; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.constant.ConstantsContext; -import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.query.QDeviceGroup; import com.zmops.iot.domain.product.query.QProduct; import com.zmops.iot.util.ToolUtil; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java index 3b17c776..8943f105 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java @@ -1,8 +1,8 @@ package com.zmops.iot.web.device.service.work; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.ScenesTriggerRecord; import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.query.QProductEvent; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java index 647f1dae..288bc951 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java @@ -3,9 +3,8 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.device.Device; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.domain.product.query.QProductAttribute; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java index ca4f8d34..dc7e4892 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java @@ -3,8 +3,8 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.Device; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java index 490c3429..17709fa2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java @@ -3,8 +3,8 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.Tag; import com.zmops.iot.domain.device.query.QTag; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/ServiceEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/ServiceEventProcess.java index 3868e88d..30802fee 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/ServiceEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/ServiceEventProcess.java @@ -2,8 +2,8 @@ import com.alibaba.fastjson.JSON; import com.dtflys.forest.Forest; -import com.zmops.iot.async.executor.Async; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.executor.Async; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductEventRelation; import com.zmops.iot.domain.product.ProductEventService; import com.zmops.iot.domain.product.ProductServiceParam; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index a87a88e2..0f508684 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -2,8 +2,8 @@ import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.async.executor.Async; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.executor.Async; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.ProductEventRelation; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java index dc9fdf33..96402087 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -2,14 +2,13 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.async.executor.Async; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.executor.Async; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.Product; import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.domain.product.query.QProduct; -import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.domain.product.query.QProductAttributeEvent; import com.zmops.iot.domain.product.query.QProductEventExpression; import com.zmops.iot.model.exception.ServiceException; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index 2170f41b..ea5e8221 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -2,8 +2,8 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.async.executor.Async; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.executor.Async; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.Product; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProduct; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index 32ca0146..90c995a3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -1,7 +1,7 @@ package com.zmops.iot.web.product.service; -import com.zmops.iot.async.executor.Async; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.executor.Async; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductService; import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.product.ProductServiceRelation; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java index ee24b0e7..db2040e5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java @@ -2,8 +2,8 @@ import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.domain.product.query.QProductAttributeEvent; import com.zmops.iot.util.ToolUtil; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java index 34bfff5a..a67dba3e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java @@ -2,8 +2,8 @@ import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.util.ToolUtil; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java index 547db7b8..ac2198e0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java @@ -2,8 +2,8 @@ import com.alibaba.fastjson.JSON; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.zeus.driver.service.ZbxTrigger; import lombok.Data; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java index 32feffbf..3a2e56d0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java @@ -2,8 +2,8 @@ import cn.hutool.core.util.IdUtil; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.util.ToolUtil; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java index 7c5a5626..3045a94c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java @@ -2,8 +2,8 @@ import cn.hutool.core.util.IdUtil; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.util.ToolUtil; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java index 4cefb599..5ebefe32 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java @@ -1,8 +1,8 @@ package com.zmops.iot.web.product.service.work; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductStatusFunctionRelation; import com.zmops.iot.web.product.dto.ProductServiceDto; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java index ff2acfb9..c8bd02ed 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java @@ -1,8 +1,8 @@ package com.zmops.iot.web.product.service.work; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.product.ProductServiceRelation; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java index f0da993e..0c01cbfe 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java @@ -2,8 +2,8 @@ import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductEventRelation; import com.zmops.iot.domain.product.ProductEventService; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java index c1f11084..8b72dfe1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java @@ -1,8 +1,8 @@ package com.zmops.iot.web.product.service.work; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.domain.product.query.QProductAttributeEvent; import com.zmops.iot.web.product.dto.ProductAttr; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java index c24df591..57cf5ffc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java @@ -1,8 +1,8 @@ package com.zmops.iot.web.product.service.work; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.web.product.dto.ProductAttr; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java index ee540f78..adb0787c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java @@ -1,11 +1,10 @@ package com.zmops.iot.web.product.service.work; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductServiceParam; -import com.zmops.iot.domain.product.query.QProductServiceParam; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.product.dto.ProductServiceDto; import io.ebean.DB; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java index 887cf937..70c1b110 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java @@ -1,8 +1,8 @@ package com.zmops.iot.web.product.service.work; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductEventService; import com.zmops.iot.web.product.dto.ProductEventRule; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/task/dto/TaskDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/task/dto/TaskDto.java index ed74cda3..faa36249 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/task/dto/TaskDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/task/dto/TaskDto.java @@ -30,9 +30,9 @@ public class TaskDto { @CachedValue(value = "STATUS") private String triggerStatus = "ENABLE"; - private Long triggerLastTime=0L; + private Long triggerLastTime = 0L; - private Long triggerNextTime=0L; + private Long triggerNextTime = 0L; private String remark; From 5408afe4b192fd4aa7483170726aad423b9bc744 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 24 Nov 2021 11:06:30 +0800 Subject: [PATCH 686/763] [fix]: validate device id --- dist-material/bin/sql/zabbix_event.sql | 5 +++++ .../src/main/java/com/zmops/iot/util/ToolUtil.java | 8 +++++--- .../zmops/iot/web/device/controller/DeviceController.java | 8 ++++---- .../zmops/iot/web/exception/enums/BizExceptionEnum.java | 2 +- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/dist-material/bin/sql/zabbix_event.sql b/dist-material/bin/sql/zabbix_event.sql index 072aa7d7..f7c3c539 100644 --- a/dist-material/bin/sql/zabbix_event.sql +++ b/dist-material/bin/sql/zabbix_event.sql @@ -102,3 +102,8 @@ EXECUTE PROCEDURE "public"."events_trace"(); CREATE TRIGGER "events_problem_trigger" AFTER INSERT OR UPDATE OF "r_clock", "acknowledged" ON "public"."problem" FOR EACH ROW EXECUTE PROCEDURE "public"."events_problem_trace"(); + + +CREATE TRIGGER "tag_trigger" AFTER INSERT ON "public"."event_tag" +FOR EACH ROW +EXECUTE PROCEDURE "public"."events_tag_trace"(); \ No newline at end of file diff --git a/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java b/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java index a518b506..b36668c2 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java @@ -8,7 +8,6 @@ import org.apache.logging.log4j.core.util.CronExpression; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.BeanUtils; import org.springframework.core.env.Environment; import java.io.IOException; @@ -439,13 +438,16 @@ public static List convertBean(List oriList, Class castClas return resList; } - public static boolean validCron(String cron){ + public static boolean validCron(String cron) { //String regEx = "(((^([0-9]|[0-5][0-9])(\\,|\\-|\\/){1}([0-9]|[0-5][0-9]))|^([0-9]|[0-5][0-9])|^(\\* ))((([0-9]|[0-5][0-9])(\\,|\\-|\\/){1}([0-9]|[0-5][0-9]) )|([0-9]|[0-5][0-9]) |(\\* ))((([0-9]|[01][0-9]|2[0-3])(\\,|\\-|\\/){1}([0-9]|[01][0-9]|2[0-3]) )|([0-9]|[01][0-9]|2[0-3]) |(\\* ))((([0-9]|[0-2][0-9]|3[01])(\\,|\\-|\\/){1}([0-9]|[0-2][0-9]|3[01]) )|(([0-9]|[0-2][0-9]|3[01]) )|(\\? )|(\\* )|(([1-9]|[0-2][0-9]|3[01])L )|([1-7]W )|(LW )|([1-7]\\#[1-4] ))((([1-9]|0[1-9]|1[0-2])(\\,|\\-|\\/){1}([1-9]|0[1-9]|1[0-2]) )|([1-9]|0[1-9]|1[0-2]) |(\\* ))(([1-7](\\,|\\-|\\/){1}[1-7])|([1-7])|(\\?)|(\\*)|(([1-7]L)|([1-7]\\#[1-4]))))|(((^([0-9]|[0-5][0-9])(\\,|\\-|\\/){1}([0-9]|[0-5][0-9]) )|^([0-9]|[0-5][0-9]) |^(\\* ))((([0-9]|[0-5][0-9])(\\,|\\-|\\/){1}([0-9]|[0-5][0-9]) )|([0-9]|[0-5][0-9]) |(\\* ))((([0-9]|[01][0-9]|2[0-3])(\\,|\\-|\\/){1}([0-9]|[01][0-9]|2[0-3]) )|([0-9]|[01][0-9]|2[0-3]) |(\\* ))((([0-9]|[0-2][0-9]|3[01])(\\,|\\-|\\/){1}([0-9]|[0-2][0-9]|3[01]) )|(([0-9]|[0-2][0-9]|3[01]) )|(\\? )|(\\* )|(([1-9]|[0-2][0-9]|3[01])L )|([1-7]W )|(LW )|([1-7]\\#[1-4] ))((([1-9]|0[1-9]|1[0-2])(\\,|\\-|\\/){1}([1-9]|0[1-9]|1[0-2]) )|([1-9]|0[1-9]|1[0-2]) |(\\* ))(([1-7](\\,|\\-|\\/){1}[1-7] )|([1-7] )|(\\? )|(\\* )|(([1-7]L )|([1-7]\\#[1-4]) ))((19[789][0-9]|20[0-9][0-9])\\-(19[789][0-9]|20[0-9][0-9])))"; //String tests = "0 0 0 L * ?"; return CronExpression.isValidExpression(cron); } - public static boolean validDeviceName(String content){ + public static boolean validDeviceId(String content) { + if (isEmpty(content)) { + return true; + } return content.contains("\\") || content.contains("/"); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java index d78095f5..5ef64139 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java @@ -63,8 +63,8 @@ public ResponseData deviceList(@RequestBody DeviceParams deviceParams) { @Permission(code = "dev_add") @RequestMapping("/create") public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody DeviceDto deviceDto) { - if (ToolUtil.validDeviceName(deviceDto.getName())) { - throw new ServiceException(BizExceptionEnum.DEVICE_NAME_HAS_INCOREECT_CHARACTER); + if (ToolUtil.validDeviceId(deviceDto.getDeviceId())) { + throw new ServiceException(BizExceptionEnum.DEVICE_ID_HAS_INCORRECT_CHARACTER); } int count = new QDevice().name.eq(deviceDto.getName()).findCount(); if (count > 0) { @@ -92,8 +92,8 @@ public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody Devi @Permission(code = "dev_update") @RequestMapping("/update") public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody DeviceDto deviceDto) { - if (ToolUtil.validDeviceName(deviceDto.getName())) { - throw new ServiceException(BizExceptionEnum.DEVICE_NAME_HAS_INCOREECT_CHARACTER); + if (ToolUtil.validDeviceId(deviceDto.getName())) { + throw new ServiceException(BizExceptionEnum.DEVICE_ID_HAS_INCORRECT_CHARACTER); } int count = new QDevice().deviceId.ne(deviceDto.getDeviceId()).name.eq(deviceDto.getName()).findCount(); if (count > 0) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index 921066c3..77a0debb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -153,7 +153,7 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { DEVICE_EXISTS(1501, "设备名称已存在"), DEVICE_ID_EXISTS(1503, "设备ID已存在"), DEVICE_NOT_EXISTS(1502, "设备不存在"), - DEVICE_NAME_HAS_INCOREECT_CHARACTER(1504,"设备名称不能包含\\或\\/字符"), + DEVICE_ID_HAS_INCORRECT_CHARACTER(1504,"设备ID不能包含\\或\\/字符"), /** * 服务相关 From 75701fffbc0c8987efc95ae73e57987fc4f9d2ad Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 24 Nov 2021 11:53:02 +0800 Subject: [PATCH 687/763] [fix]:fix alarm message --- .../zmops/iot/web/alarm/service/AlarmService.java | 3 ++- .../event/pgEvent/service/AlarmEventProcess.java | 14 ++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index f05cd4d4..1d47bc8a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -48,6 +48,7 @@ public class AlarmService { public void alarm(Map alarmInfo) { List deviceIds = (List) alarmInfo.get("hostname"); String eventRuleId = (String) alarmInfo.get("triggerName"); + String title = (String) alarmInfo.get("title"); if (ToolUtil.isEmpty(deviceIds) || ToolUtil.isEmpty(eventRuleId)) { return; @@ -60,7 +61,7 @@ public void alarm(Map alarmInfo) { if (ToolUtil.isNotEmpty(deviceList) && null != productEvent) { String deviceName = deviceList.parallelStream().map(Device::getName).collect(Collectors.joining(",")); - String alarmmessage = "设备:" + deviceName + "发生告警,告警内容:" + productEvent.getEventRuleName(); + String alarmmessage = "设备:" + deviceName +" "+ title + ",告警内容:" + productEvent.getEventRuleName(); alarmMessages.add(AlarmMessage.builder().alarmMessage(alarmmessage).build()); alarmCallbacks.forEach(alarmCallback -> { alarmCallback.doAlarm(alarmMessages); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/AlarmEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/AlarmEventProcess.java index d54def40..d2d1fc75 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/AlarmEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/AlarmEventProcess.java @@ -56,6 +56,7 @@ public void process(EventDataDto eventData) { log.debug("--------alarm event----------{}", triggerId); //step 1:插入problem + String title = "告警触发:"; Problem problem = new Problem(); problem.setEventId(Long.parseLong(eventData.getEventid())); problem.setObjectId(Long.parseLong(eventData.getObjectid())); @@ -69,6 +70,10 @@ public void process(EventDataDto eventData) { DB.insert(problem); } else { DB.update(problem); + if (problem.getRClock() == null) { + return; + } + title = "告警恢复:"; } //step 2:找出需要通知的用户ID 推送通知 @@ -78,6 +83,7 @@ public void process(EventDataDto eventData) { } Map params = new ConcurrentHashMap<>(2); params.put("hostname", deviceIds); + params.put("title", title); params.put("triggerName", triggerName); String sql = "select user_group_id from sys_usrgrp_devicegrp where device_group_id in (select device_group_id from devices_groups where device_id in (:deviceIds))"; @@ -96,7 +102,7 @@ public void process(EventDataDto eventData) { //发送Email消息 ProductEvent productEvent = new QProductEvent().eventRuleId.eq(Long.parseLong(triggerName)).findOne(); Map macros = createMacroMap(triggerId, eventData.getRClock() + "", eventData.getAcknowledged() + "", productEvent); - messageService.push(buildMessage(macros, userIds)); + messageService.push(buildMessage(macros, userIds, title)); List noticeRecords = new ArrayList<>(); sysUserList.forEach(sysUser -> { @@ -126,15 +132,15 @@ private Map createMacroMap(String triggerId, String rclock, Stri macroMap.put("${severity}", productEvent.getEventLevel()); macroMap.put("${metricName}", productEvent.getEventRuleName()); macroMap.put("${context}", productEvent.getEventRuleName()); - macroMap.put("${alarmStatus}", isnew ? "告警触发" : "撤销告警"); + macroMap.put("${alarmStatus}", isnew ? "告警触发" : "告警恢复"); macroMap.put("${confirmStatus}", "1".equals(acknowledged) ? "已确认" : "未确认"); macroMap.put("${problemId}", triggerId); return macroMap; } - private MessageBody buildMessage(Map alarmInfo, List userIds) { + private MessageBody buildMessage(Map alarmInfo, List userIds, String title) { Map params = new HashMap<>(alarmInfo); - return MessageBody.builder().msg("发生告警:" + alarmInfo.get("${metricName}")).persist(true).to(userIds).body(params).build(); + return MessageBody.builder().msg(title + alarmInfo.get("${metricName}")).persist(true).to(userIds).body(params).build(); } From f3c762fbd0c2225003e8908584e86aa0de4e0e34 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 24 Nov 2021 15:52:27 +0800 Subject: [PATCH 688/763] [fix]: fix userGroup bind deviceGroup --- .../iot/web/sys/service/SysUserGroupService.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java index d378eafa..dfc264aa 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java @@ -123,9 +123,7 @@ public SysUserGroup updateUserGroup(UserGroupDto userGroup) { BeanUtils.copyProperties(userGroup, newUserGroup); DB.update(newUserGroup); - if (ToolUtil.isNotEmpty(userGroup.getDeviceGroupIds())) { - bindHostGrp(UserGroupParam.builder().userGroupId(userGroup.getUserGroupId()).deviceGroupIds(userGroup.getDeviceGroupIds()).build()); - } + bindHostGrp(UserGroupParam.builder().userGroupId(userGroup.getUserGroupId()).deviceGroupIds(userGroup.getDeviceGroupIds()).build()); return newUserGroup; } @@ -195,11 +193,12 @@ public String getZabUsrGrpId(Long usrGrpId) { * @param userGroup */ public void bindHostGrp(UserGroupParam userGroup) { - //修改ZBX 用户组绑定主机组 - String usrGrpZbxId = getZabUsrGrpId(userGroup.getUserGroupId()); - List list = new QDeviceGroup().deviceGroupId.in(userGroup.getDeviceGroupIds()).findList(); - List hostGrpZbxIds = list.parallelStream().map(DeviceGroup::getZbxId).collect(Collectors.toList()); - zbxUserGroup.userGrpBindHostGroup(hostGrpZbxIds, usrGrpZbxId); + new QSysUserGrpDevGrp().userGroupId.eq(userGroup.getUserGroupId()).delete(); + + if (ToolUtil.isNotEmpty(userGroup.getDeviceGroupIds())) { + return; + } + List lists = new ArrayList<>(); for (Long deviceGroupId : userGroup.getDeviceGroupIds()) { SysUserGrpDevGrp devicesGroups = new SysUserGrpDevGrp(); From 28d345a950c0970a0e089c400637ddb1a3a07171 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 24 Nov 2021 16:43:01 +0800 Subject: [PATCH 689/763] [feat]: just for code format --- .../iot/server/starter/config/ApplicationConfigLoader.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java index cd1ff672..62676bda 100644 --- a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java +++ b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java @@ -19,14 +19,12 @@ package com.zmops.zeus.iot.server.starter.config; - -import com.zmops.zeus.server.util.PropertyPlaceholderHelper; import com.zmops.zeus.server.library.module.ApplicationConfiguration; import com.zmops.zeus.server.library.module.ProviderNotFoundException; import com.zmops.zeus.server.library.util.CollectionUtils; import com.zmops.zeus.server.library.util.ResourceUtils; +import com.zmops.zeus.server.util.PropertyPlaceholderHelper; import lombok.extern.slf4j.Slf4j; - import org.yaml.snakeyaml.Yaml; import java.io.FileNotFoundException; @@ -62,7 +60,6 @@ public ApplicationConfiguration load() throws ConfigFileNotFoundException { private void loadConfig(ApplicationConfiguration configuration) throws ConfigFileNotFoundException { try { Reader applicationReader = ResourceUtils.read("application.yml"); - Map> moduleConfig = yaml.loadAs(applicationReader, Map.class); if (CollectionUtils.isNotEmpty(moduleConfig)) { From a8a6715d05e11e76885eb4720d487dd405652b53 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 24 Nov 2021 18:52:19 +0800 Subject: [PATCH 690/763] [fix]: code format --- .../src/main/resources/application.yml | 2 +- .../src/main/resources/application.yaml | 2 +- .../controller/SelfMonitorController.java | 36 +++++++++++ .../iot/web/analyse/enums/CpuLoadEnum.java | 35 ++++++++++ .../analyse/service/SelfMonitorService.java | 64 +++++++++++++++++++ .../ProductEventTriggerController.java | 6 +- .../service/ProductAttributeEventService.java | 4 +- .../service/ProductEventRuleService.java | 5 +- .../product/service/ProductModelService.java | 4 +- .../product/service/ProductSvcService.java | 5 +- .../work/AsyncAttrEventZbxIdWorker.java | 4 +- .../service/work/AsyncAttrZbxIdWorker.java | 4 +- .../work/SaveProdAttrEventTriggerWorker.java | 10 +-- .../service/work/SaveProdAttrEventWorker.java | 4 +- .../service/work/SaveProdAttrWorker.java | 4 +- .../work/SaveProdStatusTriggerWorker.java | 4 +- .../service/work/SaveProdSvcWorker.java | 6 +- .../work/SaveProductEventTriggerWorker.java | 4 +- .../work/UpdateAttributeEventWorker.java | 4 +- .../service/work/UpdateAttributeWorker.java | 4 +- .../service/work/UpdateProdSvcWorker.java | 4 +- .../work/UpdateProductEventTriggerWorker.java | 4 +- .../web/sys/controller/DictController.java | 2 - 23 files changed, 177 insertions(+), 44 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/SelfMonitorController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/CpuLoadEnum.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/SelfMonitorService.java diff --git a/iot-server/server-bootstrap/src/main/resources/application.yml b/iot-server/server-bootstrap/src/main/resources/application.yml index 529e79ed..3d35cd90 100644 --- a/iot-server/server-bootstrap/src/main/resources/application.yml +++ b/iot-server/server-bootstrap/src/main/resources/application.yml @@ -8,7 +8,7 @@ camel-receiver: zabbix-sender: selector: ${ZS_RECEIVER_ZABBIX_SENDER:default} default: - port: ${ZS_RECEIVER_ZABBIX_POST:10051} + port: ${ZS_RECEIVER_ZABBIX_PORT:10051} host: ${ZS_RECEIVER_ZABBIX_HOST:127.0.0.1} # core module config diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index 1b7ba894..568cfda8 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -48,7 +48,7 @@ forest: zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:80} zbxApiUrl: ${ZEUS_ZABBIX_API_URL:/zabbix/api_jsonrpc.php} - zbxApiToken: da839aa4f6ce3c45e331a92571d9c2a0d435f4b8f7aa5f5edff92ccf633ee568 + zbxApiToken: 479bcb20ab773c8b85f78a710fd56eca80aaec03c2337ad59263d568b0e9f938 ## tdengine http request address taosUrl: http://${ZEUS_TAOS_HOST:127.0.0.1}:${ZEUS_TAOS_REST_PORT:6041}/rest/sql/zeus_data diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/SelfMonitorController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/SelfMonitorController.java new file mode 100644 index 00000000..d7ac9be5 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/SelfMonitorController.java @@ -0,0 +1,36 @@ +package com.zmops.iot.web.analyse.controller; + +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.analyse.service.SelfMonitorService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + * 自监控 + **/ +@RestController +@RequestMapping("/monitor/self") +public class SelfMonitorController { + + @Autowired + SelfMonitorService selfMonitorService; + + @RequestMapping("memory") + public ResponseData getMemInfo(){ + return ResponseData.success(selfMonitorService.getMemInfo()); + } + + @RequestMapping("cpu") + public ResponseData getCpuInfo(){ + return ResponseData.success(selfMonitorService.getCpuInfo()); + } + + @RequestMapping("process") + public ResponseData getProcessInfo(){ + return ResponseData.success(selfMonitorService.getProcessInfo()); + } + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/CpuLoadEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/CpuLoadEnum.java new file mode 100644 index 00000000..77635e64 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/CpuLoadEnum.java @@ -0,0 +1,35 @@ +package com.zmops.iot.web.analyse.enums; + +import lombok.Getter; + +/** + * @author yefei + **/ +public enum CpuLoadEnum { + avg1("system.cpu.load[all,avg1]", "avg1"), + avg5("system.cpu.load[all,avg5]", "avg5"), + avg15("system.cpu.load[all,avg15]", "avg15"); + + @Getter + String code; + @Getter + String message; + + CpuLoadEnum(String code, String message) { + this.code = code; + this.message = message; + } + + public static String getDescription(String status) { + if (status == null) { + return ""; + } else { + for (CpuLoadEnum s : CpuLoadEnum.values()) { + if (s.getCode().equals(status)) { + return s.getMessage(); + } + } + return ""; + } + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/SelfMonitorService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/SelfMonitorService.java new file mode 100644 index 00000000..1d1a1cd2 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/SelfMonitorService.java @@ -0,0 +1,64 @@ +package com.zmops.iot.web.analyse.service; + +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.analyse.enums.CpuLoadEnum; +import com.zmops.zeus.driver.service.ZbxHistoryGet; +import com.zmops.zeus.driver.service.ZbxHost; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author yefei + **/ +@Service +public class SelfMonitorService { + + @Autowired + ZbxHistoryGet zbxHistoryGet; + + @Autowired + ZbxHost zbxHost; + + private static Map> itemMap = new HashMap<>(); + + private static Map hostIdMap = new HashMap<>(); + + public Map getMemInfo() { + return null; + } + + public Map getCpuInfo() { + List itemIds = itemMap.get("cpu"); + if (ToolUtil.isEmpty(itemIds)) { + itemIds = getItemIdByNames(Arrays.asList(CpuLoadEnum.avg1.getCode(), CpuLoadEnum.avg5.getCode(), CpuLoadEnum.avg15.getCode())); + itemMap.put("cpu", itemIds); + } + String hostId = hostIdMap.get("Zabbix server"); + if (ToolUtil.isEmpty(hostId)) { + hostId = getHostIdByName("Zabbix server"); + } + String res = zbxHistoryGet.historyGet(hostId, itemIds, itemIds.size(), 0, null, null); + return null; + } + + private String getHostIdByName(String host) { + String s = zbxHost.hostGet(host); + return ""; + } + + public String getProcessInfo() { + return ""; + } + + private List getItemIdByNames(List names) { + return null; + } + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index 0f508684..e45f50bc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -2,8 +2,6 @@ import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSONObject; -import com.zmops.zeus.server.async.executor.Async; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.ProductEventRelation; @@ -25,6 +23,8 @@ import com.zmops.iot.web.product.service.work.SaveProductEventTriggerWorker; import com.zmops.iot.web.product.service.work.UpdateProductEventTriggerWorker; import com.zmops.zeus.driver.service.ZbxTrigger; +import com.zmops.zeus.server.async.executor.Async; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import io.ebean.annotation.Transactional; import org.springframework.beans.factory.annotation.Autowired; @@ -55,7 +55,7 @@ public class ProductEventTriggerController { @Autowired private ZbxTrigger zbxTrigger; - private static final String ALARM_TAG_NAME = "__alarm__"; + private static final String ALARM_TAG_NAME = "__alarm__"; private static final String EXECUTE_TAG_NAME = "__execute__"; @Autowired diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java index 96402087..4ec5250c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -2,8 +2,6 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.zmops.zeus.server.async.executor.Async; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.Product; @@ -26,6 +24,8 @@ import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.entity.ZbxProcessingStep; import com.zmops.zeus.driver.service.ZbxItem; +import com.zmops.zeus.server.async.executor.Async; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import io.ebean.DtoQuery; import org.springframework.beans.factory.annotation.Autowired; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index e578ebe5..5fd70f95 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -47,6 +47,7 @@ public class ProductEventRuleService implements CommandLineRunner { private ZbxTrigger zbxTrigger; private static final String TRIGGER_CLASSIFY = "0"; + /** * 保存触发器 * @@ -313,8 +314,8 @@ static class TriggerIds { @Data public static class Triggers { - private String triggerid; - private String description; + private String triggerid; + private String description; private List hosts; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index ea5e8221..f11b9ec5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -2,8 +2,6 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.zmops.zeus.server.async.executor.Async; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.Product; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProduct; @@ -23,6 +21,8 @@ import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.entity.ZbxProcessingStep; import com.zmops.zeus.driver.service.ZbxItem; +import com.zmops.zeus.server.async.executor.Async; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import io.ebean.DtoQuery; import org.springframework.beans.factory.annotation.Autowired; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index 90c995a3..d159841a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -1,7 +1,5 @@ package com.zmops.iot.web.product.service; -import com.zmops.zeus.server.async.executor.Async; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductService; import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.product.ProductServiceRelation; @@ -18,6 +16,8 @@ import com.zmops.iot.web.product.dto.param.ProductSvcParam; import com.zmops.iot.web.product.service.work.SaveProdSvcWorker; import com.zmops.iot.web.product.service.work.UpdateProdSvcWorker; +import com.zmops.zeus.server.async.executor.Async; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import io.ebean.DtoQuery; import org.springframework.beans.factory.annotation.Autowired; @@ -255,7 +255,6 @@ public List paramList(long serviceId) { /** * 更新服务名称 服务参数 缓存 - * */ private void updateService() { List serviceList = new QProductService().findList(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java index db2040e5..a0608e98 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java @@ -2,14 +2,14 @@ import com.alibaba.fastjson.JSONObject; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.domain.product.query.QProductAttributeEvent; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.service.ZbxItem; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java index a67dba3e..8b8aca0f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java @@ -2,14 +2,14 @@ import com.alibaba.fastjson.JSONObject; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.service.ZbxItem; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java index ac2198e0..682daf7b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java @@ -2,10 +2,10 @@ import com.alibaba.fastjson.JSON; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.zeus.driver.service.ZbxTrigger; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -24,8 +24,8 @@ public class SaveProdAttrEventTriggerWorker implements IWorker { @Autowired - private ZbxTrigger zbxTrigger; - private static final String EVENT_TAG_NAME = "__event__"; + private ZbxTrigger zbxTrigger; + private static final String EVENT_TAG_NAME = "__event__"; @Override public Boolean action(ProductAttr productAttr, Map map) { @@ -43,7 +43,7 @@ public Boolean action(ProductAttr productAttr, Map map) { String[] triggerids = JSON.parseObject(res, TriggerIds.class).getTriggerids(); Map tags = new ConcurrentHashMap<>(1); - tags.put(EVENT_TAG_NAME, "{HOST.HOST}##"+productAttr.getKey()); + tags.put(EVENT_TAG_NAME, "{HOST.HOST}##" + productAttr.getKey()); zbxTrigger.triggerTagCreate(triggerids[0], tags); return true; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java index 3a2e56d0..760d77b8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java @@ -2,12 +2,12 @@ import cn.hutool.core.util.IdUtil; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.product.dto.ProductAttr; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java index 3045a94c..3220e283 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java @@ -2,13 +2,13 @@ import cn.hutool.core.util.IdUtil; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.iot.web.product.dto.ProductAttr; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java index 5ebefe32..9058c575 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdStatusTriggerWorker.java @@ -1,11 +1,11 @@ package com.zmops.iot.web.product.service.work; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductStatusFunctionRelation; import com.zmops.iot.web.product.dto.ProductServiceDto; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java index c8bd02ed..841ca7d7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java @@ -1,13 +1,13 @@ package com.zmops.iot.web.product.service.work; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.product.ProductServiceRelation; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.product.dto.ProductServiceDto; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -50,7 +50,7 @@ public Boolean action(ProductServiceDto productServiceDto, Map { ProductServiceParam param = new ProductServiceParam(); - ToolUtil.copyProperties(productServiceParam,param); + ToolUtil.copyProperties(productServiceParam, param); param.setDeviceId(deviceId); param.setServiceId(productServiceDto.getId()); productServiceParamList.add(param); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java index 0c01cbfe..d6dc62e1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProductEventTriggerWorker.java @@ -2,8 +2,6 @@ import com.alibaba.fastjson.JSONObject; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductEventRelation; import com.zmops.iot.domain.product.ProductEventService; @@ -12,6 +10,8 @@ import com.zmops.iot.web.product.dto.ProductEventRule; import com.zmops.iot.web.product.service.ProductEventRuleService; import com.zmops.zeus.driver.service.ZbxTrigger; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java index 8b72dfe1..f5ffd2c0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeEventWorker.java @@ -1,11 +1,11 @@ package com.zmops.iot.web.product.service.work; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.domain.product.query.QProductAttributeEvent; import com.zmops.iot.web.product.dto.ProductAttr; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java index 57cf5ffc..c141334b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java @@ -1,11 +1,11 @@ package com.zmops.iot.web.product.service.work; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.web.product.dto.ProductAttr; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java index adb0787c..7e7732e9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java @@ -1,12 +1,12 @@ package com.zmops.iot.web.product.service.work; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.product.dto.ProductServiceDto; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java index 70c1b110..aecead78 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProductEventTriggerWorker.java @@ -1,12 +1,12 @@ package com.zmops.iot.web.product.service.work; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductEventService; import com.zmops.iot.web.product.dto.ProductEventRule; import com.zmops.zeus.driver.service.ZbxTrigger; +import com.zmops.zeus.server.async.callback.IWorker; +import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictController.java index 1faa1577..233f96cd 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictController.java @@ -73,7 +73,6 @@ public ResponseData listDicts(@RequestParam("dictTypeId") Long dictTypeId) { * 获取某个字典类型下的所有字典 */ @ResponseBody - @Permission(code = "dict") @RequestMapping("/listDictByCode") public ResponseData listDictByCode(@RequestParam("dictTypeCode") String dictTypeCode) { return ResponseData.success(dictService.listDicts(dictTypeCode)); @@ -83,7 +82,6 @@ public ResponseData listDictByCode(@RequestParam("dictTypeCode") String dictType * 获取某个字典类型下的所有字典 */ @ResponseBody - @Permission(code = "dict") @RequestMapping("/groupDictByCode") public ResponseData groupDictByCode(@RequestParam("dictTypeCode") String dictTypeCode) { return ResponseData.success(dictService.groupDictByCode(dictTypeCode)); From 7941d6cdf1e505b5bd8b4e9482b2f39a5c1d96b8 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 24 Nov 2021 18:59:36 +0800 Subject: [PATCH 691/763] [fix]: fix usergroup --- .../java/com/zmops/iot/web/sys/service/SysUserGroupService.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java index dfc264aa..fc34afa5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java @@ -124,7 +124,6 @@ public SysUserGroup updateUserGroup(UserGroupDto userGroup) { DB.update(newUserGroup); bindHostGrp(UserGroupParam.builder().userGroupId(userGroup.getUserGroupId()).deviceGroupIds(userGroup.getDeviceGroupIds()).build()); - return newUserGroup; } @@ -198,7 +197,6 @@ public void bindHostGrp(UserGroupParam userGroup) { if (ToolUtil.isNotEmpty(userGroup.getDeviceGroupIds())) { return; } - List lists = new ArrayList<>(); for (Long deviceGroupId : userGroup.getDeviceGroupIds()) { SysUserGrpDevGrp devicesGroups = new SysUserGrpDevGrp(); From f466d0f15a151969485fcb471256264437095b06 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 25 Nov 2021 11:51:24 +0800 Subject: [PATCH 692/763] [feat]: update zeus-ui module --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index fe13223b..a826f2e7 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit fe13223be1a943a97514e7d09a8535f45c0bc4a6 +Subproject commit a826f2e7538303f66a88b1b62a26b3ba8af55c13 From 5e131e711b8cb607d083b7199f02116ed5d128e8 Mon Sep 17 00:00:00 2001 From: yefei Date: Fri, 26 Nov 2021 09:31:41 +0800 Subject: [PATCH 693/763] fix pom --- iot-server/server-bootstrap/pom.xml | 4 ++-- iot-server/server-camel-receiver/pom.xml | 4 ++-- iot-server/server-client/pom.xml | 2 +- iot-server/server-core/pom.xml | 6 +++--- iot-server/server-health-checker/pom.xml | 2 +- iot-server/server-localdb/pom.xml | 2 +- iot-server/server-sender/pom.xml | 2 +- .../server-storage-plugin/server-none-storage/pom.xml | 2 +- .../server-storage-plugin/server-tdengine-plugin/pom.xml | 2 +- iot-server/server-telemetry/telemetry-api/pom.xml | 8 +++++++- iot-server/server-telemetry/telemetry-prometheus/pom.xml | 2 +- iot-server/server-transfer/pom.xml | 4 ++-- iot-server/server-web/pom.xml | 2 +- zeus-webapp/pom.xml | 2 +- 14 files changed, 25 insertions(+), 19 deletions(-) diff --git a/iot-server/server-bootstrap/pom.xml b/iot-server/server-bootstrap/pom.xml index fdd7b78c..2a0a739e 100644 --- a/iot-server/server-bootstrap/pom.xml +++ b/iot-server/server-bootstrap/pom.xml @@ -20,7 +20,7 @@ com.zmops toolkit-util - 1.0-SNAPSHOT + 1.0.1-RELEASE @@ -32,7 +32,7 @@ com.zmops library-module - 1.0-SNAPSHOT + 1.0.1-RELEASE org.yaml diff --git a/iot-server/server-camel-receiver/pom.xml b/iot-server/server-camel-receiver/pom.xml index b4aabf08..82af956f 100644 --- a/iot-server/server-camel-receiver/pom.xml +++ b/iot-server/server-camel-receiver/pom.xml @@ -16,7 +16,7 @@ com.zmops library-module - 1.0-SNAPSHOT + 1.0.1-RELEASE com.zmops @@ -31,7 +31,7 @@ com.zmops toolkit-datacarrier - 1.0-SNAPSHOT + 1.0.1-RELEASE diff --git a/iot-server/server-client/pom.xml b/iot-server/server-client/pom.xml index 5dc285fc..e628457b 100644 --- a/iot-server/server-client/pom.xml +++ b/iot-server/server-client/pom.xml @@ -20,7 +20,7 @@ com.zmops library-util - 1.0-SNAPSHOT + 1.0.1 com.zaxxer diff --git a/iot-server/server-core/pom.xml b/iot-server/server-core/pom.xml index 9145b57a..208775d5 100644 --- a/iot-server/server-core/pom.xml +++ b/iot-server/server-core/pom.xml @@ -14,7 +14,7 @@ com.zmops library-module - 1.0-SNAPSHOT + 1.0.1-RELEASE com.zmops @@ -29,13 +29,13 @@ com.zmops zeus-server-jetty - 1.0-SNAPSHOT + 1.0.1-RELEASE com.zmops toolkit-datacarrier - 1.0-SNAPSHOT + 1.0.1-RELEASE diff --git a/iot-server/server-health-checker/pom.xml b/iot-server/server-health-checker/pom.xml index 5c868de9..53a12bd7 100644 --- a/iot-server/server-health-checker/pom.xml +++ b/iot-server/server-health-checker/pom.xml @@ -15,7 +15,7 @@ com.zmops library-module - 1.0-SNAPSHOT + 1.0.1-RELEASE compile diff --git a/iot-server/server-localdb/pom.xml b/iot-server/server-localdb/pom.xml index 5ed9a7b1..d0fa1671 100644 --- a/iot-server/server-localdb/pom.xml +++ b/iot-server/server-localdb/pom.xml @@ -16,7 +16,7 @@ com.zmops library-module - 1.0-SNAPSHOT + 1.0.1-RELEASE com.zmops diff --git a/iot-server/server-sender/pom.xml b/iot-server/server-sender/pom.xml index 3487d785..d6f44566 100644 --- a/iot-server/server-sender/pom.xml +++ b/iot-server/server-sender/pom.xml @@ -15,7 +15,7 @@ com.zmops library-module - 1.0-SNAPSHOT + 1.0.1-RELEASE diff --git a/iot-server/server-storage-plugin/server-none-storage/pom.xml b/iot-server/server-storage-plugin/server-none-storage/pom.xml index a2cfe458..ceaaf19a 100644 --- a/iot-server/server-storage-plugin/server-none-storage/pom.xml +++ b/iot-server/server-storage-plugin/server-none-storage/pom.xml @@ -14,7 +14,7 @@ com.zmops library-module - 1.0-SNAPSHOT + 1.0.1-RELEASE com.zmops diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml index 8a835dd2..15264a3a 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml @@ -25,7 +25,7 @@ com.zmops library-module - 1.0-SNAPSHOT + 1.0.1-RELEASE com.zmops diff --git a/iot-server/server-telemetry/telemetry-api/pom.xml b/iot-server/server-telemetry/telemetry-api/pom.xml index f3ccf88a..26525e1a 100644 --- a/iot-server/server-telemetry/telemetry-api/pom.xml +++ b/iot-server/server-telemetry/telemetry-api/pom.xml @@ -14,7 +14,13 @@ com.zmops library-module - 1.0-SNAPSHOT + 1.0.1-RELEASE + compile + + + com.zmops + library-util + 1.0.1 compile diff --git a/iot-server/server-telemetry/telemetry-prometheus/pom.xml b/iot-server/server-telemetry/telemetry-prometheus/pom.xml index df5561bd..48ee2aea 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/pom.xml +++ b/iot-server/server-telemetry/telemetry-prometheus/pom.xml @@ -43,7 +43,7 @@ com.zmops zeus-server-jetty - 1.0-SNAPSHOT + 1.0.1-RELEASE compile diff --git a/iot-server/server-transfer/pom.xml b/iot-server/server-transfer/pom.xml index 7292f127..9c84fffb 100644 --- a/iot-server/server-transfer/pom.xml +++ b/iot-server/server-transfer/pom.xml @@ -21,7 +21,7 @@ com.zmops zeus-transfer-tailx - 1.0-SNAPSHOT + 1.0.1-RELEASE @@ -42,7 +42,7 @@ com.zmops library-module - 1.0-SNAPSHOT + 1.0.1-RELEASE com.zmops diff --git a/iot-server/server-web/pom.xml b/iot-server/server-web/pom.xml index 94385dc6..b64cc696 100644 --- a/iot-server/server-web/pom.xml +++ b/iot-server/server-web/pom.xml @@ -20,7 +20,7 @@ com.zmops library-web - 1.0-SNAPSHOT + 1.0.1-RELEASE diff --git a/zeus-webapp/pom.xml b/zeus-webapp/pom.xml index 69faa674..b59594d3 100644 --- a/zeus-webapp/pom.xml +++ b/zeus-webapp/pom.xml @@ -35,7 +35,7 @@ com.zmops toolkit-async - 1.0-SNAPSHOT + 1.0.1-RELEASE commons-httpclient From 0dd6c8e9b33561bb3181540d9a0cd9f5fc48b630 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 29 Nov 2021 09:12:28 +0800 Subject: [PATCH 694/763] [fix]: fix library-util version --- iot-server/server-client/pom.xml | 2 +- iot-server/server-telemetry/telemetry-api/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/iot-server/server-client/pom.xml b/iot-server/server-client/pom.xml index e628457b..1760be98 100644 --- a/iot-server/server-client/pom.xml +++ b/iot-server/server-client/pom.xml @@ -20,7 +20,7 @@ com.zmops library-util - 1.0.1 + 1.0.1-RELEASE com.zaxxer diff --git a/iot-server/server-telemetry/telemetry-api/pom.xml b/iot-server/server-telemetry/telemetry-api/pom.xml index 26525e1a..6df8e8f2 100644 --- a/iot-server/server-telemetry/telemetry-api/pom.xml +++ b/iot-server/server-telemetry/telemetry-api/pom.xml @@ -20,7 +20,7 @@ com.zmops library-util - 1.0.1 + 1.0.1-RELEASE compile From dc5981da0ea8704f8ce012abec17fa7a6d7ca671 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 30 Nov 2021 14:10:58 +0800 Subject: [PATCH 695/763] [feat]: add self os monitor --- .../controller/SelfMonitorController.java | 13 +- .../iot/web/analyse/enums/CpuLoadEnum.java | 6 +- .../analyse/enums/MemoryUtilizationEnum.java | 35 ++++ .../iot/web/analyse/enums/ProcessEnum.java | 35 ++++ .../analyse/service/SelfMonitorService.java | 178 ++++++++++++++++-- 5 files changed, 243 insertions(+), 24 deletions(-) create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/MemoryUtilizationEnum.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/ProcessEnum.java diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/SelfMonitorController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/SelfMonitorController.java index d7ac9be5..21326448 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/SelfMonitorController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/SelfMonitorController.java @@ -3,7 +3,9 @@ import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.web.analyse.service.SelfMonitorService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** @@ -17,14 +19,19 @@ public class SelfMonitorController { @Autowired SelfMonitorService selfMonitorService; - @RequestMapping("memory") + @GetMapping("memory") public ResponseData getMemInfo(){ return ResponseData.success(selfMonitorService.getMemInfo()); } - @RequestMapping("cpu") + @GetMapping("cpuLoad") public ResponseData getCpuInfo(){ - return ResponseData.success(selfMonitorService.getCpuInfo()); + return ResponseData.success(selfMonitorService.getCpuLoadInfo()); + } + + @GetMapping("cpuUtilization") + public ResponseData getCpuUtilization(){ + return ResponseData.success(selfMonitorService.getCpuUtilization()); } @RequestMapping("process") diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/CpuLoadEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/CpuLoadEnum.java index 77635e64..39fe89ff 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/CpuLoadEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/CpuLoadEnum.java @@ -6,9 +6,9 @@ * @author yefei **/ public enum CpuLoadEnum { - avg1("system.cpu.load[all,avg1]", "avg1"), - avg5("system.cpu.load[all,avg5]", "avg5"), - avg15("system.cpu.load[all,avg15]", "avg15"); + avg1("system.cpu.load[all,avg1]", "cpuLoadAvg1"), + avg5("system.cpu.load[all,avg5]", "cpuLoadAvg5"), + avg15("system.cpu.load[all,avg15]", "cpuLoadAvg15"); @Getter String code; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/MemoryUtilizationEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/MemoryUtilizationEnum.java new file mode 100644 index 00000000..a17ac3ec --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/MemoryUtilizationEnum.java @@ -0,0 +1,35 @@ +package com.zmops.iot.web.analyse.enums; + +import lombok.Getter; + +/** + * @author yefei + **/ +public enum MemoryUtilizationEnum { + utilization("vm.memory.utilization", "memoryUtilization"), + total("vm.memory.size[total]", "memoryTotal"), + available("vm.memory.size[available]", "memoryAvailable"); + + @Getter + String code; + @Getter + String message; + + MemoryUtilizationEnum(String code, String message) { + this.code = code; + this.message = message; + } + + public static String getDescription(String status) { + if (status == null) { + return ""; + } else { + for (MemoryUtilizationEnum s : MemoryUtilizationEnum.values()) { + if (s.getCode().equals(status)) { + return s.getMessage(); + } + } + return ""; + } + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/ProcessEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/ProcessEnum.java new file mode 100644 index 00000000..477c9eb7 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/ProcessEnum.java @@ -0,0 +1,35 @@ +package com.zmops.iot.web.analyse.enums; + +import lombok.Getter; + +/** + * @author yefei + **/ +public enum ProcessEnum { + num("proc.num", "num"), + run("proc.num[,,run]", "run"), + max("kernel.maxproc", "max"); + + @Getter + String code; + @Getter + String message; + + ProcessEnum(String code, String message) { + this.code = code; + this.message = message; + } + + public static String getDescription(String status) { + if (status == null) { + return ""; + } else { + for (ProcessEnum s : ProcessEnum.values()) { + if (s.getCode().equals(status)) { + return s.getMessage(); + } + } + return ""; + } + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/SelfMonitorService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/SelfMonitorService.java index 1d1a1cd2..e187aaf2 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/SelfMonitorService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/SelfMonitorService.java @@ -1,17 +1,28 @@ package com.zmops.iot.web.analyse.service; -import com.zmops.iot.model.response.ResponseData; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.analyse.dto.LatestDto; import com.zmops.iot.web.analyse.enums.CpuLoadEnum; +import com.zmops.iot.web.analyse.enums.MemoryUtilizationEnum; +import com.zmops.iot.web.analyse.enums.ProcessEnum; +import com.zmops.iot.web.product.dto.ZbxTriggerInfo; +import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.service.ZbxHistoryGet; import com.zmops.zeus.driver.service.ZbxHost; +import com.zmops.zeus.driver.service.ZbxItem; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.Arrays; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * @author yefei @@ -25,39 +36,170 @@ public class SelfMonitorService { @Autowired ZbxHost zbxHost; - private static Map> itemMap = new HashMap<>(); + @Autowired + ZbxItem zbxItem; + + @Autowired + HistoryService historyService; + + private static Map itemMap = new HashMap<>(); private static Map hostIdMap = new HashMap<>(); - public Map getMemInfo() { - return null; + + public Map getMemInfo() { + Map resMap = new HashMap<>(3); + + getItemValue(getHostId("Zabbix server"), MemoryUtilizationEnum.utilization.getCode(), MemoryUtilizationEnum.utilization.getMessage(), 0, resMap); + getItemValue(getHostId("Zabbix server"), MemoryUtilizationEnum.total.getCode(), MemoryUtilizationEnum.total.getMessage(), 3, resMap); + getItemValue(getHostId("Zabbix server"), MemoryUtilizationEnum.available.getCode(), MemoryUtilizationEnum.available.getMessage(), 3, resMap); + + resMap.put("trends", getTrendsData(getHostId("Zabbix server"), itemMap.get(MemoryUtilizationEnum.utilization.getMessage()), 0)); + return resMap; + } + + public Map getCpuLoadInfo() { + Map resMap = new HashMap<>(3); + + getItemValue(getHostId("Zabbix server"), CpuLoadEnum.avg1.getCode(), CpuLoadEnum.avg1.getMessage(), 0, resMap); + getItemValue(getHostId("Zabbix server"), CpuLoadEnum.avg5.getCode(), CpuLoadEnum.avg5.getMessage(), 0, resMap); + getItemValue(getHostId("Zabbix server"), CpuLoadEnum.avg15.getCode(), CpuLoadEnum.avg15.getMessage(), 0, resMap); + + resMap.put("trends", getTrendsData(getHostId("Zabbix server"), itemMap.get(CpuLoadEnum.avg1.getMessage()), 0)); + return resMap; + } + + public Map getProcessInfo() { + Map resMap = new HashMap<>(3); + + getItemValue(getHostId("Zabbix server"), ProcessEnum.num.getCode(), ProcessEnum.num.getMessage(), 3, resMap); + getItemValue(getHostId("Zabbix server"), ProcessEnum.run.getCode(), ProcessEnum.run.getMessage(), 3, resMap); + getItemValue(getHostId("Zabbix server"), ProcessEnum.max.getCode(), ProcessEnum.max.getMessage(), 3, resMap); + + resMap.put("trends", getTrendsData(getHostId("Zabbix server"), itemMap.get(ProcessEnum.run.getMessage()), 3)); + return resMap; + } + + + public List> getCpuUtilization() { + String itemId = getItemId(getHostId("Zabbix server"), "CpuUtilization", "system.cpu.util"); + if (ToolUtil.isEmpty(itemId)) { + return Collections.emptyList(); + } + return getTrendsData(getHostId("Zabbix server"), itemId, 0); } - public Map getCpuInfo() { - List itemIds = itemMap.get("cpu"); - if (ToolUtil.isEmpty(itemIds)) { - itemIds = getItemIdByNames(Arrays.asList(CpuLoadEnum.avg1.getCode(), CpuLoadEnum.avg5.getCode(), CpuLoadEnum.avg15.getCode())); - itemMap.put("cpu", itemIds); + + /** + * 获取趋势数据 + * + * @param hostId 主机ID + * @param itemId 监控项ID + * @param itemValueType 监控项值类型 + * @return + */ + private List> getTrendsData(String hostId, String itemId, int itemValueType) { + long timeTill = LocalDateTimeUtils.getSecondsByTime(LocalDateTime.now()); + long timeFrom = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.minu(LocalDateTime.now(), 1L, ChronoUnit.HOURS)); + + List latestDtos = historyService.queryHitoryData(hostId, Collections.singletonList(itemId), 20, itemValueType, timeFrom, timeTill); + + return latestDtos.stream().map(o -> { + Map tmpMap = new HashMap<>(2); + tmpMap.put("date", LocalDateTimeUtils.convertTimeToString(Integer.parseInt(o.getClock()), "yyyy-MM-dd HH:mm:ss")); + tmpMap.put("val", o.getValue()); + return tmpMap; + }).collect(Collectors.toList()); + } + + /** + * 获取监控项最新值 + * + * @param hostId 主机ID + * @param key 监控项key + * @param name 监控项名称 + * @param itemValueType 监控项值类型 + * @param resMap map + */ + private void getItemValue(String hostId, String key, String name, int itemValueType, Map resMap) { + String itemId = getItemId(hostId, name, key); + + if (ToolUtil.isEmpty(itemId)) { + return; + } + String res = zbxHistoryGet.historyGet(null, Collections.singletonList(itemId), 1, itemValueType, null, null); + List latestDtos = JSONObject.parseArray(res, LatestDto.class); + + if (ToolUtil.isNotEmpty(latestDtos)) { + resMap.put(name, latestDtos.get(0).getValue()); } - String hostId = hostIdMap.get("Zabbix server"); + } + + /** + * 从缓存取 hostId + * + * @param host 主机名称 + * @return hostId + */ + private String getHostId(String host) { + String hostId = hostIdMap.get(host); if (ToolUtil.isEmpty(hostId)) { - hostId = getHostIdByName("Zabbix server"); + hostId = getHostIdByName(host); + hostIdMap.put(host, hostId); } - String res = zbxHistoryGet.historyGet(hostId, itemIds, itemIds.size(), 0, null, null); - return null; + return hostId; } + /** + * 从Zbx取 hostId + * + * @param host 主机名称 + * @return hostId + */ private String getHostIdByName(String host) { String s = zbxHost.hostGet(host); + List hosts = JSON.parseArray(s, ZbxTriggerInfo.Host.class); + if (ToolUtil.isNotEmpty(hosts)) { + return hosts.get(0).getHostid(); + } return ""; } - public String getProcessInfo() { - return ""; + /** + * 从缓存取 itemId + * + * @param hostId 主机ID + * @param name 监控项名称 + * @param key 监控项key + * @return itemId + */ + private String getItemId(String hostId, String name, String key) { + String itemId = itemMap.get(name); + if (ToolUtil.isEmpty(itemId)) { + itemId = getItemIdByName(hostId, key); + itemMap.put(name, itemId); + } + return itemId; } - private List getItemIdByNames(List names) { - return null; + /** + * 从Zbx取 itemId + * + * @param hostId 主机ID + * @param key 监控项key + * @return itemId + */ + private String getItemIdByName(String hostId, String key) { + if (ToolUtil.isEmpty(key) || ToolUtil.isEmpty(hostId)) { + return ""; + } + + String item = zbxItem.getItemList(key, hostId); + List itemInfos = JSON.parseArray(item, ZbxItemInfo.class); + if (ToolUtil.isNotEmpty(itemInfos)) { + return itemInfos.get(0).getItemid(); + } + return ""; } From b4c14ac5a13dd30b66a0141ed7c6ddc24cc015d0 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 30 Nov 2021 20:44:14 +0800 Subject: [PATCH 696/763] [doc]: edit git image --- docs/images/arch.gif | Bin 1422544 -> 1215126 bytes .../receiver/routes/PgEventRouteBuilder.java | 17 ----------------- 2 files changed, 17 deletions(-) delete mode 100644 iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/PgEventRouteBuilder.java diff --git a/docs/images/arch.gif b/docs/images/arch.gif index 3560508ab35ae7653a016c26125bbcba3f25b307..26e047c7eb8d0b95a953bacfc9ace287e3ac4489 100644 GIT binary patch delta 1054376 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

-gassZ&X26YG87B09IOdaY=EJUvf@qbxmzu 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 {7}(~GC^fM}kgz)-ayyca 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%0Ah{xh1 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%0Aqawjjkvjw6_h?4EN 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 p9nTL>S(*e>*S^dxyoTY%QsmR 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℘-skbJV$3#!IWD%C6&W(dOG(_7Ef&SOF6@5z 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 z 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%0A(bI~m1(t&ocvnk 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 Va{=HsVcP~eX+Kl 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%0DID{5FSb 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

pB4^#Y&$20gsaTcRu|tBzN! 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ϑ$KMhV}VW8wmCOP2dZCHDha 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

n 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

{}|O_nlJ)@ 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%0A7)X6=HCL+Z+!(tr~ib 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

wgOz|2y7*f|y2u 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 z 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

&fQ3%3-02Il-lB-ODu@eH;|Bju| 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 z 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μW+Tr>i7S0nA@>#uE@gnJxyf2kTz7*pyJsi?6*Gnm0 zJzj{CujL9`Iw%^^T{5D&d=a6qkFj3A$Uq4;VP$pv6pZqNj-V@7;^}TE95EyV*K(KY zKliLQFc#|fFBbYwr0t(Q>t_R3xxbTEWg~Bx^I6^8U+1sz`PbejsY2NS*0OSsb1kZzOX`DOhI5=5sZaKC**`BmBc0Gge8~x<=6aUfsVt-7T+lfwSb{7EAcuk=H~t(?(Pu^Fr`ZPXcA5JB@Ye7S$yDg zn|i*wi1RF}S|x1H`tc2H&)TCn1lzN64<*!CEtLAe<(4niTKyl~y;V@#ZR4&RG)QrG zEncjK7AsmP(&8=!ic{R(Ex5Y|cY;fChvM$;?%C=4e&5<_&wuu;!#%Ten3LonGrv5~ zec#u$t59v>Vws-6qG~Z|0gQ!Zp_lL%myET0;}R0F$XE8D$= z8@8Jw#x|f>?db5+)f8anI^XmSr_*H*-Z%a{hQ(*p&ubXBR0gzi$D;Tp zpgwIn+oi*SX*`%9%( z$?VI?ChOw4+7M+IQmX(R&I-%7i|ppGa;?C{^k*c`JH^gXFHU&JH5%kmweJxhSbF00 z(caTjIL0eCpuZt-G~MDPq1?xT2Fb9*sxVRc(k+J2XH1iFo(}gWG9U7Er%b%Vo<>)ch0V%-m7j53M1Q1`@*pD(tw9`}_}`5(0# zS9lNc*IxrLi!NyeG!jU(QdRN>z=9c`O=FR^N<8pNYO5YXiSD)FC78gCk_6)*kt;q*;`S7w!Pfc2-!!+3idAs%cpk{wj1Go&+8^)2F6d{B;lFgIyneUr zi0Mmq(k&Sn^p+d5ScdE2(#5w0#Mms?_fpK&+GV0b#+wNe!E)hlE63#n`gox0j z55S&-6O_8c@&;g2!=W>UARya#s}nDNCpJv>g`i2{pU-qQWd}e7K@>-igM0!>9dJ1u z)^wk<;N_*-Vp@zkp4V~?UlY{c~S>wRaDrQSJ@xDk!i&phNV4XXD4=$T2}GD2FY)( zhpHh0h$wJyG?M7Tj+`ZF4ywdur*yzw^^I086~>BiF{~F-eSF4>VI=zW6x#Tr(kJK9 zE_8GW-q#=R^SYrN5erEP8yn5P^<`vj5EUX1lmLVT)QleQ5LvZRhtxLC(aO5VSP>d| zM`+mGW*gTyFp?Q*=t&Wxl5(0FQ}y+=vNmPr>R&Xcdh2WJdde)aJNy^9X&Sy1b>Vv+ zYD}ak3w=2|w$x2sYGS`_tSMtPH+)_V_y0_*_4X9E7 z3QGnUvH?i?)tr6fpnz?X)W!kz6Ye-e{*8C3^CN1eHR0>BJ3>bDqq5YO>Bm~Tg0aa+ zhk$Crye#-nv+83WU$3YP!uBM{7RKEoYjX|{Or@zFCZdfy@v6^$yrIvYj8&=4endM^ z(j@)kcoP5?xBLl7Ae}5_u&d^K_9sYl9V3&tF4pxhQ9UG`X=%I4t)UL!&|ODW?!PV* zgHjynHt@|vjMmiz9GjSOG*8ST!=hkp;P!kKoQ}@GG?QB-BYWSDV zJR6#~1y5a08<%0oScq~mFS=-c=7OOz(=U)L)%+2tM?eX)cy0Vo02V67DhaOdS`*!M zBatg*6jTe5AH8nGU}ansKM){_$Bbb^-M8L+=U4%))Xe2msPDAxBIvnFw)s`sF=HyzW#K1krI1}LUP8Z zcXWj5;UA%wgoZ^$rqkAZ>LK2I2-+~+uOs~g^>oU}!qiFoxcKd_2Ca+%$eCh`!CH?^19yzfN5cEpIc7slEl!@Q}F+0hx z61vvUwf^i8bHHjV^GgIPco%QS$&>vS7@I?eY2%Gj48~^}Gh49jY>- z($Pmt$c}aRWJNns5&K@6_{ypJPB^(r@DNg{%7tDyi80EkaC<+{DOM#ac5(Uf+!5V$ z(jrt6=>~ho%)UoA;0#bOQT{H1%*Za^?=H9JUX|njMT(WHo0QGOUajvJ;WxQkC2#E_ zzaM*44YpJ**=#?gf`4brhbTDxKWNWtAw&Ng?O8)VsNLHo`ybkKv06wQuAPor@Fztg zr)VN0lrR%1)RLsICP-LQ(yNxcunywz6k?2gAVvXGcz;rOM}Giaj)&1jXgw3w2O85* zNN@uW>R?jD0wk;r60vd@k>QNf!vpnSQ;Xb@3Q?y0s%2^yP8`vJgEX}nd3-qTeQlB{}p(4V`cRowzZE+a)B7)|rxooQ@=>4H(12 z6D5!&!o?da${T{i8z&(h2fJ9^a*mTF2|*h0SnrGFOV(Gq_dZ6k2_28qKy_wrjMoYA zr#g=jyNEXm(YLe@@Vz7A<&EF2On9dj^W#2VoFq|pK4u08vIoaA%z7+-47M1Eq}h)Z zltOoDjJH!y68)JdUKrPb4UG$SiJ999RlZN$T}udKO!{Q%6Xg;Y)R@cyP9j}T%1Dl; z4)!NXv@PUKDGrG&5cVobPSUpT6W09n9G)7GAM{WO% zQddb^Z%og2##ok4HcQU98VK7`&+L~TvV+B$0JHg+bWnYRX*PgxkrNJTIZl>MqWiYXP9vwe5}LEtpE2kXN-_9>N(Rf-1&@RpcIJW`P{Lpg%^h^klqnAN-u#IT z!)t-yUNztnN)st_=7~4C5ijK7-)CkvWGBq!3Zdo6HDZzq=QY8>eHTVz7KXPWE!0WL z#NaFJmx6yS49`4Xpjb=>p9P0@{k9;ez)U00k`#d%1kY4ice zV>H0tUx4ro0Lwxnn!+6(!0mHjLhMgQfmEm+Hry#`bvEGSVk9!oZ`FKoIcAxK>h^qQ z{>j9@u0_G;S@GqAwEb^6>q28#G)lh?q8B^>i;9cGNM3b@QvFUzhb>&`AZd*dOiMGo z>EclTP$~;EXpaAQ*??>57E9=$43Y;+zW0L7*V{648R;q5!j+{Unl#kK2o8Z0K)6P$ zAzYEel=s;z52ZL6;8xiojiJDj|9ucMEjV98rjpIS@@*q*9SLZ{0pM3+;xC3w+u+fY zW(!VM(KpAGt>wJxt4f#3rAZZk?H1$WUv-BAV85tNB8HdU<_p%V5nzp8#Lm{B{+OkP zIAxc8xljZD)2~UfM(RJb=kP;pI5u237P9})o}(d{io$gOY&b=mIxWq5W4C&_p(;b9 zTGPdPtH*kvdA1RHgS}>hV@VzjY>eI9;J(=4`7iC6AL6eG33P)5r$R!Tp|I!<68Q)L zku}EfH^yl;Cb<0_u%QmM;Dl24)mYZ}@287W4;rb=%tLU?l!Ezzn#>jt`|T zENtpAUFT2B3}Z+EcI%(iRvsCY*+-O()Qm;`SNAAwsm^VzGHw0MH7A-G1syFP4_a4Q zTaWqMF$dA!D=Yd=Coh;Ouxd=bd6g!$Q6q=1^$3SQo<*&v62@tBw>QDDd}(v!3yR?$%*TgOc{%Wdm@`LQL3t&9!=UOOf7r_o4|S*rCJP=9qS+WDf3qprSr|i$3k} zK1`M_UO*wQcbC6=s{J`INEV(KJNrFbNW@cr^ix+@S~hMPUU=+4i!_lia&4?YNb%;6 zw)Fv4QZz0=$4%&9Kr)gDHUh^*r8)?a%iFU&ZK$bbsAXxW?P;ike7H+sxLa$u*L}D@ zZFsO{cz9`e^l5mUd}LB!WJ+t~UrF0S%gEBw$jTFRWQ}}uLtu1EYZNAF+e;fgXc;|P z8a;U$JtH5x5E#4C8oO~HyGt8;Xc>E28hd#f1HhK_g5!wV?D&IHxz#s zc_ye^C%HZTAlw6my%EtuV3M{7A4eqXr$3)Drc|*JNI-C0AUyHqsd)${vtBnU2;TE( zN~JZ_LBG2x8X)U2ty31J^)zj8T;^2?V5!Upv=rI?Z4xI~aoih$Y>U;D79izjt=jf5Vg)k%vYE!;1k|}X;7@zRi7Lj^7 z(~depWdm);e4n0G`=%FKFu3F#mIgf9(a{ET0|q{pA?$d{)sFFw!G zMSKamk@06;agbOkH(!}~GbQva`Q;1bL|d|gY?UVLk6zxahuf-Oc+u&`MpZAyg9q^-c4v z0s@A>U|aY`c*GnFWnv!;dMDSMR0f?VEggFEH6c9$egtDar*(5wyZ^0KxvKl-FVxp> z*ET;V!jpS%X%A*DgNmAc2R~b7h0$fpe*F|_QmeYMHKx8zh_)2P*YV9N3x^a*TmjKA zY)KQ7>4)de&$gYEr5#hsqAtC0dmlt>VPkB7t>H_(Q^u}WAdzJO&?@1IC?RSKhwVD~W&B5Nm`8q}y6HUAXj7^^ zFdN1`t(SetWiC0Si%`*!h1iQgkqpU>a~6-u8#cCdPIf#`_A*Wm+D?xC-LqOX;!~Vn z>73sDch4&Q>g4I=6hL(bzuNruECeEOMk@%%t<)PGiObAxQ6?&}IeXRF-gk(N8wLh9*CAL5xJE)!zga&gso|xN8 z)_QMyv4+XzL%O5x`k6YW1OOsu_2M?9q(04K6;EBJSiR(EQ&_I9AxN`P8Tp#$qnS_F z3E?@YBL&zm$#IF<3NNJaO^YxFPQ^$W0BTPMy~IL6RrB)?fYF|Vy~4sHBL6Y;{oh$= zl6sU{cveQfmrB9Ed)B{MXaIspNCTu1_MED2OY;}^ZRzf5YX67!oSYYt6E-?r_-A_N zZx$L>Ti?67w!S#j`Fp+l@18Yn^04UW?|`LEO;}hQfmv8h;qDrq`*%=4fRE>$Hwr8Z zU8i%xq=W5QZ4-cm-(!TiVggW+UlE8|JtX~*#%0#<)a$3I&L47?Hd53_tWbFp>hsXP_8+XVzM*KC}YOyUE|1hhROrdq4QBE^RvAzF@T6 zX*EVfu+A>vp;`m5Kup?^W%rkRf57HMB%~)dr+gj~%u4j3W8k&K5JqcHhlgAARfZsW zuN=jE(ZiBT5a5|i4r)V>BsJmw~N*I|L26|56*@~88 zATbD&`2fp82?m|W;=Zf=eC;lw1BPXxlghbK+JVeFNtSZbFxqngb9RbF{eHn`Wt*h! zRQs8qySN2YQrYS5H~S`xN-KA}S^k84($KU(hT@`}?{Sd5To4~~H!YfCPGMNIaq)iq zg#&jF6}c5`&&nfCJQnC?b-@fStuM}|x0B)igP+}Gc36f$tASRga&>T6(Sgi*RM|~v zepJ=Z0HZw*|FdW13p=bGS;H@(ZxIzcu3sWGF=l9SWIchTXCFvIwhBtDOlC!6EPW4q zSu4Ko{PJaQx!fr^{hU}VgTxYe#Cq1D%$rlv4!|ot>$=#Rx1w8T={oC%r0|V(uDv`4 z)#E!IReiwX@MZr9=Vfs*P_E}b(7Y$;cQM3ixWUPAyMlW;!t*Vs`ZejdF56Mznx9;P zH0JKI<5Iax9Ann&F;{;mW{2KE2R?{dz8^lmAxE3O(>Z?MN#nO*Ppg~gu|0k?#TPQu zs9<@sxIfzB*tKv2f4jW@skClLa`V`!!Az{$X~2u5!s1z6I7+ub}>qo z{a`fWv(;OU1gFuRv67-z$ZnoI>zZtiJw?c${DuthPJk?C5A^J0`L(KN4yM}-po>5f~uNOd^;#oaW2mGgfhB3R;vucwLWKSku z^tdzxMrWF(Rt{g>+$>}QBdEx6XP6J!E1IYU#!u@ZXZ{E>+E=u}U4))}K=$zLS0+-h zEc7gpXE+%)O z*o5vphFGL2c}(Rv3c7q|MetyLr4o9%e?HsK{XbQAwhX&CGxS#|EJAIHwzgWtv;_CS zLcaXys9Iy?`JBFYxHW2#rX^&l;+4E9*UXN22O777vuzL872X)7dcZGpU8FZKLtm)@ z(a>Bk-%UP@_FQVj_+@@jr|TO8kF)KY7gj#7ICVVJSUH5nCllZ5LL$oT3%@MG zKE7!{hCMJ?Q)|;qwQ*v*+|KP$`%EINF@nb0#e-O9gWI?M@V#{{WtE1)^v5kn4?nvtu_QeC zZ{(bi`Zsd^cZ3@Rh6EQw(y~fmQ{3eI`jmgr$~gs91ts;_rLDe@hkxC}d2Iv5HC?3* z{S}Qc194wX%Rp?`Lvqh!TK`k=@8SB6(SOIet=;2)Rm8(jMWaup6E8JWFAa0hrWt7S z{7dV}Sy$i0@4>0=;f4O8$$_!??&-zh$wgQW4RaEAExk<4u1(Hw&M$BGu0e-3UjAL| zPVT(S>_O*tq4NhXuuOV$|9Jc0V*Tjl;N)uK{ATOy`S9%Ka}XdrsB;*ylbxVV5Tx7n5y zcS=?i4Ml?1fKp;x0QK8?`}z@bunY|s?d11A84#tNju7+%tc>E|v``l91FY;^YuVhH zW?ObWhLTXV564EyxC{WaMb^!C7G*Lq8Etsb3FHt zlA}1@?PNjTGOIU0=~aA{Jeb!|CSBHLC3-Mv`x#7nX4*N5EU0}=aDjpd08o>MJgF0~ zS9`;360Hv$dTp+Gq-3As^&94GasYm$_xvGTcwDdOx-C zJBTn~{`VIQT#?AT%hUn==U3wvkJsoXr^xq}bdHRJ5B1@8lxZ&7F5;tD0G^JN+-GkMM7ccsm5|4db76$HS$jERYP|9N z9zO)9LMVTo^<|P1T5T^xVf)7AMgq==wyjLoqL1Ja8N^<3ssqW%FERF4u2wSQh z5NSTDQ!;QNmgizd@2FhT+5N#=V9;PDxKBuM0P$auF#*>0O8d9S#CIlFxN2PIMu5ES z`*1i~Y(5wER-4So^_^TZb|O249>2jNa<_rj;JtlU*>i53mMKam`6|6nSecFc9WLq3 zh(2kGxpAPNNI?)**MlBy8xy6XbsBbuPtEt{PXUD{={@$q?D~1&mSV_D$h!f2er@(C zfj9Q{GT-qEK~r=lN0tUO+RN_^iA0r`f6c}pUwkMMb?n1tE#>^&B9uFqj>Rru(}3l0 z8q50OltgsX6=izw3yXDX1E>0($kdsa7*oc3HWv%7-K~6g#f{md*?6LnZ{Y^gf;^px(P6m;1hg5|(tDFCI%jeLz*W(uR=CU8v8a{wq0Kh%FiF;s^3a$$F!<%q@l1(ajF}Mx_KI;HiUh3=5yYYwMQrXfJJ$TK8VoIe#-zNw)P`#>o<+t^E4_G)f#%{=4xg|oaCJNiCc zVbnL{9~kP&xMGrNOn4K2jmj2W#y-oaJqhnOZ@%8NWwb9~IZhV;d0>~hynynK@@KIo zCBE#g!R%p9&UgS}em48a@@GRMSq9RR^hmc2)*aL&R}GvnPWx?1UIV!p+dt7C((>rP zsVYs=Ol85$&|eG(v69+woZdrwHmT|dr^{WhOY|^G)cRy*gzWQ5P31~7CS=0vny$;t z-ym!4%BWU;1(!RQm9P>g&$hM2Qx#p5=>2K>;`-{Q(vV#Ka!22X@Ng;rl(KEi5YSfZ*wUSHwV`bH-x zTeHOxD{*q)Qd^#Nsl7g=#5s%Y7YWYH79ml2jR(8F3#)d6QbUv3$Q#GP$5189kIn1& z%jE50DjPAXrNys-n#pcDhdK?dBOV;?H0F!``8wiEz9l(tbZ?CQ++)>Aow$|1g2I!|nFk-INAM(%+SlhM|OK z5-=T`Zo`hvD^h392m>Iya;Mr}i{+(l@2ZyNEFIh3@OR4_I)I*LE)@^MGv$uWw$V0T zx0);45ih(Vs_EAUF*P|`oZcjCK@-QoP z`L9YPQ(<()mV-BKj%-BFV-Xd#6U^;D@@rc6lUGr8qZ=MauXVQ1b>5$ZoH*8KdQ6s! z%Eg6O+)VRBn@2c24@chI>a3>j_w~A;RJ6JruL=$&uRP?5om!6DEgzt(#})On+w}=S zpXYuEH0YjgH*!4RYyw*z!Llc-)|ppYTVColZYzwgf+m`B0*WiA!(}ohEfvhj#V;W7jix04&Dih*!!VF9FR{O zY$_G%A@8(-{bg5+2}brhb)*iZMdMDrj}p((9#&^<6v=?)0S zj-d-d$LK(0OpfUxb_ON|hDh17C&N&h-h=UhCQh;F_pt`|AVJ;)<9(2bbo8FH{Rg!; z|3D8lRaDvexGIGhMR1I}QPnC$_X8a`JXg@k2q|{+W^Ioxz!xp*0Z%Xg zYm>2euW{gq0_>)U>Rl59mMjnBd{b|LBsEZl&-BM&fq7Fwoob;@AZ+=LY%2WL^8wjW zufVamz#+6y%q11~qj9iIkxQ{@h>U5uWZ~JJDOV+&1^_@(3Fo+m9KfLBIF3lF05Gya zNJ_~MdnmF37dsUfYHq_hgOJdK;hZ}V$SR8>9ul6Mipu#4$SdLaso}^fVecdPru7wk!U9MDG0bQ5;U1!Qe<)2@L*X}Q?Vs7 zxcQ*;B&9eSEz4a^OZ6a~K_gk05bTH@t#}vOyB{^$Q4wq(&54i5QEWA@N-gf7swxeN z6IXgJcFIt-t4#>?xsP=1)jlB23WLNDqtTeiIOI#e2Q=fZe5|%ttZwshN!hPNLrL0J z4MkRWy>fD_{q5@4GC-` z#((2ycc{>43K2;vp4&^SGf6|@t`%LZOTw$AUUU*VwBbP`raKHILJyNmN`0?h#dRML z5`>}h{&P%SwB%e6!b9Codc#BiA73EoG4-Q1&`6S+`g7Qgi#mvKF1-YZ=~B{g zvk+h?RbvobYjOyoGlc}9H#NpXat^r|`XR~E4Fn4{SJI7iK+K;VZ0e?Zb#;ETs$TA< zk$5aM8H>1unh;vD>H;_a0i2dszSUlbp+f^PWzD`7{5}ikjB0mZ=6h=VuS2~TbGrG% zp%blLn!K+%+EhqMZJkrAwKa))EP`|f z`tLLo0c3HIEIKU78rqWMndf3S2bz%g-7)Wg*lH%{!Bs)=mc&Oo!mO%fEt>C{efAld zj&3`J3hNn$I|H1vNYlDz7i%Jkx)2iGzidFeUI%r3Xwji&3VxIJ`<+YH9h!ZiY8Rna z#V3I_dADvMtw6S6YZ(FU;zn0LRp+2WpuDUNk9$w>;;WUS9$N?Z?K@9hB1c1$9v$~E zPN&}RArHAU*oxLQinVu&3^yXMnfs~NIjzq%&G08SqJ2xBH+jFWK)?V0aYg$-J;4_J zDz=0ErNO$xgT(>^Msb4`Prb(*nvy+@HN*W}*?84yLmF(D!L!&lb?=EgRokBWwYi9$ z&yYp19bw6FpL@?JIj_??kR5`o|5;{+RYAU~P`r;=1o4-S?b?>>#lxQ~|D zBI29@0i2^=r7G(Jv?b?=6riz((y@ahWfxB6I({sNdhDOvv{%t6&!ydt=YKP1FTLKY zCm<5V7+Q5r-z!X5x_r(#F4pzhbzB2A{r4*xpyu|3mH2O!jkeYB3F5qo_Yx+jlT3lw zlW1=^4}cul=_*`rxL7720YoF0@f=*=8uAcot>Y}m+LjNp7%&*VGgc@Mey zl-BvI?YTD*^OD{3If4r@4kCFT3q|P*#jOja%M0bt3zZa$)q;z)+Kcrbi;(oirq;!l z<;Aw=#SV(4F2SX4?WJCirT+A#!PceW<)zW*rE!YoNx|hQ?d2Jd<+=3bh1TVz<>i&< zIF4&)>1(){=HcUOf@QkcCu>BMdJkDh57l@Q zPwQ#<7`jnmh1gbE8^k-k3@=b^u-+^Q*JibGfRrJHf8F~kx=kL+A6~eKwAAn- zoXjGgI@DrY5|kWPbz9<|TU}{e5%mZdmC7)Q_jgQPmB?+4PpaB4K=rn5ryE9$EIJHf zCZkAg z^P+nJl=^7rh#OCc-(L1y%YiYUXyeNF3^m&vD%6^7|Wq(R}`Xq7+$UMWQvihC{+|)VQ zT{*_dJl{w-#vePzsyL@^x0s4Nr_sG&@VbCWf?3)x*j6vtp%j zUh=hH!X&|;pqIi_SE52!pLMS!yso5RlHm3$+10DBFi$YmwUW?(Ji%%eqb>k=_gGBz z_N%#$>+I)iNi0kQ-D#uK%T1e`ugF#^)W|j*$SO7iDmF+qUP!reNY)&;-z%5QSFbHs zEmX&mo0pL7v9!gsu#$U*Y+Dp|X2$cjm`k9Xh5?Z*Ei0og9MK@1THz{oGxSza-@M`%021-f%xq z1NNCO8PvMNwzC>VzG3C|MdiP1+DEC*leTl+dS}7Zw=wXKCs?`$MncZPmQ&;Hq!`T< z_CuriOG1_jZaYHcTn`(|jXL{2=TrF4iWa7?t1FqU(EDdaTdGD(FP57u=WyDzLRO(i*w=D5!+Of^GMuOkUrnT4;LbwPtlQkw@wr-f$5hQ^Z4H7 zo4^nHM*2u4;}9ZaMKflcL>)8&dE-xkKX(*4IBg3e#r7(V6~&$&I6J%u+Vy?rsmd+ka_u#-OS-NqgVyII^bda^hmY4dD`Ch z5Hpe_^2BEVuxumoGy&odaBa$E+AM)@}`8&=dyFhfWMuPf2X^2JHYkl50+UpZt zDGOI4@4ZL)*)K7(rSbZEClSgT904b{vh!IdoRxPFCC@Kg6&i0s;X-h+g+74b%j?@U zJc%z_lYYuoeoW1{OeJYb@sPZ2TMhLPRmU@y8d`}W6lJC|Jf)LDF zzGjp^fOrq@g88OI(n-5#eih^bf8@Y!hq8MqP+aBRBk@F`h)is$-U#IH^fO($5X9ev zPINic;^Jr*BID>IqF}?rOYBW%NSP@CvcBg>Kbq3HlPKaa?g$1$FGKw-wC)N(dyI<8!+hsNZK3_vHZy_M>-)yD}8nUv4jpO10LO5j02i$ZG zGakowi8vZw#<$H?*oPMB=qneZqNOia7(kMLb#=_?KP%Ur+FnK62k) z14=@-Bcp&M-s(jAH@VZ-DlK|Mi#P4LNoOLKvf|Aa8x6I~6}0wR7$X~VBB#?$#O5a|rA zu&|{K8;ko9TKXEgnO7mZD}`>-|?Bk6`8U9Afbt%+t2mnrZJFBO_g|=uo4#ORCw^ax@V>%NmHrCsHB^E z>);)0!v&lT$_9*fHsEqv^Vi86$)@S_--8RuD+5pGxyQwFA5{%j?l5VfATs?W3j~3+ zkELwFsS){pbZJWtup&2=m1YQE+Quhx^X_GjQwHdILJP&Ywq1WCgE%l=a zBR9(yTaHq4a;dL~>?`FLbeG?Cg>R*7DGP%gA((j~V;(ne3_7C})x^jaDg&DqpHG~} z_*bU00$FQ4f{j6sOV?lTx=QphJfUvb71Yj6L@(zqAN@A`)B<{kC@zw8f0M*<-cxT5I-dwWVcywX1t%lRgUs=U#KOZ3d|zd=ATh5n1ENpz$k!^ zrJlbYv5!^~;&&Tohg}cWSdw4;WC4m8O`Ph!@qyF@D8X4s{Q7_ueFaDQ5HotIh`Zo+ z5U{-vg_6g~%{1t$FF+82yiF7gJ4X<#p{)rMFRh^xoFNV3I1&>DxC$eGS;yw{Mp3Df zjpn4NpTkB5g_(Dt@azR>&4pNIA-fg%7zJ~Wdn1GIP_IRZ2e}XsvrqsEaO5;$_`3ku z+-HqAa-9dh_bm;v4N!+V@?bAw%NcRU8E9XG0+-~f$>f^?bOkrSCVud5F5z6Vknoh? z9I%lO)j&uj$PNl{;Q)XJ2uKAAj8#DRAdK*V8XAr75*=NM=&}~cY8&}e4}qE_hL$&m zbRZhTHu9V}ut_zF)YPZCFNQN19(|2lGz$o5#3ir+T64w-%)>5ik)5(YVI3e>YD8?8 zua-s%t!iNn#NojT0Xp4r9Zcb&An)przWqtA*(iQO9RQBY@Ch}PKRj;^Z6mxu5sS`o z4z+=ad)UzsS>#^S49s45&)P zXmcC-6{zSv5O-Iwj|?@EQWl~Nw&zR`)L&WQt+6vP5}bNT2-ZWQr&$)_&|IorkZY=Q z8rEkZd=WAU1jYmO5MfHkj{`bpd0W~b&ocW;6?vF+q%YmOy^plw-Rr~H>#f1P~?wS(8+GXo2xb1Cw(3e1bY8foZ`A{LItQrO89 z<`5`4g|fRo2zl~p8SPVj4aXdA2y=4kg z&G>)Gpanc=fk=z-=?gMl&5Kw*rLz=dEfm`h7S$=}R`Us0@D()hmE@A5J6r?*qZa@I zpnnzd{}!Wy2nYyhX=!=oe+hnriQ@m(qyCi)*xK53vP>d&3lXtK^?x>78ijmu``m|KDy@jzr?EeA=yS z>YZZxy=vB-R_?t{{k>yy*AMW$RmGEQ-BV&>Vsdh_FDO4CwkRaA^q-zoWpsKK49Ag? zQ<#zkj?b=5{A(&`NQE_|z|GN>ZQ1$YyrNQANvf!RQwho4Oyu@}xlY5@h2VUwshGFHY+Rn-5e~=w* zgY#J(ySXDTWuwr-acIc|v}J6!atzuwu~$9$w@%eEbJM)=(sF$IduaM^muh6@_xS42 z#Nt23gVo-t?e3|gv6=P3g`=*8+uutsqpKG~tIw0O>#!s5{PI@M8npNH3|6rEv$nOo zwgVH||Jiw&{@by7nmc%b84}jF{u&Zs+>f=R=fjiBo%5H!^pF2`to}+8{y%cs!}f0f ze|n)n0aU2uQkB%5Qpi}C;r^A>zXPL4rD5&#jjkXpB<^>?Fr-KnwOHs8Q)SM81d-%l zQrC}uA4XQQ|BJh`YKm)N!z>OB1PczqJwOQV8eD_BySux)G_C=HTX1)G5AN#5FMLh^GEBIOD?t(c@7 zIakOi+KF7q=rUHta-I2H*;}Mj#bAT|?r1|s^#yr28rw-n^J0}= z5y533jCH-aP!bB#XLczxhn<0Vo%a}-mYa!@lqlW(=h@4-T3vyt{?_|Em1(CQIJt1{ zhSNpMTgN2Cwm&O`x*)`bbu}i*Or68N5G;m`6XJEY%5k z*NV2eg=$r0f)-Zh>z|5>`GCb8ISel=@;OU6@_y$@&yO?jV>WIscCql=4VwBxv^U*E zMCYO;vLhZt!vUM3oIxn)iZ}!CSf;pmu_l%FI<{NWF-@r zpR8TPDTy6!zFa7snJvCb5pGR-@LelsDI=3UHjF%)bKy9H44qd$DBD{qUn_o)l$u5f zQjQrw5szDj@jV)9u`n+jUvoc=UlPh9-%4>Mu@LwzqqHbP)03tsQBJMQR7Ho5){B%M zPsOvk5wxJIQM({!_M@-EBWDt4ocRZAN)h?W@RCXO${U&I?c@F5T zhLv8du8=jY77Rs14}gIBMiQJqB$~x22Kcge)wd|8tu%nlgIqI6=im)~(O^bXJA~(U zTGdKz^orh5P=j07VLF0L&kJM0n;WX7V@@-G)6>E?f7#G^^sL?NoU}TZ$hn z<4>OTvv8U!j#VEx!hiLd9#OmDE`bh#3+k52=6o_;%=lFb0FSC zoc&56H>;~0zk=T-ah%gZK+b$Lpo9>*7vc*}FQ7-2@?>_+*sG_n}Izb<*^+^-n~R z+unLyMCj1I?hjfP1gb!%&%a(jqQ!~x{;V7nLz?r{7M4mruE|B|PnM~wrXMp^KW5sFA)d;GW9LqqfcX|n zoAA4V7@A`SNR&KWM$Jbu5(R)&_W|q6>75OjWHwPxQ*-yGXk zTU=f196adlUvO6h_*EoCF(vd)@m5mw*?7uet*pB^))$`(TJ!rXEGp^9mMolNkh0bA zDNo6^QQR00M9Z#XGZ)40?mMnxet92CZ$7U)bnrV|`aFznzHdCVzJI9pe|brSBzWw; z`9vRxn)jnvZmggZ7Fz*5$QYC9*wZ4{&r5`NnbA(HgQa35QS5iS5g($^hIjx=gH-Rf8E zk_j4e_aRjj`zi#UxuZ!A3=Q_Hgg$Qr%0#YiQ+}2Jwn9@7P!jabhRXii)JZbuEzX#0 z&ab$cC%wLd7XLa{Es>dqC;+`w6Bpri6@pNi<|g+rE3d+dL_y_ zwa(;F-4$e7TYTricgfFUiRFtqR7&NT(>q}HZ6mZ)`ra zA=SVRuT!7sPliv2h4yB~a-r#MwTsS?dd-Q8%6Hdtoa`T+Qku(Ks!p{D45#*SFKhcm z9L+Pbry5O}>xc|)t%sj3+`BS24hG$7x3lfMUNSfDQJTBqi# zH%o?*FRF%wLYr&22_Gv%T9GD!kGO*+sN@WzvZ$YkK$UcKW6#32O(M@K(Io%9XI*IF1jeE`iwmIUvRjr zsQDcXskgiNMZx-44g`EEaDPm7C(83@#c|0PG6*w-#!`S}pJqHA@@Jy4y=M!!WAj5B z_61RSk(=AKF8WfH1k4=~zQp{oy~wQ}@D#SK#BwA4@w zxo+|jNAO~K@Qt7j7CgcbGY5YKvg<5Zw5qv&Y4DOP!B9L55-`JxsD{Ve_xa);;z?tS z;vOJ-WXt33Owk;qweQVY;$p@bYLn&{jSyA_8uAM%@!)?5!{oG8?SX}hC-Q9$%Q|v- zDGcF%^h6AIzFhRBfABLb3ICiBuG$w_njBg4VBx?KsNWoHM(tJnsH+eVLCqTOu@up5 zZU7G-$!V^4QEacN?&`P{!dDV0wjD_V9fNNa9J1t>yyVB{7RARIq)7uvbJz98j@}tI zW($wD<%q1Iw3<}MoaOv_Zch1}8q1I4Kd}@#&td*p;@xf@N5L8Uj%%VN9x;F$HaKj4 zXzqjE9J{(0&X^oZh7g8h9+-)nFf<(e1HrxjF%JLOkZstTAuQn?$1xz>r@AEmekq=k zmW#eA)I=o;COv9Z-D$iz*tR)=9bhyFdI*7Cj?2XfSP2ghevFNzNm>_9S~5&Ze{i>J zPAUxxR#A`Sz)NOGNx;R4+&4FGFpp#TV?ibPQG(XyY0+ygEJjW}cEv6JFg1mjHrbli ziSIa!ohC|EG68KlIczW<$|OlQ)YYUk#hW&f)groiDJ6I$%)BuKeK|pU#8%2Yl{6ga zju*O=784~AI-MFb;uf?fksPv|P8k|)$7Sd%8L2>qxo86p((St>Q+3S~ zhD+o1TAZ0F{l5T zaF5h!PPu}26l^jDoTLXFC*()O^GXD)dE^vmq%%t8xme^G05ZLrVm!irXaLd#0e+t> zQ^=oxl5hu6uVhcQPLFF&!+Fl*i!^Np6#UjG3}4oV_Q=N)cc4Yg z(x>x#77I1RF9HSh!fJQrd$xtOgK1;E>DJr>!G7CDy{>5LYR9~RxI7JHW!TeW&P zTBfNYme8`7KrRI(l?Exzxrn(vJ#SPNZN63qFu0`75^h8jYK8bOBM z{DSkU7PO?XC#iI<7km{C9OY(PY@&k zinS%c1t5Sk6$%6misjJKJl;G^uuaNYi?{&mX&7OJhHMQqYkLSdeMlVpM)S-@{V`8$ zeF*q&xT2PHCy4JOnJ5rB&FX&z1Jx6K*Y9Wz=+~sqkvm z1h#%(hPgCptB>++MpA0~tlzQP)^ZwW{*w)#pgo79{m+WtuvYuv=h&Cg_K7j~DFXdD zf{vbM{v9LQg;n<@Y2lSqy>(C&-zrjc3NtK#6}FD2)7OmV;4}XbQpd|c=OI$f2|=sY z9yI^7=zUw~_uwvNR{e*}uB_TFFL%k50veb#xAYfOAhUkRH#&fJcS1LeeN-WOmV7du>4X zbwHnR(2#xr$^ep|3C)PtSXKd2$|Hfo(b0lXAKG9L27L%=5Y1|BFc1%5*Y4y>uMZa`7NcbSxik#2I;Dldwmlstp*y8R|F)m6zVJ%wNF>x@yM_vfkae-h=iOvMCLgJ|~u7*E6!x>lxT9(v>(prF1)WPB=}# z3$XK_#=3$#9-DsIoZ267)-DUBnay9#tDMZ z>P%^vF|e$;Js4D!YUkrp`Y?Y>HTJDaxvUt~u+f4Iyx9w8jWDdTV)25|aedGQKNp;{ zO{At5_MjF+$rs6V7Jb(Z-E6SH&vBNsi+(;!q}WS=+4E4<^G-2K@gI!bV~p5i<`R6C z8Q^B^Lzc7Fmvi2hb3d(sxv&DAm7@P+E^NjM?k^W6yI$?NZfakvKfS&I`Uec#@R?Yt zTwnHCH?CeMm4@3{-?%s*_q&1*(noM&f)8Or@QB}hdMmr;LkLmW4D#Q6=G%hN-FnWh zdgDWYVBCV+*jgM%i)7}J8f9zRl@PHAsg@B-tB=e z_dbp7v24tiT48;&#kLaXio0#Di`>s7uhsVDT#()uC5lyjm^>w%sn?wgcnoV*&} zwJOI_xsXyfqv6h-gwKUm>@0JQJ@iC5d|ElQdOw`_d}vffECO<);RADmk{h1Oz8DZO6`?t|*_V+PDD$`e8IywBBe4KXTfN z-fd>zW)!|2_BfsTz4oj>YkA`UOl5XVm7pO_QZcll-}+7kP#>@15I%?jb~SJdH}Co@-~Z_LoX55W5?0`O?rInIKse*dYX{Jan#c z1Wpm!uCad{_he3$@I%8rqQWsjzf_ea>fgYZ+|2m?VgUKw(01Ld^8>I3n07F4ncxA` ze*Rs&<@_MsJ?dJKO*K*Z%R~|ctPsdR{o8NiHx+dE2rv6ZMji3J@ZSEkQ8?AmRueTR z_ew^P`du}KQ%uHFw_*gdmLSIz40vQKNQbTK^5;Je0uT8_HK9-s<^m5kcJ<6xFmK5Z zjA}JD({Omw<)Lwp3Y)+30};Z0)C3dvCSE!!NIb+7&60aPG3xdvgB%k`pq0=nWEG%k zk+5X++kO!Dluw;Dtvy#=j#Lx>PezgU&6iI3ZoQY6UV+zsa96?ab@<2YXxHob=IbQr zb(;8XR^V-3?`^^FZRy9`O4r*OX!C7~`(*>Qe~b8?pZ9%ls_($>ox&RdKIQ!+uI~c$ z&Q1urk?*_H12M~h|AK*DH$h(!&=TH1P^eFD2?YbN7>$>vw?)FyDdh^(XLdxR@z`wl zmS%Rv<4HwhDKuvHB$E&+NioxA_odUmnoJgG%pJ&Pak*UVEj#S@q=0~Z zXE9%@f@GrMac{L$V?xjgI`#Zxv)1C`RmoR zSXZanc`u<_>u_Ve&HMAPi`gnhTdAND&>jwdi zSzQK#W4!{$F{JE;;0OwiIpE2Y?0X|f3a*5aS$O3{Pj z#ny7Z7R5EvrV+ris=pQ^beeY%C-O=v7bFhCyrDrt1zR;q6O}Q_$!(A#1}T3gDgLDL zA-9pDuiGmb{qSS{Mw;m}%&261F7mAmK@@AaG+V-F8u&mWA*V_FRf=0;3bt9>sldI0 zTX`HxbY}%&BsS$~(AP>B=kH?RSmJjH@|cpC;Mb%(MKR(5XQhwln376zA~BfC!Srn5 z=--vtrstSNgjH13y(sQUlu#WhRFjB2`u*9+X6|{|5tp3Q4Wrops2eA$xN4YYy8O{F zPnd}O9cRi`vJi;df~A(|yxyR8-a5yq&ij+?LECvw#ZAX`B4liZAH7vY%T|6RQSIEf z!B*Q~_5MN6ANn1q*`uj4l|sj7KutfCz;$U`pE$+cF!D_Yd4tpD)9_Z1_{#07_|1T8 z3mr`NO;WfXqrnuIAfAfxJSBh!RmmIYii|@U1&ws0>sJ&NU+M~NUaK?oX`;fGxxryZiYabegjl_ zr&e6{y`ab|1N0ykL6GP)Nu+)rdbWBp`s}wbOaroq9Cy*tyQxr^1d@+!!Js03Q!}SN<&ljNFW(lF{VX#8VO)Bln(+%(&~() ziZk!UCa90dTR%x@a}PwOV(#OJr%UU1Ql=nD7SslM$kZZV0n4lWWhki3Qb$5(0qdR!yB~@NoP5S>-h}8he4?@ z{<^Rlt54@8B8rPTtfmj;RCo=5X-(Z4x9Pr|Cppdb8Cdy3Geu)z!kWnvWYK*7dZN49 zCZz*REU!5c%d(^=X3eTOl09d`MM6^ko8=^K)q%3-JFa5Ocg(n-%4W)mE`5*dQ&xIx z6N~esGoCIATFcHeyLmZ5;%oJC>Dew6Ttu!m72<;9anxt8n!kxwIs~5|&x+Pp8rKYs~Fe ziQDcYWU5?LjgQ*8O=tlRc3iTiOcp)Xtr8AwQ>un$&b-b)V_Z!(RupvD`E^KZZ$1|_ zo!{F9d;o5)jizRuGTR5enUxy6)scAI7X~qmqrrR}m4Irq_xr8C@;O+&pB%demx>ty zvsitA<~=Ba$660#=n+xxG3XndP&n4F=7BGvHPPa)Av{aCLtJv##N!IEL~WqOApyCd z_=t)fRuZm}1D)FNu4&^4y0nUT>YlF-%{+n4+tN&k@Sjc(*_iF!_kB% z%@?jSmdACzPT@|XC9uRcRP21(^k~&XxCI7e?el|LhE37#a{IK8aP{zJeE4sF)T|wC zVPs76zeD}p%{t-&wTz{yRu!evhcf$d&o~nWXGmsS$clLO+vTv9K-wItEwV4fQC;Ia zE1asla80+ko>y_a?UIz^&*!l-*SOf6>FPa`j-j~LWv^=*WpejtQw7(S#_Y1HZ?7y( z{)rZew$%U9_FI?8%_2rNc1rRY1h>hpFB_=pB1)pxs(XUn7!DI#ff`CFB64{rasB(V#U%&nDBI+Q>-pk^9>-ZhuN&*(6*}Te~^)UkCvmxtYA@7Ry z-cE4@p0vz-#Y=wN^nwCsAo+LedHNCE)Y<1ns$k`zU96CDoyq z^B}|_g6~BHuF4~cal3Am3JI13QO*QW+XWv8KHWwIqhtwe*9pL?`+pwp3ay6vEYbO` z96BL0kOdbFRVEmUw_DOaFx);+(!P5kp!?fZ_lF9>6_(6Zf`Bz6-a#ZJiaS2atl(@G zp>1f+50AVd_C2f+Y`kb(gz?k812&DBK7D5IZojf zTD(7YMTDXIn@;P($)Qm7(aJ>#qJ~?gUOP2ek?AUUSrl4BnS$+3SrV-VwLQg*L^#58 z2QB++Ao|6$BVlZ!8$7)bEbqiD31BimiYpflp{O&a5KruA>G03=F z-0PLydu~V#@s}fVkgG9*7xJ)|6MrB*rQNo;5lfIQ^f1Voo-@o_LRPpfB1tSnTOw4Z z-fDhW3h~Ri`=FCELOjffinIifz92n9lJ0IOTzw=2hAq`wQrJ-VV}WFpv80PLTXqG7 zcJ%NQbPz*@WG3=R0HKtWaE5_L@Dn*pq4uahA$xJ~Nci5cd4*JYeY5@eC|`bGFkWy{ zmRLFRuuzFm&Ab#9W~T6?c(Tlx|M*BF4EcK0FrNm@uh&tY?%uY3vf4eaWfAFC>(TBc zfB;iQzV{eep0rp0Xn$~oSU6s zJN<+!-zHf#ZxEo%G8x zl1<)I$UhhhZxc?=Wyyo@*mCORX2#{;)^h&rO}%?hfPW4|4Au6lychz)KZ+)Ve@P@M zu%f9FGVH^L59sLV1Ox;;JUn0?NkG|ETwGjFPwzj{CJire@yE)_3XCK{+utEN-(h;* z0R+36tbNk#{n9`A|Dg;9BT0YgBmOW)KXAwY;YoOO z49v7mD{>9Zbq~$;iOToR{{;q<s~$T zU;LWif`fxoQc@C9e}GY?f2~fzz>@Hk%9xC**v!AQQdnuzzx^OEs+3vWl3m(XP+S3q zl!_~Ab1OQ*oYJqxuB^uSfR?w2j@QEKo}Zn=rC_U5<8W2;aBbTF7)*-keor2F&+flT z8+^|k0af&aTSDW_-IHy7e{(`$HmRa-KY#qaWa>X`Qs?AO?eD)-Qrils>g>1!92**% z?HgU_`zv_@$A*@B=T;`>{>Fv|=JzM&w?>!GdN)Ah>o? zgPl)*d8A{|zcr$*-Q&IE^P|(te~_e?|5hWqzPY=;f4TjCQ6u{Q2}1&Z7BGoK4knT8 zw+aGbQN=O}&d)An#jPXpcXu@k|lX4=Nu-7vOx1TBYLOYbUib!ANg#Gw?5o z^n*R0L`Y(#$$l3*BrV=nI12BJZoj!g?zc!hQMiS0j*@LjDq14l@mtE>p|3W=;AUXq z)F^p5RAnn>`Apo8IHEUitYh_jrQ*?Zd{;1uR30RerUTz-Qx9t9uU}RBVi)$oP5$|% zrb%o!&4Eg8QhP6sY~rUpkiO%2Z)_pR^3M_;+tG9mPX?%nThq)H+P*` zqP@JI)kS5O-=%8_@%CnqH*8wABlU-+H77VlF`Yo?Q={JdgbOfg>AhD`&hg-&6Lt`})hNuh>%8t1A&j5U{G6xuedQ53=NuacDT%V|F| zKj9@&h*;KgnJFZrcg?3Y+JV+()QT#y!@QSQ1l-9tWqI zs!$e@nbIB)1a*V6(+xr9(o6n7xV5Xt0x*7f{-iGgPPT8&5>~lR9RqRzJ{lTr>-AQp$%y&J=KWm zkPEY~Tg&RI&QKwJe1j0V&t>e(hNRnss}e}ZMcnJQvU}Z64by!ygu|_QA{g|xyc4tv z_&uQPDccfCn9BA?%cMA)Y$d0-;X>QCNm{)ePH2>4Gp@R&)}QXa?2){Dam{mwxK#J$ zy!n^p%Z2a5WZFgf?Zv5Sf8E8y-b(0;L({TnG|}>Is4si#!fq&Y1%ulr-&BxcH8)&P z=f&+49|7+BqdZcVDdo?w+GKb4_e_X&P_q-fK*mvWtG(TC%B?21r<3WB1@yZV+U9J+tW6eLUv z$r>(TA$sYJ;E^~Q5U?#L52%m9S4v*l3;Yyk~KC|sFWzBN8jCa3bk*4 z5G&Axjbf+yY*-W8d%A;FmnQJlx5n=aOe9{NdhedOHD%Wg839}4*H{fkrDF6Q%Q6=R zYla#=sn?%AjcTp$%4oK5T=Ty|Yk$!~Ap|40sx-_tCs@kfge*K`;nTJximH~!IQ1@3 zhp=^2L>F1|O5~0sQ=VJ}MPFa}>uswh^45=%s^%jgl`KO=ZVhR* z4yIhJ<$T$M9Z2nwAq9=#I4VGaMu@P?Gmrrolo2q~LnHvpqCFHig%Mf@M`>Pz7lWVv zG&oj;iFQb7CcOJl@|p*=IhPp20%B6Lz>K>B8gSf5ZFJUeivoiorc}lZUny()u86bH zLe6n?E+^kvj{ifMJUInM9zIsF#q#ub>65@BZkJNZ-@6*QQooZUX;P~rlO@VWRT5X~ z%k@7UtM#p@WOOH0Xv5NJmV3%1SFlx1-i|77X#Q57aVb^XN0g>^SZs=I_$B=ISwDrZUR{2`9YlWjQP*C zlR*iYdnZXzwW&DaCK`2GKNZT?NF7Z>>@l?g27ZSqwb$+I$>#pg*k7aF*0zaW9)|>p zDnl*2w+L<@`@YG2^@%y#p&EM}=3S^se8AtM(|Q_3f%|I5k*NVGp4PJp>y$=1z8tI0 zS%#I)oU%B6z+S8ZYO&z23x5DR#pWJ*#%1erb}Mu`7nUacQR;J1wYG)hQYVcseg&U< zAH~}*munH#7f{PuFy1zfnGZVujN04(dWbhQ!sZmxqxw<(MTZdlKWkBJs=g zE?*1dRB;ubq7;f&fuQO>a5E@rMEH!`>xvL8f$r?PlZ9A%hR!q^~JL1mRc|1 z$LPk!ripV~ub0)*oPg#b*$c>+ap_b-Vwc^&KZx=VuEG7L6U z0W)9sXh8BUqiT~kDSt_%xR!Af~J! z&)cy=T7QFmpF9Ffjr*#@e)G7A@9Lj4y>-N3$clR^e9E`-N*O^@# zj{&RqTM<90PptM&zx?0tIKMwrux9J|H!DEv^fSB)%$no zkfDXJSlDK2s6(0w&>n`c8&Vwn<<=PH7UJRa7#5I5z+n>Zix3_N3ik*`&%J|1&mBY!`MUGcT-QhM<+AI zuo=aS;wlC8#{71VnM#ZK#7X1p535c>Yi$^791?pn9Loh8clsD}5w3Y@gvI3)cS!@d zREph7WBD^2S2%zseD!fkEM6E3PN>>FQ3c*MFCGJIsM1Kl_DH}@Prz?UAY4u$dP?~B z*oi^|NaX>fNe9xk0O^;3j88x&yhLWML{^PNc8^3(5Li*wlK9WHQ=%YVk}y}&H;p7Q zk0gl^MW~)&gc)EWN$|H4eU)Jh7A`ay4GFEn1Z2o$V|69vW`&$ap!9IiIT=s^H!%KB za&8gO2!Q_CBSnWRD3K}I9FS%=J}aInyH6u~%ssn22x0{fScH*d01^bmcSE-wdrf;Nb{qjuN20ovc*jZ;sF;4- zSwOkkXU&yDwk;|4sd*o30N+M9@UMO}YXJJGb79I78UO%H1sES>ljUP%3`I-shgNP>O{E|VTHmWIEIJ_d2|R5^E^K7}lm)OM;s;dgkD@}! zV2s508%aKsOae`yw$SGTNr)r7ALg!5Q}y|j7O)id%J%k9pO>?`Z?YsZlK3@#Cg&nJ zfZf>7h5GnKhTKKqERm^ak$FauWowc3N|Ehz5x8yS$X)ELS?uar?4D8V*;?$qQtbO& z?2lg($XybwSrY155}r{K*;*0}S}BQrE{Vr4{rB35p9&#R5IkETcu$w+a66@ym8NmK z=CzjQfN`LVvQRDnkGewDGrExd$6uPM%c|%?B(eq(2>~-@bt~mHE9JI@HUtjkRN?8! z-vQCnoZX|6VNifd==8aIn>yiiBZ+cNuJq)Vimbi#c|@_5*0hC`^z~LrhvNh*C;%T5 z0iR&nW`@8-MioYN70HUrWm#1uMgfxs;DAdJp&Obh((ySG;`QX08l4LyPc_IAxHiJE zVc~=%oo(%_9C+U_W0}=7Fa7* zR;#yIi-B0jBKesSr0K`Z3Fwie4<)1TnJfmS-0dW> z1#K!05C;n%wA|(M>Se4-AJQ76qjZx7%Os|&AnwbJttzJn(fUUVyu`6IqX?{3(c3*6 zlZ+dkKU?;eH8x9GxgIv^tzsprqDw%)yJdSB8MZ{0hbg^aQeQQBvYB79z=P9OPTei(r}RPjtre%OZag+!WNno^ zztp8$i?pz9Q~?GGkmM?m2Hkb!@a?@XsQp&$vSICgTJ4mXZo1Mffhp~MQBDix?MA5` z%VX}M*Ny%l9&@}G$6W%y2BWBq;`%mI28?QM43a49&w%qWj!S|LxuMPrq^@Y{w9N=D zYjzq5rY;PBm~kXW2>Naq>#hkc0Hihxw05_%8pH0Wq8fqm0vRlgKa^r_*L746{&KzuU~2=K!F7?4LvQ{ry>ThuO{OTqp6g3 z4V#4r_V)S0({qe-0H(Vlha09jJ0*|@EIDh@WCr9oX>d>S0(W}V&qAmz;a!=2>Q%%y z9uJrhh6(D!TC5G)61vJ<4T1?HXYCR)4tyPc;uuNt_Dk^|xqraSu=WXO(#V$aPbVBb;utMJ_C@g+eWR{dEg8KZYOF%` zttK369vZE0AGs>jZ6fq-tQc#{@^&~I`|_v1>(#qMd%PrTtUr3Z$E;!0dUX8NBLj9~ zCd*?^d*aA#Vu^n2sd1v)ZCp)yVq>joig&UBoHsi2+{#j_%bIj9p12_Nz8crO=5?RT z8adaVvgeqpE}RM+ni4*k@`s;>VwhOho~{y~M)=^l(?0FHIE^ylhW2U3lVb+cX9hQW z2ESv5aD9g8ZHDC2)G6UC$a|WC&vm-J7SU(cv3QnBN0na3g^^*L3G``>FLhQ_Y|cJJ z5z%~(R=k6jZEmc6jygG+f1);*cO2VC$;@S5jCx+Wa-7O!UarzjS?9NY>J){`Z}qpi zM_gs?_21Muzl92almDJK%>Jz(qga=|pl-HcH@skTzMulXs3x24B)do?zQAX)XwIkT zp1tV#=IraEm^9)W#OD%XqX?E%MPxg8+o=1!p~k!|DVi;YzM+QOEGvX9M^`ROA}Aq3 zz$boibclzTJY1$s&WICS78pkR`DuZW15o_dD*Ds9Ojfbte1($}?I%O)NAVzl{wgxi zAYolixnng})*t42)&1H5>-%bdHvMJFS}xdGRY^X{u!@PZ-Us4a|3Fs3Z?aw)vktR_ zRg_Aa^v8wrU#|0ZFByK12 zIlD%a`(Bc#Y-%gQ8;Vi39+y(Ha&m*g+&J1f;MLmwui(a zfvNfBfROk)rpL6#$bOd1MFy#i4OT}j@^#Q`z) zKVk(uh~k!10x-wg-Iq2mm>v+!l8MYzdm>TMKrkr(OC*w{BXCeWo(zkZD`K`Q6+k@! zCXq}f|0R*;4&`%&LQp6*=V=rqK*|e*5)nYz5*EEd-v3S_{XSKzh9a(XMszA0Oa1=4 zDjV;=l1N&M7c(_bKjlJbtIu@017K09{*p))(yQ-3N7NZq`oSbpk@oV!Xw%sC8QhC1I!(&W)I z3*Q&9^zntduF0W3=ih-zB(AL4VLEtiW>KM5WG7knRcqVvyBz51=#NvZXhIyf^G@4f`zBhNz$U&>gI4eqhP9BqIZc$*CW~j58Ra6kcYM_(Z zoo7Xp*xhwhR@HK0D^`qQO`MZE^txBocIu#6xI2=$?}l-~a#c6{u#?=yxGG zCXpQYQU+ylm%%|ZQB~|mfp%#j#jLdjG=k$z$DTXoG^IZWmYf=*JcpVdC>Ll zu-4yn{n_oTYW0Ayixh~&$l1o%sc#tNP2kEY;rryH56duk=b|f;wPauv%QJa_LI~&X zZVVJS6AVQs3U7u)Fig9d38`Z0kEh~pONoS{D$sXYPd|}`^jOc(UAJL0z+-3v#e-dW z*jq&4BkedDN%RBAC=BR<=}>kV&U4?@I$Rbk7J2f0Opbc57!7khH+u<2jSkYSHu3;_ ziCw)s&ZvBC7(7fQf{-K^lUX*B{tEsO$Y%)n>@$6r5w-#{)LYIJOm04uL3Fer@4Meq ztNA_}G(iuH^^czdv4g2Q-7_7m0pI05=ce}fBy}^yMs<7$Zo!U3yC49w_cACL7Ye;q0){E{d-S(v zLu@`8fN=Ep7&Hq(?28961R(z)4t z+K0qv3J%j-A{}zH_lHnF@tDcfy=Q7_lrpyST7Sub4SJf4x|(owyDem~bBk}CxdrC( z;YLcM>Q^E^vTE{LKqe+V4TGU!9a_fXHm|rSLx@+?<)`QU%Nt_ zoz02)4n+8?YvH}Opi$i+Fj3&4f|&dD;l}bvF;tl-jP;cjN{_yMoSo|mu=^>}AdOcW z-@Mu2?8Zc(MsyoqDZCU}qEuL>x{(%w_G+t#HVvipaYwltJ1|a#(n=$YdE#Z6q#WG} zZ?}40x%xz*qKDZ^=e+D=eLfZcpvHD(vDUzHnK-iH#LNc%{E=yHZc~e0=ak zb1f9R(ZeQ7$kIxy^+2^bah*YP=1Of|xDjm;&(`UKmUcZidrJUAuyMARPMxq@M#jFi z<#~wCm7Gf3!!4b#uT}U|s9Fd9Cp$dj)%D2@*N)p5V=phQc#&7t&b$3fSfsDItP(h+ zPn9;I&tCe-Vmn>aHuNGW*IV{`YJ zz_4`BxG8Vb(S#SAY}TS%eA4{Wm<5VS&WD)K0&P{}F6=DHbKd3>9N|-ms$-(qd}ut< zT(g;`D*0GG7II-LLP=C?iG0~jT+&Zt`CwpEF2<7aN6YWJM)^{kw-Gf0o5@-t=1QNA zEUi@TMe)@JbzefX|5TR#k%`EIC;Sq~Fz||rgoFe@Mgv<#z(YPZAq64j7jgMXE8A`85tQ>RaISG-G2xEf3+hrMt=JG`rw)0#l;1@^aGslKYHHF z82r_aD4GN-T81fE{l`3_>-9t5G1lBQ#@Hpn%stW4E7`^;4LtT!hk!T!N9E8|JO6a2 zz)bhBAI8BYRzZ2@5x@S5NW${Gqw*b-x;%i@dQHz>`BVBuFIJVW#%=FDO>f|JKPU(+ zvJ8)ih)haKN=VHCZ~OtVg@N%!K}n_I$>4Gmc;l~0&CJcn`I(Si8&>vr>Ceh7NXo4T z&-}oeuH2tR|840ntnLh{+6?P>kLUt{XMS+Gsj_JpEFURppQ~;G&-`Q2-JqoY_q0J! z)(EKK@4!D%GqCa3KQgk|F|zz?^ek`euX&_pe7o-V-)X<|1O(podq)1*^~dLirop>XAVH~N1!>dTV(%a z|M>j)pDiEk7TLN7o&I%;JRLuRu5a(bbN*kw$lLq>XZ!m9g^vTC@M-_bMD%;4Q<3Su zl}wX}NPL2$EC>d(@BvuVreLeczcLX*jjxLTnedr^0;&I*@G+2)|DEt1UgSE6zwRH<2Sznk+m)Icg8 zhy}mV;Dz>OFanLzvcCD+PNGl9B?B|7`RjCQEcsMDZAZK@0H>;?69<+ z6h?`#RiTR*P-D@`KaqhEL5;k>CLIkNj&6ERzF+iBZ87?Ogi@(`;t3 z8?U!>bHt)%6TVn4F6Bi%b0AZlwsw!2+Np9J=~7#V&W_!ef#y{*AE^L=$*Gr4cd_kx z(qL`>iLc_hCI)NHTY)^XL;6OFI*Q6FWV9;D%7r@NDxu1i;v1eM3n{wc6pdl4LSEOd z#F6-T|AoD`3aX=j{50`%2pS}~LvVs6xZA-cxCeI#?(Po3-QC?K!S&$5-8DdPa^~cH ze>MA`+S$3;sja=3%f9I9s=n)fzR%|grFL*7~OWVr3P6c<~OC0dl|QstCy*lLs? zm58w%EG9)K$OW3%2koaP#!P-pm(B*sjDCw2T%j+_<9z$(C_h}LyeyxOC2cQBX^eX` zA%H!d&>}yi^h=^~jI^1iRf?y2M##_9+6x=YRs2duxZdWdY~yQaLlmMFpaggQz^@_ z&Z)Xu;3Cr}eWlq&Lu2g|hUXd?q4odtCu6Pa_eSQ2dT<3oUH1dKHmfuM1=_nr_>{%k zk7=!uFaU3UPvTDDVxC->hF|Kud|1|Hw0?v%48%TGoP&C&%hpELLBAT8v`+NSMr*W#|5+SCC`Shfoo8wT%$)~fL z-kRm}yVyfRY^Hh-8kWz7I+P~lDJi|)glqD3%T(N_ zN8EM0VeoG(+uQeCl*iQeG@se0_?Gq<nNIxe9okj_W0 z!OfKv(iVjk@(_mc9@PIv`zjEBA`gixt>5njo;K-<93Tbyj+F=w;(nWttTFN(tAI5G z%LZDywCKlUkq+UU_<~}qNs+Ln6ei410S^&tNhU-36;AR(ZWE0^fKQnaNQ(Lv-UGYw z!TsvLrY`xTk^iPH*%RM}n#mOsj)T5o*8GZbm@mlN0S$BS*wDC4>=GuFb`>4{iZj)v zBnK=@(5FlWbWjvg?t{Kb@Loq+co$I;(T_?@)hB+-LVk}s+IIDDiIquRL@ri7tSW*P z5-$$K6OkShl59wJ_NHOl290VBsmQcc?aDNL8`pFl|7Lt*N-RY`!AaNpcP2K>EI(MCPhD8h5|@g#D~z)@;^$-d5nGOK1Yk#n}$c z?kFf7>=dOLwf14s1ER=;)tE~jNy)zKA;Z*=nEdKZ%a5HgX2X6Pgl>AoPeV8pw!)fx zCSE4NWu+YBI3IQHYz|r~pYm1U%%>@)6K5M6iR-v6W{sgI7l<6o@WsjJWSc)o;8RdkmA4+F-%$_kAo28e>lJAmA68owKJDu zXs&phg)HlwXGsDxTVXD5NT9sEfO-UjYa)KC4`^G^ZtF*DBDXdmTJ2?TK!|tuIWxO# zeQRUb()fQz_|V8y8@+r4wvvd%uInC6ml7Pm**q_m^!-PGk)89nS3K|w7pRV&qA-4M zV~QHo?E&wganQL=R{mae>-ZR)NMXl$k9B;_r9LJ#9t$Qw{)h}}?mEavD5gmvhkMJ^kCle# zNy7FkE+6mp$eGP-F2c^ah(qsqFew3xZcF41-8Na_&=Xnf#_!tRgfqxh$IsMdt2dl6 zaD)0@#H)Yq+P)=R@CAAO+!q}G+-iI2ZBV#*j`YBWF1Qd7RvfJWZo&rf{j${c-X*ht zkYn{VkNv>E$GBW1qWcFS2snGN@bhsx?9Yj5Qo`XmqUTtgej>Y7FzGEgT&!F0Iz3+C zT+hH`eM$eORiiaG9>@FRQ@B!JFW>bygBLl{0MvO~UxHBw`1#?t7*g>)cdgT}7haI( zEsS2s!?5C?>rBYYkz()D()6FZPRQ$3T<^=F;{P1sBWU_VcS?b2{%_j+QGfcQKll^B z$9zlsbzS4@bErJ(64o)-TWk>KwwnW9_}AAK%`IAoLo@qHjkixJ4wT%1boD+?`4aET zFv);{OlfiisaUga=Io%i9D%%?v_A6Nz+^{3`Y>u*x37bT?+p9_6>PlDf%NH^!SrQx zDi4~|CLzJsPOTd7`rL3N4)77I?+|d2S-~)9Fz^X=YTLukX5pb$_%3F9q2_6!))qb+ zZn!33SViGbZE7m>BN0oW>mDE+jXa!HINZ!6JiIJ?3(|_~?*Jc9{!ZtXR%8w)oYptx zCuiD-w{BB})VGLDH(bz&SMmc_*+ImLn|sAWSlNTyPAU$&DA1-4DR?VfpPK3enDc{S zi0@*Ir%@rU?7ms-6 z2IrRqcSK922#&+KLf8cc94}dY_J^ZmMI1kfzmcLFyNi7%?UybLWNY|;iSW~tWZILU zu_%Sdq$OA6gLguz%lLA6Un5nhGAB# z)0h*aGAPpsI|@1y1U7x7wX;km40p-H3DI#+4V2dOPv;A2|JwXJ)z2{m1=m{%3z-WF z=^fw$oYLHuspIL>lgeYLLemp?(lrWv(=p-09x%`_;n5!T3$-#z(=!NKG6KUhjz)YE zlrjR_LZ8(#HG?B)OENVEGBF+_gG&v5fs6({eAx@&O z@Nk?>-je$w?aQ!*2=@t*3v2}S!<9@FertQYL@lW^NQ0C zitn_(eCa6Gdn#UaL)OW#G?Fl|iIkwcDj|JWs=-;R5{mpW9x>@b>w84z)9=!5EiV5R z6Y2U=pA$vD1uHTLn3L=(?)P9>?3;43_s~2+ndypg7&LU3AOS&EW8XoH8G|9)LbR&T z&*!Zu_N>53skm#XNbfM#2q-h7(5n7~B$J0=EL@&oh1^zA*>&=T;l8pnBUk!UW!4)D zWpS-h^@NvwS^~=|3Z!bDdy|os(jy+Nv^=DstMc0rWbZztjg>E;et>s;b!bO<5_ioT zE1RW^vhxmG=`Zl3kruz8VsM+Uk;3KS;a_CxDqXYQWZI&x z)-9RU@deevqts{J)jEXJzpJ!;)~+X7wH&#xr{rs()@gW;V)xPE|9MP=x3iIV2+053 zC`{BO%GZP`St^cVCh66rpVA~VZYsChq#des_NMvs`({->Gj*?KgOq0NRa4#7W}Ulc z!%R~nz7`Gj7Bd}F=$?q0m&E7s7U`B22NY9BzE%bGR@ZS8=$?p7ORIO3i6Wz--?OnV zqg2qTaY&R}*s5{FxLQ=FaSUTyoUCyIUwiavOA3*xeP+8*OM6yjdG4u6j&)nUPDhDX zM_FYnXmLYuIuCtxrFnd<`dQ=a(H=j#M zGj%bZO-^*w7KZqqesoVr^fnnASDtohzVWyz6gmj%x)2k39yk7l;*i1)3^JrUO726k z>HW_8IgL-&&e`TUqJnFwhu5`_8^5jT06=+#=+UQdYzXJ&k4z=kirppsExz+vt&gS3 zjFkAtAH*M6Hd35bMjT8*JTKMrO+U0$`!!X|1SY-+qe>kGYM&3T8-$z*nvSkIeqzPg;b-#FE(GaUNA(xB}~1C@KT1X&qPvphU~Kj zzeY=#$qm0v8PaPC^{5(N|2V{@E9Hwif;}{>cRL&k>Cy}IR&a10ZYv*&sxngJA7w)t zT9brz1M9o9!hVqj*-qHP<&P?Bvu5j#4F>AE@eik<8i%Zng~^RLqKV)nPzw83>6hi2T81bY70`h^JVda{WsrW!V`NTQD&Tf{Rzv`3~=k$^8^hNW8 ziE7zRbj=?d{nv@1U(pgbx?tFM!%xK1FI94=w%}M4sm&}fX%krN>oj(^9=iOrE+2(tb|$4XMxB1HAAT<466jeDYo3N?mXtS| zbvEkXDedC85*aC4K51I$4RA-+Pjwh8n-HvQUapU!iKkgwRDY{G9P+t)6&t)7bX@Ag zkF51&CAOJFaK)NHWNadat}A<8?v1uDWO7iEdDS^~^&6jgi zr;tA<_4>dmmaC!WOAAa9B)_X3-}C*cs~^pmW_cHX{#@QET)Z>TeHOfY`{7sa#V;}; zU32ow5kX1n&C?>5Gg>lTdPwf|;Kn7D;x#PUO`i)AKiN5A?iustaevJX`}7TG?TN+J zIW#&I=8uG{c-!rQWC6ZutNF#{cZGxTyVvxVqxOWd_m-Iqz*_seljgT>?a3#MJ8B_- zvEp5O2-0VJ*cSGC=UjM33`t9v)3I29$$N?r$=poo1Cfx4<)*sgF77&w*G=}~p$@&;l2a{?q{ZKw+_kHh?8(%eC z+Ck{|=Q#M5ICxHS=4L>(g zLNKH>J;6m-*@`9|bLk=x(m~pac=BscE@yuczFpmz*-;y=go9OgOg2>@3)97NwRHeG#3{;(~> zP{B?R#T3ZdgusA~hmBG>Y`7}ivfMIq2}{fWWGuN+uTQc*}NZQ zw>$%pep7XnexHdjS|mppU{wLKd%BXLE51DmWng;*fB31*TG-Q!3L_j4z-v{O&xpfo zG8qc}5R~R+8#^vaQnxxTPBW`GE}E2 zZv;%@jKhfMoV>La{p;;9EmdE@w3xW&Q&F-38$TZqlU(|9NbJcYm|ClPxIi%Xs z!vO~F6-vB((|F6vzzaqAHw$hCz9BjqTD&;F=r%ljP!M8#vDMwb{2dd?^W(}E+lmFU zXy%Jz`np3A{@uea3DtY2STUp?`~tD9Iy{pU9oI+Gv}COI9&VY75BgF2F~<98UU!e? zd0shM%-l9L_=i!4TRavenXXUAUSaB|>yUs1mbQ)J{6$aen$82|6aPwmYIDdD_Ydo) zIp~o<=L+5hUHCct3-{~MLjMBpJ_J=*Nejd+6muIZyYI~Lj!IE z)z>k`)-3BDJdJm;qFX*MU$Z~p`8dz&O|6~#9bdiNwBu&%p3NGk`rP?&9P+tD@)*53 z_2U+Z8LtH4`96r*E_v^*ajlRz2cEwF<8f3t41QSUvemuc7tx?LKJL8#<8@l*r*l&P zyQ$~!yJkcNYNte{*3yOiH2>#HO zI7Js0vXq5rR2i6!W$z1yaacj#7A6I+ZXQOA`@nO+0j0RO5q5Ss7hxbKMIPH1ToL1P zS~KOSqQ-5+Y6}TmJLPC&8*LoFg+Z(whwxN#W1{soDuSV}fx;qG$i3m;xek=$FgSJz zY%RW{Tqwr}?HQ8^%@0c84nzifaih}h&fXvTO zkXiH($V5g#BP1k*@=IbGRvH=_W@cs@HX&YKUK%!GhEEdQ(gytUMo^Z?ui`8&E-t5_ z3}u;`nwlc&_E4NDs^KA_BWvVmZtp4kAAT96W)Z4x6|QX)p=uuwm6i4WBFs2r z=LBo-6kFfFva(K8=2!m=v&bgfZ@vH8$zGB9e|6;KKF_@A@bK`&#KgZyGOjo%p#&O9 z2v4buN~?k*$$z!uu!^>S%;U!N;?|ss?!1EH!qTeZiiZ5Ep326qfU3>3mj3AW%ZMIG zde?qYU4Lcs02E2qw*5^a)OQRw^^C{%L!e0nD3Z(^fmDBAZSS9i^2nZ%g|4yH-kGJs z$-lyJ{^lPjm26mmwEQC+7i>YG8HDbmKLdYD2+L66czkvZytwgwcE4}_Ox z`?>a4FP_}{v$%5rEgr1zp8U%r*UtW97(=P#F4QnS`5Qery|_NOdi_f!uODx2@BTrO zum1;0{(pcl|9u1$WCD?;Y%Sbx_B5q+nb4z|G3Bqs>(&9 z-=Hq?K)CVn7__|T>6|DEEiZCAIie;=lul=bqJEta4J=d&lL}&xA8R82T&$2F>eA6< zrBtEbX!S8^cX;vN@}et!28QWe1#yr!T;m^GeMc9BlNb0x1Lm~w` zDbzX^+@{-&M- zs=|~)pI~>@PFG0gJ90#p@$q7KH^X+wy-3k{%)M0JW2OBt$7kx{P?`@Za{n`~q(yeJ zrh0mDO66CAgCeZ}X-g|(2A51x%j=NT^j;D;&>J+)c(?@b0P4eR?pW=Ua$a-@Ls3~# zhD_1723N_`%GQH1usSNM>+RCC+zffN3A8e^X^)HNwPnt&83Uj2N*z6T zLD9`UCx?-~upsib;z-7_T88{gyEncKjES8mW1ZyPB}3L9-0-(iE;}|5QMHrbu~ga= zW>Y+^G%YDu+5Rv!^~7y;My4JX!Z-h?y!i5cnA{CoUZh;*1dh@?u?)XV zkCBZN-^hO|l)FLU+4MG_roKdV9(&Kj(=;MVCg7+=%5csJ4y*ZnJI~%qTTda5*HFKx z>UQ2BuOBAB{?jP6nr*_YwA*~eYIvY!c}lQie$}*6((R|ZP6+#w+a^TbbyF3B_AqCG zq3|#rN{0S%5L%?!K_vTz_G?|Rq{qU0?ddGBBT+Yo(Nm#5(uy^U7 z-$Ds)SqZ02OLlxinVU5os~z8%JTJ{}(7VpUF{Zz650TY=l&U+-dAR{Mu0P%M5*fT+ zjflm0-cF`Y`CKIolRn??rB3r)=oC)B{_bns^tzkJBNKQzjT7>{IykKD{^K=g-wpYR zz45YFDgf*I!8;?9^a5w37m4>O05d5YVZmH*^2Yw{fhHPEg}agw>Hc`ytHaf2Vbe-CVTEZG8Jz+$6 zlQtq(!k#)hVa9ut4vsG2ER~+L(!R;~IZ^Vdb#&6s^Coi(wUm2Udde~5ChJJ9ly_-# z%C+Mr`zpGW|4@3`bLA%IVWL#72C8d)WR zBDQc1j{Kx7fR#q0J`gAQ=H0gr&Twu@@wd8Lfs|!Q z#mqkC3T|Vcok#;Q2|*h0oO!c3gle$`SXSlX&hsT5Y?5S{Cjg_p`HBiQNv&`zctOlr zG0oqV=Ftg+8DNBuO1M=PG=+I4NsBG9Z_)X#Ds&EImO55`*SJqs>feto_51~yXiUP0 zqJiXfpgIHN??9Dn_K9$WdP^eE7Yr1wOQi^P2F%_+PAFBrZy2Xr#LJ`unMw!u7SxYSo_pLkx7`8)I@Lc8I@!Qf7kAKLE2IvXuN<+^uhYCY;h z^=k)55YhY6;B~Js+85o7?A zgQ?D%iWppe5Z~1)iL9}|EsYu=M$(R!A)m*}`Z&mF_bZCc8~Cntd=O884eT%gAWHSe z;GO-dgFdsX^2$A;M%54(AZI{Py^#pB>HJ3@rpQucKs|!t5^f4XR+$p}J@=md- zSnje?pKEDB^!Vs>v$mp&AwFD`&3xmKZGDcPxRv3X0QV>E^v@Su!$#h_aHnZIk}d8NtQ-Cz8jro0hppQ1p*OvAFjhwh)4^{Y4-PBX^%T z7w>q8!uBh}>%JhKhq?(Z1D<9d+%Hrp65hJliufv>`<=S+FQOl3ew??3fv?(j{1HTv0R(CxH}<;R0`%GCjAvM9H=hj zAJQ(?a{vKbl?z@yjFXXI%BVe#3S6$|ItrH&(=i-Z>juwp`NK=py_^I*&%OWIha|7` zdPc=mnDpJ}oUg#lSm?L+XNRl6& zd)S92~NM?Ts8{on67PM!E{)jn&BJY#L?OO>yT`UAQXsJ{vX4+BP0WmG|3~9 z!m(t7Y0Mqm@&n9}9zNfvM0`7<>d~+(`e`L{t6TaI5x`BQQU}jRj_8#d=>?2x07bzV zM`2lrbE^RBxuaM`-9=r2@?co}IaqmckdI09$OFdMNOb95^k`eOS)0{#TD14QR7iXb zxGko9K8A1(c1u%Xz(N#M<|u;ic_1Ns{4@5_IhKZ#iiBKs&ppOdJnjxi#rrenIXrHQ zI_}0DsHhZ&24%D4F^`~lq=@)8(lTr+@x?pwFw%PZA&5d(@S2z*LCy&T?FqO%GQHsm zggnvb)bVr(rdlPS5|AlfxeW8N>)CB0ttzIe#J2#53DBGzksJ9NuLqI{g#wdsm@O`j zd6=8{ql$7^lC+izE5KRaQbm!+MVUTX7CBjMRQYqdt5$ikARdC;axyyNSHp;8qemr~ z1o#uP6!T*xp6htqM@6b%8lYU{mvQaBkWX^o>9@BF}?(? z#>;!L^3?KVHhGBGXl33wXSR*Xd)66uK4$hsh;+dRySJZ#<^ zT+e)bt54$b`NS*vq!n^M9`h-A3#hdV1jLX`t`H6U3z$|4m{%mtFbmmv3puq5KY12% z^A^5;!;St0)&lI$q>5?P2Md@Dyd}`Y-!2rc5JhJzLNF@2r`MEzDnxD*m6s{{WiF%2 z!-@4q{c}eVy>oFeh1|f;V*QmuRnIU?>Jo1F&>j!|x)2<>K0p<`pSld8t6>akTJblW z0@FyHs-r}Rc`;i=BuSdAUt|uS1W*MM56?r67;Gq|`QtCkM8}i!B`hw$rIO$BBsPq3 z9w^UwQ?Zy-mh8kHCJn67U?}Ix_+sK&R_Zl}Q=m!(6i`b8{f@1vP%N`j*58K}-G?O} zmFy*~`e7y8r2PqLrLxBpr~*@kwgs!AlwNyM1!kz8f1_ZwqO6~cC=7!jP#@LxK)e1_ zt>sX4(o{`?NF_8_;}%R6idoJ+DmzN}>EsEc#Y(y87rd)dtuYQjf4jDnx-OuQb0U)M zv7@lbxfZ#yuA!-l*tqiQsIC^Fo@lNPr&9_+mK#Zy9Y3>v8~;K8 zX^M8LBPfLW$1*1wb+UZTR(nkmKN_i{npM3xb)y>eiDaa_>WxojL94MEUM;E4wJPH+ z-6qWrr?Pr{t$8LT){N{%)~zu~ND755>^A^!J{ilXTK2})AZrP2K5a4VmWWDOvFEl% zgl6i@R{Ws0L`Kk`HNnQW{!G4R-njor}unuBN4|H5ZGzmm6_B**VviA-{le9m0a1C z%GYHpLOA~nO0wp-g8b}KnCVVR>f&)?znAIJGbsUAwjSwpoe)VMRCWzy_WbIUI78{# zTB!4P?~UN>rKf7^3c-Co?v0x7A#~CUbimaVGeEcLv!~97iDvh&>%-s8!CVt7lH~#t zH@7@#5>$awbovP!sfmcclRj`#S#vy&b+hpI&=G?+i8vm$yAs>Fp@oD%&VCZH?^}%& ztCc@kKXTvku?w#8Uv&y|>kf!!NpQ&Zqjd478B?r!eV0Fz;Lqwq=HnWlBhWYl;jWp? z%=Q^{N$O>E__GpAGYzTh4k<9PbLsTM{pjAB8?sxIV6++NqQNnW7H)GK{%A7%C8*u< zOh5l^k`sJyAOv;9Flk6{;v)rcW}wOlFA1ySxtC^QjtlbRJEW?TW(U z0cv#7icHvvH`GMaOma+6HjYeXiD6{a1`2mQk9NbAM=VW9t};2`=`xuRPq}hVg|GDq zXJH>@Nv=jmsCrLHzf8GvPEj=RWZO)822Ti|^%Z%Sy%0;9)>(XZ00XnZ0C_|n4gmTq z81ogZ#|k#&L{!ZK;|m~t!k!^M2OA2{7>Fa{#mpd+AQ7$4yk$lrKbN4iouT#tlljcj zorCQltcZ-05|rz+9|UID1?HUkz+BZ5JU%m2)nIj2fPlc9I_A6%=e$HVSal0YI%bxC za$a+9o&{}zkeNg970hP4ps_d48v|A~oP|osPKJwywh~72^CqtgEJ2G-bqm&d61D=1 zpOqHaf)+pOE!nIuYUv?@d=~Z4=6wYu+^Xl41r|uU=fh&4wc;67;UyL)fJOCE+^cwm zz`T{-vIW{w`nh;!_FP^zdy4HcNA+wznnWS~;1Z0)PRunKauq5H%d74+41}?4r;5VzwdM4U!Hy;@>KQ zN*$s;+PWM941jzVN_bAXH%@F}J~bk8Vs2hDZ;Ee$N98vpi#D*yX90a1r_3PEC--Juo) z*nwBgP=CBl3*T+sf~Rm_Q=_7W-(^b#U~O>W*lpvX!-&Z*kNE(^gyBW&)-cY0+6Ln& zA;pEROzgLAr8Vk&6ow_y0Ms|&y;&3^`OV zS0#nFe%T_}UaeUM?*+pk;DKQ%9FQcgu?`M*;NDVwBHxz`W$2;6^l$?PKzxlY&-N|h z4~zs4&SGFbiNRa@0&KPpI9cH_{X6sV5#00{DC&^>hIh7GVM}~Z%5qLBHUNQj6~*k{ zba^KYb|+OACupqR_pkdf1h+}Siza_o*qn}&1lPvT zcWqTKoVU&(Fz1LOfWtqRFp3vGIh0LEM}Zq(%XYTHa*l!of$bYd2r%$i81Qilh_56t zB&3&GtY;naJ5;`i4CGSiZ>e%}Sn>r=yf^lI(W$gp_GyIorSd5^AV_>l7uTvA`~JI| zr!la2EU@1NHKjmLO6-^(Ja6ESi03_|6MdzQ| z6dzM^=ky!^q!-UlBQ^6J%Sh$Y2P7g?{%1KJ~ac05;2H{KfR#xA-1TSfR_w)V4r zq}LkFn7T^o${1Qjus>K^ZX6#`In?h8Ds3QQ$W^N~TVMHY-JNgg+7F4G;oQ!xbGbZN zU%kIfXfPieb?3XtV(I%^MOgDV6rCx?Bjf~iV-3MqWHbAQSLL zo4!xaSHGZD1dNwgpO?qqm$|WyK3>8I1Vw^S?-*J|U?jAMy2vI<1rQiwR*`=|X5GV_ z!w)o)Td>&e6cL^1{nn4Gzg2`^br?Fjtl~G4a?^Rp8vj%gU<-= z)pmw86u20CqriW2E2n@rr>cm_`WpvYMbO&25knA?M*VlB7U|!ST6HKG%Krxp5mA32 zf+8UX76wKp8WwJ9Rv{=7g7Toho3(28P#&bFrUqp|Vp<-u27byqmY?+;rM~!qzWAws zu~RegH8iuev9)(}boB7>fcCT%EkdAfo3crel5HF`sjcr2ZRivSRocwl6Ro{c?EErx zqB87)GN6OCz9EU$3BCWuw4qeUA+E(ap%Kc4?7sE+R&JVhK|;c#qoQMClX4SNpp59h zZqq`&wd$D6y5x+K?A-jsoW`J%#_)=^to*8^{N|Lxw)CQwjN-O`ff2N)U0m4+?P*sw zbjMXqLzz)}^+0M%Ka?Ehw#)=pZ->_HhPGS=cR`>Osi+RBv<*TLQcc@16d~1h3^sO; zxAjgy#kT)Yq)|xc_o;?KaP#OUbiB56da-+Ay?6=&U9N>9B&gN)?`Cb+#l?@&xxese za(;Yv6$+2$es1>9>`%;ZLHW_h>h;*>BUEWy`DdYaa`(^t*8ax!!TQb-c>ixJd-vdE z|McSc^e;L3@58j$|CnshVcP$Ljs7=cBPbXmLiWA|<%t9#Vlarivwjf^#Ke~LE&>JR zhQrfhO@!AcNJfx}MG{M2?@~t5{2i%nFcl{i(H+Z@=Ag#I`3N1U9sNud&M6Qy8;oE{ zUBpQl8L29RLpf7Ik;@(eJ@Btqq0wkXvr;(nFBl?9nF2Ie%*DPMyW~rSqL6f`(Jk#t zwjnU;zl1B5Z6?#+{~?*ce!u;L-JVi^;^+SKkXYfAxXhL1d_{7xLQw`m<>Hi8t1Fs( zN0ViNnPR2nbM5)sQXP?C6^e5H#}!`pfx+|j;1>}#D$ITlU)xM+TH&E>bl zkMqmGI1mpdLO>xF#5mWC^i+)|E^|R0>5-Ej8OsLM2r% zBwO!&z7;`i*}gg%@AWVlX=q!q<*DU?dZYvF^)#wY%ke>`!w~&pmh;%-v=GlnNAqm& zyJPcQw}Ym`+~9X7=6QiNmPZBAJrNf1L7y1P^Wz9VsuX=Qdt;IQMLN8^ByS~xHa#+w z_lFQ`+R8!p@mHC7@Ahs8EjSy>*iNh44k}J-y3`py*Y+VX+SEm$Tc6c`Uo4_+nE2#X znGna#Sl#qd-kP}q$F-D1dC8TLseB_e)4Edq7h!eV5xR~|$63udOUFXbYE8oR6yN9W zW4lz`5QOb0mbO3oeDA9dbE3?9+X#uTnlD)7Y`f5PP`(aeh{^nFVp8*D8v-2i&J2-< zF*USd#xVUFc#j?BIM!V=aa{xM$zqacuOzCL1W@VTOz~eX4y4_dioDSOmD;O#h2FQQ|32*a&$=Sl<@d(&7P3m!AQ6PKhCqTkp{v10{%s5E7 zK$?@9!z)Z z4up_1B*XZWj$3W@ajSLAbJ4G;`J+wtVwh5VcjMx>YOnKCp+AIGeZ14P9?9=MR(i>F8v&!JoQ{&)i()>)H<|W)Xa7)e7ItXNSGYEISygiw z$ZDHGEM4A~$}`{AY0utmyTW#$CDeOo>flV&woJ?#s7P1pV(Kj>k4x0pMnvj@$SG4M zt@i1Q|92T~Fg62{?Tj;a5#&9Dwnq&hqM3*q1S?j=V|NbkxxxmV3OOialNHs+BBHKm z{LLCUxiE)opxQ-X35#zus2=VgAk8e#CUO)HpSPpQr@&kxV=t@vjw>cd50}xsnJ_}^ zXFqz_5ks_)i7AtmhZXDYb#fyyGQD4_uP=Uow&WI|>i`!rY4rz?xo%U%S=&B&{t5;* zl$!laQJwZCwXwWE>k@2qYnZ-ql6q?^FL4+-gN$#huK^DJ;xYoe?BpMY<#jA)zcL%! z*L1^qeiVxpGOOLc5av#91-LS7&Wb^(%sjNx99Cbf_H`*IdrHE6xTZ%wRl*Rw3Lte4 zZ!LNEsXm5z?F*X2&p{SLqvG#@@8gRhjvUK@DnEmXX+ba5{N>ArMC?rOcw6wAEyxsq@jc^hcQ zZAeldLULw^lAF>dCo~_7&RGjDU)MZ@u|g5YR|`)7A$t^~V75#q;`AgN*#J;pTnGEo zp|UCV0lt%8XJBx8I$4Nf9|$|;u6Bv3etOF76b{p4{9lgL+EsTX3b@4?(lsqkxyC$f zaocJr?E`m$(grwdG3f)|?M%5@5ac8J(4rrbs~}Jlo8`*Km~P<-k)Jap|B7BF7Rh^2 zHK}y2i^U%x|BmoD1rNB%IP5w^rt$#W{~71FuuYbBpv5xr*!XR|NudeBSaRwNX(;VJ z|B}08yEvAq0Li(uM0~+V@BJ-6c4|!T)weIC7&_JZ-c78sJEb=6Dc6VMu3AX_SN>gE z|78y3J{#E=KepFf!u*1A15fCpa=P^_b@N;c==U(1d+#4|(FO}W>Qq<<*>3$Bou~GO zQ+W217!tRidFx-pE$^GFG^-~Tkl3CpAdJgBPRXqtV2o)IKpKvZ`w$Q#!h@L~K*X({ z`~}HZScvjxAU`a!D=UEMD3FiB1LSHNXYQdTVTus!$@vf@HA{1W6l{Xc1G;l4Ey5y6 zw!?M%IxHEi#EnHV8;q}ErhJ5z$sw%j?mvQyOyWjMe&~0!8$tpTN`dE3As%W*7itvj z=e!Fv1u@dO2|H*qI^m1C(1l?xNv?h8n!&T2)R6bb7xQZadLMC7Bsxtxy|dsJh=9;J zog4ec=Y{j)MOf{Hx;Q!Uv^v=w31qZ|^Dl*y-bV1^MW*6&Q(!rZnMb?;kSpkd3XVh) z9wLK6BJ@q7+~#Pc!-VyIE3nVYe4~B8fruDF(oum&Musj`O<3kq1Zrv55DYSG&cILZz1?a|9T|K&`2Ww^~wU z>;Q5wKRGJ^I#`QEfJ}1CPmY;Li7dq=r8$7NZfTp5^Ws;r=FvJCLG{7K-9QRo|P7N6(>yfP8o~&!BueF?P z5gcKFoT5#gVlo>WUeH6D%Pc>;u^Pcy$w<{e3s+e?eLlt|=BS5-|u$dKmD zDDn^wd`v4H6)S1a5TDPeA;@fif+4NU7LQEb_Ov!j@s9S)T7tA5OR+lS%>H&!OZpEL z$e_3_80V`1pBtbn7?zV=#K0p99`WtOah8`D=1c@Wk4g5DH0CnIGQb=D?Ybo!;t12$ zG3$FrOlO?8yYvCmquI0V_#dI1NE#H!3UD$6ptCy1IRIZg_+K7@3QDj}b-D0QAfiv8 zxGVTiTe#41*;zw2xb(bU>E+}VdB&Vsi^~8gw0~zfl$5eD?(ALN>R|f zpgTF-Bo&-{o_~*6v3drKW<{|jLUD_cYWOXMo@X%~51(0v0A+m1_z1hv3S&1Xh%tiS zWkvF<45LJaZScHhq2#yT-O?tcGV`QTPftdtmC`mz>kf!nX;cPGGg5+vNtv5yp;Ja# zK$0DJ$VQZqce=$!H(WC52_xkRBh&&^U1YnO%wK+D$2DKhF~{U(RgqSao3I54w&IV^ z1Nzogd|_bezLja#&f0>n#B(Yi;1x@fDRC>Xoyw>>HLhajfMSsNC-Tb%q)SgqpR;n)=}yKhBEnCz*>3@qW)5=$_Gu4C9?=ZPm)BgR$D% zjvAP8F%{mrO|hB{l?q5*EfSF!)Vo8g6m?-`flQKjvXf#`xRi~N;GS0-z*GQmRKb+Xeiz4hn*vPKKDEQon zeOoIr-q2(e9tF-(cy9We%jRoV)oF(6ZJL=XdSP|iK}@1ijig_i$eS9-WSe5PqK&MD zM64U7y%_OUn=HM=o*T)&R<9dro%WJN&G) zjV-fA;SqcczT<749PPu7Z9|D|5+d!cUTjgA?c(1GvMPns7?~naXfQu^(9Ac})0c^S8_3fo$@GzS*0{OTOx==A7h8tm)}w(bHnb#}nD zo>C;w>=37%cGY8dmBLWKRrXRJeUM-6MkJtvp!8LKZi4qFxxDKE5(__f^bJ1K9h`Pz z5DPn;cC4TFI=b}Xt?|NVakTQ;o89&EdNMP2_DzAXNNv6s&Q(*$aaweKX6X`SAf}jB z{((LKM6>F43<=@Q60DLXxzJ%HdpEE})m_8KV2xx zoZqHzEs*sAZ%|u~`^vMtCFyLb*{bVWhAAV-;1SUVTV4(R}%+qdjt?#xQ^u z@A33AB+a_<7WnZ3rg7sdq*S?yv=<~T|B2?piP)F%c$?85auW{ZNb_=hi{6t-x=2>+ zOyG&poR`T4?5Q5&(UPvoR$@SP)l@z9)DrP%6Y6xu#MrIw^qu$gWYu&zD$vGZ;`N0W z;ynp#J9S759P$POU#H`lkZdr4aNVQ!Ta%dUyvRP2mlI&{+9=WF3<)!msnR&P`~;=I zY~|-!qxflhpYfN8*$N01k}-G&g_#L0dz`bImn$1=yoL0xdJe66QXrf6Q#KgaXC{Mb zQYxF*_-gL%Wk#H2_V{JK1bac6WQuljKD}#JQ;(MrbAde%me2ul>+!QBZ2cM0z97Tn#Tr^&m& zEw%SdP1XD}H3xqmbv*}t*j3NH?zOJ)J|iy#$&7)3Av$S)ii$P*ltZw88`AS!HuXGN zHhclml%CfNplvo{5Xl%k7xQw~-3vit6^Y=HJ));A#XX)gNuend{AZlJ%>taMG2hF@ zP*ge(>(?p}eJN%Ot9X z@YajHQuFU@0cY+2)V9S?i*ZVgsT9sRNiR4hFvlSyXmJw229OZ^Dakep*kS@%5=0zM z0M`$r9kl%$=@-G4F|X3VM~}-%FB$ALW{|X3N>eA=d=OZpkjGxm;`0J3t0Xt$053BT zE^-i1mpR`9q$CTGBHEPast_YdfP~-;e(nvyvOk!dAk!W!!z zj(}7x$Y2tV4_3ufIdEZKprAGo<`HMJDZC^Vh(l9K9e`p)2ef?JvUq=FYxlSKNuvgJvZi#KmS9N_>QKjM0j+SI+ z#3KNU=x~O$@JH)MyItJ#n7)7>j{{i^B-z!25z7U)sD5iYKy5aUt*QSVfrg@(!NTP} zb=4f`bT{LO7D5My+IoUUJT?6JGY)V*c09qa5}>qxNWS(@*e8*~^czv=8V?OEX>5}oH6L;1YM<0%WznUuv6M=KlG z@%b(F4j(aypBSXAaq+|U0-fhG-^!Vm`xNBch1~J!7p+Ul$UgG)%Ve@ky*8xHk_$zQ zGi~UZt|yzm%(+7P6{*aqMJt;=$tBOqrOolEeL0(>=Y@0Rm23K#dpeuv$~i{)wGH&b zUxrQJ>V|UU(x>(2^~z1c`HddnmeKR7ne_TI@l^sXTV&)dCB`-H@vR;4T?Efva^!{e z@vU3=U913-0q=dz$hN@=5=r@uX8KJfFioq;K-s}Z2Je2nH@ZICRUeP_{(NTkOB;&z~~8|l9Pan3(TMq*7npebv86Kgb@>0S64x8uV-jt9w}oU z^$#~uG6{s3hr^s2m{6nSl&)?Uqvn#X?3|(MoB`_t!sHq~*Lc_%pruEWmS4GtPk^0Y znvP$&QDm!0)PKMf7)CLTZgb9GaV=cYuD#Q1d~~ma!cu_o@$vuYHn0NVU)`n%Mp9t9 zP1KKa7)gN@0AadKeCDrz11N=!u~p5m0$^rdQEu_GbW>8@T3y!|T0EBUbHex6v41l( zs0EtRvYS=jmRr$Q{Hycd?VE~*ZkT-o<0jFa(4_YB?>*3zK4?+rKtsoHP3Hs*oiq$j zH}o(3BjCW$NyFfu*0Ifh2Pn-)M;-lBu(`j1v4y_b<+icS&Z&d``PJ_EGuY5y-^%Ue z-0DB{WbhAkadm5S^Iy`<#@^Pyq?`W%ojm;S2;l!Rc=8vW5Q;{vX8Rz&K$R@0z!V5X zA*NUGTa)SXe?e|KSU|rn97ObtPAYTyB0@i=!O%(WK;j2qJa4h8yrKB7YKx0~Rrw>a zB;yZ+{a7&)qQV?`Y-99P<2jK(#QloKb|>=XqYay3`+hU!+V!Y>Sbz8ZCek$QDCOQ) zTm9+xXM*So1Uh08D6qz43x>SriMcSt)fedyw8%sIQD?39J%a3f@Hq~c#z$*bCa(BC zCpT3E|#^($)4L77opl zrd#pe;cST<*uLM^;B;tmO+EHyZ&|UB1T;J(o^y7p{$0KFNDJ5dc|LYKknTdWyC~EN zd4>34t*4<21(?Ja2)C1>Jy+fJ)n}Zq2X@(P=VH~5M@J-6Cer{hSur>DgQjAZ)FzRM zR&>&W%XKbZqB<|&kDMsJ>3z%@qBUWH7e19!fVYlIO~K#rpM|^JAbg83I9f zwgf-7@kVR}c^`$W)DxAlh%CB`Tq2n&zM?#-kF!BSu8v8X31NWPbaIjlP9LdpR(-Gf z_hExSCRSGz5EAG{#$HiL&E8%y+b9&UU-GNrZiI)Ed0e=t`l_L*qy_1IkH_ys5LDjr zp}3^H_R4O*a#YytQ<)q0r^8~_uj*!1pQNawtLFpW9F&@tB9+zc49|Zy-wu)JY;4O* zL8!k9zr*%~8=mVeeYn~`ZUrEJK4}Bmy2`hMC`zn4IH?a#I?<1R(RN`gKOCpOHu`ZY zP2h<3(@86N`?MFeO5&^!e#MAZ4#?wkHh^i1c0P!-Ajmkxu=2pr&3^1=HA0zKOK!3P z?_Sv_>>5VZO7o}RZVZ<~%BEA!RnmTnU^}e(H|MvZOIZcyX8LNl!1q^k#`zY^lcvgU z_6ulcFCE)$M!2kI9BLnImqDJ;PgvFF=hQc=7A#UXzwL=NZKXmGe$=fyv9z#C#=Ka> zoJ&%Mp%YBT!*3G-%1<>rk;IzpYta%OE`JEP4xM&>^t7-YRI0Z$tY#Ot)NU14wQy{E zym`x7Tm2WEP?SHM4YC}=oEnj5bfWz2@p9Iv{PAk>8J(;K(mvg6Bz}9kg`tzDyMx-} zr~8v0TIj>YGdj81E{8rnTtA}|v6aF@? z4&Sg(f1MhDVJ^D;D5{6rvr_~1lC=&cBc#txT>R_Q+(1wMfMAypLE2V=9)8bG4ZWM? z96YjSmp66YX0Xa&*6VCs6cI^GDZ(tN?ot;p}!JHbD;5bHBn}C%6 ze>gS&flj0f_;LG31K2Mz!Qln34^O-yYrSFS6$sjDf3wV zHF5F()u}1bMwXcEAb9O8!CKNGNmu!bGQkj@tsTq7ZdSy&9r#`~Nf6s0rib60BxWec zh{s5EFhWp=V9ne}B!$k$uZE;#s@H&Vp>`6=;7?v+K`p3O;qP|3T}}`jg(3DSnq9Ql zu>LSnz+t{~1=ZnW`rg{6>A+$w2}}Ku%>e1sN#M@7^iRemY{%w>h87dYCQGq*4vDNm z1$o+F=>ckw`4oj49|oOs`*Qag3Hn-294S$QedEU$iX7}=ZGbOyp2SL1(i-vAFR$Xf zFkkC1OFOk=8~P!zZvx7<62809kPn}f9BM%kAyo>^Hp#xOt70%xg#Cwr>f76 zqvKi^zN{WtVu;x<44PYz4{o?&fc4_8xVy}{C< z^f$5Puyl61E8-6YomfBjkJS;IbPQ6g9c6;xAv1nHJ`A?XYrjk6c|9Hf{Gy|zw{lovfmaR+LF zHn_C)h8&^lc`wQ=7p5$?>IML)+PA;v-dSHa?Jrfx1j8){-d(q73Y~b+HfdwM1#5+E0!o9hP*DyFwf+CZkuQ~Vmwv<-QWfJLmxHLInqELy#VbRRp zwKe<(v9a*anaRw2Z*AIY+Wyq1O6*o4&H1O1_DOZg201Kc6}?ZnMRf^2i17y;cr5Yh zVue)s5UPk0anbUh;($DB@Atdk{nAbppyN*=Csh@g^Mo9=dfM+%MBg00S;l&Y(46ZD zbb2pw!iP9Zc)^Gx;pMoqr7F)SKbzo%ZH#ZD?0uil%_b;6ZO@^-$*?}9aTnnI-WXpr zQ1e2`Czzgxq)vkr02%p5*?8$?q`+ zUf5V%w3k*K&(9yx2K|e$+zwT>g1>2;?uQS$lvjf4L3$cD;##u+vH%^+Qv~WO1e|UE zXs-a)yZ{KR_;VSsPV*NWkOv8 zKt;1AQ1#+%=m}NutZ#~L@Lp~3kJ(_n3(#f0PnHw@ElWs5yJzI8=SH{IMJ+JzCL}^O zq=FUu#jGdesi_|`j(x?Os@YIZOcYOmd&|zN&q)G{Q{F8f%oCV=I%mTIE5mws!nz8) zjd~nrrj#X+5gF+aAOOShn{d)Gq50nMWl#hSJ7llJI0*Iw0C79MHn9n6xQb|Hi5^UHK?Nk#ToM9?WqDwuDnXTwnAaVHL6YFKZn|x21lSwUfPRExC z;H6VOO-f@+ez?GfLcV{^Oiofwa2&;{z=tH{XzQt_tSf*J$>fc^fTC7NjPWTAbJCWl zh@O*hT3+$LgQXcRMQG(jMCX1Ce~*TLZ8*6Ldm^NuU_JXiwHqHr4k{?5WGAwMlGc3- z(&hyU0+2fKwRW6kMuUh01b&=SNk>^Bt3~NwI;S6FCvL2>KIo=DnMgmXX583ifKa31 z2{K-o%3O+NV4zB)vS;owIbxb-?)zmT6lK1d&-k*Qxr-fz^)YLrD-+!`Ys)VSAwTO> zA&bUE3ZEc*Um=qzL>i{mAkAm8Crh)zN0pMC&l&E@ z*+$7#P|H8B+q%&qFm(m>6teV?a4FL7m(XVf53&h~|>Ay1Zo`5S8f z;G~0)c>Yi9*LhU=)FJr;`uUuD`87;=M&}kjYErMVA>h^c&rp423~fo+aA<=X z{skz)G$Oen#OhU{W^4gUE@r%G0oi-Z?+t}RNxT^$5X_$i0nrxNIhgq&MFj+I{<4Ko z+~T}Dz^`O4x_HjwWC)PHsC>Toilw-loss~%q=Ow?mkiErDDGn~Rs2(^{;DMGBo~;A z8Epk(L@XUcMRC9hpD6M~^DB*af`nTIDSh$Y6n|GtVL)|L26W<`b@>$L1>w5Vllqd2 z@k{?fEePRv$?Y8mq8WrmIDko*A0CU0h>kCT_7`Bf?Q_ogztnU+L&7VCc#yyg)10SUcQR?V~Pf{HezO zUcmhxBjkj^^V83p&#X;6Jq$glcIrZcn)Z?R4IXU8|cX2i~JRX#Pnuiva5 z1UWy`t>1TdkP+xLbvY06{v7Bo*=5M1?@fVD_E-!i`;_#e{_26Qx7!mIP@wg_IiNd{ zz%diWGZOs_`AvR&qGKBS#%6U6Sh`}Ux@gXy(ZpjAh`o3 zxVXmMNs!pVlLU5%5UEKe5~O#{bYdFg2BVYG;d~ITNkJkc#i0phu5ok7gt`=;2K5xJ z#gra3h|+!fYw9%X5)wx$odwr~;maA!$tj!1F>|X)U9M@K(wSFXGqOYD!b8(~&69rA zd;#vWZ>6S0QzyNnrovzHDT9$BAIEgS$g!!D2JUmcUY*tXfTgiuqFH4kWL}Mhn$)?D)CKvMvkptswqT?-i-lUQ#YpP8%B6|0 z=EWCw3q#=x8i#XZOA`iBGm}sY-sz>q+~(<~m-EYyOF-=9j_{?Q8q0<5%RAJ(G*)nQ z+Dl(};c=r@Zo}bKE9i_XkX(4j-P$aH=tu&qaHsCPEU?2U61duCc=)zeENQ^&3OcS6 zpp4a;2MNf z!AL%?=DLemtG9tpnr6ELXRXEtr6mC7wLlJ$EDmYSz!S2g2;^Lda8aA=zd%&xSX50Q zbI0$UC`iP8aBA8jFsDSl?(DVSG9Vyg$7XyWTyM$LW8nqK8fpc?>tSU2mq=UyWU@mf z=8Wx#3`F@0IBhS(ujmQ>Wr&;`o3Yn#?ZL4T%ZT6JZ2-vje+|RcNaI@Qa;|CY3J$L# zL)K6y5FD0w(~qWGEqIQ{5EpOZ?0L%+F;S|}g_~)qG0+D$gl!#o%;yp)GRC? zrk)+HX&$X>a#E&kQ7kWhiUQ!AtUIKx{jeNQLr1pBSiI3giU0sjegPxefUr>D_7lb~ z`cX_FQl!_B@!6r16%bqN^tIsq2=_#((>CxMRQ_Cf55)kSipw9^+7v1)U)V01+ z9w+b#0u*El9X-WPKSd=zji^A5Dcqm+*a!b4=9Cd?9wzIa*dm7@h?c{>BSw-cqZ86T z^RQa`P>Re2K-8_^8F_m+!A;JmwJ(#B=)1fZG;A62`HGSoF8S!< z11%^`dXo@+U9XL2*LaWN``+YmY01$}+0&&q51E(c78>7HVB{5sET;|~yhZCeJ{X2S zuN@vQ-Zvw0jRNtO5v08k&l|Vh%epoyZz|ATrf@bavaU#e+!+nC>4K41R^hN9_cgR| zio8hO;dEq=h+2?ww+f_#1Z2zAak5eqWho3%WG0o?>!gwh>*L>|G>XTnmv9P z<~cipQcqBSdqnVi94vpVeYw3rG%@k=3GV&VoXpc9^<$g{(w^tz0Ws1L@v;GArfFr` zoDO<{0oDbEpvaGABymHrY4m4L(n(-Wjj)~V?=_(?d}hmy*|9$&uyvJ)_p0L?V*id# zlIRWoqLY4agibIgtH@|iFyFgw6x)gaj80^8rE`<%jih}M|2$k!G8O#DQv8=wV=`4{ zP<&P-ou;#Bb+}`{PDpP7b7~f5jehY4))g&prB!|KWv5qJI9tZ5}upr=sw@?`N@CZx1zCQX5nn@zHg)f8}ruLnkn&CZfK!tv(Iq zC9e3d+rM!@mdCFoZyE^mJ@aTVX&oEsc56PU zIbn~e&rVIf>v1*g1k1DrNEQc+1B$s~uts*LlsBz^yf_g63n=VkVo5Ol6pSL3wHA7< z>?bIQr)Z`xOknoQT3Fa-lD@~&NxvZal}wnmC}}7YL++bc1*{$-+pqeV!fA0fm?XaM zPenghP1+22CR~gQ2ja;Z_fr(3#YiwsDA-B`W)Q|oGD_*&O0(~897%A#F=6PZfWC|E zXFPm%YF@gHiy5=}f3}kqev@l19DBv7Fc`3IcOfUqICMD51J^7k58L-sEaGfktP%?> zBD7ajQm-ylpq0t}B~PO990!!~u@_Uty|Y!;_I=*>3uV4i(T}D6qHKt0KQY3S67Qg9 z8p&mksnz#iy&X9ie9HX`pHN<6z5wIk;^Kl|6XKG5!Y8ABN6SM+&+(B%hCxJ&QB)g7 zo;YM}<>cf5H+f!28)4=$7kV-(y3&x+M{?^REa0QVaF0hyFvJydrV~;);S3io=tiu~T$fWnf`#cvd3}JEdpk!pKu{ zZcR$wv%2#aI5qqJqve#h!QyTiO+A^-y+yw|V12jp`rgW>{(sDzm`>=AuII_A+O{E> zoCE8-)%DD^_D*O0hGq{!3;LeToW|je$`NSm=w{{Q-^$zH`KhMkV;E%W8l3MPo*5cn z_`5o_(mr)CGQIwL?yM6g>MTD_&acfbJr7R}tUq(6rM2Dhji=e|r}^DyQD<#qcjI5f zQ|m`i7;xG;`MW)JcKaX0Q~#Se{VzjK|M5dG_=H2HD+qykJ7K^N3Qpk6&VZLMxIf3i zVYG*0;iJbn$-Wbg`0MRd=JX2SNIiQyxdSmgeoa4M@TvdfM{}6BQNkI z;&MNhT90`5d%jUl7Kag3le+TL?fG}bY>z|s+WTvTr5c@%oFVg@oAjgQJC5@1hUUxa zXc44G`ybZC)VQ-Y3z&8)zN7R=nfg&u#yT?d8U=EWNCzRf7QD6L^MN!lbftbFtTm@_TSTtfP{?fvIashG; z8#+d!)~w5lavI;?h7_mb7@B`tHvXV$`J3`j*mWwt`r9VB>y?Pd+eE_DHz@dW5sEcA z`ssemC_B;+bW=()1@^*C6I$;iMQ8Q!TTBz3h`#vT`uN?gyi=met>nPPZj-O~vWnY< zHb}ME8X@4Ge2rdwXmCz|=iB+%jGAG6jWVwf{btUK%rOQglr{ybj$}Sxc2zVQ@^=eT zU>YTIx`lP(&dj!ulZuge|4>@Np!hi;D=&cT#SiQlwOQW zvK(IUa8R9HOe!dIF=r|nmD*2nS{z=^h+m^z&1y3$V$B(wrA{ZA)Joa6&NpaWy!UIRSh(6tw8a5pKU0^v2z3J!l`cBBsl;TqhMHvs~hGrzq`Yo;HSPT2K388w^6v; z*;nPhrZZ~io2IGsF&Znf3FRT@D;dw0si}5bjOM*{77e#s5!y(P@zU}U?%Sh4E+f^YT^M|dOL=&R3*)~W4N+tIju}rWMB6_WF^`prYEU2|A}*&eoR`jkTA(i8Kb{c4 zka`Zo1V-ZWQuE!y%tOyXw~4g7i+tXfMUX)8$t;4)0#T_Vxy1g-Jod}NzspqOQ$=c* zF!)rYRNFsQ=5krA{jyl4M|`?6`Le|Ld6}vo2A?iVt-_1H{!c--e}hj~6+u!Zy0`V{&F`HaBEW>FgKZ2ge(98H?RBGvak%LRq`2 zxr;d#pr7HZBOugf7AkW>lHO`075w~4jq1hWaNw{C{xJ4Y#`y-zFD-~=Rycf%>kJhy zLo4_@3^x!(038jg@(5&286W&rbucYPQ{TiiYJlyo8~yANK>fY`LJz!IqS}7%+RT_a z=-^SX9@|M9GB{{waa-@m&B-?I8Rgui)UF>DVAEAvMYp(Z=~#5;-;i~H@~jo&I##|b za$iJ@9i@&gE&U5WXr7f7A}CoM?HStY;^*SEc)5!c>xPwLcKVyK#U5EHb5{TP;8;II zWPFfuzkn}Q+u*J!uKt={op?X53+5!n1vfDk;D7KJWR9wr0w2MTu^}rg~y^iHbN%_ z$+$)C#)JJ1-S%F|NV=*;{|ep?;E^&FDEmF0D_vcrJhZ3OcsErMQC(srwXe2tH(fV; zDUZkxPoA+yQWwwx8V|tMP#z{}UJm*RM`3RLg;uNStHT6(%mF)o3dzuGvGeW$d|dGb zskR6-BlLETDM6NLIm_IDkY zKCGmeERVgXpVdcqmkmxk{vHo&p>vwbj7i(08@q4IO zr=@UFkpP1`iJKAES;xbh#H7!E)bZu>J?o+fGzE%}iuB)c?6f^AJkrUJL8Z@DsY zyE3-y2;gwLELu|d^pLh{6&mW2aX{cVwonp zx_0TnD>eaaO5WJ?sbL>m&Hh4;NUh|%GkhON`k9AQE6@|}Pm~tA~ z30=@)ax5J(!3OE136?qL2 zzl}^-6pRnXmI<;1^1*8Z{3>R^A6MbTR}o*aSYxmd6NB+plYDU3klvnPXabOJC_VUQ z!6FqJSk)i8^XMkt*>F2y+GW5KMZx*01O*s-vj*8R7x;_cxU@obe2l6r!t1=^RDu(n zf|HVhlk1-0Q`${%23|-OYlzo1yd;<<=f+eb#Y~|+q>?qXN-6ZG z)9bok(}vj)Gks()*ezNB$iYjhLo}>=N4~=t6i^YSe;HbvB#n}`Un@UMuW1t4Jy zYakX08I~1r1X&V}EeZ`1g)AnAA{K>2<*4D$Rk_LX-B)-#D+;LUFcKG?P6|gTCjYkn z0|`~MI_%U)KgRIAy+WXDT9)j`UD?n0vC5lHT(Ctb=qSSQwXg*}d^!XC%Uubs+gLuT z*of6wGx#_r6GaP5gqI{_uwf`6HsPuBRClkKmCvq6Pu|!GCzE)(!7rA`zH9bkEy(?Su&OmKW(Lx74 zT^HV0OqhQaaYX@99H1c1hp2SIqCfT8JtGNC8{U01saeHTJ^|U8PTg+OYy}(m5v&jf z1~RODqu5ooVG~v_0KT_PNz6>H>mziv^DCcYhWuu17X%;Iq;wbJLBPPC+xI?pI5Gf4 zC2z+aeboWgRE~Ekghr{9`XbWasgE^5I)eF?%M$O^QmKVIs=9^E)pl}|h$mrR~xnh&wjROrkW});W zQ{zij(Su+(ie@S|6*(_cHP6r`4<{GYjFfIZkJT`jxBo>HxR%`2WmAok?<9`(EjhpK zyGToYYLNq`S%1DCd%mek!Rnj{-deI3RLvBRz91+$-<6;+8YCKem%@FjsP7^WX_^uj zk{^3lXtpDgNRVz=UHIc;LE6V6bAqChgLVh6&gyQ1CQqPjar7lk70k4gn0 z0)5uSjcTb4A;m+t`D%R1?P_X{Y9;f|CFRK_m3vr5QzheFpf1$XZmQD7242UU5{4V4 z*&?BWIjK_Tf>CkNDfVFFyRs94@-z1G3$^mA5CuuA^1Fuehk4lbq;kNU3V4nRpn3(8 zYXvB!0=2OMHcN$mUjfr~usD7iD3)P2s=Rjn>3s>$W*mviXMlZtJx{ zed{6?6vGCXV_lWvU(`!D)f>jw|KLzgyRWy#X~^PG_EK-y2x{;sZg3*c$RB8^c+*(P z(fCW9-SZQRKcrE_zOf;t!D@h|dB4#oyT1K}Qjy_E>eMnAYlS;MI(0-E=VsqE0 z=Es{xeY0lu%ZB;ToI$dBd1!3YI!DWfddrq;%T7wmUSkXPK=U9O^Ad;j(Ez(1LhI>( z!YYTw^@76f0Mk`ttJqX4;JOuHt^i-c1pL}I&D2^h@CD@uDEc=Da};T{NIYy634Br- zXv2&4^$YqBCh&vGZ~AtEujF`NJL>t1h{Kqa2s*+Q!LK+;P$b1IlG-UH8A6#lgRMZ& z)s9d_!VqxhpAcB#sq^hQC(!{j@((8V!OkduFh82Ppd^^Wyz7`jL}IXugi|Iuo{%1` z3!eTru6d^tCuQ_So6w(5T0$#H63~^LxY`&p+IgzM;E(rlUC|P(U^kHIq6z}NL6xG9 zpt*XUP>=lsp@&*436xO1B>pR`E!c4>9)Z^9>)Qi~|1B!eMzh!xKJ{8Ek4_$(ow(75 z()l&(0Ftm+r|sL#IoOx_fZ;R?$KfJgfiqA=sDd&0yKJ%VExWynshInmQqor@9XBS9 z#r_gR^|vQf-);uta|Q?920U~7gsTQ3rd}&m45F>Van^{>mJBVr^(!$CN=@`nm$b>- z4{nDI*TwZGXZLY54Ig}!+bCgjDmnNtQ%V^lzB z2v|BwBQ%V>G>TrT!1$y4m6Uwvj{z=oW@)#v+>PPjS7UF($1H3I-;^>Fag86wjfsCs18BmNJhekCraLF;64^yVXW}_x{)W*L)F#B79_ERRsnSksp)`l83(B;d4$>UCD~w& zDSxiHX}`Y6)X_vKwKroR3pAW!>>gY5-oS&vScN%74IR&>@Ez6m%*oVox!!yW%5T5s zScYa}nfsy##b-MgjJOn%QYkhdv*{mxjPUD1eoMFe3rWEvzo zicGR3>g)wfQdM>=T}$GUqa0qNLZANhc9Gf=fG?F{Iq}S87P1%l;?M`4BvT?;u>*S6X4U#|2u2UJZSq4JFvP9C;wp+{Y56x|d zRbXa>ME22^N(M5l@8%GNSUkK}I=p2D-iMW`b2ay??e@(zccVS_g35MVp7z_&cNGN= zg31nhmc`qafz8s)gDuD|QAlhj2W8lYzqk(uEs<@@4ok2PrLDr2J@#C@5ZBQU+tT*8 zTlSY)j*74khq;-jhWF1}#K$ZT28It@Ajh|w;$z&0SDJ?%Z%^{O4jYDd&A>+>+LN{; z;L-ANSK1y%`bnF|$)xmw5(Meg<1~8%*w=F6sEK4>f$#}%mg@(HO9CJ60f##Ze1J+b ze=|WeBH87HAfacRAFwlmR_GD&3RR7b>t)<0-5hVQC>gu!CE-(sS$redP<^VzmaJab4(|Bw1)f}yR@c3U<_ zRF8&v7a01g0D=Nw9qsz~nuGM(e91N-5U1?x7#+F#>ufT90YrB3`RP)!00FY({|LG* zu#l69_=s|bk#t3q2?gU&41-kYbUK4@7}XAN%U=*M8IDGI!vhqHrKf{(u% zxHH@>OzlP|YdB2S{DvDu6Iz|~?c>eWX95)l#5R+Z*Y1laicAW8tFP3yzcK87J+k{E>xgv?ghl~uu0FP;9r5hT}yI6$&X?PX2|J~5t zDIJQsx%I$ZCAO_3Ea-MV*b<^JQCN`G&yP`>6IUs~wEycl=r(C9vo`s;a;TsJkNQ1Z zE>oloRPdGJGkp3zA@e2O)b=y~iIUiIN~5gbnB&!9%T(8kLd`hwqtE}BaOCQJekHszl+*HiCk0U9h zgN!SLwIk||kG2!C7aZpTO0|dfi?$St7lJf0L??@Ouw|-p=fp?HAyow>?C76~3@a`4}_ixF*|3H5rR5TRyS1|O4^Og#q=p7!+JEQyr z`;gE)FFKLX@_u9!XX2Nm7uKQ|dB%Wja^JY*?VcSpRToJud(p4%Fa{`R;HqwDt7qY2 zYH4d^<@Q|gbA>(k5;KVuGkuoPmhy87Om_}S|0m_=5tak9&ve7vOp->dQpa60hODz!oXU<}D~@fepe{AgXA>~GNT83qP?FAs`;*3iOJe#WO{N2mRSA;EumU}|P@LRR%ZGFob3V^&@Xj0$FyG#8ZD z7gaUGOti3q{-B((@3rkPPWWu1Rj($tLX%pdxfLD7)tzPazhRItvvobR4H^R*fogw- zgn4bf|8T-z?c=rGb4^{N^#dy{W3w6UyM;Z6**#F0l2$eZEg!uq9)~s!Z&r*zt4EKU zM>kt14l2k0!ozuJN8huX);loSJ2Klnv(!DiGzhEwO)a%e9&|pF!>8Wmr?KhP$+@-J z#Xm53*uVY+gNMuOJM%lRxZnQ9&f(7fF)Z%4as12-|CxpQ-@x!c=-&V3HyHY3vp)Na z{?h&v`s=!A$NcZ;PgLsP(VuYKKj_bs?%&Ygt8dTf@AOqS%O`Fa`kRdXAJCtSNZP-n zKU9Y3no{*&KkE1gK|hZ=g9y23>_o@1mSa4FQJ;dw*H=6F^++`(Us3$&i86u@m&DJW z%KpU9AMO%gG@Yl!=eo6szdtkbEj>VLsG-^{*Gy}`@?NHFX`zm6?|1mmW8Ux=9G2$z zb!UBX-LaueXM*)MJ;T{NX`kIU4AWAgJ*Lg^t9#3qJJq4w8p)S?b2}5Z;iWBHGxO@U zD^sl3SIgmVUtYaLf6zN^{jDeh(SiS%ui_oa7r5%fA={H7J`-<;&o_@l{?=H{T3OSW zu)%2B`E5Wifh%c30XF|NQCybBbt$Es_B{&AxM!yhc7`308#L$5j+&<($y>Cc9YrHm zfG>yX;25tU95M6G)QE4FAn1dVY67{R7ko&36_;*`UKOi_IawlXTb zNXw%Oy&u--b9ym3%?dh7D;DIiATJ*kxw7xDFnMAScP=?)s$HdVR!O_aR8pKzeM*R( z^?FLO9g6awaEuzUd>N~Vc@^orX?%quu-Y|BOqM+qZ_QvvXBIz0k3M)gGs>o~0GqCj z#6P>ag?v~3^K^Vx{-=IiLcaS=WxeEyajK8SU+4o53m33VwtbzZ^%ea8SR}3mc(9ug zsP6T5oBbp=z4b$cKIpZ-QtQ|!_#SUa@IjLr^;co|V=1u6YsTR|rUtc^$*2?LQB0Rk z7Tx&0RB|1)pk88m-Y8Q(B)2?1ObyW92Ug)d=rts2jH|4tRyZDHnlV2gV%;t|AHF>5 zLK)#jre+$oL5HC~{&PPV`deu-oPe+lDTv7`yW6SBsg>G~?&MY5H-GV?zM8po**T-& ze5FuDpTPnX~%@ba`^yLsbR9m*ewaGG9_OhjV?s#{wX3ceCh;=f8 zXZT_%Mx@knQ|>z4dBV-b-%LKmc3Evl!j|oPJ#?hBW+I1{$a!B-9{ql_a%7k}x@KZ| z+^?R3$gIIDdx>MzAET9VUHx}j!>QQJaMQ#vPixKAxB#*KC96o}R;YFoLS>#iuwFl;%m0UN~JRRlJHbY0$)9>bIcy8v7Nf&+JKE0-F zIinvn1n6r5!ztRJm{x8$`ssUEAU;FSMt}cvvhTlmXMz;sVRfzoUbP zH6<#d!p-q{#wZyG*FgGKaj)JF%niH97P-Puq6mi&1iTK;Bri2p9+;nQxT>xQFEuxk zSeS>-U)9tNm0CIuEG*w$)waDXvkH`0Tqn4$>y;|ANgP<*V!y5*4KK6Hmsr|UyKa~r zDs!m)KTY;sMUaHTBT|sIgYFpCTaGLiaCb6r3@uS?Cka2eABL_xgp4LSED3&MZYg=Gj*ea(7B&ix%2K(c~?T>o1_pfhwAf&xLy?55D; zqo8@`-|o-%N>q3*Cgni?Obx4D$PbS4t+z7hD+%=X=Kz}t%_glETC2oP?m$XyI#$w> z`k`+~LO*^NlZ!-oqeZlxfVlb$n~>)FFcNIz$R&{>=Ig`G(xr<}2RqmT$)gz{KUC>F zA6`m!zcjR}nD3k`7!t`Qc4fcff12xc5Jbp|eW5S*Cfq$SHJPN8Z!e6j`-7Fv`aACC zqB!z{0n;d7H&YFLL?c11?lsM~xidRXWu02f}`z zgwWErg}Y344d|Xm@SIYq^v`swZ=J?`I;DCKC1C538a^ZK2%!EbBQ;<&+$K}9X-+Rg zIOO=$9=E;ti4&t?G*J2?>&@eis7%9n;_yWt$A3@uc`$mH@S?^SNlbNSz!w=tehpt^ zA3;02Tqw{;(I*Z*8s(0y-9I3)7zv+8!E%gdI*$2HpRr^T;8;Pde{#0pcpZm)gI2Ue zCZiHRyW$be5)?*GWG7CR0j9|!Z81c^|G=DL5LGIom?SSmGFD&`H`%&z4xSu;*9FV| zkiI%?`Qd&TSa|oVFYT&EhU35}poaHHh9(6_&>}#K_79oXt%U6pPt1s0fypk=iL0f# z*5mP@$KH5JGs?c72I3y}ZjSir z)R9pQ3-JOOju?#CY3PWc;)R^##Zl!&G2sQk^D^tCR0MxkT%{y3ut#_Fri=1s`@lpL zo4!AJ^x@4u>}h%8sB%`Y0&xgRk(pWP-No{Ka)l-j5mvwfTFC zdfOod1VDp=Lh6D}DGan$gEA@tRUJ^GDTAkGf`6hf7FJhfFVgn@aVHL5H6tRsbySIZJXn=fz7kS1Sd4U(HHWP8! z8?je_e6*wN0*M6RN2%t2i?agv30tBIMIoV>pv^@!2gswEfRT5jkc{kQ4NRti^aOo) zbV<7EmC?RGh0PJvQbm}5U7|2TWOylr3iE&;GvLKDyh+$%`PZyyP-4lUy~@m;7)d;LsOBal*G4qJ?oY992E{xHTRdclWP(*=P)O+~jBs%*i@D?VpBMYfj!aG&Nui(nM&Lw)X zDSHPqc-$sb#3%4m361!H+)&^?MFsICLBem7qIY9WbIBu|84`n&%5#&9#{|_FP`tq) z)~)YPOv$;<$sR&dIVQ=sa$hs*69nqX_YGy$gOYjtzx^~xOot%oR3s@10`&oMx+lQs zTx^{R=~&f>VKGr-MU?n9NsSA85`Ul@k}A*}$dKvNo=cuE3Qqx@fKLF#%LszCL}K^Y z@Mi1N1lxsi+f%tu)znDSC@0{z<^*xAfo7{|PjmkVdv6&R<^Sk!4luwBAT6PYLx?m8 zh=3s7HKdeCHwcJGOE)-lH_{;8-Q5jR(p@S&d-L`8KYPx;&Ytss{r9!|V0WL+%)@zb z-=FLAzAhpId~_sln#DPJrQ{3mS6YXkIriU*XP726zDg&oC;Up7K_ru|?+|hF(7(g@ zZKa990~v9eONdn~MwU|s{qAQ=^~~pqnI>@(W)+!q^GQ#zuwHl?6XK&?I@_h&LKxv} zjGkIU&hU}-EFs2hkEtxdD?H))teS7n5@Be>LMR-z`kG)YS*&aYEx3jZXM0Z4tEq3C zXWzQN>62pQJQa(>(NeOQxBl2?o#?64C?>C^%HgE;fyg-by!wm%x7_DGxhJ{LWY|BD zq=U8j;NCKM{=qry$e6q@1z;ad_s~-?b1SN1YcAe~ZL~!`uk_nQt^By)gi=f&Rw<=y znJhl(ND&BDAl#U&$}osK`+b$+#P8&4m%{rcRDEG1kZrmuY<&a_&5Am;in?8jdJ~KK z>x%~Gi-xa?MjsWA^A%5O6$7TeSz!59U%WV9ymVE(@~C8uuVh`TWYeW&JF#T9zC?|t zaDP|l@Tz3+;rG)59dDKI)8gMRTyy~XSHAQ8603B|Sn)A^X_s0l#%mpb{R%>sg;XG(Rq(rN1G2s*zw+nwl?CFJm4=nsewET$m04YtPp-KYn6%)s zTq=8-YOYn~F;(J)RUTbcx|T8eNfl~8OAQxPU%OWO$5dM^RNGuvUlCW@4rtoHuIY2G zaJ*I}(XMfBsCHVYk*uouf?ccnxXRa6;{;r-#t8`sQ4X@K4I9u5eq0ybP-KGbq90e6 z*ie_ePzP|o^v3}AtB+|fMOCU(`&9Sqlr!&Iwcr{rccEVXSA8i{Lk0HBBFhE|@rJs> z2Ei(R+=T{%?S_|K4V~Dk-YN1$;jr1{%{R54IdyUVH8(-2i4aqjajGMSR8XsdA zqauY-y!0Y3*P-6*D6I7?e~6oq$4x9I_-lJ9H)8l(*8)2YsfN*w+!Kv+*!sD9&=V$3 zq*%+gYs-%{iN%J-32b9ms^(Y9&0womOq{e@rpCF27JPpK6dmQW$8CiCZ6>tPmz7-m zuN&?CpFWmraC0Eox^6pkmL%clB%?4OD?<(Nbgp+G2*7t@-OpqWYM5DQMzVKsQK%Ko zbQBp#qxg4bol5RM&Yjn85^8M0rsyK`L$@>37qjY;P;1v7>>~PB{|u*F{afP?*>1gW zdUjV`W{axh3*8FFZ6p{yWY4;Vak@l&dK{SHt=KO~8+*i!yDj;-TyT2P7P;(ox`dEf zP(Q0)qK6$}jhvx_z2R=Xv~E43$vrU?aK^@#BsWzHD=s)iUs|Yq+~W>OmEL%GKdx~% zU1M*w4qLoXf03M2N;06-?^0pwOSZ}3~~hxcE8N(sjwQvM(@ky z=WJkZ8OD)nyy@rn=^3&j?$R0ZBkoV+A1s&{TH2Q^DH?n=F*u_$jPBBBnmoYm(_`oI za9;<$mE2FGGvYnjw?Z+9934Cr9lC04=J6Tk%z{oVlFxIEqE3y3G!7}0xe>|_PocN| zWE$OAXqO9x89NMNuna$w6*)w2A#HNH5^Me4Ft)oRj@#7BaPXNt8K0qO+zy#J##PL2 zaXxm?z_%(gHujPN*Ujm+vmM=Sf^$y#P>%DsaZn&iO>^q~Q6b+6)8rGYW^wCDJ`PE~ zcWiJ9e@(T=;sgeeh<3F7HjO7wz8H-r!j*rbOyjr_aJx<0ly}&NvB+k(v!rm&U6W6s zP5;c+MQige2^fn8zkj4P0~?gUnifF$@qQ7ypo zV0p}7WE~PqUWnwH|He`<6f=`bG3xzuVoohS**VXLb^#&1Ap4ppX>{8E@mOSa`VW)2 z&)`L>0-ZlPqt5p7`nMLLA}CJJV%x1Hhi(_+6LtEN1{!W>kI?3ynd@mG4Zy<>P>A)w zwNIp$pDg`+x76Cz{g`Bo)Q9_fm~830ccJ!RIz3cL_>aqV+uvc!DfRCTZUv}PYH3mQ zCp#PS<`ppyBhCcgHu87O4Q0@ct(4tDknZz|2(y9%oiK`(#f}U%`DUCjMX|-DO2T=X zJ2>Ux%z5Jv+^Ds?^=7V(wY;-6_EbfS#)U(HSMOQm&zbp&J$_oQ_a7AMRb_II6Z`Wp zulua`C$`pO4NdS8t;>arr%>d!F9;kL^T_IMEH~Cu;5?P18q-};RK$I1Haw(Q%w>$* zD|EbRd$%bF0t>Qlnd@;O5L+(ITP}B)CZn5Qh_~$CY<;>zGX+7Mki%QSxDZp&wg>Gt zLU+q#^s7kLc1SA5o0V-h@Q#nd);mv3Q6gyU@Ky*MGofV1rE|yo4owG+8T4k?B^*=8 zbJw*Ky?}K~2Z4dW-_69`L#$xx2<=sQ?0xXS2x;AGdb8_syw#p6siU`7V}lXM%5{YS z?Q7l+TiSOz-|u|0)9Z2IHoQIGd@zE0fEY$kS2(z;K8$UKe13E2sCu~QaaeM9Fjcbc zbc}YaD|!0n$S!rSr{r)S_ppU>|5`!vc6cYi=IBrJmd7YM=GWs}o5K$_7++eC_m{Q? zDNpRUPVR8QORUFxZ%$oU4=I*UC_fyg*>KS)o;Kk^jyz63Afrz=mv)(#PigU>-%5@+ zjwHB74s`VP$(BzMuss36GeJBs_Q;;|3I@;j53L^OZ;)p?_@}}&V59U8Z%4sAcu-|e zkn*y`#uC~qd{hQcw2fx8XK=8D&#$X#uqp!6p6!o22*QW|+fod)afgbE4}u~`p0iYN`(8U}ugfH=dzK)Fc-0XFmeV?hgY89|4EK)CQjemxNCC|W%$mmBC(l^tCk zabcT&A)Su06#Ahwsm{0}15fGFWf=_>0lIBQ19_rMP;wc;z!9Fm@{ceK+0jE_VCNN7 zoE0%`jYzJxq*jZZ5Y+4O@6XbdU5t$`b?{L@$YWF@01)8sz7;}mOZ#Pw4>+eW!UQoN zjEXs6nHX~tw@*Or5?5+>r4vDD&(Y9aenD$d?v;HvU>PDD2)>>f>aRYc=Ya&g53>Iq z`ZJVZMTOW(gY+;-qv?lWm-Ot)wBixI2U_s^G!-i{BN5S=R22KKmJ^`tGvq>U z1Lr0F)DD2MPg~4-p;q{kPQk5uFWOr+RZjEyiEOewSw|VQ*cc^x&$Z1CxQpADCS{WN zxuULoE)CL3bf;4M+V$eT<@7#{#8H2B_8s$PK97$ z$wVoDugb?|Ms9M6K^^=RmCxDARP`zwcn$zhq|JXIO%y~bJrHJp1#Bhg9`4}hzO1I zI2i;pRbLpm5UIyw(_bEZj&OfL;%pQt%kA9Esyt0L&3SWtp)Pg2vSyTMSq-4S24zis zPJCB#B|($nd-TU$Zxr)Zp?u5!`j+O$Kj;rxkS4EX-ZAdEz6ETsuPjSDNE*5eRqmqn zOQ<9at*RFsuK^MMU4>!5Qx9{3pw(&D56#z``BoJVEP1WFVEJf}7NWOqCru6PqBeH! zzk6-Ej7)Cq2RXma+qJ$tq+ai1_>+Y_B>U>tA@b>$n_b9b+#fdImEznT=MP>Qe(D_y zEVr3ODY^Z;;`2xK)37F6^l`%(34s2R(oP)L1}KyN1PD9cx$IX6;$AI;yiG9Qy$;hf zI~aI{bgQU6y0hREIto0M@|O7GakckH+I`sWNJM0vMtH{K9{mwBsLQT=YISa5pPKuz`t+aK;r{qZeSzPHud81D19s25X^Q-rJ= zVMjk1E3W+OE3OMZ7st9j-j1;djIfZIchVO-X-$-tj=*a1DhNxhw~gYF9fM4^!NVsH z#hCrOr3CD#F+w0+xH1uJ>a>RB<`@xlj%9(mp=$&~7ZN<`@?no@GYNh=N%9kh`aA5d z(b-6KQY*ap>O*T}S?<)EyFVsLdTID1Mp;TqB2qIrTK4H}JhPAlJThrLTLb@6I>)Lj z60Ofj2=woX=KmfcgJR*}kvt_KAt4~ABBf>nh$a~g`%@M{R#sL3YBIjyrD7AJ=aFHT zxX+UDD18uAb9|%oMN(2yU0wYz*978ZdU|?RR#vvQc7i&dLhtUyn*UO2n)w4hO#opk zeM)=(Ir?vq%+x6g&}ixgw|w+THuNjh3u!Tr$pR4Om#}Yd16tpQw!e=WeP440fK0Qv z5rAbH#*8^;Oam;_u>RJj6lqs*1VBxP3Z(NtMAI)UE<8FVGBPqDF%cL!`bOsZN9PB| z{wq`lKuzzQ3V>?{o{_q?p^CN% z0BtsPjWv!;*Yz(Ib!-4o^KYUI7(zA!Aam*-WY*6kOV*K%2ZxoL$d+9IYEA-M$id-> z-r?DSv3Vd`2H?!LnbY>!)6S*4zU8~o>D7Cp`Qx5wcJCwmR`2=`kW)anZ1o;(PHZ8U z_HM_Hk#i?^YXIZi+27th+S)t&d2q9PaJmVEhK|n<&#n$Hk$+2O=NC8EH@E*K>HGi6 zmjKa}gmM|n{2wA@TpRg5S$`vBcG3SMLPkUXZxJ$D*?%Hr>w*veM#!=tyg-DE|C7Z! z125fw8X-%h?f+MV%n=T`kC3?={XY;POUC(6BV_XbAwtIW^72d>xJv&jShG{>E z9ZB=PVbJ()Sdl`S_%4hAW5tu7MRLVN_@Vfmi3%_Jyc&+ybCS=?egR8<*G<&)}Pk3f(oC0#ntm?*o-%d&F{c5$;qcnK;A@6&|8-< ztyTj{>zJ9J-NN&0g#Em38ZBZ!{$Z)bn3mY(*BR4&L* za88V6_?G6K_{=%$&BOOLr_jmGzb4JnZY1MgQTVXfeS|F7GQIxyu4T!~w#&WJ&iei= zhAz4!EBSuzYfIlB*2DjwS%eJteLz1Nj430 zHgRgcfJNr8>bJ7%M!~X&YhFt+YVwDQP29%)1`MVU+x9L>;1P#u>Z-Iop#9NKCz)x{ zi)wspoEP$x*IKr{OWtxErTeLFd+m&IHy?Tks+i9Pxv=Fp3u%^hEDiWt`t3*9W+0Vi zba)4xgSYcm0MYzD_@ULAJEdY+W%=gg2(Iiqhl%jhLWd@u0G8jgMse2nCe8mFBV;94 zIF&PZjtA8PVXqHrj&v^%IXfRT?spY<6$vcK27649cVeYIU6e!XgVDf^$<9p zdxh73wn&QiI)IA*DQdt_ma@m`*5?uK%gwA0O;;xk%RD#x18H|xy)|rid$~e>6w{=r zybfm8C=_}~93GaMX9!Omxir+LaG_h?a8aV7^xIK?VTji8mjX`o030fe7i4QbrbJYX zQf4B!3=gasjaH#bCnDuxrM{fWix0GG+bR#(17Hp*SV&m{p-0u$f#O9}IPdaAp3RpM zGw!dVn`?ApR2K&`RvO@IVrEfWp;}22`;oRmUU>(u;uskvQDlSi4WH~0OPl$UEIVR} zGV6zH118Nsy*+QPPQH5LWWz9}?@gMBK)Gyc(!O2^zS9WAKPJsS8LiXEc)+Cjs;^JM zo4|Wun@9X@1)-b=j2TUAw7#*U5hC>bm2V7*mgI8z zXnLq#xPhFX;&%u_%7$I$iR|*|yIx2AL3&v&ouz?p7k*R1n>>LCnL`#8lAd0~7cgmB z{~RTUIAIWroM)0*KYFmi?#BQU4<>(*FJ&#re`e7Myx>+FuI~7zqZ%Pk8f{?!4 zxz$k``rYM;`1_WADkc6k0yR|gSuu@ZT8$MHIv%lrH&jrGo0sps#Ji~EjzQS8R7p;q z>L4c9xj}oWveW~{07fs=b!0|5A<4re8hDxS0QCqs7KHwU6`MKTNc|)l++H<(I1DZG!Yi|%%kRi&Uya8PSLVDL+EH-5nn=g3%9E7eRZhB^%=Vel$^b0RVPx1O6)fjLhkJ6$d3e@jWfo3(kTO_ZcD_^h}{T9l1bdjWVo zeOLn5rQv?PdTinZGORAg6>nU{{NM;0!}sR)13eJ`{gM$dX(D7v)M=1M7lLm}46K)T ziLnJj2DFLJ*ha86H!Cg&&0oSnXZ2gpKR+D(d{^jp2y`V#>fWTyjHK7}Z_6q2jeYFO zVA?-Jdu!%gT%*^K=n{Z@J~;gJM!Sem!C&TZ?4DQ z3mgu8xGX>bu=8un&6XnaY5{q7G17APX9Rh74fu@7JW+W(!5W?zf5(iq_YpGO3r~D9 zFG3zKVht}6Coi&iuSd0B6tiBG7hW(jZ)zTIS`BYHC-1jYZ$H5?Q@S9m+uots-psW| zi?lv07v4PaK0HpA_+?rc@6iD%&%wI{v-5-r84Sgj}Je>E?twMy2TRQI; zl31mHa;`CJrlPnSx>){@-pO3KEKGAOJmq)z3CUMCBCD8e@KTKeI0O8m>@&Og*TuY7 zU;--(Cq!SySBSZP5E{W0I+@mSXQs#M_UVVK#uXW$IQ7Z9)G@mCsSFZ*te$<9AO(+sya}9>4@h|X z`lW+=2i5aq{^#)cVA_Oe^MnE4gg%voj|ocf9>pHBS19X{s7uiEQf;kENdRi*JBPP- zQso5kf4@v1d+3Pg`N=xrO|l-uzZKe$FG(?;)Iy$|&6V5?O|FI}euH61=z%|x^4Ov$ z1sJJ!OUq1XhJ8)=tjxi~CWH}ljxK}LQ_QtRe_xu&QKi@L?Cbtq>fvQ-qEG6vwD~D- zTBLf~Z>af2LRxTj+Ksf?-DMgoUpiPT9m6FZl9-NFpI-bY6z3`(|4{}ZUk0&O28l}s zSz^Yc`V5Ns49cqv*rQBpzD!!JOgfiL`g+SmL?-imChJuu`@AI6qbx41EI^~llbFR< zpT$3)_2vrDXl4T%O);%(372fCL_niy?q8a%V3Cb-m8~3{sl@k<1s$R8qKu#Ljot5? z&Ld^rt8Ziva}2PQjI?sh5_2r-a}JzxtQd1V@F5ZSP_GqCcVcKlIy4ahjaV_Y30Ct= zhstF@Jxe8{@Ui3wu%eE0jFD)NKt_nF5c z3T{=D26pnvCa7M1F389#;O!~M>t{!hi&Z=-lqE`(!YoYlDXim7ggkTh>7mlI{iFvg zC=SNzz*6igD6HmVzvRL&dxg>b=yf4_u_UZ`5(+<%NhLH>^a&f>) z(kobcRI)!`0^rPJ7tXz1<}Z)FyK#L78-BlH^t?#?e%&v1EAs+*rTB}l6h>V7z_2vL zx3p8a6l*~S_nI;MvNV~vtc0VC*p(0Gnwh*%0hOqXY@uxV5eErVdAe#j-2mU?q;kXl z@<}i|{a$%iMfn28|0yU#TmbVf-Rv}gx{ne*J@LKYb5C>I5 zWw>ue`f(+^ftO3W>UVaf#-3En3Z3?2so3Kx74a$qZ5b8qYO`x+_5pUIr0TMYY8zKY z>&G=wAFIkUs~lwIKPJ`aM86}RVFXD zl$LgG@P7S*NV_4Uu;HU&4GRrcAZBA0b|ufp7u|(Y7bnC#6^(&hRh`RJs}iy=p)|OYRCkQvFS6k*@nIJ@Tn?ssu{M|h7&996@~V2v9`C&@+cPE4 zXeWODMq{u|%gQ(7taB2(I{-CG8%rH3+-+{hDtF@@bVj9ug!+K~gR zT#l6#2<@RnLU|Q$*nVht_F1;3sr7o>_PY4CniciRYI6Gwbhlp7pEO8@?Z4cd_szKB zOWlV(bL)4b?ck(neLWFX)W}D*Posy!ox?wn_p^U$kM0+CU-RNXYtcZ7%7COuo6@3C zuh?MD&;D`c7abH`gGJ4g)L4txTxEqH2{?x`4Tr+57;FdCeFlfT&M==}plv4)Z||eM z0fF7wnGqmp2>Zx6|A^xX+WH{xZu0P(W3)G(m?6hZCykI(=8^MI%!}la#EOyKeKafl z(PqLCH0#l`Moeh&XgnGir)k&%G}c5thW>8Ey%qhn=NNg@*mg1oL`}d=j0pi2UcvM+!IWV~*d(+3B)AFk zCwVdk4J6jVTh8su)WB@^<81&V;LT@_2|Lkeu6jw$MP% z6+_)km;&mVJQLg#9oJ^(xdNCNA0+LeFt`yTou1IyP8D0lNGIfWvx8F5yj!%iTQUsJ zVaHg>LjA^$S>mx*fV)?I$6tA8;{S8o$YvAm7+qKa++mEqHni!4k7hZ6nhS>%6QX7c zL5D@4nd$b0%8=Yq)SFAN!ZBEWZ} zvTfpWS<^kj@wJyWG<2yeIL_4-#PnEso_ztKz*fLEn9j#cfuL3QDhMYYCR7MC&bei2 zzO~}Lg-qY-uJ>{frp7pNpy1HhO2V(T|4F6J0}=w^w1Pl-AYR)eOTEQ9?_X-A5Ib88 zyb?^r3OfHWw@fo*egC>$Rfi((>3Ov> za=!NTdST?&5q7hKe6==$-h+3w_!aZ`Dbk%28GUd)j)(7BdqbmfKW2nJ1WcNvtD=BO zQ{mqe&3|vwB&aJg0(yb8!I40OY%XBnYc%htLx5;*DW(hmjgXD`v&7gdp>fj5Cx(pQ zv<6M?sugMe52E=bu3By)ms&N?($m*?VfsM(p9opuN9F+m)3M=7mA@uUJUX4(pFd)p z&JSZ8OpEndky`Tq7nnzoLGLv6G;+lE6MQQ6P$-POF ziK0Ld=Y`dA3nmp;mk7Qnv7J~r2bWUI19a8i4m@dx6LGTlhWBGeUv^qtykIs7O4oA& zv0FaWXOcdSHz!iGQRf2^bVssFew2?+@)Sp?bG z*m!t&o^uG%@hb9&DzJ*{@hX@D{D)uJK|uS9kem(xf9~6AZ=J*ex8-|}w>k#EuFcfa zPQk!S-aJ^`^nS%A|1nM3_eg0RFAVA_U=PESZqk4U{QtO5KdIioN-qbeq= z_I}-#Qc%x~2 zuV(5GP+J2iP{TYjV+Gl8c-Xjo*V;4Q-Z#-XIM+8aJ2<`wEZT-ASB4f>0SeSMd)l#d zH$Jm6J-;^hV;w+1y{pI{E1Qd}+sixqQ=2zSyVrmbbLHpu`rhI8?%~${+3vyFKEQnb zgA4Qj2R{Ej)BiG&2b?H=9 z%I=GzS1B00_};VTkIdp67QCoM#jh8lS+!3$S6q!&1d*g{i?4e}nJc2+rzKx#j7oM?q~THUSzMk?O?+Oy+S$vsp(1{))A`VB#S220 zx8jY%ZMGzfD?z{NOK2du>PMzPui{VPn78s7--SLi;BmMawf`e8^!XrW1*i8R?A;KW z=N!{{`a#_DX8PeAYrTe{Fz-KxUxOax(}Y1SR98eKxOdj0;M74zc5-ykjiA@MbNaDb zCfkN_x)=$B@wAynlnG`z`J0JW)jOL>w%rU{$qv)zTPaSP`CF-OzjwCMJTZV<9KIwL z+Zlm$1>2dS+`HRZ2noiW>}Yk1op13b1v@#(j=MX#>HdtndD*cRyZL!J1^)`G{l!6* z(-!wQs9>+8@%QfD_f`z1{nAbn%l)!my2AbPLGHc%ictxsgUU&DOP2WasUDN+wx+&= zkJcUoN!e?-TPAe_??MXblAYG1>5^(6YkQtgTOKuCl<%=N9y&%I0bw<_QSU^DwL`iS zm$mOrE_78N+P8xkUMOI+V4rj%)EcGfZVhfy>OYLvN)uA~B0A~1o-lIs(Pi;J%Vdgk zv+wusUOcrdc03*F<;W`H%;YD$E1-J4ih0F#at5#G{NUn zWi~7?Cqi8WK8W8Jl^Hm2+eijU5pVF;N40fZ7yt}YJK9}py;YxKc5?r zTCLPI`zQR6cLdwdOzdXJm6f z;}vbWIv*yr5ICzw4i`3r-<$-{thVUhUGC7xG+%DJp4$IREqaP9JgPXlKK#|O+lR&Bedf*nJfNdv? zC4bt*kr?rokRU5^7znHF1`~Y^%)<6v3B>IlyAP`s@lZhs*}WjoU?`7y#?S-+98@qb z^Y*HvSArWIz(Ga<#5=t*za{T+kWaFKuejD}RQ6aly`*M(4n15yUGAHuRG*A|{QzNX zx*n6M^nlP4R&;Y&;Vp~40p01oceSe8Sa(|k29KiTl2jI0zxEB9yxFnE_FO=X-5Ipd zQjus4%|QjyZV=tGq?N`|7SdLE3;(m^?Pvt*i!vUAoU@c;{!xaX(jzYO|J}gNK;N72 z&?-;tdtR%YEpsN(5Iym-xbFiiPYA_Co>bv>36&7c8lMbR;v`zg`NcX9%>#0kL^@fk z)JV=3F{X411>6u{E;t%LMgO`aBDow&k7@ZFMG-74hoiE-(|>rArk;L3digV|tkTytF{Agmu(c?+MDH1bd$21L{KaEFmcRm~V49N|D}f zAyFbMPywD%WPa8Pi)Ezt`Jra*a?lCO#7AdzKq*CPfZrisc#GroQyWR?U~yAH2;zTZ z#ZN_=%QFSaXL~wX(4ZL(5Np*U!_@H^dabdtv|h;J7~mhM8e39;JLa)Cb+X`G`gkiCj~=Vz(#mAWMfEAAz(h4*vHq_>RpR2lCap(1hSKM$+@qDSD1W$1p~M1^#pXY>=BkD#4YXm2;-3y)-rV87s!`+bAw zP0y!iZgZag+MY&1icid?`aBKO+cbzLae_6rH`kBY!qF}h$H&P$bYqZMI2t9!h=0_C zQpvwB&v*QaL%ZFe!wiMG$dJ#mtedram%nCjN}OJVJoP}B2fGw!EcLh5V}}E)8Ychf zaD*E+myJN&_0z59(YlEzHlOSb&}L%E$%B+5#01kRe<#lQ7MHcntA(0oa37w?` zO)5SFI5_cQ_j(lX4VmSlHS?y=^Nxt%WY+M0UTgh%6KXSx(m94=Bjh6P$G`2P z3if?H>ysa6l8W#9TFQ5~+!tdUMS)%%t^rey_ci;?+utdw1>`g*{SXs2CWa`shA5sN zMS-M}shNa%9=A!LpUJeYQ67lI^F1GJfVoP5O080=5c0vy zKc_&iSur7`WS~D8o9G|g_UeF{a;w`&$#^p#=V|DdQb?4UXet8YIT{FG*9dM6`dJfP zG#d<@IvivAlxukXdKDsk%DCI(fu|wIEQGG9&wxV^Qq2?k`)x=kguEp4OZ|mqj{|Yj zMMw;xmqLtJk46~GfIXpO4EraFrhObAXp9|weUVXXtoGly9X29{GowF#`)CY~kzuL{X5%U|xZOAWww0KV$jjGNm_V`3^11FvEUwczY{w|g2R+eq#uiDcGEYJt zW19cL^t^o9QfEXqo7A&o^uAT3zb<){JY}3WWl}R``cgsCHf6ppWpOTL=`v-7JarAp zo4T%6R4>9y8t@NJipy+ZDcj3g=cQ~qr6DI z{OE#QpMt#j#JrdDd9I`R_AtzpM+KRT1w)bfIW7fxE_uB3#^eMjp0)@`CB8T8!-=H$ zZBVx3m0|H!0S0-Yn^@uFJW1vL0>agT(tdiv7lmPE*^0Zy3Z=!atBZ(hFe0n%lRR`nVBF3%YaP`l^Hh$q6mz{b)?zj2 zgteU+<-SaO9(x8a43y$aYeKL&!V2}B3t^G3>$JHlNeOGY6Y3I^#QS2YQUMjuNkg5DE35+8yJ>rg8hMO5`5xH>SoVS#f{u`c>^_=gP+3!sf`z zn(@76f8v%?SLUfg%bJ14b?p}G%BCL!Eea0JqYKT1kQbLc(V(w zlh|~qRxq3*7zT5j%z3M~EERcC8>d)JU{V;V4s4&e5vC*h(5mriayu@6>-Ao{IBh$$ zy@}Ed#=_hos@nd*8>(>KAwM$J2QO)7Bnd=Pwx{)GE9K~c|41C;?Wi>1{-Y0NHKolmyTRuYch>-BdSYCNU zLMv;ST$iuJI1Ft(HiDX&MKs85{5P_35HHg51q(}BVIT2t*sBMGyzf|ALpkeovbzYL zK6)}araXpo;3=g)3I9we^Mr-Veey)hAwJF^SnbqcJ7!A|npw)U zMas0MCsp9_wC$6b55<@!LepL4(@tS%e4d!3)H5DoKy3`eQJ&ekX_}86)BSeFt{Bq} zj^@L{%nP42PeC(B%mzQ0`RIxE^$BwX%N!2^&2(it?snPkM%_WSwPEOK5qgcquJqy0vNf=YwT?fklw+^6%n#zVt~Pac zRVLblH!FPbRl@dV!lh-~2dg9sOk_(d`R*9SEK8KEs~#zHG`dW5sq-~YRw;3p*HbY0 zj@M{QmT+uQE8S6_rZ2BqV>*_u5#cWIyk3-mEq_YxZ>0kjNtr$BcN0|w&72T8y;ZUoR(O4sU}(KwFxJ~l#SHj?NzDZfsq z;7-I~9fL&Rh>#ph)4s#QH~10wn7=)aE^LmnQ4gFI7B~^;xapgra18KMz|@FgKfJ8N z4q7>6Px9ni`RQ~>C?HD{bkUQ7TN%AqqMTYv`mOJdSa_|beVdT-441b+3jgs zwV(utrtc&nOEBq6pYLx#peKJ6HH{`uxjL7V5@L^DY@B8l@-r`W+_w$g*|mM%~h)>*={40xFos?J){v6QW`p zg?b=(s1Q)U<8wJ=iiX~~)CVOQ{0nbEz-{?Q`N-ds?Lz&_FX}r6laf>I_iKzRXz{}k z13ZkmX7IetkFc-Lees}4qrb6MFjH61iOVrk;eT=}pa`K0ulM^@-??dySaDP+%F?(i zmQVIGp&=s|8K)N!iVK(WRLbd>+Tj}kE1Qn^UrJ-qh&JrpAmK8!*1Dy>B{#IK#@F09>f_5^2 zX8#Zk-&=$}5N;HetB_30x_&)mnsJ8)aR`*XULFs!tE%}2v;U;6=YTi%D&hz9c- zw`?pe%6D(hNtT`Jm2<9s7U_wSrHAzC#rAuiLUsWulRJSWm2Cht;MsWGl!fYLe<|!p$CKqpP`9?Z$m&Mq;l1X!)xkuBJh71mL#hdYeS2VNmp}S(7?4 z|M!)pK}9#;TFgU?YpcpVZI^@aV#-?TR zf03J8NamNQLbuHCN_qYHy#0l(xugo{bcx%W#J)P$#3hosj7 zC@wYQTXI$rfa0RF>i`r746*>xWK?WL8ZD8-2?9%pviuR(~E&#uk z*7a02_J{p5ze?yqCIOkb&Y_yN;fA)s^477+uDP1N<;Kpj!u~^Gdj%Befb*`pp^e6I zKqC43@BFG|`V?SqjfaN-b?fY(=op;q9hvW#oF5sR9sp`|0DGHSX$9t2OTh4IWnvDX zZui40fVwUHv$vW#zMH)-(Cuz)-!H8Io8;c%zj)if4Xkc%@BVw-^#9&p03b~fN+DI6 zF6@^UBydsuUEvObuF_axOKhCyW%9qVb(OI3#T0+$fvQL)8T-tKD8SGF{Z$%6CUo)2k? zPml6X3uW}bur&$7Z?3$ymOYVFZ~H&rn7@55*+pLa)a^tZLT-O~5SQ#*rQ`(jBRj2L z34nD+_Y3BzmbGE1#h;D@QkifW1U=8GH3)gyWJVp#ST2<%&fOhv7$8*s4J+tXKhJtN z*#js|IFcd=0BI7^g!cS$>7!u&n~LCQd?oV@K@E#OV{u*GgpF83ZdJN?(;VlSME%Si zI#F8_UI3&?nEwD1oRhbKXE*9{)4pINZi)C@LGzM7(#>yW2F$OUWrQyAGGs@X6foFc z63lOX_KsaM2dA6N=jVRYVq`3cu_+kO_su~DKQHp=-`y>)UGk;C@oo1^PA@#(&HY}i z^~mab%dpFSY2Rkzcu6lw5?$q>%-(+0Y_Mv|bM_k|6r5DrI8*0E7wkjV#7L(7I)&kU zo3wos*YSpB|AoVp^KPc2<{KAZ3dTe;Z<&gIRA%Yw;N^kJKrozu6Dn;4)gAo_WW<`-St5v)5T?o%7rCKg?oXT(9f>`Lf&| ze66y+J#=b%g>l$?`O|H`9+UNMA-(PQ?Q#FutGkooNWHtC1Cp$Qdm|b)Ewf{aW%m~{ z2EXnvWj%ieQ7^@(3ta7fHQ@N1&uRJlwz-HEd3TrB*+=~D2=B%H-DM0Y^$d#BBL2?-NE13?4b>|SBv{AqZp*wCK`J1j^k zEUOz)g@GS!h{F>L9EmeyP)jIReD>+-qduwE>fwWLOysgjb`ciclIFL@02xCW=Tgd0{KKsI3Qa6??n?@-{f5_j#fkD@rxbAoVox z3n7k{*)xL5XS7X~1FH@{1@qe@pXI)c+E2)mS=|?ZqNh3-0ktDcT_gNbKGpI}3-b#b zVw=kIjqKPb7X0@?Ta0w`x$0`(ibpSc=tsTUEFv-!$jQ)1dTj%g6GSyV3q^?-d{Rtt zhoV1T^^uOYD_D|N*++V9zE};ER`qLFP15wo(QikNeQs1Wy07kFTKqbH*{?U^dG-eC+>vh$y7y8HFr zNB2^09k+dVCqd2MW-L5v+zifd>Znl}BB(j>(lW>ssMM6vX~{(@%Xyx47QxZ|1FOGa z+WYYc4@U$tOj4>>KM)WXWW8PbwvLzX{Px2d%7a<9^81Das%;U8FjIl@X3=MT{CUS} zHYw2@yUbuyN;`?LV)(N_zX7CeWwcHuTWo|{nCfc+#$s}BxFHF(I&EycXOc;%5<<;* z^jG49RGxYdBXY!qdyjEx_bYzbX-9viefk0RcY(I!(T}B4E~Fyg@i~q9WnSZEUb^qT zDl?kEW8=&~lOI)=dy4y!C#wrJJVn;jb<&}dGmq==olM)6C?$tu4ADh}3X-_znJU-5 zc4Ej29-oB5-}T^dG#GwjCI>P zLQo#%TOC^0ZP`acI;thVAKDdx9as{44~9pqBi$8%s}=f9-zgq8CB>~=VdQ$VK=<8m z$&{}vI)FtVH1PfHn&B*6CKzVwH{~{hwKbZF04n+_Pv1~U zW?cB)mNqh4t6SOnCq?<)Hd|!Fu&Kgn(&F6?&sf8#^XO^X?cI0b|0he4dlY)JxuRIy zkm$KRH?Bf6Z>)&pU(S7_7qwy-2i7)j^CJ;XwVx7L5XA47E=Qe9^HJfB<8G@x9G9ag zKJGs0p>_o)to}H^k0UX)x+tHdS8fI#Yds(Gm5dE}ozQ_Dz9z6ODRe>T^7t%^uEj5{ zcYP|bRk}xCg5u{@B>s}^ws(x+p%ts$`QGEmI#wq}vq(uYG3zUAUhiYppgVth&w1-o z!ksK61CdI)TE(RiW*c^czsIrPQd;eR%5NweM_L2y6$fSwv*RVu1HE5Rq+mXv`6> zPTilbYB&Zqk?Z=j-^uo+&to4hhnHkS{)AL!J}mT9G*>?Rcv1{fPTsSW1)ORx>V2y^ z9t-yRCMti*r~ULY!Hx{|g>Zsj)LTEMY(H5uF6v4fa-R>eZzyuT(1^WIc#bF(=KMb@ zKh{X_*WvLZN_e7~@4u?-{jwJJ@`wiC7Of@T&FT}4ZN1k@SAex3%s0-p5O%R(%2+OGtYno$aKf+dh>}!`;sl-?rb6vuQScU6Y zC6YLm0d0BSxHm3wnhoCSiE;MmFkKg2o$I(*!Y@V)TE<#mbk3nHzF!I*zgS*>v7HZl z@K*ohfYy*ke5zyorv@$8hWNx>YU{mti5WpJhJ-kYgk7_Qcf9ez1qts55@2`<5!Z@A zB#AL3T5(Xf_-oBXhQwqo+0^UA2*RYS0nHq(q!7oX{9w((hNOU*r0~6@0QH2*Yt3q{ z7oSYT`p zw#fk{K9VYc!!}P}ZpOeY$5HCIUqyh@p46aQD#2nhpwStyG&XeAqnCVzuq0uqO%JAO zh9uh{Yuwf=?{_cq+KrCpb5NZkvAX^OaC_7zj%WFlxoRP>B(0ozA95{36fpvwE|J@i zG0)f{=C^99qX?z-O`a|3SG0#uiKXeu3i95mekC=}`G7vcAhvmS_`d2CLexnA)Ileun@nv)1ugms~D>z zb&!#_pA^5#Li*;o_#sybrb_WFti;-SaC!E7qmoi;eW zDS;=y-XAO_ERtA(m6OQ6{?!P7uvlRpTk^DsXJTIuSEQ1L|Mip53MPK>UxnpVx0UZW ztKi6vGEO%UcG(Kz^-5k@0rQhGAtnj_p$hW#DzVU4U9QsH$<_SevM1iv3Od|$WDg}4 zt8qkvc=&5hx{Bq<9_CQi=r##RVAbYQel<(3wP>o9`538QWPtBo^U|%>gSXar5kAdW z_W-YU*rINay81~+-RGiLvLC8RI_em>>t|JKA5+yciTZ~O3HTS)VN=x~lQgWL)sw$% zNRSmWSj02Et&d-9sPC!|Bx`h(Z5%#rAYQMB9p@B&;Lmfz3u-EY6E)=~R|d%9McfkB zHwhqR8Zve83T~SsI2uU28(ZHt7pc|{d?;!iYEHzjk_^osVroh9Z6;!Gess~89omwB zM5|fEYH@(J#%?xm{$QW@(6p1xTa1O5&riML)^aGzyTOmQrR$bQ?z{^_@c39)q<=eEG0&(g zCBB>*26tyDer298Ih^(p;}XwO!ILj|T~T6PI29z^!#q6}ux{ffrd${PC7$Q*?FgL? zBld0|)%u&aE!<|^M8(~{UDc>g-74<;O$d>S7Z!yai#!Hl;Z^3fffFCM9C9$c~P^8pR5lfUe<#B2}4>vV^jr;P3|4GoYF zm&y&F+;R804@@)n2d`mV7mu|tk1Sh`&A4OEk&j#24{uqHN2Flp6^~n1p|&iI|70Fs zW1jc`Bt2gJ1RxM)D(Fc&o|@7mt=^=)aId{E`eQE;X$!Xk8wdshb0X!ZM8?6KY#=m4 z)Hm&T_D55~_fu+!$#^A*aRw@D3AdOM8s+jdr3XmI9fadGKwJThr^NJE>b1{+hP%^4;^j- z+gWN53VJyhq=bf9K1&KmClNunKwvm5W2z}Zm^`3jRwH=N$+a`>N-tjUNp(nTNz2cD zD|=6on@Vho1|nDkQ^KbR+NZ_K=j07B`ETZ&C@|D)p&x|N&C4+o1TjfQ=7V)$Qhay^ zr-8wk?c!SM?PqWH*eOOm)W=K6H8Z8(Z-R>t!3youVn`4Q$~ZXmzVB7bq94MxrUn_(TZl{ z=!SonBHdWNJ3K~l8vX93&rQt+g10Y-A&<5&;ULL1Fd+z&L}Xh%V&2m5+h_PUm39=Y z%I~h@UQcJ}OnyS)>rji)ox%)EpV9BqBx{f~={MN6n7^Mx(+thJma$hBn8(3>%V1{^ zI*BqQx^>b{7(E2B^0plE`Ur%jvO%Y?%D5u;{3jh7%ckPeQk(d4RX0J=d-YY7<}X*iSCr`~qtl;Ayv=>3Twk z@6HVs&&3qa4g^k36}L?Uepw1}tFd0ZF&I-9ymYXc>GHTVjJb4ayChCK|2%fa$9nZv z?26IgymoXXD(%W4eJG5T+wa!}VrAdP1FSZtEg%jaD&y5b#RHYoCnX_A#zbp|j{nycERE zm$thO);ny^8+ZqFLh(8isd%sT?jFlvhy?F`@z-ULA?Av~eW&8ec-ejIgMqy=E~{~j z*|uB4%=;@~kMjvqivxM~0ImqeC8yt=6#COuZB3W2(+1&D!R#u>|K}rd>?Wf*T2pxg z+`NnMtwhra$-oqDXdL9@cucZ%+@Gb$J=J{WT!mcinSJ%}f@i#na zTGi&tX-0p$Dogp1T%C~8PF1~gS9M@1(xBZN{ZCiLHe4T!uT%Y@aC)=P<#-yiWIlu|A^oi4a>Z<{;6#2KSGMIF7e`I65J`l%h zy0UaVT}u-@))MY^Vt+7S13((Zx=z$o!77XV{H@Cw&{bW^H+?*u*uJj(YOwm-P8OWhDH8myFjDbZw39Uaxl&YScs_`dh zXXlSjZl6DY=GF2NG7J zz0Wy%SBU&jihSRK1e^vCn$K0o0MfYEBSS+&!y}_2V$-9dWB)k<<{On45K|ERr8qL_ zE8sK%$yE`_712rAh}3^if&D?6%;MOL>V&_sRBB;!MqWvF;h)L8f~vNd%5Q+sgg2i7 zdwJP^k*2t&y98Lu`-3#S)h&bNZIfXg$k_h~q)NI+%Q|L(K&rNVys~?~xoi9%p#ga2 zpCYPt_M~O;ck{1b?OnZHgEPP=UjOKP$JG4r)Z)bK%GBKI*z7u>GE?)L3oBbaYsmTa z?~5CI>)ZQVdxt>z^jBg|){gJ~x$E`6G3I{;CID%K{zaO&-waxRkp><|9|j;zmnRa} zVku}Mt1kdwD8xPJW45#pg=C>FL#1)AA}e}px0EUnYcewh4DTK1{fjgNbYnsMkx!ow za^|W;D>87Kkk(iX6-WRM5?u37?L;A4TRaccPKA0ywIz#n0Mew&*8QB5QWxJ_F8Wpq zAPpMUV*qK^yMpkU^oQ#!0HmP?rezx{w}%oqK49FMtNKgRiG@CvZ*&kD%aAY9AGx7a z@_tq7C)&WfOGc7u2h>hYb-w_l!Fr<5Tz|YmcSmk8+U#=5$CM(QuAt|9_#**5%X*}R z|Ht7Vv*7*sli6WV64^SeCy}t&=`(KtH;InQ_07W&&^2W{XJcVXJ)MFip$)SBH8TsRi>fU@2j0i!;1m(RN))mCmHTA zzU71<7NS9+q%|)*+@!mz{Li6)ZRf=Nq=#ik{6;ItA-1+C_!?!Ml&_uTbW>1}Y3I5p zRGju_{Lbn=NDRIH&Dt(K@j_BjDe`DAyR6~o!Vmg7A~NO@Q@qfk3KBl7;_~4)A4)W{ zZBLj=)h-GTYnO3v56jkf;ty*HW8I!>e)o|r`Ft3C`?K+EmQ1ad=+45sac;ecwe83* z+NSh&)Gf6QjAqHI3fa^?ionr0I_e})wfxaew05*v!DCol(XsRN$8qmb$iYz`;XB9U zfoJvtFZvn!n2VxP98%ch5}ziNjPR^6zyHFeV|z+pVT8#!rbhJKUP%&bnPVd9=Yhkd ztcHA1e2Nm(F+lSJj(z{UE6#DG7Mi)EvhbH>yK3W5kBh}1(s|=i;=z&c1@d{<_O$wp zNSr!FE$+R#&-$diSF1sErB@qaFMnQbA|zR^w_-J{{~%52^-hZOe?yx5uK>~%*ZsWt z@fT^TzX3>7|Go6~CxA4!zuEz$IqH67b9dZNR|X)>%U^e=My1fa&_%q_@VriH8kMV8kLY*CXFOER_{bsm_Ot0lt)SnV6nu zL44Eecpo@2u}wAOTY}i+8Hd-ApL2p9t?i?S1X1AtwUc;l^@!!W)3>Gil-*DHj)UJ0 ze0jh(j`D=Q*Z^3xAk6IVVS#N+^0g=6CVgU4`n0C;7}WEv83>qOTN?2{^~Ge{KzUJp z9Pz1Hy1Bak^@uT);C(v^?r_Fy3Lmz}An;101$^21V)9!gFSkBg#?&o%hNNwJ z&PkP`?VViWU^8KLT3EuqnqO;y`OZauN#dkhK6?`bo!wwxDV$4B_z*{hm2QCW&H~*+ zU|cQ6;+c{rmxkscwRDTCIv1*GQQWOEX=|g8f3J9vS;1wCA?5gmiD3W9PfHX3Mfb-Op;z z=Ieqx@$e6^G|zmX!uhq;|NorxYP@VY3NLg2F1vcOaM^k_Qug_BX!ZBaWg7^$+zV6p zmG^KvHsez^Wlgw2uAK@9m}@?y#usrtty-f}5$ zWNVH1ofjw1bHP|0K-3gRos}2l1VU)q(F z+_O@*`yYmnOy=qtYt!uYVri98;a(ZyCieH)rjl;6uH@)6zdu^N<8bTJ+Sf^D5QHg; zzX&m(T&(MhCS#tadif(ynxgb*VTKPCYbc_w^>XCb=iA%W+9|9DljEFY|o>#;|N86R>5)}kf6fJJ38I1eI!%Epnv6YXxZJi z7yl|b5AI*25vN+Dew@jbve~?lTJ2r^@z6eiwK8gsrLjZ0#33O*8Le%@i!Ny8%oEuU zQz`>t79-9IZ=04hG&^9WY>s7Zk?DtWSV)MqMv8!GnaYC?ec;iT156T8&@szu#KaMA3`Q$AE8Xei< zQoNZ&Vw~pHJ^U`V?n2zBDdT7hym?i08woYS^GNVGY&he7$LNFSdTd*0qrEM9`1?u& z#xa3l&FuBQmP}2J^xS@f$@*!1S=prZf{7q!-@w3n5mOMkiTd5+;Je#cc2F0Ltlc<`4lh{=ag2T&kxtaMPSn>~0$6ii z52VEK5}0uFJI<*&eJ#T%1dO^ZR&2p6Ziv9dPp)*Uz1Dz zf@b#EDm07EG1}u3Pf!mYb9OnMk5tgRULH>%ctS#Kj-5CoeK$%Q3A?C_(FBOT@uD;;zM}9h`&t; zH`fXyNgU=%j4jap;*!`OmzZR(8$6$w41H_U%L#n5o1&G}>6rAKC_Z0HJ8?3scs?op zJjnnrxspVyxeP+kgcWJiZF8Ni#I$Iaw7G#a%j&eFc?}?VGE+~# zV9@ym)mK@AP$1A$K==*#F!Lke9VE;QuGcNC-#CF1QVy(~k%hLSe9_EogYsexW>l?b z?40p6vS$*JW_5m-Kdm7n=Y!XtW)d)F5e~YX(LBps%b@QxD$mYhcFnfQ4>X~o`)B;F z2#=({JJV>6k2@rL*pwf&P!H=VOxF;~;FGgpD$+rhTkxHi7S6_DW-cB zf0ixur-n^yToDNhK~qwC)ph|=sd&0jX569#H?gDuTrvrK993OXDudt4Sn4cZ`l_Pn zdq}BSPs#FrDRC^sGc&Jwq4Xp~&D#|p7{5~jmrmXk{D$dtFO;GE5O1(3nR6}IK`+C; zE&ah)@?cQ{^r3Xeq8y(|jBuz7HMxRI{VV#93fXSs#lAGTucNn$Oy!Bs>L}AWQVFr9IEdu zDhw;2O8jEC3zg!>mB~ld8cc#@KdOx;YJ|0G-@DbCVbSy_R&#n+>V>8mxCy>>tCC-@ z)hDYXepYMH0W}V-o3E-Q?x-b>;vyEQO|DG;TqNMCQ|AZ#6PR3&7F*-<13v{(gTNAu z8my9~smHvky|HiL;B4@BtD8U9@aEF2bLFjZZ44vSNYts!al@D0ZonojE*#_)ztV{g zC9LKb+Mt2;ht$VZ6^}4BFIU&I+|~w$rsWwmXUOuE@e{S&Hq-buv&gnca5kiXf&(|3 z=Wcn)kYr6({7I2NT2`C*vlgogdl(PgT2Z@e7u_<`KeYY~%{6)3B6?goD${yiB=|*# zprWbyY_YAls!2?_VY;EsORRm>w@s*``jn#`yP4O^t^K94O~um={ANB3Yy#Q1j+};$ zt<9PzclB7zomr1vZltuxvgq-XnOZK zBi$h`&3)bou&024)l#qjUGFEae$~wWPtARSln?~@KnKTww{E|)*MNNHKuB?){~Gu+ z_FxKak?5oTZ%h1gY@@)Vcl^@G^ufUTF#qPk&^&Yhk-*Td z<*;8n_{Y-l;oWG=9k^PTV8wk%(RS=gZggxI?862e0mDEo;lGv}&te`qwH*3%G=OEr zk8?QMmV$XNM}TC8x(ZJa%JV-u9JkaR#0wu>BcH6{n7m;gOS~KNDF-vQOfn-=M-+sI zYYs;I*1#O{Q`E~tEzA%K!D;7V48iAk>Q;7}i-yx@M*U{7xBr>3-KeZ@{Jbyp_Z5h12O!uBo4gm@( znY#{Kkps=_9xQksExC|mPzuj@R*;!}=Qc+x3ZBd4pI3ip`&zhKzB)?Yly)uG!KD8g z|7HpZLm2g8`P?I6)Mr3Zq=e=wNNAtY?+aQSU&fFWCZ0WnYJQg%!*tL#MOXc1B3m1y zWrSgRCWa6;rV~lc25ri6ZuXxo7viJfL@da8EnvZCRgV{<4QEYCP*5p1t^{Ek2*

zu9R_UZD(}5xecy)NCtwr;lx@9fok}8$LQ6L_ULx~#`e3k9is?7DCpbw)Rj=dQF$^s)}V>VjGd4)R0(saPU~~odQ3yMJ>WX3 zAtgcl(Qezrz1Wq#G=;sdU10Fq&Oyl>0oy1pC8{YK;add8>(T);IBJbNaax*_cLbBK z{;o!xQ~Jt}jMn9sk2eXAQ2DGi*TOenC~R5`@`>Pn6ZZmPjDs`|XT%XG?uY^342-hU ze!UD(UoKw6|ql;MYg9av7+=Z{xw*Y*;vo zDjOk%b>CuZKN*6UT7N@Sl9RsGk?AwJ^uV(Bi9s4WK19Lq+7benPhhp;7Dd2~qFchR8vuvD+Mu+sM^XMI{Jy zf}s1?O^7?DPvl)%_TATC=V?L&6UecfmB>C9wwu{D-nq8xRL|RG*841>-?>QeT-&8f z`F+=u`yS7}^0D9Po8X@YzvXN(Paga^=S847uqNUgO~Cl9+i&fE9KT~wFEyT@+?Gus zPZjv6GPNU5Yl&+j9;Bp_n;wl@5v(=6tDN)Skmky7N4{7QqP{VIYN#abOs+zsGy4Z= zW=etayXVqLA1fBHy9u+ul?l_Vlibe!C(;}ZDFqX_TR@Ih(!{WE-zeIEj2j)+VPk?6&mX>oqDsh_;2lWn{?W~ zmKKO_s=s{W2q2BAL+ka+qunV<8#;rPJC`$(;4;(IR_^|vWhP~cf05=|;QT{41Ox;` zB#&{4{#6{}XB=cqLe$jM^z`)P&xN0ID>8~22uZ(T6f1Du%WOmafK@fZ#a0xVZ3YdkY#xioXl`$8Y35{290d*6q~I0<5d__gbX^=L(oDTj{hAjb4! zCjO*0$*bl`(;t&Z-sk+X$XEwB=R^Ll_r*x7f+LI4zm`+^Z*Ak{<>eO;6c-owH?_$D z6vscN0Pq_CZxE@Kz_Fv?KY2}FVrF4nW_5gaJ#go2PA0!|(Q_l~NX2EyC_RUDwUscrvr>F5vP zbj?@yuQqi}Gz?9*PRti|um9zo-?c+q6+?UV;|Eo<$U0!=Zsw$Z=Bo9t>vaA>o%x>G z<>9GiVB-!Doz7(>Fl{$Ew+Tcx^Q*f<8^8ZKYBaNpoZm+RyLNwcXZK+5$FJ>wJDYQ0 z*Y5P};`sa)IArv{JDdOLY>*Eb|LJVt)H45eHXIg9|Jm6{SN=0tr<-UOG!)PLADs=4 z{r=KG)mMOU#7ecfvVA6C903@5gVhC7UzM_DQe|oi)q}(&2qhS00G0jQ+590KlfXh4 z;eNVC^*@9IbT-NwnWQ&FW&aY+oaHk@|NkT$n>SbdE^I{2AN9pA%zP9LyOYJ3UP%<9 z=K1EU0)*38^T9h;u`Nx$srFD6ivF`bno)gOEz#{C!rAPPVFC!J!G4qWP5>CJb3Ny0 zEdH=Ms#m}J3-&e{*(%@Kd_A`_RaDpF*0P`a)vIk+p{@1)=ftlctE*)ENaUC|P!OO+ zokUvxq{+|lh5++$K8I8U@wOc(X6yb-+kxu=qt|`wfrB{2+TKiNCu_kwaVkcP^tDp@ zHacNcx)w%IjX+$=o&0Ru7s8dBkuB&i&=5i)^@+lT#nCy@EZhUy(XxdbTd|n_@q^J8 z74(@}Ed?qtgF-mNj)x{AFKs|!Y{Ot8IVs6JgIKsIlqMTnVmlSJhu1Xq!|y!0RIzIe z4MxwCft}20LQ?vyTZTs3Y-9s8(I&AUfxu3@qo&s`yi?uFO>~mc_?rIPcTXtGZoeQm zFMzQ?G^Y~jYEfw017j>K+kwq0y&zZj&MoThDJpB92xes9%yYmD6<|px2$S> z!!*N~du1^l-}%1id7Z=CA}jQ@ESjHn9l$~9vTep6&zttNnSQAjC1iP*ktRI+rFFjI zrq+53`@q_I13M^F2K`uI?Lax@KWalCV`5hodz;xIL}=zEVenqv{bMiLOUs{(MAYP! z<}^JBPb?DI~u{TOGAdfB+t)c*VE z*AGgzbd@+t%BHwY!>6M2cKK^`b=|@pb>9|AoGa-i>siekr0bP^lm76$POilydTR{7 z(8xLc6CRRLrpey%A#Avec78zr-M7MTYr$iO{~r?$>)bOop1*{X^T^<%20%DHMLl11 z=IvR3Up1K4%wX&JD*}Ym^lJLeYnt58w`boJZyF_0tO3G_jChXG+UfQCMzS3hRf13p zB$h-35DwoF(AfZlBP9Z%-NGQ2f?!x1w&S{%(_zUOqDumVlceMWW$3}>F88L0-SA}# zqmmcRZ^!>LSm#b@AahJpvvm|m6AN@UiG9L&sK8)diebyeM%OdG32(8mrzatrU3A*) z!BK`Cgmpop46aemYFk;v9}{}m^^Zf%z>m>x;Si3-C_fYTcMqqeB-vOBUdqR2KPDmW z6Z~Bs;WeGgNa>BiDV+7u8@OL2Ig3dI9Fq2+)ZN3b?C+<+q(;dyC?|IzAQJ!Jh(0mt z#;8@Yt?9=Htn=0GeB<@?%fdAb0`3<KJ8Y{gc=+ATDzVm7wDps256z+XNW{+;Y-=bcn3%a zRmx1btJ{F1{8@8@dFGl`qA5Qj16BO!-}yua}dZw!!iDA+=HPKvlVijFl8itq-ty~2~h$7`(i*Etlj-`$z`+D}< z6R)}}A3UQd4)QV4WIO99`EW1!?g^G^&nQkN8BVN;L~KsDk4^4_25Nkfrg@k10NkJ5 zI_7QoP`;c2YFGP13sc#}1?0j-ZT(1zwe!&8%FRVxJ5H%>pzP8H>1BPte5qah(9#ay zWy5%Qsl!*<<$dkT#<`JFr@Eo#pRSipYdB?}`eav5k}jKf<;z^Z4Xs@K&x9klhDvtT zPKyV@?q?$dOFkpCONg|8{O}pEWnae=l764{;C1)cS3F;fkNo+Y@qF%lJ8GyZ@?1~f zZf$t|{_v`z<6iA)Bz0Ey$d3k^~sK60Dqg zOAvxLDh?nmnwZpGYN$U;?{y6^x8;c#29)~ zT=TUhG2P}$-}hHAOmrD|=45HvIf*v=2}Z>3)l6PUF**qct{C%EIhKn^QC9fcB;PLW zD%3T88~N$fbh~^MQP=!kZc`Iv!f`Q~_yJ-AcS$pj?J)La&^;n%g&l(dhG3VadV;FIQJ_@c^=C0CM zt$zQw{0jlWAE!IA?<;VfN(_u_O%$6Jz5$(0)BXRMaGVEojXDsp=Czt^bTaJUM?EWY zHr3_+vcDT&dPz2K(J7{Ms-{Wh>bh^Dh_A7nqu{4DHt(XBg-DaX=*_mlfBS?lSUMrN zudFv);z``i0=~KQyZFk(=Q%|oJD-PrXw`(vZ2f&EKVSBLN9gYgyKmANNTTjDpN2-( zXJ?~uGV+)XsnRJNd@u-DR+K_s47_@$=Jon6ACz|eD9h(;$o3v)F4QO?&$2dw^ncNe zoKWu=kfa@OmYMV<%#c{r5JcH!0-ITjO-Mx&NTZwaVf9NR#6K_Md*euXKg)aOXDo%h zVpD$H4N5uc#LO0vK`%bt|7ghH$NVkq9ic#~x`)_V_yE1`0=?g}HxWBQZ+8ZIKYfJ&mpL_($-70d_1JCNBb- zXn+;`QRxf;GejFqA1J_u&UAQK+#k#(ewi$A3BMc5~6Rp2z>gP zeW}A)8uSX@#9Sl&9eB(QN;E@?>SKO#5%92u@)!mS&+GN_gmJpWesc_eJrKK;t4z@k z{|Slvt_~26K0r8|0O2&~W*Ax-xESd3epylf@_se7RG?ntFm=Ucz!u!iT+tF7(9c>x9qd32_a2 zz_)c)E{Wj-iQj4xaqto|q;;~il4gL;hF7mJSiY!0H@Pyx?K-KIFqxD+xq3jSHZggj zCOM%yxpzDHkvBj%I-LV}-C8Nhjwyo-dKJ=1BLg~s-!yThPV;J(xTN;Pr7i@g8Zjg! z%%|oe)#H{J(u^h2(#%tLNYu9*(pqNHerl!ek)(H{r;|o8oN1|qC8poar_*Gn)$OGZ z#igKX3xksIfGb9WSNPDvj9dGRwgv;#3KZIUnj(BCsaGH{IeN_vCs;5poFXGG%zVaY z6gH8uPecBskfw+_i$pu?JrDazFJ3*n{=Nf@36?Fxlf}mum^*F2A)0yIk(EzP4v3Bv zDFK`><*{=17U2_o7*vce`|GwMgmz^8F^QIv?v&(q5LnkoTo_?nn}5s-5DUF zCnjb_c~dlUIRU18{;z$q2)sSl)C0*0v)twa6?rwCNFP7&{%TqfR6iS(|1RhSZ^UC{ zbuROI4lbVQs$pOe3svE|lM^z^*HlP&l-mRPF1{gS49m_1dt;8@-`=H1c+o z{``Uu_+b-#C0&li1C7Psw__`13de)O^A>V(I>ZL|Gk9}L(k)6yLQ0znO&j)0X&eg| z3*m>1WxZl0(ArYy$FeI@slI*q!A)7cdf9iG^4gk`P4N1K zGW=wLn?X2X6C5qMqCT#WvPjCiu$;O`fUGE<8l?==tBPTSY=GU53#);TbVr-jr! z%&etstedQ=HAu#@BcoMhs&C({6EA|>Ez*QAN%*_rMUpivy!+~rjQ8nA^yVzb!y<4M z7)tvQXwOG$7*$_4SpBG@LBl*hG^8*g+oJW@p-Jn5OsF}4Yhl5#wmDMW#f6qn{Mn6?)OQ~H*Nbm!u?paP?Q!3 zc7t~CbBiuM{YkO=#TpT&8XVJvRw@%b%Z6%>X85||3OjijAuZ{!0O3$;#sZDPrj-hJ zrx}51YXw8k1VhkJCwg~BI*h68yt6l|gL8>5tf-KZyi-uF^F>E^XHyOa=Uy zWUCd)BM0C1+Fu%aP^*n6noawxrhsHK^|?QXF00PJr&JP5jMCkCz;P-MsLym&YTHM&S4S50?i? zt?;ltCf0Q!vgH%4QxozaOd>1jQ@xRZaWL)SkOJj|64G!CYh?0y_)y3Zn0=X_!(+Us zd6N10xbpZ^Gsl#W)hP7&G*#+wXvXC05`G1?nfp7iE0Cw84nLuospFWDvKm!58mA1O zG7cXm9GR)#oKdqHwK1F`6qz*%A9@x(t0zBWa6haB8h?rNErN2AU;dk8$?PKewA;ue z5PNDJLawprYVA=#M{@{@c|d3cyk-KG(9OK2BFZ7)k-6$kaD)d+*7F4-r3E53R1&Y5 zFeP*VUA`cI3b7Y4g)HLVDftXTf2)TLT^aO88ajy&FF%g)*T!tFi!V}3?{YCff`2l3u|Rdl(QEX7=plaSwZnbkKP1_IG(JA) ze09(m!G|Rb!de5t6?Q%R*9J>+SCmCi`1!31}cXI2c5^_v+^yP>e~fjS_yuP!~R=P(Zf=O>wh-cU+PF z#InsYPx!=f^YJ<9d z(#o&axC++L(@Y4Eg!GuNHnojbDt(VBkYH&q5SlP}&}xQA@C2j?!O6g33g8Fr2S)d^Uxd%3enMWikjY3vt)$jQ?3W%=o)Q{Pz_?VvH}k?BbIl)b+_lYU*`i)%B46So+vEd)Aw;VmFE)bRUE3u(8WRp_`ls z=u~Z2e!n0gLbrKcH;U!A58qx#C_%tuw=H8gu}|>6cwP%w-SsKn*m~`ir{78(-i@(d zD`$MuPruDX+T3S%-6$X3bUe8&_;sJ&byMqkW8yKhgS@YKa5wnmwr=%zIvRSh!EboQ zUBLL=nE|r+0o;cC{?GlQ4$m(HEXMgtcm#g`!~LTFBpljwVHbdKM(9I0xwp&*CXy5W zy~j8d+ih^# zpxp%Jk$BOY61{GKaNaM?9dCAf&|IREUllX>`s1kjFU_C+bHC_bxm>FwnK%CZzxRt| zQ(|@bStX`T)n!xv>1_O|OYiDp#YX}H|8_R^bxpa7@z#q@A2;J4&?;j6xnH#2<6PVN zsHtG8p`q;Y>dL*_)$x29U66i@-SwaQMXRfZ*9+wwL$9W1WqX8x`$e`LU-RvcL<&JE za_yDB2juH&h=IX6Tz&^R(E)hjc<1fh>Cqp;QLZ?RxW&rcLPh<*ZfyXl0h9&@cpSvX zCm|srpkyVWVk2P`qT*J3`cjEr#DG=KhDFZyAC}>K)VF?T|J93bBP5IM$xBD$+zuo zWSXN_n7vQ3Q$U7YM43xqrh90P3!=y^v(!DiLL*{KGjdEXVfBBp_f|n|Fz~)D1P#TC z7k7u!mg4T-;I75pt+>0pyIWh_-QC?Cio4~c-?#U@`<&TxX3osLZzq$d@WA9HGs*h@ z)-udLH!KH3U<+hBV^ssT`^WnS5@obtBf-yL<0t!a%tzO`2n*b>_D?`o#2 ztgg4Bez3Z+zoL1#x?>u$TWxIV{jX)A@*W6pnP~1BhftT_0~^gflZC@~`D1SoyIK9n zUgN~+U)b_bQ>c0N>R-~**)s@P&_L8?Lla97wb|J8Dr7+ena^~sfv5gT&2|>n4;R;V zRyX%oc8=E%Pp0?53rFC^BQV5nw!MG4cX)Pma<+GTb^KRt_7}NaUfuqST%KS4Z%XKY zKdkw0{tDUJF#N~X2K;uU_V3ol>EEqQ0Kyk@8PlKNdqRnY`Fcx!?g~VaE0!ULUXlp; zF++5~p|<;@iP(bMr>6ga8i)|h-N8g8Q!E-oJM8n3L@`z>bD&gWp;Dgm@BP-{|IOCs zo}tJ)74@gS1Fa&pjL-Qz(f_iw`2a&68v~m&2-(`K{}rN5nh z=ua&QDGOn#s9_)r&)#U_CeS^6L$G2Mhesq%dQhW6!!g(jW30#14`c49-3enu3CI*yG24xmpaxQgNc}AfeTzceOHfi-$`2g_!tO+9Ijc`6=>*a3 z3-GMd<{Jb4nC?N!Lh4kIp)1`1mBP5$L7Ex{dkiJGgkwMZ%heH0PQbXSad`S|$$n-8 zo0JiP1qXd;oRge6U91~wgGqLvvw3b#R#5YHE_GxPEik#L%skq*>e#%nstlY~Y6~OV z-A%z0R#q;U4C)plZ#tv56y$Nf6s^Irr=Fy;p?rVxI}#Ndu{Ie1kNDn4-r}gDOW7Vs zovKB?N!4@wWYxHn#9h(2l_=w)yF+`Lr5h=Dq^1k&fZ(EERPM#Ljj-Acx1S`K@u0I~t#1IaII?qqA7;4d z^9Wia@)z4L4KMbiKlik*M_`}oevP|6QnQY+eF?srHhC0v7`Y$YceJJuSzDPcQLc2f zR1q{yFec&b!Gxjii_8EPb;ID2+o^2Al;rX+6JLiiZz|xSR-We1lW629j#Q)fM5~I zL52wrO5fQa;2qfXTif+3nXlyCjCl8NOCynw?R~ui{8%jm&&C}U>`CAr>;XxSPMEj>KgjCFPAo&e8aLu0HEc-lkjk-q z8D&eDs`Ege)A?{2?SouEiXb^C^!7eFM26BAO7Y_p-W8-Qv`dODIV5#Q!xD(+N69`k zB%yH?pX2dO?}^k;F6}BI8o7{O^)W*}2_vzFl?qZ8l0JY6O87atM{NNq3l$+JHzOC3 zc}k8N;9sW<$`pN09+D}->H>~M6tQl>q?jOGr!C%WvNjCKrYO$G+O&5TgpDIw<|nJR}0pr4N~W6ZDW|$4ce4W+*=9&`Zc% zP7z26D1n}+(5X0Nf%Nl2emscMM%(pehe$LO+{tp|5JAk>Lto9E|=)`i8VADu=(Pq#kpXQ7-3 z*OSez`T(*Els#oZt4% zq_xz;8lr8T4N1#2O~m1qszjEF&1sc(Oj*_O+LkrQ++`okoQ0fGEVMroEKa`-|1y?h zMlpJ>*;pPk@#Qi1{^TsN;moFEO>ripR=Jhijh!*B#PRH-sh($7D3^1HD|db_Zey zw}$jRxni{GKB4ODYC_CERaT(U%G=T(Z46Wo&5HwacfZnKPfh=OP-7$gt|I2XeFX>e zM|Q!+0dYzvg5!nVef}0q=tD2=I+CAF>k2m7V~=$EpM>a_y@f2dZ`SLl(F-pJGsNyA z(OK8w2)jpX%y4WKS!aN_r<0AdWZ~8=6wj%L(|c`$nS!9c7S(5bd0{{ig7+ppKi^V= zE9YMJ8rQGBq|{iWEqOIhZCZ zNG)pC2M>`+E7>=0n}mf;ac;-y6yvXYD>mm7VTxbeHtxS=A(|Ny3P@Q9@iWNYeA6D0 zItHD35?7l>n6uFzJn4@vCL=iL&qwQ=N*ch!;l)@Rz@`t73lRr#U@9DXrq0_L?uux* z+V;-|N=X2*V+gPXfNG{fsiZ-Mra>=-K_&8##E_ZSC)n=~P}nT6iYY=4YQZik!FIL5 z#Z$p{w804iuw>`}kuboS+vJqb8D45}HJ->J=OM zi{1IPFytGo(Dr?34y=&4i&s^n>9;-6GhEpl7v~3dIF^*~q-pPFQ<^ImAfSZuD2d^5 zA-tc1rqwmV8sKxC4EyY7eUGd5<2GVgEmAoSh->ISkLPdh#2mQkUnFM1GS9!F7A3i@ zeqbCWx9xi<5h)vIu}!YoR7ZHM7A>qm+}NkFY#KevCh)+anO@>BJ_ikq)$$4vf>DoA zu#K@zh#~nE-hyvl|k73r2NjCFI zww%e3p^dX!vTJHG#D?avl==iyoO?>1kxj62L@1$}G zG)yp?HA(1Ae5TBix$^9A^6=c3**Pa~d~Nq4a)%QnRs$d!d?po<^Cm$`iKwav{Nf zzW)0ngJwNL_aX^+X|A#&UL+i|<03YsVk`P$9h_okt|CYCJmR!st)OBr4I>{UoIt%I zUr1R9i6AJgL=jwH65(zX^;DvaQyRDYEkdv~(OgE69y-efP2T~T2q5w9Rs#96! zrp(mi5z{poTi3#z1uAB?=P3RPo!TL3F& zAZXW=qN(6F(vt(J^Db+1IztP0e{)d_)^$=# zeT!^3w@nfQcI!$@8Ef+~eoOC&R=8%9>ZjJBXUW?1y2|nv-dOpG5t;U|)>#Y8xXspu zA3~hqmAdJZHtDIh?dP^o*p{vltfG~+&tdH@SZ%=cYTd2&i*lI`>2_iL_76WgXcL<8 zS1^~Qv2+gGp8=h3(jt#5tq2G0zKNavj;$w}&7PVjqzu1b2`Z<#ekv1qQ)71m-?esg zV*>7(5E;Lpg>_ju34LAZnt#Bd@xaDFZchBst}{>Z>7*NxqngX|SFe7}JD%=4ZYzF( z3EE0^KN2Q>YZtFa#P+8i)vgW*vuCq35=X9*lKBn2(o5|?DmdB>e_HGJsb8#>kxaAi z_jI?`DLoouHziNk%5!@kj0qn%lSQkS@Q(p(ZoE&Y*p1R%FpV`7U#xfgyA`De-A}!@ zz|eiC($;4W6rM7AjChE?Apftaz*WVevnCnkiVgsemCIHwx`c_KE4~QcP+kHqwcfBK zqEW|6E0$D0hHzwwrLNb{;S#&RZ;b&>xg)ACO$u_t3n?lIwhkE^S(U?(>0G1#L=I2sV%Is40d&L*aa|lk1cW#@j&~pr z@YyvYQjH5LjKs+Rg>6HGW5(!uL!Jo%uY@t*_D5lhYkIXt;qk+=4uvvJ6U~fzo>qPW ztuSG>Yu%E7A*9R?GP3bLi0EU65j+zK7fij#)_5pgL%VHQR^uX;6Va{R^h^*?$%|D% zfW?IJ1v?T%wOssVOa{x!vP!g{7Ud_ur|2QqG;nH~muXf=VMbh5xRqdbcz#xnXi#2O zQf6cp-E~5}Ql?3Ij*Dn)m^wn2SK42C?4zu;vFChF?QbfketPWT&*t4NaC6p7!tS6_ zj>!eD*9D(Q7)?EnFUpHSkqd5_Y`$%aUSlx!G4?@3OJtdgdcBJgV=#75OL3ly37KL^ zZHwG7@G?_~>0?Woo?_WVi=4LbGO-8++RKA(%f<=IzHM-BwkwU9E6snFYk0$cX)o3O zS>V+}koH}Pm|TH84u#MEd$S1Iha<;kmXXUe;2)*2vFVW^lxlR1>ab8p|C@AP_ z6lkc)UAebiC=e6_%P#EOGL6^nW7n=!77Q&Ew9eTcOw6v%IP|9)EL8ynuB?>;&pkC} z5Jr7X{;jx~_2n zBk~E+4TK;Fg7fxT@p)&3so*s6U=0TP1-=N&WWj{+Z6K0DvB$tfp22`>ummrTtNGx~ zvfxvBaR?B7Kk?-;LabZ!R-f!J_`6OX#Y6zMP(XoW&8$PHP3Q$7d|3XZM{!vQj+3ws0-N@oFoyEO*rc$DgCRmJK_aHRzLIA+0A>Xr4oU&R!MHA* zKUz4^mwZYvoH@`?pz{#aJ;-1Ovj$7K=891lPIq(DeiOz5`~}$fGX5oTyvQR9t{IwS z@|q8PEpUGAtp}u;WHYn{en!8M+PD_hy=k($`8+8MZwtk)2L&ODw(WbmXL}z=p#=o6 zm?o|gMJ@FG0PQ94pbrEmZmMN^wfEp_XQ7oKUHi1QU zwQV*5Qal_1{pA$SDd9H{ymM8S>!)J7%UgS4wi=jgJ}Ax@z&p_6HPf!}dsv5@$G0qm z%<2_W9~fETYn#ULvll4poNMUeCoF@r^C(>8cc*{A)4Sq&-=BnUA18Tkk3JCZoU=TGsk5Y1#` zopj|G0LsKODv$X+n5hF*O zv$o?H)^uf&w%Uqd{3As39cJN!6<-mmi{#T9M_BZcG&()~l+1;1PV%~ROZ$MxXr<0i>7>7kb)2AUq%AX<(bvFt! zbsDqZnmwRCDtrzfbyQN2{`xgvwu7}4;nUZ+1PO+3iB2jSD6)w&MD8iTS+eWHauq#) zY?TqscdVttg6AW`9s21`cS~3{xA6$fdXBfsLb-F!n%2+>cO&BQZPC-#BVX^eP6-uV zw4JElg)zGBIN@qT&;7dBk-C~=r^}qMn zbykPR82C8Wpf5#ioNN#yjMG#aE?q_W-TT_Ai_bmGFkp#|-d(wvUZU-?v zNTK^d_^6FWSrGfup|`1A>V~(v7oJ&3zE?d4s3?KDtR#^)$=#yL?CYaJc`Bs$P&LA) zDU>mzqIpu*EB9gh_fFCewFJfb$9<=R`5)&u^LNkZwe9r{XOhhJ%SP>(sveSMg;y@Q zEodE-r2jxR;J<4qF-Udj=RegU2xNnQhmMR*f{aayLGlrklm(ZbAMfu|fSC0g6~8W} zfF8Z%-{I3|Wp5q@$G?*&HFrr>TM2DXkiM6OzP-Mw8=G!4hi){dUNoP1HorxVtey{q zut|Bx{_CrQWQHJ+O~|oY#HmKyt3%SO0|MM^+`_&)L9BIgkkXK~SE_?skc&sCn`fA` zPlu;pq+>vqcR=iaE}-&cLnc6B6DkQCnpx+%x#wC%V4V`MZo`va?m5I=2WbpJ;G1{z zn{QBTU|5n*RDoYiQE*~KXi|AZY9(ajl$2fs5!68vLXf7&Uo~BRZCc@9&X!kLl3Vl> zQVuGr>BwyE`PWF7*VYdiGF3GWR5lJmq;$U^Y^`H7WEz|?^j63d!L7eyS?r7Qih92?ZrRy_T~nG&aC z?bB4V<6O`lELbw|*cbwjHzl62AY15j(m?Tui6b=n0 z;EXici$-lvP`_ⅆL-3b~#TPEVnUhf4;xHAgLE8>3Dm3JpWVO(7MKZ@>6xK2wMUQ zJd=a;5(?oAZI3W77xGm=(`JVW*BV z)oV#zC@++@3~|TvGvos@>}V}yIfQF|F+W-a6^=5J2j^&7Ma9=~HwrCCNl(&jtB63o zPjr!#SUX|b(M2}l!R&2mVJAgzv0F9zcFdSR zaHOm54c1@GClF8g=5LVt!rzArO5 zY#O8%sxnls;x-Jtsh+pE3^JS}e_=1)S9>&|Fve#I8xecfZ&x978x><4_HF60m{-pfSvW!{MX|6-RVOzK59E)@MG! z$j&xs#aB7-iurh7XuCZqJl0eha}ikwM+I6wq`z#7CpXMZxVI6IrtO1hiLMHLesN`? zgV%QBHRSW&6K%rm(&Dv6a*~Hq1cYK_p!dbTe1}(NoJO3C5sk|cgzIqID02M%SuXIW z^UvSfBu}JYNX}}4tqY_nKVxNe3R23sU}-tU3u49*U>t=|nei!o*BP62EA$$37paq?m`;73%?=j~dy% z%JDtp35B$lxd>3cbC0|YNTSUw74UH>^5Y!*sGa;TquTJ|;{Ao8Z(NEpW34nAIYZ#; z&aNSoB0@Qa%i7+{P4o1pBWg}Md1;At``q16G=q~v(vp5tPFD^GAE#WIH|P|zafWFm z_6&x-$E9?A9c3BP)dXV-9OaRyOoRy@K_NwAc}wMo%G9A;`oF3ph}ObK{H~{B#Uu*E zDq;CwL&eRQgMInbOQqr5>QdYtib5+&Wxx3=iVcBiPCQJK*xbYxQNBjLe?mZyH_!0y zjIET8ECMJV#rnNaga%ws2CE%2mTxOmdcO{+D8ek#4ueX~-8T}(@g(QfuPRb1Vl@Lm7}HRMKHRFOPq*nw`lw;M&Ex~L&<)WpCtH4Xm?441QFWlzTgx>gmx@Hu&Flz?;h$@SZn<5 zN0PT0AG+=enY2k|w(hg&s)#f;1t6})+vA2F(kLc5Awq-vn8qGhKD)p~0t{>iS4Dfb z@NkBT-yirNx>LWJ=~=#PqFt+X@x9sk29q0-ek&h@r~VuV$JkOEXfY%shMEBV!n_Yi zYC<;qXj#0vLF(|>uJdN^naF6&Leey9EO%f%iER8Ne+6c=thb5WvDE(rZ8xf3bnVqs zVRC!bG@&*R%vnp{7W|<`8)R&w&er@(q}pXX>a22nlW>zsT%(z@$uS46(oANfU?xik zt7ORIsIR}@C?}{k|Br_WlcsvR>ikVM0TQ&TerxTA4cb=;mqM%FhK1F&ZUI_{Ek;rHDH z?R(_VKPJ|QX*+*tUq~f$&&-Tp_GrFcH5$7NKdxDdZ>-K|pF7MH5*$x`f4eDZsN4TO z;@&|Lc4_0{c}m8AAIa@7^upfaf9UwA z`!-|ay-bIeD0Kl@J+OLhvHLWOnWo=+CLCB1A~@{#`aio=Fg^Mm8CLw2!$mtwD$>_f2VgKFxFM&lb#<}YvPPZ8ixLhEem z;;rA{z>VmP+UT(13$H*5r)9`R|KLfz7*M;f%iQQPVB%HaV#-$H&syU9knFEnBB)Aj z%0%t)NE3i>>YkgVlY|aWmZL(34v*69tA7w+uV##Z=s|yIg^uU&jXi)DFSuI8Ni8L? z|G-0=mQPgzL-hbdSjNH`dfq!v!O?+GaJITsCec6CB9@wmYa$>j*yrHm-1 zh$v|AZcGW|8t{_m&~r~F#t{Czq#r)d;e^0pld#~Gp5np65iuba#*P>kD(=#Y=*#_p zq0#R*PeYzG2`4%ON537ipcX9=c)K$nKqD}}7}XqX@deOZhMJ&b6? z3kFK?ee#QCJu+wt`N07$^+A;I%9e=ZbBm%-4}(#UyOeh~9Q0>0iy~Y^(D0$hQI7|i z8NREJXfJkIIgBKxi=!w_OzKJ0`fZmR8?gw1QiG9?hmNKn63vIK67PK&OoQYf{sxSG zvL{U3df_cbeRNIYbV)#3ie_(0@>AFMZSr|6iJe%8G?GkqQjefc<>d;A8&2`I2@a8P zOY%aD{AT7Bxd|mjsS3esxl5_pbZJFyX~K>$l2B>Oi%En>NtHCo>&0-iohj^7&_*>N zeJFr4XHxt?#BD>^@IWwaX{s(>P@uXqKrpRjDPvq6ee^K{k{l`vO&cr@{vG0#aTv;! zgi&jj{%H!@1e}xJdX)0@AT~lRW`R8wSv@B8G1<(`edH*0Mm;<4L*`v-cCLCRc2|6} zsn615B$8yR{bT0lBgXcT$KH`FzDwc|jlF6eQ?oJ%@P zJ!cj~w-_D#=-XWyUZ$2oBABk^l!NS>zH27^-ZZAOG_heIi@!0>eJMQ2HTMI4o=_S( zF;{^Y65fj$9{5A{>-5}JMviv|WzO0H!oz4IYuaUqUnC@k1G@kBkBuPkHa zLxH$?foNKhr4*1tia|Lw1qILJ=sxE?S2D6-p)wbS>anc)ams^>cjsW-(O`bXLww(3 zVT(kO0vMryWVnc+xhTfHK=SzgcQIQQ#9(H%#GvJPMUC_yQW&4Z3g1b^oSLPEnnnrM z2M+4Zu!e0RB&w?m& zT@@~%dvt8;9a6Pl7T?lXv3hKM+gvGaUP*;yCnRncI|<7|ih#NaU_l3lLBZf1=!l^M zjV}P0od}?qnwvQzn3bfvpz1pfEfxWo1at)47(jv^9B?I#?75mby&91Q2AvxKNv$M+ z1rX3zDoI-^kJGF*9)2>l{N9F#aTEZ4)`K?ML}Vd_0TBFp)uk!*M85aWGF2DZnQB`ugzZ5}ee?H1+&1xJ5xCEjo*_aS9F2 zD_E^9pTyJytM(%=Lt8S;jkm-RuS|hZ1AbN(d7O_S3{R1%<&^C$Ee#`q&Ce}R;3gU$ zHwtaMxVrMJ=pVt9NRiy;VMbx@qhI1piZfxGquWE;oSMTtlgn10+tx=qtQOpSp54Qq z?OnLsyi!AN4g=6W#9{&=5gq+r1n(W`99^@vON7q0@-8&Y)~_L51Fl}BT;0iTVJD_P ztVe#J0HP_cTjddwxjF0O-}M;arAH2QVXJi#oOT6Zw{M5{J)+RMyTzql^QA0`!%e2FTK5r%O?Rn)a!Go9QZV?hTG70 zVXz+_-}&7TW?HX(N|40^n$<&4f`@zT!jKY849<&d4o}-V!dxn~0P&OnN#$XoyP>Mq zwv73{0>Y7=mC#cHFES3lO60(LEwj3pk+&aN`C4J!6`g~YetKI7AYq*W4}+SQ(I1TI z>U3kj7&A`FM-qLMwgT1WU&b~G$Bi1sZ01I`J;o0+#`yVy-Yw6O#*l)A70Nu;(($ovWQbrPLu3WIkFOM42(a|$nW z3cqcNaBYhCb&8Z|nw)or=4X^I?{XgsSrFbqm>!>~emzb3YS)Zq|jW?9d`>&hS3Y+VM zo1hOAo<8uVonl8_o3M+dXvAArOeQ#QXn0;5SaR_UO1z-UEo@Xll%cYZz`gyzWBtJE?ZAil(2wt*HI&z32srC7to=~LYx~3aVa)iC;7*?QtHW5YqofA- z1QwtaDKu&gAkq^-)90wb+AUBID7|?^{R;qLNKzMi0O$n*mE%N}g(?dl*T~igVqnY# zE$YQa4e^OwB@co03B2jaC*q=}_QIC+lYYP{Qaw6T4O|f!QNLV^b|*k+RKs)1#jx-hb}D z$u^+G^JH&F#aw&+x~AB; z2F#PP3*4aF!X!oAm>1s2oZpCd=qT8b%Ytt}-g?dUFc_rJ>^_W|)u!6uTm6p9+d{mk z&0D>522%bzI2GQg$qQSXTa?fDH0!!FQTH0U_n79um>8m8EoX^2h%pzW?CYe#;5)C4 zhbZtv49R00|6_vgBV@mnlKq(0@tCpkm<4{!A$iJ!te$kAioBmnvY*O2o+>t;s=!Y* zB+tM2pKEoW<#k|G^`1+ku^Z8FjRxS|(O;}O;lZQuR_HIi6Vn!YFFhUb!l*cHHp>bF z@WJR52_VFwjtNUW#CdS^EA1G3AUZ`X2yq;3_q#rf>gKb8Dxy$6qCF`B4eQ(U=o{nB z+a(DiwJi7y4V;7yeE3IbM+sR&3I44P87@w4{io25yj$u6!(3zD)Q)&Gu4t5_+7JdY zHY#CB=l4IN`L=ErNu$J z+3Al0Swp$zh)KIVH6|RV6ckEgTuG($E?gb-q_VrfYcI13jizKFp?&#Am4WXthQ)AQ@`OfO0Bhqe>6F>#YiGxuaPk)et#YJo+2rxYJF}0_H@O? zo#xxzF6HSm_YBiU`vZucNXa=TZ}oL2H-;3&$h)IiQu=0Rf*;_GPv7}^%3#~o&k~PT zf!g>TL@NCRvJ~2v(FlmSWVr!RqTn7~2xFWGF;>5mRW{R7$T z25^FfzKbD<2=s^nlym&VCsR_OhY0BOyMa=93HDO-HD`A@%PfltbZXJrt&OE8h$H( zQj{VQYm8eK!hDmDcjG6RcS&P0plDJn<0PfO-YO}TB0J40Y06?rO1*uMQhH-uyHP>@ zo@t1Lqn6^wrRtCEyvPb(s$0+nlR2wvYI+>0>6V_LshYdhQX(P2=8+-^lxrU^TY{JB zHEoh%R5h)G8Czc5WCf*FG)c$QM=Y6`cTB^1=D}_06BCCmY?1q}n;` zEhax-kw-*yvOQbY&Zzvbs$X$_wrc#CCn95fQlGxaaX$ZJj5;%5db|iO}0q;cdbzT0M=QA^Q@T z<{MH$$KL7|D!G~;;JlL$ZrukCm333$DkhkKbj#1JWD^{Kz9@(u1PZYIpbwOF70UKN z4`eXZe}|nXgxe1a`cj~eV&y7KxDN{E-qlC*d=Msumk$x9G>$dk|#_l8^XK`TfI~s~BsMe58fpcY?JCF^+!uD2IaY zM1NexdG_U_f9!rId3_KUATNN|eP>8Eq!#)Cq|Y2=NQv|H^WZS6LY$IE0XhF?Ng2K= ziqKX=YThMb5yoB$3epuNJ~t@}b4p|)(g3luU@5gb77B;MP86-jVYPjX;IANPPir?S zZTRaTT~i}5Bw886`Nu6#_Vm6vbI5r89S6F zoMUcsjzx-@Cx#~6YmaiS{fb%FTHh-U-M)G3|IT{aHAy;M`sM?#l%w!+z_td3AOHnG zwFVK8qF;hUpbT>2J%q`5;zHPSWYME91}R`a$&0o7=G!-RWAB1O#aXZ{ePTqYB+RF! zB!u$T8BMb|QnW7iArq6|-_Ng5XL^Wf`C;6GJ*FjU9jr{~tdzBO z9P*MW6}s)BJ$VdLFYX75+kOfFcnm3N!0I`oDp%&ItA;4=n)*QfCW6^Admp4fj9j#S z7C9^5V=DhWqTgN=B?x2ux!Pe=kywIanoygJU8vv2x*(PAmvQLehY3ewnlw!ET?wtE ziTzavk3AmKvv`ztscU%6qXBJ*=F0QU3#@P_M={a z3H@4@HW-Kyy-ft>oc!5PoHoL>flER|h0MrPCrPj>mtA8)$ZHpVAIy6< zf2%HzN*|6{w`;`yeBs#Ml$YNoV|j4U>zR2Kckr@(%E`6X1axlvxUyg#T)&asWL%Rz zC*#Tf!Up}(DgL_h@{B{($(77X*g+V?i=V3Y&e~yutgy1N?&@9(-4R4t=R>^O8!@5j~8{ zcj5wm*^$%14c($8(Ik^{j zDbM$QUEA=yf#H87=y;2#cvfuR!t8|J?EpmN!+3O@hx0G2bmUlcvb%R)$9G<6^1qXz zKn@T%NEbjo75MVhiL4~>K7${FhXNB;5UZebMqQBAybE)bACHyjgJBmAtiXdJKlW%B z3zq-}tuOdDAIfaUdsrc602Hik2PPCG1ItewAwWVYK=qP`;Oc|I!cT;#;WaR*v%uIgaV_obP%!lKutpLt@r}ap;(XwP+A4YC3~2W0Ho+Xv`TzLK0Smi z{De?Guo9gVlrVfeC{SByQyR^wiO<%+2Jj37 z8ggp0<|tH1fMt=}3DHF(vHIXaA||t9Uj_%7mMcaWIHeK&>+F5d7fbz4JJ4zZL=lk@ zL&VTZB-2|ZGdzY;M#EDJU^6O)P~Cl?p?nM&#W<1u@SuDE=we04J}?*U=%>(OgMN}B zex0^{lAC_nyMB_k0AHwZ+LQpsL9uWj$<)!0%njTFVhsBmk`50E|aB zW=)5lOy^5JB6rDfc?K-E=}5=Tus4)+7p3%ytwaq-LOLYNZnV$ea`Z!pMB$1kS;+{3 z%&@E@Kdh^iQiXU7mSjD-WCr)&X7Yf-Xxw7I^-I5P#As*&>jKZfVnW=K2Qg%5(p)S3 z+#?Nc6M>3e<^3Uo}f_?9$T9og^`g8 zuaKCW`ST@@bc)J93DUJMSCC=f7y~-zZu_v^+6U81B>(*?v6w= z%1J4W*D`<(2`SEy0qX$+;Oll+C+ZhV5CT*8T==A6+T>aVh_06xS(F;35QHi!F#inF zMv{jol7~eGV4@VEuYs_Y+i`fOa0BJBGv)CiKXD|=6N(n%@5#R3n68xABr!PimZDIIGHoNWixDR)1T%PdA7L(Guf~3*abW(mSkoh84)F7 zdW9>g#XV=a6_iBh(4^)Up+^i!3da z*`$<}oe(8bxFKsBb)o_3y4irkdd)hrwp5@D6C&t!j&)dBdrkSnOtb>k*YAIFTc*ZC zLGzs4A%*|pv4)58{_C;+_i`%;a*xHQ@2@>HGdQ8yE+umDop@ZmkTRVj+fUE3Xt=?^GL~G=rFId%p~WnEz;ldPU^BMX43E`>;-8wRVJ{ym=>fHXZJ=Tq4m;PURVmhSQ9o~e$(g^HfNsxffR##_w<_}3&j zcN5(5=dAVct!H?)Z)|aJd|_x}v2Si=WO}u4cM1`qw;g4Us+n|7IRQ0Q>0p`3D3B=miD)>xBeH zMCxe8#V5pvM@Rcb1f^tVW#{DPW%?x+X(i{El~+{e`WGjrRn^wjNB&GGZD?(4Z>?#H z``yu(t6$#L-J3a>qCc)TJ{d7NGdnTAyfC-2zA;$XT>^Qt2Zu+;8;v_@Cl{Aj^P#so zF)?XR$b90MiOJGNmXadR8$+{q8_??bmRLpWBt8IN{nmcf%XM?brFjy6gYM zevP^Agp&#Q47pr7zOsvh|GnSLzy1cCUHV2!mz{!R77J};TqFwn1!q-AsdPr;vms9= z{%}8Xnc8o@v?<|oRWaVGwAuO5f+b@b-q^yXB%+nHFJR-v3~3jlsAkuxt<`<`A{p`E zi%Miyr4eY_th@I`iL)n3J-QS>Xy2!nMIt4B5x1OFb|^Q?$@4wF6rj|w%vWk3n`f)8 zN2AgjsbcW&N?K~XH{W?wosvu9IsYK$k&v>zEx_yVE~E9Rh(?~FS>UVQe5;XBy|C<> zM2$C{$6tv3?HA?A%y+w<{;~DKBv=HI+H4Xr6PtXA>o3>5ty8o+d|&qo9hQw?wSC{o z2XFf28YZi|A_a;syX___j|WcI&f)}BRf=x}ANtsKhRFDEBwN$KEzI!JkLPVLayUZk zd%aB!Zc=;_a{c~Mp9MNFin|%m_ue1}XV*zTWC{k1BTCFUEn%QFB^)mhl^hwk-&U6t zgx|iK8>*+#(;Gsef=(?%D>Oq+gIU)Uf@k1y36~KHm$Diw+0SVbFSi_5oM8)CDs~kG z3?JlVy*3r+NCXwBe6_{bFp^kP>cN*h>T;ly(akb5fHRDe@Gqtljg9y8(cj%>e(2>C zhW{|ia$xYdNwF!P)`V1EVL&PsUiEYQ_=L9eYWT25j_R?myo)%DF?ZyQi{|sHzFU%; zb!k$PWo8@~32JUsi4V^Dd@VKq-I^+51|1>fa1NnBfJXnBYM{*FwE10iYa1VfRQq{9 zcXdY!RO@*stfEm(=PRoFY4?kth`w8j)Tj!$XvNt~v0-mJse6E!^5SxUXv2{{{h<;u z!zQe+)TXoh33oP=U;W^!g@rxCmWF-DLtvEqKI3{^4T$n_@=fgf&BVBYsaYVcnM~=d zPQS`kump>(6OY-v%h>|sn^*{*=4Qk-4%dczxxHcfEAz6*kLmgq+X3E&C8vQuvuh?N zGOQam*G+qgYnftpticUz$#~){^1JhYj8GoAbTYy+Z0hp}>vkb10LnBfW z(%qsoNOvpUAq@i3-QC?K-QC^Y-6GQ6J!kaWXRW=@)!yr@%_WNqFVOk>{@(X_>gjJ@ z9@o&r#-Dyo(yxg1six*6%2$egdcEAoMiasS5_g?;numu%W%BRfIQKzEl1hTsVx`zl5-b_C4iRvHE9z z;{14?B(zBt1a2gFzk>_)u~#R-Z2Tnvu3=E7*PN%Kx)0!;K9YkgP8#1f62-wO(`DiP zg`4+Aj2ZuDm=97c${>)IMG4VazLhkIsetnF+B}$3x(g zCm{PI>eIzO<<;am3+Acy)=Rb(T;`u=1fdAt|DgzZSBboeB z*#+AsEvm+K<7az3G{e2A9BJ2nKg@V?`=h*8LeiV4?mJ!10wuBUWJSL zg(w=RnEb>(ps6X_K{P(B&D$R~A@m!RXTQCo9D=Z!%KnK_pm01%^tQ{kL{#C$oj*pcfX=!sgUtJ+P|jgM1#Auz0uOTSp! z<5wN6ePoHF5tS}PR+G$Es?9dKTy5P@n{oou5+qRXie;}6{MK*AYQafd^Q}In9MSR} z&vKmdEpe^(vB?kmrS(h4s~t&Q9!AJK1#EdE-ZBMr?ipf~E>TgwL@$jave ztaUs}*9UHMTb*B+oNq$2FJhCh#Xg*ANgv|Gm#9`udQ=*Ho2_r+7wY(h&Fncpvi_2& z-1$0h=>q$_xP^INhRr7X89iL@BWrS5{Wk-MZtas^Bk;cah4MV$oy;22_xmot-x9F& zybJgI$sITSr}pEi+DL}?z4(E)-rtTl(K_#&D8$~NKP^WPI?2B0N@NQ2Xw$(za78`HKg@ zpKyS`azJ0-0e)H;<`}q$tz1P!uD$QD?5HbI9XH=7Sb3W%TOWkLYpytnKbO(K;=pQa zuGILr*oD?$qgi$!@5VhSHozQf0bxMWzSCHmifpKxY&GMBG_DLR$Te70TUnE*EmpHT zG;#2q*g-+gck>SQpE6E0ES^>y(CQgm%B>x|w%6__8moreRn$jUxz`;VqMv~;uqjeoOZM1U8hMGxpxO>p%QiXmL zvHSYTYoon{j$N3l)^4luT{qYGWoGH~Z+FH9@70Kta1O1t1L!Z)NyJ=0n^vqmhvA&Q zhg~wk($+KkO&^ixVa3z)5wz6lRe54i+SxKH8pSoArV~?KJ9Tp6=T?j8d67!pKDX6S zg$~wxU-gvn>-olMLAOF3@-dF@K(W(t{!GrYL0II})z5v+@zhG0g>Nlv@}Zq|V}a$^ zgV77UJ?P2G`B)?EDByeTiu8+ViHYY)q!;gOJB>^3{Kkz&=hN|GgzJLS`pvU(-=1LQ zeRtUFJtMQ-m~!~T7RT%Sq`b@Vx6X-G>av!>c8+OvdFyyXzN56o@$;t&=bbd&c3<)K z#p#Kc-K6!qtzD19H=R!hsvF4*)M_V35YPF6ti_@MCOY5!&kh}(^t*Yz*I$h3I;J6dISdD26$WJg|vTi6cab~;jn!X z_rfa*a{J@AxEJz>>tB`VG072x#p%|W6k-UXCL{rzkpTz+)Uljlc>&%g;;szIw(JtV zUmCr#heGs%y*lq1JUGAm1=}?{IZxbrd6B?tZ-sJ_1I(QL>(nB8K_T`<;Yv#uP7=O8 zYT;erNDnedq}&IeH>9DdjqYD)e799p%HcTvm_%GIY1`mMi8eZ~?K>oc!&RxnHTUh~ zlYS(r>Y+J#pCmij0AY+_VPM&!(6}s}Kz^T+Ju3%2yN9C4@1nYmJp8Hs9hZ=vIjpDd zbZsy}NQeLo3{Z`8DEe|NGpARaaTKvc0GFvVUWg(7a8N5pAZjBLLa|H8o+k>Ype6vM z;LTn&8_Coh&kX)CKIn_NZ0x%fk>VKVxEH17l8{E@pB@xNHRJ}fAL&*TyE+taoD%VE z_{UpyN9B~T^t%`vvxKLnnBHIpGBZb8NgL(;xVM3Ds4RX<&WVi0k?2k#7Aa0bCieMi z-?h~tNzW3I;=mN|erNCf7>}lKnBZ_B+Gu~8h#xUWeDAC&#zvYwwvp9=8n^e3&wg)el;#A(`1ny-YE<8`srDT%i@S>q) zoZTdANyjGj42j@GQ;xKirnE1J?md#}nvzLn2dP0xDH-4dFdnseuz;Lt#xzc{9jCrm zK$wzQi2bf3xc6^sZ@GVg^7X+krj%Rx<0+EE}Spg=TJgmEsx|n2m~L zmQI!3ifH^pDPH^?brmR!2{HFFC5OT_8znS5A2%DTC70Sfo3}}!3EZj1vV>zW#EXarF>i0Lg&;%zNFx= zrC`^`LT~({`vwz}e-7(3T?0e1Dmt%=NyaSnlHZ5(4dhfrQlJ)W^aFn_|Se zzjy%CmEw=}$}1!#MX4q8h^Uz>yd{q%RiSD6QzavBOB-BEnIuc&{7TzaN;@7)yYS0; zxXb!9$_8A^hEmH$TFS;&$|fGmrtqPI@$xy1@&(uOrPT73mcJx`jmPpWd`QJMcLfv$ z05zfPr&b)cR2;8VoIX~Z<5ymCS6*vW-nv#oEu4=nmCq|sTYDvdpbE+XfYYpkcdG)Y zRUx%jp{!P+JEEi80Gs|)dBekh*aG<72g~K#V`*CZVN~-@SGx~@aZ8ho8mnokYo^7( zB&BcZ+)OCKsyUawM|s!0d#dTeVJETh<>WD8b*oLnQ*vLf<$9{dJVF<-u%zUv6||_8 zNvlg5s1fI>R&djcs;bjeb&v~lQzme{6JW13K-YdU(6<3eynDZqK%svwwaM9#sKRAa z12PG#v(_{mmtYSpVT*8R)b@_2r^s~})zglK0Vx39Z3X-AeDh*~GzGXdamJ{ITQo&B znS>x)+Qh=ZoHM~h!#HX*!#FmlAOq4?n=L^tsiVzCht1`?;W?$vRwXS611-jH0hK(e zHDPRZX)RTy=7ue;a0{*WptcSRGtE#ol;YN2dfomfra?E=(XiOOv^Mud3RR4J8HwhZ zC!INqc2PUk)zP-awDx#0QAG@p8?b2`StCZN!!1_z$f9F9t%IdCbB?C7zrMjdxIMT& z^U%=cU?uNjmvR!h1z6iG-cmp&3)HR6}ut6DmosTCv?=0hdZcO*HKcwF;gZItTC zu39Eph@sv-3|e*??phnWS?#Tzf`OkS;0Pxt0zjlTC{bn3$9quv@3I@rC>q$tz!S;T zp1-vp2*lhN;J?_wiL-#T+a|`iDsLh|5;8>`6$7YPL zX2jN1K18s6w3;SigpWo6z@5WTob*JM4SXh=D;=5@L7n?FK8SD)B0C45lK_7JLA>F3 za;Wo4>+SaW4Dv+tKQKYu;|A&hAmXiFs_4L2Ol|dg5EaHks%R%{c+Y9sym>~awa21! z#-eNcqWk(kJOI&>FW-{C_EMn7Qg8-jDYShle0>SpQi6hX|EAZxK{*t>$#qiEsz|Av~1n1sl z6$Se*u6$uQc9*`&Ux9-#*-S@i_B@9MryY?QH zYM#Gl3TU3%i)=b}C%N~)a=(P$|DK_Om+A6Ppo3RDhf|p-lf(qwyYJnk?r|tCbD^NJ zRQ&k^5C4W>a|j3&zeye%1e0J8^?O&mmfJ?L9K@f}Ct9yBmLH^h_VJS*{^Y00f4|8W zgqXHrDDVuvPUk4^AeZz7Er!Jub{xsntRGrcunABgiHl8`7WHHv>Bdl-CX3w?xxS4* zHdp&`$jz+y-qH3F2BixEAol(^cB;6#ak445=g)t-!O!@FL@k4X8_Bjm71(bm3LVWC zU%nz->y+PRo*h+CEVEIbzglpd%ow8;=}yh?zkp_4&)Le)A63l|=;F`3BRcOxx_r-gdED|51lctJfbiP;cPk1ddoC@;`hz3Oj@K^>p3eaB}-cxu&bIH~iZaJp;gntwW#8j1(7&8)PI1y;oZX?3lCXkXFk^v!WE%A?PDoFn*FA0eeW+JY_~t$3^L_OHUUg~A6{c*mCl>PfUv;U$>!~U0sYUl& z>sf;eiCXpMQv$(r4{=kU?z1&A>d@x~ z@fYNym#xZ{?a!~h^3h0EuZEhhBbBe(qpyo+ui#d*6K2Rl)a%W6$Z{0qq7nj!4A#^0 z^3vD$4-N?p3y+A5ijIM1wh4(z$tkI6>HlT6KlAbn3X6)NnQdrLn6H0eIW)6vY-(<4 zg=V&$UEMtym7&!E{kDhR z6LNBI-x>hqNoW`+ATXG(^F#JJVY;;$X}|dOKBMiSa4sxL8Xax&-hOoA5945RyBp>H zVlOeVNk+?^$LeJ1;x$jp{oRm0@(9Z2&7(_T6Pr}!ljr5_4G65xdo>K7<<+yl2lfK9 z<4NKf=)vgwX&e2@7D3S|${{nbZxY2N3a!=&CJt=M5qy`~MCz|?spkzt;0^9~Q4F5m z4r2{{6A+3Xkw+4B=#VT3jW;m_;0it{tA7M5dDe62yG5NuB& zfdD)s97ogKFm??Zrq}|Zy*w+2dr>S!_iB@91Iv|z!sOR0b zUZ$g(SxMQND^f`lJmnBjf-_mY66*pf1b2w4^tfh>{ph%MN{s%bZcfGGq<+b`^rT^p zPWrfUB*T1+Qpelkw0Ymt1hM9z;iy8T<#a@{`E0@BOy(lhpp5)@U zBKip{t`_6DV#Np63H0W99;CQ-DtGo3kjE3_?`l~Va4R3_^ zC?ggS#`|BvwS|bAn)m5Y`QD_KQ;w6Sxb>Tz)V8GudfAd>Yaz07_{DoCNsW1GU;lEJRT2b9p1zfqa!|F?lIH6&~m(Q zcm?dBKG;<^-2Gzq2J^m|ZgXmt?2<=D4Bu)5o3ueBd%S|DdSIaWU-vNzy4zT-KhDSd zZZv3%9II}Ve6CP1E&V(I@*o03WZHn!a~>#=n++0e0u5}P2fe8kMf{>7cuksXt7M*2 z3J>n1f~O1+OV|7@MnfscG99AUCbjD*(fb*NHB4`92pERj^Yr2qs$(RFx0p^tWi&|3UCJ$&8^7dBCi20uipUa4_;&DxSZV1O~@fzT&D9e~$ z&Sru8#d+TO$bZlDONL935uz@MJor?H@xV~XHzPS6DOK^tvUiV5lpI-2WZ);wH~|$P zv_5df@B^W2v5ZBvf=|OvO2_h;jMHOyXEPRSo2875i`1M}@LW765v@t+$X64r9I$Le z$=5=u`4Wwr61DLXmBx|z3fG%bJ=9XQ!T%+*ZD_eExA~jdN-egmKr`F%Qk^?!X8U+k z>7DT<7!NzzwA-L+@S3dde1J|9u@F)nj#S2>b^~H}0He&<1r#vQlYP^7tTrNl6Ab1_ z`)qIejVjjiQx`@FCRF8sCeiaPi4ts5eT!TXP;S|OuFgES&{#2w@1N^k2xAWr5!6Nv z<7NQ>1hU0^lo&s98~HBc48yP;GMW}!XfGM7wvN@L;ni$W15mnPldNQec&FCL1WAx% z60AQao(Ejw&?4wf0f4uoo3D>a9k(EW=grY3@XE;&3j_A;T%I?RLU$L&Ei-mYHsBMh zAPP?O_m4#ix}W}#pzx6R1WU32F{AGLD7I|8KNA{YwL141TKM?BE33g>#p|alJx^j< z1ER{SqRh`@I$|G{iQ1?REkp9l8~dbn7&AE9%hbQSWgzPk3;%9tjySO_4*0WZp3+$N z!mz@bs0 z22+tYD|H+2%R4Ov(?0(b({-Y*fMfhX&h2qF8?C-bT=q~Y?QyP1t{xiN9;&oH&R0d& zmzl^~%vjNzHzn!}!H=YBSYR%SKSfu#ogCrXAukp3WL&F!IhG;gSsvM~mrL{LF@z-u z+4{Y#RIF`f#izL_(P#3lDT7lTmFDdxj$>0kqoQ4!f_0pPQ&s=EwG+XI^+7`p+hfLV zYf^&MUj=vM9S=l;7E0U8P-d*|La$qe?o1Zzj0G9-Zip*8q-x0itu zS4v_2-tD;+eh4W46%>eRx_!~MQ#SJakCy_4r9h1Y|G`r9en8F8(I(Du|K08FeA7Gw zV*kUTxQFII-OrKnSw2zuP`yB4d`a+M&dJ}4eL`wMOh(mzI_I?ifjar86ew;jC~bf$ zoS~eP(wfe+=AQhj?(DYyl7F}QilzZ5=cKM}q_JzFrDvjUWTvfex?^Oat9PJlaHe;7 zrf+ZZ9tjz1s)M`UZpqh5N~eg+)ps2t_4E`G=&YL?->a+yBgq zl8(>+`vxpeBBZFOsjbUl!L0xL2Fya?Xz#95$mc*y?8{ad9T^^q8l4`Ro=cjWkzZU{ zT^l8$Scg6VcmC{-@*^A~VD6os?Rc$3TnEO4-vvFy31uX`zWO6#Ih4$F`L*kjYSA3w zK%aoxFQGJJDb!(8yzj{CtuzMAmeSj6;pJBwV`;vW#8=4?p(LCc@ff5EZEz z@+7hmWmOY9cB)jZfFPZsv!Vy%Q0oef8TaWWYKy3khqYNb5vLLs--}Vq=gK{HQ;Q37 z00ay$JebI#)jf0s*tMQiX=;fT0wET4y^*-PiH06aDK3k_YOy611B>R(r(G>F9(Plc zh2i&qu=+8(;nUVD_&sNmyc1_MnE}gOJR@xoAa7YM9E6~%ONvtKtOrG@wYc}z{7xUD zq8W;uIzSa0#$>VQ8Lp(qbeJEU@!1wX0QQEPL_4|*X1Fq%zEOs@H&bHJu8N7ctZah) zDV$A6;L4pXZ&O3bK8ugu(Aas+m!_VJu=jWM(2s!ddQP_CcfT#qW(vR&zJzy_l&vxaQCb+akeRYQ&WB!o#t-O#g!TF=-$S*c-0q zcjriVVc_Zz;gZaP|L6PjAOVzIj39|VGW?5RuOU(Nn7>&6HzCc=xmbnwBH9X2tUuwl zPt8z2LjjqzHp*|TNm4Ra_zR$EoA*1v;F2F@7ZGBFve(x$OhR23kwW2Q@9*}7`7Yl? z)vIk2|7z+N+^EJ0H^Qiy5=<(SW&Da#YD~HnI1)0LO=Rg2b1`@QS_=Bdd5~Eah9O zTH80C#s^tfySHi3TP){Qiiq9rTk~9V^3NVaat=~&Gd02~37$9=+>B>)7Wz#1MY$Bc z8fL$Kaa$AMXi;>r`R;ASsmWZjwDI`A>t6=TRr%sF=n-N7g8t}LLHwy@ z^d*J5yMxNB0y)O?OPG4Qm-efI#bpfq_2l{<|e(TnvWycu#JcauFfAh&(@a+Ot`1Q|ajCVL9(8PKXN zlsz&!i&|NlXlQ60Ke2XuTHQixY#Nk3{d>3n{|cC8&sDg2~d*6`pF_83?0Wax3rRb&o|i+Esb7e2B|b>H+bz3gc+yK!i;+@e5~j*AuC@Q7geheuux z6oxjF3UoT!n_o`9TK2qLTZ==w_H568)w)r>Ipgam=m_;v^M!Ng6kg)jc^{MYOiYIk zqIJ}{jMoM3GJh94kjU1FEBtuiW$HQy5xkML^r%wmbY(SO8L7Yfb)rAnx4zc_9npH6 zXK+4m>MGuP#CGLcM7aZKvhE}-U#}w0`f&$r0$W)-ob+gf@m)6_*LBfuYKNTnD?6UQ zia_p5i92pah0ikXK2@yCLmpQlulJLkuXmG>*Cz-BfaeY5^oI7s;hnv~$=*m!-Y8If z$h|iPo)5Gxj-}><t_zkn51^c;>Y z8vuv~FlQ6cNqAvJL;SdwfYLUwAC{;QSzt$<{5lbQn2QP71 zWpRyXCr2|AX9aQlY(0A`6Ne{NunaD{FNKrNUXTM=N!}(%snAP3$T8&HEm0t-_r@^- z3RVV(a0vpt^n$%j1Wl`hx8hL+6@Zv=K{UyzK1$&F!B9DGUr(oy>Ue${(>K6iU;c9- zb2j_3c!+0jSVyp?0#eSJv4!PZXnPB6L)je?#J zND?g{C_YXB-_IrT!E5VWAbg7cSg~bKSDR$FoESCZ>>(LC4vM3DoAl$IeWE`{4|GAm z1^HOn7&d6i@1w4rQJ5Sf8Fyq7fV?G)Yy*p_Zp=}Y;x(0$m12@QoRT>l?Trh{9Ztzl z(JMm~K|W9Yj+6HJV_J!e)3GTtQA3)tqge+c%gtWYBRCpMEFHrv-8V2DP!)AeO++ma zO)ZcH51%n3nPFs{fx(s0OzZTN1H{pTq03GmJb>Gx&D?oss$iG-`ylpoF_w&-^mN(u zG9=|10mQ@dmJ$afl+B*uNLb09rNEU9H7^5i;k1{N?cOCKxhBp#B&Z{5EQ!I;b{P}} zAR?}08w_XTw}i|pC%#!hT5dqWGS5lrr ztdc=-Y*Ig&r5Gw3zj;!nFt2DO(B_5gId6!eavqBL- z)C|o3(vts643)CvXEHX(WLMZcFau;<0Q4@fSjbQtD6lRmSfVQ6N);~Z|0Zz#ji{jT zb6;WNZlUQ2+`e(4+=|NikX{IqX*aFwo^g?px%$k7nTL>(&7*GIp;4u(Sqc&qK2}8G zT1XkJKFDg6AO!~;(aV1{6H6>{Z73-`EZHis;5dgpg)8u*B;ro|tijG)IZ&EdP}(U~ zxZ+5fwPJpSn>B21=Fu3t-$1}N1w+IFE3Kx5bq-{51QH0CE7$<3y-T;nAW#~Hf2dQCzvxRz{Rck$hhNHkz8p(zO_6AeUqK3MLE8~XG zAA#0K);7`#Kj<5*q!rBF8pl-{r-m8>kO~^>8ogUBJ*ArhG%bVDAWfEO3XY>qyA4gz zn%1#A&A)dW6Q!G7o*Gl0tP)n6Gh3URLYuN%&HbcBO*C5yjx38xTgDt)ns-`86I)Cv zTL<76xfbm$ZzUZIvDQYponLF0RU}Pq69|g3wEb` z6%f8E@j^Ockw;nn90rf2^Q||GtO6XKH_S_YmwYr3!~&G}2I48e4yJh}2>>jL^X|VP z^0EMwOBlBPD7GBgFy?mqn(Dqs=^-8CkPJa#_J-?Y0l$8OAc|(2IxqK#Un=HlstNqD zrTY(&MnFb!F0vH9#P7?Yx*ZN-{ zttoizo^mP#k~8ld25w>j=40PgQK}-i2lj3%*3A30>$qIo2Hn>NJ)i&XX?)iP*Xjt6 z6`0c`2Y0cJg9sTy+AR3e+qCS1(UU48+5kd$!`t76J$#3C7)(>2#Z+a6(F+OWvtc(% zUP;9B1Ltz>S<&MiBRPsO5Z50H7qR}WoDmW5_YJlqK zXZul@GQC;`vF_(FESz!GzA^rtvAJW@rDuedHpqDR!no*8(H4s7wv5P*)`ZK#_{5sY zVVTL^^F$)fq|na9rIsO=&E#WQom95$({oFlrHKFIq{PBxnw#h*?-ZP@dE=VNZQGPu z;5Z`cG)lyTSN0SZ(YI?95wwiyp9@oXC(~q%@tAxwb?`IjRx^?f)BF^!q~$Z0-^Sbe zehAM^vz(Zcc+5%5(ro>wKBQ_CBdU!N~Co;UE&`G+vevDRN_6`K>(4H!iYcx#AnKLLs&SltrnMU6LgdsgV^)K2Z%) zU&TyZ6}nzBU{&vE*UPY460C!>lNI`j>lLTHW@IMTg(~85vKEiJj>NuBIIa;Dybf|) zlk=aJy`#uqSKU;e<(--fe6V zc4#AHuDSBPFUVh}?9jho$A0%-eQpM_oyV<^h`OE3@jhcwVnk;9qnr+j+^-s=b$Ya) zpZR-yf)+@Lc6tZaHSKm#aCU%9OJ#sRFatYeioaC;kB}ptIyFPau7r6bzsH4Gb4iyt zMxkXNXWw!>0Ut8g5VYknF_In2WZi3F>1+~y&p@dv0#*_~BtT#`o^ZE* zbe0qKr=^MkYGDKd<+gxeg_8x(lcm>V3XGH4NXW^?>&ZfeIr|nI&N(yPIUE__^swU; zOahe826`zl<7~mPS5m^nn#V9!)XfWt*;l&@A10dgL+Sg2AK{Pa*iX`(#Jik zBry)34iD0WuQIGhV2!|`qcO!DhhJNeD$tH<(5izvLT|D~!y>Oq<*lMmErEh@38$lh z?|r>bL;Jz}s+)W4-1{P5_FdlJ8hpMr(!DkIx;4$ZHSfH&+`P4h{4aNVoXF3)g?9}B zcS@o|a^tHdTX#dB<~#~)?nL?T{VP?x(M5tQ?_9P2gh8}|Chzn(9#rP<<0C)o?`0>; zE2nPGq-Wi~e|*Sgz_alGobdfY!sJmI`;oAGKKksTVpB7a`RP7mlUD1=OZQO3{^>{i zQ`_e+p6*NOm3L*#$-VMYUv0%pD<5+(!2fdyt^f_e3;%`Sd`b@g6umBz+8$6dFI3A5 zU9LfqfY1c|?{dxZ-*W9o6m+@vHw1T0fSP$-y~5;uRLC0&(L0K-rS%&{6Z0=#X zP$#cp>x)lR!C&9*-w9jEe}Q;xVs=bsEi@4SE88t?imGalz!Yf8y)Oe<*4C~k#j z;_1!(d6ivxRXwHkebD6^l=@xWGFaU@(%d!H+BefVv`{$#X+1rKM&Uif|LJj;#%9*0 z=GSMJ)}VUazE#M`1_T<2|8wL1S^IqmRY@=Hy{sO-Ko@HNFT(q5@96UP8RY1%8~6J3 z^6~QO_CGi7^ULf1X@vd%|L370xU#RGud2VFYDjQUxN@L>R6szKBD`2=WO7JaTv}#o zR!;8UBE*-(g1;enMLr2dWo=!32^)69-y%c-3TH=8uUcAv2q#*I+E~um;ONis(aFL2 z#ih(8Xb(b-ly>7^2)@IQymxfG>$Mbdad{OKl^h+CAeNDy^7FYDXf5O*nceMOjYbDW zmO^_F4c>z3Lv$&u7Ly{fVFlIr^%1j89+p9LP_}Hs zFj-O#f0ZhmehqQ&$ftcvoJgTwgQxMyzNEBO?fQ`~_1j21gE9g^-}a8=Mqem-C(>~r zlEH9a34Fu$P7SLSd8g8E=ZN3fQ8|tI#^R3UM{#DlSsr`r6(?f1r@#0!l8_PxBPr%R z=AF#87&?dzRh)U7_x^OGLOjvhTZ-C-3XvmG)KyuJCyLYfU#blcW_3v2G{?EqkMH&j zdYvTG%B`AgEVc(05xIil5WUX{wD~}w5uca`glz9s^}R4(nAe32zj8RSey=y7;-vOC z218r^geqz>LC8`?^Cmm_V0_m-{ZGUkJ z)mHdMnGm8RfFzk0gKDiN9Vd*Fk`!O3@UWAhrc#)npy>E8ESBkxm@oD-LIla2DYI9H zhjqo&Fv70phltG0KJ}u<&Au_%PELhO?=yU;Iu*7LCRb5TC4f6GTmJ)h=+7vms-iqU zMI zp|4DCAhRs$!;v1Tj-o1M_&RoqPg@Wzirl4dX^=mzVi+s7Te95dqEuSlfnd@6d+u&b z=INni&njvMBv^!@)of&~JtEDVG?|)v_VY$=^{i7Ee(mfl9IW2CU1m${c~7p(YDDot zL~S`lZ726=r5Qi#%DS9u7aULGL&RFyBkrv7h5n9T`EnQ|Z|%IB8JFRz8~>Yr&G^r4 z6vc6xJIkVmfqj%8BdD3K)y3<%PKqu>A<{|%L|Of|^GijmGOd@qmxIKF{?HzTQIgf| zvT32m?PBZKi~1FtK}M%F%cINNHRnA>r*%ia^1Ds%xba2@Cj{%J4Zlitsb4`Ha*Yey z{sT?F<11efnvP^nn>G`|UT!p^2OTUZbd#X+hoZuY$HTJ5%zK84L1+)6=1l16q-nDv zY_<9Bl;@D(mFf8`pyk8!Me~=o_hCaEpWUP;#3#A;Ywd`lu9sjpoo?53J3Q`|ywE)% z*WFRX9gMq%o5oGJL~$M0Q=Oa7Vfnh4A%5-PnrpQM#B zXxgxfOFSm^w$8Sx1=keM@T*rvKrj+rsK!-(?=6YI!c8r(vFCpEoWHK(8*=B16dbYK ze;qQZMZk?H_>;H&I?~AzUihOBM0Nb@z|&cH&N+-v=&LqL+{Y2qltHQ>Oh*fZ7nI!Dl3x*SC}W6wS13l9iyp4hM)u|#o(SE{g)yWvUC$Ez#=YLNhf)RZs&bv9VGNCohW( z`FLF@fLfvuBsG_dk6pxt=lvmSWUhdF-bqcOX+@f=GoGN|Jt3k@CDoPtGysJ`cTjnEXb3Jo;;nGuP!%j| zDOT=)*Ux=hjXv&+4aT4Ys=?PJk246V3aA4x^gyYo<)$!n%Q#=Nfs9o$IAWtK3o}=o zvC39B>02u+D~=gzcreP6`Wc6{up|)ggvqqc0rAp4up#YqY)MMSx)tP z9}HWT#!nAsa@J2>?^?G|E1d_WH!f4}+V=k^>~=(@`=0ba?DqY5B^0|2?Lpi@vD;PN z2r^qhg8Qz2A^6x9JkNbMM&!Q`{1=kueGeWEtz~JpKS~sOgLk=}2G{W~Egcx1FI6Zw z$qL)YZ%CO{IAyev!K+y0f&Gj)e?n@z{6K&%KyklN(2q4_UnhjAJoPlJ|B)HzUu1nzx-B+;!ae!WsNQ;*-`yHF(je#Aui*&Q%yQ$;cG)Z zp<I(fZU`=91?cFe0VC82U_4c5 zqu{e3t&j@8GeBuNga7qijOIC970^kP10Wf&41Uh$Ha_ZLGsVr1d#h7`Hst^$>&`j$iq}r$919n%b_OZacQ#SwsG?1)D7}9OO0?J zq#Jnwy9r{7_Ca6K_v|zwfkk2QhK~iT-`>5xV`l*%9)9;)QiTPhox`n9d9~f4ECk|h zi+ih^xC&yxeJJqmPQvAR`!N*3C-07>(!|GV&=DW(mP$rPH00*;3r3C%@IKmyG}-a% zIrI<-AZ8(=-S=s)c4ejURX8VToP~UcEZCw`+vaBT;N&3n4chQHgVmG3EZ#Oag?uVG z{+ZG4{@F03Q($pt5Lq_N$35;eJvi{W-;g+%QxEW9YoDeE=-vv@*hfT*hRp#4_$$C5 zP60WmVC|P+#TQ|jvH_Hffi&@8{%8QLH>?0lu)tQJe>4!BO&^M91MmjW0(gve5QPBN~4X38X+y^bAuZEb&lXnowoaP_v@YL2+~)6Fc&xfN}}?sKD=K zO`+0iel1O5ZA)Pt_hDUl;XRz;eQMzY&f!DJ;Ui7qV@u%^_u*4`5i^_-b7~O_oJy}a zUsald_{lLK@nEuStkr9XHTP1)?mh-tSHvC-%1a&MuVmTxP6l6X435;Irr&4^8AkE; z$&Y$Rv56xe8h{ zU$){>vEzHmeAR6}fUXdzxW1tOj8C4Amv*t2RAo^r{PLxkMHx|D)x}}a!6)|S2hC8t zuB5#pmzr>)MhEo|{`|xo${$U8ZqTNeP(BcUOM{lhbTRp_+m^-w^y(Pn-HddAmt55( zzeN)XUu~VX1>_fiBu5^gaFW16?vum5$nX2Wa-K8R725DM8paTSmY294u-`=SW zJRm?9YV`=|`9INk13**n(%T=@=FGTfmg7X5zlek|2-C*DHwA^<(|~Q%xhU2Da8c}~ zq&wwj=FDVX1c2Uc0bwQNTz&!ngaDYf;tx_lkHeWS2bqouSx;Qq=lv)*E@+b!>L0dX z-jl%Y7k@!R%E6S%cC3Ggj-Nw!t20@Zy=EiF5|}v4m0MJpKy~PHsEkU|g1YYy;?#p% zZ2qDKfUBd0Xq3Xk(Y53fn`e=ZB&`qR@@sesJemu+W{FB!!ApQj{^UxISb-1H`+YgI3P%9Yr{pV0fgBf|)eiIL27HWME%DS6*<1@K6LBR0Y|d{IEJg~f=+wn+ z;3!hLe@GQNq^hv>6{g?9d|=`8)+h>u%5DFR*TPqdA`hKj9{!EjG>Q{li<6<_wU*-a zmEz3De{Ngul01!)0@uIewe*(4k`f)+F0Jwwy)yh#0DEcOp)Pd4_MA}KQlbmpuif92 zcA4u!_iNY6Wdn4&(ES?XNEu8+*~E$tbia1=seBGPUPBUIZqZ$6Dc_kd-=Kr&Y~fdI zeX7_w)Q0ZYRuU=>L$#s%wV9iW^A;`We(ir5uSxx+zNp++t^}?of-H34+^UF*t2Rff zekW9+m8xM7R0n^m&i?_2m6r1^O+77zPq3<*grElC2!fr0&GS>@Cjm5=MOhhDpQwN- zHF?SZ1VJ-#A6gM63*pLJ=yy`y*CWze)Ed|o_)pa`lGi1_sgrP%wbZDi3PYp>)qQHM zi}Juy_&uYRMp2q0Sf@WN-D+h zGy@cxliW1JpR8l^o8x(M$gx{;J^=F4^oYW^qb&4|>69v0HL`g4%a2;rw*WcY0HqeS z#{MG4Q@=>*8b3Am#1L zQSK86x8l+10@iqZp8fHt+WJ=8 zl6d9I#@ci>M^tY{ntl#PKA{yV7OrTv(x3&-}cP#1aF~|&* zy#@8RnVd*BQGq&vjw5yC4WRf<2?D}8qcPUW)mMjO;rCz*8s^J zmnrQN@}%>Uk%qYa;+=%-OnfUd`B5_Voc^WXJq$KO>E?N|0G8~@ed=*%vbc9R=_<9- zYz$5IE9QDaW$`E!z|902f1@3?nmhV_T@LkxJ04}oRSearZyKmQgPSl_#5NxEk*dXg zhJ{a_qV2NIhcE0_vd?Egfn|GJzAjtv&yMz%P~hD4dC^P`+s-5W;hq;c5}Rz)I686 zG?(_hqn)u<6h%ApRoYUUpzQ_0bGytThxy&1c!vdAF%GIAG3jQ>h#H6LCyIkb-li~) zB()@{ePIljQ2lM&CLuGj@V1Hl z_6n8jyXIWdWof=;ePin^hiW|{u=|)3CDA~BG$kbwikOJ1z#tpb7Ib~}1w_9BNrP%3 zUxY(|NdOqqvU07mf+fL%GqRld?F%XVS&no)$3wCEtPRo=cSsMus5O9DZ6VA?5SC96 z)@2d1%M}nZ>z*wHPXCop0{xY%giC~TH3Rc2yYcFC@70wcOwG1c(AXVzqOa|tL51GS zAmlQW<`;cf{n~dbp%VRl!Y@ZEU-HbpoE3kO)Xo0FGe5Yr7~dXPLb{=}zc{uOKB2NS zO{hIvytLT-MYe$^{lh|`;WBxVOl@jJy<1Xas8~yJ%#)~`nkP~v#muLx^Y>Eq3V62m zIPFTW=AtCFV~n=rK5ZwYZ6~#Crz~%$U2h}lcQPe*vW<37pLX(Y&3C4X&~T6E^Qw>T z_4%#tl$NME6pGlS%v95>m#6Jks_r)0s5&-^RF>?v+o&sB@AVp~IxOt&?)E$<{XEF4 zXud4gdTVd;mii3u_ql7fcKh8u@ZyeN`}d`5)iL_--)^Zm;_u&Y`o4Xw>=PlnmlnC7 zCgS-Y17=Nt-Ddw`w_;CjDv;88&OicE<&Sbqk^Nm@%#RJIJ&MO%pwT^yB zCqE>BX@TAH-#BAHe9_-BW5kVPtTM2$E;gewA*<%bG4=<_0z>70q+(?q1yvn?xolZ| zZ&g!&LL2(;O1ZIfJgXO7yR!=nl{*KfyNBocMrMbnmL_JGM;6!mzMv-oZP@(R+2zfF z74+Y&^5>1q<(*4lvAhbT6}P`{@7^qyS9UJ}F1vg1YybHC=;Y`BK`#40A-e#(Rq*mw zQu6i>2vqP3^bHC34e*o26p08+NbpMh=ZNibZ04UMwggI=!qT$xG`8CnH%DwKc)SfQ z^~%aAyaXv7VZH4G{X@P(10#K7BZHsYr>5uTm8s|!{@k#w5Ax%F+um7spAPzQa1ei( z5F-+td>$Nmk(bFX$HS3K(ll3bl};HvbVRp^6sx*(h)r)0QbOTdg=SMO=(h4^|Ap z<1){CO&QF1K^1B~6FM9B&Q1S_1xO~wRx1xu&@!e7pkM7IUp&+tlM<&}BFD4OGiues zrz2dn=P(ISyUjK7z@eO{C@q1gGAUnwR?SqwRE1I}XRZeMq=Ycl(Z4ap{>^~O)#+vw zYpKa8=AIBa>8whUddc@)N1LT4_xr+Yt{)D*_Ss@QvRM>j|5D0NQ#f7!zG5(`)`9gR zvFh|)R%>fWy>+#-g2-ykwcC2%+t%$}62g&XH=FgA9dyrICA8c19DPDri;)GYi^NZ#-FwpHBK`G`F=crVxhm0@N9FF?QS)Cei z<8(Fn`i$j5RQU~k(wx1&W$UUw4fC6^R|to>+wW}WBK}ka240?6OkRHmzPlB;8kSN4{{fLv;VbM)y-6Qt9o{M zo&u%J(%4ln=O=2-y%rZ-P`rV<$miavxxjYcFBr6G+K@OSe0Y*nsL`@!^E$NP%Te;Z z28fxGZTsX%ux&>d?+~2(mYQhj!`l=jhv>=+BLi;VG%VVKMvCCy0*T) zoZ+qpgN^ePBtz`pVpgmIn?-gbVS5IAgA&06_G5)nN+-jF42Ff{iuiU`9vg>1f4zOF$2ZH^^mv7yw7G(Ude$8kNiaU(zDWwX|e|%p2 z;foSKPtA%0=_kP@f9avx?icaR`(HdB^PaEA}>qYeAsOQn*W!mCSEnof_pZ@r>+x@|&$n^`t;AmKkL!zr-h1fFlbN^ZtFz5g^!4TG z4`4e-fCOR7w?U{6JaCke5X!zbERh3Gq7WpMO}-uP>46v35E4tUul<(Gfj5l6=$RNp;mpu#J3RJUKBd_g~J>ggd>4~-BH_G?$d8uK-;GVb$B!s`=Fm#41 zj3h>#mh2@?nA4D1mrWLwRId%fs@{Ryo6##pJ>keGgvh-`QaGz-|&u!I1%BamUI+jfuBhl>?EVra1<+Jwnk{jE~__x6eln_jQ=cf z(CGJsiO3m<)Lmi7l=?WKPZ`A*-#_&7hTVps1acLIt)3ny%?_a+*7gtExEv?15aj+3 z*)6|ed4DL}qYZ=hveJOYGXsIYLE}lCiNuagc{@Lu&r0QqjoIxf_kj9|d2<^vWKGwN zGYJ}EW1mHbxe&nGhQh+hz`ffoDJPty@jP@Ti^bB5h#G;yT?sJaHRS*q;3a!WRiSi` zB}simP+06>TvqXX$wxhNl#Bc<<_q0@`NUyTN$CKHoCe$nU|rN(X|LZe51s<*g_&&X+Q4 z!NJU{-{1Krcw#zQugD4rGzTEcEF(RPQohwSdMf(*m&egCj(K3+^HuRS`}zWoZS}(N z`hCLl@^6lplGs$&7#Q{|FR?!0kEABqrCK^{3hgHPziH97q4JO=sMKlq=C$XsjNM|R z78z?CV4+|O-eR_RAMO7sHoG#xQoeAf3Zrce1f4Th4^Eo$(viwb7ur#ErPi*mZ!5sI z1skynO;?sw7i#+M-XEWzE|r+EydU8KHAX~4aKRY@(Qm9JAuc+DyuZqaY4&u_v2e9e zj^3p_@^4;q3C^Nys>c_-$*L1^#cc~~KRD2^)cu_M8dlr1`M*10rgh_IZ_~Xe@xvGn z!i-;Y@`@$)B(j!Xr#F)8R|`9O6TP@TZ&5$!UH;y&FQtvs-}#|U%SuXR$|mz|KdAln zJtTH2E~9PxXy~Vv3;WkI%5Pmr?U4}jEzs-}L0cR1GLQQ_2rRwP-yU|8KiPO;d#1M! zP`xtSRitNCahM>m`uAUuO%#UvT?F=+(Fb%I1@yKP2xn{g6kWUdGHi{vY1-~Uqg(X) zFe1EZolWh00B9yAj5ciuj-HRWULPZGH*Y;w`#q5iG!xaDcXUU8Pd8rwJT`#%V9H)} znj;yj-Q`d4BEh;W*)3rSZu|bDF$<($7{^5AekgIT@6)5t@ti9nGs1(vp8pc;F*&F$ zdYvx*1bspD_4-rWbGOYm?lMbkIBt>l%s-;hSDD7>h#_|O)tWgq@K#JRb%6WTZhz?2 zDfR`W#p4L~G!oF@X9VUM2hN!szLN*8lY1OW;mrrcYk$j^_MYT@#wK2}x63SWr##h8 zJk@h$n1onaa4a8qdHsqng#-#_}{}VEHqjc&G_!6|@K2z13f=Y11{O?1eAvqt2Ocfx548-$y_#Hkj$= zYYce+_p_#Q=R-m!XZ&=g#pW0>_&|619gR^APnTHzKRLMtura&$z3hqB{J5q580A*h z4xt+Zb01K9&-wvcrtqy#kwX4Mb~H+D0bx{hoCy$|F%Fyvhy*)A1r(GiA9UBkEAI?D zOE1WUDk#kh#LB2%7;>vJ)CCbQ) zllSD7k>@^<4|5}r*X{0aM*fCIiLyn}^hf%bM;*#U$)0lH=SOW<5s=-9N;`^z--&LA zgYTBvKXi_!*^WLUla_)(@g8uB%rhsauAV6teJx9^aC&k93;^l``THR@j?8Fy;H5p4ZHm~7ys!z z-s4V!mvDlQeuAHKLO^0dP<=v3BKm#kc|ydU#AEWsl>E% z1Fl-lg%iEX8E{nS$X)Y(AA`TA7URO<4!!iuHvsG!?U2^5l3Dilka4Yh_sk1-==qy~btT?SKk)20E1KeUR>Pm1BUqsqzC6pfqia+}}N1A=@ zb6ch%8yNa%D7t+-&gxssz9z$!X}C?Q^C%3FqmAb$X+L*lkXo>V z&&nm0WQCtq%8JU~UZ6)LSKZFex$Rn^vRg$6t>(X|(0V38zrf3XQK_#ad3TrNM5Ow8 zGQ#A7V^Fr{#f79{WBF@*Nmc4-wkCnjTNGeRrt9%9A)9V_35S!c{ByduC+0ZT#wrtFRE@UujG?^KFU-q zsGTR<%Bt&FYq*>$$o*N6fb&TBL1FcLQ!l01Hg!`iQ*)C@(JLB>j^Bmfo++o$G(Yxe z#9V+53;@8rbc3|`Xs~Po+EO*qf@UdElL?)!Eau5Z8+^JIqhuwn%!E$ z)N;k8Fqlxfs@Q(^w2j)QZq2K$WTN4c<_Q))Xf>~WjlbjWqRN+r`pV3<-2y152bc;8 zp%6nq`bgHvzh}L+-d-?4&uE|tw(MA+3}5PL|CtEX4>?IfwB*^Ka?0WoL=ZLsRX|SG ztR$%*#`)-D_laE%Z%B>75W-NY&O}U7pMdkRZSD*1{3)r*hQ=P^lWslyULyOR)QWEV zCWK82=lhi2EmGhsy`P#8uNHf~xe>Xq`}{8-S#|gBH}(<9G(>!q5NqgQ;_8p4MTj&u zB#KGG$NG`91DRq2*#-lsj{|ur0|iY3MT-L^mjh+AgB46EMAn)>zADS`w~ah7 ziJ3VYRVN!unIHK0u(dL={0 zGbP(R;b%X^OE@Vh&c&lXDG0bRji+Rmh6oAADk4pz-&XpZzh#KY`X<~RwJp9&v zc#b>b=g=_v9G7W(aMo%D#6L9qbT}3|+PBB0Rx>m+IEZqa&r6*zXr3=xnlHJ!5sy`f zFH{*W)VM9wr7i&Cu_m`}*Kc)+gl5f#V#>RnmP~k^bYinLi($cUdQ<}XRTc-obM(HM z8z&SS`o8G;t@C>!-pmrO=Xg6&qweS7p)V?8t>Vi|Zg`tlqI1PdZA%>A=w`l$X0C>I z&0j6{8Gh;OT-tT>11S5CVx7V7U%t_;bX_eVHI{IAmv)xud+GjT9jXfuM&!Q;<6lLB zjGl|4(I-{Yo34Qd&^561)3*-%8#ORHIj^#eJBs{V1nl>lr+8-M(0>zx89WarQvkS&;) zxj~TQH~eu8$QJY*902@racz5f=VJBS_Quxtt$#HO{&6Mz{|P$+gi+ngTV2E3&&Mku zFeE5YBf=*jLIq1EA|b*5UxYC$LNzY?Mw3;*z*JOLUXjjER(YezO2rpxY)#Zm?>uhI>Pi^U=o%dvoteH-Bn-h=|4}52KEnI64xIf%Bsk>e{ALwWx4zUjZ`MueaTKwhZ+sNu+1A+V^F3QfBHIKGmtzz$SY1Mp1+&{>|4W-U#uxFyT7WQmlis@)sXyMVjDOT)PTTNveL_-rL+h&HbTz;Ilgji} zqw|t`Pc0X^`TTsgWX4ZzgTf|5vgCO8%V=vWfOoJG=zv*~#fm4^vKL@S;1yDOODMrg)$Hs5mMqTQqN-`D-Qv29g58p) zUpu>{ZCG4;WnC1n_saj@Em@Ac-)mR=xc2MT<8CZjsKWh*y_((q#)BTNA5AA#$?eT| zrV4+wT<$3Ol7gVzWu#gsuMgUB!Y@kOFept%JooXi&}PUs7DL-_42+pA?vpVYT?JV(E>VM% z31vYZrfyXzvCN>V?wg;VF*TlaVSpd0`wZ&&^VCd|+3_4;7>5`Cnisk^1P4JYc}^EO zG!MH#1h)@-ChSkY3wF^GtjvRGFW;Q4UVXZh!N!4&wJ(pt0K&MdSbjw6s(H!wE#<>C z55FqA-<<{=IRMO>tn%`S*1_+}bYgR*8-RZt-Syx{RxnL_m7z>fX zs=n~5!4Cjoe07f9ouC;GB^d_@|Hd?)q%fuGP&#;p&10Ac(OMS{F?CQ1CP z2!6>Py)ui20O~_K)!jGFO~Fig+CRL2Z+gzV@kw9?9hokK(HNh@+t)y@i*(xpZV(lX30YT)nvWH%>;AW4vK}~VPNG!5ItK~-dJEA zXL)VB7gs(>*|y{&hOtC%mI5^yiFMU%$w(ZQNOcaWb)?kEN!^xGQsKmUdgj_NrUOh> zC|JA455b?IHznW!^ZM>&S!R$uXHM9tWi8hp_`++F^zo)%(bEVV!8$OpfbQp+9><#X zCNd9eu4luC&dyS@E5bHNal=+S}+_f#rX z@iQX!(nQA9nM;)6T;dzhNU?)vuC<0%_w$S-$yFFy$eI>;Mm&4v2gRdtRNT2mj zZdaN?948SKtiMXd(YO#I`HGo=mi*uhx;K`)#yC?Y|E(f{re6cZmA#?zL)8bw^iyZ3 z97gP=>ycR#;naqIq+%P4XUZwO;9q;MqL_HByj$JL_K4-}<%xXz8& zzX&YF_mzyel}{E*tJ3|fm1-{5c1`gRW8lNk^xzOS3>*YVL8sigij*Jyy9k*WC>VA% z&HI{q@)!4klB)pC#}$l+h^MDB_kxbnA6-3s^@uac*W@@Wz0>eC>-A3Gx&H$)@C6&j z)utet(gUMU>q#2}E)G9_9s{9;$n7m^VkhlqujJsGo=;C78tB?%=P?UI{8^7 z_*vE6C=zU_xNU#=DapJ_pt$wEPuiK{Rj?z_leKW|^A}$CPs9okVF}=n3h+(v5BCcY zT7Tt0B@i+j5On4rDK9+)gBZ#O#_CBcR0c}O+*e$|kU)y1)k%|)LJ5iBghWs^y&yK3 z`}yo}!m*$dJ*jm}K~cS6CVK&B8ypI^ZV-|t!+Gfc~f%RW=w{0OK|#H~O{qB{)4{oz;R5#;rc zNSzJta6}NyMG{m+f^eg{nWLB$qMDhb*z+SP6B*d*qiVCF;0llUgroN~qaWr=0G5RH z%4o5Aapkk9M}eZM@58BtV^EqggzsbIw}lls#8nhxfXu;blGv!P(QX>CI?h6R^|7s! zu||neJPMH}=VHeCaW#{%Qh{-%c5&8oA~xr7DAM@%`tg+;U;_<^qrQZ4eZ0nY{M=-` z$GHdq8CA>^#xxTG^hJW|(Fv)O31JGt0A!5fPmFOEigQjJm41>W{4g<*A;nV03jvad z&_6oDz<{|kpYo*V%X%Y{o(kWK@JRB=Od6`SrIgZFl+o7!B^PJht4vI)QFwnylJvL= zC%d1rvX?i(BdJp%Wo9DD-8e-q2Dha?<;O%y$9YO&KX1=D^s)JEb=%a5ZJzo5)R}nh zi91PZ#-6eDU68|moG8kft-O;%ZI`2|h*Gu6qzOWC*yZTEz<35w2Wu!( z&RjjSl$QdiE8<+odEP{h3`0)X$NAiQ{CTd5c_&A?l1aI?L3tIzj8pl!Xp_7!>ici4 zU=;HCv7Ed?A~_*J`PXyMWa|4^L#2&I^}xx#JsPrk!*KA3BAg=sl9U-9z{hKeL920JLWJv59hOlzgm z5TojK{Ue;+lC=Sihm%#0*B`x#4q1g%8!}h-nxQUtsM&VyM1!Sj>q7UBs;8+W0R=-f zhpyTM6w(HVlnGvE)>!Y>u$xz6cE~B1A|DS*kyV0UU{`nyXdh2!a)|Ta&o|*^o@6k% zuS-LQ@?i6Hu-pty>zY)nhg2NF_WR#TJkcC2dP$W~%N8*0eX%wS-2ZvnU@?aJ8Qg~4 zOjjWF5Gla`)?|aAHPgS@P-rzyQ+BHGiKv#DX1ypK?Zl0U7nb-Syno)(_Sz=hAA{Zk z^zN7JuXm(_U%Nn{?n%4bO4efhO%FhD&`PIi&?MN&8*wQ3Y44@5gol@|vIb8RgH~A& z#0+FJgtIQ)rEL80`6ZZF_CCXb1n2;yY}+%?V8a5#-9$hA^^> z0mq#1U~XvL<=~v%An#azn}AwEB{Jvoq0k1Tm0(DSw%1y@cQ6{K5p&pXuZP2-HxYs9 zOz`L95BB z5=Iuo30AiW_S6Z^<_Yel3Ery-INjv5Ih4DyGj){$qK-FHg4{D%B-4TLY4hf0+Ts~K@oBj?(<(f8UW6>4 z!ETH%-b@=3wgtLzeQN$3b~S53JEzV>P7(_9S;~wX#{JJ};8OtHrT#tZ*0lc%?xgix zaA?-t83}6Zy#>#90T&BwL3da+vv95$&Np~u76|-7!LMKFAk2+k54ZH)b8`b+U(-j z&i#YYAL!-P&4sU9V+ZKD!<*jd#x}t2{_&iy|3dEps?+21-81xG+vy3A9Q{9W&<*zDcvxIGK-E(IxJ^^kVzU1D?UNW-|A4#uq<_F& z3c)*5P&2=&SEkJMYz8K+m z6dLUAPV+}^e@%1e8kctV$1)GcDGui%rEP|^JJzeaALYw4I|E1#^%wgh8RU!`SsnLs zO<3B)k;r!>mKEPRT=z09&9*Bx9(nKAjN9jrqa+f92iq5>w<4IbeD^sF2deTXZ}j%E z{Z<8^3-wBu2L`ISWTq^lyIqif@An{I8dX>MJ)#k6l>Pv7bS1TXPs4%8*Ge zTdYU!<_LMCAs`U4jXE_BzA!hBziHhyVu&>xtv` zM)EW+2P#1=W^O*lGKd2dY5Qw?(~grB{tCjac;1zwGJU?88A2V;MBoL901>>Yh+~4< zNsVoxQm*}&$oV}$9R%EX7z@Nn*Wh;IQ~=z)VK3-gBWG%%cugivAjwi(`fKO)>yEv) z&hRqEEYpapj-R^~L;LZeBJ&m#dsS0CkB14NPMUz;9+itzGx%}hd)>O1e=*;;{~Ndi z^!CkX*N(gm=f8G;SjxlRNrS=9h~Xq?)*{qB&R%nJ-CRMKJZ zeh=&m*HF2ni#4ApV=niP;`)7;qrr_l?#jlz<;tBQp-lrylqssHGG)JcIC*!X+>R;xl>0TYjXdCtCel~cXx)vep$m2M|ry+iG)(wC=>)P+XfE+0R z?(Am(y}i?B@#*r%)9=7pH#YCtiVvj?ptol$Ia~Xr>&eX$A{s}K$kRjqI(SXa=4phQ zn4~jv5)BG>(;?|Q`F0GtTw^Oscv%Jtg2E+JPhedQ&--zNfoy@y7_`(ZNZksv6btK z%`ZQ%F|@^q+ZgOdoTkaQN9$Y2NpX;%ubX$S^Gj9zVJpw+8M80Gm0ITRGMrg_5W}?E za2-lU1QD6E*N5=BHoYb}g|Sz0afdr`JT=6=|5aqRKg>}cBDe9w$0Of2Z z%Kkn%U>X<^lFh=_PbDdYz;s7u!k&+Tv=OrC$2}3gO!)8mGg->QwO7nHsvraHL=!|g z0(XfI^Ki6XAY9?>eq7kNO5}YSM0rIo*fb^M4E*>g0;{_4oNQzCu`2OI^*kT6^u=2c zNG4^GZjRLCT2|5TQ;!Z;pNtOvP$X}HL@e6?4<$GP^V zP}1Go8nllwsqB#$aN{RNIOiO>Qq@`p==>ectRU%}0$y1z#nnfLccx2B@9MlLj@6B= zAfO=t-wCXO5P4V>l;N1+!ZdcD{>yKF<2F^A?V$bzoOKtOQV!1c0B7A1p+)9wN^=7@ zZqwnSmx6K|rIk|6TQa#f-JZ_` zUv@%j#2>#M%p+Vma;&rBwy~}ETwK3)tQWE5rH*wq*iMRUsIA_2@HJW7vx={CKL8W^ zkyQSWx-ZYAnCkpFFO$+3gmKSy+hsI?iJTUxfUVxHw&`lbxu~m*9dXaSSAIf<*rAP1 zIZ{Tr;W@MvF8fgL01dGoGsb2+!$Ww02|UzI@Sp1u)BQTYGbzI$PCn~mS1k|H9WpI7 znviD%vc|yEqCDqX)QkS|un$9K`dxLsh>dp+WRhm;R7b?59+D9^;111%N%_7arjjGo zA{&9Z^RWxotzW@$1MXT<4%?JBw7Idn`a0N**An76h&^!{Ie`Hj0STY%>hL=he`@aJ zhG?gL(Yt1;VJ!z}r7DiBw^3|Hq3@O!$L}_ZpNR!hVn{A|YDmm}Y)-tFrTi&z4&zackJuA9tltdrOM~h`Vbk(ppKGH#oJ_-qShf~Q67)0_C&US&S`d71QO-Vb^TiZYKrUW~d$AR~eqWrL_2w~45X8k1hFW^WktqtoDLB#jX4v7#)_D8+ z0D@*Xp+j&Swd3QtpQ&~$9){%pQu@5;)TMd7Un0ULI9e=E9y2SalLsacQsXuGm{+o| z`p+~_LL%F}dBgOcYtMMguOMmh{a39Q3rj7hei!2ZI_t*8;61wCYq(`)dG6wB;SIyZQvAYcBk`xk(DeFmGZG(4)vixmpHs1Hv|Oylbvzt>{+46l zz>mw_y--rGgUrwQO83Fr5000D9`c&ThHN*6)9VLp;2sY`3xS_MpPxH;kWvYJ|7mo1 z*Yl3NXN8w1gT;MCTXJc2j4*yL&N?sdSufr#n!9ISd_vv=dfpH9Xf++s-WJi`B0>+v zX1xuMy%81$p%60l^Q3>cc`D)~m$>sS{M*A8C z_!v<6J;Nb2&*L|C^5cm1v%=xC79!W2_4|J0S4-*tzK-{8A7x}Th9VqO6A2Xt!4yE4 zn#P#w#!#1Ne+ql9ZJ!Uz54q^i1cLGq=@1A(8wj>ycm5NNjUnPT3IH0_|AUz>J(`=?5M4`8cpy})k924kJm7~xRA^yHI`X z(KeYYVlJh&Fy-vfpKHP9o}p$Y{{E9pD?JQH_QLO?!z89Kq(NXl5EN{RDS!Y=8e@us z1R>7;B-;riB>Za6-|uLPK2x9iG3v*tGmsh ze}__IE_R0`PPskSw4dADISxeP7#$g>XcA{tANXKS4tn4W?!dsX6|~7mc&Wz=pT^gD z#Cr%QT$|ImCMvv}a#{Ce`)RS8tOy+##=>OP1G2 zQhb-x)z8zHnDUS$MWsAtNSMC$oZPHDdF)Q=6kp1$K68(A%7P`!$epD5U#Tsosb3Y+ zhB+uU@>92jnUP{;(4Ee&Q!gh^?;MnHZV)2J@aWzR@b}Cbo;DpVR93}tUg4xlnA}J zOSVR2b{Z+6N)n?)0U7^%<~wFg2Vs~~pa60^%P2laJx|E39;48nK^vCfGlzQFPOJMH zTXiMjDPCmIO1#`lhM+c-&3vx79JL8vj%G%dR-{mpNA9Pjyp*=wp!vKyIIXTo?l4l< z!R4WU5K3|$=_&#Wo6qOoq*24mQa*$#HV|}aa4B;>jNi!*9mp%%$!#Rg%WNR?p>~bk z@ecRMy&uC6zEV)SgPMMqqxqXD&lr^Wob zj6vf`sQF?oYT^1IG^%ZiVIZiu=qc@p6}geFt}x`bF0{l!xa7JVm10%0@syTfUU=e& zVE<{(cay|(mt?+nGTU~7>j4Hz>YOJaUEw}lriyHAB^ZVXi-85F^C9j8b@|f$a{NJ^ zXvHk*T^^tNESEu{DC!CluDnx3#h9(lkD!V>9TjYaBDTbYU3it}3S_wlt>&*$wpqf@BMAdm+usIO%_>Lc$s6YyM=itm5(_2 zqmQw*B4kps&<^`nFWFdCr4K+QTVR(7;H*2=RnbpLTFV$%je!W;OmtT;2tgoB zV@S?g9qWdWGORxL3@l9+V}8_NDg~-=#f&soeBOu9^?+n7u+Z6JO4~N5Xn@$&-SJ+T zlEZWZDnL&>pg8d6sb|g83r&cFrt#O!i-XN*)8(jvhK~W-WXjjn&BfYR*pxTcmcUgHMbw`O#6&1{uv*u1MvJD?G-M?^Y*Vw4quk+X-h9X+@gOaeJPS^ICx~8$ z6lz7`f((Th&II{yX))h@OzAu6rQUww%1!=(yW8)Q#*@1*)hsDwu`e&O4@TYZW8E1; zKo?Bgk-SJ9S48H`-Jf>ZUqn2>72KcLq>2imO|{ETrNt{I7*Lp_5ELCOeG(H6%m)eZ z{*y7i0T@%zzm3BHzyvJARQ}K<&6{PI|I@$cr$9O9W*PREE+r^?MA-wkZU5SYxrJnz zHCzEi$v?I*Fs?B8&lD^wAu}?q;>HqKaAOIK&8SMquK6ITryS>D?H{OuYr2F`C^-?Vgq%hW&nu+81$_5JJJ z{gaIY^vz1_7?1|u9H;)DE$RS_Nz?15pX253PVu*)ND&kn6B`!jpO_RFml_(KmJyzi zl;fR}nO~5R;2z*pq8V5jP+3_Ri>ynn`P)$JtZj^J=;`em%<`aD-Z z^RI*=(9hZ2+WuEU@#y$uRaaL_>+~l8*U%sgJlekrMN-bL51CTFq`%1&Qvk-)9Zbb< zwYXKR7>h?GrnB0&M;{3A5HeVKc=n%!Vv0f~t9T?#c4x8Q&Rp&zkk$#YsQf3PxTE$; zl}kKpzsU(RNIgTn1imy-T{u%}{7Qt7Lz`vD6}N=-EbBqhLapr|#$;nXm&amQbQRr( zxzy@`fluEwwQrb4Q@ps~3F!`V)nU46DE?(kamsZ!jH#KrhpRGZjq^9mmEbR9Ds|RM z`GGgpc<(NDKg`)-?}jm9iyhI&6rFygXudLS`#yZbm?WBR7?UrDpN1#M6HmVw7P@#@ zf3|nSn4TXP`GPnwv@D#f6rD%*ZWt5VK>JJzGa^=F_~)w?fHC1HYwP9+Aiaog7!&Q% z*Ea22V~F@kP!n=JUVqw>~*zAQ>(63b-wtc3_n3uT#}rdWIp6Z=JF zf<<@6z8>*s94612zmAT&K}pf-ava}cv~(=L#qMvFQ38x<`xzy>mM2k;U zi3u-iwpm|T_HeLyMU|g#q?(W9Z>H^SQ+T~`!s4V$_n{CmFt5>$%tD5QSpw-C55K9OknfEB`zNSd4{Oi)z&Pv(drBLVh#VM)y?mvi&SjYZ zjKg|*BBY6`$$@d0U!2*S7FHmk=+3h$RXO%w3B~_*90nAXaGKw3$5;wQ)A{{)9kh{P zz=3wWOA-c2?@RNQDV)5uC z7xP&;8oU=>G&M+;o)R@Mg=ZH&%uzaofy)vDs~Reb<-9Vn%op1gYgZeo?YSS4hY6L7n(ov&$nK}lj@bxR4oF{c};yIFAl zs>prk%xvE@VF@i34b1kEV4Hac9k^?QfY3&C-<#r@Tk+(=IN;a=Wqq*Btq9L7D$=1J zVVD1(oSzCv!abnKEF@gD%wvTo3y;^h&4d=!ZbPu9%$( zgCJDCd85juh;@h(*>+fhH3+CGhrHyTC2Zj3;ZhyM@P`O?s6Kd^ZARmok;hqtz@XNX zWSE=nnY_Fo5frryC%~1L+_4D%hVbNJ!Bu#!&PN=-C&$XKui&b+iUyvNJTgW4*+%-mrw6+`j| z4R`kNIAN?1E#n6)%gjlG*)RFs-l(2R1TcCk%gM@okV`_99c%B$ zvB;1fgnjJ1r|NCmWVT=EbDX+){HB6^J4}iEcj>9A5QG0r4M^CqE4eII!!kJ6+oxm5&%3n{c00{tAL z3z5%vXWL5sRrbCNp`ffFBe7TLXt=59#oU;ULvEJJ8_nLHuwmY6XmBT#{s3WRTT}z| zb8Ku}X%@e!3gUu$;%wZXna?j5snA3OU_nhr6g8BIwyv;UzbdUckc|mxeN_vblqHptx9&YUBJ&NiK)a(y&2y{WF0CrZE9)l0;rX?y9{7!vp?yvTJcVj)KFEJ_ zu^LYQBi6k+&+^Q*75mHCSh_1Tb98t5N6Vh8!R2xO=#>s->qT}=%hBUmxlM2MW!|;K z?fClu8STG)hRL za~Ar(@3;5&oxQ*PU1y(joj>bZzt@iy&w8Hwj`N+X^i^2(osnUmW%g6czk-v zZ11NRbS2u*Pxr`gl98PPp?Oo=|5GJ|7zs7c_g5kdSmyJ7V0H!QhmE}ouvfUGiwii+ z0{USL4E@SV0aiY>^`EC?(W6rg=6C^2ZaA}EyXQutBO zcLsEHuVkzldi^CjF-Q_qhh82cR)OiR1xVxuT~$&I?apW7jS3xbl}OdrUfv7s zVtebqKtJB=zVI?^Gm8*5lE^fcA6ok9{tiC)i+cEep!{4=ctV2Ykg)Q51x}uM{~6)1 zTtldMxyurX-Lnd{W=8n1DH}0bYwbv4|A=%`;VMiP!Z#10J?5cTjAAYb+NisFh=T~n zfbK%ytdB%-vqyW?+22A*%fE6FS)>^_u$rD_Y^<7*Z5OCV^YKAXZ-_y38n+#E(`q63mW;_!xV2YjK(;#pN0YlSD;* zUF8+h8*&frKBJ)7gr|MDixQ&Q8F!CtO-e(CCQvL0$>>CpS$B6c=1y#3g&dh+F&k+Z-ZrYm`PH zs~$J;7DcL|wUiIXVk0_~gKk_O$;CfUQZ&O;ryWw)KxqpFLh>LQ_wiITBJGSWGYz*b2eaS=+duAP_Gf27vOnXpjZXOa z9kV-~xNf`W=q+Y{Dag5ZB4$#UeOD=0Cpw3*pGs{VYHuN|(?IofJ>$9K1yn)q!aURn zk@-59|3yEwyG7tzU4E96ybgR08k^_aFNCDX_uz;L>F4to&22}d22(KqU@!QkniA%o zUy04H%qXybkUwaZ;wf54#*mugo*U;_=o4IcN3F0EM%+VGq+XGcYEeL##Qv}=GU6?2 z-_EyoR?1s15{oWs0}*=%7u4-3zjrJagJj@OD7{aLb)Y52KE-$tac(f@gs8yd20{)s zMI`B7i7;!y7gahHZntdbBJRT>w%cQxN3)Y0EZe zE6j>`L#){p(LA-=avjw?mCP`sN302Jg^1%l9+R~kMix=RswuUCU&&P#;Y*c?k3y0! zzMyRoV`|!H3|02_Os+YINX#*U3v^2o{Gfvc%HGlg!Y*9zoWb`6KIt!`8rVjLtsn<_cKRg!2DHliitqH-c(VS7d6SW|nyKq`b9X>h0mz#F zjuHRLn#~`htzL%zT_OT)roT%>BmX$S*9=sdJcBdcv8BKU(YpQ&@HGQ7M89aj*IW<; zAejH@Yfertj7lpHDyj!krvzYw_zwnJLsWTlW^r>taW&v;4$2-$uAct~5AA%9h%c(@ z0IbcW^}W^2{QwWGuw$qeKiJR)_;t?5h`H|xr9%YV2SUXNq2VK;W#Zgl(eiz}vws{2 zr1}O&dOu8cew^+fnI8E#J3cY{{^LT&)bD{WzeYYUj8829B8#ECB&Olog=`}e;r&$|bw=e?)1Uw>Oj|Gh^bZ@T}_yovR1-V_xb6NL^0 zek;W$rvT*aTZx%|M!{)$`Kj?h+EjcWT^>|kUQkmTQFX4WXlcb)*LBpib+>o+6#~Sw z_sN6ZA3|6@vW$g{oOhbg);2a)Rtwg1E31R^i%T}kYuh_58(+We9_~E&zHf8%oACQ* zIi(N@w(Tk8m|3M42XvZ#F@X}v5N+x2Xk{GFmIa6t;6E-qLe~uSwWD}Df_RKN`TN6k z97D~IDg+Ty()q(xYsk<KkUSA9ruQB_=ro}^y zGLrmc|21r?jSXZ39uE2%fgnLAqm_Z80`vv>pS;N^_d@`ftH8wi#(CcK(v6;mRaXH0 zEx{__IF7>9kI|puL2kh^=1C3EX>#foSxIsJ&-uo`PiR*CaiZksLEGm8q?^nnQ9?%qf`cOtkgC0A4vuLX( zz(2;fnqrAgyml$x()5}}b|i$JH3=9az8qTmShxM@@ul0yl*p~-GoaJd3L+KX#zR@3 z0Aoa<;_Y@S`AuMqcwde}oc?}pI^i;jk(t!9z$e8?-s`r-=`pIPcvR*)1P@&`*dy^vu5mj-Afq8 z80Wbn*Zl=ecJnzrkf`*i#Xm$apqdfPq4*$%@1devtf|J)H;kNERs{B|fRa%*_bYd! z$b@G}3YLcBw>C=CiBHR`_Fgt_E{#iCC`fgNBd9`7pPjO`8OVC>w16(D?9_9Xu_;&$ z;@U`LBEQ!BwB3Jr<-phB>o3Corn`>ixh3ft=R9nYBRh+V8YBPS|LJGoomX3(Y z2#e%sz-B-fed3*tKScljN-Sv)rV57#h$!H-nTDfj^mUB`n(!o&R&6Auz`XP(KZu>J zgV9lU+-qWT?N`Ackr8f^*sZ}73y7YGI zaZ4cD8p7p2M6mst0VU!00qfd3#RxxHxMpS6QO2R}e<{T}=ywR5E}Z&d_wWK`;J&7K zE-}$Pt^&562i=0-SsxpTFZ6Yiy*4{}Vf02|>7mk-9{P7fww+R-Y$~kFZHRh|$nMfz zoyooq6SnAEGl@>lK%laUmrq)H2oF*0@f6+DXjfVGds^RfmqeY61&5+T)a$-YdX;K$ zT&OZO`5yL0###wMWOP9jcF*-o9E0>|xUR0+8A7J@;@&W_dik{>-Y5HRc7&Kd&oFM? zIf?5APFz@(+}ufmc4*0%RKvTw@V2#rrxHCWoMRmZBmE@T@F#lyVZz&>uPXH9xg_iv&}|@z*x&KTh#6 zYHMM;Wu|aB@+pYSim3Me0IM*%_x0)N7s9eUo;3W+G?O!ok@+AU6MmBtBK*rlKf-^EV7|moJZa87dh285)gdQwkO-xH zW%T(NF(G)9iQHrORel6NFh-=*hUEK?{~05uQUp#5F}PG_jp!@(wiSJ*;U(ZH(^fnf zw3#5+j$)@@3A%Pg`$2idAve-;FZ6n2Y^{83k2OeSf?SIKSKJvcqIuKK;B;#G_d(r< z=I<_lRTVWaRJOT=&lcoyN8R^fyD{nbZ!!ebd#``5s%VwSenB{$r)@pzG5EckOgLLL zXg&G-;rBr!;n#LV>)Fb=ubKPaNNX#0pS%8S?~B#%LoX;JpyZUe9cf5>bQzk6A|--Q znMwH>8_=4;=@q=`jDg6>78K{rAuL;tLvhuKvkAZC34-$hkyD*F8ssCaAkNq8BT*;z z8|o{SD0a!rm*^G2SAh+#ROc&{>%+h5du`QQOxRC-^*Xn`-*0JO-FzE_w(kuxF&?nL z;i{;yng7A4ui2`kMV{*hQ_=x~Oe91|D3{&SKzb4#6zH+Acj|)x{-2x< zY=MM_Y_OdG>+C0oYJi}b!6hh=G&j(LEYMHeFc%VJ#IK5%3PRg!ioOaOIgkuhP_std z*MWmJ7)VSJ_j%OrTjLWirGMOQoa-Ei#%=Wi2svT{#&Gb7B+jO}||g5(Wu`OZs69n{)7Sy!|wt$WF?1?-y6D3ttUjPxyA&FKm^PDP>uoXlRvpbsb1k!cN zM#=LszKm{5WU)qok+7$HyHF;W`~A9TE&CX+pqQHqtc+v-i?10STV)zWBSooX&Zl2b z&3_zAP?IttzjWIzZh0}*qMp}qGR|c;jx;I`Jx^>UB4KMDZ-Phr2VD1Rw4y&JncwAP(49h{4hRjP1Ip6J}L1bs+n5q1bIrs zeDbt|kcV697e%2d#WZ)Lv`>8k%Sovqp0teu{<%J?JCU(J&C?Iu(vOnTPaI!AsRoC2El=(GL@LrxKkaXk1jv;@i#aq00yk;!?s0vNg!7 zHt_N^P|}=GN?T;_7-q5RW}dZWi!Y{W>&CP4uRKq=p=FrSc-(>R%bkwZ4J@PayuRt@(@RWVhNz)_g_Z&Ve94TZ&1g{3EjIF6zU zrJ^c}BEVBohbd}kC~9gjB{ik-9H(qur}0G+t2h+{o{ApP0NVYF0 z9Ryf;5tPMJa`E`hnmuFzPWIx2nxIP$h2dcN`K9d_3B=wGE-#PVS@nkKpA!4+sOtWsHMSZKk>M` zG$4bvY7|&FDMxn25EHPXp#pU?Mg)@#Q=%`2()G z4HhP#_6`$^mL4>|qqDpBy;uJLsOv-X$iVo=smjlQ?t8X<^2^ewCw=B$e z%$I+rZBq?Ut?pMG9-p4sA9LoGnImo!`2#7+wxJq`l9PAPCjy2*v$1E6MSs80IW@ z%g+C983sK^I{ises4lP0`~GR|F!|J~`m>!c!xB^H?2KFazUk5_ z_!fU>^wGUX*fw>W1lxEA!Mjr*VLoJX8pK^mK#G!ggR2jVf>ZQjiRoSe%dqq%?CTXc z1(J9*BS_F)PhpHJ2WahRT98|ii^rfcq8}AH9Y}UszeNs zqB!{|iULTdh8&h_R15hf=SU}+YpbuO{(*GjI0cqr?-H)#`ZUG1s`@TJ-l|UNB9f?{ zd9xv5H4z|IdSmy==~n%!kvxEO(yd}*x|t*PqiXBZ&!AJ;L0}sCDLQa+gP)w8$sm zV9zas@5;V3Dp%6M@5cRKghvy#pWAs?5-wSspmDUpr{9apE?TEk#DMH~`7~Q|j;3E- z|Ak$@|9hBEI-43ULVTtHp;fq8C2qw|Y0pg5^B|Oz#s)l$oaYu7rlR6-@~J9_A!fzq z(fS|-csH%cne&O+L!JDE&S-AotbFN1@gy>#Jj4WK2j?R?rtZ}Y>Ua4aKWrbtuXBYQ zl!B;t9ol7j^)ji-hasQt8U$b7X`{e1GYVAAdzk(AEW>mFX#8$;;$XI*eBU2v{6imC z1i7Dlkp2T}Vj55?ANGMSX-bJ!x@{*+qoCeEjW{l>L*u!{asOQBOL{+S4v*3#=bhyn z360JVFO~K7S%pW(WTQ8duydz=szgdip@SG<3p!OW zgCU5XZYPEzC;$5OsF7yb&(IN_jt ziASAxDRvk%xfU54kGkM*$_q>e7ulxSy5cv(>=XLFUOYWVI_(0ub_frEbedfHuyqgH z2xwiSwr%xoqy8eD`d?7k;07OxUUJ~usk4)mV`r9tS(C^NKTbGDI_*xlTVpVhZ} zw`+Itk!IyR%K;r{P#YNS1fs)<=3D`v(E7Y9DxUY$y=2ikC_nO9tyl8#vxW?TABOWrf)a28g)O{ zvAOCQNQZ=ohdROP>5Rdar^9_eAa5jf-89@vc9U%%xvUPYs@2PLDfC zc)}Qhn)~^>G#P2?kygI&J9JPhKf$QJdjw6^BQY_BJ$rHUEd!&K6n+dik=L=5n{ z_8WP&;;sPmCj`@aNS!uE=DEQ3K_QO5bSHeT^r})oo!iotDzx5!5^}_cA$VaYzEMSS zHOPnY{qakmOKW;zImai`)H-y*~|3sT4{RdKI-F|NeE@;~(qh2KjX@;jc@4EgiT-e5h=Z&^xADl#Vx`V5Rv3SX(OSWnN>$ zjn{`wpD);P?Whv@ji3mV-)E&v@r}G>cnukWcl4olpTDwxIVyZ%yWL@r|DvcqW*OFC zxN)MwT>9zQ=J5h}AaZ))ekc9--tCD`j&IkkY2{4Sr_C*3J{!~S2mBf8hrzGK`kr>t z&vUx$NfKQyi}GR*N3@Y%MSWg>yyUs6=XICU?cLADD{}3z2nd64+g3+R*_^sV-k8v> zDKxAJNxJ#`61c-!f}t!{LNqa zo4LvXDGL7{wBVcn1BHMiwSclQ|3|J*i(&)r?_J663NZc};4~rk()GftAi3ABf#!7q zpS=Uz?WNpS1HH_oz6u8UPQblggI@Fore*{g#RP?u$wjiE^<>boiL!w6Q=lg(ARoOI zjZRCH!P*DLZU+1pxgkw;!GQBq zz&NB`JE+Yplv_Qtw=T391y)CZ7*XIwKRz=QgoF-a<^&n+RYa381^C z;Y2R%W%d;G37REe!`|EQI;w{+D@0J_X`DHQ*e-E?H`A44i1>LF@tB2ejg0R|L37@Z zc#g~fKf?Q)ERx3DPF)IcS419@-TZ#^LSQtKwm!yR-#poZ8%;;xXVH%kk?gtV>Q;KxeK&chl#F@ z5G~j8aJ9u!EX1zWhArdinKS5qu=1EC(OMqMwK!|#)biS_!F3AcJv7)zaa5%6cl??0 zPuAkWui`^G=>>2=84)C~9Y^~h!L=a4GbzM)LCen@!eRv$h9&T2UI{=G5`%RVH}c6B zWRn15Jiv4MS8FG5o^3IJFT+jBd5v<+Ueg>&WP-#%eUt?{F-ef*nqG=Lhqy)FmKTL9$clEQj4Z&KPJ6}N@<0pv`vx$t(|5_suwI}OeeJlk}6+M zHkOn+RnOa1uR9}>>V+VlXHUy9N{c|Ht+T@?+|t&L(~{fM!cb{@I_c35(u0Rnvhvb% zAEYiTx*wBcBOatyucZ$naS0KQ;HU5(J*8&J7(;zWhskN z$gGnSbb!iE)-Sg-*}`l_NOtXT7E)JGACqO$KxPt|eTxES-iI2?yK5pWzNm%G)-UAn<0f*cKSgvtou8}O} za(lj!aV}+Hej?l*y`J=Mg`Y76lm+z|#3E*MMeP1MxxafZCNe*aE$=d<;7b9yD~7Ci zz0gT5FWNmn&ap@yQg8!9UTIOV=Tz84!Pps0UKgAlj4LX!D86Hq{|1w15?T0Om-it> zUQ8hwp)dHOyWog!QT-I5WS1xT^Llp032C)x>AT&MwP22Q4uL+$JQI9j$5bKgMez@g zi!FtPvBRauj)D`I5(0+%NSAzAw5W2#f>;?ROqv@?S9-V>oUKq!wZZ3HSe*Kzj6tuQ z*^-acBY!@zd}yki5l{u|kw54!;nJ(P3n_nNRwnMje+85MU6-7avvTi61^otD{)lzZPTphFSEPErwDy}+*Ta_#-iHb|LZhM}f)KSN1f@4-DXE1}i=ZN~Q zf`~;JK`clr7tR}{`NWBoAk090iHrfPk~R$jqM#$X2j;S%CvssB9j2>;vRskjYhc0C z`{VU%l&LU9jRhSMdDCk9fR13H!2(I-3lVi!Yb0U;TMR=-5ujBx=#xkDL~`@6Sn~j) z`Br4}CrfE@#GO$X#558zpA0dzG919Z7LW85q-!2Kt%D(34?J3rI9q3wsm4Qyk1SgS z_@GOTRLf#ef*5{NnaV;4s-(?Ud)jD$jT|0tYzMWqQ5vXdHTk`4YL#LbNCpiR`6eXS zCpXr$caZUgHl`Fs&TEuV`8LE=G?YxY*@KrFu`jP06!`dZ-ZGFP3vBE-w5>bkcot4s z-_BDXo7^FuU(5QWL4~p|G`S6>$F;H2+uG%DaVLuRhd1@_Nx3H#_r+2Tq*y2Ai91)S z^nbJ+Sk34?B2Q~N<80BVBoU%~eNL6<`j3JqWy4p0ZG}L6N8ifpZ|bDy75Ud$2#m(g zQzu|F<{V}BXEX+sc+QbTZzJ!8rvB~m0P;d0etOvSJ0K(h6_yRG$NXc@S>hpy07$(2 zUm)?6jG|a<<#~xG`(Gl%mc*L&Y+PG$b!S;!cUgUJRa1X0{ymU4HFTWkO#n3o-_Z-i zOl^JVTd}?m6N5l0=kpgJVEX4!Y-whG1t{VyEUhiAZvH_J?QMMDJ?9SX9`F1ag#Eu) zzWIM%dY;?-c5w%Yw?v@~WyMD*gsfEtNHGRjr-) z_MZH%*51M7{?4J$;E~Y}pFU4a>ge6Lp{qNqm-+R4E;chae?x!e`;Tq^CLR6RFSA=q zlc#58di(3!672t+i`@b0I~{?v;5i%8^SKy{K&g#Sc~(yZ@hO_?IFy``gNOukr_b+v zF81Pu@k zeMfV8Nqcor>(P(pkEime`HpmELYRtM*|&^jWdq8)l|R?w-^#FtpCgIt8sx}kv7D~v zi+#!0(#4vWcW0U#KTxGNe>w)OPaF8%Cjfgo_uCOP)MruYG@G09R^Ft7Z1X-pd0bgs z=`Jf+qoiJ|TlsBluX>Vca%zL~)bp{@^t#d!C>gu;W(7PS>V z1zAUke+TAb>c4zr5g?8v8iE$TBstRP^o6g6k`lx5WR&V08_m_*Z`N}3^tcSY>5zix z&P1Xug-8mCY_v5Mw`U(Ci85KA2F-;#!a#lJJa|Hp0QDU|7RU48sc>5`tlE1Sn2Uu;@^n_QJ)wgpji~|kotcCBP8x>D z;Wj8kFV2r-_8dvXR`FAn{886AOZ*R#sDI#l%NfUpWYaOpd3|SN`bQht^vUx!puXeO zM6M-XUL?lTHALuOv*X(CiL)Bw$+>5D8yT z@!os#!`qdQz;%Or!y09l7o2Xfl>8j+dPAgYPq#D(*b2W+4bd48f!gSdOo8C3EI_7{ zZY?sg1HzFPc4^{?*X+==j)&doq~qrs&!=5Y??Na9-iOu9qNbA%=ly7FM*&VkX&< ztx%AX!J9l|*kFl47!f%vL(~T*3d*^rPTmd{nFtW3P{{PgVZj7364giZAc!;^>4(5x zl|171QGxrk3X>5_^r~JXSL5Q~(jw1VLXfHPv+@>Osoy@zW0VGys?PU999%EP9f3$8 zsmn>wjs&zp%IN6?d4}0b-44xDS<(66KDC#2G?;hwuD}EmbHUS*R8xEtjuP@OHeJgCX;gRV8b4;{}@U(GCvfDb274K@F=|VJ-@kx#bny8%l9$WZL@fqRu#1_wg&~H)1@|ZNJH=Ir-Mp*EUkWlaoLl zE}7n20?tpBXX|o&$&@F+1o~+58D34-_77D!zmen-ytH>sP1n|s@4@_~2PDr<>55SX zg_GBu-eC0bc*7P73_xpubGVIy2 z1WVJ+_%6uYP^D|@gSqu(`#0W|WpBAxUi`l51MrC1wK#5&`#i~Zoz`>$v2pdzYOA(W zM?&1ch%PdgxwaSt?D#zPoYzHyN#MiXZ%bY*2|Q0>H%#k>$&W17_b=A&2)^Pf`Wb-0 z)mLJ+iEQryxA3jX;lP{D>mo|TBR3mH1#Yb6h}|{vyX zE`&zTt5Yx9Hl}H~57Z4UcRomt9hvRAc*kk$UI2z_O2couJ?1{|Bh;4Ve<-JlN&L)O zIU5veWvKeFp?6~*1!4du+W48<<>|k;9lbmfzoi}2d~w}0TXgq*O-|mB*Zg48-_xAT z>NxE2Z?UuwR~L!i*+fy*ZQHz_Z6|IzDQRulK`+VXf4hG7+h?k^8iR_TwcpRyDZS>= zCbTeHY6!xtxpLi$aF*O+fA(4FH|aYs5Yg*h_j?fOE5k&*HZPmYQPisn6uqcsQk5G} zuXhl-`Kn7C`Cd=PygBo)YV!~YAR)``@8-P05_D1`krvkyAgGnAv%p3_lAQuX#B4@z zrtoKy%V(#+Q!8m3&9eHz{F%tcSnK1R?J7?d@dH?8U$>` zg6o0+ia4+p15&4G1@wJuaI7mjF%kXb$O|)pPCG&aTd_>x;1q>mF_Yk2*Q=5WRt3WP z`4hp!KZ9}F*MP;?u5m~W*)?D>_B~6;tSe-vG6Y|DwM8LRmOr#R=xSFYS#M(KXl3a8 zUc~SOU@KG^GYi{$6$Xs8Y<4Kd>%!`?!saIkA+x=qUyrUXx`ua}g-7LtZ^eXHY=?b6 zQrK3AST>GWwvU+ijo`_Sm?9Do9AW%TrgEkbIb$5@@G!F0H&Q<%vZf=Fra*;`J?c|$ z_^x)8s9h8r`&GvJsEcbs7eVaNhf(|vp?v1i!bzdB@zFD{qJQ&~5uu1mhQ$XOHq9n;-R zio1iR$MCutI~YK%;}jz8%dNzq<#BiG;|GsORrB?A~EoU@UbEOb(GMRJBAxTWuU zDcnHaOsoeuQKa2plF6W#O?4A_Pc9qNsXkCo*`;I9Xs*)Eo*G|~dU-7MjdN-}UE&_U z3o{+y6a}|gV-kGQ*89?m%@IrHX~(u#c)zBOl1m>SYwj!FN=s5AkYnpWZ^60>L==?u zFjGGjklgY_)uhCKhhJQRo2TZ_n2+Cm_Z`mS@u#4$g& zKOb!ctvk7iFJNDEkh_6TE>ujx?&Y7soEj|h1!7ZxMg^5g(ZfQjhN&72g8W#>;s7GGmG*sf38Ixc*`kiPGD_2Djd zzMnEwsf0_a=%;Ub3dQp?bDXVhVcB*WB#+_HgjR1eF_$?%&+ zdEm)#CF|>I$~DDm)s&nJ#PpH+?KQRSSrn9SO9dGnILn+j#D{gMf^!&=FX<$9D&G!x zvYqD6u@NGDLg*fQ)aCdTkZ{z#q^!48W;SMUv5R89|G572WtH*hZARXjv;ir(NNTuc zgUViA;lHi#ST@#pG}a|IHZ(RiO*gijHsU$|F&FFhXzD#xGRaJQO{^ZxcRMgrM5Xh^A@us}tg-0wpTGggXKG0?iDtB^_6+s~Y9 z7{SVzo17R!5Khz%BuGCuL$paffiR3hA9KWtLU@}|NLs8J{5xnbgAdb zRZ`BM`c!!%(4ES~wPuw8`BgixH!G>@t!(Ts?S5Z}AF65}F7G`z-_;L|*Q}k_q}tE( ztEs`!>ETav1Jes*Q(u8n)Wnz7o*z3vDGD&({aulLTl)@}@4jv90u!>$?VtZ*8vXw{ z!U94tAjQ)DclD`YmWb$>^ZHb5R3b1!JFib=Mzdz+=H+K$3W`h6MWy8xl~vU>wRt|* zLCS%^2(7KXqqCu@tGBPeJ;s-rqpz+&S675;eBuvSd+y8p!s6GZ84~z60D80`LAJTQ zvpX@me{gsd>f6{n0E9G$7bt-gtHQ2zw>tCD)3lC2x|P%r?Q&i@7Z#bTCcWiZTE?fp zf68cA*!D&V8poUX3=j7hPjEP<=ors+VifwU2m2Uj2GS9}>*{J-Jq&`nCZhX!wrIm_ zy(}8eLO*hPJ|sOkwLf(bouGdFPp;{`{78Q5zQQY*C7@2_NT}^k4WaEb6x0ew-Q}&m zgllv=Jh^bj`eYvGyZXk_(d@ZJU8IOl*9M!z5+;V$vL)2GeC0!V?3rRF7!0A-`W-|P zrX%YxmVc}AV5#Bf+IW$jX(2VI{K}Wj_|TdQmUZ9t+V6k)ZF5!!fVH)}hv2Xg6qQ$^ zhL>#fN&3cQt?~M^3yp7fLVLaBBd&7q?`{b--{%Iv+N-Xlpb1(l)ZFRu&gU;)hawCx zuivSrU%XER%&-zvH2K)K^h$uqj1AJ|M-TZP$c*B8bF|>k`GyQ1L>V9q3udn|$_!%6 zwdW0y0P0f`R##y2L{{KlzwomiHa`Dr-zWH@5Z{FW=XCLs{ZizXBKuO5J}^R))!*L6 zbAtfWg3;lH9D#&;0sa|@i1^7np7x^0-!P^=qmL4vUscG%yjU*C6S88DQl~LfMc+&J zBEeYS;$)$?{fttOLO9Ojo!V-akLFr_MigMg5s{T82140_+n*c(&7Cgg&~ zEZF9hiWU`<|3qfdS4+F+GhB#7+z1dy!i$7yCh*x*be>9^6@%v~*6?|KYW%+lJ^Gts zEuS0l{=*TPmiSI5lj%8F`$V!$l}yhWs87KH#dm@F6kx;?uqoc{C%89B^}~C__XdS4 zpX?1CGz>}&sT^*~^eK=^$To7fp6!ijkEsAgya>ym?{$FsRPPPbr`0tE20(qP{~nNH zb-X+Cp}LchDm!7HC-Jx^gxB$4TBQg8Yr9KYcaRHB49m@W9^QbPT@uEnLoOlK4;O+C zi&E#$MCk4YC9=Yk2Ymkg zVl6j0?PN>MqXk03Rt#@QtrSBxeyU^rB5S6DWmZnU@PkgxtV8SR*-v$us1BO=te(qq zIhtOw`}2VxMhJHmig6Gc54UU8N1L^mLa36&V7{k6KYIz7h0^}6`*n6myBInN>sM1UCX3|fmwU;38)-si41}~{xhD!0>_u8u1YM5^7(Ri+ZQ(2V;e1>L zLNY2i3mK<{ZKgoQPNy(N%GeKP1D|8#mX&$x0!rw+jZI2?2hH)DC ztka(R%#u3D7dnmNif59=N}wz>bTE48JpT6^cJBKS#8`-cy+jfn@}1~7R$pzL))DE;-N~5g3?9%Bb2t1Bx6Wee z64In*FRTiUP0_Mv7S{bZ5;GOZ!D-)CcE>%1#U5*uX$GOWj6`Bie&!*l3z31k<`&p#so* zTXkKUH$R0r`6uzgA9vNhjOTLe?6y8Wy4_SVPoi?lcdt+_Oj@Z%M2$?qnv*>7`kR9i z#zZ`X3JHc~Z&tWSsbPBlnA0UwIu?5I9oNBotM!2O$Tg+tG~1`?0?K#&r8i0Cl$eN$YH zF#<6($s-jEzOfpy#;T8bda2c+)XE$apervLeV?@HL zFV;7^m4ENZaM_T{-gJ8&(ztu2kEN!%B&z&@Z%`ubuZNPC+&!*s%%ptLe8Bz+Iu-wW zU%^^$);c}PV_>d!w7JOsgz4_o=~dq2;%9AMty_;tTMymmHUsAL=7#79#~TW|?hDh0 zLptflW+I*`hsjnr%24tdAzaeuXL8%L6RmU4i|9#a?qiLg{0d3j9-cI?IxI5pTKd5H z`*|&aQxe?C+pQ;+%TKZl54??vdWAafxpsjFC1uR_sN8mn6;AJJ`!P?Ec|t&2Q~lys z6mN{sJrY+2MxV8wm$wccQkq@kW_fVwz~Fg+RLM*4d`4f!34|CM%FTyhcbN}DL2{J` z0a0}Jr6qH-7XX-KetX}fnD9OT_vq7D0 za5_V79{NA(fztUQ7-M}Nk=-I;QhGQMV0rZFiE!Wz|7(y;&^`M=6JnNa83i$uK+if8 zE5oZRm4Ut!f$<|oa*08D)sXH7jZWi{*HHs&%F<*V0Qhpz;wuhoS&j)#BO*4<`{ zh=~o4(T;d78*!wqby64cXguP#>va%&q?T+Xlw5mMhhRSi58G4;-Y!Rqv3#mZq1-!H%iVy zZe4*|5$%oej=6Fyr;Mfm@Y<#_v6_kqZ3hbZr2mV#vxT$U?m4@2GjlOlb7n5)Iq%o= z#K$j+n1eKYp3Nmo;a8PaGE~JLBZ{-RN@mEEO%Y~k*$aGpk$u~RC0?$(&Hz| z0ScsW+vIl(55q)~BH5FT@1*D^kop2sHq$p3u_n~W(^ zGAXBlWZ`+q(^*n(#A!YQRL&_$dfye&r<2a5(%bgZ21PV#q|#&(pe#ga#H!#je%LsB z#x(YO59#C(_QdZS>8qAJ9Rt{FO;{J?9~(73hGrS;T8i(dU;$$7y*-@66sl7fft>~E z^I`*Fjh5Dx5vBU#=UyhgDHHsB)>Oa5!*KnHca~fkB*a#ks#; ziCIrvZNX?hdC3-4K zl_r`00xl%sifyV_K&a?C{`AIUhlMF%Th&T+GtQI zH7mExU}?s9u~a~MV`16Rh0}mSc>*hU%QZG4HSNJ`_=E^5V+I>mPg=21T#`OjM!|u7 zgjsIlQy~n!%cKgrQ3Ek~2k$Uep5uTnLM!<;OCn0J#$Dx~Y>C|HRoV%QDA)o*Y=nAk zaXbtmJ>&IDs_NAh_R?ah7Yu>i*D$IAfvZ8k^d8)!u4cl0N+gEOPF8C6fm9Gw4MKnf z>HV(zpbuN_@w!#7K|X?pDyYS>N_I4YVst9GDfSzzawqv8{ne7S zY%Kh+uw4$h_$sgK(&NDwy=ax9nrLE1FTgbrvhgZ@7o2BHSnLT{hEMC>>cJ#9u|FB7 z+lTS#@0TUOvT)@PE@?3F7VL`!(vlcEZ|cS;HK>MUqs;ImyI~)ElhVfP$$A>stOak4 z0;#6Yz7>A@*dl`^m)nK}JLT#6JmF&boYpUv#_a;#nx)Qav%>VWY(@S)$Dk3a~0~S}dMI`l(~1np%VHTSlqdCdK}Uwf~$?Ew;2RFSV`Sw5?Hp zS{M7YssCx)?bB}Br~Q^sZvxCZeeim3e5H9(>EkWEsA*Ch!`#RXdq55Se(qT=DbP)J zS=EdmX#~A7P}w#1S{<@+Y*8FlNZ2|q-JXagMF)ui78&VXAA1K=;qratT|-QezddQK zGilkB@Gc3m)4LNh55&nOTc7VMn1*_cg#dT;5g1j0wdFebaNGI?Aqwe}1-PaW^3><^!Xd~+m=C0lzQPXNX>31hYh9u zW;?sMFi&`L2oF+##zEK}xq;}CC<8qf4-lL`Z?6F5;D4f zVBreZYiyrI*NOEWBEd^7D2;bhL)zXDVYednI0sK})ZPLgZ%_u;wHVsC%-A8xRN6oh&`^%#N=Y%fAW5vW{x7(w;CRyhO z?ia&cCtPE4-eWG=V>e|F)Tjv|D_lRh#y~$YyIKe^zf#7a;rtRGb75#cJQ=^eB@9Q5 z-z_Jg@OUuz+Kc?>ght-PTm6aLFXPOH4`@~<9GfPM zITus)+Yz2p-}x7mmDP6xpbXK}ThlfKYzxb}N9vJd%^jol$Z_D}t7&AWX#rKXfdaOL zRa>aW9aQ^13fa~Bm!9>HE{seqP5!z58eCkPod2@)d8_*nHL{5s{EC|2M@<96!oPO# z{iE&u)AggD2VcLffBzGqJH0vtB6Q~$fFS%gO#6Qtq0>_L^H=u`2oCh~@*cX%!nyVuXVdvqW_3Y)?BZ=*cla1%aZ)sUB7W@EV)5AkC6sn;X zf#(hNegERo-p?m`?s&X&{=WFK6ow8t?iXsT3uHwM-snigm!J)gqAxy|n@%!h&(qny zgl1+3=Y(?g_NUN4EU*Z$q_s2YxuZSLwjQM|A1L0>19FVW=efb$X1BO`$Ds%H`lYwl3KUl{Gn)2`VNv$ zWtuw~E=LQ6irVubg&*B#i`BEe8L#Dl-iK>ZR&)ikWtO|P=#Cou`atkUFM}%eLNs@d zCq)lqtT;+Iimx$?a-_C6%D6{dt;*8gUrU2P=Qxre^~mPZ%65!{*re8L9IgsB2F1f_ zHIdS?s?PgMoV88+aGT0$!JF=S5THTz4&cFViw?dyZmHqb+vW9036>BCO+p&OD=rF0x`s8agw4vLHz#behKT0i}&yG=bk zFQ4KeS9O81ht2yQw%ok;{aj);nn_BU>9(cpv&*lQ_?MP#6(o+iw8n)t!m7r2?`h@s zJm6m8QBrJ3k0rB)f1QpI?DhZNufU|Wuk`YBt&b8rf7T2d-+a8}-2ZNbE?ns7awA&q z!PRE`^S4)9$>snnOLsZ~F1~^uG;h-c!>;#=4qgS2j-4Mw?N!fkp^NC9GC)Vo#Ecl5ZMp+h?#OZ^VJ*CVQXY^PtLY;Tl57D|^ zk&tKWqAbHmSMkEo4kiHX7*;jx=HCs_6kB%@&IF?j`0qY6!PIiSPI*ASv zd|%k)&Ol%H1G7BEi?bYxpMqeLlW-h#dTq2w;aZOW~NEg*w=pVBmu=xE{U_)}{iJw}@l0nl0eyukt3fW8Ig* z`G)!2Q8op&3+1uaC3u#noHQOT&){yEZL|M0wU&RBzbs@}-$l1cNuRM{2BzD>qgkj8Oy2mgXf za-rG43a{oZpLsPCWM2;!3Zs`uu2EFvaU>LcHc8T;?3gBblt9mpx;Cyf6`m>eWGdyc z*%UzTb5^)IFi4z!(GHlOs7Ylie~iaCH;Xn`H#$>};W9xI2!nFzl2#tsGQP~G(0Pcj zUFQ8=j;vlbuY1(bN)i4i#Ue-)v#F;`q#T)e1n9QiA3 zy1r;Y;#b%PDK4*5{b=l0u6Um`w7f0)qiH;%;zOb0%04hPG&j!Yv*sMK_4K9f>o$9b z-JvYi?U=k;UMSI(HvBDiF5&Amo>hmgl6|yBYYTTbL@D~7PpWn*K^DG1*%jz^e^%P| zbl9C-zwUU^smf^D9OdDnpUX1Lr?~SqHh?fy_r2z2r%fu%s$3F{WSoH3%LojmKtsEa zw_g{a&J$+1JZstQ+~Z~OP5#wE^PS9ODt2E`mG-jM2!=~PpFm%Xhm7gM#e6ri)GCIZ zbIVbavcB@H>dafb%u;!wYO*;|t8ei&kC#Z5ZeaCcZ)&CK9(Gke%S;`X*_PlKBq>ir+r02U$GP>Gf|ji19LK~ z3mp@;s(z zv>jC;2ZT*@GQNDRl^E}qNQ>!DK*HWQ-Ji(&p1wGZcS_rG3vlV&Ap6FB;*AO2yy`?T zoaa8P{_O96eV3lD;o-51snzNk)#r!{-Jxk>xIFF2Pv}XWEH{=X4Cwk_r{DPrI4KX zl4InqFxjP9{*HDFBR(?L$@q-JomZHa0{`B;vxktGpWSQkF5eml7(=dWFq$6;lb_pD zzlKwklhYku4q*yNzaL?;&|_hq!!sulKmMpE{M5dw{KciHErrtCd28yChmBmIY!%_m0yplo?QV)Zg&jUsYg7!|px6S?gixl5r> zY8$XOA9=J(QhOPBLK1cA{HX7F)C=jT%VY_Fl_kYNPsXEuS%`y0qFXegF;YaaQlblM zqVd>839h2ENMi2niID2Xq}#_(6pH|$EO{!1&QgS)GB%zsmYH4TzDsO$Tr9_)FxNtC z_*tx*DMTa-A{q@5TqBpUg(^ftTRJE-c3sH!d0kU8Go6ryU2 z9#Sj+9E2{CLM{VC*DRI~=SPFgk<)15Qy=N~eIlPzQ!&tn;J{X&K8+PHWO69UoM(m1!uMX>yPYI#YBqIt=V_ zMaHh4()K7&xh+Nw@<$&X+H}8(SF2%<;ZT2j!)^#ic*oPIrW4+) zzmU<}m9e%UvM%y5P2=OX2ew4nzPyTsAa!ohl6q$M6sAsb1s~6ctbr6zM=TJ_OtxsavzlB`gG+^kEcK4aJr_? zdn(E*Mo%ayiVx!Vl?xS8%oN#sPbN1=STAum{JKD zbL5-53R#BcTbGb`x#UxRFK_@)&dCASfZt%w$srd3*e$is}lFPk`gN0 zZ??rpswL$msW=lwS)!$Ge8tsz1TCSZeqXW?iv(@^r3?Xcoah={c&?pt(<}8|Z}U z-1TjrtJQm*D2DaaO$;cIiZ)7wqR2gO8ie~ub#BU0%{pQj?2=&>62t|HH&8XBrWNn{ zWNPvl>jp??cD6M|*iZ#M{C$RPQ(+iMDrZ^Alcw5Irpguy(X^8EA*>%dYz{fkD%@IB z?aEv9@yqquB3N2U^@*O1XNmgqvXOfY-jFv9)nw?i(n4_h6`Q8QD9ZF&qu#sEQ{!|j zwdr;=C9Gpt)V$hWVip?zbkg$HnY#T{{nI%xHB4*2ZfU;-B6K(HAQ~iC90@f*Vz?u* z(vdi=NW5hv!7Y-Yj^>z^<8;edAJRO>j$d{_oodove7{5R6e>af5<7vJF`ZFmT-Y=x zc=3srFI+1qnM(6D`U6{(9Hx;h>{OBL5LZFHD<(-sTNMIKgsoUWq+9mw6HLTC8c$69 zj2dYqIw9VqE^&p=5EJ-n;yuac(69{_Jr)oZk^TGk=u{vL$>}r)3lK0hv{~+bV*u8w z<))HEf4J7`Sk`N61AecBE}tb#4D|UB+?Yh@ine`$HvNi3=$Q2Q$#&?(<3aR9;Cn>i z81aF`LwtT!bXO%VdoC!$$)Ag_^ntWPPW$D)5PPsUSN}QFV8!hqLg{fB4Ss|>*rSm$ zXbqo@u_x?#kC@G?*Tp??eLbNYJ#u8d=oWOQHob)2y|!4L{5D;}?pRH?S`)Wjnnc}( z?&vb^-PAVA)bMmPB_-%#T2O#0Lz@S4sWbGq!)PL=S$Ut8uz z{Egpc81-vnsfKB3@j5U(#<4QSaoWc5R>lc_juX*N+>w|dHJrHXF+q_rLDe<^FtHas zti=Zt${jTB%~eb~G>mV^SS4uKGf0>XCt*J;+9xKpczk)^jPbuA0f?ES39C?sors|> z^&LW8iUmg_%o7K)6=k`$J}_@ZKUcMYRV%`^%FA! z6ErVJSh=XtwUlRdczn5*S`YpexIG7eTh`wqpZbTt6HE9@PhevC_c#q;Zdw)rI@ZB| ztX@%o)eE>xd*hk>-X|46Z7#u?Rtb54Bpn!6dW7YACCe-!yf=KukE$JD~$#PZ**<<7~iL+TRCooTlpQr>gE3=9#roh8y%aQodXQ%!?X-5zmL9??enAjhF2~RFl)520n z(Wu#ardfQkoSNYMM6)>h_)Ktv8S9)L%b{?EQo(XcR!a&$hMEf=gIdQgpRxhqwnfUJ zR@9%jUTxOoG`A~IVotawo+0r=nd(|$t;YZ(isNTDL-%BU-A8zWj$H|xMUy|}K`k+r zKwO8oBQyEzHfe&{REY<+MsRd8KWc7p#c{W=)jjrTU8Z)dXzXL|t=`x84~WTvKo(i$ zVT$K7y*1sgi=w=GTX8yKo*x`z^9n00Cq`*URLqDmK_Fo^#<*JD^clxr(&vSLfZM_9 zNK3=<nS8l_&3}oOzptBxiiRIiD8?}_V&%uH0>^0yI%dD!UO3@Cj)M;?G%gu zr6K+Q{=^a}@?mfu{^Rz#U-~~Er{Unrkbq8J%{8nAa=vX`b`?8n+AX-zc;l;s@Ckbb zw*y1OXE{UBVDnJ`mU^7JDl25XsZ3%7?deQ?J$tVd282tkRY%1OaR-Ec@prP^ z=a6LP3yPv`!+8y_l&Y}{9hOFaChX@D`Q4_LR{3 z$4H+-4++{K9g<|jugUYKuKnKQtHTyTucNEEcCVbXsn0(*=h~;|A9{R<4ME=}2jTWJ zJ89}VeHX9r2bh@v~eUR80JfHo`vyL=LxjJ()L-uBpOaM+U55VMK(ZCc$9s8B&hGeom81_oKh>(e<|| zZ@fHuOoe_as?+FTr94LRfqq%h)0pV+JZ9Ga;`aKlz%8HS`M{ud^JxMiJfF*4VMuTB zG_i3w{{f4`UE9X(q@DSEnDG|=OYm9pIz<7mu9lLiXbtsH_;&F}hE#JsKFZ1A?V=*f zVQW2&w6$AOp|-sd+f;jvF^ea-{VvM1Y~C50B8B1!@!_)w^pE`?SRXC$jCpeGVea4h zq{e2CdDM4jV$DP=y+?RYbJ1fm(va}sSdFJKpXV^dDm=Ar@D9GqL#b73E)y3r5vyM0 zK0~sRh?td$iTpr)Kf=<_NXmPKnEw8=+b$9=Nf20P4g0Ihp0Fu=`l??VDu50`lU|$P z;YJAJbCqZwLrLxc?_owEi%)U-I|Nm}m%huPHuyyG>8zNv%z`CTe{?W^OF*F9_G^Nr zMMG*s@Arx(6Pg!4_BoT~BPzYOv_!#*^PN-|h+yS16Y`*IY7Mz5cfLBqWR(Q&)x5n)xEfyUxc9Z4Bs@F}w*UO2*Xff(*|DeT>5C$%HAnCZ z0w0Kx5tQ1z1K-RV<=X&xbWKU*LGnvEU?s@-vrVHX?I=QRh{}Zc03&}P&i0M!vIJS$ zya;ra7J7JXvfSP1$mjSiLL+X2N--Em$r}{)?NaLAXW2+83=s5$!f2J=rQe0W+SRNR zDn6+*$eE~+&{jmlp})|hV-`6bO0)glziOaeK|kfkD_;S^LbNsZjI@89SU$SB8uKQo z&B9dPm7=~L4_2woAs_i?Vp*HVstimluP2j7YYT)%_Eg-i|NS^^>9pF@4CK5x6p zTd(uz$UF>!{h9Ikc!7t&;9A7;7;iaLnW-+VWffi{i`*5t|gJ)x8v1H5o6Y&YIyO|k$Z)Z1c zTf6;UWP%)7L6yzAo6JH@ftj$=#RQt+`vsC|VN4|WwFV%n#_AYr&$IMr%iF~rO{4kg z;W)`zVh2kgFcAWcYL+q>ZZ3K!0`eU=&l|Ki3mncawoMU#66W-AV6N%Vu2P728{4yY zwn^ZK+jFFUa>Un>IIzC8 zs~vlRgi#`oFtTQrt_S& z0Mj7RxQIxYDE$0L(7ASfVQhYUXDHT(PyDzqeRaqkIlMu2J|GSw_eLr7C&KMD63}lF(BKo`pBGTq5#TIqG5`(?WDax{6u?1<;lPCZOad*60{y!K z>*4~Hl8tyLz~)#WoN=(a4kuvva%l{To(d}d7Gy6UXYo+?`tig13KN^q7Tgr<$AEm(#b!f_h0U-=N~vSsKQ7qE=3_|`acRyrrt@}1 z`%MEMIy?)SDIam#5V3NJidb`gH_H~eI`4CG$66BsB~+y*G?L9P;(Yie@`NoaKr`z2 z67$=oA9X|23082e6gp@i3QQ>kb)hD-ji!_h>|KxcgT@%|K=1ZGp=W(gI$#`-%ze+% zn7Zi&FEJV(DOwB#7lTMF%bpyor6luJ4E-MT4h*>9Kr`iwYC63GV~^wCi}Li3;}MAy z7%<=6iY@1j4>FDS#2|Ut!4*eAB3LXJ=NwWkoS>n8iA;F(dPTtZ!*f4fMw42X}Ve6C4~2BrrQ+r}iYYv7tmO3bFjrNq$7#^)3( z)j6eFu#gZU#BeQBOPUmUzeE;KL{&AVW{|t$xuh-nzeNnBb(x~Eg3`Nn(*fGnF9Iix zP7h8<9==K+r_6}lPM_2TXj_JdY{on#Tpp1Tn4hugq6jFx>i9oy?kUI_z1$Ibw%zm* zG5zsq5AHyk@=ZkXOgFO&nt53a|Iw7$Je>*I$*h8AU9)GUN@rof6@eUIH8cy)Dsw_D ziSYU(u^u(LXm)&U7R4f*%2kJN4NOm!!zh}=td|3{_*kvj1Q9u0i#fo!5;mA~%r3+A zJ{wyG1$l6iEgYI7zL@)nDu;tAR|+S$emXl)1|koK@WCJoi+L(=NC|JAx@f-Ueone+ zUSI+?BnuMxR5p4I@{^Y$**{-56kC5W-_jS`h@&7$y5Kbqwt0#03l4N^D&m~Yf@3so zy}|tVsRb`nK~Oumv#X)&^_y}uZxcRzTLxbQ67CnuWc%H45|i_kp?JTDH0r$QJKA&M z6w}k5xYEgD@w@R?y4h$PbmzM2Vg;rxP3)yqsV#ZMK?$kVQl%)%lIfHZp4X+o%S?AS!DSM7Z1piq<4)(qz;k(>_8pOI36?RrFzcJ4sc2YP9Q) zRU_))7w@at#AJnxXt|ff1+S|QuW7ibYwq*E6tJ!l##OkpRMRh2?J`)?gr+HJEq|cH zC*xKt-%_PGRNKZ_OPE6^Yh9~)BZuo&Q}@l`rBj`Ed|jJy-HRc)JEe76V)c!Tb?3(Q z`eF5+(E7%XI+KI?nwYQs1|nYthwOw|dvMbgQ)vTXS`k zYK$wkPEZRq4>bx_|gl8KfsM}65@Fp|Z;Y%6MmF7Py`XN#7e^Aca^1E0 zbZU(paqg&Q>^K{u?y*K5!|>^BxT(r&lqEa+Z99i!+r~ONAJB9-yP=x!hC2zxyNV$! zureA>JoL`2E;gms$LViqxw_jXyM8Q@9Qm}!i*r%Ze3InC``jU-ecN4L-9)0)DruAb z*tcgOwzJbG+{l2Nxs@)pNEL&zEW;;JU}vNybvv8+psN?beGh7U{Ab7*>aTq#4Ws zyj>md^0>GY-3Lor2g{cK05_VU>fh?Fp?deB#`K}))}hwrp-;C%NSfhCCPj@KSjcO} zmuHy0HXWg)c)J+1yNSM`18>*-d@rJ#-^j_#Dq+d4)l7_|0?d194NL>9_(mRngA@vZ zMuY_V!drIIM-L1LW$7X324fdWV}6^%YD8dx@2cvJs`xS>hPC)nvn0P?w|H5`L}N=`(hulg6P(?_}7T(ST9D}#uZn|>DWmgtzHgw z%+G!a^ljfP$MFGy7_OjbSRgMD7Xe5MfRH(VASAGmmDY8IzxXH6sQ%gyhzjVx34Li7 z@i!^}Y-6q65&^v%u#NpoAOZa75uOXIVtxO)^aHw#zm;yu8HLg5h=8J6fIVjBl*VP% zrubfT>GXQn$on0B3m>c@DlLaJi3yZ6h3mc28n^S9BpTBGZ?D5O`7NC0D0#tANUx9eQ zf1`T){{T7u8+!bYX8=ONfrYHUQb16EZ%8OSJTgQnTn_puCM+yAH6=ABEjlARCpQo9 zyvZjNmI8r+$^vp~1h9}T^&)KeooOt@e%Rhsrd*-ioAD4gW1xRPX*6~`b#!cOs()c_ zc?DR=E>qn50(jnb_qJ6O9O&Nk77>E2{l=LyKVAuk`cyF zbqSbG2U!5m+l!6|R%NovnsKjbpXzQDMNHSdSsKqzcX~tf`|9tLy)W~?aI)~!&)wPJ ziCovKO9qZ$>^n#wEFn>YqS`%HGd1vzm12(K+a?n>HqpUd!1E@$8R8zBQXHD5 zN0p!U(NoW&=usrxD)MIr2M1@eRgP7pX+73nY3;04QE7dJo?=C{@1S*F!7m)H51sF+ zY^utw_N`a}&l^{K#xIT{#1!0(tFBn|ptOGIlzp#eEs%Pz(ZFQzYu#+l&_Vs)qaR!? z{p(Z*xf7w*$8DGYy9-$g^RjQfG*17rkYy_b7P4Fohrc~a3y z$rK1|9E6f2E@q(-X!Y(KrZ?fS%GN8{$Bt!ER@ zAGa{y3x*|c9>8Nep?yz(NTTq+%t>`Y?j(*`ojwqq>^3|RfA{lNq7C)S@N}y3@#7zT zpUE4iY~^mJcPN~P{k=;Y2SCIYI2U!tw9*J4{NR(wpSr5VMDg_K8MYk+jEsIH?s9F1 zJy4>z(LP!{*;s09IAo$e0SfQw!&dwJ(9GgW(Pin zn)LhcK4kc-HeQ}sp77^+>z%^W44}r` zmo|sv)R{oPzIg)Mw(J%44n?)FD^}F6Qzo0sqF!GSV{GtlG$;|&??KBOv!`py1PPIs z;k^@?5WdMGb0M#&GKq>w@sD7}bwM~8fMUUoNU^nDe~nP}gv`w(b~S88?dCh6VgnXd zeFa6s#pv85sC+}E()VftR5MqSBx4dXx7_2aaU4s(YRC%gLQ_=fqt9Q1CO3` zGob)W7~1`g2lAJ5KVy;dsd&TbySGUqODQU`9cQ%PZ|9UouOeBZ&y46`odmu{ey`UR zF$LGqNL<&@{K&pwKC$)10dM=^1nAvpNCTV?RlF_ zY(CG2MHDNU!>3Xg&kKY{idCEjr#}8)TF8zp2(QEE5=zjY(hqV9?GMf+NW2nvow0t2 zX zajQrT>2Z)%Ve?aTU|F2#%~Whh^EHLN8JbvJ_1vQc;HeD}()Tfx7d4+SGqdeq8KPc@yiEc}H^A5;YH3>=2_2YWE+EvGCb^D!+AV}EjsVx z`&}R|b-25eUWG~w+W3Vi?XsIqr7HCK@cP}~fq}@XaC4;%s-??b;ZdGY^ePZBmP%iQ zs1I1)he?5JmsC<^ir$r`nHi#RN9ulcQRK2Dt5-1{KJ3Y_Q{&gKc+k-CozdIEY0MlP zu4H|8KjSvsZt&T&Q!yX)7fvhD8Z=VM!@V(ygKgVUD=8YT+h;iK=mnCW-#z!*R>KZk z^Cl6=!kSU~5V6{4A@@`-mnY{#F6zXB1@5Yp=6GIcM{1>lSv;LjSC@oTl-H^Zo?-F) z?uy#o*J5I5ud;L~SCb|&z?7VW?K=c{(jFKd@6r-UJ_FICj9$LV#9A0MbF9*UzWE7X zT6o66aEB52f=eT5F|@wl)USMf=jJ-e|E0d+vHw@r6+&!qH-EjD(mLJ5P1o1a3x?0+ zM}|V#Si|`0@5eHZeW`EPu%0z`l8>GQiUC)DQH|ZKD&Io&Z`UctfK21)w@BdXkDjop zUryyTHtlwk?OD^{^U>49mfI~@RMRj}TS#5H-4-5e8g=>zqq~`Z*n9UhHj((01$9d| zZzdHlr)GLzRd6&e?FWWz?7vZrAdn2}3>jhkoW1}IVPtE-}ol)*9Y>b#uJMSFaU z-ZK+xB!@D~&;Lc+JV^X7o5WudLWT9jA7f7J^Up`SD9=~>w0@|Y)NF!pKfcn3QYALD zXPjJ8TRAVXy%*oajWzJh%ATTmNO?s?C<70n49HrP7M}6XF zfA4djBTW2Jg%grBeH1)azUeXwWE$_4-=XNZp^gl{^n3Md-ZSuLyN}nam#1z=4xD8XX#g@a1+6G^zKv!75uNTa)>$M>t8_M!H8ax#MV$bpwaW-?7hA`5D`Mv#~ z6!`_^IVlubsYHW?K<>)I0YF_q+xgGcUt<7YKU4zasZlZ!WfrcnFdhpNHYE%A*=KZ9XKk-({0ObTQuhQ!<7@GKnb zegub1L=|y_`laO|y|F`8gv!|?J02AIXNu4O=E&7XI=mlmzug!75g68a9=RrL#sAIs z1w>_^LSs$S!(cw@*JYIE)GG_VK*5ASmz{vcry)2C*smI+6NGsI_F93k*7yc~l*L6L z66}S5$R)>Ek@MO#Kw`+Bel2iPgoV&u1yMEzv4=QNb~y%h8}!?o8?O71N}@5&$J$+D z3Wmh}%8Pq|%_}n<$7m5bit!R^%Lr9{dDhP_UmUM=rT**+QxQ9Av>vJu!U$b^X6%>1 zUY!8jO3)ifz{L!2wUFy*R5#lTS2pqk(d#M~^E-V>wB1v;Utn-3wv{0@=+ZKeMj zCcWEBa->X_kWaRu)UWye=;#uK8S3Kir63f3mE8L}UarYZJ47IlEXBdzY2$~jth3-f zA8;bOQh&6rD_V3(Q)<~lYQ&igjj+)8|4mMv60*M0Dn0;MCU{p9h}jewX^Ok+CJBBNh#2 zM?ek+^o}JV*dS_bNk|H1=9}*X-&5$Yqcg9Yw0SAA+#Td0;|vg^DCo8JF$jza_zFQ_ zP;-`rgFNF2up|KEz_anF;!<=|X%@8}OF~#ke?v&N{rB{#ITm#}TmXdB<9a}qYa)=# zkAu<{bj^K{kSjW<1#n2c@41qpT2i8U+FE(CaII4_X9d?hpWw!eD!NB&1Q0~ zX07L;dAd}Z0C?1O$Ty-YNP5p`AX*^tJ>No4t62AeS#yDnUO@v|p?(6pIlNFfzrYzs z%eA>sr7quTzmRXH(6?FBpDHu#OgqTcB$ghusS%Wu3&B{!Rk>zMAumeI$BrD7f-+&p z>d}bQ72Ti3P79TS(#30(p1>o*jfzA^EAsA#N?>WGfn+E&dKoSoEjQ#D*DtK8aJ3bd37&`)Q!U!P4(;9$?9LF)mz=D zzqzUBn;|gaY~UoT-`lKrRD`Q4Hn_PpaI81D-Zbz|H+<)B^iLBv3`5n23^nL3HCj_Q zM&CR$*KdeZlra>mPYP?&O>0OSYGPk+$UKk?b7Kq^YYxw?D-3HMsA(?474j%;stgk{ zOiQfM7xEZtY_JweIB0Gu6-+s(YhP;aQf!H}Ztf8iYD;S^wr&|-5^M@Edk>YDto^%?)eb9MZed&<%3Cbuui|VKUvE1&5ZGB_JfUuXZeM>E#`xX3 zU5lh`Ucc#fiT`qmX@MH45!cS4j>Iq!xca@TMM`h9i&eK1aS1@&nMe&fwEd7?(VwV> z1$GXQgtr~Cxy?d3Nak>UaswuLWDxss*u!vvtFTU*sE{<1D&8fM|c zu4gr!+>>2W?%nd~e-^UK-72@;sx&?7;ys!MJ=*U7O<>@iz9-|fsavf6L;qgM9QQJM9p(wxsiQZ;eGm~dSZXlv#wJ+Q z$WN=u_!tJx5;qua4r*-z_e{&uBcLp*pkDXk{`6sFI9jLD@PPZUgu^h+$!peFIwAxV zcESilK#9g>-}R%=#=?hNLm(Z?4D?7S&p6tC>*(R~=;rY7_Ar!peDq*hOz~{rGt(JqQ=pe))Hq3XtsBBPKmGB9Ae_c9V!!2V|>(IM}p&<9P z5Uv51ZZl=-0UU{ebl8yH4wOH7APui??R+46IXGuL&GC@?91Yp(DDUo$6$P6J41VS- z{?zT(hU+TLYI#cS{j}$y##?t1LB>8VkxoIp(gp6Gukp2n%ly zn7gukeE>dg&`+41VR)ECOhm-Idj#Xj-GzH13s9zcPvv>Df(3Mvxs!`FKJ3Lb!v$8} zMT!NSf)!X)M1Ae}V*E;dj>KZJ#J|BkjK6SC7Jz$If8gFDH9O$K5a4?X&uszy9Z(Nd zH}TXnes65y@}I5^1GO!K{{$U=6Tf#Zp}@@{&~&hO33PG~aq$Rs_X)T6`<)bhlT`5c z@({>6{GR#-#{3D3=K04K1|^gR{}UFiN=Pk;`Lp>2FkpJtZw#26TlcY~HK(8oXp82Q ze=4m8{CL12VrOn!e_35uRdZi;%V0ecP~;5*BoOf9wfE1K45DhrQ7tp5PxGh-z?BCa zB6jt6{Go!~!;3&w6!^yiBt^$&*O3dT!BrH{eVANWUs&B9`SNpm4X8i-PKr)#{+ioG z&F`R=_kRI-QQ$Ojed}Oz@9XaV@z(z7#t~}&=zQnf-y!hz-zvn}pfupVv2r^9y#0zij@Q z^ln7#?xvmqlitOUo4T;b)F7%S>vG$8seTrt(C$2J&8M%4FsY<<9^~|x`rW7F`f-rc zr%g$GU;4Z%PeGr7Jyu-AhFVysj{m;9g>put<&eSqnqKZqF~bm>YZ^G|s-%i|7>7rn z6ir9qv!BH#^D)^ee(<-;s_#|lwY;@-Il4*`IH{^EWMWnp1Adj~-(b4VBGZ3}PRY6On{!wT?F*VK zdNL;2BH@Z*56cKlEVAtOv3jw5QG0U+Y@t5|vOkQd1mfK9h&zK88a83y41FPmn67|gIMhSxVLZc;qS>&N&eJVj z0?ozyl<=}9GmO%^=!HU@W(Di%el+J&**L9hOHa?0OE@b(F^2B3b?NCHR>|d5l~&{M zmg-l7&Z){H)i4rS492uu%2>z0<&~>$Y%>`qzs7@YfINFc%`hq|L`qwJNE_2tgr@Jz zNPXO5_rs*?r)NiSyRyI$4p+DcWG|dLv=dEn|HS9@E%i5)JPE{HwFkE$?HdQR{xFR1 zfR*94buP=);-Ag@QZ%WI& zJFntYqR#j_W%ww{D8^nMA~lx_NMR<3xr*eIZwpsOCp@CD;?3uNQbZcps9G zpp_3p_+zcpWkJ&!Y7;5P_rnii7;+-_k5qNgsg4|G2PDvBx}u-Pbk{|XY4v;P>1zla&A{Ar04h@tv@zQI&8;K3~f2<`-eI|K_5f_vjM?(XjH?ykYz-QA(5 z^WSIRd(NquTX(9aYWhud{l3rotX0u{^n?FpIylP>l4?x~xS?!?Ng73+y;9Db@NYfl z09#Be5-Z9~0I&V_-S8{|9!+<^yemaMUIvkryCxMrpURy2*)nKe^MzrGCK%y!(hf=x znL0erK4b#lEiO`YIx4XEY#va?HQ;K7_s|iu6P*eO!028t|p#K*rG*S&$2}6_j*1bFF-YJ>4BhU?cH@Sc$VB(ailu zZg-z>e|Fg{Yat3#-}JG+=5IBh52_ zu6O16ZWy}%zh@w+5?!h_C{e#W7$CJB2ib3BsK zsaR_(Rw{tcYSMD;_Gx!W30W$DhOr=sGU zBp69gP*fq_+2_0L@g)32ZY4abEg29eK4zMSmGlfNRE{i4E{dDU1UXrgG2{&?<+Vsn zVA;FvyXinUtnt$OK4kx+&EK)3#|CE*om4;`B zeA#Keae7QmmgagUZ|l6#5Ud=NXH)?(^);ys)+U+?DyUoydl~_}VSJjoEO*tL&Lb&Q;vD zG8^<4uk{fXw!d2X*#bh=dSVnw;FykGaGvM(DY+|XepEmVuITk!zcqAS$kO=#d|E@h zs%<8nrH_}H&BZ*k@1#aAvL(}6duyWB&2)M~Z*V;GeL}78sqqt7+f9cgY^#r!^S7gh zG+Mg>PMf!ARWNglKDD7!|3`$gs0U)hGkqIrK?J(+@%IbFTlhoN4p3n-iNQzl#39YR z9B0?4A6XOgwIWPa@q2D-RGRm#c6HTh7jDwLcj|)Bt&BW!KCVbKDbH0=siA57l=IOBO@ueR8)!*rhRk@9-AF^r2 z_8Hw)Bz$n21dKiQ7Wvoy)!&^|E#hn}+XWaxQjVy(o(3;Z?0vmP4-GV*7UxM%vv0I4 zP1ceYOzSv8@|Ro8rg)eBPI}u(^d$$nRx-FJ}i9sLtm^o=THIKZRCAJ84 zof>!qP~yFLw^_oSW2Ch&By{;V>I9vKwqz{>hM)HYf3c3@OW8#eOYG3k)wUAyUwZu_ zPUgU9n*Kt1(`)ktC6Meh>R$tmTuJ)n%Ri}dpvqNzl|Me4ZL-u9_-&cAvTRk)lDi~u z(`3?gNao>a73^W6-n_It;PEuCq;m`DGI8tU#%t-AA)PHDBR+EoZz&61wrmQo9?n32 zo`M-a0eHBd<6-e#ia>ZYaMDiF(z&bNojMmoH@_A6%4-aXT@FuIC<$J@?=We_>x6u| z&#OL~nth%LeREgl<8V4%-}YQ=g%aEgBObW)9Sd_wlLoQ&^*V&bHH?cR20z**;n zhVPCFEuEWyuJFC?>U1$@tt9*0UL4($13Xb^Jy%3M>+D<_@jajWomBhXtoJ;xKDaN_ zcrk&s&*#*@wT?FZ`VqSxnxYU7(s{2zKU~dol`x& zXDOl|UxIB=JP+@^?&h4`6Q>Pp9EfDV@2+2;ZUDqy;AW^46R*z(wlAdd)8Y0b z9vo-9`9nR8entp55Esqo^sz8 z|3!Uo|1zh^QQ$>0@9BFV*a@%UEdCqw-bQ%dxrN3_mD{hFma%kzp}YXB*YL}#Kah0K zSARb+qak?K&o?1HaFxcFN5aMI4h-J&2{3X&gZC9l@Xl}WLX&W0G zF7NTJ!{*$rOg&<`?U(NnSMQ?~2yu1SV-(e6n{cAnOk=nkK^TK(`ZR{T2VwjNC;k0-7~ zAx=Xi+=Qw8x4?}P;_k+{qKwSDqf3o`IcEZ@Uhg3&1gfw-U>i8ftQ?H?T56T1Nk%g4Z z^AzT{sgVUiJDf=(1CFopZq>-4o;hyvW5VzdWv5V^`>5npahieeOeBVK@*PYS^$?V;0X&!pJV~ZG zyE$S_xspS<0kpZw099o{cIeE1CGr8FW4lv>X z0IoGmd#t%fEi9fOR5${}@6fiFiWYy&(Q)}M76HK4LttUa4>>f`HZRl&DrA#1#XkpP zTEpN+AE6UZ7Ch!FCVj=`c<>wR?)g0P{R(I<%^( zh|j#RHmNAE$bC;e`oJ%rejsBR*))04)deZ=x2ZxUQg9Uar#THdj=IvHh`|N%kZ=#j zn3bS#&w=n7f{Ye5<7594Ywl7rsV8-ko=UCJLlOz&zQ!t z)!vfdg<+#f6-MBX;sxI^eg<$l**vO|)H*U~bNg%81?2=I;65p#*kpRJkbn{Zfr0r7OcMEPGaqSs<(`osDI6O>ybZfp$DDZ~aUV ztFs-e-u^VceZ+fr7$V`CF7V{hgIrUYXND8#GmaEB&s)p*RI4IU7l>U;JXgcCSJQhR z2lrI6r0%bgY_j+O!a2wmYp8o#NUzbaGYqcdp{|4ZR!UFbAYPx70FJ4BfJC~yso>|U zXX7d1v6> z)rxyxsu$caD_y1Tn!NPX8mrQ}K3ro&Qw^2i$tAnR1hfqYRSdhf9X|#6HvhiR3>w#H zzdy2EgmyzKgC3-zUi3By-~VLNi%9}i#C1ZS_3+#}2~s+VS~^LV|A{z|bW!qmz1M<9 z9J**zy69TE7?!)3p1W8`x{*=w5h)-DD&*biNN}N8ipL*tI77PeQ1Oj15mbL8r~`V8 zk>HFx5kQy-pbD%54lG%%9`TSKEH_+ZYgjY@0L>Z}Y~8KG;PoW}UcIGP`?-g|MH}G) zQDdZ6M+QOfx$7-^=Vt{3zKY)5KY%giUVVO$kRF0#2$_o(Lff{sxL&{0NU!U2*Yx>U zOOCfSww62!2p=b?hG7xhNxbCr5MueMtfOH!YGGq628}%j8B5T@o(CR0g-GDlMWq6u@%=o$QcgbkM$mq&3 zI!FP5iv>t!4f`X*V8>8hTc`*5H~bz0NNNNcx9Hve&+E7Q=&y#oYsdHxv{=;PjJ z3*np@?f?3?XWlw%u`+A*GHd;A&gS!+o%WoA`WX>~mp27sdceK)zK=OQe{*@C6q)i`VX&G`puk#ch)oPoly%2{suZXqSbBmPn z;syZ=&SkgcgM!*VFX||;P35kFujbJ?MN0J~1 zN^>oj6JBUrT(3~vq0M^PV?Ln)Zd2F3&``5|qkffLk2hX7%9{4;U4OT^ zj&eH9zxf_nV8dfqkt0iu$YX<`%*q*?Ew_`2^mT&^Z}VuAh9r&Yqs}IEm?fej@Dm#Z z@WC3BxozE)e2YqFi>XcZlfV|g#}>o^_lF)3;~YReK`X3dMr^n(vC0%Qvn`&sJ=L=P z!iime#q*6*z0}-=|L3w&(Kc?aROj^j>6L`}JAf*6|;sks{$YGV0qn-kSp*LBA!xA}a#fh!1wBvmQI1|i6pcUQ_=?PZ+fpgWt0Mp65jzw(R$?_`XWcBrA zU1#5$d> zsudzK0qqwcQKZiqfPI*Y@C-l*`#BaLjDX-3o$k4B1Pt0a@Uu0XAP5cTm1kVde**ZMg`od@L36C^`I4oif4?=KHQ^U)RYZ@;JX zzxS0#4ZDWJb1d~S6DCT-kc-xywc8Gd7h$6BUy zgqe5z%k#I6$x+=GBkPyGvwOcU76>r#Zxx8%vhe&y@7(zE3Q%~}^B4n^y&i*3EKXix zK{KWquiN7X*lw8j?XQm*NT7d`B>~{Tp#LYl8v`~qeG5neyp50jn=JVYWabB%kg%GR zmX#G$=9}s#C+nM5H9>()pPIU)hPIyGzW&&bPDuB_=-Bu~kLhRW#y@lIhOl+8hO_hQ z8yTjH%TQ+Z;Ba9nd1dVgN@V85|M-!1-4_4;1or*IH8NcPIGLamEDqhXvcgom=Nl?1 z<$yjJbR24%1R-w4w>&r)qzT+}mD^=(WM9KXZ2NMg<7xXn-yW3i3@3B{&~EA!#PK1< zv=tMU93z&_l%U6YXE<#}g;L-6fr3v?Df zp*kKW*XnYx9{Bz)E~J%@)%BixF*Za@GB#*-s#v$2R5r%^c#G?-!7v>7iliFB``VcuF2-4?PY6H% zO^{G74>mVOStW2THd&@{Cmv_aUOG|_k1CJFC@yh25ip&*n;fhS^kT$hK{jEwnS2mW za$JqsqsBa5*voLuwCjPS00gb!LVY&_`!bVg%}uhIw1H+>!IzQ;c@o-HBIrEI*&p+} zGB3;uqN8}R6!U`)V~Q#S?8y}?d4u$eYMDfo>G5|D>A!uvKBs3k+18t{;Hm|h)BjW6 zg*HnVb&MG1Hf!fMIkoE;W(PD;2$DEY8vgj+0_*qlh8OD&4T4i0B4)%+TMB3$t(xz5 zhcyu%nF=9~hLVc07V=A6{=^m}U445!8;ojsGgtW?&0+GRqYUAksr)y!#Q^TUvw0)>(dq_^ zIm^2hr@hjIAA zFB_hMO$3LB7*X~-i8C5&+v4L-^DbP zMP~}`RVCH6YJ>cRV{)1nX{7@>l)8QBKE)+$L zHCEQDN00I5Z7$P>p@wg7l&&PAnhuf!q(Wk{Ckk)4Pt%CQEejOM9Yy^>4c;U;)D4fS*>g!ebHt*_*h&Xk*^_07P z^wNUIpzJd2r~o7W(SH*_(L)tR<*_%cgAq=FN&{sx(=Rs(h6%#x%iz4x6b;|5sdZJl zm3aSrHbkXz8eoCE`h*8F^pS88boi08DkW%%(U5I*O0}Iw6&{Pyi)Z!tMzF>gyP>gQ z2#*-zork@N+-A(@3D%+Z57s~4<;tEL@zx6pJz4JM=A#^l>|l+2u-N1ANtk$fVT{5E zHN7i)=nk=BPx)Z5&nr#T5I%P4M^S5X7If0nPWxKXdAOXPrP&;pR!(Ho{GIBJSu@eDwaMZl ze&BX}dfA6|q2|TCQ{g0eS601n)M}QVJGxWuo+F2+aZ6Rg8vIpvS47dx1=Ncnh#M=T z^W&C0k1qx4kE;xf)_rmL$4LkyS6=&%ZKd(Y+2+@qityHB6ZxmbrPter@zzsE$oSLh z)9YOaM%#IS{PQL;URQJxw1MGHT2v_E2^K)R)xgN#(D$OT{e5@L2?M-6yXPIe(rpL!G`2vw#58kk9B;NR?HQd^U2 zWVXFLxtMho$YtMWCRfHx)x z&}eWYYCtBD@Ry`8O+k|Z+Lz*>uzjz` zIX<|AH=zlhZ{|HQ=81;m#WwSmcW6Ap6Yg0^3YZ+8$hjVJGaeg};Gp|JI2#Iv4?31O z?xbqkAwPR&eL+w~l9erwHb8Jl;wA%>I z`IB6`9^Vd0Xouuhbd}Whlr{AIMJfaG-y7IqCac8pf^LkDYrNtKrIx$J&O z*(ju99MV2{RP_f^cXZTncnpPApyI6Vq1k`ID%~?nBU4KQ^J{-**P#2gjz34eORs}# zuhWa0i>o_B>#r*t`%~L5P)ucG`w+TfJ3K!7*NScT;`QkK_T=(E=#>8}j(RA^qVf;N zq6Xzy)c$fTD$3A|W~vu= zcJ-tVB&d(6jZK71Oiho^F3!y?t*#B^b`?N-m(Y>g;abC1(h*cmKO1y6R3MIU=q);AMPS zp=$cW%imE5)w@k!R$q~)7v#x5rYGP@@r`>ZHvt^vb>Ty1>b8}WGlCg&T^L5y?LiKT;@vI z8MDyfygmJ(`bRE~|Li-~rw^udz2d~Kry^R{Ho@v{&(^P6nV5JQ3aV>qyl+sb7aNNg zo#INP-fqZ~L5tP3k8#fWTWM$ChP;4;`$ywl$tIU>0BV{DJPj=`c&{SNY;uKVEK_pt zO~x2MA5}~VZQoiMaIepT{=PoPTMdE*zdjipg8;L_9W8dVTBP(~i&ms)x2G8}Is*JQ zt#7F9iKvS8=M~s(1_`q)csv%P2p9+|A`#7Y^gZp}a-<~F!gfHrLgD*paRam9I2DKe z9S0(n!4H9kQaD5jCjN1xvOijTvoy~K6R<=1cg;dEd3NtT(^wuP#v?qP+5bR4@I9eS z6?p{EH<%-enmUkaaX(vI?ocW>gcqeSFU#8HAU{Klx+p)MDdNyEJ0M)nLrE^$#(_12@vD_EtM~1U z3ZH1+fGBT*6C%yXe%GFHa0LV!b6l3}A zFx+P3ea)B@0_}0BJCZ@~D24<+*BnWB0YO}bWl97F` zo8bQS;zZv(Vl%vwJ*xxJhELLAgt2Ts)i^rLhUL>mURYUDoOs+>-zh=TU3rO+25sKV z^I-=7Xg`NO|N6bjmvPsEkIl_vO;xj~)k3r%75x!a_oVpE6DtyW)5_?VF@r&>vI!DN z4jB;olnnBl0z5K+m*?tGmwiuzo39^PtF}KAN`cl&^Mc5~D32I`uO-_C!;T&}=vtUABeavhEZzn8T+LR$fOr@{#YUHp#db-G1qWcP;Guh0% z^_`5*5hHVu*oA7S;J>I+0Uz`N0cxHYDYU)uB9#%l1ZpRbhRy4rOoRIfp&nKI!M%{m z(1d$fqT%}hUV}-<$JAqu!K#TtMGtxJuSW6w5vJ(C4_@#L57Q9&ZfWD(Ea ze5Nm%fHWByf=|~8dIsO3%}{q}VzWk&N)Pddo;OPF!FUK!vK(cd3k+sF;WPmKWRjj8 z#9#OXIz!v>AX*b8B|`)H4{)9FXygcy+QvWE;WljWt-5lI zRT~Hqa%sot1rE4{iZ-cu)%y(t4HA+vY5C7Seh!;eq9D~qM^*Jg4XfH?*gw}29Q`Dl zyg!wJ+X6%)JqKXsVB}4hZZp|CH|wByXN}N)qi1=18_L9%6a4j19F(anD_M;*`WB5; zS4H-7SgvadgxEA=-(Sf-V$7`oHvee9Psx?tJIhqISYvKzwyx=>)bz#=cU@|(X)(5} ztpUohxTxk`LOGW2#Q{)`r6WrDt)J|%&XyN;FE4av+B#?m5%e0;aHwJ)mHsL!!9L=m zQqg)}Vj4OW{3omq-0j4#I5`-BFrtdh^TyQ=J$Q+6S|RBC(^(*oM`Uqu<^1tGiKiWhI}P zjlNJ3-DKf={|SwEJqlWSXtS?h?VzVRZdN_NbS!;+`K8fMuQwr9(6P+O=siOuMDAhO ziCV@4@oikpeg@Vx<8bCNvdU;&87Fk$$ejh?j%@7Ptno2zbsQl(OvRjL(${R-;87A@E$?AMhAc2O{pZLRbSJG zGNDl5wjy8l#GJTc$}Q|RKb7PVi#d5|ZPvbAamCCAS`gTmbF83oF;`x*9T+s`WL!`E zY4nvNI$Hs%rvH3w(|ohMdCD1+%y_8iLtHtrTi=C$dT279GzssRU;R_)mk%OIrNRnl zH*};%l1;dd8}HQfQQ&tJeoHsem{Y&%n2k2*dFAA`ZUB+=6tX$LTE)cG3|hHNdm`Bk zi3u1fTyLyY;l1uRg7=Vnx{9blT7Tm<#$7S z9=PUr1yQbK&!?`AGs0w#3uwRGhKt>9dzoIxGRNJn>my%s4Vtft<(zZRG(wZ*1uh<5 zUC*AmB)>{CZ;@HW3Yt#J!Q@eh-;|4AgwB z_B?-y8{WkKY7X!bqV+^Fb$Cx}$qV+gGu6^+@G^mZsT7!Q*L(ln#U)UCaZ_LWx=fjP zEttrl5P094c+~Z~+7kq3!P``-m_|Lg~c7PxAfTFv2m{N@fAgsSPI;e#nmz1JOs&GUSxxSfsf z!~Sslgd+J@)VeLHh4d!`Lce|5Z+wUX0>hDP_0|0F=ELj)LMs9y{?ORh-CNAxfeoF! zh#EZ5k%OO|B1dYS%pBdeXiNg|znPjuROCj?cLgh|_-i_vD<#;!RrA(}4=)0T6Yxa$ z;=3duIjJ;6_DFz$3%-;*Q6>a2S85U064rt7p=-Ii?2R$H1KLM7J|YK^&Ixt~NC96O z1B3^Ko$eyy`#lyLqQup~zXoEA2<_rbqMdMkPXof1L}Q7ZV=s`xXBq+~?n3+$q7TG_ z7pa4nRO1Ga!jyQtWocdV`@@2{BSetn<(zy?1|WgbU_0hSXZ?NGK<9X;L?66^_{ah; zuaCYv@h%ww(cEe=L1y70ALGCB_y$WvMK~vx7bI33#5iy#rxGTG$C*O=<{@#(4Lnh4 zfyo_`E}dq{Tni@cjmh1GetnIm91A9Wg(=|M6e=V;u0WH?z?3dzyH{GXbcf`w*u-t5 zG|*0Jzhuh1bIR~wYGq>@G~jspkakX(4)xMstEWTjjrWPrZCd*CLi+1NI)Eqx$eZym zH9b_5h0>IPx|o6fn1M-@iOrk&RwEP7C6gd2lc*_^WHFQUG4ns0vS^dC=$ig*$|A~U z<;{j#*EwAv+1yFlyiM7EO<9lGf!}h&g1)M|$ zocyCXhaNUafi35~7EV{LieRpaORky|4_ari9Q~;{;QYZmnV4!#a0DeJV z)6bKg|C{SDXN4RRPkX*7@2YPFgz797gs=+YoPA}$UXuTe5Q6m zc^a5`1oSmH)P*6od3i~i&P6qDi#2k@YPnOA1ykn6bh++9CF;$3wsdHk<`lg*xp>%l zf_!zs-^tm&D{=KISZUV77S$p5=4#hgJ1o`TnxU<}S2@|L_Z?23)syy9ZU{<-q)&J@ z*flpqNT;gs*@~lAD{Fp_;7bHoj`_4gk3xM*EW{O$7kmQ8h=gMUoS#s~86=PgS#S z87$V#QT+9XPs8`T#W$jroV#@(*?YsO6>qOKtG1O~fo1neJzTIAQQdx9)Ar~{0~iUD zdVz7pr={lwb8r#E8bh{|+#VjwcjQgZPtk$zK>l4XPd>qi!vCg@x|^}Pi5r>?XgT_DdcP;VDgN!LcMh)fM6m-V?!10WGn z1>kg3W!GZlcdOxQ(ZXZ@B+TFA`Mn2F!QztJBNNgi;s(EK%Zm%_MWgQ()$A1r>D|lj zRbkN5wdXCg?a@8%)==OzV5qdm?E_${7-{tt*^{eAaQ@utwJuS`VeL2X=1g``b(ZOO z8>x3()`*X;C*U9W^^?ssdBC4x08G-)dJXsCW*|5gPPk&gO|&rncpzqZFzxvtH9h}O zj@D3~+fYHu|7*&6Xhu_f?5ofkF13eKnwC_`P^eoTF8vOCf6n%ioPi|*0I&vttl<>| z#oLxg(!K+!Fk!GUVR|-T`$lLHJ%Os$z_I1g@E;IhL&|4$av-)6jKlHh{26vfbnOo35(t_=Dgt+iwRVB-5Ziz zwEvl!p7iAp`MXKV&y!FWJ+=EJZ7NiaHOa6t$@KD%DeLnTJCtK_pW;rPf(ozrSEdAB z{&FnBpQlB%r^jMpB~quQLZ^XE)2!yO3h!pVeV$Q%HF~jTv`yI-$ zybS(agp<{S6VsbDcuN1V0>>ROD~nkT!e;wyx08 z3oIdDEmR7m!*v1Lb=K&4k9$dvC4$Ixi>y;+j{zNv0b%LmW3-cDi-nda@g>KSbP(W3 zi#1#pTxjV6bU(8-c0~D@yD7KeGd6_BTD$Xlx_p{xKAhVc0*}`Ld=mtGCz#FU3;am3 z1^jXjr+bb7I!8)BM`=GtT{}mIoMVz*V1K!It9yY5x*$luAZouLS-T*GT#%DpQhvF7 zuX{-ix};6Nq-(!qSi59`T(Xc|v3|K?*S+EdU2&&h@wQ*_uU!d1t^~=hg}+>j=w6F~ zt|ij1rP{B%I8S6C*9v4e-@e=^>)xm^>&by`=*n)0l5e!ua&#a!(nPlg={ZKax8g3h zrn))i?YCct1~(6Gxl!(H#&c?MlkCHD?9%Uyb)zlE?>;r%!C>4A)7^vQA@>NUcVON7 zp!Rz~sa<1-`>?37Z0$&^F2|~xc;*ypNN+&=2x}#m-X}rU9Oj!C!}4F%Gn^& zVf(A@pYumd$n6*0n|4Sf%zx)tLe$hEVq)Xs6B3h>|EU}JMyaX53aCV>sANL7hb7rx zfZ5PD+rM=KD96$U&53rkm-qHXME4IthDV?r%Sb^{UP1Q6+0e~cHi z<$=nrj=&oMZ)i`{h|^ywkDYxGdx0#5j<7C8(soxok^|ZkUDyXcV$N!ep3{I$c*eQ&}}pa^*;VIZgi?PX_Y8Nx4$RUGzDY_ z$LVNSupQ0m6N?2xs<7+W7HVjgR!0L7&(=D8-jI>nXB>Sk2Gi?~{ll?jOQ*LzbKe}z zSO1(d*H*kdS?>-eOD}WHI@^YFEaM*0&LaEp-_7LP+uU!@&_o%Oe+<1q00;!y9)3ME z=^!9AG;dIWB{AUPJ8~D`i>hL};pb#&km38*V1FZkoM>mA96^p&7YsFvWvLUVH9*Z` zeGOyaz!5Id0M^}tt+28QS_wDKOWN%S5%X-xU?jZ4?I@X`EDF$fkwC*}WtG9~aOx&g zXx$)dpDF@$&-EkTDDES9C}tXMUZO?aLpn!%OhIn4-7Mi&g2Qehjh*f#*It?@LJ>)l zKitQCNG3Q8aW^Rtx;r%S6(cZ?3s*5O)Qcqb-pfsKXi^W3aiKdb2=$VZjLOL?q7zgT zo7XKU?xXvu{DJjQLaI8c21TZ}^&v{*li9|fik{oUm_-#fU*02f!>hUKP!!K{k7pD|h>cxyHH)mFVI^a=pFKpxi!dWLWqLww)os>B})u_}3i%`DglWw21wna$FFy6O|I?`$%&2mU; ziS-~@gkNGHRN|9pF++0|rWlHbukC2*bW#}=DJQZEg?)~250~=)lf;&_!7G1y& zp=O=JzM08s;=iF%f_s^mPzzvWiTGv{`f~y|u$1!;3)>Uo=+A!bTpu`FMx;e`PsY2| zN^cqDMK?qy+EL5k=YT2idCL3El*bo|8Qh(d_ggWx8r&4xPj|Hw-UWG%I~n-Mcj-ao zug;s9`C_!jVpO8>Y4k&-kt}j1(eLC-FhCE--{c3Lt zS}Xq&eR6gNfdEi50EiMDK%#R`B$*5#{y+x;@3|LdNCq5@L??>Ixi`T`1_IZ>f8$sb zEY(cGGV7gCj>TG)?iu#Y9#;Lq3kua5x4sX7jbGv?I7((WeU#dXZr#ytb6S$#i6FIR ztNjR$Z{(CH=m1Z+3UWU|w@lg`2~m23Pq<7ii`P!~UO<2#jKF;+PP!UVY>8)(iliV0 z33d-Y({`w3B-OjzNQQz?#W$2J+27xi!v&N?hNk`Q#AQ%Oz|f+ALjeDiH^678iVV-m zq2~HH7$Ex%Rzzf87y3PfW_=lxDw1R3Z9UlT26)3h4?r~fD2+ZJ1?xv3Ouuv~MYMbw z-+{WzNOn6+;9JE)JK>G$J1C=9G|6V=Ylypt)W-m6IuDziHpDaLZc=;s6k$n`LlJN> zGAeR`qExbp>-Sw8KMyliTWb%?XJ1?+;!lXFG8NBoVIsw?HF(x&gW~z%tHYR*oOpF6 zc>*o_uX9_ruUe7>RGGpRHCI_kjPYpnC}9CE*V*J~g%aXYlTk_6Ikd9>|IK2qg~A-S zUdl02l2Tk6<^oCP!XdMYO5bo1zso;P)8>j4KF*sXmlE}qeWNYrd3*F6^gUQQ;igz` zrbt6vVivy*SIBf_PfOf#5MP)wx%gk!%#)G*G{oI;>Ao2H6E$2kL89o)%HX` z-EE<+>|iLmnL38CGM4)f3qwDw|56i|f~p5f|Lqn1&v7FGhd^09PZ5_;1w(HYQ-7#n z^k01=L%T?0rzmLR2ztI%3rw{2{_7b1*ZI~hDAO&w5_-Y?(E|A=ag^&DRRoSL{wHx% z0Zklv=lwn9{zq9nv-Tg^XhT|Ib4*P;^qN~xT9;SR-q6$-5I%+UDN!*1_uG6SRQ@wG8YWobE$&<9}78S4YtL z(bePS)y=;u8Kx^W?5rNl%af$Kq3I5(uF^MAZ)4t3JolJSO@3aPv zaJvI4Ere1eDr3uovWsAf>rj&`<;lX|JvpH*a2rhJ4IbfHK~J{yLL>=+aCx$JpoY&? zbMj>J;-L->4|j$6)Y$~TKgbLz#~|X!W;;Yey`nwADn4e{(^ww{B1riXb2z`5s8=mo z)wK-PF><_TgP6!!OFL?gS$+YX+U4N?Y4>^tntXRLx1P%P|M(3WH^QIoE2z^5o-Hh9 zt6pp=Vt2kx5l{Ge6r{sLaXLbjeZadB=cxF(74GhWZQ3sY&lJ|ZNrxTfTyII2T>iN$ zN78x&AsO?*hNRKfMAujCf%2h|<)>~DY9J3`0i^Nc(vJZ zD>P)X-bNfRJFY$3HQl;k(uVnz2AC^1o1PUZ*tMs>l!wt9TmTh>i}+hq7?*o`bFR1YfS(_Kp=r0 zZQF-Fa!7c;qLsWwDV_c}f$@0LGvhZy ztgXKG0DpHWZ?RqPG#UzmS>n5(uT0j0C@;teQc(jB$ORd`-w3Jcf)IF3GsAEt$~_bXC`AMaqA&{eap zs-ZKbgK;l}729tjuzJ^V#2;E~3Riwi%w=_s)zRfJ5XYkV zxDm%{!n=MPo!T$Q0H5zvT~1)LP}$Jke&C$N5guDYYeR3({&$!=S8-=CeHc^xXFW*x z3*-Kv=SbYz(;vSwT|Ruz<}=r+PDbt)<*1eLQQx_}wTl2^!`Lg43Ow)(~vQ~h2XFY`Ndx9 z;wX4B#pV?9De~c53)tc8lAo(%>XF0gUUpEp2zhT#jaE2_3IVYE<*XR`Tds}BK7@_YfFhTcBtF%5 zDkuhrG-M%HBMk&tD{6e(k|N;f{#2Q85J^mINcp|Cd*4h5u!!x6w@4uF{Ps5lEHojB zJ$xJRubTM3<3<<_^Ii0R<3?lH_;t{@k!51A_Ty!IkqjnF0P@HH*gIih`Ufv(w2ZRx zdLp4IH66V(x>?*e*!ht>&icVoD~IZsETPS?0cz==No)x<-1)ruiDULn(Re#{dpv$0 z$8E(Fac`9KsRloVx}`;ny~Y@GH*O3u!LesF@SC#XK#9@1>dc-T8j*m9iNMz?8|b1y zGyr)b^wdT)kDZp`>k#;R&~$dQ5v`PM;biP=RTfiju81MsRIiXvUd#J+suOP|4TqZi zQW9GEHyYnE4y$s-ME4k?q?FZJYGc{l>G)FVzJCvrU@(L58+=!Km@4%@q1LC*Q# zE{&@#V!1I_o@tt{Ov3gwRFBnMJB(`dn32=xFq6nvABqmUDftF}tTbh=ax{+{XPHWm z@#jZbw}X8#`OcC4&m^^al(<4)(PI6RB=tJVxSaiz5>s*M#mTa%a@P}jGx?##=`g#R z((k24y3$MYle4vTqKqcLhc)MKZ)@vtOC@ZNG^YNkiJvN}J}s?btJWFWGudW7X>CZ= z*X6!Dm5%*OvEr9jG13{-4nx(YwbeeN%*N7-f#XrN*!3@EZhO*eE{6^+=l12+qdymh zUca|W`jvZLNq@VYz3V`dt8jlBT6{9UYW zjEh0B{3xhz9tIU|nP>%x*Jw2#hSbKY;_63sm|P!*_0X#m`ek-mlOIM*<*JkBMs_)y zA4aXis#E^Y#Ep_4rwin2i&X!fY#(PT!fH!QWREnK9%mcIYReo)k93|M=l-5-q3Qtx z;-~omxw@)&$mp>#-_ycGSY6HElkH#iz*t>f{pg9+|4vQ(>1hps(a?b?cmDt375&nH zMHF!nHl8GuaMduN>fT7FykRpKy0-K7lTGj}fvtx2p0|pJelS}<3Ko*`|6uMdquOrx zb|1BUT=EBz69TV*u4pN1Yw`h!2&sY0vc5yMgO!+72W+ zio{|CXnnKf4`3u*&A{Z*A9+*(*bk$8G)b!?|zif}ij-%jZ{ z(Ul-1_Z!s$KA~n@^euF4JWq#UqKg9v0XHA9dakmGBz6p5{1FcM9nkr59}pPS%$GF% zIq$O%$yEQ+*t?88lNY8Iu3J6yR`o9ZG@pB)eC$1j=sHlR zno4o@I{Q#N>xnxf+;lhkDde}Q75k}|f~ZyBejGoR$L&$%nnx#PQss0Ld|sf!^Md9F zy^o<045tPrfQ~ThHS$Y~^%H9_76}%8Dc~=q?Jwi*FPG@A(BQAM;IDG!uSOD}@n5~7 z`U?SuR{=&Of$s$Zkug?t_dv_UK$}^qeV~HUy?ouKZfV>)j2%Ny#Jz}vTqHQC>Cle6?+fkg6 za97Zzc65*A&WWt+i4^}Cxv8yapYZ9UcGRA%;*~(uuK@@~CObyQ)BT+&05kmlDry`b zemxLX-b29(g>z}RTwXyQlQQ8o!oP07aT|g7gYd7;F1*M#j5tV&Hb@^o`k6em);XG1 zK6>W+7jAl*PKlracN)%yXzoujTo|tnCqSIB;nq74xe5NOZN*+Sh*V>YLSwAbVywz_ ztQu*YhG1Mw9S(A#Tq`NAlvnF4$Wiw?u7L0vJ3eSw9fD+BPt<&j8smv3;_W`6yzYR! z1OqHX;%wyOR*oU+nVd)or(06or^bY(sRWYi1a+%8$7?nhoy5RvMC_X+N{gg;*Tuvj zQi;5oxOZ@H>~&n!CqeeAq)gJ}Y{BGQo#gya$%RSCO{4!+ujs?LQBvwqV=B@kF!p!c zXi6|`203mdZ|`{tLegHviL|wAtHs7NtYF*kgUFSm^qr7&>j89kZMmas3~C3gUpk@h z-(XM!uo%q)Q1F0Pd>KbcAm;UqE3J$rI7kp6DLxq5U?~PHmcDaxKNU3Zn}!ZbMi^PD zy~_ln7K2ZwGv_sY$&x`7m|4G=&1GY=$oG6<+SHOAfV>{Sa#l>r1%&-3d$|*l*dvp} zaf8Msl(gTF!?~A}d;t+3%6XNXBRvF=y$M7mc%D6%OFV6>*2H-_Kn>1h2OGiD&GWR2 z^9K6z#-sBD_5w$Yfp0MZU?ZTSwUwDizEx9x$6UVeNxq3fzCIjCz=guRo~P$g@TsZ5 zh0InTR^U+_J)0Pl-ABXHWE*-Djcp~QfmV8A5QX$UG^1)CIg?R&K9wT6U zz33Zmv8q6E#u5(a9OQ5}D}XSgoF!bZ5B*ZmFEzB7iN~~*EVHs$x?-usTQ1W;twes# zZbrN~v&s0H27(VN_1C0+k<=g`0 z7-VK7d(iI+*&qeG86%VxAuSA7mw!B=>#*{SF8a&luYn%6e?q_B>=oAQVxJ_JoSs9d zxBz*)04hL1TwlebTQpqO%66H`$K;jq9`+5%rDS~&qT336YHM0g1&~_Rh-+1TY}KW! z)SFC*Tdnc!l@(u!ttJcCg{$CJXeHJyRE*J_?CjHp%767W0}{iZy3jP^wG- z<~m9Wp($hvEPD&+t1L=%t<`C+9qyyhCTG&!uiosVpoGc;r~#Blb>Dg^UWoyi`a=h=DlFqV z2Gb}Q@>~X{2!|-2;O4Fjko1r zs>L2jA2BFRRqDAL>gfRKOkjtrb)phQsf z;1xZ(8#|^LKM@)Kr2bl47KKpF74ABItzR{MXM>#RJicfKz zxtFJ`FQ%CJl%6U3@F-8G5>M+?OpA=#yri5-Bc2vlo-s3@W($}u>6t>_ZaIjieH>;~ zm91!3XEY6F>od@*v!0vx!@8vkqo;aOUbRX3Y((C?e*pL~Vpt=d4#Jl$B>4R?YMe zd$u-aTn?>GmFGR}hCUh0`P`ei8K^m?DcFi47II}KKa?#*x%LUBDS8|(V7^%>B^>=6 z;op}U$`@qW?lnfBZW(f~5R>*XXJj!rVI%`*DauhTzU=K3?^3ze5@`@d|HzV`?@+@b zg{{o8_Np78YuKM_II3l&S(yfHZn1h}B1u`X&2A~>9=)e*xj&6ihj_Hgz&~jnGGjYh zeE?Zp$(lV3jyYdCKU)cA_ugz7{i%!>5n6WGiaW%jJSwWF5&@C6P`fJ~k8qW`JsihP zSZ!CH@_|BjL_d!B0>c~uOchP;@#|P?>lrrPl{iYMe_K;!uFqHphz~C%lhBa^fd9f~IIy)TyovOqm;k@7vsCUt zp+B;hHdI`)*tAkvgkNkH`9tb`zdLxZ5{+#^9?cYe-VSHjE|A(b!!z(!vD6&fqD$Wp zEq$$ExHGt_1T|D}9^0un-02e0d10@>t%w=VVfl!1SH_SsVr}*g>E7!9e7bNpRD z#m~m4PSwe<#@Eq4{JJd9!G0O@2m!%WO?X26oA6uX6V;aUFX2~5 z)EPWepZRWJFYRxsoJI6}bnTlw5*7M1U0h8cSAV#sN`V#qIr_PF+lIL9czW0M@~-FI zU7ye0K*k;NUOV#bZVYiZ@$`P`<^AB`SRvT?MEPFA6?f^e$(ft#_2Rv_*?lqiPcO?K z^o!|rOzfSPIvY_6>&1|ki9a0tGbA#`XCJhFeNfMqV58qEmi{i% zKlE(!dk>HF0tN!szwIM^v42mttvUdVNfY9Kc>cdCSSm=KU-Xyfi@$dJTfusm3j0rY z@EfZj9ovw14iDmB6BoF-d(1y1UpF+_5ti~F7(e@6{f$}6pNGLPcz$3^QAm7AMDjx& z3!eHlI=u?n#Y)L6j?Jox%V|g{cmVkEHEo%tZSgf7c@-W1;QETj{+gDdhw@eDSTnMA zH8EfE6H&XnSG|d7*+n3$R$W7L-6M+we)vOA0ax9 ze~%v{kZRzEw$)!9@I%|`uMQXq>h}&$zMubf0iWI+UL*d|0Y4P3{y)+I|KG9t|CP^? zJYV&J=W8H$!a_Ad!u`YH!HN(uc%;`XoOK(~ugDX~ZaLV!8FE|DdvTSujkDmVP3H)K?e^pwtygrE7TFwDP? zja=U5nM5D?r5%#zb1DzaIEd#fB?^q*Ps(t9d*&(TN$YW@s@AS52MN7#tDNo3S3?e3 zD-db)6l-(pj<8hfR7bGzB>NNZnJmCJMYdw+9LtvLmk{=JP(`<873-UmJp(O5yc}<( zI2h*0>)Gk9*9Els?k<%-4fLL>f=jql7Hr1Evj}yrO9$%h_Co`i-OhFxMFb(Mu^;&I zl`juk&1)nviBzRt^U$Zx{El6!r+3SPfidESyIho+PyB{{Z%n8wXZ`3NJl$!IS2zCg zQvmsBYr2Yg;#Y54+e@Yx`jqo}HWdE8SsiwpELio=*Zhdzdwr?WVvH8yba%~2&2=L^ z`OO7wEP5S=;M*bh#Z_1c)xpr+rqH3VHZhdj7ByLvUrl`yzo1e^r@GqgmCraXd z+;;lsKcDF0N+^a3GRV0@Lvuo8SeW0(zG^Cj>PDNA6M2Xg@9bIr}`eS&2SRyKk#d@b9S6QKC7>KN`XU)vT> z!oIfLp4b$&UlX&fxTU?~K5o$r4S6F^72?i-c(MM2uDmfPZn#pwf%aKWctoZr9K zzcD85B1ofZT+jsWBsQU)-lXOQ35vY66ekW8bzQ{KR18=Ut-e3y`tX(V_X>d^+6#aw zL4@{l?v93ug@ z_5tzd;wPtq|IN<~!186whffSpkP`KE8yW$ap#q3`hWvRE&DWa9_H=gm;hf+3NQUzX z)q|BnKomC`X{DH<=IBa5Uh|K|Il^f$CHpZ+mmK_CHTAXa2f82eBdrv<>6R>oQCk?a z!E$$*chQMb1l)Kbie9w1#!S7`GL@k(a!LB!86j-I-$8~oS)rNpy)R=Y!@~>LNV}ON z8LOTL+IyK`ePxm*)ToSf(w9y=zUulOCr|EWOG5$@?4kii`@yMmaefxcJ?5_Z5}XU6 z`^c0j9}16*AE6FTu4`a6okIBe-I<v(uE3u>+Ep(Pc z%g03f{9z|7HtW%7fiRzfilsSET862)a`QrnOL=qwCr+_ikZ!++2kqw*k!{Y8$?|E* zJP{!^{?Bt1W{P#si;WQ?`AX8(n$9Xt$USO0=851DsrTolmddOGqaGtgb#W;Q%3E(| zA1YYqVtLQ`DmBD<&vRz|9XhZp*UkSgJbQd367#Ub5`s>IP!^B2R5V;&dP znK)&CdH%mt!f%I{=9(^QD@UxMB}sEXvlx1{Pb&SgmXfhh$0k7Fl>Eas z*h5e@T-qF#7Q(+t$+i9od%-uc;HMwz88c`OBQ(9aDE!{kNEHWAg`GCNBdaINrZD#y z-_{89laBq6#s8%Z{c?LX3d;Bzi*w z4H4cdh=@IV_;0&w1tWlp=s6$D@R2j58;+Bz98WQ!i6CoZpK$)G-Fny|Gm z6hhm`2hvnTNGl%nFRzP5He|7LT76(y)f6|Zeq9KD^K5_iB>hEehUEvA9bN5~3l}Wk z&ko5n!s~FG7Xxkmz&!yE0Gy-RnwX;(MezF+VBjpnL>nCCDfC{muc7a8QYU($%7oh+ z@F1yJ=Ka+oDnDJVlY@7CnhybFnD|qA#8?mS6G5~`4c|cnUN4fl@AtIFo961r&dWXT z_l+JmFZ8QiRHfV>SgJNJ&5vEwHQygPL^ZE$t6VlM-ygY;H?LieUAEoc|AIblSw~a7 zLUfV;ISy8B`SE1@s!#aOZ+KM82BYfrke*>I%m{$N>Va-v?%l-7F)# zKZmLPIdE&YTkyKx$?HIbUiwTtgEC4%eT<;@mm>8a0Vj@tI%D?-iv!auJSMhBOdszr z%>W=@bV)9f0SPh^bBsc$1{81t0}#l$OPIsDU;u0WSFG+ZP63#;41~1)q}SE9jwLUMlQ&g2}pHXHz-fEScLaDSS0pxYZc3Df`$OCR2b&sgtWywK>? z)%@2h5BU7Vfq9*h*&q8Q95`SU=xiCdtrp}iAn_d@WNt~o{RQ{} z_pz7uCw#TwfIV*ARKI5P5VJc}x;@A`o?^9d+Rz zb(I)((-3v{cPA`2@6&iM3Lf-bcn1p3^EclZA<1aMk1(*o*YJ)CZ8#L(?BE6$2l7*Y zq1dJ7fI3qaVTHKhaI6Ct3gGS*?41(AG>g$J*U=my-obq4tU4~VgRTZr5CP;i78Jxr z8iQYCF1#4?5+imxNIN|@Mr1ceJJDV17`S$UhH(rWVA5A5jnmYLJ8+2`kBO@xao56) zGboDdAc~)i0hksUnq!DsUdKV_eNUtH9Wcz#_!4fq+$A*tCmH~~H~L7J|M}X`hndZ5 zH{N@jf-W-wpa!6WBjQ^F5<>?QBR?6!2N|QSkW?SSB#uG|1^VtLBo8K~ha_!4=u;Mx z?z2Kew<-Dy^|$6@kI$2h3*9x1Ks(W9V(T%Ne3YUSl*JhEhn+ACUDXM=%%{|N+%E$m zo`lR0VtEfwG>pE+)c&H>nGnp;-BgSsTzd<41upja#V^y77W|~?Ib7N%Ti^^=tw7nB zy-(g-*Koe8bm_*_(72e}EaaEwaqEk+2SxcpobgC7{f`a+fSGbAor$=%qT+|(8v(!IH1G~>JjK>`8Z^eS{ssEXOSo*WA|Y{_6U;N1XEaNxd!U9kcpy9WS^X8 zPY~o#nj^At_w4bl6KHo5L=>`r^yW}7;4l{FSZq=}qUKab%dHK_RS@z!-puW)$|aY{ z6|{b0$ww&#&jqXl(s)uj^YZlf^3a>&a(MFJ>E;Q9W=l#_i>XmQZPG&)u9V0Oor-BB zoAPCn^X%*N<IpH^q7u#V66lhJ}WMxxAWd@8zGoiNgLRNFhWs-GeD@!J8 zH;6J}Vq~kTe9NPJC%JsDsr+E6{HXXX!*RJVKgx;j*9(uYSIJ**n!esGef@Lu6+m7A z6s`d4RiJuSpf86}!z<`z%CVQ<$>K`3UsvELRMKu$5VIPSq*UITfthM5DfW%1$*brU zs$N)EF%4HdOQ}Mut76kL;<&8>5m$4Q8zHB{5H8gM&DG3=ARciLFBj;!gPu4pScVHM z0RRi-SL^eGWB`x>07QnXrUn95&U~sl0aoxdQ3^AAJ^`NT1hP#~DvQ@vLcnUcbtZ}s zwTfEaxmxWl3jPX!7qVBBS)4;(?~Da-4XdX^t^cS9@zksLCf6N%-r%LzK!b{C_;{OB zO;p0&*YJ@X0;c8!A19Ub(Z#W{B`B7XF*N#;15*?MG?@(3rG}U-9o1$XEWEC&TmW*bH#IIGAa&+T zkd9fe3tYUjI8!$q+DWz&y(8!v0_dU-r=x4>!im=D+VA*9F1f~t=;mMX2_FXMJ9ppY zb?}XJuhq&N-*$_S7>Mcjtkd_r2~E^p6Dey|L|2=j-pQ>GiNRaKGzw zx$E!W?DLth&=wi+zti^el6<*hu~#$@7H$ybHDD+*7(gMF5I)#TG%yb8Pu16nppeR> z7)o1t6=yp%usIl9I`lKIFZy7pX>)MAda&wF52Qb6<~6)tJKTb;@4GV8PN82zG1zTu z5NA6~(E}dx8p$IX38EODo*o&))`uSqQ%a4_is+V>j%o)XFjy$ME9fEY2VMHlqnUGu zr)-@gamTjUs5kG%w0>xJvAtSLHFfzhrm?9D#~nY>XM5c{w9qm#RSniR$GGu|MT(k9 z@5U(_-{yI}Qmhyg44fc3n3(uJPGZ3GgnoihS(HF|nAv>tmO}4-WrBQ^)7Pc z&m=*KDP7uBSJotND~W4BKc46-f-(ypQS>U8sTb^uU(81E55e@JW(fEMt*8#R=uAMC z0&eN_r0qCIEBL!4c224>tYb#afQbKoR$W3zCT*0{&SD5^M|g*p_EyiBeJ;vaTbS~d zW$S1G(FmwaLOa}P!F1lec9w~EemI;=`EWicu3ae=F;AM?Ex@QOZ?{lGzd-Ikvv@24 zkI*w~9Z|x4N?l0+Ia^F9)3Ib*oULAL1{VfUE@|AWB(+L-MMM{~>xCLDDc?PXQZBRe zEwQg=r>!nqMJ$)aE$p`}cAYI6Y!G#x!<9xh&76tuD2$ zuHd}ITwU!5SX~!g+b~$$`nEwxns_Tw#I{ zOo;ijN0~E&<)7aK)B?_AFbg3IBaAMvSr6B@ZZPhvGLyPIfJ4@o{3oV#`A@u2P*|+E zgz1<&pcraCBURoQ000^sSR`0h_Z_V7@tp*KV2WB-xW)U4!u1p5Eu$2+(R3vcdw>x` z4dli{$p`=8Eyy01t{#5O+N|ZfH4d5I1aaj3K4S&S%FGxkum4WS(Jj z{GhY{k?BCr2LHjj_Jf1U5@U^wmv6n%emzNy?vbIm8QymSj&=F|Zz7Lotep=EB8?D~ z0w{*x{u|Ht{;Lv3@_ezQ4a1`?@1vcz(Jw7WkG>o|>HTDP-?y@Rczr+sS4mcuJHOoknt9_b*vKi zyF%+X_V~ixqckd?H#F_T{clg=34cBJA9y5&m7<00aW1jEk$Y5x}S&PL|Dky~%+^iloBXaD)Zaw03aXGu zcxbLOb@3=l#8bdYW-5U|vt1&Y*kx&kC9_wvD3XP!*SKdYuOVF_Lhj=pQ)G((EvWJL zdj<8?w$Rq#DO1IG-s$2^2B$JTdw%3BU`v4&)!6405z;+I-W|pqM7S=!mcy||Kp>5f z(n!PG*}me6_%1n1o61U>S{FXns#85D%a>vHi>@_RX2Hi)8g`F4ZPZb&A5lUQnHV}X zu_Pmd-RnDg+x)6M*j9)(BL?U^TNw@objF#-rF}?mYR(<=zK&x%I$5mFI_=^^+IQun z8C8vba(K^*cx)cn34ZGGA0)W?ttTk>9^w7x>Xi9+y2J5z*gbh#;+Wu?myxk=^z z2!Gz!1*-wera{JvAJqxgg4TZ5=rW))d|dln*BC!&$9xo+{)sXFGJ}IN87aT5o*{V_ z*|zKcEDA03$1@KG>8o|#$JSeuh%aUzQDXwg-xnIk9ywnr*_;>h6RJ_8nyo>=xDK74 zGAHKVe>|l}$xqxSMW@q#7buwT^C3BUE7_?@r$EYWXmQKlqiTvV#o5(0DF%xy#8P|o zHPfRwbrp;v#UH+Ms(D4<1J)qO7`Qm#32tMQT4^ccY<`+IS#h{$F|4>CGjypKuIhlf zUtFznUR+#tlr+lN+&5$`t9{R+96j=}mQMRw5o9yBKpxXh@C`>yo=Vu=Z&}n8*Zsr# zby!$u!$zRZQRBLG^DzEW_I`Q&M*Qtj%kG~_#pbgy@?Q> z+c-3UIS-E7UE{MWx{r?(eHo5r6?#6OcWb$SGR)P_ zb~?g4Z_CqDyHa{OCh`m0VO$(-w3_1p)9!5Yd3Dg)lw8Il=Cm5t=!O8Zv>o3#r$L#^ zC{y=qCjz}7oU`%w3CgaE#``e-C55l-bxZa^_a!fs@bT+cI9AJQT{-;hK74Z>KB!-N zlc9Vy75LPfcO{f()%9oaem~wut z{WL;nUy#5HtO$5&nt}SZ@YNG*&OmOjtWjWa7uC&ikT`ZWZjf9LE!pp2Ii+m;gn=Fg zq2D2D;n{=*a=k3NzeBZ0vWe>ldO19PhZ$k#ko3#-aVP%{w^Yg@n;+=oZ~7hK5S~M^ zE!Qu!^gGghB!}uU_*G0mSQHdHml{oe;1$^kJXk50_Q~LYjL^v!c=+FfmxAs|bm9oI z;59g?;&FnA$;8fMl9eC&uMzLKits$PhluymNqhq`;_Ws#Y>13_cVOpp1<8-RCp%3X zP|D{{7#uMdI!&4g&*v?WAGOv!P5zIFx5sJ9I(C6Tzx~S_>ZWT!7|My3 z(l5wH&PJeMI`lpQ0R;`i>}?3#(Zib4r0`t;s3tCRJxkr#{+V)eM@lde@v!oK5N~JD81O4F}R%IAk!O zO=fGKKc%;*&D6xS-;RqmeFbunEaBNbs%erlg$7g)Br9f51^}o?-)qj^U)t2A;vJhjBa;aI>#j+V^HY>@H5fyN!rN0 zGb)T#T@qVfOmhW^Qmmf^EVz@J!7%=Cp%7?mcXE0!)9;u7&zG*m#8aZeKifXN+aU2V zIecvM=%Z=1)z2bRNY(q8)aN05i|#7xD0tx?%|-=L&_&$GC#MLvdR+fEN4yP0B?LOa zfpBL6tqG|5St&PJ($id=-_{H-lW}WMGr~T&VhsC#m~RO@*T+VD#?Wo1wdx%^uYCGB z*zh)aaA+FYT}wlZD%5 z*0Ec;(tpbSPFlmmvGi1w9!Elbt=_=QU>4cw05UGHJbtYFnn8f#haTVQ7>oDs;N{$z z9cEt?5i=;h$oVAAQ$c`&x8tOk#0K4qMt@1=r*SbYg^}ggDmYN5@7$eRtiKuye>Q(h zVolx=;cFU&A2I)lBooD2*afPkS{5p%?eSILC>4}DtJd@HA#HqZ>T7xxVU+v4KjUjooOP|la1ZYoWn zU{wGp)qD^^R-D;j;13_PU`LsCXB-k=d;woVZC_${Uy?+mAIg_v!I$dFmzo4dD*&U@ zhB3Iqm=a+u4KTI^7{?Wii^PvxK(UTPZ#f?hGs;7%RP~B*z@4DACa@XW?H7HZix0@WMk^t3e-nUst!tLpN@p5!owzUOsxG6z@X0;w>cdM6)u9T{9dW6# zW8h1*q}>4!k5TeKF1Bz7Xb7s>^TP9Lz_ z!3(LV3fW#X+fonB;Eq2GF*Xy-5JU~{-$}b5eZ9;S0d359aZW1(|9pdyc}MzLC?^^9 zM)OG~ki0(AB0m#%$N(wkN_m|{tnd~o=CZ8KqWE_!S2B#z;s46YwS-V(_V{mBE)NST z-Q2sgWVvKD*{0m<+*}nhRq1s>^-wis-Mn+>Jnbe`!N$Cknn?I|-UT@S9drJXR+5=@ z{()3JX->XQli1Vk{L`NNk1Peh!TB6Hc`sgrxF!m`Z;%46LYPpYze1sbKPWi4Ftn*K ze5o)bIoF}MfYS`b)lm?uTbP(!l)P6Ev{#tER0xzVNHTfHuU5>j2I4a+E^aF37njSp zDXt(Z2@6%pCVQVK4iKUakZ{HjfdT?0RNR;H>pU?FyT}v91{hJlg zTgmV&hDt{jO2@7JCzrs}EVxeAW%CLM^j@+cdjC?CPpX}|1+w`#6djZk9;IWr;HWN= zWvvqHcs1)KW`Sia5(?WwXNs-nwt;^}pQ=*e<>I`Ne# z-!<`Zkyooa09h;m_;J-v{#4?Mj*_=3!X96W zPhTqEswEZG1`yWiD=M3LieB&~%R1CKOM%%SdHX$ektPKt%);*!>uc!hS;Fe|hw6KC z>(MsqyTJ{xTQxVmhH|L}87D+T@UTKCD_?|-YB+gg(OE;Rr&^3><4SB}a)~lh%(ZaV zm}#So6muPbKl~RfS4z{fVieAwpsz8FmH%nwx@}^xZZ73%gc&tunl}3LyzRq^aBb#A z2E7}5Lc_3H_oZ59Se55ITPI>$Idi~Eit+=(ykq1%$gFpNPbdt)>&j_CKEOKe2fBN}!+-xua(O-+FELDIG1~4qOqX zs}y7~yfd_>r4zAkVd8`{R|aYJWug z25UF3tsEJ}3$)bkhTN`={qB&OZh27q3$`vEww@8KHpbE(zEVEmL64tQ&o7f6)bMT% zFD2HNHXUq5@s-wsg&v{qUV~H_tx`#~XMJXDO32{%T}ltHWS@<#j72HmEjh2FNPp>B z3j=mPPfWjuzWlp8ZuJ%(D8)bwVZLy8KW%AyaEq*qEw2|vpEny%(A@ysx&C=+pST}5 zF;yYPD>M$9hv9@kyX-0Hs{2XaBA3Fd3@^hN%3+$RLQ_7LRoD3wZQ^ZS+3u>6h?H#hQr(rJ>Dz?2A{g zdjV7F&Y&0FQ~EJeENS)MD5evUeO-3NQLpLhvq_$&LH(*HsN^v%Vx*C_d4u~S@Q29JjU4+Yk zl~J7~XYRsLKbF0Q31+eqOC5~EO3oEsegY;}3&o|TCcp$LR{&4=P?W?$Xk5!R2FrD$ zOXaPa73|A(tIO48%J|1%3F>#KaIoz9@__QPEEMyE2&_ttg3AI@fiLqwmS0f=7btg8y$l6b_KR?B( zHeQKsNEvR(cyGw1Zz!~FD6MU%{Mk?&Q!c@>Qz6;Z&V_21LlrDHC3!bd^*8nHrFF`o zcfz>FYXYht`MSLVEU2VPgttyhHoGUbjCi-5A4z=>+xpP5we7L3t2JcuImr8u6;vyTe}xKvfyn`s<&Tp|BDpkEs~gK{zFXF|4(A7VCbW1 z;P~3~KL!oV9tI8mElv9un*Q}-=!Kcisdqs1f1*>5(5$~|j6adF8PKRazb^#= zF@?eLrI8QG+RC`(d}OlrAAp*gRT`gNn~>9xnD?-C5L?}vUs8t@WRz63$JcgdmHmaO zwLSkxG0GYSt6PQ|+DA&dhnu^`n!2Z&$LE?S=IeHMAEX$_O@n{I)I}sr9bEi|)M1Ry zt`9A)&o2E$^3?w0v>U9~K-E9vY$p_Ya0^p)0@>6N8feI~IUGHlXA1hWHrc&a!{PEJ{AHw!RwRBj z)fdn8Yh1s#W$6!AnN>M+n3Q|EMHuFITmZ(ZlbpWgW@La3N6Z`wCsk=QC`5H_iZnxr zGD2bTiiwpfjs|Ad>dbYeI_6yC#YAqF1ub6Dh_x^iqhtOY=2%5*Kowp{l` zr*c<>Ve=2Hv$Y8_efPgtpQj8U(OA$Aq!1$^emmmKLN3bJqK14O_+g;568fviUj8}UeDx|3gW)O1j{f7E>3$NH<~Y_9nb^~xS#({{78|EnGFp-Gwu z1z^MlK+&oUDAu#h>H(p?%#`Xzd29O{(QEw3>$ns1>yiVZG$9_Omn6aVWRQcOqO%VV zKEg$;%iF>=^gvAgp37Ep1MtF2Atkzmc%7qCPwbq1a7-qp2(%l#kWMUFW$O{{akleW zZHv}IR$aHl^Le8n_KOA61iOnx%Yw3tCENPLi)Dv?_RAIL|CiHlK^(|ww*>ne2&|dskIUA3IB`CX=C5D2Ycg9{@*NKxfwDtQtuOvvqLT zdnrPDIP8I#GK>HCq6G!9oH@KqC+WgAq?T60=tUM~J3!RpNMc$UChY-0p<^Ibf(-ER zK*hl<;z(kO7vaw$)m;S*$cH?C>Ao?^n~fV_MeQK#ot?~848T_fSE=?)!*C6cfiyiz z8c}!Zbc{NKilNzvS9)+ddUnzwCF?y4L8A^E61bmRqN75Qz8Nb$;qc3flelC|dJup9 zqrLA{GEEz1BP4_)e&;6%0l;s4eL+eT%rPcygcCeCeIw>eyIzE$l%-91m{ zpYFx$M=TQ>_%+Hs!rxGyU#mSbsER^&#+~Kbn+PqoA`@1Faf#?o&>m37zKl`h&aUt~ zfuH4ZMHDGnC`>0Wo#hLR7OA)mO{d?S6^K8CXccC%$<7Pql#4YIhGz1G&WqF{inR(9 zkgluqVr|4|@tgXg*>Vr0{R*cu-y5DbevdK__wk?3lGKU6`E3w5DhenQwZ)Ni^mlzvwg?u zSumnuT^Q<+NErAcDwEa(V|qFq&*V)&$VW6Ho9OQvX)N=CdtN#S6;koy@ z*RJrw&B(3hRq?M>w5qROznf>RLZjNm&Oh+s&=~<#i9E@d(|tdM8XfM&r0NYAB6_I2 zW)q2MJdr^}*$8W6Y#aB^n_Y(IVBHbZ)Xi%54#ZWC2i|Rik!xhTJ}|E`0A#U zYDbUxq3%)XNd1)hR%0xkiGm|{u#?5lhTaSYfM9^13O{R%llVzMLWfo<#0@i{eLx_8 zAmC57ZUK%-XE6#CKn%Z`#KL)_y@QTgYhX#$AnZsfVL{r)>8%_}_d=;dI? znacr-UYUTDyXi+*4HT_*2c8NoZ0q7+T3pAWl<|92>|ZyF$dvb&l2S$3yW1GqJz~pD z=sXh?75;Sr8KMok>_^z0y1l$3&(M_r-eCTRQ2^yiORfL8VuG{E69I^vvPJ>~tKvD9 zxQHr`$YXadya698NnczhU*%aY0X1JNDCjcCMeo=bl>qi^fS(E-MjPxKb%7>4AtelO zQ>*5Bo(SaGLBK4Xdm zZ`=d469aS`0{$h%C}cF~v)I551k#zCy5pEPNVo-B+BAsUU73Fv5dWwh=%g*?QW)sw z9te#O9IpuS5(tE$2A_9hqvV`F>!Ytj~ zg!v&U10h&f?+_@VS(d^ODHnSS{XfQ`1=_+mIVdItD8C44zq*S+Hc-%^0IH7A`UNp= z69~M}ubo5~bZXO^7(UbxKC%$5lVdja-=^KlK@ls7!fRI%|20G_@TR;WG868dI}Eh35V{EzV=EL&2Z+i93Z)UJM-qh7 z2*3n~a7>`^kO-;czGrkye2<@y2t@!C1x^<&Mci@yqTew9T_xrlTFmw%_(%s$S5Yi3OA|aA0A|RpCG33z0P(ycjH`0Jw z(Dz;IUF$k)Uu*Ak&OZCUcz*Zu{oMCfR&2Qn31xO?X6R;eHX{etWV`Ih4mYYDR{B8X z?T+014(s9=?Cuv|A3Tu{aM2Ad1oRGyG2Hi&Io2$J@Ge~Rn^s)=d=8bGHLWNJ+Y>9` zi^#7tytDSaVFIJOO@45VQ0zfJ>&);kCgGq$oUYs1EPQBDE$P*AE=uiuih%qK)jWm( zN$PXf8w}Dc9o%ega!ghQkxvVFwPk^n0eHJ0dA>lD!JkE{&{6_ZK$y&y*ZiM5256rM zBmsmWlr7Y*FmWEGFE0Y*4k*FJM*JcsyF9u9#oio+HZd}`6)a}w#XpjZ1saMk?Q!l` zNZX&Q{LU|NkCA@3QsjD$M?hEl*`Wj^Ug}s;atBoE$1lAt$Le^F=Sf%=LMZ+49Pb6H z%&D>LiY;znyX<2@snA?$SX5c+id3vyv6-k}mQ}gST)8V@1&X0!&7quHg$=puT^dti zBvJaff+dBp@`-9`6RNT$M#k;DypvG4BIb70Im@&2N@I>nAGfj*d6?}{NzHl1gtnx8 zOl9qU`7lE@2^IIeeC1+H^~0_5NGnX``vA$+U6!}~K|vj~Q~1KF zI%v0!dO~n_yyjO${bf=xRcHMt{)KXw2 z(8Q5Z;I_zW9s$>=DX`jpWuz5o8E0>z6ZdnjWWH6|l98#V>fUtzq=kd4b#tJF$GT>18Dpud-DkBt?&;BUs;Y&_WDOe2!aoomB7 zXuiGB&U4tz)^elBUHsOb`aGh;oRXx5NXnnF(+HcS$z9Ssu+soIAOboDfE2@>;{in% z-C*a?zeq8rFS=$JyXO?T7p%L>d_CjF3q7qB9~zb6SxOZU5U;y;8PgbHW5cb`-BD3J zflrD)1S-XGvh<3!-(j^uI&13HiGycitGLLVC?w8^Ko{;dC(6~l{z?)EJ>vE7)hMF; zaO}<^kOaaoT|@Csodoz2i{#LfCaxch?yn+%A}J-LLHa0e$VMQM7zZT31SAd0Uy;Tl zrBouc!{8VrK!6cLzH3mt3L@z-sK7L&5;quAh;0D^Zw!JhX27azLwajqi#~8rofvB{ zj=ZP8nCRdNXB>|m`0jJC9r4KTq+zA5VKeB6OZJGH;0W9iqLDphIfL!4_{y7jL{z^Ipa<<(Nw z=(D+rTPw17Z~Hn$d)@?20xQJvuF1)@$?40<8K$W@#i<3GsW;E3ma?Z-x~577A#0be zQy>>ArUqIF)^t9&C@vKG*+w9FWg65vofkUoS~0zsEfBQZeJm)1o%C9U^YwXBd0*e_ zj!o}V!I@f$BDSphPP>^la7D-gH*q{K{#5P2X(0JSflU55oENiYUKaRs)4X53PjuP- z;Tt^YnS z1L&7ls7`1^WK^_HI6OKcCN?Zo9akYNF(Ew>KvUVddBB7`TO+lww5+_M62-*%hkgl> z|Dj*mL=v674Y~vQ5+sSbs8OBqR{#Ku8K0h*o6njaSO)0VyX704@Bi8bK1vgAfBXI; zXblm05FZ;9MEA!oa79ORMZmQ5^L;hv2|oWCt!KV!5Uw-VbItmK!Dxzo%eB!Y7InK$ zZr^Xu>^b`r(dZ`>t_`0C0>2fwI_@-lz7_VPW!AfVwnPajH_^ZPW*fm?81aMe?mvX^ z+PBBtDi$j(YTu8KHw(OtvmK0iNJz1?)acw_a5u{*<<4yn%+`30PHWA(Qk@^WX&pYb z?|NSDRFLSl)olz$QwrElw$*RFLU8Eh>b5t0nm|gpzn^Sx{PG&D8q2KL(X=yPW>RT8 z)zSR*ZJp!4(XX%Xr#f5z3gPv;+V;0bQ~pH=uixGAM+pC6y1Vn_=d}>tpr`BXaQj*a z-_w0@vbQyn2MFPRUz{HPJN;S@ZaXtYIMIC@q6{IH-bQm%dx&bgk%H{lK%}x|8<9-D zIQijsUc4D1r?vG{qr6d4wizQ{4;>WM?UHr?ap8Jy#>jpiT^HAr%-2lhhl8yWsb>H; z9raP!7A9HufOd;TwyqCMD%vmYfD;5Y?2p&;-TCzV<}^Auf^ZUD6nB&P$!6xgmYoLy zHxvBx!5%#&4{{y@MtDDtbQiXaKwSQ9w2f4LI2IQJ8WIx@2;mD)j-tT@Ai7|1F5*E& zd4?`s#{dg;Rb82A7C^s}a~L{YC=GG}`o-iMqe@ye@c%CTYLO0sP}~&P{@JtkIgqF1 z5?AmciW-XkgaY#@3MHwt6VwerITRe@gVjCiF+-f^mixm@wALFD^uB@(^{V0D`k)-8 zOdb_FAgmz@7%taSL;knV^F$**PwY-Ao_HL-{^k^>ihYyz9qEkbAWs~LD*bm!IW3JF zl9aoO51VC;ovUpZ&7YApzxgldmrQ5Gk|7A|sg7AN3Ho{S5IHp+qSZCxn<$LvHkXvF zz0MFTh%C>p7>-L#$M$hEgMLmK0%r_uzZauB6T+{56C93}e(y@oDN@l; z+SMBlX+clzZ&kM_R7o`e8;0G)I&^UQ(K}&cs0eQ69 zBO3U;_6|3n{4hi#a5Y$Y?rox{IU9J{m4PsyuSai^Zi4gXk>v z-$L)H5S(HY6o(ejTJc6o+-GwLpbDeqUiXt*us8SHR%NBBAh_9;PaZK!cR1At;YNlK zXD$u!s6UBOy$qu+rc>h=uhG~zOro8g65yPDyy@%UK4mS-KOOi{|5Hz7d z9IZ)2z!5Md2UM3Ko9b@@GJ3+z2$9wTD2A zi$Q6#^iVQsjI(Ih7DkaPa~LtRds9V#csN6~+;XgoRT&!}20V)QqPhgd)oG`;)i;tx zZiSl`GNtA51g2tPt*L_O`wG}Ccjs>PEeJ@yaMjgt6~Ri?1f4qEHwa=dC1CF_r3Jgu zit!EH5|Tpb;eha6k@aLsi^(@J=g0`AJyDeh&1yE?yT(0)4K)ua9^5=dVh6B}BucYY zTRT;1m(KCEIcU}tWWOi(tqYU#_fB%%6c~t6J$Ivc)ig{T_F9ua&M*PFwZu?9Vmy>0d4{O=R;d2pj1^QcFIA_%N2jD>W9*T*^QI$9RBjmVZf@uBM9>=8R4C$~^e zh|>MYj@g7Th&Ci+QRcWH*CE(1TqI2vUvmLUShEuG%DPD>3qd?|%RG*gbt8PE7z3Tb`duD;q!(Yy&*F~#| za8(U@H5s$s7^^_JXr*6K){6_>(bE5>A}xOur1UV~kSKOR1MJC8Z{{WlU%6GKlw4`> zE}Xsjyepy07>ls3*!-f@BzV=Q_RF|{ojGiYhrPvG1JlIq^mO!I0vAow;cYED6Il(X zp^Qd6z3zt@r>pCvCmHrkU%av|Xk?UHQO~-!OZqZdX!$U+;40Uaj#__TDy%k;`qe>(i0!94r{oW`?Lu%R z`@n$@Er;chp@=AT}C+}qAKZYY@O3k{?jBkilh_?XA+Oql5^WOCJGNseV=b?9eB>{a(kLGv0|{mQ`@5zI7C643Dvs?;_CWY_!WZsQ zm_8w*e->+@ur)>Nhf9>{yN!frwQpfK{4l@wCxaE3UOd}x0~DPb?yRbhIVj@h-IG+WwaDg&Dc!rJD(znE+IYO}Fg)$v*MY7|kMQfy~?cHwZPn<^f#eNXp%8QpW7Veowa zQLp2>)*pwxEHCV{VMqNun9*RhhsPY%8aELk#7pviC%u&#vUb4{bbTA=t9f^C76j1_ zfKpF_4i4^JIS21J@ZuP<{El; zqlIC?*wN4a+zYm8G#`hG%Z8 zrmQevh22Pgp-&ef!3(jU4L4pA0sz=*a)cF9Xy}*uU0&gPbdev$Bk%J@7C()2(WF@^ zja+kxe6%g(IU4cALeSG9${HDYCp2nFJnH#URDh;&kc-eu+2}>%=txLJpiAmNi3qPGks zqsobhn3zVEn3f@J6@(GBqly$FYXtb3q4m(racH|ArSmAN(0n7&0CY-hXg;?)WWi0hw!Gndy;}( zmXxzim*a&E9tFw3o*vI~sI&*&E(hl1@;4i>4_dKLm-P4dQ;l{~hUSuOC2!6TrheGq zxVxNM%7&#N$|?`VTI5L&J56?5PJeWk?n$5FML=yOm+@sF-EbE8mP3^1X9T*k`1sSk zJj-|`jtsX%MiC$@?2+&@40DJjUF4WiJiTP>GF7r%=J0@#MO0>|xUOyp#LX)+`%D1s zYFwBpkUK_|?~m#$$SfE`b#9{S-~wT1s75*F#CF=GGdv6Dtk&fl?d7!P{$wbv?A{&z zW=m9$fA%VQwl8_6n*(anmA~1aOrtJ)KJ&)3C0%7^P8K*PYbWPJeU7(L&Rf1*R72JV zJQrb{H4D%Aw#=JBkhkB?=C@20Hj*?R<2bo=J9yhf9MlnxC zv9()~rE)3IqQBZNG_0VyH(tu;P<(g4_$PPSi;jHD6{;+)(!Dz3=v~(Ej>41mvRP<3 zv6o1!d}#=O0dkxrg`e8OxjgW^{Hnj$CciY-t>T=#!srPkp@QnoXvNV+sfBXs6zi=@ z?aH4U6}4`Lqfib5@v5#0mNNN5+~z0`i>k)`5(}eZ7=H!+hQVY9n`9sDE5qu$n^h|T z%*!j)x(yhM^>IF9=^9yzs?Q8HJAWtSgiMX+HN*qe|MwH}PI>1FCtZZBdYQ!0IadY) zU!zOien%os7Iy-*V(TeY`GLs8W&d+K=tl3AGIqeBx87tZ&|FUBW~R_U;a(yX%O;{gc3bC#`DTN< zmY}#!BdD)25#K|e5!6T2S^pLP#5yR@;W4I z2`-Tk$*P|hR{d*3KXqwKT8!OeH6zC1XDxoTkO z$-u_hfaoLz1KINda>f37!@*v16vgxZH0yi_V49dem`1_KTlo*BQM0_pG&=W!|JCq{iy2C1;NADD6$_l^T-2Dm$F?VIi#1V)^*4WqL_jHmPUB7kPvcE195NBv`q zgOe-3h;wpob$;o?bG6^cN8s3V@T?xcG!b1YJy0YFYw3DiZ}y&xudT%}+$4io>!C$}94b zLDAtg>hQ+s#>UDtbX!i#-*DexYiCl&$g81=va!PH)X9mNg{rxs#pU+5K)L5nx9?B6 z=TEoq2T<-gI6V5GrKPQ@seO5JbqvBLWct(X!>8o88LeYed9LkUWszT)HyBGN;Rba3 z3ST9%cJ4IRDYGOa=2Dkj5M?1GFL@ouv$Yyarm|$eW^%eVl)ld6QI-b5s6Z3hnkoF( zn8qaZraw29_9Bl4ms$)BSHZ{fx3zYIF*n>L+{P-no%!XAVeTOucQIpsF-_;k$%10S z|cip~Bos3-MbOcScf${bR8fA@9P<(uS$i}pX5 zhDhfCZ!8ANW|mzvC8`~?h*K>B}0_Ju}@d@+|LOFu_P3(xrre z+4|9o^3PeG`Wb0{YD2DHa)wFnEExIy+WF$lf8*0!W)O{=%U!6Jn$fK*NdVIz)cJRc zl9}ChiodR&Q?;CJ|1^V&Vv;=Qi^l~j+C^Yl93QK0hlIn1UORaBC*+tsO#XyZ^5qDS-(#`|ulPVyP&&CHpcY&)e2v_my`p7FbVE#!^$`a@1MpLX%=Q{Joa*MwQvb$x`krKIf?Rg}l) z+r4`xonPw;g#$G&7wkd_dOsarsPvQF>yjCxOuX1Ct*F?MOPdK!yE?z5utLt78~DVLXVO-7|tknbOg14ava15^7@M zzg5EeVBiJR9t>ga18(=#2sgJ9LzwP=(~qEr5he?~f0_>gBcef?pzxHck6gV;W4A1l zF_9Jo!De7lIg&`P)Z+Uie6cFpAM)$Gww^da>U z&Vz*9^rFlvZ~sipVi>CO0E$B z^m|Z2qAZ+z={tyn)gx-<;{7SuSL;YG>&5L+8EZ~b_1`(eK^s)-P1M5S!0CS+g(9

~Y&V&KChCQ(8H|6J}Xdfa(h@#0*BH5}wE|ai-1WbP6p9&zaVRSzfpX7O!n)wYM^ByUBtj9|Z$q@LA7!6RI;X(Y zUcY$o<0&SaK>`DPJ;gRa@@Q`arVua%xAiV$d9n6I9W}dl2>37a!(J$%+4Z@}OK+0w zGHHY_s7rrRqTDy54b&v4yi%>)g1B2xGW2hTh{iG7l*;bQ58S2;Hp4Xxr^5+c8cvw6 zkHx5Xu(-pP0HTg-T*dxUF^hMu#1~mb^4+78q5Sp|3`|iM($Im=vcdeU-6V(0J2q=g zhol*Ytzdzz_-d@DInNCtGBo{o<_T>>Jo@`F z)|Z=fuiHjsruP#9FSl69+DA3?50bMkKk^#1kDE^)q<3C^5>0HMbk;vand28p8{}vk zpq{3mrGB|tYoQ;)>>Vam0lwv9Ix8i8gcN?aee2oz{En0({QG zWBIYu4cme~^A8SWZ>`QFWo3$UY+a5|RtK9G-Yk=TfBKW=mJP@OId=2shl>69eNsP6 zH(ASnH2o-h8R?fgsYMgz$1V-^9PpSdTsp z3>O?EBS+uCnz0BnXLc!z^stEBZ`5{7Gb2`svUZ9(a)?x*d}cl1{*YG~fHm4Px{GRl z@9cG>=%UxfqZLy079o0*CpQq=y2%z|3A~c!`+B;~T$g?D=p~`dr65oC2SxZnrDcNJ zWujF}F*T<#b#$=}vawATu`PbFwRC}n$e7N}kghWB%G21#b74KaaSjx5BhlQW$T<6k zxXCiEX(ayGuQ(l*xL(ot1q@{+C8F)J zgs)3HKj{*0i^piEB^+sTewQWM27G@mfCLcFb~_P95f3-y+0#T=dL@9z;t4Ggn}%`o zNCcTbhgh5F+-M^84o4?4iLu-Rtd+!~#X-xL#3q-l=n(VPE*Tr1Y%+kr-$|DDO8SBH zU_X<)nWEuypUto=#Y8jWg&C710kI69g8gWOkQ|#`S%jumD?=XEZm2G8xgkAx|Kx-$#F@`i$*@v!tm3&Br|K>3YUg|NrF@=XVxAd`}fk{ zID#Za*>OZg1o=|GdAMNCP*-PKf%msoz5o5%MXL1620XIjZ;{?}P&Kmlo*^O>Fa6K{?1 zHz7AHa$jybPbDGWiDE1weIo>-G}H`bwfaJ;&H|o(EHv@vd-+-7#{x;vo5HE2!mDy~ zHAiex5D2o4W!6a04J|gYDmD)wO!q3%U}9mz5b9D~kk|r|o+2pdndSRHUAe zTOe@PN@dS^WphBKT2f`_N+sHjw|gAB2!&sYf(Uw&2q7TV71Xuk*uCSG!mVWfR#Z=| zO6`lP0lP%Cc3;6OE5JuX7OG7ZE|2W?EQ42+#O{{xmlm746~A!9uYFc#?N&?gSNZ~6 z;y?(xPiPJeDRCPw>E)_DlrQSQE4s4MHPS4C#qeo#&}fa5=n%>hRMs7y7l`c^517)qnhqu%-#TE#zHUOGGV8kh|&a@l`a}#j7=&EO}HEh z!;#i%7Yt0Np<1g9+=ESemGtVBraBi^MwLzVKFwKT&89@wR;vs<7R}|y%`yGWYrHKe z^_JWX^_sdcw=6mvfdrSYHjiWJY$jSBGFtg`wltwz1HaOHeYO0L=OX{kAr!AU#PzL+ z*4=;HifF$?m^_F8^iu!K2PfS30nSCP#Zun?gb;4&MSr^kFJcRUixKwGYecmYd|CwtQd_%oTfhHqq&7A`Z2;z}?eE*W*Yc^4Kd-+2IQX=8 zb&W0#&-V}h4PE^IFqZlc90I6OB*CLHknq&3?40Z%9b`c`Dz~IGCp{>-C>ow_UfWRC z)STFGT@dc-?x}6*Z|)uH8+esFJTy9)H9j#FOFJ9?`Z`7dx3spluy|*=vh{I%?fts- z=BIDpyS{vQXZ7RgyVdT#_2Kd5@1v9Lk7ta2Bz8S7AOMG0GSG>~vTSh4)J)1BjKNIRCQ9H2--p;wMo^{=A^jRlU%w=0G5&bgSTTna z_uWKm?T6mLpHA?7K}Xo6}Qw?uNc6xB|)iITuMtilX`5VjcGd zL@~4-`G-UFyWN}a=?<(EU7Y1L3XMEEx;_{AY0~MH`0!m}#NChk&cIlT+hW>fVS!Ciou?A^ZJ7KM31mFH2AK4~O8N zkH^6(qY1{r`Q-wPr9QV=V-S@%d)CQ@0EdX^JT6&DF?mq_DgCX_7VI%8)z~NG{q%NA z8H48p!Po{}_W=$uaz-m_sklER=k>Y#ORh&T^tOyXRX;G6qKTm<;NEkB5IQhibBLNE zvJh%@fI}cVI9OgtwxwT>rFLVVt;64zm6esal|P;FuK+j%ja6})#R$M5JPY1fyQgge zV<}60vt_3~8h63uQ1S{+keFxC3rB(c|DfmEv-5j7i|6Z?|P}jDcLXAda09dhk#y6=x7EQOC8N> z@>Czq>B@X>dJ-z>Ilx<^NOFfpK(ua6f_!$SFU)L0Dtf{66-A2)xl^}~Sb;yuujNN1 z$vDdeeeu34R$C*!tM_`HpIL{`+#LU)4KI-n2R#}*Sq(4c!k2+HWe%^$voy1j!$wtC z-k%sIwMPY*Gryt6EiTO7cFCym5AW49&DdcnxJr|?NL>%c=Ca$@*lggCGWg#5#?eCOClah~a*#geMC%31)#+zX^JRh+%2;= zXt9fUIs*+k@XII7qDUf}1SzS;!HJcE(>+`^@N{+m*Y#5W!*dZq0@5dRW7<~OQM?63 zTr$hCH$1Q~gk*sEjCC*ThUYJ4BOf$AvX&z-W}kz*?W)I_D`w z^yn~)-q~`(+QHGoq!aw}N3_h4(9fXcSWe*PGLu%lTQg75R%mep-*hyGLz{ zbN(z=V02I)RBp}m6Kq61Jk3c~4Zp4GtobBZoSZCp;Kwi7#KbGMqQORWEf$b*62C~& z{5KMvv*i(F&4ZGRHLw&`u!-iIpW2d6TLxHmx|f#lGG&sF$pKqMMHNrV_4xV0<$auN zTGS=hm}pQ6*ly~kuWDuW{cVAsj>Q_4WJXg2D4ugK%W1CusoM>ZwSWb2Tg|b08bp(O z2c@C=gOc&(;(e}m@+78nBO>j#SZU&cw-)~^#Q}j%M&gYY*|vW4BfC|$wLV>7)lER}X-}cyoo4bBQac#ZV&k@v34?5pG z0-n=I8!6lPxI5WmG^#pc@Ag1(SfU^@&r?lhX0N2g%L>lQ2V;sO$i%Ni_XVHBun154 z;x~r!1)S-b_NB}+>Z?9s6~?jCSYWk*=Sc)ClvxA7(ODbBB23enV~^KVDD*u_0%7@j z_C4u&`F5XEH)ixhiy!9R8XHG!TFzQEmAf(TxwK4vhfGg4mB>u(=m(z9qlHQES)see zKtWiOQ(p}R4W+IY98Q8qFBtwU2sblJ0R>_AHzXR8Rl+_aXtzb)(&D;X2%FkJ1>r)g z*J_4QjitYLHa&PFwPx^Cq~hxz!R#ubWk=hlrDSed7i-%+zOeC}AHL4=(lyr4@^yR* z@PUIva?M%Cwh$aj#dR!hbV?^s5OzMf_<)t++fQK2M0&=!ZWn23H=L6$gjn}q<-i(F z^M11Jy0%o%AUi^^w~u`1xn*&Oua{iKG@c>z zh5N6i=)9T8Zh(k+vJ;LtESwbfni6)^eLx=*z; zA*-XvMb}S1uez_>f)6lM-uc#}(4|*~qOw^1+y|jKup4v1=BNcGsa;Hj6Wdbm%fc$L z?meJ5FyHY~aj?33*Nmqpz96&tqs(jn6SbbhZE4avp~t%t3F?PvgPYs8YR_FwdJfid zT|UzTZ3~6m;})`;9_nGIZk4k+8PnZ+1PK=#Tj$47JTJbjmQ4;bV$Qw@D;>GUU%toO zO(-q>eboBeedp=Dr3&V537p-_pIIN?yuWqp_?gJn<6lpH?I!k?&x>F_VHkcLEo_m! zM11-UgrP2+u}Ig0F4!R|c36yd!75Nc;-z5H(_rX-M=!M``8MPFT;#>)YrWJH?l7$d zHA%lPS%5>x|MOe~b}Bh`Y(GU2?z?rDXU0L@MT)8(^zy_}hc}#(92*A>(WZ;gofpBe z!wD$re)FL|4FB-TNAsm3jEJY`rMkDCpJ4r#wni7xhz@?wUkuJbYN`kpQG{;Xo zk1i(jln|{M!zmF{CM!|V79%zfpa^jQMF>g6HnoWZD1t8~wu3jOWGS}!G`25V!civf zY!2(UecU%Ex$$U$QX~|$6o)>DgOJD1`T4#r6JL;pzCp&PH^g7f#J|VK@U6=xXmBKa zjuwN5CG7C>d>SSDx|EP{kZ|0WaL~qcq)E2Ftwb&cQh*xXOa```pks3cZ5qwlHtDY= z*|7CQyk&NBF$H_- zmo`aQIveinRFCn*^f^P*>L}CH_>%90;|SPcxxVqzWKX}}4jwy{6!TAf)E*))O8W3D z9W0UIT`uBlDIL(B@q9T0I1~w{M~2EF!}*Z)$c$(7T&8lgZ~}~sW)tE8PzH3!NY)ZA zH_Hq^Nd5@RL=teJ_%d?J6Fx#S^IZkAfrv1i=$9s{>`b5(PW0#jPW2djUM9)YF;uM` zjwx$aBb>jy1=Wep>RQfXH_lS8&l=jvdI-;I&&=j<$bPejnkEpK%ftuZ#5`PR(m!XJ zPjqcL2WgzsafY`wVa#6n`+DF|H&xF6qd^$o}>VSL(7x#DpFpC^#(2{oX1mx;u!PF<|O&@G&jGa^};u-IA!xBlC0$*G)S_}mjhf;pk0yKAs$sh zB;J8G-Yau{N~%-`7FfrwbYp&JSlNoIJZ+HyJWE8!I%MS~r^oHUk5x>vNH> zF-k>b8GA$^HZuE4u_Cb+_ox}6sli5^kU)JIV@yhfp;*x@2@G)$+wj5oyp!k~P^M!MG$1rtTKk=0OZ!aw z#;=z6%7j8O9jJ6W-U11W=zXjb4>JEyygex}LHK)H?3}NpKb9-4u7t;QUk?~cS2a|ZrDEu3(cNJ0b+tK0rETVu{ zS=?hm`2$0BuY$V>^Z${l{D+hL-=PsejQ*aj7&wNi1;qcE7QyYGUV|cMzZBqL#XBO; zDLMZih$yZQaOnKuL&cG)f4h{|bE4$j`oHR&w1OsNQ40$2=3KkSdzxCibK6IX>jo;D zhHBbJ>)Kv5bdCY89N=uFV_>@L4;HE#{8TfIse6rSn8g5%N&pTue#W$KV}?d1uQQcn z|DZ&Zb1O58?*K$Jy|yv&;rHSnLrCZ`BMiWYK3?;oAD_SO zfBk;2{x?&3aQ5vKvwv{(kKxh(Iho4q;}v+!_3=s&c~WxX--Ky=ati8tV}!^iFDNN3 zC@L-k5~igUwGEAh*-h7m9RM12nCgNC26at)UcvhYhek%HgT^O7!>_w%Cl(f08s7rR z?RNvqAO0M#B$yiGPT(3(?NopLKKOJ0p!Vp;-q~T$aX5YO=UO`sM=UJjA!kD>m1ht} zAXAyNNyX2N%P*wBHI&SIRQERfAvUpQ%L+_tMC|zY~Xl#a$97z9e z>AZ(2Q-ce9dRWl*^xm81PW;DI-OokT;ox|#4>q))Mvnbt>r;EV$aG31Z$Dg}Nb%8n z5^4`m?S5XYxN|9Yc$bgYR2OUNZ6tn6-hbK{edA+(E;_9^{3>drB&D&LILikx>;T6r z05lr@1TL~``RB&yan{hQiHUz~i~>(K|7?t29=Dlh!)(8-_53mHtOv*AKj_E8v)FqZ z2$9}i4}+?Y-oXKLvcqsF9{kxD`6bwZ1v&ceG5rz`n$yyEymgsV;$EIW05 zymD|#51~53UC>cj!iRwsJ}zBvjHJu$Jzy&j%p5cU^g!`N4uD2BD?HYzJ!$DFHt_bP zPk>>^btOaDjVJ4_$;Y~2l=mA~XS;g6nUY7(fa8@srO)lokAi93w)2@@j-(TCOGYu8 zKAAql^NKbDpizxW>01YfmD`_nZgleihMnY?o$@mIwiPPr=X)U}%xvUK_wLy8nO6XY z9d~;^Ce}$TK0{^fduj}DPHNU~72g^n8MeNP;-ylX#mn%IeQRDS7~7O}e(3(7Wj#`$ z&;}x?3WDdVlW&T0yc7ToI{~M2c%Q(qKD;+QxAPi@GvJFfsR|apg42 zb;3o%@Rrt#lw8s>4ACkjLjEV%+Fo`2_kb$4;)>n#15b?I^Q;?CG+R+gC za@r94`H;0fCmvNA9kHvYKn%A(9GspX9BaQ%XZ5jw_O42V5NToTkMn|C!kgF<{C$dC zrj8;@+v>8R;e-#VMi@CbG`6}q3FJnVDM0fY&X;0{Fx^7=GLWWnLOlYe38=}I4!atHc$~T2^-KKOi;>Y)m10VDNuP+;|3s$JGsm`X1ISe3be`7{4ZI2cN2U@U!52=`7>uK`9TMkU zRY^m%F)Wn(CsTRj%jAgck9vfw;N+482*+N#Avt66k6}lTSs4#~ZP@Xz!7^T;QWphl za4lyHDv*`c=zbQ@I-9)n-okEn^0S13W-?=^fcRIH2$mvN9DW6ltdq$vO6K$oz9WaI z-?}bbm4q|TrW>Cn`6n^4vXbMEh6I`{ZfjuJ=2Au&sF_GywKQmvrgf4Gy-;rz%+FswqLYGH@QzjJ0gEP$xxVI`|<0^ z84Knv>?n=FIZt%?5m+r1s6&G~+%6_|!V+m>td5#fUKV(jed_l1P*uVx! z&2sv})_nW=c%`EqgbmX_IPA70r0oNx<77NJUi%`!Bmx|-OgksdUw(GYG4L?1aT;t^ zba4-TMTQGMEMUwTqg4izGx;4Q=PB-7NqE0o2@O$qRg@=MpaUk&$2G4;-cuZ%zxwd) zXZ4rtN9w;x6$^r~AgmzlAo9+&L}6r0?~8Xfm7S{_KlXaMi_A{3$*2WEsu(N_)|EN# zt_ae{-`xe2BI9Ii>cgK@jYQqP8%sytC|Zj@6&Qa=!yfms+>UdcBiEv(MKQ%l-$zrMNuhb9Hi=IK8?+!`S*u`ahgbT18chEo6*n9SqUN>b>D!RY7 z65{Bx3X>O^dw8&c?~XhUR>j#%38KviCTt7-pMXaH*-0KIX%Qw3K%+K{Bm^1utr3_R z-2`Sv(;QO3z({?ROW7~HG9_GlDO~?F+>kE9ST@4cMQ_~fUkp2C1m>p^4ziK=Eg~QI zMYb*4@P3rD>V{(=Ic zfuJ+-gcSJ6$8IZ#&Om(9T})>nRTezT!7(8v;)bHJMXE7^M-&O_hPl2xqtT#o{GjkQ zD*YphX?)`uS>gN^;%c+FIobGnXPz1y`H^jm>aaBNE8K+k2Oa~juOlLfnedEPK zANHF)%%4wC;-q5|eZ&;}%%>pnayv06Eb+FfZ!;YSE?>gCB@J48>~}c4CUuZpUqqBD z0?>I9`6opkMl&oY8EYoh_9Zd%iL++%ag>KGK226LN#=)33yu-8FDH{9CYM1|#Lq+| z{RyT0Q=T@aD4q$+!A)+_ODOXZD#@j;8>i-brfR~4wBa<{^QoZ2)V#h_<90#Q@)YwO z5z9;kYdNvInK$q8iP@JcI?AQ+Eo&ICf}~-JFTAj^M4x$Sd9l$kdW7E=;mriDpn`j`|lGt;WkD;KJS zrbiXXp^5-v;=ml-GVH7dcwYP{3%P=T6uPr zXzr+GE=5?*W@hg07{`0ptS@JHt7o~Ou$&*Rc{eHYjQj~V&hS>s^S;UvVez9+w9xae z=nDdB3_SO&9KGQMbTsjg3Gzh;@?u!?V-RQ>LJu&oZUqtn7$Fw^LYWG7x{Cbm_CgbrLRgFtg%vutuAoXnF>EK(g&ij< z6KQyEqTHXyVg-|CxP7m=$f%>Zd%wu$yx6#uO}&CZvqFB51K(;l-I;>Xmaybe$NfcE zaV=|+hP+ZkQptH^NdSGuVM&hl8#3Bo$$ zBPvSV21;Va%TOJ6e2t1g=jeN;(%3r4!u%cM;8K=dwm|JlcqY5|ctu%Ts2<%{QzZ{ucB?ly zs5=|SZykYb@D(%1@-f5`3>G?#&erpEa)1K~=64`<8$hn3QRJ(L7;B!~Y9r>DQHe;L zjxgTR(F z<9p0(s4!~%hsSpwImz_01;zB4-TNF0N!34~Z1r)s4bZ{Y>Xd?A;7O-(peYQfskwz^ zF?U5Epuh#Qns%zQ*|tQ1Te|!*PZ@E-pK<0!#z{N)5p6OGpHgI1YN)+xi7@I&(D4ow zQ1IqpoTO1BsPi_3L5g`mi`*ST77+bC!9fJJ$qWcbv}?$^YhGOZx9))!u_!bD&dQ2Q-aJGXL^Yz`=&N*tZv z1;rRvnJip!9Z{v$TsOqiX!nV;zkyz>F~_DO0$ZuHSvaY=5p%3D<*ad^Rd27$$5s4| z*HAQj$pg;jdbdXn{_{A2oVji+9-UkTbubO%;~OlQu^zJp5#6iKw`9FznaLqCz3<=jo|)%rKzlt0dy$a)^jP`^ynCNn zzHu^s`2KCKT}xlAci(VfpBGNSm#|U`-G1a%)Zmi-n9Srasp*dU{m8E@<8Jy3DF#jq zWIUY)^30RHHM1DVm6CJo|4yLtD%!Kl zV1MZ}e{6QWHLZhy&91a(q!#EJb&l2#O*VIp1C67PFRd9W{UIMg=|X z_jRN0k+6{Q?|+B$lAFJ3I_WUbvNM?m37Z*>cpJ(V=iFD@_YZp>a?m+R=B?v=ct z__x_pW>+BoU12kNWmZop8S`8-1Ht|53G%)Jqs2ShuP{k(sGH8 zkl*rCT!sK^wlCoery$RKqr~%kYL2PK6pwyMo5-c;xQ9+k%%Kysuv_0D@8yqLFD^i{I??B&9P*SuwtEvrY%jmhX!wxEunm_E2aIjyrl0Z#*+ zg5P0oS7zXf+001LLp0`<0Gd3Axi43YwYeK>9mZ-X?;M{O>A%mOD00khE99f^ymoT3 zSN)#~4de)GtSZMUr~oKv1?0uo8=(@rE@O%8I)pvor~Rn8B-VI-YciY_@J;{6aTRn) zj~qdM@w%X+jx?9|HvSQkqZHejK`cevSz$th&y=L-#-gL+?vta4f7s0IkxLGr@uBJe zu$habjD^Ng6Ku==vYG9&G$f+>Q8X6*vYAWl@RjrSD*m#WV({Ti=<2j z`#kl>X2&u&f;x*#07DfH_`_yyUXZrB<%fY6n(ThIUThZAzpcqF2H4E#sVg!M91wx> zN&5)vkj0;r>d(pZ20Rg(b!FQ9HD858+%#&rj%8@;q)Xgr)N9tV=6$Gpm%2Pad; zAHGBu8#{5=Me8NLb1E{3EIpf(58&XKw?}b3TW}DcV{E7HDLtQ&5v(|0c0}h9$yyZT z+Vz*XLi8v_B^pv|g#HuG@pzVT)YI`0j9QG_lDr3keySwlEV zypS*pRY+~eKz{ts#e9_+M9bI&Smg-m2k9_KOZ%U!VZ5RF_~SN3F~*K z5*OPg8LPS0-3u^#0PD45Kij7&K>^VT&?c$BZ<+wF-g9Qo2Ug+wCT8&`SsR?;6S!EY zbc9GyFC(Ym1e4oi{0?ds$1=E@85Xfix8QIuSv9w{qBiry3-!mP(N8}+?kA_XCcH1f z9E}b7mC_=@Dms*uxJnc0wyzK@{=m1zF?j=POj})YtufhC5XlYC+9%;+fY=lH1vKZ_ zU-mRu(wZ*;i z2jlS#R2u*PV>55uL|^P%T{GQoZkIZ6&F-Q#JAemM+z)>x)IIQ%US*}VRML_%rI0Y_9B-%JlVS!L3@y;pl~ z(=D%rYK-Gk46-V8C!2K1LUq2|S*gv>;emryTTowQ=o4`?357P|f&nF!>T?Z#0D8(n zUt_Jb$U>^|#e<0{QcbZey%Njjt-j8!gPCoJ4|!TJMYe<12hySMso!*9TrBDFuw!#S47PMmAi4aVHy0d+uVFXG4vpd z6t^|%pAgX(u%lNF9&?3GjHq%fG8i&ylZ>pc16*y$F{IfRELJ~QnC-n#RH3m28q7mR zb*kL0NN;%X9m;oRg8UPUqP@(rN7&*^VllXW#HL?TIGI$xyHAd;FTZ)=)j-joZp%?! zjRk4cWZff)#IMGqB5HD2pYEu7as@}Cc%veO2?+e?n4T=6IXxqYzpon=2-W6kkL>D- zyXc}G33>#IM-ffJel(2MmOXvv{{U*%+KhLmWLw*B((a`M#Vb;pz3VVF7r&kzi_r4T zetO_P#-TQZb|xRjK|Jb&fiY25*U;BWQVm*}Utw{swR0r>&YYnMSONFUiY`nJGUUKzGcaSgI{2`D^tSE>l&gjwmhhwKW zKR9pbFuBWTNJBt}*T1tdCK#J?^8x>fD?%y$e(VE{lG>zm!*wNE) zs09$;z*%|U2P@DX#Vwx}&T)$l=U)3ry^_d7V-dw?qC=vE8E@+S-1k)OI4S5$oowH7 zo5`2jCO#Qor131^bdUiB6Ud-@Xz(wi+~Ie!-Xg*t-mI`ndNqBxiN<60Uqd&=awu-& zdaopX(C%|h6?VJ*)Zu7ruecY{EP~$i&0S(dJ7chA?mGK{=lO_q-X^+Pq?7a)iQj9k zS0s*BzdS+AUPtm?NI~w6eTLqFe^(tky%kr;>y5~xj-LMJ|S@fyO0lG&2efHD<32kZ!ZJ7yey9hO`42FrwsPTpAF@^O)WP#Ze zv@h&I4(e=0*r>8BkQNcW2%o}`1vXE3HQ@{WGD|b^!k{~pb^VAfF*tGrOgpxN1)8ZAvBF7aqL{IHo3a>5G5j^kG4h16g#`4g_*!t~E*3dKSJlM; z;hkPLl+VvH;^O`EWOQ6r5uemba=gw35*ie!lvTo|8r6Dpo{~iQ4<9FN5+z#b%bH)R zF4jDKKn~u>db*t>=USM!q37X0D{p5bf9?z>dwj=_9RF;54R_DkJj_+|jSVk0sU&W$ zY_Nd_Y3=i#K0He1#M_CaDYIAdaaINFe7Y67c{bAJzy?KB0Sy)-LcxbNCR@p_x{M*+ ze5urWDb-$R*0Ceiwezxv-NBDPWuQ=Ycs6zFb80Ihb!$*=^Z@3_kB&!$&ur*C0qP@JTnxMn!8WmK7ETo}mQ%x0j}q=R;4 zkj0>7ecmhUBcDpR>4kvkp+Q8@;{=7~V+|+6Xb*y(U5_{;_+q_A>5334pO zB#5taWSVmAI3(T~X4_!pe;gFIO3sB?8s{>%;h&uKs}Q&v^WY}l8KZ<3Ys6~ zi`_fzc$he6_g|LAYuhqh-)_mn zY^Z*6UXLNpglZ{ib%{|^>B8Wh#MoR>qn8StvJCXPw3xEA)vS0cq)ZQ`w3h>0lK^~V zUw)BXe$`ZdGY7m7%P(z%Id^kfWXcYja1ml6&uuHJpm}G5jF_B!yG6x6L$LAOO9|bD zN|JHUIN~UV*!v7}h7Bumud&XWL~aq4I=;D7#icBJSfM#pFNlkojLP^pt9NXPxQlU4 zv8o9|tDneM&mbxouxkdiY8(eE0_Li(*-<@uCX5IJ?)wOVKjMgS&E8yN*SukgK^9kcs);Pp3qlf({~9F9 z#n-IZ@UWf=>n^G#G!r!Ju9zLw^kN>DmCgcqO+BG=bvO^?mjP4JQL$-)8SO!T=`;d# zZR>VzdsOYmDQ#FeZRBuVB04HwdoVd)`>k5LCpqdNC&h*u3eZ+U_kb~0z!<%-75HGG z&tW(c9VEsbI3+T~)F=SpSdRdO?52YRC#b);MXJB$V64R-(Za;lx*yeOIWG+}@}C=O zU9#&V^dfH-=5NN*Z00t`dy?5D;n6wDEQ?0i(q+_=aUGaTh1UsII;Cq;=jtX`>$Y!h zDz$4-y?I_rhrje#*XV5{PIu$$__r}ey>C4Ju$fzW-!AmNzv;E7?gJ!t4#s^>9(^vU zeQqs%9yjvO=K6L8^0d6{yxuaO&()OZ_UAG5`=<7XERdQ~WJTQclYi>p3bu`F;eezL z#8cxxcC$@Q<->6fle5HM&1_{V0SA}ySvtz6@PkmjJfBnsw{;RX(kzEPYmdxs}@6}%sIRFdUKejM95tz08qyCCYyH|e!Eac$g`k*2J zxKj)4+mZkla$$2`adj4;{wk{j>|aTBo!Mpg{GGz;&a#I7$|it_JlN3ET?ZQhVy8OT zSk1uq=58Q)nri%UR}WBlx(8sr-@AtZ5YOz;$OORR85~~#V966ROW&qe$EM)l?}6sqMSPy*mJzytcUqAd`X23BG^#XWVx8e=>OjvZa^*WJ`ZrNg>pcF|qfp zq_}7ZFlGBgK8~Tu&dV>zPA)7d4K6OLtg5c5t*g)X(FbV+wzb1LI=i}?T6+2i20LSY zDd`6q3QbJ~@g`^fkdOaC>MWp3ZU9J~JyFbk0I4(c{q*eoBFwkBb?EjEbWVc}WJ^_6 z?Z>rQZ{DSM1rltfg(_DvJa#5~B=rJ7>L_Vn-<~{DuCnNlX3P{9JFdrTuUKq-d@!j2%8yQICGkw8vs&``jJy$b{o5*1@gfz$3FQoGfRTaW#<`!~* z$udmLW7b#1J+z@>SZjM%JD3()t~SeO+~NTyuH~(0c0IqMxjE;2P-9m8ed7dNu~cu* zsDv6OQnH>LcW$!T*igNtZ+h!O(c#sB!RsmK*-PT)urpDp=WhFSPSEy873cWZFYeVJ zoXixa185}9bKzz0?%3bAH2&JkZVMrgvi1s+Hit^bX#9?J+@E9rSpHSg-9>S&HBma_ zgP7}C>_Tzivv#QyJ`*(148EC{$@RrfUxw%AY@)K)&FQ)67Yw`xsCSKE!$WTZ)dDkb z0-%+oW^Nq~|7vK~ZxZ+rnIJ2G>8lHaFKrRqYCvHQ1Resa6IlxdrfjddO(mn?D5gl{ z0g*RI!Hgb~x8zKBzVaNd>k&{UgY_6WqQ;D9%{PUXoR*?Tu!kTCII8}cL#V!l zD9%|!GhPg`Wv$q_vE^Cb+E5f^3!){wiAZqN)8|XR(lIOyXn0VVwSUSHR$ivc={^~R z)mz>iko5%RxjNQLMbDw~2o{fKwK*Oos+}rWQO3Xz3{%BkEH~4a?KVjeEk5|i`?a)I z^dRz6%DX1SAMaNdHu>ZDAH_f0ZqD|~qg2MdLn zmfy6u`*5BejTN`voJ>wrAz(kO$|Vt|k6RvgOMT$Iy}R)D%;opQ^?L?nOXW`mf@tb_ z?{1{mwgf!+`knzuos1iu(d(6@t1BfKvJZ~5lG>avPCpFIZJ$$@6N193+~J?p!%aF2 zMHBA-??@eb#zUVt_5w{qE^0Wp$tmfBHv2b`yJN2l?B%rZCz2E>fdbtS1vZ~yG(-K)OJH>Nz|S1pWFdy66Yg`31VvJV zcjE3=qVNO}dcIM3O(|RF!@CZbCqu|RID_PJxpW{u9PD_YtBFs3K^W!3wB8qS+=mMO z6csZWO;4BvrN$V)BeN`I^5jVx2&LJGKpK9{{<)@CDC+}eM#&QcO%+9*vY1yYlMKWi zbpA%~l|xLRt5jW1Ph{CYCbphzbbr$CE=Oo4QC^u7TsmMgP!c8&S*$#03L1GlUI8h) zU=eOs8U2*}D|K5vUu=3{)T!xL8X_!TVoT*4uw_rb7|xeEANX%bo%mEbS~#)-(}}2Q zLC52UN=(}uIMSL+!56d+%|z>yN0U+3!uqeDhlQ+VBj^>B;=R8|n91j?TPq0hP(~(f zz9BFT0^wHBlcqEY<`9qhtkMq$Uc^#AGjXx@wnwZgye%-A-q5 z$uWnS*^gW!NfNDX{>h3qTN=}s>egj+-U`ZIHodBQN^#b9^aZo#>JH*sRKdFj& zl#I_D)@b`NTZJ$98%rC5{w={&#g=PEFc!9ff%23^LIam2Cw3ejm`)Z6#$|Q1VlWn> zD`9xSK2sdJeg+DwkX2V{^vr)KuLk(GW5oIuMdEox(>j56_^$ z!YZwBg6jdn$8ai!77k~A=W(Bs68FXVuTPqZjQ5>=XI`#RZ}1Ore|TJuAV1Vy4II-c z_t;Vc21e&?7bAdHX=wTO>bxCRL> zlE0x^6c}ECE|hlBZDQbdEC`ri+eA#e^Z3y8+<^zc&iC znNOd`<#5`?AO@k$D56Y7)P%RHBq5r9Y&S{S!91t|#pd6`#IkZoS`otd2VsQNtDTc{-e`VelUXg< z;}j;cctWy452@koeieK|cnB0-Z8<7@5OPVmF$Ojp3@i;5%;ml_MkVKhAumB}g~Fg- zq(Fi*qv4Z?TM689x8(`YWRS01bQItEVv;GtkfufsomgidH1sn0Kby17Fmoku3UFv` zuY6aYWw_jgBvSc1?SrGo+|qBJ06)UE4{j(|D+H1MACWrW!ZORQkujmaQxb>Y7?(<$i6-3~`W!T*XV4g*0b zO_8qkOEsJd0)IcZY!@5-$#7OAZrqWHBwuZ==?BmGeJEu*y0Di{*<#vj;`We#dC_R) zjt}956l?~+m(p2c{?guS>1!NMFj}272#4ug?J~OOMPo+#(K(~XsyMl{ z&;<|<>NpaY?$mNd-abb|V@AC6wS11;(Xeq0 zxW8`KZ;<7Gk9uZcx89{z@`?%*BL(1IqkCbnQQReZee~v040I4a{~#vlgrn~*_*~F> z#fhweP{fLZFvoibY+i@HV(m=T8sLP5$_@vL0NyLfHiNqL+1msbaUSyoWl6hg^Uc1k^l(EK$P}h4PW~yU!be@`^~TUsWkWvSeY3k{8akEsj>c{ z1R!H&S(5?`vu(E$XG8Z`E4-Y5tx1dT$E1W&bc9g-Xq3QD%7Hi*fj9htdM}*Pv8sEqvi@)^2Ut(QkGb zgH)g#*3)2?0130G4(lbS2I#0mN9JQ9X7Iqk=@~QSXcR_1ic0Xj&jiqKE-F$4mw>fb@$kDP|})29SPD{Nmv$ zG-)M|{q#6i@KOh;B#AY~O3cPeUB=2##L0=qDHy~lHpcSV$Eh~Psn5n~T*hfq#A}Jh zzc7f`b&c0giZ^VGH=d0*vC$O0j6Wbrc-5$3VUV!nkYMeqVcVF%@dBJ7B zlYAgWsIQjJL(?eKau)nU!K5;O++_k~4=wa&|nfXGIdr3`Y?~vWZnvMjl2O zrsk}DG8H7b_R@iAJvrAVxyry>%m=sFfVf^EHCM$(g%9L#4mKm^*O0d{r9%OaISlG1 z&rUYPGIMTD&bh9W_u?kc(C<-kMWeJmG@4JbI!K3p+iqzQ*LJa0+ z6;l(~7k-q-{j$)v?B+x0pb@=jG7>acp9g^GLQ;*W?Q_Q~;%jzxpG{ODRgJKMWMaxk zju^NkCDMIj%)&q+!|}?p^iCnwB@3*77=50J{_BqP5f&&qKWpRs%O_SBOL`s+6f*bo ztTv16vs1QxxhOi~oTq}Erz)JLe8|sabPd-~8Dx@ZDRYhIa{E?t-(cqL`sKX(Lq4Wf z$g^(Bdpno+D?9J~u8cipzQbHBK(28~&Ub6dXAwoEmL>P1EbtL4@T0`FG%N^8E(mEV zXzT^h#UCOKC78s4ooic^e|i-f5C;RxLZY;-B8d zGIl9BQk7W=DLbE&nJp^6o|DPLD!)^e-WRL5t}Z&WtpL9$$HJ~yovS!tEb^qQAW)MW zHLQR@!KC7nIL(!WLl{VVmHUiEB%DF!Z5SX^fT3Ll~5y zV1Bjgyot&TXmuFnJyHj$GEeBb+E9i>!dS1~uv2vH zc(|~!q=qnc>~ddudH%@6xoo`IPZiI50 z#Zoop7&Ya&Hx;Bb6*V`N%r})8VJc+elo2tZvTF0MXX>23Fb1Zu10?0&)q@F}!>?@G z)xO%CG@C2ScO`R5Q-FsMY|>*{=y2p2!Vi~&R^|k)I7NcWD^E<1P(QMP=)A~{LCDBv zLGL@V!85IusF-o7m+D1hGvgb@W` zk6}11Fm?o32tiK?2TP5?$Wmc|Aq!KWLkjeSgaAzqL67N0h6!T1K~f`u$5MGAbHF-T z$2vI>oiT6}0)DEvA{R6GpAcXWg&4S{Ird7*ASP#M=VQ+qQ>t zXk9T*L-~nC+9&N>H+5SycUza^TMQLVWP?A{smXiFU`$_+3>Ksg7D*Vsh$b$k<|Vowq?@RzQjIV7z zB-qv06edu+Ftl}y|J0ql9cP$Kd$_lRyHjG=Sf-sMdKh@;jt={b;qdkwk3f+LM2agX zB=Bdb(ME!C2>-M8^bw#v2mF_mOXpt7^~B&Fv;-*WpPJuCQ_n5$y|Fy{)IQ?m|GJVMpezLj1qW$^ltLn-fZ9`JSVSBoDLK+0 z=mAxlZ)T7|X0}gmPC-^~eraj3UU`LIb)5khZv8!F=}$D(hW@zwKAPgk9QrmkmN8)X z!!UQc^v6ugyusAW(%ck$xo%@UR|Iu^_F!T80H8geo}Hy!MkQSRzJ=TXQZ9_0*i7xH zH_R6PgYoQ!{#pZ9@tny$q2$>VL;aPn3*XSno1`Y-8Vu+$4`n)R9az+VfUYg{8}U5yDb+FeCFtr=X2tD_SYmCrZ-r*gY}t%GKc1B^{{ctPD5l68Owg zS5j`%Zak{Wx}PKBvU#^!S&BJ9Ig;Swyt|lEy`7iw6-5o1tD%C)SBse0M0M!L4}I;@ zD!2YPy(iU>M~Py5^3_|B7SdLV;_Al3E_UDiV;c?2h9M_Y1C};n!Yqb{dI(#fc$y8yL9HpdRY$pa@)Z6-gUufL^Nm2W@a@C02C33aTUHV~y zgHas9DkW0w?!?Z`aelF9q+MEaJvc}2$;WR<`VcQvN*8LM4N{#&1@y-(NnCT!d!Qfo zErY^7bd#Q^1kijGp$nvwd$jx<+JZXG{h`z$;!87}^`RK&K;4w_?M6_n4kXSg*Kxwl&;U_>$tS*y9KWSD+r?j5 zp^vTJCEUe3Oa`Q@jFE-5+H7-Aa*`J-yBtt}g5 zq1Hu;TZ>M4T>>EULD~km->ZI9;v&VilMh`FKHPNm6PupCSMhG%d2RIRlAPBM<7dlI zSxRne(c-V;*1MUNpUC2i{CN-a?M{D$O@EoRo6IQ^40}wZ&DQ~sYgRzQaPMNrA%4uHu{bt)$$b|*3tlf6T6?t@6<73w zM`keMk;E*Mo$CQP!+>eL6;GAO*(crVQ$j1+iJ0zE|;DX+aDA5?y7C#`9rgf^6- zyS?RXM9h&q=}eNGLuUHQH8AgEo*riw{iNA2`khPxFY=qHFz-jN@uo#EJ2eG}l`}_? z*T{o0qwVhapC=8UvVEqIP6l)3p+4m>;#U^!P}V5#m`&Y9YyWr=Aj-3VSx$HP(8}OA zCSH?~k9S&8hb>P|a~y(SX+=}6QxI2tg2kbY*{{=!ldwxnZ)_+y^l>5FNnmI7LDx1b z#Y$x2Y1BF&C;PCY219I?asOrjTX+9kfr#OCBEjr|cqzqdAoQOmJ8+N=MSYieER%_4 z08w+;#lX~)@ljw5L1lSio<-zut;k+99^n?3O#=)I)=?t$EFvM!;=DzQe+Z7F>f4u zL2RPC#~ja@lPBX}kroO2+mN}q{eWtaVwyg&Q*3whK~okiwcps)Tf3U7ojNVEZQav9 z3eiy_kk3+s6u-P|@@t_aEAt=eG^o~`>Ec3Z8+}aR2}kki3q|sH)?2(RU-M$N?Un$xGbTv2$%cllhNFFG@-f-8cwUg`gxcf zy=ym(-TQJr{}nuE7en$T5~r*Am6voV^)$33am5RZ4Cl>@xF0^X@4aMEIByRs5%!@CQ7C5@`cBt8qK2NYe;-XBM2?_00~QZChAf%s}1 zOP*(!gF0nZiS%K*d{(Z*GPnK-Bm1uj122b-@;;@el$Z;Kx{f-(`IT}syhS!Y+wX!_ zlYXae!8hbO>bLYOxvRvV%^5Nj9w3li*wVaoL;pQ7fGCrw%TnLU^i=kl6Pgv2Hy<}m95l&|cJ?(5 zPA}M2KTTY>^b-=ds^xw9&S5v~gOr_h`+@hm_Fh-G&Q3y3Gj&>Iqut8d5?wcAdQ)&l ziez`5%Ns79KE1^~CNf?Zvd>n@a#JXoyxmW$(eVa6!EenrEJQUfBnw;>@#hUz<9cY8 zAb!r&Ys7tzyGJA)URb6sw(+>_EUjTDpr)A)@np6g`Il24D z^tHP-lELv`Z0v2+`@pLHF+`j(-M4= zlWbGmWX88{AJ$O?CeqjSlu*uJt^6kD{oo4E-`S>PXx9&Gm$FZnoX*ZSs!)$~h9#!+ zPUL^}Jbw6PFI19P@73p8J&cEMo}J{VymkKC`M|lb#%uM>SFCNGwk!tNce@3P53Zk- ze<^;F>+-yErlN(o-J*-)_4nV2-N+hfn06!JKga9Vy-nHci02luL%(k9*r= zatetN;aw!`qdcPqq5CtKyYL$z@V{5mllzW)ef>7(s|Uc9to>`49_CnaDK_}^68QuP z`y?a$fx(=ni2r-?z)$+VWSRa$F#pd0Wr_Tg!3($ZdSXlKfbaQ!$^`)-gf#Ael78E% zvmz*>Ajr}BtN6A{q<*lg%Li6;mwLh=9|)thh)ckXUxG-;dyK#wmk>QRqF5Jfm!Oa` zHa|WsNA#}Xv<6Q<{ZJ+m%<_iN4?#FB7ojrb!LI1uU1K3ImoOfPI0jhcRyMQ&!>7K$ zGn38h%r9(8**DK6e6GN!bB3_DAsnu6dz5$=jJ6i`Ey!_P`3ob4LL@=NVSixTMZ|Hz zSMth`EP==i7aNZ)P6&h%N(>Hkju1ZzzN!zn6p5U5iGt6BmzzamWk&tPAU@*}wY&OO~Ic#h!cJ3mke$)1eYaHJ;6%A0KlLOJfspJ}?emYw}9|)B&h%YDzk)goR zcMVezeJ|HQtxmy>I!666I84+vVag@m)*zTI*h6+ULFzJINhOh2-^Pe8ku@p7Z6^U3 z?0%(4>>^L}vI*|G@NuH})V2b`Ub_Qn8bI><6Qd}SJVld&FA^S@Cq=rvwjW3gPKq-k zKn=qL;Sr!l7A66MIkx_UqJaQI6-a4PpzCy$<~Ef&3`GKlnop4u(J#F>j;aDn`P84> zi5bB5F?ypTKBghw?nt?iAhl;UB_`OHq9$crG*CE!R=48SgCsBvGi`d-zndam>*8^n zxfxT|n;{Au>Z&w?H`FSi^z|M8G)z~Geq>(0jG3L+Ytcx^6+&uo>K9R{Pv|nP4AQ&p zp}G(h@)}e{Mi7MzZS7iA#%u5`CUo>87}XYv#o_nU$tPnrvp)#c2#R!PBZTq_<;Vb) zYc7l7%6IKD>oEj{mk*hh?~d*%3J4jBWQ5QkcEwIYH*d1Z(s)G2Uy;Q>4gQ2`1Y9?;ay#^s4BdQ1VMzEeHYJexcnnCF0Ni2~7Mce7Pn24btzzHK$;S&UhOB5;75{_Ak~A6U zSW~I+PD&vnZGrNx?4%I4|FT$DUv`$DaP_a0>#7VvS$-^5eqvaD=Jp@8ClFNyvUmlm zQ3aZN1x88*R&xc;d`Lu=ov6;yeZ;eV>93BjdZCDJLb=O3)cD&o)~K$X>`o=~}K_+@i%?AFH2 z+PZ95XRHgG&lL_pB>B4 z*Mb7e9y4m~bZrfeY0Yu-S;7Xvn_Cye3(A_1Frz?JGPD`)Z3z@5yF+b6Vt#A6SyI(7QEzsOZe*wB#(_Mh4lnMVhCY6oRY2lYY+ z?M(+Abti*FCzEj}u#00$?c`|bQO4B0^{RLVI8LuTdizy-O(pQH7kXd6#U-og zJ%;x>47Zz<^f;#WeJ<*CDe3##lH>fg*HfZjEd=~itv^UTone(ec%i?#ndSMbwg`!V zQVPykxdDiAD#C{+CUqbk2hw>xkR_2+PSuv}F=(|zmHAmDFKn=kI-VREJpW^`+;~XL zAT90fP}6V>#Tat)%@B-w7>J{~jfZ_2_Cz_@m|u12_^f?3u54 zQZ5{c4(gj_jPBdlK8lxyYz><8w zI)($AsNu0=d2zH2IkF_bbN1hkFM5ydCJl5&gM~Gbnc)fxvEv)Rs2E>!8;Oo)Ezzet|c%mb-&S80Ts zYd#%m6Bj^p|AF(m+K`)nf=l}3bpi_ZlqJU$x7yT+<z>j8rQ=Wdw(hBd?s{R^i^l328@+=)fejNLuzQ zryR7j>1=dgm)O--AJVSolnzr9fkBwdM+bLQeD7g=*Q@+ItKIu4n4x7ddu!7;NF1;V zI(sA&Y{1+%r`oozKHBx1tMAeD`jRoO<#4Z-)TsB{4L!V351d}3h>@3N8>UMm>jZsY zBsS-%H$R7MTBL7~4Qx*BZytcQv~SU6VHQ5>TeHLT!``WGw4*~Gk%{?`Sj}cU+qR4} zk-<@bUKLs3>o!gVIFyzfY_=U`GJ^ee2hs+{so=vwY$vA=w{@VT;el{qC{WtnaGGR( z0+hVMwIZI~_GsG5r4bH$l-l&YrnbG7rM)(dF7DgCPN{uk>izEY;oh(NeX09{Cd0!^ z`(v~R-=z*FO%A5M9?Ya4%(WdXECIHg+XFc5;i}Z(y2;_@*Te1f!`-&S{iVah+e5@* z&^OwjCni77zW%&;540(M3g4g#HT=9e>;^qVs7oMFJrNkog&H7Vv>j@)?z*Jze(BsG8HXXs$bd+^kRDT&89X5@mFvvmhLk4s#v}8^63gnv{__-Ip3KtsQgXjnMrx9-M6y>vs0SBvX8vy zt*nubAAFyubrJEOwP>ChdfuIR+7$cOzd;oZU3 z-dT87FvPzT_I_u+?VPOHZDA%C0;-5NUR&q*!QAq=k**597v~~0W zneAP5?@&H1)mjeWn7%B-do;eDj(+r48nwC- z17)3ln|O!Zdo=#qKZZV+f06OMP`V`58Y*%sj?2hRh8rr^tnx^t)72XVe$*yBvRm3G zsb(BVl@Fy2|NhJBdx3Uwo6?8_<5)2OIlH65I^vxUGn-f%X%=RfZ?NaIoo6fkxz->1 zjfiKU;hu74^eSDso`LgwwcQrh0@$+s!NccGN9-SuwV%IRSPKk9%451f5ra}P|gGm`qD!rIO2L((nzXCUMJfN1Vxix zO!#T1{Tki-yStm_vpWb_F=BH>X2#YphpK;mnNeXmVqFm5l~ zR+>wl{8qU3CIC6RyMQnNWPIDPJ2ojY<>0IUp^R-Q@U#SAtLhMhCt}SU z_MT(c#a0W2$uK+5);cGnO?2REW)TNxVo9CrZb`!?R&YwwnXPGI7GL1X!&ssEev&p8 zHMW$x2!SUhgNk-$rS%%eC1x{kiVx}*?zgJDDn^Bl5XzMPYEKa7VN)OGyjk%kgAY&h zNw2{>rs=8T@-K%%);+C3BF@}wyN7ms&%w(A`^*)$(I1-7m4-7T?_M2O00nH;h0X-H zNI4m%71!~55|k2*8pizn7yYqsZ+Nv|1x6&g`UXcO|BH;@Nmp7E zt0s&~H>RP~N^v)-r6*YnP|lR>r;MeQ9H-3!xzGOT6Xur+`Iwd;oXy+!ai0Ty!guG3 z_kF@8kMo1`WiQ_RP!V{m&Hy|RN0EKi$YSMUElQkcbp0K=)I`)OB7eguLQSA?vvt^V zn@{J4`f^QL?_=(Ug=Hot5dnw~hBjyMQIDbQ15)#TjqqW^suxS495RSY#+M~utqhEd z4T|!@%BYZU9JdpA2;l9AjZb90J~7#rG2MvUE@Vz$UMoS3LU z!35J=tZ-lm-meW_AfYh6UfPnl)QJdW9aubkqbJ@hv*B2|_G&FizuUe?#ijcZ z?QzUB_NFMl+Zt?Dm#-c?W+Uri5r#^05Y#6Tp+T+Bw)i1tt7*9a@9C#?)k79N5r*Ck z!ceBvZOR@IIl1?rg4AT?RIJs;}DuY_d$8iP!JII;2HZotJ%J8dRR*wYr zJOOSSbzO$fNn^%u9vP|hS{oQXa-C4$XfHtw+qqTi&fd%mHD8Wc2gD|Cv}}r|8H_k^ zd``<>*c4f0f9fI@n?6vJ&%Po0%;S}IhVm~fvF9BbPFN(VpdVDym0csgQaqVC#@k;h zcgJKvAo@#Gq<`?B4#2h3_aC?IXPLj(PD3|Uldu2Y!q>OEKXsaYx<`e+afy5DkpO6A z>^+mT{S)ph_&zCrQ4dZ5P?rFxM@W`eByjKq2oJ@8Q|8aXvjVtw0=0X9@Q{&J90#qA z&u&P{txL(fKX}GewLy#9Vsbk(n!B^hJAs2|e$7BhZFhM?FVMU%Zk?`ZyvIH?z((pi z#{T+c>h}J1>KvWzoR}Y(Sol7@G&;31IlBsIZ)cacdw(JpfvWxL&eHDn%K8q_u;1DH z`3LN9^gnBFfBzqK$NW!9+yD9r6!D+^DdOK>JJmsQ|8eb1p`d>D{CPAq3YwkamzhzR z?~_}YSDIJmTUN`BQ~TE`^XJ-$=Gg^&IR_qN432&q%T4Ro(#riYRraHHb`Cl}4PS*X z&#XV++?2-O+1Oayxp&*1o}^qvC0yS8hFsqwV=2_w&T%})u%QWiLNF!!vcPFEL=pIK zTBE%;Ug#$zsg9uIq@cV3W|LfYBpH)ND zp~bfMgCoD$`YDb|Ek{k5ZZ+O@L2dECOGd}i{T~9xWpS|0R=ac3mm^H#cTP-|!9??O zX)eEx6_SHhywp5Ul#a3WD^`>#B$zB6tqU^)BQS+ZdNfHbhjNVt5rd7N*-=F#LV*`l z&9)7*PF`(j%mX9W!`(M_?By&`XdsXv=vDR7%U0L{4Vg~$X6H&kHc7@O>P!2Lo>KNF zPg^ zOT=(hWqY3L6+o&7h-J{~LVVDsYV_$x3?5LtjuoApv}}{nPj#bXSj+rK|4ESHGqVrL zlq*N@+LE4i>x{15`^Oy*J(qu@!6QT-E3c5KsYlJDs_|{Tem)4kzjl(+iV{3kMV477 z(Ry1o=7cM$tI9?2QH3l@PSwD|oju_a7ow(R!}3HkK$JPjPHbX8pSs6+#GtJ)XXMLF zzXB{ARi-2Liv*clWbCs^lFcY0hPl`*VU4kZY+2dCj2vx?W7UNCm%+J-ByzQ(xnWu4 zTgf@9DyxNqIU(%DBsMVFwDn;YM)mSW{prw>T_0>>xWnCQ>0c4<=|o) z8}Rh&-I(!N%wNp9Fp_sV3OAFR;EgxH+W2chDB0-!3|%^{}tf)};Fg zB2l;HmwL=j^Lc_)8u#OOHSM%-2?>sdN%f(U;7`+#Mk2>4g>P@?X0`K6&kFSG!;k0N zCR0DRxuwTZ8l9Epei+|mqxbVX*|x4RiQt&_`>wuaeL6KLpy9n1dHz3$d#j+hAAR4l zp>YcuG-!ec2m~j1uwVg#2S{)YkOX&!#@*fBY22Z4clSnvd+6!pzxUba+^MO#cV6a= z;)yDX?&i0?>$7se+iRbSASwz{m)wrJ9>V8P+oByGP^c&~bGEt9Uc|-i#XO!T^NuOm4SL?bW{R?ga2tk;p)i~1 zs$XK6Wm?7t|rmpDwll%XNm!WyT7 zzL}iwm@Nx)w-#I?Us6q;WctB~Akbz>^~uaf47)F!zwW}|^?F0{O5Tp6>p6Ltfp3ZS zCkdza=HQKc-Uy4|+g>SP8k`1)Sj;cbH*_(`zyW$TG>gIyO^G3B(!O!8PJCDthkH{M zgSZmrnR&onn`@^D;)z~gJs&p7vAqquvyM0dO@!z~!tt3AaPWQ<{oAre)T)0JrBBWf$unL*2CR*!aEdOxWWazl&t!B|3;c~UX+XvS z9~KjVga~*VhtR2=$0i#g5-8sd(7g1HPDR>b(jgtvo;^p;Z`r1Lq8*|yos5ridj&Tz zkdy|`6XwQ7q*&`->`bW2lR_$?Eob?FLm7+kWJ%^)Slu-%rNi6Xgl^?h_t1+FR-;m4ovz*~0Q{IO_ zdb8`=jQ3?`?=2T*qSb4|AFT+LK||BU>U9;pM^;45IurJ>4aLXDHvT2>wrw}KADPW0 zE@gR_HUT{7Z}UCyL3c||qiM$2#-U(H7aCpDywGZ6=ZTQuj@NU;t*kkPehg8 zvR{w_daZnEhQDC5)OS-|+xopv{qks|N%?Jh_9tu48*!+*gqWWkt|3J_F>HdU<+ow@ zoYB_jBTXR@;e=mMqXg<-2as|a`}A^12`S=UHz>4P=!pZ_fXPAAFUDT+?U9IzJgv_% z%U4D{`7K?)ax0UAv#`JtL&M6!ktQ#$pwLI2yBVK`Q-tMF7vp%gC)NN~B;43Kd8mje zjb=*P_0>exv%O6Nw{-=WLyNRSDLiumgxC_m>m&&J7)FYza9g`{>-mBRPpccMZ z$<`ftrewjSw_#KkBgQ2#c#=F@c2;fn9Z>ZKClw1Q=5CJW!9JC2!PJfFV`kHd>9DS_c?*DZWd;cb5jp(cy%_Ls0fuu4Pu-7|^DH(^Sqm+}f9+6{+t_BIEC&q+=IB@4bLuz0 zgd9?*?j5uWKfE|U$4i}br306%ty&Y~M@VBPfG1Y*6B?Cecbzv-6JLd8h4Yi>TKm~8 z49eSw306&hWOYu?8Zr4um-cB|{mVB`-4bS#6lGVoTCkl5SnPe^;nlp$C8MN+d=S4? zUZou*RqS$<o!fW0MViE)(aT_QuV-QXBnR*%&?c@s1HLN1=o|H z%CakLc4AcgEvE2^)7a{V20^N`bm39K-@54<5$NaxEX4(>Re*u$z4%5A^W(>baL*;s(o#mLyxb&US3W7b&bRkZu@Ufxqs!MmH4G1yZe z73mYP7owRPVU)*Mr3Wz43q!`rjn`9g)~w3Zv(wwtpujV1f&w$qn~d>WccnLFp*J$* z#}F|Qm8K6m+OrR{E_jUImkmDErrt3IKAa?8o4md}5D%I+FdtkyUm+O}BnHoE4MswU zPuQN1WFh*yM87o+U-&%eD6tP>f%E)^pPG|fMHbz1J)MM%-xpKAP*h(cRN+s20X_YG zMos}usQwh*US{(FjDfbVO`Y^0{_kZ1(XY9p63}eGfh8sZZnuFdK_1>{SXO93W`#z_ z-ah`D2rmr+=XnFK1N{Qbf;{+wtqTL(QL*FEg3J>PxN+IO}DNc?P=!Q4g zoxz|>#=n&$j5pEOS4MAI)4!(h$7DfhJtPzt61)I`1q1lP+ZlsC-iGWlhNYo}^qRT3 zZz3t$eqRS0H-p0t6aA(VBPh{A6$-E(=Y2oky51(bqN@{}-~PNZdp1fE+3kddWA6Jz z;)BQJTf+@PHV++5Fi@;SKrsN21GF%;{D`!of#3*wCa>ATaHfR_$Lr8Z4FWQ1KqC!+ zOw{-_zptnSZCPXt8+w#*lDDvw@qQ;J%I&M6kB(wmVLi8QViGZrG=K|m>~Bp1<#D9( zDh#zoFUH2W9mnT=6G#%iywZ1K8Vh2i`*F+zCbzq>Ln>^lneiBCq8wfTKqP=WlcLBA z$zIlXXFlOE0dx2x5FG$OgLh#KW9QJ~m6c%$j!6mmh>0Ex;aEX#+-CsZa{xC@5<*bi za0eBm)@k*h6a}ROc^pRkkjE;m~&KZqR$^~@o#?Cb6)3kH`beDzL+l7E3 z?^NU_KUJ?3$6z3aQ3g6$RuS}h@uPPL{#hxmH;c?M+pUj_1w{vP6+CFfiGJ;b-U&xc>( z+Y1!@&@OOr`PU&neBQz1zTjVn_}Ya5F8?~j4_zz_zb}j=D~c8&pYI57w5Ya7bX`MHxY^BoW#lV~7Z{@QR;g*asR{0@d54+Zj?bz| zUn_kWBb#E@(^U(;sqMnAQ((ygAR*#oBKmaYYUo5gA^tfW&~2`2CayQssmHypyG4It zPn2Yp60?0)Z|PdE&L3ey-e4_=EN(!pSJHsTge<|q=e*>a&&Br>^M8&!L<=^?>NLi? zHYTPtCO7~45TCp$Tk!vOi2u-335T45&9yqs^{&nTG-Xz zc(b_$p2!$|Xc;GOoz(H4@j_t64WCMBwb#KWwr#!0Y+Y}T+Z}H`c;2=P2cCzmst#>O zI?=lZt@BH5=ZBzQC2eOM?YGV0yP1f5%58TK?Olmfyu@|@-Hr)HByMG(xIqV&d>D5X z5G#@#s}hK|*zvqHT@|HV2JGEUhbCFq##hI5Ekm;VMY2b_Ww2yy4B5nB)WI1AUVF5U4~Mh=M=ly7j0f-)|_Jo)0KRG2`qP|u#>&`*KUNvz^stlpus0>9MaW7fV? zim`K{u}j^tA)fxM78A47G0&tJ>&HHzY|ol9P(&H>D8!}G0pu|lH^xe2tOC9h#rc2* z5z`$&#TMNDIDwV+O(z&a_5zE}Es7g}NFA8~a-N_?&3S1($yk=7mSn*Ed9sFRR5&%O z<_hqpmha{UTQu{` zfi__U!(z!V4S=TaiYbuheLjO_tzdByQw5~&;tLk%ThDq_06-DkLX}D&x9C)sHnyFe z_4VUI=8MJbcZ<27|I*I1#p2e*(v`*X-;0$mmP#0rw;x)o6?*2CmkwQ*gj1KUKSZ~< zcWyl_)etXp>$X2xE;9=)50ov_TH%ncBc2^D16VtTs+Oi(mt`Z7lG9eGbP41D2#p8` zc$+KSx&)geRJfwkyCWSm%d2!)T*DMKr!Ur2l@UIuA{>2Qg9&OphYwmAAe;=W(WZ_f z*{pF@t)aH9W38^^JgwtWZr}@V5bA9__t+pw-ymz-pjh3YeA=L<+@uxWe5tod@3G04 zzRBFS$-279_O!`Cxy30A+j^_F#pAKXm%b&?wk5Q>CH%A{O1UjAye+A>eFGVgDsPfa z+b(S0mbYnYMb=UpZFDJ!h1gy3l#PCVqEu1Sol@GXZ9hR6n#1O3z0_O` zZwe@@bCBle*&;F8ey@1qL3bIbdq5At&MgtnqioG>RXnh^Jg8-vWO0u&IXL3{{Iz~) zze0zAqjHu^ZcaA@cD%ScS8aJbM~STKp5XgB-*{zaxvgo_<5;!zMD2ccL%3z%BVipU z-%jfU-S$`6(n+Nb!JEq2H<|0I7^jFzrzUzWde-xg;lEs7%-52hJh3&aqrWguo{(Hv zF+4Ho2H`L&t6MT7OWGm^t^A^h*h>^VW2|UkZa=qLI%o5&>!7@d!n}C9R>R|Y!I^R) z;8`uScJch-LR93^srxOC#;#Ch30AQCQ% zWyl1sm_ZDoTyS(PIEGJn81 zcOWL^QQYf|?jVA-X$#G&t^P=MsWAD*YU2R9*LthNjWyt?uy-Izg+)#1AKD2Y=B+#Y z+X06uG}j+{cyh0;jx1g5uXg+s0zZS(P8R*qKkF&~YC2sV&cBdO>PmBsWmxYH)TnKJ zi2b$MYx?bFuiNhO>G#9KC)d{B5<59>@BD>-zm?qiU6nyibeFK|?*F4;kZQGeFVjci zN8q|&uoW>f7CQWcIo5OGkD1<^);FjDWcE&!E`;=xdIY3MfDWLn{8_qhs6tc^5P%dZ z=697B^x2ii2+b>i2ZFZg=?7qX86|bUw?(~N$F~hqPL;_~R~7Z%iWIQF$&FwYMd*r^ z@BtuWqUILuCR+vY(7a*yU&_H65-cC%z5)SXEP0~&7 zaedGtLa6t1V?#2bDXKi$`}s@=C;4`t4Kq>!NIRc_4HgyV_1a<{`l#$O#s#8&^Tr*vWQ z9-aOt1m63<*8%_j?fvqf4*1;Tud(9;*O%U&SMwJWu?S^9++=uH;sZZOmlf+zscF2r zn*3z?E@oWfnLYQocA!EWfsr7>)!afz*)@;Zhj+?L8s)EVq;!3uc*{7WWsXY5H(|U} zuBcDSE7$m4gKLfG&c zY_4kLDR1EQkKqR&pMo2HdbXi(>}B`^j=f?mT;kx^3qEiD(?1;!y#6u#+(6lm>7{==gYeRYGAEq@lK=HT;ET?2o_KDgD_KfOFUJ`JBVAD^6sPnu86u1_y+ z!j-=HH7I=29L~I!H=*!Vsm-n3KiCTj$6oL-9(>RI{1`6tUEH1jXV3iqf9wTkUdsP| z{R~q0Uzk^fN)R#GAHz@OzZ-tae+@sC|7rNW{U3&(>Wu2Y3_q3s7=CL?AJx>L`@3t~ ze+<8y+sl-P$oNMX;LRO;e2O|(DL_#yxh|53StH+!Nbc34M!6aM>c-ouKK3NZYUW zWnRnS^QWYN$rp}bsQs!R#S4in&E3x=VXkGlj-#&45c)a!@&U&stBVc>e}&tPK!T8- zD~7Fi$ZYm%VGz6^y056o_*y;*pNV9B8Z^~kn&i0^Y`~&BL;JU-Nrm^LWUV_d!-H3s zugF5WHcS)*@oGuL1TQ-Iwn7D;XB#HN)4B8?ZlIen~>Oaw?)`U#qv+)t&9tU#DlY&?q5f1=KsTc~2pcA@)W zar$kux#2G|WLC3rnUxJXkvz|4?*%di)laC$;LB}Kr{_cNZ%hiaExN2~QesssY6)cD zYKg}lSAS;r=?OWEuJ!mZT(*gGF(5}>RzT~1-NL>3S*_BLHNk`)L|>r5D2h}o$)Cj@ z`FO56h)OR*9~?19rd3v#_~~K&HM^#Ac`WWWM-_~dN74)0+xmzQBF)-Zds3xkLYh(W zYAUB2fpf<4TYjqI22K(J@N#7MWV$qVxX<1vSbX{u(Si@Iun@AMk-Zz`m@LbRx`KjW z>ukSzHR@*2!PQs$)^7jr-GJljhx1nR`fem#QI3i5(TBva`bD+M-(w+asc81=R-nj z72}ZHus5W=faYZgzduMRRTKc^@3kn^CvihFi<@s&izn176`K#kOJ2Dio)A_joYu^> zRc%H#TnWvdHugeiyk5gU<-SS3b@sHX=W>PZTXwSr-@X=y|3@908If^s$MSV%Rcf?R zt5|<0BKKjNxZF+aG3WDEEV1bA?{Cko(Bo(G8#-cL7`$y_V$k+6w)7TATD-*vOCVd<~%!Q389g(uo_X1N7vGAMtMd7#4!ecSna)|+Q_YD$4tqedZNFR+r%%5KPO^B*c2GJR?_jcr$bc`9UI>{{W+8YSx zrysP$Iegufxo07~KbFboNc!Q=l;vm#$(mPxzA6uXO|Lq?OvM1@e>FP3uTPC#L zh>zUU5LEiXwRSn)Y^%_~m@b&mDvSo1po!T+6aix#K>qrU(2!O&snF2GC^c!=7^8@W zV1nQYJk{)XCeAhOM-NnG>amrwOWlcHAPCnQ+0L7kfC}MRaUdqfo*^arQ{>wP0Q_lg zYceGGd^Ugl7a6v{|r z_|x6SnBrLn5&#a6LId7rQM@o0j~G{u3{cDA<=+3GRqRJ2s+J9m^ARy@QuUmy%@%)E zq`=LLoJRY$2>qwHQXpWa_(?7A307MCF{XH?^m%NFK6Z&lQL$>7fDg&jTSU!%xtR*G ztTL;z1D!mMPfRUD4JNq5D}| zTf>BoRn?~vN9ee!NhP#Exhn|Yy6Roj&!Nx%mJogd_>0IGpj^du;H6U|pl>I%T_aZ_-7e@e z0>lszpL5`5DzDQ}-?m@9M}QIVECQL3;D#T>)*Uvkf^ACDK{& zLG~+VAUKx{Mf_PPhd)hbW)GEORk+CG7vdQDeo`r`0Qc0dRL%2{cZ!_m;T%S{Gdf{Hb2jV5ox6(#3?JbQKGO{-ZSs{X)K!GFPa)tG3z4%R3T>3zKYY)p=>d zTXHP-Q$Y^Z$z`SH91%@ZRKj%;1>^cJNJJ4S6T2{Q-3~s^3Cw`wzm@+SF;)F_Kiyc5 zy0+cGte72%`;KzQw;Fa)9GFMHuii5yg zKfJ_NY!eYNU1vc|Ri5bTr=%t6=54N8;g~MA?`4Kmd!=83uXMN?OC~HWi98ohqt>WW zmJ4_h_=F!mhGKsfBiPW9l?xm&D45D!?ixpYrh(goQ`~)Ug?B} z;OeE4eZRB3smnzI({UyFDJn%`wD+u+_Y4Q~)Em;sD8qmP!Qa3jaOSgi>Hkj>PXkScw82A`k%ZfhfPW&OD<0kK@36T;B9;?4&}}|YlLUJi z6jvR@-(vYfg5ksF zg2c4X8wk?+gTgc^toS@*(4+!HL#p{e(Y#o-PM{iSFsi0+CvFJ%78GZubdwq6JrPne zPtX_SRuP2WF&~V6nAU3V21TOCal5fRk(UJ)<)QJ%VDwtfdF~p>?2HMkwP)rLR_UOh`nl8I}lhmljKZ0P(LJIp`0G)}TKOijy zEoIp`sAXJBMpfF`IhHFZ%@g-S>|I*Gd~9H2y17i+OmL`*EV7)a0D>*Tte@49R`BXV zM&f*`k}X0D0z&U5B|9V6%|7}4z9JYsbKN}s`JMkZF7ORU#-(%GM-JgTS!8JrL~62Z zT$j{d{%lvY?3eH?sVFkiz3>q(7CJFIg$u%U5+ai=43WdOYkf*SFSh*&jKVb7bJHN;1vUSj?)%&r@k@Ae7{I5eUC(NnrCpI>uP57oZkAR zG3l9{zc2vEu?~b&Fr5%8B(L|PclkRqSPt5O8+S-*7I{A}ee4#=zuy-)hXmM|r=Je^ zA4dYQ#>ufFfyc^)`;0la6Im(SZqdm_ly?}%$BB90PA zx?bXs)4235=A@yJurn3FYZXAIOW7yQH_9Q#YqvtaD$10)8~0H*a+6zTGbd7M|7 zWdLQstB&H6e+<9Hz_VyX{bafm<+p+17z! zTg_RREnOd4cwa_B1X~UoC_5g&GcDu&*-w*A|j2*Wd?YEd6 zxQjUS9qj;H0KGv4#&A5=Q3oz-C$c;;_A)tfY6rn^ItxDXlK=uhhmQ&?fs?KaHi*-K z;?E@1^=i3`0W0lC46L&AO*i8a4$l#eI)qD*wVTf>buAM3HlSHdK28-EDRQveoRKLK zqeq&eS4F5-?Y}4S{>{9;3iTQ3{%;JMFZX*q_Ipu4e1sr=x{v@jNDzF|yaf`v41rIY zM^X$#3;mDrDMfPxrVjY{RKm>qzzyzTK1J-TGW)8JcA4t)G@CJ7r`}0Hy89RpM1lezYH3Og+$0+%W zN!oXlFF#MxyH7HvP13zXVE$aIqFfIko@yIMAfTRtkv6G}BT#i<&Maf#jU)2Bn65EE zB&MEjW$DS|Kt$fc9C%D=v7FxSdE0gHL`@mXcvTHBRb>f>QG0D=&T2wlpYYwNi5;T%=p+_qKwOUdeh zV;HSc$~>9c=*b-Ind2PU!+cx_fx?G{Q`3dz<)WLYjFX3|RBX?#R|}Hli&*yyvsMJe z8~~s#Lh_4h&Ml;pl||2q+NyU;<;Sy2j{)P0bIdbK3BQ-P&qfc_#^_VJSSjitWlOJD zmPdat1Ak94h|Y2<|* zEDV2LJYL0jY2e)g_B6jy_}s0huok}6eIDIp^sW)`G~H!8NOOcp8i~Mmn*C(Wcb2`5 zb+UdrlE%ckfjzoBBah4!2_TIJ9Lg<{4#D9UDmBi$)L+AIhXVQ4)5b^9YPM0BA>el{ z*V7knz0uGziJ&wwp_5v{6QuBW$e81_nABXfhdA%UsifI9#Y?uO!nZ9Hkhv?KecY2O+_ziN-k9UYIcg@&#4^N1>EF|a=jC_Fm-w6% zYb!qR{(Kr{$^xdV18(7yx-}qsLdE;ZM*=%Kd2J{aC&Ic(~q|zMtH-pSrrA z{saeJ2id|0xq1irPkqI12TQuxRjk9sibF%CAr&}>L&JkL=>vW8&l*k!8&4veJqBC# zT-t30JB4$*Z3cQrq5U|6v!@8e2M5jdM+sQmaZJZkHW~bpK-q@xfi|$?kYyavbwKL| zeA#(^<>WYc8D}$`3a4^>FZ?7Zb?p55Uz{NuZLhIAGWi9-?U7TN#YbGRQku#EvGqUzGinTLJ*cmm|IjzX~OZ{_t&vV9% zb2#u)g#2QKopVrKaEe^K)xUrPuLkHjAFNNH{la?rLYV4OyrKw>y;MSx%*`%cbuZyOLV zHdH;fR5w5LZyeeOzI)yPQg2+?+uhb~b{}rMB3gYS{C$7H>ipULrQB{mrQ9M8-0B|Q z24mjou-wHef#da?K(Ia^4gf#=K&J$Vc)A|Kbym23x1v^=M}2Q0d(S8xm81mG@V+k+ zsVot>FK1_CA$`y(=+9ZdgKs~SQQtQzQ6e_q*~z1IDB%@*KJ@CdG%F>$KH?5V6d?&d zf?MLRpPi6*iR3)nWmKd?Qb~0BH#}OVh{Cydb2X! zx-;R6l;1x?6aJv4rt)W%?Y}dxIM4ruc_pe86ql6#7xT(hRTF;(06Y^{Q>}*w1G>RY zEo~jJ-oMPNrgI{@XnO8%F(AtiKHcUAH~d!B)(5tB|1htf*`)K+KM!s1?*B5c9Vi0D zf7K|_l&SwPuYU|b^IZz<<$oD|Ar$|rQ3gyGR_6^RzzsjQe*659Kcd28U{q>Wny4?_ z@VnF+v*8B)G5nY&a+af`eZ=dEXG;F5QI^bA7<7mHG5i*4G}DSd52?pbe^g%lWB8rC zD|Gm4__3EXWNqHRkOx<8$U8M4puD=RgflNX%m=2%>YbtQ1g1KnjWv5?Y}|%hx(Ddc zsX|p^LU-&5)~VvZhF{E&g1#hq!K{(yhHp8f*6-}99~$7yOQ$N_B!$36z8l1lq1YCvo_lL0M!_SbzCd9wcNREjg{z+Q4%^Rj7>FUD2eXag_rcoyK_!eXH@EIbDCe+FUn#2zH~d^KskvfDvJC<`#Oxpde(>%BjR2a# z0EnXxZuq?ofK2<7gv)GxP|t!uj9HsBw<0BmIau4N2T zH!0eQmn@ci7EUHmq@o+Zx9&^xsmv_s8Mf{IZi=loExs3C2x&|(cpWj6P_2mHpU~xr zbT89yk}nbF=FlbCi!Y2;JsRT4x(KCKdwGBpp5kY|FWc{xGaT*vGkKUjlT*{;b)tB| zRz9;kK{#KW%dQ3AGoe9d(Fb!EOIbC(GiG+ho<*&Sc6jZsJfu!#kEw~a1eZt&>+}Gi zga#t5oeYpDs~Z)Mv1nk&%NDB#ni(7#Z$?|PHLRZ#q%n`wyW-Z8vsQMX%=iQh5nQe6 z92Wr*k7g}P26dv-mDHL;+x%Y22X&yBUfA?7eS9NHh?&9TPaq*AZ^yOvoHgXfnTOT+ zKp7KggX&ez(fJU*f|cA5#~l1QIBi$6ECKJ$Q4K$5O!gOopeL)#0Nm#D*Q}E4?(ks1 zcl=8jBR&s8FQKe-88lIbNwEN8(Rl80tqYUc3bWkVp{vaGYR7 zN|zBB&wDaaFef?-@VZbi0UZd6UR5aCaEpMi69G^OAWyaQ3Ea=XWrJWM#(Lo%4+Ri8s)*O?)X2novyaBC1!G;)tcewuY4J_ulXLwlZgO zig=H}oaH@ul3yW^%H*I*;euvg4nNGBW`Am8_l%>(9A0lMAe-Py`+q0~z#rNY!#4^A zF0*jM3MCojCPK6?vq?q@rFaM7vuu|+)YwHb(sGmciBN@CzYDd}ZB>@?F7sB*isB9A zRQqg;^7&>YyEL2fQcW&d?~{s@0z=S~6oU(8xDTQtEk0)2WXs8y?JE|@JZ!plCze>PK6GvStDEu6TfB!2~?EI?C z(zdjw-o$nod{*_Jvd^EaPs>nJ2duth6#N&u{zF__Xa6*Pz=wy;P*_L*MCZV4_wXWQ zbPk^Nfuq;Iv#M*Ov+LbUu))8xs(%>l>dwdpY~%#ie|omGzPJ3R^7Ax#2%F#iy#RfJ zPpmGUKmAQiA43m*?HrtM9zPu(pKV|K$^9Ik-yhz>{@t4X4S$#WFE8-_+ZS-MYW$b1 z`kDEdfkHw4!M=vkF#$2rzG2~sLCHyfvp$i=@d^Iud5{Ki(S}TFhD@p0GFMVMsrgyphwM7Csr-b}z z0^Dmf9ub6glNNQMqKraLqIhPUH19P{zqFBEavy1OTfnw_@Tb*T7i#U5CO-jZ*_K

^rs5XL2v(`8B)X)7X~4JU;~af4>%4=i>k3Tw*1rgi#r zlNq)G7(v?z@DDDLk@6s!`VEa*>#f<>7mjk?b>H?ptR7$5Zw$eBGT4q9?N=s?bZUj& zwswcsol!ouVAnK^2c;GBt7eP&;%BH1C1e=3{kFMos$=_Ia;2_AUql;eJNTym69e%E z(Y#j!QDU0IQjr+7&9E2**B4t@Im@3S+$YQTh0l3RP==cfjaY`8^aAgPxP}Ec#3+sq zYhdL1iaXz^p#<>jwwb=i@{e93;YjeTj)q0hgaOR=YvIP2cjzs_Cao-+vrddEk6K=w zrioTsw5~98Csv1TVJ9&wmsl@JK4f1tIj%@%+9{#asV@{82R9?aEg#s2h@LuL5Fvgp zZ6s1DD+_T!X4UF2<$5n0^$nNvfHBt$$I#q2qA6*gIc0Trzd$Phqoc5$Xik|c-ytN4 zVf*97ZfbQ1UAl92mGdhx-|NLNbabQ?zlvl8^w>!01K(0{35*``oPuiQEaCSmp!}Ng z=WvdiTkTU;xa9CK*f3$kSnjZGVR_QH=^SkXX6h4AbBfMlAOID-d8Lf>LCTh{%9kF` zs*)5S6jwFR`eEA=i=|o*lR$nPF+W;;m<<+ZD$4q%m$>=dwuj*R(wQ;UH`a5AJ#y?D z$l1>li{|yBQacFy76@nfN?TPeO#!_YsU1#?d)iSR5<5FOX?5QUeyrTpuYMpzPto%E zaZMVc!hm6%JFSIHHdy8q#ywAqvAr;7M9y$MWUj$AzA#*bo>W@b=A_qVx42Y8_L;&? zk{JFrua6^xIs_o`QO!H03rG&IqLUGInVr?5OE%wTXjlm%`=}Y^y!eqY-}yVjtBIFO zY&H0iB(kAtNg#<{6S48dEYaL*u58^F3qWCERP74j0eW66-DTg;FURI0BkG89k zaMO#;OgBG1af&xp!5fTUB1sC`pGYdS8J7JpsbnNTRhFQ4Rz1&1`T97rb3=1th{=8t zkzp*33Q14vproBkGO~R%ci2XGDh_I4O*X;9dGsZ!g7&Kaz~k_KOGi!RB=MGck~aKk zvA72!<6IS`zV(F)pUatdV)_j%BIoWUV^vju027NdBbG8JN)!Z$fXj}?pZf*B2qI%K z79XLD!dBxaaK#iE^(~ipc(qWr{Ha@gD=PfIh zpC3!Z@@Yuy+e9cgZGc`q%zjOwdqX(&JeHZjok96nYfQp?Bqt_^LMFWUMV>fE@uttA zsvT6Vk|{QNzl11_m5&sAl8y1m&s4F!IJ}bQqq*@)AT{E^e4oH|Rb*JH5yQ~@mss!W z#F0{yH-e!fF4r|FuTae3HK_jVqT0gOWe2#)i?c53lu>qNR$Q198za~CQLWFU!UE-% z?`NyhewW#92rO@4Y*qJO9h=91bn1&^8^Jrd%0Y;qmwoD*s%OfSh$o4T26@1%)~}tq zLE5&_ymdqGDlB}n^roc<(-O_UnOCr^jZtz1-u|XBa@5ox4{vBs{>|>iKeUPv=pc_G zY&-9hXt0=HpvP-%3p3eg*;sypkR$DW^C!Xz#a2@9pe(oYmax)BiUIe$5Uw(OA;5cC z=+rytR`q2g_{*e)W*@b%UAU~39_bMGD`5vq7N5tSHet;O$^280XKpRT;#U1SyO)~^=gHWRnr$wI47?_7z?4 zr#4^z$n!3Ne*DllUAS9Q^s4MYjr@KxR`@DVOyN*_Nnp0Zhp!oJWpqTpyMOb}FjEJ|E*Erz}oM zH6-K7so{MmUp@_QX!+P;snzhXq7i@Hw55CEt*5iJFw0%Lr*P^+PLXK5oh3Z>ZqoBY zaOK$=Z#}TB)mP_nbC|v%CTHdJb;;6*^~n|UCFm?V<#9GMGq3dB>X}Eg&judq9b>A% ze$3M2u8lBv8%^1_B%PFU!mk27Q~PNuIC1)053OL=K+UnH z*@n@p@^8PP2H)!KKjG+lftH4CKJj%OhRhX@5fxi0tw(H;Ia;%SuKoFpFWZrCyWz6} zHtnkGJnFYYSlYMLWN&?eY}C)c>T>K(zB#(eUYxv(QF%&Oy0~ctt(=II?je&xIxvN~ zY`aqQrWJSV`}$=Ll0|fu+tmb@WGS7&DR}3y@A=rkS{e&CZJSkrN6nPq?>9@ds(C#e zw+2>SKF2&4VJxtx_)U*sP={YW_wqAI9I_&HCGj&$1-a;!l10C5;C!Z~! z7pwX#%y5y)Ho+i zM)w#gjrtznh;9EDhyfJh$~=rxWC`{(^Zr!zF1S@l@F#W>-7J2u{C{Zb6=^tp+H(i@ zI9(9yl50A5BsddFYcS2Zia&SLBJp@B@k)Qn>*sCI-cN^zJhu}E|4S)fzaVFKGd)kR z!pCb*I%z*$GcQFFZ@D?mg$^W2Tzv?tf8=dQ@lPk&K!+k;BgnN^7C1N+8l1)#M8K;o zf#zir806w;C3Fb{+8PNVgPx=MkMdaN23aL&`X=#x7cK-<^n(^ji0$?~$FKbeO?`oZ zFl>m^r*cRrlu!E;R7=gtFPJf0(iHR+92V2y-GnM@0tMa1hdFCH>_9>$%zgj>$SWu) zz@(38Ns$;@D3lzCXiUNEP`^pXfG#xG5@p~sudt3tfS`dCel!WN zOL-d`C7BdAfRR8dMYRxoN)jZZ;c^buuX6s8rs>hVT>2SP;wfoXU@*!UlUgi^7p|>$^NB3VO#M9_^4L!S*4p{`^%l5E1?9WnDrO6k`kacM zBbzBBqeKF~j^~%76h@F1miAe=kQMlABXd>)J}D#XbrgCY6h_?_R$do=V=fABf@_6l z5=|D|rp4Pk`OGE=?*RZp0|bb_WmGSaNED!4iTKSaD8ML3>l#@V)691BBP> z0P4z;WV!M{p0Z8tvLcM4UAeLhva~zxic$fG2_l0Wbohm9a2`ocgk#t;UxZ;$C0$OX zNPjHuX5}SAI_qGdNnrN<`#6{Wq)#s2FQ=@_8AG#glN_{yHWuvkA(aey)!q~CyM5IP z4W7@T4!BUKm*y$7K?!*14(6gF0z_%hJhyTFc$I;OTi#%M4bY=s?K_g#>4^|K<7$bA z;2g8)ZKhf?xNE2*GUSwzbx_ABRjVA5iPq#RZz*cpTuZP}`{uqjVP2G7I>C`I{gsq` z4pWZwd=+W}HXPfwzxPLd@O9Gkehzi|7LaX$nHS6gt4f~xZj=M2GmC%N3+qjaE=a&u zRz}oEuD6u~Z#L9hyS{O{RnJUu&$IO8IK<0I;SmMb*A>~CI0rf`h4=n9nZ4l#K+{2R(p$QxpQgmHp&ZJF+>(L)lyVAU5XK%K3nAB!Rz>DkTo; zbQ9AZblit^K8%1k2TEF`mehBaaJx&gr7&Ab$=%j9{9iTJcRs_6LoIB0Z|Z}c?U%M&vVYqk=Gb}Ugm0hMS|v8%-*1M2Lujq1ee_JbZiRCt*1mHDWEM?Nn}rrDR*jq}kQx20S8 zp+(ZIdp5pX%B_c7x3TxeIg8gtY`BMBqg$=CmPkxjqotF@qK3nY$FrgLQ%l!Z-5%up z9(IjBRP|a3EBnu0FY5Z5e>Zijm-Zb#WYL=cO-BD8lGXp7^`TBd4-g&nI}$$msc{7w zj0i;m1Bul)2Hjft!4le4R$;Xi1C`4p9yDq-O+#O;hWu!7GygB*-ukWTzi-!EEEce6 z6r`j_4t~}el7OT3jgc#dA~Y6%kVzkd zIY0ulvKq6agLMl8X+|`p<0y~uMt-x7Y&UlO#^S|Y5yn~5I4VZf!E*+YkDiAH@7{^* z%i_25Sgp0?w2glj9->0Asuo!Z+T1-eDyb_mt z@m+-$rb7}Ygt2JS{;6kPLLbcmMZR$dO(?a9YLi7DXEBRu( z;9{rtVz=93Z|Y)y)8gRYWObB$XYFQy+nM(q?JtXt{-ughhN)huXiR(`WiJ$XJqYv2MOd@}Fyq37r z?m?C}DAYriYJG#r{>?-Y@(M0N5|8>G@68GM>eCBMqlp2k!BvcWF5}SwEL0ynFI4T4 z6`Eyln^k1?74T{df}Bmrf`elHMQKIuw{ri})!15VHeandA)BX?8 zyK)f2($@X?))%4e#LwH(W|G`3^<-UhmUWOa*0ixT&13dr<56EL3YRtS zN=G6$a?P0Pp`5QyRXyytQXI7F>}%Q#bhsbvI--E7QRUiqdLItHLLt)8NFY2A$tay1 z6kw-%^Kl|j&4dqY^bgGxQ5JNLp!uk}de4wJ+qagFeDjcZN{I3*o zhub-4`njxvjT{_B9}iVy6cWD((crvL)4PaVf~dhSEUXuFD9=ymQFOk%`b>oqYjLS{ zNay@()-~c%-ezHO6iL$>asE3V#nc9s3ywreg=`#&szKEkJaQF|du?ii5~h6}hPaCQ zer@~xET9Evi5`z55>yif;wbwSW^t2`3o0DBaX-8%Xt}{0ncwh*7|C3&R8xFUzi~Y3 zZEm4M$Gh_oyu((ytNA|fzU?$HVqrqjH)cIMp|G&8j|_MWU+LYQ(&Op4KgFiH4LP{~ z!2aMM_n>R_P$G9*W_?RYgeSJLi7gDte&_{1LaZntM&68Gav*?Y^}k;e2ALV7gHk}~ z#%2isJJrL?Oqz#BIxpw%n$Rb&ps1wcF99ylw5qV!%(VHRHDQ>UL29Z&#=t~io=NNY ze_nbtjW*LKWoCCJnRwdmBSu(@w2OIKhxJQyKX?pM=~AOXd(bRl}2C_ znZgrQXp8Az>{MV)2>V6wSVfA?Hk)9zt2ZV`_LFem_j@oky3g}-aU zzsV}VPW`(kEVM0{$WzS1X=2)2d{?lYZzkuszN{+2FSyt$^LI^{-b@u$UGgzg_g(6{ zQ&EYe)Gw!d_k5R=1r64JZpK$hx(0su2}|aE$NHU$B=6D&al)9M%fyN)X8|hq5m64~ zWvu$j_x;hVJWmhVxb|ksVvs@*Tq2{sjJpPgDcZLqhl}+-ENhleFW;>8#+WNlEL6*F zf)eqQj>+n+c75`VD~6jISdB+OfhXa3cNHfaQON=E%}p*cX1!2Hde6a&%e}RcUmp-c z?%g+I#y>qEgi^gsGzScx&|G3E9B&M+ophg%BE5ay*h=~OE+=7StzcTLT56uw$W`jV z3v!-J)n{qMG&U^Vfn={f&7x(6_Ft)F>GG;N_J>cMGtznL1oCchwFaJag-KS&e&S|+ z#k2_|tEQX4xfV!Pwd|QRNca-zw_w39#kUfLnvAE=J&`sylW#W8z<_{VBRDnWmf$c)U0`p(2 z&zANB%e%Wn;*$EeZep7MH`j!xL%iF6)`XV_e^u;fqhdssXJb+fC1>NZe^u;~Z0Cr{ z4{Da@Q|ccFy?~DFVHF+3Qf_qi)6>ku8I!ky)w7>!mh9(k-pRdMuqtx2Uv#9Evq!U^ za$8(-LX$sRbemzjT9w5=x||Kfd9v2T~&9yMMb0WNklj=SSdz;$)f`=63kj{CDoHS7EH z*92Y{N`aGN)FK)xG`1WK6+55=+~Aj? ztI9@r)aX-s{x}qCK0TOt9-#z`Bsziq%|7~AGaW%Du7xD4k4AhyZMSWv8h}Sehj9~Q zI;rYP1HJXAjy#c2=)ihlMZNLld=qh2vq$!dcRmDm4j3GC)aW`kGztBV-P|}Q_MBu{ zN1k5TuT{~BcdkMXi6sMhg*d>{Hq-cAHj#qOHhA_BIE~@sZZY=XQM9IXbPRpO(n`Oh z3BJ$)?9@m6X3;Tlf*yvq(lUOb<+1sYUMA%}fE8FCS4P&uGV^3WQ_~<`om&j!(W76VApGx2HKRS%bJtiIQf)r zGd3>&Kr-qtFHUt4+Q~P!%i>1Zma$^MC=nnY7bx1EfWMS0W%_zN+Mb1l-ZDp$^3ix~ z{bVvnnCbUVGRmK)&vJRSw`873@iMQ zCo@&3d0wdQwx^g%7oNuMo$?WTpQ@i~dI#xcemoU$k}I69;+iN5GAa6)?4X*dDq3o% zt)u-JNmVqG`g`{R3(X3t+S|J)WmRIkbjQqr9W?d`NAH&qDcZK#4&Z*<9AZHYbqQ?7 z$&`56Zo&L|L8IeA1S{bQ8>93>U`yt!s=}dEBRl=M+4$%xzg89t%K_=d@TtnM%|kPe zjD-=5nwsPs3u>~4h4qK>^6qa(&joMMwq%H6nx8-nvs{*>jfftVT3R`nqiat}D5OYP z#=T~`Tw0U)o=POhoWI8888+Ro<$z-KE!Fq~H`Q5#uBYU4)0X@IdOk|%4QM5ZfkIkH>0l^YS?D`l)bH%%-M`gi=%35b)zu?5G&kM;| z*FCEtt?rvvv|1@0k9&xF1ZBR2A?=0q%J4p-MX07l1ZXjnzR-A&>do#=*|z?Ztu7N^ z;<;P87V|97cTrjXadLNS=x#RKrzJ5FxXAzcc?6G(q>xzjPm5;Wr#ypStDhxr%R&XV zNt~O9xYE(ye}03gb7cz`%c$tzk>I}>iwv*KW*C}$J7DnLOTzY9Cy4c3!$^~l5F`(C z*Yue(%~Jf^2 z!_u@lej|?)k^RVm-{o*k^X1Sl_uHo=lMgkB>jO66XnVH;Rj6$z8n!Xhd-Bvnx{#Kt z)SvS%bj^});LX{rji}bk2!mN!(s0s!qMK(Mc~_Jp@(*ggFmcJ`>$SF`V5yg1k%Ewp zL9y=NaB_}1ws>diNR!Gcl!ZmWAmY{#F7`M=Y!K*iFF=HR_%f{i2=w|AbtKHpmRn13 zpJ6hQw9)gcJQf^M($>!;bNp3aiYkm8;RD{1zpP(aIwC4_azyolM?1Cx+a1pas8freBXy)HGTv~m_ z8C)2K)9ee1n+_EN8jinXgeDtm@6a+lD48GKr%3wj7^roO#Wa7d;3eNvinyh`3Hh9U zd9v}GsHG4A`aP82xRa-+GZpZJ`?1~cJni)wD6yJ{lK2Xuv7L(Tf;B zz}0$@&3aK>c~KF2)9`xJse98q{ukjDC$SHyC<>Rl&nsd)!S{|l>fEV6d_?S2UPk)} z@$v^f_f>tXEiuan_w$twe5GFHdpqNs-{GrN%Lgd0Bpp@!@%+>sdEw`OHZk(2zPiM| zrquo_KAQSaWc2^)wEZ8w3=y?|*=!XIy#EZ{Kl%I_x|{zQy6gXo?;K<59H$qaX6KXo zPv^otEc;t(p-%O+FTiw;$q$VCm&7(IwG60Q#K9{PvH*Q8KywDF7WJ8VW&e!ZYwDW< zv&WKZI+Cka5?T;I?IP!UYi?OvVO2-zU$XPRu+A-muvSF+Pefi@e}3CQP3v%d+fc*b z-FxmZqI3uW|M^fhf+!zFWUL?>cOF`M#yk6`x`qJD?R4+R+`!mE|J?FFqT8;8hk>8> zV>2sLeS9cb9ker?&29w;zBa2C$7^-TW)M{lkMk1%~lkCl3G;8mM6W zf3S@QdKo(Z^fL6k_5SH)Xhp}w#{Jh`hE9BLY;e|}_GFrO-j9OP$|^vUkXum=IBlD1 z>*5+(x+?X<+v9_K^@fH*^v5T{CZ_+ECuiIG6Lf|b*8x4k{PIt4K#wr*u@vw-`SedC zW3Mwc8`h0TioHgb8das!zr|p_ivkQeN9FQ@i}>T$onmbxGh-YeOUgLoza?-actcExIFgb(?sE+gKEiw#WAAvnmhRkbrsLZxd{d?NgO>dTGj2|+e&n?G_cK4e z@YtYKKA`JuS&vZ>M?GS6uzH4{wiDsBx2|IE(zmq0t~e(Or`|N@-&H2zgs6CMuaJYG zs-J@Q8@zBD17B)iC=JwWm9c`r6#iB4fp`NENk$q2IBij9={OYFfrmbpD#@n7Q$ims ze<4xyT;o*J>hZ+kNcuFDf*(@r$#b8CTT>)jrSaW#=OjncoY#1v{ybDbCkVQ@LM0Cw zpZMhAg`>HXp+4Q75BDW?{+wMTyO*B>qhXTBiW8k@GEOrg-OFM0PoPnUrRL`*<<#i` zvp?eJ+bOuC^N-W?cbIT3t5zALB4YXa>E4Kj_3ILMJ$5cGPvqjy|B)~Hv9NN2=D4`Z z{}F#l#gwS}s%@`h@?rJ&Bm(TxlaLtJV^`-=@BTpmrzSNgPo0MTyKK`J^XDht<|o^;_?pQ&tAU z{D9f{HUx*4S7f#Mpw07F3Yv*m#k*!9@PWp~wQ*|=sxPlzdG8u*lSon_xw41u6z%1> zj9S>rl#+4DH)RP!xoR{G}0VNL!R?Z!;#NwTunQ*X;7m}Mt z%_VQ+Lq9?0H>5#)PZ}}os|@5fu0;0tFT<;$neIci>#zt*%gq$yQYSIEE<0b%Xe>_a zx?sH2TCIMGDNf^ybK}cO%pE~Tv$rMPBQ7WlxvT{)y(0Uwp^zO-5y`*l@!t=H;%Z#Xx z{CBjT*637X=Wns^m1@Iougw`ckf+B9Uttn|MIwnF=(M5w^cLH!L{;iozY9hMahAhl z_N@0t@qj(T(r#0fJHQ(dU8}Aw82YUIRnmi7Q4|CfMy@xcmQ!Vvuz*-Q-ezRzw!%@s zXX1<@FW?fkj4-y^lfaBCWVGYnK%g-a@!@3M4;uYQL??$uh3CgB8f3Fdy8Kf)Z2g#$5xb@(;890JX{;eL0}Z*!c=@C16unp9(W5Li z-$l`#7$)R9iqEuR!8Edih%@10pGcK;KOfK`&L$W#HW{Bxr$EX1;}oo%mF*B4^dexH z#4ji9k)JZjiw0w)E>iPfu6^B3U15@N%8W`h8%!sHn-Y=F`FN7;ZNEgM^VNlbr8 za6ofY?Mq>+@>F(*m#`o{P-gPkEAd=$lH6Lqa|Lxbf=}*S`K(dnTsfp~_oQ)2heW^- zk~!D8{^c(AB&8>*2Z-KXxuuM$l8fLx5td~)95l}GLay*4^&Gv>8<`y2fs%JQC|YbA zN){3?f}6zfjRrSFn&QzzUhEdC4N=cJ+WMund*>Pu4g9;8Vc_xOeV^t*pdZ zA51OX5An6tY;3mX4I}Sa6KcX)`_$9S7lM=$s%qV+B{sik&stSC6yLKuD%>udM9+wB z334b;uxR2}6-OPAmwa0v&>+=Nj=cZMO1$$_^W^ts#U{|pm|@YI13m-n8%hvf%1TUN zPa#(G0m7B`VD`XPsUie!V|-t<+HG6g5rWMb=!Ti`XupPt-pZl@Z?~M_g?&3y^|86) z{#svfZ8xR-Ntkx=A}LQ5p^*QUkKx`52^vW^y{eoVWrOaW{B)nt@Q2qE5q7$?Op&O5~BzlclE7C9*KXJX) z7;(cnb3|;Yeg?|o8T3cLb?I=d@B?nmz6tdi}sr{_$Qf~g{-yo2* zt;2@WEpK0t+%zxFW7%G@bmoD7kAH}>H?c`EWA&gO@6balokMOp%9pUQVAOSsM~{j~ zTDUq0)ODDDiD}bezA#ev;Ls)be5U?;=I`ltfy%9d`bS8 z37jj9>YMG@h(_%tY=<(B<=>m<+lP|dzhi3zF6b!l2i@4`y00JEyi{oVou~CXJz)0m z=;B2e1NNPzkjGIiN8naSy^E)P%SBh()wbyyH{F{~~MT*!;|Gp8m^N zjVGFv$72Sk`)vo>C!UmsN;N$W=(7&;m+l0;4vvJV?_0q%<@S$weN2or&K%rE0}x&z z5)NTJE@_uupdW5oG`@Fq-sC19R2W=K13b3;eL`Mhzor6NX8DXs`l#~iRNMR9eD(>r z^t8A%S>bV)fckdixfn63G39%wqS>R?dKPV)kK_6IeA8D`4_K~prpxugBvSN|@b4D( zg@FU7&U`NH-CNaMta>pRssm>UP~Y$PUm6EQ_v(&r`+W?w9!dxhfH}<31yb$=DT9OM zxI8^-Jg$iRqw+npuN=dk__4q&V~9gmx||E`twM-At+%aRc>LWRy{H}i{fR?^1HCu4 ze5V~8+XCEG7()hYwQ6=;_0gQjh&3W49h$GcG+k-8&Z;&_d9L)>FvI-ist}w_&Q@GDTyvIy2}&du(}-|1YK~gWHj1Vq_3lU3ZwTk z^{BF|;M>|LuD+=6m!VLN$fvxnZoQHG0nw5ha>u-O2@X-!d0yn|Uu|prw|HY@cSAdg z9Y`46qU?Rm8C?W+J%kG63}H&rP-pZ+|H%NaYpJMDbFoH!eoYc?uVy1CW+PM`!fc%4 zf@i~$B@-6&qS>x3iA;mja>Cy^#d`(?Rl(vLb0b~U{q*a6@p+tVUn3GU3SNr8j%{~{ zHOY@=%J*2Ejq<8XOnKt!SQ~y>1EZAwB1@bYwhL>4CAsc~^#yttnYdpYyU3a7rOd^0 zse4e^hsMET4QBnnn8Nac+$29Iyp{6yQxDTI{g$_r)an$=ViNvCBe{wswbs-$=XEkw zT}p3XL>p7eqEy7OV`RIOUf*m&5>x6#o#wVvP-H^#cYkw#3E+2w`R`qiI@I*Wt&xFG8g`=rN3T!E znup`|XHf8EqBy71IA>x9o7~o9F!80M$z-x=dYqBKxivE%Gb6G%f-_&3WeF5!fC{r- z?`0wPr}^~h5cWI5uM_#zQ+3tC1EdlaF-Y3aBhRH$h@R&x))CV)J!sx5-ryFR5hG^YKtZA8m(i2go?;})=@^BvCSD=)*@BLRdHLE)}9-pFy{oCr!ZfP!f$gimq(Hq5wjb& zxtq7ch<&api$0wOzYe?GOExDYALJ`Vb|FT;Ekp|`quwv`fJJ9Jxs}NjYZB*E7Pw9* z{zxX!Nq-U(F<B^e0L14?Y5hWS0)!`27A<7mPBqt0E;H?DrsKeF6ok`jVYG zTX=s?Cwj3pW90a#r%q0lZ~r$v{&Mx}WNDsi@uXm}I@k3I_f6#r6HIM`r!^kXqNixZ zpJxk>ja@xFT_?LMHH*G|;ji^|(as5YMXmG?<#{01hv&K9Ozj`avx}eK3@h{)E$ZW6 z%Jb82_m7Zcy+O}MDbro*^ONgw)Es4KAW21kDbFkxc-eKy{C_FW<_7X0aBjo@lJd;o zH2JY<+9g-$OOxL1S5v-(dH%Y9eVS^W9+Wy;t3L{;qHqR8`l8c$Kc7 z(REs(U52-{=(OE0q`URWG)yeIefB9K$83pW_Y+q8k?Ob!?PP>6& zZR$i1_`1i3rne=e$AAj#8QSYA+dJVT@R$l|9=Q*nr7t#A^xUs+)3DF$qsWK-zCa$j z4(`s9IFU@UT76Gs0c|x!&|Py zJ1N6^jl&0v!$)_+|3P`aa2>fy0T%BgcZ(wrcOyVA11vadzzW3#ffvO`@2bEU@Pb!? z$e58v7(+TfHltbGV~8p!R#WsQ=Gfz~u@!MBq1zahWwu`HD2^PA!m{ewk~U4)=-$G3 zTNjkkve~s}{2jx@Ko{2Y(SEv;iODC}5}>Nu(1Icc?Dsav;(|58hvOin{`=9%k(bnZ ziv50{d@w&vd9zGC*`wsJK>}3HG96QsQ-ZqW(@7~BM%dE^mi?au4OrmnU+$-8Ue36G zno0GWag>`Ou&*t$>v3KB=q~s&<>jm=`7BB`qC1dnmLB;{#DRKn(`*nnDr|r2uf~Jit@f8;%lYvv zR5i^dRxMPLLz+_;B6A=!oE+aReMr1JI>WTFJ~gD+_alu950Psy>MhnDNa{v%7KUju zXhS?dE=8Tw&MoQ4m4V0Dmc!$~j5c6l1LTj#C={H3OaTR&%)1W&bpiu3?&kIU_|<98MS*`)o+aEjq|!G2 zIBl0VyWnXzc-Q!|LcJLx2(dxiy%SJcyX#D}D+~rsB zOVCYP#~qH`1I5tv=wZ&ZO;l=qSQw{R<1zl*S%V#qYqFU+*jol+nM=+ag8rzz#|kOc)# z)Amn=e?mk(nlaB#MSlJsXgo!Ga{`J!{UFOB+0x89*gj5nqJXd=@kDOj2UAgXkB@?j zqn05EwD*xH&hneT$5D{z&UfucTa%G+^}6*Ukx2C>2M#Dn;UEk+QUJMah|TDT&hxJx zh`2{UsLoMTw@67mDh~EUQu%Hjs)xj>c(qs#b{dHZ;=pG1T;4n!r28c5^~;9qIftn4 zb&uEL#Ckwrz<$2<#bC-YZC;%k6+{#+R`UI3h#9pe{Z`1r39r|*IpVgS#v0r*K;gK={x z9futELkffUC%5&Kb~r64<;e(aj_3cEy^Iip#H56j)HH7cT`(vc1lBc3|GRki$jHjc zEBIbr15lm=e&polHvn6@&aNmj&hCB$%z(HYOq@6{FM}JzUNhpZN}N^MP7V;ZNkeqxVLq-O`*r&HyOS z=%$5?Y=4}#*uh`Qb5wg{;`j7}qH%KuoS1)9x&oBvzl--jPTP_6|J=&}7Vm$18Gk9y z|J~xc|D`m;;OVhD&d}mJrHcOaj-ZJJg8^BY&K>$M_`?3c7c9 zH&>_oKSx?x0HY`>GOfb`>UN5A3O=hRbK*ClT|-rqkLfTZojh{K;;iO zZRz4o)`A#w^8u%A_0F39Wz(OO8n_%NRT|i`=^&-wVU=NmaKppS60<@E73#-T_wSyy3fc{KQM?ISB9(LQ z^+uA_MZu<*t+J6jLR3CV#0PTSlR`@P*fxV$EQ zjs!8@UO~Rq&62BLXkbB3K{xY$apAaFVL|0q;cj6-<=$Slz9*hIaXq2AMF|Je(=O;W zo(pTo^ME_Khm=%8?Sv6gk!#JrmDX6-s1xC;>N?aRAUV|U@Y zzWq2mLVcTB%h5}CJfZ7<)q{TdGTR+&v2+Lh(h8!-bI|ThN2XM7fPy2v3ty}d{tiI2 zVU1h+{Mx758#e~PahzW<2_ScLj-nWk${y2^bwWPE>WCj!y}4sYF&S1{pu?O2u`gDT zykPavq{zUy2`aQGm>A+mWROU9I#z}hAEnasU@Wq=Cr|U**u1U$B+oLv?H!xM?i54a z-mTsiLxY}W{t)_<(n<2Omltg~D*W5T3i-(_53PSx1WIrgjlq?eWbJ!QPm3f%h71%Q z`e;d)uVS<{l6^9ozoTJ;|7WKyS8T+AG#&o)z7Jq@k0LQK7H#ytcZ1RKkz#suMoi3F z^8u8vvLPHUyYEQYem^Q1{P6tLsOdA`Y2s*TuD<=Vp?bv2ilo^=qpzg}Lsrgqy#05% zygk=X&7$$876ptW7;}cH^b1puL-Pc-rAM6S?cQuP<_TT)jkw>Orh}g4)s&(5%h4FX ze=_e}F{Ib(?pqqpdn@kS<0hcz~Wsg>Zm)z`>I_$hcGC> zY8CTLlu-Ellph8J1j4pyui9}`dU$<3281I{*7)q(lx`fBQ6HgP?b2Cp7bRi4r?(a#(#sH9Svs0PQy9Kugg zW~|_qDhp;zjm-XGMoP2>idJeZnu-g{uXtc)`yUgTXX3**zX_3O;p6j999;{zlSOC!_q2V70+D!iK9Z&hQ_h#E|!#~0u2G=QWuX==WxB}9sHfWyKJ<3s@R4okGB1b&e5Z+ZTmrZX>R(jRh_u)c8 zJx5@Z^^Ng>7HU~S4)PXfp50)@^G&3I!Oz@p^Smrn%afBWwqA^oyvpVFB^q?yroVj6 zZ)UX;S4Z|=_yf`af1va)e?Ual0pJgaYdTA5yZyr)P&V>YHTC~!8LVp)rf(Nv_%+hV zG1|l_#`dqi*eE&^&=Z>h5o}9_;=I|%c=r$?zDo2%#!A` z`Yu3LTvXXnT-^&q+9kEUe&kHPr#`Y$fv=IrY3e;*eB1d9LfegHZ5J0RzllkG+(2KX0Z)V)D}RipmTI+`l&CGz_+;wk&!7&h+j~Hmt%o~3C9qj?-GArIvKMaa=38_gdat}$Le;x||j9>TYBSZL9WYb$Tt3QyS zRI1mCdT$4lIWM1&OOL*9N=N>MzK6CKBP=iZqFyw=ayQ>!KI>H!W0jeBsA>osR>7c# zR0M-y{30wmS=DmRM&7&tcrqE2A~1TZPO3{Q9qFC6-exQO%93(T^wrx&x1q@htf(fv zQ~A+N@{*LF(1^AxCMxDdjkAOS)M%)bPVK2dBJ5MFUSgbzsp>)H6zAN0>iw|4RvoTM zOBeqT$4Im5`Gf0kUupa`KZa*0sll~hHU_czz6?X0&$K6!1zKF28uE6#itH{aE@m$c zCWF$KlwV^Um1;*+J$kFuM zDhWodcw=iyEwd9c_riUi_K#Eh_XH6dsLnaTGJ+U_qiKQ`!@g0t9yiTs@-TG~#aP^* z2g+gG^!b4v3)OEv6-0i#^Az!gjtuygLW|VXHbDM1j&CQ+hn^ElTD>C^uOMNXnvmmJ zw+Z{iY?KSr&h1-E(u&_yd1*U-MXFgmm%ko<{$$q}>SY{K-N-}77bK4 zAT%SP4;*-JlH(gAezTEnnLDS2A1#WWnU`r&zl)R=tr=I4Qb>xyRUFK>oHEmxWURS0 zm`51lPbmEs+|=y5^FosFHd#1CAgVJrnSLxcN5v|iwL*b!-^^}6$^5V?UAD+FZ;^SE ztzyA{zpr*E++kb#XwGb?zP3DITaKw1uQ;P+xncY<2=$4UFX$HmXEXqm1yw*5&D1N! zrK3&p(X5j=YqtyxI1%jyNiIJ+Nz`P=x)tOPp1+_%rs87aO7n|1HyEp%Ph%0uOKZO0 zd}qghXAq;1#mBaH{2t|vmuM#x?wR`@Cd0x#CZT-r{L9;b#j{?2;i0p!4;-JWCe<5~ zhNkHisb4pQDEkIJKA0fwUl3P807So0>0n4%xL5hIn~Zt_S9`QdTzUhjC?P~wp~j! z;?pn;3FjNMf7Ek>$VG3JZ_unr_rMXUM`JvW!+J`i{y0&X-*w#2xQqDg`>^oa^U^}u z%`3@A!$1venIu)xQy7dA9RB%8MuWdq66dSRKG&Z4yBn^+FvN}pM}%{_4fG7(3lGKg ziuQ>z^a?${%!V1?NnfIDJau9)lf^MuuTdx_o-fSD+tN@J38vz?XM^X~%16Uvkyq1% zmZvX;)L$t#ma?CsLS zw*JaQTe5k4Mbc^C>g`g;h`ac=HRQh*`=?#q(LWuF8gVz6V0XHcJA$l^cq`eZpvp0F zKPpu8na)hcJ~!s4-BS?B_0B}8%H~z_e(%wqoplY_c~w3Ki8P4Kpm$@CQN~cvEc=>< z?`HbWm|EGP**q+#XqWFzp|aftW74xFdPQvgA^1gQ3X5Q&ka@<3?E1=r?K7MYS%nyb zvQJWC5v~!W2~H~3zblIn#UY1{LFi>b+104YNNIvuF1NfYU&)Pye~ekp^rB4Qq=4mR zOQG7r>Zjs8ZZq8(X0`U_sS-DB6D|A(x%!K5+MgyK8D{jUH3dH@JAmwQ`!K6Fk;a## z%dr^XKUE&*n=U7-Go7Q~S99mO$V>jrrYgy=KJR={`Hjue(v)w`A?`?`xWqzx>G9CB z{)<|f!voQmAzE2{33Z~D>|f(<7dJI|>St3+?Q>j~_KXs$mP<+oNzl3kOSz9z(ymq zhhhjro{!UakFVN^hs$J7_tCrR9oib=P#i6j7of>kt#8B1{Qta}E@LZ(tB&DbGJV0E@&Hg;xyz$estl7@DsWy>$vYX7x#NC4Kw)7H< zkoebj#HJ-pSr8`C+C*0 z`W#Z>g~FQC+Ds%3(y`hCSFB-q5R@U0%GXEh`(Xd z-=+;zc5-0$@pgW;x*R{-a?t|d53JzunAfqHe@VVw{F8If3?11w+%Em$4{Xc*a$dMy zzWR5U_4X$Sx3(2c{y$Y&kN@P{coDUo4Du(z0DpjZq_&%9_$1urZk-CZu2)k2H^3j* zU{t89-zF1hGB;;PumkW7EM9B+%&>$%YA7kVy?;{>)*sO6QPM!>vGX%*e zy>Tl<9`F}afUtxw@Lwt1WZ)Y^U%=Y%xO8u(5sRYr_Du&Kr9S9`f4Z#yVKZ*UZT`2- zxR>&Z%0$?+g+aF(0{3Ff;fo7V1UKpF0_*Hn+_T0HZ`Jj{QjDjUGw%Yi z1X_9aTMDV^B9T-FtI*#v3g1jodYoZ&LdJQh?ioB9K7q58-Q_tU*dH*EcRZRqAZufc z*p44&kiD8Gux=m}^BEMsxxFqvQ?sog0be-bnwOp*6*aGSR;B_Kqc`2G7d@|rLL?Xp zl7s4zWDy~J)L#0$yh7vYbzbT8c@^lx*QG6oa3n zxZi7H-#Jls4HLiOm(Cfs0PEUM=St~^H}j`_Ib%n%&x{{!z`m9+C2N@f9CyGMs1bQI z5=kWWd&dBZm(EP^047dY?3^p}=CjzczGmHgxzZbd)%3oHuMzJ#5-BY!((aUmLbK8@6on)w>l$ z<%xjy&q8R+KpQn5q9CRNywEjX+#VC?HY|Lt^4$QHNv9O_*Q}VYUI>gcf=@yfRu*nM z9Uim-d2viB@B-STj>U7#hb$Hm{E}Sam@hm#s0Rk^SH|sj6qE-6m14s+I>EV)@IFT} z@8?MPE7H#bL+yyb%ze>*S8^OAF%oBChEVX#B^n9{93d5|0FN1+jCrFGAlerrBpoov zC?@uSyuUX#SxIaQ5~n~D_cPG1FEDO3JFb-%+i=!?mriIP?o4pFPH2&0q=ti~0ic60@IN#HgctO| z3Yo`tBHHB|VvWyZM*@pyO58gMd3>DscoZxP0*7AHdDtLJdqN@$sC$2e+HLbYOUti_ zV5MG%SocA2kI@Fp<$QKNP;w#@JB3m+2A^*rQ*y>MJ0{olvBrNv;=N9pI*S+4ND2$G zAO@w*nyQT}l7-B{@OD$?5>v-D$ZXMJtGi)3bM{+KX$Ny@N7re`B- zC8pohrQgk^126#)DIClPhiJl4o#D_VI7U4j2(xi+;CQ4NkNGkPG&2aDGl-KiNb57m zfFFaK41nxT!o;Uz6RyejoTwo3GA|&(QC`|6p`Iz2$S(PYE_E-o^9NEO8VI=z z$xzBBOS3R9sgS*<5FT6@$Q;@=_9w$2k1Rmuai|V1;@P!rbS|nZ%QZDh>#wnqTYJqJw#`|m^Gn99A5m90f9Zbr%7iPv_@L8q*$8Ii@lyy zs!AV@m4{R(ZRZb1!Wj#A*HgMPZz*B~U4!OU(|re-M+f<%Uy!D#qw4czpi*N}Ii^%#T4sS-OVLxe_^4ugfQDe$-!N(@uT& z5O%<71(j7BGMKXuh*i95a9nh@2vI8B$xt zTQoWTDk(`a07a~@1~M-!EtVqFYGA@ysbrBTkOmb@Div@BRNM5#si-<7Y!`wVYLb8F zs_%cXzom0bwr`*Z4bp&QB5NS3dFcsx;zic}1Be>i8(S;8+E>CgdXi*>pjr?WKx?Qb zl^_$PLgu1^B$->M?AO8H)smx8q~6x`klHucBca)Vh&XE@UUQG4 zUoVgsGY!tLBHqg#g9L4?`68bhEPANj4Us1RQTG=h>L$4yK6d>A2#qfe($8H-Zc@^r z4I>l@BM%2QK-7)JGYToOL3JC2CX8ZO+F&h>LS{zr1jo*1O^} z_d|q&bn8r@wzUYhoKDzOnD)&6*=)4iT#Vf8{l;|SkhM$LT*Xo+0a{lYTgT=$R#vfO;L zoLpDxVgljfXo>ZZ;8GR+(pc=m%Gsg^JZbvgJU(@4K~PSrb?K+2@qp#>#)oAEw`CTi zxhBEou@B29E6a}Y%Y|WbBXU14EX^ar7I!o{T%o@452VZlq}x}{_HAQ z!PGJ1#6w<%Ad7LX9!jK;0yblc%*PL_L)|LW?0;;=n3`*hI_7}TxMg~cz0{180;DlWj=F>=od?t@*siv|1mMy@Ht>B&~73BWLNb zc~XWe7)p^41#5VhFx-aY3-wuc5fmB)6u6n2QLBVDxrEn)=+-~L=QiLC;6x}EbmISTvu|92nG#WG+ z4U(aPpepX=y6@#b?7qU=%L?DiS+>g^Mv}t=k5)20X@#)D`N|#S#-n|?R`5jW!P>%3 zpjBb8)%Ka*QG`5M;E7#~&aR5nuGtlY4!)bhPU^?LZ6O4*vZ7ul+Mb;Mg>Z+8Q1241 zLtH2%-P7a%$+A!QmTB{52oY|$uquIq1{wO-7>cc!9hJ}Fx%6Dk(m2P|Vv6GD7Ge=oJr|UF+`o27`+b+J(JInhn26(rt1Wh5U8XZ z;zpfYKbif|h^O`a9QDzK0SDHnbXBjz2KfkiK@cubIqk}v^ ztT-T9;P_nhpWwG*8qP90?#kM>fLT=KllwnrQ5pA0MMG~*OMra)k6AR*7{K1TCIDtp zdG8p2cI)mJ{U35s_plsbcJ;aOAv`u6mXzWZkpqZE17ZszV&OsY#s8e9lyTV8K0ja0u@17J@s3 zKyY_=cXxLuxVw9BhY;KX`z86uYG!t(cIINMxaNZD>Tb?=-t)+=A;&XL5G1QjM7O5| zv5H(6M!uU!t;_c+#WKMEXfgnv&F&u_JDWA-!)52_jEn~#8 zlLDiUP)yNkUUMW5^q0C^e}0xWJWPQ7?so#fp(+?W9s6T$$pnBe2=xvi9i zs=)$Dh7RKi%e%uyczJ*RTQC>|^6Era=AF9%#yTCmdtj4ep{52!{~C58zo9! zoExkvxs@MeJEszyrgu{ul89ACAjJp0tO|}tql|I@rIk*3?4j6FPr1R?sA3x30?l+Rs$|ZoIHh>Hq_W_^y!ouR zCCvSHQlc>Ye)pRQW;X&}A66R}e&e&SrsS7)(CVXQ-pf4gd1t~XqD^Nn$!JtJ=v|m@ zJ)r<_Wasz87)#%H%eIZ8`JlnkdXNf+B3CD5vG}Kl8lyY|^yF{cjjZqBm5Y%$t|z!} z^oWRdJ$)BpER$TX$?7IJ?Ut6v#cuCwnR8Nb5mE?4mFy*mVtJMaHA7iq(>{#f&|8IU zP>I{~UyXuLwFGmhm(6QszUEKnpR%q9&$#=qfy&aqO~K9)-2RxA9ShlTWap@FBn$~z zpW7-}s&~_t8xL<$opkvj%dwTbjU}|G+hf<8aOzMwBk<mAED zY#%w_5Mg>;Z->}Hjj-|Pt6hoY4_@MoU9EwEHjbpsw3-8beNoozdXiWVdE#uxE zpHE)m=^CxL1rc0K_zdiXikh|}5Wm>}8o>Mf!o4I#EOIk3qT>AW?N{g?7bQP;ei?!y zsyD`sQLc)m9HWx_#=T%QG+|w(qCiyFG(}UCQCTP48+_EJHbp;dMgy&k79`;!Z_by*UQE~g;45;_n*@T4&&3fT}@aiWH7{Rv+BSja(;BBu9MYSCz zMJp^C-~&fTddwQUPr(uAbf}JUE`uS#&}g#`GK#iUh9_GQ7qcR(Mu^oWBVxJlld(mA z39Gx?!Ff$BDL>l?E$GAKFRNAAZc2W1P98pVb`fMEK80%Mzs!c{X#AOifQivRLDmo-wrD2m(bMU&1XkFB%5r-E`n@G;E z`OIc>Ae+%U4o{}l)D_lSn#wwJ&GLfdi+~orqCtpq4#|gNf$$?Gi+>#j#g{lUrEtyJ z3Q_xF#W@=F!iULf7pxL?UVY8#;rWJ^`oy}hW7$tF^R73SIkbHiIw}tn7A;q)NoB`c zuu_ZNIZWl5PSi?2OB6NSuJU%SETk%_d!^jws{X`ptx6U>`5d@1?N5Y=Ez}gQ=E6PK z%FNY9mOG~B3JcrIB;Inbw9n5sP}QGEy>KnfKio7X<(E-%acghj-Zl-&RM;kttnLA` zqLbkj-wLJHjx=vu7RM?a8b{X7Ty9%8kSm=AN|%tI^q~L3=aKcBlEk+2@JhG+)K#N9 zT@YbzrN`~ak7trwwA=OoPgv;i^aQ`-h0#5>*84G=h}yJ$>3uE$K0A%qX55bM^F7{Ac%jr~ z!O9#6;yp|%%oBsq#tz;x2u=OAsLT8OWV*k}NEka_7nDov_e$FZF9oGOII%kGt$FWT}xow{OiuWS(7-sEhYehGYBBF2C)XYkt2Sey(W9c{BOkB$ZAq*O*r~WL8L1*e8 z_D1cX=PAvv|JAjyY9Ru8O%MZn9p9QNK?Pz>7c8Hy?>l$*Xf<^1r7z-rb&>5SOPt)C zMnu9bBLp!Hu=?wzO}FhoekUVp^0#AeWWIcVWIFd{aKl7npzBUuIq$)D$V@@L=aJ0N zQ*PtgrF}hmay4o;x7miz3*6N+tRrOpOg$8-9637Yw-Wurbvy-^zQ8?p5b3CYs^@vS zbj-~CHckMw;>>kfi}Y>M#it!_ zSen9=aRq$0J)&|Y--KB{wN+-gWpIr`&m*2T#0X9^DH71_bYz(h*0)!z16pSE#RuIKGte=x-U{X+Ml1StoY)F!4i5@On7QVnF z2&4;opXDS`M+6Og0)s*xC`0m0Lt4aOa;fO@7lY0mp=zi?=}}>XI)mNyLClk`;(5+h z9G)FX&M-oj-^7t8y`e!uP$lZZlfOXM7oaw$5Vei4ZgBW_^`M!%uqh5tQzw`~b%tT5 z@HwUz$m|_x;#c4Ud&I6&gcU5;aZ~t3A##>)XnIrV!XUHQBs8xLaF@9s+q z5rGeqJlC4=vEhB_?_(H&_$_BFtHz)BEk|-JS92`SQY_znEdSd$LC!d!VJqq!C!QQ9 z*&HXm1k8%Y$-j+PwAnir2Z1*L|Cy&zWGTkzgz#jLL36#t)@^ z14rhClQ-wi3H23UIkB`V!NJUT+6ey3;nxQfc-oC`&YVdJRnW}*NfkDqbgH4b&tC+~ zCq1}p@eh5I{OAz>1bE#G9go}ip&=sf4-BYMrS9v!EUc{XS~p!TVIvhO~j?vDYPMO>xQ?sMM6b5=^@EHsG`+HNA-79< zkb8VBRRXcj$Y$pR06vp(>8S8076d0bCFgh)C#g&(3KSW?*>L>s4^K7xlH=T*!(pyT z|Bz#ooMh90#IlTBTF)Xw#KdjRJ%;KGc}*@LC9aC zgau(bU-ltCxmmli*!nS+#Z?qp-37(3{vEuq5J}ZXLxh4O3b1Xt841Hd# zhFv1STH+N@Y|W+KRit08X|$YNGR0q%Qlc>l1$7OE3Tx7DOet;EG-{`zYoRGNXDdy{ zwMbDR5cMhrfuJ;+^oNJb#&L_3UJ;BeQ_e`1nPDR{PeKcqXijdvK!g|}74!O=Tot=6 zM*ET#VVWi{zfuNOqGyLo&612RXi`0l%fpKCmt9oeMnSVsK$A`ysS-i6Ru#IuA`sXB zxo?3wG;%(}5+Kpip-fhwwtlH}sb*r&I84sMUHLLu4gT2-#(u26yUB!F&Z40GwnR$& zyQSu*1B}RI9^?PvtY|=$PN|tLUPCNfgW-y)v1>z6LW8-5spU$84PK)ycjGs$MhDkM zr_@H5)<(CLMvuovFT5rn;K)j=DZsS}a@P=~1w3(IY5G*!6oJ2OK2(4GAdhXQMv){tc+^7TiwiCO;lT(T3bJv zHMCe*Mlymn*ck&w02xmt*fj4R$w>?AE?er9`qHSa@+`;nDd(=f;k2%spybG2qI8_qo;4l^iecTFiy7 z)&(=5H|tHW;d~EXX}YYm&f8KGc{h=(ekb=Wr#A(Cpw2!whrSWzFO$U3KDT{0i+yUk z{aR`L7Ut5kj@FL?z;+_=1k@2H!NDPH;0rJV7G{m*qURlEqJJXwXbi)(0U65DQ_X^K z*nCq(8fc@}hp9pN zIwdM>{U&_sUBQ${?-U`gp~B=8>6#vqj4-+TG*QB|P~9Y*%qJAyKn2Vx3W6D&y=lR^ zboTHW`uXvl8(7}c87#I*{;?V1c0JMdDZ%tv+<-}G-dWjneX;j*O1xcjZBwf5bN&7k zQUuf5zxBn|X7xVJ+WO5Jt!d9Z%`wQ#o5{=(w@-iJ)qBRDQh?0Z@qU*7J#Cu4K=CJB zDlBli;MX^5k36p>^Rh_FwkYqn5F(=!IJV%OE(}y~x3HG1(ianu_2XrhQjtF=5eN&E zFY)&-+WcBVe6^VO8#V$NCOv$a32Vgl{c`1R;R@cBD)&z%Ym0(A%jC%`i~cKRyi4MK z3l+$#FahKB<-!U!E3d*D`TY?G@C97;z@Us#ndYaiRa1i*wZN1B8^M;dw zn*M8;m+>f=U?<^)cX4owzc+;#zFLaL3gl%mqQ`t)wLQGIoxI)kMU+UPa~s`@;6R-~ zcG6<)rW;l^XNt{=mym^qP*{bY4&7^)p~9HS8cKD2HxibheV!6Z7b-t_n_Lq{L3h{P zhX5f8^zHAFl{Lyfh-lw&9ncz$9c5t@h(Ms3JPeR9h7F7ih!NZw?Qyoxm}&{~C7|*G zQ|cbZ1GAz!hcP+~aUF+Q5nz*sLsiBDe-9XHkT7G`K^P&7DsXv4c&OI7?Jl_Y*(18n zWA{#x-x7PzfH2&cp3bae?@lKEF?vU+f+yMTo#6WRFv^Z~z>ehjj^NIYyeyQGW`521 z))Gb*gQVZqk}s(Z_Vy}DB$dbZ2en$>p778F}|ny2IuJ~$pf?=pTqbo_i; z|M~p<6ZGyJ{P7&}`TUjVIb7yB!uNBeALqz#uuwc@7m%>feyF}t__a94fav{;$Yc!O z{TKe{Pq-gZi6>M^8IZ`os63FuQ2s!q{$acDG%@pdp+0w^E_^9rifLeY`8D`5-*1e~ z5tZ+=67A_JyT6%vyCSw zfWzF`GYIhEuAw<#5DjpcXBJlhb$M=OXK8JF?D*%}#@_nY!RF54?!oEaF@S|HfOWI~ z8Vf)De*V8}8voz=Z2&Zu@bUGL^7EAn4hjsD2=I&a_m32P^)VzODL6GYH6!J(v7BEZ zmQe8b$}69cxU#mczT`c6LklojT7bmb(cL4R+84}<5-dHMJvuOwJ2o;gFt@On@yA$} zenTOU5tZe1Ifa4AqKf%I-He6O;`z|;L0$TA+S97iI0UEi0_)vO_Y?sx=fKt zyLxf!$fuqu87|uwd^ye&URDpws>^BQp~53 zd&A{%lON6DQY~mYP1kIPc4Wc!YicgpHzG(=(D2I$saxy6j~Mm)T1zxXPo!4{B4Sw_ z?dMOKhsLsU6Cdf;@=Y7^Hgl}4aDU_pIBI2{EwGrLwAVVngOuqkZrq%U+(*c9mTqmv z2uRXbtTOK$t?1qU7?&I=ujgc$M$0K(MW9$So$LZ|z_WAi?PE$%_h~ZB` zYzP~=A!s73O!~p6GU9&dv^CfG^H2b z4@?><4!2EgdKltF**W^~!|J5*s(VHGv`VVZyNP9fOXR_ZeEB4a78d~&DS2hod+}c= z5?4j;{r#6Tg-JBlqCHw_4bA+HFn2AKU84BGgz6fE@_Pb7S~;O?%X%rL(m{SXVVdxi z1u3@XhlNRknCAHz3Fgw_sX1IZp6X_`DhAFEi)m3Q{uo8kM<>JM_7kJC1bpmhnz11S zaKP&v{4HzCX}3D4tY(zUwYVf#y4A9FLjN(iVb0;< zM4A5eA+3qm`XjnyzcF)}nS!FkX+s1yEj9JqlHlIXQEVP-Dlmi8dGop`UG)nHl23aX{jpBncaZOAA~Pqdcko=?$T|LVIR4T!EL`GNZG z1m{nm+Ho=VvCBze?)M+2Jx^jTXO)EBv(76~T78(&epCM8m7e1#dsnr@_YL#r?5FkA znFVVN69yAj-^TZ~DH_+@4AQ?zy56?4Ecqz4V^@v#+MAMbvY*{;M~Ttj@5HG+JG@UY zskq-u@f^F~&-zj^GM$}h{jhzWUh!}U+gS5(oV{{1CRVl3!MV|}&v(D+ySy57)+u!6 zeBS$7j_14u-_z}A7&g=Gvh&4h|Em=LJ6_58eH7j8Ikho&k{HKK_m|WD$V!*{z0_y7 zhfMt&N^FXD3X5}WmHizxAqO_oA|*Taw) zv;05++NsP8=FF{&(f| zUyS7fw#Fgg$O|x*kqS8m0Ao4jGVK5`mKTP`9a=8`%aPY*#{b!@X-vvh9+gb7q}uRw zLd#V?<3DJevJAv`$BJbghi5V#t_t~)OXLG3XLE4>r}5pFu@cqB;kgQz>r!3hQuP7J z`I?mLGEXtyH7nhCOLDN9-hklLy+ig!euOU% z!VnyIA#Sbw02?TaNP0y(A&+i^pg_HPwEFL$aW+CX6cv$7pnans7OO6%Qm-7fs9UFi zmwGQt`&sy^sVv>LRi2zY{0^9SBSyQ3TJ`-ynV4f| z5_eDsjE3`9AmM>e-(`xDFxA;IEp*C87{AMo2%^A5f7do(5voL$xf2M%6y{`nvQDzQw^((0n$5wb0j!J0j)6=11s#SD6 z$A+fUT*R6{KD9f+4lF?WhzNUP3Hevgyu}{zU81w7YklwL* zP_dt#lSC}&yO(y*Njv5gtmi`-$*z(M3CxF?WFvWTp`kw3V?{tyo}5u${bcimb4lbf6}^Sq6~M2a%&|tq!iepaXqINPOaZ zd=~q^(SV`$VW5BwH5vXFUvvXs8Ydr4bzgR>Z(Sk~E;uL-eNWPT5)miAoOy_F6P+lP z4M!k2fRYQ20wSnu%I@f|f#Vm`KofBilfpai#(kwo1``JZqioPo*RY60&^hV~GDNYQO0n$sN}QarJoh1} zcc12AV&C;agyBI)s4C*lI#SKS^Vn7~g9_19aRMswsYQ_6db)F?c#h)upZOu;b2@s5 z@#h63)Ha{tqQJb=3c$RzrC9>sb%OTWL>?1TI)FTNg7qanOGYKSE+vY6AoeUybh{7W zSO~F_P>6DPA(t*rvTe4JCW8K`8%J_&J1U}r(GC6N5T4PjCIyP5=1f^Xz|2c_+}jDi zPl|ZFi=eVe$(4w#l0e+>i}c-h$-YmiHH)rkPHm)?&FGBK-E&Dn*Y1Fi@`ERZkw`f@ z&INeRvu1m!Oc&Qu)CJ}xh-jc`|yj4ChgWA@} zNRY65PGo@!QoOu}y{1;VP0o~W_9n(jM$7jm;)oZ!_D09>agX<0^ou9$%aYm6auo4- z*hi^n_2q}lLN&_fZc5_L&z2v|HpKGAIC2}$^OGO+BQ?qaq5A*QP^Q84$Kg`FW6!z0 zl-7lN$$4u|s*V#NZ=cIVlS{(oJ+>3@epx}7OU3#wm!BqkyHOgg3QVU0#W8_vU&EWqrCkc;P-E*Dro6xf)HV}tU)a_Jif<=VG= zvJixD_!K&8YSSn}(5mRrqDUkk3S09@d})}_HVT7iv``<4kSMZXC9`5$bZAI`_ZblS zMp2@gzC91Mt4ZJ2r9w2p|j{NslqL-;VK0>Qw=VqO+Y8ArL=9iwBw<) z6Su6JtE^YEtUxKRKSX0Nr7XI>Y;;+D{Gluqt9&{|eO9x4F{OODrF?Z6u>8t5a9=96 zxGHuuEB0I}4pJ(PS}IPKE6yG&&T%U*xGJwSD{ovX?@}sX+m}Be+QN-j}~V>0CaQ zvB3~AD)3ta-5$I-Egb4xgZg8`F98|b(1w7l2A5VmYrLkbU()U?eA|8S60I){DE^Ip zq3^T5HHEV3R8%*)G}Wm+HYG7j#f%6X``2+*5q(dTPcCgXL~llAt!p~Owv>iKp3TVL4!08>v|IPJRd2VgVihC$cbJNFWaYMdJ^13e6y5G*(;gKo z_I1GY>S8cML^vRO$?}gY-(R@3@Tot;y@K#}=5m%m;L1A9{J$&Z37>`5V#9Rh2zAlU zec_1Wq{-sJ2>CfrR$-u+_GLB*r;ZnZmXsg+S$k(cPDhsCW&zp&eH zpqpb=nPIg@__~LmPFZl3g9G{eJ|`T0mV2o~VTuuHES_$V7@i>te^HDl*Tl4;lvO2< zw1Fi2VM_af5b5D8%V84#;YjJ>G9EeG(Vk4`{sg3vQfZyW<0Pn()=EkBc(cgcV5ur%IT9WAG6Ew?z7{%qO*XzM zHNHB^@D-rX+Yd<-+F>c4vH7XOm~^Ft(tcple@N@@k;0P8%koaITVRx74>WpYdBxz=o~BefilCI%sSe7pA(3cSShS zy)Ipm`F6SSy+UCFVB*WQ{9ftiHCtv}rM6t9F+v)2SL~}=rGY^nmr=|oSfkionRQ=V zOkZ2(|i}K!3eLp%aLg88@YUKTJlKN&n6K!>aprIjovc zfbQ&4M5Y;p%?JD{D~|J=&MuJ^3LwVv8;KX(4{JDZ*x-ak5Kq*n=hI}>7%;T;C#*A9 zKSp9)6di(bg1`h-Eq!nX90)ne=Da;UlM`A}7iy~i1?))#hPBz|$k^u6fo9^{{!p>a zPq@ROqss3A#g+qnJBocnv?I;8V|WD3>!Cwe1z{lqlj`oO@_{w^z>$~G3iM1$e9&5d z%UoJIsz!v+VuV&~Z=sE!_Y5Nn-gazCE^U4zeoZ91kI1+MZwvRuev7(e3vVdO5Me`- zXai!sAs4d|EK8hvTYHMk#7447qqDih>1=BLSyzihVHDhIc4$_ z>&UYV@lC#^gY~mZKAG6}XRo7wj`(8c*ZzDuJAL*LmptM4rGxk%n+tINbYNA0>}LNZ zyIk^i0NE8%cLsD|K8N6cWLMG1Pt`0?%{)lmBIrL{VEbr*?3y~q*?1;@^-eL2&ic2% z;2f0YmRtQ#1O}LHKwNR~pDsl?z;vV1Dx))M0r@wuxGAWlDK5Je`0O`^Et0x20#Qd2Fun==cxW9hmMOo(Htw!OqwiqV(kq_eS-OWlxMwPS4HHE-Wqg5|FL@*Z_3kO)kWpgTrmX z`Ou88(1^2;i;UEBzxc$=pzi0=!kgcCgNWE&zBSgw+JlpGl>t3DV}haw8g=Ga`7${P zXsHbmM-BFf5;b`e`g^h^!ncKMZHbI{yd|&_(H+UR9M`R|)vBEt{944e(+Kxd1h3ttRB$3oY``iA&`1cFaRP}@R(^ir>Gm|Cz zo%S>2G9*m1zY>}o=7hXjGR~E*$sx*^7ZalqNfea)Fq4aiI-L5(9m*1|t-Jah5@Pehk+wgm1eYY7zS#h@& z_Fs`*>-*iLKV&z}@eCllf%Fdtc>vix{6CsiGpYQ2v+DTs_w7a?!}H7CPU4s6`-8&D z=ZBNVpU;oy0}L-uR|{WWe&3CJnRlev`{~&&xA^Ym>gqd~28nzhXF~#Mu+ul5+#7*T z0-BPe$^_pV)*^I6jcQQ9ZSxg^*=58ljp;7*BU&~YMga(kF1S8C%8w#!vt67YbcyN( zVFsT6@QZupLV1DAXR=W>Ucr#xO`1xoFQX=!)-17h1|nDCVia=JEbVLrgG~8R^2Gb- zJuKM-f&`F!Iz<>#q7Bxlx8E)#F^yOK3bzT%#oren;9C9_;WU~{csn@2haiiJ!XY62 z#6e0~l?9c(fkuoggdnIogzAkMP8w-1E~Xe$N5(1Ns8(vt~T%2p13jwaov&) z)w5tWyAKfQK;#5f@n!$pWEa>{iwZ9@q?B43{NKLGLxNOi@6PI6QLBriVBGI5&U&(_-W|%zK!X+3_$81Xb6;In7 zC9yd%yPCI5feJv#!<>gG4 z<@Xgg&gxhC7x%!BnU6cSudh@JKbw$3y&G05s3WWLhAJV2d3V|=neX+2AY7vGEQ9La2(KkBB9SBl@yO~|n7&QD6HM+fATNo}P1|*%aqg7{z64fV zOs`UTkMc9KqzFhOp~V{T>8CSuW}c7KzYQ*Zn%htOBCScYfHS&qP|Nl*Y9ioSW6gBX z72Kd_DmY#M|5?yBmmnDzH!cg(8FiI+&yk8l)oF?l)D^`(W=84uV2Z$xT#TWu_u9f` z&JnUX8y4V2)U6q-kctZ~xjE8WK=adqPAzv2w?Hi^U+8Th#Wa24?>FRr{Ijc8SNLah z0ccT-H#9Vkom&5GQ8YFU$eh`7(?)sP`M^d@7qlyfp%Mo9SGgVg@izc1ih$mhODnv9 zL#_3`dU|5bNoWr|Z4S9X0i-t9b8l&B3HU<1o^}xtL7s<2gd^y&z;sQ09E&wn0hwyELC=Mqa))Bo?M|8v28g&~-B)ow~CIGn^AI8+KU+vIo2` zoHfpzR~aKqma?W?Q<)vjMXgj&%9JLh(M65rzIESpDl1i$SS<32AFK^;iNWK9Ep_j# zPNfQ2G4n(%bhh6w*t56np38n{e`&IKcgMfDbyoM1-A4p4Xo9aO3{GkLtBW2JDTA%} zEkpYn#d6|TyT7nI-&%HDKt0lPjc-{0a z=-BQ%s^^GDJx;xotFzpb=0@`!QQ{(FyU^nXZF$h5NXM1huP2t*o(~*~9@n{_wZw9a zN7VZ}?s7MGXeobPrj}mBHitbs32qMUp)qeJ-#mkQUk39^Uw)HTN{}yp7oncFe|h7n z&(8I{PXfi^pvUgXKcgq!>lLx>^_kt_XQM9a0Sk&TD=G!oTR0G2k+N)oH~k*l5v5Pu zJ}3Es_x`PuJdsXwHv37RXB>v_n?*70Id&(97cNdGmlrS?vx*BqNIV>V!s>paPJZG^ zev)wH=nZ}pv<YoHkf0NUGzpbN6>~awT?QY;n9q?5IcVIYk^KMF1T4 zWHCZS9dd>fdBG8Rr5<_X6nU2v`9P)h=)|qD5Lt2=2@2){b4C>?MZJ>Xf=iC_s)a_< z;2ye*%E5?6hv&l7h^7jPF1L%uP4*yY=EA>^PQr*GG25d{p`zxbfv2R^V0%AA z!63oLluVA;%qPnT;*8Rk-i82w{_Qt$H;S>Uwy}o>a9qVYEJAP}-^StY^B3sH9oWH1 zIKTb~4KH&TH_aZWpuwLkAJ4PIq7EOYdH)qkC{BeW{%{+P>mGNElEnZJgzp(l52?HT zK1R#OFB`FZrB1YKX0X?wLN z&AbZZymXzkMQJ4ig2wLzV($=HjFeoB6fj$?D2Fn2Cw1IV3Il0!JoEdSx2$!}WYx~8 zbeGVdhEnBXQ$xXNnYF3C!OYznssl@`Lx)r&L#$)XG7}p1GsT?!8tGnk>5I)Da&yvG z?wO{F#ebM_CT^u~J7-8^W^4s#u;ylz)sqQ#XE+&TT->wy+Q$CU$i&&sD9p)Z?#Z0p z$&3)n+*9xZKd?fMKEpmRf+T5-NMsS0S*w#X8FC;%ltLgj>)AdVCxj8%g$jE)n-@Nl zr8}F1Ccy~;?^2wN-xFtem>j%G|Bi<0^-;Wd@(VPS8jCx8?#wL%h9oIPNMdSL4$trx z4UIgOLS})GkKd*e=5|@QL-Lwo8RI0f-z$EW8qT8$$(5r?pr^?{y`f`qNvtO$Rp%1$ zl}`%1Phg*s3Oh{F4MD}r&DKcy*zK77b(ta|u@E3_1`p!KnuRaEDS2ioP4}>VB`KaR zQM%|k_`Qy;*ddhA#SWCbx5;8P1rEhdEXfZJsYiT1M<1gOLR9L!5=zKTGzEofL40)} zqyU!E<&w%_&QQ&Ka$KSG{u1EqK1Z~KB(_wvr!)rmVr?#15&%u13+7-ft$KhREGZi; z;kh!)V!kphQE-yeO>r=ej*H34<`R(Oe*p{2BgtVvh;+kt4e}8l%IO8mDMOec!xd@| z71rAoAM^pf%WPg;QJg{w6I6Ns!1U-+3Wdl4vM7K_Wrn6Dy(r0|kAVOyOh@K~$d8qt zQ4mLcddz2xc-KGk$3)fhdMp7PbNkMTljYJLi4Qml~Rl-6LgKx}QHJ$0c4z%`Z# zwZ^rdHM46kmumSe*opD#=zS}MUF$q%wZ*yFo<7t`Sumf+)yS>nC~4K(D`Tmaeo#!U z$KFQLrgfHmtS9kJ(m!S$Q)p1Htv79L09;_ok~(V(7IVBtd)7BO-f-;dI^wpzU3PA~ zh^lH%jlZhcB)z`U>cja9H{smAa2vnM&TWJ&erR+Th4`$%)iFVrg@7;$q(b;f6H}XM zve@)oId!i<891`FQ!?>)Aj6%~Wzpt%3n|X5QukX3cXU(jqk{@*a}YF)m~M+G3kaVP z4}UTkbPf{RXjxJP!A`dQX;D13QB6WWJdg;|#hgaP2h~5o>X-;))bLHqjY|G$ilb3H3^KGM4_e0li9`$Y(uWi2O zr^#ID&ROBkcdcj{&1)F|^kxo1jl!mpsn>eJWPD|9xid|V5E+X-znHp4M=Fe*>g18B z#x)hR3CHeluK$VbuJ-9X_37gG>+|#*YWEwv^_!;ko456wkkwi~_20l_3hJW?&7s4wD6u^3uMHTJS{9vA z<6BtwPYC=MHO(&T07g3h(4zW3v{65n3eYCJ^1eoWn8klJ98Lu9g1f0Ou z@wv*wgMaX-VgIFR|D}6i>Yo`nIKD7C1^g@n+nkegYqN`Me-YC5pGi)j0ll%iy0N>y zbGUYJymATPq{F{y(?7c4?#;{p4~;mY}MxzM+)zbt51Lb`&BoeeWq#s!-}rXF^IJ8XQs_ zkC{vvpO}~#Tv`AM@IN+Iafvqn7U1`k6_k{J9szQoZ%lZ^ZBRf+Zdy!S0$=on$!ldw zpI*y+grq7xAq^DLi(&HWoIaf{dh;?-nb|la0wImTvv~@TVzcuA{iPG zPS+IA8Qm;B(r{YqDDy%HfjjS{z-n}g{=NCO?#rZD<`EheWO7oVix0-ws_$F1a!~|B z!6a7m1w&bayZ`8`Y0aTn{nFsHz4#sW8MB4GPh%J9+91$Dx51bLL!;}*P?A?iYVV42 zlVfPcM@yJ~g}&v-j}*6Wwo^??{L*1mW?@>BGnQeks_M#lW~nkm=ow)QTC9RzB>SG? z_%oaL5~d$Eze-@e!cUCtc~$S?xtA4?1Ji}YHmKLa^*^zWMZH?LUyAoj*Pw95CgeOZ zf(YlCBBLvlC)l(uYx;zB8nrkw7$vr03KmFT?uirfH% zvO?VTWb>^4=aT*E9v1|Q+9W>2^88v^JS)$6os|&3QDa22l3~f^;Kn})sVF6_wEX=M z4UJW+*B-*p%!YC9qPCkH1Zyhqf>Zz@L9beMZmCM0XZ$2|Bd0?k4YTTjSpa{{+2D|aU3_~KdYrAk3Qd!1vEs9V2 z1cvFZCWQexa7vuA{AwCNNLMrRV(+hKmDQ}S0fbb3J+JL}dcB|<`2Ge!NLDvXriJA< z%a(r-lFh*T+tqIi|4W4A)(B4q$bkSt`Yj1OEiTplgOCi?hxX6|{~)B>^f5RJ)7XdO zssZ}D;+h5P$I~yZLL#WNWk9v736|mM{L}Z^9&pwBsvhoM_McCeGT(i9To4&w|Gr){ z$z%#70PDuy00_zBrS$}Lk{C)sp6L%lk~`)mN_q`~B2xeP{QGV{vxr;4Z;~IHSp41T zl~^YjSKd)U{KqE%A-y`9AP_+91`~*PA!wfa;EZOyVjt{6aXI%TLdu2{6YoY(IrpQI z&PGrh?8a_6_h$^tMluoa!CgKN;26zDaUAR+d^ivMZ!XGn&=UuHDgIoPhvi@v0vF|) zze3c3i}J?7K6;m5p}I)9f91fGUty-wxws31{cJ7&LxlA3E7A)ok7&QZ7vdH4!B^UF zK1yLwXiqpgY6q7T`A}R>ul<5oQpO}nUHz3p7W`}-ilNkTf-A6x5SI9NhkFu6;_dk>aG0YWpz2ICfC-~!a zp(;0G$*>JWd<4x=!Q@3B$-l}gT3Tk09;69ji39}+>gU3g9#Em=!w0Zo=J_8T@FRLp zj|MAalJ%L=YD!YYcLe6&&h|=aRF}mV$9-b$n;}t_C=@-n!>#v&{eFgptYUnKDS%Z% zXXZ2BamAvt|B^P;boOB`#WWsU;lup9E#|})ziVMbEXurT^Z8mngw#VOWBJVz84Ze% zif`4WT0fWlEDH*g--lDU6bz|-?|)V0NVve?(i5DeM33qFieIBIUO2KV6i!+_wL{D3|*2uzcHbH}>zM{NeU{ zr8dYjdqY7GqJqG^Mk66(u5cjuEnhXA>ct1`2q93yyNlGSLgsQ)K3x%~KsvryG`UqT z*C8qAozBsyFp>(gkRX_Xs>GX|&L2}etBW?l2gRBPxWW@`?uQHU3wOo9nvrV$Y06|* zz3lhysgu6!JymQv(r)~eRDz6$ZHyH0Ct_9*8#1boRy&e0)5nle5ZtB1k6%Vtto)VU z`GTokNG5&5%|c)1-+!aT(->gOc8%Mm&3fedM8hKhB0%rNxLTDHBE{tmF|NzNPd^Yb zxg~hxR0pExkIh;po2go2HG}duld*e%UyAq1X0q{u*4=5Ej? zj?~09!6xZ~5YeoN_O@;KP#xf%I9IZ~gcMo$V9V%(wv#oE_I;mQCknJkwgHnne#bMn@b!uev`zBvKC@Nq zAg(8t0QO)KYI@(+wZj0y1ltKEih7Y!8B0LX)CnWaZBzux5^%G}rm(0BGxS(ZW`ZZ$d{t!l^5BM*bPmsrUu*0a z4PX7U1{AH$qi<#JUW!1?=T_`1tZB=Lu6)`ElJec#Xma-|Oi(%*I52 zR}+kN^4T$xYxiBkJ@z*~y|o7vctaKt`knh}iRbSVq3=Gca*?;OKOpc(x*&8@&NFQb zkE?-szmt!i4;pea$xbSd4YeP+l!`p_eKQD33V6?mV8C^P&_(7g4)%X8$`3f8$iXRZ zys`hEM(+Nd3H^`b_-?hiJ3_@sqOvKq+|FjXnY%@y?Qj}hkrZ-DQw%#9mYYq?O_Nb> zHe)xo8R_Ka)VFWBoRXrWE}C4vyT0eTzCV3`IDf|H`FXz{?dhh|Cb9Rf z#-C4!XojDU%C!kLG+)bo@G3p7I@je(m}VK|yG*v5&Vx;YJ^S+xsz?_*Xm~X^W9w#y z?Oym2=ZdjMzE7e)OyJ{e!Q3XK5n9R3m83-m$btbxa*hOIt~aWgVHVfDgRi?zyMKGb z4F7?V9RS^%3UHtT_A+vm_629xwwx;}uo4s`&8q z_+7c6hp?PoTfyKd#{cI`|Cf+%I;YIRh$@rRm#L-MotN~Yj2DqXt6im^XhAEmOJ5R$ zRuhfCt_7~sj5dA<+FUaPqB!r?N+BmXX>+9`Le7um)Qx!#RRBcUmS+o&-cBq}bPYMq zB_oJION?`I-11$hz?6dXx{4IbEOPuBSf!W5op%_Yu88?;Y|)Tpv7GHftaMAd0Am2; z^DM8-0QK_}fpb-YKlErS1Y2BX@a`Wh$}_o%HQeO;+>{ya#jo5{%jzSYmDH2f(ZuTX zn(BHg*q;L-`sj2*>`(6?$Cs<=%<96KeE&o&5wlrxnR$yoY;11}G)02~Rz1JD)ZBy@ zXlcYHTM!gr1+@jCk}&m_JOG;4Obp~$)0~tV107T>h#q?>?mnD=}3fW3w3JZI2;oxPh zSDF}g6+uYlwKSx)l-Qx@$+&CXhjX*|E6SGZV&5WOE7zqpW~B9fR5J%5`k-vB)M82z zhZsDh$FHJ0T2TW++=LYiC}N@323RAC3PhDsMTLBE=cHIh!6;acQmmwiBr#9Zod|l5 z*PQ6niYpK(B|@6Zm%xT3w7lfeSr661onf)V<5}rUyeKDJ+WH(a)$Q?&KI z1pzXolk(Qp$)J4=K|E?82xq4gYVRI|h0o8*;cQ}*K_}O~Gi>~>O{;s5fwJ1QD>1}2 zdcDh`vO{93%$e)TU-mq=|K1j7cT$fumQCDe2Mv*QTzk_=mng4wY<7JgeKarp=i&>N z1fFMkt!0A7>0DOl)(gnl*&wEYU>_BGIr=_?>VfEKU(Ih1OYLS(-fz92{O(ITIvOck z?|xd@UVNgb>pi1g;vh9Z$|OBKYz(`*s{_}&N>J3Xd&@|@*?;xqH1&k`_sZjY)7cJ_ z`+KLXFa_+s@Ht+7+!X7|NHJ&Jv-iH<6OhRtcqXW|9<3ENY^Jeem2=~d-Q`m z7w|^K1MPmy>-7iJg$JORej((HUP;N$+WzVM7|7#(F?hhV%lz8d) z)CY5fg@1s^ibu5V&|pqkN{LOP;Rr{)W5CdAXwi(VAW%c`=_#gU z&cnC9-oIMjI1#G*wX|}l+byC;0Izz6XCA|&N(kThBUilcG%t^=*pHUNO9Ko?ig#Dy z-ws`Ut%P8ooxVDJj57>8IrQ=H(~8&6_H_}0pX*~62Vu9>`h9AhWoo>kHrY90ik~n) zHKDUiEpAUB`X;P58VTwN+dhAa9}Z_d8BEySJ({uaiQ7cOFBvB$_uqDn+^Qj(iBAV< z4xAdm7-94pCvm4-8?_L;k;dC->R7~7j7GC9cj{z*ir)uKsFO=mmc!8xCJ{H>j&DqD J*Nts){{e<`GBW@G diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/PgEventRouteBuilder.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/PgEventRouteBuilder.java deleted file mode 100644 index 75eb50df..00000000 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/PgEventRouteBuilder.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.zmops.zeus.iot.server.receiver.routes; - -import org.apache.camel.LoggingLevel; -import org.apache.camel.builder.RouteBuilder; - -/** - * @author nantian created at 2021/10/26 0:28 - */ -public class PgEventRouteBuilder extends RouteBuilder { - - - @Override - public void configure() throws Exception { -// from("pgevent:172.16.60.99:5432/zabbix/zabbix_pg_event?pass=postgres&user=postgres") -// .log(LoggingLevel.DEBUG, log, ">>> PgEvent received from Zabbix Events : ${body}"); - } -} From b69542327676023fec27e8ab00d4abbbd360af51 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 2 Dec 2021 09:21:49 +0800 Subject: [PATCH 697/763] [fix]: fix library version --- iot-server/server-bootstrap/pom.xml | 4 ++-- iot-server/server-camel-receiver/pom.xml | 4 ++-- .../iot/server/receiver/provider/CamelReceiverProvider.java | 3 +-- iot-server/server-client/pom.xml | 2 +- iot-server/server-core/pom.xml | 6 +++--- iot-server/server-health-checker/pom.xml | 2 +- iot-server/server-localdb/pom.xml | 2 +- iot-server/server-sender/pom.xml | 2 +- .../server-storage-plugin/server-none-storage/pom.xml | 2 +- .../server-storage-plugin/server-tdengine-plugin/pom.xml | 2 +- iot-server/server-telemetry/telemetry-api/pom.xml | 4 ++-- iot-server/server-telemetry/telemetry-prometheus/pom.xml | 2 +- iot-server/server-transfer/pom.xml | 4 ++-- iot-server/server-web/pom.xml | 2 +- zeus-webapp/pom.xml | 2 +- 15 files changed, 21 insertions(+), 22 deletions(-) diff --git a/iot-server/server-bootstrap/pom.xml b/iot-server/server-bootstrap/pom.xml index 2a0a739e..2be1f9b3 100644 --- a/iot-server/server-bootstrap/pom.xml +++ b/iot-server/server-bootstrap/pom.xml @@ -20,7 +20,7 @@ com.zmops toolkit-util - 1.0.1-RELEASE + 1.0.2-RELEASE @@ -32,7 +32,7 @@ com.zmops library-module - 1.0.1-RELEASE + 1.0.2-RELEASE org.yaml diff --git a/iot-server/server-camel-receiver/pom.xml b/iot-server/server-camel-receiver/pom.xml index 82af956f..1a36aedc 100644 --- a/iot-server/server-camel-receiver/pom.xml +++ b/iot-server/server-camel-receiver/pom.xml @@ -16,7 +16,7 @@ com.zmops library-module - 1.0.1-RELEASE + 1.0.2-RELEASE com.zmops @@ -31,7 +31,7 @@ com.zmops toolkit-datacarrier - 1.0.1-RELEASE + 1.0.2-RELEASE diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverProvider.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverProvider.java index 336b81c1..f98fe4f6 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverProvider.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverProvider.java @@ -2,7 +2,6 @@ import com.zmops.zeus.iot.server.receiver.Const; import com.zmops.zeus.iot.server.receiver.module.CamelReceiverModule; -import com.zmops.zeus.iot.server.receiver.routes.PgEventRouteBuilder; import com.zmops.zeus.iot.server.receiver.service.CamelContextHolderService; import com.zmops.zeus.iot.server.receiver.tozabbix.ZabbixSenderComponent; import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; @@ -50,7 +49,7 @@ public void start() throws ServiceNotProvidedException, ModuleStartException { camelContext.addComponent(Const.CAMEL_ZABBIX_COMPONENT_NAME, new ZabbixSenderComponent(getManager())); try { - camelContext.addRoutes(new PgEventRouteBuilder()); +// camelContext.addRoutes(new PgEventRouteBuilder()); } catch (Exception e) { e.printStackTrace(); } diff --git a/iot-server/server-client/pom.xml b/iot-server/server-client/pom.xml index 1760be98..09ef40f2 100644 --- a/iot-server/server-client/pom.xml +++ b/iot-server/server-client/pom.xml @@ -20,7 +20,7 @@ com.zmops library-util - 1.0.1-RELEASE + 1.0.2-RELEASE com.zaxxer diff --git a/iot-server/server-core/pom.xml b/iot-server/server-core/pom.xml index 208775d5..e59c2eff 100644 --- a/iot-server/server-core/pom.xml +++ b/iot-server/server-core/pom.xml @@ -14,7 +14,7 @@ com.zmops library-module - 1.0.1-RELEASE + 1.0.2-RELEASE com.zmops @@ -29,13 +29,13 @@ com.zmops zeus-server-jetty - 1.0.1-RELEASE + 1.0.2-RELEASE com.zmops toolkit-datacarrier - 1.0.1-RELEASE + 1.0.2-RELEASE diff --git a/iot-server/server-health-checker/pom.xml b/iot-server/server-health-checker/pom.xml index 53a12bd7..7b6fd9ae 100644 --- a/iot-server/server-health-checker/pom.xml +++ b/iot-server/server-health-checker/pom.xml @@ -15,7 +15,7 @@ com.zmops library-module - 1.0.1-RELEASE + 1.0.2-RELEASE compile diff --git a/iot-server/server-localdb/pom.xml b/iot-server/server-localdb/pom.xml index d0fa1671..3eb4e5a2 100644 --- a/iot-server/server-localdb/pom.xml +++ b/iot-server/server-localdb/pom.xml @@ -16,7 +16,7 @@ com.zmops library-module - 1.0.1-RELEASE + 1.0.2-RELEASE com.zmops diff --git a/iot-server/server-sender/pom.xml b/iot-server/server-sender/pom.xml index d6f44566..3406d2ac 100644 --- a/iot-server/server-sender/pom.xml +++ b/iot-server/server-sender/pom.xml @@ -15,7 +15,7 @@ com.zmops library-module - 1.0.1-RELEASE + 1.0.2-RELEASE diff --git a/iot-server/server-storage-plugin/server-none-storage/pom.xml b/iot-server/server-storage-plugin/server-none-storage/pom.xml index ceaaf19a..9fb8063f 100644 --- a/iot-server/server-storage-plugin/server-none-storage/pom.xml +++ b/iot-server/server-storage-plugin/server-none-storage/pom.xml @@ -14,7 +14,7 @@ com.zmops library-module - 1.0.1-RELEASE + 1.0.2-RELEASE com.zmops diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml index 15264a3a..28a44f1e 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml @@ -25,7 +25,7 @@ com.zmops library-module - 1.0.1-RELEASE + 1.0.2-RELEASE com.zmops diff --git a/iot-server/server-telemetry/telemetry-api/pom.xml b/iot-server/server-telemetry/telemetry-api/pom.xml index 6df8e8f2..7275637b 100644 --- a/iot-server/server-telemetry/telemetry-api/pom.xml +++ b/iot-server/server-telemetry/telemetry-api/pom.xml @@ -14,13 +14,13 @@ com.zmops library-module - 1.0.1-RELEASE + 1.0.2-RELEASE compile com.zmops library-util - 1.0.1-RELEASE + 1.0.2-RELEASE compile diff --git a/iot-server/server-telemetry/telemetry-prometheus/pom.xml b/iot-server/server-telemetry/telemetry-prometheus/pom.xml index 48ee2aea..f5561356 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/pom.xml +++ b/iot-server/server-telemetry/telemetry-prometheus/pom.xml @@ -43,7 +43,7 @@ com.zmops zeus-server-jetty - 1.0.1-RELEASE + 1.0.2-RELEASE compile diff --git a/iot-server/server-transfer/pom.xml b/iot-server/server-transfer/pom.xml index 9c84fffb..b279f71b 100644 --- a/iot-server/server-transfer/pom.xml +++ b/iot-server/server-transfer/pom.xml @@ -21,7 +21,7 @@ com.zmops zeus-transfer-tailx - 1.0.1-RELEASE + 1.0.2-RELEASE @@ -42,7 +42,7 @@ com.zmops library-module - 1.0.1-RELEASE + 1.0.2-RELEASE com.zmops diff --git a/iot-server/server-web/pom.xml b/iot-server/server-web/pom.xml index b64cc696..43fcb8fe 100644 --- a/iot-server/server-web/pom.xml +++ b/iot-server/server-web/pom.xml @@ -20,7 +20,7 @@ com.zmops library-web - 1.0.1-RELEASE + 1.0.2-RELEASE diff --git a/zeus-webapp/pom.xml b/zeus-webapp/pom.xml index b59594d3..5c764f96 100644 --- a/zeus-webapp/pom.xml +++ b/zeus-webapp/pom.xml @@ -35,7 +35,7 @@ com.zmops toolkit-async - 1.0.1-RELEASE + 1.0.2-RELEASE commons-httpclient From fb8df3e9b03b6aa1e601f258cad94248aa9cc9a3 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 2 Dec 2021 11:50:55 +0800 Subject: [PATCH 698/763] [fix]: fix device detail --- .../java/com/zmops/iot/web/device/service/DeviceService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 087bc8b0..a730f2e6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -519,6 +519,9 @@ public DeviceDto deviceDetail(String deviceId) { StringBuilder sql = generateBaseSql(); sql.append(" where d.device_id=:deviceId"); DeviceDto deviceDto = DB.findDto(DeviceDto.class, sql.toString()).setParameter("deviceId", deviceId).setParameter("deviceGroupIds", devGroupIds).findOne(); + if (deviceDto == null) { + throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); + } return deviceDto; } From 867fc6a836195a95a0baf2b22e8475fe1968224e Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 2 Dec 2021 14:26:10 +0800 Subject: [PATCH 699/763] [fix]: fix global translation --- .../zmops/iot/model/cache/filter/CachedValue.java | 5 +++-- .../iot/model/cache/filter/CachedValueFilter.java | 4 +--- .../java/com/zmops/iot/web/alarm/dto/AlarmDto.java | 4 ++-- .../com/zmops/iot/web/analyse/dto/LatestDto.java | 2 +- .../java/com/zmops/iot/web/device/dto/DeviceDto.java | 10 +++++----- .../com/zmops/iot/web/device/dto/DeviceGroupDto.java | 4 ++-- .../com/zmops/iot/web/device/dto/DeviceLogDto.java | 4 ++-- .../iot/web/device/dto/MultipleDeviceEventDto.java | 10 +++++----- .../zmops/iot/web/product/dto/ProductAttrDto.java | 12 ++++++------ .../com/zmops/iot/web/product/dto/ProductDto.java | 8 ++++---- .../zmops/iot/web/product/dto/ProductEventDto.java | 12 ++++++------ .../iot/web/product/dto/ProductEventRuleDto.java | 2 +- .../zmops/iot/web/product/dto/ProductServiceDto.java | 4 ++-- .../web/product/dto/ProductStatusFunctionDto.java | 12 ++++++------ .../java/com/zmops/iot/web/sys/dto/SysDictDto.java | 2 +- .../com/zmops/iot/web/sys/dto/SysDictTypeDto.java | 2 +- .../com/zmops/iot/web/sys/dto/SysLoginLogDto.java | 2 +- .../zmops/iot/web/sys/dto/SysOperationLogDto.java | 2 +- .../main/java/com/zmops/iot/web/sys/dto/UserDto.java | 6 +++--- .../java/com/zmops/iot/web/sys/dto/UserGroupDto.java | 6 +++--- .../java/com/zmops/iot/web/task/dto/TaskDto.java | 6 +++--- 21 files changed, 59 insertions(+), 60 deletions(-) diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValue.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValue.java index 1ed0e4ff..31db0d96 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValue.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValue.java @@ -7,6 +7,7 @@ /** * 字典翻译注解 @Repeatable + * @author yefei */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @@ -21,11 +22,11 @@ /** - * 添加的后缀名 + * 翻译后的字段名 * * @return */ - String suffix() default "Name"; + String fieldName(); /** diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java index 239231da..ca868b81 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java @@ -20,8 +20,6 @@ */ public class CachedValueFilter extends JsonSerializer { - public final static String SUFFIX = "Name"; - @Override public void serialize(Object object, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeStartObject(); @@ -62,7 +60,7 @@ public void serialize(Object object, JsonGenerator jsonGenerator, SerializerProv String res = getCachedValue(cachedValue, value); if (res != null) { exists = true; - jsonGenerator.writeStringField(fieldName + Optional.of(cachedValue.suffix()).orElse(SUFFIX), res); + jsonGenerator.writeStringField(cachedValue.fieldName(), res); } else { exists = exists || cachedValue.type().isNullable(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java index db500988..8f9020c1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java @@ -27,10 +27,10 @@ public class AlarmDto { private String acknowledged; - @CachedValue(type = DicType.Device) + @CachedValue(type = DicType.Device, fieldName = "deviceName") private String deviceId; - @CachedValue(value = "EVENT_LEVEL") + @CachedValue(value = "EVENT_LEVEL",fieldName = "severityName") private String severity; private String status; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java index 8ee33603..a662652b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java @@ -30,7 +30,7 @@ public class LatestDto { private String tags; - @CachedValue(value = "UNITS") + @CachedValue(value = "UNITS",fieldName = "unitsName") private String units; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java index 17aaca46..866d9367 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java @@ -21,7 +21,7 @@ @JsonSerialize(using = CachedValueFilter.class) public class DeviceDto { - @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Delete.class,BaseEntity.Status.class}) + @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Delete.class, BaseEntity.Status.class}) private String deviceId; private String edit; @@ -37,11 +37,11 @@ public class DeviceDto { @NotEmpty(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private List deviceGroupIds; - @CachedValue(value = "STATUS") + @CachedValue(value = "STATUS", fieldName = "statusName") @NotBlank(groups = {BaseEntity.Status.class}) private String status; - @CachedValue(value = "DEVICE_TYPE") + @CachedValue(value = "DEVICE_TYPE", fieldName = "typeName") private String type; private String remark; @@ -50,10 +50,10 @@ public class DeviceDto { private LocalDateTime updateTime; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") private Long createUser; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") private Long updateUser; private Long oldProductId; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java index aa47712a..8605fd5a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java @@ -23,9 +23,9 @@ public class DeviceGroupDto { private String remark; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") private Long createUser; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") private Long updateUser; private LocalDateTime createTime; private LocalDateTime updateTime; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java index 32bb7c27..fd767706 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java @@ -27,10 +27,10 @@ public class DeviceLogDto { private String content; - @CachedValue(type = DicType.Device) + @CachedValue(type = DicType.Device, fieldName = "deviceName") private String deviceId; - @CachedValue(value = "EVENT_LEVEL") + @CachedValue(value = "EVENT_LEVEL", fieldName = "severityName") private String severity; private String param; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java index 2d605350..01d956a0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java @@ -25,10 +25,10 @@ public class MultipleDeviceEventDto { private String eventRuleName; - @CachedValue(value = "EVENT_LEVEL") + @CachedValue(value = "EVENT_LEVEL", fieldName = "eventLevelName") private String eventLevel; - @CachedValue(value = "STATUS") + @CachedValue(value = "STATUS", fieldName = "statusName") private String status; private String inherit; @@ -36,10 +36,10 @@ public class MultipleDeviceEventDto { private String remark; private String classify; private String expLogic; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") private Long createUser; private String createTime; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") private Long updateUser; private String updateTime; @@ -49,7 +49,7 @@ public class MultipleDeviceEventDto { private Integer taskId; - @CachedValue(value = "triggerType") + @CachedValue(value = "triggerType", fieldName = "triggerTypeName") private String triggerType; private String scheduleConf; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java index fcf40173..56b3c989 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java @@ -28,17 +28,17 @@ public class ProductAttrDto { private String key; - @CachedValue(value = "UNITS") + @CachedValue(value = "UNITS", fieldName = "unitsName") private String units; - @CachedValue(value = "ATTR_TYPE") + @CachedValue(value = "ATTR_TYPE", fieldName = "sourceName") private String source; private String remark; private Long depAttrId; - @CachedValue(value = "EVENT_LEVEL") + @CachedValue(value = "EVENT_LEVEL", fieldName = "eventLevelName") private String eventLevel; @JsonIgnore @@ -46,7 +46,7 @@ public class ProductAttrDto { private String productId; - @CachedValue(value = "DATA_TYPE") + @CachedValue(value = "DATA_TYPE", fieldName = "valueTypeName") private String valueType; private String valuemapid; @@ -61,9 +61,9 @@ public class ProductAttrDto { LocalDateTime createTime; LocalDateTime updateTime; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") private Long createUser; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") private Long updateUser; private String clock; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java index a071757c..98c5eb4b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java @@ -19,14 +19,14 @@ public class ProductDto { private Long productId; - @CachedValue(type = DicType.ProdType) + @CachedValue(type = DicType.ProdType, fieldName = "groupName") private Long groupId; @JsonProperty("prodName") private String name; @JsonProperty("prodType") - @CachedValue(value = "DEVICE_TYPE") + @CachedValue(value = "DEVICE_TYPE", fieldName = "typeName") private String type; private String manufacturer; @@ -42,9 +42,9 @@ public class ProductDto { private LocalDateTime createTime; private LocalDateTime updateTime; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") private Long createUser; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") private Long updateUser; private Long deviceNum; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java index 49f1384e..f721fdb1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java @@ -19,25 +19,25 @@ public class ProductEventDto { private String eventRuleName; - @CachedValue(value = "EVENT_LEVEL") + @CachedValue(value = "EVENT_LEVEL", fieldName = "eventLevelName") private String eventLevel; - @CachedValue(value = "STATUS") + @CachedValue(value = "STATUS", fieldName = "statusName") private String status; - @CachedValue(value = "WHETHER") + @CachedValue(value = "WHETHER", fieldName = "inheritName") private String inherit; private String remark; private String classify; private String expLogic; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") private Long createUser; private String createTime; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") private Long updateUser; private String updateTime; private Integer taskId; - @CachedValue(value = "triggerType") + @CachedValue(value = "triggerType", fieldName = "triggerTypeName") private String triggerType; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java index 62162e30..7eaa5414 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java @@ -50,7 +50,7 @@ public class ProductEventRuleDto { private String scheduleConf; - @CachedValue(value = "triggerType") + @CachedValue(value = "triggerType", fieldName = "triggerTypeName") private Integer triggerType; private Integer taskId; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java index 9d986a40..84ebf5bf 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java @@ -31,10 +31,10 @@ public class ProductServiceDto { @NotNull(groups = BaseEntity.Create.class) private String relationId; - @CachedValue(value = "EXECUTE_TYPE") + @CachedValue(value = "EXECUTE_TYPE", fieldName = "asyncName") private String async; - @CachedValue(value = "WHETHER") + @CachedValue(value = "WHETHER", fieldName = "inheritName") private String inherit; private List productServiceParamList; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusFunctionDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusFunctionDto.java index b7a54023..b8fa4084 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusFunctionDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusFunctionDto.java @@ -29,13 +29,13 @@ public class ProductStatusFunctionDto { private String ruleCondition; - @CachedValue(value = "UNITS") + @CachedValue(value = "UNITS", fieldName = "unitName") private String unit; - @CachedValue(value = "UNITS") + @CachedValue(value = "UNITS", fieldName = "unitsName") private String units; - @CachedValue(value = "UNITS") + @CachedValue(value = "UNITS", fieldName = "unitsRecoveryName") private String unitsRecovery; private String productAttrKey; @@ -48,17 +48,17 @@ public class ProductStatusFunctionDto { private String productAttrKeyRecovery; - @CachedValue(value = "UNITS") + @CachedValue(value = "UNITS", fieldName = "unitRecoveryName") private String unitRecovery; private String attrName; private String attrNameRecovery; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") private Long createUser; private String createTime; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") private Long updateUser; private String updateTime; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictDto.java index ba873264..5f885c19 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictDto.java @@ -39,7 +39,7 @@ public class SysDictDto { /** * 状态 */ - @CachedValue(value = "STATUS") + @CachedValue(value = "STATUS", fieldName = "statusName") private String status; /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictTypeDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictTypeDto.java index 362cd216..dac2615e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictTypeDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictTypeDto.java @@ -44,7 +44,7 @@ public class SysDictTypeDto { /** * 状态 */ - @CachedValue(value = "STATUS") + @CachedValue(value = "STATUS", fieldName = "statusName") private String status; /** diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysLoginLogDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysLoginLogDto.java index 63227ae6..44062e1c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysLoginLogDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysLoginLogDto.java @@ -20,7 +20,7 @@ public class SysLoginLogDto { String logName; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "userName") Long userId; LocalDateTime createTime; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysOperationLogDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysOperationLogDto.java index 25f3baff..e5d15123 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysOperationLogDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysOperationLogDto.java @@ -22,7 +22,7 @@ public class SysOperationLogDto { private String logName; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "userName") private Long userId; private String className; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java index ccb3f61f..73e9128b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java @@ -53,7 +53,7 @@ public class UserDto { @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private Long userGroupId; - @CachedValue(value = "STATUS") + @CachedValue(value = "STATUS", fieldName = "statusName") private String status; @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) @@ -61,10 +61,10 @@ public class UserDto { private String roleName; private String userGroupName; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") private Long createUser; private String createTime; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") private Long updateUser; private String updateTime; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java index a5ea88de..0862fe0d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java @@ -42,7 +42,7 @@ public class UserGroupDto { @NotBlank private String groupName; - @CachedValue(value = "STATUS") + @CachedValue(value = "STATUS", fieldName = "statusName") private String status; private String remark; @@ -56,9 +56,9 @@ public class UserGroupDto { LocalDateTime updateTime; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") Long createUser; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") Long updateUser; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/task/dto/TaskDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/task/dto/TaskDto.java index faa36249..e95953cb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/task/dto/TaskDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/task/dto/TaskDto.java @@ -27,7 +27,7 @@ public class TaskDto { private Integer taskFailRetryCount = 0; - @CachedValue(value = "STATUS") + @CachedValue(value = "STATUS", fieldName = "triggerStatusName") private String triggerStatus = "ENABLE"; private Long triggerLastTime = 0L; @@ -42,9 +42,9 @@ public class TaskDto { LocalDateTime updateTime; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") private Long createUser; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") private Long updateUser; } From b9ed237bb1493e11643f945f176b5ad4d9018b58 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 2 Dec 2021 16:05:57 +0800 Subject: [PATCH 700/763] [feat]: sysuser add remark filed --- dist-material/bin/sql/zeus-iot.sql | 10 ++++++---- .../main/java/com/zmops/iot/domain/sys/SysUser.java | 2 ++ .../main/java/com/zmops/iot/web/sys/dto/UserDto.java | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/dist-material/bin/sql/zeus-iot.sql b/dist-material/bin/sql/zeus-iot.sql index 3ca1da35..df8a3711 100644 --- a/dist-material/bin/sql/zeus-iot.sql +++ b/dist-material/bin/sql/zeus-iot.sql @@ -12,7 +12,7 @@ Target Server Version : 130004 File Encoding : 65001 - Date: 23/11/2021 14:28:57 + Date: 02/12/2021 16:03:24 */ @@ -1571,7 +1571,8 @@ CREATE TABLE "public"."sys_user" ( "update_time" timestamp(6), "user_id" int8 NOT NULL DEFAULT nextval('sys_user_user_id_seq'::regclass), "zbx_token" varchar(255) COLLATE "pg_catalog"."default", - "zbx_id" varchar(64) COLLATE "pg_catalog"."default" + "zbx_id" varchar(64) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default" ) ; COMMENT ON COLUMN "public"."sys_user"."account" IS '登陆账号名'; @@ -1590,12 +1591,13 @@ COMMENT ON COLUMN "public"."sys_user"."update_time" IS '更新时间'; COMMENT ON COLUMN "public"."sys_user"."user_id" IS '用户ID'; COMMENT ON COLUMN "public"."sys_user"."zbx_token" IS 'zabbix 登陆 token'; COMMENT ON COLUMN "public"."sys_user"."zbx_id" IS 'zabbix 用户ID'; +COMMENT ON COLUMN "public"."sys_user"."remark" IS '备注'; -- ---------------------------- -- Records of sys_user -- ---------------------------- -INSERT INTO "public"."sys_user" VALUES ('root', '17db03c22596b7609c7c9704f16663e0', 'abcdef', '超级管理员', '888888@qq.com', '13812345678', 1, 1437232484602372096, 'ENABLE', 1, 1, '2021-07-30 21:43:02.686', '2021-07-30 21:43:02.686', 1, '5859e004e8d2a23e6c330c3f9cd277e2', '4'); -INSERT INTO "public"."sys_user" VALUES ('Admin', 'cbde417443393372dbac9c185a6ec159', 'gt3zs', '超级管理员', '', '', 1, 1437232484602372096, 'ENABLE', 1, 1, '2021-09-28 09:38:33.668', '2021-09-28 09:38:33.668', 122, 'f6ce31c5f70bf40fae2067087254202c', '1'); +INSERT INTO "public"."sys_user" VALUES ('root', '17db03c22596b7609c7c9704f16663e0', 'abcdef', '超级管理员', '888888@qq.com', '13812345678', 1, 1437232484602372096, 'ENABLE', 1, 1, '2021-07-30 21:43:02.686', '2021-07-30 21:43:02.686', 1, '5859e004e8d2a23e6c330c3f9cd277e2', '4', NULL); +INSERT INTO "public"."sys_user" VALUES ('Admin', 'cbde417443393372dbac9c185a6ec159', 'gt3zs', '超级管理员', '', '', 1, 1437232484602372096, 'ENABLE', 1, 1, '2021-09-28 09:38:33.668', '2021-09-28 09:38:33.668', 122, 'f6ce31c5f70bf40fae2067087254202c', '1', NULL); -- ---------------------------- -- Table structure for sys_user_group diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysUser.java b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysUser.java index e28b4728..925209f5 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysUser.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysUser.java @@ -42,4 +42,6 @@ public class SysUser extends BaseEntity { String zbxToken; String zbxId; + + String remark; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java index 73e9128b..13d224e4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java @@ -67,4 +67,5 @@ public class UserDto { @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") private Long updateUser; private String updateTime; + private String remark; } From f681c3c29b7d9a5d60452c2a3306db54ff94790b Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 7 Dec 2021 15:45:13 +0800 Subject: [PATCH 701/763] [fix]: fix forest retry --- zeus-starter/src/main/assembly/webapp.yml | 2 ++ zeus-starter/src/main/resources/application.yaml | 4 +++- .../java/com/zmops/iot/web/sys/service/SysUserService.java | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/zeus-starter/src/main/assembly/webapp.yml b/zeus-starter/src/main/assembly/webapp.yml index 650e57c8..7c854e70 100644 --- a/zeus-starter/src/main/assembly/webapp.yml +++ b/zeus-starter/src/main/assembly/webapp.yml @@ -44,6 +44,8 @@ spring: forest: log-enabled: false timeout: 5000 + max-retry-count: 3 # 最大请求重试次数,默认为 0 次 + max-retry-interval: 10 # 为最大重试时间间隔, 单位为毫秒,默认为 0 毫秒 variables: ## Zabbix API IP And ServerIp and ServerPort zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index 568cfda8..dff0033d 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -41,8 +41,10 @@ spring: template-loader-path: classpath:/public/ forest: - log-enabled: false + log-enabled: true timeout: 5000 + max-retry-count: 3 # 最大请求重试次数,默认为 0 次 + max-retry-interval: 10 # 为最大重试时间间隔, 单位为毫秒,默认为 0 毫秒 variables: ## Zabbix API IP And ServerIp and ServerPort zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java index 1fabd982..5254913d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java @@ -79,7 +79,7 @@ public Pager userList(UserParam userParam) { StringBuilder sql = new StringBuilder( "select u.account, u.name, u.email, u.phone, u.role_id,r.name role_name," + "u.user_group_id,g.group_name user_group_name, u.status, u.create_user, " + - "u.update_user, u.create_time, u.update_time, u.user_id FROM sys_user u"); + "u.update_user, u.create_time, u.update_time, u.user_id,u.remark FROM sys_user u"); sql.append(" LEFT JOIN sys_role r ON r.role_id = u.role_id "); sql.append(" LEFT JOIN sys_user_group g ON g.user_group_id = u.user_group_id "); From ed5d2ebeed844c641c44d93befa74b54bdbace32 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 7 Dec 2021 16:10:01 +0800 Subject: [PATCH 702/763] [fix]: user update --- .../main/java/com/zmops/iot/web/sys/factory/UserFactory.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/factory/UserFactory.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/factory/UserFactory.java index 535d8509..1157253a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/factory/UserFactory.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/factory/UserFactory.java @@ -77,6 +77,9 @@ public static SysUser editUser(UserDto newUser, SysUser oldUser) { if (ToolUtil.isNotEmpty(newUser.getStatus())) { oldUser.setStatus(newUser.getStatus()); } + if (ToolUtil.isNotEmpty(newUser.getRemark())) { + oldUser.setRemark(newUser.getRemark()); + } return oldUser; } } From 4df964002309c0451d6f167e2e2fdb0c7ab3ba18 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 8 Dec 2021 14:33:11 +0800 Subject: [PATCH 703/763] [feat]: update zabbix-receiver --- .../zabbix}/IoTDeviceValue.java | 0 .../zabbix}/ZabbixSenderComponent.java | 0 .../zabbix}/ZabbixSenderConsumer.java | 0 .../zabbix}/ZabbixSenderEndpoint.java | 0 .../zabbix}/ZabbixTrapper.java | 0 .../zabbix}/ZabbixTrapperProducer.java | 0 .../process/JsonToItemValueProcess.java | 0 .../zabbix}/worker/AbstractWorker.java | 0 .../worker/ItemDataTransferWorker.java | 0 .../zabbix}/worker/TransferWorker.java | 0 .../iot/server/receiver/tozabbix/Item.java | 23 -------- .../server/receiver/tozabbix/ItemValue.java | 55 ------------------- 12 files changed, 78 deletions(-) rename iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/{tozabbix => handler/zabbix}/IoTDeviceValue.java (100%) rename iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/{tozabbix => handler/zabbix}/ZabbixSenderComponent.java (100%) rename iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/{tozabbix => handler/zabbix}/ZabbixSenderConsumer.java (100%) rename iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/{tozabbix => handler/zabbix}/ZabbixSenderEndpoint.java (100%) rename iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/{tozabbix => handler/zabbix}/ZabbixTrapper.java (100%) rename iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/{tozabbix => handler/zabbix}/ZabbixTrapperProducer.java (100%) rename iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/{tozabbix => handler/zabbix}/process/JsonToItemValueProcess.java (100%) rename iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/{tozabbix => handler/zabbix}/worker/AbstractWorker.java (100%) rename iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/{tozabbix => handler/zabbix}/worker/ItemDataTransferWorker.java (100%) rename iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/{tozabbix => handler/zabbix}/worker/TransferWorker.java (100%) delete mode 100644 iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/Item.java delete mode 100644 iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ItemValue.java diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/IoTDeviceValue.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/IoTDeviceValue.java similarity index 100% rename from iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/IoTDeviceValue.java rename to iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/IoTDeviceValue.java diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixSenderComponent.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderComponent.java similarity index 100% rename from iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixSenderComponent.java rename to iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderComponent.java diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixSenderConsumer.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderConsumer.java similarity index 100% rename from iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixSenderConsumer.java rename to iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderConsumer.java diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixSenderEndpoint.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderEndpoint.java similarity index 100% rename from iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixSenderEndpoint.java rename to iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderEndpoint.java diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixTrapper.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapper.java similarity index 100% rename from iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixTrapper.java rename to iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapper.java diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixTrapperProducer.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapperProducer.java similarity index 100% rename from iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ZabbixTrapperProducer.java rename to iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapperProducer.java diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/process/JsonToItemValueProcess.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/process/JsonToItemValueProcess.java similarity index 100% rename from iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/process/JsonToItemValueProcess.java rename to iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/process/JsonToItemValueProcess.java diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/worker/AbstractWorker.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/AbstractWorker.java similarity index 100% rename from iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/worker/AbstractWorker.java rename to iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/AbstractWorker.java diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/worker/ItemDataTransferWorker.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/ItemDataTransferWorker.java similarity index 100% rename from iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/worker/ItemDataTransferWorker.java rename to iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/ItemDataTransferWorker.java diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/worker/TransferWorker.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/TransferWorker.java similarity index 100% rename from iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/worker/TransferWorker.java rename to iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/TransferWorker.java diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/Item.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/Item.java deleted file mode 100644 index 5abce615..00000000 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/Item.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.zmops.zeus.iot.server.receiver.tozabbix; - -/** - * @author nantian created at 2021/8/23 15:14 - *

- * 对应设备的属性 - */ -public interface Item { - - /** - * 设备ID 唯一 - * - * @return string - */ - String host(); - - /** - * 属性标识 唯一 - * - * @return string - */ - String key(); -} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ItemValue.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ItemValue.java deleted file mode 100644 index a9ca753a..00000000 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/tozabbix/ItemValue.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.zmops.zeus.iot.server.receiver.tozabbix; - -import lombok.Getter; -import lombok.Setter; - -/** - * @author nantian created at 2021/8/23 15:15 - */ - -@Getter -@Setter -public class ItemValue implements Item { - - private String host; // 【设备ID】 - - private String key; // 【属性标识】 - - // 【设备上报 值】,都是文本 - // Zabbix 会根据配置的ITEM 类型,进行转换,如果失败就报错 - private String value; - - private Long clock; // 秒,如果为 Null,则 zabbix 以接收时间为准 - - private Long ns; // 纳秒,如果为 Null,则 zabbix 以接收时间为准 - - - public ItemValue(String host, Long clock) { - this.host = host; - if (clock != null) { - this.clock = clock; - } - } - - /** - * 设置 数据时间,单独设置 以设备推送的时间数据为准 - * - * @param clock 毫秒,70年到现在 - * @param ns 纳秒,0-9位数 - */ - public void setTime(Long clock, Long ns) { - this.clock = clock; - this.ns = ns; - } - - - @Override - public String host() { - return getHost(); - } - - @Override - public String key() { - return getKey(); - } -} From d23b5da3e82b1a1e8bf409cc78aaf2f3320bf70b Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 8 Dec 2021 14:34:16 +0800 Subject: [PATCH 704/763] [feat]: update pom.xml --- iot-server/server-bootstrap/pom.xml | 9 ++++- iot-server/server-camel-receiver/pom.xml | 11 +++++++ iot-server/server-starter/pom.xml | 42 +++++++++++++----------- iot-server/server-web/pom.xml | 40 ++++++++++++++++++++++ pom.xml | 2 -- 5 files changed, 82 insertions(+), 22 deletions(-) diff --git a/iot-server/server-bootstrap/pom.xml b/iot-server/server-bootstrap/pom.xml index 2a0a739e..4413ef59 100644 --- a/iot-server/server-bootstrap/pom.xml +++ b/iot-server/server-bootstrap/pom.xml @@ -85,6 +85,14 @@ server-localdb 1.0-beta + + + + com.zmops.hello + zeus-ark-hello + 1.0-beta + ark-biz + - - - - - - - - - - - - + @@ -85,7 +78,18 @@ - + + org.apache.maven.plugins + maven-resources-plugin + + + + D:\\666 + src/main/webapp + + + + com.alipay.sofa sofa-ark-maven-plugin diff --git a/iot-server/server-web/pom.xml b/iot-server/server-web/pom.xml index b64cc696..5fc1cb81 100644 --- a/iot-server/server-web/pom.xml +++ b/iot-server/server-web/pom.xml @@ -22,6 +22,46 @@ library-web 1.0.1-RELEASE + + + com.zmops + runtime-server + 1.0.1-RELEASE + + + + com.zmops + zeus-commons + 1.0.1-RELEASE + + + com.zmops + library-module + 1.0.1-RELEASE + compile + + + com.zmops + server-camel-receiver + 1.0-beta + compile + + + cn.hutool + hutool-all + 5.7.6 + + + + org.apache.commons + commons-lang3 + 3.12.0 + + + + org.projectlombok + lombok + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 07d2a6aa..a735fb45 100644 --- a/pom.xml +++ b/pom.xml @@ -226,8 +226,6 @@ - - \ No newline at end of file From 7f45336803c2f6f1df491533558d48c80aab2fec Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 8 Dec 2021 14:35:14 +0800 Subject: [PATCH 705/763] [feat]: add ark biz component --- .../provider/CamelReceiverProvider.java | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverProvider.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverProvider.java index 336b81c1..07baa5e1 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverProvider.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverProvider.java @@ -1,10 +1,10 @@ package com.zmops.zeus.iot.server.receiver.provider; import com.zmops.zeus.iot.server.receiver.Const; +import com.zmops.zeus.iot.server.receiver.handler.ark.ArkBizComponent; +import com.zmops.zeus.iot.server.receiver.handler.zabbix.ZabbixSenderComponent; import com.zmops.zeus.iot.server.receiver.module.CamelReceiverModule; -import com.zmops.zeus.iot.server.receiver.routes.PgEventRouteBuilder; import com.zmops.zeus.iot.server.receiver.service.CamelContextHolderService; -import com.zmops.zeus.iot.server.receiver.tozabbix.ZabbixSenderComponent; import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; import com.zmops.zeus.server.library.module.*; import org.apache.camel.impl.DefaultCamelContext; @@ -46,15 +46,12 @@ public void prepare() throws ServiceNotProvidedException, ModuleStartException { @Override public void start() throws ServiceNotProvidedException, ModuleStartException { - camelContext.addComponent(Const.CAMEL_ZABBIX_COMPONENT_NAME, new ZabbixSenderComponent(getManager())); + camelContext.addComponent(Const.CAMEL_ARK_COMPONENT_NAME, new ArkBizComponent(getManager())); + } - try { - camelContext.addRoutes(new PgEventRouteBuilder()); - } catch (Exception e) { - e.printStackTrace(); - } - + @Override + public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { try { camelContext.start(); } catch (Exception e) { @@ -62,11 +59,6 @@ public void start() throws ServiceNotProvidedException, ModuleStartException { } } - @Override - public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { - - } - @Override public String[] requiredModules() { return new String[]{ From 9cf4edbc725ff5afaa55aa2030a0635f801ac5f4 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 8 Dec 2021 14:37:49 +0800 Subject: [PATCH 706/763] [feat]: update receiver --- .../zmops/zeus/iot/server/receiver/Const.java | 2 + .../receiver/handler/ark/ArkBizComponent.java | 28 +++++++++ .../receiver/handler/ark/ArkBizConsumer.java | 15 +++++ .../receiver/handler/ark/ArkBizEndpoint.java | 41 +++++++++++++ .../receiver/handler/ark/ArkBizProducer.java | 59 +++++++++++++++++++ .../handler/zabbix/IoTDeviceValue.java | 2 +- .../handler/zabbix/ZabbixSenderComponent.java | 2 +- .../handler/zabbix/ZabbixSenderConsumer.java | 2 +- .../handler/zabbix/ZabbixSenderEndpoint.java | 2 +- .../handler/zabbix/ZabbixTrapper.java | 3 +- .../handler/zabbix/ZabbixTrapperProducer.java | 12 +++- .../process/JsonToItemValueProcess.java | 6 +- .../handler/zabbix/worker/AbstractWorker.java | 2 +- .../zabbix/worker/ItemDataTransferWorker.java | 6 +- .../handler/zabbix/worker/TransferWorker.java | 4 +- .../receiver/routes/HttpRouteBuilder.java | 3 +- .../routes/MqttBrokerRouteBuilder.java | 20 +++++++ .../routes/MqttClientRouteBuilder.java | 38 +++++++++--- .../service/CamelContextHolderService.java | 33 ++++++++++- 19 files changed, 251 insertions(+), 29 deletions(-) create mode 100644 iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizComponent.java create mode 100644 iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizConsumer.java create mode 100644 iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizEndpoint.java create mode 100644 iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizProducer.java create mode 100644 iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttBrokerRouteBuilder.java diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/Const.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/Const.java index 2061058e..02a660ad 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/Const.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/Const.java @@ -3,4 +3,6 @@ public class Const { public static final String CAMEL_ZABBIX_COMPONENT_NAME = "Zabbix"; + + public static final String CAMEL_ARK_COMPONENT_NAME = "ArkBiz"; } diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizComponent.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizComponent.java new file mode 100644 index 00000000..84a90b5a --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizComponent.java @@ -0,0 +1,28 @@ +package com.zmops.zeus.iot.server.receiver.handler.ark; + +import com.zmops.zeus.server.library.module.ModuleManager; +import org.apache.camel.Endpoint; +import org.apache.camel.impl.DefaultComponent; + +import java.util.Map; + +/** + * @author nantian created at 2021/12/2 22:35 + */ +public class ArkBizComponent extends DefaultComponent { + + private final ModuleManager moduleManager; + + public ArkBizComponent(ModuleManager moduleManager) { + this.moduleManager = moduleManager; + } + + @Override + protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { + + String uniqueId = getAndRemoveParameter(parameters, "uniqueId", String.class); + String methodName = getAndRemoveParameter(parameters, "methodName", String.class); + + return new ArkBizEndpoint(uri, this, moduleManager, uniqueId, methodName); + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizConsumer.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizConsumer.java new file mode 100644 index 00000000..c48534cc --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizConsumer.java @@ -0,0 +1,15 @@ +package com.zmops.zeus.iot.server.receiver.handler.ark; + +import org.apache.camel.Endpoint; +import org.apache.camel.Processor; +import org.apache.camel.impl.DefaultConsumer; + +/** + * @author nantian created at 2021/12/2 22:35 + */ +public class ArkBizConsumer extends DefaultConsumer { + + public ArkBizConsumer(Endpoint endpoint, Processor processor) { + super(endpoint, processor); + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizEndpoint.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizEndpoint.java new file mode 100644 index 00000000..a2f235e2 --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizEndpoint.java @@ -0,0 +1,41 @@ +package com.zmops.zeus.iot.server.receiver.handler.ark; + +import com.zmops.zeus.server.library.module.ModuleManager; +import org.apache.camel.Component; +import org.apache.camel.Consumer; +import org.apache.camel.Processor; +import org.apache.camel.Producer; +import org.apache.camel.impl.DefaultEndpoint; + +/** + * @author nantian created at 2021/12/2 22:34 + */ +@SuppressWarnings("all") +public class ArkBizEndpoint extends DefaultEndpoint { + + private final ModuleManager moduleManager; + private final ArkBizProducer producer; + + public ArkBizEndpoint(String endpointUri, Component component, ModuleManager moduleManager, + String uniqueId, String methodName) { + super(endpointUri, component); + this.moduleManager = moduleManager; + this.producer = new ArkBizProducer(this, moduleManager, uniqueId, methodName); + } + + + @Override + public Producer createProducer() throws Exception { + return this.producer; + } + + @Override + public Consumer createConsumer(Processor processor) throws Exception { + return new ArkBizConsumer(this, processor); + } + + @Override + public boolean isSingleton() { + return false; + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizProducer.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizProducer.java new file mode 100644 index 00000000..09dfbb01 --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizProducer.java @@ -0,0 +1,59 @@ +package com.zmops.zeus.iot.server.receiver.handler.ark; + +import com.zmops.zeus.dto.DataMessage; +import com.zmops.zeus.dto.ItemValue; +import com.zmops.zeus.facade.DynamicProcotol; +import com.zmops.zeus.server.library.module.ModuleManager; +import com.zmops.zeus.server.runtime.SofaStarter; +import com.zmops.zeus.server.runtime.api.client.ReferenceClient; +import com.zmops.zeus.server.runtime.api.client.param.ReferenceParam; +import org.apache.camel.Endpoint; +import org.apache.camel.Exchange; +import org.apache.camel.impl.DefaultProducer; + +import java.util.Collections; +import java.util.List; + +/** + * @author nantian created at 2021/12/2 22:35 + */ +@SuppressWarnings("all") +public class ArkBizProducer extends DefaultProducer { + + private final SofaStarter sofaStarter; + private final ReferenceClient referenceClient; + + private final String methodName; + private final ModuleManager moduleManager; + + private final DynamicProcotol dynamicClient; + + public ArkBizProducer(Endpoint endpoint, ModuleManager moduleManager, String uniqueId, String methodName) { + super(endpoint); + this.moduleManager = moduleManager; + this.sofaStarter = new SofaStarter(); + this.referenceClient = this.sofaStarter.getSofaRuntimeContext().getClientFactory().getClient(ReferenceClient.class); + this.methodName = methodName; + + ReferenceParam referenceParam = new ReferenceParam<>(); + referenceParam.setInterfaceType(DynamicProcotol.class); + referenceParam.setUniqueId(uniqueId); + dynamicClient = referenceClient.reference(referenceParam); + } + + @Override + public void process(Exchange exchange) throws Exception { + + DataMessage message = new DataMessage(); + message.setBody(exchange.getMessage().getBody()); + message.setHeaders(exchange.getMessage().getHeaders()); + + List itemValueList = dynamicClient.protocolHandler(message); + + if (itemValueList == null) { + itemValueList = Collections.emptyList(); + } + + exchange.getIn().setBody(itemValueList); + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/IoTDeviceValue.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/IoTDeviceValue.java index 8646307d..42c8b951 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/IoTDeviceValue.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/IoTDeviceValue.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.receiver.tozabbix; +package com.zmops.zeus.iot.server.receiver.handler.zabbix; import lombok.Getter; import lombok.Setter; diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderComponent.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderComponent.java index 4cf93b32..008855a6 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderComponent.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderComponent.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.receiver.tozabbix; +package com.zmops.zeus.iot.server.receiver.handler.zabbix; import com.zmops.zeus.server.library.module.ModuleManager; import org.apache.camel.Endpoint; diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderConsumer.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderConsumer.java index 47e3e003..fc74bd2b 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderConsumer.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderConsumer.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.receiver.tozabbix; +package com.zmops.zeus.iot.server.receiver.handler.zabbix; import org.apache.camel.Endpoint; import org.apache.camel.Processor; diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderEndpoint.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderEndpoint.java index 495cf8f4..8b9452fd 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderEndpoint.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderEndpoint.java @@ -1,4 +1,4 @@ -package com.zmops.zeus.iot.server.receiver.tozabbix; +package com.zmops.zeus.iot.server.receiver.handler.zabbix; import com.zmops.zeus.server.library.module.ModuleManager; import org.apache.camel.Component; diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapper.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapper.java index 93823424..ad45c766 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapper.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapper.java @@ -1,5 +1,6 @@ -package com.zmops.zeus.iot.server.receiver.tozabbix; +package com.zmops.zeus.iot.server.receiver.handler.zabbix; +import com.zmops.zeus.dto.ItemValue; import lombok.Getter; import lombok.Setter; diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapperProducer.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapperProducer.java index 44ce527e..5614f9a5 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapperProducer.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapperProducer.java @@ -1,7 +1,8 @@ -package com.zmops.zeus.iot.server.receiver.tozabbix; +package com.zmops.zeus.iot.server.receiver.handler.zabbix; import com.google.gson.Gson; -import com.zmops.zeus.iot.server.receiver.tozabbix.worker.ItemDataTransferWorker; +import com.zmops.zeus.dto.ItemValue; +import com.zmops.zeus.iot.server.receiver.handler.zabbix.worker.ItemDataTransferWorker; import com.zmops.zeus.server.library.module.ModuleManager; import com.zmops.zeus.server.library.util.StringUtil; import org.apache.camel.Endpoint; @@ -39,7 +40,12 @@ public ZabbixTrapperProducer(Endpoint endpoint, ModuleManager moduleManager) { @Override public void process(Exchange exchange) { Message message = exchange.getIn(); - List values = (List) message.getBody(); //TODO 类型检查 + + if (message.getBody() == null && !(message.getBody() instanceof List)) { + return; + } + + List values = (List) message.getBody(); for (ItemValue itemValue : values) { if (StringUtil.isEmpty(itemValue.getHost()) diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/process/JsonToItemValueProcess.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/process/JsonToItemValueProcess.java index 39fdd7dd..74721dcd 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/process/JsonToItemValueProcess.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/process/JsonToItemValueProcess.java @@ -1,8 +1,8 @@ -package com.zmops.zeus.iot.server.receiver.tozabbix.process; +package com.zmops.zeus.iot.server.receiver.handler.zabbix.process; import com.google.gson.Gson; -import com.zmops.zeus.iot.server.receiver.tozabbix.IoTDeviceValue; -import com.zmops.zeus.iot.server.receiver.tozabbix.ItemValue; +import com.zmops.zeus.dto.ItemValue; +import com.zmops.zeus.iot.server.receiver.handler.zabbix.IoTDeviceValue; import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.camel.Processor; diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/AbstractWorker.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/AbstractWorker.java index b7c7fd9c..885d831f 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/AbstractWorker.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/AbstractWorker.java @@ -16,7 +16,7 @@ * */ -package com.zmops.zeus.iot.server.receiver.tozabbix.worker; +package com.zmops.zeus.iot.server.receiver.handler.zabbix.worker; import com.zmops.zeus.server.library.module.ModuleDefineHolder; import lombok.Getter; diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/ItemDataTransferWorker.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/ItemDataTransferWorker.java index a3296d50..4f7f1a35 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/ItemDataTransferWorker.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/ItemDataTransferWorker.java @@ -1,8 +1,8 @@ -package com.zmops.zeus.iot.server.receiver.tozabbix.worker; +package com.zmops.zeus.iot.server.receiver.handler.zabbix.worker; import com.google.gson.Gson; -import com.zmops.zeus.iot.server.receiver.tozabbix.ItemValue; -import com.zmops.zeus.iot.server.receiver.tozabbix.ZabbixTrapper; +import com.zmops.zeus.dto.ItemValue; +import com.zmops.zeus.iot.server.receiver.handler.zabbix.ZabbixTrapper; import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; import com.zmops.zeus.iot.server.sender.service.ZabbixSenderService; import com.zmops.zeus.iot.server.telemetry.TelemetryModule; diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/TransferWorker.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/TransferWorker.java index 444341e7..ba7e2cd2 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/TransferWorker.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/TransferWorker.java @@ -16,10 +16,10 @@ * */ -package com.zmops.zeus.iot.server.receiver.tozabbix.worker; +package com.zmops.zeus.iot.server.receiver.handler.zabbix.worker; -import com.zmops.zeus.iot.server.receiver.tozabbix.Item; +import com.zmops.zeus.dto.Item; import com.zmops.zeus.server.library.module.ModuleDefineHolder; import lombok.extern.slf4j.Slf4j; diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/HttpRouteBuilder.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/HttpRouteBuilder.java index 8a897ce4..05e8168a 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/HttpRouteBuilder.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/HttpRouteBuilder.java @@ -21,7 +21,8 @@ public HttpRouteBuilder(String routeId, Map option) { @Override public void configure() throws Exception { fromF("netty4-http:http://0.0.0.0:%s/data?sync=true", options.get("port")) - .routeId(routeId).log(LoggingLevel.DEBUG, log, ">>> Message received from Netty4 Http Server : ${body}"); + .routeId(routeId) + .log(LoggingLevel.DEBUG, log, ">>> Message received from Netty4 Http Server : ${body}"); } diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttBrokerRouteBuilder.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttBrokerRouteBuilder.java new file mode 100644 index 00000000..c91d72cd --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttBrokerRouteBuilder.java @@ -0,0 +1,20 @@ +package com.zmops.zeus.iot.server.receiver.routes; + +import com.zmops.zeus.iot.server.receiver.ReceiverServerRoute; + +import java.util.Map; + +/** + * @author nantian created at 2021/11/26 13:54 + */ +public class MqttBrokerRouteBuilder extends ReceiverServerRoute { + + public MqttBrokerRouteBuilder(String routeId, Map options) { + super(routeId, options); + } + + @Override + public void configure() throws Exception { + + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttClientRouteBuilder.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttClientRouteBuilder.java index a9a5fecf..19c01321 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttClientRouteBuilder.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttClientRouteBuilder.java @@ -3,8 +3,9 @@ import com.zmops.zeus.iot.server.receiver.ReceiverServerRoute; import org.apache.camel.Exchange; import org.apache.camel.LoggingLevel; -import org.apache.camel.Processor; +import org.apache.camel.Message; +import java.util.List; import java.util.Map; /** @@ -20,14 +21,35 @@ public MqttClientRouteBuilder(String routeId, Map options) { @Override public void configure() throws Exception { - fromF("mqtt:zeus-iot-mqtt?host=tcp://%s:%s&subscribeTopicNames=123/up", options.get("hostIp"), options.get("port")) - .routeId(routeId).log(LoggingLevel.DEBUG, log, ">>> Message received from Mqtt Client : ${body}"); + fromF("mqtt:zeus-iot-mqtt?host=tcp://%s:%s&subscribeTopicNames=%s", options.get("hostIp"), options.get("port"), options.get("topicNames")) + .routeId(routeId) + .log(LoggingLevel.DEBUG, log, ">>> Message received from Mqtt Client : \n${body}") + .dynamicRouter(method(RouteJudge.class, "slip")).to("Zabbix"); + } + + + static class RouteJudge { + public static String slip(Exchange exchange) { + Message message = exchange.getMessage(); - from("direct:foo").process(new Processor() { - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setBody("123"); + if (message.getBody() instanceof List) { + return null; } - }).to("mqtt:zeus-iot-mqtt"); + + String topicName = exchange.getIn().getHeader("CamelMQTTSubscribeTopic").toString(); + + //TODO 这里需要动态加载规则 + + if (topicName.equals("zeusiot/123")) { + return "ArkBiz?uniqueId=198909118"; + } + + if (topicName.equals("zeusiot/1234")) { + return "ArkBiz?uniqueId=19890918"; + } + + return null; + } + } } diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/CamelContextHolderService.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/CamelContextHolderService.java index 6b9f4934..97d18b65 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/CamelContextHolderService.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/CamelContextHolderService.java @@ -2,16 +2,21 @@ import com.zmops.zeus.server.library.module.ModuleManager; import com.zmops.zeus.server.library.module.Service; +import lombok.extern.slf4j.Slf4j; import org.apache.camel.CamelContext; import org.apache.camel.Route; import org.apache.camel.RoutesBuilder; import org.apache.camel.impl.EventDrivenConsumerRoute; +import org.apache.camel.model.FromDefinition; + +import java.util.List; /** * @author nantian created at 2021/8/17 0:24 *

* CamelContextHolderService ,便于模块服务调用,全局只有一个 Camel 上下文 */ +@Slf4j public class CamelContextHolderService implements Service { private final CamelContext camelContext; @@ -22,7 +27,6 @@ public CamelContextHolderService(CamelContext camelContext, ModuleManager module this.moduleManager = moduleManager; } - /** * 配置路由 * @@ -44,13 +48,36 @@ public void addRoutes(RoutesBuilder builder) { */ public void routeShutDown(String routeId) { EventDrivenConsumerRoute route = (EventDrivenConsumerRoute) camelContext.getRoute(routeId); + List fromDefinitions = camelContext.getRouteDefinition(routeId).getInputs(); + try { - route.getEndpoint().stop(); - route.getConsumer().stop(); + camelContext.stopRoute(routeId); + camelContext.removeRoute(routeId); +// camelContext.removeRouteDefinition(camelContext.getRouteDefinition(routeId)); } catch (Exception e) { e.printStackTrace(); } + + +// if (route == null) { +// log.error("当前 routeId : {} 对应的路由不存在", routeId); +// return; +// } +// try { +// route.getEndpoint().stop(); +// route.getConsumer().stop(); +// +// } catch (Exception e) { +// e.printStackTrace(); +// } +// +// +// try { +// camelContext.removeRoute(routeId); +// } catch (Exception e) { +// e.printStackTrace(); +// } } From 1285b76a3e2e1f241c1d632f5fb6dc97513a6d55 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 8 Dec 2021 14:38:10 +0800 Subject: [PATCH 707/763] [feat]: add ark component starter --- .../com/zmops/zeus/iot/server/starter/IoTServerStartUp.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerStartUp.java b/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerStartUp.java index fbd0699a..b3435976 100644 --- a/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerStartUp.java +++ b/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerStartUp.java @@ -1,5 +1,6 @@ package com.zmops.zeus.iot.server.starter; +import com.alipay.sofa.ark.support.startup.SofaArkBootstrap; import lombok.extern.slf4j.Slf4j; /** @@ -11,7 +12,7 @@ public class IoTServerStartUp { public static void main(String[] args) { -// SofaArkBootstrap.launch(args); + SofaArkBootstrap.launch(args); IoTServerBootstrap.start(); log.info("IoT Server Platform start successfully ..."); From 7c9e8277033b95a8b41b195426b0a428446031f2 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 8 Dec 2021 14:40:49 +0800 Subject: [PATCH 708/763] [web]: add web page file --- .../src/main/webapp/assets/gulpfile.js | 170 + .../src/main/webapp/assets/package-lock.json | 3808 +++++++++++++++++ .../src/main/webapp/assets/package.json | 23 + .../src/main/webapp/assets/src/config.js | 153 + .../webapp/assets/src/controller/common.js | 40 + .../webapp/assets/src/controller/console.js | 335 ++ .../webapp/assets/src/controller/contlist.js | 166 + .../webapp/assets/src/controller/forum.js | 125 + .../webapp/assets/src/controller/sample.js | 299 ++ .../webapp/assets/src/controller/senior.js | 1153 +++++ .../main/webapp/assets/src/controller/set.js | 155 + .../main/webapp/assets/src/controller/user.js | 52 + .../webapp/assets/src/controller/useradmin.js | 184 + .../webapp/assets/src/controller/workorder.js | 70 + .../src/main/webapp/assets/src/index.js | 213 + .../src/main/webapp/assets/src/lib/admin.js | 861 ++++ .../webapp/assets/src/lib/extend/echarts.js | 39 + .../assets/src/lib/extend/echartsTheme.js | 267 ++ .../layim/layim-assets/html/chatlog.html | 98 + .../extend/layim/layim-assets/html/find.html | 43 + .../layim/layim-assets/html/getmsg.json | 72 + .../layim/layim-assets/html/msgbox.html | 218 + .../layim/layim-assets/images/default.png | Bin 0 -> 6727 bytes .../layim/layim-assets/images/face/0.gif | Bin 0 -> 2689 bytes .../layim/layim-assets/images/face/1.gif | Bin 0 -> 5514 bytes .../layim/layim-assets/images/face/10.gif | Bin 0 -> 2797 bytes .../layim/layim-assets/images/face/11.gif | Bin 0 -> 4121 bytes .../layim/layim-assets/images/face/12.gif | Bin 0 -> 3361 bytes .../layim/layim-assets/images/face/13.gif | Bin 0 -> 7425 bytes .../layim/layim-assets/images/face/14.gif | Bin 0 -> 2375 bytes .../layim/layim-assets/images/face/15.gif | Bin 0 -> 1793 bytes .../layim/layim-assets/images/face/16.gif | Bin 0 -> 6721 bytes .../layim/layim-assets/images/face/17.gif | Bin 0 -> 4439 bytes .../layim/layim-assets/images/face/18.gif | Bin 0 -> 3017 bytes .../layim/layim-assets/images/face/19.gif | Bin 0 -> 3040 bytes .../layim/layim-assets/images/face/2.gif | Bin 0 -> 3222 bytes .../layim/layim-assets/images/face/20.gif | Bin 0 -> 5144 bytes .../layim/layim-assets/images/face/21.gif | Bin 0 -> 5191 bytes .../layim/layim-assets/images/face/22.gif | Bin 0 -> 9823 bytes .../layim/layim-assets/images/face/23.gif | Bin 0 -> 3792 bytes .../layim/layim-assets/images/face/24.gif | Bin 0 -> 8096 bytes .../layim/layim-assets/images/face/25.gif | Bin 0 -> 3127 bytes .../layim/layim-assets/images/face/26.gif | Bin 0 -> 3291 bytes .../layim/layim-assets/images/face/27.gif | Bin 0 -> 4377 bytes .../layim/layim-assets/images/face/28.gif | Bin 0 -> 2793 bytes .../layim/layim-assets/images/face/29.gif | Bin 0 -> 4854 bytes .../layim/layim-assets/images/face/3.gif | Bin 0 -> 4017 bytes .../layim/layim-assets/images/face/30.gif | Bin 0 -> 2555 bytes .../layim/layim-assets/images/face/31.gif | Bin 0 -> 2002 bytes .../layim/layim-assets/images/face/32.gif | Bin 0 -> 3481 bytes .../layim/layim-assets/images/face/33.gif | Bin 0 -> 2454 bytes .../layim/layim-assets/images/face/34.gif | Bin 0 -> 3700 bytes .../layim/layim-assets/images/face/35.gif | Bin 0 -> 1800 bytes .../layim/layim-assets/images/face/36.gif | Bin 0 -> 2331 bytes .../layim/layim-assets/images/face/37.gif | Bin 0 -> 1513 bytes .../layim/layim-assets/images/face/38.gif | Bin 0 -> 3615 bytes .../layim/layim-assets/images/face/39.gif | Bin 0 -> 6495 bytes .../layim/layim-assets/images/face/4.gif | Bin 0 -> 5689 bytes .../layim/layim-assets/images/face/40.gif | Bin 0 -> 3154 bytes .../layim/layim-assets/images/face/41.gif | Bin 0 -> 3644 bytes .../layim/layim-assets/images/face/42.gif | Bin 0 -> 5305 bytes .../layim/layim-assets/images/face/43.gif | Bin 0 -> 2674 bytes .../layim/layim-assets/images/face/44.gif | Bin 0 -> 4126 bytes .../layim/layim-assets/images/face/45.gif | Bin 0 -> 3417 bytes .../layim/layim-assets/images/face/46.gif | Bin 0 -> 3007 bytes .../layim/layim-assets/images/face/47.gif | Bin 0 -> 2333 bytes .../layim/layim-assets/images/face/48.gif | Bin 0 -> 2689 bytes .../layim/layim-assets/images/face/49.gif | Bin 0 -> 2315 bytes .../layim/layim-assets/images/face/5.gif | Bin 0 -> 4567 bytes .../layim/layim-assets/images/face/50.gif | Bin 0 -> 5866 bytes .../layim/layim-assets/images/face/51.gif | Bin 0 -> 2785 bytes .../layim/layim-assets/images/face/52.gif | Bin 0 -> 777 bytes .../layim/layim-assets/images/face/53.gif | Bin 0 -> 2127 bytes .../layim/layim-assets/images/face/54.gif | Bin 0 -> 2196 bytes .../layim/layim-assets/images/face/55.gif | Bin 0 -> 1971 bytes .../layim/layim-assets/images/face/56.gif | Bin 0 -> 2034 bytes .../layim/layim-assets/images/face/57.gif | Bin 0 -> 2705 bytes .../layim/layim-assets/images/face/58.gif | Bin 0 -> 2258 bytes .../layim/layim-assets/images/face/59.gif | Bin 0 -> 10311 bytes .../layim/layim-assets/images/face/6.gif | Bin 0 -> 2213 bytes .../layim/layim-assets/images/face/60.gif | Bin 0 -> 3245 bytes .../layim/layim-assets/images/face/61.gif | Bin 0 -> 2495 bytes .../layim/layim-assets/images/face/62.gif | Bin 0 -> 2017 bytes .../layim/layim-assets/images/face/63.gif | Bin 0 -> 5871 bytes .../layim/layim-assets/images/face/64.gif | Bin 0 -> 6448 bytes .../layim/layim-assets/images/face/65.gif | Bin 0 -> 3576 bytes .../layim/layim-assets/images/face/66.gif | Bin 0 -> 3029 bytes .../layim/layim-assets/images/face/67.gif | Bin 0 -> 2701 bytes .../layim/layim-assets/images/face/68.gif | Bin 0 -> 1424 bytes .../layim/layim-assets/images/face/69.gif | Bin 0 -> 2431 bytes .../layim/layim-assets/images/face/7.gif | Bin 0 -> 3398 bytes .../layim/layim-assets/images/face/70.gif | Bin 0 -> 4590 bytes .../layim/layim-assets/images/face/71.gif | Bin 0 -> 5304 bytes .../layim/layim-assets/images/face/8.gif | Bin 0 -> 4050 bytes .../layim/layim-assets/images/face/9.gif | Bin 0 -> 4221 bytes .../lib/extend/layim/layim-assets/layim.css | 2 + .../layim/layim-assets/lib/layer-mobile.js | 2 + .../layim-assets/lib/layim-mobile-open.js | 2 + .../layim/layim-assets/lib/layim-mobile.js | 2 + .../extend/layim/layim-assets/lib/zepto.js | 2 + .../lib/extend/layim/layim-assets/mobile.css | 2 + .../lib/extend/layim/layim-assets/skin/1.jpg | Bin 0 -> 19399 bytes .../lib/extend/layim/layim-assets/skin/2.jpg | Bin 0 -> 11883 bytes .../lib/extend/layim/layim-assets/skin/3.jpg | Bin 0 -> 18610 bytes .../lib/extend/layim/layim-assets/skin/4.jpg | Bin 0 -> 39279 bytes .../lib/extend/layim/layim-assets/skin/5.jpg | Bin 0 -> 45901 bytes .../layim/layim-assets/voice/default.mp3 | Bin 0 -> 9341 bytes .../assets/src/lib/extend/layim/layim.js | 3 + .../src/main/webapp/assets/src/lib/view.js | 344 ++ .../main/webapp/assets/src/style/admin.css | 522 +++ .../main/webapp/assets/src/style/login.css | 51 + .../webapp/assets/src/style/res/bg-none.jpg | Bin 0 -> 832 bytes .../assets/src/style/res/layui-logo.jpg | Bin 0 -> 2871 bytes .../assets/src/style/res/logo-black.png | Bin 0 -> 455 bytes .../main/webapp/assets/src/style/res/logo.png | Bin 0 -> 457 bytes .../src/style/res/template/character.jpg | Bin 0 -> 6727 bytes .../assets/src/style/res/template/huge.jpg | Bin 0 -> 12627 bytes .../src/style/res/template/portrait.png | Bin 0 -> 6727 bytes .../main/webapp/assets/src/style/template.css | 182 + .../assets/src/views/app/content/comment.html | 107 + .../src/views/app/content/contform.html | 20 + .../assets/src/views/app/content/list.html | 151 + .../src/views/app/content/listform.html | 67 + .../assets/src/views/app/content/tags.html | 65 + .../src/views/app/content/tagsform.html | 17 + .../assets/src/views/app/forum/list.html | 124 + .../assets/src/views/app/forum/listform.html | 53 + .../assets/src/views/app/forum/replys.html | 99 + .../src/views/app/forum/replysform.html | 34 + .../assets/src/views/app/message/detail.html | 42 + .../assets/src/views/app/message/index.html | 176 + .../assets/src/views/app/workorder/list.html | 89 + .../src/views/app/workorder/listform.html | 59 + .../views/app/\350\257\264\346\230\216.txt" | 2 + .../src/views/component/anim/index.html | 108 + .../src/views/component/auxiliar/index.html | 103 + .../src/views/component/badge/index.html | 103 + .../src/views/component/button/index.html | 178 + .../src/views/component/carousel/index.html | 219 + .../src/views/component/code/index.html | 141 + .../views/component/colorpicker/index.html | 190 + .../src/views/component/dropdown/index.html | 571 +++ .../src/views/component/flow/index.html | 124 + .../src/views/component/form/element.html | 237 + .../src/views/component/form/group.html | 291 ++ .../assets/src/views/component/grid/all.html | 80 + .../assets/src/views/component/grid/list.html | 122 + .../src/views/component/grid/mobile-pc.html | 80 + .../src/views/component/grid/mobile.html | 112 + .../src/views/component/grid/speed-dial.html | 84 + .../src/views/component/grid/stack.html | 143 + .../src/views/component/laydate/demo1.html | 324 ++ .../src/views/component/laydate/demo2.html | 276 ++ .../views/component/laydate/special-demo.html | 74 + .../src/views/component/laydate/theme.html | 173 + .../src/views/component/layer/list.html | 491 +++ .../views/component/layer/special-demo.html | 174 + .../src/views/component/layer/theme.html | 82 + .../src/views/component/laypage/demo1.html | 158 + .../src/views/component/laypage/demo2.html | 159 + .../src/views/component/laytpl/index.html | 34 + .../assets/src/views/component/nav/index.html | 206 + .../src/views/component/panel/index.html | 181 + .../src/views/component/progress/index.html | 159 + .../src/views/component/rate/index.html | 177 + .../src/views/component/slider/index.html | 216 + .../src/views/component/table/auto.html | 49 + .../src/views/component/table/cellEdit.html | 56 + .../src/views/component/table/cellEvent.html | 67 + .../src/views/component/table/checkbox.html | 50 + .../src/views/component/table/data.html | 141 + .../src/views/component/table/fixed.html | 53 + .../src/views/component/table/form.html | 82 + .../src/views/component/table/height.html | 51 + .../src/views/component/table/initSort.html | 48 + .../src/views/component/table/onrow.html | 67 + .../src/views/component/table/operate.html | 107 + .../src/views/component/table/page.html | 57 + .../src/views/component/table/parseData.html | 65 + .../src/views/component/table/radio.html | 70 + .../src/views/component/table/reload.html | 87 + .../src/views/component/table/resetPage.html | 58 + .../src/views/component/table/simple.html | 48 + .../src/views/component/table/static.html | 309 ++ .../src/views/component/table/style.html | 63 + .../src/views/component/table/thead.html | 96 + .../src/views/component/table/toolbar.html | 109 + .../src/views/component/table/tostatic.html | 75 + .../src/views/component/table/totalRow.html | 78 + .../src/views/component/tabs/index.html | 188 + .../src/views/component/timeline/index.html | 121 + .../src/views/component/transfer/index.html | 185 + .../src/views/component/tree/index.html | 432 ++ .../src/views/component/upload/demo1.html | 199 + .../src/views/component/upload/demo2.html | 187 + .../src/views/component/util/index.html | 90 + .../component/\350\257\264\346\230\216.txt" | 2 + .../assets/src/views/home/homepage1.html | 194 + .../assets/src/views/home/homepage2.html | 306 ++ .../assets/src/views/iframe/layer/iframe.html | 83 + .../assets/src/views/iframe/link/baidu.html | 3 + .../iframe/\350\257\264\346\230\216.txt" | 3 + .../main/webapp/assets/src/views/index.html | 391 ++ .../main/webapp/assets/src/views/layout.html | 200 + .../assets/src/views/senior/echarts/bar.html | 108 + .../assets/src/views/senior/echarts/line.html | 102 + .../assets/src/views/senior/echarts/map.html | 34 + .../assets/src/views/senior/im/index.html | 427 ++ .../senior/\350\257\264\346\230\216.txt" | 2 + .../assets/src/views/set/system/email.html | 69 + .../assets/src/views/set/system/website.html | 95 + .../assets/src/views/set/user/info.html | 98 + .../assets/src/views/set/user/password.html | 53 + .../views/set/\350\257\264\346\230\216.txt" | 2 + .../webapp/assets/src/views/system/about.html | 17 + .../webapp/assets/src/views/system/more.html | 22 + .../webapp/assets/src/views/system/theme.html | 43 + .../system/\350\257\264\346\230\216.txt" | 3 + .../main/webapp/assets/src/views/temp.html | 51 + .../src/views/template/addresslist.html | 370 ++ .../assets/src/views/template/caller.html | 195 + .../assets/src/views/template/goodslist.html | 410 ++ .../assets/src/views/template/msgboard.html | 97 + .../src/views/template/personalpage.html | 425 ++ .../assets/src/views/template/search.html | 97 + .../assets/src/views/template/tips/404.html | 15 + .../assets/src/views/template/tips/error.html | 13 + .../assets/src/views/template/tips/test.html | 13 + .../src/views/template/user/forget.html | 30 + .../assets/src/views/template/user/login.html | 69 + .../assets/src/views/template/user/reg.html | 30 + .../template/\350\257\264\346\230\216.txt" | 2 + .../views/user/administrators/adminform.html | 66 + .../src/views/user/administrators/list.html | 161 + .../src/views/user/administrators/role.html | 127 + .../views/user/administrators/roleform.html | 59 + .../webapp/assets/src/views/user/forget.html | 138 + .../webapp/assets/src/views/user/login.html | 121 + .../webapp/assets/src/views/user/reg.html | 120 + .../assets/src/views/user/user/list.html | 150 + .../assets/src/views/user/user/userform.html | 72 + .../views/user/\350\257\264\346\230\216.txt" | 2 + .../src/main/webapp/assets/zeus/index.html | 28 + .../assets/zeus/json/console/prograss.js | 36 + .../assets/zeus/json/console/top-card.js | 76 + .../assets/zeus/json/console/top-search.js | 46 + .../assets/zeus/json/content/comment.js | 56 + .../webapp/assets/zeus/json/content/list.js | 62 + .../webapp/assets/zeus/json/content/tags.js | 21 + .../webapp/assets/zeus/json/forum/list.js | 62 + .../webapp/assets/zeus/json/forum/replys.js | 69 + .../webapp/assets/zeus/json/layer/photos.js | 39 + .../webapp/assets/zeus/json/layim/getList.js | 96 + .../assets/zeus/json/layim/getMembers.js | 22 + .../webapp/assets/zeus/json/mall/order.js | 42 + .../src/main/webapp/assets/zeus/json/menu.js | 400 ++ .../webapp/assets/zeus/json/message/all.js | 46 + .../webapp/assets/zeus/json/message/detail.js | 10 + .../webapp/assets/zeus/json/message/direct.js | 46 + .../webapp/assets/zeus/json/message/new.js | 7 + .../webapp/assets/zeus/json/message/notice.js | 46 + .../webapp/assets/zeus/json/table/demo.js | 96 + .../webapp/assets/zeus/json/table/demo2.js | 61 + .../webapp/assets/zeus/json/table/demo3.js | 96 + .../webapp/assets/zeus/json/table/user.js | 2 + .../webapp/assets/zeus/json/table/user30.js | 2 + .../webapp/assets/zeus/json/upload/demo.js | 7 + .../webapp/assets/zeus/json/user/forget.js | 7 + .../webapp/assets/zeus/json/user/login.js | 7 + .../webapp/assets/zeus/json/user/logout.js | 5 + .../main/webapp/assets/zeus/json/user/reg.js | 7 + .../webapp/assets/zeus/json/user/resetpass.js | 7 + .../webapp/assets/zeus/json/user/session.js | 9 + .../main/webapp/assets/zeus/json/user/sms.js | 7 + .../assets/zeus/json/useradmin/mangadmin.js | 78 + .../webapp/assets/zeus/json/useradmin/role.js | 54 + .../assets/zeus/json/useradmin/webuser.js | 143 + .../webapp/assets/zeus/json/workorder/demo.js | 78 + .../zeus/json/\350\257\264\346\230\216.txt" | 3 + .../webapp/assets/zeus/layui/css/layui.css | 1 + .../assets/zeus/layui/css/modules/code.css | 1 + .../css/modules/laydate/default/laydate.css | 1 + .../css/modules/layer/default/icon-ext.png | Bin 0 -> 5911 bytes .../layui/css/modules/layer/default/icon.png | Bin 0 -> 11493 bytes .../layui/css/modules/layer/default/layer.css | 1 + .../css/modules/layer/default/loading-0.gif | Bin 0 -> 5793 bytes .../css/modules/layer/default/loading-1.gif | Bin 0 -> 701 bytes .../css/modules/layer/default/loading-2.gif | Bin 0 -> 1787 bytes .../assets/zeus/layui/font/iconfont.eot | Bin 0 -> 46684 bytes .../assets/zeus/layui/font/iconfont.svg | 554 +++ .../assets/zeus/layui/font/iconfont.ttf | Bin 0 -> 46508 bytes .../assets/zeus/layui/font/iconfont.woff | Bin 0 -> 30628 bytes .../assets/zeus/layui/font/iconfont.woff2 | Bin 0 -> 25964 bytes .../main/webapp/assets/zeus/layui/layui.js | 5 + .../src/main/webapp/pages/index.html | 10 + 295 files changed, 27363 insertions(+) create mode 100644 iot-server/server-starter/src/main/webapp/assets/gulpfile.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/package-lock.json create mode 100644 iot-server/server-starter/src/main/webapp/assets/package.json create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/config.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/common.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/console.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/contlist.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/forum.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/sample.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/senior.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/set.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/user.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/useradmin.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/workorder.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/index.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/admin.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/echarts.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/echartsTheme.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/chatlog.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/find.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/getmsg.json create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/msgbox.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/default.png create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/0.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/1.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/10.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/11.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/12.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/13.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/14.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/15.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/16.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/17.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/18.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/19.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/2.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/20.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/21.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/22.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/23.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/24.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/25.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/26.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/27.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/28.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/29.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/3.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/30.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/31.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/32.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/33.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/34.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/35.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/36.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/37.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/38.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/39.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/4.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/40.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/41.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/42.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/43.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/44.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/45.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/46.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/47.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/48.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/49.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/5.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/50.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/51.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/52.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/53.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/54.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/55.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/56.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/57.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/58.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/59.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/6.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/60.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/61.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/62.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/63.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/64.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/65.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/66.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/67.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/68.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/69.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/7.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/70.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/71.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/8.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/9.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/layim.css create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/layer-mobile.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/layim-mobile-open.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/layim-mobile.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/zepto.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/mobile.css create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/1.jpg create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/2.jpg create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/3.jpg create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/4.jpg create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/5.jpg create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/voice/default.mp3 create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/view.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/admin.css create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/login.css create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/res/bg-none.jpg create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/res/layui-logo.jpg create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/res/logo-black.png create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/res/logo.png create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/res/template/character.jpg create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/res/template/huge.jpg create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/res/template/portrait.png create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/template.css create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/content/comment.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/content/contform.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/content/list.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/content/listform.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/content/tags.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/content/tagsform.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/list.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/listform.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/replys.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/replysform.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/message/detail.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/message/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/workorder/list.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/workorder/listform.html create mode 100644 "iot-server/server-starter/src/main/webapp/assets/src/views/app/\350\257\264\346\230\216.txt" create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/anim/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/auxiliar/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/badge/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/button/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/carousel/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/code/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/colorpicker/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/dropdown/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/flow/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/form/element.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/form/group.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/all.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/list.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/mobile-pc.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/mobile.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/speed-dial.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/stack.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/demo1.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/demo2.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/special-demo.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/theme.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/list.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/special-demo.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/theme.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/laypage/demo1.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/laypage/demo2.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/laytpl/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/nav/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/panel/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/progress/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/rate/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/slider/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/auto.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/cellEdit.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/cellEvent.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/checkbox.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/data.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/fixed.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/form.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/height.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/initSort.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/onrow.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/operate.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/page.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/parseData.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/radio.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/reload.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/resetPage.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/simple.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/static.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/style.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/thead.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/toolbar.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/tostatic.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/totalRow.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/tabs/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/timeline/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/transfer/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/tree/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/upload/demo1.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/upload/demo2.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/util/index.html create mode 100644 "iot-server/server-starter/src/main/webapp/assets/src/views/component/\350\257\264\346\230\216.txt" create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/home/homepage1.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/home/homepage2.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/iframe/layer/iframe.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/iframe/link/baidu.html create mode 100644 "iot-server/server-starter/src/main/webapp/assets/src/views/iframe/\350\257\264\346\230\216.txt" create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/layout.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/bar.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/line.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/map.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/senior/im/index.html create mode 100644 "iot-server/server-starter/src/main/webapp/assets/src/views/senior/\350\257\264\346\230\216.txt" create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/set/system/email.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/set/system/website.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/set/user/info.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/set/user/password.html create mode 100644 "iot-server/server-starter/src/main/webapp/assets/src/views/set/\350\257\264\346\230\216.txt" create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/system/about.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/system/more.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/system/theme.html create mode 100644 "iot-server/server-starter/src/main/webapp/assets/src/views/system/\350\257\264\346\230\216.txt" create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/temp.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/addresslist.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/caller.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/goodslist.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/msgboard.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/personalpage.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/search.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/404.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/error.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/test.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/user/forget.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/user/login.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/user/reg.html create mode 100644 "iot-server/server-starter/src/main/webapp/assets/src/views/template/\350\257\264\346\230\216.txt" create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/adminform.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/list.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/role.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/roleform.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/user/forget.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/user/login.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/user/reg.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/user/user/list.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/user/user/userform.html create mode 100644 "iot-server/server-starter/src/main/webapp/assets/src/views/user/\350\257\264\346\230\216.txt" create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/index.html create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/console/prograss.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/console/top-card.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/console/top-search.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/content/comment.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/content/list.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/content/tags.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/forum/list.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/forum/replys.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/layer/photos.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/layim/getList.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/layim/getMembers.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/mall/order.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/menu.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/message/all.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/message/detail.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/message/direct.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/message/new.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/message/notice.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo2.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo3.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/table/user.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/table/user30.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/upload/demo.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/user/forget.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/user/login.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/user/logout.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/user/reg.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/user/resetpass.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/user/session.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/user/sms.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/mangadmin.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/role.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/webuser.js create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/workorder/demo.js create mode 100644 "iot-server/server-starter/src/main/webapp/assets/zeus/json/\350\257\264\346\230\216.txt" create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/layui.css create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/code.css create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/laydate/default/laydate.css create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/icon-ext.png create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/icon.png create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/layer.css create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/loading-0.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/loading-1.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/loading-2.gif create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.eot create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.svg create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.ttf create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.woff create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.woff2 create mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/layui.js create mode 100644 iot-server/server-starter/src/main/webapp/pages/index.html diff --git a/iot-server/server-starter/src/main/webapp/assets/gulpfile.js b/iot-server/server-starter/src/main/webapp/assets/gulpfile.js new file mode 100644 index 00000000..d5e6354a --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/gulpfile.js @@ -0,0 +1,170 @@ + +/*! + layuiAdmin pro 构建 +*/ + +var pkg = require('./package.json'); +var inds = pkg.independents; + +var gulp = require('gulp'); +var uglify = require('gulp-uglify'); +var minify = require('gulp-minify-css'); +var concat = require('gulp-concat'); +var rename = require('gulp-rename'); +var replace = require('gulp-replace'); +var header = require('gulp-header'); +var del = require('del'); +var gulpif = require('gulp-if'); +var minimist = require('minimist'); + +//获取参数 +var argv = require('minimist')(process.argv.slice(2), { + default: { + ver: 'all' + } +}) + +//注释 +,note = [ + // '/** <%= pkg.name %>-v<%= pkg.version %> <%= pkg.license %> License */\n <%= js %>' + ,'' + ,{pkg: pkg, js: ';'} +] + +,destDir = './dist' //构建的目标目录 +,releaseDir = '../pack/layuiAdmin.pack/'+ pkg.name +'-v' + pkg.version //发行版本目录 + +//任务 +,task = { + //压缩 JS + minjs: function(){ + var src = [ + './src/**/*.js' + ,'!./src/config.js' + ,'!./src/lib/extend/**/*.js' + ]; + + return gulp.src(src).pipe(uglify({ + output: { + ascii_only: true //escape Unicode characters in strings and regexps + } + })) + .pipe(header.apply(null, note)) + .pipe(gulp.dest(destDir)); + } + + //压缩 CSS + ,mincss: function(){ + var src = [ + './src/**/*.css' + ] + ,noteNew = JSON.parse(JSON.stringify(note)); + + + noteNew[1].js = ''; + + return gulp.src(src).pipe(minify({ + compatibility: 'ie7' + })).pipe(header.apply(null, noteNew)) + .pipe(gulp.dest(destDir)); + } + + //复制文件夹 + ,mv: function(){ + gulp.src('./src/config.js') + .pipe(gulp.dest(destDir)); + + gulp.src('./src/lib/extend/**/*') + .pipe(gulp.dest(destDir + '/lib/extend')); + + gulp.src('./src/style/res/**/*') + .pipe(gulp.dest(destDir + '/style/res')); + + return gulp.src('./src/views/**/*') + .pipe(gulp.dest(destDir + '/views')); + } +}; + +gulp.task('minjs', task.minjs); +gulp.task('mincss', task.mincss); +gulp.task('mv', task.mv); + +//清理 +gulp.task('clear', function(cb) { + return del(['./dist/*'], cb); +}); + +//构建核心源文件(发行版) +gulp.task('default', ['clear'], function(){ //命令:gulp + for(var key in task){ + task[key](); + } +}); + + + +/** + * 开发模式 + */ + +//清理 src +gulp.task('clearSrc', function(cb) { + return del(['./src/*'], cb); +}); + +//复制 src +gulp.task('src', ['clearSrc'], function(){ + return gulp.src('./dev-src/**/*') + .pipe(gulp.dest('./src')); +}); + +//构建核心源文件(开发版) +gulp.task('dev', ['clear', 'src'], function(){ //命令:gulp dev + for(var key in task){ + task[key](); + } +}); + +//发行文件 +gulp.task('release', function(){ //命令:gulp && gulp release + + //复制核心文件 + gulp.src('./dist/**/*') + .pipe(gulp.dest(releaseDir + '/dist')); + + gulp.src('./src/**/*') + .pipe(gulp.dest(releaseDir + '/src')); + + //复制 json + gulp.src('./dev/json/**/*') + .pipe(gulp.dest('./json')) + .pipe(gulp.dest('./start/json')) + .pipe(gulp.dest(releaseDir + '/start/json')); + + //复制并转义宿主页面 + gulp.src('./dev/index.html') + .pipe(replace(/\<\!-- clear s --\>([\s\S]*?)\<\!-- clear e --\>/, '')) + .pipe(replace('//local.res.layui.com/layui/src', 'layui')) + .pipe(replace("base: '../dev-src/'", "base: '../dist/'")) + .pipe(replace('@@version@@', pkg.version)) + .pipe(gulp.dest('./start')) + .pipe(gulp.dest(releaseDir + '/start')); + + //复制帮助文件 + gulp.src([ + './帮助/*' + ]).pipe(gulp.dest(releaseDir)); + + + //复制 gulpfile + gulp.src([ + 'gulpfile.js' + ,'package.json' + ]).pipe(gulp.dest(releaseDir)); + + //复制 layui + return gulp.src('../../../../res/layui/rc/**/*') + .pipe(gulp.dest('./start/layui')) + .pipe(gulp.dest(releaseDir + '/start/layui')) +}); + diff --git a/iot-server/server-starter/src/main/webapp/assets/package-lock.json b/iot-server/server-starter/src/main/webapp/assets/package-lock.json new file mode 100644 index 00000000..f44c04c3 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/package-lock.json @@ -0,0 +1,3808 @@ +{ + "name": "layuiAdmin.pro", + "version": "1.7.2", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@dabh/diagnostics": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", + "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", + "dev": true, + "requires": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, + "@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/formatio": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", + "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^3.1.0" + } + }, + "@sinonjs/samsam": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", + "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.3.0", + "array-from": "^2.1.1", + "lodash": "^4.17.15" + }, + "dependencies": { + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + } + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-from": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", + "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", + "dev": true + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "binaryextensions": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-1.0.1.tgz", + "integrity": "sha1-HmN0iLNbWL2l9HdL+WpSEqjJB1U=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "bufferstreams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.0.1.tgz", + "integrity": "sha1-z7GtlWjTujz+k1upq92VLeiKqyo=", + "dev": true, + "requires": { + "readable-stream": "^1.0.33" + } + }, + "build": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/build/-/build-0.1.4.tgz", + "integrity": "sha1-cH/gJv/O3crL/c3zVur9pk8VEEY=", + "dev": true, + "requires": { + "cssmin": "0.3.x", + "jsmin": "1.x", + "jxLoader": "*", + "moo-server": "*", + "promised-io": "*", + "timespan": "2.x", + "uglify-js": "1.x", + "walker": "1.x", + "winston": "*", + "wrench": "1.3.x" + }, + "dependencies": { + "uglify-js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-1.3.5.tgz", + "integrity": "sha1-S1v/+Rhu/7qoiOTJ6UvZ/EyUkp0=", + "dev": true + } + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "chai": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "clean-css": { + "version": "3.4.28", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", + "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=", + "dev": true, + "requires": { + "commander": "2.8.x", + "source-map": "0.4.x" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "dev": true, + "requires": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "color-string": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz", + "integrity": "sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==", + "dev": true, + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true + }, + "colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "dev": true, + "requires": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "dev": true, + "requires": { + "graceful-readlink": ">= 1.0.0" + } + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "cssmin": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/cssmin/-/cssmin-0.3.2.tgz", + "integrity": "sha1-3c5MVHtRCuDVlKjx+/iq+OLFwA0=", + "dev": true + }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", + "dev": true + }, + "deap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deap/-/deap-1.0.1.tgz", + "integrity": "sha512-k75KYNZMvwAwes2xIPry/QTffXIchjD8QfABvvfTr80P85jv5ZcKqcoDo+vMe71nNnVnXYe8MA28weyqcf/DKw==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + } + }, + "deprecated": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", + "dev": true + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "diff": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", + "dev": true + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "~1.1.9" + } + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", + "dev": true + }, + "end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "dev": true, + "requires": { + "once": "~1.3.0" + }, + "dependencies": { + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1" + } + } + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dev": true, + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + } + }, + "fecha": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz", + "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", + "dev": true + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true + }, + "fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "fork-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", + "integrity": "sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA=", + "dev": true + }, + "formatio": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", + "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs=", + "dev": true, + "requires": { + "samsam": "1.x" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "dev": true, + "requires": { + "globule": "~0.1.0" + } + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "dev": true, + "requires": { + "glob": "^4.3.1", + "glob2base": "^0.0.12", + "minimatch": "^2.0.1", + "ordered-read-streams": "^0.1.0", + "through2": "^0.6.1", + "unique-stream": "^1.0.0" + }, + "dependencies": { + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^2.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "^1.0.0" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "dev": true, + "requires": { + "gaze": "^0.5.1" + } + }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "dev": true, + "requires": { + "find-index": "^0.1.1" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "dev": true, + "requires": { + "glob": "~3.1.21", + "lodash": "~1.0.1", + "minimatch": "~0.2.11" + }, + "dependencies": { + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "~1.2.0", + "inherits": "1", + "minimatch": "~0.2.11" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + } + } + }, + "glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } + }, + "graceful-fs": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.12.tgz", + "integrity": "sha512-J55gaCS4iTTJfTXIxSVw3EMQckcqkpdRv3IR7gu6sq0+tbC363Zx6KH/SEwXASK9JRbhyZmVjJEVJIOxYsB3Qg==", + "dev": true, + "requires": { + "natives": "^1.1.3" + } + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "gulp": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "dev": true, + "requires": { + "archy": "^1.0.0", + "chalk": "^1.0.0", + "deprecated": "^0.0.1", + "gulp-util": "^3.0.0", + "interpret": "^1.0.0", + "liftoff": "^2.1.0", + "minimist": "^1.1.0", + "orchestrator": "^0.3.0", + "pretty-hrtime": "^1.0.0", + "semver": "^4.1.0", + "tildify": "^1.0.0", + "v8flags": "^2.0.2", + "vinyl-fs": "^0.3.0" + } + }, + "gulp-concat": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", + "dev": true, + "requires": { + "concat-with-sourcemaps": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^2.0.0" + }, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true + }, + "vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + } + } + }, + "gulp-header": { + "version": "1.8.12", + "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", + "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", + "dev": true, + "requires": { + "concat-with-sourcemaps": "*", + "lodash.template": "^4.4.0", + "through2": "^2.0.0" + }, + "dependencies": { + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0" + } + } + } + }, + "gulp-if": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz", + "integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=", + "dev": true, + "requires": { + "gulp-match": "^1.0.3", + "ternary-stream": "^2.0.1", + "through2": "^2.0.1" + } + }, + "gulp-match": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.1.0.tgz", + "integrity": "sha512-DlyVxa1Gj24DitY2OjEsS+X6tDpretuxD6wTfhXE/Rw2hweqc1f6D/XtsJmoiCwLWfXgR87W9ozEityPCVzGtQ==", + "dev": true, + "requires": { + "minimatch": "^3.0.3" + } + }, + "gulp-minify-css": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/gulp-minify-css/-/gulp-minify-css-1.2.4.tgz", + "integrity": "sha1-thZJV2Auon+eWtiCJ2ld0gV3jAY=", + "dev": true, + "requires": { + "clean-css": "^3.3.3", + "gulp-util": "^3.0.5", + "object-assign": "^4.0.1", + "readable-stream": "^2.0.0", + "vinyl-bufferstream": "^1.0.1", + "vinyl-sourcemaps-apply": "^0.2.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "gulp-rename": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.4.0.tgz", + "integrity": "sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg==", + "dev": true + }, + "gulp-replace": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-0.6.1.tgz", + "integrity": "sha1-Eb+Mj85TPjPi9qjy9DC5VboL4GY=", + "dev": true, + "requires": { + "istextorbinary": "1.0.2", + "readable-stream": "^2.0.1", + "replacestream": "^4.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "gulp-uglify": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-1.5.4.tgz", + "integrity": "sha1-UkeI2HZm0J+dDCH7IXf5ADmmWMk=", + "dev": true, + "requires": { + "deap": "^1.0.0", + "fancy-log": "^1.0.0", + "gulp-util": "^3.0.0", + "isobject": "^2.0.0", + "through2": "^2.0.0", + "uglify-js": "2.6.4", + "uglify-save-license": "^0.4.1", + "vinyl-sourcemaps-apply": "^0.2.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", + "replace-ext": "0.0.1", + "through2": "^2.0.0", + "vinyl": "^0.5.0" + }, + "dependencies": { + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "^1.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-core-module": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "istextorbinary": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-1.0.2.tgz", + "integrity": "sha1-rOGTVNGpoBc+/rEITOD4ewrX3s8=", + "dev": true, + "requires": { + "binaryextensions": "~1.0.0", + "textextensions": "~1.0.0" + } + }, + "js-yaml": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-0.3.7.tgz", + "integrity": "sha1-1znY7oZGHlSzVNan19HyrZoWf2I=", + "dev": true + }, + "jsmin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/jsmin/-/jsmin-1.0.1.tgz", + "integrity": "sha1-570NzWSWw79IYyNb9GGj2YqjuYw=", + "dev": true + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "just-extend": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "dev": true + }, + "jxLoader": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jxLoader/-/jxLoader-0.1.1.tgz", + "integrity": "sha1-ATTqUUTlM7WU/B/yX/GU4jXFPs0=", + "dev": true, + "requires": { + "js-yaml": "0.3.x", + "moo-server": "1.3.x", + "promised-io": "*", + "walker": "1.x" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", + "dev": true + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "liftoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^2.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + } + }, + "lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash.keys": "^3.0.0" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "dev": true, + "requires": { + "lodash._baseassign": "^3.0.0", + "lodash._basecreate": "^3.0.0", + "lodash._isiterateecall": "^3.0.0" + } + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "^3.0.0" + } + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } + }, + "logform": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.3.0.tgz", + "integrity": "sha512-graeoWUH2knKbGthMtuG1EfaSPMZFZBIrhuJHhkS5ZseFBrc7DupCzihOQAzsK/qIKPQaPJ/lFQFctILUY5ARQ==", + "dev": true, + "requires": { + "colors": "^1.2.1", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^1.1.0", + "triple-beam": "^1.3.0" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "lolex": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", + "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", + "dev": true + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "requires": { + "tmpl": "1.0.5" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "mocha": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", + "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.6.8", + "diff": "3.2.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.1", + "growl": "1.9.2", + "he": "1.1.1", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + }, + "dependencies": { + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": ">= 1.0.0" + } + }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "moo-server": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/moo-server/-/moo-server-1.3.0.tgz", + "integrity": "sha1-XceVaVZaENbv7VQ5SR5p0jkuWPE=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + } + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "native-promise-only": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", + "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=", + "dev": true + }, + "natives": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.6.tgz", + "integrity": "sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==", + "dev": true + }, + "nise": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.3.tgz", + "integrity": "sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ==", + "dev": true, + "requires": { + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "lolex": "^5.0.1", + "path-to-regexp": "^1.7.0" + }, + "dependencies": { + "lolex": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", + "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + } + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "dev": true, + "requires": { + "fn.name": "1.x.x" + } + }, + "orchestrator": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "dev": true, + "requires": { + "end-of-stream": "~0.1.5", + "sequencify": "~0.0.7", + "stream-consume": "~0.1.0" + } + }, + "ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "requires": { + "isarray": "0.0.1" + } + }, + "pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "promised-io": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/promised-io/-/promised-io-0.3.6.tgz", + "integrity": "sha512-bNwZusuNIW4m0SPR8jooSyndD35ggirHlxVl/UhIaZD/F0OBv9ebfc6tNmbpZts3QXHggkjIBH8lvtnzhtcz0A==", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "replacestream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.3.tgz", + "integrity": "sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.3", + "object-assign": "^4.0.1", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safe-stable-stringify": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz", + "integrity": "sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==", + "dev": true + }, + "samsam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", + "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", + "dev": true + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + }, + "sequencify": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dev": true, + "requires": { + "is-arrayish": "^0.3.1" + } + }, + "sinon": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-3.3.0.tgz", + "integrity": "sha512-/flfGfIxIRXSvZBHJzIf3iAyGYkmMQq6SQjA0cx9SOuVuq+4ZPPO4LJtH1Ce0Lznax1KSG1U6Dad85wIcSW19w==", + "dev": true, + "requires": { + "build": "^0.1.4", + "diff": "^3.1.0", + "formatio": "1.2.0", + "lodash.get": "^4.4.2", + "lolex": "^2.1.2", + "native-promise-only": "^0.8.1", + "nise": "^1.0.1", + "path-to-regexp": "^1.7.0", + "samsam": "^1.1.3", + "text-encoding": "0.6.4", + "type-detect": "^4.0.0" + } + }, + "sinon-chai": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-2.14.0.tgz", + "integrity": "sha512-9stIF1utB0ywNHNT7RgiXbdmen8QDCRsrTjw+G9TgKt1Yexjiv8TOWZ6WHsTPz57Yky3DIswZvEqX8fpuHNDtQ==", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "dev": true + }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stream-consume": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", + "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", + "dev": true + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "dev": true, + "requires": { + "first-chunk-stream": "^1.0.0", + "is-utf8": "^0.2.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "ternary-stream": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.1.1.tgz", + "integrity": "sha512-j6ei9hxSoyGlqTmoMjOm+QNvUKDOIY6bNl4Uh1lhBvl6yjPW2iLqxDUYyfDPZknQ4KdRziFl+ec99iT4l7g0cw==", + "dev": true, + "requires": { + "duplexify": "^3.5.0", + "fork-stream": "^0.0.4", + "merge-stream": "^1.0.0", + "through2": "^2.0.1" + } + }, + "text-encoding": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", + "dev": true + }, + "text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", + "dev": true + }, + "textextensions": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-1.0.2.tgz", + "integrity": "sha1-ZUhjk+4fK7A5pgy7oFsLaL2VAdI=", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true, + "requires": { + "os-homedir": "^1.0.0" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "timespan": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz", + "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", + "dev": true + }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==", + "dev": true + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "uglify-js": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.4.tgz", + "integrity": "sha1-ZeovswWck5RpLxX+2HwrNsFrmt8=", + "dev": true, + "requires": { + "async": "~0.2.6", + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + } + }, + "uglify-save-license": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/uglify-save-license/-/uglify-save-license-0.4.1.tgz", + "integrity": "sha1-lXJsF8xv0XHDYX479NjYKqjEzOE=", + "dev": true + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "unique-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "^1.1.1" + } + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-bufferstream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vinyl-bufferstream/-/vinyl-bufferstream-1.0.1.tgz", + "integrity": "sha1-BTeGn1gO/6TKRay0dXnkuf5jCBo=", + "dev": true, + "requires": { + "bufferstreams": "1.0.1" + } + }, + "vinyl-fs": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "dev": true, + "requires": { + "defaults": "^1.0.0", + "glob-stream": "^3.1.5", + "glob-watcher": "^0.0.6", + "graceful-fs": "^3.0.0", + "mkdirp": "^0.5.0", + "strip-bom": "^1.0.0", + "through2": "^0.6.1", + "vinyl": "^0.4.0" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + } + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "requires": { + "source-map": "^0.5.1" + } + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "requires": { + "makeerror": "1.0.12" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "winston": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", + "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", + "dev": true, + "requires": { + "@dabh/diagnostics": "^2.0.2", + "async": "^3.1.0", + "is-stream": "^2.0.0", + "logform": "^2.2.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.4.0" + }, + "dependencies": { + "async": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz", + "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "winston-transport": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", + "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", + "dev": true, + "requires": { + "readable-stream": "^2.3.7", + "triple-beam": "^1.2.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "wrench": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/wrench/-/wrench-1.3.9.tgz", + "integrity": "sha1-bxPsNRRTF+spLKX2UxORskQRFBE=", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + } + } +} diff --git a/iot-server/server-starter/src/main/webapp/assets/package.json b/iot-server/server-starter/src/main/webapp/assets/package.json new file mode 100644 index 00000000..cc87238f --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/package.json @@ -0,0 +1,23 @@ +{ + "name": "layuiAdmin.pro", + "version": "1.7.2", + "description": "通用纯静态网页 UI 界面模板", + "license": "LGPL", + "homepage": "", + "devDependencies": { + "chai": "^4.1.1", + "del": "^2.2.2", + "gulp": "^3.9.1", + "gulp-concat": "^2.6.0 ", + "gulp-header": "^1.8.8", + "gulp-if": "^2.0.1", + "gulp-minify-css": "^1.2.4", + "gulp-rename": "^1.2.2", + "gulp-replace": "^0.6.1", + "gulp-uglify": "^1.5.4", + "minimist": "^1.2.0", + "mocha": "^3.2.0", + "sinon": "^3.2.1", + "sinon-chai": "^2.13.0" + } +} diff --git a/iot-server/server-starter/src/main/webapp/assets/src/config.js b/iot-server/server-starter/src/main/webapp/assets/src/config.js new file mode 100644 index 00000000..1225eea8 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/config.js @@ -0,0 +1,153 @@ +/*! + * 全局配置 + */ + +layui.define(['laytpl', 'layer', 'element', 'util'], function (exports) { + exports('setter', { + container: 'LAY_app' //容器ID + , base: layui.cache.base //记录layuiAdmin文件夹所在路径 + , views: layui.cache.base + 'views/' //视图所在目录 + , entry: 'index' //默认视图文件名 + , engine: '.html' //视图文件后缀名 + , pageTabs: false //是否开启页面选项卡功能。单页版不推荐开启 + + , name: 'layuiAdmin' + , tableName: 'layuiAdmin' //本地存储表名 + , MOD_NAME: 'admin' //模块事件名 + + , debug: true //是否开启调试模式。如开启,接口异常时会抛出异常 URL 等信息 + + , interceptor: false //是否开启未登入拦截 + + //自定义请求字段 + , request: { + tokenName: 'access_token' //自动携带 token 的字段名。可设置 false 不携带。 + } + + //自定义响应字段 + , response: { + statusName: 'code' //数据状态的字段名称 + , statusCode: { + ok: 0 //数据状态一切正常的状态码 + , logout: 1001 //登录状态失效的状态码 + } + , msgName: 'msg' //状态信息的字段名称 + , dataName: 'data' //数据详情的字段名称 + } + + //独立页面路由,可随意添加(无需写参数) + , indPage: [ + '/user/login' //登入页 + , '/user/reg' //注册页 + , '/user/forget' //找回密码 + , '/template/tips/test' //独立页的一个测试 demo + ] + + //扩展的模块(相对于 lib/extend 目录) + , extend: { + echarts: 'echarts', //第三方 echarts 核心包 + echartsTheme: 'echartsTheme', //第三方 echarts 主题 + layim: 'layim/layim' //layim + } + + //主题配置 + , theme: { + //内置主题配色方案 + color: [{ + main: '#20222A' //主题色 + , selected: '#009688' //选中色 + , alias: 'default' //默认别名 + }, { + main: '#03152A' + , selected: '#3B91FF' + , alias: 'dark-blue' //藏蓝 + }, { + main: '#2E241B' + , selected: '#A48566' + , alias: 'coffee' //咖啡 + }, { + main: '#50314F' + , selected: '#7A4D7B' + , alias: 'purple-red' //紫红 + }, { + main: '#344058' + , logo: '#1E9FFF' + , selected: '#1E9FFF' + , alias: 'ocean' //海洋 + }, { + main: '#3A3D49' + , logo: '#2F9688' + , selected: '#5FB878' + , alias: 'green' //墨绿 + }, { + main: '#20222A' + , logo: '#F78400' + , selected: '#F78400' + , alias: 'red' //橙色 + }, { + main: '#28333E' + , logo: '#AA3130' + , selected: '#AA3130' + , alias: 'fashion-red' //时尚红 + }, { + main: '#24262F' + , logo: '#3A3D49' + , selected: '#009688' + , alias: 'classic-black' //经典黑 + }, { + logo: '#226A62' + , header: '#2F9688' + , alias: 'green-header' //墨绿头 + }, { + main: '#344058' + , logo: '#0085E8' + , selected: '#1E9FFF' + , header: '#1E9FFF' + , alias: 'ocean-header' //海洋头 + }, { + header: '#393D49' + , alias: 'classic-black-header' //经典黑 + }, { + main: '#50314F' + , logo: '#50314F' + , selected: '#7A4D7B' + , header: '#50314F' + , alias: 'purple-red-header' //紫红头 + }, { + main: '#28333E' + , logo: '#28333E' + , selected: '#AA3130' + , header: '#AA3130' + , alias: 'fashion-red-header' //时尚红头 + }, { + main: '#28333E' + , logo: '#009688' + , selected: '#009688' + , header: '#009688' + , alias: 'green-header' //墨绿头 + }, { + main: '#393D49' + , logo: '#393D49' + , selected: '#009688' + , header: '#23262E' + , alias: 'Classic-style1' //经典风格1 + }, { + main: '#001529' + , logo: '#001529' + , selected: '#1890FF' + , header: '#1890FF' + , alias: 'Classic-style2' //经典风格2 + }, { + main: '#25282A' + , logo: '#25282A' + , selected: '#35BDB2' + , header: '#35BDB2' + , alias: 'Classic-style3' //经典风格3 + }] + + //初始的颜色索引,对应上面的配色方案数组索引 + //如果本地已经有主题色记录,则以本地记录为优先,除非请求本地数据(localStorage) + , initColorIndex: 0 + } + }); +}); diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/common.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/common.js new file mode 100644 index 00000000..36f8867b --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/controller/common.js @@ -0,0 +1,40 @@ +/** + + @Name:layuiAdmin 公共业务 + + + @License:LPPL + + */ + +layui.define(function (exports) { + var $ = layui.$ + , layer = layui.layer + , laytpl = layui.laytpl + , setter = layui.setter + , view = layui.view + , admin = layui.admin + + //公共业务的逻辑处理可以写在此处,切换任何页面都会执行 + //…… + + + //退出 + admin.events.logout = function () { + //执行退出接口 + admin.req({ + url: './json/user/logout.js' + , type: 'get' + , data: {} + , done: function (res) { //这里要说明一下:done 是只有 response 的 code 正常才会执行。而 succese 则是只要 http 为 200 就会执行 + + //清空本地记录的 token,并跳转到登入页 + admin.exit(); + } + }); + }; + + + //对外暴露的接口 + exports('common', {}); +}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/console.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/console.js new file mode 100644 index 00000000..66dce2c1 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/controller/console.js @@ -0,0 +1,335 @@ +/*! + * 主页 + */ + + +layui.define(function (exports) { + + /* + 下面通过 layui.use 分段加载不同的模块,实现不同区域的同时渲染,从而保证视图的快速呈现 + */ + + + //区块轮播切换 + layui.use(['admin', 'carousel'], function () { + var $ = layui.$ + , admin = layui.admin + , carousel = layui.carousel + , element = layui.element + , device = layui.device(); + + //轮播切换 + $('.layadmin-carousel').each(function () { + var othis = $(this); + carousel.render({ + elem: this + , width: '100%' + , arrow: 'none' + , interval: othis.data('interval') + , autoplay: othis.data('autoplay') === true + , trigger: (device.ios || device.android) ? 'click' : 'hover' + , anim: othis.data('anim') + }); + }); + + element.render('progress'); + + }); + + //数据概览 + layui.use(['admin', 'carousel', 'echarts'], function () { + var $ = layui.$ + , admin = layui.admin + , carousel = layui.carousel + , echarts = layui.echarts; + + var echartsApp = [], options = [ + //今日流量趋势 + { + title: { + text: '今日流量趋势', + x: 'center', + textStyle: { + fontSize: 14 + } + }, + tooltip: { + trigger: 'axis' + }, + legend: { + data: ['', ''] + }, + xAxis: [{ + type: 'category', + boundaryGap: false, + data: ['06:00', '06:30', '07:00', '07:30', '08:00', '08:30', '09:00', '09:30', '10:00', '11:30', '12:00', '12:30', '13:00', '13:30', '14:00', '14:30', '15:00', '15:30', '16:00', '16:30', '17:00', '17:30', '18:00', '18:30', '19:00', '19:30', '20:00', '20:30', '21:00', '21:30', '22:00', '22:30', '23:00', '23:30'] + }], + yAxis: [{ + type: 'value' + }], + series: [{ + name: 'PV', + type: 'line', + smooth: true, + itemStyle: {normal: {areaStyle: {type: 'default'}}}, + data: [111, 222, 333, 444, 555, 666, 3333, 33333, 55555, 66666, 33333, 3333, 6666, 11888, 26666, 38888, 56666, 42222, 39999, 28888, 17777, 9666, 6555, 5555, 3333, 2222, 3111, 6999, 5888, 2777, 1666, 999, 888, 777] + }, { + name: 'UV', + type: 'line', + smooth: true, + itemStyle: {normal: {areaStyle: {type: 'default'}}}, + data: [11, 22, 33, 44, 55, 66, 333, 3333, 5555, 12666, 3333, 333, 666, 1188, 2666, 3888, 6666, 4222, 3999, 2888, 1777, 966, 655, 555, 333, 222, 311, 699, 588, 277, 166, 99, 88, 77] + }] + }, + + /* + //访客浏览器分布 + { + title : { + text: '访客浏览器分布', + x: 'center', + textStyle: { + fontSize: 14 + } + }, + tooltip : { + trigger: 'item', + formatter: "{a}
{b} : {c} ({d}%)" + }, + legend: { + orient : 'vertical', + x : 'left', + data:['Chrome','Firefox','IE 8.0','Safari','其它浏览器'] + }, + series : [{ + name:'访问来源', + type:'pie', + radius : '55%', + center: ['50%', '50%'], + data:[ + {value:9052, name:'Chrome'}, + {value:1610, name:'Firefox'}, + {value:3200, name:'IE 8.0'}, + {value:535, name:'Safari'}, + {value:1700, name:'其它浏览器'} + ] + }] + }, + */ + + //新增的用户量 + { + title: { + text: '最近一周新增的用户量', + x: 'center', + textStyle: { + fontSize: 14 + } + }, + tooltip: { //提示框 + trigger: 'axis', + formatter: "{b}
新增用户:{c}" + }, + xAxis: [{ //X轴 + type: 'category', + data: ['11-07', '11-08', '11-09', '11-10', '11-11', '11-12', '11-13'] + }], + yAxis: [{ //Y轴 + type: 'value' + }], + series: [{ //内容 + type: 'line', + data: [200, 300, 400, 610, 150, 270, 380], + }] + } + ] + , elemDataView = $('#LAY-index-dataview').children('div') + , renderDataView = function (index) { + echartsApp[index] = echarts.init(elemDataView[index], layui.echartsTheme); + echartsApp[index].setOption(options[index]); + //window.onresize = echartsApp[index].resize; + admin.resize(function () { + echartsApp[index].resize(); + }); + }; + + + //没找到DOM,终止执行 + if (!elemDataView[0]) return; + + + renderDataView(0); + + //触发数据概览轮播 + var carouselIndex = 0; + carousel.on('change(LAY-index-dataview)', function (obj) { + renderDataView(carouselIndex = obj.index); + }); + + //触发侧边伸缩 + layui.admin.on('side', function () { + setTimeout(function () { + renderDataView(carouselIndex); + }, 300); + }); + + //触发路由 + layui.admin.on('hash(tab)', function () { + layui.router().path.join('') || renderDataView(carouselIndex); + }); + }); + + //地图 + layui.use(['carousel', 'echarts'], function () { + var $ = layui.$ + , carousel = layui.carousel + , echarts = layui.echarts; + + var echartsApp = [], options = [ + { + title: { + text: '访客地区分布', + subtext: '不完全统计' + }, + tooltip: { + trigger: 'item' + }, + dataRange: { + orient: 'horizontal', + min: 0, + max: 60000, + text: ['高', '低'], + splitNumber: 0 + }, + series: [ + { + name: '访客地区分布', + type: 'map', + mapType: 'china', + selectedMode: 'multiple', + itemStyle: { + normal: {label: {show: true}}, + emphasis: {label: {show: true}} + }, + data: [ + {name: '西藏', value: 60}, + {name: '青海', value: 167}, + {name: '宁夏', value: 210}, + {name: '海南', value: 252}, + {name: '甘肃', value: 502}, + {name: '贵州', value: 570}, + {name: '新疆', value: 661}, + {name: '云南', value: 8890}, + {name: '重庆', value: 10010}, + {name: '吉林', value: 5056}, + {name: '山西', value: 2123}, + {name: '天津', value: 9130}, + {name: '江西', value: 10170}, + {name: '广西', value: 6172}, + {name: '陕西', value: 9251}, + {name: '黑龙江', value: 5125}, + {name: '内蒙古', value: 1435}, + {name: '安徽', value: 9530}, + {name: '北京', value: 51919}, + {name: '福建', value: 3756}, + {name: '上海', value: 59190}, + {name: '湖北', value: 37109}, + {name: '湖南', value: 8966}, + {name: '四川', value: 31020}, + {name: '辽宁', value: 7222}, + {name: '河北', value: 3451}, + {name: '河南', value: 9693}, + {name: '浙江', value: 62310}, + {name: '山东', value: 39231}, + {name: '江苏', value: 35911}, + {name: '广东', value: 55891} + ] + } + ] + } + ] + , elemDataView = $('#LAY-index-pagethree-home').children('div') + , renderDataView = function (index) { + echartsApp[index] = echarts.init(elemDataView[index], layui.echartsTheme); + echartsApp[index].setOption(options[index]); + window.onresize = echartsApp[index].resize; + }; + //没找到DOM,终止执行 + if (!elemDataView[0]) return; + + renderDataView(0); + }); + + + //table + layui.use('table', function () { + var $ = layui.$ + , table = layui.table; + + //今日热搜 + table.render({ + elem: '#LAY-index-topSearch' + , url: './json/console/top-search.js' //模拟接口 + , page: true + , cols: [[ + {type: 'numbers', fixed: 'left'} + , { + field: 'keywords', + title: '关键词', + minWidth: 300, + templet: '

' + } + , {field: 'frequency', title: '搜索次数', minWidth: 120, sort: true} + , {field: 'userNums', title: '用户数', sort: true} + ]] + , skin: 'line' + }); + + //今日热贴 + table.render({ + elem: '#LAY-index-topCard' + , url: './json/console/top-card.js' //模拟接口 + , page: true + , cellMinWidth: 120 + , cols: [[ + {type: 'numbers', fixed: 'left'} + , { + field: 'title', + title: '标题', + minWidth: 300, + templet: '' + } + , {field: 'username', title: '发帖者'} + , {field: 'channel', title: '类别'} + , {field: 'crt', title: '点击率', sort: true} + ]] + , skin: 'line' + }); + + //项目进展 + table.render({ + elem: '#LAY-home-homepage-console' + , url: './json/console/prograss.js' //模拟接口 + , cols: [[ + {type: 'checkbox', fixed: 'left'} + , {field: 'prograss', title: '任务'} + , {field: 'time', title: '所需时间'} + , { + field: 'complete', title: '完成情况' + , templet: function (d) { + if (d.complete == '已完成') { + return '' + d.complete + '' + } else if (d.complete == '进行中') { + return '' + d.complete + '' + } else { + return '' + d.complete + '' + } + } + } + ]] + , skin: 'line' + }); + }); + + exports('console', {}) +}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/contlist.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/contlist.js new file mode 100644 index 00000000..7dfd42d5 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/controller/contlist.js @@ -0,0 +1,166 @@ +/** + + @Name:layuiAdmin 内容系统 + @Author:star1029 + + @License:LPPL + + */ + + +layui.define(['table', 'form'], function (exports) { + var $ = layui.$ + , admin = layui.admin + , view = layui.view + , table = layui.table + , form = layui.form; + + //文章管理 + table.render({ + elem: '#LAY-app-content-list' + , url: './json/content/list.js' //模拟接口 + , cols: [[ + {type: 'checkbox', fixed: 'left'} + , {field: 'id', width: 100, title: '文章ID', sort: true} + , {field: 'label', title: '文章标签', minWidth: 100} + , {field: 'title', title: '文章标题'} + , {field: 'author', title: '作者'} + , {field: 'uploadtime', title: '上传时间', sort: true} + , {field: 'status', title: '发布状态', templet: '#buttonTpl', minWidth: 80, align: 'center'} + , {title: '操作', minWidth: 150, align: 'center', fixed: 'right', toolbar: '#table-content-list'} + ]] + , page: true + , limit: 10 + , limits: [10, 15, 20, 25, 30] + , text: '对不起,加载出现异常!' + }); + + //工具条 + table.on('tool(LAY-app-content-list)', function (obj) { + var data = obj.data; + if (obj.event === 'del') { + layer.confirm('确定删除此文章?', function (index) { + obj.del(); + layer.close(index); + }); + } else if (obj.event === 'edit') { + admin.popup({ + title: '编辑文章' + , area: ['550px', '550px'] + , id: 'LAY-popup-content-edit' + , success: function (layero, index) { + view(this.id).render('app/content/listform', data).done(function () { + form.render(null, 'layuiadmin-app-form-list'); + + //提交 + form.on('submit(layuiadmin-app-form-submit)', function (data) { + var field = data.field; //获取提交的字段 + + //提交 Ajax 成功后,关闭当前弹层并重载表格 + //$.ajax({}); + layui.table.reload('LAY-app-content-list'); //重载表格 + layer.close(index); //执行关闭 + }); + }); + } + }); + } + }); + + //分类管理 + table.render({ + elem: '#LAY-app-content-tags' + , url: './json/content/tags.js' //模拟接口 + , cols: [[ + {type: 'numbers', fixed: 'left'} + , {field: 'id', width: 100, title: 'ID', sort: true} + , {field: 'tags', title: '分类名', minWidth: 100} + , {title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#layuiadmin-app-cont-tagsbar'} + ]] + , text: '对不起,加载出现异常!' + }); + + //工具条 + table.on('tool(LAY-app-content-tags)', function (obj) { + var data = obj.data; + if (obj.event === 'del') { + layer.confirm('确定删除此分类?', function (index) { + obj.del(); + layer.close(index); + }); + } else if (obj.event === 'edit') { + admin.popup({ + title: '编辑分类' + , area: ['450px', '200px'] + , id: 'LAY-popup-content-tags' + , success: function (layero, index) { + view(this.id).render('app/content/tagsform', data).done(function () { + form.render(null, 'layuiadmin-form-tags'); + + //提交 + form.on('submit(layuiadmin-app-tags-submit)', function (data) { + var field = data.field; //获取提交的字段 + + //提交 Ajax 成功后,关闭当前弹层并重载表格 + //$.ajax({}); + layui.table.reload('LAY-app-content-tags'); //重载表格 + layer.close(index); //执行关闭 + }); + }); + } + }); + } + }); + + //评论管理 + table.render({ + elem: '#LAY-app-content-comm' + , url: './json/content/comment.js' //模拟接口 + , cols: [[ + {type: 'checkbox', fixed: 'left'} + , {field: 'id', width: 100, title: 'ID', sort: true} + , {field: 'reviewers', title: '评论者', minWidth: 100} + , {field: 'content', title: '评论内容', minWidth: 100} + , {field: 'commtime', title: '评论时间', minWidth: 100, sort: true} + , {title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#table-content-com'} + ]] + , page: true + , limit: 10 + , limits: [10, 15, 20, 25, 30] + , text: '对不起,加载出现异常!' + }); + + //工具条 + table.on('tool(LAY-app-content-comm)', function (obj) { + var data = obj.data; + if (obj.event === 'del') { + layer.confirm('确定删除此条评论?', function (index) { + obj.del(); + layer.close(index); + }); + } else if (obj.event === 'edit') { + admin.popup({ + title: '编辑评论' + , area: ['450px', '300px'] + , id: 'LAY-popup-content-comm' + , success: function (layero, index) { + view(this.id).render('app/content/contform', data).done(function () { + form.render(null, 'layuiadmin-form-comment'); + + //提交 + form.on('submit(layuiadmin-app-com-submit)', function (data) { + var field = data.field; //获取提交的字段 + + //提交 Ajax 成功后,关闭当前弹层并重载表格 + //$.ajax({}); + layui.table.reload('LAY-app-content-comm'); //重载表格 + layer.close(index); //执行关闭 + }); + }); + } + }); + } + }); + + exports('contlist', {}) +}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/forum.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/forum.js new file mode 100644 index 00000000..a6913277 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/controller/forum.js @@ -0,0 +1,125 @@ +/** + + @Name:layuiAdmin 社区系统 + @Author:star1029 + + @License:LPPL + + */ + + +layui.define(['table', 'form'], function (exports) { + var $ = layui.$ + , admin = layui.admin + , view = layui.view + , table = layui.table + , form = layui.form; + + //帖子管理 + table.render({ + elem: '#LAY-app-forum-list' + , url: './json/forum/list.js' //模拟接口 + , cols: [[ + {type: 'checkbox', fixed: 'left'} + , {field: 'id', width: 100, title: 'ID', sort: true} + , {field: 'poster', title: '发帖人'} + , {field: 'avatar', title: '头像', width: 100, templet: '#imgTpl'} + , {field: 'content', title: '发帖内容'} + , {field: 'posttime', title: '发帖时间', sort: true} + , {field: 'top', title: '置顶', templet: '#buttonTpl', minWidth: 80, align: 'center'} + , {title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#table-forum-list'} + ]] + , page: true + , limit: 10 + , limits: [10, 15, 20, 25, 30] + , text: '对不起,加载出现异常!' + }); + + //工具条 + table.on('tool(LAY-app-forum-list)', function (obj) { + var data = obj.data; + if (obj.event === 'del') { + layer.confirm('确定删除此条帖子?', function (index) { + obj.del(); + layer.close(index); + }); + } else if (obj.event === 'edit') { + admin.popup({ + title: '编辑帖子' + , area: ['550px', '450px'] + , id: 'LAY-popup-forum-edit' + , resize: false + , success: function (layero, index) { + view(this.id).render('app/forum/listform', data).done(function () { + form.render(null, 'layuiadmin-form-list'); + + //提交 + form.on('submit(layuiadmin-app-forum-submit)', function (data) { + var field = data.field; //获取提交的字段 + + //提交 Ajax 成功后,关闭当前弹层并重载表格 + //$.ajax({}); + layui.table.reload('LAY-app-forum-list'); //重载表格 + layer.close(index); //执行关闭 + }); + }); + } + }); + } + }); + + //回帖管理 + table.render({ + elem: '#LAY-app-forumreply-list' + , url: './json/forum/replys.js' //模拟接口 + , cols: [[ + {type: 'checkbox', fixed: 'left'} + , {field: 'id', width: 100, title: 'ID', sort: true} + , {field: 'replyer', title: '回帖人'} + , {field: 'cardid', title: '回帖ID', sort: true} + , {field: 'avatar', title: '头像', width: 100, templet: '#imgTpl'} + , {field: 'content', title: '回帖内容', width: 200} + , {field: 'replytime', title: '回帖时间', sort: true} + , {title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#table-forum-replys'} + ]] + , page: true + , limit: 10 + , limits: [10, 15, 20, 25, 30] + , text: '对不起,加载出现异常!' + }); + + //工具条 + table.on('tool(LAY-app-forumreply-list)', function (obj) { + var data = obj.data; + if (obj.event === 'del') { + layer.confirm('确定删除此条评论?', function (index) { + obj.del(); + layer.close(index); + }); + } else if (obj.event === 'edit') { + admin.popup({ + title: '编辑回帖' + , area: ['550px', '400px'] + , id: 'LAY-popup-forum-edit' + , resize: false + , success: function (layero, index) { + view(this.id).render('app/forum/replysform', data).done(function () { + form.render(null, 'layuiadmin-app-forum-reply'); + + //提交 + form.on('submit(layuiadmin-app-forumreply-submit)', function (data) { + var field = data.field; //获取提交的字段 + + //提交 Ajax 成功后,关闭当前弹层并重载表格 + //$.ajax({}); + layui.table.reload('LAY-app-forumreply-list'); //重载表格 + layer.close(index); //执行关闭 + }); + }); + } + }); + } + }); + + exports('forum', {}) +}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/sample.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/sample.js new file mode 100644 index 00000000..1a20eefe --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/controller/sample.js @@ -0,0 +1,299 @@ +/** + + @Name:layuiAdmin 主页示例 + @Author:star1029 + + @License:GPL-2 + + */ + + +layui.define(function(exports){ + var admin = layui.admin; + + //区块轮播切换 + layui.use(['admin', 'carousel'], function(){ + var $ = layui.$ + ,admin = layui.admin + ,carousel = layui.carousel + ,element = layui.element + ,device = layui.device(); + + //轮播切换 + $('.layadmin-carousel').each(function(){ + var othis = $(this); + carousel.render({ + elem: this + ,width: '100%' + ,arrow: 'none' + ,interval: othis.data('interval') + ,autoplay: othis.data('autoplay') === true + ,trigger: (device.ios || device.android) ? 'click' : 'hover' + ,anim: othis.data('anim') + }); + }); + + element.render('progress'); + + }); + + //八卦新闻 + layui.use(['carousel', 'echarts'], function(){ + var $ = layui.$ + ,carousel = layui.carousel + ,echarts = layui.echarts; + + var echartsApp = [], options = [ + { + title : { + subtext: '完全实况球员数据', + textStyle: { + fontSize: 14 + } + }, + tooltip : { + trigger: 'axis' + }, + legend: { + x : 'left', + data:['罗纳尔多','舍普琴科'] + }, + polar : [ + { + indicator : [ + {text : '进攻', max : 100}, + {text : '防守', max : 100}, + {text : '体能', max : 100}, + {text : '速度', max : 100}, + {text : '力量', max : 100}, + {text : '技巧', max : 100} + ], + radius : 130 + } + ], + series : [ + { + type: 'radar', + center : ['50%', '50%'], + itemStyle: { + normal: { + areaStyle: { + type: 'default' + } + } + }, + data:[ + {value : [97, 42, 88, 94, 90, 86], name : '舍普琴科'}, + {value : [97, 32, 74, 95, 88, 92], name : '罗纳尔多'} + ] + } + ] + } + ] + ,elemDataView = $('#LAY-index-pageone').children('div') + ,renderDataView = function(index){ + echartsApp[index] = echarts.init(elemDataView[index], layui.echartsTheme); + echartsApp[index].setOption(options[index]); + window.onresize = echartsApp[index].resize; + }; + //没找到DOM,终止执行 + if(!elemDataView[0]) return; + + renderDataView(0); + }); + + //访问量 + layui.use(['carousel', 'echarts'], function(){ + var $ = layui.$ + ,carousel = layui.carousel + ,echarts = layui.echarts; + + var echartsApp = [], options = [ + { + tooltip : { + trigger: 'axis' + }, + calculable : true, + legend: { + data:['访问量','下载量','平均访问量'] + }, + + xAxis : [ + { + type : 'category', + data : ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'] + } + ], + yAxis : [ + { + type : 'value', + name : '访问量', + axisLabel : { + formatter: '{value} 万' + } + }, + { + type : 'value', + name : '下载量', + axisLabel : { + formatter: '{value} 万' + } + } + ], + series : [ + { + name:'访问量', + type:'line', + data:[900, 850, 950, 1000, 1100, 1050, 1000, 1150, 1250, 1370, 1250, 1100] + }, + { + name:'下载量', + type:'line', + yAxisIndex: 1, + data:[850, 850, 800, 950, 1000, 950, 950, 1150, 1100, 1240, 1000, 950] + }, + { + name:'平均访问量', + type:'line', + data:[870, 850, 850, 950, 1050, 1000, 980, 1150, 1000, 1300, 1150, 1000] + } + ] + } + ] + ,elemDataView = $('#LAY-index-pagetwo').children('div') + ,renderDataView = function(index){ + echartsApp[index] = echarts.init(elemDataView[index], layui.echartsTheme); + echartsApp[index].setOption(options[index]); + window.onresize = echartsApp[index].resize; + }; + //没找到DOM,终止执行 + if(!elemDataView[0]) return; + renderDataView(0); + + }); + + //地图 + layui.use(['carousel', 'echarts'], function(){ + var $ = layui.$ + ,carousel = layui.carousel + ,echarts = layui.echarts; + + var echartsApp = [], options = [ + { + title : { + text: '访客地区分布', + subtext: '不完全统计' + }, + tooltip : { + trigger: 'item' + }, + dataRange: { + orient: 'horizontal', + min: 0, + max: 60000, + text:['高','低'], + splitNumber:0 + }, + series : [ + { + name: '访客地区分布', + type: 'map', + mapType: 'china', + selectedMode : 'multiple', + itemStyle:{ + normal:{label:{show:true}}, + emphasis:{label:{show:true}} + }, + data:[ + {name:'西藏', value:60}, + {name:'青海', value:167}, + {name:'宁夏', value:210}, + {name:'海南', value:252}, + {name:'甘肃', value:502}, + {name:'贵州', value:570}, + {name:'新疆', value:661}, + {name:'云南', value:8890}, + {name:'重庆', value:10010}, + {name:'吉林', value:5056}, + {name:'山西', value:2123}, + {name:'天津', value:9130}, + {name:'江西', value:10170}, + {name:'广西', value:6172}, + {name:'陕西', value:9251}, + {name:'黑龙江', value:5125}, + {name:'内蒙古', value:1435}, + {name:'安徽', value:9530}, + {name:'北京', value:51919}, + {name:'福建', value:3756}, + {name:'上海', value:59190}, + {name:'湖北', value:37109}, + {name:'湖南', value:8966}, + {name:'四川', value:31020}, + {name:'辽宁', value:7222}, + {name:'河北', value:3451}, + {name:'河南', value:9693}, + {name:'浙江', value:62310}, + {name:'山东', value:39231}, + {name:'江苏', value:35911}, + {name:'广东', value:55891} + ] + } + ] + } + ] + ,elemDataView = $('#LAY-index-pagethree').children('div') + ,renderDataView = function(index){ + echartsApp[index] = echarts.init(elemDataView[index], layui.echartsTheme); + echartsApp[index].setOption(options[index]); + window.onresize = echartsApp[index].resize; + }; + //没找到DOM,终止执行 + if(!elemDataView[0]) return; + + renderDataView(0); + }); + + //项目进展 + layui.use('table', function(){ + var $ = layui.$ + ,table = layui.table; + + table.render({ + elem: '#LAY-home-homepage2' + ,url: './json/console/prograss.js' //模拟接口 + ,cols: [[ + {type: 'checkbox', fixed: 'left'} + ,{field: 'prograss', title: '任务'} + ,{field: 'time', title: '所需时间'} + ,{field: 'complete', title: '完成情况' + ,templet: function(d){ + if(d.complete == '已完成'){ + return ''+ d.complete +'' + }else if(d.complete == '进行中'){ + return ''+ d.complete +'' + }else{ + return ''+ d.complete +'' + } + } + } + ]] + ,skin: 'line' + }); + }); + + //回复留言 + admin.events.replyNote = function(othis){ + var nid = othis.data('id'); + layer.prompt({ + title: '回复留言 ID:'+ nid + ,formType: 2 + }, function(value, index){ + //这里可以请求 Ajax + //… + layer.msg('得到:'+ value); + layer.close(index); + }); + }; + + exports('sample', {}) +}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/senior.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/senior.js new file mode 100644 index 00000000..15b5df3a --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/controller/senior.js @@ -0,0 +1,1153 @@ +/** + + @Name:layuiAdmin Echarts集成 + @Author:star1029 + + @License:GPL-2 + + */ + + +layui.define(function(exports){ + + //区块轮播切换 + layui.use(['admin', 'carousel'], function(){ + var $ = layui.$ + ,admin = layui.admin + ,carousel = layui.carousel + ,element = layui.element + ,device = layui.device(); + + //轮播切换 + $('.layadmin-carousel').each(function(){ + var othis = $(this); + carousel.render({ + elem: this + ,width: '100%' + ,arrow: 'none' + ,interval: othis.data('interval') + ,autoplay: othis.data('autoplay') === true + ,trigger: (device.ios || device.android) ? 'click' : 'hover' + ,anim: othis.data('anim') + }); + }); + + }); + + //折线图 + layui.use(['echarts'], function(){ + var $ = layui.$ + ,echarts = layui.echarts; + + //标准折线图 + var echnormline = [], normline = [ + { + title : { + text: '未来一周气温变化', + subtext: '纯属虚构' + }, + tooltip : { + trigger: 'axis' + }, + legend: { + data:['最高气温','最低气温'] + }, + calculable : true, + xAxis : [ + { + type : 'category', + boundaryGap : false, + data : ['周一','周二','周三','周四','周五','周六','周日'] + } + ], + yAxis : [ + { + type : 'value', + axisLabel : { + formatter: '{value} °C' + } + } + ], + series : [ + { + name:'最高气温', + type:'line', + data:[11, 11, 15, 13, 12, 13, 10], + markPoint : { + data : [{type : 'max', name: '最大值'},{type : 'min', name: '最小值'}] + }, + markLine : { + data : [{type : 'average', name: '平均值'}] + } + }, + { + name:'最低气温', + type:'line', + data:[1, -2, 2, 5, 3, 2, 0], + markPoint : { + data : [{name : '周最低', value : -2, xAxis: 1, yAxis: -1.5}] + }, + markLine : { + data : [{type : 'average', name : '平均值'}] + } + } + ] + } + ] + ,elemnormline = $('#LAY-index-normline').children('div') + ,rendernormline = function(index){ + echnormline[index] = echarts.init(elemnormline[index], layui.echartsTheme); + echnormline[index].setOption(normline[index]); + window.onresize = echnormline[index].resize; + }; + if(!elemnormline[0]) return; + rendernormline(0); + + //堆积折线图 + var echheapline = [], heapline = [ + { + tooltip : { + trigger: 'axis' + }, + legend: {data:['邮件营销','联盟广告','视频广告','直接访问','搜索引擎']}, + calculable : true, + xAxis : [ + { + type : 'category', + boundaryGap : false, + data : ['周一','周二','周三','周四','周五','周六','周日'] + } + ], + yAxis : [ + { + type : 'value' + } + ], + series : [ + { + name:'邮件营销', + type:'line', + stack: '总量', + data:[120, 132, 101, 134, 90, 230, 210] + }, + { + name:'联盟广告', + type:'line', + stack: '总量', + data:[220, 182, 191, 234, 290, 330, 310] + }, + { + name:'视频广告', + type:'line', + stack: '总量', + data:[150, 232, 201, 154, 190, 330, 410] + }, + { + name:'直接访问', + type:'line', + stack: '总量', + data:[320, 332, 301, 334, 390, 330, 320] + }, + { + name:'搜索引擎', + type:'line', + stack: '总量', + data:[820, 932, 901, 934, 1290, 1330, 1320] + } + ] + } + ] + ,elemheapline = $('#LAY-index-heapline').children('div') + ,renderheapline = function(index){ + echheapline[index] = echarts.init(elemheapline[index], layui.echartsTheme); + echheapline[index].setOption(heapline[index]); + window.onresize = echheapline[index].resize; + }; + if(!elemheapline[0]) return; + renderheapline(0); + + //不等距折线图 + var echdiffline = [], diffline = [ + { + title : { + text: '双数值轴折线', + subtext: '纯属虚构' + }, + tooltip : { + trigger: 'axis', + axisPointer:{ + show: true, + type : 'cross', + lineStyle: { + type : 'dashed', + width : 1 + } + }, + formatter : function (params) { + return params.seriesName + ' : [ '+ params.value[0] + ', ' + params.value[1] + ' ]'; + } + }, + legend: { + data:['数据1','数据2'] + }, + calculable : true, + xAxis : [ + { + type: 'value' + } + ], + yAxis : [ + { + type: 'value', + axisLine: { + lineStyle: { color: '#dc143c' } + } + } + ], + series : [ + { + name:'数据1', + type:'line', + data:[ + [1.5, 10], [5, 7], [8, 8], [12, 6], [11, 12], [16, 9], [14, 6], [17, 4], [19, 9] + ], + markPoint : { + data : [ + // 纵轴,默认 + {type : 'max', name: '最大值',symbol: 'emptyCircle', itemStyle:{normal:{color:'#dc143c',label:{position:'top'}}}}, + {type : 'min', name: '最小值',symbol: 'emptyCircle', itemStyle:{normal:{color:'#dc143c',label:{position:'bottom'}}}}, + // 横轴 + {type : 'max', name: '最大值', valueIndex: 0, symbol: 'emptyCircle', itemStyle:{normal:{color:'#1e90ff',label:{position:'right'}}}}, + {type : 'min', name: '最小值', valueIndex: 0, symbol: 'emptyCircle', itemStyle:{normal:{color:'#1e90ff',label:{position:'left'}}}} + ] + }, + markLine : { + data : [ + // 纵轴,默认 + {type : 'max', name: '最大值', itemStyle:{normal:{color:'#dc143c'}}}, + {type : 'min', name: '最小值', itemStyle:{normal:{color:'#dc143c'}}}, + {type : 'average', name : '平均值', itemStyle:{normal:{color:'#dc143c'}}}, + // 横轴 + {type : 'max', name: '最大值', valueIndex: 0, itemStyle:{normal:{color:'#1e90ff'}}}, + {type : 'min', name: '最小值', valueIndex: 0, itemStyle:{normal:{color:'#1e90ff'}}}, + {type : 'average', name : '平均值', valueIndex: 0, itemStyle:{normal:{color:'#1e90ff'}}} + ] + } + }, + { + name:'数据2', + type:'line', + data:[ + [1, 2], [2, 3], [4, 2], [7, 5], [11, 2], [18, 3] + ] + } + ] + } + ] + ,elemdiffline = $('#LAY-index-diffline').children('div') + ,renderdiffline = function(index){ + echdiffline[index] = echarts.init(elemdiffline[index], layui.echartsTheme); + echdiffline[index].setOption(diffline[index]); + window.onresize = echdiffline[index].resize; + }; + if(!elemdiffline[0]) return; + renderdiffline(0); + + //堆积面积图 + var echheaparea = [], heaparea = [ + { + tooltip : { + trigger: 'axis' + }, + legend: { + data:['邮件营销','联盟广告','视频广告','直接访问','搜索引擎'] + }, + calculable : true, + xAxis : [ + { + type : 'category', + boundaryGap : false, + data : ['周一','周二','周三','周四','周五','周六','周日'] + } + ], + yAxis : [ + { + type : 'value' + } + ], + series : [ + { + name:'邮件营销', + type:'line', + stack: '总量', + itemStyle: {normal: {areaStyle: {type: 'default'}}}, + data:[120, 132, 101, 134, 90, 230, 210] + }, + { + name:'联盟广告', + type:'line', + stack: '总量', + itemStyle: {normal: {areaStyle: {type: 'default'}}}, + data:[220, 182, 191, 234, 290, 330, 310] + }, + { + name:'视频广告', + type:'line', + stack: '总量', + itemStyle: {normal: {areaStyle: {type: 'default'}}}, + data:[150, 232, 201, 154, 190, 330, 410] + }, + { + name:'直接访问', + type:'line', + stack: '总量', + itemStyle: {normal: {areaStyle: {type: 'default'}}}, + data:[320, 332, 301, 334, 390, 330, 320] + }, + { + name:'搜索引擎', + type:'line', + stack: '总量', + itemStyle: {normal: {areaStyle: {type: 'default'}}}, + data:[820, 932, 901, 934, 1290, 1330, 1320] + } + ] + } + ] + ,elemheaparea = $('#LAY-index-heaparea').children('div') + ,renderheaparea = function(index){ + echheaparea[index] = echarts.init(elemheaparea[index], layui.echartsTheme); + echheaparea[index].setOption(heaparea[index]); + window.onresize = echheaparea[index].resize; + }; + if(!elemheaparea[0]) return; + renderheaparea(0); + + //面积图 + var echarea = [], area = [ + { + title : { + text: '雨量流量关系图', + x: 'center' + }, + tooltip : { + trigger: 'axis', + formatter: function(params) { + return params[0].name + '
' + params[0].seriesName + ' : ' + params[0].value + ' (m^3/s)
' + + params[1].seriesName + ' : ' + -params[1].value + ' (mm)'; + } + }, + legend: { + data:['流量','降雨量'], + x: 'left' + }, + dataZoom : { + show : true, + realtime : true, + start : 0, + end : 100 + }, + xAxis : [ + { + type : 'category', + boundaryGap : false, + axisLine: {onZero: false}, + data : [ + '2009/6/12 2:00', '2009/6/12 3:00', '2009/6/12 4:00', '2009/6/12 5:00', '2009/6/12 6:00', '2009/6/12 7:00', '2009/6/12 8:00', '2009/6/12 9:00', '2009/6/12 10:00', '2009/6/12 11:00', '2009/6/12 12:00', '2009/6/12 13:00', '2009/6/12 14:00', '2009/6/12 15:00', '2009/6/12 16:00', '2009/6/12 17:00', '2009/6/12 18:00', '2009/6/12 19:00', '2009/6/12 20:00', '2009/6/12 21:00', '2009/6/12 22:00', '2009/6/12 23:00', + '2009/6/13 0:00', '2009/6/13 1:00', '2009/6/13 2:00', '2009/6/13 3:00', '2009/6/13 4:00', '2009/6/13 5:00', '2009/6/13 6:00', '2009/6/13 7:00', '2009/6/13 8:00', '2009/6/13 9:00', '2009/6/13 10:00', '2009/6/13 11:00', '2009/6/13 12:00', '2009/6/13 13:00', '2009/6/13 14:00', '2009/6/13 15:00', '2009/6/13 16:00', '2009/6/13 17:00', '2009/6/13 18:00', '2009/6/13 19:00', '2009/6/13 20:00', '2009/6/13 21:00', '2009/6/13 22:00', '2009/6/13 23:00', + '2009/6/14 0:00', '2009/6/14 1:00', '2009/6/14 2:00', '2009/6/14 3:00', '2009/6/14 4:00', '2009/6/14 5:00', '2009/6/14 6:00', '2009/6/14 7:00', '2009/6/14 8:00', '2009/6/14 9:00', '2009/6/14 10:00', '2009/6/14 11:00', '2009/6/14 12:00', '2009/6/14 13:00', '2009/6/14 14:00', '2009/6/14 15:00', '2009/6/14 16:00', '2009/6/14 17:00', '2009/6/14 18:00', '2009/6/14 19:00', '2009/6/14 20:00', '2009/6/14 21:00', '2009/6/14 22:00', '2009/6/14 23:00', + '2009/6/15 0:00', '2009/6/15 1:00', '2009/6/15 2:00', '2009/6/15 3:00', '2009/6/15 4:00', '2009/6/15 5:00', '2009/6/15 6:00', '2009/6/15 7:00', '2009/6/15 8:00', '2009/6/15 9:00', '2009/6/15 10:00', '2009/6/15 11:00', '2009/6/15 12:00', '2009/6/15 13:00', '2009/6/15 14:00', '2009/6/15 15:00', '2009/6/15 16:00', '2009/6/15 17:00', '2009/6/15 18:00', '2009/6/15 19:00', '2009/6/15 20:00', '2009/6/15 21:00', '2009/6/15 22:00', '2009/6/15 23:00', + '2009/6/15 0:00', '2009/6/16 1:00', '2009/6/16 2:00', '2009/6/16 3:00', '2009/6/16 4:00', '2009/6/16 5:00', '2009/6/16 6:00', '2009/6/16 7:00', '2009/6/16 8:00', '2009/6/16 9:00', '2009/6/16 10:00', '2009/6/16 11:00', '2009/6/16 12:00', '2009/6/16 13:00', '2009/6/16 14:00', '2009/6/16 15:00', '2009/6/16 16:00', '2009/6/16 17:00', '2009/6/16 18:00', '2009/6/16 19:00', '2009/6/16 20:00', '2009/6/16 21:00', '2009/6/16 22:00', '2009/6/16 23:00', + '2009/6/15 0:00', '2009/6/17 1:00', '2009/6/17 2:00', '2009/6/17 3:00', '2009/6/17 4:00', '2009/6/17 5:00', '2009/6/17 6:00', '2009/6/17 7:00', '2009/6/17 8:00', '2009/6/17 9:00', '2009/6/17 10:00', '2009/6/17 11:00', '2009/6/17 12:00', '2009/6/17 13:00', '2009/6/17 14:00', '2009/6/17 15:00', '2009/6/17 16:00', '2009/6/17 17:00', '2009/6/17 18:00', '2009/6/17 19:00', '2009/6/17 20:00', '2009/6/17 21:00', '2009/6/17 22:00', '2009/6/17 23:00', + '2009/6/18 0:00', '2009/6/18 1:00', '2009/6/18 2:00', '2009/6/18 3:00', '2009/6/18 4:00', '2009/6/18 5:00', '2009/6/18 6:00', '2009/6/18 7:00', '2009/6/18 8:00', '2009/6/18 9:00', '2009/6/18 10:00', '2009/6/18 11:00', '2009/6/18 12:00', '2009/6/18 13:00', '2009/6/18 14:00', '2009/6/18 15:00', '2009/6/18 16:00', '2009/6/18 17:00', '2009/6/18 18:00', '2009/6/18 19:00', '2009/6/18 20:00', '2009/6/18 21:00', '2009/6/18 22:00', '2009/6/18 23:00', + '2009/6/15 0:00', '2009/6/19 1:00', '2009/6/19 2:00', '2009/6/19 3:00', '2009/6/19 4:00', '2009/6/19 5:00', '2009/6/19 6:00', '2009/6/19 7:00', '2009/6/19 8:00', '2009/6/19 9:00', '2009/6/19 10:00', '2009/6/19 11:00', '2009/6/19 12:00', '2009/6/19 13:00', '2009/6/19 14:00', '2009/6/19 15:00', '2009/6/19 16:00', '2009/6/19 17:00', '2009/6/19 18:00', '2009/6/19 19:00', '2009/6/19 20:00', '2009/6/19 21:00', '2009/6/19 22:00', '2009/6/19 23:00', + '2009/6/20 0:00', '2009/6/20 1:00', '2009/6/20 2:00', '2009/6/20 3:00', '2009/6/20 4:00', '2009/6/20 5:00', '2009/6/20 6:00', '2009/6/20 7:00', '2009/6/20 8:00', '2009/6/20 9:00', '2009/6/20 10:00', '2009/6/20 11:00', '2009/6/20 12:00', '2009/6/20 13:00', '2009/6/20 14:00', '2009/6/20 15:00', '2009/6/20 16:00', '2009/6/20 17:00', '2009/6/20 18:00', '2009/6/20 19:00', '2009/6/20 20:00', '2009/6/20 21:00', '2009/6/20 22:00', '2009/6/20 23:00', + '2009/6/21 0:00', '2009/6/21 1:00', '2009/6/21 2:00', '2009/6/21 3:00', '2009/6/21 4:00', '2009/6/21 5:00', '2009/6/21 6:00', '2009/6/21 7:00', '2009/6/21 8:00', '2009/6/21 9:00', '2009/6/21 10:00', '2009/6/21 11:00', '2009/6/21 12:00', '2009/6/21 13:00', '2009/6/21 14:00', '2009/6/21 15:00', '2009/6/21 16:00', '2009/6/21 17:00', '2009/6/21 18:00', '2009/6/21 19:00', '2009/6/21 20:00', '2009/6/21 21:00', '2009/6/21 22:00', '2009/6/21 23:00', + '2009/6/22 0:00', '2009/6/22 1:00', '2009/6/22 2:00', '2009/6/22 3:00', '2009/6/22 4:00', '2009/6/22 5:00', '2009/6/22 6:00', '2009/6/22 7:00', '2009/6/22 8:00', '2009/6/22 9:00', '2009/6/22 10:00', '2009/6/22 11:00', '2009/6/22 12:00', '2009/6/22 13:00', '2009/6/22 14:00', '2009/6/22 15:00', '2009/6/22 16:00', '2009/6/22 17:00', '2009/6/22 18:00', '2009/6/22 19:00', '2009/6/22 20:00', '2009/6/22 21:00', '2009/6/22 22:00', '2009/6/22 23:00', + '2009/6/23 0:00', '2009/6/23 1:00', '2009/6/23 2:00', '2009/6/23 3:00', '2009/6/23 4:00', '2009/6/23 5:00', '2009/6/23 6:00', '2009/6/23 7:00', '2009/6/23 8:00', '2009/6/23 9:00', '2009/6/23 10:00', '2009/6/23 11:00', '2009/6/23 12:00', '2009/6/23 13:00', '2009/6/23 14:00', '2009/6/23 15:00', '2009/6/23 16:00', '2009/6/23 17:00', '2009/6/23 18:00', '2009/6/23 19:00', '2009/6/23 20:00', '2009/6/23 21:00', '2009/6/23 22:00', '2009/6/23 23:00', + '2009/6/24 0:00', '2009/6/24 1:00', '2009/6/24 2:00', '2009/6/24 3:00', '2009/6/24 4:00', '2009/6/24 5:00', '2009/6/24 6:00', '2009/6/24 7:00', '2009/6/24 8:00', '2009/6/24 9:00', '2009/6/24 10:00', '2009/6/24 11:00', '2009/6/24 12:00', '2009/6/24 13:00', '2009/6/24 14:00', '2009/6/24 15:00', '2009/6/24 16:00', '2009/6/24 17:00', '2009/6/24 18:00', '2009/6/24 19:00', '2009/6/24 20:00', '2009/6/24 21:00', '2009/6/24 22:00', '2009/6/24 23:00', + '2009/6/25 0:00', '2009/6/25 1:00', '2009/6/25 2:00', '2009/6/25 3:00', '2009/6/25 4:00', '2009/6/25 5:00', '2009/6/25 6:00', '2009/6/25 7:00', '2009/6/25 8:00', '2009/6/25 9:00', '2009/6/25 10:00', '2009/6/25 11:00', '2009/6/25 12:00', '2009/6/25 13:00', '2009/6/25 14:00', '2009/6/25 15:00', '2009/6/25 16:00', '2009/6/25 17:00', '2009/6/25 18:00', '2009/6/25 19:00', '2009/6/25 20:00', '2009/6/25 21:00', '2009/6/25 22:00', '2009/6/25 23:00', + '2009/6/26 0:00', '2009/6/26 1:00', '2009/6/26 2:00', '2009/6/26 3:00', '2009/6/26 4:00', '2009/6/26 5:00', '2009/6/26 6:00', '2009/6/26 7:00', '2009/6/26 8:00', '2009/6/26 9:00', '2009/6/26 10:00', '2009/6/26 11:00', '2009/6/26 12:00', '2009/6/26 13:00', '2009/6/26 14:00', '2009/6/26 15:00', '2009/6/26 16:00', '2009/6/26 17:00', '2009/6/26 18:00', '2009/6/26 19:00', '2009/6/26 20:00', '2009/6/26 21:00', '2009/6/26 22:00', '2009/6/26 23:00', + '2009/6/27 0:00', '2009/6/27 1:00', '2009/6/27 2:00', '2009/6/27 3:00', '2009/6/27 4:00', '2009/6/27 5:00', '2009/6/27 6:00', '2009/6/27 7:00', '2009/6/27 8:00', '2009/6/27 9:00', '2009/6/27 10:00', '2009/6/27 11:00', '2009/6/27 12:00', '2009/6/27 13:00', '2009/6/27 14:00', '2009/6/27 15:00', '2009/6/27 16:00', '2009/6/27 17:00', '2009/6/27 18:00', '2009/6/27 19:00', '2009/6/27 20:00', '2009/6/27 21:00', '2009/6/27 22:00', '2009/6/27 23:00', + '2009/6/28 0:00', '2009/6/28 1:00', '2009/6/28 2:00', '2009/6/28 3:00', '2009/6/28 4:00', '2009/6/28 5:00', '2009/6/28 6:00', '2009/6/28 7:00', '2009/6/28 8:00', '2009/6/28 9:00', '2009/6/28 10:00', '2009/6/28 11:00', '2009/6/28 12:00', '2009/6/28 13:00', '2009/6/28 14:00', '2009/6/28 15:00', '2009/6/28 16:00', '2009/6/28 17:00', '2009/6/28 18:00', '2009/6/28 19:00', '2009/6/28 20:00', '2009/6/28 21:00', '2009/6/28 22:00', '2009/6/28 23:00', + '2009/6/29 0:00', '2009/6/29 1:00', '2009/6/29 2:00', '2009/6/29 3:00', '2009/6/29 4:00', '2009/6/29 5:00', '2009/6/29 6:00', '2009/6/29 7:00', '2009/6/29 8:00', '2009/6/29 9:00', '2009/6/29 10:00', '2009/6/29 11:00', '2009/6/29 12:00', '2009/6/29 13:00', '2009/6/29 14:00', '2009/6/29 15:00', '2009/6/29 16:00', '2009/6/29 17:00', '2009/6/29 18:00', '2009/6/29 19:00', '2009/6/29 20:00', '2009/6/29 21:00', '2009/6/29 22:00', '2009/6/29 23:00', + '2009/6/30 0:00', '2009/6/30 1:00', '2009/6/30 2:00', '2009/6/30 3:00', '2009/6/30 4:00', '2009/6/30 5:00', '2009/6/30 6:00', '2009/6/30 7:00', '2009/6/30 8:00', '2009/6/30 9:00', '2009/6/30 10:00', '2009/6/30 11:00', '2009/6/30 12:00', '2009/6/30 13:00', '2009/6/30 14:00', '2009/6/30 15:00', '2009/6/30 16:00', '2009/6/30 17:00', '2009/6/30 18:00', '2009/6/30 19:00', '2009/6/30 20:00', '2009/6/30 21:00', '2009/6/30 22:00', '2009/6/30 23:00', + '2009/7/1 0:00', '2009/7/1 1:00', '2009/7/1 2:00', '2009/7/1 3:00', '2009/7/1 4:00', '2009/7/1 5:00', '2009/7/1 6:00', '2009/7/1 7:00', '2009/7/1 8:00', '2009/7/1 9:00', '2009/7/1 10:00', '2009/7/1 11:00', '2009/7/1 12:00', '2009/7/1 13:00', '2009/7/1 14:00', '2009/7/1 15:00', '2009/7/1 16:00', '2009/7/1 17:00', '2009/7/1 18:00', '2009/7/1 19:00', '2009/7/1 20:00', '2009/7/1 21:00', '2009/7/1 22:00', '2009/7/1 23:00', + '2009/7/2 0:00', '2009/7/2 1:00', '2009/7/2 2:00', '2009/7/2 3:00', '2009/7/2 4:00', '2009/7/2 5:00', '2009/7/2 6:00', '2009/7/2 7:00', '2009/7/2 8:00', '2009/7/2 9:00', '2009/7/2 10:00', '2009/7/2 11:00', '2009/7/2 12:00', '2009/7/2 13:00', '2009/7/2 14:00', '2009/7/2 15:00', '2009/7/2 16:00', '2009/7/2 17:00', '2009/7/2 18:00', '2009/7/2 19:00', '2009/7/2 20:00', '2009/7/2 21:00', '2009/7/2 22:00', '2009/7/2 23:00', + '2009/7/3 0:00', '2009/7/3 1:00', '2009/7/3 2:00', '2009/7/3 3:00', '2009/7/3 4:00', '2009/7/3 5:00', '2009/7/3 6:00', '2009/7/3 7:00', '2009/7/3 8:00', '2009/7/3 9:00', '2009/7/3 10:00', '2009/7/3 11:00', '2009/7/3 12:00', '2009/7/3 13:00', '2009/7/3 14:00', '2009/7/3 15:00', '2009/7/3 16:00', '2009/7/3 17:00', '2009/7/3 18:00', '2009/7/3 19:00', '2009/7/3 20:00', '2009/7/3 21:00', '2009/7/3 22:00', '2009/7/3 23:00', + '2009/7/4 0:00', '2009/7/4 1:00', '2009/7/4 2:00', '2009/7/4 3:00', '2009/7/4 4:00', '2009/7/4 5:00', '2009/7/4 6:00', '2009/7/4 7:00', '2009/7/4 8:00', '2009/7/4 9:00', '2009/7/4 10:00', '2009/7/4 11:00', '2009/7/4 12:00', '2009/7/4 13:00', '2009/7/4 14:00', '2009/7/4 15:00', '2009/7/4 16:00', '2009/7/4 17:00', '2009/7/4 18:00', '2009/7/4 19:00', '2009/7/4 20:00', '2009/7/4 21:00', '2009/7/4 22:00', '2009/7/4 23:00', + '2009/7/5 0:00', '2009/7/5 1:00', '2009/7/5 2:00', '2009/7/5 3:00', '2009/7/5 4:00', '2009/7/5 5:00', '2009/7/5 6:00', '2009/7/5 7:00', '2009/7/5 8:00', '2009/7/5 9:00', '2009/7/5 10:00', '2009/7/5 11:00', '2009/7/5 12:00', '2009/7/5 13:00', '2009/7/5 14:00', '2009/7/5 15:00', '2009/7/5 16:00', '2009/7/5 17:00', '2009/7/5 18:00', '2009/7/5 19:00', '2009/7/5 20:00', '2009/7/5 21:00', '2009/7/5 22:00', '2009/7/5 23:00', + '2009/7/6 0:00', '2009/7/6 1:00', '2009/7/6 2:00', '2009/7/6 3:00', '2009/7/6 4:00', '2009/7/6 5:00', '2009/7/6 6:00', '2009/7/6 7:00', '2009/7/6 8:00', '2009/7/6 9:00', '2009/7/6 10:00', '2009/7/6 11:00', '2009/7/6 12:00', '2009/7/6 13:00', '2009/7/6 14:00', '2009/7/6 15:00', '2009/7/6 16:00', '2009/7/6 17:00', '2009/7/6 18:00', '2009/7/6 19:00', '2009/7/6 20:00', '2009/7/6 21:00', '2009/7/6 22:00', '2009/7/6 23:00', + '2009/7/7 0:00', '2009/7/7 1:00', '2009/7/7 2:00', '2009/7/7 3:00', '2009/7/7 4:00', '2009/7/7 5:00', '2009/7/7 6:00', '2009/7/7 7:00', '2009/7/7 8:00', '2009/7/7 9:00', '2009/7/7 10:00', '2009/7/7 11:00', '2009/7/7 12:00', '2009/7/7 13:00', '2009/7/7 14:00', '2009/7/7 15:00', '2009/7/7 16:00', '2009/7/7 17:00', '2009/7/7 18:00', '2009/7/7 19:00', '2009/7/7 20:00', '2009/7/7 21:00', '2009/7/7 22:00', '2009/7/7 23:00', + '2009/7/8 0:00', '2009/7/8 1:00', '2009/7/8 2:00', '2009/7/8 3:00', '2009/7/8 4:00', '2009/7/8 5:00', '2009/7/8 6:00', '2009/7/8 7:00', '2009/7/8 8:00', '2009/7/8 9:00', '2009/7/8 10:00', '2009/7/8 11:00', '2009/7/8 12:00', '2009/7/8 13:00', '2009/7/8 14:00', '2009/7/8 15:00', '2009/7/8 16:00', '2009/7/8 17:00', '2009/7/8 18:00', '2009/7/8 19:00', '2009/7/8 20:00', '2009/7/8 21:00', '2009/7/8 22:00', '2009/7/8 23:00', + '2009/7/9 0:00', '2009/7/9 1:00', '2009/7/9 2:00', '2009/7/9 3:00', '2009/7/9 4:00', '2009/7/9 5:00', '2009/7/9 6:00', '2009/7/9 7:00', '2009/7/9 8:00', '2009/7/9 9:00', '2009/7/9 10:00', '2009/7/9 11:00', '2009/7/9 12:00', '2009/7/9 13:00', '2009/7/9 14:00', '2009/7/9 15:00', '2009/7/9 16:00', '2009/7/9 17:00', '2009/7/9 18:00', '2009/7/9 19:00', '2009/7/9 20:00', '2009/7/9 21:00', '2009/7/9 22:00', '2009/7/9 23:00', + '2009/7/10 0:00', '2009/7/10 1:00', '2009/7/10 2:00', '2009/7/10 3:00', '2009/7/10 4:00', '2009/7/10 5:00', '2009/7/10 6:00', '2009/7/10 7:00', '2009/7/10 8:00', '2009/7/10 9:00', '2009/7/10 10:00', '2009/7/10 11:00', '2009/7/10 12:00', '2009/7/10 13:00', '2009/7/10 14:00', '2009/7/10 15:00', '2009/7/10 16:00', '2009/7/10 17:00', '2009/7/10 18:00', '2009/7/10 19:00', '2009/7/10 20:00', '2009/7/10 21:00', '2009/7/10 22:00', '2009/7/10 23:00', + '2009/7/11 0:00', '2009/7/11 1:00', '2009/7/11 2:00', '2009/7/11 3:00', '2009/7/11 4:00', '2009/7/11 5:00', '2009/7/11 6:00', '2009/7/11 7:00', '2009/7/11 8:00', '2009/7/11 9:00', '2009/7/11 10:00', '2009/7/11 11:00', '2009/7/11 12:00', '2009/7/11 13:00', '2009/7/11 14:00', '2009/7/11 15:00', '2009/7/11 16:00', '2009/7/11 17:00', '2009/7/11 18:00', '2009/7/11 19:00', '2009/7/11 20:00', '2009/7/11 21:00', '2009/7/11 22:00', '2009/7/11 23:00', + '2009/7/12 0:00', '2009/7/12 1:00', '2009/7/12 2:00', '2009/7/12 3:00', '2009/7/12 4:00', '2009/7/12 5:00', '2009/7/12 6:00', '2009/7/12 7:00', '2009/7/12 8:00', '2009/7/12 9:00', '2009/7/12 10:00', '2009/7/12 11:00', '2009/7/12 12:00', '2009/7/12 13:00', '2009/7/12 14:00', '2009/7/12 15:00', '2009/7/12 16:00', '2009/7/12 17:00', '2009/7/12 18:00', '2009/7/12 19:00', '2009/7/12 20:00', '2009/7/12 21:00', '2009/7/12 22:00', '2009/7/12 23:00', + '2009/7/13 0:00', '2009/7/13 1:00', '2009/7/13 2:00', '2009/7/13 3:00', '2009/7/13 4:00', '2009/7/13 5:00', '2009/7/13 6:00', '2009/7/13 7:00', '2009/7/13 8:00', '2009/7/13 9:00', '2009/7/13 10:00', '2009/7/13 11:00', '2009/7/13 12:00', '2009/7/13 13:00', '2009/7/13 14:00', '2009/7/13 15:00', '2009/7/13 16:00', '2009/7/13 17:00', '2009/7/13 18:00', '2009/7/13 19:00', '2009/7/13 20:00', '2009/7/13 21:00', '2009/7/13 22:00', '2009/7/13 23:00', + '2009/7/14 0:00', '2009/7/14 1:00', '2009/7/14 2:00', '2009/7/14 3:00', '2009/7/14 4:00', '2009/7/14 5:00', '2009/7/14 6:00', '2009/7/14 7:00', '2009/7/14 8:00', '2009/7/14 9:00', '2009/7/14 10:00', '2009/7/14 11:00', '2009/7/14 12:00', '2009/7/14 13:00', '2009/7/14 14:00', '2009/7/14 15:00', '2009/7/14 16:00', '2009/7/14 17:00', '2009/7/14 18:00', '2009/7/14 19:00', '2009/7/14 20:00', '2009/7/14 21:00', '2009/7/14 22:00', '2009/7/14 23:00', + '2009/7/15 0:00', '2009/7/15 1:00', '2009/7/15 2:00', '2009/7/15 3:00', '2009/7/15 4:00', '2009/7/15 5:00', '2009/7/15 6:00', '2009/7/15 7:00', '2009/7/15 8:00', '2009/7/15 9:00', '2009/7/15 10:00', '2009/7/15 11:00', '2009/7/15 12:00', '2009/7/15 13:00', '2009/7/15 14:00', '2009/7/15 15:00', '2009/7/15 16:00', '2009/7/15 17:00', '2009/7/15 18:00', '2009/7/15 19:00', '2009/7/15 20:00', '2009/7/15 21:00', '2009/7/15 22:00', '2009/7/15 23:00', + '2009/7/16 0:00', '2009/7/16 1:00', '2009/7/16 2:00', '2009/7/16 3:00', '2009/7/16 4:00', '2009/7/16 5:00', '2009/7/16 6:00', '2009/7/16 7:00', '2009/7/16 8:00', '2009/7/16 9:00', '2009/7/16 10:00', '2009/7/16 11:00', '2009/7/16 12:00', '2009/7/16 13:00', '2009/7/16 14:00', '2009/7/16 15:00', '2009/7/16 16:00', '2009/7/16 17:00', '2009/7/16 18:00', '2009/7/16 19:00', '2009/7/16 20:00', '2009/7/16 21:00', '2009/7/16 22:00', '2009/7/16 23:00', + '2009/7/17 0:00', '2009/7/17 1:00', '2009/7/17 2:00', '2009/7/17 3:00', '2009/7/17 4:00', '2009/7/17 5:00', '2009/7/17 6:00', '2009/7/17 7:00', '2009/7/17 8:00', '2009/7/17 9:00', '2009/7/17 10:00', '2009/7/17 11:00', '2009/7/17 12:00', '2009/7/17 13:00', '2009/7/17 14:00', '2009/7/17 15:00', '2009/7/17 16:00', '2009/7/17 17:00', '2009/7/17 18:00', '2009/7/17 19:00', '2009/7/17 20:00', '2009/7/17 21:00', '2009/7/17 22:00', '2009/7/17 23:00', + '2009/7/18 0:00', '2009/7/18 1:00', '2009/7/18 2:00', '2009/7/18 3:00', '2009/7/18 4:00', '2009/7/18 5:00', '2009/7/18 6:00', '2009/7/18 7:00', '2009/7/18 8:00', '2009/7/18 9:00', '2009/7/18 10:00', '2009/7/18 11:00', '2009/7/18 12:00', '2009/7/18 13:00', '2009/7/18 14:00', '2009/7/18 15:00', '2009/7/18 16:00', '2009/7/18 17:00', '2009/7/18 18:00', '2009/7/18 19:00', '2009/7/18 20:00', '2009/7/18 21:00', '2009/7/18 22:00', '2009/7/18 23:00', + '2009/7/19 0:00', '2009/7/19 1:00', '2009/7/19 2:00', '2009/7/19 3:00', '2009/7/19 4:00', '2009/7/19 5:00', '2009/7/19 6:00', '2009/7/19 7:00', '2009/7/19 8:00', '2009/7/19 9:00', '2009/7/19 10:00', '2009/7/19 11:00', '2009/7/19 12:00', '2009/7/19 13:00', '2009/7/19 14:00', '2009/7/19 15:00', '2009/7/19 16:00', '2009/7/19 17:00', '2009/7/19 18:00', '2009/7/19 19:00', '2009/7/19 20:00', '2009/7/19 21:00', '2009/7/19 22:00', '2009/7/19 23:00', + '2009/7/20 0:00', '2009/7/20 1:00', '2009/7/20 2:00', '2009/7/20 3:00', '2009/7/20 4:00', '2009/7/20 5:00', '2009/7/20 6:00', '2009/7/20 7:00', '2009/7/20 8:00', '2009/7/20 9:00', '2009/7/20 10:00', '2009/7/20 11:00', '2009/7/20 12:00', '2009/7/20 13:00', '2009/7/20 14:00', '2009/7/20 15:00', '2009/7/20 16:00', '2009/7/20 17:00', '2009/7/20 18:00', '2009/7/20 19:00', '2009/7/20 20:00', '2009/7/20 21:00', '2009/7/20 22:00', '2009/7/20 23:00', + '2009/7/21 0:00', '2009/7/21 1:00', '2009/7/21 2:00', '2009/7/21 3:00', '2009/7/21 4:00', '2009/7/21 5:00', '2009/7/21 6:00', '2009/7/21 7:00', '2009/7/21 8:00', '2009/7/21 9:00', '2009/7/21 10:00', '2009/7/21 11:00', '2009/7/21 12:00', '2009/7/21 13:00', '2009/7/21 14:00', '2009/7/21 15:00', '2009/7/21 16:00', '2009/7/21 17:00', '2009/7/21 18:00', '2009/7/21 19:00', '2009/7/21 20:00', '2009/7/21 21:00', '2009/7/21 22:00', '2009/7/21 23:00', + '2009/7/22 0:00', '2009/7/22 1:00', '2009/7/22 2:00', '2009/7/22 3:00', '2009/7/22 4:00', '2009/7/22 5:00', '2009/7/22 6:00', '2009/7/22 7:00', '2009/7/22 8:00', '2009/7/22 9:00', '2009/7/22 10:00', '2009/7/22 11:00', '2009/7/22 12:00', '2009/7/22 13:00', '2009/7/22 14:00', '2009/7/22 15:00', '2009/7/22 16:00', '2009/7/22 17:00', '2009/7/22 18:00', '2009/7/22 19:00', '2009/7/22 20:00', '2009/7/22 21:00', '2009/7/22 22:00', '2009/7/22 23:00', + '2009/7/23 0:00', '2009/7/23 1:00', '2009/7/23 2:00', '2009/7/23 3:00', '2009/7/23 4:00', '2009/7/23 5:00', '2009/7/23 6:00', '2009/7/23 7:00', '2009/7/23 8:00', '2009/7/23 9:00', '2009/7/23 10:00', '2009/7/23 11:00', '2009/7/23 12:00', '2009/7/23 13:00', '2009/7/23 14:00', '2009/7/23 15:00', '2009/7/23 16:00', '2009/7/23 17:00', '2009/7/23 18:00', '2009/7/23 19:00', '2009/7/23 20:00', '2009/7/23 21:00', '2009/7/23 22:00', '2009/7/23 23:00', + '2009/7/24 0:00', '2009/7/24 1:00', '2009/7/24 2:00', '2009/7/24 3:00', '2009/7/24 4:00', '2009/7/24 5:00', '2009/7/24 6:00', '2009/7/24 7:00', '2009/7/24 8:00', '2009/7/24 9:00', '2009/7/24 10:00', '2009/7/24 11:00', '2009/7/24 12:00', '2009/7/24 13:00', '2009/7/24 14:00', '2009/7/24 15:00', '2009/7/24 16:00', '2009/7/24 17:00', '2009/7/24 18:00', '2009/7/24 19:00', '2009/7/24 20:00', '2009/7/24 21:00', '2009/7/24 22:00', '2009/7/24 23:00', + '2009/7/25 0:00', '2009/7/25 1:00', '2009/7/25 2:00', '2009/7/25 3:00', '2009/7/25 4:00', '2009/7/25 5:00', '2009/7/25 6:00', '2009/7/25 7:00', '2009/7/25 8:00', '2009/7/25 9:00', '2009/7/25 10:00', '2009/7/25 11:00', '2009/7/25 12:00', '2009/7/25 13:00', '2009/7/25 14:00', '2009/7/25 15:00', '2009/7/25 16:00', '2009/7/25 17:00', '2009/7/25 18:00', '2009/7/25 19:00', '2009/7/25 20:00', '2009/7/25 21:00', '2009/7/25 22:00', '2009/7/25 23:00', + '2009/7/26 0:00', '2009/7/26 1:00', '2009/7/26 2:00', '2009/7/26 3:00', '2009/7/26 4:00', '2009/7/26 5:00', '2009/7/26 6:00', '2009/7/26 7:00', '2009/7/26 8:00', '2009/7/26 9:00', '2009/7/26 10:00', '2009/7/26 11:00', '2009/7/26 12:00', '2009/7/26 13:00', '2009/7/26 14:00', '2009/7/26 15:00', '2009/7/26 16:00', '2009/7/26 17:00', '2009/7/26 18:00', '2009/7/26 19:00', '2009/7/26 20:00', '2009/7/26 21:00', '2009/7/26 22:00', '2009/7/26 23:00', + '2009/7/27 0:00', '2009/7/27 1:00', '2009/7/27 2:00', '2009/7/27 3:00', '2009/7/27 4:00', '2009/7/27 5:00', '2009/7/27 6:00', '2009/7/27 7:00', '2009/7/27 8:00', '2009/7/27 9:00', '2009/7/27 10:00', '2009/7/27 11:00', '2009/7/27 12:00', '2009/7/27 13:00', '2009/7/27 14:00', '2009/7/27 15:00', '2009/7/27 16:00', '2009/7/27 17:00', '2009/7/27 18:00', '2009/7/27 19:00', '2009/7/27 20:00', '2009/7/27 21:00', '2009/7/27 22:00', '2009/7/27 23:00', + '2009/7/28 0:00', '2009/7/28 1:00', '2009/7/28 2:00', '2009/7/28 3:00', '2009/7/28 4:00', '2009/7/28 5:00', '2009/7/28 6:00', '2009/7/28 7:00', '2009/7/28 8:00', '2009/7/28 9:00', '2009/7/28 10:00', '2009/7/28 11:00', '2009/7/28 12:00', '2009/7/28 13:00', '2009/7/28 14:00', '2009/7/28 15:00', '2009/7/28 16:00', '2009/7/28 17:00', '2009/7/28 18:00', '2009/7/28 19:00', '2009/7/28 20:00', '2009/7/28 21:00', '2009/7/28 22:00', '2009/7/28 23:00', + '2009/7/29 0:00', '2009/7/29 1:00', '2009/7/29 2:00', '2009/7/29 3:00', '2009/7/29 4:00', '2009/7/29 5:00', '2009/7/29 6:00', '2009/7/29 7:00', '2009/7/29 8:00', '2009/7/29 9:00', '2009/7/29 10:00', '2009/7/29 11:00', '2009/7/29 12:00', '2009/7/29 13:00', '2009/7/29 14:00', '2009/7/29 15:00', '2009/7/29 16:00', '2009/7/29 17:00', '2009/7/29 18:00', '2009/7/29 19:00', '2009/7/29 20:00', '2009/7/29 21:00', '2009/7/29 22:00', '2009/7/29 23:00', + '2009/7/30 0:00', '2009/7/30 1:00', '2009/7/30 2:00', '2009/7/30 3:00', '2009/7/30 4:00', '2009/7/30 5:00', '2009/7/30 6:00', '2009/7/30 7:00', '2009/7/30 8:00', '2009/7/30 9:00', '2009/7/30 10:00', '2009/7/30 11:00', '2009/7/30 12:00', '2009/7/30 13:00', '2009/7/30 14:00', '2009/7/30 15:00', '2009/7/30 16:00', '2009/7/30 17:00', '2009/7/30 18:00', '2009/7/30 19:00', '2009/7/30 20:00', '2009/7/30 21:00', '2009/7/30 22:00', '2009/7/30 23:00', + '2009/7/31 0:00', '2009/7/31 1:00', '2009/7/31 2:00', '2009/7/31 3:00', '2009/7/31 4:00', '2009/7/31 5:00', '2009/7/31 6:00', '2009/7/31 7:00', '2009/7/31 8:00', '2009/7/31 9:00', '2009/7/31 10:00', '2009/7/31 11:00', '2009/7/31 12:00', '2009/7/31 13:00', '2009/7/31 14:00', '2009/7/31 15:00', '2009/7/31 16:00', '2009/7/31 17:00', '2009/7/31 18:00', '2009/7/31 19:00', '2009/7/31 20:00', '2009/7/31 21:00', '2009/7/31 22:00', '2009/7/31 23:00', + '2009/8/1 0:00', '2009/8/1 1:00', '2009/8/1 2:00', '2009/8/1 3:00', '2009/8/1 4:00', '2009/8/1 5:00', '2009/8/1 6:00', '2009/8/1 7:00', '2009/8/1 8:00', '2009/8/1 9:00', '2009/8/1 10:00', '2009/8/1 11:00', '2009/8/1 12:00', '2009/8/1 13:00', '2009/8/1 14:00', '2009/8/1 15:00', '2009/8/1 16:00', '2009/8/1 17:00', '2009/8/1 18:00', '2009/8/1 19:00', '2009/8/1 20:00', '2009/8/1 21:00', '2009/8/1 22:00', '2009/8/1 23:00', '2009/8/2 0:00', '2009/8/2 1:00', '2009/8/2 2:00', '2009/8/2 3:00', '2009/8/2 4:00', '2009/8/2 5:00', '2009/8/2 6:00', '2009/8/2 7:00', '2009/8/2 8:00', '2009/8/2 9:00', '2009/8/2 10:00', '2009/8/2 11:00', '2009/8/2 12:00', '2009/8/2 13:00', '2009/8/2 14:00', '2009/8/2 15:00', '2009/8/2 16:00', '2009/8/2 17:00', '2009/8/2 18:00', '2009/8/2 19:00', '2009/8/2 20:00', '2009/8/2 21:00', '2009/8/2 22:00', '2009/8/2 23:00', '2009/8/3 0:00', '2009/8/3 1:00', '2009/8/3 2:00', '2009/8/3 3:00', '2009/8/3 4:00', '2009/8/3 5:00', '2009/8/3 6:00', '2009/8/3 7:00', '2009/8/3 8:00', '2009/8/3 9:00', '2009/8/3 10:00', '2009/8/3 11:00', '2009/8/3 12:00', '2009/8/3 13:00', '2009/8/3 14:00', '2009/8/3 15:00', '2009/8/3 16:00', '2009/8/3 17:00', '2009/8/3 18:00', '2009/8/3 19:00', '2009/8/3 20:00', '2009/8/3 21:00', '2009/8/3 22:00', '2009/8/3 23:00', '2009/8/4 0:00', '2009/8/4 1:00', '2009/8/4 2:00', '2009/8/4 3:00', '2009/8/4 4:00', '2009/8/4 5:00', '2009/8/4 6:00', '2009/8/4 7:00', '2009/8/4 8:00', '2009/8/4 9:00', '2009/8/4 10:00', '2009/8/4 11:00', '2009/8/4 12:00', '2009/8/4 13:00', '2009/8/4 14:00', '2009/8/4 15:00', '2009/8/4 16:00', '2009/8/4 17:00', '2009/8/4 18:00', '2009/8/4 19:00', '2009/8/4 20:00', '2009/8/4 21:00', '2009/8/4 22:00', '2009/8/4 23:00', '2009/8/5 0:00', '2009/8/5 1:00', '2009/8/5 2:00', '2009/8/5 3:00', '2009/8/5 4:00', '2009/8/5 5:00', '2009/8/5 6:00', '2009/8/5 7:00', '2009/8/5 8:00', '2009/8/5 9:00', '2009/8/5 10:00', '2009/8/5 11:00', '2009/8/5 12:00', '2009/8/5 13:00', '2009/8/5 14:00', '2009/8/5 15:00', '2009/8/5 16:00', '2009/8/5 17:00', '2009/8/5 18:00', '2009/8/5 19:00', '2009/8/5 20:00', '2009/8/5 21:00', '2009/8/5 22:00', '2009/8/5 23:00', '2009/8/6 0:00', '2009/8/6 1:00', '2009/8/6 2:00', '2009/8/6 3:00', '2009/8/6 4:00', '2009/8/6 5:00', '2009/8/6 6:00', '2009/8/6 7:00', '2009/8/6 8:00', '2009/8/6 9:00', '2009/8/6 10:00', '2009/8/6 11:00', '2009/8/6 12:00', '2009/8/6 13:00', '2009/8/6 14:00', '2009/8/6 15:00', '2009/8/6 16:00', '2009/8/6 17:00', '2009/8/6 18:00', '2009/8/6 19:00', '2009/8/6 20:00', '2009/8/6 21:00', '2009/8/6 22:00', '2009/8/6 23:00', '2009/8/7 0:00', '2009/8/7 1:00', '2009/8/7 2:00', '2009/8/7 3:00', '2009/8/7 4:00', '2009/8/7 5:00', '2009/8/7 6:00', '2009/8/7 7:00', '2009/8/7 8:00', '2009/8/7 9:00', '2009/8/7 10:00', '2009/8/7 11:00', '2009/8/7 12:00', '2009/8/7 13:00', '2009/8/7 14:00', '2009/8/7 15:00', '2009/8/7 16:00', '2009/8/7 17:00', '2009/8/7 18:00', '2009/8/7 19:00', '2009/8/7 20:00', '2009/8/7 21:00', '2009/8/7 22:00', '2009/8/7 23:00', '2009/8/8 0:00', '2009/8/8 1:00', '2009/8/8 2:00', '2009/8/8 3:00', '2009/8/8 4:00', '2009/8/8 5:00', '2009/8/8 6:00', '2009/8/8 7:00', '2009/8/8 8:00', '2009/8/8 9:00', '2009/8/8 10:00', '2009/8/8 11:00', '2009/8/8 12:00', '2009/8/8 13:00', '2009/8/8 14:00', '2009/8/8 15:00', '2009/8/8 16:00', '2009/8/8 17:00', '2009/8/8 18:00', '2009/8/8 19:00', '2009/8/8 20:00', '2009/8/8 21:00', '2009/8/8 22:00', '2009/8/8 23:00', '2009/8/9 0:00', '2009/8/9 1:00', '2009/8/9 2:00', '2009/8/9 3:00', '2009/8/9 4:00', '2009/8/9 5:00', '2009/8/9 6:00', '2009/8/9 7:00', '2009/8/9 8:00', '2009/8/9 9:00', '2009/8/9 10:00', '2009/8/9 11:00', '2009/8/9 12:00', '2009/8/9 13:00', '2009/8/9 14:00', '2009/8/9 15:00', '2009/8/9 16:00', '2009/8/9 17:00', '2009/8/9 18:00', '2009/8/9 19:00', '2009/8/9 20:00', '2009/8/9 21:00', '2009/8/9 22:00', '2009/8/9 23:00', '2009/8/10 0:00', '2009/8/10 1:00', '2009/8/10 2:00', '2009/8/10 3:00', '2009/8/10 4:00', '2009/8/10 5:00', '2009/8/10 6:00', '2009/8/10 7:00', '2009/8/10 8:00', '2009/8/10 9:00', '2009/8/10 10:00', '2009/8/10 11:00', '2009/8/10 12:00', '2009/8/10 13:00', '2009/8/10 14:00', '2009/8/10 15:00', '2009/8/10 16:00', '2009/8/10 17:00', '2009/8/10 18:00', '2009/8/10 19:00', '2009/8/10 20:00', '2009/8/10 21:00', '2009/8/10 22:00', '2009/8/10 23:00', '2009/8/11 0:00', '2009/8/11 1:00', '2009/8/11 2:00', '2009/8/11 3:00', '2009/8/11 4:00', '2009/8/11 5:00', '2009/8/11 6:00', '2009/8/11 7:00', '2009/8/11 8:00', '2009/8/11 9:00', '2009/8/11 10:00', '2009/8/11 11:00', '2009/8/11 12:00', '2009/8/11 13:00', '2009/8/11 14:00', '2009/8/11 15:00', '2009/8/11 16:00', '2009/8/11 17:00', '2009/8/11 18:00', '2009/8/11 19:00', '2009/8/11 20:00', '2009/8/11 21:00', '2009/8/11 22:00', '2009/8/11 23:00', '2009/8/12 0:00', '2009/8/12 1:00', '2009/8/12 2:00', '2009/8/12 3:00', '2009/8/12 4:00', '2009/8/12 5:00', '2009/8/12 6:00', '2009/8/12 7:00', '2009/8/12 8:00', '2009/8/12 9:00', '2009/8/12 10:00', '2009/8/12 11:00', '2009/8/12 12:00', '2009/8/12 13:00', '2009/8/12 14:00', '2009/8/12 15:00', '2009/8/12 16:00', '2009/8/12 17:00', '2009/8/12 18:00', '2009/8/12 19:00', '2009/8/12 20:00', '2009/8/12 21:00', '2009/8/12 22:00', '2009/8/12 23:00', '2009/8/13 0:00', '2009/8/13 1:00', '2009/8/13 2:00', '2009/8/13 3:00', '2009/8/13 4:00', '2009/8/13 5:00', '2009/8/13 6:00', '2009/8/13 7:00', '2009/8/13 8:00', '2009/8/13 9:00', '2009/8/13 10:00', '2009/8/13 11:00', '2009/8/13 12:00', '2009/8/13 13:00', '2009/8/13 14:00', '2009/8/13 15:00', '2009/8/13 16:00', '2009/8/13 17:00', '2009/8/13 18:00', '2009/8/13 19:00', '2009/8/13 20:00', '2009/8/13 21:00', '2009/8/13 22:00', '2009/8/13 23:00', '2009/8/14 0:00', '2009/8/14 1:00', '2009/8/14 2:00', '2009/8/14 3:00', '2009/8/14 4:00', '2009/8/14 5:00', '2009/8/14 6:00', '2009/8/14 7:00', '2009/8/14 8:00', '2009/8/14 9:00', '2009/8/14 10:00', '2009/8/14 11:00', '2009/8/14 12:00', '2009/8/14 13:00', '2009/8/14 14:00', '2009/8/14 15:00', '2009/8/14 16:00', '2009/8/14 17:00', '2009/8/14 18:00', '2009/8/14 19:00', '2009/8/14 20:00', '2009/8/14 21:00', '2009/8/14 22:00', '2009/8/14 23:00', '2009/8/15 0:00', '2009/8/15 1:00', '2009/8/15 2:00', '2009/8/15 3:00', '2009/8/15 4:00', '2009/8/15 5:00', '2009/8/15 6:00', '2009/8/15 7:00', '2009/8/15 8:00', '2009/8/15 9:00', '2009/8/15 10:00', '2009/8/15 11:00', '2009/8/15 12:00', '2009/8/15 13:00', '2009/8/15 14:00', '2009/8/15 15:00', '2009/8/15 16:00', '2009/8/15 17:00', '2009/8/15 18:00', '2009/8/15 19:00', '2009/8/15 20:00', '2009/8/15 21:00', '2009/8/15 22:00', '2009/8/15 23:00', '2009/8/16 0:00', '2009/8/16 1:00', '2009/8/16 2:00', '2009/8/16 3:00', '2009/8/16 4:00', '2009/8/16 5:00', '2009/8/16 6:00', '2009/8/16 7:00', '2009/8/16 8:00', '2009/8/16 9:00', '2009/8/16 10:00', '2009/8/16 11:00', '2009/8/16 12:00', '2009/8/16 13:00', '2009/8/16 14:00', '2009/8/16 15:00', '2009/8/16 16:00', '2009/8/16 17:00', '2009/8/16 18:00', '2009/8/16 19:00', '2009/8/16 20:00', '2009/8/16 21:00', '2009/8/16 22:00', '2009/8/16 23:00', '2009/8/17 0:00', '2009/8/17 1:00', '2009/8/17 2:00', '2009/8/17 3:00', '2009/8/17 4:00', '2009/8/17 5:00', '2009/8/17 6:00', '2009/8/17 7:00', '2009/8/17 8:00', '2009/8/17 9:00', '2009/8/17 10:00', '2009/8/17 11:00', '2009/8/17 12:00', '2009/8/17 13:00', '2009/8/17 14:00', '2009/8/17 15:00', '2009/8/17 16:00', '2009/8/17 17:00', '2009/8/17 18:00', '2009/8/17 19:00', '2009/8/17 20:00', '2009/8/17 21:00', '2009/8/17 22:00', '2009/8/17 23:00', '2009/8/18 0:00', '2009/8/18 1:00', '2009/8/18 2:00', '2009/8/18 3:00', '2009/8/18 4:00', '2009/8/18 5:00', '2009/8/18 6:00', '2009/8/18 7:00', '2009/8/18 8:00', '2009/8/18 9:00', '2009/8/18 10:00', '2009/8/18 11:00', '2009/8/18 12:00', '2009/8/18 13:00', '2009/8/18 14:00', '2009/8/18 15:00', '2009/8/18 16:00', '2009/8/18 17:00', '2009/8/18 18:00', '2009/8/18 19:00', '2009/8/18 20:00', '2009/8/18 21:00', '2009/8/18 22:00', '2009/8/18 23:00', '2009/8/19 0:00', '2009/8/19 1:00', '2009/8/19 2:00', '2009/8/19 3:00', '2009/8/19 4:00', '2009/8/19 5:00', '2009/8/19 6:00', '2009/8/19 7:00', '2009/8/19 8:00', '2009/8/19 9:00', '2009/8/19 10:00', '2009/8/19 11:00', '2009/8/19 12:00', '2009/8/19 13:00', '2009/8/19 14:00', '2009/8/19 15:00', '2009/8/19 16:00', '2009/8/19 17:00', '2009/8/19 18:00', '2009/8/19 19:00', '2009/8/19 20:00', '2009/8/19 21:00', '2009/8/19 22:00', '2009/8/19 23:00', '2009/8/20 0:00', '2009/8/20 1:00', '2009/8/20 2:00', '2009/8/20 3:00', '2009/8/20 4:00', '2009/8/20 5:00', '2009/8/20 6:00', '2009/8/20 7:00', '2009/8/20 8:00', '2009/8/20 9:00', '2009/8/20 10:00', '2009/8/20 11:00', '2009/8/20 12:00', '2009/8/20 13:00', '2009/8/20 14:00', '2009/8/20 15:00', '2009/8/20 16:00', '2009/8/20 17:00', '2009/8/20 18:00', '2009/8/20 19:00', '2009/8/20 20:00', '2009/8/20 21:00', '2009/8/20 22:00', '2009/8/20 23:00', '2009/8/21 0:00', '2009/8/21 1:00', '2009/8/21 2:00', '2009/8/21 3:00', '2009/8/21 4:00', '2009/8/21 5:00', '2009/8/21 6:00', '2009/8/21 7:00', '2009/8/21 8:00', '2009/8/21 9:00', '2009/8/21 10:00', '2009/8/21 11:00', '2009/8/21 12:00', '2009/8/21 13:00', '2009/8/21 14:00', '2009/8/21 15:00', '2009/8/21 16:00', '2009/8/21 17:00', '2009/8/21 18:00', '2009/8/21 19:00', '2009/8/21 20:00', '2009/8/21 21:00', '2009/8/21 22:00', '2009/8/21 23:00', '2009/8/22 0:00', '2009/8/22 1:00', '2009/8/22 2:00', '2009/8/22 3:00', '2009/8/22 4:00', '2009/8/22 5:00', '2009/8/22 6:00', '2009/8/22 7:00', '2009/8/22 8:00', '2009/8/22 9:00', '2009/8/22 10:00', '2009/8/22 11:00', '2009/8/22 12:00', '2009/8/22 13:00', '2009/8/22 14:00', '2009/8/22 15:00', '2009/8/22 16:00', '2009/8/22 17:00', '2009/8/22 18:00', '2009/8/22 19:00', '2009/8/22 20:00', '2009/8/22 21:00', '2009/8/22 22:00', '2009/8/22 23:00', '2009/8/23 0:00', '2009/8/23 1:00', '2009/8/23 2:00', '2009/8/23 3:00', '2009/8/23 4:00', '2009/8/23 5:00', '2009/8/23 6:00', '2009/8/23 7:00', '2009/8/23 8:00', '2009/8/23 9:00', '2009/8/23 10:00', '2009/8/23 11:00', '2009/8/23 12:00', '2009/8/23 13:00', '2009/8/23 14:00', '2009/8/23 15:00', '2009/8/23 16:00', '2009/8/23 17:00', '2009/8/23 18:00', '2009/8/23 19:00', '2009/8/23 20:00', '2009/8/23 21:00', '2009/8/23 22:00', '2009/8/23 23:00', '2009/8/24 0:00', '2009/8/24 1:00', '2009/8/24 2:00', '2009/8/24 3:00', '2009/8/24 4:00', '2009/8/24 5:00', '2009/8/24 6:00', '2009/8/24 7:00', '2009/8/24 8:00', '2009/8/24 9:00', '2009/8/24 10:00', '2009/8/24 11:00', '2009/8/24 12:00', '2009/8/24 13:00', '2009/8/24 14:00', '2009/8/24 15:00', '2009/8/24 16:00', '2009/8/24 17:00', '2009/8/24 18:00', '2009/8/24 19:00', '2009/8/24 20:00', '2009/8/24 21:00', '2009/8/24 22:00', '2009/8/24 23:00', '2009/8/25 0:00', '2009/8/25 1:00', '2009/8/25 2:00', '2009/8/25 3:00', '2009/8/25 4:00', '2009/8/25 5:00', '2009/8/25 6:00', '2009/8/25 7:00', '2009/8/25 8:00', '2009/8/25 9:00', '2009/8/25 10:00', '2009/8/25 11:00', '2009/8/25 12:00', '2009/8/25 13:00', '2009/8/25 14:00', '2009/8/25 15:00', '2009/8/25 16:00', '2009/8/25 17:00', '2009/8/25 18:00', '2009/8/25 19:00', '2009/8/25 20:00', '2009/8/25 21:00', '2009/8/25 22:00', '2009/8/25 23:00', '2009/8/26 0:00', '2009/8/26 1:00', '2009/8/26 2:00', '2009/8/26 3:00', '2009/8/26 4:00', '2009/8/26 5:00', '2009/8/26 6:00', '2009/8/26 7:00', '2009/8/26 8:00', '2009/8/26 9:00', '2009/8/26 10:00', '2009/8/26 11:00', '2009/8/26 12:00', '2009/8/26 13:00', '2009/8/26 14:00', '2009/8/26 15:00', '2009/8/26 16:00', '2009/8/26 17:00', '2009/8/26 18:00', '2009/8/26 19:00', '2009/8/26 20:00', '2009/8/26 21:00', '2009/8/26 22:00', '2009/8/26 23:00', '2009/8/27 0:00', '2009/8/27 1:00', '2009/8/27 2:00', '2009/8/27 3:00', '2009/8/27 4:00', '2009/8/27 5:00', '2009/8/27 6:00', '2009/8/27 7:00', '2009/8/27 8:00', '2009/8/27 9:00', '2009/8/27 10:00', '2009/8/27 11:00', '2009/8/27 12:00', '2009/8/27 13:00', '2009/8/27 14:00', '2009/8/27 15:00', '2009/8/27 16:00', '2009/8/27 17:00', '2009/8/27 18:00', '2009/8/27 19:00', '2009/8/27 20:00', '2009/8/27 21:00', '2009/8/27 22:00', '2009/8/27 23:00', '2009/8/28 0:00', '2009/8/28 1:00', '2009/8/28 2:00', '2009/8/28 3:00', '2009/8/28 4:00', '2009/8/28 5:00', '2009/8/28 6:00', '2009/8/28 7:00', '2009/8/28 8:00', '2009/8/28 9:00', '2009/8/28 10:00', '2009/8/28 11:00', '2009/8/28 12:00', '2009/8/28 13:00', '2009/8/28 14:00', '2009/8/28 15:00', '2009/8/28 16:00', '2009/8/28 17:00', '2009/8/28 18:00', '2009/8/28 19:00', '2009/8/28 20:00', '2009/8/28 21:00', '2009/8/28 22:00', '2009/8/28 23:00', '2009/8/29 0:00', '2009/8/29 1:00', '2009/8/29 2:00', '2009/8/29 3:00', '2009/8/29 4:00', '2009/8/29 5:00', '2009/8/29 6:00', '2009/8/29 7:00', '2009/8/29 8:00', '2009/8/29 9:00', '2009/8/29 10:00', '2009/8/29 11:00', '2009/8/29 12:00', '2009/8/29 13:00', '2009/8/29 14:00', '2009/8/29 15:00', '2009/8/29 16:00', '2009/8/29 17:00', '2009/8/29 18:00', '2009/8/29 19:00', '2009/8/29 20:00', '2009/8/29 21:00', '2009/8/29 22:00', '2009/8/29 23:00', '2009/8/30 0:00', '2009/8/30 1:00', '2009/8/30 2:00', '2009/8/30 3:00', '2009/8/30 4:00', '2009/8/30 5:00', '2009/8/30 6:00', '2009/8/30 7:00', '2009/8/30 8:00', '2009/8/30 9:00', '2009/8/30 10:00', '2009/8/30 11:00', '2009/8/30 12:00', '2009/8/30 13:00', '2009/8/30 14:00', '2009/8/30 15:00', '2009/8/30 16:00', '2009/8/30 17:00', '2009/8/30 18:00', '2009/8/30 19:00', '2009/8/30 20:00', '2009/8/30 21:00', '2009/8/30 22:00', '2009/8/30 23:00', '2009/8/31 0:00', '2009/8/31 1:00', '2009/8/31 2:00', '2009/8/31 3:00', '2009/8/31 4:00', '2009/8/31 5:00', '2009/8/31 6:00', '2009/8/31 7:00', '2009/8/31 8:00', '2009/8/31 9:00', '2009/8/31 10:00', '2009/8/31 11:00', '2009/8/31 12:00', '2009/8/31 13:00', '2009/8/31 14:00', '2009/8/31 15:00', '2009/8/31 16:00', '2009/8/31 17:00', '2009/8/31 18:00', '2009/8/31 19:00', '2009/8/31 20:00', '2009/8/31 21:00', '2009/8/31 22:00', '2009/8/31 23:00', + '2009/9/1 0:00', '2009/9/1 1:00', '2009/9/1 2:00', '2009/9/1 3:00', '2009/9/1 4:00', '2009/9/1 5:00', '2009/9/1 6:00', '2009/9/1 7:00', '2009/9/1 8:00', '2009/9/1 9:00', '2009/9/1 10:00', '2009/9/1 11:00', '2009/9/1 12:00', '2009/9/1 13:00', '2009/9/1 14:00', '2009/9/1 15:00', '2009/9/1 16:00', '2009/9/1 17:00', '2009/9/1 18:00', '2009/9/1 19:00', '2009/9/1 20:00', '2009/9/1 21:00', '2009/9/1 22:00', '2009/9/1 23:00', '2009/9/2 0:00', '2009/9/2 1:00', '2009/9/2 2:00', '2009/9/2 3:00', '2009/9/2 4:00', '2009/9/2 5:00', '2009/9/2 6:00', '2009/9/2 7:00', '2009/9/2 8:00', '2009/9/2 9:00', '2009/9/2 10:00', '2009/9/2 11:00', '2009/9/2 12:00', '2009/9/2 13:00', '2009/9/2 14:00', '2009/9/2 15:00', '2009/9/2 16:00', '2009/9/2 17:00', '2009/9/2 18:00', '2009/9/2 19:00', '2009/9/2 20:00', '2009/9/2 21:00', '2009/9/2 22:00', '2009/9/2 23:00', '2009/9/3 0:00', '2009/9/3 1:00', '2009/9/3 2:00', '2009/9/3 3:00', '2009/9/3 4:00', '2009/9/3 5:00', '2009/9/3 6:00', '2009/9/3 7:00', '2009/9/3 8:00', '2009/9/3 9:00', '2009/9/3 10:00', '2009/9/3 11:00', '2009/9/3 12:00', '2009/9/3 13:00', '2009/9/3 14:00', '2009/9/3 15:00', '2009/9/3 16:00', '2009/9/3 17:00', '2009/9/3 18:00', '2009/9/3 19:00', '2009/9/3 20:00', '2009/9/3 21:00', '2009/9/3 22:00', '2009/9/3 23:00', '2009/9/4 0:00', '2009/9/4 1:00', '2009/9/4 2:00', '2009/9/4 3:00', '2009/9/4 4:00', '2009/9/4 5:00', '2009/9/4 6:00', '2009/9/4 7:00', '2009/9/4 8:00', '2009/9/4 9:00', '2009/9/4 10:00', '2009/9/4 11:00', '2009/9/4 12:00', '2009/9/4 13:00', '2009/9/4 14:00', '2009/9/4 15:00', '2009/9/4 16:00', '2009/9/4 17:00', '2009/9/4 18:00', '2009/9/4 19:00', '2009/9/4 20:00', '2009/9/4 21:00', '2009/9/4 22:00', '2009/9/4 23:00', '2009/9/5 0:00', '2009/9/5 1:00', '2009/9/5 2:00', '2009/9/5 3:00', '2009/9/5 4:00', '2009/9/5 5:00', '2009/9/5 6:00', '2009/9/5 7:00', '2009/9/5 8:00', '2009/9/5 9:00', '2009/9/5 10:00', '2009/9/5 11:00', '2009/9/5 12:00', '2009/9/5 13:00', '2009/9/5 14:00', '2009/9/5 15:00', '2009/9/5 16:00', '2009/9/5 17:00', '2009/9/5 18:00', '2009/9/5 19:00', '2009/9/5 20:00', '2009/9/5 21:00', '2009/9/5 22:00', '2009/9/5 23:00', '2009/9/6 0:00', '2009/9/6 1:00', '2009/9/6 2:00', '2009/9/6 3:00', '2009/9/6 4:00', '2009/9/6 5:00', '2009/9/6 6:00', '2009/9/6 7:00', '2009/9/6 8:00', '2009/9/6 9:00', '2009/9/6 10:00', '2009/9/6 11:00', '2009/9/6 12:00', '2009/9/6 13:00', '2009/9/6 14:00', '2009/9/6 15:00', '2009/9/6 16:00', '2009/9/6 17:00', '2009/9/6 18:00', '2009/9/6 19:00', '2009/9/6 20:00', '2009/9/6 21:00', '2009/9/6 22:00', '2009/9/6 23:00', '2009/9/7 0:00', '2009/9/7 1:00', '2009/9/7 2:00', '2009/9/7 3:00', '2009/9/7 4:00', '2009/9/7 5:00', '2009/9/7 6:00', '2009/9/7 7:00', '2009/9/7 8:00', '2009/9/7 9:00', '2009/9/7 10:00', '2009/9/7 11:00', '2009/9/7 12:00', '2009/9/7 13:00', '2009/9/7 14:00', '2009/9/7 15:00', '2009/9/7 16:00', '2009/9/7 17:00', '2009/9/7 18:00', '2009/9/7 19:00', '2009/9/7 20:00', '2009/9/7 21:00', '2009/9/7 22:00', '2009/9/7 23:00', '2009/9/8 0:00', '2009/9/8 1:00', '2009/9/8 2:00', '2009/9/8 3:00', '2009/9/8 4:00', '2009/9/8 5:00', '2009/9/8 6:00', '2009/9/8 7:00', '2009/9/8 8:00', '2009/9/8 9:00', '2009/9/8 10:00', '2009/9/8 11:00', '2009/9/8 12:00', '2009/9/8 13:00', '2009/9/8 14:00', '2009/9/8 15:00', '2009/9/8 16:00', '2009/9/8 17:00', '2009/9/8 18:00', '2009/9/8 19:00', '2009/9/8 20:00', '2009/9/8 21:00', '2009/9/8 22:00', '2009/9/8 23:00', '2009/9/9 0:00', '2009/9/9 1:00', '2009/9/9 2:00', '2009/9/9 3:00', '2009/9/9 4:00', '2009/9/9 5:00', '2009/9/9 6:00', '2009/9/9 7:00', '2009/9/9 8:00', '2009/9/9 9:00', '2009/9/9 10:00', '2009/9/9 11:00', '2009/9/9 12:00', '2009/9/9 13:00', '2009/9/9 14:00', '2009/9/9 15:00', '2009/9/9 16:00', '2009/9/9 17:00', '2009/9/9 18:00', '2009/9/9 19:00', '2009/9/9 20:00', '2009/9/9 21:00', '2009/9/9 22:00', '2009/9/9 23:00', '2009/9/10 0:00', '2009/9/10 1:00', '2009/9/10 2:00', '2009/9/10 3:00', '2009/9/10 4:00', '2009/9/10 5:00', '2009/9/10 6:00', '2009/9/10 7:00', '2009/9/10 8:00', '2009/9/10 9:00', '2009/9/10 10:00', '2009/9/10 11:00', '2009/9/10 12:00', '2009/9/10 13:00', '2009/9/10 14:00', '2009/9/10 15:00', '2009/9/10 16:00', '2009/9/10 17:00', '2009/9/10 18:00', '2009/9/10 19:00', '2009/9/10 20:00', '2009/9/10 21:00', '2009/9/10 22:00', '2009/9/10 23:00', '2009/9/11 0:00', '2009/9/11 1:00', '2009/9/11 2:00', '2009/9/11 3:00', '2009/9/11 4:00', '2009/9/11 5:00', '2009/9/11 6:00', '2009/9/11 7:00', '2009/9/11 8:00', '2009/9/11 9:00', '2009/9/11 10:00', '2009/9/11 11:00', '2009/9/11 12:00', '2009/9/11 13:00', '2009/9/11 14:00', '2009/9/11 15:00', '2009/9/11 16:00', '2009/9/11 17:00', '2009/9/11 18:00', '2009/9/11 19:00', '2009/9/11 20:00', '2009/9/11 21:00', '2009/9/11 22:00', '2009/9/11 23:00', '2009/9/12 0:00', '2009/9/12 1:00', '2009/9/12 2:00', '2009/9/12 3:00', '2009/9/12 4:00', '2009/9/12 5:00', '2009/9/12 6:00', '2009/9/12 7:00', '2009/9/12 8:00', '2009/9/12 9:00', '2009/9/12 10:00', '2009/9/12 11:00', '2009/9/12 12:00', '2009/9/12 13:00', '2009/9/12 14:00', '2009/9/12 15:00', '2009/9/12 16:00', '2009/9/12 17:00', '2009/9/12 18:00', '2009/9/12 19:00', '2009/9/12 20:00', '2009/9/12 21:00', '2009/9/12 22:00', '2009/9/12 23:00', '2009/9/13 0:00', '2009/9/13 1:00', '2009/9/13 2:00', '2009/9/13 3:00', '2009/9/13 4:00', '2009/9/13 5:00', '2009/9/13 6:00', '2009/9/13 7:00', '2009/9/13 8:00', '2009/9/13 9:00', '2009/9/13 10:00', '2009/9/13 11:00', '2009/9/13 12:00', '2009/9/13 13:00', '2009/9/13 14:00', '2009/9/13 15:00', '2009/9/13 16:00', '2009/9/13 17:00', '2009/9/13 18:00', '2009/9/13 19:00', '2009/9/13 20:00', '2009/9/13 21:00', '2009/9/13 22:00', '2009/9/13 23:00', '2009/9/14 0:00', '2009/9/14 1:00', '2009/9/14 2:00', '2009/9/14 3:00', '2009/9/14 4:00', '2009/9/14 5:00', '2009/9/14 6:00', '2009/9/14 7:00', '2009/9/14 8:00', '2009/9/14 9:00', '2009/9/14 10:00', '2009/9/14 11:00', '2009/9/14 12:00', '2009/9/14 13:00', '2009/9/14 14:00', '2009/9/14 15:00', '2009/9/14 16:00', '2009/9/14 17:00', '2009/9/14 18:00', '2009/9/14 19:00', '2009/9/14 20:00', '2009/9/14 21:00', '2009/9/14 22:00', '2009/9/14 23:00', '2009/9/15 0:00', '2009/9/15 1:00', '2009/9/15 2:00', '2009/9/15 3:00', '2009/9/15 4:00', '2009/9/15 5:00', '2009/9/15 6:00', '2009/9/15 7:00', '2009/9/15 8:00', '2009/9/15 9:00', '2009/9/15 10:00', '2009/9/15 11:00', '2009/9/15 12:00', '2009/9/15 13:00', '2009/9/15 14:00', '2009/9/15 15:00', '2009/9/15 16:00', '2009/9/15 17:00', '2009/9/15 18:00', '2009/9/15 19:00', '2009/9/15 20:00', '2009/9/15 21:00', '2009/9/15 22:00', '2009/9/15 23:00', '2009/9/16 0:00', '2009/9/16 1:00', '2009/9/16 2:00', '2009/9/16 3:00', '2009/9/16 4:00', '2009/9/16 5:00', '2009/9/16 6:00', '2009/9/16 7:00', '2009/9/16 8:00', '2009/9/16 9:00', '2009/9/16 10:00', '2009/9/16 11:00', '2009/9/16 12:00', '2009/9/16 13:00', '2009/9/16 14:00', '2009/9/16 15:00', '2009/9/16 16:00', '2009/9/16 17:00', '2009/9/16 18:00', '2009/9/16 19:00', '2009/9/16 20:00', '2009/9/16 21:00', '2009/9/16 22:00', '2009/9/16 23:00', '2009/9/17 0:00', '2009/9/17 1:00', '2009/9/17 2:00', '2009/9/17 3:00', '2009/9/17 4:00', '2009/9/17 5:00', '2009/9/17 6:00', '2009/9/17 7:00', '2009/9/17 8:00', '2009/9/17 9:00', '2009/9/17 10:00', '2009/9/17 11:00', '2009/9/17 12:00', '2009/9/17 13:00', '2009/9/17 14:00', '2009/9/17 15:00', '2009/9/17 16:00', '2009/9/17 17:00', '2009/9/17 18:00', '2009/9/17 19:00', '2009/9/17 20:00', '2009/9/17 21:00', '2009/9/17 22:00', '2009/9/17 23:00', '2009/9/18 0:00', '2009/9/18 1:00', '2009/9/18 2:00', '2009/9/18 3:00', '2009/9/18 4:00', '2009/9/18 5:00', '2009/9/18 6:00', '2009/9/18 7:00', '2009/9/18 8:00', '2009/9/18 9:00', '2009/9/18 10:00', '2009/9/18 11:00', '2009/9/18 12:00', '2009/9/18 13:00', '2009/9/18 14:00', '2009/9/18 15:00', '2009/9/18 16:00', '2009/9/18 17:00', '2009/9/18 18:00', '2009/9/18 19:00', '2009/9/18 20:00', '2009/9/18 21:00', '2009/9/18 22:00', '2009/9/18 23:00', '2009/9/19 0:00', '2009/9/19 1:00', '2009/9/19 2:00', '2009/9/19 3:00', '2009/9/19 4:00', '2009/9/19 5:00', '2009/9/19 6:00', '2009/9/19 7:00', '2009/9/19 8:00', '2009/9/19 9:00', '2009/9/19 10:00', '2009/9/19 11:00', '2009/9/19 12:00', '2009/9/19 13:00', '2009/9/19 14:00', '2009/9/19 15:00', '2009/9/19 16:00', '2009/9/19 17:00', '2009/9/19 18:00', '2009/9/19 19:00', '2009/9/19 20:00', '2009/9/19 21:00', '2009/9/19 22:00', '2009/9/19 23:00', '2009/9/20 0:00', '2009/9/20 1:00', '2009/9/20 2:00', '2009/9/20 3:00', '2009/9/20 4:00', '2009/9/20 5:00', '2009/9/20 6:00', '2009/9/20 7:00', '2009/9/20 8:00', '2009/9/20 9:00', '2009/9/20 10:00', '2009/9/20 11:00', '2009/9/20 12:00', '2009/9/20 13:00', '2009/9/20 14:00', '2009/9/20 15:00', '2009/9/20 16:00', '2009/9/20 17:00', '2009/9/20 18:00', '2009/9/20 19:00', '2009/9/20 20:00', '2009/9/20 21:00', '2009/9/20 22:00', '2009/9/20 23:00', '2009/9/21 0:00', '2009/9/21 1:00', '2009/9/21 2:00', '2009/9/21 3:00', '2009/9/21 4:00', '2009/9/21 5:00', '2009/9/21 6:00', '2009/9/21 7:00', '2009/9/21 8:00', '2009/9/21 9:00', '2009/9/21 10:00', '2009/9/21 11:00', '2009/9/21 12:00', '2009/9/21 13:00', '2009/9/21 14:00', '2009/9/21 15:00', '2009/9/21 16:00', '2009/9/21 17:00', '2009/9/21 18:00', '2009/9/21 19:00', '2009/9/21 20:00', '2009/9/21 21:00', '2009/9/21 22:00', '2009/9/21 23:00', '2009/9/22 0:00', '2009/9/22 1:00', '2009/9/22 2:00', '2009/9/22 3:00', '2009/9/22 4:00', '2009/9/22 5:00', '2009/9/22 6:00', '2009/9/22 7:00', '2009/9/22 8:00', '2009/9/22 9:00', '2009/9/22 10:00', '2009/9/22 11:00', '2009/9/22 12:00', '2009/9/22 13:00', '2009/9/22 14:00', '2009/9/22 15:00', '2009/9/22 16:00', '2009/9/22 17:00', '2009/9/22 18:00', '2009/9/22 19:00', '2009/9/22 20:00', '2009/9/22 21:00', '2009/9/22 22:00', '2009/9/22 23:00', '2009/9/23 0:00', '2009/9/23 1:00', '2009/9/23 2:00', '2009/9/23 3:00', '2009/9/23 4:00', '2009/9/23 5:00', '2009/9/23 6:00', '2009/9/23 7:00', '2009/9/23 8:00', '2009/9/23 9:00', '2009/9/23 10:00', '2009/9/23 11:00', '2009/9/23 12:00', '2009/9/23 13:00', '2009/9/23 14:00', '2009/9/23 15:00', '2009/9/23 16:00', '2009/9/23 17:00', '2009/9/23 18:00', '2009/9/23 19:00', '2009/9/23 20:00', '2009/9/23 21:00', '2009/9/23 22:00', '2009/9/23 23:00', '2009/9/24 0:00', '2009/9/24 1:00', '2009/9/24 2:00', '2009/9/24 3:00', '2009/9/24 4:00', '2009/9/24 5:00', '2009/9/24 6:00', '2009/9/24 7:00', '2009/9/24 8:00', '2009/9/24 9:00', '2009/9/24 10:00', '2009/9/24 11:00', '2009/9/24 12:00', '2009/9/24 13:00', '2009/9/24 14:00', '2009/9/24 15:00', '2009/9/24 16:00', '2009/9/24 17:00', '2009/9/24 18:00', '2009/9/24 19:00', '2009/9/24 20:00', '2009/9/24 21:00', '2009/9/24 22:00', '2009/9/24 23:00', '2009/9/25 0:00', '2009/9/25 1:00', '2009/9/25 2:00', '2009/9/25 3:00', '2009/9/25 4:00', '2009/9/25 5:00', '2009/9/25 6:00', '2009/9/25 7:00', '2009/9/25 8:00', '2009/9/25 9:00', '2009/9/25 10:00', '2009/9/25 11:00', '2009/9/25 12:00', '2009/9/25 13:00', '2009/9/25 14:00', '2009/9/25 15:00', '2009/9/25 16:00', '2009/9/25 17:00', '2009/9/25 18:00', '2009/9/25 19:00', '2009/9/25 20:00', '2009/9/25 21:00', '2009/9/25 22:00', '2009/9/25 23:00', '2009/9/26 0:00', '2009/9/26 1:00', '2009/9/26 2:00', '2009/9/26 3:00', '2009/9/26 4:00', '2009/9/26 5:00', '2009/9/26 6:00', '2009/9/26 7:00', '2009/9/26 8:00', '2009/9/26 9:00', '2009/9/26 10:00', '2009/9/26 11:00', '2009/9/26 12:00', '2009/9/26 13:00', '2009/9/26 14:00', '2009/9/26 15:00', '2009/9/26 16:00', '2009/9/26 17:00', '2009/9/26 18:00', '2009/9/26 19:00', '2009/9/26 20:00', '2009/9/26 21:00', '2009/9/26 22:00', '2009/9/26 23:00', '2009/9/27 0:00', '2009/9/27 1:00', '2009/9/27 2:00', '2009/9/27 3:00', '2009/9/27 4:00', '2009/9/27 5:00', '2009/9/27 6:00', '2009/9/27 7:00', '2009/9/27 8:00', '2009/9/27 9:00', '2009/9/27 10:00', '2009/9/27 11:00', '2009/9/27 12:00', '2009/9/27 13:00', '2009/9/27 14:00', '2009/9/27 15:00', '2009/9/27 16:00', '2009/9/27 17:00', '2009/9/27 18:00', '2009/9/27 19:00', '2009/9/27 20:00', '2009/9/27 21:00', '2009/9/27 22:00', '2009/9/27 23:00', '2009/9/28 0:00', '2009/9/28 1:00', '2009/9/28 2:00', '2009/9/28 3:00', '2009/9/28 4:00', '2009/9/28 5:00', '2009/9/28 6:00', '2009/9/28 7:00', '2009/9/28 8:00', '2009/9/28 9:00', '2009/9/28 10:00', '2009/9/28 11:00', '2009/9/28 12:00', '2009/9/28 13:00', '2009/9/28 14:00', '2009/9/28 15:00', '2009/9/28 16:00', '2009/9/28 17:00', '2009/9/28 18:00', '2009/9/28 19:00', '2009/9/28 20:00', '2009/9/28 21:00', '2009/9/28 22:00', '2009/9/28 23:00', '2009/9/29 0:00', '2009/9/29 1:00', '2009/9/29 2:00', '2009/9/29 3:00', '2009/9/29 4:00', '2009/9/29 5:00', '2009/9/29 6:00', '2009/9/29 7:00', '2009/9/29 8:00', '2009/9/29 9:00', '2009/9/29 10:00', '2009/9/29 11:00', '2009/9/29 12:00', '2009/9/29 13:00', '2009/9/29 14:00', '2009/9/29 15:00', '2009/9/29 16:00', '2009/9/29 17:00', '2009/9/29 18:00', '2009/9/29 19:00', '2009/9/29 20:00', '2009/9/29 21:00', '2009/9/29 22:00', '2009/9/29 23:00', '2009/9/30 0:00', '2009/9/30 1:00', '2009/9/30 2:00', '2009/9/30 3:00', '2009/9/30 4:00', '2009/9/30 5:00', '2009/9/30 6:00', '2009/9/30 7:00', '2009/9/30 8:00', '2009/9/30 9:00', '2009/9/30 10:00', '2009/9/30 11:00', '2009/9/30 12:00', '2009/9/30 13:00', '2009/9/30 14:00', '2009/9/30 15:00', '2009/9/30 16:00', '2009/9/30 17:00', '2009/9/30 18:00', '2009/9/30 19:00', '2009/9/30 20:00', '2009/9/30 21:00', '2009/9/30 22:00', '2009/9/30 23:00', + '2009/10/1 0:00', '2009/10/1 1:00', '2009/10/1 2:00', '2009/10/1 3:00', '2009/10/1 4:00', '2009/10/1 5:00', '2009/10/1 6:00', '2009/10/1 7:00', '2009/10/1 8:00', '2009/10/1 9:00', '2009/10/1 10:00', '2009/10/1 11:00', '2009/10/1 12:00', '2009/10/1 13:00', '2009/10/1 14:00', '2009/10/1 15:00', '2009/10/1 16:00', '2009/10/1 17:00', '2009/10/1 18:00', '2009/10/1 19:00', '2009/10/1 20:00', '2009/10/1 21:00', '2009/10/1 22:00', '2009/10/1 23:00', '2009/10/2 0:00', '2009/10/2 1:00', '2009/10/2 2:00', '2009/10/2 3:00', '2009/10/2 4:00', '2009/10/2 5:00', '2009/10/2 6:00', '2009/10/2 7:00', '2009/10/2 8:00', '2009/10/2 9:00', '2009/10/2 10:00', '2009/10/2 11:00', '2009/10/2 12:00', '2009/10/2 13:00', '2009/10/2 14:00', '2009/10/2 15:00', '2009/10/2 16:00', '2009/10/2 17:00', '2009/10/2 18:00', '2009/10/2 19:00', '2009/10/2 20:00', '2009/10/2 21:00', '2009/10/2 22:00', '2009/10/2 23:00', '2009/10/3 0:00', '2009/10/3 1:00', '2009/10/3 2:00', '2009/10/3 3:00', '2009/10/3 4:00', '2009/10/3 5:00', '2009/10/3 6:00', '2009/10/3 7:00', '2009/10/3 8:00', '2009/10/3 9:00', '2009/10/3 10:00', '2009/10/3 11:00', '2009/10/3 12:00', '2009/10/3 13:00', '2009/10/3 14:00', '2009/10/3 15:00', '2009/10/3 16:00', '2009/10/3 17:00', '2009/10/3 18:00', '2009/10/3 19:00', '2009/10/3 20:00', '2009/10/3 21:00', '2009/10/3 22:00', '2009/10/3 23:00', '2009/10/4 0:00', '2009/10/4 1:00', '2009/10/4 2:00', '2009/10/4 3:00', '2009/10/4 4:00', '2009/10/4 5:00', '2009/10/4 6:00', '2009/10/4 7:00', '2009/10/4 8:00', '2009/10/4 9:00', '2009/10/4 10:00', '2009/10/4 11:00', '2009/10/4 12:00', '2009/10/4 13:00', '2009/10/4 14:00', '2009/10/4 15:00', '2009/10/4 16:00', '2009/10/4 17:00', '2009/10/4 18:00', '2009/10/4 19:00', '2009/10/4 20:00', '2009/10/4 21:00', '2009/10/4 22:00', '2009/10/4 23:00', '2009/10/5 0:00', '2009/10/5 1:00', '2009/10/5 2:00', '2009/10/5 3:00', '2009/10/5 4:00', '2009/10/5 5:00', '2009/10/5 6:00', '2009/10/5 7:00', '2009/10/5 8:00', '2009/10/5 9:00', '2009/10/5 10:00', '2009/10/5 11:00', '2009/10/5 12:00', '2009/10/5 13:00', '2009/10/5 14:00', '2009/10/5 15:00', '2009/10/5 16:00', '2009/10/5 17:00', '2009/10/5 18:00', '2009/10/5 19:00', '2009/10/5 20:00', '2009/10/5 21:00', '2009/10/5 22:00', '2009/10/5 23:00', '2009/10/6 0:00', '2009/10/6 1:00', '2009/10/6 2:00', '2009/10/6 3:00', '2009/10/6 4:00', '2009/10/6 5:00', '2009/10/6 6:00', '2009/10/6 7:00', '2009/10/6 8:00', '2009/10/6 9:00', '2009/10/6 10:00', '2009/10/6 11:00', '2009/10/6 12:00', '2009/10/6 13:00', '2009/10/6 14:00', '2009/10/6 15:00', '2009/10/6 16:00', '2009/10/6 17:00', '2009/10/6 18:00', '2009/10/6 19:00', '2009/10/6 20:00', '2009/10/6 21:00', '2009/10/6 22:00', '2009/10/6 23:00', '2009/10/7 0:00', '2009/10/7 1:00', '2009/10/7 2:00', '2009/10/7 3:00', '2009/10/7 4:00', '2009/10/7 5:00', '2009/10/7 6:00', '2009/10/7 7:00', '2009/10/7 8:00', '2009/10/7 9:00', '2009/10/7 10:00', '2009/10/7 11:00', '2009/10/7 12:00', '2009/10/7 13:00', '2009/10/7 14:00', '2009/10/7 15:00', '2009/10/7 16:00', '2009/10/7 17:00', '2009/10/7 18:00', '2009/10/7 19:00', '2009/10/7 20:00', '2009/10/7 21:00', '2009/10/7 22:00', '2009/10/7 23:00', '2009/10/8 0:00', '2009/10/8 1:00', '2009/10/8 2:00', '2009/10/8 3:00', '2009/10/8 4:00', '2009/10/8 5:00', '2009/10/8 6:00', '2009/10/8 7:00', '2009/10/8 8:00', '2009/10/8 9:00', '2009/10/8 10:00', '2009/10/8 11:00', '2009/10/8 12:00', '2009/10/8 13:00', '2009/10/8 14:00', '2009/10/8 15:00', '2009/10/8 16:00', '2009/10/8 17:00', '2009/10/8 18:00', '2009/10/8 19:00', '2009/10/8 20:00', '2009/10/8 21:00', '2009/10/8 22:00', '2009/10/8 23:00', '2009/10/9 0:00', '2009/10/9 1:00', '2009/10/9 2:00', '2009/10/9 3:00', '2009/10/9 4:00', '2009/10/9 5:00', '2009/10/9 6:00', '2009/10/9 7:00', '2009/10/9 8:00', '2009/10/9 9:00', '2009/10/9 10:00', '2009/10/9 11:00', '2009/10/9 12:00', '2009/10/9 13:00', '2009/10/9 14:00', '2009/10/9 15:00', '2009/10/9 16:00', '2009/10/9 17:00', '2009/10/9 18:00', '2009/10/9 19:00', '2009/10/9 20:00', '2009/10/9 21:00', '2009/10/9 22:00', '2009/10/9 23:00', '2009/10/10 0:00', '2009/10/10 1:00', '2009/10/10 2:00', '2009/10/10 3:00', '2009/10/10 4:00', '2009/10/10 5:00', '2009/10/10 6:00', '2009/10/10 7:00', '2009/10/10 8:00', '2009/10/10 9:00', '2009/10/10 10:00', '2009/10/10 11:00', '2009/10/10 12:00', '2009/10/10 13:00', '2009/10/10 14:00', '2009/10/10 15:00', '2009/10/10 16:00', '2009/10/10 17:00', '2009/10/10 18:00', '2009/10/10 19:00', '2009/10/10 20:00', '2009/10/10 21:00', '2009/10/10 22:00', '2009/10/10 23:00', '2009/10/11 0:00', '2009/10/11 1:00', '2009/10/11 2:00', '2009/10/11 3:00', '2009/10/11 4:00', '2009/10/11 5:00', '2009/10/11 6:00', '2009/10/11 7:00', '2009/10/11 8:00', '2009/10/11 9:00', '2009/10/11 10:00', '2009/10/11 11:00', '2009/10/11 12:00', '2009/10/11 13:00', '2009/10/11 14:00', '2009/10/11 15:00', '2009/10/11 16:00', '2009/10/11 17:00', '2009/10/11 18:00', '2009/10/11 19:00', '2009/10/11 20:00', '2009/10/11 21:00', '2009/10/11 22:00', '2009/10/11 23:00', '2009/10/12 0:00', '2009/10/12 1:00', '2009/10/12 2:00', '2009/10/12 3:00', '2009/10/12 4:00', '2009/10/12 5:00', '2009/10/12 6:00', '2009/10/12 7:00', '2009/10/12 8:00', '2009/10/12 9:00', '2009/10/12 10:00', '2009/10/12 11:00', '2009/10/12 12:00', '2009/10/12 13:00', '2009/10/12 14:00', '2009/10/12 15:00', '2009/10/12 16:00', '2009/10/12 17:00', '2009/10/12 18:00', '2009/10/12 19:00', '2009/10/12 20:00', '2009/10/12 21:00', '2009/10/12 22:00', '2009/10/12 23:00', '2009/10/13 0:00', '2009/10/13 1:00', '2009/10/13 2:00', '2009/10/13 3:00', '2009/10/13 4:00', '2009/10/13 5:00', '2009/10/13 6:00', '2009/10/13 7:00', '2009/10/13 8:00', '2009/10/13 9:00', '2009/10/13 10:00', '2009/10/13 11:00', '2009/10/13 12:00', '2009/10/13 13:00', '2009/10/13 14:00', '2009/10/13 15:00', '2009/10/13 16:00', '2009/10/13 17:00', '2009/10/13 18:00', '2009/10/13 19:00', '2009/10/13 20:00', '2009/10/13 21:00', '2009/10/13 22:00', '2009/10/13 23:00', '2009/10/14 0:00', '2009/10/14 1:00', '2009/10/14 2:00', '2009/10/14 3:00', '2009/10/14 4:00', '2009/10/14 5:00', '2009/10/14 6:00', '2009/10/14 7:00', '2009/10/14 8:00', '2009/10/14 9:00', '2009/10/14 10:00', '2009/10/14 11:00', '2009/10/14 12:00', '2009/10/14 13:00', '2009/10/14 14:00', '2009/10/14 15:00', '2009/10/14 16:00', '2009/10/14 17:00', '2009/10/14 18:00', '2009/10/14 19:00', '2009/10/14 20:00', '2009/10/14 21:00', '2009/10/14 22:00', '2009/10/14 23:00', '2009/10/15 0:00', '2009/10/15 1:00', '2009/10/15 2:00', '2009/10/15 3:00', '2009/10/15 4:00', '2009/10/15 5:00', '2009/10/15 6:00', '2009/10/15 7:00', '2009/10/15 8:00', '2009/10/15 9:00', '2009/10/15 10:00', '2009/10/15 11:00', '2009/10/15 12:00', '2009/10/15 13:00', '2009/10/15 14:00', '2009/10/15 15:00', '2009/10/15 16:00', '2009/10/15 17:00', '2009/10/15 18:00', '2009/10/15 19:00', '2009/10/15 20:00', '2009/10/15 21:00', '2009/10/15 22:00', '2009/10/15 23:00', '2009/10/16 0:00', '2009/10/16 1:00', '2009/10/16 2:00', '2009/10/16 3:00', '2009/10/16 4:00', '2009/10/16 5:00', '2009/10/16 6:00', '2009/10/16 7:00', '2009/10/16 8:00', '2009/10/16 9:00', '2009/10/16 10:00', '2009/10/16 11:00', '2009/10/16 12:00', '2009/10/16 13:00', '2009/10/16 14:00', '2009/10/16 15:00', '2009/10/16 16:00', '2009/10/16 17:00', '2009/10/16 18:00', '2009/10/16 19:00', '2009/10/16 20:00', '2009/10/16 21:00', '2009/10/16 22:00', '2009/10/16 23:00', '2009/10/17 0:00', '2009/10/17 1:00', '2009/10/17 2:00', '2009/10/17 3:00', '2009/10/17 4:00', '2009/10/17 5:00', '2009/10/17 6:00', '2009/10/17 7:00', '2009/10/17 8:00', '2009/10/17 9:00', '2009/10/17 10:00', '2009/10/17 11:00', '2009/10/17 12:00', '2009/10/17 13:00', '2009/10/17 14:00', '2009/10/17 15:00', '2009/10/17 16:00', '2009/10/17 17:00', '2009/10/17 18:00', '2009/10/17 19:00', '2009/10/17 20:00', '2009/10/17 21:00', '2009/10/17 22:00', '2009/10/17 23:00', '2009/10/18 0:00', '2009/10/18 1:00', '2009/10/18 2:00', '2009/10/18 3:00', '2009/10/18 4:00', '2009/10/18 5:00', '2009/10/18 6:00', '2009/10/18 7:00', '2009/10/18 8:00' + ] + } + ], + yAxis : [ + { + name : '流量(m^3/s)', + type : 'value', + max : 500 + }, + { + name : '降雨量(mm)', + type : 'value', + axisLabel : { + formatter: function(v){ + return - v; + } + } + } + ], + series : [ + { + name:'流量', + type:'line', + itemStyle: {normal: {areaStyle: {type: 'default'}}}, + data:[ + 0.97,0.96,0.96,0.95,0.95,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.93,0.92,0.91,0.9,0.89,0.88,0.87,0.87,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.87,0.88,0.9,0.93,0.96,0.99,1.03,1.06,1.1,1.14,1.17,1.2,1.23,1.26,1.29,1.33,1.36,1.4,1.43,1.45,1.48,1.49,1.51,1.51,1.5,1.49,1.47,1.44,1.41,1.37,1.34,1.3,1.27,1.24,1.22,1.2,1.19,1.18,1.16,1.15,1.14,1.13,1.12,1.11,1.11,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.09,1.09,1.08,1.07,1.06,1.05,1.04,1.03,1.03,1.02,1.01,1.01,1,0.99,0.98,0.97,0.96,0.96,0.95,0.95,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.93,0.92,0.91,0.9,0.89,0.88,0.87,0.87,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.85,0.84,0.83,0.82,0.81,0.8,0.8,0.79,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.77,0.75,0.73,0.71,0.68,0.65,0.63,0.61,0.59,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.57,0.57,0.57,0.56,0.55,0.55,0.54,0.54,0.53,0.52,0.52,0.51,0.51,0.5,0.5,0.49,0.48,0.48,0.47,0.47,0.47,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.52,0.67,0.9,1.19,1.52,1.87,2.22,2.55,2.84,3.07,3.22,3.28,3.28,3.28,3.28,3.28,3.28,3.28,3.28,3.28,3.28,3.28,3.28,3.28,3.24,3.13,2.97,2.77,2.54,2.3,2.05,1.82,1.62,1.46,1.35,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.3,1.26,1.21,1.14,1.06,0.97,0.89,0.81,0.74,0.69,0.65,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.63,0.63,0.62,0.62,0.61,0.6,0.59,0.59,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.59,0.61,0.63,0.65,0.68,0.71,0.73,0.75,0.77,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.77,0.75,0.73,0.71,0.68,0.65,0.63,0.61,0.59,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.59,0.59,0.6,0.61,0.62,0.62,0.63,0.63,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.65,0.66,0.68,0.69,0.71,0.73,0.74,0.76,0.77,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.79,0.81,0.82,0.84,0.86,0.88,0.9,0.92,0.93,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.93,0.92,0.91,0.9,0.89,0.88,0.87,0.87,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.85,0.84,0.82,0.8,0.78,0.76,0.75,0.73,0.72,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.72,0.73,0.74,0.76,0.78,0.79,0.82,0.84,0.86,0.89,0.91,0.94,0.97,1,1.02,1.05,1.08,1.11,1.14,1.17,1.19,1.22,1.25,1.27,1.29,1.31,1.33,1.35,1.36,1.38,1.39,1.39,1.4,1.4,1.4,1.39,1.37,1.35,1.32,1.29,1.26,1.22,1.18,1.14,1.1,1.05,1.01,0.97,0.93,0.89,0.85,0.82,0.78,0.76,0.74,0.72,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.72,0.73,0.74,0.75,0.77,0.78,0.8,0.82,0.84,0.87,0.89,0.92,0.94,0.97,0.99,1.02,1.05,1.08,1.1,1.13,1.16,1.18,1.21,1.23,1.26,1.28,1.3,1.32,1.34,1.35,1.37,1.38,1.39,1.4,1.41,1.41,1.42,1.42,1.43,1.43,1.43,1.44,1.44,1.44,1.44,1.45,1.45,1.45,1.46,1.46,1.46,1.47,1.47,1.48,1.48,1.49,1.5,1.51,1.54,1.62,1.73,1.88,2.05,2.24,2.45,2.67,2.89,3.11,3.31,3.51,3.69,3.86,4.03,4.18,4.33,4.48,4.62,4.76,4.89,5.02,5.16,5.29,5.43,5.57,5.71,5.86,6.02,6.18,6.36,6.54,6.73,6.93,7.15,7.38,7.62,7.88,8.16,8.46,8.77,9.11,9.46,9.84,10.24,10.67,11.12,11.6,12.3,13.66,16,38.43,82.21,146.6,218.7,226,225.23,223.08,219.78,212,199.82,184.6,168,151.65,137.21,126.31,119.94,115.52,112.06,108.92,105.44,101,94.56,86.36,77.67,69.76,63.9,60.38,57.41,54.84,52.57,50.56,48.71,46.97,45.25,43.48,41.6,39.5,37.19,34.81,32.46,30.27,28.36,26.85,25.86,25.5,25.5,25.5,25.5,25.5,25.5,25.5,25.5,25.5,25.5,25.5,25.5,25.5,25.27,24.65,23.7,22.52,21.17,19.75,18.33,16.98,15.8,14.85,14.23,14,14.02,14.08,14.17,14.29,14.44,14.61,14.8,15.01,15.23,15.47,15.71,15.95,16.19,16.43,16.67,16.89,17.1,17.29,17.46,17.61,17.73,17.82,17.88,17.9,17.63,16.88,15.75,14.33,12.71,10.98,9.23,7.56,6.05,4.81,3.92,3.47,3.28,3.1,2.93,2.76,2.61,2.46,2.32,2.19,2.07,1.96,1.85,1.75,1.66,1.58,1.51,1.44,1.39,1.34,1.29,1.26,1.23,1.22,1.2,1.2,1.2,1.2,1.2,1.2,1.21,1.21,1.21,1.21,1.22,1.22,1.22,1.23,1.23,1.23,1.24,1.24,1.25,1.25,1.25,1.26,1.26,1.27,1.27,1.27,1.28,1.28,1.28,1.29,1.29,1.29,1.29,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.29,1.29,1.29,1.29,1.28,1.28,1.28,1.27,1.27,1.26,1.25,1.25,1.24,1.23,1.23,1.22,1.21,1.2,1.16,1.06,0.95,0.83,0.74,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.69,0.69,0.69,0.69,0.69,0.69,0.69,0.69,0.68,0.68,0.68,0.68,0.68,0.68,0.67,0.67,0.67,0.67,0.67,0.67,0.67,0.66,0.66,0.66,0.66,0.66,0.66,0.66,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.65,0.66,0.68,0.69,0.71,0.73,0.74,0.76,0.77,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.8,0.86,0.95,1.08,1.25,1.46,1.7,1.97,2.28,2.63,3.01,3.42,3.87,4.35,4.86,5.4,5.98,6.59,7.92,10.49,14.04,18.31,23.04,27.98,32.87,37.45,41.46,44.64,46.74,47.5,46.86,45.16,42.77,40.04,37.33,35,32.74,30.21,27.7,25.5,23.9,23.2,23.06,22.94,22.84,22.77,22.72,22.7,22.8,23.23,23.95,24.91,26.04,27.3,28.76,30.7,33.39,37.12,42.15,48.77,65.22,252.1,257,237.32,221.19,212,208.67,206.89,205.2,202.15,189.82,172,165.3,160.49,156.8,153.44,149.62,144.6,138.27,131,123.11,114.9,106.69,98.79,91.5,85.13,80,75.53,71.03,66.65,62.54,58.85,55.73,53.31,51.75,51.2,56.53,68.25,80,91.01,102.03,109,112.37,115.29,117.68,119.48,120.61,121,119.45,115.57,110.52,105.47,101.58,100,99.97,99.94,99.92,99.9,99.88,99.86,99.85,99.84,99.83,99.82,99.81,99.81,99.8,99.8,99.8,122.15,163.65,186,182.96,175.15,164.56,153.18,143,136,131.37,126.98,122.81,118.85,115.09,111.52,108.13,104.9,101.83,98.9,96.11,93.44,90.87,88.41,86.04,83.74,81.51,79.33,77.2,75.1,73.02,70.95,68.88,66.8,64.87,63.14,61.4,59.53,57.67,56,54.6,53.36,52.2,51.05,49.85,48.5,46.87,44.92,42.74,40.42,38.04,35.69,33.46,31.44,29.72,28.38,27.51,27.2,27.2,27.2,27.2,27.2,27.2,27.2,27.2,27.2,27.2,27.2,27.2,27.2,27.14,26.97,26.7,26.35,25.95,25.49,25.02,24.53,24.04,23.58,23.16,22.8,22.46,22.11,21.75,21.39,21.03,20.69,20.36,20.05,19.78,19.54,19.35,19.2,19.09,19,18.92,18.85,18.79,18.74,18.68,18.62,18.56,18.49,18.4,18.3,18.17,18.02,17.83,17.63,17.41,17.18,16.93,16.68,16.43,16.18,15.93,15.7,15.47,15.22,14.97,14.71,14.45,14.18,13.93,13.68,13.44,13.21,13,12.8,12.62,12.46,12.31,12.16,12.03,11.89,11.76,11.62,11.48,11.33,11.17,11,10.81,10.59,10.36,10.12,9.86,9.61,9.36,9.12,8.89,8.68,8.5,8.35,8.21,8.08,7.94,7.81,7.68,7.56,7.46,7.36,7.29,7.23,7.19,7.18,7.51,8.42,9.81,11.58,13.63,15.86,18.16,20.44,22.58,24.49,26.06,27.2,28.08,28.95,29.81,30.65,31.48,32.28,33.07,33.82,34.55,35.25,35.92,36.56,37.15,37.71,38.23,38.7,39.13,39.5,39.83,40.1,40.31,40.47,40.57,40.6,40.49,40.16,39.64,38.94,38.09,37.1,36,34.79,33.51,32.17,30.79,29.39,27.99,26.6,25.25,23.96,22.75,21.63,20.63,19.76,19.04,18.49,18.14,18,17.97,17.95,17.94,17.92,17.91,17.9,17.89,17.88,17.87,17.85,17.83,17.8,17.7,17.46,17.13,16.7,16.21,15.68,15.13,14.57,14.04,13.56,13.14,12.8,12.52,12.27,12.02,11.79,11.57,11.37,11.16,10.97,10.78,10.59,10.39,10.2,10.01,9.81,9.63,9.44,9.26,9.08,8.9,8.73,8.56,8.39,8.22,8.06,7.9,7.73,7.57,7.41,7.25,7.09,6.94,6.79,6.65,6.52,6.4,6.28,6.17,6.08,5.98,5.9,5.81,5.73,5.65,5.57,5.49,5.41,5.32,5.23,5.14,5.04,4.94,4.84,4.74,4.63,4.53,4.43,4.33,4.23,4.13,4.03,3.93,3.81,3.69,3.57,3.45,3.33,3.22,3.12,3.04,2.98,2.93,2.92,2.92,2.92,2.92,2.92,2.92,2.92,2.92,2.92,2.92,2.92,2.92,2.92,2.9,2.86,2.8,2.71,2.62,2.52,2.42,2.33,2.24,2.18,2.14,2.12,2.12,2.12,2.12,2.12,2.12,2.12,2.12,2.12,2.12,2.12,2.12,2.12,2.1,2.06,2,1.91,1.82,1.71,1.61,1.5,1.4,1.32,1.25,1.2,1.16,1.13,1.1,1.06,1.03,1,0.97,0.93,0.9,0.87,0.85,0.82,0.79,0.77,0.74,0.72,0.69,0.67,0.65,0.63,0.61,0.59,0.58,0.56,0.54,0.53,0.52,0.51,0.5,0.49,0.48,0.48,0.47,0.47,0.46,0.46,0.47,0.48,0.5,0.53,0.56,0.59,0.62,0.64,0.67,0.69,0.7,0.71,0.71,0.71,0.71,0.7,0.7,0.7,0.69,0.69,0.69,0.68,0.68,0.67,0.67,0.67,0.66,0.66,0.65,0.65,0.65,0.65,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.65,0.65,0.65,0.66,0.66,0.67,0.68,0.69,0.69,0.7,0.71,0.73,0.74,0.75,0.76,0.78,0.8,0.81,0.83,0.85,0.87,0.89,0.92,0.94,0.97,0.99,1.02,1.05,1.08,1.11,1.15,1.18,1.32,1.66,2.21,2.97,3.94,5.11,6.5,8.1,9.9,11.92,14.15,16.6,22.3,22.8,24.48,30.38,35.74,42.4,57.14,94.04,112.9,123.4,130.4,130,119.4,120.7,116.8,118.1,119.4,124.8,143.5,204,294,319.2,328.4,365,350.8,347.6,347.6,325,331.6,319.2,308,308,308,308,296.8,300,281,278.4,270.6,271,253.6,233.5,219.2,207.8,205.9,204,189.6,178.8,173.4,160,154.4,146,145,140.5,130.4,126.2,116.8,112.9,106.5,101.6,98.51,82.67,67.3,80.05,76.12,72.3,71.02,69.78,67.3,67.3,68.54,57.6,71.02,66.06,59.12,57.14,55.16,55.16,52.19,52.19,51.2,48.56,44.16,43,45.92,49.44,44.16,36.48,35.74,35,32.36,37.22,32.36,32.36,32.36,33.68,32.36,31.7,35.74,29.72,32.36,30.38,29.72,28.4,28.4,28.4,27.28,25.6,25.04,23.92,22.3,21.8,21.8,21.8,22.8,21.8,25.6,22.8,22.8,17.8,16.04,16.04,16.04,16.04,16.04,16.04,16.04,16.04,16.04,16.04,15.02,14,14.03,14.11,14.25,14.45,14.72,15.06,15.46,15.95,16.51,17.15,17.87,18.69,19.59,20.59,21.69,22.88,24.18,25.59,27.1,28.73,30.48,32.34,34.33,36.44,38.69,41.06,43.57,46.22,49.01,51.95,55.04,58.27,61.66,65.21,68.92,72.8,88.09,104.9,105.7,110.3,111.6,110.3,106.5,105.7,103.3,100,97.02,98.8,91.07,83.98,88.09,81.36,78.74,77.43,77.43,73.5,74.81,72.63,68.58,66.4,68.54,69.78,67.3,64.82,61.1,59.12,56.15,53.18,50.32,49.44,44.16,36.5,42.4,37.96,37.22,33.68,36.48,35.74,35,35,37.22,37.22,39.44,32.6,34.54,36.48,35.74,34.34,33.68,33.02,31.04,29.72,29.72,29.72,26.16,25.6,29.72,18.3,22.3,21.3,21.8,21.8,20.3,20.8,25.04,25.04,25.6,25.6,25.04,25.6,25.04,25.6,23.92,25.04,21.3,21.8,22.3,21.8,20.8,16.1,20.3,18.3,13.22,19.3,19.3,18.3,14.4,13.86,13.36,12.9,12.48,12.1,11.75,11.43,11.15,10.9,10.67,10.48,10.31,10.16,10.04,9.93,9.85,9.78,9.73,9.69,9.67,9.65,9.65,12.08,8.67,11.7,11.38,10.65,9.84,9.32,9.07,8.85,8.66,8.49,8.35,8.22,8.1,7.98,7.86,7.74,7.61,7.47,7.31,7.14,6.96,6.78,6.58,6.39,6.19,5.99,5.78,5.58,5.39,5.2,5.01,4.83,4.67,4.51,4.37,4.24,4.12,4.02,3.95,3.89,3.85,3.84,4.41,5.77,7.39,8.75,9.32,9.18,9,8.94,8.88,8.83,8.78,8.73,8.68,8.64,8.6,8.56,8.53,8.5,8.47,8.45,8.42,8.4,8.39,8.37,8.36,8.35,8.35,8.34,8.34,8.67,9.65,9.62,9.53,9.4,9.21,8.98,8.7,8.4,8.06,7.69,7.3,6.89,6.47,6.03,5.59,5.14,4.7,4.26,3.83,3.42,3.02,2.65,2.3,1.98,1.7,1.45,1.25,1.09,0.99,0.94,0.92,0.91,0.89,0.87,0.85,0.84,0.82,0.81,0.79,0.78,0.77,0.75,0.74,0.73,0.72,0.71,0.7,0.69,0.68,0.67,0.66,0.65,0.64,0.64,0.63,0.63,0.62,0.62,0.61,0.61,0.61,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.61,0.61,0.61,0.61,0.61,0.61,0.62,0.62,0.62,0.62,0.63,0.63,0.63,0.63,0.63,0.64,0.64,0.64,0.64,0.64,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.64,0.63,0.62,0.6,0.59,0.57,0.55,0.54,0.53,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.51,0.51,0.51,0.5,0.5,0.49,0.48,0.47,0.47,0.46,0.45,0.45,0.44,0.43,0.42,0.42,0.41,0.41,0.41,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.41,0.42,0.43,0.44,0.46,0.48,0.5,0.53,0.55,0.58,0.61,0.64,0.67,0.7,0.73,0.77,0.8,0.83,0.87,0.9,0.93,0.96,0.99,1.02,1.05,1.08,1.1,1.12,1.14,1.16,1.17,1.18,1.19,1.2,1.2,1.2,1.19,1.17,1.15,1.12,1.09,1.06,1.02,0.98,0.94,0.9,0.86,0.82,0.78,0.74,0.7,0.66,0.63,0.6,0.57,0.55,0.53,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.51,0.51,0.5,0.5,0.49,0.49,0.48,0.47,0.47,0.47,0.46,0.46,0.45,0.45,0.45,0.44,0.44,0.44,0.43,0.43,0.43,0.42,0.42,0.42,0.41,0.41,0.41,0.41,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.41,0.41,0.41,0.41,0.41,0.41,0.41,0.41,0.41,0.41,0.41,0.41,0.41,0.41,0.41,0.42,0.42,0.42,0.42,0.42,0.42,0.42,0.42,0.42,0.43,0.43,0.43,0.43,0.43,0.43,0.44,0.44,0.44,0.44,0.44,0.44,0.45,0.45,0.45 + ] + }, + { + name:'降雨量', + type:'line', + yAxisIndex:1, + itemStyle: {normal: {areaStyle: {type: 'default'}}}, + data: (function(){ + var oriData = [ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005,0.017,0.017,0.017,0.017,0.011,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.021,0.026,0.03,0.036,0.036,0.195,0.221,0.019,0.013,0.017,0.03,0.03,0.03,0.046,0.045,0.038,0.084,0.045,0.045,0.037,0.034,0.035,0.036,0.044,0.052,0.048,0.109,0.033,0.029,0.04,0.042,0.042,0.042,0.073,0.076,0.062,0.066,0.066,0.075,0.096,0.128,0.121,0.128,0.14,0.226,0.143,0.097,0.018,0,0,0,0,0,0.018,0.047,0.054,0.054,0.054,0.036,0.185,0.009,0.038,0.061,0.077,0.091,0.126,0.69,0.182,0.349,0.231,0.146,0.128,0.167,0.1,0.075,0.071,0.071,0.117,0.01,0.002,0.002,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005,0.026,0.038,0.038,0.038,0.076,0.086,0.109,0.213,0.276,0.288,0.297,0.642,1.799,1.236,2.138,0.921,0.497,0.685,0.828,0.41,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.018,0.024,0.024,0.024,0.024,0.006,0.003,0.046,0.046,0.046,0.046,0.043,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.204,0.303,1.028,1.328,1.524,1.41,1.362,1.292,1.191,0.529,0.501,0.944,1.81,2.899,0.859,0.126,0.087,0.047,0,0,0,0,0.011,0.028,0.028,0.028,0.028,0.017,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.099,0.159,0.297,0.309,0.309,0.614,0.818,1.436,1.195,0.553,0.542,0.955,0.898,0.466,0.386,0.556,0.388,0.221,0.192,0.192,0.187,0.166,0.18,0.302,0.158,0.009,0.009,0.009,0.009,0.009,0.007,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.004,0.032,0.032,0.032,0.032,0.082,0.149,0.204,0.247,0.262,0.49,0.51,0.533,0.746,0.847,2.393,1.188,1.114,0.475,0.043,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.017,0.017,0.021,0.042,0.079,0.111,0.126,0.122,0.133,0.846,0.102,0.077,0.067,0.056,0.005,0,0,0,0,0,0,0,0,0,0,0,0,0,0.011,0.017,0.017,0.017,0.017,0.006,0,0,0,0,0,0.01,0.03,0.054,0.067,0.07,0.25,0.251,0.494,0.065,0.054,0.054,0.064,0.084,0.077,0.101,0.132,0.248,0.069,0.117,0.115,0.087,0.326,0.036,0.009,0.009,0.009,0.009,0.009,0.004,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.02,0.039,0.04,0.04,0.04,0.229,0.079,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.023,0.069,0.082,0.082,0.082,0.503,0.774,0.038,0.012,0.012,0.012,0.016,0.02,0.028,0.051,0.06,0.064,0.19,0.15,0.164,0.139,0.13,0.085,0.031,0.023,0.022,0.007,0.005,0.005,0.001,0,0.02,0.048,0.048,0.053,0.056,0.036,0.008,0.008,0.004,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.013,0.017,0.036,0.068,0.095,0.233,0.272,0.377,0.722,1.494,3.756,0.954,0.439,0.442,0.462,0.373,0.249,0.214,0.1,0.044,0.037,0.023,0.002,0,0,0,0,0,0,0.02,0.024,0.024,0.024,0.024,0.004,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.008,0.017,0.017,0.045,0.186,0.308,0.241,0.241,0.893,4.067,4.494,5.015,3.494,2.057,1.411,0.718,0.407,0.313,0.339,1.537,1.105,0.218,0.136,0.03,0.005,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.037,0.448,1.2,1.309,1.309,1.425,1.223,0.471,0.767,0.423,0.273,0.412,0.646,0.481,0.239,0.131,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.044,0.15,0.223,0.388,0.513,0.883,2.828,4.786,5.959,4.95,6.434,6.319,3.35,2.806,4.204,1.395,1.015,1.015,0.836,0.74,0.72,0.615,0.477,0.192,0.046,0.007,0.007,0.007,0.007,0.007,0.007,0.007,0.008,0.005,0.005,0.005,0.005,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.001,0.012,0.012,0.012,0.012,0.011,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.002,0.012,0.028,0.028,0.028,0.138,0.092,0.082,0.082,0.096,0.719,0.155,0.042,0.047,0.129,0.021,0.021,0.014,0.009,0.029,0.067,0.088,0.095,0.095,0.138,0.091,0.032,0.025,0.025,0.003,0,0,0,0,0,0,0,0,0,0,0,0,0.002,0.045,0.228,0.297,0.325,0.339,0.581,1.244,0.796,0.517,0.227,0.053,0.006,0,0,0,0,0,0,0,0,0,0.003,0.005,0.005,0.005,0.005,0.081,0.129,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.014,0.041,0.041,0.041,0.041,0.027,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.009,0.017,0.017,0.017,0.017,0.355,0.174,0.009,0.009,0.012,0.136,0.208,0.208,0.208,0.215,7.359,1.858,0.458,0.053,0.053,0.047,0.045,0.045,0.059,0.136,0.188,0.206,0.21,0.588,1.517,6.02,4.688,4.42,0.624,0.326,0.359,0.553,0.899,0.94,2.95,9.415,5.752,1.092,0.096,0.035,0.026,0.018,0.015,0.011,0.011,0.011,0,0,0,0,0,0,0,0,0,0,0,0.056,0.27,0.314,0.351,0.354,0.609,0.796,1.857,0.848,0.538,0.214,0.178,0.178,0.201,0.231,0.227,0.272,0.397,0.45,1.014,2.917,1.675,0.081,0.059,0.059,0.148,0.075,0.075,0.078,0.236,0.784,0.784,0.784,0.784,0.741,0.115,0.058,0.058,0.058,0.029,0.015,0.015,0.015,0.015,0.012,0.008,0.604,0.985,1.305,2.273,2.528,2.336,2.496,2.281,1.397,1.713,3.259,1.167,0.745,0.548,1.058,0.684,0.728,0.392,0.179,0.283,0.283,0.46,0.08,0.099,0.099,0.099,0.1,0.143,0.137,0.238,0.317,0.262,0.225,0.792,0.426,0.332,0.261,0.11,0.093,0.102,0.171,0.292,0.504,0.605,1.745,2.485,1.964,0.33,0.171,0.259,0.242,0.215,0.366,0.354,0.205,0.203,0.262,0.153,0.13,0.137,0.362,0.691,0.295,0.433,0.154,0.056,0.053,0.053,0.053,0.051,0.047,0.065,0.078,0.091,0.206,0.813,0.102,0.151,0.05,0.024,0.004,0.001,0,0,0,0.021,0.021,0.021,0.021,0.021,0.013,0.013,0.013,0.013,0.013,0.013,0.013,0.013,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.008,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.018,0.021,0.021,0.021,0.021,0.003,0,0,0,0,0,0,0,0,0,0.024,0.173,0.261,0.267,0.267,0.534,1.354,1.772,0.72,0.218,0.018,0.018,0.028,0.036,0.032,0.194,0.082,0.035,0.286,0.027,0.038,0.038,0.027,0.021,0.014,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.016,0.017,0.017,0.031,0.047,0.043,0.056,0.104,0.149,0.179,0.205,0.328,0.998,0.522,1.851,3.727,3.273,2.204,1.169,1.006,1.179,0.74,0.741,1.065,0.925,0.671,0.497,0.431,0.327,0.277,0.126,0.581,0.207,0.359,2.485,0.038,0.036,0.003,0.003,0.003,0.003,0.004,0.098,0.023,0.021,0.021,0.022,0.041,0.041,0.043,0.045,0.043,0.014,0.014,0.014,0.014,0.014,0.014,0.014,0.031,0.046,0.063,0.119,0.107,0.092,0.085,0.065,0.06,0.054,0.042,0.039,0.046,0.044,0.028,0.028,0.02,0.013,0.013,0.013,0.013,0.016,0.032,0.031,0.031,0.031,0.028,0.011,0.011,0.011,0.011,0.011,0.023,0.024,0.024,0.024,0.019,0.015,0.015,0.015,0.015,0.015,0.015,0.013,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.001,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.011,0.017,0.024,0.026,0.061,0.172,0.206,0.213,0.267,0.511,0.668,0.157,0.017,0.017,0.017,0.046,0.054,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.001,0.017,0.017,0.017,0.017,0.016,0,0,0,0,0,0,0,0,0,0.01,0.017,0.017,0.017,0.017,0.012,0.017,0.017,0.017,0.017,0.012,0,0,0,0,0,0.003,0.031,0.066,0.093,0.112,0.122,0.202,0.068,0.041,0.022,0.011,0,0,0,0,0,0,0,0,0,0,0,0.002,0.005,0.012,0.021,0.021,0.019,0.033,0.03,0.026,0.026,0.034,0.095,0.024,0.024,0.024,0.023,0.019,0.018,0.018,0.018,0.011,0.03,0.045,0.044,0.044,0.044,0.022,0.009,0.024,0.033,0.033,0.033,0.024,0.009,0,0,0,0,0,0,0.003,0.017,0.017,0.017,0.017,0.014,0,0,0,0,0,0.032,0.032,0.032,0.032,0.032,0.005,0.008,0.009,0.014,0.014,0.009,0.005,0.004,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.007,0.009,0.009,0.009,0.009,0.043,0.063,0.084,0.098,0.101,0.213,0.334,0.383,0.43,0.448,0.511,0.801,0.835,1.642,1.614,1.496,1.496,1.476,1.068,0.481,0.22,0.119,0.099,0.07,0.072,0.063,0.076,0.14,0.205,0.28,0.297,0.3,0.479,0.877,1.098,1.611,1.629,1.686,1.686,1.631,1.528,1.862,1.703,1.531,2.196,0.395,0.416,0.453,0.728,0.917,0.986,1.17,2.171,3.011,2.909,3.301,1.377,0.778,0.799,0.947,1.039,0.879,0.76,1.372,1.674,1.674,1.68,1.823,1.793,1.162,0.783,0.216,0.152,0.152,0.152,0.049,0,0,0,0.117,0.127,0.127,0.127,0.127,0.127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.003,0.005,0.005,0.005,0.005,0.003,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.309,0.364,0.364,0.364,0.364,0.063,0.01,0.01,0.01,0.012,0.015,0.015,0.11,0.55,0.824,0.825,0.829,1.39,1.429,1.342,1.43,1.636,1.717,2.135,2.203,3.191,3.022,1.589,0.86,0.807,0.645,0.595,0.588,0.557,0.552,1.271,0.708,0.677,0.629,0.714,0.203,0.133,0.061,0.062,0.018,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.001,0.072,0.29,0.438,0.53,0.557,0.873,1.039,1.04,0.208,0.049,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.03,0.039,0.039,0.039,0.039,0.098,0.008,0.007,0.007,0.007,0.007,0.007,0.007,0.007,0.007,0.007,0.056,0.062,0.065,0.065,0.065,0.047,0.216,0.256,0.315,0.4,0.502,0.449,0.47,0.571,0.814,1.153,0.774,0.202,0.086,0.075,0.071,0.032,0.019,0.003,0.004,0.004,0.004,0.004,0.004,0.004,0.007,0.072,0.153,0.256,0.306,0.404,0.698,0.733,0.823,0.715,0.563,0.404,0.293,0.217,0.213,0.202,0.202,0.294,0.704,0.797,1.359,1.101,0.72,0.514,0.539,0.434,0.389,0.387,0.386,0.375,0.369,0.319,0.239,0.183,0.136,0.062,0.052,0.096,0.119,0.119,0.114,0.127,0.132,0.139,0.169,0.191,0.278,0.254,0.214,0.237,0.221,0.143,0.129,0.125,0.109,0.1,0.087,0.06,0.038,0.029,0.029,0.028,0.048,0.053,0.053,0.111,0.125,0.102,0.097,0.097,0.039,0.02,0.02,0.02,0.014,0.004,0.031,0.043,0.047,0.052,0.08,0.144,0.182,0.176,0.171,0.149,0.112,0.025,0,0,0,0,0,0,0,0.016,0.031,0.031,0.031,0.031,0.015,0,0,0,0,0,0.005,0.005,0.005,0.005,0.005,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005,0.005,0.005,0.005,0.005,0.001,0,0,0 + ]; + var len = oriData.length; + while(len--) { + oriData[len] *= -1; + } + return oriData; + })() + } + ] + } + ] + ,elemarea = $('#LAY-index-area').children('div') + ,renderarea = function(index){ + echarea[index] = echarts.init(elemarea[index], layui.echartsTheme); + echarea[index].setOption(area[index]); + window.onresize = echarea[index].resize; + }; + if(!elemarea[0]) return; + renderarea(0); + + //对数轴 + var echlogline = [], logline = [ + { + title: { + text: "对数轴示例", + x: "center" + }, + tooltip: { + trigger: "item", + formatter: "{a}
{b} : {c}" + }, + legend: { + x: 'left', + data: ["2的指数", "3的指数"] + }, + xAxis: [ + { + type: "category", + name: "x", + splitLine: {show: false}, + data: ["一", "二", "三", "四", "五", "六", "七", "八", "九"] + } + ], + yAxis: [ + { + type: "log", + name: "y" + } + ], + calculable: true, + series: [ + { + name: "3的指数", + type: "line", + data: [1, 3, 9, 27, 81, 247, 741, 2223, 6669] + }, + { + name: "2的指数", + type: "line", + data: [1, 2, 4, 8, 16, 32, 64, 128, 256] + } + ] + } + ] + ,elemlogline = $('#LAY-index-logline').children('div') + ,renderlogline = function(index){ + echlogline[index] = echarts.init(elemlogline[index], layui.echartsTheme); + echlogline[index].setOption(logline[index]); + window.onresize = echlogline[index].resize; + }; + if(!elemlogline[0]) return; + renderlogline(0); + }); + + + //柱状图 + layui.use(['echarts'], function(){ + var $ = layui.$ + ,echarts = layui.echarts; + + //标准柱状图 + var echnormcol = [], normcol = [ + { + title : { + text: '某地区蒸发量和降水量', + subtext: '纯属虚构' + }, + tooltip : { + trigger: 'axis' + }, + legend: { + data:['蒸发量','降水量'] + }, + calculable : true, + xAxis : [ + { + type : 'category', + data : ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'] + } + ], + yAxis : [ + { + type : 'value' + } + ], + series : [ + { + name:'蒸发量', + type:'bar', + data:[2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3], + markPoint : { + data : [ + {type : 'max', name: '最大值'}, + {type : 'min', name: '最小值'} + ] + }, + markLine : { + data : [{type : 'average', name: '平均值'}] + } + }, + { + name:'降水量', + type:'bar', + data:[2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3], + markPoint : { + data : [ + {name : '年最高', value : 182.2, xAxis: 7, yAxis: 183, symbolSize:18}, + {name : '年最低', value : 2.3, xAxis: 11, yAxis: 3} + ] + }, + markLine : { + data : [ + {type : 'average', name : '平均值'} + ] + } + } + ] + } + ] + ,elemNormcol = $('#LAY-index-normcol').children('div') + ,renderNormcol = function(index){ + echnormcol[index] = echarts.init(elemNormcol[index], layui.echartsTheme); + echnormcol[index].setOption(normcol[index]); + window.onresize = echnormcol[index].resize; + }; + if(!elemNormcol[0]) return; + renderNormcol(0); + + //堆积柱状图 + var echheapcol = [], heapcol = [ + { + tooltip : { + trigger: 'axis', + axisPointer : { // 坐标轴指示器,坐标轴触发有效 + type : 'shadow' // 默认为直线,可选为:'line' | 'shadow' + } + }, + legend: { + data:['直接访问','邮件营销','联盟广告','视频广告','搜索引擎','百度','谷歌','必应','其他'] + }, + calculable : true, + xAxis : [ + { + type : 'category', + data : ['周一','周二','周三','周四','周五','周六','周日'] + } + ], + yAxis : [ + { + type : 'value' + } + ], + series : [ + { + name:'直接访问', + type:'bar', + data:[320, 332, 301, 334, 390, 330, 320] + }, + { + name:'邮件营销', + type:'bar', + stack: '广告', + data:[120, 132, 101, 134, 90, 230, 210] + }, + { + name:'联盟广告', + type:'bar', + stack: '广告', + data:[220, 182, 191, 234, 290, 330, 310] + }, + { + name:'视频广告', + type:'bar', + stack: '广告', + data:[150, 232, 201, 154, 190, 330, 410] + }, + { + name:'搜索引擎', + type:'bar', + data:[862, 1018, 964, 1026, 1679, 1600, 1570], + markLine : { + itemStyle:{ + normal:{ + lineStyle:{ + type: 'dashed' + } + } + }, + data : [ + [{type : 'min'}, {type : 'max'}] + ] + } + }, + { + name:'百度', + type:'bar', + barWidth : 5, + stack: '搜索引擎', + data:[620, 732, 701, 734, 1090, 1130, 1120] + }, + { + name:'谷歌', + type:'bar', + stack: '搜索引擎', + data:[120, 132, 101, 134, 290, 230, 220] + }, + { + name:'必应', + type:'bar', + stack: '搜索引擎', + data:[60, 72, 71, 74, 190, 130, 110] + }, + { + name:'其他', + type:'bar', + stack: '搜索引擎', + data:[62, 82, 91, 84, 109, 110, 120] + } + ] + } + ] + ,elemHeapcol = $('#LAY-index-heapcol').children('div') + ,renderHeapcol = function(index){ + echheapcol[index] = echarts.init(elemHeapcol[index], layui.echartsTheme); + echheapcol[index].setOption(heapcol[index]); + window.onresize = echheapcol[index].resize; + }; + if(!elemHeapcol[0]) return; + renderHeapcol(0); + + //不等距柱形图 + var echdiffcol = [], diffcol = [ + { + title : { + text: '双数值柱形图', + subtext: '纯属虚构' + }, + tooltip : { + trigger: 'axis', + axisPointer:{ + show: true, + type : 'cross', + lineStyle: { + type : 'dashed', + width : 1 + } + }, + formatter : function (params) { + return params.seriesName + ' : [ ' + params.value[0] + ', ' + params.value[1] + ' ]'; + } + }, + legend: { + data:['数据1','数据2'] + }, + calculable : true, + xAxis : [ + { + type : 'value' + } + ], + yAxis : [ + { + type : 'value', + axisLine: { + lineStyle: { + color: '#dc143c' + } + } + } + ], + series : [ + { + name:'数据1', + type:'bar', + data:[ + [1.5, 10], [5, 7], [8, 8], [12, 6], [11, 12], [16, 9], [14, 6], [17, 4], [19, 9] + ], + markPoint : { + data : [ + // 纵轴,默认 + {type : 'max', name: '最大值',symbol: 'emptyCircle', itemStyle:{normal:{color:'#dc143c',label:{position:'top'}}}}, + {type : 'min', name: '最小值',symbol: 'emptyCircle', itemStyle:{normal:{color:'#dc143c',label:{position:'bottom'}}}}, + // 横轴 + {type : 'max', name: '最大值', valueIndex: 0, symbol: 'emptyCircle', itemStyle:{normal:{color:'#1e90ff',label:{position:'right'}}}}, + {type : 'min', name: '最小值', valueIndex: 0, symbol: 'emptyCircle', itemStyle:{normal:{color:'#1e90ff',label:{position:'left'}}}} + ] + }, + markLine : { + data : [ + // 纵轴,默认 + {type : 'max', name: '最大值', itemStyle:{normal:{color:'#dc143c'}}}, + {type : 'min', name: '最小值', itemStyle:{normal:{color:'#dc143c'}}}, + {type : 'average', name : '平均值', itemStyle:{normal:{color:'#dc143c'}}}, + // 横轴 + {type : 'max', name: '最大值', valueIndex: 0, itemStyle:{normal:{color:'#1e90ff'}}}, + {type : 'min', name: '最小值', valueIndex: 0, itemStyle:{normal:{color:'#1e90ff'}}}, + {type : 'average', name : '平均值', valueIndex: 0, itemStyle:{normal:{color:'#1e90ff'}}} + ] + } + }, + { + name:'数据2', + type:'bar', + barHeight:10, + data:[ + [1, 2], [2, 3], [4, 4], [7, 5], [11, 11], [18, 15] + ] + } + ] + } + ] + ,elemDiffcol = $('#LAY-index-diffcol').children('div') + ,renderDiffcol = function(index){ + echdiffcol[index] = echarts.init(elemDiffcol[index], layui.echartsTheme); + echdiffcol[index].setOption(diffcol[index]); + window.onresize = echdiffcol[index].resize; + }; + if(!elemDiffcol[0]) return; + renderDiffcol(0); + + //彩虹柱形图 + var echcolorline = [], colorline = [ + { + title: { + x: 'center', + text: 'ECharts例子个数统计', + subtext: 'Rainbow bar example', + link: 'http://echarts.baidu.com/doc/example.html' + }, + tooltip: { + trigger: 'item' + }, + calculable: true, + grid: { + borderWidth: 0, + y: 80, + y2: 60 + }, + xAxis: [ + { + type: 'category', + show: false, + data: ['Line', 'Bar', 'Scatter', 'K', 'Pie', 'Radar', 'Chord', 'Force', 'Map', 'Gauge', 'Funnel'] + } + ], + yAxis: [ + { + type: 'value', + show: false + } + ], + series: [ + { + name: 'ECharts例子个数统计', + type: 'bar', + itemStyle: { + normal: { + color: function(params) { + // build a color map as your need. + var colorList = [ + '#C1232B','#B5C334','#FCCE10','#E87C25','#27727B', + '#FE8463','#9BCA63','#FAD860','#F3A43B','#60C0DD', + '#D7504B','#C6E579','#F4E001','#F0805A','#26C0C0' + ]; + return colorList[params.dataIndex] + }, + label: { + show: true, + position: 'top', + formatter: '{b}\n{c}' + } + } + }, + data: [12,21,10,4,12,5,6,5,25,23,7], + markPoint: { + tooltip: { + trigger: 'item', + backgroundColor: 'rgba(0,0,0,0)', + formatter: function(params){ + return ''; + } + }, + data: [ + {xAxis:0, y: 350, name:'Line', symbolSize:20}, + {xAxis:1, y: 350, name:'Bar', symbolSize:20}, + {xAxis:2, y: 350, name:'Scatter', symbolSize:20}, + {xAxis:3, y: 350, name:'K', symbolSize:20}, + {xAxis:4, y: 350, name:'Pie', symbolSize:20}, + {xAxis:5, y: 350, name:'Radar', symbolSize:20}, + {xAxis:6, y: 350, name:'Chord', symbolSize:20}, + {xAxis:7, y: 350, name:'Force', symbolSize:20}, + {xAxis:8, y: 350, name:'Map', symbolSize:20}, + {xAxis:9, y: 350, name:'Gauge', symbolSize:20}, + {xAxis:10, y: 350, name:'Funnel', symbolSize:20}, + ] + } + } + ] + } + ] + ,elemColorline = $('#LAY-index-colorline').children('div') + ,renderColorline = function(index){ + echcolorline[index] = echarts.init(elemColorline[index], layui.echartsTheme); + echcolorline[index].setOption(colorline[index]); + window.onresize = echcolorline[index].resize; + }; + if(!elemColorline[0]) return; + renderColorline(0); + + //标准条形图 + var echnormbar = [], normbar = [ + { + title : { + text: '世界人口总量', + subtext: '数据来自网络' + }, + tooltip : { + trigger: 'axis' + }, + legend: { + data:['2011年', '2012年'] + }, + calculable : true, + xAxis : [ + { + type : 'value', + boundaryGap : [0, 0.01] + } + ], + yAxis : [ + { + type : 'category', + data : ['巴西','印尼','美国','印度','中国','世界人口(万)'] + } + ], + series : [ + { + name:'2011年', + type:'bar', + data:[18203, 23489, 29034, 104970, 131744, 630230] + }, + { + name:'2012年', + type:'bar', + data:[19325, 23438, 31000, 121594, 134141, 681807] + } + ] + } + ] + ,elemNormbar = $('#LAY-index-normbar').children('div') + ,renderNormbar = function(index){ + echnormbar[index] = echarts.init(elemNormbar[index], layui.echartsTheme); + echnormbar[index].setOption(normbar[index]); + window.onresize = echnormbar[index].resize; + }; + if(!elemNormbar[0]) return; + renderNormbar(0); + + //堆积条形图 + var echheapbar = [], heapbar = [ + { + tooltip : { + trigger: 'axis', + axisPointer : { // 坐标轴指示器,坐标轴触发有效 + type : 'shadow' // 默认为直线,可选为:'line' | 'shadow' + } + }, + legend: { + data:['直接访问', '邮件营销','联盟广告','视频广告','搜索引擎'] + }, + calculable : true, + xAxis : [ + { + type : 'value' + } + ], + yAxis : [ + { + type : 'category', + data : ['周一','周二','周三','周四','周五','周六','周日'] + } + ], + series : [ + { + name:'直接访问', + type:'bar', + stack: '总量', + itemStyle : { normal: {label : {show: true, position: 'insideRight'}}}, + data:[320, 302, 301, 334, 390, 330, 320] + }, + { + name:'邮件营销', + type:'bar', + stack: '总量', + itemStyle : { normal: {label : {show: true, position: 'insideRight'}}}, + data:[120, 132, 101, 134, 90, 230, 210] + }, + { + name:'联盟广告', + type:'bar', + stack: '总量', + itemStyle : { normal: {label : {show: true, position: 'insideRight'}}}, + data:[220, 182, 191, 234, 290, 330, 310] + }, + { + name:'视频广告', + type:'bar', + stack: '总量', + itemStyle : { normal: {label : {show: true, position: 'insideRight'}}}, + data:[150, 212, 201, 154, 190, 330, 410] + }, + { + name:'搜索引擎', + type:'bar', + stack: '总量', + itemStyle : { normal: {label : {show: true, position: 'insideRight'}}}, + data:[820, 832, 901, 934, 1290, 1330, 1320] + } + ] + } + ] + ,elemheapbar = $('#LAY-index-heapbar').children('div') + ,renderheapbar = function(index){ + echheapbar[index] = echarts.init(elemheapbar[index], layui.echartsTheme); + echheapbar[index].setOption(heapbar[index]); + window.onresize = echheapbar[index].resize; + }; + if(!elemheapbar[0]) return; + renderheapbar(0); + + //旋风条形图 + var echwindline = [], labelRight = {normal: {label : {position: 'right'}}}, windline = [ + { + title: { + text: '交错正负轴标签', + subtext: 'From ExcelHome', + sublink: 'http://e.weibo.com/1341556070/AjwF2AgQm' + }, + tooltip : { + trigger: 'axis', + axisPointer : { // 坐标轴指示器,坐标轴触发有效 + type : 'shadow' // 默认为直线,可选为:'line' | 'shadow' + } + }, + grid: { + y: 80, + y2: 30 + }, + xAxis : [ + { + type : 'value', + position: 'top', + splitLine: {lineStyle:{type:'dashed'}}, + } + ], + yAxis : [ + { + type : 'category', + axisLine: {show: false}, + axisLabel: {show: false}, + axisTick: {show: false}, + splitLine: {show: false}, + data : ['ten', 'nine', 'eight', 'seven', 'six', 'five', 'four', 'three', 'two', 'one'] + } + ], + series : [ + { + name:'生活费', + type:'bar', + stack: '总量', + itemStyle : { normal: { + color: 'orange', + borderRadius: 5, + label : { + show: true, + position: 'left', + formatter: '{b}' + } + }}, + data:[ + {value:-0.07, itemStyle:labelRight}, + {value:-0.09, itemStyle:labelRight}, + 0.2, 0.44, + {value:-0.23, itemStyle:labelRight}, + 0.08, + {value:-0.17, itemStyle:labelRight}, + 0.47, + {value:-0.36, itemStyle:labelRight}, + 0.18 + ] + } + ] + } + ] + ,elemwindline = $('#LAY-index-windline').children('div') + ,renderwindline = function(index){ + echwindline[index] = echarts.init(elemwindline[index], layui.echartsTheme); + echwindline[index].setOption(windline[index]); + window.onresize = echwindline[index].resize; + }; + if(!elemwindline[0]) return; + renderwindline(0); + }); + + + //地图 + layui.use(['echarts'], function(){ + var $ = layui.$ + ,echarts = layui.echarts; + + var echplat = [], plat = [ + { + title : { + text: '2011全国GDP(亿元)', + subtext: '数据来自国家统计局' + }, + tooltip : { + trigger: 'item' + }, + dataRange: { + orient: 'horizontal', + min: 0, + max: 55000, + text:['高','低'], // 文本,默认为数值文本 + splitNumber:0 + }, + series : [ + { + name: '2011全国GDP分布', + type: 'map', + mapType: 'china', + mapLocation: { + x: 'center' + }, + selectedMode : 'multiple', + itemStyle:{ + normal:{label:{show:true}}, + emphasis:{label:{show:true}} + }, + data:[ + {name:'西藏', value:605.83}, + {name:'青海', value:1670.44}, + {name:'宁夏', value:2102.21}, + {name:'海南', value:2522.66}, + {name:'甘肃', value:5020.37}, + {name:'贵州', value:5701.84}, + {name:'新疆', value:6610.05}, + {name:'云南', value:8893.12}, + {name:'重庆', value:10011.37}, + {name:'吉林', value:10568.83}, + {name:'山西', value:11237.55}, + {name:'天津', value:11307.28}, + {name:'江西', value:11702.82}, + {name:'广西', value:11720.87}, + {name:'陕西', value:12512.3}, + {name:'黑龙江', value:12582}, + {name:'内蒙古', value:14359.88}, + {name:'安徽', value:15300.65}, + {name:'北京', value:16251.93, selected:true}, + {name:'福建', value:17560.18}, + {name:'上海', value:19195.69, selected:true}, + {name:'湖北', value:19632.26}, + {name:'湖南', value:19669.56}, + {name:'四川', value:21026.68}, + {name:'辽宁', value:22226.7}, + {name:'河北', value:24515.76}, + {name:'河南', value:26931.03}, + {name:'浙江', value:32318.85}, + {name:'山东', value:45361.85}, + {name:'江苏', value:49110.27}, + {name:'广东', value:53210.28, selected:true} + ] + } + ] + } + ] + ,elemplat = $('#LAY-index-plat').children('div') + ,renderplat = function(index){ + echplat[index] = echarts.init(elemplat[index], layui.echartsTheme); + echplat[index].setOption(plat[index]); + window.onresize = echplat[index].resize; + }; + if(!elemplat[0]) return; + renderplat(0); + }); + + exports('senior', {}) + +}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/set.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/set.js new file mode 100644 index 00000000..55233788 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/controller/set.js @@ -0,0 +1,155 @@ +/** + + @Name:layuiAdmin 设置 + + + @License: LPPL + + */ + +layui.define(['form', 'upload'], function(exports){ + var $ = layui.$ + ,layer = layui.layer + ,laytpl = layui.laytpl + ,setter = layui.setter + ,view = layui.view + ,admin = layui.admin + ,form = layui.form + ,upload = layui.upload; + + var $body = $('body'); + + form.render(); + + //自定义验证 + form.verify({ + nickname: function(value, item){ //value:表单的值、item:表单的DOM对象 + if(!new RegExp("^[a-zA-Z0-9_\u4e00-\u9fa5\\s·]+$").test(value)){ + return '用户名不能有特殊字符'; + } + if(/(^\_)|(\__)|(\_+$)/.test(value)){ + return '用户名首尾不能出现下划线\'_\''; + } + if(/^\d+\d+\d$/.test(value)){ + return '用户名不能全为数字'; + } + } + + //我们既支持上述函数式的方式,也支持下述数组的形式 + //数组的两个值分别代表:[正则匹配、匹配不符时的提示文字] + ,pass: [ + /^[\S]{6,12}$/ + ,'密码必须6到12位,且不能出现空格' + ] + + //确认密码 + ,repass: function(value){ + if(value !== $('#LAY_password').val()){ + return '两次密码输入不一致'; + } + } + }); + + //网站设置 + form.on('submit(set_website)', function(obj){ + layer.msg(JSON.stringify(obj.field)); + + //提交修改 + /* + admin.req({ + url: '' + ,data: obj.field + ,success: function(){ + + } + }); + */ + return false; + }); + + //邮件服务 + form.on('submit(set_system_email)', function(obj){ + layer.msg(JSON.stringify(obj.field)); + + //提交修改 + /* + admin.req({ + url: '' + ,data: obj.field + ,success: function(){ + + } + }); + */ + return false; + }); + + + //设置我的资料 + form.on('submit(setmyinfo)', function(obj){ + layer.msg(JSON.stringify(obj.field)); + + //提交修改 + /* + admin.req({ + url: '' + ,data: obj.field + ,success: function(){ + + } + }); + */ + return false; + }); + + //上传头像 + var avatarSrc = $('#LAY_avatarSrc'); + upload.render({ + url: '/api/upload/' + ,elem: '#LAY_avatarUpload' + ,done: function(res){ + if(res.status == 0){ + avatarSrc.val(res.url); + } else { + layer.msg(res.msg, {icon: 5}); + } + } + }); + + //查看头像 + admin.events.avartatPreview = function(othis){ + var src = avatarSrc.val(); + layer.photos({ + photos: { + "title": "查看头像" //相册标题 + ,"data": [{ + "src": src //原图地址 + }] + } + ,shade: 0.01 + ,closeBtn: 1 + ,anim: 5 + }); + }; + + + //设置密码 + form.on('submit(setmypass)', function(obj){ + layer.msg(JSON.stringify(obj.field)); + + //提交修改 + /* + admin.req({ + url: '' + ,data: obj.field + ,success: function(){ + + } + }); + */ + return false; + }); + + //对外暴露的接口 + exports('set', {}); +}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/user.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/user.js new file mode 100644 index 00000000..bb433e40 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/controller/user.js @@ -0,0 +1,52 @@ +/** + + @Name:layuiAdmin 用户登入和注册等 + + + @License: LPPL + + */ + +layui.define('form', function(exports){ + var $ = layui.$ + ,layer = layui.layer + ,laytpl = layui.laytpl + ,setter = layui.setter + ,view = layui.view + ,admin = layui.admin + ,form = layui.form; + + var $body = $('body'); + + //自定义验证 + form.verify({ + nickname: function(value, item){ //value:表单的值、item:表单的DOM对象 + if(!new RegExp("^[a-zA-Z0-9_\u4e00-\u9fa5\\s·]+$").test(value)){ + return '用户名不能有特殊字符'; + } + if(/(^\_)|(\__)|(\_+$)/.test(value)){ + return '用户名首尾不能出现下划线\'_\''; + } + if(/^\d+\d+\d$/.test(value)){ + return '用户名不能全为数字'; + } + } + + //我们既支持上述函数式的方式,也支持下述数组的形式 + //数组的两个值分别代表:[正则匹配、匹配不符时的提示文字] + ,pass: [ + /^[\S]{6,12}$/ + ,'密码必须6到12位,且不能出现空格' + ] + }); + + + //更换图形验证码 + $body.on('click', '#LAY-user-get-vercode', function(){ + var othis = $(this); + this.src = 'https://www.oschina.net/action/user/captcha?t='+ new Date().getTime() + }); + + //对外暴露的接口 + exports('user', {}); +}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/useradmin.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/useradmin.js new file mode 100644 index 00000000..1eaf315f --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/controller/useradmin.js @@ -0,0 +1,184 @@ +/** + + @Name:layuiAdmin 用户管理 管理员管理 角色管理 + @Author:star1029 + + @License:LPPL + + */ + + +layui.define(['table', 'form'], function(exports){ + var $ = layui.$ + ,admin = layui.admin + ,view = layui.view + ,table = layui.table + ,form = layui.form; + + //用户管理 + table.render({ + elem: '#LAY-user-manage' + ,url: './json/useradmin/webuser.js' //模拟接口 + ,cols: [[ + {type: 'checkbox', fixed: 'left'} + ,{field: 'id', width: 100, title: 'ID', sort: true} + ,{field: 'username', title: '用户名', minWidth: 100} + ,{field: 'avatar', title: '头像', width: 100, templet: '#imgTpl'} + ,{field: 'phone', title: '手机'} + ,{field: 'email', title: '邮箱'} + ,{field: 'sex', width: 80, title: '性别'} + ,{field: 'ip', title: 'IP'} + ,{field: 'jointime', title: '加入时间', sort: true} + ,{title: '操作', width: 150, align:'center', fixed: 'right', toolbar: '#table-useradmin-webuser'} + ]] + ,page: true + ,limit: 30 + ,height: 'full-320' + ,text: '对不起,加载出现异常!' + }); + + //工具条 + table.on('tool(LAY-user-manage)', function(obj){ + var data = obj.data; + if(obj.event === 'del'){ + layer.prompt({ + formType: 1 + ,title: '敏感操作,请验证口令' + }, function(value, index){ + layer.close(index); + + layer.confirm('真的删除行么', function(index){ + obj.del(); + layer.close(index); + }); + }); + } else if(obj.event === 'edit'){ + admin.popup({ + title: '编辑用户' + ,area: ['500px', '450px'] + ,id: 'LAY-popup-user-add' + ,success: function(layero, index){ + view(this.id).render('user/user/userform', data).done(function(){ + form.render(null, 'layuiadmin-form-useradmin'); + + //提交 + form.on('submit(LAY-user-front-submit)', function(data){ + var field = data.field; //获取提交的字段 + + //提交 Ajax 成功后,关闭当前弹层并重载表格 + //$.ajax({}); + layui.table.reload('LAY-user-manage'); //重载表格 + layer.close(index); //执行关闭 + }); + }); + } + }); + } + }); + + //管理员管理 + table.render({ + elem: '#LAY-user-back-manage' + ,url: './json/useradmin/mangadmin.js' //模拟接口 + ,cols: [[ + {type: 'checkbox', fixed: 'left'} + ,{field: 'id', width: 80, title: 'ID', sort: true} + ,{field: 'loginname', title: '登录名'} + ,{field: 'telphone', title: '手机'} + ,{field: 'email', title: '邮箱'} + ,{field: 'role', title: '角色'} + ,{field: 'jointime', title: '加入时间', sort: true} + ,{field: 'check', title:'审核状态', templet: '#buttonTpl', minWidth: 80, align: 'center'} + ,{title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#table-useradmin-admin'} + ]] + ,text: '对不起,加载出现异常!' + }); + + //工具条 + table.on('tool(LAY-user-back-manage)', function(obj){ + var data = obj.data; + if(obj.event === 'del'){ + layer.prompt({ + formType: 1 + ,title: '敏感操作,请验证口令' + }, function(value, index){ + layer.close(index); + layer.confirm('确定删除此管理员?', function(index){ + console.log(obj) + obj.del(); + layer.close(index); + }); + }); + }else if(obj.event === 'edit'){ + admin.popup({ + title: '编辑管理员' + ,area: ['420px', '450px'] + ,id: 'LAY-popup-user-add' + ,success: function(layero, index){ + view(this.id).render('user/administrators/adminform', data).done(function(){ + form.render(null, 'layuiadmin-form-admin'); + + //提交 + form.on('submit(LAY-user-back-submit)', function(data){ + var field = data.field; //获取提交的字段 + + //提交 Ajax 成功后,关闭当前弹层并重载表格 + //$.ajax({}); + layui.table.reload('LAY-user-back-manage'); //重载表格 + layer.close(index); //执行关闭 + }); + }); + } + }); + } + }); + + //角色管理 + table.render({ + elem: '#LAY-user-back-role' + ,url: './json/useradmin/role.js' //模拟接口 + ,cols: [[ + {type: 'checkbox', fixed: 'left'} + ,{field: 'id', width: 80, title: 'ID', sort: true} + ,{field: 'rolename', title: '角色名'} + ,{field: 'limits', title: '拥有权限'} + ,{field: 'descr', title: '具体描述'} + ,{title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#table-useradmin-admin'} + ]] + ,text: '对不起,加载出现异常!' + }); + + //工具条 + table.on('tool(LAY-user-back-role)', function(obj){ + var data = obj.data; + if(obj.event === 'del'){ + layer.confirm('确定删除此角色?', function(index){ + obj.del(); + layer.close(index); + }); + }else if(obj.event === 'edit'){ + admin.popup({ + title: '添加新角色' + ,area: ['500px', '480px'] + ,id: 'LAY-popup-user-add' + ,success: function(layero, index){ + view(this.id).render('user/administrators/roleform', data).done(function(){ + form.render(null, 'layuiadmin-form-role'); + + //提交 + form.on('submit(LAY-user-role-submit)', function(data){ + var field = data.field; //获取提交的字段 + + //提交 Ajax 成功后,关闭当前弹层并重载表格 + //$.ajax({}); + layui.table.reload('LAY-user-back-role'); //重载表格 + layer.close(index); //执行关闭 + }); + }); + } + }); + } + }); + + exports('useradmin', {}) +}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/workorder.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/workorder.js new file mode 100644 index 00000000..3e94d8ac --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/controller/workorder.js @@ -0,0 +1,70 @@ +/** + + @Name:layuiAdmin 工单系统 + @Author:star1029 + + @License:GPL-2 + + */ + + +layui.define(['table', 'form', 'element'], function(exports){ + var $ = layui.$ + ,admin = layui.admin + ,view = layui.view + ,table = layui.table + ,form = layui.form + ,element = layui.element; + + table.render({ + elem: '#LAY-app-workorder' + ,url: './json/workorder/demo.js' //模拟接口 + ,cols: [[ + {type: 'numbers', fixed: 'left'} + ,{field: 'orderid', width: 100, title: '工单号', sort: true} + ,{field: 'attr', width: 100, title: '业务性质'} + ,{field: 'title', width: 100, title: '工单标题', width: 300} + ,{field: 'progress', title: '进度', width: 200, align: 'center', templet: '#progressTpl'} + ,{field: 'submit', width: 100, title: '提交者'} + ,{field: 'accept', width: 100, title: '受理人员'} + ,{field: 'state', title: '工单状态', templet: '#buttonTpl', minWidth: 80, align: 'center'} + ,{title: '操作', align: 'center', fixed: 'right', toolbar: '#table-system-order'} + ]] + ,page: true + ,limit: 10 + ,limits: [10, 15, 20, 25, 30] + ,text: '对不起,加载出现异常!' + ,done: function(){ + element.render('progress'); + } + }); + + //工具条 + table.on('tool(LAY-app-workorder)', function(obj){ + var data = obj.data; + if(obj.event === 'edit'){ + admin.popup({ + title: '编辑工单' + ,area: ['450px', '450px'] + ,id: 'LAY-popup-workorder-add' + ,success: function(layero, index){ + view(this.id).render('app/workorder/listform').done(function(){ + form.render(null, 'layuiadmin-form-workorder'); + + //提交 + form.on('submit(LAY-app-workorder-submit)', function(data){ + var field = data.field; //获取提交的字段 + + //提交 Ajax 成功后,关闭当前弹层并重载表格 + //$.ajax({}); + layui.table.reload('LAY-app-workorder'); //重载表格 + layer.close(index); //执行关闭 + }); + }); + } + }); + } + }); + + exports('workorder', {}) +}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/index.js b/iot-server/server-starter/src/main/webapp/assets/src/index.js new file mode 100644 index 00000000..44c0aea0 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/index.js @@ -0,0 +1,213 @@ +/*! + * 界面入口模块 + */ + +layui.extend({ + setter: 'config' //配置文件 + , admin: 'lib/admin' //核心模块 + , view: 'lib/view' //核心模块 +}).define(['setter', 'admin'], function (exports) { + var setter = layui.setter + , element = layui.element + , admin = layui.admin + , tabsPage = admin.tabsPage + , view = layui.view + + //根据路由渲染页面 + , renderPage = function () { + var router = layui.router() + , path = router.path + , pathURL = admin.correctRouter(router.path.join('/')) + + + //默认读取主页 + if (!path.length) path = ['']; + + //如果最后一项为空字符,则读取默认文件 + if (path[path.length - 1] === '') { + path[path.length - 1] = setter.entry; + } + + /* + layui.config({ + base: setter.base + 'controller/' + }); + */ + + //重置状态 + var reset = function (type) { + //renderPage.haveInit && layer.closeAll(); + if (renderPage.haveInit) { + $('.layui-layer').each(function () { + var othis = $(this), + index = othis.attr('times'); + if (!(othis.hasClass('layui-layim') || othis.hasClass('layui-layim-chat'))) { + layer.close(index); + } + }); + } + renderPage.haveInit = true; + + $(APP_BODY).scrollTop(0); + delete tabsPage.type; //重置页面标签的来源类型 + }; + + //如果路由来自于 tab 切换,则不重新请求视图 + if (tabsPage.type === 'tab') { + //切换到非主页、或者切换到主页且主页必须有内容。方可阻止请求 + if (pathURL !== '/' || (pathURL === '/' && admin.tabsBody().html())) { + admin.tabsBodyChange(tabsPage.index); + return reset(tabsPage.type); + } + } + + //请求视图渲染 + view().render(path.join('/')).then(function (res) { + + //遍历页签选项卡 + var matchTo + , tabs = $('#LAY_app_tabsheader>li'); + + tabs.each(function (index) { + var li = $(this) + , layid = li.attr('lay-id'); + + if (layid === pathURL) { + matchTo = true; + tabsPage.index = index; + } + }); + + //如果未在选项卡中匹配到,则追加选项卡 + if (setter.pageTabs && pathURL !== '/') { + if (!matchTo) { + $(APP_BODY).append('
'); + tabsPage.index = tabs.length; + element.tabAdd(FILTER_TAB_TBAS, { + title: '' + (res.title || '新标签页') + '' + , id: pathURL + , attr: router.href + }); + } + } + + this.container = admin.tabsBody(tabsPage.index); + setter.pageTabs || this.container.scrollTop(0); //如果不开启标签页,则跳转时重置滚动条 + + //定位当前tabs + element.tabChange(FILTER_TAB_TBAS, pathURL); + admin.tabsBodyChange(tabsPage.index); + + }).done(function () { + layui.use('common', layui.cache.callback.common); + $win.on('resize', layui.data.resize); + + element.render('breadcrumb', 'breadcrumb'); + + //容器 scroll 事件,剔除吸附层 + admin.tabsBody(tabsPage.index).on('scroll', function () { + var othis = $(this) + , elemDate = $('.layui-laydate') + , layerOpen = $('.layui-layer')[0]; + + //关闭 layDate + if (elemDate[0]) { + elemDate.each(function () { + var thisElemDate = $(this); + thisElemDate.hasClass('layui-laydate-static') || thisElemDate.remove(); + }); + othis.find('input').blur(); + } + + //关闭 Tips 层 + layerOpen && layer.closeAll('tips'); + }); + }); + + reset(); + } + + //入口页面 + , entryPage = function (fn) { + var router = layui.router() + , container = view(setter.container) + , pathURL = admin.correctRouter(router.path.join('/')) + , isIndPage; + + //检查是否属于独立页面 + layui.each(setter.indPage, function (index, item) { + if (pathURL === item) { + return isIndPage = true; + } + }); + + //将模块根路径设置为 controller 目录 + layui.config({ + base: setter.base + 'controller/' + }); + + //独立页面 + if (isIndPage || pathURL === '/user/login') { //此处单独判断登入页,是为了兼容旧版(即未在 config.js 配置 indPage 的情况) + container.render(router.path.join('/')).done(function () { + admin.pageType = 'alone'; + }); + } else { //后台框架页面 + + //强制拦截未登入 + if (setter.interceptor) { + var local = layui.data(setter.tableName); + if (!local[setter.request.tokenName]) { + return location.hash = '/user/login/redirect=' + encodeURIComponent(pathURL); //跳转到登入页 + } + } + + //渲染后台结构 + if (admin.pageType === 'console') { //后台主体页 + renderPage(); + } else { //初始控制台结构 + container.render('layout').done(function () { + renderPage(); + layui.element.render(); + + if (admin.screen() < 2) { + admin.sideFlexible(); + } + admin.pageType = 'console'; + }); + } + + } + } + + , APP_BODY = '#LAY_app_body', FILTER_TAB_TBAS = 'layadmin-layout-tabs' + , $ = layui.$, $win = $(window); + + //初始主体结构 + layui.link( + setter.base + 'style/admin.css?v=' + (admin.v + '-1') + , function () { + entryPage() + } + , 'layuiAdmin' + ); + + //Hash改变 + window.onhashchange = function () { + entryPage(); + //执行 {setter.MOD_NAME}.hash 下的事件 + layui.event.call(this, setter.MOD_NAME, 'hash({*})', layui.router()); + }; + + //扩展 lib 目录下的其它模块 + layui.each(setter.extend, function (key, value) { + var mods = {} + , _isArray = setter.extend.constructor === Array; + mods[_isArray ? value : key] = '{/}' + setter.base + 'lib/extend/' + value; + layui.extend(mods); + }); + + //对外输出 + exports('index', { + render: renderPage + }); +}); diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/admin.js b/iot-server/server-starter/src/main/webapp/assets/src/lib/admin.js new file mode 100644 index 00000000..ea81176d --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/lib/admin.js @@ -0,0 +1,861 @@ + +/*! + * 界面核心模块 + */ + +layui.define(['view', 'table', 'upload'], function(exports){ + var $ = layui.jquery + ,laytpl = layui.laytpl + ,element = layui.element + ,table = layui.table + ,upload = layui.upload + ,setter = layui.setter + ,view = layui.view + ,device = layui.device() + + ,$win = $(window), $body = $('body') + ,container = $('#'+ setter.container) + + ,SHOW = 'layui-show', HIDE = 'layui-hide', THIS = 'layui-this', DISABLED = 'layui-disabled', TEMP = 'template' + ,APP_BODY = '#LAY_app_body', APP_FLEXIBLE = 'LAY_app_flexible' + ,FILTER_TAB_TBAS = 'layadmin-layout-tabs' + ,APP_SPREAD_SM = 'layadmin-side-spread-sm', TABS_BODY = 'layadmin-tabsbody-item' + ,ICON_SHRINK = 'layui-icon-shrink-right', ICON_SPREAD = 'layui-icon-spread-left' + ,SIDE_SHRINK = 'layadmin-side-shrink', SIDE_MENU = 'LAY-system-side-menu' + + //通用方法 + ,admin = { + v: '1.7.2 pro' + + //数据的异步请求 + ,req: view.req + + //清除本地 token,并跳转到登入页 + ,exit: view.exit + + //xss 转义 + ,escape: function(html){ + return String(html || '').replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&') + .replace(//g, '>') + .replace(/'/g, ''').replace(/"/g, '"'); + } + + //事件 + ,on: function(events, callback){ + return layui.onevent.call(this, setter.MOD_NAME, events, callback); + } + + //弹出面板 + ,popup: view.popup + + //右侧面板 + ,popupRight: function(options){ + //layer.close(admin.popup.index); + return admin.popup.index = layer.open($.extend({ + type: 1 + ,id: 'LAY_adminPopupR' + ,anim: -1 + ,title: false + ,closeBtn: false + ,offset: 'r' + ,shade: 0.1 + ,shadeClose: true + ,skin: 'layui-anim layui-anim-rl layui-layer-adminRight' + ,area: '300px' + }, options)); + } + + //发送验证码 + ,sendAuthCode: function(options){ + options = $.extend({ + seconds: 60 + ,elemPhone: '#LAY_phone' + ,elemVercode: '#LAY_vercode' + }, options); + + var seconds = options.seconds + ,token = null + ,timer, countDown = function(loop){ + var btn = $(options.elem) + seconds--; + if(seconds < 0){ + btn.removeClass(DISABLED).html('获取验证码'); + seconds = options.seconds; + clearInterval(timer); + } else { + btn.addClass(DISABLED).html(seconds + '秒后重获'); + } + + if(!loop){ + timer = setInterval(function(){ + countDown(true); + }, 1000); + } + }; + + $body.off('click', options.elem).on('click', options.elem, function(){ + options.elemPhone = $(options.elemPhone); + options.elemVercode = $(options.elemVercode); + + var elemPhone = options.elemPhone + ,value = elemPhone.val(); + + if(seconds !== options.seconds || $(this).hasClass(DISABLED)) return; + + if(!/^1\d{10}$/.test(value)){ + elemPhone.focus(); + return layer.msg('请输入正确的手机号') + }; + + if(typeof options.ajax === 'object'){ + var success = options.ajax.success; + delete options.ajax.success; + } + + admin.req($.extend(true, { + url: '/auth/code' + ,type: 'get' + ,data: { + phone: value + } + ,success: function(res){ + layer.msg('验证码已发送至你的手机,请注意查收', { + icon: 1 + ,shade: 0 + }); + options.elemVercode.focus(); + countDown(); + success && success(res); + } + }, options.ajax)); + }); + } + + //屏幕类型 + ,screen: function(){ + var width = $win.width(); + if(width > 1200){ + return 3; //大屏幕 + } else if(width > 992){ + return 2; //中屏幕 + } else if(width > 768){ + return 1; //小屏幕 + } else { + return 0; //超小屏幕 + } + } + + //侧边伸缩 + ,sideFlexible: function(status){ + var app = container + ,iconElem = $('#'+ APP_FLEXIBLE) + ,screen = admin.screen(); + + //设置状态,PC:默认展开、移动:默认收缩 + if(status === 'spread'){ + //切换到展开状态的 icon,箭头:← + iconElem.removeClass(ICON_SPREAD).addClass(ICON_SHRINK); + + //移动:从左到右位移;PC:清除多余选择器恢复默认 + if(screen < 2){ + app.addClass(APP_SPREAD_SM); + } else { + app.removeClass(APP_SPREAD_SM); + } + + app.removeClass(SIDE_SHRINK) + } else { + //切换到搜索状态的 icon,箭头:→ + iconElem.removeClass(ICON_SHRINK).addClass(ICON_SPREAD); + + //移动:清除多余选择器恢复默认;PC:从右往左收缩 + if(screen < 2){ + app.removeClass(SIDE_SHRINK); + } else { + app.addClass(SIDE_SHRINK); + } + + app.removeClass(APP_SPREAD_SM) + } + + layui.event.call(this, setter.MOD_NAME, 'side({*})', { + status: status + }); + } + + //重置主体区域表格尺寸 + ,resizeTable: function(delay){ + var that = this, runResizeTable = function(){ + that.tabsBody(admin.tabsPage.index).find('.layui-table-view').each(function(){ + var tableID = $(this).attr('lay-id'); + layui.table.resize(tableID); + }); + }; + if(!layui.table) return; + delay ? setTimeout(runResizeTable, delay) : runResizeTable(); + } + + //主题设置 + ,theme: function(options){ + var theme = setter.theme + ,local = layui.data(setter.tableName) + ,id = 'LAY_layadmin_theme' + ,style = document.createElement('style') + ,styleText = laytpl([ + //主题色 + '.layui-side-menu,' + ,'.layadmin-pagetabs .layui-tab-title li:after,' + ,'.layadmin-pagetabs .layui-tab-title li.layui-this:after,' + ,'.layui-layer-admin .layui-layer-title,' + ,'.layadmin-side-shrink .layui-side-menu .layui-nav>.layui-nav-item>.layui-nav-child' + ,'{background-color:{{d.color.main}} !important;}' + + //选中色 + ,'.layui-nav-tree .layui-this,' + ,'.layui-nav-tree .layui-this>a,' + ,'.layui-nav-tree .layui-nav-child dd.layui-this,' + ,'.layui-nav-tree .layui-nav-child dd.layui-this a' + ,'{background-color:{{d.color.selected}} !important;}' + + //logo + ,'.layui-layout-admin .layui-logo{background-color:{{d.color.logo || d.color.main}} !important;}' + + //头部色 + ,'{{# if(d.color.header){ }}' + ,'.layui-layout-admin .layui-header{background-color:{{ d.color.header }};}' + ,'.layui-layout-admin .layui-header a,' + ,'.layui-layout-admin .layui-header a cite{color: #f8f8f8;}' + ,'.layui-layout-admin .layui-header a:hover{color: #fff;}' + ,'.layui-layout-admin .layui-header .layui-nav .layui-nav-more{border-top-color: #fbfbfb;}' + ,'.layui-layout-admin .layui-header .layui-nav .layui-nav-mored{border-color: transparent; border-bottom-color: #fbfbfb;}' + ,'.layui-layout-admin .layui-header .layui-nav .layui-this:after, .layui-layout-admin .layui-header .layui-nav-bar{background-color: #fff; background-color: rgba(255,255,255,.5);}' + ,'.layadmin-pagetabs .layui-tab-title li:after{display: none;}' + ,'{{# } }}' + ].join('')).render(options = $.extend({}, local.theme, options)) + ,styleElem = document.getElementById(id); + + //添加主题样式 + if('styleSheet' in style){ + style.setAttribute('type', 'text/css'); + style.styleSheet.cssText = styleText; + } else { + style.innerHTML = styleText; + } + style.id = id; + + styleElem && $body[0].removeChild(styleElem); + $body[0].appendChild(style); + $body.attr('layadmin-themealias', options.color.alias); + + //本地存储记录 + local.theme = local.theme || {}; + layui.each(options, function(key, value){ + local.theme[key] = value; + }); + layui.data(setter.tableName, { + key: 'theme' + ,value: local.theme + }); + } + + //初始化主题 + ,initTheme: function(index){ + var theme = setter.theme; + index = index || 0; + if(theme.color[index]){ + theme.color[index].index = index; + admin.theme({ + color: theme.color[index] + }); + } + } + + //记录最近一次点击的页面标签数据 + ,tabsPage: {} + + //获取标签页的头元素 + ,tabsHeader: function(index){ + return $('#LAY_app_tabsheader').children('li').eq(index || 0); + } + + //获取页面标签主体元素 + ,tabsBody: function(index){ + return $(APP_BODY).find('.'+ TABS_BODY).eq(index || 0); + } + + //切换页面标签主体 + ,tabsBodyChange: function(index){ + admin.tabsHeader(index).attr('lay-attr', layui.router().href); + admin.tabsBody(index).addClass(SHOW).siblings().removeClass(SHOW); + events.rollPage('auto', index); + } + + //resize事件管理 + ,resize: function(fn){ + var router = layui.router() + ,key = router.path.join('-'); + + if(admin.resizeFn[key]){ + $win.off('resize', admin.resizeFn[key]); + delete admin.resizeFn[key]; + } + + if(fn === 'off') return; //如果是清除 resize 事件,则终止往下执行 + + fn(), admin.resizeFn[key] = fn; + $win.on('resize', admin.resizeFn[key]); + } + ,resizeFn: {} + ,runResize: function(){ + var router = layui.router() + ,key = router.path.join('-'); + admin.resizeFn[key] && admin.resizeFn[key](); + } + ,delResize: function(){ + this.resize('off'); + } + + //关闭当前 pageTabs + ,closeThisTabs: function(){ + if(!admin.tabsPage.index) return; + $(TABS_HEADER).eq(admin.tabsPage.index).find('.layui-tab-close').trigger('click'); + } + + //全屏 + ,fullScreen: function(){ + var ele = document.documentElement + ,reqFullScreen = ele.requestFullScreen || ele.webkitRequestFullScreen + || ele.mozRequestFullScreen || ele.msRequestFullscreen; + if(typeof reqFullScreen !== 'undefined' && reqFullScreen) { + reqFullScreen.call(ele); + }; + } + + //退出全屏 + ,exitScreen: function(){ + var ele = document.documentElement + if (document.exitFullscreen) { + document.exitFullscreen(); + } else if (document.mozCancelFullScreen) { + document.mozCancelFullScreen(); + } else if (document.webkitCancelFullScreen) { + document.webkitCancelFullScreen(); + } else if (document.msExitFullscreen) { + document.msExitFullscreen(); + } + } + + //纠正单页路由格式 + ,correctRouter: function(href){ + if(!/^\//.test(href)) href = '/' + href; + + //纠正首尾 + return href.replace(/^(\/+)/, '/') + .replace(new RegExp('\/' + setter.entry + '$'), '/'); //过滤路由最后的默认视图文件名(如:index) + } + + //…… + }; + + //事件 + var events = admin.events = { + //伸缩 + flexible: function(othis){ + var iconElem = othis.find('#'+ APP_FLEXIBLE) + ,isSpread = iconElem.hasClass(ICON_SPREAD); + admin.sideFlexible(isSpread ? 'spread' : null); //控制伸缩 + admin.resizeTable(350); + } + + //刷新 + ,refresh: function(){ + layui.index.render(); + } + + //输入框搜索 + ,serach: function(othis){ + othis.off('keypress').on('keypress',function(e){ + if(!this.value.replace(/\s/g, '')) return; + //回车跳转 + if(e.keyCode === 13){ + var href = othis.attr('lay-action') + ,text = othis.attr('lay-text') || '搜索'; + + href = href + this.value; + text = text + ' '+ admin.escape(this.value) +''; + + //打开标签页 + location.hash = admin.correctRouter(href) + + //如果搜索关键词已经打开,则刷新页面即可 + events.serach.keys || (events.serach.keys = {}); + events.serach.keys[admin.tabsPage.index] = this.value; + if(this.value === events.serach.keys[admin.tabsPage.index]){ + events.refresh(othis); + } + + //清空输入框 + this.value = ''; + } + }); + } + + //点击消息 + ,message: function(othis){ + othis.find('.layui-badge-dot').remove(); + } + + //弹出主题面板 + ,theme: function(){ + admin.popupRight({ + id: 'LAY_adminPopupTheme' + ,success: function(){ + view(this.id).render('system/theme') + } + }); + } + + //便签 + ,note: function(othis){ + var mobile = admin.screen() < 2 + ,note = layui.data(setter.tableName).note; + + events.note.index = admin.popup({ + title: '便签' + ,shade: 0 + ,offset: [ + '41px' + ,(mobile ? null : (othis.offset().left - 250) + 'px') + ] + ,anim: -1 + ,id: 'LAY_adminNote' + ,skin: 'layadmin-note layui-anim layui-anim-upbit' + ,content: '' + ,resize: false + ,success: function(layero, index){ + var textarea = layero.find('textarea') + ,value = note === undefined ? '便签中的内容会存储在本地,这样即便你关掉了浏览器,在下次打开时,依然会读取到上一次的记录。是个非常小巧实用的本地备忘录' : note; + + textarea.val(value).focus().on('keyup', function(){ + layui.data(setter.tableName, { + key: 'note' + ,value: this.value + }); + }); + } + }) + } + + //全屏 + ,fullscreen: function(othis){ + var SCREEN_FULL = 'layui-icon-screen-full' + ,SCREEN_REST = 'layui-icon-screen-restore' + ,iconElem = othis.children("i"); + + if(iconElem.hasClass(SCREEN_FULL)){ + admin.fullScreen(); + iconElem.addClass(SCREEN_REST).removeClass(SCREEN_FULL); + } else { + admin.exitScreen(); + iconElem.addClass(SCREEN_FULL).removeClass(SCREEN_REST); + } + } + + //弹出关于面板 + ,about: function(){ + admin.popupRight({ + id: 'LAY_adminPopupAbout' + ,success: function(){ + view(this.id).render('system/about') + } + }); + } + + //弹出更多面板 + ,more: function(){ + admin.popupRight({ + id: 'LAY_adminPopupMore' + ,success: function(){ + view(this.id).render('system/more') + } + }); + } + + //返回上一页 + ,back: function(){ + history.back(); + } + + //主题设置 + ,setTheme: function(othis){ + var index = othis.data('index') + ,nextIndex = othis.siblings('.layui-this').data('index'); + + if(othis.hasClass(THIS)) return; + + othis.addClass(THIS).siblings('.layui-this').removeClass(THIS); + admin.initTheme(index); + } + + //左右滚动页面标签 + ,rollPage: function(type, index){ + var tabsHeader = $('#LAY_app_tabsheader') + ,liItem = tabsHeader.children('li') + ,scrollWidth = tabsHeader.prop('scrollWidth') + ,outerWidth = tabsHeader.outerWidth() + ,tabsLeft = parseFloat(tabsHeader.css('left')); + + //右左往右 + if(type === 'left'){ + if(!tabsLeft && tabsLeft <=0) return; + + //当前的left减去可视宽度,用于与上一轮的页标比较 + var prefLeft = -tabsLeft - outerWidth; + + liItem.each(function(index, item){ + var li = $(item) + ,left = li.position().left; + + if(left >= prefLeft){ + tabsHeader.css('left', -left); + return false; + } + }); + } else if(type === 'auto'){ //自动滚动 + (function(){ + var thisLi = liItem.eq(index), thisLeft; + + if(!thisLi[0]) return; + thisLeft = thisLi.position().left; + + //当目标标签在可视区域左侧时 + if(thisLeft < -tabsLeft){ + return tabsHeader.css('left', -thisLeft); + } + + //当目标标签在可视区域右侧时 + if(thisLeft + thisLi.outerWidth() >= outerWidth - tabsLeft){ + var subLeft = thisLeft + thisLi.outerWidth() - (outerWidth - tabsLeft); + liItem.each(function(i, item){ + var li = $(item) + ,left = li.position().left; + + //从当前可视区域的最左第二个节点遍历,如果减去最左节点的差 > 目标在右侧不可见的宽度,则将该节点放置可视区域最左 + if(left + tabsLeft > 0){ + if(left - tabsLeft > subLeft){ + tabsHeader.css('left', -left); + return false; + } + } + }); + } + }()); + } else { + //默认向左滚动 + liItem.each(function(i, item){ + var li = $(item) + ,left = li.position().left; + + if(left + li.outerWidth() >= outerWidth - tabsLeft){ + tabsHeader.css('left', -left); + return false; + } + }); + } + } + + //向右滚动页面标签 + ,leftPage: function(){ + events.rollPage('left'); + } + + //向左滚动页面标签 + ,rightPage: function(){ + events.rollPage(); + } + + //关闭当前标签页 + ,closeThisTabs: function(){ + admin.closeThisTabs(); + } + + //关闭其它标签页 + ,closeOtherTabs: function(type){ + var TABS_REMOVE = 'LAY-system-pagetabs-remove'; + if(type === 'all'){ + $(TABS_HEADER+ ':gt(0)').remove(); + $(APP_BODY).find('.'+ TABS_BODY+ ':gt(0)').remove(); + } else { + $(TABS_HEADER).each(function(index, item){ + if(index && index != admin.tabsPage.index){ + $(item).addClass(TABS_REMOVE); + admin.tabsBody(index).addClass(TABS_REMOVE); + } + }); + $('.'+ TABS_REMOVE).remove(); + } + } + + //关闭全部标签页 + ,closeAllTabs: function(){ + events.closeOtherTabs('all'); + location.hash = ''; + } + + //遮罩 + ,shade: function(){ + admin.sideFlexible(); + } + }; + + //初始 + !function(){ + //主题初始化,本地主题记录优先,其次为 initColorIndex + var local = layui.data(setter.tableName); + if(local.theme){ + admin.theme(local.theme); + } else if(setter.theme){ + admin.initTheme(setter.theme.initColorIndex); + } + + //禁止水平滚动 + $body.addClass('layui-layout-body'); + + //移动端强制不开启页面标签功能 + if(admin.screen() < 1){ + delete setter.pageTabs; + } + + //不开启页面标签时 + if(!setter.pageTabs){ + container.addClass('layadmin-tabspage-none'); + } + + //低版本IE提示 + if(device.ie && device.ie < 10){ + view.error('IE'+ device.ie + '下访问可能不佳,推荐使用:Chrome / Firefox / Edge 等高级浏览器', { + offset: 'auto' + ,id: 'LAY_errorIE' + }); + } + + }(); + + //admin.prevRouter = {}; //上一个路由 + + // hash 改变侧边状态 + admin.on('hash(side)', function(router){ + var path = router.path, getData = function(item){ + return { + list: item.children('.layui-nav-child') + ,name: item.data('name') + ,jump: item.data('jump') + } + } + ,sideMenu = $('#'+ SIDE_MENU) + ,SIDE_NAV_ITEMD = 'layui-nav-itemed' + + //捕获对应菜单 + ,matchMenu = function(list){ + var pathURL = admin.correctRouter(path.join('/')); + list.each(function(index1, item1){ + var othis1 = $(item1) + ,data1 = getData(othis1) + ,listChildren1 = data1.list.children('dd') + ,matched1 = path[0] == data1.name || (index1 === 0 && !path[0]) + || (data1.jump && pathURL == admin.correctRouter(data1.jump)); + + listChildren1.each(function(index2, item2){ + var othis2 = $(item2) + ,data2 = getData(othis2) + ,listChildren2 = data2.list.children('dd') + ,matched2 = (path[0] == data1.name && path[1] == data2.name) + || (data2.jump && pathURL == admin.correctRouter(data2.jump)); + + listChildren2.each(function(index3, item3){ + var othis3 = $(item3) + ,data3 = getData(othis3) + ,matched3 = (path[0] == data1.name && path[1] == data2.name && path[2] == data3.name) + || (data3.jump && pathURL == admin.correctRouter(data3.jump)) + + if(matched3){ + var selected = data3.list[0] ? SIDE_NAV_ITEMD : THIS; + othis3.addClass(selected).siblings().removeClass(selected); //标记选择器 + return false; + } + + }); + + if(matched2){ + var selected = data2.list[0] ? SIDE_NAV_ITEMD : THIS; + othis2.addClass(selected).siblings().removeClass(selected); //标记选择器 + return false + } + + }); + + if(matched1){ + var selected = data1.list[0] ? SIDE_NAV_ITEMD : THIS; + othis1.addClass(selected).siblings().removeClass(selected); //标记选择器 + return false; + } + + }); + } + + //重置状态 + sideMenu.find('.'+ THIS).removeClass(THIS); + + //移动端点击菜单时自动收缩 + if(admin.screen() < 2) admin.sideFlexible(); + + //开始捕获 + matchMenu(sideMenu.children('li')); + }); + + //侧边导航点击事件 + element.on('nav(layadmin-system-side-menu)', function(elem){ + if(elem.siblings('.layui-nav-child')[0] && container.hasClass(SIDE_SHRINK)){ + admin.sideFlexible('spread'); + layer.close(elem.data('index')); + }; + admin.tabsPage.type = 'nav'; + }); + + //选项卡的更多操作 + element.on('nav(layadmin-pagetabs-nav)', function(elem){ + var dd = elem.parent(); + dd.removeClass(THIS); + dd.parent().removeClass(SHOW); + }); + + //同步路由 + var setThisRouter = function(othis){ + var layid = othis.attr('lay-id') + ,attr = othis.attr('lay-attr') + ,index = othis.index(); + + location.hash = layid === setter.entry ? '/' : (attr || '/'); + admin.tabsBodyChange(index); + } + ,TABS_HEADER = '#LAY_app_tabsheader>li'; + + //页面标签点击 + $body.on('click', TABS_HEADER, function(){ + var othis = $(this) + ,index = othis.index(); + + admin.tabsPage.type = 'tab'; + admin.tabsPage.index = index; + + //如果是iframe类型的标签页 + if(othis.attr('lay-attr') === 'iframe'){ + return admin.tabsBodyChange(index); + }; + + + setThisRouter(othis); //同步路由 + admin.runResize(); //执行resize事件,如果存在的话 + admin.resizeTable(); //重置当前主体区域的表格尺寸 + }); + + // tabspage 删除 + element.on('tabDelete(layadmin-layout-tabs)', function(obj){ + var othis = $(TABS_HEADER+ '.layui-this'); + + obj.index && admin.tabsBody(obj.index).remove(); + setThisRouter(othis); + + //移除resize事件 + admin.delResize(); + }); + + //页面跳转 + $body.on('click', '*[lay-href]', function(){ + var othis = $(this) + ,href = othis.attr('lay-href') + ,router = layui.router(); + + admin.tabsPage.elem = othis; + //admin.prevRouter[router.path[0]] = router.href; //记录上一次各菜单的路由信息 + + //执行跳转 + location.hash = admin.correctRouter(href); + + //如果为当前页,则执行刷新 + if(admin.correctRouter(href) === router.href){ + admin.events.refresh(); + } + }); + + //点击事件 + $body.on('click', '*[layadmin-event]', function(){ + var othis = $(this) + ,attrEvent = othis.attr('layadmin-event'); + events[attrEvent] && events[attrEvent].call(this, othis); + }); + + //tips + $body.on('mouseenter', '*[lay-tips]', function(){ + var othis = $(this); + + if(othis.parent().hasClass('layui-nav-item') && !container.hasClass(SIDE_SHRINK)) return; + + var tips = othis.attr('lay-tips') + ,offset = othis.attr('lay-offset') + ,direction = othis.attr('lay-direction') + ,index = layer.tips(tips, this, { + tips: direction || 1 + ,time: -1 + ,success: function(layero, index){ + if(offset){ + layero.css('margin-left', offset + 'px'); + } + } + }); + othis.data('index', index); + }).on('mouseleave', '*[lay-tips]', function(){ + layer.close($(this).data('index')); + }); + + //窗口resize事件 + var resizeSystem = layui.data.resizeSystem = function(){ + //layer.close(events.note.index); + layer.closeAll('tips'); + + if(!resizeSystem.lock){ + setTimeout(function(){ + admin.sideFlexible(admin.screen() < 2 ? '' : 'spread'); + delete resizeSystem.lock; + }, 100); + } + + resizeSystem.lock = true; + } + $win.on('resize', layui.data.resizeSystem); + + + //设置组件全局 token + ;!function(){ + var request = setter.request; + if(request.tokenName){ + var obj = {}; + obj[request.tokenName] = layui.data(setter.tableName)[request.tokenName] || '' + + //table + table.set({ + headers: obj, //通过 request 头传递 + where: obj //通过参数传递 + }); + //upload + upload.set({ + headers: obj, //通过 request 头传递 + data: obj //通过参数传递 + }); + } + }(); + + + //接口输出 + exports('admin', admin); +}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/echarts.js b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/echarts.js new file mode 100644 index 00000000..7af448cd --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/echarts.js @@ -0,0 +1,39 @@ +!function(e){var t,i;!function(){function e(e,t){if(!t)return e;if(0===e.indexOf(".")){var i=t.split("/"),n=e.split("/"),a=i.length-1,o=n.length,r=0,s=0;e:for(var l=0;o>l;l++)switch(n[l]){case"..":if(!(a>r))break e;r++,s++;break;case".":s++;break;default:break e}return i.length=a-r,n=n.slice(s),i.concat(n).join("/")}return e}function n(t){function i(i,r){if("string"==typeof i){var s=n[i];return s||(s=o(e(i,t)),n[i]=s),s}i instanceof Array&&(r=r||function(){},r.apply(this,a(i,r,t)))}var n={};return i}function a(i,n,a){for(var s=[],l=r[a],h=0,m=Math.min(i.length,n.length);m>h;h++){var V,U=e(i[h],a);switch(U){case"require":V=l&&l.require||t;break;case"exports":V=l.exports;break;case"module":V=l;break;default:V=o(U)}s.push(V)}return s}function o(e){var t=r[e];if(!t)throw new Error("No "+e);if(!t.defined){var i=t.factory,n=i.apply(this,a(t.deps||[],i,e));"undefined"!=typeof n&&(t.exports=n),t.defined=1}return t.exports}var r={};i=function(e,t,i){r[e]={id:e,deps:t,factory:i,defined:0,exports:{},require:n(e)}},t=n("")}(),i("echarts",["echarts/echarts"],function(e){return e}),i("echarts/echarts",["require","./config","zrender/tool/util","zrender/tool/event","zrender/tool/env","zrender","zrender/config","./chart/island","./component/toolbox","./component","./component/title","./component/tooltip","./component/legend","./util/ecData","./chart","zrender/tool/color","./component/timeline","zrender/shape/Image","zrender/loadingEffect/Bar","zrender/loadingEffect/Bubble","zrender/loadingEffect/DynamicLine","zrender/loadingEffect/Ring","zrender/loadingEffect/Spin","zrender/loadingEffect/Whirling","./theme/macarons","./theme/infographic"],function(e){function t(){r.Dispatcher.call(this)}function i(e){e.innerHTML="",this._themeConfig={},this.dom=e,this._connected=!1,this._status={dragIn:!1,dragOut:!1,needRefresh:!1},this._curEventType=!1,this._chartList=[],this._messageCenter=new t,this._messageCenterOutSide=new t,this.resize=this.resize(),this._init()}function n(e,t,i,n,a){for(var o=e._chartList,r=o.length;r--;){var s=o[r];"function"==typeof s[t]&&s[t](i,n,a)}}var a=e("./config"),o=e("zrender/tool/util"),r=e("zrender/tool/event"),s={},l=e("zrender/tool/env").canvasSupported,h=new Date-0,m={},V="_echarts_instance_";s.version="2.2.7",s.dependencies={zrender:"2.1.1"},s.init=function(t,n){var a=e("zrender");a.version.replace(".","")-0r;r++){var l=d[r],h=U[l];o[h]="_on"+l.toLowerCase(),i.on(h,this._onzrevent)}this.chart={},this.component={};var m=e("./chart/island");this._island=new m(this._themeConfig,this._messageCenter,i,{},this),this.chart.island=this._island;var V=e("./component/toolbox");this._toolbox=new V(this._themeConfig,this._messageCenter,i,{},this),this.component.toolbox=this._toolbox;var p=e("./component");p.define("title",e("./component/title")),p.define("tooltip",e("./component/tooltip")),p.define("legend",e("./component/legend")),(0===i.getWidth()||0===i.getHeight())&&console.error("Dom’s width & height should be ready before init.")},__onevent:function(e){e.__echartsId=e.__echartsId||this.id;var t=e.__echartsId===this.id;switch(this._curEventType||(this._curEventType=e.type),e.type){case a.EVENT.LEGEND_SELECTED:this._onlegendSelected(e);break;case a.EVENT.DATA_ZOOM:if(!t){var i=this.component.dataZoom;i&&(i.silence(!0),i.absoluteZoom(e.zoom),i.silence(!1))}this._ondataZoom(e);break;case a.EVENT.DATA_RANGE:t&&this._ondataRange(e);break;case a.EVENT.MAGIC_TYPE_CHANGED:if(!t){var n=this.component.toolbox;n&&(n.silence(!0),n.setMagicType(e.magicType),n.silence(!1))}this._onmagicTypeChanged(e);break;case a.EVENT.DATA_VIEW_CHANGED:t&&this._ondataViewChanged(e);break;case a.EVENT.TOOLTIP_HOVER:t&&this._tooltipHover(e);break;case a.EVENT.RESTORE:this._onrestore();break;case a.EVENT.REFRESH:t&&this._onrefresh(e);break;case a.EVENT.TOOLTIP_IN_GRID:case a.EVENT.TOOLTIP_OUT_GRID:if(t){if(this._connected){var o=this.component.grid;o&&(e.x=(e.event.zrenderX-o.getX())/o.getWidth(),e.y=(e.event.zrenderY-o.getY())/o.getHeight())}}else{var o=this.component.grid;o&&this._zr.trigger("mousemove",{connectTrigger:!0,zrenderX:o.getX()+e.x*o.getWidth(),zrenderY:o.getY()+e.y*o.getHeight()})}}if(this._connected&&t&&this._curEventType===e.type){for(var r in this._connected)this._connected[r].connectedEventHandler(e);this._curEventType=null}(!t||!this._connected&&t)&&(this._curEventType=null)},_onclick:function(e){if(n(this,"onclick",e),e.target){var t=this._eventPackage(e.target);t&&null!=t.seriesIndex&&this._messageCenter.dispatch(a.EVENT.CLICK,e.event,t,this)}},_ondblclick:function(e){if(n(this,"ondblclick",e),e.target){var t=this._eventPackage(e.target);t&&null!=t.seriesIndex&&this._messageCenter.dispatch(a.EVENT.DBLCLICK,e.event,t,this)}},_onmouseover:function(e){if(e.target){var t=this._eventPackage(e.target);t&&null!=t.seriesIndex&&this._messageCenter.dispatch(a.EVENT.HOVER,e.event,t,this)}},_onmouseout:function(e){if(e.target){var t=this._eventPackage(e.target);t&&null!=t.seriesIndex&&this._messageCenter.dispatch(a.EVENT.MOUSEOUT,e.event,t,this)}},_ondragstart:function(e){this._status={dragIn:!1,dragOut:!1,needRefresh:!1},n(this,"ondragstart",e)},_ondragenter:function(e){n(this,"ondragenter",e)},_ondragover:function(e){n(this,"ondragover",e)},_ondragleave:function(e){n(this,"ondragleave",e)},_ondrop:function(e){n(this,"ondrop",e,this._status),this._island.ondrop(e,this._status)},_ondragend:function(e){if(n(this,"ondragend",e,this._status),this._timeline&&this._timeline.ondragend(e,this._status),this._island.ondragend(e,this._status),this._status.needRefresh){this._syncBackupData(this._option);var t=this._messageCenter;t.dispatch(a.EVENT.DATA_CHANGED,e.event,this._eventPackage(e.target),this),t.dispatch(a.EVENT.REFRESH,null,null,this)}},_onlegendSelected:function(e){this._status.needRefresh=!1,n(this,"onlegendSelected",e,this._status),this._status.needRefresh&&this._messageCenter.dispatch(a.EVENT.REFRESH,null,null,this)},_ondataZoom:function(e){this._status.needRefresh=!1,n(this,"ondataZoom",e,this._status),this._status.needRefresh&&this._messageCenter.dispatch(a.EVENT.REFRESH,null,null,this)},_ondataRange:function(e){this._clearEffect(),this._status.needRefresh=!1,n(this,"ondataRange",e,this._status),this._status.needRefresh&&this._zr.refreshNextFrame()},_onmagicTypeChanged:function(){this._clearEffect(),this._render(this._toolbox.getMagicOption())},_ondataViewChanged:function(e){this._syncBackupData(e.option),this._messageCenter.dispatch(a.EVENT.DATA_CHANGED,null,e,this),this._messageCenter.dispatch(a.EVENT.REFRESH,null,null,this)},_tooltipHover:function(e){var t=[];n(this,"ontooltipHover",e,t)},_onrestore:function(){this.restore()},_onrefresh:function(e){this._refreshInside=!0,this.refresh(e),this._refreshInside=!1},_syncBackupData:function(e){this.component.dataZoom&&this.component.dataZoom.syncBackupData(e)},_eventPackage:function(t){if(t){var i=e("./util/ecData"),n=i.get(t,"seriesIndex"),a=i.get(t,"dataIndex");return a=-1!=n&&this.component.dataZoom?this.component.dataZoom.getRealDataIndex(n,a):a,{seriesIndex:n,seriesName:(i.get(t,"series")||{}).name,dataIndex:a,data:i.get(t,"data"),name:i.get(t,"name"),value:i.get(t,"value"),special:i.get(t,"special")}}},_noDataCheck:function(e){for(var t=e.series,i=0,n=t.length;n>i;i++)if(t[i].type==a.CHART_TYPE_MAP||t[i].data&&t[i].data.length>0||t[i].markPoint&&t[i].markPoint.data&&t[i].markPoint.data.length>0||t[i].markLine&&t[i].markLine.data&&t[i].markLine.data.length>0||t[i].nodes&&t[i].nodes.length>0||t[i].links&&t[i].links.length>0||t[i].matrix&&t[i].matrix.length>0||t[i].eventList&&t[i].eventList.length>0)return!1;var o=this._option&&this._option.noDataLoadingOption||this._themeConfig.noDataLoadingOption||a.noDataLoadingOption||{text:this._option&&this._option.noDataText||this._themeConfig.noDataText||a.noDataText,effect:this._option&&this._option.noDataEffect||this._themeConfig.noDataEffect||a.noDataEffect};return this.clear(),this.showLoading(o),!0},_render:function(t){if(this._mergeGlobalConifg(t),!this._noDataCheck(t)){var i=t.backgroundColor;if(i)if(l||-1==i.indexOf("rgba"))this.dom.style.backgroundColor=i;else{var n=i.split(",");this.dom.style.filter="alpha(opacity="+100*n[3].substring(0,n[3].lastIndexOf(")"))+")",n.length=3,n[0]=n[0].replace("a",""),this.dom.style.backgroundColor=n.join(",")+")"}this._zr.clearAnimation(),this._chartList=[];var o=e("./chart"),r=e("./component");(t.xAxis||t.yAxis)&&(t.grid=t.grid||{},t.dataZoom=t.dataZoom||{});for(var s,h,m,V=["title","legend","tooltip","dataRange","roamController","grid","dataZoom","xAxis","yAxis","polar"],U=0,d=V.length;d>U;U++)h=V[U],m=this.component[h],t[h]?(m?m.refresh&&m.refresh(t):(s=r.get(/^[xy]Axis$/.test(h)?"axis":h),m=new s(this._themeConfig,this._messageCenter,this._zr,t,this,h),this.component[h]=m),this._chartList.push(m)):m&&(m.dispose(),this.component[h]=null,delete this.component[h]);for(var p,c,u,y={},U=0,d=t.series.length;d>U;U++)c=t.series[U].type,c?y[c]||(y[c]=!0,p=o.get(c),p?(this.chart[c]?(u=this.chart[c],u.refresh(t)):u=new p(this._themeConfig,this._messageCenter,this._zr,t,this),this._chartList.push(u),this.chart[c]=u):console.error(c+" has not been required.")):console.error("series["+U+"] chart type has not been defined.");for(c in this.chart)c==a.CHART_TYPE_ISLAND||y[c]||(this.chart[c].dispose(),this.chart[c]=null,delete this.chart[c]);this.component.grid&&this.component.grid.refixAxisShape(this.component),this._island.refresh(t),this._toolbox.refresh(t),t.animation&&!t.renderAsImage?this._zr.refresh():this._zr.render();var g="IMG"+this.id,b=document.getElementById(g);t.renderAsImage&&l?(b?b.src=this.getDataURL(t.renderAsImage):(b=this.getImage(t.renderAsImage),b.id=g,b.style.position="absolute",b.style.left=0,b.style.top=0,this.dom.firstChild.appendChild(b)),this.un(),this._zr.un(),this._disposeChartList(),this._zr.clear()):b&&b.parentNode.removeChild(b),b=null,this._option=t}},restore:function(){this._clearEffect(),this._option=o.clone(this._optionRestore),this._disposeChartList(),this._island.clear(),this._toolbox.reset(this._option,!0),this._render(this._option)},refresh:function(e){this._clearEffect(),e=e||{};var t=e.option;!this._refreshInside&&t&&(t=this.getOption(),o.merge(t,e.option,!0),o.merge(this._optionRestore,e.option,!0),this._toolbox.reset(t)),this._island.refresh(t),this._toolbox.refresh(t),this._zr.clearAnimation();for(var i=0,n=this._chartList.length;n>i;i++)this._chartList[i].refresh&&this._chartList[i].refresh(t);this.component.grid&&this.component.grid.refixAxisShape(this.component),this._zr.refresh()},_disposeChartList:function(){this._clearEffect(),this._zr.clearAnimation();for(var e=this._chartList.length;e--;){var t=this._chartList[e];if(t){var i=t.type;this.chart[i]&&delete this.chart[i],this.component[i]&&delete this.component[i],t.dispose&&t.dispose()}}this._chartList=[]},_mergeGlobalConifg:function(t){for(var i=["backgroundColor","calculable","calculableColor","calculableHolderColor","nameConnector","valueConnector","animation","animationThreshold","animationDuration","animationDurationUpdate","animationEasing","addDataAnimation","symbolList","DRAG_ENABLE_TIME"],n=i.length;n--;){var o=i[n];null==t[o]&&(t[o]=null!=this._themeConfig[o]?this._themeConfig[o]:a[o])}var r=t.color;r&&r.length||(r=this._themeConfig.color||a.color),this._zr.getColor=function(t){var i=e("zrender/tool/color");return i.getColor(t,r)},l||(t.animation=!1,t.addDataAnimation=!1)},setOption:function(e,t){return e.timeline?this._setTimelineOption(e):this._setOption(e,t)},_setOption:function(e,t,i){return!t&&this._option?this._option=o.merge(this.getOption(),o.clone(e),!0):(this._option=o.clone(e),!i&&this._timeline&&this._timeline.dispose()),this._optionRestore=o.clone(this._option),this._option.series&&0!==this._option.series.length?(this.component.dataZoom&&(this._option.dataZoom||this._option.toolbox&&this._option.toolbox.feature&&this._option.toolbox.feature.dataZoom&&this._option.toolbox.feature.dataZoom.show)&&this.component.dataZoom.syncOption(this._option),this._toolbox.reset(this._option),this._render(this._option),this):void this._zr.clear()},getOption:function(){function e(e){var n=i._optionRestore[e];if(n)if(n instanceof Array)for(var a=n.length;a--;)t[e][a].data=o.clone(n[a].data);else t[e].data=o.clone(n.data)}var t=o.clone(this._option),i=this;return e("xAxis"),e("yAxis"),e("series"),t},setSeries:function(e,t){return t?(this._option.series=e,this.setOption(this._option,t)):this.setOption({series:e}),this},getSeries:function(){return this.getOption().series},_setTimelineOption:function(t){this._timeline&&this._timeline.dispose();var i=e("./component/timeline"),n=new i(this._themeConfig,this._messageCenter,this._zr,t,this);return this._timeline=n,this.component.timeline=this._timeline,this},addData:function(e,t,i,n,r){function s(){if(V._zr){V._zr.clearAnimation();for(var e=0,t=X.length;t>e;e++)X[e].motionlessOnce=h.addDataAnimation&&X[e].addDataAnimation;V._messageCenter.dispatch(a.EVENT.REFRESH,null,{option:h},V)}}for(var l=e instanceof Array?e:[[e,t,i,n,r]],h=this.getOption(),m=this._optionRestore,V=this,U=0,d=l.length;d>U;U++){e=l[U][0],t=l[U][1],i=l[U][2],n=l[U][3],r=l[U][4];var p=m.series[e],c=i?"unshift":"push",u=i?"pop":"shift";if(p){var y=p.data,g=h.series[e].data;if(y[c](t),g[c](t),n||(y[u](),t=g[u]()),null!=r){var b,f;if(p.type===a.CHART_TYPE_PIE&&(b=m.legend)&&(f=b.data)){var k=h.legend.data;if(f[c](r),k[c](r),!n){var x=o.indexOf(f,t.name);-1!=x&&f.splice(x,1),x=o.indexOf(k,t.name),-1!=x&&k.splice(x,1)}}else if(null!=m.xAxis&&null!=m.yAxis){var _,L,W=p.xAxisIndex||0;(null==m.xAxis[W].type||"category"===m.xAxis[W].type)&&(_=m.xAxis[W].data,L=h.xAxis[W].data,_[c](r),L[c](r),n||(_[u](),L[u]())),W=p.yAxisIndex||0,"category"===m.yAxis[W].type&&(_=m.yAxis[W].data,L=h.yAxis[W].data,_[c](r),L[c](r),n||(_[u](),L[u]()))}}this._option.series[e].data=h.series[e].data}}this._zr.clearAnimation();for(var X=this._chartList,v=0,w=function(){v--,0===v&&s()},U=0,d=X.length;d>U;U++)h.addDataAnimation&&X[U].addDataAnimation&&(v++,X[U].addDataAnimation(l,w));return this.component.dataZoom&&this.component.dataZoom.syncOption(h),this._option=h,h.addDataAnimation||setTimeout(s,0),this},addMarkPoint:function(e,t){return this._addMark(e,t,"markPoint")},addMarkLine:function(e,t){return this._addMark(e,t,"markLine")},_addMark:function(e,t,i){var n,a=this._option.series;if(a&&(n=a[e])){var r=this._optionRestore.series,s=r[e],l=n[i],h=s[i];l=n[i]=l||{data:[]},h=s[i]=h||{data:[]};for(var m in t)"data"===m?(l.data=l.data.concat(t.data),h.data=h.data.concat(t.data)):"object"!=typeof t[m]||null==l[m]?l[m]=h[m]=t[m]:(o.merge(l[m],t[m],!0),o.merge(h[m],t[m],!0));var V=this.chart[n.type];V&&V.addMark(e,t,i)}return this},delMarkPoint:function(e,t){return this._delMark(e,t,"markPoint")},delMarkLine:function(e,t){return this._delMark(e,t,"markLine")},_delMark:function(e,t,i){var n,a,o,r=this._option.series;if(!(r&&(n=r[e])&&(a=n[i])&&(o=a.data)))return this;t=t.split(" > ");for(var s=-1,l=0,h=o.length;h>l;l++){var m=o[l];if(m instanceof Array){if(m[0].name===t[0]&&m[1].name===t[1]){s=l;break}}else if(m.name===t[0]){s=l;break}}if(s>-1){o.splice(s,1),this._optionRestore.series[e][i].data.splice(s,1);var V=this.chart[n.type];V&&V.delMark(e,t.join(" > "),i)}return this},getDom:function(){return this.dom},getZrender:function(){return this._zr},getDataURL:function(e){if(!l)return"";if(0===this._chartList.length){var t="IMG"+this.id,i=document.getElementById(t);if(i)return i.src}var n=this.component.tooltip;switch(n&&n.hideTip(),e){case"jpeg":break;default:e="png"}var a=this._option.backgroundColor;return a&&"rgba(0,0,0,0)"===a.replace(" ","")&&(a="#fff"),this._zr.toDataURL("image/"+e,a)},getImage:function(e){var t=this._optionRestore.title,i=document.createElement("img");return i.src=this.getDataURL(e),i.title=t&&t.text||"ECharts",i},getConnectedDataURL:function(t){if(!this.isConnected())return this.getDataURL(t);var i=this.dom,n={self:{img:this.getDataURL(t),left:i.offsetLeft,top:i.offsetTop,right:i.offsetLeft+i.offsetWidth,bottom:i.offsetTop+i.offsetHeight}},a=n.self.left,o=n.self.top,r=n.self.right,s=n.self.bottom;for(var l in this._connected)i=this._connected[l].getDom(),n[l]={img:this._connected[l].getDataURL(t),left:i.offsetLeft,top:i.offsetTop,right:i.offsetLeft+i.offsetWidth,bottom:i.offsetTop+i.offsetHeight},a=Math.min(a,n[l].left),o=Math.min(o,n[l].top),r=Math.max(r,n[l].right),s=Math.max(s,n[l].bottom);var h=document.createElement("div");h.style.position="absolute",h.style.left="-4000px",h.style.width=r-a+"px",h.style.height=s-o+"px",document.body.appendChild(h);var m=e("zrender").init(h),V=e("zrender/shape/Image");for(var l in n)m.addShape(new V({style:{x:n[l].left-a,y:n[l].top-o,image:n[l].img}}));m.render();var U=this._option.backgroundColor;U&&"rgba(0,0,0,0)"===U.replace(/ /g,"")&&(U="#fff");var d=m.toDataURL("image/png",U);return setTimeout(function(){m.dispose(),h.parentNode.removeChild(h),h=null},100),d},getConnectedImage:function(e){var t=this._optionRestore.title,i=document.createElement("img");return i.src=this.getConnectedDataURL(e),i.title=t&&t.text||"ECharts",i},on:function(e,t){return this._messageCenterOutSide.bind(e,t,this),this},un:function(e,t){return this._messageCenterOutSide.unbind(e,t),this},connect:function(e){if(!e)return this;if(this._connected||(this._connected={}),e instanceof Array)for(var t=0,i=e.length;i>t;t++)this._connected[e[t].id]=e[t];else this._connected[e.id]=e;return this},disConnect:function(e){if(!e||!this._connected)return this;if(e instanceof Array)for(var t=0,i=e.length;i>t;t++)delete this._connected[e[t].id];else delete this._connected[e.id];for(var n in this._connected)return this;return this._connected=!1,this},connectedEventHandler:function(e){e.__echartsId!=this.id&&this._onevent(e)},isConnected:function(){return!!this._connected},showLoading:function(t){var i={bar:e("zrender/loadingEffect/Bar"),bubble:e("zrender/loadingEffect/Bubble"),dynamicLine:e("zrender/loadingEffect/DynamicLine"),ring:e("zrender/loadingEffect/Ring"),spin:e("zrender/loadingEffect/Spin"),whirling:e("zrender/loadingEffect/Whirling")};this._toolbox.hideDataView(),t=t||{};var n=t.textStyle||{};t.textStyle=n;var r=o.merge(o.merge(o.clone(n),this._themeConfig.textStyle),a.textStyle);n.textFont=r.fontStyle+" "+r.fontWeight+" "+r.fontSize+"px "+r.fontFamily,n.text=t.text||this._option&&this._option.loadingText||this._themeConfig.loadingText||a.loadingText,null!=t.x&&(n.x=t.x),null!=t.y&&(n.y=t.y),t.effectOption=t.effectOption||{},t.effectOption.textStyle=n;var s=t.effect;return("string"==typeof s||null==s)&&(s=i[t.effect||this._option&&this._option.loadingEffect||this._themeConfig.loadingEffect||a.loadingEffect]||i.spin),this._zr.showLoading(new s(t.effectOption)),this},hideLoading:function(){return this._zr.hideLoading(),this},setTheme:function(t){if(t){if("string"==typeof t)switch(t){case"macarons":t=e("./theme/macarons");break;case"infographic":t=e("./theme/infographic");break;default:t={}}else t=t||{};this._themeConfig=t}if(!l){var i=this._themeConfig.textStyle;i&&i.fontFamily&&i.fontFamily2&&(i.fontFamily=i.fontFamily2),i=a.textStyle,i.fontFamily=i.fontFamily2}this._timeline&&this._timeline.setTheme(!0),this._optionRestore&&this.restore()},resize:function(){var e=this;return function(){if(e._clearEffect(),e._zr.resize(),e._option&&e._option.renderAsImage&&l)return e._render(e._option),e;e._zr.clearAnimation(),e._island.resize(),e._toolbox.resize(),e._timeline&&e._timeline.resize();for(var t=0,i=e._chartList.length;i>t;t++)e._chartList[t].resize&&e._chartList[t].resize();return e.component.grid&&e.component.grid.refixAxisShape(e.component),e._zr.refresh(),e._messageCenter.dispatch(a.EVENT.RESIZE,null,null,e),e}},_clearEffect:function(){this._zr.modLayer(a.EFFECT_ZLEVEL,{motionBlur:!1}),this._zr.painter.clearLayer(a.EFFECT_ZLEVEL)},clear:function(){return this._disposeChartList(),this._zr.clear(),this._option={},this._optionRestore={},this.dom.style.backgroundColor=null,this},dispose:function(){var e=this.dom.getAttribute(V);e&&delete m[e],this._island.dispose(),this._toolbox.dispose(),this._timeline&&this._timeline.dispose(),this._messageCenter.unbind(),this.clear(),this._zr.dispose(),this._zr=null}},s}),i("echarts/config",[],function(){var e={CHART_TYPE_LINE:"line",CHART_TYPE_BAR:"bar",CHART_TYPE_SCATTER:"scatter",CHART_TYPE_PIE:"pie",CHART_TYPE_RADAR:"radar",CHART_TYPE_VENN:"venn",CHART_TYPE_TREEMAP:"treemap",CHART_TYPE_TREE:"tree",CHART_TYPE_MAP:"map",CHART_TYPE_K:"k",CHART_TYPE_ISLAND:"island",CHART_TYPE_FORCE:"force",CHART_TYPE_CHORD:"chord",CHART_TYPE_GAUGE:"gauge",CHART_TYPE_FUNNEL:"funnel",CHART_TYPE_EVENTRIVER:"eventRiver",CHART_TYPE_WORDCLOUD:"wordCloud",CHART_TYPE_HEATMAP:"heatmap",COMPONENT_TYPE_TITLE:"title",COMPONENT_TYPE_LEGEND:"legend",COMPONENT_TYPE_DATARANGE:"dataRange",COMPONENT_TYPE_DATAVIEW:"dataView",COMPONENT_TYPE_DATAZOOM:"dataZoom",COMPONENT_TYPE_TOOLBOX:"toolbox",COMPONENT_TYPE_TOOLTIP:"tooltip",COMPONENT_TYPE_GRID:"grid",COMPONENT_TYPE_AXIS:"axis",COMPONENT_TYPE_POLAR:"polar",COMPONENT_TYPE_X_AXIS:"xAxis",COMPONENT_TYPE_Y_AXIS:"yAxis",COMPONENT_TYPE_AXIS_CATEGORY:"categoryAxis",COMPONENT_TYPE_AXIS_VALUE:"valueAxis",COMPONENT_TYPE_TIMELINE:"timeline",COMPONENT_TYPE_ROAMCONTROLLER:"roamController",backgroundColor:"rgba(0,0,0,0)",color:["#ff7f50","#87cefa","#da70d6","#32cd32","#6495ed","#ff69b4","#ba55d3","#cd5c5c","#ffa500","#40e0d0","#1e90ff","#ff6347","#7b68ee","#00fa9a","#ffd700","#6699FF","#ff6666","#3cb371","#b8860b","#30e0e0"],markPoint:{clickable:!0,symbol:"pin",symbolSize:10,large:!1,effect:{show:!1,loop:!0,period:15,type:"scale",scaleSize:2,bounceDistance:10},itemStyle:{normal:{borderWidth:2,label:{show:!0,position:"inside"}},emphasis:{label:{show:!0}}}},markLine:{clickable:!0,symbol:["circle","arrow"],symbolSize:[2,4],smoothness:.2,precision:2,effect:{show:!1,loop:!0,period:15,scaleSize:2},bundling:{enable:!1,maxTurningAngle:45},itemStyle:{normal:{borderWidth:1.5,label:{show:!0,position:"end"},lineStyle:{type:"dashed"}},emphasis:{label:{show:!1},lineStyle:{}}}},textStyle:{decoration:"none",fontFamily:"Arial, Verdana, sans-serif",fontFamily2:"微软雅黑",fontSize:12,fontStyle:"normal",fontWeight:"normal"},EVENT:{REFRESH:"refresh",RESTORE:"restore",RESIZE:"resize",CLICK:"click",DBLCLICK:"dblclick",HOVER:"hover",MOUSEOUT:"mouseout",DATA_CHANGED:"dataChanged",DATA_ZOOM:"dataZoom",DATA_RANGE:"dataRange",DATA_RANGE_SELECTED:"dataRangeSelected",DATA_RANGE_HOVERLINK:"dataRangeHoverLink",LEGEND_SELECTED:"legendSelected",LEGEND_HOVERLINK:"legendHoverLink",MAP_SELECTED:"mapSelected",PIE_SELECTED:"pieSelected",MAGIC_TYPE_CHANGED:"magicTypeChanged",DATA_VIEW_CHANGED:"dataViewChanged",TIMELINE_CHANGED:"timelineChanged",MAP_ROAM:"mapRoam",FORCE_LAYOUT_END:"forceLayoutEnd",TOOLTIP_HOVER:"tooltipHover",TOOLTIP_IN_GRID:"tooltipInGrid",TOOLTIP_OUT_GRID:"tooltipOutGrid",ROAMCONTROLLER:"roamController"},DRAG_ENABLE_TIME:120,EFFECT_ZLEVEL:10,effectBlendAlpha:.95,symbolList:["circle","rectangle","triangle","diamond","emptyCircle","emptyRectangle","emptyTriangle","emptyDiamond"],loadingEffect:"spin",loadingText:"数据读取中...",noDataEffect:"bubble",noDataText:"暂无数据",calculable:!1,calculableColor:"rgba(255,165,0,0.6)",calculableHolderColor:"#ccc",nameConnector:" & ",valueConnector:": ",animation:!0,addDataAnimation:!0,animationThreshold:2e3,animationDuration:2e3,animationDurationUpdate:500,animationEasing:"ExponentialOut"};return e}),i("zrender/tool/util",["require","../dep/excanvas"],function(e){function t(e){return e&&1===e.nodeType&&"string"==typeof e.nodeName}function i(e){if("object"==typeof e&&null!==e){var n=e;if(e instanceof Array){n=[];for(var a=0,o=e.length;o>a;a++)n[a]=i(e[a])}else if(!y[g.call(e)]&&!t(e)){n={};for(var r in e)e.hasOwnProperty(r)&&(n[r]=i(e[r]))}return n}return e}function n(e,i,n,o){if(i.hasOwnProperty(n)){var r=e[n];"object"!=typeof r||y[g.call(r)]||t(r)?!o&&n in e||(e[n]=i[n]):a(e[n],i[n],o)}}function a(e,t,i){for(var a in t)n(e,t,a,i);return e}function o(){if(!U)if(e("../dep/excanvas"),window.G_vmlCanvasManager){var t=document.createElement("div");t.style.position="absolute",t.style.top="-1000px",document.body.appendChild(t),U=G_vmlCanvasManager.initElement(t).getContext("2d")}else U=document.createElement("canvas").getContext("2d");return U}function r(e,t){if(e.indexOf)return e.indexOf(t);for(var i=0,n=e.length;n>i;i++)if(e[i]===t)return i;return-1}function s(e,t){function i(){}var n=e.prototype;i.prototype=t.prototype,e.prototype=new i;for(var a in n)e.prototype[a]=n[a];e.constructor=e}function l(e,t,i){if(e&&t)if(e.forEach&&e.forEach===p)e.forEach(t,i);else if(e.length===+e.length)for(var n=0,a=e.length;a>n;n++)t.call(i,e[n],n,e);else for(var o in e)e.hasOwnProperty(o)&&t.call(i,e[o],o,e)}function h(e,t,i){if(e&&t){if(e.map&&e.map===c)return e.map(t,i);for(var n=[],a=0,o=e.length;o>a;a++)n.push(t.call(i,e[a],a,e));return n}}function m(e,t,i){if(e&&t){if(e.filter&&e.filter===u)return e.filter(t,i);for(var n=[],a=0,o=e.length;o>a;a++)t.call(i,e[a],a,e)&&n.push(e[a]);return n}}function V(e,t){return function(){e.apply(t,arguments)}}var U,d=Array.prototype,p=d.forEach,c=d.map,u=d.filter,y={"[object Function]":1,"[object RegExp]":1,"[object Date]":1,"[object Error]":1,"[object CanvasGradient]":1},g=Object.prototype.toString;return{inherits:s,clone:i,merge:a,getContext:o,indexOf:r,each:l,map:h,filter:m,bind:V}}),i("zrender/tool/event",["require","../mixin/Eventful"],function(e){"use strict";function t(e){return"undefined"!=typeof e.zrenderX&&e.zrenderX||"undefined"!=typeof e.offsetX&&e.offsetX||"undefined"!=typeof e.layerX&&e.layerX||"undefined"!=typeof e.clientX&&e.clientX}function i(e){return"undefined"!=typeof e.zrenderY&&e.zrenderY||"undefined"!=typeof e.offsetY&&e.offsetY||"undefined"!=typeof e.layerY&&e.layerY||"undefined"!=typeof e.clientY&&e.clientY}function n(e){return"undefined"!=typeof e.zrenderDelta&&e.zrenderDelta||"undefined"!=typeof e.wheelDelta&&e.wheelDelta||"undefined"!=typeof e.detail&&-e.detail}var a=e("../mixin/Eventful"),o="function"==typeof window.addEventListener?function(e){e.preventDefault(),e.stopPropagation(),e.cancelBubble=!0}:function(e){e.returnValue=!1,e.cancelBubble=!0};return{getX:t,getY:i,getDelta:n,stop:o,Dispatcher:a}}),i("zrender/tool/env",[],function(){function e(e){var t=this.os={},i=this.browser={},n=e.match(/Web[kK]it[\/]{0,1}([\d.]+)/),a=e.match(/(Android);?[\s\/]+([\d.]+)?/),o=e.match(/(iPad).*OS\s([\d_]+)/),r=e.match(/(iPod)(.*OS\s([\d_]+))?/),s=!o&&e.match(/(iPhone\sOS)\s([\d_]+)/),l=e.match(/(webOS|hpwOS)[\s\/]([\d.]+)/),h=l&&e.match(/TouchPad/),m=e.match(/Kindle\/([\d.]+)/),V=e.match(/Silk\/([\d._]+)/),U=e.match(/(BlackBerry).*Version\/([\d.]+)/),d=e.match(/(BB10).*Version\/([\d.]+)/),p=e.match(/(RIM\sTablet\sOS)\s([\d.]+)/),c=e.match(/PlayBook/),u=e.match(/Chrome\/([\d.]+)/)||e.match(/CriOS\/([\d.]+)/),y=e.match(/Firefox\/([\d.]+)/),g=e.match(/MSIE ([\d.]+)/),b=n&&e.match(/Mobile\//)&&!u,f=e.match(/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/)&&!u,g=e.match(/MSIE\s([\d.]+)/);return(i.webkit=!!n)&&(i.version=n[1]),a&&(t.android=!0,t.version=a[2]),s&&!r&&(t.ios=t.iphone=!0,t.version=s[2].replace(/_/g,".")),o&&(t.ios=t.ipad=!0,t.version=o[2].replace(/_/g,".")),r&&(t.ios=t.ipod=!0,t.version=r[3]?r[3].replace(/_/g,"."):null),l&&(t.webos=!0,t.version=l[2]),h&&(t.touchpad=!0),U&&(t.blackberry=!0,t.version=U[2]),d&&(t.bb10=!0,t.version=d[2]),p&&(t.rimtabletos=!0,t.version=p[2]),c&&(i.playbook=!0),m&&(t.kindle=!0,t.version=m[1]),V&&(i.silk=!0,i.version=V[1]),!V&&t.android&&e.match(/Kindle Fire/)&&(i.silk=!0),u&&(i.chrome=!0,i.version=u[1]),y&&(i.firefox=!0,i.version=y[1]),g&&(i.ie=!0,i.version=g[1]),b&&(e.match(/Safari/)||t.ios)&&(i.safari=!0),f&&(i.webview=!0),g&&(i.ie=!0,i.version=g[1]),t.tablet=!!(o||c||a&&!e.match(/Mobile/)||y&&e.match(/Tablet/)||g&&!e.match(/Phone/)&&e.match(/Touch/)),t.phone=!(t.tablet||t.ipod||!(a||s||l||U||d||u&&e.match(/Android/)||u&&e.match(/CriOS\/([\d.]+)/)||y&&e.match(/Mobile/)||g&&e.match(/Touch/))),{browser:i,os:t,canvasSupported:document.createElement("canvas").getContext?!0:!1}}return e(navigator.userAgent)}),i("zrender",["zrender/zrender"],function(e){return e}),i("zrender/zrender",["require","./dep/excanvas","./tool/util","./tool/log","./tool/guid","./Handler","./Painter","./Storage","./animation/Animation","./tool/env"],function(e){function t(e){return function(){e._needsRefreshNextFrame&&e.refresh()}}e("./dep/excanvas");var i=e("./tool/util"),n=e("./tool/log"),a=e("./tool/guid"),o=e("./Handler"),r=e("./Painter"),s=e("./Storage"),l=e("./animation/Animation"),h={},m={};m.version="2.1.1",m.init=function(e){var t=new V(a(),e);return h[t.id]=t,t},m.dispose=function(e){if(e)e.dispose();else{for(var t in h)h[t].dispose();h={}}return m},m.getInstance=function(e){return h[e]},m.delInstance=function(e){return delete h[e],m};var V=function(i,n){this.id=i,this.env=e("./tool/env"),this.storage=new s,this.painter=new r(n,this.storage),this.handler=new o(n,this.storage,this.painter),this.animation=new l({stage:{update:t(this)}}),this.animation.start();var a=this;this.painter.refreshNextFrame=function(){a.refreshNextFrame()},this._needsRefreshNextFrame=!1;var a=this,h=this.storage,m=h.delFromMap;h.delFromMap=function(e){var t=h.get(e);a.stopAnimation(t),m.call(h,e)}};return V.prototype.getId=function(){return this.id},V.prototype.addShape=function(e){return this.addElement(e),this},V.prototype.addGroup=function(e){return this.addElement(e),this},V.prototype.delShape=function(e){return this.delElement(e),this},V.prototype.delGroup=function(e){return this.delElement(e),this},V.prototype.modShape=function(e,t){return this.modElement(e,t),this},V.prototype.modGroup=function(e,t){return this.modElement(e,t),this},V.prototype.addElement=function(e){return this.storage.addRoot(e),this._needsRefreshNextFrame=!0,this},V.prototype.delElement=function(e){return this.storage.delRoot(e),this._needsRefreshNextFrame=!0,this},V.prototype.modElement=function(e,t){return this.storage.mod(e,t),this._needsRefreshNextFrame=!0,this},V.prototype.modLayer=function(e,t){return this.painter.modLayer(e,t),this._needsRefreshNextFrame=!0,this},V.prototype.addHoverShape=function(e){return this.storage.addHover(e),this},V.prototype.render=function(e){return this.painter.render(e),this._needsRefreshNextFrame=!1,this},V.prototype.refresh=function(e){return this.painter.refresh(e),this._needsRefreshNextFrame=!1,this},V.prototype.refreshNextFrame=function(){return this._needsRefreshNextFrame=!0,this},V.prototype.refreshHover=function(e){return this.painter.refreshHover(e),this},V.prototype.refreshShapes=function(e,t){return this.painter.refreshShapes(e,t),this},V.prototype.resize=function(){return this.painter.resize(),this},V.prototype.animate=function(e,t,a){var o=this;if("string"==typeof e&&(e=this.storage.get(e)),e){var r;if(t){for(var s=t.split("."),l=e,h=0,m=s.length;m>h;h++)l&&(l=l[s[h]]);l&&(r=l)}else r=e;if(!r)return void n('Property "'+t+'" is not existed in element '+e.id); + +null==e.__animators&&(e.__animators=[]);var V=e.__animators,U=this.animation.animate(r,{loop:a}).during(function(){o.modShape(e)}).done(function(){var t=i.indexOf(e.__animators,U);t>=0&&V.splice(t,1)});return V.push(U),U}n("Element not existed")},V.prototype.stopAnimation=function(e){if(e.__animators){for(var t=e.__animators,i=t.length,n=0;i>n;n++)t[n].stop();t.length=0}return this},V.prototype.clearAnimation=function(){return this.animation.clear(),this},V.prototype.showLoading=function(e){return this.painter.showLoading(e),this},V.prototype.hideLoading=function(){return this.painter.hideLoading(),this},V.prototype.getWidth=function(){return this.painter.getWidth()},V.prototype.getHeight=function(){return this.painter.getHeight()},V.prototype.toDataURL=function(e,t,i){return this.painter.toDataURL(e,t,i)},V.prototype.shapeToImage=function(e,t,i){var n=a();return this.painter.shapeToImage(n,e,t,i)},V.prototype.on=function(e,t,i){return this.handler.on(e,t,i),this},V.prototype.un=function(e,t){return this.handler.un(e,t),this},V.prototype.trigger=function(e,t){return this.handler.trigger(e,t),this},V.prototype.clear=function(){return this.storage.delRoot(),this.painter.clear(),this},V.prototype.dispose=function(){this.animation.stop(),this.clear(),this.storage.dispose(),this.painter.dispose(),this.handler.dispose(),this.animation=this.storage=this.painter=this.handler=null,m.delInstance(this.id)},m}),i("zrender/config",[],function(){var e={EVENT:{RESIZE:"resize",CLICK:"click",DBLCLICK:"dblclick",MOUSEWHEEL:"mousewheel",MOUSEMOVE:"mousemove",MOUSEOVER:"mouseover",MOUSEOUT:"mouseout",MOUSEDOWN:"mousedown",MOUSEUP:"mouseup",GLOBALOUT:"globalout",DRAGSTART:"dragstart",DRAGEND:"dragend",DRAGENTER:"dragenter",DRAGOVER:"dragover",DRAGLEAVE:"dragleave",DROP:"drop",touchClickDelay:300},elementClassName:"zr-element",catchBrushException:!1,debugMode:0,devicePixelRatio:Math.max(window.devicePixelRatio||1,1)};return e}),i("echarts/chart/island",["require","./base","zrender/shape/Circle","../config","../util/ecData","zrender/tool/util","zrender/tool/event","zrender/tool/color","../util/accMath","../chart"],function(e){function t(e,t,n,a,r){i.call(this,e,t,n,a,r),this._nameConnector,this._valueConnector,this._zrHeight=this.zr.getHeight(),this._zrWidth=this.zr.getWidth();var l=this;l.shapeHandler.onmousewheel=function(e){var t=e.target,i=e.event,n=s.getDelta(i);n=n>0?-1:1,t.style.r-=n,t.style.r=t.style.r<5?5:t.style.r;var a=o.get(t,"value"),r=a*l.option.island.calculateStep;a=r>1?Math.round(a-r*n):+(a-r*n).toFixed(2);var h=o.get(t,"name");t.style.text=h+":"+a,o.set(t,"value",a),o.set(t,"name",h),l.zr.modShape(t.id),l.zr.refreshNextFrame(),s.stop(i)}}var i=e("./base"),n=e("zrender/shape/Circle"),a=e("../config");a.island={zlevel:0,z:5,r:15,calculateStep:.1};var o=e("../util/ecData"),r=e("zrender/tool/util"),s=e("zrender/tool/event");return t.prototype={type:a.CHART_TYPE_ISLAND,_combine:function(t,i){var n=e("zrender/tool/color"),a=e("../util/accMath"),r=a.accAdd(o.get(t,"value"),o.get(i,"value")),s=o.get(t,"name")+this._nameConnector+o.get(i,"name");t.style.text=s+this._valueConnector+r,o.set(t,"value",r),o.set(t,"name",s),t.style.r=this.option.island.r,t.style.color=n.mix(t.style.color,i.style.color)},refresh:function(e){e&&(e.island=this.reformOption(e.island),this.option=e,this._nameConnector=this.option.nameConnector,this._valueConnector=this.option.valueConnector)},getOption:function(){return this.option},resize:function(){var e=this.zr.getWidth(),t=this.zr.getHeight(),i=e/(this._zrWidth||e),n=t/(this._zrHeight||t);if(1!==i||1!==n){this._zrWidth=e,this._zrHeight=t;for(var a=0,o=this.shapeList.length;o>a;a++)this.zr.modShape(this.shapeList[a].id,{style:{x:Math.round(this.shapeList[a].style.x*i),y:Math.round(this.shapeList[a].style.y*n)}})}},add:function(e){var t=o.get(e,"name"),i=o.get(e,"value"),a=null!=o.get(e,"series")?o.get(e,"series").name:"",r=this.getFont(this.option.island.textStyle),s=this.option.island,l={zlevel:s.zlevel,z:s.z,style:{x:e.style.x,y:e.style.y,r:this.option.island.r,color:e.style.color||e.style.strokeColor,text:t+this._valueConnector+i,textFont:r},draggable:!0,hoverable:!0,onmousewheel:this.shapeHandler.onmousewheel,_type:"island"};"#fff"===l.style.color&&(l.style.color=e.style.strokeColor),this.setCalculable(l),l.dragEnableTime=0,o.pack(l,{name:a},-1,i,-1,t),l=new n(l),this.shapeList.push(l),this.zr.addShape(l)},del:function(e){this.zr.delShape(e.id);for(var t=[],i=0,n=this.shapeList.length;n>i;i++)this.shapeList[i].id!=e.id&&t.push(this.shapeList[i]);this.shapeList=t},ondrop:function(e,t){if(this.isDrop&&e.target){var i=e.target,n=e.dragged;this._combine(i,n),this.zr.modShape(i.id),t.dragIn=!0,this.isDrop=!1}},ondragend:function(e,t){var i=e.target;this.isDragend?t.dragIn&&(this.del(i),t.needRefresh=!0):t.dragIn||(i.style.x=s.getX(e.event),i.style.y=s.getY(e.event),this.add(i),t.needRefresh=!0),this.isDragend=!1}},r.inherits(t,i),e("../chart").define("island",t),t}),i("echarts/component/toolbox",["require","./base","zrender/shape/Line","zrender/shape/Image","zrender/shape/Rectangle","../util/shape/Icon","../config","zrender/tool/util","zrender/config","zrender/tool/event","./dataView","../component"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.dom=o.dom,this._magicType={},this._magicMap={},this._isSilence=!1,this._iconList,this._iconShapeMap={},this._featureTitle={},this._featureIcon={},this._featureColor={},this._featureOption={},this._enableColor="red",this._disableColor="#ccc",this._markShapeList=[];var r=this;r._onMark=function(e){r.__onMark(e)},r._onMarkUndo=function(e){r.__onMarkUndo(e)},r._onMarkClear=function(e){r.__onMarkClear(e)},r._onDataZoom=function(e){r.__onDataZoom(e)},r._onDataZoomReset=function(e){r.__onDataZoomReset(e)},r._onDataView=function(e){r.__onDataView(e)},r._onRestore=function(e){r.__onRestore(e)},r._onSaveAsImage=function(e){r.__onSaveAsImage(e)},r._onMagicType=function(e){r.__onMagicType(e)},r._onCustomHandler=function(e){r.__onCustomHandler(e)},r._onmousemove=function(e){return r.__onmousemove(e)},r._onmousedown=function(e){return r.__onmousedown(e)},r._onmouseup=function(e){return r.__onmouseup(e)},r._onclick=function(e){return r.__onclick(e)}}var i=e("./base"),n=e("zrender/shape/Line"),a=e("zrender/shape/Image"),o=e("zrender/shape/Rectangle"),r=e("../util/shape/Icon"),s=e("../config");s.toolbox={zlevel:0,z:6,show:!1,orient:"horizontal",x:"right",y:"top",color:["#1e90ff","#22bb22","#4b0082","#d2691e"],disableColor:"#ddd",effectiveColor:"red",backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,padding:5,itemGap:10,itemSize:16,showTitle:!0,feature:{mark:{show:!1,title:{mark:"辅助线开关",markUndo:"删除辅助线",markClear:"清空辅助线"},lineStyle:{width:1,color:"#1e90ff",type:"dashed"}},dataZoom:{show:!1,title:{dataZoom:"区域缩放",dataZoomReset:"区域缩放后退"}},dataView:{show:!1,title:"数据视图",readOnly:!1,lang:["数据视图","关闭","刷新"]},magicType:{show:!1,title:{line:"折线图切换",bar:"柱形图切换",stack:"堆积",tiled:"平铺",force:"力导向布局图切换",chord:"和弦图切换",pie:"饼图切换",funnel:"漏斗图切换"},type:[]},restore:{show:!1,title:"还原"},saveAsImage:{show:!1,title:"保存为图片",type:"png",lang:["点击保存"]}}};var l=e("zrender/tool/util"),h=e("zrender/config"),m=e("zrender/tool/event"),V="stack",U="tiled";return t.prototype={type:s.COMPONENT_TYPE_TOOLBOX,_buildShape:function(){this._iconList=[];var e=this.option.toolbox;this._enableColor=e.effectiveColor,this._disableColor=e.disableColor;var t=e.feature,i=[];for(var n in t)if(t[n].show)switch(n){case"mark":i.push({key:n,name:"mark"}),i.push({key:n,name:"markUndo"}),i.push({key:n,name:"markClear"});break;case"magicType":for(var a=0,o=t[n].type.length;o>a;a++)t[n].title[t[n].type[a]+"Chart"]=t[n].title[t[n].type[a]],t[n].option&&(t[n].option[t[n].type[a]+"Chart"]=t[n].option[t[n].type[a]]),i.push({key:n,name:t[n].type[a]+"Chart"});break;case"dataZoom":i.push({key:n,name:"dataZoom"}),i.push({key:n,name:"dataZoomReset"});break;case"saveAsImage":this.canvasSupported&&i.push({key:n,name:"saveAsImage"});break;default:i.push({key:n,name:n})}if(i.length>0){for(var r,n,a=0,o=i.length;o>a;a++)r=i[a].name,n=i[a].key,this._iconList.push(r),this._featureTitle[r]=t[n].title[r]||t[n].title,t[n].icon&&(this._featureIcon[r]=t[n].icon[r]||t[n].icon),t[n].color&&(this._featureColor[r]=t[n].color[r]||t[n].color),t[n].option&&(this._featureOption[r]=t[n].option[r]||t[n].option);this._itemGroupLocation=this._getItemGroupLocation(),this._buildBackground(),this._buildItem();for(var a=0,o=this.shapeList.length;o>a;a++)this.zr.addShape(this.shapeList[a]);this._iconShapeMap.mark&&(this._iconDisable(this._iconShapeMap.markUndo),this._iconDisable(this._iconShapeMap.markClear)),this._iconShapeMap.dataZoomReset&&0===this._zoomQueue.length&&this._iconDisable(this._iconShapeMap.dataZoomReset)}},_buildItem:function(){var t,i,n,o,s=this.option.toolbox,l=this._iconList.length,h=this._itemGroupLocation.x,m=this._itemGroupLocation.y,V=s.itemSize,U=s.itemGap,d=s.color instanceof Array?s.color:[s.color],p=this.getFont(s.textStyle);"horizontal"===s.orient?(i=this._itemGroupLocation.y/this.zr.getHeight()<.5?"bottom":"top",n=this._itemGroupLocation.x/this.zr.getWidth()<.5?"left":"right",o=this._itemGroupLocation.y/this.zr.getHeight()<.5?"top":"bottom"):i=this._itemGroupLocation.x/this.zr.getWidth()<.5?"right":"left",this._iconShapeMap={};for(var c=this,u=0;l>u;u++){switch(t={type:"icon",zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:h,y:m,width:V,height:V,iconType:this._iconList[u],lineWidth:1,strokeColor:this._featureColor[this._iconList[u]]||d[u%d.length],brushType:"stroke"},highlightStyle:{lineWidth:1,text:s.showTitle?this._featureTitle[this._iconList[u]]:void 0,textFont:p,textPosition:i,strokeColor:this._featureColor[this._iconList[u]]||d[u%d.length]},hoverable:!0,clickable:!0},this._featureIcon[this._iconList[u]]&&(t.style.image=this._featureIcon[this._iconList[u]].replace(new RegExp("^image:\\/\\/"),""),t.style.opacity=.8,t.highlightStyle.opacity=1,t.type="image"),"horizontal"===s.orient&&(0===u&&"left"===n&&(t.highlightStyle.textPosition="specific",t.highlightStyle.textAlign=n,t.highlightStyle.textBaseline=o,t.highlightStyle.textX=h,t.highlightStyle.textY="top"===o?m+V+10:m-10),u===l-1&&"right"===n&&(t.highlightStyle.textPosition="specific",t.highlightStyle.textAlign=n,t.highlightStyle.textBaseline=o,t.highlightStyle.textX=h+V,t.highlightStyle.textY="top"===o?m+V+10:m-10)),this._iconList[u]){case"mark":t.onclick=c._onMark;break;case"markUndo":t.onclick=c._onMarkUndo;break;case"markClear":t.onclick=c._onMarkClear;break;case"dataZoom":t.onclick=c._onDataZoom;break;case"dataZoomReset":t.onclick=c._onDataZoomReset;break;case"dataView":if(!this._dataView){var y=e("./dataView");this._dataView=new y(this.ecTheme,this.messageCenter,this.zr,this.option,this.myChart)}t.onclick=c._onDataView;break;case"restore":t.onclick=c._onRestore;break;case"saveAsImage":t.onclick=c._onSaveAsImage;break;default:this._iconList[u].match("Chart")?(t._name=this._iconList[u].replace("Chart",""),t.onclick=c._onMagicType):t.onclick=c._onCustomHandler}"icon"===t.type?t=new r(t):"image"===t.type&&(t=new a(t)),this.shapeList.push(t),this._iconShapeMap[this._iconList[u]]=t,"horizontal"===s.orient?h+=V+U:m+=V+U}},_buildBackground:function(){var e=this.option.toolbox,t=this.reformCssArray(this.option.toolbox.padding);this.shapeList.push(new o({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._itemGroupLocation.x-t[3],y:this._itemGroupLocation.y-t[0],width:this._itemGroupLocation.width+t[3]+t[1],height:this._itemGroupLocation.height+t[0]+t[2],brushType:0===e.borderWidth?"fill":"both",color:e.backgroundColor,strokeColor:e.borderColor,lineWidth:e.borderWidth}}))},_getItemGroupLocation:function(){var e=this.option.toolbox,t=this.reformCssArray(this.option.toolbox.padding),i=this._iconList.length,n=e.itemGap,a=e.itemSize,o=0,r=0;"horizontal"===e.orient?(o=(a+n)*i-n,r=a):(r=(a+n)*i-n,o=a);var s,l=this.zr.getWidth();switch(e.x){case"center":s=Math.floor((l-o)/2);break;case"left":s=t[3]+e.borderWidth;break;case"right":s=l-o-t[1]-e.borderWidth;break;default:s=e.x-0,s=isNaN(s)?0:s}var h,m=this.zr.getHeight();switch(e.y){case"top":h=t[0]+e.borderWidth;break;case"bottom":h=m-r-t[2]-e.borderWidth;break;case"center":h=Math.floor((m-r)/2);break;default:h=e.y-0,h=isNaN(h)?0:h}return{x:s,y:h,width:o,height:r}},__onmousemove:function(e){this._marking&&(this._markShape.style.xEnd=m.getX(e.event),this._markShape.style.yEnd=m.getY(e.event),this.zr.addHoverShape(this._markShape)),this._zooming&&(this._zoomShape.style.width=m.getX(e.event)-this._zoomShape.style.x,this._zoomShape.style.height=m.getY(e.event)-this._zoomShape.style.y,this.zr.addHoverShape(this._zoomShape),this.dom.style.cursor="crosshair",m.stop(e.event)),this._zoomStart&&"pointer"!=this.dom.style.cursor&&"move"!=this.dom.style.cursor&&(this.dom.style.cursor="crosshair")},__onmousedown:function(e){if(!e.target){this._zooming=!0;var t=m.getX(e.event),i=m.getY(e.event),n=this.option.dataZoom||{};return this._zoomShape=new o({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:t,y:i,width:1,height:1,brushType:"both"},highlightStyle:{lineWidth:2,color:n.fillerColor||s.dataZoom.fillerColor,strokeColor:n.handleColor||s.dataZoom.handleColor,brushType:"both"}}),this.zr.addHoverShape(this._zoomShape),!0}},__onmouseup:function(){if(!this._zoomShape||Math.abs(this._zoomShape.style.width)<10||Math.abs(this._zoomShape.style.height)<10)return this._zooming=!1,!0;if(this._zooming&&this.component.dataZoom){this._zooming=!1;var e=this.component.dataZoom.rectZoom(this._zoomShape.style);e&&(this._zoomQueue.push({start:e.start,end:e.end,start2:e.start2,end2:e.end2}),this._iconEnable(this._iconShapeMap.dataZoomReset),this.zr.refreshNextFrame())}return!0},__onclick:function(e){if(!e.target)if(this._marking)this._marking=!1,this._markShapeList.push(this._markShape),this._iconEnable(this._iconShapeMap.markUndo),this._iconEnable(this._iconShapeMap.markClear),this.zr.addShape(this._markShape),this.zr.refreshNextFrame();else if(this._markStart){this._marking=!0;var t=m.getX(e.event),i=m.getY(e.event);this._markShape=new n({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{xStart:t,yStart:i,xEnd:t,yEnd:i,lineWidth:this.query(this.option,"toolbox.feature.mark.lineStyle.width"),strokeColor:this.query(this.option,"toolbox.feature.mark.lineStyle.color"),lineType:this.query(this.option,"toolbox.feature.mark.lineStyle.type")}}),this.zr.addHoverShape(this._markShape)}},__onMark:function(e){var t=e.target;if(this._marking||this._markStart)this._resetMark(),this.zr.refreshNextFrame();else{this._resetZoom(),this.zr.modShape(t.id,{style:{strokeColor:this._enableColor}}),this.zr.refreshNextFrame(),this._markStart=!0;var i=this;setTimeout(function(){i.zr&&i.zr.on(h.EVENT.CLICK,i._onclick)&&i.zr.on(h.EVENT.MOUSEMOVE,i._onmousemove)},10)}return!0},__onMarkUndo:function(){if(this._marking)this._marking=!1;else{var e=this._markShapeList.length;if(e>=1){var t=this._markShapeList[e-1];this.zr.delShape(t.id),this.zr.refreshNextFrame(),this._markShapeList.pop(),1===e&&(this._iconDisable(this._iconShapeMap.markUndo),this._iconDisable(this._iconShapeMap.markClear))}}return!0},__onMarkClear:function(){this._marking&&(this._marking=!1);var e=this._markShapeList.length;if(e>0){for(;e--;)this.zr.delShape(this._markShapeList.pop().id);this._iconDisable(this._iconShapeMap.markUndo),this._iconDisable(this._iconShapeMap.markClear),this.zr.refreshNextFrame()}return!0},__onDataZoom:function(e){var t=e.target;if(this._zooming||this._zoomStart)this._resetZoom(),this.zr.refreshNextFrame(),this.dom.style.cursor="default";else{this._resetMark(),this.zr.modShape(t.id,{style:{strokeColor:this._enableColor}}),this.zr.refreshNextFrame(),this._zoomStart=!0;var i=this;setTimeout(function(){i.zr&&i.zr.on(h.EVENT.MOUSEDOWN,i._onmousedown)&&i.zr.on(h.EVENT.MOUSEUP,i._onmouseup)&&i.zr.on(h.EVENT.MOUSEMOVE,i._onmousemove)},10),this.dom.style.cursor="crosshair"}return!0},__onDataZoomReset:function(){return this._zooming&&(this._zooming=!1),this._zoomQueue.pop(),this._zoomQueue.length>0?this.component.dataZoom.absoluteZoom(this._zoomQueue[this._zoomQueue.length-1]):(this.component.dataZoom.rectZoom(),this._iconDisable(this._iconShapeMap.dataZoomReset),this.zr.refreshNextFrame()),!0},_resetMark:function(){this._marking=!1,this._markStart&&(this._markStart=!1,this._iconShapeMap.mark&&this.zr.modShape(this._iconShapeMap.mark.id,{style:{strokeColor:this._iconShapeMap.mark.highlightStyle.strokeColor}}),this.zr.un(h.EVENT.CLICK,this._onclick),this.zr.un(h.EVENT.MOUSEMOVE,this._onmousemove))},_resetZoom:function(){this._zooming=!1,this._zoomStart&&(this._zoomStart=!1,this._iconShapeMap.dataZoom&&this.zr.modShape(this._iconShapeMap.dataZoom.id,{style:{strokeColor:this._iconShapeMap.dataZoom.highlightStyle.strokeColor}}),this.zr.un(h.EVENT.MOUSEDOWN,this._onmousedown),this.zr.un(h.EVENT.MOUSEUP,this._onmouseup),this.zr.un(h.EVENT.MOUSEMOVE,this._onmousemove))},_iconDisable:function(e){"image"!=e.type?this.zr.modShape(e.id,{hoverable:!1,clickable:!1,style:{strokeColor:this._disableColor}}):this.zr.modShape(e.id,{hoverable:!1,clickable:!1,style:{opacity:.3}})},_iconEnable:function(e){"image"!=e.type?this.zr.modShape(e.id,{hoverable:!0,clickable:!0,style:{strokeColor:e.highlightStyle.strokeColor}}):this.zr.modShape(e.id,{hoverable:!0,clickable:!0,style:{opacity:.8}})},__onDataView:function(){return this._dataView.show(this.option),!0},__onRestore:function(){return this._resetMark(),this._resetZoom(),this.messageCenter.dispatch(s.EVENT.RESTORE,null,null,this.myChart),!0},__onSaveAsImage:function(){var e=this.option.toolbox.feature.saveAsImage,t=e.type||"png";"png"!=t&&"jpeg"!=t&&(t="png");var i;i=this.myChart.isConnected()?this.myChart.getConnectedDataURL(t):this.zr.toDataURL("image/"+t,this.option.backgroundColor&&"rgba(0,0,0,0)"===this.option.backgroundColor.replace(" ","")?"#fff":this.option.backgroundColor);var n=document.createElement("div");n.id="__echarts_download_wrap__",n.style.cssText="position:fixed;z-index:99999;display:block;top:0;left:0;background-color:rgba(33,33,33,0.5);text-align:center;width:100%;height:100%;line-height:"+document.documentElement.clientHeight+"px;";var a=document.createElement("a");a.href=i,a.setAttribute("download",(e.name?e.name:this.option.title&&(this.option.title.text||this.option.title.subtext)?this.option.title.text||this.option.title.subtext:"ECharts")+"."+t),a.innerHTML='图片另存为":e.lang?e.lang[0]:"点击保存")+'"/>',n.appendChild(a),document.body.appendChild(n),a=null,n=null,setTimeout(function(){var e=document.getElementById("__echarts_download_wrap__");e&&(e.onclick=function(){var e=document.getElementById("__echarts_download_wrap__");e.onclick=null,e.innerHTML="",document.body.removeChild(e),e=null},e=null)},500)},__onMagicType:function(e){this._resetMark();var t=e.target._name;return this._magicType[t]||(this._magicType[t]=!0,t===s.CHART_TYPE_LINE?this._magicType[s.CHART_TYPE_BAR]=!1:t===s.CHART_TYPE_BAR&&(this._magicType[s.CHART_TYPE_LINE]=!1),t===s.CHART_TYPE_PIE?this._magicType[s.CHART_TYPE_FUNNEL]=!1:t===s.CHART_TYPE_FUNNEL&&(this._magicType[s.CHART_TYPE_PIE]=!1),t===s.CHART_TYPE_FORCE?this._magicType[s.CHART_TYPE_CHORD]=!1:t===s.CHART_TYPE_CHORD&&(this._magicType[s.CHART_TYPE_FORCE]=!1),t===V?this._magicType[U]=!1:t===U&&(this._magicType[V]=!1),this.messageCenter.dispatch(s.EVENT.MAGIC_TYPE_CHANGED,e.event,{magicType:this._magicType},this.myChart)),!0},setMagicType:function(e){this._resetMark(),this._magicType=e,!this._isSilence&&this.messageCenter.dispatch(s.EVENT.MAGIC_TYPE_CHANGED,null,{magicType:this._magicType},this.myChart)},__onCustomHandler:function(e){var t=e.target.style.iconType,i=this.option.toolbox.feature[t].onclick;"function"==typeof i&&i.call(this,this.option)},reset:function(e,t){if(t&&this.clear(),this.query(e,"toolbox.show")&&this.query(e,"toolbox.feature.magicType.show")){var i=e.toolbox.feature.magicType.type,n=i.length;for(this._magicMap={};n--;)this._magicMap[i[n]]=!0;n=e.series.length;for(var a,o;n--;)a=e.series[n].type,this._magicMap[a]&&(o=e.xAxis instanceof Array?e.xAxis[e.series[n].xAxisIndex||0]:e.xAxis,o&&"category"===(o.type||"category")&&(o.__boundaryGap=null!=o.boundaryGap?o.boundaryGap:!0),o=e.yAxis instanceof Array?e.yAxis[e.series[n].yAxisIndex||0]:e.yAxis,o&&"category"===o.type&&(o.__boundaryGap=null!=o.boundaryGap?o.boundaryGap:!0),e.series[n].__type=a,e.series[n].__itemStyle=l.clone(e.series[n].itemStyle||{})),(this._magicMap[V]||this._magicMap[U])&&(e.series[n].__stack=e.series[n].stack)}this._magicType=t?{}:this._magicType||{};for(var r in this._magicType)if(this._magicType[r]){this.option=e,this.getMagicOption();break}var s=e.dataZoom;if(s&&s.show){var h=null!=s.start&&s.start>=0&&s.start<=100?s.start:0,m=null!=s.end&&s.end>=0&&s.end<=100?s.end:100;h>m&&(h+=m,m=h-m,h-=m),this._zoomQueue=[{start:h,end:m,start2:0,end2:100}]}else this._zoomQueue=[]},getMagicOption:function(){var e,t;if(this._magicType[s.CHART_TYPE_LINE]||this._magicType[s.CHART_TYPE_BAR]){for(var i=this._magicType[s.CHART_TYPE_LINE]?!1:!0,n=0,a=this.option.series.length;a>n;n++)t=this.option.series[n].type,(t==s.CHART_TYPE_LINE||t==s.CHART_TYPE_BAR)&&(e=this.option.xAxis instanceof Array?this.option.xAxis[this.option.series[n].xAxisIndex||0]:this.option.xAxis,e&&"category"===(e.type||"category")&&(e.boundaryGap=i?!0:e.__boundaryGap),e=this.option.yAxis instanceof Array?this.option.yAxis[this.option.series[n].yAxisIndex||0]:this.option.yAxis,e&&"category"===e.type&&(e.boundaryGap=i?!0:e.__boundaryGap));this._defaultMagic(s.CHART_TYPE_LINE,s.CHART_TYPE_BAR)}if(this._defaultMagic(s.CHART_TYPE_CHORD,s.CHART_TYPE_FORCE),this._defaultMagic(s.CHART_TYPE_PIE,s.CHART_TYPE_FUNNEL),this._magicType[V]||this._magicType[U])for(var n=0,a=this.option.series.length;a>n;n++)this._magicType[V]?(this.option.series[n].stack="_ECHARTS_STACK_KENER_2014_",t=V):this._magicType[U]&&(this.option.series[n].stack=null,t=U),this._featureOption[t+"Chart"]&&l.merge(this.option.series[n],this._featureOption[t+"Chart"]||{},!0);return this.option},_defaultMagic:function(e,t){if(this._magicType[e]||this._magicType[t])for(var i=0,n=this.option.series.length;n>i;i++){var a=this.option.series[i].type;(a==e||a==t)&&(this.option.series[i].type=this._magicType[e]?e:t,this.option.series[i].itemStyle=l.clone(this.option.series[i].__itemStyle),a=this.option.series[i].type,this._featureOption[a+"Chart"]&&l.merge(this.option.series[i],this._featureOption[a+"Chart"]||{},!0))}},silence:function(e){this._isSilence=e},resize:function(){this._resetMark(),this.clear(),this.option&&this.option.toolbox&&this.option.toolbox.show&&this._buildShape(),this._dataView&&this._dataView.resize()},hideDataView:function(){this._dataView&&this._dataView.hide()},clear:function(e){this.zr&&(this.zr.delShape(this.shapeList),this.shapeList=[],e||(this.zr.delShape(this._markShapeList),this._markShapeList=[]))},onbeforDispose:function(){this._dataView&&(this._dataView.dispose(),this._dataView=null),this._markShapeList=null},refresh:function(e){e&&(this._resetMark(),this._resetZoom(),e.toolbox=this.reformOption(e.toolbox),this.option=e,this.clear(!0),e.toolbox.show&&this._buildShape(),this.hideDataView())}},l.inherits(t,i),e("../component").define("toolbox",t),t}),i("echarts/component",[],function(){var e={},t={};return e.define=function(i,n){return t[i]=n,e},e.get=function(e){return t[e]},e}),i("echarts/component/title",["require","./base","zrender/shape/Text","zrender/shape/Rectangle","../config","zrender/tool/util","zrender/tool/area","zrender/tool/color","../component"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Rectangle"),o=e("../config");o.title={zlevel:0,z:6,show:!0,text:"",subtext:"",x:"left",y:"top",backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,padding:5,itemGap:5,textStyle:{fontSize:18,fontWeight:"bolder",color:"#333"},subtextStyle:{color:"#aaa"}};var r=e("zrender/tool/util"),s=e("zrender/tool/area"),l=e("zrender/tool/color");return t.prototype={type:o.COMPONENT_TYPE_TITLE,_buildShape:function(){if(this.titleOption.show){this._itemGroupLocation=this._getItemGroupLocation(),this._buildBackground(),this._buildItem();for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e])}},_buildItem:function(){var e=this.titleOption.text,t=this.titleOption.link,i=this.titleOption.target,a=this.titleOption.subtext,o=this.titleOption.sublink,r=this.titleOption.subtarget,s=this.getFont(this.titleOption.textStyle),h=this.getFont(this.titleOption.subtextStyle),m=this._itemGroupLocation.x,V=this._itemGroupLocation.y,U=this._itemGroupLocation.width,d=this._itemGroupLocation.height,p={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{y:V,color:this.titleOption.textStyle.color,text:e,textFont:s,textBaseline:"top"},highlightStyle:{color:l.lift(this.titleOption.textStyle.color,1),brushType:"fill"},hoverable:!1};t&&(p.hoverable=!0,p.clickable=!0,p.onclick=function(){i&&"self"==i?window.location=t:window.open(t)});var c={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{y:V+d,color:this.titleOption.subtextStyle.color,text:a,textFont:h,textBaseline:"bottom"},highlightStyle:{color:l.lift(this.titleOption.subtextStyle.color,1),brushType:"fill"},hoverable:!1};switch(o&&(c.hoverable=!0,c.clickable=!0,c.onclick=function(){r&&"self"==r?window.location=o:window.open(o)}),this.titleOption.x){case"center":p.style.x=c.style.x=m+U/2,p.style.textAlign=c.style.textAlign="center";break;case"left":p.style.x=c.style.x=m,p.style.textAlign=c.style.textAlign="left";break;case"right":p.style.x=c.style.x=m+U,p.style.textAlign=c.style.textAlign="right";break;default:m=this.titleOption.x-0,m=isNaN(m)?0:m,p.style.x=c.style.x=m}this.titleOption.textAlign&&(p.style.textAlign=c.style.textAlign=this.titleOption.textAlign),this.shapeList.push(new n(p)),""!==a&&this.shapeList.push(new n(c))},_buildBackground:function(){var e=this.reformCssArray(this.titleOption.padding);this.shapeList.push(new a({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._itemGroupLocation.x-e[3],y:this._itemGroupLocation.y-e[0],width:this._itemGroupLocation.width+e[3]+e[1],height:this._itemGroupLocation.height+e[0]+e[2],brushType:0===this.titleOption.borderWidth?"fill":"both",color:this.titleOption.backgroundColor,strokeColor:this.titleOption.borderColor,lineWidth:this.titleOption.borderWidth}}))},_getItemGroupLocation:function(){var e,t=this.reformCssArray(this.titleOption.padding),i=this.titleOption.text,n=this.titleOption.subtext,a=this.getFont(this.titleOption.textStyle),o=this.getFont(this.titleOption.subtextStyle),r=Math.max(s.getTextWidth(i,a),s.getTextWidth(n,o)),l=s.getTextHeight(i,a)+(""===n?0:this.titleOption.itemGap+s.getTextHeight(n,o)),h=this.zr.getWidth();switch(this.titleOption.x){case"center":e=Math.floor((h-r)/2);break;case"left":e=t[3]+this.titleOption.borderWidth;break;case"right":e=h-r-t[1]-this.titleOption.borderWidth;break;default:e=this.titleOption.x-0,e=isNaN(e)?0:e}var m,V=this.zr.getHeight();switch(this.titleOption.y){case"top":m=t[0]+this.titleOption.borderWidth;break;case"bottom":m=V-l-t[2]-this.titleOption.borderWidth;break;case"center":m=Math.floor((V-l)/2);break;default:m=this.titleOption.y-0,m=isNaN(m)?0:m}return{x:e,y:m,width:r,height:l}},refresh:function(e){e&&(this.option=e,this.option.title=this.reformOption(this.option.title),this.titleOption=this.option.title,this.titleOption.textStyle=this.getTextStyle(this.titleOption.textStyle),this.titleOption.subtextStyle=this.getTextStyle(this.titleOption.subtextStyle)),this.clear(),this._buildShape()}},r.inherits(t,i),e("../component").define("title",t),t}),i("echarts/component/tooltip",["require","./base","../util/shape/Cross","zrender/shape/Line","zrender/shape/Rectangle","../config","../util/ecData","zrender/config","zrender/tool/event","zrender/tool/area","zrender/tool/color","zrender/tool/util","zrender/shape/Base","../component"],function(e){function t(e,t,o,r,s){i.call(this,e,t,o,r,s),this.dom=s.dom;var l=this;l._onmousemove=function(e){return l.__onmousemove(e)},l._onglobalout=function(e){return l.__onglobalout(e)},this.zr.on(h.EVENT.MOUSEMOVE,l._onmousemove),this.zr.on(h.EVENT.GLOBALOUT,l._onglobalout),l._hide=function(e){return l.__hide(e)},l._tryShow=function(e){return l.__tryShow(e)},l._refixed=function(e){return l.__refixed(e)},l._setContent=function(e,t){return l.__setContent(e,t)},this._tDom=this._tDom||document.createElement("div"),this._tDom.onselectstart=function(){return!1},this._tDom.onmouseover=function(){l._mousein=!0},this._tDom.onmouseout=function(){l._mousein=!1},this._tDom.className="echarts-tooltip",this._tDom.style.position="absolute",this.hasAppend=!1,this._axisLineShape&&this.zr.delShape(this._axisLineShape.id),this._axisLineShape=new a({zlevel:this.getZlevelBase(),z:this.getZBase(),invisible:!0,hoverable:!1}),this.shapeList.push(this._axisLineShape),this.zr.addShape(this._axisLineShape),this._axisShadowShape&&this.zr.delShape(this._axisShadowShape.id),this._axisShadowShape=new a({zlevel:this.getZlevelBase(),z:1,invisible:!0,hoverable:!1}),this.shapeList.push(this._axisShadowShape),this.zr.addShape(this._axisShadowShape),this._axisCrossShape&&this.zr.delShape(this._axisCrossShape.id),this._axisCrossShape=new n({zlevel:this.getZlevelBase(),z:this.getZBase(),invisible:!0,hoverable:!1}),this.shapeList.push(this._axisCrossShape),this.zr.addShape(this._axisCrossShape),this.showing=!1,this.refresh(r)}var i=e("./base"),n=e("../util/shape/Cross"),a=e("zrender/shape/Line"),o=e("zrender/shape/Rectangle"),r=new o({}),s=e("../config");s.tooltip={zlevel:1,z:8,show:!0,showContent:!0,trigger:"item",islandFormatter:"{a}
{b} : {c}",showDelay:20,hideDelay:100,transitionDuration:.4,enterable:!1,backgroundColor:"rgba(0,0,0,0.7)",borderColor:"#333",borderRadius:4,borderWidth:0,padding:5,axisPointer:{type:"line",lineStyle:{color:"#48b",width:2,type:"solid"},crossStyle:{color:"#1e90ff",width:1,type:"dashed"},shadowStyle:{color:"rgba(150,150,150,0.3)",width:"auto",type:"default"}},textStyle:{color:"#fff"}};var l=e("../util/ecData"),h=e("zrender/config"),m=e("zrender/tool/event"),V=e("zrender/tool/area"),U=e("zrender/tool/color"),d=e("zrender/tool/util"),p=e("zrender/shape/Base");return t.prototype={type:s.COMPONENT_TYPE_TOOLTIP,_gCssText:"position:absolute;display:block;border-style:solid;white-space:nowrap;",_style:function(e){if(!e)return"";var t=[];if(e.transitionDuration){var i="left "+e.transitionDuration+"s,top "+e.transitionDuration+"s";t.push("transition:"+i),t.push("-moz-transition:"+i),t.push("-webkit-transition:"+i),t.push("-o-transition:"+i)}e.backgroundColor&&(t.push("background-Color:"+U.toHex(e.backgroundColor)),t.push("filter:alpha(opacity=70)"),t.push("background-Color:"+e.backgroundColor)),null!=e.borderWidth&&t.push("border-width:"+e.borderWidth+"px"),null!=e.borderColor&&t.push("border-color:"+e.borderColor),null!=e.borderRadius&&(t.push("border-radius:"+e.borderRadius+"px"),t.push("-moz-border-radius:"+e.borderRadius+"px"),t.push("-webkit-border-radius:"+e.borderRadius+"px"),t.push("-o-border-radius:"+e.borderRadius+"px"));var n=e.textStyle;n&&(n.color&&t.push("color:"+n.color),n.decoration&&t.push("text-decoration:"+n.decoration),n.align&&t.push("text-align:"+n.align),n.fontFamily&&t.push("font-family:"+n.fontFamily),n.fontSize&&t.push("font-size:"+n.fontSize+"px"),n.fontSize&&t.push("line-height:"+Math.round(3*n.fontSize/2)+"px"),n.fontStyle&&t.push("font-style:"+n.fontStyle),n.fontWeight&&t.push("font-weight:"+n.fontWeight));var a=e.padding;return null!=a&&(a=this.reformCssArray(a),t.push("padding:"+a[0]+"px "+a[1]+"px "+a[2]+"px "+a[3]+"px")),t=t.join(";")+";"},__hide:function(){this._lastDataIndex=-1,this._lastSeriesIndex=-1,this._lastItemTriggerId=-1,this._tDom&&(this._tDom.style.display="none");var e=!1;this._axisLineShape.invisible||(this._axisLineShape.invisible=!0, +this.zr.modShape(this._axisLineShape.id),e=!0),this._axisShadowShape.invisible||(this._axisShadowShape.invisible=!0,this.zr.modShape(this._axisShadowShape.id),e=!0),this._axisCrossShape.invisible||(this._axisCrossShape.invisible=!0,this.zr.modShape(this._axisCrossShape.id),e=!0),this._lastTipShape&&this._lastTipShape.tipShape.length>0&&(this.zr.delShape(this._lastTipShape.tipShape),this._lastTipShape=!1,this.shapeList.length=2),e&&this.zr.refreshNextFrame(),this.showing=!1},_show:function(e,t,i,n){var a=this._tDom.offsetHeight,o=this._tDom.offsetWidth;e&&("function"==typeof e&&(e=e([t,i])),e instanceof Array&&(t=e[0],i=e[1])),t+o>this._zrWidth&&(t-=o+40),i+a>this._zrHeight&&(i-=a-20),20>i&&(i=0),this._tDom.style.cssText=this._gCssText+this._defaultCssText+(n?n:"")+"left:"+t+"px;top:"+i+"px;",(10>a||10>o)&&setTimeout(this._refixed,20),this.showing=!0},__refixed:function(){if(this._tDom){var e="",t=this._tDom.offsetHeight,i=this._tDom.offsetWidth;this._tDom.offsetLeft+i>this._zrWidth&&(e+="left:"+(this._zrWidth-i-20)+"px;"),this._tDom.offsetTop+t>this._zrHeight&&(e+="top:"+(this._zrHeight-t-10)+"px;"),""!==e&&(this._tDom.style.cssText+=e)}},__tryShow:function(){var e,t;if(this._curTarget){if("island"===this._curTarget._type&&this.option.tooltip.show)return void this._showItemTrigger();var i=l.get(this._curTarget,"series"),n=l.get(this._curTarget,"data");e=this.deepQuery([n,i,this.option],"tooltip.show"),null!=i&&null!=n&&e?(t=this.deepQuery([n,i,this.option],"tooltip.trigger"),"axis"===t?this._showAxisTrigger(i.xAxisIndex,i.yAxisIndex,l.get(this._curTarget,"dataIndex")):this._showItemTrigger()):(clearTimeout(this._hidingTicket),clearTimeout(this._showingTicket),this._hidingTicket=setTimeout(this._hide,this._hideDelay))}else this._findPolarTrigger()||this._findAxisTrigger()},_findAxisTrigger:function(){if(!this.component.xAxis||!this.component.yAxis)return void(this._hidingTicket=setTimeout(this._hide,this._hideDelay));for(var e,t,i=this.option.series,n=0,a=i.length;a>n;n++)if("axis"===this.deepQuery([i[n],this.option],"tooltip.trigger"))return e=i[n].xAxisIndex||0,t=i[n].yAxisIndex||0,this.component.xAxis.getAxis(e)&&this.component.xAxis.getAxis(e).type===s.COMPONENT_TYPE_AXIS_CATEGORY?void this._showAxisTrigger(e,t,this._getNearestDataIndex("x",this.component.xAxis.getAxis(e))):this.component.yAxis.getAxis(t)&&this.component.yAxis.getAxis(t).type===s.COMPONENT_TYPE_AXIS_CATEGORY?void this._showAxisTrigger(e,t,this._getNearestDataIndex("y",this.component.yAxis.getAxis(t))):void this._showAxisTrigger(e,t,-1);"cross"===this.option.tooltip.axisPointer.type&&this._showAxisTrigger(-1,-1,-1)},_findPolarTrigger:function(){if(!this.component.polar)return!1;var e,t=m.getX(this._event),i=m.getY(this._event),n=this.component.polar.getNearestIndex([t,i]);return n?(e=n.valueIndex,n=n.polarIndex):n=-1,-1!=n?this._showPolarTrigger(n,e):!1},_getNearestDataIndex:function(e,t){var i=-1,n=m.getX(this._event),a=m.getY(this._event);if("x"===e){for(var o,r,s=this.component.grid.getXend(),l=t.getCoordByIndex(i);s>l&&(r=l,n>=l);)o=l,l=t.getCoordByIndex(++i);return 0>=i?i=0:r-n>=n-o?i-=1:null==t.getNameByIndex(i)&&(i-=1),i}for(var h,V,U=this.component.grid.getY(),l=t.getCoordByIndex(i);l>U&&(h=l,l>=a);)V=l,l=t.getCoordByIndex(++i);return 0>=i?i=0:a-h>=V-a?i-=1:null==t.getNameByIndex(i)&&(i-=1),i},_showAxisTrigger:function(e,t,i){if(!this._event.connectTrigger&&this.messageCenter.dispatch(s.EVENT.TOOLTIP_IN_GRID,this._event,null,this.myChart),null==this.component.xAxis||null==this.component.yAxis||null==e||null==t)return clearTimeout(this._hidingTicket),clearTimeout(this._showingTicket),void(this._hidingTicket=setTimeout(this._hide,this._hideDelay));var n,a,o,r,l=this.option.series,h=[],V=[],U="";if("axis"===this.option.tooltip.trigger){if(!this.option.tooltip.show)return;a=this.option.tooltip.formatter,o=this.option.tooltip.position}var d,p,c=-1!=e&&this.component.xAxis.getAxis(e).type===s.COMPONENT_TYPE_AXIS_CATEGORY?"xAxis":-1!=t&&this.component.yAxis.getAxis(t).type===s.COMPONENT_TYPE_AXIS_CATEGORY?"yAxis":!1;if(c){var u="xAxis"==c?e:t;n=this.component[c].getAxis(u);for(var y=0,g=l.length;g>y;y++)this._isSelected(l[y].name)&&l[y][c+"Index"]===u&&"axis"===this.deepQuery([l[y],this.option],"tooltip.trigger")&&(r=this.query(l[y],"tooltip.showContent")||r,a=this.query(l[y],"tooltip.formatter")||a,o=this.query(l[y],"tooltip.position")||o,U+=this._style(this.query(l[y],"tooltip")),null!=l[y].stack&&"xAxis"==c?(h.unshift(l[y]),V.unshift(y)):(h.push(l[y]),V.push(y)));this.messageCenter.dispatch(s.EVENT.TOOLTIP_HOVER,this._event,{seriesIndex:V,dataIndex:i},this.myChart);var b;"xAxis"==c?(d=this.subPixelOptimize(n.getCoordByIndex(i),this._axisLineWidth),p=m.getY(this._event),b=[d,this.component.grid.getY(),d,this.component.grid.getYend()]):(d=m.getX(this._event),p=this.subPixelOptimize(n.getCoordByIndex(i),this._axisLineWidth),b=[this.component.grid.getX(),p,this.component.grid.getXend(),p]),this._styleAxisPointer(h,b[0],b[1],b[2],b[3],n.getGap(),d,p)}else d=m.getX(this._event),p=m.getY(this._event),this._styleAxisPointer(l,this.component.grid.getX(),p,this.component.grid.getXend(),p,0,d,p),i>=0?this._showItemTrigger(!0):(clearTimeout(this._hidingTicket),clearTimeout(this._showingTicket),this._tDom.style.display="none");if(h.length>0){if(this._lastItemTriggerId=-1,this._lastDataIndex!=i||this._lastSeriesIndex!=V[0]){this._lastDataIndex=i,this._lastSeriesIndex=V[0];var f,k;if("function"==typeof a){for(var x=[],y=0,g=h.length;g>y;y++)f=h[y].data[i],k=this.getDataFromOption(f,"-"),x.push({seriesIndex:V[y],seriesName:h[y].name||"",series:h[y],dataIndex:i,data:f,name:n.getNameByIndex(i),value:k,0:h[y].name||"",1:n.getNameByIndex(i),2:k,3:f});this._curTicket="axis:"+i,this._tDom.innerHTML=a.call(this.myChart,x,this._curTicket,this._setContent)}else if("string"==typeof a){this._curTicket=0/0,a=a.replace("{a}","{a0}").replace("{b}","{b0}").replace("{c}","{c0}");for(var y=0,g=h.length;g>y;y++)a=a.replace("{a"+y+"}",this._encodeHTML(h[y].name||"")),a=a.replace("{b"+y+"}",this._encodeHTML(n.getNameByIndex(i))),f=h[y].data[i],f=this.getDataFromOption(f,"-"),a=a.replace("{c"+y+"}",f instanceof Array?f:this.numAddCommas(f));this._tDom.innerHTML=a}else{this._curTicket=0/0,a=this._encodeHTML(n.getNameByIndex(i));for(var y=0,g=h.length;g>y;y++)a+="
"+this._encodeHTML(h[y].name||"")+" : ",f=h[y].data[i],f=this.getDataFromOption(f,"-"),a+=f instanceof Array?f:this.numAddCommas(f);this._tDom.innerHTML=a}}if(r===!1||!this.option.tooltip.showContent)return;this.hasAppend||(this._tDom.style.left=this._zrWidth/2+"px",this._tDom.style.top=this._zrHeight/2+"px",this.dom.firstChild.appendChild(this._tDom),this.hasAppend=!0),this._show(o,d+10,p+10,U)}},_showPolarTrigger:function(e,t){if(null==this.component.polar||null==e||null==t||0>t)return!1;var i,n,a,o=this.option.series,r=[],s=[],l="";if("axis"===this.option.tooltip.trigger){if(!this.option.tooltip.show)return!1;i=this.option.tooltip.formatter,n=this.option.tooltip.position}for(var h=this.option.polar[e].indicator[t].text,V=0,U=o.length;U>V;V++)this._isSelected(o[V].name)&&o[V].polarIndex===e&&"axis"===this.deepQuery([o[V],this.option],"tooltip.trigger")&&(a=this.query(o[V],"tooltip.showContent")||a,i=this.query(o[V],"tooltip.formatter")||i,n=this.query(o[V],"tooltip.position")||n,l+=this._style(this.query(o[V],"tooltip")),r.push(o[V]),s.push(V));if(r.length>0){for(var d,p,c,u=[],V=0,U=r.length;U>V;V++){d=r[V].data;for(var y=0,g=d.length;g>y;y++)p=d[y],this._isSelected(p.name)&&(p=null!=p?p:{name:"",value:{dataIndex:"-"}},c=this.getDataFromOption(p.value[t]),u.push({seriesIndex:s[V],seriesName:r[V].name||"",series:r[V],dataIndex:t,data:p,name:p.name,indicator:h,value:c,0:r[V].name||"",1:p.name,2:c,3:h}))}if(u.length<=0)return;if(this._lastItemTriggerId=-1,this._lastDataIndex!=t||this._lastSeriesIndex!=s[0])if(this._lastDataIndex=t,this._lastSeriesIndex=s[0],"function"==typeof i)this._curTicket="axis:"+t,this._tDom.innerHTML=i.call(this.myChart,u,this._curTicket,this._setContent);else if("string"==typeof i){i=i.replace("{a}","{a0}").replace("{b}","{b0}").replace("{c}","{c0}").replace("{d}","{d0}");for(var V=0,U=u.length;U>V;V++)i=i.replace("{a"+V+"}",this._encodeHTML(u[V].seriesName)),i=i.replace("{b"+V+"}",this._encodeHTML(u[V].name)),i=i.replace("{c"+V+"}",this.numAddCommas(u[V].value)),i=i.replace("{d"+V+"}",this._encodeHTML(u[V].indicator));this._tDom.innerHTML=i}else{i=this._encodeHTML(u[0].name)+"
"+this._encodeHTML(u[0].indicator)+" : "+this.numAddCommas(u[0].value);for(var V=1,U=u.length;U>V;V++)i+="
"+this._encodeHTML(u[V].name)+"
",i+=this._encodeHTML(u[V].indicator)+" : "+this.numAddCommas(u[V].value);this._tDom.innerHTML=i}if(a===!1||!this.option.tooltip.showContent)return;return this.hasAppend||(this._tDom.style.left=this._zrWidth/2+"px",this._tDom.style.top=this._zrHeight/2+"px",this.dom.firstChild.appendChild(this._tDom),this.hasAppend=!0),this._show(n,m.getX(this._event),m.getY(this._event),l),!0}},_showItemTrigger:function(e){if(this._curTarget){var t,i,n,a=l.get(this._curTarget,"series"),o=l.get(this._curTarget,"seriesIndex"),r=l.get(this._curTarget,"data"),h=l.get(this._curTarget,"dataIndex"),V=l.get(this._curTarget,"name"),U=l.get(this._curTarget,"value"),d=l.get(this._curTarget,"special"),p=l.get(this._curTarget,"special2"),c=[r,a,this.option],u="";if("island"!=this._curTarget._type){var y=e?"axis":"item";this.option.tooltip.trigger===y&&(t=this.option.tooltip.formatter,i=this.option.tooltip.position),this.query(a,"tooltip.trigger")===y&&(n=this.query(a,"tooltip.showContent")||n,t=this.query(a,"tooltip.formatter")||t,i=this.query(a,"tooltip.position")||i,u+=this._style(this.query(a,"tooltip"))),n=this.query(r,"tooltip.showContent")||n,t=this.query(r,"tooltip.formatter")||t,i=this.query(r,"tooltip.position")||i,u+=this._style(this.query(r,"tooltip"))}else this._lastItemTriggerId=0/0,n=this.deepQuery(c,"tooltip.showContent"),t=this.deepQuery(c,"tooltip.islandFormatter"),i=this.deepQuery(c,"tooltip.islandPosition");this._lastDataIndex=-1,this._lastSeriesIndex=-1,this._lastItemTriggerId!==this._curTarget.id&&(this._lastItemTriggerId=this._curTarget.id,"function"==typeof t?(this._curTicket=(a.name||"")+":"+h,this._tDom.innerHTML=t.call(this.myChart,{seriesIndex:o,seriesName:a.name||"",series:a,dataIndex:h,data:r,name:V,value:U,percent:d,indicator:d,value2:p,indicator2:p,0:a.name||"",1:V,2:U,3:d,4:p,5:r,6:o,7:h},this._curTicket,this._setContent)):"string"==typeof t?(this._curTicket=0/0,t=t.replace("{a}","{a0}").replace("{b}","{b0}").replace("{c}","{c0}"),t=t.replace("{a0}",this._encodeHTML(a.name||"")).replace("{b0}",this._encodeHTML(V)).replace("{c0}",U instanceof Array?U:this.numAddCommas(U)),t=t.replace("{d}","{d0}").replace("{d0}",d||""),t=t.replace("{e}","{e0}").replace("{e0}",l.get(this._curTarget,"special2")||""),this._tDom.innerHTML=t):(this._curTicket=0/0,this._tDom.innerHTML=a.type===s.CHART_TYPE_RADAR&&d?this._itemFormatter.radar.call(this,a,V,U,d):a.type===s.CHART_TYPE_EVENTRIVER?this._itemFormatter.eventRiver.call(this,a,V,U,r):""+(null!=a.name?this._encodeHTML(a.name)+"
":"")+(""===V?"":this._encodeHTML(V)+" : ")+(U instanceof Array?U:this.numAddCommas(U))));var g=m.getX(this._event),b=m.getY(this._event);this.deepQuery(c,"tooltip.axisPointer.show")&&this.component.grid?this._styleAxisPointer([a],this.component.grid.getX(),b,this.component.grid.getXend(),b,0,g,b):this._hide(),n!==!1&&this.option.tooltip.showContent&&(this.hasAppend||(this._tDom.style.left=this._zrWidth/2+"px",this._tDom.style.top=this._zrHeight/2+"px",this.dom.firstChild.appendChild(this._tDom),this.hasAppend=!0),this._show(i,g+20,b-20,u))}},_itemFormatter:{radar:function(e,t,i,n){var a="";a+=this._encodeHTML(""===t?e.name||"":t),a+=""===a?"":"
";for(var o=0;o";return a},chord:function(e,t,i,n,a){if(null==a)return this._encodeHTML(t)+" ("+this.numAddCommas(i)+")";var o=this._encodeHTML(t),r=this._encodeHTML(n);return""+(null!=e.name?this._encodeHTML(e.name)+"
":"")+o+" -> "+r+" ("+this.numAddCommas(i)+")
"+r+" -> "+o+" ("+this.numAddCommas(a)+")"},eventRiver:function(e,t,i,n){var a="";a+=this._encodeHTML(""===e.name?"":e.name+" : "),a+=this._encodeHTML(t),a+=""===a?"":"
",n=n.evolution;for(var o=0,r=n.length;r>o;o++)a+='
");return a}},_styleAxisPointer:function(e,t,i,n,a,o,r,s){if(e.length>0){var l,h,m=this.option.tooltip.axisPointer,V=m.type,U={line:{},cross:{},shadow:{}};for(var d in U)U[d].color=m[d+"Style"].color,U[d].width=m[d+"Style"].width,U[d].type=m[d+"Style"].type;for(var p=0,c=e.length;c>p;p++)l=e[p],h=this.query(l,"tooltip.axisPointer.type"),V=h||V,h&&(U[h].color=this.query(l,"tooltip.axisPointer."+h+"Style.color")||U[h].color,U[h].width=this.query(l,"tooltip.axisPointer."+h+"Style.width")||U[h].width,U[h].type=this.query(l,"tooltip.axisPointer."+h+"Style.type")||U[h].type);if("line"===V){var u=U.line.width,y=t==n;this._axisLineShape.style={xStart:y?this.subPixelOptimize(t,u):t,yStart:y?i:this.subPixelOptimize(i,u),xEnd:y?this.subPixelOptimize(n,u):n,yEnd:y?a:this.subPixelOptimize(a,u),strokeColor:U.line.color,lineWidth:u,lineType:U.line.type},this._axisLineShape.invisible=!1,this.zr.modShape(this._axisLineShape.id)}else if("cross"===V){var g=U.cross.width;this._axisCrossShape.style={brushType:"stroke",rect:this.component.grid.getArea(),x:this.subPixelOptimize(r,g),y:this.subPixelOptimize(s,g),text:("( "+this.component.xAxis.getAxis(0).getValueFromCoord(r)+" , "+this.component.yAxis.getAxis(0).getValueFromCoord(s)+" )").replace(" , "," ").replace(" , "," "),textPosition:"specific",strokeColor:U.cross.color,lineWidth:g,lineType:U.cross.type},this.component.grid.getXend()-r>100?(this._axisCrossShape.style.textAlign="left",this._axisCrossShape.style.textX=r+10):(this._axisCrossShape.style.textAlign="right",this._axisCrossShape.style.textX=r-10),s-this.component.grid.getY()>50?(this._axisCrossShape.style.textBaseline="bottom",this._axisCrossShape.style.textY=s-10):(this._axisCrossShape.style.textBaseline="top",this._axisCrossShape.style.textY=s+10),this._axisCrossShape.invisible=!1,this.zr.modShape(this._axisCrossShape.id)}else"shadow"===V&&((null==U.shadow.width||"auto"===U.shadow.width||isNaN(U.shadow.width))&&(U.shadow.width=o),t===n?Math.abs(this.component.grid.getX()-t)<2?(U.shadow.width/=2,t=n+=U.shadow.width/2):Math.abs(this.component.grid.getXend()-t)<2&&(U.shadow.width/=2,t=n-=U.shadow.width/2):i===a&&(Math.abs(this.component.grid.getY()-i)<2?(U.shadow.width/=2,i=a+=U.shadow.width/2):Math.abs(this.component.grid.getYend()-i)<2&&(U.shadow.width/=2,i=a-=U.shadow.width/2)),this._axisShadowShape.style={xStart:t,yStart:i,xEnd:n,yEnd:a,strokeColor:U.shadow.color,lineWidth:U.shadow.width},this._axisShadowShape.invisible=!1,this.zr.modShape(this._axisShadowShape.id));this.zr.refreshNextFrame()}},__onmousemove:function(e){if(clearTimeout(this._hidingTicket),clearTimeout(this._showingTicket),!this._mousein||!this._enterable){var t=e.target,i=m.getX(e.event),n=m.getY(e.event);if(t){this._curTarget=t,this._event=e.event,this._event.zrenderX=i,this._event.zrenderY=n;var a;if(this._needAxisTrigger&&this.component.polar&&-1!=(a=this.component.polar.isInside([i,n])))for(var o=this.option.series,l=0,h=o.length;h>l;l++)if(o[l].polarIndex===a&&"axis"===this.deepQuery([o[l],this.option],"tooltip.trigger")){this._curTarget=null;break}this._showingTicket=setTimeout(this._tryShow,this._showDelay)}else this._curTarget=!1,this._event=e.event,this._event.zrenderX=i,this._event.zrenderY=n,this._needAxisTrigger&&this.component.grid&&V.isInside(r,this.component.grid.getArea(),i,n)?this._showingTicket=setTimeout(this._tryShow,this._showDelay):this._needAxisTrigger&&this.component.polar&&-1!=this.component.polar.isInside([i,n])?this._showingTicket=setTimeout(this._tryShow,this._showDelay):(!this._event.connectTrigger&&this.messageCenter.dispatch(s.EVENT.TOOLTIP_OUT_GRID,this._event,null,this.myChart),this._hidingTicket=setTimeout(this._hide,this._hideDelay))}},__onglobalout:function(){clearTimeout(this._hidingTicket),clearTimeout(this._showingTicket),this._hidingTicket=setTimeout(this._hide,this._hideDelay)},__setContent:function(e,t){this._tDom&&(e===this._curTicket&&(this._tDom.innerHTML=t),setTimeout(this._refixed,20))},ontooltipHover:function(e,t){if(!this._lastTipShape||this._lastTipShape&&this._lastTipShape.dataIndex!=e.dataIndex){this._lastTipShape&&this._lastTipShape.tipShape.length>0&&(this.zr.delShape(this._lastTipShape.tipShape),this.shapeList.length=2);for(var i=0,n=t.length;n>i;i++)t[i].zlevel=this.getZlevelBase(),t[i].z=this.getZBase(),t[i].style=p.prototype.getHighlightStyle(t[i].style,t[i].highlightStyle),t[i].draggable=!1,t[i].hoverable=!1,t[i].clickable=!1,t[i].ondragend=null,t[i].ondragover=null,t[i].ondrop=null,this.shapeList.push(t[i]),this.zr.addShape(t[i]);this._lastTipShape={dataIndex:e.dataIndex,tipShape:t}}},ondragend:function(){this._hide()},onlegendSelected:function(e){this._selectedMap=e.selected},_setSelectedMap:function(){this._selectedMap=this.component.legend?d.clone(this.component.legend.getSelectedMap()):{}},_isSelected:function(e){return null!=this._selectedMap[e]?this._selectedMap[e]:!0},showTip:function(e){if(e){var t,i=this.option.series;if(null!=e.seriesIndex)t=e.seriesIndex;else for(var n=e.seriesName,a=0,o=i.length;o>a;a++)if(i[a].name===n){t=a;break}var r=i[t];if(null!=r){var m=this.myChart.chart[r.type],V="axis"===this.deepQuery([r,this.option],"tooltip.trigger");if(m)if(V){var U=e.dataIndex;switch(m.type){case s.CHART_TYPE_LINE:case s.CHART_TYPE_BAR:case s.CHART_TYPE_K:case s.CHART_TYPE_RADAR:if(null==this.component.polar||r.data[0].value.length<=U)return;var d=r.polarIndex||0,p=this.component.polar.getVector(d,U,"max");this._event={zrenderX:p[0],zrenderY:p[1]},this._showPolarTrigger(d,U)}}else{var c,u,y=m.shapeList;switch(m.type){case s.CHART_TYPE_LINE:case s.CHART_TYPE_BAR:case s.CHART_TYPE_K:case s.CHART_TYPE_TREEMAP:case s.CHART_TYPE_SCATTER:for(var U=e.dataIndex,a=0,o=y.length;o>a;a++)if(null==y[a]._mark&&l.get(y[a],"seriesIndex")==t&&l.get(y[a],"dataIndex")==U){this._curTarget=y[a],c=y[a].style.x,u=m.type!=s.CHART_TYPE_K?y[a].style.y:y[a].style.y[0];break}break;case s.CHART_TYPE_RADAR:for(var U=e.dataIndex,a=0,o=y.length;o>a;a++)if("polygon"===y[a].type&&l.get(y[a],"seriesIndex")==t&&l.get(y[a],"dataIndex")==U){this._curTarget=y[a];var p=this.component.polar.getCenter(r.polarIndex||0);c=p[0],u=p[1];break}break;case s.CHART_TYPE_PIE:for(var g=e.name,a=0,o=y.length;o>a;a++)if("sector"===y[a].type&&l.get(y[a],"seriesIndex")==t&&l.get(y[a],"name")==g){this._curTarget=y[a];var b=this._curTarget.style,f=(b.startAngle+b.endAngle)/2*Math.PI/180;c=this._curTarget.style.x+Math.cos(f)*b.r/1.5,u=this._curTarget.style.y-Math.sin(f)*b.r/1.5;break}break;case s.CHART_TYPE_MAP:for(var g=e.name,k=r.mapType,a=0,o=y.length;o>a;a++)if("text"===y[a].type&&y[a]._mapType===k&&y[a].style._name===g){this._curTarget=y[a],c=this._curTarget.style.x+this._curTarget.position[0],u=this._curTarget.style.y+this._curTarget.position[1];break}break;case s.CHART_TYPE_CHORD:for(var g=e.name,a=0,o=y.length;o>a;a++)if("sector"===y[a].type&&l.get(y[a],"name")==g){this._curTarget=y[a];var b=this._curTarget.style,f=(b.startAngle+b.endAngle)/2*Math.PI/180;return c=this._curTarget.style.x+Math.cos(f)*(b.r-2),u=this._curTarget.style.y-Math.sin(f)*(b.r-2),void this.zr.trigger(h.EVENT.MOUSEMOVE,{zrenderX:c,zrenderY:u})}break;case s.CHART_TYPE_FORCE:for(var g=e.name,a=0,o=y.length;o>a;a++)if("circle"===y[a].type&&l.get(y[a],"name")==g){this._curTarget=y[a],c=this._curTarget.position[0],u=this._curTarget.position[1];break}}null!=c&&null!=u&&(this._event={zrenderX:c,zrenderY:u},this.zr.addHoverShape(this._curTarget),this.zr.refreshHover(),this._showItemTrigger())}}}},hideTip:function(){this._hide()},refresh:function(e){if(this._zrHeight=this.zr.getHeight(),this._zrWidth=this.zr.getWidth(),this._lastTipShape&&this._lastTipShape.tipShape.length>0&&this.zr.delShape(this._lastTipShape.tipShape),this._lastTipShape=!1,this.shapeList.length=2,this._lastDataIndex=-1,this._lastSeriesIndex=-1,this._lastItemTriggerId=-1,e){this.option=e,this.option.tooltip=this.reformOption(this.option.tooltip),this.option.tooltip.textStyle=d.merge(this.option.tooltip.textStyle,this.ecTheme.textStyle),this._needAxisTrigger=!1,"axis"===this.option.tooltip.trigger&&(this._needAxisTrigger=!0);for(var t=this.option.series,i=0,n=t.length;n>i;i++)if("axis"===this.query(t[i],"tooltip.trigger")){this._needAxisTrigger=!0;break}this._showDelay=this.option.tooltip.showDelay,this._hideDelay=this.option.tooltip.hideDelay,this._defaultCssText=this._style(this.option.tooltip),this._setSelectedMap(),this._axisLineWidth=this.option.tooltip.axisPointer.lineStyle.width,this._enterable=this.option.tooltip.enterable,!this._enterable&&this._tDom.className.indexOf(h.elementClassName)<0&&(this._tDom.className+=" "+h.elementClassName)}if(this.showing){var a=this;setTimeout(function(){a.zr.trigger(h.EVENT.MOUSEMOVE,a.zr.handler._event)},50)}},onbeforDispose:function(){this._lastTipShape&&this._lastTipShape.tipShape.length>0&&this.zr.delShape(this._lastTipShape.tipShape),clearTimeout(this._hidingTicket),clearTimeout(this._showingTicket),this.zr.un(h.EVENT.MOUSEMOVE,this._onmousemove),this.zr.un(h.EVENT.GLOBALOUT,this._onglobalout),this.hasAppend&&this.dom.firstChild&&this.dom.firstChild.removeChild(this._tDom),this._tDom=null},_encodeHTML:function(e){return String(e).replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}},d.inherits(t,i),e("../component").define("tooltip",t),t}),i("echarts/component/legend",["require","./base","zrender/shape/Text","zrender/shape/Rectangle","zrender/shape/Sector","../util/shape/Icon","../util/shape/Candle","../config","zrender/tool/util","zrender/tool/area","../component"],function(e){function t(e,t,n,a,o){if(!this.query(a,"legend.data"))return void console.error("option.legend.data has not been defined.");i.call(this,e,t,n,a,o);var r=this;r._legendSelected=function(e){r.__legendSelected(e)},r._dispatchHoverLink=function(e){return r.__dispatchHoverLink(e)},this._colorIndex=0,this._colorMap={},this._selectedMap={},this._hasDataMap={},this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Rectangle"),o=e("zrender/shape/Sector"),r=e("../util/shape/Icon"),s=e("../util/shape/Candle"),l=e("../config");l.legend={zlevel:0,z:4,show:!0,orient:"horizontal",x:"center",y:"top",backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,padding:5,itemGap:10,itemWidth:20,itemHeight:14,textStyle:{color:"#333"},selectedMode:!0};var h=e("zrender/tool/util"),m=e("zrender/tool/area");t.prototype={type:l.COMPONENT_TYPE_LEGEND,_buildShape:function(){if(this.legendOption.show){this._itemGroupLocation=this._getItemGroupLocation(),this._buildBackground(),this._buildItem();for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e])}},_buildItem:function(){var e,t,i,a,o,s,l,V,U=this.legendOption.data,d=U.length,p=this.legendOption.textStyle,c=this.zr.getWidth(),u=this.zr.getHeight(),y=this._itemGroupLocation.x,g=this._itemGroupLocation.y,b=this.legendOption.itemWidth,f=this.legendOption.itemHeight,k=this.legendOption.itemGap;"vertical"===this.legendOption.orient&&"right"===this.legendOption.x&&(y=this._itemGroupLocation.x+this._itemGroupLocation.width-b);for(var x=0;d>x;x++)o=h.merge(U[x].textStyle||{},p),s=this.getFont(o),e=this._getName(U[x]),l=this._getFormatterName(e),""!==e?(t=U[x].icon||this._getSomethingByName(e).type,V=this.getColor(e),"horizontal"===this.legendOption.orient?200>c-y&&b+5+m.getTextWidth(l,s)+(x===d-1||""===U[x+1]?0:k)>=c-y&&(y=this._itemGroupLocation.x,g+=f+k):200>u-g&&f+(x===d-1||""===U[x+1]?0:k)>=u-g&&("right"===this.legendOption.x?y-=this._itemGroupLocation.maxWidth+k:y+=this._itemGroupLocation.maxWidth+k,g=this._itemGroupLocation.y),i=this._getItemShapeByType(y,g,b,f,this._selectedMap[e]&&this._hasDataMap[e]?V:"#ccc",t,V),i._name=e,i=new r(i),a={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:y+b+5,y:g+f/2,color:this._selectedMap[e]?"auto"===o.color?V:o.color:"#ccc",text:l,textFont:s,textBaseline:"middle"},highlightStyle:{color:V,brushType:"fill"},hoverable:!!this.legendOption.selectedMode,clickable:!!this.legendOption.selectedMode},"vertical"===this.legendOption.orient&&"right"===this.legendOption.x&&(a.style.x-=b+10,a.style.textAlign="right"),a._name=e,a=new n(a),this.legendOption.selectedMode&&(i.onclick=a.onclick=this._legendSelected,i.onmouseover=a.onmouseover=this._dispatchHoverLink,i.hoverConnect=a.id,a.hoverConnect=i.id),this.shapeList.push(i),this.shapeList.push(a),"horizontal"===this.legendOption.orient?y+=b+5+m.getTextWidth(l,s)+k:g+=f+k):"horizontal"===this.legendOption.orient?(y=this._itemGroupLocation.x,g+=f+k):("right"===this.legendOption.x?y-=this._itemGroupLocation.maxWidth+k:y+=this._itemGroupLocation.maxWidth+k,g=this._itemGroupLocation.y);"horizontal"===this.legendOption.orient&&"center"===this.legendOption.x&&g!=this._itemGroupLocation.y&&this._mLineOptimize()},_getName:function(e){return"undefined"!=typeof e.name?e.name:e},_getFormatterName:function(e){var t,i=this.legendOption.formatter;return t="function"==typeof i?i.call(this.myChart,e):"string"==typeof i?i.replace("{name}",e):e},_getFormatterNameFromData:function(e){var t=this._getName(e);return this._getFormatterName(t)},_mLineOptimize:function(){for(var e=[],t=this._itemGroupLocation.x,i=2,n=this.shapeList.length;n>i;i++)this.shapeList[i].style.x===t?e.push((this._itemGroupLocation.width-(this.shapeList[i-1].style.x+m.getTextWidth(this.shapeList[i-1].style.text,this.shapeList[i-1].style.textFont)-t))/2):i===n-1&&e.push((this._itemGroupLocation.width-(this.shapeList[i].style.x+m.getTextWidth(this.shapeList[i].style.text,this.shapeList[i].style.textFont)-t))/2);for(var a=-1,i=1,n=this.shapeList.length;n>i;i++)this.shapeList[i].style.x===t&&a++,0!==e[a]&&(this.shapeList[i].style.x+=e[a])},_buildBackground:function(){var e=this.reformCssArray(this.legendOption.padding);this.shapeList.push(new a({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._itemGroupLocation.x-e[3],y:this._itemGroupLocation.y-e[0],width:this._itemGroupLocation.width+e[3]+e[1],height:this._itemGroupLocation.height+e[0]+e[2],brushType:0===this.legendOption.borderWidth?"fill":"both",color:this.legendOption.backgroundColor,strokeColor:this.legendOption.borderColor,lineWidth:this.legendOption.borderWidth}}))},_getItemGroupLocation:function(){var e=this.legendOption.data,t=e.length,i=this.legendOption.itemGap,n=this.legendOption.itemWidth+5,a=this.legendOption.itemHeight,o=this.legendOption.textStyle,r=this.getFont(o),s=0,l=0,V=this.reformCssArray(this.legendOption.padding),U=this.zr.getWidth()-V[1]-V[3],d=this.zr.getHeight()-V[0]-V[2],p=0,c=0;if("horizontal"===this.legendOption.orient){l=a;for(var u=0;t>u;u++)if(""!==this._getName(e[u])){var y=m.getTextWidth(this._getFormatterNameFromData(e[u]),e[u].textStyle?this.getFont(h.merge(e[u].textStyle||{},o)):r);p+n+y+i>U?(p-=i,s=Math.max(s,p),l+=a+i,p=0):(p+=n+y+i,s=Math.max(s,p-i))}else p-=i,s=Math.max(s,p),l+=a+i,p=0}else{for(var u=0;t>u;u++)c=Math.max(c,m.getTextWidth(this._getFormatterNameFromData(e[u]),e[u].textStyle?this.getFont(h.merge(e[u].textStyle||{},o)):r));c+=n,s=c;for(var u=0;t>u;u++)""!==this._getName(e[u])?p+a+i>d?(s+=c+i,p-=i,l=Math.max(l,p),p=0):(p+=a+i,l=Math.max(l,p-i)):(s+=c+i,p-=i,l=Math.max(l,p),p=0)}U=this.zr.getWidth(),d=this.zr.getHeight();var g;switch(this.legendOption.x){case"center":g=Math.floor((U-s)/2);break;case"left":g=V[3]+this.legendOption.borderWidth;break;case"right":g=U-s-V[1]-V[3]-2*this.legendOption.borderWidth;break;default:g=this.parsePercent(this.legendOption.x,U)}var b;switch(this.legendOption.y){case"top":b=V[0]+this.legendOption.borderWidth;break;case"bottom":b=d-l-V[0]-V[2]-2*this.legendOption.borderWidth;break;case"center":b=Math.floor((d-l)/2);break;default:b=this.parsePercent(this.legendOption.y,d)}return{x:g,y:b,width:s,height:l,maxWidth:c}},_getSomethingByName:function(e){for(var t,i=this.option.series,n=0,a=i.length;a>n;n++){if(i[n].name===e)return{type:i[n].type,series:i[n],seriesIndex:n,data:null,dataIndex:-1};if(i[n].type===l.CHART_TYPE_PIE||i[n].type===l.CHART_TYPE_RADAR||i[n].type===l.CHART_TYPE_CHORD||i[n].type===l.CHART_TYPE_FORCE||i[n].type===l.CHART_TYPE_FUNNEL||i[n].type===l.CHART_TYPE_TREEMAP){t=i[n].categories||i[n].data||i[n].nodes;for(var o=0,r=t.length;r>o;o++)if(t[o].name===e)return{type:i[n].type,series:i[n],seriesIndex:n,data:t[o],dataIndex:o}}}return{type:"bar",series:null,seriesIndex:-1,data:null,dataIndex:-1}},_getItemShapeByType:function(e,t,i,n,a,o,r){var s,h="#ccc"===a?r:a,m={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{iconType:"legendicon"+o,x:e,y:t,width:i,height:n,color:a,strokeColor:a,lineWidth:2},highlightStyle:{color:h,strokeColor:h,lineWidth:1},hoverable:this.legendOption.selectedMode,clickable:this.legendOption.selectedMode};if(o.match("image")){var s=o.replace(new RegExp("^image:\\/\\/"),"");o="image"}switch(o){case"line":m.style.brushType="stroke",m.highlightStyle.lineWidth=3;break;case"radar":case"venn":case"tree":case"treemap":case"scatter":m.highlightStyle.lineWidth=3;break;case"k":m.style.brushType="both",m.highlightStyle.lineWidth=3,m.highlightStyle.color=m.style.color=this.deepQuery([this.ecTheme,l],"k.itemStyle.normal.color")||"#fff",m.style.strokeColor="#ccc"!=a?this.deepQuery([this.ecTheme,l],"k.itemStyle.normal.lineStyle.color")||"#ff3200":a;break;case"image":m.style.iconType="image",m.style.image=s,"#ccc"===a&&(m.style.opacity=.5)}return m},__legendSelected:function(e){var t=e.target._name;if("single"===this.legendOption.selectedMode)for(var i in this._selectedMap)this._selectedMap[i]=!1;this._selectedMap[t]=!this._selectedMap[t],this.messageCenter.dispatch(l.EVENT.LEGEND_SELECTED,e.event,{selected:this._selectedMap,target:t},this.myChart)},__dispatchHoverLink:function(e){this.messageCenter.dispatch(l.EVENT.LEGEND_HOVERLINK,e.event,{target:e.target._name},this.myChart)},refresh:function(e){if(e){this.option=e||this.option,this.option.legend=this.reformOption(this.option.legend),this.legendOption=this.option.legend;var t,i,n,a,o=this.legendOption.data||[];if(this.legendOption.selected)for(var r in this.legendOption.selected)this._selectedMap[r]="undefined"!=typeof this._selectedMap[r]?this._selectedMap[r]:this.legendOption.selected[r];for(var s=0,h=o.length;h>s;s++)t=this._getName(o[s]),""!==t&&(i=this._getSomethingByName(t),i.series?(this._hasDataMap[t]=!0,a=!i.data||i.type!==l.CHART_TYPE_PIE&&i.type!==l.CHART_TYPE_FORCE&&i.type!==l.CHART_TYPE_FUNNEL?[i.series]:[i.data,i.series],n=this.getItemStyleColor(this.deepQuery(a,"itemStyle.normal.color"),i.seriesIndex,i.dataIndex,i.data),n&&i.type!=l.CHART_TYPE_K&&this.setColor(t,n),this._selectedMap[t]=null!=this._selectedMap[t]?this._selectedMap[t]:!0):this._hasDataMap[t]=!1)}this.clear(),this._buildShape()},getRelatedAmount:function(e){for(var t,i=0,n=this.option.series,a=0,o=n.length;o>a;a++)if(n[a].name===e&&i++,n[a].type===l.CHART_TYPE_PIE||n[a].type===l.CHART_TYPE_RADAR||n[a].type===l.CHART_TYPE_CHORD||n[a].type===l.CHART_TYPE_FORCE||n[a].type===l.CHART_TYPE_FUNNEL){t=n[a].type!=l.CHART_TYPE_FORCE?n[a].data:n[a].categories;for(var r=0,s=t.length;s>r;r++)t[r].name===e&&"-"!=t[r].value&&i++}return i},setColor:function(e,t){this._colorMap[e]=t},getColor:function(e){return this._colorMap[e]||(this._colorMap[e]=this.zr.getColor(this._colorIndex++)),this._colorMap[e]},hasColor:function(e){return this._colorMap[e]?this._colorMap[e]:!1},add:function(e,t){ +for(var i=this.legendOption.data,n=0,a=i.length;a>n;n++)if(this._getName(i[n])===e)return;this.legendOption.data.push(e),this.setColor(e,t),this._selectedMap[e]=!0,this._hasDataMap[e]=!0},del:function(e){for(var t=this.legendOption.data,i=0,n=t.length;n>i;i++)if(this._getName(t[i])===e)return this.legendOption.data.splice(i,1)},getItemShape:function(e){if(null!=e)for(var t,i=0,n=this.shapeList.length;n>i;i++)if(t=this.shapeList[i],t._name===e&&"text"!=t.type)return t},setItemShape:function(e,t){for(var i,n=0,a=this.shapeList.length;a>n;n++)i=this.shapeList[n],i._name===e&&"text"!=i.type&&(this._selectedMap[e]||(t.style.color="#ccc",t.style.strokeColor="#ccc"),this.zr.modShape(i.id,t))},isSelected:function(e){return"undefined"!=typeof this._selectedMap[e]?this._selectedMap[e]:!0},getSelectedMap:function(){return this._selectedMap},setSelected:function(e,t){if("single"===this.legendOption.selectedMode)for(var i in this._selectedMap)this._selectedMap[i]=!1;this._selectedMap[e]=t,this.messageCenter.dispatch(l.EVENT.LEGEND_SELECTED,null,{selected:this._selectedMap,target:e},this.myChart)},onlegendSelected:function(e,t){var i=e.selected;for(var n in i)this._selectedMap[n]!=i[n]&&(t.needRefresh=!0),this._selectedMap[n]=i[n]}};var V={line:function(e,t){var i=t.height/2;e.moveTo(t.x,t.y+i),e.lineTo(t.x+t.width,t.y+i)},pie:function(e,t){var i=t.x,n=t.y,a=t.width,r=t.height;o.prototype.buildPath(e,{x:i+a/2,y:n+r+2,r:r,r0:6,startAngle:45,endAngle:135})},eventRiver:function(e,t){var i=t.x,n=t.y,a=t.width,o=t.height;e.moveTo(i,n+o),e.bezierCurveTo(i+a,n+o,i,n+4,i+a,n+4),e.lineTo(i+a,n),e.bezierCurveTo(i,n,i+a,n+o-4,i,n+o-4),e.lineTo(i,n+o)},k:function(e,t){var i=t.x,n=t.y,a=t.width,o=t.height;s.prototype.buildPath(e,{x:i+a/2,y:[n+1,n+1,n+o-6,n+o],width:a-6})},bar:function(e,t){var i=t.x,n=t.y+1,a=t.width,o=t.height-2,r=3;e.moveTo(i+r,n),e.lineTo(i+a-r,n),e.quadraticCurveTo(i+a,n,i+a,n+r),e.lineTo(i+a,n+o-r),e.quadraticCurveTo(i+a,n+o,i+a-r,n+o),e.lineTo(i+r,n+o),e.quadraticCurveTo(i,n+o,i,n+o-r),e.lineTo(i,n+r),e.quadraticCurveTo(i,n,i+r,n)},force:function(e,t){r.prototype.iconLibrary.circle(e,t)},radar:function(e,t){var i=6,n=t.x+t.width/2,a=t.y+t.height/2,o=t.height/2,r=2*Math.PI/i,s=-Math.PI/2,l=n+o*Math.cos(s),h=a+o*Math.sin(s);e.moveTo(l,h),s+=r;for(var m=0,V=i-1;V>m;m++)e.lineTo(n+o*Math.cos(s),a+o*Math.sin(s)),s+=r;e.lineTo(l,h)}};V.chord=V.pie,V.map=V.bar;for(var U in V)r.prototype.iconLibrary["legendicon"+U]=V[U];return h.inherits(t,i),e("../component").define("legend",t),t}),i("echarts/util/ecData",[],function(){function e(e,t,i,n,a,o,r,s){var l;return"undefined"!=typeof n&&(l=null==n.value?n:n.value),e._echartsData={_series:t,_seriesIndex:i,_data:n,_dataIndex:a,_name:o,_value:l,_special:r,_special2:s},e._echartsData}function t(e,t){var i=e._echartsData;if(!t)return i;switch(t){case"series":case"seriesIndex":case"data":case"dataIndex":case"name":case"value":case"special":case"special2":return i&&i["_"+t]}return null}function i(e,t,i){switch(e._echartsData=e._echartsData||{},t){case"series":case"seriesIndex":case"data":case"dataIndex":case"name":case"value":case"special":case"special2":e._echartsData["_"+t]=i}}function n(e,t){t._echartsData={_series:e._echartsData._series,_seriesIndex:e._echartsData._seriesIndex,_data:e._echartsData._data,_dataIndex:e._echartsData._dataIndex,_name:e._echartsData._name,_value:e._echartsData._value,_special:e._echartsData._special,_special2:e._echartsData._special2}}return{pack:e,set:i,get:t,clone:n}}),i("echarts/chart",[],function(){var e={},t={};return e.define=function(i,n){return t[i]=n,e},e.get=function(e){return t[e]},e}),i("zrender/tool/color",["require","../tool/util"],function(e){function t(e){D=e}function i(){D=N}function n(e,t){return e=0|e,t=t||D,t[e%t.length]}function a(e){B=e}function o(){H=B}function r(){return B}function s(e,t,i,n,a,o,r){O||(O=P.getContext());for(var s=O.createRadialGradient(e,t,i,n,a,o),l=0,h=r.length;h>l;l++)s.addColorStop(r[l][0],r[l][1]);return s.__nonRecursion=!0,s}function l(e,t,i,n,a){O||(O=P.getContext());for(var o=O.createLinearGradient(e,t,i,n),r=0,s=a.length;s>r;r++)o.addColorStop(a[r][0],a[r][1]);return o.__nonRecursion=!0,o}function h(e,t,i){e=p(e),t=p(t),e=I(e),t=I(t);for(var n=[],a=(t[0]-e[0])/i,o=(t[1]-e[1])/i,r=(t[2]-e[2])/i,s=(t[3]-e[3])/i,l=0,h=e[0],m=e[1],U=e[2],d=e[3];i>l;l++)n[l]=V([S(Math.floor(h),[0,255]),S(Math.floor(m),[0,255]),S(Math.floor(U),[0,255]),d.toFixed(4)-0],"rgba"),h+=a,m+=o,U+=r,d+=s;return h=t[0],m=t[1],U=t[2],d=t[3],n[l]=V([h,m,U,d],"rgba"),n}function m(e,t){var i=[],n=e.length;if(void 0===t&&(t=20),1===n)i=h(e[0],e[0],t);else if(n>1)for(var a=0,o=n-1;o>a;a++){var r=h(e[a],e[a+1],t);o-1>a&&r.pop(),i=i.concat(r)}return i}function V(e,t){if(t=t||"rgb",e&&(3===e.length||4===e.length)){if(e=C(e,function(e){return e>1?Math.ceil(e):e}),t.indexOf("hex")>-1)return"#"+((1<<24)+(e[0]<<16)+(e[1]<<8)+ +e[2]).toString(16).slice(1);if(t.indexOf("hs")>-1){var i=C(e.slice(1,3),function(e){return e+"%"});e[1]=i[0],e[2]=i[1]}return t.indexOf("a")>-1?(3===e.length&&e.push(1),e[3]=S(e[3],[0,1]),t+"("+e.slice(0,4).join(",")+")"):t+"("+e.slice(0,3).join(",")+")"}}function U(e){e=L(e),e.indexOf("rgba")<0&&(e=p(e));var t=[],i=0;return e.replace(/[\d.]+/g,function(e){e=3>i?0|e:+e,t[i++]=e}),t}function d(e,t){if(!E(e))return e;var i=I(e),n=i[3];return"undefined"==typeof n&&(n=1),e.indexOf("hsb")>-1?i=F(i):e.indexOf("hsl")>-1&&(i=T(i)),t.indexOf("hsb")>-1||t.indexOf("hsv")>-1?i=A(i):t.indexOf("hsl")>-1&&(i=M(i)),i[3]=n,V(i,t)}function p(e){return d(e,"rgba")}function c(e){return d(e,"rgb")}function u(e){return d(e,"hex")}function y(e){return d(e,"hsva")}function g(e){return d(e,"hsv")}function b(e){return d(e,"hsba")}function f(e){return d(e,"hsb")}function k(e){return d(e,"hsla")}function x(e){return d(e,"hsl")}function _(e){for(var t in G)if(u(G[t])===u(e))return t;return null}function L(e){return String(e).replace(/\s+/g,"")}function W(e){if(G[e]&&(e=G[e]),e=L(e),e=e.replace(/hsv/i,"hsb"),/^#[\da-f]{3}$/i.test(e)){e=parseInt(e.slice(1),16);var t=(3840&e)<<8,i=(240&e)<<4,n=15&e;e="#"+((1<<24)+(t<<4)+t+(i<<4)+i+(n<<4)+n).toString(16).slice(1)}return e}function X(e,t){if(!E(e))return e;var i=t>0?1:-1;"undefined"==typeof t&&(t=0),t=Math.abs(t)>1?1:Math.abs(t),e=c(e);for(var n=I(e),a=0;3>a;a++)n[a]=1===i?n[a]*(1-t)|0:(255-n[a])*t+n[a]|0;return"rgb("+n.join(",")+")"}function v(e){if(!E(e))return e;var t=I(p(e));return t=C(t,function(e){return 255-e}),V(t,"rgb")}function w(e,t,i){if(!E(e)||!E(t))return e;"undefined"==typeof i&&(i=.5),i=1-S(i,[0,1]);for(var n=2*i-1,a=I(p(e)),o=I(p(t)),r=a[3]-o[3],s=((n*r===-1?n:(n+r)/(1+n*r))+1)/2,l=1-s,h=[],m=0;3>m;m++)h[m]=a[m]*s+o[m]*l;var U=a[3]*i+o[3]*(1-i);return U=Math.max(0,Math.min(1,U)),1===a[3]&&1===o[3]?V(h,"rgb"):(h[3]=U,V(h,"rgba"))}function K(){return"#"+(Math.random().toString(16)+"0000").slice(2,8)}function I(e){e=W(e);var t=e.match(R);if(null===t)throw new Error("The color format error");var i,n,a,o=[];if(t[2])i=t[2].replace("#","").split(""),a=[i[0]+i[1],i[2]+i[3],i[4]+i[5]],o=C(a,function(e){return S(parseInt(e,16),[0,255])});else if(t[4]){var r=t[4].split(",");n=r[3],a=r.slice(0,3),o=C(a,function(e){return e=Math.floor(e.indexOf("%")>0?2.55*parseInt(e,0):e),S(e,[0,255])}),"undefined"!=typeof n&&o.push(S(parseFloat(n),[0,1]))}else if(t[5]||t[6]){var s=(t[5]||t[6]).split(","),l=parseInt(s[0],0)/360,h=s[1],m=s[2];n=s[3],o=C([h,m],function(e){return S(parseFloat(e)/100,[0,1])}),o.unshift(l),"undefined"!=typeof n&&o.push(S(parseFloat(n),[0,1]))}return o}function J(e,t){if(!E(e))return e;null===t&&(t=1);var i=I(p(e));return i[3]=S(Number(t).toFixed(4),[0,1]),V(i,"rgba")}function C(e,t){if("function"!=typeof t)throw new TypeError;for(var i=e?e.length:0,n=0;i>n;n++)e[n]=t(e[n]);return e}function S(e,t){return e<=t[0]?e=t[0]:e>=t[1]&&(e=t[1]),e}function E(e){return e instanceof Array||"string"==typeof e}function F(e){var t,i,n,a=e[0],o=e[1],r=e[2];if(0===o)t=255*r,i=255*r,n=255*r;else{var s=6*a;6===s&&(s=0);var l=0|s,h=r*(1-o),m=r*(1-o*(s-l)),V=r*(1-o*(1-(s-l))),U=0,d=0,p=0;0===l?(U=r,d=V,p=h):1===l?(U=m,d=r,p=h):2===l?(U=h,d=r,p=V):3===l?(U=h,d=m,p=r):4===l?(U=V,d=h,p=r):(U=r,d=h,p=m),t=255*U,i=255*d,n=255*p}return[t,i,n]}function T(e){var t,i,n,a=e[0],o=e[1],r=e[2];if(0===o)t=255*r,i=255*r,n=255*r;else{var s;s=.5>r?r*(1+o):r+o-o*r;var l=2*r-s;t=255*z(l,s,a+1/3),i=255*z(l,s,a),n=255*z(l,s,a-1/3)}return[t,i,n]}function z(e,t,i){return 0>i&&(i+=1),i>1&&(i-=1),1>6*i?e+6*(t-e)*i:1>2*i?t:2>3*i?e+(t-e)*(2/3-i)*6:e}function A(e){var t,i,n=e[0]/255,a=e[1]/255,o=e[2]/255,r=Math.min(n,a,o),s=Math.max(n,a,o),l=s-r,h=s;if(0===l)t=0,i=0;else{i=l/s;var m=((s-n)/6+l/2)/l,V=((s-a)/6+l/2)/l,U=((s-o)/6+l/2)/l;n===s?t=U-V:a===s?t=1/3+m-U:o===s&&(t=2/3+V-m),0>t&&(t+=1),t>1&&(t-=1)}return t=360*t,i=100*i,h=100*h,[t,i,h]}function M(e){var t,i,n=e[0]/255,a=e[1]/255,o=e[2]/255,r=Math.min(n,a,o),s=Math.max(n,a,o),l=s-r,h=(s+r)/2;if(0===l)t=0,i=0;else{i=.5>h?l/(s+r):l/(2-s-r);var m=((s-n)/6+l/2)/l,V=((s-a)/6+l/2)/l,U=((s-o)/6+l/2)/l;n===s?t=U-V:a===s?t=1/3+m-U:o===s&&(t=2/3+V-m),0>t&&(t+=1),t>1&&(t-=1)}return t=360*t,i=100*i,h=100*h,[t,i,h]}var O,P=e("../tool/util"),D=["#ff9277"," #dddd00"," #ffc877"," #bbe3ff"," #d5ffbb","#bbbbff"," #ddb000"," #b0dd00"," #e2bbff"," #ffbbe3","#ff7777"," #ff9900"," #83dd00"," #77e3ff"," #778fff","#c877ff"," #ff77ab"," #ff6600"," #aa8800"," #77c7ff","#ad77ff"," #ff77ff"," #dd0083"," #777700"," #00aa00","#0088aa"," #8400dd"," #aa0088"," #dd0000"," #772e00"],N=D,B="rgba(255,255,0,0.5)",H=B,R=/^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i,G={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#0ff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000",blanchedalmond:"#ffebcd",blue:"#00f",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#0ff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgrey:"#a9a9a9",darkgreen:"#006400",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#f0f",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",grey:"#808080",green:"#008000",greenyellow:"#adff2f",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgrey:"#d3d3d3",lightgreen:"#90ee90",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#789",lightslategrey:"#789",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#0f0",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#f0f",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370d8",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#d87093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#f00",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#fff",whitesmoke:"#f5f5f5",yellow:"#ff0",yellowgreen:"#9acd32"};return{customPalette:t,resetPalette:i,getColor:n,getHighlightColor:r,customHighlight:a,resetHighlight:o,getRadialGradient:s,getLinearGradient:l,getGradientColors:m,getStepColors:h,reverse:v,mix:w,lift:X,trim:L,random:K,toRGB:c,toRGBA:p,toHex:u,toHSL:x,toHSLA:k,toHSB:f,toHSBA:b,toHSV:g,toHSVA:y,toName:_,toColor:V,toArray:U,alpha:J,getData:I}}),i("echarts/component/timeline",["require","./base","zrender/shape/Rectangle","../util/shape/Icon","../util/shape/Chain","../config","zrender/tool/util","zrender/tool/area","zrender/tool/event","../component"],function(e){function t(e,t,i,a,o){n.call(this,e,t,i,a,o);var r=this;if(r._onclick=function(e){return r.__onclick(e)},r._ondrift=function(e,t){return r.__ondrift(this,e,t)},r._ondragend=function(){return r.__ondragend()},r._setCurrentOption=function(){var e=r.timelineOption;r.currentIndex%=e.data.length;var t=r.options[r.currentIndex]||{};r.myChart._setOption(t,e.notMerge,!0),r.messageCenter.dispatch(s.EVENT.TIMELINE_CHANGED,null,{currentIndex:r.currentIndex,data:null!=e.data[r.currentIndex].name?e.data[r.currentIndex].name:e.data[r.currentIndex]},r.myChart)},r._onFrame=function(){r._setCurrentOption(),r._syncHandleShape(),r.timelineOption.autoPlay&&(r.playTicket=setTimeout(function(){return r.currentIndex+=1,!r.timelineOption.loop&&r.currentIndex>=r.timelineOption.data.length?(r.currentIndex=r.timelineOption.data.length-1,void r.stop()):void r._onFrame()},r.timelineOption.playInterval))},this.setTheme(!1),this.options=this.option.options,this.currentIndex=this.timelineOption.currentIndex%this.timelineOption.data.length,this.timelineOption.notMerge||0===this.currentIndex||(this.options[this.currentIndex]=l.merge(this.options[this.currentIndex],this.options[0])),this.timelineOption.show&&(this._buildShape(),this._syncHandleShape()),this._setCurrentOption(),this.timelineOption.autoPlay){var r=this;this.playTicket=setTimeout(function(){r.play()},null!=this.ecTheme.animationDuration?this.ecTheme.animationDuration:s.animationDuration)}}function i(e,t){var i=2,n=t.x+i,a=t.y+i+2,r=t.width-i,s=t.height-i,l=t.symbol;if("last"===l)e.moveTo(n+r-2,a+s/3),e.lineTo(n+r-2,a),e.lineTo(n+2,a+s/2),e.lineTo(n+r-2,a+s),e.lineTo(n+r-2,a+s/3*2),e.moveTo(n,a),e.lineTo(n,a);else if("next"===l)e.moveTo(n+2,a+s/3),e.lineTo(n+2,a),e.lineTo(n+r-2,a+s/2),e.lineTo(n+2,a+s),e.lineTo(n+2,a+s/3*2),e.moveTo(n,a),e.lineTo(n,a);else if("play"===l)if("stop"===t.status)e.moveTo(n+2,a),e.lineTo(n+r-2,a+s/2),e.lineTo(n+2,a+s),e.lineTo(n+2,a);else{var h="both"===t.brushType?2:3;e.rect(n+2,a,h,s),e.rect(n+r-h-2,a,h,s)}else if(l.match("image")){var m="";m=l.replace(new RegExp("^image:\\/\\/"),""),l=o.prototype.iconLibrary.image,l(e,{x:n,y:a,width:r,height:s,image:m})}}var n=e("./base"),a=e("zrender/shape/Rectangle"),o=e("../util/shape/Icon"),r=e("../util/shape/Chain"),s=e("../config");s.timeline={zlevel:0,z:4,show:!0,type:"time",notMerge:!1,realtime:!0,x:80,x2:80,y2:0,height:50,backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,padding:5,controlPosition:"left",autoPlay:!1,loop:!0,playInterval:2e3,lineStyle:{width:1,color:"#666",type:"dashed"},label:{show:!0,interval:"auto",rotate:0,textStyle:{color:"#333"}},checkpointStyle:{symbol:"auto",symbolSize:"auto",color:"auto",borderColor:"auto",borderWidth:"auto",label:{show:!1,textStyle:{color:"auto"}}},controlStyle:{itemSize:15,itemGap:5,normal:{color:"#333"},emphasis:{color:"#1e90ff"}},symbol:"emptyDiamond",symbolSize:4,currentIndex:0};var l=e("zrender/tool/util"),h=e("zrender/tool/area"),m=e("zrender/tool/event");return t.prototype={type:s.COMPONENT_TYPE_TIMELINE,_buildShape:function(){if(this._location=this._getLocation(),this._buildBackground(),this._buildControl(),this._chainPoint=this._getChainPoint(),this.timelineOption.label.show)for(var e=this._getInterval(),t=0,i=this._chainPoint.length;i>t;t+=e)this._chainPoint[t].showLabel=!0;this._buildChain(),this._buildHandle();for(var t=0,n=this.shapeList.length;n>t;t++)this.zr.addShape(this.shapeList[t])},_getLocation:function(){var e,t=this.timelineOption,i=this.reformCssArray(this.timelineOption.padding),n=this.zr.getWidth(),a=this.parsePercent(t.x,n),o=this.parsePercent(t.x2,n);null==t.width?(e=n-a-o,o=n-o):(e=this.parsePercent(t.width,n),o=a+e);var r,s,l=this.zr.getHeight(),h=this.parsePercent(t.height,l);return null!=t.y?(r=this.parsePercent(t.y,l),s=r+h):(s=l-this.parsePercent(t.y2,l),r=s-h),{x:a+i[3],y:r+i[0],x2:o-i[1],y2:s-i[2],width:e-i[1]-i[3],height:h-i[0]-i[2]}},_getReformedLabel:function(e){var t=this.timelineOption,i=null!=t.data[e].name?t.data[e].name:t.data[e],n=t.data[e].formatter||t.label.formatter;return n&&("function"==typeof n?i=n.call(this.myChart,i):"string"==typeof n&&(i=n.replace("{value}",i))),i},_getInterval:function(){var e=this._chainPoint,t=this.timelineOption,i=t.label.interval;if("auto"===i){var n=t.label.textStyle.fontSize,a=t.data,o=t.data.length;if(o>3){var r,s,l=!1;for(i=0;!l&&o>i;){i++,l=!0;for(var m=i;o>m;m+=i){if(r=e[m].x-e[m-i].x,0!==t.label.rotate)s=n;else if(a[m].textStyle)s=h.getTextWidth(e[m].name,e[m].textFont);else{var V=e[m].name+"",U=(V.match(/\w/g)||"").length,d=V.length-U;s=U*n*2/3+d*n}if(s>r){l=!1;break}}}}else i=1}else i=i-0+1;return i},_getChainPoint:function(){function e(e){return null!=h[e].name?h[e].name:h[e]+""}var t,i=this.timelineOption,n=i.symbol.toLowerCase(),a=i.symbolSize,o=i.label.rotate,r=i.label.textStyle,s=this.getFont(r),h=i.data,m=this._location.x,V=this._location.y+this._location.height/4*3,U=this._location.x2-this._location.x,d=h.length,p=[];if(d>1){var c=U/d;if(c=c>50?50:20>c?5:c,U-=2*c,"number"===i.type)for(var u=0;d>u;u++)p.push(m+c+U/(d-1)*u);else{p[0]=new Date(e(0).replace(/-/g,"/")),p[d-1]=new Date(e(d-1).replace(/-/g,"/"))-p[0];for(var u=1;d>u;u++)p[u]=m+c+U*(new Date(e(u).replace(/-/g,"/"))-p[0])/p[d-1];p[0]=m+c}}else p.push(m+U/2);for(var y,g,b,f,k,x=[],u=0;d>u;u++)m=p[u],y=h[u].symbol&&h[u].symbol.toLowerCase()||n,y.match("empty")?(y=y.replace("empty",""),b=!0):b=!1,y.match("star")&&(g=y.replace("star","")-0||5,y="star"),t=h[u].textStyle?l.merge(h[u].textStyle||{},r):r,f=t.align||"center",o?(f=o>0?"right":"left",k=[o*Math.PI/180,m,V-5]):k=!1,x.push({x:m,n:g,isEmpty:b,symbol:y,symbolSize:h[u].symbolSize||a,color:h[u].color,borderColor:h[u].borderColor,borderWidth:h[u].borderWidth,name:this._getReformedLabel(u),textColor:t.color,textAlign:f,textBaseline:t.baseline||"middle",textX:m,textY:V-(o?5:0),textFont:h[u].textStyle?this.getFont(t):s,rotation:k,showLabel:!1});return x},_buildBackground:function(){var e=this.timelineOption,t=this.reformCssArray(this.timelineOption.padding),i=this._location.width,n=this._location.height;(0!==e.borderWidth||"rgba(0,0,0,0)"!=e.backgroundColor.replace(/\s/g,""))&&this.shapeList.push(new a({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._location.x-t[3],y:this._location.y-t[0],width:i+t[1]+t[3],height:n+t[0]+t[2],brushType:0===e.borderWidth?"fill":"both",color:e.backgroundColor,strokeColor:e.borderColor,lineWidth:e.borderWidth}}))},_buildControl:function(){var e=this,t=this.timelineOption,i=t.lineStyle,n=t.controlStyle;if("none"!==t.controlPosition){var a,r=n.itemSize,s=n.itemGap;"left"===t.controlPosition?(a=this._location.x,this._location.x+=3*(r+s)):(a=this._location.x2-(3*(r+s)-s),this._location.x2-=3*(r+s));var h=this._location.y,m={zlevel:this.getZlevelBase(),z:this.getZBase()+1,style:{iconType:"timelineControl",symbol:"last",x:a,y:h,width:r,height:r,brushType:"stroke",color:n.normal.color,strokeColor:n.normal.color,lineWidth:i.width},highlightStyle:{color:n.emphasis.color,strokeColor:n.emphasis.color,lineWidth:i.width+1},clickable:!0};this._ctrLastShape=new o(m),this._ctrLastShape.onclick=function(){e.last()},this.shapeList.push(this._ctrLastShape),a+=r+s,this._ctrPlayShape=new o(l.clone(m)),this._ctrPlayShape.style.brushType="fill",this._ctrPlayShape.style.symbol="play",this._ctrPlayShape.style.status=this.timelineOption.autoPlay?"playing":"stop",this._ctrPlayShape.style.x=a,this._ctrPlayShape.onclick=function(){"stop"===e._ctrPlayShape.style.status?e.play():e.stop()},this.shapeList.push(this._ctrPlayShape),a+=r+s,this._ctrNextShape=new o(l.clone(m)),this._ctrNextShape.style.symbol="next",this._ctrNextShape.style.x=a,this._ctrNextShape.onclick=function(){e.next()},this.shapeList.push(this._ctrNextShape)}},_buildChain:function(){var e=this.timelineOption,t=e.lineStyle;this._timelineShae={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:this._location.x,y:this.subPixelOptimize(this._location.y,t.width),width:this._location.x2-this._location.x,height:this._location.height,chainPoint:this._chainPoint,brushType:"both",strokeColor:t.color,lineWidth:t.width,lineType:t.type},hoverable:!1,clickable:!0,onclick:this._onclick},this._timelineShae=new r(this._timelineShae),this.shapeList.push(this._timelineShae)},_buildHandle:function(){var e=this._chainPoint[this.currentIndex],t=e.symbolSize+1;t=5>t?5:t,this._handleShape={zlevel:this.getZlevelBase(),z:this.getZBase()+1,hoverable:!1,draggable:!0,style:{iconType:"diamond",n:e.n,x:e.x-t,y:this._location.y+this._location.height/4-t,width:2*t,height:2*t,brushType:"both",textPosition:"specific",textX:e.x,textY:this._location.y-this._location.height/4,textAlign:"center",textBaseline:"middle"},highlightStyle:{},ondrift:this._ondrift,ondragend:this._ondragend},this._handleShape=new o(this._handleShape),this.shapeList.push(this._handleShape)},_syncHandleShape:function(){if(this.timelineOption.show){var e=this.timelineOption,t=e.checkpointStyle,i=this._chainPoint[this.currentIndex];this._handleShape.style.text=t.label.show?i.name:"",this._handleShape.style.textFont=i.textFont,this._handleShape.style.n=i.n,"auto"===t.symbol?this._handleShape.style.iconType="none"!=i.symbol?i.symbol:"diamond":(this._handleShape.style.iconType=t.symbol,t.symbol.match("star")&&(this._handleShape.style.n=t.symbol.replace("star","")-0||5,this._handleShape.style.iconType="star"));var n;"auto"===t.symbolSize?(n=i.symbolSize+2,n=5>n?5:n):n=t.symbolSize-0,this._handleShape.style.color="auto"===t.color?i.color?i.color:e.controlStyle.emphasis.color:t.color,this._handleShape.style.textColor="auto"===t.label.textStyle.color?this._handleShape.style.color:t.label.textStyle.color,this._handleShape.highlightStyle.strokeColor=this._handleShape.style.strokeColor="auto"===t.borderColor?i.borderColor?i.borderColor:"#fff":t.borderColor,this._handleShape.style.lineWidth="auto"===t.borderWidth?i.borderWidth?i.borderWidth:0:t.borderWidth-0,this._handleShape.highlightStyle.lineWidth=this._handleShape.style.lineWidth+1,this.zr.animate(this._handleShape.id,"style").when(500,{x:i.x-n,textX:i.x,y:this._location.y+this._location.height/4-n,width:2*n,height:2*n}).start("ExponentialOut")}},_findChainIndex:function(e){var t=this._chainPoint,i=t.length;if(e<=t[0].x)return 0;if(e>=t[i-1].x)return i-1;for(var n=0;i-1>n;n++)if(e>=t[n].x&&e<=t[n+1].x)return Math.abs(e-t[n].x)=n[a-1].x-n[a-1].symbolSize?(e.style.x=n[a-1].x-n[a-1].symbolSize,i=a-1):(e.style.x+=t,i=this._findChainIndex(e.style.x));var o=n[i],r=o.symbolSize+2;if(e.style.iconType=o.symbol,e.style.n=o.n,e.style.textX=e.style.x+r/2,e.style.y=this._location.y+this._location.height/4-r,e.style.width=2*r,e.style.height=2*r,e.style.text=o.name,i===this.currentIndex)return!0;if(this.currentIndex=i,this.timelineOption.realtime){clearTimeout(this.playTicket);var s=this;this.playTicket=setTimeout(function(){s._setCurrentOption()},200)}return!0},__ondragend:function(){this.isDragend=!0},ondragend:function(e,t){this.isDragend&&e.target&&(!this.timelineOption.realtime&&this._setCurrentOption(),t.dragOut=!0,t.dragIn=!0,t.needRefresh=!1,this.isDragend=!1,this._syncHandleShape())},last:function(){return this.timelineOption.autoPlay&&this.stop(),this.currentIndex-=1,this.currentIndex<0&&(this.currentIndex=this.timelineOption.data.length-1),this._onFrame(),this.currentIndex},next:function(){return this.timelineOption.autoPlay&&this.stop(),this.currentIndex+=1,this.currentIndex>=this.timelineOption.data.length&&(this.currentIndex=0),this._onFrame(),this.currentIndex},play:function(e,t){return this._ctrPlayShape&&"playing"!=this._ctrPlayShape.style.status&&(this._ctrPlayShape.style.status="playing",this.zr.modShape(this._ctrPlayShape.id),this.zr.refreshNextFrame()),this.timelineOption.autoPlay=null!=t?t:!0,this.timelineOption.autoPlay||clearTimeout(this.playTicket),this.currentIndex=null!=e?e:this.currentIndex+1,this.currentIndex>=this.timelineOption.data.length&&(this.currentIndex=0),this._onFrame(),this.currentIndex},stop:function(){return this._ctrPlayShape&&"stop"!=this._ctrPlayShape.style.status&&(this._ctrPlayShape.style.status="stop",this.zr.modShape(this._ctrPlayShape.id),this.zr.refreshNextFrame()),this.timelineOption.autoPlay=!1,clearTimeout(this.playTicket),this.currentIndex},resize:function(){this.timelineOption.show&&(this.clear(),this._buildShape(),this._syncHandleShape())},setTheme:function(e){this.timelineOption=this.reformOption(l.clone(this.option.timeline)),this.timelineOption.label.textStyle=this.getTextStyle(this.timelineOption.label.textStyle),this.timelineOption.checkpointStyle.label.textStyle=this.getTextStyle(this.timelineOption.checkpointStyle.label.textStyle),this.myChart.canvasSupported||(this.timelineOption.realtime=!1),this.timelineOption.show&&e&&(this.clear(),this._buildShape(),this._syncHandleShape())},onbeforDispose:function(){clearTimeout(this.playTicket)}},o.prototype.iconLibrary.timelineControl=i,l.inherits(t,n),e("../component").define("timeline",t),t}),i("zrender/shape/Image",["require","./Base","../tool/util"],function(e){var t=e("./Base"),i=function(e){t.call(this,e)};return i.prototype={type:"image",brush:function(e,t,i){var n=this.style||{};t&&(n=this.getHighlightStyle(n,this.highlightStyle||{}));var a=n.image,o=this;if(this._imageCache||(this._imageCache={}),"string"==typeof a){var r=a;this._imageCache[r]?a=this._imageCache[r]:(a=new Image,a.onload=function(){a.onload=null,o.modSelf(),i()},a.src=r,this._imageCache[r]=a)}if(a){if("IMG"==a.nodeName.toUpperCase())if(window.ActiveXObject){if("complete"!=a.readyState)return}else if(!a.complete)return;var s=n.width||a.width,l=n.height||a.height,h=n.x,m=n.y;if(!a.width||!a.height)return;if(e.save(),this.doClip(e),this.setContext(e,n),this.setTransform(e),n.sWidth&&n.sHeight){var V=n.sx||0,U=n.sy||0;e.drawImage(a,V,U,n.sWidth,n.sHeight,h,m,s,l)}else if(n.sx&&n.sy){var V=n.sx,U=n.sy,d=s-V,p=l-U;e.drawImage(a,V,U,d,p,h,m,s,l)}else e.drawImage(a,h,m,s,l);n.width||(n.width=s),n.height||(n.height=l),this.style.width||(this.style.width=s),this.style.height||(this.style.height=l),this.drawText(e,n,this.style),e.restore()}},getRect:function(e){return{x:e.x,y:e.y,width:e.width,height:e.height}},clearCache:function(){this._imageCache={}}},e("../tool/util").inherits(i,t),i}),i("zrender/loadingEffect/Bar",["require","./Base","../tool/util","../tool/color","../shape/Rectangle"],function(e){function t(e){i.call(this,e)}var i=e("./Base"),n=e("../tool/util"),a=e("../tool/color"),o=e("../shape/Rectangle");return n.inherits(t,i),t.prototype._start=function(e,t){var i=n.merge(this.options,{textStyle:{color:"#888"},backgroundColor:"rgba(250, 250, 250, 0.8)",effectOption:{x:0,y:this.canvasHeight/2-30,width:this.canvasWidth,height:5,brushType:"fill",timeInterval:100}}),r=this.createTextShape(i.textStyle),s=this.createBackgroundShape(i.backgroundColor),l=i.effectOption,h=new o({highlightStyle:n.clone(l)});return h.highlightStyle.color=l.color||a.getLinearGradient(l.x,l.y,l.x+l.width,l.y+l.height,[[0,"#ff6400"],[.5,"#ffe100"],[1,"#b1ff00"]]),null!=i.progress?(e(s),h.highlightStyle.width=this.adjust(i.progress,[0,1])*i.effectOption.width,e(h),e(r),void t()):(h.highlightStyle.width=0,setInterval(function(){e(s),h.highlightStyle.widthc;c++){var u="random"==l.color?a.alpha(a.random(),.3):l.color;U[c]=new o({highlightStyle:{x:Math.ceil(Math.random()*d),y:Math.ceil(Math.random()*p),r:Math.ceil(40*Math.random()),brushType:m,color:u,strokeColor:u,lineWidth:V},animationY:Math.ceil(20*Math.random())})}return setInterval(function(){e(s);for(var i=0;h>i;i++){var n=U[i].highlightStyle;n.y-U[i].animationY+n.r<=0&&(U[i].highlightStyle.y=p+n.r,U[i].highlightStyle.x=Math.ceil(Math.random()*d)),U[i].highlightStyle.y-=U[i].animationY,e(U[i])}e(r),t()},l.timeInterval)},t}),i("zrender/loadingEffect/DynamicLine",["require","./Base","../tool/util","../tool/color","../shape/Line"],function(e){function t(e){i.call(this,e)}var i=e("./Base"),n=e("../tool/util"),a=e("../tool/color"),o=e("../shape/Line");return n.inherits(t,i),t.prototype._start=function(e,t){for(var i=n.merge(this.options,{textStyle:{color:"#fff"},backgroundColor:"rgba(0, 0, 0, 0.8)",effectOption:{n:30,lineWidth:1,color:"random",timeInterval:100}}),r=this.createTextShape(i.textStyle),s=this.createBackgroundShape(i.backgroundColor),l=i.effectOption,h=l.n,m=l.lineWidth,V=[],U=this.canvasWidth,d=this.canvasHeight,p=0;h>p;p++){var c=-Math.ceil(1e3*Math.random()),u=Math.ceil(400*Math.random()),y=Math.ceil(Math.random()*d),g="random"==l.color?a.random():l.color;V[p]=new o({highlightStyle:{xStart:c,yStart:y,xEnd:c+u,yEnd:y,strokeColor:g,lineWidth:m},animationX:Math.ceil(100*Math.random()),len:u})}return setInterval(function(){e(s);for(var i=0;h>i;i++){var n=V[i].highlightStyle;n.xStart>=U&&(V[i].len=Math.ceil(400*Math.random()),n.xStart=-400,n.xEnd=-400+V[i].len,n.yStart=Math.ceil(Math.random()*d),n.yEnd=n.yStart),n.xStart+=V[i].animationX,n.xEnd+=V[i].animationX,e(V[i])}e(r),t()},l.timeInterval)},t}),i("zrender/loadingEffect/Ring",["require","./Base","../tool/util","../tool/color","../shape/Ring","../shape/Sector"],function(e){function t(e){i.call(this,e)}var i=e("./Base"),n=e("../tool/util"),a=e("../tool/color"),o=e("../shape/Ring"),r=e("../shape/Sector");return n.inherits(t,i),t.prototype._start=function(e,t){var i=n.merge(this.options,{textStyle:{color:"#07a"},backgroundColor:"rgba(250, 250, 250, 0.8)",effect:{x:this.canvasWidth/2,y:this.canvasHeight/2,r0:60,r:100,color:"#bbdcff",brushType:"fill",textPosition:"inside",textFont:"normal 30px verdana",textColor:"rgba(30, 144, 255, 0.6)",timeInterval:100}}),s=i.effect,l=i.textStyle; + +null==l.x&&(l.x=s.x),null==l.y&&(l.y=s.y+(s.r0+s.r)/2-5);for(var h=this.createTextShape(i.textStyle),m=this.createBackgroundShape(i.backgroundColor),V=s.x,U=s.y,d=s.r0+6,p=s.r-6,c=s.color,u=a.lift(c,.1),y=new o({highlightStyle:n.clone(s)}),g=[],b=a.getGradientColors(["#ff6400","#ffe100","#97ff00"],25),f=15,k=240,x=0;16>x;x++)g.push(new r({highlightStyle:{x:V,y:U,r0:d,r:p,startAngle:k-f,endAngle:k,brushType:"fill",color:u},_color:a.getLinearGradient(V+d*Math.cos(k,!0),U-d*Math.sin(k,!0),V+d*Math.cos(k-f,!0),U-d*Math.sin(k-f,!0),[[0,b[2*x]],[1,b[2*x+1]]])})),k-=f;k=360;for(var x=0;4>x;x++)g.push(new r({highlightStyle:{x:V,y:U,r0:d,r:p,startAngle:k-f,endAngle:k,brushType:"fill",color:u},_color:a.getLinearGradient(V+d*Math.cos(k,!0),U-d*Math.sin(k,!0),V+d*Math.cos(k-f,!0),U-d*Math.sin(k-f,!0),[[0,b[2*x+32]],[1,b[2*x+33]]])})),k-=f;var _=0;if(null!=i.progress){e(m),_=100*this.adjust(i.progress,[0,1]).toFixed(2)/5,y.highlightStyle.text=5*_+"%",e(y);for(var x=0;20>x;x++)g[x].highlightStyle.color=_>x?g[x]._color:u,e(g[x]);return e(h),void t()}return setInterval(function(){e(m),_+=_>=20?-20:1,e(y);for(var i=0;20>i;i++)g[i].highlightStyle.color=_>i?g[i]._color:u,e(g[i]);e(h),t()},s.timeInterval)},t}),i("zrender/loadingEffect/Spin",["require","./Base","../tool/util","../tool/color","../tool/area","../shape/Sector"],function(e){function t(e){i.call(this,e)}var i=e("./Base"),n=e("../tool/util"),a=e("../tool/color"),o=e("../tool/area"),r=e("../shape/Sector");return n.inherits(t,i),t.prototype._start=function(e,t){var i=n.merge(this.options,{textStyle:{color:"#fff",textAlign:"start"},backgroundColor:"rgba(0, 0, 0, 0.8)"}),s=this.createTextShape(i.textStyle),l=10,h=o.getTextWidth(s.highlightStyle.text,s.highlightStyle.textFont),m=o.getTextHeight(s.highlightStyle.text,s.highlightStyle.textFont),V=n.merge(this.options.effect||{},{r0:9,r:15,n:18,color:"#fff",timeInterval:100}),U=this.getLocation(this.options.textStyle,h+l+2*V.r,Math.max(2*V.r,m));V.x=U.x+V.r,V.y=s.highlightStyle.y=U.y+U.height/2,s.highlightStyle.x=V.x+V.r+l;for(var d=this.createBackgroundShape(i.backgroundColor),p=V.n,c=V.x,u=V.y,y=V.r0,g=V.r,b=V.color,f=[],k=Math.round(180/p),x=0;p>x;x++)f[x]=new r({highlightStyle:{x:c,y:u,r0:y,r:g,startAngle:k*x*2,endAngle:k*x*2+k,color:a.alpha(b,(x+1)/p),brushType:"fill"}});var _=[0,c,u];return setInterval(function(){e(d),_[0]-=.3;for(var i=0;p>i;i++)f[i].rotation=_,e(f[i]);e(s),t()},V.timeInterval)},t}),i("zrender/loadingEffect/Whirling",["require","./Base","../tool/util","../tool/area","../shape/Ring","../shape/Droplet","../shape/Circle"],function(e){function t(e){i.call(this,e)}var i=e("./Base"),n=e("../tool/util"),a=e("../tool/area"),o=e("../shape/Ring"),r=e("../shape/Droplet"),s=e("../shape/Circle");return n.inherits(t,i),t.prototype._start=function(e,t){var i=n.merge(this.options,{textStyle:{color:"#888",textAlign:"start"},backgroundColor:"rgba(250, 250, 250, 0.8)"}),l=this.createTextShape(i.textStyle),h=10,m=a.getTextWidth(l.highlightStyle.text,l.highlightStyle.textFont),V=a.getTextHeight(l.highlightStyle.text,l.highlightStyle.textFont),U=n.merge(this.options.effect||{},{r:18,colorIn:"#fff",colorOut:"#555",colorWhirl:"#6cf",timeInterval:50}),d=this.getLocation(this.options.textStyle,m+h+2*U.r,Math.max(2*U.r,V));U.x=d.x+U.r,U.y=l.highlightStyle.y=d.y+d.height/2,l.highlightStyle.x=U.x+U.r+h;var p=this.createBackgroundShape(i.backgroundColor),c=new r({highlightStyle:{a:Math.round(U.r/2),b:Math.round(U.r-U.r/6),brushType:"fill",color:U.colorWhirl}}),u=new s({highlightStyle:{r:Math.round(U.r/6),brushType:"fill",color:U.colorIn}}),y=new o({highlightStyle:{r0:Math.round(U.r-U.r/3),r:U.r,brushType:"fill",color:U.colorOut}}),g=[0,U.x,U.y];return c.highlightStyle.x=u.highlightStyle.x=y.highlightStyle.x=g[1],c.highlightStyle.y=u.highlightStyle.y=y.highlightStyle.y=g[2],setInterval(function(){e(p),e(y),g[0]-=.3,c.rotation=g,e(c),e(u),e(l),t()},U.timeInterval)},t}),i("echarts/theme/macarons",[],function(){var e={color:["#2ec7c9","#b6a2de","#5ab1ef","#ffb980","#d87a80","#8d98b3","#e5cf0d","#97b552","#95706d","#dc69aa","#07a2a4","#9a7fd1","#588dd5","#f5994e","#c05050","#59678c","#c9ab00","#7eb00a","#6f5553","#c14089"],title:{textStyle:{fontWeight:"normal",color:"#008acd"}},dataRange:{itemWidth:15,color:["#5ab1ef","#e0ffff"]},toolbox:{color:["#1e90ff","#1e90ff","#1e90ff","#1e90ff"],effectiveColor:"#ff4500"},tooltip:{backgroundColor:"rgba(50,50,50,0.5)",axisPointer:{type:"line",lineStyle:{color:"#008acd"},crossStyle:{color:"#008acd"},shadowStyle:{color:"rgba(200,200,200,0.2)"}}},dataZoom:{dataBackgroundColor:"#efefff",fillerColor:"rgba(182,162,222,0.2)",handleColor:"#008acd"},grid:{borderColor:"#eee"},categoryAxis:{axisLine:{lineStyle:{color:"#008acd"}},splitLine:{lineStyle:{color:["#eee"]}}},valueAxis:{axisLine:{lineStyle:{color:"#008acd"}},splitArea:{show:!0,areaStyle:{color:["rgba(250,250,250,0.1)","rgba(200,200,200,0.1)"]}},splitLine:{lineStyle:{color:["#eee"]}}},polar:{axisLine:{lineStyle:{color:"#ddd"}},splitArea:{show:!0,areaStyle:{color:["rgba(250,250,250,0.2)","rgba(200,200,200,0.2)"]}},splitLine:{lineStyle:{color:"#ddd"}}},timeline:{lineStyle:{color:"#008acd"},controlStyle:{normal:{color:"#008acd"},emphasis:{color:"#008acd"}},symbol:"emptyCircle",symbolSize:3},bar:{itemStyle:{normal:{barBorderRadius:5},emphasis:{barBorderRadius:5}}},line:{smooth:!0,symbol:"emptyCircle",symbolSize:3},k:{itemStyle:{normal:{color:"#d87a80",color0:"#2ec7c9",lineStyle:{color:"#d87a80",color0:"#2ec7c9"}}}},scatter:{symbol:"circle",symbolSize:4},radar:{symbol:"emptyCircle",symbolSize:3},map:{itemStyle:{normal:{areaStyle:{color:"#ddd"},label:{textStyle:{color:"#d87a80"}}},emphasis:{areaStyle:{color:"#fe994e"}}}},force:{itemStyle:{normal:{linkStyle:{color:"#1e90ff"}}}},chord:{itemStyle:{normal:{borderWidth:1,borderColor:"rgba(128, 128, 128, 0.5)",chordStyle:{lineStyle:{color:"rgba(128, 128, 128, 0.5)"}}},emphasis:{borderWidth:1,borderColor:"rgba(128, 128, 128, 0.5)",chordStyle:{lineStyle:{color:"rgba(128, 128, 128, 0.5)"}}}}},gauge:{axisLine:{lineStyle:{color:[[.2,"#2ec7c9"],[.8,"#5ab1ef"],[1,"#d87a80"]],width:10}},axisTick:{splitNumber:10,length:15,lineStyle:{color:"auto"}},splitLine:{length:22,lineStyle:{color:"auto"}},pointer:{width:5}},textStyle:{fontFamily:"微软雅黑, Arial, Verdana, sans-serif"}};return e}),i("echarts/theme/infographic",[],function(){var e={color:["#C1232B","#B5C334","#FCCE10","#E87C25","#27727B","#FE8463","#9BCA63","#FAD860","#F3A43B","#60C0DD","#D7504B","#C6E579","#F4E001","#F0805A","#26C0C0"],title:{textStyle:{fontWeight:"normal",color:"#27727B"}},dataRange:{x:"right",y:"center",itemWidth:5,itemHeight:25,color:["#C1232B","#FCCE10"]},toolbox:{color:["#C1232B","#B5C334","#FCCE10","#E87C25","#27727B","#FE8463","#9BCA63","#FAD860","#F3A43B","#60C0DD"],effectiveColor:"#ff4500"},tooltip:{backgroundColor:"rgba(50,50,50,0.5)",axisPointer:{type:"line",lineStyle:{color:"#27727B",type:"dashed"},crossStyle:{color:"#27727B"},shadowStyle:{color:"rgba(200,200,200,0.3)"}}},dataZoom:{dataBackgroundColor:"rgba(181,195,52,0.3)",fillerColor:"rgba(181,195,52,0.2)",handleColor:"#27727B"},grid:{borderWidth:0},categoryAxis:{axisLine:{lineStyle:{color:"#27727B"}},splitLine:{show:!1}},valueAxis:{axisLine:{show:!1},splitArea:{show:!1},splitLine:{lineStyle:{color:["#ccc"],type:"dashed"}}},polar:{axisLine:{lineStyle:{color:"#ddd"}},splitArea:{show:!0,areaStyle:{color:["rgba(250,250,250,0.2)","rgba(200,200,200,0.2)"]}},splitLine:{lineStyle:{color:"#ddd"}}},timeline:{lineStyle:{color:"#27727B"},controlStyle:{normal:{color:"#27727B"},emphasis:{color:"#27727B"}},symbol:"emptyCircle",symbolSize:3},line:{itemStyle:{normal:{borderWidth:2,borderColor:"#fff",lineStyle:{width:3}},emphasis:{borderWidth:0}},symbol:"circle",symbolSize:3.5},k:{itemStyle:{normal:{color:"#C1232B",color0:"#B5C334",lineStyle:{width:1,color:"#C1232B",color0:"#B5C334"}}}},scatter:{itemStyle:{normal:{borderWidth:1,borderColor:"rgba(200,200,200,0.5)"},emphasis:{borderWidth:0}},symbol:"star4",symbolSize:4},radar:{symbol:"emptyCircle",symbolSize:3},map:{itemStyle:{normal:{areaStyle:{color:"#ddd"},label:{textStyle:{color:"#C1232B"}}},emphasis:{areaStyle:{color:"#fe994e"},label:{textStyle:{color:"rgb(100,0,0)"}}}}},force:{itemStyle:{normal:{linkStyle:{color:"#27727B"}}}},chord:{itemStyle:{normal:{borderWidth:1,borderColor:"rgba(128, 128, 128, 0.5)",chordStyle:{lineStyle:{color:"rgba(128, 128, 128, 0.5)"}}},emphasis:{borderWidth:1,borderColor:"rgba(128, 128, 128, 0.5)",chordStyle:{lineStyle:{color:"rgba(128, 128, 128, 0.5)"}}}}},gauge:{center:["50%","80%"],radius:"100%",startAngle:180,endAngle:0,axisLine:{show:!0,lineStyle:{color:[[.2,"#B5C334"],[.8,"#27727B"],[1,"#C1232B"]],width:"40%"}},axisTick:{splitNumber:2,length:5,lineStyle:{color:"#fff"}},axisLabel:{textStyle:{color:"#fff",fontWeight:"bolder"}},splitLine:{length:"5%",lineStyle:{color:"#fff"}},pointer:{width:"40%",length:"80%",color:"#fff"},title:{offsetCenter:[0,-20],textStyle:{color:"auto",fontSize:20}},detail:{offsetCenter:[0,0],textStyle:{color:"auto",fontSize:40}}},textStyle:{fontFamily:"微软雅黑, Arial, Verdana, sans-serif"}};return e}),i("zrender/dep/excanvas",["require"],function(){return document.createElement("canvas").getContext?G_vmlCanvasManager=!1:!function(){function e(){return this.context_||(this.context_=new f(this))}function t(e,t){var i=O.call(arguments,2);return function(){return e.apply(t,i.concat(O.call(arguments)))}}function i(e){return String(e).replace(/&/g,"&").replace(/"/g,""")}function n(e,t,i){e.namespaces[t]||e.namespaces.add(t,i,"#default#VML")}function a(e){if(n(e,"g_vml_","urn:schemas-microsoft-com:vml"),n(e,"g_o_","urn:schemas-microsoft-com:office:office"),!e.styleSheets.ex_canvas_){var t=e.createStyleSheet();t.owningElement.id="ex_canvas_",t.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}"}}function o(e){var t=e.srcElement;switch(e.propertyName){case"width":t.getContext().clearRect(),t.style.width=t.attributes.width.nodeValue+"px",t.firstChild.style.width=t.clientWidth+"px";break;case"height":t.getContext().clearRect(),t.style.height=t.attributes.height.nodeValue+"px",t.firstChild.style.height=t.clientHeight+"px"}}function r(e){var t=e.srcElement;t.firstChild&&(t.firstChild.style.width=t.clientWidth+"px",t.firstChild.style.height=t.clientHeight+"px")}function s(){return[[1,0,0],[0,1,0],[0,0,1]]}function l(e,t){for(var i=s(),n=0;3>n;n++)for(var a=0;3>a;a++){for(var o=0,r=0;3>r;r++)o+=e[n][r]*t[r][a];i[n][a]=o}return i}function h(e,t){t.fillStyle=e.fillStyle,t.lineCap=e.lineCap,t.lineJoin=e.lineJoin,t.lineWidth=e.lineWidth,t.miterLimit=e.miterLimit,t.shadowBlur=e.shadowBlur,t.shadowColor=e.shadowColor,t.shadowOffsetX=e.shadowOffsetX,t.shadowOffsetY=e.shadowOffsetY,t.strokeStyle=e.strokeStyle,t.globalAlpha=e.globalAlpha,t.font=e.font,t.textAlign=e.textAlign,t.textBaseline=e.textBaseline,t.scaleX_=e.scaleX_,t.scaleY_=e.scaleY_,t.lineScale_=e.lineScale_}function m(e){var t=e.indexOf("(",3),i=e.indexOf(")",t+1),n=e.substring(t+1,i).split(",");return(4!=n.length||"a"!=e.charAt(3))&&(n[3]=1),n}function V(e){return parseFloat(e)/100}function U(e,t,i){return Math.min(i,Math.max(t,e))}function d(e){var t,i,n,a,o,r;if(a=parseFloat(e[0])/360%360,0>a&&a++,o=U(V(e[1]),0,1),r=U(V(e[2]),0,1),0==o)t=i=n=r;else{var s=.5>r?r*(1+o):r+o-r*o,l=2*r-s;t=p(l,s,a+1/3),i=p(l,s,a),n=p(l,s,a-1/3)}return"#"+D[Math.floor(255*t)]+D[Math.floor(255*i)]+D[Math.floor(255*n)]}function p(e,t,i){return 0>i&&i++,i>1&&i--,1>6*i?e+6*(t-e)*i:1>2*i?t:2>3*i?e+(t-e)*(2/3-i)*6:e}function c(e){if(e in R)return R[e];var t,i=1;if(e=String(e),"#"==e.charAt(0))t=e;else if(/^rgb/.test(e)){for(var n,a=m(e),t="#",o=0;3>o;o++)n=-1!=a[o].indexOf("%")?Math.floor(255*V(a[o])):+a[o],t+=D[U(n,0,255)];i=+a[3]}else if(/^hsl/.test(e)){var a=m(e);t=d(a),i=a[3]}else t=H[e]||e;return R[e]={color:t,alpha:i}}function u(e){if(Y[e])return Y[e];var t,i=document.createElement("div"),n=i.style;try{n.font=e,t=n.fontFamily.split(",")[0]}catch(a){}return Y[e]={style:n.fontStyle||G.style,variant:n.fontVariant||G.variant,weight:n.fontWeight||G.weight,size:n.fontSize||G.size,family:t||G.family}}function y(e,t){var i={};for(var n in e)i[n]=e[n];var a=parseFloat(t.currentStyle.fontSize),o=parseFloat(e.size);return i.size="number"==typeof e.size?e.size:-1!=e.size.indexOf("px")?o:-1!=e.size.indexOf("em")?a*o:-1!=e.size.indexOf("%")?a/100*o:-1!=e.size.indexOf("pt")?o/.75:a,i}function g(e){return e.style+" "+e.variant+" "+e.weight+" "+e.size+"px '"+e.family+"'"}function b(e){return Q[e]||"square"}function f(e){this.m_=s(),this.mStack_=[],this.aStack_=[],this.currentPath_=[],this.strokeStyle="#000",this.fillStyle="#000",this.lineWidth=1,this.lineJoin="miter",this.lineCap="butt",this.miterLimit=1*A,this.globalAlpha=1,this.font="12px 微软雅黑",this.textAlign="left",this.textBaseline="alphabetic",this.canvas=e;var t="width:"+e.clientWidth+"px;height:"+e.clientHeight+"px;overflow:hidden;position:absolute",i=e.ownerDocument.createElement("div");i.style.cssText=t,e.appendChild(i);var n=i.cloneNode(!1);n.style.backgroundColor="#fff",n.style.filter="alpha(opacity=0)",e.appendChild(n),this.element_=i,this.scaleX_=1,this.scaleY_=1,this.lineScale_=1}function k(e,t,i,n){e.currentPath_.push({type:"bezierCurveTo",cp1x:t.x,cp1y:t.y,cp2x:i.x,cp2y:i.y,x:n.x,y:n.y}),e.currentX_=n.x,e.currentY_=n.y}function x(e,t){var i=c(e.strokeStyle),n=i.color,a=i.alpha*e.globalAlpha,o=e.lineScale_*e.lineWidth;1>o&&(a*=o),t.push("')}function _(e,t,i,n){var a=e.fillStyle,o=e.scaleX_,r=e.scaleY_,s=n.x-i.x,l=n.y-i.y;if(a instanceof v){var h=0,m={x:0,y:0},V=0,U=1;if("gradient"==a.type_){var d=a.x0_/o,p=a.y0_/r,u=a.x1_/o,y=a.y1_/r,g=L(e,d,p),b=L(e,u,y),f=b.x-g.x,k=b.y-g.y;h=180*Math.atan2(f,k)/Math.PI,0>h&&(h+=360),1e-6>h&&(h=0)}else{var g=L(e,a.x0_,a.y0_);m={x:(g.x-i.x)/s,y:(g.y-i.y)/l},s/=o*A,l/=r*A;var x=C.max(s,l);V=2*a.r0_/x,U=2*a.r1_/x-V}var _=a.colors_;_.sort(function(e,t){return e.offset-t.offset});for(var W=_.length,X=_[0].color,K=_[W-1].color,I=_[0].alpha*e.globalAlpha,J=_[W-1].alpha*e.globalAlpha,S=[],E=0;W>E;E++){var F=_[E];S.push(F.offset*U+V+" "+F.color)}t.push('')}else if(a instanceof w){if(s&&l){var T=-i.x,z=-i.y;t.push("')}}else{var M=c(e.fillStyle),O=M.color,P=M.alpha*e.globalAlpha;t.push('')}}function L(e,t,i){var n=e.m_;return{x:A*(t*n[0][0]+i*n[1][0]+n[2][0])-M,y:A*(t*n[0][1]+i*n[1][1]+n[2][1])-M}}function W(e){return isFinite(e[0][0])&&isFinite(e[0][1])&&isFinite(e[1][0])&&isFinite(e[1][1])&&isFinite(e[2][0])&&isFinite(e[2][1])}function X(e,t,i){if(W(t)&&(e.m_=t,e.scaleX_=Math.sqrt(t[0][0]*t[0][0]+t[0][1]*t[0][1]),e.scaleY_=Math.sqrt(t[1][0]*t[1][0]+t[1][1]*t[1][1]),i)){var n=t[0][0]*t[1][1]-t[0][1]*t[1][0];e.lineScale_=z(T(n))}}function v(e){this.type_=e,this.x0_=0,this.y0_=0,this.r0_=0,this.x1_=0,this.y1_=0,this.r1_=0,this.colors_=[]}function w(e,t){switch(I(e),t){case"repeat":case null:case"":this.repetition_="repeat";break;case"repeat-x":case"repeat-y":case"no-repeat":this.repetition_=t;break;default:K("SYNTAX_ERR")}this.src_=e.src,this.width_=e.width,this.height_=e.height}function K(e){throw new J(e)}function I(e){e&&1==e.nodeType&&"IMG"==e.tagName||K("TYPE_MISMATCH_ERR"),"complete"!=e.readyState&&K("INVALID_STATE_ERR")}function J(e){this.code=this[e],this.message=e+": DOM Exception "+this.code}var C=Math,S=C.round,E=C.sin,F=C.cos,T=C.abs,z=C.sqrt,A=10,M=A/2,O=(+navigator.userAgent.match(/MSIE ([\d.]+)?/)[1],Array.prototype.slice);a(document);var P={init:function(e){var i=e||document;i.createElement("canvas"),i.attachEvent("onreadystatechange",t(this.init_,this,i))},init_:function(e){for(var t=e.getElementsByTagName("canvas"),i=0;iN;N++)for(var B=0;16>B;B++)D[16*N+B]=N.toString(16)+B.toString(16);var H={aliceblue:"#F0F8FF",antiquewhite:"#FAEBD7",aquamarine:"#7FFFD4",azure:"#F0FFFF",beige:"#F5F5DC",bisque:"#FFE4C4",black:"#000000",blanchedalmond:"#FFEBCD",blueviolet:"#8A2BE2",brown:"#A52A2A",burlywood:"#DEB887",cadetblue:"#5F9EA0",chartreuse:"#7FFF00",chocolate:"#D2691E",coral:"#FF7F50",cornflowerblue:"#6495ED",cornsilk:"#FFF8DC",crimson:"#DC143C",cyan:"#00FFFF",darkblue:"#00008B",darkcyan:"#008B8B",darkgoldenrod:"#B8860B",darkgray:"#A9A9A9",darkgreen:"#006400",darkgrey:"#A9A9A9",darkkhaki:"#BDB76B",darkmagenta:"#8B008B",darkolivegreen:"#556B2F",darkorange:"#FF8C00",darkorchid:"#9932CC",darkred:"#8B0000",darksalmon:"#E9967A",darkseagreen:"#8FBC8F",darkslateblue:"#483D8B",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",darkturquoise:"#00CED1",darkviolet:"#9400D3",deeppink:"#FF1493",deepskyblue:"#00BFFF",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1E90FF",firebrick:"#B22222",floralwhite:"#FFFAF0",forestgreen:"#228B22",gainsboro:"#DCDCDC",ghostwhite:"#F8F8FF",gold:"#FFD700",goldenrod:"#DAA520",grey:"#808080",greenyellow:"#ADFF2F",honeydew:"#F0FFF0",hotpink:"#FF69B4",indianred:"#CD5C5C",indigo:"#4B0082",ivory:"#FFFFF0",khaki:"#F0E68C",lavender:"#E6E6FA",lavenderblush:"#FFF0F5",lawngreen:"#7CFC00",lemonchiffon:"#FFFACD",lightblue:"#ADD8E6",lightcoral:"#F08080",lightcyan:"#E0FFFF",lightgoldenrodyellow:"#FAFAD2",lightgreen:"#90EE90",lightgrey:"#D3D3D3",lightpink:"#FFB6C1",lightsalmon:"#FFA07A",lightseagreen:"#20B2AA",lightskyblue:"#87CEFA",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#B0C4DE",lightyellow:"#FFFFE0",limegreen:"#32CD32",linen:"#FAF0E6",magenta:"#FF00FF",mediumaquamarine:"#66CDAA",mediumblue:"#0000CD",mediumorchid:"#BA55D3",mediumpurple:"#9370DB",mediumseagreen:"#3CB371",mediumslateblue:"#7B68EE",mediumspringgreen:"#00FA9A",mediumturquoise:"#48D1CC",mediumvioletred:"#C71585",midnightblue:"#191970",mintcream:"#F5FFFA",mistyrose:"#FFE4E1",moccasin:"#FFE4B5",navajowhite:"#FFDEAD",oldlace:"#FDF5E6",olivedrab:"#6B8E23",orange:"#FFA500",orangered:"#FF4500",orchid:"#DA70D6",palegoldenrod:"#EEE8AA",palegreen:"#98FB98",paleturquoise:"#AFEEEE",palevioletred:"#DB7093",papayawhip:"#FFEFD5",peachpuff:"#FFDAB9",peru:"#CD853F",pink:"#FFC0CB",plum:"#DDA0DD",powderblue:"#B0E0E6",rosybrown:"#BC8F8F",royalblue:"#4169E1",saddlebrown:"#8B4513",salmon:"#FA8072",sandybrown:"#F4A460",seagreen:"#2E8B57",seashell:"#FFF5EE",sienna:"#A0522D",skyblue:"#87CEEB",slateblue:"#6A5ACD",slategray:"#708090",slategrey:"#708090",snow:"#FFFAFA",springgreen:"#00FF7F",steelblue:"#4682B4",tan:"#D2B48C",thistle:"#D8BFD8",tomato:"#FF6347",turquoise:"#40E0D0",violet:"#EE82EE",wheat:"#F5DEB3",whitesmoke:"#F5F5F5",yellowgreen:"#9ACD32"},R={},G={style:"normal",variant:"normal",weight:"normal",size:12,family:"微软雅黑"},Y={},Q={butt:"flat",round:"round"},Z=f.prototype;Z.clearRect=function(){this.textMeasureEl_&&(this.textMeasureEl_.removeNode(!0),this.textMeasureEl_=null),this.element_.innerHTML=""},Z.beginPath=function(){this.currentPath_=[]},Z.moveTo=function(e,t){var i=L(this,e,t);this.currentPath_.push({type:"moveTo",x:i.x,y:i.y}),this.currentX_=i.x,this.currentY_=i.y},Z.lineTo=function(e,t){var i=L(this,e,t);this.currentPath_.push({type:"lineTo",x:i.x,y:i.y}),this.currentX_=i.x,this.currentY_=i.y},Z.bezierCurveTo=function(e,t,i,n,a,o){var r=L(this,a,o),s=L(this,e,t),l=L(this,i,n);k(this,s,l,r)},Z.quadraticCurveTo=function(e,t,i,n){var a=L(this,e,t),o=L(this,i,n),r={x:this.currentX_+2/3*(a.x-this.currentX_),y:this.currentY_+2/3*(a.y-this.currentY_)},s={x:r.x+(o.x-this.currentX_)/3,y:r.y+(o.y-this.currentY_)/3};k(this,r,s,o)},Z.arc=function(e,t,i,n,a,o){i*=A;var r=o?"at":"wa",s=e+F(n)*i-M,l=t+E(n)*i-M,h=e+F(a)*i-M,m=t+E(a)*i-M;s!=h||o||(s+=.125);var V=L(this,e,t),U=L(this,s,l),d=L(this,h,m);this.currentPath_.push({type:r,x:V.x,y:V.y,radius:i,xStart:U.x,yStart:U.y,xEnd:d.x,yEnd:d.y})},Z.rect=function(e,t,i,n){this.moveTo(e,t),this.lineTo(e+i,t),this.lineTo(e+i,t+n),this.lineTo(e,t+n),this.closePath()},Z.strokeRect=function(e,t,i,n){var a=this.currentPath_;this.beginPath(),this.moveTo(e,t),this.lineTo(e+i,t),this.lineTo(e+i,t+n),this.lineTo(e,t+n),this.closePath(),this.stroke(),this.currentPath_=a},Z.fillRect=function(e,t,i,n){var a=this.currentPath_;this.beginPath(),this.moveTo(e,t),this.lineTo(e+i,t),this.lineTo(e+i,t+n),this.lineTo(e,t+n),this.closePath(),this.fill(),this.currentPath_=a},Z.createLinearGradient=function(e,t,i,n){var a=new v("gradient");return a.x0_=e,a.y0_=t,a.x1_=i,a.y1_=n,a},Z.createRadialGradient=function(e,t,i,n,a,o){var r=new v("gradientradial");return r.x0_=e,r.y0_=t,r.r0_=i,r.x1_=n,r.y1_=a,r.r1_=o,r},Z.drawImage=function(e){var t,i,n,a,o,r,s,l,h=e.runtimeStyle.width,m=e.runtimeStyle.height;e.runtimeStyle.width="auto",e.runtimeStyle.height="auto";var V=e.width,U=e.height;if(e.runtimeStyle.width=h,e.runtimeStyle.height=m,3==arguments.length)t=arguments[1],i=arguments[2],o=r=0,s=n=V,l=a=U;else if(5==arguments.length)t=arguments[1],i=arguments[2],n=arguments[3],a=arguments[4],o=r=0,s=V,l=U;else{if(9!=arguments.length)throw Error("Invalid number of arguments");o=arguments[1],r=arguments[2],s=arguments[3],l=arguments[4],t=arguments[5],i=arguments[6],n=arguments[7],a=arguments[8]}var d=L(this,t,i),p=[],c=10,u=10,y=b=1;if(p.push(" '),(o||r)&&p.push('
'),p.push('
'),(o||r)&&p.push("
"),p.push("
"),this.element_.insertAdjacentHTML("BeforeEnd",p.join(""))},Z.stroke=function(e){var t=[],i=10,n=10;t.push("o.x)&&(o.x=l.x),(null==a.y||l.yo.y)&&(o.y=l.y))}t.push(' ">'),e?_(this,t,a,o):x(this,t),t.push(""),this.element_.insertAdjacentHTML("beforeEnd",t.join(""))},Z.fill=function(){this.stroke(!0)},Z.closePath=function(){this.currentPath_.push({type:"close"})},Z.save=function(){var e={};h(this,e),this.aStack_.push(e),this.mStack_.push(this.m_),this.m_=l(s(),this.m_)},Z.restore=function(){this.aStack_.length&&(h(this.aStack_.pop(),this),this.m_=this.mStack_.pop())},Z.translate=function(e,t){var i=[[1,0,0],[0,1,0],[e,t,1]];X(this,l(i,this.m_),!1)},Z.rotate=function(e){var t=F(e),i=E(e),n=[[t,i,0],[-i,t,0],[0,0,1]];X(this,l(n,this.m_),!1)},Z.scale=function(e,t){var i=[[e,0,0],[0,t,0],[0,0,1]];X(this,l(i,this.m_),!0)},Z.transform=function(e,t,i,n,a,o){var r=[[e,t,0],[i,n,0],[a,o,1]];X(this,l(r,this.m_),!0)},Z.setTransform=function(e,t,i,n,a,o){var r=[[e,t,0],[i,n,0],[a,o,1]];X(this,r,!0)},Z.drawText_=function(e,t,n,a,o){var r=this.m_,s=1e3,l=0,h=s,m={x:0,y:0},V=[],U=y(u(this.font),this.element_),d=g(U),p=this.element_.currentStyle,c=this.textAlign.toLowerCase();switch(c){case"left":case"center":case"right":break;case"end":c="ltr"==p.direction?"right":"left";break;case"start":c="rtl"==p.direction?"right":"left";break;default:c="left"}switch(this.textBaseline){case"hanging":case"top":m.y=U.size/1.75;break;case"middle":break;default:case null:case"alphabetic":case"ideographic":case"bottom":m.y=-U.size/2.25}switch(c){case"right":l=s,h=.05;break;case"center":l=h=s/2}var b=L(this,t+m.x,n+m.y);V.push(''),o?x(this,V):_(this,V,{x:-l,y:0},{x:h,y:U.size});var f=r[0][0].toFixed(3)+","+r[1][0].toFixed(3)+","+r[0][1].toFixed(3)+","+r[1][1].toFixed(3)+",0,0",k=S(b.x/A)+","+S(b.y/A);V.push('','',''),this.element_.insertAdjacentHTML("beforeEnd",V.join(""))},Z.fillText=function(e,t,i,n){this.drawText_(e,t,i,n,!1)},Z.strokeText=function(e,t,i,n){this.drawText_(e,t,i,n,!0)},Z.measureText=function(e){if(!this.textMeasureEl_){var t='';this.element_.insertAdjacentHTML("beforeEnd",t),this.textMeasureEl_=this.element_.lastChild}var i=this.element_.ownerDocument;this.textMeasureEl_.innerHTML="";try{this.textMeasureEl_.style.font=this.font}catch(n){}return this.textMeasureEl_.appendChild(i.createTextNode(e)),{width:this.textMeasureEl_.offsetWidth}},Z.clip=function(){},Z.arcTo=function(){},Z.createPattern=function(e,t){return new w(e,t)},v.prototype.addColorStop=function(e,t){t=c(t),this.colors_.push({offset:e,color:t.color,alpha:t.alpha})};var q=J.prototype=new Error;q.INDEX_SIZE_ERR=1,q.DOMSTRING_SIZE_ERR=2,q.HIERARCHY_REQUEST_ERR=3,q.WRONG_DOCUMENT_ERR=4,q.INVALID_CHARACTER_ERR=5,q.NO_DATA_ALLOWED_ERR=6,q.NO_MODIFICATION_ALLOWED_ERR=7,q.NOT_FOUND_ERR=8,q.NOT_SUPPORTED_ERR=9,q.INUSE_ATTRIBUTE_ERR=10,q.INVALID_STATE_ERR=11,q.SYNTAX_ERR=12,q.INVALID_MODIFICATION_ERR=13,q.NAMESPACE_ERR=14,q.INVALID_ACCESS_ERR=15,q.VALIDATION_ERR=16,q.TYPE_MISMATCH_ERR=17,G_vmlCanvasManager=P,CanvasRenderingContext2D=f,CanvasGradient=v,CanvasPattern=w,DOMException=J}(),G_vmlCanvasManager}),i("zrender/mixin/Eventful",["require"],function(){var e=function(){this._handlers={}};return e.prototype.one=function(e,t,i){var n=this._handlers;return t&&e?(n[e]||(n[e]=[]),n[e].push({h:t,one:!0,ctx:i||this}),this):this},e.prototype.bind=function(e,t,i){var n=this._handlers;return t&&e?(n[e]||(n[e]=[]),n[e].push({h:t,one:!1,ctx:i||this}),this):this},e.prototype.unbind=function(e,t){var i=this._handlers;if(!e)return this._handlers={},this;if(t){if(i[e]){for(var n=[],a=0,o=i[e].length;o>a;a++)i[e][a].h!=t&&n.push(i[e][a]);i[e]=n}i[e]&&0===i[e].length&&delete i[e]}else delete i[e];return this},e.prototype.dispatch=function(e){if(this._handlers[e]){var t=arguments,i=t.length;i>3&&(t=Array.prototype.slice.call(t,1));for(var n=this._handlers[e],a=n.length,o=0;a>o;){switch(i){case 1:n[o].h.call(n[o].ctx);break;case 2:n[o].h.call(n[o].ctx,t[1]);break;case 3:n[o].h.call(n[o].ctx,t[1],t[2]);break;default:n[o].h.apply(n[o].ctx,t)}n[o].one?(n.splice(o,1),a--):o++}}return this},e.prototype.dispatchWithContext=function(e){if(this._handlers[e]){var t=arguments,i=t.length;i>4&&(t=Array.prototype.slice.call(t,1,t.length-1));for(var n=t[t.length-1],a=this._handlers[e],o=a.length,r=0;o>r;){switch(i){case 1:a[r].h.call(n);break;case 2:a[r].h.call(n,t[1]);break;case 3:a[r].h.call(n,t[1],t[2]);break;default:a[r].h.apply(n,t)}a[r].one?(a.splice(r,1),o--):r++}}return this},e}),i("zrender/tool/log",["require","../config"],function(e){var t=e("../config");return function(){if(0!==t.debugMode)if(1==t.debugMode)for(var e in arguments)throw new Error(arguments[e]);else if(t.debugMode>1)for(var e in arguments)console.log(arguments[e])}}),i("zrender/tool/guid",[],function(){var e=2311;return function(){return"zrender__"+e++}}),i("zrender/Handler",["require","./config","./tool/env","./tool/event","./tool/util","./tool/vector","./tool/matrix","./mixin/Eventful"],function(e){"use strict";function t(e,t){return function(i,n){return e.call(t,i,n)}}function i(e,t){return function(i,n,a){return e.call(t,i,n,a)}}function n(e){for(var i=d.length;i--;){var n=d[i];e["_"+n+"Handler"]=t(c[n],e)}}function a(e,t,i){if(this._draggingTarget&&this._draggingTarget.id==e.id||e.isSilent())return!1;var n=this._event;if(e.isCover(t,i)){e.hoverable&&this.storage.addHover(e);for(var a=e.parent;a;){if(a.clipShape&&!a.clipShape.isCover(this._mouseX,this._mouseY))return!1;a=a.parent}return this._lastHover!=e&&(this._processOutShape(n),this._processDragLeave(n),this._lastHover=e,this._processDragEnter(n)),this._processOverShape(n),this._processDragOver(n),this._hasfound=1,!0}return!1}var o=e("./config"),r=e("./tool/env"),s=e("./tool/event"),l=e("./tool/util"),h=e("./tool/vector"),m=e("./tool/matrix"),V=o.EVENT,U=e("./mixin/Eventful"),d=["resize","click","dblclick","mousewheel","mousemove","mouseout","mouseup","mousedown","touchstart","touchend","touchmove"],p=function(e){if(window.G_vmlCanvasManager)return!0;e=e||window.event;var t=e.toElement||e.relatedTarget||e.srcElement||e.target;return t&&t.className.match(o.elementClassName)},c={resize:function(e){e=e||window.event,this._lastHover=null,this._isMouseDown=0,this.dispatch(V.RESIZE,e)},click:function(e,t){if(p(e)||t){e=this._zrenderEventFixed(e);var i=this._lastHover;(i&&i.clickable||!i)&&this._clickThreshold<5&&this._dispatchAgency(i,V.CLICK,e),this._mousemoveHandler(e)}},dblclick:function(e,t){if(p(e)||t){e=e||window.event,e=this._zrenderEventFixed(e);var i=this._lastHover;(i&&i.clickable||!i)&&this._clickThreshold<5&&this._dispatchAgency(i,V.DBLCLICK,e),this._mousemoveHandler(e)}},mousewheel:function(e,t){if(p(e)||t){e=this._zrenderEventFixed(e);var i=e.wheelDelta||-e.detail,n=i>0?1.1:1/1.1,a=!1,o=this._mouseX,r=this._mouseY;this.painter.eachBuildinLayer(function(t){var i=t.position;if(t.zoomable){t.__zoom=t.__zoom||1;var l=t.__zoom;l*=n,l=Math.max(Math.min(t.maxZoom,l),t.minZoom),n=l/t.__zoom,t.__zoom=l,i[0]-=(o-i[0])*(n-1),i[1]-=(r-i[1])*(n-1),t.scale[0]*=n,t.scale[1]*=n,t.dirty=!0,a=!0,s.stop(e)}}),a&&this.painter.refresh(),this._dispatchAgency(this._lastHover,V.MOUSEWHEEL,e),this._mousemoveHandler(e)}},mousemove:function(e,t){if((p(e)||t)&&!this.painter.isLoading()){e=this._zrenderEventFixed(e),this._lastX=this._mouseX,this._lastY=this._mouseY,this._mouseX=s.getX(e),this._mouseY=s.getY(e);var i=this._mouseX-this._lastX,n=this._mouseY-this._lastY;this._processDragStart(e),this._hasfound=0,this._event=e,this._iterateAndFindHover(),this._hasfound||((!this._draggingTarget||this._lastHover&&this._lastHover!=this._draggingTarget)&&(this._processOutShape(e), +this._processDragLeave(e)),this._lastHover=null,this.storage.delHover(),this.painter.clearHover());var a="default";if(this._draggingTarget)this.storage.drift(this._draggingTarget.id,i,n),this._draggingTarget.modSelf(),this.storage.addHover(this._draggingTarget),this._clickThreshold++;else if(this._isMouseDown){var o=!1;this.painter.eachBuildinLayer(function(e){e.panable&&(a="move",e.position[0]+=i,e.position[1]+=n,o=!0,e.dirty=!0)}),o&&this.painter.refresh()}this._draggingTarget||this._hasfound&&this._lastHover.draggable?a="move":this._hasfound&&this._lastHover.clickable&&(a="pointer"),this.root.style.cursor=a,this._dispatchAgency(this._lastHover,V.MOUSEMOVE,e),(this._draggingTarget||this._hasfound||this.storage.hasHoverShape())&&this.painter.refreshHover()}},mouseout:function(e,t){if(p(e)||t){e=this._zrenderEventFixed(e);var i=e.toElement||e.relatedTarget;if(i!=this.root)for(;i&&9!=i.nodeType;){if(i==this.root)return void this._mousemoveHandler(e);i=i.parentNode}e.zrenderX=this._lastX,e.zrenderY=this._lastY,this.root.style.cursor="default",this._isMouseDown=0,this._processOutShape(e),this._processDrop(e),this._processDragEnd(e),this.painter.isLoading()||this.painter.refreshHover(),this.dispatch(V.GLOBALOUT,e)}},mousedown:function(e,t){if(p(e)||t){if(this._clickThreshold=0,2==this._lastDownButton)return this._lastDownButton=e.button,void(this._mouseDownTarget=null);this._lastMouseDownMoment=new Date,e=this._zrenderEventFixed(e),this._isMouseDown=1,this._mouseDownTarget=this._lastHover,this._dispatchAgency(this._lastHover,V.MOUSEDOWN,e),this._lastDownButton=e.button}},mouseup:function(e,t){(p(e)||t)&&(e=this._zrenderEventFixed(e),this.root.style.cursor="default",this._isMouseDown=0,this._mouseDownTarget=null,this._dispatchAgency(this._lastHover,V.MOUSEUP,e),this._processDrop(e),this._processDragEnd(e))},touchstart:function(e,t){(p(e)||t)&&(e=this._zrenderEventFixed(e,!0),this._lastTouchMoment=new Date,this._mobileFindFixed(e),this._mousedownHandler(e))},touchmove:function(e,t){(p(e)||t)&&(e=this._zrenderEventFixed(e,!0),this._mousemoveHandler(e),this._isDragging&&s.stop(e))},touchend:function(e,t){if(p(e)||t){e=this._zrenderEventFixed(e,!0),this._mouseupHandler(e);var i=new Date;i-this._lastTouchMoment=0;o--){var r=n[o];if(t!==r.zlevel&&(i=this.painter.getLayer(r.zlevel,i),a[0]=this._mouseX,a[1]=this._mouseY,i.needTransform&&(m.invert(e,i.transform),h.applyTransform(a,a,e))),this._findHover(r,a[0],a[1]))break}}}();var y=[{x:10},{x:-20},{x:10,y:10},{y:-20}];return u.prototype._mobileFindFixed=function(e){this._lastHover=null,this._mouseX=e.zrenderX,this._mouseY=e.zrenderY,this._event=e,this._iterateAndFindHover();for(var t=0;!this._lastHover&&ts;s++){var h=e[s];if(n!==h.zlevel&&(i&&(i.needTransform&&o.restore(),o.flush&&o.flush()),n=h.zlevel,i=this.getLayer(n),i.isBuildin||r("ZLevel "+n+" has been used by unkown layer "+i.id),o=i.ctx,i.unusedCount=0,(i.dirty||t)&&i.clear(),i.needTransform&&(o.save(),i.setTransform(o))),(i.dirty||t)&&!h.invisible&&(!h.onbrush||h.onbrush&&!h.onbrush(o,!1)))if(a.catchBrushException)try{h.brush(o,!1,this.refreshNextFrame)}catch(m){r(m,"brush error of "+h.type,h)}else h.brush(o,!1,this.refreshNextFrame);h.__dirty=!1}i&&(i.needTransform&&o.restore(),o.flush&&o.flush()),this.eachBuildinLayer(this._postProcessLayer)},h.prototype.getLayer=function(e){var t=this._layers[e];return t||(t=new l(e,this),t.isBuildin=!0,this._layerConfig[e]&&o.merge(t,this._layerConfig[e],!0),t.updateTransform(),this.insertLayer(e,t),t.initContext()),t},h.prototype.insertLayer=function(e,t){if(this._layers[e])return void r("ZLevel "+e+" has been used already");if(!n(t))return void r("Layer of zlevel "+e+" is not valid");var i=this._zlevelList.length,a=null,o=-1;if(i>0&&e>this._zlevelList[0]){for(o=0;i-1>o&&!(this._zlevelList[o]e);o++);a=this._layers[this._zlevelList[o]]}this._zlevelList.splice(o+1,0,e);var s=a?a.dom:this._bgDom;s.nextSibling?s.parentNode.insertBefore(t.dom,s.nextSibling):s.parentNode.appendChild(t.dom),this._layers[e]=t},h.prototype.eachLayer=function(e,t){for(var i=0;in;n++){var o=e[n],r=o.zlevel,s=t[r];if(s){if(s.elCount++,s.dirty)continue;s.dirty=o.__dirty}}this.eachBuildinLayer(function(e,t){i[t]!==e.elCount&&(e.dirty=!0)})},h.prototype.refreshShapes=function(e,t){for(var i=0,n=e.length;n>i;i++){var a=e[i];a.modSelf()}return this.refresh(t),this},h.prototype.setLoadingEffect=function(e){return this._loadingEffect=e,this},h.prototype.clear=function(){return this.eachBuildinLayer(this._clearLayer),this},h.prototype._clearLayer=function(e){e.clear()},h.prototype.modLayer=function(e,t){if(t){this._layerConfig[e]?o.merge(this._layerConfig[e],t,!0):this._layerConfig[e]=t;var i=this._layers[e];i&&o.merge(i,this._layerConfig[e],!0)}},h.prototype.delLayer=function(e){var t=this._layers[e];t&&(this.modLayer(e,{position:t.position,rotation:t.rotation,scale:t.scale}),t.dom.parentNode.removeChild(t.dom),delete this._layers[e],this._zlevelList.splice(o.indexOf(this._zlevelList,e),1))},h.prototype.refreshHover=function(){this.clearHover();for(var e=this.storage.getHoverShapes(!0),t=0,i=e.length;i>t;t++)this._brushHover(e[t]);var n=this._layers.hover.ctx;return n.flush&&n.flush(),this.storage.delHover(),this},h.prototype.clearHover=function(){var e=this._layers.hover;return e&&e.clear(),this},h.prototype.showLoading=function(e){return this._loadingEffect&&this._loadingEffect.stop(),e&&this.setLoadingEffect(e),this._loadingEffect.start(this),this.loading=!0,this},h.prototype.hideLoading=function(){return this._loadingEffect.stop(),this.clearHover(),this.loading=!1,this},h.prototype.isLoading=function(){return this.loading},h.prototype.resize=function(){var e=this._domRoot;e.style.display="none";var t=this._getWidth(),i=this._getHeight();if(e.style.display="",this._width!=t||i!=this._height){this._width=t,this._height=i,e.style.width=t+"px",e.style.height=i+"px";for(var n in this._layers)this._layers[n].resize(t,i);this.refresh(null,!0)}return this},h.prototype.clearLayer=function(e){var t=this._layers[e];t&&t.clear()},h.prototype.dispose=function(){this.isLoading()&&this.hideLoading(),this.root.innerHTML="",this.root=this.storage=this._domRoot=this._layers=null},h.prototype.getDomHover=function(){return this._layers.hover.dom},h.prototype.toDataURL=function(e,t,i){if(window.G_vmlCanvasManager)return null;var n=new l("image",this);this._bgDom.appendChild(n.dom),n.initContext();var o=n.ctx;n.clearColor=t||"#fff",n.clear();var s=this;this.storage.iterShape(function(e){if(!e.invisible&&(!e.onbrush||e.onbrush&&!e.onbrush(o,!1)))if(a.catchBrushException)try{e.brush(o,!1,s.refreshNextFrame)}catch(t){r(t,"brush error of "+e.type,e)}else e.brush(o,!1,s.refreshNextFrame)},{normal:"up",update:!0});var h=n.dom.toDataURL(e,i);return o=null,this._bgDom.removeChild(n.dom),h},h.prototype.getWidth=function(){return this._width},h.prototype.getHeight=function(){return this._height},h.prototype._getWidth=function(){var e=this.root,t=e.currentStyle||document.defaultView.getComputedStyle(e);return((e.clientWidth||parseInt(t.width,10))-parseInt(t.paddingLeft,10)-parseInt(t.paddingRight,10)).toFixed(0)-0},h.prototype._getHeight=function(){var e=this.root,t=e.currentStyle||document.defaultView.getComputedStyle(e);return((e.clientHeight||parseInt(t.height,10))-parseInt(t.paddingTop,10)-parseInt(t.paddingBottom,10)).toFixed(0)-0},h.prototype._brushHover=function(e){var t=this._layers.hover.ctx;if(!e.onbrush||e.onbrush&&!e.onbrush(t,!0)){var i=this.getLayer(e.zlevel);if(i.needTransform&&(t.save(),i.setTransform(t)),a.catchBrushException)try{e.brush(t,!0,this.refreshNextFrame)}catch(n){r(n,"hoverBrush error of "+e.type,e)}else e.brush(t,!0,this.refreshNextFrame);i.needTransform&&t.restore()}},h.prototype._shapeToImage=function(t,i,n,a,o){var r=document.createElement("canvas"),s=r.getContext("2d");r.style.width=n+"px",r.style.height=a+"px",r.setAttribute("width",n*o),r.setAttribute("height",a*o),s.clearRect(0,0,n*o,a*o);var l={position:i.position,rotation:i.rotation,scale:i.scale};i.position=[0,0,0],i.rotation=0,i.scale=[1,1],i&&i.brush(s,!1);var h=e("./shape/Image"),m=new h({id:t,style:{x:0,y:0,image:r}});return null!=l.position&&(m.position=i.position=l.position),null!=l.rotation&&(m.rotation=i.rotation=l.rotation),null!=l.scale&&(m.scale=i.scale=l.scale),m},h.prototype._createShapeToImageProcessor=function(){if(window.G_vmlCanvasManager)return i;var e=this;return function(t,i,n,o){return e._shapeToImage(t,i,n,o,a.devicePixelRatio)}},h}),i("zrender/Storage",["require","./tool/util","./Group"],function(e){"use strict";function t(e,t){return e.zlevel==t.zlevel?e.z==t.z?e.__renderidx-t.__renderidx:e.z-t.z:e.zlevel-t.zlevel}var i=e("./tool/util"),n=e("./Group"),a={hover:!1,normal:"down",update:!1},o=function(){this._elements={},this._hoverElements=[],this._roots=[],this._shapeList=[],this._shapeListOffset=0};return o.prototype.iterShape=function(e,t){if(t||(t=a),t.hover)for(var i=0,n=this._hoverElements.length;n>i;i++){var o=this._hoverElements[i];if(o.updateTransform(),e(o))return this}switch(t.update&&this.updateShapeList(),t.normal){case"down":for(var n=this._shapeList.length;n--;)if(e(this._shapeList[n]))return this;break;default:for(var i=0,n=this._shapeList.length;n>i;i++)if(e(this._shapeList[i]))return this}return this},o.prototype.getHoverShapes=function(e){for(var i=[],n=0,a=this._hoverElements.length;a>n;n++){i.push(this._hoverElements[n]);var o=this._hoverElements[n].hoverConnect;if(o){var r;o=o instanceof Array?o:[o];for(var s=0,l=o.length;l>s;s++)r=o[s].id?o[s]:this.get(o[s]),r&&i.push(r)}}if(i.sort(t),e)for(var n=0,a=i.length;a>n;n++)i[n].updateTransform();return i},o.prototype.getShapeList=function(e){return e&&this.updateShapeList(),this._shapeList},o.prototype.updateShapeList=function(){this._shapeListOffset=0;for(var e=0,i=this._roots.length;i>e;e++){var n=this._roots[e];this._updateAndAddShape(n)}this._shapeList.length=this._shapeListOffset;for(var e=0,i=this._shapeList.length;i>e;e++)this._shapeList[e].__renderidx=e;this._shapeList.sort(t)},o.prototype._updateAndAddShape=function(e,t){if(!e.ignore)if(e.updateTransform(),e.clipShape&&(e.clipShape.parent=e,e.clipShape.updateTransform(),t?(t=t.slice(),t.push(e.clipShape)):t=[e.clipShape]),"group"==e.type){for(var i=0;i0},o.prototype.addRoot=function(e){this._elements[e.id]||(e instanceof n&&e.addChildrenToStorage(this),this.addToMap(e),this._roots.push(e))},o.prototype.delRoot=function(e){if("undefined"==typeof e){for(var t=0;tt;t++)this.delRoot(e[t]);else{var r;r="string"==typeof e?this._elements[e]:e;var s=i.indexOf(this._roots,r);s>=0&&(this.delFromMap(r.id),this._roots.splice(s,1),r instanceof n&&r.delChildrenFromStorage(this))}},o.prototype.addToMap=function(e){return e instanceof n&&(e._storage=this),e.modSelf(),this._elements[e.id]=e,this},o.prototype.get=function(e){return this._elements[e]},o.prototype.delFromMap=function(e){var t=this._elements[e];return t&&(delete this._elements[e],t instanceof n&&(t._storage=null)),this},o.prototype.dispose=function(){this._elements=this._renderList=this._roots=this._hoverElements=null},o}),i("zrender/animation/Animation",["require","./Clip","../tool/color","../tool/util","../tool/event"],function(e){"use strict";function t(e,t){return e[t]}function i(e,t,i){e[t]=i}function n(e,t,i){return(t-e)*i+e}function a(e,t,i,a,o){var r=e.length;if(1==o)for(var s=0;r>s;s++)a[s]=n(e[s],t[s],i);else for(var l=e[0].length,s=0;r>s;s++)for(var h=0;l>h;h++)a[s][h]=n(e[s][h],t[s][h],i)}function o(e){switch(typeof e){case"undefined":case"string":return!1}return"undefined"!=typeof e.length}function r(e,t,i,n,a,o,r,l,h){var m=e.length;if(1==h)for(var V=0;m>V;V++)l[V]=s(e[V],t[V],i[V],n[V],a,o,r);else for(var U=e[0].length,V=0;m>V;V++)for(var d=0;U>d;d++)l[V][d]=s(e[V][d],t[V][d],i[V][d],n[V][d],a,o,r)}function s(e,t,i,n,a,o,r){var s=.5*(i-e),l=.5*(n-t);return(2*(t-i)+s+l)*r+(-3*(t-i)-2*s-l)*o+s*a+t}function l(e){if(o(e)){var t=e.length;if(o(e[0])){for(var i=[],n=0;t>n;n++)i.push(c.call(e[n]));return i}return c.call(e)}return e}function h(e){return e[0]=Math.floor(e[0]),e[1]=Math.floor(e[1]),e[2]=Math.floor(e[2]),"rgba("+e.join(",")+")"}var m=e("./Clip"),V=e("../tool/color"),U=e("../tool/util"),d=e("../tool/event").Dispatcher,p=window.requestAnimationFrame||window.msRequestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||function(e){setTimeout(e,16)},c=Array.prototype.slice,u=function(e){e=e||{},this.stage=e.stage||{},this.onframe=e.onframe||function(){},this._clips=[],this._running=!1,this._time=0,d.call(this)};u.prototype={add:function(e){this._clips.push(e)},remove:function(e){if(e.__inStep)e.__needsRemove=!0;else{var t=U.indexOf(this._clips,e);t>=0&&this._clips.splice(t,1)}},_update:function(){for(var e=(new Date).getTime(),t=e-this._time,i=this._clips,n=i.length,a=[],o=[],r=0;n>r;r++){var s=i[r];s.__inStep=!0;var l=s.step(e);s.__inStep=!1,l&&(a.push(l),o.push(s))}for(var r=0;n>r;)i[r].__needsRemove?(i[r]=i[n-1],i.pop(),n--):r++;n=a.length;for(var r=0;n>r;r++)o[r].fire(a[r]);this._time=e,this.onframe(t),this.dispatch("frame",t),this.stage.update&&this.stage.update()},start:function(){function e(){t._running&&(p(e),t._update())}var t=this;this._running=!0,this._time=(new Date).getTime(),p(e)},stop:function(){this._running=!1},clear:function(){this._clips=[]},animate:function(e,t){t=t||{};var i=new y(e,t.loop,t.getter,t.setter);return i.animation=this,i},constructor:u},U.merge(u.prototype,d.prototype,!0);var y=function(e,n,a,o){this._tracks={},this._target=e,this._loop=n||!1,this._getter=a||t,this._setter=o||i,this._clipCount=0,this._delay=0,this._doneList=[],this._onframeList=[],this._clipList=[]};return y.prototype={when:function(e,t){for(var i in t)this._tracks[i]||(this._tracks[i]=[],0!==e&&this._tracks[i].push({time:0,value:l(this._getter(this._target,i))})),this._tracks[i].push({time:parseInt(e,10),value:t[i]});return this},during:function(e){return this._onframeList.push(e),this},start:function(e){var t=this,i=this._setter,l=this._getter,U="spline"===e,d=function(){if(t._clipCount--,0===t._clipCount){t._tracks={};for(var e=t._doneList.length,i=0;e>i;i++)t._doneList[i].call(t)}},p=function(p,c){var u=p.length;if(u){var y=p[0].value,g=o(y),b=!1,f=g&&o(y[0])?2:1;p.sort(function(e,t){return e.time-t.time});var k;if(u){k=p[u-1].time;for(var x=[],_=[],L=0;u>L;L++){x.push(p[L].time/k);var W=p[L].value;"string"==typeof W&&(W=V.toArray(W),0===W.length&&(W[0]=W[1]=W[2]=0,W[3]=1),b=!0),_.push(W)}var X,L,v,w,K,I,J,C=0,S=0;if(b)var E=[0,0,0,0];var F=function(e,o){if(S>o){for(X=Math.min(C+1,u-1),L=X;L>=0&&!(x[L]<=o);L--);L=Math.min(L,u-2)}else{for(L=C;u>L&&!(x[L]>o);L++);L=Math.min(L-1,u-2)}C=L,S=o;var m=x[L+1]-x[L];if(0!==m){if(v=(o-x[L])/m,U)if(K=_[L],w=_[0===L?L:L-1],I=_[L>u-2?u-1:L+1],J=_[L>u-3?u-1:L+2],g)r(w,K,I,J,v,v*v,v*v*v,l(e,c),f);else{var V;b?(V=r(w,K,I,J,v,v*v,v*v*v,E,1),V=h(E)):V=s(w,K,I,J,v,v*v,v*v*v),i(e,c,V)}else if(g)a(_[L],_[L+1],v,l(e,c),f);else{var V;b?(a(_[L],_[L+1],v,E,1),V=h(E)):V=n(_[L],_[L+1],v),i(e,c,V)}for(L=0;L=t[1]&&(e=t[1]),e},t.prototype.getLocation=function(e,t,i){var n=null!=e.x?e.x:"center";switch(n){case"center":n=Math.floor((this.canvasWidth-t)/2);break;case"left":n=0;break;case"right":n=this.canvasWidth-t}var a=null!=e.y?e.y:"center";switch(a){case"center":a=Math.floor((this.canvasHeight-i)/2);break;case"top":a=0;break;case"bottom":a=this.canvasHeight-i}return{x:n,y:a,width:t,height:i}},t}),i("zrender/Layer",["require","./mixin/Transformable","./tool/util","./config"],function(e){function t(){return!1}function i(e,t,i){var n=document.createElement(t),a=i.getWidth(),o=i.getHeight();return n.style.position="absolute",n.style.left=0,n.style.top=0,n.style.width=a+"px",n.style.height=o+"px",n.width=a*r.devicePixelRatio,n.height=o*r.devicePixelRatio,n.setAttribute("data-zr-dom-id",e),n}var n=e("./mixin/Transformable"),a=e("./tool/util"),o=window.G_vmlCanvasManager,r=e("./config"),s=function(e,a){this.id=e,this.dom=i(e,"canvas",a),this.dom.onselectstart=t,this.dom.style["-webkit-user-select"]="none",this.dom.style["user-select"]="none",this.dom.style["-webkit-touch-callout"]="none",this.dom.style["-webkit-tap-highlight-color"]="rgba(0,0,0,0)",this.dom.className=r.elementClassName,o&&o.initElement(this.dom),this.domBack=null,this.ctxBack=null,this.painter=a,this.unusedCount=0,this.config=null,this.dirty=!0,this.elCount=0,this.clearColor=0,this.motionBlur=!1,this.lastFrameAlpha=.7,this.zoomable=!1,this.panable=!1,this.maxZoom=1/0,this.minZoom=0,n.call(this)};return s.prototype.initContext=function(){this.ctx=this.dom.getContext("2d");var e=r.devicePixelRatio;1!=e&&this.ctx.scale(e,e)},s.prototype.createBackBuffer=function(){if(!o){this.domBack=i("back-"+this.id,"canvas",this.painter),this.ctxBack=this.domBack.getContext("2d");var e=r.devicePixelRatio;1!=e&&this.ctxBack.scale(e,e)}},s.prototype.resize=function(e,t){var i=r.devicePixelRatio;this.dom.style.width=e+"px",this.dom.style.height=t+"px",this.dom.setAttribute("width",e*i),this.dom.setAttribute("height",t*i),1!=i&&this.ctx.scale(i,i),this.domBack&&(this.domBack.setAttribute("width",e*i),this.domBack.setAttribute("height",t*i),1!=i&&this.ctxBack.scale(i,i))},s.prototype.clear=function(){var e=this.dom,t=this.ctx,i=e.width,n=e.height,a=this.clearColor&&!o,s=this.motionBlur&&!o,l=this.lastFrameAlpha,h=r.devicePixelRatio;if(s&&(this.domBack||this.createBackBuffer(),this.ctxBack.globalCompositeOperation="copy",this.ctxBack.drawImage(e,0,0,i/h,n/h)),t.clearRect(0,0,i/h,n/h),a&&(t.save(),t.fillStyle=this.clearColor,t.fillRect(0,0,i/h,n/h),t.restore()),s){var m=this.domBack;t.save(),t.globalAlpha=l,t.drawImage(m,0,0,i/h,n/h),t.restore()}},a.merge(s.prototype,n.prototype),s}),i("zrender/shape/Text",["require","../tool/area","./Base","../tool/util"],function(e){ +var t=e("../tool/area"),i=e("./Base"),n=function(e){i.call(this,e)};return n.prototype={type:"text",brush:function(e,i){var n=this.style;if(i&&(n=this.getHighlightStyle(n,this.highlightStyle||{})),"undefined"!=typeof n.text&&n.text!==!1){e.save(),this.doClip(e),this.setContext(e,n),this.setTransform(e),n.textFont&&(e.font=n.textFont),e.textAlign=n.textAlign||"start",e.textBaseline=n.textBaseline||"middle";var a,o=(n.text+"").split("\n"),r=t.getTextHeight("国",n.textFont),s=this.getRect(n),l=n.x;a="top"==n.textBaseline?s.y:"bottom"==n.textBaseline?s.y+r:s.y+r/2;for(var h=0,m=o.length;m>h;h++){if(n.maxWidth)switch(n.brushType){case"fill":e.fillText(o[h],l,a,n.maxWidth);break;case"stroke":e.strokeText(o[h],l,a,n.maxWidth);break;case"both":e.fillText(o[h],l,a,n.maxWidth),e.strokeText(o[h],l,a,n.maxWidth);break;default:e.fillText(o[h],l,a,n.maxWidth)}else switch(n.brushType){case"fill":e.fillText(o[h],l,a);break;case"stroke":e.strokeText(o[h],l,a);break;case"both":e.fillText(o[h],l,a),e.strokeText(o[h],l,a);break;default:e.fillText(o[h],l,a)}a+=r}e.restore()}},getRect:function(e){if(e.__rect)return e.__rect;var i=t.getTextWidth(e.text,e.textFont),n=t.getTextHeight(e.text,e.textFont),a=e.x;"end"==e.textAlign||"right"==e.textAlign?a-=i:"center"==e.textAlign&&(a-=i/2);var o;return o="top"==e.textBaseline?e.y:"bottom"==e.textBaseline?e.y-n:e.y-n/2,e.__rect={x:a,y:o,width:i,height:n},e.__rect}},e("../tool/util").inherits(n,i),n}),i("zrender/shape/Rectangle",["require","./Base","../tool/util"],function(e){var t=e("./Base"),i=function(e){t.call(this,e)};return i.prototype={type:"rectangle",_buildRadiusPath:function(e,t){var i,n,a,o,r=t.x,s=t.y,l=t.width,h=t.height,m=t.radius;"number"==typeof m?i=n=a=o=m:m instanceof Array?1===m.length?i=n=a=o=m[0]:2===m.length?(i=a=m[0],n=o=m[1]):3===m.length?(i=m[0],n=o=m[1],a=m[2]):(i=m[0],n=m[1],a=m[2],o=m[3]):i=n=a=o=0;var V;i+n>l&&(V=i+n,i*=l/V,n*=l/V),a+o>l&&(V=a+o,a*=l/V,o*=l/V),n+a>h&&(V=n+a,n*=h/V,a*=h/V),i+o>h&&(V=i+o,i*=h/V,o*=h/V),e.moveTo(r+i,s),e.lineTo(r+l-n,s),0!==n&&e.quadraticCurveTo(r+l,s,r+l,s+n),e.lineTo(r+l,s+h-a),0!==a&&e.quadraticCurveTo(r+l,s+h,r+l-a,s+h),e.lineTo(r+o,s+h),0!==o&&e.quadraticCurveTo(r,s+h,r,s+h-o),e.lineTo(r,s+i),0!==i&&e.quadraticCurveTo(r,s,r+i,s)},buildPath:function(e,t){t.radius?this._buildRadiusPath(e,t):(e.moveTo(t.x,t.y),e.lineTo(t.x+t.width,t.y),e.lineTo(t.x+t.width,t.y+t.height),e.lineTo(t.x,t.y+t.height),e.lineTo(t.x,t.y)),e.closePath()},getRect:function(e){if(e.__rect)return e.__rect;var t;return t="stroke"==e.brushType||"fill"==e.brushType?e.lineWidth||1:0,e.__rect={x:Math.round(e.x-t/2),y:Math.round(e.y-t/2),width:e.width+t,height:e.height+t},e.__rect}},e("../tool/util").inherits(i,t),i}),i("zrender/tool/area",["require","./util","./curve"],function(e){"use strict";function t(e){return e%=C,0>e&&(e+=C),e}function i(e,t,i,o){if(!t||!e)return!1;var r=e.type;L=L||W.getContext();var s=n(e,t,i,o);if("undefined"!=typeof s)return s;if(e.buildPath&&L.isPointInPath)return a(e,L,t,i,o);switch(r){case"ellipse":return!0;case"trochoid":var l="out"==t.location?t.r1+t.r2+t.d:t.r1-t.r2+t.d;return d(t,i,o,l);case"rose":return d(t,i,o,t.maxr);default:return!1}}function n(e,t,i,n){var a=e.type;switch(a){case"bezier-curve":return"undefined"==typeof t.cpX2?l(t.xStart,t.yStart,t.cpX1,t.cpY1,t.xEnd,t.yEnd,t.lineWidth,i,n):s(t.xStart,t.yStart,t.cpX1,t.cpY1,t.cpX2,t.cpY2,t.xEnd,t.yEnd,t.lineWidth,i,n);case"line":return r(t.xStart,t.yStart,t.xEnd,t.yEnd,t.lineWidth,i,n);case"polyline":return m(t.pointList,t.lineWidth,i,n);case"ring":return V(t.x,t.y,t.r0,t.r,i,n);case"circle":return d(t.x,t.y,t.r,i,n);case"sector":var o=t.startAngle*Math.PI/180,h=t.endAngle*Math.PI/180;return t.clockWise||(o=-o,h=-h),p(t.x,t.y,t.r0,t.r,o,h,!t.clockWise,i,n);case"path":return t.pathArray&&k(t.pathArray,Math.max(t.lineWidth,5),t.brushType,i,n);case"polygon":case"star":case"isogon":return c(t.pointList,i,n);case"text":var u=t.__rect||e.getRect(t);return U(u.x,u.y,u.width,u.height,i,n);case"rectangle":case"image":return U(t.x,t.y,t.width,t.height,i,n)}}function a(e,t,i,n,a){return t.beginPath(),e.buildPath(t,i),t.closePath(),t.isPointInPath(n,a)}function o(e,t,n,a){return!i(e,t,n,a)}function r(e,t,i,n,a,o,r){if(0===a)return!1;var s=Math.max(a,5),l=0,h=e;if(r>t+s&&r>n+s||t-s>r&&n-s>r||o>e+s&&o>i+s||e-s>o&&i-s>o)return!1;if(e===i)return Math.abs(o-e)<=s/2;l=(t-n)/(e-i),h=(e*n-i*t)/(e-i);var m=l*o-r+h,V=m*m/(l*l+1);return s/2*s/2>=V}function s(e,t,i,n,a,o,r,s,l,h,m){if(0===l)return!1;var V=Math.max(l,5);if(m>t+V&&m>n+V&&m>o+V&&m>s+V||t-V>m&&n-V>m&&o-V>m&&s-V>m||h>e+V&&h>i+V&&h>a+V&&h>r+V||e-V>h&&i-V>h&&a-V>h&&r-V>h)return!1;var U=X.cubicProjectPoint(e,t,i,n,a,o,r,s,h,m,null);return V/2>=U}function l(e,t,i,n,a,o,r,s,l){if(0===r)return!1;var h=Math.max(r,5);if(l>t+h&&l>n+h&&l>o+h||t-h>l&&n-h>l&&o-h>l||s>e+h&&s>i+h&&s>a+h||e-h>s&&i-h>s&&a-h>s)return!1;var m=X.quadraticProjectPoint(e,t,i,n,a,o,s,l,null);return h/2>=m}function h(e,i,n,a,o,r,s,l,h){if(0===s)return!1;var m=Math.max(s,5);l-=e,h-=i;var V=Math.sqrt(l*l+h*h);if(V-m>n||n>V+m)return!1;if(Math.abs(a-o)>=C)return!0;if(r){var U=a;a=t(o),o=t(U)}else a=t(a),o=t(o);a>o&&(o+=C);var d=Math.atan2(h,l);return 0>d&&(d+=C),d>=a&&o>=d||d+C>=a&&o>=d+C}function m(e,t,i,n){for(var t=Math.max(t,10),a=0,o=e.length-1;o>a;a++){var s=e[a][0],l=e[a][1],h=e[a+1][0],m=e[a+1][1];if(r(s,l,h,m,t,i,n))return!0}return!1}function V(e,t,i,n,a,o){var r=(a-e)*(a-e)+(o-t)*(o-t);return n*n>r&&r>i*i}function U(e,t,i,n,a,o){return a>=e&&e+i>=a&&o>=t&&t+n>=o}function d(e,t,i,n,a){return i*i>(n-e)*(n-e)+(a-t)*(a-t)}function p(e,t,i,n,a,o,r,s,l){return h(e,t,(i+n)/2,a,o,r,n-i,s,l)}function c(e,t,i){for(var n=e.length,a=0,o=0,r=n-1;n>o;o++){var s=e[r][0],l=e[r][1],h=e[o][0],m=e[o][1];a+=u(s,l,h,m,t,i),r=o}return 0!==a}function u(e,t,i,n,a,o){if(o>t&&o>n||t>o&&n>o)return 0;if(n==t)return 0;var r=t>n?1:-1,s=(o-t)/(n-t),l=s*(i-e)+e;return l>a?r:0}function y(){var e=E[0];E[0]=E[1],E[1]=e}function g(e,t,i,n,a,o,r,s,l,h){if(h>t&&h>n&&h>o&&h>s||t>h&&n>h&&o>h&&s>h)return 0;var m=X.cubicRootAt(t,n,o,s,h,S);if(0===m)return 0;for(var V,U,d=0,p=-1,c=0;m>c;c++){var u=S[c],g=X.cubicAt(e,i,a,r,u);l>g||(0>p&&(p=X.cubicExtrema(t,n,o,s,E),E[1]1&&y(),V=X.cubicAt(t,n,o,s,E[0]),p>1&&(U=X.cubicAt(t,n,o,s,E[1]))),d+=2==p?uV?1:-1:uU?1:-1:U>s?1:-1:uV?1:-1:V>s?1:-1)}return d}function b(e,t,i,n,a,o,r,s){if(s>t&&s>n&&s>o||t>s&&n>s&&o>s)return 0;var l=X.quadraticRootAt(t,n,o,s,S);if(0===l)return 0;var h=X.quadraticExtremum(t,n,o);if(h>=0&&1>=h){for(var m=0,V=X.quadraticAt(t,n,o,h),U=0;l>U;U++){var d=X.quadraticAt(e,i,a,S[U]);r>d||(m+=S[U]V?1:-1:V>o?1:-1)}return m}var d=X.quadraticAt(e,i,a,S[0]);return r>d?0:t>o?1:-1}function f(e,i,n,a,o,r,s,l){if(l-=i,l>n||-n>l)return 0;var h=Math.sqrt(n*n-l*l);if(S[0]=-h,S[1]=h,Math.abs(a-o)>=C){a=0,o=C;var m=r?1:-1;return s>=S[0]+e&&s<=S[1]+e?m:0}if(r){var h=a;a=t(o),o=t(h)}else a=t(a),o=t(o);a>o&&(o+=C);for(var V=0,U=0;2>U;U++){var d=S[U];if(d+e>s){var p=Math.atan2(l,d),m=r?1:-1;0>p&&(p=C+p),(p>=a&&o>=p||p+C>=a&&o>=p+C)&&(p>Math.PI/2&&p<1.5*Math.PI&&(m=-m),V+=m)}}return V}function k(e,t,i,n,a){var o=0,m=0,V=0,U=0,d=0,p=!0,c=!0;i=i||"fill";for(var y="stroke"===i||"both"===i,k="fill"===i||"both"===i,x=0;x0&&(k&&(o+=u(m,V,U,d,n,a)),0!==o))return!0;U=L[L.length-2],d=L[L.length-1],p=!1,c&&"A"!==_.command&&(c=!1,m=U,V=d)}switch(_.command){case"M":m=L[0],V=L[1];break;case"L":if(y&&r(m,V,L[0],L[1],t,n,a))return!0;k&&(o+=u(m,V,L[0],L[1],n,a)),m=L[0],V=L[1];break;case"C":if(y&&s(m,V,L[0],L[1],L[2],L[3],L[4],L[5],t,n,a))return!0;k&&(o+=g(m,V,L[0],L[1],L[2],L[3],L[4],L[5],n,a)),m=L[4],V=L[5];break;case"Q":if(y&&l(m,V,L[0],L[1],L[2],L[3],t,n,a))return!0;k&&(o+=b(m,V,L[0],L[1],L[2],L[3],n,a)),m=L[2],V=L[3];break;case"A":var W=L[0],X=L[1],v=L[2],w=L[3],K=L[4],I=L[5],J=Math.cos(K)*v+W,C=Math.sin(K)*w+X;c?(c=!1,U=J,d=C):o+=u(m,V,J,C);var S=(n-W)*w/v+W;if(y&&h(W,X,w,K,K+I,1-L[7],t,S,a))return!0;k&&(o+=f(W,X,w,K,K+I,1-L[7],S,a)),m=Math.cos(K+I)*v+W,V=Math.sin(K+I)*w+X;break;case"z":if(y&&r(m,V,U,d,t,n,a))return!0;p=!0}}return k&&(o+=u(m,V,U,d,n,a)),0!==o}function x(e,t){var i=e+":"+t;if(v[i])return v[i];L=L||W.getContext(),L.save(),t&&(L.font=t),e=(e+"").split("\n");for(var n=0,a=0,o=e.length;o>a;a++)n=Math.max(L.measureText(e[a]).width,n);return L.restore(),v[i]=n,++K>J&&(K=0,v={}),n}function _(e,t){var i=e+":"+t;if(w[i])return w[i];L=L||W.getContext(),L.save(),t&&(L.font=t),e=(e+"").split("\n");var n=(L.measureText("国").width+2)*e.length;return L.restore(),w[i]=n,++I>J&&(I=0,w={}),n}var L,W=e("./util"),X=e("./curve"),v={},w={},K=0,I=0,J=5e3,C=2*Math.PI,S=[-1,-1,-1],E=[-1,-1];return{isInside:i,isOutside:o,getTextWidth:x,getTextHeight:_,isInsidePath:k,isInsidePolygon:c,isInsideSector:p,isInsideCircle:d,isInsideLine:r,isInsideRect:U,isInsidePolyline:m,isInsideCubicStroke:s,isInsideQuadraticStroke:l}}),i("zrender/shape/Base",["require","../tool/matrix","../tool/guid","../tool/util","../tool/log","../mixin/Transformable","../mixin/Eventful","../tool/area","../tool/color"],function(e){function t(t,n,a,o,r,s,l){r&&(t.font=r),t.textAlign=s,t.textBaseline=l;var h=i(n,a,o,r,s,l);n=(n+"").split("\n");var m=e("../tool/area").getTextHeight("国",r);switch(l){case"top":o=h.y;break;case"bottom":o=h.y+m;break;default:o=h.y+m/2}for(var V=0,U=n.length;U>V;V++)t.fillText(n[V],a,o),o+=m}function i(t,i,n,a,o,r){var s=e("../tool/area"),l=s.getTextWidth(t,a),h=s.getTextHeight("国",a);switch(t=(t+"").split("\n"),o){case"end":case"right":i-=l;break;case"center":i-=l/2}switch(r){case"top":break;case"bottom":n-=h*t.length;break;default:n-=h*t.length/2}return{x:i,y:n,width:l,height:h*t.length}}var n=window.G_vmlCanvasManager,a=e("../tool/matrix"),o=e("../tool/guid"),r=e("../tool/util"),s=e("../tool/log"),l=e("../mixin/Transformable"),h=e("../mixin/Eventful"),m=function(e){e=e||{},this.id=e.id||o();for(var t in e)this[t]=e[t];this.style=this.style||{},this.highlightStyle=this.highlightStyle||null,this.parent=null,this.__dirty=!0,this.__clipShapes=[],l.call(this),h.call(this)};m.prototype.invisible=!1,m.prototype.ignore=!1,m.prototype.zlevel=0,m.prototype.draggable=!1,m.prototype.clickable=!1,m.prototype.hoverable=!0,m.prototype.z=0,m.prototype.brush=function(e,t){var i=this.beforeBrush(e,t);switch(e.beginPath(),this.buildPath(e,i),i.brushType){case"both":e.fill();case"stroke":i.lineWidth>0&&e.stroke();break;default:e.fill()}this.drawText(e,i,this.style),this.afterBrush(e)},m.prototype.beforeBrush=function(e,t){var i=this.style;return this.brushTypeOnly&&(i.brushType=this.brushTypeOnly),t&&(i=this.getHighlightStyle(i,this.highlightStyle||{},this.brushTypeOnly)),"stroke"==this.brushTypeOnly&&(i.strokeColor=i.strokeColor||i.color),e.save(),this.doClip(e),this.setContext(e,i),this.setTransform(e),i},m.prototype.afterBrush=function(e){e.restore()};var V=[["color","fillStyle"],["strokeColor","strokeStyle"],["opacity","globalAlpha"],["lineCap","lineCap"],["lineJoin","lineJoin"],["miterLimit","miterLimit"],["lineWidth","lineWidth"],["shadowBlur","shadowBlur"],["shadowColor","shadowColor"],["shadowOffsetX","shadowOffsetX"],["shadowOffsetY","shadowOffsetY"]];m.prototype.setContext=function(e,t){for(var i=0,n=V.length;n>i;i++){var a=V[i][0],o=t[a],r=V[i][1];"undefined"!=typeof o&&(e[r]=o)}};var U=a.create();return m.prototype.doClip=function(e){if(this.__clipShapes&&!n)for(var t=0;t=i.x&&e<=i.x+i.width&&t>=i.y&&t<=i.y+i.height},m.prototype.drawText=function(e,i,n){if("undefined"!=typeof i.text&&i.text!==!1){var a=i.textColor||i.color||i.strokeColor;e.fillStyle=a;var o,r,s,l,h=10,m=i.textPosition||this.textPosition||"top";switch(m){case"inside":case"top":case"bottom":case"left":case"right":if(this.getRect){var V=(n||i).__rect||this.getRect(n||i);switch(m){case"inside":s=V.x+V.width/2,l=V.y+V.height/2,o="center",r="middle","stroke"!=i.brushType&&a==i.color&&(e.fillStyle="#fff");break;case"left":s=V.x-h,l=V.y+V.height/2,o="end",r="middle";break;case"right":s=V.x+V.width+h,l=V.y+V.height/2,o="start",r="middle";break;case"top":s=V.x+V.width/2,l=V.y-h,o="center",r="bottom";break;case"bottom":s=V.x+V.width/2,l=V.y+V.height+h,o="center",r="top"}}break;case"start":case"end":var U=i.pointList||[[i.xStart||0,i.yStart||0],[i.xEnd||0,i.yEnd||0]],d=U.length;if(2>d)return;var p,c,u,y;switch(m){case"start":p=U[1][0],c=U[0][0],u=U[1][1],y=U[0][1];break;case"end":p=U[d-2][0],c=U[d-1][0],u=U[d-2][1],y=U[d-1][1]}s=c,l=y;var g=Math.atan((u-y)/(c-p))/Math.PI*180;0>c-p?g+=180:0>u-y&&(g+=360),h=5,g>=30&&150>=g?(o="center",r="bottom",l-=h):g>150&&210>g?(o="right",r="middle",s-=h):g>=210&&330>=g?(o="center",r="top",l+=h):(o="left",r="middle",s+=h);break;case"specific":s=i.textX||0,l=i.textY||0,o="start",r="middle"}null!=s&&null!=l&&t(e,i.text,s,l,i.textFont,i.textAlign||o,i.textBaseline||r)}},m.prototype.modSelf=function(){this.__dirty=!0,this.style&&(this.style.__rect=null),this.highlightStyle&&(this.highlightStyle.__rect=null)},m.prototype.isSilent=function(){return!(this.hoverable||this.draggable||this.clickable||this.onmousemove||this.onmouseover||this.onmouseout||this.onmousedown||this.onmouseup||this.onclick||this.ondragenter||this.ondragover||this.ondragleave||this.ondrop)},r.merge(m.prototype,l.prototype,!0),r.merge(m.prototype,h.prototype,!0),m}),i("zrender/tool/curve",["require","./vector"],function(e){function t(e){return e>-u&&u>e}function i(e){return e>u||-u>e}function n(e,t,i,n,a){var o=1-a;return o*o*(o*e+3*a*t)+a*a*(a*n+3*o*i)}function a(e,t,i,n,a){var o=1-a;return 3*(((t-e)*o+2*(i-t)*a)*o+(n-i)*a*a)}function o(e,i,n,a,o,r){var s=a+3*(i-n)-e,l=3*(n-2*i+e),h=3*(i-e),m=e-o,V=l*l-3*s*h,U=l*h-9*s*m,d=h*h-3*l*m,p=0;if(t(V)&&t(U))if(t(l))r[0]=0;else{var c=-h/l;c>=0&&1>=c&&(r[p++]=c)}else{var u=U*U-4*V*d;if(t(u)){var b=U/V,c=-l/s+b,f=-b/2;c>=0&&1>=c&&(r[p++]=c),f>=0&&1>=f&&(r[p++]=f)}else if(u>0){var k=Math.sqrt(u),x=V*l+1.5*s*(-U+k),_=V*l+1.5*s*(-U-k);x=0>x?-Math.pow(-x,g):Math.pow(x,g),_=0>_?-Math.pow(-_,g):Math.pow(_,g);var c=(-l-(x+_))/(3*s);c>=0&&1>=c&&(r[p++]=c)}else{var L=(2*V*l-3*s*U)/(2*Math.sqrt(V*V*V)),W=Math.acos(L)/3,X=Math.sqrt(V),v=Math.cos(W),c=(-l-2*X*v)/(3*s),f=(-l+X*(v+y*Math.sin(W)))/(3*s),w=(-l+X*(v-y*Math.sin(W)))/(3*s);c>=0&&1>=c&&(r[p++]=c),f>=0&&1>=f&&(r[p++]=f),w>=0&&1>=w&&(r[p++]=w)}}return p}function r(e,n,a,o,r){var s=6*a-12*n+6*e,l=9*n+3*o-3*e-9*a,h=3*n-3*e,m=0;if(t(l)){if(i(s)){var V=-h/s;V>=0&&1>=V&&(r[m++]=V)}}else{var U=s*s-4*l*h;if(t(U))r[0]=-s/(2*l);else if(U>0){var d=Math.sqrt(U),V=(-s+d)/(2*l),p=(-s-d)/(2*l);V>=0&&1>=V&&(r[m++]=V),p>=0&&1>=p&&(r[m++]=p)}}return m}function s(e,t,i,n,a,o){var r=(t-e)*a+e,s=(i-t)*a+t,l=(n-i)*a+i,h=(s-r)*a+r,m=(l-s)*a+s,V=(m-h)*a+h;o[0]=e,o[1]=r,o[2]=h,o[3]=V,o[4]=V,o[5]=m,o[6]=l,o[7]=n}function l(e,t,i,a,o,r,s,l,h,m,V){var U,d=.005,p=1/0;b[0]=h,b[1]=m;for(var y=0;1>y;y+=.05){f[0]=n(e,i,o,s,y),f[1]=n(t,a,r,l,y);var g=c.distSquare(b,f);p>g&&(U=y,p=g)}p=1/0;for(var x=0;32>x&&!(u>d);x++){var _=U-d,L=U+d;f[0]=n(e,i,o,s,_),f[1]=n(t,a,r,l,_);var g=c.distSquare(f,b);if(_>=0&&p>g)U=_,p=g;else{k[0]=n(e,i,o,s,L),k[1]=n(t,a,r,l,L);var W=c.distSquare(k,b);1>=L&&p>W?(U=L,p=W):d*=.5}}return V&&(V[0]=n(e,i,o,s,U),V[1]=n(t,a,r,l,U)),Math.sqrt(p)}function h(e,t,i,n){var a=1-n;return a*(a*e+2*n*t)+n*n*i}function m(e,t,i,n){return 2*((1-n)*(t-e)+n*(i-t))}function V(e,n,a,o,r){var s=e-2*n+a,l=2*(n-e),h=e-o,m=0;if(t(s)){if(i(l)){var V=-h/l;V>=0&&1>=V&&(r[m++]=V)}}else{var U=l*l-4*s*h;if(t(U)){var V=-l/(2*s);V>=0&&1>=V&&(r[m++]=V)}else if(U>0){var d=Math.sqrt(U),V=(-l+d)/(2*s),p=(-l-d)/(2*s);V>=0&&1>=V&&(r[m++]=V),p>=0&&1>=p&&(r[m++]=p)}}return m}function U(e,t,i){var n=e+i-2*t;return 0===n?.5:(e-t)/n}function d(e,t,i,n,a){var o=(t-e)*n+e,r=(i-t)*n+t,s=(r-o)*n+o;a[0]=e,a[1]=o,a[2]=s,a[3]=s,a[4]=r,a[5]=i}function p(e,t,i,n,a,o,r,s,l){var m,V=.005,U=1/0;b[0]=r,b[1]=s;for(var d=0;1>d;d+=.05){f[0]=h(e,i,a,d),f[1]=h(t,n,o,d);var p=c.distSquare(b,f);U>p&&(m=d,U=p)}U=1/0;for(var y=0;32>y&&!(u>V);y++){var g=m-V,x=m+V;f[0]=h(e,i,a,g),f[1]=h(t,n,o,g);var p=c.distSquare(f,b);if(g>=0&&U>p)m=g,U=p;else{k[0]=h(e,i,a,x),k[1]=h(t,n,o,x);var _=c.distSquare(k,b);1>=x&&U>_?(m=x,U=_):V*=.5}}return l&&(l[0]=h(e,i,a,m),l[1]=h(t,n,o,m)),Math.sqrt(U)}var c=e("./vector"),u=1e-4,y=Math.sqrt(3),g=1/3,b=c.create(),f=c.create(),k=c.create();return{cubicAt:n,cubicDerivativeAt:a,cubicRootAt:o,cubicExtrema:r,cubicSubdivide:s,cubicProjectPoint:l,quadraticAt:h,quadraticDerivativeAt:m,quadraticRootAt:V,quadraticExtremum:U,quadraticSubdivide:d,quadraticProjectPoint:p}}),i("zrender/mixin/Transformable",["require","../tool/matrix","../tool/vector"],function(e){"use strict";function t(e){return e>-s&&s>e}function i(e){return e>s||-s>e}var n=e("../tool/matrix"),a=e("../tool/vector"),o=[0,0],r=n.translate,s=5e-5,l=function(){this.position||(this.position=[0,0]),"undefined"==typeof this.rotation&&(this.rotation=[0,0,0]),this.scale||(this.scale=[1,1,0,0]),this.needLocalTransform=!1,this.needTransform=!1};return l.prototype={constructor:l,updateNeedTransform:function(){this.needLocalTransform=i(this.rotation[0])||i(this.position[0])||i(this.position[1])||i(this.scale[0]-1)||i(this.scale[1]-1)},updateTransform:function(){this.updateNeedTransform();var e=this.parent&&this.parent.needTransform;if(this.needTransform=this.needLocalTransform||e,this.needTransform){var t=this.transform||n.create();if(n.identity(t),this.needLocalTransform){var a=this.scale;if(i(a[0])||i(a[1])){o[0]=-a[2]||0,o[1]=-a[3]||0;var s=i(o[0])||i(o[1]);s&&r(t,t,o),n.scale(t,t,a),s&&(o[0]=-o[0],o[1]=-o[1],r(t,t,o))}if(this.rotation instanceof Array){if(0!==this.rotation[0]){o[0]=-this.rotation[1]||0,o[1]=-this.rotation[2]||0;var s=i(o[0])||i(o[1]);s&&r(t,t,o),n.rotate(t,t,this.rotation[0]),s&&(o[0]=-o[0],o[1]=-o[1],r(t,t,o))}}else 0!==this.rotation&&n.rotate(t,t,this.rotation);(i(this.position[0])||i(this.position[1]))&&r(t,t,this.position)}e&&(this.needLocalTransform?n.mul(t,this.parent.transform,t):n.copy(t,this.parent.transform)),this.transform=t,this.invTransform=this.invTransform||n.create(),n.invert(this.invTransform,t)}},setTransform:function(e){if(this.needTransform){var t=this.transform;e.transform(t[0],t[1],t[2],t[3],t[4],t[5])}},lookAt:function(){var e=a.create();return function(i){this.transform||(this.transform=n.create());var o=this.transform;if(a.sub(e,i,this.position),!t(e[0])||!t(e[1])){a.normalize(e,e);var r=this.scale;o[2]=e[0]*r[1],o[3]=e[1]*r[1],o[0]=e[1]*r[0],o[1]=-e[0]*r[0],o[4]=this.position[0],o[5]=this.position[1],this.decomposeTransform()}}}(),decomposeTransform:function(){if(this.transform){var e=this.transform,t=e[0]*e[0]+e[1]*e[1],n=this.position,a=this.scale,o=this.rotation;i(t-1)&&(t=Math.sqrt(t));var r=e[2]*e[2]+e[3]*e[3];i(r-1)&&(r=Math.sqrt(r)),n[0]=e[4],n[1]=e[5],a[0]=t,a[1]=r,a[2]=a[3]=0,o[0]=Math.atan2(-e[1]/r,e[0]/t),o[1]=o[2]=0}},transformCoordToLocal:function(e,t){var i=[e,t];return this.needTransform&&this.invTransform&&a.applyTransform(i,i,this.invTransform),i}},l}),i("zrender/Group",["require","./tool/guid","./tool/util","./mixin/Transformable","./mixin/Eventful"],function(e){var t=e("./tool/guid"),i=e("./tool/util"),n=e("./mixin/Transformable"),a=e("./mixin/Eventful"),o=function(e){e=e||{},this.id=e.id||t();for(var i in e)this[i]=e[i];this.type="group",this.clipShape=null,this._children=[],this._storage=null,this.__dirty=!0,n.call(this),a.call(this)};return o.prototype.ignore=!1,o.prototype.children=function(){return this._children.slice()},o.prototype.childAt=function(e){return this._children[e]},o.prototype.addChild=function(e){e!=this&&e.parent!=this&&(e.parent&&e.parent.removeChild(e),this._children.push(e),e.parent=this,this._storage&&this._storage!==e._storage&&(this._storage.addToMap(e),e instanceof o&&e.addChildrenToStorage(this._storage)))},o.prototype.removeChild=function(e){var t=i.indexOf(this._children,e);t>=0&&this._children.splice(t,1),e.parent=null,this._storage&&(this._storage.delFromMap(e.id),e instanceof o&&e.delChildrenFromStorage(this._storage))},o.prototype.clearChildren=function(){for(var e=0;et)){t=Math.min(t,1);var n="string"==typeof this.easing?i[this.easing]:this.easing,a="function"==typeof n?n(t):t;return this.fire("frame",a),1==t?this.loop?(this.restart(),"restart"):(this.__needsRemove=!0,"destroy"):null}},restart:function(){var e=(new Date).getTime(),t=(e-this._startTime)%this._life;this._startTime=(new Date).getTime()-t+this.gap,this.__needsRemove=!1},fire:function(e,t){for(var i=0,n=this._targetPool.length;n>i;i++)this["on"+e]&&this["on"+e](this._targetPool[i],t)},constructor:t},t}),i("zrender/animation/easing",[],function(){var e={Linear:function(e){return e},QuadraticIn:function(e){return e*e},QuadraticOut:function(e){return e*(2-e)},QuadraticInOut:function(e){return(e*=2)<1?.5*e*e:-.5*(--e*(e-2)-1)},CubicIn:function(e){return e*e*e},CubicOut:function(e){return--e*e*e+1},CubicInOut:function(e){return(e*=2)<1?.5*e*e*e:.5*((e-=2)*e*e+2)},QuarticIn:function(e){return e*e*e*e},QuarticOut:function(e){return 1- --e*e*e*e},QuarticInOut:function(e){return(e*=2)<1?.5*e*e*e*e:-.5*((e-=2)*e*e*e-2)},QuinticIn:function(e){return e*e*e*e*e},QuinticOut:function(e){return--e*e*e*e*e+1},QuinticInOut:function(e){return(e*=2)<1?.5*e*e*e*e*e:.5*((e-=2)*e*e*e*e+2)},SinusoidalIn:function(e){return 1-Math.cos(e*Math.PI/2)},SinusoidalOut:function(e){return Math.sin(e*Math.PI/2)},SinusoidalInOut:function(e){return.5*(1-Math.cos(Math.PI*e))},ExponentialIn:function(e){return 0===e?0:Math.pow(1024,e-1)},ExponentialOut:function(e){return 1===e?1:1-Math.pow(2,-10*e)},ExponentialInOut:function(e){return 0===e?0:1===e?1:(e*=2)<1?.5*Math.pow(1024,e-1):.5*(-Math.pow(2,-10*(e-1))+2)},CircularIn:function(e){return 1-Math.sqrt(1-e*e)},CircularOut:function(e){return Math.sqrt(1- --e*e)},CircularInOut:function(e){return(e*=2)<1?-.5*(Math.sqrt(1-e*e)-1):.5*(Math.sqrt(1-(e-=2)*e)+1)},ElasticIn:function(e){var t,i=.1,n=.4;return 0===e?0:1===e?1:(!i||1>i?(i=1,t=n/4):t=n*Math.asin(1/i)/(2*Math.PI),-(i*Math.pow(2,10*(e-=1))*Math.sin(2*(e-t)*Math.PI/n)))},ElasticOut:function(e){var t,i=.1,n=.4;return 0===e?0:1===e?1:(!i||1>i?(i=1,t=n/4):t=n*Math.asin(1/i)/(2*Math.PI),i*Math.pow(2,-10*e)*Math.sin(2*(e-t)*Math.PI/n)+1)},ElasticInOut:function(e){var t,i=.1,n=.4;return 0===e?0:1===e?1:(!i||1>i?(i=1,t=n/4):t=n*Math.asin(1/i)/(2*Math.PI),(e*=2)<1?-.5*i*Math.pow(2,10*(e-=1))*Math.sin(2*(e-t)*Math.PI/n):i*Math.pow(2,-10*(e-=1))*Math.sin(2*(e-t)*Math.PI/n)*.5+1)},BackIn:function(e){var t=1.70158;return e*e*((t+1)*e-t)},BackOut:function(e){var t=1.70158;return--e*e*((t+1)*e+t)+1},BackInOut:function(e){var t=2.5949095;return(e*=2)<1?.5*e*e*((t+1)*e-t):.5*((e-=2)*e*((t+1)*e+t)+2)},BounceIn:function(t){return 1-e.BounceOut(1-t)},BounceOut:function(e){return 1/2.75>e?7.5625*e*e:2/2.75>e?7.5625*(e-=1.5/2.75)*e+.75:2.5/2.75>e?7.5625*(e-=2.25/2.75)*e+.9375:7.5625*(e-=2.625/2.75)*e+.984375},BounceInOut:function(t){return.5>t?.5*e.BounceIn(2*t):.5*e.BounceOut(2*t-1)+.5}};return e}),i("echarts/chart/base",["require","zrender/shape/Image","../util/shape/Icon","../util/shape/MarkLine","../util/shape/Symbol","zrender/shape/Polyline","zrender/shape/ShapeBundle","../config","../util/ecData","../util/ecAnimation","../util/ecEffect","../util/accMath","../component/base","../layout/EdgeBundling","zrender/tool/util","zrender/tool/area"],function(e){function t(e){return null!=e.x&&null!=e.y}function i(e,t,i,n,a){p.call(this,e,t,i,n,a);var o=this;this.selectedMap={},this.lastShapeList=[],this.shapeHandler={onclick:function(){o.isClick=!0},ondragover:function(e){var t=e.target;t.highlightStyle=t.highlightStyle||{};var i=t.highlightStyle,n=i.brushTyep,a=i.strokeColor,r=i.lineWidth;i.brushType="stroke",i.strokeColor=o.ecTheme.calculableColor||h.calculableColor,i.lineWidth="icon"===t.type?30:10,o.zr.addHoverShape(t),setTimeout(function(){i&&(i.brushType=n,i.strokeColor=a,i.lineWidth=r)},20)},ondrop:function(e){null!=m.get(e.dragged,"data")&&(o.isDrop=!0)},ondragend:function(){o.isDragend=!0}}}var n=e("zrender/shape/Image"),a=e("../util/shape/Icon"),o=e("../util/shape/MarkLine"),r=e("../util/shape/Symbol"),s=e("zrender/shape/Polyline"),l=e("zrender/shape/ShapeBundle"),h=e("../config"),m=e("../util/ecData"),V=e("../util/ecAnimation"),U=e("../util/ecEffect"),d=e("../util/accMath"),p=e("../component/base"),c=e("../layout/EdgeBundling"),u=e("zrender/tool/util"),y=e("zrender/tool/area");return i.prototype={setCalculable:function(e){return e.dragEnableTime=this.ecTheme.DRAG_ENABLE_TIME||h.DRAG_ENABLE_TIME,e.ondragover=this.shapeHandler.ondragover,e.ondragend=this.shapeHandler.ondragend,e.ondrop=this.shapeHandler.ondrop,e},ondrop:function(e,t){if(this.isDrop&&e.target&&!t.dragIn){var i,n=e.target,a=e.dragged,o=m.get(n,"seriesIndex"),r=m.get(n,"dataIndex"),s=this.series,l=this.component.legend;if(-1===r){if(m.get(a,"seriesIndex")==o)return t.dragOut=t.dragIn=t.needRefresh=!0,void(this.isDrop=!1);i={value:m.get(a,"value"),name:m.get(a,"name")},this.type===h.CHART_TYPE_PIE&&i.value<0&&(i.value=0);for(var V=!1,U=s[o].data,p=0,c=U.length;c>p;p++)U[p].name===i.name&&"-"===U[p].value&&(s[o].data[p].value=i.value,V=!0);!V&&s[o].data.push(i),l&&l.add(i.name,a.style.color||a.style.strokeColor)}else i=s[o].data[r]||"-",null!=i.value?(s[o].data[r].value="-"!=i.value?d.accAdd(s[o].data[r].value,m.get(a,"value")):m.get(a,"value"),(this.type===h.CHART_TYPE_FUNNEL||this.type===h.CHART_TYPE_PIE)&&(l&&1===l.getRelatedAmount(i.name)&&this.component.legend.del(i.name),i.name+=this.option.nameConnector+m.get(a,"name"),l&&l.add(i.name,a.style.color||a.style.strokeColor))):s[o].data[r]="-"!=i?d.accAdd(s[o].data[r],m.get(a,"value")):m.get(a,"value");t.dragIn=t.dragIn||!0,this.isDrop=!1;var u=this;setTimeout(function(){u.zr.trigger("mousemove",e.event)},300)}},ondragend:function(e,t){if(this.isDragend&&e.target&&!t.dragOut){var i=e.target,n=m.get(i,"seriesIndex"),a=m.get(i,"dataIndex"),o=this.series;if(null!=o[n].data[a].value){o[n].data[a].value="-";var r=o[n].data[a].name,s=this.component.legend;s&&0===s.getRelatedAmount(r)&&s.del(r)}else o[n].data[a]="-";t.dragOut=!0,t.needRefresh=!0,this.isDragend=!1}},onlegendSelected:function(e,t){var i=e.selected;for(var n in this.selectedMap)this.selectedMap[n]!=i[n]&&(t.needRefresh=!0),this.selectedMap[n]=i[n]},_buildPosition:function(){this._symbol=this.option.symbolList,this._sIndex2ShapeMap={},this._sIndex2ColorMap={},this.selectedMap={},this.xMarkMap={};for(var e,t,i,n,a=this.series,o={top:[],bottom:[],left:[],right:[],other:[]},r=0,s=a.length;s>r;r++)a[r].type===this.type&&(a[r]=this.reformOption(a[r]),this.legendHoverLink=a[r].legendHoverLink||this.legendHoverLink,e=a[r].xAxisIndex,t=a[r].yAxisIndex,i=this.component.xAxis.getAxis(e),n=this.component.yAxis.getAxis(t),i.type===h.COMPONENT_TYPE_AXIS_CATEGORY?o[i.getPosition()].push(r):n.type===h.COMPONENT_TYPE_AXIS_CATEGORY?o[n.getPosition()].push(r):o.other.push(r));for(var l in o)o[l].length>0&&this._buildSinglePosition(l,o[l]);this.addShapeList()},_buildSinglePosition:function(e,t){var i=this._mapData(t),n=i.locationMap,a=i.maxDataLength;if(0!==a&&0!==n.length){switch(e){case"bottom":case"top":this._buildHorizontal(t,a,n,this.xMarkMap);break;case"left":case"right":this._buildVertical(t,a,n,this.xMarkMap);break;case"other":this._buildOther(t,a,n,this.xMarkMap)}for(var o=0,r=t.length;r>o;o++)this.buildMark(t[o])}},_mapData:function(e){for(var t,i,n,a,o=this.series,r=0,s={},l="__kener__stack__",m=this.component.legend,V=[],U=0,d=0,p=e.length;p>d;d++){if(t=o[e[d]],n=t.name,this._sIndex2ShapeMap[e[d]]=this._sIndex2ShapeMap[e[d]]||this.query(t,"symbol")||this._symbol[d%this._symbol.length],m){if(this.selectedMap[n]=m.isSelected(n),this._sIndex2ColorMap[e[d]]=m.getColor(n),a=m.getItemShape(n)){var c=a.style;if(this.type==h.CHART_TYPE_LINE)c.iconType="legendLineIcon",c.symbol=this._sIndex2ShapeMap[e[d]];else if(t.itemStyle.normal.barBorderWidth>0){var u=a.highlightStyle;c.brushType="both",c.x+=1,c.y+=1,c.width-=2,c.height-=2,c.strokeColor=u.strokeColor=t.itemStyle.normal.barBorderColor,u.lineWidth=3}m.setItemShape(n,a)}}else this.selectedMap[n]=!0,this._sIndex2ColorMap[e[d]]=this.zr.getColor(e[d]);this.selectedMap[n]&&(i=t.stack||l+e[d],null==s[i]?(s[i]=r,V[r]=[e[d]],r++):V[s[i]].push(e[d])),U=Math.max(U,t.data.length)}return{locationMap:V,maxDataLength:U}},_calculMarkMapXY:function(e,t,i){for(var n=this.series,a=0,o=t.length;o>a;a++)for(var r=0,s=t[a].length;s>r;r++){var l=t[a][r],h="xy"==i?0:"",m=this.component.grid,V=e[l];if("-1"!=i.indexOf("x")){V["counter"+h]>0&&(V["average"+h]=V["sum"+h]/V["counter"+h]);var U=this.component.xAxis.getAxis(n[l].xAxisIndex||0).getCoord(V["average"+h]);V["averageLine"+h]=[[U,m.getYend()],[U,m.getY()]],V["minLine"+h]=[[V["minX"+h],m.getYend()],[V["minX"+h],m.getY()]],V["maxLine"+h]=[[V["maxX"+h],m.getYend()],[V["maxX"+h],m.getY()]],V.isHorizontal=!1}if(h="xy"==i?1:"","-1"!=i.indexOf("y")){V["counter"+h]>0&&(V["average"+h]=V["sum"+h]/V["counter"+h]);var d=this.component.yAxis.getAxis(n[l].yAxisIndex||0).getCoord(V["average"+h]);V["averageLine"+h]=[[m.getX(),d],[m.getXend(),d]],V["minLine"+h]=[[m.getX(),V["minY"+h]],[m.getXend(),V["minY"+h]]],V["maxLine"+h]=[[m.getX(),V["maxY"+h]],[m.getXend(),V["maxY"+h]]],V.isHorizontal=!0}}},addLabel:function(e,t,i,n,a){var o=[i,t],r=this.deepMerge(o,"itemStyle.normal.label"),s=this.deepMerge(o,"itemStyle.emphasis.label"),l=r.textStyle||{},h=s.textStyle||{}; + +if(r.show){var m=e.style;m.text=this._getLabelText(t,i,n,"normal"),m.textPosition=null==r.position?"horizontal"===a?"right":"top":r.position,m.textColor=l.color,m.textFont=this.getFont(l),m.textAlign=l.align,m.textBaseline=l.baseline}if(s.show){var V=e.highlightStyle;V.text=this._getLabelText(t,i,n,"emphasis"),V.textPosition=r.show?e.style.textPosition:null==s.position?"horizontal"===a?"right":"top":s.position,V.textColor=h.color,V.textFont=this.getFont(h),V.textAlign=h.align,V.textBaseline=h.baseline}return e},_getLabelText:function(e,t,i,n){var a=this.deepQuery([t,e],"itemStyle."+n+".label.formatter");a||"emphasis"!==n||(a=this.deepQuery([t,e],"itemStyle.normal.label.formatter"));var o=this.getDataFromOption(t,"-");return a?"function"==typeof a?a.call(this.myChart,{seriesName:e.name,series:e,name:i,value:o,data:t,status:n}):"string"==typeof a?a=a.replace("{a}","{a0}").replace("{b}","{b0}").replace("{c}","{c0}").replace("{a0}",e.name).replace("{b0}",i).replace("{c0}",this.numAddCommas(o)):void 0:o instanceof Array?null!=o[2]?this.numAddCommas(o[2]):o[0]+" , "+o[1]:this.numAddCommas(o)},buildMark:function(e){var t=this.series[e];this.selectedMap[t.name]&&(t.markLine&&this._buildMarkLine(e),t.markPoint&&this._buildMarkPoint(e))},_buildMarkPoint:function(e){for(var t,i,n=(this.markAttachStyle||{})[e],a=this.series[e],o=u.clone(a.markPoint),r=0,s=o.data.length;s>r;r++)t=o.data[r],i=this.getMarkCoord(e,t),t.x=null!=t.x?t.x:i[0],t.y=null!=t.y?t.y:i[1],!t.type||"max"!==t.type&&"min"!==t.type||(t.value=i[3],t.name=t.name||t.type,t.symbolSize=t.symbolSize||y.getTextWidth(i[3],this.getFont())/2+5);for(var l=this._markPoint(e,o),r=0,s=l.length;s>r;r++){var m=l[r];m.zlevel=a.zlevel,m.z=a.z+1;for(var V in n)m[V]=u.clone(n[V]);this.shapeList.push(m)}if(this.type===h.CHART_TYPE_FORCE||this.type===h.CHART_TYPE_CHORD)for(var r=0,s=l.length;s>r;r++)this.zr.addShape(l[r])},_buildMarkLine:function(e){for(var t,i=(this.markAttachStyle||{})[e],n=this.series[e],a=u.clone(n.markLine),o=0,r=a.data.length;r>o;o++){var s=a.data[o];!s.type||"max"!==s.type&&"min"!==s.type&&"average"!==s.type?t=[this.getMarkCoord(e,s[0]),this.getMarkCoord(e,s[1])]:(t=this.getMarkCoord(e,s),a.data[o]=[u.clone(s),{}],a.data[o][0].name=s.name||s.type,a.data[o][0].value="average"!==s.type?t[3]:+t[3].toFixed(null!=a.precision?a.precision:this.deepQuery([this.ecTheme,h],"markLine.precision")),t=t[2],s=[{},{}]),null!=t&&null!=t[0]&&null!=t[1]&&(a.data[o][0].x=null!=s[0].x?s[0].x:t[0][0],a.data[o][0].y=null!=s[0].y?s[0].y:t[0][1],a.data[o][1].x=null!=s[1].x?s[1].x:t[1][0],a.data[o][1].y=null!=s[1].y?s[1].y:t[1][1])}var m=this._markLine(e,a),V=a.large;if(V){var U=new l({style:{shapeList:m}}),d=m[0];if(d){u.merge(U.style,d.style),u.merge(U.highlightStyle={},d.highlightStyle),U.style.brushType="stroke",U.zlevel=n.zlevel,U.z=n.z+1,U.hoverable=!1;for(var p in i)U[p]=u.clone(i[p])}this.shapeList.push(U),this.zr.addShape(U),U._mark="largeLine";var c=a.effect;c.show&&(U.effect=c)}else{for(var o=0,r=m.length;r>o;o++){var y=m[o];y.zlevel=n.zlevel,y.z=n.z+1;for(var p in i)y[p]=u.clone(i[p]);this.shapeList.push(y)}if(this.type===h.CHART_TYPE_FORCE||this.type===h.CHART_TYPE_CHORD)for(var o=0,r=m.length;r>o;o++)this.zr.addShape(m[o])}},_markPoint:function(e,t){var i=this.series[e],n=this.component;u.merge(u.merge(t,u.clone(this.ecTheme.markPoint||{})),u.clone(h.markPoint)),t.name=i.name;var a,o,r,s,l,V,U,d=[],p=t.data,c=n.dataRange,y=n.legend,g=this.zr.getWidth(),b=this.zr.getHeight();if(t.large)a=this.getLargeMarkPointShape(e,t),a._mark="largePoint",a&&d.push(a);else for(var f=0,k=p.length;k>f;f++)null!=p[f].x&&null!=p[f].y&&(r=null!=p[f].value?p[f].value:"",y&&(o=y.getColor(i.name)),c&&(o=isNaN(r)?o:c.getColor(r),s=[p[f],t],l=this.deepQuery(s,"itemStyle.normal.color")||o,V=this.deepQuery(s,"itemStyle.emphasis.color")||l,null==l&&null==V)||(o=null==o?this.zr.getColor(e):o,p[f].tooltip=p[f].tooltip||t.tooltip||{trigger:"item"},p[f].name=null!=p[f].name?p[f].name:"",p[f].value=r,a=this.getSymbolShape(t,e,p[f],f,p[f].name,this.parsePercent(p[f].x,g),this.parsePercent(p[f].y,b),"pin",o,"rgba(0,0,0,0)","horizontal"),a._mark="point",U=this.deepMerge([p[f],t],"effect"),U.show&&(a.effect=U),i.type===h.CHART_TYPE_MAP&&(a._geo=this.getMarkGeo(p[f])),m.pack(a,i,e,p[f],f,p[f].name,r),d.push(a)));return d},_markLine:function(){function e(e,t){e[t]=e[t]instanceof Array?e[t].length>1?e[t]:[e[t][0],e[t][0]]:[e[t],e[t]]}return function(i,n){var a=this.series[i],o=this.component,r=o.dataRange,s=o.legend;u.merge(u.merge(n,u.clone(this.ecTheme.markLine||{})),u.clone(h.markLine));var l=s?s.getColor(a.name):this.zr.getColor(i);e(n,"symbol"),e(n,"symbolSize"),e(n,"symbolRotate");for(var V=n.data,U=[],d=this.zr.getWidth(),p=this.zr.getHeight(),y=0;yy;y++){var K=U[y],I=K.rawEdge||K,g=I.rawData,x=null!=g.value?g.value:"",J=this.getMarkLineShape(n,i,g,y,K.points,W,I.color);J._mark="line";var C=this.deepMerge([g[0],g[1],n],"effect");C.show&&(J.effect=C,J.effect.large=n.large),a.type===h.CHART_TYPE_MAP&&(J._geo=[this.getMarkGeo(g[0]),this.getMarkGeo(g[1])]),m.pack(J,a,i,g[0],y,g[0].name+(""!==g[1].name?" > "+g[1].name:""),x),v.push(J)}return v}}(),getMarkCoord:function(){return[0,0]},getSymbolShape:function(e,t,i,o,r,s,l,h,V,U,d){var p=[i,e],c=this.getDataFromOption(i,"-");h=this.deepQuery(p,"symbol")||h;var u=this.deepQuery(p,"symbolSize");u="function"==typeof u?u(c):u,"number"==typeof u&&(u=[u,u]);var y=this.deepQuery(p,"symbolRotate"),g=this.deepMerge(p,"itemStyle.normal"),b=this.deepMerge(p,"itemStyle.emphasis"),f=null!=g.borderWidth?g.borderWidth:g.lineStyle&&g.lineStyle.width;null==f&&(f=h.match("empty")?2:0);var k=null!=b.borderWidth?b.borderWidth:b.lineStyle&&b.lineStyle.width;null==k&&(k=f+2);var x=this.getItemStyleColor(g.color,t,o,i),_=this.getItemStyleColor(b.color,t,o,i),L=u[0],W=u[1],X=new a({style:{iconType:h.replace("empty","").toLowerCase(),x:s-L,y:l-W,width:2*L,height:2*W,brushType:"both",color:h.match("empty")?U:x||V,strokeColor:g.borderColor||x||V,lineWidth:f},highlightStyle:{color:h.match("empty")?U:_||x||V,strokeColor:b.borderColor||g.borderColor||_||x||V,lineWidth:k},clickable:this.deepQuery(p,"clickable")});return h.match("image")&&(X.style.image=h.replace(new RegExp("^image:\\/\\/"),""),X=new n({style:X.style,highlightStyle:X.highlightStyle,clickable:this.deepQuery(p,"clickable")})),null!=y&&(X.rotation=[y*Math.PI/180,s,l]),h.match("star")&&(X.style.iconType="star",X.style.n=h.replace("empty","").replace("star","")-0||5),"none"===h&&(X.invisible=!0,X.hoverable=!1),X=this.addLabel(X,e,i,r,d),h.match("empty")&&(null==X.style.textColor&&(X.style.textColor=X.style.strokeColor),null==X.highlightStyle.textColor&&(X.highlightStyle.textColor=X.highlightStyle.strokeColor)),m.pack(X,e,t,i,o,r),X._x=s,X._y=l,X._dataIndex=o,X._seriesIndex=t,X},getMarkLineShape:function(e,t,i,n,a,r,l){var h=null!=i[0].value?i[0].value:"-",m=null!=i[1].value?i[1].value:"-",V=[i[0].symbol||e.symbol[0],i[1].symbol||e.symbol[1]],U=[i[0].symbolSize||e.symbolSize[0],i[1].symbolSize||e.symbolSize[1]];U[0]="function"==typeof U[0]?U[0](h):U[0],U[1]="function"==typeof U[1]?U[1](m):U[1];var d=[this.query(i[0],"symbolRotate")||e.symbolRotate[0],this.query(i[1],"symbolRotate")||e.symbolRotate[1]],p=[i[0],i[1],e],c=this.deepMerge(p,"itemStyle.normal");c.color=this.getItemStyleColor(c.color,t,n,i);var u=this.deepMerge(p,"itemStyle.emphasis");u.color=this.getItemStyleColor(u.color,t,n,i);var y=c.lineStyle,g=u.lineStyle,b=y.width;null==b&&(b=c.borderWidth);var f=g.width;null==f&&(f=null!=u.borderWidth?u.borderWidth:b+2);var k=this.deepQuery(p,"smoothness");this.deepQuery(p,"smooth")||(k=0);var x=r?s:o,_=new x({style:{symbol:V,symbolSize:U,symbolRotate:d,brushType:"both",lineType:y.type,shadowColor:y.shadowColor||y.color||c.borderColor||c.color||l,shadowBlur:y.shadowBlur,shadowOffsetX:y.shadowOffsetX,shadowOffsetY:y.shadowOffsetY,color:c.color||l,strokeColor:y.color||c.borderColor||c.color||l,lineWidth:b,symbolBorderColor:c.borderColor||c.color||l,symbolBorder:c.borderWidth},highlightStyle:{shadowColor:g.shadowColor,shadowBlur:g.shadowBlur,shadowOffsetX:g.shadowOffsetX,shadowOffsetY:g.shadowOffsetY,color:u.color||c.color||l,strokeColor:g.color||y.color||u.borderColor||c.borderColor||u.color||c.color||l,lineWidth:f,symbolBorderColor:u.borderColor||c.borderColor||u.color||c.color||l,symbolBorder:null==u.borderWidth?c.borderWidth+2:u.borderWidth},clickable:this.deepQuery(p,"clickable")}),L=_.style;return r?(L.pointList=a,L.smooth=k):(L.xStart=a[0][0],L.yStart=a[0][1],L.xEnd=a[1][0],L.yEnd=a[1][1],L.curveness=k,_.updatePoints(_.style)),_=this.addLabel(_,e,i[0],i[0].name+" : "+i[1].name)},getLargeMarkPointShape:function(e,t){var i,n,a,o,s,l,h=this.series[e],m=this.component,V=t.data,U=m.dataRange,d=m.legend,p=[V[0],t];if(d&&(n=d.getColor(h.name)),!U||(a=null!=V[0].value?V[0].value:"",n=isNaN(a)?n:U.getColor(a),o=this.deepQuery(p,"itemStyle.normal.color")||n,s=this.deepQuery(p,"itemStyle.emphasis.color")||o,null!=o||null!=s)){n=this.deepMerge(p,"itemStyle.normal").color||n;var c=this.deepQuery(p,"symbol")||"circle";c=c.replace("empty","").replace(/\d/g,""),l=this.deepMerge([V[0],t],"effect");var u=window.devicePixelRatio||1;return i=new r({style:{pointList:V,color:n,strokeColor:n,shadowColor:l.shadowColor||n,shadowBlur:(null!=l.shadowBlur?l.shadowBlur:8)*u,size:this.deepQuery(p,"symbolSize"),iconType:c,brushType:"fill",lineWidth:1},draggable:!1,hoverable:!1}),l.show&&(i.effect=l),i}},backupShapeList:function(){this.shapeList&&this.shapeList.length>0?(this.lastShapeList=this.shapeList,this.shapeList=[]):this.lastShapeList=[]},addShapeList:function(){var e,t,i=this.option.animationThreshold/(this.canvasSupported?2:4),n=this.lastShapeList,a=this.shapeList,o=n.length>0,r=o?this.query(this.option,"animationDurationUpdate"):this.query(this.option,"animationDuration"),s=this.query(this.option,"animationEasing"),l={},m={};if(this.option.animation&&!this.option.renderAsImage&&a.lengthV;V++)t=this._getAnimationKey(n[V]),t.match("undefined")?this.zr.delShape(n[V].id):(t+=n[V].type,l[t]?this.zr.delShape(n[V].id):l[t]=n[V]);for(var V=0,U=a.length;U>V;V++)t=this._getAnimationKey(a[V]),t.match("undefined")?this.zr.addShape(a[V]):(t+=a[V].type,m[t]=a[V]);for(t in l)m[t]||this.zr.delShape(l[t].id);for(t in m)l[t]?(this.zr.delShape(l[t].id),this._animateMod(l[t],m[t],r,s,0,o)):(e=this.type!=h.CHART_TYPE_LINE&&this.type!=h.CHART_TYPE_RADAR||0===t.indexOf("icon")?0:r/2,this._animateMod(!1,m[t],r,s,e,o));this.zr.refresh(),this.animationEffect()}else{this.motionlessOnce=!1,this.zr.delShape(n);for(var V=0,U=a.length;U>V;V++)this.zr.addShape(a[V])}},_getAnimationKey:function(e){return this.type!=h.CHART_TYPE_MAP&&this.type!=h.CHART_TYPE_TREEMAP&&this.type!=h.CHART_TYPE_VENN&&this.type!=h.CHART_TYPE_TREE?m.get(e,"seriesIndex")+"_"+m.get(e,"dataIndex")+(e._mark?e._mark:"")+(this.type===h.CHART_TYPE_RADAR?m.get(e,"special"):""):m.get(e,"seriesIndex")+"_"+m.get(e,"dataIndex")+(e._mark?e._mark:"undefined")},_animateMod:function(e,t,i,n,a,o){switch(t.type){case"polyline":case"half-smooth-polygon":V.pointList(this.zr,e,t,i,n);break;case"rectangle":V.rectangle(this.zr,e,t,i,n);break;case"image":case"icon":V.icon(this.zr,e,t,i,n,a);break;case"candle":o?this.zr.addShape(t):V.candle(this.zr,e,t,i,n);break;case"ring":case"sector":case"circle":o?"sector"===t.type?V.sector(this.zr,e,t,i,n):this.zr.addShape(t):V.ring(this.zr,e,t,i+(m.get(t,"dataIndex")||0)%20*100,n);break;case"text":V.text(this.zr,e,t,i,n);break;case"polygon":o?V.pointList(this.zr,e,t,i,n):V.polygon(this.zr,e,t,i,n);break;case"ribbon":V.ribbon(this.zr,e,t,i,n);break;case"gauge-pointer":V.gaugePointer(this.zr,e,t,i,n);break;case"mark-line":V.markline(this.zr,e,t,i,n);break;case"bezier-curve":case"line":V.line(this.zr,e,t,i,n);break;default:this.zr.addShape(t)}},animationMark:function(e,t,i){for(var i=i||this.shapeList,n=0,a=i.length;a>n;n++)i[n]._mark&&this._animateMod(!1,i[n],e,t,0,!0);this.animationEffect(i)},animationEffect:function(e){if(!e&&this.clearEffectShape(),e=e||this.shapeList,null!=e){var t=h.EFFECT_ZLEVEL;this.canvasSupported&&this.zr.modLayer(t,{motionBlur:!0,lastFrameAlpha:this.option.effectBlendAlpha||h.effectBlendAlpha});for(var i,n=0,a=e.length;a>n;n++)i=e[n],i._mark&&i.effect&&i.effect.show&&U[i._mark]&&(U[i._mark](this.zr,this.effectList,i,t),this.effectList[this.effectList.length-1]._mark=i._mark)}},clearEffectShape:function(e){var t=this.effectList;if(this.zr&&t&&t.length>0){e&&this.zr.modLayer(h.EFFECT_ZLEVEL,{motionBlur:!1}),this.zr.delShape(t);for(var i=0;il;l++)this.zr.addShape(this.shapeList[l]);this.zr.refreshNextFrame()}n[i].data=r}},delMark:function(e,t,i){i=i.replace("mark","").replace("large","").toLowerCase();var n=this.series[e];if(this.selectedMap[n.name]){for(var a=!1,o=[this.shapeList,this.effectList],r=2;r--;)for(var s=0,l=o[r].length;l>s;s++)if(o[r][s]._mark==i&&m.get(o[r][s],"seriesIndex")==e&&m.get(o[r][s],"name")==t){this.zr.delShape(o[r][s].id),o[r].splice(s,1),a=!0;break}a&&this.zr.refreshNextFrame()}}},u.inherits(i,p),i}),i("zrender/shape/Circle",["require","./Base","../tool/util"],function(e){"use strict";var t=e("./Base"),i=function(e){t.call(this,e)};return i.prototype={type:"circle",buildPath:function(e,t){e.moveTo(t.x+t.r,t.y),e.arc(t.x,t.y,t.r,0,2*Math.PI,!0)},getRect:function(e){if(e.__rect)return e.__rect;var t;return t="stroke"==e.brushType||"fill"==e.brushType?e.lineWidth||1:0,e.__rect={x:Math.round(e.x-e.r-t/2),y:Math.round(e.y-e.r-t/2),width:2*e.r+t,height:2*e.r+t},e.__rect}},e("../tool/util").inherits(i,t),i}),i("echarts/util/accMath",[],function(){function e(e,t){var i=e.toString(),n=t.toString(),a=0;try{a=n.split(".")[1].length}catch(o){}try{a-=i.split(".")[1].length}catch(o){}return(i.replace(".","")-0)/(n.replace(".","")-0)*Math.pow(10,a)}function t(e,t){var i=e.toString(),n=t.toString(),a=0;try{a+=i.split(".")[1].length}catch(o){}try{a+=n.split(".")[1].length}catch(o){}return(i.replace(".","")-0)*(n.replace(".","")-0)/Math.pow(10,a)}function i(e,t){var i=0,n=0;try{i=e.toString().split(".")[1].length}catch(a){}try{n=t.toString().split(".")[1].length}catch(a){}var o=Math.pow(10,Math.max(i,n));return(Math.round(e*o)+Math.round(t*o))/o}function n(e,t){return i(e,-t)}return{accDiv:e,accMul:t,accAdd:i,accSub:n}}),i("echarts/util/shape/Icon",["require","zrender/tool/util","zrender/shape/Star","zrender/shape/Heart","zrender/shape/Droplet","zrender/shape/Image","zrender/shape/Base"],function(e){function t(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i,n+t.height),e.lineTo(i+5*a,n+14*o),e.lineTo(i+t.width,n+3*o),e.lineTo(i+13*a,n),e.lineTo(i+2*a,n+11*o),e.lineTo(i,n+t.height),e.moveTo(i+6*a,n+10*o),e.lineTo(i+14*a,n+2*o),e.moveTo(i+10*a,n+13*o),e.lineTo(i+t.width,n+13*o),e.moveTo(i+13*a,n+10*o),e.lineTo(i+13*a,n+t.height)}function i(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i,n+t.height),e.lineTo(i+5*a,n+14*o),e.lineTo(i+t.width,n+3*o),e.lineTo(i+13*a,n),e.lineTo(i+2*a,n+11*o),e.lineTo(i,n+t.height),e.moveTo(i+6*a,n+10*o),e.lineTo(i+14*a,n+2*o),e.moveTo(i+10*a,n+13*o),e.lineTo(i+t.width,n+13*o)}function n(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i+4*a,n+15*o),e.lineTo(i+9*a,n+13*o),e.lineTo(i+14*a,n+8*o),e.lineTo(i+11*a,n+5*o),e.lineTo(i+6*a,n+10*o),e.lineTo(i+4*a,n+15*o),e.moveTo(i+5*a,n),e.lineTo(i+11*a,n),e.moveTo(i+5*a,n+o),e.lineTo(i+11*a,n+o),e.moveTo(i,n+2*o),e.lineTo(i+t.width,n+2*o),e.moveTo(i,n+5*o),e.lineTo(i+3*a,n+t.height),e.lineTo(i+13*a,n+t.height),e.lineTo(i+t.width,n+5*o)}function a(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i,n+3*o),e.lineTo(i+6*a,n+3*o),e.moveTo(i+3*a,n),e.lineTo(i+3*a,n+6*o),e.moveTo(i+3*a,n+8*o),e.lineTo(i+3*a,n+t.height),e.lineTo(i+t.width,n+t.height),e.lineTo(i+t.width,n+3*o),e.lineTo(i+8*a,n+3*o)}function o(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i+6*a,n),e.lineTo(i+2*a,n+3*o),e.lineTo(i+6*a,n+6*o),e.moveTo(i+2*a,n+3*o),e.lineTo(i+14*a,n+3*o),e.lineTo(i+14*a,n+11*o),e.moveTo(i+2*a,n+5*o),e.lineTo(i+2*a,n+13*o),e.lineTo(i+14*a,n+13*o),e.moveTo(i+10*a,n+10*o),e.lineTo(i+14*a,n+13*o),e.lineTo(i+10*a,n+t.height)}function r(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16,r=t.width/2;e.lineWidth=1.5,e.arc(i+r,n+r,r-a,0,2*Math.PI/3),e.moveTo(i+3*a,n+t.height),e.lineTo(i+0*a,n+12*o),e.lineTo(i+5*a,n+11*o),e.moveTo(i,n+8*o),e.arc(i+r,n+r,r-a,Math.PI,5*Math.PI/3),e.moveTo(i+13*a,n),e.lineTo(i+t.width,n+4*o),e.lineTo(i+11*a,n+5*o)}function s(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i,n),e.lineTo(i,n+t.height),e.lineTo(i+t.width,n+t.height),e.moveTo(i+2*a,n+14*o),e.lineTo(i+7*a,n+6*o),e.lineTo(i+11*a,n+11*o),e.lineTo(i+15*a,n+2*o)}function l(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i,n),e.lineTo(i,n+t.height),e.lineTo(i+t.width,n+t.height),e.moveTo(i+3*a,n+14*o),e.lineTo(i+3*a,n+6*o),e.lineTo(i+4*a,n+6*o),e.lineTo(i+4*a,n+14*o),e.moveTo(i+7*a,n+14*o),e.lineTo(i+7*a,n+2*o),e.lineTo(i+8*a,n+2*o),e.lineTo(i+8*a,n+14*o),e.moveTo(i+11*a,n+14*o),e.lineTo(i+11*a,n+9*o),e.lineTo(i+12*a,n+9*o),e.lineTo(i+12*a,n+14*o)}function h(e,t){var i=t.x,n=t.y,a=t.width-2,o=t.height-2,r=Math.min(a,o)/2;n+=2,e.moveTo(i+r+3,n+r-3),e.arc(i+r+3,n+r-3,r-1,0,-Math.PI/2,!0),e.lineTo(i+r+3,n+r-3),e.moveTo(i+r,n),e.lineTo(i+r,n+r),e.arc(i+r,n+r,r,-Math.PI/2,2*Math.PI,!0),e.lineTo(i+r,n+r),e.lineWidth=1.5}function m(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;n-=o,e.moveTo(i+1*a,n+2*o),e.lineTo(i+15*a,n+2*o),e.lineTo(i+14*a,n+3*o),e.lineTo(i+2*a,n+3*o),e.moveTo(i+3*a,n+6*o),e.lineTo(i+13*a,n+6*o),e.lineTo(i+12*a,n+7*o),e.lineTo(i+4*a,n+7*o),e.moveTo(i+5*a,n+10*o),e.lineTo(i+11*a,n+10*o),e.lineTo(i+10*a,n+11*o),e.lineTo(i+6*a,n+11*o),e.moveTo(i+7*a,n+14*o),e.lineTo(i+9*a,n+14*o),e.lineTo(i+8*a,n+15*o),e.lineTo(i+7*a,n+15*o)}function V(e,t){var i=t.x,n=t.y,a=t.width,o=t.height,r=a/16,s=o/16,l=2*Math.min(r,s);e.moveTo(i+r+l,n+s+l),e.arc(i+r,n+s,l,Math.PI/4,3*Math.PI),e.lineTo(i+7*r-l,n+6*s-l),e.arc(i+7*r,n+6*s,l,Math.PI/4*5,4*Math.PI),e.arc(i+7*r,n+6*s,l/2,Math.PI/4*5,4*Math.PI),e.moveTo(i+7*r-l/2,n+6*s+l),e.lineTo(i+r+l,n+14*s-l),e.arc(i+r,n+14*s,l,-Math.PI/4,2*Math.PI),e.moveTo(i+7*r+l/2,n+6*s),e.lineTo(i+14*r-l,n+10*s-l/2),e.moveTo(i+16*r,n+10*s),e.arc(i+14*r,n+10*s,l,0,3*Math.PI),e.lineWidth=1.5}function U(e,t){var i=t.x,n=t.y,a=t.width,o=t.height,r=Math.min(a,o)/2;e.moveTo(i+a,n+o/2),e.arc(i+r,n+r,r,0,2*Math.PI),e.arc(i+r,n,r,Math.PI/4,Math.PI/5*4),e.arc(i,n+r,r,-Math.PI/3,Math.PI/3),e.arc(i+a,n+o,r,Math.PI,Math.PI/2*3),e.lineWidth=1.5}function d(e,t){for(var i=t.x,n=t.y,a=t.width,o=t.height,r=Math.round(o/3),s=Math.round((r-2)/2),l=3;l--;)e.rect(i,n+r*l+s,a,2)}function p(e,t){for(var i=t.x,n=t.y,a=t.width,o=t.height,r=Math.round(a/3),s=Math.round((r-2)/2),l=3;l--;)e.rect(i+r*l+s,n,2,o)}function c(e,t){var i=t.x,n=t.y,a=t.width/16;e.moveTo(i+a,n),e.lineTo(i+a,n+t.height),e.lineTo(i+15*a,n+t.height),e.lineTo(i+15*a,n),e.lineTo(i+a,n),e.moveTo(i+3*a,n+3*a),e.lineTo(i+13*a,n+3*a),e.moveTo(i+3*a,n+6*a),e.lineTo(i+13*a,n+6*a),e.moveTo(i+3*a,n+9*a),e.lineTo(i+13*a,n+9*a),e.moveTo(i+3*a,n+12*a),e.lineTo(i+9*a,n+12*a)}function u(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i,n),e.lineTo(i,n+t.height),e.lineTo(i+t.width,n+t.height),e.lineTo(i+t.width,n),e.lineTo(i,n),e.moveTo(i+4*a,n),e.lineTo(i+4*a,n+8*o),e.lineTo(i+12*a,n+8*o),e.lineTo(i+12*a,n),e.moveTo(i+6*a,n+11*o),e.lineTo(i+6*a,n+13*o),e.lineTo(i+10*a,n+13*o),e.lineTo(i+10*a,n+11*o),e.lineTo(i+6*a,n+11*o)}function y(e,t){var i=t.x,n=t.y,a=t.width,o=t.height;e.moveTo(i,n+o/2),e.lineTo(i+a,n+o/2),e.moveTo(i+a/2,n),e.lineTo(i+a/2,n+o)}function g(e,t){var i=t.width/2,n=t.height/2,a=Math.min(i,n);e.moveTo(t.x+i+a,t.y+n),e.arc(t.x+i,t.y+n,a,0,2*Math.PI),e.closePath()}function b(e,t){e.rect(t.x,t.y,t.width,t.height),e.closePath()}function f(e,t){var i=t.width/2,n=t.height/2,a=t.x+i,o=t.y+n,r=Math.min(i,n);e.moveTo(a,o-r),e.lineTo(a+r,o+r),e.lineTo(a-r,o+r),e.lineTo(a,o-r),e.closePath()}function k(e,t){var i=t.width/2,n=t.height/2,a=t.x+i,o=t.y+n,r=Math.min(i,n);e.moveTo(a,o-r),e.lineTo(a+r,o),e.lineTo(a,o+r),e.lineTo(a-r,o),e.lineTo(a,o-r),e.closePath()}function x(e,t){var i=t.x,n=t.y,a=t.width/16;e.moveTo(i+8*a,n),e.lineTo(i+a,n+t.height),e.lineTo(i+8*a,n+t.height/4*3),e.lineTo(i+15*a,n+t.height),e.lineTo(i+8*a,n),e.closePath()}function _(t,i){var n=e("zrender/shape/Star"),a=i.width/2,o=i.height/2;n.prototype.buildPath(t,{x:i.x+a,y:i.y+o,r:Math.min(a,o),n:i.n||5})}function L(t,i){var n=e("zrender/shape/Heart");n.prototype.buildPath(t,{x:i.x+i.width/2,y:i.y+.2*i.height,a:i.width/2,b:.8*i.height})}function W(t,i){var n=e("zrender/shape/Droplet");n.prototype.buildPath(t,{x:i.x+.5*i.width,y:i.y+.5*i.height,a:.5*i.width,b:.8*i.height})}function X(e,t){var i=t.x,n=t.y-t.height/2*1.5,a=t.width/2,o=t.height/2,r=Math.min(a,o);e.arc(i+a,n+o,r,Math.PI/5*4,Math.PI/5),e.lineTo(i+a,n+o+1.5*r),e.closePath()}function v(t,i,n){var a=e("zrender/shape/Image");this._imageShape=this._imageShape||new a({style:{}});for(var o in i)this._imageShape.style[o]=i[o];this._imageShape.brush(t,!1,n)}function w(e){I.call(this,e)}var K=e("zrender/tool/util"),I=e("zrender/shape/Base");return w.prototype={type:"icon",iconLibrary:{mark:t,markUndo:i,markClear:n,dataZoom:a,dataZoomReset:o,restore:r,lineChart:s,barChart:l,pieChart:h,funnelChart:m,forceChart:V,chordChart:U,stackChart:d,tiledChart:p,dataView:c,saveAsImage:u,cross:y,circle:g,rectangle:b,triangle:f,diamond:k,arrow:x,star:_,heart:L,droplet:W,pin:X,image:v},brush:function(t,i,n){var a=i?this.highlightStyle:this.style;a=a||{};var o=a.iconType||this.style.iconType;if("image"===o){var r=e("zrender/shape/Image");r.prototype.brush.call(this,t,i,n)}else{var a=this.beforeBrush(t,i);switch(t.beginPath(),this.buildPath(t,a,n),a.brushType){case"both":t.fill();case"stroke":a.lineWidth>0&&t.stroke();break;default:t.fill()}this.drawText(t,a,this.style),this.afterBrush(t)}},buildPath:function(e,t,i){this.iconLibrary[t.iconType]?this.iconLibrary[t.iconType].call(this,e,t,i):(e.moveTo(t.x,t.y),e.lineTo(t.x+t.width,t.y),e.lineTo(t.x+t.width,t.y+t.height),e.lineTo(t.x,t.y+t.height),e.lineTo(t.x,t.y),e.closePath())},getRect:function(e){return e.__rect?e.__rect:(e.__rect={x:Math.round(e.x),y:Math.round(e.y-("pin"==e.iconType?e.height/2*1.5:0)),width:e.width,height:e.height*("pin"===e.iconType?1.25:1)},e.__rect)},isCover:function(e,t){var i=this.transformCoordToLocal(e,t);e=i[0],t=i[1];var n=this.style.__rect;n||(n=this.style.__rect=this.getRect(this.style));var a=n.height<8||n.width<8?4:0;return e>=n.x-a&&e<=n.x+n.width+a&&t>=n.y-a&&t<=n.y+n.height+a}},K.inherits(w,I),w}),i("echarts/util/shape/MarkLine",["require","zrender/shape/Base","./Icon","zrender/shape/Line","zrender/shape/BezierCurve","zrender/tool/area","zrender/shape/util/dashedLineTo","zrender/tool/util","zrender/tool/curve"],function(e){function t(e){i.call(this,e),this.style.curveness>0&&this.updatePoints(this.style),this.highlightStyle.curveness>0&&this.updatePoints(this.highlightStyle)}var i=e("zrender/shape/Base"),n=e("./Icon"),a=e("zrender/shape/Line"),o=new a({}),r=e("zrender/shape/BezierCurve"),s=new r({}),l=e("zrender/tool/area"),h=e("zrender/shape/util/dashedLineTo"),m=e("zrender/tool/util"),V=e("zrender/tool/curve");return t.prototype={type:"mark-line",brush:function(e,t){var i=this.style;t&&(i=this.getHighlightStyle(i,this.highlightStyle||{})),e.save(),this.setContext(e,i),this.setTransform(e),e.save(),e.beginPath(),this.buildPath(e,i),e.stroke(),e.restore(),this.brushSymbol(e,i,0),this.brushSymbol(e,i,1),this.drawText(e,i,this.style),e.restore()},buildPath:function(e,t){var i=t.lineType||"solid";if(e.moveTo(t.xStart,t.yStart),t.curveness>0){var n=null;switch(i){case"dashed":n=[5,5];break;case"dotted":n=[1,1]}n&&e.setLineDash&&e.setLineDash(n),e.quadraticCurveTo(t.cpX1,t.cpY1,t.xEnd,t.yEnd)}else if("solid"==i)e.lineTo(t.xEnd,t.yEnd);else{var a=(t.lineWidth||1)*("dashed"==t.lineType?5:1);h(e,t.xStart,t.yStart,t.xEnd,t.yEnd,a)}},updatePoints:function(e){var t=e.curveness||0,i=1,n=e.xStart,a=e.yStart,o=e.xEnd,r=e.yEnd,s=(n+o)/2-i*(a-r)*t,l=(a+r)/2-i*(o-n)*t;e.cpX1=s,e.cpY1=l},brushSymbol:function(e,t,i){if("none"!=t.symbol[i]){e.save(),e.beginPath(),e.lineWidth=t.symbolBorder,e.strokeStyle=t.symbolBorderColor;var a=t.symbol[i].replace("empty","").toLowerCase();t.symbol[i].match("empty")&&(e.fillStyle="#fff");var o=t.xStart,r=t.yStart,s=t.xEnd,l=t.yEnd,h=0===i?o:s,m=0===i?r:l,U=t.curveness||0,d=null!=t.symbolRotate[i]?t.symbolRotate[i]-0:0;if(d=d/180*Math.PI,"arrow"==a&&0===d)if(0===U){var p=0===i?-1:1;d=Math.PI/2+Math.atan2(p*(l-r),p*(s-o))}else{var c=t.cpX1,u=t.cpY1,y=V.quadraticDerivativeAt,g=y(o,c,s,i),b=y(r,u,l,i);d=Math.PI/2+Math.atan2(b,g)}e.translate(h,m),0!==d&&e.rotate(d);var f=t.symbolSize[i];n.prototype.buildPath(e,{x:-f,y:-f,width:2*f,height:2*f,iconType:a}),e.closePath(),e.fill(),e.stroke(),e.restore()}},getRect:function(e){return e.curveness>0?s.getRect(e):o.getRect(e),e.__rect},isCover:function(e,t){var i=this.transformCoordToLocal(e,t);return e=i[0],t=i[1],this.isCoverRect(e,t)?this.style.curveness>0?l.isInside(s,this.style,e,t):l.isInside(o,this.style,e,t):!1}},m.inherits(t,i),t}),i("echarts/util/shape/Symbol",["require","zrender/shape/Base","zrender/shape/Polygon","zrender/tool/util","./normalIsCover"],function(e){function t(e){i.call(this,e)}var i=e("zrender/shape/Base"),n=e("zrender/shape/Polygon"),a=new n({}),o=e("zrender/tool/util");return t.prototype={type:"symbol",buildPath:function(e,t){var i=t.pointList,n=i.length;if(0!==n)for(var a,o,r,s,l,h=1e4,m=Math.ceil(n/h),V=i[0]instanceof Array,U=t.size?t.size:2,d=U,p=U/2,c=2*Math.PI,u=0;m>u;u++){e.beginPath(),a=u*h,o=a+h,o=o>n?n:o;for(var y=a;o>y;y++)if(t.random&&(r=t["randomMap"+y%20]/100,d=U*r*r,p=d/2),V?(s=i[y][0],l=i[y][1]):(s=i[y].x,l=i[y].y),3>d)e.rect(s-p,l-p,d,d);else switch(t.iconType){case"circle":e.moveTo(s,l),e.arc(s,l,p,0,c,!0);break;case"diamond":e.moveTo(s,l-p),e.lineTo(s+p/3,l-p/3),e.lineTo(s+p,l),e.lineTo(s+p/3,l+p/3),e.lineTo(s,l+p),e.lineTo(s-p/3,l+p/3),e.lineTo(s-p,l),e.lineTo(s-p/3,l-p/3),e.lineTo(s,l-p);break;default:e.rect(s-p,l-p,d,d)}if(e.closePath(),m-1>u)switch(t.brushType){case"both":e.fill(),t.lineWidth>0&&e.stroke();break;case"stroke":t.lineWidth>0&&e.stroke();break;default:e.fill()}}},getRect:function(e){return e.__rect||a.getRect(e)},isCover:e("./normalIsCover")},o.inherits(t,i),t}),i("zrender/shape/Polyline",["require","./Base","./util/smoothSpline","./util/smoothBezier","./util/dashedLineTo","./Polygon","../tool/util"],function(e){var t=e("./Base"),i=e("./util/smoothSpline"),n=e("./util/smoothBezier"),a=e("./util/dashedLineTo"),o=function(e){this.brushTypeOnly="stroke",this.textPosition="end",t.call(this,e)};return o.prototype={type:"polyline",buildPath:function(e,t){var n=t.pointList;if(!(n.length<2)){var o=Math.min(t.pointList.length,Math.round(t.pointListLength||t.pointList.length));if(t.smooth&&"spline"!==t.smooth){t.controlPointList||this.updateControlPoints(t);var r=t.controlPointList;e.moveTo(n[0][0],n[0][1]);for(var s,l,h,m=0;o-1>m;m++)s=r[2*m],l=r[2*m+1],h=n[m+1],e.bezierCurveTo(s[0],s[1],l[0],l[1],h[0],h[1])}else if("spline"===t.smooth&&(n=i(n),o=n.length),t.lineType&&"solid"!=t.lineType){if("dashed"==t.lineType||"dotted"==t.lineType){var V=(t.lineWidth||1)*("dashed"==t.lineType?5:1);e.moveTo(n[0][0],n[0][1]);for(var m=1;o>m;m++)a(e,n[m-1][0],n[m-1][1],n[m][0],n[m][1],V)}}else{e.moveTo(n[0][0],n[0][1]);for(var m=1;o>m;m++)e.lineTo(n[m][0],n[m][1])}}},updateControlPoints:function(e){e.controlPointList=n(e.pointList,e.smooth,!1,e.smoothConstraint)},getRect:function(t){return e("./Polygon").prototype.getRect(t)}},e("../tool/util").inherits(o,t),o}),i("zrender/shape/ShapeBundle",["require","./Base","../tool/util"],function(e){var t=e("./Base"),i=function(e){t.call(this,e)};return i.prototype={constructor:i,type:"shape-bundle",brush:function(e,t){var i=this.beforeBrush(e,t);e.beginPath();for(var n=0;n0&&e.stroke();break;default:e.fill()}this.drawText(e,i,this.style),this.afterBrush(e)},getRect:function(e){if(e.__rect)return e.__rect;for(var t=1/0,i=-(1/0),n=1/0,a=-(1/0),o=0;oh;h++)o[h]=[r[h][0],l];else for(var m=r[0][0],h=0;s>h;h++)o[h]=[m,r[h][1]];"half-smooth-polygon"==i.type&&(o[s-1]=p.clone(r[s-1]),o[s-2]=p.clone(r[s-2])),t={style:{pointList:o}}}o=t.style.pointList;var V=o.length;i.style.pointList=V==s?o:s>V?o.concat(r.slice(V)):o.slice(0,s),e.addShape(i),i.__animating=!0,e.animate(i.id,"style").when(n,{pointList:r}).during(function(){i.updateControlPoints&&i.updateControlPoints(i.style)}).done(function(){i.__animating=!1}).start(a)}function i(e,t){for(var i=arguments.length,n=2;i>n;n++){var a=arguments[n];e.style[a]=t.style[a]}}function n(e,t,n,a,o){var r=n.style;t||(t={position:n.position,style:{x:r.x,y:"vertical"==n._orient?r.y+r.height:r.y,width:"vertical"==n._orient?r.width:0,height:"vertical"!=n._orient?r.height:0}});var s=r.x,l=r.y,h=r.width,m=r.height,V=[n.position[0],n.position[1]];i(n,t,"x","y","width","height"),n.position=t.position,e.addShape(n),(V[0]!=t.position[0]||V[1]!=t.position[1])&&e.animate(n.id,"").when(a,{position:V}).start(o),n.__animating=!0,e.animate(n.id,"style").when(a,{x:s,y:l,width:h,height:m}).done(function(){n.__animating=!1}).start(o)}function a(e,t,i,n,a){if(!t){var o=i.style.y;t={style:{y:[o[0],o[0],o[0],o[0]]}}}var r=i.style.y;i.style.y=t.style.y,e.addShape(i),i.__animating=!0,e.animate(i.id,"style").when(n,{y:r}).done(function(){i.__animating=!1}).start(a)}function o(e,t,i,n,a){var o=i.style.x,r=i.style.y,s=i.style.r0,l=i.style.r;i.__animating=!0,"r"!=i._animationAdd?(i.style.r0=0,i.style.r=0,i.rotation=[2*Math.PI,o,r],e.addShape(i),e.animate(i.id,"style").when(n,{r0:s,r:l}).done(function(){i.__animating=!1}).start(a),e.animate(i.id,"").when(n,{rotation:[0,o,r]}).start(a)):(i.style.r0=i.style.r,e.addShape(i),e.animate(i.id,"style").when(n,{r0:s}).done(function(){i.__animating=!1}).start(a))}function r(e,t,n,a,o){t||(t="r"!=n._animationAdd?{ +style:{startAngle:n.style.startAngle,endAngle:n.style.startAngle}}:{style:{r0:n.style.r}});var r=n.style.startAngle,s=n.style.endAngle;i(n,t,"startAngle","endAngle"),e.addShape(n),n.__animating=!0,e.animate(n.id,"style").when(a,{startAngle:r,endAngle:s}).done(function(){n.__animating=!1}).start(o)}function s(e,t,n,a,o){t||(t={style:{x:"left"==n.style.textAlign?n.style.x+100:n.style.x-100,y:n.style.y}});var r=n.style.x,s=n.style.y;i(n,t,"x","y"),e.addShape(n),n.__animating=!0,e.animate(n.id,"style").when(a,{x:r,y:s}).done(function(){n.__animating=!1}).start(o)}function l(t,i,n,a,o){var r=e("zrender/shape/Polygon").prototype.getRect(n.style),s=r.x+r.width/2,l=r.y+r.height/2;n.scale=[.1,.1,s,l],t.addShape(n),n.__animating=!0,t.animate(n.id,"").when(a,{scale:[1,1,s,l]}).done(function(){n.__animating=!1}).start(o)}function h(e,t,n,a,o){t||(t={style:{source0:0,source1:n.style.source1>0?360:-360,target0:0,target1:n.style.target1>0?360:-360}});var r=n.style.source0,s=n.style.source1,l=n.style.target0,h=n.style.target1;t.style&&i(n,t,"source0","source1","target0","target1"),e.addShape(n),n.__animating=!0,e.animate(n.id,"style").when(a,{source0:r,source1:s,target0:l,target1:h}).done(function(){n.__animating=!1}).start(o)}function m(e,t,i,n,a){t||(t={style:{angle:i.style.startAngle}});var o=i.style.angle;i.style.angle=t.style.angle,e.addShape(i),i.__animating=!0,e.animate(i.id,"style").when(n,{angle:o}).done(function(){i.__animating=!1}).start(a)}function V(e,t,i,a,o,r){if(i.style._x=i.style.x,i.style._y=i.style.y,i.style._width=i.style.width,i.style._height=i.style.height,t)n(e,t,i,a,o);else{var s=i._x||0,l=i._y||0;i.scale=[.01,.01,s,l],e.addShape(i),i.__animating=!0,e.animate(i.id,"").delay(r).when(a,{scale:[1,1,s,l]}).done(function(){i.__animating=!1}).start(o||"QuinticOut")}}function U(e,t,n,a,o){t||(t={style:{xStart:n.style.xStart,yStart:n.style.yStart,xEnd:n.style.xStart,yEnd:n.style.yStart}});var r=n.style.xStart,s=n.style.xEnd,l=n.style.yStart,h=n.style.yEnd;i(n,t,"xStart","xEnd","yStart","yEnd"),e.addShape(n),n.__animating=!0,e.animate(n.id,"style").when(a,{xStart:r,xEnd:s,yStart:l,yEnd:h}).done(function(){n.__animating=!1}).start(o)}function d(e,t,i,n,a){a=a||"QuinticOut",i.__animating=!0,e.addShape(i);var o=i.style,r=function(){i.__animating=!1},s=o.xStart,l=o.yStart,h=o.xEnd,m=o.yEnd;if(o.curveness>0){i.updatePoints(o);var V={p:0},U=o.cpX1,d=o.cpY1,p=[],u=[],y=c.quadraticSubdivide;e.animation.animate(V).when(n,{p:1}).during(function(){y(s,U,h,V.p,p),y(l,d,m,V.p,u),o.cpX1=p[1],o.cpY1=u[1],o.xEnd=p[2],o.yEnd=u[2],e.modShape(i)}).done(r).start(a)}else e.animate(i.id,"style").when(0,{xEnd:s,yEnd:l}).when(n,{xEnd:h,yEnd:m}).done(r).start(a)}var p=e("zrender/tool/util"),c=e("zrender/tool/curve");return{pointList:t,rectangle:n,candle:a,ring:o,sector:r,text:s,polygon:l,ribbon:h,gaugePointer:m,icon:V,line:U,markline:d}}),i("echarts/util/ecEffect",["require","../util/ecData","zrender/shape/Circle","zrender/shape/Image","zrender/tool/curve","../util/shape/Icon","../util/shape/Symbol","zrender/shape/ShapeBundle","zrender/shape/Polyline","zrender/tool/vector","zrender/tool/env"],function(e){function t(e,t,i,n){var a,r=i.effect,l=r.color||i.style.strokeColor||i.style.color,m=r.shadowColor||l,V=r.scaleSize,U=r.bounceDistance,d="undefined"!=typeof r.shadowBlur?r.shadowBlur:V;"image"!==i.type?(a=new h({zlevel:n,style:{brushType:"stroke",iconType:"droplet"!=i.style.iconType?i.style.iconType:"circle",x:d+1,y:d+1,n:i.style.n,width:i.style._width*V,height:i.style._height*V,lineWidth:1,strokeColor:l,shadowColor:m,shadowBlur:d},draggable:!1,hoverable:!1}),"pin"==i.style.iconType&&(a.style.y+=a.style.height/2*1.5),p&&(a.style.image=e.shapeToImage(a,a.style.width+2*d+2,a.style.height+2*d+2).style.image,a=new s({zlevel:a.zlevel,style:a.style,draggable:!1,hoverable:!1}))):a=new s({zlevel:n,style:i.style,draggable:!1,hoverable:!1}),o.clone(i,a),a.position=i.position,t.push(a),e.addShape(a);var c="image"!==i.type?window.devicePixelRatio||1:1,u=(a.style.width/c-i.style._width)/2;a.style.x=i.style._x-u,a.style.y=i.style._y-u,"pin"==i.style.iconType&&(a.style.y-=i.style.height/2*1.5);var y=100*(r.period+10*Math.random());e.modShape(i.id,{invisible:!0});var g=a.style.x+a.style.width/2/c,b=a.style.y+a.style.height/2/c;"scale"===r.type?(e.modShape(a.id,{scale:[.1,.1,g,b]}),e.animate(a.id,"",r.loop).when(y,{scale:[1,1,g,b]}).done(function(){i.effect.show=!1,e.delShape(a.id)}).start()):e.animate(a.id,"style",r.loop).when(y,{y:a.style.y-U}).when(2*y,{y:a.style.y}).done(function(){i.effect.show=!1,e.delShape(a.id)}).start()}function i(e,t,i,n){var a=i.effect,o=a.color||i.style.strokeColor||i.style.color,r=a.scaleSize,s=a.shadowColor||o,l="undefined"!=typeof a.shadowBlur?a.shadowBlur:2*r,h=window.devicePixelRatio||1,V=new m({zlevel:n,position:i.position,scale:i.scale,style:{pointList:i.style.pointList,iconType:i.style.iconType,color:o,strokeColor:o,shadowColor:s,shadowBlur:l*h,random:!0,brushType:"fill",lineWidth:1,size:i.style.size},draggable:!1,hoverable:!1});t.push(V),e.addShape(V),e.modShape(i.id,{invisible:!0});for(var U=Math.round(100*a.period),d={},p={},c=0;20>c;c++)V.style["randomMap"+c]=0,d={},d["randomMap"+c]=100,p={},p["randomMap"+c]=0,V.style["randomMap"+c]=100*Math.random(),e.animate(V.id,"style",!0).when(U,d).when(2*U,p).when(3*U,d).when(4*U,d).delay(Math.random()*U*c).start()}function n(e,t,i,n,a){var s=i.effect,h=i.style,m=s.color||h.strokeColor||h.color,V=s.shadowColor||h.strokeColor||m,c=h.lineWidth*s.scaleSize,u="undefined"!=typeof s.shadowBlur?s.shadowBlur:c,y=new r({zlevel:n,style:{x:u,y:u,r:c,color:m,shadowColor:V,shadowBlur:u},hoverable:!1}),g=0;if(p&&!a){var n=y.zlevel;y=e.shapeToImage(y,2*(c+u),2*(c+u)),y.zlevel=n,y.hoverable=!1,g=u}a||(o.clone(i,y),y.position=i.position,t.push(y),e.addShape(y));var b=function(){a||(i.effect.show=!1,e.delShape(y.id)),y.effectAnimator=null};if(i instanceof U){for(var f=[0],k=0,x=h.pointList,_=h.controlPointList,L=1;L0){var F=h.cpX1-g,T=h.cpY1-g;y.effectAnimator=e.animation.animate(y,{loop:s.loop}).when(E,{p:1}).during(function(t,i){y.style.x=l.quadraticAt(K,F,J,i),y.style.y=l.quadraticAt(I,T,C,i),a||e.modShape(y)}).done(b).start()}else y.effectAnimator=e.animation.animate(y.style,{loop:s.loop}).when(E,{x:J,y:C}).during(function(){a||e.modShape(y)}).done(b).start();y.effectAnimator.duration=E}return y}function a(e,t,i,a){var o=new V({style:{shapeList:[]},zlevel:a,hoverable:!1}),r=i.style.shapeList,s=i.effect;o.position=i.position;for(var l=0,h=[],m=0;ml&&(l=d.duration),0===m&&(o.style.color=U.style.color,o.style.shadowBlur=U.style.shadowBlur,o.style.shadowColor=U.style.shadowColor),h.push(d)}t.push(o),e.addShape(o);var p=function(){for(var e=0;e=0;o--)t=s.type==i.CHART_TYPE_PIE||s.type==i.CHART_TYPE_FUNNEL?n.get(s.shapeList[o],"name"):(n.get(s.shapeList[o],"series")||{}).name,t!=a||s.shapeList[o].invisible||s.shapeList[o].__animating||s.zr.addHoverShape(s.shapeList[o])},t&&t.bind(i.EVENT.LEGEND_HOVERLINK,this._onlegendhoverlink)}var i=e("../config"),n=e("../util/ecData"),a=e("../util/ecQuery"),o=e("../util/number"),r=e("zrender/tool/util");return t.prototype={canvasSupported:e("zrender/tool/env").canvasSupported,_getZ:function(e){if(null!=this[e])return this[e];var t=this.ecTheme[this.type];return t&&null!=t[e]?t[e]:(t=i[this.type],t&&null!=t[e]?t[e]:0)},getZlevelBase:function(){return this._getZ("zlevel")},getZBase:function(){return this._getZ("z")},reformOption:function(e){return e=r.merge(r.merge(e||{},r.clone(this.ecTheme[this.type]||{})),r.clone(i[this.type]||{})),this.z=e.z,this.zlevel=e.zlevel,e},reformCssArray:function(e){if(!(e instanceof Array))return[e,e,e,e];switch(e.length+""){case"4":return e;case"3":return[e[0],e[1],e[2],e[1]];case"2":return[e[0],e[1],e[0],e[1]];case"1":return[e[0],e[0],e[0],e[0]];case"0":return[0,0,0,0]}},getShapeById:function(e){for(var t=0,i=this.shapeList.length;i>t;t++)if(this.shapeList[t].id===e)return this.shapeList[t];return null},getFont:function(e){var t=this.getTextStyle(r.clone(e));return t.fontStyle+" "+t.fontWeight+" "+t.fontSize+"px "+t.fontFamily},getTextStyle:function(e){return r.merge(r.merge(e||{},this.ecTheme.textStyle),i.textStyle)},getItemStyleColor:function(e,t,i,n){return"function"==typeof e?e.call(this.myChart,{seriesIndex:t,series:this.series[t],dataIndex:i,data:n}):e},getDataFromOption:function(e,t){return null!=e?null!=e.value?e.value:e:t},subPixelOptimize:function(e,t){return e=t%2===1?Math.floor(e)+.5:Math.round(e)},resize:function(){this.refresh&&this.refresh(),this.clearEffectShape&&this.clearEffectShape(!0);var e=this;setTimeout(function(){e.animationEffect&&e.animationEffect()},200)},clear:function(){this.clearEffectShape&&this.clearEffectShape(),this.zr&&this.zr.delShape(this.shapeList),this.shapeList=[]},dispose:function(){this.onbeforDispose&&this.onbeforDispose(),this.clear(),this.shapeList=null,this.effectList=null,this.messageCenter&&this.messageCenter.unbind(i.EVENT.LEGEND_HOVERLINK,this._onlegendhoverlink),this.onafterDispose&&this.onafterDispose()},query:a.query,deepQuery:a.deepQuery,deepMerge:a.deepMerge,parsePercent:o.parsePercent,parseCenter:o.parseCenter,parseRadius:o.parseRadius,numAddCommas:o.addCommas,getPrecision:o.getPrecision},t}),i("echarts/layout/EdgeBundling",["require","../data/KDTree","zrender/tool/vector"],function(e){function t(e,t){e=e.array,t=t.array;var i=t[0]-e[0],n=t[1]-e[1],a=t[2]-e[2],o=t[3]-e[3];return i*i+n*n+a*a+o*o}function i(e){this.points=[e.mp0,e.mp1],this.group=e}function n(e){var t=e.points;t[0][1]0&&t(e[o],n[a-1])||(n[a++]=U(e[o]));return i[0]&&!t(n[0],i[0])&&(n=n.reverse()),n}for(var a=this._iterate(e),o=0;o++f&&(f=W,k=L,V(g,c),V(y,p),b=u)}if(k){s+=f;var X;k.group||(X=new a,o.push(X),X.addEdge(k)),X=k.group,V(X.mp0,y),V(X.mp1,g),X.ink=b,k.group.addEdge(m)}else{var X=new a;o.push(X),V(X.mp0,m.getStartPoint()),V(X.mp1,m.getEndPoint()),X.ink=m.ink,X.addEdge(m)}}}return{groups:o,edges:i,savedInk:s}},_calculateEdgeEdgeInk:function(){var e=[],t=[];return function(i,n,a,o){e[0]=i.getStartPoint(),e[1]=n.getStartPoint(),t[0]=i.getEndPoint(),t[1]=n.getEndPoint(),this._calculateMeetPoints(e,t,a,o);var r=m(e[0],a)+m(a,o)+m(o,t[0])+m(e[1],a)+m(o,t[1]);return r}}(),_calculateGroupEdgeInk:function(e,t,i,n){for(var a=[],o=[],r=0;rl;l++)s.add(e,e,i[l]);s.scale(e,e,1/r),r=n.length;for(var l=0;r>l;l++)s.add(t,t,n[l]);s.scale(t,t,1/r),this._limitTurningAngle(i,e,t,a),this._limitTurningAngle(n,t,e,o)}}(),_limitTurningAngle:function(){var e=l(),t=l(),i=l(),n=l();return function(a,o,r,l){var V=Math.cos(this.maxTurningAngle),U=Math.tan(this.maxTurningAngle);s.sub(e,o,r),s.normalize(e,e),s.copy(l,o);for(var d=0,p=0;py){s.scaleAndAdd(i,o,e,u*y);var g=m(i,c),b=g/U;s.scaleAndAdd(n,i,e,-b);var f=h(n,o);f>d&&(d=f,s.copy(l,n))}}}}()},o}),i("zrender/shape/Star",["require","../tool/math","./Base","../tool/util"],function(e){var t=e("../tool/math"),i=t.sin,n=t.cos,a=Math.PI,o=e("./Base"),r=function(e){o.call(this,e)};return r.prototype={type:"star",buildPath:function(e,t){var o=t.n;if(o&&!(2>o)){var r=t.x,s=t.y,l=t.r,h=t.r0;null==h&&(h=o>4?l*n(2*a/o)/n(a/o):l/3);var m=a/o,V=-a/2,U=r+l*n(V),d=s+l*i(V);V+=m;var p=t.pointList=[];p.push([U,d]);for(var c,u=0,y=2*o-1;y>u;u++)c=u%2===0?h:l,p.push([r+c*n(V),s+c*i(V)]),V+=m;p.push([U,d]),e.moveTo(p[0][0],p[0][1]);for(var u=0;ur;r+=2)e[0]=Math.min(e[0],e[0],o[r]),e[1]=Math.min(e[1],e[1],o[r+1]),i[0]=Math.max(i[0],i[0],o[r]),i[1]=Math.max(i[1],i[1],o[r+1]);break;case"Q":for(var r=0;4>r;r+=2)e[0]=Math.min(e[0],e[0],o[r]),e[1]=Math.min(e[1],e[1],o[r+1]),i[0]=Math.max(i[0],i[0],o[r]),i[1]=Math.max(i[1],i[1],o[r+1]);break;case"A":var s=o[0],l=o[1],h=o[2],m=o[3];e[0]=Math.min(e[0],e[0],s-h),e[1]=Math.min(e[1],e[1],l-m),i[0]=Math.max(i[0],i[0],s+h),i[1]=Math.max(i[1],i[1],l+m)}}return{x:e[0],y:e[1],width:i[0]-e[0],height:i[1]-e[1]}},n.prototype.begin=function(e){return this._ctx=e||null,this.pathCommands.length=0,this},n.prototype.moveTo=function(e,t){return this.pathCommands.push(new i("M",[e,t])),this._ctx&&this._ctx.moveTo(e,t),this},n.prototype.lineTo=function(e,t){return this.pathCommands.push(new i("L",[e,t])),this._ctx&&this._ctx.lineTo(e,t),this},n.prototype.bezierCurveTo=function(e,t,n,a,o,r){return this.pathCommands.push(new i("C",[e,t,n,a,o,r])),this._ctx&&this._ctx.bezierCurveTo(e,t,n,a,o,r),this},n.prototype.quadraticCurveTo=function(e,t,n,a){return this.pathCommands.push(new i("Q",[e,t,n,a])),this._ctx&&this._ctx.quadraticCurveTo(e,t,n,a),this},n.prototype.arc=function(e,t,n,a,o,r){return this.pathCommands.push(new i("A",[e,t,n,n,a,o-a,0,r?0:1])),this._ctx&&this._ctx.arc(e,t,n,a,o,r),this},n.prototype.arcTo=function(e,t,i,n,a){return this._ctx&&this._ctx.arcTo(e,t,i,n,a),this},n.prototype.rect=function(e,t,i,n){return this._ctx&&this._ctx.rect(e,t,i,n),this},n.prototype.closePath=function(){return this.pathCommands.push(new i("z")),this._ctx&&this._ctx.closePath(),this},n.prototype.isEmpty=function(){return 0===this.pathCommands.length},n.PathSegment=i,n}),i("zrender/shape/Line",["require","./Base","./util/dashedLineTo","../tool/util"],function(e){var t=e("./Base"),i=e("./util/dashedLineTo"),n=function(e){this.brushTypeOnly="stroke",this.textPosition="end",t.call(this,e)};return n.prototype={type:"line",buildPath:function(e,t){if(t.lineType&&"solid"!=t.lineType){if("dashed"==t.lineType||"dotted"==t.lineType){var n=(t.lineWidth||1)*("dashed"==t.lineType?5:1);i(e,t.xStart,t.yStart,t.xEnd,t.yEnd,n)}}else e.moveTo(t.xStart,t.yStart),e.lineTo(t.xEnd,t.yEnd)},getRect:function(e){if(e.__rect)return e.__rect;var t=e.lineWidth||1;return e.__rect={x:Math.min(e.xStart,e.xEnd)-t,y:Math.min(e.yStart,e.yEnd)-t,width:Math.abs(e.xStart-e.xEnd)+t,height:Math.abs(e.yStart-e.yEnd)+t},e.__rect}},e("../tool/util").inherits(n,t),n}),i("zrender/shape/BezierCurve",["require","./Base","../tool/util"],function(e){"use strict";var t=e("./Base"),i=function(e){this.brushTypeOnly="stroke",this.textPosition="end",t.call(this,e)};return i.prototype={type:"bezier-curve",buildPath:function(e,t){e.moveTo(t.xStart,t.yStart),"undefined"!=typeof t.cpX2&&"undefined"!=typeof t.cpY2?e.bezierCurveTo(t.cpX1,t.cpY1,t.cpX2,t.cpY2,t.xEnd,t.yEnd):e.quadraticCurveTo(t.cpX1,t.cpY1,t.xEnd,t.yEnd)},getRect:function(e){if(e.__rect)return e.__rect;var t=Math.min(e.xStart,e.xEnd,e.cpX1),i=Math.min(e.yStart,e.yEnd,e.cpY1),n=Math.max(e.xStart,e.xEnd,e.cpX1),a=Math.max(e.yStart,e.yEnd,e.cpY1),o=e.cpX2,r=e.cpY2;"undefined"!=typeof o&&"undefined"!=typeof r&&(t=Math.min(t,o),i=Math.min(i,r),n=Math.max(n,o),a=Math.max(a,r));var s=e.lineWidth||1;return e.__rect={x:t-s,y:i-s,width:n-t+s,height:a-i+s},e.__rect}},e("../tool/util").inherits(i,t),i}),i("zrender/shape/util/dashedLineTo",[],function(){var e=[5,5];return function(t,i,n,a,o,r){if(t.setLineDash)return e[0]=e[1]=r,t.setLineDash(e),t.moveTo(i,n),void t.lineTo(a,o);r="number"!=typeof r?5:r;var s=a-i,l=o-n,h=Math.floor(Math.sqrt(s*s+l*l)/r);s/=h,l/=h;for(var m=!0,V=0;h>V;++V)m?t.moveTo(i,n):t.lineTo(i,n),m=!m,i+=s,n+=l;t.lineTo(a,o)}}),i("zrender/shape/Polygon",["require","./Base","./util/smoothSpline","./util/smoothBezier","./util/dashedLineTo","../tool/util"],function(e){var t=e("./Base"),i=e("./util/smoothSpline"),n=e("./util/smoothBezier"),a=e("./util/dashedLineTo"),o=function(e){t.call(this,e)};return o.prototype={type:"polygon",buildPath:function(e,t){var o=t.pointList;if(!(o.length<2)){if(t.smooth&&"spline"!==t.smooth){var r=n(o,t.smooth,!0,t.smoothConstraint);e.moveTo(o[0][0],o[0][1]);for(var s,l,h,m=o.length,V=0;m>V;V++)s=r[2*V],l=r[2*V+1],h=o[(V+1)%m],e.bezierCurveTo(s[0],s[1],l[0],l[1],h[0],h[1])}else if("spline"===t.smooth&&(o=i(o,!0)),t.lineType&&"solid"!=t.lineType){if("dashed"==t.lineType||"dotted"==t.lineType){var U=t._dashLength||(t.lineWidth||1)*("dashed"==t.lineType?5:1);t._dashLength=U,e.moveTo(o[0][0],o[0][1]);for(var V=1,d=o.length;d>V;V++)a(e,o[V-1][0],o[V-1][1],o[V][0],o[V][1],U);a(e,o[o.length-1][0],o[o.length-1][1],o[0][0],o[0][1],U)}}else{e.moveTo(o[0][0],o[0][1]);for(var V=1,d=o.length;d>V;V++)e.lineTo(o[V][0],o[V][1]);e.lineTo(o[0][0],o[0][1])}e.closePath()}},getRect:function(e){if(e.__rect)return e.__rect;for(var t=Number.MAX_VALUE,i=Number.MIN_VALUE,n=Number.MAX_VALUE,a=Number.MIN_VALUE,o=e.pointList,r=0,s=o.length;s>r;r++)o[r][0]i&&(i=o[r][0]),o[r][1]a&&(a=o[r][1]);var l;return l="stroke"==e.brushType||"fill"==e.brushType?e.lineWidth||1:0,e.__rect={x:Math.round(t-l/2),y:Math.round(n-l/2),width:i-t+l,height:a-n+l},e.__rect}},e("../tool/util").inherits(o,t),o}),i("echarts/util/shape/normalIsCover",[],function(){return function(e,t){var i=this.transformCoordToLocal(e,t);return e=i[0],t=i[1],this.isCoverRect(e,t)}}),i("zrender/shape/util/smoothSpline",["require","../../tool/vector"],function(e){function t(e,t,i,n,a,o,r){var s=.5*(i-e),l=.5*(n-t);return(2*(t-i)+s+l)*r+(-3*(t-i)-2*s-l)*o+s*a+t}var i=e("../../tool/vector");return function(e,n){for(var a=e.length,o=[],r=0,s=1;a>s;s++)r+=i.distance(e[s-1],e[s]);var l=r/5;l=a>l?a:l;for(var s=0;l>s;s++){var h,m,V,U=s/(l-1)*(n?a:a-1),d=Math.floor(U),p=U-d,c=e[d%a];n?(h=e[(d-1+a)%a],m=e[(d+1)%a],V=e[(d+2)%a]):(h=e[0===d?d:d-1],m=e[d>a-2?a-1:d+1],V=e[d>a-3?a-1:d+2]);var u=p*p,y=p*u;o.push([t(h[0],c[0],m[0],V[0],p,u,y),t(h[1],c[1],m[1],V[1],p,u,y)])}return o}}),i("zrender/shape/util/smoothBezier",["require","../../tool/vector"],function(e){var t=e("../../tool/vector");return function(e,i,n,a){var o,r,s,l,h=[],m=[],V=[],U=[],d=!!a;if(d){s=[1/0,1/0],l=[-(1/0),-(1/0)];for(var p=0,c=e.length;c>p;p++)t.min(s,s,e[p]),t.max(l,l,e[p]);t.min(s,s,a[0]),t.max(l,l,a[1])}for(var p=0,c=e.length;c>p;p++){var o,r,u=e[p];if(n)o=e[p?p-1:c-1],r=e[(p+1)%c];else{if(0===p||p===c-1){h.push(t.clone(e[p]));continue}o=e[p-1],r=e[p+1]}t.sub(m,r,o),t.scale(m,m,i);var y=t.distance(u,o),g=t.distance(u,r),b=y+g;0!==b&&(y/=b,g/=b),t.scale(V,m,-y),t.scale(U,m,g);var f=t.add([],u,V),k=t.add([],u,U);d&&(t.max(f,f,s),t.min(f,f,l),t.max(k,k,s),t.min(k,k,l)),h.push(f),h.push(k)}return n&&h.push(t.clone(h.shift())),h}}),i("echarts/util/ecQuery",["require","zrender/tool/util"],function(e){function t(e,t){if("undefined"!=typeof e){if(!t)return e;t=t.split(".");for(var i=t.length,n=0;i>n;){if(e=e[t[n]],"undefined"==typeof e)return;n++}return e}}function i(e,i){for(var n,a=0,o=e.length;o>a;a++)if(n=t(e[a],i),"undefined"!=typeof n)return n}function n(e,i){for(var n,o=e.length;o--;){var r=t(e[o],i);"undefined"!=typeof r&&("undefined"==typeof n?n=a.clone(r):a.merge(n,r,!0))}return n}var a=e("zrender/tool/util");return{query:t,deepQuery:i,deepMerge:n}}),i("echarts/util/number",[],function(){function e(e){return e.replace(/^\s+/,"").replace(/\s+$/,"")}function t(t,i){return"string"==typeof t?e(t).match(/%$/)?parseFloat(t)/100*i:parseFloat(t):t}function i(e,i){return[t(i[0],e.getWidth()),t(i[1],e.getHeight())]}function n(e,i){i instanceof Array||(i=[0,i]);var n=Math.min(e.getWidth(),e.getHeight())/2;return[t(i[0],n),t(i[1],n)]}function a(e){return isNaN(e)?"-":(e=(e+"").split("."),e[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g,"$1,")+(e.length>1?"."+e[1]:""))}function o(e){for(var t=1,i=0;Math.round(e*t)/t!==e;)t*=10,i++;return i}return{parsePercent:t,parseCenter:i,parseRadius:n,addCommas:a,getPrecision:o}}),i("echarts/data/KDTree",["require","./quickSelect"],function(e){function t(e,t){this.left=null,this.right=null,this.axis=e,this.data=t}var i=e("./quickSelect"),n=function(e,t){e.length&&(t||(t=e[0].array.length),this.dimension=t,this.root=this._buildTree(e,0,e.length-1,0),this._stack=[],this._nearstNList=[])};return n.prototype._buildTree=function(e,n,a,o){if(n>a)return null;var r=Math.floor((n+a)/2);r=i(e,n,a,r,function(e,t){return e.array[o]-t.array[o]});var s=e[r],l=new t(o,s);return o=(o+1)%this.dimension,a>n&&(l.left=this._buildTree(e,n,r-1,o),l.right=this._buildTree(e,r+1,a,o)),l},n.prototype.nearest=function(e,t){var i=this.root,n=this._stack,a=0,o=1/0,r=null;for(i.data!==e&&(o=t(i.data,e),r=i),e.array[i.axis]s,h=!1;s*=s,o>s&&(s=t(i.data,e),o>s&&i.data!==e&&(o=s,r=i),h=!0),l?(h&&i.right&&(n[a++]=i.right),i.left&&(n[a++]=i.left)):(h&&i.left&&(n[a++]=i.left),i.right&&(n[a++]=i.right))}return r.data},n.prototype._addNearest=function(e,t,i){for(var n=this._nearstNList,a=e-1;a>0&&!(t>=n[a-1].dist);a--)n[a].dist=n[a-1].dist,n[a].node=n[a-1].node;n[a].dist=t,n[a].node=i},n.prototype.nearestN=function(e,t,i,n){if(0>=t)return n.length=0,n;for(var a=this.root,o=this._stack,r=0,s=this._nearstNList,l=0;t>l;l++)s[l]||(s[l]={}),s[l].dist=0,s[l].node=null;var h=i(a.data,e),m=0;for(a.data!==e&&(m++,this._addNearest(m,h,a)),e.array[a.axis]h,U=!1;h*=h,(t>m||hm||hm&&m++,this._addNearest(m,h,a)),U=!0),V?(U&&a.right&&(o[r++]=a.right),a.left&&(o[r++]=a.left)):(U&&a.left&&(o[r++]=a.left),a.right&&(o[r++]=a.right))}for(var l=0;m>l;l++)n[l]=s[l].node.data;return n.length=m,n},n}),i("echarts/data/quickSelect",["require"],function(){function e(e,t){return e-t}function t(e,t,i){var n=e[t];e[t]=e[i],e[i]=n}function i(e,i,n,a,o){for(var r=i;n>i;){var r=Math.round((n+i)/2),s=e[r];t(e,r,n),r=i;for(var l=i;n-1>=l;l++)o(s,e[l])>=0&&(t(e,l,r),r++);if(t(e,n,r),r===a)return r;a>r?i=r+1:n=r-1}return i}function n(t,n,a,o,r){return arguments.length<=3&&(o=n,r=2==arguments.length?e:a,n=0,a=t.length-1),i(t,n,a,o,r)}return n}),i("echarts/component/dataView",["require","./base","../config","zrender/tool/util","../component"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.dom=o.dom,this._tDom=document.createElement("div"),this._textArea=document.createElement("textArea"),this._buttonRefresh=document.createElement("button"),this._buttonRefresh.setAttribute("type","button"),this._buttonClose=document.createElement("button"),this._buttonClose.setAttribute("type","button"),this._hasShow=!1,this._zrHeight=n.getHeight(),this._zrWidth=n.getWidth(),this._tDom.className="echarts-dataview",this.hide(),this.dom.firstChild.appendChild(this._tDom),window.addEventListener?(this._tDom.addEventListener("click",this._stop),this._tDom.addEventListener("mousewheel",this._stop),this._tDom.addEventListener("mousemove",this._stop),this._tDom.addEventListener("mousedown",this._stop),this._tDom.addEventListener("mouseup",this._stop),this._tDom.addEventListener("touchstart",this._stop),this._tDom.addEventListener("touchmove",this._stop),this._tDom.addEventListener("touchend",this._stop)):(this._tDom.attachEvent("onclick",this._stop),this._tDom.attachEvent("onmousewheel",this._stop),this._tDom.attachEvent("onmousemove",this._stop),this._tDom.attachEvent("onmousedown",this._stop),this._tDom.attachEvent("onmouseup",this._stop))}var i=e("./base"),n=e("../config"),a=e("zrender/tool/util");return t.prototype={type:n.COMPONENT_TYPE_DATAVIEW,_lang:["Data View","close","refresh"],_gCssText:"position:absolute;display:block;overflow:hidden;transition:height 0.8s,background-color 1s;-moz-transition:height 0.8s,background-color 1s;-webkit-transition:height 0.8s,background-color 1s;-o-transition:height 0.8s,background-color 1s;z-index:1;left:0;top:0;",hide:function(){this._sizeCssText="width:"+this._zrWidth+"px;height:0px;background-color:#f0ffff;",this._tDom.style.cssText=this._gCssText+this._sizeCssText},show:function(e){this._hasShow=!0;var t=this.query(this.option,"toolbox.feature.dataView.lang")||this._lang;this.option=e,this._tDom.innerHTML='

'+(t[0]||this._lang[0])+"

";var i=this.query(this.option,"toolbox.feature.dataView.optionToContent");"function"!=typeof i?this._textArea.value=this._optionToContent():(this._textArea=document.createElement("div"),this._textArea.innerHTML=i(this.option)),this._textArea.style.cssText="display:block;margin:0 0 8px 0;padding:4px 6px;overflow:auto;width:100%;height:"+(this._zrHeight-100)+"px;",this._tDom.appendChild(this._textArea),this._buttonClose.style.cssText="float:right;padding:1px 6px;",this._buttonClose.innerHTML=t[1]||this._lang[1];var n=this;this._buttonClose.onclick=function(){n.hide()},this._tDom.appendChild(this._buttonClose),this.query(this.option,"toolbox.feature.dataView.readOnly")===!1?(this._buttonRefresh.style.cssText="float:right;margin-right:10px;padding:1px 6px;",this._buttonRefresh.innerHTML=t[2]||this._lang[2],this._buttonRefresh.onclick=function(){n._save()},this._textArea.readOnly=!1,this._textArea.style.cursor="default"):(this._buttonRefresh.style.cssText="display:none", +this._textArea.readOnly=!0,this._textArea.style.cursor="text"),this._tDom.appendChild(this._buttonRefresh),this._sizeCssText="width:"+this._zrWidth+"px;height:"+this._zrHeight+"px;background-color:#fff;",this._tDom.style.cssText=this._gCssText+this._sizeCssText},_optionToContent:function(){var e,t,i,a,o,r,s=[],l="";if(this.option.xAxis)for(s=this.option.xAxis instanceof Array?this.option.xAxis:[this.option.xAxis],e=0,a=s.length;a>e;e++)if("category"==(s[e].type||"category")){for(r=[],t=0,i=s[e].data.length;i>t;t++)r.push(this.getDataFromOption(s[e].data[t]));l+=r.join(", ")+"\n\n"}if(this.option.yAxis)for(s=this.option.yAxis instanceof Array?this.option.yAxis:[this.option.yAxis],e=0,a=s.length;a>e;e++)if("category"==s[e].type){for(r=[],t=0,i=s[e].data.length;i>t;t++)r.push(this.getDataFromOption(s[e].data[t]));l+=r.join(", ")+"\n\n"}var h,m=this.option.series;for(e=0,a=m.length;a>e;e++){for(r=[],t=0,i=m[e].data.length;i>t;t++)o=m[e].data[t],h=m[e].type==n.CHART_TYPE_PIE||m[e].type==n.CHART_TYPE_MAP?(o.name||"-")+":":"",m[e].type==n.CHART_TYPE_SCATTER&&(o=this.getDataFromOption(o).join(", ")),r.push(h+this.getDataFromOption(o));l+=(m[e].name||"-")+" : \n",l+=r.join(m[e].type==n.CHART_TYPE_SCATTER?"\n":", "),l+="\n\n"}return l},_save:function(){var e=this.query(this.option,"toolbox.feature.dataView.contentToOption");if("function"!=typeof e){for(var t=this._textArea.value.split("\n"),i=[],a=0,o=t.length;o>a;a++)t[a]=this._trim(t[a]),""!==t[a]&&i.push(t[a]);this._contentToOption(i)}else e(this._textArea,this.option);this.hide();var r=this;setTimeout(function(){r.messageCenter&&r.messageCenter.dispatch(n.EVENT.DATA_VIEW_CHANGED,null,{option:r.option},r.myChart)},r.canvasSupported?800:100)},_contentToOption:function(e){var t,i,a,o,r,s,l,h=[],m=0;if(this.option.xAxis)for(h=this.option.xAxis instanceof Array?this.option.xAxis:[this.option.xAxis],t=0,o=h.length;o>t;t++)if("category"==(h[t].type||"category")){for(s=e[m].split(","),i=0,a=h[t].data.length;a>i;i++)l=this._trim(s[i]||""),r=h[t].data[i],"undefined"!=typeof h[t].data[i].value?h[t].data[i].value=l:h[t].data[i]=l;m++}if(this.option.yAxis)for(h=this.option.yAxis instanceof Array?this.option.yAxis:[this.option.yAxis],t=0,o=h.length;o>t;t++)if("category"==h[t].type){for(s=e[m].split(","),i=0,a=h[t].data.length;a>i;i++)l=this._trim(s[i]||""),r=h[t].data[i],"undefined"!=typeof h[t].data[i].value?h[t].data[i].value=l:h[t].data[i]=l;m++}var V=this.option.series;for(t=0,o=V.length;o>t;t++)if(m++,V[t].type==n.CHART_TYPE_SCATTER)for(var i=0,a=V[t].data.length;a>i;i++)s=e[m],l=s.replace(" ","").split(","),"undefined"!=typeof V[t].data[i].value?V[t].data[i].value=l:V[t].data[i]=l,m++;else{s=e[m].split(",");for(var i=0,a=V[t].data.length;a>i;i++)l=(s[i]||"").replace(/.*:/,""),l=this._trim(l),l="-"!=l&&""!==l?l-0:"-","undefined"!=typeof V[t].data[i].value?V[t].data[i].value=l:V[t].data[i]=l;m++}},_trim:function(e){var t=new RegExp("(^[\\s\\t\\xa0\\u3000]+)|([\\u3000\\xa0\\s\\t]+$)","g");return e.replace(t,"")},_stop:function(e){e=e||window.event,e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},resize:function(){this._zrHeight=this.zr.getHeight(),this._zrWidth=this.zr.getWidth(),this._tDom.offsetHeight>10&&(this._sizeCssText="width:"+this._zrWidth+"px;height:"+this._zrHeight+"px;background-color:#fff;",this._tDom.style.cssText=this._gCssText+this._sizeCssText,this._textArea.style.cssText="display:block;margin:0 0 8px 0;padding:4px 6px;overflow:auto;width:100%;height:"+(this._zrHeight-100)+"px;")},dispose:function(){window.removeEventListener?(this._tDom.removeEventListener("click",this._stop),this._tDom.removeEventListener("mousewheel",this._stop),this._tDom.removeEventListener("mousemove",this._stop),this._tDom.removeEventListener("mousedown",this._stop),this._tDom.removeEventListener("mouseup",this._stop),this._tDom.removeEventListener("touchstart",this._stop),this._tDom.removeEventListener("touchmove",this._stop),this._tDom.removeEventListener("touchend",this._stop)):(this._tDom.detachEvent("onclick",this._stop),this._tDom.detachEvent("onmousewheel",this._stop),this._tDom.detachEvent("onmousemove",this._stop),this._tDom.detachEvent("onmousedown",this._stop),this._tDom.detachEvent("onmouseup",this._stop)),this._buttonRefresh.onclick=null,this._buttonClose.onclick=null,this._hasShow&&(this._tDom.removeChild(this._textArea),this._tDom.removeChild(this._buttonRefresh),this._tDom.removeChild(this._buttonClose)),this._textArea=null,this._buttonRefresh=null,this._buttonClose=null,this.dom.firstChild.removeChild(this._tDom),this._tDom=null}},a.inherits(t,i),e("../component").define("dataView",t),t}),i("echarts/util/shape/Cross",["require","zrender/shape/Base","zrender/shape/Line","zrender/tool/util","./normalIsCover"],function(e){function t(e){i.call(this,e)}var i=e("zrender/shape/Base"),n=e("zrender/shape/Line"),a=e("zrender/tool/util");return t.prototype={type:"cross",buildPath:function(e,t){var i=t.rect;t.xStart=i.x,t.xEnd=i.x+i.width,t.yStart=t.yEnd=t.y,n.prototype.buildPath(e,t),t.xStart=t.xEnd=t.x,t.yStart=i.y,t.yEnd=i.y+i.height,n.prototype.buildPath(e,t)},getRect:function(e){return e.rect},isCover:e("./normalIsCover")},a.inherits(t,i),t}),i("zrender/shape/Sector",["require","../tool/math","../tool/computeBoundingBox","../tool/vector","./Base","../tool/util"],function(e){var t=e("../tool/math"),i=e("../tool/computeBoundingBox"),n=e("../tool/vector"),a=e("./Base"),o=n.create(),r=n.create(),s=n.create(),l=n.create(),h=function(e){a.call(this,e)};return h.prototype={type:"sector",buildPath:function(e,i){var n=i.x,a=i.y,o=i.r0||0,r=i.r,s=i.startAngle,l=i.endAngle,h=i.clockWise||!1;s=t.degreeToRadian(s),l=t.degreeToRadian(l),h||(s=-s,l=-l);var m=t.cos(s),V=t.sin(s);e.moveTo(m*o+n,V*o+a),e.lineTo(m*r+n,V*r+a),e.arc(n,a,r,s,l,!h),e.lineTo(t.cos(l)*o+n,t.sin(l)*o+a),0!==o&&e.arc(n,a,o,l,s,h),e.closePath()},getRect:function(e){if(e.__rect)return e.__rect;var a=e.x,h=e.y,m=e.r0||0,V=e.r,U=t.degreeToRadian(e.startAngle),d=t.degreeToRadian(e.endAngle),p=e.clockWise;return p||(U=-U,d=-d),m>1?i.arc(a,h,m,U,d,!p,o,s):(o[0]=s[0]=a,o[1]=s[1]=h),i.arc(a,h,V,U,d,!p,r,l),n.min(o,o,r),n.max(s,s,l),e.__rect={x:o[0],y:o[1],width:s[0]-o[0],height:s[1]-o[1]},e.__rect}},e("../tool/util").inherits(h,a),h}),i("echarts/util/shape/Candle",["require","zrender/shape/Base","zrender/tool/util","./normalIsCover"],function(e){function t(e){i.call(this,e)}var i=e("zrender/shape/Base"),n=e("zrender/tool/util");return t.prototype={type:"candle",_numberOrder:function(e,t){return t-e},buildPath:function(e,t){var i=n.clone(t.y).sort(this._numberOrder);e.moveTo(t.x,i[3]),e.lineTo(t.x,i[2]),e.moveTo(t.x-t.width/2,i[2]),e.rect(t.x-t.width/2,i[2],t.width,i[1]-i[2]),e.moveTo(t.x,i[1]),e.lineTo(t.x,i[0])},getRect:function(e){if(!e.__rect){var t=0;("stroke"==e.brushType||"fill"==e.brushType)&&(t=e.lineWidth||1);var i=n.clone(e.y).sort(this._numberOrder);e.__rect={x:Math.round(e.x-e.width/2-t/2),y:Math.round(i[3]-t/2),width:e.width+t,height:i[0]-i[3]+t}}return e.__rect},isCover:e("./normalIsCover")},n.inherits(t,i),t}),i("zrender/tool/computeBoundingBox",["require","./vector","./curve"],function(e){function t(e,t,i){if(0!==e.length){for(var n=e[0][0],a=e[0][0],o=e[0][1],r=e[0][1],s=1;sa&&(a=l[0]),l[1]r&&(r=l[1])}t[0]=n,t[1]=o,i[0]=a,i[1]=r}}function i(e,t,i,n,a,r){var s=[];o.cubicExtrema(e[0],t[0],i[0],n[0],s);for(var l=0;l=2*Math.PI)return m[0]=e-i,m[1]=t-i,V[0]=e+i,void(V[1]=t+i);if(r[0]=Math.cos(n)*i+e,r[1]=Math.sin(n)*i+t,s[0]=Math.cos(o)*i+e,s[1]=Math.sin(o)*i+t,a.min(m,r,s),a.max(V,r,s),n%=2*Math.PI,0>n&&(n+=2*Math.PI),o%=2*Math.PI,0>o&&(o+=2*Math.PI),n>o&&!h?o+=2*Math.PI:o>n&&h&&(n+=2*Math.PI),h){var U=o;o=n,n=U}for(var d=0;o>d;d+=Math.PI/2)d>n&&(l[0]=Math.cos(d)*i+e,l[1]=Math.sin(d)*i+t,a.min(m,l,m),a.max(V,l,V))};return t.cubeBezier=i,t.quadraticBezier=n,t.arc=h,t}),i("echarts/util/shape/Chain",["require","zrender/shape/Base","./Icon","zrender/shape/util/dashedLineTo","zrender/tool/util","zrender/tool/matrix"],function(e){function t(e){i.call(this,e)}var i=e("zrender/shape/Base"),n=e("./Icon"),a=e("zrender/shape/util/dashedLineTo"),o=e("zrender/tool/util"),r=e("zrender/tool/matrix");return t.prototype={type:"chain",brush:function(e,t){var i=this.style;t&&(i=this.getHighlightStyle(i,this.highlightStyle||{})),e.save(),this.setContext(e,i),this.setTransform(e),e.save(),e.beginPath(),this.buildLinePath(e,i),e.stroke(),e.restore(),this.brushSymbol(e,i),e.restore()},buildLinePath:function(e,t){var i=t.x,n=t.y+5,o=t.width,r=t.height/2-10;if(e.moveTo(i,n),e.lineTo(i,n+r),e.moveTo(i+o,n),e.lineTo(i+o,n+r),e.moveTo(i,n+r/2),t.lineType&&"solid"!=t.lineType){if("dashed"==t.lineType||"dotted"==t.lineType){var s=(t.lineWidth||1)*("dashed"==t.lineType?5:1);a(e,i,n+r/2,i+o,n+r/2,s)}}else e.lineTo(i+o,n+r/2)},brushSymbol:function(e,t){var i=t.y+t.height/4;e.save();for(var a,o=t.chainPoint,r=0,s=o.length;s>r;r++){if(a=o[r],"none"!=a.symbol){e.beginPath();var l=a.symbolSize;n.prototype.buildPath(e,{iconType:a.symbol,x:a.x-l,y:i-l,width:2*l,height:2*l,n:a.n}),e.fillStyle=a.isEmpty?"#fff":t.strokeColor,e.closePath(),e.fill(),e.stroke()}a.showLabel&&(e.font=a.textFont,e.fillStyle=a.textColor,e.textAlign=a.textAlign,e.textBaseline=a.textBaseline,a.rotation?(e.save(),this._updateTextTransform(e,a.rotation),e.fillText(a.name,a.textX,a.textY),e.restore()):e.fillText(a.name,a.textX,a.textY))}e.restore()},_updateTextTransform:function(e,t){var i=r.create();if(r.identity(i),0!==t[0]){var n=t[1]||0,a=t[2]||0;(n||a)&&r.translate(i,i,[-n,-a]),r.rotate(i,i,t[0]),(n||a)&&r.translate(i,i,[n,a])}e.transform.apply(e,i)},isCover:function(e,t){var i=this.style;return e>=i.x&&e<=i.x+i.width&&t>=i.y&&t<=i.y+i.height?!0:!1}},o.inherits(t,i),t}),i("zrender/shape/Ring",["require","./Base","../tool/util"],function(e){var t=e("./Base"),i=function(e){t.call(this,e)};return i.prototype={type:"ring",buildPath:function(e,t){e.arc(t.x,t.y,t.r,0,2*Math.PI,!1),e.moveTo(t.x+t.r0,t.y),e.arc(t.x,t.y,t.r0,0,2*Math.PI,!0)},getRect:function(e){if(e.__rect)return e.__rect;var t;return t="stroke"==e.brushType||"fill"==e.brushType?e.lineWidth||1:0,e.__rect={x:Math.round(e.x-e.r-t/2),y:Math.round(e.y-e.r-t/2),width:2*e.r+t,height:2*e.r+t},e.__rect}},e("../tool/util").inherits(i,t),i}),i("echarts/component/axis",["require","./base","zrender/shape/Line","../config","../util/ecData","zrender/tool/util","zrender/tool/color","./categoryAxis","./valueAxis","../component"],function(e){function t(e,t,n,a,o,r){i.call(this,e,t,n,a,o),this.axisType=r,this._axisList=[],this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Line"),a=e("../config"),o=e("../util/ecData"),r=e("zrender/tool/util"),s=e("zrender/tool/color");return t.prototype={type:a.COMPONENT_TYPE_AXIS,axisBase:{_buildAxisLine:function(){var e=this.option.axisLine.lineStyle.width,t=e/2,i={_axisShape:"axisLine",zlevel:this.getZlevelBase(),z:this.getZBase()+3,hoverable:!1},a=this.grid;switch(this.option.position){case"left":i.style={xStart:a.getX()-t,yStart:a.getYend(),xEnd:a.getX()-t,yEnd:a.getY(),lineCap:"round"};break;case"right":i.style={xStart:a.getXend()+t,yStart:a.getYend(),xEnd:a.getXend()+t,yEnd:a.getY(),lineCap:"round"};break;case"bottom":i.style={xStart:a.getX(),yStart:a.getYend()+t,xEnd:a.getXend(),yEnd:a.getYend()+t,lineCap:"round"};break;case"top":i.style={xStart:a.getX(),yStart:a.getY()-t,xEnd:a.getXend(),yEnd:a.getY()-t,lineCap:"round"}}var o=i.style;""!==this.option.name&&(o.text=this.option.name,o.textPosition=this.option.nameLocation,o.textFont=this.getFont(this.option.nameTextStyle),this.option.nameTextStyle.align&&(o.textAlign=this.option.nameTextStyle.align),this.option.nameTextStyle.baseline&&(o.textBaseline=this.option.nameTextStyle.baseline),this.option.nameTextStyle.color&&(o.textColor=this.option.nameTextStyle.color)),o.strokeColor=this.option.axisLine.lineStyle.color,o.lineWidth=e,this.isHorizontal()?o.yStart=o.yEnd=this.subPixelOptimize(o.yEnd,e):o.xStart=o.xEnd=this.subPixelOptimize(o.xEnd,e),o.lineType=this.option.axisLine.lineStyle.type,i=new n(i),this.shapeList.push(i)},_axisLabelClickable:function(e,t){return e?(o.pack(t,void 0,-1,void 0,-1,t.style.text),t.hoverable=!0,t.clickable=!0,t.highlightStyle={color:s.lift(t.style.color,1),brushType:"fill"},t):t},refixAxisShape:function(e,t){if(this.option.axisLine.onZero){var i;if(this.isHorizontal()&&null!=t)for(var n=0,a=this.shapeList.length;a>n;n++)"axisLine"===this.shapeList[n]._axisShape?(this.shapeList[n].style.yStart=this.shapeList[n].style.yEnd=this.subPixelOptimize(t,this.shapeList[n].stylelineWidth),this.zr.modShape(this.shapeList[n].id)):"axisTick"===this.shapeList[n]._axisShape&&(i=this.shapeList[n].style.yEnd-this.shapeList[n].style.yStart,this.shapeList[n].style.yStart=t-i,this.shapeList[n].style.yEnd=t,this.zr.modShape(this.shapeList[n].id));if(!this.isHorizontal()&&null!=e)for(var n=0,a=this.shapeList.length;a>n;n++)"axisLine"===this.shapeList[n]._axisShape?(this.shapeList[n].style.xStart=this.shapeList[n].style.xEnd=this.subPixelOptimize(e,this.shapeList[n].stylelineWidth),this.zr.modShape(this.shapeList[n].id)):"axisTick"===this.shapeList[n]._axisShape&&(i=this.shapeList[n].style.xEnd-this.shapeList[n].style.xStart,this.shapeList[n].style.xStart=e,this.shapeList[n].style.xEnd=e+i,this.zr.modShape(this.shapeList[n].id))}},getPosition:function(){return this.option.position},isHorizontal:function(){return"bottom"===this.option.position||"top"===this.option.position}},reformOption:function(e){if(!e||e instanceof Array&&0===e.length?e=[{type:a.COMPONENT_TYPE_AXIS_VALUE}]:e instanceof Array||(e=[e]),e.length>2&&(e=[e[0],e[1]]),"xAxis"===this.axisType){(!e[0].position||"bottom"!=e[0].position&&"top"!=e[0].position)&&(e[0].position="bottom"),e.length>1&&(e[1].position="bottom"===e[0].position?"top":"bottom");for(var t=0,i=e.length;i>t;t++)e[t].type=e[t].type||"category",e[t].xAxisIndex=t,e[t].yAxisIndex=-1}else{(!e[0].position||"left"!=e[0].position&&"right"!=e[0].position)&&(e[0].position="left"),e.length>1&&(e[1].position="left"===e[0].position?"right":"left");for(var t=0,i=e.length;i>t;t++)e[t].type=e[t].type||"value",e[t].xAxisIndex=-1,e[t].yAxisIndex=t}return e},refresh:function(t){var i;t&&(this.option=t,"xAxis"===this.axisType?(this.option.xAxis=this.reformOption(t.xAxis),i=this.option.xAxis):(this.option.yAxis=this.reformOption(t.yAxis),i=this.option.yAxis),this.series=t.series);for(var n=e("./categoryAxis"),a=e("./valueAxis"),o=Math.max(i&&i.length||0,this._axisList.length),r=0;o>r;r++)!this._axisList[r]||!t||i[r]&&this._axisList[r].type==i[r].type||(this._axisList[r].dispose&&this._axisList[r].dispose(),this._axisList[r]=!1),this._axisList[r]?this._axisList[r].refresh&&this._axisList[r].refresh(i?i[r]:!1,this.series):i&&i[r]&&(this._axisList[r]="category"===i[r].type?new n(this.ecTheme,this.messageCenter,this.zr,i[r],this.myChart,this.axisBase):new a(this.ecTheme,this.messageCenter,this.zr,i[r],this.myChart,this.axisBase,this.series))},getAxis:function(e){return this._axisList[e]},getAxisCount:function(){return this._axisList.length},clear:function(){for(var e=0,t=this._axisList.length;t>e;e++)this._axisList[e].dispose&&this._axisList[e].dispose();this._axisList=[]}},r.inherits(t,i),e("../component").define("axis",t),t}),i("echarts/component/grid",["require","./base","zrender/shape/Rectangle","../config","zrender/tool/util","../component"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Rectangle"),a=e("../config");a.grid={zlevel:0,z:0,x:80,y:60,x2:80,y2:60,backgroundColor:"rgba(0,0,0,0)",borderWidth:1,borderColor:"#ccc"};var o=e("zrender/tool/util");return t.prototype={type:a.COMPONENT_TYPE_GRID,getX:function(){return this._x},getY:function(){return this._y},getWidth:function(){return this._width},getHeight:function(){return this._height},getXend:function(){return this._x+this._width},getYend:function(){return this._y+this._height},getArea:function(){return{x:this._x,y:this._y,width:this._width,height:this._height}},getBbox:function(){return[[this._x,this._y],[this.getXend(),this.getYend()]]},refixAxisShape:function(e){for(var t,i,n,o=e.xAxis._axisList.concat(e.yAxis?e.yAxis._axisList:[]),r=o.length;r--;)n=o[r],n.type==a.COMPONENT_TYPE_AXIS_VALUE&&n._min<0&&n._max>=0&&(n.isHorizontal()?t=n.getCoord(0):i=n.getCoord(0));if("undefined"!=typeof t||"undefined"!=typeof i)for(r=o.length;r--;)o[r].refixAxisShape(t,i)},refresh:function(e){if(e||this._zrWidth!=this.zr.getWidth()||this._zrHeight!=this.zr.getHeight()){this.clear(),this.option=e||this.option,this.option.grid=this.reformOption(this.option.grid);var t=this.option.grid;this._zrWidth=this.zr.getWidth(),this._zrHeight=this.zr.getHeight(),this._x=this.parsePercent(t.x,this._zrWidth),this._y=this.parsePercent(t.y,this._zrHeight);var i=this.parsePercent(t.x2,this._zrWidth),a=this.parsePercent(t.y2,this._zrHeight);this._width="undefined"==typeof t.width?this._zrWidth-this._x-i:this.parsePercent(t.width,this._zrWidth),this._width=this._width<=0?10:this._width,this._height="undefined"==typeof t.height?this._zrHeight-this._y-a:this.parsePercent(t.height,this._zrHeight),this._height=this._height<=0?10:this._height,this._x=this.subPixelOptimize(this._x,t.borderWidth),this._y=this.subPixelOptimize(this._y,t.borderWidth),this.shapeList.push(new n({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._x,y:this._y,width:this._width,height:this._height,brushType:t.borderWidth>0?"both":"fill",color:t.backgroundColor,strokeColor:t.borderColor,lineWidth:t.borderWidth}})),this.zr.addShape(this.shapeList[0])}}},o.inherits(t,i),e("../component").define("grid",t),t}),i("echarts/component/dataZoom",["require","./base","zrender/shape/Rectangle","zrender/shape/Polygon","../util/shape/Icon","../config","../util/date","zrender/tool/util","../component"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o);var r=this;r._ondrift=function(e,t){return r.__ondrift(this,e,t)},r._ondragend=function(){return r.__ondragend()},this._fillerSize=30,this._isSilence=!1,this._zoom={},this.option.dataZoom=this.reformOption(this.option.dataZoom),this.zoomOption=this.option.dataZoom,this._handleSize=this.zoomOption.handleSize,this.myChart.canvasSupported||(this.zoomOption.realtime=!1),this._location=this._getLocation(),this._zoom=this._getZoom(),this._backupData(),this.option.dataZoom.show&&this._buildShape(),this._syncData()}var i=e("./base"),n=e("zrender/shape/Rectangle"),a=e("zrender/shape/Polygon"),o=e("../util/shape/Icon"),r=e("../config");r.dataZoom={zlevel:0,z:4,show:!1,orient:"horizontal",backgroundColor:"rgba(0,0,0,0)",dataBackgroundColor:"#eee",fillerColor:"rgba(144,197,237,0.2)",handleColor:"rgba(70,130,180,0.8)",handleSize:8,showDetail:!0,realtime:!0};var s=e("../util/date"),l=e("zrender/tool/util");return t.prototype={type:r.COMPONENT_TYPE_DATAZOOM,_buildShape:function(){this._buildBackground(),this._buildFiller(),this._buildHandle(),this._buildFrame();for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e]);this._syncFrameShape()},_getLocation:function(){var e,t,i,n,a=this.component.grid;return"horizontal"==this.zoomOption.orient?(i=this.zoomOption.width||a.getWidth(),n=this.zoomOption.height||this._fillerSize,e=null!=this.zoomOption.x?this.zoomOption.x:a.getX(),t=null!=this.zoomOption.y?this.zoomOption.y:this.zr.getHeight()-n-2):(i=this.zoomOption.width||this._fillerSize,n=this.zoomOption.height||a.getHeight(),e=null!=this.zoomOption.x?this.zoomOption.x:2,t=null!=this.zoomOption.y?this.zoomOption.y:a.getY()),{x:e,y:t,width:i,height:n}},_getZoom:function(){var e=this.option.series,t=this.option.xAxis;!t||t instanceof Array||(t=[t],this.option.xAxis=t);var i=this.option.yAxis;!i||i instanceof Array||(i=[i],this.option.yAxis=i);var n,a,o=[],s=this.zoomOption.xAxisIndex;if(t&&null==s){n=[];for(var l=0,h=t.length;h>l;l++)("category"==t[l].type||null==t[l].type)&&n.push(l)}else n=s instanceof Array?s:null!=s?[s]:[];if(s=this.zoomOption.yAxisIndex,i&&null==s){a=[];for(var l=0,h=i.length;h>l;l++)"category"==i[l].type&&a.push(l)}else a=s instanceof Array?s:null!=s?[s]:[];for(var m,l=0,h=e.length;h>l;l++)if(m=e[l],m.type==r.CHART_TYPE_LINE||m.type==r.CHART_TYPE_BAR||m.type==r.CHART_TYPE_SCATTER||m.type==r.CHART_TYPE_K){for(var V=0,U=n.length;U>V;V++)if(n[V]==(m.xAxisIndex||0)){o.push(l);break}for(var V=0,U=a.length;U>V;V++)if(a[V]==(m.yAxisIndex||0)){o.push(l);break}null==this.zoomOption.xAxisIndex&&null==this.zoomOption.yAxisIndex&&m.data&&this.getDataFromOption(m.data[0])instanceof Array&&(m.type==r.CHART_TYPE_SCATTER||m.type==r.CHART_TYPE_LINE||m.type==r.CHART_TYPE_BAR)&&o.push(l)}var d=null!=this._zoom.start?this._zoom.start:null!=this.zoomOption.start?this.zoomOption.start:0,p=null!=this._zoom.end?this._zoom.end:null!=this.zoomOption.end?this.zoomOption.end:100;d>p&&(d+=p,p=d-p,d-=p);var c=Math.round((p-d)/100*("horizontal"==this.zoomOption.orient?this._location.width:this._location.height));return{start:d,end:p,start2:0,end2:100,size:c,xAxisIndex:n,yAxisIndex:a,seriesIndex:o,scatterMap:this._zoom.scatterMap||{}}},_backupData:function(){this._originalData={xAxis:{},yAxis:{},series:{}};for(var e=this.option.xAxis,t=this._zoom.xAxisIndex,i=0,n=t.length;n>i;i++)this._originalData.xAxis[t[i]]=e[t[i]].data;for(var a=this.option.yAxis,o=this._zoom.yAxisIndex,i=0,n=o.length;n>i;i++)this._originalData.yAxis[o[i]]=a[o[i]].data;for(var s,l=this.option.series,h=this._zoom.seriesIndex,i=0,n=h.length;n>i;i++)s=l[h[i]],this._originalData.series[h[i]]=s.data,s.data&&this.getDataFromOption(s.data[0])instanceof Array&&(s.type==r.CHART_TYPE_SCATTER||s.type==r.CHART_TYPE_LINE||s.type==r.CHART_TYPE_BAR)&&(this._backupScale(),this._calculScatterMap(h[i]))},_calculScatterMap:function(t){this._zoom.scatterMap=this._zoom.scatterMap||{},this._zoom.scatterMap[t]=this._zoom.scatterMap[t]||{};var i=e("../component"),n=i.get("axis"),a=l.clone(this.option.xAxis);"category"==a[0].type&&(a[0].type="value"),a[1]&&"category"==a[1].type&&(a[1].type="value");var o=new n(this.ecTheme,null,!1,{xAxis:a,series:this.option.series},this,"xAxis"),r=this.option.series[t].xAxisIndex||0;this._zoom.scatterMap[t].x=o.getAxis(r).getExtremum(),o.dispose(),a=l.clone(this.option.yAxis),"category"==a[0].type&&(a[0].type="value"),a[1]&&"category"==a[1].type&&(a[1].type="value"),o=new n(this.ecTheme,null,!1,{yAxis:a,series:this.option.series},this,"yAxis"),r=this.option.series[t].yAxisIndex||0,this._zoom.scatterMap[t].y=o.getAxis(r).getExtremum(),o.dispose()},_buildBackground:function(){var e=this._location.width,t=this._location.height;this.shapeList.push(new n({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._location.x,y:this._location.y,width:e,height:t,color:this.zoomOption.backgroundColor}}));for(var i=0,o=this._originalData.xAxis,s=this._zoom.xAxisIndex,l=0,h=s.length;h>l;l++)i=Math.max(i,o[s[l]].length);for(var m=this._originalData.yAxis,V=this._zoom.yAxisIndex,l=0,h=V.length;h>l;l++)i=Math.max(i,m[V[l]].length);for(var U,d=this._zoom.seriesIndex[0],p=this._originalData.series[d],c=Number.MIN_VALUE,u=Number.MAX_VALUE,l=0,h=p.length;h>l;l++)U=this.getDataFromOption(p[l],0),this.option.series[d].type==r.CHART_TYPE_K&&(U=U[1]),isNaN(U)&&(U=0),c=Math.max(c,U),u=Math.min(u,U);var y=c-u,g=[],b=e/(i-(i>1?1:0)),f=t/(i-(i>1?1:0)),k=1;"horizontal"==this.zoomOption.orient&&1>b?k=Math.floor(3*i/e):"vertical"==this.zoomOption.orient&&1>f&&(k=Math.floor(3*i/t));for(var l=0,h=i;h>l;l+=k)U=this.getDataFromOption(p[l],0),this.option.series[d].type==r.CHART_TYPE_K&&(U=U[1]),isNaN(U)&&(U=0),g.push("horizontal"==this.zoomOption.orient?[this._location.x+b*l,this._location.y+t-1-Math.round((U-u)/y*(t-10))]:[this._location.x+1+Math.round((U-u)/y*(e-10)),this._location.y+f*(h-l-1)]);"horizontal"==this.zoomOption.orient?(g.push([this._location.x+e,this._location.y+t]),g.push([this._location.x,this._location.y+t])):(g.push([this._location.x,this._location.y]),g.push([this._location.x,this._location.y+t])),this.shapeList.push(new a({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{pointList:g,color:this.zoomOption.dataBackgroundColor},hoverable:!1}))},_buildFiller:function(){this._fillerShae={zlevel:this.getZlevelBase(),z:this.getZBase(),draggable:!0,ondrift:this._ondrift,ondragend:this._ondragend,_type:"filler"},this._fillerShae.style="horizontal"==this.zoomOption.orient?{x:this._location.x+Math.round(this._zoom.start/100*this._location.width)+this._handleSize,y:this._location.y,width:this._zoom.size-2*this._handleSize,height:this._location.height,color:this.zoomOption.fillerColor,text:":::",textPosition:"inside"}:{x:this._location.x,y:this._location.y+Math.round(this._zoom.start/100*this._location.height)+this._handleSize,width:this._location.width,height:this._zoom.size-2*this._handleSize,color:this.zoomOption.fillerColor,text:"::",textPosition:"inside"},this._fillerShae.highlightStyle={brushType:"fill",color:"rgba(0,0,0,0)"},this._fillerShae=new n(this._fillerShae),this.shapeList.push(this._fillerShae)},_buildHandle:function(){var e=this.zoomOption.showDetail?this._getDetail():{start:"",end:""};this._startShape={zlevel:this.getZlevelBase(),z:this.getZBase(),draggable:!0,style:{iconType:"rectangle",x:this._location.x,y:this._location.y,width:this._handleSize,height:this._handleSize,color:this.zoomOption.handleColor,text:"=",textPosition:"inside"},highlightStyle:{text:e.start,brushType:"fill",textPosition:"left"},ondrift:this._ondrift,ondragend:this._ondragend},"horizontal"==this.zoomOption.orient?(this._startShape.style.height=this._location.height,this._endShape=l.clone(this._startShape),this._startShape.style.x=this._fillerShae.style.x-this._handleSize,this._endShape.style.x=this._fillerShae.style.x+this._fillerShae.style.width,this._endShape.highlightStyle.text=e.end,this._endShape.highlightStyle.textPosition="right"):(this._startShape.style.width=this._location.width,this._endShape=l.clone(this._startShape),this._startShape.style.y=this._fillerShae.style.y+this._fillerShae.style.height,this._startShape.highlightStyle.textPosition="bottom",this._endShape.style.y=this._fillerShae.style.y-this._handleSize,this._endShape.highlightStyle.text=e.end,this._endShape.highlightStyle.textPosition="top"),this._startShape=new o(this._startShape),this._endShape=new o(this._endShape),this.shapeList.push(this._startShape),this.shapeList.push(this._endShape)},_buildFrame:function(){var e=this.subPixelOptimize(this._location.x,1),t=this.subPixelOptimize(this._location.y,1);this._startFrameShape={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:e,y:t,width:this._location.width-(e>this._location.x?1:0),height:this._location.height-(t>this._location.y?1:0),lineWidth:1,brushType:"stroke",strokeColor:this.zoomOption.handleColor}},this._endFrameShape=l.clone(this._startFrameShape),this._startFrameShape=new n(this._startFrameShape),this._endFrameShape=new n(this._endFrameShape),this.shapeList.push(this._startFrameShape),this.shapeList.push(this._endFrameShape)},_syncHandleShape:function(){"horizontal"==this.zoomOption.orient?(this._startShape.style.x=this._fillerShae.style.x-this._handleSize,this._endShape.style.x=this._fillerShae.style.x+this._fillerShae.style.width,this._zoom.start=(this._startShape.style.x-this._location.x)/this._location.width*100,this._zoom.end=(this._endShape.style.x+this._handleSize-this._location.x)/this._location.width*100):(this._startShape.style.y=this._fillerShae.style.y+this._fillerShae.style.height,this._endShape.style.y=this._fillerShae.style.y-this._handleSize,this._zoom.start=(this._location.y+this._location.height-this._startShape.style.y)/this._location.height*100,this._zoom.end=(this._location.y+this._location.height-this._endShape.style.y-this._handleSize)/this._location.height*100),this.zr.modShape(this._startShape.id),this.zr.modShape(this._endShape.id),this._syncFrameShape(),this.zr.refreshNextFrame()},_syncFillerShape:function(){var e,t;"horizontal"==this.zoomOption.orient?(e=this._startShape.style.x,t=this._endShape.style.x,this._fillerShae.style.x=Math.min(e,t)+this._handleSize,this._fillerShae.style.width=Math.abs(e-t)-this._handleSize,this._zoom.start=(Math.min(e,t)-this._location.x)/this._location.width*100,this._zoom.end=(Math.max(e,t)+this._handleSize-this._location.x)/this._location.width*100):(e=this._startShape.style.y,t=this._endShape.style.y,this._fillerShae.style.y=Math.min(e,t)+this._handleSize,this._fillerShae.style.height=Math.abs(e-t)-this._handleSize,this._zoom.start=(this._location.y+this._location.height-Math.max(e,t))/this._location.height*100,this._zoom.end=(this._location.y+this._location.height-Math.min(e,t)-this._handleSize)/this._location.height*100),this.zr.modShape(this._fillerShae.id),this._syncFrameShape(),this.zr.refreshNextFrame()},_syncFrameShape:function(){"horizontal"==this.zoomOption.orient?(this._startFrameShape.style.width=this._fillerShae.style.x-this._location.x,this._endFrameShape.style.x=this._fillerShae.style.x+this._fillerShae.style.width,this._endFrameShape.style.width=this._location.x+this._location.width-this._endFrameShape.style.x):(this._startFrameShape.style.y=this._fillerShae.style.y+this._fillerShae.style.height,this._startFrameShape.style.height=this._location.y+this._location.height-this._startFrameShape.style.y,this._endFrameShape.style.height=this._fillerShae.style.y-this._location.y),this.zr.modShape(this._startFrameShape.id),this.zr.modShape(this._endFrameShape.id)},_syncShape:function(){this.zoomOption.show&&("horizontal"==this.zoomOption.orient?(this._startShape.style.x=this._location.x+this._zoom.start/100*this._location.width,this._endShape.style.x=this._location.x+this._zoom.end/100*this._location.width-this._handleSize,this._fillerShae.style.x=this._startShape.style.x+this._handleSize,this._fillerShae.style.width=this._endShape.style.x-this._startShape.style.x-this._handleSize):(this._startShape.style.y=this._location.y+this._location.height-this._zoom.start/100*this._location.height,this._endShape.style.y=this._location.y+this._location.height-this._zoom.end/100*this._location.height-this._handleSize,this._fillerShae.style.y=this._endShape.style.y+this._handleSize,this._fillerShae.style.height=this._startShape.style.y-this._endShape.style.y-this._handleSize),this.zr.modShape(this._startShape.id),this.zr.modShape(this._endShape.id),this.zr.modShape(this._fillerShae.id),this._syncFrameShape(),this.zr.refresh())},_syncData:function(e){var t,i,n,a,o;for(var s in this._originalData){t=this._originalData[s];for(var l in t)o=t[l],null!=o&&(a=o.length,i=Math.floor(this._zoom.start/100*a),n=Math.ceil(this._zoom.end/100*a),this.getDataFromOption(o[0])instanceof Array&&this.option[s][l].type!=r.CHART_TYPE_K?(this._setScale(),this.option[s][l].data=this._synScatterData(l,o)):this.option[s][l].data=o.slice(i,n))}this._isSilence||!this.zoomOption.realtime&&!e||this.messageCenter.dispatch(r.EVENT.DATA_ZOOM,null,{zoom:this._zoom},this.myChart)},_synScatterData:function(e,t){if(0===this._zoom.start&&100==this._zoom.end&&0===this._zoom.start2&&100==this._zoom.end2)return t;var i,n,a,o,r,s=[],l=this._zoom.scatterMap[e]; + +"horizontal"==this.zoomOption.orient?(i=l.x.max-l.x.min,n=this._zoom.start/100*i+l.x.min,a=this._zoom.end/100*i+l.x.min,i=l.y.max-l.y.min,o=this._zoom.start2/100*i+l.y.min,r=this._zoom.end2/100*i+l.y.min):(i=l.x.max-l.x.min,n=this._zoom.start2/100*i+l.x.min,a=this._zoom.end2/100*i+l.x.min,i=l.y.max-l.y.min,o=this._zoom.start/100*i+l.y.min,r=this._zoom.end/100*i+l.y.min);var h;(h=l.x.dataMappingMethods)&&(n=h.coord2Value(n),a=h.coord2Value(a)),(h=l.y.dataMappingMethods)&&(o=h.coord2Value(o),r=h.coord2Value(r));for(var m,V=0,U=t.length;U>V;V++)m=t[V].value||t[V],m[0]>=n&&m[0]<=a&&m[1]>=o&&m[1]<=r&&s.push(t[V]);return s},_setScale:function(){var e=0!==this._zoom.start||100!==this._zoom.end||0!==this._zoom.start2||100!==this._zoom.end2,t={xAxis:this.option.xAxis,yAxis:this.option.yAxis};for(var i in t)for(var n=0,a=t[i].length;a>n;n++)t[i][n].scale=e||t[i][n]._scale},_backupScale:function(){var e={xAxis:this.option.xAxis,yAxis:this.option.yAxis};for(var t in e)for(var i=0,n=e[t].length;n>i;i++)e[t][i]._scale=e[t][i].scale},_getDetail:function(){for(var e=["xAxis","yAxis"],t=0,i=e.length;i>t;t++){var n=this._originalData[e[t]];for(var a in n){var o=n[a];if(null!=o){var r=o.length,l=Math.floor(this._zoom.start/100*r),h=Math.ceil(this._zoom.end/100*r);return h-=h>0?1:0,{start:this.getDataFromOption(o[l]),end:this.getDataFromOption(o[h])}}}}e="horizontal"==this.zoomOption.orient?"xAxis":"yAxis";var m=this._zoom.seriesIndex[0],V=this.option.series[m][e+"Index"]||0,U=this.option[e][V].type,d=this._zoom.scatterMap[m][e.charAt(0)].min,p=this._zoom.scatterMap[m][e.charAt(0)].max,c=p-d;if("value"==U)return{start:d+c*this._zoom.start/100,end:d+c*this._zoom.end/100};if("time"==U){p=d+c*this._zoom.end/100,d+=c*this._zoom.start/100;var u=s.getAutoFormatter(d,p).formatter;return{start:s.format(u,d),end:s.format(u,p)}}return{start:"",end:""}},__ondrift:function(e,t,i){this.zoomOption.zoomLock&&(e=this._fillerShae);var n="filler"==e._type?this._handleSize:0;if("horizontal"==this.zoomOption.orient?e.style.x+t-n<=this._location.x?e.style.x=this._location.x+n:e.style.x+t+e.style.width+n>=this._location.x+this._location.width?e.style.x=this._location.x+this._location.width-e.style.width-n:e.style.x+=t:e.style.y+i-n<=this._location.y?e.style.y=this._location.y+n:e.style.y+i+e.style.height+n>=this._location.y+this._location.height?e.style.y=this._location.y+this._location.height-e.style.height-n:e.style.y+=i,"filler"==e._type?this._syncHandleShape():this._syncFillerShape(),this.zoomOption.realtime&&this._syncData(),this.zoomOption.showDetail){var a=this._getDetail();this._startShape.style.text=this._startShape.highlightStyle.text=a.start,this._endShape.style.text=this._endShape.highlightStyle.text=a.end,this._startShape.style.textPosition=this._startShape.highlightStyle.textPosition,this._endShape.style.textPosition=this._endShape.highlightStyle.textPosition}return!0},__ondragend:function(){this.zoomOption.showDetail&&(this._startShape.style.text=this._endShape.style.text="=",this._startShape.style.textPosition=this._endShape.style.textPosition="inside",this.zr.modShape(this._startShape.id),this.zr.modShape(this._endShape.id),this.zr.refreshNextFrame()),this.isDragend=!0},ondragend:function(e,t){this.isDragend&&e.target&&(!this.zoomOption.realtime&&this._syncData(),t.dragOut=!0,t.dragIn=!0,this._isSilence||this.zoomOption.realtime||this.messageCenter.dispatch(r.EVENT.DATA_ZOOM,null,{zoom:this._zoom},this.myChart),t.needRefresh=!1,this.isDragend=!1)},ondataZoom:function(e,t){t.needRefresh=!0},absoluteZoom:function(e){this._zoom.start=e.start,this._zoom.end=e.end,this._zoom.start2=e.start2,this._zoom.end2=e.end2,this._syncShape(),this._syncData(!0)},rectZoom:function(e){if(!e)return this._zoom.start=this._zoom.start2=0,this._zoom.end=this._zoom.end2=100,this._syncShape(),this._syncData(!0),this._zoom;var t=this.component.grid.getArea(),i={x:e.x,y:e.y,width:e.width,height:e.height};if(i.width<0&&(i.x+=i.width,i.width=-i.width),i.height<0&&(i.y+=i.height,i.height=-i.height),i.x>t.x+t.width||i.y>t.y+t.height)return!1;i.xt.x+t.width&&(i.width=t.x+t.width-i.x),i.y+i.height>t.y+t.height&&(i.height=t.y+t.height-i.y);var n,a=(i.x-t.x)/t.width,o=1-(i.x+i.width-t.x)/t.width,r=1-(i.y+i.height-t.y)/t.height,s=(i.y-t.y)/t.height;return"horizontal"==this.zoomOption.orient?(n=this._zoom.end-this._zoom.start,this._zoom.start+=n*a,this._zoom.end-=n*o,n=this._zoom.end2-this._zoom.start2,this._zoom.start2+=n*r,this._zoom.end2-=n*s):(n=this._zoom.end-this._zoom.start,this._zoom.start+=n*r,this._zoom.end-=n*s,n=this._zoom.end2-this._zoom.start2,this._zoom.start2+=n*a,this._zoom.end2-=n*o),this._syncShape(),this._syncData(!0),this._zoom},syncBackupData:function(e){for(var t,i,n=this._originalData.series,a=e.series,o=0,r=a.length;r>o;o++){i=a[o].data||a[o].eventList,t=n[o]?Math.floor(this._zoom.start/100*n[o].length):0;for(var s=0,l=i.length;l>s;s++)n[o]&&(n[o][s+t]=i[s])}},syncOption:function(e){this.silence(!0),this.option=e,this.option.dataZoom=this.reformOption(this.option.dataZoom),this.zoomOption=this.option.dataZoom,this.myChart.canvasSupported||(this.zoomOption.realtime=!1),this.clear(),this._location=this._getLocation(),this._zoom=this._getZoom(),this._backupData(),this.option.dataZoom&&this.option.dataZoom.show&&this._buildShape(),this._syncData(),this.silence(!1)},silence:function(e){this._isSilence=e},getRealDataIndex:function(e,t){if(!this._originalData||0===this._zoom.start&&100==this._zoom.end)return t;var i=this._originalData.series;return i[e]?Math.floor(this._zoom.start/100*i[e].length)+t:-1},resize:function(){this.clear(),this._location=this._getLocation(),this._zoom=this._getZoom(),this.option.dataZoom.show&&this._buildShape()}},l.inherits(t,i),e("../component").define("dataZoom",t),t}),i("echarts/component/categoryAxis",["require","./base","zrender/shape/Text","zrender/shape/Line","zrender/shape/Rectangle","../config","zrender/tool/util","zrender/tool/area","../component"],function(e){function t(e,t,n,a,o,r){if(a.data.length<1)return void console.error("option.data.length < 1.");i.call(this,e,t,n,a,o),this.grid=this.component.grid;for(var s in r)this[s]=r[s];this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Line"),o=e("zrender/shape/Rectangle"),r=e("../config");r.categoryAxis={zlevel:0,z:0,show:!0,position:"bottom",name:"",nameLocation:"end",nameTextStyle:{},boundaryGap:!0,axisLine:{show:!0,onZero:!0,lineStyle:{color:"#48b",width:2,type:"solid"}},axisTick:{show:!0,interval:"auto",inside:!1,length:5,lineStyle:{color:"#333",width:1}},axisLabel:{show:!0,interval:"auto",rotate:0,margin:8,textStyle:{color:"#333"}},splitLine:{show:!0,lineStyle:{color:["#ccc"],width:1,type:"solid"}},splitArea:{show:!1,areaStyle:{color:["rgba(250,250,250,0.3)","rgba(200,200,200,0.3)"]}}};var s=e("zrender/tool/util"),l=e("zrender/tool/area");return t.prototype={type:r.COMPONENT_TYPE_AXIS_CATEGORY,_getReformedLabel:function(e){var t=this.getDataFromOption(this.option.data[e]),i=this.option.data[e].formatter||this.option.axisLabel.formatter;return i&&("function"==typeof i?t=i.call(this.myChart,t):"string"==typeof i&&(t=i.replace("{value}",t))),t},_getInterval:function(){var e=this.option.axisLabel.interval;if("auto"==e){var t=this.option.axisLabel.textStyle.fontSize,i=this.option.data,n=this.option.data.length;if(this.isHorizontal())if(n>3){var a,o,r=this.getGap(),h=!1,m=Math.floor(.5/r);for(m=1>m?1:m,e=Math.floor(15/r);!h&&n>e;){e+=m,h=!0,a=Math.floor(r*e);for(var V=Math.floor((n-1)/e)*e;V>=0;V-=e){if(0!==this.option.axisLabel.rotate)o=t;else if(i[V].textStyle)o=l.getTextWidth(this._getReformedLabel(V),this.getFont(s.merge(i[V].textStyle,this.option.axisLabel.textStyle)));else{var U=this._getReformedLabel(V)+"",d=(U.match(/\w/g)||"").length,p=U.length-d;o=d*t*2/3+p*t}if(o>a){h=!1;break}}}}else e=1;else if(n>3){var r=this.getGap();for(e=Math.floor(11/r);t>r*e-6&&n>e;)e++}else e=1}else e="function"==typeof e?1:e-0+1;return e},_buildShape:function(){if(this._interval=this._getInterval(),this.option.show){this.option.splitArea.show&&this._buildSplitArea(),this.option.splitLine.show&&this._buildSplitLine(),this.option.axisLine.show&&this._buildAxisLine(),this.option.axisTick.show&&this._buildAxisTick(),this.option.axisLabel.show&&this._buildAxisLabel();for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e])}},_buildAxisTick:function(){var e,t=this.option.data,i=this.option.data.length,n=this.option.axisTick,o=n.length,r=n.lineStyle.color,s=n.lineStyle.width,l="function"==typeof n.interval?n.interval:"auto"==n.interval&&"function"==typeof this.option.axisLabel.interval?this.option.axisLabel.interval:!1,h=l?1:"auto"==n.interval?this._interval:n.interval-0+1,m=n.onGap,V=m?this.getGap()/2:"undefined"==typeof m&&this.option.boundaryGap?this.getGap()/2:0,U=V>0?-h:0;if(this.isHorizontal())for(var d,p="bottom"==this.option.position?n.inside?this.grid.getYend()-o-1:this.grid.getYend()+1:n.inside?this.grid.getY()+1:this.grid.getY()-o-1,c=U;i>c;c+=h)(!l||l(c,t[c]))&&(d=this.subPixelOptimize(this.getCoordByIndex(c)+(c>=0?V:0),s),e={_axisShape:"axisTick",zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:d,yStart:p,xEnd:d,yEnd:p+o,strokeColor:r,lineWidth:s}},this.shapeList.push(new a(e)));else for(var u,y="left"==this.option.position?n.inside?this.grid.getX()+1:this.grid.getX()-o-1:n.inside?this.grid.getXend()-o-1:this.grid.getXend()+1,c=U;i>c;c+=h)(!l||l(c,t[c]))&&(u=this.subPixelOptimize(this.getCoordByIndex(c)-(c>=0?V:0),s),e={_axisShape:"axisTick",zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:y,yStart:u,xEnd:y+o,yEnd:u,strokeColor:r,lineWidth:s}},this.shapeList.push(new a(e)))},_buildAxisLabel:function(){var e,t,i=this.option.data,a=this.option.data.length,o=this.option.axisLabel,r=o.rotate,l=o.margin,h=o.clickable,m=o.textStyle,V="function"==typeof o.interval?o.interval:!1;if(this.isHorizontal()){var U,d;"bottom"==this.option.position?(U=this.grid.getYend()+l,d="top"):(U=this.grid.getY()-l,d="bottom");for(var p=0;a>p;p+=this._interval)V&&!V(p,i[p])||""===this._getReformedLabel(p)||(t=s.merge(i[p].textStyle||{},m),e={zlevel:this.getZlevelBase(),z:this.getZBase()+3,hoverable:!1,style:{x:this.getCoordByIndex(p),y:U,color:t.color,text:this._getReformedLabel(p),textFont:this.getFont(t),textAlign:t.align||"center",textBaseline:t.baseline||d}},r&&(e.style.textAlign=r>0?"bottom"==this.option.position?"right":"left":"bottom"==this.option.position?"left":"right",e.rotation=[r*Math.PI/180,e.style.x,e.style.y]),this.shapeList.push(new n(this._axisLabelClickable(h,e))))}else{var c,u;"left"==this.option.position?(c=this.grid.getX()-l,u="right"):(c=this.grid.getXend()+l,u="left");for(var p=0;a>p;p+=this._interval)V&&!V(p,i[p])||""===this._getReformedLabel(p)||(t=s.merge(i[p].textStyle||{},m),e={zlevel:this.getZlevelBase(),z:this.getZBase()+3,hoverable:!1,style:{x:c,y:this.getCoordByIndex(p),color:t.color,text:this._getReformedLabel(p),textFont:this.getFont(t),textAlign:t.align||u,textBaseline:t.baseline||0===p&&""!==this.option.name?"bottom":p==a-1&&""!==this.option.name?"top":"middle"}},r&&(e.rotation=[r*Math.PI/180,e.style.x,e.style.y]),this.shapeList.push(new n(this._axisLabelClickable(h,e))))}},_buildSplitLine:function(){var e,t=this.option.data,i=this.option.data.length,n=this.option.splitLine,o=n.lineStyle.type,r=n.lineStyle.width,s=n.lineStyle.color;s=s instanceof Array?s:[s];var l=s.length,h="function"==typeof this.option.axisLabel.interval?this.option.axisLabel.interval:!1,m=n.onGap,V=m?this.getGap()/2:"undefined"==typeof m&&this.option.boundaryGap?this.getGap()/2:0;if(i-=m||"undefined"==typeof m&&this.option.boundaryGap?1:0,this.isHorizontal())for(var U,d=this.grid.getY(),p=this.grid.getYend(),c=0;i>c;c+=this._interval)(!h||h(c,t[c]))&&(U=this.subPixelOptimize(this.getCoordByIndex(c)+V,r),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:U,yStart:d,xEnd:U,yEnd:p,strokeColor:s[c/this._interval%l],lineType:o,lineWidth:r}},this.shapeList.push(new a(e)));else for(var u,y=this.grid.getX(),g=this.grid.getXend(),c=0;i>c;c+=this._interval)(!h||h(c,t[c]))&&(u=this.subPixelOptimize(this.getCoordByIndex(c)-V,r),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:y,yStart:u,xEnd:g,yEnd:u,strokeColor:s[c/this._interval%l],lineType:o,lineWidth:r}},this.shapeList.push(new a(e)))},_buildSplitArea:function(){var e,t=this.option.data,i=this.option.splitArea,n=i.areaStyle.color;if(n instanceof Array){var a=n.length,r=this.option.data.length,s="function"==typeof this.option.axisLabel.interval?this.option.axisLabel.interval:!1,l=i.onGap,h=l?this.getGap()/2:"undefined"==typeof l&&this.option.boundaryGap?this.getGap()/2:0;if(this.isHorizontal())for(var m,V=this.grid.getY(),U=this.grid.getHeight(),d=this.grid.getX(),p=0;r>=p;p+=this._interval)s&&!s(p,t[p])&&r>p||(m=r>p?this.getCoordByIndex(p)+h:this.grid.getXend(),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:d,y:V,width:m-d,height:U,color:n[p/this._interval%a]}},this.shapeList.push(new o(e)),d=m);else for(var c,u=this.grid.getX(),y=this.grid.getWidth(),g=this.grid.getYend(),p=0;r>=p;p+=this._interval)s&&!s(p,t[p])&&r>p||(c=r>p?this.getCoordByIndex(p)-h:this.grid.getY(),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:u,y:c,width:y,height:g-c,color:n[p/this._interval%a]}},this.shapeList.push(new o(e)),g=c)}else e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this.grid.getX(),y:this.grid.getY(),width:this.grid.getWidth(),height:this.grid.getHeight(),color:n}},this.shapeList.push(new o(e))},refresh:function(e){e&&(this.option=this.reformOption(e),this.option.axisLabel.textStyle=this.getTextStyle(this.option.axisLabel.textStyle)),this.clear(),this._buildShape()},getGap:function(){var e=this.option.data.length,t=this.isHorizontal()?this.grid.getWidth():this.grid.getHeight();return this.option.boundaryGap?t/e:t/(e>1?e-1:1)},getCoord:function(e){for(var t=this.option.data,i=t.length,n=this.getGap(),a=this.option.boundaryGap?n/2:0,o=0;i>o;o++){if(this.getDataFromOption(t[o])==e)return a=this.isHorizontal()?this.grid.getX()+a:this.grid.getYend()-a;a+=n}},getCoordByIndex:function(e){if(0>e)return this.isHorizontal()?this.grid.getX():this.grid.getYend();if(e>this.option.data.length-1)return this.isHorizontal()?this.grid.getXend():this.grid.getY();var t=this.getGap(),i=this.option.boundaryGap?t/2:0;return i+=e*t,i=this.isHorizontal()?this.grid.getX()+i:this.grid.getYend()-i},getNameByIndex:function(e){return this.getDataFromOption(this.option.data[e])},getIndexByName:function(e){for(var t=this.option.data,i=t.length,n=0;i>n;n++)if(this.getDataFromOption(t[n])==e)return n;return-1},getValueFromCoord:function(){return""},isMainAxis:function(e){return e%this._interval===0}},s.inherits(t,i),e("../component").define("categoryAxis",t),t}),i("echarts/component/valueAxis",["require","./base","zrender/shape/Text","zrender/shape/Line","zrender/shape/Rectangle","../config","../util/date","zrender/tool/util","../util/smartSteps","../util/accMath","../util/smartLogSteps","../component"],function(e){function t(e,t,n,a,o,r,s){if(!s||0===s.length)return void console.err("option.series.length == 0.");i.call(this,e,t,n,a,o),this.series=s,this.grid=this.component.grid;for(var l in r)this[l]=r[l];this.refresh(a,s)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Line"),o=e("zrender/shape/Rectangle"),r=e("../config");r.valueAxis={zlevel:0,z:0,show:!0,position:"left",name:"",nameLocation:"end",nameTextStyle:{},boundaryGap:[0,0],axisLine:{show:!0,onZero:!0,lineStyle:{color:"#48b",width:2,type:"solid"}},axisTick:{show:!1,inside:!1,length:5,lineStyle:{color:"#333",width:1}},axisLabel:{show:!0,rotate:0,margin:8,textStyle:{color:"#333"}},splitLine:{show:!0,lineStyle:{color:["#ccc"],width:1,type:"solid"}},splitArea:{show:!1,areaStyle:{color:["rgba(250,250,250,0.3)","rgba(200,200,200,0.3)"]}}};var s=e("../util/date"),l=e("zrender/tool/util");return t.prototype={type:r.COMPONENT_TYPE_AXIS_VALUE,_buildShape:function(){if(this._hasData=!1,this._calculateValue(),this._hasData&&this.option.show){this.option.splitArea.show&&this._buildSplitArea(),this.option.splitLine.show&&this._buildSplitLine(),this.option.axisLine.show&&this._buildAxisLine(),this.option.axisTick.show&&this._buildAxisTick(),this.option.axisLabel.show&&this._buildAxisLabel();for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e])}},_buildAxisTick:function(){var e,t=this._valueList,i=this._valueList.length,n=this.option.axisTick,o=n.length,r=n.lineStyle.color,s=n.lineStyle.width;if(this.isHorizontal())for(var l,h="bottom"===this.option.position?n.inside?this.grid.getYend()-o-1:this.grid.getYend()+1:n.inside?this.grid.getY()+1:this.grid.getY()-o-1,m=0;i>m;m++)l=this.subPixelOptimize(this.getCoord(t[m]),s),e={_axisShape:"axisTick",zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:l,yStart:h,xEnd:l,yEnd:h+o,strokeColor:r,lineWidth:s}},this.shapeList.push(new a(e));else for(var V,U="left"===this.option.position?n.inside?this.grid.getX()+1:this.grid.getX()-o-1:n.inside?this.grid.getXend()-o-1:this.grid.getXend()+1,m=0;i>m;m++)V=this.subPixelOptimize(this.getCoord(t[m]),s),e={_axisShape:"axisTick",zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:U,yStart:V,xEnd:U+o,yEnd:V,strokeColor:r,lineWidth:s}},this.shapeList.push(new a(e))},_buildAxisLabel:function(){var e,t=this._valueList,i=this._valueList.length,a=this.option.axisLabel.rotate,o=this.option.axisLabel.margin,r=this.option.axisLabel.clickable,s=this.option.axisLabel.textStyle;if(this.isHorizontal()){var l,h;"bottom"===this.option.position?(l=this.grid.getYend()+o,h="top"):(l=this.grid.getY()-o,h="bottom");for(var m=0;i>m;m++)e={zlevel:this.getZlevelBase(),z:this.getZBase()+3,hoverable:!1,style:{x:this.getCoord(t[m]),y:l,color:"function"==typeof s.color?s.color(t[m]):s.color,text:this._valueLabel[m],textFont:this.getFont(s),textAlign:s.align||"center",textBaseline:s.baseline||h}},a&&(e.style.textAlign=a>0?"bottom"===this.option.position?"right":"left":"bottom"===this.option.position?"left":"right",e.rotation=[a*Math.PI/180,e.style.x,e.style.y]),this.shapeList.push(new n(this._axisLabelClickable(r,e)))}else{var V,U;"left"===this.option.position?(V=this.grid.getX()-o,U="right"):(V=this.grid.getXend()+o,U="left");for(var m=0;i>m;m++)e={zlevel:this.getZlevelBase(),z:this.getZBase()+3,hoverable:!1,style:{x:V,y:this.getCoord(t[m]),color:"function"==typeof s.color?s.color(t[m]):s.color,text:this._valueLabel[m],textFont:this.getFont(s),textAlign:s.align||U,textBaseline:s.baseline||(0===m&&""!==this.option.name?"bottom":m===i-1&&""!==this.option.name?"top":"middle")}},a&&(e.rotation=[a*Math.PI/180,e.style.x,e.style.y]),this.shapeList.push(new n(this._axisLabelClickable(r,e)))}},_buildSplitLine:function(){var e,t=this._valueList,i=this._valueList.length,n=this.option.splitLine,o=n.lineStyle.type,r=n.lineStyle.width,s=n.lineStyle.color;s=s instanceof Array?s:[s];var l=s.length;if(this.isHorizontal())for(var h,m=this.grid.getY(),V=this.grid.getYend(),U=0;i>U;U++)h=this.subPixelOptimize(this.getCoord(t[U]),r),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:h,yStart:m,xEnd:h,yEnd:V,strokeColor:s[U%l],lineType:o,lineWidth:r}},this.shapeList.push(new a(e));else for(var d,p=this.grid.getX(),c=this.grid.getXend(),U=0;i>U;U++)d=this.subPixelOptimize(this.getCoord(t[U]),r),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:p,yStart:d,xEnd:c,yEnd:d,strokeColor:s[U%l],lineType:o,lineWidth:r}},this.shapeList.push(new a(e))},_buildSplitArea:function(){var e,t=this.option.splitArea.areaStyle.color;if(t instanceof Array){var i=t.length,n=this._valueList,a=this._valueList.length;if(this.isHorizontal())for(var r,s=this.grid.getY(),l=this.grid.getHeight(),h=this.grid.getX(),m=0;a>=m;m++)r=a>m?this.getCoord(n[m]):this.grid.getXend(),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:h,y:s,width:r-h,height:l,color:t[m%i]}},this.shapeList.push(new o(e)),h=r;else for(var V,U=this.grid.getX(),d=this.grid.getWidth(),p=this.grid.getYend(),m=0;a>=m;m++)V=a>m?this.getCoord(n[m]):this.grid.getY(),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:U,y:V,width:d,height:p-V,color:t[m%i]}},this.shapeList.push(new o(e)),p=V}else e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this.grid.getX(),y:this.grid.getY(),width:this.grid.getWidth(),height:this.grid.getHeight(),color:t}},this.shapeList.push(new o(e))},_calculateValue:function(){if(isNaN(this.option.min-0)||isNaN(this.option.max-0)){for(var e,t,i={},n=this.component.legend,a=0,o=this.series.length;o>a;a++)!(this.series[a].type!=r.CHART_TYPE_LINE&&this.series[a].type!=r.CHART_TYPE_BAR&&this.series[a].type!=r.CHART_TYPE_SCATTER&&this.series[a].type!=r.CHART_TYPE_K&&this.series[a].type!=r.CHART_TYPE_EVENTRIVER||n&&!n.isSelected(this.series[a].name)||(e=this.series[a].xAxisIndex||0,t=this.series[a].yAxisIndex||0,this.option.xAxisIndex!=e&&this.option.yAxisIndex!=t||!this._calculSum(i,a)));var s;for(var a in i){s=i[a];for(var l=0,h=s.length;h>l;l++)if(!isNaN(s[l])){this._hasData=!0,this._min=s[l],this._max=s[l];break}if(this._hasData)break}for(var a in i){s=i[a];for(var l=0,h=s.length;h>l;l++)isNaN(s[l])||(this._min=Math.min(this._min,s[l]),this._max=Math.max(this._max,s[l]))}var m="log"!==this.option.type?this.option.boundaryGap:[0,0],V=Math.abs(this._max-this._min);this._min=isNaN(this.option.min-0)?this._min-Math.abs(V*m[0]):this.option.min-0,this._max=isNaN(this.option.max-0)?this._max+Math.abs(V*m[1]):this.option.max-0,this._min===this._max&&(0===this._max?this._max=1:this._max>0?this._min=this._max/this.option.splitNumber!=null?this.option.splitNumber:5:this._max=this._max/this.option.splitNumber!=null?this.option.splitNumber:5),"time"===this.option.type?this._reformTimeValue():"log"===this.option.type?this._reformLogValue():this._reformValue(this.option.scale)}else this._hasData=!0,this._min=this.option.min-0,this._max=this.option.max-0,"time"===this.option.type?this._reformTimeValue():"log"===this.option.type?this._reformLogValue():this._customerValue()},_calculSum:function(e,t){var i,n,a=this.series[t].name||"kener";if(this.series[t].stack){var o="__Magic_Key_Positive__"+this.series[t].stack,l="__Magic_Key_Negative__"+this.series[t].stack;e[o]=e[o]||[],e[l]=e[l]||[],e[a]=e[a]||[],n=this.series[t].data;for(var h=0,m=n.length;m>h;h++)i=this.getDataFromOption(n[h]),"-"!==i&&(i-=0,i>=0?null!=e[o][h]?e[o][h]+=i:e[o][h]=i:null!=e[l][h]?e[l][h]+=i:e[l][h]=i,this.option.scale&&e[a].push(i))}else if(e[a]=e[a]||[],this.series[t].type!=r.CHART_TYPE_EVENTRIVER){n=this.series[t].data;for(var h=0,m=n.length;m>h;h++)i=this.getDataFromOption(n[h]),this.series[t].type===r.CHART_TYPE_K?(e[a].push(i[0]),e[a].push(i[1]),e[a].push(i[2]),e[a].push(i[3])):i instanceof Array?(-1!=this.option.xAxisIndex&&e[a].push("time"!=this.option.type?i[0]:s.getNewDate(i[0])),-1!=this.option.yAxisIndex&&e[a].push("time"!=this.option.type?i[1]:s.getNewDate(i[1]))):e[a].push(i)}else{n=this.series[t].data;for(var h=0,m=n.length;m>h;h++)for(var V=n[h].evolution,U=0,d=V.length;d>U;U++)e[a].push(s.getNewDate(V[U].time))}},_reformValue:function(t){var i=e("../util/smartSteps"),n=this.option.splitNumber;!t&&this._min>=0&&this._max>=0&&(this._min=0),!t&&this._min<=0&&this._max<=0&&(this._max=0);var a=i(this._min,this._max,n);n=null!=n?n:a.secs,this._min=a.min,this._max=a.max,this._valueList=a.pnts,this._reformLabelData()},_reformTimeValue:function(){var e=null!=this.option.splitNumber?this.option.splitNumber:5,t=s.getAutoFormatter(this._min,this._max,e),i=t.formatter,n=t.gapValue;this._valueList=[s.getNewDate(this._min)];var a;switch(i){case"week":a=s.nextMonday(this._min);break;case"month":a=s.nextNthOnMonth(this._min,1);break;case"quarter":a=s.nextNthOnQuarterYear(this._min,1);break;case"half-year":a=s.nextNthOnHalfYear(this._min,1);break;case"year":a=s.nextNthOnYear(this._min,1);break;default:72e5>=n?a=(Math.floor(this._min/n)+1)*n:(a=s.getNewDate(this._min- -n),a.setHours(6*Math.round(a.getHours()/6)),a.setMinutes(0),a.setSeconds(0))}for(a-this._min=0&&(("month"==i||"quarter"==i||"half-year"==i||"year"==i)&&t.setDate(1),!(this._max-t=a;a++)this._valueList.push(t.accAdd(this._min,t.accMul(n,a)));this._reformLabelData()},_reformLogValue:function(){var t=this.option,i=e("../util/smartLogSteps")({dataMin:this._min,dataMax:this._max,logPositive:t.logPositive,logLabelBase:t.logLabelBase,splitNumber:t.splitNumber});this._min=i.dataMin,this._max=i.dataMax,this._valueList=i.tickList,this._dataMappingMethods=i.dataMappingMethods,this._reformLabelData(i.labelFormatter)},_reformLabelData:function(e){this._valueLabel=[];var t=this.option.axisLabel.formatter;if(t)for(var i=0,n=this._valueList.length;n>i;i++)"function"==typeof t?this._valueLabel.push(e?t.call(this.myChart,this._valueList[i],e):t.call(this.myChart,this._valueList[i])):"string"==typeof t&&this._valueLabel.push(e?s.format(t,this._valueList[i]):t.replace("{value}",this._valueList[i]));else for(var i=0,n=this._valueList.length;n>i;i++)this._valueLabel.push(e?e(this._valueList[i]):this.numAddCommas(this._valueList[i]))},getExtremum:function(){this._calculateValue();var e=this._dataMappingMethods;return{min:this._min,max:this._max,dataMappingMethods:e?l.merge({},e):null}},refresh:function(e,t){e&&(this.option=this.reformOption(e),this.option.axisLabel.textStyle=l.merge(this.option.axisLabel.textStyle||{},this.ecTheme.textStyle),this.series=t),this.zr&&(this.clear(),this._buildShape())},getCoord:function(e){this._dataMappingMethods&&(e=this._dataMappingMethods.value2Coord(e)),e=ethis._max?this._max:e;var t;return t=this.isHorizontal()?this.grid.getX()+(e-this._min)/(this._max-this._min)*this.grid.getWidth():this.grid.getYend()-(e-this._min)/(this._max-this._min)*this.grid.getHeight()},getCoordSize:function(e){return Math.abs(this.isHorizontal()?e/(this._max-this._min)*this.grid.getWidth():e/(this._max-this._min)*this.grid.getHeight())},getValueFromCoord:function(e){var t;return this.isHorizontal()?(e=ethis.grid.getXend()?this.grid.getXend():e,t=this._min+(e-this.grid.getX())/this.grid.getWidth()*(this._max-this._min)):(e=ethis.grid.getYend()?this.grid.getYend():e,t=this._max-(e-this.grid.getY())/this.grid.getHeight()*(this._max-this._min)),this._dataMappingMethods&&(t=this._dataMappingMethods.coord2Value(t)),t.toFixed(2)-0},isMaindAxis:function(e){for(var t=0,i=this._valueList.length;i>t;t++)if(this._valueList[t]===e)return!0;return!1}},l.inherits(t,i),e("../component").define("valueAxis",t),t}),i("echarts/util/date",[],function(){function e(e,t,i){i=i>1?i:2;for(var n,a,o,r,s=0,l=m.length;l>s;s++)if(n=m[s].value,a=Math.ceil(t/n)*n-Math.floor(e/n)*n,Math.round(a/n)<=1.2*i){o=m[s].formatter,r=m[s].value;break}return null==o&&(o="year",n=317088e5,a=Math.ceil(t/n)*n-Math.floor(e/n)*n,r=Math.round(a/(i-1)/n)*n),{formatter:o,gapValue:r}}function t(e){return 10>e?"0"+e:e}function i(e,i){("week"==e||"month"==e||"quarter"==e||"half-year"==e||"year"==e)&&(e="MM - dd\nyyyy");var n=h(i),a=n.getFullYear(),o=n.getMonth()+1,r=n.getDate(),s=n.getHours(),l=n.getMinutes(),m=n.getSeconds();return e=e.replace("MM",t(o)),e=e.toLowerCase(),e=e.replace("yyyy",a),e=e.replace("yy",a%100),e=e.replace("dd",t(r)),e=e.replace("d",r),e=e.replace("hh",t(s)),e=e.replace("h",s),e=e.replace("mm",t(l)),e=e.replace("m",l),e=e.replace("ss",t(m)),e=e.replace("s",m)}function n(e){return e=h(e),e.setDate(e.getDate()+8-e.getDay()),e}function a(e,t,i){return e=h(e),e.setMonth(Math.ceil((e.getMonth()+1)/i)*i),e.setDate(t),e}function o(e,t){return a(e,t,1)}function r(e,t){return a(e,t,3)}function s(e,t){return a(e,t,6)}function l(e,t){return a(e,t,12)}function h(e){return e instanceof Date?e:new Date("string"==typeof e?e.replace(/-/g,"/"):e)}var m=[{formatter:"hh : mm : ss",value:1e3},{formatter:"hh : mm : ss",value:5e3},{formatter:"hh : mm : ss",value:1e4},{formatter:"hh : mm : ss",value:15e3},{formatter:"hh : mm : ss",value:3e4},{formatter:"hh : mm\nMM - dd",value:6e4},{formatter:"hh : mm\nMM - dd",value:3e5},{formatter:"hh : mm\nMM - dd",value:6e5},{formatter:"hh : mm\nMM - dd",value:9e5},{formatter:"hh : mm\nMM - dd",value:18e5},{formatter:"hh : mm\nMM - dd",value:36e5},{formatter:"hh : mm\nMM - dd",value:72e5},{formatter:"hh : mm\nMM - dd",value:216e5},{formatter:"hh : mm\nMM - dd",value:432e5},{formatter:"MM - dd\nyyyy",value:864e5},{formatter:"week",value:6048e5},{formatter:"month",value:26784e5},{formatter:"quarter",value:8208e6},{formatter:"half-year",value:16416e6},{formatter:"year",value:32832e6}];return{getAutoFormatter:e,getNewDate:h,format:i,nextMonday:n,nextNthPerNmonth:a,nextNthOnMonth:o,nextNthOnQuarterYear:r,nextNthOnHalfYear:s,nextNthOnYear:l}}),i("echarts/util/smartSteps",[],function(){function e(e){return X.log(I(e))/X.LN10}function t(e){return X.pow(10,e)}function i(e){return e===w(e)}function n(e,t,n,a){b=a||{},f=b.steps||L,k=b.secs||W,n=v(+n||0)%99,e=+e||0,t=+t||0,x=_=0,"min"in b&&(e=+b.min||0,x=1),"max"in b&&(t=+b.max||0,_=1),e>t&&(t=[e,e=t][0]);var o=t-e;if(x&&_)return g(e,t,n);if((n||5)>o){if(i(e)&&i(t))return d(e,t,n);if(0===o)return p(e,t,n)}return h(e,t,n)}function a(e,i,n,a){a=a||0;var s=o((i-e)/n,-1),l=o(e,-1,1),h=o(i,-1),m=X.min(s.e,l.e,h.e);0===l.c?m=X.min(s.e,h.e):0===h.c&&(m=X.min(s.e,l.e)),r(s,{c:0,e:m}),r(l,s,1),r(h,s),a+=m,e=l.c,i=h.c;for(var V=(i-e)/n,U=t(a),d=0,p=[],c=n+1;c--;)p[c]=(e+V*c)*U;if(0>a){d=u(U),V=+(V*U).toFixed(d),e=+(e*U).toFixed(d),i=+(i*U).toFixed(d);for(var c=p.length;c--;)p[c]=p[c].toFixed(d),0===+p[c]&&(p[c]="0")}else e*=U,i*=U,V*=U;return k=0,f=0,b=0,{min:e,max:i,secs:n,step:V,fix:d,exp:a,pnts:p}}function o(n,a,o){a=v(a%10)||2,0>a&&(i(n)?a=(""+I(n)).replace(/0+$/,"").length||1:(n=n.toFixed(15).replace(/0+$/,""),a=n.replace(".","").replace(/^[-0]+/,"").length,n=+n));var r=w(e(n))-a+1,s=+(n*t(-r)).toFixed(15)||0;return s=o?w(s):K(s),!s&&(r=0),(""+I(s)).length>a&&(r+=1,s/=10),{c:s,e:r}}function r(e,i,n){var a=i.e-e.e;a&&(e.e+=a,e.c*=t(-a),e.c=n?w(e.c):K(e.c))}function s(e,t,i){e.et[n];)n++;if(!t[n])for(i/=10,e.e+=1,n=0;i>t[n];)n++;return e.c=t[n],e}function h(e,t,n){var s,h=n||+k.slice(-1),p=l((t-e)/h,f),u=o(t-e),g=o(e,-1,1),b=o(t,-1);if(r(u,p),r(g,p,1),r(b,p),n?s=V(g,b,h):h=m(g,b),i(e)&&i(t)&&e*t>=0){if(h>t-e)return d(e,t,h);h=U(e,t,n,g,b,h)}var L=c(e,t,g.c,b.c);return g.c=L[0],b.c=L[1],(x||_)&&y(e,t,g,b),a(g.c,b.c,h,b.e)}function m(e,i){for(var n,a,o,r,s=[],h=k.length;h--;)n=k[h],a=l((i.c-e.c)/n,f),a=a.c*t(a.e),o=w(e.c/a)*a,r=K(i.c/a)*a,s[h]={min:o,max:r,step:a,span:r-o};return s.sort(function(e,t){var i=e.span-t.span;return 0===i&&(i=e.step-t.step),i}),s=s[0],n=s.span/s.step,e.c=s.min,i.c=s.max,3>n?2*n:n}function V(e,i,n){for(var a,o,r=i.c,s=(i.c-e.c)/n-1;r>e.c;)s=l(s+1,f),s=s.c*t(s.e),a=s*n,o=K(i.c/s)*s,r=o-a;var h=e.c-r,m=o-i.c,V=h-m;return V>1.1*s&&(V=v(V/s/2)*s,r+=V,o+=V),e.c=r,i.c=o,s}function U(e,n,a,o,r,s){var l=r.c-o.c,h=l/s*t(r.e);if(!i(h)&&(h=w(h),l=h*s,n-e>l&&(h+=1,l=h*s,!a&&h*(s-1)>=n-e&&(s-=1,l=h*s)),l>=n-e)){var m=l-(n-e);o.c=v(e-m/2),r.c=v(n+m/2),o.e=0,r.e=0}return s}function d(e,t,i){if(i=i||5,x)t=e+i;else if(_)e=t-i;else{var n=i-(t-e),o=v(e-n/2),r=v(t+n/2),s=c(e,t,o,r);e=s[0],t=s[1]}return a(e,t,i)}function p(e,t,i){i=i||5;var n=X.min(I(t/i),i)/2.1;return x?t=e+n:_?e=t-n:(e-=n,t+=n),h(e,t,i)}function c(e,t,i,n){ +return e>=0&&0>i?(n-=i,i=0):0>=t&&n>0&&(i-=n,n=0),[i,n]}function u(e){return e=(+e).toFixed(15).split("."),e.pop().replace(/0+$/,"").length}function y(e,t,i,n){if(x){var a=o(e,4,1);i.e-a.e>6&&(a={c:0,e:i.e}),s(i,a),s(n,a),n.c+=a.c-i.c,i.c=a.c}else if(_){var r=o(t,4);n.e-r.e>6&&(r={c:0,e:n.e}),s(i,r),s(n,r),i.c+=r.c-n.c,n.c=r.c}}function g(e,t,i){var n=i?[i]:k,s=t-e;if(0===s)return t=o(t,3),i=n[0],t.c=v(t.c+i/2),a(t.c-i,t.c,i,t.e);I(t/s)<1e-6&&(t=0),I(e/s)<1e-6&&(e=0);var l,h,m,V=[[5,10],[10,2],[50,10],[100,2]],U=[],d=[],p=o(t-e,3),c=o(e,-1,1),u=o(t,-1);r(c,p,1),r(u,p),s=u.c-c.c,p.c=s;for(var y=n.length;y--;){i=n[y],l=K(s/i),h=l*i-s,m=3*(h+3),m+=2*(i-n[0]+2),i%5===0&&(m-=10);for(var g=V.length;g--;)l%V[g][0]===0&&(m/=V[g][1]);d[y]=[i,l,h,m].join(),U[y]={secs:i,step:l,delta:h,score:m}}return U.sort(function(e,t){return e.score-t.score}),U=U[0],c.c=v(c.c-U.delta/2),u.c=v(u.c+U.delta/2),a(c.c,u.c,U.secs,p.e)}var b,f,k,x,_,L=[10,20,25,50],W=[4,5,6],X=Math,v=X.round,w=X.floor,K=X.ceil,I=X.abs;return n}),i("echarts/util/smartLogSteps",["require","./number"],function(e){function t(e){return i(),u=e||{},n(),a(),[o(),i()][0]}function i(){U=u=g=c=b=f=y=k=d=p=null}function n(){d=u.logLabelBase,null==d?(p="plain",d=10,c=I):(d=+d,1>d&&(d=10),p="exponent",c=L(d)),y=u.splitNumber,null==y&&(y=E);var e=parseFloat(u.dataMin),t=parseFloat(u.dataMax);isFinite(e)||isFinite(t)?isFinite(e)?isFinite(t)?e>t&&(t=[e,e=t][0]):t=e:e=t:e=t=1,U=u.logPositive,null==U&&(U=t>0||0===e),b=U?e:-t,f=U?t:-e,S>b&&(b=S),S>f&&(f=S)}function a(){function e(){y>m&&(y=m);var e=w(l(m/y)),t=v(l(m/e)),i=e*t,n=(i-U)/2,a=w(l(r-n));V(a-r)&&(a-=1),g=-a*c;for(var s=a;o>=s-e;s+=e)k.push(W(d,s))}function t(){for(var e=i(h,0),t=e+2;t>e&&a(e+1)+n(e+1)*Ct&&a(l-1)+n(l-1)*C>o;)l--;g=-(a(e)*I+n(e)*J);for(var m=e;l>=m;m++){var V=a(m),U=n(m);k.push(W(10,V)*W(2,U))}}function i(e,t){return 3*e+t}function n(e){return e-3*a(e)}function a(e){return w(l(e/3))}k=[];var o=l(L(f)/c),r=l(L(b)/c),s=v(o),h=w(r),m=s-h,U=o-r;"exponent"===p?e():F>=m&&y>F?t():e()}function o(){for(var e=[],t=0,i=k.length;i>t;t++)e[t]=(U?1:-1)*k[t];!U&&e.reverse();var n=s(),a=n.value2Coord,o=a(e[0]),l=a(e[e.length-1]);return o===l&&(o-=1,l+=1),{dataMin:o,dataMax:l,tickList:e,logPositive:U,labelFormatter:r(),dataMappingMethods:n}}function r(){if("exponent"===p){var e=d,t=c;return function(i){if(!isFinite(parseFloat(i)))return"";var n="";return 0>i&&(i=-i,n="-"),n+e+m(L(i)/t)}}return function(e){return isFinite(parseFloat(e))?x.addCommas(h(e)):""}}function s(){var e=U,t=g;return{value2Coord:function(i){return null==i||isNaN(i)||!isFinite(i)?i:(i=parseFloat(i),isFinite(i)?e&&S>i?i=S:!e&&i>-S&&(i=-S):i=S,i=X(i),(e?1:-1)*(L(i)+t))},coord2Value:function(i){return null==i||isNaN(i)||!isFinite(i)?i:(i=parseFloat(i),isFinite(i)||(i=S),e?W(K,i-t):-W(K,-i+t))}}}function l(e){return+Number(+e).toFixed(14)}function h(e){return Number(e).toFixed(15).replace(/\.?0*$/,"")}function m(e){e=h(Math.round(e));for(var t=[],i=0,n=e.length;n>i;i++){var a=e.charAt(i);t.push(T[a]||"")}return t.join("")}function V(e){return e>-S&&S>e}var U,d,p,c,u,y,g,b,f,k,x=e("./number"),_=Math,L=_.log,W=_.pow,X=_.abs,v=_.ceil,w=_.floor,K=_.E,I=_.LN10,J=_.LN2,C=J/I,S=1e-9,E=5,F=2,T={0:"⁰",1:"¹",2:"²",3:"³",4:"⁴",5:"⁵",6:"⁶",7:"⁷",8:"⁸",9:"⁹","-":"⁻"};return t}),i("echarts/chart/line",["require","./base","zrender/shape/Polyline","../util/shape/Icon","../util/shape/HalfSmoothPolygon","../component/axis","../component/grid","../component/dataZoom","../config","../util/ecData","zrender/tool/util","zrender/tool/color","../chart"],function(e){function t(e,t,i,a,o){n.call(this,e,t,i,a,o),this.refresh(a)}function i(e,t,i){var n=t.x,a=t.y,r=t.width,s=t.height,l=s/2;t.symbol.match("empty")&&(e.fillStyle="#fff"),t.brushType="both";var h=t.symbol.replace("empty","").toLowerCase();h.match("star")?(l=h.replace("star","")-0||5,a-=1,h="star"):("rectangle"===h||"arrow"===h)&&(n+=(r-s)/2,r=s);var m="";if(h.match("image")&&(m=h.replace(new RegExp("^image:\\/\\/"),""),h="image",n+=Math.round((r-s)/2)-1,r=s+=2),h=o.prototype.iconLibrary[h]){var V=t.x,U=t.y;e.moveTo(V,U+l),e.lineTo(V+5,U+l),e.moveTo(V+t.width-5,U+l),e.lineTo(V+t.width,U+l);var d=this;h(e,{x:n+4,y:a+4,width:r-8,height:s-8,n:l,image:m},function(){d.modSelf(),i()})}else e.moveTo(n,a+l),e.lineTo(n+r,a+l)}var n=e("./base"),a=e("zrender/shape/Polyline"),o=e("../util/shape/Icon"),r=e("../util/shape/HalfSmoothPolygon");e("../component/axis"),e("../component/grid"),e("../component/dataZoom");var s=e("../config");s.line={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,xAxisIndex:0,yAxisIndex:0,dataFilter:"nearest",itemStyle:{normal:{label:{show:!1},lineStyle:{width:2,type:"solid",shadowColor:"rgba(0,0,0,0)",shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0}},emphasis:{label:{show:!1}}},symbolSize:2,showAllSymbol:!1};var l=e("../util/ecData"),h=e("zrender/tool/util"),m=e("zrender/tool/color");return t.prototype={type:s.CHART_TYPE_LINE,_buildShape:function(){this.finalPLMap={},this._buildPosition()},_buildHorizontal:function(e,t,i,n){for(var a,o,r,s,l,h,m,V,U,d=this.series,p=i[0][0],c=d[p],u=this.component.xAxis.getAxis(c.xAxisIndex||0),y={},g=0,b=t;b>g&&null!=u.getNameByIndex(g);g++){o=u.getCoordByIndex(g);for(var f=0,k=i.length;k>f;f++){a=this.component.yAxis.getAxis(d[i[f][0]].yAxisIndex||0),l=s=m=h=a.getCoord(0);for(var x=0,_=i[f].length;_>x;x++)p=i[f][x],c=d[p],V=c.data[g],U=this.getDataFromOption(V,"-"),y[p]=y[p]||[],n[p]=n[p]||{min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY,sum:0,counter:0,average:0},"-"!==U?(U>=0?(s-=x>0?a.getCoordSize(U):l-a.getCoord(U),r=s):0>U&&(h+=x>0?a.getCoordSize(U):a.getCoord(U)-m,r=h),y[p].push([o,r,g,u.getNameByIndex(g),o,l]),n[p].min>U&&(n[p].min=U,n[p].minY=r,n[p].minX=o),n[p].max0&&(this.finalPLMap[p]=this.finalPLMap[p]||[],this.finalPLMap[p].push(y[p]),y[p]=[])}s=this.component.grid.getY();for(var L,f=0,k=i.length;k>f;f++)for(var x=0,_=i[f].length;_>x;x++)p=i[f][x],c=d[p],V=c.data[g],U=this.getDataFromOption(V,"-"),"-"==U&&this.deepQuery([V,c,this.option],"calculable")&&(L=this.deepQuery([V,c],"symbolSize"),s+=2*L+5,r=s,this.shapeList.push(this._getCalculableItem(p,g,u.getNameByIndex(g),o,r,"horizontal")))}for(var W in y)y[W].length>0&&(this.finalPLMap[W]=this.finalPLMap[W]||[],this.finalPLMap[W].push(y[W]),y[W]=[]);this._calculMarkMapXY(n,i,"y"),this._buildBorkenLine(e,this.finalPLMap,u,"horizontal")},_buildVertical:function(e,t,i,n){for(var a,o,r,s,l,h,m,V,U,d=this.series,p=i[0][0],c=d[p],u=this.component.yAxis.getAxis(c.yAxisIndex||0),y={},g=0,b=t;b>g&&null!=u.getNameByIndex(g);g++){r=u.getCoordByIndex(g);for(var f=0,k=i.length;k>f;f++){a=this.component.xAxis.getAxis(d[i[f][0]].xAxisIndex||0),l=s=m=h=a.getCoord(0);for(var x=0,_=i[f].length;_>x;x++)p=i[f][x],c=d[p],V=c.data[g],U=this.getDataFromOption(V,"-"),y[p]=y[p]||[],n[p]=n[p]||{min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY,sum:0,counter:0,average:0},"-"!==U?(U>=0?(s+=x>0?a.getCoordSize(U):a.getCoord(U)-l,o=s):0>U&&(h-=x>0?a.getCoordSize(U):m-a.getCoord(U),o=h),y[p].push([o,r,g,u.getNameByIndex(g),l,r]),n[p].min>U&&(n[p].min=U,n[p].minX=o,n[p].minY=r),n[p].max0&&(this.finalPLMap[p]=this.finalPLMap[p]||[],this.finalPLMap[p].push(y[p]),y[p]=[])}s=this.component.grid.getXend();for(var L,f=0,k=i.length;k>f;f++)for(var x=0,_=i[f].length;_>x;x++)p=i[f][x],c=d[p],V=c.data[g],U=this.getDataFromOption(V,"-"),"-"==U&&this.deepQuery([V,c,this.option],"calculable")&&(L=this.deepQuery([V,c],"symbolSize"),s-=2*L+5,o=s,this.shapeList.push(this._getCalculableItem(p,g,u.getNameByIndex(g),o,r,"vertical")))}for(var W in y)y[W].length>0&&(this.finalPLMap[W]=this.finalPLMap[W]||[],this.finalPLMap[W].push(y[W]),y[W]=[]);this._calculMarkMapXY(n,i,"x"),this._buildBorkenLine(e,this.finalPLMap,u,"vertical")},_buildOther:function(e,t,i,n){for(var a,o=this.series,r={},s=0,l=i.length;l>s;s++)for(var h=0,m=i[s].length;m>h;h++){var V=i[s][h],U=o[V];a=this.component.xAxis.getAxis(U.xAxisIndex||0);var d=this.component.yAxis.getAxis(U.yAxisIndex||0),p=d.getCoord(0);r[V]=r[V]||[],n[V]=n[V]||{min0:Number.POSITIVE_INFINITY,min1:Number.POSITIVE_INFINITY,max0:Number.NEGATIVE_INFINITY,max1:Number.NEGATIVE_INFINITY,sum0:0,sum1:0,counter0:0,counter1:0,average0:0,average1:0};for(var c=0,u=U.data.length;u>c;c++){var y=U.data[c],g=this.getDataFromOption(y,"-");if(g instanceof Array){var b=a.getCoord(g[0]),f=d.getCoord(g[1]);r[V].push([b,f,c,g[0],b,p]),n[V].min0>g[0]&&(n[V].min0=g[0],n[V].minY0=f,n[V].minX0=b),n[V].max0g[1]&&(n[V].min1=g[1],n[V].minY1=f,n[V].minX1=b),n[V].max10&&(this.finalPLMap[k]=this.finalPLMap[k]||[],this.finalPLMap[k].push(r[k]),r[k]=[]);this._calculMarkMapXY(n,i,"xy"),this._buildBorkenLine(e,this.finalPLMap,a,"other")},_buildBorkenLine:function(e,t,i,n){for(var o,s="other"==n?"horizontal":n,V=this.series,U=e.length-1;U>=0;U--){var d=e[U],p=V[d],c=t[d];if(p.type===this.type&&null!=c)for(var u=this._getBbox(d,s),y=this._sIndex2ColorMap[d],g=this.query(p,"itemStyle.normal.lineStyle.width"),b=this.query(p,"itemStyle.normal.lineStyle.type"),f=this.query(p,"itemStyle.normal.lineStyle.color"),k=this.getItemStyleColor(this.query(p,"itemStyle.normal.color"),d,-1),x=null!=this.query(p,"itemStyle.normal.areaStyle"),_=this.query(p,"itemStyle.normal.areaStyle.color"),L=0,W=c.length;W>L;L++){var X=c[L],v="other"!=n&&this._isLarge(s,X);if(v)X=this._getLargePointList(s,X,p.dataFilter);else for(var w=0,K=X.length;K>w;w++)o=p.data[X[w][2]],(this.deepQuery([o,p,this.option],"calculable")||this.deepQuery([o,p],"showAllSymbol")||"categoryAxis"===i.type&&i.isMainAxis(X[w][2])&&"none"!=this.deepQuery([o,p],"symbol"))&&this.shapeList.push(this._getSymbol(d,X[w][2],X[w][3],X[w][0],X[w][1],s));var I=new a({zlevel:p.zlevel,z:p.z,style:{miterLimit:g,pointList:X,strokeColor:f||k||y,lineWidth:g,lineType:b,smooth:this._getSmooth(p.smooth),smoothConstraint:u,shadowColor:this.query(p,"itemStyle.normal.lineStyle.shadowColor"),shadowBlur:this.query(p,"itemStyle.normal.lineStyle.shadowBlur"),shadowOffsetX:this.query(p,"itemStyle.normal.lineStyle.shadowOffsetX"),shadowOffsetY:this.query(p,"itemStyle.normal.lineStyle.shadowOffsetY")},hoverable:!1,_main:!0,_seriesIndex:d,_orient:s});if(l.pack(I,V[d],d,0,L,V[d].name),this.shapeList.push(I),x){var J=new r({zlevel:p.zlevel,z:p.z,style:{miterLimit:g,pointList:h.clone(X).concat([[X[X.length-1][4],X[X.length-1][5]],[X[0][4],X[0][5]]]),brushType:"fill",smooth:this._getSmooth(p.smooth),smoothConstraint:u,color:_?_:m.alpha(y,.5)},highlightStyle:{brushType:"fill"},hoverable:!1,_main:!0,_seriesIndex:d,_orient:s});l.pack(J,V[d],d,0,L,V[d].name),this.shapeList.push(J)}}}},_getBbox:function(e,t){var i=this.component.grid.getBbox(),n=this.xMarkMap[e];return null!=n.minX0?[[Math.min(n.minX0,n.maxX0,n.minX1,n.maxX1),Math.min(n.minY0,n.maxY0,n.minY1,n.maxY1)],[Math.max(n.minX0,n.maxX0,n.minX1,n.maxX1),Math.max(n.minY0,n.maxY0,n.minY1,n.maxY1)]]:("horizontal"===t?(i[0][1]=Math.min(n.minY,n.maxY),i[1][1]=Math.max(n.minY,n.maxY)):(i[0][0]=Math.min(n.minX,n.maxX),i[1][0]=Math.max(n.minX,n.maxX)),i)},_isLarge:function(e,t){return t.length<2?!1:"horizontal"===e?Math.abs(t[0][0]-t[1][0])<.5:Math.abs(t[0][1]-t[1][1])<.5},_getLargePointList:function(e,t,i){var n;n="horizontal"===e?this.component.grid.getWidth():this.component.grid.getHeight();var a=t.length,o=[];if("function"!=typeof i)switch(i){case"min":i=function(e){return Math.max.apply(null,e)};break;case"max":i=function(e){return Math.min.apply(null,e)};break;case"average":i=function(e){for(var t=0,i=0;is;s++){var l=Math.floor(a/n*s),h=Math.min(Math.floor(a/n*(s+1)),a);if(!(l>=h)){for(var m=l;h>m;m++)r[m-l]="horizontal"===e?t[m][1]:t[m][0];r.length=h-l;for(var V=i(r),U=-1,d=1/0,m=l;h>m;m++){var p="horizontal"===e?t[m][1]:t[m][0],c=Math.abs(p-V);d>c&&(U=m,d=c)}var u=t[U].slice();"horizontal"===e?u[1]=V:u[0]=V,o.push(u)}}return o},_getSmooth:function(e){return e?.3:0},_getCalculableItem:function(e,t,i,n,a,o){var r=this.series,l=r[e].calculableHolderColor||this.ecTheme.calculableHolderColor||s.calculableHolderColor,h=this._getSymbol(e,t,i,n,a,o);return h.style.color=l,h.style.strokeColor=l,h.rotation=[0,0],h.hoverable=!1,h.draggable=!1,h.style.text=void 0,h},_getSymbol:function(e,t,i,n,a,o){var r=this.series,s=r[e],l=s.data[t],h=this.getSymbolShape(s,e,l,t,i,n,a,this._sIndex2ShapeMap[e],this._sIndex2ColorMap[e],"#fff","vertical"===o?"horizontal":"vertical");return h.zlevel=s.zlevel,h.z=s.z+1,this.deepQuery([l,s,this.option],"calculable")&&(this.setCalculable(h),h.draggable=!0),h},getMarkCoord:function(e,t){var i=this.series[e],n=this.xMarkMap[e],a=this.component.xAxis.getAxis(i.xAxisIndex),o=this.component.yAxis.getAxis(i.yAxisIndex);if(t.type&&("max"===t.type||"min"===t.type||"average"===t.type)){var r=null!=t.valueIndex?t.valueIndex:null!=n.maxX0?"1":"";return[n[t.type+"X"+r],n[t.type+"Y"+r],n[t.type+"Line"+r],n[t.type+r]]}return["string"!=typeof t.xAxis&&a.getCoordByIndex?a.getCoordByIndex(t.xAxis||0):a.getCoord(t.xAxis||0),"string"!=typeof t.yAxis&&o.getCoordByIndex?o.getCoordByIndex(t.yAxis||0):o.getCoord(t.yAxis||0)]},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()},ontooltipHover:function(e,t){for(var i,n,a=e.seriesIndex,o=e.dataIndex,r=a.length;r--;)if(i=this.finalPLMap[a[r]])for(var s=0,l=i.length;l>s;s++){n=i[s];for(var h=0,m=n.length;m>h;h++)o===n[h][2]&&t.push(this._getSymbol(a[r],n[h][2],n[h][3],n[h][0],n[h][1],"horizontal"))}},addDataAnimation:function(e,t){function i(){c--,0===c&&t&&t()}function n(e){e.style.controlPointList=null}for(var a=this.series,o={},r=0,s=e.length;s>r;r++)o[e[r][0]]=e[r];for(var l,h,m,V,U,d,p,c=0,r=this.shapeList.length-1;r>=0;r--)if(U=this.shapeList[r]._seriesIndex,o[U]&&!o[U][3]){if(this.shapeList[r]._main&&this.shapeList[r].style.pointList.length>1){if(d=this.shapeList[r].style.pointList,h=Math.abs(d[0][0]-d[1][0]),V=Math.abs(d[0][1]-d[1][1]),p="horizontal"===this.shapeList[r]._orient,o[U][2]){if("half-smooth-polygon"===this.shapeList[r].type){var u=d.length;this.shapeList[r].style.pointList[u-3]=d[u-2],this.shapeList[r].style.pointList[u-3][p?0:1]=d[u-4][p?0:1],this.shapeList[r].style.pointList[u-2]=d[u-1]}this.shapeList[r].style.pointList.pop(),p?(l=h,m=0):(l=0,m=-V)}else{if(this.shapeList[r].style.pointList.shift(),"half-smooth-polygon"===this.shapeList[r].type){var y=this.shapeList[r].style.pointList.pop();p?y[0]=d[0][0]:y[1]=d[0][1],this.shapeList[r].style.pointList.push(y)}p?(l=-h,m=0):(l=0,m=V)}this.shapeList[r].style.controlPointList=null,this.zr.modShape(this.shapeList[r])}else{if(o[U][2]&&this.shapeList[r]._dataIndex===a[U].data.length-1){this.zr.delShape(this.shapeList[r].id);continue}if(!o[U][2]&&0===this.shapeList[r]._dataIndex){this.zr.delShape(this.shapeList[r].id);continue}}this.shapeList[r].position=[0,0],c++,this.zr.animate(this.shapeList[r].id,"").when(this.query(this.option,"animationDurationUpdate"),{position:[l,m]}).during(n).done(i).start()}c||t&&t()}},o.prototype.iconLibrary.legendLineIcon=i,h.inherits(t,n),e("../chart").define("line",t),t}),i("echarts/util/shape/HalfSmoothPolygon",["require","zrender/shape/Base","zrender/shape/util/smoothBezier","zrender/tool/util","zrender/shape/Polygon"],function(e){function t(e){i.call(this,e)}var i=e("zrender/shape/Base"),n=e("zrender/shape/util/smoothBezier"),a=e("zrender/tool/util");return t.prototype={type:"half-smooth-polygon",buildPath:function(t,i){var a=i.pointList;if(!(a.length<2))if(i.smooth){var o=n(a.slice(0,-2),i.smooth,!1,i.smoothConstraint);t.moveTo(a[0][0],a[0][1]);for(var r,s,l,h=a.length,m=0;h-3>m;m++)r=o[2*m],s=o[2*m+1],l=a[m+1],t.bezierCurveTo(r[0],r[1],s[0],s[1],l[0],l[1]);t.lineTo(a[h-2][0],a[h-2][1]),t.lineTo(a[h-1][0],a[h-1][1]),t.lineTo(a[0][0],a[0][1])}else e("zrender/shape/Polygon").prototype.buildPath(t,i)}},a.inherits(t,i),t}),i("echarts/chart/bar",["require","./base","zrender/shape/Rectangle","../component/axis","../component/grid","../component/dataZoom","../config","../util/ecData","zrender/tool/util","zrender/tool/color","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Rectangle");e("../component/axis"),e("../component/grid"),e("../component/dataZoom");var a=e("../config");a.bar={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,xAxisIndex:0,yAxisIndex:0,barMinHeight:0,barGap:"30%",barCategoryGap:"20%",itemStyle:{normal:{barBorderColor:"#fff",barBorderRadius:0,barBorderWidth:0,label:{show:!1}},emphasis:{barBorderColor:"#fff",barBorderRadius:0,barBorderWidth:0,label:{show:!1}}}};var o=e("../util/ecData"),r=e("zrender/tool/util"),s=e("zrender/tool/color");return t.prototype={type:a.CHART_TYPE_BAR,_buildShape:function(){this._buildPosition()},_buildNormal:function(e,t,i,o,r){for(var s,l,h,m,V,U,d,p,c,u,y,g,b=this.series,f=i[0][0],k=b[f],x="horizontal"==r,_=this.component.xAxis,L=this.component.yAxis,W=x?_.getAxis(k.xAxisIndex):L.getAxis(k.yAxisIndex),X=this._mapSize(W,i),v=X.gap,w=X.barGap,K=X.barWidthMap,I=X.barMaxWidthMap,J=X.barWidth,C=X.barMinHeightMap,S=X.interval,E=this.deepQuery([this.ecTheme,a],"island.r"),F=0,T=t;T>F&&null!=W.getNameByIndex(F);F++){x?m=W.getCoordByIndex(F)-v/2:V=W.getCoordByIndex(F)+v/2;for(var z=0,A=i.length;A>z;z++){var M=b[i[z][0]].yAxisIndex||0,O=b[i[z][0]].xAxisIndex||0;s=x?L.getAxis(M):_.getAxis(O),d=U=c=p=s.getCoord(0);for(var P=0,D=i[z].length;D>P;P++)f=i[z][P],k=b[f],y=k.data[F],g=this.getDataFromOption(y,"-"),o[f]=o[f]||{min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY,sum:0,counter:0,average:0},h=Math.min(I[f]||Number.MAX_VALUE,K[f]||J),"-"!==g&&(g>0?(l=P>0?s.getCoordSize(g):x?d-s.getCoord(g):s.getCoord(g)-d,1===D&&C[f]>l&&(l=C[f]),x?(U-=l,V=U):(m=U,U+=l)):0>g?(l=P>0?s.getCoordSize(g):x?s.getCoord(g)-c:c-s.getCoord(g),1===D&&C[f]>l&&(l=C[f]),x?(V=p,p+=l):(p-=l,m=p)):(l=0,x?(U-=l,V=U):(m=U,U+=l)),o[f][F]=x?m+h/2:V-h/2,o[f].min>g&&(o[f].min=g,x?(o[f].minY=V,o[f].minX=o[f][F]):(o[f].minX=m+l,o[f].minY=o[f][F])),o[f].maxP;P++)f=i[z][P],k=b[f],y=k.data[F],g=this.getDataFromOption(y,"-"),h=Math.min(I[f]||Number.MAX_VALUE,K[f]||J),"-"==g&&this.deepQuery([y,k,this.option],"calculable")&&(x?(U-=E,V=U):(m=U,U+=E),u=this._getBarItem(f,F,W.getNameByIndex(F),m,V-(x?0:h),x?h:E,x?E:h,x?"vertical":"horizontal"),u.hoverable=!1,u.draggable=!1,u.style.lineWidth=1,u.style.brushType="stroke",u.style.strokeColor=k.calculableHolderColor||this.ecTheme.calculableHolderColor||a.calculableHolderColor,this.shapeList.push(new n(u)));x?m+=h+w:V-=h+w}}this._calculMarkMapXY(o,i,x?"y":"x")},_buildHorizontal:function(e,t,i,n){return this._buildNormal(e,t,i,n,"horizontal")},_buildVertical:function(e,t,i,n){return this._buildNormal(e,t,i,n,"vertical")},_buildOther:function(e,t,i,a){for(var o=this.series,r=0,s=i.length;s>r;r++)for(var l=0,h=i[r].length;h>l;l++){var m=i[r][l],V=o[m],U=V.xAxisIndex||0,d=this.component.xAxis.getAxis(U),p=d.getCoord(0),c=V.yAxisIndex||0,u=this.component.yAxis.getAxis(c),y=u.getCoord(0);a[m]=a[m]||{min0:Number.POSITIVE_INFINITY,min1:Number.POSITIVE_INFINITY,max0:Number.NEGATIVE_INFINITY,max1:Number.NEGATIVE_INFINITY,sum0:0,sum1:0,counter0:0,counter1:0,average0:0,average1:0};for(var g=0,b=V.data.length;b>g;g++){var f=V.data[g],k=this.getDataFromOption(f,"-");if(k instanceof Array){var x,_,L=d.getCoord(k[0]),W=u.getCoord(k[1]),X=[f,V],v=this.deepQuery(X,"barWidth")||10,w=this.deepQuery(X,"barHeight");null!=w?(x="horizontal",k[0]>0?(v=L-p,L-=v):v=k[0]<0?p-L:0,_=this._getBarItem(m,g,k[0],L,W-w/2,v,w,x)):(x="vertical",k[1]>0?w=y-W:k[1]<0?(w=W-y,W-=w):w=0,_=this._getBarItem(m,g,k[0],L-v/2,W,v,w,x)),this.shapeList.push(new n(_)),L=d.getCoord(k[0]),W=u.getCoord(k[1]),a[m].min0>k[0]&&(a[m].min0=k[0],a[m].minY0=W,a[m].minX0=L),a[m].max0k[1]&&(a[m].min1=k[1],a[m].minY1=W,a[m].minX1=L),a[m].max1=a&&(d=Math.floor(t.length/n),a=1);else if(n="string"==typeof U&&U.match(/%$/)?(e.getGap()*(100-parseFloat(U))/100).toFixed(2)-0:e.getGap()-U,"string"==typeof V&&V.match(/%$/)?(V=parseFloat(V)/100,a=+((n-m)/((t.length-1)*V+t.length-h)).toFixed(2),V=a*V):(V=parseFloat(V),a=+((n-m-V*(t.length-1))/(t.length-h)).toFixed(2)),0>=a)return this._mapSize(e,t,!0)}else if(n=h>1?"string"==typeof U&&U.match(/%$/)?+(e.getGap()*(100-parseFloat(U))/100).toFixed(2):e.getGap()-U:m,a=0,V=h>1?+((n-m)/(h-1)).toFixed(2):0,0>V)return this._mapSize(e,t,!0);return this._recheckBarMaxWidth(t,r,s,l,n,a,V,d)},_findSpecialBarSzie:function(e,t){for(var i,n,a,o,r=this.series,s={},l={},h={},m=0,V=0,U=0,d=e.length;d>U;U++)for(var p={barWidth:!1,barMaxWidth:!1},c=0,u=e[U].length;u>c;c++){var y=e[U][c],g=r[y];if(!t){if(p.barWidth)s[y]=i;else if(i=this.query(g,"barWidth"),null!=i){s[y]=i,V+=i,m++,p.barWidth=!0;for(var b=0,f=c;f>b;b++){var k=e[U][b];s[k]=i}}if(p.barMaxWidth)l[y]=n;else if(n=this.query(g,"barMaxWidth"),null!=n){l[y]=n,p.barMaxWidth=!0;for(var b=0,f=c;f>b;b++){var k=e[U][b];l[k]=n}}}h[y]=this.query(g,"barMinHeight"),a=null!=a?a:this.query(g,"barGap"),o=null!=o?o:this.query(g,"barCategoryGap")}return{barWidthMap:s,barMaxWidthMap:l,barMinHeightMap:h,sBarWidth:i,sBarMaxWidth:n,sBarWidthCounter:m,sBarWidthTotal:V,barGap:a,barCategoryGap:o}},_recheckBarMaxWidth:function(e,t,i,n,a,o,r,s){for(var l=0,h=e.length;h>l;l++){var m=e[l][0];i[m]&&i[m]0&&b.height>g&&b.width>g?(b.y+=g/2,b.height-=g,b.x+=g/2,b.width-=g):b.brushType="fill",m.highlightStyle.textColor=m.highlightStyle.color,m=this.addLabel(m,U,d,i,h);for(var f=[b,m.highlightStyle],k=0,x=f.length;x>k;k++){var _=f[k].textPosition;if("insideLeft"===_||"insideRight"===_||"insideTop"===_||"insideBottom"===_){var L=5;switch(_){case"insideLeft":f[k].textX=b.x+L,f[k].textY=b.y+b.height/2,f[k].textAlign="left",f[k].textBaseline="middle";break;case"insideRight":f[k].textX=b.x+b.width-L,f[k].textY=b.y+b.height/2,f[k].textAlign="right",f[k].textBaseline="middle";break;case"insideTop":f[k].textX=b.x+b.width/2,f[k].textY=b.y+L/2,f[k].textAlign="center",f[k].textBaseline="top";break;case"insideBottom":f[k].textX=b.x+b.width/2,f[k].textY=b.y+b.height-L/2,f[k].textAlign="center",f[k].textBaseline="bottom"}f[k].textPosition="specific",f[k].textColor=f[k].textColor||"#fff"}}return this.deepQuery([d,U,this.option],"calculable")&&(this.setCalculable(m),m.draggable=!0),o.pack(m,V[e],e,V[e].data[t],t,i),m},getMarkCoord:function(e,t){var i,n,a=this.series[e],o=this.xMarkMap[e],r=this.component.xAxis.getAxis(a.xAxisIndex),s=this.component.yAxis.getAxis(a.yAxisIndex);if(!t.type||"max"!==t.type&&"min"!==t.type&&"average"!==t.type)if(o.isHorizontal){i="string"==typeof t.xAxis&&r.getIndexByName?r.getIndexByName(t.xAxis):t.xAxis||0;var l=o[i];l=null!=l?l:"string"!=typeof t.xAxis&&r.getCoordByIndex?r.getCoordByIndex(t.xAxis||0):r.getCoord(t.xAxis||0),n=[l,s.getCoord(t.yAxis||0)]}else{i="string"==typeof t.yAxis&&s.getIndexByName?s.getIndexByName(t.yAxis):t.yAxis||0;var h=o[i];h=null!=h?h:"string"!=typeof t.yAxis&&s.getCoordByIndex?s.getCoordByIndex(t.yAxis||0):s.getCoord(t.yAxis||0),n=[r.getCoord(t.xAxis||0),h]}else{var m=null!=t.valueIndex?t.valueIndex:null!=o.maxX0?"1":"";n=[o[t.type+"X"+m],o[t.type+"Y"+m],o[t.type+"Line"+m],o[t.type+m]]}return n},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()},addDataAnimation:function(e,t){function i(){c--,0===c&&t&&t()}for(var n=this.series,a={},r=0,s=e.length;s>r;r++)a[e[r][0]]=e[r];for(var l,h,m,V,U,d,p,c=0,r=this.shapeList.length-1;r>=0;r--)if(d=o.get(this.shapeList[r],"seriesIndex"),a[d]&&!a[d][3]&&"rectangle"===this.shapeList[r].type){if(p=o.get(this.shapeList[r],"dataIndex"),U=n[d],a[d][2]&&p===U.data.length-1){this.zr.delShape(this.shapeList[r].id);continue}if(!a[d][2]&&0===p){this.zr.delShape(this.shapeList[r].id);continue}"horizontal"===this.shapeList[r]._orient?(V=this.component.yAxis.getAxis(U.yAxisIndex||0).getGap(),m=a[d][2]?-V:V,l=0):(h=this.component.xAxis.getAxis(U.xAxisIndex||0).getGap(),l=a[d][2]?h:-h,m=0),this.shapeList[r].position=[0,0],c++,this.zr.animate(this.shapeList[r].id,"").when(this.query(this.option,"animationDurationUpdate"),{position:[l,m]}).done(i).start()}c||t&&t()}},r.inherits(t,i),e("../chart").define("bar",t),t}),i("echarts/chart/scatter",["require","./base","../util/shape/Symbol","../component/axis","../component/grid","../component/dataZoom","../component/dataRange","../config","zrender/tool/util","zrender/tool/color","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e("./base"),n=e("../util/shape/Symbol");e("../component/axis"),e("../component/grid"),e("../component/dataZoom"),e("../component/dataRange");var a=e("../config");a.scatter={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,xAxisIndex:0,yAxisIndex:0,symbolSize:4,large:!1,largeThreshold:2e3,itemStyle:{normal:{label:{show:!1}},emphasis:{label:{show:!1}}}};var o=e("zrender/tool/util"),r=e("zrender/tool/color");return t.prototype={type:a.CHART_TYPE_SCATTER,_buildShape:function(){var e=this.series;this._sIndex2ColorMap={},this._symbol=this.option.symbolList,this._sIndex2ShapeMap={},this.selectedMap={},this.xMarkMap={};for(var t,i,n,o,s=this.component.legend,l=[],h=0,m=e.length;m>h;h++)if(t=e[h],i=t.name,t.type===a.CHART_TYPE_SCATTER){if(e[h]=this.reformOption(e[h]),this.legendHoverLink=e[h].legendHoverLink||this.legendHoverLink,this._sIndex2ShapeMap[h]=this.query(t,"symbol")||this._symbol[h%this._symbol.length],s){if(this.selectedMap[i]=s.isSelected(i),this._sIndex2ColorMap[h]=r.alpha(s.getColor(i),.5),n=s.getItemShape(i)){var o=this._sIndex2ShapeMap[h];n.style.brushType=o.match("empty")?"stroke":"both",o=o.replace("empty","").toLowerCase(),o.match("rectangle")&&(n.style.x+=Math.round((n.style.width-n.style.height)/2),n.style.width=n.style.height),o.match("star")&&(n.style.n=o.replace("star","")-0||5,o="star"),o.match("image")&&(n.style.image=o.replace(new RegExp("^image:\\/\\/"),""),n.style.x+=Math.round((n.style.width-n.style.height)/2),n.style.width=n.style.height,o="image"),n.style.iconType=o,s.setItemShape(i,n)}}else this.selectedMap[i]=!0,this._sIndex2ColorMap[h]=r.alpha(this.zr.getColor(h),.5);this.selectedMap[i]&&l.push(h)}this._buildSeries(l),this.addShapeList()},_buildSeries:function(e){if(0!==e.length){for(var t,i,n,a,o,r,s,l,h=this.series,m={},V=0,U=e.length;U>V;V++)if(t=e[V],i=h[t],0!==i.data.length){o=this.component.xAxis.getAxis(i.xAxisIndex||0),r=this.component.yAxis.getAxis(i.yAxisIndex||0),m[t]=[];for(var d=0,p=i.data.length;p>d;d++)n=i.data[d],a=this.getDataFromOption(n,"-"),"-"===a||a.length<2||(s=o.getCoord(a[0]),l=r.getCoord(a[1]),m[t].push([s,l,d,n.name||""]));this.xMarkMap[t]=this._markMap(o,r,i.data,m[t]),this.buildMark(t)}this._buildPointList(m)}},_markMap:function(e,t,i,n){for(var a,o={min0:Number.POSITIVE_INFINITY,max0:Number.NEGATIVE_INFINITY,sum0:0,counter0:0,average0:0,min1:Number.POSITIVE_INFINITY,max1:Number.NEGATIVE_INFINITY,sum1:0,counter1:0,average1:0},r=0,s=n.length;s>r;r++)a=i[n[r][2]].value||i[n[r][2]],o.min0>a[0]&&(o.min0=a[0],o.minY0=n[r][1],o.minX0=n[r][0]),o.max0a[1]&&(o.min1=a[1],o.minY1=n[r][1],o.minX1=n[r][0]),o.max1t.largeThreshold)this.shapeList.push(this._getLargeSymbol(t,i,this.getItemStyleColor(this.query(t,"itemStyle.normal.color"),r,-1)||this._sIndex2ColorMap[r]));else for(var s=0,l=i.length;l>s;s++)n=i[s],a=this._getSymbol(r,n[2],n[3],n[0],n[1]),a&&this.shapeList.push(a)},_getSymbol:function(e,t,i,n,a){var o,r=this.series,s=r[e],l=s.data[t],h=this.component.dataRange;if(h){if(o=isNaN(l[2])?this._sIndex2ColorMap[e]:h.getColor(l[2]),!o)return null}else o=this._sIndex2ColorMap[e];var m=this.getSymbolShape(s,e,l,t,i,n,a,this._sIndex2ShapeMap[e],o,"rgba(0,0,0,0)","vertical");return m.zlevel=s.zlevel,m.z=s.z,m._main=!0,m},_getLargeSymbol:function(e,t,i){return new n({zlevel:e.zlevel,z:e.z,_main:!0,hoverable:!1,style:{pointList:t,color:i,strokeColor:i},highlightStyle:{pointList:[]}})},getMarkCoord:function(e,t){var i,n=this.series[e],a=this.xMarkMap[e],o=this.component.xAxis.getAxis(n.xAxisIndex),r=this.component.yAxis.getAxis(n.yAxisIndex);if(!t.type||"max"!==t.type&&"min"!==t.type&&"average"!==t.type)i=["string"!=typeof t.xAxis&&o.getCoordByIndex?o.getCoordByIndex(t.xAxis||0):o.getCoord(t.xAxis||0),"string"!=typeof t.yAxis&&r.getCoordByIndex?r.getCoordByIndex(t.yAxis||0):r.getCoord(t.yAxis||0)];else{var s=null!=t.valueIndex?t.valueIndex:1;i=[a[t.type+"X"+s],a[t.type+"Y"+s],a[t.type+"Line"+s],a[t.type+s]]}return i},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()},ondataRange:function(e,t){this.component.dataRange&&(this.refresh(),t.needRefresh=!0)}},o.inherits(t,i),e("../chart").define("scatter",t),t}),i("echarts/component/dataRange",["require","./base","zrender/shape/Text","zrender/shape/Rectangle","../util/shape/HandlePolygon","../config","zrender/tool/util","zrender/tool/event","zrender/tool/area","zrender/tool/color","../component"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o);var s=this;s._ondrift=function(e,t){return s.__ondrift(this,e,t)},s._ondragend=function(){return s.__ondragend()},s._dataRangeSelected=function(e){return s.__dataRangeSelected(e)},s._dispatchHoverLink=function(e){return s.__dispatchHoverLink(e)},s._onhoverlink=function(e){return s.__onhoverlink(e); + +},this._selectedMap={},this._range={},this.refresh(a),t.bind(r.EVENT.HOVER,this._onhoverlink)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Rectangle"),o=e("../util/shape/HandlePolygon"),r=e("../config");r.dataRange={zlevel:0,z:4,show:!0,orient:"vertical",x:"left",y:"bottom",backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,padding:5,itemGap:10,itemWidth:20,itemHeight:14,precision:0,splitNumber:5,splitList:null,calculable:!1,selectedMode:!0,hoverLink:!0,realtime:!0,color:["#006edd","#e0ffff"],textStyle:{color:"#333"}};var s=e("zrender/tool/util"),l=e("zrender/tool/event"),h=e("zrender/tool/area"),m=e("zrender/tool/color");return t.prototype={type:r.COMPONENT_TYPE_DATARANGE,_textGap:10,_buildShape:function(){if(this._itemGroupLocation=this._getItemGroupLocation(),this._buildBackground(),this._isContinuity()?this._buildGradient():this._buildItem(),this.dataRangeOption.show)for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e]);this._syncShapeFromRange()},_buildItem:function(){var e,t,i,o,r=this._valueTextList,s=r.length,l=this.getFont(this.dataRangeOption.textStyle),m=this._itemGroupLocation.x,V=this._itemGroupLocation.y,U=this.dataRangeOption.itemWidth,d=this.dataRangeOption.itemHeight,p=this.dataRangeOption.itemGap,c=h.getTextHeight("国",l);"vertical"==this.dataRangeOption.orient&&"right"==this.dataRangeOption.x&&(m=this._itemGroupLocation.x+this._itemGroupLocation.width-U);var u=!0;this.dataRangeOption.text&&(u=!1,this.dataRangeOption.text[0]&&(i=this._getTextShape(m,V,this.dataRangeOption.text[0]),"horizontal"==this.dataRangeOption.orient?m+=h.getTextWidth(this.dataRangeOption.text[0],l)+this._textGap:(V+=c+this._textGap,i.style.y+=c/2+this._textGap,i.style.textBaseline="bottom"),this.shapeList.push(new n(i))));for(var y=0;s>y;y++)e=r[y],o=this.getColorByIndex(y),t=this._getItemShape(m,V,U,d,this._selectedMap[y]?o:"#ccc"),t._idx=y,t.onmousemove=this._dispatchHoverLink,this.dataRangeOption.selectedMode&&(t.clickable=!0,t.onclick=this._dataRangeSelected),this.shapeList.push(new a(t)),u&&(i={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:m+U+5,y:V,color:this._selectedMap[y]?this.dataRangeOption.textStyle.color:"#ccc",text:r[y],textFont:l,textBaseline:"top"},highlightStyle:{brushType:"fill"}},"vertical"==this.dataRangeOption.orient&&"right"==this.dataRangeOption.x&&(i.style.x-=U+10,i.style.textAlign="right"),i._idx=y,i.onmousemove=this._dispatchHoverLink,this.dataRangeOption.selectedMode&&(i.clickable=!0,i.onclick=this._dataRangeSelected),this.shapeList.push(new n(i))),"horizontal"==this.dataRangeOption.orient?m+=U+(u?5:0)+(u?h.getTextWidth(e,l):0)+p:V+=d+p;!u&&this.dataRangeOption.text[1]&&("horizontal"==this.dataRangeOption.orient?m=m-p+this._textGap:V=V-p+this._textGap,i=this._getTextShape(m,V,this.dataRangeOption.text[1]),"horizontal"!=this.dataRangeOption.orient&&(i.style.y-=5,i.style.textBaseline="top"),this.shapeList.push(new n(i)))},_buildGradient:function(){var t,i,o=this.getFont(this.dataRangeOption.textStyle),r=this._itemGroupLocation.x,s=this._itemGroupLocation.y,l=this.dataRangeOption.itemWidth,m=this.dataRangeOption.itemHeight,V=h.getTextHeight("国",o),U=10,d=!0;this.dataRangeOption.text&&(d=!1,this.dataRangeOption.text[0]&&(i=this._getTextShape(r,s,this.dataRangeOption.text[0]),"horizontal"==this.dataRangeOption.orient?r+=h.getTextWidth(this.dataRangeOption.text[0],o)+this._textGap:(s+=V+this._textGap,i.style.y+=V/2+this._textGap,i.style.textBaseline="bottom"),this.shapeList.push(new n(i))));for(var p=e("zrender/tool/color"),c=1/(this.dataRangeOption.color.length-1),u=[],y=0,g=this.dataRangeOption.color.length;g>y;y++)u.push([y*c,this.dataRangeOption.color[y]]);"horizontal"==this.dataRangeOption.orient?(t={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:r,y:s,width:l*U,height:m,color:p.getLinearGradient(r,s,r+l*U,s,u)},hoverable:!1},r+=l*U+this._textGap):(t={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:r,y:s,width:l,height:m*U,color:p.getLinearGradient(r,s,r,s+m*U,u)},hoverable:!1},s+=m*U+this._textGap),this.shapeList.push(new a(t)),this._calculableLocation=t.style,this.dataRangeOption.calculable&&(this._buildFiller(),this._bulidMask(),this._bulidHandle()),this._buildIndicator(),!d&&this.dataRangeOption.text[1]&&(i=this._getTextShape(r,s,this.dataRangeOption.text[1]),this.shapeList.push(new n(i)))},_buildIndicator:function(){var e,t,i=this._calculableLocation.x,n=this._calculableLocation.y,a=this._calculableLocation.width,r=this._calculableLocation.height,s=5;"horizontal"==this.dataRangeOption.orient?"bottom"!=this.dataRangeOption.y?(e=[[i,n+r],[i-s,n+r+s],[i+s,n+r+s]],t="bottom"):(e=[[i,n],[i-s,n-s],[i+s,n-s]],t="top"):"right"!=this.dataRangeOption.x?(e=[[i+a,n],[i+a+s,n-s],[i+a+s,n+s]],t="right"):(e=[[i,n],[i-s,n-s],[i-s,n+s]],t="left"),this._indicatorShape={style:{pointList:e,color:"#fff",__rect:{x:Math.min(e[0][0],e[1][0]),y:Math.min(e[0][1],e[1][1]),width:s*("horizontal"==this.dataRangeOption.orient?2:1),height:s*("horizontal"==this.dataRangeOption.orient?1:2)}},highlightStyle:{brushType:"fill",textPosition:t,textColor:this.dataRangeOption.textStyle.color},hoverable:!1},this._indicatorShape=new o(this._indicatorShape)},_buildFiller:function(){this._fillerShape={zlevel:this.getZlevelBase(),z:this.getZBase()+1,style:{x:this._calculableLocation.x,y:this._calculableLocation.y,width:this._calculableLocation.width,height:this._calculableLocation.height,color:"rgba(255,255,255,0)"},highlightStyle:{strokeColor:"rgba(255,255,255,0.5)",lineWidth:1},draggable:!0,ondrift:this._ondrift,ondragend:this._ondragend,onmousemove:this._dispatchHoverLink,_type:"filler"},this._fillerShape=new a(this._fillerShape),this.shapeList.push(this._fillerShape)},_bulidHandle:function(){var e,t,i,n,a,r,s,l,m=this._calculableLocation.x,V=this._calculableLocation.y,U=this._calculableLocation.width,d=this._calculableLocation.height,p=this.getFont(this.dataRangeOption.textStyle),c=h.getTextHeight("国",p),u=Math.max(h.getTextWidth(this._textFormat(this.dataRangeOption.max),p),h.getTextWidth(this._textFormat(this.dataRangeOption.min),p))+2;"horizontal"==this.dataRangeOption.orient?"bottom"!=this.dataRangeOption.y?(e=[[m,V],[m,V+d+c],[m-c,V+d+c],[m-1,V+d],[m-1,V]],t=m-u/2-c,i=V+d+c/2+2,n={x:m-u-c,y:V+d,width:u+c,height:c},a=[[m+U,V],[m+U,V+d+c],[m+U+c,V+d+c],[m+U+1,V+d],[m+U+1,V]],r=m+U+u/2+c,s=i,l={x:m+U,y:V+d,width:u+c,height:c}):(e=[[m,V+d],[m,V-c],[m-c,V-c],[m-1,V],[m-1,V+d]],t=m-u/2-c,i=V-c/2-2,n={x:m-u-c,y:V-c,width:u+c,height:c},a=[[m+U,V+d],[m+U,V-c],[m+U+c,V-c],[m+U+1,V],[m+U+1,V+d]],r=m+U+u/2+c,s=i,l={x:m+U,y:V-c,width:u+c,height:c}):(u+=c,"right"!=this.dataRangeOption.x?(e=[[m,V],[m+U+c,V],[m+U+c,V-c],[m+U,V-1],[m,V-1]],t=m+U+u/2+c/2,i=V-c/2,n={x:m+U,y:V-c,width:u+c,height:c},a=[[m,V+d],[m+U+c,V+d],[m+U+c,V+c+d],[m+U,V+1+d],[m,V+d+1]],r=t,s=V+d+c/2,l={x:m+U,y:V+d,width:u+c,height:c}):(e=[[m+U,V],[m-c,V],[m-c,V-c],[m,V-1],[m+U,V-1]],t=m-u/2-c/2,i=V-c/2,n={x:m-u-c,y:V-c,width:u+c,height:c},a=[[m+U,V+d],[m-c,V+d],[m-c,V+c+d],[m,V+1+d],[m+U,V+d+1]],r=t,s=V+d+c/2,l={x:m-u-c,y:V+d,width:u+c,height:c})),this._startShape={style:{pointList:e,text:this._textFormat(this.dataRangeOption.max),textX:t,textY:i,textFont:p,color:this.getColor(this.dataRangeOption.max),rect:n,x:e[0][0],y:e[0][1],_x:e[0][0],_y:e[0][1]}},this._startShape.highlightStyle={strokeColor:this._startShape.style.color,lineWidth:1},this._endShape={style:{pointList:a,text:this._textFormat(this.dataRangeOption.min),textX:r,textY:s,textFont:p,color:this.getColor(this.dataRangeOption.min),rect:l,x:a[0][0],y:a[0][1],_x:a[0][0],_y:a[0][1]}},this._endShape.highlightStyle={strokeColor:this._endShape.style.color,lineWidth:1},this._startShape.zlevel=this._endShape.zlevel=this.getZlevelBase(),this._startShape.z=this._endShape.z=this.getZBase()+1,this._startShape.draggable=this._endShape.draggable=!0,this._startShape.ondrift=this._endShape.ondrift=this._ondrift,this._startShape.ondragend=this._endShape.ondragend=this._ondragend,this._startShape.style.textColor=this._endShape.style.textColor=this.dataRangeOption.textStyle.color,this._startShape.style.textAlign=this._endShape.style.textAlign="center",this._startShape.style.textPosition=this._endShape.style.textPosition="specific",this._startShape.style.textBaseline=this._endShape.style.textBaseline="middle",this._startShape.style.width=this._endShape.style.width=0,this._startShape.style.height=this._endShape.style.height=0,this._startShape.style.textPosition=this._endShape.style.textPosition="specific",this._startShape=new o(this._startShape),this._endShape=new o(this._endShape),this.shapeList.push(this._startShape),this.shapeList.push(this._endShape)},_bulidMask:function(){var e=this._calculableLocation.x,t=this._calculableLocation.y,i=this._calculableLocation.width,n=this._calculableLocation.height;this._startMask={zlevel:this.getZlevelBase(),z:this.getZBase()+1,style:{x:e,y:t,width:"horizontal"==this.dataRangeOption.orient?0:i,height:"horizontal"==this.dataRangeOption.orient?n:0,color:"#ccc"},hoverable:!1},this._endMask={zlevel:this.getZlevelBase(),z:this.getZBase()+1,style:{x:"horizontal"==this.dataRangeOption.orient?e+i:e,y:"horizontal"==this.dataRangeOption.orient?t:t+n,width:"horizontal"==this.dataRangeOption.orient?0:i,height:"horizontal"==this.dataRangeOption.orient?n:0,color:"#ccc"},hoverable:!1},this._startMask=new a(this._startMask),this._endMask=new a(this._endMask),this.shapeList.push(this._startMask),this.shapeList.push(this._endMask)},_buildBackground:function(){var e=this.reformCssArray(this.dataRangeOption.padding);this.shapeList.push(new a({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._itemGroupLocation.x-e[3],y:this._itemGroupLocation.y-e[0],width:this._itemGroupLocation.width+e[3]+e[1],height:this._itemGroupLocation.height+e[0]+e[2],brushType:0===this.dataRangeOption.borderWidth?"fill":"both",color:this.dataRangeOption.backgroundColor,strokeColor:this.dataRangeOption.borderColor,lineWidth:this.dataRangeOption.borderWidth}}))},_getItemGroupLocation:function(){var e=this._valueTextList,t=e.length,i=this.dataRangeOption.itemGap,n=this.dataRangeOption.itemWidth,a=this.dataRangeOption.itemHeight,o=0,r=0,s=this.getFont(this.dataRangeOption.textStyle),l=h.getTextHeight("国",s),m=10;if("horizontal"==this.dataRangeOption.orient){if(this.dataRangeOption.text||this._isContinuity())o=(this._isContinuity()?n*m+i:t*(n+i))+(this.dataRangeOption.text&&"undefined"!=typeof this.dataRangeOption.text[0]?h.getTextWidth(this.dataRangeOption.text[0],s)+this._textGap:0)+(this.dataRangeOption.text&&"undefined"!=typeof this.dataRangeOption.text[1]?h.getTextWidth(this.dataRangeOption.text[1],s)+this._textGap:0);else{n+=5;for(var V=0;t>V;V++)o+=n+h.getTextWidth(e[V],s)+i}o-=i,r=Math.max(l,a)}else{var U;if(this.dataRangeOption.text||this._isContinuity())r=(this._isContinuity()?a*m+i:t*(a+i))+(this.dataRangeOption.text&&"undefined"!=typeof this.dataRangeOption.text[0]?this._textGap+l:0)+(this.dataRangeOption.text&&"undefined"!=typeof this.dataRangeOption.text[1]?this._textGap+l:0),U=Math.max(h.getTextWidth(this.dataRangeOption.text&&this.dataRangeOption.text[0]||"",s),h.getTextWidth(this.dataRangeOption.text&&this.dataRangeOption.text[1]||"",s)),o=Math.max(n,U);else{r=(a+i)*t,n+=5,U=0;for(var V=0;t>V;V++)U=Math.max(U,h.getTextWidth(e[V],s));o=n+U}r-=i}var d,p=this.reformCssArray(this.dataRangeOption.padding),c=this.zr.getWidth();switch(this.dataRangeOption.x){case"center":d=Math.floor((c-o)/2);break;case"left":d=p[3]+this.dataRangeOption.borderWidth;break;case"right":d=c-o-p[1]-this.dataRangeOption.borderWidth;break;default:d=this.parsePercent(this.dataRangeOption.x,c),d=isNaN(d)?0:d}var u,y=this.zr.getHeight();switch(this.dataRangeOption.y){case"top":u=p[0]+this.dataRangeOption.borderWidth;break;case"bottom":u=y-r-p[2]-this.dataRangeOption.borderWidth;break;case"center":u=Math.floor((y-r)/2);break;default:u=this.parsePercent(this.dataRangeOption.y,y),u=isNaN(u)?0:u}if(this.dataRangeOption.calculable){var g=Math.max(h.getTextWidth(this.dataRangeOption.max,s),h.getTextWidth(this.dataRangeOption.min,s))+l;"horizontal"==this.dataRangeOption.orient?(g>d&&(d=g),d+o+g>c&&(d-=g)):(l>u&&(u=l),u+r+l>y&&(u-=l))}return{x:d,y:u,width:o,height:r}},_getTextShape:function(e,t,i){return{zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:"horizontal"==this.dataRangeOption.orient?e:this._itemGroupLocation.x+this._itemGroupLocation.width/2,y:"horizontal"==this.dataRangeOption.orient?this._itemGroupLocation.y+this._itemGroupLocation.height/2:t,color:this.dataRangeOption.textStyle.color,text:i,textFont:this.getFont(this.dataRangeOption.textStyle),textBaseline:"horizontal"==this.dataRangeOption.orient?"middle":"top",textAlign:"horizontal"==this.dataRangeOption.orient?"left":"center"},hoverable:!1}},_getItemShape:function(e,t,i,n,a){return{zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:e,y:t+1,width:i,height:n-2,color:a},highlightStyle:{strokeColor:a,lineWidth:1}}},__ondrift:function(e,t,i){var n=this._calculableLocation.x,a=this._calculableLocation.y,o=this._calculableLocation.width,r=this._calculableLocation.height;return"horizontal"==this.dataRangeOption.orient?e.style.x+t<=n?e.style.x=n:e.style.x+t+e.style.width>=n+o?e.style.x=n+o-e.style.width:e.style.x+=t:e.style.y+i<=a?e.style.y=a:e.style.y+i+e.style.height>=a+r?e.style.y=a+r-e.style.height:e.style.y+=i,"filler"==e._type?this._syncHandleShape():this._syncFillerShape(e),this.dataRangeOption.realtime&&this._dispatchDataRange(),!0},__ondragend:function(){this.isDragend=!0},ondragend:function(e,t){this.isDragend&&e.target&&(t.dragOut=!0,t.dragIn=!0,this.dataRangeOption.realtime||this._dispatchDataRange(),t.needRefresh=!1,this.isDragend=!1)},_syncShapeFromRange:function(){var e=this.dataRangeOption.range||{},t=e.start,i=e.end;if(t>i&&(t=[i,i=t][0]),this._range.end=null!=t?t:null!=this._range.end?this._range.end:0,this._range.start=null!=i?i:null!=this._range.start?this._range.start:100,100!=this._range.start||0!==this._range.end){if("horizontal"==this.dataRangeOption.orient){var n=this._fillerShape.style.width;this._fillerShape.style.x+=n*(100-this._range.start)/100,this._fillerShape.style.width=n*(this._range.start-this._range.end)/100}else{var a=this._fillerShape.style.height;this._fillerShape.style.y+=a*(100-this._range.start)/100,this._fillerShape.style.height=a*(this._range.start-this._range.end)/100}this.zr.modShape(this._fillerShape.id),this._syncHandleShape()}},_syncHandleShape:function(){var e=this._calculableLocation.x,t=this._calculableLocation.y,i=this._calculableLocation.width,n=this._calculableLocation.height;"horizontal"==this.dataRangeOption.orient?(this._startShape.style.x=this._fillerShape.style.x,this._startMask.style.width=this._startShape.style.x-e,this._endShape.style.x=this._fillerShape.style.x+this._fillerShape.style.width,this._endMask.style.x=this._endShape.style.x,this._endMask.style.width=e+i-this._endShape.style.x,this._range.start=Math.ceil(100-(this._startShape.style.x-e)/i*100),this._range.end=Math.floor(100-(this._endShape.style.x-e)/i*100)):(this._startShape.style.y=this._fillerShape.style.y,this._startMask.style.height=this._startShape.style.y-t,this._endShape.style.y=this._fillerShape.style.y+this._fillerShape.style.height,this._endMask.style.y=this._endShape.style.y,this._endMask.style.height=t+n-this._endShape.style.y,this._range.start=Math.ceil(100-(this._startShape.style.y-t)/n*100),this._range.end=Math.floor(100-(this._endShape.style.y-t)/n*100)),this._syncShape()},_syncFillerShape:function(e){var t,i,n=this._calculableLocation.x,a=this._calculableLocation.y,o=this._calculableLocation.width,r=this._calculableLocation.height;"horizontal"==this.dataRangeOption.orient?(t=this._startShape.style.x,i=this._endShape.style.x,e.id==this._startShape.id&&t>=i?(i=t,this._endShape.style.x=t):e.id==this._endShape.id&&t>=i&&(t=i,this._startShape.style.x=t),this._fillerShape.style.x=t,this._fillerShape.style.width=i-t,this._startMask.style.width=t-n,this._endMask.style.x=i,this._endMask.style.width=n+o-i,this._range.start=Math.ceil(100-(t-n)/o*100),this._range.end=Math.floor(100-(i-n)/o*100)):(t=this._startShape.style.y,i=this._endShape.style.y,e.id==this._startShape.id&&t>=i?(i=t,this._endShape.style.y=t):e.id==this._endShape.id&&t>=i&&(t=i,this._startShape.style.y=t),this._fillerShape.style.y=t,this._fillerShape.style.height=i-t,this._startMask.style.height=t-a,this._endMask.style.y=i,this._endMask.style.height=a+r-i,this._range.start=Math.ceil(100-(t-a)/r*100),this._range.end=Math.floor(100-(i-a)/r*100)),this._syncShape()},_syncShape:function(){this._startShape.position=[this._startShape.style.x-this._startShape.style._x,this._startShape.style.y-this._startShape.style._y],this._startShape.style.text=this._textFormat(this._gap*this._range.start+this.dataRangeOption.min),this._startShape.style.color=this._startShape.highlightStyle.strokeColor=this.getColor(this._gap*this._range.start+this.dataRangeOption.min),this._endShape.position=[this._endShape.style.x-this._endShape.style._x,this._endShape.style.y-this._endShape.style._y],this._endShape.style.text=this._textFormat(this._gap*this._range.end+this.dataRangeOption.min),this._endShape.style.color=this._endShape.highlightStyle.strokeColor=this.getColor(this._gap*this._range.end+this.dataRangeOption.min),this.zr.modShape(this._startShape.id),this.zr.modShape(this._endShape.id),this.zr.modShape(this._startMask.id),this.zr.modShape(this._endMask.id),this.zr.modShape(this._fillerShape.id),this.zr.refreshNextFrame()},_dispatchDataRange:function(){this.messageCenter.dispatch(r.EVENT.DATA_RANGE,null,{range:{start:this._range.end,end:this._range.start}},this.myChart)},__dataRangeSelected:function(e){if("single"===this.dataRangeOption.selectedMode)for(var t in this._selectedMap)this._selectedMap[t]=!1;var i=e.target._idx;this._selectedMap[i]=!this._selectedMap[i];var n,a;this._useCustomizedSplit()?(n=this._splitList[i].max,a=this._splitList[i].min):(n=(this._colorList.length-i)*this._gap+this.dataRangeOption.min,a=n-this._gap),this.messageCenter.dispatch(r.EVENT.DATA_RANGE_SELECTED,e.event,{selected:this._selectedMap,target:i,valueMax:n,valueMin:a},this.myChart),this.messageCenter.dispatch(r.EVENT.REFRESH,null,null,this.myChart)},__dispatchHoverLink:function(e){var t,i;if(this.dataRangeOption.calculable){var n,a=this.dataRangeOption.max-this.dataRangeOption.min;n="horizontal"==this.dataRangeOption.orient?(1-(l.getX(e.event)-this._calculableLocation.x)/this._calculableLocation.width)*a:(1-(l.getY(e.event)-this._calculableLocation.y)/this._calculableLocation.height)*a,t=n-.05*a,i=n+.05*a}else if(this._useCustomizedSplit()){var o=e.target._idx;i=this._splitList[o].max,t=this._splitList[o].min}else{var o=e.target._idx;i=(this._colorList.length-o)*this._gap+this.dataRangeOption.min,t=i-this._gap}this.messageCenter.dispatch(r.EVENT.DATA_RANGE_HOVERLINK,e.event,{valueMin:t,valueMax:i},this.myChart)},__onhoverlink:function(e){if(this.dataRangeOption.show&&this.dataRangeOption.hoverLink&&this._indicatorShape&&e&&null!=e.seriesIndex&&null!=e.dataIndex){var t=e.value;if(""===t||isNaN(t))return;tthis.dataRangeOption.max&&(t=this.dataRangeOption.max),this._indicatorShape.position="horizontal"==this.dataRangeOption.orient?[(this.dataRangeOption.max-t)/(this.dataRangeOption.max-this.dataRangeOption.min)*this._calculableLocation.width,0]:[0,(this.dataRangeOption.max-t)/(this.dataRangeOption.max-this.dataRangeOption.min)*this._calculableLocation.height],this._indicatorShape.style.text=this._textFormat(e.value),this._indicatorShape.style.color=this.getColor(t),this.zr.addHoverShape(this._indicatorShape)}},_textFormat:function(e,t){var i=this.dataRangeOption;if(e!==-Number.MAX_VALUE&&(e=(+e).toFixed(i.precision)),null!=t&&t!==Number.MAX_VALUE&&(t=(+t).toFixed(i.precision)),i.formatter){if("string"==typeof i.formatter)return i.formatter.replace("{value}",e===-Number.MAX_VALUE?"min":e).replace("{value2}",t===Number.MAX_VALUE?"max":t);if("function"==typeof i.formatter)return i.formatter.call(this.myChart,e,t)}return null==t?e:e===-Number.MAX_VALUE?"< "+t:t===Number.MAX_VALUE?"> "+e:e+" - "+t},_isContinuity:function(){var e=this.dataRangeOption;return!(e.splitList?e.splitList.length>0:e.splitNumber>0)||e.calculable},_useCustomizedSplit:function(){var e=this.dataRangeOption;return e.splitList&&e.splitList.length>0},_buildColorList:function(e){if(this._colorList=m.getGradientColors(this.dataRangeOption.color,Math.max((e-this.dataRangeOption.color.length)/(this.dataRangeOption.color.length-1),0)+1),this._colorList.length>e){for(var t=this._colorList.length,i=[this._colorList[0]],n=t/(e-1),a=1;e-1>a;a++)i.push(this._colorList[Math.floor(a*n)]);i.push(this._colorList[t-1]),this._colorList=i}if(this._useCustomizedSplit())for(var o=this._splitList,a=0,t=o.length;t>a;a++)o[a].color&&(this._colorList[a]=o[a].color)},_buildGap:function(e){if(!this._useCustomizedSplit()){var t=this.dataRangeOption.precision;for(this._gap=(this.dataRangeOption.max-this.dataRangeOption.min)/e;this._gap.toFixed(t)-0!=this._gap&&5>t;)t++;this.dataRangeOption.precision=t,this._gap=((this.dataRangeOption.max-this.dataRangeOption.min)/e).toFixed(t)-0}},_buildDataList:function(e){for(var t=this._valueTextList=[],i=this.dataRangeOption,n=this._useCustomizedSplit(),a=0;e>a;a++){this._selectedMap[a]=!0;var o="";if(n){var r=this._splitList[e-1-a];o=null!=r.label?r.label:null!=r.single?this._textFormat(r.single):this._textFormat(r.min,r.max)}else o=this._textFormat(a*this._gap+i.min,(a+1)*this._gap+i.min);t.unshift(o)}},_buildSplitList:function(){if(this._useCustomizedSplit())for(var e=this.dataRangeOption.splitList,t=this._splitList=[],i=0,n=e.length;n>i;i++){var a=e[i];if(!a||null==a.start&&null==a.end)throw new Error("Empty item exists in splitList!");var o={label:a.label,color:a.color};o.min=a.start,o.max=a.end,o.min>o.max&&(o.min=[o.max,o.max=o.min][0]),o.min===o.max&&(o.single=o.max),null==o.min&&(o.min=-Number.MAX_VALUE),null==o.max&&(o.max=Number.MAX_VALUE),t.push(o)}},refresh:function(e){if(e){this.option=e,this.option.dataRange=this.reformOption(this.option.dataRange);var t=this.dataRangeOption=this.option.dataRange;if(!this._useCustomizedSplit()&&(null==t.min||null==t.max))throw new Error("option.dataRange.min or option.dataRange.max has not been defined.");this.myChart.canvasSupported||(t.realtime=!1);var i=this._isContinuity()?100:this._useCustomizedSplit()?t.splitList.length:t.splitNumber;this._buildSplitList(),this._buildColorList(i),this._buildGap(i),this._buildDataList(i)}this.clear(),this._buildShape()},getColor:function(e){if(isNaN(e))return null;var t;if(this._useCustomizedSplit()){for(var i=this._splitList,n=0,a=i.length;a>n;n++)if(i[n].min<=e&&i[n].max>=e){t=n;break}}else{if(this.dataRangeOption.min==this.dataRangeOption.max)return this._colorList[0];if(ethis.dataRangeOption.max&&(e=this.dataRangeOption.max),this.dataRangeOption.calculable&&(e-(this._gap*this._range.start+this.dataRangeOption.min)>5e-5||e-(this._gap*this._range.end+this.dataRangeOption.min)<-5e-5))return null;t=this._colorList.length-Math.ceil((e-this.dataRangeOption.min)/(this.dataRangeOption.max-this.dataRangeOption.min)*this._colorList.length),t==this._colorList.length&&t--}return this._selectedMap[t]?this._colorList[t]:null},getColorByIndex:function(e){return e>=this._colorList.length?e=this._colorList.length-1:0>e&&(e=0),this._colorList[e]},onbeforDispose:function(){this.messageCenter.unbind(r.EVENT.HOVER,this._onhoverlink)}},s.inherits(t,i),e("../component").define("dataRange",t),t}),i("echarts/util/shape/HandlePolygon",["require","zrender/shape/Base","zrender/shape/Polygon","zrender/tool/util"],function(e){function t(e){i.call(this,e)}var i=e("zrender/shape/Base"),n=e("zrender/shape/Polygon"),a=e("zrender/tool/util");return t.prototype={type:"handle-polygon",buildPath:function(e,t){n.prototype.buildPath(e,t)},isCover:function(e,t){var i=this.transformCoordToLocal(e,t);e=i[0],t=i[1];var n=this.style.rect;return e>=n.x&&e<=n.x+n.width&&t>=n.y&&t<=n.y+n.height?!0:!1}},a.inherits(t,i),t}),i("echarts/chart/k",["require","./base","../util/shape/Candle","../component/axis","../component/grid","../component/dataZoom","../config","../util/ecData","zrender/tool/util","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e("./base"),n=e("../util/shape/Candle");e("../component/axis"),e("../component/grid"),e("../component/dataZoom");var a=e("../config");a.k={zlevel:0,z:2,clickable:!0,hoverable:!0,legendHoverLink:!1,xAxisIndex:0,yAxisIndex:0,itemStyle:{normal:{color:"#fff",color0:"#00aa11",lineStyle:{width:1,color:"#ff3200",color0:"#00aa11"},label:{show:!1}},emphasis:{label:{show:!1}}}};var o=e("../util/ecData"),r=e("zrender/tool/util");return t.prototype={type:a.CHART_TYPE_K,_buildShape:function(){var e=this.series;this.selectedMap={};for(var t,i={top:[],bottom:[]},n=0,o=e.length;o>n;n++)e[n].type===a.CHART_TYPE_K&&(e[n]=this.reformOption(e[n]),this.legendHoverLink=e[n].legendHoverLink||this.legendHoverLink,t=this.component.xAxis.getAxis(e[n].xAxisIndex),t.type===a.COMPONENT_TYPE_AXIS_CATEGORY&&i[t.getPosition()].push(n));for(var r in i)i[r].length>0&&this._buildSinglePosition(r,i[r]);this.addShapeList()},_buildSinglePosition:function(e,t){var i=this._mapData(t),n=i.locationMap,a=i.maxDataLength;if(0!==a&&0!==n.length){this._buildHorizontal(t,a,n);for(var o=0,r=t.length;r>o;o++)this.buildMark(t[o])}},_mapData:function(e){for(var t,i,n=this.series,a=this.component.legend,o=[],r=0,s=0,l=e.length;l>s;s++)t=n[e[s]],i=t.name,this.selectedMap[i]=a?a.isSelected(i):!0,this.selectedMap[i]&&o.push(e[s]),r=Math.max(r,t.data.length);return{locationMap:o,maxDataLength:r}},_buildHorizontal:function(e,t,i){for(var n,a,o,r,s,l,h,m,V,U,d=this.series,p={},c=0,u=i.length;u>c;c++){n=i[c],a=d[n],o=a.xAxisIndex||0,r=this.component.xAxis.getAxis(o),h=a.barWidth||Math.floor(r.getGap()/2),U=a.barMaxWidth,U&&h>U&&(h=U),s=a.yAxisIndex||0,l=this.component.yAxis.getAxis(s),p[n]=[];for(var y=0,g=t;g>y&&null!=r.getNameByIndex(y);y++)m=a.data[y],V=this.getDataFromOption(m,"-"),"-"!==V&&4==V.length&&p[n].push([r.getCoordByIndex(y),h,l.getCoord(V[0]),l.getCoord(V[1]),l.getCoord(V[2]),l.getCoord(V[3]),y,r.getNameByIndex(y)])}this._buildKLine(e,p)},_buildKLine:function(e,t){for(var i,n,o,r,s,l,h,m,V,U,d,p,c,u,y,g,b,f=this.series,k=0,x=e.length;x>k;k++)if(b=e[k],d=f[b],u=t[b],this._isLarge(u)&&(u=this._getLargePointList(u)),d.type===a.CHART_TYPE_K&&null!=u){p=d,i=this.query(p,"itemStyle.normal.lineStyle.width"),n=this.query(p,"itemStyle.normal.lineStyle.color"),o=this.query(p,"itemStyle.normal.lineStyle.color0"),r=this.query(p,"itemStyle.normal.color"),s=this.query(p,"itemStyle.normal.color0"),l=this.query(p,"itemStyle.emphasis.lineStyle.width"),h=this.query(p,"itemStyle.emphasis.lineStyle.color"),m=this.query(p,"itemStyle.emphasis.lineStyle.color0"),V=this.query(p,"itemStyle.emphasis.color"),U=this.query(p,"itemStyle.emphasis.color0");for(var _=0,L=u.length;L>_;_++)y=u[_],c=d.data[y[6]],p=c,g=y[3]a;a++)n[a]=e[Math.floor(i/t*a)];return n},_getCandle:function(e,t,i,a,r,s,l,h,m,V,U,d,p,c,u){var y=this.series,g=y[e],b=g.data[t],f=[b,g],k={zlevel:g.zlevel,z:g.z,clickable:this.deepQuery(f,"clickable"),hoverable:this.deepQuery(f,"hoverable"),style:{x:a,y:[s,l,h,m],width:r,color:V,strokeColor:d,lineWidth:U,brushType:"both"},highlightStyle:{color:p,strokeColor:u,lineWidth:c},_seriesIndex:e};return k=this.addLabel(k,g,b,i),o.pack(k,g,e,b,t,i),k=new n(k)},getMarkCoord:function(e,t){var i=this.series[e],n=this.component.xAxis.getAxis(i.xAxisIndex),a=this.component.yAxis.getAxis(i.yAxisIndex);return["string"!=typeof t.xAxis&&n.getCoordByIndex?n.getCoordByIndex(t.xAxis||0):n.getCoord(t.xAxis||0),"string"!=typeof t.yAxis&&a.getCoordByIndex?a.getCoordByIndex(t.yAxis||0):a.getCoord(t.yAxis||0)]},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()},addDataAnimation:function(e,t){function i(){p--,0===p&&t&&t()}for(var n=this.series,a={},r=0,s=e.length;s>r;r++)a[e[r][0]]=e[r];for(var l,h,m,V,U,d,p=0,r=0,s=this.shapeList.length;s>r;r++)if(U=this.shapeList[r]._seriesIndex,a[U]&&!a[U][3]&&"candle"===this.shapeList[r].type){if(d=o.get(this.shapeList[r],"dataIndex"),V=n[U],a[U][2]&&d===V.data.length-1){this.zr.delShape(this.shapeList[r].id);continue}if(!a[U][2]&&0===d){this.zr.delShape(this.shapeList[r].id);continue}h=this.component.xAxis.getAxis(V.xAxisIndex||0).getGap(),l=a[U][2]?h:-h,m=0,p++,this.zr.animate(this.shapeList[r].id,"").when(this.query(this.option,"animationDurationUpdate"),{position:[l,m]}).done(i).start()}p||t&&t()}},r.inherits(t,i),e("../chart").define("k",t),t}),i("echarts/chart/pie",["require","./base","zrender/shape/Text","zrender/shape/Ring","zrender/shape/Circle","zrender/shape/Sector","zrender/shape/Polyline","../config","../util/ecData","zrender/tool/util","zrender/tool/math","zrender/tool/color","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o);var r=this;r.shapeHandler.onmouseover=function(e){var t=e.target,i=h.get(t,"seriesIndex"),n=h.get(t,"dataIndex"),a=h.get(t,"special"),o=[t.style.x,t.style.y],s=t.style.startAngle,l=t.style.endAngle,m=((l+s)/2+360)%360,V=t.highlightStyle.color,U=r.getLabel(i,n,a,o,m,V,!0);U&&r.zr.addHoverShape(U);var d=r.getLabelLine(i,n,o,t.style.r0,t.style.r,m,V,!0);d&&r.zr.addHoverShape(d)},this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Ring"),o=e("zrender/shape/Circle"),r=e("zrender/shape/Sector"),s=e("zrender/shape/Polyline"),l=e("../config");l.pie={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,center:["50%","50%"],radius:[0,"75%"],clockWise:!0,startAngle:90,minAngle:0,selectedOffset:10,itemStyle:{normal:{borderColor:"rgba(0,0,0,0)",borderWidth:1,label:{show:!0,position:"outer"},labelLine:{show:!0,length:20,lineStyle:{width:1,type:"solid"}}},emphasis:{borderColor:"rgba(0,0,0,0)",borderWidth:1,label:{show:!1},labelLine:{show:!1,length:20,lineStyle:{width:1,type:"solid"}}}}};var h=e("../util/ecData"),m=e("zrender/tool/util"),V=e("zrender/tool/math"),U=e("zrender/tool/color");return t.prototype={type:l.CHART_TYPE_PIE,_buildShape:function(){var e=this.series,t=this.component.legend;this.selectedMap={},this._selected={};var i,n,r;this._selectedMode=!1;for(var s,m=0,V=e.length;V>m;m++)if(e[m].type===l.CHART_TYPE_PIE){if(e[m]=this.reformOption(e[m]),this.legendHoverLink=e[m].legendHoverLink||this.legendHoverLink,s=e[m].name||"",this.selectedMap[s]=t?t.isSelected(s):!0,!this.selectedMap[s])continue;i=this.parseCenter(this.zr,e[m].center),n=this.parseRadius(this.zr,e[m].radius),this._selectedMode=this._selectedMode||e[m].selectedMode,this._selected[m]=[],this.deepQuery([e[m],this.option],"calculable")&&(r={zlevel:e[m].zlevel,z:e[m].z,hoverable:!1,style:{x:i[0],y:i[1],r0:n[0]<=10?0:n[0]-10,r:n[1]+10,brushType:"stroke",lineWidth:1,strokeColor:e[m].calculableHolderColor||this.ecTheme.calculableHolderColor||l.calculableHolderColor}},h.pack(r,e[m],m,void 0,-1),this.setCalculable(r),r=n[0]<=10?new o(r):new a(r),this.shapeList.push(r)),this._buildSinglePie(m),this.buildMark(m)}this.addShapeList()},_buildSinglePie:function(e){for(var t,i=this.series,n=i[e],a=n.data,o=this.component.legend,r=0,s=0,l=0,h=Number.NEGATIVE_INFINITY,m=[],V=0,U=a.length;U>V;V++)t=a[V].name, +this.selectedMap[t]=o?o.isSelected(t):!0,this.selectedMap[t]&&!isNaN(a[V].value)&&(0!==+a[V].value?r++:s++,l+=+a[V].value,h=Math.max(h,+a[V].value));if(0!==l){for(var d,p,c,u,y,g,b=100,f=n.clockWise,k=(n.startAngle.toFixed(2)-0+360)%360,x=n.minAngle||.01,_=360-x*r-.01*s,L=n.roseType,V=0,U=a.length;U>V;V++)if(t=a[V].name,this.selectedMap[t]&&!isNaN(a[V].value)){if(p=o?o.getColor(t):this.zr.getColor(V),b=a[V].value/l,d="area"!=L?f?k-b*_-(0!==b?x:.01):b*_+k+(0!==b?x:.01):f?k-360/U:360/U+k,d=d.toFixed(2)-0,b=(100*b).toFixed(2),c=this.parseCenter(this.zr,n.center),u=this.parseRadius(this.zr,n.radius),y=+u[0],g=+u[1],"radius"===L?g=a[V].value/h*(g-y)*.8+.2*(g-y)+y:"area"===L&&(g=Math.sqrt(a[V].value/h)*(g-y)+y),f){var W;W=k,k=d,d=W}this._buildItem(m,e,V,b,a[V].selected,c,y,g,k,d,p),f||(k=d)}this._autoLabelLayout(m,c,g);for(var V=0,U=m.length;U>V;V++)this.shapeList.push(m[V]);m=null}},_buildItem:function(e,t,i,n,a,o,r,s,l,m,V){var U=this.series,d=((m+l)/2+360)%360,p=this.getSector(t,i,n,a,o,r,s,l,m,V);h.pack(p,U[t],t,U[t].data[i],i,U[t].data[i].name,n),e.push(p);var c=this.getLabel(t,i,n,o,d,V,!1),u=this.getLabelLine(t,i,o,r,s,d,V,!1);u&&(h.pack(u,U[t],t,U[t].data[i],i,U[t].data[i].name,n),e.push(u)),c&&(h.pack(c,U[t],t,U[t].data[i],i,U[t].data[i].name,n),c._labelLine=u,e.push(c))},getSector:function(e,t,i,n,a,o,s,l,h,m){var d=this.series,p=d[e],c=p.data[t],u=[c,p],y=this.deepMerge(u,"itemStyle.normal")||{},g=this.deepMerge(u,"itemStyle.emphasis")||{},b=this.getItemStyleColor(y.color,e,t,c)||m,f=this.getItemStyleColor(g.color,e,t,c)||("string"==typeof b?U.lift(b,-.2):b),k={zlevel:p.zlevel,z:p.z,clickable:this.deepQuery(u,"clickable"),style:{x:a[0],y:a[1],r0:o,r:s,startAngle:l,endAngle:h,brushType:"both",color:b,lineWidth:y.borderWidth,strokeColor:y.borderColor,lineJoin:"round"},highlightStyle:{color:f,lineWidth:g.borderWidth,strokeColor:g.borderColor,lineJoin:"round"},_seriesIndex:e,_dataIndex:t};if(n){var x=((k.style.startAngle+k.style.endAngle)/2).toFixed(2)-0;k.style._hasSelected=!0,k.style._x=k.style.x,k.style._y=k.style.y;var _=this.query(p,"selectedOffset");k.style.x+=V.cos(x,!0)*_,k.style.y-=V.sin(x,!0)*_,this._selected[e][t]=!0}else this._selected[e][t]=!1;return this._selectedMode&&(k.onclick=this.shapeHandler.onclick),this.deepQuery([c,p,this.option],"calculable")&&(this.setCalculable(k),k.draggable=!0),(this._needLabel(p,c,!0)||this._needLabelLine(p,c,!0))&&(k.onmouseover=this.shapeHandler.onmouseover),k=new r(k)},getLabel:function(e,t,i,a,o,r,s){var l=this.series,h=l[e],U=h.data[t];if(this._needLabel(h,U,s)){var d,p,c,u=s?"emphasis":"normal",y=m.merge(m.clone(U.itemStyle)||{},h.itemStyle),g=y[u].label,b=g.textStyle||{},f=a[0],k=a[1],x=this.parseRadius(this.zr,h.radius),_="middle";g.position=g.position||y.normal.label.position,"center"===g.position?(d=f,p=k,c="center"):"inner"===g.position||"inside"===g.position?(x=(x[0]+x[1])*(g.distance||.5),d=Math.round(f+x*V.cos(o,!0)),p=Math.round(k-x*V.sin(o,!0)),r="#fff",c="center"):(x=x[1]- -y[u].labelLine.length,d=Math.round(f+x*V.cos(o,!0)),p=Math.round(k-x*V.sin(o,!0)),c=o>=90&&270>=o?"right":"left"),"center"!=g.position&&"inner"!=g.position&&"inside"!=g.position&&(d+="left"===c?20:-20),U.__labelX=d-("left"===c?5:-5),U.__labelY=p;var L=new n({zlevel:h.zlevel,z:h.z+1,hoverable:!1,style:{x:d,y:p,color:b.color||r,text:this.getLabelText(e,t,i,u),textAlign:b.align||c,textBaseline:b.baseline||_,textFont:this.getFont(b)},highlightStyle:{brushType:"fill"}});return L._radius=x,L._labelPosition=g.position||"outer",L._rect=L.getRect(L.style),L._seriesIndex=e,L._dataIndex=t,L}},getLabelText:function(e,t,i,n){var a=this.series,o=a[e],r=o.data[t],s=this.deepQuery([r,o],"itemStyle."+n+".label.formatter");return s?"function"==typeof s?s.call(this.myChart,{seriesIndex:e,seriesName:o.name||"",series:o,dataIndex:t,data:r,name:r.name,value:r.value,percent:i}):"string"==typeof s?(s=s.replace("{a}","{a0}").replace("{b}","{b0}").replace("{c}","{c0}").replace("{d}","{d0}"),s=s.replace("{a0}",o.name).replace("{b0}",r.name).replace("{c0}",r.value).replace("{d0}",i)):void 0:r.name},getLabelLine:function(e,t,i,n,a,o,r,l){var h=this.series,U=h[e],d=U.data[t];if(this._needLabelLine(U,d,l)){var p=l?"emphasis":"normal",c=m.merge(m.clone(d.itemStyle)||{},U.itemStyle),u=c[p].labelLine,y=u.lineStyle||{},g=i[0],b=i[1],f=a,k=this.parseRadius(this.zr,U.radius)[1]- -u.length,x=V.cos(o,!0),_=V.sin(o,!0);return new s({zlevel:U.zlevel,z:U.z+1,hoverable:!1,style:{pointList:[[g+f*x,b-f*_],[g+k*x,b-k*_],[d.__labelX,d.__labelY]],strokeColor:y.color||r,lineType:y.type,lineWidth:y.width},_seriesIndex:e,_dataIndex:t})}},_needLabel:function(e,t,i){return this.deepQuery([t,e],"itemStyle."+(i?"emphasis":"normal")+".label.show")},_needLabelLine:function(e,t,i){return this.deepQuery([t,e],"itemStyle."+(i?"emphasis":"normal")+".labelLine.show")},_autoLabelLayout:function(e,t,i){for(var n=[],a=[],o=0,r=e.length;r>o;o++)("outer"===e[o]._labelPosition||"outside"===e[o]._labelPosition)&&(e[o]._rect._y=e[o]._rect.y,e[o]._rect.xa;a++)if(e[a]._rect.y+=n,e[a].style.y+=n,e[a]._labelLine&&(e[a]._labelLine.style.pointList[1][1]+=n,e[a]._labelLine.style.pointList[2][1]+=n),a>t&&i>a+1&&e[a+1]._rect.y>e[a]._rect.y+e[a]._rect.height)return void o(a,n/2);o(i-1,n/2)}function o(t,i){for(var n=t;n>=0&&(e[n]._rect.y-=i,e[n].style.y-=i,e[n]._labelLine&&(e[n]._labelLine.style.pointList[1][1]-=i,e[n]._labelLine.style.pointList[2][1]-=i),!(n>0&&e[n]._rect.y>e[n-1]._rect.y+e[n-1]._rect.height));n--);}function r(e,t,i,n,a){for(var o,r,s,l=i[0],h=i[1],m=a>0?t?Number.MAX_VALUE:0:t?Number.MAX_VALUE:0,V=0,U=e.length;U>V;V++)r=Math.abs(e[V]._rect.y-h),s=e[V]._radius-n,o=n+s>r?Math.sqrt((n+s+20)*(n+s+20)-Math.pow(e[V]._rect.y-h,2)):Math.abs(e[V]._rect.x+(a>0?0:e[V]._rect.width)-l),t&&o>=m&&(o=m-10),!t&&m>=o&&(o=m+10),e[V]._rect.x=e[V].style.x=l+o*a,e[V]._labelLine&&(e[V]._labelLine.style.pointList[2][0]=l+(o-5)*a,e[V]._labelLine.style.pointList[1][0]=l+(o-20)*a),m=o}e.sort(function(e,t){return e._rect.y-t._rect.y});for(var s,l=0,h=e.length,m=[],V=[],U=0;h>U;U++)s=e[U]._rect.y-l,0>s&&a(U,h,-s,n),l=e[U]._rect.y+e[U]._rect.height;this.zr.getHeight()-l<0&&o(h-1,l-this.zr.getHeight());for(var U=0;h>U;U++)e[U]._rect.y>=t[1]?V.push(e[U]):m.push(e[U]);r(V,!0,t,i,n),r(m,!1,t,i,n)},reformOption:function(e){var t=m.merge;return e=t(t(e||{},m.clone(this.ecTheme.pie||{})),m.clone(l.pie)),e.itemStyle.normal.label.textStyle=this.getTextStyle(e.itemStyle.normal.label.textStyle),e.itemStyle.emphasis.label.textStyle=this.getTextStyle(e.itemStyle.emphasis.label.textStyle),this.z=e.z,this.zlevel=e.zlevel,e},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()},addDataAnimation:function(e,t){function i(){s--,0===s&&t&&t()}for(var n=this.series,a={},o=0,r=e.length;r>o;o++)a[e[o][0]]=e[o];var s=0,h={},m={},V={},U=this.shapeList;this.shapeList=[];for(var d,p,c,u={},o=0,r=e.length;r>o;o++)d=e[o][0],p=e[o][2],c=e[o][3],n[d]&&n[d].type===l.CHART_TYPE_PIE&&(p?(c||(h[d+"_"+n[d].data.length]="delete"),u[d]=1):c?u[d]=0:(h[d+"_-1"]="delete",u[d]=-1),this._buildSinglePie(d));for(var y,g,o=0,r=this.shapeList.length;r>o;o++)switch(d=this.shapeList[o]._seriesIndex,y=this.shapeList[o]._dataIndex,g=d+"_"+y,this.shapeList[o].type){case"sector":h[g]=this.shapeList[o];break;case"text":m[g]=this.shapeList[o];break;case"polyline":V[g]=this.shapeList[o]}this.shapeList=[];for(var b,o=0,r=U.length;r>o;o++)if(d=U[o]._seriesIndex,a[d]){if(y=U[o]._dataIndex+u[d],g=d+"_"+y,b=h[g],!b)continue;if("sector"===U[o].type)"delete"!=b?(s++,this.zr.animate(U[o].id,"style").when(400,{startAngle:b.style.startAngle,endAngle:b.style.endAngle}).done(i).start()):(s++,this.zr.animate(U[o].id,"style").when(400,u[d]<0?{startAngle:U[o].style.startAngle}:{endAngle:U[o].style.endAngle}).done(i).start());else if("text"===U[o].type||"polyline"===U[o].type)if("delete"===b)this.zr.delShape(U[o].id);else switch(U[o].type){case"text":s++,b=m[g],this.zr.animate(U[o].id,"style").when(400,{x:b.style.x,y:b.style.y}).done(i).start();break;case"polyline":s++,b=V[g],this.zr.animate(U[o].id,"style").when(400,{pointList:b.style.pointList}).done(i).start()}}this.shapeList=U,s||t&&t()},onclick:function(e){var t=this.series;if(this.isClick&&e.target){this.isClick=!1;for(var i,n=e.target,a=n.style,o=h.get(n,"seriesIndex"),r=h.get(n,"dataIndex"),s=0,m=this.shapeList.length;m>s;s++)if(this.shapeList[s].id===n.id){if(o=h.get(n,"seriesIndex"),r=h.get(n,"dataIndex"),a._hasSelected)n.style.x=n.style._x,n.style.y=n.style._y,n.style._hasSelected=!1,this._selected[o][r]=!1;else{var U=((a.startAngle+a.endAngle)/2).toFixed(2)-0;n.style._hasSelected=!0,this._selected[o][r]=!0,n.style._x=n.style.x,n.style._y=n.style.y,i=this.query(t[o],"selectedOffset"),n.style.x+=V.cos(U,!0)*i,n.style.y-=V.sin(U,!0)*i}this.zr.modShape(n.id)}else this.shapeList[s].style._hasSelected&&"single"===this._selectedMode&&(o=h.get(this.shapeList[s],"seriesIndex"),r=h.get(this.shapeList[s],"dataIndex"),this.shapeList[s].style.x=this.shapeList[s].style._x,this.shapeList[s].style.y=this.shapeList[s].style._y,this.shapeList[s].style._hasSelected=!1,this._selected[o][r]=!1,this.zr.modShape(this.shapeList[s].id));this.messageCenter.dispatch(l.EVENT.PIE_SELECTED,e.event,{selected:this._selected,target:h.get(n,"name")},this.myChart),this.zr.refreshNextFrame()}}},m.inherits(t,i),e("../chart").define("pie",t),t}),i("echarts/chart/radar",["require","./base","zrender/shape/Polygon","../component/polar","../config","../util/ecData","zrender/tool/util","zrender/tool/color","../util/accMath","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Polygon");e("../component/polar");var a=e("../config");a.radar={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,polarIndex:0,itemStyle:{normal:{label:{show:!1},lineStyle:{width:2,type:"solid"}},emphasis:{label:{show:!1}}},symbolSize:2};var o=e("../util/ecData"),r=e("zrender/tool/util"),s=e("zrender/tool/color");return t.prototype={type:a.CHART_TYPE_RADAR,_buildShape:function(){this.selectedMap={},this._symbol=this.option.symbolList,this._queryTarget,this._dropBoxList=[],this._radarDataCounter=0;for(var e,t=this.series,i=this.component.legend,n=0,o=t.length;o>n;n++)t[n].type===a.CHART_TYPE_RADAR&&(this.serie=this.reformOption(t[n]),this.legendHoverLink=t[n].legendHoverLink||this.legendHoverLink,e=this.serie.name||"",this.selectedMap[e]=i?i.isSelected(e):!0,this.selectedMap[e]&&(this._queryTarget=[this.serie,this.option],this.deepQuery(this._queryTarget,"calculable")&&this._addDropBox(n),this._buildSingleRadar(n),this.buildMark(n)));this.addShapeList()},_buildSingleRadar:function(e){for(var t,i,n,a,o=this.component.legend,r=this.serie.data,s=this.deepQuery(this._queryTarget,"calculable"),l=0;lr;r++)n=this.getDataFromOption(t.value[r]),i="-"!=n?o.getVector(e,r,n):!1,i&&a.push(i);return a},_addSymbol:function(e,t,i,n,a){for(var r,s=this.series,l=this.component.polar,h=0,m=e.length;m>h;h++)r=this.getSymbolShape(this.deepMerge([s[n].data[i],s[n]]),n,s[n].data[i].value[h],h,l.getIndicatorText(a,h),e[h][0],e[h][1],this._symbol[this._radarDataCounter%this._symbol.length],t,"#fff","vertical"),r.zlevel=this.getZlevelBase(),r.z=this.getZBase()+1,o.set(r,"data",s[n].data[i]),o.set(r,"value",s[n].data[i].value),o.set(r,"dataIndex",i),o.set(r,"special",h),this.shapeList.push(r)},_addDataShape:function(e,t,i,a,r,l){var h=this.series,m=[i,this.serie],V=this.getItemStyleColor(this.deepQuery(m,"itemStyle.normal.color"),a,r,i),U=this.deepQuery(m,"itemStyle.normal.lineStyle.width"),d=this.deepQuery(m,"itemStyle.normal.lineStyle.type"),p=this.deepQuery(m,"itemStyle.normal.areaStyle.color"),c=this.deepQuery(m,"itemStyle.normal.areaStyle"),u={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{pointList:e,brushType:c?"both":"stroke",color:p||V||("string"==typeof t?s.alpha(t,.5):t),strokeColor:V||t,lineWidth:U,lineType:d},highlightStyle:{brushType:this.deepQuery(m,"itemStyle.emphasis.areaStyle")||c?"both":"stroke",color:this.deepQuery(m,"itemStyle.emphasis.areaStyle.color")||p||V||("string"==typeof t?s.alpha(t,.5):t),strokeColor:this.getItemStyleColor(this.deepQuery(m,"itemStyle.emphasis.color"),a,r,i)||V||t,lineWidth:this.deepQuery(m,"itemStyle.emphasis.lineStyle.width")||U,lineType:this.deepQuery(m,"itemStyle.emphasis.lineStyle.type")||d}};o.pack(u,h[a],a,i,r,i.name,this.component.polar.getIndicator(h[a].polarIndex)),l&&(u.draggable=!0,this.setCalculable(u)),u=new n(u),this.shapeList.push(u)},_addDropBox:function(e){var t=this.series,i=this.deepQuery(this._queryTarget,"polarIndex");if(!this._dropBoxList[i]){var n=this.component.polar.getDropBox(i);n.zlevel=this.getZlevelBase(),n.z=this.getZBase(),this.setCalculable(n),o.pack(n,t,e,void 0,-1),this.shapeList.push(n),this._dropBoxList[i]=!0}},ondragend:function(e,t){var i=this.series;if(this.isDragend&&e.target){var n=e.target,a=o.get(n,"seriesIndex"),r=o.get(n,"dataIndex");this.component.legend&&this.component.legend.del(i[a].data[r].name),i[a].data.splice(r,1),t.dragOut=!0,t.needRefresh=!0,this.isDragend=!1}},ondrop:function(t,i){var n=this.series;if(this.isDrop&&t.target){var a,r,s=t.target,l=t.dragged,h=o.get(s,"seriesIndex"),m=o.get(s,"dataIndex"),V=this.component.legend;if(-1===m)a={value:o.get(l,"value"),name:o.get(l,"name")},n[h].data.push(a),V&&V.add(a.name,l.style.color||l.style.strokeColor);else{var U=e("../util/accMath");a=n[h].data[m],V&&V.del(a.name),a.name+=this.option.nameConnector+o.get(l,"name"),r=o.get(l,"value");for(var d=0;dh;h++)t=m.polar2cartesian(s,o*Math.PI/180+r*h),l.push({vector:[t[1],-t[0]]})},_getRadius:function(){var e=this.polar[this._index];return this.parsePercent(e.radius,Math.min(this.zr.getWidth(),this.zr.getHeight())/2)},_buildSpiderWeb:function(e){var t=this.polar[e],i=t.__ecIndicator,n=t.splitArea,a=t.splitLine,o=this.getCenter(e),r=t.splitNumber,s=a.lineStyle.color,l=a.lineStyle.width,h=a.show,m=this.deepQuery(this._queryTarget,"axisLine");this._addArea(i,r,o,n,s,l,h),m.show&&this._addLine(i,o,m)},_addAxisLabel:function(t){for(var i,a,o,r,a,s,l,m,V,U,d=e("../util/accMath"),p=this.polar[t],c=this.deepQuery(this._queryTarget,"indicator"),u=p.__ecIndicator,y=this.deepQuery(this._queryTarget,"splitNumber"),g=this.getCenter(t),b=0;b=x;x+=U+1)r=h.merge({},o),l=d.accAdd(s.min,d.accMul(s.step,x)),l="function"==typeof k?k(l):"string"==typeof k?k.replace("{a}","{a0}").replace("{a0}",l):this.numAddCommas(l),r.text=l,r.x=x*a[0]/y+Math.cos(m)*V+g[0],r.y=x*a[1]/y+Math.sin(m)*V+g[1],this.shapeList.push(new n({zlevel:this.getZlevelBase(),z:this.getZBase(),style:r,draggable:!1,hoverable:!1}))}},_buildText:function(e){for(var t,i,a,o,r,s,l,h=this.polar[e],m=h.__ecIndicator,V=this.deepQuery(this._queryTarget,"indicator"),U=this.getCenter(e),d=0,p=0,c=0;c0?"left":Math.round(t[0])<0?"right":"center",null==o.margin?t=this._mapVector(t,U,1.1):(s=o.margin,d=t[0]>0?s:-s,p=t[1]>0?s:-s,d=0===t[0]?0:d,p=0===t[1]?0:p,t=this._mapVector(t,U,1)),i.textAlign=a,i.x=t[0]+d,i.y=t[1]+p,r=o.rotate?[o.rotate/180*Math.PI,t[0],t[1]]:[0,0,0],this.shapeList.push(new n({zlevel:this.getZlevelBase(),z:this.getZBase(),style:i,draggable:!1,hoverable:!1,rotation:r})))},getIndicatorText:function(e,t){return this.polar[e]&&this.polar[e].__ecIndicator[t]&&this.polar[e].__ecIndicator[t].text},getDropBox:function(e){var t,i,e=e||0,n=this.polar[e],a=this.getCenter(e),o=n.__ecIndicator,r=o.length,s=[],l=n.type;if("polygon"==l){for(var h=0;r>h;h++)t=o[h].vector,s.push(this._mapVector(t,a,1.2));i=this._getShape(s,"fill","rgba(0,0,0,0)","",1)}else"circle"==l&&(i=this._getCircle("",1,1.2,a,"fill","rgba(0,0,0,0)"));return i},_addArea:function(e,t,i,n,a,o,r){for(var s,l,h,m,V=this.deepQuery(this._queryTarget,"type"),U=0;t>U;U++)l=(t-U)/t,r&&("polygon"==V?(m=this._getPointList(e,l,i),s=this._getShape(m,"stroke","",a,o)):"circle"==V&&(s=this._getCircle(a,o,l,i,"stroke")),this.shapeList.push(s)),n.show&&(h=(t-U-1)/t,this._addSplitArea(e,n,l,h,i,U))},_getCircle:function(e,t,i,n,a,o){var s=this._getRadius();return new r({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:n[0],y:n[1],r:s*i,brushType:a,strokeColor:e,lineWidth:t,color:o},hoverable:!1,draggable:!1})},_getRing:function(e,t,i,n){var a=this._getRadius();return new s({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:n[0],y:n[1],r:t*a,r0:i*a,color:e,brushType:"fill"},hoverable:!1,draggable:!1})},_getPointList:function(e,t,i){for(var n,a=[],o=e.length,r=0;o>r;r++)n=e[r].vector,a.push(this._mapVector(n,i,t));return a},_getShape:function(e,t,i,n,a){return new o({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{pointList:e,brushType:t,color:i,strokeColor:n,lineWidth:a},hoverable:!1,draggable:!1})},_addSplitArea:function(e,t,i,n,a,o){var r,s,l,h,m,V=e.length,U=t.areaStyle.color,d=[],V=e.length,p=this.deepQuery(this._queryTarget,"type");if("string"==typeof U&&(U=[U]),s=U.length,r=U[o%s],"polygon"==p)for(var c=0;V>c;c++)d=[],l=e[c].vector,h=e[(c+1)%V].vector,d.push(this._mapVector(l,a,i)),d.push(this._mapVector(l,a,n)),d.push(this._mapVector(h,a,n)),d.push(this._mapVector(h,a,i)),m=this._getShape(d,"fill",r,"",1),this.shapeList.push(m);else"circle"==p&&(m=this._getRing(r,i,n,a),this.shapeList.push(m))},_mapVector:function(e,t,i){return[e[0]*i+t[0],e[1]*i+t[1]]},getCenter:function(e){var e=e||0;return this.parseCenter(this.zr,this.polar[e].center)},_addLine:function(e,t,i){for(var n,a,o=e.length,r=i.lineStyle,s=r.color,l=r.width,h=r.type,m=0;o>m;m++)a=e[m].vector,n=this._getLine(t[0],t[1],a[0]+t[0],a[1]+t[1],s,l,h),this.shapeList.push(n)},_getLine:function(e,t,i,n,o,r,s){return new a({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{xStart:e,yStart:t,xEnd:i,yEnd:n,strokeColor:o,lineWidth:r,lineType:s},hoverable:!1})},_adjustIndicatorValue:function(t){for(var i,n,a,o=this.polar[t],r=this.deepQuery(this._queryTarget,"indicator"),s=r.length,l=o.__ecIndicator,h=this._getSeriesData(t),m=o.boundaryGap,V=o.splitNumber,U=o.scale,d=e("../util/smartSteps"),p=0;s>p;p++){if("number"==typeof r[p].max)i=r[p].max,n=r[p].min||0,a={max:i,min:n};else{var c=this._findValue(h,p,V,m);n=c.min,i=c.max}!U&&n>=0&&i>=0&&(n=0),!U&&0>=n&&0>=i&&(i=0);var u=d(n,i,V,a);l[p].value={min:u.min,max:u.max,step:u.step}}},_getSeriesData:function(e){for(var t,i,n,a=[],o=this.component.legend,r=0;ro||void 0===o)&&(o=e),(r>e||void 0===r)&&(r=e)}var o,r,s;if(e&&0!==e.length){if(1==e.length&&(r=0),1!=e.length)for(var l=0;l0?r=o/i:o/=i),{max:o,min:r}}},getVector:function(e,t,i){e=e||0,t=t||0;var n=this.polar[e].__ecIndicator;if(!(t>=n.length)){var a,o=this.polar[e].__ecIndicator[t],r=this.getCenter(e),s=o.vector,l=o.value.max,h=o.value.min;if("undefined"==typeof i)return r;switch(i){case"min":i=h;break;case"max":i=l;break;case"center":i=(l+h)/2}return a=l!=h?(i-h)/(l-h):.5,this._mapVector(s,r,a)}},isInside:function(e){var t=this.getNearestIndex(e);return t?t.polarIndex:-1},getNearestIndex:function(e){for(var t,i,n,a,o,r,s,l,h,V=0;Va[0])return{polarIndex:V,valueIndex:Math.floor((h+l/2)/l)%s}}},getIndicator:function(e){var e=e||0;return this.polar[e].indicator},refresh:function(e){e&&(this.option=e,this.polar=this.option.polar,this.series=this.option.series),this.clear(),this._buildShape()}},h.inherits(t,i),e("../component").define("polar",t),t}),i("echarts/util/coordinates",["require","zrender/tool/math"],function(e){function t(e,t){return[e*n.sin(t),e*n.cos(t)]}function i(e,t){return[Math.sqrt(e*e+t*t),Math.atan(t/e)]}var n=e("zrender/tool/math");return{polar2cartesian:t,cartesian2polar:i}}),i("echarts/chart/chord",["require","./base","zrender/shape/Text","zrender/shape/Line","zrender/shape/Sector","../util/shape/Ribbon","../util/shape/Icon","zrender/shape/BezierCurve","../config","../util/ecData","zrender/tool/util","zrender/tool/vector","../data/Graph","../layout/Chord","../chart"],function(e){"use strict";function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.scaleLineLength=4,this.scaleUnitAngle=4,this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Line"),o=e("zrender/shape/Sector"),r=e("../util/shape/Ribbon"),s=e("../util/shape/Icon"),l=e("zrender/shape/BezierCurve"),h=e("../config");h.chord={zlevel:0,z:2,clickable:!0,radius:["65%","75%"],center:["50%","50%"],padding:2,sort:"none",sortSub:"none",startAngle:90,clockWise:!0,ribbonType:!0,minRadius:10,maxRadius:20,symbol:"circle",showScale:!1,showScaleText:!1,itemStyle:{normal:{borderWidth:0,borderColor:"#000",label:{show:!0,rotate:!1,distance:5},chordStyle:{width:1,color:"black",borderWidth:1,borderColor:"#999",opacity:.5}},emphasis:{borderWidth:0,borderColor:"#000",chordStyle:{width:1,color:"black",borderWidth:1,borderColor:"#999"}}}};var m=e("../util/ecData"),V=e("zrender/tool/util"),U=e("zrender/tool/vector"),d=e("../data/Graph"),p=e("../layout/Chord");return t.prototype={type:h.CHART_TYPE_CHORD,_init:function(){var e=this.series;this.selectedMap={};for(var t={},i={},n=0,a=e.length;a>n;n++)if(e[n].type===this.type){var o=this.isSelected(e[n].name);this.selectedMap[e[n].name]=o,o&&this.buildMark(n),this.reformOption(e[n]),t[e[n].name]=e[n]}for(var n=0,a=e.length;a>n;n++)if(e[n].type===this.type)if(e[n].insertToSerie){var r=t[e[n].insertToSerie];e[n]._referenceSerie=r}else i[e[n].name]=[e[n]];for(var n=0,a=e.length;a>n;n++)if(e[n].type===this.type&&e[n].insertToSerie){for(var s=e[n]._referenceSerie;s&&s._referenceSerie;)s=s._referenceSerie;i[s.name]&&this.selectedMap[e[n].name]&&i[s.name].push(e[n])}for(var l in i)this._buildChords(i[l]);this.addShapeList()},_getNodeCategory:function(e,t){return e.categories&&e.categories[t.category||0]},_getNodeQueryTarget:function(e,t){var i=this._getNodeCategory(e,t);return[t,i,e]},_getEdgeQueryTarget:function(e,t,i){return i=i||"normal",[t.itemStyle&&t.itemStyle[i],e.itemStyle[i].chordStyle]},_buildChords:function(e){for(var t=[],i=e[0],n=function(e){return e.layout.size>0},a=function(e){return function(t){return e.getEdge(t.node2,t.node1)}},o=0;oa;a++){var r=n[a];if(r&&!r.ignore){var s=this._getNodeCategory(t,r),l=s?s.name:r.name;if(this.selectedMap[l]=this.isSelected(l),this.selectedMap[l]){var h=i.addNode(r.name,r);h.rawIndex=a}}}for(var a=0,o=e.links.length;o>a;a++){var m=e.links[a],V=m.source,U=m.target;"number"==typeof V&&(V=n[V],V&&(V=V.name)),"number"==typeof U&&(U=n[U],U&&(U=U.name));var p=i.addEdge(V,U,m);p&&(p.rawIndex=a)}return i.eachNode(function(e){var i=e.data.value;if(null==i)if(i=0,t.ribbonType)for(var n=0;n0&&(p.style.brushType="both"),p.highlightStyle.lineWidth>0&&(p.highlightStyle.brushType="both"),m.pack(p,e,t,i.data,i.rawIndex,i.id,i.category),this.shapeList.push(p),i.shape=p},this)},_buildNodeIcons:function(e,t,i,n){var a=this.parseCenter(this.zr,n.center),o=this.parseRadius(this.zr,n.radius),r=o[1];i.eachNode(function(i){var o=i.layout.startAngle,l=i.layout.endAngle,h=(o+l)/2,V=r*Math.cos(h),U=r*Math.sin(h),d=this._getNodeQueryTarget(n,i.data),p=this._getNodeCategory(n,i.data),c=this.deepQuery(d,"itemStyle.normal.color");c||(c=this.getColor(p?p.name:i.id));var u=new s({zlevel:e.zlevel,z:e.z+1,style:{x:-i.layout.size,y:-i.layout.size,width:2*i.layout.size,height:2*i.layout.size,iconType:this.deepQuery(d,"symbol"),color:c,brushType:"both",lineWidth:this.deepQuery(d,"itemStyle.normal.borderWidth"),strokeColor:this.deepQuery(d,"itemStyle.normal.borderColor")},highlightStyle:{color:this.deepQuery(d,"itemStyle.emphasis.color"),lineWidth:this.deepQuery(d,"itemStyle.emphasis.borderWidth"),strokeColor:this.deepQuery(d,"itemStyle.emphasis.borderColor")},clickable:n.clickable,position:[V+a[0],U+a[1]]});m.pack(u,e,t,i.data,i.rawIndex,i.id,i.category),this.shapeList.push(u),i.shape=u},this)},_buildLabels:function(e,t,i,a){var o=this.query(a,"itemStyle.normal.label.rotate"),r=this.query(a,"itemStyle.normal.label.distance"),s=this.parseCenter(this.zr,a.center),l=this.parseRadius(this.zr,a.radius),h=a.clockWise,m=h?1:-1; + +i.eachNode(function(t){var i=t.layout.startAngle/Math.PI*180*m,h=t.layout.endAngle/Math.PI*180*m,V=(i*-m+h*-m)/2;V%=360,0>V&&(V+=360);var d=90>=V||V>=270;V=V*Math.PI/180;var p=[Math.cos(V),-Math.sin(V)],c=0;c=a.ribbonType?a.showScaleText?35+r:r:r+t.layout.size;var u=U.scale([],p,l[1]+c);U.add(u,u,s);var y={zlevel:e.zlevel,z:e.z+1,hoverable:!1,style:{text:null==t.data.label?t.id:t.data.label,textAlign:d?"left":"right"}};o?(y.rotation=d?V:Math.PI+V,y.style.x=d?l[1]+c:-l[1]-c,y.style.y=0,y.position=s.slice()):(y.style.x=u[0],y.style.y=u[1]),y.style.color=this.deepQuery([t.data,a],"itemStyle.normal.label.textStyle.color")||"#000000",y.style.textFont=this.getFont(this.deepQuery([t.data,a],"itemStyle.normal.label.textStyle")),y=new n(y),this.shapeList.push(y),t.labelShape=y},this)},_buildRibbons:function(e,t,i,n){var a=e[t],o=this.parseCenter(this.zr,n.center),s=this.parseRadius(this.zr,n.radius);i.eachEdge(function(l,h){var V,U=i.getEdge(l.node2,l.node1);if(U&&!l.shape){if(U.shape)return void(l.shape=U.shape);var d=l.layout.startAngle/Math.PI*180,p=l.layout.endAngle/Math.PI*180,c=U.layout.startAngle/Math.PI*180,u=U.layout.endAngle/Math.PI*180;V=this.getColor(1===e.length?l.layout.weight<=U.layout.weight?l.node1.id:l.node2.id:a.name);var y,g,b=this._getEdgeQueryTarget(a,l.data),f=this._getEdgeQueryTarget(a,l.data,"emphasis"),k=new r({zlevel:a.zlevel,z:a.z,style:{x:o[0],y:o[1],r:s[0],source0:d,source1:p,target0:c,target1:u,brushType:"both",opacity:this.deepQuery(b,"opacity"),color:V,lineWidth:this.deepQuery(b,"borderWidth"),strokeColor:this.deepQuery(b,"borderColor"),clockWise:n.clockWise},clickable:n.clickable,highlightStyle:{brushType:"both",opacity:this.deepQuery(f,"opacity"),lineWidth:this.deepQuery(f,"borderWidth"),strokeColor:this.deepQuery(f,"borderColor")}});l.layout.weight<=U.layout.weight?(y=U.node1,g=U.node2):(y=l.node1,g=l.node2),m.pack(k,a,t,l.data,null==l.rawIndex?h:l.rawIndex,l.data.name||y.id+"-"+g.id,y.id,g.id),this.shapeList.push(k),l.shape=k}},this)},_buildEdgeCurves:function(e,t,i,n,a){var o=e[t],r=this.parseCenter(this.zr,n.center);i.eachEdge(function(e,i){var n=a.getNodeById(e.node1.id),s=a.getNodeById(e.node2.id),h=n.shape,V=s.shape,U=this._getEdgeQueryTarget(o,e.data),d=this._getEdgeQueryTarget(o,e.data,"emphasis"),p=new l({zlevel:o.zlevel,z:o.z,style:{xStart:h.position[0],yStart:h.position[1],xEnd:V.position[0],yEnd:V.position[1],cpX1:r[0],cpY1:r[1],lineWidth:this.deepQuery(U,"width"),strokeColor:this.deepQuery(U,"color"),opacity:this.deepQuery(U,"opacity")},highlightStyle:{lineWidth:this.deepQuery(d,"width"),strokeColor:this.deepQuery(d,"color"),opacity:this.deepQuery(d,"opacity")}});m.pack(p,o,t,e.data,null==e.rawIndex?i:e.rawIndex,e.data.name||e.node1.id+"-"+e.node2.id,e.node1.id,e.node2.id),this.shapeList.push(p),e.shape=p},this)},_buildScales:function(e,t,i){var o,r,s=e.clockWise,l=this.parseCenter(this.zr,e.center),h=this.parseRadius(this.zr,e.radius),m=s?1:-1,V=0,d=-(1/0);e.showScaleText&&(i.eachNode(function(e){var t=e.data.value;t>d&&(d=t),V+=t}),d>1e10?(o="b",r=1e-9):d>1e7?(o="m",r=1e-6):d>1e4?(o="k",r=.001):(o="",r=1));var p=V/(360-e.padding);i.eachNode(function(t){for(var i=t.layout.startAngle/Math.PI*180,V=t.layout.endAngle/Math.PI*180,d=i;;){if(s&&d>V||!s&&V>d)break;var c=d/180*Math.PI,u=[Math.cos(c),Math.sin(c)],y=U.scale([],u,h[1]+1);U.add(y,y,l);var g=U.scale([],u,h[1]+this.scaleLineLength);U.add(g,g,l);var b=new a({zlevel:e.zlevel,z:e.z-1,hoverable:!1,style:{xStart:y[0],yStart:y[1],xEnd:g[0],yEnd:g[1],lineCap:"round",brushType:"stroke",strokeColor:"#666",lineWidth:1}});this.shapeList.push(b),d+=m*this.scaleUnitAngle}if(e.showScaleText)for(var f=i,k=5*p*this.scaleUnitAngle,x=0;;){if(s&&f>V||!s&&V>f)break;var c=f;c%=360,0>c&&(c+=360);var _=90>=c||c>=270,L=new n({zlevel:e.zlevel,z:e.z-1,hoverable:!1,style:{x:_?h[1]+this.scaleLineLength+4:-h[1]-this.scaleLineLength-4,y:0,text:Math.round(10*x)/10+o,textAlign:_?"left":"right"},position:l.slice(),rotation:_?[-c/180*Math.PI,0,0]:[-(c+180)/180*Math.PI,0,0]});this.shapeList.push(L),x+=k*r,f+=m*this.scaleUnitAngle*5}},this)},refresh:function(e){if(e&&(this.option=e,this.series=e.series),this.legend=this.component.legend,this.legend)this.getColor=function(e){return this.legend.getColor(e)},this.isSelected=function(e){return this.legend.isSelected(e)};else{var t={},i=0;this.getColor=function(e){return t[e]?t[e]:(t[e]||(t[e]=this.zr.getColor(i++)),t[e])},this.isSelected=function(){return!0}}this.backupShapeList(),this._init()},reformOption:function(e){var t=V.merge;e=t(t(e||{},this.ecTheme.chord),h.chord),e.itemStyle.normal.label.textStyle=this.getTextStyle(e.itemStyle.normal.label.textStyle),this.z=e.z,this.zlevel=e.zlevel}},V.inherits(t,i),e("../chart").define("chord",t),t}),i("echarts/util/shape/Ribbon",["require","zrender/shape/Base","zrender/shape/util/PathProxy","zrender/tool/util","zrender/tool/area"],function(e){function t(e){i.call(this,e),this._pathProxy=new n}var i=e("zrender/shape/Base"),n=e("zrender/shape/util/PathProxy"),a=e("zrender/tool/util"),o=e("zrender/tool/area");return t.prototype={type:"ribbon",buildPath:function(e,t){var i=t.clockWise||!1,n=this._pathProxy;n.begin(e);var a=t.x,o=t.y,r=t.r,s=t.source0/180*Math.PI,l=t.source1/180*Math.PI,h=t.target0/180*Math.PI,m=t.target1/180*Math.PI,V=a+Math.cos(s)*r,U=o+Math.sin(s)*r,d=a+Math.cos(l)*r,p=o+Math.sin(l)*r,c=a+Math.cos(h)*r,u=o+Math.sin(h)*r,y=a+Math.cos(m)*r,g=o+Math.sin(m)*r;n.moveTo(V,U),n.arc(a,o,t.r,s,l,!i),n.bezierCurveTo(.7*(a-d)+d,.7*(o-p)+p,.7*(a-c)+c,.7*(o-u)+u,c,u),(t.source0!==t.target0||t.source1!==t.target1)&&(n.arc(a,o,t.r,h,m,!i),n.bezierCurveTo(.7*(a-y)+y,.7*(o-g)+g,.7*(a-V)+V,.7*(o-U)+U,V,U))},getRect:function(e){return e.__rect?e.__rect:(this._pathProxy.isEmpty()||this.buildPath(null,e),this._pathProxy.fastBoundingRect())},isCover:function(e,t){var i=this.getRect(this.style);return e>=i.x&&e<=i.x+i.width&&t>=i.y&&t<=i.y+i.height?o.isInsidePath(this._pathProxy.pathCommands,0,"fill",e,t):void 0}},a.inherits(t,i),t}),i("echarts/data/Graph",["require","zrender/tool/util"],function(e){var t=e("zrender/tool/util"),i=function(e){this._directed=e||!1,this.nodes=[],this.edges=[],this._nodesMap={},this._edgesMap={}};i.prototype.isDirected=function(){return this._directed},i.prototype.addNode=function(e,t){if(this._nodesMap[e])return this._nodesMap[e];var n=new i.Node(e,t);return this.nodes.push(n),this._nodesMap[e]=n,n},i.prototype.getNodeById=function(e){return this._nodesMap[e]},i.prototype.addEdge=function(e,t,n){if("string"==typeof e&&(e=this._nodesMap[e]),"string"==typeof t&&(t=this._nodesMap[t]),e&&t){var a=e.id+"-"+t.id;if(this._edgesMap[a])return this._edgesMap[a];var o=new i.Edge(e,t,n);return this._directed&&(e.outEdges.push(o),t.inEdges.push(o)),e.edges.push(o),e!==t&&t.edges.push(o),this.edges.push(o),this._edgesMap[a]=o,o}},i.prototype.removeEdge=function(e){var i=e.node1,n=e.node2,a=i.id+"-"+n.id;this._directed&&(i.outEdges.splice(t.indexOf(i.outEdges,e),1),n.inEdges.splice(t.indexOf(n.inEdges,e),1)),i.edges.splice(t.indexOf(i.edges,e),1),i!==n&&n.edges.splice(t.indexOf(n.edges,e),1),delete this._edgesMap[a],this.edges.splice(t.indexOf(this.edges,e),1)},i.prototype.getEdge=function(e,t){return"string"!=typeof e&&(e=e.id),"string"!=typeof t&&(t=t.id),this._directed?this._edgesMap[e+"-"+t]:this._edgesMap[e+"-"+t]||this._edgesMap[t+"-"+e]},i.prototype.removeNode=function(e){if("string"!=typeof e||(e=this._nodesMap[e])){delete this._nodesMap[e.id],this.nodes.splice(t.indexOf(this.nodes,e),1);for(var i=0;in;)e.call(t,this.nodes[n],n)?n++:(this.removeNode(this.nodes[n]),i--)},i.prototype.filterEdge=function(e,t){for(var i=this.edges.length,n=0;i>n;)e.call(t,this.edges[n],n)?n++:(this.removeEdge(this.edges[n]),i--)},i.prototype.eachNode=function(e,t){for(var i=this.nodes.length,n=0;i>n;n++)this.nodes[n]&&e.call(t,this.nodes[n],n)},i.prototype.eachEdge=function(e,t){for(var i=this.edges.length,n=0;i>n;n++)this.edges[n]&&e.call(t,this.edges[n],n)},i.prototype.clear=function(){this.nodes.length=0,this.edges.length=0,this._nodesMap={},this._edgesMap={}},i.prototype.breadthFirstTraverse=function(e,t,i,n){if("string"==typeof t&&(t=this._nodesMap[t]),t){var a="edges";"out"===i?a="outEdges":"in"===i&&(a="inEdges");for(var o=0;or;r++){var s=o.addNode(e[r].id,e[r]);s.data.value=0,n&&(s.data.outValue=s.data.inValue=0)}for(var r=0;a>r;r++)for(var l=0;a>l;l++){var h=t[r][l];n&&(o.nodes[r].data.outValue+=h,o.nodes[l].data.inValue+=h),o.nodes[r].data.value+=h,o.nodes[l].data.value+=h}for(var r=0;a>r;r++)for(var l=r;a>l;l++){var h=t[r][l];if(0!==h){var m=o.nodes[r],V=o.nodes[l],U=o.addEdge(m,V,{});if(U.data.weight=h,r!==l&&n&&t[l][r]){var d=o.addEdge(V,m,{});d.data.weight=t[l][r]}}}return o}},i}),i("echarts/layout/Chord",["require"],function(){var e=function(e){e=e||{},this.sort=e.sort||null,this.sortSub=e.sortSub||null,this.padding=.05,this.startAngle=e.startAngle||0,this.clockWise=null==e.clockWise?!1:e.clockWise,this.center=e.center||[0,0],this.directed=!0};e.prototype.run=function(e){e instanceof Array||(e=[e]);var n=e.length;if(n){for(var a=e[0],o=a.nodes.length,r=[],s=0,l=0;o>l;l++){var h=a.nodes[l],m={size:0,subGroups:[],node:h};r.push(m);for(var V=0,U=0;Ul;l++){var m=r[l];m.node.layout.startAngle=f,m.node.layout.endAngle=f+k*m.size*b,m.node.layout.subGroups=[];for(var u=0;un;n++){var o=i[n];if(o.type===d.CHART_TYPE_FORCE){if(i[n]=this.reformOption(i[n]),e=i[n].name||"",this.selectedMap[e]=t?t.isSelected(e):!0,!this.selectedMap[e])continue;this.buildMark(n),this._initSerie(o,n);break}}this.animationEffect()},_getNodeCategory:function(e,t){return e.categories&&e.categories[t.category||0]},_getNodeQueryTarget:function(e,t,i){i=i||"normal";var n=this._getNodeCategory(e,t)||{};return[t.itemStyle&&t.itemStyle[i],n&&n.itemStyle&&n.itemStyle[i],e.itemStyle[i].nodeStyle]},_getEdgeQueryTarget:function(e,t,i){return i=i||"normal",[t.itemStyle&&t.itemStyle[i],e.itemStyle[i].linkStyle]},_initSerie:function(e,t){this._temperature=1,e.matrix?this._graph=this._getSerieGraphFromDataMatrix(e):e.links&&(this._graph=this._getSerieGraphFromNodeLinks(e)),this._buildLinkShapes(e,t),this._buildNodeShapes(e,t);var i=e.roam===!0||"move"===e.roam,n=e.roam===!0||"scale"===e.roam;this.zr.modLayer(this.getZlevelBase(),{panable:i,zoomable:n}),(this.query("markPoint.effect.show")||this.query("markLine.effect.show"))&&this.zr.modLayer(d.EFFECT_ZLEVEL,{panable:i,zoomable:n}),this._initLayout(e),this._step()},_getSerieGraphFromDataMatrix:function(e){for(var t=[],i=0,n=[],a=0;an;n++){var o=i[n];if(o&&!o.ignore){var r=this._getNodeCategory(e,o),l=r?r.name:o.name;if(this.selectedMap[l]=this.isSelected(l),this.selectedMap[l]){var h=t.addNode(o.name,o);h.rawIndex=n}}}for(var n=0,a=e.links.length;a>n;n++){var m=e.links[n],V=m.source,U=m.target;"number"==typeof V&&(V=i[V],V&&(V=V.name)),"number"==typeof U&&(U=i[U],U&&(U=U.name));var d=t.addEdge(V,U,m);d&&(d.rawIndex=n)}return t.eachNode(function(e){var t=e.data.value;if(null==t){t=0;for(var i=0;ih;h++){var m=t.nodes[h];l=Math.max(m.layout.size,l),s=Math.min(m.layout.size,s)}for(var V=l-s,h=0;i>h;h++){var m=t.nodes[h];V>0?(m.layout.size=(m.layout.size-s)*(a-n)/V+n,m.layout.mass=m.layout.size/a):(m.layout.size=(a-n)/2,m.layout.mass=.5)}for(var h=0;i>h;h++){var m=t.nodes[h];if("undefined"!=typeof this.__nodePositionMap[m.id])m.layout.position=y.create(),y.copy(m.layout.position,this.__nodePositionMap[m.id]);else if("undefined"!=typeof m.data.initial)m.layout.position=y.create(),y.copy(m.layout.position,m.data.initial);else{var U=this._layout.center,d=Math.min(this._layout.width,this._layout.height);m.layout.position=o(U[0],U[1],.8*d)}var p=m.shape.style,c=m.layout.size;p.width=p.width||2*c,p.height=p.height||2*c,p.x=-p.width/2,p.y=-p.height/2,y.copy(m.shape.position,m.layout.position)}i=t.edges.length,l=-(1/0);for(var h=0;i>h;h++){var u=t.edges[h];u.layout.weight>l&&(l=u.layout.weight)}for(var h=0;i>h;h++){var u=t.edges[h];u.layout.weight/=l}this._layout.init(t,e.useWorker)},_buildNodeShapes:function(e,t){var i=this._graph,n=this.query(e,"categories");i.eachNode(function(i){var a=this._getNodeCategory(e,i.data),o=[i.data,a,e],r=this._getNodeQueryTarget(e,i.data),s=this._getNodeQueryTarget(e,i.data,"emphasis"),l=new U({style:{x:0,y:0,color:this.deepQuery(r,"color"),brushType:"both",strokeColor:this.deepQuery(r,"strokeColor")||this.deepQuery(r,"borderColor"),lineWidth:this.deepQuery(r,"lineWidth")||this.deepQuery(r,"borderWidth")},highlightStyle:{color:this.deepQuery(s,"color"),strokeColor:this.deepQuery(s,"strokeColor")||this.deepQuery(s,"borderColor"),lineWidth:this.deepQuery(s,"lineWidth")||this.deepQuery(s,"borderWidth")},clickable:e.clickable,zlevel:this.getZlevelBase(),z:this.getZBase()});l.style.color||(l.style.color=this.getColor(a?a.name:i.id)),l.style.iconType=this.deepQuery(o,"symbol");var h=this.deepQuery(o,"symbolSize")||0;"number"==typeof h&&(h=[h,h]),l.style.width=2*h[0],l.style.height=2*h[1],l.style.iconType.match("image")&&(l.style.image=l.style.iconType.replace(new RegExp("^image:\\/\\/"),""),l=new V({style:l.style,highlightStyle:l.highlightStyle,clickable:l.clickable,zlevel:this.getZlevelBase(),z:this.getZBase()})),this.deepQuery(o,"itemStyle.normal.label.show")&&(l.style.text=null==i.data.label?i.id:i.data.label,l.style.textPosition=this.deepQuery(o,"itemStyle.normal.label.position"),l.style.textColor=this.deepQuery(o,"itemStyle.normal.label.textStyle.color"),l.style.textFont=this.getFont(this.deepQuery(o,"itemStyle.normal.label.textStyle")||{})),this.deepQuery(o,"itemStyle.emphasis.label.show")&&(l.highlightStyle.textPosition=this.deepQuery(o,"itemStyle.emphasis.label.position"),l.highlightStyle.textColor=this.deepQuery(o,"itemStyle.emphasis.label.textStyle.color"),l.highlightStyle.textFont=this.getFont(this.deepQuery(o,"itemStyle.emphasis.label.textStyle")||{})),this.deepQuery(o,"draggable")&&(this.setCalculable(l),l.dragEnableTime=0,l.draggable=!0,l.ondragstart=this.shapeHandler.ondragstart,l.ondragover=null);var m="";if("undefined"!=typeof i.category){var a=n[i.category];m=a&&a.name||""}p.pack(l,e,t,i.data,i.rawIndex,i.data.name||"",i.category),this.shapeList.push(l),this.zr.addShape(l),i.shape=l},this)},_buildLinkShapes:function(e,t){for(var i=this._graph,n=i.edges.length,a=0;n>a;a++){var o=i.edges[a],r=o.data,s=o.node1,l=o.node2,V=i.getEdge(l,s),d=this._getEdgeQueryTarget(e,r),u=this.deepQuery(d,"type");e.linkSymbol&&"none"!==e.linkSymbol&&(u="line");var y="line"===u?h:m,g=new y({style:{xStart:0,yStart:0,xEnd:0,yEnd:0},clickable:this.query(e,"clickable"),highlightStyle:{},zlevel:this.getZlevelBase(),z:this.getZBase()});if(V&&V.shape&&(g.style.offset=4,V.shape.style.offset=4),c.merge(g.style,this.query(e,"itemStyle.normal.linkStyle"),!0),c.merge(g.highlightStyle,this.query(e,"itemStyle.emphasis.linkStyle"),!0),"undefined"!=typeof r.itemStyle&&(r.itemStyle.normal&&c.merge(g.style,r.itemStyle.normal,!0),r.itemStyle.emphasis&&c.merge(g.highlightStyle,r.itemStyle.emphasis,!0)),g.style.lineWidth=g.style.lineWidth||g.style.width,g.style.strokeColor=g.style.strokeColor||g.style.color,g.highlightStyle.lineWidth=g.highlightStyle.lineWidth||g.highlightStyle.width,g.highlightStyle.strokeColor=g.highlightStyle.strokeColor||g.highlightStyle.color,p.pack(g,e,t,o.data,null==o.rawIndex?a:o.rawIndex,o.data.name||s.id+" - "+l.id,s.id,l.id),this.shapeList.push(g),this.zr.addShape(g),o.shape=g,e.linkSymbol&&"none"!==e.linkSymbol){var b=new U({style:{x:-5,y:0,width:e.linkSymbolSize[0],height:e.linkSymbolSize[1],iconType:e.linkSymbol,brushType:"fill",color:g.style.strokeColor},highlightStyle:{brushType:"fill"},position:[0,0],rotation:0,zlevel:this.getZlevelBase(),z:this.getZBase()});g._symbolShape=b,this.shapeList.push(b),this.zr.addShape(b)}}},_updateLinkShapes:function(){for(var e=y.create(),t=y.create(),i=y.create(),n=y.create(),a=this._graph.edges,o=0,r=a.length;r>o;o++){var s=a[o],l=s.node1.shape,h=s.node2.shape;y.copy(i,l.position),y.copy(n,h.position);var m=s.shape.style;if(y.sub(e,i,n),y.normalize(e,e),m.offset?(t[0]=e[1],t[1]=-e[0],y.scaleAndAdd(i,i,t,m.offset),y.scaleAndAdd(n,n,t,m.offset)):"bezier-curve"===s.shape.type&&(m.cpX1=(i[0]+n[0])/2-(n[1]-i[1])/4,m.cpY1=(i[1]+n[1])/2-(i[0]-n[0])/4),m.xStart=i[0],m.yStart=i[1],m.xEnd=n[0],m.yEnd=n[1],s.shape.modSelf(),s.shape._symbolShape){var V=s.shape._symbolShape;y.copy(V.position,n),y.scaleAndAdd(V.position,V.position,e,h.style.width/2+2);var U=Math.atan2(e[1],e[0]);V.rotation=Math.PI/2-U,V.modSelf()}}},_syncNodePositions:function(){for(var e=this._graph,t=0;t.01?this._layout.step(this._steps):this.messageCenter.dispatch(d.EVENT.FORCE_LAYOUT_END,{},{},this.myChart)},refresh:function(e){if(e&&(this.option=e,this.series=this.option.series),this.legend=this.component.legend,this.legend)this.getColor=function(e){return this.legend.getColor(e)},this.isSelected=function(e){return this.legend.isSelected(e)};else{var t={},i=0;this.getColor=function(e){return t[e]?t[e]:(t[e]||(t[e]=this.zr.getColor(i++)),t[e])},this.isSelected=function(){return!0}}this._init()},dispose:function(){this.clear(),this.shapeList=null,this.effectList=null,this._layout.dispose(),this._layout=null,this.__nodePositionMap={}},getPosition:function(){var e=[];return this._graph.eachNode(function(t){t.layout&&e.push({name:t.data.name,position:Array.prototype.slice.call(t.layout.position)})}),e}},c.inherits(t,r),e("../chart").define("force",t),t}),i("echarts/layout/Force",["require","./forceLayoutWorker","zrender/tool/vector"],function(e){function t(){if("undefined"!=typeof Worker&&"undefined"!=typeof Blob)try{var e=new Blob([n.getWorkerCode()]);i=window.URL.createObjectURL(e)}catch(t){i=""}return i}var i,n=e("./forceLayoutWorker"),a=e("zrender/tool/vector"),o=window.requestAnimationFrame||window.msRequestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||function(e){setTimeout(e,16)},r="undefined"==typeof Float32Array?Array:Float32Array,s=function(e){"undefined"==typeof i&&t(),e=e||{},this.width=e.width||500,this.height=e.height||500,this.center=e.center||[this.width/2,this.height/2],this.ratioScaling=e.ratioScaling||!1,this.scaling=e.scaling||1,this.gravity="undefined"!=typeof e.gravity?e.gravity:1,this.large=e.large||!1,this.preventNodeOverlap=e.preventNodeOverlap||!1,this.preventNodeEdgeOverlap=e.preventNodeEdgeOverlap||!1,this.maxSpeedIncrease=e.maxSpeedIncrease||1,this.onupdate=e.onupdate||function(){},this.temperature=e.temperature||1,this.coolDown=e.coolDown||.99,this._layout=null,this._layoutWorker=null;var n=this,a=this._$onupdate;this._$onupdate=function(e){a.call(n,e)}};return s.prototype.updateConfig=function(){var e=this.width,t=this.height,i=Math.min(e,t),n={center:this.center,width:this.ratioScaling?e:i,height:this.ratioScaling?t:i,scaling:this.scaling||1,gravity:this.gravity||1,barnesHutOptimize:this.large,preventNodeOverlap:this.preventNodeOverlap,preventNodeEdgeOverlap:this.preventNodeEdgeOverlap,maxSpeedIncrease:this.maxSpeedIncrease};if(this._layoutWorker)this._layoutWorker.postMessage({cmd:"updateConfig",config:n});else for(var a in n)this._layout[a]=n[a]},s.prototype.init=function(e,t){if(this._layoutWorker&&(this._layoutWorker.terminate(),this._layoutWorker=null),i&&t)try{this._layoutWorker||(this._layoutWorker=new Worker(i),this._layoutWorker.onmessage=this._$onupdate),this._layout=null}catch(a){this._layoutWorker=null,this._layout||(this._layout=new n)}else this._layout||(this._layout=new n);this.temperature=1,this.graph=e;for(var o=e.nodes.length,s=new r(2*o),l=new r(o),h=new r(o),m=0;o>m;m++){var V=e.nodes[m];s[2*m]=V.layout.position[0],s[2*m+1]=V.layout.position[1],l[m]="undefined"==typeof V.layout.mass?1:V.layout.mass,h[m]="undefined"==typeof V.layout.size?1:V.layout.size,V.layout.__index=m}o=e.edges.length;for(var U=new r(2*o),d=new r(o),m=0;o>m;m++){var p=e.edges[m];U[2*m]=p.node1.layout.__index,U[2*m+1]=p.node2.layout.__index,d[m]=p.layout.weight||1}this._layoutWorker?this._layoutWorker.postMessage({cmd:"init",nodesPosition:s,nodesMass:l,nodesSize:h,edges:U,edgesWeight:d}):(this._layout.initNodes(s,l,h),this._layout.initEdges(U,d)),this.updateConfig()},s.prototype.step=function(e){var t=this.graph.nodes;if(this._layoutWorker){for(var i=new r(2*t.length),n=0;nn;n++)this.temperature*=this.coolDown}else{o(this._$onupdate);for(var n=0;nn;n++)this._layout.temperature=this.temperature,this._layout.update(),this.temperature*=this.coolDown}},s.prototype._$onupdate=function(e){if(this._layoutWorker){for(var t=new Float32Array(e.data),i=0;i0&&(a=1/Math.sqrt(a),e[0]=t[0]*a,e[1]=t[1]*a),e},negate:function(e,t){return e[0]=-t[0],e[1]=-t[1],e},copy:function(e,t){return e[0]=t[0],e[1]=t[1],e},set:function(e,t,i){return e[0]=t,e[1]=i,e}}:e("zrender/tool/vector");var l="undefined"==typeof Float32Array?Array:Float32Array;if(t.prototype.beforeUpdate=function(){for(var e=0;e=e&&this.bbox[1]<=t&&this.bbox[3]>=t},t.prototype.setBBox=function(e,t,i,n){this.bbox[0]=e,this.bbox[1]=t,this.bbox[2]=i,this.bbox[3]=n,this.size=(i-e+n-t)/2},t.prototype._newSubRegion=function(){var e=this.subRegions[this.nSubRegions];return e||(e=new t,this.subRegions[this.nSubRegions]=e),this.nSubRegions++,e},t.prototype._addNodeToSubRegion=function(e){var t=this.findSubRegion(e.position[0],e.position[1]),i=this.bbox;if(!t){var n=(i[0]+i[2])/2,a=(i[1]+i[3])/2,o=(i[2]-i[0])/2,r=(i[3]-i[1])/2,s=e.position[0]>=n?1:0,l=e.position[1]>=a?1:0,t=this._newSubRegion();t.setBBox(s*o+i[0],l*r+i[1],(s+1)*o+i[0],(l+1)*r+i[1])}t.addNode(e)},t.prototype._updateCenterOfMass=function(e){null==this.centerOfMass&&(this.centerOfMass=r.create());var t=this.centerOfMass[0]*this.mass,i=this.centerOfMass[1]*this.mass;t+=e.position[0]*e.mass,i+=e.position[1]*e.mass,this.mass+=e.mass,this.centerOfMass[0]=t/this.mass,this.centerOfMass[1]=i/this.mass},a.prototype.nodeToNodeRepulsionFactor=function(e,t,i){return i*i*e/t},a.prototype.edgeToNodeRepulsionFactor=function(e,t,i){return i*e/t},a.prototype.attractionFactor=function(e,t,i){return e*t/i},a.prototype.initNodes=function(e,t,n){this.temperature=1;var a=e.length/2;this.nodes.length=0;for(var o="undefined"!=typeof n,r=0;a>r;r++){var s=new i;s.position[0]=e[2*r],s.position[1]=e[2*r+1],s.mass=t[r],o&&(s.size=n[r]),this.nodes.push(s)}this._massArr=t,o&&(this._sizeArr=n)},a.prototype.initEdges=function(e,t){var i=e.length/2;this.edges.length=0;for(var a="undefined"!=typeof t,o=0;i>o;o++){var r=e[2*o],s=e[2*o+1],l=this.nodes[r],h=this.nodes[s];if(l&&h){l.outDegree++,h.inDegree++;var m=new n(l,h);a&&(m.weight=t[o]),this.edges.push(m)}}},a.prototype.update=function(){var e=this.nodes.length;if(this.updateBBox(),this._k=.4*this.scaling*Math.sqrt(this.width*this.height/e),this.barnesHutOptimize){this._rootRegion.setBBox(this.bbox[0],this.bbox[1],this.bbox[2],this.bbox[3]),this._rootRegion.beforeUpdate();for(var t=0;e>t;t++)this._rootRegion.addNode(this.nodes[t]);this._rootRegion.afterUpdate()}else{var i=0,n=this._rootRegion.centerOfMass;r.set(n,0,0);for(var t=0;e>t;t++){var a=this.nodes[t];i+=a.mass,r.scaleAndAdd(n,n,a.position,a.mass); + +}i>0&&r.scale(n,n,1/i)}this.updateForce(),this.updatePosition()},a.prototype.updateForce=function(){for(var e=this.nodes.length,t=0;e>t;t++){var i=this.nodes[t];r.copy(i.forcePrev,i.force),r.copy(i.speedPrev,i.speed),r.set(i.force,0,0)}this.updateNodeNodeForce(),this.gravity>0&&this.updateGravityForce(),this.updateEdgeForce(),this.preventNodeEdgeOverlap&&this.updateNodeEdgeForce()},a.prototype.updatePosition=function(){for(var e=this.nodes.length,t=r.create(),i=0;e>i;i++){var n=this.nodes[i],a=n.speed;r.scale(n.force,n.force,1/30);var o=r.len(n.force)+.1,s=Math.min(o,500)/o;r.scale(n.force,n.force,s),r.add(a,a,n.force),r.scale(a,a,this.temperature),r.sub(t,a,n.speedPrev);var l=r.len(t);if(l>0){r.scale(t,t,1/l);var h=r.len(n.speedPrev);h>0&&(l=Math.min(l/h,this.maxSpeedIncrease)*h,r.scaleAndAdd(a,n.speedPrev,t,l))}var m=r.len(a),s=Math.min(m,100)/(m+.1);r.scale(a,a,s),r.add(n.position,n.position,a)}},a.prototype.updateNodeNodeForce=function(){for(var e=this.nodes.length,t=0;e>t;t++){var i=this.nodes[t];if(this.barnesHutOptimize)this.applyRegionToNodeRepulsion(this._rootRegion,i);else for(var n=t+1;e>n;n++){var a=this.nodes[n];this.applyNodeToNodeRepulsion(i,a,!1)}}},a.prototype.updateGravityForce=function(){for(var e=0;ethis.barnesHutTheta*t.size*t.size){var a=this._k*this._k*(i.mass+t.mass)/(n+1);r.scaleAndAdd(i.force,i.force,e,2*a)}else for(var o=0;o0?o=this.nodeToNodeRepulsionFactor(s,l,this._k):0>=l&&(o=this._k*this._k*10*s)):o=this.nodeToNodeRepulsionFactor(s,l,this._k),n||r.scaleAndAdd(t.force,t.force,e,2*o),r.scaleAndAdd(i.force,i.force,e,2*-o)}}}}(),a.prototype.applyEdgeAttraction=function(){var e=r.create();return function(t){var i=t.node1,n=t.node2;r.sub(e,i.position,n.position);var a,o=r.len(e);a=0===this.edgeWeightInfluence?1:1==this.edgeWeightInfluence?t.weight:Math.pow(t.weight,this.edgeWeightInfluence);var s;if(!(this.preventOverlap&&(o=o-i.size-n.size,0>=o))){var s=this.attractionFactor(a,o,this._k);r.scaleAndAdd(i.force,i.force,e,-s),r.scaleAndAdd(n.force,n.force,e,s)}}}(),a.prototype.applyNodeGravity=function(){var e=r.create();return function(t){r.sub(e,this.center,t.position),this.width>this.height?e[1]*=this.width/this.height:e[0]*=this.height/this.width;var i=r.len(e)/100;this.strongGravity?r.scaleAndAdd(t.force,t.force,e,i*this.gravity*t.mass):r.scaleAndAdd(t.force,t.force,e,this.gravity*t.mass/(i+1))}}(),a.prototype.applyEdgeToNodeRepulsion=function(){var e=r.create(),t=r.create(),i=r.create();return function(n,a){var o=n.node1,s=n.node2;if(o!==a&&s!==a){r.sub(e,s.position,o.position),r.sub(t,a.position,o.position);var l=r.len(e);r.scale(e,e,1/l);var h=r.dot(e,t);if(!(0>h||h>l)){r.scaleAndAdd(i,o.position,e,h);var m=r.dist(i,a.position)-a.size,V=this.edgeToNodeRepulsionFactor(a.mass,Math.max(m,.1),100);r.sub(e,a.position,i),r.normalize(e,e),r.scaleAndAdd(a.force,a.force,e,V),r.scaleAndAdd(o.force,o.force,e,-V),r.scaleAndAdd(s.force,s.force,e,-V)}}}}(),a.prototype.updateBBox=function(){for(var e=1/0,t=1/0,i=-(1/0),n=-(1/0),a=0;an;n++){var o=h.nodes[n];o.position[0]=t[2*n],o.position[1]=t[2*n+1]}}else switch(e.data.cmd){case"init":h||(h=new a),h.initNodes(e.data.nodesPosition,e.data.nodesMass,e.data.nodesSize),h.initEdges(e.data.edges,e.data.edgesWeight);break;case"updateConfig":if(h)for(var r in e.data.config)h[r]=e.data.config[r];break;case"update":var s=e.data.steps;if(h){var i=h.nodes.length,t=new Float32Array(2*i);h.temperature=e.data.temperature;for(var n=0;s>n;n++)h.update(),h.temperature*=e.data.coolDown;for(var n=0;i>n;n++){var o=h.nodes[n];t[2*n]=o.position[0],t[2*n+1]=o.position[1]}self.postMessage(t.buffer,[t.buffer])}else{var l=new Float32Array;self.postMessage(l.buffer,[l.buffer])}}}}return a}),i("echarts/chart/map",["require","./base","zrender/shape/Text","zrender/shape/Path","zrender/shape/Circle","zrender/shape/Rectangle","zrender/shape/Line","zrender/shape/Polygon","zrender/shape/Ellipse","zrender/shape/Image","../component/dataRange","../component/roamController","../layer/heatmap","../config","../util/ecData","zrender/tool/util","zrender/config","zrender/tool/event","../util/mapData/params","../util/mapData/textFixed","../util/mapData/geoCoord","../util/projection/svg","../util/projection/normal","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o);var r=this;r._onmousewheel=function(e){return r.__onmousewheel(e)},r._onmousedown=function(e){return r.__onmousedown(e)},r._onmousemove=function(e){return r.__onmousemove(e)},r._onmouseup=function(e){return r.__onmouseup(e)},r._onroamcontroller=function(e){return r.__onroamcontroller(e)},r._ondrhoverlink=function(e){return r.__ondrhoverlink(e)},this._isAlive=!0,this._selectedMode={},this._activeMapType={},this._clickable={},this._hoverable={},this._showLegendSymbol={},this._selected={},this._mapTypeMap={},this._mapDataMap={},this._nameMap={},this._specialArea={},this._refreshDelayTicket,this._mapDataRequireCounter,this._markAnimation=!1,this._hoverLinkMap={},this._roamMap={},this._scaleLimitMap={},this._mx,this._my,this._mousedown,this._justMove,this._curMapType,this.refresh(a),this.zr.on(c.EVENT.MOUSEWHEEL,this._onmousewheel),this.zr.on(c.EVENT.MOUSEDOWN,this._onmousedown),t.bind(U.EVENT.ROAMCONTROLLER,this._onroamcontroller),t.bind(U.EVENT.DATA_RANGE_HOVERLINK,this._ondrhoverlink)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Path"),o=e("zrender/shape/Circle"),r=e("zrender/shape/Rectangle"),s=e("zrender/shape/Line"),l=e("zrender/shape/Polygon"),h=e("zrender/shape/Ellipse"),m=e("zrender/shape/Image");e("../component/dataRange"),e("../component/roamController");var V=e("../layer/heatmap"),U=e("../config");U.map={zlevel:0,z:2,mapType:"china",showLegendSymbol:!0,dataRangeHoverLink:!0,hoverable:!0,clickable:!0,itemStyle:{normal:{borderColor:"rgba(0,0,0,0)",borderWidth:1,areaStyle:{color:"#ccc"},label:{show:!1,textStyle:{color:"rgb(139,69,19)"}}},emphasis:{borderColor:"rgba(0,0,0,0)",borderWidth:1,areaStyle:{color:"rgba(255,215,0,0.8)"},label:{show:!1,textStyle:{color:"rgb(100,0,0)"}}}}};var d=e("../util/ecData"),p=e("zrender/tool/util"),c=e("zrender/config"),u=e("zrender/tool/event"),y=e("../util/mapData/params").params,g=e("../util/mapData/textFixed"),b=e("../util/mapData/geoCoord");return t.prototype={type:U.CHART_TYPE_MAP,_buildShape:function(){var e=this.series;this.selectedMap={},this._activeMapType={};for(var t,i,n,a,o=this.component.legend,r={},s={},l={},h={},m=0,V=e.length;V>m;m++)if(e[m].type==U.CHART_TYPE_MAP&&(e[m]=this.reformOption(e[m]),i=e[m].mapType,s[i]=s[i]||{},s[i][m]=!0,l[i]=l[i]||e[m].mapValuePrecision,this._scaleLimitMap[i]=this._scaleLimitMap[i]||{},e[m].scaleLimit&&p.merge(this._scaleLimitMap[i],e[m].scaleLimit,!0),this._roamMap[i]=e[m].roam||this._roamMap[i],(null==this._hoverLinkMap[i]||this._hoverLinkMap[i])&&(this._hoverLinkMap[i]=e[m].dataRangeHoverLink),this._nameMap[i]=this._nameMap[i]||{},e[m].nameMap&&p.merge(this._nameMap[i],e[m].nameMap,!0),this._activeMapType[i]=!0,e[m].textFixed&&p.merge(g,e[m].textFixed,!0),e[m].geoCoord&&p.merge(b,e[m].geoCoord,!0),this._selectedMode[i]=this._selectedMode[i]||e[m].selectedMode,(null==this._hoverable[i]||this._hoverable[i])&&(this._hoverable[i]=e[m].hoverable),(null==this._clickable[i]||this._clickable[i])&&(this._clickable[i]=e[m].clickable),(null==this._showLegendSymbol[i]||this._showLegendSymbol[i])&&(this._showLegendSymbol[i]=e[m].showLegendSymbol),h[i]=h[i]||e[m].mapValueCalculation,t=e[m].name,this.selectedMap[t]=o?o.isSelected(t):!0,this.selectedMap[t])){r[i]=r[i]||{},n=e[m].data;for(var d=0,c=n.length;c>d;d++){a=this._nameChange(i,n[d].name),r[i][a]=r[i][a]||{seriesIndex:[],valueMap:{},precision:0};for(var u in n[d])"value"!=u?r[i][a][u]=n[d][u]:isNaN(n[d].value)||(null==r[i][a].value&&(r[i][a].value=0),r[i][a].precision=Math.max(this.getPrecision(+n[d].value),r[i][a].precision),r[i][a].value+=+n[d].value,r[i][a].valueMap[m]=+n[d].value);r[i][a].seriesIndex.push(m)}}this._mapDataRequireCounter=0;for(var f in r)this._mapDataRequireCounter++;this._clearSelected(),0===this._mapDataRequireCounter&&(this.clear(),this.zr&&this.zr.delShape(this.lastShapeList),this.lastShapeList=[]);for(var f in r){for(var c in r[f]){"average"==h[f]&&(r[f][c].value/=r[f][c].seriesIndex.length);var k=r[f][c].value;null!=k&&(r[f][c].value=k.toFixed(null==l[f]?r[f][c].precision:l[f])-0)}this._mapDataMap[f]=this._mapDataMap[f]||{},this._mapDataMap[f].mapData?this._mapDataCallback(f,r[f],s[f])(this._mapDataMap[f].mapData):y[f.replace(/\|.*/,"")].getGeoJson&&(this._specialArea[f]=y[f.replace(/\|.*/,"")].specialArea||this._specialArea[f],y[f.replace(/\|.*/,"")].getGeoJson(this._mapDataCallback(f,r[f],s[f])))}},_mapDataCallback:function(t,i,n){var a=this;return function(o){a._isAlive&&null!=a._activeMapType[t]&&(-1!=t.indexOf("|")&&(o=a._getSubMapData(t,o)),a._mapDataMap[t].mapData=o,o.firstChild?(a._mapDataMap[t].rate=1,a._mapDataMap[t].projection=e("../util/projection/svg")):(a._mapDataMap[t].rate=.75,a._mapDataMap[t].projection=e("../util/projection/normal")),a._buildMap(t,a._getProjectionData(t,o,n),i,n),a._buildMark(t,n),--a._mapDataRequireCounter<=0&&(a.addShapeList(),a.zr.refreshNextFrame()),a._buildHeatmap(t))}},_clearSelected:function(){for(var e in this._selected)this._activeMapType[this._mapTypeMap[e]]||(delete this._selected[e],delete this._mapTypeMap[e])},_getSubMapData:function(e,t){for(var i=e.replace(/^.*\|/,""),n=t.features,a=0,o=n.length;o>a;a++)if(n[a].properties&&n[a].properties.name==i){n=n[a],"United States of America"==i&&n.geometry.coordinates.length>1&&(n={geometry:{coordinates:n.geometry.coordinates.slice(5,6),type:n.geometry.type},id:n.id,properties:n.properties,type:n.type});break}return{type:"FeatureCollection",features:[n]}},_getProjectionData:function(e,t,i){var n,a=this._mapDataMap[e].projection,o=[],r=this._mapDataMap[e].bbox||a.getBbox(t,this._specialArea[e]);n=this._mapDataMap[e].hasRoam?this._mapDataMap[e].transform:this._getTransform(r,i,this._mapDataMap[e].rate);var s,l=this._mapDataMap[e].lastTransform||{scale:{}};n.left!=l.left||n.top!=l.top||n.scale.x!=l.scale.x||n.scale.y!=l.scale.y?(s=a.geoJson2Path(t,n,this._specialArea[e]),l=p.clone(n)):(n=this._mapDataMap[e].transform,s=this._mapDataMap[e].pathArray),this._mapDataMap[e].bbox=r,this._mapDataMap[e].transform=n,this._mapDataMap[e].lastTransform=l,this._mapDataMap[e].pathArray=s;for(var h=[n.left,n.top],m=0,V=s.length;V>m;m++)o.push(this._getSingleProvince(e,s[m],h));if(this._specialArea[e])for(var U in this._specialArea[e])o.push(this._getSpecialProjectionData(e,t,U,this._specialArea[e][U],h));if("china"==e){var d=this.geo2pos(e,b["南海诸岛"]||y["南海诸岛"].textCoord),c=n.scale.x/10.5,u=[32*c+d[0],83*c+d[1]];g["南海诸岛"]&&(u[0]+=g["南海诸岛"][0],u[1]+=g["南海诸岛"][1]),o.push({name:this._nameChange(e,"南海诸岛"),path:y["南海诸岛"].getPath(d,c),position:h,textX:u[0],textY:u[1]})}return o},_getSpecialProjectionData:function(t,i,n,a,o){i=this._getSubMapData("x|"+n,i);var r=e("../util/projection/normal"),s=r.getBbox(i),l=this.geo2pos(t,[a.left,a.top]),h=this.geo2pos(t,[a.left+a.width,a.top+a.height]),m=Math.abs(h[0]-l[0]),V=Math.abs(h[1]-l[1]),U=s.width,d=s.height,p=m/.75/U,c=V/d;p>c?(p=.75*c,m=U*p):(c=p,p=.75*c,V=d*c);var u={OffsetLeft:l[0],OffsetTop:l[1],scale:{x:p,y:c}},y=r.geoJson2Path(i,u);return this._getSingleProvince(t,y[0],o)},_getSingleProvince:function(e,t,i){var n,a=t.properties.name,o=g[a]||[0,0];if(b[a])n=this.geo2pos(e,b[a]);else if(t.cp)n=[t.cp[0]+o[0],t.cp[1]+o[1]];else{var r=this._mapDataMap[e].bbox;n=this.geo2pos(e,[r.left+r.width/2,r.top+r.height/2]),n[0]+=o[0],n[1]+=o[1]}return t.name=this._nameChange(e,a),t.position=i,t.textX=n[0],t.textY=n[1],t},_getTransform:function(e,t,i){var n,a,o,r,s,l,h,m=this.series,V=this.zr.getWidth(),U=this.zr.getHeight(),d=Math.round(.02*Math.min(V,U));for(var p in t)n=m[p].mapLocation||{},o=n.x||o,s=n.y||s,l=n.width||l,h=n.height||h;a=this.parsePercent(o,V),a=isNaN(a)?d:a,r=this.parsePercent(s,U),r=isNaN(r)?d:r,l=null==l?V-a-2*d:this.parsePercent(l,V),h=null==h?U-r-2*d:this.parsePercent(h,U);var c=e.width,u=e.height,y=l/i/c,g=h/u;if(y>g?(y=g*i,l=c*y):(g=y,y=g*i,h=u*g),isNaN(o))switch(o=o||"center",o+""){case"center":a=Math.floor((V-l)/2);break;case"right":a=V-l}if(isNaN(s))switch(s=s||"center",s+""){case"center":r=Math.floor((U-h)/2);break;case"bottom":r=U-h}return{left:a,top:r,width:l,height:h,baseScale:1,scale:{x:y,y:g}}},_buildMap:function(e,t,i,m){for(var V,c,u,y,g,b,f,k,x,_,L,W=this.series,X=this.component.legend,v=this.component.dataRange,w=0,K=t.length;K>w;w++){if(k=p.clone(t[w]),x={name:k.name,path:k.path,position:p.clone(k.position)},c=k.name,u=i[c]){g=[u],V="";for(var I=0,J=u.seriesIndex.length;J>I;I++){var C=W[u.seriesIndex[I]];g.push(C),V+=C.name+" ",X&&this._showLegendSymbol[e]&&X.hasColor(C.name)&&this.shapeList.push(new o({zlevel:C.zlevel,z:C.z+1,position:p.clone(k.position),_mapType:e,style:{x:k.textX+3+7*I,y:k.textY-10,r:3,color:X.getColor(C.name)},hoverable:!1}))}y=u.value}else{u={name:c,value:"-"},V="",g=[];for(var S in m)g.push(W[S]);y="-"}switch(this.ecTheme.map&&g.push(this.ecTheme.map),g.push(U.map),b=v&&!isNaN(y)?v.getColor(y):null,k.color=k.color||b||this.getItemStyleColor(this.deepQuery(g,"itemStyle.normal.color"),u.seriesIndex,-1,u)||this.deepQuery(g,"itemStyle.normal.areaStyle.color"),k.strokeColor=k.strokeColor||this.deepQuery(g,"itemStyle.normal.borderColor"),k.lineWidth=k.lineWidth||this.deepQuery(g,"itemStyle.normal.borderWidth"),x.color=this.getItemStyleColor(this.deepQuery(g,"itemStyle.emphasis.color"),u.seriesIndex,-1,u)||this.deepQuery(g,"itemStyle.emphasis.areaStyle.color")||k.color,x.strokeColor=this.deepQuery(g,"itemStyle.emphasis.borderColor")||k.strokeColor,x.lineWidth=this.deepQuery(g,"itemStyle.emphasis.borderWidth")||k.lineWidth,k.brushType=x.brushType=k.brushType||"both",k.lineJoin=x.lineJoin="round",k._name=x._name=c,f=this.deepQuery(g,"itemStyle.normal.label.textStyle"),L={zlevel:this.getZlevelBase(),z:this.getZBase()+1,position:p.clone(k.position),_mapType:e,_geo:this.pos2geo(e,[k.textX,k.textY]),style:{brushType:"fill",x:k.textX,y:k.textY,text:this.getLabelText(c,y,g,"normal"),_name:c,textAlign:"center",color:this.deepQuery(g,"itemStyle.normal.label.show")?this.deepQuery(g,"itemStyle.normal.label.textStyle.color"):"rgba(0,0,0,0)",textFont:this.getFont(f)}},L._style=p.clone(L.style),L.highlightStyle=p.clone(L.style),this.deepQuery(g,"itemStyle.emphasis.label.show")?(L.highlightStyle.text=this.getLabelText(c,y,g,"emphasis"),L.highlightStyle.color=this.deepQuery(g,"itemStyle.emphasis.label.textStyle.color")||L.style.color,f=this.deepQuery(g,"itemStyle.emphasis.label.textStyle")||f,L.highlightStyle.textFont=this.getFont(f)):L.highlightStyle.color="rgba(0,0,0,0)",_={zlevel:this.getZlevelBase(),z:this.getZBase(),position:p.clone(k.position),style:k,highlightStyle:x,_style:p.clone(k),_mapType:e},null!=k.scale&&(_.scale=p.clone(k.scale)),L=new n(L),_.style.shapeType){case"rectangle":_=new r(_);break;case"line":_=new s(_);break;case"circle":_=new o(_);break;case"polygon":_=new l(_);break;case"ellipse":_=new h(_);break;default:_=new a(_),_.buildPathArray&&(_.style.pathArray=_.buildPathArray(_.style.path))}(this._selectedMode[e]&&this._selected[c]&&u.selected!==!1||u.selected===!0)&&(L.style=L.highlightStyle,_.style=_.highlightStyle),L.clickable=_.clickable=this._clickable[e]&&(null==u.clickable||u.clickable),this._selectedMode[e]&&(this._selected[c]=null!=this._selected[c]?this._selected[c]:u.selected,this._mapTypeMap[c]=e,(null==u.selectable||u.selectable)&&(_.clickable=L.clickable=!0,_.onclick=L.onclick=this.shapeHandler.onclick)),this._hoverable[e]&&(null==u.hoverable||u.hoverable)?(L.hoverable=_.hoverable=!0,_.hoverConnect=L.id,L.hoverConnect=_.id):L.hoverable=_.hoverable=!1,d.pack(L,{name:V,tooltip:this.deepQuery(g,"tooltip")},0,u,0,c),this.shapeList.push(L),d.pack(_,{name:V,tooltip:this.deepQuery(g,"tooltip")},0,u,0,c),this.shapeList.push(_)}},_buildMark:function(e,t){this._seriesIndexToMapType=this._seriesIndexToMapType||{},this.markAttachStyle=this.markAttachStyle||{};var i=[this._mapDataMap[e].transform.left,this._mapDataMap[e].transform.top];"none"==e&&(i=[0,0]);for(var n in t)this._seriesIndexToMapType[n]=e,this.markAttachStyle[n]={position:i,_mapType:e},this.buildMark(n)},_buildHeatmap:function(e){for(var t=this.series,i=0,n=t.length;n>i;i++)if(t[i].heatmap){var a=t[i].heatmap.data;if(t[i].heatmap.needsTransform===!1){for(var o=[],r=0,s=a.length;s>r;++r)o.push([a[r][3],a[r][4],a[r][2]]);var l=[0,0]}else{var h=t[i].heatmap._geoData;if(void 0===h){t[i].heatmap._geoData=[];for(var r=0,s=a.length;s>r;++r)t[i].heatmap._geoData[r]=a[r];h=t[i].heatmap._geoData}for(var s=a.length,U=0;s>U;++U)a[U]=this.geo2pos(e,[h[U][0],h[U][1]]);var l=[this._mapDataMap[e].transform.left,this._mapDataMap[e].transform.top]}var d=new V(t[i].heatmap),p=d.getCanvas(a[0][3]?o:a,this.zr.getWidth(),this.zr.getHeight()),c=new m({zlevel:this.getZlevelBase(),z:this.getZBase()+1,position:l,scale:[1,1],hoverable:!1,style:{x:0,y:0,image:p,width:p.width,height:p.height}});c.type="heatmap",c._mapType=e,this.shapeList.push(c),this.zr.addShape(c)}},getMarkCoord:function(e,t){return t.geoCoord||b[t.name]?this.geo2pos(this._seriesIndexToMapType[e],t.geoCoord||b[t.name]):[0,0]},getMarkGeo:function(e){return e.geoCoord||b[e.name]},_nameChange:function(e,t){return this._nameMap[e][t]||t},getLabelText:function(e,t,i,n){var a=this.deepQuery(i,"itemStyle."+n+".label.formatter");return a?"function"==typeof a?a.call(this.myChart,e,t):"string"==typeof a?(a=a.replace("{a}","{a0}").replace("{b}","{b0}"),a=a.replace("{a0}",e).replace("{b0}",t)):void 0:e},_findMapTypeByPos:function(e,t){var i,n,a,o,r;for(var s in this._mapDataMap)if(i=this._mapDataMap[s].transform,i&&this._roamMap[s]&&this._activeMapType[s]&&(n=i.left,a=i.top,o=i.width,r=i.height,e>=n&&n+o>=e&&t>=a&&a+r>=t))return s},__onmousewheel:function(e){function t(e,t){for(var i=0;in;n++){var o=this.shapeList[n];if(o.__animating)return}var r,s,l=e.event,h=u.getX(l),m=u.getY(l),V=u.getDelta(l),d=e.mapTypeControl;d||(d={},s=this._findMapTypeByPos(h,m),s&&this._roamMap[s]&&"move"!=this._roamMap[s]&&(d[s]=!0));var p=!1;for(s in d)if(d[s]){p=!0;var c=this._mapDataMap[s].transform,y=c.left,g=c.top,b=c.width,f=c.height,k=this.pos2geo(s,[h-y,m-g]);if(V>0){if(r=1.2,null!=this._scaleLimitMap[s].max&&c.baseScale>=this._scaleLimitMap[s].max)continue}else if(r=1/1.2,null!=this._scaleLimitMap[s].min&&c.baseScale<=this._scaleLimitMap[s].min)continue;c.baseScale*=r,c.scale.x*=r,c.scale.y*=r,c.width=b*r,c.height=f*r,this._mapDataMap[s].hasRoam=!0,this._mapDataMap[s].transform=c,k=this.geo2pos(s,k),c.left-=k[0]-(h-y),c.top-=k[1]-(m-g),this._mapDataMap[s].transform=c,this.clearEffectShape(!0);for(var n=0,a=this.shapeList.length;a>n;n++){var o=this.shapeList[n];if(o._mapType==s){var x=o.type,_=o.style;switch(o.position[0]=c.left,o.position[1]=c.top,x){case"path":case"symbol":case"circle":case"rectangle":case"polygon":case"line":case"ellipse":case"heatmap":o.scale[0]*=r,o.scale[1]*=r;break;case"mark-line":i(_,r);break;case"polyline":t(_,r);break;case"shape-bundle":for(var L=0;L<_.shapeList.length;L++){var W=_.shapeList[L];"mark-line"==W.type?i(W.style,r):"polyline"==W.type&&t(W.style,r)}break;case"icon":case"image":k=this.geo2pos(s,o._geo),_.x=_._x=k[0]-_.width/2,_.y=_._y=k[1]-_.height/2;break;default:k=this.geo2pos(s,o._geo),_.x=k[0],_.y=k[1],"text"==x&&(o._style.x=o.highlightStyle.x=k[0],o._style.y=o.highlightStyle.y=k[1])}this.zr.modShape(o.id)}}}if(p){u.stop(l),this.zr.refreshNextFrame();var X=this;clearTimeout(this._refreshDelayTicket),this._refreshDelayTicket=setTimeout(function(){X&&X.shapeList&&X.animationEffect()},100),this.messageCenter.dispatch(U.EVENT.MAP_ROAM,e.event,{type:"scale"},this.myChart)}}},__onmousedown:function(e){if(!(this.shapeList.length<=0)){var t=e.target;if(!t||!t.draggable){var i=e.event,n=u.getX(i),a=u.getY(i),o=this._findMapTypeByPos(n,a);if(o&&this._roamMap[o]&&"scale"!=this._roamMap[o]){this._mousedown=!0,this._mx=n,this._my=a,this._curMapType=o,this.zr.on(c.EVENT.MOUSEUP,this._onmouseup);var r=this;setTimeout(function(){r.zr.on(c.EVENT.MOUSEMOVE,r._onmousemove)},100)}}}},__onmousemove:function(e){if(this._mousedown&&this._isAlive){var t=e.event,i=u.getX(t),n=u.getY(t),a=this._mapDataMap[this._curMapType].transform;a.hasRoam=!0,a.left-=this._mx-i,a.top-=this._my-n,this._mx=i,this._my=n,this._mapDataMap[this._curMapType].transform=a;for(var o=0,r=this.shapeList.length;r>o;o++)this.shapeList[o]._mapType==this._curMapType&&(this.shapeList[o].position[0]=a.left,this.shapeList[o].position[1]=a.top,this.zr.modShape(this.shapeList[o].id));this.messageCenter.dispatch(U.EVENT.MAP_ROAM,e.event,{type:"move"},this.myChart),this.clearEffectShape(!0),this.zr.refreshNextFrame(),this._justMove=!0,u.stop(t)}},__onmouseup:function(e){var t=e.event;this._mx=u.getX(t),this._my=u.getY(t),this._mousedown=!1;var i=this;setTimeout(function(){i._justMove&&i.animationEffect(),i._justMove=!1,i.zr.un(c.EVENT.MOUSEMOVE,i._onmousemove),i.zr.un(c.EVENT.MOUSEUP,i._onmouseup)},120)},__onroamcontroller:function(e){var t=e.event;t.zrenderX=this.zr.getWidth()/2,t.zrenderY=this.zr.getHeight()/2;var i=e.mapTypeControl,n=0,a=0,o=e.step;switch(e.roamType){case"scaleUp":return t.zrenderDelta=1,void this.__onmousewheel({event:t,mapTypeControl:i});case"scaleDown":return t.zrenderDelta=-1,void this.__onmousewheel({event:t,mapTypeControl:i});case"up":n=-o;break;case"down":n=o;break;case"left":a=-o;break;case"right":a=o}var r,s;for(s in i)this._mapDataMap[s]&&this._activeMapType[s]&&(r=this._mapDataMap[s].transform,r.hasRoam=!0,r.left-=a,r.top-=n,this._mapDataMap[s].transform=r);for(var l=0,h=this.shapeList.length;h>l;l++)s=this.shapeList[l]._mapType,i[s]&&this._activeMapType[s]&&(r=this._mapDataMap[s].transform,this.shapeList[l].position[0]=r.left,this.shapeList[l].position[1]=r.top,this.zr.modShape(this.shapeList[l].id));this.messageCenter.dispatch(U.EVENT.MAP_ROAM,e.event,{type:"move"},this.myChart),this.clearEffectShape(!0),this.zr.refreshNextFrame(),clearTimeout(this.dircetionTimer);var m=this;this.dircetionTimer=setTimeout(function(){m.animationEffect()},150)},__ondrhoverlink:function(e){for(var t,i,n=0,a=this.shapeList.length;a>n;n++)t=this.shapeList[n]._mapType,this._hoverLinkMap[t]&&this._activeMapType[t]&&(i=d.get(this.shapeList[n],"value"),null!=i&&i>=e.valueMin&&i<=e.valueMax&&this.zr.addHoverShape(this.shapeList[n]))},onclick:function(e){if(this.isClick&&e.target&&!this._justMove&&"icon"!=e.target.type){this.isClick=!1;var t=e.target,i=t.style._name,n=this.shapeList.length,a=t._mapType||"";if("single"==this._selectedMode[a])for(var o in this._selected)if(this._selected[o]&&this._mapTypeMap[o]==a){for(var r=0;n>r;r++)this.shapeList[r].style._name==o&&this.shapeList[r]._mapType==a&&(this.shapeList[r].style=this.shapeList[r]._style,this.zr.modShape(this.shapeList[r].id));o!=i&&(this._selected[o]=!1)}this._selected[i]=!this._selected[i];for(var r=0;n>r;r++)this.shapeList[r].style._name==i&&this.shapeList[r]._mapType==a&&(this.shapeList[r].style=this._selected[i]?this.shapeList[r].highlightStyle:this.shapeList[r]._style,this.zr.modShape(this.shapeList[r].id));this.messageCenter.dispatch(U.EVENT.MAP_SELECTED,e.event,{selected:this._selected,target:i},this.myChart),this.zr.refreshNextFrame();var s=this;setTimeout(function(){s.zr.trigger(c.EVENT.MOUSEMOVE,e.event)},100)}},refresh:function(e){e&&(this.option=e,this.series=e.series),this._mapDataRequireCounter>0?this.clear():this.backupShapeList(),this._buildShape(),this.zr.refreshHover()},ondataRange:function(e,t){this.component.dataRange&&(this.refresh(),t.needRefresh=!0)},pos2geo:function(e,t){return this._mapDataMap[e].transform?this._mapDataMap[e].projection.pos2geo(this._mapDataMap[e].transform,t):null},getGeoByPos:function(e,t){if(!this._mapDataMap[e].transform)return null;var i=[this._mapDataMap[e].transform.left,this._mapDataMap[e].transform.top];return t instanceof Array?(t[0]-=i[0],t[1]-=i[1]):(t.x-=i[0],t.y-=i[1]),this.pos2geo(e,t)},geo2pos:function(e,t){return this._mapDataMap[e].transform?this._mapDataMap[e].projection.geo2pos(this._mapDataMap[e].transform,t):null},getPosByGeo:function(e,t){if(!this._mapDataMap[e].transform)return null;var i=this.geo2pos(e,t);return i[0]+=this._mapDataMap[e].transform.left,i[1]+=this._mapDataMap[e].transform.top,i},getMapPosition:function(e){return this._mapDataMap[e].transform?[this._mapDataMap[e].transform.left,this._mapDataMap[e].transform.top]:null},onbeforDispose:function(){this._isAlive=!1,this.zr.un(c.EVENT.MOUSEWHEEL,this._onmousewheel),this.zr.un(c.EVENT.MOUSEDOWN,this._onmousedown),this.messageCenter.unbind(U.EVENT.ROAMCONTROLLER,this._onroamcontroller),this.messageCenter.unbind(U.EVENT.DATA_RANGE_HOVERLINK,this._ondrhoverlink)}},p.inherits(t,i),e("../chart").define("map",t),t}),i("zrender/shape/Path",["require","./Base","./util/PathProxy","../tool/util"],function(e){var t=e("./Base"),i=e("./util/PathProxy"),n=i.PathSegment,a=function(e){return Math.sqrt(e[0]*e[0]+e[1]*e[1])},o=function(e,t){return(e[0]*t[0]+e[1]*t[1])/(a(e)*a(t))},r=function(e,t){return(e[0]*t[1]0&&""===d[0]&&d.shift();for(var p=0;p0&&!isNaN(d[0]);){var c,u,y,g,b,f,k,x,_=null,L=[],W=h,X=m;switch(U){case"l":h+=d.shift(),m+=d.shift(),_="L",L.push(h,m);break;case"L":h=d.shift(),m=d.shift(),L.push(h,m);break;case"m":h+=d.shift(),m+=d.shift(),_="M",L.push(h,m),U="l";break;case"M":h=d.shift(),m=d.shift(),_="M",L.push(h,m),U="L";break;case"h":h+=d.shift(),_="L",L.push(h,m);break;case"H":h=d.shift(),_="L",L.push(h,m);break;case"v":m+=d.shift(),_="L",L.push(h,m);break;case"V":m=d.shift(),_="L",L.push(h,m);break;case"C":L.push(d.shift(),d.shift(),d.shift(),d.shift()),h=d.shift(),m=d.shift(),L.push(h,m);break;case"c":L.push(h+d.shift(),m+d.shift(),h+d.shift(),m+d.shift()),h+=d.shift(),m+=d.shift(),_="C",L.push(h,m);break;case"S":c=h,u=m,y=l[l.length-1],"C"===y.command&&(c=h+(h-y.points[2]),u=m+(m-y.points[3])),L.push(c,u,d.shift(),d.shift()),h=d.shift(),m=d.shift(),_="C",L.push(h,m);break;case"s":c=h,u=m,y=l[l.length-1],"C"===y.command&&(c=h+(h-y.points[2]),u=m+(m-y.points[3])),L.push(c,u,h+d.shift(),m+d.shift()),h+=d.shift(),m+=d.shift(),_="C",L.push(h,m);break;case"Q":L.push(d.shift(),d.shift()),h=d.shift(),m=d.shift(),L.push(h,m);break;case"q":L.push(h+d.shift(),m+d.shift()),h+=d.shift(),m+=d.shift(),_="Q",L.push(h,m);break;case"T":c=h,u=m,y=l[l.length-1],"Q"===y.command&&(c=h+(h-y.points[0]),u=m+(m-y.points[1])),h=d.shift(),m=d.shift(),_="Q",L.push(c,u,h,m);break;case"t":c=h,u=m,y=l[l.length-1],"Q"===y.command&&(c=h+(h-y.points[0]),u=m+(m-y.points[1])),h+=d.shift(),m+=d.shift(),_="Q",L.push(c,u,h,m);break;case"A":g=d.shift(),b=d.shift(),f=d.shift(),k=d.shift(),x=d.shift(),W=h,X=m,h=d.shift(),m=d.shift(),_="A",L=this._convertPoint(W,X,h,m,k,x,g,b,f);break;case"a":g=d.shift(),b=d.shift(),f=d.shift(),k=d.shift(),x=d.shift(),W=h,X=m,h+=d.shift(),m+=d.shift(),_="A",L=this._convertPoint(W,X,h,m,k,x,g,b,f)}for(var v=0,w=L.length;w>v;v+=2)L[v]+=t,L[v+1]+=i;l.push(new n(_||U,L))}("z"===U||"Z"===U)&&l.push(new n("z",[]))}return l},_convertPoint:function(e,t,i,n,a,s,l,h,m){var V=m*(Math.PI/180),U=Math.cos(V)*(e-i)/2+Math.sin(V)*(t-n)/2,d=-1*Math.sin(V)*(e-i)/2+Math.cos(V)*(t-n)/2,p=U*U/(l*l)+d*d/(h*h);p>1&&(l*=Math.sqrt(p),h*=Math.sqrt(p));var c=Math.sqrt((l*l*h*h-l*l*d*d-h*h*U*U)/(l*l*d*d+h*h*U*U));a===s&&(c*=-1),isNaN(c)&&(c=0);var u=c*l*d/h,y=c*-h*U/l,g=(e+i)/2+Math.cos(V)*u-Math.sin(V)*y,b=(t+n)/2+Math.sin(V)*u+Math.cos(V)*y,f=r([1,0],[(U-u)/l,(d-y)/h]),k=[(U-u)/l,(d-y)/h],x=[(-1*U-u)/l,(-1*d-y)/h],_=r(k,x);return o(k,x)<=-1&&(_=Math.PI),o(k,x)>=1&&(_=0),0===s&&_>0&&(_-=2*Math.PI),1===s&&0>_&&(_+=2*Math.PI),[g,b,l,h,f,_,V,s]},buildPath:function(e,t){var i=t.path,n=t.x||0,a=t.y||0;t.pathArray=t.pathArray||this.buildPathArray(i,n,a);for(var o=t.pathArray,r=t.pointList=[],s=[],l=0,h=o.length;h>l;l++){"M"==o[l].command.toUpperCase()&&(s.length>0&&r.push(s),s=[]);for(var m=o[l].points,V=0,U=m.length;U>V;V+=2)s.push([m[V],m[V+1]])}s.length>0&&r.push(s);for(var l=0,h=o.length;h>l;l++){var d=o[l].command,m=o[l].points;switch(d){case"L":e.lineTo(m[0],m[1]);break;case"M":e.moveTo(m[0],m[1]);break;case"C":e.bezierCurveTo(m[0],m[1],m[2],m[3],m[4],m[5]);break;case"Q":e.quadraticCurveTo(m[0],m[1],m[2],m[3]);break;case"A":var p=m[0],c=m[1],u=m[2],y=m[3],g=m[4],b=m[5],f=m[6],k=m[7],x=u>y?u:y,_=u>y?1:u/y,L=u>y?y/u:1;e.translate(p,c),e.rotate(f),e.scale(_,L),e.arc(0,0,x,g,g+b,1-k),e.scale(1/_,1/L),e.rotate(-f),e.translate(-p,-c);break;case"z":e.closePath()}}},getRect:function(e){if(e.__rect)return e.__rect;var t;t="stroke"==e.brushType||"fill"==e.brushType?e.lineWidth||1:0;for(var i=Number.MAX_VALUE,n=Number.MIN_VALUE,a=Number.MAX_VALUE,o=Number.MIN_VALUE,r=e.x||0,s=e.y||0,l=e.pathArray||this.buildPathArray(e.path),h=0;hn&&(n=m[V])):(m[V]+so&&(o=m[V]));var U;return U=i===Number.MAX_VALUE||n===Number.MIN_VALUE||a===Number.MAX_VALUE||o===Number.MIN_VALUE?{x:0,y:0,width:0,height:0}:{x:Math.round(i-t/2),y:Math.round(a-t/2),width:n-i+t,height:o-a+t},e.__rect=U,U}},e("../tool/util").inherits(s,t),s}),i("zrender/shape/Ellipse",["require","./Base","../tool/util"],function(e){var t=e("./Base"),i=function(e){t.call(this,e)};return i.prototype={type:"ellipse",buildPath:function(e,t){var i=.5522848,n=t.x,a=t.y,o=t.a,r=t.b,s=o*i,l=r*i;e.moveTo(n-o,a),e.bezierCurveTo(n-o,a-l,n-s,a-r,n,a-r),e.bezierCurveTo(n+s,a-r,n+o,a-l,n+o,a),e.bezierCurveTo(n+o,a+l,n+s,a+r,n,a+r),e.bezierCurveTo(n-s,a+r,n-o,a+l,n-o,a),e.closePath()},getRect:function(e){if(e.__rect)return e.__rect;var t;return t="stroke"==e.brushType||"fill"==e.brushType?e.lineWidth||1:0,e.__rect={x:Math.round(e.x-e.a-t/2), +y:Math.round(e.y-e.b-t/2),width:2*e.a+t,height:2*e.b+t},e.__rect}},e("../tool/util").inherits(i,t),i}),i("echarts/component/roamController",["require","./base","zrender/shape/Rectangle","zrender/shape/Sector","zrender/shape/Circle","../config","zrender/tool/util","zrender/tool/color","zrender/tool/event","../component"],function(e){function t(e,t,n,a,o){if(this.rcOption={},a.roamController&&a.roamController.show){if(!a.roamController.mapTypeControl)return void console.error("option.roamController.mapTypeControl has not been defined.");i.call(this,e,t,n,a,o),this.rcOption=a.roamController;var r=this;this._drictionMouseDown=function(e){return r.__drictionMouseDown(e)},this._drictionMouseUp=function(e){return r.__drictionMouseUp(e)},this._drictionMouseMove=function(e){return r.__drictionMouseMove(e)},this._drictionMouseOut=function(e){return r.__drictionMouseOut(e)},this._scaleHandler=function(e){return r.__scaleHandler(e)},this.refresh(a)}}var i=e("./base"),n=e("zrender/shape/Rectangle"),a=e("zrender/shape/Sector"),o=e("zrender/shape/Circle"),r=e("../config");r.roamController={zlevel:0,z:4,show:!0,x:"left",y:"top",width:80,height:120,backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,padding:5,handleColor:"#6495ed",fillerColor:"#fff",step:15,mapTypeControl:null};var s=e("zrender/tool/util"),l=e("zrender/tool/color"),h=e("zrender/tool/event");return t.prototype={type:r.COMPONENT_TYPE_ROAMCONTROLLER,_buildShape:function(){if(this.rcOption.show){this._itemGroupLocation=this._getItemGroupLocation(),this._buildBackground(),this._buildItem();for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e])}},_buildItem:function(){this.shapeList.push(this._getDirectionShape("up")),this.shapeList.push(this._getDirectionShape("down")),this.shapeList.push(this._getDirectionShape("left")),this.shapeList.push(this._getDirectionShape("right")),this.shapeList.push(this._getScaleShape("scaleUp")),this.shapeList.push(this._getScaleShape("scaleDown"))},_getDirectionShape:function(e){var t=this._itemGroupLocation.r,i=this._itemGroupLocation.x+t,n=this._itemGroupLocation.y+t,o={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:i,y:n,r:t,startAngle:-45,endAngle:45,color:this.rcOption.handleColor,text:">",textX:i+t/2+4,textY:n-.5,textAlign:"center",textBaseline:"middle",textPosition:"specific",textColor:this.rcOption.fillerColor,textFont:Math.floor(t/2)+"px arial"},highlightStyle:{color:l.lift(this.rcOption.handleColor,-.2),brushType:"fill"},clickable:!0};switch(e){case"up":o.rotation=[Math.PI/2,i,n];break;case"left":o.rotation=[Math.PI,i,n];break;case"down":o.rotation=[-Math.PI/2,i,n]}return o=new a(o),o._roamType=e,o.onmousedown=this._drictionMouseDown,o.onmouseup=this._drictionMouseUp,o.onmousemove=this._drictionMouseMove,o.onmouseout=this._drictionMouseOut,o},_getScaleShape:function(e){var t=this._itemGroupLocation.width,i=this._itemGroupLocation.height-t;i=0>i?20:i;var n=Math.min(t/2-5,i)/2,a=this._itemGroupLocation.x+("scaleDown"===e?t-n:n),r=this._itemGroupLocation.y+this._itemGroupLocation.height-n,s={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:a,y:r,r:n,color:this.rcOption.handleColor,text:"scaleDown"===e?"-":"+",textX:a,textY:r-2,textAlign:"center",textBaseline:"middle",textPosition:"specific",textColor:this.rcOption.fillerColor,textFont:Math.floor(n)+"px verdana"},highlightStyle:{color:l.lift(this.rcOption.handleColor,-.2),brushType:"fill"},clickable:!0};return s=new o(s),s._roamType=e,s.onmousedown=this._scaleHandler,s},_buildBackground:function(){var e=this.reformCssArray(this.rcOption.padding);this.shapeList.push(new n({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._itemGroupLocation.x-e[3],y:this._itemGroupLocation.y-e[0],width:this._itemGroupLocation.width+e[3]+e[1],height:this._itemGroupLocation.height+e[0]+e[2],brushType:0===this.rcOption.borderWidth?"fill":"both",color:this.rcOption.backgroundColor,strokeColor:this.rcOption.borderColor,lineWidth:this.rcOption.borderWidth}}))},_getItemGroupLocation:function(){var e,t=this.reformCssArray(this.rcOption.padding),i=this.rcOption.width,n=this.rcOption.height,a=this.zr.getWidth(),o=this.zr.getHeight();switch(this.rcOption.x){case"center":e=Math.floor((a-i)/2);break;case"left":e=t[3]+this.rcOption.borderWidth;break;case"right":e=a-i-t[1]-t[3]-2*this.rcOption.borderWidth;break;default:e=this.parsePercent(this.rcOption.x,a)}var r;switch(this.rcOption.y){case"top":r=t[0]+this.rcOption.borderWidth;break;case"bottom":r=o-n-t[0]-t[2]-2*this.rcOption.borderWidth;break;case"center":r=Math.floor((o-n)/2);break;default:r=this.parsePercent(this.rcOption.y,o)}return{x:e,y:r,r:i/2,width:i,height:n}},__drictionMouseDown:function(e){this.mousedown=!0,this._drictionHandlerOn(e)},__drictionMouseUp:function(e){this.mousedown=!1,this._drictionHandlerOff(e)},__drictionMouseMove:function(e){this.mousedown&&this._drictionHandlerOn(e)},__drictionMouseOut:function(e){this._drictionHandlerOff(e)},_drictionHandlerOn:function(e){this._dispatchEvent(e.event,e.target._roamType),clearInterval(this.dircetionTimer);var t=this;this.dircetionTimer=setInterval(function(){t._dispatchEvent(e.event,e.target._roamType)},100),h.stop(e.event)},_drictionHandlerOff:function(){clearInterval(this.dircetionTimer)},__scaleHandler:function(e){this._dispatchEvent(e.event,e.target._roamType),h.stop(e.event)},_dispatchEvent:function(e,t){this.messageCenter.dispatch(r.EVENT.ROAMCONTROLLER,e,{roamType:t,mapTypeControl:this.rcOption.mapTypeControl,step:this.rcOption.step},this.myChart)},refresh:function(e){e&&(this.option=e||this.option,this.option.roamController=this.reformOption(this.option.roamController),this.rcOption=this.option.roamController),this.clear(),this._buildShape()}},s.inherits(t,i),e("../component").define("roamController",t),t}),i("echarts/layer/heatmap",["require"],function(){function e(e){if(this.option=e,e)for(var i in t)this.option[i]=void 0!==e[i]?e[i]:t[i];else this.option=t}var t={blurSize:30,gradientColors:["blue","cyan","lime","yellow","red"],minAlpha:.05,valueScale:1,opacity:1},i=20,n=256;return e.prototype={getCanvas:function(e,t,a){var o=this._getBrush(),r=this._getGradient(),s=i+this.option.blurSize,l=document.createElement("canvas");l.width=t,l.height=a;for(var h=l.getContext("2d"),m=e.length,V=0;m>V;++V){var U=e[V],d=U[0],p=U[1],c=U[2],u=Math.min(1,Math.max(c*this.option.valueScale||this.option.minAlpha,this.option.minAlpha));h.globalAlpha=u,h.drawImage(o,d-s,p-s)}for(var y=h.getImageData(0,0,l.width,l.height),g=y.data,m=g.length/4;m--;){var b=4*m+3,u=g[b]/256,f=Math.floor(u*(n-1));g[b-3]=r[4*f],g[b-2]=r[4*f+1],g[b-1]=r[4*f+2],g[b]*=this.option.opacity}return h.putImageData(y,0,0),l},_getBrush:function(){if(!this._brushCanvas){this._brushCanvas=document.createElement("canvas");var e=i+this.option.blurSize,t=2*e;this._brushCanvas.width=t,this._brushCanvas.height=t;var n=this._brushCanvas.getContext("2d");n.shadowOffsetX=t,n.shadowBlur=this.option.blurSize,n.shadowColor="black",n.beginPath(),n.arc(-e,e,i,0,2*Math.PI,!0),n.closePath(),n.fill()}return this._brushCanvas},_getGradient:function(){if(!this._gradientPixels){var e=n,t=document.createElement("canvas");t.width=1,t.height=e;for(var i=t.getContext("2d"),a=i.createLinearGradient(0,0,0,e),o=this.option.gradientColors.length,r=0;o>r;++r)"string"==typeof this.option.gradientColors[r]?a.addColorStop((r+1)/o,this.option.gradientColors[r]):a.addColorStop(this.option.gradientColors[r].offset,this.option.gradientColors[r].color);i.fillStyle=a,i.fillRect(0,0,1,e),this._gradientPixels=i.getImageData(0,0,1,e).data}return this._gradientPixels}},e}),i("echarts/util/mapData/params",["require"],function(e){function t(e){if(!e.UTF8Encoding)return e;for(var t=e.features,n=0;n>1^-(1&r),s=s>>1^-(1&s),r+=n,s+=a,n=r,a=s,i.push([r/1024,s/1024])}return i}var n={none:{getGeoJson:function(e){e({type:"FeatureCollection",features:[{type:"Feature",geometry:{coordinates:[],encodeOffsets:[],type:"Polygon"},properties:{}}]})}},world:{getGeoJson:function(i){e(["./geoJson/world_geo"],function(e){i(t(e))})}},china:{getGeoJson:function(i){e(["./geoJson/china_geo"],function(e){i(t(e))})}},"南海诸岛":{textCoord:[126,25],getPath:function(e,t){for(var i=[[[0,3.5],[7,11.2],[15,11.9],[30,7],[42,.7],[52,.7],[56,7.7],[59,.7],[64,.7],[64,0],[5,0],[0,3.5]],[[13,16.1],[19,14.7],[16,21.7],[11,23.1],[13,16.1]],[[12,32.2],[14,38.5],[15,38.5],[13,32.2],[12,32.2]],[[16,47.6],[12,53.2],[13,53.2],[18,47.6],[16,47.6]],[[6,64.4],[8,70],[9,70],[8,64.4],[6,64.4]],[[23,82.6],[29,79.8],[30,79.8],[25,82.6],[23,82.6]],[[37,70.7],[43,62.3],[44,62.3],[39,70.7],[37,70.7]],[[48,51.1],[51,45.5],[53,45.5],[50,51.1],[48,51.1]],[[51,35],[51,28.7],[53,28.7],[53,35],[51,35]],[[52,22.4],[55,17.5],[56,17.5],[53,22.4],[52,22.4]],[[58,12.6],[62,7],[63,7],[60,12.6],[58,12.6]],[[0,3.5],[0,93.1],[64,93.1],[64,0],[63,0],[63,92.4],[1,92.4],[1,3.5],[0,3.5]]],n="",a=e[0],o=e[1],r=0,s=i.length;s>r;r++){n+="M "+((i[r][0][0]*t+a).toFixed(2)-0)+" "+((i[r][0][1]*t+o).toFixed(2)-0)+" ";for(var l=1,h=i[r].length;h>l;l++)n+="L "+((i[r][l][0]*t+a).toFixed(2)-0)+" "+((i[r][l][1]*t+o).toFixed(2)-0)+" "}return n+" Z"}},"新疆":{getGeoJson:function(i){e(["./geoJson/xin_jiang_geo"],function(e){i(t(e))})}},"西藏":{getGeoJson:function(i){e(["./geoJson/xi_zang_geo"],function(e){i(t(e))})}},"内蒙古":{getGeoJson:function(i){e(["./geoJson/nei_meng_gu_geo"],function(e){i(t(e))})}},"青海":{getGeoJson:function(i){e(["./geoJson/qing_hai_geo"],function(e){i(t(e))})}},"四川":{getGeoJson:function(i){e(["./geoJson/si_chuan_geo"],function(e){i(t(e))})}},"黑龙江":{getGeoJson:function(i){e(["./geoJson/hei_long_jiang_geo"],function(e){i(t(e))})}},"甘肃":{getGeoJson:function(i){e(["./geoJson/gan_su_geo"],function(e){i(t(e))})}},"云南":{getGeoJson:function(i){e(["./geoJson/yun_nan_geo"],function(e){i(t(e))})}},"广西":{getGeoJson:function(i){e(["./geoJson/guang_xi_geo"],function(e){i(t(e))})}},"湖南":{getGeoJson:function(i){e(["./geoJson/hu_nan_geo"],function(e){i(t(e))})}},"陕西":{getGeoJson:function(i){e(["./geoJson/shan_xi_1_geo"],function(e){i(t(e))})}},"广东":{getGeoJson:function(i){e(["./geoJson/guang_dong_geo"],function(e){i(t(e))})}},"吉林":{getGeoJson:function(i){e(["./geoJson/ji_lin_geo"],function(e){i(t(e))})}},"河北":{getGeoJson:function(i){e(["./geoJson/he_bei_geo"],function(e){i(t(e))})}},"湖北":{getGeoJson:function(i){e(["./geoJson/hu_bei_geo"],function(e){i(t(e))})}},"贵州":{getGeoJson:function(i){e(["./geoJson/gui_zhou_geo"],function(e){i(t(e))})}},"山东":{getGeoJson:function(i){e(["./geoJson/shan_dong_geo"],function(e){i(t(e))})}},"江西":{getGeoJson:function(i){e(["./geoJson/jiang_xi_geo"],function(e){i(t(e))})}},"河南":{getGeoJson:function(i){e(["./geoJson/he_nan_geo"],function(e){i(t(e))})}},"辽宁":{getGeoJson:function(i){e(["./geoJson/liao_ning_geo"],function(e){i(t(e))})}},"山西":{getGeoJson:function(i){e(["./geoJson/shan_xi_2_geo"],function(e){i(t(e))})}},"安徽":{getGeoJson:function(i){e(["./geoJson/an_hui_geo"],function(e){i(t(e))})}},"福建":{getGeoJson:function(i){e(["./geoJson/fu_jian_geo"],function(e){i(t(e))})}},"浙江":{getGeoJson:function(i){e(["./geoJson/zhe_jiang_geo"],function(e){i(t(e))})}},"江苏":{getGeoJson:function(i){e(["./geoJson/jiang_su_geo"],function(e){i(t(e))})}},"重庆":{getGeoJson:function(i){e(["./geoJson/chong_qing_geo"],function(e){i(t(e))})}},"宁夏":{getGeoJson:function(i){e(["./geoJson/ning_xia_geo"],function(e){i(t(e))})}},"海南":{getGeoJson:function(i){e(["./geoJson/hai_nan_geo"],function(e){i(t(e))})}},"台湾":{getGeoJson:function(i){e(["./geoJson/tai_wan_geo"],function(e){i(t(e))})}},"北京":{getGeoJson:function(i){e(["./geoJson/bei_jing_geo"],function(e){i(t(e))})}},"天津":{getGeoJson:function(i){e(["./geoJson/tian_jin_geo"],function(e){i(t(e))})}},"上海":{getGeoJson:function(i){e(["./geoJson/shang_hai_geo"],function(e){i(t(e))})}},"香港":{getGeoJson:function(i){e(["./geoJson/xiang_gang_geo"],function(e){i(t(e))})}},"澳门":{getGeoJson:function(i){e(["./geoJson/ao_men_geo"],function(e){i(t(e))})}}};return{decode:t,params:n}}),i("echarts/util/mapData/textFixed",[],function(){return{"广东":[0,-10],"香港":[10,10],"澳门":[-10,18],"黑龙江":[0,20],"天津":[5,5],"深圳市":[-35,0],"红河哈尼族彝族自治州":[0,20],"楚雄彝族自治州":[-5,15],"石河子市":[-5,5],"五家渠市":[0,-10],"昌吉回族自治州":[10,10],"昌江黎族自治县":[0,20],"陵水黎族自治县":[0,20],"东方市":[0,20],"渭南市":[0,20]}}),i("echarts/util/mapData/geoCoord",[],function(){return{Russia:[100,60],"United States of America":[-99,38]}}),i("echarts/util/projection/svg",["require","zrender/shape/Path"],function(e){function t(e){return parseFloat(e||0)}function i(e){for(var i=e.firstChild;"svg"!=i.nodeName.toLowerCase()||1!=i.nodeType;)i=i.nextSibling;var n=t(i.getAttribute("x")),a=t(i.getAttribute("y")),o=t(i.getAttribute("width")),r=t(i.getAttribute("height"));return{left:n,top:a,width:o,height:r}}function n(e,t){function i(e){var t=e.tagName;if(m[t]){var o=m[t](e,n);o&&(o.scale=n,o.properties={name:e.getAttribute("name")||""},o.id=e.id,s(o,e),a.push(o))}for(var r=e.childNodes,l=0,h=r.length;h>l;l++)i(r[l])}var n=[t.scale.x,t.scale.y],a=[];return i(e),a}function a(e,t){var i=t instanceof Array?[1*t[0],1*t[1]]:[1*t.x,1*t.y];return[i[0]/e.scale.x,i[1]/e.scale.y]}function o(e,t){var i=t instanceof Array?[1*t[0],1*t[1]]:[1*t.x,1*t.y];return[i[0]*e.scale.x,i[1]*e.scale.y]}function r(e){return e.replace(/^\s\s*/,"").replace(/\s\s*$/,"")}function s(e,t){var i=t.getAttribute("fill"),n=t.getAttribute("stroke"),a=t.getAttribute("stroke-width"),o=t.getAttribute("opacity");i&&"none"!=i?(e.color=i,n?(e.brushType="both",e.strokeColor=n):e.brushType="fill"):n&&"none"!=n&&(e.strokeColor=n,e.brushType="stroke"),a&&"none"!=a&&(e.lineWidth=parseFloat(a)),o&&"none"!=o&&(e.opacity=parseFloat(o))}function l(e){for(var t=r(e).replace(/,/g," ").split(/\s+/),i=[],n=0;no;o++)if(n=a[o],!n.properties.name||!t[n.properties.name])switch(n.type){case"Feature":r[n.geometry.type](n.geometry.coordinates);break;case"GeometryCollection":i=n.geometries;for(var l=0,h=i.length;h>l;l++)r[i[l].type](i[l].coordinates)}return e.srcSize={left:1*r.xmin.toFixed(4),top:1*r.ymin.toFixed(4),width:1*(r.xmax-r.xmin).toFixed(4),height:1*(r.ymax-r.ymin).toFixed(4)},e}function i(e,i,n){function a(e,t){c=e.type,u=e.coordinates,o._bbox={xmin:360,xmax:-360,ymin:180,ymax:-180},y=o[c](u),m.push({path:y,cp:o.makePoint(t.properties.cp?t.properties.cp:[(o._bbox.xmin+o._bbox.xmax)/2,(o._bbox.ymin+o._bbox.ymax)/2]),properties:t.properties,id:t.id})}n=n||{},o.scale=null,o.offset=null,e.srcSize||t(e,n),i.offset={x:e.srcSize.left,y:e.srcSize.top,left:i.OffsetLeft||0,top:i.OffsetTop||0},o.scale=i.scale,o.offset=i.offset;for(var r,s,l,h=e.features,m=[],V=0,U=h.length;U>V;V++)if(l=h[V],!l.properties.name||!n[l.properties.name])if("Feature"==l.type)a(l.geometry,l);else if("GeometryCollection"==l.type){r=l.geometries;for(var d=0,p=r.length;p>d;d++)s=r[d],a(s,s)}var c,u,y;return m}function n(e,t){var i,n;return t instanceof Array?(i=1*t[0],n=1*t[1]):(i=1*t.x,n=1*t.y),i=i/e.scale.x+e.offset.x-168.5,i=i>180?i-360:i,n=90-(n/e.scale.y+e.offset.y),[i,n]}function a(e,t){return o.offset=e.offset,o.scale=e.scale,o.makePoint(t instanceof Array?[1*t[0],1*t[1]]:[1*t.x,1*t.y])}var o={formatPoint:function(e){return[(e[0]<-168.5&&e[1]>63.8?e[0]+360:e[0])+168.5,90-e[1]]},makePoint:function(e){var t=this,i=t.formatPoint(e);t._bbox.xmin>e[0]&&(t._bbox.xmin=e[0]),t._bbox.xmaxe[1]&&(t._bbox.ymin=e[1]),t._bbox.ymaxn;n++)t=o.makePoint(e[n]),i=0===n?"M"+t.join(","):i+"L"+t.join(",");return i},Polygon:function(e){for(var t="",i=0,n=e.length;n>i;i++)t=t+o.LineString(e[i])+"z";return t},MultiPoint:function(e){for(var t=[],i=0,n=e.length;n>i;i++)t.push(o.Point(e[i]));return t},MultiLineString:function(e){for(var t="",i=0,n=e.length;n>i;i++)t+=o.LineString(e[i]);return t},MultiPolygon:function(e){for(var t="",i=0,n=e.length;n>i;i++)t+=o.Polygon(e[i]);return t}},r={formatPoint:o.formatPoint,makePoint:function(e){var t=this,i=t.formatPoint(e),n=i[0],a=i[1];t.xmin>n&&(t.xmin=n),t.xmaxa&&(t.ymin=a),t.ymaxt;t++)this.makePoint(e[t])},Polygon:function(e){for(var t=0,i=e.length;i>t;t++)this.LineString(e[t])},MultiPoint:function(e){for(var t=0,i=e.length;i>t;t++)this.Point(e[t])},MultiLineString:function(e){for(var t=0,i=e.length;i>t;t++)this.LineString(e[t])},MultiPolygon:function(e){for(var t=0,i=e.length;i>t;t++)this.Polygon(e[t])}};return{getBbox:e,geoJson2Path:i,pos2geo:n,geo2pos:a}}),i("echarts/util/mapData/geoJson/an_hui_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"3415",properties:{name:"六安市",cp:[116.3123,31.8329],childNum:6},geometry:{type:"Polygon",coordinates:["@@„„nJ‚UXUVƒ°U„ÑnU@mlLVaVln@@bn@VU@xlb@lšLnKlšƒVI„JšUVxnI@lVL@b„Ž°VX@˜b„x„nVVUnVVnU‚›@kX@VwV@„al¥UUnUWa@ƒ@wĸU„LU¥lKUa@aUI@alLVaUƒ¯anƒWkUKm@XV@VaXlW@aU_UWVUƒI¯@ma¯W¯™™I@UU@WWU@U@@UU@VkV@@WUUm@UaU@„lK@IUK„L@KWmXUWaXI@ƒ@a@a@U@U@KV¥lw„k°b²JVIVKlV@UX„la„Ul`œUVLVVVUšJ„U@Lnm@_VK@KUIW@™J@Xk@WW@U—ƒmm™XmWk@kK@aUUƒVmmkUwUmWL™@WmU@™UJmUULkKWakLWVkIƒlƒwULƒW@X°lUJ@°ULƒWV—wmJ@bmb¯Vkm@@WkWm¯wƒL@lkXƒWmXym¯UImJUbkV™@Vn¯„@V@lUbƒ@mk@maUxmlUbULWn@J—LmKUkWKkwUKƒbm„X„WxkVUKmLkVV@JUUWL@xkJUUƒV@X@VVlUbVX@xk¤šx‚¼œxWxn„‚nn@Þ¼„JVb°aVn„@šmlnXU„JlbVlkz@‚lUŽlXJmxVxXnWxXÈWlUŽ@šUxU@VX@xUL@šUÆmLnV@lWXk@@JlbXblnlJ"],encodeOffsets:[[118710,33351]]}},{type:"Feature",id:"3408",properties:{name:"安庆市",cp:[116.7517,30.5255],childNum:9},geometry:{type:"Polygon",coordinates:["@@n°‚znW„XlW@k„K°xXn‚l@Xn@l‚°Una@anI˜xXU„ŽVK@¯VIkW¯X@‚„VK„x„klJXUlKXblLVKnVVIšŽV@Xn‚@šŽXKVnVxlŽnn„UlmV@²óUkV™lW„b„lƒšƒn@VVVIn@lw@WVIXblV„@Èx‚aUaVIVVnKVLšK„ƒln@b²K@»U£ƒÑķƒġÝÅb™K™a@Im@ۍ„@kWÓkkmKÅnóJƒUÅ£›W@w„ĕ@wĉţ¯¯ƒUkK±l¯Uƒ¥UÑkÝUķ»Ý¥¯™JƒIUŽVbUl¯ÈV¼VJU¼Vb@bkLUl@„VJ@bUXǚ@lkVmXmKkLVxš‚Ž„VƒL@VkVVVlzW˜kbmLUUUbVbUV™šlÒnJlUnLllUL@bU„Vx„l‚LXVƦÈVU¦WJ"],encodeOffsets:[[118834,31759]]}},{type:"Feature",id:"3411",properties:{name:"滁州市",cp:[118.1909,32.536],childNum:7},geometry:{type:"Polygon",coordinates:["@@š„@`nnl@„xšK@X°KXV˜IXVlbXVWnX‚lL@šÈ»‚LVan@VJ„êVVn@‚X@laÞbVaƒyn@„_‚xnWVXnWl@VnUVkI@l‚nXKVLVV@V@kW@LlVô„@J@bVnnKnkVa@»lç@ƒnwšKma™UUUVњ@n™mWXalI@alVn@VwUaVU„@„nlaôJnU„VVXlJšaXXVK@UšV@VWx@nXVWšXVšUlLUbV‚ULVVnUVbUbVbš@@a„KÆnnKVK@U@UU@@a„@Vƒ°¯ÈJVIlķ@aa˜UaVKU_@mkxUI@aƒUlyU@@™wkKWmUbUnUVWbkJW_J@bƒn@Vm@@KULk@V@@bVbÅm@LW@UVVbkK@UkKWL@VULUKWIUJUbkK@_WVXU›Jka@XƒVa@kšy@aVIUUW@@m„UlLœKWÑUKVan@UkVmmIXKƒaVaUwVU@UmykU¯@±UUL@WUIVUU@KkIWaƒaU@kUUaǃUó»mKƒk¯@y@kWK@bkI¯`mn™l¯XWlkVUzUJlbUbVJl@nnm„@VULV`XnWƗbmUUn™JmUknƒJ¯km@ƒyk@kU›xL@VUbmnn¤lX@`™z@JmaULUVl@Xn@xllkXWa—aW@UVmUbƒ@mVXšWxXbWbUŽƒÒnVVnVVUL"],encodeOffsets:[[120004,33520]]}},{type:"Feature",id:"3418",properties:{name:"宣城市",cp:[118.8062,30.6244],childNum:7},geometry:{type:"Polygon",coordinates:["@@Vb@„XL˜JXxlIXxlVlV@I²¤šnlUnVšU@VULWVUJ@Lnb@lV@UnV@@VVVlLnbnJ‚UVkUUVWn@@anUVnVJVIV‚@@nUJVbUb‚„@VUbVK@bn@VbnIlxkllXVlXKWUXUlL°¤UVVb@bš„UlkXW‚ƒxXz@‚„Ila„UlƒnUlJVInVÆJ„U„LVUnV„K°@VnlVnxV@XLlK@wVL@KnUlJXU˜bnKVLX„lUw@VWlLXKm@@a„@VLnmlIVVnKn@škVašVlwk@@a@k@ƒVIUa™@maUa@wna@kmWƒ™UUmVUIVǗ@aƒKm™aƒ™kU™J@InmUUaVa„k‚lX@Vk@m@VU@wnK@alKVUkUkKƒbmUkmƒ@U£WVk@@UÝbbƒaÇx@b@WVUa¯ƒ@wVwUUV@VwnK@KWaŁ@KšIUyUI@WmXó™UbWaKm™@km@IUyƒIUaWKƒx@zUKUL@llVUnkLVVkJWX@VUKUVƒIkVWakb@VWb@n@JkXUlmL@xkL@`VxšLUÈUJ@Vm@@bmIUlUL@VUVVbknm@mKUw™KVÈ@J@LV±kkJUIƒl"],encodeOffsets:[[120803,31247]]}},{type:"Feature",id:"3412",properties:{name:"阜阳市",cp:[115.7629,32.9919],childNum:6},geometry:{type:"Polygon",coordinates:["@@V™nƒš@ša„k°aš±@‚¥@UUI@aUmlwUUx›b@¥XU@mmI@a@Kn@@_W@@W„I@mšUVVXUl@XaV@‚K@I@a„LX@aVI°K@KVL„UUw‚yXkšK@kšKÆbXnlK@k@a„JlU@w@U@»@aXKWƒn_‚JXkVKnƒ@°LlKXƒW@¯Uƒ@aUK@kmJUw™VƒIUJ™„kŽmL™K@kka@wUVm@@am@UkUbkK@nmVƒÒ¯VU„WVVmIƒƒULk@ƒƒma@kkKƒƒ@nUbUamU™`UUVUkKVkkƒW@@bkmƒnƒmUXVKXVƒL@VƒbU„m‚™bVXJ@nmKÅI@KWKUXVJUL@VUKUX@KUKWL@LUJmaXXm@kVVV@L@VUL@VlK@L@V@LUK@VUb@UUU@°@nVxU`‚Lkn@`@XVJ@X™Vm„k@UKmV¯LVVn±Wm@Ub@JlLUl„@VLk„@lmVVn@bnV@V°IV™šaVJXI°K°V@XXVlVVU„nšKVlUš„bWXnV@bV`U„„@@m@@‚ƒ@nxmn@bXVlL@¤nb„Ul¦šVVUnJVU„Vl@@bÞL"],encodeOffsets:[[118418,34392]]}},{type:"Feature",id:"3413",properties:{name:"宿州市",cp:[117.5208,33.6841],childNum:5},geometry:{type:"Polygon",coordinates:["@@@UWU@bkW@aWU@aUIkWV™lLXb„lVIUVV@‚mn@V_n@VaUK@I‚@UašanJVU„@lV„UVnnKVVlaUa„I@wnK‚Lnll@nVlk@wVKXkl@@b„bUJ@V‚U@U„UUyVk@aVUXwlWXX‚WU¹@aU™@WUI@mlUšn„J@Il@šaXbV@VKl@XxVL@W„IšJlb„@„al@„IUUm@@aVK@¥¯—@mUķ¯bWƒk£Vm@akm@VaÅ@UVWaƒ@UJWkƒJ—UƒbWbU@UlƒXk@ƒamV@K¯nk@ƒlU@Uxmz@bU`ÇbUbÅVm£U@Ww™x@akLUK@UlakwUJWVkLmaUal@n_ƒmVUnKVUUmÅXWa™@kJmx@XUJ@bVLXxl@VVUVV„UbkLWbU@@lUVV„VVX„›K@XkJ@nU@@bV@VxUVlb„U@xXLWŽn@UxVbVĊ„V@b@XV`mnkJ@kUKmbƒaU@VbnbÆx@XU@@`k@@bl„™@@bkL@WƒakXWaU@Vmkx@XWW@@wUUUbƒJ™U¯V™@¯ÞU@WxXŽlL@bkb@ŽlVlnb™JW@kkU@mbkaWJ—IVlmz¯`UnU@mb™@@„ƒ`@bkVlœnV@b@šV@„aVxn@Vx‚KXnl@nbVK„bVK@a„_V@Vƒ„w@W„LlwnK@UmIU@VWš@šUÈ@lKnal„wš@@V°@šaUmlUUw@„ƒV@@UXK"],encodeOffsets:[[119836,35061]]}},{type:"Feature",id:"3410",properties:{name:"黄山市",cp:[118.0481,29.9542],childNum:5},geometry:{type:"Polygon",coordinates:["@@lXnlWX@VUJVnUJVzXJVx„kVJlI²l‚U@K@IUǚLVxnLn@lmUaVU@UVKVknJ@an@@UVIVǙKUw@_lK@wnKVklW@I@mXa@UlaXblU„JVUVL@UXWlIUUlKVmkU@kVKVL@y„wXLVb„JVz@Jlnš@nŽ‚LXbVaôšnW@la@UVWUa@@a@mk@WIk@VwUa¯¥m@UUVK@ImK@aX£ƒkK›ÅV™a™™ƒ_@±ƒakXWW—LƒƒƒnU@@a@¯mK@L™JUWwUV™VmbXX@lWLn`mzUJUb™Lƒ„k@makVWmkX™ambkKknƒaƒ@ƒaƒb@‚U@Unm@—ƒWVƒ@VbUbUJWIk@@lmL@°UVUVm„nš™@@kmWkb@xƒ_m@@aU@b@JlŽUz™lWxXn„@‚b²@l`„IVl„UlL@VšK„nVbUl@VlIn@@b„bVWUk‚@@bX@Valb@bnb°Vn@„xVKlbVnV@V‚x„L@ln@UXVV‚L˜"],encodeOffsets:[[120747,31095]]}},{type:"Feature",id:"3414",properties:{name:"巢湖市",cp:[117.7734,31.4978],childNum:5},geometry:{type:"Polygon",coordinates:["@@VV@blL@ŽXlWnnšnŽ˜„@VXXl@@WšIX@VJ@LšxŎxlnšŽ@bXJVblX@VVbUVn@VbUVlb@LnJVbVLV‚XLšÒVL„ÒšV„bVIVylUXk°Wšknm°_lJ@aXL@l‚z°@„lnLô¼V‚È„VUUaVKU@WW@@UUa@knmVLlaV@„a@kšak±@UmwkKmk™lj™ÝUUkL@mlIVmnÝWkkUÝ@KƑĉ™a@»ƒmma@mX™¤¯Uƒw@ƒ@UU@bU±±L@akmƒ„™LUKmLUUUJVbbÇwƒ@kUWaUJ@Xkxm@UJUUm@™„k„ƒ‚ƒakXUšVl±ôU@kn"],encodeOffsets:[[119847,32007]]}},{type:"Feature",id:"3416",properties:{name:"亳州市",cp:[116.1914,33.4698],childNum:4},geometry:{type:"Polygon",coordinates:["@@lU@Un@@anUlw@KVmUwlaX_lKna@KU@@kWKUU@ankW™XK˜@@V²VVIÈU@al@VaÈamK@wU™@klaUƒV@XƒVUU»WUUbkmUkVmk@aÈw@mWU@VkIkVWKUÑķXȭºU¯lƒ@kkLWmÅa™L@l™LWlzVxƒVUK@L¯LUJ@bWƒK@b@JLU@Wbk@WVUU™V@nƒJ@XX@@`m@@L@bnJ@nWV@¦œa‚wVVkxVn@bVJ@V¦@Ž™²¯bƒl™b™@m„UšUŽƒŽ@¼ƒ¦Xb‚UV`@nnxUxWLkUkVWKkV@XV@@VVL@VX„@lVV@L@blL@`šL@xXKVL‚@„VnUš@lwnU@ml@XnV@@UVW°LnalƒUI@aUK@a‚a@U„kXW@I@mWL@UXK@UVW@U‚@@k„Wn‚@@V„@XblaVxšL@bVKXb„IlJ"],encodeOffsets:[[119183,34594]]}},{type:"Feature",id:"3417",properties:{name:"池州市",cp:[117.3889,30.2014],childNum:4},geometry:{type:"Polygon",coordinates:["@@„V°°ĊŤ@xƒĖ@xœXƤ„VôIÆmnLllXÔ@lƒÜŽn@@JšbšLÆaĢÞĸ„°VVUUKVanK@UV@VL„VVn„ln@‚xnklxXamk@WV@Xa˜@naVk„Klk™@mkUWwkJWw—IWK@ƒUaUwWIUyVIUmVI@UXWmkkW‚—KUUVWm@@kƒKw@U‚UUmkaULƒwm@¯Uma@akaUbW@@a@VlUXƒa@am@kJ@UVkUaƒm™L@UkKƒVUkƒJk_±@aƒ@WmXwÇkkaVaUa±ƒœwV@VkƒwnyUaW@UU¯amLk@m™@kmmU™™¯K@L@lUX¯ƒWlkXƒŽVb„bƒVUL@J@LVKnlJXnlb@`nXlalV@bnL@Vnb˜¼@lXbWlkL™K@zUJmIUxUVUVmX","@@llUL@VlxšL@a@UƒwXa¯@"],encodeOffsets:[[119543,30781],[120061,31152]]}},{type:"Feature",id:"3401",properties:{name:"合肥市",cp:[117.29,32.0581],childNum:4},geometry:{type:"Polygon",coordinates:["@@„L„xV‚ĊLÞkšVlVVXaWaXwW™nU„@‚anVVUX@˜bXblWkk@wWmk@VUVKnb@Išy@_kWm£nmVa@U‚KœwlVl@„zn@°l„IlmnVšIVmnV˜aXÅWmU_VK@Unƒmmk@UIVakaƒa™UƒÑUK™ÑWKUUKUamI@KkaVUUam@VUUa@UkWUaWI@a™kmōw™wUL@`mn@KƒV™IUVUUUK›Vk_ƒVkbWƒ@VkUULUJ±I¯aƒlkxU¦@L@V@V@b@b@„WJXbWVXn@LƒKVL@JkLƒŽV@Vbn@VV@XU@UlV@@VV@V@XXV@@VšJ°š°Xnb°@„JUVVXV`@bkXWŽUbU@WŽn@VLXlm„°bV„UbkK@bVJ@bVbkLV¦ƒKķV@x@„XbmVVVk¦"],encodeOffsets:[[119678,33323]]}},{type:"Feature",id:"3403",properties:{name:"蚌埠市",cp:[117.4109,33.1073],childNum:4},geometry:{type:"Polygon",coordinates:["@@VÒXLlUlJ@UXV@nÇx@bnlUVllnVaXVV¼UVW„U@V„²wVV@Vl@„VnwlIš@XbÆWVnUVmLUV„nm`k@VbnblKXUVIlxkb@VVLlK@bšwXxV@n¤ÆUVaÈaV_@anyVwV@„kl@°m@LnU„bl@„WVkV@Xa„a˜V„IXl‚IV‚„@XbVUÆ@XKWwUkmW@_UmnIlJXkWKXmV@‚w@_XV@Kl@kU@KlX@@UUUUKWLm@klJVUUmk@mXUWmXwƒ`m@„zUbÝakbW@m@UUƒéUIm@UbKǼ@™kKWXmWUkaWU—JWU¯L@W™Lƒwk@mm@_™ƒÅl™UVkmWUnV@VWLUb™bƑĬ¯l"],encodeOffsets:[[119543,33722]]}},{type:"Feature",id:"3402",properties:{name:"芜湖市",cp:[118.3557,31.0858],childNum:4},geometry:{type:"Polygon",coordinates:["@@„bVaV@XllLXU°ŽlL@V@VUnVl¯Ikš›VUVU@@b@lUXUWmb„n@¼šbƒĊ‚LÞ@lVXlmÞUnkJ@nlKVVšÞXklWVaVI@aUKn»lL@Kn@‚XXwlm@mn°@„V@Wy„wXlWVk™ƒ@aUaVU¯£kKWVXVWLUkkWlkkwmJUam@@aULVa@UƒVaUaVI@m‚@UUJUIUmmV@bm@UXVVUlVmImakKUU@UU@VmU@@kma@KVIXUVK@U™VmUkV™m±£@JkU@nlšk‚ƒLUlmb—@WbU@@XnlWb"],encodeOffsets:[[120814,31585]]}},{type:"Feature",id:"3406",properties:{name:"淮北市",cp:[116.6968,33.6896],childNum:3},geometry:{type:"MultiPolygon",coordinates:[["@@lnnK@¦n@@V‚V„@@VV@nIV„V@VW²a@b@bVnUVVV@V™z@lš@°UšV„IVaVV@x@ŽXX@WlwUnV@XblW„b@XlK@aš@kƒ@al@@_V@@WÅwmaUaV@„bnaVL@llInmU_@W@aƒUUĉUaVwm@XWK@wƒVkaVUUwU@@aV@@mlI@WœLWƒUUUƒVU@kV@XalKVaUƒVUUUk@WwUK@aVI@WƒUk@@UUU±xkb@lVš@xnLÇbUbk@@bÇVUJ±U@U—@WLXšml@bVVXL@lV@@LmbkLW`kbVxUn@LkxmV@bm@@VkV"],["@@VVVkV@¥@UV@U@VUUJƒkWakKUšlXVJ@bXV@blX@aXV@V"]],encodeOffsets:[[[119183,34594]],[[119836,35061]]]}},{type:"Feature",id:"3404",properties:{name:"淮南市",cp:[116.7847,32.7722],childNum:2},geometry:{type:"Polygon",coordinates:["@@°kƒīšaVaXK@U‚UVmnXUlšVÆkVKUUUmmU„ÑkU™UÝlĉKUƒwƒKƒbU@UxW@@lœmVUUVmUUƒmƒw—aW„kL¯K@Žm„ULWlIm`X„WL@b@¼@V@xkVƒI@b@l@lk„V°Ȯ¹ĸW"],encodeOffsets:[[119543,33722]]}},{type:"Feature",id:"3405",properties:{name:"马鞍山市",cp:[118.6304,31.5363],childNum:2},geometry:{type:"Polygon",coordinates:["@@šNJnllLnxV@laXLVKma„aXbVI„bVKVVVIVyn@n_ƒƒW@@ƒ„UnJlUVVXlLnaUWlV@VV„IXW@_W@XK@K@UVUUwVamÑXmmwƒw™KUnUK™çU@ƒJƒU¯@mŽ@nknWxWm@@LkKm¼VL@bUJUbkXWl"],encodeOffsets:[[121219,32288]]}},{type:"Feature",id:"3407",properties:{name:"铜陵市",cp:[117.9382,30.9375],childNum:3},geometry:{type:"MultiPolygon",coordinates:[["@@„ÒV¤@¼V²@aVV@Ž@„„x°Vš£nW‚@nbnaVXVW@k@aV@VUœUl™°JUkVm@U@UkK¯WVkKWkU@Ubƒakwmlwm@ƒkUmƒUUKU@@VmLUbVLUV¯U"],["@@LllUL@VlxšL@a@UƒwXamK"]],encodeOffsets:[[[120522,31529]],[[120094,31146]]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/ao_men_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"8200",properties:{name:"澳门",cp:[113.5715,22.1583],childNum:1},geometry:{type:"Polygon",coordinates:["@@HQFMDIDGBI@E@EEKEGCEIGGEKEMGSEU@CBEDAJAP@F@LBT@JCHMPOdADCFADAB@LFLDFFP@DAB@@AF@D@B@@FBD@FADHBBHAD@FAJ@JEDCJI`gFIJW"],encodeOffsets:[[116325,22699]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/bei_jing_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"110228",properties:{name:"密云县",cp:[117.0923,40.5121],childNum:1},geometry:{type:"Polygon",coordinates:["@@vIHZDZQtDLNMXIbHRCXXITbJ@H`LGPRDDJNCLHTOCWFGvGBUJMKGFO^IHWXITQCI’Y^AXGfRˆDXF`DJOLB~G\\DZIHHpErUVMhHb]\\M†BVF@FTP`@zTbD\\@~M\\K`H^EVODWICAakAQXoIcCOCIgGYNWFWNGGKKGaJEGMEIKYJUT_J_Go@_SyQaSFMEGTcYOQLIIi@EKAUPCV[EEXQCW|aMUMAaYCYNIDGGACIMGGSKDQGaF_C[GaB@GOIiOKAYL“mI@CN]F[SWWAcKKI@HMUimEKbeYQYISNUOcBKPIFBNgvDPGZYFSf]CMSIWGEUFgDIQ[MeDMJS@RR@LphFPCHaBAJKF@J]IBJO@HlO@@RKAMPJHCNDJTHFP@ZGNANBRFH@J_fM^ONJNF\\VTDJHDON@XRND\\XRCPVETCLBVKDFJINHRGPRV@\\CLJN@VbXbLVT"],encodeOffsets:[[119561,41684]]}},{type:"Feature",id:"110116",properties:{name:"怀柔区",cp:[116.6377,40.6219],childNum:1},geometry:{type:"Polygon",coordinates:["@@JHTVHXCHPfnDJGHNDJSB[JSBGVSAOH@PMPuDEHHXZN@PHF@ZLJ@LHVYJA\\OFWP]BMtMBSRGV[JeVAPQVIFENMD¡–@^NV\\JH@NNL@NM\\kTQ\\I^FNIpBHGTBFFAZQfKDIXQTLXFXNNVMVHRGpCFLlRLEVBBH`IVO\\G`RDPAXLXBXORHZEHTDLLN@VGTMrQNFPeASKG@GMOAKBYMK@GTUHUXSHMVDNMOUEOZMJML@^KRACMZEZMRQLUHE@OFENPR@DI\\ChMHIDG\\GJMDWHCKGMDCIQCHO_K@GaIJSWWQDaGWJMNCKRsCYGYuJUSaKaW@UIMDK@[QUHOGQJMEILCAUDKFSOUQD[WMC‚Q@WPMGCCIUSE[IMPMN]`e@IEGAQBMHM@YEOSGCIDMIGNOLB@QP@GkP@AI^J@ILEBIbADGEOog@KQQWSekWQQUOFKZLF@PUNmIaHIUeBCTSHENcJa@_IWSaGu`GLSBKJQFOXGDXVQVOBIHcDSJWBEFGTMH[^mLaXcHiKElTRKtFXZ`MHMPCNRDxZˆB\\ICIHK@KŽHbIVFZ@BPnGTGbDXRDJaZKRiGEFSFEJhjFNZFjn"],encodeOffsets:[[119314,41552]]}},{type:"Feature",id:"110111",properties:{name:"房山区",cp:[115.8453,39.7163],childNum:1},geometry:{type:"Polygon",coordinates:["@@h@bl@HRJDZ``TA\\VVD^H`\\pF\\JŒ`JGv@ZO\\GPSTEjPTR`FnEbDTDHEhLFMTK@ETSPULKEI@OVISKSJACEQNQbV˜IXGDIN@dMB[IIBcN]ZHNLP@XOWCFWŠCNRHTpATD@^NVNLED@Rh@jCEF}E[OOHUEW]W@QGGDIQSH_MmFmCUT_K]i@MHCMW—FCF‹E{BMHMPOHKS]CFNGBELDH_@BcAKOACESAOBELaXAROB@FODMEDWJAG[aE@UM@DImEWJMC@OeCA{aE[@{L@MINUCQXKfUJORCHqJBF@TCXWNQX]M[EAJO@@KMBQJIC]EWMCCUBEBFHKDOTMBGNGF]MWDBRDdMDQVyE@LPVHDCP@JVVMTG~HNSH[CmRUvHPHBbA\\PTNRC\\YNJ€PRARPJDDR"],encodeOffsets:[[118343,40770]]}},{type:"Feature",id:"110229",properties:{name:"延庆县",cp:[116.1543,40.5286],childNum:1},geometry:{type:"Polygon",coordinates:["@@^AXOPEB[ZIGU@KKI@YGE@OYMGWFGvCNO@OPGTBHUTA\\ITACIGMIHmCOeDGGWSUIGimYEEMgiFITEFEjHLQbYCIWQaCSHmHAOY@UEaJG@LGLDJ[J‡AwYQCDMNONGY_EWLsSQFkMO[NWAIGaIYL@HMBOKiOQDWEUDMQSF_QIUBWdg@[NaAKQ@M]OQ@WhgLUMMFYQDIRCEUZOOCIOJ[KIUMKL@HIDKVEBM`HJAJSJUdBLGNEdMBMO[BYEWJSNKNaD]PE\\SjOT_RQVEZPpƒNQXfŠNA~lNG`@PNLp¼RFLfbdKbATUh@FSNWjGFZVLFHVA~X¨PPROfFJbNJPLFbENJPrEFNPFRHDDJdENJLVEPBJTVTHGHFRFH@PXP\\ORQHW\\BjWFDERLPPBbB\\E`B\\D\\L`@F]FCnJ^AZL"],encodeOffsets:[[119262,41751]]}},{type:"Feature",id:"110109",properties:{name:"门头沟区",cp:[115.8,39.9957],childNum:1},geometry:{type:"Polygon",coordinates:["@@V@XMnGPY²‰JQNEhH\\AZMPDVTTDZCPiJkHSHCjIdFtEHITCNITQEKUAMCEIKCECABYESKFWAKBEIIHABGDCKCAIHMHALKEI\\CFIBILIJQZS]BBEECS@E@@C]COKI@CABAAEEDMGƒCH]A[M@CJWH—JaUMRFRBDTITLUJ@PFJKLOVST@FSLENgKGFSCaCmF_ESQiOSFOT[HYPu@IH‹_[IoE_[]GUC[USB__CYQI@Gakg@qZeHQNMNV\\FVLPgJAFJPRLCH[XcPELUT[JiV_EELFTADBXRTRLJC@fHXHHbPd`fR@NfT`@TLplHMpCEJHJBVLFŽ@JT‚VnG^KXDXHNVGRLRXFJVdDHSNWLGfEzA"],encodeOffsets:[[118635,41113]]}},{type:"Feature",id:"110114",properties:{name:"昌平区",cp:[116.1777,40.2134],childNum:1},geometry:{type:"Polygon",coordinates:["@@VNLJI\\JPPDYPFVQDCJZRNEVNhKXgR@^P@NLRbB\\Mh@XcVARJE`RTCNFV€XRCjPPLNA@GZKbJJHXB\\MNPjLdGbWnK\\]NGHSFEXATIdCJGPARUWUHCPWRELITAHKv_E@iYCaW_BQ\\Y@QIO@QDCIGZCEMWGFMFAFgHEDOCSqKCCFGAMKEAC@ODGCGs@WH@KQA@EE@CE@GEA@EH@GGUEEJEAYD@JM@@DAA@FHD@FTJEHUC@JUBKCKG@G[CIIQReAYhO@OXGDO@@FF@IHJFCPEBACBIAAKDOABXARHPNEHGbQAAKQFGIAM[C@WHKaGiCEGOA‹HUKCIokSCUSOCYN[BgGMFIR±ŠOZmHWNU@ShbbXDHVXXGJ^lZ@PZ\\Nb@\\FHJAD"], +encodeOffsets:[[118750,41232]]}},{type:"Feature",id:"110115",properties:{name:"大兴区",cp:[116.4716,39.6352],childNum:1},geometry:{type:"Polygon",coordinates:["@@F\\E~DFN@BDFEpHFCHBBEGCDCJBHUDSBB@ELCPbF@B\\J@BJVAFJ\\ADKTCBGECFMT@BMN@@FH@DaNBEnvB@FPBATK@FHEFIAKFBFL@@PKBFJHC@FXBRAFCDMPDTOL@JIVFDHH@DDH@BGRFCDLD@N^@@CNA@KNOAEBCECFEGCFGMGFIPMOEJOLBADBBHGG@GCHIECY@INC@DMGS\\AIOZAAEYA@GT@KKMBEETCGMVINFxA@MJADB@FlA@HJA@NND@DFA@DVAZBBOFKH_JA@K^GBC@EFE„G@gAENMXKJigC@IbSJMqGOP£RGSMGE@kbQFDPEFiBSGGSBK]I{CDWCIDOic[C_G@SuSO@EWKCO@MNY@\\uZOPENQD[LKESSKGBKEG@EJGAGHoH¥CqhifeJkX_XFFGHFNEDFPENKHM^IFIVL^S`DVEnNnG`RTCJHH@R^XFXGVPP"],encodeOffsets:[[119042,40704]]}},{type:"Feature",id:"110113",properties:{name:"顺义区",cp:[116.7242,40.1619],childNum:1},geometry:{type:"Polygon",coordinates:["@@EhEBENXHFNYDJHCD@RJP@R[ZARX`DbjZF@bHXT`Jb@dIFMTGDSfAJVbGnJVM@OKELYPERVXRflXTT@NIfC\\NJRhCVEHFJXNT^DTeZEHYCOhuAMJELOdAVPTMOWBWNMNEJgl]@WGUFIC[T{EEDEHGCIGMI@SECUQI[D{A{GQESPUH]CsiMCmHUeoHENcAaDGCMDGMQCACCBaCGLMAHB@DIEQLOAAEEJ@CW@CDINGAAGKQOCgV@LG@BEGDKNeREFBNCFIDOPKD[@YRW@GFWDAFE@EHDDrLDTCPGF","@@KrJEH[\\B@FF@CHFBHUN‹AJKADGECBCMAG^E@EbI@BEGP"],encodeOffsets:[[119283,41084],[119377,41046]]}},{type:"Feature",id:"110117",properties:{name:"平谷区",cp:[117.1706,40.2052],childNum:1},geometry:{type:"Polygon",coordinates:["@@ZJZRafFLjn€VGNJ@LLBdXX\\T^EDMJ@”nZKLBjPPJ@HbA\\H`DbERHLCFK^BZaFWXQLAGMHa\\OLO@SBIpBdCLƒVQfElO@GSAKEDQTC@GEBKG@ORIJBDAPDFA@CaOq@GGQAAEJK@KMUGAAGEAa@MGMBGCGSIIW@WSUCMDOJeWOM@IUF{WMWaDIMgIoRoCOKeEOEAG_I[cg@wLIFENQFDVTFJ@HNDJGHCFFFS|D\\EJHV@Xk^IhMFMNAXPX"],encodeOffsets:[[119748,41190]]}},{type:"Feature",id:"110112",properties:{name:"通州区",cp:[116.7297,39.8131],childNum:1},geometry:{type:"Polygon",coordinates:["@@FDAJTGDNDCTDDEDBBE@DT@@EHCDGJ@EIZ@@FDBR@ATFBBVFFE@@HNA\\VE@CLIFNJFNJBCP]A@LJFA@HJEDD\\C@DBCHLAEPF@@DH@APHAERDF\\GIxDTM@CFLBBFJ@CNUPMHECGDBF]BMFPDLRBHHBJMDCX@@DFIBFPBRKJF@CGANBHKbDDABDRDHNNCHDbCdBFMpGHiOYMefKJMC}HWAUNW\\NNBNA„kNU|]HMTMN@MZBLFFF@RIRUT‘BMFIEGaAGGAOIIUGTSFcYKS@MSLYPKRUBU]EWDOI]CKGASgW@MTWKIMCS@uMAKKADMECGAKVUTSDy@IjWLMNBF@hƒHEF@FAD]H@LIBG`ELAPYAUB@CEB@CMC@MIB@GkB@ECAIB@NwBMEUJHNSDFFNALLS@@HZBBFYBJP[BHTCND@JMZ@FDGJHDH@GHAABCKAIPPFONEJNHEHHDEFFDADBFMP@L"],encodeOffsets:[[119329,40782]]}},{type:"Feature",id:"110105",properties:{name:"朝阳区",cp:[116.4977,39.949],childNum:2},geometry:{type:"MultiPolygon",coordinates:[["@@bFGHBHFBFIVFHHG@@FFB@HDFF@@FRB@LXGt@DHCH@PBDLFBNF@BEXCHEX@ZQ\\@LCPOJCDEAMFEfQLMHCAFH@@KhUNE^AAEHCFDNGVODMI@AEKADEN@CSJw[HCEFQGBBOG@@CE@FOKBDGCAD@C[FCGIB@IE@K^BDOIAEMMIJEDKF@[UMB@GF@EEAUEABSQ@CA@EY@FJI@CHGD@FS@@CAFCACFSCCDCMSHBIECMB@D]@@MKCDCQEAHG@CCG@CGUEIJK@SPOCCNEDQBDNDB@DJCDLFCBBALJB@BVGPBKVO@KHCCCD@FE@BNA@FNCTDDJA@FGB@NBDW@CL@hT@@ZHHQDDDAFSAANBC@HG@EFS@@DE@@PCB@Ue@CADNJB@FCBWA@LI^ix@FIHrH"],["@@HUN‹AJKADGECBCMAG^E@EbI@BEGPKrJEH[\\B@FF@CHFB"]],encodeOffsets:[[[119169,40992]],[[119398,41063]]]}},{type:"Feature",id:"110108",properties:{name:"海淀区",cp:[116.2202,40.0239],childNum:1},geometry:{type:"Polygon",coordinates:["@@plDJVLŒGPBFHjDbHGL@X\\DBNHJREBLRBHaFGŽMGOBQAWPBLCBBAJBDFADOIEJGE@@EP@HCPWP@ZgfBRQJJ\\D@HLHLDVA@IVDFGSI@EGC@EBB@CN@@IZCAGHGaEqGJG@EjwJ]@K@GSA@e_I@NE@CA@Kg@KC@ENCFƒAKQAW@WIMK@V‹@I@@F@^EDFB@HcIaDYCBRRDCHD@EFLN@FE@CJUPEJOJMTBPEDIFCMIAKNOGMRFJNDVBFLSRMJSDGJsFcEiJGDGTIlOjYD"],encodeOffsets:[[118834,41050]]}},{type:"Feature",id:"110106",properties:{name:"丰台区",cp:[116.2683,39.8309],childNum:1},geometry:{type:"Polygon",coordinates:["@@hMN@NFTQCFRCBJFA@HJ@@HJ@HJ\\FTACDŒ@@UNLXJX@@MA@@IECAQlDFEHBDI~D@GXCFMVDFCH@@NF@ANJC@FnAB@AMF@@EDCDDLGP@LUOAUH@AIABKAAEDCKID@CCACMWA@EGDEILA@OK@AELEJBFEEGL@BSOA@EuAFmMACbG@@EM@ANS@ENFDAHSDCL[BEIUBAII@A[E@OaKD@FAACTGVIACDHDAFGAEDoGEFACM@i€g@@QFCMKMU@]SCoBGSMQ‰DEXXDWPO@MKYGM^AdJJA\\cNB\\G^„DNHFCBFABDBJ@PL^D@DF@T@FDAF^A"],encodeOffsets:[[118958,40846]]}},{type:"Feature",id:"110107",properties:{name:"石景山区",cp:[116.1887,39.9346],childNum:1},geometry:{type:"Polygon",coordinates:["@@NQPHLMJBDNJEFCAONSPIFIVODIF@@EKMFEC@DGQCAQZDbCdJ@GEAFC@]@EJ@DCSB[EGII@@GI@@GEBAIQDDESRMEM@gNYTIRKJAJEJ[DFJKLGBGNBJLDCDAHGBJJAFBLEXTLZFBAFDLD"],encodeOffsets:[[118940,40953]]}},{type:"Feature",id:"110102",properties:{name:"西城区",cp:[116.3631,39.9353],childNum:1},geometry:{type:"Polygon",coordinates:["@@XBDA@EIACM@IJAD]BC@SFABISAD]H@@OAEDQEW@BLE„MD@FLDh@@LDBF@@M`J@fTB@H"],encodeOffsets:[[119175,40932]]}},{type:"Feature",id:"110101",properties:{name:"东城区",cp:[116.418,39.9367],childNum:1},geometry:{type:"Polygon",coordinates:["@@DBf@@VDA@OF@@CT@FEH@@GADBMTBBECCRCGG@YS@@gDK@A‘C@PG@C^TBAJEB@TADC^IB@J"],encodeOffsets:[[119182,40921]]}},{type:"Feature",id:"110104",properties:{name:"宣武区",cp:[116.3603,39.8852],childNum:1},geometry:{type:"Polygon",coordinates:["@@RBX@RFFCŽBFU@aK@WA}CCJGAEFkCBRFD@JB@@N"],encodeOffsets:[[119118,40855]]}},{type:"Feature",id:"110103",properties:{name:"崇文区",cp:[116.4166,39.8811],childNum:1},geometry:{type:"Polygon",coordinates:["@@XBL@@bEV’D@BX@AC@MHA@EIBCCDSEMmB@EIDBME@@MG@EDUCENWD@H"],encodeOffsets:[[119175,40829]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/china_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"xin_jiang",properties:{name:"新疆",cp:[84.9023,41.748],childNum:18},geometry:{type:"Polygon",coordinates:["@@@›ρȁôƧƦóəʵסʵóƪԫʵѵͩƧͩړ›υࡓɛʵ@ȃ@óᇑѵƨɝɚôóНѺͩɜ̏ԭʵôƧɞñ@υƩ—݇ȂóƩƧ@ѵȂυœƥŌਗ—॥ɛóʵѵƧѹ˜݇̍ࢯ˜əɞυ˜ρͩ̏óਙƨƧŋôōóš̍ͩóʵן›óŋړͪƧѶ@ɜԭ—ԫƦɛȄ̍›ɝȄöςƩȂ̏œñȀ̏œƩóóŎə˜@Ő̎@ɞȀɝŎôƨóנѵȄƧ@óŏɝœóɜôŎ̍ͨςŎ@ƨóôƨɞ݈ʶóƨφó̎Ȁƨ̍ԮòѸԮמ@ѺȀ@ƪၬֆòȂñ̐òȂɜ˜óƨ̒Ŏ̑߼@φρȀ@Ő๐ς̎Ƨφ@ɝφڔ೦Ԯǿࢰ@ƦŏԮƨƨȄƧ۬ɜʶڔŐɚɚóŐôƨ߼˜ôƧƧó̐ƥóŏѺǿƦȁφƧς˜ƨƧ̒@ɜƥƦυ̐ɛƪͩƩəƪʷ̑ə@ȃƨʵנŋྸōਚԭԪ—@ɝƨŋ̒օςʵôƧ"],encodeOffsets:[[98730,43786]]}},{type:"Feature",id:"xi_zang",properties:{name:"西藏",cp:[88.7695,31.6846],childNum:7},geometry:{type:"Polygon",coordinates:["@@ôŌנœôʶ̎ͪô™óŎƨŌਚƧ̐ôςͪφ—ɚɝࢰ—݈̎Ѻ—Ѷƨôʶ०ɜਘ˜Ʀŋφ›Ѷȁ̍—ôŏɚŋ@̑ə—@ŏò̍ɜ›óƥôʷƧ̍φѹԪ̍ע@Ѹʷɜ@ôñנ@Ѷɛɞô̐ŏѶƨѸƧƥōƦœôŏô—@ƧôƩ̒ŋƨŌƦǿô̎ɜȁ̒—óʶѶôôО̒›ςƥɜНφσɛȁ̎υƨఱƧŏ@ʵƥœ@ŌóóóͩƨƧóŋ̑õóɞóɝԩͪɝρôƧ̍ƧѹͨڑŎ̑ōóƧࢭͩ̏ѵɝóఱóóԪυô@̒ƥŌ̏Ƨ̑Ȅ݇ŎƧ›ѵӏ@ɛõŏɛȄôӒƧŌѵǿɝ˜Ƨŋԫ@̏ʴƥ@óǿ̑Ȁóǿ̍ςóóυô@ʶɛñρƦƩŐó̎óœѵó̑ͪࢯОóɜן˜Ƨ̏ƥȄ߻̎̏̐ןŎɝɜöɞƩȀôöɛȀóͪ̐ƨƪ̍̎ȂƥԪυО@φɞ˜ôƪ"],encodeOffsets:[[80911,35146]]}},{type:"Feature",id:"nei_meng_gu",properties:{name:"内蒙古",cp:[117.5977,44.3408],childNum:12},geometry:{type:"Polygon",coordinates:["@@ኊȁ૊ö߼ƩɜɛנñԮɛѶóԮô@ȁѸóמ̎ගѺၬ@߼ʶԮӒ߼̎@ŐѹӒ̒Ԫƨöග̑ѶȄ̒ς।œѶɚöɞɜʴڔôôȂ̎—ѺȀς—ƨ˜ƪóԪ—ɜôɛОਕڔԭ˜ѵ̍ѹȂԫ›ɛƥ̍Ȃóɜ̎ô@ʶ݊ੲࢮʵږͪנƨôȂƧ˜̐ͪ@ŐƦƨφԬѶɜôƦ@ŐƧôôƦəŐ̏›@ŐڒѶԬô̐ʳԩНςōôŏɞ@ƨȂѶəóƧ̒ػ̎ó̐Őנóƨô̒@ƨɚɚ@עԫɛɛ@ȁυͩƥʳòևρ—̑ࡗƧͪ༃ॣԮփ̎Ʀ@ôô@ôō@š@ȁѵóƨ̍υȃóʵɛƨƥóυȂóəƪ›̐ρƧͩɜԭڔȄ̎عƧȁ̐ŏó̍ɛ›ƥƧ̑óρŐ@Ƨ̏˜ɝəɛ˜߻ͩ̍ͩɝО̍ƪƧóóӓƨóƧʳ݇@ɝςƪœ@ʴƩ—ƧƦôƨɛȄə›Ƨŋυ›óͩѵ@ɝǿóŌן̍ɛ˜óО̍œ̑̏ôȁ̍ŏòȁñóƦͩ@ǿə@ɛƧ̑˜ρȁυô̍օѹœóȃə™@ȂσʵѷƪòƩ̍—ôó߻ۯôʳƧ™óšõʵѵóѹɜ̍ȂѹôɛŌφֈƩͨρóυӑóޟఱ̑݇ͪóƪƨŌóȄڔԬƩςםñ̑ȃѵŐԭŏƨȁɛǿρôõɚɛóƧОə@ѹ̐ѵöԪͨôͪɛ̒ןŏƧƥóôƥƧɛŌôóɝó@̒݇Ӓ̒Ō@Ŏԭࢰ"],encodeOffsets:[[99540,43830]]}},{type:"Feature",id:"qing_hai",properties:{name:"青海",cp:[96.2402,35.4199],childNum:8},geometry:{type:"Polygon",coordinates:["@@ƨ@ôƪ݈ȁƪ˜@φɝòóƨԮʶɛ̐ѹͪôОəóƧɞᇒѶ@ôږô@ǿѶ›ƪȁςœɜͩφ˜ςŋɞôѶɛƨŌɞ—@ɚςŐñԪॢͩƨȂɞóƨŐ̎ŏעӏ̎óƧƦôœ̒ȁɜ›ςͩ̒œɚɛƨôƨɝφɛóȁƨŋóóɚͩƨóóƩ@ƧəŋƦƩ̍@ƧƧôǿυ̑@ȁɞǿõŏρƥסɚƧóτԫɞœôƧƦ@ñȃòñƥóυôôѹѵ—@ŏ̏Ȅɝó@ȂəŌóəѹƦ@Ő̍Ōυ݈ԩŐƧóôƧ̑›ôʵɞƧ̑ѵôƩɞƧ̑œóНѵóôʵ̑˜ɛȂó̍ƥȀƧŋ̑Ōóƪ@ƨó˜óŐƥ›ƦŎѷƨѵƧ̏Őɝóѵɜן@óòɛ@ѷʸס@ԩ̎υѺƨ̎óʸôƦɛœñ̎@Őɚ˜@̒əŌóŐ̎˜"],encodeOffsets:[[91890,36945]]}},{type:"Feature",id:"si_chuan",properties:{name:"四川",cp:[102.9199,30.1904],childNum:21},geometry:{type:"Polygon",coordinates:["@@ô˜ôŋó̑Ԯ̒ɛОמͪƨōöͫ߼ƥôȃƨóóñôƧóƧôōڔŏƨŐ@Ŏô˜òƥѺŎ@ōɜóנ˜ôǿô›ƦôԮ̍ɜôɚ›Ƨ—ñɛɚȁ̍Ƨɛևυ@óóôŋρԭɝ@Ƨʸ̍ŏυɜƧƧóƧƨȁρ̍ƨȃɚ—ôʵφóô̑̏Ȃ̑ʵɜʵɞ@ƨʳסƩóŎə—óɜƧôƩƧρ˜óôôô@ŎƧƨƨƪѹ˜ó̍̍Ʃ@̏ѹНôޟ̍Ʃóƪυɝɛ—əƨôŎɛȀ@Ȃ@ñɝʶ@Ōρנ̏—õóɛͨƨȂѵОɛʵ@̏ƩŐó߼Ƨల̍φɜȂυτɛОρƦɝƨóƪ̒Ѷɝƨóʶ̒œóƨƨôԪŏφ݇̎ŋ@ŏѺƥôɚɚŋ@ȁɞô̐ȃ@ŐѶ˜óѺφóƦôñòòȄ"],encodeOffsets:[[104220,34336]]}},{type:"Feature",id:"hei_long_jiang",properties:{name:"黑龙江",cp:[128.1445,48.5156],childNum:13},geometry:{type:"Polygon",coordinates:["@@ᇔȂਚНƨŐѶŏöƥςŏñƧƦóƨȁ@óƨ—óȁφӑóóƨ˜óǿ̎̑ôНɞ—ó̑ɜə߼›̎ǿ̒ôڒӑφ@Ƨȁ̎̏ƥƩ̎ρశ˜ôȂςƨφ@נɞ݈˜̑ƥƧɛƨʵƧȃƥ@Ƨƥ@ŏ̑ԩôɝρρóɛƧ›ƩͩƧó߻ʸ̍ʷѹƥɞڕõ̍öɝυ—̍ȂƧ̐̑ŏóƨñŋѹóóȁ̍›̏Ԭõʸ̏ŏ@ǿ̍@ƧОυ@ñƨòȀƥŎ̑ŐѵóɛŌóȂԫōƧŎѹñ̍ʶóОן@Ƨ̎Ѷô@Ȃ@™óŎó@@ó̍ƥԭք༄।ƨͩ̒ࡘς˜ñֈƦʴφͪ@ȂɜɜסԬə@Ƨə̑@Ƨóןô̏ŏ̍ô̑ؼôƨѵɚƧȁɝ@óŐρŎԪО̏ʴ"],encodeOffsets:[[124380,54630]]}},{type:"Feature",id:"gan_su",properties:{name:"甘肃",cp:[95.7129,40.166],childNum:14},geometry:{type:"Polygon",coordinates:["@@ڔôԮࢯ@ō̑ŋ݈ӑ@̑ɞôóôɜŋƦƨôóƨƦנŐɜ̑óͩԩͧѶõѺ̏ɚ@ƨНɜôöəςóɜȀƧȂԮŐѶŏ̒ȄמòƪρړԫôȃƧŋôƩ݈ͩɚ@@ǿɜ@φͩóŏɜӑƧōôǿ̎›ôƥƪóõ›ö@ô—ƨ˜ôƧƦôó̒ɜ@ɞŌõʶ̏Ő@ȀóôƨȂ@ʶע@@ƥ୾ӑó̑óŋôʵóɛړ@@ƩöóƩóρ—ɛƨ̑@óʷƥƥ̎ɛƧ›ôōƧǿôͩѵôɝȃɞȁõƧρóó—@ōƧŏړŐóŎôƨóƨôòƧôóȄ߻ƦõͬƧŎםͩɜНԭ̑ô̒óŌó—ƥ@óƨɝ›σԬƨôעəςƦöŐɝȀ@Ȃφ̒óȀƨƨ̎@ƥƪɚŌ@ƨôƪƧôəͪôôƧŌôȂυɜƧɞƧóəɜ̑›ρͪɛœ̑Ȃó›ƨƥ̍ôסӐ̍ŐƧŏɝôƧȁॡͪòԩρŏ@əɝ˜ƧŋѵɜɝóρŌυ—ɛͪρ›ƩȂѵœ@Ȁڕó@ȄɜʶφࡔڔœƨͪѶͪԬʶôƩעʶɚʶƥôóƨςȂ"],encodeOffsets:[[98730,43740]]}},{type:"Feature",id:"yun_nan",properties:{name:"云南",cp:[101.8652,25.1807],childNum:16},geometry:{type:"Polygon",coordinates:["@@ôɞôɝ̒öôŌƧƨôͪôô@ŋƦ›@ʶƨŐô߻ƪŏ@̐ɜʶѶНƧȁɜͧöô̐˜ςן@ŋɞʵ@ò@ȁɜǿóōɚƧɜ˜φɞôƩ̎ƪóޠѺО@̐̎ƪô̎Ѻ—ƧƩƨƧ@ōóóôóς—ƪƨƨóôɛó̑ԭ—ƥŌɛǿɝƨɛͩô›@ǿƨȁѺŌɚɛ̍ןѶНɛƧôóƥȁƦͩôŎɞ—ƨ̑ɜ—òôφ@ƨʵ@ɛѹōóȃəƨυǿóʵρƧƧŌƩɛ̏ȄñƧƧȀɝ̍ԩʶƧ̑υ—óŌƥʳɚӑóНƥô̑›óӒѵʵѹœƧӐןôƪφõŌƪ̒ԫŌƧؼƨƨס›ρȁƧœƨȂóʶó@@ʴƨôôφ̎Ŏ@Ȁƨ—ƪɚƨœóƨôôôςóޤƧŌƩŋƧԪ"],encodeOffsets:[[100530,28800]]}},{type:"Feature",id:"guang_xi",properties:{name:"广西",cp:[108.2813,23.6426],childNum:14},geometry:{type:"Polygon",coordinates:["@@ƦŋѺ̎ڔʵƨŐ@ƦמȄƪôóȂɜŌɚͩɜ@öóɜôôȂƦôɜȁ@ɞφ›óȄ̎›ƨʶɞŋƨʴɚǿ̐̎Ԭ@ôñ@̏ƨ›ρ۫ô›ɚƨƨНƪŐ̎›ƥóƦʵƥŋ@ȃóƥƧ@@ŏɝǿôυƧȁѵɛ@əóŏ̑@@ə̍›óƧó—@ȁƩ˜ρóòНƥô@Ӓ̑@óŎ̍ƥσŎυ@̍ƨ@Ō̑ôóͪƨ̒óŌړœ̏Ŏ@ŌôȄѺŎ@ɜƧʶυ@ñóɛ˜Ƨ̒ɝ˜óōƥͪ"],encodeOffsets:[[107011,25335]]}},{type:"Feature",id:"hu_nan",properties:{name:"湖南",cp:[111.5332,27.3779],childNum:14},geometry:{type:"Polygon",coordinates:["@@@քɜОƨ@öŐמóƪôƩɚ̒Ő߼ȁςͩɜòƪ—ɜȀò—ñɝò—Ѻͪ@ŏƨŋóɝôǿƨ™ɚȃóəƨȃѵͩó̍@ȃƨóóƥƨƧ@ʵƦ›óͩɜ—ɛóñԭɛōυȂ̍ƧƦō@ɛƥ—ɛȀ̑œóʷóō̍œƩŏƧОəƧóœς۬Ƨœ@̐óòԫ@̏̍əȀƧʳɝŌóɞƧ˜ƨɜóŐƨò@ȄƧŌρŋóôԪОóʶ@̎óȄ"],encodeOffsets:[[111870,29161]]}},{type:"Feature",id:"shan_xi_1",properties:{name:"陕西",cp:[109.5996,35.6396],childNum:10},geometry:{type:"Polygon",coordinates:["@@ςôöƨɝȂɞȄѶóóͪƨȀóŎƨœ̍ɜƦƦôʸ̒@ɜƧς˜ƪôõô@ƪڔ@ôɜóʶôŌô̒୽Ӓ@Ʀ@Ѻ̎ɜѺɛѶôöʶô™ƨšóʴ߼۰óô̎˜ñƪѸƩτʶ@ȁòŋəѹóǿ̑ʵ@ȁ̒ʷυփô݉ôН̏ط@ȁƨóô̏ƪõ@ʳ̐ʵ@ɝɛŋƩŌɛóןôƧŋ̒ó@ŏ̐ƥ@ŏυ@ƧƧôן̏@ƥȂѹɜəœɛóԭ̎ƥóóœóȀן—ɛô@ŎѹōñƦ"],encodeOffsets:[[108001,33705]]}},{type:"Feature",id:"guang_dong",properties:{name:"广东",cp:[113.4668,22.8076],childNum:21},geometry:{type:"Polygon",coordinates:["@@@Ȃô˜ôƨ̎œ@ɚ̒@ôŐ@ɚѶɜƨȂóφɞȀ@Őƨ@ôƦ@ȄƦŌƥʶƦôôŎôʸ̒›ɜǿƦ˜@ɜƥŎ̎ƨφȁɜŎòƥԮŎƨōóŏɛƧɝəɞƧ߼ɜςȃñȄƦŎ̒ōôòƨəƨ˜ɚН@əƨ̏ƪʵυŌəɛóəԭŏəœóŏѹœρʵɝƦ̏™ƥʳѶ›öō̑óóŋρȀυƧƥɛѹōƧôן—ɛŏѵ@óŋôʵɝ›ƪԩõ@Ƨō̍@Ƨ@@ƦɝԮƪО@@","@@X¯aWĀ„@l"],encodeOffsets:[[112411,21916],[116325,22697]]}},{type:"Feature",id:"ji_lin",properties:{name:"吉林",cp:[126.4746,43.5938],childNum:9},geometry:{type:"Polygon",coordinates:["@@נ@ôН̎ʵѺòƨōԬŎôȁɜŋѶô̒ŏƦōñǿòƧφ@ƨН̎@@Ȁ̐Őöʷ̐ԫ̎œôȂѺôòŌôƧ̒Őƨ̏̎ȁφ˜@ŋƩͩםȃƨ—@ȁ̑ʶ@Ōóôɛœƥѹ̑—συ݇@ɜρƧȃࢯƨôœəȂɛōƩɛ̏υρóõœƪʴυφ@ʶôŌóœρք@ɜƧ@ɝǿƧͪρȀƩó̏ŐƨȂ̍غړȃɛԮƨͪ̏ςƩœôɚφȁƦôɜƧôʶφȄ"],encodeOffsets:[[126181,47341]]}},{type:"Feature",id:"he_bei",properties:{name:"河北",cp:[115.4004,37.9688],childNum:11},geometry:{type:"MultiPolygon",coordinates:[["@@Ʃ̒̏ŌѺ̒Ʃ˜óȄƧŌƥͪòôñȂ̎ŐóȂ̒̐̎›ôНɜ—נ̎ôŋɞȀѶ@ôͪφœƨŌɚœɜȃóƧƨƥƪ˜@ʳƩ›ɞρ݈@υНφʵɜ˜ƦρƨƧ̍ɝóɛѹ̍ρŏ̑ôóƨ@œƧƦôƨɛ@ƥƨ@ȂƦ@@ôəŐƧʶƨŌυœ̍̎ɛŋôōɝ@óƧ̍›ƦʵѵʳôʵɜŏςôƪŋƨŌɚ@ôНƥƧ@ōѸɛ̐ô̎ʵѵНԭ@̍̍Ƨò@ȁɝ@əρυͩƪ̏ƩõƧŎƧōóšॡȄɛʶɜȀ@ɞςѶƧœƥςɛŐ@ɚɜɜ@Ŏôôςœƪς"],["@@õə@Ƨɛ˜@ŐóƦφô"]],encodeOffsets:[[[117271,40455]],[[120061,41040]]]}},{type:"Feature",id:"hu_bei",properties:{name:"湖北",cp:[112.2363,31.1572],childNum:17},geometry:{type:"Polygon",coordinates:["@@ñȄυƦöŐƩ˜óנƨƨφ@@Ő̏Ʀ@Ő̑ôƨŌנóɜôƪŋɜŌѶօڔə݈òɞōɜŎôӏƦóƨô̒óôȃƨó̎ŐôƧƪ@ƨȁςƧə̑̎Н@̍Ƨŏρôԭͩԫ—̍ʵƧšóȀôɞƧŌ@Őѹͩñ˜òɞñ˜ɛǿƩ˜ɛñρͪ߻Ȃ̑ŏƪəƩóםôõŏƧ@ɛНƥȄó›̑ѺƧ›ôφóƨƨƦƪóɜŐôóòôƨóφ̐ƨóƦ̎"],encodeOffsets:[[112860,31905]]}},{type:"Feature",id:"gui_zhou",properties:{name:"贵州",cp:[106.6113,26.9385],childNum:9},geometry:{type:"Polygon",coordinates:["@@ɜȀƦŋԮ˜ô̒ɚ˜ôōעƪƧʴɝ@ɛʶ̒ʶ̐ȁƦœóȂô@ôŏ@ōô—ƨʶѸô@ʶƨ˜ɞó@ōτöòυƨ@@əƨô@ɛ̒@Ʀɜôȃ@̍ôʵԩНôóςŌƨŋ@ȃƧñôŏƧɛƨ—ôɝƧʵ̍œôȃυœ@ɝɛȂƥóóȁɛóõôɛ@əͪɛŋôȁƩóםȃ@ƥƧŏړʶѹ̍ƥŌƦȂóôɜƨѵО̎נəɜѹŋƧȂ@ȀóœɜͪɞƧ"],encodeOffsets:[[106651,27901]]}},{type:"Feature",id:"shan_dong",properties:{name:"山东",cp:[118.7402,36.4307],childNum:17},geometry:{type:"Polygon",coordinates:["@@Ʃ̐φͪɚςɞ@@Ȃƨñ̎̎Ԯ@ѶОƨƧڔ@φН̑ŋ@Ʃ̒ǿ̎@ƨɜԬςôʶ̐ʶöԫƨƧנƥɜŎôō̎@ôŏóρƧŏԫôóƧԩó@ƥɜƧԭóƨʵɛƨ߻ӑɜНԩ˜óô̑óƧʳə™óɛƧ@õȀƧœ̍ȃɛŐóŏυО̍—óɝƩ—ԩ@ƧɚԫȄɚʶƨ˜ɞʶԪ̐ړɛƪ̒"],encodeOffsets:[[118261,37036]]}},{type:"Feature",id:"jiang_xi",properties:{name:"江西",cp:[116.0156,27.29],childNum:11},geometry:{type:"Polygon",coordinates:["@@ƧȄôɚəȄ̎ʶԬ˜ԮͪςóƨŐƪ›τɞƦōƥƧ@ŏςôóŐôô̒ʷѶ—ƪƩƩǿ@ō̒ɛôυ@—Ƨȁѹɛəƨѹ̑ƨ̏óƥѵʷô̍ɛȁôŏɝǿƧԫƧ›ôʳƥōòȃρȄ߻ɛɝƨɞɚɜƨôŐƧŎԭōñƦòԮɜôɛ˜ôͪƥœ@ʶƧƨôƦƧô@Ȅô̎Ѷͪ"],encodeOffsets:[[117e3,29025]]}},{type:"Feature",id:"he_nan",properties:{name:"河南",cp:[113.4668,33.8818],childNum:17},geometry:{type:"Polygon",coordinates:["@@φ˜̎ƪ̐˜ɞȄɚ@@Ȃעó̎ŌѺ̒ôֆॢȃô™ƨŎƨōƪöƩ̑ڔɜԩ̏ɝʵƧ—əʵԬȃƨəԪ@@Ƨ̒ŏô̍υȁƧɚ̍ôóŋ@ɝƧŋõ̑σ—@ŏɜŋôɝ̒ƧɚôôطρóóɛƩ@óƨ̍ŏƧôóȄ̑ôƧóƥôóӐɛōɝŎ݇ñړɚѵֆ@ɞ̏ʶ@ʴƩöó̐"],encodeOffsets:[[113040,35416]]}},{type:"Feature",id:"liao_ning",properties:{name:"辽宁",cp:[122.3438,41.0889],childNum:14},geometry:{type:"Polygon",coordinates:["@@ƨʴƧôôӔƨô̎ƩɞН̎ͪ߼ͪɜ—ɞɚ̐—@ƨςŏ̒ôƦƨɜœô̎ƪôςǿƨͩɞȀƨ@@ɛςփô›óŋ@ʵφυƩʳö›॥փρѹס@əɛ@ͩࢯ@ѹʵρ—ƩʶφȀƧ݈̒۬óʸɝŎѵ@ԭԫןɛƧƨƥςɛ—υʶφО"],encodeOffsets:[[122131,42301]]}},{type:"Feature",id:"shan_xi_2",properties:{name:"山西",cp:[112.4121,37.6611],childNum:11},geometry:{type:"Polygon",coordinates:["@@ɚѺñŌɚšôȄѺ›̎ֆφóςȂ̒—ɜƨɚ@@Ȁƨŋôȃƪ—ѹ̑̐ŋƪ̑Ʃρρ›óó@ōɛɛ@əɜŏƦρƨ›ρѵ@ɝɛǿɜʵóօѹ̑̍ŋסô@ȁə@ɝȃ̏—̍Ʃυ—Ƨô@Ȃ̐ظóОó݊φք̑ʸ@Ȃ̒ʶôȀ"],encodeOffsets:[[113581,39645]]}},{type:"Feature",id:"an_hui",properties:{name:"安徽",cp:[117.2461,32.0361],childNum:17},geometry:{type:"Polygon",coordinates:["@@ó̎̑Ő@ƨƪ˜Ѷǿɜ̑φ—Ʀʵ̐˜Ƨѵôóƪôôυς—ƨȂɞŏ@̍ԫôò̑ƥ—óȃѶͩƧƥôŏѺœôŏƦ—@›ƥͩƧ—ôȁυó@̑ƧɛѵʵƩƪѵ˜̑ʸóóôŏρó@ŐƦƨƥŎσɝƩœ@̎̍Оɚ̒ρƨƧȂôɜςôóظəó̑ƨóɞɛŌ@Őτ˜ö̒ƨŌ@ɞôŌ̎óƨəφȂ"],encodeOffsets:[[119431,34741]]}},{type:"Feature",id:"fu_jian",properties:{name:"福建",cp:[118.3008,25.9277],childNum:9},geometry:{type:"Polygon",coordinates:["@@̎›óȁƨӑ̒—̎ɚƨͩφŐƨɝ̎ŋóŏρ—@ōƨ›òʳəóƨō̏˜õɛƧ@ƨѵƧōəŏóŋƧô̑ɝɛʳƥ@@óɛõ@Ƨ̑ƧóȁəƧ̑—Ƨ̐@ɚəОƧ—Ƨɚóñ̑ŎóʴƨœƨԬɞȀóŐɜȂó̎ѶʸôƦƧ̐Ѻ̒ɚƧѺɜƨȂ"],encodeOffsets:[[121321,28981]]}},{type:"Feature",id:"zhe_jiang",properties:{name:"浙江",cp:[120.498,29.0918],childNum:11},geometry:{type:"Polygon",coordinates:["@@Ѷʶƨɜ@̒φôóȂƨ˜Ʀͪ@œ̐˜Ѹ̍τȂ̒̑נŐמôƪƧôӑ̑›@ƥρͩƨօ̏@@υɝó@ŋɛ@ôƩəóƧѵυó@ƩɜŋƧ@̍ŌƧɞυŏƧͪ̍ə̑˜ƧӒôȂ̍œ@˜óφ̑ɜ@ŎƪȀ"],encodeOffsets:[[121051,30105]]}},{type:"Feature",id:"jiang_su",properties:{name:"江苏",cp:[120.0586,32.915],childNum:13},geometry:{type:"Polygon",coordinates:["@@ôɞ̎˜φНôŐɜŏ̎Ȅƨ›öǿƨ@ôɜɚšƨʴ̒ôôó@Ƨ̎əԮȃԪૉöͩ̐ƧòʵφƧôʵ@óړɜóŏɜǿƧ›ɝρσȁѷ̎̏—ƥ˜óŐѹ›óŐƨƦѵͪôȄƦ˜ñ̒Ԭó@̎ɝŐƧȁρ˜óφƩóóôƨѶ̏—ƥʶυ˜ɛ̒ѵȀ"],encodeOffsets:[[119161,35460]]}},{type:"Feature",id:"chong_qing",properties:{name:"重庆",cp:[107.7539,30.1904],childNum:40},geometry:{type:"Polygon",coordinates:["@@əȂòɜƨ˜ѺɛƦȁ̐@ƪ—õŏφƥòȃƥ̍Ƨôυ̏ƧôñóóôɛŏƩôƧƥôƧóυƨœ̒ѹôœƦȃ@փƥɛ̑@@ɜƧó@ɚƧ@ñφσõ@ŎɝôƧ—@ʵѷóƧʵó˜@ŎóŐó@ôȁƥ›ó̒υôóʶə˜ƧȄς̎ƧȂôƨƨƨφɛ̎Őƨʷɞ@ςԮóŌôôφ@ɜֈ̎ƨ"],encodeOffsets:[[111150,32446]]}},{type:"Feature",id:"ning_xia",properties:{name:"宁夏",cp:[105.9961,37.3096],childNum:5},geometry:{type:"Polygon",coordinates:["@@ల̒ôޠφӒςôƪͧυևɜŋѺó̎ȁ̍ɛ@ѹס@@ʵƧȁôó@ǿ̐ŏöʵɝŋɛ@ô̑ƥóóƨƧ—ó˜ôœó@ƩôóƦ̍œóȀƨŎɛӒôŐυͪɛ@@Ȁə@"],encodeOffsets:[[106831,38340]]}},{type:"Feature",id:"hai_nan",properties:{name:"海南",cp:[109.9512,19.2041],childNum:18},geometry:{type:"Polygon",coordinates:["@@φɜƦʶ̐ôφô̎@ƨŎö@τʵƦ˜ԩ۫õН̏óƥȃƧ@Ʃəםƨ̑Ʀ@ޤ"],encodeOffsets:[[111240,19846]]}},{type:"Feature",id:"tai_wan",properties:{name:"台湾",cp:[121.0254,23.5986],childNum:1},geometry:{type:"Polygon",coordinates:["@@ô—ƩɝöƧɝѵəޣ̏ρƩԭóōóͪρɞƧОôԪ݈ଦѶɜ̒ɛ"],encodeOffsets:[[124831,25650]]}},{type:"Feature",id:"bei_jing",properties:{name:"北京",cp:[116.4551,40.2539],childNum:19},geometry:{type:"Polygon",coordinates:["@@óóó›υóôƥ@ŏóóə@ƧŋƩŌρóɛŐóʶѶʴƥʶ̎œôƨɞ@óŎɜŌ̎̍φ›Ƨŋƨʵ"],encodeOffsets:[[120241,41176]]}},{type:"Feature",id:"tian_jin",properties:{name:"天津",cp:[117.4219,39.4189],childNum:18},geometry:{type:"Polygon",coordinates:["@@ôôɜ—@ƨöɚôœôôɚŏ@óƥ@@ȁƦƧɜ@óƧƨƥ@›ƧóəН̏óѷɜ@ŎƦƨóО"],encodeOffsets:[[119610,40545]]}},{type:"Feature",id:"shang_hai",properties:{name:"上海",cp:[121.4648,31.2891],childNum:19},geometry:{type:"Polygon",coordinates:["@@ɞςƨœɛȀôŐڔɛóυô̍ןŏ̑̒"],encodeOffsets:[[123840,31771]]}},{type:"Feature",id:"xiang_gang",properties:{name:"香港",cp:[114.2578,22.3242],childNum:1},geometry:{type:"Polygon",coordinates:["@@óɛƩ@ρ@óœôȀɚŎƨ@ö@@ōƨ@"],encodeOffsets:[[117361,22950]]}},{type:"Feature",id:"ao_men",properties:{name:"澳门",cp:[113.5547,22.1484],childNum:1},geometry:{type:"Polygon",coordinates:["@@X¯aWĀ„@l"],encodeOffsets:[[116325,22697]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/chong_qing_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"500242",properties:{name:"酉阳土家族苗族自治县",cp:[108.8196,28.8666],childNum:1},geometry:{type:"Polygon",coordinates:["@@XJ°œlJX@lbl@XbV@VLnJlxnbšƒUU@IVK@lVIVwnJlU@n@J@L@Jn@l_nWVLVln@@blLšmV@@xœÔ‚`nœ™xV‚ÈLlx„LVxVVšƒV_U»VWn_m¥XwVmnX°ƒlmUUVwÞaVƒk@a@mmIUa@™mwk@™ƒm@@U¯a@UV@@K™@ykkmwkV@kU@ƒÑƒVkKWLÅamaUm@kyU@WkU@Ua™IUašVaUUmUUa@aVLXKWa¯UUbmJXnWnX`l@@xkzWÆ@V„LU¦‚x@b@JkIkJ@LmbUamJwm@óxƒnk@V„@x„ŽVnUVmVUVŽUbVlUbkXWŽ"],encodeOffsets:[[110914,29695]]}},{type:"Feature",id:"500236",properties:{name:"奉节县",cp:[109.3909,30.9265],childNum:1},geometry:{type:"Polygon",coordinates:["@@WVXb‚UnK@x@b‚²kxmKkl¯_ƒVV°™VU@bnKVVV@@nkŽ@n›bn‚@š°@VLČUš@°WV@V™nU@InKVl@nU„b˜KnX„WlknLlKUwnalLša„VlUXmWk@UU@UWWIUyķ¹XaWW@X™ƒKUIVm„U@W@UVU@KV@n»VkUkÇmUmVIUmULUbm@ƒwUaƒKkkm¯ÑUL@bWVnx@VmxUI@„klmkkK@aƒK@IlJ@I¯ƒk@mak@mnkJVL@bV@Ub„„W`UUUV™I@VƒU@VVbUJVLUVVbUX„VVxk¦VJUnVxnVVUšJV@Ubl@@bXV@L"],encodeOffsets:[[111781,31658]]}},{type:"Feature",id:"500238",properties:{name:"巫溪县",cp:[109.3359,31.4813],childNum:1},geometry:{type:"Polygon",coordinates:["@@nLWbX‚VLVU„V@KšIVl@b„@lbšU„VnU@JÆU@V@n°KĢUl@VbÞKšVš@„_„V‚KXU‚U@KXƒ@wlkkU@mWKUU@UôJ@XV@œaVmÞIVaVLƒƒ@»kmƒ@ƒUkL™U@aU@WWƒLUUU™™KkbƒwWa@KU@kaƒXmW—LƒamVk@UmL@JmVUšU@¯X™@ċVUK¯@ÅnWK™LkKULWK@UXK@wW@™LkV@bVLƒlXn›`¯xU„°LnŽlV@n°Lnl"],encodeOffsets:[[111488,32361]]}},{type:"Feature",id:"500234",properties:{name:"开县",cp:[108.4131,31.2561],childNum:1},geometry:{type:"Polygon",coordinates:["@@n@na‚I„wš@@VVK„LVbVxnVÆUnanKWXamKmk¯K@mkUm¯KVƒ°w@Wm@UIUUlKUU@a¯KWanwmUXamKkUWUnU@KƒkUwWKXaWLUWkImaUUUƒƒKka±k@lƒ¯w™wmbUƒ™ƒkXm@UJkIW‚XXƒbƒmƒ„UJ™XUV@°šKlšlVXV@xmbnV@blV@VšœU`UL@V™a@bULlb°VXbܚ@V@bƒL@J„xnLVb@lVb@V@@z˜bXWšX„KVLV‚š@@bUVVL@b„„lVna@ll@„zl@@J"],encodeOffsets:[[111150,32434]]}},{type:"Feature",id:"500243",properties:{name:"彭水苗族土家族自治县",cp:[108.2043,29.3994],childNum:1},geometry:{type:"Polygon",coordinates:["@@„Jlb@nVV@bXb@ÆlL„Ul`nVKU¼VxkbW„nlUxlXX‚@°°WnnJ@VUn@J„k°L@VlV@nUJ„x@bVVVz@VnLla„KnalVlIUŽ„¼@nV@@anKUwVal@UlJœƒlI@akU@UWXKVI‚¯Uak@@KmkXWÜkXWykIWwXw@laXamkVUUym_XmlkkmmakwmIUKU@Wak@kaW@kI¯›WIk¦VŽƒUUƒmaUV@XkVUV±aUb¯b¯¥m@@ImJ—@mƒmL@kUKUkkJƒbV¦"],encodeOffsets:[[110408,29729]]}},{type:"Feature",id:"500235",properties:{name:"云阳县",cp:[108.8306,31.0089],childNum:1},geometry:{type:"Polygon",coordinates:["@@lb„LV„VVnblJVXXKWbXLVx„l@LmVXVVl‚nLWbnVmxXb°L@bVVkLVVVJn@@X‚‚œ_Wm„kUK@alUšKX@@xWL@VXLVKlLšKXLÆm@™mœa@ml@mU@UUmL@aVšUU¯„U°`lknLlw±@a@wmLVWaXU@KWU@ak@VaU@™IUVmUUwVmUIl¥UwƒUVWUaVUUKVIUa@UUUUJƒUUm™kƒ„nl@„@VWV@L¯aUb™Ulxƒ@@b@VULUx@VUxVV™U@bU@mxU„U@mUVŽklkkƒ@WxknlxK@amLƒKU„K"],encodeOffsets:[[111016,31742]]}},{type:"Feature",id:"500101",properties:{name:"万州区",cp:[108.3911,30.6958],childNum:1},geometry:{type:"Polygon",coordinates:["@@ĸĊVI„ƒ„n„aWWXlJVIn@lWš„V„našx°xk„l@²Ž‚LVƒ„LnK@b‚LkwlmXw„@lllkUnVV@VƒnwV@@ašVUUVw@UVwVK@U@a„@kwšVVa°b@KXU@U@ƒmk„ƒÇсaml™kUVmn@VULU˜m@kUVkUaƒwUWm@Uw¯„mKUUmVUUULUKU„W@XbWVkaWwkUU™ƒ™k@maUbmbVlk¦ƒxUVUIWVU„kJVVkL@UmJ™UUVU@lLUVU„lx„@@VbƒJ™U™L¯¤@Vƒ„"],encodeOffsets:[[110464,31551]]}},{type:"Feature",id:"500229",properties:{name:"城口县",cp:[108.7756,31.9098],childNum:1},geometry:{type:"Polygon",coordinates:["@@VK@w¯L@m@UÅV@ImVƒU™Vkaƒ@@aUk™J@LƒUUVUKmLmbÅVmUUwUaƒKUL@U™@ƒxJmbm@nVJ@X@VkV‚n™lƒLXx™@ƒb@bUVƒLU`UnƒbU@@ŽmVVX@JX@VLVVšklV—„‚`@bUL@V„LVKn@‚U@„UJkn@lmLmK@X@Jn@mb„nÞWVXnJ‚k„KČÑÆ@VK@knaÜmXlUČW°kôÇƁ@a@yÞ_VmƒUnU@K"],encodeOffsets:[[111893,32513]]}},{type:"Feature",id:"500116",properties:{name:"江津区",cp:[106.2158,28.9874],childNum:1},geometry:{type:"Polygon",coordinates:["@@„InWUUlU@LVašlX@°²lÒXxlK@Ul@@Un@UaVJ@I@W@UƒUUVUwVIUKUa‚UUVwn@Üx@XUlnn‚bœJ@¥VklKUUlk@ynU@kVƒUUVWnI@¥V£VWVIUKU@UVƒa@n@Vm@@nlUaVkUwƒJ@blLkLW@XWmXkmmLn™@m@U@UVm@™„UVUUlakUVa„ƒVkV@@wnaWUk@VwkƒlmVIkUUxmJ@U„™@KƒIkx±V@IUm@K@IUKkbWKUbn„m„@bmVnbmb@xkxUJ@ULW`@bX@WVXL@Vƒš¯„mk¯@UJ@VmLUaWnX@WJ@nkKkxW@UIV@@KkImmkK@UW@XaWIU@U‚ƒIkbWb„xXŽlLVbnV@bWlX@VxVLnl@nÆÞVÜ"],encodeOffsets:[[108585,30032]]}},{type:"Feature",id:"500240",properties:{name:"石柱土家族自治县",cp:[108.2813,30.1025],childNum:1},geometry:{type:"Polygon",coordinates:["@@„š@kl@š¼UbmVXJ@bV@nxVIVJULVVk@@LWbnJVU@bVbUJ@blLXnWV—@mbnV‚@V„„bn@VJVLnaVanbl@„šVšlVXxlbXUWaX@VƒUUVwUUVm@I@WmI@a„mlLœ™lK@alwnUV@kóVaƒÝk@UlbVK@™VU»VUUVWUƒ@U`ULkwm@@KmU@knKƒ»VkJkUmbƒLkbmK@UUyUU@aƒwm@@XXJ@VVLVVUbVnUJVX@K„„k`WXXJWXUbmW@bkL™Um`Xnƒb@JVL@LU@™°VVXKVnUxVLUbmJ"],encodeOffsets:[[110588,30769]]}},{type:"Feature",id:"500237",properties:{name:"巫山县",cp:[109.8853,31.1188],childNum:1},geometry:{type:"Polygon",coordinates:["@@kVƒU™bkKmbVxkLmKkllbV@@LXb„xlašLVšVV„KXXV@@bšVlK„V„@ln@¼°KXa„U@Ulw°JXalIUa„ÝWXW@kVU@ƒVUVWUUUamUw@aVamwn@VUUƒlLXWm£@wÇĉkKklmLUÒ¯ƒWn™@ğ±kwmaWm¼U@@LUV@V@XƒVUnVJ„LWš@‚XXWbĸºVzXJVXV@@VXlWn"],encodeOffsets:[[112399,31917]]}},{type:"Feature",id:"500102",properties:{name:"涪陵区",cp:[107.3364,29.6796],childNum:1},geometry:{type:"Polygon",coordinates:["@@nèVblĖVVnLšŽ„@šx‚V„n@nšJ@L„UVVX@lbUJV@@nn@VVVK@z„˜V@nzVJVUlmX@@_VVVbnaVal@@knW@wnaƒVK@aVI„J@£kUVW@‚wXUVJ„amƒ@Ikƒƒƒƒ_X¥ƒ@WwkKkwmŽ™šƒkUxƒnÅmm¥™WV@Um@UlVL@JU@@Xƒ@UVkKVk™KVk™Kkb@bmJVXU„VVUbU@@`W_UV¯b"],encodeOffsets:[[109508,30207]]}},{type:"Feature",id:"500230",properties:{name:"丰都县",cp:[107.8418,29.9048],childNum:1},geometry:{type:"Polygon",coordinates:["@@Þè@XUK@LlV@blbUJ@„„V@bnV‚@VVVXU@ƒlbXal@VXnKV@maXUރ@amk@aVKXV‚anbš£°mnIVaUKVwUmWLUUš¯V@@KUK@I„aWmn_šVlK@anXVaXWWIXWl_ƒƒ@LUWVIUmVaUUUK@UWI@Wn@VI@mkU@U¯Kƒl@ImVÅLƒwU¤óbUU@wWXkmm@LU@@VUIWVUL@JUnƒaƒx@Jn„ƒbUIWVx@ŽUXlV@¤ƒIUJ@bUL„Žmb@xmX@lk@UbmbUaUU@`W@kn"],encodeOffsets:[[110048,30713]]}},{type:"Feature",id:"500232",properties:{name:"武隆县",cp:[107.655,29.35],childNum:1},geometry:{type:"Polygon",coordinates:["@@l„„w„bVm@IVKXUVJ@UV@@KnnWlX@xVVôaV£„xÆKnUVm@UmIXm¯¯@WkWVwmkXƒlaUwV»ULmk_ƒVkK@ÅWa@aUU@mkaƒIƒb@‚n¼ƒnm‚_@mmK@UƒLUVVmI@aUJ@XWJ@U`UIkm±kk@@lULmUmKUnVšnlUVmI@VkVlx™bkIƒVmLUxkKUŽ‚Xš‚n¦Æn„mVw„lš™nlxlLXx„@W¦„`„„"],encodeOffsets:[[110262,30291]]}},{type:"Feature",id:"500119",properties:{name:"南川区",cp:[107.1716,29.1302],childNum:1},geometry:{type:"Polygon",coordinates:["@@VšUbVJVUn@VLX@WVXVVI@VUVWxU@mš@ĊX@@¼V°aVUX`@_V@VaUUVƒUWnI@alašLUlšLUllLVU„@@WV@@IUKVkn@@VlLVwnK„UlJšakwlU@UnJVUmkU™VmXa@wVK@UUw™@VƒVI@akƒ@alInwlKXUmaUW@wWLk™™KVak_ÇaUƒƒV@šXbƒLVxUlWIk@UK@V™@ƒkU@VbUVUlVnƒLUV@lVXmxkV@L@V@Vk@WbUwmL@JUI@xVxkx"],encodeOffsets:[[109463,29830]]}},{type:"Feature",id:"500241",properties:{name:"秀山土家族苗族自治县",cp:[109.0173,28.5205],childNum:1},geometry:{type:"Polygon",coordinates:["@@XlV@lzn@VŽnbÆbXKlL„U„ÒV@@llUnxll@zšŽ@LU@@V°b@Vn@š„l@VÑUƒnK@UšU@aUaƒkVm@K¯wƒklmnn„Ul`nI@almkIUwmWVkUaƒkkJmUUa@K@aU@@_m@@wUyVUUa@Umƒ@awl@Wka±„UkUykIWV™b@bUVk@›aU@UXU‚UIWakUWmUxUV@nUVWbšŽ@XXVVŽmXXŽ@VƒbVLkVWx"],encodeOffsets:[[111330,29183]]}},{type:"Feature",id:"500114",properties:{name:"黔江区",cp:[108.7207,29.4708],childNum:1},geometry:{type:"Polygon",coordinates:["@@VX@V@LV@VJUL@lVnnxlb@VXV‚XV@@W„@UIVK@kUKna@£VWUaVUUalIVJVIUW„_lm@bXKV@mn@J„UUw@KnIVll@VanLVmUkVKXLVKUIVamw@UaU_lw„KlwUWV_Ua@aUa@KUšwm›_›Ó@wU@™nkK@am@UkUKmXk`m@@I@K@I@mkVmIUxUJ@kUL@JVV™„lnklWnn`VzUVnlWbkb@WxXxlJXzWŽÛlWXnl@Ll@Vb°UJWLX@VlV@bkJ"],encodeOffsets:[[111106,30420]]}},{type:"Feature",id:"500117",properties:{name:"合川区",cp:[106.3257,30.108],childNum:1},geometry:{type:"Polygon",coordinates:["@@XKVXlK„ƒVL@UnV@aValXXK„U@WVwUaVU@IV@@aVW„L@U@anVV@@bVK@UVL@bnJWL@VnUnb˜@@JnIlVl‚@@bXIWbn@UKVLVKXLlaV@VVnK@bVL„m„IVƒ@KmknUUWVI@aVJ@_„WU_VmUwƒU@K™ƒVak@am¯mJU_UJUkU@WkIV`UI@JV@LmmU@@mƒbUzś™@„VK@nUKƒ„ƒb™akb@UWK@bkVVbV„Û@@`ƒXk@WŽ@n@lXL@bmb@VVJUn@JnUlnUlmX@`XLlbkJW@kzlb@`@b@b"],encodeOffsets:[[108529,31101]]}},{type:"Feature",id:"500222",properties:{name:"綦江县",cp:[106.6553,28.8171],childNum:1},geometry:{type:"Polygon",coordinates:["@@@¦‚@X„lVX@@UVKl„VUX@lanVlUVbXWVXVƒ„VVUnKVUlwUwU@UJ@nmVkUV™lwXam@VaUUUw@W@kk»mV@UmKkwVKVUU@@LUKVI@mV@XVWxnXVKUUUK@wWU@UUWnUlLXa‚mUI„am@wI@K@amIm‚UUkI@m‚akUkKWUUanƒ@wƒamLVxk@UVmUUL@Vm@kV@I@ak@@bWVXJlLVbVL@š@bn@@`Un„@WbUKULWVXbƒ@UVmbX„WVƒb@bVmxUKUƒV@šUn@V@V@nmšnKlnnWWXX@lKkK@a„IVxUlVb‚k@mn@@U@m„bVUV@VLUJUXU¤"],encodeOffsets:[[109137,29779]]}},{type:"Feature",id:"500233",properties:{name:"忠县",cp:[107.8967,30.3223],childNum:1},geometry:{type:"Polygon",coordinates:["@@VLÞĊ„U@Wš@¼V‚„@lk@w²mlšVUœ„llšVnI@VlKUUlIVƒXUVJVU„wl¥UkUKUIm@ƒaUƒ@mUna˜@XUWmkK@aVIUa@aUVmIXa@Kl@UUVKUIUJmwU@@aWInUVa™»k@@lƒ™¯n™¤mabWUUL@bnl@b݄WVnbU@mLUWk@Wbka@„WVUU@UmUmVkUULV„lVUx„l@L@VƒbÈÒlb"],encodeOffsets:[[110239,31146]]}},{type:"Feature",id:"500228",properties:{name:"梁平县",cp:[107.7429,30.6519],childNum:1},geometry:{type:"Polygon",coordinates:["@@XLV@VV@b°°nšƒnkb@bƒšnJWVXblIUVšxWnUJnVVLVU„JlUnLVK@UnUVJš²nKVbVKla@aXlJ„k„Klb„ƒ@U°£šKšV„IUa@ƒ@kwVƒVUkKV@VUkk›ƒUVk™±n@xklƒ@U@»™‚@XƒVÝĉUJnxWb@UX›KkVUbUKWUkVmkkLU`›b"],encodeOffsets:[[109980,31247]]}},{type:"Feature",id:"500113",properties:{name:"巴南区",cp:[106.7322,29.4214],childNum:1},geometry:{type:"Polygon",coordinates:["@@nxnVlJlUXLƒ¦@x@Vl@nKVVX@V_V@@KlVXU„@lKlxXIl@ÈĊ@Vl@n_VJlŽnVlnb„²VVVJVVmUUkĕUamçU@»W@@ĉn™V@XwVU@UUJWUXUW@UKm@UVUIVaU™UVmLUVƒUU„UWWXUakVmUkbW@UVkƒUL@VW@kUWƒ@mJUXVVU„@lmV@zklVVkLUl@¦›I"],encodeOffsets:[[108990,30061]]}},{type:"Feature",id:"500223",properties:{name:"潼南县",cp:[105.7764,30.1135],childNum:1},geometry:{type:"Polygon",coordinates:["@@@a@a@_kalyX@lIkaWK@_nWVkkmmV@IVmUI@Una@aWK@k@mkbWaknmJUk@mk@@kUal@Uaš@Wa@aXLlwUKlkkƒ@KmI@VUJ@Lk@@VUUmL@amJU£kKUaWakLmU@bVVUbnbWV@xkL@bUb‚xUxVbXJVbUVWIUVU@kLWxkKWV@n¯VUbU@@VVX@VmaUL@VUK@VVbn@lVnI‚@@lnLULm@Ub@Žl@na„@lK@XVVkJ@b@zl@@VnV@bVb@J@bnXV`lXXmVI@W@InbV@@aVKUblKVLUanLlmnLlK"],encodeOffsets:[[108529,31101]]}},{type:"Feature",id:"500118",properties:{name:"永川区",cp:[105.8643,29.2566],childNum:1},geometry:{type:"Polygon",coordinates:["@@@b܄nWVLX„lxV„VxXxlVn@@bVblK@a@UnLVJV@@UnLVU@VXaVKVXš@n`WUÿ@IUKlaUUUkWyUÛÅÝ@mmkUKUwW@Xk@amUUakKWƒwXaƒK@VVLklƒXVlkxV„UL@bm@Vxn`ƒIVxUVkLVšUšl@@lkXmmƒVUn@VV@Xb"],encodeOffsets:[[108192,30038]]}},{type:"Feature",id:"500231",properties:{name:"垫江县",cp:[107.4573,30.2454],childNum:1},geometry:{type:"Polygon",coordinates:["@@šĊ°¤nҘ¼œaV_lKnllUXVVLValUœLVW‚@XamwVIUKkaÇфa@U@KƒkVwkUUƒVKlVnU@aƒU@ƒVIka@akU@KVL@WÝçUV@Vmbů@L™KƒnnJW„ƒVkxlL@VX@VxmnXVWxUb@bkn"],encodeOffsets:[[109812,30961]]}},{type:"Feature",id:"500112",properties:{name:"渝北区",cp:[106.7212,29.8499],childNum:1},geometry:{type:"Polygon",coordinates:["@@@bVVXL‚a@lnbWn@L„@XVlK@VVLUVlbkLUKVVVL@VšnX‚VL@VV@UbVb@x@¦UxVb@bUJƒL@L„VVxlK@™nk@U@W„UVLlKXV„@VblU@UUKVU@wn@VJVanLlkX@VaVK™¯@a@U@U@ƒVaUK„kUUƒ±maUkm@UUkbm@@Vk@@JƒwU@Ub@I@JmwUL@aƒ@@KkVÇLkƒWkƒ@kUU@@xUVmKUnllUb"],encodeOffsets:[[109013,30381]]}},{type:"Feature",id:"500115",properties:{name:"长寿区",cp:[107.1606,29.9762],childNum:1},geometry:{type:"Polygon",coordinates:["@@VVšU„bX‚lX„¥l@XnVmlxUx„@@blVnnôĀlm@aVaXwWUnmUwW@@UkKlw„UXƒmI„mšL@KÆ°na@UUImyU@ƒ—@yULUUm@@mU@VIkaW@UUƒV@K™I@mƒmU™wƒ@™mKUnU‚UIƒlVLUb@„@V@V@bš°ULUbW@klmKUbUIm@@xUVVL"],encodeOffsets:[[109429,30747]]}},{type:"Feature",id:"500225",properties:{name:"大足县",cp:[105.7544,29.6136],childNum:1},geometry:{type:"Polygon",coordinates:["@@XUmaVaUU@anVlKXbValU@aV@@IXKš@@bV@VxVK@UXLlUšJXa@_‚@@aVK—ÅWVkwWaƒƒwUa@am@kUWLU@kWmX@ykI@W@UV@na@LlLV@UƒkwWƒUKmXX`mIVl@bXLWVkbkkƒx@`VXm@@J@U@UUKUxk@WbUIVl@VXLW„ƒJUkUlUImxXlmb@X@VUJUnVbšW@UV@@VVX@bnW@LVxUnlJUV@n„@VxVIn@l`„UVVVL"],encodeOffsets:[[108270,30578]]}},{type:"Feature",id:"500224",properties:{name:"铜梁县",cp:[106.0291,29.8059],childNum:1},geometry:{type:"Polygon",coordinates:["@@VblLV¤nI@bnKVV@Ul@@KVI@UnJ@Ll„klVLkxWK@bXb™@Vbk@Vb@ll@@nVlnIlmXblaXl@„W@_Ü@UƒUalU@aXL@Vlašb„a„ƒVL@mUL@ƒUUƒƒÇXUW›X_WaƒƒUƒ»m_™@UWULWb@UUVmK@VU@UImK@V@bkL„x‚„XblxXU˜ÆUL@b@@`Wb™IkVWK@VULUwU@@a™@WL@JU@@bkVUb"],encodeOffsets:[[108316,30527]]}},{type:"Feature",id:"500226",properties:{name:"荣昌县",cp:[105.5127,29.4708],childNum:1},geometry:{type:"Polygon",coordinates:["@@VI@U@WnaWknwVJVkVl„IXƒWK@UUkVJXal@VwVL@V@V@In@UW@_„wlllaXUWK@aUknJW_ۃ@aWaU@@UVm„UUaUImJVnÅUmVUm`kUUVWLnVU@VVmXƒK@„nxmŽULkx™ImJ@nU`@X@Vkn@`@nlV@nVJVaX„VLnK@bVV@nV@lbXWš@"],encodeOffsets:[[108012,30392]]}},{type:"Feature",id:"500227",properties:{name:"璧山县",cp:[106.2048,29.5807],childNum:1},geometry:{type:"Polygon",coordinates:["@@XzVlVVkbVL@JVĀXŽ‚¼V„„„XbW`XœWVȎ„„VVšŽVkV@@UXa@alK@IƒƒU@UKWUyUI@wVUUWVak@VUkƒW¹@WXI@yVIUK@kWwkѯ±W@™kUb@KkVVVmXƒJ"],encodeOffsets:[[108585,30032]]}},{type:"Feature",id:"500109",properties:{name:"北碚区",cp:[106.5674,29.8883],childNum:1},geometry:{type:"Polygon",coordinates:["@@X‚VLV@„„@JkL@bWb@VU@UlƜVy„a@nV@nn@KU@IVJU_lJXV@VlVIV`nIn°@b‚lUbš„„KVI@aUaVw@¥@wUaVaU@@UUKW™m@UUKUUVLlKkaVUUK@UkLWUƒ@@KXmma@kbWKUU@aUamLnÞ@VWLk@@Wm@ULU@@U™KUVWI"],encodeOffsets:[[108855,30449]]}},{type:"Feature",id:"500110",properties:{name:"万盛区",cp:[106.908,28.9325],childNum:1},geometry:{type:"Polygon",coordinates:["@@VIV@@wVJ@InKVxXal@@U@U@KlUnwUW@kVU„KUmVkUa@I@KW@@bk@@mƒU@m@k@a@aƒIUxmJk@ƒwULƒwkKmVVX@VXV@xVLVVULmWXwWUU@@nUJVL@KV@UVULlxnL@VnUl¼@l@XVxVVUbn@WbkxUšlVnU@m"],encodeOffsets:[[109452,29779]]}},{type:"Feature",id:"500107",properties:{name:"九龙坡区",cp:[106.3586,29.4049],childNum:1},geometry:{type:"Polygon",coordinates:["@@XK‚L@Vš@XbV@lW@UV@@VXIV@U™VKlL@KnnJ@VV@VU@I„@@mVUVWUUmL@V¯LUK@UV@UU@a@U@yU@WLUK@X@KUVmL@ƒ@aXI@w@ammVk@WÛwm@UxVVVbVLUJVxVU„V@V@X@JUIVbm@@Vk@@VkL@lVLUJ@zWJ@X"],encodeOffsets:[[108799,30241]]}},{type:"Feature",id:"500106",properties:{name:"沙坪坝区",cp:[106.3696,29.6191],childNum:1},geometry:{type:"Polygon",coordinates:["@@Xºl„UVl@UbVXUV@xVJVzXJVUšL@VV@VKn@@Xl@XK@UmÝnKVbVakkVm@k„ƒUK@UmIm@LkKULVšU@WJ@UU@@VkXU@Wa™@@UKWL"],encodeOffsets:[[108799,30241]]}},{type:"Feature",id:"500108",properties:{name:"南岸区",cp:[106.6663,29.5367],childNum:1},geometry:{type:"Polygon",coordinates:["@@VV„JVL@bUVVnl`XIlwXJlw°nnl‚IXW@UÇĉk@WJkwkLƒ@WVkU@LU@U`W@UXUV@n"],encodeOffsets:[[109092,30241]]}},{type:"Feature",id:"500105",properties:{name:"江北区",cp:[106.8311,29.6191],childNum:1},geometry:{type:"Polygon",coordinates:["@@nLVU@wV@lV„@Xll„ÈKlU@L„@@bVKnx@I@JVaV@„x@Il@@Un@laVVn@mkUIm`k@WXJmk¯mkxWIkxWJk_UmVUUKƒ@UU™@ƒ„@l"],encodeOffsets:[[109013,30319]]}},{type:"Feature",id:"500104",properties:{name:"大渡口区",cp:[106.4905,29.4214],childNum:1},geometry:{type:"Polygon",coordinates:["@@k@@U@w„¥WKkVkImUmwa@b@xWJ@b@„nKVU@L@WVLXKV@@z@V@bVVU@@VVL°K@U"],encodeOffsets:[[109080,30190]]}},{type:"Feature",id:"500111",properties:{name:"双桥区",cp:[105.7874,29.4928],childNum:1},geometry:{type:"Polygon",coordinates:["@@WwUwU@kK@KmbU@@V@XlJ@znWlXV@XK"],encodeOffsets:[[108372,30235]]}},{type:"Feature",id:"500103",properties:{name:"渝中区",cp:[106.5344,29.5477],childNum:1},geometry:{type:"Polygon",coordinates:["@@VLš@VV„@VL@aUKƒIUUƒ@@JUVU@"],encodeOffsets:[[109036,30257]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/fu_jian_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"3507",properties:{name:"南平市",cp:[118.136,27.2845],childNum:10},geometry:{type:"Polygon",coordinates:["@@@knyƒk@ƒKU¥šwV@nkƒWƒzUmk@@lKUa@aVI@UƒKUamKUUVaUI‚@Xƒ@UV@K±IUVVlUbUbUL@KWUXmWk@KkXmmkŃKUƒ™a@amUƒbkUkKWUnwUƒÇwV™UUƒÝUKV£U™@ƒnKWwXLVKm¥@wUXkmWk@ƒ@wX@lU„@šyVImaXwVƒƒ@kŽƒnU@mbk@mlUXƒmU@mV@n@bnW@bUIWJ—ImVUKWbUK@nkKƒaU@W_VUUmWmL@UU@™bUWUL@V@bmVUz@`mUUVVbXL@V™L@lmLUxmVamXkW@xWbU„VbUxkU±@ÅUmmkLUbW@@`kLknVlV@lbXxlVUXVV™ŽU„U@UbWŽkIWVUUUJkI@llbUxVL@V™VƒUU°ULUmWXUV@VULWb@™xm@UaVLVKUa@ƒw@V›bkmVambUUm@@VkK@„@b„xlxX@‚„n¤@Xƒ@@lkLWV@Žn„V„kb@bWJXLWx@nkxmm™bXn@VWVUn@VnJ@bVXl@„™VJXnWbX`lL„UlJVI@Žœ@VXV@Vl@bn@@Æmn@VšxXU@mVIlxšVššnI„l@nVJ‚aXI@mlU@aXkVm°klmnVV_naš°@V@xܦXK„V‚nnUlVXbVK‚LXKV@naV@@VVl@@lXblXšWnLlbVK²nš@@‚VLUnlV@lƒXxô°‚V@UnaUUlKXLVUVVUbVVlUnJVX„@VW@an@lb„@nl@VU@anƒšUVW@kƒaUm@InVVKVU@kUW@Uam@km@kVa@a@™nwšU@WlI@mVI@WXaW_nƒ@™nƒlkkW@U‚¥@kV@Uw@wUƒ@@IXK‚¥VIn@nU@`@Xl@VV„LnašW‚bVaUwnU„@VIšKlV"],encodeOffsets:[[122119,28086]]}},{type:"Feature",id:"3504",properties:{name:"三明市",cp:[117.5317,26.3013],childNum:11},geometry:{type:"Polygon",coordinates:["@@lL@Un@VVna‚bnUlœa@U‚x@„VbULUKVbn@šw‚@XaVK@UVUXWVnVKV¯„VšU@UUKVwka@klJVIVVXUlJXVaV@VƒšUUVWkUWwkaU@UklmlK@_X@ValKnnÆV²@lVVwUaVƒXa@wlXnW‚bnUVwnK@kšK@UWKUaVUnV@_VynU@a@UVKVXšaV@@VnKnXVV‚UX`V@„blL@mVLXaVLnU˜JXIVJ@amX@a@mnUV@„nVWnkl@naV@„ml„@@KmKUam@UU@ƒ@UlKU™Vk™U™K@aVaUwV™U¥UIkJ@wmI@‚mbkwkVW@UXƒKULU`™IVKUa@LƒkkVmUU@WlULUWÅU@I@ƒWW™nU@@w@a@ƒUam_XyVIVWkkƒ@mwVKXUV@nw˜VXkWƒÅ™U@ƒaƒU¯KUnƒK@ƒ¯šmUƒLXŽVLnWVbVbUVm@Ub¯¼W@amƒ`kb™amLUUUƒ™aUXV`@x@XmJ@n@L@xkJUU@kU@mWm@kUUwUUVWl@VUkIƒy@kkaVUUm™IWVXbWxU@k„mVkK@nWVX¦WxU@@bkx@VU@WŽk@™kUbmJUUmkUW@_kKWKƒ@knV¤kIUKWLUbV‚@Wbk@@VWL@VkI@lUXVxUVU@@mWIƒV@a¯nUaƒaUV@„ƒJ™b@bÞ°VbUš@X™aUVmL@‚VXblŽnV„°˜n@Vnx„@VUUUlK@InJVb@„Vlnn@V™L@VWJU„x@XlJUVVVl@LUUUJ@Lƒ„@lUL°¦k˜V„VnV@„xV„„l@blLnlšLVaXll@šnVUn@‚xn@nml°‚X@lb"], +encodeOffsets:[[119858,27754]]}},{type:"Feature",id:"3508",properties:{name:"龙岩市",cp:[116.8066,25.2026],childNum:7},geometry:{type:"Polygon",coordinates:["@@ša„I@ƒVU„bVb°m@b„UXJ@nV@VUUwVW@klJ@UXK@Ul@Xa‚@UVaXKVLlJU£lm„@XLlL@`VXnlVVnIVašll@XV@@Ulw@aV@XwW¥XU@mlLnUlƒV@XwWaXUšJVnUVlb@l„zlJUVk@UXVVVxlVn@nXV@@lVVlI@w@K@mnI@W@wU_VWšbV„VVnKšbla„_n‚bX@°»Van@VUUaUamXUKW„K@a@Ukƒ@wWkXƒWW@wUU™Kw@_lyƒwUkU@@Uƒ@kamVmƒXašUVUka@Wk@»UUUVƒKkbWU™VUbk@mkƒxkƒƒKnIVUmW@kUKmXUmVaU@kU@m@KUWVkIWJ@ŽU@UI@wUUUa@KW»nU@mVkUmm@XwWU@ƒUUmL@ƒw@mnƒVUU@aWak@@amxU@UxULWVXbVLU`mbUImVU„ƒbn‚V@@bVn@bnVWxLmyUbƒIUKƒ@aƒVm™akbV‚UXW„UlKWbkV@„WLUlk@@nšbƒb@lkKmU@ƒUIWJkw¯UUVVxm@@XkbWx—›XKƒlUzWJkUUL@bmKkVƒ@@VUIUlWV@X„K@VkbWx°xUb@LUbk@@VWb@LXJ@VWXU@@bUVV„VVn@VVlLn„@l„@‚xk¦Vx@bVJXbƒn@JlnXxV@@„nJ@X@V@lmx„bUn@xVL@VVKlL@l„„nLVaVL@xkl@LƒxVl°š„X„WVX„Vl„œJWnxlJ"],encodeOffsets:[[119194,26657]]}},{type:"Feature",id:"3509",properties:{name:"宁德市",cp:[119.6521,26.9824],childNum:9},geometry:{type:"Polygon",coordinates:["@@@LVKVaVaUkVU²J@LVU„@@W‚VJUbVVnLVb„L@VUJ@bVbkL@Žl@Vn„y„XmlU@™xV¦„L@Ž„lmz@lnL@bVVšbVb@l„nšKVk„Vl¤@zXV@šl@XJVLVKnXVK‚VnU@wUm@šKUƒ@UlVlw@U@U@ƒUaUKlU@kXKlmXIWKXaVIVUVK@KU@@k„JVUnLVJUL@V‚IVa@VnLšKUnl`Vb„V„V@š‚Vbn@Vzn@lKnVlI„VVKUalkXJl@XXVWVLVUUmVU@Unm„£lK@Uk@WUXK@U@WVwVkšƒĠkĢÇ°aUÅUwmaţƒɱUÇa™w„±V¹XalKôx„@„UVaÜʓͿVóbÅLƒJm„¯Vk¦ƒŽk@mamXkKUƒUL›akbk@mV@LkJWb@Vk„mXk@UVmaUV@amLUKUamI@KUaU@WbU@UUUƒUIWJUkm@šƒw™Kk„VJm@kxǁVƒUK@mUVUkmlkkVm@amwƒLVWU@UbVLkšUbƒ@VƒmK@XaVWU_VJnwV@@kUmWakxƒ@kwWakIWxnbUJ™zƒ@kVW@@x@„XllnVW@xn¦ULWKXxmL@„VšU¤VL„ÞVVUšÈxV„mxXVlLlV„anV@bšbV„„LlÆnnlW@LXlWnXV"],encodeOffsets:[[121816,27816]]}},{type:"Feature",id:"3501",properties:{name:"福州市",cp:[119.4543,25.9222],childNum:9},geometry:{type:"Polygon",coordinates:["@@lxna@nJ@xlIVJV¦UšVxUb@bšLšVUlVškL@V@„VVn@Vb‚Ln‚@LU„lJXblx„@lwXbVn@lU@mxUIV`UXWb@‚nLU„„@Val™UKVaV@UX„Knx‚bn@lUkllnUVnV‚@VLU„È‚lwn@UIlƒšL„x‚™n@VlXIVJV„VVV@XaV@Vb@LnJVbVLnK@bVUnbVUl@nWlƒ@UXalI@KnUl@laœbVKV„lLnWnbl@„l¥°Unƒ„IÆKôa΀U„a@UUwÇWǓIUWUÅVkƨm@ƒ@£@KmLU¤ULˣJ™kUƒVǟUUķ@ĉVƒKUk@Ñ°wôǚç@īšé@Åţ¥mīÛkm¼Å@ƒVķVó°ō¦U°ƒn@bVJXVVL@bUŽƒakLmx@xmxXzW`XbWnXV@bWLÛ@™aƒ@ƒaXbWVkaÝwU@mlWKkLWWkLUKULW@kVmVUU݁UamV—¤›n@xUVUzkJV¦lJU„"],encodeOffsets:[[121253,26511]]}},{type:"Feature",id:"3506",properties:{name:"漳州市",cp:[117.5757,24.3732],childNum:10},geometry:{type:"Polygon",coordinates:["@@@bl@Xb@bVVUŽm„@n„x‚@nKVV@„XVWxn@VnUl@nmVX¼@LVbVV@xVJV@@XIlJXU‚V@Ln‚@lVV@UbVnnWVL@lnXUVmJ„Ll„„wnll@VašUXVla„LVUVV@¼Xl@lbUV™VWbn„nUlb„@@VV@„aVUšmlUašUny@kU@Wkk@WaUVk@@ammk@@U@UlU@aUa@wl@šmXLllnL‚U@anVnU@L@VVV@KlXnWVnVanUšw@w@wm›nÅ@wƒaUam@Uk„mUl@@a„a@U@¥škôK‚wȯ°w@ŻkwǕaK›ÑÛk@ĕōřċ£ĵƒUKW»kÅŻLU@Ulġw@¤Vz™VUbkKUbmLmlULU¼UxmbXl@bWVƒb@bUnV‚UšVbULU@@VkbVL@`U@WX@ŽXV@b°„@b¯š@¤@Xm@@b@`U„VVUL"],encodeOffsets:[[119712,24953]]}},{type:"Feature",id:"3505",properties:{name:"泉州市",cp:[118.3228,25.1147],childNum:9},geometry:{type:"Polygon",coordinates:["@@Vl„xkz@`‚xšLVV@xXXW„Xl@xl„@V@bnV°™@„„LVm°L„V„bV@ƚX„Wl—UmxU@WVULnx„@llUXUJWzn`Vb@„@b@xV@šmXX@„@JÆVVXVKXkV@nVlU„l@KVbULšJV_VK„LVWX@lUVƒkIU¥lIVyVU@wœm˜£nUVWU@aƒm@UmWw@UX@@am™VUn@@aUUlUVanaWUXWmUnkšK@VšUlVVUUwš@XLWWX™ma@knm‚bVb„VXbVL‚@XJlInlšL„w˜mXóšw@çV»ÇçŋaķƧóƅóKġ°nÅUķƑUÇW@—¯xÇ°öÆlV„n@llšaš@„Lšbƒ`™@™„VšXVƒVx@V@bULVJUk‚Ç@ƒ¼ƒXUKk@mmULkaWbk@ƒx@UkL@a@K@U@UmKmbU@kV@UmVUbUmmXkW@LUU@U@KmVmU@bVmKkkWK™nk@@xVb@bkV@V@Vl@nn@bl@VUXbl@XlV@@lmz™VVbkŽ™nUVƒb"],encodeOffsets:[[120398,25797]]}},{type:"Feature",id:"3503",properties:{name:"莆田市",cp:[119.0918,25.3455],childNum:2},geometry:{type:"Polygon",coordinates:["@@VbނVVnUlUX@VKVLlKXXlKXL‚‚nkV@ÞxlbXUWa„b„@šbÜ@XK@aWUXmWaX_Wynw@wnwlK„bV@aUKWUUI@a„mV¯Ŏ¥ô¯ĸU„UÆ@n»¯aƿé@ţ¯nĉĬÝK™óó@™ÑU¼@è™xWô—nƒx™KmkkJWI@UKWaƒUUaamn@lnbWšXXWK™@VxUVkU™V@U™LmlnVWXXVmbUbkVVV@bm@UVnš@bW@@VXx‚n@V„n@bV‚UX"],encodeOffsets:[[121388,26264]]}},{type:"Feature",id:"3502",properties:{name:"厦门市",cp:[118.1689,24.6478],childNum:1},geometry:{type:"Polygon",coordinates:["@@@VlUV@nanL@V@V@L@blK@V„wl@XalbVKnnl@VL„W„»È@lVUIVK@a@UUw„WUU™šƒš@„_™aƒK™@™bkkm@UƒkõŁxóL™l@¦@Vƒb@bk@VŽƒnVln@Vb„b@xmÆnœ@x@x™x"],encodeOffsets:[[120747,25465]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/gan_su_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"6209",properties:{name:"酒泉市",cp:[96.2622,40.4517],childNum:8},geometry:{type:"Polygon",coordinates:["@@ÇnÅaĉ@ƒU¯¥›UŹ‚ƒ£™WUýUU±JkkUw‚yÞIČxĊĕĊ¯š¥ÆUkţ™UÅÓ±¼™IUx¯UƒÒƑ‚ݐŰƒKÝnğ°ÅU@Žƒ@Vn@þš¼¯šWnŎ°XLWlnVnbWnƒVXxmbƒa—bóUƒlǕUUa™IUmlU™ƒš¥™kƒ¥ĉwkkƒÝɛa@¯™™U¯°mVƒkVnKlƒōÑÇÑU@kl™UġŽkUŻnUW™@š¯ƒk»šmWV£UKnUƒmUw‚w@ƒUIVaX™šwm»Èmmwn¯ċ™¯LĉŽUƒJUalka±Va@U‚k@ƒÛф¯WmnUaɝ¤Ûmƒn¯m±x@wóxÛLġÒUx¯VƒÈ™JUbóz݃ÇKĉ¯ōlÝUŎWl¯nťbÝ@¯ǩLġmV@ƯĢkÆm™ĊkVťLɃmÝXó°@„ĢbVŽóVݦɱ@Ƨaġ„UV„ĠÇÈV¼UVţwmbJÇwˋa™XmǯKkkmŽƒbXšm¼V¼ǬŚ²¤ôŰÆƴô̐ŤǪnɆӨ¼ɆLÆłUĊšxŎƞȘǔˎǬǪnƨŮǬö°»šġ„„ÞÜÆĸÒĊ„ǀbƾèôÈ@¼¯þŤĸƧ°VĀ¯b@lÈĊ‚šʠń̐„ȘKǀŽֲॗţÿǕý@ʊǓƨóÆÑǖŃôw@΋ʈƆÅÈVVĊV„óĊÅ@ÞƒĬV@Þīš@°Ž„V@ĸĢƒ°XτƜĠ@ÈaÜ¥Őƅ‚™nğóĕVġUůƿŋ—ĕƒa±V—UťÇğÑ"],encodeOffsets:[[101892,40821]]}},{type:"Feature",id:"6207",properties:{name:"张掖市",cp:[99.7998,38.7433],childNum:9},geometry:{type:"Polygon",coordinates:["@@ÈÒŎÒk„mLUŽlŽU„¯nV°šš@°ɜb„ÞĠaÈ»ĸl‚š„LVUÈ@Ċ@ýUm„@@ÆVĠ¯Þm„LƯޏƒ„Ñ°VVwšJ²»ÆԚVlŤÅV™¦ĉ°ĉĖċwÝJzVxll²IVVVþšX„¤źœV°¦„VĊ@ÆbÈmǔLĸĠ¯Ģaô¯ĸmÆÛUƒlÇĸk°XyĊUǔV„ǩnmV»ƒa@ýnK°n@l¥@»ż„Ċ¤m皃@£ČU@mƒmVkÞUƐ±²¹°‚ĠwÅƑŃU¯™›V¯aÈŁšƒÇ»™ġn_°xŎKlxœklx„@Þw‚„„@Æm²b‚DzLlkšWXať¯ĊaœÑšK±w@wƒUÅçV±Uk™@@„¯š¯xƒU™±±UU°ōxVxÅÔō°ó¯UÝ¦óbÝþƒ@ĉÈóUV‚Ux„„@VŽUVÝwÅÈǎóVkk¯JǐkmmL@„™KÇx@bkš™@U°ķ²ó`ƒš™šmn¯°ƒUwlÅkUƒ`™¦ɛô™Žķz@ŽÅnÇ°U¼¯KmVk²ƒJƒ¼ƏÞķôš¤ULƒ@mnğ`™šÇnUxÇ@Ûÿ™U@ƒƒkŻŽ@x@móJkŃ¥VŹĉóÒĉlċ°ķ„Uƽ܃@›x"],encodeOffsets:[[99720,40090]]}},{type:"Feature",id:"6230",properties:{name:"甘南藏族自治州",cp:[102.9199,34.6893],childNum:9},geometry:{type:"Polygon",coordinates:["@@ލš™nKlnšwX¥WÝXk˜xÞUnƒ°aĊVnUUKlÞĶWXnĠ¥ô»„™@nmVL@¤°™Vz„JšanU@aÆwna@k›ƒU¯šyX_›aĉb™ƒ„wƒéXkWwÅaš¯V¥mƒ¯UƒƒI@ƒš@„mšb°aÈçšUš¥@»‚knwɜƇ°I°ÑÈmVU™¯Xa@w‚W@wšV¯Č¥l¯Uwnm@k˜aUaóKkk@™Ça™b@ŽÒWa¯IÇxÛam¼™VUƒxÒl‚@zÝÒ¯bÝaĉVĉwDŽW›zJ™mJn²mܯUƒ¯ĉ@ġ¤Åb@²nšmlƒ@@Ž„„U„ƒLVxšV™„U¼Ålma™b@ƒ°™l@WIUƒ¯@mƒ™@™™ó„™„@U›zţyƒXÇU™ÇVUUVLkbWakVWmUbkkƒKUÆ»nƒ°Knk@aƒUVmšnk»l¯Ģ›lw@_kKVU@ƒnaƒ@lUk@¯¥mV@kmbW™b¯Åõa@mkU@kƒÇŽkU@›`@™óó—bl¼Uxƒn„¼šlVȄx@blVkVVnƒ`XÈġÈ@ǃK£ÝJmUUnUĖmlU„mKUn™VÅaUw›Uĉ`¯n¯wW¼nxVŽ™š@bĉnƒ‚kIċŘkXUŽ±Ò™xšÈ@ŽX°`l„œV˜IȯĊV„ƒšVVan@VašUVażVmšblkÈW„ƒWIXa„alL@wVb„„V„¦lL@lĠ™n҄U‚nk‚šL@ÆÞkšÞšK‚bñþW¦Û„ċVƒ„ULUºkÈlŎUxÆxÞUUxšÒ‚x„@XbšL@lÆ@„ÒlXVln@„bm¼ƒJ@„Ån„šƒx@bnšĠm„xVXmbÈè@ŽĊ£ČW˜w"],encodeOffsets:[[105210,36349]]}},{type:"Feature",id:"6206",properties:{name:"武威市",cp:[103.0188,38.1061],childNum:4},geometry:{type:"Polygon",coordinates:["@@±¯¥@klwU»ƒƒÞÝmwKm¯™™ç@™kVÇUL¯lVUKġ„ġm@a@U„@X£°l°LŎÇ@aōVÝw™ÔƒKUŽÅš„WJ¯lm@ÛVWa™@klĉUmaƒLUanaƒ™ƒk¯J„™™±KkXóÜÅxƒ²Ç‚@„„nUÒĊb°@™ÆkL™Ž™XÇÆ@xÝn—xWxţ„¯¤ƒI@Æn„ƒVV„VlU²Æè„V@x²x™L›ÒĉbŦ°Wb™Xklބš@l¤šXĊ`„wl@ĢÈŎm@bšnV‚Ubƒ„@șÆÛLƒèǚUÒŦlĸ™`°ĮʟÆǓbĉôϚĊƚĢnŤé΀ÑĸĀĊ¦„@@l°lœ¦Ȯ¦ɆÞĊKŤ™ĵĸů„»mŁyġ™ķŭ@Çɱȭ¯mƧUĊķnŁŻ»UaU™˜ƛɞÝƨů"],encodeOffsets:[[106336,38543]]}},{type:"Feature",id:"6212",properties:{name:"陇南市",cp:[105.304,33.5632],childNum:9},geometry:{type:"Polygon",coordinates:["@@šÈÞ@l`UmVƒ¼œŽ‚@nnÆwVlnVVa„LVƒÈ_‚ÿރ@n„a„xÆ@„lš_š@VxnK@llLnxmÈŎJnbUxšI°Žl@n¦‚lÈIlmX¥„k°@šk‚J„k²é˜@klaUaVaU@@ÝnIWnmnx‚k„ºÞ„„aV™°„V@nw‚KšxôbÞ£šVšU„bšþšLn»mƒVw„IšJ°Ž@„nb@°°I„ġUkÇKVƒ™™@ů»lƒ„Lnmƒ£@anK@Ñ܍n@»mL@£™yk„UUmbUÞÝ@kyÇbó»™XUxƒWVzb±mÝbXaƒwUamL¯»@wUKVwm¯ĵJ°ÅUWVk„KVk°wÈVšVуlUšƒ¥škmVamknƒUw¯¯ƒbċ¥ÅKƒk™Kk„™VċVk£kKVw‚Ñ„a@kóyÛ¯ÇVk™ów›š—Xō¥Ç¼ów™Ž¯U±‚k„ƒ@x›IĉÒÅVmÈnšÜ@n°„bUbÝV‚ŽUnnJ¯Į@‚m¦nV܃@„„L°JXb‚Ñ@šaÈb@šllôLVb—b@lmnVxk°ċ¦U°™Ž@xX@xWbš°UVÇn¯Ò¯Jɛƈmxl@¼"],encodeOffsets:[[106527,34943]]}},{type:"Feature",id:"6210",properties:{name:"庆阳市",cp:[107.5342,36.2],childNum:8},geometry:{type:"Polygon",coordinates:["@@kw‚ĉ—»VamƒƒV¯wƒIóVkl¯™Km™Vō¯ÝWkL@bÝKō¦@Ž™„@š™Lx›@b@l™a@km@@l¯nm@UaÅ@ƒ„óWUXm¥™nƒw`@UUxķôÇ°ğ¦@„VJš_n‚‚IVŽnalxkX„JWn¯šnVƒLšxl¤nnVbklVX@xnxmV@bUK@nm@@xƒV—°±aÅnƒŽkUWnUaƒx@m™n@ƒ¯LƒššmUĀlU@lV@blLUblxklkIÇx¯°‚UXbšaVŽUnšV@°‚LUlnbšX@`°nVmbnÆmV‚kLmK™¦UŽ@X„y@kl@U„°K@¼XbW„ƒš@b„WnLVa„VšƒVz@xlVČ¥lbUxލlV„U@nÆWôn²™VJlU„Ƨ„LnmÜLXa˜n@mœw@wlUlV²mšblwšVȃlLލ„±@lVnUlxnkma@mškšJ@kXV‚U@mn@š¼VXUƒVƒlLnmVbôaVnWV»ÈUl°È¯ÆIn›ÆU@kk»mKkÆġk¯@»mƒk—¯@óÇlÇ@—Vykkl™Uml¯Þ™@w"],encodeOffsets:[[111229,36383]]}},{type:"Feature",id:"6204",properties:{name:"白银市",cp:[104.8645,36.5076],childNum:6},geometry:{type:"Polygon",coordinates:["@@VKUȚl@šè°šnŽ‚LnxÝބ„V¼kx@l‚¦²°ĊóĠ„™Ċ»š@ÈxšaĊxlwÈVŤa@¯²aÇ£ƒJk£lƒnUÞ@°šô™@y„wl»lIX¥Ǫnw@ÑÞWla„ÅlL@ƒUwĉakƒl@ƒš¯mwna°J„V¯nUVÓÞÑm£²óWaUƒÇ@óÝUçV»ÈkkW@¯‚xV@XlK@wX@Vmm_@wÈݙKU¯ÇwVwÅK¯VƒkƒJ™™™XkWVaƒImŽ¯Uk„ÇlVšœĀV°mxóšk„@¼ó„WxĉÜU@Ub‚zÛJÇk@‚ÆnVlԙ@kŽ„x™ô@ĬWL¯ƒƒK@aÛImm™@ƒIUaƒ@™™UŽÇêU¤VÒÇx¯ÒV„šš™lk@Wbĉ¦UbkWV_‚y¯Lƒaó„kŽ@b@nmbkx„°"],encodeOffsets:[[106077,37885]]}},{type:"Feature",id:"6211",properties:{name:"定西市",cp:[104.5569,35.0848],childNum:7},geometry:{type:"Polygon",coordinates:["@@„a‚V²wVJV_@„LlanÅllŦçÜӚ_šlnƒWaôk„xUš„bmV@È°lèšnk°l¦„`@nnL‚@ÈlÜIyVaV@ĊÛXwôƒ@»lƒô™nwU¯›ÿU™Èklƒ°Vn„JUblXšWšš„I„l°U„ƒVƒš—@aVVVmnL@„lƒ„UUw‚mkƒš£„bV¥VUVwۂƒlaÇÝރmk£ƒLUy¯L@WlkKW_XaWƒ—mƒ„ġU@a™k™‚ƒakXkmVwmŹVƒU™b™WƒónmwnWW£„KÈnV¥ƒ¥„ƒÆ_k™lW„bU¯„V°aôbnaVwmaōInÇmwkK@kmLUw™@™`ƒkÅ@ƒwƒb@m݄ĀÇ`U„ƒKUbmUUkÅxmm@›„»nUVk_Ý@™Ç™¦™VÇè¯b™aƒn™@@„„JV„°Žn„U¦™°ÆbXxWl„êƒxš„ĊaœbW`™zV°œ„@lmbÅx@bmV™bƒI™`™¦@ÒUVUI@ƃL@bš¼@ššŽ@„šlmxnL„°ULƒŽƒÞğޛ°kLUŽƒL™°™xVŽ„n„KVƒl@šzX@"],encodeOffsets:[[106122,36794]]}},{type:"Feature",id:"6205",properties:{name:"天水市",cp:[105.6445,34.6289],childNum:6},geometry:{type:"Polygon",coordinates:["@@UyȍVƒVUnn@ƒVU„`UblzšJnk‚@Vb„KU„°l„wš„„W°„nkVŽ‚UÈlš£°V@n¥šV„kl™kU˜±U„ƒn™ƒlw¯UkwmKUlmkUmnkym@ō@U„mWÈU°l°anlJškUKlU„¯Èm@kmWV»kkÝLUWUx±b™@¯ma@ƒ¯™IƒJUxn„m¼™K™ýƒa™V™Uݤóa™wLmxU@¯ƒUšƒb݃ƒ¹lmwmnXŽmJ@ÞV@UbVbkblŽ—@±êƒlI™l¯@ƒlW¦knÇJkm¥k@¯™Jmbóa¯bƒUV°ƒakXlšÅ`ƒ„„¦U¦ÇmƒLX¤mXnxm‚„ôšXša„VźUnŽUxlnlW„bššl@bĢV„ƒ˜nX„WbX`lLXk@Ž°KVz„Kl¤„nÞ݂Èkb„‚܁"],encodeOffsets:[[108180,35984]]}},{type:"Feature",id:"6201",properties:{name:"兰州市",cp:[103.5901,36.3043],childNum:5},geometry:{type:"MultiPolygon",coordinates:[["@@lW²LššƒŽ°I„l„šmbVb„KnbĊVlkš@XbÜU@Žkn°‚XIƒÆ™V„LšÓÞxŎUlôƒ„b°KzU`lXVaĊ¥Xal@šk™™Uƒ°ÑÈwUтV£ÈéVšš„@Vb„Jš@nnÜJ@b„L°„XK@īšóƒwlš@kÓmUÅmK@mƒ_k¥l¯™mkçǯ@nUƒaV™ƒwólXbm„™k™`ÛÔťèkkmÆkbƒK@U`UI±xUƒbWlX„mbVbÅÒólkƒƒIWJkšƒ@ƒz—KŻ¼™@™xUx󎃄¯LWb@ŽÅ҄„±¦U`nbťĀUšVb„LšŽ„U"],["@@ƒ¯lwna@mōȯK¯kW¤ƒ@@V@bĢnĢƒVLU‚°k"]],encodeOffsets:[[[105188,37649]],[[106077,37885]]]}},{type:"Feature",id:"6208",properties:{name:"平凉市",cp:[107.0728,35.321],childNum:7},geometry:{type:"Polygon",coordinates:["@@ÆLUxÈxV°šLÇÞ@xn`Ü@X@nĊŽÆwnJmwUx‚aUkšw@V@w„aVmlLXÝl@X‚VĢmV°@nl@UUUWK@w„ÿVI²Òlmš@nÝĊýVV@nšJ°„„šUłm@kV¼nK›ĢȤôK„blnKllVk²aĠ¥È¯ĸóVw@V‚_„xšmn¦VWôX„ƒÆ@Vbn@°m@kn@@lšb@k‚aœ@‚wšK@™šƒ@UlKVaƒWX™W²¹lӄw@_°›n@@_lKōķW™@ŽmLUWƒn™»Û@›l_Ç`ƒÛmm°ÅbWb@š—VWbƒUUKDŽÅaġlmkUġlƒ»—Lƒl™Um¦@Ž¯U™¤ÇkVUml¯ƒƒX™ƒƒx¯kVƒƒLUa@ml™IkyVaƒ_UV@„mmUVU„ÇŽVzUxUVU¦ƒa™¤l„nVxƒVk„@ƒmKUnUU@b™˜U„ƒ„","@@@Žż@™mlkƒġk"],encodeOffsets:[[107877,36338],[108439,36265]]}},{type:"Feature",id:"6229",properties:{name:"临夏回族自治州",cp:[103.2715,35.5737],childNum:8},geometry:{type:"Polygon",coordinates:["@@š@ż»˜L„y„@l™XI„Jl„ôkÆÑUanaWƒXkW@™yk@U„ƒLƒmUšwš¯„KVlKœ¯Ġ݄݄VKƒ¯mKnw™k@ƒ™@™™»@a„K@ÅVJVU@њ¥š_Uy¯š@£UKmn@‚ƒšó¼ğ¦WmĵXݎkŽVLmVĉU¯bm„ÝV—wWlXÞW¦™xkmmL™šÝŽœ„±U@Vގ™š@„ÅÈW°X„ܼƨyUĮnŽWŽnXÝxUx°lVXJlôV"],encodeOffsets:[[105548,37075]]}},{type:"Feature",id:"6203",properties:{name:"金昌市",cp:[102.074,38.5126],childNum:2},geometry:{type:"Polygon",coordinates:["@@šĢȼ™„Çł°bœU°šV‚ƒń‚ÆǖŰnšÆ„ōĬǔaʠůĭš_kķÆ¥VÑș„çÜKšÅ@DŽƒVaU™m@aōnġÇk@ƒxĉ_™Wk£™@݃±KÈ±aÅnƒ@ƒÝxƒ@kw›lkwōL¯wm`"],encodeOffsets:[[103849,38970]]}},{type:"Feature",id:"6202",properties:{name:"嘉峪关市",cp:[98.1738,39.8035],childNum:1},geometry:{type:"Polygon",coordinates:["@@llĊx„¦šl™¦š„kVVnšJVbǖV„kôV˜a„bnaWw„UXmmamUXkWKō¯Xm°™™»ĉÇ@UVƒK™ķkǼğb"],encodeOffsets:[[100182,40664]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/guang_dong_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"4418",properties:{name:"清远市",cp:[112.9175,24.3292],childNum:8},geometry:{type:"Polygon",coordinates:["@@lǯkÿƒaV¯™VaÈU„¥ÆDŽIlxšmnb‚Uœxl™„Uôl°kš„„Wl„š@ô™VwUanUl@„xVkšaX¥‚kU»„aš¯±@kka@ƒUwmUkwƒJk™˜„±k@ƒ™™L@ÝWUwV݃—xÇU¯ŽÇX@m™Åƒ@@yĉ£VmUwȗ»ÇšUn„lUnWU¯`Ukƒ@@„™x„Ž@bÇxX¼ƒVVš¯LšĀk‚ÝLƒ„¯@VŽƒĀ¯lnĊW¦kVÇôkUDŽUK@ţ™U@a™™ó܃UU»ƒ@™¦k@Vx„KVb„n‚š@„Æ™„l„@xšƒbWšnlU„lxÈlV„È°Æ„@¼™„@x„šWxœŎ‚V„šK°„š¥ššnƒÆkŎ@ÈÑm™„K@¥šk@™ô@„nôV"],encodeOffsets:[[115707,25527]]}},{type:"Feature",id:"4402",properties:{name:"韶关市",cp:[113.7964,24.7028],childNum:8},geometry:{type:"Polygon",coordinates:["@@W™Xk±Ñ@ƒUw™mUwĉwlmn@Æwn£mkIš¥ÇÅ@¥šaƒón£nWWwš£V`Þ@šnVml@xô¼„IV¥ƒkUmkamUkVWwÛ»móƒ£UVÅKmn@x™@kbmm¯a™Xka›VĉaUb݃ƒ²—‚lš„IlxnVVx@„lb@l²™°ƒbV¼lW¦™bUlƒwk@mVVbUxóš™@kƒƒX™ƒ¯lókƒVkš›wVma™nkwƒJÅȃ¦ÇVUbšŽU°„blĀ°ŽkÈ@x™¦Æܙ°@„°„¦óa™VUôlUlbXl@nÜV„„nKlŽnIVÞ°Wš„°U@bnm@¥šIVƒ²Ulƒ°VnalzXyl_Vyƒ¦lƒœLlxš„@ŽÞbšKm„knVWanwƒÑVwČº˜@n_ÞV„aVŽÜIœl@„˜KȚ„VJ@aš£È@˜™@km™„aV¯W@_ƒa¯KmbkÇkLmwƒ@Å¥"],encodeOffsets:[[117147,25549]]}},{type:"Feature",id:"4408",properties:{name:"湛江市",cp:[110.3577,20.9894],childNum:6},geometry:{type:"Polygon",coordinates:["@@@ƒkXƒ™@a„UUċlk„Jƒk„™@wVJXUWk°W@nKnwlUlš²ƒ„blU@‚lI„l@„XbW„šxnm@lW@w„wU‚JX¯VU°`ŎóˋkÝÝkÅ@ÇmğÈřmw™aĵV›xUہ»°™ĠǷnýmóX¥ɅĵҏÇ@°²ĊUĖ±ĮU¤Ç°™Ā¯ɐnżUĊĊĬV@脎@ԃÒU¼l¤nƒĠb„êVĠ°Èy„zVaV‚nUÆL„ašbVl„wÆ@"],encodeOffsets:[[113040,22416]]}},{type:"Feature",id:"4414",properties:{name:"梅州市",cp:[116.1255,24.1534],childNum:8},geometry:{type:"Polygon",coordinates:["@@„‚nԚlW¼x‚¦@lœVl™lLkè„a@zš¤ƒĖ„¼UxlnUKUbÝlU¼lb@„Vx„V„klJÈwV¯š@ĠlÛĖšnƒbkšÆźÞƒUÈôklmšL„¥‚LœW˜„„™nKUkVa°V„x@IVV@x°bUk„a™a@mV@„@y„w‚L„ÑUwVUšV„‚„U‚bÞVVann‚@XwÇÿš¯²aVamkXaÆ»@»nw@¥›UXaƒkbWa¯KUw@¥m@kwmLU»UU™J@kmU@UUWUƒ@ƒyƒanwmçÛl¯ƒŽ¯UƒmKUmƒwVkmÝXbW@XWÝbƒk¯@±‚w@»U@W¯Å@ƒÇ¥UƒU@ƒƒ™IU™ƒakJƒĀ„ꃰšþƒXkamŽ@Žƒ_J°m‚@X"],encodeOffsets:[[118125,24419]]}},{type:"Feature",id:"4416",properties:{name:"河源市",cp:[114.917,23.9722],childNum:6},geometry:{type:"Polygon",coordinates:["@@°VlmX¹laĢÒlm„@„„šVš£‚‚@¦Ģklynn¼lW°z„W„„°VbÈV@lÆbnn‚JškX„šVÆašÅ„W@™ƒUUw@ƒkaV»ÞkVaVLkmVwƒ»„ĕ™£@yƒblçkKkš›U@k¥‚wX»™kmӃ@Wn¯‚I„`@nlb„W™ý„¯ƒé„ÿlI@™XUmWUwƒ@@UJU„Ç„mKUV@x™„ţk¯¯LWƒƒnUxK@ű»Vwa¯š@¤WX@ŽÛ¦@¤ÇIȼWxXŽƒ@Wx—w›ŽUnVbÅèmVa±²UWl@Žk„lȄ¤nôܼXxlUnVlbVn„lU¦ƒJó»@wnkmU™‚Ý@U_™¤XxmXm¤„ô™b@¦Èƙ¦lJn"],encodeOffsets:[[117057,25167]]}},{type:"Feature",id:"4412",properties:{name:"肇庆市",cp:[112.1265,23.5822],childNum:7},geometry:{type:"Polygon",coordinates:["@@l@š¥„@V¼„Vôۚš@bšV@ŤVLȃlVÈólUX¥mĉ°k„ÿU°@„ƒÞKl™ÿ°KU™„UW»Èw@aƒšw@ƒ„@nm@w›£kÓVUVn„Kš™k¥™£Vamƒ@nkKkbÆǫma—kmLU¥™UmƒÛwmVU™mUƒJ—ÇaUxÇIn`mb@Þ¯b@„nJ@nl„U‚V„lVU„L›W¯—Û`Ç_¯`mš¯I™bĉWċzx±J™xš¯ÆUƒƒ_k@™šƒJ@Umb„šXôlLš˜n¦@¼ĊxlUXŽ˜xUbL‚Ġ„UnVĊwlšUš„b@lW„X„‚m²˜@ÞWxXš‚Unb"],encodeOffsets:[[114627,24818]]}},{type:"Feature",id:"4413",properties:{name:"惠州市",cp:[114.6204,23.1647],childNum:4},geometry:{type:"Polygon",coordinates:["@@lbšW°bnnlaš@@wnmÆLVUkÇlƒ@Xk‚V²±‚bnUÆçUaVmœ˜xXw„@WXwÇ»ÈJ@£Ü¥@XW@£°™‚bUx²¼@ƂLVw„mX„°K°Ťlšƒ@wVUnLȃVƒVIky±wkƒKU¯ƒÅkƒ™XġÑۃlwUwlm@m„nKWašÅm›¯óÇmğb¯alĉUwķbmb@lÞÒVn—šmĀŹ@VŽƒbVŽUnmakLm`@xĉkklVÔVJVn—lV„UnmJmaLUbl‚™zmŽkL™a™‚ō@@zš‚V¦UŽV²kJ„nÜU@˜VXUŽL@„lJƒL@bݤUnVŽ—b@xVnlK²„Vx°V„xlI„lkVl²k¤@n"],encodeOffsets:[[116776,24492]]}},{type:"Feature",id:"4409",properties:{name:"茂名市",cp:[111.0059,22.0221],childNum:5},geometry:{type:"Polygon",coordinates:["@@‚LnÇlk„KnkÆL„ƒUm™ÈxlUœJló°n@ššanŽš„„a@ƒ˜@X_@mÝóóU@a™aU¯mL¯ƒƒkV¯™ÇVwkw@V±Ŏ£@™™@šalw±Vk@m„Åm¯™ÿŃƧIÇ`ōô¯_UVW°IV‚ƒx@xkX@Žmn™wXƒWa@ƒƒkkJ@kVƒa±„k™kVmxmL@‚¯XXlWVUI@xƒš„lƒIklVȃV@b„šlW@„@nUxVblVxkôlx™n„‚y„šnIƻư„aXwlK„bVnƒŽXb‚L„¤„k‚L—èƒVV¼ƒŽ²IlĠVX„ynz°KVx°@VlœLlblKœš"],encodeOffsets:[[113761,23237]]}},{type:"Feature",id:"4407",properties:{name:"江门市",cp:[112.6318,22.1484],childNum:5},geometry:{type:"Polygon",coordinates:["@@lUXx°JWnnƚXVš„W„X@„šºVLV¯nU‚Vnb™ô„x‚aXmW™XIšŽUb°xlK„l¯œK˜xXÞ°ŽšXÈ¥Ü@„ĉޏU™‚çš»nóƒVma—x‚¯UÅU¥Ý¯@ƒƒç@ș@çĉÅUmU籃ĉKÝxÝ_ÅJƒk¯»ó¯nmèkǀšŽWxœ¼mnUÜġ°@¦@ƒxƒLkŽÇaVnUxV„™šVlnIlbnÆÆKX¦"],encodeOffsets:[[114852,22928]]}},{type:"Feature",id:"4417",properties:{name:"阳江市",cp:[111.8298,22.0715],childNum:4},geometry:{type:"Polygon",coordinates:["@@°„nKV°šb@bôVÞô@n„VlÒôÆUnlnn@lmkmVkƒaÈkÆƄ™k¥‚ÅÞ»ÆKXkW¥ÅLmÅkamJUkš™UƒVwUmÈbl„K„w‚@@¥Ģ¯VÛnm›»Xw™lƿ™@kbW™—aʵ@óL›l¯ƽ@™ƒƒLn°ƒÆ@nUl‚²kx™b@‚š@šō¤U²@ŽlxUxšÈU°lŽ„"],encodeOffsets:[[114053,22782]]}},{type:"Feature",id:"4453",properties:{name:"云浮市",cp:[111.7859,22.8516],childNum:5},geometry:{type:"Polygon",coordinates:["@@@V„Iš™l@„`V„°Å™šw²I‚wČyĊXša°Jn™°_È`Ü_°˜œX‚KVƒkUUƒVkƒ@mmI@ƒ°a@Ýnam_ÈJVwlĉX@„šlUšómaUmVU°UK™¹@ƒƒWƒXU™™WmÅXm¯IWwkVWlÅLݼÆl¦ƒšÅÅÇl„bUllnknm@kmVmóÅkуUW`—@@„ƒb™ƒm™b@™¯mkô›IkVÇwnš„VƒÅKmlƒLklmȁKƒšVĊK°²„`n˜¤n„U„bWl„xVx™LUx@°nXm`VklVxmnnx"],encodeOffsets:[[114053,23873]]}},{type:"Feature",id:"4401",properties:{name:"广州市",cp:[113.5107,23.2196],childNum:13},geometry:{type:"Polygon",coordinates:["@@Ș¼VxUnĊ¤@z„@šÆ@nÈW°ÈV˜w„ŽUÞVxÞX@ŽšK„šl@ބVaĊbœU@ml£k±lUƒkkJƒw¯UUw±ƒkLUm@w˜aUVmÞ£@a„KkI@ƒ‚KVUW@—ÛVƒmlIU±VU¥™@yğzƧǃƒšƽĠřšÅnī±m@ƒ²¯lƒ°@nÝÆóUll@XnÝVU¦mVV°—„V¼™Jƒn„b@°mbn„ƒ‚@²¯‚¯wVwƒ@@nmxX¤¯L@ŽVLU„m@@l"],encodeOffsets:[[115673,24019]]}},{type:"Feature",id:"4415",properties:{name:"汕尾市",cp:[115.5762,23.0438],childNum:4},geometry:{type:"Polygon",coordinates:["@@@‚„@VxnXWV@š„bVššJ„„V@ÞÅU¥Ċxš£UWU‚wÅUU¥WVUkĊÇnkV`°LV™„wƒƒnU@™„ƒlbĊ¯„Vnalšš@@çkUÝ¥ġaó¯ÅaÅLŻÆUýmy¯ó@ĉÆó„ȯw™ÆXbmLƒ‚@nknVxkx܄ĢҚW„Æl„V°„Ll‚²xlz"],encodeOffsets:[[118193,23806]]}},{type:"Feature",id:"4452",properties:{name:"揭阳市",cp:[116.1255,23.313],childNum:5},geometry:{type:"Polygon",coordinates:["@@V„Ȧ„Æ@X°V@@¼‚x²°@„lÞaWXX@‚aÞWlnUŽ„xVnnL„‚°V„@k‚mĢl@„ak™@mlk°aXƒ±„nwm±™²¯JV²@ƒwW˜—_mƒa„V»ƒU@m¯ĉUф™šJl™„ašbVn„lĸLlƅÛDZwÝ@ĉxó@è™@k™mbƒUĉ°kaƒ„@šmV„„ƒxUš¯KU_mlĉÈVlXUV¦ÆVxVŽVX™¤ĉwV¦ÝÆ"],encodeOffsets:[[118384,24036]]}},{type:"Feature",id:"4404",properties:{name:"珠海市",cp:[113.7305,22.1155],childNum:1},geometry:{type:"Polygon",coordinates:["@@„è@„Þ°V¦VƁ°˜wnb„UÆ»nçƏ@nxܤ²llU°VnÈJސ°UôéšķUklƒô£VVˌKÞV°£n¥ƒ£ȗ™Ýy¯¯mÅkw¯bÇĔğ@Ýn¯ĊƒVğōŁŻƒķJ@Ț","@@X¯kmèVbnJ‚™"],encodeOffsets:[[115774,22602],[116325,22697]]}},{type:"Feature",id:"4406",properties:{name:"佛山市",cp:[112.8955,23.1097],childNum:1},geometry:{type:"Polygon",coordinates:["@@Èb˜Ž„InVVšnUÜxn„šVV¦nK˜lnbÅǬlalL@mn„Ubš¤l¦™šƒLUmUVlԜ¤@xmnVl°_XVVmƒkVmș@kn@VƒUK@°KW£nw@m„@Ux°x°@±„mƒna@¯ƒa„mšIU»˜ƒU¯nUV¥ÞUWmk@Vk¯™Ukn›ÑWݐƒĊÛ@Ǧ™W¯Wݗw›Lk°ƒkL¯wVa™WJXšWnbƒwkVƒ™W@kĊ"],encodeOffsets:[[115088,23316]]}},{type:"Feature",id:"4451",properties:{name:"潮州市",cp:[116.7847,23.8293],childNum:3},geometry:{type:"Polygon",coordinates:["@@°ŽÜknèmx„b„z„@V‚VX@VnV@lšIVVV¼nKlxn@@¦Vx°LXbla„ŽWbœV°£¯™W@nW@™‚aUñVœwWš»@¥ŤÅUÝǓÝóV@ńǎkUVmƒIUwÅVWÇX¹›—@W„¯bkl@nlšƒb@‚kġŽn@l"],encodeOffsets:[[119161,24306]]}},{type:"Feature",id:"4405",properties:{name:"汕头市",cp:[117.1692,23.3405],childNum:2},geometry:{type:"Polygon",coordinates:["@@‚@U±°Iš±n²mx²ƒ˜@œWºXÈÆUVx„JUnlVȍ@ŃôUǔÞVçn»VyĢÛVm@»kaÝUǼóšÛÈķKċ¥X„¥Wwğk™ƒ¯@ƒwķKƒkUm™aƒbkš™IƒšVÒ°Ċ@n„VU¼ƒ‚„bn˜`X—„x"],encodeOffsets:[[119251,24059]]}},{type:"Feature",id:"4403",properties:{name:"深圳市",cp:[114.5435,22.5439],childNum:1},geometry:{type:"Polygon",coordinates:["@@ÞLš„@xšbV„šVšK°™X°Kô¥Vw@anU„胐š‚lkĊl@wn_lKnbVmU„aUź@nÿ˜™UmÝѯUƒbk„@ÆkxŻ@™aÇX—wƒJƒƒ¯LķÝUĕ™ó™ĸóêWº@b²nmĬ™Æ"],encodeOffsets:[[116404,23265]]}},{type:"Feature",id:"4419",properties:{name:"东莞市",cp:[113.8953,22.901],childNum:1},geometry:{type:"Polygon",coordinates:["@@Ŏ@ššblKnšykVa‚KnbnIVmUƒ˜kUmUIUә„ƒçmV@bUxó¦¯LW‚¯š™L™UUƒ™a@w™ƒÝKğŚ™ƾ„„ƨÈĠy"],encodeOffsets:[[116573,23670]]}},{type:"Feature",id:"4420",properties:{name:"中山市",cp:[113.4229,22.478],childNum:1},geometry:{type:"Polygon",coordinates:["@@‚XœÒlmšV°ôÞÅ@m„¯°k„±‚@@aX¹¯VݏÇIUmV¯kk‚±Û£mw@‚Őmèżmô™¼èVš"],encodeOffsets:[[115887,23209]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/guang_xi_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"4510",properties:{name:"百色市",cp:[106.6003,23.9227],childNum:12},geometry:{type:"Polygon",coordinates:["@@lklWXL@VšI‚l@XnJn@VUUalk@mK@kny@UlU@a°™„ƒUU@VmaU@Ua@UWw@ƒn@KmLm@alkšmnI‚m@an@VIUamWÅImwU@@a@K„X@JVL„UVmUaVkUa@m„@@Ulmkk°ƒUaVUlKXbVwVIkaVmUk@KVk@a„aW¯m@w„¥laœX@KmaškVmnUl@nxVKšInU@yVaVIV@na°KlxX@@_lmXšUV`VIV™V@„n@lšbn@@WUkValK@²yl@„„VUV@@K°L@KU@@UVaXIVVV@naVkVa@K@UUK@UUa™LWa—w@m@K@UVVƒ@mVUUVKnL„mVL„K‚bVK@UUIk›mI@mUIVK@IUK@VkLƒ@WU@mU@WmUk@ƒI@VƒJk@WwX_@amK@UUWkIƒ„ƒK@LVb@mVmakL@J@bU@Ux@xƒbmI@`ƒIwm@UbmKUaUWa¯UkJWV@XƒJUU¯LUmV@ma@kkamKwƒLUUmWVkkm@aVUUkVKnVVUmXK@UW@km@Ukkm@@W@U™kUy@I@aUUmbƒ¤U@kUmL@bmJU@Ua@wkLWWkL@Uƒ@VaU@ƒLUakKWbkUWVkKkLVLUV@JVbƒz@Vƒ„@ƒVmUU@kVmK¯@VƒU_™VWakVmIUKUaU@@bml@XU@@V@LmKUV„mVUKƒƒKƒbkaUXƒKUL@x@V@l@„mxU¦„V@ŽlL@V@Ln@@VV@„nlKUaV@nLUbmJnL@VWLkbmV„@@L„W‚„XLlx„VVIVV@x@V²blUVm„LVUœK@kWWXUlV@Xl`„LX„l@@VšŽƒn@VnbVš@lVUVUÈVbš@@`UXU`l@@XUVm@kš@xmVknUJVXUbmKULmbx@VlJ@LVbkKUbVLÇUUVƒUVmU@VaUkUKƒVUwmLkUUVVlƒbka™XmwƒKUšVVU@@V±Uk@VWUUm»XamU™bƒKk™`ƒ„™U@UnWW_kKmbUVUVmnUV@„nJVUlšUbU@UV@n@JmI@VmbnVUXlx¯ŽkKmnVV@L@V™bkV™Umm™@Ub¯LmlUƒL@VWLkmkLmmn£WmnKU_mW™š™bnbmxƒ@U¦UJU„@Xmlk¦@‚mnUUm@@Jn@lV„ÔVJnIVW„I@a„ƒÆK@I@aVK„IlŽÞnnl@nl`nbÆX²l@xV„@llbVn²ŽVVl@nn„V@IlW@Un@@kVa°KšnÈmVaVXUlaVƒÈU„VlwôUlynIVašan@lVXb‚Iš@n¥la@Kš_n‚@bÆx@XnJV„nKVz@`VXVšU`@bƒ¦UV@VšIlx„UnV‚K„XÈbšVllšbVbnVn@"],encodeOffsets:[[109126,25684]]}},{type:"Feature",id:"4512",properties:{name:"河池市",cp:[107.8638,24.5819],childNum:11},geometry:{type:"Polygon",coordinates:["@@lLVl„bVV@nXVlI@JVX„mšn„W°b„IVV@‚ln„@nalVUb„nW‚@kVkÒlbVKn²°bUŽlV²@˜X@`nb„aUI@ƒ°wlU@aXJVI@aVK@wUamIXm‚@XUV@@bV@Vm„ImnUUwVaVKXU‚nVK@akƒVwV@nL@UV`n@@X‚lnIUJl@X¦˜V@aUIVm@anƒV@UwnL@VlbVL@KVVXUWƒ„wUUVUka@UVJnUlbnalbVVn@°„„LV`Þ@šXVxV@@bVlUVVbXnWlXnmlš@XXWVXJmbUI@V„llUVkn@@VWV@Vnb„@VXUJVnn`lLVk„a„»lVšLnw@WV@lInw@WnU@U@m‚knUVó„K‚wUmUXUƒU@@wVJVIl@XKVVVbVI„J@Un@lŽVLnm„b@U@Ul@nUš°VUVJnnVJV@„@mVU@ƒ@wkUVwkKWk™yUUkU@alkÈ@lJ@x„Ilƒ@UUWVkUw@Kn@@kmaƒVUl™UUL™ÇƒUUKl@UUmL@aXU@mlUUwmKkUUVKVUƒaƒKUnK@U@Vl@XUWU„KlwX@šb@K‚@XkV@UwWJka@aUwmV@U™@@U@wUm@»kLWVkIWŽXnmV@VkbmKƒLUbk™Va@aƒa@@aVU@aVak£@ƒ±UkVU¯V™UUƒJVƒUIƒ@kxmUmWUbL›w@K@aU@@aVU@Kma@aka@_VWkk@UWVUKULWKULUš@KUnƒwVaUKƒxU@UmaƒL—m@kVmVa@UkƒmI@ƒ@KmIkxU@@K™U@mmakI@VƒLkmWkkJ™_U‚@V@L@n˜xXbšKVb@VVL@V@LUbUlmbU@UUWJUb@VV@@L¯K@LU@UVƒƒk@±z@‚kLUbVl@Xm@™akm@ƒU@UšUJU_™VWŽkn@`W@kw¯LmbU@UJUb@zmV™JULmwk@mVUn™lnb@L›Wkbƒ¦@x°nXŽƒb@bUl@LVlUnlbUJUxWakLUVVb¯„llkn@Vƒ@@nVbUlVbUnƒVUK@IƒW@L@bV@nxÆJnXVbUJm@@bnmJ™nkl@b‚nnK@L„m‚@Xx@VVbV@nb@UVVƒ„¯š@bkV@Vmz@lnLl@kŽVbUVm@mI@Wk™J@UWKkXkl"],encodeOffsets:[[109126,25684]]}},{type:"Feature",id:"4503",properties:{name:"桂林市",cp:[110.5554,25.318],childNum:13},geometry:{type:"Polygon",coordinates:["@@nU@J‚X@`XLm¦Vb`lšVXXWš@VblČnVšŽlanLnmVLšK@_Vaƒ¥@kUa„@VmVb„aV@XVVzlVVK@knKVmX£VKšLlbnš@b@llL@xĊôXaV@°È@¤„bn„V@@Wl_„V„U@W„nVamw„wVbn@„K‚VšLX@VmVUxlV@šnVV_nK@m‚I@Wn@@IšUĊ@@wVWX@@I°VVm@wmU@m@IUƒV™kƒlkUmmkÅV@@aV@@Wn_UKla@kšaV„šlVanb@k„@@KlVn@@aV@nIWW™UUaVU@™kKmwU@UImKk@UU@w@W@‚™k@™UkWƒ@mk_W@Ua@a™ƒƒ@—¯ƒmV£@mƒUUam@—kWakƒVama@UUm@nw@alaUmnUlVlIœV‚™šLVyk£Vm@k@UUJkƒK@kmKUw™KkWK@UXImyVwnI@m‚ƒkUlkUKkUVmƒw@kkJWUÈm@_k@@aƒaW@U„UJUwU@@IWKkƒmUUV@nVl@bVb@bU‚UXƒakw@ƒWUkbkKƒbm@™xUlkLm@@wmKUX@‚™UaVW™XVmU@@UUUƒxkmWXkKkUWaUaUb™L@`UL@LV`UXmK@VmakLVbkL‚xUJUIVbUVVb¯KƒV@Xnl@lVXbmÒnV@L@VWKkVUIWJkIƒŽUamUUbm@U„kU@JUbW@X„WxUam@kbVVUnUJmUUV@bƒU@UUV™@ƒVk@ƒbƒmULV¦U@V„U`VLUL@xVbn@UJ@nWJXXVŽVV@bkxVbUx‚Lšš@x„¦@šU‚lXUVVlULV@@šnŽU„ƒb@xl„nJVnlVknUlVUbmŽU@ƒbVš„x"],encodeOffsets:[[112399,26500]]}},{type:"Feature",id:"4501",properties:{name:"南宁市",cp:[108.479,23.1152],childNum:7},geometry:{type:"Polygon",coordinates:["@@lKnbnU‚@Ua@K„L„ƒlJVX@VnL@bW`Xxl@„I@U„Jl@nV@X‚V@nXV„@lK@UVL@JULVJ@nnJlœVJ@VULaƒLUKƒnmKULVVUŽ@nU„š`lIXlln„K@UlJnb@nšV@LV@lwnJ@L@„nJl„@VUbUn@l˜n„KnbVŽV@„wVLUb„xVm@LV™VKXLVKVLXU@VllUX@`lb@bnb‚L@ŽUV@bV@@b@Lœx‚KVanXVƒUUmVUUUaVUky‚UUa„ImK@mUUVUkKU_@W@UVVVIUW„UVaVU@UUKnƒ@k@al@ll@bnL@b„VUV˜X@Vœ@@b‚Knblmn@V_@aUalL@a@akK@kVKUKlwUUnV¥VmU_VWVIVaX@Va„alńK@LVJnalL@LnK„wlVUw‚mX@VXšƒlLUVnblaUmVUVwXU@Wm¯Va@ÞKnw@w™mšk„»‚UVW²a@_mW@U@I„y„LVUUKW@@™„LX@VUV@@yVU@UV@nwUUmJka@IU@ƒmƒVkaW@UwUX@`ƒ@kLWUk@mƒkUUm@k‚UUWkUƒkWxk@@VƒK@nV@UVaƒUUJmIkVƒ@UamLUbkVmamLka™@ƒ‚kmL¯WI@wJmwƒx@akU@aUKmbkaW_nW@_U@Wm@a@wkwUKmƒk@ƒbkb›w@mKUkkU@J@bW@kVWz@bVUa›VUx@„ULkJWbXVVXƒ`@œmJUVU@@Lk@WbU@UJlnXlm„Vx@Ln@‚b@K„LX„WJUUW@kƒaUVUbmV@nnV@n@lVLƒVmLX‚mXkV±@kxÅL›šUbJWIÅJ@I‚mXalkUamKkškL±aVwKƒUU@mÞnbWJX„m„@lbmKULWUUVkaƒbnn@Vl@VVV@VƒbVbnLWLXJWxXLV@@VV"],encodeOffsets:[[109958,23806]]}},{type:"Feature",id:"4502",properties:{name:"柳州市",cp:[109.3799,24.9774],childNum:7},geometry:{type:"Polygon",coordinates:["@@ƒwU™„aV@nVaUVklmkUUmmIkƒ@w„aVƒm@™U@VKUkVUkWV@™ƒ¥@w™™KVwUalw@aUUUWWXI@mVIm@Ua@wVKUKV_UƒV@U¥VK„n„al@„Uš@VU@V„V@aVUnVVIVmUUlan@VbXwWƒX@Va@IlVVƒn@VanVVb„lJXIVJlUXL@U@KmUnÑWakU@mkƒJUI@mk™@wUmmUV@JXaWIXWmaUIƒJƒkk@W„nJ@„ƒaUak@›kkJ@kUKU_ƒ@myUóWUkm¥kUmL@KUKm@k_UmVa@ƒk@@UmU@mm_—JWIUVUŽWLUlbVUJÇVUIVwƒKUVk@mU@n@lUL@Km@@l@L™VƒzJmUU¤m@UbV²U`U@@¼Vn@x@Vš@@VnUVx@blbXIVxU@Wl@@L™aW@kxƒLXVWVk@@U@VmLVŽ„L„bUVULVV‚lnLVxkV@nWV@bnKVVk@VL„VšÈVKšVVk„Unb@lm@@LVxUlVX@Vk„ƒJ@wkIÇ@kl@blVVVšzXllLUxlV@x@„UV@nƒ‚U@UImmUIUV™¯mVk@@V@VƒamnUKkm@@VƒIUJUaUUWLk@UJUI@xV@V„VWVnxƒLUômVV„@VkVVVUnV@UVkL@VVV@bVxla@bkXVJVn„`nU@bƒb@bVL@VnJ@„l@šV„aU@@_lW@UUU@Unƒlll@XLl@@UX@°bVWVanLlknVV@VVX@VVƒnUŽVLmbXJ@nllXX@`VXƒlmaXVWk@Wkƒw—J@„VL@J‚bnU@bn@@bVKUnVJVIVVVL²a@bV@@Vl@nUVakalmš„UL@VUL@V‚a@mXl@nK@UlK„L@Vl@@nkllb@š„Vnn@‚šnV„™V°l„šVInwlKXxlU°Žn@@ƒ‚I@UnVlakUJWkUK@anUWK@_ÞJ@U"],encodeOffsets:[[112399,26500]]}},{type:"Feature",id:"4514",properties:{name:"崇左市",cp:[107.3364,22.4725],childNum:7},geometry:{type:"Polygon",coordinates:["@@@JVzšl@V@Xn@ll@VlnX@@VWLnŽUVmUULVlUV@blnUlnXVV„K‚xnLlb@lnbU@Vn°KVV„I@WXUlI°VXb‚VVbnLVan@‚x„J@_nJ„a@wVwV@@a@IU@UU@WKXwWIXKmKUa„a@U‚UUUk@@Umm„albVUXVVKnL‚a@knƒWƒXImanÝV@„V‚LUx²blKl™nLVbklWbn@JÆIXJ‚IVaœ™ÆKlw²@lUnWWnK„UUK@k@mmU@mnUVaVU„b@lVXVXIWƒƒK@Lam@@KUwnƒWkkmVIV@Xal@@KV@VUnI@›„_UWWUkam@kkm@ka@mƒk@wkJWIUU@WXkW™XkWWLUUƒ@UakLƒW™XV±VIVWUU@anUWaUK@IU@Vak@@UUKWaƒ@m@ak@@wUkla@mUaUklakwVƒ¯¯@WWUkLkKmaƒ™kLUnV`UxWX@Jkn@bmlƒakkk@ƒb@l¯bm„ƒbJ›b@VXn„bVV@„ƒbƒJUkkKWVU@mœÛVUUW@UVUJWXkVkKmUL@WW@U„Vl@XXKW„XJ@XVlmbUxnnm@UlVnV@XVm¦VJb@šmLkKÇbXblVkn@l@bWnX`V@@IVV@ŽV„V°n@@_naÆVVbUVVbUJnzlVUl‚XkV@Vlx@X„VnxƒbƒKUK@b¯VVUV™L"],encodeOffsets:[[109227,23440]]}},{type:"Feature",id:"4513",properties:{name:"来宾市",cp:[109.7095,23.8403],childNum:6},geometry:{type:"Polygon",coordinates:["@@nVlw„@VJU„„IVVUšV°lU²V@„l¤Ub@bUV@b‚@„b@bUblšVa„KnLla@UnUWmXlJXUlKV@V_U±Van@V£nV‚I„yšU@K@kn@@LVK@k@mnVl@VU„LUxVJÈUVIU‚aVkXKVVUXJ˜In`@nnV@Vl@@„UbVnl`n@VL@LnKlVn¦VlôXV‚nz„@V`VL@llIœll@Vb„b@ƒmIXƒl@„l„IVJnbWXXJWb@IU‚nVVn@xlš@nVJ„I@W„U°LUaVUUaVJVIwlKUalKnb@UnLVWU_@KVK@_šKVa„@VKU¯VLVKn@la„aUkU@maVU„J@k™@Um@XmbkyVaUIUU@KV@laVn@KXKWUkUk@ƒaW™UUVw@aXKmƒVaUUkšmIƒlUU@wUa™xUmmU™¯™U@WƒLUmVIUym@UVmUa@wmw@çm@aWLU„™JUIUamKmL@™aƒx¯¥ƒkU¥U@±„k„UVmKU_mJUbkKm„ƒLÅǙ_@WWUXUmaVUkK™„UWW@nVxkUƒxmL@KkKmbUI@KƒLkƃbUbW@UbUJUXV`UnU¦mŽVVkxVLUL@llL@b@bkKVb@bU`m@knmaL@a›@@U—WVUƒU@amK@akkk@@b@lm„VL@VUVUbƒVVXUJUU@V@XV`lLUVVV@nnLƒJVbVlzUVVbVVnUVVU„"],encodeOffsets:[[111083,24599]]}},{type:"Feature",id:"4509",properties:{name:"玉林市",cp:[110.2148,22.3792],childNum:6},geometry:{type:"Polygon",coordinates:["@@VJUXVVXlWX@V™xVnX@@`ššULWŽUXÅbWK@mULUUmJ@n¯b@l@VULVx„x‚XU`VXXJVI„V@nm`@nUŽVXn@lWVn@b@Jn@nU@Lm`@Xn@WJƒ¦U@@VnL„lV@@Xl`nIlJnkVL„w@KVK@UšaVL@bVKX™lUUKVK@I„VšL„a@U@WšLUlVL@bU@@blb@VlbUxVbXUVJ@xVL„U„lV@VU„bVLnKl„XJ@L‚b@an@VanL@`VLšKV_UWl@U_„a@WVInlVUUUVm@I@W@wVakIWm@U@ƒXwlaVbnI@ƒm»Va@aXaVLšU„»@aVa@k™KkL@KmU@WƒzUK@wU@VWUUVUUKUa@mKmbUK@_nWVaUkVaUaVUVLXKVƒVUVmVI@UkKkLm`UkW@UwWW_„UaU@WakXmK@xUXƒJkƒUUWUk@Wl—mJ@km@@aUKzmyVk„a@kkWVUU¯lmU@@w‚kkmV@Vk@mÅIƒ‚Ukƒaƒ@Ub@m@UUU`mUbWaWmb™X™XKWIXUWm@љ@y@UkIUJUUWLUWƒL@UkVUxW@kaWbKWnXxW¦n„m`XLVlUbVbUx™I@JmLUKUb@VW@@bkL@b@VlU@xkš@L@lƒxXxWXX°V@VVVbUVV@UVVbULVnVJUb²b‚aUb@VVVVInlV@VnXaVUšlI„VUb"],encodeOffsets:[[112478,22872]]}},{type:"Feature",id:"4504",properties:{name:"梧州市",cp:[110.9949,23.5052],childNum:6},geometry:{type:"Polygon",coordinates:["@@VbXblVlLXWln„wVV@VV@UnšWUXVbš‚@VWXa@kVK„UaVaVkšUlyX@Vaƒ—VmUwUaVU@UÈymI@aU°@š™nWV@VaVaw@IV@VmnLVK@kmmna@™„™VbVI@aV@XbW`U„„LUVVx„@VbUV@bl@VLXblJn¦lL„°°@n™@K@UlLnK„a°LWbnJ„¦UÒV„UllLlVnKnbWnn„V`„w‚@@Xa±™n™l@XKV_„WVkVa@kVyUa@wU£UW@UIVW‚@@a—wWaX_WKkVmUULmak@UJUI@±m»™—k@m»VyUIm™nmmwnkUmVaVIUn_mW@»Vk„@VwkmmUXa@IƒaVm—mƒ@Wm_U@mIUWóLmUk@laXmmkUK@UmKULUUmWULƒ@VakU™@Ub@bƒ¼™VUKWb@bUbn¼@„mJUakbWx@„@VXnlJUb@x@X@JUnVVUVmkUJ@XƒbV`k@VXU`™LUK@_mKUbm@@b@„U`@nlV@b„UnbVbn@@`VbUbVV¯bm@@mJXb@bVnUllVXUlbUl@LU¦VVmŽkLVb@b™l@V@XlK@V@nUJUz„°mŽwmLmlXbWVU@UUUlƒIU@VVmV@@¦‚bXbWxX„WlXVWL@LUmkbU@@LVVVJUblzna@WVnš@@lƒIUVnbV@Vlƒbkbm@ULUKV°ULƒ@"],encodeOffsets:[[112973,24863]]}},{type:"Feature",id:"4511",properties:{name:"贺州市",cp:[111.3135,24.4006],childNum:4},geometry:{type:"Polygon",coordinates:["@@nL@xn@lKVkšwn@„alLlaXV@„lx„bVWV@aUa@aUk@mVUnVl„XL@JV@VxVIVƒX@„b@bl@@`ÇnXVlI@l„xUnlVVLkllV„@nmJUxnzWJ@VXLlŽšLVxnL@l„LlŽVI@V@lUnl¤Uz™Kš@„Vl@š„L‚l„Lnš‚b@VnVVU@k„a‚Knxn@VkVJ@ńUlakmWIUaVanm@_UK@UVWUa@klXam™U@Vmƒ™VIXW„@lUVknVlKVLXŽVXšW@b@VlšnnVL@KXL‚Kn@lb@UnW°@Va„X„WVb°aVa@I¯aUkUaVKVwƒaXk@a„a‚™@wkm@alanUVw@alK@Umkw@UƒaUmU@WXUaUK@UW@UaVWI@¥Xa@w@WWšVƒXwƒU@mKUXUWVU@a¯kl@akU@UULmK¯VUVW@U_m`U@@xVbUz@lUbUlƒXU`WLk@mš²šWb@Ž@ƒxU_mƒXmmamLkUkKVkUƒVу¥mIXa¯KƒbmLkK@V@Lmš¯@ƒ¯kKm¥kIWaUKk@@aVUUaƒ@UwVUƒKVƒX_WaU@@bUJUaƒš@šmbnn@lULmKUnU@@J‚xUbUbU@mX™š¯@VŽ@bnJÇz@VUVVbVxUn„˜UbW@kz™VUlUbVbƒŽUL@lWb"],encodeOffsets:[[113220,24947]]}},{type:"Feature",id:"4507",properties:{name:"钦州市",cp:[109.0283,22.0935],childNum:3},geometry:{type:"Polygon",coordinates:["@@@IlVVlnL‚@œxla„al@n„VLlx@x@bXnV@@`mXX`lbnaVL@blV@b„wnx‚I@xXJ°nK‚l„š@lbnKnblUVanKVb„@lUnJVI„VUb@V‚U@m„L@Ul@Xw„llVVXV@lVnlVn„l@XVlK„@@_VWVxX@lb„U„nV@@JlbnIlmnVV@UwVK@U@k°a@mnIVVVK@nXLÆaVWXVK™™@_W@Umšw@UXWWkUUVWUIVaƒUkJ™UVWbUmU@mkUJUU@UVab±aVaUIUmVKUaVUU@VUUaUUU@W¯XWWw„w@k@Kl™@wkV@U@alK@aX@@UmIUWUIƒ@mmkXU`U_WJUnUJmUk@@amLU@UVW@UkU@@VƒbUWVUk@@wmKkUWLUWX@JmIƒlUkkKWKkLWU@UKWa@bU@@a@_UKWƒUUUmJmw@nV_@ġğKóLmbU¼VÆ@xUXƒ@Um@wklVnUn›lkaUV@„lV²WVklWXXbWlkVkIm`UUƒLƒUU@UWƒx@XU@@lWLU@kbUbV`UXllUV@bmb@LnKVbULm‚šnVVIV`X@"],encodeOffsets:[[110881,22742]]}},{type:"Feature",id:"4508",properties:{name:"贵港市",cp:[109.9402,23.3459],childNum:3},geometry:{type:"Polygon",coordinates:["@@n@VzUJ‚nVŽ„K@XšVš°nVVnšwVb@xVV„knJl™VVUbn„WL@bUxVVXš„bl@lVXkWƒXwWaa@¥‚@nUUUV@„JVkVVV@XUWanknK‚xnƒ¯VyVI@m@UkL@W@Ušk@aUalKnUUV¥@KVkkaWVkUVkUm@aWanI@n@°aUUVaUa@_m@UamaƒV@akU@mV_@ƒa@KWIkƒmLUKƒaUVU@ƒkƒVUK@wUIWVUaVwka@Uka@aV@@aUKVk™K@X@Vƒb™KƒU@JULVLkVWšUL@aUK™b@VUL@LƒxUKmlkImJk_@WU@ƒkmK@UV@„¥XIm@@Wn_@KmVm@@I@aUmkXm@UWV@mn_@mƒUUJWIUWV_WƒwU@mUknVVmxU@@VUV@zU@UVW@ƒK@šX@VLUVƒKƒz@J@VnX@`±bUXVƒ¼™lšn@xmxÝL@‚Ubn°@XWVUxUVVnkbWVXV@Xš`ÆȄKnƒlLVanIV`nLVUlƒ²ƒV@V¦„l°¦„w‚b@šnKnLVbVJšIVƒXK@b‚n@ènx@xVbUnV‚"],encodeOffsets:[[112568,24255]]}},{type:"Feature",id:"4506",properties:{name:"防城港市",cp:[108.0505,21.9287],childNum:3},geometry:{type:"Polygon",coordinates:["@@XV@X°°U„lxkbVlVb@nkbVl@xl@@b@n„‚XbVL@Vl@UbV@@JVLXbmV@bVVUXUJU²šW„XlKVb„@VVXKlXšWlXXWV@VXJlI@x„l@nlbn@lln@lbXalIVK@ƒVwœUVb‚U@aXylUX@@aW@U_UJmU™nVKUamL@Kna@aVUkkVWU_ValaV@XK@kV@@W„wVXV@„V„KVVn_lJlUXkWaXWlkXU‚±kU@ƒVUlbœkVmUmlk™¯Ý™™W@mb@¦VxULm™kJUU@ma¯wƒmkX@VóJ±bUVUXÝWk™lWXXlƒxUaƒbƒIğ™Ç@U@mVUKkkm@UJm@XnWV@x"],encodeOffsets:[[110070,22174]]}},{type:"Feature",id:"4505",properties:{name:"北海市",cp:[109.314,21.6211],childNum:2},geometry:{type:"Polygon",coordinates:["@@VaVLnK@IšJVwUaVaUkWKn_mƒX¥WwXm‚LXalbU£UyV„Å@ݙwm@™°l›LÅUƒmk™mwÛaƑLÝUUm@ȣƃV_„Ó@£UƒƒUVƒ„™¼U°W̄™ÞVbXbôx@b@bmV@ǃ™UÝ@@ĢU`m@ŽnxnIVV‚VX„VL@`@bV@@aXbVL‚@XVlKXLlLVl„knJ@I‚WVXXKlVnL@xl@UVVX„a@UV@VlX@VUV@nK@bl@nVVIVmXIV`V_lWnn„@VJVXnJ"],encodeOffsets:[[112242,22444]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/gui_zhou_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"5203",properties:{name:"遵义市",cp:[106.908,28.1744],childNum:14},geometry:{type:"MultiPolygon",coordinates:[["@@@UnUlJn„w‚JU°VL@bnVšU„wlJ@XƒŽXVlU@klVUJknl„UllL@bUJ@xULUlƒ„UblVkblbnw‚UXmla@„wV@VK@L@UXaVKVLXWƒUVa@U@Im@@W@£UKUakKWIXU@al@@llUnL@W@Un@@VlUV@VIUanKl@Xb@lmxVb@b°bb@nlJVVnnJ@b@L‚V@ln„@LmV@Vx@blnVK„nlJXIlw„J@҄b@nlK@Un@UL@VVVVUUUVK„l„@VUVL„J@UVUUw„@Wm@™„UV„ÈVlbUb@JšLlŽX@@x„„ƒLmŽk@@nlx@bUJUzVJ„@@LVxUV@bWxnLnVVK@_‚K²xVbV@n¥@aVI@b„@l@Va„Knb@n‚`n„mmý„W@ƒU_šwV@VlVV@Vn@n„˜@nI@Jn@°¦VaUU@™„mVVWVaUńU@aVKnƒVbVUmmU@a@kUw™m@aUUmUUJ¯lakU‚aXaWUUaVƒkk„amkmUnVlULƒVlJ@XU@UJWUUw„k@aU@WbkWƒL@U@WU@@XUKmV@aUVwUĕUJUamUUVUÑm™nIVJ@kl@XalJVn@KVLœ¥@UWIXWmU@mVUKnUWLUKUaWUUKVU@U@anUny@UlUkK@w@a@aVUƒ»UkVw@Wmk—JƒÅmUUVmwXalLXWWUnam@XkƒJ@UVU@U@W„@@U@I@Wl@Ènlw@KXLWb„lVUkalKUU„VVaV@@wnIlaUmkUƒKWU@KkUkLWaƒKUUWUn@VƒK@LnnWJUIƒVkUWVnV@V™@@XƒK@VUIUJ@IWJkX@VVJ™IƒVkK@I@UVaUWk@m„@wnUWKk@mxk@@„lV@b„xmb@x@VUmLkUƒJ@nVV@b@VkLVbU`¯I›l@™U_UW@UU@™™ƒK¯wm@™xƒL¯¥kIƒ™ƒ‚@bkbƒ@Ua@ƒm@kkW@XVbmV@ŽkV@bWbUbV@„¦ƒxXlmVk@ƒ¦™bkaWL@KUImK@wUK@VUI™b@bmK@LÅy@akXW@kbWlXblL@ŽULUbƒ`@U™kUymX¯@mšUJUUJƒL@Lm@@WX@lU„VlšXll„@l@Èk°V°Ž„X@VU@UVll@XUJVXUVm@@VXLWlnV@Xƒšk@mVULnxV@@bm‚kL@VWLUbU@UVm@ƒb@ķ¥UnmJ@UUVƒkkJUšlÔU`UIW@ƒ°kLUlUI@WVI™U@mWKkXk@ƒ‚WU@bXšW„@J@xX@l@LVl@xšLVxXX@x‚KnxVknb‚KVV@U„L„WlXU`@nUlšX@llVXšVU„KlkUKlI@anKVLXKVaUIVWV_VK@VnLlU„»VKVL„m"],["@@@KlKkUUVVX"]], +encodeOffsets:[[[108799,29239]],[[110532,27822]]]}},{type:"Feature",id:"5226",properties:{name:"黔东南苗族侗族自治州",cp:[108.4241,26.4166],childNum:17},geometry:{type:"MultiPolygon",coordinates:[["@@VV@XkV@bUbWJU¼Vb@Vnb@bš„@J@bƒL@LV@UVƒlUI@a™KULVb@bkJmx„šlLVxknVJk„‚xnKmnnL@bn`WIXlWLU@UxVbUVmKV„XI@JVIVJ@U„L@Wš@@UmUXUlV„UVJXImm@K„L@UVmVXV‚„LXblKlV@LXV„LlVVnkbmJ@xnXl@šbXa‚@Vana„ÒšL„m‚VnIl‚Þ¦°k@b„@@lV„nJlUnš‚VX_„@lVlK„šV„UUxVLVWVIXJšUlnnWlI@KUaUUVKn@VaVXV@na@ƒmw¯@mUkJUamI@lk@@am@@I„ƒUmVImUUw˜™@anUVaUU@LU@WaWUXWW„wV@VwnU@L@ynbl@@X@a„J@nW@@Vn@„lVLlxnI„lš@@UWKUƒnIlJXIVllIVVš¼XK@aVI„V‚@@bn@VKXLVKVVVInw„J@UWI@mX@WKnI@KmU„UVJUL@V„KW@@k„@aU@@W@InJWUXwWI@Wƒ@¯wkaVaUIl@nŽValIXWWI@UUm@anwWkXWWIUbk@UJmIUamKVUUUVVama¯VkIVVUlKnXVwX@@WVaUUVa@IlƒaVmƒkna›wk™UU@ƒU@mUVƒšUVwœl°LVbnJVU™¯la@mX@@UWKXU@aV_V@@JlkUƒ¯@V™nK@km¯k„U@ƒWUW@mmƒU@™kmlU@wkL@WƒUkL@VmLƒJ@b@V@bknUUVK@UVKUK@Uk@Wa@LUVVnUbmVk@@UU@@aƒV¯K@U@UU@WmUL@aU@WV—w@ƒ˜I„xXll@UX‚K@KXXVJna@wWaƒ£naUKV„m@UU@mUmalm@@XkVm@U@VƒLmWU@kkWxU@@bVV@VkXVlƒVƒ@UUk@@ƒmI@KUw„m@UmVƒUUwU@lwkV@IUa@mUaVIVKVa@w@U@™UJkb@n@bmJ@XmlVUxWXkJmUkUUVW™xUlU@ƒaULUšmbU@@‚WXkmƒL@xUV@nUxÇm@„XLWbnlƒnV‚nnUV˜U‚nVVz„@lbUVVlULVb@V@nUJkwm@Ux@bWbUK@UULka›JbƒU™U@U@lUK@XUJmn™J@bU@UwWa™x@zkJWnUJUUVšVV@bXn@xVb@J™L™m@X™w@`@bkb@VmXUV¯L@mW@@n@V@‚ƒL@K—IW@@aƒaUx¯@U„m@XbW@@L„V@bnVWVkKUzlV@bÆa@lnI@VV@@LnVVKUaV_VJVbnU@bn@‚‚nX@yVIVxXKVLlUVaXU°J","@@@KlKkUUVVX"],["@@UUVUkUmV@ln@VXVK@K"]],encodeOffsets:[[[110318,27214],[110532,27822]],[[112219,27394]]]}},{type:"Feature",id:"5224",properties:{name:"毕节地区",cp:[105.1611,27.0648],childNum:8},geometry:{type:"Polygon",coordinates:["@@UkVƒ@k‚W@Xn@@K„KVIVVIn™°@nWVzšl@V„_VaVK@kKWaXklaX@lW@bÆz@KnL@ašaVJ@UVL@xnLVJ@LXKlbša„¥l@nUWk„wƒ¥U@VaXa@amLkUƒKmƒ¯kƒmkIUaƒKUIWƒkKm@anw@mlwXIƒmƒUk¯@a@amUƒ`kkKWVkxmUUak_mJmw@w„mXUW¯X›_@WnI@aVwkWWýŃU@WLkU™aUbVV@lUVVnm@kUmV¯™kK™LƒwmVUUaWV™aaWw¯wƒÈ@VULUVUUƒK@nWJkI™l@Umxnbm@kbUJƒa¯bUbVxmLUV™aU@VUUWxkVVV@bUV@XWbnlUbƒbUJlbUV¯b@z„`WbXnmbƒaƒwUwVWUƒbUxmbU@Uam™@Vƒk™VaƒwVaUƒWI@mUKóz@lUlÅ@WIƒb@xXxml@XklULWKUmwUa¯KUXWJkaULmKkLWbkKUVƒImƒƒWa@kUaULƒW¯LƒK¯@kbƒL@b™x@J@bmnnlUšlzU`U@@Uƒb@„m‚n¦°bU„Vx@bkVm¼mx@mk™mVV@bkxVn„aVV@bU@mL@b²`lIVV@lXLlš„bVxn@@bl@XllIVšnbVšn°°wlbXw@mVa°lVnU@mš™VLVbn@@b„@@WVnUV@Xlxn`VznJVb@L@bV`V@šUnwšU„@WUXKV@UUlmUUlaXalLšm„bšIVbnJVIlVVaUUnWVXn‚VL‚k@ƒnWnblnlb²x„xVKVXlVXLVW„LlUVJna@wVL„¼@JVX@`@nnx@nWJU@Vx@XXKšŽUblxUš°„LVKVVlL@KnbVUnJ„IlUšƒnKl£VW„x„IlJ@nšVÞUVVnb‚VX@V_°lnK","@@@UmWUwkU@Um@@VkL@V@„„‚V„VkV@nbVa@ƒ"],encodeOffsets:[[108552,28412],[107213,27445]]}},{type:"Feature",id:"5227",properties:{name:"黔南布依族苗族自治州",cp:[107.2485,25.8398],childNum:12},geometry:{type:"Polygon",coordinates:["@@‚V@IöalK@UV@@KUaVIVVœLlaVbVWnX@‚@LnUlxl@naVLXVVaVU„J@lUUanWWI„@VlV@Xbƒb@V„n@VmVVbk@kU@V›V@X„J@zn`ULW@kK@_WVUK@LUb@Jlxn@nnWlU@@b„x@XVVU@UbVb‚@n`VI@VVLUlUIUV@KmL@VV@XIV@@lVLVmXV„@WLXLW@U`šnkb@Vl@UL@VVV„L„llX@`lIXb„J˜IXW„L‚aVL@ŽXXW‚Ģ™b@bmK@L@°@Vnxmxšn„K@xVn@VkL@V™Lƒakbl`VnnxVnUlššV@@VVXV`@šœk°JV_UalK@U@aUU@m„IlVnK‚V@U@wnaƒw@akU@ƒl@nwl@XLmV@xnƒl@VXUb@V@JlL„UšJUI@UlWUƒnLVUUaVwV@XKWkXJm_@amKnmmLwlƒUIlmUwkKƒ™nwlI@aUaVKšL@bVJ„kVUU@@K„K@a@I™ƒ@ama@UUaV»XIVa@alU@WUU¯IWVUbkVUKWLUwUJ@zmWm@@amVUaUIU`VbULmU@KU@@UmJ@kÅb@akUVylLXUmU@aƒU@KX@Wan@Vƒ°@Vw„b@bX@˜J@L„K@@U@mX@@n°KVUnW@Ula@a@_šx@WšnšK@IUa@wWm@aUUU™VVVIXmlI@yšwXbVxV@@ašInmVI@WVL@k@VšV„V‚aœIlbVK@VVLXa@aVwn@lxVI@m@UUaVKUkVUkaƒ@UymUV—VUmmU„mmkXaWK@ƒÈnVw@mVU@w„KlnXW@V@naV™VKUk@KVIUWƒ@mk@KXU@Um@@lVƒk@UVJna@UWaƒL@a@ƒXa@kmmVUUk@mkkƒamJ—ImJUUmIm±aUUkambkamVUU@VlbUbVVƒxX„WVUU@VUakU@UmUV‚U@mnUVVnUbVJ@b—UW¥kLVamVkUaWJU_UVWKk@@nl„UVVJUXm@Vm@UnVlmbnmJUbULU@@UUKWVIWxnJVb@xUL@bUJWIkxƒbkb@xVJƒbmU@kW±LkKUkVa@a¯am¥ULkalÑlKXUWƒXƒaVakImVƒ@ka@UUƒJ¯aƒX™mmb—KWU@wUUƒaUa™KmU@UXlWb—¼WLUKUb°„UlVbkbVL@VƒšƒJ@nVlUbUXmJ@VX@lbUbU@@bWb@VnLVJ@bVVUz„ŽVL@lnL@b™VVVULmKUk™Jkbm@ƒxVb@V—kƒKVnnV@b@ŽWXU‚„nV„l‚VVXVJUXlVXbWV@VU@Ubk@@KWbUUmL@JnXV°XJ@_‚`UbkXVVlÆkbƒ@VLXVV@‚V@k„KXX@`V@@n"],encodeOffsets:[[108912,26905]]}},{type:"Feature",id:"5222",properties:{name:"铜仁地区",cp:[108.6218,28.0096],childNum:10},geometry:{type:"Polygon",coordinates:["@@°a@aÈbVUlU@aVKnVV„VUlyX¹lWVa@U™VƒnUVU@m™@mUl@„mÞw„@‚xnIVbna@KVI‚J@kwV¥ƒUXÇVkVW@kkKWU@aXUWmnIVa°VXbmL@VVbnVVVUb™VbšJVbVKXkVKVanU@aWnWUWa@U™nk@mVIVK@wXxlLXbVJVlKœbl@VI@mšaXalVV„VbX@@ašalnkx@b@V‚b@Vnx@bVVUXn¤WXn@Vl@Vlzn@š`@I@KUU@ƒV£namVkXa@aVK‚nnU@anVlKƒa@UUU@amk@»kƒU¯@aš„VWnkWmkImU@akaVm@»VUV@UKnkW¯XWlkUKnIWaš@nmlIXmWUnwUwWm@wULmaUJkIUaƒaWa—klwkwmJmU@bkJ@XUJ¯W@XbWbUKUkWJUUVKnn@UmmXUWa@mU@@UI@WmXVykwm@kaULWwU@¯ƒlKUUVU@mU@UkmaUbmV@b—š‚xVnVUJVnƒ„@Jn@@bl@@knJVblInV°@nx@„mbU@UWUbm@ULVVVb@LkJmXkm™VWIUJUXUKVwƒV™UƒŽkLkUƒ@W`Um™kVmIUƒ@kƒ@@a¯lÝ¥kmJUƒn™KƒÑmbUb@Wb™ak@mWU@UbƒUVVkLlbUVƒkXaWK@LkxÇmk@@X@J@Vƒ@@X@VUV@V„IWln@mbXVWXkKWbnxVUnV„ƘInl@XUxVl„¼UV@b@b@xlLkV@VmzmV@b@VUVVLXVVbVLXKmVVLU‚@nnVWXXJ@V›¦UK@LUmkIWbk@@lUImJnšVÒVUnVVbVIVĖUxV‚@bnUVL@WV@@X@V„KlXXaV@@bƒlVxXVVIV@@WkI„UVKUkVmlnnŽƒbllU„VbXVWbblVkb°ŽVInVVV@bšnVx@l@bnVVnUŽUam„UL@bƒVVÆUbUXU‚ƒn@šVVUb"],encodeOffsets:[[110667,29785]]}},{type:"Feature",id:"5223",properties:{name:"黔西南布依族苗族自治州",cp:[105.5347,25.3949],childNum:8},geometry:{type:"Polygon",coordinates:["@@VL@Vl@@IXW@kVUVbnW@XlKVVnU„VlL@b„aVbƒb@xX‚°ÔUxV@kbm@VxkxWJœ„V¦ƒŽ@ÈnšVKšxWXJmV@n„Ò@xVbn@@blLk`VX@bššla²JVUlnn@U±lw@wnw@mlwVIX@@m@klKnk‚a„KnwmmXkƍVm„Uš¥l@nb°n@„aVwVmVIVnI@a„¯@mšU°ƒl@@VnI@JV@UV@b@IUbVJmXöºƒzllUbVa@aXUl@„U@llLnKVaUa@UmK@UšwV„bnKV@VwVK@UXƒV@Vbn@‚w@U„WnX‚@„a@m„I„™@UUKlaUaVk¯ƒVaVLXK˜»XaWk¯mƒkğwmW@mIƒVkwƒJUIšÇVwU™UkVKkƒm@UkmU@WÅwm£Vƒ„m¤¯IkJWa™_™lUbmJzÝJk„ƒUÇVU„ƒ‚@bU„Ýn™m¯LUb@`mL@VkL@VƒUmmk@UU±Umka@kUƒ@ķymUkk@mmkÝmUaUakImV@V@VÅLƒ¦ƒJUXmJXšWb@n°Æœx‚¼nV@LlbUŽUbmL¯@ÞbV¤nbVx@bUVlblIœ™@KVVUnVJUn@VlLUlmLUUUxmK@I@@VW@@bU@UJmUkLVVUl@b@V"],encodeOffsets:[[107157,25965]]}},{type:"Feature",id:"5202",properties:{name:"六盘水市",cp:[104.7546,26.0925],childNum:5},geometry:{type:"MultiPolygon",coordinates:[["@@ôyVL@nXJV„Ub„x‚bUŽlšU„@ŽšnŽVbV@naVw„a‚VUXVx„x„bnaWmXaƒ_@y°aVUkaVI„aVamkXa@WVU@aUUlUXwVV@UVšbVUnKUwVa°a„bVIlan@manw@VšklJXI@m„LVVVUVK@U„ǃk@KUa@UkaVU@UVWV_XWVXVWlLXKlLXaÆKšwVL@akKm@Uwƒ@@XUVk@VUI@wWK@aUV™I@UkK@ƒmL™Wƒ@kImJƒUÅVmkXUW@UJkx@nmx@xkxV²m@kmUV±Ikb™™@aUWl_kK@am@Ua@wƒÑ@mnUWIX™wULm™@DŽU¥›ƒXIlwUwn@laU@Vw¯ÓW@w„aUaƒb@akKƒUmVUUkL@WmXUaUV@lWX@Jk@@UUKULmLUJmzkKmVX°VšUnWKUL™ƒƒL@mU@UnVJ@b@„UV@Xƒ`m_@l@@bmbXJmnnš@°˜wnn@ŽVLX@V‚@nVl@nk@@b‚l@nn°WlXzW`XXVKnUlxVbUb@‚V„Xb@Ž‚VxÈbVlnbmn@ŽkVUL@„ƒŽmLUVVL"],["@@@ƒ@UmWUwkU@Um@@VkL@V@„„‚@„V@VkV@nbVa"]],encodeOffsets:[[[107089,27181]],[[107213,27479]]]}},{type:"Feature",id:"5204",properties:{name:"安顺市",cp:[105.9082,25.9882],childNum:6},geometry:{type:"Polygon",coordinates:["@@lL@bUK™xÅLWbkKWLkKUXUWWXU`UX@VUVlb@VVb@L„l°xXx‚bšbXUVb‚VnU„xšKlL°šnUlVn@UmVU@kUUVašblVXKV@ƄXþlXUxnU@mVK@_@ml@UU„@šblU@KnLVyUw„@@UmkšWVw@UVK@VXzVK@n„VVUUW@kVJnlaš@nKW™kaWL@U—™õb@JU@mU@@_WWƒL@lUU@WUUK„@lakÅUUlWVa_@`WIU¯mW@InKVVXa@Ll@VaV@@UXUWakUVWUIUW‚UkUƒƒmVXW@@amUUm„L˜l@UUa„wn@lašIVlnLVKUUšU@amK@kUKƒVyUU@aUImK@UXa@aV@VakaW@@UnIVWVaUkƒb@mWƒX@Vxm@UaU@W„@VULUxU@mLƒaUŽ™x@VnL@VVbUbmLkK@kƒVk@WV@bUbVakk„yõ¹nWUIVa@J@aVUU@@ImJ@Uk@¯„™V@nƒ°@bmJUUJUnUxƒbm@¯Žmak@™¦ƒVUnŎWlnnmxƒLbmlkL@l@nWVnlÆU„VnIlJ„@šXnK@„lL@VšJVU@bXL@xVJUl@VU@W„@Vxn@"],encodeOffsets:[[108237,26792]]}},{type:"Feature",id:"5201",properties:{name:"贵阳市",cp:[106.6992,26.7682],childNum:5},geometry:{type:"Polygon",coordinates:["@@nŽlLX„VJ„LVblJ„n°ln„„LlVnKlU@nUUa@WlX@l„n@‚Vb„@la@a„„šlJ°¦„Kšwn@°x„LVkUmmwUmk_la„bšK@UlK@UUm@wƒL™mnwmw@U@¯@KnL@aša‚ġXWW@UKbƒKWX—JƒIWakJ@_kWƒkƒKUU@UVKk@@Ula™mV_X@WKXKƒ@WUUnUK@kU@WJU@@UnK@LVUVJVkUK@UUJm_@UaVaV@UU@Wƒw@aV@Xkmmm@kw@IVa@KVLXU@`lLX@VKm_@yƒI@WœU@UlVl@UanU@Uƒm@U„aWaU@Ukƒ@XJmXVbkV@ŽƒIUVUbWUUKmbk@kwmV@K@mWUXUakb›KUUUJVb@LU@@VkL˜š@VXKlbXšmL™@kbm‚UI@lVXUVƒU@mULWy@UUL@VUx™Xnl@Vƒ@VxUzmK@LkV™aƒ@VVk@@n@`UL@nmV@bmJ@Xœ`WX°WVƒn@xnxnIl`VbnVlwXUlLl‚„_nV@b@bl°„V„nWJkx@nmx@b"],encodeOffsets:[[108945,27760]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/hai_nan_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"469003",properties:{name:"儋州市",cp:[109.3291,19.5653],childNum:1},geometry:{type:"Polygon",coordinates:["@@஼jpnr’``ŽpRVHʘ̤žZt^JÖA˜[†CâlTébQhRPOhMBcRSQiROE[FYdGNOEIH]MgEAMLLIAG_WMCSL@ED]PCLYC[ZIHgjSxJTMbHNEFCMEE_HSDFHSLECRNSFDRICHNADGPI\\RZGIJTIAHLDQOHG`GTNCOIC@eIGDWHIS[kiE[FMbECZS@KKS[FDWsCeRuU_DUQNOE[LKGUBM¨EDQP@HWHGDImXƒCog_~‹I_fGDG|QDUWKBC\\ore|}[KLsISBHVXHCN`lNdQLOnFJSXcUEJMCKSHOUMDIm_‹DI`kNDIGEYFM\\YPEEIPMSGLIKOVAU_EBGQ@CIk`WGGDUM_XcIOLCJphHT_NCISG_R@V]\\OjSGAQSAKF]@q^mGFKSW^cQUC[]T}SGD@^_ˆaRUTO@OHATŸ”"],encodeOffsets:[[111506,20018]]}},{type:"Feature",id:"469005",properties:{name:"文昌市",cp:[110.8905,19.7823],childNum:1},geometry:{type:"Polygon",coordinates:["@@€hIJ¤Ī¯LQDaFßL[VQìw€G‚F~Z^Ab[€¹ZYöpFº lN®D´INQQk]U‘[GSU©S_­c‹}aoSiA£cŁ¡©EiQeU­qWoESKSSOmwŸćõWkàmJMAAMMCWHGoM]gA[FGZLZCTURFNBncVOXCdGB@TSbk\\gDOKMNKWQHIvXDJ\\VDTXPERHJMFNj@OwX@LOTGzL^GHN^@RPHPE^KTDhhtBjZL[Pg@MNGLEdHV[HbRb@JHEV_NKLBRTPZhERHJcH^HDRlZJOPGdDJPOpXTETaV[GOZXTARQTRLBLWDa^QAF`ENUPBP…\\Eji`yºEvåà"],encodeOffsets:[[113115,20665]]}},{type:"Feature",id:"469033",properties:{name:"乐东黎族自治县",cp:[109.0283,18.6301],childNum:1},geometry:{type:"Polygon",coordinates:["@@ªVLP`@PEdNRAHOPEAKHEVL`GZBJfvdTAXNNTZJFPrHHNpKTD\\ILHbEVd^J‚OHLh@NNBnHP`\\xH@NBRLJTlŽNv_^CTLd@bNDVFbxdFV€UPBTKOGEOUO@OEBXQP[H_EI\\EbeYa@UO_J‹MEJ_IEDKJUGMDcNUd_FMTEJSGoZ]EIYGO[YW‘gEQ]a@WHEDQKUSDUGAbYBUpSCYNiWqOSQEoF[UcQISWWNMSDe_cLQ_UBiKQOOASQAWgS­ā]ZaŽSPÝZ]XMXSŒ[^oVËNgNKlE RôEø"],encodeOffsets:[[111263,19164]]}},{type:"Feature",id:"4602",properties:{name:"三亚市",cp:[109.3716,18.3698],childNum:1},geometry:{type:"Polygon",coordinates:["@@®ĂhTBXTRPBRPjLVAR`dKf`TC‚NXMTXRJVdE\\FpTRrPjXZMTDVoZABaVHTCLVCRGF@X^bFR’hZXP\\ZHHMA[^wBWXJlW¤EJ[bCTOF‹WWMm@ILMGWQ@DQ^QNWFSHEbF`OXNbO„VNKTEPDTLTCCVTREfvfEHNbRAENH^RJXCFHNFRpVGHWISDOTMVCZeGamaLoLÛD¹¹ėgsia{OųE—Tt‰lɂwr}jŸR±E{L}j]HąKÃT[P"],encodeOffsets:[[111547,18737]]}},{type:"Feature",id:"469036",properties:{name:"琼中黎族苗族自治县",cp:[109.8413,19.0736],childNum:1},geometry:{type:"Polygon",coordinates:["@@bRFnHNbHŒgN@NPEnbXP@bND`NT\\@\\QZb@`@J]V@XhžDpW„nCJGHGXO@CR§FANHVKLF\\MPVR`CvVfQtDPKpGHG@S`WJP~^dSTHWX\\RHTFACQTIAUPOU@MG__IaYSFQK‘NSbORHXCZeTFJg„B`YBMNMFi~IVDV[tGJWXGDQRGF]ˆJrALgESLSAYDGIaFeXQLS\\MKSLSQYJY}eKO[EHiGSaK[Yw[bmdURgEK^_kcSGEOHKIAS]aFSU@Y]IWFUTYlkP_CUOUEkmYbSQK@EMWUuAU\\M@EpK^_ZMDQ^OXwC_ZODBrERURGVVZ\\DTXcFWNIAWJWAYUUFYEWLQQaCIZeDM`cLKRGpanJZQd"],encodeOffsets:[[112153,19488]]}},{type:"Feature",id:"469007",properties:{name:"东方市",cp:[108.8498,19.0414],childNum:1},geometry:{type:"Polygon",coordinates:["@@ºŸx‹JYZQ”IŠYXLl@dR\\WZEn]bA\\S~F`KXaDeTiNO^EEKWEDQXITBXaWaDQMUJOIaTWf@NJV@dSxGZ‰Fu_@WMKAUˆ}AQ@MwG_[GOAmMMg@GKP]IUcaFKG[JSCoLGMqGEOYIMSWMSBucIeYA_HUKGFBLOFGPQBcMOF_@KO©UAtERadwZQ\\@ÊJÒgòUĪRlR°KĮVŽLJ"],encodeOffsets:[[111208,19833]]}},{type:"Feature",id:"4601",properties:{name:"海口市",cp:[110.3893,19.8516],childNum:1},geometry:{type:"Polygon",coordinates:["@@ńZƂtĢ¬æßFuz¹j_Fi†[AOVOFME_RBb]XCAKQKRSBQWSPY\\HbUFSWSPoIOcCOHIPkYCQ]GdGGIFQYgSOAQLK`MFUIGa@aQ\\GGUFcHKNMh@\\OYKAigsCgLSF]GOQO]@GM]HyKSHKPW@Pxi@EMINYREXWRQ@MQcFGWIAwXGRH\\yDI`KJIdOCGRNPNtd\\UTMbQYi@]JeYOWaL[EcICMUJqWGDNZEXGJWFEXNbZRELFV]XQbAZFrYVUBCLNFCHmJaMIDDHXHEhQNXZ_TARFHVB@DTQIRR@YHAJVnAbKFUEMLd\\c^ÍÞ"],encodeOffsets:[[112711,20572]]}},{type:"Feature",id:"469006",properties:{name:"万宁市",cp:[110.3137,18.8388],childNum:1},geometry:{type:"Polygon",coordinates:["@@^J@ZTVbET^JBGLFPTHld]`FLQhcVanx\\\\ZbLHTGj\\FLP~fIZRZPVTQFSVAFJE^NDLEE[~LjsxVTG\\NZZNGlLRRGLJTV@hPZANN^@T\\NEPPbDZXO`d^HSvcJDIV\\XZAJUFCLNP@PQ¤@[ïKLÑIÏ]ÇE±I{uƒ­YśUćFcYUmsVeBSVgB[RO@aYYPO^]@UVaNeDShMLG\\EfFVE\\F`"],encodeOffsets:[[112657,19182]]}},{type:"Feature",id:"469027",properties:{name:"澄迈县",cp:[109.9937,19.7314],childNum:1},geometry:{type:"Polygon",coordinates:["@@T\\GJCXJH@fJDDPNCNJENN^NLHBNSx@DDYbBLLDRbjZTj@`XXTlG^Xr@PJLW\\WLTlWR@HDJTD@X_PO@STMDNTMVV@NLDM`M\\XM\\JNBH[PYZ‡úYzŸ`Ċ\\ÎÝd]c[NKVFLEBaUmBIZGQ@JQSR@CUAEGBQ`SWYRMFgWGCGJCbNnIDGMEDKVAZUEqBYRa^WEUFKYQMaFWXEHIFWMYHCrXVIIiaK@aMCUYNSIISTwXALKH@XWXIEIJQCG[IEQDE_XSBaa[AIPW@]RS[FWS[CD]PEBYNGFSaSyJG]@ugEUDQlGHiBKHUIoNSKqHFaPMICK]UUHIPDJMuCA[SCPIDIOILGAEmU[POPBVSJDREBGS[QXWSGcT}]IO_X@TGHoHOLCX\\ELT@LYTD‚aFENF\\lj"],encodeOffsets:[[112385,19987]]}},{type:"Feature",id:"469030",properties:{name:"白沙黎族自治县",cp:[109.3703,19.211],childNum:1},geometry:{type:"Polygon",coordinates:["@@D\\RV]dTXELnHr]^@LETBBRTHPi^[@U`QTHDJ`MGSogDIPKdJ`WVNHCXHl_DJR@AH`FBVPUJLHKNTJOFFZON[ZEHFCJlMJ_ŒCn`CJVNGPLTNDFIdVTWEIPmRKMc_kDMWGGUTAtJLK~\\f{pqD[LAVXRCH{HC`eŒJ`}@W^U@I@_Ya[R[@MSC_aMO@aWFmMOM@‹haGGMEmaQ[@MESHaIQJQ……MckBIw[AOSKKAMPSDSLOAV_@@`KJRbKRDfMdHZERgAWVsDMTUHqOUr@VQXTT@Tƒfg‚L^NH\\@heTCZaESNObHPƒHeZF\\X^ElM^F^"],encodeOffsets:[[111665,19890]]}},{type:"Feature",id:"469002",properties:{name:"琼海市",cp:[110.4208,19.224],childNum:1},geometry:{type:"Polygon",coordinates:["@@TP\\pATHTGlZDJGAQjE\\Rb@jVBDCN`JZ[NCNHNXbULPrP\\KNbMTLjJJRFP`“pNLZz^FLRHjVPZ@hxVKbHBHMNNJFRlLzGPnNHhIrHHADcPWdUAmEMVQDSKYHY\\EhBN^HpXGNDBNNBnIß‹Å_g{³So]ã@ORO@KMEDIVYB[WJUICudGTc]P_YWaCOOMFS[]@MMYBgOU@ISHKQQkKMHYY[MSHwUit}KF\\KFMCF]EIUBETSROUKTLT[NKTWREfJbCHBZKTFTKh"],encodeOffsets:[[112763,19595]]}},{type:"Feature",id:"469031",properties:{name:"昌江黎族自治县",cp:[109.0407,19.2137],childNum:1},geometry:{type:"Polygon",coordinates:["@@`ZĤd–`òüˆ˜ “BSPGP@VSbQ`‡@]HC~T^SE]N]FkW]E[fY„GGOPaTMbFDYfS@g[MGK]h„e@SSSRW@UVqrPVGNStCXUhBFQGYNcCeLQQaLI@_`@EUwcEaCUaMc@SK]Du`MSkKI‡~BVNL@X`‚EvYŠwHcTU@MIe@SXJbIPNVCRXbWbSAWJCRXFFL]FMPSjCfWb_L}E[TaBm^YF[XcQk@WK‰Z“JYRIZwŒ¹ "],encodeOffsets:[[111208,19833]]}},{type:"Feature",id:"469028",properties:{name:"临高县",cp:[109.6957,19.8063],childNum:1},geometry:{type:"Polygon",coordinates:["@@jD`hNd\\^dZädĒH´Op@ˆùZY\\OAGIMN[[W_NCNMKU@NUMSNCTSP@`O@WSCCI@GXQSkXKX[IK@OWqH]SkWW@_SiiYQaKCAKZaCCw@MTGAMKM]FMMIMDSM_HGHRPKCBGSJJIYH[QOJCHMBDGQJECMTDQKFGTCEGTF`NFEDMFaGSNwIiTGhYJD\\KZODC^@FTKND`XBHKJNKFBNhG^FJMPcHEZF\\QPRjQTAdgNOPgQaRSê"],encodeOffsets:[[112122,20431]]}},{type:"Feature",id:"469034",properties:{name:"陵水黎族自治县",cp:[109.9924,18.5415],childNum:1},geometry:{type:"Polygon",coordinates:["@@R]NC`YL]FoN@V[vBXVFNL@TRZalnVFVP`DlOZkVSXEE_F[EUFeH[NKTgfCbMVU^@P]ZObZP@\\QhATUfAtUasñiāEoI]eYǯ@aKmaeƒWuCºKÜKpnbHbYfUDSNCPJTRAHJTDJSfDNLHXC``VBNGTYCQDIXMDSP@xLNEFRNXBIpVNLXah@RgF@`qOML@LJNSPLbaHAh@Jdj"],encodeOffsets:[[112409,19261]]}},{type:"Feature",id:"469026",properties:{name:"屯昌县",cp:[110.0377,19.362],childNum:1},geometry:{type:"Polygon",coordinates:["@@\\OnVBFKHPJCJOJTDB\\vDINOCGJVVL^JDONEbrGTLpMVJLGjAHGRkVChF@vH^zIbTETMHAZOFC^\\DXT\\EffAP\\PdAV@UIYfS|S@YPICMeM@sC[_A]VQEwyHSMuNcAUlQJMVGMS@mVBZPFO\\CSFQK[LqDMACiUa@[QiFBRIHYCHkGSBS[oSOqB‡IE^QHCRWHIXsHU\\UC}JEjMNAN_ZƒAIhSEYfWDQGaPMTL’ERZTJb``NHV@"],encodeOffsets:[[112513,19852]]}},{type:"Feature",id:"469025",properties:{name:"定安县",cp:[110.3384,19.4698],childNum:1},geometry:{type:"Polygon",coordinates:["@@JjDNdJ\\FbKPXfZ^Ij@RZNaVSc[MsMOHQPDJcLIJ_zCG[HQxWJBHXdENRR@XQFWZQQGOFSWUCI[WCJuRGLXNMPLhCl[Ta@SqGgJMGOmyHkKEQMINMAGaGULgwY@UOGiKQ]EYyMK”oO_QEIIKiNSMa[LqOKOaVMWMGMDY\\_IKrL\\ERT[DEPYOUA@nNTUHINkRBVMdNvGTxzRF^U`BD\\@tfNDNOJ@Z{TeTJZ@VU€cB[OBOeeQT@^OXBJb\\AbWTF`RCJFH\\RDJIJFXW@WLGBKxWTSJJMTVZND@bbL"],encodeOffsets:[[112903,20139]]}},{type:"Feature",id:"469035",properties:{name:"保亭黎族苗族自治县",cp:[109.6284,18.6108],childNum:1},geometry:{type:"Polygon",coordinates:["@@FJp@fxpQ\\ApN\\GNPNBM`HLMrXLXj\\PEHnI@WUCEM\\GTc\\GZYHTPBHRCPTd€H\\K\\@HXi–BJILJJAVNTOZJNtFPC`YxDPWci@IBgbGKaTOIM@KNKrP@_hE@QbgKWUMJoWAQMFEKM@wTONCJWRCZDHSAM_UD_GWMKeCITSCGIQBGXUHQoMEEGWDQIG]FMQBMaFGueFeSQDUSDSKOCSFMLƒUaPWM_PaEGFETMX]RCRR@HXKN@JNnXXEŒSPaDI\\£FkXWIAX]xB\\GN"],encodeOffsets:[[112031,19071]]}},{type:"Feature",id:"469001",properties:{name:"五指山市",cp:[109.5282,18.8299],childNum:1},geometry:{type:"Polygon",coordinates:["@@TCNOLBTLBPx\\AJdl†NR†RIbJTGNF\\@RcIYbmHoLQdKN_fCJYbDRRXKZFVEZVXBXIJBXMdESW[CUYHUVQFQAqsEIMPYMSBUIIJKAIj•GW[@[LGScDOGQOAGSYZ[HSd[HFNVD@XmJFG[OWiWKNqGKN_MAMO[HoM[BoRewo@Y^HpITSFENc`MVCdHNIVCLJFI`NFIŒP`@VZbaf[FFJG`O\\WRFA@PVPFPPH"],encodeOffsets:[[111973,19401]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/hei_long_jiang_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"2311",properties:{name:"黑河市",cp:[127.1448,49.2957],childNum:6},geometry:{type:"Polygon",coordinates:["@@VÈÞ@Žkx˜nXŽ°VÈa°V@kôw„b‚š„JVškXlVUx„„@ŽlL@xkVV°ƒ„VbxlVUnVxk@ƒ„ƒKkŽVb„Il„@°kVl„@„™lÆnkll@@V„VXƒŽš@V„²bUlƒVlV„U„VÇn@nkJšŽlkVbœ@›x²V@n°VUnlKU„n`@n°bWLnVUblVUVVbknV`°kkŽl@@V°@nz„J@XšxlWXb°n@bƒĠlbXb™bVbƒJ@Všb„a@„„@lbUbšVmnœ@lšVmnIW‚œ@WbÞ@„n@x°@š„ĢaƐéϚnœ„‚lČ¯ĠŻÈwm@ôçU™mm£Xy°UV™›@wÈ£Ǫ¯kõÝçUњ™Uķ‚ƒĢkVфÆšÞU°nŎ¥ČUĊx°m°¦żVƐœx°ƒÇ£@y„UônރÆ@Èĉ°Kô¦šW„kWU—bÇ»@™ÈĕWÇÈ£ŤU@›n£ÆUUKVamanwŃmÝJ¯k@JƒIkaVaUUÇbkaÆÑkWmÝUۙ™Ý@™ƒwnU±ƒ@kkV¯KUkƒJƒ¼U¦ƒšÅ@ówķaķůV¥Uaó@Åwmƒƒ_kVƒwĉ‚ĉmmn_V»™a@U™ƒVwķóƒ‚U¦LǫéóXÇmōLǓÇķxÝkƒƒĉ™kmakbUĶ°@W¼„@bƒšÈÆ@Ė™L„l@„°J¯„mkl¯L݃±L—amJ@¼ƒ„™VƧUó„™UX˜ċb¯ńVbkÆÝI@llx„k°V²šV@Uxގ˜L@b„@b™`ƒšÇzkókݤ@ğ¯Wƒ™LĉǙLmmnċVkbUaƒL@Ž¯„‚bU°ğL݂Ý@"],encodeOffsets:[[127744,50102]]}},{type:"Feature",id:"2327",properties:{name:"大兴安岭地区",cp:[124.1016,52.2345],childNum:3},geometry:{type:"Polygon",coordinates:["@@k›ƒϙmƏêġb™ƒ¯@@wƒmÝ@XV@IlŽl@bUxl¯VlV™bV@ULVlUV™_kx™VVV™ÈÝJ@„¯šU„™lm¯x@xóÒĉ¼m„¯Wƒxţ@Uz¯ƒWwnUwťƒ@knƒWƒ£óVƒUUwğyó¦WI—Vmm™I@±kwÇ@@bƒ@ĉ¼ó@¯wó@¯aó¼›KՃaUwmWUwÅI@aƒKó@Ua™LƒaƒVÅwō¼UUÝl±I—¤VxÇx@zkJmnn‚mbnz™xlŽƒl¯ČkJl™°@„kb„Žmx@x™@kêmVnŽWxôXšxU°„bWLóJnÇWĵ„V¦™ŽƒUUb™b™ÆġK™šk¯™VU±aXmċÑUwĉKġ„k„™ŽVxk„ÇKkbƒIƒ‚ÛXWl¯bƒŽ™X¯K™bĊš„„ÞVƚnŽĸ²lxUŽ°n°òÈb‚¦—xVbƒŽƒ@¯„Vx@¯VķÞČlĊ°KĸŽȘI°¤ČIôŽò»ƨnȰKǬ¦ôWŎÈƨwlƒnKVXmbX`lbšwkVW‚XXŽ„L°a„ƾaĊ£nƒ°@°¥ŎzÞ¥‚»œalwôkƒJ„a@ĶK„£„bU°ĊxźVÈUĠ¥ƨ™VI@XU°x°Ln¥šw°UmwXm݁V¥ĢŽ°@nU@mÆ£š¯lKœšÜw@aÅU‚¥UaÝIkmV²‚nn@Ķ»@Uk¥VKÞ@ÞÛ@ƒkVmĢa@_ƒJómƒǖ¯Æw—óÇa@alƒUwšwĢřšk@wÆWXUWXƒWa™m@_ƒ»ÇéXaĸwVa@ÝKkUWkX‚kšKXxƒn@lĊV@¯m¯nřÆwš¥"],encodeOffsets:[[130084,52206]]}},{type:"Feature",id:"2301",properties:{name:"哈尔滨市",cp:[127.9688,45.368],childNum:11},geometry:{type:"Polygon",coordinates:["@@°`„_šJlUšŽ@„„@V¦°JUšŽnLôlnŤ@@šÈaUÒVbkbl¤ƒzk°ÇVÛô°IlVUVôU„xÆU„Ž@bźĀ„º@¦šb@l²‚UVlœ@°ÒĠxšnXxÆVô¼Þ@Üx²KލlƒVÑ°UȰôlwô@²ƒĸ°„lanV@„šVŎUll@bÈnÜm„wĢ@la@ÝÞb°UXb˜lŎ²ÆškšV‚I@ŽnJnĠŽ°knƒÜbĢwna@a˜kÞKƒĀ„a‚™œ‚‚IVbU¥wĠwkô˜xnLƒċVçkaUƒ±IUmnġW„°WôĉšalƒÞÅĵ¯@W¹XÝaƒb¯a±X¯ºLƒaVƒmkLóƒƒbkaƒVUKVkkKV_@aÝykk±L@ƒÅU@yV_™aU¥ówÇx™@UkVƒn@lƒkÅlwšWVwUkĉmkklW@šašbVwnWWƒ—wWL™™@Ušƒ™UƒÇLšÇmƒ„@wƒJĉƒL¥@ƒÝ_@a¯y„UWw¯ƒ¯Uġx¯aÝXVmaU£ó±›¯nwƒa¯óÅVƒXman™„Uƒ›lUXkWa@mkI„›ğaƒm™IklÇU™„kĊƒƒzkKƒš„lU„ōĬlš™„@ŽnX°@llUxŹ²mKĉVWwk@UbUK@bmVmI—ƒVmwaWxXlWȁšmºšÞÆbUxV@ĵńWÆĉLkWUbƒaWzkbĉ`U„±LklōwUVÝ£™UW`Uwk@mk¯VkaõVX@WbL™K@XƧºWzxƒK@lmX@bkVVÆk¼Vbk@Vn"],encodeOffsets:[[128712,46604]]}},{type:"Feature",id:"2302",properties:{name:"齐齐哈尔市",cp:[124.541,47.5818],childNum:11},geometry:{type:"Polygon",coordinates:["@@Þ@ށĠKV¯a°ƒ@„KVblaČU‚mnnšKĊȚKX„°ŽĠ@Þ£ôllÈy„™š_@a‚ƒ@a—KݍVwU@±™¯Uƒlkw@kÞJlÅUa°ŃČaW—šVôƒƨVšU„ƒ@»nI˜b²Kބ°Klkn°ƒ¯I@ƒƒkšK@ĕÇń™@aƒX»¯@VĵlaÿVamI@aÅÝउýƒĊȗJƒôȁÅkmƑۃ@kxġ@@l™aVk¯»ƒīŹaƒkƒ¥Å¯™JUaWU@@w™aƒ»„KUkÆkUm„UmwÛ±±UUbUŽUXƒwWwÆÝk™lkUanaWwnKl™kal¯ka™ƽa›kÅx™a¯@™amb¯V™lÇwÛĀ™V@x™šmêVƜVV‚aôV„wÈx@šˌx„¦VÞ¯VšlmX@‚ƒL@¯Ua¯LmV@„„°X„ċK™V™ƒ@UƒÈ@‚¥@w—ƒġIU™km¥Źwƒ¦¯lmn@°kxVV@¦óam„n¦l@nx™lĉVóšmx™n™ÒĉĀĊ¼„þ„šǔêÞ°ˌĠÞÒ°ĀɲĀƨźˤȤƨĊ°w@£nymwnkUUV¥ôÑVmkÆmUUVa™mVIkmô„lxkXÞþƒbl„ƒl@kV„ƆƒV„xV@š¼VÒ@šŽUŽšnnނJ"],encodeOffsets:[[127744,50102]]}},{type:"Feature",id:"2310",properties:{name:"牡丹江市",cp:[129.7815,44.7089],childNum:7},geometry:{type:"Polygon",coordinates:["@@U`lLUlVL„Ulb„aô„lKnŽU„„b‚K°¹²W°b„aÞb˜knyUlUkamř²L@m°@lšmš²n`ôÅlK„x„ÜKnxV@„l@œƒ›ÅXyW_k@™wm™ŹĕmƒX™»‚ƒÛ™l°ƒôšÈ„»š—ô˜ô_WW@Uœal»šwU@@wšUVƒš@VƒXI@w‚Ģ͑ÞȻ›aU_@mUkly@¯óV»XmWUXUWmnm¥nUUaWLk»Æ²IÇa™wÅaÝ°¯nUa±a™ƒ™@¦õÆğ„@„™@Åb›xU܁nÇłlb¯¦„ôó»mƒ—@±ƒUk@Wwƒa¯xU„V°ƒxXbǎŁUV™™ƒK@¹ƒKUaȯ@ōݙXƒal™ƒlÛkalÇUǫÇńÇakbÝƆ¯nlš¯Ž@¼™VUx@x¯W¼™Æ¯šmĖ„Ĭ¯ČƒVk‚ķÅmxœ°ô²V¤‚bUnÞW°bĢw°V°„XxƒV°z@bÞ`@„‚¦„KĊŽ„I@xƒŽn„™ÈÈK‚„šV™„@VššXK˜xX„mXUx™a™b@‚kXllĊnVlUx™XkxlÆk„m@U„Vlš@ÈwôxV¦šbU`@zÆV@„²KllÞz@b"],encodeOffsets:[[132672,46936]]}},{type:"Feature",id:"2312",properties:{name:"绥化市",cp:[126.7163,46.8018],childNum:10},geometry:{type:"Polygon",coordinates:["@@ऊþÆÞ@bnJUb‚ĀnblŽĊš„„ÞlĸwǔÈŎKÈnôWǬê‚KV¥„ĸôUxš„@VšbU¼m`nnĊŽĊ„xlUšmkaVÿšLšwš@°»UmbKmݙUšwUmVknKUUl¯ƒKU™ƒUȃ‚™nK@ĠkX±lX„°„L@¯¥@wV_m›ĵ¯Ww™L¯ƒUkōƒÇVU™l›w—V󁱃¯aƒVka°wVk°mÞ¯Ŧřƙl™²™Ŏk™U@ƒmUkb¯ƒķŽ±„ó@kxȯó¯VUÒk„ÝŽ±LÛwÝ@ó»ÅUWw™mğw¯Ñ›@UkV±@k™a@¥ƒ¹Źÿ@aƒÅVƒwóVVUkU¯JÜóÈUl¯„yk£laUaVÑÇb@™ţ@kmómK™V¯IU¥ƒ@@ƒ™kV™Iƒ`@ô™¼„blU„lƒ™bÈb@xÇKkĢɳaÅɆō@ƒŽVƒK@z™@@¥ÆKnÜ@@aۏUw›wnU‚ķ@ƒ_ƒV°Ž@„klVššnULVVÞbVl@°™@nx™n°LŚÆlV„ȃmU²@VmĠLƒx„n¯xkWƒzšJ‚wnLmbXbW°šÆ‚™²™@™Žšx@JVx„L‚Ā²Æ°I¯º‚È@ÒnÈ"],encodeOffsets:[[128352,48421]]}},{type:"Feature",id:"2307",properties:{name:"伊春市",cp:[129.1992,47.9608],childNum:3},geometry:{type:"Polygon",coordinates:["@@ƒKƒ¯kWW²ğl@ŽmLšÇ„„VVš„Lk°VVmLUlVn™xšVnނLnaVŽ¯¼™@™x™KUĀlb™n„`n„Æxô@VbU¦ĸŰĸbôxÆ@„™V¥„»„IVl°LUŽll@²„mV„x@ššÞܚÞVnŽlXÅÒlbÈaVVUblb„J@I°lÞIn‚Æ„mxnbUbVLÅVm¤@œţVǤXÈÇĖ@šÈ¼˜aXVÜaXbWŽnzŎašř„KôbšUlw@¯naÆKnUU¯Üa@mkkVUĊm„™żÝ‚ǖŽ‚K„™°L²lÆI@ƒ¯¥ĉƛVaÞk@ÝVaĠlnUVwƒœómaƒ@™wĉ@™a™VƒxamX@aƒ@UaÅLƒaVWƒ_nWm£nWm_ÅV¯ƒm@m„󤁚ݦƒ¯ÅalmX£ƒ™VWUŚw™mÇ@@IV™„WUw@ašI@„k@wŎ»Wƒ„ƒ™ÅVaœK›Ika@¥lUkUlwÅwVyÈwWU@a¯U°m—Ç@UçƒaVa¯mV»ÅwÝUlƒUk™V@k„mUk‚X£šw°@@ǃaÝIƒƒam™Ûam„¯lğmmI@J™U™l±ÅōŽ—kWa¯VÝa@Þkbġ@ƒxÛnÇm@akkōVōl±škšÅšťŚÝ°¯nUl¯xlb„U°b²„ô‚˜Uœxšk‚VÈUŎ„Vl°„šKXxĶ°nœU`@x°¦@"],encodeOffsets:[[131637,48556]]}},{type:"Feature",id:"2308",properties:{name:"佳木斯市",cp:[133.0005,47.5763],childNum:7},geometry:{type:"Polygon",coordinates:["@@nš„b‚„ÞJ„b@ȯ@™xW¤Vlƒn@lšUVlk„ÞVÆxU¼°nUb„bVèÈ@˜ŽnIn‚@šĢmlUw°™żƒ‚VUn@lnL@VôbšwĊ‚lœ„JķĸĢl„wôwƨxVVUƒŦšxšLź™Èš°`nnĠwŎJސĶwôJ„@¤Xn܄ĸlšn°¼È°lŽ„„Uš‚b„xš@„l@ÞÞÈm°„lôwšL°¼ĸ‚°Þ²nĠ@ôwÞ`ŤI„V„ÒĠU„„@„VJĸbƄ²@°ŽĊKšœ„JĶaĢȰ@ô¥°nš¤‚bČUš@Vx„mUw@a݁ţƒÇ™ķƒ@ĕķīU¯²@ÆmVÑô¯X¥ċç@™ĉ»U¥ÝţKWVÅkUVÝŎUmǍÝx¯aķxÛUóL¯a±óōb¯™ƒÑŃVÿƒ_Åķ„a@UƒK@wm@Van@UmmLVa—@VImmXUWƒÝUřƒKUwÝUUƒkVƒk@l¯X›‚Å_ƒJ¯k™Jm„ÅLƒa@¥U@¯Vƒz¯@ƒ`@¼šmxƥšŏKÛk@±laÛ@@Xm@™ƒ@xƽ@WŎnšˣĕÅ@@aÅ@@nÝbǏ¯@ƒ_U›kUWƒkb™wÝU@ç„Wlw@anIƒ¯lyœX°m°VšašÛšm@„mVwÞK°ƒšXlaXmm_ƒ@UƒkwÝK@ƒVI™ƒXmV»ƒI@aƒ¯ğW™bġaU_¯JU¯ġŽƒ„ĉ„k„ō`±nÝÆk„™bóĊ¯Xƒ‚ĢX‚mVn²JV„lbUè„ČmK—wlóğx‚xV¦UaJ›šƒbƑÿÝL—l@bmbġx"],encodeOffsets:[[132615,47740]]}},{type:"Feature",id:"2303",properties:{name:"鸡西市",cp:[132.7917,45.7361],childNum:4},geometry:{type:"Polygon",coordinates:["@@‚LšKVVnkšbVšÈb‚²U°VnklVlaÈL@anU°ÜmXV`œnôLƒèšxlŽšLX„˜L²ašVVmÈX@ķ˜lnU„Èl`ȹš@ŤŽ°U@x„KnnV„mlnnUl‚lVnnaŎwlVÞ҄@n¦šLVŽ°lšwVk„Lšaގl„n҄š@xmLÞ¤Wnœ¼‚WÈLVVUxlÈô„„WVaU_VKšKXUÆbn™‚nôK„bÞw°bÆWXamVwœK˜™Uw¯WUk„UlJUwVUa™@@kmyzm›ĉw@kVwškƒW¯ÅKU_Vmƒƒ™xU@aW@@kK@w„a@Kƒ@@kVUƒaky°_Vm™kna¯K@™ƒL™wġk@@IÇóX™ƒwVakmV@mwXUWanƒlĉ@ǙUw™KƒƒóšܛNJۄm°@›w—Å@ƒ±b¯Wƒ¹„WVwŹĕ¯kVmōb¯w@aƒwmV™UUb™V™IkaVwķ™xk¼›b@VXXó`󗙘ƒ¼Çó™¯„kŽÜš„š¼WŽn„źĖnššxl@X`WzœÆ"],encodeOffsets:[[133921,46716]]}},{type:"Feature",id:"2305",properties:{name:"双鸭山市",cp:[133.5938,46.7523],childNum:5},geometry:{type:"Polygon",coordinates:["@@™UƒƒUwó™mÑÞÑUÝÝUkmmŃyV¯ī„¥ƒUÿĉ¯mÇkaWbÅX¯aÝxƒaóLmmšÅaWV™LULV`UbƒXóƒkÇVwUUÇKX›»XmÝ£nK@wƒ™mÑkƒÝ™bƒKUl™x¯kU™Km¥ƒ@ÝÑkUōxmbUmkVkmmnkUƒmmƒL@w¯Vţ™@Ǻk_ƒÇmV—k@ĸVx‚VÈ°lLkllšUbōwƒnVW¼nlUx¯XmWUnÝ@™xÝUó¼¯J@LVbkJWnkb™W¯„ÝLUxƒn@‚™n™Ü™b¯U¯n›Wkz„°mJ@bkxƒX@èÞVšxlaX„lVVœ„`°@ȐÞa@mÆ@@bÆ@ˤĖm™Xōƾ@@wš„n@@WÜ@kb@²ÜlŐLƦ™nw™@»„_°@„y°UV@@¦„bÆKnƒšI°l„IÆ`œ°W@k„llUV„ÞVVx„LƚÞVX„WVnnUJ˜@UbnKVnm@Ubn@@x„L@VƒbÆĸ„`UĀƄ„Ò°šŎa²ô°bôKÜVĸw°bÞwȎVnÞōVUÆlXU"],encodeOffsets:[[137577,48578]]}},{type:"Feature",id:"2306",properties:{name:"大庆市",cp:[124.7717,46.4282],childNum:5},geometry:{type:"Polygon",coordinates:["@@mÇ@сǰ¹¯J±ÅÿƒKUw‚I@™wšš@š±Å‚™X¯WanamKx™I„ylX°wƒm„wğKUn±@nVDŽUƒÅkƙ¯Kšmmwš@@¯UkÝaUUVK™mU™lk@ƒ¯„U„`ĸ@V‚mœxVxܐ@bÛ@m‚ÅL@¦š@@y„L‚U„Ŏ@ÆɅɴblġÈL@wÇaša„ƒkkVƒaš»@ó¯_ÝJ™wÇaÅXny›U¯¥Å„@w™bÝa™Lmm@@ƒVUŽlbğVmš™¯Xƒm_ƒ`¯_Ux™m™L™a¯b@mƒaó¦Çk™¤V„@bóJknVx™VXx±aƒLUbVxkLVlLWlƒ@nX@VÅbWlÈnƒx„bWšÅbmŽ@xœbml°b™„XbW„XVmnn`ƒLmšnbmb@šk@mwU@@š¯Jlbk°lbkšmLXxmbVbkllšÅނxX„xVWVVa²VܲnxƒVVnÅlVlƒL„¼šb@xV@XŽVbšIÆ°„¦„lźb„Ĭ°¼Ulšb@kĢ@lw„@ƒÜlnȂƄóȘI„ĉ"],encodeOffsets:[[128352,48421]]}},{type:"Feature",id:"2304",properties:{name:"鹤岗市",cp:[130.4407,47.7081],childNum:3},geometry:{type:"Polygon",coordinates:["@@Þ¥‚™ô£nƒn@°„ÆUn`mXn¤mX„`UX„bÆKVb„@@bnW‚b„wšUšbĊ@šx„@nbšWVmƒ_mm@ó»Um„ŘWXkĠ»²¯‚¯nķšwŎ@ĊšŎK°bĸUnјKȦĠÈbÆknJššÆUĢV°IšŽšVƾƒwaV™ƒƒkÇ¯¯»™mķkۃWm@£ƒóIĵxݏōIğxmm¯_ǙŹš™K™wťŽ„UVUŽƧwóxƒxġkĸķƒIk›ĉ™xóa@UmK@kVmUŻ„¯šVxkŽġn™‚@mmJ¯n°V@bXVÇxUzÆxkxlVkV@¦lbœJ›LUbšÆƒ„X„ō¼@xƒl@™J@bVxƒXUš@JÈ@šn™xVÆUXš‚„W¤knÆb„°"],encodeOffsets:[[132998,49478]]}},{type:"Feature",id:"2309",properties:{name:"七台河市",cp:[131.2756,45.9558],childNum:2},geometry:{type:"Polygon",coordinates:["@@²mŎ_lƒĊƒ„ƒĢV°°IV`ĢbšaĠX„°@b„JU¼Wnš„UJ@„ÞLlxV„„@n`lIUa@K°Iô»ÞVšwÞ@VmnX°WVwmkX»‚U„mŎxVak™lkkKǯUUwÇWUn™U±b—KWƒ™Kk™w„çóK›mU_nW¯ÛmV@bÇKkbkUml¯U±VÇaU™™amlUU™LK›„k@ƒU@mwÛLƒŽƒwkLóÆm_™±™nkŽ¯@@n±KnŚlbkVV‚mz—lWXº@Ķ°"],encodeOffsets:[[133369,47228]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/he_bei_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"1308",properties:{name:"承德市",cp:[117.5757,41.4075],childNum:11},geometry:{type:"Polygon",coordinates:["@@lLnlmxn„„IVVlUnb@VVxXJWL@LގVnnV„J˜_@wkmšK„b‚x„wXk˜WXXšKlb²K@nVVVb„L@WlU²„lKVnUJVz@VVb@lżmVUVnbôaVX@°Ub@lWbXš@b@bVb°x„@VxÈLVlšaÆ@Þb²k°@lVUŽ@Xn@VW‚LXb@¤VXšKVVVLnm°_ƨ¤@aUIVa„alkX›°k„™V@„alwUVy„U@k󙰃na°UVUUmUÆw@mkLVUƒWVI„WšLnn@xlVnK„myU@ƒU°UXaV@U¥ƒU@Uƙ@aVUkWU¯ƒaU@WLUV@bkbmKULmKkUVUkmVIUwlWV²™Uml°U@W„LUwVm@UUK@_ƒKUUÜaXw@ƒVKUU@mVIUUlmnIVVVbÈVlKnbVKš@nI˜@nVnwVLVK„K„„˜Vnb@aUIVW@In™°@lVnIš@lWĢ@°UVL@b„@VyUUƒa@w@WUnU@Wǯ™K@UkkJWaÛbmk@mVaÞU@amkWƒ@mXUKkÿƒ£@a„kl@Um°UXwla„al@nmlXnW°znW@aƒwV™@ƒakbĉ¥VmU@ƒIƒVƒUƒJkUmWU™KbmkUaƒKkUVU@KV@@klw—™WaU@kmƒXVènbmlUUƒKƒX¯JkbƒI@JmIUWU@ƒLml@XkJ@U™kƒK@aVKwWa—IWwƒmUƒ@mU@J@UaċU™aUUƒVkI±ƒk@UUƒ@UbVVm@UVKƒLƒlkIWaULUWƒXUJU„ƒ@WbUb@lkXUxm@@JVn@J@b„nƒb@Vkx@bšLU‚Æn„JšaVXnKVVmzX‚°V@_lJXxWXƒK¯bÅamUƒ@lUI›bñJ@LÇKkIÇ`kxWL@„ƒ@@bUVUb¯xWKk„Å„VlULW@ƒŽn¦Ul@I™lmUUUVm@kWƒnkKma¯XUKWmnwVwÝL„mŽ™VUbUVWb@Lnxm„xVŽmbXx›¦@„nb@`™„ƒVƒ@kbƒLU„mVUlkbVXkºmnm@@xk¦šbĢÜlš"],encodeOffsets:[[118868,42784]]}},{type:"Feature",id:"1307",properties:{name:"张家口市",cp:[115.1477,40.8527],childNum:15},geometry:{type:"Polygon",coordinates:["@@k™ġۙal¥@wn@nml¹UWlaVknUVƒ„Kla„@„Ušƒ@_ma@ƒœ¥WwnaU‚wnƒmw@KXaVUVašUnmWUk°™lƒnUVUXWVw™IWVóKUI@WXƒxUU@mma@kUKWLkw@yk@ƒaVkUUċaUU@Wk@Unm@UVmLm±IUƒkJ™kWƒ@a„I@m@U„ƒVƒ„Ula„@VXVƒXmVwnkWKƒKU_k@m¥ƒmX_™JmnU@km@U@KmU™VƒU@U™@Umk@@LƒmW@Û£Wƒka@wk™@aƒI@mmk@mUa@UmUƒIƒwW@aWUƒbU@kbÇ@kwƒ@makVUk™U@aƒm@aU@mxkUƒbƒKUXUƒ±KXVWLUK@wkU@V™@WXUa@WbUxƒJIƒŽ@¦VèVVX@±ê¯KUIƒ`¯UULVx@Vƒ@UKƒIƒVkLmVkKmš@nUJÝbkIUJVXšVVxVbU„VJ„Un™°bV„mlU°„XnK@Ul@lVÈVUXšx@W„@VXšV‚KÞb„n@VnbV„m`ƒUx™kW@UVkL™Km¼@lUnUJVnV„XV@Vm@@LV„klƒIkl@VƒWlŽULWKUL@mJ„@blbUVUlmzUJUxm@UUbċÜk@Ub@VšLVV„¦ôbVŽmšUKUkU@m„„@VlVn¼WbUJ¯@@„°šnIllÈl˜@nXšWlLœk‚J@bkxlxkxlXUlklJƒšXL@bW„n`@nƎXxlL@xl@Xb‚LœKlVlIXblVUbUJW@lX@VL@VVŽšXšJšw„n@WnL°K„bVbl@VI@K„@U@nmVmV@XUWI@aXm@™VUUkWmn@lmUUk@mUmK@UnwVĉ@ƒƒmU_V@XJôVVUšLVUn@šllUnJl_n@šml@XŽlLlw²LVJUL@VmbVblVXmVnlš@Ť¦„nn@܎@bšl„@@XV`„Unb@VlLVb²J‚Xn¥ÆÑ@¥Þ@"],encodeOffsets:[[118868,42784]]}},{type:"Feature",id:"1306",properties:{name:"保定市",cp:[115.0488,39.0948],childNum:23},geometry:{type:"Polygon",coordinates:["@@VbXWš@@UlV@xVLXKWU²LV„VW„L„alVnwV@@b„n@bšVVllUnb„@lxÈ@laV@„aXV@b‚X„x„J‚nV@VVb@nnl@n„J@blšl@„ašƒU_VWUwVUškUm™Ukb±mVwœU@VIUW@UWk„@VU@ynL„m@IV@‚bnK„LVaVmnIlaXwV@@WVL°@@xnX„@V`V@VbUVVLVKnwnL@ll@@_V@VVnaÆ@œKVXÆ@nƒ@wƒKmU—™Wm@km@kÜKXU@ÑW±nIUwVƒ„Kla@I°wU±kškmm¯mƒ_ƒJnƒaƒwW@IVaUama@wƒUƒmU@mVw@aXk@mWa@£km@aƒ_kVmUnWW@¯bƒkUmk@ƒVÇm@@kUU™KUU™@UVUamVUaWIkb@xU@@amUkKƒVkam@@kVUkUWmKmUkLUb@xmJƒ™U@UImVÛVmnUwƒJƒU@VƒX@UWm@Ub°¦UšmxklmX@`ULU@@UW@@xkn¯@makV™UmxUb™°ƒlUšƒbUbƒnUJƒUUVƒa™LkbUU›JUU@mUUUƒJkaƒ@™xUIWJƒUnƒJ@V™zƒ@kb@`@bln@l™bƒŽ@X@š@š„@Xl‚bnbVb„@„„VJlInlšbVw@U„K„l@lbnan@Vb‚JôLn‚UzlV@lÈLVbVK@LVx—VWXX`WxXz‚bV`UXV¤nx@„bVlVnVlUL"],encodeOffsets:[[117304,40512]]}},{type:"Feature",id:"1302",properties:{name:"唐山市",cp:[118.4766,39.6826],childNum:11},geometry:{type:"Polygon",coordinates:["@@„@VVl@²„lJ„UVVšbČVVb‚@@InV„@‚V„nXx˜JXb‚xUL@b„Lšl@VlI@Wnk„KV@VXnJ@I„Jla°I„W„LVVnkmaUç„WVkôaܯ„@nV°wnJlaV@VUnUUaW¯wXWWwna@£UaWKU¯ƒ¯@aVUkKUamUUƒn»‚an™„IVwUWlkš@„LlWVakU@K„_lƒšbÞU°@šy°n„@„KÈkWW™ţ¥ĉōƒkġWUw¯£¯ƒÇwţwƒ@kK@kƒ¥ÝwÅbǤېťV™lW°@ĸ™x@VVVULVLkl@V@Xƒ`Ub@Xm@UWbƒk@ÆVbnLWV@lnXUbl‚@X¯lmU™VkKWLkK@_UK@U@UmmUxmVXLWVULkU@`W@ULUK@XlJXzV@@xml@VU@UX@Kk@WbUK@Xn`ƒXmJnšmškxUVbUVlVVxUbV@nKlL„kVKÞbVKXI°KVšmVUIUKULVxVJVLkV@Vƒ@UbU@WUU@UbUK@b@nƒV@VkLmb@b"],encodeOffsets:[[120398,41159]]}},{type:"Feature",id:"1309",properties:{name:"沧州市",cp:[116.8286,38.2104],childNum:15},geometry:{type:"Polygon",coordinates:["@@@ln@UȄŽl@Vn„l°aX@mXnVlU„`@bln@¤Xb@nWl@bUx@nnV‚„„V@xnbVbUb@J‚X„x„b‚mXa@k„UVwlW„k„KôVm@w™kkK@kl»Èƒm™VKXkla°@XVV@VI@ml@@Vn@VX@V@J„@VxUzVVšš²blVk¦@šĠ@@»š@VK@VÈLlK@XnJ@alIUl„a„VVbš@„n@a„U@WUIV@mUn@mKXml@lL@LnWšb@XV@@a„VVb„V„@VV„IVWÈb˜IÈ»ƒǟlWšaVUÅUƒƒ™Um@kVU™WVkaUwmaóUƒJUU¯ÑU¥mk™¯UaƒKÅnÇyóXmWÛX¯aċbÛa›J—W™ÝU¯»ƒaóóUm@IƒšVVl@bƒLUJWLX@@xšXUxl¤V@V„nVUV„XVbVš@Ž„@@VVn„°VŽ@ţU¯VƒUmƒUWV@mUXƒaƒbUKUwUaÇKn„ƒVk¦Wb@VnLmV@bkV@n„xW`Å_UVƒV@bƒUklVX@VmlUƒx@VVL@x—VWVL@VW@UUm@"],encodeOffsets:[[118485,39280]]}},{type:"Feature",id:"1301",properties:{name:"石家庄市",cp:[114.4995,38.1006],childNum:19},geometry:{type:"Polygon",coordinates:["@@la„@šy@U„I‚m„VXIVJšw„@lb„IVVnV‚@VVœIVVlašK„bVU„VVI„mVa„aV™„kš¯VanwšVlUnb°@lm@wX@@VV@VK@_nWlknwV™¯¥Van@VX‚@„W@U„V„IVxnmÜUnUVJV@„šnI@wValKnV@k‚mU£na@mVk°K„LVa@UU@UƒmknWWkXU@aWW@@km@UaU@@klK@UkaWaUnamm@U„a¯wWU@UkƒL@ŽUn@x™V™lUXVJUb™LmU@aUWUkmKkLUUm@mW—XƒaƒmmkkWUm@@U¯JUUm™kU¯@mKĉxÝwÝ¥LƒUóŽmwkUUUWVkKm™kKmLX„lxVLVxXJ@nVJnz@VWL@`nX@šƒxƒ@kVUUmJmIXx„JV„ƒnUVƒ@UVV„@LUšƒ`UXVVƒ„ƒlXL@l@b@VmX@b™xn°™UƒbkKWLXlW@@bƒK„mKULmakLUlmb@šXb@xmXU`V„b@`lLx@nWVXL@‚°WlXnlb„KVK„XVb@˜X@l_lJ@V@XnŽ„I"],encodeOffsets:[[116562,39691]]}},{type:"Feature",id:"1305",properties:{name:"邢台市",cp:[114.8071,37.2821],childNum:18},geometry:{type:"Polygon",coordinates:["@@nKlLnšlLXUVVlVnxô„V‚KÞ¦ÞxĊwnL°@lVnšVV°I@Vn@V‚lXnl„n„b˜WnXn@VVlKnLVlVX@bnVšKVaUIVWškšU@wVm@¯@U¥VmU_°lšK„k‚w@LX‚Va„U@wšUƒUUKlUóW@UVUœUlƒ°K„wlKU_na„KVnlKkkšWWa@IœJVa@IlJnU@„KVUUmVlaXUl@lm@kXWÝÑnkƒ™±™k@wğ›@@U@mKĉLmVJ@zmlnŽWLUÝJU_ƒ@@šmJkXUVlbklÝ@Ýa™b¯@¯±JÅwġaUU@ƒkU™@mVI±bUKƒL™WUXƒJkaƒLóKULWbUVkKmnk@@bmLUŽƒl@b@mnmJkUULƒaƒbnŽmn@lVV@¦n@„l@b‚znx@`Vz@b„xnV@xl„lbnKVx"],encodeOffsets:[[116764,38346]]}},{type:"Feature",id:"1304",properties:{name:"邯郸市",cp:[114.4775,36.535],childNum:18},geometry:{type:"Polygon",coordinates:["@@„bVKlVnInm‚@@a„kVnK@al@nmlLVUXaVKôL„Klb„IVWšX„KVL²a‚JnUš@lV@„VVĢbÆx²I°Ž°@šaÞbÞ@lkkaVUlWnI@™„@V`ÞI‚VXKmnk@y‚InUĊKƒÇkUUamUUkƒƒ@aU@U™ƒk@WUwVkVJVkkw°a@„mK@UX@VV„LVW@wšwVa@¯Xm@@lUIWaU@UWkXWmU@UwmUkKmn@lkVƒ²™VƒaULUVmJUUUwƒLma@™UmkIUm›L—mVšmx@b™LUamKÅL@VmbkU¯KÝamzkJUb±Vkb™L@lU@WIkJƒzkKmKƒnUalWkkKW@@nkbk@WW¯XUVUJ@XlJ@Xƒ@XlWLkUƒ`VUnaWa„UV@UVIƒaUxUUmVƒK@I@W@DŽU@@U@bƒ‚@nmKXmx™@UxkVWUX„@`VLlL@`™zX‚Ýb@b‚„@VUVkIUJVz°KVlnLlKnL„xlLVVUVlXUJ@nn‚„I@mVUlbn@@Žm„@bV„nV"],encodeOffsets:[[116528,37885]]}},{type:"Feature",id:"1303",properties:{name:"秦皇岛市",cp:[119.2126,40.0232],childNum:5},geometry:{type:"Polygon",coordinates:["@@lnV@Xb˜škx@lU@@LUVlV„LVbnl‚ašLXVVn‚l„I„V„U„JV@UnĊ¦la„bš@nJ°UmƒV@„wn@VU„JVI°bnWlXnWVLVK²b‚akk„lI@aUaVƒUwVUUalaVwnUVak¥šX@W‚kœLVÓm„mUK@_lWš@n_UK@alÅ@ğÅƑŃݍmƒ@їţÇlƒLƒ@¯m™z¯@ÝV™ak„ƒ`@LlVUbkXƒK™@klVXUxƒJmšbm¼V„nVVblLUV@b„°V°XLVb@¤mbXxWX°xXŽVbmVUVU@kbmI¯xmUƒ@Û°óbUl"],encodeOffsets:[[121411,41254]]}},{type:"Feature",id:"1311",properties:{name:"衡水市",cp:[115.8838,37.7161],childNum:11},geometry:{type:"Polygon",coordinates:["@@„KVlV@X°xƒb@VnnmbVŽXblb@VkL@lV@Vbn@@l‚@XX@bWVXlmXnlV„V@@VUbƒK¯LUl@nmbV¤n@l‚LXnlVUV@ln@lb„UlLnV@bV@@wlaXJVbnUVbVUš@VVšLVVn@VVX@@U‚KXU˜U@wUK@U„wVnk@UUWlk„V@a„UVUÆ`X_ƒw@mlU@anUmK@UXal¥„UmƒÈLVbVxVL„a„bVW@nXU‚Vn„„V°UŤV@Uƒ¯Um@Uƒ@@U™UaƒWVUmUUƒU@k£Vw™W@wW@XKƒIUa@wU@@al@UK@_mKXKƒbUU@aVKmš@Xmƒƒ±@kbÇakLğVaUw@a@ƒmkUJƒk@ykw@£ƒWX@lknk@WVkbUŽVnUVƒL@‚mVkI@JUb›I@JXb™XllkLUmƒLmbV`kLƒx¯Lk„›VUV@VôXkVVL„V™V@xƒVUbW@Kxƒl™L¯kV`UnV¦°@"],encodeOffsets:[[118024,38549]]}},{type:"Feature",id:"1310",properties:{name:"廊坊市",cp:[116.521,39.0509],childNum:9},geometry:{type:"MultiPolygon",coordinates:[["@@la„Ušš@šUnL@VWbklWxnIVV„V@X„JlbUlšXVbn@@K„mV@@X°WVInJmn²@lmVbnL@amKV_kwlmX@@LVamaXaƒaVU@UnJVanLlUkaW@UaVakK@IlKUU@an@ln@alKUƒkIVa@a@klaUKUV@UkUV¯šKVƒV@kUmƒU@@a¯ImJUU@VV@UL@Uƒ@@WXUWa@Ukwm™@ƒX@@w@al@@aVIUmVUUUVWUknK@I@™l¥kU±a™™UUVyUwƒ@@I@UUWm@@Uk@@nUJU@WU¯@kbWlULnšÇ„k¼@llLšl@xUnóŽƒLƒlkXUxƒV@lWb„I„`°nnn™llŽV²¯x@JkbƒLU„VxmJX²@ÒWVÛL@lln@‚Xn˜šnV„L"],["@@@kX@Valaa@KWI@UXW@WanaUIW@UaUKķŽk_W@UVUKUš@bƒ@UamxVXnJUbWVXLVbn@W°kb@U@Wó¼mIU¼k`V„@bVbl@„lX@lUôVlUœIV`lX„Vn@lUlVn@„l@UVaƒIUWl£Um™VWU@@UUKlUUUnƒVL@KšUnLVWUa›@™U"]],encodeOffsets:[[[119037,40467]],[[119970,40776]]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/he_nan_geo",[],function(){ +return{type:"FeatureCollection",features:[{type:"Feature",id:"4113",properties:{name:"南阳市",cp:[112.4011,33.0359],childNum:12},geometry:{type:"Polygon",coordinates:["@@lKl@nVV@„bn„@VVnm‚nL‚LXx@š„‚VLlKVU„IXWÜ@șlbl@XUĊUlwnW„LÞw‚m@ÞUVmnVl@nX‚JXLm@VnnJla„I@VkxVb„@VŽln„J@knKVn„@°aVanal@XK°b„‚@š¯VJXIš„VK@al@nV„k‚@nK„a‚b„@XL@blVVKVLXK„@VaVI°mVaX@V_@a@yUkVw„VšIVašJ°™@anIlaV@nKnXÆm@wUUV±UUWUKnaWwXUWmŁ¯Vƒam@kakImƒUKƒ»lan@VXXa˜W@@UlUUa@a@UlwUƒV@Xal@@anIVaUK@V™XmwVmUmV„LXl‚@nalLnal@„šnKlkV@@UnJ‚UXnl@nVl¦V@@VnJ@nUVVVVIn@Va„JƗn@@K@m„kƒa@kmWVaUI@a@™k@@aUL@mmaVIUKUVƒ@@IU@mƒUmmL@K@UUUU@mW@@nU@ğ»mVmbk@klW@UXnV@LƒJm„™lUnUJ™UUUWƒƒ@UnkKƒxmLa@ƒ@@lUU™bmUVWk@@nkUmam@UakJU_ƒVm@ÅlÇLUVmVUwULƒKU@ƒk@UƒVUlU@@Uƒ@UaUUWaŎƒzJƒaWLkl™b@bmL@„kKƒabWŽUVƒ_@mV@b¯JmXUbUK™¤ÇLUU@b@JkLWmkUWIkJ@VmX@JUbVXU`¯VV¯blK@LXKl„UV@Um@@Uk@kxWŽkbƒL@KkbmL@‚UXmaU@@l@x@blX@xUJ@bULUlULÇ@@VšnU`W@@nÛ¼U@@VmKUkm@VVX@@xǚ@bUbVb@VX@@x‚LUb@lƒ¼XLlbUlVVU„Ub@n"],encodeOffsets:[[113671,34364]]}},{type:"Feature",id:"4115",properties:{name:"信阳市",cp:[114.8291,32.0197],childNum:9},geometry:{type:"Polygon",coordinates:["@@VllInJlknJVkVU@mXlUÞ`VnV™VU@U@y„@nXlKV„nJVkXKWaXI‚b@yVk„VUkVwn@‚K@nW@k„KlUXVVUlbnUV`n@V_V@llX@@V„b@bV@@nlVUb¯‚WLnbmb@ŽnLnK˜b„U„bVWnLlaX@VVUX@Vln@`kL@ll@VXVJÈIVl@XÞJ°Una„LlylU@UXKlnn@lanLWWnbVI@KXKVL@LVWVL@UVKUIVWX@@XÆJ@In`@lJVI@a„WšÛnK@UlK@UU@VK„nlm„nXal„UllLUbVVšknJ@nV@Vm@a„l@@xnV„„lJVUU@™w@aƒk„@XW@_mWnUlŁUmVKV@VXwW»XƒWaUwnkWUkVUƒU@@@WlaUkkaƒIWVkm¯xmIUmƒLUVƒaUIó»m@mmwXk@a›mk¯¯l™@wƒmkLmmU@UbkUWJ@XUbƒJ@b@l@znÆmK@Xk@Ub@lm@ƒI@akmVKUUVUkU@U±JUbkƒ@IWmkxƒa@UUV™UWVkIUaW@UlLWn@VkJƒI@VkK@L@bmKƒkJmUUaUKWXk¼VxnJ@„V@@VULV¼ƒ@@UkaUlWL@U@W@IkKmL@KULUWULWKUXUJmIƒb—KƒŽƒ²UW™nWKUUkLUƒmUUam@UU™@ƒmUL@xkV@„VV@bmV@Vk@mwkUƒVUx@mbX‚ÇnVb„‚UL¯šWŽnUVLVb@xnlWnU@UVUVVUbVVlVkn@llVUXUWUXVbUJ@bmLUJnb@nVK@bl@@š@bVJUbnX@l„b"],encodeOffsets:[[116551,33385]]}},{type:"Feature",id:"4103",properties:{name:"洛阳市",cp:[112.0605,34.3158],childNum:11},geometry:{type:"Polygon",coordinates:["@@VVUllLXl@LWn@J„@bƒKUVmnL@`VblLnbV@„b@JmL@LnV@VV@¯„VJVnXL˜@nm@aÞ@‚a„k@m„IšmVbXL‚ynLšk°@°aVJnUV@UVVXk@WJ@VXLlUnJVnnƒ°U@»°U„wl@šb„WmUXƒÆ@VLXU@m@U„a@I›mkb™a@naWW@_@WXUV@@U‚ƒ²@„K@I±U@¥kKWLóLlƒa@£Um@kWKXU@mlLXUVKUU±J¯_@`UL¯Wmk@Wa„kkƒlUnƒVUVaU@KUU@mmK@_ƒa@KX@VaUIm±™k„aVKVUkw™@kaƒƒW@kbkL±UUaƒK@UUKVak£ƒ@UmmL@lƒIkmUƒ@Ualw@UƒJkbmIUmn@WKImWk@mUUnÝV@ŽnÝxƒKmXkxĉVWVk@kaċšÛ@WXƒJUV@zŽm„VWnbUbVbšLlUnŽ‚lUÒnWV—VWnk@@Vm@kxm@Un™l@Ll@@V@šXnƒškJV„šV@nlVXx˜U@l„n@aš@VLnWĊ¦nxš@lbVKXLl@ރVLƒ„XJl@XXl`lIXVl@Xl‚XUVšK„wV@lanx„zUbVJ@VVX@b"],encodeOffsets:[[114683,35551]]}},{type:"Feature",id:"4117",properties:{name:"驻马店市",cp:[114.1589,32.9041],childNum:10},geometry:{type:"Polygon",coordinates:["@@n@„b°UƂXnVlnLÜ@VLœm@n˜@na@J„„m@k„@lVšVxXX@„V`lLV„XVV@VVÞLVV°„²@lašbnxV@@b„Lšmlm„_VWnIWUna@lšLšbnV°ƒVL@KšV„LVUVaVLXK@mÆXna@wVm„a‚@Xw@KlL@a„@Va@wUkaWnIVƒla@Kn@Vn@VUl@nKVn„J@LnK@aVkVUUWƒ@VakUVanI‚²X‚W@UUU°KnUVLl@XaVK@ašU@KUI@W@_lm@KkLUKV_Uƒ@»@UVJ@XV@@mVL@K@U@Kk@VwUUm@kmWL@VkVkzƒKmb¯VÝI@WUkÇJUIUWk@@klK@_km@UVWUUW@kbmKUXƒaƒV—amLmK@namaXK°VakU@mU@@aƒa@UW@kkU@U`m@U_mVkaUVWUkVƒL@lmX@ŽLm@UxVlƒUUl@zaWJXbWLUlmIUƒkLmWƒ@@z@VUVUšUmÝ_kVWŽ@nUVUlmIklmIkJUkƒl@n@Lm@؃IUbm@UJUUVU@mmI@UU@k¥mUk@WmVmI@VU@klmLƒ™k@mbkKmb@WkƒKUŽVnUnnxšW@UVLUbmJ@bk@WbU@V„kx@V@bVbkV@V‚@‚—XWbUWm@kb„¼VLn„lJlb"],encodeOffsets:[[115920,33863]]}},{type:"Feature",id:"4116",properties:{name:"周口市",cp:[114.873,33.6951],childNum:10},geometry:{type:"Polygon",coordinates:["@@lšnb@xlJ@UnLlKXUlJl_„KnV@xVL@bkbVVUè@šWb@„Ubmš„ŽkšVšmbX„VJnUl@„a°@@b„LVbƒlXx˜InmnLVw‚anJÆw²IlmnXVl°VVbÈaVb„@lkn@VWnLlUVmÞUUklƒkƒVkUaVaVaUw™K@kkaVWmw„_„‚l@nU„VVb@b„aV@VV@zXJl@@kl@šlœk°WVnÆbnbUšVJ„Iš@VKVm@k™K@_kK@a@aU@@wW@@k@aUW@IUWVUnLlUlVXKVwmk@W@—VWa„¥@k@lnƒUIÇKUaU@ƒUUVmIUV™Uk¥ƒVma@¯k@Wanwmƒ„@@n@@m@UIVƒkUVamUXWƒaV™U_™@ƒmUVUImW@aUIĉK@VmI™b@lU@@n™JƒkU™@KƒIUmmLk@UVm@UŽm@@LkbU„mJXlbV‚@xUbƒ@@bkK@LWx@ƒbUn@xmbÅW@nWLUKUbUVƒK™U@LUK¯„mU@šVV@xULUŽVL@bU`WšUz¯aUamKUaƒ@@xkX@x"],encodeOffsets:[[116832,34527]]}},{type:"Feature",id:"4114",properties:{name:"商丘市",cp:[115.741,34.2828],childNum:8},geometry:{type:"Polygon",coordinates:["@@XVl@lLȃ„@VkV@V»UanƒWX@VaÆÇô@ÈaVX@xVJXUÞU‚aVLĸbXKl„V@šm°Vn_ny˜XX»mUk¥lK@a„_@yšInaVKVa°_@WXI@ƒ@K‚VnIlbnaV@„l„@‚a@_w@ƒlwUKm™Xa@UV@š»Vƒšw@kUKVUUm@w±VUXUKUwmJUUƒ@km@@±mXkmUI™@mm™KUwkbWakLWaUIkJmŽƒX@l@@VUX@JWbX@VbULWbƒlUVULknlV@bVJk„mb¯KknWmk@@nmVkx™@ƒVmU¯KUnUL™@ƒJUIV™maÅaUm¯X›l™kk@@lk@WI@yUUU@ƒb@aUaƒUmVk@ƒƒ`nxUXlb@lšLVxUbUbVbUll„k„VlÝVUnkVmKUXm@klƒ@ƒnUx@xnxƒn@`VX@V²x@V@b@„Wl@zU`VUVVb„L@Vƒb™W@bkXllkLWV@V„@VVÈwlVœ@@X˜K²Llb„WnnÆL@VnJWn"],encodeOffsets:[[118024,35680]]}},{type:"Feature",id:"4112",properties:{name:"三门峡市",cp:[110.8301,34.3158],childNum:6},geometry:{type:"Polygon",coordinates:["@@WKUmUI°ƒU@@UmU@KnK@IƒaU@makKUa@_‚KnmVU„L@a‚ƒ@IXm@KWkkKVkUU@aUW@UUIVaƒymwkbU@ƒx™LVUWWkk@WUkJk_WWk@WI„ƒUK݄k@WKULka™@mwĉ¥mXUK™@@bƒm@k—VWwkU@m™UUƒlI„™Wm@™@Uk@@KškVmn@lwn@@Ul@Xm˜UXUmVсkmkV™KUaVamaUXnƒ‚@ykLUKƒ@™WwKmKnUm@UmƒƒaU@mUk@kL@lƒxċxUnkVmnXxWb@`kzWJ@V—LmVUn™lmUL@lW@Ub@VšXUbš`VLUbUJ@nmnUlUUm@@bUJlnU„š‚U@lxkbƒ@@XƒJUnƒ@kb¯VVVmlXXlJlzn@VlkVW@bkK™bmškŽUbVb„lƒXVxšKÈnšwÞlĊKlšVnKlwX@lL@xlUnVn„@šl@lmX@ƄÈb°¼ÈwVJlx„_°xšašlšUÈxlUnbVxnL@lllšbm„n@nb‚@@V„L@V„@@„VLšJnIVVlKnV„_"],encodeOffsets:[[114661,35911]]}},{type:"Feature",id:"4107",properties:{name:"新乡市",cp:[114.2029,35.3595],childNum:9},geometry:{type:"Polygon",coordinates:["@@XVlL„K°bUblbUbšl@nX@W„XVVKVkš@@Žmb@„Ubn„W`kL„LƒV@VVLnKlVXIlVš@@a„@l£nWlƒkVa„@°bnUlLVlna‚bnUVUXKlU@ƒ@lk@a„I°y„@ôkUU@wšmôšnkWakml™UkVmkUlmUUm@nkUKWanamU„LXW@U‚VnUln„`l„œblL°KXV@ĠJ@L°„šJšUVw„anK@UUImmƒkK@¯±Um@IVmUmmÅnWaUK¯aUk„w@W±kVƒx™U™VƒwƒnÅJUIWaÝJóI—bm`ÝbÅImJUI¯¥¯@mU¯UƒJmnUVóUkl±V@zXl„bWVXL@bm„mº@@XmJUXU°llk„@nWJk@U„@¦U`m¯ŽWx"],encodeOffsets:[[116100,36349]]}},{type:"Feature",id:"4104",properties:{name:"平顶山市",cp:[112.9724,33.739],childNum:8},geometry:{type:"Polygon",coordinates:["@@l¤UbVL@V„LVb²VlKlaX@„„lbš@lxUVULƒbšln²VJUbW@@L„b@`nL@nVV@LVŽUbUVm„kVl„ƒlXbl@Xn°ŽVK@_°`²IVVV@VUVJnInaWK@Uš@„K„LÆ@nmlXXWVUUw@klKVa@knyVkVanI‚JXUl@XbVUl@@aša@mXk‚bnK@UlK@UUUVaXaWmkUm¥n—WmXaWaœkl@VmÞb„KVL@aVI@mUwVm„@KōméUL™KVaUk@kUK@U˜WXI@VlKXU‚@VVnInVV@VLlK@UUƒkKU_@ƒWWUwU™@klƒn@ƒƒ@Imb—@@m›nUKÛ@mKUkWVXxmbVLXŽVVU²VV@xÅnmWmLU@kbmJ@b¯š™IUb™JƒUUxVl@z@bU`W@Ub¯nUJUbƒ@WLUKULkU@aWKƒ@aƒbmL@ƒlmUk@@bUL™ƒWJUI™°@ƒŽ¯aWLk@mbUb¯b"],encodeOffsets:[[114942,34527]]}},{type:"Feature",id:"4101",properties:{name:"郑州市",cp:[113.4668,34.6234],childNum:8},geometry:{type:"Polygon",coordinates:["@@@nWVUKÅ@W„nVnI‚ŽV@œkƂšwV@šnn@lxÞlnôJ˜zXJl@nalUČVlƒl@²UlkôVVUnm„I°VnV°@°¦VJnIÆJÞan_VmU@ama™@kU˜¥kaUklw@UIV¥kVUI@ƒmmUÅmUlƒwVU@amU—JWbUakVƒ—Vé¯Im`ƒk—@ƒwVWmLkU¯ŽƒXkWmLmx@UUƒbm@@x™J@LbW@UUVWUkVKƒ@ka™IUamKUkkmmLƒUkJUVWXkWmnÅ@ƒKƒL™@@VXLmbmJUIUVU@ULWVkK@nWVXL@lVn@¤„b‚kôKXKlL@¦²V@JƒL±@„@VU@WV@X@`XXmb@Žšblaœn@Jƒb@V"],encodeOffsets:[[115617,35584]]}},{type:"Feature",id:"4105",properties:{name:"安阳市",cp:[114.5325,36.0022],childNum:6},geometry:{type:"Polygon",coordinates:["@@°kVaV¥kVmUkWkWVkVKUwkkmKUU@a„wWWXWakKWkXmlašIVmX¥ƒU@a„@WnK@kƒƒ™V™I¯ƒ@KğI@WU¯LkK›akƒƒ_kmmVU@VWXƒKnVmbXbVLmln@VVknlVUnVlkšlnXbmlmlXblnÈlWbn@@nšK@V„L„bVV°VVzšlnš@V™xƒI™b™ŽU@WLUa¯V™UkWõ@¯kkmxk¼l‚„XUlVbVLnlULmU@lƒLkVUlƒX@xW@¯mUƒ@UmIUW™L@aXa˜kU™¯anƒWk°@k™kKmmUIWaambUkkKmV¯aƒ@UblŽk„mXk¤ƒ@@b™@UbULWVnb@lUVVnmšnVVU„J@bWXX@WJkL@blVU°UV@XlWnXUbW@UVkVšVWbnLUJWLUK@Lnn@blVU‚„nUblxVUVJXU„a˜@Ub„LnUVV@mVIVVn@UbV@‚XbmbUV„_lVXUWanJVI@WkI@WVIVU°WXXl@la@mX@lLXl‚kVbœm‚X„ylIXJV@@kšKla²UVa„IVyÞb°LlVna@UÆKnLVbšK@anwU™"],encodeOffsets:[[117676,36917]]}},{type:"Feature",id:"4102",properties:{name:"开封市",cp:[114.5764,34.6124],childNum:6},geometry:{type:"Polygon",coordinates:["@@lUVbXa˜InV@bUV„x‚knVVÆnn@„VJlUU¦VJ@kxVllb—¦lVš@nb@bVŽUn˜aôJÞIXbVJÆI„m„xšUšV„w‚U²l@XƒxVl°bVLXb‚`XklUnmVblLœ@lmšx°LVK@UXIVašWlL@Ukƒ°KkVaVUXmmI@UÅKmmƒXka±K—L@W›@kUÇxUUƒ@@UXUlKkklW@ašX„a@UƒKUaVUUV_@yXk@ƒ@a@U±w@UUW@_„mmw@wVw„mUaÇbUa¯UUkmWkn±JÅxmIbUxmKmn—JWw„kUaƒK@a¯@ƒbk@mVUIWƒ—Lmwm@Ua@WJUb@LUl™@UUmLUbWJ@VL@VmXWWzUJUꄘ"],encodeOffsets:[[116641,35280]]}},{type:"Feature",id:"4108",properties:{name:"焦作市",cp:[112.8406,35.1508],childNum:8},geometry:{type:"Polygon",coordinates:["@@V@VL@x@bXŽWV@XkššlUŽWX@J„@nI@KlL„KšUVaV@œJlL@KUk@KÞL‚l²_‚@nWlL„UVVš@nLWVUJVn@anV@a„wÞUVLVx„b„@lW„@lbXn‚Vn@@¼šL°mšKVn@bnl@nVK@blb„L„W„U@VWLXV@nlKn@lVVbXw°nV_@¥Vƒl@XI@mlƒkkV¯VWnI@W‚@n¹nƒ@aWKXUƒaWk@yk@k„ċUkVmbk@WI—yóImÝkkwm@™mU@™xŁ›lU@mJƒX™ak@ƒx¯V@¼¯Vm„UmmIkVWK@UXIl@UWVUU@mVUI¯b¯@™lmKzWKUa™nƒJ@nƒlbÝ@@b"],encodeOffsets:[[114728,35888]]}},{type:"Feature",id:"4110",properties:{name:"许昌市",cp:[113.6975,34.0466],childNum:6},geometry:{type:"Polygon",coordinates:["@@lI„VnKlnVlnLVbšJlb„@ULVlUXVVX@‚a@KšI@wn@„aVV‚@nwnKlX„W°lVnKUX„x˜@„ln_°JVIXy‚XnW@U‚K@UXIVanKVVš@Vk@KVaXI‚@Vbn@nx˜KnaU™l™ƒn™Va@ƒXa@™VçUUla@aUK@wmUƒLk`kIWVkLmK@V@XUlƒn@JXV@nm„™bU‚óIƒmUa±@@ÑóVUUk@UlKVU@akWVUUlUUaUK@UUKWbUkÅJ@XWaƒ@XbmJ@nUJ@bUKƒLÝaUnk@›lXbWbXnm˜n¦lVXnWbUbVV@VkL@VmLaWl@n™b@bk@UVWak@WVImJUbUlmz@lUbkL@lVx"],encodeOffsets:[[115797,35089]]}},{type:"Feature",id:"4109",properties:{name:"濮阳市",cp:[115.1917,35.799],childNum:6},geometry:{type:"Polygon",coordinates:["@@lLXbW‚XXƒx@bVVnLllVxULUl‚XXlVlUnlŽU¦Ub¯l˜nœK@V‚bVb@šXbVL„KVxVVnIlašb„a„¥lU@wnalLnVVlVLXnlWVXn@@lVI@WnU@mƒÅW¥—aW_k@WwXy@kmƒ@wU„mš„š¦šlUxVLV@UwšJ°xš@VX„@Vb„@š`VX@VX@llšIVbnJlI„bšV„l„˜J@ƒmѯLóa@ƒƒKUa„k™ƒ™Xƒ@UK@wU@ƒlWUUݯImW¯aƒLUKU@ƒkƒ»k@mƒwƒa@UnKWI@ƒUU@akVWK—k@a±ƒbóUWKXUmk™KUmLƒbUx„„@lmLXŽƒ@@b„VW¦Un™JkbWnXl"],encodeOffsets:[[117642,36501]]}},{type:"Feature",id:"4111",properties:{name:"漯河市",cp:[113.8733,33.6951],childNum:3},geometry:{type:"Polygon",coordinates:["@@@Lƒ‚UnVxnIWa„@Xb@WÆIVlXaVL@VVLVbkVVŽUVlX@bUVkLV‚l@VVôU@Ò²@Vb„nôJVšanƒ@mWU@I„mVk@WkI@wmak™@wlW@w„@VbnLVb°bVyX™V_@aUKVVK@wUU@™™a™K@kmbXVmJUXƒ`kn™nƒK@aU@mw™akb±@¯ƒUUÝKUUU@WU@VkLUKU@mUmJUU@WVkL@UWJ—X@VVL@lVlUbšLVKnêƎ"],encodeOffsets:[[116348,34431]]}},{type:"Feature",id:"4106",properties:{name:"鹤壁市",cp:[114.3787,35.744],childNum:3},geometry:{type:"Polygon",coordinates:["@@ó™™n@xVVólƒ@¯zƒJ@bkl@@„kVWLUVmVXbVJnnlLlš¯@Xlm„°bVš—lWb@bšKVXnJ@VV„°nX@@w„WVklU„K@knVVKmkUKUaVkƒWkl»nwlŽ°lö@lXšV°UVbXKV@šša„Jšw@Um™™kUy¯UUUƒaƒK@U™L@mm@XaÇkkmWank"],encodeOffsets:[[117158,36338]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/hu_bei_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"4228",properties:{name:"恩施土家族苗族自治州",cp:[109.5007,30.2563],childNum:8},geometry:{type:"Polygon",coordinates:["@@VK‚bX@lbUVnL°„@VlVnUl@VUX@„aVƒmaXƒlašUUU@wmaVUn@Vƒnmmk@m™U@kna™aU¥Vam™X_@WƒU™mW@_kƒVaVKnL‚lœ@VVal@k¥@kUW@kUKVUlUVсW@kÇaU»ValmkUVUVak™@aƒV¯_@W‚UkmVUlU@aœƒƒalI@akkVWUaWXUWwœWVbÆ@„„l„alIVK@U™m@UU„W@al²a‚¯UağÇm@ƒbkk@wƒ@@W™aULmxƒIU‚™ƒb¯@U`UX™JmL¯aƒKX›WUL@aknmK™@aWUXaWm@I@UÅmVU@™™aUV@b™VƒI@WkU›bXkm@VakwUKULWKXmJ@XUK@ƒmL@KUwVaUI@KU@mmn™mXka@»V@@UUaƒw¯yVk@ƒUUVmmkÛÈU@mWUnmx„šmlUbV¦UlbWVUL@UUƒ™IUmÇKV„VbUVVxkn™LUxV`VX@š„„kJVVUXWaUVVlUnmKUbkI@WULmK@L@LVlƒLnmUIWV@aknƒ`VXUJIVlUVVbUX@¤mbnLm‚m@UXk@mm@Ukaƒ¥@kV@@KkU@aUKWbkLWVkIVŽk@UbVlmX@bU@@mmL@bn`@Ln@llVLVk„@XVVU@`VXUš‚¼k`VULka@VllVIn¤VU@@bl܃bkx@bkL›škKƒn@bn@@b@JUnV`UnVbVKlVXUlbn@°ƒVx„@@b„nVbUllVn@V—VK@UnW@UVUšlnk‚VÈޚxVb„VVI„xVaÆ@@aka@UVaU@@a„k@Wl@nbVIƎ@Jk@„L@VlXnlla@VJnw@UmwXU@aVK°ÒnllnLlb„xnKVaV@l¦²nVl@llL„x@XVVœ‚Ķš@našx@U@al™XUVa‚LÈþV°XxWXkK@šmLnlUb@b‚xnLVlVVkb@UJ@xWXXš"],encodeOffsets:[[112816,32052]]}},{type:"Feature",id:"4203",properties:{name:"十堰市",cp:[110.5115,32.3877],childNum:9},geometry:{type:"MultiPolygon",coordinates:[["@@@a@w@kV@nbVK@ƒnUla„@la„Ål@nlVakwWX@WkLšaVmšwV@anK@UlIXmWkk@@mmLkWlwk@U_mKXwWK@U¯K@UU@ƒVUa™kmƒkI™yUUVUmanU@mlwkƒ@_mWXaƒUWU@ǃ@U@aUaVwUKUIƒVkK@UWIXƒmaV@k@Vm@UnwlƒUamk@V@„ULUamxUJkU@Iƒ`WkkK¯XWak@@W@IUV™LWJkXkaÇVUKƒ@kUmbmUUƒUKƒbkKWUkI@ƒkKÝ@@aƒUm»nI@mƒU@UnWV_@aUmWbkLUl¯b@a›kkk@WkkJm_k@UV±@J@b›nU@@WÝIUJVbXL@nlJkx@„Wn@VkJmb—LmUƒ`VbUL@xVn„@XVƒŽ@„mVVnnJVbU„ƒx@„V„nVUbVVƒx@šn„™bUK@bƒ„@bƒJ„šm²„VU‚lbXzVJV„„JVbn@@Xmb@V@bVJÈ@‚Vnkn@°aVVV@šX„KnalLVmšUnnVKVlnLWlXX„Klk°š™šXŽWškLUVVV@nU@ml¯nmbk@W`Å@mb—LWm¯UƒxnêVèk@mbƒVƒnUK™@kKmXk@@JUI›lÛLllnbVnlJ@LULnlÆaVLnŽV@nkVJ„@lkô@²bÆm°w„L„WV@VXšKšVXI@W°ÆVšK„b°U„JVIVV„¦XKVL@l‚InaVÝnUl@@bX@‚™nmVL@lVL„lVLVUnbVW@xXn˜bœU°¤V@š™„a@kWKUUn@VlnL@UV@Ü»@mX@V_ƒakaÞ@VK‚¯@kkW"],["@@mUkUUm@nllVKXXVK"]],encodeOffsets:[[[113918,33739]],[[113817,32811]]]}},{type:"Feature",id:"4205",properties:{name:"宜昌市",cp:[111.1707,30.7617],childNum:9},geometry:{type:"Polygon",coordinates:["@@°`„U@blšUbUVlVkn‚ŽUbV¼Èb@l‚XUÒkVUVVL@lVX@ll¦k@UbU‚›@kmKULUbl„@`nXšŽ„V@XW`nšUbV¦šbmb@lšV@nnlmnU„m@UVnb@xVV™VkbW„nb‚VnVa@an@UaVU‚JXnWlXX@l„¦@ŽlKÆX„bX‚V@VV„@°¯°xXx‚XV@nV°UVWU_VWXkmaVnWVkn@lln@lb@UVLXWlnX@˜aXUmaVK@UXU„U@WVI‚W„XXV‚U@¥VKœ@‚Uގ„„‚a²LlV@kV@UanKma@UVUnK@UVLXyVL‚knJ@UV@@UXKWUXaV@Vb@mVLnKW„m@aUUm@@UkK@Ula„LXKWaXI@alKlmUk@wVKXL@m@WWn@UVa@K@wna@aW_XWWkXbVW@k@U¯WWwka@UUaVIVƒkU@m±@U@@wVKkaš_@VV@XUVwU¥‚šyUkm@V±ÈUKk»ÇL„m˜mLk@ó£kmWwƒm@U„IkWKXwWU@ƒkLƒwkbmaƒbkK@VƒLkmWIUKkUUƒÇIǫJ™XÅJULVŽÇLUVƒ@UK™@kI@WVI@UaƒWmXVVUL`±kÅLmKkƒƒkƒÅ@Ua›XXxWVXŽVbUXll@bkJ„b›„@bkVUVlnV@X"],encodeOffsets:[[112906,30961]]}},{type:"Feature",id:"4206",properties:{name:"襄樊市",cp:[111.9397,31.9263],childNum:7},geometry:{type:"Polygon",coordinates:["@@@Xl@Xb°WlLXl„_@JlVVInwVbVK@ƒ@UnlVbk„mx@VUnl@U@nbW„XJ@VlL„UVJVLUxVb@b@VȄ‚@XV„VWbnX@`l„kx@nmVnbUVVVšzlJn„šlVb„UV@@V°L@VXLWxnLV`l@kxlXnK@nl@XlWn„`Xnl@@UVa@VÈKš£VLVanW°U@UVU„@„`VIn‚mV@„nV@Xa@aVW@UšalkXKšblI„yƍXnlJXbl@@VV@nklU@`„nVK„LVKVb@V„U@UÈK„UVKšIlUX@V`lIVbn@nblVVmV@@XXJšUVV@knKVn@`@X‚VnK„wlLVmUUU@ƒU@aXL@WlU@UUW@UmU@KkLWaXkWmXUWm@U@ƒnk@UmK@U@UaUVUUKV_@al@namWUI@KUƒK@aV@WUIƒbƒ¥ULUJkIm™ƒK@U@K™V@U@a@UkU@K@wVaUwlU@mUƒULmKUkV@@anIWmUK@I¯„mKkl@LUb±lUakLmk@WwUKÝVUIm`¯n@Uk@makJU_@ƒƒJma¯ImwUVkKƒb™aUÅ@wWaU@VU@mXIVmmUkJkwm@mIlUKWzUK@VmLUV@VnbmLVbU@@lkU±KbƒƒÝV›@UL@¦VWUƒWXUJ@XƒVWV@VULnbWV—bW@kmWXUK@Vkam@kkm@UlmXUŽnbWlUXV`UX¯VmUU@Ul@Lll@nnJ@LƒnWmbmš@b™`ƒš","@@kUUm@nllVKXXVKmU"],encodeOffsets:[[113423,32597],[113794,32800]]}},{type:"Feature",id:"4211",properties:{name:"黄冈市",cp:[115.2686,30.6628],childNum:10},geometry:{type:"Polygon",coordinates:["@@VVUnWVXnVJ@„‚U@V@VXŽV@@IVJUnŽ@V@L@KlIVlVanLVbnVlI„ƒn@@a@Kl@@I„JlI@aXU@KlK„kVblJXU„VlU@V„bVkVKXn@VlxVa²I@VlVUxln@bšJXklaVWnLmÅ@y@k@ašI@W@aXIlVVaV@nnlKnLVW@IUa@a@K„UVVlI@wXKVV@IUƒla„@lUXwWƒnƒnalLlxXLll°@XwVKVaXIl™nb˜@nln@Va@U@k°ƒUmÆUVaXI„JV¯ÇUmmkU@WaKmakVm@U@aVKkkmKkVmIkÇ°£@aUUVaVVnKlkX‚mkƒ@ƒlUVaX@@Um@‚™UmlUXV„UVU@w‚K²¥Ua@I@UV™l@U™V±UIUÇ°»VkUmVI@a@U™m™ĉ™¯V±bŹĖğaÇL¯lmŽkX@‚óĀ@ŽmšÝêb±WkLƒn@xXx@Ž@b@V@LW@UbƒlţXƒ`kxWnXô¯¦ÆV@L@JVLƒxkK@V@bkz°l‚lXz@J„UlVla@XUV„bVKXnW`XXV@laVV@V„X@V¯xƒx@xULVbUJ@n@LU@VmmakbUK@b™IWWUUVkUmkLm@VJkb@nUJƒ@`V@kX™aUaVmmLkUmJ@Uk@U„±lkzmJUb@b„VUxVXU¤ƒL@JƒX@VlL@JkLUVU@mnUl„¦@V"],encodeOffsets:[[117181,32063]]}},{type:"Feature",id:"4210",properties:{name:"荆州市",cp:[113.291,30.0092],childNum:7},geometry:{type:"Polygon",coordinates:["@@ÈJV„lVVLXJln„K@UlL„anbla„xlK@„XVWxXLlƒJ@V„nXxlnô¤l@nKn—‚ƒÈKl¼VL²Ç‚Un@Vl™zŽV¦UxWVU@@U™`lbUL@xV@²@@nlVU„UJVb@VlbXx°XVWX_VKUwVKVa@UVKUUVk@KnblaUU@wnWl@UX@lÆ@@a„IVmUk„™šxVJ„U„bܙ@Uk@WWnk@Vƒ„™Vm@I@m@Un@m™XUlVlUnJ@knJVU°@@aÆLX@ƒllL@¦nJV@XblLVa²U@UlWš@VX@`@LV@@bXJlIXml_lJœU°b„KÆLnVVl‚@ö—Vƒ‚mXaVIĢllUlVnLVlX@@b‚ašnnxšV„L‚bn@°ÆXmmkĉƒ¯w±™™™Uċ@KÝÅƧŃÝ癙Uw¯ƒm™¯k@W‚kV@¯UIUJW¼kb™Uƒwk@W`@¦Uônb@VƚlÈ@VU@ƒƒ£UWWnUÆUnmJkUÇ£VWUI@aUU@WkI@Uƒa@JW@k£kaWVUKmnkKƒb™kkVWb—VmUUmwU@kk›@UakUUa@V@nlx@lUb±lUbnnWLUyk@UamœUK™@mlk@Wb@VXL@x@xWI@a¯Ž¯V@bVn@LkKmL@`XmKmVU@@bkL@V±bk@Uaƒa™L™KUVƒIƒ„™W™XamVVbUK@b@Lm@UWkxULWVUnm@UlUX"],encodeOffsets:[[113918,30764]]}},{type:"Feature",id:"4208",properties:{name:"荆门市",cp:[112.6758,30.9979],childNum:4},geometry:{type:"Polygon",coordinates:["@@n@lxlInVUnWJ@nUVV@Xb@xVƚb„alLVUnx°Jnb„I@„V`lInbl@@V°mn_VJÞUVLXx‚@nllKVb²kVa@KlknL°ƒ@JVLXnmJ@bU@VlnLVKV„@nX@lUšKVaXal@VKn@¥°L@Unw˜bnašV@KV@VUX@lVXI@KW@@IXWV@laVL„„KlaXUVVnkVWV@lwXblIXWVkVmšaU£VaUmVIkU@y@WakKUamU@UUK@kmK@w@@mK@LƒV¯™U@WwkmULƒamVVUU@ƒƒIƒbUKUa™kmƒm@UakLmxU@UÒWlULţÿmwkIUm@a‚kÈblW@UVƒUUk@JW@XkWWUkUKUIlw@aUWknWUUmnIWƒ™aUwVaۚƒaƒVUI™wƒšVlUnƒJ@bÅ@@kVWk@mX@xVVkbma@LUlVVUL@VUbULVxULW`UX@V@lUXWaXlWXX`@bmb@x@LUb@VmŽXX@‚@nWKUL@xVlknkL@bWJXbWLƒKkb@VlL@Vn@VV@bƒnX‚mLUK@nUaU@WbXVWL@VU@@V"],encodeOffsets:[[114548,31984]]}},{type:"Feature",id:"4212",properties:{name:"咸宁市",cp:[114.2578,29.6631],childNum:6},geometry:{type:"Polygon",coordinates:["@@ÞƂLČ@šV‚š²š°xĊ„nlWnŎ¯m@aƒK@„„°‚n„Jšwn™VIUaÆJšÅ@wšwV™XW@aV_l@²V°lĊwlaXLšwlUkalVVaX@lVXI@a˜UXJ@U°UU¥VIVKVklanLVa@VÈIVV@nk@aVa@mV_@a„K@klKUa@UnKWk@@lU@@UW@@nUWUwmaVIXƒ„lV@mLXblJ@kV@kk@KU@WƒkUWVÅwkLmW@UmL@lUL™KULƒak@maUUÝwUJƒIb›KUUƒ@š™aWK@kUWVkUwVw@™mÝ@™I@wkW@a›ww@LU¥™kƒJ@nVJƒIkVVnkV›UkyUIUl@xWUkaW@@°kz„ŽWxkLUWmzk@@bVVVš„b@‚@XlVœ@Vl@bVbUn™`Wn—@Wb„VVI@`„LVbXLV`mnU@@lƒL@LUŽƒak@ƒLk@WbUJn¦@lVb@xVb@n"],encodeOffsets:[[116303,30567]]}},{type:"Feature",id:"4213",properties:{name:"随州市",cp:[113.4338,31.8768],childNum:2},geometry:{type:"Polygon",coordinates:["@@„@nš`lw„k„ƒ„UmUVWX@lk„@VanUĠ¼V@@mX@@nVV‚VXLmJVLnK@b„V@@J„@VUn@VaVUUUVWVLV@@Kk_@almaVkUU@WVƒVUVLXmmk@wUaUKUV@°™@kmaUaÈmW„mUƒVklaX@lVnxl@@UnaUk@ƒVUVwVK„nš@VVn@VbVJUknUmmVmk_Vw„KUUm™Vak¥@UVKVIkW@UmIVWkIVƒkmmLkwmVUƒ@LƒUU@VVXL@JmLUbmK@UUKmkKUUmVUaUnÇlk¯™mJUnmLUaUJUaWL@UkJ™ƒUƒ@ƒaklkU@¯@KWLUmUUWVkbƒLƒŽUKkbU@WX@JX@@LWJkUW@UVU@@L™Umb—amx@V¯K@¦mŽULk@WbUb™LkVW@kVVxUb@x@LlV@V@b@VšU@L@V„LnšlJVIVK„¦„aVJ@XUŽ@b„LV‚@LVJnXmbk@@bU`VLUVV‚b@V@VnL@Vml@„@VXnWVXnWlXblK@LnV@VVX@VkV@XWK@b„VV@VV"],encodeOffsets:[[115830,33154]]}},{type:"Feature",id:"4209",properties:{name:"孝感市",cp:[113.9502,31.1188],childNum:7},geometry:{type:"Polygon",coordinates:["@@VnXK@L@°lVlk„b„@„VšlI@VXKVbVIVbnKVmnI°šlŽÈkVmVbnUVVlLnVL@VnLVanK@IWKUUV@„V@KV„nUlxnKlnU„lJUXnJ@VlXUJUL@Vl¦UbnšVVƒLUxl`UnnnmVVlnVK„bšmVX@a°Ý°LšaXJV@VUnKVXVK@LnKlLUbVVX@VwVJVn„@@UU¥V@@UUK@ƒmaUVUkkJ@L@K@UmVUI@JU@W@U@UV@ƒUIWmXUVmUUÇ@UVmIlmnmakK@akaW@UwVUkKVnUlKVwk™ƒVU_WKUkVW@UXaWkUa@w@VU@XaW±@IkbƒKƒb¯L@WƒXkWƒ@UakL@UV@UmVUmL@UXWVL@ašUƒVUUUVU@yUUƒIUa@wUKWVU@kƒ™™Wk¯UkwVKƒLUx™K@nVxUlUUWVUmw@wƒUUyXWlX¦WbUV@„U‚@blbUVVbXXƒl@lVL@bk@lxkVVnVx™¦ƒ`UnkL@V@L@Ž‚@@xnL@lVL@VnVVblLXb@‚@zlVUJVnUbV¤™bUnUlWXkJWakxU@UXml"],encodeOffsets:[[116033,32091]]}},{type:"Feature",id:"4201",properties:{name:"武汉市",cp:[114.3896,30.6628],childNum:1},geometry:{type:"Polygon",coordinates:["@@nbnm‚knJVUÈ@@Uƒ¥VknmV@VUlK@IkK@U„W@I„KV£UWVwƒU@aVanIly²kVƒl@@VnIlVnKUnVbšblWU@@_„‚VI@mlaUIn@lKVnUlVVXXšJ@aVLlanbUnV@@K@mVIUaVK@w„w°w@UƒW@UUUkbU@WWX_WmULƒaVU@WkbkUƒV@IWyk¯kly@a@UlL„wUK@I@KÅUW@ѱUm@wl¥kaƒ@@_Vw@ķƒa@akw@ƒkKW£XVUVwVwUaU@VUU™™xWKkbĉx¯k±Uk@U`@bWXUš™x@x™ÆÅIVbUJmš™xƒImƒ¯@ƒ™Umx™nUVVbnJV„@Lƒ@@ŽkV@bVnƒ@UVULlx°VXlššl„V@XUVL@xVb„JVV@zUVVVUV„™V@bUKWX@VnKUVVnU@@VlKVb„@lX„W@X°K„a„Lla@JX²Wb@ŽUV@@xVbXlWb@VUXVlXLV`Uš„lŽUxkLmVUŽlLUVVxX@lb@blL"],encodeOffsets:[[117e3,32097]]}},{type:"Feature",id:"4202",properties:{name:"黄石市",cp:[115.0159,29.9213],childNum:3},geometry:{type:"Polygon",coordinates:["@@VšUVV@VbUx„aWUœblUVmnKlX@bXJVIlVUxVVVIU‚zlx¯š@‚VbnL@x‚x@UVaXK„b˜@Xk‚WU_Vm²klW„XVK„Žl@nXV@@w„mlK²X‚aÞén™@ôÿ@lWn°kUKmmUљUmm@ƒwkImWU@UakL@bVLUVċ@™bUK@alIXKWK@™nXnKmkUVwƒ@¯b@L„lUL±W™n@KULUaW@kL@lƒL@bU`@nUb@bmlU@UÇJ@UUbmKkblŽUULUJV¦¯V@VWI—V@bWJkUW@UbkUlbkV"],encodeOffsets:[[117282,30685]]}},{type:"Feature",id:"429021",properties:{name:"神农架林区",cp:[110.4565,31.5802],childNum:1},geometry:{type:"Polygon",coordinates:["@@n`lIXll@lœl@b°aVklKXaVn@bU`mX@V„V@nmJn¼„V@bÞ@lL@„lJXVlL„aVLV„nVnalV„@VLÈUlblWXIšKVU@J„™š_‚@an™na‚X„m@KmI@mkk@KVkWWw¯w¯°ƒ@UUU@WƒaÅWkL@ƒ¥@kWWXkWmIUVVbm@@bUbmUU„ƒbW@UVk@mVkU@U¯ƒmKVUkaW@aULƒÆVbƒb@VÅ@Un@VƒLWl¯Lš„"],encodeOffsets:[[112624,32266]]}},{type:"Feature",id:"429006",properties:{name:"天门市",cp:[113.0273,30.6409],childNum:1},geometry:{type:"Polygon",coordinates:["@@@K@UlKVm„_š¥UwUmlUkwl@@aUK@k„kWWUaVUka@aV@ƒVUXaW¥Xk@WWIklm@ÅxmI™VÝUkxkaƒ„@bWJaUL@„W@™l¯UULU‚ƒbƒkV™Ua¯bm¤UnÇUkmUšUx˜b@VkXÇal@bVnlJnxŤĀVKXkVÑV@nwlKVbn@n„šlVbVL„a„J@„VV‚UnU„bVKlnXxV@°š„U@KnL"],encodeOffsets:[[116056,31636]]}},{type:"Feature",id:"429004",properties:{name:"仙桃市",cp:[113.3789,30.3003],childNum:1},geometry:{type:"Polygon",coordinates:["@@VK°VškX@@ƒVK‚bXI@a„ƒlblwÞVšUnJÆwn@lkXJ@X‚WVz„V@xnx‚VXUVVVkUw@mšLVw„KVU„@Um@alU@„@@KUƒmIUaVUšmnwmw™mb@aW@UkmKkUkVġkUJWbnU„õ˜@UkmUÅKƒL¯a›VkIk`WnkJƒ@xVLUVVbUbk@WlXbm„VxnxUblbUV™@@VUV@nVL"],encodeOffsets:[[115662,31259]]}},{type:"Feature",id:"429005",properties:{name:"潜江市",cp:[112.7637,30.3607],childNum:1},geometry:{type:"Polygon",coordinates:["@@UbVxšbX„mJVnXVlmVX@bkxVJVLVlXXWlX@@IVl„V‚U—aVwV™lnÈVVmn£°aVbUš„l„aVUK@mVU@Uš@VUkaVamwUwnƒWaXkl@VaUaVUUK@w„WI@aU@@K@_UW™@kX@V±VUbkKWaU@mI@¥kK„kW@ÅK@b¯@UVmI@lmIkVkUWVnšm@@V@n@JUnƒšU„@ŽmlXXl@@V"],encodeOffsets:[[115234,31118]]}},{type:"Feature",id:"4207",properties:{name:"鄂州市",cp:[114.7302,30.4102],childNum:1},geometry:{type:"Polygon",coordinates:["@@°¥WóXmlw„_ŤW„kVaX@@K@U@a@WwU@mWk@ƒULƒWkX±lUnV`XWl—@ƒaWLUb@Vw@wmKUa@°™kw‚yVUJUUVwkUUJWI@akWmLUnkV›aXVƒbUxUVWX¤lL@„lx@b„b@ĸUx@`„@lbk¦@x‚n²VƄX@"],encodeOffsets:[[117541,31349]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/hu_nan_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"4312",properties:{name:"怀化市",cp:[109.9512,27.4438],childNum:12},geometry:{type:"Polygon",coordinates:["@@@n„‚@b@XnJ@k°x@aVUnl‚UXnV@@VnJWUJV„nIVV°ŽUbVVVL@Ž²LUVa°V@aV@nm‚UXblLXWVXVmVLVK@an_„`@X@l°„VlXXW`nX@Jmn@b„@nV@Lm`„bUb‚n@VUVl@nIVbUlƒV@LkJUnVV@xVblVUbU@ƒzUKU@mx@xUnn@@WV@lbUb@šnVWXX‚V@VIV@VUnJ@VUz@JWbXllI@VXVVL@ŽVn@„„Wlb@„Žl„XVlL„aV@VJ@XX`„kVwVl@bk„‚bUŽlVXIlƒnLVa„mVwV@@nV@XaVJVbX@lwV@n„@nV@VWnIVVUŽÆ@Xx‚a@I„UUKmk@mVƒ„IXmWUš™VJnUVU@anaVwk™›U@UXa@W™@m_@a¯@@K@UVƒ„bnK@blIlbXa@WW_n@VƒU@¯bmyƒUkUJÇÅ@WU@kWKÅwƒnm°KVkmankVWnXVWV@UƒƒwXkV@mƒ„UlLnaƒVaX@VUn@VnVK@xlnXWšU@a™@@klak™Vw™mUaV@™wmIÛ`m—@mVUXmlIXƒV‚I@K@aU@UaV_UK@wkUmmUKWXŽmVkUƒL@mƒƒU_nK‚™@aVU@Ukak»@U™™@ymUƒ„¯™ƒUUƒVKkam@™nka@ƒmwkLWb¯mkaƒ_VaVKUƒ™IUw@kKmU@WK@UnƒmaULkU@wUalWV¹U@@WUI@WU@‚_@W@U@mƒU@WbbUK@Um@@UmbUwWWkk@WU„a@anUUwlWUwUU@wlJVUnnV@@mnI@m‚K@U@w„a@wUm@_mƒVUUaVUkƒƒƒ_kċUk™VWLƒ@mlU@kn¥W@UwUWV@VÝU@lXLWVUbVLXlVIl‚knmU@VUJk@@„ƒ@™kVmwmVkxU@@XmVUb@xnKVLl@VxUxkIU`@bWVXX@JWL@bkb„¤@bmUUU¯Kƒkmb@V™VU„VVn@@„Vb@`lnœxmb„lUn‚bk„@xU„mV@bmWbUV@VJ„Il@nVUb‚K@nn@VbnJVIlJVkXJ@X@lmx@bnnWVXJWXU@UlU@mk@@llb°x„IUbnJ@VWbXVmI@JVX@bk‚@bWL@JUXUK@U@Uƒ`n@@Xm@XVW@@nX@@`ƒImxU@@JUI@KƒLmK@UÅUUV@VW@™¯kUU@UamVUUmJ@n„xmLKƒkmJkwkKm_mKXU@aƒU@b@Wk@ma@zUJVUmbUlU@™xnXlWlXXblK„¤V@@nUVVLkVš„l@Xb@VVK‚nXKVx@znW@X‚@@lVK@X@JXbWbnn@JUamLVVXIVxnK@aWUX@˜x@VnI@WlI@anV„IVxk‚l@lbXXšxVVVJVInbV@@ln¦ml@XXVWbkJWb","@@XLVKVXVKUa@UUUmV@l"],encodeOffsets:[[112050,28384],[112174,27394]]}},{type:"Feature",id:"4311",properties:{name:"永州市",cp:[111.709,25.752],childNum:10},geometry:{type:"Polygon",coordinates:["@@lxUXV‚lXUVnlVĢ„JVbUXVJV@XUW¯„VIUK@klW@Un@„nl@V`XUVL@l@šVx@„XXW`UnUbšxUlVnUšV„lb@VnJšUVVVInJlUšVnwVklKnw„LVJVšV@nIV@nbVa@KVVVUUa„KV_nVVJ@_VW„nV@n¥lI@anƒl¥X_VKlwVlULUVVVš@šU@VXL˜ƒ@IUmn@VU@wmKXUWU@m²šl@VIXWWkWUkWlkIVamUXamUnmWUU@@Un™lK@XJl@kVUk@mWKXkl@@aVU@UVWUUVa„In`VUVLnw@U@K@Uƒƒ@w@UVmUUƒ™°K@UnV@bV@Xk@KVm@amk„aU£VWUUmUUwm`UbULka›KXU@kVmU™@aV_UWVIn@˜y„XXK@klmV„V_kWVUn@WUU@UƒmaU@™wnwWanUmmXkƒam@UakLmK@b™xUUUU@Km¥Vaƒ¯@ƒkUaVUlm„UU@mUUÇmUk™Uyƒb™bUa™XUWWbÅLmL@V™aL@WWXUKmmk@a@UUK™XW¥kU@VƒUkxmVkUWbUJnVJ@nVJXzWxkŽ@lVbUX@VVL@`mbUnšŽUn™VV¼k@Ulm@mwLƒb@lmLUK@UamƒWkƒK@£Ua@ƒ›UkJkUmbVlkX@bWbUŽVŽnnUVl„@bšbVK@VX@lb„V@nU¤šx‚²„Knblb@x„V„ô@šlŽ@b@l@XWxnVl@„VV@XLVl‚LUŽUXV`šbXXmJU@@bm@UUkLW@UlUKWUUb™wUm™L@nklVVmVXXm@@bUKlÆn„‚XkllVUVVL@nUbV‚@V@nnV@xUn¯U@JW@UX@xĉ@™`m@@LV@b"],encodeOffsets:[[113671,26989]]}},{type:"Feature",id:"4305",properties:{name:"邵阳市",cp:[110.9619,26.8121],childNum:10},geometry:{type:"Polygon",coordinates:["@@XIlJšI„VVK@n@VVVKnLVwVmnLVK@U„@šw„J@wVIƚ°X@ÜȄUÈxll@kn@VwVaXJWXn@@WVL@UUKVKV_U@@aVK„x@U„aV@lk„@XylbUaV_šVnal@W„U@a„I@aV@@aVUl@Xm‚UXWaXml@@kk@ma@V_UnUV™UUWJUa@kkaWLUmk@@LUVWUkJWkK@¼UnWJƒIkV@b@JUIm@Ul™V™m@Uw@a@kWƒXWKUknW@ƒWUU@k™mx™UkVmIUJUU™VmI@UkaUƒV™UmVk™wVaVmX_WW@ƒUw@™@kUKWVU_k@ƒmm@@VkX@lVLUJƒX°WVU@UIVWUaƒIUġmkVUkWUVWkwWXk`mI@¥kUVƒUƒUn±@m›XkWknV„UVmmU@@XƒVƒUk`@Xƒƒƒk@¥¯»mbĉó@mkU@kU™ƒƒ™KmX@˜UnmL@lULkKUƒWUU@ƒbUaUnƒ@Vb@l„¦Ub@l™@UKmnƒKUnl„UVVbUVn„@`Vn@xƒb@x@VL@nmJ@nU@mmUVkI@xVVVxkXVxmV@bƒbXVl@Xl‚XVxna@Vn@@VVL‚aXaV@n„‚@@V@X`V@@XVJ@XV@UºkXVb@xlVVKnbm„@VXLV@n‚lL@VxšJV„ULUb„`lb°nXalKnx@„lbšmn@lbULV„„V°š„ƒnV@zšš@Vl¼lb@VUV@bšmLV`„„@n„KlVnU‚XWVLnnlV@xVLU`VbV@"],encodeOffsets:[[113535,28322]]}},{type:"Feature",id:"4310",properties:{name:"郴州市",cp:[113.2361,25.8673],childNum:10},geometry:{type:"Polygon",coordinates:["@@²zVaVlnVl@nšVk„Jl_XJlIVmnL@mV@VXn@lV@‚XzV@lyV¯²U@UlJ@XVKnVVIXl@UVLV`@n@J„I@mlI„KVLnUlVUVVLXašKVLl@nb@ŽW„XV°KUnVV„L@xVJ„L@b@LUVVVU„˜VXbmbVbn@@lUbm@x@XVVVŽ@@˜@bkImx@Vm@Xbƒb@l°XU¤„a‚L„mnL@bl@@™VUX@VxnV˜anLnƒWƒ¥XKVwnUWXmVIUWÆLVx„L„w@wVmlU@¥XƒWUkwlÇn_Uw„WV@VU°wnU—ƒy@aVškVlnL@lVn„w@VlJ@b„X„x@bVKnb@U@WVUl@@Vnbl@XLlK@aVLVKnxÞn@a„LlmUaVU™ƒm@ÅknUmaUKmVk@m™kk@UlWUkVm@w@kUU@W™U¯™¥@w„Ç@aVIlUV@kUWU@UUm»@k@mKVkUKUwƒaUaUa›@k„kUWJkImaU@UK™@maUzk`@zƒy@XmJkL@UUJmUkV@z›@kŽkVmK@¦UbWL@a@UbmKmwUK™Xk›VUUkmVkw@UUKmL@WUIWa—JW_k@@WmI@mk@WkWULUUVKUUVm@šU„bš@‚nUǃ@U@w„™V@Ua@aƒL@ak„›l@k™UƒJƒwó@@L@V@„™`@œƒJ@xnn™šmV@bkJmUó@ƒn—JW„UUmƒU@UV@Lk„WlnnmVXbmxšxV@nbV„V@XVm@UVlXU`ƒUŽkn@lWLƒW—zm@UJVXU`@bVšUn@lWVœLlbVKVan_VxnVVVUXV¤ƒbnl@bUn@LWlU@@amU@V¯L„šVVUn@V@x„„@V@L@VmxUKUVm_ƒJUbVV"],encodeOffsets:[[114930,26747]]}},{type:"Feature",id:"4307",properties:{name:"常德市",cp:[111.4014,29.2676],childNum:8},geometry:{type:"Polygon",coordinates:["@@l™U™mkUwUyV™@VW@¯Va—VmUU@KVUVUVLnaWƒnkUÓV_@mVU@݄w@ƒka@kVmƒUmK@IkaUamKkXWaUW@WUk„™@@KVU@aU@™L@J@XÇVUKVak_mWkLWakVUbmLUUmlUVKUU@kUWW@UImJ@xkLkKm@@Xƒ@ó݃@UUk@UKƒV™ƒULƒKƒXkWWbkaƒIUƒWU@mUk@WLaUJġ™ƒ@@XÈÆVIl‚„Vnz°aV@U„m@X`@XWbkakJ@amLƒaU„@V@L°@@bn`š@@XWb@VœVlšUxmb@bUVmVUI™šXVWnƒJU„@nnlVLƒV@JbWzk`m@UVK²V‚x„k„LVl„@Vn@V„„°xVKVkœVVlUblx@bU„‚Æœ@@nVnUll„kx@VW@@VkLWxUL@bÝ@kKkVõV@bkXVVUVƒ@ƒVkUkV›LkV™a™@@™ƒ¯xUxmX@JVb°WXkK@Vm@k„Vb™bn¤‚xUXkJƒblxnXÆK²l‚_@Wnašn@ŽUL@b‚JnIlV„@lUœ@@¯ô@lWȂIVKVm„U@aXaV@lwVXn@@K@UVKUUnU‚bn@lWšX„ƒlJnUšLšKV@„„l@²a@UlK@aV@naVX„WV_nKlL@KUm@a°U°@VXL@a@wWmXal@„k„@VLn›V@@bl@VnX@mwVa²aVU@mk@"],encodeOffsets:[[114976,30201]]}},{type:"Feature",id:"4331",properties:{name:"湘西土家族苗族自治州",cp:[109.7864,28.6743],childNum:8},geometry:{type:"Polygon",coordinates:["@@@KšL@wnK±nƒnm‚—@WUk„ƒÜÈn@n»@mVamk„mšU„„l@V™nmmU@wUan¯VKšLn„VWlInyWUœI@WWk@KXU˜n@mnUmU@WœƒmkV@ƒkXašaVaUm‚Ikƒƒ@kaƒX@ƒUm@UKWU@UkJWkXa@IVy@UmIUVU@UJU@WXWmU@™VakaU@@Xm@Vm@wnwV@VL„yV@VakUUa@wUUVmlI@K„UVkUamJk@VU@UmVaƒan_@KmUƒ@@anm@ImWX_WWUk¯ƒ@k@Wƒ_m`@bULUKUnUWWXkKWaVmnU@@b¯UUbVŽ±K@UKUUVa¯UUmJUƒVIXmI@UU@WmVmkUV@b¯w@lmI@W@aƒ@m¯LXbmJVLklWL@V@XXŽmbVVU@@VU²Ul@VlX@bš`Xx›zUmkUVÒlŽ@bXLWxXVlš@V„bkLma@nmVmULVbmVUb@lnzmbUÒVl@°nLV„lJkn@bmJk_ƒVmmkblxÈx@LUb„xVb@V™n@JmLVŽUš@„nV@¦VbnJ@lVVbkx™bm@UxVLV@n`UnVVV„kl°z„xVb@VU@@ÆlXnWm¦nbVK@XVVUVVl@X„KUV@nVL@WnIWŽXLVKVLlxUbVKXVWbn@@UnKVLVb„JšU@aVU°b"],encodeOffsets:[[112354,30325]]}},{type:"Feature",id:"4304",properties:{name:"衡阳市",cp:[112.4121,26.7902],childNum:9},geometry:{type:"Polygon",coordinates:["@@lšV@XV@„mXVlXL„W‚X@l@bVxn@šŽšUVkn@VJ@I@alU„JXIVm@»‚LXllIXVVU@Kl@VnXKlb@lVbXIVVUšmVVU`@nbl@@lXLVVVKVbnXWJ@VXbWxXb„Ul™VK„¦nLVVUVVbšb„K@U˜LnK@Un@VxlUV`UnnL@VVL@JV@VUnxnKVbV@@VšIVUnJUVUl@nW„XllIUa„KVbÞLV¼²`V@VIUwlaVmXa@IWanK@U@m„kVƒVUVaX@lšnaVLÈ@‚¥@kkJUWJUaƒXkaUm‚wVXJ@_lWUU@¥n_‚KkamUK„™@amKƒnKƒbV£¯W@k„aWan@@UnwlJ@a@—@UUU@W‚wn@Va@km@UanaWa—UVƒUUVU@K@aƒKUI@wƒKUUVm¯LWUXƒ@mak@UK™LWbUKVUkUmVUKƒLkJ@nƒJ@I@mU_UK@VWkUJmUUL@WkI@V±VU°kzU@Wy@kUm@UWU@@nmKUnkJWIk`ƒIUlm™k@mUUkUb±yUX@VUV@bk@WlXL@nVlUl‚k@WI@ŽkLmš@VV@XVmnnVWbnVUblJXkVl‚XXlWXUJk@±™@nXVWVnL@xUVm@Vn@J—„WK@U™V™@UUVUVKUkkxULW`k¦m„@bkJm¦U@ƒmUX@`UImUU`ƒLVbUVUU@LUbmaU@mJU@U™UIƒKmxkLUl"],encodeOffsets:[[114222,27484]]}},{type:"Feature",id:"4306",properties:{name:"岳阳市",cp:[113.2361,29.1357],childNum:7},geometry:{type:"Polygon",coordinates:["@@@wUklmUUmU@@UVm@wUaV_mmUKmwkIkJmUUnm@™™@UUƒbUKUƒmÛamm¯xVLkbÇƃUƒVUzkVUlƒUUKWLX¦W@ƒVUUUaƒKUbmLKm„@akU@aƒmVaUUVIVWkk@wkƒƒ@@xmLlmÅwmbVlXlÝIWVkK@kkVƒL@VWKU@Ublnaƒƒm@b@bšnW`@XUJk@UUWKƒk@UKƒnn‚@xmLUVm@kbVbV„nV@V„b‚@KnV„LWšXŽÆVĢ¦VblŽš„n„UJWz@ƙVóUVbkV™aÅx@¦lVUbVVknWKƒ„k@ƒwƒK™VU„Å„ƒl@zkb@`m_mJ@xX„mbVbœ@llV@n„@llbXL˜UXalUšl„alVnwnLVKlšVbX@@I„V@blJ@bVL@VVVUXȤ‚VnkVÑXmlbnš‚„VKkÑř@UmaVç@±XUlI„xlV„@VaX¯lUVVUšVJn—V@°°nŽ°„Vxĸł°¦šb²¦lJ@U@aUK@kUm@_m±VIXal@„Kl@„bV@K„K@k„m@UmUUaƒK@_UJƒaXU˜@Xmš_VmUk@WUk›@kU@a@m@UƒaUUU@al@ny‚XXWWwkly@¯n@@bnV@k@mVI‚„œVlUUmlU„JUw„I‚bXƒVaUal@K„b@ƒVKVkXVl@VkUU@ylUœVVaVL"],encodeOffsets:[[116888,29526]]}},{type:"Feature",id:"4309",properties:{name:"益阳市",cp:[111.731,28.3832],childNum:5},geometry:{type:"Polygon",coordinates:["@@„ŽÆxXL@l‚V„@ĢšVI‚bXKl@nVV@„XVŽ„JlbXalX„W„LVKš„„UVLl@VV„@ôބ@@Wn@lLlK@wnIVJX@VX@lVVUL‚VnkVVnKValUXblKnXl`UbVLÈU@W@IšKV@@bUV@Lš@lƒXV‚@VXXblWnLVblb@JnL„VUn@llb@„ƒx@ÞUV@nU`VÔmlX„mbUKUVUV@LVVUn˜ŽUb@°UXš@U‚VzVxnlVškšVnlVnaWƒ@wnIn`@_la@y„kƃVƒšU„L„xl@„ƒXLlmUUVakU@¥ÆwšblUUaôVšU@ÅXyVImƒ™ƒkUaġ¥ÅUWX™ƒKmU@Lƒa@UmUUƒUalan@VUnK@wm„m‚L@V„lXLVVl@VI@WX_™m@a™¯mKUkwW¥UK@_UWWLUVkUWL@WUIkVƒU@JƒwkLUUmJVI@WkXm@VmkKUIU@mmm_@VUV™@™„kJċwUU@KUWkkW@IWW@km@klwkWVkkU™V¯m@kWLU`mIkmkXm@@`@L@xUKWkU@VL@JUU@mbUKVa¯WVnL@`lXUVkU@xW@UbUWVU@UJ@„lnU@m‚nÈmVƒa@bUL™wUb™@@VkxmUUƒ™UV›K@IƒUƒmk@akm@wmIƒŽkK@b™VWXkm@wULUmm@UVW@Ub„mbkKƒVn„U@Wl„xV„U@UXmWUXmlnbUl¯Lmn"],encodeOffsets:[[113378,28981]]}},{type:"Feature",id:"4301",properties:{name:"长沙市",cp:[113.0823,28.2568],childNum:5},geometry:{type:"Polygon",coordinates:["@@lVUllXkx@lln@‚XX@JlXXl‚V@LVVČxlIšƒš@VU@Un`nnV@VJlLUnn@lW@XUJnIVVlK„x@I„VlUVJ@XXKlVVUXKVX@`VLX¦lxVŽnLš°‚an@„„‚bkmVaV@XL@U„KlU@llLXUÞJWkUknaÆxnŽ‚knK@w„@l„@xllUXUJVVUb„n@blV@bnƒ‚LnKVa„LVbVV„UX@W¥XKVL„VVklUVy„U„VÈÅlaUK°wnnÜbn‚V„VL„aVVš@šn@VmnVlIlJna„@Valkn@na@amwm@„UXw˜K@aUUVUUaVa—wWK@kU@UaW@kKUUƒƒ@k™W¯XWan@k„™mmÅ@@I@U@KmLkaVUƒKkLWVUƒk@UVmU@am@kkk¥ƒUƒVUK™„maUb@ŽUb™I@aƒKkkWm@W¯K¯b@VmaULVxUXlVk@UxVJVbUb@xULƒ@ULWW—LƒĕmxVVL@šVb™KUwƒaŲWwX@@WƒUWLU@VbkV@aU@@VUnmJ@VUn@VƒLUK@U‚mUIk@UÇmU@@UW@J@LƒbUmVI@aUmW@@bkXUx@lmLUbm@UbkJ@V@XmlUbkKm@ma@kUaVU@aUK@mImJUIkVƒUƒVUakbWwka@UWKkLUamKUXm`Å_U˜ƒULmaU@@lUV@X"],encodeOffsets:[[114582,28694]]}},{type:"Feature",id:"4302",properties:{name:"株洲市",cp:[113.5327,27.0319],childNum:6},geometry:{type:"Polygon",coordinates:["@@X‚‚Unw„Ė˜KXXVK„@VK@wVaUaUIVwl@kUVWUwVKnb@U°a°LXŽ‚@Xnll„L@bšJVa@VanbšƒVL„U„V@al@@UV¯ÅÇ@Ummk™w@¯ƒyVwnUVVVUkmWV—nKVUƒa@WXkVKn@lUVU„VVVXIlV°VnI@VlKnV@mwVm@LXKWkU¥wWwƒƒ@k@m„X@KX¯V@VUVa@VnKWkœƒV@VUkm@aWa@wkUWwkmV£VÿXUVL@mVIXaò@nW@ašUš@@am™@aUU„UmXmWUk@ƒƒnUW@_maVm™wUkamaUL@aƒwƒW@akI@UƒxUm@kmKUk™lUŽ@b„zV˜m¯xUVU@ƒXVxm`kÈlxXVW„@¦kVUn@xƒxƒKUwÅKVXUJWnXŽmVUxWL„¦XŽm„mK—bmUUwW@UV@šk@ƒšVLnŽlbLm`@¦VVkX@`WIUŽxVnlb„WVbXIV‚lI@l¦Ç@UKmbk™W@UbUVU„ƒl@n@VmLXb@JWbUnkbVxUJUxWXXlWL@V@V@XXJWx„zUVVVVKnXW`@bkIUl‚„nLVJUbUIWVXlWV@XklVbnn@xlš"],encodeOffsets:[[115774,28587]]}},{type:"Feature",id:"4308",properties:{name:"张家界市",cp:[110.5115,29.328],childNum:3},geometry:{type:"Polygon",coordinates:["@@@InWVw°wš„@š@šblUœKlUlV„U„@VUUUlW@aöUlUlLÞ@@aVKXwlK@UX@@UlwkƒVkUm@m›@ÅVƒ@akwVaUk›UUlUL¯wƒƒ@UUmƒ@UkƒKƒlw±UULVn@l_XyWwÅ@VUUmJUXU@@mmƒU@kxW@UaUIWbU@@mU@UxƒnUbmKk„WJkUValƒ@aUkUxƒlW_@WUIU@ƒbkKWUJVnUb™bWb„lU@nl›„@XnVmV@n—mWV@LXl@X›JXVmzkJUXmƒ™KULm°Vb@xnVmnUšk@ƒƒ™VƒnnlUb@nm¼m@Ûǃ„Vl@X˜mnm„²ŽmL@x™K@LUl@nULÆx@V@VXVWbXX˜l„@nLlm@bVKœX‚W„L°bnUš@VaVUš@šmšVw„JnwVK°zn@V‚Vb„a„@Ċ¼"],encodeOffsets:[[113288,30471]]}},{type:"Feature",id:"4313",properties:{name:"娄底市",cp:[111.6431,27.7185],childNum:5},geometry:{type:"Polygon",coordinates:["@@lL„nJ@xln@bnlV„‚„@JœLVUšŽV„nVlw@Uš@VašxVK@a„bnUmÇnV@km@ƒ‚I@VUVVXVaX@@wlVVUkW@_mKXU°‚UbVLnaV@‚V@IUKV@XlVL@w@K@_n@lWlnnJV_XK@l°nšU@WVU@kV@nbVK„V—lƒ@nLlƒ„LXU@ƒlmkw@nW@UKVa¯IVn@@aVUUKl@nXVKVn²a˜ŽXblKnLlmVI@KUU@akLUaVa‚UXm@aƒ@wVUVKnLnWlXl‚n@@U@anUVm@U‚Inm@IUK@UmKVmU_kVUwm@@VmL—K@VƒL™aUaVUUUmKƒ¥ULkšƒVWaXwWa@UXImWUaULUUWKk@WnXbWŽVWnk@UV@bU@@bƒJ@bƒV@XkŽmb™UU`VbkaWzƒ@klU@ƒb@VƒwUL@bV@U`ULVL@VUK@Xm@XWWIUbUxm@@lkkÇwƒVÛÇW@¯Å™UJ@xƒI™xƒ@@VULmKUnUxmKULUUm@@‚ULƒU™JkIWJ@b@LJUW„kJWnUV@nn˜Ü_nJšxU@VbšnUxlškb@lš@"],encodeOffsets:[[113682,28699]]}},{type:"Feature",id:"4303",properties:{name:"湘潭市",cp:[112.5439,27.7075],childNum:4},geometry:{type:"Polygon",coordinates:["@@Æ`n_VWnLVblKXL@VlbXxlaVb„U„VlUVJnInJ‚@VL@bUVVb@lnbn@lLVank@W@UlIVan@VanK@kVwlW@aX@Vn@bUJVn„a@K‚IX@@VV@nŽVÈl@VJn@VVL„K@UVm@UnIVm@UV@@blUUaV@XK„V@XW@XxƱ„bVxšLUa@™UKWk™@wmmUalk@WXUWkXUVJVaUImKƒVklJ@aX_mWULUUVUƒyXwWI@W@U@UXKWkXWVwU@±_U»ÝKUaƒLVbkJkƒWmXk@UVVŽmIUV™J@UU@UamLmwUVU@mnJ@VUnmV@b@Vm@kkWmXmKULUV@x„Ž@bWnVUbVblK@bVV@LUJknmKkLWa—±bUmULmWk@VLUV@bm@U°JUbVLX@@mlxkn@„WVƒKk„mK@k„"],encodeOffsets:[[114683,28576]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/jiang_su_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"3209",properties:{name:"盐城市",cp:[120.2234,33.5577],childNum:8},geometry:{type:"Polygon",coordinates:["@@„n@‚°ĀÞ°@¦ULWKkx@bkLWb@lUlVXXJVbƒnUKmxXV@bm@@Xš‚„LޚܦXlVnš‚mzVJ@n@‚²ÞôkƃÞaȰĉ‚wnljÜó„éVÛnĊīČlj‚ĉ@ō@KÞUlU@ƒkklÇÈњÑlġXɛ@UġƒƒaU@U_ƒW@n™@kaUL@VW@kKmkUV@bkbWW@bkzma@ƒJWI@KUKULƒ@U¦™`@XUJ™U@KmXƒw¯KXkmy@aUIWJXXmV@K¯UU@@bVL@¤VLXbV@@JVXVK@„„JVn@bkKmakVVXUVVVlI@`U@nzVVƒb@¤n@@UlKXLVVšI@V@nV@V‚@ÈUx@šóVōšƒkÅWó@mU@bk@Ýwk@WbXxm@@J@zV@kVƒbV‚nLWVUX™WUXUŽWLUŽ@Wl°z@VkxU@UVWIxWJkbƒĬ„nW@@bUl"], +encodeOffsets:[[122344,34504]]}},{type:"Feature",id:"3203",properties:{name:"徐州市",cp:[117.5208,34.3268],childNum:7},geometry:{type:"Polygon",coordinates:["@@XKVX@WnIVx@K°Lnll@@I°K„nVašU°x²mlxš@VanU@aƒk@akmV@@w™@Ua@aUwVwUw@w›@UK@£kaĉlóIÇVkŽ±@@kUKmVkIkxW@Ua¯UUm@UVI@WVI„JV@ƒ@Um@Uana„U@m‚I@J@XV@XaVlkXƒVaUUWLUyVIXmWak@ƒXkJókƒJUL@KWkk@ULU@Wa™lUIkJmI™mk„VbVš@lV°kXUKWKULU„mb@VUlVnƒb@VV@IVKUUmU@ak@@bmV@xklƒUƒU@UKmV@nƒJVbkXƒKUamLUJ¯UUVmI™bVV—Ll`@LƒLU`m@kXUVU@V„lxUK@xkIWbUKƒx@V‚kVVn™b¯@@U™@ƒxk‚mbkLÇK™b™@@XnJ@LmVklƒ@@XƒlUƒVkxƒakVVb@bVnUbU@@x˜VUšVb@š„ŽnIĊ`šXVVôJš_„K@xlU²Klk„U„@VaVVÈm@kVUVmnamUUaVƒXIVJ„@‚ç@¥nkVLn›„@@XVK@VUX@JVUV@UnVJVLUJVLUVlšnI„b‚KnU@m°™VanI@anV‚KVL„an„lK„blš„KÞk@¦@¤@„VKnLVK„L„KVzlWšLX@VmV@VbnU°@Ualk™˜WXLVU„KWkUUWšƒ@£Wa"],encodeOffsets:[[121005,35213]]}},{type:"Feature",id:"3206",properties:{name:"南通市",cp:[121.1023,32.1625],childNum:7},geometry:{type:"Polygon",coordinates:["@@VJ@bnzWl°L„xnW@LšVVI@Wš_V¥„@VKVL@LXJ„I‚@nbly@aXXla@aVUnllLX@@UVKlbš@@m„XV`V@„bĢ„lkČÇƃȘ¯šwnĕVĉVÿšUƒUĠƒŦğlXÑVǵ@±ōLʵĖ¯lÇbÝÞ¯xk@Çkķé™n¯@ğŽġƴǫ@kVVlUbƒL@xULǂóLUl¤@nkVV°VLkxVb@l™aUXUKWĖklVX@¤UšƒUkb"],encodeOffsets:[[123087,33385]]}},{type:"Feature",id:"3208",properties:{name:"淮安市",cp:[118.927,33.4039],childNum:5},geometry:{type:"Polygon",coordinates:["@@šnźUôÒɴ胚l¦nĖV‚kbmš„X@xVlVL@xUb@bUJVnUx‚šœ„lKVLÈx‚m„zXV@lW@XV‚b@bȚVxnb‚ƒVIXa°L„aÆVVaXUlK@aXIƄVlXKVUlIXalK@alwXLVK@¥Ý¯¯ÿ@ƒmVk@aX@ƒm„īlaXI‚wXJVUV@lw@U¯yb›UaƒUġUÅaUKVknaġm@kUm@wÆIV±nLÆw„ÇnUUkƒ@ƅÝU¯JÝI¯¦Ul@bƒ@@VVL@l@LƒLÅmƒL@b™@UaVaUWmLUKV¹KƒLWKX¥WI@mXk@UmaUVUU@VmL@W™bkIUWƒUmVóIkbmm™@UbVLUxmJkU@bkJWbnXU`Wz™KUÞÈlVb™Lmx@„kè@Æ"],encodeOffsets:[[121062,33975]]}},{type:"Feature",id:"3205",properties:{name:"苏州市",cp:[120.6519,31.3989],childNum:6},geometry:{type:"Polygon",coordinates:["@@ôèĊVnX°¤²„lxƒÈÜ@²x@J@b@X‚`nIUƙUUV@bl@VVnL@L@xƒJ@X@blJXnW@@`XbW„kVƒ@UbVxƒXUxkV@LóxVbUVWš²šVJĸklUǬ@ĢƳĠ°@šmƒī°»ÈÇ¥ULUU±a@bU@¯ƒU@KnImUVWUk™mXUVU@lIVaUUVWKUbUkWKU¥n£WakJUkUL›K¯L™KkƒVIn@VaUƒVUUƒ›UkVk@ƒU@amUkJƒ@UUlwX¥W@@UkVmk@JUakL›@kk¯ÝmJUn@nmVXlmbVVkn@„UJ@±WUxV¯a¯KōbżÇxUxƒšUUlWL"],encodeOffsets:[[122794,31917]]}},{type:"Feature",id:"3213",properties:{name:"宿迁市",cp:[118.5535,33.7775],childNum:4},geometry:{type:"Polygon",coordinates:["@@XbWnUJVzXKVVUbW„klUWbU@@W@IJ@nƒVmbVbn@@V@„UŽƒIUJ@XUJ@VVn°VVbX@lwlJnUVL@l²@lÈUôJĊklb@¤VLœ@@xVxUxVx@bVbš@@xU@ln„mnX˜mXLVmV@X@lxVnVJôL„LXa‚x@b„@@KVL@bn@@m@™@alLUUVaU¥nIV±‚I@mXI@aWWXU@LlUXWW_XWmaUwǙ@aaWUX@@kWUƒynÇwUKkL›ƒ™VwUmVI@aVa@wUKUk@wƒWn™laUmĕk¥„™ɳçóÑŹV™mmzkVmm@a@Ióƒk@@LWU@`—„WbXLWlkImJVn@`nXVbXŽmL@Vn@‚l@nUVl°Xx°U@LVĠ@z°˜@¦UV@Xn@VJmV"],encodeOffsets:[[121005,34560]]}},{type:"Feature",id:"3207",properties:{name:"连云港市",cp:[119.1248,34.552],childNum:5},geometry:{type:"Polygon",coordinates:["@@@‚lzXxmÆV„„@@¦„@l`XnlKšXXm‚KnLla„b„@„xmbm@kL@V@Vl@@VUXšJX„mbš@@„°Æ@èÈzlW°XĢJlÈ`lInbšWV_@mš™@UUķnƒôw°ÆmnaVƒVÛVmĸ»Ģw±Ý@@mUIny™UmWkۥݙƒK™@Wn@@aWUnwVL„mUaWIUWVk@kkJUVWLUkŃWJ@bkLWVUbÅUƒb¯KWbUJ„WXX`WXkV@KWVXX@bWJ@nJU²mJV¦UbVVkK@b@š@nm@@aUK@Lƒ@@awWbƒKóKUIUmkwW@U@UnWK—nmWƒn@b„l@bmVUb™@kw±n¯w™VUb"],encodeOffsets:[[121253,35264]]}},{type:"Feature",id:"3210",properties:{name:"扬州市",cp:[119.4653,32.8162],childNum:5},geometry:{type:"Polygon",coordinates:["@@VUXblVVV„b@xV@kz„V@l‚wVLUbVV@VU@VbUbl‚b@nkĶ°IÞV@Ɔ„VlmVƒÈÅxmKU²ÅJ@xVn@lĢnmbUlVLÆbĢV„V‚bœV‚aXk‚@VXKVVWšXVWXUmKU„aWaU@™¥@£XW‚UUV@@ynam_VWkUVUna@ÆV@mnkWmXkWU„W@k„@@akklƒlWUI@UnKl¥™I@VVma@a@I@U@a@anK@UmK@ÅVUnJl™kI@aVwka@mVIUW@UWL@WÅbmIƒƒULka™UWƒUxkLUKWlXL@VƒImƒÅVƒU™mĉL™Uól¯I±l@ÒUbVbUVVXUJUnVV@lnbl@"],encodeOffsets:[[121928,33244]]}},{type:"Feature",id:"3201",properties:{name:"南京市",cp:[118.8062,31.9208],childNum:3},geometry:{type:"Polygon",coordinates:["@@k@ma@kUUVmVIUWVUUaVa@Ѳk°Jôk@Wmk¯KmX¯aUakKƒƒWU„@XU‚LXaV@@mUaVUUl@VmkaUXm@ƒWUUna°IlmV™m™IUW‚@Uk@@aV@VVX@„V‚I°»nm„U@VKVan@m»UaU@U_@WlIUa™aVaUala@¯n@‚ƒkaUkUUWKU@mwkUUmmL@K@ƒLmUUVƒKƒVÅImU—JƒƒVkVVLšèVLVU@W„L„V„š@nVÜULVŽUL@bW@XbWbkJƒUUVUxVXmVk@WUUkVmIƒV@„nbnVWbƒJU„kUULƒa@Jma@XkK@VVL@L@JƒLUVU@V¼ƒnXlƒbm@kbUKmn@lVb@VXXV‚UV@b@LVbÆxXbl@@lV@U„VV@XVK²VlIš`„UbVbUlVVn@WXn@@VUV@„@KmbVLXқLkKƒV@nX@VVUV@b™nVllbšmnb„IWVXU@`lLlknVnmlLlbUmVInK°nUƒU@l@VU@Vn@„ƒ@alI„`VIXaVaVa"],encodeOffsets:[[121928,33244]]}},{type:"Feature",id:"3212",properties:{name:"泰州市",cp:[120.0586,32.5525],childNum:5},geometry:{type:"Polygon",coordinates:["@@lUU@@y@In@WwXal@Þxl@@anVô@ÆX„lŎ™ôU@™Vw@ÇUU@@m@U™JUUWKkL@Vm@@£„aUUmyV@@_kJUUVUUWlUnblL@aUmƒI@ƒULUW@IU@WaUK@£UK@aV@°V@LnUWWXIla„VV™@£UWlkXĕVLVWšb@kUalwUKU¯lU@mk£VôKȁVK@w„KVaUkķlUI±™ğ¥ÝUŹš™Ž¯ôm¦ƒĸ™‚@XXK@VVXUJ@nlbUx@blJkšmIUV@ÆnL@VmL@b@b@V@J@bnb‚U@UšJk¦mL@VVJkXk„ll@bƒ@@lƒXXVWlXnml@nÅU@ŽmbUVlVUXn`mb@zU@V‚VWX@¤š¦V@Xb"],encodeOffsets:[[122592,34015]]}},{type:"Feature",id:"3202",properties:{name:"无锡市",cp:[120.3442,31.5527],childNum:3},geometry:{type:"Polygon",coordinates:["@@nLƒÒlxUVkL™am@™ƒkVWUULUxVVVbUV@bVLU‚nnź™ÞVĠ¦X™VUUaôw@KlUVw„WUwVa„@lUXƒWa@_X@WmkI@a@W„I@w@KmKUUk@@aVUšVVÅmJ_@W@a@I±wÛ@ƑÇkw±ƒ¯£mWĉUóçƒK¯VkUWK@XkV¯UWabƒmUa™UUb™lln@b@xƒbXŽWX`@„VxUblL@bn@Vb@`m@XbWnn@l¤„n@xnVlU„™VLÆWœkV@VbÞJ‚_nƒl@nKVU@aU™U@mVk°WVLUV¯bVXŽ˜bXlVn@VmL@x—V@bl„š‚@œnW@X@VVJ@²VJVU"],encodeOffsets:[[123064,32513]]}},{type:"Feature",id:"3204",properties:{name:"常州市",cp:[119.4543,31.5582],childNum:3},geometry:{type:"Polygon",coordinates:["@@„L˜ŽnxUbVVƒL@xnnW‚nn@VVXn@‚yœImx„„°ƒšL„a‚¥n@VkšKVw„W@nX„VJ@b‚@UVn„ƒ@UnUV@L‚b@`VLklVÞn„Æ@VaXLl™ÈJšmmVUK@aVUUaUUVwVKXVlUš„n@šblKVUkw„ÑmKUVUI@±UI@U@WmX@›™kƒ@a˜U@wnK@UUmWk—aWU°aVUUK¯XUl@nVŽVš@bUVmLk@m„`ÝIUaU@›lÅXUKƒškVmU@wƒmk£m@XmWan@@_Uam@@akKVaUw@ƒW_XW„a@w@akmm@mL@UJmnUKƒ@@XnJWLkKUb@„Vxk„WƒL—aWVUImVULUK@L@lkLVVVllb„m@@°kbVbUbšbVbkJ@XV`V@Vbn¼"],encodeOffsets:[[122097,32389]]}},{type:"Feature",id:"3211",properties:{name:"镇江市",cp:[119.4763,31.9702],childNum:4},geometry:{type:"Polygon",coordinates:["@@šVĊKšn„VÆUn„„J@UWKXkVLlKVwX„šVlbVK„„nJÆaš„ķn¥°óÇIkšWKUbÅ@mƒUÝlkUK@_a@KVUVm„@mƒVU@@aUIWƒ@mƒXUx™LUlm@¦ƒb™K¯„ƒƒnw›Jzm@UW@UmmXmm@w„KUUVamw—ƒKm@UbUL@ŽƒVmn¯¼JƒUW@UUU@@bl@@VŽVXšJšnnU‚‚k¯JmbVV„Xn@VWlbUnk@VVUŽVb@nU@WbKWVƒ@XV„„lLVb°bnW°Lnl@X"],encodeOffsets:[[122097,32997]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/jiang_xi_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"3607",properties:{name:"赣州市",cp:[115.2795,25.8124],childNum:18},geometry:{type:"Polygon",coordinates:["@@„`l@Èbln„@„KVLl@„V@bȎlnšKXkVlVL@„lJnb„¦VKVVnX„W@w°@VU„mln„UV`šU„bVUV@„xnKVI°KXKVkVL@al@Xa„LVlULWV™VVL@b„x@VXVmb@x@V™VV@nn¤„šlb°b°KXXWbX`lbXx‚z@x„`VIVUnK„L‚x„WXLVKVbVLVU@wnW°b„@nalX„‚mXVJn@U²mKkVl„U@@xlnœaVmlKnœ@JVLlŽnVššl@XXÆèVlUX@xVLXVšb°W@wnUWmXk@K‚LVwUmUkUKUw@wVaVK@kƒ@WnkUKWkwlmXL@KVUlLVKXmWU„L@ašL@malaVk@aa‚ašƒnXš@VVUblb„Jn˜ƒXa„V‚wn£„K@UWmUk@ƒUaWIV@b™JW@KmmU@aUUUkmKkVKlUU™nKVU„lVaV£Å¥WUUK@UkUUw@m@mIkƒƒUUWƒLƒK¯Uw°¯@wUKUbƒKmƒ@kkKUL@UUKV¥U@manw@k@U@Wm@@U@Wwkm„wWaUU@UUmV¯kwƒ@@kmƒkKkUW@UK@ÅV@XWWkXa@Ul@Va@KVaUUU@ƒaXwla@UkVWaXk@K@lmkUmV@Vmbk@ƒ»XIƒ¥VUkƒVUVU@anKVUƒKUalU@wX@˜™@a@K—@ÝwƒL@ŽUnÇlUIkJmn@ŽƒbVVb@VmnkLƒV¯U@ƒ±l—IWmƒ@kaUI@aÇU@K@KUIkbWbƒJUIUyƒX¯ƒUbU@méUUmUk„WK—xWIkJm@V¥U_UJUwmVkšƒUU@ƒƒƒ@knƒwm@UmkWJkL@n@VW@@‚U@knm@kUml@xÅxƒ@@XUJlb„@VX„JVxn@lbV„@lULnV@VlnV@bWV@bXL@lVLVb„V@blLn@Vl„K@xln@bX@lašLVbnKUVVb„KlXVVkxƒV@nnVUb‚lV@@z—°WWkbƒIk‚WL@LUJ@bUI@b™`@UmI@mkK¯XW™™mUV¯@UUVUUam@@VULWUJƒIm`IUJ›KUkW@Uxn‚WbnnmlXbmIUVmV@Vnb@V™LUKWLnÒVVV@V„UL@„kJUV@bƒÈ@ŽšV°šŽ@XVV@l@xUz"],encodeOffsets:[[116753,26596]]}},{type:"Feature",id:"3608",properties:{name:"吉安市",cp:[114.884,26.9659],childNum:12},geometry:{type:"Polygon",coordinates:["@@lxnb@V@bV@ln@‚n„‚lInš@blVXK‚nk¼@VUKWL@b™L@`UXU`ƒ@V¦XLĠ@lJ„¦@„nV@l°nn@‚mVXnaš@nb‚K„n@l„IVƒš@VanJ@_lKVVnš„L@L‚K@Vn@VbšUVanKlLnbnJVbšnWVnVVanI@‚Vb@L„bVKVanXVbVJVU@aXLll„bôlƼXxVLVK@Xn@ƒxnVVVmb@LnVVKVXV@@mnaVXUVnV˜K@_UaUmšwnKV_‚anKVLš»„K@¯ÝU@›™U@kWlUn™lknK‚VnaUkma@ƒUIUwl»Åw@ƒVwV@n™‚n@ÈXlKVmna@kVw@anm‚@n_WWk@™™mUkUK@Im›kLUn›bkm@wV@kƒlUnLV±m@UInWƒkWmbƒ@¯amX@xUVUKUaULWKƒXwƒKmLUVUJƒ_@wyWwkaW_XaWW¯L¯akaƒ™m£@mUUš@U@wnaWU@Uƒw@aUKšUXUVKUkƒKWbk@@bUKUlWL¯LUJmLƒwU@UVƒa™VU_ƒVkmƒnUV¯@@xƒXmWUUULƒ¥makI@ƒUKUkWl™LkmǍ@aƒUk@UKƒLƒ@kmÇak@ƒ_VlkL@`lbnšlLVanLnbmVÆln@škJlbknmKUbÝmmwULUK@bkLWKULUUma@Kk@UV@L@llbVzšxUxnl@bVLmŽšŽ@IVJXœVlƒLV`@bn²@J™@™V@Xmbñ@WbUJ@bm@@LUĬU‚„¦lV@xXb@blnUV"],encodeOffsets:[[116652,27608]]}},{type:"Feature",id:"3611",properties:{name:"上饶市",cp:[117.8613,28.7292],childNum:12},geometry:{type:"Polygon",coordinates:["@@„„@„V‚š„„I°`nm¤²@bVJUVVXUl@Vmb@xV@XbmVVœ@lkLmbn`VbnU‚@Va„UnbVllUXV„a@w°VW@_VWšLššnVlbšLVbnl„KšnVK@IUW@_@am@™‚ÑUólK@U@WU@VwU@UI@aUU‚aXƒƒ@kwmJV@yX@k‚anƒƒ@mkwVmmI@aUU@aUUW@kVkV@@anKš»„XVWnIVUl`@_„W@wlUœV@UWKnU‚bnŽ°InJl„UV@VnI‚b„Wn@VklL@l@Vn²m@U`kI@bWJƒnV@°VXnJm„XVmx@VVL@bkLmWULUmU@ƒbWXb@llnX@‚xkxVV„nVV@¤nL‚nVxnJVXX@˜ššbn`VI„b„@„blmlLnaV@„blWXnlUnbl@„ƒšKVanUVmm_XK@kWWnašU@UnaWUXa›ƒXamUkKmXUWƒLX¯WakKm™nUWwXa@KW_„aXWW_@WnIVl@XU‚LnWVknK@ImyUUÆbXK„Û@W@IÆUnƒVÝlkVK@mUIVwkUVaUm@aVIVyXIƒaÈwmmk@UnanVUmÅaó»lwšW@kkUVmUK@WKLƒUmWULkamK™Lk@Wa@wk@UU@U@mbUIWVKUXWmkUmVm›U@LkakKƒw@w@U™¯ƒ‚ƒUUn¯l@bmn@xkJWxkL@VkI@mƒkmJUI@V@b@VVxnbWlkÈkVƒLƒbkKmVƒL@V@²nxW‚kLUL@xlKVx„bXmVnšWJ@ޙ°@n™xUKUw±`UImVmnU@kalm@akwƒU@UUJmxU@@Uƒ@kU@Um@@Kn™ƒVm@k™KmkU@@WUnkLWxkVUwmKmLkU™bmKUbVŽ@xUnkJ@n±ŽšUxVXUšWJ@LUb™lUnm@ƒW@nknUJUVm@kXllknVbÆK„VVbš¼V„@šUl"],encodeOffsets:[[119194,29751]]}},{type:"Feature",id:"3604",properties:{name:"九江市",cp:[115.4224,29.3774],childNum:12},geometry:{type:"Polygon",coordinates:["@@WUkVUkmaƒVUb@mVUam_nalK@kU›nUWaU@@wna@UVkUWVUUI@a‚±n£m¯_ƒJ™ƒU@ƒƒƒĉ¦Ul@UV™Km™mLlm@ğ¹m`Uk¯@@UVK¯™@UUK@amkmKkVVUa@UkUƒKƒŽUa™L@VVXUJ™@ƒnƒ@™š™WUbƒnVb¯V@LÅlÝIƒJÅkݙm@Ua™WUU@UmUXmmwVUUKWUX±mUam@kWƒzUaVmÇw@aÅLmKXƒ‚UWKkL@W¯IƒwVw™lkUƒJ@Um@ÛÈWŽKUxWkƒaUU@KkLVl@„UKUX±KUb@nVVUbUVmaUlUL@„ƒaUL@‚@nUlWzX`@„V@lx²„@Vlb@bšVÞ@°nl@UxVL@lUbVV@n²xVUVmnUÞb‚a„J@IšV°xnbl@nbÆ@VwnK@VnXlK°xnUlVX„V@Vl@L@lk@W_XK@KƒkWxUL@J„nVx@aX@VVUa˜IXlmL@bVVX@VbnK‚a²XVWƒk°a„@UnV¤nbmLmW@XbmJUbVL„aÞK„L@K@U@aVKlbV@nXlJœxV@VnšŽVȚ„ÞKôbźĕČmV@ĊšŽ²xÆIšV@Þ¦ĸ¼ÞVlŽVÞnxln°Jœk‚LXWVUVUVwnJVI@yn@lXlaXmWI@w—»ma@UmK@akKkXmW@_kaWakKWk@@K@IšWƒkUa„ƒ"],encodeOffsets:[[119487,30319]]}},{type:"Feature",id:"3610",properties:{name:"抚州市",cp:[116.4441,27.4933],childNum:11},geometry:{type:"Polygon",coordinates:["@@°V°UnÜ@n@lnLlV@bšV°L„lnLllVzVVXlV„V@@L@xX@WlX„m@UVƒL@V@n„°škVmVUnKlaXxVbšnlU@lVVnaVI@aX@V„šJš@V„@b„b@šVbš‚@X@lUL@Ž@VlIVm@wUVanLšalVnKnLVxlUXwlKVm@k@Una@mWIXKWUÛVƒk@a@UVWn@@kl@@W„XlW@_Um@UVK@a„LnalInWV@@xnI@¥‚K„—šm@kKmƒnk@mlI„¤laXbVblknV@U‚KXVlUXa‚@@Unw@±mU@ak_±a@ƒUJUIƒVKW_Xa@aWU™šK@mmUVa@IXa@UWmšannlmX¯WKXwVUVwƒ@XUlK@klJXa@kƒkmm@Uwƒw@¯ƒW¯kw@WmbULƒaUUU@mVUU™WmkUb™KmkkK@aƒkUƒ¯¥Uƒl—ƒm@akU@mš@KVIVV@KUkUVUkaƒUWb—„mƒIkaVaUU™@mW™„b‚b@bUlkb‚b@n™K@bƒKXVWnULkKUV@LWKknlxXŽVLml@X„Ž@lULUb@xVxVLVlVnUxK@LWlXnmV@x¯X™aWUUK@wVWUkÅçm`@mn@bUx@lmbUnkLÇWm@mšU@Ux@„Æxk¼VxVJ@„nbVlmbUmLklmškVlX@‚VœšV@°Þ"],encodeOffsets:[[118508,28396]]}},{type:"Feature",id:"3609",properties:{name:"宜春市",cp:[115.0159,28.3228],childNum:10},geometry:{type:"Polygon",coordinates:["@@@VlbnK@b@JšLlUnx±ĀXxÆW„X@lš@V„@@blJ@nX@˜xUbVVUbVV@b—VmnmJœ„@bmbm@klUbƒLmbœš@lVb@xUX@bVVVbV¤@LVV„bXlVw‚LXÜÇn@@V„IlVškUx„x°J@XlKXLV„‚WnLÆK@bÈxUnVb„ylXn@Vbn‚W²XV‚LVVUŽnxWnnV@VVVšXVbn@ޚÆl„IÞJÆk@K°UUa„mVa@UUUš»@wV@VƒkkUKUVW£U@UmW@@aXkVUnVlKVV„UUkVmU™@kWaUanU„VVamIX¥W@@aUaUVW@_mW@UnIVVn@VbVm@bVL@anKVUkƒWK„UXV‚Ikx‚@na„bVK„b@nVJ„_V›@Vw„‚VUVVXUlUUaV@X@VblašbnKlkVaXaƒ¯@m@U„KVUn@WƒXkW@@w@KU@UƒWkUUUykkmKƒk¯K™U@akUmK@k@mmÛ¯V¯U@‚ƒL™¼UKmLbU`mL™xVnVb@`—LmUVUUWmb@nU@UWULmU@KnaUUmU„wmJ¯IUJWIkVkaWVUIUlWaUIUVkKmbUIƒÒlVUnnŽ@VlLUJ@bUX¯@ƒaWVUKUXƒKUbm@UwKWa@a@VkUWn™@Uak@mbX„WJXbm@mL—aWVk@™wƒL@WmanU@knwWmkaWL—KWUXaƒU@¥l„UVVVbnwƒ¥nKV™»@aUk@a@UƒJ@kƒmLma™@mbUWnm@ULǺ@LXnmxUŽm@UbkbW@@akLmWk@UXmJmUkV@VUXVlULmKUxkL@lmXnJ@X‚l°Vnb@bU@WbKUX@VmKUX"],encodeOffsets:[[116652,28666]]}},{type:"Feature",id:"3601",properties:{name:"南昌市",cp:[116.0046,28.6633],childNum:6},geometry:{type:"Polygon",coordinates:["@@šXš™„@„mš@VIUW@UšKVb„„LlV@VVbUŽlUnLnl@bVL@V°šUL@V°@Vln_Ġºn@‚knKnššLVU@VkĊ¥Vk@™Uƒ™»UaƒUÅLUalmkklWn@VUVIlm@m„Xn@VmškVa@KXIV™UWVw‚™²@m@U@VK@k@W™Ua@™ƒa@aUƒ™@™IUƒW@@bUJmbUU@kkV™mUaWwkbmLUVUn™lWbUbklmL™akbUaW@U@VbkVWVUUUVƒUx@‚Uœƒ`UI@mƒaULƒamb@lwJWUƒVXLl„UVmL@bUK@aUnUam@UUmJ@VnX@`UXVŽVb@bX@W¦nJUbƒUmVVbXb@lVšUnVlƒVUUkLmUUVWl@bX@VnV@X¤VUVLllU„U@@x™¼VV@V"],encodeOffsets:[[118249,29700]]}},{type:"Feature",id:"3602",properties:{name:"景德镇市",cp:[117.334,29.3225],childNum:3},geometry:{type:"Polygon",coordinates:["@@VVX@Vbmz„xUlU@mbmL@V²xVbUVVblbX@šVškVykValKVI@bn@n`lVWnX@l„L@™WKnƒVIVa@¯nK@alIXJVIVWUw‚ƒn@nU˜„nK@alI@a@anKm_™a—™W@UWmIUwmmK@£UUƒmUUlwwW@km@kWaX„aV@VnVKnXlK@aUK@UnwWUnƒmIUW@¯mU„XI@alJV_n@m±@U@kkKUlm@ƒXamJ@UVUkƒmI¯JmamVXL@V›UkV@xƒX@`k_UVmJUXƒW™¼mL@bU@UllX@VV@bVV@bnJUnlx@n„Žm„b@lWŽ@zU‚nIlx„@W„bVV@bVJV@UxV@@X@VkLVôÒ‚šn@@b@`VX@J"],encodeOffsets:[[119903,30409]]}},{type:"Feature",id:"3603",properties:{name:"萍乡市",cp:[113.9282,27.4823],childNum:4},geometry:{type:"Polygon",coordinates:["@@VWnL@UVW‚LXaV@@ama¯Uk@WmInW@klKVwnLVKUkVW@UlUnVnIVWl@nXlK@bX@laVan@VnwWm@KȹVK¯m@kmU@ƒƒ¥kIğ@WKU¥„@V_VW@_šK@aXKVL@Ul»mWLkU@am™kJƒm@kmU@@a@UmakwU@›„Xlƒ@VXk`UIW¼kWWX@‚œ@l‚xV¦XlW@Ubn„@ŽmUkL@UmJ¯UkUWVUaƒUlm@UXWl„nUJ@LmLU˜nXll@bUVUUmVUn„Ž@¦šxlŽnn@VÆÈU°kbV„VxllnL@VnVVUl@V„„anL"],encodeOffsets:[[116652,28666]]}},{type:"Feature",id:"3606",properties:{name:"鹰潭市",cp:[117.0813,28.2349],childNum:3},geometry:{type:"Polygon",coordinates:["@@@XV@nlšL@lUnš„mŽ@Ln@@VlV„@@VV@nwVI@V„Vlx@bknlbV@nmnUVJ‚_²‚VxVLšw@mš¯@ÝXIm™nUWƒaUwkL@wVKlKXmw@±@U„KnUlL„a„KlUlÇXkmaUw@U@a@Uƒ™UkwUJ@zWJ™w@WbkVWUL@VmUklUaWakbƒ£kJ@nmln„lL@Ž™nƒ˜L@¦mJ@wU@mXkJmbƒK@bUL@VVn@`kXƒW@Xk@@lm@UX@V@b„lÜUXVWLXJ@nmb@V@l"],encodeOffsets:[[119599,29025]]}},{type:"Feature",id:"3605",properties:{name:"新余市",cp:[114.95,27.8174],childNum:2},geometry:{type:"Polygon",coordinates:["@@m@@WULUKWwÅ»ókƒakkWK@bUVUIUamWUbULƒa@KUa@mJUbmUXU™mUamImakKmLUb™VUam@@UL@KƒKm™UUkL@`mIUb™@U„@V@bVl@bš¼UŽmL„¦mxUaUUƒVkŽ@¦„VWbXV˜LXKlbXnmx@lmVnb@X„Kšxl@XU˜bnKn@WaXIWƒnal@Vbš@XmlV@U@bXb‚LVxn@Va„LVWVLXU„b°@VW@aVIkK@UmVmkU„ÑVJnalLVUVJXbVkVJXUlblUXJVI°JnI"],encodeOffsets:[[118182,28542]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/ji_lin_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"2224",properties:{name:"延边朝鲜族自治州",cp:[129.397,43.2587],childNum:8},geometry:{type:"Polygon",coordinates:["@@Wxĵ„mš@„ó¤VX@@xܼƨš²xWxƒV„V@„XVƒ„„„ƒbWšXllaÞU°Ċ„@ô¼„LôÝWanV¥ƒÑnĉ°¥šÅX¥°¯@w°w@»°k£°mÈŹ‚mÈbƃŎ¦„K°z@Žkxl¦UbU¤šššklV„KŤÞȰ@@bšV@nVVUlÞ¦lUllœVlU°ÑU¯Vƒ°w„bXxl@VŽ²„˜@n„ô¼ƒó°™kmVk²ĕ‚w@wV™ÞÞ@@Ġƒö»˜¯œ@‚„šbnb°mÞ¯°V°„ÈJmX¥mam™UřƒUƒlaU¯™ƒ@w™Kk—l±n@@wƒkÝVUUl±¯I¯b™a™lƒ@™kLmakbƒ@ġƒŹé°™Þb°šékƒƒLm™„wX™‚aÅb@bVlƒbVb—ÒVbUb›UUanwƒakbVŽUV›ak„¯„UŽƒLmxV°UxnôŻX@J„Xkl‚bkbĉaƒbƒWU„ƒ@ƒk„WUU¯@@klmƒ@@™Å@aƒwWXlKkI@WbUaVIUanUƒƒ@ĕƒ¯K™„mUnWUwm@£ċèkUmbUmm@@nkJUalwk@@nmWUan_óaWmnw±KœIƒwl@UmƒI@an@@mlUÅmV_™KUkƒ@U`@_ƒKUmU™@U¯™mmb¯@kb™ImV¯ƒƒLkbƒKƒƒÛ@ÇnɱJóaÝĢkb@„›x—ÒÇllœ@‚Ž²V‚„ÆUVV„UÇ°X„óxlV¯„lV@bƒV@n—x›@—¤@„șŎnxV¼knšJ‚nšKX°˜¦UlnVbUbÆVnÞWVX¦llšb@l°œVJôÒnLVbšbXŽ"],encodeOffsets:[[131086,44798]]}},{type:"Feature",id:"2202",properties:{name:"吉林市",cp:[126.8372,43.6047],childNum:6},geometry:{type:"Polygon",coordinates:["@@ôl‚zšaÈV°„šK@„mŽ—LWl™nšVxUV‚È@ŽÝĬUÈn‚ôLša‚„²VmĀkV@„ĠĊnU@b„V@b˜@nl°UVnÞaôJ@bš™V„¦mlkššbmVXx¯@Vxm„nbƒ„šbÈK‚V@bÈL„wĠyônšmnbÜ@nn„V˜x@n²K‚„„J@k„al@nxÞU„Lź±Vwkw¯LWWUš™kŎīVwƒw„°y„Vĕ°wÈVlkÛ»@wW@Uô£@ƒn™ĶƒXwW™aUamKóÑUI¯›@k™akkW¥XUmÝÅUVaUa‚mVk—¥W¯™Lm™IlmU»mwȚō@ƒ˜£kJUÇk@am¯y¯UVwƒa@wġx¦ƒKƒƒ¯X°Ċ¯¦U°ċWULÅa±b¯@UkÅWmVƒ™ƒkIUlóŽċ¹™`óIƒlX„WŽXxmbUƒLݏƒbƧ@ƒx¯bƒÈ—l@xƒš¯zƒaݤ@nšm„VWb²bmn¯J¯Ò@n„š"],encodeOffsets:[[128701,44303]]}},{type:"Feature",id:"2208",properties:{name:"白城市",cp:[123.0029,45.2637],childNum:5},geometry:{type:"Polygon",coordinates:["@@ó™ǩŁ@WlwUaƑwÛÅÇéĉamKƒōÇ@Iƒ™ôġVƒȁÑŹçƒ™ÝUƧċĉwóóÝ@Ƒ»ğL¯ll²@ƆÅV@¦m‚Åb@nmlU²VxšlUn™@VbnW„bÇbk҃š„n@èlnlšU҄Ž°Lšx@¼ĉb@҄šUŽċxՃènLVxƒÒƒbÅJ±a@_ÅJÅnƒŽVb„Kl„nUÜĊ@„Uš™xXVÆn„mšVššJÞ¯V™ĠwšƒXw°xWL„x„KV¦ôU„wVÝǬóÞޙ¼‚‚„ÞkŽVôȘxބU„lVn¦ÞšĊa°w„b°@šbÆw„lŤL²`„z°@V@@™nJVnl@@¥nUmmn„@mwnmmUnk@mlwUaƒLnƒ›wn¯°anƒWakI„ƒÇmXwÆamUXUlJXa‚UUklKUknmÞV@‚K@VWÞ@VkUwVƒ"],encodeOffsets:[[127350,46553]]}},{type:"Feature",id:"2207",properties:{name:"松原市",cp:[124.0906,44.7198],childNum:5},geometry:{type:"Polygon",coordinates:["@@„šźèȂÒU„óĢ„š@JŎȄ‚‚LnŽĊbÈêÜƃxVbkx@XǪłôš„kÞ`„šW„b@n°ašbšKšnVw°`š_X`W„š¦„ĊIkmVšakw‚K„x°UÞb„U@lšƒl@°¦œVW„šaÞbšxÞI@mVI@ƒVkŚUWK„¥nL‚a@ƒ„@ȍ„@°ƒÆ@nU@KÞalkUwVékUWw„™kU›VkkƒJk¯@»ókƒV¯ÆÇI@bĉô¯@™ķw¯nmmÅL¯wƒVƒUÞy@UówÇLkmm@@UóxkkĉmL¯wVwkWWX™mLõm@kűV_ƒƒô»ÛƒÆ¯@™Va™VšaĠVlmğwķUóÝƽ£ÇJkbǫaƽLW@nxݤkzƒy¯XɅm@VšôÇX¯Ė¯ºÝnUŽnLVlUÔmV"],encodeOffsets:[[126068,45580]]}},{type:"Feature",id:"2201",properties:{name:"长春市",cp:[125.8154,44.2584],childNum:5},geometry:{type:"Polygon",coordinates:["@@„U°xÆKnn°mĸxš°@Ċó@aÈJ°Å„Uôl@¼l°„IllœUlVƒšXxlVUêVxkllnÈUVll@Vx²IÞ¤VUlVnIôlރlwô_„›„bVaĶLXÅÞÇ@K˜¯@wÛaƒçn¥š¯WXyW¯XwƒUmmÛ@ma™nómğzƒxÇK@aUÇL™a„ƒmanƒUw°@WwnU™al™nkƒ¥šU™@aóIÝbUm¯Vmk—@@aƒU@amVğĉ@ƒlUnÿ±Uƒ™bóKmVÇÞī@ÇVUUw‚™šmXk˜Kn@ƒ™L¯ƒÇU™byókōè@b‚n@lÝX@x¯ô@ƙUV_maXm@aóƒJWxnX@ŽVVnĖVnUJ@nōÆǼV¼kxƒLklÝw@xƒx@zV`ÅbmxU±xU„nnm‚kn‚ŽğU™bUŽ‚šUb@šÅ°Ü„󼄄U`Ʋ@lön‚KšnXWlXUx°xnKĊllôw@Vn@lnÈKôx@VÝz„V"],encodeOffsets:[[128262,45940]]}},{type:"Feature",id:"2206",properties:{name:"白山市",cp:[127.2217,42.0941],childNum:5},geometry:{type:"Polygon",coordinates:["@@Ušl¦kÒÆ°„IlÒU¤ôz„¼lJš„U„n‚ÆXVl°@²aÆbVKČXV¯°¥¯ĉ°W„„„L‚¥Ģw@x„bUx°V°zn‚‚b@ÈlVŽlIœ@˜w@m„U@akU°ƒkUôwWƒÈ¯VUƒVUƒÅ±U›@kÈk˜Ñœw@ƒlaÞġƒUÞ£@ƅ‚KnÑĢ¯@W‚aUaVUVkkw@a¯@¯™Ý™ƒVXnW@@WkXmK@xkKUb@bW@Uw¯„mmb@WKUbmUbUaWbƒJĉIVW@I—l±LkšmU™bUm™@ƒnkKWa¯n™@„`Ubma™„ĉL@bƚ—@W`ƒL@n¯‚Xb‚@kb@x™Lƒ„™@V‚kL±™™mlUIU¥mL@lÅx@_laƒƒ@U—aƒV@kmmƒK„£ƒƒLƒƒmKUnÅKVbmXVlèĉUUbml„ĢŤƒIlŽ¯bǦœl‚@ô¼Ģ„@x°„l¤„n„a„l@x™b"],encodeOffsets:[[129567,43262]]}},{type:"Feature",id:"2205",properties:{name:"通化市",cp:[125.9583,41.8579],childNum:7},geometry:{type:"Polygon",coordinates:["@@ÆlXnĠxĢ°lÈ°š„K„°kXm‚@¦Vbk„ŤJšnݤk„VÞVVkȄb°y„™@w˜k„Ç°a„wƨ@„aސ„K‚VnaWwXWƒ„kôJš_ČºôVkƒ»óyV£kуJůlÑk¥V™ša@wƒkƒbƒmk£¯ƒ@wġƒó»@›kÈ¥°ak„JÆ£ƒġnkVaĊVkçWUnUaÆLVmnL„„‚KU™±@—„m@a¯U„bmV¯m@_ƒK™™U™ƒaƒÅ™Wó¹ƒ@UanmWak@@wmI@y™@mk„JVa™@UaƒIkJ@n™@Um±kkxƒm™Ik„ƒbÇm@Ž°bXn„V@Ž°ÈmlÞ¼¯XVº¯Lm„kWWXLmVVlknƒ@@lnWƙ„Vxbmšnšm„¯lÝaVȁè@¼V„„b™„ÆŽ°ÞUVšJ„„kx›I—xƒƒƒIV¤™ÒXxmn"],encodeOffsets:[[128273,43330]]}},{type:"Feature",id:"2203",properties:{name:"四平市",cp:[124.541,43.4894],childNum:5},geometry:{type:"Polygon",coordinates:["@@Ɇn°W„zlyÞ£mwX@ƾKǬblaÈIƾ¤ôÞĸVĠxnmmVƒ²w‚VnwÆaU_@y„w@wÞxlk„KlwU»È»ŎÅ@mVIUmmĕUU@mWXw„Iô‚@bWnnbU`‚šV@Å°ó@wÞW@km@aŎ烙@m°Ñ°Inm±aXaƒU™n@mƑšU¦@šÇŽ¯aU£šaU™ġ¦ÅҙJōUŻókUÇ@™¥¯ak¯mUVak@@aċçÅaUƒm¦Ý`XbƄ@n`ƒI™xĊÞōÞml@šUb@Wl™_¯JkšÇUÝÆÅb@n™„llUb¯„±a@ƒ—ƒWĉJġĀ¯™Unóšm¤œxôaVnƒxôI@x„V@bmƙ„@lnLmޯޙxVb¯þ"],encodeOffsets:[[126293,45124]]}},{type:"Feature",id:"2204",properties:{name:"辽源市",cp:[125.343,42.7643],childNum:3},geometry:{type:"Polygon",coordinates:["@@żôŎVšIÆÑĢ¥Vš™bV¤°bȍ@™V¥ƒ™Þ£lÇUUUÝlƒÞ£™mţIlƒUa@¥nlWƒ¯ƒL¯™kÇġ¯ğwWmÅk¯UƒVU„„bWlXlmnƒbUx¯xVVknlŽUbV„ÇKUb@„™VnbmlnzUº±bmJUbWÈnèm҄š@X`WL"],encodeOffsets:[[127879,44168]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/liao_ning_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"2102",properties:{name:"大连市",cp:[122.2229,39.4409],childNum:5},geometry:{type:"Polygon",coordinates:["@@‚IÞmVk@wXWÜbnwlLnU„@‚nLlbXW@a‚wnbl@XL‚aš@Ċ¥@LULnJ@xVnmV@VXXV@VJkn@VÜKXXôJlb„xl@„IVbnJVLUbn‚lnVw„JVU@ƒXU‚aUUlwn@°ƒn„VKnV°_VJšwl@nwlV„IXWlIVVnK@IWmkIVaVU@WÈUlmU@U„WUalkXġŻ@kIƒ»mm™akUm›ĉUŁV»²ġVĕ@aUU؍IɃ`ȃ@kƒw@ƒUƒmwĉ™@ƒWķсIĉÇbÝLkymbIƒwÇmÛbmbU„¯ÜõÈkÆVbŎxnXVÆnšǪ¦„bš¤Uš™xÝnĉÒmĊVȄ¤Èš„bƼ„Ā„„ÆÆބźb„VVbX„‚°²¤"],encodeOffsets:[[124786,41102]]}},{type:"Feature",id:"2113",properties:{name:"朝阳市",cp:[120.0696,41.4899],childNum:6},geometry:{type:"Polygon",coordinates:["@@na@UVI@m„ÑW™kaV¥UI@wl@„aÈbšm@wVašk„@@K@kƒ™@a@UUmƒUUalmU@KÇUű¯@±kUKVkUaƒaU@¥m@@¯k@WLUmkn@mmIkm@amU@wVmkU@Klk@U—m˜aXIWWUL™aULVbƒmk@UUmUk±™_Uym@mbkImaX¯WW™xWKzU@WƒkJWwkV™@Um@UbVVVVXb@VWX—@WŽ@Vkb@V™nUK±aUUlwX™ÇWKknU@mmUkƒLUVƒVUUVƒUaƒw™bkKmwnIƒ™kJ@nmbƒ`kmVkLWwUm@UUU™K@UmaUa@UUaWK@mUƒ¯Wkk¯VmUUŽ„xVXUVmL¯ymXkWUbmXUKƒVknWx¯JVnkLƒl@VVxnxlĀVL²WlX„l@bÝVUn@bnlÜaXblIVl@šš@Ȧ@VmbXV‚@@x„VVnUn@`°@VnXU@K@„VV@VmbnVn@ln@b„xƒ°Ub@bšLV`Ånƒ„W@@lUšnnWVU@Vbkl@Xl`XxV„UblŽkX@Ž°¦V„UVVbUlkV›@UbVbkLUxmJkXšš@b‚bœxVKÆlXX˜bnŽnala@ƒUk@U„VVklKVUXKVU°KVan@VUnLšKVL„WVaU_@mmUXa@m˜wXwVkVWXk‚k@›„k@klm@wXKl@U@KVUUUVaUƒV@„alL„xUx@b°°VnnVšxlIXJmx„LUVlV@bnX@Všb„aVx‚@XJ@b‚n@VŽVXȄl@llX@lU„Vô°°@ބVbn@‚V„k„@VW"],encodeOffsets:[[123919,43262]]}},{type:"Feature",id:"2106",properties:{name:"丹东市",cp:[124.541,40.4242],childNum:4},geometry:{type:"Polygon",coordinates:["@@lzXJ‚U@š²x‚@@Vš„@bUVmKUn„°n@lnVK„„nV@n@VlV„°WbXn@‚VzƒJ@¦@bkb‚bUl@bkbƒJ¯zƒWULWbklV„nb™¦VJ@„„K°U„kl@@W„bVn°@„Všm²U˜nX`„UÜLXmVXlKVbUVVnUbn˜ƒX@VUL@lUbWxš@²kl`n@Vlb„@nUVWVLVU@aV@²bl@ÈmšxWX„VÈU„JV„l@„„la„WnX‚KÈkÈ@Va°bÆm„@XV°IVV°UnalƒVUn@UwVU„@@VVJ„I@bl@XK@wWmXU‚UVbkJVXnJVI@mƒknwlKXL@`l@VI@UUaVKÞn„aVm@aÇ£XW„U@aÇUU@mbkKm£™@WW™ƒL@@Kk@kl›U—bWKUkUU¯UõÛƒmUUaVU„U@WU_W@kVkJƒ_WKkV@bUL™¯¯ƒ±mk¯ġƒğÑ@UmwƒKUakƒ™ƒa@a„m¥ÝƒIUWmk@w™mţ—L›KʝbȗKWĢklVbƒX@VV‚knÇV@XUVUblJXn@J"],encodeOffsets:[[126372,40967]]}},{type:"Feature",id:"2112",properties:{name:"铁岭市",cp:[124.2773,42.7423],childNum:7},geometry:{type:"Polygon",coordinates:["@@XJm@¯šmXUlnVbUJƒU@bV@UJWL@VXLmJVbkXlJXxVL@b@V@n@b@`Vbk@lxknV@VV™V@bUL@bV@@bVK@VXLWLXJ@LV@nbWJ@IUV„x@LVJUXVxVx@VV@@LXJWL@VU@@L@VnL@bVVmVX@@VVInJmbnLWVnVULVVU@VVmX@@JVz‚l@„nVVKVXރ@mk_lm„UUWV_nJlUÞÑÞVVUVƒVL„UVJ@I„Vna‚@@KV@XwWknwnKlalU„w„aĉݚwšJl_@aUaƒKUUU@WU@WXUÆ@@UVK@n@UnVVšblK@bœllb@b„bW@Xbl@UlnLl°°bš¦nKlVnI„V@UWU@WXkƒw@am@nm@aVw@I@KUaVIm±XÑlknJVnVJšaX_VaUaVKmwnkmmn@lU@U@mnašXlKUmUIVmklaUK@UlUVUW@U™kVm™a@UUU@JmUU@@bmb—KWV¯XUKm@ka@UVKVk@aUKmLkKUUÝUmbXbÇJ@k@WU_@m™™@klm@UXKVaUI@KWUXaƒÇWk™aWUkWUL±U@lUU@ƒUJƒI@V¯JmIm@@aU@Uwƒa™@UV@VkI›V¯aUkƒWkb@bVL„@@VVVUXW@Uaƒ@@b—‚ÝbUV݄@ŽƒLmUkVUbVllLUV@LššXŽWbUXm@U`@„kxlnnJlbnIllšLX„lVlUXmVK„n‚V@L"],encodeOffsets:[[126720,43572]]}},{type:"Feature",id:"2101",properties:{name:"沈阳市",cp:[123.1238,42.1216],childNum:5},geometry:{type:"Polygon",coordinates:["@@ȚĊÜ°„b„L‚lÞxUbUn±‚@ÈnVÆL@xnLšlUVƒbƒxkImJkn@V±LUxkV@bšbšKVKnzVl@L°@Va„xÞUlbôxVVœ@@V±bnŽ@llXL˜ŽöXĶŽnal@nkVJVI@aU@@aVK@ašUUUU@lmkwl@Ua@_@a@m@U@aUKWwkIlWUanIWK@UXKVIU@@a„VVIUa‚mVknW°™n@WI@KUƒmULWnkVkUWƒ™KkkmJkamIkmlw@ƒV_n@VWXaW™™@KVUkKUkValUnV„K@ÞƒVUÞa˜@a„@VbX@VWUU@Uƒ@UK@ala@IkKmUUa@U@ƒVƒkk™WVwU_@KÜUXbl@V¥XUVmƒƒƒXa‚kŃlUUkIm`UIUJW@UIKmkm@UUJƒImmU@ƒVUXU`mIUbUK@LƒJUU™l@Xƒ@UbƒJ™kU@ƒŽn„m@Uam@@ƒ™aUmLKƒwƒ™mWXUK@kUaÇa@JUIUa@aƒKVUƒUXmƒUy™_@lmbkLUKWLX`‚n@bVL@JXL„‚WX@Vnb@Vm@UbnVmL@V@x@LUbVV@V@LƒUVl@mb¯U@xU@UVVV@X@VVblJ@bn„VKUn„x@llnL±¤™b@k`VXÆK@„kV@¼kl@bWIUl@VmLnbm@@JXXmb"],encodeOffsets:[[125359,43139]]}},{type:"Feature",id:"2104",properties:{name:"抚顺市",cp:[124.585,41.8579],childNum:4},geometry:{type:"Polygon",coordinates:["@@„XVl°bœUlJ@UVUš@„bVxV@@bn@nJ°I@U„J‚I„VV@V@k²VVKlXXVšb‚lÈX„ŽWbXV@LVJUbWL@Vkn@lšš@nV`@X@lÈIWanaÞVVVlLnKVL@bUlUL@Vlbn@VL°WXU˜Lna@aV@nV@IVV@VšbUnšl@V‚XnKVa@U„UnyWkXaƒaVk@ašašbnm@_WKXmWanU@alaU—l@XJVLVxX@˜wnKnVlwƒƒ™@V_@a¯¥@UkKWUaUU‚anK@IƒaU@WUaVw@klUVyUUVUUÇ@Iôbša@mnUma@kXa@UWak@Wa—l@a›@WUƒLmU@U`mIUU™`mUk@@UUK±nkJƒbUam@kwm@@a@UU@Ua@@K@ƒVK@kmKU_UKƒUUaĉWmkkL@`™LƒnmlkLkbmK@k™@Ulmb@b™„@Ž„xUVƒIUlmVXXƒxm@™JUUk@WUk@ƒakx±@¯x¯Umb™KUUVmUU¯UmVVn™WkÆ„lWb„„„ŽUnWVU¦k@WaÛV@LV`UxšXllU„@„@VVbnVlL@J"],encodeOffsets:[[126754,42992]]}},{type:"Feature",id:"2114",properties:{name:"葫芦岛市",cp:[120.1575,40.578],childNum:4},geometry:{type:"Polygon",coordinates:["@@ll°X„ŽnV‚@XLVb@VVbnb@VšLVV@VVnXxlKnU‚l„_na@mlI„šmJnxlLša„xVbU„VV„UVU„KVlnnV@lmXLšÈWŽkxVV²bVLšm@Ula@UX˜@XW@UWaUUUUVan@V‚š@lUXxlIX„V@‚yXLšw‚ŽXXW°nblJnan@Vzš`l²nVVVl@„nUaVKšbVKnXVaUaVUšyšnXK@kVK‚@X@m@m‚LXa„LWƒU¯„w@™ƒa@UVw„¥°™ó¯¯y¯ƒUǯ»›w¯Iƒm—¯Ç™UUl™¯»ţKċÑţķm¯w@mU_ómk¼VnU`±IkbVlƒnnŽU¼±Lk`@X™Wl¦UbmVUxkXVlkbllU„Vb@bkVmx@XVV@Jb±aULkKWXkWmX¯aUJmIkVm@ƒxU@n„"],encodeOffsets:[[122097,41575]]}},{type:"Feature",id:"2109",properties:{name:"阜新市",cp:[122.0032,42.2699],childNum:4},geometry:{type:"Polygon",coordinates:["@@šXnb°lš„VlnXVJ„LlVnl@zÆxnK@b„blKVLn@@V„aVLVK@L@Vl@XVVInVVKVwlUXwlKšL„ššVVb@aV@X„lUXbVW@n„lWnXKV@@V@XUVVLUVV@@bVVV@@ln@VbVUXV‚I„xVanJ@UšIVWšL@UV@@¤V@nInw˜W„k„lnIVx‚lnzUVÇJ¦VVÜLĸUnW@aV_šWĊXXa‚Knkl@nm™L™a@alUVw²K@UlmnIlJ„w„aVU™kmK@wÅKmU@DzVmVaÝwkƒKƒaÛ¯șĉķ¥ğ¥ƒ@kUWkƏī݃ƒ@@akU„K@KWIUm¯nƒU¯JmwUVmIkJÇLm@™UImJUU@aW@U@@nUb™JƒaƒbXVWn@UVmX@V@b„š@l@Lƒ@™lUb@x™nÇaƒbk@@xVJU¦lbXšƒÒ@nUJ@Vmb"],encodeOffsets:[[123919,43262]]}},{type:"Feature",id:"2107",properties:{name:"锦州市",cp:[121.6626,41.4294],childNum:5},geometry:{type:"Polygon",coordinates:["@@nJ@nlmVnXKl@@°n@@¦‚V„bVbUlVL²l°@ƲÈV@LV‚knVb„VVnnWVU‚@XmWU„a„bšIVa@mV@X@@bVVnIVJ@š‚nÈKlInJVUnx°I„V°mVnXJ@LƒLlV@b„@ބƐĬXllV„@Ġ¦ĸ¦naWW@In@manK@UVkXJ@alk@»lU@ƒÅLUWl_@ša²£‚Kkm@kƒwVmULmƒ@akIUa@U@WUUVU™aÝ@ğ›wkƒƒmĉ£UWƒ@@bÇL@m—a@_mKƒlƒXUwKƒLţÓ@UWw@K@U„I@m™U@UV¥„@°UnJ°@@_™KUwƒW@UnaWUmmI@m™ķwUaÇLóVĵwݙUUW™¯šƒ¦Ux@V„b@šƒxV°X„ƒKWbK@n@nW‚@UL@lWL™m™zUVVbUbmWXXWJ—b˜n@Vkl@LlVUn@xnV@bln"],encodeOffsets:[[123694,42391]]}},{type:"Feature",id:"2103",properties:{name:"鞍山市",cp:[123.0798,40.6055],childNum:4},geometry:{type:"Polygon",coordinates:["@@l„œxĠŽÞ@šbV@@w°Vna‚@Uk„V@K@UUUVa@K@w@UnKmUVan@@Uma@UXWƒWK@IUK@amW_XKVLlKna@kmKVak@VU„@VmšU@anIÆan@‚a„šUVnb@blLV`ÞLlU„bna‚Kn@naVU@¥°IVK@anUUKVaƒUVak™@mJƒkXƒ™UVwkƒVUUa°U@Wƒ@WlkXWlIXUlJlaœx‚IVVXLšll@nLV@lLXl„KĊzš¥maUƒlkXaVK„X°y„Ila@aVkala@a@¥„IUy@WmXaƒ¯kU@U@mmUƒƒULkmm@ƒ¯VmnLVU@a™ƒ@U@±w@™VWIkymLUUkJWXƒJkUmxk@™xUI¯`mUULmƒ¯„m@kxVVbWV@„UVƒIUx@bkšVšVVšxUbVV@V@zšJVXU‚lnk@@lkLƒlƒLUU±Jkšm@UIUVƒLUVU@™K@UƒnnV@l@Ll„ƒaUJ@zn`@nWlƒIUVUUUV±Ln‚@nmL@VUVkLVlUxVLVlÅXma™@@akLmWUX@JUnVJVkXJ@X@`WX„VUVUIlb„W@bVUVL@`Un@¦U`@bUV@z@Jm@@XV`„LUL¯J@IVKmKÅI@J™nWVnLnšVxV¤™z@bmV@VUV@bUL"],encodeOffsets:[[125123,42447]]}},{type:"Feature",id:"2105",properties:{name:"本溪市",cp:[124.1455,41.1987],childNum:3},geometry:{type:"Polygon",coordinates:["@@lb@Vn„lnVVUb@šVJ@nnJ@bmXUx@xVbkbkŽWLUxnl@Ul@„xWx@nUV@¼Ull„knkK@bmbnl‚LVJX@VIVJn_lJVVšXUmnU°VVVUnVVšLna°V°w²@lw„bl@XVl@VVšIn@„wWWnUVk„JVUƒw@šƒ@anaVkš@@lnLlalKnk„mšK@_lKnlĊXVb„VVLV`nL@lUL@„@L@‚VbV@@V@bn@lxn@Vb„alI²mVL@Vl@nVš_VVnJV_‚@nV„K‚V@Xœ‚@b˜kXbl@XblylUUkš™@Xa@UVIlK@UUWVU„Llm@UUUnKWU@K@UXm„XVa@U°KVUUWUk@ašUVKkaWkƒKUknaWa@U—@m@mk@ƒaUJk@@_WKkLmx„l@nUJmIUWlIUaVWVXn@xWLk@@aƒJUI@Uƒ@UVVxm@UVk„mb¯VUU¯JWUƒ@Ån¯aUbÇ@ÇlLmWƒXkbƒƒk@UƒƒIÇVƒUXW™wÇnk@±aU@@bUVUKUXmVƒ@kaUm@k_±l™@XwVa@kVK@U„Wm—VaUmVUUakLUWWnÛKƒVW_—m±V™nƒU¯@Umƒa@Xk@ƒl¯V"],encodeOffsets:[[126552,41839]]}},{type:"Feature",id:"2108",properties:{name:"营口市",cp:[122.4316,40.4297],childNum:4},geometry:{type:"Polygon",coordinates:["@@ĊĖƐn¤„„°Ċ¯ŎWšô„@xXb‚wnKl@nX@VUVƒKmL@VU@Ux݄@Vlb„x„U@VUb@b‚kœ`‚IUlVUn„V@@UV@@JnXlK@bš@nbÆWUkUKVwUklKVU@UnK@mm²KVUVVVU„JXk@mm_@yVI„bkƒ@K@kmU„m@VšLV@VU„KVUVJn@l™²IVV„K„klK@kl@kmVUW™I@y@UUUVa™wUUU™l™@akmmVaUKmIUaƒJk@ƒwkaóIWWÛL@UlmUIU@WW@UnUUm@wmIVK@Kĉ¦™@bWKk@max@bWXkamKƒ@mVkKmxÛaWX@xUlÝnJ"],encodeOffsets:[[124786,41102]]}},{type:"Feature",id:"2110",properties:{name:"辽阳市",cp:[123.4094,41.1383],childNum:5},geometry:{type:"Polygon",coordinates:["@@š`Vz„‚Wn„VUV„L@bVbVJ@IÈbVb@lVLXW‚n„š„x‚LnKVŽšb@„n@Vbn@mƒ„V@šl„IVa„@@WškVV„I@KVLVanJV_VW„UV@nn„JVI‚Vn@na@alLlmkƒVk@»VU@mXwƒwk@@VmkVwXKllaUa@wVwnW@amI@mUI@™VaUUkmmƒ@UkaƒL@ƒUIĉyƒLWkkKU@mKk@™kWKUUJ›wkbkIWVkJWXkl@X„‚@X¯VVbUVl„UxšVW„„lnIš@l‚Ub„VUbVLmV@bUL¯J@¦UVmbm@LmbƒakVÝKU_kK@amaVUƒ™bm@ÅbmJ@b™VUnƒ@UVl@UbnL"],encodeOffsets:[[125562,42194]]}},{type:"Feature",id:"2111",properties:{name:"盘锦市",cp:[121.9482,41.0449],childNum:3},geometry:{type:"Polygon",coordinates:["@@Vbĸx‚š@nnJVnXŽmb@V„XVxšL@`¯@mI¯Vƒ@U¦@VšV@nƒJ@V@LXx@VŤÔ„K‚LVx„W„knL@`˜b@nÈK@a„@VXĊ¤„nVK@aVU@UnU@ašyU£Uwm™mKXUšm@IÆJnLUL@J°IVKƒKU_@Wn@@I@yVU@aV_@¥Vm@_UKUV@aƒXkaVJVUƒUXW@_@WWIUlUIVm@IVW@IU@@VU@mƒUVVkJ›_l@aVa@UƒVƒwka@UރVwV@@UnK„LVU@UmWk@mLxWa@wóƒUVUIÇÆĉ¦¯¦¯xʟJ"],encodeOffsets:[[124392,41822]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/nei_meng_gu_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"1507",properties:{name:"呼伦贝尔市",cp:[120.8057,50.2185],childNum:13},geometry:{type:"Polygon",coordinates:["@@„m@Łkƒ™Žƒklƒôƒ@£kJ°ý™ɅķÑó¤ğLĉÅlÇğŁW¯¯›™ƥóÿlwkţÈéÝƛó™°ÞÅxV¤ĉĖWƒ¯lȭţυ̃ɱÿķƅˋğɱřÝţϙȍƧĊţ@¯kWKUKm¹Å@ķJU@ƧÑƧ„ō¥˹Ɔ@L@„Þ‚VLnš@VōČWJX¦@JŻbU@ţÞmVU@ȁýóbkWWLƒƒÅ™¯UWġkmóƒ±UŹôV¼ƽ¼ƒł̥ĖƽǬʉxĉŽŻȗKΕ̛ʵƨʟÞ˹»Ƨţ»Ǖō˷Ȍ±ȚʊĠUɾɜɨmÜ֞߼˸ƅȂ¯ǖKˢğÈÒǔnƾŎՂ@šĊbôô̐¼ƒ@ĊôĊŽÞĀ™xšĖƧL±ŽœŽ‚Uš°U„°ĬƒČ°ÜƒêɴȂVł°@ƒ„nxŎèƒbȄÞȌ΀ǸlŽ²IlxĊl²ÒmšôĖ™Èl„ĵºm„ÈêVþ„xɛČʉÇĵVmš„ÒƒÈɆôƐŰǀĊ°ÆǬĮƾb„yĊ@ĠšƒXǀċm»ôw°Ûk¥Çm¯ç™kkÇǫţǕéX_ĶWǖīŎaÆĵĸĊ@ȚȘ‚™ĊLĢĉ„VÆĉʊÇĕóaU¥šĉ°mkÅ°ġUĠřk°mƒÑČÿ˜ÛƒWĸ£ʠšÆxÈÞŎÞ»ʈ²ĊÇČalÒ°Ť±ĸz„ŽĊKȲm¤Ŏ@Ò°¼nyȂUźīǖƳÈē°@šÝĶƒ@ƒÈkl¥Ççkxk™›JXÇƒUÅ@˜£k»„óƿīÛ@lÅJl¥óý@¯ƽġƍÅan™ċ™°é¯¹"],encodeOffsets:[[128194,51014]]}},{type:"Feature",id:"1529",properties:{name:"阿拉善盟",cp:[102.019,40.1001],childNum:3},geometry:{type:"Polygon",coordinates:["@@™ƏnǟƨʫšŹɆÿ°¯ÆV²ˢ™żÿ@ÝÆŁȰ¯ȀƳĉó™™@ğkyš¹@īš›ƒwl£Źƒƒ¯Ŧé@™ÇÇxŋĉƩUUŃōL™Ç™ĵóÝnƒóç@™™ó@ġƒƱ„¥ƒç™WUçÆōƒ@é—çťK™çȭVһƽ̻aW¥ȁ£ʵNJǓƲɳޗǔlżÞmĠóĬȂɲȮ@ÈĢŮźÔnĶŻǠšŎȭœгŃċóȭţΗÆƑÞƧÅΫóȘǫɱȁġlÛkÇ°ȁÈnšõl¯ô„ÞɛÝkĢóWĊ„zÇɼʝ@ÇÈķlUČÅÜķnέƒǓKȮŎŎb°ĢǀŌ@ȼôĬmĠğŰōĖƧbЇƧōx@ķó£Ål±ĀƧīXÝġƃêĉK°Ýʇƅ@ΌʉżÅÒϱʈ@˺ƾ֛।࡬ţશóЈèʞUš¤Ґ_޸Ƒʠɽ̦ÝɜL׈ɛϜóȂJϚÈ@ǟͪaÞ»Ȯź"],encodeOffsets:[[107764,42750]]}},{type:"Feature",id:"1525",properties:{name:"锡林郭勒盟",cp:[115.6421,44.176],childNum:12},geometry:{type:"Polygon",coordinates:["@@ʶĬĊIȘƨƨŽ@ĬÛĢșŤĉĬƒĀóšU‚ÈŚÜènŦƐȤȄłϰUƨťƾÑ܆ğɲƜǔÈèʈƲĊƞƒšɆ¯̼V˺Ò˺ȂŤVĢêU܃x„Āˌ˘ƨ„Æ°ѢmÞżU¼ÆlŎ@ĊçŎnÈÒͪŎźƒĸU°lżwUb°°°Vš£ÞlĠĉĊLޏɆnźÞ„n¦ĊaȂīġŃ¯Iĉůl»kƒ„™Çý„¥Ŏ¯ƒén£ġљÝȭxƒÇ™@Åçķ»óƱŎ¥™çWÿmlóa£Çb™yVÅČÇV»ÝU¯™KĉýǕċţnġ¯»ÇōUm»ğƒÑ™wƏbċÇŎċwˋÈÛÿʉÑ°Łkw@óÇ»ĉw™¥VÑŹU™mW»ğğljVÿŤÅźī@ř¯ğnõƐ@ÞÅnŁVljóJƒwĊÑkĕÝw¯nk¥ŏaó¦ĉƒV¦Å`ğуÑÝ@mwn¯m±@óƒÛKˍƏǓ±UšÝ™a¯lƒōšșk„èƒĬގn@ŤġŰk°ċx@œĉ`Ƨĕ°@ţÒĉwmĉ@ƒƒnƒƒa„™¥ķnƒÞĉVóÆókĉŽķ@ÝkƧƧÛaƒ°Ç@ÝÈU˜óbݼ@„ÛÒV°™@V¼ˋL™ÞɅŤŹǠVÞȗŤÇĖŚōbȁƜ"],encodeOffsets:[[113817,44421]]}},{type:"Feature",id:"1506",properties:{name:"鄂尔多斯市",cp:[108.9734,39.2487],childNum:8},geometry:{type:"Polygon",coordinates:["@@ĶL²ĬVłƑkkl@Ȏ™ŘWńÈĬȗ¯™ºlz@ĠššĊôŦô„ÒĠ°kÞܚ™n@¤„UĸèĸbŌÈXŽĸLlÒĢxɲÆ¤ÈÛƾJÈÝ°UšÅĶ»²VW¯ĸJôšbk‚V@ôlbnĊyÈzVôašb@ĸ‚ÞUl°yǬ²Ǭm°ššk„±lbn°@È»˜JX„VŎÑÆJ@k„LšƒÆl²™Ġ²ʊůĊġ‚řóƛÞÅ@m„ƒmLUÿóĉƧ@™»L@„›`ČĸmšȗÑţů±ĉğl¯Ā™wǎƒçƧŤÛI@±ÜĉǓçō°Uwô™ǫůķƳř±bÅ£™ÓÇwnÑó@ȁƽ@™ƒÇƧĢón»ŏĕóĊ¯b„Å™™VȯÅImƒōKU„™LǓ±Ýxċ—ŋ˜V±Āȗ°™„Źl±šÛ@WÒȁŚŹНŚÅèŌô„¼°ȰɞȂVĊ"],encodeOffsets:[[109542,39983]]}},{type:"Feature",id:"1504",properties:{name:"赤峰市",cp:[118.6743,43.2642],childNum:10},geometry:{type:"Polygon",coordinates:["@@ɲŁĢljĊwƾōÞĭ°_ŎŃźȹƒUČÿl»¯ôķVÿǬƽ™ɅġÅÑǫ»̐ʟȣU™¯wVWݍÈġW»Þ¹m݃ɛŎÿŎōͩůV¹›ō™éċ™óŹÅVVĢǩʈ@Ėċ@ķšÛšV°¯xÇÅţ¥™»°Ûô™ĉʟ„¥WýČ¥™w‚灻±mnÅķ¥ˋVƒbUÒġ»ÅxğLƧ™ƒbWĖÅxš¦U°ÝVóŰlô²@š¥ÜÞÛô„V@²±`š¦™„™¯Ý@„ŽÅ„VÒō¼ôš™¤V²ŹĬÇĊƑƒţxƒç¯Lk»ʟlƽýmłÝÆƏ@mö°Ġ@ŚŹĬţÆUĀĠNJĠŽX¼šnźVUҚ¦Ċxȼ@ôlx¯łʊÒÜĀˌÇČxƍČÈƐašx„ÒĠŽn¼ŎVȐ‚¼Ģ°ŤmǖČĊþšLV°ÞŽU¼ċÈUƚzÈa‚¤ôbkŽ‚nXĀšè"],encodeOffsets:[[122232,46328]]}},{type:"Feature",id:"1508",properties:{name:"巴彦淖尔市",cp:[107.5562,41.3196],childNum:7},geometry:{type:"Polygon",coordinates:["@@²@Ζǀݴʶհĸ„˜ƒ¦Ķ™̒Uˌ¼ӾÇƾ¼̨UÞĉ˜Ƨ—éÝ»ƒĕĉ—ƐȍœōǪakó‚ó¯a@™ôţ™aV¯Þ¯°@²él¥ĵğťwōxó¯k±š—Vó@™aóbUÇyĉzmŽkaóŽU@l™aó‚ķIX°±Uĵ¼™Æ¯VÇÞƽIÇÜÅ£ɱŽġwkÑķKWŋÇķaķçƒV@£šmۙlÝğ¯ƒÑťóǿƴȯ°Åł@ÞŻĀˡš±ŽÅU¯°ɅĀ™źƧʬmǠšƐ"],encodeOffsets:[[107764,42750]]}},{type:"Feature",id:"1505",properties:{name:"通辽市",cp:[121.4758,43.9673],childNum:8},geometry:{type:"Polygon",coordinates:["@@ôƲĸ¼Æèš@„ÈȮwƾ»ʠĢ¥VÆ@²¥@»Ŏњ¯ĊJŤ£k»ÆÇX¯̼ōšī°aX£ôƒƾȁź¥„ƒ™aôŤ™ĢL°ƒĸ@Ȯ¼ÈÒʈŚôVXůÆaĠƛÈKƒķšĉôÿ@ğÈĉ™»ÇVn™ĉV›wXĠÝ°šČÿĸwVƒ™¯¯ǵ±™ĉ‚ǫ™ÅÅm»²Ż±ƽIm¥ţÈķ@¯šƧJV»ÞUÝç¯UġºU£ţŽóaÅÅlƒƒ™Ƨī¯K¯Þ݃ğL̑ȍƽ@ōŎōĀƑɜnÞݺX¼ÇĢގUX°xVšʠȤ̏Ǭ¼ÆÒɆĢšŽǫƾUĀóĸ°‚k¼ċĀƑVŹȺōń¯`ÝĮƽŎĉxġNJɱłō¦"],encodeOffsets:[[122097,46379]]}},{type:"Feature",id:"1509",properties:{name:"乌兰察布市",cp:[112.5769,41.77],childNum:11},geometry:{type:"Polygon",coordinates:["@@ʠǠÞĸɲȺƒÒȂƛŎaƙÈĕȘţUÝźǟɆţšÝˌKU»š@U¯ÜÑ@ƒÞ»ôaV—ÞÇÈ@„¯ÜbƨƨÞlĸ@ĊôlôÅĊU„Ýĸmš¦ƒŽ„bm„„„Ċ@n‚ĊxŤÑ@¯‚ƨĖĊ_@›Čwl¯™ƒȭL›Ý„»ƽ¯ķů„Ǔ@ÇǓbċ™ÅÅÆwÿĠÇU£óaƒ¥¯aŎğĠţkw°»¯ůlÝĵkǻݰɱƧǫaóôɱ»Çk¯ŃóƒʇŐŻ›ĉNJŻĢ„Ž¯ÒÈUl°ƒx°n„Ò™Ĭón™Ċğ°ÇŚĉ¦ʵVƒ°°ĬÛżÇJȁńʇʹó˂ƽŎ›Æţ¦"],encodeOffsets:[[112984,43763]]}},{type:"Feature",id:"1522",properties:{name:"兴安盟",cp:[121.3879,46.1426],childNum:6},geometry:{type:"Polygon",coordinates:["@@ÆXnlŎ°@LVLĠþœxĊUȮĊnU„ĠV@żaW¯XIŎġƒ¥Ý@K@w@K@I˺ŻŎ¦ƨƒƨÒŎIÆ@X@VºnX°lŎ@ƾĉˤƒȘǷȘÑÝݚÞbVţĸÿŤxÈĖƐŽêÇKnĸ¥ô@›ķÞUnÒl@UŚaƒīˋƒ¯ÑƧx@±kXřƐƏÛéV™ˋ»lō¯ĉ„ÅÇÓǫޗĖġV@ğ»›°ĵ„ÇÞǓ¼¯m˜ÛÅŃĉĠÇƾb²çƒ™šéż¯VƒƒğÞml»ōÑV痻V¯™¯šĕÆU¯y°k¯¯V»ôDŽѰa@Źk™ġKţšóŽšbƒ„Ź¦ƽȂó„W¤¯b™Ĭ̻ŎW°ÅÈl¼ţ¤ĉI™°ōÒ@¼±¦Å@UŽġ¦ʟŽƽ¼šÞĢÒm¤„êō°ƒ¦Èþƒšl„k¼ĊŰ°JĢńȁĬ„°ƒżn‚ÇbV„ݼ@¼óĸţ¤@°Ånšl"],encodeOffsets:[[122412,48482]]}},{type:"Feature",id:"1502",properties:{name:"包头市",cp:[110.3467,41.4899],childNum:5},geometry:{type:"Polygon",coordinates:["@@źxżĀǔÆǬVȘĀŤ¥œÅƾōôˁʈͳȂŃÈIÜŻ¯ī„¯ōm™¯ɱĖ¯ƒķÒÝIÝ»ÅV™ƒlÅôфġ™ğVmÞnnƒWçkW܁XƝÆwU»Șĕš£ĉÑ𱱚Åk™„ƒK@lÅIō҃UW‚—IǼ¯@m‚kaƒ²™l¯™ǫnǫ±¯zkŽÝVķUô™˜l²ô°ŎwŦxĶĠk¦±ê¯@Ý°U°šbóŤ@š°bôlôǩb›ŎƏȎĊ˜„ĖÞ¼˜ê—ƨÝĊ"],encodeOffsets:[[112017,43465]]}},{type:"Feature",id:"1501", +properties:{name:"呼和浩特市",cp:[111.4124,40.4901],childNum:6},geometry:{type:"Polygon",coordinates:["@@ʶUĊ¥ÈřĠ¯šĉômšīƒÑ¯m„wk¯ÇV°ÑƒżġĊljǓɱţǓ›ƝóX¯ƒɛÒóa@nÝÆôƜŚĉĢʉŰĊҙ¤ȗĖV¼ÅxWƞۂlXXèm„ÝmUnšĠƒĢóÒkƚ„ÆUÞ¼ÞJĸÑ°„ɲĕš°Ŏn"],encodeOffsets:[[114098,42312]]}},{type:"Feature",id:"1503",properties:{name:"乌海市",cp:[106.886,39.4739],childNum:1},geometry:{type:"Polygon",coordinates:["@@Ș°ÇīXњŗ@ȍlkƒlUŁ±īĵKō¼VŽÇôXĸ¯Ž@šťê„°ź„k¤„x™œ@Ĭ"],encodeOffsets:[[109317,40799]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/ning_xia_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"6403",properties:{name:"吴忠市",cp:[106.853,37.3755],childNum:4},geometry:{type:"Polygon",coordinates:["@@nLV‚@šVLšaÞbn@@l˜š@bUVlUV„zVx™¤kÞVèšXnš‚@nm°a@UƒÑ„@VŽXnV@Va„UšŽVKUUU@@U‚@@KVa@U²@‚wXkWnk„±lLnU@UmmVKnIVWnI@UK›@UK@@UVKXkmWLWUXmlkVwUyVa@w„w@aVI„K@aVÈw„KlLVV@LnV„VVnU‚ܲ°WÈIUÆ@nÞ¼‚‚@¦™@UÞUVW@UxUxVn„b„K‚b¯ÞU`VbǬ™V@XXÆVVl°InmnUôƒ°¯‚anam£œWVX‚KXmškôaVU@ƒVak@@wmaƒn@K@UÛUWKXUƒÇƒ@UI™b@alW@akLUKV@@Ukw±Iš›nL@kmwkWmk@JUIƒůVmnnU@m@UƒK„VKlkUwkƒƒnVUKmbkI±š—KƒkmVkKƒb@U@aƒVkUmn™`kIlaUK@UUKmbUIݚUa@mUa@aƒ„m@UUULUK@bmKkbWI@WXwlkXƒWa@k@kKƒLVkkK@L@JUVmzUKlwUUnW˜£XVlKUwVU@aXI@aWaUw@W@_nam@¯‚UkWVkUWaU@nwmJkUVkWVUmUkJ@ImbUaƒ@@WÅ_mJknmak@@mƒXƒaUV@„ƒxUšƒ„@‚ƒ„@VUnkVƒ@Vn@`ULUbWLXVW@kbUJ@XW`@ƒnÅĖWJƒ@—m°@xƒxšbnUa‚w²lƒÞ°xŤIVVULۂWbšbkVVXÆ`UbVL„@kx°LlV@Vœ„WbƒJn@bl¤ULV„°@lmL@ƒƒ£U@@aUwmKULVxUVVx@„™@kU™@mK¯LÇa¯@"],encodeOffsets:[[108124,38605]]}},{type:"Feature",id:"6405",properties:{name:"中卫市",cp:[105.4028,36.9525],childNum:3},geometry:{type:"Polygon",coordinates:["@@°@Èb°KnLš@lVš@@ƒUwVUUwVKnLVx@bV@„¤@„nK@k‚¯UƒVKk£@a‚m„IXa›ƒ@UkU¯Klwƒ@UKVaÅ_UWlU™aXa܁VKUUţJ¯w„ݱkxVbmŽ™a„w@wn¯˜„@XIÆĕ„m‚@X_@WVIlaX@WUXKVaVK@_Um„@lUVm@U„ƒ@„ƒV™„w@ƒVUÛwm@@W@ImKUkU@Ua‚aXƒ@wWaUKkw@UVaUamLU™nk@»±`¯@k—W@Ua™ykbƒI„„@VWJkLWUkJƒwU@ƒn¤mL¯wm@Umƒ²XVWbnV@bmxƒVkxUblLUV@kVWKU¼ƒŽkUƒ@mn@JnV@bUnmJUn@„k‚@XlxšLVVnKlLVV@š@LkKULVbk`WL@lkXW@kVƒ@UÞUlÇX™lkaUbmV¯@@L@šƒV@bkb@xƒlW„—bƒbW@—±@UJ@IU@mVk„VxV@@l„Illœn@Vm@ƒVUbl„@JLmKÛXmVkU›KULU`@LĉwƒKUX„lVUl@Vb„JX¦̼bÞxŎxɜĖĠ„Ŏaô@"],encodeOffsets:[[108124,38605]]}},{type:"Feature",id:"6404",properties:{name:"固原市",cp:[106.1389,35.9363],childNum:6},geometry:{type:"MultiPolygon",coordinates:[["@@Vnn@°xnK‚£„mV@„xlIXVlKXI@Uƒƒ„JlašzVbX@l˜°@²_@¼mlVšnKVbUb@VlxVLXb@xW„bVbV@VlnL@J@Xn@Üx„b„W@nl@nblmnIÆ`@X„@Vbna@aVUUWVkƒ@kbWakbU@VwšW@_l@nmn@@alVlk@UkmVak@@a‚UXaƒL@¯@KVa@axWI@KnkVaVJn_lJ@„X@‚m@nVanUVb@mXLlJ„VWnLla„VVaVX@KXVVkVKlknKVa@aVU@KXb@klJUknUmƒ@K@_UW@alIUamaU¯kJma@IUK@U„@@UW@@aXLVƒVJVaXIƒKlaUkUV@ambUUJkIWJ@wUI™V@JU@UwV@@Um@™nU`@UkUmVUxWUUV@aÅb@aWXkKUUƒUUaWK@wnm@IVU@aXwm@UmVaUalk@anKUwlƒUwlkK@wmaƒUkmmIk@VmkUUbW@UVUnW@kV@xkVmbVnU‚™@UbUV@a›k@kkW@„kLW¤@„nV@VU@W_UV™UU`VLUV@IUVõVULU@UUUJ@wmkUJ@šWI@l@bkKkbVVƒbVbUL@UUJ@Vm@@L@xbVVVLVlVwX@Vb@bmUkbk@@JWIUVÅw@Km@UkWKXxWLÅ@UVUnWK@xkVW„@KULwWVXVWzXVVKVXkV›V@VUbV@U„VV@š@LXxVL@V„b‚Ž„LnKVLVxXVmb@l"],["@@@J@aƒU@LWK¯UUxVVn@Ġ„„LUW@UbUUUa@KUX"]],encodeOffsets:[[[108023,37052]],[[108541,36299]]]}},{type:"Feature",id:"6401",properties:{name:"银川市",cp:[106.3586,38.1775],childNum:4},geometry:{type:"Polygon",coordinates:["@@šUšwVK@UVWÞUšbšw„V@knV˜@@KU_VK@K„ƒn@W_XWlL@Vn@Ċw@Ulaœ@Wanamī@aƒ»ŋó@aÆÅɲÿUaV_°ÝaƒLƒaUmVwVwX@VUVݚ@@¥Ý»@mVÅÇJ¯XÛ±VUmƒUmU@KUUkKƒLÇxUŽ@bƒLUJ@bƒx@xUbVzUxklWnXV‚KnXWlUL@V@ŽVLœ@VL@ŽmJUXmJULnn@VmVkKƒ²mlXWlx±@@VUb@L@@VV@VVUL™ƒVUbU@WmUƒ@„Ò@V¯bmn@VŽƒ„@lVnUšnVWŽXVl@¦VVUn@x‚š@‚XL@¦‚lXxš„Vb"],encodeOffsets:[[108563,39803]]}},{type:"Feature",id:"6402",properties:{name:"石嘴山市",cp:[106.4795,39.0015],childNum:2},geometry:{type:"Polygon",coordinates:["@@U¯ķó±ÇÛ¯™ķmbXb›@kb@Vĉxm@@UkKWXX`m@ƒ„@LULV`@L—@mU@lƒU™x™aÝVUX@VUL™x™VkLWVšš@J„nVLXVlŽUV@zl‚VL@V@b„„n@lU²WVLlLVbUŽVxUx@xǀL˜xôҜk‚K²ŽVa‚U@wXa@W™ÈĉUa@‚bÈk„m@¯"],encodeOffsets:[[109542,39938]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/qing_hai_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"6328",properties:{name:"海西蒙古族藏族自治州",cp:[94.9768,37.1118],childNum:7},geometry:{type:"MultiPolygon",coordinates:[["@@„V£°š@laœXô±źwš™ô@„Ulƒża܍n™Kƒw@U„aƒ™ša²L‚mÈLƚÈxlaUa„wÞmÜbÞUšnJ°a„kôƒ‚ÑkwÝVğwÇ@ÝkkV¯¥@ò„»„nŤ¥XImw@mVwša@Åw™mLkaW—wƒ¥l»kçƒó„»@ƒWÑĉŽğ@ĉ„™‚Ń„UwóřVómĵ»™™Ý@VǕ¯kšÝĊÅk™°ÓUklkU±šI„ÇÞkƒ±@šƽJƒ™@UġIk@W¦™VÑșÓÅnťKULnŽ¯X›ƒ@¯mUÛ@WřmóKknōbƒxÝ@ƒŽU@kw@ÿÇLţšÝUkšmwƒŽk™lċVŚU¦™ŽƒLkUWlÅÑ@aƒ@ÅѱUóġŹ¼ƒÈĉmŻ@@wkw™Kl¯U™ġ@—„lÇU™Ó¯_ƒ‚Waĉ²Åló¼VbknƒKǎÅ@ƧĢō°Ý@ğ„W™ÅxUUm@™‚ÝXۂW„ULUè¯@mbUaƒLƒbUWġxIUJWz™a¯b™y™@ōÈóLU`ÇXUl™UĉV¯n›mÛbǕLklƒUĉVƒšóaġ„ƏbġKţnkbÝmmnÝWȭȃŽÝXţWókUÇl¯U¯‚ġUɅĀ@°¯„„š¯„VÆnmJ@ĊķnóJUbÝXUlVškL@lVxnnmb@¤Vzš`ÞÞŤ@„VnÆJV„°b„UôJkzlŽkl@²óš@ÆÇ°kĖƒšÇbÛU@lmb™XV˜kzƒV™ŽɅĀXˢlń„ĬŹ@›éÅ@ĉńÆ°ğbUšlŽɜ_°‚@xŦ˜škbVbƒKĢ„ŤVŎŽ°@żÈźlĊ„ôKôb@nôxŦ„Æ@ôŽŎL@þÆb@šnnšWˌbÈx‚InaŎxlU@Ѳ±ƒğVUĢƒƨbɲ@Þ¥ôUUķWVô¯ĊWʶnôaŤˁ@£nmnIôŽǪK°xUXô@Ŧa°m‚kXÆÞVŎkĊ°ÞLȄôyVašIlwX°UVwĢÑÜKôw@nV@œm°nmŽn„Ü‚ɞ£VbmŽXnƒ°ÜÒ@xx@V‚b²UlbkxVnšJUnVVĊ°KȚm°nxÇnn¤±¦@ŽUXVV@„lV„„bmVVȁŽVxšÒ™°šIšbźaȃšbVwš@šƒVL„™ƾÑ@ƒŦô¯ĊkôÑ"],["@@„@šƒ„@n„òVœa‚w²bVxšxÜaČVô_ĊJšIVmšL„a°@Ŏ¥XlK@ƒšk„l„KVbUb˜@nUĢn‚aÈ@lmǬ»Ġ¯œn‚mnƒƨVy™Ñǖ™Ġ»ɲInŽ‚@@ÅĢƳ@¯°™ôV„KÈbVIÇ¥¯@Ýó„™@ÑnīWKšƒk™‚k@¥š™¯™Åa™Xƒ±VÅw@±Ġ¯@»™š™n™Wmw@ƒ™@¯ƒVƒUUWçƒKĉ„a±VkkƒV¯w™x@šUJ‚x@bknÇb™mÅ@Uw±U¯¦UŽ™Kmš¯I¯Žť¼ğĊ™@ǃŹÈ¯@Ý»ÇnˡJƒbÛèÇnƒ„ÅK¯„ġĠŹW¼Ålm„@¤n²ƒŽÝb@b„š¯lƒ¯@ƒšÅ¤W„™¼nV@x„„°@Vx„@lbUblbX¼W‚œšÇ²lšUŽ@¼ŽV¦@bÇlVxUbVxÞbVšœbm¦ƒVV„"]],encodeOffsets:[[[100452,39719]],[[91980,35742]]]}},{type:"Feature",id:"6327",properties:{name:"玉树藏族自治州",cp:[93.5925,33.9368],childNum:6},geometry:{type:"Polygon",coordinates:["@@ɆÿĢV°°VÈklVôŤXÞW„ȮÇÞXnmÞnlaŤmĢLƐaĢƒôb„™ĊU„VlkǖKÜaœn°mĊUšVVkÈWV_ôKŎǚ@šz°ašbXyVI‚JĢwVX„a„KVbna°@VçVKXƒÜÞWšn@VVÆwXšĠƒÞ@Ŏ¯ƨġÆ@ȍ„LlmUaô»ÆkĊ±Xb„°`šÔV‚kȘƒĢ@Všk°šLlx@xż@Ċn„Çź»ôĢ²VÆ҄@@bÆÒXklV„KšV¥Æ™ČUšk‚l„nxl™çƒ¥ċç@±m¥ƒwÅJƒ@™™™Vƒ„mÈIléÈa°U¥™™@kÞV‚K²ÑWƒ°w²Ñ‚K²ñšyƐ„ÝšVmw„»kkWĉ—JWUƒVÅwƒL™mÅ@@ƒmw„kn¥Vу»°™°@@»„¯„Lla„JônV‚UůƒU@W¯Umѯ¯k@WykU@¯„wV¥ƒkVwţƒk»šwWǜĉĶçšK„ƒÞ™ÇaĉbƒI™lUƒ@kwƒWƒXUƒ°w™±@UšKn£Wĉ—KWxƒkĕVƒšamwXw™@™„Wmnk@aƒVkƒ™bĉLƒl™Imm„wUÇ‚Wx™nÝJn@¥Æ™kwƒaXƒÜĉ™¯ÅV¯¤mkƒx¯kķܙ²VWôŹVUƒƒ@V£™¥@ƒ°wn@™m@¯@UbUôķŽmn@ÆÛ@ÇýVaUÇĊVƒ@Çlğ—¯xÝŤ™lVÈÈVƒx„ƒ¤Vx™„kK@™@ƒx@„kVƒĖġ¥kIWbXŽŎx@nƒxÅUW`ƒ_—@±ŽUa™LUxƒK¯„WbkVlb—bmŽƒLÛÆWIUwƒWkwÝV@kI›ŽéUb›UUk™V¯Km¯k@Umݐ¯m¯›m—L›Þĉ‚ÛUm™ġ£UxkKm°™Lw›šk@kšƒVm„ƒKVUk›@¯a¯Ģ™móKUU™x™ImlÅn™™ÇbXèVVU„°„@ŽšŽ@„‚xXnmš™ššŽ@¼ğ°@²ÆxU‚„²šWÆb°š™š@¦llš™„XLmĬ@҃šÞô°@ȦUJÇaƒLóU¯š@°ġƴ@Ɓ@mɱJğ¼ǕššÒUzƧ‚m„n›mğ°ǫ¼knÇ@bġmmV—@VaUaƒLƒk™l@„kLW‚ō¦¯@ƒb™KUn™JĉIó`ċUÛb™wUw±ax›bñUmƒƒ@™„ƒ@—bƒaƒbǏÅXm˜„ƒÝ„ÅôVbގ™bl„UšÞVޚ„U‚°„VUxƒ@U„V„@l`™¼nL@Ċ„LW„„¤kXķWġXUVVVķ„UbVb@°kVVxÈa‚@ȦĊbšaźJ„U@Ț„„˜Vœƒlš@XkôaWƒĢ™Þ@laĸUÆb²mÞLĠ™ÞÑôbšÒĊa„JVbm¦"],encodeOffsets:[[93285,37030]]}},{type:"Feature",id:"6326",properties:{name:"果洛藏族自治州",cp:[99.3823,34.0466],childNum:6},geometry:{type:"Polygon",coordinates:["@@ÞVŤ™ÈK@ĀlxV@„Þ@„wŎalmôLšnXÆÜ@nV‚°@œ„°WmVKŦLÆmȚԂҚUX¥l@ĢJVš@„ŽƾI@w™W°™™Ån¥›kÅÝVwôƒÈç„@lÑĊĕša„JnaÆLVw°kny°UnkÆVȍĊll¦„Vƾ@@™nUźƒÈǂIn°X„wÞKô¦VWV£„@£°ókċ±I™™am¯Va™»ČĉV¥°™@m„k„¥l@„Ċm@ašU™mwXƒ@wÆxšmĢ_„`VnÆbšKVw„@@ƒnUVğVmVVöIlŽl@@çÛmƒ£UDŽw°@VUƒ¯»m¯ƒJōĖÅLƒa@»ĉĢ±`U_k`ÇçšóƒkX™lK@ƒakÝރš£WċkÝ™kxƒJݯÅw™xķxmIÅx„@k±J@ýŋš›¤UœkŽmV™°ÅÝxkwmġƒnÝVU„š¦ƒŤlmšóXk¤™UKƒç™@mVkK@klīƒ£mš¯VUbƒW¯¼ċb¯ĵam¼mVX„m@k¤ÇX‚ÇbƒUƒ„¯J¯„¯È@˜™bVXVҙ¤V¼kxݚV„@l‚V—„WxÛ¦Wš¯šmKnlŽkŽ‚šU‚@nƑUĉ„Ý@ǺۄċUĉ¥™UƒÞŏ™z±òL±Ò¯xX„±ÒLÝU@lššV¦¯‚ÇbkêÇJƒnU„šš@š„‚ÆI„xn¦‚‚@²Č脦‚è"],encodeOffsets:[[99709,36130]]}},{type:"Feature",id:"6325",properties:{name:"海南藏族自治州",cp:[100.3711,35.9418],childNum:5},geometry:{type:"Polygon",coordinates:["@@VxƒŽńƒš@ĊĠŽĊXÒ°UƾĕÞm°£nb@‚@LUUW„Ûº@nlÆǬšĠ£ÞV°UXb‚VȂǵ„éƒ@kWanm°@™x„z„K°¯ĠVšƒVƒkw™Lnm°kÞxÆa„¥@‚wnĉƏ@™œ_l›š_VwšmĸèŤÅČU@™˜Wn@ÑmKU™nğƒK@ƒ°¯UÿV£nmšLl™„UƒUÛé±óókkmƒnƒakV@Ç°óÝXƒWəÞťIţxmm™VÛUVȂÓnWyȁĉkƒVš°WnkĊa„¥‚_œK°ÿWna@ƒmU¯wƒlÝIU¤UXó¥ÝLƒx¯WmJÇÈŹ„mV@šƽ@ƒUk¥ĉkċŽÅUml¯Vmz¯lUxÅKmbƒI™bĉĖk҃@Çèó„UxÆޜlm¦šÆ¯ššX@x™Ž@Ž„²ÝlƒÈ™JV²klVl¯ÔlšĉƙްlUǖÞ@ššĶ¼nŽUôôŚ"],encodeOffsets:[[101712,37632]]}},{type:"Feature",id:"6322",properties:{name:"海北藏族自治州",cp:[100.3711,37.9138],childNum:4},geometry:{type:"Polygon",coordinates:["@@ōmġxƽUm±Lǿþġԙ@kxmWƒb¯I¯‚mIUx@bƒbŹVǎƒkĵbƒlĉI¯¥ƒUšm@ƒÆ¯È@šašóšUlƒČ»@w›œ»›wXaƒƒó°ţç݄kUƒaV¥ÅbÝw¯lmnšKlxU„™„ğU¯°ƒLƒyšw¯@mnXb‚l„@ƒêȁǶUWa¯VÝUğ¤ǫ™kÅ@mܹXƒVV@K@ma¯¤ÝnƽĖ¯V@„ƒ¼„ôlèk¼„¦˜xXŽlbnKšÆx@Ž™bUx@nnxWJţ¦ƒmƒ¼ñ@Ž°¦lUÞlÈ@ĠxÞUlxÒó„ƒl¯bmI™ŽÝVÛaÝnƒxVbkbÇwřÇKn±K™b„šƒb@V„xšLmŽÛŽŻbk„ƒVó@™šŹxó²›Wkb™@¯U¤ƒźĊ@lUX„°lÆôU„ƒlLX‚aœV°wšxUb°xÜôÈKVkÈmlwškÈKšwšK™™VUŤĉŎ»„»„Il¥na°LV»²¯Üy@wĢƒ°ĸwlwĢw°±„_lVkš@°ƒbƒÆ¯zƒ‚„š„@l_„@Ģ±lŚVlUaރ„LVƒnKlnȏ°IllČa˜wÞÑ°x„UU™@wƒVkmĠLô»„KÞýôaÞ¥ôĀÞmƁ„™‚mUƒŎV¥Èl°²°a²¥V„@@w„amm@Ñn@Æ£żƒVƒĠ£@W„¯Þƒšl@š»@Uk@"],encodeOffsets:[[105087,37992]]}},{type:"Feature",id:"6323",properties:{name:"黄南藏族自治州",cp:[101.5686,35.1178],childNum:4},geometry:{type:"Polygon",coordinates:["@@ôl²ôÜê„VƒVkš™KmnU¤VĀ¯°@„„LmĠVšnLÈL@alb@al@n°Vš_XmWUÈamaVIn@n‚aV£œóVWƒ™U£°ašxÈ¥@™‚aĊwȹ@óša™ƒğbm@k„w@mƒaÆw@ƒ„In¯mmƒ@UkkWƒÑÅ@@kċÅçVkÝJÅkVykŹl¥@¯š™ĢU܃X¥òý—mmX™ÝÅlmU@£™Wly™XW»Åbƒl@aI›»k@klm@UxUUƒVƒ¼¯Xƒl™aUnķ‚ƒI@x™@¯„ƒK™„ĉUU`óšlČ¯ô@¤ƒÞJ„k°xVŽ„n@ŽmbXŽ¯Ā›L`ƒ¦ĉbml¯X™ŽUŽl„ȂĊXzm‚ȁÔU‚ÜVšUnnŤwŦJɚ݄XÞW¯ô@ÈlU„b„mln"],encodeOffsets:[[103984,36344]]}},{type:"Feature",id:"6321",properties:{name:"海东地区",cp:[102.3706,36.2988],childNum:6},geometry:{type:"Polygon",coordinates:["@@@҄bš¤ÆI°ôU¼š°UŽnnWx™š@b¯L@lUUWbXxWl„ƨnxVUllš„XVŽUŽnL@lȀý²KVnƾ‚ĢwV»ƒ@mÞ£nÆƒÞÑmL™ƒKUaVżĕƒWVk²ƒƒÆÝ@ƒXw°@„ô™@a°wóUUmIk™™aVmÞwmknyƒ¹VÿƧnŏm£X»˜™naV±„Ýw@ašb@aƒm¯„ĉVó¦kÝWKUU@WanU™b@ôǺĉxb@šÇ¦™w¯bV¤„šUX›ôU¤bmm@UJnbÇbXVWn™`¯Umk@@bka@bÇK"],encodeOffsets:[[104108,37030]]}},{type:"Feature",id:"6301",properties:{name:"西宁市",cp:[101.4038,36.8207],childNum:4},geometry:{type:"Polygon",coordinates:["@@@kmKVUƒWk™VkUmwƒƧXkWwXaVV@k°K@aš™XwmmV™¯V»¯óÅJ™£ƒamŽ—X@šċVţÆķç™nUx™`kœ›`@šÅmĊx@Žƒ¦U¦„blVރŤèô¯„„Wbœx›¼œŽ@xċ¼k„™V™ô™bÇ@Å°@„™n„V°¦ĊJ„kĶa„lȍźU„a@aVwnJ°°J„anXlwš@ĢÓ"],encodeOffsets:[[104356,38042]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/shang_hai_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"310230",properties:{name:"崇明县",cp:[121.5637,31.5383],childNum:1},geometry:{type:"Polygon",coordinates:["@@uŏu»GPIV±ÐɃŜ{\\qJmC[W\\t„¾ÕjÕp‡nα|ěÔe`²„ †nZzZ~V|B^IpUbU†{bs\\a\\OvQ’Kªs†Mň£RAhQĤ‹lA`GĂA@ĥWĝO“"],encodeOffsets:[[124908,32105]]}},{type:"Feature",id:"310119",properties:{name:"南汇区",cp:[121.8755,30.954],childNum:1},geometry:{type:"Polygon",coordinates:["@@`y”ĉNǕDwǏ»ƒÖLxCdJ`HB@LBTD@CPFXANC@@PGBKNECCBB@EBFHEDDDSNKAUNBDMNqf[HcDCCcF…@EFGLEBa@ACoCCDDD@LGHD@DJFBBJED@BGAEGGFKIGDBDLBAD@FHBEF@RFDMLE@SGANFFJBANPH@@E@FJjRIACDMDOEKLFD@DbDAJI@AP@BGHFBCBGDCC@DCA@CECGH@FKCEHFJGBFDIHACEDNJDCVFBDCRKRLDLITB@CjNJI^DBCfNVDHDFKHAFGDIICDWBIF@@CFAjFJNJBBHD@CJ@AEFJ@@DH@BFBCPDBMFEQGDIFCNDHIP@HDABFACBJFHEBSZC@DP@@JDBƤ~"],encodeOffsets:[[124854,31907]]}},{type:"Feature",id:"310120",properties:{name:"奉贤区",cp:[121.5747,30.8475],childNum:1},geometry:{type:"Polygon",coordinates:["@@~T~JjZdDbLXDLCB_J@@FHFZJJIAGH@HGR@BENBLID@@LFCDF\\FpDBDb@FAHKFE†@dEDDdC\\GreNMACVMLBTMCCFCEGFAA@DAFDLMHA@OD@BMEWDOC@AS@KGAI_DcKw„ÕísƝ‘åĆctKbMBQ@EGEBEJ@@MBKL@BJB@FIBGKE@ABG@@FMFCPL@AjCD@ZOFCJIDICIlKJHNGJALH@@FPDCTJDGDBNCn"],encodeOffsets:[[124274,31722]]}},{type:"Feature",id:"310115",properties:{name:"浦东新区",cp:[121.6928,31.2561],childNum:1},geometry:{type:"Polygon",coordinates:["@@EN@JJLNHjLJNR^GRYVBNZJRBV@PDvbLNDN@LGNER@nCNQNuT_TIVFV\\Z\\XnDrI|[Ʉś²ÏJUHOƣ}CA@IO@@CYDATGFIEDAEBBAGCO@GJMCEDCJRHEFANOCADAEG@@CI@FE@BDIC@AGIAIMiEEB@DE@AJCXJDCJEHGBELGCUCeMAD]CIJiM@DSAKJKCLQDQACUECDMIFCBDJGECHAEIWCK@GLMCCGEACNKCEJG@MMBMC@@CIJUINT@JAJSTEPZZCP"],encodeOffsets:[[124383,31915]]}},{type:"Feature",id:"310116",properties:{name:"金山区",cp:[121.2657,30.8112],childNum:1},geometry:{type:"Polygon",coordinates:["@@L@BIHFN@@EE@@EFBDGDAADVDD@@EF@CA@IIsRE@GDAF@BF@CV@|FBCHBLCNHAFCADBMDCFZXHILBVEEQA@MWFARJJ@DCX@@TEFBLHAAERE@AJABRPBNK\\BrJ\\VHGND@CNADKDADQjGAGNC@GJ@FCFFHC@JF@@dLBDSFADHVG\\DTEPDDHJALIJkJDJCDIPE@YDCBiK@DONE@EH@BAF@HLJA@EIA@ALKNA@@FIFAFHR@NALadsæąyQY@ƒA±DʼnXUVI^BF@FFF@HBJEDFFGFEBSRkVEXGHFBMFIVW@GAEEFOIAIPKABGWEKFSCQLQBSEIBC\\FdBLRR@JGACFDDEF@AWB@LJJYNABBA@CUEGPaO_AIE@MYMFIGAEFECHSAAKAO\\[JEDB@E@MMA@@AGBKMGDFFCDDFEDFJF@NPBAFLHFH@EDDHBADDC@DDCDHHCDDFDABDAD@FEFOBCJ[D@HEDDNJBDDHABJIBBvGLBJAH"],encodeOffsets:[[123901,31695]]}},{type:"Feature",id:"310118",properties:{name:"青浦区",cp:[121.1751,31.1909],childNum:1},geometry:{type:"Polygon",coordinates:["@@RUNKdOFDJCbRFMLAHPLDN@JGL@@APBWYCKN@TU@SHGCEJIDIJKVIZVNM`iNY@CIE@CA@KBOEGEUFCCSADEIEFCDDDIDDHC@CKIeDCG@IG@DHWFEEGCH@@GO@@O]CNpeEQDBFME[JC]DGF@CKOA@QSB@GB@@GW@@ED@AQIJIAAFE@@DO@CFI@KNG@CDACAFEGKGBEGBDCCAIFCCLIECFI@MBCLDHGNAHSF@DMB@EEKBA@@C]DEICFG@ADBHGFKCDAKKHKD@@FHGAANGEEFCHKCECBCKG@ADKCNE\\[A[I@@mGBDQQEO@BCE@AI[AML@JGACLOAFKEMM@EQKC@CUCBCCBCHEA@FF@@FM@GEAJK@GNF@EXPH@FD@M^@HIADJCFDBER@DK@@DE@CAKFOCCBDHIBCNSB@GFC@GQEEOWFICGDUAEJIDBTAHJHEB@DIF@NE@H|HBDBEH@DKBAHEF@HEEUB@FGFGCCCE@AHOB@NH@PRLVNNFBX@RC€PbAvMtBfH@DJF@ELBFA@EH@HNED@FFB@HLC@CJ@@DJ@PIRf@HE@CFF@GPHD@DKE@FFBEFFD@DEFCA@DD@IjCRFBAHFDKD@HF@@PM@H@BlbDJDBFEF@DLXB@HCD@@IFCBIFEJD@FDC@FBALLF@PAACJERACAJCBD@EL@JD"],encodeOffsets:[[124061,32028]]}},{type:"Feature",id:"310117",properties:{name:"松江区",cp:[121.1984,31.0268],childNum:1},geometry:{type:"Polygon",coordinates:["@@@DLDFRN@FNELPBDKHB@INK\\BBJF@ADP@RFCRHA@nJ@B\\[\\MFLDBCH@DLDADFGLEDFFMHBBGH@EC@GLLLCBLDHEAGBCH@DEFJ^C@DB@LAFFA@CNE@GTMBGHKCAD@NEJFDKJDDJEDBCDHAAFLHFHBEBDDCH@LMJ@DEP@@CF@BEJBJIBRC@@FX@@HA@@HTA@RPBDLE@CHD^\\INFAERCfFMo^D@PP@@HG@HDFFXECGH@@JDHfCLJ@DGDCCCJCCEDJFCFTBDDVEHFPFLAB@NBFCFKFC@CHIACNOHWHCAAFIDD@CDAGEI@ACFMF@R@R_@GQED@EGFEQEDE_IAHKAEXCQUOQCUDEN@ZI\\DDmAMHCICDSOC@EG@BKHIGMIBCGOCSF[CUHCGEBCTKA@cE@@IGDEEEDI@@HMDBHiHCRCBCLMB@DMCGH[UqI[AMLOAAQIB@BQFBFGBAKFE@SW@CDI@QIEBNXB@FRUFKAGJYWDENCCADBBEMGKDGAAD{EU@@DAEE@CB@HQFJt@JDBE@@FC@"],encodeOffsets:[[123933,31687]]}},{type:"Feature",id:"310114",properties:{name:"嘉定区",cp:[121.2437,31.3625],childNum:1},geometry:{type:"Polygon",coordinates:["@@F@LI@IDKJADKIEJICADGACFECCJ@HKCAFOHAJI@aCBEE@ICAEB[GFGCKL@FGEIFADMLCAEJM@ELQECEIG@BE^QKKLQCA@EHBIGQ[GEHOMGGDHKH@JOECFCjCBEFDNCACMBCILGTABDLEEOEIG@GFIMM@CGKFBFCDE@@GEAGEEACIcGaHMFITIHDN[AKF@FS@OA@BK@IHM@KCGOKBENaQIDECcPMLQVFHFB@BFBKLGD@FAJOVGIACQ@A`LPCB@JEF@RU@ANS@@RCL\\HIFpRBFRBBDKLLDADJDGBFDABHBEDNF@DGBBBADKDAHC@\\JJFBDEH[DEFDH\\LX@XLBLbT@DNJLDCEL@VJABJNDHB@HBHYFBAA@GNFB@@AFB@AFABFLFBHFCL@HJBAFBLC@DN@HN"],encodeOffsets:[[124213,32254]]}},{type:"Feature",id:"310113",properties:{name:"宝山区",cp:[121.4346,31.4051],childNum:1},geometry:{type:"Polygon",coordinates:["@@ˆmÖoÖiƒ½[s[YEUJU`SCIEBCCWJY_LIICDWU@@FaBCJIB[ICH[@@CDKEE@MK@@IMCAEBCH@AMFI@SMGEFGB@FK@BHCAIFJNQD@FEBDFMBKGACG@ECWH@@CDDTOEEBGEK@GC@EE@GPHFR\\JHGA@FDBKRLL]RAFH@FJFDKR@FINBFKDCNEBFJEHK@DLEH\\HFADB@JFFDA@bIJGBEPDBGLI@DDEFBDCHDBIJJFCLIBCL@JKJE@ADHDBHJ@HIBBDFHBBAEIJ@BJFAVL¢ˆ"],encodeOffsets:[[124300,32302]]}},{type:"Feature",id:"310112",properties:{name:"闵行区",cp:[121.4992,31.0838],childNum:1},geometry:{type:"Polygon",coordinates:["@@T@@ELE\\BCMJGJSNEbGdHDJFBJAFIEIFCEWG@@gMENSFCVJFAxR~B@IH@AIiI@GE@FGEAFQPDRiV[\\DFSGMHAXHDOMCJCDETBBNVJJI@DD@ANNNH@FILDDMFBDHNDHKL@XDFGLD@EHGFD@DDB@CDDHCDAEAHG@ABOJ@BIaC@CECLKPFNCDCJBiQEIF@@@OGBMIAEEBMTHF@NKEC@QFEGA@EBCKAACHCLJHEFHHB@AFCAIEACIC@HG@KCCDC[ECEED@KC@KJMAAFQ@GHG@BHIJYIGE@EI@A`KDWCaKcCiY}I}S[CYJM@CFDVPRRVWDFžLBBG`JCFRFEFFHC@RF@HQ`Q@E@ENBDJ@HFCB@DCCEJBBGDGXMPBDGJ@DEDELEDMA@DJF@DMZ_jMNYUUJILCJIJDFGH@TSVM@DLXZ"],encodeOffsets:[[124165,32010]]}},{type:"Feature",id:"310110",properties:{name:"杨浦区",cp:[121.528,31.2966],childNum:1},geometry:{type:"Polygon",coordinates:["@@V@CXJDKJZ`XIDDFADJvSRMDM@mFQHM@KCMKMuaOCU@BDAJSX@HKJGD@PNJCJWAGT@R"],encodeOffsets:[[124402,32064]]}},{type:"Feature",id:"310107",properties:{name:"普陀区",cp:[121.3879,31.2602],childNum:1},geometry:{type:"Polygon",coordinates:["@@F@@FHDL@HFFAPFCSDC@@XGFDH@BDLHNACEFA@ERCIMJEDBAGL@@EHAFENHHJ\\ONQBQCIBC[MKACKI@GGGH@I_G@CW@[DMHCDIBMTDHN@JNHEH@FJFPKFACSBKHDJNABDMDECAFiDEDFDIPG@GLHCNH"],encodeOffsets:[[124248,32045]]}},{type:"Feature",id:"310104",properties:{name:"徐汇区",cp:[121.4333,31.1607],childNum:1},geometry:{type:"Polygon",coordinates:["@@RADL\\NCPHFfLJaJ@FWLGMGIK@IFMDOYYFOTSBI@IMSAMSACFIDNDCPWGGBHNET[CU\\QjOCERFBEHF@@HjJBJG@@J"],encodeOffsets:[[124327,31941]]}},{type:"Feature",id:"310105",properties:{name:"长宁区",cp:[121.3852,31.2115],childNum:1},geometry:{type:"Polygon",coordinates:["@@HFFB@HF@DCAELENSJADCNG\\CX@@D`H@JHGHHJ@BINBFUGEDO[MCKQB}AwQEBUIEDMTNF@hH@FXEDFJEJIB"],encodeOffsets:[[124250,31987]]}},{type:"Feature",id:"310108",properties:{name:"闸北区",cp:[121.4511,31.2794],childNum:1},geometry:{type:"Polygon",coordinates:["@@CSG@BQGODUPWTOBQAAFMECKBGEMFKEOHADDJARMR[PGI@TEJBNG@ADBFND@JL@@NFFCL@D\\@DG\\JJADI"],encodeOffsets:[[124385,32068]]}},{type:"Feature",id:"310109",properties:{name:"虹口区",cp:[121.4882,31.2788],childNum:1},geometry:{type:"Polygon",coordinates:["@@bA@E@QHSXBDIMI@OHCLI@GTWBIACQAYIOFGCENBBARSPOXCVHPARH@DT"],encodeOffsets:[[124385,32068]]}},{type:"Feature",id:"310101",properties:{name:"黄浦区",cp:[121.4868,31.219],childNum:1},geometry:{type:"Polygon",coordinates:["@@NEHFLAFDHDPEAMZUHQQ]IMKJG@EPERABHBGRUCCNGV"],encodeOffsets:[[124379,31992]]}},{type:"Feature",id:"310103",properties:{name:"卢湾区",cp:[121.4758,31.2074],childNum:1},geometry:{type:"Polygon",coordinates:["@@VDHQGABAFQFOH@LIiKKHEXI@IbAFZB"],encodeOffsets:[[124385,31974]]}},{type:"Feature",id:"310106",properties:{name:"静安区",cp:[121.4484,31.2286],childNum:1},geometry:{type:"Polygon",coordinates:["@@DLLB\\NPGLFHUDMYABEeKEVMAAJ"],encodeOffsets:[[124343,31979]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/shan_dong_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"3706",properties:{name:"烟台市",cp:[120.7397,37.5128],childNum:9},geometry:{type:"Polygon",coordinates:["@@ŤLšLllVń²è°xżĢĠÆl҄šŤbœ„V¤ĊXnŽlĢVĊ„Òš„È°ĊŰÞè˜L„±@џn»VUźċ²»ÆkôVɆkĊŃ²kŤVVwUUVmUaƒ@KkU@ƒmUmmk@UwUkmW@UVIXa@ƒmw@a™KULƒaƒx@Uk@UbWU@yULmK¯@kXƒVUwm@@JUUknWKUVƒLUbU@™wWykIƒa@w@mUI@ašUVynIWa„k„@@W„bl@@knmƒK@wnIl™°Kna@V¥ğ@ġUķ»™¥@UōJƒX¯¤k@™wmI¯‚k@mwƒak@@šlX@bUJ@VƒbknWxkLkxlŽšLVlkLmŽšb@bU@ƒbU@VbU`Vb@n„L@Žmb—U@˜VnUVmnU@mm™@kIUWVIUK›VkkUJUnmL@VmLUaVWaXamU@™™U@KUUmVƒU—JƒU™VÇwğn™mƒ@mXĉV@l¯xnô"],encodeOffsets:[[122446,38042]]}},{type:"Feature",id:"3713",properties:{name:"临沂市",cp:[118.3118,35.2936],childNum:10},geometry:{type:"Polygon",coordinates:["@@˜bXlƒl@zlV@lXXmŽkbVVlš„U@Vn@@Vmb@XšKšVX„WJ@XXl@„‚ŽÈbVLšUl`„@XXV@VVUxVbUxVbš¦„@‚WnXVJ@bnVUzl@„°Æx„U„KlU@mUUnUlUVWVUnVV@XX°V@Všll@Vk„aXVl@Ux@bmbXLlKlb@b@bUJn@@„„b@n°x°K@an@@UlLVKVbXb@bVVnK°LVa@UVa@™Xw‚KVxnLšU°@naV@UWUkWƒULmV—wÝKUUla@aó_@mƒK@aUU@ƒWUkwVm@aVI°W„@@IUw@a±¯@¥kUVUm@a‚wkw™@ƒK@kVKk@maXalI@alL„WXblaVLVU„V@LnKš@„l@w˜aXašLlnUl„LšmV@n°J@_VmnIVym£UKmI@WnIVm@anUVmÇ_kġIÅWUXÇm@U@ݯÅ@ƒ™@naWƒ™IVW@IkK@klKn@naWIƒmk@ƒaƒbkKkLWn™WkLWmk_ƒ@UaVƒUKmLUw@mn£WwUmU™ƒaóV@UkUm@UKULUwmJUX@WW@XҙzVblJXŽWXk@UVWK—X‚¤UL@xU@ƒ@ƒVUaU@@XmVkLmWkXUyÝLmKXnVŽ@n@l™x@bWLnVVn™`knULmxUl„„WLXŽVb@VƒK@z¯x¯¼Wx™KUn@bk@ƒlƒVVVz"],encodeOffsets:[[120241,36119]]}},{type:"Feature",id:"3707",properties:{name:"潍坊市",cp:[119.0918,36.524],childNum:9},geometry:{type:"Polygon",coordinates:["@@l@@UšK@Ž@L@bX@@VlL@JƒLUVnX@`ÜXn`V²mJ@bU@@n„b@l°xnnĸVƚ°@„ƒĊ£Þ@lWnÑnkʶJmó°w@kk»V@»ƒ¥k@V@kw@wVm„a˜Å„mšaô£ŎƒXI@mln„Kla@mV_UKƒ@kUkw@alW™IU»™mƒ—@WUIl±UUÅU›bkJƒ@a@wUKUaVIÆmXIWaka@m@Ul£XKVw@ƒUIƒJUkmJ™ƒVkU@a„ƒWK—ImVƒ@UxmL@bX`WXU@U`ÇkUak@@°UblXk‚mLUKmL@VULóƒƒVk@@Vlbn@Ub@ċaUJUbƒIUlVLUVVbVKX„VlVXU@mb¯@™VmKUwLWx@šUb@VUb¯KmLUU@aWaUaULkK@Vm@@b¯L¯w@mƒa@ƒm@UUU@U¦lJUXƒVƒmkb@nm„XVWŽkb™IVxUV@VUbWLXVƒLW`Ux@nk@Vn@x@VkJ@œV`mXkŽ@V„xV@lVššI@VULš˜VU„IV`°bVXXx„V@VWVnL@xV„Ub"],encodeOffsets:[[121332,37840]]}},{type:"Feature",id:"3702",properties:{name:"青岛市",cp:[120.4651,36.3373],childNum:6},geometry:{type:"Polygon",coordinates:["@@„@nU˜JXLƒ„@blVU‚š„nIVl„IVJ@„UxWLk¤@V@nlbXbWJÅnUJVbVL@x@b„ŽlIœaÆVVVk²VJ@X„˜šnV¼šJkX@blxlV„@VLU`@nkbƒLkm@nWJō„ó¤™bƒn—ƃbUn@xlxU@l@„¦@¼UŽl¼ĊUnW„@šnĠmÈxšU„V˜I„VnUVV@LšV@šnVWbXb‚UVbnK@UnKVmVIllœUVLUJVXlJš@nnV@nmVUUm@—˜Vna@ƒK@mUaV_UaV@„aV@@a™anlKUk™KklwlKXwlm„a@UVI@akW@™l@„bnxl@°nJšxl@°£„WŎIUÑn»lašmô¹Ŏ¥VaUUkƒmkġWɱIUUŹ`›@kk@ĉƨřV¥_Ç@™Ĭƒ¤ÝL¯m¯£ƽóķwUW±ī¯kōaĉĕ™kğmó°ƒbW@UKkLUaƒVmz@V@ŽUxVn"],encodeOffsets:[[122389,36580]]}},{type:"Feature",id:"3717",properties:{name:"菏泽市",cp:[115.6201,35.2057],childNum:9},geometry:{type:"Polygon",coordinates:["@@@¥šIVUÈmÞ»@UlU@Un@VW@UVmkk@aVUUKVÝ@UVknK@UV@VVnIVƒ@wnƒmwmKXaWaXI@UV@Vy²blkVKkam™U@kb@Um@VmUkmƒKmkXKWwkU@Ulƒ@UnK@UVUUm‚KXwšUVL„w‚K„U„@@Wl@@wUkV¥—@@I@W@_V@VWUw@UUa@aƒaWa—@@_mKUw™l¯amzmV—@WK™nU@kƒWLķaUKbÝVmV@UWÇbÛ@ƒX™°UbW@XŽm„Vlk²UJUbmLÇxÅWUzl‚¯Ll„@VkK™XUbWJ@bU@¯@™ƒkbƒLmKka™„@l™_WšXºVbUz@J‚n²V@¤lX„Ž„nV°šLn`WbXLôVlKVUšxXn˜lXLlU@bVV@„XJWLUVnVV@„„@n‚l„°nn‚V„KÈbVXÆJU°VnXV„kV@@xVL„@šWlb"],encodeOffsets:[[118654,36726]]}},{type:"Feature",id:"3708",properties:{name:"济宁市",cp:[116.8286,35.3375],childNum:11},geometry:{type:"Polygon",coordinates:["@@nam_nKlVLXa„Il`š_@KVVXI@m@w‚ƒ„@@k@Kšnô@n`VbV@@L„L@KVVn@VX@‚VL„Jl„š@VUUƒU@Uam@Uk„wšKWaXamkJmIUVUÈblašUnV@kVKl@@lXL°kVJ@VÈnVJUX@V‚LXl@xVLnU‚@VK„V@a„IUaV@„bĊU„x„K‚kVJXUlV„ƒ„UVašI@WUI@KlUnw„mWk@WXIWƒ™U™L@Wna@Um@@UƒVk™UUlanWW@kkU@y„kWk—aWVUlÝbUU@kƒJUIU@@ƒ™JmaókƒLKǃUUkKWLk@WbkUUaƒbmKn¯°¥V@XwV@VanaVaU_@Wlk@WÈ@VUÈVVۂm„aklKȯlLVUX@lK@aX@@kV@VmV@VwnJV_UWUwƒX™am@kW@wVUkKVIUUVmU@UV@IVK@aUL@aƒV@Lm„UKmx@ŽômLkUWJ@šnXmlUxUL@Vkn›VUšU„@V™L™`Ub±LkV@kUKÇbÛ@ƒU™Wó_mJƒ@Wk@@Xƒ@ƒVLƒxUK™VWxLVnUV@VmL@Vk„@VlVXxWLnl‚Ln„VlUnn@@VlaV@nšlbULkl±aUzU@@VWJXbWbnLnxm„@xU„mJUUU@@VmLUl@VUÞVLUV@bllUn@VUXm@@VkV@VݼÇnUV™J@¦nnƒlnVlL@„Þb°KVV"],encodeOffsets:[[118834,36844]]}},{type:"Feature",id:"3714",properties:{name:"德州市",cp:[116.6858,37.2107],childNum:11},geometry:{type:"Polygon",coordinates:["@@„¤@VmbVXnVVbVJššX@Žll@z„lVInl@„@bVxUbĠ‚l@Èbla„IšxXVWb@L™@n‚ULWVXXšWWLnL@`@LUVVL@lVn„JšU@UUk‚a„™nš‚Vôô„b°¼V‚ސXš˜‚œIÜbČa˜bôW„XÞWÈzÆmnLVJ°ÈnlV²lbnW@™@UƒUV™šmnwmkkKWƒkla@mVIUKUa™aUwmn™JU@@amIk@@bVlkX@mmUklUUƒƒa@_UaUUƒV@wƒw™WkXmW@I@WUaÝU@UXaWUU@UUVW@UUUWUn¥nUVa@m@k@alU@wk™LWa@UUm@@wnmU™wla@anKn_@alK@ݙ_ƒ@@WUUUmlkaƒIƒyU@UwU_Wa¯yU_mWUwkImm@InWWUk@@UVWV—kW¯U@VƒL@b¯b@l±¦@šVV@lUbV„@škxVnUšl¼XV@b@lV@nIWxnbƒ‚™@UU™LƒxÅxm¯ƒaUƒ™wU@mUÅVÝKULm@bmKUXó@"],encodeOffsets:[[118542,37801]]}},{type:"Feature",id:"3716",properties:{name:"滨州市",cp:[117.8174,37.4963],childNum:7},geometry:{type:"Polygon",coordinates:["@@Vb@`„bV„kVlnV@nlWUk@al@nJ@bV@šInmVxšbVbVLUJ@nkb‚lX„lLnlmx™nUš„V@V@šmXn˜lbĸ@nnVx‚b@lnXV@UJ@nVxšxnxVbÆVn¯ƒĕ‚@@wÈçUÇlķVIœb‚@„Çmk@¥k@UkUK@aWakUóJW_UW@wkkWK@U@Kš@XUƒƒUkmUUalKXala@U@kkWlkÈl@kšV„mVIVmU_‚a„ƒƒwnwVW@wƒwUƒ@wU£ƒwkJWIyUI±bk‚VUJ@nmV™Ukl„Xmx@lnbW„kVƒUkLWŽƒxkKUUmUkb™J±—LÇxUKmkUmkkW™™a„mUaVkšJÆ_²KĠ@U„W@w„U‚¥nUWwK@aÝUkÅVaVK@akLWƒƒƒ¯I@bnbVx¯JW„ñšWbUL@šƒŽnV@VmbkUUV@IÇak@@bWak@WJUœJWL@bXV@„‚@„V„Jlb@zUlUŽUImšnbV‚mz@°UV@V™bV@@V@L@xLmKUnmJVX„J@VkLW@UVUL@b"],encodeOffsets:[[120083,38442]]}},{type:"Feature",id:"3715",properties:{name:"聊城市",cp:[115.9167,36.4032],childNum:8},geometry:{type:"Polygon",coordinates:["@@ô@VWnL‚an@VKÞLÆUnVV@šxV„„bn°Æw„wšKVVš@„maXwmJU@@k@aWUk»V™Umlw@™UƒVa@kUU@™²¥@k°a@a„K@U›ƒU@mmm@ów—ѱ¥¯@@w™Kmw—I›¥kU¯UmakJmIUaƒVkKUkm@VUUa™Uƒ@UaƒKUK¯@™w™UVŽUIUKVw™k™¥™wƒbVŽ@xn„@lWnXxlL@`„XlJX¦l°XxW¦@¦Ul™n@Ž™@@Um@@VXVmx@¯bllUnUJ@VULVn@b„xV‚VL@b„„VlnVVblV„ÈnVlIVJœLô„lJ@xl²„"],encodeOffsets:[[118542,37801]]}},{type:"Feature",id:"3705",properties:{name:"东营市",cp:[118.7073,37.5513],childNum:5},geometry:{type:"Polygon",coordinates:["@@ͬUǪlô@°Uœw°ōĠ¯š»Ģ炻XÇ@w™wƑa™ÇƒkwVƑ¯@řķUmm¯w@kƒa@mV@@anIU±m_ÛW@_mWVU„K@IkK@UW@@a@K@™L@Vk@±U@UV@lm@mUU@kLm„„xV¤@xV„„x@xUXmx„xƒ„bV`UnUJƒn™U@lÇkkllX@l@VkbWbkLVbnVVl„„WV™@@L@VXLll@xVXX`ôIlVXb@bVLVll@@¦nlƒÈ@›aUJkĸVÈÇè@x"],encodeOffsets:[[121005,39066]]}},{type:"Feature",id:"3701",properties:{name:"济南市",cp:[117.1582,36.8701],childNum:5},geometry:{type:"Polygon",coordinates:["@@²¦˜Òôxn@nn‚@V‚œ„°VlXU˜UX@Vl@XVmX@JnnlJVxnXV`°zXbV`VxV@„z„JlbkŽVnVV@X„@š`@ÞkL@bm`mL@bkbšxnVm@xn@VV‚@XbšKl@xkV@b@l@nUbmVm¦XVVV@VUXVVV@XVWb@VÞVVb@X@JnXlWšX„x@x„UVV@aVKVUX@lK@UƒIUWnIVmnL‚K@w@K@UU@ša@UVU@¯nyUman™VJVVk@ykaƒIƒU@@ƒWU@aXK‚IV›XIl@Xb@al@Èb@JVUlVna@UmU„@™VKXaò™Xƒ°IUwma@aU@UU@wVW@фw@a™I±`kbƒUkw™UmJ@UkmÇUUkmKknUVƒ@mJUkaWkƒa@KmKkUƒLmyXa¯_@WmImmbƒLmUkVUbUVƒJ™bƒUkkWJkUƒl™IUm™k™Lƒ›„lK@knaVmkI@mWaƒLUK™UU@@VmLUVLWK@UUUƒWUkkVmx@„Vl™¦"],encodeOffsets:[[119014,37041]]}},{type:"Feature",id:"3709",properties:{name:"泰安市",cp:[117.0264,36.0516],childNum:5},geometry:{type:"Polygon",coordinates:["@@n¼šŽW„nxšL@x°@š¥Uk@ƒnwlUVl„XVV@VXL‚KVUnK@UV@šVVL„KXb@nlJUnmb@lkLƒ‚„œšKšlVnšJ„klVXIll„Vša„IVUValUnV„K‚annnJ@X°`Wbnz„KlVnL‚Ž@L„bXl‚bVlnI„@VUU@UmVƒ@U@Uš¥@VmV@@_Ua@m°@@ƒ„kmUUm@UVmn@nX‚@@a„anJVUVL„mlIVJn@nkVLVa@KVmVLXVVLš@@U°bn@VaV@@K@aVkœbWaXUVymU@aUImWXƒ@™¥UaVwUaVwUUU@WWƒ@k_™VUKÇa@ƒƒnmxkV@LVJ@X™JUbƒVƒ„kUWVUIlƒLƒwĉVƒaU@VbƒJ@bƒUUL@mVUK@wWkK@UVWUIÇm@UUI¯lWK@kk@UL@lmU™VkbÇaUVVnJlIn‚WbXb™LƒxVln@VbV@V„UV™@kƒƒIUK@UWm@UU@LƒK@KU@Uam_ó@™m@L@lƒ@„@x@nWJUU@L™`k_ƒJWbUKkmLn`mb"],encodeOffsets:[[118834,36844]]}},{type:"Feature",id:"3710",properties:{name:"威海市",cp:[121.9482,37.1393],childNum:4},geometry:{type:"Polygon",coordinates:["@@VbUnVVUxĊ¼š¼ô@Þф¯‚WǬLŎUÆW„¹Uǃō¯ÑƒÝkţ™™ţóġ™óL™ł̥U™wm¥kÝmkkKóbÝ@U¦@‚mb¯LkšmJ@x„Lmn@lk@ƒa@Xƒ@ƒlXbmJUz™V@bVJ@n@x„blJXzšxV@Va„KVUXLlmVV@In@Vx„UlW°@nLVK@zXVVal@@V„w„bVKšL@bnx@„WbUJ@VnXVlVxl@nnnV@„lV@L„‚"],encodeOffsets:[[124842,38312]]}},{type:"Feature",id:"3711",properties:{name:"日照市",cp:[119.2786,35.5023],childNum:3},geometry:{type:"Polygon",coordinates:["@@UaVUUKVk„JVaVIČb@Vam@ka@Ul@„Uô„VK@UnKVLnKlkWVa@¯l@VbÈlV_V@XWW_@anKVwUmVw@@Uny„UVblKVLX@„aô¯ó¥mÛĊÿÈ¥š™Þ¹lUīƒ¯Kĉ¼ʟbÇV™U™ŽUŽ™XmakJUnmV@bUnmJ@XnJVLn¤UzmJUn@`¯ImŽU@™nƒKVkkm™KWb—b@xƒk™@mL@KƒUUVUKkbWaƒXkK@bkJWbnbl@UL@l„Lš@lxx@b‚nUVlV@¦²°@bVx@Jƒ@¯XUJ@bUnlxVŽ„X@‚VV@b„L@nô`@bkbVVÞL˜xnU"],encodeOffsets:[[121883,36895]]}},{type:"Feature",id:"3703",properties:{name:"淄博市",cp:[118.0371,36.6064],childNum:4},geometry:{type:"Polygon",coordinates:["@@nƒlKV@nVn@@kVU‚@²VVaUƒ@wmKXU@UƒUWwUW¯aU_ƒJUV™—VK@U™JU™@kUƒw@UlnWU_@›lI@U@wUml@@mVwX_„KWUXKVa@UVUUwšJlaXWUnƒ@mla„n„UVWkIV¥V@VVVI@a@akakLWKna@aVwk@WUƒbUlk@™k@U¯UWWU@mUUVUXkVmVVV@nkVƒLƒVÅwƒ¯k@WVXb›aUl@bV@@b@xkVVXVxkJ@nk@@ŽVLUlVb‚VXUVVUzV‚™LVbUbV„VWVkLmškJ@n±@UxU„VVkV@bƒx@ÒUX@xVVV@°J„„X„lK@bULUblÆÞV@b‚LXxmV¦ƒV@xƒXVŽğ@±LÅ`™IUlVbƒnšbXšllVnnlVLÈw˜K²ŽšIlanVVVlL„wXlK„VlUXƒma@knwƒWlkšVnU@mVIUl²aVJ‚zXJlI"],encodeOffsets:[[121129,37891]]}},{type:"Feature",id:"3704",properties:{name:"枣庄市",cp:[117.323,34.8926],childNum:2},geometry:{type:"Polygon",coordinates:["@@‚yUU„U„kl@@aVmšLXw°»°w@y„L@UUaWXKƒƒVknwVKlmš_UmmUXK@ašw@k@mUWmUL@ƒ@™@£@KƒbÝV@akw™aULmƒƒbUK™LUU@lm@—°mL@nUJVxVXU`mIUxU@UnU@@lW@@bkLW@UVkKÇ°kLlŽƒbnUÜÇUUVÇ@@Xkl@XV`UbmbUbU@WxU@¯¦m°nL„aVblVXal@XKlLVVȄ‚L„KôlnbšI@„V@VJ„I@lVVÞaVkXU"],encodeOffsets:[[120241,36119]]}},{type:"Feature",id:"3712",properties:{name:"莱芜市",cp:[117.6526,36.2714],childNum:1},geometry:{type:"Polygon",coordinates:["@@lmnLVlÈVln@VnIšVlx„Vla²_šJlUUUVƒVw²@@mlIn™lKXU‚UUƒVaUašKUVyUUWVUUaVkUK@l@@mlIUwUWlU@w@aU@@LU@Ubm@¯a@V™@UKWUUKUn@LUbUKmlm@UIkJƒnUKUVmIƒb@b@mWm@Un@VVnnVƒl@„¯@@nVb@`U@Un@Ž™¦@V@VU„VnV@"],encodeOffsets:[[120173,37334]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/shan_xi_1_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"6108",properties:{name:"榆林市",cp:[109.8743,38.205],childNum:12},geometry:{type:"Polygon",coordinates:["@@™ýVƒnIW»ƒW@»kUÇL—݃U¯¥ÇIUWWїUWwX¯mƒ@»n@ÜÈķô™@a±kȱƒw„ÑmwçċmU»ÆkkVyIm™ĉÿ@ƒÝ¹ƒWnwÇVš™Åaƒzmmĉ¦ó™kVmx™xU¼VškVm_UlVlk„°IV‚kmJa›¦k™™LmmV@XmKnšlUô›VXbƒbƒ@UaÇLğܙ™Åwƒ£mKnmċwÅ@UkƒbmaVƒƒƒn@m¯aU™Jm_k˜@kWXyl@@kÅamw™LU™Þ™ƒ™mWÅzUKƒš™Uk±@™b@nnK‚bX¤mzVšŽVxÇn„‚¯„@ÒknWƒƒVUbkķÈÑWkk@Va™™U@„mUkbƒÝÅ@Ý¥ÇbkĬ™XV`kLǍVmalUUa™nV±nwmkƒJ@Inƒ°KVw¯UnÅ@¥™ƒ™U±bUU˜±œmWbÛKWnUm`UƒVK@bmnœm‚Èż@V„L@xƒxmš„Ť°nŽ@VmK™²VlšlKk„ô@„êÜV@VXLlmš¦UššV°Ș¯²ÿ@¥š@ƁĊ˜²IšmĶnnb°b„KVƒĸLl„Þ@UȮš™Ü°IVƒÞÝސlŽœx@ŽķĀWŽ„Ux„èƐ@š°ŽXnšlĊĖ°m„nƒšV„²V°ÒƦ„aބ„˜@zll@bÞĀšlš¼nKĊ¼óȂb²±šIǪÒ¯ĖV@„lxnVlk„JlaXwŌĉ„„@VnŽššlÆĕ„UÆLœèŌŤôxȚlUœ@šxlaUċĕXm„IWmnkšVVƒ„VW_@aÈWUUmk@ƒ¯çVm»™±W¯n¥V™mkXw±ÇVwƒ"],encodeOffsets:[[113592,39645]]}},{type:"Feature",id:"6106",properties:{name:"延安市",cp:[109.1052,36.4252],childNum:13},geometry:{type:"Polygon",coordinates:["@@@kkÇmIšmUwVkUƒƒU²WmšVkm@m`mIĢĕUƒVa@™mXƒƒÿVVkyUýšĕ@l_UmnƒW„KVkţ™™¥™aƒwğ@™@aôƒ„ƒWa„kUmƒa¯¯™a±£kx™mmxUwÝ@xmU™b¯K™wó„Ý@kmm¹Ub@lklVbmnnVUV@x›UknƧJUX@ŽƒLÇWkw™LķƧÅwWJk„ƒLkþĉxWz™JUnǚkš@Ɛk¼ÜÔÈKšè@°lșÆk¦l„n@l¼@l¯L™°UU™VÇ°ƒ¹—`m¼mXk‚™bUaƒV@U¯x@¦™Ç™„UUmlmUVm„nnmlkw™@@šƒ¦Å‚ÇLmx¯Iklš„@¦mÆ°VUx¯Lm„@J„InlmxU²šmVbkV‚bUnȎlKU_šWlīÈaÞ¦Æ@„ÞlanV@ƒšVšUbl@XlÇÒĸlŽVa„UX„lm@Ñ°ƒƒÈmUw‚U™nyW£amL@mša²@lšV„™VLÆynX„šÝšVššKnxÆb@lk@WzXŽ@ll—n`šIV‚°b@n„m„„‚Unb„aVlÆ@ČxmnnL„¤ÆxššĠÛÈKVb„@„aWaœU‚ókVm™nL@W‚UnnšKlšœ¥‚bnIlU¯JlƒUkVkn`lUU™V»šwnwlUôšĊ¥nn„yÆb"],encodeOffsets:[[113074,37862]]}},{type:"Feature",id:"6107",properties:{name:"汉中市",cp:[106.886,33.0139],childNum:11},geometry:{type:"Polygon",coordinates:["@@lKnb@n„lWb°bkxĸwVb@ł„nlŽ„ƒĊ¥šL@XŽl™ÈƒVblÈK‚b„akVwôml²`‚nœ@‚nVKœl˜k²xŎƒ°¦VU„JĊw@çnWçރVkUóÛ@¥kwš™šUmƒX¯WšÑkƒ@UymIUwlUn¥‚mUk²a°¯V»@™ÝVș„ÝċÅÅVl»@l@a°±@_kammÅb™a@ƒƒm@ż™KknõĠ—@mšƒ„¯LÅw›‚—LVxmb@¼kV™@mw¯wVakKW»X±¼¯Vkxƒb„¼WŽ@nx@x±bóakbƒ@ÝmU™@ķÓÛL™kƒVUm™k¯¤ÝLUlÝ@Ýz™š„x@x™°™™™bƒmƒX¯aUJW¯—k@bÇWƒwÛwWxƒ@XWlb@Žƒ„VŽÈUlwšLnl°VlUô¦œU°¤VšUxVXUxlbkVVlƒI„°„ÅVlU°m@k„ÇU¯xUlƒLUlVL@b™°ĠInĠ°ÈnK‚„@xÞa²n‚aUyšXUKVkšWô¼Èa‚z°JXUVÇV_„JVƒšz@Žnb"],encodeOffsets:[[109137,34392]]}},{type:"Feature",id:"6109",properties:{name:"安康市",cp:[109.1162,32.7722],childNum:10},geometry:{type:"Polygon",coordinates:["@@„bĊaƨèšwôô„¼šb°ašXVƒÞVUÞ@‚aXƒm¥kImx¯¯ƒV@anU@UÇéğL@ƒ¯¥V£mƒ@ÝÈb„K‚™„X°wČÿ˜ƒ„b@xÈblxȯĊ„„mÆUVƒ„nÈ@ƨÜLĢ¥ƒŹnƒ°Vnn˜K„aô_ȃšwU‚aXmnW‚¯kl›LXƒÇ™ō¦ÝaÅVmbğUn¥±wÅéVƒan¥ƒ„U„»°am¥„£ƒÝ@ƒ„wVw™¥nU„уUmmVwmķIÅaóVWxkblb@ból@œğÒĉ¤ċXƒ˜¯X™xk„Ç@óÆÅx@š™xķ_kmݎǣkblb@`¯²@bk‚‚@k¼ÆUČƃÞǚÞU@šU¼¯°±bVlnm¦kVVxnJVz@‚l„™ÒXW°n„™V™šlx@¦ôÜVUl݄Xèm@è"],encodeOffsets:[[110644,34521]]}},{type:"Feature",id:"6110",properties:{name:"商洛市",cp:[109.8083,33.761],childNum:7},geometry:{type:"Polygon",coordinates:["@@²nl‚ôbš„°aVwnKÞIš`°wšXôw°VĊ°@ŽÅš„ÞÆV„zÞK@xšŽ@a‚LŚ@b@ŽnLlƒ@šln„mnLVw„a„bVƒ‚VnbU¼„Vƒ°„bl„šbÈ@ĶŦb˜@nÇ@amIyUI@ĠVmôƒU™ƒVwkwlanJ„¯lwó¥@an°Jš_„‚@š™nóƒó@£l¥UwmašÑ@ƒUm±V_ƒJ—£›J—UW¥¯@ƒ_k¯¼mUƒVUè¯b@wmL™»ğVmağI¯¤ċIUW™XƒKĵ¦ķaƒJUb™IƒlUóVmk@WÅÅÇ@ƒmU„ÅVƒnĉƒÇ°kwÇa@wƒa—„ċĀ¯xƒWšƒLÇa@Þn„U¤°¦@„ĠKÈê@VmV@b„U°°nwlJn¦W„bÝ@VŽ"],encodeOffsets:[[111454,34628]]}},{type:"Feature",id:"6103",properties:{name:"宝鸡市",cp:[107.1826,34.3433],childNum:10},geometry:{type:"Polygon",coordinates:["@@@ƒ„£@›°Išb@¯°ynŹƒaUƒlƒU£„Umšĵĉ@@ylUÞ@@£kWU¯WaU£¯ÇV¥ƒ@kb¯wƒn™¥ÇkUÇnUƒ@¯±›kULm›@m±_kŽónUxlŽƒbaÇLkŽUaDŽkšW@™Kĉ¦ƒ„kƒm@ŁUaķxlw¯aXaƒk@mmakL@šmšÛŽ@¼m„@l„XV`ƒn™KUš°°@²š¤UÈ@VxmôƒxKl„VV²aVw„Xla„Vlx@UVnŽÇnk°ƒVVL™lkI™šƒJÇk¯V@šknƘn@lznmlVkzVŽ„VVxš@Ux„z@x±¼VxxU„l‚kb˜@„¼Čk˜VXlĠkôV²w‚LUKlwœJ@a‚IV¥Þƒn¯Ün„‚„@nk˜l²kÆ@š°„aVbnI@™š‚Ťn"],encodeOffsets:[[110408,35815]]}},{type:"Feature",id:"6105",properties:{name:"渭南市",cp:[109.7864,35.0299],childNum:11},geometry:{type:"Polygon",coordinates:["@@@ÈôL„xUŽ°„Þ@mŽÈnl¤nUôL‚wX`@ÞÝL™ŽUšmLô„„ŽôbVbnºlnÞ@ôƒšx°LšanV‚wÞ@Vxnwšnlw²¤šb°°„bVnƒlXbƒ„ó„@bš‚Ġ@„xšbš¦ŤšV™Xġ„£W¥ƽɽƒó@ýóƝÝ»„£X™mƅšĊkUƒ„@™™šó„kťaĵŽÇ@™akƒƒa„¯ƒUV»maUU„ƒaƒbUxmKƒnkm@™k„mK@ƒxó@¯n¯KǦ@ôÅèlxkx°nƒƾ¯KU¯WķL@VÝIUb™yWbX¼Ç°"],encodeOffsets:[[111589,35657]]}},{type:"Feature",id:"6104",properties:{name:"咸阳市",cp:[108.4131,34.8706],childNum:14},geometry:{type:"Polygon",coordinates:["@@šIXyĊwlý„KlƒXIVaķƒ™»a›£„¯aVU@a™‚wÈō‚ašL²»‚VœUln°WȯW»XašzVaÞJ@Uƒ»@¯Ýbğwly@£kÑţ±Wу@ka™IUƒƒnƒ@¯ƒómţU™b™U¯lÇIÝb@¤Ý@kV@zĊ@™ĶnƒVV¤k„V„„bmź¯z@°™a¯J@œƒ¤@„„bUx™bƒ„@`™xUÔ±ºVXœW‚„UnUJ‚LĢ¯ÈKlblmÈXŎ°šU„°LšŽlkÞKš@Èxl_°ĶUÒkblš"],encodeOffsets:[[111229,36394]]}},{type:"Feature",id:"6101",properties:{name:"西安市",cp:[109.1162,34.2004],childNum:5},geometry:{type:"Polygon",coordinates:["@@°²@‚„mVVÈÈlš¦„m°xla„@U¦°ÈV¤XbV°lXÞaÈJ°kšVšaŤVôn°„„@„mV„šJlb„@XÒŤ²lÒ@¤kzĠxÞa@°„¼ĸK°XV‚°L„ƽ¯mlwkwÆç@óÈ¥°L°mô@„w@aƙK@b™@wÝLƒyÅUƒÝƙ@ĉ¯¯Uóx™W¯x™_ÝJmLUx¯b™ƒóak±mÝUU„™W¯b™aƒ»óó™xƧçĉbƒaĉxƒIUV¯¥ō„±w—l"],encodeOffsets:[[110206,34532]]}},{type:"Feature",id:"6102",properties:{name:"铜川市",cp:[109.0393,35.1947],childNum:2},geometry:{type:"Polygon",coordinates:["@@ÆxĸƨšKlxÈX„K@VWƨIlmœV@wVUmUnmUalk@kVaUaóaƒóƒnKV™šÞK@ÝW_xóKmVk£ÇmnÝ@¯ƒVƒwóK@ǯXkm›VU±¼™KbÇŎx‚š@bUV°bƒœ¤‚bš¼ĸ„Ub"],encodeOffsets:[[111477,36192]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/shan_xi_2_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"1409",properties:{name:"忻州市",cp:[112.4561,38.8971],childNum:14},geometry:{type:"Polygon",coordinates:["@@Vx@lnbn¦WlnnUšmš°š²VšV‚VVVnUn„ºlz@l„„@Jƒ@kXWVXl@Lƒa@„ƒKUL„ŽlbnKlLnK‚LnKÆXn°šbVV@bUVl°Un@LnaVJUbW@UX²l‚@ČwlVVIšWnkÆa°„„anV‚Kn°™UW¯@™aVUVk@Un@„aV@ValwUanmWU„k@WVUUanaVwnLVl°@nk@mVU@UVK@w„LVKVU@ƒ„K@UUKVUV@@bnL„a‚V„aôšlIXmlKX_°KVV@bVV„@šzV`kblI„V„Ul‚šL@bnV@V„Ċll„„VlIXW@k„a‚U²blKšVnIlJ„albXXlWVn°JnšnL@l@XlJlaX@„X˜W²@l_VmnKšU„blU@mnkVK„¯@U@ƒma@kX¥VƒmakkƒLƒa@aƒ@WIUUVXWWnk@a°a@kkm@kUUmJm@WUUUIk`m@V—kaWWkX™KmƒXk¯ƒ@WKƒLkak@±bƒw@ƒaƒa@akaƒ@ma¯@ƒL—KÇÅkKWbkmġ™±ÅUƒLUK™VVkƒm¯LUVVbƒ„UwUW¯bm„ƒULƒxWJ—@ƒklmkUm@@KnwVkVK@akwƒ@@a¯bƒKkn›VUI™b¯mmbk@UbmKUL@xUUƒ@klmLUŽlVXI‚VVVUVUœU`mLXVWbXnW`Ų°xmŽxU@mĉƒƒwU@mbU@UƒmbkVW¦kJ™@ƒX@`¯Im@UlUVVnb@bWJXnmbƒJUU™UUaƒ@UamIkaƒxƒ@@x@b"], +encodeOffsets:[[113614,39657]]}},{type:"Feature",id:"1411",properties:{name:"吕梁市",cp:[111.3574,37.7325],childNum:13},geometry:{type:"Polygon",coordinates:["@@@a@w„@„wlbnJVb„@VbšVVV„InaWmXI@a‚aUmVUVkn@°J@_„Wš@lIX¥lUnaV„V@naV@„xĊ„n‚V@‚wn¯wƱX_WmXaWUnKV_V›VUUUUWJkUVnKlk¯™@@kmKUaŁ±KkU@WmI@WUIlUUmVwXƒ‚w@ƒUlUVwœV‚@„Lnb‚W@anU@UšaVkô@l»n@na˜JnUÈLVaƃUUVm„VKVƒ²L@mU_lK@UVWkU‚a@a@U¯aUaƒÑóÑUb™„ƒKk@@aƒk¯mVaUwVƒÑkWUmK@UUKmXUWÝwUa™LUU@aWJUUU@Ua݄U@WL@VKVaVI@WnU@alIVKƒƒ@kIƒmIkJ@™m@ƒ™@@_™K@xƒ@kaW@U„@Vmn@ŽUK@mIƒJUXV¤XXWlkKƒkkK@XmJVakImJU@ó™¯LWKUV@nUVƒLkxmKkLma@kXKmmƒLƒab™LmK@V@mXVÆUxƒX@`nL„aV@@VmLUVnLlLš˜„b@„šŽ°²nx@b‚VUxlb@V¯bUV@zV‚XVĊXVx@lVn@VnnmŽUš@LlJXVƒz¯VWVXbšV@bmn™VUVk„Çþń@XVxmbUlV„Uln„W„@„Xl‚@VLXÒ@bÞJ°¦„L˜ò„@nU‚b@°„X@ŽXbmVU„V„nb@x‚x"],encodeOffsets:[[113614,39657]]}},{type:"Feature",id:"1410",properties:{name:"临汾市",cp:[111.4783,36.1615],childNum:17},geometry:{type:"Polygon",coordinates:["@@nW‚@@UnLšK‚a„b„KnnWL@lnblKnLlw„KVU@mVUXL°KôšV@nIlJUbnI@WlL„llLXkWWU£VW„InJ‚@VL@nm@UVƒX@lb„@@wšL@`‚@„šn@V@lw„@n„VmVX„WmwnUlƒœa@_lK„wVlUn°xVKVXXWlUšVVI@K@K„n°KœwlVlU@kna@V_„Wn‚m„UVm@kXml_@m„LlKXw°m@_ôJVUV@X™l@UaV@Va°I„lk»VwUkVmwUmmVn@V¯@KƒU—wmK@U¯wUVÝ@mJƒU—nWK™@@UnKVa„_lykUmKÛnm@™x@ƒUUlwVk™ƒXW@ƒa@Uƒ@@K@ƒkIV™nammVakUlƒ@wX@@kƒ™¯@ƒVVbml@„„°UbULmlVbnbÅK±VƒKVXUJWa@ULWaUU@@U@aWK@UkxUKƒLUUUJ±UkL@V±kk@kam@UV@l@LWl@n@VVUx„LlUUx@VUV™U@aƒIUl™L@°mLU‚ƒbkUUaWUUaUU@aWK—LWJ@bUL@VUVVbU@m@a@kmKmnĉlUK™XƒWUblb—xmIkƒƒU@xWb@lkšVx™LXŽmzVV@bklVVUzm˜@bk„@Vx@xlŽU„@lUbVnl@„Wxnl@n@ŽUbV„mL‚mƒb@`X@lUX@@xlnkLWaUJnnWV™Vn@l„@bULVV@l™V@XnJVX"],encodeOffsets:[[113063,37784]]}},{type:"Feature",id:"1407",properties:{name:"晋中市",cp:[112.7747,37.37],childNum:11},geometry:{type:"Polygon",coordinates:["@@@šlInJ„lJ„@‚„ULkJ@bmV@XUJUb‚L@UXKV@ރVbV@VVXI@bVVšKVbÞxVXnWVL@VnLV‚lX„ÒUŽVxUb°n„l@bl@„LšƒVaô҄ÒVb°b@VnLnnV@lmn@lb„U„V@„‚JœUVV‚Xkl@lUzmJ@xšXkl‚bUn„JVšUb„nU‚lb„V@nlLX@lakšV`Ub°š@XVJnU‚L²KlxnI@KV@lbUbVV„KnVl@„zlm@Uš@nŽšI@WUaVl@@mVU„@XkW@ƒnkVKVƒ„_Vw„y@knwVa‚@XalU„@šVnml@„X@V„L‚KVaÞbnnlJšI„mVKn„VVVInVlU„@„m@™mXK@UmyUI@mWUUakamw@wUwmLkakwVƒmK™w@wUam£y@am_ƒW@™UU@knmm„amU@WUa@knw@ƒUUUUV@nƒJm@mVUkKVUUUkKmwƒKULƒKUImV@lUn™nŽm@mbUK@°™bUnmbUmkkƒWUb@am@UXkK@a±@™V™@ĉř„V‚UXVxUVkLWl¯@@bULUlm@@nm`—XƒlWakIkm›VUbUL@Vm@kIƒ@@Kšm@—VaX‚I@W@aU@kUƒVU_™KƒbƒJkkǎ™b@nkKmL™wÅW@kVUUƒVU@WUIƒJmIXmma@_kyVaUUlkUm@ƒkU›x¯Lƒm@L@LUJ™UkVWXUWUL¯wVmUkƒxkL@`›bk„mVnxƒXUWUnmƒƒ@kxU@"],encodeOffsets:[[114087,37682]]}},{type:"Feature",id:"1408",properties:{name:"运城市",cp:[111.1487,35.2002],childNum:13},geometry:{type:"Polygon",coordinates:["@@„Vl„nJ˜wkaVa„XšWVLĊknmnL‚l@@bn‚V@UaVU@UVK@aXI˜KXL@bVVVbXVVblV„aVnK@¯šKVk„J@bšVVU@UVwkVƒKVwUUm@@Xk@K@kVUn@lbl@²l@UlK²VVIVV„KVLlw@VXL@b@VV@VŽXbVK‚@XbVIUW„L‚U²ÆLmaUankVKVaƒ¯@ƒnkUa„U°@„š‚n@@kWa„UVaXUW@IXKVw@U™ƒ„™WU@W@@UUƒU@mn@ƒ`m@UUULkUmJ™IUƒ@@UƒK@U@›anƒ™ak_@wmKUwmakV™kmK™V™k¯b™wƒ`kwUIÇx¯»ÇaŃmn@@™mƒmUkV@wkKW@kxmL™UkĉLÝk™xÝw¯lóVU„mV@ĀVVX¦W¤kz@`Vx°„²ĸ‚š@„Ul@x„êĸNJ°¤V„VlXLWnXxmV@nUl@„"],encodeOffsets:[[113232,36597]]}},{type:"Feature",id:"1402",properties:{name:"大同市",cp:[113.7854,39.8035],childNum:8},geometry:{type:"Polygon",coordinates:["@@²£šyl@Ȑ˜Ė@bĸŽĢbĸ„˜X„a‚KŤnn@ŎôllÈx„nVnÞDŽV@b‚nXllL°KšbVb@J@b—„‚„@ŽU„„xlKXLlKlXk„@Ulk„JlkUƒVKXUƒÇVIVm@_nǚLšašl‚w„VnU@UUwma@aƒaÝaLmUk@@Wƒ@U@@X™wVWÝUUUk@@VmLƒKV»nwUw™aUL@`mzƒJUIVƒUaUw™KUaVIlJôanÑlLVUn@ša„@VV„@@UUwVK°Vn_lJÆLœéW@UUUÅ@»lm@aÞIVwXW˜UUkkm@U@aƒU@mwU£VWU_kWmƒXwW_°yUkkK@UÇK@kkUVymóK—U@KWIƒbUak@mJ@bkbmLkŽ™UmƒkVU„W¦@lnb@„@Vƒ°ULml@nkVƒa™VmLUnk`±@—XƒWW@kbǦXŽ¯„WxI@xmbmxXlWV„„@bŎUz@J‚b@bÞb™ŽU@Wbk@ƒxk@WX¯VۙƒWÝbÝUkVUU@alI@a@akLWa™m@U¯UUmÇL@K@aU@¯VUkƒKmX@`@œkJ@nV‚Ub@lbVÆXVW„ULU`VbkLUV@XWl@bXJ˜@VbV@Vl"],encodeOffsets:[[115335,41209]]}},{type:"Feature",id:"1404",properties:{name:"长治市",cp:[112.8625,36.4746],childNum:12},geometry:{type:"Polygon",coordinates:["@@Uk™Lky@I‚JVa@mÞaWšy@_W@_WƒXVlUVwš@nw°K@m„UƒVaƒmVkU@mmmnLVUmKXa™U@IlKVUnK@UmWkX@WV_Vƒ@akU@a„KWIXyƒIUVmUn™Ua@WaXUVKVmkUWVkUƒLU@@VƒbƒKbƒIUmƒ@mbVL—x›WUUkn±V¯wƒbÅJUbmLkbmKÅKƒbVnUbƒV™KUb™KUbmLKmƒb™aƒKkUm@UŽnn‚VnxUVlUxl¼ƒk¯JUbU@Vbk@WšU@UVóI@`¯nWxkLƒK@nk`Wn@lUnƒVnm‚ƒXU`@mb@lkV@„VnklVVUblz@`nbWnnJ„IVJ@XUVV„UV@lÆXšxnKlL@mšaȍll„I„ašLV`„UlVV@@b@XJWUb@˜™n@L„@lJn@@UVKVaœUlnlJXb„k˜Wn_@mn@VkVK@a°@XklKVUUwVWUšƒĊƚ@šU²@@blLVWn@@bVa„XllVnnaVmša@¯VLnan@‚šmVm@knUVJ"],encodeOffsets:[[116269,37637]]}},{type:"Feature",id:"1406",properties:{name:"朔州市",cp:[113.0713,39.6991],childNum:5},geometry:{type:"Polygon",coordinates:["@@XXWVXVWnnlnn@èƼ@„„xlš„ŽV„nblšššVŽÈUVl‚š@„blnœL܃ĊmUkU@Ua‚—@WI@aXk@WVUlKUaV_VKXƒWUUÅka@VaU@mlI@›@_nW„LVl°UV@@b@LÈKVn°V@VšnXblK@b@bkJ@bVVlUÞVÞa„Xܚ°UXWl@„wl@XaV@šÝa@aa@IVyƍ@aƒƒXUWknwna@w‚JXw°ƒWÈ¥kI@W@kmKm™¯IUmkXWWkaƒbkImJ™UkL±aVƒb@lWXkJƒUkƒĉkƒ@UmU@a™KkƒVƒUkJlaU_™yƒ@UU@aUU¯LW`kLWnkJó™ƒbUƒbmK@aU@UVVL@VƒL@„UVULƒK@xUL@VUV@nml¯@UkmKUxmbVbUV@XƒlXVmnVbkxUbU@ƒbm@@VUlUVšb°@VX¯šm‚"],encodeOffsets:[[114615,40562]]}},{type:"Feature",id:"1405",properties:{name:"晋城市",cp:[112.7856,35.6342],childNum:6},geometry:{type:"Polygon",coordinates:["@@lV„Lšb„an‚LnKVašLVašL„UVaUm„aÆLnLlanKVaÆI„a°x²UlmVVœX˜wUKna„@Vn„J‚a„L„a@UV@@alUkKVKnkmmVwUk„w@ƒ™@kxWUXƒW@@mƒk@aUa@a¯aƒLkKmwkUm@kL@K@aWIXmƒVƒXƒWkUVakL@UVKƒw@aUK@UUKmLU@¯n™KUwVƒUIWJUWmka™@UXƒJƒk@UkmW@kLWKVƒx@bmI@VUaVU@a¯@UUmVKmX@±`kÝKVxUL±akL@V™bƒLkKmVƒ@XWVUbƒVXb@lm@@lW@@xk„lVUbnnmbUšlJ@„@L„@@V„b@‚WXš„UlkxVV@„šwn@ÜmnLlVkzƒ`UbmL@Vš@XL˜m„VnIÞ@VU°x@VnL˜x„V@LU°"],encodeOffsets:[[115223,36895]]}},{type:"Feature",id:"1401",properties:{name:"太原市",cp:[112.3352,37.9413],childNum:5},geometry:{type:"Polygon",coordinates:["@@„@VV@wVKnLVal@na°nšaVJœUlm„L°a@b„@lx@bULUlmx@Ln@lVkn„l˜@XI„w‚K„Vnƒ°aVXVx„ƒUaVU°K„nUlšUVL„KÆVš²Ģ‚lnXalLÈƘL„KUaVkUanmWU™a@WwkUWU¯y¯Ñ@anIl@@aVU„m„I„ymUƒLUUVakaU@@LmJkw±LKmVUI@W¯™VaU_l™kbW@kK@mƒUkaVƒmVaU™ƒIVmalk™W@wnIVy@klkWUU›VI@ƒƒUƒVkam@knU@mmmK@bblVUX@VkLV`@n±KU„ULƒ‚UnVVńUbÇKmV—Imbm@k¼ó@Ul™b@VmV@bXmaƒK@›UUxkV‚V@„xW„UxVnkVVJ@XnJ@XlV²LƂVbnL@lš@°"],encodeOffsets:[[114503,39134]]}},{type:"Feature",id:"1403",properties:{name:"阳泉市",cp:[113.4778,38.0951],childNum:3},geometry:{type:"Polygon",coordinates:["@@°@nb„@lb@b„b„b‚@„x²al@lb„KXU@m‚kUWkkmUUƒVwV@XUW@™naVklKXblKnL‚ƒnLVanImaXKlL„ašV@U@KUKW„alƒXK@£WKXUV@VU„ƒUUVW„_V™@W@@K„@šƒUƒƒIWmXUmƒULƒn™JkImmÝaUbLƒK@UƒWk@mn™Uƒ@kVWb@Ubmx@lƒzUxƒ`U„ULml@„XWlƒ@UV@nk@U‚Vb@X™Jm™@@Vknƒyk@ƒzƒJƒnUV@bk@mJ@b°Ò°zXVlVXx‚@šbXVmnVbUlVb"],encodeOffsets:[[115864,39336]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/si_chuan_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"5133",properties:{name:"甘孜藏族自治州",cp:[99.9207,31.0803],childNum:18},geometry:{type:"Polygon",coordinates:["@@ƒaXamƒ¯wm@±°wUwV@UaVw²Kš™„U@UƒU„¥‚a„ƒ@£Þ™ôx‚Knkm™X¥™IUƒÝUwlk°V„@ƒÈ™‚KUwlkUyV¹„mšx²Xll„ÑW»š„l„w°UŎ„nƒ„„˜Jœƒl¯°V@wôIVÇn™nUllšLšVǚLô¼XW£@±„@¥k_ÇJƒkUéƒkšƒƒwXa@ƒšLlw²™Vx„b‚mš¼ÈxlLȃ„VWÞn¯mǙÑUÝlÛkwlĉmƒULmwUJ™ç@wkm@ÑlUX™ƒÑôġƒVa™ƒUф¯@wķÓkbV„mnU@@y¯IķKƒV@¹šaƒé@k„mÞU°¥@a¯@anKlblU„¥@óğç@Çw@wkla„çݱk¯±@ğÝUÛmݯwƒ@kb±¯akXWÜkXUÆÇUš¤X_Ɛw„V@¤ƒXU‚ƒbUƒŽƒIUlÇUkŽġ@™aXČmlUlèUV@„mVk¦Vxš@¦±š¯ƒƒ¯¯anlWš¯nƒƒÅw@w°KVak£m@klƒKknÇU™»óKšīlaUaV£@™™¯@ƙU™VƒÛÝÇXƒÇl—ÓlŹ„»WUğJ¯£mx™Lĵô›ºX„VlUll²bl„„lŽƒxónn°ÝšU¼mJUš¯nƒƒƒV@êĉ°Uĸ™w™@mƒ@¯kmXamѯaUwÝKU¥„mÅn¥Wmn™ƒ¹n±ƑƆÇôXê±NJnšƒ‚UôlĖkȂVÒ¯¼VnƒȮ¯ĀnƆ˜Ģ@Žk°V°¯ĢVlkšVxm¼X²™Ŏ@ŽVxknWÜ°U‚¯n™Æݜ@`„ôݲÒƒ‚Çzn‚mX@x„è°K°Å„UČĬóĖ݄ƒ˜ó¼ÅêƒÒƒbmšk@V„Ž˜„@ҁl@nĉܛê—x@Ėml՛J¯¦óxȭ°ÝmŽ¯Lĵè›Ā@Ɓ„l°żƒ‚šX@xmŽkV@z@‚„°blŽnÞ°J@bn@ƼUVƒUóŽóLƒ°X°ÝLƒxUn„°ƒĬƒn@lnL@ŽÆ@šn„KÆxnUnV˜InĬmÆnxŎ¼ĊIĢóÞ@ĊƒƨbUƒ‚mV¥lkƒ‚wnL„mšÅÆ¥Xƒ˜wU@w‚wUÞ™@alUUŚU™Vkkm°aU—°Ó°w°U„ƒ„b°aš²K˜¯œĕ˜@ÈbޏĊaš»„XVm°In„‚Ĭk¼Vb„ašJšôš£VĊan™‚k„ů™™nƒÜU@anKnĮ‚bÈmƎš»nI‚霣Ġ™"],encodeOffsets:[[103073,33295]]}},{type:"Feature",id:"5132",properties:{name:"阿坝藏族羌族自治州",cp:[102.4805,32.4536],childNum:13},geometry:{type:"Polygon",coordinates:["@@l@@þ²I@lƒ„VL°wnJ°Uĸ™Ŏè„Ilw„V°¤nĮ™¤Ý„lè„L@„ƒ„@x„l™è²ôĊ_ĊġVÈôJżīlbXšÆÈVŽkxÇVƒ„n°„¦Üb@è@nn@@°šUÈ¥WDŽ_Uala¯¯UǙkƒ»„mVwk»˜k²°VxlL@¤œ_@x‚`ȍ‚Ėöb˜š@l²alX„a@bnK°¦VK@nnWmx@nUnl@@lƒlĉk°l°UXkmW@Unš`k„ÇL„ŽW„ÛÈVxšVVlVk@l„IXb@ylXÈW˜Į„WŤzœy@šmIƒŽ²šJ‚š@nŽ°@V„„J°a„Å@ƒŎkVǚk™aUw„KVw™™Vƒ„@nkm™@±ôkô™ĊJš¼šInÑm±nIššÞ‚XȃĊxĊUÈbÜyÈ£Vkw@kVUV™„m@ša„»ÜbÈmƒUXwÝxƒUn¥@°ġ™Å‚aœJVk™aW¯Û@W¥—UŏĶ™@¯kUƒŃ@ašI@mmanwސ‚W@œ™mw°»Uřk¹±W„xVx¯¦U°ƒzţW™w@°ÇVÑk¯@„y°aš£š@šmšnl¼„ašÝÝakwUƒ±aĉImlĵn@ƒm@kkVƒ¯Ñm™ĸ™°x„l™œ@˜ƒXVÞmlÛݙĉUÅ¥mwÅ¥VaUw›™XġċaVůÛŹlwU¯U™ó±™xÛV±¯¯n¯mċƒLmnĊm‚™@™_kJWaXmwUƒĉK™»™@mwX݃UDŽkKÇw™»nƒaUw±škx™K@„Wb„x™„„lVê„lÈIl`@¦ƒŽ@²X¤Wó»™KUșŽ™KkkmVmšUÈóJ@x¯Uk°›„—Iƒƒm„ōƒ¯Vƒxƒk™ŽX¼ƒÒkk±W™wƒnUºVzklVxLǚ@„ƒŽ¯UklVxސV„šJW¦nšmlLówݚ@¤ƒ„bƒ¦„V@VƒV™š±LUxVbU@Vx¯x@²n‚°xn„Wb„b"],encodeOffsets:[[103073,33295]]}},{type:"Feature",id:"5134",properties:{name:"凉山彝族自治州",cp:[101.9641,27.6746],childNum:17},geometry:{type:"Polygon",coordinates:["@@ĶóšKnw°¤ĠIXVƒ¼kź˜Ôk‚„ÈWŽÞȄÜUVšÅš°@šš‚@U¤Vbkb™ĬôLš¼ÈVlm„Llkn@l¤Ub¯L@xÆx„„°mX™mk°b„°°„²™@¥‚™Uwl¥nU@ƒVUkçVnkWċšbĢ@lÈVVk„J„‚V„aV„W@£ƒUƏxW`™£ÈVVÅlWXÛlW°b²la„@°xnÞVÜĠÞ²@l°Þ²ƒèkblŽ@xÈx@Ġènal£nU‚Dz@‚ÞK„nn¤@¼˜°U¼„nV‚šXU‚šbn™ĠUVbUlVš°LX„@lV„èÜUnK@_ƒyXVyUwmIU»Vƒ„kÇ¥šÿkkV¯m±n@ƒn¯ÜanVVƄz@Ž‚bœwÜb„m@wša@kƒmk»@™a@VUUó„w˜@nb°mš„XŽmnVbގVôanwšJ‚ak£lw„˜šLšÅnÝ@wl¥IÇӃ@U™™Lƒ¼kVǃÅó¯kVmmw@ƒn_‚Vn»°LÅ»@éÇçŹīVÇÝ@ÝğU™ƒaVݙ™š¯ķlŭġlƒ@óÞۂċ@¯nkUӄ—m±™IVġUwóKUn±¯—K›w»ƒKݐV„nl@„óxUwţ›£ĉƒUmŗÇ݃K™„ÝUlmKƒ£UVŽ@ÞȎW¦„Ò@Ĭšnny‚@nÒmœVŽ—¼@°Vbl@VlnUUwl™°a@„œ„@llnk°lbnKWĀnŽU„VxUŽ‚²Å‚m¦Û›ÇŚƒaU„Vbš@¦m`móX™Umm™xÅ@±Þn虲™U¯»m™ƒV—m@wƒU@wݚÝmLƒa@„™VÇUk„l°¯„VlkVƒ¦UšmxƒaULUèVx@„kIUxmWV¼¯VmȯšU„nl›È—@m»Å™ƒVWxÅbÅğW@kƒm@kVV¦mlnn@‚ō„l¦Åƙxkœ"],encodeOffsets:[[102466,28756]]}},{type:"Feature",id:"5107",properties:{name:"绵阳市",cp:[104.7327,31.8713],childNum:8},geometry:{type:"Polygon",coordinates:["@@„ńlV°š@Őĵ˜VX»ÆUĊќJ‚w„@È»m»š£°Kšk@ÇnÑƍš@„w°JUwnw@wšbVbš@VlźLUw„aƒ»„aUklyUUVakwWXwWƒUxkLƒmn¥mšwk™˜UX™lJ„w@aƒIk°X„¥Wƒ²l¥šaU™„IlmkklƒÈL@m°nlWU™aW—š@Vƒ„@UaV¥@ašk@Çk¹ƒK@a™K@kƒKkšÇX@VU@kx±V™èkIWwUVUkkKÇ@ƒa@wkml¯@kUWn£Wa„aVwnaV݃w¯@UaWx—n›JńUxUšma@L@„mbUŽU±VVnkxUƙ„VŽm@kkKW°„X@¤ÇUkÆÇnU¦¯ŽkƒmLVwÅK@UóbÇƁVƒ¦™L@‚±êX¦mVޚkÜÝnWU—„›@kšƒŽ¯wķšnš°ÒU„lln@@„ĶmnkĊJ²bV„lxÞb™Þƒbk»™m™n™@™¤¯bƒz@Žl°UÒ¯È@ŽšxŤX„yV¯°¥Uwƒw²XlºVŚ¯¼nx›š@ŽXݏmxnb@n™J@b"],encodeOffsets:[[106448,33694]]}},{type:"Feature",id:"5117",properties:{name:"达州市",cp:[107.6111,31.333],childNum:7},geometry:{type:"Polygon",coordinates:["@@Uxn°‚bnŽlUnÒƃnn@n‚¤„LnxlU„ššV@„Æl„x°XXxl`XœƒVW‚œL˜è—„±nÈbƒŽ°b@š²x°Kܼ°ĉ„V¦lJnU@¦šÞ‚JÞğ„mšLÞ»šxU„lb„VÆann„alŽ„VƍX@lnŎV„mU™maÅXƒa@aWmœ@‚£@wĉJVƒkk‚kkmƒnk@ƒmna@šal„Kš™‚J@Þwm‚ÅŃ@ambkUƒƒ@™™KUġKU@m‚ak¯±ƒ„a@aĉÑÅaVwšXlwƒ±—V¥l@@a™kƒ›@@£šmƒĉÝónWV@ŽnÝÇÇx—UmbƒaVkkk@m„@m°ƒÝýXm›akÅīƒ@@ƒmb@@xmšnbƒ@mxšŽkWL@ƒ¯b@WUXmWœWKkbm@kx™Xmm@LUl„xlêóK™nUš„all™LƒlLó°m¯JVšU„K„„@x˜K²Āô¦l°"],encodeOffsets:[[109519,31917]]}},{type:"Feature",id:"5108",properties:{name:"广元市",cp:[105.6885,32.2284],childNum:5},geometry:{type:"Polygon",coordinates:["@@ÆL„Ċx°»Ŧ¦˜W„™šLȄ@xÞKÜ°ÞnVxÅĀlÒnJ°a@w„V¯l@XWknKnw˜VȚ°XXa˜lX°VI°b„W„nšaššš¥@ƒw°™n@šyÆ@nkÞ@°¯lJn„°IÈl‚UšlXÅ@ķlUV¥VUUÝޙUUƒ@UwƒJUkĉm@ýƒƒlk™WUwVwWJk@VUK™lUkaVƒUƒmLk„m@ƒƒ@Uƒ›Ik`@„™UmlUkV¯ÇXKÝ_mm¯@Uƒ`kwmƒl¼±KV¯—¯Vk±Vk±kzma™KUnDZ™bk¦±ŽX„ƒ¦¯Wl„J@bƒxkIWš—Vlš™xnŽm¦„nlKVwX„WxXŽlxUbVVkzVlƒb„¼ƒbVxŹKUk™@Ua™a@xmxVx¯Iƒx™@ŎmÒ@șl¯L™¤n¼"],encodeOffsets:[[107146,33452]]}},{type:"Feature",id:"5118",properties:{name:"雅安市",cp:[102.6672,29.8938],childNum:8},geometry:{type:"Polygon",coordinates:["@@ln@xšèVInxVKn„‚ĊklxkÜVޚÒnÈm°nxš@š¼ĊLV„nx‚WXblIš`š@nmĉn‚KȄôÅlUÑmU„K²¹@ÇÅVÓůVýÞW„‚UVmX„ÆbnwšKUÿ‚™@UmmIUb¯¥Uwƒ™¯™Çmš™„çmanUm»UUƒl—kƒ¤ƒa¯bV™U_WĕmÇŚ±ĢUlƒUl™ÛVƒçkUƒ@WŽ¯KU™VkUağVmš™aV™WUƒmV»—¯@»m£ƒmÝLŽ±@ÈmVk¤mb@ôƒ¦kVkamL@b°‚@b¯¦ÝVƒn@l„ê™b@º„UĸL°J@zV@nmUƒlaĸÔ@xƒ°VҚ„Ub„‚óĢ„ÒWškV@Ò"],encodeOffsets:[[104727,30797]]}},{type:"Feature",id:"5115",properties:{name:"宜宾市",cp:[104.6558,28.548],childNum:10},geometry:{type:"Polygon",coordinates:["@@VlÈnl‚XnWLX`m„²nV‚@b°xĢçlnšVm‚nn„@@„°‚UzšlV°nޘÒkxl„w„`UnVb„mšL@albÞKÈۚmܼ°@Xǚ@wmW@ńKĊL„lV„šLVŎçÞL²±‚ğkw@Uƒy@¹lKX™lKVa@w™™Č@‚w@a˜ÇU¯n™@@wġak—™aō‚ƒƒK@Å»VakUWmķwkbğ¥mL™akš™@ġރ°¯xVVÞ@VšxVš—VWx„XlxU‚™@k²WVŃULmèULVĊklĠ„VœJVx±nŃ¯¦mwğ@mƒƒlğkkl±@kšUk@¯±Ç™Kƒ—kxl¤b™Imx"],encodeOffsets:[[106099,29279]]}},{type:"Feature",id:"5111",properties:{name:"乐山市",cp:[103.5791,29.1742],childNum:9},geometry:{type:"Polygon",coordinates:["@@kšVŽk„ššÆkšV²UlºÈIlxƒLXèÜlU„„XU‚mkƒbVè„x°@„@¼°Knnn@m˜ÆIUbnJ@bVI°b°±@nK@mVakkƒKl¯nbšmĸ„èl@VnÈl‚UUw„wmwnm°¥„L„™lLnU@Va™ImbkƒmK„ƒƒnk@mƒb™ƒƒLV„JVUUƒ„VnkVmb@a¯JUaÆkk¥„IW¥„Klw—ÑmÝU¯™kVy¯@ƒƒ@mmn™Ukmġè¯w@aU±mnƒW_XKWmkÇmUkóbUÝUanmW™ƒ¯nma—@ƒxVôUV@šb@‚l¼„n@l™b@xƒnÛa›xa@ƒyUÅmUÛbm°@„m‚n²U°ll™ĀȦƒlU„V¼nJVxUz‚W„z@`mL"],encodeOffsets:[[105480,29993]]}},{type:"Feature",id:"5113",properties:{name:"南充市",cp:[106.2048,31.1517],childNum:7},geometry:{type:"Polygon",coordinates:["@@ȲVmšLnblyl²²UUl˜°U°²L‚»„knlx„_VŽ°@nnÞ`WL°ÈUŽVlnkšV@ƒl_œJV„‚@„„n@lƒnKV£™Çšƒ„UV¯šm„@laX˜U„‚UbVx„@VkôJU°Jn™@™‚wUk°wnUƒV_nJmknmm¯Vwk¯ó¥±ÿ—L@wƒƒƒLVU™kU›bX¯mykI@a±Kk¦ULmaXƒƒVm¯ƒK—z±ƒklUIVbÇJšƒkL¯™l™ƒU™ÿ™UƒlUkJƒUmŽUUkVVklKk@@a™U@„™J„²ƒxƒ¦kĬ@¼±ºXnWb—xƒU@xƒx@lšL@b„Llº@șl@bU¦Vbƒ@U„™@X˜‚bVškX¯m@nÇKk„llknƒJVš"],encodeOffsets:[[107989,32282]]}},{type:"Feature",id:"5119",properties:{name:"巴中市",cp:[107.0618,31.9977],childNum:4},geometry:{type:"Polygon",coordinates:["@@V„U„lbkVšŽVLUŽl@XI‚ŽUxVxšXkl„„@þĊnVl„IVx„@VVݚVÞUVU¦kV@ĸWÆô²š@VÞnš@Vaôb²W@‚K@XUmÑUW°¯°Ina@y„_lWn¼lLUbô¼„Kla@™nkUyô—Æx°@šn£™Ý@¥mVkIU¥Ċƒ‚¯Û»¯L±w@™¯a„Ça²m˜ƒ—ç›KX„UW›k_Ww¯WƒwÅk@ƒ™Uƒ™kVmwƒK£@mmmńmÑkVmamnnlmIU`V„m¯xVlx@šmš¯IV‚óIUlƒ@UwVaƒ—VW‚kbƒ@™nU°ƒV™„šÈU¤"],encodeOffsets:[[108957,32569]]}},{type:"Feature",id:"5105",properties:{name:"泸州市",cp:[105.4578,28.493],childNum:5},geometry:{type:"Polygon",coordinates:["@@VVXwVKn„˜wnVƒn„l@b¯xmKUbVn°°X°@blLšènV„@Vn‚l@U„LnmmUna„VV_ĶV@wnJ„„l@@kkKVólaUwnJm„wUlm@ašUaôKVnJWbޚ@VšwVLX¥VVš_Þ`šw„WƒÞŹmmnIn¥Wƒ@k„WV¯@ƒ°kI™ŽƒLk¼Ç@k¤±Xk˜™nmݯUlÅÛKWV¯kƒlUwkLƒÓ™@U—@ƒ‚w@ġXV„˜WX„š@UbVbšV›š_kÇV™lU°lnwŎ¦ÞaƯnmm¯šU„™m¥nkVmkƒl_ó¥¯UÇl¯@™ƒ™L™kƒ`¯ķLUy¯@mw—¼ķ°ġ_řU°mlšnÇVUޚ„@‚ƒš_ƒJUnV‚UXšbl˜Ģb@x@mšV°—È‚b@‚xċ@šš@xUbkLWškL@º„zV‚@lxĠ±²"],encodeOffsets:[[107674,29639]]}},{type:"Feature",id:"5101",properties:{name:"成都市",cp:[103.9526,30.7617],childNum:11},geometry:{type:"Polygon",coordinates:["@@°n°m²°ÜUšw²ŽôVš°ŽVkxÜźUŰČb‚ŽĢlaÈL„»ƒ@k„wVǂ@„ƒnÛƻșUÝ°Kl_„V°Uš`Vbn@VbÈLšaVU@ƨ»V™nIl™šUUa„±lIk±š@VnKmÅ@WaƒK¦™lVōškK™Ý@maXÇmw¯IU‚@kƒVƒwUmVIƒƒƒç—ÿƒU±ŽÅ@¯È@xƒK@wƒLUbÇKō@mÝ£@yóUóóUxkI@WlIUaƒbƒaŽVĀ™LmxÅaWƒUnVƒÝXUþÆ°UÔÈÆ@±ºƒLnVVÒkóÆ"],encodeOffsets:[[105492,31534]]}},{type:"Feature",id:"5120",properties:{name:"资阳市",cp:[104.9744,30.1575],childNum:4},geometry:{type:"Polygon",coordinates:["@@„è„„UJVn„x„U@lV°JnxWÈnbÞ@šŽlLŎ™Ušk‚¥„LXbÆ@nŽmLU‚@zlbXmlnVynL„çšJVb‚UnómUnamU„an¥lKV_²aValWô„n@nƒ‚bVœK°¯VblW@kkƒlUnlV£°W@w„UXk°KVwƒmVkwVyVI@wkmƒVÅ_Umm@Uÿmbk£™xUaVw±V¼V¤kLWxU@Uk™bƒyƒXšómƒ°V@@zÝÒkKƒn™±U@@_VVkƒÇaVwnLWalm@@kkVVl™¦kIV`±n@w„Kƒƒk²™aƒVUUV¤™nkxmUkVWVnLUbVbƒ`kUU„mLU‚mX@`ÅbǚXbWLXŽ›n"],encodeOffsets:[[106695,31062]]}},{type:"Feature",id:"5104",properties:{name:"攀枝花市",cp:[101.6895,26.7133],childNum:3},geometry:{type:"Polygon",coordinates:["@@„b‚KÞnޙ@x„V@x˜n„Unš°¼šVš±mç²ÝÆ@šwnnšVWŽnôn_@¥‚™UaVƒ„bƙœÈ܎n¥Æ±VUwVƒmXÿmLkal¯km@k›ƒ@ƒ¯bkšVxmVUkk@Ua@¯˜»Un›mс@mz™m@īƒÑX¥Ç@ݙxU¦ƒšÅŽÇUkx@šlb„UWVX„mV@xĵĖ±@@Ž¯xUšÆLnÆm„šx@nXL±lUUVwKWak@WxkbšÞƒŽĉbUn@‚ƒ@@xó¦„Ŏ"],encodeOffsets:[[103602,27816]]}},{type:"Feature",id:"5114",properties:{name:"眉山市",cp:[103.8098,30.0146],childNum:6},geometry:{type:"Polygon",coordinates:["@@„šVx°¦VanJVnš@„b„aVbkJ@XlJVwôôôV@zÞ¤@nƎÈLVa„K@x„L@w°ÇÆ@²„V˜ĀœmWXKWașÆa@_nWVnKVƒlV„_UaVamKXUWwnmmwœÑm£@ynUƒkWƒĉUkWVkkV±çkJmkKƒšƒK¯¦mnnxƒxVxVÇkUmk@ƒçķ™nmak°„LllUb@nmL@‚¯²¯aUJ@amIVaÅJn—m@mm¯L@»ƒŽ¯@ƒwUç„anlVƒWVƒÛkWç„KkwÇJk¹±V™UÅl™™ġV™²ÈƂnXĖV`Uš°a„b„£˜l„kVVn¼mVnbƒè™šÈn°š"],encodeOffsets:[[105683,30685]]}},{type:"Feature",id:"5116",properties:{name:"广安市",cp:[106.6333,30.4376],childNum:5},geometry:{type:"Polygon",coordinates:["@@„VlIV‚„kšVšĀ„Vkš°šlK™„ÈIUaVJlk²„˜y„Ln°„UW„nbVKl¥²L@blJnzW°œalV°Inô¯‚K„kšKkkƒbV™šmôLkéƒwVk@KnnšWlwn@laXL›ŽnXVW@X°a@„XKl™nw„@man™@w‚@na@„„@ƒw™ĕġġ™wUkUWb@mk@™¦ƒ¥mUÛb±yÅn@bml@kV@„ƒlknVbmVnlmš—bÇk¯bWyk@V_UamJ@I—@WaƒVXamIVWkUkbVaƒUUxƒ@VnkVU¼›bkKUxmK™„@WšƒxnV@n"],encodeOffsets:[[108518,31208]]}},{type:"Feature",id:"5106",properties:{name:"德阳市",cp:[104.48,31.1133],childNum:6},geometry:{type:"Polygon",coordinates:["@@nUW¥²é@šK„¥‚UÈÅôa@VÆLUxnKl„°V¥ÈmlÅÈV@£ƒWX¯lLln@UšƒVÅlwUm²U‚VVna@ƒ@KnbV™VwƃœI˜mXwWƒkIVwÝĕVUa™IƒèmKUzkmWnka@y™@l²kJƒ²Vb™VkšmJUšƧ¼@UV™bÇKUam@Ua™_¯VƒUk`¯LVÞǚżm܃„@Uȃx@l„ƒ¼ÇKkbWŽœšVxUbƦnxƦĊV"],encodeOffsets:[[106594,32457]]}},{type:"Feature",id:"5110",properties:{name:"内江市",cp:[104.8535,29.6136],childNum:4},geometry:{type:"Polygon",coordinates:["@@²èlUUllXĊVX„„lmV@zn¤›ÒnxmnXxlUnVlwšmU£VV„Ušbl±„„ƒL@x²mU_lJš¥UklU@ln@‚kXbmKUxÈbl„UU@`V@š²„mlLÞÑ@yU@„¯ôn‚™„W„zšaVlV@XwlKU£‚»—aVaUwm@mwUVUwkƒlVDzLlƒ„KV™m_@ykUmƒ@mU™çkKmxkIU‚Ý„@LUJ@n±„kº‚LXb™¼@mmIXa™@mamnkW™ƒKUƒƒxƒ_U`UklwUw™mUbƒV™²ƒakbƒmkn@`„UmҙšVxUb™I™`UƒaÝÈ"],encodeOffsets:[[106774,30342]]}},{type:"Feature",id:"5109",properties:{name:"遂宁市",cp:[105.5347,30.6683],childNum:4},geometry:{type:"Polygon",coordinates:["@@ÞĖUxlJX„Vb°@„xUÞmbUxƒbXbm¤VX@lk°ln@x„bÈ@lLVlVUXxlJšç²UlwV@@UÈWl™„L„w@w„V˜wXaWm²¹@»lī„¥„wƒ±šI@ƒšV@bl@kLUllUVVn@mmU„wX™ċbVb@VUkbmamšW@kƒa@™™k@ƒlaUa™@¯b@šmmwó@@lkXUa¯°›LU‚am„m@óƒkXUb±bU`kLm¦ƒbnVmbnVmô"],encodeOffsets:[[107595,31270]]}},{type:"Feature",id:"5103",properties:{name:"自贡市",cp:[104.6667,29.2786],childNum:3},geometry:{type:"Polygon",coordinates:["@@lIÞDŽbVŽš_šJVaUwš™nуV@_lm„nla„bš±„UVašnVxkxVlV_„`„wV„„LšlXnmnbš@WbnJ@nš»WaKl¹²ƒ@mVI@KރVlJnw@aW¯¯¯UmVanL°w@aƒk„mmU—xmƒULWxUUÝKōèU™KUƒƒkĉKƒL@ÆnX@x™‚Wȯ@Û»™nÇÜÝLka@b™KƒnUaVmƒ_ƒxkƒLX¦ƒJl¦ÅlVb°I@bnaUŽmlƒUV„UVƒIUŽ„Kš„„a@nml„„ƒŽnLl„našJUbV@"],encodeOffsets:[[106752,30347]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/tai_wan_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"7100",properties:{name:"台湾",cp:[121.0295,23.6082],childNum:1},geometry:{type:"Polygon",coordinates:["@@\\sŽ@pS}aekgKSu™SsMß`¡CqZ·be@Q^o@‹gieMp‹‰]}•}Ľc_Kk…{™ù“A¡r‰[uom@эĥJiq©mʼnq¯Bq]ÙYgSåk_gwU­isTE…“‘ĕiqiUEkue_‰OSsZ‹aWKo¡­q“ycY£w}‹ĩ™ĕS§Z©S™N¥SyLÑ¡±Ks^IY‰PdƒY[Uo†Fp}´\\¬\\j]ˆe܍ò‹¤¡–ā a\\bn™U㺹Ìs¼j®[cíȈEŽĝĆ`ļf¶Š®K|VØDdKGpVnU‚FjpH—F`†B’[pMºxÖjbpÎxp€¬‚|ΟÜÒCŠ²®‚ÜAp„ZG~€Šd˜ÞàV¨|¸€`|Œ²tx~\\~|dFf^zG€ĄŚhœdL\\hĸž¼†ŠOªP®lV`p\\]Xpll˜æ¤œCpQ|oF}fMRi†NSon_²qämœM„NM‹\\•"],encodeOffsets:[[124853,25650]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/tian_jin_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"120225",properties:{name:"蓟县",cp:[117.4672,40.004],childNum:1},geometry:{type:"Polygon",coordinates:["@@EUDAEI@WNMNCBFAHFFNACDJDPBD@@GD@DIFFHEFGDBDEQOFG@EI_KG@OcJQM]RMEKBGPG@[LaCIICBWKCEEG@WBQHCDFD@HSLEJI@IHWECFGAAEKCGDBFCBSBIDCKKHEADMJMFABKOKEQAA@IEEG@GIQAEK@OZEESMOL“lu@SLUTYFQCMG@@SQUAYKAACA@IB@BDB@B@DC@@BGAEFAA@BEGKJCC@AGAIHA@@JC@QEIP@@A@EGIDC@O@C@@@@CJCWKABFLBBEBSQGBAAMIEM@AKBcJEN@BEBCFMAEFEF@J@BG@BFABECKFG@AFQ@@F@BEB@@A@@AAAKAE@GFGDECEFEECBKIKDELDFEDYH@EIACDCHKBEB@BAAC@ADBHABKJIAIJICEDGDCD@@A@A@DHCHJHDFEFGBKRKBGIK@GIMHSBCH_BOJECCJCFKKMD@DNJEDEGC@OJCJHRUL@HRJ@H[DCNKDZHCTFDHCFFKR`TANVDFZRDLFARB@HPAPG`ILAR@TERNDFNHDLCLDDCXDYbHF@FEB@LDDVE@JPNfXPINCVDJJD@NJPAJHLXHDNANHhB@DPNLRMTBFRBHHr@`NBFEBOCCBIAQJDHCHLHFA@HSDCRLFTB@HEFLNF@PELBDJALFLTC@EPFLLP@tUHQJDfIHGTB^JTCPDLKAIBATFPADIEGECEMJ@JIAIHGECFEAGDI\\SPOXAFCL@BQTQBBTMZECYGAHA@GJAE@HCAEME@IECFKJADDBABLTHHG@ILEAMNDJCDHEBF@@JNFJELDFKTOT@JETBFFHBHEHKI@@IJEJ@XKEOUMS@AF@CEB"],encodeOffsets:[[120575,41009]]}},{type:"Feature",id:"120114",properties:{name:"武清区",cp:[117.0621,39.4121],childNum:1},geometry:{type:"Polygon",coordinates:["@@FWôµ@IFCLIB@EHNBp]AGEAKAEDMGZKFGBGME@ILGP@HEFB@BXMEAHUGC@IHCLOD@X[NWHWPKAEF[@EKIOL@EKGBNMJ@EIEHKBIC@BAKMIACCFQZCF]DB@ERAKADIHGEIBCGIIECFaGLZO@EFCNGAGDGAKL@BMG@IE@ADSDEH[JGC@CGA@BMDeK@EIACFE@@GG@FIAMM@CCGC@EM@ADE@CFMAAGHBDKIEAJG@DOGCDEKAGIS@KFCHKAEHIE]BeKNO[IFIOELC@A]GMBKVYCDDgGAICARc@MW@AQE@DGI@@AQ@@BKBAIQQYEFW@CEADIGGBCEIiMEMF_LGEKMBBDWEBGRC@E_CHYGCH_IAED@FFBQh@FGJaJ}AHRAREF@bE\\C@CT`FHC@\\BBF@BID@HGDDJ@@FAHKBARECKDAZBJIVNHCTA@EREAMLHDAFFBVFFC@RNRETHD@FOJMACH@CAB@P@DF@@FGDWE@FFSIEMKQDYCCHKb^JADOCIDGNDBdBCFJB@EC\\A@BJEA@JAAAD@HHD@LFBCFF@BERDHNhZQHMBGHOACCEBWEGD@PSJKCGEUD@CINLFGHE@AJK@HDABBHTB@F`DBFLBBHEDARCFG@ABJBAPVFE^FBGLGCFG_BMLEXGAAFE@@JNRVJHFALFBEHQJCTbNDHCF@PlFLJSXCHFHfVBTNJ\\BPJXC^FAVNFCHFB@FFH@JF@\\ABCFD\\BDMCAAJKQBGAILOEGHILECQLWFENJHADC@QxNHFJNLDFA@CBA@D˜UÂmR@FBL@BD"],encodeOffsets:[[119959,40574]]}},{type:"Feature",id:"120115",properties:{name:"宝坻区",cp:[117.4274,39.5913],childNum:1},geometry:{type:"Polygon",coordinates:["@@TZbB@JHD@DODCLM@AP@LL@BNH@ETFN@`E@DNG@CHLBCJA@AICFKDDBKA@\\N@AFNAGRBFjFFFL@DHLBLFQPcXAZMJ]GAVHAIZJFNE@JpDRRDCLFDGXA@EFF@CFFPDfEBDB@DCHCFCJDJIJBLI@I@CB@@ADBB@FALADGDC@@H@BB@FZGFCCE@@FMLALJDAFFFEFDFCB@@AHCF@L@@BBB@BB@FC@E@@R@BEL@HEFD@G@AH@AIB@@@FEFEBALDDEFAFO^IF@JCBBFPNJJ@D@PRDCEKBAXL@BIFD@T@JE@BHHJORFDI@@B@JGH@@B@BDDLIFFHCD@D@DEE@BAAAB@DAF@B@H@NGLJLMRDNMfGIEPMI@GDAKK@KIDIJ@GE@CFDN@FE@GFEPGV@TCDFKHBBF@RW@DD@@ID@TJFKIKLI@EP@IGBCLAEKLEN@KSHIGYACSD@SEAMBBMGEBMQBCMIGKFB[D@HDLPHDBC@IFITDLG@IIIFGVBNJDLN@VIRI@YIAIHIC@CLKZCBEE@JECEIHEAKGDGECBGEEM@@DA@CCCBBEGA[GEDBBoNAAH]MKiIAWKQoIIPMFQAEEDMH@FMSUYIeF@EK@BIOEKJEBICFKaKPFAFSE@LWCCFMHDDEKESBOGBKIEIODLG@CCDEQCEDWEMDIEIB@EHGEEDAEAa@@HqDEJGF[AECCFa@WCEIKAAEQB@FCAE^YDERDDJBLNABD@AJGLJF@FNIAMLH@FPKLJ@FE\\BFOLGXMXW\\C@KPGD@JHDGVFBWN@AEAGFO@KH@JNFAHEHYLNHFCLBFBBHo^MAFGA@KJED@Jó¶EX"],encodeOffsets:[[119959,40574]]}},{type:"Feature",id:"120223",properties:{name:"静海县",cp:[116.9824,38.8312],childNum:1},geometry:{type:"Polygon",coordinates:["@@NGFMDATCNDR@CCbINEHNJA@C\\EEGVE@IhE–[˜w”epc¢·²›^QEKIEKIgiQDkehY£uSDBMkUDOJDHC@GF@CAFBFEN@C‹Q@BeP@@G@HD@@MHQKi@[IGCOCESE@GMA_OcCGDu`aˆ@VZzKDkJBLNXGDqKEWE@cFEFA@ƒISIi@@KMABJGBcMuFEzGVH\\ATSEUBeALCEMG@CEBUHUCGXaBPtUBBFIBFTDFF@DDKBFNGBJPHXDDMDCLJ^mBIHIL@LR\\@LCR[@@z@NFD@LLBNb@RHDBNTPT\\F@BJF@BXCFBHHBDLFB@HODADE@@JHVXCPDHCFTLBBFNCDCCCU@@GAABEHHZHBCAEdEjFDD@GfD@DXFCHF@ERFDLBH@"],encodeOffsets:[[119688,40010]]}},{type:"Feature",id:"120221",properties:{name:"宁河县",cp:[117.6801,39.3853],childNum:1},geometry:{type:"Polygon",coordinates:["@@BFLBFJXDb@DEFD\\BHEFIrC@Gb@FBCBFFGH@FJAJFNCXFFCRDCFDDH@CKJPJFALPHTALFCFGCENDDKXF@ETEBO‚bLELJDFALIPFAJL@@FfEZJTVENG@CNFFRBNEJOpJLRBXjJNLG^BBpMAAFC\\HHBAFDADDB@@CN@FFAHFDCHLHFBJGFCFUNKJJTD\\XUXF\\^F@DDDQXXBRLRCBDFEVCDLVDpUl@LEDJHAPRFGL@CETGPBTCDDVI@CFF@GFDCCVGLKEK[Y@MECISG@BKNSCGCKWEAaEBEKNGFSECO@GGM@GYI@DÅCMLHPTF@DJHAVVNKEGDETJ^[TJNNd@NOAMFYJ@@GFANDPEJB^aOadSTQSI@MHBDIEOKCG@EEFCKCqXO@@DMFENCDDHCCGJ]AKFoDaGGHYFDHKJiCMFGC@EQ@AEHGAC@IEAATKOHGIC@IXIFEoƒGE[JCFCDHNmRADFZMF[EEBMO{GU@AOW@@]ZeHBDEHBKEfQkuIWBs‡@EC@d[@[^EDMTKCEEcI@cDAB@FCBCACmOCG{PYHeBgPwPFDDALFFFCHQGSD@BHFAR[TaFYXMASUiGFL@DQNCJI@@D@PLDN`ETEFIGMCGBCE‘~CAIFDPEHGEQPHJADFJGHCJLB"],encodeOffsets:[[120145,40295]]}},{type:"Feature",id:"120109",properties:{name:"大港区",cp:[117.3875,38.757],childNum:1},geometry:{type:"Polygon",coordinates:["@@JFFL°_`ONJKDDFIFZN xlb~yFVNRŒrdJGzDPVFBCTNND\\UR@E`F@@Ip@IWGUoawOEE@ÏDgK{İEEMFëC—b…™@—KwOCDHHKBDJCDEEEAGHOABFABMCgDLSQ@CFEB‰MgYIDQINE@AUSwSAdYEHQMEyK[KI@GRMLE@@OqOoBOnpJ@BmEAFHL^FDB[C@BBDVFAHFJENB@sNEjQAMYsUgCSBGDJH@\\LjGR@NC@@G@HO@AfR@DŒM@EFEADBE@@HGDICCPlVANTC¤vgZlfRChjLJ"],encodeOffsets:[[120065,39771]]}},{type:"Feature",id:"120107",properties:{name:"塘沽区",cp:[117.6801,38.9987],childNum:1},geometry:{type:"Polygon",coordinates:["@@|ODHnPBDADEDA@CB@ddJFFLDNSFC\\]\\@@cFDˆ@nACOMW@M@ITURBRZNHNWRQšoO•j½f‡cqŸAqeiDÿÍyÓįFL|Ch@ÐFFxPpbHVJXo@@JCTR^BPABQA]^MB@bE@@FQBFVJRH@FXtPNZSBAja@@NƒDTŽLJrQTHFXZFB`"],encodeOffsets:[[120391,40118]]}},{type:"Feature",id:"120111",properties:{name:"西青区",cp:[117.1829,39.0022],childNum:1},geometry:{type:"Polygon",coordinates:["@@@LHAHRHATh`LHNHDG`HDGZ`D@FQDAHXFACNAFLVRTBFOfHDCVBFQH@HSXHEPFB@LDBF[bDbLFKJBFLADBDjLvCPEI]FGEIGCBEUSjcFiBIVWfaHCjN^HtwBBFGPBJGjFBEGECGDONMFAP]TDHQOWCMGAMHKIJEIGQ]aDlUG]VGEGDC„{PEbBZmE@@GH@BCA@FMQCFMYMJECELCMI_P¯`]R±œ¡¸od“f—x•\\gF@JUFFH[F@DIBGMMFaJDDQ@MCSDCBENMH"],encodeOffsets:[[119688,40010]]}},{type:"Feature",id:"120113",properties:{name:"北辰区",cp:[117.1761,39.2548],childNum:1},geometry:{type:"Polygon",coordinates:["@@ROHFFGCOJEDB’}DFHANDJHFEFSM_KC@O@CJ@DIRM@CEKKA…L…FKACHoLSJSIBETDJaEIIE]E]K[MYUYQILC@GF[MGNKEK@A@BCWECAIFEFYAGFOMI[OFuDiKACBCEKIAELaKaCE\\CA@KEAFOWGGTG@ERUACDeGEPSAUQKHE`FNjNFJADHHCJFB@DEXZFRRBJLA@AR@@BJ@CHF@BRX@@NQdDBBJhHCCZDLUNA^H@BKDPFEJ\\JMPfL^AJFFGLBDGLET@HJLBCFHDCPH@BIJFCLGABHNBDEF@BCN@@FHDDDN@BNEJH@@HF@DEJB@FfLNC@AHB@DHD\\IFGTCBCF@@JNH@ALKHBHCHBDMFEP@KYbHDEJF"],encodeOffsets:[[120139,40273]]}},{type:"Feature",id:"120110",properties:{name:"东丽区",cp:[117.4013,39.1223],childNum:1},geometry:{type:"Polygon",coordinates:["@@ZV\\N^L^FJFFJIbSCAFTJTIpKDGLB†E†KLBjHTVNBZWbE\\SBQGE@ATCRHDGEEKECBECxOhOfAZGA_YEEWSGqRKIS„C@Mb@BiTAMYsOEWG@IQEURA@EF@@acUOXQRYCUDCHDTEF[SUEgAYDcVGJM`iAWDWLQRMHUHgDsDBLHJFCFDFGHBFFVEAGHCJN@RJF‡PIhBD\\FENCPWA@LFBAFHBEJUEARCDIAEDQBRNa^"],encodeOffsets:[[120048,40134]]}},{type:"Feature",id:"120108",properties:{name:"汉沽区",cp:[117.8888,39.2191],childNum:1},geometry:{type:"Polygon",coordinates:["@@LMEI\\MTABKN@FCDMH@COAcH[AoēA™M¡Wa[Meq™pQRMXMGQYQASV@J@NNXDPmBAtJXlveRLFGACFGAYf@^X@BPV@|HNPFA\\FNEEYBCnQGMDCDE\\IHFp„EFWJ@JJDGHLPBSFB@JBDGHBFR@@FHDNEjDLICGZEHGbHpCLE^BHIDDCGDCFMNE@CP@rWLDEDFFH@"],encodeOffsets:[[120859,40235]]}},{type:"Feature",id:"120112",properties:{name:"津南区",cp:[117.3958,38.9603],childNum:1},geometry:{type:"Polygon",coordinates:["@@TLv@CNHFFBHGZFETNPhCVGNGRQXKXCjBN_HIdUZChBVF\\TFECSDGVCZDRQPWdVNA^]RBBAAOQ]DSE@F_Q@[VMCSMADUECOHycI‹qMQEU}zkaŸwENRDENB@ADG@@HF@YnaAOFƒ|CDFHUHH^kVbCR^JHIFLJNGHBDNPXGRSCO^EBMNCPDHHFAFiEIHOAEH"],encodeOffsets:[[120045,39982]]}},{type:"Feature",id:"120103",properties:{name:"河西区",cp:[117.2365,39.0804],childNum:1},geometry:{type:"Polygon",coordinates:["@@d@hZNFdcLYXKRCtCMOFSYEGHEAGEDMu@SKAAsx]GMTGt"],encodeOffsets:[[119992,40041]]}},{type:"Feature",id:"120102",properties:{name:"河东区",cp:[117.2571,39.1209],childNum:1},geometry:{type:"Polygon",coordinates:["@@ZBVFFIGABEEA@KXBDOFM[EACJgˆOIE@QIMGDBHUFEEGAEHECEDGIAKQDWLKZcdQPEP@FOFBJTJ@HNORJf@DBCN"],encodeOffsets:[[120063,40098]]}},{type:"Feature",id:"120104",properties:{name:"南开区",cp:[117.1527,39.1065],childNum:1},geometry:{type:"Polygon",coordinates:["@@NMVDCG\\E^B@HlB@YEDS@C…HsNSiMGDebUXAJEjidVTAFHDFJ"],encodeOffsets:[[119940,40093]]}},{type:"Feature",id:"120105",properties:{name:"河北区",cp:[117.2145,39.1615],childNum:1},geometry:{type:"Polygon",coordinates:["@@DBXFADB@L@LFHM\\NHED@JKZRb]QMRAFCJBDCBQYADMCAe@QIMP@GSIAIPE@E[EGH@ZEF]^HJAXK@KF"],encodeOffsets:[[119980,40125]]}},{type:"Feature",id:"120106",properties:{name:"红桥区",cp:[117.1596,39.1663],childNum:1},geometry:{type:"Polygon",coordinates:["@@J\\PNHEZBFEJELEL@BWGI^]FEkA@G]A[FDHUCMNEHJ^"],encodeOffsets:[[119942,40112]]}},{type:"Feature",id:"120101",properties:{name:"和平区",cp:[117.2008,39.1189],childNum:1},geometry:{type:"Polygon",coordinates:["@@D†T@FCHG\\FFOROMEgYc@"],encodeOffsets:[[119992,40041]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/world_geo",[],function(){return{type:"FeatureCollection",offset:{x:170,y:90},features:[{type:"Feature",id:"AFG",properties:{name:"Afghanistan"},geometry:{type:"Polygon",coordinates:["@@ࡪ͇وŐǬϠڐŶӂʮǚڦ۾njƀ̚ІɣʪҴMوǯʲĹ،˒˰Nj˖ϪԈiżŬĘͺβ̈Ҕȏĝʱʪ¡ý۷ͪ˟̊ǰώĊԼϖׂ×ࢀAƬʋӧĥяƹ७ĭࣗǭӫλȤΣĪллΛ–͑ɳ̡ߛ€ͦ։՗ɅΥԕ²ԋ͡ɿ̳þٝŋğɻسDҵӇ‡܍થΓבôǝȁԇņ࠿űටіހހåզُƚßՔ˟ڢάҢιŮɲؒ΂ਸ"],encodeOffsets:[[62680,36506]]}},{type:"Feature",id:"AGO",properties:{name:"Angola"},geometry:{type:"MultiPolygon",coordinates:[["@@ȸصʌԋȘ˕͐ѯ֊æˤŠҬşŲɀɂӨԶ®ƤіHñ̡৴RfՉǞ͕ūԑÖԫ˪̷­ৃȼüκsԴŴϦ¹ĘʹĩСƨϿů̿î́ყZᦵ֤ۋպԽ໳΁᎝Š׋Ж₭—ŵÏԃϞկ~ԉƝЙDžÿՈŜ݊̂ޒªΰ˚ݶȨΆӘռːϐĘج«ӊʣ̜ɡԚȵԎ®Ǩʶͬʭ߼ǣ֚сՐĄǎΌŔʒg̎ĸៜ["],["@@ɉėɣلͼδʪƘ̀˽̩ǯƍɍλ"]],encodeOffsets:[[[16719,-6018]],[[12736,-5820]]]}},{type:"Feature",id:"ALB",properties:{name:"Albania"},geometry:{type:"Polygon",coordinates:["@@Ń˷ŢέΒȳiə˗ŧ»˙ϷСƛÐgȂү˰ñАîֶŖʼƗƂÉˌθаÂƿɨôǴɥȪďȨ̂"],encodeOffsets:[[21085,42860]]}},{type:"Feature",id:"ARE",properties:{name:"United Arab Emirates"},geometry:{type:"Polygon",coordinates:["@@Ƭ¤ŒɱڂƂ۞uԖ{ֺ֪ظՠՎԮdž˹ŖڑѕGçճƪŝϝǑE΅ʓΏuͷǝDZᡋъ͏࡚Ț"],encodeOffsets:[[52818,24828]]}},{type:"Feature",id:"ARG",properties:{name:"Argentina"},geometry:{type:"MultiPolygon",coordinates:[["@@ߗ§ѓ̔ԑx࣑@Aሞ͒ϵрؿનԋ୲ȿϙп"],["@@Ӵ؇͠ڰॠ“ƊǷ໶ോۊŷਆاࡾ͡Ŧχࠡ౧ࡒɭ़ŷڔƈނ٢ƎݐжLjфӝiڣۻҩ֟΁ॅࠃ૭ଧȽڥɣࡹT࠷ǽȇÝիËѫ੨ܙŗ׃Հν§Ч߯ઁఛ҉။ǩउĎǰԅǣػƺщԋ̏ࡱř̪͕߱ɗŜ࠳֨ʧҠˆʢѧޛʻڭԹūࡋȣ҇ߏEڃљʋؿؙࠞߦǝ˿ݭ঳Ӄձটލͧ΅Ͽ˔ࢍ֔ӡΟ¨ީƀ᎓ŒΑӪhؾ֓Ą̃̏óࢺ٤φˈՒĭьѾܔ̬૘ěӲξDŽę̈́ϵǚˢΜϛ͈ȝॺ͸Ǣƙ਀ȠࡲɤݢԊ̨ʭࠐEޚَոo۰ӒࠎDޜɓƶϭฐԬࡺÿࠀ̜ބռ߂צԺʥ͢Ǭ˔ඔࣶд̀ࢎĹɂ۬ݺશȱ"]],encodeOffsets:[[[-67072,-56524]],[[-66524,-22605]]]}},{type:"Feature",id:"ARM",properties:{name:"Armenia"},geometry:{type:"Polygon",coordinates:["@@୞ƀǨə͌ƣǛɁ҄˽ʁˋΦɫϘƏl׋̣}΃ӢHżχCʝɤǩuͧʖرȼĄФƛ̒"],encodeOffsets:[[44629,42079]]}},{type:"Feature",id:"ATF",properties:{name:"French Southern and Antarctic Lands"},geometry:{type:"Polygon",coordinates:["@@ը˃ߐĿˆDžɽϣಇÃq҂ŮΎÊǢ"],encodeOffsets:[[70590,-49792]]}},{type:"Feature",id:"AUS",properties:{name:"Australia"},geometry:{type:"MultiPolygon",coordinates:[["@@ߺ́ҜŘپNJԎÉÐঽ˽́ēگ̉ɰ׍בǧ®ԫ€ԭܘŗֈӝܸtϬռõ"],["@@̢ڇբ̈́˦ΡЖ͟đϋǴܛŸнɄĹɬܕąѥ˖֭࣬ѭצЋ֞λŋȯӔՃࣧ͜ͲȂ;ηȴźƢࢹ׬ԩϸ͋ڀڹʀڭtӏËԳА܋µݓơϵɩݡjӕǕ׻χއثЭ̫ٱ˫гʝܧ͕нɅػʼnׁªˇӕ̇व‰ޡ·ϫ͙ԕέ۟ψԥƪżѬҝǃ݁؉ܩɪӉƄӑÔ߿ʐիԮƻْțьЭ;߱ĸˢРȯزЧ׉ݝƷѮҬŶӞ͘ЬãجہܑԿ˽͏ڛٽΊ~ҀԿ،ѹ̀ǂȘઃԚןz߯Цຓāછ̝ख़˫ߡÈࢻљܯȗljѱ̳Ϳ܉qՅõݑƶ׿ğֽԁ҃ʕœуʁЗˋؕ֛Bࢽ՜ҋDŽlӖкŘƚȒ‡̠ĺאģӼѻࡖƏӒ˜ӎͭնsʚϋͰĽڄӓڔřΪτε˳ެиʑʞ͗aјеڎă˄țʦĠӠǢȸŘрęӮΎ؀Úٕ΢׀ۀˬЦΪٜ̰ϤàɴĻڎ̺ԚĤŶȀɞüҬoࢨʖҚώɊ҆ӲѐœͲvҘט܎ΠܩΦǚ̗Ј˂ТψǻĸٖҠаȮͨцƜ`ɼτĭdɂτŦОŔبϫҲӽՂMՖÿDZҦДڪϜɘſȾκӒԘ̒јıۺǂeі؛ˢ҂Ū֎ȻҀ·ۼɋʈĐԶʵӬʊ͂ñȠNJϬеɡ͉҇ͻ˿ƒĮͱʙп̗ЭÔʁڜҫ٨ˏѠ́؈ӻʂBѰɍŶʷߤ˵ֈ˼ǐҊǠόľҤʰڞŝОÔʔīӔŌنLjǠŽˬȮѾdžҦtʈ̸̾ʂЩÎՃȾķ˜Λ̨ёÚӇ‡̥"]],encodeOffsets:[[[148888,-41771]],[[147008,-14093]]]}},{type:"Feature",id:"AUT",properties:{name:"Austria"},geometry:{type:"Polygon",coordinates:["@@Û΃ӁCǎǻ˧էLJƗܽsщȏۛÞயɐȉ̊ࠧƣĭDžԗŢѕxϝƶźȴƬʪ²ьɹŤɜݎ•׸ƮЖ}ˀǣþƜšո̠ń̒ϰز˓ӀΆ̐ÚٶʱЂªϰǁãŃČ̅"],encodeOffsets:[[17388,49279]]}},{type:"Feature",id:"AZE",properties:{name:"Azerbaijan"},geometry:{type:"MultiPolygon",coordinates:[["@@ʞɣψDGŻ΄ӡֽŒщϰƃ͆Ǫv"],["@@ϊËƞɈԈͺѴѵђ׭ϺŸʸɧۗãƣٵƟ̭̍ȝvзȽ¥ԻѲ̂дʝʚ̿×যإk׌ϗƐΥɬʂˌ҃˾ǜɂ͋ƤǧɚȶƎضʍҐ¹ŘIJбҔɔŚʀ…׀ԙ"]],encodeOffsets:[[[46083,40694]],[[48511,42210]]]}},{type:"Feature",id:"BDI",properties:{name:"Burundi"},geometry:{type:"Polygon",coordinates:["@@Á০ɃϢԜßʲӎҀŸͧǸȏT˗ȹǭ͛ѫ̧̥΍Ÿ"],encodeOffsets:[[30045,-4607]]}},{type:"Feature",id:"BEL",properties:{name:"Belgium"},geometry:{type:"Polygon",coordinates:["@@؜áުǪՐοҦȝħ֧ɕĝһܿϦћßדІϷͶϷ`ũ̒ڪǔ"],encodeOffsets:[[3395,52579]]}},{type:"Feature",id:"BEN",properties:{name:"Benin"},geometry:{type:"Polygon",coordinates:["@@ۛįȹ׆žኞǛǦЮ̇̌ʱʞņѶ̀ĨǠξЪĀȀʤˮʘ̠F٘ә˩ȎӽǓͷĘɧСԳʵʳǁՉt՗µണ"],encodeOffsets:[[2757,6410]]}},{type:"Feature",id:"BFA",properties:{name:"Burkina Faso"},geometry:{type:"Polygon",coordinates:["@@ֹɐϽ‹̍Ƀϗǰƥ˦ϙǾÅӦɮΤo˴ښۢŬּɲȴОœΚǢŘɎٴϖdžˀ޼ΒҦŢɀLJՠJáСŔϣӀչ€НॺȏmֻǿʣЩÿǟν˿ħ݁lϳâ˓ƉωÖร¡qӉŘم"],encodeOffsets:[[-2895,9874]]}},{type:"Feature",id:"BGD",properties:{name:"Bangladesh"},geometry:{type:"Polygon",coordinates:["@@i׽̉ŶÆگʉѬµєDžКΕӨޟ’ü΋˃ҳΧǠũƵʃĠ͗øŽۖ̅لƜԒԫɤȆ̪Հ̼؅Ѽ֮̔ږεВ£ô׏ߞřު^Ӟƛϯ܅ϕµʷӍҢѥƎ՞ɶFѶ೯"],encodeOffsets:[[94897,22571]]}},{type:"Feature",id:"BGR",properties:{name:"Bulgaria"},geometry:{type:"Polygon",coordinates:["@@ʎΉ͚Ö٦ſ௾«иɌবȜ̩ؒӴĕѥΏ̫׹˔ӏܣŒࡥ˃Uлޅÿס̊ڧɱة|Ñ֊сːƒŢĝĴƘˌ͌ˀСδ÷̬ȸȐ"],encodeOffsets:[[23201,45297]]}},{type:"Feature",id:"BHS",properties:{name:"The Bahamas"},geometry:{type:"MultiPolygon",coordinates:[["@@ȵ£ɇӜ̿ʐǾՔʨ‘ۣ̎Jӥ"],["@@ࣷƅÏ̴Ђäֈ{~ɕ"],["@@ƟׯƷņ`ѮϓͪCĪڐϗ"]],encodeOffsets:[[[-79395,24330]],[[-79687,27218]],[[-78848,27229]]]}},{type:"Feature",id:"BIH",properties:{name:"Bosnia and Herzegovina"},geometry:{type:"Polygon",coordinates:["@@̦FȿσМ͓ūЃȡ™ƽû˙țūҥݓ͈ͅΘ͋Ȅϭ̾ǻʺЩϾǬΒ̞ȕǼǨϾnܠƓ׈\\Ϟȅ"],encodeOffsets:[[19462,45937]]}},{type:"Feature",id:"BLR",properties:{name:"Belarus"},geometry:{type:"Polygon",coordinates:["@@߼Mࣰ̈́ȚӄېːÿϔԜƚ͖ࣘࢮɁŢȻѲĴࠒȧĊЁǷɧՄս΂Ƴ»Ʊ֦Ʃʎɡ͝ǿڳˆljÿȠ˧ȸ՝ܝ¹ʵȁÃхͭĆݷ¡əȞ̿ƥ́ŨڍjफȬࡕàٱmҡɩГeϐʷϴԌǢLͰɷ͌™ϊ"],encodeOffsets:[[24048,55207]]}},{type:"Feature",id:"BLZ",properties:{name:"Belize"},geometry:{type:"Polygon",coordinates:["@@OŮĸžƴı̞ԔDŽZHūDŽGaɭƋεôŻĕ̝ÀăīщǓɟƱǓ̅ʣ@àॆPژ"],encodeOffsets:[[-91282,18236]]}},{type:"Feature",id:"BMU",properties:{name:"Bermuda"},geometry:{type:"Polygon",coordinates:["@@OEMA]NOGNG\\Q^McMOI_OK@CQSGa@WNLVWHFLJXVFGJ`ZRTDLeeWKIHGIK@@[MQNi`]VDTBHCJAPBJLVFjT^LV\\RJZRn^RH`TfJjZHHOTTFJP_NOX[EYQQKMEJOLANJH@HQHAARF@ZEPS[U_IcRQXE@EEKKOCGGCQCOGISKYGUC"],encodeOffsets:[[-66334,33083]]}},{type:"Feature",id:"BOL",properties:{name:"Bolivia"},geometry:{type:"Polygon",coordinates:["@@य़”͟گӳ؈વȲ۫ݹ؅ŗ͡୆ҋऺˆ߾ѳ΢ŏ؆ЫֲՌ࣢αۺȖ˰ƭ̶͠рh܎¤נǸ˶ܩഠزíѠnȈʪ݀;Ѷ͂સƚęؽļ͓ãࣰ֛ݫऴƑ̻ͦ֨ǕΐʑՈTӦʟšӟǐʕZγʓa͒এྖ“ūӟĜͧҞɽȤԹƫڋɯρĄӏʿǥaʶ޳јޭ^ัʓЕ݋sҋͥ৕ƉǸ"],encodeOffsets:[[-64354,-22563]]}},{type:"Feature",id:"BRA",properties:{name:"Brazil"},geometry:{type:"Polygon",coordinates:["@@૮ନॆࠄ֠΂ۼҪjڤуӞеLJǒӜŖӼBҦ̡ƴ̿Ƌ̻œį͔ýޔƿʤ֥ɪ΃ǏࢱLjÈଜʝҴˀǦăӐɰςƬڌȣԺҝɾěͨŬӠྕ”͑ঐʔbYδǏʖ™ӠӥʠՇSΏʒ֧ǖ̼ͥळƒ࣯ݬä֜Ļ͔Ěؾષƙѵ́ܿͽȇʩџmرîӃƟϡĪÈ౨ۏӷݏv҄ͅ֏¶DzΰұԞΓݴɜƶA΢ԖʎċҔɊ̈Ôϼ०ֲێNJŔŴݴŸϚᘰpθſӔύ̬LؐӀƒǚē†͐ӯĔYՀ࿖k˦̂ɸˉǐӷǂļҨѻٸÆnjʲشȞΊƐĮΤ׸ʆ¯Ǯ܅ðśՊ’֞ϓɒǀþجŅڜȿʐȤ؀žल̮͎̾ŏʂѪšȜȗʼnσ̀ŵȖϷɷ̏ƅ܏ɌыÔϳԬϿЮ¥Ģǒˆ˜ϠƦ˚ɢҬíȲŠҚçøǢƗǘĎʐͺõЈĒӔDZξǥʺɪȊ•ŘɿДÒ͒͊ʴؤӼޒ˺¢ȺҫҼ฽҈Ƒxׅمەʾʩ๤ƁŠࡃٔր੐̟ඊԡШӱƏҫ঎ʶ࿐ѹఴŽఔ۝੸व٪ʏܖ‘̦˅˸੭Ɣԗͯ൹ёշஅୡՙोثܯȿgɻءÒ༽ɹಓęօˇͧƫ૱࡛઱ƛࢁڹηȟԋ࣯Fೕ͓סύवʗ঩ڝ܅࠯ũطƔҫƽࡓȏЧחҥट๕݉ڗ֯Ͻϥߛ։ӑɷӈψЊӟֲڇҬࡹՠ̹{ࡅٰձę"], +encodeOffsets:[[-59008,-30941]]}},{type:"Feature",id:"BRN",properties:{name:"Brunei"},geometry:{type:"Polygon",coordinates:["@@ͬ̾܎Ң›Я·՛Б€ǭ˹ϥѦ"],encodeOffsets:[[116945,4635]]}},{type:"Feature",id:"BTN",properties:{name:"Bhutan"},geometry:{type:"Polygon",coordinates:["@@΂ˍÏԩۇ{ۿÈՇſޅ͊kǚ֌زҒɈ׸șѺqπɥ"],encodeOffsets:[[93898,28439]]}},{type:"Feature",id:"BWA",properties:{name:"Botswana"},geometry:{type:"Polygon",coordinates:["@@ǜƭ˄ӡॎइήĝD̑ʚՑٰŹ՚ϝ஑أݭع˩֓ʧ́ҙãƧГďʽ՝țہ¤БɾΟĸХșȵГЉʧпϑ׻đȇ̐üԠӽߚɧŲAរࠤˆ|Ჾش„ಖ͎̎΍՜ͤʮDӂȎưÙ͔ڣ"],encodeOffsets:[[26265,-18980]]}},{type:"Feature",id:"CAF",properties:{name:"Central African Republic"},geometry:{type:"Polygon",coordinates:["@@ۜÚƺɎƔgȾȏ੔͐Τ͠Ѭ̌ĉ̐ʂüߺ½߆ϴ؊ࣺю;ՐƜĪΫӜԿF΃ƋΓÄʻ̆ʍٖοҢͻT˗֠ѫΖεɆԋغͩƊˉˣęաpكĘ̹ïųȱ˕}ͧDzधнϥĎŗÝʥԕطǐؙĊ՗̴ۓ˸҉˓͛яùדգ²֩Ƙԅѻѯޱėʐ›Ϧϧ˔̳Ѡï̠ЇѮæʢċΞÞٴȬƴц࡜"],encodeOffsets:[[15647,7601]]}},{type:"Feature",id:"CAN",properties:{name:"Canada"},geometry:{type:"MultiPolygon",coordinates:[["@@؎œުxЯ΅̵Å੥Φȿˬ͆ʸ̎С"],["@@Хcઝ˂ޯІ̄î૆Ɂ࡮Η|Ʒ"],["@@хŝൡϢʥ̘ݩ̌Ưʈࡻư͕ҜðȚࢨǿԨŵ߄ė˺̃дЋ࠼΍Όҩ"],["@@։ܿո˴֠ǵ̏̉ݚɱϰȴ࠼ʵʹ؛טƞņѿʼԷΝ݉ϝ‹փǂǾیɻńইܯԅ†צЂ߫Ȳࣙ¹࿅~ŹʠԼ̐λɬ۸Ԓࢄ೾Զӎܲ̂϶™Njɫ҅Չ"],["@@@@@@@@߰äʥ॓ܶگͯDԑϪ̵ϮчʾƻτºˎЂŋ"],["@@͡ѳχîəʢ Î͖ʦΆkɈǣ"],["@@ঝҧץnǿɪزϲ଼SiǍ"],["@@ƼυјżӨɗं˽४ʽöЍؤÞ׶˥ݙ˃ಳȬҽϚ࠭ҁ஡ѣ˿Ӯଗăܴдņڌ˺ޔ؈å"],["@@ष¥ȿЪΦҼޖŜپɷXέħřձʛ"],["@@Է̍ଉʬۃğଫϘ݊ʼטζࢼʃԎƯʦDžԠ͍"],["@@G࡭૰ڄ৐եʡح߾֥࢚؈ؖܨ°ईஞÝఔūૼй¼зس҃פ҇ŃУ࿩חୡŻࢃʨʣуߵ۽ʓοই֩ளÇڏΡÇձ঍Ŀਉڻ࣭ु͙ڏ±উంƕϜ޻ϼّ୲ǔ༞εࡀ͋׺Ѕ੆ɳࢸΟ൶µࣴąƍܫʼࡋ،ळనߗ٨˚ҔࡺѭೢףѶഎЀ॒לҮהç֭֘܌৷لলࢤνݾ˫ಾגȘ෸ɫࡸć۠ɚ޴˵ਚӣʮ͙ຄÛ}۷˪ਜ਼ގſ،ӵ௖Ұߦऔ֌ϸٺݣબੳघ৙͵Յ૤Ӂݰӓംɏբˍͬ܃ټŏͶͅÖऻ؍́׽̏൯̗੏ۑ෇ƋᅛǮుPࢇÍ۱׽ੳω௉૗ॵޡ܌Ɛഘૄᄈ۪సČݔЫߍ֟ˊࣟ˜هતп൸ŨࡆीÎ؍ժ̥ਣսᇷԁ࠯ͽय؁ٓ֍܆ฤ۞഍ƒणĹջӆBନύʐ֛ƛ˧ɚٙىʱٹ̕ϡΥŽˏ¥čȹ໽A౥MϛƷࢵ؃Ŀßˍ͝ޗBࠛGϛƅƊǑøʯeďષлࡽſউ҅Ɂ@˷ƂĥŦnĔȂ̎ЂҦʘӺǙܴǵނ࢕ЂľƬūĺɳ@ǛƆ¥ȤǍēɥ€¾ĊȡĊćɚٵːڹ˪ࠑ͘߁̨ݧʃ˝Sਕɔڻʼnࠁʺ࡫Ɔו¾ʻƜƫҤ˳IE͓჏BᮝA᭯@ᡃ@ᠿ@៙@ᢡ@ࠛ@᠁@ᛷ@őF྽ࠜ׵δຽΐҳݖŤԨ੻ΨƧڴ৭؎iѠҲКwՌෙ՘࡭ॠՁ׾ޑϚ֣ΈѿѢࡇ˕ࠇҹݛւדπࠋɸࠟ|JⷎNᷲ༬ȭ೘Й࢘û݆ΖৰˀఢĹ఼τ൘Ⱦ־ΑظȠȊЄ׈ęෆݫ૦֬ŖّਔƐ͆ʖৰ·౼Λዸ̭ୄƛࠖÄଊэ஁зຶǷᗘIJܒƦࣆԋࣴьࡩΦժ˼৾žڦĎڴȩࡊҗरä๢ϛಬƄ௬oĭԺݞƦದ˵KߑՖڠڰuϞࡊ࣑԰কͺäघশ؎ૌƇࡘχଞॅݗЭ༠ǝ"],["@@нϿሎʬୠщॊіސ˟یࠛфΒ׭ࡰ݊Ŭ࠲Ƈश͹ՆࠉʼץථеະЉĝσൡã՚͓˱ູ̯Ƃฃɪঋ»ཅ˷ᒃű๻āҕІଫɮݙģਛږ֔ĚಘƜஈ›રƦྷȞᅗã஗jѷ̴ዎͲಗ[ืɚ۶ـגͮᖬԠ࡬Nj"],["@@݉ևಹך˸Ş૸’ٔȁ"],["@@öɵࢿ|ࣟjࣿőʑ¼ऍѾ˜̠ИÈነěชң"],["@@ڎԽޤڴᒆΈ෺ࢅůջဒʒߒͮሀыୄЏŊν༚Ȑ࢘՗᎐ܸͩ͹ߐ޻໯ϹጘչೲȁீޙೖÇʽכ้ঋਗά೓߲ઙĿŁӕࢪӥଜϯΌɟմࠩ́׿੕ɪᑏڨஎܣ࢔ԕƎ̉ᗱͲᅩӤ৳Ц̌ʂయќ௥Т`ʑᝡƅ܃˾ֆؤ཈dႸņ˫̜̊оચࠊɳϊ͕˾౿Рၳ˺՞ɆࢷԺ݋´ڏ˸҇ʛ຿ŅᵝȈᄫʚഹŴۥ̐࢞Ϧ஝Hˉ࡚٦ݨࡺ΄ᓪɢأի"],["@@৊ǯຄńɖʑ޷Е౜αƱݳ൝͗߳ê׉͎ᐡٮjˎ႖ĽएռসР"],["@@࣓عय़ŒԽ݆`кѮΨ࠰ɮც‡ྈȱళݟ৉Ǎ"],["@@ᕍЙѷςኹѺήΤ׌ؘܰւࠑԦᭊƀ஬ǧᒰ±ࠄʑࣖΝ੍ɃᏝןਫי@ν"],["@@ҙ͙௝Øৱɖ҂Ϛீɨܼ̬̍ˇ"],["@@ٞϵ€љϣس൱đࣗƈjӬ൝ÝÁٮࣜౌ˺ஂµÜŎ"],["@@̙͢ݠƘࢢ™ƪЩԝЋ᭗Žᑯη౩mŅ˜პϊ④ij୯Ʈପࠐ߈ɾᛄ˳๶ӻฺÛறߨޔ̪ࢄĭ˲Џ"],["@@ढ˓ကFܨˡȑ́८ȍՔȧଊ™௬ë೸ǼႊðീÏ࣒ͅȊ΍ԽɟభǷ੽ĸᜱŻႫcഫļᖁ˔̃ҦĹжࡇξ჋ĺঅʼ͂ΈႾÁ"],["@@ŗ٣٩̇޹£༝Ϋ഍ŹଗǼ@@ුؼႮծಆ[ସŬ"],["@@ϣy༽Âɡɼၜ]מƻĵĩ"],["@@༩ʋఝ˔ڼˎ௮Đஈſ˩ʥ"],["@@৽ǏඉBbŤࡴʦҌદǝ"],["@@కǥۃȚέ͂áΎજ‘ӪÅ৐̇ɫ̣"],["@@͜Ε൏Ĥ൩˘ሏŒߺʠ৫ȮÕ͐࿶ŕᗢ̫ٞЍ"],["@@০˕ଽʟ༇ك๥Óდņࣗ΄^̦ڔɢ໡Oए˨ՑϠ׌ώ׊ʲࡴÎοȖዜ¨੶҅මǵ൞ǃڒև"],["@@ᖢßᅮŅ໤ɫ™ɡᏅη᎙ǟݻȉᆬJጡԙേʃ෯ۇႿƓՙǡᡷěୈĿׇƭ۞бߙ˽ಛʃЋ͡୫ʣŞȏ෬lȳᖟԋᔧɴឿŻధĸཟªĿЖ༊Ȑб؆ԢÐᖤγ଩բഹLjڼ͘๰Ȩʄ̊஋͠ΥѠᘞ—ڒĝ಼̪ቃĬ᰽Á๣˸۩ͼগʘȁ˺దLjঘ‚࿲ƌం̺ਬ©ࣤɽٔҒૐƈບĢᢲ–Ҁĝ᝚ƚᆔÁᆒÁ"]],encodeOffsets:[[[-65192,47668]],[[-63289,50284]],[[-126474,49675]],[[-57481,51904]],[[-135895,55337]],[[-81168,63651]],[[-83863,64216]],[[-87205,67234]],[[-77686,68761]],[[-97943,70767]],[[-92720,71166]],[[-116907,74877]],[[-107008,75183]],[[-78172,74858]],[[-88639,74914]],[[-102764,75617]],[[-95433,74519]],[[-123351,73097]],[[-95859,76780]],[[-100864,78562]],[[-110808,78031]],[[-96956,78949]],[[-118987,79509]],[[-96092,79381]],[[-112831,79562]],[[-112295,80489]],[[-98130,79931]],[[-102461,80205]],[[-89108,81572]],[[-70144,85101]]]}},{type:"Feature",id:"CHE",properties:{name:"Switzerland"},geometry:{type:"Polygon",coordinates:["@@ƫŹȳϞƵіwá΅χƙةŀǻ͹ЏơƄһ˵Л¡αǶ˽ςБſ^ϠؚҾɈϤûɲƞ܎MǦǼ࣒ʱ"],encodeOffsets:[[9825,48666]]}},{type:"Feature",id:"CHL",properties:{name:"Chile"},geometry:{type:"MultiPolygon",coordinates:[["@@Bም࣒@Ԓw˧ͻܛʻЭ‚ӻä؏ʨ࢟ŨੑҸ࡫Ҏୃशۘǭ୼֗૜̟ѢϬ˘ֺޠΎװı"],["@@͢୅؆ŘĺɁ˿ࢍࣵг€ඓǫ˓ʦ͡ץԹջ߁̛ރĀ߿ԫࡹϮฏɔƵCޛӑࠍpۯٍշFޙʮࠏԉ̧ɣݡȟࡱƚ৿ͷǡȞॹϜ͇ˡΛ϶ǙĚ̓νǃĜӱ̫૗ѽܓĮыˇՑ٣υôࢹ̧̐֔ÄgؽΒө᎔őުſݝPЙȷݷ̣Ɖ޹Σoॅ˚१ג@@ਲ਼ӔˁՒʄӰх֒Ņ෤Φ߰ࢴٰౣʔߞݒ˸ඊत̏Ѯგ֝ɠʿ਻ՉŠ˂ல˺༒ϮָʍࠎéूΠ„Ԩപ׈എΤబȗ఼ʤۚĵਞӮਆưྺ˒ნˀሤÕ൘ǩ஄ќɌɦњЬֱŐ؅ѴΡ˅߽Ҍह"]],encodeOffsets:[[[-70281,-53899]],[[-69857,-22010]]]}},{type:"Feature",id:"CHN",properties:{name:"China"},geometry:{type:"MultiPolygon",coordinates:[["@@ԑഓΫۏѷ܂ĩخӶࠜڦَϨʡƣԓ","@@ܩЗۏʺyܢаϠࣾɾӚoȊ͍σσșӟ"],["@@ฬˍ঺ׯͼ߃౨Cܰͨ൸ʜѳݱ͙̭˽ः֡ࠇ৵ƪܝ̑ɜܙť঳ѕwLяթӺͯһಙαƀѹܩŒЍ˂ֽ׭ऑҋۃա୭ʑأϽࣝɭ҂ϴǭ͞ږ֠ѹѲܷ̓ॉ׏ԫթ࠙¡ѓϻѸ֩یƏ„ϕڔʕस׶ݚ͝լuƌѱஓɻϻҏࠇућיࣜҥͦࠝԞޓ֮٥_دՅɯȪ҃ӶʻŻۃɇڗҷ÷ؗࣧڹિޭোିޡୟۻृĩԣύ̃˘Ӈй୭сࢵŹ˻ࢱҭ·ə؎Ȧ͘ૻːЇƍࡍɔЏ΀ƄӜޏƶЙܑ̀҃ࠇīڡJ҉ȳѥūŶ॥҃x÷Ȣ}Ύ؝ʓεƸر͂ʔۤՏǎȧޜࢱƓĴাߔۮ”ۚ{٠νȨ˭ӶӭÙࣟŲ˴ΜϿԺ׳Ν۵ȸॷ՗އسڳĿοɦѹr׷Țґɇ֋رëڌԟǭওĈोȖڿτٵǔ˯ЖҽŦࡓոکʴΑȩଢ଼טࠛՒɽऐ׾ő‚іͭјĐۆࣙঠ൧ͼʝ٦ةϼƫʌųӎˆ͜ԛȔ˟ďɇިʈȔśȠߤЈ׈ǐࢸő͆՜ંIJͮ̚೜ҔŠȐãӐּɔݱฦဘͲјȈ؆ຒဠˡҲϞ¢ࡆۦĀٖ֔͢èɚו۸ѽப̿׆ڱ͕ঙ̢ηূƝଆŝ৪ԻԲġϤޟӲӿऒnჄȉ૤Ŝࠦůఔԛ৮BόʽঐҌബ̈ాŒঘ̒׾҈ך˰Ƌˤˍ͔ѴըӀùࡺǝ࠸Ѿ౲͚؞֊נʆ௠ŐڐĥĠ̘ݿזګː٥̳ࠣžӇŃɏΆר࠾Цو৚̓ஆՎQτݸࢾҲːWҪңȦۜмਰƲ૜vసʡ݈̱԰ࡏ̀α̊ԩ̶ࠕ"]],encodeOffsets:[[[124701,24980],[112988,19127]],[[130722,50955]]]}},{type:"Feature",id:"CIV",properties:{name:"Ivory Coast"},geometry:{type:"Polygon",coordinates:["@@ϣUוǒ՟Wহƥ׍ʍ̯ࠫNjvÞۖĄŀ}ͨΣΚˉÈʕɲǾώčО ʔƄB¸ξÝnjĄŜ̸ĶȹڨȗΎæ˸ǘÞŊúɸųٮOƸʖƢgʎĦžΫȞłΌŰϚǽƦ˥Ϙǯ̎ɄϾŒֺɏɠ஡Ο۷ɕेθܣ›ͧ"],encodeOffsets:[[-2924,5115]]}},{type:"Feature",id:"CMR",properties:{name:"Cameroon"},geometry:{type:"Polygon",coordinates:["@@Ľ°ӻŇԝŒЋÅ൅nŬڒ͟֊ϧƚǟϖɋŦXɶɎתЎ߸ʒRԄӮ͈bҾΉ־˲ĀΔȌͺžь҆ΊǞךDzȊŢѨɜ՚۾ٲ¬˨ĠƲͫͰ‚ˌʂ¶ͮ՟Ê֏‹֏ҜޅҷTʁÏϥČǻЅӸөμƛŠΏˆ׃ſɩх࡛ȫƳÝٳČΝåʡЈѭð̴̟џϨ˓œϥĘʏÓґڛȤڷɜ੗"],encodeOffsets:[[13390,2322]]}},{type:"Feature",id:"COD",properties:{name:"Democratic Republic of the Congo"},geometry:{type:"Polygon",coordinates:["@@»ঙͶŕˑ̗͓ɟ͍ѫǯϷ±ګț͍Oهʍɹ‹ԃŗÝýҟɄϡÂ৥ưޝċѧǘӣӤҹҒ੕ͥĒ૿ƙɣĵʇՙȊχƫষĻࡇɨƫט͝ɲƴìٟࣟR·Ҧ̳ΨٟŠȋѰԣ˅ڧŞ˫ϢՕüϽqµʾ́rϥºԳųιtȻû®ৄ˩̸ÕԬŬԒǝ͖eՊ৳Qò̢ѕG­ƣԵɁӧűȿҫŠˣş։å͏Ѱȗ˖ʋԌȷض៛\\̍ķʑh΋œşʼɊʀμƎɎ̪ǰɚđ˼͐ҜSÄʃ̼ƩӶՄӨШɆːƒ۔θࠆϬўքМĪˌt̰Ǝ̆«ӊŀݖǐԾʦ҈¸Ԕúה͜ѐҊ˔۔˷՘ؚ̳ĉظǏʦԖŘÞϦčनоͨDZ˖~ŴȲ̺ðلėբoˤĚԘۙϘķɤƖϲÅҶDzȦΫ݊֏"],encodeOffsets:[[31574,3594]]}},{type:"Feature",id:"COG",properties:{name:"Republic of the Congo"},geometry:{type:"Polygon",coordinates:["@@̿˾ʩƗͻγۏࢸٖҪ̓֌˾ɂ֦ĺäό҆Зݐ•ʴЈł֒ĝڀЉӺζ঄ȽǘسçɻѢÔξ੘ڸɛڜȣÔҒѰ޲ԆѼ֪Ɨդ±·ԓʥ҇ǏԽĿݕ¬Ӊƍ̅s̯ĩˋփЛϫѝηࠅ„ۓɅˏӧЧӵՃ̻ƪÃʄқT˻͏əĒ"],encodeOffsets:[[13308,-4895]]}},{type:"Feature",id:"COL",properties:{name:"Colombia"},geometry:{type:"Polygon",coordinates:["@@ΫȤЭ˨ʅƅ܉Ŝȱΰƽ_࠿Ӓŕʺ̼ڛтȢ̦иÊΞՆ͐Ѵ̳ȦDŽӦȏސǸɚƃ܄ͻ҄ņТ˔ÑǂʠțӶĺŬѢـהΌĚT˦ƺ܂ӖϸՊfäǪڂéڌъ͞ȊОК̖»ɚɛǍ˱գƕɇп͗ʋʓ̷Ĺ׵ɷӭѢÇņϭȄȁâ͹ij̵ˆǫȸéȨ̉ઊĄӦŃעܡͼĚ؂­ӐĪ̔ƟƱҍȇ˯ß׻ǜ֑ʆʟ†ȉэл̨ȃɠ̋ʰ࠹ǁĻǏӸɷˊ˥́࿕lZԿӰē…͏ǙĔҿƑK؏ώ̫ƀӓoηϙᘯп҂ʣpժࡤٟϾԍị̈ƤҧɝصŀӵࢤϳɐˍІ֑Њɡā"],encodeOffsets:[[-77182,-155]]}},{type:"Feature",id:"CRI",properties:{name:"Costa Rica"},geometry:{type:"Polygon",coordinates:["@@җȆǟǮĬƤ‰ȄɷȪͥǔ́ņÅʖəƮÄʑǗȩȓɸˑĊŗǞLʮŎˆʁŠȖnjŴňֆɝȖŊˊéƔǥʜÇȪDzɈҙ͖ͷЂΩ͗õLͷǪűűıƱëǟ©Ǖ"],encodeOffsets:[[-84956,8423]]}},{type:"Feature",id:"CUB",properties:{name:"Cuba"},geometry:{type:"Polygon",coordinates:["@@ܨÑڊW߄˹̭ͮ޺Ĩ̔ȡ܈ԳԺϛˢ\\ԆǟÕʁئ“ٌ΅ıȟ֑Ń֡¥׃âளą֜Ҷ΁ɔէÈ̃ʐȥӎӃ޵ɦʥǬભž̋ǐ̀ɀࠗ¨׿ѧΏ[ťȳеğΫĂѺʸǼ̤ϞȈіǎَĄȰĢ"],encodeOffsets:[[-84242,23746]]}},{type:"Feature",id:"-99",properties:{name:"Northern Cyprus"},geometry:{type:"Polygon",coordinates:["@@ÐJŨȮ؄Yކʢ֧ΧÔƿęˆLJÙűj¥iĎѾNjVɫïƿ¬"],encodeOffsets:[[33518,35984]]}},{type:"Feature",id:"CYP",properties:{name:"Cyprus"},geometry:{type:"Polygon",coordinates:["@@€ãࡱͿЩŊȟͶЎŒǀ«ɬðnjUÒ½j覎ŲiLjÚ̇"],encodeOffsets:[[34789,35900]]}},{type:"Feature",id:"CZE",properties:{name:"Czech Republic"},geometry:{type:"Polygon",coordinates:["@@ϯǂЁ©ٵʲ̏Ùҿ΅ر˔ӃΰѕȬėΠƧʠؒǾ̸Ⱦ׾ǎɂdžɜīϒĖЊ˓ؼñ¿ɳҘǧŲɒּĥĄʿز»ϮЯʡCŽƯȕ—ÅȑLJ¡wý˹ēϋbšȁ"],encodeOffsets:[[17368,49764]]}},{type:"Feature",id:"DEU",properties:{name:"Germany"},geometry:{type:"Polygon",coordinates:["@@d͗ࡔțS̗ࡢǂҾɰॊͧІˋȞёɹɣ̨̙Ⱥ҅ß́Έ՛ϑĕɛĬɁDž׽Ǎ̷ȽؑǽƨʟĘΟіȫӄί̑ϯ̟ŃŢշýƛʿǤЕ~׷ƭݍ–ţɛыɺʩ±࣑ʲǥǻ܍Nń״ьֺ௅ƸЇɘ´ςǗȐĨ֨ƗࢢԎ@Ɉ͂Ⱦޔƿ˴ǐDz۰°Ƽȃ֮вȓ̀ӈٌōՠŸ"],encodeOffsets:[[10161,56303]]}},{type:"Feature",id:"DJI",properties:{name:"Djibouti"},geometry:{type:"Polygon",coordinates:["@@ȤʹΑӏȩήɯ̱҇ȅƬȭÏҷb_ʮßɶ˴Ѐ̐ϊήñʪȴ"],encodeOffsets:[[44116,13005]]}},{type:"Feature",id:"DNK",properties:{name:"Denmark"},geometry:{type:"MultiPolygon",coordinates:[["@@ԋڹ࢟ӄŝΒ௼˨ˎу"],["@@ȵ̓ʡĞ؁؁ɮХ՟ŷًŎͽҲ}࡬Ɣɪʌʦ݌À̐ɴڮʂƒѝʟ˙ĶɽҘŵ"]],encodeOffsets:[[[12995,56945]],[[11175,57814]]]}},{type:"Feature",id:"DOM",properties:{name:"Dominican Republic"},geometry:{type:"Polygon",coordinates:["@@ŀƞپIӾɏɜtƴ̕Ҡhʡϐ‰Ю̷̯ͿЍǼϫ•ˡ¢ƱƵ͑½ŷȲˣťͳֻɏƆ§ʎjɬɍʦȲƚÞ͒óҜ"],encodeOffsets:[[-73433,20188]]}},{type:"Feature",id:"DZA",properties:{name:"Algeria"},geometry:{type:"Polygon",coordinates:["@@ᮩཽᝩ࿷இϑटćU՘ϵƌԹʊȧЀᬻᆴᬻᆴṕᎠfnj@ÊQ঺ബب࠼Ÿێɦ͎тচͪ˜جӢòϞ̶સƚƸ͜ɛDz̃ࢲ¹Ԟ́ՠ߰ҠࣦƢՌΎ߶ʰ෎Ƭർæшůߊͨ࣌P΀ȝֺ¾ǟћƄߟȡۙԭҵôمۊԃRȯԮ͹Ϊຝ˖ݏ°ϵƧۇÔϥŃҟòՇͫΗӺؓŽέ̘ҵϼƸڒϷςՃ"],encodeOffsets:[[12288,24035]]}},{type:"Feature",id:"ECU",properties:{name:"Ecuador"},geometry:{type:"Polygon",coordinates:["@@҂غǻξ͍ϵԉςǞʀƙބ̎ŴƺԼ͆զÍ΄ҢǸ׀Ͱࡀӑƾ`Ȳί܊śʆƆЮ˧άȣŞٓʽճࣷ࢟য়ͧԥܵǃ֣Ӆ΋ΙъͻĞ΍áw̮ʈȨıΔ"],encodeOffsets:[[-82229,-3486]]}},{type:"Feature",id:"EGY",properties:{name:"Egypt"},geometry:{type:"Polygon",coordinates:["@@ɽͷǹىɫѩȝƥ˩˔ϛϒ׵ஸđùΐࢯԪࡋٌವ̴ҙ˒ӃݮछǗƣ‚ճ঒ݭƨǣΏ@Ὁ@⁩@@ᶶ@Ჴʥڲɐ԰Żά̤Ж૦b߲ɝ࠲ʛϴſ٨ˊΌʊݎêװŃɮеȜ˜ڨȣټ³аɄւ෽"],encodeOffsets:[[35761,30210]]}},{type:"Feature",id:"ERI",properties:{name:"Eritrea"},geometry:{type:"Polygon",coordinates:["@@˻˖ΉӰϋ˒ɏܷ̄ͶֻXȭǬӯȡԛϢʽط঑ǬęʹβఀĊ֒ˆʴؤƐьӒӦঃɴޗҢУବߏҲӍҖӝˀ˿аʧʩȳέò"],encodeOffsets:[[43368,12844]]}},{type:"Feature",id:"ESP",properties:{name:"Spain"},geometry:{type:"Polygon",coordinates:["@@¦״΃θஒ؆ਊƱ૾NࣂƝۦªമƒͰ͛໺ϡ̨ǺीϝআŊ®ӥߓ֓ઁǯõ˱ԩү͕ہ͞ӑӟϑǹճىǗש٥੧_ߟhՃ͍̓ͅЩê̵˴ʃӚ޷žé˦̶̀Śɬ̃ʢɶրͳԌδè’ЈƎŬZپϲɪɻфөˆƝŁӹCɁЬ΃ū̥ɇ"],encodeOffsets:[[-9251,42886]]}},{type:"Feature",id:"EST",properties:{name:"Estonia"},geometry:{type:"Polygon",coordinates:["@@ĮӸ̱ŁՓ̘ñӘਫ਼ɼ੔Ũ࣮Ƒࢂ|Ŵƣׯӝʞ޵ΫˉۙDܡ̸ρļ܏Ʃ"],encodeOffsets:[[24897,59181]]}},{type:"Feature",id:"ETH",properties:{name:"Ethiopia"},geometry:{type:"Polygon",coordinates:["@@ԜϡӰȢȮǫּWܸ͵ɐ̃όˑΊӯ˼˕̏ω˳Ͽàɵ`ʭҸaȮÐȆƫǽ̴̕ҧ̴Й̛͎ᩨঽۺNᛛᡃફ™ݟףաeɯ˅ַB͹˴ލΙʝΓ֕àȃĬȟwˇT੟܌ב@˹ˢ@ҾѧƘӻࣴϥȚƧʹэЦԧÒ˸ӐҀrŲʰ[ݲʞࢠЊɾĎ΄ήٜԔи΀ࠠƆܠ঒ǫʾظ"],encodeOffsets:[[38816,15319]]}},{type:"Feature",id:"FIN",properties:{name:"Finland"},geometry:{type:"Polygon",coordinates:["@@ūיಀ֓ޡى঎ख़֡ܛݴس΅յఘֻ́ѓޭӟᅡੵໃá๑̯ൃǯӡҞ߿ˠȈࠢСݶАӪނՆ኎࣮֖Ǭē΢ୟЈ˳͜uಒ಻ֲ૩ЪԊɞतѻલ¦ࣘȭߠϊЬ؞ಬ˶઄ͯΡכ"],encodeOffsets:[[29279,70723]]}},{type:"Feature",id:"FJI",properties:{name:"Fiji"},geometry:{type:"MultiPolygon",coordinates:[["@@̂ʍƓѭԳŗҩļąτ͖̀ϤĻȼƐ"],["@@՛ǯŅ̼оǤˊ°Ӱˀ@ЧՕȷ"],["@@é­@ШǨžĽЗ"]],encodeOffsets:[[[182655,-17756]],[[183669,-17204]],[[-184235,-16897]]]}},{type:"Feature",id:"FLK",properties:{name:"Falkland Islands"},geometry:{type:"Polygon",coordinates:["@@৘Ԍ܎ȿԌʹڦϙʥ̋ଋʥϙ̌܋ϙпϚ"],encodeOffsets:[[-62668,-53094]]}},{type:"Feature",id:"FRA",properties:{name:"France"},geometry:{type:"MultiPolygon",coordinates:[["@@ˣ٭ϡǠș֢ǜ̺ը͎Ɯܛ"],["@@הЅќà݀ϥȊñʎjЈɗெƷыֹŃ׳ɱƝϣü‚ɇؙҽ]ϟВƀ˾ρ“ʁʚ̿̅ʯɐٱҖŃĩηݿӅစɬ௧˗ĩԑঅʼnिϞ̧ǹ໹Ϣͯ͜ѢԎdžူࢁࢤإю౹͒čؖઠǾථɏˇॎߌέዠپʨێܾǞŪ̑ϸ_ϸ͵"]],encodeOffsets:[[[9790,43165]],[[3675,51589]]]}},{type:"Feature",id:"GAB",properties:{name:"Gabon"},geometry:{type:"Polygon",coordinates:["@@ࡹࡔ։ۚԙࢄ‚˨ǾˎȲؔǜخ˴¶௢SOৠЌÆԞőӼňľ¯ÓνɼѡشèȾǗεঃЊӹĞٿŁ֑ʳЇݏ–҅Иãϋ֥Ĺ˽Ɂ̈́֋ٕҩ"],encodeOffsets:[[11361,-4074]]}},{type:"Feature",id:"GBR",properties:{name:"United Kingdom"},geometry:{type:"MultiPolygon",coordinates:[["@@҉ֽًǦԱ[ǦҊǥ҈۴–ࣔԳ"],["@@࣋ࣧࡦŘऄIɕۅݯݩࢄÃäĕݠ঱ֺƇԬढ़ʈͧৰDžķ՝ѓʗͲѣݱѯ૳Rෝɱϻǒ։ϿޥĪם͍ҁǘ௼ࢨݪǺOBಽƔʃͰ࢜ʺҡҐdžռఢ÷D@ŮӤ֛Ԯ_\\৵ƨȧɬ̨ϒˡɴҍЇ·߶щє̨ࢆٶھڤá০ì"]],encodeOffsets:[[[-5797,55864]],[[-3077,60043]]]}},{type:"Feature",id:"GEO",properties:{name:"Georgia"},geometry:{type:"Polygon",coordinates:["@@Ųάȿִӟ̲ҭĬ̯ʴĺIJ܄ƝఆƋଦЕƦƻԚƂ޶ǭʴ·Նșɓřвғŗıҏºصʎȵƍଢ଼ſ߳Юࣅ¡"],encodeOffsets:[[42552,42533]]}},{type:"Feature",id:"GHA",properties:{name:"Ghana"},geometry:{type:"Polygon",coordinates:["@@೉ӯҳ˽ݳʑݡʆœͨηܤɖैΠ۸ɟ஢ŗنrӊฤ¢ϊÕ˔ƊϴáÕʿΖџC؍Ąڍɂ̫ȅݳäйɢՓȈ̍"],encodeOffsets:[[1086,6072]]}},{type:"Feature",id:"GIN",properties:{name:"Guinea"},geometry:{type:"Polygon",coordinates:["@@ʃtǡͷʁJǏǴÈͶΗԨɕħǵmɳ³V̮Ƈɘ‚ʔǻΜɹ̜ڥDțǁɵoƝǷīɹ҅σρӼ͛͢ɋŊȿǖħϊūȂʓƐώЦʮeɖƘȄDƄŎï˨ĢĖd˶МU؀ȱȄlÚĤҜáŨ´¶̭ƆBɖŒƔƒɸɇάãɲǺ˖ŒȬŠǚuȈȁĴɳΆΙǣɏ˙ǴĊŀį«ʡʲʍǗÝå˷Ș΍Ⱥڧ̷ĵăśÞNj·νƃA"],encodeOffsets:[[-8641,7871]]}},{type:"Feature",id:"GMB",properties:{name:"Gambia"},geometry:{type:"Polygon",coordinates:["@@ņόࣶzȎȦˊ`ͨȷʼIˢƚǞʏεȋιdέǰ̷ȗƭQȫŝއl"],encodeOffsets:[[-17245,13468]]}},{type:"Feature",id:"GNB",properties:{name:"Guinea Bissau"},geometry:{type:"Polygon",coordinates:["@@҅ΘΝÈȕʀLŸʯǴÁǶѼƌ˦ɦĨ༈•c˵ġĕð˧ƃōȃCɕƗʭfύХ"],encodeOffsets:[[-15493,11306]]}},{type:"Feature",id:"GNQ",properties:{name:"Equatorial Guinea"},geometry:{type:"Polygon",coordinates:["@@ƿŴ़̀െmPয়௡T˳µ"],encodeOffsets:[[9721,1035]]}},{type:"Feature",id:"GRC",properties:{name:"Greece"},geometry:{type:"MultiPolygon",coordinates:[["@@Ҡ˱ٺ¶شÑqƣҜĶĿʛ௃íTƒਁǎƺΦ"],["@@ʹՁȥĥԟ|ѫĀৱɓ׌ҿяƋҳAѻўƿȁȊԅрЁ̓ǿҴϯжʑ^ӅޥɠʜѕՓĕ͈ݏ֏Yۍμ̿ڦƧ֒͝ϮљӐÉʆϸТ¼˚˘Ũjɚռö͌ȀҖgƒƦdž„ت{ڨɲע̉ކĀVмЦɝ"]],encodeOffsets:[[[24269,36562]],[[27243,42560]]]}},{type:"Feature",id:"GRL",properties:{name:"Greenland"},geometry:{type:"Polygon",coordinates:["@@ᬜԆ᱒›ੴ̴ᲈĄ䀦Ŀ㉊ڗ༅͕ộ™⭏ćшƫᲐĠᡚ́࿈ʴۦ̝इӧᒞ̺✘͚ᠼNjҾΫ⃝ױӃȕ᧑ơወ¡ছؕگկ€ध৚շಽ“൧ˇ༂ѽȢ܋࣍ýઞܡህÑঈ΁˟̑இŽ୥E੆֩\\Ϗပΐћɣଌȿ઼ԣ͈ڱກlj٫͖ਣӘ˼֭উѵᕖ•୆¯ᖯܵᗿڏឧ́ओIࢅ͓ୟࢱᅵכׅ“૧ȷ஽ȝܛԱ[כыտോڧͺٿϗ۝љࠍஅ½఍ۈဿLࠁҢ֕ࠐฝਲэոŗݮ୓ޢ̢ئ֗̒ࠪচొ̺ͨΘǬڀॡ̕қůݯţਏ˜Éְ͢҂ެ\\႔ɟ෿Քݩ˾࠷ş۫ȼम޴ԝ̺ڗ׈ৡࢼ੯͚XΚᖷӮᄻÖᖟ‘Ꮕ×ইˌวՈᕂ˄ၚ¬≹ɖ቉΄Ś͜ẊИᶎИ̪͘ᗗ̠ܺͰ᯲ז௢ĚΓϘጲɜᣚƂᣖRࣺʽᕺҨፘ̽୺áპ˙ፅҐŘή"],encodeOffsets:[[-47886,84612]]}},{type:"Feature",id:"GTM",properties:{name:"Guatemala"},geometry:{type:"Polygon",coordinates:["@@ћƦԻfϩǖҍΌrʖĮȠšƾКۆ઄Ft˸Ƌ¾ġǺ̵Ț̹ˬϜDBӂ޸BަUOڗßॅʤ@˚ƱòŰʘŃϥ͍ЉɻÏljâǑǧɇȟ½¬ıƿġ˽Ƀ}ŭ"],encodeOffsets:[[-92257,14065]]}},{type:"Feature",id:"GUF",properties:{name:"French Guiana"},geometry:{type:"Polygon",coordinates:["@@͉͑ГÑŗʀȉ–ʹɩνǦɈΪòϤƢή͛ӸáֺѪܠ˸ğؤȥࢸۿƔ·ӻޑʳأ"],encodeOffsets:[[-53817,2565]]}},{type:"Feature",id:"GUY",properties:{name:"Guyana"},geometry:{type:"Polygon",coordinates:["@@ր̯Դյzџ̈́o҈Чͪ̇Ƈݱԛɕ°ȣƹџϊ؏ːAŎӃԢܳȱ‰ҫî˙ɡϟƥ˅—ġǑЭ¦ԫЀÓϴɋьƆܐɸ̐ȕϸ˿ŶŊτțȘѩ™ْ֩ɬɲiϲԬƊȾƾ˽̸ô̬ږӲ"],encodeOffsets:[[-61192,8568]]}},{type:"Feature",id:"HND",properties:{name:"Honduras"},geometry:{type:"Polygon",coordinates:["@@ơˀʭòÐʹŗĞǣÒσij‹ŔʩƈǷǚʛìǨɈáǒÐNJЊɼϦ͎ĔȂƨʊ\\þ垦ϸùϲv˒ĢİĦˎ©ȪÉɘnǖòϨśƄkʲƿʐį̏Źɜɳ˽jśŕ̇ŋɃAȅŃǙœƛźĕ{ŇȩăRaǥ̉ɳƹıđĽʛǞǹɣǫPȟqlЭūQĿȓʽ“"],encodeOffsets:[[-89412,13297]]}},{type:"Feature",id:"HRV",properties:{name:"Croatia"},geometry:{type:"Polygon",coordinates:["@@Ȳ͗ˊʇ͓̓ϝȆׇ[ܟƔϽmǻǧ̝ȖǫΑЪϽǼʹϮ̽͌ȃ͆Ηݔ͇ġƛ߃̶ӣ̢ޑʠ۹ؤǞØϥΞe˲եƄʱγʝˮn̆Šbג…Ƹƚ˸ƍͤgGɼ̈ĒĈͺڞɠˊĻؼέۜlj̼Ų"],encodeOffsets:[[19282,47011]]}},{type:"Feature",id:"HTI",properties:{name:"Haiti"},geometry:{type:"Polygon",coordinates:["@@Ԣ™ܰƁôқÝ͑ȱƙɎʥiɫ֏ƜЅÍԡÔϽƿ҉ʾö˔ޜśيã̢ȈϧθP͎ՋžȌɶ"],encodeOffsets:[[-74946,20394]]}},{type:"Feature",id:"HUN",properties:{name:"Hungary"},geometry:{type:"Polygon",coordinates:["@@˨ըǍǼӂDÜ΄ђɋ̲ğ۸ļäǚͮ~ЦžĜÃЂŀȠȢˠ¼࣒ʭǴĒҲɭÎɣԡǭЉ֫ԕ֭کǁԽš١ə̻űۛNJػήˉļǍ˴ƗV"],encodeOffsets:[[16592,47977]]}},{type:"Feature",id:"IDN",properties:{name:"Indonesia"},geometry:{type:"MultiPolygon",coordinates:[["@@Λe૝ך޴ǒѴʭ̎ʭ»ɩ"],["@@ܙȁijĶø˸ΰԢࠨͬĐǓfʫշع"],["@@̢ɣԲèȼΥॿǛ׉őҍP̀ӚҤPɤ̖"],["@@ūұ౅ʅૣľE̬ښǪՂʥ֔Üݬ̮"],["@@ྔċȂΌ༘З̪կీƵਐӿय़͋ऍ͸ݻwࢍØ޻ưঅ͎؝ČΓŁ໕ΌƣΰޑØּߤ৶·ڴ͡ΒÛŘ̗"],["@@ѝֱćنƬ̠Ǭ˴ȒʗCЏ"],["@@̿˥ׅƸǏΰࡘ¢Ⱦˣ"],["@@̨ٝۿΌۯìӃÅׇˆȦҦਠ”ऎʕ"],["@@ɼയ࢈ԉ۰ࢼ८ԔݜBܘ̉خ̛ࣘLJbᩑbᩑݟې࡟ǜȷʇ੡}ΦۂՈɺɕࣲЕ۸࿃܆ۗêృަʛУ͑óȏ̮GκٛЮ̢ࣞ״gëɠ௵DͩԄݥƺΡдଈȰњ˜ഘ·Ƃ̹"],["@@ڭ࠭كlj߱ǐඓ¥ܽŧţٍݪݛҒϠ༪˸çϯλŪιӯ͙݉ߒ੿Ƶ˿ݲॻQտ҅ʙ̐͡Мی࠙͗ȻɶŊ͖؅ӲØࠌ֕ʭîও”றՓũίʚʌޜŽ߸ΛPʻֺΎվŤښф౎ǮΎ܎ذپʛ੖śॴ–ࠨ؎Ʀȉ"],["@@©ܽџĈŷԝΌѷɽĵ͹Ւʟ੺ǚڤ˨̨ÔҝӸóĀ΃"],["@@सާহį˫ֵšݿַ߱u࠷͕౻ŭ̚ॕϙͫԤ׳´лːৃ̟̩Оս¯ۗĬŹૺнɺЕܘŝ݀ĮުԂ֐Ɩָ֗ӅըǠ՜ÑӪъЖôߒɽۆǶњୠ͔̈̆क़ॲ@ܰƙӍݷآߓơϭ"],["@@छkۻ۰અۊέԚٍۄзؾٕ୴۪݅ʙܠ̳ڀݵՊѭܘمҺࢗऒóђզ‘ಢNjݔࠓٮ֫ҪΓߔࣙࡢ_ۺֹӠ۳٘ϥͳۉӖ̞̅sƜו̊ҵؠõФՏɁ਱‘ಟ"]],encodeOffsets:[[[123613,-10485]],[[127423,-10383]],[[120730,-8289]],[[125854,-8288]],[[111231,-6940]],[[137959,-6363]],[[130304,-3542]],[[133603,-3168]],[[137363,-1179]],[[128247,1454]],[[131777,1160]],[[120705,1872]],[[108358,-5992]]]}},{type:"Feature",id:"IND",properties:{name:"India"},geometry:{type:"Polygon",coordinates:["@@ࣚটďۅͮїѕ׽ŒɾएࠜՑ୞חՑϟ͛޻ࠀͅߊЭરһସʼnӜёٮāৠȝ۪bĪͪŋՖÞβԠǮìڋlǙކ͉Ոƀ܀Çۈ|ÐԪ΁ˎڴŀވشॸ՘۶ȷ״ΞЀԹ˳Λ࣠űÜ͇̍Ʒèԫ׷Ʋછׅ~ӓҩ۵§ХϏۗځȒࢇȏ˹ĚΣгȥѵ೰ɵEƍ՝ҡѦʸӎϖ¶ϰ܆ӝƜީ]ߝŚóאБ¤ڕζ֭̓؆ѻԿ̻ȅ̩Ԭɣƛԑ̆كžەţֱ̫Zਛǩ´ك҃ӻ௃֡ळ঩كՋ࠷ջCϭлȹݳ̝Ͻ«ʥٙǪધ®ۡΣߙI෗ѣ¡ϣٙʰˣދʃ˱֯͵ʍߑ޸ϳ୴͑ࡒ̍Јѿ߰ȻੂơՀޅ଼Α࿀ʣ੾HৰǍ޾௣ԉףĶ઱৲И̤ʝͤড܊֖֔ᇜCǗܞҽюĩ٨ջϘऒࢢঊÙ࢞ࢢՄ࡞ࠄࡈ_״ܒӠڳд֪݂̇̕Ьβ౤ȱपŰߺ۸"],encodeOffsets:[[79706,36346]]}},{type:"Feature",id:"IRL",properties:{name:"Ireland"},geometry:{type:"Polygon",coordinates:["@@ƒ׷ًݣ๯ӹ஑Ŷڼ࢚ѭࡢତڄٌϼǦ҇ǥ҉Բ\\ٌǥ"],encodeOffsets:[[-6346,55161]]}},{type:"Feature",id:"IRN",properties:{name:"Iran"},geometry:{type:"Polygon",coordinates:["@@݈njװӔ֚{τƾװýघэڤğ।ݓظ‰òۻ΁਷ɱؑκŭΫҡˠڡàՓِƙæեݿݿжѵ͸ԓߦυx݉ДƋêϯ௉ѡ̓উཌྷʪࣷȖेŊΧਐЕƪ٣ƭࡑНਇ˦ࡑ٦߳ʈ֗ߘا૪ҍƋՕ˦̻͝ҭѴS҂ˍ@Ɛ،ѝٔ਍Ң׉ߜȜپц̂ÙӬտʨխ৊ҟڨǐʼʿ६ּʈƄͅъϯ־ő̤~রئ̀Øʞʙ́гԼѱȾ¦ˈإߖǩ׎у஠ƟಾɞĄȞ"],encodeOffsets:[[55216,38092]]}},{type:"Feature",id:"IRQ",properties:{name:"Iraq"},geometry:{type:"Polygon",coordinates:["@@րʧÚӫх́țٽ׊ߛ਎ҡўٓƏ؋ˎ@TҁҮѳӿ¤֟ê؝߭༟äᛍၖఫךৡɪ͹৾ᇶ࢔͆৬āؘҢȺјԾΰž঎Ň̐ɉЖƚծ৉"],encodeOffsets:[[46511,36842]]}},{type:"Feature",id:"ISL",properties:{name:"Iceland"},geometry:{type:"Polygon",coordinates:["@@șիॊֵથٙᝓֹܣƵૉŮᚑˈࠠψᆧЪ๪ǎ—ʘᄋȜ֨նౠŰಸ֭౨Ҝ੒ʃൌ҄ආÑ"],encodeOffsets:[[-14856,68051]]}},{type:"Feature",id:"ISR",properties:{name:"Israel"},geometry:{type:"Polygon",coordinates:["@@ƥ˅̣Ŝǫ֓ɂĥɋř—ɛЄŖp͛нഉց෾ʔˢ˶ɞϼǠيŤɆzVˬCþƦɤ\\`·ŕŵhM"],encodeOffsets:[[36578,33495]]}},{type:"Feature",id:"ITA",properties:{name:"Italy"},geometry:{type:"MultiPolygon",coordinates:[["@@̟ڋŲʹǭѝٝ̈́ёĞ୩ѐŞќজûࡪĠْò"],["@@Ԍ׭ş૕ϣÂ΁˫͇ɞ‘২ȓӒҨ¥рʼ"],["@@ரɏĝЯȬΧڝŪہ̗²зĻʇˠё߀чцۛदڱچLȲȃɽǗݪ̥ؠʩܜѫĔƿƽ̛үϼܳƐΝի؈̷ıѫΗ¹҅ܛΕÝHʲǢҊǼǶ͝ӤʱшΑŀʛδգƴεͶثÆٿϜޑմ֯ӜʿࠪйĮہˤϯŕӝϵΓÕĪθҕńɏٲ̆ʰʙ̀”ʂβǵМ¢Ҽ˶ƢƃА€ǼͺتĿψƚâΆԘšĮdžࠨƤȊ̉"]],encodeOffsets:[[[15893,39149]],[[9432,42200]],[[12674,47890]]]}},{type:"Feature",id:"JAM",properties:{name:"Jamaica"},geometry:{type:"Polygon",coordinates:["@@֢÷ҀȫƔɯןeʭƗҹƊӑ̪ĶȔΜÎȒƒ"],encodeOffsets:[[-79431,18935]]}},{type:"Feature",id:"JOR",properties:{name:"Jordan"},geometry:{type:"Polygon",coordinates:["@@Ʀˆपͫ࿪ࣆͺ৽Džų၅у࠸࠿ˣƛƑ˭ٙřȩ̡εʵधƆƒŨоഊo͜Ůʚ@Ԥ"],encodeOffsets:[[36399,33172]]}},{type:"Feature",id:"JPN",properties:{name:"Japan"},geometry:{type:"MultiPolygon",coordinates:[["@@ņ˽ҿԕΉːљțɝӭշʈRЊҬԆӌīΊΜؠǹ"],["@@́ڡƤсѩף੹Ѓ๏½ணॡ͔֡“غษȃষЃঝe࡞أ֗෗իΝН͜ȶݶՏʒͿ־ߐʶѲՈࡌѢ؞ָာʤ࣎ǣࢠ๺֔Б௾ࡀӌ͜ՈਈƟा΢ՎࣀƸҞୗ}ڻޥࡍbࢁ"],["@@נǵרΤȈहఝɯ݁࠱೓ָқँण]ř࠴д٨࣌²ʖ୐ʜټন࢓٤˯"]],encodeOffsets:[[[137870,34969]],[[144360,38034]],[[147365,45235]]]}},{type:"Feature",id:"KAZ",properties:{name:"Kazakhstan"},geometry:{type:"Polygon",coordinates:["@@ӕƹ્דο׹̹KɱЊ੫‚ǡێХNÚࡆ৓ؘ෷ßডũߣݶۋ͆ಥ׼ƽðᓗӹᶽљ£יچ֧ɼॕǩχ˧±ȲȶΖDž̊অ˺ϛݮҩɆ…˜ࠊāŽؘ܎ƎܼűƲࠎƭԲ࠿£܍ȴঃσ޵ǭяƌĐўՙ֘دw܉֬ӞِʕǢڢऊࡺӣŀؘჄࣴಾtᇢ׉঺ͻࢼΠ೰j੺ѥʔʠ୼—ɂЊഷ׀߮Цƿɮ߮ɔ؅ֺϬ˼Ḯ̈ШȺᑆ̴ݰΒຢǹ˄ࢉ࢚Ȳઆ˹éҝ߮´ᑌߎ̭ˁ੶٭ሠᒑ҄ѰୄӛீɎҪƯКӟטNjΨΥ઎ŒѾԣٕ֓ۥÿ¡ࡅұϝဟˢ؅ຑїȇဗͱݲลֻɓäӏԭŬу̠ఝĖඃx̧ġ஥ΞӉǧŽӹ൩̂փşȉρ"],encodeOffsets:[[72666,43281]]}},{type:"Feature",id:"KEN",properties:{name:"Kenya"},geometry:{type:"Polygon",coordinates:["@@ӾۙיͱȹΕ̿Õšףˑ͹Ǐ֑ͷ˥஻ࡀËӤᵁႌƙĢSࢺʊ;а֌̨ؔσ॰įтЉ׎ԬԈ֬ֆѨƗ@ҽ˺ˡג@੠܋ˈSȠxȄī֖ßʞΔގΚͺ˳ָAܽ॑Xᵣ"],encodeOffsets:[[41977,-878]]}},{type:"Feature",id:"KGZ",properties:{name:"Kyrgyzstan"},geometry:{type:"Polygon",coordinates:["@@ȊςքŠ൪́žӺӊǨ஦Ν̨Ģ඄wఞĕф̟Ԯūşȏ೛ғ̙ͭઁıͅ՛ࢷŒׇǏߣЇŜȟʇȓཟŵਡ˘࣫ÝĂӜࣴƕ̮ʸٖĉ੾؂঻ѸױȽإ͂۶ծʟĊ"],encodeOffsets:[[72666,43281]]}},{type:"Feature",id:"KHM",properties:{name:"Cambodia"},geometry:{type:"Polygon",coordinates:["@@΁Ѭыࢄȣ২ՠۨઘdž߀ťۚ͡Ϟׄݖ̱Ȝ֕Ļ৕ඳ٧τԙࢥÓܫͷ۱Ū"],encodeOffsets:[[105982,10888]]}},{type:"Feature",id:"KOR",properties:{name:"South Korea"},geometry:{type:"Polygon",coordinates:["@@ܨযȺխPॷ̓ҥݽljڥΏݳïĥҚƼـχ࢔ذƚֻܘÂúϒ‡͞Ϝצ¢ΨÈŨȮ"],encodeOffsets:[[131431,39539]]}},{type:"Feature",id:"CS-KM",properties:{name:"Kosovo"},geometry:{type:"Polygon",coordinates:["@@›ǣŃPĘ́ȩĐdzɦƾȌȪÒŜ˨ư²Ţşƾ¿ŌƅƒŸǎƻŢLĥȳijij„×ȉӹŻ"],encodeOffsets:[[21261,43062]]}},{type:"Feature",id:"KWT",properties:{name:"Kuwait"},geometry:{type:"Polygon",coordinates:["@@Ǭχõȓ˔هשuȽАݟĆ؞߮֠é"],encodeOffsets:[[49126,30696]]}},{type:"Feature",id:"LAO",properties:{name:"Laos"},geometry:{type:"Polygon",coordinates:["@@˚Ϝœ܆ڹܸ¿ٕࠦھٍÎǛ̉ӯyʣƨࢯԅoݬȸࢮ֧ž³ԎηʸǴ̲ܐնøȡ҄wŵ०ѦŬӮڏϖޅਚO͚ܹ՝ɗʉ̟৔ԉۦ঳Ռ݋َ׏ɄץƵ࠿ݕ̲ϝ׃ۙ͢"],encodeOffsets:[[107745,14616]]}},{type:"Feature",id:"LBN",properties:{name:"Lebanon"},geometry:{type:"Polygon",coordinates:["@@ɣ[ýƥ˫D̘ۄмעfˆϘ§Ɛͣқ̓ȷҟ"],encodeOffsets:[[36681,34077]]}},{type:"Feature",id:"LBR",properties:{name:"Liberia"},geometry:{type:"Polygon",coordinates:["@@ɗQࡽАޅٖ܏Ң֣ըȪː¬ʔϜҘϺϺǶnɖĨΘԧÇ͵ǐdzʂIǢ͸ʄsŸʓĎНǽύʖɱˊÇΤΙ~ͧăĿÝە"],encodeOffsets:[[-7897,4470]]}},{type:"Feature",id:"LBY",properties:{name:"Libya"},geometry:{type:"Polygon",coordinates:["@@ק̷ҿҤ೧βρՄڑϸϻƷ̗ҶήӹؔͬΘñՈńҠÓϦƨۈ¯϶˕ݐШȜðΠėΒ־͔ʶːЦʌ´٦দ́ΜðۮƓ૞ϓЀݛݮǍஆΙࣆйЦɔЖϮț٠˂Ф؄ЀׂŘ଒ǣ˺ϑ̺Iˌƛ࠴ıȲˣ̣ЕżΫɏԯʦڱ@Ჳ@ᶵ@့ॱGYΙ‧ྐ‧ྒࡓҟ"],encodeOffsets:[[15208,23412]]}},{type:"Feature",id:"LKA",properties:{name:"Sri Lanka"},geometry:{type:"Polygon",coordinates:["@@ų࢓ΙʇܵȓЍڜƫீϠ഼׆ұϺסО࢓"],encodeOffsets:[[83751,7704]]}},{type:"Feature",id:"LSO",properties:{name:"Lesotho"},geometry:{type:"Polygon",coordinates:["@@̆ʩʳУƛ˛ҳſƹˍ̛ċؿ٨҄ՐҖ͢ϼǠξʵ"],encodeOffsets:[[29674,-29650]]}},{type:"Feature",id:"LTU",properties:{name:"Lithuania"},geometry:{type:"Polygon",coordinates:["@@ãɊĚɲχƄࢡƨDZ۸२ʴඬÁࠜĊŞǩ҂Ã߲СĀϓۏˏșӃ࣯̓߻NȫʶљĜ"],encodeOffsets:[[23277,55632]]}},{type:"Feature",id:"LUX",properties:{name:"Luxembourg"},geometry:{type:"Polygon",coordinates:["@@ǘȏ³ρʍiȉòĞҼɖŽ"],encodeOffsets:[[6189,51332]]}},{type:"Feature",id:"LVA",properties:{name:"Latvia"},geometry:{type:"Polygon",coordinates:["@@†نЮՆߊ˼ڜعڪhNJ٤ܐƪςĻܢ̷ۚCКȕîС˒ӷ͕ࣗԛƙ߱ТҁÄŝǪࠛĉණÂ१ʳ"],encodeOffsets:[[21562,57376]]}},{type:"Feature",id:"MAR",properties:{name:"Morocco"},geometry:{type:"Polygon",coordinates:["@@ԒΥߜÎࢊȃκU͂՟ºԝ̄ࢱɜDZƷ͛ષƙϝ̵ӡñ—ثঙ͍ͩсۍɥ࠻ŷഫاRহŷ@@@p҉Ա˓ȑϡ@̥Ŋ۹ě˛ٻʿÕЁ੕ୟ࣡ˣୋ΅ϗĵ̡ቅãaD ϶͒ɮ˞ѪÃ˶̀פҴՖ˲ƊɞӬp҂̤Բ̪֔Ւ࡬f\\ц͔ްĢڎָтɠۮۮȿਸ਼͊ܢŔѶդ֨ࡈϦخΐ֘࢈˄ԪؤI"],encodeOffsets:[[-5318,36614]]}},{type:"Feature",id:"MDA",properties:{name:"Moldova"},geometry:{type:"Polygon",coordinates:["@@ȨŮ֒ĊؤʽΊϞɥÑ˵̪ƏŨΗ̊ɇÏűƾčɝ×ӷ|ĉŜǫãÒƭɱˍƥ˽ɁĝƯϦĘΪςӝԂˉΠʹʠʯĈ"],encodeOffsets:[[27259,49379]]}},{type:"Feature",id:"MDG",properties:{name:"Madagascar"},geometry:{type:"Polygon",coordinates:["@@ɠΥȺ։Ɗঢ়ɒϽĉЗƩʙ˷ӰǁʝLjثõΥɵȗ¿܅ͧওб୅ԯཧ͑ୟϛইہȣܻΡӛɊڙ̜ɳѺÇݘ̑ڠù؂Ʈ؄ϰƢD˪Дِø՚șЈǃՌãޠ̊ҺŔՒмŒҶǤ̶Ʋτ\\ӐӎۖԮʦцŗάΦĵҪ׎fԐ˦ϔ̊ί"],encodeOffsets:[[50733,-12769]]}},{type:"Feature",id:"MEX",properties:{name:"Mexico"},geometry:{type:"Polygon",coordinates:["@@͙݅ƥ؁Õ૷ąЧƤқʺЧǚٳ֎سȞӏ͢бࢾɝΐΙ݄ɾٚĎؼưՊƠՖ΂ȨӬè۸Ƣʖ֬ɚࢶȚݔ‡ԚîȬDZ…ЙҋԁȥԝƸƥűγɁٽɅɎǭcǃY̝ԓƳIJķPŭޥV޷AAӁϛC̺˫̶șĢǹƌ½s˷ઃEЙۅŢƽĭȟqʕ्ࣞџ˘ۇɖҷÓګ́чĉץɜؿDŽ޹ϬؿŠ्ϸ۱ВɃɤҹº࡯ˈΓϦࣗӊсՌȧЦ˪ĈđʈȖɔJ̄˱Ϙùͮ˭ъ݋࠴ࡋڀУԼܝ΄ƷȴŸԲѓȞӹФȽהҍæӣѸϿФ™ˀҍو̓٠^͔؇ͬ˫™ӑɴƇͿƔЕĆف̀΋خׁƒȡŸÓŎ˽Ƭ\\ǜթʮɇǴ̕Նё˨ޯʠρɸϿ²ѷКƒͶϡ̨ϑqƭΝ̱ƫJɛԞջӎ؃РїɈ„ؚŵҖЏʺֿϒŏŇɃɖԭȰӷӦÖÚΊ³̸̼ŽϜ٩׶ӱɶ̱Հ̷վϳڦͿݲॖÞ੪ĞÿǑ౔СኀףဪPژ@DΌผ@̪̕јˇԀσ˨ѭȾҥѢʩۤʥՊڒۊhפͱфֹ̄ӯӸӏȂחɾЃپʹ׮ȁ͞|"],encodeOffsets:[[-99471,26491]]}},{type:"Feature",id:"MKD",properties:{name:"Macedonia"},geometry:{type:"Polygon",coordinates:["@@ńOœǤӺżȊ˺¶ϴbтˏÒ։DžƒƑƥҕh͋ǿջõΑȴšήń˸"],encodeOffsets:[[21085,42860]]}},{type:"Feature",id:"MLI",properties:{name:"Mali"},geometry:{type:"Polygon",coordinates:["@@˰ƶƘӶˊpזɻӄǖ͖ÇŴȈ⁚^ȈךƣļЛ⋈Л⋆౾dᬼᆳᬼᆳȨϿԺʉ϶ƋV՗ठĈFካҟ֗íԭݛƃ଩ï̳̗ա՟IȿLjҥš޻ΑDžʿٳϕŗɍΙǡНŔɱȳūֻڙۡp˳ɭΣÆӥ΋ůȝŁŽάʍĥơhƷʕ٭PɷŴʼnùʱʎ¬ʢĿİdzĉ˚Ǥɐ΅ΚijɴȇȂǙvȫş˕őɱǹΫäɷɈƓ„ɕőƅAµ̮žʾí̽͘ʀǓӔԺ"],encodeOffsets:[[-12462,14968]]}},{type:"Feature",id:"MMR",properties:{name:"Myanmar"},geometry:{type:"Polygon",coordinates:["@@ӫηץ›ϥࣥΟƳО݅ՔؗΈօ̭ܵ̃ƹȪу֖ڙĪҷ_ϵ͠ދң޵Сࡷăذʴ٠˯ӼæࣸͽѤ˛৔Ʊਗ਼εۢօуॕ׳ҽöԳȠ̂ਪǫ޾څॺļ̢ӭņ׭ۆÅڰ̊ŵj׾дȦęΤȐ˺Ž࢈ڂȑϐۘ¨ЦҪ۶}Ӕજ׆׸ƱçԬ̎ƸÛ͈ӮÚˮӵξȧ|ٟ“ۙߓۭijঽࢲƔȨޛՐǍʓۣز́ζƷ؞ʔ~΍܏յdẕӓȗ"],encodeOffsets:[[101933,20672]]}},{type:"Feature",id:"MNE",properties:{name:"Montenegro"},geometry:{type:"Polygon",coordinates:["@@ÁǀηЯÊˋǫÞɽ˞εǖĢƜŬҦ˚ȜƾüɠƟŬśˠě͌ǧçïƽȋɧó"],encodeOffsets:[[20277,43521]]}},{type:"Feature",id:"MNG",properties:{name:"Mongolia"},geometry:{type:"Polygon",coordinates:["@@ࢮƢ྄ܤ౬Єܴʳ࢚]֘Ͻ࠼‰ௐɁࠈגͿӶࢊࢊश΍ނįনɍLjؿஜΛߐƺਫ਼ŌࡆōࠖЗԚѕެT੒Ƌޜȼૈƒ௸פԌĝѰ˭ৌêХهק࠽ɐ΅ӈńࠤŽ٦̴ڬˏހוğ̗ڏĦ௟ŏןʅ؝։౱͙࠷ѽࡹǞҿúѳէˎ͓ƌˣי˯׽҇গ̑ఽ‹ഫ̇এҋϋʾ৭AఓԜࠥŰૣśჃȊऑmӱԀϣޠԱĢ৩ԼଅŞুƞ̡θ͖চׅڲன̀۷Ѿəז"],encodeOffsets:[[89858,50481]]}},{type:"Feature",id:"MOZ",properties:{name:"Mozambique"},geometry:{type:"Polygon",coordinates:["@@لæ৞ʁɖńגt̚ʦԌaऀ͜ڞӤƊϕ“࠷ľ݅ಿƨЫʣ׷͙׍՗Եޏ͉ृСॉ͓ࣕƵוׯ΋ȗí׳ЌُǔӱZʣƪ¦{ࠗƋϷȤƝűΓΗ̗ۗ˳য়ҕρ̳ðΟɊÉíѵّRïϊůϖí̠ƬपɓװГஂࢬ॔ɜ؆ŶúĨӶƉʞ˜غǐ׌E੠ѥ˒ЏÔǹȼϳǰ۫gÅ̼āװᢈۘӚЕɴüͨɅ¸͵ǯϷØסոԱʲ׌ζǰíઊΙ؈̣˖̅]ɽદɾٔ"],encodeOffsets:[[35390,-11796]]}},{type:"Feature",id:"MRT",properties:{name:"Mauritania"},geometry:{type:"Polygon",coordinates:["@@և־ԗؤ֍ɞГʚҵUЧǽйð˽ˏïҐɺаŀߊģࠨĵкČмɑЎѵδǾˬᾔMǃ௎ȴќ߀øᒸ᪂©F౞Ṗ᎟౽cМ⋅М⋇ƤĻȇי⁙]ųȇ͕ÈӃǕוɼˉoƗӵ˯Ƶ"],encodeOffsets:[[-12462,14968]]}},{type:"Feature",id:"MWI",properties:{name:"Malawi"},geometry:{type:"Polygon",coordinates:["@@ɽٓɾથ̆^̤˕Κ؇îઉεǯʱ׋շԲ×עǰϸ·ͶͧɆɳûәЖѵɔʮޮ˄̈LJۢǚڼƞɪɉ܌Ѕϐ࠘ƽǜɵ˶Ϲɾଡ"],encodeOffsets:[[35390,-11796]]}},{type:"Feature",id:"MYS",properties:{name:"Malaysia"},geometry:{type:"MultiPolygon",coordinates:[["@@àћֈĶ˞ΈȘýӸԓΜ֛¶֣ęϡĆ˿Öӻ̒ɵͤݑe˳׫Éߑخ঵ښįђӟ֚ś̡۠ҜĠؔȃΤƤƮۈρ"],["@@أ˹ܯƚॱ@̅ॗ͓̇љୟۅǵߑɾЕóөщ՛Òէǟַӆƕ֘؜˽ٮǀǜ܆άǂ৖Ǻ׾ڔЬՐϦѥǮ˺В¸՜œа٪אшڀͼHќыžιֆɻ۬ʧÑ֝͡¥ƮЧ"]],encodeOffsets:[[[103502,6354]],[[121466,4586]]]}},{type:"Feature",id:"NAM",properties:{name:"Namibia"},geometry:{type:"Polygon",coordinates:["@@رٌؖ͡ȃࠊȷ،˯ಒm৒ŅҞ͛Όѡۜѳ৘ǽՆۃࠐ»٢КdžԊƞհ}ԄϝŶÐ₮˜׌Е᎞ş໴΂یȒհµͨȍPéӁȍʭC՛͍ͣΎಕ̍سƒ{Ჽࠣ‡BយA᷋ݣѕҋÕՇDŽϗÔƗάͩɰГг"],encodeOffsets:[[16738,-29262]]}},{type:"Feature",id:"NCL",properties:{name:"New Caledonia"},geometry:{type:"Polygon",coordinates:["@@ېԵѨϭ͉ȫҥɪ׹ϚէѼ։פś˶β[Һ˹φ˷ˎɻ"],encodeOffsets:[[169759,-21585]]}},{type:"Feature",id:"NER",properties:{name:"Niger"},geometry:{type:"Polygon",coordinates:["@@nּॹȐОҿպœϤâТբ̴̘ପðݜƄîԮҠ֘Eኬஈϒᝪ࿸᮪ཾ೨αӀңר̸ȸಯ̾ɓ`ˋΔ˽ǻί͕ၻ«ધੳߋγૉΔ̵CեբmčЃʁµˋƻm֩ंȟ’ځҷٱʔҍ¸ʏşӯ~ӷΧѓq৯ѢЉȵѓb̿͆ࡅ̼ࣗıɕǻşӗʋ͹ÍݣٗӚ̟E˭ʗ"],encodeOffsets:[[2207,12227]]}},{type:"Feature",id:"NGA",properties:{name:"Nigeria"},geometry:{type:"Polygon",coordinates:["@@ࢍ̡͉¬͓ȉڥl҇Ղˡ؊שֆكYݍB¶തs՘ǂՊʶʴТԴėɨǔ͸ȍӾ˪ÎݤʌͺŠӘɖǼࣘIJࡆ̻̀ͅєaЊȶৰѡєrӸΨӰ}ʐŠҎ·ٲʓڂҸȠ‘֪ँƼnͬͯğƱ«˧۽ٱɛՙšѧDZȉǝי҅ΉŽыȋ͹ÿΓֽ˱ҽΊ͇aԃӭʑQЍ߷ɍש"],encodeOffsets:[[8705,4887]]}},{type:"Feature",id:"NIC",properties:{name:"Nicaragua"},geometry:{type:"Polygon",coordinates:["@@̃ˆϽͺȁ˲Ο˄сϜĤžƒŵÚÒʾ”ŀȔŬRkЮȠrǬOǺɤʜǝĒľƺIJ̊ɴbǦĄQňȪĖ|ƜŹǚ›ȆńɄB̈ŌŜŖ˾iïă§ȉĐ̫ȗ˹ěͷυ®ɏtϙŹĉýΫÌɛǣɋ ɩźƏȩDZʛÈƓǦˉêȕʼnօɞųŇ"],encodeOffsets:[[-87769,11355]]}},{type:"Feature",id:"NLD",properties:{name:"Netherlands"},geometry:{type:"Polygon",coordinates:["@@ۦyǀ˳Ƚޓɇ́ԍ@ƘࢡҥȞՏπީǩ؛âѠɲ݀ఆଲΘ"],encodeOffsets:[[6220,54795]]}},{type:"Feature",id:"NOR",properties:{name:"Norway"},geometry:{type:"MultiPolygon",coordinates:[["@@᥆ؙઍɣऄՅෛ͵ڵû΢לઃͰಫ˵Ы؝ߟωࣗȮ઱¥णѼԉɝԷ“ūփནƊɝҵ߭Hևױ࠿झಫ஁̨˹̇ͫ࠯bձ޿¾૟՞э˥ধֻۧυӛ֝Ԫဋঁ૫ȟ୏є̛ࣚˇ኶ޞզᕠ۶ဌࢂ໤୦፺ྴඦلᘼ੊ᇎπ൪­౮ۢ໖›ພǘ"],["@@ም΅๝Ȝ׆ɐԕˎეǚͮ̿ொȍ"],["@@᪖صᑟͥұأ݅ǁЍۡৣᅵԢނ̘ఽʐ࿕܂ٷڄᘎ̜Ң̋஦\\͊˼௾ˆ੖̋"],["@@࿮̏ఝҍ᝱ı៙ƖƫɴஹdँϬᣴɼ௞ȫࡘʤᑺȽ"]],encodeOffsets:[[[28842,72894]],[[25318,79723]],[[18690,81615]],[[26059,82338]]]}},{type:"Feature",id:"NPL",properties:{name:"Nepal"},geometry:{type:"Polygon",coordinates:["@@ÝαŌՕĩͩ۩aয়Ȟ٭ĂӛђଷŊયҼ߉Ю߿͆͜޼ՒϠΒȪڪʳࡔշҾť˰ЕٶǓۀσौȕঔć"],encodeOffsets:[[90236,28546]]}},{type:"Feature",id:"NZL",properties:{name:"New Zealand"},geometry:{type:"MultiPolygon",coordinates:[["@@Ȓ΋װ;ʐΡBΝ̹ϳչإїͷ̴З٭Yܗ̓ɣջӋࡗڇϓнʇޝlխˢࣱÐƗ̰Ҍذ੐ࠦժǀ׾͌ܜѰԎѦώظ͈ɆŰҶלϴȆΧ"],["@@،ࢫlָϜɯŲًڰ˛֨ãӒ͎юĭȯݗʯӫٛjɡʭþαūƻͅҏзֹ٭ͯƟɘΕŨӞ۔˟ҨࣛͲz̦؈̌ƚ٨Ÿլͻ֜vƪБΎڋݔΗת̸àҚұٺɑʂݡ"]],encodeOffsets:[[[177173,-41901]],[[178803,-37024]]]}},{type:"Feature",id:"OMN",properties:{name:"Oman"},geometry:{type:"MultiPolygon",coordinates:[["@@ֹ̻ϟªǩȧƉэļ֗ÿĻϯFԽ̻ćХȓǯԹP͡ɃJͻПɷҩĂ֗˳ϱ³˝טٿ൴ᠾ࠾֖၂ϩתv͸ʔΐFΆϞǒƩŞèմіHϖֵҸ̧؞ŋӼƳϜӕɨ˧̞ŃCȉ̩ԃƅɽΟˏ"],["@@ʼnƳDž˺ʔ˺ľñā΍"]],encodeOffsets:[[[60274,21621]],[[57745,26518]]]}},{type:"Feature",id:"PAK",properties:{name:"Pakistan"},geometry:{type:"Polygon",coordinates:["@@تϻʞ٥൨ͻ߹۷ऩůౣȲЫα̖݁̈֩ڴгܑӟ`׳ࠃࡇՃ࡝࢝ࢡউÚऑࢡռϗĪ٧ҾэǘܝᇛD֓֕؛Ɇʣ؀٭٘໻ǁിeஃŝ̈́ঊொѢéϰГƌw݊ߥφͷԔеѶඨѕࡀŲԈŅǞȂגóદĈ܎ҶӈشCĠɼٞŌ̴ý͢ʀ±ԌΦԖ՘Ɇͥ֊ߜɴ̢•͒мΜĩмȣΤӬμࣘǮ८ĮѐƺӨĦ"],encodeOffsets:[[76962,38025]]}},{type:"Feature",id:"PAN",properties:{name:"Panama"},geometry:{type:"Polygon",coordinates:["@@˫ʎǵҒȺɢɅÎƿˤлɸοÁǝ̇ͻɁǽ‡ĉǩВҗɯŅŧŭϷ©ơԈŋƛˡ¸ǝ͸·ÈɓİέCǻĩŶªǖìǠƲŲIJǩŲK͸͘ö̠̝iDZͲ›ĀæɴȵЮÔΨɄԜǞ˺ʤҬ·‹ĉҶ…ώơ˜ʧ̈́ɵĹūȜӵǁʟ˓ÒŅС"],encodeOffsets:[[-79750,7398]]}},{type:"Feature",id:"PER",properties:{name:"Peru"},geometry:{type:"Polygon",coordinates:["@@ɥљћɋࡅӘñΈရࡊທࣾ٫԰ΏۜƐʎ܅ાࠣ༄ߍီ΅Ϥ˃ؤٷպױͼ˖ϒПߢʼךڢՎIJΓʇȧx̭ΎâͼĝΚщӆΌDŽ֤ԦܶৠͨࣸࢠʾմŝٔɢĂ֒ЉˎЅϴɏӶࢣضĿҨɞ̤ƣԎð٠Ͻթࡣʤoрҁݳ œųۍlj॥ֱÓϻɉ̇ČғԕʍBΡɛƵΔݳҲԝDZί֐µ͆҃ݐuېӸÇ౧ϢĩӄƠܪടǷ˵£ןg܍͟пƮ̵ȕ˯β۹Ջ࣡"],encodeOffsets:[[-71260,-18001]]}},{type:"Feature",id:"PHL",properties:{name:"Philippines"},geometry:{type:"MultiPolygon",coordinates:[["@@Đ֏ºҽ˹ޑ̫ࡨϽэˎإʉϿ঩Ӧɿ؊ʰЎՑЈˁΑЃثҵƑʖ͢۾ՌʀҜ̈́̔ϝٔɰƎϒרv·ٰڼЋêхÐ̱"],["@@̟ˡˁՍ˃ʝԫ׈ǦɤɂɾĢԸҨ¸Ɖ֣جߺāߡ"],["@@ૣߕЬט؈԰Ԏ׊Ѱ࠲Ʈۅևҧѳֿ"],["@@Ԏʹ՘BgΗϳΣՕʧ‡ϸÒєŽА"],["@@ʀभ٫ɞj˭ȶԯЍȋ•עʧªƁԘӶãY͈ԣٜ߮mɴ̻"],["@@ɟܩέоѓ٘ܚ‰̡̈"],["@@ԮʉʶɖüɇƍΑ˼׻ɛۥӷ˥ƁڳȊڝѾġϊIJਾүăҙ˜ȫēϯٻЮ̵Ѵɍ̯՗ԊރůлȆ¨ΎˀɊʣȘŇ̡бӚűμߨͺˡĔೄ˜ހԘA"]],encodeOffsets:[[[129410,8617]],[[126959,10526]],[[121349,9540]],[[124809,12178]],[[128515,12455]],[[124445,13384]],[[124234,18949]]]}},{type:"Feature",id:"PNG",properties:{name:"Papua New Guinea"},geometry:{type:"MultiPolygon",coordinates:[["@@ɽčε͔ρՔǷ٘ŜĆĜʡʬȏРՑЈ˵ŝɽ"],["@@ѯçƃɽҟȱћȟѽBۏʔӑɺêʺݬũҠàŶЖŦrĆѽӐÜʂ˼Ҹ̚ġӸԌfǜƏgү˯ԡ"],["@@ݤտղࢻӖ„‘ω٬ƛʥǁࣀΝġʏ֋ÏȷɔܟĦࡕŴٷ՚ӉҦѧ݀ભπ܇ʇԡˣńإڇ˿һƖࢅ–aᩒaᩒภ׃༊ӓׄїҴхŸӵඔԱȲѽޛěȄ֕"],["@@ʿɡǁӸȝ͘ϝ˞ӍΪ؇ʚɺȮҒɻ˸ȁΜȫʹΛ͊ˏĶѧ"]],encodeOffsets:[[[159622,-6983]],[[155631,-5609]],[[150725,-7565]],[[156816,-4607]]]}},{type:"Feature",id:"POL",properties:{name:"Poland"},geometry:{type:"Polygon",coordinates:["@@·՜à̂ȹ̧҆̚ɺɤȝђָʘ಼ϴ੒˴࠼ƙÚȱ߸Yਚħ໶^њěȬʵšωɸ͋KͯԋǡʸϳfϏцܻěɽзįރۥɒϗǿ¶ߙ͔؁šЇĒӹǵч̖Ήŕ³¼ϭаر¼ăˀֻĦűɑҗǨÀɴػòЉ˔"],encodeOffsets:[[15378,52334]]}},{type:"Feature",id:"PRI",properties:{name:"Puerto Rico"},geometry:{type:"Polygon",coordinates:["@@јõưǕɋɃمLӫ‡·άŢŬیK"],encodeOffsets:[[-67873,18960]]}},{type:"Feature",id:"PRK",properties:{name:"North Korea"},geometry:{type:"Polygon",coordinates:["@@Şƥ͉ºη˵ʣ˷Ž׽ѣȅƫƧ̓ʝ֓ƏηɥηįġͰƋӈσŧȭΧÇץ¡͝ϛϑˆÁùСdžĵƿʙé‡ǀɑüɥƆɰφȤİõƶɆҒÅƎөĠЇɤۄբऒҌ־׮Ўˁܪ‹ſѺಚβͰҼժӹ"],encodeOffsets:[[133776,43413]]}},{type:"Feature",id:"PRT",properties:{name:"Portugal"},geometry:{type:"Polygon",coordinates:["@@̦Ɉ΄ŬɂЫӺDƞłӪ‡ɼуϱɩYٽƍū‘Їγçʹԋɵտ̄ʡřɫ̵̿ê˥ͷɓѷŠџġŸڂÿԬϓþȩ͈äռͰ̨ÒͼǪԎkΤǙ̠™˲"],encodeOffsets:[[-9251,42886]]}},{type:"Feature",id:"PRY",properties:{name:"Paraguay"},geometry:{type:"Polygon",coordinates:["@@ͦ৖tҌЖ݌าʔޮ]޴їbʵʞҳÇଛࢲLJ΄ǐ֦ɩǀʣþޓİ͓̼›̀ƌ̢ƳAҥŕӻǑӛƍݏށ١ړƇऻŸࡑɮࠢ౨ťψࡽ͢ਅبۉŸ໵ൌ"],encodeOffsets:[[-64189,-22783]]}},{type:"Feature",id:"QAT",properties:{name:"Qatar"},geometry:{type:"Polygon",coordinates:["@@ÇؔɨѲɰĜʬˁdӯǽӳɵÑʫǖ"],encodeOffsets:[[52030,25349]]}},{type:"Feature",id:"ROU",properties:{name:"Romania"},geometry:{type:"Polygon",coordinates:["@@δǶԴġՠGϸȳ˺źبĄɄȠΠ@ʰćʺʟˊΟӞԁ€ρėΩưϥϒƹЂƊϠƟpɏПǹʯĀɻ৥ӳĖ̪ؑফțзɋ௽¬٥ƀ͙ÕʍΊƵƦȚƘȷŀ˃ȋөʔßΌԟȢĥˌҕͤڪǂԖ֮Њ֬ԢǮ"],encodeOffsets:[[23256,49032]]}},{type:"Feature",id:"RUS",properties:{name:"Russia"},geometry:{type:"MultiPolygon",coordinates:[["@@ࡌ๫కˤԫ்ࠌࡳyוُԒսٱƻ۸Ĥࠊħ࣢Țٌš૴ӯࠜôରަϮͭϴϐŠɔ։̆ߵuࠟΎࡑ"],["@@໵]ਙĨȒτ୊˚ࢢƧψƃęɱäɉ"],["@@֦Ƚțؐᗸű࿨޻࠭λ൛ēsࠑͳǩ޽~ٗ̊ૣʖȉθ࡟Ǝॗʼnҗ̎Ǽ̸৓ȥϚЃӉΣ@„Ꮪٛᔺ࠳ïԷ"],["@@ः©ƭˌੲΖ@ַ"],["@@ળ»@ָň–܈E௒ʉïŗࡽȩ"],["@@ౡMႣĤƧ¬ߘͪੀþஞ͏ĸə"],["@@ॿͩഉø༛ͨȪ˖༨ųᑔɗ"],["@@ډرᶽzඃȣမղҎ׀૎ǂᕞ™ᴬѽ"],["@@ӹóᩣŊɟώູɦūҒ࡮Ƕ…Ҟသܒޙĺ፨݆ɩϢሤѺ᪪բ᫠ǀ෴̸࿐Ŋאͩ֟ʻᲗз᢭Џᤙߝఫࠍ೉߱Ǡۥྎۏ"],["@@ɨгސȲឤYቈЧڬ̿ȽѧङʝᕅүفʟਬşఖɃݴDŽєաτɔഊƂ᧪ƑȴϽ↲ů´ٜᄼƥഄLബѷϮ՝ӹΙੌڋ೔Ϳ߸ࢦഖϙ෢ɦྼʵؤʀൖş؅ޮૐζ䢀ձܐӿᔲٛ₎DŽာƑ۪΍Ĺؙਜʇ૴Ǥ๰vཚǑཪĢะݛਪˎڷ՞ϐώᧆɻფºᝂБ୲ν@”MKઇσઝÖݶҁԄەϲɧĮΏɑɝ༧Ǿ᚝مݛĭ౽ן௛ԧ̱ϣய׊ᔗڇϣ̸ߵΫ૱Ř˓ց৙߽Šͻड़ȋő௣ޭ‹Ϋ۱Δα฽ѕ̅ॡభȳʥ࡟ே޳ׂ̳έ௬ҵለИ୘܀ԆªϾರȊຊ੒คࡺຢڢڮஆ৷ëԍۗᒉइۍਖᓧ˷ᑃටۚԧሙɕಝēÔ؊ಯŶ਩ЭᢵƠ᪏ʟᨩ࿛ủጝ೚ŁаՃࠄȅ՞оईÃௌऍ†܍ځ࠽ë্ϛഉ్௓˯ׇଙ঑ଇॻթӹ૩ӱՉYՇФૻؙſ˩ŝƦKѐіxŦ঴ɛܚܞ̒৶Ʃ֢ࠈ˾ऄ͚̮Ѵݲ൷ʛܯͧ౧Dͻ߄হװหˎ̵ࠖ̉Ԫ̿βԯࡐ̲݇షʢ૛uਯƱۛлҤȥXҩұˑݷࢻRσஅՍ৙̈́োéѯˮԋĞ௷ףેƑޛȻੑƌޫSԙіࠕИࡅŎ੝ŋߏƹ஛ΜLJـধɎށİवΎࢉࢉ΀ӵࠇב௏ɂ࠻Š֗Ͼ࢙^ܳʴ౫Ѓྃܣࢭơ͡çѽԤઍőΧΦחnjЙӠҩưிɍୃӜ҃ѯሟᒒੵٮ̮˂ᑋߍ߭³êҞઅ˺࢙ȱ˃ࢊມǺݯΑᑅ̳Чȹḭ̇ϫ˻؆ֹ߭ɓǀɭ߭ХസֿɁЉ୻˜ʓʟ੹Ѧ೯iࢻΟহͼᇡ׊ಽsჃࣳĿؗࡹӤڡउʖǡӝُ܊֫ذx՚֗ďѝѐƋϥӽ߿Ƒ࠳ࢁކߕĉ֣ࣼফԇ͹ƝɇωÌֿԚɿ†ՅȚʳΈ޵ǮԙƁƥƼଥЖఅƌ܃ƞĹıੱ܂य़̈́ܩӴؒƈۤ۰ҹͪఌ΄uȀݯƉ‚ώѠɼ߼ÖƄ˪ȅҪ΀ѰWʚఉ˚ӭUԯЀ١ƃ੩̐lǒ̗θڟ¤éʼɀǞ՝ӈࢋąʭ¦Ƀȑ̽”ȷ՞ȟ˨NJĀڴ‡͞Ȁʍɢ֥ƪ¼Ʋ΁ƴՃվǸɨĉЂࠑȨѱijšȼࢭɂˑӸíТЙȖάˊʝ޶װӞųƤक़ҬࢡЎᅢ੶ޮӠ͂єగּΆնݳش֢ܜ঍ग़ޢي౿֔ŬךڶüොͶࢀ̈൦ԕᘨȧṺो٤ЋÆ֓टѳ൏ɡ⏷ٔ؟Ńൌ؛ÂϵÆ࡫ઌʯڂɓňРԑΰ՘͈᎖Թ۾Ȳ֣؜ዦࠖޢµ޸̋Ӫ׀۫ԄЪԊءԶᚠˑӔҹ੡ĻNҳڌ˽ಜǼȶ՚ჶАᰪܞي£ࠣԙਬĕ׼˼༾xఢΐफ़ԏॖ֌ࢡӢѪˤ២ʫ୒ʿᴾॣ֚ѰࡡѺ{ǴৣĈˢЌ҅ټ}ː༄ݾրކزǒᕮɛǬұߕڽԺˋ˒חȏଵऒԧέ֕࿫஝०ŭ̢ͮऎɎɞжܮЎөӌϼֈࣿêȫҲڢࡈણۆຒ֦șװмnѴүͧ߷࣐Ƶϥ؄ඤͦლ¬༈ӏݛ۪ċࣆศǞ፾™ᆘŌہѮংւॲx࿎иᕠŐ˪ɲᕂþیȋሴҀ໲aɶδߤΨጤΈ෸˗ଥȷበŹ"],["@@ⵙ͕ໞીےĦقÃᒈӋʟͿ"],["@@૽ōݱÛśƏঙƑ࣫ȦӐʾል~࿞ƶ౨XǢɧӘȬߊƐఞǿ͗ŷ"],["@@ᆳĿᚉʎඅ͎٣׾଩ǔᔆָᆎȎ࿌чኬ߻ȹݯ"]],encodeOffsets:[[[147096,51966]],[[23277,55632]],[[-179214,68183]],[[184320,72533]],[[-182982,72595]],[[147051,74970]],[[154350,76887]],[[148569,77377]],[[58917,72418]],[[109538,78822]],[[107598,80187]],[[52364,82481]],[[102339,80775]]]}},{type:"Feature",id:"RWA",properties:{name:"Rwanda"},geometry:{type:"Polygon",coordinates:["@@ͬӃµӵʏŁѿÆʱӍԛàþҠŘތԄʎɺȰďԈʸ"],encodeOffsets:[[31150,-1161]]}},{type:"Feature",id:"ESH",properties:{name:"Western Sahara"},geometry:{type:"Polygon",coordinates:["@@oҊŸ@@ÉeNjEౝ᪁ª‚ᒷ޿÷ȳћDŽ்ᾓNǽ˫˜΢bCቆäĶ̢ΆϘˤୌୠ࣢Ђ੖ˀÖ˜ټۺĜ̦ʼnϢ@˔ȒԲ‚"],encodeOffsets:[[-9005,27772]]}},{type:"Feature",id:"SAU",properties:{name:"Saudi Arabia"},geometry:{type:"Polygon",coordinates:["@@ʼnΪʩʨÝͲѡ̞҃۴ʁۆׇ׀ϑƐ֋ߠīא–ӾӕञϿ͠ґǨˡӖ°ȎɹѦʕȊ͝زԟڴѓ־лIžҦœ̌ļͲनƅζʶȪ̢ٚŚƒˮˤƜ࠷ࡀ၆фdžŴৢɩబיᛎၕ༠ãݠąȾЏתv͠ܥаȓƠִ̏Λ¼΍ċ˩ł˯ʎɽŐ˟ŲȵʬǕɶÒdž͍Žș࡙͐ᡌщǞDzϪש֕၁ᠽ࠽ᝑ͑޷ϙ׻ࢥϹƕɁˬ͏§߻ĎƷČॹmɫùΉɔɝЭĒΟρˋ"],encodeOffsets:[[43807,16741]]}},{type:"Feature",id:"SDN",properties:{name:"Sudan"},geometry:{type:"Polygon",coordinates:["@@śhdмĵ̀џͨĵ؄ĶبϳÌÍȇԍ©Ȭʕðԍңңл؅џđ۹Ӫͅǥđʓџǃ…ǥ࠵@řǦ؃†̡ƝɳîѝӬƟɲ؃ŗɱϵɏݣ˿ǁʳğå ̅ʎÃʼƌΔE΄ӛՀĩάZȰ̱ʜUӦǭ͖̍µĎ̰ɒΖħΐˢʴǫȞɞ԰ϨئܦÏ¥ ZΚॲH@း@Ὂ@ῼ@˔ࠗȁƳŪࡻ্̰͌ȷҠ̳ыӑأƏ˅ʳĉ֑α௿ĚͳƅܟͿࠟԓзέٛč΃Љɽʝ࢟Dij"],encodeOffsets:[[34779,9692]]}},{type:"Feature",id:"SDS",properties:{name:"South Sudan"},geometry:{type:"Polygon",coordinates:["@@Xٽűʯѿq˷ӏԨÑюХƨͳϦșӼࣳ֫օԫԇԫϭסFگȟՕȊ΋ɭ݉֐ȥάҵDZϱÆɣƕϗĸԗۚƉˊعͪɅԌΕζ֟ѬS˘ҡͼ֯͠ʴĠ̀ǂɐݤɲ϶؄ŘƠɱўӫɴí̢ƞ؄…Śǥ࠶@†ǦѠDŽĒʔ͆ǦۺөѠĒм؆ҤҤïԎȫʖԎªÎȈϴËĵاĶ؃ѠͧĶ˿cлŜg"],encodeOffsets:[[34779,9692]]}},{type:"Feature",id:"SEN",properties:{name:"Senegal"},geometry:{type:"Polygon",coordinates:["@@΍ٺн̚φDŽРמȦќ˾ːкïШǾҶVДʙ֎ɝԘأֈֽžԹǔӓ̾ɿî͗ʽŧ³қâÙģȃk׿ȲЛV༇–ɥħ˥‚ѻƋƏ٢ވkȬŞƮR̸ȘήǯκcζȌǝʐˡƙʻJͧȸˉ_ȍȥࣵy"],encodeOffsets:[[-17114,13922]]}},{type:"Feature",id:"SLB",properties:{name:"Solomon Islands"},geometry:{type:"MultiPolygon",coordinates:[["@@ɾ˿חN͉ԬԈȯǜ‰"],["@@͝mԧĎǫżÀͮֈƁ˜ǭƎə"],["@@ųƹحܰǫԈ˺@̠ڥʹЗ"],["@@–ǛڅΦҟ̠̿˪ŰĐϮȫېϭȢˉ"],["@@Ǘ³οȒ·Ί¨ƖԈΡͰ˛"]],encodeOffsets:[[[166010,-10734]],[[164713,-10109]],[[165561,-9830]],[[163713,-8537]],[[161320,-7524]]]}},{type:"Feature",id:"SLE",properties:{name:"Sierra Leone"},geometry:{type:"Polygon",coordinates:["@@ɧØ؁ͺѩ҈Ƨ̬Ĺت҆τĬɺƞǸɶpȜǂڦCɺ̛ǼˁʓƈɗṶɴ´ϹϹϛҗ«ʓȩˏ"],encodeOffsets:[[-11713,6949]]}},{type:"Feature",id:"SLV",properties:{name:"El Salvador"},geometry:{type:"Polygon",coordinates:["@@ġȡӡ^̡Ą΍ǘұÀʃǶ~Ů˾ɄǀĢ«IJȠ¾ʜëǸǙʪƇŒœτĴǤÑŘĝÏͳ"],encodeOffsets:[[-89900,13706]]}},{type:"Feature",id:"-99",properties:{name:"Somaliland"},geometry:{type:"Polygon",coordinates:["@@ϛԩד۫۹Mᩧা͍̜̳К̳ҨǾ̖̲҈˚ƹǒΏϜΗкGߊɌࣴĴ݌ʼиÆ̚ƶӎˆKaE΋Aࡑ@ѫ"], +encodeOffsets:[[50113,9679]]}},{type:"Feature",id:"SOM",properties:{name:"Somalia"},geometry:{type:"Polygon",coordinates:["@@ѼĎЊ˾͈FpɵýӧHѳǯ̣ʁࣥЙयԱ੷ܝ௷ܓवধ଩ࡁڹష࠯޳ٕँৱȗѷȍȣӽۚWᵤܾ॒ɰˆբfݠפબšᛜᡄה۬ϜԪ@ѬBࡒFΌLbːhϰŰ"],encodeOffsets:[[50923,11857]]}},{type:"Feature",id:"SRB",properties:{name:"Republic of Serbia"},geometry:{type:"Polygon",coordinates:["@@Ԡȡà΋Ӫʓ˄ȌȸĿșƗƶƥȷȏø̫Тγ͋ʿƗˋĞijƑšϳa˹µƒØĴĴĦȴšKǍƼƑ ŋƆƽÀšŠƯ±ś˧ȩÑèð͋Ǩ˟ĜūŜɟƠȢšŬЄЛ͔ɀτ̥Ë͔́ˉʈȱ͘٢ɚԾ™ҖͣĦˋ"],encodeOffsets:[[21376,46507]]}},{type:"Feature",id:"SUR",properties:{name:"Suriname"},geometry:{type:"Polygon",coordinates:["@@৔ǙĞưڶÔࣚɥѩܟâֹͤӽƥίóϩɉΛӓDzЇđ͹öčʏƘǗ÷ǡҙèԡܴōӄˏBωؐƺѠ¯ȤԜɖƈݲ"],encodeOffsets:[[-58518,6117]]}},{type:"Feature",id:"SVK",properties:{name:"Slovakia"},geometry:{type:"Polygon",coordinates:["@@´»ΊŖш̕ӺǶЈđ؂Ţߚ͓ɷɓǏ͹dzđ࣑ʮ˟»ȟȡЁĿěÄХŽͭ}ãǙ۷Ļ̱ĠёɌċ̆äńŢȂόa˺ĔxþLj¢ÆȒȖ˜žưʢD"],encodeOffsets:[[19306,50685]]}},{type:"Feature",id:"SVN",properties:{name:"Slovenia"},geometry:{type:"Polygon",coordinates:["@@ۜÝъȐܾtLjƘƘUǎ˳ڝɟć͹̇đHɻͣh˷ƎƷƙב†ȈúȫΨĞа"],encodeOffsets:[[14138,47626]]}},{type:"Feature",id:"SWE",properties:{name:"Sweden"},geometry:{type:"Polygon",coordinates:["@@ࠁוƀԥ೹ڭྱܡؓஃײףߦүޗॅ࢑ȝ͍තӋ޿৳ĆӅڗঃˉߐ۳॔ٓஐφӜּۨ˦ন՝ю½ૠղ߀࠰ä̧ͬ˺ಬஂࡀञֈײ߮GɞҶཔƉŬքԸ”૪Щ಼ֱv಑˴͛ฃʃ"],encodeOffsets:[[22716,67302]]}},{type:"Feature",id:"SWZ",properties:{name:"Swaziland"},geometry:{type:"Polygon",coordinates:["@@ǡύӭěԅҖS̄ɰ̀ĂʔʐÒшƵŰϕðω"],encodeOffsets:[[32842,-27375]]}},{type:"Feature",id:"SYR",properties:{name:"Syria"},geometry:{type:"Polygon",coordinates:["@@࿩ࣅऩͬgNŖŶ_ΈȸҠҜ̈́Əͤϗ¨ÿٞȶΌɤȀɤȀ°Ҹ˞Ǐऎɺ҂ƿۖFॴ̀Ґaक़žїԽҡȹĂؗͅ৫ᇵ࢓"],encodeOffsets:[[39724,34180]]}},{type:"Feature",id:"TCD",properties:{name:"Chad"},geometry:{type:"Polygon",coordinates:["@@ĎЄաnDզΓ̶δ૊ੴߌ¬ન͖ၼǼΰΓ˾_ˌ̽ɔȷರࡔҠ…ྑ…ྏ¦ ܥÐϧإɝԯǬȝˡʳĨΏɑΕč̯̎¶Ǯ͕Vӥ̲ʛYȯՏƛэͽ؉ࣹ߅ϳ߹¾ʁûĊ̏ѫ̋Σ͟੓͏ȽȐƓhƹɍۛÙƀɪ˅ׄşΐλƜӷӪǼІϦċʂÐҸSқކŒ֐É֐ͭՠ"],encodeOffsets:[[14844,13169]]}},{type:"Feature",id:"TGO",properties:{name:"Togo"},geometry:{type:"Polygon",coordinates:["@@ڱdzȇ̎ɡՔãкȆݴɁ̬ăڎD؎ΕѠÖˀ݂kŅѵʲʝ̈̋ŽЭǜǥኝȺׅ"],encodeOffsets:[[1911,6290]]}},{type:"Feature",id:"THA",properties:{name:"Thailand"},geometry:{type:"Polygon",coordinates:["@@ݭϬܗeŬڈ݉Káऋґ௯˙ݏÌ؋ն΀ދưܭҶӓԚĭѤѧ˝·ևĵßќۇςƣƭͧ͒ƝжҁӄПЌƏӳǃҲĠԾʚ߬ТࡸҤ޶͟ތ`϶ĩҸ֕ښȩф̄ƺ̮ܶ·ֆՓؘН݆ΠƴϦࣦצœӬθӔȘθʷ´ԍ֨ȷࢭpݫࢰԆʤƧӰzǜَ̊ÍٖڽÀࠥںܷ›܅˙ϛ޿ŦગDž՟ۧȤ১"],encodeOffsets:[[105047,12480]]}},{type:"Feature",id:"TJK",properties:{name:"Tajikistan"},geometry:{type:"Polygon",coordinates:["@@̭ʷࣳƖāӛ࣬Þਢ˗འŶɈާˠĐԜȓ‡͛ŴӍࡿBׁØԻϕύĉ̉ǯͩˠþ۸ʩ¢ĞʲғȐα̇ė͹Żūԇj˕ϩ˯nj؋ˑʱĺӀࡘǹض؟ȨɔφۮŸЌҬˌբ૲ȜǩϵŤɹΎv"],encodeOffsets:[[72719,41211]]}},{type:"Feature",id:"TKM",properties:{name:"Turkmenistan"},geometry:{type:"Polygon",coordinates:["@@ñۼطŠॣݔڣĠगюׯþσƽ֙|ׯӓ݇NjƻרŪ࢞ٽ˶Ɏֺ֏¸Ȇ۾ߊȵ݈ˎؓԎʉӔڱɋď؛ʿհψ˨ॖǪ֨ɻךڅњ¤ॆ\\Əцܖ̂۾ӦଆѹĜڡ͐ǣࣦžˮƳаࡽ०ׇոЃ࢞Щ૤Ϋwԥʩ€Ѕɤſ̙۽NjǙڥӁʭڏŵǫϟهŏࡩ͈"],encodeOffsets:[[62680,36506]]}},{type:"Feature",id:"TLS",properties:{name:"East Timor"},geometry:{type:"Polygon",coordinates:["@@IJȤܢȌז†ˀŀ͆Ľ̯ɫ࢕ο۳ʋeʬďǔ"],encodeOffsets:[[127968,-9106]]}},{type:"Feature",id:"TTO",properties:{name:"Trinidad and Tobago"},geometry:{type:"Polygon",coordinates:["@@ӚŊǮ‡‘صۭġƯúʒɲiͪ"],encodeOffsets:[[-63160,11019]]}},{type:"Feature",id:"TUN",properties:{name:"Tunisia"},geometry:{type:"Polygon",coordinates:["@@ΩພԭͺQȰۉԄóنԮҶȢۚƃߠǠќࣶͺךĵ}ы܊̲ÒljпЫMϱ̆ȽōܫփхDŽқѤaɄЍ͊ſ³٥Хʋʵˏֽ͓ĘΑïΟЧț"],encodeOffsets:[[9710,31035]]}},{type:"Feature",id:"TUR",properties:{name:"Turkey"},geometry:{type:"MultiPolygon",coordinates:[["@@஺͗ঐżܤõলѬࣆ¢ߴЭƜ̑ăУزȻͨʕֻʇˀ५ǏʻҠڧЕƙ̏Ɋ঍ňίŽॗŽҏbॳ̿ەEҁǀऍɹ˝ǐ¯ҷɣǿɣǿ̱Ϡ͈͂ԟí۱ȖֿәౣĥڹҊࣟ†ȗΑׇij߻҄ࣻeӽ࠶ؗҰЦٸՓВठߨಒ’Μྀٔŏ৞հ঒ʄർlุף"],["@@۫ҏ˃Ϻ\\ǦȦĦʺՂХɞࡦ˄ܤőĴ͓ܼ˓Ƶȵি±Ωʷ"]],encodeOffsets:[[[37800,42328]],[[27845,41668]]]}},{type:"Feature",id:"TZA",properties:{name:"United Republic of Tanzania"},geometry:{type:"Polygon",coordinates:["@@ƚġᵂႋÌӣ஼࠿ϱਙ¸Ӊՠ̩~ɓɳԓ¶ʭÇГ̌Ճΐ̰ࠡǿڝӣࣿ͛ԋb̙ʥבsɕŃঢ়ʂكåɽଢ˵ϺǛɶࠗƾӉʨՕƘͯƘΗɈґ੖ӣҺǗӤČѨƯޞΎ ̨̦͜ѬȺǮS˘ǷȐ·ͨʐł¶Ӷͫӄ̎Ķऄ[ႎà"],encodeOffsets:[[34718,-972]]}},{type:"Feature",id:"UGA",properties:{name:"Uganda"},geometry:{type:"Polygon",coordinates:["@@ः\\̍ĵԇʷȯĐPوȜ͎²ڬǰϸ͎Ѭ͔ɠ˒̘͵Ŗ¼চΌɮՖȉڰȠעEԬϮЊ׍İсτ९̧ؓЯ֋ʉͽTࢹႍß"],encodeOffsets:[[32631,-1052]]}},{type:"Feature",id:"UKR",properties:{name:"Ukraine"},geometry:{type:"Polygon",coordinates:["@@̾“ɄȒʮ¥ࢌĆ՞Ӈȿǝêʻڠ£̘ηkǑ੪̏٢Ƅ԰ϿӮVఊ˙XʙͿѯȆҩƃ˩߻Õџɻύڡã֑˕޽«ܣ̻¸ԹЪȭࡨ¼Ǐ̛ँơଛӟұǠȄЂࣽʘƨLjߪ˪ʑȔಯɆË̼ީĻ̷ҧٱةϟƠЁƉϑƺɂĞƦ˾ɲˎÑƮǬäĊśӸ{ɞØƽĎÐŲ̉ɈŧΘ̩ƐÒ˶ϝɦΉŽأʾ֑ĉȧŭΟ@Ƀȟاă˹ŹϷȴ՟HԳĢγǵÍɤұɮǐͺɸɔȀµɑϘބۦиİĜɾхܼДҢɪٲnࡖßबȫڎi͂ŧ̀Ʀɚȝݸ¢ͮąÄцʶȂܞº"],encodeOffsets:[[32549,53353]]}},{type:"Feature",id:"URY",properties:{name:"Uruguay"},geometry:{type:"Polygon",coordinates:["@@ղĚࡆٯ̺|ࡺ՟ڈҫӠֱχЉɸӇεՇॉұاǚғěޥΰ֫ԟҬÞլǾȈS࠸ɤࡺȾڦ"],encodeOffsets:[[-59008,-30941]]}},{type:"Feature",id:"USA",properties:{name:"United States of America"},geometry:{type:"MultiPolygon",coordinates:[["@@ũƕȽŤ|ɾƓ̨¦ĤƤƎÍǔ¸þÜe͐ƙƬñƌőɊ̍q¯͟ǵˏſ"],["@@˭ÑƟǮīèQÀĈî̘āɘŹëĵ"],["@@ĝ҉|Úĸа•"],["@@­µÓŻˆŃȒ’ɤŚêÃʐ˥"],["@@ıĉ˱ƴªÖŸĈȘijȝ"],["@@Ƭңʼƛז½࡬ƅࠂʹڼŊਖɓ˞Tݨʄ߂̧ࠒ͗ں˩ٶˏĈəȢĉ½ĉɦǎĔ¦ȣǜƅɴ@ŬĹĽƫ࢖ЁǶށǚܳʗӹЁҥȁ̍mēĦť˸Ɓɂ@ঊ҆ࡾƀસмfĐ÷ʰƉǒϜƆࠜHޘAˎ͞ŀàࢶ؄ϜƸ౦N໾BĎȺː¦Φž̖Ϣʲٺٚي˨ə֜ƜώʏAଧռӅƢ˝࣋Пࡷ̃ࢱʝѻӿƛȋSѽˤѽΒsė̬ʦȇãʇ֥ƋЗhةƥλ¥ӥ¥۫ʏఀǂʠǃ୳ʥ՗C|ĺʭɷʚǹ׽ؑ٧×Ɏȁª˟ɀǪҍȼƭ^ͅˏ͛ҿڡûʺֲѕ͎įۦljεǴՑևƀׂ˓˜ߛʊÍĖ̃ŠࡁՕدࢇʝցӱнÁэ̱ţ˭इձӁЍЅӽŻׯƪ׍ˬܗώשLεЊঅ֥—͛ȿԡʣŃЯĺƁς͋ȖѻܢϹٞű͢Ǥ֐ɽҦٻ۲͟źࡑϡƭ¦СϼՃȺोŁݗĤٙÍΏſƲɟaͽǴǓLJō̵Ů́ǃ؍€طѺܻĿ؏ȚԹÏۻȝއح࠳γҝБȕϗUׅ¨ЕDŽ˹͝{׭ȂٽʺɽЄȁטӷӐ̃ӰуֺףͲۉgՉڑۣʦѡʪȽҦ˧Ѯӿτїˈ̩̖ป@C΋ڗ@ဩOቿפ౓ТĀǒ੩ĝॕÝƙіխӚϻĴğʌһ¦̝ɪޭĊɉƌĹҢࠁࡊ۩ୠˆȚχˤٯ۴řۆ҃ҞȀۢ…ܜˍ٢͠ߊĸނĺނƱૼˇܘʓ϶ĸǐ௒˷҂ߋȺɜƇې˷ێᛸ@᠂@ࠜ@ᢢ@៚@ᡀ@ᡄ@᭰@ᮞBაAF͔˴J"],["@@࠽͋ѕɐŽЀބ̘҆Ÿ֐ÉΤʻܫЍ"],["@@ԧŽսƾԛɮࠦƞښùĂ͑"],["@@԰DžԾĒڸɛ࠲őéĝُDZٕǾ͋Ʋݍµȧôº̈́"],["@@؊ϛώnjහ»¹ȕ౾ƛࡨČᄚ˅ྤā٨ʼn૦Ǝౢʧࣲŝ@@MᷱIⷍࠠ{ࠌɵהρݜցࠈҺࡈ˖Ҁѡ֤·ޒϙՂ׽࡮य़ේ՗xՋұЙҥ͂ݍˌʃܺએںҍߎ߯Ä೷rটʌ჉ࢎߩDŽ฽̜୑í࿻ϬৃΨटǯǦ׏ҫÁঁǫ݉˱झdzťӶϚࠚࣀʶɱɂੱҵֵ֑௅ױؚСߏ׿ࣗΗࡁʱȻωಽѡ˅ϿছΫֽÞ޷ɻ࡝˹ۧ˫෹ʉſƘऀϾࠔʸࣆҠਬĨвΈ୘ԊȈǚب̒ƢْђӸॹʫ˓Ơҕ̧շюɧ̝̽м࠿ͳԩBïԄƲ̮ե̚થLJ܁ЀַȬIӈ٩Ϊ͘ӘۆҸ̚њںÖ־ƇڴМ؎ï٘ʼƻϨҹưج͖ԩWࢻǽʯȃڏȄஏĥ௷ȬΛ͸੟Ӧ୾ΘመШ۔@ŕнᄢŽڽԶਕ͌ױр߫ΨଽˈҺѲ๰‚ਗ਼ϦȨФ࡬ЎࠊĪཪώޜÉಐ҄ౚǭ"]],encodeOffsets:[[[-159275,19542]],[[-159825,21140]],[[-160520,21686]],[[-161436,21834]],[[-163169,22510]],[[-97093,50575]],[[-156678,58487]],[[-169553,61348]],[[-175853,65314]],[[-158789,72856]]]}},{type:"Feature",id:"UZB",properties:{name:"Uzbekistan"},geometry:{type:"Polygon",coordinates:["@@xԦૣά࢝ЪշЄ॥׈Яࡾ˭ƴࣥ͏ǤěڢଅѺ۽ӥܕ́Ɛхॅ[ᶾᓘӺƾïದ׻یͅߤݵঢŪ෸à৔ؗÙࡅЦMǢۍ੬ɲЉ̺Lπ׺૎הӖƺʠĉ۵խئ́ײȾ়ѷ੽؁ٕĊ΍uţɺǪ϶૱țˋաЋҫۭ ɓυؠȧǺصҿࡗهǰҳN"],encodeOffsets:[[68116,38260]]}},{type:"Feature",id:"VEN",properties:{name:"Venezuela"},geometry:{type:"Polygon",coordinates:["@@yȣӱĭ˜ϡYѭυӥ͆ڙδÆȌ؈ʻ̒§َਸ਼΀řІ̎ˆ̞ןל_մҵ˧ݮQ࣌ĔӖϕٞĻҼʾXɄਨ¼৖\\܉ʛ˼Їڦ×ِЯƆڧѬn͢ȣڕӱó̫˾̷ȽƽԫƉjϱɫɱّ֪Őʁ̭͍ऱ̽׿Žʏȣڛɀثņƿýϔɑ‘֝ŜՉ܆ï°ǭ׷ʅĭΣΉƏسȝNjʱٷÅҧѼʯ࠺ɟ̧̌Ȅюм…ȊʅʠǛ֒à׼Ȉ˰ƲҎ̓Ơӏĩ؁®ͻęסܢӥńઉăȧ̊ȷê‡ǬĴ̶áͺȃȂŅϮѡÈɸӮĺ׶ʔ̸͘ʌɈрդƖ"],encodeOffsets:[[-73043,12059]]}},{type:"Feature",id:"VNM",properties:{name:"Vietnam"},geometry:{type:"Polygon",coordinates:["@@૭ܗ۫ߍȁ׍٠ࢭ޺ળނԱԞګϪ།ŕ๓۫փ१եۇ۫਷ޱ̧ՠʀ֬دӌܬ͸ࢦÔσԚප٨ļ৖ț֖ƶࡀɃצٍאՋ݌ۥ঴৓Ԋʊ̠՞ɘ͙ܺਙPϕކӭڐҊȴڢIࠈĬܒ҄К̿ސƵƃӛАͿࡎɓ"],encodeOffsets:[[110644,22070]]}},{type:"Feature",id:"VUT",properties:{name:"Vanuatu"},geometry:{type:"MultiPolygon",coordinates:[["@@ˣō˭ςŒɤՆӗ"],["@@ƌڱɥŀǩ­ťɴi٢Дʵ"]],encodeOffsets:[[[171874,-16861]],[[171119,-15292]]]}},{type:"Feature",id:"PSE",properties:{name:"West Bank"},geometry:{type:"Polygon",coordinates:["@@@ԣŭʙЃŕ˜ɜɌŚɁĦǬ̤֔ś"],encodeOffsets:[[36399,33172]]}},{type:"Feature",id:"YEM",properties:{name:"Yemen"},geometry:{type:"Polygon",coordinates:["@@؉ɥNjύo˹࠷Οഇϻݩףυ±ʥºӭΑ՗lj۷©ɃµǿɛəÕŻɇеlˍœ׉¨ɓӬzҠƍʜǑتʋΊǚ¤đϨĸNJ™ξςˌđΠɞЮΊɓɬúॺnƸċ߼č͐¨ɂ˫ϺƖ׼ࢦ޸Ϛᝒ͒ڀ൳˞ח"],encodeOffsets:[[54384,17051]]}},{type:"Feature",id:"ZAF",properties:{name:"South Africa"},geometry:{type:"Polygon",coordinates:["@@ǏŧΣяɻћӇ׻ोࢁףԋًϣ࢛͙ѓ«ŇɷԛŰеDž࣫NJԙĹΏ¬ࡿͩܓƃԱͅϡoΣ̚˳fαϒŸśŏɦLӰ˙֞˔ƴs٤ս޼х܈AF׽તДдͪɯƘΫϘÓՈǃҌÖݤіB᷌ɨűӾߙûԟȈ̏׼ĒрϒЊʨȶДЦȚΠķВɽۂ£՞ȜĐʾƨДҚäʨ͂˪֔ݮغஒؤ΂UОƛ˲Ķ҂ċД஁ɔׯƫऩî̟чƶʏÑāʓɯ̿T̃ԆҕӮĜǢώْQȿؑıۥɑϛֵщ","@@νʶϻǟҕ҃͡Տـ٧̜ČƺˎҴƀƜ˜ʴФ̅ʪ"],encodeOffsets:[[32278,-29959],[29674,-29650]]}},{type:"Feature",id:"ZMB",properties:{name:"Zambia"},geometry:{type:"Polygon",coordinates:["@@ІϏɊ܋ƝɩǙڻLjۡ˃̇ʭޭѶɓᢇۗĂׯٍřӍͯĹ̛̅ßܵۓҭխ˳o˗ĬऱĠƯÚOêͧȎկ¶ۋȑչԾ֣یžᦶშYí̂Ű̀ƧЀĪТėʺ̂q¶ʽϾrՖûˬϡڨŝԤˆȌѯ٠ş̴ΧΈҥ٠Që࣠ɱƳח͞ɧƬļࡈƬসȉψʈ՚ɤĶ଀ƚͦđΘɇͰƗՖƗӊʧ"],encodeOffsets:[[33546,-9452]]}},{type:"Feature",id:"ZWE",properties:{name:"Zimbabwe"},geometry:{type:"Polygon",coordinates:["@@ҁČ˱ĵНƜ΁VՙϞٯźʙՒC̒έĞ्ई˃ӢǛƮ͓ڤलğ˘ī˴pҮծܶ۔̜àĺ̆ӎͰَŚÆ̻۬hϴǯǺȻАÓѦˑF੟Ǐ׋—عƊʝħӵŵùɛ؅ࢫ॓"],encodeOffsets:[[31941,-22785]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/xiang_gang_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"8100",properties:{name:"香港",cp:[114.2784,22.3057],childNum:1},geometry:{type:"Polygon",coordinates:["@@™@}ScTʟ@cWuJÁ–]„l¦RLj¼BĄà˜ ŽH@TOHCTDDDHDNAT@PEHDDNJLX@BABALHFF@DKHADBBLDHHFBLEJB@GDBBFBADDB@@KFAFBBJJA@BB@@FFDDADFF@FADDDBJC@AFBD@@DDD@DAA@D@DB@DHHBFJBBFEHDFAN@DGDC@DLCBDDCFDlAFBFCBEF@BC@GDAB@FD@DZJ‚X´HĐMja@Ý`p_PCZ@lLnRGSDMFK|a\\Y}­ƒ§™Mën"],encodeOffsets:[[117078,22678]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/xin_jiang_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"6528",properties:{name:"巴音郭楞蒙古自治州",cp:[88.1653,39.6002],childNum:9},geometry:{type:"Polygon",coordinates:["@@˜@ÈÒĊanwŎV„™Ȯ¦ͪŃĢ„ÜōȂçČéƐżLɆóĊ‚ĊaʊŁ±¯²Um»ˌmÈ»V™ʠţWÑůǓ郙ôƑƒğÆīŎī@Ƿ™wô™˺LÞ¯ƨVǪуšĢ™ȘV°wĢŽôk°¯ƒ»΀@Ȃ»ĸŽǔ@΀ƒ͔ôôLɆó̐ÝɜLɲōͪƒƨóŤK@ī@IU܃ÛmȻţǩÝ˹ÛljťǓǫō@Ɲ²¯VçōKͿŁΗÇţ»ƽ™ɅƑLÓŏÅÅɱV@ÝĊU¯ÑĊĭÞLšÞŎJ±̃XȣˌōlƒUÈ¯ŎKÆƅ°™XÑܱnŗġV¯™óaUƒƧUōŁ„Ñ™±„çɲ¥lĉkğ°ƒk¥˜ƒnğţL¯ÝÝUƽĬ΁lķ°@„ō„XÿݯV»ŹLʉÞɱŤĉó°ÝJ™¦ÝKÝ£ţܙÈĉ@ƒxǩUċƑ@ky͓¹™`U²ĉVġ»ğa¯¥ť@ĉ™‚ó@ŻÛÛJƒw¯nó¯ġWƽʩķÝɛwĉĕݼȭÞķō@ó£Å΀ƑŽ¯ôȯÞ¯Ȱ™ÆōèĉXǼó@ݚnºƒĸ„ÞVƜĸȚUʶõˀĵĖɱŎÝĖVࢰӒѢ°˘nϚVˌ™ÈmɼĵŦW¤öʊõʔ@°ÈXVŽ™ènŎȁb¯ǫĉ„±Èğ`ġwōÔğ»mVVŽ„Ý¥ó@™ĸķô@ššbX„ĶmV²²`Þ_˜˜ɴbͪÈ°„ÞWĸÈŌmބškɲŽÈUÆ»n¼ǬVķĸźô¯°n¦ɄǜÈ"],encodeOffsets:[[86986,44534]]}},{type:"Feature",id:"6532",properties:{name:"和田地区",cp:[81.167,36.9855],childNum:8},geometry:{type:"Polygon",coordinates:["@@ƨ¥šèź٨ΘƑᩄbUࢯÞĕɲōĶĕöʿVʵķșUƛƒÝ„ķm¹Þ™ô@È»ĊWŎçšÅ°ȯȰÝ°óƒÆͿĉ»̽çnƒmɱĵƧºóU™™ƽ@±wóL¯°̻L±Æ¯Vƴķb¯VÇ¥ğ²Ǖbk¥ÇKlÅɱġ@у™óK@™ÇaÝXğţxĉČǫķê¯K@уaŹ„ƑKƒ¼¯Vóaónġw™óÞéU™ġbóĉğÇl¹™aUóğKW„Vůn›ÇŋƑ›ķnʇ»óxĉw™çÇ°Åw™°ċ„XŽ™„ób±ƒkÈÇJ—ƒm²ţx@ÒݎšŦǺn„ó¼n°ÇbUÒ±¼XĸĠłƽXmwĉºƒzÈÜmnxmx²ĖmҚbnŽƧêUºĊêÆVóĖóUĉ¼ÅĬƑ°ɆƆŻŚlłÞLš¼nĠƒ¼@ޙšÞź@ŎÞ°VšɄɴжϼِ͈Ŏ„"],encodeOffsets:[[81293,39764]]}},{type:"Feature",id:"6522",properties:{name:"哈密地区",cp:[93.7793,42.9236],childNum:3},geometry:{type:"Polygon",coordinates:["@@WnŐÆĶLĢ¦ţºź„lxÅĸƽŚ‚Ʉ—Į˜è@ô²ÞUĔƐńV°¯ĸX¦Ɛm̐bƒ»Ɇa΀šĢ™ƐLˤ™ȘÑnƒІljĸÿn¯ĶaŎ¯ĢĕȘ¯°΂œla¯¥™ǕǔwˤӱlťО̻nŻmɃĕċţUw°WUóƨÅţķ°ýV±óÅǓéʉ¯ƽŁƒéōǖȁÝƏůǕw˹ǫȗǓƧǕVý™é@ĬţLƧôͩ„ɱŎɛK̏ÞɅôóK@²@°ōؚ¼lŦ¯ŰóƜÛlV¼ķ¼ƒ°kȰ™Ű„ĠƒǬ™ŚÝŎmĖ`@ÇÜn„"],encodeOffsets:[[93387,44539]]}},{type:"Feature",id:"6529",properties:{name:"阿克苏地区",cp:[82.9797,41.0229],childNum:10},geometry:{type:"Polygon",coordinates:["@@VƚxˌŎÞŎƒ°n„ȂÒ°²VĊ¯VğƾˍǬƨÞÞKÈÞĊVźôɆÞĢèŌôWČ²ŤVÞĸʶbl‚¯ôn_VÆĸlmÞnVź_ĸ¼Ȯmǖ„šéĸW°°„ĸJ„kʠ¼Æw°¤ÈƒlxɆzČºĶI²ÆǔUš°ô@Þ¦‚ƒUnUĠ¼ŎÓĢxĠ_²ÇĊƒǬ°ŽȂamōšçUÇW@¯öʓõʉX£ĶťnɻšÇUˋmϙ¯˗ӑѡᩃaΗƒœɜ°xWƴUxɃÒˣ¤Ʌwğ„ʉōóÝŹ±°ȗ@¯„ƃ²¼","@@ō™гwȁ¥Ƨ°ŹÑķV™¼ÞêĊ»‚lĵšm¦ÅW@ĀôÈźaɜxÈbÞÆĶIОŘnIÇŃÛÝĊÑĠƏ"],encodeOffsets:[[80022,41294],[83914,41474]]}},{type:"Feature",id:"6543",properties:{name:"阿勒泰地区",cp:[88.2971,47.0929],childNum:7},geometry:{type:"Polygon",coordinates:["@@ɲˣĊIÈ¥‚ÅU±Ċýkō°ƒĉƽó»ĶƽXóʵʵ™ȯƑÅȁɅ¯ĉ@ÇሗK֛@@ˤV֜ʵрƒǬVĸƑŎ@ƆϯÑóŽķ@ʇ»ķ¦έmlÈĸĊX¼WźÛÞÝѸ‚ĢČþ„ĀĊôάVö¼ĊUƨ°°èŎČUÜƐóôVôôŽ²êȘlˌç°`n²ǬŽĊaš™ƒÛ°±kğmm»š@°ÝɆÛÅÇVaݍVm͔ğôÝÈb‚„@„ƒ™n¯š™ÜUĢÑĊ@źīżWŤÈǖWôŁÆI²ÓƨL@ŽĊX„mmÑÆ»ȰÑkƒĶō@ý°m—¯"],encodeOffsets:[[92656,48460]]}},{type:"Feature",id:"6531",properties:{name:"喀什地区",cp:[77.168,37.8534],childNum:13},geometry:{type:"Polygon",coordinates:["@@Č@°ƒĠ„ôÓô@Ŏĉ@Ƴĸ@Ť£ĢlVôWVóřXĉŤêÞ@ƐÒĢÑlèÈV@šĠIk°ÆŘ@ÈÈĀ@ǶťÒğ@š„@ÒĉlŻ_@šƧĖÅĬōÆ@bźÞnƒƒlVœÝĬšWƼʇ„ƒÝÅ@ÇÅÈwWóĉ±ğz‚ĬČƨƂÝIĉݯbÇÑĉƒ¯ʈV°xUŰĊ¤ƪ_ôÓɚI@lȚXȮ™ŎlɴȘ՘š„¦ɲÆʈ_ɴŽźŽôÞʊŎĠƒɆxˤ£ɄÑVwXƳ¯w›ɛŹ٧™çƧ¦ōƒُ͇еϻɃɳU™Ý¯@ōÝŹš™@݄»mğ™»ÝKkŁżřɅƅƒ¯ÆīĊ»ôVôĕÅUĉéV¹ƨém™anѱĕnwmwnÇۄyĉ¹ŹlŏkĵèķmōÞġKñÔċKÅèĉzƒŽ„ômxȗÿƿI@þÅČÝKÝ°@¼ÈVºš@ÅĢšÆUċłn„ÝÆǕČĵJm£ÝJ¦@ĊƒxV°ƏLċ¼ǩ™@™m@ÅĢómÇÆğ¹Çš™ÆšĖÞKšx„wô¦ÆÑÆL²ÆƾŽU„Ž±ŚÅŻĖ@ĬŤÈñ„@ǔÇx„Èǃ","@@VÇ™ţ°ğUĠ¯mk¯ó¥ķIġÿƏbƒ„ĉa±ÒĸĀlKU„_m»nwšŽ„m@ÈŤ¦ĉbÞ°±Þżł̦°ĢŁVé"],encodeOffsets:[[76624,39196],[81507,40877]]}},{type:"Feature",id:"6542",properties:{name:"塔城地区",cp:[86.6272,45.8514],childNum:7},geometry:{type:"Polygon",coordinates:["@@ήnĸ¥ʈ¼ĸ@ôϰÒ@ƅƒōUķƑǫʶпU֛܃LګK@΋ĸ@Æ£ÞġÅĠċšLV݄»™@Å»Ýnm¯š»nŻĊ@nķŃ@¯ómóÛÝǟ¯aÝóȭ¥ƒšōUmxĉbÇї@›bUº¯X¯ÆƧbVÒĉnǕw¯°ƑŽV„—ŽÇ@kx±Uƒšɱn™ŽÅKƒ„¯ƒĠǠU°ɜL@°ƒxnĬ‚ĀŋŎÇLƒŽğšϱÞέƜkôÅĀǕłƒĸĊŤUŰĢ°„¦ȂϰÜɨ°x@°żǠÆƈČVĠ»ČL°ÇšbĊÑ̐óÞlĶwބɆVÞwǬxǪţȼÜLŐĶˢ@","@@óKĵĀV͈ĉłƾNJÆŤƒzXl°ƒÆL²¼źŽôÈĢǔ™¦l„ô°ɜÞʊĠğŃm»ʵƳƑʝȗīV¥¯ĉ°Ñ@ŃÅI™»ĉmğn™ƒašƒċƨbš™Vğ—w›ġ¯@Uōa™ĉÝJğÑÆŎkŎÞĀlźƒ¦"],encodeOffsets:[[87593,48184],[86884,45760]]}},{type:"Feature",id:"6523",properties:{name:"昌吉回族自治州",cp:[89.6814,44.4507],childNum:7},geometry:{type:"MultiPolygon",coordinates:[["@@መL@È°ĊȂɆƒÆĊ£„ťôWÓɆbĢÅŎƒÆ¦ČÑW¥°ķU¯ƏŃVē±Ý@ó—ç˜ĭɃƾřÆķkwŹƒŤ¹ġ¥ĵKŏÅXmˍщwǓ¤Ƒ@wóōVķ£ɱšġôÛa±Òȁ„óèţIVŽƽ¼k¤ó¹ġJmx—»ÝUƒ²™@ÅƃĸǫŎ„ĊmŎǬ՘"],["@@Þô°bÞǠôÜôn@°ĸń˜Ƕkłƒ¼UޙKğȂÆÝĢŤķ@@ΌڬL܄K@ˣȂ˭lĉńW¥ĵVÆý@ŃÞēUŃȗƅ@ŹƩǕĉ»k»Ç™VğóřX™ŻKƏŽċêȁèÛŎġƒͩń"]],encodeOffsets:[[[90113,46080]],[[87638,44579]]]}},{type:"Feature",id:"6530",properties:{name:"克孜勒苏柯尔克孜自治州",cp:[74.6301,39.5233],childNum:4},geometry:{type:"Polygon",coordinates:["@@ˎǫĠƽ°UUĉ¯±ȁÑmƒ„¯Ýōˋō™wUű»ÅƑ°ƒȘ@²¯ɳʇ`ɱŃ¥՗™ɳȗōkȭšșW@kəJóÔƩ`ĉ£Vů¯wU°ʇĊ„ÈÒ°aĊÞÞJŁċƧīĠyĊ²XôÇxÈÆÆ@„ÞʈƒÅ»™XÞīU›Ƒkm„ŹÝ@aŎÅÆīƨĕ@™ż`Ċk@љƒĠ@ŦÑ@ǵÇÿ@ÇÅŗl¯ğJ@™ÇUkçġÒƏÑÝ@ţéWĊôŚUŽóXUġkţ¤ķ@@ƴōĊó@óÔğƒ¯„ċ@@Қ¤kôˣŰ͓„k»ƒKX¯ċwƧôğɐšÒôIVƙš¯UķǬķšnŽ™¼ôb°ÒȰVVÈÞ°ƒĸó¤V¼°„V°²êƒlĢ҂Uƨ¦ôȰƴĊVV¼ǖIċĊ„ÞɜéšnČW˸Ǹša„řÈw±īšçĸ¤ĊšôšwšŽĸUĢ¦˜éǖĬ„Āô¼lÞkÒ°x°ƆÞx„šÆV²ǔ»„b°wގȘ¥°n„šŎV@°„„ʠè‚ŰȂb"],encodeOffsets:[[80269,42396]]}},{type:"Feature",id:"6521",properties:{name:"吐鲁番地区",cp:[89.6375,42.4127],childNum:3},geometry:{type:"Polygon",coordinates:["@@ôK„ĉǪa²¼lÜô@ʠê°Ĭ™ôȂƒ²ÑÜbĢóɲ™ĸ¤ŎUô@xƒŽǔ£ъxˎmƒÈÛ@‚_nĕÞōšř„ǫƒğšůlȯ„¯ĸ»U»Ükôƛ°ůkť™»Ŏŗ@¯@±͓óͿ„Ǔ@ķȁ¼Ϳ@Ƒ¼¯°ólġ¯xȗUġšƑ™ǩÒƧUÝ°˹Kóššx@ǸōĬÅĬƑĠ󃄚ǔêÆ°XÒʟŤUšÇ¼ˋnn¼±V²°ȂUŌݜbʟǔɅô@żǬaҎÈ"],encodeOffsets:[[90248,44371]]}},{type:"Feature",id:"6540",properties:{name:"伊犁哈萨克自治州",cp:[82.5513,43.5498],childNum:10},geometry:{type:"MultiPolygon",coordinates:[["@@ĉ„ÆŘȁ̐mÞ¯ĀX°±¼@ƾ¯ƴ°ŎÝþŋ¦WÜÞbȂĉźUœÇmwVUȂóô@ȰÝ΀nÆJn™ƾ™ʠ™ŌLČóǪ¯œ¥ǔaǖšŌaôÝĢLšx„ƒÆLšɲm„™²VlwÈ@˜Uƒƒ°¯ǖxĊmUÑƨa°Å°WV¹œa›ÇɃÈm¥°¯ŹóĸķǫUm»Å¼ÇVɱ™l݃ŋnķÇÝX¯ƒͩÇɳa——Ý`±_U±ĵnWƒ™a@™ĸóšķ™¯ǓV±ÅĵJċ¹ɅykwDŽ¯£Åxʟ»ƒlķI¯ƒX¯ķ‚™êǕƒȭnķ»Ź`±„kÞ@Žš„Ýô@Þ°xšŤŎIƨÆUxōš¯²ǔĬǬlUŚ"],["@@ÞĀlźƒ¦¯ĸŤKޙšƒċƨbš™Vğ—w›ġ¯@ţƽJ"]],encodeOffsets:[[[82722,44337]],[[86817,45456]]]}},{type:"Feature",id:"6527",properties:{name:"博尔塔拉蒙古自治州",cp:[81.8481,44.6979],childNum:3},geometry:{type:"Polygon",coordinates:["@@ήƛϲÝĠ™„ÈKŌōÿmī„w@¯ɛKV¯ğǟ°Ƒ™wġKóÞŋbǕ™Ǔb›¦ǩ°ċôŋKʟšƽšmšÅImŽͿŽȯÞó@ȁôUVnx›ÈŹVȁĊÝabŻ£¯°l„óxȂŤĸkĊšÞyĊêĊmĢxV„ƨÈŽĠX„ŽΘÆĠÔź‚Ɇţ°LXƾŤŤb"],encodeOffsets:[[84555,46311]]}},{type:"Feature",id:"6501",properties:{name:"乌鲁木齐市",cp:[87.9236,43.5883],childNum:4},geometry:{type:"Polygon",coordinates:["@@šŽWŽôŚUĠȚl¼Ċ¼ƪǖ@źȘƆ@ýlܚXVŘޙš¦V¼kĖó҃èkĊȁˮ֜@ǫ՗nōƒĉǬō„ķÆŚ@„±ÞV˜¼nwĢIôºl£ƾ»UŤJôçšó¯īʟéó@kÛ±»ǩbƒĊóLҍÇǫb@ŻɆóʠǓ›aŋÞȁVʉłĉbĉɅô"],encodeOffsets:[[88887,44146]]}},{type:"Feature",id:"6502",properties:{name:"克拉玛依市",cp:[85.2869,45.5054],childNum:2},geometry:{type:"MultiPolygon",coordinates:[["@@ɜÞʊĊýVaŃm»ʵƳƑʝȗīV¥¯ĉ°Ñ@ŃÅI™»ĉmğn™ƒaݚţL°ķóKĵĀV͈ĉłƾNJÆŤƒzXl°ƒÆL²¼źŽôÈĢǔ™¦l„ô°"],["@@ƾIŤ@UUwōa™ĉÝJğÑÆŎkŎ"]],encodeOffsets:[[[87424,47245]],[[86817,45456]]]}},{type:"Feature",id:"659002",properties:{name:"阿拉尔市",cp:[81.2769,40.6549],childNum:1},geometry:{type:"Polygon",coordinates:["@@nIÇŃÛÝĊÑĠƏō™гwȁ¥Ƨ°ŹÑķV™¼ÞêĊ»‚lĵšm¦ÅW@ĀôÈźaɜxÈbÞÆĶIОŘ"],encodeOffsets:[[83824,41929]]}},{type:"Feature",id:"659003",properties:{name:"图木舒克市",cp:[79.1345,39.8749],childNum:1},geometry:{type:"Polygon",coordinates:["@@VéVÇ™ţ°ğUĠ¯mk¯ó¥ķIġÿƏbƒ„ĉa±ÒĸĀlKU„_m»nwšŽ„m@ÈŤ¦ĉbÞ°±Þżł̦°ĢŁ"],encodeOffsets:[[81496,40962]]}},{type:"Feature",id:"659004",properties:{name:"五家渠市",cp:[87.5391,44.3024],childNum:1},geometry:{type:"Polygon",coordinates:["@@„çôÑlĕU»™¥ÝšUŗ™WkÛ@þVńÝĔ@ńÅþĶUX¦Æƒ"],encodeOffsets:[[89674,45636]]}},{type:"Feature",id:"659001",properties:{name:"石河子市",cp:[86.0229,44.2914],childNum:1},geometry:{type:"Polygon",coordinates:["@@lŁ—ǵm‚ĉ@mż™¼n°ÞmƼš@"],encodeOffsets:[[88178,45529]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/xi_zang_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"5424",properties:{name:"那曲地区",cp:[88.1982,33.3215],childNum:10},geometry:{type:"Polygon",coordinates:["@@ƨʔĸbܺÞwnxźbÞ°ô@„ĶŽĸIȼĊJŎÈôUšÝƒ¤ǔLސŎ@ĢŽȘblƒôL„ÇźçȤôLš¥ÞIÞ¯Ķxʊťƨ™ƿÑĉXVķŦ¯ȂKÇǕšÑ¯IUš£¯Óƿ£VĕōÞÿÆwƒƑ„£ǖxÞĕ±ÇÝaUÑȃU¯‚UōÈ݃wWŁĵ™±Ý„óĢÿ°IÞ±mÅĢ¯mÿ„¥°UnÑŤĢĕĶwǬŻͪwŎ¼źÇĢ„ĠĕˎŁ°óƨ¼Èa‚m@¥°wǔ„ǖ°ŽƨÇŤœšġƨ„ŎŃôbÈÛŎĊ°@Ġw²ÑÞJƃÆb²ƒ°êĊUނlȲƒV„ÈKĊÒĸĉ›»ÅôťUÅǃk¯@ǂÑklǁÅl™Ģ™VÑóƒ@°@„ÛĸƒV¯ƒÇĊ™n¯Uĕšƽ¯m›¯b™È@Ò°Ĭƒbĵ›¼„‚kxķýÇJk£ÝaUÑÅóĶǟkÓʉnĉƒÝ¼Ƒ„ó»Þmn£m™Č¯@ƒȮÿV¯ĸƒ™k@Ýówƒ»ğ„ġ±ǓLō„ƒšV¼Əèķĉ™è±b@Òţ„UÑóakƒl£™Ó@¯L@™ÇlUóȁš¯aġÈÅĕÝLķ¯Ė¯@WĬ—x‚ÒÈnW°ţôU²ǓÓġ²V°¯ôƒǔÝL—ċšk™š»Ý»Ýš¯ÞƒVƒwۄÝÇōͩÈĉċ»ĉm¯£W¥ţKkóġƏW@¯±kōŽÈ›b@җšÇaƒÆ¯a™„ƒkóŽÛƒÇ¦Ýa¯šÝ™ĉ@ǻۄmƒǓxķƛ¯lVĀÅÞġb™™ÇJUÅV™ĖƑW™zō»ōšƒW™n@è¯ÞóVkwƩnkźÇބҙޯƒƒýğÇUxÆÈnè±bĉÝ»ÈуwšwÞ@m»ÈV@ýÇ°ķ™xƒa„ݯXċ¥ƒÈóW@ôkxlnxVÈóĊkŤġ¼@°¯ŰƑL̻۱ŎÝV—Þ›VƒÇÞŎÇakƞ‚š@èğŎĸżšƾ°ÒšLÞôĠKȰĖźVÈÒĠ„¤™VôšŽU„ÈþťL@ôǬÞlÜÈnÇÒUŚ™@šĊƨW°™°Xƒ‚@ČÇþ„ƴĉÒķ¦@ŽĢôWĀôłUÞĢǬ™ź°¼š@ƒôV°„bUÆnzm¤ƽĸƒÈ"],encodeOffsets:[[88133,36721]]}},{type:"Feature",id:"5425",properties:{name:"阿里地区",cp:[82.3645,32.7667],childNum:7},geometry:{type:"Polygon",coordinates:["@@„Çƾķn£myVŃaU¯„ó™@¯»šŹġǫVÝóŁXÿġó@ĸ¥ĊуƳÈý@ċ„Wš¯X¯ĉƧ‚™š@VřÈÑÇmkÛǫÝ@óŦKÇýVƒ™U󚏃£ğÇÑŹUȯĕğLÝó™K¯Ñ™ƽķŻĠō@灙lƝÈbƍÈ݂„œU˜ÝÞU²ō̼ůƒK°ů@¯UK±—ĊƧbōÇmçÈġƒóšÅób™™źóš¥kīƯól™ç™KôĵUƒÅ„VŃķ¥nÅŏm¯¹Å‚™»@ÑǍóxÝkʇȤU¤ķb@ƒ¯ĊÇx¯ĸĉKm°šĀk¦l„„KnĬȀƾÛ¦WÆŐmNJĉ°ōUţ¤UšŎ°šŎKÞłÆ„Ǔ¦ƒÞ™‚™„ř¯bmUÝl¯Um™ğl¯£șwŎǫaÝnĉĶƒk@¯™K™šō»ĉn™aÞ»ťnkml™ĸ¥UŚŻkÑťƒĉV™ôó°LôīĠU„ÿĉǕÅz±Kƒ¤„²ō¤¯Ė¯UÝ¥Vĵ™óÈťÝwķșÑk¤ó„™ƒWýĵĕ™„VĠƒV󍃎Ǔ„ķ°k±VU±ţ¦UǟÝřJVљ¥XUċUŎlÛƆǕÆȗƆ¯wŏÞÅ@™šĉl݁óŽƒÒ™nUôńlxólÝôێ±™™LÛôÝL@‚ġ¯X¯ÇUżóa󤛼XÒġŎóLk¦‚ôżĸĠ™¼™KġƆô¦„ÆƑÔĉĶ¯ImÒ°¦n°¯Þl˜ÝČn„ƒÒšKĠޚĕkƒlýƾťœšôI‚ĖŤÒnƜm¼¯lnżóÞ@Ůó¦™ôƽĖċŚn°Ý°ôÈUƜƒblÞóŽ@Žǖô°UÈƆ°X„þôŽô‚lѢšŽ²Ėm¦°š@¤™XŽĊblܚzkºƒĖmX„šŎWVšóÞn°lĠxȚa°»żLźƒ„b@Æ°XĠÝȚxĊĕŤaȚ‚°È@„„@èŤ¦Ü¼œW˜ÞkŽÈ@V°lŤkŎ±²¦ƐUšlj°aÈÑŎbĢƒŎbÆ¥ÞIȘlššôVÈU‚™šb„kɲĶn„mnXb̼òƾĖŎ@ĢȂÑôÓĠĖʊšĊÔ"],encodeOffsets:[[88133,36721]]}},{type:"Feature",id:"5423",properties:{name:"日喀则地区",cp:[86.2427,29.5093],childNum:18},geometry:{type:"Polygon",coordinates:["@@ĶĖXþš„ôƒl£šÒĸÇÞxÇŦšôUĶÞ¦°V°ĕŎ£ƒ±„£²LÆyĊǖƒĀğVóĬ¯KóôUš‚ĊŦ„lҙżVÆķ¦kšlnŦmݼšbĊmŎ¼š™šL@°„lĊĵÞmǬbƍȚx°¤Ġknš°VÞkVn°aƒŚš‚š„Ýǔ¥ÅƒÝŁōL¯™ōV™Ť£ŎVĊ¯nljƏXÅÜ¥ǿƽmīƒLkƒl¥™ÿn¯ĊL°ķÈw°ĉ@ƑĸaV£ʈȣÞlôwȎ@Қ¼Æ°ºŐnmÆĸ¦UńƃV„óĶšLšèôkÅ°lĬ™¦Źôššôa™Æ„ôÇĢnèŎÈƨa˜ĉ²‚VLĢ»lţôĉUǂwkmlw@óôX„ÇȦ°WƒÞ„b‚wĸšÈ¯@þÇUn¼Ý@™x„xÇńÞ¼ĊŽ²amçÅÇVwĠȄþ°„šÝƒÑÈÝlŹƪmlxôU°Ý@çšm„XŎ™Ŏ¼šyƒXšĕÆUVÈIššĢaÆÝUÿ°kĸƜǔwn„܃ȼĊ@ޚ°™Þbȥ܄ô„lšƒ°b„ÅÈb˜™@ќa‚ǯUU¯Vġš»ƒ™¯aV¯Ç°Å™mnÑŤçǬVǬ™±ĉ¯¥Vĕ¯Ýk£˜ō—w@±ġÛ°ÇVїƒ@ۘa@ČL™Ƴ™„ƒÇa¯¤ÝIĵ¼U¥ƿōķÅţŻókÝóĕ‚¥¯™U»Æ£X¯ġŃÛkÝ°V°ó¼¯èWôÞĖ„ȎƒŽkĀƧĀówm¥¯JŹÝJݙōVVŁaݐƑ@ƒ˜ğŭǂ¯_ƒ˜ĵ—›VnxŃón›ƒĵxÇĖĉVÝÈğV™Ò󃯐±Żĉ£ķÆÅL™Ljĉý˜ţۃ¯VƒnV¤ÝÈ@°ÅÞݤ™ŰğŁm¦ÝxóKƒ¥ɱÈUĠôêVôÛ¼ÇWÝçĵaō¦óĖƧlÇĢƑŽnŎDŽV¼¼‚ºÛ@m¦ƽ„ĉmm¯ÝKÛç¯bŏłĬ™bƒ¼ÅLmŽ„xť°ÅU™šÝXkŽÝmĉ¦W„¯K„ÒknÝaV„Ýè¯KɅńÝKnÞ¯¼"],encodeOffsets:[[84117,30927]]}},{type:"Feature",id:"5426",properties:{name:"林芝地区",cp:[95.4602,29.1138],childNum:7},geometry:{type:"Polygon",coordinates:["@@‚VÈłVôÈk@š°K@ŽšÔk¤l„ôbVÒŤƒ@ѲašçĸĊƐçU»„™ŎƒǔKĢ²Ġƒ„¼ôx@ޚlƨĬ„Ul¯ÈLV‚šÞJ„°Ünʊ„wÜbXê‚VÞ¯°ššanaU°wƼɴÑWÑ°mÈýÈam¥Þ£Ť@„¥ôblÞĢ„ź¥ôxÈÅmݚ™ƒĕŃV»ĉōŤōnóƒ»ÈīķIUƒĠÑ°ġĸLÞ¯VÒƂ@Ābš¼WôÈ@V¼ôóŤKÈÑU»šwVǫżnWÒÈx™¼‚lŦ£ĊōŤx²¯@ƒÆƒU¯šçÆ@„¤°£„é°k°lšůÈó@¯ŤÇÈĉƒkkÿó¥ÝXķљÜ@ÒóŚÝ¯°ĉówÇ±¦ÅJUÒĉĀķw¯°mĖ¯„±akxÝÅnƒ™»lуK@¯lU™¯UVѯóĊ¯mōğVǓƅƒÞƒWÝÈÛ@ƿô¯ÜġzÅþ¯ólmôʇġĊÅUͿřŏȁˋŁóÇˡōƧƒÇb™w°Ķôk¦šÒƒnUþġҙÔkǔķèó@ƒ²@ŘōńĵyƒzġaݤÅIƒ¤Ƀť¦ğѯ¤ķbóš¯ó±ŽU²°¤ČÜVnÈƂ„ŚŎ°ôĢ„þÆzèVĀǎĀǘƒXŹÑ¯¤ówċķk¦šłUÒġzÇ@ƒ™ÆÝx@²Þ@Ƥ„Uô¦Uš°x„U"],encodeOffsets:[[94737,30809]]}},{type:"Feature",id:"5421",properties:{name:"昌都地区",cp:[97.0203,30.7068],childNum:11},geometry:{type:"Polygon",coordinates:["@@™ŽVĖm°ĉš„ÈU°ķ„ƒÜ¯@@ô„UÒġškš‚ÆkÈlŽÒ@Èl°È„VÆóŦƂœ¼‚a„ÅĢ™Ʉwnōw@¥Ŏ¦°ŹÞmVš°wnÿƒw„wÝw@¯šmÞŗ°wĠ˜ĸkÞğlĔ²¦°@„ĕĸwVóšal@nĢÇĊn°@¦šŽźUXçǔůĸVš™ÆK„ÈÝĠš²ÅĔô@lšŽÈ_m˜„zǖl„šaU¼ôwV°¯¦‚ĬÈa„l@Čǎ„¼™„nŽ˜I„xô»ɜ@ƨ¥ɆŁ„ŃǪȁkƛƨȍʊȡóĭ›@—ÈÇVƒůރĸƅmēƨť™ÅÈʉVǵ°ġVŭÅɧ°ÿnɛš£mƒķ²ŃóÑUĉ°mÇ»¯@mxUĀ¯èţ°ȁÝç„ġU¯ÆÇţÈ@°Çô™Ű¯k¯lƒê¯¤ƒ£Å@™èV°Å„@„±°ţwĉŎť¤kš»ÇwXÑŻmUǬ™xV¼ÇÒţLóôU»Ç@X󙻂a@ÿŁUÑÝ°ķK¯ĢğÒV„ĸJÇĬ„¼môţŎĊŎU¼Æ„„Ė™šnÞÇÆówŹ¦ġƒkÝóaƒ¦ţ@ݤn¦ÇbÇþ¯nXÒɳÒÅ»¯xVmb™b¯™Ý°UWéÛaƒxʉÛmƒ¯ÝI™‚UÇKk°ƒVƧīķ„U°ȭĀ@„ċ°nšm¤Ýnô¼ƒƒÞ»Ċ„ʊmlÔĵǠÆôVÒÞbl¤ÈIĸþlwƒœ»ĶŽ„a¯ī@њǰanœƾ°"],encodeOffsets:[[97302,31917]]}},{type:"Feature",id:"5422",properties:{name:"山南地区",cp:[92.2083,28.3392],childNum:12},geometry:{type:"Polygon",coordinates:["@@°ÞUĖ°¦²ĊôÇÜLǖĀɜŽȘŰÞLĸźêÞ@UÜUŤ°ɞ¯Ü„°WŦĀmŎ„¦ĢyVљŁl¥Čĸôx°£źÒ„Wȗ‚ÿȍUÿ‚çÅyƒýóġō¯ƒřŁmÇÛUċŽ¯£V±²°ôô™ĸa°£ĠÒŦ¥ɄŽ„£ÆJÞ£Ģb„yĶzŎŃ@ŗ„±ô@ĸçlǓšÓĢÑVý„m™Ñl¥ĵó‚¯̻̥™ƛǫÝһÇƧĉyţ¼ҍēVĶĉŎ°ĸmšÞVÝĸ™ÒÛaċ„ó™ŹĖƒèÈÈl¼k¤ÝX@`ސŏ¼Æō¼ÇçĉKUÝÝ£ğ¤@¦ġl¯Òġĉ¯óš™móxÝÞğVšƴċK@—b@ܘ„UÒ¯ÈĢÜ@²˜x—Ŏl¤"],encodeOffsets:[[92363,29672]]}},{type:"Feature",id:"5401",properties:{name:"拉萨市",cp:[91.1865,30.1465],childNum:8},geometry:{type:"Polygon",coordinates:["@@Ŏ²l@°‚XĢƐlôŤLX¦°¤ĊnČ¼ÇĊŎͪÞÈ܃„x„U°Ýޙ޼™¼lšČ™˜ŽÞK„Ǔ°óU¯Ģ±ǔÔV±ŤóX¯ÇmÑ˜wXī°@°ĕĸÞKÆĖĢÇ°bȂ™ÇŁUƒV¯wV™ó¥ƒVÅ£Ý@@±ÞwšÅ‚„È@ƒ¥nōťÿ¯Xۃɝ°ţ¯ÛVVÝ@ŹéķÝKȗůɛǕÿÛKóÈǫšǫUţèmҚn¯Æ°ÈU‚°b„š™¼UĢV°°V"],encodeOffsets:[[92059,30696]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/yun_nan_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"5308",properties:{name:"普洱市",cp:[100.7446,23.4229],childNum:10},geometry:{type:"Polygon",coordinates:["@@U‚ô²‚a@Ž²²Ķ¥œV°šĶ²bl¤kVxl‚@œ°‚Ś²@˜„„y„@ô¦¯„@xƒxVxU„VššbVšÜm¼Ŏ„„ĢmºXXWÆ@ĀœšmŽmXU°ÅÒm¼Þx°w„@°‚XêĠ°»nV°U„l@k„@V±ôī@£‚ƒČŃÆ£„KÞý@¥‚k@y„a@—nWV„UVƒšwƒmƒ£Jƒknm@wmkn‚X„˜šX„¥mUUlUnbš¯°ŽnkƒVInlIUw°n™mk@@mlanXlanmšk@wVWUw™_@éĠašnmUaÜ£ƒmXƒ¥¯@@„óUmݯ¯ÞÝlKnxô£š»„»Ġ„J°aV„UÝÿV¥ÛbƒI@wmŽón¯yÛL@ƒWkŎmș`IWa¯K@¯mUnmaXm™bmak„¯ŽƒĢ™ÒÝm¯mV¯KÇb¯KۜWW™X@a™V™knċLUWV™kXóW@k™a@ƒób¯Uƒwmb¥UUlaU¥U£maķšƒKXkƒmÝ@kwmѯk±ċbUUVakaġ¦ƒƒkL@`ƒœ™a¯xƒm™Åƒ™LUWƒ@ċnŎUV°LkL@b°°@¤š²ƒ‚šnôôk„l°kè›ÒÈzV¤È„WôôƒnV@„ƒ¦@¼Ux"],encodeOffsets:[[101903,23637]]}},{type:"Feature",id:"5325",properties:{name:"红河哈尼族彝族自治州",cp:[103.0408,23.6041],childNum:13},geometry:{type:"Polygon",coordinates:["@@°°nÞôV@ƒ°@„¦WŽ„nÛ¤Vbmn™ğb@êš`VxUX@xš„ƏÞUnn˜WÞĸĢƒšÈ@ŽÇè@zÛÜWšÅêlš²„˜KnV¯ĖĊx@bk@@„°JÆ£Èbl„nnm°nlUkVUUwVm„Kn„‚nVŽÞxVLX¥laX@@xl@VzȎVmšk@b°šÈĸmŽV¦`W„XšƒbUb‚bX¼°x@ašVVkn@lþnXUlVxŤÅ„y‚IUƒka‚IŎĊ@lXx@b„z@‚ô„ƒ¥„_V@l‚n@„ôy@al_l`nmƒÈ»@kƒmXwWK™U¯»™a™Å@wƒmUÝKUa™UUƒ™wWƒ@w²»@kƃV£—mm£VKkÑV@@»nwƒ¥™ƒ@kƙnllIVlnLVakalknJšWmnaUaVÑVVލn¥m@ƒ„¯Uÿl™@™™™VçƒaXaV¯UyVLVkš@nJlšXLlŽkxlbla²Òl@nVJVkšx„KlkUaVķÝÑU@Åm¯@±™Uó°ğńķĠmU™Ñ@ǯ¯Å¼@nml@°¯¯`@w™£@¯Çƒk@ƒ»nmċ¯U»™I™Ž¯LÇĶÛn@bó°™U›šwmŽ¯„™Umǯa„™ƒ™ƒI@ykIƒVUŽ¯bƒIğŽƒ¼™¼ó¤mwkLÝÞ"],encodeOffsets:[[104243,23429]]}},{type:"Feature",id:"5326",properties:{name:"文山壮族苗族自治州",cp:[104.8865,23.5712],childNum:8},geometry:{type:"Polygon",coordinates:["@@šwô„š@²¯maUmôUÆxš@Xš˜bÞInlVUVw„JVaU„K°¥„xmÞXnlKlnna°@ĊČ„ÆwUmnkl@°ƒƒ£nyn@VV@Vak™ƒ@@kÞ݄bmx°Vnw°klÞInĖÞVlKl™@Xa°„„KlV„U@šJnx‚U@ÈĢbUKlm@ak_‚wšanWUk°ƒl»„k@Wk@lwU_ƒ@UalóU¥ƒÇnƒ™kJWƒ@mVXx±bƒK@nV±a@™Åa™£ÝK²ƒWknamKknǏk¯ƒaV™™V¯ĀƒU™„™Ò¥ƒI@mm¯¯xōW@@`k@ó»ƒUU¯lm£ÅWlĵ„w@mmwÅmWU@y±U—xmwU„¯Uƒ¥Ý¥¯£m@kŽÇVUV°VbklƒL™wUlUIm‚k@±ÑkbkalwkWKk™mI™@UlUKVzU°Wb„bU蚚@škšVĀƒ°@„n‚m¦ÝŽUUUÒVbmbXn™‚mIkllbUbmKUkkJmkŚ@lš„„¦mx@¼U@lÒULn¤˜nU¤Å„@l±¼@xX„šxV„šVVbÞLVŽ„n@xšÆšb°¼šV"],encodeOffsets:[[106504,25037]]}},{type:"Feature",id:"5303",properties:{name:"曲靖市",cp:[103.9417,25.7025],childNum:9},geometry:{type:"Polygon",coordinates:["@@ȦlKÞĕUV¯Um¯„ÇVUnVVUƒĉn™ĊÇƾLn°°È„JÆw„@lbÞa„¦V„XJ°¯W¯„aÞJVkUša„ƒ@lKnÅmWUk¯a¯»@m±@уkkbWWX_WÓU»_l™kÑm@U»m@l@IWċn¯l@VanV„UV™UVwVx„KȄVmUē‚@„ƒn@VÝÆL„w„VVwnVlmkUVÑÇ°ka@k™ÿÝaÞUl£™›—ċĕX±±ĉƒa@UnVnalónk@wl™UVmkÝJ—aW™™@ÅwóVVnnb±°™@óƒ™xXLWx„n@lǼn„m‚k_k`@bózƒ‚m@kU@ƒ`„¦óƒ@nWš@ÜÅXWw@ƒyƒb¦@ÒlnUb@x™lܐk‚@²Ç@Uƒ¯bmy@kV@bƒb„¦U`lLVx@b—Ll¼Þ¤@„°VVބU@WސUb›J@nnš@lnnm„šxUŽƒUUbƒK@šÇwklkUƒVWakn@ŽlbU@@„ULVxkKUn‚°¯Ò@¼™„kmƒ¦m@kl™Ȱ@lU„l¦„@Vl°wšnnþĊUÆbUx™b„ŽV„šĖU°„a‚nnašV„al@@b"],encodeOffsets:[[106099,27653]]}},{type:"Feature",id:"5323",properties:{name:"楚雄彝族自治州",cp:[101.6016,25.3619],childNum:10},geometry:{type:"Polygon",coordinates:["@@mҁXU`Wnšš™@Xl±¦š„Uxnbl°knmKUx„„ƒxVôUx°¼ôÒȄ°JlnÞKĠœW°¦ƒ„Vx²JVwš_°¥@UV@@wnymknK¯I@‚™²b°ƒš£V¥šwU‚V„¤nLškÆJÈwôô°„l»Č¯ƒġVƒUU@@ƒ°ƒƒÝXl@U»°Å„@U„¯@w±¯VmUUlm@m™„ÑnIVyUwmak£Vwm±—@Çw@nƒ@UxkwlÇnL‚mkř@±Žk™ka@kóJV¯Ç»U£lw¯™Xalbl¥¯UXƒ@a˜™UaÈL@ÇVIVƒkaU¯mm™akLWkUJ¯Umxnšƒ@ƒkUx¯xƒ„mWÅīÝkkbƒŤƒbkxWmXwWk¯wƒKkƒƒLŤċń„@¤óĬU²ƒ@@lƒk¯VmU¯¼@xV@k°l°kbUš°nm‚VnUš@°„š„UVèރÆbUÒÞnU¦›V—¼lô„@Vl"],encodeOffsets:[[103433,26196]]}},{type:"Feature",id:"5329",properties:{name:"大理白族自治州",cp:[99.9536,25.6805],childNum:12},geometry:{type:"Polygon",coordinates:["@@lbœKVIUa˜@²m@b™xôÒÜxXLmbnšl@š„„K°šš¼k„Uô‚xôlV¦nJ„Uš™Ænšm„@šx„ÆwšbXšÆôô„LUVwôK@wlmšaVwœ@WknmƒIUmlnJla@_™@kÝmKUašÑm¯Xw°aUaVl»²JV„bÆJkôĶĀ²VVk„mšbVwUó„wƒƒVwnLlmk¯maVw™ƒ²¥Wkš@™™XmV_‚WnÑUkƒ@k󘻜UV¥ÝmVÑÅa݄UçƒVƒ™@¯V™Umn¯mV™lak¯l¯U@@wğŽW鯁ƒ@¯xÝw¯š¯Jċa¯U¥mLU¤„bÞȤƒbÇLWUwmIUVW¼kbš`U„Vb¯L±ĊÛkƒÿÝKkwƒKţê™UĉþƒÈƒV¯ÞVbUŽ°KVšk²Ý‚mI—ƒmV@kƒm™UkšVxm„¯KXÈķJU¦V°ULWxšL@môƒšb@bkx±LnVUŽVLnkÜWnwlLŃmW@kkJU_ƒV„šWĊ„Þ"],encodeOffsets:[[101408,26770]]}},{type:"Feature",id:"5309",properties:{name:"临沧市",cp:[99.613,24.0546],childNum:8},geometry:{type:"Polygon",coordinates:["@@‚xĢ„l`²X°ŽV„šx@x°Þ°KXašğUњW‚bnIl`X²°b„xl°„„šV@xVxk¦mb„l@xšXV‚ÆzX¤™Æ˜k°„kx@lźêlaX»VUnJVx‚XÈK„aÝȣƒaV£nKV¦°‚Čb°I°™n»ÆÑV¯nWn›™@ÿXÅWWn¹ƒġōƒn»‚ÛU™™aU™VƒUw„w@w°ƒó¥ƒ@ƒz—ƒ±@ř›¯@kUwlk£±aĵŽ¯™›Uĵ¦±±@bó±VÝ@ó¤ƒw¯I@mńóm±XŽ¯IólƒK@š°Ullb™zkKlln@@ԙºƒUmVk²ôҙx™ŎUVóLƒb„ŽmÈnŽmbnl‚a„x@z„@Ǝ„¦kš"],encodeOffsets:[[101251,24734]]}},{type:"Feature",id:"5334",properties:{name:"迪庆藏族自治州",cp:[99.4592,27.9327],childNum:3},geometry:{type:"Polygon",coordinates:["@@W™Xwƒ™@akk@y›—k°īX¥›Uóķ¯w@n»UaVaUۃ¯ƒmV¼k‚™Þċô@n¯xÛÒm„V‚¯Ô@xƒ‚@šk™wm™Åa@ƒUa‚݁¯VŃyV„a@ÿšn»ÝVmank™mmÞÅôƒ@n£±›ğzÇmU¦™Vm„nÜmbn@°nV@xmzÅ@mºV¦k°ln¤š¼õô„n@xkƃIUxUš@Ťƒ¦VšmVkmkXW¤XzVx@ƚx™¼ƒÞ¯b@lVš™ĸގV„m¼XŽm¦V„ŽÞ@Ǝš¹Vón¥ÆKn„‚KX¯x@èĊȱłXšaÆxnlV@UÛlȻkğV¥„m²ljmÅÞĕƒƛm°„ÆmX¤mznƃŽV¦ÞVVb°bnÞWbnŽ°l@V„È@„‚VĵĊ±@ó„InxÆw„¥@£Þ›W¯ĸ£UƒUK‚ƒk±akkkbmWmÈķ„aÆÇU—ȃÆW@wmknmU¯"],encodeOffsets:[[102702,28401]]}},{type:"Feature",id:"5306",properties:{name:"昭通市",cp:[104.0955,27.6031],childNum:11},geometry:{type:"Polygon",coordinates:["@@mƒnK@wmƒUř¥mšóXǓŏmX@Ž—VƒmL@xţ™nk@mlUšŻÒğŋ@ƒL@mmLkm™š@b™XŎW¼ka¯lÇŹ¯aÇ»™ÝÝ_@m„@@a™@UklwUm@ak@ƒb™UmbmƒbV¯™ĕUƒƒšaVwÅaĉVmý™m¯xUkƒ@k¥VƒUXƒ¤VÈm`@„—ńÇÜ@Ākn‚ĔkƞÆĠ„™Þš‚U„VôƆÞI@ŽUxƦn„l@ĊĊnxUÒ°¦Vb¯WUnWŽIml@xn„Ubô¤‚¼ÈxlI„»šKVš„@ÈԂJkšUĖ±ÆVb@nœ„VÜVUVƒšL„wĠl„kn„Ġ@nx°¥Æ„²mUwƒ@m™mÅUl¯UњÑUm„Lll„Il±š@VkwƒW@w°@U»™kUóI°ƒ„»ĢтL„™š`nUĠ²lm„bôV@n„JUxƦX¦l@š‚ŎUƒV„@lV„KVřV£UaÞU™ƒnW@¯VU@ó™"],encodeOffsets:[[107787,28244]]}},{type:"Feature",id:"5301",properties:{name:"昆明市",cp:[102.9199,25.4663],childNum:11},geometry:{type:"Polygon",coordinates:["@@n@Vk‚VUn²°@xƒ°Vƒ@¯ÆV¼k@WŽ„Þ¯„@„@‚VVU„„Ģċ°k¼V„Ċxœ¤Ōœx°mVkƒÑȏšL‚°„x°Xœ°VmĊLVxUĖ°bX¦VW@kšȯlkn@„¥lnšƒ@»°Ñ¯VmlLUwVK@ƒV@ka@lmXb„UlVlkÈx@™„LVa„VV™wnƒmm@km™@mœIVaݏ@XƒVUݯU@ƒÝ£k»˜K@aUwkKV_ƒ¥„a@alU@nz°aV„È@@±lÛšk@wVakm@т¥„a„z‚@XxÆW@ÛX™@m@ƒy@aWw@kōĉJlbV„JƒzţÆUwVkmWkým@Ul™U@b¯wVºƒU™VUêšĠƒXUaUbVĊUŽWXUmkK™™WnUUU™V™ƒƒVV™Ý@kk±‚™¯ƒƒLkƒš±WkXlVklƒ@ƒwXbmLƒ›VUIVmk@Ubma@kkaVKUƒ™kmlXLWn™J¯ÒĊ°@zkºlLUŤn@@n›ô@lƁnmKkÈlxVw„@@mÈx˜@n²Uxl¤nbVxUzmJƒÒnš"],encodeOffsets:[[104828,25999]]}},{type:"Feature",id:"5307",properties:{name:"丽江市",cp:[100.448,26.955],childNum:5},geometry:{type:"Polygon",coordinates:["@@l@™„@w°ÓUnƒÜÑ°w@mČóšÝlU»n°„„VÜUbVbm¼@Ž°xôĸœVW¦¯Ĭlœ˜@zll@b„šWxXš‚a„X@ÆĠÆaXwl@XaƦn¼˜Jn@mnKW¯È»V¯°ak™VanXVwl@VyUĕVU„bÈīlaUk°ƒk¯lƒ²V˜Ukƛô@ƒ„I@mVwĊa„™ƒVaka„™ÆbUŽVLšaXIWKUw™ƒ„aWÑÅKUaVk°ƒ@Uw„ƒ¯¥›XğÝLkm¯Iǃóѯ»™aƒnUl±UĵÿlóÅIƒaU‚±Ik¼UŽVb¯bWxn°™ÒVbnLlޚ@@`kbmIkŽVn„JmnXl›@Ux™bkn@xóLUxVŽƒKóóŐW™™aÅxƒŽ™wƒ@™nÅm™šƒV™„ƒôX„ƒLlVU¤ƒb¦m¼™Ž@ĀƒbU‚„zUƂ°ÞVb@„Æbnššx"],encodeOffsets:[[101937,28227]]}},{type:"Feature",id:"5328",properties:{name:"西双版纳傣族自治州",cp:[100.8984,21.8628],childNum:3},geometry:{type:"Polygon",coordinates:["@@l²°ŽnÒlxÞ@„nWl„Lĸ™nbV¤V¦kbVV‚¦na„x°Vôa@„šb@lôXlWUšVXČKlmššU@bšWXXܛ°LÈa°LnU°‚ÞnšÑ„ġ°lƒnbšaƒ¯¯KWƒœó@kmK@UšĉV@k°„VV¹„a@y‚_ċl_nÓlL@anI@ƒóWl£VU—ƒl™kĕl™šKVw„U@™kVƒam¯ÅL@bƒ‚Ýk@Vn„UbÇbÝwÅ@ċ¥¯lk‚¼ÅŽ™Ò°b@¦nlUn@ŽÇV„mƁbWôU@ÝÅōm™¯ƒaU™™mk™WWw—@±ƒ™n¯U™è™a™Lƒ¯mƒL™škwƒl@°mnÈÒ¯šów@V™xƒĀU¤°Įƒ°Xl"],encodeOffsets:[[102376,22579]]}},{type:"Feature",id:"5305",properties:{name:"保山市",cp:[99.0637,24.9884],childNum:5},geometry:{type:"Polygon",coordinates:["@@X°„Il‚@¦ƒŽÈ¼m¼ÞaÞÅl„ÈxV¼šlVôÈÆlLޣȺlkUƒ‚ƒUw„¯UĕVwĊ@n¦mlnVĸIWÇ°LnƒUwl™šV„n@lnU˜„nJށl±U™¯LVUa°Ý„U„ÇĊýšVŤé„LlxÞL„ĀÜl²ĉ°KUaVƒ™_Źé@klw¯ƒlÅ—šW£ÅyU™W@wƒknal¥Uw@w™Uƒƒk¯ƒw¯aW±k_mJa™XVҙĠWb¯L¯Ý@w™wUƒ¯±Wk_ġƒwƒwōKmb@¤„bk°lĖƒô„UJƒšVnÅlťUš¯°VbnbWxX„m„ÞššWUĀ™L™yWzÛKmbUxVKkn݃kŽVšĀċ¤Ux„@Ž¯Žm@ƒ¦"],encodeOffsets:[[100440,25943]]}},{type:"Feature",id:"5304",properties:{name:"玉溪市",cp:[101.9312,23.8898],childNum:9},geometry:{type:"Polygon",coordinates:["@@l„„L°xXlWxXnlw„a„ţlaÞlÆĬnX„ƒ°wVw„l„@m™nw°VVIXllKšbnnV°lbU„UJ@ÈÇKVb—š@bW„°Vk¦kaWb°škxV¤È¼U°ôI@llblš²š@‚@œó@mm@VţkKl¹@yĉ¯°ÑšIXmWKnkšlV„ULlb@lnbVal@UnVJœU‚„nKWa„x„@lkkUlW²X„™‚l„K°„šl²@lšÞUŽ„U‚„UšVšVVXmššlLVnXWVUĉVaVb„W™ğVéšU„VU¹W»aVa„aW™Xƒ‚_U¥nÇķ¯™@a™lUnǍUyk@@wW@kbW¦UKÝwUmmƒƒLUnVxUVVlk¯mmnƒmkÇaŤ¯I@ƒl@@aĉw°ĕmU—L±ƒk™ÆéX™ÜÛ@yÈç@™Çġ„Ýķ—XmmÝVՙƒ™lmnkbmWkb@nl@nŽmš¯VxkJmUJ„ml¯™°makVVnVƒ¦™Wƒ—Wmnl@xmn„l‚I„¤„n™xU„ƒVUŽmX@˜ƒb@zl@¦Ýþ"],encodeOffsets:[[103703,24874]]}},{type:"Feature",id:"5333",properties:{name:"怒江傈僳族自治州",cp:[99.1516,26.5594],childNum:4},geometry:{type:"Polygon",coordinates:["@@WyX£lWlnnUU™„¥@ţV™Vw„JlÅ@wƒmö󙻂£kml¯U¥n¹Æ@ny@wmU@¯mnamÛnƒšUV¥ÈnĠy²œm¤„@ÆónݚnmlnbÞU‚¥„aV£kU„KWƒ„óšƒmIU¥ókwVólƒ™»¯™ƒL™ƒk@m™naWKÛwóњw@a±n—@VbUJ›LkaƒÝXĉƒ™„UV`lI@lnXÆƑkKmxÛXmlUKVmU²Klw@a™aó„@n™KXwVKU¯V¥mUnkm¥ĉ@UxVĖƒ°Vx„V„klmޙkKWĀkVWšnl°Lnm@°ŽUxlV@nk¦™JVÈ°ŽVÒ@nX°@ÆlUômlnôƒ²nxmłnVV„¯x@Èm°XblVUšl°@xkXU¤WXX‚W„Xƃ„mkÅJmށw±bƒxUīkKmÅVUĖÝèV„kx@š›lX„lnk¤ƒLkŽ‚Ėk¦‚xUššL°‚¯Ė@LnK@b°xVI„¥Ua°Ñ@»nm@¹‚KŎÞÈWln²n"],encodeOffsets:[[101071,28891]]}},{type:"Feature",id:"5331",properties:{name:"德宏傣族景颇族自治州",cp:[98.1299,24.5874],childNum:5},geometry:{type:"Polygon",coordinates:["@@„¥n@°@ƒVwČ£™ÿUlÞ„lmULVwnaÜLXyšzšKVÿ™XݙnƒWƒXwmaUa°¯V™ŦŽÆkUm„™VIƒ„ókĕl¯ƒa@£nama™@¯m¯œó@óyţbġkÅm±ÛammVkƒLwU`Wk@VƒkUmŃlUUKmbkkUVUwƒ¦óŽ°¼šbn°ô¦lºƒz@xšŽ¯„™@UŽ°nƒšU¤ţU„°VƆ@ÈmlnzÞl°¦Æa„xUxƒLkxWƒn@‚š²ŰšW„™‚@°ÈXl°Llx"],encodeOffsets:[[100440,25943]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/zhe_jiang_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"3311",properties:{name:"丽水市",cp:[119.5642,28.1854],childNum:9},geometry:{type:"Polygon",coordinates:["@@@V‚bVl@Xn‚UXƒKVŽ@¦nxlUXV‚n„KVmnL‚UV@bn¤lLXK˜²„`nnlJXIVJ‚I„Vnn°KnnVll@VLXWV@UkVaVK„zV@„ƒšVVaUK@U»VUl@@WnUUƒ@wVLn@Vwl@XW°LVbn@VU‚@X„l`@XnKVbkl@XVJlUnlV„„xlL@lnXl„@VšUnV°°„@a„UVLXblWVXn@VVUV@Lš¤VLV„U‚VbnalLUUVX_laVa„WVzXKV@@a@KUmImmXama@kU@yVIUK‚aVa@kXK@aWU@VIUmW@kkVm„Uš@VwUa@K@k@Uƒ`@kUKVk@UV@VaUm²Vy@klUUWUkVmUa@_ƒKVaXa›XmƒU@mUlWkaUXƒ@mmkL@w™JƒnVVÅbWKXa™@@I@aƒJUUÇ@V„UL™W@akLmb@K@a™XXw@mƒVmUVkUy@£@aU@@VkUWm@kUKƒXUWU_mW@wkkmJUUkLWWUXƒW@IkJ@k@mW_kӃ_Ul™Lƒm@I@aUa¯m@kƒa¯LUJƒ@mVVxUb™a@LUKkXƒbm@Uak@@a@Um`ƒIUbUJ@nUVW@@LnVV@lšUbVlUX@`š@blXklW„Ušm„Xlm¦U@@V¯bml@š@nUb@llnn@VbX@lV@ŽUVULmU@JVn„bVbkb™VWxU@@nUVk@"],encodeOffsets:[[121546,28992]]}},{type:"Feature",id:"3301",properties:{name:"杭州市",cp:[119.5313,29.8773],childNum:6},geometry:{type:"Polygon",coordinates:["@@X@l„°KXXlW„b@²„`šššb‚I„šX`l@„@bWl@n@VnLUV@V„@°¦@šl@XVlU@š@xVbUb@Vkb@‚@XVJVz™J@Lޚ@VmLUxUJ@LU„Vx‚b„xXUl@VaÈw„b‚aÞa@Vl@XUVx@V@V„LlbnV„al@lb„Vnn‚LnKnL@VlbVJXalIšb@KUU@mVInJ˜„U„Vl@xUšVLnUš@UÞaV@lkV@UanK„L@UlKVUnbÆmn@@nUlVnVJl@@UXU„L@WVIVJVxVLXV@IÜKnbn@V¥V@@I@ƒƒ„y°b@UUwnk°ÆƨVlUšçXm›£aƒÇ™IkVƒ@WV@@aWIUWUIkb@WW@UnƒK@UU@kaWVkƒVIVVnU@UWVUV@VmVkKkWIkVWaULU`UImJUImm—U@ƒƒwmwUV™IUWVkUamaU@mV—kƒb@KVU@aVU@anKULVJ‚U@kÛU™JUV›kkƒVakU@ƒaVwkW@UWkXmWaULUaUK@XƒJUUmƒVU@UVƒUkJ@ImwmKU@k„@lU„W@@akKm„kamIkWl_UwVm@UkaVUUaƒ@UamakbWlkL@aUalU@mkL@U@U™lmK@XkKm@Ýakb@xƒnXbƒ`ƒnUUU@›™U@™wU@@ƒmKkkƒV¯U@lULUbVbUb@V‚a@L™ºÝb@bLmK™x@VUL@bk@mxULWl"],encodeOffsets:[[121185,30184]]}},{type:"Feature",id:"3303",properties:{name:"温州市",cp:[120.498,27.8119],childNum:9},geometry:{type:"Polygon",coordinates:["@@ll@xnXV`VX„WVL@lXnlV@UV@@b@¤VzUlnV„U@nWxšW@b@LnalK@bšXVKUƒÈ@VV„I@b@Jš@WbXLÆaUU„mšI@xlKnn„@VWlbkXV‚@n„VWnœ‚WbUb„L@`VbUnVlVXkV@lUz±‚VnUbU@@VUlVL@l„_@V@l@LVbV@XLV`VÈlxn@lU@aœaVV‚k„@XJ@nl@@LU`°LVb„L°a@a„UVy@anI@a„a‚nV@²wÜJX@VšVV°k„na@WVk„aWwU@m@™ƒkƒaUĕ™ÝšÝŤnÈa„aóI›»@±X™WkUķ@kV±kw™ƒUkWw„™UƒÝ»ÛkɳlImaUaWóXÿǬk‚UnWVmmk™KţnŏÞğl™„UlUx@XWb„V@JkXƒ°mb@VULVxUVk@@LWWk@WIkšƒUkJmUkVmI@yƒ@Ua™kLm‚U@mUUUkaVk™@mK@UlUU@UmKmbUUUJ@n@KVLUL@VkJWXX`mnULWlkL@JVLVb@°kxkU@LVŽ™V@„VLV`UL@VUX"],encodeOffsets:[[122502,28334]]}},{type:"Feature",id:"3302",properties:{name:"宁波市",cp:[121.5967,29.6466],childNum:6},geometry:{type:"Polygon",coordinates:["@@Ċ¦ĸĀ°‚nXÞVšKškƨƑźÿ°»n„@wô¥ÜbœU°ÆXÞWóçĉݱIUƒÈ¥@U°wÆ»²mm_@aXƒVKÞVlk@akk›̅@£X»VwƏXWa¯aȗb™KƽۃĊ™xƒLóŽk@ƒƒƒ@¯nƒKUL@xkL›ÑkWULUUmJUXVŽU@mŽUX¯@V`mbXbV@@nn¤WXšx@škJ@nVVUVl²UbÝVUVk@Wx@V@„ƒVXzmlaƒL@VlLU`„XUVVVUnl@VbnJlnUVVnƒlUKkbmnn„VxlJnxmbU@UL@KUV™X@xmb@lk@mnVVUš™è"],encodeOffsets:[[123784,30977]]}},{type:"Feature",id:"3309",properties:{name:"舟山市",cp:[122.2559,30.2234],childNum:3},geometry:{type:"Polygon",coordinates:["@@l΢ƒʠþÆVĢLĊƒǬXĊ܄XôV„ÑÆw„ƒlšƏÈóVĭVǓ@ƒĉwɛkmK@ĉXīWaĉUĵÝmƒ¯ĉƒwĉ±±nż¯x@VǦV„²JĊÞôèÝXÅW¯›VÛaó¦@xƒŽmŽ¯¼ŹĀ"], +encodeOffsets:[[124437,30983]]}},{type:"Feature",id:"3310",properties:{name:"台州市",cp:[121.1353,28.6688],childNum:7},geometry:{type:"Polygon",coordinates:["@@lV„IVWVz@bXJl@Xal@°„nLll@nVxnV„K@UJVbƒ¦°„k`UIWJXnƚ@bUJ„Xl@lb„Wn@UzVV@bVVšmVnnJVXna‚bšKUKnUVVUnVLlKVLXa„Jm£@mU@WanaU_°@VWnV@UVWnIVVVKlXœÒlK@wVK„L°m„@„„l@ô„Kšw„ĉƾůUƒl£@»UƒVk„m@ƅUƒƒaÛIŏmUk@m„w@a™£ƒWk@ţšƒIm±@ankôUlaU™Uw¯ƒōaƒbÇbţm™ÞšÞVĖ„b„l@š@n‚VXxƒbUl@XmbƒŽ¯lUUU™W@ÛI±xU@mƒb@bmJ@bUzƒV@b¯bƒKUa¯KV_@Kk@@mWIƒ@lUU›b@bkVm@kwUÇU_WKU@Ux™@ƒVUnllX@Vn‚J@UXV@bWL@lUbbVLUJ@z‚V@lnbWbnnnJVŽ@L"],encodeOffsets:[[123312,29526]]}},{type:"Feature",id:"3307",properties:{name:"金华市",cp:[120.0037,29.1028],childNum:8},geometry:{type:"Polygon",coordinates:["@@nbVb„@VbUVlb@VUnVxk`lXnJlbnƒlL@bX@Vƒ@klƒV@nLnx@JlI„V‚U@VUVn„VV„I@WVLVbVKXbWnXl@VlXUx„b@ŽlVUbl„œlVUšIÜVnalKX@@bV@@aUUlUƒwUw„@naWW„UVaUUšaVb„LlxXJVk°ƒUƒlkU¥@k„a@LVlXLVlšVWznVn@lxšJl_@WX_@mVa„a@alU@kVVna„KVLlK„b@UUaVašbnUWmXU@k@yVI@ařWmXIVJl_¯ƒ„¥UaVI@ƒLmUUw@mkkmK¯ƒk@Wbk@WI@aUyUXƒJkU@bU@WLUyƒXUbkbW`UVVkKmbUaVUƒUK™£@KVUUUm@UWkXWaUKƒV@b¯ƒ¯mU™V@UkƒmW@kkKƒwUƒmkkVUI@WlkUamL@Wk_Wƒ@UVm@Ua¯KWXk@Uxm@UK@xV„mV@Xk@UVV¼@‚VLUb™Uƒ„U@ƒyULUbVlU@@XlVUVVbƒU@lXXVW@XUVl@@VUVƒÈn@VVU„@lVa@„U„mL@`X@`WL@VUX@lUL@xlx"],encodeOffsets:[[122119,29948]]}},{type:"Feature",id:"3308",properties:{name:"衢州市",cp:[118.6853,28.8666],childNum:5},geometry:{type:"Polygon",coordinates:["@@XkVKnwl@@aVK@UšwnL‚K@aÞaš¹@Kb@UVaUaVaVK@k°V„UllnL@„V@šxV@œšV@VV„m„_Wa„m@wlaÞbn@lL@WnLšk@V@VlK@nkVVb@blKXklakw@wVK@kVW@UXK@_‚W@_nKVƒ@ƒUb@kVƒUUm@„ÇVU@Uk@VU@WUXWW@k„VUaVUkU@WWXUKk@Ukmm¯LmmƒUJUIWJkImmƒ_—±WLkKm£@aVUmKUnƒLmWUkVmw@¥U„LVWm@WUka@UmmLmm@@bUX™@@WUIm@UVUK@UVUUU™VVJmb@b„Xn‚mVƒ¼nnn¦mJUVƒL„V@VW@UzUlVnUbl`UnVl@XU@kl@bmÈUx™Vk@@J@„ƒ¼W@ÅaVVnzmVƒ„@WJk@kWJ@ƒlXbWbXxmVnšlLXb@°lKVXnWšbWV„„X„mbV@Xl‚bšI@Kn@@x@šVLlm"],encodeOffsets:[[121185,30184]]}},{type:"Feature",id:"3306",properties:{name:"绍兴市",cp:[120.564,29.7565],childNum:6},geometry:{type:"Polygon",coordinates:["@@„x@„˜VnnVJnIVJV_VKXblUXJlŽlLUŽUnU@UVVX@ŽmVUUUJl„XUlbV@@V„LVmX@@XlaVJVXXJ@b‚@XU„@lUšJ„È‚bœ¤Ō„JšçV™UUnml@@kna@wšWVU@LVKV@namwkIUwmƒnmlaVL„kUmVUkmmIUak@VmUUVUƒWV_kK@U„K‚bnkWy„U@ƒ@UXwl@VUÞUVak±VUUU@mlI@™™wXWƒIWbUKkLUKVmUUmVVL™LambUWmIUm™nUU@aUUVym@ƒXkak@ƒW@z@lWVXnmV™aUbVb@VƒakLUKƒLmbUU@lkV@bƒbUb@nW`@Xk`™Ikwm@mUXy™UUkWKUk@Kƒb@lV¦klV„¯„UlWIkwƒKUa™bVVUbƒVXXmbƒ@Vx„xkVVV@bU@@aW@kLmb@lVUIVKmL@bUV@bUV@L„a˜lnUV@nbVbUlVXšJVUnx"],encodeOffsets:[[122997,30561]]}},{type:"Feature",id:"3304",properties:{name:"嘉兴市",cp:[120.9155,30.6354],childNum:6},geometry:{type:"Polygon",coordinates:["@@@blIX@@VÜVUnn@l‚k„lKnI°Þl`²LVKVbnbVaVLUVn@W¦@VkVVb„@VI„`@blLnL‚aX@„VVb@U‚@XlVa„@@kVaUKV»U_lWXUƒƒ@alb„k@VllnLVKn@@UVIUw@y°IVVXU@VV@lw„m@wVkƾaœJ‚LkΡƧƒ™l™LÝUmW¯ķÿĉ¥ƒIŋŽWn™èkVƧU¯ÅmlVx@V¯aƒz„Ž@„@JU@U¦m@@šnVmn@V„LV‚"],encodeOffsets:[[123233,31382]]}},{type:"Feature",id:"3305",properties:{name:"湖州市",cp:[119.8608,30.7782],childNum:4},geometry:{type:"Polygon",coordinates:["@@kLlƒkm@VmÛU@UW@kJ@aUƒK@UnmmU@™maÛL@JWUUKUwUIUJ@XƒKWV@Vk@UIUmVk@mm@ÅnmaUVkL@VƒKmLVbU@klU@ÝbV™@mVUKV™@wUkVƒ—ƒmIUJ@nVV@L™akJWbUIka@UmKmLKmmƒUUVk@@nmLX`WXUV@Ž@nUl™kmlU@Ub„„ƒxVVšIlV„Žšnn„@@n˜„UҚ@„°n@@xmb@„VbnV@šš„@b@`@L@L@x@blVklVbnnV@‚aXb°VlU@W„b°U„LXWVUV™„™VwÈwÜ»ĸaĠnUVw²X@V@lVU@wlaUUVm@knUV›"],encodeOffsets:[[123379,31500]]}}],UTF8Encoding:!0}}),i("echarts/chart/gauge",["require","./base","../util/shape/GaugePointer","zrender/shape/Text","zrender/shape/Line","zrender/shape/Rectangle","zrender/shape/Circle","zrender/shape/Sector","../config","../util/ecData","../util/accMath","zrender/tool/util","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e("./base"),n=e("../util/shape/GaugePointer"),a=e("zrender/shape/Text"),o=e("zrender/shape/Line"),r=e("zrender/shape/Rectangle"),s=e("zrender/shape/Circle"),l=e("zrender/shape/Sector"),h=e("../config");h.gauge={zlevel:0,z:2,center:["50%","50%"],clickable:!0,legendHoverLink:!0,radius:"75%",startAngle:225,endAngle:-45,min:0,max:100,splitNumber:10,axisLine:{show:!0,lineStyle:{color:[[.2,"#228b22"],[.8,"#48b"],[1,"#ff4500"]],width:30}},axisTick:{show:!0,splitNumber:5,length:8,lineStyle:{color:"#eee",width:1,type:"solid"}},axisLabel:{show:!0,textStyle:{color:"auto"}},splitLine:{show:!0,length:30,lineStyle:{color:"#eee",width:2,type:"solid"}},pointer:{show:!0,length:"80%",width:8,color:"auto"},title:{show:!0,offsetCenter:[0,"-40%"],textStyle:{color:"#333",fontSize:15}},detail:{show:!0,backgroundColor:"rgba(0,0,0,0)",borderWidth:0,borderColor:"#ccc",width:100,height:40,offsetCenter:[0,"40%"],textStyle:{color:"auto",fontSize:30}}};var m=e("../util/ecData"),V=e("../util/accMath"),U=e("zrender/tool/util");return t.prototype={type:h.CHART_TYPE_GAUGE,_buildShape:function(){var e=this.series;this._paramsMap={},this.selectedMap={};for(var t=0,i=e.length;i>t;t++)e[t].type===h.CHART_TYPE_GAUGE&&(this.selectedMap[e[t].name]=!0,e[t]=this.reformOption(e[t]),this.legendHoverLink=e[t].legendHoverLink||this.legendHoverLink,this._buildSingleGauge(t),this.buildMark(t));this.addShapeList()},_buildSingleGauge:function(e){var t=this.series[e];this._paramsMap[e]={center:this.parseCenter(this.zr,t.center),radius:this.parseRadius(this.zr,t.radius),startAngle:t.startAngle.toFixed(2)-0,endAngle:t.endAngle.toFixed(2)-0},this._paramsMap[e].totalAngle=this._paramsMap[e].startAngle-this._paramsMap[e].endAngle,this._colorMap(e),this._buildAxisLine(e),this._buildSplitLine(e),this._buildAxisTick(e),this._buildAxisLabel(e),this._buildPointer(e),this._buildTitle(e),this._buildDetail(e)},_buildAxisLine:function(e){var t=this.series[e];if(t.axisLine.show)for(var i,n,a=t.min,o=t.max-a,r=this._paramsMap[e],s=r.center,l=r.startAngle,h=r.totalAngle,V=r.colorArray,U=t.axisLine.lineStyle,d=this.parsePercent(U.width,r.radius[1]),p=r.radius[1],c=p-d,u=l,y=0,g=V.length;g>y;y++)n=l-h*(V[y][0]-a)/o,i=this._getSector(s,c,p,n,u,V[y][1],U,t.zlevel,t.z),u=n,i._animationAdd="r",m.set(i,"seriesIndex",e),m.set(i,"dataIndex",y),this.shapeList.push(i)},_buildSplitLine:function(e){var t=this.series[e];if(t.splitLine.show)for(var i,n,a,r=this._paramsMap[e],s=t.splitNumber,l=t.min,h=t.max-l,m=t.splitLine,V=this.parsePercent(m.length,r.radius[1]),U=m.lineStyle,d=U.color,p=r.center,c=r.startAngle*Math.PI/180,u=r.totalAngle*Math.PI/180,y=r.radius[1],g=y-V,b=0;s>=b;b++)i=c-u/s*b,n=Math.sin(i),a=Math.cos(i),this.shapeList.push(new o({zlevel:t.zlevel,z:t.z+1,hoverable:!1,style:{xStart:p[0]+a*y,yStart:p[1]-n*y,xEnd:p[0]+a*g,yEnd:p[1]-n*g,strokeColor:"auto"===d?this._getColor(e,l+h/s*b):d,lineType:U.type,lineWidth:U.width,shadowColor:U.shadowColor,shadowBlur:U.shadowBlur,shadowOffsetX:U.shadowOffsetX,shadowOffsetY:U.shadowOffsetY}}))},_buildAxisTick:function(e){var t=this.series[e];if(t.axisTick.show)for(var i,n,a,r=this._paramsMap[e],s=t.splitNumber,l=t.min,h=t.max-l,m=t.axisTick,V=m.splitNumber,U=this.parsePercent(m.length,r.radius[1]),d=m.lineStyle,p=d.color,c=r.center,u=r.startAngle*Math.PI/180,y=r.totalAngle*Math.PI/180,g=r.radius[1],b=g-U,f=0,k=s*V;k>=f;f++)f%V!==0&&(i=u-y/k*f,n=Math.sin(i),a=Math.cos(i),this.shapeList.push(new o({zlevel:t.zlevel,z:t.z+1,hoverable:!1,style:{xStart:c[0]+a*g,yStart:c[1]-n*g,xEnd:c[0]+a*b,yEnd:c[1]-n*b,strokeColor:"auto"===p?this._getColor(e,l+h/k*f):p,lineType:d.type,lineWidth:d.width,shadowColor:d.shadowColor,shadowBlur:d.shadowBlur,shadowOffsetX:d.shadowOffsetX,shadowOffsetY:d.shadowOffsetY}})))},_buildAxisLabel:function(e){var t=this.series[e];if(t.axisLabel.show)for(var i,n,o,r,s=t.splitNumber,l=t.min,h=t.max-l,m=t.axisLabel.textStyle,U=this.getFont(m),d=m.color,p=this._paramsMap[e],c=p.center,u=p.startAngle,y=p.totalAngle,g=p.radius[1]-this.parsePercent(t.splitLine.length,p.radius[1])-5,b=0;s>=b;b++)r=V.accAdd(l,V.accMul(V.accDiv(h,s),b)),i=u-y/s*b,n=Math.sin(i*Math.PI/180),o=Math.cos(i*Math.PI/180),i=(i+360)%360,this.shapeList.push(new a({zlevel:t.zlevel,z:t.z+1,hoverable:!1,style:{x:c[0]+o*g,y:c[1]-n*g,color:"auto"===d?this._getColor(e,r):d,text:this._getLabelText(t.axisLabel.formatter,r),textAlign:i>=110&&250>=i?"left":70>=i||i>=290?"right":"center",textBaseline:i>=10&&170>=i?"top":i>=190&&350>=i?"bottom":"middle",textFont:U,shadowColor:m.shadowColor,shadowBlur:m.shadowBlur,shadowOffsetX:m.shadowOffsetX,shadowOffsetY:m.shadowOffsetY}}))},_buildPointer:function(e){var t=this.series[e];if(t.pointer.show){var i=t.max-t.min,a=t.pointer,o=this._paramsMap[e],r=this.parsePercent(a.length,o.radius[1]),l=this.parsePercent(a.width,o.radius[1]),h=o.center,V=this._getValue(e);V=V2?2:l/2,color:"#fff"}});m.pack(p,this.series[e],e,this.series[e].data[0],0,this.series[e].data[0].name,V),this.shapeList.push(p),this.shapeList.push(new s({zlevel:t.zlevel,z:t.z+2,hoverable:!1,style:{x:h[0],y:h[1],r:a.width/2.5,color:"#fff"}}))}},_buildTitle:function(e){var t=this.series[e];if(t.title.show){var i=t.data[0],n=null!=i.name?i.name:"";if(""!==n){var o=t.title,r=o.offsetCenter,s=o.textStyle,l=s.color,h=this._paramsMap[e],m=h.center[0]+this.parsePercent(r[0],h.radius[1]),V=h.center[1]+this.parsePercent(r[1],h.radius[1]);this.shapeList.push(new a({zlevel:t.zlevel,z:t.z+(Math.abs(m-h.center[0])+Math.abs(V-h.center[1])<2*s.fontSize?2:1),hoverable:!1,style:{x:m,y:V,color:"auto"===l?this._getColor(e):l,text:n,textAlign:"center",textFont:this.getFont(s),shadowColor:s.shadowColor,shadowBlur:s.shadowBlur,shadowOffsetX:s.shadowOffsetX,shadowOffsetY:s.shadowOffsetY}}))}}},_buildDetail:function(e){var t=this.series[e];if(t.detail.show){var i=t.detail,n=i.offsetCenter,a=i.backgroundColor,o=i.textStyle,s=o.color,l=this._paramsMap[e],h=this._getValue(e),m=l.center[0]-i.width/2+this.parsePercent(n[0],l.radius[1]),V=l.center[1]+this.parsePercent(n[1],l.radius[1]);this.shapeList.push(new r({zlevel:t.zlevel,z:t.z+(Math.abs(m+i.width/2-l.center[0])+Math.abs(V+i.height/2-l.center[1])r;r++)o.push([a[r][0]*n+i,a[r][1]]);this._paramsMap[e].colorArray=o},_getColor:function(e,t){null==t&&(t=this._getValue(e));for(var i=this._paramsMap[e].colorArray,n=0,a=i.length;a>n;n++)if(i[n][0]>=t)return i[n][1];return i[i.length-1][1]},_getSector:function(e,t,i,n,a,o,r,s,h){return new l({zlevel:s,z:h,hoverable:!1,style:{x:e[0],y:e[1],r0:t,r:i,startAngle:n,endAngle:a,brushType:"fill",color:o,shadowColor:r.shadowColor,shadowBlur:r.shadowBlur,shadowOffsetX:r.shadowOffsetX,shadowOffsetY:r.shadowOffsetY}})},_getLabelText:function(e,t){if(e){if("function"==typeof e)return e.call(this.myChart,t);if("string"==typeof e)return e.replace("{value}",t)}return t},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()}},U.inherits(t,i),e("../chart").define("gauge",t),t}),i("echarts/util/shape/GaugePointer",["require","zrender/shape/Base","zrender/tool/util","./normalIsCover"],function(e){function t(e){i.call(this,e)}var i=e("zrender/shape/Base"),n=e("zrender/tool/util");return t.prototype={type:"gauge-pointer",buildPath:function(e,t){var i=t.r,n=t.width,a=t.angle,o=t.x-Math.cos(a)*n*(n>=i/3?1:2),r=t.y+Math.sin(a)*n*(n>=i/3?1:2);a=t.angle-Math.PI/2,e.moveTo(o,r),e.lineTo(t.x+Math.cos(a)*n,t.y-Math.sin(a)*n),e.lineTo(t.x+Math.cos(t.angle)*i,t.y-Math.sin(t.angle)*i),e.lineTo(t.x-Math.cos(a)*n,t.y+Math.sin(a)*n),e.lineTo(o,r)},getRect:function(e){if(e.__rect)return e.__rect;var t=2*e.width,i=e.x,n=e.y,a=i+Math.cos(e.angle)*e.r,o=n-Math.sin(e.angle)*e.r;return e.__rect={x:Math.min(i,a)-t,y:Math.min(n,o)-t,width:Math.abs(i-a)+t,height:Math.abs(n-o)+t},e.__rect},isCover:e("./normalIsCover")},n.inherits(t,i),t}),i("echarts/chart/funnel",["require","./base","zrender/shape/Text","zrender/shape/Line","zrender/shape/Polygon","../config","../util/ecData","../util/number","zrender/tool/util","zrender/tool/color","zrender/tool/area","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Line"),o=e("zrender/shape/Polygon"),r=e("../config");r.funnel={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,x:80,y:60,x2:80,y2:60,min:0,max:100,minSize:"0%",maxSize:"100%",sort:"descending",gap:0,funnelAlign:"center",itemStyle:{normal:{borderColor:"#fff",borderWidth:1,label:{show:!0,position:"outer"},labelLine:{show:!0,length:10,lineStyle:{width:1,type:"solid"}}},emphasis:{borderColor:"rgba(0,0,0,0)",borderWidth:1,label:{show:!0},labelLine:{show:!0}}}};var s=e("../util/ecData"),l=e("../util/number"),h=e("zrender/tool/util"),m=e("zrender/tool/color"),V=e("zrender/tool/area");return t.prototype={type:r.CHART_TYPE_FUNNEL,_buildShape:function(){var e=this.series,t=this.component.legend;this._paramsMap={},this._selected={},this.selectedMap={};for(var i,n=0,a=e.length;a>n;n++)if(e[n].type===r.CHART_TYPE_FUNNEL){if(e[n]=this.reformOption(e[n]),this.legendHoverLink=e[n].legendHoverLink||this.legendHoverLink,i=e[n].name||"",this.selectedMap[i]=t?t.isSelected(i):!0,!this.selectedMap[i])continue;this._buildSingleFunnel(n),this.buildMark(n)}this.addShapeList()},_buildSingleFunnel:function(e){var t=this.component.legend,i=this.series[e],n=this._mapData(e),a=this._getLocation(e);this._paramsMap[e]={location:a,data:n};for(var o,r=0,s=[],h=0,m=n.length;m>h;h++)o=n[h].name,this.selectedMap[o]=t?t.isSelected(o):!0,this.selectedMap[o]&&!isNaN(n[h].value)&&(s.push(n[h]),r++);if(0!==r){for(var V,U,d,p,c=this._buildFunnelCase(e),u=i.funnelAlign,y=i.gap,g=r>1?(a.height-(r-1)*y)/r:a.height,b=a.y,f="descending"===i.sort?this._getItemWidth(e,s[0].value):l.parsePercent(i.minSize,a.width),k="descending"===i.sort?1:0,x=a.centerX,_=[],h=0,m=s.length;m>h;h++)if(o=s[h].name,this.selectedMap[o]&&!isNaN(s[h].value)){switch(V=m-2>=h?this._getItemWidth(e,s[h+k].value):"descending"===i.sort?l.parsePercent(i.minSize,a.width):l.parsePercent(i.maxSize,a.width),u){case"left":U=a.x;break;case"right":U=a.x+a.width-f;break;default:U=x-f/2}d=this._buildItem(e,s[h]._index,t?t.getColor(o):this.zr.getColor(s[h]._index),U,b,f,V,g,u),b+=g+y,p=d.style.pointList,_.unshift([p[0][0]-10,p[0][1]]),_.push([p[1][0]+10,p[1][1]]),0===h&&(0===f?(p=_.pop(),"center"==u&&(_[0][0]+=10),"right"==u&&(_[0][0]=p[0]),_[0][1]-="center"==u?10:15,1==m&&(p=d.style.pointList)):(_[_.length-1][1]-=5,_[0][1]-=5)),f=V}c&&(_.unshift([p[3][0]-10,p[3][1]]),_.push([p[2][0]+10,p[2][1]]),0===f?(p=_.pop(),"center"==u&&(_[0][0]+=10),"right"==u&&(_[0][0]=p[0]),_[0][1]+="center"==u?10:15):(_[_.length-1][1]+=5,_[0][1]+=5),c.style.pointList=_)}},_buildFunnelCase:function(e){var t=this.series[e];if(this.deepQuery([t,this.option],"calculable")){var i=this._paramsMap[e].location,n=10,a={hoverable:!1,style:{pointListd:[[i.x-n,i.y-n],[i.x+i.width+n,i.y-n],[i.x+i.width+n,i.y+i.height+n],[i.x-n,i.y+i.height+n]],brushType:"stroke",lineWidth:1,strokeColor:t.calculableHolderColor||this.ecTheme.calculableHolderColor||r.calculableHolderColor}};return s.pack(a,t,e,void 0,-1),this.setCalculable(a),a=new o(a),this.shapeList.push(a),a}},_getLocation:function(e){var t=this.series[e],i=this.zr.getWidth(),n=this.zr.getHeight(),a=this.parsePercent(t.x,i),o=this.parsePercent(t.y,n),r=null==t.width?i-a-this.parsePercent(t.x2,i):this.parsePercent(t.width,i);return{x:a,y:o,width:r,height:null==t.height?n-o-this.parsePercent(t.y2,n):this.parsePercent(t.height,n),centerX:a+r/2}},_mapData:function(e){function t(e,t){return"-"===e.value?1:"-"===t.value?-1:t.value-e.value}function i(e,i){return-t(e,i)}for(var n=this.series[e],a=h.clone(n.data),o=0,r=a.length;r>o;o++)a[o]._index=o;return"none"!=n.sort&&a.sort("descending"===n.sort?t:i),a},_buildItem:function(e,t,i,n,a,o,r,l,h){var m=this.series,V=m[e],U=V.data[t],d=this.getPolygon(e,t,i,n,a,o,r,l,h);s.pack(d,m[e],e,m[e].data[t],t,m[e].data[t].name),this.shapeList.push(d);var p=this.getLabel(e,t,i,n,a,o,r,l,h);s.pack(p,m[e],e,m[e].data[t],t,m[e].data[t].name),this.shapeList.push(p),this._needLabel(V,U,!1)||(p.invisible=!0);var c=this.getLabelLine(e,t,i,n,a,o,r,l,h);this.shapeList.push(c),this._needLabelLine(V,U,!1)||(c.invisible=!0);var u=[],y=[];return this._needLabelLine(V,U,!0)&&(u.push(c.id),y.push(c.id)),this._needLabel(V,U,!0)&&(u.push(p.id),y.push(d.id)),d.hoverConnect=u,p.hoverConnect=y,d},_getItemWidth:function(e,t){var i=this.series[e],n=this._paramsMap[e].location,a=i.min,o=i.max,r=l.parsePercent(i.minSize,n.width),s=l.parsePercent(i.maxSize,n.width);return(t-a)*(s-r)/(o-a)+r},getPolygon:function(e,t,i,n,a,r,s,l,h){var V,U=this.series[e],d=U.data[t],p=[d,U],c=this.deepMerge(p,"itemStyle.normal")||{},u=this.deepMerge(p,"itemStyle.emphasis")||{},y=this.getItemStyleColor(c.color,e,t,d)||i,g=this.getItemStyleColor(u.color,e,t,d)||("string"==typeof y?m.lift(y,-.2):y);switch(h){case"left":V=n;break;case"right":V=n+(r-s);break;default:V=n+(r-s)/2}var b={zlevel:U.zlevel,z:U.z,clickable:this.deepQuery(p,"clickable"),style:{pointList:[[n,a],[n+r,a],[V+s,a+l],[V,a+l]],brushType:"both",color:y,lineWidth:c.borderWidth,strokeColor:c.borderColor},highlightStyle:{color:g,lineWidth:u.borderWidth,strokeColor:u.borderColor}};return this.deepQuery([d,U,this.option],"calculable")&&(this.setCalculable(b),b.draggable=!0),new o(b)},getLabel:function(e,t,i,a,o,r,s,l,U){var d,p=this.series[e],c=p.data[t],u=this._paramsMap[e].location,y=h.merge(h.clone(c.itemStyle)||{},p.itemStyle),g="normal",b=y[g].label,f=b.textStyle||{},k=y[g].labelLine.length,x=this.getLabelText(e,t,g),_=this.getFont(f),L=i;b.position=b.position||y.normal.label.position,"inner"===b.position||"inside"===b.position||"center"===b.position?(d=U,L=Math.max(r,s)/2>V.getTextWidth(x,_)?"#fff":m.reverse(i)):d="left"===b.position?"right":"left";var W={zlevel:p.zlevel,z:p.z+1,style:{x:this._getLabelPoint(b.position,a,u,r,s,k,U),y:o+l/2,color:f.color||L,text:x,textAlign:f.align||d,textBaseline:f.baseline||"middle",textFont:_}};return g="emphasis",b=y[g].label||b,f=b.textStyle||f,k=y[g].labelLine.length||k,b.position=b.position||y.normal.label.position,x=this.getLabelText(e,t,g),_=this.getFont(f),L=i,"inner"===b.position||"inside"===b.position||"center"===b.position?(d=U,L=Math.max(r,s)/2>V.getTextWidth(x,_)?"#fff":m.reverse(i)):d="left"===b.position?"right":"left",W.highlightStyle={x:this._getLabelPoint(b.position,a,u,r,s,k,U),color:f.color||L,text:x,textAlign:f.align||d,textFont:_,brushType:"fill"},new n(W)},getLabelText:function(e,t,i){var n=this.series,a=n[e],o=a.data[t],r=this.deepQuery([o,a],"itemStyle."+i+".label.formatter");return r?"function"==typeof r?r.call(this.myChart,{seriesIndex:e,seriesName:a.name||"",series:a,dataIndex:t,data:o,name:o.name,value:o.value}):"string"==typeof r?r=r.replace("{a}","{a0}").replace("{b}","{b0}").replace("{c}","{c0}").replace("{a0}",a.name).replace("{b0}",o.name).replace("{c0}",o.value):void 0:o.name},getLabelLine:function(e,t,i,n,o,r,s,l,m){var V=this.series[e],U=V.data[t],d=this._paramsMap[e].location,p=h.merge(h.clone(U.itemStyle)||{},V.itemStyle),c="normal",u=p[c].labelLine,y=p[c].labelLine.length,g=u.lineStyle||{},b=p[c].label;b.position=b.position||p.normal.label.position;var f={zlevel:V.zlevel,z:V.z+1,hoverable:!1,style:{xStart:this._getLabelLineStartPoint(n,d,r,s,m),yStart:o+l/2,xEnd:this._getLabelPoint(b.position,n,d,r,s,y,m),yEnd:o+l/2,strokeColor:g.color||i,lineType:g.type,lineWidth:g.width}};return c="emphasis",u=p[c].labelLine||u,y=p[c].labelLine.length||y,g=u.lineStyle||g,b=p[c].label||b,b.position=b.position,f.highlightStyle={xEnd:this._getLabelPoint(b.position,n,d,r,s,y,m),strokeColor:g.color||i,lineType:g.type,lineWidth:g.width},new a(f)},_getLabelPoint:function(e,t,i,n,a,o,r){switch(e="inner"===e||"inside"===e?"center":e){case"center":return"center"==r?t+n/2:"left"==r?t+10:t+n-10;case"left":return"auto"===o?i.x-10:"center"==r?i.centerX-Math.max(n,a)/2-o:"right"==r?t-(a>n?a-n:0)-o:i.x-o;default:return"auto"===o?i.x+i.width+10:"center"==r?i.centerX+Math.max(n,a)/2+o:"right"==r?i.x+i.width+o:t+Math.max(n,a)+o}},_getLabelLineStartPoint:function(e,t,i,n,a){return"center"==a?t.centerX:n>i?e+Math.min(i,n)/2:e+Math.max(i,n)/2},_needLabel:function(e,t,i){return this.deepQuery([t,e],"itemStyle."+(i?"emphasis":"normal")+".label.show")},_needLabelLine:function(e,t,i){return this.deepQuery([t,e],"itemStyle."+(i?"emphasis":"normal")+".labelLine.show")},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()}},h.inherits(t,i),e("../chart").define("funnel",t),t}),i("echarts/chart/eventRiver",["require","./base","../layout/eventRiver","zrender/shape/Polygon","../component/axis","../component/grid","../component/dataZoom","../config","../util/ecData","../util/date","zrender/tool/util","zrender/tool/color","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o);var r=this;r._ondragend=function(){r.isDragend=!0},this.refresh(a)}var i=e("./base"),n=e("../layout/eventRiver"),a=e("zrender/shape/Polygon");e("../component/axis"),e("../component/grid"),e("../component/dataZoom");var o=e("../config");o.eventRiver={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,itemStyle:{normal:{borderColor:"rgba(0,0,0,0)",borderWidth:1,label:{show:!0,position:"inside",formatter:"{b}"}},emphasis:{borderColor:"rgba(0,0,0,0)",borderWidth:1,label:{show:!0}}}};var r=e("../util/ecData"),s=e("../util/date"),l=e("zrender/tool/util"),h=e("zrender/tool/color");return t.prototype={type:o.CHART_TYPE_EVENTRIVER,_buildShape:function(){var e=this.series;this.selectedMap={},this._dataPreprocessing();for(var t=this.component.legend,i=[],a=0;an;n++)if(i[n].type===this.type){e=this.component.xAxis.getAxis(i[n].xAxisIndex||0);for(var o=0,r=i[n].data.length;r>o;o++){t=i[n].data[o].evolution;for(var l=0,h=t.length;h>l;l++)t[l].timeScale=e.getCoord(s.getNewDate(t[l].time)-0),t[l].valueScale=Math.pow(t[l].value,.8)}}this._intervalX=Math.round(this.component.grid.getWidth()/40)},_drawEventRiver:function(){for(var e=this.series,t=0;ta)){for(var o=[],r=[],s=0;a>s;s++)o.push(n[s].timeScale),r.push(n[s].valueScale);var l=[];l.push([o[0],i]);var s=0;for(s=0;a-1>s;s++)l.push([(o[s]+o[s+1])/2,r[s]/-2+i]);for(l.push([(o[s]+(o[s]+t))/2,r[s]/-2+i]),l.push([o[s]+t,i]),l.push([(o[s]+(o[s]+t))/2,r[s]/2+i]),s=a-1;s>0;s--)l.push([(o[s]+o[s-1])/2,r[s-1]/2+i]);return l}},ondragend:function(e,t){this.isDragend&&e.target&&(t.dragOut=!0,t.dragIn=!0,t.needRefresh=!1,this.isDragend=!1)},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()}},l.inherits(t,i),e("../chart").define("eventRiver",t),t}),i("echarts/layout/eventRiver",["require"],function(){function e(e,i,o){function r(e,t){var i=e.importance,n=t.importance;return i>n?-1:n>i?1:0}for(var s=4,l=0;l=e)return[0];for(var t=[];e--;)t.push(0);return t}(),u=c.slice(0),y=[],g=0,b=0,l=0;l.5?.5:1,r=t.y,s=(t.height-n)/i,l=0,h=e.length;h>l;l++){var m=e[l];m.y=r+s*m.y+m._offset*o,delete m.time,delete m.value,delete m.xpx,delete m.ypx,delete m._offset;for(var V=m.evolution,U=0,d=V.length;d>U;U++)V[U].valueScale*=s}}function i(e,t,i,n){if(e===i)throw new Error("x0 is equal with x1!!!");if(t===n)return function(){return t};var a=(t-n)/(e-i),o=(n*e-t*i)/(e-i);return function(e){return a*e+o}}function n(e,t,n){var a=~~t,o=e.time.length;e.xpx=[],e.ypx=[];for(var r,s=0,l=0,h=0,m=0,V=0;o>s;s++){l=~~e.time[s],m=e.value[s]/2,s===o-1?(h=l+a,V=0):(h=~~e.time[s+1],V=e.value[s+1]/2),r=i(l,m,h,V);for(var U=l;h>U;U++)e.xpx.push(U-n),e.ypx.push(r(U))}e.xpx.push(h-n),e.ypx.push(V)}function a(e,t,i){for(var n,a=0,o=t.xpx.length,r=0;o>r;r++)n=i(t,r),a=Math.max(a,n+e[t.xpx[r]]);for(r=0;o>r;r++)n=i(t,r),e[t.xpx[r]]=a+n;return a}return e}),i("echarts/chart/venn",["require","./base","zrender/shape/Text","zrender/shape/Circle","zrender/shape/Path","../config","../util/ecData","zrender/tool/util","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Circle"),o=e("zrender/shape/Path"),r=e("../config");r.venn={zlevel:0,z:1,calculable:!1};var s=e("../util/ecData"),l=e("zrender/tool/util");return t.prototype={type:r.CHART_TYPE_VENN,_buildShape:function(){this.selectedMap={},this._symbol=this.option.symbolList,this._queryTarget,this._dropBoxList=[],this._vennDataCounter=0;for(var e=this.series,t=this.component.legend,i=0;ia[1].value?(t=this.zr.getHeight()/3,i=t*Math.sqrt(a[1].value)/Math.sqrt(a[0].value)):(i=this.zr.getHeight()/3,t=i*Math.sqrt(a[0].value)/Math.sqrt(a[1].value));var o=this.zr.getWidth()/2-t,r=(t+i)/2*Math.sqrt(a[2].value)/Math.sqrt((a[0].value+a[1].value)/2),s=t+i;0!==a[2].value&&(s=this._getCoincideLength(a[0].value,a[1].value,a[2].value,t,i,r,Math.abs(t-i),t+i));var l=o+s,h=this.zr.getHeight()/2;if(this._buildItem(e,0,a[0],o,h,t),this._buildItem(e,1,a[1],l,h,i),0!==a[2].value&&a[2].value!==a[0].value&&a[2].value!==a[1].value){var m=(t*t-i*i)/(2*s)+s/2,V=s/2-(t*t-i*i)/(2*s),U=Math.sqrt(t*t-m*m),d=0,p=0;a[0].value>a[1].value&&o+m>l&&(p=1),a[0].valuel&&(d=1),this._buildCoincideItem(e,2,a[2],o+m,h-U,h+U,t,i,d,p)}},_getCoincideLength:function(e,t,i,n,a,o,r,s){var l=(n*n-a*a)/(2*o)+o/2,h=o/2-(n*n-a*a)/(2*o),m=Math.acos(l/n),V=Math.acos(h/a),U=n*n*Math.PI,d=m*n*n-l*n*Math.sin(m)+V*a*a-h*a*Math.sin(V),p=d/U,c=i/e,u=Math.abs(p/c);return u>.999&&1.001>u?o:.999>=u?(s=o,o=(o+r)/2,this._getCoincideLength(e,t,i,n,a,o,r,s)):(r=o,o=(o+s)/2,this._getCoincideLength(e,t,i,n,a,o,r,s))},_buildItem:function(e,t,i,n,a,o){var r=this.series,l=r[e],h=this.getCircle(e,t,i,n,a,o);if(s.pack(h,l,e,i,t,i.name),this.shapeList.push(h),l.itemStyle.normal.label.show){var m=this.getLabel(e,t,i,n,a,o);s.pack(m,l,e,l.data[t],t,l.data[t].name),this.shapeList.push(m)}},_buildCoincideItem:function(e,t,i,n,a,r,l,h,m,V){var U=this.series,d=U[e],p=[i,d],c=this.deepMerge(p,"itemStyle.normal")||{},u=this.deepMerge(p,"itemStyle.emphasis")||{},y=c.color||this.zr.getColor(t),g=u.color||this.zr.getColor(t),b="M"+n+","+a+"A"+l+","+l+",0,"+m+",1,"+n+","+r+"A"+h+","+h+",0,"+V+",1,"+n+","+a,f={color:y,path:b},k={zlevel:d.zlevel,z:d.z,style:f,highlightStyle:{color:g,lineWidth:u.borderWidth,strokeColor:u.borderColor}};k=new o(k),k.buildPathArray&&(k.style.pathArray=k.buildPathArray(f.path)),s.pack(k,U[e],0,i,t,i.name),this.shapeList.push(k)},getCircle:function(e,t,i,n,o,r){var s=this.series[e],l=[i,s],h=this.deepMerge(l,"itemStyle.normal")||{},m=this.deepMerge(l,"itemStyle.emphasis")||{},V=h.color||this.zr.getColor(t),U=m.color||this.zr.getColor(t),d={zlevel:s.zlevel,z:s.z,clickable:!0,style:{x:n,y:o,r:r,brushType:"fill",opacity:1,color:V},highlightStyle:{color:U,lineWidth:m.borderWidth,strokeColor:m.borderColor}};return this.deepQuery([i,s,this.option],"calculable")&&(this.setCalculable(d),d.draggable=!0),new a(d)},getLabel:function(e,t,i,a,o,r){var s=this.series[e],l=s.itemStyle,h=[i,s],m=this.deepMerge(h,"itemStyle.normal")||{},V="normal",U=l[V].label,d=U.textStyle||{},p=this.getLabelText(t,i,V),c=this.getFont(d),u=m.color||this.zr.getColor(t),y=d.fontSize||12,g={zlevel:s.zlevel,z:s.z,style:{x:a,y:o-r-y,color:d.color||u,text:p,textFont:c,textAlign:"center"}};return new n(g)},getLabelText:function(e,t,i){var n=this.series,a=n[0],o=this.deepQuery([t,a],"itemStyle."+i+".label.formatter");return o?"function"==typeof o?o(a.name,t.name,t.value):"string"==typeof o?(o=o.replace("{a}","{a0}").replace("{b}","{b0}").replace("{c}","{c0}"),o=o.replace("{a0}",a.name).replace("{b0}",t.name).replace("{c0}",t.value)):void 0:t.name},refresh:function(e){e&&(this.option=e,this.series=e.series),this._buildShape()}},l.inherits(t,i),e("../chart").define("venn",t),t}),i("echarts/chart/treemap",["require","./base","zrender/tool/area","zrender/shape/Rectangle","zrender/shape/Text","zrender/shape/Line","../layout/TreeMap","../data/Tree","../config","../util/ecData","zrender/config","zrender/tool/event","zrender/tool/util","zrender/tool/color","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a);var r=this;r._onclick=function(e){return r.__onclick(e)},r.zr.on(V.EVENT.CLICK,r._onclick)}var i=e("./base"),n=e("zrender/tool/area"),a=e("zrender/shape/Rectangle"),o=e("zrender/shape/Text"),r=e("zrender/shape/Line"),s=e("../layout/TreeMap"),l=e("../data/Tree"),h=e("../config");h.treemap={zlevel:0,z:1,calculable:!1,clickable:!0,center:["50%","50%"],size:["80%","80%"],root:"",itemStyle:{normal:{label:{ +show:!0,x:5,y:12,textStyle:{align:"left",color:"#000",fontFamily:"Arial",fontSize:13,fontStyle:"normal",fontWeight:"normal"}},breadcrumb:{show:!0,textStyle:{}},borderWidth:1,borderColor:"#ccc",childBorderWidth:1,childBorderColor:"#ccc"},emphasis:{}}};var m=e("../util/ecData"),V=e("zrender/config"),U=(e("zrender/tool/event"),e("zrender/tool/util")),d=e("zrender/tool/color");return t.prototype={type:h.CHART_TYPE_TREEMAP,refresh:function(e){this.clear(),e&&(this.option=e,this.series=this.option.series),this._treesMap={};for(var t=this.series,i=this.component.legend,n=0;nt.width||e.normal.label.y+U>t.height)&&(h=""):h="",e.emphasis.label.show?(s.x+u>t.width||s.y+y>t.height)&&(p=""):p="";var g={style:{textX:t.x+e.normal.label.x,textY:t.y+e.normal.label.y,text:h,textPosition:"specific",textColor:o.color,textFont:m},highlightStyle:{textX:t.x+e.emphasis.label.x,textY:t.y+e.emphasis.label.y,text:p,textColor:s.color,textPosition:"specific"}};return g},getLabelText:function(e,t,i){return i?"function"==typeof i?i.call(this.myChart,e,t):"string"==typeof i?(i=i.replace("{b}","{b0}").replace("{c}","{c0}"),i=i.replace("{b0}",e).replace("{c0}",t)):void 0:e},_buildChildrenTreemap:function(e,t,i,n){for(var a=i.width*i.height,o=0,r=[],l=0;l ":"")},V),clickable:!0,highlightStyle:p});m.set(u,"seriesIndex",t),m.set(u,"name",a[c]),i+=u.getRect(u.style).width,this.shapeList.push(u)}},__onclick:function(e){var t=e.target;if(t){var i=m.get(t,"seriesIndex"),n=m.get(t,"name"),a=this._treesMap[i],o=a.getNodeById(n);o&&o.children.length&&this._buildTreemap(o,i)}}},U.inherits(t,i),e("../chart").define("treemap",t),t}),i("echarts/layout/TreeMap",["require"],function(){function e(e){({x:e.x,y:e.y,width:e.width,height:e.height});this.x=e.x,this.y=e.y,this.width=e.width,this.height=e.height}return e.prototype.run=function(e){var t=[];return this._squarify(e,{x:this.x,y:this.y,width:this.width,height:this.height},t),t},e.prototype._squarify=function(e,t,i){var n="VERTICAL",a=t.width,o=t.height;t.widthl;l++)r[s].y+=r[l].height}var h={};if("VERTICAL"==n){for(var m=0;ml;l++){var h=i*e[l]/o;a.push({width:s,height:h})}return a},e.prototype._isFirstBetter=function(e,t){var i=e[0].height/e[0].width;i=i>1?1/i:i;var n=t[0].height/t[0].width;return n=n>1?1/n:n,Math.abs(i-1)<=Math.abs(n-1)?!0:!1},e}),i("echarts/data/Tree",["require","zrender/tool/util"],function(e){function t(e,t){this.id=e,this.depth=0,this.height=0,this.children=[],this.parent=null,this.data=t||null}function i(e){this.root=new t(e)}var n=e("zrender/tool/util");return t.prototype.add=function(e){var t=this.children;e.parent!==this&&(t.push(e),e.parent=this)},t.prototype.remove=function(e){var t=this.children,i=n.indexOf(t,e);i>=0&&(t.splice(i,1),e.parent=null)},t.prototype.traverse=function(e,t){e.call(t,this);for(var i=0;it&&(t=n.height)}this.height=t+1},t.prototype.getNodeById=function(e){if(this.id===e)return this;for(var t=0;t0&&this._buildLink(i,e)},this);var n=e.roam===!0||"move"===e.roam,a=e.roam===!0||"scale"===e.roam;this.zr.modLayer(this.getZlevelBase(),{panable:n,zoomable:a}),(this.query("markPoint.effect.show")||this.query("markLine.effect.show"))&&this.zr.modLayer(m.EFFECT_ZLEVEL,{panable:n,zoomable:a}),this.addShapeList()},_buildItem:function(e,t,i){var n=[e.data,t],r=this.deepQuery(n,"symbol"),s=this.deepMerge(n,"itemStyle.normal")||{},l=this.deepMerge(n,"itemStyle.emphasis")||{},h=s.color||this.zr.getColor(),m=l.color||this.zr.getColor(),U=-e.layout.angle||0;e.id===this.tree.root.id&&(U=0);var d="right";Math.abs(U)>=Math.PI/2&&Math.abs(U)<3*Math.PI/2&&(U+=Math.PI,d="left");var p=[U,e.layout.position[0],e.layout.position[1]],c=new a({zlevel:this.getZlevelBase(),z:this.getZBase()+1,rotation:p,clickable:this.deepQuery(n,"clickable"),style:{x:e.layout.position[0]-.5*e.layout.width,y:e.layout.position[1]-.5*e.layout.height,width:e.layout.width,height:e.layout.height,iconType:r,color:h,brushType:"both",lineWidth:s.borderWidth,strokeColor:s.borderColor},highlightStyle:{color:m,lineWidth:l.borderWidth,strokeColor:l.borderColor}});c.style.iconType.match("image")&&(c.style.image=c.style.iconType.replace(new RegExp("^image:\\/\\/"),""),c=new o({rotation:p,style:c.style,highlightStyle:c.highlightStyle,clickable:c.clickable,zlevel:this.getZlevelBase(),z:this.getZBase()})),this.deepQuery(n,"itemStyle.normal.label.show")&&(c.style.text=null==e.data.label?e.id:e.data.label,c.style.textPosition=this.deepQuery(n,"itemStyle.normal.label.position"),"radial"===t.orient&&"inside"!==c.style.textPosition&&(c.style.textPosition=d),c.style.textColor=this.deepQuery(n,"itemStyle.normal.label.textStyle.color"),c.style.textFont=this.getFont(this.deepQuery(n,"itemStyle.normal.label.textStyle")||{})),this.deepQuery(n,"itemStyle.emphasis.label.show")&&(c.highlightStyle.textPosition=this.deepQuery(n,"itemStyle.emphasis.label.position"),c.highlightStyle.textColor=this.deepQuery(n,"itemStyle.emphasis.label.textStyle.color"),c.highlightStyle.textFont=this.getFont(this.deepQuery(n,"itemStyle.emphasis.label.textStyle")||{})),V.pack(c,t,i,e.data,0,e.id),this.shapeList.push(c)},_buildLink:function(e,t){var i=t.itemStyle.normal.lineStyle;if("broken"===i.type)return void this._buildBrokenLine(e,i,t);for(var n=0;nr&&(t=r),r>n&&(n=r)}e.layout.position[0]=e.children.length>0?(t+n)/2:0;var s=this._layerOffsets[e.depth]||0;if(s>e.layout.position[0]){var l=s-e.layout.position[0];this._shiftSubtree(e,l);for(var a=e.depth+1;ai;i++)this._buildTextShape(e[i],0,i);this.addShapeList()},_buildTextShape:function(e,t,i){var a=this.series,o=a[t],s=o.name||"",h=o.data[i],m=[h,o],V=this.component.legend,U=V?V.getColor(s):this.zr.getColor(t),d=this.deepMerge(m,"itemStyle.normal")||{},p=this.deepMerge(m,"itemStyle.emphasis")||{},c=this.getItemStyleColor(d.color,t,i,h)||U,u=this.getItemStyleColor(p.color,t,i,h)||("string"==typeof c?l.lift(c,-.2):c),y=new n({zlevel:o.zlevel,z:o.z,hoverable:!0,clickable:this.deepQuery(m,"clickable"),style:{x:0,y:0,text:e.text,color:c,textFont:[e.style,e.weight,e.size+"px",e.font].join(" "),textBaseline:"alphabetic",textAlign:"center"},highlightStyle:{brushType:p.borderWidth?"both":"fill",color:u,lineWidth:p.borderWidth||0,strokeColor:p.borderColor},position:[e.x,e.y],rotation:[-e.rotate/180*Math.PI,0,0]});r.pack(y,o,t,h,i,h.name),this.shapeList.push(y)}},s.inherits(t,i),e("../chart").define("wordCloud",t),t}),i("echarts/layout/WordCloud",["require","../layout/WordCloudRectZero","zrender/tool/util"],function(e){function t(e){this._init(e)}var i=e("../layout/WordCloudRectZero"),n=e("zrender/tool/util");return t.prototype={start:function(){function e(){p.totalArea=r,U.autoSizeCal.enable&&p._autoCalTextSize(m,r,a,o,U.autoSizeCal.minSize),V.timer&&clearInterval(V.timer),V.timer=setInterval(t,0),t()}function t(){for(var e,t=+new Date,i=m.length;+new Date-t>1,e.y=d[1]>>1,p._cloudSprite(e,m,s),e.hasText&&p._place(n,e,h)&&(l.push(e),e.x-=d[0]>>1,e.y-=d[1]>>1);s>=i&&(p.stop(),p._fixTagPosition(l),V.endcallback(l))}var n=null,a=0,o=0,r=0,s=-1,l=[],h=null,m=this.wordsdata,V=this.defaultOption,U=V.wordletype,d=V.size,p=this,c=new i({type:U.type,width:d[0],height:d[1]});return c.calculate(function(t){n=t.initarr,a=t.maxWit,o=t.maxHit,r=t.area,h=t.imgboard,e()},this),this},_fixTagPosition:function(e){for(var t=this.defaultOption.center,i=0,n=e.length;n>i;i++)e[i].x+=t[0],e[i].y+=t[1]},stop:function(){return this.defaultOption.timer&&(clearInterval(this.defaultOption.timer),this.defaultOption.timer=null),this},end:function(e){return e&&(this.defaultOption.endcallback=e),this},_init:function(e){this.defaultOption={},this._initProperty(e),this._initMethod(e),this._initCanvas(),this._initData(e.data)},_initData:function(e){var t=this,i=t.defaultOption;this.wordsdata=e.map(function(e,n){return e.text=i.text.call(t,e,n),e.font=i.font.call(t,e,n),e.style=i.fontStyle.call(t,e,n),e.weight=i.fontWeight.call(t,e,n),e.rotate=i.rotate.call(t,e,n),e.size=~~i.fontSize.call(t,e,n),e.padding=i.padding.call(t,e,n),e}).sort(function(e,t){return t.value-e.value})},_initMethod:function(e){function t(e){return e.name}function i(){return"sans-serif"}function n(){return"normal"}function a(e){return e.value}function o(){return 0}function r(e){return function(){return e[Math.round(Math.random()*(e.length-1))]}}function s(){return 0}function l(e){var t=e[0]/e[1];return function(e){return[t*(e*=.1)*Math.cos(e),e*Math.sin(e)]}}function h(e){var t=4,i=t*e[0]/e[1],n=0,a=0;return function(e){var o=0>e?-1:1;switch(Math.sqrt(1+4*o*e)-o&3){case 0:n+=i;break;case 1:a+=t;break;case 2:n-=i;break;default:a-=t}return[n,a]}}function m(e){return"function"==typeof e?e:function(){return e}}var V=this.defaultOption;V.text=e.text?m(e.text):t,V.font=e.font?m(e.font):i,V.fontSize=e.fontSize?m(e.fontSize):a,V.fontStyle=e.fontStyle?m(e.fontStyle):n,V.fontWeight=e.fontWeight?m(e.fontWeight):n,V.rotate=e.rotate?r(e.rotate):o,V.padding=e.padding?m(e.padding):s,V.center=e.center,V.spiral=l,V.endcallback=function(){},V.rectangularSpiral=h,V.archimedeanSpiral=l},_initProperty:function(e){var t=this.defaultOption;t.size=e.size||[256,256],t.wordletype=e.wordletype,t.words=e.words||[],t.timeInterval=1/0,t.timer=null,t.spirals={archimedean:t.archimedeanSpiral,rectangular:t.rectangularSpiral},n.merge(t,{size:[256,256],wordletype:{type:"RECT",areaPresent:.058,autoSizeCal:{enable:!0,minSize:12}}})},_initCanvas:function(){var e,t=Math.PI/180,i=64,n=2048,a=1;"undefined"!=typeof document?(e=document.createElement("canvas"),e.width=1,e.height=1,a=Math.sqrt(e.getContext("2d").getImageData(0,0,1,1).data.length>>2),e.width=(i<<5)/a,e.height=n/a):e=new Canvas(i<<5,n);var o=e.getContext("2d");o.fillStyle=o.strokeStyle="red",o.textAlign="center",this.defaultOption.c=o,this.defaultOption.cw=i,this.defaultOption.ch=n,this.defaultOption.ratio=a,this.defaultOption.cloudRadians=t},_cloudSprite:function(e,t,i){if(!e.sprite){var n=this.defaultOption.cw,a=this.defaultOption.ch,o=this.defaultOption.c,r=this.defaultOption.ratio,s=this.defaultOption.cloudRadians;o.clearRect(0,0,(n<<5)/r,a/r);var l=0,h=0,m=0,V=t.length;for(--i;++i>5<<5,d=~~Math.max(Math.abs(y+g),Math.abs(y-g))}else U=U+31>>5<<5;if(d>m&&(m=d),l+U>=n<<5&&(l=0,h+=m,m=0),h+d>=a)break;o.translate((l+(U>>1))/r,(h+(d>>1))/r),e.rotate&&o.rotate(e.rotate*s),o.fillText(e.text,0,0),e.padding&&(o.lineWidth=2*e.padding,o.strokeText(e.text,0,0)),o.restore(),e.width=U,e.height=d,e.xoff=l,e.yoff=h,e.x1=U>>1,e.y1=d>>1,e.x0=-e.x1,e.y0=-e.y1,e.hasText=!0,l+=U}for(var f=o.getImageData(0,0,(n<<5)/r,a/r).data,k=[];--i>=0;)if(e=t[i],e.hasText){for(var U=e.width,x=U>>5,d=e.y1-e.y0,_=0;d*x>_;_++)k[_]=0;if(l=e.xoff,null==l)return;h=e.yoff;for(var L=0,W=-1,X=0;d>X;X++){for(var _=0;U>_;_++){var v=x*X+(_>>5),w=f[(h+X)*(n<<5)+(l+_)<<2]?1<<31-_%32:0;k[v]|=w,L|=w}L?W=X:(e.y0++,d--,X--,h++)}e.y1=e.y0+W,e.sprite=k.slice(0,(e.y1-e.y0)*x)}}},_place:function(e,t,i){function n(e,t,i){i>>=5;for(var n,a=e.sprite,o=e.width>>5,r=e.x-(o<<4),s=127&r,l=32-s,h=e.y1-e.y0,m=(e.y+e.y0)*i+(r>>5),V=0;h>V;V++){n=0;for(var U=0;o>=U;U++)if((n<U?(n=a[V*o+U])>>>s:0))&t[m+U])return!0;m+=i}return!1}function a(e,t){return t.row[e.y]&&t.cloumn[e.x]&&e.x>=t.row[e.y].start&&e.x<=t.row[e.y].end&&e.y>=t.cloumn[e.x].start&&e.y<=t.cloumn[e.x].end}for(var o,r,s,l=this.defaultOption.size,h=([{x:0,y:0},{x:l[0],y:l[1]}],t.x),m=t.y,V=Math.sqrt(l[0]*l[0]+l[1]*l[1]),U=this.defaultOption.spiral(l),d=Math.random()<.5?1:-1,p=-d;(o=U(p+=d))&&(r=~~o[0],s=~~o[1],!(Math.min(r,s)>V));)if(t.x=h+r,t.y=m+s,!(t.x+t.x0<0||t.y+t.y0<0||t.x+t.x1>l[0]||t.y+t.y1>l[1])&&!n(t,e,l[0])&&a(t,i)){for(var c,u=t.sprite,y=t.width>>5,g=l[0]>>5,b=t.x-(y<<4),f=127&b,k=32-f,x=t.y1-t.y0,_=(t.y+t.y0)*g+(b>>5),L=0;x>L;L++){c=0;for(var W=0;y>=W;W++)e[_+W]|=c<W?(c=u[L*y+W])>>>f:0);_+=g}return delete t.sprite,!0}return!1},_autoCalTextSize:function(e,t,i,n,a){function o(e){c.clearRect(0,0,(d<<5)/u,p/u),c.save(),c.font=e.style+" "+e.weight+" "+~~((e.size+1)/u)+"px "+e.font;var t=c.measureText(e.text+"m").width*u,r=e.size<<1;t=t+31>>5<<5,c.restore(),e.aw=t,e.ah=r;var s,l,h;if(e.rotate){var m=Math.sin(e.rotate*y),V=Math.cos(e.rotate*y),g=t*V,b=t*m,f=r*V,k=r*m;l=Math.max(Math.abs(g+k),Math.abs(g-k))+31>>5<<5,h=~~Math.max(Math.abs(b+f),Math.abs(b-f))}return e.size<=U||e.rotate&&t*r<=e.area&&i>=l&&n>=h||t*r<=e.area&&i>=t&&n>=r?void(e.area=t*r):(s=e.rotate&&l>i&&h>n?Math.min(i/l,n/h):t>i||r>n?Math.min(i/t,n/r):Math.sqrt(e.area/(e.aw*e.ah)),e.size=~~(s*e.size),e.sizel?l:V:l,s.area=t*s.areapre,s.totalarea=t,o(s)}},t}),i("echarts/layout/WordCloudRectZero",["require"],function(){function e(e){this.defaultOption={type:"RECT"},this._init(e)}return e.prototype={RECT:"_calculateRect",_init:function(e){this._initOption(e),this._initCanvas()},_initOption:function(e){for(k in e)this.defaultOption[k]=e[k]},_initCanvas:function(){var e=document.createElement("canvas");e.width=1,e.height=1;var t=Math.sqrt(e.getContext("2d").getImageData(0,0,1,1).data.length>>2);if(e.width=this.defaultOption.width,e.height=this.defaultOption.height,e.getContext)var i=e.getContext("2d");this.canvas=e,this.ctx=i,this.ratio=t},calculate:function(e,t){var i=this.defaultOption.type,n=this[i];this[n].call(this,e,t)},_calculateReturn:function(e,t,i){t.call(i,e)},_calculateRect:function(e,t){var i={},n=this.defaultOption.width>>5<<5,a=this.defaultOption.height;i.initarr=this._rectZeroArray(n*a),i.area=n*a,i.maxHit=a,i.maxWit=n,i.imgboard=this._rectBoard(n,a),this._calculateReturn(i,e,t)},_rectBoard:function(e,t){for(var i=[],n=0;t>n;n++)i.push({y:n,start:0,end:e});for(var a=[],n=0;e>n;n++)a.push({x:n,start:0,end:t});return{row:i,cloumn:a}},_rectZeroArray:function(e){for(var t=[],i=e,n=-1;++ni;++i)if(e[i].type===a.CHART_TYPE_HEATMAP){e[i]=this.reformOption(e[i]);var o=new n(e[i]),s=o.getCanvas(e[i].data,this.zr.getWidth(),this.zr.getHeight()),l=new r({position:[0,0],scale:[1,1],hoverable:this.option.hoverable,style:{x:0,y:0,image:s,width:s.width,height:s.height}});this.shapeList.push(l)}this.addShapeList()}},o.inherits(t,i),e("../chart").define("heatmap",t),t});var n=t("zrender");n.tool={color:t("zrender/tool/color"),math:t("zrender/tool/math"),util:t("zrender/tool/util"),vector:t("zrender/tool/vector"),area:t("zrender/tool/area"),event:t("zrender/tool/event")},n.animation={Animation:t("zrender/animation/Animation"),Cip:t("zrender/animation/Clip"),easing:t("zrender/animation/easing")};var a=t("echarts");a.config=t("echarts/config"),a.util={mapData:{params:t("echarts/util/mapData/params")}},t("echarts/chart/line"),t("echarts/chart/bar"),t("echarts/chart/scatter"),t("echarts/chart/k"),t("echarts/chart/pie"),t("echarts/chart/radar"),t("echarts/chart/chord"),t("echarts/chart/force"),t("echarts/chart/map"),t("echarts/chart/gauge"),t("echarts/chart/funnel"),t("echarts/chart/eventRiver"),t("echarts/chart/venn"),t("echarts/chart/treemap"),t("echarts/chart/tree"),t("echarts/chart/wordCloud"),t("echarts/chart/heatmap"),e.echarts=a,e.zrender=n}(window); + +layui.define('echartsTheme', function(exports){ + exports('echarts', echarts); +}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/echartsTheme.js b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/echartsTheme.js new file mode 100644 index 00000000..ef8a2eda --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/echartsTheme.js @@ -0,0 +1,267 @@ +/** + + @Name:echarts 主题 + + + @License:GPL-2 + + */ + + +layui.define(function(exports) { + exports('echartsTheme', { + // 默认色板 + color: [ + '#009688','#1E9FFF','#5FB878','#FFB980','#D87A80', + '#8d98b3','#e5cf0d','#97b552','#95706d','#dc69aa', + '#07a2a4','#9a7fd1','#588dd5','#f5994e','#c05050', + '#59678c','#c9ab00','#7eb00a','#6f5553','#c14089' + ], + + // 图表标题 + title: { + textStyle: { + fontWeight: 'normal', + color: '#666' // 主标题文字颜色 + } + }, + + // 值域 + dataRange: { + itemWidth: 15, + color: ['#009688','#e0ffff'] + }, + + // 工具箱 + toolbox: { + color : ['#1e90ff', '#1e90ff', '#1e90ff', '#1e90ff'], + effectiveColor : '#ff4500' + }, + + // 提示框 + tooltip: { + backgroundColor: 'rgba(50,50,50,0.5)', // 提示背景颜色,默认为透明度为0.7的黑色 + axisPointer : { // 坐标轴指示器,坐标轴触发有效 + type : 'line', // 默认为直线,可选为:'line' | 'shadow' + lineStyle : { // 直线指示器样式设置 + color: '#009688' + }, + crossStyle: { + color: '#008acd' + }, + shadowStyle : { // 阴影指示器样式设置 + color: 'rgba(200,200,200,0.2)' + } + } + }, + + // 区域缩放控制器 + dataZoom: { + dataBackgroundColor: '#efefff', // 数据背景颜色 + fillerColor: 'rgba(182,162,222,0.2)', // 填充颜色 + handleColor: '#008acd' // 手柄颜色 + }, + + // 网格 + grid: { + borderColor: '#eee' + }, + + // 类目轴 - X轴 + categoryAxis: { + axisLine: { // 坐标轴线 + lineStyle: { // 属性lineStyle控制线条样式 + color: '#009688' + } + }, + axisTick: { //小标记 + show: false + }, + splitLine: { // 分隔线 + lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式 + color: ['#eee'] + } + } + }, + + // 数值型坐标轴默认参数 - Y轴 + valueAxis: { + axisLine: { // 坐标轴线 + lineStyle: { // 属性lineStyle控制线条样式 + color: '#009688' + } + }, + splitArea : { + show : true, + areaStyle : { + color: ['rgba(250,250,250,0.1)','rgba(200,200,200,0.1)'] + } + }, + splitLine: { // 分隔线 + lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式 + color: ['#eee'] + } + } + }, + + polar : { + axisLine: { // 坐标轴线 + lineStyle: { // 属性lineStyle控制线条样式 + color: '#ddd' + } + }, + splitArea : { + show : true, + areaStyle : { + color: ['rgba(250,250,250,0.2)','rgba(200,200,200,0.2)'] + } + }, + splitLine : { + lineStyle : { + color : '#ddd' + } + } + }, + + timeline : { + lineStyle : { + color : '#009688' + }, + controlStyle : { + normal : { color : '#009688'}, + emphasis : { color : '#009688'} + }, + symbol : 'emptyCircle', + symbolSize : 3 + }, + + // 柱形图默认参数 + bar: { + itemStyle: { + normal: { + barBorderRadius: 2 + }, + emphasis: { + barBorderRadius: 2 + } + } + }, + + // 折线图默认参数 + line: { + smooth : true, + symbol: 'emptyCircle', // 拐点图形类型 + symbolSize: 3 // 拐点图形大小 + }, + + // K线图默认参数 + k: { + itemStyle: { + normal: { + color: '#d87a80', // 阳线填充颜色 + color0: '#2ec7c9', // 阴线填充颜色 + lineStyle: { + color: '#d87a80', // 阳线边框颜色 + color0: '#2ec7c9' // 阴线边框颜色 + } + } + } + }, + + // 散点图默认参数 + scatter: { + symbol: 'circle', // 图形类型 + symbolSize: 4 // 图形大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2 + }, + + // 雷达图默认参数 + radar : { + symbol: 'emptyCircle', // 图形类型 + symbolSize:3 + //symbol: null, // 拐点图形类型 + //symbolRotate : null, // 图形旋转控制 + }, + + map: { + itemStyle: { + normal: { + areaStyle: { + color: '#ddd' + }, + label: { + textStyle: { + color: '#d87a80' + } + } + }, + emphasis: { // 也是选中样式 + areaStyle: { + color: '#fe994e' + } + } + } + }, + + force : { + itemStyle: { + normal: { + linkStyle : { + color : '#1e90ff' + } + } + } + }, + + chord : { + itemStyle : { + normal : { + borderWidth: 1, + borderColor: 'rgba(128, 128, 128, 0.5)', + chordStyle : { + lineStyle : { + color : 'rgba(128, 128, 128, 0.5)' + } + } + }, + emphasis : { + borderWidth: 1, + borderColor: 'rgba(128, 128, 128, 0.5)', + chordStyle : { + lineStyle : { + color : 'rgba(128, 128, 128, 0.5)' + } + } + } + } + }, + + gauge : { + axisLine: { // 坐标轴线 + lineStyle: { // 属性lineStyle控制线条样式 + color: [[0.2, '#2ec7c9'],[0.8, '#5ab1ef'],[1, '#d87a80']], + width: 10 + } + }, + axisTick: { // 坐标轴小标记 + splitNumber: 10, // 每份split细分多少段 + length :15, // 属性length控制线长 + lineStyle: { // 属性lineStyle控制线条样式 + color: 'auto' + } + }, + splitLine: { // 分隔线 + length :22, // 属性length控制线长 + lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式 + color: 'auto' + } + }, + pointer : { + width : 5 + } + }, + + textStyle: { + fontFamily: '微软雅黑, Arial, Verdana, sans-serif' + } + }); +}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/chatlog.html b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/chatlog.html new file mode 100644 index 00000000..04d17f18 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/chatlog.html @@ -0,0 +1,98 @@ + + + + + + + +聊天记录 + + + + + + +
+
    +
    + +
    + + + + + + + + + + + diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/find.html b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/find.html new file mode 100644 index 00000000..5a66d6e0 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/find.html @@ -0,0 +1,43 @@ + + + + + + + +发现 + + + + + + +
    +
    此为自定义的【查找】页面,因需求不一,所以官方暂不提供该模版结构与样式,实际使用时,可移至该文件到你的项目中,对页面自行把控。 +
    文件所在目录(相对于layui.js):/layim-assets/html/find.html
    +
    + + + + + + + diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/getmsg.json b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/getmsg.json new file mode 100644 index 00000000..c4ef35fa --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/getmsg.json @@ -0,0 +1,72 @@ +{ + "code": 0, + "pages": 1, + "data": [ + { + "id": 76, + "content": "申请添加你为好友", + "uid": 168, + "from": 166488, + "from_group": 0, + "type": 1, + "remark": "test1", + "href": null, + "read": 1, + "time": "刚刚", + "user": { + "id": 166488, + "avatar": "http://q.qlogo.cn/qqapp/101235792/B704597964F9BD0DB648292D1B09F7E8/100", + "username": "测试111", + "sign": null + } + }, + { + "id": 75, + "content": "申请添加你为好友", + "uid": 168, + "from": 347592, + "from_group": 0, + "type": 1, + "remark": "test2", + "href": null, + "read": 1, + "time": "刚刚", + "user": { + "id": 347592, + "avatar": "http://q.qlogo.cn/qqapp/101235792/B78751375E0531675B1272AD994BA875/100", + "username": "测试222", + "sign": null + } + }, + { + "id": 62, + "content": "测试333 拒绝了你的好友申请", + "uid": 168, + "from": null, + "from_group": null, + "type": 1, + "remark": null, + "href": null, + "read": 1, + "time": "10天前", + "user": { + "id": null + } + }, + { + "id": 60, + "content": "测试666 已经同意你的好友申请", + "uid": 168, + "from": null, + "from_group": null, + "type": 1, + "remark": null, + "href": null, + "read": 1, + "time": "10天前", + "user": { + "id": null + } + } + ] +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/msgbox.html b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/msgbox.html new file mode 100644 index 00000000..f56d0f74 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/msgbox.html @@ -0,0 +1,218 @@ + + + + + + + +消息盒子 + + + + + + +
      + +
      +
      注意:这些都是模拟数据,实际使用时,需将其中的模拟接口改为你的项目真实接口。 +
      该模版文件所在目录(相对于 layim.js):/html/msgbox.html
      +
      + + + + + + + + + + diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/default.png b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/default.png new file mode 100644 index 0000000000000000000000000000000000000000..33c7691aa62991324afeed6acfd220e0b3ae4e85 GIT binary patch literal 6727 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 CBC!|% literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/1.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/1.gif new file mode 100644 index 0000000000000000000000000000000000000000..b2b78b218996f70773540d0d3a8649d3c2d199a2 GIT binary patch literal 5514 zcmeI0X;f2Z8pm%|0tv}wF|q`>VUY-kh?astAQA;dB?6_fabYVUO9#+)7)Q(s2}KDA zighC_TBPE*AR-hSAO%6du#{TxXn-QNiVcVgN|Fij%v8I5oO9-!+)ww*d!7%!|9hVI z{|nx@!P_T>2oQmXY@j$fRCS-Fst#8Fl-Ji<_wt8B#oMn7hHBnZ4SIK-bRDmyJo~XxHIe<@S;}yGsph#%R&3pM=?m3xsA@drb+`R>L5S-6 zz>yk^YAiuB+oYNAZ_LF?#Sxmh?wKCnks9lU+z5q2ar+DGPfeziHw@J?S6jsf&!0cP zdJv^~b+7qw%%v2U$@--gvCCCsdk<_PHte%$Jmk_-lRDCrG;npxi~bPRgV?D7zN#&_ zCe2g*w7m0(@9fi`>xz@w^U1XtK2y!sP1)pEFP~|YwX*|ZH)_kL?|yde{AtyLq;?6r zrS5!RPuG*%o2S}r6<3x__s6NL<5VMzZyPSC`gf@xv3stwub#tO^-JmF&hTmZ_Q|h(Unn2|LQqcJljcz`CqNT-d#=P4TsI+`$f9Ch+HH6_=gXNx+LO~J;=#8M2bsj0pAsmE~jpC z+e9r#gRZAtL!FaYC?7{MaSw`>N^<&&ALWFFS+Qsk`6z^CS-}uaQG8o7OPH^h*N!^J zB?bn*FiR_2UPN3N6Xq3j4@!m%=yWd_((FOaO!^t=l&v`jJMzn0XXJy!`5gR078K1v9z+wE}3v}$MR=6 zIFTWuo=H)j?LKN}v%e&C+c=j~Y*=?dE}h{YLpr1Us*A?L@@)yGj!AMTkYgK|JtLTp zUWYwtNqJJ#_vQJ4FS9uod6LmbIk@-lL+QNel<(bl-msVKb!gj$+4V_uU<(q(x}GL@ zP{By=zzPD^M&24#*nggXldXc+BNE$8YZmMYeZm}wO7Pr>N#jQ-B(?~MM===Y3%&*=Az{%xjzo9W+X z`aYxYGyeyD21WR52Y^Qx#cLG+wFnJr4M0ddVvCPf0r+fTZ3%Hb=^BdjXJOs64!{j- z=8t&W0hH)!X479OfRW#}%z;G(K(o*q2{@ATH=C@;d9$e&vFpb-3t_8bq(m%AT5@Bi zGKi3|JlPKn^yD5RScM;yAK_GS4BiW0*wZ&o;~|Z$kQjO8WbdgJcAJw{tw!Ydd%mLV z?5ZPx4kl~B=EBi-Yvfii`n%!vDN)FMpTt8(Ew_zvl;e_+rl=Jxb0hxKtiGzC91`BW zqTyE4hbwpcrhAe4$e0eaKLebbF8(+pE&#b81IH#>A%oS!(rt_mamlx3=#H zfJ`;IZGvzuAmC!j{5rHu0AsnC&xJqi665{5&Q?zcb2^b9QInYSv`~04FS!aFd?!vT z?KXphV}y6&glQ}sz4LCID8Gpl_h}Ya87wsNA?=`Nl$ZW;|K?|kRPTx)u)uh~1X4b8 z&WAd9zsAXep^cMydzlIptr}~=83}fgrZaeGbNI#uc}5V>o9Fz&=fwToM4rGRP+`G| nqjLpT%jon>&iI|hI5DGFNqSH|Meaf1bVU=!q}mt-2YmkxGX3TC literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/10.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/10.gif new file mode 100644 index 0000000000000000000000000000000000000000..556c7e326801a0ea090bd693ca43807925d3cbc2 GIT binary patch literal 2797 zcmd^A`#)6c8Xsolx+O`H%Q93$nTyL{n9MM)A-684%gM}GWn?bROqpmGJGZ^Fi(PxC zQc0BVBpao@iAv-WQX~e2E`%;_^UgXmoi68xeb(o*-uGGG@ArA0^?g3?^6~R_ zc3~Q#3{evksAPYm+ldxe`B>25hYY5H$5ilyap#a4=-C9i!a--i^?{+Kq>xB__^Jl4Vn&qDieZbVwCxhx2@ zILKOvg+lCu6V~AQ`is#P@}Y#M=jR}wYR+vn|5TiK@RaXU!OgY6vPDVqMt==D71BV~Djr?Wup*KT5)s0Nt z1Ea;`y*Z$Vg^U%+NAu)^dy4m>3*sq2x(&3`O809f`!AG_6@bUi^1&ZV_v?Zdd(dFk zaB1^UmD5ngJo#|eL{F^zWjuI$5Ol4%mt`$$vYF`IF#R$WJTyT@^O32h{2hyB4HojL z=IPO!U?>rcovq1KN5(EAA1kK%5`D7*2eJ&VEMP|C>Q*F(8D`a)X#VL03k>m1L zNkAHLnrro;Eo8bcxh+q#qdYo0+G?;|YpN42;h4%E5#%GMLHA}^^K#ikNY-R6d*oOs zTKf3>vYC2QS))~Z!7^DZ^;7j+S>2+dJsMN@jAc!@>Domz^^oi_W2V7c*5V2pOc4Y@ z&2m{F+Cg67VV?A0FFQODt)hS_LhA#AAqG>-R6O0>B?2aUJ1mA+@HP&QihXzMZ!E-# zq+-`O1`-1Wo^TY$H%P1BC+l(AvXy{!WD2~F%yz-V|XHpgowuN zu~vo&Sm-lEyq$`rD_=m$oSu9k3_0TMZP`Q;2_lp6BnL+_nY043Ba-Y0M8!?EB{@(W z$rL*$=*xvwWD`birGzrPzvNQvsMsj6SU@2VVq;_RvG#bra2tW-;^Lyzu(PvOAZ$gu zd19u-mM60Os=$CnY#~P==J0utQjy8x?-Wz9ic0_80$1=&mM6l0ZU@iia|sfrfIz|% zl`VY*1_u6bD3|*UEfR;q-|PLa!lLlq0+> z3;A5=bJG;g?6o+|s`rH(IeRURvvLWFVhBoW|HJC9A;tVCm){0gvH3RoFi$b>Ld9UK zAaWp^nVy=Q`1J9^`|+{ScO%1Z-@JY`G&u0`MSowfw5R)d*R#%!r%&1+x3#uBYHn(5 zcvxTep!WW~yEWB!sw)5f>vqMho8@Jtf0o=RzFt&#?dp}wmo8o?IDalb?`-awoYSXH zW}i5IEbHhWzaKgLTV}?ggTJO9_~qxc)Rg3;{XZop?A!a}p7^-klGt54#UkMj0iVZ> z*&fY_+O`#rWV4tNTmHFu)5Z<|Sif%Vn((mDkl@upfdQ-h{d|4Ay%?Szbej80s+%jt z#o3AM=wNS0A`&{X=-C5hG6x_Mhp(KcU9@@YgLMeldR?axtN zwEd5V&Z~-T*Iv@rI8N2DD@?W3Rvb>{t;?G1!&v7sZ$i}`xn`>FQLpFZa5oZbQ!WU# z6N0id*ekoxJ8V?Re!96gG%&ojbC{6bC=zRL(qC9 z9AVRaGo3jGR+2<4BiUquM~)5rObdsjH=o&{j`7Fgq#-%QIg)q|V7l8WN}3~Mr^HPsnv zYBVTkuWYI`!P&3tY=gmCJ!#Glz7;G6+M758sp#>>(`c$v8b;e4Wr3n58|AJ_HBZ4M zKkT%FdUFzk{<}(CnOdM}KuhNHXeOR1V!?SZ4Gh!>qiTZn!)^dLP>z z5V6E{^;KymZ80qbv*Od_xEFz6_>=chubAD346L#aA6UNh2+PBUmt8$z7(H-o8%=4b z+W)tqA(h_^MWGdj)+!Cv!1vT~=&*>=JeMuyj@YH oWz4#Y8lWniX5g=81^=RXq3ldhwpWFqvq6_o40028>wtN;K2 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/11.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/11.gif new file mode 100644 index 0000000000000000000000000000000000000000..2bfc58be8c70d512f4371b50b2b98c7b8adbe719 GIT binary patch literal 4121 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 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/15.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/15.gif new file mode 100644 index 0000000000000000000000000000000000000000..c9f25fa1d25412e2e929347c0db0878b0b641d58 GIT binary patch literal 1793 zcmZ?wbhEHb6k`x$cvjC)UFLjcxo+2{sU44AEqro)?t{~@-b%N3XFR-Hwxr+ulK%oH+No|8@joUb;8o>khO;% z-pt54c=5$f_l$zz1xIF9ZC!k8rPSX?m75>!3YoF0@6_@yw?fNicKtc8QFZZ3q7CQQ zJ28K6dKNF8dwdf2>Dz5FoA&JK_I!S*#c%QM(+{R^st_tYd#Py0=A#ot|K1Au_q1vD z6!%ScSEOWk{yZ-7e1G7dQxZR(%&R%HD{|8GPuFK(p3ArTeE-+$eg#|BB~~S$dA0ra zCi@?c7ri|%pb4sD-Qd^>BZ@TkN^$;DL)19`Dfod@V3w#!8pDhc-E$->ITP|u(PWCJ5fjDdmu ze?xs!vs8YWOpZ)hzDjdnpQuc^mXOXgX{{oe-u@~|ZFy%{R@dafm z@IQa9kQKz2C85GpugPS}VD;TfljXPO4=V=Kgd@?P4xMV}iXHU$+K4vH=vCN_(f6?!dfWS6n2`SY^jFjF5#yp%}dht@+k^lQ5mUcOp* zcs?^%!Geg4gAHe92$#NpR-1INsfoGiRz$%hw=FUkg|bMf)@r}A%N=>H&t=-OGD)%dJ&%aS1;>?S28-4y56)#MguSwF{Wn{Bi0wrzT;!uy3&oA(_^ zP4_wBW87?f(kHzUYzsfa7D1pbvq83K2{lV=HFwoZ*)}QIN_Dj=yXlz=G?~}CDNBnw z0PXZuXlB-166sJM;cnU891&3uiN0ojaP%=)9kJ4E);wy(ATN9lXld$sVfl^MZ`{0f z`<5JUy@-h7JMl*sta~4a6oo18!%LOf$q&}sITYaYiet1X;M?G&Sqt4V`0s%?q;x>VWruo zITPfDMZ!^SQHzD;+gGnyyKeo4jrC#{^>Vzt^*iM1EyS8U1jSr=;w_HEA1-Lp7hf0JU8dSF%T&D%E<+7ylUKYC)M*n|{ZEMUu7fY$3aNE)ViSQzrOwtGm1);sbf z_Dz^%r|aYuqCS15lTnC&w5K1hmuJ8d&l*pEtR`qRKwZ!p-%_Ak4|D*~1b>MAGiJ?5 Y2vsx^3s|^#p`syH?V}DDY9U|^06Jl%MgRZ+ literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/16.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/16.gif new file mode 100644 index 0000000000000000000000000000000000000000..34f28e4cde0cd13acdbbd7482282eb306f5b21e5 GIT binary patch literal 6721 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 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/17.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/17.gif new file mode 100644 index 0000000000000000000000000000000000000000..39cd03538a5bc595fbc46c97cf2b06c8bd8dadd1 GIT binary patch literal 4439 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 IdD(dV7kW}yvj6}9 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/18.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/18.gif new file mode 100644 index 0000000000000000000000000000000000000000..7bce2997f86e477a6008fb1cae8dd03cda10abf6 GIT binary patch literal 3017 zcmeH}`&W`_9>8Dl1yK_aL;=Ob3nGb&N=AwoykI7&SsFG?;bls#Q?`m}L+3&8mQre& zIhILwGPi9z*=?-c$}De97tM;9W?i*RZLH05$~M7$)uy&if585*zr8;^=RME!`JU(V zdBVcQg2f3|kQMY4K>D$L6S^e*VCwsu-ujWeGlg;bq3@?|+D^5LdymJCUa~Y8^!gsY z{z2f>E#`2~Uw$8|*Z2Aw-rjh4oPRNYo?+rb`(D}^h4Ei=yw2tG^*=}Kj3iFKyRZM} zw>>}ZHeB#+uVQcHV~3jDI;&&G?pO8JbDnoe441zu5^60UJokvzr zv@PhaVNYFm*7q#wK9SmdwCvfV*1neFSKZ$}>n?nC)p6=?;rbSj_t$KHAL}3PEa<7l z>mRPT*&x4NGr#As@2yM6pSLjn(Y*dj>7NEpTfVv_{OyY4+Zz^dS_zZCtkypa)!&IX zoLZ*8lhA*0#ic^$@t)+qlbrW=g8yD6d*A8Wcf0xDy12e8^3j1`$4=T$Pfs(a%_2ir zt_T)IhkCm6j8G5+G2g)$PY6J6$Tu=1D+n^4RsxkeFTbELWWAf4sj1ugkixtW)6Ecv zWNS;}U`@q)+|pne3uOy!gtTyu*sY)rX4J3DCQt+`soayN)bb+?bUm^900+)sKxuL{ z8%=Mmr~F_`>6A0*Shk9_(VXAA|H04URGZCwbQ%k!hM3(&Bw}bBN2+@$iK77J6p;J1m6pocLCoTxg|5!y ze0Aaf=r6G|2gf1@CqP8x;N4093&QL$)a(tQM5EzQI10xor(GH%kwT&%jUNV^Cc!$Qr>))HJJ+FdjJP<~NCyx1LPaqE_63aOSL zgJ#3zZC@Ma=aC`_vIgR0DmB(FDmg1eWaa-$x(nHA>C)vM+xn(*6BFAkVVCoQt)yUc zi`;qCl*tU^fl7hP3x0~0)j?;Ir{@K}9Dr56MqFM(BC4y7VU+0E<@FR@0E;H2X%)v} z@f=?+L)W;zvo>&cXtSq;Arxc*kv?21kSdccVylbQVo%pZV7DqhphS%gSiH`C74Qou zvSgKjLh&Xz#rpvTd8hh^c&7$$;F+OHld7a#6W1_8So~tSn(GC`T+gsL@33|2Jmpdm zS>YrI@jDy0{X2rUlOH+5eK0+6lrp`Ee8TDsDT5j z{-{H!`6`2m$W+<;CXJK>VGkKG6H^utqr~ZXveDXw4q44brq@gD?PV95b>qfeAzVB@vs@)69ynJ_({9pf zhXVH+nX;txC(7&P0o&fLE>_-)ne&9@%ylt>um~*^gjS9cFwg+8GeA@d_$)LQ;uHZi zgD)qu=rnE_w5OnwK~M8frDxL6Wr(NuN%zy8qu5)>%nUU;MT(Z%M9@8KPp(5}(^nwq}4<2ejm;;1)1H#-RipPvSpCYvuGQVrc%(rF&-pS>snM~eV|J%Sv zVq-^GX)VgPl2}_>75Xf-Tx#V}ke21+QxWOo&{t9T)y@1L%_lUNxjB7y$3Ez%ct$^V zbNYej{G*ulPYDA+6bhIzPzGY4;_7%OZ-TeLGlR7lNL7qa5<4|1H190@IRAMg5(j8}L?(phY-y`50aH_-& z8U{DVAdq$){Y{AivqB20s8-wpxRcT?Z`FaicaB1cs)H@ zqu@!rE~yt8sHR{M}v6=UaO z1;V8&kz9rTSSvM(4H%a_|H#z?Bv%Z^7s2BH^hL48W|DP0J3FWiUv6)uh@L!>i#eM%g!m2b=EomsZoMrFNGwm%(_p IDGd4k2Wv_t&Hw-a literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/19.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/19.gif new file mode 100644 index 0000000000000000000000000000000000000000..adac542fd33e152fc08baf165d1c5a467f0c2747 GIT binary patch literal 3040 zcmeH}`&Uxg9>5Q86bs~`fKmvGN=OJ=XsCdSFDfllZ)I9iBDJa+pA|D35dp&{&8Do( zY;4M!>h`{Mb4u-@Ju!RP^cd|iS-0+W(rKJY^ny7y&FUYxYu(?@4||=p&*yvg=d)wt z6ylJDZjc-F6M$^5zP`10c7JD6)#SchlXsnjv(6| z>EJc5=N)_dp6s#Rns#?z&_7FEhJL*;)OV`2igr|s`EHfycxjOBUP9S){P1tLZ9k?D zotoBK?YlGx{p=*K^F;QQZAq_hZ@zN8_Vs1ut=;}ZXX5Vf!w&stkF7!6_vF~~Q_e42 zQwFd5Z7rPp{N$7umsj06{^iwb7u)?=E$cCNcT@WxZGL;VwCh{n!S+dC&tvtpE@`a} z>AzoKJ09@5IkaXOckr_N+m5)tp0@s5Nzbou89I^r`sNqsEVLj0A>Wii8n{S$u_w6y z;-m-7>#a51!Sg=0j@TRfa~i*`czOR^-;MN_H%xDu*n0ImrrWFwyHC$LZSv{uP`$H8K03&4+LrO|lK-RYjlXxMJUUzOqWi(CgUsRKVXtA_ zjOgUqk+Q^SAzy%iK@jBi8xkdi0K~ID+lS-^L6~73(3coWjV2JaB*57@AYe(9xkTZN z;gUT)$y{i;^9ECZf)YoQcu0yM3<{+QFxGSV)MPOQUzEI`@%O_e`5K6ki{etYdJ-TM z;*2K0#2-UvmP|bqDW)S>ja&4r@f$q3$u32Ab{dUSUB|Z%WYr@|umzzS z8QeEhTIEOcJk%^~L;JWA>!g)T<+^(M3`J&BCNvYLYXAONR(5JEH6pX5PP3yhWsM7pwJ6#Sc%<&*+cVb)n|V zh-4;ne&?aZnDT9c#FhGX)TQZ0^OACDKVgbXM=viAc2#xr(0#$lKv*R*bgH0gibqRJ zbzDV+@}yMTVz^!khmDZOJIG@pIE00ecJg$cSRz3KBcQUm)Ka6COO6(qHUb{N6n|&g#oQ7BP0T2A!<>-(?d%YZ0Y)3g*%^dbs`F=VP_01?5WkkRBu3`YSH!tr@T1}2Wn1C6=y;p(WM zWE@W9o>0S$Q{{;k;1YeipWs%ri5L|d|K#7jL8K?~x~|Wy-Mz)(-0;z7` zrq|^&C|BA1fvl{xrB3eEY3+&ZHWU{hzbx~cNWxl5Xx@XQzMs|^32qyeiQk+<6h}x? z_II}EitEth^oI8CsGdy`U+SRBH;ZD-!C)=1mzno+V$iIU%#{_E@PxslwJZbq4VGTz5S8EOsyqc)urqel zLWyG*BFPf<0W+yl>L!t_yn1dTA@k6anYFyaiw{<@{N!+aVi=*V?=k+epF6+(RAd(( z2A|h5E5En3wRQqb>vyVhPme{ilEq*Wj(NvoV4v$%pGgY{aO8Bi*F9@9+vY3G!!EQ9 z12dT;M{Nw-pPfBwCg2DZum@_nB|u?M6tE}Cemk;o2C_C$fvM3wl%!KSf9 zA%G)N){#hEY(p^qk|_q`<4|=5kCv+8YJ(nzps^Vmtng>=7LRFx7yXhJHOCRe!9jzE zcNW7Crh=jKD<4PUHXvs|!gh=#OaH3QTz?@FKFxJVTePUyiG&MusvD@%=~@}t`h^1` x&iYmvvfx#bmpT3`PtF^0k?a@iE%))*1NVySmZizF-M!R86}DbhY`;HF`!D7eFhu|W literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/2.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/2.gif new file mode 100644 index 0000000000000000000000000000000000000000..7edbb58a843cec27a1641a5c9b6d30b8fc1f8c26 GIT binary patch literal 3222 zcmeH}Sx{4F97iv?30p`p30s7afI%Y0usQ~*kRTvo39F(M9fDyo)qyIGxZdPOAXfuw zMXOZ@MT%f;N3m|GEf6fID6)v4qTr4|g<*?Gl4b#gPG5ZI?R!4|GvE0w;|8(3`Bs1x z@CE`_yJD2}b|0SX8E<8)R4Qff@v))So3@t97s9rhpC4WH_pkwL!xySPHq{)oZ7p>h zzvrkPIQOBeShx`LV*^5%D6C%`ebEiEl~ zk7CE4B~|Y;QY-4zgO`-;+$Y!56kQ@|0&T3P_~I^%dg!{c*>mvT;;r*BVqy5BGo%N1 z>y$4yj<eSIAsOnz$S)c;g7`UNK{5a%gXzk9w@* zb+!N1Z*Z#q(|tE>A72qE-$~S?mF?$QKjr5tH)lqBI}f!)-Psh@T^p)=9MN)#S6{a5 z)5GBNdp(u?=bL}eIw4v-(&%^nXp+1*wON*U)QfoKAiI@LkEEj?KB(WsGWwPb_Q~x# z%Pj_))}E%~{$aCw?}kb3!SMzc<>;fP!fzD)jmqa~!+lLXRgS8nQwfW3qmScXUR|)( z58qz3wdeK<)!QANf2Y5%2`s^ZidsvxTJ505@&aRHmU1EkJ(zBw0RR9FAJG_700J1A zx8_Jz0AQpRL9k>=GRa;_N?sz#%Zsq5<3pC>LV|oY+spD{Qbe2&7lU`gW43MM#*2ar*Rwx+$e-nGQen7iJ*HH&6s0DE)T16NM@URLM4sVjkz-7 zEVM@ox@)%#;|K;6VBO^yGDT45hL=an%;wJ9`Sg_goSH(sqv#czn<8!~#3sD~%K0_n zM8E1+ZQZBKnoC0ED>;cRViOmBxv=BT@LrSCmTmn8?91ocFUGXRDmGPv$5s+|%)PO4 zu!z}lmB=t-ZS|%1LinMQX;MOwcmS^G?9*u1hBP-+<}$vIIbo+9TL7Q-4AIssuw z=N}TG(+?p~3br$0y?OA2c(7hNM6a9{%@o_D&;*eH}6v}Ak*0_@l)tisouy=(k7zah6uVrZhe;O``p=gyk5s|!3?bZf88ne*I%R2?0u zS@(sfB0s%2$%Th?;siz>TCk?_9ePuuvyJQQP8vMj7X;0X5*K4F3?nP3QSNhuu{urs z84)e)87pS2n6YB!ulU@SnZM$z3t}))Q*A*^DVoWmscAMP6tU3N6pmY^9V;nttf6+O z=$l~2j(DK-Bo4lc`8k zQg{>bzl{g&%nN?YhqNV#O ztd%y!jg0~xk-W}^+K#6lpv-gGpDC^eLab>noeHkN6PT!JRZZ+!1SKWgcK&*DT0tgB zXm^Ef+`*7`+buyz`jvr4Q3^sy@c+#WJ(tOup_y~jhsI<}!D%hkERC;dDT30s^pD^v pEloJ|-EsmUGDRV$ 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 TKb&t*bx4GV=Q(`>7FhdV^sO<; literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/21.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/21.gif new file mode 100644 index 0000000000000000000000000000000000000000..b98421282467fb377dced2eabd72bcc5525f3e8e GIT binary patch literal 5191 zcmeHJXIN9|w%#EDLMRCx5oHq)5g~;dB9Mdx2uKqUK~NJ&fFL1(1O*ETN)=1&;5bqh zMjZheJy=FUQGrpZ_5uo{aK-|HBPxco1LNqq&-Fg{-~DmVPM&A){q1k9^{#KdtN8l) zklfftfD!P12C%cU!{Kno#>RL&-ptI5OeR}eS`r8ZQ&ZEWOP89Pn_F93TUl8xT)2=% zqfsc7&!0b|(dfmC7u(v}IypIEFc<>^16Nm9ZEbBLk?7#y;OOY+=H_N&V?!d5bai#- z&!4|!$r5L0=Xvwyd3bnOSXe|vL?{#r6B82#gYog>#}6MqczSv!CnwYC^kvJI85$b; z`uavjMsnifHm0Y0dwZ{ni16|8ad&su)6=V{sK8>e@87>)yLN3yM@L^@-_+DpcX#)V z8#kh(qj`ymK|w*Gp`mecahozTy}Z1lA|n?pSm5vP&-C?8OiYaDax*q;c=6%|o5k|= z@u{w^j*E?TadDAmWu*!P{(gSpVPOgJ@uJjJu}Jjk)2E)Ep5&yY)lpF_7R!&xR@ z-@bjzrcHUdxoK%>H*enDyLWFuKmdosS+iyho6Vk{p6>7OU%q^KQBl#YTenuMSW#0` zBb7*EqN5)^eE9hB<0ns^tX{qP-o1OdIXRh`nJZVW?Ck8kdiCnNckdoOdbFdku&k_X zWMt&|^XKQ!pTB+kc5rZTY;5eEJ9n;KyS91r=2fd!J$UdSGb3Z)zJ2@m?@vlf+O=!f z!Gj0e+S()%iAW?03=9+sg?v80tE;Q9uuxrH{q*V6$BrEv9v)6lPahZNfCMqi{8yXt!-@nh}@d^qGdV71fZrwUQK3-K-HSpxgxpU`Ig~GA1vE1C;vuDrN z)z!Uv^(rwT;lhOrO-)TvQBjkVlc}kx8X6k<`ubEVb#!#}?%lgOIy#*l9j&dcfBf-B zd3pJ%Q>R|Pek~9P5)u+*GTG435DJB2GMQRhT3a@64hsuIB9Sj&zD(lr4jed;mzS58 zn)=gEKh@XQ7Z(>dHa6zx=c}oyy?OJ7%jL$z#BANXxum2dKQFJgwibav7#SIrmX>bV zuz{D5kdcuQ%VxKU6JY15M)!yE|Xwf1N z1OWh;nY}D#G=sdu!|1dSZwDL!4ud{GOOb&gAcHMtLw9#dhL9b%o+}1pxe2@!5A2&u zO<0h}@xZQf4kQE$>D)vfb5j~OY*SEp+@|$$ZX7Jd6LilYXYhr5u9yvG@RL(SdmnDcl%E!Nn z3%&eJeQpZG_cVyuuo=bY=}#X&Ouhf}-Q>jE@v%3rU%mX}pQ9r$p8q~P^z7;2z>~+1 z9zM8#@9v%3{e8VX-CehC-uSJvqy74|t8J|<&GM!zzh1s{@j~N2&Y%0G;cR_f?U|oX zpE~(dP4$W6Rh1RxWu?b{Jo>|tlH$XM4j$OQZ?A06?p-^Jb`%!m=jG;X-qSi_49c?X5lm=2=O%(xGfy#r$2ZSmIfEp)MDWDc=1OUhxU`E3%k_DFna223?kX=U4 zM+5FQX;t1u^L#=Rfw5;#selfL!>*|6)L&wKq_M_gTdA+i0TobRpR1{D=lDyN4Q9v- zo^R*=2&BaZm=Ks}s1~t9YC1Z^(k=2R^Ej^e)bEyI50eSRpS5A}1;_eXK z(D`duB;Z2EpNsR)noGoBP5J3o{!vsJ9?9EW5oCeSKp`?Kw|5qv-?DIcDj#euHB4Vg zx&W$Oh&J>$npFAd;0V@=1c&|!03u)VzIf+)) z)?&#IX#KLvOWgz*tfIqSwgw|~S=|6-c{1;LiHa&h89EJ=GIZL27N8DjK%pZ+p_}gY z8KfAWyU4Q{N6W1xn1vdT7Bg5j*~rVtM}O9~s@u+lGYzIX=!L;5i%gsnSuLFs7;KgY zv&z2mAXdo(W?fnHcBH;-OnY5KE=w)r= zi+5yi(?Tz=3)$-#z{<2(TF;_>HLLVN z74iZ=+5$75w-XZDo3!9oCP)kRfR3u#)VO6`6)am~q*q4WYsn~-7y>Wl7|g6VOnC$_ z00HO&C`i0~7Ig^AYI)KTw(c5v2L7wt`~59`OwG^tp^0#Z)YM>)XAqT4hGZ zfDqpEo2^g6==<88HzoBbgh{W6MzKuq$J|am(Ak8T z7qc>8Sfl@hE4k)q-RPU!O&B1_XF_+s3zOugSLsX_C1U<@Ws4Kz96X8d|VQ5oFLC4Km`6SWnWJCRc@;5vZr+(y!<9Z(RFaG`_yqim#$?8-5SI zuPJ}=u(w{#`hHzAGaKa2`1VpS$z{cl^Q>jXSY35R;M=LL0kkeu;2ja8ZLMwwp=)DD zYwtE?9TN789v*$#WCeGBX)w~&)3xTf^<>y2Mx_uSjf{uuqI3~SCs!A4N=%||lc332 z?(YSGmPp%pLjdD7Xc~$($J&BIxVkP(PaI-Wk$c>KkC6gSpt0u?Y&NP&)N@?h2_0Kp z=n|#@bNsDFOuMY(Xs%*<0eRw0N2#f%pETB{d%$eN>l+7CbTXlvB)SJ_gEiaBI#;?z@CEe9($%a!yn{{%xZ6V4h|b__5Emu-`QJq{2IO3=co9 zZ}$2AMWN*n)mCuC>u6Vjh0I^m*=(>~>J>^slN_{=|9-4<0A&!sOSElm#RQfN8Pnda zT5WC{vY?33dV{j2ayOw(yp4T^$+@L9@nTPLg~YDKe%c~d+m)CHrcb)QFkhPY>&MRx z2MdFm0u+i5%X@d0S7v?ouP+%3UJ-({ij=Re!5UOVlfuvGE$TlYUqv&EH?db%M;P=2kO*LAt_IH~jgpo6v#dPy4J#E5`_+&b zbGpGr-Kw!tl-JD1G0aF8)Z1oAQ<&lx&AH~=Ur%>WVEqp47AlTQ!EV2%Y{j2PseQHU zN+b)`yO(_kz77&{gT)S_jlD5`CfCK%!iG( zNPEFJJtdF>S5zFQSDO5%R{lS$l@4=l@&B$?&Q23w+xikHEtWwe0|ia9gNO`mP3x-O&QFJ!nzJS0>tLe>Afaq?fjZH2@6bB6Em!&%OdTG4OpzSW zvKf5ZweCkfqvuof+bMoINu{1_n|RpjI<#Ez$`KHh&K2!BRbR)NsM!JG`(w@c@td9n zu$caTo+w8!fFGu58Na}vd0Hr@b3aaDvJV$OG^I{cua@rc)deG_hRfTk3-rh=Kw8iH zW}5kG?LWix|8kgSmRSp?EISbMtiTY}Y5ABrMeSunmx__UEFk*M(YMXic}%KQ6^ZGV zs-VWUKhwF=xKfJH+1d?58p)+CNaS#VmsYy>P>(u%r;S`jZxMD1`24{hih&bB3JY5=_{)1Y}iDzqL7DO4o@Y9LV|BQ3V8gQq z`;RItYB%`(qcvGM-TK)X_tRxUL(i(8+Y_HYsCjnI`{9Ym`%Ub<**-trIdW-VjG#ZhSshwl2_A%Vd*s;+52po3#knqfY z;n{tu_ZzvjFuppEV>}#uV5#4u{?80e-qm93!FtP~y9Wk)sxGNhv|GV@E%4wW%flbp z-u#-;RciY{>!LrOHQbqFxK}>hyREsz*>E}bkuLJ_ZOPEp*~THw;|sCBoC@su(tYUS zbb}^JS3Tpwh5X^J+=ulxU(OK3x|WCRdhb`pL3EeQ-^ zmTV1{tUXZc;!Lb+BU`RPIN_0Ygh;FnNL)rNE#B$2d5HDxZ1H%l*w zgTe_V1C!|jqSP~-3w2|UBtyRV1(Q|M3LoWotNf1qiVEWSP_ev9*X{1>0A_p_Ri$n! zCUb?Du5Bx$V`R?Mzwtcd_1{Pd%%#(SVfRd|?3l&c&w&a)PQ{!IgqFI+B5K=oORfqS zJ~d85cW@dIbhoL47S?{nlWN;``US*qjS}^@BK#RAp$s~|SwRV1)MZ1LDu57Mhji}+ zY$*gpZ|R`_xCj8~q$CC@%3A{lWeP25+KNfUaGX#+n8%VF0N6s_Oh6M;G88y>vTbJL z4#U%8Eav^=rJC?sUNeyjA3|l+l180QHek;cq>1%|8Y0T;=qtPw)PS%9CSGBi$9VlD zm(C|lE_%)@VePYp9KO~SYvQFJO1Rdz(VZKv>r=eo6%lf%)-Cc0uPg{Tw2iJ|BPxpR zqKsP{+_x&oAHVIW+kk*RjwA%^LV8a=bjK+H+IEeQejCQl)mz8nr5GperZ4qb5*24& zAl{C_lS2?}1LV>x8!5IFx4QW^tB;NFrRJQObM}A!Uo_{;JkQMY?Cn2)m~&>%nK@_X zoSB~+|ETvf@V&ZE|8eFSXl3#s7ytz5fEDUN)|fnq9HuH%*7A6j+%-v_@^LYooc5tS zG{sdeq9jEGCCal|5%}crrK~i3u+>!gYO5%95P5|IGYW2yHCTyrR=~bU*v2q<*zD6k z$Wmit{Zf&YehCSw(^aXdo`~m-lHNWfq+j857s1WDKNH6F4fIM)cl_Vil4YvJS_adU z1u#8HneuTVlAM;O#H6??MdOkp@R7<@d(b*ovC{s|gOri3Ks*-BXg;#Su#>(F#wzH+s2rZT$Isq>}Z#RDY30wAMj5F~+N0-}JS zWLQl0k}C+gcFG+{6v=@~B`S%#Vc!zi4_ROF*}Np(o#x;288m{AD(p0Od%GFlE z=o(hy^<+XJLYzR;Wo;!BljE+3-0X)(k&?jIC_=eHxk*(}xVfl!ixM?_sPr>wKxd*iYW;q% z`9O~`&xfFzZ^y5iZ!e@KEk|%zCb`Nr35#VgQnF6ik(r5zJD1sjZXwe0PG}16Dv8NO z=0YM$Py{QNkod%FG;v%=(&>q3VuM|pH5%ISPl-|YzSrrZbz`asLoY_QI=QClx?@2H zKCt3sU4>TZ>UhiABR3~nM&9X*Pbk%>y>KpmJh2W~09x&{@Ko79+TSWA(DS3#-3}GV zaOqIF{i8|?FB@-B>CwE(n3;!(r}JlV2FUgp|75nRE;qBqqMpq@Oyl)qD=0BZ9yCnG z$?Xw>8y0{YTUx;0NCfM;#}}zEf^cy^uz1W6d5;<*3Q(ugUR6+9*s)Vm7|^>W_54i| z)&?KW%i!^muneOGO~l7c+z^jSSYEUx|0M}~azn;#b+(lchvQkr%W8HFgt%$E18Ne} zD>2WZlm$Y&$qxA3b=5pv2^h4hAy-wAQ%sA1{3Y#KsMK2_5V2@IO(`H*M_b$NewV_H zMkOpus35pnmGAN>ozrwyM)bX01L)%fdq@`8(9%r2oIrIeYNNGfAb36=S~XGUhID)V z2_GlURkv>DCpVUyZ^44(&>4qnIq4>;SNuZiwP^y_SPCXPkXtWm7Gmju(y2*{X$1hb zb*VQyUnHT-)2j5Sgxy4*@=yi!^a+4Cj8IjI8I!R7616e^;L~9uh7~$SLB7`aEWr?*m|`WiZm>s5cFiv5d&UDpQo;v<>?#zP7Eh4aFT0Bs$OyFb zZ}5va{31L*sNP9TW9fHzNlg}3p(*3fKP}FZVije6GiH}~Zcw-V6_ov3VAbxuXI=$n z=O&k}vCJjB046yMNH%-x)9WOGw@ttt-%()Zgqag&PS{&|k!YS_<{4(5VQ=$Qy*Xj# TguQ+mZP{ha!SUN*Q#T$ZGKvWRLv@}vHJ9z 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 Lls229f${$VzcBA< literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/25.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/25.gif new file mode 100644 index 0000000000000000000000000000000000000000..0b4a88322946c1b65e9236657d6f42c71e412a94 GIT binary patch literal 3127 zcmeH}Sy)r~8OBdG60(?tEF?im2r+;L1lbWy5OoM5NLU65Q$b)@h6?I*ijH!^Ie`Ra zC+-{I0$SlgMa2~iD4?}c!BMND2!czsN^wC=U``U8YM-`Oz34^na(Djk_j{LoC12#{ zpTq{(z%U3*yz6*VPh5@91jVmp9hk*h_ue zPJQ3W9I7V2)w{mF$m+;*>u>N~s}C$^0`3@1m;r!i)ctaNxQyEFz(9+eC`^XN3!8BQIW zt(<1eq0t%6P)gK1?i~Ktd>1RgD&R3clgnP50)~j$^r-=)g}=2U`P7FrwO!vqU_*lU zFw_kbR;~X&u~yc;$&E*};A ze5@dpf)h2mKgvz4`5VTT6Y|IUpn?~B`O!Xow+E^_0HQ)fRwZ|q!mi;yyT(Q|dNO5( z(vaIEBo^5_+8bJG6foKk?C;Q)qcmHc(BdBLY_wYC6rS^a^2noz&3GFqSXDV4J%vAC z=ygah&ds5MJuT_7^Jnmlu+);;JL9n6_Cf`txBd`g4RhfCW$xgc}fq5F^bFhU|C@tyaSPrXmiWx_-;j z5{OH5aS8B-y#rjF!nZ?Npn#VKr||^yXmubK7N3GoHlI6xp_vXT&t-${;6-psCed4Z zju{@l@;WGkgg5K1S4V?6;eLXa^J0PgH(&%T2jlBr%DGT{sEszJRRQMz+ZQ1&fFZ;L zTCD{?98kf}EP*W8;ThJXyzh2EtH5btM3@+smE~CvCcpxi0iQZ?p|$PAT1a%k0lb8~ zN*V1XM=G=P7E0aLQrUW{8%L`2wu_dUPcC+qVwegWOwJEdU(ghkP-diGnZMYcPcW7@VbmOIpx>pYmRCzed%2X+OamT;YIX&wUMpf-{_n-e{s zN%$P^C$0a3oe}+cXRJY+JA)~xIrynF;Ke9!5mD7YqETbKiJ6Anb{rbZpvC2^4Zc{! z@Rbq`?@=ki6uJ~mORT8L#Gz4nS%;41Un!I3?CJ-SYA;dAvBLTW)x%B-Lr`6rn?L$k zUQFOV%IqF#gC5}Bdi>;-4rr1qs0)dcpyspYF!zUWfX;B1Pw|1=G5GRA`1$l9>H$VDpJQo!fe^lQ++|HN)tdbJB?X#PIO)x4gJ8!2~2 z#cM>{Dvru&7`$UFnDf{c`}j!Jz`M*RZyV@ z^7Pj#MM@!7tHBCOaFE%PsLDbV6GZ%IZL;I;y%5Uc#Be!-<|=i7Qv73~>`5Pbu))rF z4u;KN_alhm#Gf?TP=UVBjrl==;SVbw#biM?3VSySG~J$pUOaa$xC~86cY`RyE~c(y z;VHb7q8o$qEoz*V&^-!AW>ZrGnNNZrm(c~e^_=&;`>AxV)ar!vH+7{Dj`*x8YjbMB zHIxKdFw=fb%KE~K|CGA|=P)WgdLGg&yjf|cZgHZsr#XXx0-Pulm#|#GXl8gM;4(!x zK_DnH%g;`r(Zn=Kf+dqU&=N`%R>FP2!cLyzQz()2zGiX$kx5}ne_g7o0A|~ha|cB7 zLV~2(5Gkyw#S&tyLY|H|Y{a_6+>X-?Jf!k$DT*zx1Tt9>YjOOZusexEd`ajc0VncO z5C&z(?hjceaQeanUKQm*8~Y?)J-YnWH9d5H%9D_3Gk;f#^_)%f$Z?0hy@IC_R`#iE1Ud98@p~5HAYTDuK4U(zc<#GppqcpSq`GsG$aR6;x2k0_?6-$i z7m=~qrPV9qZVTWbdZ literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/26.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/26.gif new file mode 100644 index 0000000000000000000000000000000000000000..45c4fb5563081d684f00cc3560df41b803cf7bbf GIT binary patch literal 3291 zcmeHI`#;p_7awFU=3N(!aa z)@F63%VJeZ7o=9ZQnt0-6xqs9JUi^x?ho7dFZh0*&+GMhp7S~9ywBzRI**T^H`7C4 z2s4C@Ps2a}4)C#HI~NoigHSB6*8!HOC}Tq)*G;fC2OKPj(FGJVaMc0jhEI`juo?%# zaMPRdAVYurYr<3!zjB>V21i&gak{lAP5J_jKOvfu-^l)FrbJJ zYMHdu?mXbW<6M<|Y| zA7M8>`ZC!V2bA`phykRIr;IV+AX^n{3v%H74Duba8K{B=jqE_49XJ^VR%_n&!S)dB z9_rY26KnuO1C-jd*p-SfdSR<_g2Or}K^W7S`c_1>>H(0|FnoE2Dtn+MKt7mk-&j=y~ypsn%lmxoVC zdZ5H|I>KavivdiXQX}mqD?~$B*i#4WNk77aw9K>q-nW-Wl{i>Tyn5Y}zx7_pjuXpm z-amiVI}dkG5I%)vQPqK4LQ?mp&HY5Z8&QJyH1vm&(Xlk* z^NW`zUCN#(D_Jix)u)Q(37JxkRKCK&g@>X)-I7O%@1c zF(Q_FKO=S~L$fN%L^j!T<_9!`=_ON$Aa{zZQ!JH6gXnY$&CQ)or#V6{RGN!3RsGVP zXl^WbI?IIt{r!;DXbNE*E12i~Hba%90aga>y%$4%zw(V#U%Kf!(Zyzdy@QnyeH^V?};EHd*b1A{Gl- z3|Bs#>dBzWidmzAMzk)=-blj~^x{RO9d8z5QeC&FIMMSHmw~Jb(7|_o3gO{5tsf(ZIw0Uw(ej z_tX7*y?1-MyYAe+b+hxv^^R*-ueATz*4pyJGV% z-LO7InXFhRmq{f_iEG6P@o^$yY>Xg!&FZMgi14sgD_1NJ4G9hkTo&N})zT$?zCPZ3 zo)_1Xvv?7E;R2QilR>co;>YZj#w?Q2>&na`qI z;P6A9*UbBTGj5qHeb0NMbcesk>yo7nt>&=64j3%Gu)bZ(E-AD_%hEo&CC|scp>@Z? zB&#mGyRfCTjNaG9(VE+vk+&0#)yRV{sBXxHXUVS)?Mav<;AeZMGt;}7F;7r07;<#B zcYzt6SxCK7!7kZSa~aA~zn0s5Gh?nELQ$(3%P%ybUKFn@4$Lx4U+a6kuT_ag6*8M`RjFL!A)XSUC?DQd$IFpPS^kjr2)m5Fadb!#?~ zU?17hwYm<~GGKB$Q+BxvfZm2h8moZb!vTPlnm{-Fbvs zTiy8VW>&3@PL@xR?~6<-^j{c3F!98{F|xnG&BMSuQmipmE8=;oyT7A{X96tV-m~NL8l~6+F7aUlOIu@M5({Ic8FO>gh^2MGk_!BcJ BI{yFw literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/27.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/27.gif new file mode 100644 index 0000000000000000000000000000000000000000..7a4c0131dc926ee932804276038bf053a5cc1634 GIT binary patch literal 4377 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 G^ZyND2?^l< literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/3.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/3.gif new file mode 100644 index 0000000000000000000000000000000000000000..86df67b7aad1ac80079562c74945d9c4ced3c397 GIT binary patch literal 4017 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 Z`!_Z%27Br#6>oByc-ZnwM>1&V{{f6`u%rM0 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/30.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/30.gif new file mode 100644 index 0000000000000000000000000000000000000000..b751f98abcf8173ae3c08402c99ae885a0dfe162 GIT binary patch literal 2555 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 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/35.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/35.gif new file mode 100644 index 0000000000000000000000000000000000000000..a9322643dae616390d8263e8cf1bc4d9fdfa03ec GIT binary patch literal 1800 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 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/38.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/38.gif new file mode 100644 index 0000000000000000000000000000000000000000..8b1c88a3e8658cde7b25b6e063d23d010f7ed86a GIT binary patch literal 3615 zcmeHIc~ld39-o=q5R!1nAxDM?f(RjrT#0}Q2{9;W1Xl3ang9_}4T&Mv=qe;!f?|nR zi+8-Swp;6Jz1lSiqLiwQXzQ(@Xwia#r2;hxJ3+DAee1q`uYc@6J2UUi%x}Ku@ALV7 zW@?%+fi3k0ynz87P&M7p-d3J?AIn+ z>TyrbxZA#)FnHd}b|u>W(>nV@wWIg2{Ri%ajee)AiT3NMw#(yxJVmhGTlDd~G4_Y= z5BHyP{A_;NmS+1l@b)J-OU)QZ&;A_?Ny9^J*AK^BXb8W5)XV;Tyko#*d$RTF{)il= z`-@AHtviAo&vu@ujdk=Mt;=$CJlopZ;M()G|Mi2uJxxK6kNey{Q`G%!`q0x)zN(Kp zQ61iSlKy!mudgltrIM8&!g3GsE`hxY)Zk z8H>Z7T$npN*g9})?)n^(Y1{0cmZWbE$sI%Y`mITQch|jaBDd`#{n{E(HU;W?uz#T0 zy~85Ca#xzP4>$E%C9mmO;k<$3j8ne+T|&dFVJ+vEC^yOsStfi=#7RV&meNkuZzFWJNQOD=vx| z!-SMH-EY6CJ&5*)saFNpz*UFq+9`vz;+mtSH1H zs$_YwMyib}E*Uo(K_Dy1SIbozxw05`MwI3$muiw|NTsh^P^jL9EiR#tv_sEVDx$Sg zRWy^%aJDpRn33_HO%;l_)+L%u*>Cm!+rTB+%T==IOj(I?sXAYVn2&R&QgQfdnN*`x zXDgM9M|V+Nq|_)&ij*ptpA`p(XGrtq#m#wR zpTdqwWyPej83HCVm6^hh6$<0nf>?G8Q^?@QjQR?c`AZeDV$G;;!Ee5?@AP$&L7_r2 z3uJ2f2eJa8TB(3Xn&!ygT?^}-@!t3ryt|f3@AQpEiivhY`%h4hE+PDJKE5R`^75AY zvSNhqYJ}L}u)}V9_3O~!z{_9ye}2)|`}|o?_fJosbp81FQRl-49qsq;-Mw@B*3BE& zfB62|)wV0v?=D}u_-*SqEf>x=pKG$1O=ti9^;c(3pE`Ns%j3uXcJzxQpa1om48{W zT)XUprJ54;5|y%8v3Sw@@}k0pvV#0Psbs->f1W>Y?ws75*?-E;%A6&hIU^%|`m{9B zRAH)spTgr#Nlr?f%wZ?Q$Hm4>Vlf%f^r*;*5fj40#)pQCqXom%puhnCv3|Zj-ebHx zJ=`f|k{i+0g@DIlF=!No$V2cDnot1ffJmoiIe(%6ei#4=0eISKEDj&r2{4aHn?gwj zajw4k+?sfg0|}BYin!K8uuzmssj!S8#aIGz4XG9ULf+%q`g2pSb7?79okFtGb1QR9*h8c^l8IGmiuNVyF8j;l5v zXX-)M@fmlp33o$GxG*uH*Lg0BJCBmgh2WLt;yv+sHmM7P;`TB<(bNTQn0slDODoe zmZWkkKJyVi3oIL7LuqMht@aMJ`dXp=)5se=#-k}*V~R(RE)(6@TUgsb(j2>Hr0}7u zr^+I9B2ZKbV$1M&yw$AJV{k-G!}NA?1(2_38RX49@8#Dx3)gPLp(+S*KrF!ZHw8k+ z6|TnHTlG|wTS1wx!`wuD&^&qIrKgmyaxHTa^fnnGEV1n9g3sG0r|74cXC>Bm{cO}x zpMF14HPADHnHad$VVq8V(e~X>0}i;!?mrpd$){2(+ne>cHUqD0po(Eac@s6|q+qW2 zT$K-9wSXE719~dwm{knL69Ev7-`AM8Mj|kzs7Rrvs#=$8MSG!njk+dGAVFgxClKL% zhKNR>62s`fVI_pmH<&j1%!l`E$ev9Qah(`p{t!kYCq`yztw-_-d;+DZ!fQfKf)(${ zwXFRJwYw`4ECg%G)N-phvuXwobbSx+7jDsQrm~7k^(
    • ap0JjxBHsOrGeE$JcnI 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 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/4.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/4.gif new file mode 100644 index 0000000000000000000000000000000000000000..d52200c51ee924f0b91132e5cd3737fadcf40ef8 GIT binary patch literal 5689 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 E2fD;K%>V!Z literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/42.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/42.gif new file mode 100644 index 0000000000000000000000000000000000000000..0eb1434b4e81d4437098efe06cb4e1ab44a86211 GIT binary patch literal 5305 zcmeH~Ygkj~0mo0^kOXo&KnQ_Au3TbK#w}bT)dT{>Ajri^K(Gmy8kCK&isJR;LP$U^ zkqSk0YrG-a+6lUjwbVgCMJo$M$H`}j>#dkk(v3$GV{6*}BFogLpYc0=u zKR>~-Jn6LD+if0BwA`ZyF>EB(yK615x?nd;V zkF(F}WncgC7d>^znVFf&rS|QWQ8Qz^F6|@k@jx{eP(~{%ERT7eL*BjtR{s)r*-F7F|Ic4F_%#>Q{@-nzWU<6+;@FF#!;2?VbE)@$TkUDu(F{Rab{ zj>xqV_J=Cp+vnDtP{#JY{`!;Ax~JbheE7xI8*MRH58y{m2Yl5|ynp}x-^TY0o{Y7O z@9L}%KkQ4|>W6s#dHUGze0%DNmS_z<3TiIsq`S*!pdSL;?WRoB~#w?QxscUMI-QzHu z9RfFt7+c({YgNI?1e!k?L%@)Wi~Y9-|K_~_X=(u>Fwl!okSfiLI;q|k#b6fXMPxfP zWJlzIZvIi*)S+(cq(Ugdb9;klgiuHX@S!SSF~^MzqM#h=W@^q~z*dhkUw9+OgYF|l zIPaA}t+)ArkBpaJ*8a`aY9@;pDSq6|cL+%OV6|KxQ;CLH8}y+j3Ao&wqLWFx(l7^b zTw*OGHLcQnvRA5jgK3vVNL2ozGS^-|G%>1RdgzeyZW_SSbJUk z$B+c*`WQ{YtbMo?Ej#6G+>fiF zQ;MG5NExrIbjNwF3^L}Pt0P@?SS)QTh?#Qt1NZSDuzM0)jI5Y8*!MmCc6h1zE&wRY zpP`}YlvRH^dzkmX!17J|9@ctZ@Na^XK`FG;Mr$WTT>pYrZsN`eltY7)r(I(1OIjfU zVPwSih6qnc5VAn)mvSg4+)67v$MnnM1zbT0s)XDM#-gzVJ3X*x^kVb!(5h-+)Ra`S z81<{5NWYfz6cjyvh`qk68x3=fLE?+`2rqAJf-dN>zYs_CFE}%D(WeJZELII2s6Ve& z24K&ylRkb@g`gF-pg*}OI$WuxsqC7e8)W&N5YuCC z#<-Ez`fb`JjnO-Te5gsr*Ptkjj>1h_y+0{sITre1O-z%v1Oa|)C{r5VG2lbiRhwK# z`Q_ns#nA9rXDSLn`{)uBT?xEHc^HXSJn4nYkQoasGLXv((^cs~US0(6jGXYmhVYyWZ>ks7XK-x`2II^ZVXSyC zBEIvzqw%ne#>6ujDOaiyZ`*&?^a~*7iR?Lq^G4Nv`}{6;Byclf2ubG?#IYF7t*qrF300 zAW&(@H;!-P^HG9<09?GWo4=+uIVztMe&uTU^++%IKY=p8|fRqn49 zmG`|BdlYkxv)FQ^aVnvz{PLEL>eRmzdGk6 zNVYb~_q{JtiwFpzjP9{&V`vpjOZfla(xZ(XpOgf7bio~uqS|J)(Qa;O5=Ojt#Ftu^}7U&!WricKDW0ccoQSQQT;IoEgc;-VL~uu zB2OCf!=|uBQ-s<8_D!HOeLZqi8XYV~lqbw^iYkT+q}J~HE%3VjdZO(C7wKd zj&>nYT(nOxv(Dc=P#~x9l~o=uIj5)#OK(Y1 zb{|}=4ZwzM$d?~gqwrMW%IBvG22~Eus-hvXk8#C{f5?AkBHxgXQ9zuy9TSgHRkc*% zBl>`W&$>>h=%4=62(nAKUhOGAbt8mv- %FKWjtVdL1P%I)BVn;-eLqw9kid`E}a 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 Sh@V0@dM8BG^xew?0{#K$QUnA5 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/44.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/44.gif new file mode 100644 index 0000000000000000000000000000000000000000..ad44497691d150ea5d02a900231e48ff519d9616 GIT binary patch literal 4126 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 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/45.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/45.gif new file mode 100644 index 0000000000000000000000000000000000000000..6837fcaf214a394d8efb68f5d48c9ec6f9ea1fa3 GIT binary patch literal 3417 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 Be_#Lr literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/47.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/47.gif new file mode 100644 index 0000000000000000000000000000000000000000..58a083611d7c1afd95d136e3a7fa798c86d0c2ef GIT binary patch literal 2333 zcmeH|YfMuI7>2)d+R_WymLAH@(krc}g@UaIXysZc6v|DCFw{lML_tx9cp184*`ZL1 z8relh&=?dGG3o?08na|UL^p_06A@IL<1U+y4ZKZ27)xB1?B{;%hyT9c&-c9VYf4Gd z>GQq88%FK$%pZF7=(9wa`2rr;b`38_u1Ni#YoJ?-PQ<{Q1Mt)dw;~qzlI6dI!E6&; zR4S&=!}MYJULot>=bAnPrxl7WG3{Y~-ZMS?R7Fmx;JV!ZrqlUU4ZS8>Z=`Gh;F>w* zWhsn$!lPWuh!*)(43jHi(gHKv;NC*y$D;Kw)BTS}1Ph!lJ4eqYW z{g%g>PJ`Dq@YVr0ZM$bS!gWJbUl8S%5Sg+-e-LyD{YIE@A&eMd!^;HdTx;!1^10x_ zc$`oDtrVHP22a+a6LRQY#Ggupb_~Y&@Tv?ZN#um07ao2`LhsAe+>VK!o12r&xo0FU z&rUEbOVoxerXTCRc;d(gnBusp#@^!YJb!2 zEjv?U4%vf|HLNuvF}0Gq+TAmiuS;9EgNm>?9F_(VG~2`EI{r7h$iiJ^X3FI&h0z%4 zL6hltEXxP6ib9p1!Xj|?EmBaZ#MNqCo0Ah8sZwch=Bm7K5>qgR3O1d7XW6dOArs4w zeTi$Z#&Hh_i;mYzcq1Kd6%cVmEO9zGLXsFOmM(H|d63aejf+oa1m%s#@d~JB5|f|p zkhEvl9ORZ>`lH{%a6?t;-40NlJkhCOSOwY!SO8(U=fBerAgKw)j~WY_$x-8%lobMT zW7F7yst~s7Xu+w;z)Ft$W}2Y_4NP#ueD06(iH`OLp_|x4(cOjy1niZi9*xp*|H8+7 zhYy*DhrPq+6`BzeOuFpBOEN^>#J7Aurs3C{ZP@)Gp7QeZ;u1*0eVkjWV_tTGL5lLsZ%QmVr#~iiiTQ&bn%& zAUN6hdnd%DpD^<88eN#Qi{-iWM!ilP=s2j$lAgWD8yu=<+sn3hwix!OON`05TM$!!`a0qYQ+D0Gm zjNQ!D;g+hwM9lVZCZ`~Ozsn=@Xkban)%L+;Zpe$0I!N|e`gP{GrlKDW&>WlF*Kz-^fm&{KNpQTa;MH3VbMTSO)Iy`7$cc!}$F;)1yn)K77`oAz1q&dbPwMcqZS4-Gw#0WxD0%0Pa38b|9mayJf#kALK}E#J$BBuS_BN>|>~!Pl rL2H#EiEFFJCp(ZsP5Wj&2CVH=rzDGc@3T0Qspp*aTJ3^`42b*_XAT7W literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/48.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/48.gif new file mode 100644 index 0000000000000000000000000000000000000000..7ffd1613b5fa36c3ffa7daca94e7e8cd6f8d82ef GIT binary patch literal 2689 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 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/5.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/5.gif new file mode 100644 index 0000000000000000000000000000000000000000..4e8b09f15101f3e3fad0777ad068fb559ed483a9 GIT binary patch literal 4567 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 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/51.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/51.gif new file mode 100644 index 0000000000000000000000000000000000000000..ad3f4d3a8158106dbfa48e521084e6c56fc6406f GIT binary patch literal 2785 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 Y?y9hKVE|Dl+bifDKf^#>4e-@}0Qq7Ywg3PC literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/52.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/52.gif new file mode 100644 index 0000000000000000000000000000000000000000..39f8a22846945358446ed010e2b9bd50dfcc7a25 GIT binary patch literal 777 zcmV+k1NQt!Nk%w1VHN-u0Oo%H_RysE&7t_xrK?&j)|+hq+_3!Ft?IFT)0AV!c0$aC zRqD8h_|TsJ>&E)ltKOw@>9vIN%AU!BNyvIc?7@=%;kM9?T>taZ_{^H%oM+RGRsZhF z`r5JEo^R2GQ{9+i_}Q%gdgjaz^&bp0Z&w@W+~| zS1ZnjO~rUYx^+wGxrybje(A1!?Z1)y)1|L4Q~-nP||Tg`+@%Y8|vQYP4yVcL>g zvt~NObU**!w6tnI+^U8B*sH*IM&_z|#eGZp)T8>;r>$c?$Bk&qfJV7zHKbH2=(mZ+ zgI36gSAsHn*{k%yj=+0P^2nRuqi?otLDrynz;{Fc`{2HH zLjBdIzja5VP9(HtHTc)8{no1Ese0nAeZ78I+ml?_ms$MWwEzGAA^8LW004ggEC2ui z02Tli000O7fPaF6gnvseg^7xP76J~4i-a$bjEyHm@r9@V1n%lQKHaE#3h9gAw5QHw^!C@58A-z#?=7-ZCbD#S>_nhy%@3*|?JLj$r zU5vC!qK3OKOyIjL&=f_HLf;KT*4p zQZHIL*>mDv-L`YvVqf%rGdps+K56x(eBtbHo$;}uzd}0JS}|NHxm~Bf|9!#3hMa)| zDaI$A1BX-3rLP^W*F9<~ynSN(aJBl!)R389s$bvw?#gaq-51dF?#kK0W4(oOk6Vjd zl)UkdlJ?B7ryW&o`i)(Mab3EYQ(Gg(4dpMdA02BcGLHN()!#I5aO>55Th64cdC-(| zwOC--@u~4nqj9|JV(vQQqt;8=(I;hVCN5SESIegd&yKZyJy4;Xxn48%Yi)PVrrDum zwVPMYj&|Ov(T&s>bmqnO6vK~ON+vEGtV;-P&x!A?*#7eJ{->>_51Vs-Z`$|ZOwr`k zQzuiRjZ=f?cYHSW^ZuKa>Y;{;!RoB3YgL!?HW>SkyuMb`y;nRv)bQ$7qwz+=!{*|X zim<)|Dg70x&o7rxc9a*g78|FA2CFj9?@E{%ta~+Ff2TU_Zf%CqXmm4LNAO~zIqXOt znLsk12LJ$KS|1(>as_Gu^7RkYC- zP{Pp}5i!DyWFb?83tR>IYgihoLJF$|phhZ@saTo-oIoUxhgrzjWG3RkHxPAl0FG^1 z08KGDawQB>34Xpp5(I%X8UdnEX*9?OB$FUAk%YW7Ux>n@(pY3V`0l|W(UhVstSB!3 zT`Xi4fJ;=X6)Yk#EiH|Z=0}h#6NnI#$u#*OlYJ3{uPR-p7HE8BD*T)WF02wN#R|1p zE(1*-1@ZC}bpQ^@^lb@JMR@po$1)Y+O+f^qTuRgk6hw$XB1)yEy568w>L~a>X?zf^ zib+?%#3)!LPf-eC1dg90Bij9WAQKSDhP75HMm9wt;mU<6Qdp)A-l=L?+7Ba#f;S0dk^gpjWs+ zD3+NF-lh$DTQ3(@ic?_`Un!S@Zxm*UKac^%j|uTeTr!FOzbb#r75zV|5s_qwruO)+ zc9}CFJ!l%fZ+>L*{`kN$I5A-hEE2{GHgEc3W88+%KU=@WKC$uYCez431$Zct_tv9$zn3-G%Cf943UTgU!N7ry}dk_dAQ?oZlLSO zE`RyRd8yM9$Hfkd?Coq9E|_m)ZH2{HqEQy+X2=!eHf@1*0JMM)a@!!k0Y?C^G-hda zIt)gi?Vp>kx0Ypw>SM!KI2GiF%B@^;w6Q!MswCgqRYTBm(HyWU*Wbpa`euwQ`( z?ld}ph9XzSBFsm1-tb@LJnV#;e?cw?yRuZ+b(fAQtFN7aB`_E zNo`e`D+i->_KEXu((}=12xIHxlF_CMVxWVt_~h+fx(#$2+s{26mvxzO&0IWFah{&+ zHZ~Ycu#012!K9HY_Ixv&V3Zp+BG}70G0sXSEHbzCdVyK*#_hCN*q4 S8f7`(nZXDyt@tenSosGvnoLjt literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/54.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/54.gif new file mode 100644 index 0000000000000000000000000000000000000000..e289d929b9552beb7be70329b7cbefb1d0618008 GIT binary patch literal 2196 zcmbW2X;@QN8i2zdHUU9)$4j6T6|#|pkg|m=0&O4yDyY*Ek}CwrViIH#8X#;!fP&G% z;({n0L5fgC!J;fx7EuSJ6skCc5iO!DMeEQ(dwT=o^oP?QbD#S>_nhy1>wCU)?zUhi z*_&gHutq$QBVOLB89$TJt%#ne&wlbv@m#0sX>;C<%y8&wJ2chSpS2xY=pHNs@2L{U zzf2e|2=B-Ug`Qu7rmsG0DeB4I(UlVN=EvrdNtcv+MjPfjj@?zpydF6ZJ!*j_uRN|hID75rRAc^~Lwn{g zW4=?uQ?iy3^hE$T7wu+`$(t{dFyU>5G{}eRaK6)a#zgz&_Klf^|wk3%H z&0HOBIJ`7;daF>sZ5x-zo0fVGFF$U1Gu=AVrh0z$2sD4~a)OV#K1W@jyZBwz z-Lm+*M}&*lmC*QwpW4d1vUbi~DTmaT=Gx1kpKnamruP=@8z_ib8me0!se>ji&30Fg zoe*`)7_)6(K(ig==j2ljiifoahK@-F%E0cd2nd3lAmdO*WCV@MX5i6S9W4X`0gIwo zY=F*@ap13yf2x?nO$22?EEvZZ`l9B)?LYy1o-b+_k%eW6X<$4*C|v?Zq=!aw(-XPg zJe0p5;FC&86^I3(j02T32z@IoX&h33!eF+;$<>1 z1%pXRNkON0qD7K849?rzTjK+d_kcA#q-jDKC)GnJbzbv82c=vIUo7K`gn-5)Csvd! z^F_g#u9hGWvsmvO3#I6lg3w%%0F%lQV{m9JMj+7CwW2MRg@gZ1lKn6Y#&mc2AaX1Dp(3{9)lDz3eZvu{qr4iO_ zgN0HVN5}=&;_~6RZ*6gZYD=L>K#oi#i4=*F);fS4FOrF*@ggxmiy#4REDo11)Ce|f zHfXh8Iw;{E0C`M_NC2!5rtsgB0fFF+V_@lcEc1U=zG}<+f2d*LWH6fc_(Qv_iQpd8 z4Bs_BJb8C~Kp}i)B=F(Tf_{7Rdig)UF8%w}FE3v#{=6_hH~akA%+u+go;;p<^shdJ$t6+boHr|CyrNrd93npM~|ouSCoHIR$8JgE;>|Lke`>U$jQ!< zf1a6fFg-0bE+QwwiX@S%Le?MQJk0{<`FA|a9iN|3vXb<S)7PjMJ~WhE@nU!X3VC;NO5X0$~7U$#WEPGlS39 z&90mn}`MmRFg6x+I1XVw*+WNk9Lpx7AVlVoRR zbl_uKZEe*S8+U9{^bUPHJ6~TLa|I(L+0-GKhP1$7kZ3BEKoAbewLt`SI}(WroEI3Q zo$Y_w5SintW9>snreds-dlwkSI?lK0XZs3zx=T0GT$-wEwTkTQcV=W&It3Z6w~dP` zoT66TEY*Esb*=%Rv5mBy8mBAyUEL)P^dDMdnw)wqwD`LHh-|LX&=L{rR$^hGpJiz2 z_j-XH$}HWa|I!vacypk@EJbX-fUODC!zvP{rqxr(LWCAUKi7hm6Og6P3vF+v1_?^7 zw}z|6I;+EU%uPes|4rGyebcC2z;H-TQS)rxf zYik)q%Pq8U)-^#`x@Ig*P99e}`hRa8Q1ex>%_cvw8c=iSc}6k%BZGrohK^QRp4uiz z=X~94glXULAg*F?x2eZYmpXBPmLA}i71`NzR&?5atL_KU%{2`5t*G7P>yO>c5g+{y DWiE05 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/55.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/55.gif new file mode 100644 index 0000000000000000000000000000000000000000..4351083ac8e0e65a64ff362cbd480f2c86eab4fb GIT binary patch literal 1971 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 O9M literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/57.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/57.gif new file mode 100644 index 0000000000000000000000000000000000000000..0bf130f0d930a1fb72ca83265bb504304cb08090 GIT binary patch literal 2705 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 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/6.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/6.gif new file mode 100644 index 0000000000000000000000000000000000000000..f7715bf52817bc577c0d33cd0cbd17da898848a1 GIT binary patch literal 2213 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 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/61.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/61.gif new file mode 100644 index 0000000000000000000000000000000000000000..f092d7e351cb195eaf707dbec74d32ced42f432f GIT binary patch literal 2495 zcmZvddpwls0>@{J%gYR7j4+up;~ps-g^~<|amh}yl}_7Y+vT7Wvfa*3b5mn-Xw(QEPFk@m^%H;^Pm=R@3$tBn3-FJp|Pv^7m^UwSD_xb+5kGGGPlXIvZOb_;w z4hu>WRu9bO^{zf1oIGFNTQT^7Th-I``h94IsJwfkq%pUy5n8e4q73P$oDwNA;h+TRVnUA`_FJACO6c)M++_wCByGB~^fmi{J_E`ZV%ux@x^UqeupTcd6~3D0Ton_H_0dMVc-Ceds;7_7Op3fM?JF4-(bWew!@<4uipnOUf!5Fgk22^bcK<9t@@i zGUzOJ!o^FRL@r%h`{;L9cxhLT+S;;hHGHjda`bQ9$hGqE`;ukr>qwwg1iB)Ba1E>= zIQo{*H$+bQXPwkpP7f2#7?1(FWFz!_ND+*?I0CmU!Y%?{_}D zgB9YeWcn`vZu)Kp4uqR3Ift;0s3_^+y^owVpxk|gF^N>x?KB?ea#FcF4ONmD~V zOSFv{O=Ol(xcPUxJUjIaHyf_N$Ui51Du&lY#~(285j^#0 z+p)y$5wMc&90YA8OG+(0$;KU54((qFY0GR#-E>RB_@<5BWT5+m-*`@lH`jD>3>hhz zO~73TLx7mVd9In)PVrDkF?$jV7g=gyLt50aTFVsNwqKcC>~5umE*o)@KCH9I?^-I1 zneX=3MJU0PVLC93;v#%wA)ts0iChFHIM&yQOGI(gh+HEG+aj=;={M8#GNt0Ik;)Iwz)ZYnw*K#u=Ajy&HMWM(0U$r z8WcwtvX<6=aIbLZ?X}1*j+C92WHcJL^@OhOiBq^avgOX`vt{m75!@Q6lt`x;`D%um z?Jn0NMjJ)kEy>0Fh*CkaD%CyCN!$K7PU~y;^Q(&xo3w3TlqNDEHdnE60n`H)%qPm< zipFzoO~l+H3u8)cb!gM39T?sXK*x=f9A)oD8L(0jeU7z{R|c?*%fVLe>6YAlQ!cOi zD<#NKxt}PxpPyiX%)1Dg$8`<72${F8-8KH2c1C;@iq9t!`EpKj;qLyZ5UzYpw)%!O z*%YSPZ0>k$J(D9)C5odx@fG2tVqgz{w$-kxU{cj& zQ`HSX+q^LqYmT2w6K16$uolXvd78?9fsqdv4jq^pfTBc1g@vvj=GIqKdz z>}2-8ad;CGJZ?`4i9pK^M8;a*G;+zN5lBHrIj+bG*TAx%sI?v6t5pDvGO9(PYHNwa z+K)gxyA(j%)_@KTe*$#s%{tI@xp^zAa-P0oCN(TEbFaCMl|SI##?#UGbFB8zSkvTV zjm{^`NJxel)l|G4qskPctFUi2#n9TR60Z&Clq&4QMUFn{ETAVB8$^~0ZmLoXA^Ubj zLiQEzqAf%A-9GlPRI$uTx_Mb%Q!(?Is=w-kvOI#N_TQnIhg!$-^3&(&W4wIWDJ*=n zD>5SH_I#u^`C373Y>nE|@)|V_fY&IcAkhG}#wm=P!cdCyN*22z zDC{HyrbKL8n1Bb&E>X^f6c)Fp6N*t=3SeBV&1Ae2C8p%%Rb_kbbSG1!s$q=Y{1YZr zBE}%dY#mbQiz^%}>TvCk?!9erOiccHgSq00G{hJ8OKsB&D?W|QM@i-wbUNU@UEhku z(%0Ya4RFKvAzk(Msa{jvr{{{?7f$y@X3%k4b#LjO!qIY(zCJ~CV>M)K&2~J2p6kP9 zd8t(**0*4*=}hVpw~ zk>4iKC;9E}`7^(Cw7Eno`6R#7|DRt=YQ#S*Joc_vr63V;(D;a;NlNliR7Kb&hNt4? zZ&a6}DrHbrO4^{Rl(}$cpsH*=IpmK)Kvi+D0P^xn16W1s6NxyeDm*OpGcqqGyy?>J tNMrII%;*&@oa8uz=YCKFxNClV+=*Obvw`TNkx8belN0|*V!~j%{{ZDj7zF?T literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/62.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/62.gif new file mode 100644 index 0000000000000000000000000000000000000000..7fe49840bf69219fa40585741f901fa0b187c044 GIT binary patch literal 2017 zcmb7E2~<-@6b%XriWPA~E&7S5U?CeMKrqS@kf@<3s92X0ldnl3i^)eK*p}kPCV~ix zfJKFXfD#rh3MxeF%Bm~@$`%k=RFE|W0{x-ja#}p6bLO0xdGqdl@7;N4Hc}idt!Rr7 zix6#oh~B}G&K^Ze*N58H!N&G6xk4GARi+#rdr?2s-mN$Zt8|D2&!)bX9 z@fj60tpjNVjWOA^RZV?0ErU@hrAfEy&WTE&RlgllC~rT09U&^daj!XAEKSO4Z0OE?(wdM}k@xJCRMvO;(u1r*Sz~*@ zq`Y0$DZiRi^Q5v@Qr1~s|L**?@+fgtLCM?PXKk_BwY9CiaoN&K;!4HHXkmFrbBA21 z9KBQYI=!&*?6v1`Er`#C!PsnP2RB!HTNei$3Nu{|zJg8eR2P6ugJ|%&ZiA3VqkDo7 zupd0g;*gNtdH0b3i$Ox}#8WX;o;}E9Ir;KIS6^p0y00hQih}inbI*>EI=Tju;zFI0c!%_ zFjyQK15bh})|`kZ5OEg3#6ZH)_>2R@ZDhxZSn!F2WI_;+h(`PP_@I2uP+a~&G}g+> zO2vW0nZh2Xf+HM=CN$*;R!%aIK>?l5;z2Af2T(E6_H(@<5)#hzpAy)-kF*>CYP=j2 zoy$fGX*@I*g;A9>=}4u1-IdM$=q-S@fuHjIPhx@F5gv%%1`4>|d^!lbuT+KN5$*XP z4dU|MxLmJE6^PHtOFLFmUsf*4rhUJu(PwYFgL?aV#!>(Hyh+YlUT+lEN)7ysu|ckI5HXJ zvkrp{M?RMgj2BI0O_>YMaZ0`kEMw|iFjHdDa58As(|-2UlP0)-RNIe@3m-nVKFERl zoewv*+SsUaWLWV*J~TMc-`D%Tr~BR8H(i|_?XTNjwYJEbn;IMH|EjC4kyck#R=j*s zURGLCT=e|e($a^f-#b&cY~Dn1+UV#&wzspj*|46p z&YEatX+gl7o8hn+G|JTEyS2tfYgVr^T!}OQRxH>5cG=P;dW#n=TrgjEp3dBF=4j8J zrKLG@hKBm|Y4G=8@IhT`0m2VqqWVNspEzRXh`(RJvEwIBo(c>K4hiuvHMQOtdR#}q zFwx(=H_}f>UlZqsTW+Eky2fa^dRm$zKn^rB_L`5MHH*J~PM-F`%<2aO_;S@38RMvJ~yY(nXQh9H$#C+X_N6J7*$<3$?X(0mkzJForwl@3YZR zD(7ypEO`2UwUg#jKaV}(l2@CjA#_$wOK5tyC3Nl~OJ>c>w!&a-TDZC%g`ap*7qR1L z3eZjo)z+#wr(=^XLRhaYF-#~^4@uA#A)`uxOotZCF_r@COs07jYnjoR41IHx^3z(23>`O(`)4x0N+N9Ug7`A4=;!*$FD3vz)I&(EtPkek$P3WH+wR>*i|S;@u67A}zhS~gjRlsT&q z>2ep_vPiupx+%s62_mZ6VYfJn&1J1cwzHwYdCiDZL26Es7v)%gW`st7wp5Hko~cZ8 fzaAzQ7Zd=~XY>c^Z;pPWn-TRQb#LAp9fbAYHD_Zj literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/63.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/63.gif new file mode 100644 index 0000000000000000000000000000000000000000..cf8e23e5b2e83bf4f383cd994510a7a04a74f57c GIT binary patch literal 5871 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 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/64.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/64.gif new file mode 100644 index 0000000000000000000000000000000000000000..a7797198af0f3bb98361b1b8737784d0a8c2cba0 GIT binary patch literal 6448 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 E1xN?}xc~qF literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/66.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/66.gif new file mode 100644 index 0000000000000000000000000000000000000000..bb6d077504e3b39871f72150c1f5fa43d4e18bfe GIT binary patch literal 3029 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 n_4QGfNp-c(#;#v)!?fJ=R?7`D2^Hm literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/67.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/67.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e33f7c4f762b5c4eda2a630793d681345423734 GIT binary patch literal 2701 zcmeHHX;@Qd7QP`wAR!P4LKMNv4ag!{fe<2l0wNMfff>RmQ$ung5we&B2sE}NQQ0hl z0##@QM5-uS7zc}jV`Pm>RVw1%Vylj=ZLzi0Qai)kFhb|YIKSsdzvp|N`+eu0_dVx) zXIZ;0ksTp&2i$>2dSD!leuTm7o^ZHfYuo>&Z`mPt!x{U-cRY5C*l#mC41LSmbHT;( zUGkI2nA2#Rrb`|(j*iO1cHQ?pn>;WFZ!LY-f^QrJJ1>S+WVvi^!dIWSuQ{>0b;9GY z9lH1^R@7iOPITRW)o1$v;bH{m?OsCtkax=nP1QzdzT*05X7UsP*FHsTpY$DAMmjku zHJ&8a40_cKyS{&MMd$Uv!e*DAJDlB@v7OgebU^t17Vx9nkfdcv>K1JA{$-LT+^>20 z*PhFU9}1p=KA*p=ujus4GGL#0dDncr?3a|ZhSRZ=1VYCp|7s4ldSK}bF7J8PhFLnj z>w4I+JCvP6u7>XATl;W>Unkd$;tqWpd@ms2%JYp!ZuyKpf*;VCr@mm{{^?CcEAB@( zx33b`9=e<|HY094!#O-AZXH=K-Q{|9M)S;X)z$<44FiFZSoG=!L84kW$5MoU&$>XH+5?|RuZc&g_t5tDm zw33n%YDoxHsm`Y{A|fKJ984w!(V%Eb6l7NT zNFj#T@uDDvgDR6rIAIZS^zd+cNJ1Es%U~oh;#mwPJ3cOs7akWE9~Kw7faNL0MRHi7 zUBF6y!-l>VYb^%33bD+C)v{t(lBib7!TF#$ve)~s zFNl!(u^tx-7r88!KCD3MU5ykrYVM!^`1R#4vp>Ih{?m`oe)#_B%y-{@^W^KV9{>H( z!v|k}aew;r&+gs5bNklK8&lUOuYEdk^~&W>E?vBE-ZDNmIx;+T&V2T7X9fpOpX&ek zWZz#;{H3?&qvOZAj~?kdeCWf@gB=Ij+gkU3@P144zP;}?H8$+oU0=7W_T8N|)m4=h zJGO5#84cy{yuDTbR#~a8q_{|{QEyQx74pJ@%`$0z9xM^(iZ;FZ=bVij{**1u`r{um zGt%D>q^0sx)+et^TAP@_xD9-fyB-6$pG36_y?M{(1_q6hr8^^LS-#_kcH}58IGV?6=MdMD+5tUHk&0(>?g&0>`2iA*g?VMdC zmdaRm(jLeZy-5U`hE1NFpy2)?1KNnSCyiL>(s4(Os~bURs4yDQHnyRo9cFXYNIGc+ z2pWb^k*-f4kC~d!HQq2r>t@r}blF69IS`U4(--l}tGJdA<(@ATpV^Rn%cCu8r)H*y zXJ*^F24{JO`Q$h_FC=Fvu=G`Oaw*$$jg{LdK^2uoN{&7$7w~EV$Z4s1O07Phh&(;P zi7c;3?jY#3wHQ5$fI{nY1UVqkhjNOl%+DnD^*I6KUdCi}PyuZ8SChsXNkzrQMJbbP z&$HsoB}DcV&l6UA7AQy$)S2Q?E>}s-%cII9FJ&8%K{F=ojVJH2ccCY(D4jSsf~(-W zdI!dCx2=jSjZe8Bl8{_!$~YioOMS3AJ)9Y-*=>w5H{8ngl|A$y4q_@wuWq_~{zQIS zs9x9Ieyv05ygZZ{kkf2Pb@4V<6V}B)v}v(%;|n6T7^|ynU?vzJvZJP|MYuUd2HD`6 zOi+Hm&_WL2x-moYw(a$Kc+P|g7G~-Mh7)u*?!>io2`ZH#lbLZlN1QCU3@6uz?6Qi{de e&Ns&5+yCAe|96dnSxgQJK<1box?FDn*8B_Be&pBy literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/68.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/68.gif new file mode 100644 index 0000000000000000000000000000000000000000..1a6c400d2aee3c2bf384ea98105ea143a7be97a9 GIT binary patch literal 1424 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 ig6vPE;(vp8vN=19VTuwMWT7@8^o literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/7.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/7.gif new file mode 100644 index 0000000000000000000000000000000000000000..e6d4db80572a8321fa233d7efd82636fd896bf49 GIT binary patch literal 3398 zcmd^>X;@Qd7RPTELI_!bkd;Wn76gSL8VCjmtHxL~xKN`N+n}hegVj>h8D8>cxj_Xi zSjVMQtw_~*7^&k@lqw)n5L%Qf;?}a%$_S(4Sc^ztZUR`_vClK#=R=++pYA>9{D0^C zZu0D;h{zS5h$r$BKyDljeeg~Gzpv>>pPpV9$sVltd~rxR`uyh5zR4p4e|vFC+O#|H zv~`i~-j?S%p|-YZRTls5(~6<90^7Bykw*t_{yoLk9^2PA*Vd`G-JE0VS^KObdni9- zrJysV)|MRV zaBJYG?OEYU%}|A8=;|Avr3>mxX52f;8N5DkxF+IZrSRUFsV^@0bbS{2%grTUf2o$GyCOZ|TCDz;sYyO{G90Ih5#fO`;Ud>i6G9Sc>o%d*M-cshOA3A78FdM{l3e3 z=iv1o5zA&zFEoa5a1lOUE(8}Z0nH~Xq%>s4f(3602*DW{)Gyc(>Ix$sVT<^*41ecb ze}Y$%isPfk8w2pXi+Yb!A2;jyVLW~SpYku+tU=qPli8pW=;!x4wjSv$pR&(F+B z_YEXRt-{9|pf4I)HIeQ!AzOyucb@(bM=` z(PEI~p50sx_;3Nc9 z5xKbS5K0$YDtkL?YQ-f1a9u?2idnO)BD(NSXl0^lvMR{K`%0sstSMecA>VpCmWdB^ z@(>jtRYRiLFa{*W4kQjCV$D&p_HwZHqNP}SnKaZqq4a2a~w^|4;5dy4mPab+0 z@VU$0XQ*Ye@MVyO=Y)qZjsZ(tUFW#U_<&P=UIrJ=CC(>K`nsukk{Tw!D5MIx2HKYc zBoPM^@!4k+E#||T@_s1pJ1iuZQyxDx{C3t%$E@qIVmLUg7y%7+kPk8Nv2wxU0{nWd0|dEHQp6|+bed(ZJD^M+%YPXeg< z6m|}mqJlK4fJ}`HEkT=%@he;Igy!|N?h2UV^j_`sm712_GyXK<@;ive8awt1M6WUg zUttK?8A2_YhYx{qhAP?cw+z`4I>+BPh7d+j(>cJu#l0HCdkIiacX&I7&!dHl0sG-& zcVOoSC*Xn9XHL@Yp4v%)%FVsZx5?Y+bfE|TY}bM0V=;8$(mRb;uk6Bmr5gIVty( z*3rs1?|2L_`#PWd<0PV`j&%l^G`RF|{_l-Q8s7*$=lf0> zkGpU#m=7kwKH|ekY95k6Bt{`{aA0Vi1JVHSj2pOC0oIHR4z%rp`lwn0V+d)tfSZtNXQOIQR zHj`(XLTM6{ghJBRI5GJ!nW9xHNg7j1%Arc&2DBuK6Ds+~ISQ&PHt8;SYBft&kjUgWbx@~;SRvvy;0@rWbt?pvmb>Pe*9vuRaX&t0 zpsy_?GY`Z8li6Yl&o-@Aps9d^x|`BSg`mhHHY??HI$5!LwOF}-zmP;(A^coUP7^CC z=zxBl0!sHE*NI6dPYcOaCZ$lR)#3Xyby_@m+qPkM0*+oFwZGrfJm%=S6h3H2pyl(Iu2|m8IIiYIUBrX7AZE zQl{fthK+q4Onm%wVLeU=8N4)dA=~m>BSSoI--MB&!^qnlLWT|@e>5)S^S=`^_|?dr z_VW*ZRdP3`WZ-bJC78J}iSdy%zMZRZM<^b?EMkV;0463JGl1C78#6$y%Gq5-Z~1Y> zlg?IxSn*`{`mBpJyApMu4sSXUhl2uoM90$bmD{~p^3kWU-ihR^iLgxn=0E@wiTV!_ Ch@v0> literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/70.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/70.gif new file mode 100644 index 0000000000000000000000000000000000000000..416c5c14a19fbdaf8fb8d6baf5cf7e31e54f751a GIT binary patch literal 4590 zcmd5-X;c$gx6M?UNJ0o^af}oNFh>Et20R$pWXrm%( z8&nW+LYz>$WmIVtWe`-~=1@jPK0~Qn^Kr$L6Ab<)FcA5kt5XX7EVSmG&7)&_^(}c&@;&9+n zFxYDYY8+1CaLq(~oqlDTF~~xeqEO(p2e=yzmLR|p3s5-K5_&m>)rj0@Oc+i=KMu$A zGmX1#sJ$@hq9gu3m-^n%v<{E$bEBTc<6ETCfnfYiTk`t^^us{tQ4rKbCp4K7-pztO ziRoAH(0Nzf0EhCzgW6|_1N-eB2x))$P;Yzd8*u5dAUt3Y9j^Ou-_ba*OqwA zhB7o2YBMLk;8N~#Xiqq_x8vxKxWrQixZ5Jq08ILrh;GG07x36l8s)h!`IFeV2akCp zMT71La3lKYv}r(xsUQ-M<8ZI1LoJ5*OTL&U26S17ZF7Jwc;jx2!<@~_J4wfa8(xQv zp?+_u(E)eP5Z`8wyXK4q7xm3R6(J#DBN?3a1E(BY#zLUk2ebx&rWml^2wZao4fddo z2ey$nySagzv7ke;pM(XCLeOFa@{K^N_^b~KtVM$JuAtinTuK5xsUV94dc(kV7_``d zLkLikC0H5nLY& zx`M&)2H@OSa6S~I;Oo5+po4NCIvTudK8VAeF~hx#g$8G!cVV%8UJ!V)Z99?J?tC?Q-J*)huek0fb|IdWd{r< z1x80n#NmNlcQzXNWho{s91f7GrTTv#zf6@>HczgG6XbJJ6uyk7r|KARN}?}gnr9e0 zOeK*grvxuamq#s`6fIjaPbNrY_>F^oGKHC`s#LjJ3TLLyS7Zn?eHqe3WrAF&zaLp< zG2qW3>Uq8l@yH8!q^3lfE{8qcJ()5#hX;EL+&P{c9-rd|bJ-jZ7Tbfx@nCYeLbgE2 z@r3`r82W1IiAlo9fS|u?>7RTV$!fJq$YL#8w8(vthr2R;4vQlY2v}?`i_2x|BbXVB z6>4cFQ;}i+b%y|XhAcfrrA|>Q;E^4r3Caa(UxvQZFGomKg@t|FSdroW`9SV6WhyIE zs$y~6*{symk#l{H&QM3n|GSOvMrTAXR>@hB@(ksIbeUWqZvQn|kKKPRG!m%qMmRY= zMgLKx^8=K!1*vj{IwZiCp?~9^n35>u$)$X0B8SWL_7r$Cle~EXW&(#RWhN$iBzbws zJb5w?_Sb#Bm(TZ-@B{%8cAy83%i#p__*{uzIK4TZL4gvUSAgVeZipg7Emg?mUu&o6 zYk$f05BiU}LP@$@s#c~)E0y!VvLHNJsa9qrD^;*W0y|AhQ6wrCWjK#~p)Usxkf*0C zlqUwID^uam5DQbjSKd1z$%7;CV#@eQ2~0r(Ps-%Wy}g)h4oBcAkn$4vGCt$){KWq) zbS!;StP!643va$I>B%^9`)vyJ58viUuFwxpx_(NKVEEI=5AWZ-ee?R&(90LkpFMr@ z*W*VI9}M2VH*oh(|Lt3Sf8M-tz4zMHD?QzpyE;4CFI{ZAaK81AmUCy%G&eOi)YqN< z{kKymPt+bicJ#>MnnTqG5A5H!w`x!2?uznVJ9m`nw*R_q>z2~ZC7U*GDE?*rx}vpf zR*u9EEm@qoXyF2NMtYh`sYsnaZ*EHRoFsXoEI}GSd)Caj z8Pj89rcIp^9Tgc7K6z4D=)?&j!Q+Dh10?=pk>5C9pRqy#-`mTR=fUN$S?)|XR~Kie zF^&$S?HP8kt&O$SC`$`-GgA|~G0li-NFkF9hy*+i3t`YGz1G;h!w`rFfN&d;q7g?% z-~j>R`ZR3a_;)TEzV&~A+v^3aab%%aqo8Vb&zZH3s;pEuXOm{3%x zMjSk7#*4utm2rm4g;%>rQR@*L4A#Hp)bWF1MjXia7QaAYa~koKiqYOzbddt)){cf- z>J5<#XoKZw1Uy@iMQ;2J7Ud!vAlHgGPS?e)zCXVY{)?ZMUtr*DfPcLg1rb(SI+j+# z;T6zEPW~GHgE3?CHo7^*YgXh`w68T!scesJT>iE`YvuY|&$&+LOh<7iEcJZ1bNnRT zxE|=WJu0BRG)SqyEZ*U?&e}WUWKjq>xP5~}9<`=kjJFSZCY>qz5t5D{ z%d5*=kSI$VI(1BAww6X9X1)@c;Z|8dLnmJ$Y54_qv4T>Qna{KUA_((GXJCJe^ntsPv2ga{NDL6N9TTw;bv zX2Z4dXNp~uLN_oxrH$p*V=g{Z*~yU&SyObdG@>cM*aXvhq@H`W-Du3GS-acULlB7_ z(N2GFWKT8`PAtLLUR6fWd}d(>t|mx=R0wQvcS=bWt13ee!EcMZ0!h9}b7^Z6*8-752jb7~~=hcFJ^pM1L!-8t7&9o#0*vUUiq#}?rXP5Af zIx{NbQC1sm7PQi<6q>m0UTvaX`4dq&q>of;wq^9BH?VbbEL6jTyI)G$R&h^lw{v*5pKAePhX(aOskz|C)O4Zq<8L=0QCU+|G1aK$ ze4Jw>Jrf~0ILn3?xle=aESO>VP#bOT>VGiUf=ll@%9TQ&v6Pc73rcbGQsJ}-R!4mf z!_*8XorLRfRj1%rt8Z&U>_wVdb^=XXMer@Rgc}?6)Z}4`{*{_H5&xj3`_0K)lHkZD z2c#IAh1bp%iF0x%P)3I*Q}01YOA_8ahBHuT5mg=>R-#Hdx5C3GE;v?HJ=?@7IOa0D zBLK?gGOJf{)XgDvz0OAx#Yl80otKx@94yJZNOL@gdp)BVvv!kMaO|p}D5C$ot#3N& z)gSKFwnlJH4{u3^eT#A6ipRB^yYfgMmVJsz!^1=;xY_!rxApn79poOZTY3b(IAWHzOW2?VklZ_-m_OBJ=Go#*|0nktp80nw$Z< z4yj`!$|Ppp)eZNr?)#Nypsn(yN;+T6oiV4!5+{sLwuOcu+O5x?@giQ;#@|&9SiXqI0DcL#81Ifl=(Nw1{)OmBs_^m@LxA{*rrL*e; z#8HFeSMj0;-K5;5@pXYA&oV8FWh==R4yQlzI_$@UZ-0pTV1#5Ohwb$C&hd#TZdtQM zFtbGmu3T!h6a5p&=pO^g_^g=IJ1IQ9V%p+Jd*iw{2Y2)#Nk!vsEU8}C@3+jzW~tV6 ze~CBV%J}_D%{*;e>JdhBTnn+pO?EcN`g-+CT^)J!!m{bT`y~;%!~Q%;#V(hckjZ7k zmPm%xv?;NKB@;|Uxp^bBtajLg^S3SzN}Fo}BXUmu!-0x#BL2@DNb&CuH2RwZ`Fyh= zy#t;4o&!Dk)V0>+J9ED9$8*jY+8th2ha5Kd;tj5qY(;<8%!Y2)nQ3~>#7RdqGcLsV z#4`;}VUf^Z)$~GFhc@4ueG*%^v7nSLxX_wW*y~Iir7;~c+aal$bI`_TUPZCa57`ju2UTN|3Bwr{|lP7$n literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/71.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/71.gif new file mode 100644 index 0000000000000000000000000000000000000000..c17d60cbd15e80d83629b2220b562a224eec5554 GIT binary patch literal 5304 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 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/8.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/8.gif new file mode 100644 index 0000000000000000000000000000000000000000..66f967b48da173b68cbfc92986e4426ea35ade74 GIT binary patch literal 4050 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 JEmCgizW{zshWG#g literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/9.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/9.gif new file mode 100644 index 0000000000000000000000000000000000000000..60447400d31b035f56554b29af1aefc76bda1698 GIT binary patch literal 4221 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 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/layim.css b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/layim.css new file mode 100644 index 00000000..face39b4 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/layim.css @@ -0,0 +1,2 @@ +/** WebIMUI-v3.9.8 */ + html #layuicss-skinlayimcss{display:none;position:absolute;width:1989px}body .layui-layim,body .layui-layim-chat{border:1px solid #D9D9D9;border-color:rgba(0,0,0,.05);background-repeat:no-repeat;background-color:#F6F6F6;color:#333;font-family:\5FAE\8F6F\96C5\9ED1}body .layui-layim-chat{background-size:cover}body .layui-layim .layui-layer-title{height:110px;border-bottom:none;background:0 0}.layui-layim-main{position:relative;top:-98px;left:0}body .layui-layim .layui-layer-content,body .layui-layim-chat .layui-layer-content{overflow:visible}.layui-layim cite,.layui-layim em,.layui-layim-chat cite,.layui-layim-chat em{font-style:normal}.layui-layim-info{height:50px;font-size:0;padding:0 15px}.layui-layim-info *{font-size:14px}.layim-tab-content li h5 *,.layui-layim-info div,.layui-layim-skin li,.layui-layim-tab li,.layui-layim-tool li{display:inline-block;vertical-align:top;*zoom:1;*display:inline}.layim-tab-content li h5 span,.layui-layim-info .layui-layim-user,.layui-layim-list li p,.layui-layim-list li span,.layui-layim-remark{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.layui-layim-info .layui-layim-user{max-width:150px;margin-right:5px;font-size:16px}.layui-layim-status{position:relative;top:2px;line-height:19px;cursor:pointer}.layim-status-online{color:#3FDD86}.layim-status-hide{color:#DD691D}.layim-menu-box{display:none;position:absolute;z-index:100;top:24px;left:-31px;padding:5px 0;width:85px;border:1px solid #E2E2E2;border-radius:2px;background-color:#fff;box-shadow:1px 1px 20px rgba(0,0,0,.1)}.layim-menu-box li{position:relative;line-height:22px;padding-left:30px;font-size:12px}.layim-menu-box li cite{padding-right:5px;font-size:14px}.layim-menu-box li i{display:none;position:absolute;left:8px;top:0;font-weight:700;color:#5FB878}.layim-menu-box .layim-this i{display:block}.layim-menu-box li:hover{background-color:#eee}.layui-layim-remark{position:relative;left:-6px;display:block;width:100%;border:1px solid transparent;margin-top:8px;padding:0 5px;height:26px;line-height:26px;background:0 0;border-radius:2px}.layui-layim-remark:focus,.layui-layim-remark:hover{border:1px solid #d2d2d2;border-color:rgba(0,0,0,.15)}.layui-layim-remark:focus{background-color:#fff}.layui-layim-tab{margin-top:10px;padding:9px 0;font-size:0}.layui-layim-tab li{position:relative;width:33.33%;height:24px;line-height:24px;font-size:22px;text-align:center;color:#666;color:rgba(0,0,0,.6);cursor:pointer}.layim-tab-two li{width:50%}.layui-layim-tab li.layim-this:after{content:'';position:absolute;left:0;bottom:-9px;width:100%;height:3px;background-color:#3FDD86}.layui-layim-tab li.layim-hide{display:none}.layui-layim-tab li:hover{opacity:.8;filter:Alpha(opacity=80)}.layim-tab-content{display:none;padding:10px 0;height:349px;overflow:hidden;background-color:#fff;background-color:rgba(255,255,255,.9)}.layim-tab-content:hover{overflow-y:auto}.layim-tab-content li h5{position:relative;margin-right:15px;padding-left:30px;height:28px;line-height:28px;cursor:pointer;font-size:0;white-space:nowrap;overflow:hidden}.layim-tab-content li h5 *{font-size:14px}.layim-tab-content li h5 span{max-width:125px}.layim-tab-content li h5 i{position:absolute;left:12px;top:0;color:#C9BDBB}.layim-tab-content li h5 em{padding-left:5px;color:#999}.layim-tab-content li h5[lay-type=true] i{top:2px}.layim-tab-content li ul{display:none;margin-bottom:10px}.layui-layim-list li{position:relative;height:42px;padding:5px 15px 5px 60px;font-size:0;cursor:pointer}.layui-layim-list li:hover{background-color:#F2F2F2;background-color:rgba(0,0,0,.05)}.layui-layim-list li.layim-null{height:20px;line-height:20px;padding:0;font-size:14px;color:#999;text-align:center;cursor:default}.layui-layim-list li.layim-null:hover{background:0 0}.layui-layim-list li *{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:14px}.layui-layim-list li span{margin-top:4px;max-width:155px}.layui-layim-list li img{position:absolute;left:15px;top:8px;width:36px;height:36px;border-radius:100%}.layui-layim-list li p{display:block;padding-right:30px;line-height:18px;font-size:12px;color:#999}.layui-layim-list li .layim-msg-status{display:none;position:absolute;right:10px;bottom:7px;padding:0 5px;height:16px;line-height:16px;border-radius:16px;text-align:center;font-size:10px;background-color:#F74C31;color:#fff}.layim-list-gray{-webkit-filter:grayscale(100%);-ms-filter:grayscale(100%);filter:grayscale(100%);filter:gray}.layui-layim-tool{padding:0 10px;font-size:0;background-color:#F6F6F6;border-radius:0 0 2px 2px}.layui-layim-tool li{position:relative;width:48px;height:37px;line-height:40px;text-align:center;font-size:22px;cursor:pointer}.layui-layim-tool li:active{background-color:#e2e2e2}.layui-layim-tool .layim-tool-msgbox{line-height:37px}.layui-layim-tool .layim-tool-find{line-height:38px}.layui-layim-tool .layim-tool-skin{font-size:26px}.layim-tool-msgbox span{display:none;position:absolute;left:12px;top:-12px;height:20px;line-height:20px;padding:0 10px;border-radius:2px;background-color:#33DF83;color:#fff;font-size:12px;-webkit-animation-duration:1s;animation-duration:1s}.layim-tool-msgbox .layer-anim-05{display:block}.layui-layim-search{display:none;position:absolute;bottom:5px;left:5px;height:28px;line-height:28px}.layui-layim-search input{width:210px;padding:0 30px 0 10px;height:30px;line-height:30px;border:none;border-radius:3px;background-color:#ddd}.layui-layim-search label{position:absolute;right:6px;top:4px;font-size:20px;cursor:pointer;color:#333;font-weight:400}.layui-layim-skin{margin:10px 0 0 10px;font-size:0}.layui-layim-skin li{margin:0 10px 10px 0;line-height:60px;text-align:center;background-color:#f6f6f6}.layui-layim-skin li,.layui-layim-skin li img{width:86px;height:60px;cursor:pointer}.layui-layim-skin li img:hover{opacity:.8;filter:Alpha(opacity=80)}.layui-layim-skin li cite{font-size:14px;font-style:normal}body .layui-layim-chat{background-color:#fff}body .layui-layim-chat-list{width:760px}body .layui-layim-chat .layui-layer-title{height:80px;border-bottom:none;background-color:#F8F8F8;background-color:rgba(245,245,245,.7)}body .layui-layim-chat .layui-layer-content{background:0 0}.layim-chat-list li *,.layui-layim-min .layui-layer-content *{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:14px}.layim-chat-list{display:none;position:absolute;z-index:1000;top:-80px;width:200px;height:100%;background-color:#D9D9D9;overflow:hidden;font-size:0}.layim-chat-list:hover{overflow-y:auto}.layim-chat-list li,.layui-layim-min .layui-layer-content{position:relative;margin:5px;padding:5px 30px 5px 5px;line-height:40px;cursor:pointer;border-radius:3px}.layim-chat-list li img,.layui-layim-min .layui-layer-content img{width:40px;height:40px;border-radius:100%}.layui-layim-photos{cursor:crosshair}.layim-chat-list li{white-space:nowrap}.layim-chat-list li span,.layui-layim-min .layui-layer-content span{width:100px;padding-left:10px;font-size:16px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.layim-chat-list li span cite{color:#999;padding-left:10px}.layim-chat-list li:hover{background-color:#E2E2E2}.layim-chat-list li.layim-this{background-color:#F3F3F3}.layim-chat-list li .layui-icon{display:none;position:absolute;right:5px;top:7px;color:#555;font-size:22px}.layim-chat-list li .layui-icon:hover{color:#c00}.layim-chat-list li:hover .layui-icon{display:inline-block}.layim-chat-system{margin:10px 0;text-align:center}.layim-chat-system span{display:inline-block;line-height:30px;padding:0 15px;border-radius:3px;background-color:#e2e2e2;cursor:default;font-size:14px}.layim-chat{display:none;position:relative;background-color:#fff;background-color:rgba(255,255,255,.9)}.layim-chat-title{position:absolute;top:-80px;height:80px}.layim-chat-other{position:relative;top:15px;left:15px;padding-left:60px;cursor:default}.layim-chat-other img{position:absolute;left:0;top:0;width:50px;height:50px;border-radius:100%}.layim-chat-username{position:relative;top:5px;font-size:18px}.layim-chat-status{margin-top:6px;font-size:14px;color:#999}.layim-chat-group .layim-chat-other .layim-chat-username{cursor:pointer}.layim-chat-group .layim-chat-other .layim-chat-username em{padding:0 10px;color:#999}.layim-chat-main{height:262px;padding:15px 15px 5px;overflow-x:hidden;overflow-y:auto}.layim-chat-main ul li{position:relative;font-size:0;margin-bottom:10px;padding-left:60px;min-height:68px}.layim-chat-text,.layim-chat-user{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:14px}.layim-chat-user{position:absolute;left:3px}.layim-chat-user img{width:40px;height:40px;border-radius:100%}.layim-chat-user cite{position:absolute;left:60px;top:-2px;width:500px;line-height:24px;font-size:12px;white-space:nowrap;color:#999;text-align:left;font-style:normal}.layim-chat-user cite i{padding-left:15px;font-style:normal}.layim-chat-text{position:relative;line-height:22px;margin-top:25px;padding:8px 15px;background-color:#e2e2e2;border-radius:3px;color:#333;word-break:break-all;max-width:462px\9}.layim-chat-text:after{content:'';position:absolute;left:-10px;top:13px;width:0;height:0;border-style:solid dashed dashed;border-color:#e2e2e2 transparent transparent;overflow:hidden;border-width:10px}.layim-chat-text a{color:#33DF83}.layim-chat-text img{max-width:100%;vertical-align:middle}.layim-chat-text .layui-layim-file,.layui-layim-file{display:block;text-align:center}.layim-chat-text .layui-layim-file{color:#333}.layui-layim-file:hover{opacity:.9}.layui-layim-file i{font-size:80px;line-height:80px}.layui-layim-file cite{display:block;line-height:20px;font-size:14px}.layui-layim-audio{text-align:center;cursor:pointer}.layui-layim-audio .layui-icon{position:relative;top:5px;font-size:24px}.layui-layim-audio p{margin-top:3px}.layui-layim-video{width:120px;height:80px;line-height:80px;background-color:#333;text-align:center;border-radius:3px}.layui-layim-video .layui-icon{font-size:36px;cursor:pointer;color:#fff}.layim-chat-main ul .layim-chat-system{min-height:0;padding:0}.layim-chat-main ul .layim-chat-mine{text-align:right;padding-left:0;padding-right:60px}.layim-chat-mine .layim-chat-user{left:auto;right:3px}.layim-chat-mine .layim-chat-user cite{left:auto;right:60px;text-align:right}.layim-chat-mine .layim-chat-user cite i{padding-left:0;padding-right:15px}.layim-chat-mine .layim-chat-text{margin-left:0;text-align:left;background-color:#5FB878;color:#fff}.layim-chat-mine .layim-chat-text:after{left:auto;right:-10px;border-top-color:#5FB878}.layim-chat-mine .layim-chat-text a{color:#fff}.layim-chat-footer{border-top:1px solid #F1F1F1}.layim-chat-tool{position:relative;padding:0 8px;height:38px;line-height:38px;font-size:0}.layim-chat-tool span{position:relative;margin:0 10px;display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:24px;cursor:pointer}.layim-chat-tool .layim-tool-log{position:absolute;right:5px;font-size:14px}.layim-tool-log i{position:relative;top:2px;margin-right:5px;font-size:20px;color:#999}.layim-tool-image input{position:absolute;font-size:0;left:0;top:0;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}body .layui-layim-face{margin:10px 0 0 -18px;border:none;background:0 0}body .layui-layim-face .layui-layer-content{padding:0;background-color:#fff;color:#666;box-shadow:none}.layui-layim-face .layui-layer-TipsG{display:none}.layui-layim-face ul{position:relative;width:372px;padding:10px;border:1px solid #D9D9D9;background-color:#fff;box-shadow:0 0 20px rgba(0,0,0,.2)}.layui-layim-face ul li{cursor:pointer;float:left;border:1px solid #e8e8e8;height:22px;width:26px;overflow:hidden;margin:-1px 0 0 -1px;padding:4px 2px;text-align:center}.layui-layim-face ul li:hover{position:relative;z-index:2;border:1px solid #eb7350;background:#fff9ec}.layim-chat-textarea{margin-left:10px}.layim-chat-textarea textarea{display:block;width:100%;padding:5px 0 0;height:68px;line-height:20px;border:none;overflow:auto;resize:none;background:0 0}.layim-chat-textarea textarea:focus{outline:0}.layim-chat-bottom{position:relative;height:46px}.layim-chat-send{position:absolute;right:15px;top:3px;height:32px;line-height:32px;font-size:0;cursor:pointer}.layim-chat-send span{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:14px;line-height:32px;margin-left:5px;padding:0 20px;background-color:#5FB878;color:#fff;border-radius:3px}.layim-chat-send span:hover{background-color:#69BC80}.layim-chat-send span:active{background-color:#59B573}.layim-chat-send .layim-send-btn{border-radius:3px 0 0 3px}.layim-chat-send .layim-send-set{position:relative;width:30px;height:32px;margin-left:0;padding:0;border-left:1px solid #85C998;border-radius:0 3px 3px 0}.layim-send-set .layui-edge{position:absolute;top:14px;left:9px;border-width:6px;border-top-style:solid;border-top-color:#fff}.layim-chat-send .layim-menu-box{left:auto;right:0;top:33px;width:180px;padding:10px 0}.layim-chat-send .layim-menu-box li{padding-right:15px;line-height:28px}body .layui-layim-min{border:1px solid #D9D9D9}.layui-layim-min .layui-layer-content{margin:0 5px;padding:5px 10px;white-space:nowrap}.layui-layim-close .layui-layer-content span{width:auto;max-width:120px}body .layui-layim-members{margin:25px 0 0 -75px;border:none;background:0 0}body .layui-layim-members .layui-layer-content{padding:0;background:0 0;color:#666;box-shadow:none}.layui-layim-members .layui-layer-TipsG{display:none}.layui-layim-members ul{position:relative;width:578px;height:200px;padding:10px 10px 0;border:1px solid #D9D9D9;background-color:#fff;background-color:rgba(255,255,255,.9);box-shadow:none;overflow:hidden;font-size:0}.layui-layim-members ul:hover{overflow:auto}.layim-add-img,.layim-add-remark,.layui-layim-members li{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:14px}.layui-layim-members li{width:112px;margin:10px 0;text-align:center}.layui-layim-members li a{position:relative;display:inline-block;max-width:100%}.layui-layim-members li a:after{content:'';position:absolute;width:46px;height:46px;left:50%;margin-left:-23px;top:0;border:1px solid #eee;border-color:rgba(0,0,0,.1);border-radius:100%}.layui-layim-members li img{width:48px;height:48px;border-radius:100%}.layui-layim-members li:hover{opacity:.9}.layui-layim-members li a cite{display:block;padding:0 3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}body .layui-layim-contextmenu{margin:70px 0 0 30px;width:200px;padding:5px 0;border:1px solid #ccc;background:#fff;border-radius:0;box-shadow:0 0 5px rgba(0,0,0,.2)}body .layui-layim-contextmenu .layui-layer-content{padding:0;background-color:#fff;color:#333;font-size:14px;box-shadow:none}.layui-layim-contextmenu .layui-layer-TipsG{display:none}.layui-layim-contextmenu li{padding:0 15px 0 35px;cursor:pointer;line-height:30px}.layui-layim-contextmenu li:hover{background-color:#F2F2F2}.layim-add-box{margin:15px;font-size:0}.layim-add-img img,.layim-add-remark p{margin-bottom:10px}.layim-add-img{width:100px;margin-right:20px;text-align:center}.layim-add-img img{width:100px;height:100px}.layim-add-remark{width:280px}.layim-add-remark .layui-select{width:100%;margin-bottom:10px}.layim-add-remark .layui-textarea{height:80px;min-height:80px;resize:none}.layim-tab-content,.layui-layim-face ul,.layui-layim-tab{margin-bottom:0}.layim-tab-content li h5{margin-top:0;margin-bottom:0},.layui-layim-face img{vertical-align:bottom}.layim-chat-other span{color:#444}.layim-chat-other span cite{padding:0 15px;color:#999}.layim-chat-other:hover{text-decoration:none} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/layer-mobile.js b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/layer-mobile.js new file mode 100644 index 00000000..0eb5d52b --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/layer-mobile.js @@ -0,0 +1,2 @@ +/** WebIMUI-v3.9.8 */ + ;layui.define(function(e){"use strict";var t=(window,document),i="querySelectorAll",n="getElementsByClassName",a=function(e){return t[i](e)},s={type:0,shade:!0,shadeClose:!0,fixed:!0,anim:"scale"},l={extend:function(e){var t=JSON.parse(JSON.stringify(s));for(var i in e)t[i]=e[i];return t},timer:{},end:{}};l.touch=function(e,t){e.addEventListener("click",function(e){t.call(this,e)},!1)};var o=0,r=["layui-m-layer"],d=function(e){var t=this;t.config=l.extend(e),t.view()};d.prototype.view=function(){var e=this,i=e.config,s=t.createElement("div");e.id=s.id=r[0]+o,s.setAttribute("class",r[0]+" "+r[0]+(i.type||0)),s.setAttribute("index",o);var l=function(){var e="object"==typeof i.title;return i.title?'

      '+(e?i.title[0]:i.title)+"

      ":""}(),d=function(){"string"==typeof i.btn&&(i.btn=[i.btn]);var e,t=(i.btn||[]).length;return 0!==t&&i.btn?(e=''+i.btn[0]+"",2===t&&(e=''+i.btn[1]+""+e),'
      '+e+"
      "):""}();if(i.fixed||(i.top=i.hasOwnProperty("top")?i.top:100,i.style=i.style||"",i.style+=" top:"+(t.body.scrollTop+i.top)+"px"),2===i.type&&(i.content='

      '+(i.content||"")+"

      "),i.skin&&(i.anim="up"),"msg"===i.skin&&(i.shade=!1),s.innerHTML=(i.shade?"
      ':"")+'
      "+l+'
      '+i.content+"
      "+d+"
      ",!i.type||2===i.type){var y=t[n](r[0]+i.type),u=y.length;u>=1&&c.close(y[0].getAttribute("index"))}document.body.appendChild(s);var m=e.elem=a("#"+e.id)[0];i.success&&i.success(m),e.index=o++,e.action(i,m)},d.prototype.action=function(e,t){var i=this;e.time&&(l.timer[i.index]=setTimeout(function(){c.close(i.index)},1e3*e.time));var a=function(){var t=this.getAttribute("type");0==t?(e.no&&e.no(),c.close(i.index)):e.yes?e.yes(i.index):c.close(i.index)};if(e.btn)for(var s=t[n]("layui-m-layerbtn")[0].children,o=s.length,r=0;r
      {{ data.username||data.groupname||data.name||"\u4f5a\u540d" }}

      {{ data.remark||data.sign||"" }}

      new
    • ',"{{# }); if(length === 0){ }}",'
    • '+(i[a.type]||"\u6682\u65e0\u6570\u636e")+"
    • ","{{# } }}"].join("")},p=function(a,i,e){return['
      ','
      ',"

      ",e?'':"",'{{ d.title || d.base.title }}',"{{# if(d.data){ }}",'{{# if(d.data.type === "group"){ }}','',"{{# } }}","{{# } }}","

      ","
      ",'
      ',a,"
      ","
      "].join("")},f=['
      ','
      ','
        ','
          ',y({type:"history"}),"
        ","
      ","
      ",'
      ','
        ',"{{# if(d.base.isNewFriend){ }}",'
      • \u65b0\u7684\u670b\u53cb
      • ',"{{# } if(d.base.isgroup){ }}",'
      • \u7fa4\u804a
      • ',"{{# } }}","
      ",'
        ','{{# layui.each(d.friend, function(index, item){ var spread = d.local["spread"+index]; }}',"
      • ",'
        {{# if(spread === "true"){ }}{{# } else { }}{{# } }}{{ item.groupname||"\u672a\u547d\u540d\u5206\u7ec4"+index }}( {{ (item.list||[]).length }})
        ','
          ',y({type:"friend",item:"item.list",index:"index"}),"
        ","
      • ","{{# }); if(d.friend.length === 0){ }}",'
        • \u6682\u65e0\u8054\u7cfb\u4eba
        ',"{{# } }}","
      ","
      ",'
      ','
        ',"{{# layui.each(d.base.moreList, function(index, item){ }}",'
      • ','{{item.iconUnicode||""}}{{item.title}}',"
      • ","{{# }); if(!d.base.copyright){ }}",'
      • \u5173\u4e8e
      • ',"{{# } }}","
      ","
      ","
      ",'
        ','
      • \u6d88\u606f
      • ','
      • \u8054\u7cfb\u4eba
      • ','
      • \u66f4\u591a
      • ',"
      "].join(""),h=['
      ','
      ',"
        ","
        ",'","
        "].join(""),v=function(a){return a<10?"0"+(0|a):a};layui.data.date=function(a){var i=new Date(a||new Date);return v(i.getMonth()+1)+"-"+v(i.getDate())+" "+v(i.getHours())+":"+v(i.getMinutes())},layui.data.content=function(a){var i=function(a){return new RegExp("\\n*\\["+(a||"")+"(pre|div|p|table|thead|th|tbody|tr|td|ul|li|ol|li|dl|dt|dd|h2|h3|h4|h5)([\\s\\S]*?)\\]\\n*","g")};return a=(a||"").replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,""").replace(/@(\S+)(\s+?|$)/g,'@
        $1$2').replace(/face\[([^\s\[\]]+?)\]/g,function(a){var i=a.replace(/^face/g,"");return''+i+''}).replace(/img\[([^\s]+?)\]/g,function(a){return''}).replace(/file\([\s\S]+?\)\[[\s\S]*?\]/g,function(a){var i=(a.match(/file\(([\s\S]+?)\)\[/)||[])[1],e=(a.match(/\)\[([\s\S]*?)\]/)||[])[1];return i?''+(e||i)+"":a}).replace(/audio\[([^\s]+?)\]/g,function(a){return'

        \u97f3\u9891\u6d88\u606f

        '}).replace(/video\[([^\s]+?)\]/g,function(a){return'
        '}).replace(/a\([\s\S]+?\)\[[\s\S]*?\]/g,function(a){var i=(a.match(/a\(([\s\S]+?)\)\[/)||[])[1],e=(a.match(/\)\[([\s\S]*?)\]/)||[])[1];return i?''+(e||i)+"":a}).replace(i(),"<$1 $2>").replace(i("/"),"").replace(/\n/g,"
        ")};var g,b,x=['
      • ','
        {{ d.uid || d.id }}','{{ d.username||"\u4f5a\u540d" }}',"
        ",'
        {{ layui.data.content(d.content||" ") }}
        ',"
      • "].join(""),w={message:{},chat:[]},C=function(a){var i=a.init||{};return mine=i.mine||{},local=layui.data("layim-mobile")[mine.id]||{},obj={base:a,local:local,mine:mine,history:local.history||[]},create=function(i){var n=i.mine||{},l=layui.data("layim-mobile")[n.id]||{},s={base:a,local:l,mine:n,friend:i.friend||[],group:i.group||[],history:l.history||[]};s.sortHistory=T(s.history,"historyTime"),w=e.extend(w,s),k(t(p(f)).render(s)),layui.each(d.ready,function(a,i){i&&i(s)})},w=e.extend(w,obj),a.brief?layui.each(d.ready,function(a,i){i&&i(obj)}):void create(i)},k=function(a){return n.open({type:1,shade:!1,shadeClose:!1,anim:-1,content:a,success:function(a){g=e(a),N(g.find(".layui-layim")),w.base.tabIndex&&R.tab(e(".layui-layim-tab>li").eq(w.base.tabIndex))}})},A=function(a,i){a=a||{};var l=e.extend({},w,{title:a.title||"",data:a.data});return n.open({type:1,shade:!1,shadeClose:!1,anim:-1,content:t(p(a.tpl,i!==-1,!0)).render(l),success:function(i){var t=e(i);t.prev().find(".layim-panel").addClass("layui-m-anim-lout"),a.success&&a.success(i),a.isChat||N(t.find(".layim-content"))},end:a.end})},S=function(a,i,t){return a=a||{},a.id?(n.close(S.index),S.index=A({tpl:h,data:a,title:a.name,isChat:!0,success:function(i){b=e(i),Y(),F(),delete w.message[a.type+a.id],P("Msg");var t=L(),n=t.elem.find(".layim-chat-main");layui.each(d.chatChange,function(a,i){i&&i(t)}),N(n),t.textarea.on("focus",function(){setTimeout(function(){n.scrollTop(n[0].scrollHeight+1e3)},500)})},end:function(){b=null,H.time=0}},i)):n.msg("\u975e\u6cd5\u7528\u6237")},N=function(a){l.ios&&a.on("touchmove",function(i){var e=a.scrollTop();e<=0&&(a.scrollTop(1),i.preventDefault(i)),this.scrollHeight-e-a.height()<=0&&(a.scrollTop(a.scrollTop()-1),i.preventDefault(i))})},L=function(){if(!b)return{};var a=b.find(".layim-chat"),i=JSON.parse(decodeURIComponent(a.find(".layim-chat-tool").data("json")));return{elem:a,data:i,textarea:a.find("input")}},T=function(a,i,e){var t=[],n=function(a,e){var t=a[i],n=e[i];return nt?1:0};return layui.each(a,function(a,i){t.push(i)}),t.sort(n),e&&t.reverse(),t},j=function(a){var i=layui.data("layim-mobile")[w.mine.id]||{},e={},n=i.history||{};n[a.type+a.id];if(g){var l=g.find(".layim-list-history");a.historyTime=(new Date).getTime(),a.sign=a.content,n[a.type+a.id]=a,i.history=n,layui.data("layim-mobile",{key:w.mine.id,value:i});var o=l.find(".layim-"+a.type+a.id),c=(w.message[a.type+a.id]||[]).length,d=function(){o=l.find(".layim-"+a.type+a.id),o.find("p").html(a.content),c>0&&o.find(".layim-msg-status").html(c).addClass(s)};if(o.length>0)d(),l.prepend(o.clone()),o.remove();else{e[a.type+a.id]=a;var r=t(y({type:"history",item:"d.data"})).render({data:e});l.prepend(r),d(),l.find(".layim-null").remove()}P("Msg")}},P=function(a,i){if(!i){var i;layui.each(w.message,function(){return i=!0,!1})}e("#LAY_layimNew"+a)[i?"addClass":"removeClass"](s)},H=function(){var a={username:w.mine?w.mine.username:"\u8bbf\u5ba2",avatar:w.mine?w.mine.avatar:layui.cache.layimAssetsPath+"images/default.png",id:w.mine?w.mine.id:null,mine:!0},i=L(),e=i.elem.find(".layim-chat-main ul"),l=i.data,s=w.base.maxLength||3e3,o=(new Date).getTime(),c=i.textarea;if(a.content=c.val(),""!==a.content){if(a.content.length>s)return n.msg("\u5185\u5bb9\u6700\u957f\u4e0d\u80fd\u8d85\u8fc7"+s+"\u4e2a\u5b57\u7b26");o-(H.time||0)>6e4&&(e.append('
      • '+layui.data.date()+"
      • "),H.time=o),e.append(t(x).render(a));var r={mine:a,to:l},u={username:r.mine.username,avatar:r.mine.avatar||layui.cache.layimAssetsPath+"images/default.png",id:l.id,type:l.type,content:r.mine.content,timestamp:o,mine:!0};_(u),layui.each(d.sendMessage,function(a,i){i&&i(r)}),l.content=a.content,j(l),O(),c.val(""),c.next().addClass("layui-disabled")}},q=function(){var a=document.createElement("audio");a.src=layui.cache.layimAssetsPath+"voice/"+w.base.voice,a.play()},I={},D=function(a){a=a||{};var i={},n=L(),l=n.data||{},s=l.id==a.id&&l.type==a.type;a.timestamp=a.timestamp||(new Date).getTime(),a.system||_(a),console.log(a),I=JSON.parse(JSON.stringify(a)),w.base.voice&&q(),(!b&&a.content||!s)&&(w.message[a.type+a.id]?w.message[a.type+a.id].push(a):w.message[a.type+a.id]=[a]);var i={};if("friend"===a.type){var o;layui.each(w.friend,function(i,e){if(layui.each(e.list,function(i,e){if(e.id==a.id)return a.type="friend",a.name=e.username,o=!0}),o)return!0}),o||(a.temporary=!0)}else"group"===a.type?layui.each(w.group,function(e,t){if(t.id==a.id)return a.type="group",a.name=a.groupname=t.groupname,i.avatar=t.avatar||layui.cache.layimAssetsPath+"images/default.png",!0}):a.name=a.name||a.username||a.groupname;var c=e.extend({},a,{avatar:i.avatar||a.avatar||layui.cache.layimAssetsPath+"images/default.png"});if("group"===a.type&&delete c.username,j(c),b&&s){var d=b.find(".layim-chat"),r=d.find(".layim-chat-main ul");a.system?r.append('
      • '+a.content+"
      • "):""!==a.content.replace(/\s/g,"")&&(a.timestamp-(H.time||0)>6e4&&(r.append('
      • '+layui.data.date(a.timestamp)+"
      • "),H.time=a.timestamp),r.append(t(x).render(a))),O()}},_=function(a){var i=layui.data("layim-mobile")[w.mine.id]||{},e=i.chatlog||{};e[a.type+a.id]?(e[a.type+a.id].push(a),e[a.type+a.id].length>c&&e[a.type+a.id].shift()):e[a.type+a.id]=[a],i.chatlog=e,layui.data("layim-mobile",{key:w.mine.id,value:i})},F=function(){var a=layui.data("layim-mobile")[w.mine.id]||{},i=L(),e=a.chatlog||{},n=i.elem.find(".layim-chat-main ul");layui.each(e[i.data.type+i.data.id],function(a,i){(new Date).getTime()>i.timestamp&&i.timestamp-(H.time||0)>6e4&&(n.append('
      • '+layui.data.date(i.timestamp)+"
      • "),H.time=i.timestamp),n.append(t(x).render(i))}),O()},M=function(a){var i,e={},l=g.find(".layim-list-"+a.type);if(w[a.type])if("friend"===a.type)layui.each(w.friend,function(t,l){if(a.groupid==l.id)return layui.each(w.friend[t].list,function(e,t){if(t.id==a.id)return i=!0}),i?n.msg("\u597d\u53cb ["+(a.username||"")+"] \u5df2\u7ecf\u5b58\u5728\u5217\u8868\u4e2d",{anim:6}):(w.friend[t].list=w.friend[t].list||[],e[w.friend[t].list.length]=a,a.groupIndex=t,w.friend[t].list.push(a),!0)});else if("group"===a.type){if(layui.each(w.group,function(e,t){if(t.id==a.id)return i=!0}),i)return n.msg("\u60a8\u5df2\u662f ["+(a.groupname||"")+"] \u7684\u7fa4\u6210\u5458",{anim:6});e[w.group.length]=a,w.group.push(a)}if(!i){var s=t(y({type:a.type,item:"d.data",index:"friend"===a.type?"data.groupIndex":null})).render({data:e});if("friend"===a.type){var o=l.children("li").eq(a.groupIndex);o.find(".layui-layim-list").append(s),o.find(".layim-count").html(w.friend[a.groupIndex].list.length),o.find(".layim-null")[0]&&o.find(".layim-null").remove()}else"group"===a.type&&(l.append(s),l.find(".layim-null")[0]&&l.find(".layim-null").remove())}},$=function(a){var i=g.find(".layim-list-"+a.type);w[a.type]&&("friend"===a.type?layui.each(w.friend,function(e,t){layui.each(t.list,function(t,n){if(a.id==n.id){var l=i.children("li").eq(e);l.find(".layui-layim-list").children("li");return l.find(".layui-layim-list").children("li").eq(t).remove(),w.friend[e].list.splice(t,1),l.find(".layim-count").html(w.friend[e].list.length),0===w.friend[e].list.length&&l.find(".layui-layim-list").html('
      • \u8be5\u5206\u7ec4\u4e0b\u5df2\u65e0\u597d\u53cb\u4e86
      • '),!0}})}):"group"===a.type&&layui.each(w.group,function(e,t){if(a.id==t.id)return i.children("li").eq(e).remove(),w.group.splice(e,1),0===w.group.length&&i.html('
      • \u6682\u65e0\u7fa4\u7ec4
      • '),!0}))},O=function(){var a=L(),i=a.elem.find(".layim-chat-main"),e=i.find("ul"),t=e.children(".layim-chat-li");if(t.length>=c){var n=t.eq(0);n.prev().remove(),e.prev().hasClass("layim-chat-system")||e.before('
        \u67e5\u770b\u66f4\u591a\u8bb0\u5f55
        '),n.remove()}i.scrollTop(i[0].scrollHeight+1e3)},Y=function(){var a=L(),i=a.textarea,e=i.next();i.off("keyup").on("keyup",function(a){var t=a.keyCode;13===t&&(a.preventDefault(),H()),e[""===i.val()?"addClass":"removeClass"]("layui-disabled")})},J=function(){var a=["[\u5fae\u7b11]","[\u563b\u563b]","[\u54c8\u54c8]","[\u53ef\u7231]","[\u53ef\u601c]","[\u6316\u9f3b]","[\u5403\u60ca]","[\u5bb3\u7f9e]","[\u6324\u773c]","[\u95ed\u5634]","[\u9119\u89c6]","[\u7231\u4f60]","[\u6cea]","[\u5077\u7b11]","[\u4eb2\u4eb2]","[\u751f\u75c5]","[\u592a\u5f00\u5fc3]","[\u767d\u773c]","[\u53f3\u54fc\u54fc]","[\u5de6\u54fc\u54fc]","[\u5618]","[\u8870]","[\u59d4\u5c48]","[\u5410]","[\u54c8\u6b20]","[\u62b1\u62b1]","[\u6012]","[\u7591\u95ee]","[\u998b\u5634]","[\u62dc\u62dc]","[\u601d\u8003]","[\u6c57]","[\u56f0]","[\u7761]","[\u94b1]","[\u5931\u671b]","[\u9177]","[\u8272]","[\u54fc]","[\u9f13\u638c]","[\u6655]","[\u60b2\u4f24]","[\u6293\u72c2]","[\u9ed1\u7ebf]","[\u9634\u9669]","[\u6012\u9a82]","[\u4e92\u7c89]","[\u5fc3]","[\u4f24\u5fc3]","[\u732a\u5934]","[\u718a\u732b]","[\u5154\u5b50]","[ok]","[\u8036]","[good]","[NO]","[\u8d5e]","[\u6765]","[\u5f31]","[\u8349\u6ce5\u9a6c]","[\u795e\u9a6c]","[\u56e7]","[\u6d6e\u4e91]","[\u7ed9\u529b]","[\u56f4\u89c2]","[\u5a01\u6b66]","[\u5965\u7279\u66fc]","[\u793c\u7269]","[\u949f]","[\u8bdd\u7b52]","[\u8721\u70db]","[\u86cb\u7cd5]"],i={};return layui.each(a,function(a,e){i[e]=layui.cache.layimAssetsPath+"images/face/"+a+".gif"}),i}(),B=layui.stope,E=function(a,i,e){var t,n=a.value;e||a.focus(),document.selection?(t=document.selection.createRange(),document.selection.empty(),t.text=i):(t=[n.substring(0,a.selectionStart),i,n.substr(a.selectionEnd)],e||a.focus(),a.value=t.join(""))},R={chat:function(a){var i=layui.data("layim-mobile")[w.mine.id]||{},t=a.data("type"),n=a.data("index"),l=a.attr("data-list")||a.index(),o={};"friend"===t?o=w[t][n].list[l]:"group"===t?o=w[t][l]:"history"===t&&(o=(i.history||{})[n]||{}),o.name=o.name||o.username||o.groupname,"history"!==t&&(o.type=t),S(o,!0),e(".layim-"+o.type+o.id).find(".layim-msg-status").removeClass(s)},spread:function(a){var i=a.attr("lay-type"),e="true"===i?"false":"true",t=layui.data("layim-mobile")[w.mine.id]||{};a.next()["true"===i?"removeClass":"addClass"](s),t["spread"+a.parent().index()]=e,layui.data("layim-mobile",{key:w.mine.id,value:t}),a.attr("lay-type",e),a.find(".layui-icon").html("true"===e?"":"")},tab:function(a){var i=a.index(),e=".layim-tab-content";a.addClass(o).siblings().removeClass(o),g.find(e).eq(i).addClass(s).siblings(e).removeClass(s)},back:function(a){var i=a.parents(".layui-m-layer").eq(0),e=i.attr("index"),t=".layim-panel";setTimeout(function(){n.close(e)},300),a.parents(t).eq(0).removeClass("layui-m-anim-left").addClass("layui-m-anim-rout"),i.prev().find(t).eq(0).removeClass("layui-m-anim-lout").addClass("layui-m-anim-right"),layui.each(d.back,function(a,i){setTimeout(function(){i&&i()},200)})},send:function(){H()},face:function(a,i){var t="",l=L(),s=l.textarea;layui.each(J,function(a,i){t+='
      • '}),t='
          '+t+"
        ",n.popBottom({content:t,success:function(a){var i=e(a).find(".layui-layim-face").children("li");u(i,function(){return E(s[0],"face"+this.title+" ",!0),s.next()[""===s.val()?"addClass":"removeClass"]("layui-disabled"),!1})}});var o=e(document);m?u(o,function(){R.faceHide()}):o.off("click",R.faceHide).on("click",R.faceHide),B(i)},faceHide:function(){n.close(n.popBottom.index),e(document).off("touchend",R.faceHide).off("click",R.faceHide)},image:function(a){var i=a.data("type")||"images",e={images:"uploadImage",file:"uploadFile"},t=L(),l=w.base[e[i]]||{};layui.upload.render({url:l.url||"",method:l.type,elem:a.find("input")[0],accept:i,done:function(a){0==a.code?(a.data=a.data||{},"images"===i?E(t.textarea[0],"img["+(a.data.src||"")+"]"):"file"===i&&E(t.textarea[0],"file("+(a.data.src||"")+")["+(a.data.name||"\u4e0b\u8f7d\u6587\u4ef6")+"]"),H()):n.msg(a.msg||"\u4e0a\u4f20\u5931\u8d25")}})},extend:function(a){var i=a.attr("lay-filter"),e=L();layui.each(d["tool("+i+")"],function(i,t){t&&t.call(a,function(a){E(e.textarea[0],a)},H,e)})},newFriend:function(){layui.each(d.newFriend,function(a,i){i&&i()})},group:function(){A({title:"\u7fa4\u804a",tpl:['
        ',y({type:"group",item:"d.group"}),"
        "].join(""),data:{}})},detail:function(){var a=L();layui.each(d.detail,function(i,e){e&&e(a.data)})},playAudio:function(a){var i=a.data("audio"),e=i||document.createElement("audio"),t=function(){e.pause(),a.removeAttr("status"),a.find("i").html("")};return a.data("error")?n.msg("\u64ad\u653e\u97f3\u9891\u6e90\u5f02\u5e38"):e.play?void(a.attr("status")?t():(i||(e.src=a.data("src")),e.play(),a.attr("status","pause"),a.data("audio",e),a.find("i").html(""),e.onended=function(){t()},e.onerror=function(){n.msg("\u64ad\u653e\u97f3\u9891\u6e90\u5f02\u5e38"),a.data("error",!0),t()})):n.msg("\u60a8\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301audio")},playVideo:function(a){var i=a.data("src"),e=document.createElement("video");return e.play?(n.close(R.playVideo.index),void(R.playVideo.index=n.open({type:1,anim:!1,style:"width: 100%; height: 50%;",content:'
        '}))):n.msg("\u60a8\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301video")},chatLog:function(a){var i=L();layui.each(d.chatlog,function(a,e){e&&e(i.data,i.elem.find(".layim-chat-main>ul"))})},moreList:function(a){var i=a.attr("lay-filter");layui.each(d.moreList,function(a,e){e&&e({alias:i})})},about:function(){n.open({content:'

        \u7248\u672c\uff1a v'+i+"

        ",className:"layim-about",shadeClose:!1,btn:"\u6211\u77e5\u9053\u4e86"})}};a("layim-mobile",new r)}).link(layui.cache.layimAssetsPath+"mobile.css","skinlayim-mobilecss"); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/zepto.js b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/zepto.js new file mode 100644 index 00000000..6d8e6439 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/zepto.js @@ -0,0 +1,2 @@ +/** WebIMUI-v3.9.8 */ + ;layui.define(function(t){var e=function(){function t(t){return null==t?String(t):J[W.call(t)]||"object"}function e(e){return"function"==t(e)}function n(t){return null!=t&&t==t.window}function r(t){return null!=t&&t.nodeType==t.DOCUMENT_NODE}function i(e){return"object"==t(e)}function o(t){return i(t)&&!n(t)&&Object.getPrototypeOf(t)==Object.prototype}function a(t){var e=!!t&&"length"in t&&t.length,r=T.type(t);return"function"!=r&&!n(t)&&("array"==r||0===e||"number"==typeof e&&e>0&&e-1 in t)}function s(t){return A.call(t,function(t){return null!=t})}function u(t){return t.length>0?T.fn.concat.apply([],t):t}function c(t){return t.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function l(t){return t in F?F[t]:F[t]=new RegExp("(^|\\s)"+t+"(\\s|$)")}function f(t,e){return"number"!=typeof e||k[c(t)]?e:e+"px"}function h(t){var e,n;return $[t]||(e=L.createElement(t),L.body.appendChild(e),n=getComputedStyle(e,"").getPropertyValue("display"),e.parentNode.removeChild(e),"none"==n&&(n="block"),$[t]=n),$[t]}function p(t){return"children"in t?D.call(t.children):T.map(t.childNodes,function(t){if(1==t.nodeType)return t})}function d(t,e){var n,r=t?t.length:0;for(n=0;n]*>/,R=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,Z=/^(?:body|html)$/i,q=/([A-Z])/g,H=["val","css","html","text","data","width","height","offset"],I=["after","prepend","before","append"],V=L.createElement("table"),_=L.createElement("tr"),B={tr:L.createElement("tbody"),tbody:V,thead:V,tfoot:V,td:_,th:_,"*":L.createElement("div")},U=/complete|loaded|interactive/,X=/^[\w-]*$/,J={},W=J.toString,Y={},G=L.createElement("div"),K={tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},Q=Array.isArray||function(t){return t instanceof Array};return Y.matches=function(t,e){if(!e||!t||1!==t.nodeType)return!1;var n=t.matches||t.webkitMatchesSelector||t.mozMatchesSelector||t.oMatchesSelector||t.matchesSelector;if(n)return n.call(t,e);var r,i=t.parentNode,o=!i;return o&&(i=G).appendChild(t),r=~Y.qsa(i,e).indexOf(t),o&&G.removeChild(t),r},C=function(t){return t.replace(/-+(.)?/g,function(t,e){return e?e.toUpperCase():""})},N=function(t){return A.call(t,function(e,n){return t.indexOf(e)==n})},Y.fragment=function(t,e,n){var r,i,a;return R.test(t)&&(r=T(L.createElement(RegExp.$1))),r||(t.replace&&(t=t.replace(z,"<$1>")),e===E&&(e=M.test(t)&&RegExp.$1),e in B||(e="*"),a=B[e],a.innerHTML=""+t,r=T.each(D.call(a.childNodes),function(){a.removeChild(this)})),o(n)&&(i=T(r),T.each(n,function(t,e){H.indexOf(t)>-1?i[t](e):i.attr(t,e)})),r},Y.Z=function(t,e){return new d(t,e)},Y.isZ=function(t){return t instanceof Y.Z},Y.init=function(t,n){var r;if(!t)return Y.Z();if("string"==typeof t)if(t=t.trim(),"<"==t[0]&&M.test(t))r=Y.fragment(t,RegExp.$1,n),t=null;else{if(n!==E)return T(n).find(t);r=Y.qsa(L,t)}else{if(e(t))return T(L).ready(t);if(Y.isZ(t))return t;if(Q(t))r=s(t);else if(i(t))r=[t],t=null;else if(M.test(t))r=Y.fragment(t.trim(),RegExp.$1,n),t=null;else{if(n!==E)return T(n).find(t);r=Y.qsa(L,t)}}return Y.Z(r,t)},T=function(t,e){return Y.init(t,e)},T.extend=function(t){var e,n=D.call(arguments,1);return"boolean"==typeof t&&(e=t,t=n.shift()),n.forEach(function(n){m(t,n,e)}),t},Y.qsa=function(t,e){var n,r="#"==e[0],i=!r&&"."==e[0],o=r||i?e.slice(1):e,a=X.test(o);return t.getElementById&&a&&r?(n=t.getElementById(o))?[n]:[]:1!==t.nodeType&&9!==t.nodeType&&11!==t.nodeType?[]:D.call(a&&!r&&t.getElementsByClassName?i?t.getElementsByClassName(o):t.getElementsByTagName(e):t.querySelectorAll(e))},T.contains=L.documentElement.contains?function(t,e){return t!==e&&t.contains(e)}:function(t,e){for(;e&&(e=e.parentNode);)if(e===t)return!0;return!1},T.type=t,T.isFunction=e,T.isWindow=n,T.isArray=Q,T.isPlainObject=o,T.isEmptyObject=function(t){var e;for(e in t)return!1;return!0},T.isNumeric=function(t){var e=Number(t),n=typeof t;return null!=t&&"boolean"!=n&&("string"!=n||t.length)&&!isNaN(e)&&isFinite(e)||!1},T.inArray=function(t,e,n){return O.indexOf.call(e,t,n)},T.camelCase=C,T.trim=function(t){return null==t?"":String.prototype.trim.call(t)},T.uuid=0,T.support={},T.expr={},T.noop=function(){},T.map=function(t,e){var n,r,i,o=[];if(a(t))for(r=0;r=0?t:t+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){null!=this.parentNode&&this.parentNode.removeChild(this)})},each:function(t){return O.every.call(this,function(e,n){return t.call(e,n,e)!==!1}),this},filter:function(t){return e(t)?this.not(this.not(t)):T(A.call(this,function(e){return Y.matches(e,t)}))},add:function(t,e){return T(N(this.concat(T(t,e))))},is:function(t){return this.length>0&&Y.matches(this[0],t)},not:function(t){var n=[];if(e(t)&&t.call!==E)this.each(function(e){t.call(this,e)||n.push(this)});else{var r="string"==typeof t?this.filter(t):a(t)&&e(t.item)?D.call(t):T(t);this.forEach(function(t){r.indexOf(t)<0&&n.push(t)})}return T(n)},has:function(t){return this.filter(function(){return i(t)?T.contains(this,t):T(this).find(t).size()})},eq:function(t){return t===-1?this.slice(t):this.slice(t,+t+1)},first:function(){var t=this[0];return t&&!i(t)?t:T(t)},last:function(){var t=this[this.length-1];return t&&!i(t)?t:T(t)},find:function(t){var e,n=this;return e=t?"object"==typeof t?T(t).filter(function(){var t=this;return O.some.call(n,function(e){return T.contains(e,t)})}):1==this.length?T(Y.qsa(this[0],t)):this.map(function(){return Y.qsa(this,t)}):T()},closest:function(t,e){var n=[],i="object"==typeof t&&T(t);return this.each(function(o,a){for(;a&&!(i?i.indexOf(a)>=0:Y.matches(a,t));)a=a!==e&&!r(a)&&a.parentNode;a&&n.indexOf(a)<0&&n.push(a)}),T(n)},parents:function(t){for(var e=[],n=this;n.length>0;)n=T.map(n,function(t){if((t=t.parentNode)&&!r(t)&&e.indexOf(t)<0)return e.push(t),t});return v(e,t)},parent:function(t){return v(N(this.pluck("parentNode")),t)},children:function(t){return v(this.map(function(){return p(this)}),t)},contents:function(){return this.map(function(){return this.contentDocument||D.call(this.childNodes)})},siblings:function(t){return v(this.map(function(t,e){return A.call(p(e.parentNode),function(t){return t!==e})}),t)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(t){return T.map(this,function(e){return e[t]})},show:function(){return this.each(function(){"none"==this.style.display&&(this.style.display=""),"none"==getComputedStyle(this,"").getPropertyValue("display")&&(this.style.display=h(this.nodeName))})},replaceWith:function(t){return this.before(t).remove()},wrap:function(t){var n=e(t);if(this[0]&&!n)var r=T(t).get(0),i=r.parentNode||this.length>1;return this.each(function(e){T(this).wrapAll(n?t.call(this,e):i?r.cloneNode(!0):r)})},wrapAll:function(t){if(this[0]){T(this[0]).before(t=T(t));for(var e;(e=t.children()).length;)t=e.first();T(t).append(this)}return this},wrapInner:function(t){var n=e(t);return this.each(function(e){var r=T(this),i=r.contents(),o=n?t.call(this,e):t;i.length?i.wrapAll(o):r.append(o)})},unwrap:function(){return this.parent().each(function(){T(this).replaceWith(T(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(t){return this.each(function(){var e=T(this);(t===E?"none"==e.css("display"):t)?e.show():e.hide()})},prev:function(t){return T(this.pluck("previousElementSibling")).filter(t||"*")},next:function(t){return T(this.pluck("nextElementSibling")).filter(t||"*")},html:function(t){return 0 in arguments?this.each(function(e){var n=this.innerHTML;T(this).empty().append(g(this,t,e,n))}):0 in this?this[0].innerHTML:null},text:function(t){return 0 in arguments?this.each(function(e){var n=g(this,t,e,this.textContent);this.textContent=null==n?"":""+n}):0 in this?this.pluck("textContent").join(""):null},attr:function(t,e){var n;return"string"!=typeof t||1 in arguments?this.each(function(n){if(1===this.nodeType)if(i(t))for(j in t)y(this,j,t[j]);else y(this,t,g(this,e,n,this.getAttribute(t)))}):0 in this&&1==this[0].nodeType&&null!=(n=this[0].getAttribute(t))?n:E},removeAttr:function(t){return this.each(function(){1===this.nodeType&&t.split(" ").forEach(function(t){y(this,t)},this)})},prop:function(t,e){return t=K[t]||t,1 in arguments?this.each(function(n){this[t]=g(this,e,n,this[t])}):this[0]&&this[0][t]},removeProp:function(t){return t=K[t]||t,this.each(function(){delete this[t]})},data:function(t,e){var n="data-"+t.replace(q,"-$1").toLowerCase(),r=1 in arguments?this.attr(n,e):this.attr(n);return null!==r?b(r):E},val:function(t){return 0 in arguments?(null==t&&(t=""),this.each(function(e){this.value=g(this,t,e,this.value)})):this[0]&&(this[0].multiple?T(this[0]).find("option").filter(function(){return this.selected}).pluck("value"):this[0].value)},offset:function(t){if(t)return this.each(function(e){var n=T(this),r=g(this,t,e,n.offset()),i=n.offsetParent().offset(),o={top:r.top-i.top,left:r.left-i.left};"static"==n.css("position")&&(o.position="relative"),n.css(o)});if(!this.length)return null;if(L.documentElement!==this[0]&&!T.contains(L.documentElement,this[0]))return{top:0,left:0};var e=this[0].getBoundingClientRect();return{left:e.left+window.pageXOffset,top:e.top+window.pageYOffset,width:Math.round(e.width),height:Math.round(e.height)}},css:function(e,n){if(arguments.length<2){var r=this[0];if("string"==typeof e){if(!r)return;return r.style[C(e)]||getComputedStyle(r,"").getPropertyValue(e)}if(Q(e)){if(!r)return;var i={},o=getComputedStyle(r,"");return T.each(e,function(t,e){i[e]=r.style[C(e)]||o.getPropertyValue(e)}),i}}var a="";if("string"==t(e))n||0===n?a=c(e)+":"+f(e,n):this.each(function(){this.style.removeProperty(c(e))});else for(j in e)e[j]||0===e[j]?a+=c(j)+":"+f(j,e[j])+";":this.each(function(){this.style.removeProperty(c(j))});return this.each(function(){this.style.cssText+=";"+a})},index:function(t){return t?this.indexOf(T(t)[0]):this.parent().children().indexOf(this[0])},hasClass:function(t){return!!t&&O.some.call(this,function(t){return this.test(x(t))},l(t))},addClass:function(t){return t?this.each(function(e){if("className"in this){S=[];var n=x(this),r=g(this,t,e,n);r.split(/\s+/g).forEach(function(t){T(this).hasClass(t)||S.push(t)},this),S.length&&x(this,n+(n?" ":"")+S.join(" "))}}):this},removeClass:function(t){return this.each(function(e){if("className"in this){if(t===E)return x(this,"");S=x(this),g(this,t,e,S).split(/\s+/g).forEach(function(t){S=S.replace(l(t)," ")}),x(this,S.trim())}})},toggleClass:function(t,e){return t?this.each(function(n){var r=T(this),i=g(this,t,n,x(this));i.split(/\s+/g).forEach(function(t){(e===E?!r.hasClass(t):e)?r.addClass(t):r.removeClass(t)})}):this},scrollTop:function(t){if(this.length){var e="scrollTop"in this[0];return t===E?e?this[0].scrollTop:this[0].pageYOffset:this.each(e?function(){this.scrollTop=t}:function(){this.scrollTo(this.scrollX,t)})}},scrollLeft:function(t){if(this.length){var e="scrollLeft"in this[0];return t===E?e?this[0].scrollLeft:this[0].pageXOffset:this.each(e?function(){this.scrollLeft=t}:function(){this.scrollTo(t,this.scrollY)})}},position:function(){if(this.length){var t=this[0],e=this.offsetParent(),n=this.offset(),r=Z.test(e[0].nodeName)?{top:0,left:0}:e.offset();return n.top-=parseFloat(T(t).css("margin-top"))||0,n.left-=parseFloat(T(t).css("margin-left"))||0,r.top+=parseFloat(T(e[0]).css("border-top-width"))||0,r.left+=parseFloat(T(e[0]).css("border-left-width"))||0,{top:n.top-r.top,left:n.left-r.left}}},offsetParent:function(){return this.map(function(){for(var t=this.offsetParent||L.body;t&&!Z.test(t.nodeName)&&"static"==T(t).css("position");)t=t.offsetParent;return t})}},T.fn.detach=T.fn.remove,["width","height"].forEach(function(t){var e=t.replace(/./,function(t){return t[0].toUpperCase()});T.fn[t]=function(i){var o,a=this[0];return i===E?n(a)?a["inner"+e]:r(a)?a.documentElement["scroll"+e]:(o=this.offset())&&o[t]:this.each(function(e){a=T(this),a.css(t,g(this,i,e,a[t]()))})}}),I.forEach(function(e,n){var r=n%2;T.fn[e]=function(){var e,i,o=T.map(arguments,function(n){var r=[];return e=t(n),"array"==e?(n.forEach(function(t){return t.nodeType!==E?r.push(t):T.zepto.isZ(t)?r=r.concat(t.get()):void(r=r.concat(Y.fragment(t)))}),r):"object"==e||null==n?n:Y.fragment(n)}),a=this.length>1;return o.length<1?this:this.each(function(t,e){i=r?e:e.parentNode,e=0==n?e.nextSibling:1==n?e.firstChild:2==n?e:null;var s=T.contains(L.documentElement,i);o.forEach(function(t){if(a)t=t.cloneNode(!0);else if(!i)return T(t).remove();i.insertBefore(t,e),s&&w(t,function(t){if(!(null==t.nodeName||"SCRIPT"!==t.nodeName.toUpperCase()||t.type&&"text/javascript"!==t.type||t.src)){var e=t.ownerDocument?t.ownerDocument.defaultView:window;e.eval.call(e,t.innerHTML)}})})})},T.fn[r?e+"To":"insert"+(n?"Before":"After")]=function(t){return T(t)[e](this),this}}),Y.Z.prototype=d.prototype=T.fn,Y.uniq=N,Y.deserializeValue=b,T.zepto=Y,T}();!function(t){function e(t){return t._zid||(t._zid=h++)}function n(t,n,o,a){if(n=r(n),n.ns)var s=i(n.ns);return(v[e(t)]||[]).filter(function(t){return t&&(!n.e||t.e==n.e)&&(!n.ns||s.test(t.ns))&&(!o||e(t.fn)===e(o))&&(!a||t.sel==a)})}function r(t){var e=(""+t).split(".");return{e:e[0],ns:e.slice(1).sort().join(" ")}}function i(t){return new RegExp("(?:^| )"+t.replace(" "," .* ?")+"(?: |$)")}function o(t,e){return t.del&&!y&&t.e in x||!!e}function a(t){return b[t]||y&&x[t]||t}function s(n,i,s,u,l,h,p){var d=e(n),m=v[d]||(v[d]=[]);i.split(/\s/).forEach(function(e){if("ready"==e)return t(document).ready(s);var i=r(e);i.fn=s,i.sel=l,i.e in b&&(s=function(e){var n=e.relatedTarget;if(!n||n!==this&&!t.contains(this,n))return i.fn.apply(this,arguments)}),i.del=h;var d=h||s;i.proxy=function(t){if(t=c(t),!t.isImmediatePropagationStopped()){t.data=u;var e=d.apply(n,t._args==f?[t]:[t].concat(t._args));return e===!1&&(t.preventDefault(),t.stopPropagation()),e}},i.i=m.length,m.push(i),"addEventListener"in n&&n.addEventListener(a(i.e),i.proxy,o(i,p))})}function u(t,r,i,s,u){var c=e(t);(r||"").split(/\s/).forEach(function(e){n(t,e,i,s).forEach(function(e){delete v[c][e.i],"removeEventListener"in t&&t.removeEventListener(a(e.e),e.proxy,o(e,u))})})}function c(e,n){return!n&&e.isDefaultPrevented||(n||(n=e),t.each(T,function(t,r){var i=n[t];e[t]=function(){return this[r]=w,i&&i.apply(n,arguments)},e[r]=E}),e.timeStamp||(e.timeStamp=Date.now()),(n.defaultPrevented!==f?n.defaultPrevented:"returnValue"in n?n.returnValue===!1:n.getPreventDefault&&n.getPreventDefault())&&(e.isDefaultPrevented=w)),e}function l(t){var e,n={originalEvent:t};for(e in t)j.test(e)||t[e]===f||(n[e]=t[e]);return c(n,t)}var f,h=1,p=Array.prototype.slice,d=t.isFunction,m=function(t){return"string"==typeof t},v={},g={},y="onfocusin"in window,x={focus:"focusin",blur:"focusout"},b={mouseenter:"mouseover",mouseleave:"mouseout"};g.click=g.mousedown=g.mouseup=g.mousemove="MouseEvents",t.event={add:s,remove:u},t.proxy=function(n,r){var i=2 in arguments&&p.call(arguments,2);if(d(n)){var o=function(){return n.apply(r,i?i.concat(p.call(arguments)):arguments)};return o._zid=e(n),o}if(m(r))return i?(i.unshift(n[r],n),t.proxy.apply(null,i)):t.proxy(n[r],n);throw new TypeError("expected function")},t.fn.bind=function(t,e,n){return this.on(t,e,n)},t.fn.unbind=function(t,e){return this.off(t,e)},t.fn.one=function(t,e,n,r){return this.on(t,e,n,r,1)};var w=function(){return!0},E=function(){return!1},j=/^([A-Z]|returnValue$|layer[XY]$|webkitMovement[XY]$)/,T={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};t.fn.delegate=function(t,e,n){return this.on(e,t,n)},t.fn.undelegate=function(t,e,n){return this.off(e,t,n)},t.fn.live=function(e,n){return t(document.body).delegate(this.selector,e,n),this},t.fn.die=function(e,n){return t(document.body).undelegate(this.selector,e,n),this},t.fn.on=function(e,n,r,i,o){var a,c,h=this;return e&&!m(e)?(t.each(e,function(t,e){h.on(t,n,r,e,o)}),h):(m(n)||d(i)||i===!1||(i=r,r=n,n=f),i!==f&&r!==!1||(i=r,r=f),i===!1&&(i=E),h.each(function(f,h){o&&(a=function(t){return u(h,t.type,i),i.apply(this,arguments)}),n&&(c=function(e){var r,o=t(e.target).closest(n,h).get(0);if(o&&o!==h)return r=t.extend(l(e),{currentTarget:o,liveFired:h}),(a||i).apply(o,[r].concat(p.call(arguments,1)))}),s(h,e,i,r,n,c||a)}))},t.fn.off=function(e,n,r){var i=this;return e&&!m(e)?(t.each(e,function(t,e){i.off(t,n,e)}),i):(m(n)||d(r)||r===!1||(r=n,n=f),r===!1&&(r=E),i.each(function(){u(this,e,r,n)}))},t.fn.trigger=function(e,n){return e=m(e)||t.isPlainObject(e)?t.Event(e):c(e),e._args=n,this.each(function(){e.type in x&&"function"==typeof this[e.type]?this[e.type]():"dispatchEvent"in this?this.dispatchEvent(e):t(this).triggerHandler(e,n)})},t.fn.triggerHandler=function(e,r){var i,o;return this.each(function(a,s){i=l(m(e)?t.Event(e):e),i._args=r,i.target=s,t.each(n(s,e.type||e),function(t,e){if(o=e.proxy(i),i.isImmediatePropagationStopped())return!1})}),o},"focusin focusout focus blur load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(e){t.fn[e]=function(t){return 0 in arguments?this.bind(e,t):this.trigger(e)}}),t.Event=function(t,e){m(t)||(e=t,t=e.type);var n=document.createEvent(g[t]||"Events"),r=!0;if(e)for(var i in e)"bubbles"==i?r=!!e[i]:n[i]=e[i];return n.initEvent(t,r,!0),c(n)}}(e),function(t){function e(e,n,r){var i=t.Event(n);return t(e).trigger(i,r),!i.isDefaultPrevented()}function n(t,n,r,i){if(t.global)return e(n||x,r,i)}function r(e){e.global&&0===t.active++&&n(e,null,"ajaxStart")}function i(e){e.global&&!--t.active&&n(e,null,"ajaxStop")}function o(t,e){var r=e.context;return e.beforeSend.call(r,t,e)!==!1&&n(e,r,"ajaxBeforeSend",[t,e])!==!1&&void n(e,r,"ajaxSend",[t,e])}function a(t,e,r,i){var o=r.context,a="success";r.success.call(o,t,a,e),i&&i.resolveWith(o,[t,a,e]),n(r,o,"ajaxSuccess",[e,r,t]),u(a,e,r)}function s(t,e,r,i,o){var a=i.context;i.error.call(a,r,e,t),o&&o.rejectWith(a,[r,e,t]),n(i,a,"ajaxError",[r,i,t||e]),u(e,r,i)}function u(t,e,r){var o=r.context;r.complete.call(o,e,t),n(r,o,"ajaxComplete",[e,r]),i(r)}function c(t,e,n){if(n.dataFilter==l)return t;var r=n.context;return n.dataFilter.call(r,t,e)}function l(){}function f(t){return t&&(t=t.split(";",2)[0]),t&&(t==T?"html":t==j?"json":w.test(t)?"script":E.test(t)&&"xml")||"text"}function h(t,e){return""==e?t:(t+"&"+e).replace(/[&?]{1,2}/,"?")}function p(e){e.processData&&e.data&&"string"!=t.type(e.data)&&(e.data=t.param(e.data,e.traditional)),!e.data||e.type&&"GET"!=e.type.toUpperCase()&&"jsonp"!=e.dataType||(e.url=h(e.url,e.data),e.data=void 0)}function d(e,n,r,i){return t.isFunction(n)&&(i=r,r=n,n=void 0),t.isFunction(r)||(i=r,r=void 0),{url:e,data:n,success:r,dataType:i}}function m(e,n,r,i){var o,a=t.isArray(n),s=t.isPlainObject(n);t.each(n,function(n,u){o=t.type(u),i&&(n=r?i:i+"["+(s||"object"==o||"array"==o?n:"")+"]"),!i&&a?e.add(u.name,u.value):"array"==o||!r&&"object"==o?m(e,u,r,n):e.add(n,u)})}var v,g,y=+new Date,x=window.document,b=/)<[^<]*)*<\/script>/gi,w=/^(?:text|application)\/javascript/i,E=/^(?:text|application)\/xml/i,j="application/json",T="text/html",S=/^\s*$/,C=x.createElement("a");C.href=window.location.href,t.active=0,t.ajaxJSONP=function(e,n){if(!("type"in e))return t.ajax(e);var r,i,u=e.jsonpCallback,c=(t.isFunction(u)?u():u)||"Zepto"+y++,l=x.createElement("script"),f=window[c],h=function(e){t(l).triggerHandler("error",e||"abort")},p={abort:h};return n&&n.promise(p),t(l).on("load error",function(o,u){clearTimeout(i),t(l).off().remove(),"error"!=o.type&&r?a(r[0],p,e,n):s(null,u||"error",p,e,n),window[c]=f,r&&t.isFunction(f)&&f(r[0]),f=r=void 0}),o(p,e)===!1?(h("abort"),p):(window[c]=function(){r=arguments},l.src=e.url.replace(/\?(.+)=\?/,"?$1="+c),x.head.appendChild(l),e.timeout>0&&(i=setTimeout(function(){h("timeout")},e.timeout)),p)},t.ajaxSettings={type:"GET",beforeSend:l,success:l,error:l,complete:l,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript, application/x-javascript",json:j,xml:"application/xml, text/xml",html:T,text:"text/plain"},crossDomain:!1,timeout:0,processData:!0,cache:!0,dataFilter:l},t.ajax=function(e){var n,i,u=t.extend({},e||{}),d=t.Deferred&&t.Deferred();for(v in t.ajaxSettings)void 0===u[v]&&(u[v]=t.ajaxSettings[v]);r(u),u.crossDomain||(n=x.createElement("a"),n.href=u.url,n.href=n.href,u.crossDomain=C.protocol+"//"+C.host!=n.protocol+"//"+n.host),u.url||(u.url=window.location.toString()),(i=u.url.indexOf("#"))>-1&&(u.url=u.url.slice(0,i)),p(u);var m=u.dataType,y=/\?.+=\?/.test(u.url);if(y&&(m="jsonp"),u.cache!==!1&&(e&&e.cache===!0||"script"!=m&&"jsonp"!=m)||(u.url=h(u.url,"_="+Date.now())),"jsonp"==m)return y||(u.url=h(u.url,u.jsonp?u.jsonp+"=?":u.jsonp===!1?"":"callback=?")),t.ajaxJSONP(u,d);var b,w=u.accepts[m],E={},j=function(t,e){E[t.toLowerCase()]=[t,e]},T=/^([\w-]+:)\/\//.test(u.url)?RegExp.$1:window.location.protocol,N=u.xhr(),O=N.setRequestHeader;if(d&&d.promise(N),u.crossDomain||j("X-Requested-With","XMLHttpRequest"),j("Accept",w||"*/*"),(w=u.mimeType||w)&&(w.indexOf(",")>-1&&(w=w.split(",",2)[0]),N.overrideMimeType&&N.overrideMimeType(w)),(u.contentType||u.contentType!==!1&&u.data&&"GET"!=u.type.toUpperCase())&&j("Content-Type",u.contentType||"application/x-www-form-urlencoded"),u.headers)for(g in u.headers)j(g,u.headers[g]);if(N.setRequestHeader=j,N.onreadystatechange=function(){if(4==N.readyState){N.onreadystatechange=l,clearTimeout(b);var e,n=!1;if(N.status>=200&&N.status<300||304==N.status||0==N.status&&"file:"==T){if(m=m||f(u.mimeType||N.getResponseHeader("content-type")),"arraybuffer"==N.responseType||"blob"==N.responseType)e=N.response;else{e=N.responseText;try{e=c(e,m,u),"script"==m?(0,eval)(e):"xml"==m?e=N.responseXML:"json"==m&&(e=S.test(e)?null:t.parseJSON(e))}catch(r){n=r}if(n)return s(n,"parsererror",N,u,d)}a(e,N,u,d)}else s(N.statusText||null,N.status?"error":"abort",N,u,d)}},o(N,u)===!1)return N.abort(),s(null,"abort",N,u,d),N;var P=!("async"in u)||u.async;if(N.open(u.type,u.url,P,u.username,u.password),u.xhrFields)for(g in u.xhrFields)N[g]=u.xhrFields[g];for(g in E)O.apply(N,E[g]);return u.timeout>0&&(b=setTimeout(function(){N.onreadystatechange=l,N.abort(),s(null,"timeout",N,u,d)},u.timeout)),N.send(u.data?u.data:null),N},t.get=function(){return t.ajax(d.apply(null,arguments))},t.post=function(){var e=d.apply(null,arguments);return e.type="POST",t.ajax(e)},t.getJSON=function(){var e=d.apply(null,arguments);return e.dataType="json",t.ajax(e)},t.fn.load=function(e,n,r){if(!this.length)return this;var i,o=this,a=e.split(/\s/),s=d(e,n,r),u=s.success;return a.length>1&&(s.url=a[0],i=a[1]),s.success=function(e){o.html(i?t("
        ").html(e.replace(b,"")).find(i):e),u&&u.apply(o,arguments)},t.ajax(s),this};var N=encodeURIComponent;t.param=function(e,n){var r=[];return r.add=function(e,n){t.isFunction(n)&&(n=n()),null==n&&(n=""),this.push(N(e)+"="+N(n))},m(r,e,n),r.join("&").replace(/%20/g,"+")}}(e),function(t){t.fn.serializeArray=function(){var e,n,r=[],i=function(t){return t.forEach?t.forEach(i):void r.push({name:e,value:t})};return this[0]&&t.each(this[0].elements,function(r,o){n=o.type,e=o.name,e&&"fieldset"!=o.nodeName.toLowerCase()&&!o.disabled&&"submit"!=n&&"reset"!=n&&"button"!=n&&"file"!=n&&("radio"!=n&&"checkbox"!=n||o.checked)&&i(t(o).val())}),r},t.fn.serialize=function(){var t=[];return this.serializeArray().forEach(function(e){t.push(encodeURIComponent(e.name)+"="+encodeURIComponent(e.value))}),t.join("&")},t.fn.submit=function(e){if(0 in arguments)this.bind("submit",e);else if(this.length){var n=t.Event("submit");this.eq(0).trigger(n),n.isDefaultPrevented()||this.get(0).submit()}return this}}(e),function(){try{getComputedStyle(void 0)}catch(t){var e=getComputedStyle;window.getComputedStyle=function(t,n){try{return e(t,n)}catch(r){return null}}}}(),t("zepto",e)}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/mobile.css b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/mobile.css new file mode 100644 index 00000000..5a7c113d --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/mobile.css @@ -0,0 +1,2 @@ +/** WebIMUI-v3.9.8 */ + .layim-panel,.layui-m-layerchild{-webkit-animation-fill-mode:both}html #layuicss-skinlayim-mobilecss{display:none;position:absolute;width:1989px}blockquote,body,button,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,input,legend,li,ol,p,td,textarea,th,ul{margin:0;padding:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}html{font:12px 'Helvetica Neue','PingFang SC',STHeitiSC-Light,Helvetica,Arial,sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}a,button,input{-webkit-tap-highlight-color:rgba(255,0,0,0)}a{text-decoration:none;background:0 0}a:active,a:hover{outline:0}table{border-collapse:collapse;border-spacing:0}li{list-style:none}b,strong{font-weight:700}h1,h2,h3,h4,h5,h6{font-weight:500}address,cite,dfn,em,var{font-style:normal}dfn{font-style:italic}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}img{border:0;vertical-align:bottom}.layui-inline,input,label{vertical-align:middle}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0;outline:0}button,select{text-transform:none}select{-webkit-appearance:none;border:none}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}.layui-box,.layui-box *{-webkit-box-sizing:content-box!important;-moz-box-sizing:content-box!important;box-sizing:content-box!important}.layim-chat-main,.layui-border-box,.layui-border-box *{-webkit-box-sizing:border-box!important;-moz-box-sizing:border-box!important}.layui-border-box,.layui-border-box *{box-sizing:border-box!important}.layui-inline{position:relative;display:inline-block;*display:inline;*zoom:1}.layui-edge,.layui-upload-iframe{position:absolute;width:0;height:0}.layui-edge{border-style:dashed;border-color:transparent;overflow:hidden}.layui-elip{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-unselect{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-disabled,.layui-disabled:active{background-color:#d2d2d2!important;color:#fff!important;cursor:not-allowed!important}.layui-circle{border-radius:100%}.layui-show{display:block!important}.layui-hide{display:none!important}.layui-upload-iframe{border:0;visibility:hidden}.layui-upload-enter{border:1px solid #009E94;background-color:#009E94;color:#fff;-webkit-transform:scale(1.1);transform:scale(1.1)}@-webkit-keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}.layui-m-anim-scale{animation-name:layui-m-anim-scale;-webkit-animation-name:layui-m-anim-scale}@-webkit-keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}.layui-m-anim-up{-webkit-animation-name:layui-m-anim-up;animation-name:layui-m-anim-up}@-webkit-keyframes layui-m-anim-left{0%{-webkit-transform:translateX(100%);transform:translateX(100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes layui-m-anim-left{0%{-webkit-transform:translateX(100%);transform:translateX(100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}.layui-m-anim-left{-webkit-animation-name:layui-m-anim-left;animation-name:layui-m-anim-left}@-webkit-keyframes layui-m-anim-right{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes layui-m-anim-right{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}.layui-m-anim-right{-webkit-animation-name:layui-m-anim-right;animation-name:layui-m-anim-right}@-webkit-keyframes layui-m-anim-lout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}@keyframes layui-m-anim-lout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}.layui-m-anim-lout{-webkit-animation-name:layui-m-anim-lout;animation-name:layui-m-anim-lout}@-webkit-keyframes layui-m-anim-rout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(100%);transform:translateX(100%)}}@keyframes layui-m-anim-rout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(100%);transform:translateX(100%)}}.layui-m-anim-rout{-webkit-animation-name:layui-m-anim-rout;animation-name:layui-m-anim-rout}.layui-m-layer{position:relative;z-index:19891014}.layui-m-layer *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.layui-m-layermain,.layui-m-layershade{position:fixed;left:0;top:0;width:100%;height:100%}.layui-m-layershade{background-color:rgba(0,0,0,.7);pointer-events:auto}.layui-m-layermain{display:table;font-family:Helvetica,arial,sans-serif;pointer-events:none}.layui-m-layermain .layui-m-layersection{display:table-cell;vertical-align:middle;text-align:center}.layui-m-layerchild{position:relative;display:inline-block;text-align:left;background-color:#fff;font-size:14px;border-radius:5px;box-shadow:0 0 8px rgba(0,0,0,.1);pointer-events:auto;-webkit-overflow-scrolling:touch;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}.layim-tab-content li h5 span,.layui-layim-list li p,.layui-layim-list li span,.layui-m-layerbtn span,.layui-m-layerchild h3{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.layui-m-layer0 .layui-m-layerchild{width:90%;max-width:640px}.layui-m-layer1 .layui-m-layerchild{border:none;border-radius:0}.layui-m-layer2 .layui-m-layerchild{width:auto;max-width:260px;min-width:40px;border:none;background:0 0;box-shadow:none;color:#fff}.layui-m-layerchild h3{padding:0 10px;height:60px;line-height:60px;font-size:16px;font-weight:400;border-radius:5px 5px 0 0;text-align:center}.layui-m-layercont{padding:50px 30px;line-height:22px;text-align:center}.layui-m-layer1 .layui-m-layercont{padding:0;text-align:left}.layui-m-layer2 .layui-m-layercont{text-align:center;padding:0;line-height:0}.layui-m-layer2 .layui-m-layercont i{width:25px;height:25px;margin-left:8px;display:inline-block;background-color:#fff;border-radius:100%;-webkit-animation:layui-m-anim-loading 1.4s infinite ease-in-out;animation:layui-m-anim-loading 1.4s infinite ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-m-layerbtn,.layui-m-layerbtn span{position:relative;border-radius:0 0 5px 5px;text-align:center}.layui-m-layer2 .layui-m-layercont p{margin-top:20px}@-webkit-keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}@keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}.layui-m-layer2 .layui-m-layercont i:first-child{margin-left:0;-webkit-animation-delay:-.32s;animation-delay:-.32s}.layui-m-layer2 .layui-m-layercont i.layui-m-layerload{-webkit-animation-delay:-.16s;animation-delay:-.16s}.layui-m-layer2 .layui-m-layercont>div{line-height:22px;padding-top:7px;margin-bottom:20px;font-size:14px}.layui-m-layerbtn{display:box;display:-moz-box;display:-webkit-box;width:100%;height:50px;line-height:50px;font-size:0;border-top:1px solid #D0D0D0;background-color:#F2F2F2}.layui-m-layerbtn span{display:block;-moz-box-flex:1;box-flex:1;-webkit-box-flex:1;font-size:14px;cursor:pointer}.layui-m-layerbtn span[yes]{color:#40AFFE}.layui-m-layerbtn span[no]{border-right:1px solid #D0D0D0;border-radius:0 0 0 5px}.layui-m-layerbtn span:active{background-color:#F6F6F6}.layui-m-layerend{position:absolute;right:7px;top:10px;width:30px;height:30px;border:0;font-weight:400;background:0 0;cursor:pointer;-webkit-appearance:none;font-size:30px}.layim-tab-content li h5,.layui-layim-list li{border-bottom:1px solid #f2f2f2;cursor:pointer}.layui-m-layerend::after,.layui-m-layerend::before{position:absolute;left:5px;top:15px;content:'';width:18px;height:1px;background-color:#999;transform:rotate(45deg);-webkit-transform:rotate(45deg);border-radius:3px}.layui-m-layerend::after{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}body .layui-m-layer .layui-m-layer-footer{position:fixed;width:95%;max-width:100%;margin:0 auto;left:0;right:0;bottom:10px;background:0 0}.layui-m-layer-footer .layui-m-layercont{padding:20px;border-radius:5px 5px 0 0;background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn{display:block;height:auto;background:0 0;border-top:none}.layui-m-layer-footer .layui-m-layerbtn span{background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn span[no]{color:#FD482C;border-top:1px solid #c2c2c2;border-radius:0 0 5px 5px}.layui-m-layer-footer .layui-m-layerbtn span[yes]{margin-top:10px;border-radius:5px}body .layui-m-layer .layui-m-layer-msg{width:auto;max-width:90%;margin:0 auto;bottom:-150px;background-color:rgba(0,0,0,.7);color:#fff}.layui-m-layer-msg .layui-m-layercont{padding:10px 20px}.layim-tab-content li h5 *,.layui-layim-skin li,.layui-layim-tab li,.layui-layim-tool li{display:inline-block;vertical-align:top;*zoom:1;*display:inline}.layui-layim-tab{position:absolute;bottom:0;left:0;right:0;height:50px;border-top:1px solid #f2f2f2;background-color:#fff}.layui-layim-tab li{position:relative;width:33.33%;height:50px;text-align:center;color:#666;color:rgba(0,0,0,.6);cursor:pointer}.layui-layim-tab li .layui-icon{position:relative;top:7px;font-size:25px}.layui-layim-tab li span{position:relative;bottom:-3px;display:block;font-size:12px}.layui-layim-tab li[lay-type=more] .layui-icon{top:4px;font-size:22px}.layui-layim-tab li.layim-this{color:#3FDD86}.layim-new{display:none;position:absolute;top:5px;left:50%;margin-left:15px;width:10px;height:10px;border-radius:10px;background-color:#F74C31;color:#fff}.layim-list-top .layim-new{position:relative;vertical-align:top;top:10px;left:initial;margin-left:5px}.layim-list-top i.layui-show{display:inline-block!important}.layim-tab-content,.layim-tab-content li ul{display:none}.layui-layim{position:fixed;left:0;right:0;top:50px;bottom:50px;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch}.layim-tab-content li h5{position:relative;padding-left:35px;height:45px;line-height:45px;font-size:0;white-space:nowrap;overflow:hidden}.layim-tab-content li h5 *{font-size:17px}.layim-tab-content li h5 span{max-width:80%}.layim-tab-content li h5 i{position:absolute;left:12px;top:0;color:#C9BDBB}.layim-tab-content li h5 em{padding-left:5px;color:#999}.layim-list-friend,.layim-list-group{background-color:#fff}.layui-layim-list li{position:relative;height:42px;padding:5px 15px 5px 60px;font-size:0}.layui-layim-list li:active{background-color:#F2F2F2;background-color:rgba(0,0,0,.05)}.layui-layim-list li.layim-null{height:20px;line-height:20px;padding:10px 0;color:#999;text-align:center;cursor:default;font-size:14px}.layim-list-history li.layim-null{padding:30px 0;border-bottom:none;background-color:#eee}.layui-layim-list li *{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:17px}.layui-layim-list li span{margin-top:2px;max-width:155px;font-size:17px}.layui-layim-list li img{position:absolute;left:12px;top:8px;width:36px;height:36px;border-radius:100%}.layui-layim-list li p{display:block;padding-right:30px;line-height:18px;font-size:13px;color:#999}.layui-layim-list li .layim-msg-status{display:none;position:absolute;right:10px;bottom:7px;padding:0 5px;height:17px;line-height:17px;border-radius:17px;text-align:center;font-size:10px;background-color:#F74C31;color:#fff}.layim-list-gray{-webkit-filter:grayscale(100%);-ms-filter:grayscale(100%);filter:grayscale(100%);filter:gray}.layim-list-top{background-color:#fff;font-size:17px}.layim-list-top li{position:relative;padding:0 15px 0 50px;line-height:45px;border-bottom:1px solid #f2f2f2;cursor:pointer}.layim-list-top li:last-child{margin-bottom:10px;border-bottom:none}.layim-list-top li .layui-icon{position:absolute;left:12px;top:0;margin-right:10px;color:#36373C;font-size:24px}.layim-list-top li[layim-event=newFriend] .layui-icon{left:15px}.layim-panel,.layim-title{position:fixed;left:0;right:0;top:0}.layim-list-top li[layim-event=group] .layui-icon{font-size:20px}.layim-list-top li[layim-event=about] .layui-icon{font-size:25px}.layim-panel{bottom:0;background-color:#eee;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}.layim-title{height:50px;line-height:50px;padding:0 15px;background-color:#36373C;color:#fff;font-size:18px}.layim-chat-status{padding-left:15px;font-size:14px;opacity:.7}.layim-title .layim-chat-back{display:inline-block;vertical-align:middle;position:relative;padding:0 15px;margin-left:-10px;top:0;font-size:24px;cursor:pointer}.layim-chat-detail{position:absolute;right:0;top:0;padding:0 15px;font-size:18px;cursor:pointer}.layim-chat-main,.layim-content{position:fixed;top:50px;left:0;right:0;overflow-y:auto;overflow-x:hidden}.layim-chat-detail:active,.layim-title .layim-chat-back:active{opacity:.8}.layui-layim .layim-title{text-align:left}.layui-layim .layim-title p{padding:0 15px}.layim-content{bottom:0}.layim-chat-main{width:100%;bottom:85px;padding:15px;box-sizing:border-box!important}.layim-chat-main ul{overflow-x:hidden}.layim-chat-main ul li{position:relative;font-size:0;margin-bottom:10px;padding-left:60px;min-height:68px}.layim-chat-text,.layim-chat-user{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:15px}.layim-chat-user{position:absolute;left:3px}.layim-chat-user img{width:40px;height:40px;border-radius:100%}.layim-chat-user cite{position:absolute;left:60px;top:-2px;width:500px;line-height:24px;font-size:12px;white-space:nowrap;color:#999;text-align:left;font-style:normal}.layim-chat-user cite i{padding-left:15px;font-style:normal}.layim-chat-text{position:relative;min-height:22px;line-height:22px;margin-top:25px;padding:8px 15px;background-color:#fff;border-radius:3px;color:#333;word-break:break-all}.layim-chat-text:after{content:'';position:absolute;left:-10px;top:13px;width:0;height:0;border-style:solid dashed dashed;border-color:#fff transparent transparent;overflow:hidden;border-width:10px}.layim-chat-text a{color:#33DF83}.layim-chat-text img{max-width:100%;vertical-align:middle}.layim-chat-text .layui-layim-file,.layui-layim-file{display:block;text-align:center}.layim-chat-text .layui-layim-file{color:#333}.layui-layim-file:active{opacity:.9}.layui-layim-file i{font-size:80px;line-height:80px}.layui-layim-file cite{display:block;line-height:20px;font-size:17px}.layui-layim-audio{text-align:center;cursor:pointer}.layui-layim-audio .layui-icon{position:relative;top:5px;font-size:24px}.layui-layim-audio p{margin-top:3px}.layui-layim-video{width:120px;height:80px;line-height:80px;background-color:#333;text-align:center;border-radius:3px}.layui-layim-video .layui-icon{font-size:36px;cursor:pointer;color:#fff}.layim-chat-main ul .layim-chat-mine{text-align:right;padding-left:0;padding-right:60px}.layim-chat-mine .layim-chat-user{left:auto;right:3px}.layim-chat-mine .layim-chat-user cite{left:auto;right:60px;text-align:right}.layim-chat-mine .layim-chat-user cite i{padding-left:0;padding-right:15px}.layim-chat-mine .layim-chat-text{margin-left:0;text-align:left;background-color:#5FB878;color:#fff}.layim-chat-mine .layim-chat-text:after{left:auto;right:-10px;border-top-color:#5FB878}.layim-chat-mine .layim-chat-text a{color:#fff}.layim-chat-main ul .layim-chat-system{min-height:0;margin:20px 0 5px;padding:0}.layim-chat-system{margin:10px 0;text-align:center}.layim-chat-system span{display:inline-block;line-height:30px;padding:0 15px;border-radius:3px;background-color:#ddd;color:#fff;font-size:14px;cursor:pointer}.layim-chat-footer{position:fixed;bottom:0;left:10px;right:10px;height:80px}.layim-chat-send{display:-webkit-box;display:-webkit-flex;display:flex}.layim-chat-send input{-webkit-box-flex:1;-webkit-flex:1;flex:1;height:40px;padding-left:5px;border:0;background-color:#fff;border-radius:3px}.layim-chat-send button{border-radius:3px;height:40px;padding:0 20px;border:0;margin-left:10px;background-color:#5FB878;color:#fff}.layim-chat-tool{position:relative;width:100%;overflow-x:auto;padding:0;height:38px;line-height:38px;margin-top:3px;font-size:0;white-space:nowrap}.layim-chat-tool span{position:relative;margin:0 15px;display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:28px;cursor:pointer}.layim-chat-tool .layim-tool-log{position:absolute;right:5px;font-size:14px}.layim-tool-log i{position:relative;top:2px;margin-right:5px;font-size:20px;color:#999}.layim-tool-image input{position:absolute;font-size:0;left:0;top:0;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layim-layer{position:fixed;bottom:85px;left:10px;right:10px;margin:0 auto}.layui-layim-face{position:relative;max-height:180px;overflow:auto;padding:10px;font-size:0}.layui-layim-face li{cursor:pointer;display:inline-block;vertical-align:bottom;padding:5px 2px;text-align:center;width:10%;-webkit-box-sizing:border-box!important;-moz-box-sizing:border-box!important;box-sizing:border-box!important}.layui-layim-face li img{width:22px;height:22px}.layim-about{font-size:17px}.layim-about .layui-m-layercont{text-align:left}.layim-about .layui-m-layercont p{line-height:30px}.layim-about .layui-m-layercont a{color:#01AAED} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/1.jpg b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..60f6a154e307f1ca11e4f740a11eabaa829715b9 GIT binary patch literal 19399 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 Qqm@m#%f|z;!CyB13ue9iV6#hiej-> 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 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/3.jpg b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..53ba9216283a962b6d325965a4a11c7504056e54 GIT binary patch literal 18610 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 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/5.jpg b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/5.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f0e3b369197e5b498c0a8b8c2e4d02b0743b272c GIT binary patch literal 45901 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 E2VAoQp8x;= literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/voice/default.mp3 b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/voice/default.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..90013c5a2120567db77c1fc6d00160e88af4d46b GIT binary patch literal 9341 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 iguvlh0?dAaU|Np{{ data.username||data.groupname||data.name||"\u4f5a\u540d" }}

          {{ data.remark||data.sign||"" }}

          new',"{{# }); if(length === 0){ }}",'
        • '+(i[a.type]||"\u6682\u65e0\u6570\u636e")+"
        • ","{{# } }}"].join("")},y=['
          ','
          ','
          {{ d.mine.username }}
          ','
          ','{{# if(d.mine.status === "online"){ }}','','{{# } else if(d.mine.status === "hide") { }}','',"{{# } }}",'
            ','
          • \u5728\u7ebf
          • ','
          • \u9690\u8eab
          • ',"
          ","
          ",'',"
          ",'
            ','
          • ','
          • ','
          • ',"
          ",'
            ','{{# layui.each(d.friend, function(index, item){ var spread = d.local["spread"+index]; }}',"
          • ",'
            {{# if(spread === "true"){ }}{{# } else { }}{{# } }}{{ item.groupname||"\u672a\u547d\u540d\u5206\u7ec4"+index }}( {{ (item.list||[]).length }})
            ','
              ',r({type:"friend",item:"item.list",index:"index"}),"
            ","
          • ","{{# }); if(d.friend.length === 0){ }}",'
            • \u6682\u65e0\u8054\u7cfb\u4eba
            ',"{{# } }}","
          ",'
            ',"
          • ",'
              ',r({type:"group"}),"
            ","
          • ","
          ",'
            ',"
          • ",'
              ',r({type:"history"}),"
            ","
          • ","
          ",'
            ',"
          • ",'',"
          • ","
          ",'
            ','',"{{# if(d.base.msgbox){ }}",'
          • ',"{{# } }}","{{# if(d.base.find){ }}",'
          • ',"{{# } }}",'
          • ',"{{# if(!d.base.copyright){ }}",'
          • ',"{{# } }}","
          ",'',"
          "].join(""),m=['
            ',"{{# layui.each(d.skin, function(index, item){ }}",'
          • ',"{{# }); }}",'
          • \u7b80\u7ea6
          • ',"
          "].join(""),f=['
          ','
          ','
          ','{{ d.data.name||"\u4f5a\u540d" }} {{d.data.temporary ? "\u4e34\u65f6\u4f1a\u8bdd" : ""}} {{# if(d.data.type==="group"){ }} {{# } }}','

          ',"
          ","
          ",'
          ',"
            ","
            ",'","
            "].join(""),p=['
            ','

            {{ d.data.name||"" }}

            ','
            ','{{# if(d.data.type === "friend" && d.type === "setGroup"){ }}',"

            \u9009\u62e9\u5206\u7ec4

            ",'{{# } if(d.data.type === "friend"){ }}','","{{# } }}",'{{# if(d.data.type === "group"){ }}',"

            \u8bf7\u8f93\u5165\u9a8c\u8bc1\u4fe1\u606f

            ",'{{# } if(d.type !== "setGroup"){ }}','',"{{# } }}","
            ","
            "].join(""),h=['
          • ','
            ',"{{# if(d.mine){ }}",'{{ layui.data.date(d.timestamp) }}{{ d.username||"\u4f5a\u540d" }}',"{{# } else { }}",'{{ d.username||"\u4f5a\u540d" }}{{ layui.data.date(d.timestamp) }}',"{{# } }}","
            ",'
            {{ layui.data.content(d.content||" ") }}
            ',"
          • "].join(""),g='
          • {{ d.data.name||"\u4f5a\u540d" }}{{# if(!d.base.brief){ }}{{# } }}
          • ',v=function(a){return a<10?"0"+(0|a):a};layui.data.date=function(a){var i=new Date(a||new Date);return i.getFullYear()+"-"+v(i.getMonth()+1)+"-"+v(i.getDate())+" "+v(i.getHours())+":"+v(i.getMinutes())+":"+v(i.getSeconds())},layui.data.content=function(a){var i=function(a){return new RegExp("\\n*\\["+(a||"")+"(code|pre|div|span|p|table|thead|th|tbody|tr|td|ul|li|ol|li|dl|dt|dd|h2|h3|h4|h5)([\\s\\S]*?)\\]\\n*","g")};return a=(a||"").replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,""").replace(/@(\S+)(\s+?|$)/g,'@
            $1$2').replace(/face\[([^\s\[\]]+?)\]/g,function(a){var i=a.replace(/^face/g,"");return''+i+''}).replace(/img\[([^\s]+?)\]/g,function(a){return''}).replace(/file\([\s\S]+?\)\[[\s\S]*?\]/g,function(a){var i=(a.match(/file\(([\s\S]+?)\)\[/)||[])[1],e=(a.match(/\)\[([\s\S]*?)\]/)||[])[1];return i?''+(e||i)+"":a}).replace(/audio\[([^\s]+?)\]/g,function(a){return'

            \u97f3\u9891\u6d88\u606f

            '}).replace(/video\[([^\s]+?)\]/g,function(a){return'
            '}).replace(/a\([\s\S]+?\)\[[\s\S]*?\]/g,function(a){var i=(a.match(/a\(([\s\S]+?)\)\[/)||[])[1],e=(a.match(/\)\[([\s\S]*?)\]/)||[])[1];return i?''+(e||i)+"":a}).replace(i(),"<$1 $2>").replace(i("/"),"").replace(/\n/g,"
            ")};var x,b,w,k,C,A=function(a,i,n){return a=a||{},e.ajax({url:a.url,type:a.type||"get",data:a.data,dataType:a.dataType||"json",headers:a.headers||{},cache:!1,success:function(a){0==a.code?i&&i(a.data||{}):t.msg(a.msg||(n||"Error")+": LAYIM_NOT_GET_DATA",{time:5e3})},error:function(a,i){window.console&&console.log&&console.error("LAYIM_DATE_ERROR\uff1a"+i)}})},S={message:{},chat:[]},P=function(a){var i=a.init||{};return mine=i.mine||{},local=layui.data("layim")[mine.id]||{},obj={base:a,local:local,mine:mine,history:local.history||{}},create=function(i){var t=i.mine||{},l=layui.data("layim")[t.id]||{},s={base:a,local:l,mine:t,friend:i.friend||[],group:i.group||[],history:l.history||{}};S=e.extend(S,s),H(n(y).render(s)),(l.close||a.min)&&L(),layui.each(u.ready,function(a,i){i&&i(s)})},S=e.extend(S,obj),a.brief?layui.each(u.ready,function(a,i){i&&i(obj)}):void(i.url?A(i,create,"INIT"):create(i))},H=function(a){return t.open({type:1,area:["260px","520px"],skin:"layui-box layui-layim",title:"​",offset:"rb",id:"layui-layim",shade:!1,anim:2,resize:!1,content:a,success:function(a){x=a,R(a),S.base.right&&a.css("margin-left","-"+S.base.right),b&&t.close(b.attr("times"));var i=[],n=a.find(".layim-list-history");n.find("li").each(function(){i.push(e(this).prop("outerHTML"))}),i.length>0&&(i.reverse(),n.html(i.join(""))),j(),ta.sign()},cancel:function(a){L();var i=layui.data("layim")[S.mine.id]||{};return i.close=!0,layui.data("layim",{key:S.mine.id,value:i}),!1}})},j=function(){x.on("contextmenu",function(a){return a.cancelBubble=!0,a.returnValue=!1,!1});var a=function(){t.closeAll("tips")};x.find(".layim-list-history").on("contextmenu","li",function(i){var n=e(this),l='
            • \u79fb\u9664\u8be5\u4f1a\u8bdd
            • \u6e05\u7a7a\u5168\u90e8\u4f1a\u8bdd\u5217\u8868
            ';n.hasClass("layim-null")||(t.tips(l,this,{tips:1,time:0,anim:5,fixed:!0,skin:"layui-box layui-layim-contextmenu",success:function(a){var i=function(a){aa(a)};a.off("mousedown",i).on("mousedown",i)}}),e(document).off("mousedown",a).on("mousedown",a),e(window).off("resize",a).on("resize",a))})},L=function(a){return b&&t.close(b.attr("times")),x&&x.hide(),S.mine=S.mine||{},t.open({type:1,title:!1,id:"layui-layim-close",skin:"layui-box layui-layim-min layui-layim-close",shade:!1,closeBtn:!1,anim:2,offset:"rb",resize:!1,content:''+(a||S.base.title||"\u6211\u7684 IM")+"",move:"#layui-layim-close img",success:function(a,i){b=a,S.base.right&&a.css("margin-left","-"+S.base.right),a.on("click",function(){t.close(i),x.show();var a=layui.data("layim")[S.mine.id]||{};delete a.close,layui.data("layim",{key:S.mine.id,value:a})})}})},T=function(a){a=a||{};var i=e("#layui-layim-chat"),l={data:a,base:S.base,local:S.local};if(!a.id)return t.msg("\u975e\u6cd5\u7528\u6237");if(i[0]){var s=w.find(".layim-chat-list"),o=s.find(".layim-chatlist-"+a.type+a.id),d=w.find(".layui-layer-max").hasClass("layui-layer-maxmin"),c=i.children(".layim-chat-box");return"none"===w.css("display")&&w.show(),k&&t.close(k.attr("times")),1!==s.find("li").length||o[0]||(d||w.css("width",800),s.css({height:w.height()}).show(),c.css("margin-left","200px")),o[0]||(s.append(n(g).render(l)),c.append(n(f).render(l)),z(a),E()),M(s.find(".layim-chatlist-"+a.type+a.id)),o[0]||B(),_(a),Q(),C}l.first=!0;var r=C=t.open({type:1,area:"600px",skin:"layui-box layui-layim-chat",id:"layui-layim-chat",title:"​",shade:!1,maxmin:!0,offset:a.offset||"auto",anim:a.anim||0,closeBtn:!S.base.brief&&1,content:n('
              '+g+'
            '+f+"
            ").render(l),success:function(i){w=i,i.css({"min-width":"500px","min-height":"420px"}),z(a),"function"==typeof a.success&&a.success(i),Q(),R(i),_(a),B(),O(),layui.each(u.chatChange,function(a,i){i&&i(q())}),i.on("dblclick",".layui-layim-photos",function(){var a=this.src;t.close(T.photosIndex),t.photos({photos:{data:[{alt:"\u5927\u56fe\u6a21\u5f0f",src:a}]},shade:.01,closeBtn:2,anim:0,resize:!1,success:function(a,i){T.photosIndex=i}})})},full:function(a){t.style(r,{width:"100%",height:"100%"},!0),E()},resizing:E,restore:E,min:function(){return I(),!1},end:function(){t.closeAll("tips"),w=null}});return r},z=function(a){e(".layim-"+a.type+a.id).each(function(){e(this).hasClass("layim-list-gray")&&layui.layim.setFriendStatus(a.id,"offline")})},E=function(){var a=w.find(".layim-chat-list"),i=w.find(".layim-chat-main"),e=w.height();a.css({height:e}),i.css({height:e-20-80-158})},I=function(a){var i=a||q().data,n=layui.layim.cache().base;w&&!a&&w.hide(),t.close(I.index),I.index=t.open({type:1,title:!1,skin:"layui-box layui-layim-min",shade:!1,closeBtn:!1,anim:i.anim||2,offset:"b",move:"#layui-layim-min",resize:!1,area:["182px","50px"],content:''+i.name+"",success:function(i,l){a||(k=i),n.minRight&&t.style(l,{left:e(window).width()-i.outerWidth()-parseFloat(n.minRight)}),i.find(".layui-layer-content span").on("click",function(){t.close(l),a?layui.each(S.chat,function(a,i){T(i)}):w.show(),a&&(S.chat=[],Z())}),i.find(".layui-layer-content img").on("click",function(a){aa(a)})}})},N=function(a,i){return a=a||{},t.close(N.index),N.index=t.open({type:1,area:"430px",title:{friend:"\u6dfb\u52a0\u597d\u53cb",group:"\u52a0\u5165\u7fa4\u7ec4"}[a.type]||"",shade:!1,resize:!1,btn:i?["\u786e\u8ba4","\u53d6\u6d88"]:["\u53d1\u9001\u7533\u8bf7","\u5173\u95ed"],content:n(p).render({data:{name:a.username||a.groupname,avatar:a.avatar||layui.cache.layimAssetsPath+"images/default.png",group:a.group||parent.layui.layim.cache().friend||[],type:a.type},type:i}),yes:function(e,t){var n=t.find("#LAY_layimGroup"),l=t.find("#LAY_layimRemark");i?a.submit&&a.submit(n.val(),e):a.submit&&a.submit(n.val(),l.val(),e)}})},M=function(a,i){a=a||e(".layim-chat-list ."+o);var n=a.index()===-1?0:a.index(),l=".layim-chat",d=w.find(l).eq(n),c=w.find(".layui-layer-max").hasClass("layui-layer-maxmin");if(i){a.hasClass(o)&&M(0===n?a.next():a.prev());var r=w.find(l).length;return 1===r?t.close(C):(a.remove(),d.remove(),2===r&&(w.find(".layim-chat-list").hide(),c||w.css("width","600px"),w.find(".layim-chat-box").css("margin-left",0)),!1)}a.addClass(o).siblings().removeClass(o),d.addClass(s).siblings(l).removeClass(s),d.find("textarea").focus(),layui.each(u.chatChange,function(a,i){i&&i(q())}),O()},O=function(){var a=q(),i=S.message[a.data.type+a.data.id];i&&delete S.message[a.data.type+a.data.id]},q=c.prototype.thisChat=function(){if(w){var a=e(".layim-chat-list ."+o).index(),i=w.find(".layim-chat").eq(a),t=JSON.parse(decodeURIComponent(i.find(".layim-chat-tool").data("json")));return{elem:i,data:t,textarea:i.find("textarea")}}},R=function(a){var i=layui.data("layim")[S.mine.id]||{},e=i.skin;a.css({"background-image":e?"url("+e+")":function(){return S.base.initSkin?"url("+(layui.cache.layimAssetsPath+"skin/"+S.base.initSkin)+")":"none"}()})},_=function(a){var i=layui.data("layim")[S.mine.id]||{},e={},t=i.history||{},l=t[a.type+a.id];if(x){var s=x.find(".layim-list-history");if(a.historyTime=(new Date).getTime(),t[a.type+a.id]=a,i.history=t,layui.data("layim",{key:S.mine.id,value:i}),!l){e[a.type+a.id]=a;var o=n(r({type:"history",item:"d.data"})).render({data:e});s.prepend(o),s.find(".layim-null").remove()}}},$=function(){var a={username:S.mine?S.mine.username:"\u8bbf\u5ba2",avatar:S.mine?S.mine.avatar:layui.cache.layimAssetsPath+"images/default.png",id:S.mine?S.mine.id:null,mine:!0},i=q(),e=i.elem.find(".layim-chat-main ul"),l=S.base.maxLength||3e3;if(a.content=i.textarea.val(),""!==a.content.replace(/\s/g,"")){if(a.content.length>l)return t.msg("\u5185\u5bb9\u6700\u957f\u4e0d\u80fd\u8d85\u8fc7"+l+"\u4e2a\u5b57\u7b26");e.append(n(h).render(a));var s={mine:a,to:i.data},o={username:s.mine.username,avatar:s.mine.avatar||layui.cache.layimAssetsPath+"images/default.png",id:s.to.id,type:s.to.type,content:s.mine.content,timestamp:(new Date).getTime(),mine:!0};V(o),layui.each(u.sendMessage,function(a,i){i&&i(s)})}Z(),i.textarea.val("").focus()},D=function(a){if(a=a||{},window.Notification)if("granted"===Notification.permission){new Notification(a.title||"",{body:a.content||"",icon:a.avatar||layui.cache.layimAssetsPath+"images/default.png"})}else Notification.requestPermission()},J=function(){if(!(l.ie&&l.ie<9)){var a=document.createElement("audio");a.src=layui.cache.layimAssetsPath+"voice/"+S.base.voice,a.play()}},F={},G=function(a){a=a||{};var i=e(".layim-chatlist-"+a.type+a.id),t={},l=i.index();if(a.timestamp=a.timestamp||(new Date).getTime(),a.fromid==S.mine.id&&(a.mine=!0),a.system||V(a),F=JSON.parse(JSON.stringify(a)),S.base.voice&&J(),!w&&a.content||l===-1){if(S.message[a.type+a.id])S.message[a.type+a.id].push(a);else if(S.message[a.type+a.id]=[a],"friend"===a.type){var s;layui.each(S.friend,function(i,e){if(layui.each(e.list,function(i,e){if(e.id==a.id)return e.type="friend",e.name=e.username,S.chat.push(e),s=!0}),s)return!0}),s||(a.name=a.username,a.temporary=!0,S.chat.push(a))}else if("group"===a.type){var o;layui.each(S.group,function(i,e){if(e.id==a.id)return e.type="group",e.name=e.groupname,S.chat.push(e),o=!0}),o||(a.name=a.groupname,S.chat.push(a))}else a.name=a.name||a.username||a.groupname,S.chat.push(a);if("group"===a.type&&layui.each(S.group,function(i,e){if(e.id==a.id)return t.avatar=e.avatar||layui.cache.layimAssetsPath+"images/default.png",!0}),!a.system)return S.base.notice&&D({title:"\u6765\u81ea "+a.username+" \u7684\u6d88\u606f",content:a.content,avatar:t.avatar||a.avatar||layui.cache.layimAssetsPath+"images/default.png"}),I({name:"\u6536\u5230\u65b0\u6d88\u606f",avatar:t.avatar||a.avatar||layui.cache.layimAssetsPath+"images/default.png",anim:6})}if(w){var d=q();d.data.type+d.data.id!==a.type+a.id&&(i.addClass("layui-anim layer-anim-06"),setTimeout(function(){i.removeClass("layui-anim layer-anim-06")},300));var u=w.find(".layim-chat").eq(l),c=u.find(".layim-chat-main ul");a.system?l!==-1&&c.append('
          • '+a.content+"
          • "):""!==a.content.replace(/\s/g,"")&&c.append(n(h).render(a)),Z()}},K="layui-anim-loop layer-anim-05",Y=function(a){var i=x.find(".layim-tool-msgbox");i.find("span").addClass(K).html(a)},V=function(a){var i=layui.data("layim")[S.mine.id]||{};i.chatlog=i.chatlog||{};var e=i.chatlog[a.type+a.id];if(e){var t;layui.each(e,function(i,e){e.timestamp===a.timestamp&&e.type===a.type&&e.id===a.id&&e.content===a.content&&(t=!0)}),t||a.fromid==S.mine.id||e.push(a),e.length>d&&e.shift()}else i.chatlog[a.type+a.id]=[a];layui.data("layim",{key:S.mine.id,value:i})},B=function(){var a=layui.data("layim")[S.mine.id]||{},i=q(),e=a.chatlog||{},t=i.elem.find(".layim-chat-main ul");layui.each(e[i.data.type+i.data.id],function(a,i){t.append(n(h).render(i))}),Z()},U=function(a){var i,e={},l=x.find(".layim-list-"+a.type);if(S[a.type])if("friend"===a.type)layui.each(S.friend,function(n,l){if(a.groupid==l.id)return layui.each(S.friend[n].list,function(e,t){if(t.id==a.id)return i=!0}),i?t.msg("\u597d\u53cb ["+(a.username||"")+"] \u5df2\u7ecf\u5b58\u5728\u5217\u8868\u4e2d",{anim:6}):(S.friend[n].list=S.friend[n].list||[],e[S.friend[n].list.length]=a,a.groupIndex=n,S.friend[n].list.push(a),!0)});else if("group"===a.type){if(layui.each(S.group,function(e,t){if(t.id==a.id)return i=!0}),i)return t.msg("\u60a8\u5df2\u662f ["+(a.groupname||"")+"] \u7684\u7fa4\u6210\u5458",{anim:6});e[S.group.length]=a,S.group.push(a)}if(!i){var s=n(r({type:a.type,item:"d.data",index:"friend"===a.type?"data.groupIndex":null})).render({data:e});if("friend"===a.type){var o=l.find(">li").eq(a.groupIndex);o.find(".layui-layim-list").append(s),o.find(".layim-count").html(S.friend[a.groupIndex].list.length),o.find(".layim-null")[0]&&o.find(".layim-null").remove()}else"group"===a.type&&(l.append(s),l.find(".layim-null")[0]&&l.find(".layim-null").remove())}},W=function(a){var i=x.find(".layim-list-"+a.type);S[a.type]&&("friend"===a.type?layui.each(S.friend,function(e,t){layui.each(t.list,function(t,n){if(a.id==n.id){var l=i.find(">li").eq(e);l.find(".layui-layim-list>li");return l.find(".layui-layim-list>li").eq(t).remove(),S.friend[e].list.splice(t,1),l.find(".layim-count").html(S.friend[e].list.length),0===S.friend[e].list.length&&l.find(".layui-layim-list").html('
          • \u8be5\u5206\u7ec4\u4e0b\u5df2\u65e0\u597d\u53cb\u4e86
          • '),!0}})}):"group"===a.type&&layui.each(S.group,function(e,t){if(a.id==t.id)return i.find(">li").eq(e).remove(),S.group.splice(e,1),0===S.group.length&&i.html('
          • \u6682\u65e0\u7fa4\u7ec4
          • '),!0}))},Z=function(){var a=q(),i=a.elem.find(".layim-chat-main"),e=i.find("ul"),t=e.find("li").length;if(t>=d){var n=e.find("li").eq(0);e.prev().hasClass("layim-chat-system")||e.before('
            \u67e5\u770b\u66f4\u591a\u8bb0\u5f55
            '),t>d&&n.remove()}i.scrollTop(i[0].scrollHeight+1e3),i.find("ul li:last").find("img").load(function(){i.scrollTop(i[0].scrollHeight+1e3)})},Q=function(){var a=q(),i=a.textarea;i.focus(),i.off("keydown").on("keydown",function(a){var e=layui.data("layim")[S.mine.id]||{},t=a.keyCode;if("Ctrl+Enter"===e.sendHotKey)return void(a.ctrlKey&&13===t&&$());if(13===t){if(a.ctrlKey)return i.val(i.val()+"\n");if(a.shiftKey)return;a.preventDefault(),$()}})},X=function(){var a=["[\u5fae\u7b11]","[\u563b\u563b]","[\u54c8\u54c8]","[\u53ef\u7231]","[\u53ef\u601c]","[\u6316\u9f3b]","[\u5403\u60ca]","[\u5bb3\u7f9e]","[\u6324\u773c]","[\u95ed\u5634]","[\u9119\u89c6]","[\u7231\u4f60]","[\u6cea]","[\u5077\u7b11]","[\u4eb2\u4eb2]","[\u751f\u75c5]","[\u592a\u5f00\u5fc3]","[\u767d\u773c]","[\u53f3\u54fc\u54fc]","[\u5de6\u54fc\u54fc]","[\u5618]","[\u8870]","[\u59d4\u5c48]","[\u5410]","[\u54c8\u6b20]","[\u62b1\u62b1]","[\u6012]","[\u7591\u95ee]","[\u998b\u5634]","[\u62dc\u62dc]","[\u601d\u8003]","[\u6c57]","[\u56f0]","[\u7761]","[\u94b1]","[\u5931\u671b]","[\u9177]","[\u8272]","[\u54fc]","[\u9f13\u638c]","[\u6655]","[\u60b2\u4f24]","[\u6293\u72c2]","[\u9ed1\u7ebf]","[\u9634\u9669]","[\u6012\u9a82]","[\u4e92\u7c89]","[\u5fc3]","[\u4f24\u5fc3]","[\u732a\u5934]","[\u718a\u732b]","[\u5154\u5b50]","[ok]","[\u8036]","[good]","[NO]","[\u8d5e]","[\u6765]","[\u5f31]","[\u8349\u6ce5\u9a6c]","[\u795e\u9a6c]","[\u56e7]","[\u6d6e\u4e91]","[\u7ed9\u529b]","[\u56f4\u89c2]","[\u5a01\u6b66]","[\u5965\u7279\u66fc]","[\u793c\u7269]","[\u949f]","[\u8bdd\u7b52]","[\u8721\u70db]","[\u86cb\u7cd5]"],i={};return layui.each(a,function(a,e){i[e]=layui.cache.layimAssetsPath+"images/face/"+a+".gif"}),i}(),aa=layui.stope,ia=function(a,i){var e,t=a.value;a.focus(),document.selection?(e=document.selection.createRange(),document.selection.empty(),e.text=i):(e=[t.substring(0,a.selectionStart),i,t.substr(a.selectionEnd)],a.focus(),a.value=e.join(""))},ea="layui-anim-upbit",ta={status:function(a,i){var t=function(){a.next().hide().removeClass(ea)},n=a.attr("lay-type");if("show"===n)aa(i),a.next().show().addClass(ea),e(document).off("click",t).on("click",t);else{var l=a.parent().prev();a.addClass(o).siblings().removeClass(o),l.html(a.find("cite").html()),l.removeClass("layim-status-"+("online"===n?"hide":"online")).addClass("layim-status-"+n),layui.each(u.online,function(a,i){i&&i(n)})}},sign:function(){var a=x.find(".layui-layim-remark");a.on("change",function(){var a=this.value;layui.each(u.sign,function(i,e){e&&e(a)})}),a.on("keyup",function(a){var i=a.keyCode;13===i&&this.blur()})},tab:function(a){var i,e=".layim-tab-content",t=x.find(".layui-layim-tab>li");"number"==typeof a?(i=a,a=t.eq(i)):i=a.index(),i>2?t.removeClass(o):(ta.tab.index=i,a.addClass(o).siblings().removeClass(o)),x.find(e).eq(i).addClass(s).siblings(e).removeClass(s)},spread:function(a){var i=a.attr("lay-type"),e="true"===i?"false":"true",t=layui.data("layim")[S.mine.id]||{};a.next()["true"===i?"removeClass":"addClass"](s),t["spread"+a.parent().index()]=e,layui.data("layim",{key:S.mine.id,value:t}),a.attr("lay-type",e),a.find(".layui-icon").html("true"===e?"":"")},search:function(a){var i=x.find(".layui-layim-search"),e=x.find("#layui-layim-search"),t=i.find("input"),n=function(a){var i=t.val().replace(/\s/);if(""===i)ta.tab(0|ta.tab.index);else{for(var n=[],l=S.friend||[],s=S.group||[],o="",d=0;d0)for(var r=0;r'+(n[r].username||n[r].groupname||"\u4f5a\u540d")+"

            "+(n[r].remark||n[r].sign||"")+"

            ";else o='
          • \u65e0\u641c\u7d22\u7ed3\u679c
          • ';e.html(o),ta.tab(3)}};!S.base.isfriend&&S.base.isgroup?ta.tab.index=1:S.base.isfriend||S.base.isgroup||(ta.tab.index=2),i.show(),t.focus(),t.off("keyup",n).on("keyup",n)},closeSearch:function(a){a.parent().hide(),ta.tab(0|ta.tab.index)},msgbox:function(){var a=x.find(".layim-tool-msgbox");return t.close(ta.msgbox.index),a.find("span").removeClass(K).html(""),ta.msgbox.index=t.open({type:2,title:"\u6d88\u606f\u76d2\u5b50",shade:!1,maxmin:!0,area:["600px","520px"],skin:"layui-box layui-layer-border",resize:!1,content:S.base.msgbox})},find:function(){return t.close(ta.find.index),ta.find.index=t.open({type:2,title:"\u67e5\u627e",shade:!1,maxmin:!0,area:["1000px","520px"],skin:"layui-box layui-layer-border",resize:!1,content:S.base.find})},skin:function(){t.open({type:1,title:"\u66f4\u6362\u80cc\u666f",shade:!1,area:"300px",skin:"layui-box layui-layer-border",id:"layui-layim-skin",zIndex:66666666,resize:!1,content:n(m).render({skin:S.base.skin})})},about:function(){t.alert("\u7248\u672c\uff1a v"+i,{title:"\u5173\u4e8e",shade:!1})},setSkin:function(a){var i=a.attr("src"),e=layui.data("layim")[S.mine.id]||{};e.skin=i,i||delete e.skin,layui.data("layim",{key:S.mine.id,value:e});try{x.css({"background-image":i?"url("+i+")":"none"}),w.css({"background-image":i?"url("+i+")":"none"})}catch(t){}layui.each(u.setSkin,function(a,e){var t=(i||"").replace(layui.cache.layimAssetsPath+"skin/","");e&&e(t,i)})},chat:function(a){var i=layui.data("layim")[S.mine.id]||{},e=a.data("type"),t=a.data("index"),n=a.attr("data-list")||a.index(),l={}; +"friend"===e?l=S[e][t].list[n]:"group"===e?l=S[e][n]:"history"===e&&(l=(i.history||{})[t]||{}),l.name=l.name||l.username||l.groupname,"history"!==e&&(l.type=e),T(l)},tabChat:function(a){M(a)},closeChat:function(a,i){M(a.parent(),1),aa(i)},closeThisChat:function(){M(null,1)},groupMembers:function(a,i){var n=a.find(".layui-icon"),l=function(){n.html(""),a.data("down",null),t.close(ta.groupMembers.index)},s=function(a){aa(a)};a.data("down")?l():(n.html(""),a.data("down",!0),ta.groupMembers.index=t.tips('
              ',a,{tips:3,time:0,anim:5,fixed:!0,skin:"layui-box layui-layim-members",success:function(i){var t=S.base.members||{},n=q(),s=i.find(".layim-members-list"),o="",d={},c=w.find(".layui-layer-max").hasClass("layui-layer-maxmin"),r="none"===w.find(".layim-chat-list").css("display");c&&s.css({width:e(window).width()-22-(r||200)}),t.data=e.extend(t.data,{id:n.data.id}),A(t,function(i){layui.each(i.list,function(a,i){o+='
            • '+i.username+"
            • ",d[i.id]=i}),s.html(o),a.find(".layim-chat-members").html(i.members||(i.list||[]).length+"\u4eba"),s.find("li").on("click",function(){var a=e(this).data("uid"),i=d[a];T({name:i.username,type:"friend",avatar:i.avatar||layui.cache.layimAssetsPath+"images/default.png",id:i.id}),l()}),layui.each(u.members,function(a,e){e&&e(i)})}),i.on("mousedown",function(a){aa(a)})}}),e(document).off("mousedown",l).on("mousedown",l),e(window).off("resize",l).on("resize",l),a.off("mousedown",s).on("mousedown",s))},send:function(){$()},setSend:function(a,i){var t=ta.setSend.box=a.siblings(".layim-menu-box"),n=a.attr("lay-type");if("show"===n)aa(i),t.show().addClass(ea),e(document).off("click",ta.setSendHide).on("click",ta.setSendHide);else{a.addClass(o).siblings().removeClass(o);var l=layui.data("layim")[S.mine.id]||{};l.sendHotKey=n,layui.data("layim",{key:S.mine.id,value:l}),ta.setSendHide(i,a.parent())}},setSendHide:function(a,i){(i||ta.setSend.box).hide().removeClass(ea)},face:function(a,i){var n="",l=q();for(var s in X)n+='
            • ';n='
                '+n+"
              ",ta.face.index=t.tips(n,a,{tips:1,time:0,fixed:!0,skin:"layui-box layui-layim-face",success:function(a){a.find(".layim-face-list>li").on("mousedown",function(a){aa(a)}).on("click",function(){ia(l.textarea[0],"face"+this.title+" "),t.close(ta.face.index)})}}),e(document).off("mousedown",ta.faceHide).on("mousedown",ta.faceHide),e(window).off("resize",ta.faceHide).on("resize",ta.faceHide),aa(i)},faceHide:function(){t.close(ta.face.index)},image:function(a){var i=a.data("type")||"images",e={images:"uploadImage",file:"uploadFile"},n=q(),l=S.base[e[i]]||{};layui.upload.render({url:l.url||"",method:l.type,elem:a.find("input")[0],accept:i,done:function(a){0==a.code?(a.data=a.data||{},"images"===i?ia(n.textarea[0],"img["+(a.data.src||"")+"]"):"file"===i&&ia(n.textarea[0],"file("+(a.data.src||"")+")["+(a.data.name||"\u4e0b\u8f7d\u6587\u4ef6")+"]"),$()):t.msg(a.msg||"\u4e0a\u4f20\u5931\u8d25")}})},media:function(a){var i=a.data("type"),n={audio:"\u97f3\u9891",video:"\u89c6\u9891"},l=q();t.prompt({title:"\u8bf7\u8f93\u5165\u7f51\u7edc"+n[i]+"\u5730\u5740",shade:!1,offset:[a.offset().top-e(window).scrollTop()-158+"px",a.offset().left+"px"]},function(a,e){ia(l.textarea[0],i+"["+a+"]"),$(),t.close(e)})},extend:function(a){var i=a.attr("lay-filter"),e=q();layui.each(u["tool("+i+")"],function(i,t){t&&t.call(a,function(a){ia(e.textarea[0],a)},$,e)})},playAudio:function(a){var i=a.data("audio"),e=i||document.createElement("audio"),n=function(){e.pause(),a.removeAttr("status"),a.find("i").html("")};return a.data("error")?t.msg("\u64ad\u653e\u97f3\u9891\u6e90\u5f02\u5e38"):e.play?void(a.attr("status")?n():(i||(e.src=a.data("src")),e.play(),a.attr("status","pause"),a.data("audio",e),a.find("i").html(""),e.onended=function(){n()},e.onerror=function(){t.msg("\u64ad\u653e\u97f3\u9891\u6e90\u5f02\u5e38"),a.data("error",!0),n()})):t.msg("\u60a8\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301audio")},playVideo:function(a){var i=a.data("src"),e=document.createElement("video");return e.play?(t.close(ta.playVideo.index),void(ta.playVideo.index=t.open({type:1,title:"\u64ad\u653e\u89c6\u9891",area:["460px","300px"],maxmin:!0,shade:!1,content:'
              '}))):t.msg("\u60a8\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301video")},chatLog:function(a){var i=q();return S.base.chatLog?(t.close(ta.chatLog.index),ta.chatLog.index=t.open({type:2,maxmin:!0,title:"\u4e0e "+i.data.name+" \u7684\u804a\u5929\u8bb0\u5f55",area:["450px","100%"],shade:!1,offset:"rb",skin:"layui-box",anim:2,id:"layui-layim-chatlog",content:S.base.chatLog+"?id="+i.data.id+"&type="+i.data.type})):t.msg("\u672a\u5f00\u542f\u66f4\u591a\u804a\u5929\u8bb0\u5f55")},menuHistory:function(a,i){var n=layui.data("layim")[S.mine.id]||{},l=a.parent(),s=a.data("type"),o=x.find(".layim-list-history"),d='
            • \u6682\u65e0\u5386\u53f2\u4f1a\u8bdd
            • ';if("one"===s){var u=n.history;delete u[l.data("index")],n.history=u,layui.data("layim",{key:S.mine.id,value:n}),e(".layim-list-history li.layim-"+l.data("index")).remove(),0===o.find("li").length&&o.html(d)}else"all"===s&&(delete n.history,layui.data("layim",{key:S.mine.id,value:n}),o.html(d));t.closeAll("tips")}};a("layim",new c)}).link(layui.cache.layimAssetsPath+"layim.css","skinlayimcss"); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/view.js b/iot-server/server-starter/src/main/webapp/assets/src/lib/view.js new file mode 100644 index 00000000..017ce703 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/lib/view.js @@ -0,0 +1,344 @@ + +/*! + * 界面视图模块 + */ + +layui.define(['laytpl', 'layer'], function(exports){ + var $ = layui.jquery + ,laytpl = layui.laytpl + ,layer = layui.layer + ,setter = layui.setter + ,device = layui.device() + ,hint = layui.hint() + + //对外接口 + ,view = function(id){ + return new Class(id); + } + + ,SHOW = 'layui-show', LAY_BODY = 'LAY_app_body' + + //构造器 + ,Class = function(id){ + this.id = id; + this.container = $('#'+(id || LAY_BODY)); + }; + + //加载中 + view.loading = function(elem){ + elem.append( + this.elemLoad = $('') + ); + }; + + //移除加载 + view.removeLoad = function(){ + this.elemLoad && this.elemLoad.remove(); + }; + + //清除 token,并跳转到登入页 + view.exit = function(){ + //清空本地记录的 token + layui.data(setter.tableName, { + key: setter.request.tokenName + ,remove: true + }); + + //跳转到登入页 + location.hash = '/user/login'; + }; + + //Ajax请求 + view.req = function(options){ + var that = this + ,success = options.success + ,error = options.error + ,request = setter.request + ,response = setter.response + ,debug = function(){ + return setter.debug + ? '
              URL:' + options.url + : ''; + }; + + options.data = options.data || {}; + options.headers = options.headers || {}; + + if(request.tokenName){ + var sendData = typeof options.data === 'string' + ? JSON.parse(options.data) + : options.data; + + //自动给参数传入默认 token + options.data[request.tokenName] = request.tokenName in sendData + ? options.data[request.tokenName] + : (layui.data(setter.tableName)[request.tokenName] || ''); + + //自动给 Request Headers 传入 token + options.headers[request.tokenName] = request.tokenName in options.headers + ? options.headers[request.tokenName] + : (layui.data(setter.tableName)[request.tokenName] || ''); + } + + delete options.success; + delete options.error; + + return $.ajax($.extend({ + type: 'get' + ,dataType: 'json' + ,success: function(res){ + var statusCode = response.statusCode; + + //只有 response 的 code 一切正常才执行 done + if(res[response.statusName] == statusCode.ok) { + typeof options.done === 'function' && options.done(res); + } + + //登录状态失效,清除本地 access_token,并强制跳转到登入页 + else if(res[response.statusName] == statusCode.logout){ + view.exit(); + } + + //其它异常 + else { + var errorText = [ + 'Error: ' + (res[response.msgName] || '返回状态码异常') + ,debug() + ].join(''); + view.error(errorText); + } + + //只要 http 状态码正常,无论 response 的 code 是否正常都执行 success + typeof success === 'function' && success(res); + } + ,error: function(e, code){ + var errorText = [ + '请求异常,请重试
              错误信息:'+ code + ,debug() + ].join(''); + view.error(errorText); + + typeof error === 'function' && error.apply(this, arguments); + } + }, options)); + }; + + //弹窗 + view.popup = function(options){ + var success = options.success + ,skin = options.skin; + + delete options.success; + delete options.skin; + + return layer.open($.extend({ + type: 1 + ,title: '提示' + ,content: '' + ,id: 'LAY-system-view-popup' + ,skin: 'layui-layer-admin' + (skin ? ' ' + skin : '') + ,shadeClose: true + ,closeBtn: false + ,success: function(layero, index){ + var elemClose = $(''); + layero.append(elemClose); + elemClose.on('click', function(){ + layer.close(index); + }); + typeof success === 'function' && success.apply(this, arguments); + } + }, options)) + }; + + //异常提示 + view.error = function(content, options){ + return view.popup($.extend({ + content: content + ,maxWidth: 300 + //,shade: 0.01 + ,offset: 't' + ,anim: 6 + ,id: 'LAY_adminError' + }, options)) + }; + + + //请求模板文件渲染 + Class.prototype.render = function(views, params){ + var that = this, router = layui.router(); + views = setter.views + views + setter.engine; + + $('#'+ LAY_BODY).children('.layadmin-loading').remove(); + view.loading(that.container); //loading + + //请求模板 + $.ajax({ + url: views + ,type: 'get' + ,dataType: 'html' + ,data: { + v: layui.cache.version + } + ,success: function(html){ + html = '
              ' + html + '
              '; + + var elemTitle = $(html).find('title') + ,title = elemTitle.text() || (html.match(/\([\s\S]*)\<\/title>/)||[])[1]; + + var res = { + title: title + ,body: html + }; + + elemTitle.remove(); + that.params = params || {}; //获取参数 + + if(that.then){ + that.then(res); + delete that.then; + } + + that.parse(html); + view.removeLoad(); + + if(that.done){ + that.done(res); + delete that.done; + } + + } + ,error: function(e){ + view.removeLoad(); + + if(that.render.isError){ + return view.error('请求视图文件异常,状态:'+ e.status); + }; + + if(e.status === 404){ + that.render('template/tips/404'); + } else { + that.render('template/tips/error'); + } + + that.render.isError = true; + } + }); + return that; + }; + + //解析模板 + Class.prototype.parse = function(html, refresh, callback){ + var that = this + ,isScriptTpl = typeof html === 'object' //是否模板元素 + ,elem = isScriptTpl ? html : $(html) + ,elemTemp = isScriptTpl ? html : elem.find('*[template]') + ,fn = function(options){ + var tpl = laytpl(options.dataElem.html()) + ,res = $.extend({ + params: router.params + }, options.res); + + options.dataElem.after(tpl.render(res)); + typeof callback === 'function' && callback(); + + try { + options.done && new Function('d', options.done)(res); + } catch(e){ + console.error(options.dataElem[0], '\n存在错误回调脚本\n\n', e) + } + } + ,router = layui.router(); + + elem.find('title').remove(); + that.container[refresh ? 'after' : 'html'](elem.children()); + + router.params = that.params || {}; + + //遍历模板区块 + for(var i = elemTemp.length; i > 0; i--){ + (function(){ + var dataElem = elemTemp.eq(i - 1) + ,layDone = dataElem.attr('lay-done') || dataElem.attr('lay-then') //获取回调 + ,url = laytpl(dataElem.attr('lay-url')|| '').render(router) //接口 url + ,data = laytpl(dataElem.attr('lay-data')|| '').render(router) //接口参数 + ,headers = laytpl(dataElem.attr('lay-headers')|| '').render(router); //接口请求的头信息 + + try { + data = new Function('return '+ data + ';')(); + } catch(e) { + hint.error('lay-data: ' + e.message); + data = {}; + }; + + try { + headers = new Function('return '+ headers + ';')(); + } catch(e) { + hint.error('lay-headers: ' + e.message); + headers = headers || {} + }; + + if(url){ + view.req({ + type: dataElem.attr('lay-type') || 'get' + ,url: url + ,data: data + ,dataType: 'json' + ,headers: headers + ,success: function(res){ + fn({ + dataElem: dataElem + ,res: res + ,done: layDone + }); + } + }); + } else { + fn({ + dataElem: dataElem + ,done: layDone + }); + } + }()); + } + + return that; + }; + + //直接渲染字符 + Class.prototype.send = function(views, data){ + var tpl = laytpl(views || this.container.html()).render(data || {}); + this.container.html(tpl); + return this; + }; + + //局部刷新模板 + Class.prototype.refresh = function(callback){ + var that = this + ,next = that.container.next() + ,templateid = next.attr('lay-templateid'); + + if(that.id != templateid) return that; + + that.parse(that.container, 'refresh', function(){ + that.container.siblings('[lay-templateid="'+ that.id +'"]:last').remove(); + typeof callback === 'function' && callback(); + }); + + return that; + }; + + //视图请求成功后的回调 + Class.prototype.then = function(callback){ + this.then = callback; + return this; + }; + + //视图渲染完毕后的回调 + Class.prototype.done = function(callback){ + this.done = callback; + return this; + }; + + //对外接口 + exports('view', view); +}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/style/admin.css b/iot-server/server-starter/src/main/webapp/assets/src/style/admin.css new file mode 100644 index 00000000..f0627bf7 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/style/admin.css @@ -0,0 +1,522 @@ + +/** + * admin.css + */ + +html #layuicss-layuiAdmin{display: none; position: absolute; width: 1989px;} + + +/* 系统 */ +::-webkit-input-placeholder{color: #ccc} + +/** 滚动条 **/ +/* +::-webkit-scrollbar{width: 10px; height: 10px;} +::-webkit-scrollbar-button:vertical{display: none;} +::-webkit-scrollbar-track, ::-webkit-scrollbar-corner{background-color: #e2e2e2;} +::-webkit-scrollbar-thumb{border-radius: 0; background-color: rgba(0,0,0,.3);} +::-webkit-scrollbar-thumb:vertical:hover{background-color: rgba(0,0,0,.35);} +::-webkit-scrollbar-thumb:vertical:active{background-color: rgba(0,0,0,.38);} +*/ + + +/* 全局 */ +html{background-color: #f2f2f2; color: #666;} +*[template], +.layadmin-tabsbody-item{display: none;} +*[lay-href], +*[lay-tips], +*[layadmin-event]{cursor: pointer;} + +/* 重置布局结构 */ +.layui-layout-admin .layui-header{position: fixed; top: 0; left: 0; width: 100%; height: 50px;} + +/* +.layui-layout-admin .layui-header .layui-layout-right .layui-nav-item a{color: #fff;} +.layui-layout-admin .layui-header .layui-layout-right .layui-nav-item a cite{color: rgba(255,255,255,.7);} +*/ + +.layui-layout-admin .layui-header .layui-nav .layui-nav-child a{color: #333;} +.layui-layout-admin .layui-side{width: 220px; top: 0; z-index: 1001;} +.layui-layout-admin .layui-logo, +.layui-layout-admin .layui-header .layui-nav .layui-nav-item{height: 50px; line-height: 50px;} +.layui-layout-admin .layui-logo{position: fixed; left: 0; top: 0; z-index: 1002; width: 220px; height: 49px; padding: 0 15px; box-sizing: border-box; overflow: hidden; font-weight: 300; background-repeat: no-repeat; background-position: center center;} +.layui-layout-admin .layui-layout-left, +.layadmin-pagetabs, +.layui-layout-admin .layui-body, +.layui-layout-admin .layui-footer{left: 220px;} +.layadmin-pagetabs{position: fixed; top: 50px; right: 0; z-index: 999;} +.layadmin-pagetabs .layui-breadcrumb{padding: 0 15px;} +.layui-layout-admin .layui-body{position: fixed; top: 90px; bottom: 0;} +.layui-layout-admin .layui-body .layadmin-tabsbody-item{position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow: hidden; overflow-y: auto;} +.layui-layout-admin .layui-header .layui-nav-img{width: 26px; height: 26px;} +.layui-layout-admin .layui-header .layui-nav-child{top: 55px;} +.layui-layout-admin .layui-header .layui-layout-right .layui-nav-child{left: auto; right: 0;} +.layui-layout-admin .layui-header .layui-nav .layui-nav-child dd.layui-this a, +.layui-layout-admin .layui-header .layui-nav .layui-nav-child dd.layui-this{background: none} + +/* 统一动画 */ +.layui-layout-admin .layui-header .layui-nav .layui-nav-item, +.layui-layout-admin .layui-layout-left, +.layadmin-pagetabs, +.layui-layout-admin .layui-body, +.layui-layout-admin .layui-footer, +.layui-layout-admin .layui-side, +.layui-layout-admin .layui-logo, +.layui-layout-admin .layui-header .layui-layout-right{transition: all .3s; -webkit-transition: all .3s;} + +/* 图标 */ +.layui-icon-login-qq{color: #3492ED;} +.layui-icon-login-wechat{color: #4DAF29;} +.layui-icon-login-weibo{color: #CF1900;} + +/* 重置表格风格 */ +/* +.layui-table th, +.layui-table td, +.layui-table[lay-skin="line"], +.layui-table[lay-skin="row"], +.layui-table-view, +.layui-table-header, +.layui-table-tool, +.layui-table-page, +.layui-table-fixed-r, +.layui-table-tips-main{border-color: #f6f6f6;} + +.layui-table thead tr, +.layui-table-header, +.layui-table-tool, +.layui-table-patch, +.layui-table-mend{background-color: #fff;} + +.layui-table[lay-even] tr:nth-child(even), +.layui-table tbody tr:hover, +.layui-table-hover, +.layui-table-click{background-color: #f8f8f8;} +*/ + +/* 表单 */ +.layui-form[wid100] .layui-form-label{width: 100px;} +.layui-form[wid100] .layui-input-block{margin-left: 130px;} +@media screen and (max-width: 450px){ + .layui-form[wid100] .layui-form-item .layui-input-inline{margin-left: 132px;} + .layui-form[wid100] .layui-form-item .layui-input-inline+.layui-form-mid{margin-left: 130px;} +} +.layui-form-item .layui-input-company{width: auto; padding-right: 10px; line-height: 38px;} + +/* 辅助 */ +.layadmin-flexible{} +.layui-bg-white{background-color: #fff;} +.layadmin-loading{position: absolute; left: 50%; top: 50%; margin: -16px -15px; font-size: 30px; color: #c2c2c2;} +.layadmin-fixed{position: fixed; left: 0; top: 0; z-index: 999;} +.layadmin-link{color: #029789!important;} +.layadmin-link:hover{opacity: 0.8;} + +/* 弹出面板 */ +.layui-layer-admin .layui-layer-title{height: 50px; line-height: 50px; border: none 0; background-color: #20222A; color: #fff;} +.layui-layer-admin i[close]{position: absolute; padding: 5px; right: 10px; top: 12px; color: #fff; cursor: pointer;} +.layui-layer-admin .layui-layer-content{padding: 20px; line-height: 22px;} +.layui-layer-admin .layui-layer-content cite{font-style: normal; color: #FF5722;} + +/* 右侧面板 */ +.layui-layer-adminRight{top: 50px !important; bottom: 0; box-shadow: 1px 1px 10px rgba(0,0,0,.1); border-radius: 0; overflow: auto;} + +/* 弹出便签 */ +.layadmin-note .layui-layer-content{padding: 0;} +.layadmin-note textarea{display: block; width: 300px; height: 132px; min-width: 300px; min-height: 132px; line-height: 20px; padding: 10px 20px; border: none; box-sizing: border-box; color: #666; word-wrap: break-word;} + +/* 头部导航 */ +.layui-layout-admin .layui-layout-left{padding: 0 10px;} +.layui-layout-admin .layui-layout-left .layui-nav-item{margin: 0 20px;} +.layui-layout-admin .layui-input-search{display: inline-block; vertical-align: middle; height: 32px; border: none; cursor: text;} +.layui-layout-admin .layui-layout-left a{padding: 0;} +.layui-layout-admin .layui-layout-right{padding: 0;} +.layui-header .layui-nav-item:hover{} +.layui-header .layui-layout-right .layui-badge-dot{margin-left: 0px;} +.layui-header .layui-nav .layui-this:after, +.layui-layout-admin .layui-header .layui-nav-bar{top: 0 !important; bottom: auto; height: 3px; background-color: #fff; background-color: rgba(255,255,255,.3);} + +/* 遮罩 */ +.layadmin-body-shade{position: fixed; display: none; left: 0; right: 0; top: 0; bottom: 0; background-color: rgba(0,0,0,.3); z-index: 1000;} + +/* 侧边菜单 */ +.layui-side-menu .layui-side-scroll{width: 240px;} +.layui-side-menu .layui-nav{width: 220px; margin-top: 50px; background: none;} +.layui-side-menu .layui-nav .layui-nav-item a{padding-left: 45px; padding-right: 30px;} +.layui-side-menu .layui-nav .layui-nav-item a:hover{background: none;} +.layui-side-menu .layui-nav .layui-nav-itemed > .layui-nav-child{padding: 5px 0;} +.layui-side-menu .layui-nav>.layui-nav-item .layui-icon:first-child{position: absolute; top: 50%; left: 20px; margin-top: -19px;} +.layui-side-menu .layui-nav .layui-nav-child .layui-nav-child{background: none!important;} +.layui-side-menu .layui-nav .layui-nav-child .layui-nav-child a{padding-left: 60px} + +/* 侧边菜单 - 平板移动设备 */ +@media screen and (max-width: 992px) { + .layui-layout-admin .layui-side{transform: translate3d(-220px, 0, 0); -webkit-transform: translate3d(-220px, 0, 0); width: 220px;} + .layui-layout-admin .layui-layout-left, + .layadmin-pagetabs, + .layui-layout-admin .layui-body, + .layui-layout-admin .layui-footer{left: 0;} +} + +/* 侧边收缩模式 */ +.layadmin-side-shrink .layui-layout-admin .layui-logo{width: 60px; background-image: url(res/logo.png); /*background-size: 20px;)*/} +.layadmin-side-shrink .layui-layout-admin .layui-logo span{display: none;} +.layadmin-side-shrink .layui-side{left: 0; width: 60px;} +.layadmin-side-shrink .layui-layout-admin .layui-layout-left, +.layadmin-side-shrink .layadmin-pagetabs, +.layadmin-side-shrink .layui-layout-admin .layui-body, +.layadmin-side-shrink .layui-layout-admin .layui-footer{left: 60px;} +.layadmin-side-shrink .layui-side-menu .layui-nav{position: static; width: 60px;} +.layadmin-side-shrink .layui-side-menu .layui-nav-item{position: static;} +.layadmin-side-shrink .layui-side-menu .layui-nav-item>a{padding-right: 0;} +.layadmin-side-shrink .layui-side-menu .layui-nav-item cite, +.layadmin-side-shrink .layui-side-menu .layui-nav > .layui-nav-item > a .layui-nav-more, +.layadmin-side-shrink .layui-side-menu .layui-nav > .layui-nav-item > .layui-nav-child{display: none; padding: 8px 0; width: 200px;} +.layadmin-side-shrink .layui-side-menu .layui-nav > .layui-nav-itemed>a{background: rgba(0,0,0,.3);} + +/* 移动端展开模式 */ +.layadmin-side-spread-sm .layui-layout-admin .layui-layout-left, +.layadmin-side-spread-sm .layadmin-pagetabs, +.layadmin-side-spread-sm .layui-layout-admin .layui-body, +.layadmin-side-spread-sm .layui-layout-admin .layui-footer{left: 0; transform: translate3d(220px, 0, 0); -webkit-transform: translate3d(220px, 0, 0);} +.layadmin-side-spread-sm .layui-layout-admin .layui-layout-right{transform: translate3d(220px, 0, 0); -webkit-transform: translate3d(220px, 0, 0);} +.layadmin-side-spread-sm .layui-side{transform: translate3d(0, 0, 0); -webkit-transform: translate3d(0, 0, 0);} +.layadmin-side-spread-sm .layadmin-body-shade{display: block; } + + +/* 页面标签 */ +.layadmin-pagetabs{height: 40px; line-height: 40px; padding: 0 80px 0 40px; /*border-bottom: 2px solid #292B34;*/ background-color: #fff; box-sizing: border-box; box-shadow: 0 1px 2px 0 rgba(0,0,0,.1);} +.layadmin-pagetabs .layadmin-tabs-control{position: absolute; top: 0; width: 40px; height: 100%; text-align: center; cursor: pointer; transition: all .3s; -webkit-transition: all .3s; box-sizing: border-box; border-left: 1px solid #f6f6f6;} +.layadmin-pagetabs .layadmin-tabs-control:hover{background-color: #f6f6f6;} +.layadmin-pagetabs .layui-icon-prev{left: 0; border-left: none; border-right: 1px solid #f6f6f6;} +.layadmin-pagetabs .layui-icon-next{right: 40px; right: 40px;} +.layadmin-pagetabs .layui-icon-down{right: 0;} +.layadmin-tabs-select.layui-nav{position: absolute; left: 0; top: 0; width: 100%; height: 100%; padding: 0; background: none;} +.layadmin-tabs-select.layui-nav .layui-nav-item{line-height: 40px;} +.layadmin-tabs-select.layui-nav .layui-nav-item>a{height: 40px;} +.layadmin-tabs-select.layui-nav .layui-nav-item a{color: #666;} +.layadmin-tabs-select.layui-nav .layui-nav-child{top: 40px; left: auto; right: 0;} +.layadmin-tabs-select.layui-nav .layui-nav-child dd.layui-this, +.layadmin-tabs-select.layui-nav .layui-nav-child dd.layui-this a{background-color: #f2f2f2!important; color: #333;} +.layadmin-tabs-select.layui-nav .layui-nav-more, +.layadmin-tabs-select.layui-nav .layui-nav-bar{display: none;} + +.layadmin-pagetabs .layui-tab{margin: 0; overflow: hidden;} +.layadmin-pagetabs .layui-tab-title{height: 40px; border: none;} +.layadmin-pagetabs .layui-tab-title li{min-width: 0; line-height: 40px; max-width: 160px; text-overflow: ellipsis; padding-right: 40px; overflow: hidden; border-right: 1px solid #f6f6f6; vertical-align: top;} +.layadmin-pagetabs .layui-tab-title li:first-child{ padding-right: 15px;} +.layadmin-pagetabs .layui-tab-title li:first-child .layui-tab-close{display: none;} +.layadmin-pagetabs .layui-tab-title li .layui-tab-close{position: absolute; right: 8px; top: 50%; margin: -7px 0 0 0; width: 16px; height: 16px; line-height: 16px; border-radius: 50%; font-size: 12px;} +.layadmin-pagetabs .layui-tab-title li:after{content:''; position: absolute; top: 0; left: 0; width: 0; height: 2px; border-radius: 0; background-color: #292B34; transition: all .3s; -webkit-transition: all .3s;} +.layadmin-pagetabs .layui-tab-title li:hover:after{width: 100%;} +.layadmin-pagetabs .layui-tab-title li:hover, +.layadmin-pagetabs .layui-tab-title li.layui-this{background-color: #f6f6f6;} +.layadmin-pagetabs .layui-tab-title li.layui-this:after{width: 100%; border: none; height: 2px; background-color: #292B34;} + +/* 不开启页面标签时 */ +.layadmin-tabspage-none .layui-layout-admin .layui-header{border-bottom: none; box-shadow: 0 1px 2px 0 rgba(0,0,0,.05);} +.layadmin-tabspage-none .layui-layout-admin .layui-body{top: 50px;} +.layadmin-tabspage-none .layadmin-header{display: block;} +.layadmin-tabspage-none .layadmin-header .layui-breadcrumb{border-top: 1px solid #f6f6f6;} + +/* 底部固定区域 */ +.layui-layout-admin .layui-footer{padding: 10px 0; text-align: center;} + +/* 默认主题修饰 */ +.layui-layout-admin .layui-header{border-bottom: 1px solid #f6f6f6; box-sizing: border-box; background-color: #fff;} +.layui-layout-admin .layui-header a, +.layui-layout-admin .layui-header a cite{color: #333;} +.layui-layout-admin .layui-header a:hover{color: #000;} +.layui-layout-admin .layui-header .layui-nav .layui-nav-more{border-top-color: #666} +.layui-layout-admin .layui-header .layui-nav .layui-nav-mored{border-color: transparent; border-bottom-color: #666;} +.layui-layout-admin .layui-header .layui-nav .layui-this:after, +.layui-layout-admin .layui-header .layui-nav-bar{height: 2px; background-color: #20222A} +.layui-layout-admin .layui-logo{background-color: #20222A; box-shadow: 0 1px 2px 0 rgba(0,0,0,.15);} +.layui-layout-admin .layui-logo, +.layui-layout-admin .layui-logo a{color: #fff; color: rgba(255,255,255,.8)} +.layui-side-menu{box-shadow: 1px 0 2px 0 rgba(0,0,0,.05);} +.layui-layout-admin .layui-footer{box-shadow: 0 -1px 2px 0 rgba(0,0,0,.05);} + +.layui-side-menu, +.layadmin-setTheme-side{background-color: #20222A; color: #fff;} +.layadmin-setTheme-header{background-color: #fff;} + +.layui-layout-admin .layui-footer{background-color: #fff;} +.layui-tab-admin .layui-tab-title{background-color: #393D49; color: #fff;} + + +/* + + 格局 + +*/ + +.layui-fluid{padding: 15px;} +.layadmin-header{display: none; height: 50px; line-height: 50px; margin-bottom: 0; border-radius: 0;} +.layadmin-header .layui-breadcrumb{padding: 0 15px;} +.layui-card-header{position: relative;} +.layui-card-header .layui-icon{line-height: initial; position: absolute; right: 15px; top: 50%; margin-top: -7px;} +.layadmin-iframe{position: absolute; width: 100%; height: 100%; left: 0; top: 0; right: 0; bottom: 0;} + + +/* + + 控制台 + +*/ + + +/* 重置轮播样式 */ +.layadmin-carousel{height: 185px !important; background-color: #fff;} +.layadmin-carousel .layui-carousel-ind li{background-color: #e2e2e2;} +.layadmin-carousel .layui-carousel-ind li:hover{background-color: #c2c2c2;} +.layadmin-carousel .layui-carousel-ind li.layui-this{background-color: #999;} +.layadmin-carousel .layui-carousel, +.layadmin-carousel > *[carousel-item] > *{background-color: #fff;} +.layadmin-carousel .layui-col-space10{margin: 0;} +.layadmin-carousel .layui-carousel-ind{position: absolute; top: -41px; text-align: right;} +.layadmin-carousel .layui-carousel-ind ul{background: none;} + +/* 重置tab样式 */ +.layui-card .layui-tab-brief .layui-tab-title{height: 42px; border-bottom-color: #f6f6f6;} +.layui-card .layui-tab-brief .layui-tab-title li{margin: 0 15px; padding: 0; line-height: 42px;} +.layui-card .layui-tab-brief .layui-tab-title li.layui-this{color: #333;} +.layui-card .layui-tab-brief .layui-tab-title .layui-this:after{height: 43px;} +.layui-card .layui-tab-brief .layui-tab-content{padding: 15px;} +.layui-card .layui-table-view{margin: 0;} + +/* 快捷方式 */ +.layadmin-shortcut li{text-align: center;} +.layadmin-shortcut li .layui-icon{display: inline-block; width: 100%; height: 60px; line-height: 60px; text-align: center; border-radius: 2px; font-size: 30px; background-color: #F8F8F8; color: #333; transition: all .3s; -webkit-transition: all .3s;} +.layadmin-shortcut li cite{position: relative; top: 2px; display: block; color: #666; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; font-size: 14px;} +.layadmin-shortcut li:hover .layui-icon{background-color: #f2f2f2;} + +/* 待办事项 */ +.layadmin-backlog .layadmin-backlog-body{display: block; padding: 10px 15px; background-color: #f8f8f8; color: #999; border-radius: 2px; transition: all .3s; -webkit-transition: all .3s;} +.layadmin-backlog-body h3{padding-bottom: 10px; font-size: 12px;} +.layadmin-backlog-body p cite{font-style: normal; font-size: 30px; font-weight: 300; color: #009688;} +.layadmin-backlog-body:hover{background-color: #f2f2f2; color: #888;} + +/* 版本信息 */ +.layadmin-version .layui-table{padding: 6px 0;} +.layadmin-version .layui-table td, +.layadmin-version .layui-table th{line-height: 25px;} + +/* 数据概览 */ +.layadmin-dataview{height: 332px !important;} +.layadmin-dataview>*[carousel-item]:before{display: none;} +.layadmin-dataview>*[carousel-item]>div{height: 332px;} + +/* 控制台效果报告 */ +.layadmin-takerates{padding-top: 5px;} +.layadmin-takerates .layui-progress{margin: 50px 0 60px;} +.layadmin-takerates .layui-progress:last-child{margin-bottom: 10px;} +.layadmin-takerates .layui-progress h3{position: absolute; right: 0; top: -35px; color: #999; font-size: 14px;} +.layadmin-takerates .layui-progress-bar{text-align: left;} +.layadmin-takerates .layui-progress-text{top: -35px; line-height: 26px; font-size: 26px;} + +/* 产品动态 */ +.layadmin-news{height: 60px !important; padding: 5px 0;} +.layadmin-news a{display: block; line-height: 60px; text-align: center;} +.layadmin-news .layui-carousel-ind{height: 45px;} + +/* 文字列表 */ +.layadmin-list li{margin-bottom: 6px; padding-bottom: 6px; border-bottom-color: #f6f6f6; list-style-position: inside; list-style-type: disc;} +.layadmin-list li{text-overflow: ellipsis; overflow: hidden; white-space: nowrap;} +.layadmin-list li a{color: #666;} +.layadmin-list li a:hover{color: #009688;} +.layadmin-list li:last-child{border: none; padding: 0; margin: 0;} + +/* 文本区域 */ +.layadmin-text p{margin-bottom: 10px; text-indent: 2em;} +.layadmin-text p:last-child{margin: 0;} +.layadmin-font-em{font-size: 13px; color: #758697;} + + + + +/******************************** + + 其它主页开始 + +*******************************/ + +/* 主页示例一 */ +/* 进行中的项目 */ +.layui-card-header .layui-a-tips{position: absolute; right: 15px; color: #01AAED;} +.layuiadmin-card-text{background-color: #f8f8f8; color: #777; padding: 24px;} +.layuiadmin-card-text .layui-text-top{padding-bottom: 10px;} +.layuiadmin-card-text .layui-text-top i{margin-right: 10px; font-size: 24px; color: #009688;} +.layuiadmin-card-text .layui-text-top a{line-height: 24px; font-size: 16px; vertical-align: top;} +.layuiadmin-card-text .layui-text-center{height: 44px; line-height: 22px; margin-bottom: 10px; overflow: hidden;} +.layuiadmin-card-text .layui-text-bottom{position: relative;} +.layuiadmin-card-text .layui-text-bottom a{color: #777; font-size: 12px; text-overflow: ellipsis; word-break: break-all;} +.layuiadmin-card-text .layui-text-bottom span{color: #CCC; font-size: 12px; position: absolute; right: 0;} +.layuiadmin-card-text a:hover, +.layuiadmin-card-link a:hover, +.layuiadmin-card-team li a:hover{color: #01AAED; transition: all 300ms;} + +/* 动态 */ +.layuiadmin-card-status{padding: 0 10px 10px 10px;} +.layuiadmin-card-status dd{padding: 15px 0; border-bottom: 1px solid #EEE; display: -webkit-flex; display: flex;} +.layuiadmin-card-status dd:last-child{border: none;} +.layuiadmin-card-status dd div.layui-status-img, +.layuiadmin-card-team .layui-team-img{width: 32px; height: 32px; border-radius: 50%; background-color: #009688; margin-right: 15px;} +.layuiadmin-card-status dd div.layui-status-img a{width: 100%; height: 100%; display: inline-block; text-align: center; line-height: 32px;} +.layuiadmin-card-status dd div.layui-status-img img, +.layuiadmin-card-team .layui-team-img img{width: 50%; height: 50%;} +.layuiadmin-card-status dd div a{color: #01AAED;} +.layuiadmin-card-status dd div span{color: #BBB;} + +/* 便捷导航 */ +.layuiadmin-card-link{padding-left: 10px; font-size: 0} +.layuiadmin-card-link a{display: inline-block; width: 25%; color: #666; font-size: 14px; margin-bottom: 12px;} +.layuiadmin-card-link button{vertical-align: top;} +.layuiadmin-card-link button:hover{color: #009688;} + +/* 团队 */ +.layuiadmin-card-team li{padding: 10px 0 10px 10px;} +.layuiadmin-card-team .layui-team-img{display: inline-block; margin-right: 8px; width: 24px; height: 24px; text-align: center; line-height: 24px;} +.layuiadmin-card-team span{color: #777;} + + +/* 主页示例二 */ +.layuiadmin-badge{position: absolute; top: 50%; margin-top: -9px; right: 15px; color: #01AAED; } +.layuiadmin-card-list{padding: 15px;} +.layuiadmin-card-list p.layuiadmin-big-font{font-size: 36px; color: #666; line-height: 36px; padding: 5px 0 10px; overflow: hidden; text-overflow: ellipsis; word-break: break-all; white-space: nowrap;} +.layuiadmin-card-list p.layuiadmin-normal-font{padding-bottom: 10px; font-size: 20px; color: #666; line-height: 24px;} +.layuiadmin-span-color{font-size: 14px; position: absolute; right: 15px;} +.layuiadmin-span-color i{padding-left: 5px;} +.layuiadmin-btn-group{position: absolute; right: 15px;} + +.layuiadmin-card-status li{position: relative; padding: 10px 0; border-bottom: 1px solid #EEE;} +.layuiadmin-card-status li h3{padding-bottom: 5px; font-weight: 700;} +.layuiadmin-card-status li p{padding-bottom: 10px;} +.layuiadmin-card-status li>span{color: #999;} +.layuiadmin-home2-usernote .layuiadmin-reply{display: none; position: absolute; right: 0; bottom: 12px;} +.layuiadmin-home2-usernote li:hover .layuiadmin-reply{display: block;} + +.layuiadmin-page-table td span{color: #2F4056;} +.layuiadmin-page-table td span.first{color: #FF5722;} +.layuiadmin-page-table td span.second{color: #FFB800;} +.layuiadmin-page-table td span.third{color: #5FB878;} + + +/****** 其它主页结束 ******/ + + + + +/* + + 应用 + +*/ + + +/* 消息中心 */ +.layuiAdmin-msg-detail h1{font-size: 16px;} +.layuiAdmin-msg-detail .layui-card-header{height: auto; line-height: 30px; padding: 15px;} +.layuiAdmin-msg-detail .layui-card-header span{padding: 0 5px; color: #999;} +.layuiAdmin-msg-detail .layui-card-header span:first-child{padding-left: 0;} +.layuiAdmin-msg-detail .layui-card-body{padding: 15px;} + +/* 文章列表 */ +.layuiadmin-content-bread{padding-bottom: 20px;} + +/* 进度条样式 */ +.layuiadmin-order-progress{position: relative; top: 12px;} + + + + +/* + + 系统 + +*/ + + +/* 头部图标重置 */ +.layui-card-header.layuiadmin-card-header-auto{padding-top: 15px; padding-bottom: 15px; height: auto;} +.layuiadmin-card-header-auto i.layuiadmin-button-btn{position: relative; right: 0; top: 0; vertical-align: middle;} +.layuiadmin-card-header-auto .layui-form-item:last-child{margin-bottom: 0;} + + +/* 主题设置 */ +.layadmin-setTheme{padding: 15px; overflow-x: hidden;} +.layadmin-setTheme>h5{padding: 20px 0 10px; color: #000;} +.layadmin-setTheme>h5:first-child{padding-top: 0;} +.layadmin-setTheme-color{width: 330px; font-size: 0;} +.layadmin-setTheme-color li{position: relative; display: inline-block; vertical-align: top; width: 80px; height: 50px; margin: 0 15px 15px 0; background-color: #f2f2f2; cursor: pointer; font-size: 12px; color: #666;} +.layadmin-setTheme-color li:after{content: ''; position: absolute; z-index: 20; top: 50%; left: 50%; width: 1px; height: 0; border: 1px solid #f2f2f2; transition: all .3s; -webkit-transition: all .3s; opacity: 0;} +.layadmin-setTheme-color li.layui-this:after, +.layadmin-setTheme-color li:hover:after{width: 100%; height: 100%; padding: 4px; top: -5px; left: -5px; border-color: #5FB878; opacity: 1;} + +.layadmin-setTheme-header{position: relative; z-index: 10; height: 10px; border-top: 1px solid #f2f2f2; border-right: 1px solid #f2f2f2;} +.layadmin-setTheme-side{position: absolute; left: 0; top: 0; width: 20px; height: 100%; z-index: 11; box-shadow: 1px 0 2px 0 rgba(0,0,0,.05);} +.layadmin-setTheme-logo{position: absolute; left: 0; top: 0; width: 100%; height: 10px; box-shadow: 0 1px 2px 0 rgba(0,0,0,.15);} +.layadmin-form-right{text-align: right;} + + +/* 关于 */ +.layadmin-about p{margin-bottom: 10px;} + +/* 菜单列表 */ +.layadmin-menu-list .layui-card-header{height: 50px; line-height: 50px; font-size: 16px;} +.layadmin-menu-list .layui-card-header:active{background-color: #f2f2f2;} +.layadmin-menu-list .layui-card-header .layui-icon{position: relative; top: 1px; left: 0; display: inline-block; margin: 0 10px 0; font-size: 18px;} + + +/* 动画 */ +@-webkit-keyframes layui-rl{ /* 从右往左滑入 */ + from {-webkit-transform: translate3d(100%, 0, 0);} + to {-webkit-transform: translate3d(0, 0, 0);} +} +@keyframes layui-rl{ + from {transform: translate3d(100%, 0, 0);} + to {transform: translate3d(0, 0, 0);} +} +.layui-anim-rl{-webkit-animation-name: layui-rl; animation-name: layui-rl;} + +@-webkit-keyframes layui-lr{ /* 从右往左滑入 */ + from {-webkit-transform: translate3d(0 0, 0); opacity: 1;} + to {-webkit-transform: translate3d(100%, 0, 0); opacity: 1;} +} +@keyframes layui-lr{ + from {transform: translate3d(0, 0, 0);} + to {transform: translate3d(100%, 0, 0);} +} +.layui-anim-lr{-webkit-animation-name: layui-lr; animation-name: layui-lr;} + +.layui-anim-rl.layer-anim-close{-webkit-animation-name: layui-lr; animation-name: layui-lr;} + + +/* 提示页 */ +.layadmin-tips{margin-top: 30px; text-align: center;} +.layadmin-tips .layui-icon[face]{display: inline-block; font-size: 300px; color: #393D49;} +.layadmin-tips .layui-text{width: 500px; margin: 30px auto; padding-top: 20px; border-top: 5px solid #009688; font-size: 16px;} +.layadmin-tips h1{font-size: 100px; line-height: 100px; color: #009688;} +.layadmin-tips .layui-text .layui-anim{display: inline-block;} + + +/* + + 响应式补充 + +*/ + +@media screen and (max-width: 768px) { + + /* 产品清单模板 */ + .layadmin-panel-selection{margin: 0; width: auto;} + + /* 导航 */ + .layui-body .layui-nav .layui-nav-item{display: block;} + + /* 主体容器 */ + .layui-layout-admin .layui-body .layadmin-tabsbody-item{-webkit-overflow-scrolling: touch; overflow: auto;} +} + + + diff --git a/iot-server/server-starter/src/main/webapp/assets/src/style/login.css b/iot-server/server-starter/src/main/webapp/assets/src/style/login.css new file mode 100644 index 00000000..a666b4bb --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/style/login.css @@ -0,0 +1,51 @@ + +/** + * admin.login.css + */ + +html,body,#LAY_app{height:100%;} +.layui-layout-body{overflow: auto;} + +#LAY-user-login, +.layadmin-user-display-show{display: block !important;} +.layadmin-user-login{position: relative; left: 0; top: 0; padding: 110px 0; min-height: 100%; box-sizing: border-box;} +.layadmin-user-login-main{width: 375px; margin: 0 auto; box-sizing: border-box;} +.layadmin-user-login-box{padding: 20px;} +.layadmin-user-login-header{text-align: center;} +.layadmin-user-login-header h2{margin-bottom: 10px; font-weight: 300; font-size: 30px; color: #000;} +.layadmin-user-login-header p{font-weight: 300; color: #999;} + +.layadmin-user-login-body .layui-form-item{position: relative;} +.layadmin-user-login-icon{position: absolute; left: 1px; top: 1px; width: 38px; line-height: 36px; text-align: center; color: #d2d2d2;} +.layadmin-user-login-body .layui-form-item .layui-input{padding-left: 38px;} +.layadmin-user-login-codeimg{max-height: 38px; width: 100%; cursor: pointer; box-sizing: border-box;} + +.layadmin-user-login-other{position: relative; font-size: 0; line-height: 38px; padding-top: 20px;} +.layadmin-user-login-other>*{display: inline-block; vertical-align: middle; margin-right: 10px; font-size: 14px;} +.layadmin-user-login-other .layui-icon{position: relative; top: 2px; font-size: 26px;} +.layadmin-user-login-other a:hover{opacity: 0.8;} + +.layadmin-user-jump-change{float: right;} + +.layadmin-user-login-footer{position: absolute; left: 0; bottom: 0; width: 100%; line-height: 30px; padding: 20px; text-align: center; box-sizing: border-box; color: rgba(0,0,0,.5)} +.layadmin-user-login-footer span{padding: 0 5px;} +.layadmin-user-login-footer a{padding: 0 5px; color: rgba(0,0,0,.5);} +.layadmin-user-login-footer a:hover{color: rgba(0,0,0,1);} + +/* 有背景图时 */ +.layadmin-user-login-main[bgimg]{background-color: #fff; box-shadow: 0 0 5px rgba(0,0,0,0.05);} + +/* 主题背景 */ +.ladmin-user-login-theme{position: fixed; bottom: 0; left: 0; width: 100%; text-align: center;} +.ladmin-user-login-theme ul{display: inline-block; padding: 5px; background-color: #fff;} +.ladmin-user-login-theme ul li{display: inline-block; vertical-align: top; width: 64px; height: 43px; cursor: pointer; transition: all .3s; -webkit-transition: all .3s; background-color: #f2f2f2;} +.ladmin-user-login-theme ul li:hover{opacity: 0.9} + +@media screen and (max-width: 768px) { + .layadmin-user-login{padding-top: 60px;} + .layadmin-user-login-main{width: 300px;} + .layadmin-user-login-box{padding: 10px;} +} + + + diff --git a/iot-server/server-starter/src/main/webapp/assets/src/style/res/bg-none.jpg b/iot-server/server-starter/src/main/webapp/assets/src/style/res/bg-none.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b7c9e7b864d9354ae00404bb74f1e144ab57e03b GIT binary patch literal 832 zcmex=76T7ZFOwj%ATaE{cASwgX5%^7Y|PA-aBzk}8jk@^fh}&{hLSo* zQZ@@t1{wl#DNZ;Zwm-mu+Vl>Q_HtgT*9|CH2iZ&kqzz#o5}<- z^#Yj5j9@Y`vDq^@LqriwMn<6MsZ(iN6OA^_TpQuDW?6Qau(sx`t1Z{osD%ZauI8LN zXOKo}2X-UI-(5y<5L literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/style/res/layui-logo.jpg b/iot-server/server-starter/src/main/webapp/assets/src/style/res/layui-logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..da24fdfc9a047daea9128a967bc13a3766aea200 GIT binary patch literal 2871 zcmds%X;hN=8o*yfvD^ulO4PE&%<(#|xr8*;xTI*Nv}mIfnyD$K=7y$C-LlldYi_v& zR~aq_w?a@xL@vl-t(UGJm>kpzvuTpAO6yA z=>VW{$jQ|S0D(Y2oa_OlJm3HTk(ZZOkcTKJK-NQKuktzwWSz2#l9IBLl8T1PAEBY5 zrmmr`rUHX$YQkV}U0q%HmM`%c0#Z~|R8>*ksG+fOvldiq^Oxp-nn<4j&~+dP2m%H{ z0XZlL3vPxc2 zR{uHoGZ*TmumQH!9P-1dY%Lj;@|3N)ZT}I>C2hm)R?&k~rP3ZiMW!JK1w#QOuw1xx z-xufqgJgY?UIFoho1a!S9QKGEI*LYZqICCGIO$_{Umq>+q6SWUdT^mu5`kJGrBOsa z?z@^Jl8y=9XMRXN>|=59+Y2DxopWRbxGWXov=`@6!bGoaj3Q1+ZYB~I6IXnTJL)T{ z6Z-v}1kN|yoXQ?n#^AkGuD)UOT*>#1N9+6@;ybm;(FOaTV1}S!CXA((&w_4j5(}X{A+U2kZn-hQL|rgMpLhigR+16CJlfTB*W?OEKdcBV_(+b zP5cNC7>0YfRrNJKJ$~5Q@iOi%yc8(oygz?(uj6D^ytw(J@cUG36Cr6Xv7HnqwD;Dd zj&F-sM@+}g#&?D>aF$DE5ooj*b~4piL)yz%TIYB{Iw3#FtX5R_;nZ==Qm!_*X|Tn;@pGYh0<;5wr7jspCY(=oL=K7yN7K?s_3GT^heB^&NRK?I{h5a zaIR2d(vN+X=)=#u+>B1)d+AGob%7C~^hyrb@^MNPJ_BVA%{`y?^zd5S?(p_=;UYw8 znGyHaZahAoR@2vV3|YP7h=$^x$iwEonf@=la&#_n42rfhD+WJC@+xaF@IEsDQ0s{Z zCZSTk(-|xj;GZuryGybuwr=s|yN9eMX}A^MgQ&^LUZf~M`*_o!&@naR^~#noYu{f{ zl3D*q#4YyB6`0+few;PoJ zP#*85#D)+cxYl%g+sTQ38`GCUYsXE^a#ww1kbclV)}ny*4h}kW?$4y4zMUyvugHX| zr2QX<(}sSgs3QFpC(M#()u`jo;ZZ1jn15HNYQb4fh9>S)b?k#d$c0v=hxL_h5DUS(_xbZRK0lTSN-=yRU_P`14$-c&LhOjPLDYk0R;nN!Any8yz>|}krs!o z^G6V^H@pZ106nX@4{tGb7X${y-6vYm3~coj@p1$r6dRmDqh;501nBhR^X*ovq(E3$ z<{mSY^g;`pb%qd<3o{n{<_u#j^XvK4NJ#gFbRsj+Bc_L6}-P`y2Nnd6B(g!su{4 zLJPLH2x*lnw9HU#`FcN)tei!&)0blR;0ckJ+lh}>$iCRVwn;7%pF1a(-F){1pHHXJ zX%Az4ja$4K{|1paFsK~oqo#9;XH^q^K1!8Th>}WcaHz*qwa~B5E?Fl6B;#`#emO__GG)C zRz+^QR?H1WwA^6;{f1!YC?I$`8I?<7R71RzpI;5`rm15{Rwx|%5SiX3{b5^>`?6xp&Ji+P}JoHzSf`ms{oDt LmH+Q&(s#cDsUr%7 literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/style/res/logo-black.png b/iot-server/server-starter/src/main/webapp/assets/src/style/res/logo-black.png new file mode 100644 index 0000000000000000000000000000000000000000..73e5ebcb43833eeb621ff764dc7e44323c9afe10 GIT binary patch literal 455 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~q!3HGX7W?Z1DVAa<&kznEsNqQI0P;BtJR*x3 z7=(O5nDO)UBg=t;VkNE-CC){ui6xo&c?uz!xv30>hWbX9`iACTwud+YRmgx;1m~xf zlqVLYGB~E>C#5R5WfrBD=NDxcD>w(6z1XvIwhi*x%GkhWbX9`iACTwud+YRmgx;1m~xf zlqVLYGB~E>C#5R5WfrBD=NDxcD>w(6z1Xv?mq)LJVQ&Orvhh3ZhBjJwL{si@i8$Z~hZfH6NoY=UdxG=(8f}dx% z_2%ldXJ^60g?*18$|4;XJS`KiBE zP^;Mbm-T|g=Ve?zOF2#{gdNR$^iinwM)`p_p9$`fza4ayELhkM@D;Fx{Arb3@buj6 zXVt~~qEFvp%WIezUgCPGyY7R|%E5ZPMa}8-t3p_tY z``aAc)A=}%`4wlAYjl6(8WjtMYm2)ZlZ@m}-}uo`n;@XFmMQ#zo6_yck!&@AFSa~; u)bDs{X{bSo?#XMB;jRpJjpgF&>zVIg*(;naCF>3hR0dC1KbLh*2~7ZTNv#_I literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/style/res/template/character.jpg b/iot-server/server-starter/src/main/webapp/assets/src/style/res/template/character.jpg new file mode 100644 index 0000000000000000000000000000000000000000..33c7691aa62991324afeed6acfd220e0b3ae4e85 GIT binary patch literal 6727 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 YMAsk3Colp2V*^C?oswj!xbcVo13N#e{r~^~ literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/style/res/template/portrait.png b/iot-server/server-starter/src/main/webapp/assets/src/style/res/template/portrait.png new file mode 100644 index 0000000000000000000000000000000000000000..33c7691aa62991324afeed6acfd220e0b3ae4e85 GIT binary patch literal 6727 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评论管理 + + + +
              +
              +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              +
              +
              +
              +
              + +
              +
              + +
              +
              +
              + + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/contform.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/contform.html new file mode 100644 index 00000000..fc24c49e --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/contform.html @@ -0,0 +1,20 @@ + + +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/list.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/list.html new file mode 100644 index 00000000..126882cb --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/list.html @@ -0,0 +1,151 @@ + + + 文章列表 + +
              + +
              + +
              +
              +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              +
              +
              + +
              +
              + + +
              +
              + + +
              +
              +
              + + diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/listform.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/listform.html new file mode 100644 index 00000000..c916f443 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/listform.html @@ -0,0 +1,67 @@ +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              + +
              + +
              + +
              +
              +
              diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/tags.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/tags.html new file mode 100644 index 00000000..ad15f3fa --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/tags.html @@ -0,0 +1,65 @@ +分类管理 + + + +
              +
              +
              + +
              +
              +
              + +
              +
              +
              + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/tagsform.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/tagsform.html new file mode 100644 index 00000000..bdd5521c --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/tagsform.html @@ -0,0 +1,17 @@ +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/list.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/list.html new file mode 100644 index 00000000..ad817aaa --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/list.html @@ -0,0 +1,124 @@ +帖子列表 + + + +
              +
              +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              +
              +
              + +
              +
              + +
              +
              + + + +
              +
              +
              + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/listform.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/listform.html new file mode 100644 index 00000000..95be57fa --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/listform.html @@ -0,0 +1,53 @@ +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              + +
              +
              + +
              + +
              +
              +
              + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/replys.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/replys.html new file mode 100644 index 00000000..3e3fa07c --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/replys.html @@ -0,0 +1,99 @@ + + +回帖列表 + + + +
              +
              +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              +
              +
              +
              +
              + +
              +
              + + +
              +
              +
              + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/replysform.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/replysform.html new file mode 100644 index 00000000..08c45b60 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/replysform.html @@ -0,0 +1,34 @@ +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/message/detail.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/message/detail.html new file mode 100644 index 00000000..59a34432 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/app/message/detail.html @@ -0,0 +1,42 @@ +消息详情 + + + +
              +
              +
              +
              +

              {{ d.data.title }}

              +

              + {{ layui.util.timeAgo(d.data.time) }} +

              +
              +
              +
              + {{ d.data.content }} +
              + + +
              +
              +
              +
              + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/message/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/message/index.html new file mode 100644 index 00000000..85f169f8 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/app/message/index.html @@ -0,0 +1,176 @@ + +消息中心 + +
              + +
              + +
              +
              +
              +
                +
              • 全部消息
              • +
              • 通知6
              • +
              • 私信
              • +
              +
              + +
              +
              + + + +
              + +
              +
              +
              + +
              + + + +
              + +
              +
              +
              + +
              + + + +
              + +
              +
              +
              +
              +
              +
              + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/workorder/list.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/workorder/list.html new file mode 100644 index 00000000..011d884d --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/app/workorder/list.html @@ -0,0 +1,89 @@ + + +工单系统 + + + +
              +
              +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              +
              +
              +
              +
              + + + +
              +
              +
              + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/workorder/listform.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/workorder/listform.html new file mode 100644 index 00000000..c66c5ec7 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/app/workorder/listform.html @@ -0,0 +1,59 @@ + + +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + +
              + +
              +
              +
              + + \ No newline at end of file diff --git "a/iot-server/server-starter/src/main/webapp/assets/src/views/app/\350\257\264\346\230\216.txt" "b/iot-server/server-starter/src/main/webapp/assets/src/views/app/\350\257\264\346\230\216.txt" new file mode 100644 index 00000000..1f8f3e55 --- /dev/null +++ "b/iot-server/server-starter/src/main/webapp/assets/src/views/app/\350\257\264\346\230\216.txt" @@ -0,0 +1,2 @@ + +该目录存放【应用】的视图文件 \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/anim/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/anim/index.html new file mode 100644 index 00000000..7e9abd33 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/anim/index.html @@ -0,0 +1,108 @@ + +动画 + +
              +
              + 主页 + 组件 + 动画 +
              +
              + + + +
              +
              +
              +
              +
              点击演示动画
              +
              + +
                +
              • +
                从最底部往上滑入
                +
                layui-anim-up
                +
              • +
              • +
                微微往上滑入
                +
                layui-anim-upbit
                +
              • +
              • +
                平滑放大
                +
                layui-anim-scale
                +
              • +
              • +
                弹簧式放大
                +
                layui-anim-scaleSpring
                +
              • +
              +
                +
              • +
                渐现
                +
                layui-anim-fadein
                +
              • +
              • +
                渐隐
                +
                layui-anim-fadeout
                +
              • +
              • +
                360度旋转
                +
                layui-anim-rotate
                +
              • +
              • +
                循环动画
                +
                追加:layui-anim-loop
                +
              • +
              + +
              +
              +
              +
              +
              + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/auxiliar/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/auxiliar/index.html new file mode 100644 index 00000000..4104a5ca --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/auxiliar/index.html @@ -0,0 +1,103 @@ + +辅助元素 + +
              +
              + 主页 + 组件 + 辅助 +
              +
              + + + +
              +
              +
              +
              +
              引用区块
              +
              +
              这个貌似不用多介绍,因为你已经在太多的地方都看到
              + +
              + 猿强,则国强。国强,则猿更强! +
              ——孟子(好囖。。其实这特喵的是我说的) +
              +
              +
              +
              +
              字段集区块
              +
              + +
              + 爱好 +
              + 你可以在这里放任何内容,比如表单神马的 +
              +
              + +
              + +
              + 带标题的横线 +
              + +
              +
              +
              +
              分割线
              +
              + + 默认分割线 +
              + + 赤色分割线 +
              + + 橙色分割线 +
              + + 墨绿分割线 +
              + + 青色分割线 +
              + + 蓝色分割线 +
              + + 黑色分割线 +
              + + 灰色分割线 +
              + +
              +
              +
              +
              纯圆角
              +
              + +
              + +
              + +
              +
              +
              +
              +
              + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/badge/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/badge/index.html new file mode 100644 index 00000000..b1221a42 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/badge/index.html @@ -0,0 +1,103 @@ + +徽章 + +
              +
              + 主页 + 组件 + 徽章 +
              +
              + + + +
              +
              +
              +
              +
              小徽章大家族
              +
              + +
              小圆点: + + + + + + + + + +

              常规弧形徽章: + + 6 + 99 + 61728 + + + 绿 + + + + + +

              边框徽章: + + 6 + Hot + +

              + +
              +
              +
              +
              +
              +
              与其它元素的搭配
              +
              + +
              + + + + +

              + +
                <-- 小Tips:这里有没有发现,设置导航靠右对齐(或居中对齐)其实非常简单 --> +
              • + 控制台9 +
              • +
              • + 个人中心 +
              • +
              +
              + +
              +
                +
              • 网站设置
              • +
              • 用户管理
              • +
              • 最新邮件99+
              • +
              +
              +
              + +
              +
              +
              +
              +
              + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/button/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/button/index.html new file mode 100644 index 00000000..9a6c7e74 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/button/index.html @@ -0,0 +1,178 @@ + +按钮 + +
              +
              + 主页 + 组件 + 按钮 +
              +
              + +
              +
              +
              +
              +
              按钮主题
              +
              +
              + + + + + + +
              +
              +
              +
              +
              按钮尺寸
              +
              +
              + + + + + +
              + + + + + + +
              + + + + + +
              +
              +
              +
              +
              按钮图标
              +
              +
              + + + + + + + +
              + + + + + + + + +
              + + + + + + + + +
              + + + + + + + + +
              + + + + + + + +
              +
              +
              +
              +
              +
              +
              按钮圆角
              +
              +
              + + + + + + +
              +
              +
              +
              +
              按钮混搭
              +
              +
              + + 跳转的按钮 + + + +
              +
              +
              +
              +
              按钮组合
              +
              +
              +
              + + + +
              +
              +
              +
              + + + + +
              +
              + + + + +
              +
              +
              +
              +
              +
              按钮铺满
              +
              +
              + + + + +
              +
              +
              +
              + +
              +
              + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/carousel/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/carousel/index.html new file mode 100644 index 00000000..292111a8 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/carousel/index.html @@ -0,0 +1,219 @@ + + + 轮播 + + + +
              +
              + 主页 + 组件 + 轮播 +
              +
              + + + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/code/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/code/index.html new file mode 100644 index 00000000..9027d91a --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/code/index.html @@ -0,0 +1,141 @@ + + + 代码修饰 + +
              + +
              + +
              +
              +
              +
              +
              默认修饰
              +
              +
              //在里面存放任意的代码
              +Lay.fn.event = function(modName, events, params){
              +  var that = this, result = null, filter = events.match(/\(.*\)$/)||[];
              +  var set = (events = modName + '.'+ events).replace(filter, ''); 
              +};
              +            
              +
              +
              + +
              +
              notepad风格
              +
              +
              //代码区域
              +Lay.fn.event = function(modName, events, params){
              +  var that = this, result = null, filter = events.match(/\(.*\)$/)||[];
              +  var set = (events = modName + '.'+ events).replace(filter, ''); 
              +};
              +            
              +
              +
              + +
              +
              代码中的代码
              +
              +
              //代码区域
              +Lay.fn.event = function(modName, events, params){
              +  var that = this, result = null, filter = events.match(/\(.*\)$/)||[];
              +  var set = (events = modName + '.'+ events).replace(filter, ''); 
              +};
              +      
              //代码区域
              +Lay.fn.event = function(modName, events, params){
              +  var that = this, result = null, filter = events.match(/\(.*\)$/)||[];
              +  var set = (events = modName + '.'+ events).replace(filter, ''); 
              +};
              +      
              +
              + +
              //代码区域
              +Lay.fn.event = function(modName, events, params){
              +  var that = this, result = null, filter = events.match(/\(.*\)$/)||[];
              +  var set = (events = modName + '.'+ events).replace(filter, ''); 
              +};
              +      
              //代码区域
              +Lay.fn.event = function(modName, events, params){
              +  var that = this, result = null, filter = events.match(/\(.*\)$/)||[];
              +  var set = (events = modName + '.'+ events).replace(filter, ''); 
              +};
              +
              //代码区域
              +Lay.fn.event = function(modName, events, params){
              +  var that = this, result = null, filter = events.match(/\(.*\)$/)||[];
              +  var set = (events = modName + '.'+ events).replace(filter, ''); 
              +};
              +
              //代码区域
              +Lay.fn.event = function(modName, events, params){
              +  var that = this, result = null, filter = events.match(/\(.*\)$/)||[];
              +  var set = (events = modName + '.'+ events).replace(filter, ''); 
              +};
              +
              //代码区域
              +Lay.fn.event = function(modName, events, params){
              +  var that = this, result = null, filter = events.match(/\(.*\)$/)||[];
              +  var set = (events = modName + '.'+ events).replace(filter, ''); 
              +};
              +            
              +
              +
              +
              +
              +
              +
              + +
              +
              固定高度
              +
              +
              //代码区域
              +Lay.fn.event = function(modName, events, params){
              +  var that = this, result = null, filter = events.match(/\(.*\)$/)||[]; //提取事件过滤器
              +  var set = (events = modName + '.'+ events).replace(filter, ''); //获取事件本体名
              +  var callback = function(_, item){
              +    var res = item && item.call(that, params);
              +    res === false && result === null && (result = false);
              +  };
              +  layui.each(config.event[set], callback);
              +  filter[0] && layui.each(config.event[events], callback); //执行过滤器中的事件
              +  return result;
              +};
              +            
              +
              +
              + +
              +
              XXX
              +
              + +
              +
              + +
              +
              XXX
              +
              + +
              +
              + +
              +
              XXX
              +
              + +
              +
              + +
              +
              +
              + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/colorpicker/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/colorpicker/index.html new file mode 100644 index 00000000..76e8cff9 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/colorpicker/index.html @@ -0,0 +1,190 @@ + + + 颜色选择器组件 + + + +
              +
              +
              +
              +
              常规使用
              +
              +
              +
              +
              +
              +
              +
              表单赋值
              +
              +
              +
              +
              + +
              +
              +
              +
              +
              +
              +
              +
              +
              +
              RGB / RGBA 色值
              +
              +
              +
              +
              +
              +
              +
              透明度选择
              +
              +
              +
              +
              +
              +
              +
              +
              预定义颜色项
              +
              +
              +
              +
              +
              +
              +
              全功能和回调的使用
              +
              + +
              +
              +
              +
              +
              颜色框尺寸
              +
              +
              +
              +
              +
              +
              +
              +
              +
              + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/dropdown/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/dropdown/index.html new file mode 100644 index 00000000..3f91c9e2 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/dropdown/index.html @@ -0,0 +1,571 @@ + + + 下拉菜单 + + + +
              +
              +
              +
              +
              初演示
              +
              + +
              + + + +
              + +
              + +
              +
              + 可以绑定任意元素,比如这段文字 +
              + +
              +
              +
              +
              +
              +
              在表格中的应用
              +
              + +
              + + +
              +
              +
              +
              +
              +
              自定义事件
              +
              + +
              + + + +
              + +
              +
              +
              +
              +
              +
              右键菜单
              +
              + +
              + 在此区域单击鼠标右键 +
              + + +
              +
              +
              +
              +
              +
              重定义风格
              +
              + +
              + + + +
              + +
              +
              +
              +
              +
              + + + diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/flow/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/flow/index.html new file mode 100644 index 00000000..31b877da --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/flow/index.html @@ -0,0 +1,124 @@ + + + 流加载 + + + + +
              + +
              + +
              +
              +
              +
              +
              信息流 - 滚动加载
              +
              +
                +
                +
                +
                + +
                +
                +
                信息流 - 手工加载
                +
                +
                  +
                  +
                  +
                  + +
                  +
                  +
                  图片懒加载
                  +
                  +
                  + + + + + + + + + + + + + + + +
                  +
                  +
                  +
                  + +
                  +
                  + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/form/element.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/form/element.html new file mode 100644 index 00000000..1bfb120a --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/form/element.html @@ -0,0 +1,237 @@ + +表单元素 + + + + + +
                  +
                  +
                  +
                  +
                  输入框
                  +
                  +
                  + +
                  +
                  + +
                  +
                  + +
                  +
                  +
                  +
                  +
                  下拉选择框
                  +
                  +
                  + +
                  +
                  + +
                  +
                  + +
                  +
                  + +
                  +
                  + +
                  +
                  +
                  +
                  +
                  复选框
                  +
                  +
                  + + + +
                  +
                  + + + + +
                  +
                  +
                  +
                  +
                  开关
                  +
                  +
                  + + + + +
                  +
                  +
                  +
                  +
                  单选框
                  +
                  +
                  + + + +
                  +
                  +
                  +
                  +
                  +
                  +
                  文本域
                  +
                  +
                  + +
                  +
                  +
                  +
                  +
                  响应式组合
                  +
                  +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  +
                  + +
                  + + + + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + + + + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  +
                  + + +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/form/group.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/form/group.html new file mode 100644 index 00000000..ca39f880 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/form/group.html @@ -0,0 +1,291 @@ + +表单组合 + + + +
                  +
                  +
                  表单组合
                  +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  + +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  请填写6到12位密码
                  +
                  + +
                  +
                  + +
                  + +
                  +
                  -
                  +
                  + +
                  +
                  +
                  + +
                  + +
                  + +
                  +
                  + + +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  + +
                  +
                  + +
                  +
                  + +
                  +
                  +
                  此处只是演示联动排版,并未做联动交互
                  +
                  +
                  +
                  + +
                  + +
                  + + + +
                  +
                  + +
                  + +
                  + + + +
                  +
                  + +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + + + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  +
                  +
                  + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/all.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/all.html new file mode 100644 index 00000000..d55c8723 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/all.html @@ -0,0 +1,80 @@ + +全端复杂组合 + + + + + +
                  +
                  +
                  + +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/list.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/list.html new file mode 100644 index 00000000..28fe1f77 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/list.html @@ -0,0 +1,122 @@ + +等比例列表排列 + + + + + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/mobile-pc.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/mobile-pc.html new file mode 100644 index 00000000..6dab654a --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/mobile-pc.html @@ -0,0 +1,80 @@ + +移动桌面组合 + + + + + +
                  +
                  +
                  + +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/mobile.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/mobile.html new file mode 100644 index 00000000..b38ffa68 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/mobile.html @@ -0,0 +1,112 @@ + +按移动端排列 + + + + + +
                  +
                  +
                  + +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/speed-dial.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/speed-dial.html new file mode 100644 index 00000000..06f6b11d --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/speed-dial.html @@ -0,0 +1,84 @@ + +九宫格 + +
                  + +
                  + + + +
                  +
                  +
                  + +
                  +
                  1
                  +
                  +
                  +
                  +
                  +
                  2
                  +
                  +
                  +
                  +
                  +
                  3
                  +
                  +
                  +
                  +
                  +
                  4
                  +
                  +
                  +
                  +
                  +
                  5
                  +
                  +
                  +
                  +
                  +
                  6
                  +
                  +
                  +
                  +
                  +
                  7
                  +
                  +
                  +
                  +
                  +
                  8
                  +
                  +
                  +
                  +
                  +
                  9
                  +
                  +
                  +
                  +
                  + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/stack.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/stack.html new file mode 100644 index 00000000..c0910a5e --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/stack.html @@ -0,0 +1,143 @@ + +低于桌面堆叠排列 + + + + + +
                  +
                  +
                  + +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/demo1.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/demo1.html new file mode 100644 index 00000000..5a5fd250 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/demo1.html @@ -0,0 +1,324 @@ + + layDate 功能演示一 + +
                  + +
                  + +
                  +
                  +
                  +
                  +
                  常规用法
                  +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  + +
                  +
                  +
                  五大选择器
                  +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  + +
                  +
                  +
                  范围选择
                  +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  + +
                  +
                  +
                  自定义格式
                  +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  + +
                  +
                  +
                  同时绑定多个
                  +
                  +
                  +
                  +
                  + +
                  +
                  + +
                  +
                  + +
                  +
                  +
                  +
                  +
                  +
                  + + + +
                  +
                  + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/demo2.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/demo2.html new file mode 100644 index 00000000..220a1acd --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/demo2.html @@ -0,0 +1,276 @@ + + + layDate 功能演示二 + +
                  + +
                  + +
                  +
                  +
                  +
                  +
                  公历节日和自定义重要日子
                  +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  +
                  + +
                  +
                  +
                  + +
                  +
                  +
                  控制可选的日期与时间
                  +
                  +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  + 这里以控制在9:30-17:30为例 +
                  +
                  +
                  +
                  +
                  +
                  +
                  + +
                  +
                  +
                  其它功能示例
                  +
                  +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  + +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  + +
                  + +
                  + +
                  +
                  +
                  + +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  + +
                  +
                  + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/special-demo.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/special-demo.html new file mode 100644 index 00000000..9fb7c444 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/special-demo.html @@ -0,0 +1,74 @@ + + +layDate 日期组件功能演示 + +
                  + +
                  + +
                  +
                  +
                  +
                  +
                  联动范围选择
                  +
                  +
                  +
                  +
                  + +
                  + +
                  +
                  + - +
                  +
                  + +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/theme.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/theme.html new file mode 100644 index 00000000..8103d9fb --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/theme.html @@ -0,0 +1,173 @@ + + + layDate 日期组件功能演示 + + + +
                  + +
                  + +
                  +
                  +
                  +
                  +
                  自定义按钮主题
                  +
                  +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  + +
                  + +
                  +
                  +
                  +
                  +
                  +
                  +
                  + +
                  +
                  +
                  直接嵌套显示
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  + + + +
                  +
                  + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/list.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/list.html new file mode 100644 index 00000000..c0b8c8ab --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/list.html @@ -0,0 +1,491 @@ + +layer 组件功能演示 + + + + + +
                  +
                  +
                  +
                  +
                  弹层之美
                  +
                  + +
                  + layer 是 layui 中最广为人知的组件,它可以轻松应对 Web 应用开发中的各类复杂的弹出交互。有人说使用 layer 是一种情怀,一旦用上了,就离不开了。有多少人是因为 layer 才选择 layui 的呢,有一种信仰,叫:无条件相信 +
                  + +
                  +
                  + +
                  +
                  弹层类型
                  +
                  + +
                  + + + + + + + + + +
                  + +
                  +
                  +
                  +
                  常规使用
                  +
                  + +
                  + + + + + + + + + + + + + + + + +
                  + +
                  +
                  +
                  +
                  +
                  +
                  信息框
                  +
                  + +
                  + + + + + + + +
                  + +
                  +
                  +
                  +
                  +
                  +
                  页面层与iframe层
                  +
                  + +
                  + + + +
                  + +
                  +
                  +
                  +
                  +
                  +
                  加载层
                  +
                  + +
                  + + + + +
                  + +
                  +
                  +
                  +
                  +
                  +
                  tips层
                  +
                  + +
                  + + + + + +
                  + +
                  +
                  +
                  +
                  +
                  +
                  其它示例
                  +
                  + +
                  + + +
                  + +
                  +
                  +
                  +
                  +
                  + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/special-demo.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/special-demo.html new file mode 100644 index 00000000..544b6196 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/special-demo.html @@ -0,0 +1,174 @@ + +layer 组件特殊示例 + + + + + +
                  +
                  +
                  +
                  +
                  场景
                  +
                  + +
                  + + + +
                  + +
                  +
                  +
                  +
                  +
                  +
                  坐标
                  +
                  + +
                  + + + + + + + + + +
                  + +
                  +
                  +
                  +
                  +
                  + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/theme.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/theme.html new file mode 100644 index 00000000..8bdc0d1b --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/theme.html @@ -0,0 +1,82 @@ + +layer 组件风格定制 + + + + + +
                  +
                  +
                  +
                  +
                  风格定制
                  +
                  + +
                  + + +
                  + +
                  +
                  +
                  +
                  +
                  +
                  + + 持续增加中 + +
                  +
                  +
                  +
                  +
                  + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laypage/demo1.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laypage/demo1.html new file mode 100644 index 00000000..1b66596c --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laypage/demo1.html @@ -0,0 +1,158 @@ + + + 功能演示1 - 通用分页组件 + + + +
                  +
                  +
                  +
                  +
                  总页数低于页码总数
                  +
                  +
                  +
                  +
                  +
                  + +
                  +
                  +
                  总页数大于页码总数
                  +
                  +
                  +
                  +
                  +
                  + +
                  +
                  +
                  自定义主题 - 颜色随意定义
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  + +
                  +
                  +
                  自定义首页、尾页、上一页、下一页文本
                  +
                  +
                  +
                  +
                  +
                  + +
                  +
                  +
                  不显示首页尾页
                  +
                  +
                  +
                  +
                  +
                  + +
                  +
                  +
                  开启HASH
                  +
                  +
                  +
                  +
                  +
                  + +
                  +
                  +
                  只显示上一页、下一页
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  + + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laypage/demo2.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laypage/demo2.html new file mode 100644 index 00000000..d69dbab0 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laypage/demo2.html @@ -0,0 +1,159 @@ + + + 功能演示2 - 通用分页组件 + + + +
                  +
                  +
                  +
                  +
                  显示完整功能
                  +
                  +
                  +
                  +
                  +
                  + +
                  +
                  +
                  自定义排版
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  + +
                  +
                  +
                  自定义每页条数的选择项
                  +
                  +
                  +
                  +
                  +
                  + +
                  +
                  +
                  将一段已知数组分页展示
                  +
                  +
                  +
                    +
                    +
                    +
                    + +
                    +
                    + + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laytpl/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laytpl/index.html new file mode 100644 index 00000000..c62b0c19 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laytpl/index.html @@ -0,0 +1,34 @@ + +模板引擎 + + + + + +
                    + + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/nav/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/nav/index.html new file mode 100644 index 00000000..9a5eb6c6 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/nav/index.html @@ -0,0 +1,206 @@ + +导航 + +
                    +
                    + 主页 + 组件 + 导航 +
                    +
                    + + + +
                    +
                    +
                    +
                    +
                    水平导航菜单
                    + +
                    +
                    +
                    导航带徽章和图片
                    +
                    + +
                    +
                    + +
                    + +
                    + +
                    +
                    面包屑
                    + +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/panel/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/panel/index.html new file mode 100644 index 00000000..6c46f015 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/panel/index.html @@ -0,0 +1,181 @@ + +面板 + +
                    +
                    + 主页 + 组件 + 面板 +
                    +
                    + + + +
                    +
                    +
                    +
                    +
                    折叠面板
                    +
                    +
                    +
                    +

                    为什么JS社区大量采用未发布或者未广泛支持的语言特性?

                    +
                    +

                    有不少其他答案说是因为JS太差。我下面的答案已经说了,这不是根本性的原因。但除此之外,我还要纠正一些对JS具体问题的误解。JS当初是被作为脚本语言设计的,所以某些问题并不是JS设计得差或者是JS设计者的失误。比如var的作用域问题,并不是“错误”,而是当时绝大部分脚本语言都是这样的,如perl/php/sh等。模块的问题也是,脚本语言几乎都没有模块/命名空间功能。弱类型、for-in之类的问题也是,只不过现在用那些老的脚本语言的人比较少,所以很多人都误以为是JS才有的坑。另外有人说JS是半残语言,满足不了开发需求,1999年就该死。半残这个嘛,就夸张了。JS虽然有很多问题,但是设计总体还是优秀的。——来自知乎@贺师俊

                    +
                    +
                    +
                    +

                    为什么前端工程师多不愿意用 Bootstrap 框架?

                    +
                    +

                    因为不适合。如果希望开发长期的项目或者制作产品类网站,那么就需要实现特定的设计,为了在维护项目中可以方便地按设计师要求快速修改样式,肯定会逐步编写出各种业务组件、工具类,相当于为项目自行开发一套框架。——来自知乎@Kayo

                    +
                    +
                    +
                    +

                    layui 更适合哪些开发者?

                    +
                    +

                    在前端技术快速变革的今天,layui 仍然坚持语义化的组织模式,甚至于模块理念都是采用类AMD组织形式,并非是有意与时代背道而驰。layui 认为以jQuery为核心的开发方式还没有到完全消亡的时候,而早期市面上基于jQuery的UI都普通做得差强人意,所以需要有一个新的UI去重新为这一领域注入活力,并采用一些更科学的架构方式。 +

                    + 因此准确地说,layui 更多是面向那些追求开发简单的前端工程师们,以及所有层次的服务端程序员。

                    +
                    +
                    +
                    +

                    贤心是男是女?

                    +
                    +

                    man! 所以这个问题不要再出现了。。。

                    +
                    +
                    +
                    +
                    +
                    +
                    + +
                    手风琴折叠
                    +
                    +
                    +
                    +

                    layui 更适合哪些开发者?

                    +
                    +

                    在前端技术快速变革的今天,layui 仍然坚持语义化的组织模式,甚至于模块理念都是采用类AMD组织形式,并非是有意与时代背道而驰。layui 认为以jQuery为核心的开发方式还没有到完全消亡的时候,而早期市面上基于jQuery的UI都普通做得差强人意,所以需要有一个新的UI去重新为这一领域注入活力,并采用一些更科学的架构方式。 +
                    + 因此准确地说,layui 更多是面向那些追求开发简单的前端工程师们,以及所有层次的服务端程序员。

                    +
                    +
                    +
                    +

                    为什么JS社区大量采用未发布或者未广泛支持的语言特性?

                    +
                    +

                    有不少其他答案说是因为JS太差。我下面的答案已经说了,这不是根本性的原因。但除此之外,我还要纠正一些对JS具体问题的误解。JS当初是被作为脚本语言设计的,所以某些问题并不是JS设计得差或者是JS设计者的失误。比如var的作用域问题,并不是“错误”,而是当时绝大部分脚本语言都是这样的,如perl/php/sh等。模块的问题也是,脚本语言几乎都没有模块/命名空间功能。弱类型、for-in之类的问题也是,只不过现在用那些老的脚本语言的人比较少,所以很多人都误以为是JS才有的坑。另外有人说JS是半残语言,满足不了开发需求,1999年就该死。半残这个嘛,就夸张了。JS虽然有很多问题,但是设计总体还是优秀的。——来自知乎@贺师俊

                    +
                    +
                    +
                    +

                    为什么前端工程师多不愿意用 Bootstrap 框架?

                    +
                    +

                    因为不适合。如果希望开发长期的项目或者制作产品类网站,那么就需要实现特定的设计,为了在维护项目中可以方便地按设计师要求快速修改样式,肯定会逐步编写出各种业务组件、工具类,相当于为项目自行开发一套框架。——来自知乎@Kayo

                    +
                    +
                    +
                    +

                    贤心是男是女?

                    +
                    +

                    man! 所以这个问题不要再出现了。。。

                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    折叠面板嵌套
                    +
                    +
                    +
                    +

                    文豪

                    +
                    + +
                    +
                    +

                    唐代

                    +
                    + +
                    +
                    +

                    杜甫

                    +
                    + 伟大的诗人 +
                    +
                    +
                    +

                    李白

                    +
                    +

                    据说是韩国人

                    +
                    +
                    +
                    +

                    王勃

                    +
                    +

                    千古绝唱《滕王阁序》

                    +
                    +
                    +
                    + +
                    +
                    +
                    +

                    宋代

                    +
                    +

                    比如苏轼、李清照

                    +
                    +
                    +
                    +

                    当代

                    +
                    +

                    比如贤心

                    +
                    +
                    +
                    +
                    +
                    +
                    +

                    科学家

                    +
                    +

                    伟大的科学家

                    +
                    +
                    +
                    +

                    艺术家

                    +
                    +

                    浑身散发着艺术细胞

                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    卡片面板
                    +
                    + 就是当前这个 +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/progress/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/progress/index.html new file mode 100644 index 00000000..aeaeaa2d --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/progress/index.html @@ -0,0 +1,159 @@ + +进度条 + +
                    + +
                    + + + +
                    +
                    +
                    +
                    +
                    默认进度条
                    +
                    + +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    + +
                    +
                    +
                    +
                    +
                    +
                    更多颜色进度条
                    +
                    + +
                    +
                    +
                    + +
                    +
                    +
                    + +
                    +
                    +
                    + +
                    +
                    +
                    + +
                    +
                    +
                    + +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    + +
                    +
                    +
                    +
                    +
                    +
                    动态改变进度
                    +
                    + +
                    +
                    +
                    + +
                    + + +
                    + +
                    +
                    +
                    +
                    +
                    +
                    显示进度比文本
                    +
                    + +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/rate/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/rate/index.html new file mode 100644 index 00000000..b1e2af43 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/rate/index.html @@ -0,0 +1,177 @@ + + + 评分组件 + +
                    + +
                    + +
                    +
                    +
                    +
                    +
                    基础效果
                    +
                    +
                    +
                    +
                    +
                    +
                    显示文字
                    +
                    +
                    +
                    +
                    +
                    +
                    半星效果
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    自定义主题色
                    +
                    +
                      +
                    • +
                    • +
                    • +
                    • +
                    • +
                    +
                    +
                    +
                    +
                    +
                    +
                    只读
                    +
                    +
                    +
                    +
                    +
                    +
                    自定义内容
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    自定义长度
                    +
                    +
                    +
                    +
                    +
                    +
                    + +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/slider/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/slider/index.html new file mode 100644 index 00000000..73f11a11 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/slider/index.html @@ -0,0 +1,216 @@ + + + 滑块组件 + +
                    + +
                    + + + +
                    +
                    +
                    +
                    +
                    基础效果
                    +
                    +
                    +
                    +
                    +
                    +
                    定义初始值
                    +
                    +
                    +
                    +
                    +
                    +
                    设置最大最小值
                    +
                    +
                    +
                    +
                    +
                    +
                    设置步长
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    设置提示文本
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    开启输入框
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    开启范围选择
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    垂直滑块
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    自定义颜色
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    禁用滑块
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/auto.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/auto.html new file mode 100644 index 00000000..b7568b28 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/auto.html @@ -0,0 +1,49 @@ + + + 列宽自动分配 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    列宽自动分配
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/cellEdit.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/cellEdit.html new file mode 100644 index 00000000..bf467bf1 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/cellEdit.html @@ -0,0 +1,56 @@ + + + 开启单元格编辑 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    开启单元格编辑
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/cellEvent.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/cellEvent.html new file mode 100644 index 00000000..51b678cc --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/cellEvent.html @@ -0,0 +1,67 @@ + + + 单元格事件 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    单元格事件
                    +
                    +
                    点击下面表格中的【签名列】,以演示单元格事件
                    +
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/checkbox.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/checkbox.html new file mode 100644 index 00000000..b1a33091 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/checkbox.html @@ -0,0 +1,50 @@ + + + 开启复选框 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    开启复选框
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/data.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/data.html new file mode 100644 index 00000000..126c03a1 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/data.html @@ -0,0 +1,141 @@ + + + 赋值已知数据 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    赋值已知数据
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/fixed.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/fixed.html new file mode 100644 index 00000000..fedaed33 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/fixed.html @@ -0,0 +1,53 @@ + + + 固定列 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    固定列
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/form.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/form.html new file mode 100644 index 00000000..467009f9 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/form.html @@ -0,0 +1,82 @@ + + + 加入表单元素 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    加入表单元素
                    +
                    +
                    + + + + + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/height.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/height.html new file mode 100644 index 00000000..2649dc87 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/height.html @@ -0,0 +1,51 @@ + + + 高度最大适应 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    高度最大适应
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/initSort.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/initSort.html new file mode 100644 index 00000000..66acc1f3 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/initSort.html @@ -0,0 +1,48 @@ + + + 设置初始排序 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    设置初始排序
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/onrow.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/onrow.html new file mode 100644 index 00000000..4b6e7920 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/onrow.html @@ -0,0 +1,67 @@ + + + 行事件 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    行事件
                    +
                    + +
                    + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/operate.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/operate.html new file mode 100644 index 00000000..94845258 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/operate.html @@ -0,0 +1,107 @@ + + + 数据操作 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    数据操作
                    +
                    +
                    + + + +
                    + +
                    + + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/page.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/page.html new file mode 100644 index 00000000..bc765ec0 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/page.html @@ -0,0 +1,57 @@ + + + 开启分页 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    开启分页
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/parseData.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/parseData.html new file mode 100644 index 00000000..8a4756e6 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/parseData.html @@ -0,0 +1,65 @@ + + + 解析任意数据格式 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    解析任意数据格式
                    +
                    +
                    + 尽管本示例中的原始数据:./json/table/demo3.js,并不符合 table 组件默认规定的数据格式,但从 layui 2.4.0 开始,新增的 parseData 回调可以将原始的任意格式的数据重新解析成 table 组件规定的数据格式。具体可以点击上方查看代码。 +
                    + +
                    + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/radio.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/radio.html new file mode 100644 index 00000000..98952175 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/radio.html @@ -0,0 +1,70 @@ + + + 开启单选框 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    开启单选框
                    +
                    +
                    + + + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/reload.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/reload.html new file mode 100644 index 00000000..2f06619d --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/reload.html @@ -0,0 +1,87 @@ + + + 数据表格的重载 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    数据表格的重载
                    +
                    + +
                    + 搜索ID: +
                    + +
                    + +
                    + +
                    + +
                    此处由于是静态模拟数据,所以搜索后重载的结果没变,这并非是 BUG。实际使用时改成真实接口并根据搜索的字段筛选出对应的数据即可。
                    + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/resetPage.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/resetPage.html new file mode 100644 index 00000000..38e2e516 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/resetPage.html @@ -0,0 +1,58 @@ + + + 自定义分页 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    自定义分页
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/simple.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/simple.html new file mode 100644 index 00000000..05ff19a4 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/simple.html @@ -0,0 +1,48 @@ + + + 简单用法 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    简单用法
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/static.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/static.html new file mode 100644 index 00000000..07429218 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/static.html @@ -0,0 +1,309 @@ + + + 静态表格 + +
                    + +
                    + +
                    +
                    +
                    +
                    +
                    默认风格
                    +
                    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                    人物民族出场时间格言
                    贤心汉族1989-10-14人生似修行
                    张爱玲汉族1920-09-30于千万人之中遇见你所遇见的人,于千万年之中,时间的无涯的荒野里…
                    Helen Keller拉丁美裔1880-06-27 Life is either a daring adventure or nothing.
                    岳飞汉族1103-北宋崇宁二年教科书再滥改,也抹不去“民族英雄”的事实
                    孟子华夏族(汉族)公元前-372年猿强,则国强。国强,则猿更强!
                    +
                    +
                    +
                    +
                    +
                    +
                    行边框风格
                    +
                    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                    人物民族出场时间格言
                    贤心汉族1989-10-14人生似修行
                    张爱玲汉族1920-09-30于千万人之中遇见你所遇见的人,于千万年之中,时间的无涯的荒野里…
                    Helen Keller拉丁美裔1880-06-27 Life is either a daring adventure or nothing.
                    岳飞汉族1103-北宋崇宁二年教科书再滥改,也抹不去“民族英雄”的事实
                    孟子华夏族(汉族)公元前-372年猿强,则国强。国强,则猿更强!
                    +
                    +
                    +
                    +
                    +
                    +
                    列边框风格
                    +
                    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                    人物民族出场时间格言
                    贤心汉族1989-10-14人生似修行
                    张爱玲汉族1920-09-30于千万人之中遇见你所遇见的人,于千万年之中,时间的无涯的荒野里…
                    Helen Keller拉丁美裔1880-06-27 Life is either a daring adventure or nothing.
                    岳飞汉族1103-北宋崇宁二年教科书再滥改,也抹不去“民族英雄”的事实
                    孟子华夏族(汉族)公元前-372年猿强,则国强。国强,则猿更强!
                    +
                    +
                    +
                    +
                    +
                    +
                    无边框风格
                    +
                    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                    人物民族出场时间格言
                    贤心汉族1989-10-14人生似修行
                    张爱玲汉族1920-09-30于千万人之中遇见你所遇见的人,于千万年之中,时间的无涯的荒野里…
                    Helen Keller拉丁美裔1880-06-27 Life is either a daring adventure or nothing.
                    岳飞汉族1103-北宋崇宁二年教科书再滥改,也抹不去“民族英雄”的事实
                    孟子华夏族(汉族)公元前-372年猿强,则国强。国强,则猿更强!
                    +
                    +
                    +
                    +
                    +
                    +
                    其它尺寸
                    +
                    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                    昵称加入时间签名
                    贤心2016-11-29人生就像是一场修行
                    许闲心2016-11-28于千万人之中遇见你所遇见的人,于千万年之中,时间的无涯的荒野里…
                    sentsin2016-11-27 Life is either a daring adventure or nothing.
                    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                    昵称加入时间签名
                    贤心2016-11-29人生就像是一场修行
                    许闲心2016-11-28于千万人之中遇见你所遇见的人,于千万年之中,时间的无涯的荒野里…
                    sentsin2016-11-27 Life is either a daring adventure or nothing.
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/style.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/style.html new file mode 100644 index 00000000..cf32b4e0 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/style.html @@ -0,0 +1,63 @@ + + + 设置单元格样式 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    设置单元格样式
                    +
                    +
                    + + + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/thead.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/thead.html new file mode 100644 index 00000000..0513b82d --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/thead.html @@ -0,0 +1,96 @@ + + + 复杂表头 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    复杂表头
                    +
                    +
                    + 常用两级表头 +
                    + + + + + + + + + + + + + + + + +
                    联系人地址金额操作
                    + +
                    + +
                    + 更多级表头(可以无限极) +
                    + + + + + + + + + + + + + + + + + + + + + + +
                    联系人金额地址1地址2操作
                    详细
                    街道小区单元
                    + + + +
                    +
                    注:上述例子读取的均是静态模拟数据
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/toolbar.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/toolbar.html new file mode 100644 index 00000000..6dcfd146 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/toolbar.html @@ -0,0 +1,109 @@ + + + 开启头部工具栏 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    开启头部工具栏
                    +
                    +
                    + + + + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/tostatic.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/tostatic.html new file mode 100644 index 00000000..eb9899ed --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/tostatic.html @@ -0,0 +1,75 @@ + + + 转化静态表格 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    转化静态表格
                    +
                    + +
                    + +
                    + + + + + + + + + + + + + + + + + + + + + + + + + + +
                    昵称加入时间签名
                    贤心12016-11-28人生就像是一场修行 A
                    贤心22016-11-29人生就像是一场修行 B
                    贤心32016-11-30人生就像是一场修行 C
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/totalRow.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/totalRow.html new file mode 100644 index 00000000..98b4e660 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/totalRow.html @@ -0,0 +1,78 @@ + + + 开启合计行 - 数据表格 + + + +
                    +
                    +
                    +
                    +
                    开启合计行
                    +
                    +
                    + + + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/tabs/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/tabs/index.html new file mode 100644 index 00000000..12ea587c --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/tabs/index.html @@ -0,0 +1,188 @@ + +选项卡组件 + +
                    + +
                    + + + +
                    +
                    +
                    +
                    +
                    默认风格
                    +
                    +
                    +
                      +
                    • 网站设置
                    • +
                    • 用户管理
                    • +
                    • 权限分配
                    • +
                    • 商品管理
                    • +
                    • 订单管理
                    • +
                    +
                    +
                    + 1. 高度默认自适应,也可以随意固宽。 +
                    2. Tab进行了响应式处理,所以无需担心数量多少。 +
                    +
                    内容2
                    +
                    内容3
                    +
                    内容4
                    +
                    内容5
                    +
                    +
                    +
                    +
                    +
                    +
                    简洁风格
                    +
                    +
                    +
                      +
                    • 网站设置
                    • +
                    • 用户管理
                    • +
                    • 权限分配
                    • +
                    • 商品管理
                    • +
                    • 订单管理
                    • +
                    +
                    +
                    + 你也可以 tab 事件 +
                    +
                    内容2
                    +
                    内容3
                    +
                    内容4
                    +
                    内容5
                    +
                    +
                    +
                    +
                    +
                    +
                    卡片风格
                    +
                    +
                    +
                      +
                    • 网站设置
                    • +
                    • 用户管理
                    • +
                    • 权限分配
                    • +
                    • 商品管理
                    • +
                    • 订单管理
                    • +
                    +
                    +
                    默认宽度是相对于父元素100%适应的,你也可以固定宽度。
                    +
                    2
                    +
                    3
                    +
                    4
                    +
                    5
                    +
                    6
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    动态操作
                    +
                    +
                    +
                      +
                    • 网站设置
                    • +
                    • 用户管理
                    • +
                    • 权限分配
                    • +
                    • 商品管理
                    • +
                    • 订单管理
                    • +
                    +
                    +
                    内容1
                    +
                    内容2
                    +
                    内容3
                    +
                    +
                    +
                    + + + +
                    +
                    +
                    +
                    +
                    记录状态
                    +
                    +
                    +
                      +
                    • 网站设置
                    • +
                    • 用户管理
                    • +
                    • 权限分配
                    • +
                    • 商品管理
                    • +
                    • 订单管理
                    • +
                    +
                    +
                    + 点击该Tab的任一标题,观察地址栏变化,再刷新页面。选项卡将会自动定位到上一次切换的项 +
                    +
                    内容2
                    +
                    内容3
                    +
                    内容4
                    +
                    内容5
                    +
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/timeline/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/timeline/index.html new file mode 100644 index 00000000..8294ac51 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/timeline/index.html @@ -0,0 +1,121 @@ + +时间线 + +
                    + +
                    + + + +
                    +
                    +
                    +
                    +
                    常规时间线
                    +
                    + +
                      +
                    • + +
                      +

                      12月28日

                      +

                      + 一直以来,layui 秉承无偿开源的初心,虔诚致力于服务各层次前后端 Web 开发者,在商业横飞的当今时代,这一信念从未动摇。即便身单力薄,仍然重拾决心,埋头造轮,以尽可能地填补产品本身的缺口。在过去的一段的时间,我一直在寻求持久之道,已维持你眼前所见的一切。而 layuiAdmin 是我们尝试解决的手段之一。我相信真正有爱于 layui 生态的你,定然不会错过这一拥抱吧。 +

                      +


                      子曰:君子不用防,小人防不住。请务必通过官网正规渠道,获得 layuiAdmin

                      +
                      +
                    • +
                    • + +
                      +

                      12月25日

                      +

                      又是一年 “圣诞节”,2018 向我们正在走来

                      +
                        +
                      • 叮叮当,叮叮当,铃儿响叮当
                      • +
                      • 今晚滑雪多快乐,我们坐在雪橇上
                      • +
                      +
                      +
                    • +
                    • + +
                      +

                      12月24日

                      +

                      + 美丽的夜晚,都是祈祷的人们。
                      他们等待着第二天,收到圣诞老人的礼物。

                      +

                      +
                      平安夜,天赐平安。愿真善美的事物都能永恒。
                      +
                      +
                    • +
                    • + +
                      +
                      过去
                      +
                      +
                    • +
                    + +
                    +
                    +
                    +
                    +
                    +
                    简约时间线
                    +
                    + +
                      +
                    • + +
                      +
                      + 2018年,layui 5.0 发布,并发展成为中国最受欢迎的前端 UI 框架(期望) +
                      +
                      +
                    • +
                    • + +
                      +
                      2017年,layui 里程碑版本 2.0 发布
                      +
                      +
                    • +
                    • + +
                      +
                      2016年,layui 首个版本发布
                      +
                      +
                    • +
                    • + +
                      +
                      2015年,layui 孵化
                      +
                      +
                    • +
                    • + +
                      +
                      更久前,轮子时代。维护几个独立组件:layer等
                      +
                      +
                    • +
                    + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/transfer/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/transfer/index.html new file mode 100644 index 00000000..c89cdbd2 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/transfer/index.html @@ -0,0 +1,185 @@ + + + 穿梭框组件 + + + +
                    +
                    +
                    +
                    +
                    基础效果
                    +
                    +
                    +
                    +
                    +
                    +
                    定义标题及数据源
                    +
                    +
                    +
                    +
                    +
                    +
                    初始右侧数据集合
                    +
                    +
                    +
                    +
                    +
                    +
                    显示搜索框
                    +
                    +
                    +
                    +
                    +
                    +
                    数据格式解析
                    +
                    +
                    +
                    +
                    +
                    +
                    穿梭时的回调
                    +
                    +
                    +
                    +
                    +
                    +
                    实例调用
                    +
                    +
                    + + +
                    +
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/tree/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/tree/index.html new file mode 100644 index 00000000..56117339 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/tree/index.html @@ -0,0 +1,432 @@ + + + 树形组件 + +
                    + +
                    + +
                    +
                    +
                    +
                    +
                    基本演示
                    +
                    +
                    + + + +
                    +
                    +
                    +
                    +
                    +
                    常规用法
                    +
                    +
                    +
                    +
                    +
                    +
                    无连接线风格
                    +
                    +
                    +
                    +
                    +
                    +
                    仅节点左侧图标控制收缩
                    +
                    +
                    +
                    +
                    +
                    +
                    手风琴模式
                    +
                    +
                    +
                    +
                    +
                    +
                    点击节点新窗口跳转
                    +
                    +
                    +
                    +
                    +
                    +
                    开启复选框
                    +
                    +
                    +
                    +
                    +
                    +
                    开启节点操作图标
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/upload/demo1.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/upload/demo1.html new file mode 100644 index 00000000..777ca260 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/upload/demo1.html @@ -0,0 +1,199 @@ + + + 功能演示一 - 上传组件 + + + + + +
                    +
                    +
                    +
                    +
                    普通图片上传
                    +
                    +
                    + +
                    + +

                    +
                    +
                    +
                    + 为节省服务器开销,以下示例均未配置真实上传接口,所以每次上传都会报提示:请求上传接口出现异常,这属于正常现象。 +
                    +
                    +
                    +
                    + +
                    +
                    +
                    上传多张图片
                    +
                    +
                    + +
                    + 预览图: +
                    +
                    +
                    +
                    +
                    +
                    + +
                    +
                    +
                    指定允许上传的文件类型
                    +
                    + + + + +
                    +
                    +
                    + +
                    +
                    +
                    设定文件大小限制
                    +
                    + +
                    + 这里以限制 60KB 为例 +
                    +
                    +
                    +
                    + +
                    +
                    +
                    同时绑定多个元素,并将属性设定在元素上
                    +
                    + + + +
                    +
                    +
                    + +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/upload/demo2.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/upload/demo2.html new file mode 100644 index 00000000..1e5b8226 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/upload/demo2.html @@ -0,0 +1,187 @@ + + + 功能演示二 - 上传组件 + + + +
                    +
                    + +
                    +
                    +
                    高级应用:制作一个多文件列表
                    +
                    +
                    + +
                    + + + + + + + + + + + + + + + + +
                    文件名大小上传进度操作
                    +
                    + +
                    +
                    +
                    +
                    + +
                    +
                    +
                    选完文件后不自动上传
                    +
                    +
                    + + +
                    +
                    +
                    +
                    + +
                    +
                    +
                    拖拽上传
                    +
                    +
                    + +

                    点击上传,或将文件拖拽到此处

                    +
                    +
                    +
                    +
                    + +
                    +
                    +
                    绑定原始文件域
                    +
                    + +
                    +
                    +
                    + +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/util/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/util/index.html new file mode 100644 index 00000000..249ccd63 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/component/util/index.html @@ -0,0 +1,90 @@ + + + 工具模块 - 组件 + +
                    + +
                    + +
                    +
                    +
                    +
                    +
                    倒计时
                    +
                    + 请选择要计算的日期: +
                    + +
                    +
                    +
                    +
                    +
                    +
                    +
                    + +
                    +
                    +
                    某个时间在当前时间的多久前
                    +
                    + 请选择要计算的日期: +
                    + +
                    + +
                    +
                    +
                    + +
                    +
                    + + \ No newline at end of file diff --git "a/iot-server/server-starter/src/main/webapp/assets/src/views/component/\350\257\264\346\230\216.txt" "b/iot-server/server-starter/src/main/webapp/assets/src/views/component/\350\257\264\346\230\216.txt" new file mode 100644 index 00000000..951755f8 --- /dev/null +++ "b/iot-server/server-starter/src/main/webapp/assets/src/views/component/\350\257\264\346\230\216.txt" @@ -0,0 +1,2 @@ + +该目录存放【组件】的视图文件 \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/home/homepage1.html b/iot-server/server-starter/src/main/webapp/assets/src/views/home/homepage1.html new file mode 100644 index 00000000..8a5a402f --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/home/homepage1.html @@ -0,0 +1,194 @@ + +主页一 + +
                    + +
                    + +
                    +
                    +
                    +
                    +
                    + 最近更新 + 全部更新 +
                    +
                    +
                    +
                    +
                    + +

                    修复开启 isLazyimg:true 后, 图片懒加载但是图片不存在的报错问题

                    +

                    流加载7 天前

                    +
                    +
                    +
                    +
                    + +

                    修复开启 size 参数后,文件超出规定大小时,提示信息有误的问题

                    +

                    文件上传7 天前

                    +
                    +
                    +
                    +
                    + +

                    增加 form.val(filter, fields)方法,用于给指定表单集合的元素初始赋值

                    +

                    表单7 天前

                    +
                    +
                    +
                    +
                    + +

                    对 select 组件新增上下键(↑ ↓)回车键(Enter)选择功能

                    +

                    表单7 天前

                    +
                    +
                    +
                    +
                    + +

                    优化 switch 开关组件,让其能根据文本自由伸缩宽

                    +

                    表单7 天前

                    +
                    +
                    +
                    +
                    + +

                    修复 checkbox 复选框组件在高分辨屏下出现的样式不雅问题

                    +

                    表单7 天前

                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    动态
                    +
                    +
                    +
                    +
                    +
                    +

                    纸飞机 在 layuiadmin专区 回答问题

                    + 几秒前 +
                    +
                    +
                    +
                    +
                    +

                    纸飞机 在 layuiadmin专区 进行了 提问

                    + 2天前 +
                    +
                    +
                    +
                    +
                    +

                    纸飞机 将 layui 更新至 2.3.0-rc1 版本

                    + 7天前 +
                    +
                    +
                    +
                    +
                    +

                    纸飞机 在 Fly社区 发布了 建议

                    + 7天前 +
                    +
                    +
                    +
                    +
                    +

                    纸飞机 在 Fly社区 发布了 建议

                    + 8天前 +
                    +
                    +
                    +
                    +
                    +

                    纸飞机 在 layuiadmin专区 进行了 提问

                    + 8天前 +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    快速开始/便捷导航
                    +
                    + +
                    +
                    +
                    +
                    八卦新闻
                    +
                    + + + +
                    +
                    + +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/home/homepage2.html b/iot-server/server-starter/src/main/webapp/assets/src/views/home/homepage2.html new file mode 100644 index 00000000..96b3a8cd --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/home/homepage2.html @@ -0,0 +1,306 @@ + +主页二 + +
                    + +
                    + +
                    +
                    +
                    +
                    +
                    + 访问量 + +
                    +
                    +

                    99,666

                    +

                    + 总计访问量 + 88万 +

                    +
                    +
                    +
                    +
                    +
                    +
                    + 下载 + +
                    +
                    +

                    33,555

                    +

                    + 新下载 + 10% +

                    +
                    +
                    +
                    +
                    +
                    +
                    + 点赞 + +
                    +
                    + +

                    999,666

                    +

                    + 总赞 + *** +

                    +
                    +
                    +
                    +
                    +
                    +
                    + 活跃用户 + +
                    +
                    + +

                    66,666

                    +

                    + 最近一个月 + 15% +

                    +
                    +
                    +
                    +
                    +
                    +
                    + 访问量 +
                    + + +
                    +
                    +
                    +
                    +
                    + +
                    +
                    +
                    +

                    月访问数

                    + 同上期增长 +
                    +
                    +
                    +
                    +
                    +

                    月下载数

                    + 同上期增长 +
                    +
                    +
                    +
                    +
                    +

                    月点赞数

                    + 同上期增长 +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    用户留言
                    +
                    +
                      +
                    • +

                      贤心

                      +

                      作为 layui 官方原创的高质量管理系统模板,layuiAdmin 已经逐步成为后端工程师开发管理系统的首选界面模板。

                      + 5月30日 00:00 + 回复 +
                    • +
                    • +

                      诸葛亮

                      +

                      皓首匹夫!苍髯老贼!你枉活九十有六,一生未立寸功,只会摇唇鼓舌!助曹为虐!一条断脊之犬,还敢在我军阵前狺狺狂吠,我从未见过有如此厚颜无耻之人!

                      + 5月02日 00:00 + 回复 +
                    • +
                    • +

                      纸飞机

                      +

                      你以为只要长得漂亮就有男生喜欢?你以为只要有了钱漂亮妹子就自己贴上来了?你以为学霸就能找到好工作?我告诉你吧,这些都是真的!

                      + 5月11日 00:00 + 回复 +
                    • +
                    • +

                      杜甫

                      +

                      人才虽高,不务学问,不能致圣。刘向十日画一水,五日画一石。

                      + 4月11日 00:00 + 回复 +
                    • +
                    • +

                      鲁迅

                      +

                      路本是无所谓有和无的,走的人多了,就没路了。。

                      + 4月28日 00:00 + 回复 +
                    • +
                    • +

                      张爱玲

                      +

                      于千万人之中遇到你所要遇到的人,于千万年之中,时间的无涯的荒野中,没有早一步,也没有晚一步,刚巧赶上了,那也没有别的话好说,唯有轻轻的问一声:“噢,原来你也在这里?”

                      + 4月11日 00:00 + 回复 +
                    • +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    本周活跃用户列表
                    +
                    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                    用户名最后登录时间状态获得赞
                    纸飞机 11:20在线22
                    纸飞机 10:40在线21
                    纸飞机 01:30离线66
                    纸飞机 21:18离线45
                    纸飞机 09:30在线21
                    纸飞机 21:18在线45
                    纸飞机 09:30在线21
                    +
                    +
                    +
                    +
                    +
                    +
                    项目进展
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    访客地区分布
                    +
                    +
                    +
                    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                    排名地区人数
                    1浙江62310
                    2上海59190
                    3广东55891
                    4北京51919
                    5山东39231
                    6湖北37109
                    +
                    +
                    + +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/iframe/layer/iframe.html b/iot-server/server-starter/src/main/webapp/assets/src/views/iframe/layer/iframe.html new file mode 100644 index 00000000..a6c20874 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/iframe/layer/iframe.html @@ -0,0 +1,83 @@ + + + + + + + layer iframe 示例 + + + + + + + + + + +
                    + + + + +
                    + + + + + diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/iframe/link/baidu.html b/iot-server/server-starter/src/main/webapp/assets/src/views/iframe/link/baidu.html new file mode 100644 index 00000000..4995350d --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/iframe/link/baidu.html @@ -0,0 +1,3 @@ + +百度 + \ No newline at end of file diff --git "a/iot-server/server-starter/src/main/webapp/assets/src/views/iframe/\350\257\264\346\230\216.txt" "b/iot-server/server-starter/src/main/webapp/assets/src/views/iframe/\350\257\264\346\230\216.txt" new file mode 100644 index 00000000..621fae53 --- /dev/null +++ "b/iot-server/server-starter/src/main/webapp/assets/src/views/iframe/\350\257\264\346\230\216.txt" @@ -0,0 +1,3 @@ + +尽管 layuiAdmin 采用的是单页面应用开发模式,但有时你可能需要 iframe 嵌入一个页面,layuiAdmin 对此做了支持。 +该目录存放的就是 iframe 页面的视图文件。 \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/index.html new file mode 100644 index 00000000..971f2c35 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/index.html @@ -0,0 +1,391 @@ +
                    +
                    +
                    +
                    + + +
                    +
                    +
                    数据概览
                    +
                    + + + +
                    +
                    + +
                    +
                    访客地区分布
                    +
                    +
                    +
                    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                    排名地区人数
                    1浙江62310
                    2上海59190
                    3广东55891
                    4北京51919
                    5山东39231
                    6湖北37109
                    +
                    +
                    + +
                    +
                    +
                    +
                    + +
                    +
                    +
                      +
                    • 今日热搜
                    • +
                    • 今日热帖
                    • +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    + +
                    +
                    +
                    版本信息
                    +
                    + + + + + + + + + + + + + + + + + + + + + + + +
                    模板名称通用纯静态界面模板
                    当前版本 + +
                    UI 版本 + +
                    主要特色单页面 / 响应式 / 清爽 / 极简
                    +
                    +
                    + +
                    +
                    效果报告
                    +
                    +
                    +

                    转化率(日同比 28% ) +

                    +
                    +
                    +
                    +

                    签到率(日同比 11%

                    +
                    +
                    +
                    +
                    + +
                    +
                    进度占用
                    +
                    +
                    +

                    CPU使用率

                    +
                    +
                    +
                    +

                    内存占用率

                    +
                    +
                    +
                    +
                    + +
                    +
                    项目进展
                    +
                    +
                    +
                    +
                    + + + +
                    +
                    + 模板心语 + +
                    +
                    +
                    +

                    所谓“单页版”,即 SPA(单页面应用系统)开发模式,也就是所有的页面动作都是在一个宿主页面中完成,通常用于前后端分离。其中视图层全权由前端把控,数据一律走 Ajax + 异步请求。layuiAdmin 内部实现了一套基于 location.hash 的路由和模板机制,这使得你可以很轻松地实现界面的跳转与渲染。另外注意的是,接口鉴权不再适用于传统的 + session 模式,一般需要采用 JWT。总体来说,刚开始使用会相对有些复杂,但使用习惯后,项目会更易维护。

                    +

                    子曰:君子不用防,小人防不住。

                    +

                    请尊重知识产权,尊重他人劳动成果。

                    +
                    +
                    +
                    +
                    + +
                    +
                    + + + + diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/layout.html b/iot-server/server-starter/src/main/webapp/assets/src/views/layout.html new file mode 100644 index 00000000..275c469d --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/layout.html @@ -0,0 +1,200 @@ + +
                    +
                    + + + +
                    + + +
                    +
                    + +
                    +
                    + + + + + + + +
                    +
                    +
                    + + +
                    + +
                    diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/bar.html b/iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/bar.html new file mode 100644 index 00000000..b13c4ab5 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/bar.html @@ -0,0 +1,108 @@ + +柱状图 + + + +
                    +
                    +
                    +
                    +
                    标准柱状图
                    +
                    + + + +
                    +
                    +
                    +
                    堆积柱状图
                    +
                    + + + +
                    +
                    +
                    +
                    不等距柱形图
                    +
                    + + + +
                    +
                    +
                    +
                    彩虹柱形图
                    +
                    + + + +
                    +
                    +
                    +
                    +
                    +
                    标准条形图
                    +
                    + + + +
                    +
                    +
                    +
                    堆积条形图
                    +
                    + + + +
                    +
                    +
                    +
                    旋风条形图
                    +
                    + + + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/line.html b/iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/line.html new file mode 100644 index 00000000..e1e03b99 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/line.html @@ -0,0 +1,102 @@ +折线图 + + + +
                    +
                    +
                    +
                    +
                    标准折线图
                    +
                    + + + +
                    +
                    +
                    +
                    堆积折线图
                    +
                    + + + +
                    +
                    +
                    +
                    不等距折线图
                    +
                    + + + +
                    +
                    +
                    +
                    +
                    +
                    堆积面积图
                    +
                    + + + +
                    +
                    +
                    +
                    面积图
                    +
                    + + + +
                    +
                    +
                    +
                    对数轴
                    +
                    + + + +
                    +
                    +
                    + +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/map.html b/iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/map.html new file mode 100644 index 00000000..6d6e2a86 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/map.html @@ -0,0 +1,34 @@ +地图 + + + +
                    +
                    +
                    +
                    +
                    地图
                    +
                    + + + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/senior/im/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/senior/im/index.html new file mode 100644 index 00000000..91557e2e --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/senior/im/index.html @@ -0,0 +1,427 @@ + +社交聊天 + + + + +
                    +
                    +
                    +
                    +
                    面板外的操作示例
                    +
                    + +
                    + + + + + + +
                    + + + + + + + + +
                    + + +
                    + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git "a/iot-server/server-starter/src/main/webapp/assets/src/views/senior/\350\257\264\346\230\216.txt" "b/iot-server/server-starter/src/main/webapp/assets/src/views/senior/\350\257\264\346\230\216.txt" new file mode 100644 index 00000000..559f97d3 --- /dev/null +++ "b/iot-server/server-starter/src/main/webapp/assets/src/views/senior/\350\257\264\346\230\216.txt" @@ -0,0 +1,2 @@ + +该目录存放【高级】的视图文件 \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/set/system/email.html b/iot-server/server-starter/src/main/webapp/assets/src/views/set/system/email.html new file mode 100644 index 00000000..c6dd9b9d --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/set/system/email.html @@ -0,0 +1,69 @@ +邮件服务 + + + +
                    +
                    +
                    +
                    +
                    邮件服务
                    +
                    + +
                    +
                    + +
                    + +
                    +
                    如:smtp.163.com
                    +
                    +
                    + +
                    + +
                    +
                    一般为 25 或 465
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    +
                    + +
                    +
                    +
                    + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/set/system/website.html b/iot-server/server-starter/src/main/webapp/assets/src/views/set/system/website.html new file mode 100644 index 00000000..d905c7d3 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/set/system/website.html @@ -0,0 +1,95 @@ +网站设置 + + + +
                    +
                    +
                    +
                    +
                    网站设置
                    +
                    + +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    分钟
                    +
                    本地开发一般推荐设置为 0,线上环境建议设置为 10。
                    +
                    +
                    + +
                    + +
                    +
                    KB
                    +
                    提示:1 M = 1024 KB
                    +
                    +
                    + +
                    + +
                    +
                    + +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    +
                    + +
                    +
                    +
                    + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/set/user/info.html b/iot-server/server-starter/src/main/webapp/assets/src/views/set/user/info.html new file mode 100644 index 00000000..2c145387 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/set/user/info.html @@ -0,0 +1,98 @@ + +设置我的资料 + + + +
                    +
                    +
                    +
                    +
                    设置我的资料
                    +
                    + +
                    +
                    + +
                    + +
                    +
                    当前角色不可更改为其它角色
                    +
                    +
                    + +
                    + +
                    +
                    不可修改。一般用于后台登入名
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + + +
                    +
                    +
                    + +
                    + +
                    +
                    + + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    +
                    + + +
                    +
                    +
                    + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/set/user/password.html b/iot-server/server-starter/src/main/webapp/assets/src/views/set/user/password.html new file mode 100644 index 00000000..170a6b12 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/set/user/password.html @@ -0,0 +1,53 @@ +设置我的密码 + + + +
                    +
                    +
                    +
                    +
                    修改密码
                    +
                    + +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    6到16个字符
                    +
                    +
                    + +
                    + +
                    +
                    +
                    +
                    + +
                    +
                    +
                    + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git "a/iot-server/server-starter/src/main/webapp/assets/src/views/set/\350\257\264\346\230\216.txt" "b/iot-server/server-starter/src/main/webapp/assets/src/views/set/\350\257\264\346\230\216.txt" new file mode 100644 index 00000000..c40b5158 --- /dev/null +++ "b/iot-server/server-starter/src/main/webapp/assets/src/views/set/\350\257\264\346\230\216.txt" @@ -0,0 +1,2 @@ + +该目录存放【设置】的视图文件 \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/system/about.html b/iot-server/server-starter/src/main/webapp/assets/src/views/system/about.html new file mode 100644 index 00000000..2e6d5ff7 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/system/about.html @@ -0,0 +1,17 @@ +
                    版本
                    +
                    +
                    + +
                    +
                    + +
                    关于
                    +
                    +
                    + 一套纯静态的 HTML 网页界面模板,以开源免费的 layui 基础组件和页面模板 Demo 为组成,没有任何后端程序及数据库存储等服务端代码。 +

                    开发者使用该网页模板,可省去前端的大量工作,从而更高效地开发 Web 应用系统。 +

                    该模板受国家计算机软件著作权保护(登记号:2018SR410669),禁止公开及传播模板源文件、盗版及非法倒卖等,违者将自行承担相应的法律责任。 +
                    +
                    \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/system/more.html b/iot-server/server-starter/src/main/webapp/assets/src/views/system/more.html new file mode 100644 index 00000000..c1f570b6 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/system/more.html @@ -0,0 +1,22 @@ + + + diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/system/theme.html b/iot-server/server-starter/src/main/webapp/assets/src/views/system/theme.html new file mode 100644 index 00000000..d3f4617d --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/system/theme.html @@ -0,0 +1,43 @@ + + + + + + diff --git "a/iot-server/server-starter/src/main/webapp/assets/src/views/system/\350\257\264\346\230\216.txt" "b/iot-server/server-starter/src/main/webapp/assets/src/views/system/\350\257\264\346\230\216.txt" new file mode 100644 index 00000000..46923e05 --- /dev/null +++ "b/iot-server/server-starter/src/main/webapp/assets/src/views/system/\350\257\264\346\230\216.txt" @@ -0,0 +1,3 @@ + +注意: +该目录存放的是 layuiAdmin 的系统模板碎片,很多界面需要依赖到它,请勿剔除。 \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/temp.html b/iot-server/server-starter/src/main/webapp/assets/src/views/temp.html new file mode 100644 index 00000000..0a74d9dd --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/temp.html @@ -0,0 +1,51 @@ + +标题 + +
                    +
                    + 主页 + 组件 + XXX +
                    +
                    + + + +
                    +
                    +
                    +
                    +
                    YYY
                    +
                    + + + +
                    +
                    +
                    +
                    +
                    +
                    ZZZ
                    +
                    + + + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/addresslist.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/addresslist.html new file mode 100644 index 00000000..6bcdd744 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/template/addresslist.html @@ -0,0 +1,370 @@ + + +通讯录 + + + +
                    + +
                    + +
                    +
                    + + + + + + + + + +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/caller.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/caller.html new file mode 100644 index 00000000..4bd5becd --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/template/caller.html @@ -0,0 +1,195 @@ +客户列表 + + + + + +
                    +
                    +
                    + + + +
                    +
                    +
                      +
                    • 所有联系人
                    • +
                    • 联系方式
                    • +
                    • 联系地址
                    • +
                    +
                    +
                    +
                    + +
                    +

                    纸飞机 最近联系:1 小时前

                    +

                    浙江省广州市越秀区中山六路109

                    +
                    + + + +
                    +
                    + +
                    +
                    + +
                    +

                    纸飞机 最近联系:1 小时前

                    +

                    浙江省广州市越秀区中山六路109

                    +
                    + + + +
                    +
                    + +
                    +
                    + +
                    +

                    纸飞机 最近联系:1 小时前

                    +

                    浙江省广州市越秀区中山六路109

                    +
                    + + + +
                    +
                    + +
                    +
                    + +
                    +

                    纸飞机 最近联系:1 小时前

                    +

                    浙江省广州市越秀区中山六路109

                    +
                    + + + +
                    +
                    + +
                    +
                    + +
                    +

                    纸飞机 最近联系:1 小时前

                    +

                    浙江省广州市越秀区中山六路109

                    +
                    + + + +
                    +
                    + +
                    +
                    + +
                    +

                    纸飞机 最近联系:1 小时前

                    +

                    浙江省广州市越秀区中山六路109

                    +
                    + + + +
                    +
                    + +
                    +
                    + +
                    +

                    纸飞机 最近联系:1 小时前

                    +

                    浙江省广州市越秀区中山六路109

                    +
                    + + + +
                    +
                    + +
                    +
                    + +
                    +

                    纸飞机 最近联系:1 小时前

                    +

                    浙江省广州市越秀区中山六路109

                    +
                    + + + +
                    +
                    + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/goodslist.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/goodslist.html new file mode 100644 index 00000000..1b1ce7b5 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/template/goodslist.html @@ -0,0 +1,410 @@ + + +商品列表 + + + + + +
                    +
                    + + + + + + + + + + + + + + + + +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/msgboard.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/msgboard.html new file mode 100644 index 00000000..502208ab --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/template/msgboard.html @@ -0,0 +1,97 @@ + + +留言板 + + + +
                    + +
                    + +
                    +
                    +
                    +
                    +
                    +
                    + +
                    +
                    + +
                    +
                    + +
                    +
                    + + + +
                    +
                    +
                    +
                    +
                    +
                    + + + +
                    +

                    纸飞机

                    +

                    + + + 从移动 + 11分钟前 + +

                    +
                    +

                    历经打磨,@索尼中国 再献新作品—OLED电视A8F完美诞生。很开心一起参加了A8F的“首映礼”![鼓掌]正如我们演员对舞台的热爱,索尼对科技与艺术的追求才创造出了让人惊喜的作品。作为A1兄弟款,A8F沿袭了黑科技“屏幕发声技术”和高清画质,色彩的出众表现和高端音质,让人在体验的时候如同身临其境。A8F,这次的“视帝”要颁发给你! 索尼官网预售: O网页链接 索尼旗舰店预售:

                    +
                    +
                    + + + +
                    +

                    纸飞机

                    +

                    + + + 从移动 + 11分钟前 + +

                    +
                    +

                    历经打磨,@索尼中国 再献新作品—OLED电视A8F完美诞生。很开心一起参加了A8F的“首映礼”![鼓掌]正如我们演员对舞台的热爱,索尼对科技与艺术的追求才创造出了让人惊喜的作品。作为A1兄弟款,A8F沿袭了黑科技“屏幕发声技术”和高清画质,色彩的出众表现和高端音质,让人在体验的时候如同身临其境。A8F,这次的“视帝”要颁发给你! 索尼官网预售: O网页链接 索尼旗舰店预售:

                    +
                    +
                    + 更多 +
                    +
                    + +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/personalpage.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/personalpage.html new file mode 100644 index 00000000..5a67298a --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/template/personalpage.html @@ -0,0 +1,425 @@ + + +个人主页 + + + + + +
                    +
                    +
                    +
                    +
                    +
                    +
                    + +
                    +

                    纸飞机

                    +

                    中国非知名前端

                    +
                    + + + + +
                    + +
                    +
                    +

                    + 关于我 +

                    + +
                    + 纸飞机喜欢摄影,也喜欢写字,他视角独特,充满着奇思妙想。他有着极丰富的情感,和对生活的热情,他能点燃观众心中爱的火焰;纸飞机积极、乐观、坚强,他脚踏实地地做好每一件事,真诚地对待身边每一个人 +
                    +

                    + 技能 +

                    + +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +

                    52K

                    + 关注 +
                    +
                    +

                    72K

                    + 以下 +
                    +
                    +

                    5343

                    + 照片 +
                    +
                    +

                    4.5

                    + 排行 +
                    +
                    +
                    + +
                    +
                    +
                    +
                    +
                    + + + +
                    +
                    +

                    纸飞机普通照片添加了新的照片

                    +

                    + + + 从移动 + 11分钟前 + +

                    +
                    +

                    layer 是一款历年来备受青睐的 Web 弹出层组件,具备全方位的解决方案,面向各个水平段的开发人员,您的页面会轻松地拥有丰富友好的操作体验。在与同类组件的比较中,layer 会更能被开发者所选择。这不仅是凭「脸」取胜,而是它尽可能地在以更少的代码展现更强健的功能,且格外注重性能的提升、易用和实用性,layer 甚至还兼容了包括 IE6 在内的所有主流浏览器。其数量可观的基础属性和方法,使得您可以自定义太多您需要的风格,每一种弹层模式各具特色,广受欢迎。当然,这种「王婆卖瓜」的陈述听起来总是有点难受,因此你需要进一步了解她是否真的如你所愿。

                    + + + +
                    +
                    + + + + +
                    +
                    + 纸飞机 + 3月21日 19:56 +
                    +
                    一次难忘更难得的拍摄经历 谢谢
                    +
                    +
                    +
                    + + + +
                    +
                    + 纸飞机 + 3月21日 19:56 +
                    +
                    一次难忘更难得的拍摄经历 谢谢
                    +
                    +
                    +
                    + + + +
                    +
                    + 纸飞机 + 3月21日 19:56 +
                    +
                    一次难忘更难得的拍摄经历 谢谢
                    +
                    +
                    + 更多 +
                    +
                    +
                    +
                    + + + +
                    +
                    +

                    纸飞机普通照片添加了新的照片

                    +

                    + + + 从移动 + 11分钟前 + +

                    +
                    +

                    历经打磨,@索尼中国 再献新作品—OLED电视A8F完美诞生。很开心一起参加了A8F的“首映礼”![鼓掌]正如我们前端对舞台的热爱,索尼对科技与艺术的追求才创造出了让人惊喜的作品。作为A1兄弟款,A8F沿袭了黑科技“屏幕发声技术”和高清画质,色彩的出众表现和高端音质,让人在体验的时候如同身临其境。A8F,这次的“视帝”要颁发给你! 索尼官网预售: O网页链接 索尼旗舰店预售:

                    + +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +

                    + + 画廊 +

                    +
                    +
                    +
                    +
                    + +
                    +
                    + +
                    +
                    + +
                    +
                    + +
                    +
                    + +
                    +
                    + +
                    +
                    + +
                    +
                    + +
                    +
                    + +
                    +
                    + 更多 +
                    +
                    +
                    +
                    + +
                    +
                    +
                    +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/search.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/search.html new file mode 100644 index 00000000..f865a6b9 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/template/search.html @@ -0,0 +1,97 @@ + + +搜索结果 + + + + + +
                    +
                    +
                    +
                    +
                    +

                    + 关键词 查询到 + 66 个结果 +

                    +

                    耗时:350ms

                    +
                    +
                    + +
                      +
                    • +
                      +

                      前端的进化?

                      +

                      在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。

                      +
                      +
                    • +
                    • + + + +
                      +

                      前端 UI

                      +

                      UI 设计(或称界面设计)是指对软件的人机交互、操作逻辑、界面美观的整体设计。 UI 设计分为实体 UI和虚拟 UI,互联网常用的 UI 设计是虚拟 UI, UI即 User Interface (用户界面)的简称。

                      +
                      +
                    • +
                    • +
                      +

                      前端的进化?

                      +

                      在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。

                      +

                      + 前端 + 性别 + +

                      +
                      +
                    • +
                    • +
                      +

                      + 热点 + UI 设计 +

                      +

                      UI 设计(或称界面设计)是指对软件的人机交互、操作逻辑、界面美观的整体设计。 UI 设计分为实体 UI和虚拟 UI,互联网常用的 UI 设计是虚拟 UI, UI即 User Interface (用户界面)的简称。

                      +
                      +
                    • +
                    • +
                      +

                      前端的进化?

                      +

                      在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。

                      +
                      +
                    • +
                    +
                    + +
                    +
                    +
                    +
                    +
                    + + diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/404.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/404.html new file mode 100644 index 00000000..fc9f1127 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/404.html @@ -0,0 +1,15 @@ + +404 页面不存在 + +
                    +
                    + +
                    +

                    + 4 + 0 + 4 +

                    +
                    +
                    +
                    \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/error.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/error.html new file mode 100644 index 00000000..6242c6ad --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/error.html @@ -0,0 +1,13 @@ + +出错了 + +
                    +
                    + + +
                    + 好像出错了呢 +
                    + +
                    +
                    \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/test.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/test.html new file mode 100644 index 00000000..6242c6ad --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/test.html @@ -0,0 +1,13 @@ + +出错了 + +
                    +
                    + + +
                    + 好像出错了呢 +
                    + +
                    +
                    \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/user/forget.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/user/forget.html new file mode 100644 index 00000000..ca8352e4 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/template/user/forget.html @@ -0,0 +1,30 @@ + +忘记密码 + + + + + +
                    + 即将开放 +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/user/login.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/user/login.html new file mode 100644 index 00000000..a406283f --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/template/user/login.html @@ -0,0 +1,69 @@ + +登入页面 + +
                    +
                    + 主页 + 模板 + 登入 +
                    +
                    + +
                    +
                    +
                    说明:正式登入页面将在 beta3 开放
                    +
                    + +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    + layui 怎么念? +
                    +
                    +
                    +
                    + + + 忘记密码? + +
                    +
                    +
                    + +
                    +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/user/reg.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/user/reg.html new file mode 100644 index 00000000..35cccf19 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/template/user/reg.html @@ -0,0 +1,30 @@ + +注册页面 + +
                    +
                    + 主页 + 模板 + 注册 +
                    +
                    + + + +
                    + 即将开放 +
                    + + \ No newline at end of file diff --git "a/iot-server/server-starter/src/main/webapp/assets/src/views/template/\350\257\264\346\230\216.txt" "b/iot-server/server-starter/src/main/webapp/assets/src/views/template/\350\257\264\346\230\216.txt" new file mode 100644 index 00000000..a294d398 --- /dev/null +++ "b/iot-server/server-starter/src/main/webapp/assets/src/views/template/\350\257\264\346\230\216.txt" @@ -0,0 +1,2 @@ + +该目录存放【模板】的视图文件 \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/adminform.html b/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/adminform.html new file mode 100644 index 00000000..f8de6ee0 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/adminform.html @@ -0,0 +1,66 @@ + + +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/list.html b/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/list.html new file mode 100644 index 00000000..a6c2e301 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/list.html @@ -0,0 +1,161 @@ + + +后台管理员 + + + +
                    +
                    +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    +
                    +
                    + +
                    +
                    + + +
                    + +
                    + + +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/role.html b/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/role.html new file mode 100644 index 00000000..9520dcc0 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/role.html @@ -0,0 +1,127 @@ + + +角色管理 + + + +
                    +
                    +
                    +
                    +
                    + 角色筛选 +
                    +
                    + +
                    +
                    +
                    +
                    +
                    + + +
                    + +
                    + + +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/roleform.html b/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/roleform.html new file mode 100644 index 00000000..b690a74b --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/roleform.html @@ -0,0 +1,59 @@ + + +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + + + + + + + + + + + + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + + diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/user/forget.html b/iot-server/server-starter/src/main/webapp/assets/src/views/user/forget.html new file mode 100644 index 00000000..9c1a0691 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/user/forget.html @@ -0,0 +1,138 @@ + + + + + + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/user/login.html b/iot-server/server-starter/src/main/webapp/assets/src/views/user/login.html new file mode 100644 index 00000000..2b9509b8 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/user/login.html @@ -0,0 +1,121 @@ + + + + + + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/user/reg.html b/iot-server/server-starter/src/main/webapp/assets/src/views/user/reg.html new file mode 100644 index 00000000..0126388a --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/user/reg.html @@ -0,0 +1,120 @@ + + + + + + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/user/user/list.html b/iot-server/server-starter/src/main/webapp/assets/src/views/user/user/list.html new file mode 100644 index 00000000..950fdb2e --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/user/user/list.html @@ -0,0 +1,150 @@ + + +网站用户 + + + +
                    +
                    +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    +
                    +
                    + +
                    +
                    + + +
                    + +
                    + + +
                    +
                    +
                    + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/user/user/userform.html b/iot-server/server-starter/src/main/webapp/assets/src/views/user/user/userform.html new file mode 100644 index 00000000..5f5b029b --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/src/views/user/user/userform.html @@ -0,0 +1,72 @@ + + +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    + +
                    +
                    + +
                    + +
                    +
                    +
                    + +
                    + +
                    +
                    +
                    + + \ No newline at end of file diff --git "a/iot-server/server-starter/src/main/webapp/assets/src/views/user/\350\257\264\346\230\216.txt" "b/iot-server/server-starter/src/main/webapp/assets/src/views/user/\350\257\264\346\230\216.txt" new file mode 100644 index 00000000..ba22b0a2 --- /dev/null +++ "b/iot-server/server-starter/src/main/webapp/assets/src/views/user/\350\257\264\346\230\216.txt" @@ -0,0 +1,2 @@ + +该目录存放【用户】的视图文件 \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/index.html b/iot-server/server-starter/src/main/webapp/assets/zeus/index.html new file mode 100644 index 00000000..24e2313f --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/index.html @@ -0,0 +1,28 @@ + + + + + + + layuiAdmin pro - 通用后台管理模板系统(单页面专业版) + + + + + + + +
                    + + + + + + diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/console/prograss.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/console/prograss.js new file mode 100644 index 00000000..13a093bf --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/console/prograss.js @@ -0,0 +1,36 @@ +{ + "code": 0 + ,"msg": "" + ,"count": "100" + ,"data": [{ + "prograss": "开会" + ,"time": "一小时" + ,"complete": "已完成" + ,"LAY_CHECKED": true + },{ + "prograss": "项目开发" + ,"time": "两小时" + ,"complete": "进行中" + ,"LAY_CHECKED": true + },{ + "prograss": "陪吃饭" + ,"time": "一小时" + ,"complete": "未完成" + },{ + "prograss": "修改小bug" + ,"time": "半小时" + ,"complete": "未完成" + },{ + "prograss": "修改大bug" + ,"time": "两小时" + ,"complete": "未完成" + },{ + "prograss": "修改小bug" + ,"time": "半小时" + ,"complete": "未完成" + },{ + "prograss": "修改大bug" + ,"time": "两小时" + ,"complete": "未完成" + }] +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/console/top-card.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/console/top-card.js new file mode 100644 index 00000000..ae52d1c0 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/console/top-card.js @@ -0,0 +1,76 @@ +{ + "code": 0 + ,"msg": "" + ,"count": "100" + ,"data": [{ + "id": 111 + ,"title": "热帖测试" + ,"username": "test" + ,"channel": "公告" + ,"href": "" + ,"crt": 61632 + },{ + "id": 222 + ,"title": "一周年" + ,"username": "猫吃" + ,"channel": "讨论" + ,"href": "" + ,"crt": 61632 + },{ + "id": 333 + ,"title": "四个月的前端" + ,"username": "fd" + ,"channel": "分享" + ,"href": "" + ,"crt": 61632 + },{ + "id": 333 + ,"title": "如何评价前端 UI 框架" + ,"username": "纸飞机" + ,"channel": "提问" + ,"href": "" + ,"crt": 61632 + },{ + "id": 333 + ,"title": "如何评价前端 UI 框架" + ,"username": "纸飞机" + ,"channel": "提问" + ,"href": "" + ,"crt": 61632 + },{ + "id": 333 + ,"title": "如何评价前端 UI 框架" + ,"username": "纸飞机" + ,"channel": "提问" + ,"href": "" + ,"crt": 61632 + },{ + "id": 333 + ,"title": "如何评价前端 UI 框架" + ,"username": "纸飞机" + ,"channel": "提问" + ,"href": "" + ,"crt": 61632 + },{ + "id": 333 + ,"title": "如何评价前端 UI 框架" + ,"username": "纸飞机" + ,"channel": "提问" + ,"href": "" + ,"crt": 61632 + },{ + "id": 333 + ,"title": "如何评价前端 UI 框架" + ,"username": "纸飞机" + ,"channel": "提问" + ,"href": "" + ,"crt": 61632 + },{ + "id": 333 + ,"title": "如何评价前端 UI 框架" + ,"username": "纸飞机" + ,"channel": "提问" + ,"href": "" + ,"crt": 61632 + }] +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/console/top-search.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/console/top-search.js new file mode 100644 index 00000000..6b9956ba --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/console/top-search.js @@ -0,0 +1,46 @@ +{ + "code": 0 + ,"msg": "" + ,"count": "100" + ,"data": [{ + "keywords": "UI" + ,"frequency": 8520 + ,"userNums": 2216 + },{ + "keywords": "layer 弹出层组件" + ,"frequency": 666 + ,"userNums": 333 + },{ + "keywords": "此表格是静态模拟数据" + ,"frequency": 666 + ,"userNums": 333 + },{ + "keywords": "前端 UI" + ,"frequency": 666 + ,"userNums": 333 + },{ + "keywords": "前端 UI" + ,"frequency": 666 + ,"userNums": 333 + },{ + "keywords": "前端 UI" + ,"frequency": 666 + ,"userNums": 333 + },{ + "keywords": "前端 UI" + ,"frequency": 666 + ,"userNums": 333 + },{ + "keywords": "前端 UI" + ,"frequency": 666 + ,"userNums": 333 + },{ + "keywords": "前端 UI" + ,"frequency": 666 + ,"userNums": 333 + },{ + "keywords": "前端 UI" + ,"frequency": 666 + ,"userNums": 333 + }] +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/content/comment.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/content/comment.js new file mode 100644 index 00000000..45b8c3fb --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/content/comment.js @@ -0,0 +1,56 @@ +{ + "code": 0 + ,"msg": "" + ,"count": "100" + ,"data": [{ + "id": "001" + ,"reviewers": "赵" + ,"content": "我又爱上编程了" + ,"commtime": 20160312 + },{ + "id": "002" + ,"reviewers": "钱" + ,"content": "女生出门要小心" + ,"commtime": 20160821 + },{ + "id": "003" + ,"reviewers": "孙" + ,"content": "框架就用layui" + ,"commtime": 20161212 + },{ + "id": "004" + ,"reviewers": "李" + ,"content": "心姐么么哒" + ,"commtime": 20170311 + },{ + "id": "005" + ,"reviewers": "周" + ,"content": "希望明天是个好天气" + ,"commtime": 20170612 + },{ + "id": "006" + ,"reviewers": "吴" + ,"content": "我又爱上编程了" + ,"commtime": 20171112 + },{ + "id": "007" + ,"reviewers": "郑" + ,"content": "女生出门要小心" + ,"commtime": 20171230 + },{ + "id": "008" + ,"reviewers": "王" + ,"content": "框架就用layui" + ,"commtime": 20180112 + },{ + "id": "009" + ,"reviewers": "冯" + ,"content": "心姐么么哒" + ,"commtime": 20180221 + },{ + "id": "010" + ,"reviewers": "陈" + ,"content": "希望明天是个好天气" + ,"commtime": 20180312 + }] +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/content/list.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/content/list.js new file mode 100644 index 00000000..b70f3e7e --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/content/list.js @@ -0,0 +1,62 @@ +{ + "code": 0 + ,"msg": "" + ,"count": "100" + ,"data": [{ + "id": "001" + ,"label": "美食" + ,"title": "舌尖上的中国第一季" + ,"author": "作者-1" + ,"content": "通过中华美食的多个侧面,来展现食物给中国人生活带来的仪式、伦理等方面的文化;见识中国特色食材以及与食物相关、构成中国美食特有气质的一系列元素;了解中华饮食文化的精致和源远流长" + ,"uploadtime": 20121204 + ,"status": true + },{ + "id": "002" + ,"label": "美食" + ,"title": "舌尖上的中国第二季" + ,"author": "作者-2" + ,"content": "以食物为窗口,读懂中国——通过美食,使人们可以有滋有味地认知这个古老的东方国度。“一方水土一方人”,本片将通过展示人们日常生活中与美食相关的多重侧面,描绘与感知中国人的文化传统、家族观念、生活态度与故土难离。人们收获、保存、烹饪、生产美食,并在其过程中留存和传承食物所承载的味觉记忆、饮食习俗、文化样态与家常情感。" + ,"uploadtime": 20141204 + ,"status": false + },{ + "id": "003" + ,"label": "美食" + ,"title": "舌尖上的中国第三季" + ,"author": "作者-3" + ,"content": "以食物为窗口,读懂中国——通过美食,使人们可以有滋有味地认知这个古老的东方国度。“一方水土一方人”,本片将通过展示人们日常生活中与美食相关的多重侧面,描绘与感知中国人的文化传统、家族观念、生活态度与故土难离。人们收获、保存、烹饪、生产美食,并在其过程中留存和传承食物所承载的味觉记忆、饮食习俗、文化样态与家常情感将世界美食和中国美食进行比照。春耕、夏耘、秋收、冬藏,天人合一的东方哲学让中国饮食依时而变,智慧灵动,中医营养摄生学说创造了食材运用的新天地,儒家人伦道德则把心意和家的味道端上我们的餐桌。淘洗历史,糅合时光,一代又一代的中国人在天地间升起烟火,用至精至诚的心意烹制食物,一餐一食之间,中国人展示个性,确认归属,构建文明,理解和把握着世界的奥妙。" + ,"uploadtime": 20161204 + ,"status": false + },{ + "id": "004" + ,"label": "历史" + ,"title": "诸葛亮骂王朗" + ,"author": "作者-1" + ,"content": "皓首匹夫!苍髯老贼!你即将命归于九泉之下,届时,有何面目见汉朝二十四代先帝?二臣贼子!你枉活七十有六,一生未立寸功,只会摇唇舞舌,助曹为虐!一条断脊之犬,还敢在我军阵前狺狺狂吠!我从未见过如此厚颜无耻之人!!!" + ,"uploadtime": 20180201 + ,"status": false + },{ + "id": "005" + ,"label": "新闻" + ,"title": "新时代特色中国梦" + ,"author": "作者-1" + ,"content": "今天,我们比历史上任何时期都更接近、更有信心和能力实现中华民族伟大复兴的目标。新时代已经到来,蓝图已经绘就,中国梦离我们越来越近了。" + ,"uploadtime": 20180512 + ,"status": false + },{ + "id": "006" + ,"label": "新闻" + ,"title": "新时代特色中国梦" + ,"author": "作者-2" + ,"content": "梦想不会主动走向我们,只有我们去主动实现梦想。行百里者半九十。虽然中国梦离我们越来越近了,但是要实现中国梦,还要靠我们以永不懈怠的精神状态、功在不舍的坚强意志,不忘初心,继续前进。" + ,"uploadtime": 20180514 + ,"status": false + },{ + "id": "007" + ,"label": "体育" + ,"title": "皇马大战利物浦" + ,"author": "作者-3" + ,"content": "对欧足联而言,更想要产生个新冠军。连续三年都是同一个冠军队,这会毁掉欧冠……”格里姆表态,“皇马有梦幻般的阵容,但从促进竞争的角度而言,另一支球队获胜会更好。" + ,"uploadtime": 20180515 + ,"status": false + }] +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/content/tags.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/content/tags.js new file mode 100644 index 00000000..6ca85cd1 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/content/tags.js @@ -0,0 +1,21 @@ +{ + "code": 0 + ,"msg": "" + ,"count": "100" + ,"data": [{ + "id": "001" + ,"tags": "美食" + },{ + "id": "002" + ,"tags": "新闻" + },{ + "id": "003" + ,"tags": "八卦" + },{ + "id": "004" + ,"tags": "体育" + },{ + "id": "005" + ,"tags": "音乐" + }] +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/forum/list.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/forum/list.js new file mode 100644 index 00000000..fc8c7c25 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/forum/list.js @@ -0,0 +1,62 @@ +{ + "code": 0 + ,"msg": "" + ,"count": "100" + ,"data": [{ + "id": "1001" + ,"poster": "赵" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"content": "为什么花儿这么么红" + ,"posttime": 20160805 + ,"top": false + },{ + "id": "1002" + ,"poster": "钱" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"content": "喜欢纸飞机,赞赞赞" + ,"posttime": 20161205 + ,"top": true + },{ + "id": "1003" + ,"poster": "孙" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"content": "明天就要考试了,好紧张,求保佑" + ,"posttime": 20170405 + ,"top": false + },{ + "id": "1004" + ,"poster": "李" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"content": "希望明天是个好天气" + ,"posttime": 20171005 + ,"top": false + },{ + "id": "1005" + ,"poster": "周" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"content": "女追男隔层纱,是不是真的" + ,"posttime": 20180205 + ,"top": false + },{ + "id": "1006" + ,"poster": "吴" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"content": "竟然有人跳楼,年轻人想不开啊!" + ,"posttime": 20180512 + ,"top": false + },{ + "id": "1007" + ,"poster": "郑" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"content": "大家一定不能学那个年轻人,珍爱生命啊" + ,"posttime": 20180512 + ,"top": false + },{ + "id": "1008" + ,"poster": "王" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"content": "想知道南昌哪里有好吃的西安肉夹馍" + ,"posttime": 20180514 + ,"top": false + }] +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/forum/replys.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/forum/replys.js new file mode 100644 index 00000000..a7be0d0b --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/forum/replys.js @@ -0,0 +1,69 @@ +{ + "code": 0 + ,"msg": "" + ,"count": "100" + ,"data": [{ + "id": "001" + ,"replyer": "吴" + ,"cardid": "1002" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"content": "有眼光,我也喜欢纸飞机!" + ,"replytime": 20161205 + },{ + "id": "002" + ,"replyer": "郑" + ,"cardid": "1002" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"content": "同上同上。" + ,"replytime": 20161205 + },{ + "id": "003" + ,"replyer": "王" + ,"cardid": "1003" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"content": "能过一定过,不能过紧张也没用" + ,"replytime": 20170405 + },{ + "id": "004" + ,"replyer": "冯" + ,"cardid": "1001" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"content": "可能因为你流鼻血了。" + ,"replytime": 20170405 + },{ + "id": "005" + ,"replyer": "陈" + ,"cardid": "1003" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"content": "加油加油,看好你" + ,"replytime": 20170405 + },{ + "id": "006" + ,"replyer": "褚" + ,"cardid": "1005" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"content": "纯属放屁" + ,"replytime": 20180207 + },{ + "id": "007" + ,"replyer": "卫" + ,"cardid": "1005" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"content": "可以试试" + ,"replytime": 20180207 + },{ + "id": "006" + ,"replyer": "蒋" + ,"cardid": "1006" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"content": "是啊是啊,太恐怖了。" + ,"replytime": 20180512 + },{ + "id": "007" + ,"replyer": "沈" + ,"cardid": "1008" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"content": "魏家凉皮的凉皮就很不错奥。" + ,"replytime": 20180515 + }] +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/layer/photos.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/layer/photos.js new file mode 100644 index 00000000..a1898c17 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/layer/photos.js @@ -0,0 +1,39 @@ +{ + "code": 0, + "msg": "", + "title": "JSON请求的相册", + "id": 8, + "start": 0, + "data": [ + { + "alt": "layer", + "pid": 109, + "src": "https://sentsin.gitee.io/res/images/layui/avatar.png", + "thumb": "" + }, + { + "alt": "说好的,一起Fly", + "pid": 110, + "src": "https://wx4.sinaimg.cn/mw1024/5db11ff4gy1fmx4kebemcj20ga09saa1.jpg", + "thumb": "" + }, + { + "alt": "佟丽娅女神", + "pid": 111, + "src": "https://sentsin.gitee.io/res/images/layui/avatar.png", + "thumb": "" + }, + { + "alt": "凤姐是个好人", + "pid": 112, + "src": "https://wx3.sinaimg.cn/mw690/5db11ff4gy1fmx4kec9vuj20b20dwmyk.jpg", + "thumb": "" + }, + { + "alt": "星空如此深邃", + "pid": 113, + "src": "https://sentsin.gitee.io/res/images/layui/avatar.png", + "thumb": "" + } + ] +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/layim/getList.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/layim/getList.js new file mode 100644 index 00000000..8ea6ab88 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/layim/getList.js @@ -0,0 +1,96 @@ +{ + "code": 0 + ,"msg": "" + ,"data": { + "mine": { + "username": "测试名称" + ,"id": "100000" + ,"status": "online" + ,"sign": "测试" + ,"avatar": "" + } + ,"friend": [{ + "groupname": "测试分组一" + ,"id": 0 + ,"list": [{ + "username": "测试1" + ,"id": "100001" + ,"avatar": "" + ,"sign": "测试内容1" + ,"status": "online" + },{ + "username": "测试2" + ,"id": "100001222" + ,"sign": "测试内容2" + ,"avatar": "" + },{ + "username": "测试3" + ,"id": "10034001" + ,"avatar": "" + ,"sign": "" + },{ + "username": "测试4" + ,"id": "168168" + ,"avatar": "" + ,"sign": "测试内容4" + },{ + "username": "测试5" + ,"id": "666666" + ,"avatar": "" + ,"sign": "测试内容5" + }] + },{ + "groupname": "测试分组二" + ,"id": 1 + ,"list": [{ + "username": "测试6" + ,"id": "121286" + ,"avatar": "" + ,"sign": "测试内容6" + },{ + "username": "测试7" + ,"id": "108101" + ,"avatar": "" + ,"sign": "微电商达人" + },{ + "username": "测试8" + ,"id": "12123454" + ,"avatar": "" + ,"sign": "测试内容8" + },{ + "username": "测试9" + ,"id": "102101" + ,"avatar": "" + ,"sign": "" + },{ + "username": "测试10" + ,"id": "3435343" + ,"avatar": "" + ,"sign": "" + }] + },{ + "groupname": "测试分组三" + ,"id": 2 + ,"list": [{ + "username": "测试11" + ,"id": "76543" + ,"avatar": "" + ,"sign": "测试内容11" + },{ + "username": "测试12" + ,"id": "4803920" + ,"avatar": "" + ,"sign": "测试内容12" + }] + }] + ,"group": [{ + "groupname": "测试群组一" + ,"id": "101" + ,"avatar": "" + },{ + "groupname": "测试群组二" + ,"id": "102" + ,"avatar": "" + }] + } +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/layim/getMembers.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/layim/getMembers.js new file mode 100644 index 00000000..e45872e6 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/layim/getMembers.js @@ -0,0 +1,22 @@ +{ + "code": 0 + ,"msg": "" + ,"data": { + "list": [{ + "username": "测试1" + ,"id": "100001" + ,"avatar": "" + ,"sign": "测试内容" + },{ + "username": "测试6" + ,"id": "121286" + ,"avatar": "" + ,"sign": "测试内容" + },{ + "username": "测试8" + ,"id": "12123454" + ,"avatar": "" + ,"sign": "" + }] + } +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/mall/order.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/mall/order.js new file mode 100644 index 00000000..9ce29719 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/mall/order.js @@ -0,0 +1,42 @@ +{ + "code": 0 + ,"msg": "" + ,"count": "100" + ,"data": [{ + "invoice": "X123565541" + ,"username": "张小三" + ,"orderDate": "2017-11-10" + ,"amount": 800 + ,"status": 1 + },{ + "invoice": "X123565542" + ,"username": "李小四" + ,"orderDate": "2017-11-10" + ,"amount": 800 + ,"status": 0 + },{ + "invoice": "X123565543" + ,"username": "王老五" + ,"orderDate": "2017-11-10" + ,"amount": 800 + ,"status": 1 + },{ + "invoice": "X123565544" + ,"username": "赵小六" + ,"orderDate": "2017-11-09" + ,"amount": 1600 + ,"status": 1 + },{ + "invoice": "X123565545" + ,"username": "孙小七" + ,"orderDate": "2017-11-09" + ,"amount": 1600 + ,"status": -1 + },{ + "invoice": "X123565546" + ,"username": "周小八" + ,"orderDate": "2017-11-08" + ,"amount": 2600 + ,"status": 1 + }] +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/menu.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/menu.js new file mode 100644 index 00000000..18385961 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/menu.js @@ -0,0 +1,400 @@ +{ + "code": 0 + ,"msg": "" + ,"data": [{ + "title": "主页" + ,"icon": "layui-icon-home" + ,"list": [{ + "title": "控制台" + ,"jump": "/" + }, { + "name": "homepage1" + ,"title": "主页一" + ,"jump": "home/homepage1" + }, { + "name": "homepage2" + ,"title": "主页二" + ,"jump": "home/homepage2" + }] + }, { + "name": "component" + ,"title": "组件" + ,"icon": "layui-icon-component" + ,"list": [{ + "name": "grid" + ,"title": "栅格" + ,"list": [{ + "name": "list" + ,"title": "等比例列表排列" + },{ + "name": "mobile" + ,"title": "按移动端排列" + },{ + "name": "mobile-pc" + ,"title": "移动桌面端组合" + },{ + "name": "all" + ,"title": "全端复杂组合" + },{ + "name": "stack" + ,"title": "低于桌面堆叠排列" + },{ + "name": "speed-dial" + ,"title": "九宫格" + }] + }, { + "name": "button" + ,"title": "按钮" + }, { + "name": "form" + ,"title": "表单" + ,"list": [{ + "name": "element" + ,"title": "表单元素" + },{ + "name": "group" + ,"title": "表单组合" + }] + }, { + "name": "nav" + ,"title": "导航" + }, { + "name": "tabs" + ,"title": "选项卡" + }, { + "name": "progress" + ,"title": "进度条" + }, { + "name": "panel" + ,"title": "面板" + }, { + "name": "badge" + ,"title": "徽章" + }, { + "name": "timeline" + ,"title": "时间线" + }, { + "name": "anim" + ,"title": "动画" + }, { + "name": "auxiliar" + ,"title": "辅助" + }, { + "name": "layer" + ,"title": "通用弹层" + ,"list": [{ + "name": "list" + ,"title": "功能演示" + },{ + "name": "special-demo" + ,"title": "特殊示例" + },{ + "name": "theme" + ,"title": "风格定制" + }] + }, { + "name": "laydate" + ,"title": "日期时间" + ,"list": [{ + "name": "demo1" + ,"title": "功能演示一" + },{ + "name": "demo2" + ,"title": "功能演示二" + },{ + "name": "theme" + ,"title": "设定主题" + },{ + "name": "special-demo" + ,"title": "特殊示例" + }] + }, { + "name": "table" + ,"title": "表格" + ,"list": [{ + "name": "simple" + ,"title": "简单数据表格" + },{ + "name": "auto" + ,"title": "列宽自动分配" + },{ + "name": "data" + ,"title": "赋值已知数据" + },{ + "name": "tostatic" + ,"title": "转化静态表格" + },{ + "name": "page" + ,"title": "开启分页" + },{ + "name": "resetPage" + ,"title": "自定义分页" + },{ + "name": "toolbar" + ,"title": "开启头部工具栏" + },{ + "name": "totalRow" + ,"title": "开启合计行" + },{ + "name": "height" + ,"title": "高度最大适应" + },{ + "name": "checkbox" + ,"title": "开启复选框" + },{ + "name": "radio" + ,"title": "开启单选框" + },{ + "name": "cellEdit" + ,"title": "开启单元格编辑" + },{ + "name": "form" + ,"title": "加入表单元素" + },{ + "name": "style" + ,"title": "设置单元格样式" + },{ + "name": "fixed" + ,"title": "固定列" + },{ + "name": "operate" + ,"title": "数据操作" + },{ + "name": "parseData" + ,"title": "解析任意数据格式" + },{ + "name": "onrow" + ,"title": "监听行事件" + },{ + "name": "reload" + ,"title": "数据表格的重载" + },{ + "name": "initSort" + ,"title": "设置初始排序" + },{ + "name": "cellEvent" + ,"title": "监听单元格事件" + },{ + "name": "thead" + ,"title": "复杂表头" + }] + }, { + "name": "laypage" + ,"title": "分页" + ,"list": [{ + "name": "demo1" + ,"title": "功能演示一" + },{ + "name": "demo2" + ,"title": "功能演示二" + }] + }, { + "name": "dropdown" + ,"title": "下拉菜单" + }, { + "name": "upload" + ,"title": "上传" + ,"list": [{ + "name": "demo1" + ,"title": "功能演示一" + },{ + "name": "demo2" + ,"title": "功能演示二" + }] + }, { + "name": "transfer" + ,"title": "穿梭框" + }, { + "name": "tree" + ,"title": "树形组件" + }, { + "name": "colorpicker" + ,"title": "颜色选择器" + }, { + "name": "slider" + ,"title": "滑块组件" + }, { + "name": "rate" + ,"title": "评分" + }, { + "name": "carousel" + ,"title": "轮播" + }, { + "name": "flow" + ,"title": "流加载" + }, { + "name": "util" + ,"title": "工具" + }, { + "name": "code" + ,"title": "代码修饰" + }, { + "name": "layim" + ,"title": "即时聊天" + ,"jump": "senior/im/" + }] + }, { + "name": "template" + ,"title": "页面" + ,"icon": "layui-icon-template" + ,"list": [{ + "name": "personalpage" + ,"title": "个人主页" + ,"jump": "template/personalpage" + },{ + "name": "addresslist" + ,"title": "通讯录" + ,"jump": "template/addresslist" + },{ + "name": "caller" + ,"title": "客户列表" + ,"jump": "template/caller" + },{ + "name": "goodslist" + ,"title": "商品列表" + ,"jump": "template/goodslist" + },{ + "name": "msgboard" + ,"title": "留言板" + ,"jump": "template/msgboard" + },{ + "name": "search" + ,"title": "搜索结果" + ,"jump": "template/search" + },{ + "name": "reg" + ,"title": "注册" + ,"jump": "user/reg" + },{ + "name": "login" + ,"title": "登入" + ,"jump": "user/login" + },{ + "name": "forget" + ,"title": "忘记密码" + ,"jump": "user/forget" + },{ + "name": "404" + ,"title": "404" + ,"jump": "template/tips/404" + },{ + "name": "error" + ,"title": "错误提示" + ,"jump": "template/tips/error" + }, { + "name": "" + ,"title": "内嵌页面" + ,"spread": true + ,"list": [{ + "name": "" + ,"title": "百度一下" + ,"jump": "/iframe/link/baidu" + }] + }] + }, { + "name": "app" + ,"title": "应用" + ,"icon": "layui-icon-app" + ,"list": [{ + "name": "content" + ,"title": "内容系统" + ,"list": [{ + "name": "list" + ,"title": "文章列表" + },{ + "name": "tags" + ,"title": "分类管理" + },{ + "name": "comment" + ,"title": "评论管理" + }] + },{ + "name": "forum" + ,"title": "社区系统" + ,"list": [{ + "name": "list" + ,"title": "帖子列表" + },{ + "name": "replys" + ,"title": "回帖列表" + }] + },{ + "name": "message" + ,"title": "消息中心" + },{ + "name": "workorder" + ,"title": "工单系统" + ,"jump": "app/workorder/list" + }] + }, { + "name": "senior" + ,"title": "高级" + ,"icon": "layui-icon-senior" + ,"list": [{ + "name": "im" + ,"title": "WebIM UI" + },{ + "name": "echarts" + ,"title": "Echarts" + ,"list": [{ + "name": "line" + ,"title": "折线图" + },{ + "name": "bar" + ,"title": "柱状图" + },{ + "name": "map" + ,"title": "地图" + }] + }] + }, { + "name": "user" + ,"title": "用户" + ,"icon": "layui-icon-user" + ,"list": [{ + "name": "user" + ,"title": "网站用户" + ,"jump": "user/user/list" + }, { + "name": "administrators-list" + ,"title": "后台管理员" + ,"jump": "user/administrators/list" + }, { + "name": "administrators-rule" + ,"title": "角色管理" + ,"jump": "user/administrators/role" + }] + }, { + "name": "set" + ,"title": "设置" + ,"icon": "layui-icon-set" + ,"list": [{ + "name": "system" + ,"title": "系统设置" + ,"spread": true + ,"list": [{ + "name": "website" + ,"title": "网站设置" + },{ + "name": "email" + ,"title": "邮件服务" + }] + },{ + "name": "user" + ,"title": "我的设置" + ,"spread": true + ,"list": [{ + "name": "info" + ,"title": "基本资料" + },{ + "name": "password" + ,"title": "修改密码" + }] + }] + }, { + "name": "get" + ,"title": "关于" + ,"icon": "layui-icon-auz" + ,"jump": "system/about" + }] +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/all.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/all.js new file mode 100644 index 00000000..e7ac7087 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/all.js @@ -0,0 +1,46 @@ +{ + "code": 0 + ,"msg": "" + ,"count": 60 + ,"data": [{ + "id": 123 + ,"title": "Hello World" + ,"time": 1510363800000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1507447570000 + }] +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/detail.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/detail.js new file mode 100644 index 00000000..4a5c879b --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/detail.js @@ -0,0 +1,10 @@ +{ + "code": 0 + ,"msg": "" + ,"data": { + "id": 111 + ,"title": "Hello World" + ,"content": "

                    来自通用型纯静态 UI 界面模板的初识语 & 本地模拟测试消息

                    " + ,"time": 1510363800000 + } +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/direct.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/direct.js new file mode 100644 index 00000000..d8cbe165 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/direct.js @@ -0,0 +1,46 @@ +{ + "code": 0 + ,"msg": "" + ,"count": 60 + ,"data": [{ + "id": 123 + ,"title": "一段模拟的测试私信" + ,"time": 1510363800000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1507447570000 + }] +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/new.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/new.js new file mode 100644 index 00000000..668f4b51 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/new.js @@ -0,0 +1,7 @@ +{ + "code": 0 + ,"msg": "" + ,"data": { + "newmsg": 3 + } +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/notice.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/notice.js new file mode 100644 index 00000000..d8cbe165 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/notice.js @@ -0,0 +1,46 @@ +{ + "code": 0 + ,"msg": "" + ,"count": 60 + ,"data": [{ + "id": 123 + ,"title": "一段模拟的测试私信" + ,"time": 1510363800000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1510212370000 + }, { + "id": 111 + ,"title": "一段模拟的测试私信" + ,"time": 1507447570000 + }] +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo.js new file mode 100644 index 00000000..c96c09fd --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo.js @@ -0,0 +1,96 @@ + +{ + "code": 0 + ,"msg": "" + ,"count": 3000000 + ,"data": [{ + "id": "10001" + ,"username": "杜甫" + ,"email": "test@email.com" + ,"sex": "男" + ,"city": "浙江杭州" + ,"sign": "点击此处,显示更多。当内容超出时,点击单元格会自动显示更多内容。" + ,"experience": "116" + ,"ip": "192.168.0.8" + ,"logins": "108" + ,"joinTime": "2016-10-14" + }, { + "id": "10002" + ,"username": "李白" + ,"email": "test@email.com" + ,"sex": "男" + ,"city": "浙江杭州" + ,"sign": "君不见,黄河之水天上来,奔流到海不复回。 君不见,高堂明镜悲白发,朝如青丝暮成雪。 人生得意须尽欢,莫使金樽空对月。 天生我材必有用,千金散尽还复来。 烹羊宰牛且为乐,会须一饮三百杯。 岑夫子,丹丘生,将进酒,杯莫停。 与君歌一曲,请君为我倾耳听。(倾耳听 一作:侧耳听) 钟鼓馔玉不足贵,但愿长醉不复醒。(不足贵 一作:何足贵;不复醒 一作:不愿醒/不用醒) 古来圣贤皆寂寞,惟有饮者留其名。(古来 一作:自古;惟 通:唯) 陈王昔时宴平乐,斗酒十千恣欢谑。 主人何为言少钱,径须沽取对君酌。 五花马,千金裘,呼儿将出换美酒,与尔同销万古愁。" + ,"experience": "12" + ,"ip": "192.168.0.8" + ,"logins": "106" + ,"joinTime": "2016-10-14" + ,"LAY_CHECKED": true + }, { + "id": "10003" + ,"username": "王勃" + ,"email": "test@email.com" + ,"sex": "男" + ,"city": "浙江杭州" + ,"sign": "人生恰似一场修行" + ,"experience": "65" + ,"ip": "192.168.0.8" + ,"logins": "106" + ,"joinTime": "2016-10-14" + }, { + "id": "10004" + ,"username": "李清照" + ,"email": "test@email.com" + ,"sex": "女" + ,"city": "浙江杭州" + ,"sign": "人生恰似一场修行" + ,"experience": "666" + ,"ip": "192.168.0.8" + ,"logins": "106" + ,"joinTime": "2016-10-14" + }, { + "id": "10005" + ,"username": "冰心" + ,"email": "test@email.com" + ,"sex": "女" + ,"city": "浙江杭州" + ,"sign": "人生恰似一场修行" + ,"experience": "86" + ,"ip": "192.168.0.8" + ,"logins": "106" + ,"joinTime": "2016-10-14" + }, { + "id": "10006" + ,"username": "tester" + ,"email": "test@email.com" + ,"sex": "男" + ,"city": "浙江杭州" + ,"sign": "人生恰似一场修行" + ,"experience": "12" + ,"ip": "192.168.0.8" + ,"logins": "106" + ,"joinTime": "2016-10-14" + }, { + "id": "10007" + ,"username": "tester" + ,"email": "test@email.com" + ,"sex": "男" + ,"city": "浙江杭州" + ,"sign": "人生恰似一场修行" + ,"experience": "16" + ,"ip": "192.168.0.8" + ,"logins": "106" + ,"joinTime": "2016-10-14" + }, { + "id": "10008" + ,"username": "tester" + ,"email": "test@email.com" + ,"sex": "男" + ,"city": "浙江杭州" + ,"sign": "人生恰似一场修行" + ,"experience": "106" + ,"ip": "192.168.0.8" + ,"logins": "106" + ,"joinTime": "2016-10-14" + }] +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo2.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo2.js new file mode 100644 index 00000000..f6fae592 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo2.js @@ -0,0 +1,61 @@ + +{ + "code": 0 + ,"msg": "" + ,"count": 66 + ,"data": [{ + "username": "张小三" + ,"amount": 18 + ,"province": "浙江" + ,"city": "杭州" + ,"zone": "西湖区" + ,"street": "西溪街道" + ,"address": "西溪花园" + ,"house": "30栋1单元" + }, { + "username": "李小四" + ,"amount": 39 + ,"province": "江苏" + ,"city": "苏州" + ,"zone": "姑苏区" + ,"street": "丝绸路" + ,"address": "天墅之城" + ,"house": "9幢2单元" + }, { + "username": "王小五" + ,"amount": 8 + ,"province": "江西" + ,"city": "南昌" + ,"zone": "青山湖区" + ,"street": "艾溪湖办事处" + ,"address": "中兴和园" + ,"house": "1幢3单元" + }, { + "username": "赵小六" + ,"amount": 16 + ,"province": "福建" + ,"city": "泉州" + ,"zone": "丰泽区" + ,"street": "南洋街道" + ,"address": "南洋村" + ,"house": "6幢1单元" + }, { + "username": "孙小七" + ,"amount": 12 + ,"province": "湖北" + ,"city": "武汉" + ,"zone": "武昌区" + ,"street": "武昌大道" + ,"address": "两湖花园" + ,"house": "16幢2单元" + }, { + "username": "周小八" + ,"amount": 11 + ,"province": "安徽" + ,"city": "黄山" + ,"zone": "黄山区" + ,"street": "汤口镇" + ,"address": "温泉村" + ,"house": "21号" + }] +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo3.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo3.js new file mode 100644 index 00000000..4217f5d2 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo3.js @@ -0,0 +1,96 @@ +{ + "status": 200 + ,"message": "" + ,"total": 8 + ,"rows": { + "item": [{ + "id": "10001" + ,"username": "杜甫" + ,"email": "test@email.com" + ,"sex": "男" + ,"city": "浙江杭州" + ,"sign": "点击此处,显示更多。当内容超出时,点击单元格会自动显示更多内容。" + ,"experience": "116" + ,"ip": "192.168.0.8" + ,"logins": "108" + ,"joinTime": "2016-10-14" + }, { + "id": "10002" + ,"username": "李白" + ,"email": "test@email.com" + ,"sex": "男" + ,"city": "浙江杭州" + ,"sign": "君不见,黄河之水天上来,奔流到海不复回。 君不见,高堂明镜悲白发,朝如青丝暮成雪。 人生得意须尽欢,莫使金樽空对月。 天生我材必有用,千金散尽还复来。 烹羊宰牛且为乐,会须一饮三百杯。 岑夫子,丹丘生,将进酒,杯莫停。 与君歌一曲,请君为我倾耳听。(倾耳听 一作:侧耳听) 钟鼓馔玉不足贵,但愿长醉不复醒。(不足贵 一作:何足贵;不复醒 一作:不愿醒/不用醒) 古来圣贤皆寂寞,惟有饮者留其名。(古来 一作:自古;惟 通:唯) 陈王昔时宴平乐,斗酒十千恣欢谑。 主人何为言少钱,径须沽取对君酌。 五花马,千金裘,呼儿将出换美酒,与尔同销万古愁。" + ,"experience": "12" + ,"ip": "192.168.0.8" + ,"logins": "106" + ,"joinTime": "2016-10-14" + }, { + "id": "10003" + ,"username": "王勃" + ,"email": "test@email.com" + ,"sex": "男" + ,"city": "浙江杭州" + ,"sign": "人生恰似一场修行" + ,"experience": "65" + ,"ip": "192.168.0.8" + ,"logins": "106" + ,"joinTime": "2016-10-14" + }, { + "id": "10004" + ,"username": "李清照" + ,"email": "test@email.com" + ,"sex": "女" + ,"city": "浙江杭州" + ,"sign": "人生恰似一场修行" + ,"experience": "666" + ,"ip": "192.168.0.8" + ,"logins": "106" + ,"joinTime": "2016-10-14" + }, { + "id": "10005" + ,"username": "冰心" + ,"email": "test@email.com" + ,"sex": "女" + ,"city": "浙江杭州" + ,"sign": "人生恰似一场修行" + ,"experience": "86" + ,"ip": "192.168.0.8" + ,"logins": "106" + ,"joinTime": "2016-10-14" + }, { + "id": "10006" + ,"username": "tester" + ,"email": "test@email.com" + ,"sex": "男" + ,"city": "浙江杭州" + ,"sign": "人生恰似一场修行" + ,"experience": "12" + ,"ip": "192.168.0.8" + ,"logins": "106" + ,"joinTime": "2016-10-14" + }, { + "id": "10007" + ,"username": "tester" + ,"email": "test@email.com" + ,"sex": "男" + ,"city": "浙江杭州" + ,"sign": "人生恰似一场修行" + ,"experience": "16" + ,"ip": "192.168.0.8" + ,"logins": "106" + ,"joinTime": "2016-10-14" + }, { + "id": "10008" + ,"username": "tester" + ,"email": "test@email.com" + ,"sex": "男" + ,"city": "浙江杭州" + ,"sign": "人生恰似一场修行" + ,"experience": "106" + ,"ip": "192.168.0.8" + ,"logins": "106" + ,"joinTime": "2016-10-14" + }] + } +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/user.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/user.js new file mode 100644 index 00000000..240c7aa1 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/user.js @@ -0,0 +1,2 @@ + +{"code":0,"msg":"","count":1000,"data":[{"id":10000,"username":"user-0","sex":"女","city":"城市-0","sign":"签名-0","experience":255,"logins":24,"wealth":82830700,"classify":"作家","score":57},{"id":10001,"username":"user-1","sex":"男","city":"城市-1","sign":"签名-1","experience":884,"logins":58,"wealth":64928690,"classify":"词人","score":27},{"id":10002,"username":"user-2","sex":"女","city":"城市-2","sign":"签名-2","experience":650,"logins":77,"wealth":6298078,"classify":"酱油","score":31},{"id":10003,"username":"user-3","sex":"女","city":"城市-3","sign":"签名-3","experience":362,"logins":157,"wealth":37117017,"classify":"诗人","score":68},{"id":10004,"username":"user-4","sex":"男","city":"城市-4","sign":"签名-4","experience":807,"logins":51,"wealth":76263262,"classify":"作家","score":6},{"id":10005,"username":"user-5","sex":"女","city":"城市-5","sign":"签名-5","experience":173,"logins":68,"wealth":60344147,"classify":"作家","score":87},{"id":10006,"username":"user-6","sex":"女","city":"城市-6","sign":"签名-6","experience":982,"logins":37,"wealth":57768166,"classify":"作家","score":34},{"id":10007,"username":"user-7","sex":"男","city":"城市-7","sign":"签名-7","experience":727,"logins":150,"wealth":82030578,"classify":"作家","score":28},{"id":10008,"username":"user-8","sex":"男","city":"城市-8","sign":"签名-8","experience":951,"logins":133,"wealth":16503371,"classify":"词人","score":14},{"id":10009,"username":"user-9","sex":"女","city":"城市-9","sign":"签名-9","experience":484,"logins":25,"wealth":86801934,"classify":"词人","score":75}]} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/user30.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/user30.js new file mode 100644 index 00000000..0246bbd4 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/user30.js @@ -0,0 +1,2 @@ + +{"code":0,"msg":"","count":1000,"data":[{"id":10000,"username":"user-0","sex":"女","city":"城市-0","sign":"签名-0","experience":255,"logins":24,"wealth":82830700,"classify":"作家","score":57},{"id":10001,"username":"user-1","sex":"男","city":"城市-1","sign":"签名-1","experience":884,"logins":58,"wealth":64928690,"classify":"词人","score":27},{"id":10002,"username":"user-2","sex":"女","city":"城市-2","sign":"签名-2","experience":650,"logins":77,"wealth":6298078,"classify":"酱油","score":31},{"id":10003,"username":"user-3","sex":"女","city":"城市-3","sign":"签名-3","experience":362,"logins":157,"wealth":37117017,"classify":"诗人","score":68},{"id":10004,"username":"user-4","sex":"男","city":"城市-4","sign":"签名-4","experience":807,"logins":51,"wealth":76263262,"classify":"作家","score":6},{"id":10005,"username":"user-5","sex":"女","city":"城市-5","sign":"签名-5","experience":173,"logins":68,"wealth":60344147,"classify":"作家","score":87},{"id":10006,"username":"user-6","sex":"女","city":"城市-6","sign":"签名-6","experience":982,"logins":37,"wealth":57768166,"classify":"作家","score":34},{"id":10007,"username":"user-7","sex":"男","city":"城市-7","sign":"签名-7","experience":727,"logins":150,"wealth":82030578,"classify":"作家","score":28},{"id":10008,"username":"user-8","sex":"男","city":"城市-8","sign":"签名-8","experience":951,"logins":133,"wealth":16503371,"classify":"词人","score":14},{"id":10009,"username":"user-9","sex":"女","city":"城市-9","sign":"签名-9","experience":484,"logins":25,"wealth":86801934,"classify":"词人","score":75},{"id":10010,"username":"user-10","sex":"女","city":"城市-10","sign":"签名-10","experience":1016,"logins":182,"wealth":71294671,"classify":"诗人","score":34},{"id":10011,"username":"user-11","sex":"女","city":"城市-11","sign":"签名-11","experience":492,"logins":107,"wealth":8062783,"classify":"诗人","score":6},{"id":10012,"username":"user-12","sex":"女","city":"城市-12","sign":"签名-12","experience":106,"logins":176,"wealth":42622704,"classify":"词人","score":54},{"id":10013,"username":"user-13","sex":"男","city":"城市-13","sign":"签名-13","experience":1047,"logins":94,"wealth":59508583,"classify":"诗人","score":63},{"id":10014,"username":"user-14","sex":"男","city":"城市-14","sign":"签名-14","experience":873,"logins":116,"wealth":72549912,"classify":"词人","score":8},{"id":10015,"username":"user-15","sex":"女","city":"城市-15","sign":"签名-15","experience":1068,"logins":27,"wealth":52737025,"classify":"作家","score":28},{"id":10016,"username":"user-16","sex":"女","city":"城市-16","sign":"签名-16","experience":862,"logins":168,"wealth":37069775,"classify":"酱油","score":86},{"id":10017,"username":"user-17","sex":"女","city":"城市-17","sign":"签名-17","experience":1060,"logins":187,"wealth":66099525,"classify":"作家","score":69},{"id":10018,"username":"user-18","sex":"女","city":"城市-18","sign":"签名-18","experience":866,"logins":88,"wealth":81722326,"classify":"词人","score":74},{"id":10019,"username":"user-19","sex":"女","city":"城市-19","sign":"签名-19","experience":682,"logins":106,"wealth":68647362,"classify":"词人","score":51},{"id":10020,"username":"user-20","sex":"男","city":"城市-20","sign":"签名-20","experience":770,"logins":24,"wealth":92420248,"classify":"诗人","score":87},{"id":10021,"username":"user-21","sex":"男","city":"城市-21","sign":"签名-21","experience":184,"logins":131,"wealth":71566045,"classify":"词人","score":99},{"id":10022,"username":"user-22","sex":"男","city":"城市-22","sign":"签名-22","experience":739,"logins":152,"wealth":60907929,"classify":"作家","score":18},{"id":10023,"username":"user-23","sex":"女","city":"城市-23","sign":"签名-23","experience":127,"logins":82,"wealth":14765943,"classify":"作家","score":30},{"id":10024,"username":"user-24","sex":"女","city":"城市-24","sign":"签名-24","experience":212,"logins":133,"wealth":59011052,"classify":"词人","score":76},{"id":10025,"username":"user-25","sex":"女","city":"城市-25","sign":"签名-25","experience":938,"logins":182,"wealth":91183097,"classify":"作家","score":69},{"id":10026,"username":"user-26","sex":"男","city":"城市-26","sign":"签名-26","experience":978,"logins":7,"wealth":48008413,"classify":"作家","score":65},{"id":10027,"username":"user-27","sex":"女","city":"城市-27","sign":"签名-27","experience":371,"logins":44,"wealth":64419691,"classify":"诗人","score":60},{"id":10028,"username":"user-28","sex":"女","city":"城市-28","sign":"签名-28","experience":977,"logins":21,"wealth":75935022,"classify":"作家","score":37},{"id":10029,"username":"user-29","sex":"男","city":"城市-29","sign":"签名-29","experience":647,"logins":107,"wealth":97450636,"classify":"酱油","score":27}]} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/upload/demo.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/upload/demo.js new file mode 100644 index 00000000..acc06a5b --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/upload/demo.js @@ -0,0 +1,7 @@ +{ + "code": 0, + "msg": "", + "data": { + "src": "https://sentsin.gitee.io/res/images/layui/avatar.png" + } +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/forget.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/forget.js new file mode 100644 index 00000000..836bba4e --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/forget.js @@ -0,0 +1,7 @@ +{ + "code": 0 + ,"msg": "注册成功" + ,"data": { + + } +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/login.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/login.js new file mode 100644 index 00000000..ff906d5c --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/login.js @@ -0,0 +1,7 @@ +{ + "code": 0 + ,"msg": "登入成功" + ,"data": { + "access_token": "c262e61cd13ad99fc650e6908c7e5e65b63d2f32185ecfed6b801ee3fbdd5c0a" + } +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/logout.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/logout.js new file mode 100644 index 00000000..9fd1ff2c --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/logout.js @@ -0,0 +1,5 @@ +{ + "code": 0 + ,"msg": "退出成功" + ,"data": null +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/reg.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/reg.js new file mode 100644 index 00000000..836bba4e --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/reg.js @@ -0,0 +1,7 @@ +{ + "code": 0 + ,"msg": "注册成功" + ,"data": { + + } +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/resetpass.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/resetpass.js new file mode 100644 index 00000000..836bba4e --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/resetpass.js @@ -0,0 +1,7 @@ +{ + "code": 0 + ,"msg": "注册成功" + ,"data": { + + } +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/session.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/session.js new file mode 100644 index 00000000..491a376b --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/session.js @@ -0,0 +1,9 @@ +{ + "code": 0 + ,"msg": "" + ,"data": { + "username": "tester" + ,"sex": "男" + ,"role": 1 + } +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/sms.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/sms.js new file mode 100644 index 00000000..836bba4e --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/sms.js @@ -0,0 +1,7 @@ +{ + "code": 0 + ,"msg": "注册成功" + ,"data": { + + } +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/mangadmin.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/mangadmin.js new file mode 100644 index 00000000..fa2e6369 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/mangadmin.js @@ -0,0 +1,78 @@ +{ + "code": 0 + ,"msg": "" + ,"count": "100" + ,"data": [{ + "id": "1001" + ,"loginname": "admin" + ,"telphone": "11111111111" + ,"email": "111@qq.com" + ,"role": "超级管理员" + ,"jointime": "20150217" + ,"audit": true + },{ + "id": "1002" + ,"loginname": "common-1" + ,"telphone": "22222222222" + ,"email": "222@qq.com" + ,"role": "管理员" + ,"jointime": "20160217" + ,"audit": false + },{ + "id": "1003" + ,"loginname": "common-2" + ,"telphone": "33333333333" + ,"email": "333@qq.com" + ,"role": "管理员" + ,"jointime": "20161012" + ,"audit": false + },{ + "id": "1004" + ,"loginname": "common-3" + ,"telphone": "44444444444" + ,"email": "444@qq.com" + ,"role": "管理员" + ,"jointime": "20170518" + ,"audit": true + },{ + "id": "1005" + ,"loginname": "common-4" + ,"telphone": "55555555555" + ,"email": "555@qq.com" + ,"role": "管理员" + ,"jointime": "20180101" + ,"audit": false + },{ + "id": "1006" + ,"loginname": "common-5" + ,"telphone": "66666666666" + ,"email": "666@qq.com" + ,"role": "管理员" + ,"jointime": "20160217" + ,"audit": false + },{ + "id": "1007" + ,"loginname": "common-6" + ,"telphone": "77777777777" + ,"email": "777@qq.com" + ,"role": "管理员" + ,"jointime": "20161012" + ,"audit": false + },{ + "id": "1008" + ,"loginname": "common-7" + ,"telphone": "88888888888" + ,"email": "888@qq.com" + ,"role": "管理员" + ,"jointime": "20170518" + ,"audit": true + },{ + "id": "1009" + ,"loginname": "common-8" + ,"telphone": "99999999999" + ,"email": "999@qq.com" + ,"role": "管理员" + ,"jointime": "20180101" + ,"audit": false + }] +} diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/role.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/role.js new file mode 100644 index 00000000..6d5ba5df --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/role.js @@ -0,0 +1,54 @@ +{ + "code": 0 + ,"msg": "" + ,"count": "100" + ,"data": [{ + "id": "1" + ,"rolename": "超级管理员" + ,"limits": "管理所有的管理员" + ,"descr": "拥有至高无上的权利" + ,"check": true + },{ + "id": "2" + ,"rolename": "管理员" + ,"limits": "所有列表的管理" + ,"descr": "事情很多,权力很大" + ,"check": true + },{ + "id": "3" + ,"rolename": "文章撰写员" + ,"limits": "负责文章的编写" + ,"descr": "文采第一的人才集合" + ,"check": false + },{ + "id": "4" + ,"rolename": "纠错员" + ,"limits": "负责文章内容的修改" + ,"descr": "暂无" + ,"check": false + },{ + "id": "5" + ,"rolename": "统计人员" + ,"limits": "对数据进行统计" + ,"descr": "暂无" + ,"check": false + },{ + "id": "6" + ,"rolename": "评估员" + ,"limits": "对统计数据进行评估" + ,"descr": "及时捕捉市场发展动态" + ,"check": false + },{ + "id": "7" + ,"rolename": "采购员" + ,"limits": "负责员工的伙食" + ,"descr": "暂无" + ,"check": false + },{ + "id": "8" + ,"rolename": "推销员" + ,"limits": "介绍销售公司产品" + ,"descr": "暂无" + ,"check": false + }] +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/webuser.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/webuser.js new file mode 100644 index 00000000..233a47a2 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/webuser.js @@ -0,0 +1,143 @@ +{ + "code": 0 + ,"msg": "" + ,"count": "100" + ,"data": [{ + "id": "001" + ,"username": "用户-1" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"phone": 12345678901 + ,"email": "11111@qq.com" + ,"sex": "男" + ,"ip": "1111111" + ,"jointime": 20171204 + },{ + "id": "002" + ,"username": "用户-2" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"phone": 12345678901 + ,"email": "11111@qq.com" + ,"sex": "男" + ,"ip": "1111111" + ,"jointime": 20171204 + },{ + "id": "003" + ,"username": "用户-3" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"phone": 12345678901 + ,"email": "11111@qq.com" + ,"sex": "女" + ,"ip": "1111111" + ,"jointime": 20171011 + ,"LAY_CHECKED": true + },{ + "id": "004" + ,"username": "用户-4" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"phone": 12345678901 + ,"email": "11111@qq.com" + ,"sex": "男" + ,"ip": "1111111" + ,"jointime": 20160505 + },{ + "id": "005" + ,"username": "用户-5" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"phone": 12345678901 + ,"email": "11111@qq.com" + ,"sex": "男" + ,"ip": "1111111" + ,"jointime": 20171204 + },{ + "id": "006" + ,"username": "用户-6" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"phone": 12345678901 + ,"email": "11111@qq.com" + ,"sex": "男" + ,"ip": "1111111" + ,"jointime": 20171204 + },{ + "id": "007" + ,"username": "用户-7" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"phone": 12345678901 + ,"email": "11111@qq.com" + ,"sex": "男" + ,"ip": "1111111" + ,"jointime": 20180210 + },{ + "id": "008" + ,"username": "用户-8" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"phone": 12345678901 + ,"email": "11111@qq.com" + ,"sex": "女" + ,"ip": "1111111" + ,"jointime": 20171204 + },{ + "id": "009" + ,"username": "用户-9" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"phone": 12345678901 + ,"email": "11111@qq.com" + ,"sex": "女" + ,"ip": "1111111" + ,"jointime": 20171204 + },{ + "id": "010" + ,"username": "用户-10" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"phone": 12345678901 + ,"email": "11111@qq.com" + ,"sex": "男" + ,"ip": "1111111" + ,"jointime": 20170719 + },{ + "id": "011" + ,"username": "用户-11" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"phone": 12345678901 + ,"email": "11111@qq.com" + ,"sex": "男" + ,"ip": "1111111" + ,"jointime": 20171204 + },{ + "id": "012" + ,"username": "用户-12" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"phone": 12345678901 + ,"email": "11111@qq.com" + ,"sex": "女" + ,"ip": "1111111" + ,"jointime": 20171204 + },{ + "id": "013" + ,"username": "用户-13" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"phone": 12345678901 + ,"email": "11111@qq.com" + ,"sex": "女" + ,"ip": "1111111" + ,"jointime": 20171204 + ,"LAY_CHECKED": true + },{ + "id": "014" + ,"username": "用户-14" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"phone": 12345678901 + ,"email": "11111@qq.com" + ,"sex": "男" + ,"ip": "1111111" + ,"jointime": 20171204 + },{ + "id": "015" + ,"username": "用户-15" + ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" + ,"phone": 12345678901 + ,"email": "11111@qq.com" + ,"sex": "男" + ,"ip": "1111111" + ,"jointime": 20171204 + }] +} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/workorder/demo.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/workorder/demo.js new file mode 100644 index 00000000..70ab5f0c --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/json/workorder/demo.js @@ -0,0 +1,78 @@ +{ + "code": 0 + ,"msg": "" + ,"count": "100" + ,"data": [{ + "orderid": 111 + ,"title": "移动支付踏入马来西亚,聚合支付紧随其后" + ,"attr": "公告" + ,"progress": "25%" + ,"submit": "tester" + ,"accept": "员工-1" + ,"state": "处理中" + },{ + "orderid": 222 + ,"title": "凡科拖拽式免费建站神器,享双重优惠!" + ,"attr": "讨论" + ,"progress": "100%" + ,"submit": "猫吃" + ,"accept": "员工-1" + ,"state": "已处理" + },{ + "orderid": 333 + ,"title": "看着别人的老板给员工送汽车有感" + ,"attr": "分享" + ,"progress": "0%" + ,"submit": "纸飞机" + ,"accept": "" + ,"state": "未分配" + },{ + "orderid": 444 + ,"title": "DISCUZ的云平台还有戏吗" + ,"attr": "提问" + ,"progress": "0%" + ,"submit": "纸飞机" + ,"accept": "" + ,"state": "未分配" + },{ + "orderid": 555 + ,"title": "现在个人网站还有必要长期坚持下去吗?" + ,"attr": "提问" + ,"progress": "50%" + ,"submit": "纸飞机" + ,"accept": "员工-2" + ,"state": "处理中" + },{ + "orderid": 666 + ,"title": "求安排一个技术客服?" + ,"attr": "公告" + ,"progress": "25%" + ,"submit": "纸飞机" + ,"accept": "员工-3" + ,"state": "处理中" + },{ + "orderid": 777 + ,"title": "游戏 网页美工,一个月多少工资才正常?" + ,"attr": "提问" + ,"progress": "100%" + ,"submit": "纸飞机" + ,"accept": "员工-1" + ,"state": "已处理" + },{ + "orderid": 888 + ,"title": "几年没来了,蓝色理想帖子这么少了啊" + ,"attr": "提问" + ,"progress": "0%" + ,"submit": "纸飞机" + ,"accept": "" + ,"state": "未分配" + },{ + "orderid": 999 + ,"title": "我的天,求推荐靠谱的学习网站" + ,"attr": "提问" + ,"progress": "50%" + ,"submit": "纸飞机" + ,"accept": "员工-2" + ,"state": "处理中" + }] +} \ No newline at end of file diff --git "a/iot-server/server-starter/src/main/webapp/assets/zeus/json/\350\257\264\346\230\216.txt" "b/iot-server/server-starter/src/main/webapp/assets/zeus/json/\350\257\264\346\230\216.txt" new file mode 100644 index 00000000..ff402e5b --- /dev/null +++ "b/iot-server/server-starter/src/main/webapp/assets/zeus/json/\350\257\264\346\230\216.txt" @@ -0,0 +1,3 @@ + +注意:这里是模拟的数据。 +实际应用时,请在模板文件(.html)中的 lay-url="" 和其它相关接口的 url 设置成你真实的接口地址 \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/layui.css b/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/layui.css new file mode 100644 index 00000000..c784a25e --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/layui.css @@ -0,0 +1 @@ +.layui-inline,img{display:inline-block;vertical-align:middle}h1,h2,h3,h4,h5,h6{font-weight:400}a,body{color:#333}.layui-edge,.layui-header,.layui-inline,.layui-main{position:relative}.layui-edge,hr{height:0;overflow:hidden}.layui-layout-body,.layui-side,.layui-side-scroll{overflow-x:hidden}.layui-edge,.layui-elip,hr{overflow:hidden}.layui-btn,.layui-edge,.layui-inline,img{vertical-align:middle}.layui-btn,.layui-disabled,.layui-icon,.layui-unselect{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}blockquote,body,button,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,input,li,ol,p,pre,td,textarea,th,ul{margin:0;padding:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}a:active,a:hover{outline:0}img{border:none}li{list-style:none}table{border-collapse:collapse;border-spacing:0}h4,h5,h6{font-size:100%}button,input,optgroup,option,select,textarea{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;outline:0}pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}body{line-height:1.6;color:rgba(0,0,0,.85);font:14px Helvetica Neue,Helvetica,PingFang SC,Tahoma,Arial,sans-serif}hr{line-height:0;margin:10px 0;padding:0;border:none!important;border-bottom:1px solid #eee!important;clear:both;background:0 0}a{text-decoration:none}a:hover{color:#777}a cite{font-style:normal;*cursor:pointer}.layui-border-box,.layui-border-box *{box-sizing:border-box}.layui-box,.layui-box *{box-sizing:content-box}.layui-clear{clear:both;*zoom:1}.layui-clear:after{content:'\20';clear:both;*zoom:1;display:block;height:0}.layui-inline{*display:inline;*zoom:1}.layui-btn,.layui-btn-group,.layui-edge{display:inline-block}.layui-edge{width:0;border-width:6px;border-style:dashed;border-color:transparent}.layui-edge-top{top:-4px;border-bottom-color:#999;border-bottom-style:solid}.layui-edge-right{border-left-color:#999;border-left-style:solid}.layui-edge-bottom{top:2px;border-top-color:#999;border-top-style:solid}.layui-edge-left{border-right-color:#999;border-right-style:solid}.layui-elip{text-overflow:ellipsis;white-space:nowrap}.layui-disabled,.layui-disabled:hover{color:#d2d2d2!important;cursor:not-allowed!important}.layui-circle{border-radius:100%}.layui-show{display:block!important}.layui-hide{display:none!important}.layui-show-v{visibility:visible!important}.layui-hide-v{visibility:hidden!important}@font-face{font-family:layui-icon;src:url(../font/iconfont.eot?v=256);src:url(../font/iconfont.eot?v=256#iefix) format('embedded-opentype'),url(../font/iconfont.woff2?v=256) format('woff2'),url(../font/iconfont.woff?v=256) format('woff'),url(../font/iconfont.ttf?v=256) format('truetype'),url(../font/iconfont.svg?v=256#layui-icon) format('svg')}.layui-icon{font-family:layui-icon!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-icon-reply-fill:before{content:"\e611"}.layui-icon-set-fill:before{content:"\e614"}.layui-icon-menu-fill:before{content:"\e60f"}.layui-icon-search:before{content:"\e615"}.layui-icon-share:before{content:"\e641"}.layui-icon-set-sm:before{content:"\e620"}.layui-icon-engine:before{content:"\e628"}.layui-icon-close:before{content:"\1006"}.layui-icon-close-fill:before{content:"\1007"}.layui-icon-chart-screen:before{content:"\e629"}.layui-icon-star:before{content:"\e600"}.layui-icon-circle-dot:before{content:"\e617"}.layui-icon-chat:before{content:"\e606"}.layui-icon-release:before{content:"\e609"}.layui-icon-list:before{content:"\e60a"}.layui-icon-chart:before{content:"\e62c"}.layui-icon-ok-circle:before{content:"\1005"}.layui-icon-layim-theme:before{content:"\e61b"}.layui-icon-table:before{content:"\e62d"}.layui-icon-right:before{content:"\e602"}.layui-icon-left:before{content:"\e603"}.layui-icon-cart-simple:before{content:"\e698"}.layui-icon-face-cry:before{content:"\e69c"}.layui-icon-face-smile:before{content:"\e6af"}.layui-icon-survey:before{content:"\e6b2"}.layui-icon-tree:before{content:"\e62e"}.layui-icon-ie:before{content:"\e7bb"}.layui-icon-upload-circle:before{content:"\e62f"}.layui-icon-add-circle:before{content:"\e61f"}.layui-icon-download-circle:before{content:"\e601"}.layui-icon-templeate-1:before{content:"\e630"}.layui-icon-util:before{content:"\e631"}.layui-icon-face-surprised:before{content:"\e664"}.layui-icon-edit:before{content:"\e642"}.layui-icon-speaker:before{content:"\e645"}.layui-icon-down:before{content:"\e61a"}.layui-icon-file:before{content:"\e621"}.layui-icon-layouts:before{content:"\e632"}.layui-icon-rate-half:before{content:"\e6c9"}.layui-icon-add-circle-fine:before{content:"\e608"}.layui-icon-prev-circle:before{content:"\e633"}.layui-icon-read:before{content:"\e705"}.layui-icon-404:before{content:"\e61c"}.layui-icon-carousel:before{content:"\e634"}.layui-icon-help:before{content:"\e607"}.layui-icon-code-circle:before{content:"\e635"}.layui-icon-windows:before{content:"\e67f"}.layui-icon-water:before{content:"\e636"}.layui-icon-username:before{content:"\e66f"}.layui-icon-find-fill:before{content:"\e670"}.layui-icon-about:before{content:"\e60b"}.layui-icon-location:before{content:"\e715"}.layui-icon-up:before{content:"\e619"}.layui-icon-pause:before{content:"\e651"}.layui-icon-date:before{content:"\e637"}.layui-icon-layim-uploadfile:before{content:"\e61d"}.layui-icon-delete:before{content:"\e640"}.layui-icon-play:before{content:"\e652"}.layui-icon-top:before{content:"\e604"}.layui-icon-firefox:before{content:"\e686"}.layui-icon-friends:before{content:"\e612"}.layui-icon-refresh-3:before{content:"\e9aa"}.layui-icon-ok:before{content:"\e605"}.layui-icon-layer:before{content:"\e638"}.layui-icon-face-smile-fine:before{content:"\e60c"}.layui-icon-dollar:before{content:"\e659"}.layui-icon-group:before{content:"\e613"}.layui-icon-layim-download:before{content:"\e61e"}.layui-icon-picture-fine:before{content:"\e60d"}.layui-icon-link:before{content:"\e64c"}.layui-icon-diamond:before{content:"\e735"}.layui-icon-log:before{content:"\e60e"}.layui-icon-key:before{content:"\e683"}.layui-icon-rate-solid:before{content:"\e67a"}.layui-icon-fonts-del:before{content:"\e64f"}.layui-icon-unlink:before{content:"\e64d"}.layui-icon-fonts-clear:before{content:"\e639"}.layui-icon-triangle-r:before{content:"\e623"}.layui-icon-circle:before{content:"\e63f"}.layui-icon-radio:before{content:"\e643"}.layui-icon-align-center:before{content:"\e647"}.layui-icon-align-right:before{content:"\e648"}.layui-icon-align-left:before{content:"\e649"}.layui-icon-loading-1:before{content:"\e63e"}.layui-icon-return:before{content:"\e65c"}.layui-icon-fonts-strong:before{content:"\e62b"}.layui-icon-upload:before{content:"\e67c"}.layui-icon-dialogue:before{content:"\e63a"}.layui-icon-video:before{content:"\e6ed"}.layui-icon-headset:before{content:"\e6fc"}.layui-icon-cellphone-fine:before{content:"\e63b"}.layui-icon-add-1:before{content:"\e654"}.layui-icon-face-smile-b:before{content:"\e650"}.layui-icon-fonts-html:before{content:"\e64b"}.layui-icon-screen-full:before{content:"\e622"}.layui-icon-form:before{content:"\e63c"}.layui-icon-cart:before{content:"\e657"}.layui-icon-camera-fill:before{content:"\e65d"}.layui-icon-tabs:before{content:"\e62a"}.layui-icon-heart-fill:before{content:"\e68f"}.layui-icon-fonts-code:before{content:"\e64e"}.layui-icon-ios:before{content:"\e680"}.layui-icon-at:before{content:"\e687"}.layui-icon-fire:before{content:"\e756"}.layui-icon-set:before{content:"\e716"}.layui-icon-fonts-u:before{content:"\e646"}.layui-icon-triangle-d:before{content:"\e625"}.layui-icon-tips:before{content:"\e702"}.layui-icon-picture:before{content:"\e64a"}.layui-icon-more-vertical:before{content:"\e671"}.layui-icon-bluetooth:before{content:"\e689"}.layui-icon-flag:before{content:"\e66c"}.layui-icon-loading:before{content:"\e63d"}.layui-icon-fonts-i:before{content:"\e644"}.layui-icon-refresh-1:before{content:"\e666"}.layui-icon-rmb:before{content:"\e65e"}.layui-icon-addition:before{content:"\e624"}.layui-icon-home:before{content:"\e68e"}.layui-icon-time:before{content:"\e68d"}.layui-icon-user:before{content:"\e770"}.layui-icon-notice:before{content:"\e667"}.layui-icon-chrome:before{content:"\e68a"}.layui-icon-edge:before{content:"\e68b"}.layui-icon-login-weibo:before{content:"\e675"}.layui-icon-voice:before{content:"\e688"}.layui-icon-upload-drag:before{content:"\e681"}.layui-icon-login-qq:before{content:"\e676"}.layui-icon-snowflake:before{content:"\e6b1"}.layui-icon-heart:before{content:"\e68c"}.layui-icon-logout:before{content:"\e682"}.layui-icon-file-b:before{content:"\e655"}.layui-icon-template:before{content:"\e663"}.layui-icon-transfer:before{content:"\e691"}.layui-icon-auz:before{content:"\e672"}.layui-icon-console:before{content:"\e665"}.layui-icon-app:before{content:"\e653"}.layui-icon-prev:before{content:"\e65a"}.layui-icon-website:before{content:"\e7ae"}.layui-icon-next:before{content:"\e65b"}.layui-icon-component:before{content:"\e857"}.layui-icon-android:before{content:"\e684"}.layui-icon-more:before{content:"\e65f"}.layui-icon-login-wechat:before{content:"\e677"}.layui-icon-shrink-right:before{content:"\e668"}.layui-icon-spread-left:before{content:"\e66b"}.layui-icon-camera:before{content:"\e660"}.layui-icon-note:before{content:"\e66e"}.layui-icon-refresh:before{content:"\e669"}.layui-icon-female:before{content:"\e661"}.layui-icon-male:before{content:"\e662"}.layui-icon-screen-restore:before{content:"\e758"}.layui-icon-password:before{content:"\e673"}.layui-icon-senior:before{content:"\e674"}.layui-icon-theme:before{content:"\e66a"}.layui-icon-tread:before{content:"\e6c5"}.layui-icon-praise:before{content:"\e6c6"}.layui-icon-star-fill:before{content:"\e658"}.layui-icon-rate:before{content:"\e67b"}.layui-icon-template-1:before{content:"\e656"}.layui-icon-vercode:before{content:"\e679"}.layui-icon-service:before{content:"\e626"}.layui-icon-cellphone:before{content:"\e678"}.layui-icon-print:before{content:"\e66d"}.layui-icon-cols:before{content:"\e610"}.layui-icon-wifi:before{content:"\e7e0"}.layui-icon-export:before{content:"\e67d"}.layui-icon-rss:before{content:"\e808"}.layui-icon-slider:before{content:"\e714"}.layui-icon-email:before{content:"\e618"}.layui-icon-subtraction:before{content:"\e67e"}.layui-icon-mike:before{content:"\e6dc"}.layui-icon-light:before{content:"\e748"}.layui-icon-gift:before{content:"\e627"}.layui-icon-mute:before{content:"\e685"}.layui-icon-reduce-circle:before{content:"\e616"}.layui-icon-music:before{content:"\e690"}.layui-main{width:1140px;margin:0 auto}.layui-header{z-index:1000;height:60px}.layui-header a:hover{transition:all .5s;-webkit-transition:all .5s}.layui-side{position:fixed;left:0;top:0;bottom:0;z-index:999;width:200px}.layui-side-scroll{position:relative;width:220px;height:100%}.layui-body{position:relative;left:200px;right:0;top:0;bottom:0;z-index:900;width:auto;box-sizing:border-box}.layui-layout-admin .layui-header{position:fixed;top:0;left:0;right:0;background-color:#23262E}.layui-layout-admin .layui-side{top:60px;width:200px;overflow-x:hidden}.layui-layout-admin .layui-body{position:absolute;top:60px;padding-bottom:44px}.layui-layout-admin .layui-main{width:auto;margin:0 15px}.layui-layout-admin .layui-footer{position:fixed;left:200px;right:0;bottom:0;z-index:990;height:44px;line-height:44px;padding:0 15px;box-shadow:-1px 0 4px rgb(0 0 0 / 12%);background-color:#FAFAFA}.layui-layout-admin .layui-logo{position:absolute;left:0;top:0;width:200px;height:100%;line-height:60px;text-align:center;color:#009688;font-size:16px;box-shadow:0 1px 2px 0 rgb(0 0 0 / 15%)}.layui-layout-admin .layui-header .layui-nav{background:0 0}.layui-layout-left{position:absolute!important;left:200px;top:0}.layui-layout-right{position:absolute!important;right:0;top:0}.layui-container{position:relative;margin:0 auto;padding:0 15px;box-sizing:border-box}.layui-fluid{position:relative;margin:0 auto;padding:0 15px}.layui-row:after,.layui-row:before{content:"";display:block;clear:both}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9,.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9,.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9,.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{position:relative;display:block;box-sizing:border-box}.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{float:left}.layui-col-xs1{width:8.33333333%}.layui-col-xs2{width:16.66666667%}.layui-col-xs3{width:25%}.layui-col-xs4{width:33.33333333%}.layui-col-xs5{width:41.66666667%}.layui-col-xs6{width:50%}.layui-col-xs7{width:58.33333333%}.layui-col-xs8{width:66.66666667%}.layui-col-xs9{width:75%}.layui-col-xs10{width:83.33333333%}.layui-col-xs11{width:91.66666667%}.layui-col-xs12{width:100%}.layui-col-xs-offset1{margin-left:8.33333333%}.layui-col-xs-offset2{margin-left:16.66666667%}.layui-col-xs-offset3{margin-left:25%}.layui-col-xs-offset4{margin-left:33.33333333%}.layui-col-xs-offset5{margin-left:41.66666667%}.layui-col-xs-offset6{margin-left:50%}.layui-col-xs-offset7{margin-left:58.33333333%}.layui-col-xs-offset8{margin-left:66.66666667%}.layui-col-xs-offset9{margin-left:75%}.layui-col-xs-offset10{margin-left:83.33333333%}.layui-col-xs-offset11{margin-left:91.66666667%}.layui-col-xs-offset12{margin-left:100%}@media screen and (max-width:768px){.layui-hide-xs{display:none!important}.layui-show-xs-block{display:block!important}.layui-show-xs-inline{display:inline!important}.layui-show-xs-inline-block{display:inline-block!important}}@media screen and (min-width:768px){.layui-container{width:750px}.layui-hide-sm{display:none!important}.layui-show-sm-block{display:block!important}.layui-show-sm-inline{display:inline!important}.layui-show-sm-inline-block{display:inline-block!important}.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9{float:left}.layui-col-sm1{width:8.33333333%}.layui-col-sm2{width:16.66666667%}.layui-col-sm3{width:25%}.layui-col-sm4{width:33.33333333%}.layui-col-sm5{width:41.66666667%}.layui-col-sm6{width:50%}.layui-col-sm7{width:58.33333333%}.layui-col-sm8{width:66.66666667%}.layui-col-sm9{width:75%}.layui-col-sm10{width:83.33333333%}.layui-col-sm11{width:91.66666667%}.layui-col-sm12{width:100%}.layui-col-sm-offset1{margin-left:8.33333333%}.layui-col-sm-offset2{margin-left:16.66666667%}.layui-col-sm-offset3{margin-left:25%}.layui-col-sm-offset4{margin-left:33.33333333%}.layui-col-sm-offset5{margin-left:41.66666667%}.layui-col-sm-offset6{margin-left:50%}.layui-col-sm-offset7{margin-left:58.33333333%}.layui-col-sm-offset8{margin-left:66.66666667%}.layui-col-sm-offset9{margin-left:75%}.layui-col-sm-offset10{margin-left:83.33333333%}.layui-col-sm-offset11{margin-left:91.66666667%}.layui-col-sm-offset12{margin-left:100%}}@media screen and (min-width:992px){.layui-container{width:970px}.layui-hide-md{display:none!important}.layui-show-md-block{display:block!important}.layui-show-md-inline{display:inline!important}.layui-show-md-inline-block{display:inline-block!important}.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9{float:left}.layui-col-md1{width:8.33333333%}.layui-col-md2{width:16.66666667%}.layui-col-md3{width:25%}.layui-col-md4{width:33.33333333%}.layui-col-md5{width:41.66666667%}.layui-col-md6{width:50%}.layui-col-md7{width:58.33333333%}.layui-col-md8{width:66.66666667%}.layui-col-md9{width:75%}.layui-col-md10{width:83.33333333%}.layui-col-md11{width:91.66666667%}.layui-col-md12{width:100%}.layui-col-md-offset1{margin-left:8.33333333%}.layui-col-md-offset2{margin-left:16.66666667%}.layui-col-md-offset3{margin-left:25%}.layui-col-md-offset4{margin-left:33.33333333%}.layui-col-md-offset5{margin-left:41.66666667%}.layui-col-md-offset6{margin-left:50%}.layui-col-md-offset7{margin-left:58.33333333%}.layui-col-md-offset8{margin-left:66.66666667%}.layui-col-md-offset9{margin-left:75%}.layui-col-md-offset10{margin-left:83.33333333%}.layui-col-md-offset11{margin-left:91.66666667%}.layui-col-md-offset12{margin-left:100%}}@media screen and (min-width:1200px){.layui-container{width:1170px}.layui-hide-lg{display:none!important}.layui-show-lg-block{display:block!important}.layui-show-lg-inline{display:inline!important}.layui-show-lg-inline-block{display:inline-block!important}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9{float:left}.layui-col-lg1{width:8.33333333%}.layui-col-lg2{width:16.66666667%}.layui-col-lg3{width:25%}.layui-col-lg4{width:33.33333333%}.layui-col-lg5{width:41.66666667%}.layui-col-lg6{width:50%}.layui-col-lg7{width:58.33333333%}.layui-col-lg8{width:66.66666667%}.layui-col-lg9{width:75%}.layui-col-lg10{width:83.33333333%}.layui-col-lg11{width:91.66666667%}.layui-col-lg12{width:100%}.layui-col-lg-offset1{margin-left:8.33333333%}.layui-col-lg-offset2{margin-left:16.66666667%}.layui-col-lg-offset3{margin-left:25%}.layui-col-lg-offset4{margin-left:33.33333333%}.layui-col-lg-offset5{margin-left:41.66666667%}.layui-col-lg-offset6{margin-left:50%}.layui-col-lg-offset7{margin-left:58.33333333%}.layui-col-lg-offset8{margin-left:66.66666667%}.layui-col-lg-offset9{margin-left:75%}.layui-col-lg-offset10{margin-left:83.33333333%}.layui-col-lg-offset11{margin-left:91.66666667%}.layui-col-lg-offset12{margin-left:100%}}.layui-col-space1{margin:-.5px}.layui-col-space1>*{padding:.5px}.layui-col-space2{margin:-1px}.layui-col-space2>*{padding:1px}.layui-col-space4{margin:-2px}.layui-col-space4>*{padding:2px}.layui-col-space5{margin:-2.5px}.layui-col-space5>*{padding:2.5px}.layui-col-space6{margin:-3px}.layui-col-space6>*{padding:3px}.layui-col-space8{margin:-4px}.layui-col-space8>*{padding:4px}.layui-col-space10{margin:-5px}.layui-col-space10>*{padding:5px}.layui-col-space12{margin:-6px}.layui-col-space12>*{padding:6px}.layui-col-space14{margin:-7px}.layui-col-space14>*{padding:7px}.layui-col-space15{margin:-7.5px}.layui-col-space15>*{padding:7.5px}.layui-col-space16{margin:-8px}.layui-col-space16>*{padding:8px}.layui-col-space18{margin:-9px}.layui-col-space18>*{padding:9px}.layui-col-space20{margin:-10px}.layui-col-space20>*{padding:10px}.layui-col-space22{margin:-11px}.layui-col-space22>*{padding:11px}.layui-col-space24{margin:-12px}.layui-col-space24>*{padding:12px}.layui-col-space25{margin:-12.5px}.layui-col-space25>*{padding:12.5px}.layui-col-space26{margin:-13px}.layui-col-space26>*{padding:13px}.layui-col-space28{margin:-14px}.layui-col-space28>*{padding:14px}.layui-col-space30{margin:-15px}.layui-col-space30>*{padding:15px}.layui-btn,.layui-input,.layui-select,.layui-textarea,.layui-upload-button{outline:0;-webkit-appearance:none;transition:all .3s;-webkit-transition:all .3s;box-sizing:border-box}.layui-elem-quote{margin-bottom:10px;padding:15px;line-height:1.6;border-left:5px solid #5FB878;border-radius:0 2px 2px 0;background-color:#FAFAFA}.layui-quote-nm{border-style:solid;border-width:1px 1px 1px 5px;background:0 0}.layui-elem-field{margin-bottom:10px;padding:0;border-width:1px;border-style:solid}.layui-elem-field legend{margin-left:20px;padding:0 10px;font-size:20px;font-weight:300}.layui-field-title{margin:10px 0 20px;border-width:1px 0 0}.layui-field-box{padding:15px}.layui-field-title .layui-field-box{padding:10px 0}.layui-progress{position:relative;height:6px;border-radius:20px;background-color:#eee}.layui-progress-bar{position:absolute;left:0;top:0;width:0;max-width:100%;height:6px;border-radius:20px;text-align:right;background-color:#5FB878;transition:all .3s;-webkit-transition:all .3s}.layui-progress-big,.layui-progress-big .layui-progress-bar{height:18px;line-height:18px}.layui-progress-text{position:relative;top:-20px;line-height:18px;font-size:12px;color:#666}.layui-progress-big .layui-progress-text{position:static;padding:0 10px;color:#fff}.layui-collapse{border-width:1px;border-style:solid;border-radius:2px}.layui-colla-content,.layui-colla-item{border-top-width:1px;border-top-style:solid}.layui-colla-item:first-child{border-top:none}.layui-colla-title{position:relative;height:42px;line-height:42px;padding:0 15px 0 35px;color:#333;background-color:#FAFAFA;cursor:pointer;font-size:14px;overflow:hidden}.layui-colla-content{display:none;padding:10px 15px;line-height:1.6;color:#666}.layui-colla-icon{position:absolute;left:15px;top:0;font-size:14px}.layui-card-body,.layui-card-header,.layui-form-label,.layui-form-mid,.layui-form-select,.layui-input-block,.layui-input-inline,.layui-panel,.layui-textarea{position:relative}.layui-card{margin-bottom:15px;border-radius:2px;background-color:#fff;box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.layui-form-select dl,.layui-panel{box-shadow:1px 1px 4px rgb(0 0 0 / 8%)}.layui-card:last-child{margin-bottom:0}.layui-card-header{height:42px;line-height:42px;padding:0 15px;border-bottom:1px solid #f6f6f6;color:#333;border-radius:2px 2px 0 0;font-size:14px}.layui-card-body{padding:10px 15px;line-height:24px}.layui-card-body[pad15]{padding:15px}.layui-card-body[pad20]{padding:20px}.layui-card-body .layui-table{margin:5px 0}.layui-card .layui-tab{margin:0}.layui-panel{border-width:1px;border-style:solid;border-radius:2px;background-color:#fff;color:#666}.layui-bg-black,.layui-bg-blue,.layui-bg-cyan,.layui-bg-green,.layui-bg-orange,.layui-bg-red{color:#fff!important}.layui-panel-window{position:relative;padding:15px;border-radius:0;border-top:5px solid #eee;background-color:#fff}.layui-border,.layui-border-black,.layui-border-blue,.layui-border-cyan,.layui-border-green,.layui-border-orange,.layui-border-red{border-width:1px;border-style:solid}.layui-auxiliar-moving{position:fixed;left:0;right:0;top:0;bottom:0;width:100%;height:100%;background:0 0;z-index:9999999999}.layui-bg-red{background-color:#FF5722!important}.layui-bg-orange{background-color:#FFB800!important}.layui-bg-green{background-color:#009688!important}.layui-bg-cyan{background-color:#2F4056!important}.layui-bg-blue{background-color:#1E9FFF!important}.layui-bg-black{background-color:#393D49!important}.layui-bg-gray{background-color:#FAFAFA!important;color:#666!important}.layui-badge-rim,.layui-border,.layui-colla-content,.layui-colla-item,.layui-collapse,.layui-elem-field,.layui-form-pane .layui-form-item[pane],.layui-form-pane .layui-form-label,.layui-input,.layui-layedit,.layui-layedit-tool,.layui-panel,.layui-quote-nm,.layui-select,.layui-tab-bar,.layui-tab-card,.layui-tab-title,.layui-tab-title .layui-this:after,.layui-textarea{border-color:#eee}.layui-border{color:#666!important}.layui-border-red{border-color:#FF5722!important;color:#FF5722!important}.layui-border-orange{border-color:#FFB800!important;color:#FFB800!important}.layui-border-green{border-color:#009688!important;color:#009688!important}.layui-border-cyan{border-color:#2F4056!important;color:#2F4056!important}.layui-border-blue{border-color:#1E9FFF!important;color:#1E9FFF!important}.layui-border-black{border-color:#393D49!important;color:#393D49!important}.layui-timeline-item:before{background-color:#eee}.layui-text{line-height:1.6;font-size:14px;color:#666}.layui-text h1,.layui-text h2,.layui-text h3{font-weight:500;color:#333}.layui-text h1{font-size:30px}.layui-text h2{font-size:24px}.layui-text h3{font-size:18px}.layui-text a:not(.layui-btn){color:#01AAED}.layui-text a:not(.layui-btn):hover{text-decoration:underline}.layui-text ul{padding:5px 0 5px 15px}.layui-text ul li{margin-top:5px;list-style-type:disc}.layui-text em,.layui-word-aux{color:#999!important;padding-left:5px!important;padding-right:5px!important}.layui-text p{margin:10px 0}.layui-text p:first-child{margin-top:0}.layui-font-12{font-size:12px!important}.layui-font-14{font-size:14px!important}.layui-font-16{font-size:16px!important}.layui-font-18{font-size:18px!important}.layui-font-20{font-size:20px!important}.layui-font-red{color:#FF5722!important}.layui-font-orange{color:#FFB800!important}.layui-font-green{color:#009688!important}.layui-font-cyan{color:#2F4056!important}.layui-font-blue{color:#01AAED!important}.layui-font-black{color:#000!important}.layui-font-gray{color:#c2c2c2!important}.layui-btn{height:38px;line-height:38px;border:1px solid transparent;padding:0 18px;background-color:#009688;color:#fff;white-space:nowrap;text-align:center;font-size:14px;border-radius:2px;cursor:pointer}.layui-btn:hover{opacity:.8;filter:alpha(opacity=80);color:#fff}.layui-btn:active{opacity:1;filter:alpha(opacity=100)}.layui-btn+.layui-btn{margin-left:10px}.layui-btn-container{font-size:0}.layui-btn-container .layui-btn{margin-right:10px;margin-bottom:10px}.layui-btn-container .layui-btn+.layui-btn{margin-left:0}.layui-table .layui-btn-container .layui-btn{margin-bottom:9px}.layui-btn-radius{border-radius:100px}.layui-btn .layui-icon{padding:0 2px;vertical-align:middle\9;vertical-align:bottom}.layui-btn-primary{border-color:#d2d2d2;background:0 0;color:#666}.layui-btn-primary:hover{border-color:#009688;color:#333}.layui-btn-normal{background-color:#1E9FFF}.layui-btn-warm{background-color:#FFB800}.layui-btn-danger{background-color:#FF5722}.layui-btn-checked{background-color:#5FB878}.layui-btn-disabled,.layui-btn-disabled:active,.layui-btn-disabled:hover{border-color:#eee!important;background-color:#FBFBFB!important;color:#d2d2d2!important;cursor:not-allowed!important;opacity:1}.layui-btn-lg{height:44px;line-height:44px;padding:0 25px;font-size:16px}.layui-btn-sm{height:30px;line-height:30px;padding:0 10px;font-size:12px}.layui-btn-xs{height:22px;line-height:22px;padding:0 5px;font-size:12px}.layui-btn-xs i{font-size:12px!important}.layui-btn-group{vertical-align:middle;font-size:0}.layui-btn-group .layui-btn{margin-left:0!important;margin-right:0!important;border-left:1px solid rgba(255,255,255,.5);border-radius:0}.layui-btn-group .layui-btn-primary{border-left:none}.layui-btn-group .layui-btn-primary:hover{border-color:#d2d2d2;color:#009688}.layui-btn-group .layui-btn:first-child{border-left:none;border-radius:2px 0 0 2px}.layui-btn-group .layui-btn-primary:first-child{border-left:1px solid #d2d2d2}.layui-btn-group .layui-btn:last-child{border-radius:0 2px 2px 0}.layui-btn-group .layui-btn+.layui-btn{margin-left:0}.layui-btn-group+.layui-btn-group{margin-left:10px}.layui-btn-fluid{width:100%}.layui-input,.layui-select,.layui-textarea{height:38px;line-height:1.3;line-height:38px\9;border-width:1px;border-style:solid;background-color:#fff;color:rgba(0,0,0,.85);border-radius:2px}.layui-input::-webkit-input-placeholder,.layui-select::-webkit-input-placeholder,.layui-textarea::-webkit-input-placeholder{line-height:1.3}.layui-input,.layui-textarea{display:block;width:100%;padding-left:10px}.layui-input:hover,.layui-textarea:hover{border-color:#eee!important}.layui-input:focus,.layui-textarea:focus{border-color:#d2d2d2!important}.layui-textarea{min-height:100px;height:auto;line-height:20px;padding:6px 10px;resize:vertical}.layui-select{padding:0 10px}.layui-form input[type=checkbox],.layui-form input[type=radio],.layui-form select{display:none}.layui-form [lay-ignore]{display:initial}.layui-form-item{margin-bottom:15px;clear:both;*zoom:1}.layui-form-item:after{content:'\20';clear:both;*zoom:1;display:block;height:0}.layui-form-label{float:left;display:block;padding:9px 15px;width:80px;font-weight:400;line-height:20px;text-align:right}.layui-form-label-col{display:block;float:none;padding:9px 0;line-height:20px;text-align:left}.layui-form-item .layui-inline{margin-bottom:5px;margin-right:10px}.layui-input-block{margin-left:110px;min-height:36px}.layui-input-inline{display:inline-block;vertical-align:middle}.layui-form-item .layui-input-inline{float:left;width:190px;margin-right:10px}.layui-form-text .layui-input-inline{width:auto}.layui-form-mid{float:left;display:block;padding:9px 0!important;line-height:20px;margin-right:10px}.layui-form-danger+.layui-form-select .layui-input,.layui-form-danger:focus{border-color:#FF5722!important}.layui-form-select .layui-input{padding-right:30px;cursor:pointer}.layui-form-select .layui-edge{position:absolute;right:10px;top:50%;margin-top:-3px;cursor:pointer;border-width:6px;border-top-color:#c2c2c2;border-top-style:solid;transition:all .3s;-webkit-transition:all .3s}.layui-form-select dl{display:none;position:absolute;left:0;top:42px;padding:5px 0;z-index:899;min-width:100%;border:1px solid #eee;max-height:300px;overflow-y:auto;background-color:#fff;border-radius:2px;box-sizing:border-box}.layui-form-select dl dd,.layui-form-select dl dt{padding:0 10px;line-height:36px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.layui-form-select dl dt{font-size:12px;color:#999}.layui-form-select dl dd{cursor:pointer}.layui-form-select dl dd:hover{background-color:#F6F6F6;-webkit-transition:.5s all;transition:.5s all}.layui-form-select .layui-select-group dd{padding-left:20px}.layui-form-select dl dd.layui-select-tips{padding-left:10px!important;color:#999}.layui-form-select dl dd.layui-this{background-color:#5FB878;color:#fff}.layui-form-checkbox,.layui-form-select dl dd.layui-disabled{background-color:#fff}.layui-form-selected dl{display:block}.layui-form-checkbox,.layui-form-checkbox *,.layui-form-switch{display:inline-block;vertical-align:middle}.layui-form-selected .layui-edge{margin-top:-9px;-webkit-transform:rotate(180deg);transform:rotate(180deg);margin-top:-3px\9}:root .layui-form-selected .layui-edge{margin-top:-9px\0/IE9}.layui-form-selectup dl{top:auto;bottom:42px}.layui-select-none{margin:5px 0;text-align:center;color:#999}.layui-select-disabled .layui-disabled{border-color:#eee!important}.layui-select-disabled .layui-edge{border-top-color:#d2d2d2}.layui-form-checkbox{position:relative;height:30px;line-height:30px;margin-right:10px;padding-right:30px;cursor:pointer;font-size:0;-webkit-transition:.1s linear;transition:.1s linear;box-sizing:border-box}.layui-form-checkbox span{padding:0 10px;height:100%;font-size:14px;border-radius:2px 0 0 2px;background-color:#d2d2d2;color:#fff;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.layui-form-checkbox:hover span{background-color:#c2c2c2}.layui-form-checkbox i{position:absolute;right:0;top:0;width:30px;height:28px;border:1px solid #d2d2d2;border-left:none;border-radius:0 2px 2px 0;color:#fff;font-size:20px;text-align:center}.layui-form-checkbox:hover i{border-color:#c2c2c2;color:#c2c2c2}.layui-form-checked,.layui-form-checked:hover{border-color:#5FB878}.layui-form-checked span,.layui-form-checked:hover span{background-color:#5FB878}.layui-form-checked i,.layui-form-checked:hover i{color:#5FB878}.layui-form-item .layui-form-checkbox{margin-top:4px}.layui-form-checkbox[lay-skin=primary]{height:auto!important;line-height:normal!important;min-width:18px;min-height:18px;border:none!important;margin-right:0;padding-left:28px;padding-right:0;background:0 0}.layui-form-checkbox[lay-skin=primary] span{padding-left:0;padding-right:15px;line-height:18px;background:0 0;color:#666}.layui-form-checkbox[lay-skin=primary] i{right:auto;left:0;width:16px;height:16px;line-height:16px;border:1px solid #d2d2d2;font-size:12px;border-radius:2px;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-checkbox[lay-skin=primary]:hover i{border-color:#5FB878;color:#fff}.layui-form-checked[lay-skin=primary] i{border-color:#5FB878!important;background-color:#5FB878;color:#fff}.layui-checkbox-disabled[lay-skin=primary] span{background:0 0!important;color:#c2c2c2!important}.layui-checkbox-disabled[lay-skin=primary]:hover i{border-color:#d2d2d2}.layui-form-item .layui-form-checkbox[lay-skin=primary]{margin-top:10px}.layui-form-switch{position:relative;height:22px;line-height:22px;min-width:35px;padding:0 5px;margin-top:8px;border:1px solid #d2d2d2;border-radius:20px;cursor:pointer;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch i{position:absolute;left:5px;top:3px;width:16px;height:16px;border-radius:20px;background-color:#d2d2d2;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch em{position:relative;top:0;width:25px;margin-left:21px;padding:0!important;text-align:center!important;color:#999!important;font-style:normal!important;font-size:12px}.layui-form-onswitch{border-color:#5FB878;background-color:#5FB878}.layui-checkbox-disabled,.layui-checkbox-disabled i{border-color:#eee!important}.layui-form-onswitch i{left:100%;margin-left:-21px;background-color:#fff}.layui-form-onswitch em{margin-left:5px;margin-right:21px;color:#fff!important}.layui-checkbox-disabled span{background-color:#eee!important}.layui-checkbox-disabled em{color:#d2d2d2!important}.layui-checkbox-disabled:hover i{color:#fff!important}[lay-radio]{display:none}.layui-form-radio,.layui-form-radio *{display:inline-block;vertical-align:middle}.layui-form-radio{line-height:28px;margin:6px 10px 0 0;padding-right:10px;cursor:pointer;font-size:0}.layui-form-radio *{font-size:14px}.layui-form-radio>i{margin-right:8px;font-size:22px;color:#c2c2c2}.layui-form-radio:hover *,.layui-form-radioed,.layui-form-radioed>i{color:#5FB878}.layui-radio-disabled>i{color:#eee!important}.layui-radio-disabled *{color:#c2c2c2!important}.layui-form-pane .layui-form-label{width:110px;padding:8px 15px;height:38px;line-height:20px;border-width:1px;border-style:solid;border-radius:2px 0 0 2px;text-align:center;background-color:#FAFAFA;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;box-sizing:border-box}.layui-form-pane .layui-input-inline{margin-left:-1px}.layui-form-pane .layui-input-block{margin-left:110px;left:-1px}.layui-form-pane .layui-input{border-radius:0 2px 2px 0}.layui-form-pane .layui-form-text .layui-form-label{float:none;width:100%;border-radius:2px;box-sizing:border-box;text-align:left}.layui-form-pane .layui-form-text .layui-input-inline{display:block;margin:0;top:-1px;clear:both}.layui-form-pane .layui-form-text .layui-input-block{margin:0;left:0;top:-1px}.layui-form-pane .layui-form-text .layui-textarea{min-height:100px;border-radius:0 0 2px 2px}.layui-form-pane .layui-form-checkbox{margin:4px 0 4px 10px}.layui-form-pane .layui-form-radio,.layui-form-pane .layui-form-switch{margin-top:6px;margin-left:10px}.layui-form-pane .layui-form-item[pane]{position:relative;border-width:1px;border-style:solid}.layui-form-pane .layui-form-item[pane] .layui-form-label{position:absolute;left:0;top:0;height:100%;border-width:0 1px 0 0}.layui-form-pane .layui-form-item[pane] .layui-input-inline{margin-left:110px}@media screen and (max-width:450px){.layui-form-item .layui-form-label{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-form-item .layui-inline{display:block;margin-right:0;margin-bottom:20px;clear:both}.layui-form-item .layui-inline:after{content:'\20';clear:both;display:block;height:0}.layui-form-item .layui-input-inline{display:block;float:none;left:-3px;width:auto!important;margin:0 0 10px 112px}.layui-form-item .layui-input-inline+.layui-form-mid{margin-left:110px;top:-5px;padding:0}.layui-form-item .layui-form-checkbox{margin-right:5px;margin-bottom:5px}}.layui-layedit{border-width:1px;border-style:solid;border-radius:2px}.layui-layedit-tool{padding:3px 5px;border-bottom-width:1px;border-bottom-style:solid;font-size:0}.layedit-tool-fixed{position:fixed;top:0;border-top:1px solid #eee}.layui-layedit-tool .layedit-tool-mid,.layui-layedit-tool .layui-icon{display:inline-block;vertical-align:middle;text-align:center;font-size:14px}.layui-layedit-tool .layui-icon{position:relative;width:32px;height:30px;line-height:30px;margin:3px 5px;color:#777;cursor:pointer;border-radius:2px}.layui-layedit-tool .layui-icon:hover{color:#393D49}.layui-layedit-tool .layui-icon:active{color:#000}.layui-layedit-tool .layedit-tool-active{background-color:#eee;color:#000}.layui-layedit-tool .layui-disabled,.layui-layedit-tool .layui-disabled:hover{color:#d2d2d2;cursor:not-allowed}.layui-layedit-tool .layedit-tool-mid{width:1px;height:18px;margin:0 10px;background-color:#d2d2d2}.layedit-tool-html{width:50px!important;font-size:30px!important}.layedit-tool-b,.layedit-tool-code,.layedit-tool-help{font-size:16px!important}.layedit-tool-d,.layedit-tool-face,.layedit-tool-image,.layedit-tool-unlink{font-size:18px!important}.layedit-tool-image input{position:absolute;font-size:0;left:0;top:0;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-layedit-iframe iframe{display:block;width:100%}#LAY_layedit_code{overflow:hidden}.layui-laypage{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;margin:10px 0;font-size:0}.layui-laypage>a:first-child,.layui-laypage>a:first-child em{border-radius:2px 0 0 2px}.layui-laypage>a:last-child,.layui-laypage>a:last-child em{border-radius:0 2px 2px 0}.layui-laypage>:first-child{margin-left:0!important}.layui-laypage>:last-child{margin-right:0!important}.layui-laypage a,.layui-laypage button,.layui-laypage input,.layui-laypage select,.layui-laypage span{border:1px solid #eee}.layui-laypage a,.layui-laypage span{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;padding:0 15px;height:28px;line-height:28px;margin:0 -1px 5px 0;background-color:#fff;color:#333;font-size:12px}.layui-flow-more a *,.layui-laypage input,.layui-table-view select[lay-ignore]{display:inline-block}.layui-laypage a:hover{color:#009688}.layui-laypage em{font-style:normal}.layui-laypage .layui-laypage-spr{color:#999;font-weight:700}.layui-laypage a{text-decoration:none}.layui-laypage .layui-laypage-curr{position:relative}.layui-laypage .layui-laypage-curr em{position:relative;color:#fff}.layui-laypage .layui-laypage-curr .layui-laypage-em{position:absolute;left:-1px;top:-1px;padding:1px;width:100%;height:100%;background-color:#009688}.layui-laypage-em{border-radius:2px}.layui-laypage-next em,.layui-laypage-prev em{font-family:Sim sun;font-size:16px}.layui-laypage .layui-laypage-count,.layui-laypage .layui-laypage-limits,.layui-laypage .layui-laypage-refresh,.layui-laypage .layui-laypage-skip{margin-left:10px;margin-right:10px;padding:0;border:none}.layui-laypage .layui-laypage-limits,.layui-laypage .layui-laypage-refresh{vertical-align:top}.layui-laypage .layui-laypage-refresh i{font-size:18px;cursor:pointer}.layui-laypage select{height:22px;padding:3px;border-radius:2px;cursor:pointer}.layui-laypage .layui-laypage-skip{height:30px;line-height:30px;color:#999}.layui-laypage button,.layui-laypage input{height:30px;line-height:30px;border-radius:2px;vertical-align:top;background-color:#fff;box-sizing:border-box}.layui-laypage input{width:40px;margin:0 10px;padding:0 3px;text-align:center}.layui-laypage input:focus,.layui-laypage select:focus{border-color:#009688!important}.layui-laypage button{margin-left:10px;padding:0 10px;cursor:pointer}.layui-table,.layui-table-view{margin:10px 0}.layui-flow-more{margin:10px 0;text-align:center;color:#999;font-size:14px}.layui-flow-more a{height:32px;line-height:32px}.layui-flow-more a *{vertical-align:top}.layui-flow-more a cite{padding:0 20px;border-radius:3px;background-color:#eee;color:#333;font-style:normal}.layui-flow-more a cite:hover{opacity:.8}.layui-flow-more a i{font-size:30px;color:#737383}.layui-table{width:100%;background-color:#fff;color:#666}.layui-table tr{transition:all .3s;-webkit-transition:all .3s}.layui-table th{text-align:left;font-weight:400}.layui-table tbody tr:hover,.layui-table thead tr,.layui-table-click,.layui-table-header,.layui-table-hover,.layui-table-mend,.layui-table-patch,.layui-table-tool,.layui-table-total,.layui-table-total tr,.layui-table[lay-even] tr:nth-child(even){background-color:#FAFAFA}.layui-table td,.layui-table th,.layui-table-col-set,.layui-table-fixed-r,.layui-table-grid-down,.layui-table-header,.layui-table-page,.layui-table-tips-main,.layui-table-tool,.layui-table-total,.layui-table-view,.layui-table[lay-skin=line],.layui-table[lay-skin=row]{border-width:1px;border-style:solid;border-color:#eee}.layui-table td,.layui-table th{position:relative;padding:9px 15px;min-height:20px;line-height:20px;font-size:14px}.layui-table[lay-skin=line] td,.layui-table[lay-skin=line] th{border-width:0 0 1px}.layui-table[lay-skin=row] td,.layui-table[lay-skin=row] th{border-width:0 1px 0 0}.layui-table[lay-skin=nob] td,.layui-table[lay-skin=nob] th{border:none}.layui-table img{max-width:100px}.layui-table[lay-size=lg] td,.layui-table[lay-size=lg] th{padding:15px 30px}.layui-table-view .layui-table[lay-size=lg] .layui-table-cell{height:40px;line-height:40px}.layui-table[lay-size=sm] td,.layui-table[lay-size=sm] th{font-size:12px;padding:5px 10px}.layui-table-view .layui-table[lay-size=sm] .layui-table-cell{height:20px;line-height:20px}.layui-table[lay-data]{display:none}.layui-table-box{position:relative;overflow:hidden}.layui-table-view .layui-table{position:relative;width:auto;margin:0}.layui-table-view .layui-table[lay-skin=line]{border-width:0 1px 0 0}.layui-table-view .layui-table[lay-skin=row]{border-width:0 0 1px}.layui-table-view .layui-table td,.layui-table-view .layui-table th{padding:5px 0;border-top:none;border-left:none}.layui-table-view .layui-table th.layui-unselect .layui-table-cell span{cursor:pointer}.layui-table-view .layui-table td{cursor:default}.layui-table-view .layui-table td[data-edit=text]{cursor:text}.layui-table-view .layui-form-checkbox[lay-skin=primary] i{width:18px;height:18px}.layui-table-view .layui-form-radio{line-height:0;padding:0}.layui-table-view .layui-form-radio>i{margin:0;font-size:20px}.layui-table-init{position:absolute;left:0;top:0;width:100%;height:100%;text-align:center;z-index:110}.layui-table-init .layui-icon{position:absolute;left:50%;top:50%;margin:-15px 0 0 -15px;font-size:30px;color:#c2c2c2}.layui-table-header{border-width:0 0 1px;overflow:hidden}.layui-table-header .layui-table{margin-bottom:-1px}.layui-table-tool .layui-inline[lay-event]{position:relative;width:26px;height:26px;padding:5px;line-height:16px;margin-right:10px;text-align:center;color:#333;border:1px solid #ccc;cursor:pointer;-webkit-transition:.5s all;transition:.5s all}.layui-table-tool .layui-inline[lay-event]:hover{border:1px solid #999}.layui-table-tool-temp{padding-right:120px}.layui-table-tool-self{position:absolute;right:17px;top:10px}.layui-table-tool .layui-table-tool-self .layui-inline[lay-event]{margin:0 0 0 10px}.layui-table-tool-panel{position:absolute;top:29px;left:-1px;padding:5px 0;min-width:150px;min-height:40px;border:1px solid #d2d2d2;text-align:left;overflow-y:auto;background-color:#fff;box-shadow:0 2px 4px rgba(0,0,0,.12)}.layui-table-cell,.layui-table-tool-panel li{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.layui-table-tool-panel li{padding:0 10px;line-height:30px;-webkit-transition:.5s all;transition:.5s all}.layui-menu li,.layui-menu-body-title a:hover,.layui-menu-body-title>.layui-icon:hover{transition:all .3s}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary]{width:100%;padding-left:28px}.layui-table-tool-panel li:hover{background-color:#F6F6F6}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary] i{position:absolute;left:0;top:0}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary] span{padding:0}.layui-table-tool .layui-table-tool-self .layui-table-tool-panel{left:auto;right:-1px}.layui-table-col-set{position:absolute;right:0;top:0;width:20px;height:100%;border-width:0 0 0 1px;background-color:#fff}.layui-table-sort{width:10px;height:20px;margin-left:5px;cursor:pointer!important}.layui-table-sort .layui-edge{position:absolute;left:5px;border-width:5px}.layui-table-sort .layui-table-sort-asc{top:3px;border-top:none;border-bottom-style:solid;border-bottom-color:#b2b2b2}.layui-table-sort .layui-table-sort-asc:hover{border-bottom-color:#666}.layui-table-sort .layui-table-sort-desc{bottom:5px;border-bottom:none;border-top-style:solid;border-top-color:#b2b2b2}.layui-table-sort .layui-table-sort-desc:hover{border-top-color:#666}.layui-table-sort[lay-sort=asc] .layui-table-sort-asc{border-bottom-color:#000}.layui-table-sort[lay-sort=desc] .layui-table-sort-desc{border-top-color:#000}.layui-table-cell{height:28px;line-height:28px;padding:0 15px;position:relative;box-sizing:border-box}.layui-table-cell .layui-form-checkbox[lay-skin=primary]{top:-1px;padding:0}.layui-table-cell .layui-table-link{color:#01AAED}.laytable-cell-checkbox,.laytable-cell-numbers,.laytable-cell-radio,.laytable-cell-space{padding:0;text-align:center}.layui-table-body{position:relative;overflow:auto;margin-right:-1px;margin-bottom:-1px}.layui-table-body .layui-none{line-height:26px;padding:30px 15px;text-align:center;color:#999}.layui-table-fixed{position:absolute;left:0;top:0;z-index:101}.layui-table-fixed .layui-table-body{overflow:hidden}.layui-table-fixed-l{box-shadow:1px 0 8px rgba(0,0,0,.08)}.layui-table-fixed-r{left:auto;right:-1px;border-width:0 0 0 1px;box-shadow:-1px 0 8px rgba(0,0,0,.08)}.layui-table-fixed-r .layui-table-header{position:relative;overflow:visible}.layui-table-mend{position:absolute;right:-49px;top:0;height:100%;width:50px}.layui-table-tool{position:relative;z-index:890;width:100%;min-height:50px;line-height:30px;padding:10px 15px;border-width:0 0 1px}.layui-table-tool .layui-btn-container{margin-bottom:-10px}.layui-table-page,.layui-table-total{border-width:1px 0 0;margin-bottom:-1px;overflow:hidden}.layui-table-page{position:relative;width:100%;padding:7px 7px 0;height:41px;font-size:12px;white-space:nowrap}.layui-table-page>div{height:26px}.layui-table-page .layui-laypage{margin:0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span{height:26px;line-height:26px;margin-bottom:10px;border:none;background:0 0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span.layui-laypage-curr{padding:0 12px}.layui-table-page .layui-laypage span{margin-left:0;padding:0}.layui-table-page .layui-laypage .layui-laypage-prev{margin-left:-7px!important}.layui-table-page .layui-laypage .layui-laypage-curr .layui-laypage-em{left:0;top:0;padding:0}.layui-table-page .layui-laypage button,.layui-table-page .layui-laypage input{height:26px;line-height:26px}.layui-table-page .layui-laypage input{width:40px}.layui-table-page .layui-laypage button{padding:0 10px}.layui-table-page select{height:18px}.layui-table-patch .layui-table-cell{padding:0;width:30px}.layui-table-edit{position:absolute;left:0;top:0;width:100%;height:100%;padding:0 14px 1px;border-radius:0;box-shadow:1px 1px 20px rgba(0,0,0,.15)}.layui-table-edit:focus{border-color:#5FB878!important}select.layui-table-edit{padding:0 0 0 10px;border-color:#d2d2d2}.layui-table-view .layui-form-checkbox,.layui-table-view .layui-form-radio,.layui-table-view .layui-form-switch{top:0;margin:0;box-sizing:content-box}.layui-colorpicker-alpha-slider,.layui-colorpicker-side-slider,.layui-menu,.layui-menu *,.layui-nav{box-sizing:border-box}.layui-table-view .layui-form-checkbox{top:-1px;height:26px;line-height:26px}.layui-table-view .layui-form-checkbox i{height:26px}.layui-table-grid .layui-table-cell{overflow:visible}.layui-table-grid-down{position:absolute;top:0;right:0;width:26px;height:100%;padding:5px 0;border-width:0 0 0 1px;text-align:center;background-color:#fff;color:#999;cursor:pointer}.layui-table-grid-down .layui-icon{position:absolute;top:50%;left:50%;margin:-8px 0 0 -8px}.layui-table-grid-down:hover{background-color:#fbfbfb}body .layui-table-tips .layui-layer-content{background:0 0;padding:0;box-shadow:0 1px 6px rgba(0,0,0,.12)}.layui-table-tips-main{margin:-44px 0 0 -1px;max-height:150px;padding:8px 15px;font-size:14px;overflow-y:scroll;background-color:#fff;color:#666}.layui-table-tips-c{position:absolute;right:-3px;top:-13px;width:20px;height:20px;padding:3px;cursor:pointer;background-color:#666;border-radius:50%;color:#fff}.layui-table-tips-c:hover{background-color:#777}.layui-table-tips-c:before{position:relative;right:-2px}.layui-upload-file{display:none!important;opacity:.01;filter:Alpha(opacity=1)}.layui-upload-drag,.layui-upload-form,.layui-upload-wrap{display:inline-block}.layui-upload-list{margin:10px 0}.layui-upload-choose{max-width:200px;padding:0 10px;color:#999;font-size:14px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-upload-drag{position:relative;padding:30px;border:1px dashed #e2e2e2;background-color:#fff;text-align:center;cursor:pointer;color:#999}.layui-upload-drag .layui-icon{font-size:50px;color:#009688}.layui-upload-drag[lay-over]{border-color:#009688}.layui-upload-iframe{position:absolute;width:0;height:0;border:0;visibility:hidden}.layui-upload-wrap{position:relative;vertical-align:middle}.layui-upload-wrap .layui-upload-file{display:block!important;position:absolute;left:0;top:0;z-index:10;font-size:100px;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-btn-container .layui-upload-choose{padding-left:0}.layui-menu{position:relative;margin:5px 0;background-color:#fff}.layui-menu li,.layui-menu-body-title a{padding:5px 15px}.layui-menu li{position:relative;margin:1px 0;width:calc(100% + 1px);line-height:26px;color:rgba(0,0,0,.8);font-size:14px;white-space:nowrap;cursor:pointer}.layui-menu li:hover{background-color:#F6F6F6}.layui-menu-item-parent:hover>.layui-menu-body-panel{display:block;animation-name:layui-fadein;animation-duration:.3s;animation-fill-mode:both;animation-delay:.2s}.layui-menu-item-group .layui-menu-body-title,.layui-menu-item-parent .layui-menu-body-title{padding-right:25px}.layui-menu .layui-menu-item-divider:hover,.layui-menu .layui-menu-item-group:hover,.layui-menu .layui-menu-item-none:hover{background:0 0;cursor:default}.layui-menu .layui-menu-item-group>ul{margin:5px 0 -5px}.layui-menu .layui-menu-item-group>.layui-menu-body-title{color:rgba(0,0,0,.35);user-select:none}.layui-menu .layui-menu-item-none{color:rgba(0,0,0,.35);cursor:default;text-align:center}.layui-menu .layui-menu-item-divider{margin:5px 0;padding:0;height:0;line-height:0;border-bottom:1px solid #eee;overflow:hidden}.layui-menu .layui-menu-item-down:hover,.layui-menu .layui-menu-item-up:hover{cursor:pointer}.layui-menu .layui-menu-item-up>.layui-menu-body-title{color:rgba(0,0,0,.8)}.layui-menu .layui-menu-item-up>ul{visibility:hidden;height:0;overflow:hidden}.layui-menu .layui-menu-item-down:hover>.layui-menu-body-title>.layui-icon,.layui-menu .layui-menu-item-up>.layui-menu-body-title:hover>.layui-icon{color:rgba(0,0,0,1)}.layui-menu .layui-menu-item-down>ul{visibility:visible;height:auto}.layui-breadcrumb,.layui-tree-btnGroup{visibility:hidden}.layui-menu .layui-menu-item-checked,.layui-menu .layui-menu-item-checked2{background-color:#F6F6F6!important;color:#5FB878}.layui-menu .layui-menu-item-checked a,.layui-menu .layui-menu-item-checked2 a{color:#5FB878}.layui-menu .layui-menu-item-checked:after{position:absolute;right:0;top:0;bottom:0;border-right:3px solid #5FB878;content:""}.layui-menu-body-title{position:relative;overflow:hidden;text-overflow:ellipsis}.layui-menu-body-title a{display:block;margin:-5px -15px;color:rgba(0,0,0,.8)}.layui-menu-body-title>.layui-icon{position:absolute;right:0;top:0;font-size:14px}.layui-menu-body-title>.layui-icon-right{right:-1px}.layui-menu-body-panel{display:none;position:absolute;top:-7px;left:100%;z-index:1000;margin-left:13px;padding:5px 0}.layui-menu-body-panel:before{content:"";position:absolute;width:20px;left:-16px;top:0;bottom:0}.layui-menu-body-panel-left{left:auto;right:100%;margin:0 13px}.layui-menu-body-panel-left:before{left:auto;right:-16px}.layui-menu-lg li{line-height:32px}.layui-menu-lg .layui-menu-body-title a:hover,.layui-menu-lg li:hover{background:0 0;color:#5FB878}.layui-menu-lg li .layui-menu-body-panel{margin-left:14px}.layui-menu-lg li .layui-menu-body-panel-left{margin:0 15px}.layui-dropdown{position:absolute;left:-999999px;top:-999999px;z-index:66666666;margin:5px 0;min-width:100px}.layui-dropdown:before{content:"";position:absolute;width:100%;height:6px;left:0;top:-6px}.layui-nav{position:relative;padding:0 20px;background-color:#393D49;color:#fff;border-radius:2px;font-size:0}.layui-nav *{font-size:14px}.layui-nav .layui-nav-item{position:relative;display:inline-block;*display:inline;*zoom:1;vertical-align:middle;line-height:60px}.layui-nav .layui-nav-item a{display:block;padding:0 20px;color:#fff;color:rgba(255,255,255,.7);transition:all .3s;-webkit-transition:all .3s}.layui-nav .layui-this:after,.layui-nav-bar{content:"";position:absolute;left:0;top:0;width:0;height:5px;background-color:#5FB878;transition:all .2s;-webkit-transition:all .2s;pointer-events:none}.layui-nav-bar{z-index:1000}.layui-nav[lay-bar=disabled] .layui-nav-bar{display:none}.layui-nav .layui-nav-item a:hover,.layui-nav .layui-this a{color:#fff}.layui-nav .layui-this:after{top:auto;bottom:0;width:100%}.layui-nav-img{width:30px;height:30px;margin-right:10px;border-radius:50%}.layui-nav .layui-nav-more{position:absolute;top:0;right:3px;left:auto!important;margin-top:0;font-size:12px;cursor:pointer;transition:all .2s;-webkit-transition:all .2s}.layui-nav .layui-nav-mored,.layui-nav-itemed>a .layui-nav-more{transform:rotate(180deg)}.layui-nav-child{display:none;position:absolute;left:0;top:65px;min-width:100%;line-height:36px;padding:5px 0;box-shadow:0 2px 4px rgba(0,0,0,.12);border:1px solid #eee;background-color:#fff;z-index:100;border-radius:2px;white-space:nowrap}.layui-nav .layui-nav-child a{color:#666;color:rgba(0,0,0,.8)}.layui-nav .layui-nav-child a:hover{background-color:#F6F6F6;color:rgba(0,0,0,.8)}.layui-nav-child dd{margin:1px 0;position:relative}.layui-nav-child dd.layui-this{background-color:#F6F6F6;color:#000}.layui-nav-child dd.layui-this:after{display:none}.layui-nav-child-r{left:auto;right:0}.layui-nav-child-c{text-align:center}.layui-nav-tree{width:200px;padding:0}.layui-nav-tree .layui-nav-item{display:block;width:100%;line-height:40px}.layui-nav-tree .layui-nav-item a{position:relative;height:40px;line-height:40px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-nav-tree .layui-nav-item>a{padding-top:5px;padding-bottom:5px}.layui-nav-tree .layui-nav-more{right:15px}.layui-nav-tree .layui-nav-item>a .layui-nav-more{padding:5px 0}.layui-nav-tree .layui-nav-bar{width:5px;height:0;background-color:#009688}.layui-side .layui-nav-tree .layui-nav-bar{width:2px}.layui-nav-tree .layui-nav-child dd.layui-this,.layui-nav-tree .layui-nav-child dd.layui-this a,.layui-nav-tree .layui-this,.layui-nav-tree .layui-this>a,.layui-nav-tree .layui-this>a:hover{background-color:#009688;color:#fff}.layui-nav-tree .layui-this:after{display:none}.layui-nav-itemed>a,.layui-nav-tree .layui-nav-title a,.layui-nav-tree .layui-nav-title a:hover{color:#fff!important}.layui-nav-tree .layui-nav-child{position:relative;z-index:0;top:0;border:none;box-shadow:none}.layui-nav-tree .layui-nav-child dd{margin:0}.layui-nav-tree .layui-nav-child a{color:#fff;color:rgba(255,255,255,.7)}.layui-nav-tree .layui-nav-child,.layui-nav-tree .layui-nav-child a:hover{background:0 0;color:#fff}.layui-nav-itemed>.layui-nav-child{display:block;background-color:rgba(0,0,0,.3)!important}.layui-nav-itemed>.layui-nav-child>.layui-this>.layui-nav-child{display:block}.layui-nav-side{position:fixed;top:0;bottom:0;left:0;overflow-x:hidden;z-index:999}.layui-breadcrumb{font-size:0}.layui-breadcrumb>*{font-size:14px}.layui-breadcrumb a{color:#999!important}.layui-breadcrumb a:hover{color:#5FB878!important}.layui-breadcrumb a cite{color:#666;font-style:normal}.layui-breadcrumb span[lay-separator]{margin:0 10px;color:#999}.layui-tab{margin:10px 0;text-align:left!important}.layui-tab[overflow]>.layui-tab-title{overflow:hidden}.layui-tab-title{position:relative;left:0;height:40px;white-space:nowrap;font-size:0;border-bottom-width:1px;border-bottom-style:solid;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;font-size:14px;transition:all .2s;-webkit-transition:all .2s;position:relative;line-height:40px;min-width:65px;padding:0 15px;text-align:center;cursor:pointer}.layui-tab-title li a{display:block;padding:0 15px;margin:0 -15px}.layui-tab-title .layui-this{color:#000}.layui-tab-title .layui-this:after{position:absolute;left:0;top:0;content:"";width:100%;height:41px;border-width:1px;border-style:solid;border-bottom-color:#fff;border-radius:2px 2px 0 0;box-sizing:border-box;pointer-events:none}.layui-tab-bar{position:absolute;right:0;top:0;z-index:10;width:30px;height:39px;line-height:39px;border-width:1px;border-style:solid;border-radius:2px;text-align:center;background-color:#fff;cursor:pointer}.layui-tab-bar .layui-icon{position:relative;display:inline-block;top:3px;transition:all .3s;-webkit-transition:all .3s}.layui-tab-item{display:none}.layui-tab-more{padding-right:30px;height:auto!important;white-space:normal!important}.layui-tab-more li.layui-this:after{border-bottom-color:#eee;border-radius:2px}.layui-tab-more .layui-tab-bar .layui-icon{top:-2px;top:3px\9;-webkit-transform:rotate(180deg);transform:rotate(180deg)}:root .layui-tab-more .layui-tab-bar .layui-icon{top:-2px\0/IE9}.layui-tab-content{padding:15px 0}.layui-tab-title li .layui-tab-close{position:relative;display:inline-block;width:18px;height:18px;line-height:20px;margin-left:8px;top:1px;text-align:center;font-size:14px;color:#c2c2c2;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li .layui-tab-close:hover{border-radius:2px;background-color:#FF5722;color:#fff}.layui-tab-brief>.layui-tab-title .layui-this{color:#009688}.layui-tab-brief>.layui-tab-more li.layui-this:after,.layui-tab-brief>.layui-tab-title .layui-this:after{border:none;border-radius:0;border-bottom:2px solid #5FB878}.layui-tab-brief[overflow]>.layui-tab-title .layui-this:after{top:-1px}.layui-tab-card{border-width:1px;border-style:solid;border-radius:2px;box-shadow:0 2px 5px 0 rgba(0,0,0,.1)}.layui-tab-card>.layui-tab-title{background-color:#FAFAFA}.layui-tab-card>.layui-tab-title li{margin-right:-1px;margin-left:-1px}.layui-tab-card>.layui-tab-title .layui-this{background-color:#fff}.layui-tab-card>.layui-tab-title .layui-this:after{border-top:none;border-width:1px;border-bottom-color:#fff}.layui-tab-card>.layui-tab-title .layui-tab-bar{height:40px;line-height:40px;border-radius:0;border-top:none;border-right:none}.layui-tab-card>.layui-tab-more .layui-this{background:0 0;color:#5FB878}.layui-tab-card>.layui-tab-more .layui-this:after{border:none}.layui-timeline{padding-left:5px}.layui-timeline-item{position:relative;padding-bottom:20px}.layui-timeline-axis{position:absolute;left:-5px;top:0;z-index:10;width:20px;height:20px;line-height:20px;background-color:#fff;color:#5FB878;border-radius:50%;text-align:center;cursor:pointer}.layui-timeline-axis:hover{color:#FF5722}.layui-timeline-item:before{content:"";position:absolute;left:5px;top:0;z-index:0;width:1px;height:100%}.layui-timeline-item:first-child:before{display:block}.layui-timeline-item:last-child:before{display:none}.layui-timeline-content{padding-left:25px}.layui-timeline-title{position:relative;margin-bottom:10px;line-height:22px}.layui-badge,.layui-badge-dot,.layui-badge-rim{position:relative;display:inline-block;padding:0 6px;font-size:12px;text-align:center;background-color:#FF5722;color:#fff;border-radius:2px}.layui-badge{height:18px;line-height:18px}.layui-badge-dot{width:8px;height:8px;padding:0;border-radius:50%}.layui-badge-rim{height:18px;line-height:18px;border-width:1px;border-style:solid;background-color:#fff;color:#666}.layui-btn .layui-badge,.layui-btn .layui-badge-dot{margin-left:5px}.layui-nav .layui-badge,.layui-nav .layui-badge-dot{position:absolute;top:50%;margin:-5px 6px 0}.layui-nav .layui-badge{margin-top:-10px}.layui-tab-title .layui-badge,.layui-tab-title .layui-badge-dot{left:5px;top:-2px}.layui-carousel{position:relative;left:0;top:0;background-color:#f8f8f8}.layui-carousel>[carousel-item]{position:relative;width:100%;height:100%;overflow:hidden}.layui-carousel>[carousel-item]:before{position:absolute;content:'\e63d';left:50%;top:50%;width:100px;line-height:20px;margin:-10px 0 0 -50px;text-align:center;color:#c2c2c2;font-family:layui-icon!important;font-size:30px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-carousel>[carousel-item]>*{display:none;position:absolute;left:0;top:0;width:100%;height:100%;background-color:#f8f8f8;transition-duration:.3s;-webkit-transition-duration:.3s}.layui-carousel-updown>*{-webkit-transition:.3s ease-in-out up;transition:.3s ease-in-out up}.layui-carousel-arrow{display:none\9;opacity:0;position:absolute;left:10px;top:50%;margin-top:-18px;width:36px;height:36px;line-height:36px;text-align:center;font-size:20px;border:0;border-radius:50%;background-color:rgba(0,0,0,.2);color:#fff;-webkit-transition-duration:.3s;transition-duration:.3s;cursor:pointer}.layui-carousel-arrow[lay-type=add]{left:auto!important;right:10px}.layui-carousel:hover .layui-carousel-arrow[lay-type=add],.layui-carousel[lay-arrow=always] .layui-carousel-arrow[lay-type=add]{right:20px}.layui-carousel[lay-arrow=always] .layui-carousel-arrow{opacity:1;left:20px}.layui-carousel[lay-arrow=none] .layui-carousel-arrow{display:none}.layui-carousel-arrow:hover,.layui-carousel-ind ul:hover{background-color:rgba(0,0,0,.35)}.layui-carousel:hover .layui-carousel-arrow{display:block\9;opacity:1;left:20px}.layui-carousel-ind{position:relative;top:-35px;width:100%;line-height:0!important;text-align:center;font-size:0}.layui-carousel[lay-indicator=outside]{margin-bottom:30px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind{top:10px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind ul{background-color:rgba(0,0,0,.5)}.layui-carousel[lay-indicator=none] .layui-carousel-ind{display:none}.layui-carousel-ind ul{display:inline-block;padding:5px;background-color:rgba(0,0,0,.2);border-radius:10px;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind li{display:inline-block;width:10px;height:10px;margin:0 3px;font-size:14px;background-color:#eee;background-color:rgba(255,255,255,.5);border-radius:50%;cursor:pointer;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind li:hover{background-color:rgba(255,255,255,.7)}.layui-carousel-ind li.layui-this{background-color:#fff}.layui-carousel>[carousel-item]>.layui-carousel-next,.layui-carousel>[carousel-item]>.layui-carousel-prev,.layui-carousel>[carousel-item]>.layui-this{display:block}.layui-carousel>[carousel-item]>.layui-this{left:0}.layui-carousel>[carousel-item]>.layui-carousel-prev{left:-100%}.layui-carousel>[carousel-item]>.layui-carousel-next{left:100%}.layui-carousel>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel>[carousel-item]>.layui-carousel-prev.layui-carousel-right{left:0}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-left{left:-100%}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-right{left:100%}.layui-carousel[lay-anim=updown] .layui-carousel-arrow{left:50%!important;top:20px;margin:0 0 0 -18px}.layui-carousel[lay-anim=updown]>[carousel-item]>*,.layui-carousel[lay-anim=fade]>[carousel-item]>*{left:0!important}.layui-carousel[lay-anim=updown] .layui-carousel-arrow[lay-type=add]{top:auto!important;bottom:20px}.layui-carousel[lay-anim=updown] .layui-carousel-ind{position:absolute;top:50%;right:20px;width:auto;height:auto}.layui-carousel[lay-anim=updown] .layui-carousel-ind ul{padding:3px 5px}.layui-carousel[lay-anim=updown] .layui-carousel-ind li{display:block;margin:6px 0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next{top:100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-left{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-right{top:100%}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev{opacity:0}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{opacity:1}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-right{opacity:0}.layui-fixbar{position:fixed;right:15px;bottom:15px;z-index:999999}.layui-fixbar li{width:50px;height:50px;line-height:50px;margin-bottom:1px;text-align:center;cursor:pointer;font-size:30px;background-color:#9F9F9F;color:#fff;border-radius:2px;opacity:.95}.layui-fixbar li:hover{opacity:.85}.layui-fixbar li:active{opacity:1}.layui-fixbar .layui-fixbar-top{display:none;font-size:40px}body .layui-util-face{border:none;background:0 0}body .layui-util-face .layui-layer-content{padding:0;background-color:#fff;color:#666;box-shadow:none}.layui-util-face .layui-layer-TipsG{display:none}.layui-transfer-active,.layui-transfer-box{display:inline-block;vertical-align:middle}.layui-util-face ul{position:relative;width:372px;padding:10px;border:1px solid #D9D9D9;background-color:#fff;box-shadow:0 0 20px rgba(0,0,0,.2)}.layui-util-face ul li{cursor:pointer;float:left;border:1px solid #e8e8e8;height:22px;width:26px;overflow:hidden;margin:-1px 0 0 -1px;padding:4px 2px;text-align:center}.layui-util-face ul li:hover{position:relative;z-index:2;border:1px solid #eb7350;background:#fff9ec}.layui-code{position:relative;margin:10px 0;padding:15px;line-height:20px;border:1px solid #eee;border-left-width:6px;background-color:#FAFAFA;color:#333;font-family:Courier New;font-size:12px}.layui-transfer-box,.layui-transfer-header,.layui-transfer-search{border-width:0;border-style:solid;border-color:#eee}.layui-transfer-box{position:relative;border-width:1px;width:200px;height:360px;border-radius:2px;background-color:#fff}.layui-transfer-box .layui-form-checkbox{width:100%;margin:0!important}.layui-transfer-header{height:38px;line-height:38px;padding:0 10px;border-bottom-width:1px}.layui-transfer-search{position:relative;padding:10px;border-bottom-width:1px}.layui-transfer-search .layui-input{height:32px;padding-left:30px;font-size:12px}.layui-transfer-search .layui-icon-search{position:absolute;left:20px;top:50%;margin-top:-8px;color:#666}.layui-transfer-active{margin:0 15px}.layui-transfer-active .layui-btn{display:block;margin:0;padding:0 15px;background-color:#5FB878;border-color:#5FB878;color:#fff}.layui-transfer-active .layui-btn-disabled{background-color:#FBFBFB;border-color:#eee;color:#d2d2d2}.layui-transfer-active .layui-btn:first-child{margin-bottom:15px}.layui-transfer-active .layui-btn .layui-icon{margin:0;font-size:14px!important}.layui-transfer-data{padding:5px 0;overflow:auto}.layui-transfer-data li{height:32px;line-height:32px;padding:0 10px}.layui-transfer-data li:hover{background-color:#F6F6F6;transition:.5s all}.layui-transfer-data .layui-none{padding:15px 10px;text-align:center;color:#999}.layui-rate,.layui-rate *{display:inline-block;vertical-align:middle}.layui-rate{padding:10px 5px 10px 0;font-size:0}.layui-rate li i.layui-icon{font-size:20px;color:#FFB800;margin-right:5px;transition:all .3s;-webkit-transition:all .3s}.layui-rate li i:hover{cursor:pointer;transform:scale(1.12);-webkit-transform:scale(1.12)}.layui-rate[readonly] li i:hover{cursor:default;transform:scale(1)}.layui-colorpicker{width:26px;height:26px;border:1px solid #eee;padding:5px;border-radius:2px;line-height:24px;display:inline-block;cursor:pointer;transition:all .3s;-webkit-transition:all .3s}.layui-colorpicker:hover{border-color:#d2d2d2}.layui-colorpicker.layui-colorpicker-lg{width:34px;height:34px;line-height:32px}.layui-colorpicker.layui-colorpicker-sm{width:24px;height:24px;line-height:22px}.layui-colorpicker.layui-colorpicker-xs{width:22px;height:22px;line-height:20px}.layui-colorpicker-trigger-bgcolor{display:block;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);border-radius:2px}.layui-colorpicker-trigger-span{display:block;height:100%;box-sizing:border-box;border:1px solid rgba(0,0,0,.15);border-radius:2px;text-align:center}.layui-colorpicker-trigger-i{display:inline-block;color:#FFF;font-size:12px}.layui-colorpicker-trigger-i.layui-icon-close{color:#999}.layui-colorpicker-main{position:absolute;left:-999999px;top:-999999px;z-index:66666666;width:280px;margin:5px 0;padding:7px;background:#FFF;border:1px solid #d2d2d2;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12)}.layui-colorpicker-main-wrapper{height:180px;position:relative}.layui-colorpicker-basis{width:260px;height:100%;position:relative}.layui-colorpicker-basis-white{width:100%;height:100%;position:absolute;top:0;left:0;background:linear-gradient(90deg,#FFF,hsla(0,0%,100%,0))}.layui-colorpicker-basis-black{width:100%;height:100%;position:absolute;top:0;left:0;background:linear-gradient(0deg,#000,transparent)}.layui-colorpicker-basis-cursor{width:10px;height:10px;border:1px solid #FFF;border-radius:50%;position:absolute;top:-3px;right:-3px;cursor:pointer}.layui-colorpicker-side{position:absolute;top:0;right:0;width:12px;height:100%;background:linear-gradient(red,#FF0,#0F0,#0FF,#00F,#F0F,red)}.layui-colorpicker-side-slider{width:100%;height:5px;box-shadow:0 0 1px #888;background:#FFF;border-radius:1px;border:1px solid #f0f0f0;cursor:pointer;position:absolute;left:0}.layui-colorpicker-main-alpha{display:none;height:12px;margin-top:7px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.layui-colorpicker-alpha-bgcolor{height:100%;position:relative}.layui-colorpicker-alpha-slider{width:5px;height:100%;box-shadow:0 0 1px #888;background:#FFF;border-radius:1px;border:1px solid #f0f0f0;cursor:pointer;position:absolute;top:0}.layui-colorpicker-main-pre{padding-top:7px;font-size:0}.layui-colorpicker-pre{width:20px;height:20px;border-radius:2px;display:inline-block;margin-left:6px;margin-bottom:7px;cursor:pointer}.layui-colorpicker-pre:nth-child(11n+1){margin-left:0}.layui-colorpicker-pre-isalpha{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.layui-colorpicker-pre.layui-this{box-shadow:0 0 3px 2px rgba(0,0,0,.15)}.layui-colorpicker-pre>div{height:100%;border-radius:2px}.layui-colorpicker-main-input{text-align:right;padding-top:7px}.layui-colorpicker-main-input .layui-btn-container .layui-btn{margin:0 0 0 10px}.layui-colorpicker-main-input div.layui-inline{float:left;margin-right:10px;font-size:14px}.layui-colorpicker-main-input input.layui-input{width:150px;height:30px;color:#666}.layui-slider{height:4px;background:#eee;border-radius:3px;position:relative;cursor:pointer}.layui-slider-bar{border-radius:3px;position:absolute;height:100%}.layui-slider-step{position:absolute;top:0;width:4px;height:4px;border-radius:50%;background:#FFF;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.layui-slider-wrap{width:36px;height:36px;position:absolute;top:-16px;-webkit-transform:translateX(-50%);transform:translateX(-50%);z-index:10;text-align:center}.layui-slider-wrap-btn{width:12px;height:12px;border-radius:50%;background:#FFF;display:inline-block;vertical-align:middle;cursor:pointer;transition:.3s}.layui-slider-wrap:after{content:"";height:100%;display:inline-block;vertical-align:middle}.layui-slider-wrap-btn.layui-slider-hover,.layui-slider-wrap-btn:hover{transform:scale(1.2)}.layui-slider-wrap-btn.layui-disabled:hover{transform:scale(1)!important}.layui-slider-tips{position:absolute;top:-42px;z-index:66666666;white-space:nowrap;display:none;-webkit-transform:translateX(-50%);transform:translateX(-50%);color:#FFF;background:#000;border-radius:3px;height:25px;line-height:25px;padding:0 10px}.layui-slider-tips:after{content:"";position:absolute;bottom:-12px;left:50%;margin-left:-6px;width:0;height:0;border-width:6px;border-style:solid;border-color:#000 transparent transparent}.layui-slider-input{width:70px;height:32px;border:1px solid #eee;border-radius:3px;font-size:16px;line-height:32px;position:absolute;right:0;top:-14px}.layui-slider-input-btn{position:absolute;top:0;right:0;width:20px;height:100%;border-left:1px solid #eee}.layui-slider-input-btn i{cursor:pointer;position:absolute;right:0;bottom:0;width:20px;height:50%;font-size:12px;line-height:16px;text-align:center;color:#999}.layui-slider-input-btn i:first-child{top:0;border-bottom:1px solid #eee}.layui-slider-input-txt{height:100%;font-size:14px}.layui-slider-input-txt input{height:100%;border:none}.layui-slider-input-btn i:hover{color:#009688}.layui-slider-vertical{width:4px;margin-left:33px}.layui-slider-vertical .layui-slider-bar{width:4px}.layui-slider-vertical .layui-slider-step{top:auto;left:0;-webkit-transform:translateY(50%);transform:translateY(50%)}.layui-slider-vertical .layui-slider-wrap{top:auto;left:-16px;-webkit-transform:translateY(50%);transform:translateY(50%)}.layui-slider-vertical .layui-slider-tips{top:auto;left:2px}@media \0screen{.layui-slider-wrap-btn{margin-left:-20px}.layui-slider-vertical .layui-slider-wrap-btn{margin-left:0;margin-bottom:-20px}.layui-slider-vertical .layui-slider-tips{margin-left:-8px}.layui-slider>span{margin-left:8px}}.layui-tree{line-height:22px}.layui-tree .layui-form-checkbox{margin:0!important}.layui-tree-set{width:100%;position:relative}.layui-tree-pack{display:none;padding-left:20px;position:relative}.layui-tree-iconClick,.layui-tree-main{display:inline-block;vertical-align:middle}.layui-tree-line .layui-tree-pack{padding-left:27px}.layui-tree-line .layui-tree-set .layui-tree-set:after{content:"";position:absolute;top:14px;left:-9px;width:17px;height:0;border-top:1px dotted #c0c4cc}.layui-tree-entry{position:relative;padding:3px 0;height:20px;white-space:nowrap}.layui-tree-entry:hover{background-color:#eee}.layui-tree-line .layui-tree-entry:hover{background-color:rgba(0,0,0,0)}.layui-tree-line .layui-tree-entry:hover .layui-tree-txt{color:#999;text-decoration:underline;transition:.3s}.layui-tree-main{cursor:pointer;padding-right:10px}.layui-tree-line .layui-tree-set:before{content:"";position:absolute;top:0;left:-9px;width:0;height:100%;border-left:1px dotted #c0c4cc}.layui-tree-line .layui-tree-set.layui-tree-setLineShort:before{height:13px}.layui-tree-line .layui-tree-set.layui-tree-setHide:before{height:0}.layui-tree-iconClick{position:relative;height:20px;line-height:20px;margin:0 10px;color:#c0c4cc}.layui-tree-icon{height:12px;line-height:12px;width:12px;text-align:center;border:1px solid #c0c4cc}.layui-tree-iconClick .layui-icon{font-size:18px}.layui-tree-icon .layui-icon{font-size:12px;color:#666}.layui-tree-iconArrow{padding:0 5px}.layui-tree-iconArrow:after{content:"";position:absolute;left:4px;top:3px;z-index:100;width:0;height:0;border-width:5px;border-style:solid;border-color:transparent transparent transparent #c0c4cc;transition:.5s}.layui-tree-btnGroup,.layui-tree-editInput{position:relative;vertical-align:middle;display:inline-block}.layui-tree-spread>.layui-tree-entry>.layui-tree-iconClick>.layui-tree-iconArrow:after{transform:rotate(90deg) translate(3px,4px)}.layui-tree-txt{display:inline-block;vertical-align:middle;color:#555}.layui-tree-search{margin-bottom:15px;color:#666}.layui-tree-btnGroup .layui-icon{display:inline-block;vertical-align:middle;padding:0 2px;cursor:pointer}.layui-tree-btnGroup .layui-icon:hover{color:#999;transition:.3s}.layui-tree-entry:hover .layui-tree-btnGroup{visibility:visible}.layui-tree-editInput{height:20px;line-height:20px;padding:0 3px;border:none;background-color:rgba(0,0,0,.05)}.layui-tree-emptyText{text-align:center;color:#999}.layui-anim{-webkit-animation-duration:.3s;-webkit-animation-fill-mode:both;animation-duration:.3s;animation-fill-mode:both}.layui-anim.layui-icon{display:inline-block}.layui-anim-loop{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.layui-trans,.layui-trans a{transition:all .2s;-webkit-transition:all .2s}@-webkit-keyframes layui-rotate{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(360deg)}}@keyframes layui-rotate{from{transform:rotate(0)}to{transform:rotate(360deg)}}.layui-anim-rotate{-webkit-animation-name:layui-rotate;animation-name:layui-rotate;-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-timing-function:linear;animation-timing-function:linear}@-webkit-keyframes layui-up{from{-webkit-transform:translate3d(0,100%,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-up{from{transform:translate3d(0,100%,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-up{-webkit-animation-name:layui-up;animation-name:layui-up}@-webkit-keyframes layui-upbit{from{-webkit-transform:translate3d(0,15px,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-upbit{from{transform:translate3d(0,15px,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-upbit{-webkit-animation-name:layui-upbit;animation-name:layui-upbit}@keyframes layui-down{0%{opacity:.3;transform:translate3d(0,-100%,0)}100%{opacity:1;transform:translate3d(0,0,0)}}.layui-anim-down{animation-name:layui-down}@keyframes layui-downbit{0%{opacity:.3;transform:translate3d(0,-5px,0)}100%{opacity:1;transform:translate3d(0,0,0)}}.layui-anim-downbit{animation-name:layui-downbit}@-webkit-keyframes layui-scale{0%{opacity:.3;-webkit-transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale{0%{opacity:.3;-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-ms-transform:scale(1);transform:scale(1)}}.layui-anim-scale{-webkit-animation-name:layui-scale;animation-name:layui-scale}@-webkit-keyframes layui-scale-spring{0%{opacity:.5;-webkit-transform:scale(.5)}80%{opacity:.8;-webkit-transform:scale(1.1)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale-spring{0%{opacity:.5;transform:scale(.5)}80%{opacity:.8;transform:scale(1.1)}100%{opacity:1;transform:scale(1)}}.layui-anim-scaleSpring{-webkit-animation-name:layui-scale-spring;animation-name:layui-scale-spring}@keyframes layui-scalesmall{0%{opacity:.3;transform:scale(1.5)}100%{opacity:1;transform:scale(1)}}.layui-anim-scalesmall{animation-name:layui-scalesmall}@keyframes layui-scalesmall-spring{0%{opacity:.3;transform:scale(1.5)}80%{opacity:.8;transform:scale(.9)}100%{opacity:1;transform:scale(1)}}.layui-anim-scalesmall-spring{animation-name:layui-scalesmall-spring}@-webkit-keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}@keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}.layui-anim-fadein{-webkit-animation-name:layui-fadein;animation-name:layui-fadein}@-webkit-keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}@keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}.layui-anim-fadeout{-webkit-animation-name:layui-fadeout;animation-name:layui-fadeout} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/code.css b/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/code.css new file mode 100644 index 00000000..0fee0c50 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/code.css @@ -0,0 +1 @@ +html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-h3,.layui-code-view{position:relative;font-size:12px}.layui-code-view{display:block;margin:10px 0;padding:0;border:1px solid #eee;border-left-width:6px;background-color:#FAFAFA;color:#333;font-family:Courier New}.layui-code-h3{padding:0 10px;height:40px;line-height:40px;border-bottom:1px solid #eee}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 10px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view .layui-code-ol li:first-child{padding-top:10px}.layui-code-view .layui-code-ol li:last-child{padding-bottom:10px}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0C0C0C;border-left-color:#3F3F3F;background-color:#0C0C0C;color:#C2BE9E}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3F3F3F;border-left:none}.layui-code-demo .layui-code{visibility:visible!important;margin:-15px;border-top:none;border-right:none;border-bottom:none}.layui-code-demo .layui-tab-content{padding:15px;border-top:none} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/laydate/default/laydate.css b/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/laydate/default/laydate.css new file mode 100644 index 00000000..c08928b5 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/laydate/default/laydate.css @@ -0,0 +1 @@ +.laydate-set-ym,.layui-laydate,.layui-laydate *,.layui-laydate-list{box-sizing:border-box}html #layuicss-laydate{display:none;position:absolute;width:1989px}.layui-laydate *{margin:0;padding:0}.layui-laydate{position:absolute;z-index:66666666;margin:5px 0;border-radius:2px;font-size:14px;-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;animation-name:laydate-downbit}.layui-laydate-main{width:272px}.layui-laydate-content td,.layui-laydate-header *,.layui-laydate-list li{transition-duration:.3s;-webkit-transition-duration:.3s}@keyframes laydate-downbit{0%{opacity:.3;transform:translate3d(0,-5px,0)}100%{opacity:1;transform:translate3d(0,0,0)}}.layui-laydate-static{position:relative;z-index:0;display:inline-block;margin:0;-webkit-animation:none;animation:none}.laydate-ym-show .laydate-next-m,.laydate-ym-show .laydate-prev-m{display:none!important}.laydate-ym-show .laydate-next-y,.laydate-ym-show .laydate-prev-y{display:inline-block!important}.laydate-time-show .laydate-set-ym span[lay-type=month],.laydate-time-show .laydate-set-ym span[lay-type=year],.laydate-time-show .layui-laydate-header .layui-icon,.laydate-ym-show .laydate-set-ym span[lay-type=month]{display:none!important}.layui-laydate-header{position:relative;line-height:30px;padding:10px 70px 5px}.layui-laydate-header *{display:inline-block;vertical-align:bottom}.layui-laydate-header i{position:absolute;top:10px;padding:0 5px;color:#999;font-size:18px;cursor:pointer}.layui-laydate-header i.laydate-prev-y{left:15px}.layui-laydate-header i.laydate-prev-m{left:45px}.layui-laydate-header i.laydate-next-y{right:15px}.layui-laydate-header i.laydate-next-m{right:45px}.laydate-set-ym{width:100%;text-align:center;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.laydate-set-ym span{padding:0 10px;cursor:pointer}.laydate-time-text{cursor:default!important}.layui-laydate-content{position:relative;padding:10px;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-laydate-content table{border-collapse:collapse;border-spacing:0}.layui-laydate-content td,.layui-laydate-content th{width:36px;height:30px;padding:5px;text-align:center}.layui-laydate-content td{position:relative;cursor:pointer}.laydate-day-mark{position:absolute;left:0;top:0;width:100%;line-height:30px;font-size:12px;overflow:hidden}.laydate-day-mark::after{position:absolute;content:'';right:2px;top:2px;width:5px;height:5px;border-radius:50%}.layui-laydate-footer{position:relative;height:46px;line-height:26px;padding:10px}.layui-laydate-footer span{display:inline-block;vertical-align:top;height:26px;line-height:24px;padding:0 10px;border:1px solid #C9C9C9;border-radius:2px;background-color:#fff;font-size:12px;cursor:pointer;white-space:nowrap;transition:all .3s}.layui-laydate-list>li,.layui-laydate-range .layui-laydate-main{display:inline-block;vertical-align:middle}.layui-laydate-footer span:hover{color:#5FB878}.layui-laydate-footer span.layui-laydate-preview{cursor:default;border-color:transparent!important}.layui-laydate-footer span.layui-laydate-preview:hover{color:#666}.layui-laydate-footer span:first-child.layui-laydate-preview{padding-left:0}.laydate-footer-btns{position:absolute;right:10px;top:10px}.laydate-footer-btns span{margin:0 0 0 -1px}.layui-laydate-list{position:absolute;left:0;top:0;width:100%;height:100%;padding:10px;background-color:#fff}.layui-laydate-list>li{position:relative;width:33.3%;height:36px;line-height:36px;margin:3px 0;text-align:center;cursor:pointer}.laydate-month-list>li{width:25%;margin:17px 0}.laydate-time-list>li{height:100%;margin:0;line-height:normal;cursor:default}.laydate-time-list p{position:relative;top:-4px;line-height:29px}.laydate-time-list ol{height:181px;overflow:hidden}.laydate-time-list>li:hover ol{overflow-y:auto}.laydate-time-list ol li{width:130%;padding-left:33px;height:30px;line-height:30px;text-align:left;cursor:pointer}.layui-laydate-hint{position:absolute;top:115px;left:50%;width:250px;margin-left:-125px;line-height:20px;padding:15px;text-align:center;font-size:12px}.layui-laydate-range{width:546px}.layui-laydate-range .laydate-main-list-1 .layui-laydate-content,.layui-laydate-range .laydate-main-list-1 .layui-laydate-header{border-left:1px solid #e2e2e2}.layui-laydate,.layui-laydate-hint{border:1px solid #d2d2d2;box-shadow:0 2px 4px rgba(0,0,0,.12);background-color:#fff;color:#666}.layui-laydate-header{border-bottom:1px solid #e2e2e2}.layui-laydate-header i:hover,.layui-laydate-header span:hover{color:#5FB878}.layui-laydate-content{border-top:none 0;border-bottom:none 0}.layui-laydate-content th{font-weight:400;color:#333}.layui-laydate-content td{color:#666}.layui-laydate-content td.laydate-selected{background-color:#B5FFF8}.laydate-selected:hover{background-color:#00F7DE!important}.layui-laydate-content td:hover,.layui-laydate-list li:hover{background-color:#eee;color:#333}.laydate-time-list li ol{margin:0;padding:0;border:1px solid #e2e2e2;border-left-width:0}.laydate-time-list li:first-child ol{border-left-width:1px}.laydate-time-list>li:hover{background:0 0}.layui-laydate-content .laydate-day-next,.layui-laydate-content .laydate-day-prev{color:#d2d2d2}.laydate-selected.laydate-day-next,.laydate-selected.laydate-day-prev{background-color:#f8f8f8!important}.layui-laydate-footer{border-top:1px solid #e2e2e2}.layui-laydate-hint{color:#FF5722}.laydate-day-mark::after{background-color:#5FB878}.layui-laydate-content td.layui-this .laydate-day-mark::after{display:none}.layui-laydate-footer span[lay-type=date]{color:#5FB878}.layui-laydate .layui-this{background-color:#009688!important;color:#fff!important}.layui-laydate .laydate-disabled,.layui-laydate .laydate-disabled:hover{background:0 0!important;color:#d2d2d2!important;cursor:not-allowed!important;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.laydate-theme-molv{border:none}.laydate-theme-molv.layui-laydate-range{width:548px}.laydate-theme-molv .layui-laydate-main{width:274px}.laydate-theme-molv .layui-laydate-header{border:none;background-color:#009688}.laydate-theme-molv .layui-laydate-header i,.laydate-theme-molv .layui-laydate-header span{color:#f6f6f6}.laydate-theme-molv .layui-laydate-header i:hover,.laydate-theme-molv .layui-laydate-header span:hover{color:#fff}.laydate-theme-molv .layui-laydate-content{border:1px solid #e2e2e2;border-top:none;border-bottom:none}.laydate-theme-molv .laydate-main-list-1 .layui-laydate-content{border-left:none}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li,.laydate-theme-grid .layui-laydate-content td,.laydate-theme-grid .layui-laydate-content thead,.laydate-theme-molv .layui-laydate-footer{border:1px solid #e2e2e2}.laydate-theme-grid .laydate-selected,.laydate-theme-grid .laydate-selected:hover{background-color:#f2f2f2!important;color:#009688!important}.laydate-theme-grid .laydate-selected.laydate-day-next,.laydate-theme-grid .laydate-selected.laydate-day-prev{color:#d2d2d2!important}.laydate-theme-grid .laydate-month-list,.laydate-theme-grid .laydate-year-list{margin:1px 0 0 1px}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li{margin:0 -1px -1px 0}.laydate-theme-grid .laydate-year-list>li{height:43px;line-height:43px}.laydate-theme-grid .laydate-month-list>li{height:71px;line-height:71px} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/icon-ext.png b/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/icon-ext.png new file mode 100644 index 0000000000000000000000000000000000000000..bbbb669bb311514baa5db3a6a00b4644d0e280f1 GIT binary patch literal 5911 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 bWW^%>x7XlHV^#Q1uOX^B?ki3(VEg|7!QHuF literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/loading-1.gif b/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/loading-1.gif new file mode 100644 index 0000000000000000000000000000000000000000..db3a483e4b74971fbfb1cc0fb6499852cedfe650 GIT binary patch literal 701 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 NqtXTTr(IH0bTL$Q#&Rt$( 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 WEo6sg2$g9lKpdZ$$_>);_x}MD5#CJz literal 0 HcmV?d00001 diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.svg b/iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.svg new file mode 100644 index 00000000..999ca1fe --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.svg @@ -0,0 +1,554 @@ + + + + + +Created by iconfont + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.ttf b/iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..06e30f9e2a856cbfefff25111ceb4b9c034f35fd GIT binary patch literal 46508 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
                    _X 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"interactive"===n[o].readyState){t=n[o].src;break}return t||n[r].src}();return n.dir=o.dir||t.substring(0,t.lastIndexOf("/")+1)}(),i=function(e,n){n=n||"log",t.console&&console[n]&&console[n]("layui error hint: "+e)},u="undefined"!=typeof opera&&"[object Opera]"===opera.toString(),l=n.builtin={lay:"lay",layer:"layer",laydate:"laydate",laypage:"laypage",laytpl:"laytpl",layedit:"layedit",form:"form",upload:"upload",dropdown:"dropdown",transfer:"transfer",tree:"tree",table:"table",element:"element",rate:"rate",colorpicker:"colorpicker",slider:"slider",carousel:"carousel",flow:"flow",util:"util",code:"code",jquery:"jquery",all:"all","layui.all":"layui.all"};r.prototype.cache=n,r.prototype.define=function(t,e){var r=this,o="function"==typeof t,a=function(){var t=function(t,e){layui[t]=e,n.status[t]=!0};return"function"==typeof e&&e(function(r,o){t(r,o),n.callback[r]=function(){e(t)}}),this};return o&&(e=t,t=[]),r.use(t,a,null,"define"),r},r.prototype.use=function(r,o,c,s){function p(t,e){var r="PLaySTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/;("load"===t.type||r.test((t.currentTarget||t.srcElement).readyState))&&(n.modules[h]=e,v.removeChild(b),function o(){return++m>1e3*n.timeout/4?i(h+" is not a valid module","error"):void(n.status[h]?f():setTimeout(o,4))}())}function f(){c.push(layui[h]),r.length>1?y.use(r.slice(1),o,c,s):"function"==typeof o&&function(){return layui.jquery&&"function"==typeof layui.jquery&&"define"!==s?layui.jquery(function(){o.apply(layui,c)}):void o.apply(layui,c)}()}var y=this,d=n.dir=n.dir?n.dir:a,v=e.getElementsByTagName("head")[0];r=function(){return"string"==typeof r?[r]:"function"==typeof r?(o=r,["all"]):r}(),t.jQuery&&jQuery.fn.on&&(y.each(r,function(t,e){"jquery"===e&&r.splice(t,1)}),layui.jquery=layui.$=jQuery);var h=r[0],m=0;if(c=c||[],n.host=n.host||(d.match(/\/\/([\s\S]+?)\//)||["//"+location.host+"/"])[0],0===r.length||layui["layui.all"]&&l[h])return f(),y;var g=(l[h]?d+"modules/":/^\{\/\}/.test(y.modules[h])?"":n.base||"")+(y.modules[h]||h)+".js";if(g=g.replace(/^\{\/\}/,""),!n.modules[h]&&layui[h]&&(n.modules[h]=g),n.modules[h])!function S(){return++m>1e3*n.timeout/4?i(h+" is not a valid module","error"):void("string"==typeof n.modules[h]&&n.status[h]?f():setTimeout(S,4))}();else{var b=e.createElement("script");b.async=!0,b.charset="utf-8",b.src=g+function(){var t=n.version===!0?n.v||(new Date).getTime():n.version||"";return t?"?v="+t:""}(),v.appendChild(b),!b.attachEvent||b.attachEvent.toString&&b.attachEvent.toString().indexOf("[native code")<0||u?b.addEventListener("load",function(t){p(t,g)},!1):b.attachEvent("onreadystatechange",function(t){p(t,g)}),n.modules[h]=g}return y},r.prototype.getStyle=function(e,n){var r=e.currentStyle?e.currentStyle:t.getComputedStyle(e,null);return r[r.getPropertyValue?"getPropertyValue":"getAttribute"](n)},r.prototype.link=function(t,r,o){var a=this,u=e.getElementsByTagName("head")[0],l=e.createElement("link");"string"==typeof r&&(o=r);var c=(o||t).replace(/\.|\//g,""),s=l.id="layuicss-"+c,p="creating",f=0;return l.rel="stylesheet",l.href=t+(n.debug?"?v="+(new Date).getTime():""),l.media="all",e.getElementById(s)||u.appendChild(l),"function"!=typeof r?a:(function y(o){var u=100,l=e.getElementById(s);return++f>1e3*n.timeout/u?i(t+" timeout"):void(1989===parseInt(a.getStyle(l,"width"))?(o===p&&l.removeAttribute("lay-status"),l.getAttribute("lay-status")===p?setTimeout(y,u):r()):(l.setAttribute("lay-status",p),setTimeout(function(){y(p)},u)))}(),a)},r.prototype.addcss=function(t,e,r){return layui.link(n.dir+"css/"+t,e,r)},n.callback={},r.prototype.factory=function(t){if(layui[t])return"function"==typeof n.callback[t]?n.callback[t]:null},r.prototype.img=function(t,e,n){var r=new Image;return r.src=t,r.complete?e(r):(r.onload=function(){r.onload=null,"function"==typeof e&&e(r)},void(r.onerror=function(t){r.onerror=null,"function"==typeof n&&n(t)}))},r.prototype.config=function(t){t=t||{};for(var e in t)n[e]=t[e];return this},r.prototype.modules=function(){var t={};for(var e in l)t[e]=l[e];return t}(),r.prototype.extend=function(t){var e=this;t=t||{};for(var n in t)e[n]||e.modules[n]?i(n+" Module already exists","error"):e.modules[n]=t[n];return e},r.prototype.router=function(t){var e=this,t=t||location.hash,n={path:[],search:{},hash:(t.match(/[^#](#.*$)/)||[])[1]||""};return/^#\//.test(t)?(t=t.replace(/^#\//,""),n.href="/"+t,t=t.replace(/([^#])(#.*$)/,"$1").split("/")||[],e.each(t,function(t,e){/^\w+=/.test(e)?function(){e=e.split("="),n.search[e[0]]=e[1]}():n.path.push(e)}),n):n},r.prototype.url=function(t){var e=this,n={pathname:function(){var e=t?function(){var e=(t.match(/\.[^.]+?\/.+/)||[])[0]||"";return e.replace(/^[^\/]+/,"").replace(/\?.+/,"")}():location.pathname;return e.replace(/^\//,"").split("/")}(),search:function(){var n={},r=(t?function(){var e=(t.match(/\?.+/)||[])[0]||"";return e.replace(/\#.+/,"")}():location.search).replace(/^\?+/,"").split("&");return e.each(r,function(t,e){var r=e.indexOf("="),o=function(){return r<0?e.substr(0,e.length):0!==r&&e.substr(0,r)}();o&&(n[o]=r>0?e.substr(r+1):null)}),n}(),hash:e.router(function(){return t?(t.match(/#.+/)||[])[0]||"/":location.hash}())};return n},r.prototype.data=function(e,n,r){if(e=e||"layui",r=r||localStorage,t.JSON&&t.JSON.parse){if(null===n)return delete r[e];n="object"==typeof n?n:{key:n};try{var o=JSON.parse(r[e])}catch(a){var o={}}return"value"in n&&(o[n.key]=n.value),n.remove&&delete o[n.key],r[e]=JSON.stringify(o),n.key?o[n.key]:o}},r.prototype.sessionData=function(t,e){return this.data(t,e,sessionStorage)},r.prototype.device=function(e){var n=navigator.userAgent.toLowerCase(),r=function(t){var e=new RegExp(t+"/([^\\s\\_\\-]+)");return t=(n.match(e)||[])[1],t||!1},o={os:function(){return/windows/.test(n)?"windows":/linux/.test(n)?"linux":/iphone|ipod|ipad|ios/.test(n)?"ios":/mac/.test(n)?"mac":void 0}(),ie:function(){return!!(t.ActiveXObject||"ActiveXObject"in t)&&((n.match(/msie\s(\d+)/)||[])[1]||"11")}(),weixin:r("micromessenger")};return e&&!o[e]&&(o[e]=r(e)),o.android=/android/.test(n),o.ios="ios"===o.os,o.mobile=!(!o.android&&!o.ios),o},r.prototype.hint=function(){return{error:i}},r.prototype._typeof=function(t){return null===t?String(t):"object"==typeof t||"function"==typeof t?function(){var e=Object.prototype.toString.call(t).match(/\s(.+)\]$/)||[],n="Function|Array|Date|RegExp|Object|Error|Symbol";return e=e[1]||"Object",new RegExp("\\b("+n+")\\b").test(e)?e.toLowerCase():"object"}():typeof t},r.prototype._isArray=function(e){var n,r=this,o=r._typeof(e);return!(!e||"object"!=typeof e||e===t)&&(n="length"in e&&e.length,"array"===o||0===n||"number"==typeof n&&n>0&&n-1 in e)},r.prototype.each=function(t,e){var n,r=this,o=function(t,n){return e.call(n[t],t,n[t])};if("function"!=typeof e)return r;if(t=t||[],r._isArray(t))for(n=0;no?1:r(t.innerHeight||n.documentElement.clientHeight)},r.style=function(t){t=t||{};var e=r.elem("style"),n=t.text||"",i=t.target||r("body")[0];if(n){"styleSheet"in e?(e.setAttribute("type","text/css"),e.styleSheet.cssText=n):e.innerHTML=n,r.style.index=r.style.index||0,r.style.index++;var o=e.id="LAY-STYLE-"+(t.id||"DF-"+r.style.index),c=r(i).find("#"+o);c[0]&&c.remove(),r(i).append(e)}},r.position=function(e,i,o){if(i){o=o||{},e!==n&&e!==r("body")[0]||(o.clickType="right");var c="right"===o.clickType?function(){var e=o.e||t.event||{};return{left:e.clientX,top:e.clientY,right:e.clientX,bottom:e.clientY}}():e.getBoundingClientRect(),u=i.offsetWidth,a=i.offsetHeight,s=function(t){return t=t?"scrollLeft":"scrollTop",n.body[t]|n.documentElement[t]},l=function(t){return n.documentElement[t?"clientWidth":"clientHeight"]},f=5,h=c.left,p=c.bottom;"center"===o.align?h-=(u-e.offsetWidth)/2:"right"===o.align&&(h=h-u+e.offsetWidth),h+u+f>l("width")&&(h=l("width")-u-f),hl()&&(c.top>a+f?p=c.top-a-2*f:"right"===o.clickType&&(p=l()-a-2*f,p<0&&(p=0)));var y=o.position;if(y&&(i.style.position=y),i.style.left=h+("fixed"===y?0:s(1))+"px",i.style.top=p+("fixed"===y?0:s())+"px",!r.hasScrollbar()){var d=i.getBoundingClientRect();!o.SYSTEM_RELOAD&&d.bottom+f>l()&&(o.SYSTEM_RELOAD=!0,setTimeout(function(){r.position(e,i,o)},50))}}},r.options=function(t,e){var n=r(t),i=e||"lay-options";try{return new Function("return "+(n.attr(i)||"{}"))()}catch(o){return hint.error("parseerror\uff1a"+o,"error"),{}}},r.isTopElem=function(t){var e=[n,r("body")[0]],i=!1;return r.each(e,function(e,n){if(n===t)return i=!0}),i},i.addStr=function(t,e){return t=t.replace(/\s+/," "),e=e.replace(/\s+/," ").split(" "),r.each(e,function(e,n){new RegExp("\\b"+n+"\\b").test(t)||(t=t+" "+n)}),t.replace(/^\s|\s$/,"")},i.removeStr=function(t,e){return t=t.replace(/\s+/," "),e=e.replace(/\s+/," ").split(" "),r.each(e,function(e,n){var r=new RegExp("\\b"+n+"\\b");r.test(t)&&(t=t.replace(r,""))}),t.replace(/\s+/," ").replace(/^\s|\s$/,"")},i.prototype.find=function(t){var e=this,n=0,i=[],o="object"==typeof t;return this.each(function(r,c){for(var u=o?c.contains(t):c.querySelectorAll(t||null);n0)return n[0].style[t]}():n.each(function(n,o){"object"==typeof t?r.each(t,function(t,e){o.style[t]=i(e)}):o.style[t]=i(e)})},i.prototype.width=function(t){var e=this;return void 0===t?function(){if(e.length>0)return e[0].offsetWidth}():e.each(function(n,r){e.css("width",t)})},i.prototype.height=function(t){var e=this;return void 0===t?function(){if(e.length>0)return e[0].offsetHeight}():e.each(function(n,r){e.css("height",t)})},i.prototype.attr=function(t,e){var n=this;return void 0===e?function(){if(n.length>0)return n[0].getAttribute(t)}():n.each(function(n,r){r.setAttribute(t,e)})},i.prototype.removeAttr=function(t){return this.each(function(e,n){n.removeAttribute(t)})},i.prototype.html=function(t){var e=this;return void 0===t?function(){if(e.length>0)return e[0].innerHTML}():this.each(function(e,n){n.innerHTML=t})},i.prototype.val=function(t){var e=this;return void 0===t?function(){if(e.length>0)return e[0].value}():this.each(function(e,n){n.value=t})},i.prototype.append=function(t){return this.each(function(e,n){"object"==typeof t?n.appendChild(t):n.innerHTML=n.innerHTML+t})},i.prototype.remove=function(t){return this.each(function(e,n){t?n.removeChild(t):n.parentNode.removeChild(n)})},i.prototype.on=function(t,e){return this.each(function(n,r){r.attachEvent?r.attachEvent("on"+t,function(t){t.target=t.srcElement,e.call(r,t)}):r.addEventListener(t,e,!1)})},i.prototype.off=function(t,e){return this.each(function(n,r){r.detachEvent?r.detachEvent("on"+t,e):r.removeEventListener(t,e,!1)})},t.lay=r,t.layui&&layui.define&&layui.define(function(t){t(e,r)})}(window,window.document);layui.define(function(e){"use strict";var r={open:"{{",close:"}}"},c={exp:function(e){return new RegExp(e,"g")},query:function(e,c,t){var o=["#([\\s\\S])+?","([^{#}])*?"][e||0];return n((c||"")+r.open+o+r.close+(t||""))},escape:function(e){return String(e||"").replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,""")},error:function(e,r){var c="Laytpl Error: ";return"object"==typeof console&&console.error(c+e+"\n"+(r||"")),c+e}},n=c.exp,t=function(e){this.tpl=e};t.pt=t.prototype,window.errors=0,t.pt.parse=function(e,t){var o=this,p=e,a=n("^"+r.open+"#",""),l=n(r.close+"$","");e=e.replace(/\s+|\r|\t|\n/g," ").replace(n(r.open+"#"),r.open+"# ").replace(n(r.close+"}"),"} "+r.close).replace(/\\/g,"\\\\").replace(n(r.open+"!(.+?)!"+r.close),function(e){return e=e.replace(n("^"+r.open+"!"),"").replace(n("!"+r.close),"").replace(n(r.open+"|"+r.close),function(e){return e.replace(/(.)/g,"\\$1")})}).replace(/(?="|')/g,"\\").replace(c.query(),function(e){return e=e.replace(a,"").replace(l,""),'";'+e.replace(/\\(.)/g,"$1")+';view+="'}).replace(c.query(1),function(e){var c='"+(';return e.replace(/\s/g,"")===r.open+r.close?"":(e=e.replace(n(r.open+"|"+r.close),""),/^=/.test(e)&&(e=e.replace(/^=/,""),c='"+_escape_('),c+e.replace(/\\(.)/g,"$1")+')+"')}),e='"use strict";var view = "'+e+'";return view;';try{return o.cache=e=new Function("d, _escape_",e),e(t,c.escape)}catch(u){return delete o.cache,c.error(u,p)}},t.pt.render=function(e,r){var n,t=this;return e?(n=t.cache?t.cache(e,c.escape):t.parse(t.tpl,e),r?void r(n):n):c.error("no data")};var o=function(e){return"string"!=typeof e?c.error("Template not found"):new t(e)};o.config=function(e){e=e||{};for(var c in e)r[c]=e[c]},o.v="1.2.0",e("laytpl",o)});layui.define(function(e){"use strict";var a=document,t="getElementById",n="getElementsByTagName",i="laypage",r="layui-disabled",u=function(e){var a=this;a.config=e||{},a.config.index=++s.index,a.render(!0)};u.prototype.type=function(){var e=this.config;if("object"==typeof e.elem)return void 0===e.elem.length?2:3},u.prototype.view=function(){var e=this,a=e.config,t=a.groups="groups"in a?0|a.groups:5;a.layout="object"==typeof a.layout?a.layout:["prev","page","next"],a.count=0|a.count,a.curr=0|a.curr||1,a.limits="object"==typeof a.limits?a.limits:[10,20,30,40,50],a.limit=0|a.limit||10,a.pages=Math.ceil(a.count/a.limit)||1,a.curr>a.pages&&(a.curr=a.pages),t<0?t=1:t>a.pages&&(t=a.pages),a.prev="prev"in a?a.prev:"上一页",a.next="next"in a?a.next:"下一页";var n=a.pages>t?Math.ceil((a.curr+(t>1?1:0))/(t>0?t:1)):1,i={prev:function(){return a.prev?''+a.prev+"":""}(),page:function(){var e=[];if(a.count<1)return"";n>1&&a.first!==!1&&0!==t&&e.push(''+(a.first||1)+"");var i=Math.floor((t-1)/2),r=n>1?a.curr-i:1,u=n>1?function(){var e=a.curr+(t-i-1);return e>a.pages?a.pages:e}():t;for(u-r2&&e.push('');r<=u;r++)r===a.curr?e.push('"+r+""):e.push(''+r+"");return a.pages>t&&a.pages>u&&a.last!==!1&&(u+1…'),0!==t&&e.push(''+(a.last||a.pages)+"")),e.join("")}(),next:function(){return a.next?''+a.next+"":""}(),count:'\u5171 '+a.count+" \u6761",limit:function(){var e=['"}(),refresh:['','',""].join(""),skip:function(){return['到第','','页',""].join("")}()};return['
                    ',function(){var e=[];return layui.each(a.layout,function(a,t){i[t]&&e.push(i[t])}),e.join("")}(),"
                    "].join("")},u.prototype.jump=function(e,a){if(e){var t=this,i=t.config,r=e.children,u=e[n]("button")[0],l=e[n]("input")[0],p=e[n]("select")[0],c=function(){var e=0|l.value.replace(/\s|\D/g,"");e&&(i.curr=e,t.render())};if(a)return c();for(var o=0,y=r.length;oi.pages||(i.curr=e,t.render())});p&&s.on(p,"change",function(){var e=this.value;i.curr*e>i.count&&(i.curr=Math.ceil(i.count/e)),i.limit=e,t.render()}),u&&s.on(u,"click",function(){c()})}},u.prototype.skip=function(e){if(e){var a=this,t=e[n]("input")[0];t&&s.on(t,"keyup",function(t){var n=this.value,i=t.keyCode;/^(37|38|39|40)$/.test(i)||(/\D/.test(n)&&(this.value=n.replace(/\D/,"")),13===i&&a.jump(e,!0))})}},u.prototype.render=function(e){var n=this,i=n.config,r=n.type(),u=n.view();2===r?i.elem&&(i.elem.innerHTML=u):3===r?i.elem.html(u):a[t](i.elem)&&(a[t](i.elem).innerHTML=u),i.jump&&i.jump(i,e);var s=a[t]("layui-laypage-"+i.index);n.jump(s),i.hash&&!e&&(location.hash="!"+i.hash+"="+i.curr),n.skip(s)};var s={render:function(e){var a=new u(e);return a.index},index:layui.laypage?layui.laypage.index+1e4:0,on:function(e,a,t){return e.attachEvent?e.attachEvent("on"+a,function(a){a.target=a.srcElement,t.call(e,a)}):e.addEventListener(a,t,!1),this}};e(i,s)});!function(e,t){"use strict";var a=e.layui&&layui.define,n={getPath:e.lay&&lay.getPath?lay.getPath:"",link:function(t,a,n){l.path&&e.lay&&lay.layui&&lay.layui.link(l.path+t,a,n)}},i=e.LAYUI_GLOBAL||{},l={v:"5.3.1",config:{},index:e.laydate&&e.laydate.v?1e5:0,path:i.laydate_dir||n.getPath,set:function(e){var t=this;return t.config=lay.extend({},t.config,e),t},ready:function(e){var t="laydate",i="",r=(a?"modules/laydate/":"theme/")+"default/laydate.css?v="+l.v+i;return a?layui.addcss(r,e,t):n.link(r,e,t),this}},r=function(){var e=this,t=e.config,a=t.id;return r.that[a]=e,{hint:function(t){e.hint.call(e,t)},config:e.config}},o="laydate",s=".layui-laydate",y="layui-this",d="laydate-disabled",m=[100,2e5],c="layui-laydate-static",u="layui-laydate-list",h="layui-laydate-hint",f="layui-laydate-footer",p=".laydate-btns-confirm",g="laydate-time-text",v="laydate-btns-time",T="layui-laydate-preview",D=function(e){var t=this;t.index=++l.index,t.config=lay.extend({},t.config,l.config,e),e=t.config,e.id="id"in e?e.id:t.index,l.ready(function(){t.init()})},w="yyyy|y|MM|M|dd|d|HH|H|mm|m|ss|s";r.formatArr=function(e){return(e||"").match(new RegExp(w+"|.","g"))||[]},D.isLeapYear=function(e){return e%4===0&&e%100!==0||e%400===0},D.prototype.config={type:"date",range:!1,format:"yyyy-MM-dd",value:null,isInitValue:!0,min:"1900-1-1",max:"2099-12-31",trigger:"click",show:!1,showBottom:!0,isPreview:!0,btns:["clear","now","confirm"],lang:"cn",theme:"default",position:null,calendar:!1,mark:{},zIndex:null,done:null,change:null},D.prototype.lang=function(){var e=this,t=e.config,a={cn:{weeks:["\u65e5","\u4e00","\u4e8c","\u4e09","\u56db","\u4e94","\u516d"],time:["\u65f6","\u5206","\u79d2"],timeTips:"\u9009\u62e9\u65f6\u95f4",startTime:"\u5f00\u59cb\u65f6\u95f4",endTime:"\u7ed3\u675f\u65f6\u95f4",dateTips:"\u8fd4\u56de\u65e5\u671f",month:["\u4e00","\u4e8c","\u4e09","\u56db","\u4e94","\u516d","\u4e03","\u516b","\u4e5d","\u5341","\u5341\u4e00","\u5341\u4e8c"],tools:{confirm:"\u786e\u5b9a",clear:"\u6e05\u7a7a",now:"\u73b0\u5728"},timeout:"\u7ed3\u675f\u65f6\u95f4\u4e0d\u80fd\u65e9\u4e8e\u5f00\u59cb\u65f6\u95f4
                    \u8bf7\u91cd\u65b0\u9009\u62e9",invalidDate:"\u4e0d\u5728\u6709\u6548\u65e5\u671f\u6216\u65f6\u95f4\u8303\u56f4\u5185",formatError:["\u65e5\u671f\u683c\u5f0f\u4e0d\u5408\u6cd5
                    \u5fc5\u987b\u9075\u5faa\u4e0b\u8ff0\u683c\u5f0f\uff1a
                    ","
                    \u5df2\u4e3a\u4f60\u91cd\u7f6e"],preview:"\u5f53\u524d\u9009\u4e2d\u7684\u7ed3\u679c"},en:{weeks:["Su","Mo","Tu","We","Th","Fr","Sa"],time:["Hours","Minutes","Seconds"],timeTips:"Select Time",startTime:"Start Time",endTime:"End Time",dateTips:"Select Date",month:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],tools:{confirm:"Confirm",clear:"Clear",now:"Now"},timeout:"End time cannot be less than start Time
                    Please re-select",invalidDate:"Invalid date",formatError:["The date format error
                    Must be followed\uff1a
                    ","
                    It has been reset"],preview:"The selected result"}};return a[t.lang]||a.cn},D.prototype.init=function(){var t=this,a=t.config,n="static"===a.position,i={year:"yyyy",month:"yyyy-MM",date:"yyyy-MM-dd",time:"HH:mm:ss",datetime:"yyyy-MM-dd HH:mm:ss"};a.elem=lay(a.elem),a.eventElem=lay(a.eventElem),a.elem[0]&&(t.rangeStr=a.range?"string"==typeof a.range?a.range:"-":"","array"===layui._typeof(a.range)&&(t.rangeElem=[lay(a.range[0]),lay(a.range[1])]),i[a.type]||(e.console&&console.error&&console.error("laydate type error:'"+a.type+"' is not supported"),a.type="date"),a.format===i.date&&(a.format=i[a.type]||i.date),t.format=r.formatArr(a.format),t.EXP_IF="",t.EXP_SPLIT="",lay.each(t.format,function(e,a){var n=new RegExp(w).test(a)?"\\d{"+function(){return new RegExp(w).test(t.format[0===e?e+1:e-1]||"")?/^yyyy|y$/.test(a)?4:a.length:/^yyyy$/.test(a)?"1,4":/^y$/.test(a)?"1,308":"1,2"}()+"}":"\\"+a;t.EXP_IF=t.EXP_IF+n,t.EXP_SPLIT=t.EXP_SPLIT+"("+n+")"}),t.EXP_IF_ONE=new RegExp("^"+t.EXP_IF+"$"),t.EXP_IF=new RegExp("^"+(a.range?t.EXP_IF+"\\s\\"+t.rangeStr+"\\s"+t.EXP_IF:t.EXP_IF)+"$"),t.EXP_SPLIT=new RegExp("^"+t.EXP_SPLIT+"$",""),t.isInput(a.elem[0])||"focus"===a.trigger&&(a.trigger="click"),a.elem.attr("lay-key")||(a.elem.attr("lay-key",t.index),a.eventElem.attr("lay-key",t.index)),a.mark=lay.extend({},a.calendar&&"cn"===a.lang?{"0-1-1":"\u5143\u65e6","0-2-14":"\u60c5\u4eba","0-3-8":"\u5987\u5973","0-3-12":"\u690d\u6811","0-4-1":"\u611a\u4eba","0-5-1":"\u52b3\u52a8","0-5-4":"\u9752\u5e74","0-6-1":"\u513f\u7ae5","0-9-10":"\u6559\u5e08","0-9-18":"\u56fd\u803b","0-10-1":"\u56fd\u5e86","0-12-25":"\u5723\u8bde"}:{},a.mark),lay.each(["min","max"],function(e,t){var n=[],i=[];if("number"==typeof a[t]){var l=a[t],r=(new Date).getTime(),o=864e5,s=new Date(l?l0)return!0;var t=lay.elem("div",{"class":"layui-laydate-header"}),i=[function(){var e=lay.elem("i",{"class":"layui-icon laydate-icon laydate-prev-y"});return e.innerHTML="",e}(),function(){var e=lay.elem("i",{"class":"layui-icon laydate-icon laydate-prev-m"});return e.innerHTML="",e}(),function(){var e=lay.elem("div",{"class":"laydate-set-ym"}),t=lay.elem("span"),a=lay.elem("span");return e.appendChild(t),e.appendChild(a),e}(),function(){var e=lay.elem("i",{"class":"layui-icon laydate-icon laydate-next-m"});return e.innerHTML="",e}(),function(){var e=lay.elem("i",{"class":"layui-icon laydate-icon laydate-next-y"});return e.innerHTML="",e}()],l=lay.elem("div",{"class":"layui-laydate-content"}),r=lay.elem("table"),m=lay.elem("thead"),c=lay.elem("tr");lay.each(i,function(e,a){t.appendChild(a)}),m.appendChild(c),lay.each(new Array(6),function(e){var t=r.insertRow(0);lay.each(new Array(7),function(a){if(0===e){var i=lay.elem("th");i.innerHTML=n.weeks[a],c.appendChild(i)}t.insertCell(a)})}),r.insertBefore(m,r.children[0]),l.appendChild(r),o[e]=lay.elem("div",{"class":"layui-laydate-main laydate-main-list-"+e}),o[e].appendChild(t),o[e].appendChild(l),s.push(i),y.push(l),d.push(r)}),lay(m).html(function(){var e=[],t=[];return"datetime"===a.type&&e.push(''+n.timeTips+""),(a.range||"datetime"!==a.type)&&e.push(''),lay.each(a.btns,function(e,l){var r=n.tools[l]||"btn";a.range&&"now"===l||(i&&"clear"===l&&(r="cn"===a.lang?"\u91cd\u7f6e":"Reset"),t.push(''+r+""))}),e.push('"),e.join("")}()),lay.each(o,function(e,t){r.appendChild(t)}),a.showBottom&&r.appendChild(m),/^#/.test(a.theme)){var u=lay.elem("style"),h=["#{{id}} .layui-laydate-header{background-color:{{theme}};}","#{{id}} .layui-this{background-color:{{theme}} !important;}"].join("").replace(/{{id}}/g,e.elemID).replace(/{{theme}}/g,a.theme);"styleSheet"in u?(u.setAttribute("type","text/css"),u.styleSheet.cssText=h):u.innerHTML=h,lay(r).addClass("laydate-theme-molv"),r.appendChild(u)}l.thisId=a.id,e.remove(D.thisElemDate),i?a.elem.append(r):(t.body.appendChild(r),e.position()),e.checkDate().calendar(null,0,"init"),e.changeEvent(),D.thisElemDate=e.elemID,"function"==typeof a.ready&&a.ready(lay.extend({},a.dateTime,{month:a.dateTime.month+1})),e.preview()},D.prototype.remove=function(e){var t=this,a=(t.config,lay("#"+(e||t.elemID)));return a[0]?(a.hasClass(c)||t.checkDate(function(){a.remove()}),t):t},D.prototype.position=function(){var e=this,t=e.config;return lay.position(e.bindElem||t.elem[0],e.elem,{position:t.position}),e},D.prototype.hint=function(e){var t=this,a=(t.config,lay.elem("div",{"class":h}));t.elem&&(a.innerHTML=e||"",lay(t.elem).find("."+h).remove(),t.elem.appendChild(a),clearTimeout(t.hinTimer),t.hinTimer=setTimeout(function(){lay(t.elem).find("."+h).remove()},3e3))},D.prototype.getAsYM=function(e,t,a){return a?t--:t++,t<0&&(t=11,e--),t>11&&(t=0,e++),[e,t]},D.prototype.systemDate=function(e){var t=e||new Date;return{year:t.getFullYear(),month:t.getMonth(),date:t.getDate(),hours:e?e.getHours():0,minutes:e?e.getMinutes():0,seconds:e?e.getSeconds():0}},D.prototype.checkDate=function(e){var t,a,n=this,i=(new Date,n.config),r=n.lang(),o=i.dateTime=i.dateTime||n.systemDate(),s=n.bindElem||i.elem[0],y=(n.isInput(s)?"val":"html",function(){if(n.rangeElem){var e=[n.rangeElem[0].val(),n.rangeElem[1].val()];if(e[0]&&e[1])return e.join(" "+n.rangeStr+" ")}return n.isInput(s)?s.value:"static"===i.position?"":lay(s).attr("lay-date")}()),d=function(e){e.year>m[1]&&(e.year=m[1],a=!0),e.month>11&&(e.month=11,a=!0),e.hours>23&&(e.hours=0,a=!0),e.minutes>59&&(e.minutes=0,e.hours++,a=!0),e.seconds>59&&(e.seconds=0,e.minutes++,a=!0),t=l.getEndDate(e.month+1,e.year),e.date>t&&(e.date=t,a=!0)},c=function(e,t,l){var r=["startTime","endTime"];t=(t.match(n.EXP_SPLIT)||[]).slice(1),l=l||0,i.range&&(n[r[l]]=n[r[l]]||{}),lay.each(n.format,function(o,s){var y=parseFloat(t[o]);t[o].lengthh(i.max)||h(o)h(i.max))&&(n.endDate=lay.extend({},i.max)),e&&e(),n},D.prototype.mark=function(e,t){var a,n=this,i=n.config;return lay.each(i.mark,function(e,n){var i=e.split("-");i[0]!=t[0]&&0!=i[0]||i[1]!=t[1]&&0!=i[1]||i[2]!=t[2]||(a=n||t[2])}),a&&e.html(''+a+""),n},D.prototype.limit=function(e,t,a,n){var i,l=this,r=l.config,o={},s=r[a>41?"endDate":"dateTime"],y=lay.extend({},s,t||{});return lay.each({now:y,min:r.min,max:r.max},function(e,t){o[e]=l.newDate(lay.extend({year:t.year,month:t.month,date:t.date},function(){var e={};return lay.each(n,function(a,n){e[n]=t[n]}),e}())).getTime()}),i=o.nowo.max,e&&e[i?"addClass":"removeClass"](d),i},D.prototype.thisDateTime=function(e){var t=this,a=t.config;return e?t.endDate:a.dateTime},D.prototype.calendar=function(e,t,a){var n,i,r,o=this,s=o.config,t=t?1:0,d=e||o.thisDateTime(t),c=new Date,u=o.lang(),h="date"!==s.type&&"datetime"!==s.type,f=lay(o.table[t]).find("td"),g=lay(o.elemHeader[t][2]).find("span");return d.yearm[1]&&(d.year=m[1],o.hint(u.invalidDate)),o.firstDate||(o.firstDate=lay.extend({},d)),c.setFullYear(d.year,d.month,1),n=c.getDay(),i=l.getEndDate(d.month||12,d.year),r=l.getEndDate(d.month+1,d.year),lay.each(f,function(e,t){var a=[d.year,d.month],l=0;t=lay(t),t.removeAttr("class"),e=n&&e=a.firstDate.year&&(l.month=n.max.month,l.date=n.max.date),a.limit(lay(i),l,t),M++}),lay(m[f?0:1]).attr("lay-ym",M-8+"-"+D[1]).html(E+T+" - "+(M-1+T))}else if("month"===e)lay.each(new Array(12),function(e){var i=lay.elem("li",{"lay-ym":e}),r={year:D[0],month:e};e+1==D[1]&&lay(i).addClass(y),i.innerHTML=l.month[e]+(f?"\u6708":""),o.appendChild(i),D[0]=a.firstDate.year&&(r.date=n.max.date),a.limit(lay(i),r,t)}),lay(m[f?0:1]).attr("lay-ym",D[0]+"-"+D[1]).html(D[0]+T);else if("time"===e){var C=function(){lay(o).find("ol").each(function(e,n){lay(n).find("li").each(function(n,i){a.limit(lay(i),[{hours:n},{hours:a[x].hours,minutes:n},{hours:a[x].hours,minutes:a[x].minutes,seconds:n}][e],t,[["hours"],["hours","minutes"],["hours","minutes","seconds"]][e])})}),n.range||a.limit(lay(a.footer).find(p),a[x],0,["hours","minutes","seconds"])};n.range?a[x]||(a[x]="startTime"===x?i:a.endDate):a[x]=i,lay.each([24,60,60],function(e,t){var n=lay.elem("li"),i=["

                    "+l.time[e]+"

                      "];lay.each(new Array(t),function(t){i.push(""+lay.digit(t,2)+"")}),n.innerHTML=i.join("")+"
                    ",o.appendChild(n)}),C()}if(h&&c.removeChild(h),c.appendChild(o),"year"===e||"month"===e)lay(a.elemMain[t]).addClass("laydate-ym-show"),lay(o).find("li").on("click",function(){var l=0|lay(this).attr("lay-ym");if(!lay(this).hasClass(d)){0===t?(i[e]=l,a.limit(lay(a.footer).find(p),null,0)):a.endDate[e]=l;var s="year"===n.type||"month"===n.type;s?(lay(o).find("."+y).removeClass(y),lay(this).addClass(y),"month"===n.type&&"year"===e&&(a.listYM[t][0]=l,r&&((t?a.endDate:i).year=l),a.list("month",t))):(a.checkDate("limit").calendar(null,t),a.closeList()),a.setBtnStatus(),n.range||("month"===n.type&&"month"===e||"year"===n.type&&"year"===e)&&a.setValue(a.parse()).remove().done(),a.done(null,"change"),lay(a.footer).find("."+v).removeClass(d)}});else{var I=lay.elem("span",{"class":g}),k=function(){lay(o).find("ol").each(function(e){var t=this,n=lay(t).find("li");t.scrollTop=30*(a[x][w[e]]-2),t.scrollTop<=0&&n.each(function(e,a){if(!lay(this).hasClass(d))return t.scrollTop=30*(e-2),!0})})},b=lay(s[2]).find("."+g);k(),I.innerHTML=n.range?[l.startTime,l.endTime][t]:l.timeTips,lay(a.elemMain[t]).addClass("laydate-time-show"),b[0]&&b.remove(),s[2].appendChild(I),lay(o).find("ol").each(function(e){var t=this;lay(t).find("li").on("click",function(){var l=0|this.innerHTML;lay(this).hasClass(d)||(n.range?a[x][w[e]]=l:i[w[e]]=l,lay(t).find("."+y).removeClass(y),lay(this).addClass(y),C(),k(),(a.endDate||"time"===n.type)&&a.done(null,"change"),a.setBtnStatus())})})}return a},D.prototype.listYM=[],D.prototype.closeList=function(){var e=this;e.config;lay.each(e.elemCont,function(t,a){lay(this).find("."+u).remove(),lay(e.elemMain[t]).removeClass("laydate-ym-show laydate-time-show")}),lay(e.elem).find("."+g).remove()},D.prototype.setBtnStatus=function(e,t,a){var n,i=this,l=i.config,r=i.lang(),o=lay(i.footer).find(p);l.range&&"time"!==l.type&&(t=t||l.dateTime,a=a||i.endDate,n=i.newDate(t).getTime()>i.newDate(a).getTime(),i.limit(null,t)||i.limit(null,a)?o.addClass(d):o[n?"addClass":"removeClass"](d),e&&n&&i.hint("string"==typeof e?r.timeout.replace(/\u65e5\u671f/g,e):r.timeout))},D.prototype.parse=function(e,t){var a=this,n=a.config,i=t||("end"==e?lay.extend({},a.endDate,a.endTime):n.range?lay.extend({},n.dateTime,a.startTime):n.dateTime),r=l.parse(i,a.format,1);return n.range&&void 0===e?r+" "+a.rangeStr+" "+a.parse("end"):r},D.prototype.newDate=function(e){return e=e||{},new Date(e.year||1,e.month||0,e.date||1,e.hours||0,e.minutes||0,e.seconds||0)},D.prototype.setValue=function(e){var t=this,a=t.config,n=t.bindElem||a.elem[0];return"static"===a.position?t:(e=e||"",t.isInput(n)?lay(n).val(e):t.rangeElem?(t.rangeElem[0].val(e?t.parse("start"):""),t.rangeElem[1].val(e?t.parse("end"):"")):(0===lay(n).find("*").length&&lay(n).html(e),lay(n).attr("lay-date",e)),t)},D.prototype.preview=function(){var e=this,t=e.config;if(t.isPreview){var a=lay(e.elem).find("."+T),n=t.range?e.endDate?e.parse():"":e.parse();a.html(n).css({color:"#5FB878"}),setTimeout(function(){a.css({color:"#666"})},300)}},D.prototype.done=function(e,t){var a=this,n=a.config,i=lay.extend({},lay.extend(n.dateTime,a.startTime)),l=lay.extend({},lay.extend(a.endDate,a.endTime));return lay.each([i,l],function(e,t){"month"in t&&lay.extend(t,{month:t.month+1})}),a.preview(),e=e||[a.parse(),i,l],"function"==typeof n[t||"done"]&&n[t||"done"].apply(n,e),a},D.prototype.choose=function(e,t){var a=this,n=a.config,i=a.thisDateTime(t),l=(lay(a.elem).find("td"),e.attr("lay-ymd").split("-"));l={year:0|l[0],month:(0|l[1])-1,date:0|l[2]},e.hasClass(d)||(lay.extend(i,l),n.range?(lay.each(["startTime","endTime"],function(e,t){a[t]=a[t]||{hours:0,minutes:0,seconds:0}}),a.calendar(null,t).done(null,"change")):"static"===n.position?a.calendar().done().done(null,"change"):"date"===n.type?a.setValue(a.parse()).remove().done():"datetime"===n.type&&a.calendar().done(null,"change"))},D.prototype.tool=function(e,t){var a=this,n=a.config,i=a.lang(),l=n.dateTime,r="static"===n.position,o={datetime:function(){lay(e).hasClass(d)||(a.list("time",0),n.range&&a.list("time",1),lay(e).attr("lay-type","date").html(a.lang().dateTips))},date:function(){a.closeList(),lay(e).attr("lay-type","datetime").html(a.lang().timeTips)},clear:function(){r&&(lay.extend(l,a.firstDate),a.calendar()),n.range&&(delete n.dateTime,delete a.endDate,delete a.startTime,delete a.endTime),a.setValue("").remove(),a.done(["",{},{}])},now:function(){var e=new Date;lay.extend(l,a.systemDate(),{hours:e.getHours(),minutes:e.getMinutes(),seconds:e.getSeconds()}),a.setValue(a.parse()).remove(),r&&a.calendar(),a.done()},confirm:function(){if(n.range){if(lay(e).hasClass(d))return a.hint("time"===n.type?i.timeout.replace(/\u65e5\u671f/g,"\u65f6\u95f4"):i.timeout)}else if(lay(e).hasClass(d))return a.hint(i.invalidDate);a.done(),a.setValue(a.parse()).remove()}};o[t]&&o[t]()},D.prototype.change=function(e){var t=this,a=t.config,n=t.thisDateTime(e),i=a.range&&("year"===a.type||"month"===a.type),l=t.elemCont[e||0],r=t.listYM[e],o=function(o){var s=lay(l).find(".laydate-year-list")[0],y=lay(l).find(".laydate-month-list")[0];return s&&(r[0]=o?r[0]-15:r[0]+15,t.list("year",e)),y&&(o?r[0]--:r[0]++,t.list("month",e)),(s||y)&&(lay.extend(n,{year:r[0]}),i&&(n.year=r[0]),a.range||t.done(null,"change"),a.range||t.limit(lay(t.footer).find(p),{year:r[0]})),t.setBtnStatus(),s||y};return{prevYear:function(){o("sub")||(n.year--,t.checkDate("limit").calendar(null,e),t.done(null,"change"))},prevMonth:function(){var a=t.getAsYM(n.year,n.month,"sub");lay.extend(n,{year:a[0],month:a[1]}),t.checkDate("limit").calendar(null,e),t.done(null,"change")},nextMonth:function(){var a=t.getAsYM(n.year,n.month);lay.extend(n,{year:a[0],month:a[1]}),t.checkDate("limit").calendar(null,e),t.done(null,"change")},nextYear:function(){o()||(n.year++,t.checkDate("limit").calendar(null,e),t.done(null,"change"))}}},D.prototype.changeEvent=function(){var e=this;e.config;lay(e.elem).on("click",function(e){lay.stope(e)}).on("mousedown",function(e){lay.stope(e)}),lay.each(e.elemHeader,function(t,a){lay(a[0]).on("click",function(a){e.change(t).prevYear()}),lay(a[1]).on("click",function(a){e.change(t).prevMonth()}),lay(a[2]).find("span").on("click",function(a){var n=lay(this),i=n.attr("lay-ym"),l=n.attr("lay-type");i&&(i=i.split("-"),e.listYM[t]=[0|i[0],0|i[1]],e.list(l,t),lay(e.footer).find("."+v).addClass(d))}),lay(a[3]).on("click",function(a){e.change(t).nextMonth()}),lay(a[4]).on("click",function(a){e.change(t).nextYear()})}),lay.each(e.table,function(t,a){var n=lay(a).find("td");n.on("click",function(){e.choose(lay(this),t)})}),lay(e.footer).find("span").on("click",function(){var t=lay(this).attr("lay-type");e.tool(this,t)})},D.prototype.isInput=function(e){return/input|textarea/.test(e.tagName.toLocaleLowerCase())},D.prototype.events=function(){var e=this,t=e.config,a=function(a,n){a.on(t.trigger,function(){n&&(e.bindElem=this),e.render()})};t.elem[0]&&!t.elem[0].eventHandler&&(a(t.elem,"bind"),a(t.eventElem),t.elem[0].eventHandler=!0)},r.that={},r.getThis=function(e){var t=r.that[e];return!t&&a&&layui.hint().error(e?o+" instance with ID '"+e+"' not found":"ID argument required"),t},n.run=function(a){a(t).on("mousedown",function(e){if(l.thisId){var t=r.getThis(l.thisId);if(t){var n=t.config;e.target!==n.elem[0]&&e.target!==n.eventElem[0]&&e.target!==a(n.closeStop)[0]&&t.remove()}}}).on("keydown",function(e){if(l.thisId){var t=r.getThis(l.thisId);t&&13===e.keyCode&&a("#"+t.elemID)[0]&&t.elemID===D.thisElemDate&&(e.preventDefault(),a(t.footer).find(p)[0].click())}}),a(e).on("resize",function(){if(l.thisId){var e=r.getThis(l.thisId);if(e)return!(!e.elem||!a(s)[0])&&void e.position()}})},l.render=function(e){var t=new D(e);return r.call(t)},l.parse=function(e,t,a){return e=e||{},"string"==typeof t&&(t=r.formatArr(t)),t=(t||[]).concat(),lay.each(t,function(n,i){/yyyy|y/.test(i)?t[n]=lay.digit(e.year,i.length):/MM|M/.test(i)?t[n]=lay.digit(e.month+(a||0),i.length):/dd|d/.test(i)?t[n]=lay.digit(e.date,i.length):/HH|H/.test(i)?t[n]=lay.digit(e.hours,i.length):/mm|m/.test(i)?t[n]=lay.digit(e.minutes,i.length):/ss|s/.test(i)&&(t[n]=lay.digit(e.seconds,i.length))}),t.join("")},l.getEndDate=function(e,t){var a=new Date;return a.setFullYear(t||a.getFullYear(),e||a.getMonth()+1,1),new Date(a.getTime()-864e5).getDate()},a?(l.ready(),layui.define("lay",function(e){l.path=layui.cache.dir,n.run(lay),e(o,l)})):"function"==typeof define&&define.amd?define(function(){return n.run(lay),l}):function(){l.ready(),n.run(e.lay),e.laydate=l}()}(window,window.document);!function(e,t){"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){function n(e){var t=!!e&&"length"in e&&e.length,n=pe.type(e);return"function"!==n&&!pe.isWindow(e)&&("array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e)}function r(e,t,n){if(pe.isFunction(t))return pe.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return pe.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(Ce.test(t))return pe.filter(t,e,n);t=pe.filter(t,e)}return pe.grep(e,function(e){return pe.inArray(e,t)>-1!==n})}function i(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function o(e){var t={};return pe.each(e.match(De)||[],function(e,n){t[n]=!0}),t}function a(){re.addEventListener?(re.removeEventListener("DOMContentLoaded",s),e.removeEventListener("load",s)):(re.detachEvent("onreadystatechange",s),e.detachEvent("onload",s))}function s(){(re.addEventListener||"load"===e.event.type||"complete"===re.readyState)&&(a(),pe.ready())}function u(e,t,n){if(void 0===n&&1===e.nodeType){var r="data-"+t.replace(_e,"-$1").toLowerCase();if(n=e.getAttribute(r),"string"==typeof n){try{n="true"===n||"false"!==n&&("null"===n?null:+n+""===n?+n:qe.test(n)?pe.parseJSON(n):n)}catch(i){}pe.data(e,t,n)}else n=void 0}return n}function l(e){var t;for(t in e)if(("data"!==t||!pe.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}function c(e,t,n,r){if(He(e)){var i,o,a=pe.expando,s=e.nodeType,u=s?pe.cache:e,l=s?e[a]:e[a]&&a;if(l&&u[l]&&(r||u[l].data)||void 0!==n||"string"!=typeof t)return l||(l=s?e[a]=ne.pop()||pe.guid++:a),u[l]||(u[l]=s?{}:{toJSON:pe.noop}),"object"!=typeof t&&"function"!=typeof t||(r?u[l]=pe.extend(u[l],t):u[l].data=pe.extend(u[l].data,t)),o=u[l],r||(o.data||(o.data={}),o=o.data),void 0!==n&&(o[pe.camelCase(t)]=n),"string"==typeof t?(i=o[t],null==i&&(i=o[pe.camelCase(t)])):i=o,i}}function f(e,t,n){if(He(e)){var r,i,o=e.nodeType,a=o?pe.cache:e,s=o?e[pe.expando]:pe.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){pe.isArray(t)?t=t.concat(pe.map(t,pe.camelCase)):t in r?t=[t]:(t=pe.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;for(;i--;)delete r[t[i]];if(n?!l(r):!pe.isEmptyObject(r))return}(n||(delete a[s].data,l(a[s])))&&(o?pe.cleanData([e],!0):fe.deleteExpando||a!=a.window?delete a[s]:a[s]=void 0)}}}function d(e,t,n,r){var i,o=1,a=20,s=r?function(){return r.cur()}:function(){return pe.css(e,t,"")},u=s(),l=n&&n[3]||(pe.cssNumber[t]?"":"px"),c=(pe.cssNumber[t]||"px"!==l&&+u)&&Me.exec(pe.css(e,t));if(c&&c[3]!==l){l=l||c[3],n=n||[],c=+u||1;do o=o||".5",c/=o,pe.style(e,t,c+l);while(o!==(o=s()/u)&&1!==o&&--a)}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}function p(e){var t=ze.split("|"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function h(e,t){var n,r,i=0,o="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):void 0;if(!o)for(o=[],n=e.childNodes||e;null!=(r=n[i]);i++)!t||pe.nodeName(r,t)?o.push(r):pe.merge(o,h(r,t));return void 0===t||t&&pe.nodeName(e,t)?pe.merge([e],o):o}function g(e,t){for(var n,r=0;null!=(n=e[r]);r++)pe._data(n,"globalEval",!t||pe._data(t[r],"globalEval"))}function m(e){Be.test(e.type)&&(e.defaultChecked=e.checked)}function y(e,t,n,r,i){for(var o,a,s,u,l,c,f,d=e.length,y=p(t),v=[],x=0;x"!==f[1]||Ve.test(a)?0:u:u.firstChild,o=a&&a.childNodes.length;o--;)pe.nodeName(c=a.childNodes[o],"tbody")&&!c.childNodes.length&&a.removeChild(c);for(pe.merge(v,u.childNodes),u.textContent="";u.firstChild;)u.removeChild(u.firstChild);u=y.lastChild}else v.push(t.createTextNode(a));for(u&&y.removeChild(u),fe.appendChecked||pe.grep(h(v,"input"),m),x=0;a=v[x++];)if(r&&pe.inArray(a,r)>-1)i&&i.push(a);else if(s=pe.contains(a.ownerDocument,a),u=h(y.appendChild(a),"script"),s&&g(u),n)for(o=0;a=u[o++];)Ie.test(a.type||"")&&n.push(a);return u=null,y}function v(){return!0}function x(){return!1}function b(){try{return re.activeElement}catch(e){}}function w(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)w(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),i===!1)i=x;else if(!i)return e;return 1===o&&(a=i,i=function(e){return pe().off(e),a.apply(this,arguments)},i.guid=a.guid||(a.guid=pe.guid++)),e.each(function(){pe.event.add(this,t,i,r,n)})}function T(e,t){return pe.nodeName(e,"table")&&pe.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function C(e){return e.type=(null!==pe.find.attr(e,"type"))+"/"+e.type,e}function E(e){var t=it.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function N(e,t){if(1===t.nodeType&&pe.hasData(e)){var n,r,i,o=pe._data(e),a=pe._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;r1&&"string"==typeof p&&!fe.checkClone&&rt.test(p))return e.each(function(i){var o=e.eq(i);g&&(t[0]=p.call(this,i,o.html())),S(o,t,n,r)});if(f&&(l=y(t,e[0].ownerDocument,!1,e,r),i=l.firstChild,1===l.childNodes.length&&(l=i),i||r)){for(s=pe.map(h(l,"script"),C),a=s.length;c")).appendTo(t.documentElement),t=(ut[0].contentWindow||ut[0].contentDocument).document,t.write(),t.close(),n=D(e,t),ut.detach()),lt[e]=n),n}function L(e,t){return{get:function(){return e()?void delete this.get:(this.get=t).apply(this,arguments)}}}function H(e){if(e in Et)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=Ct.length;n--;)if(e=Ct[n]+t,e in Et)return e}function q(e,t){for(var n,r,i,o=[],a=0,s=e.length;a=0&&n=0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},isPlainObject:function(e){var t;if(!e||"object"!==pe.type(e)||e.nodeType||pe.isWindow(e))return!1;try{if(e.constructor&&!ce.call(e,"constructor")&&!ce.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}if(!fe.ownFirst)for(t in e)return ce.call(e,t);for(t in e);return void 0===t||ce.call(e,t)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?ue[le.call(e)]||"object":typeof e},globalEval:function(t){t&&pe.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(ge,"ms-").replace(me,ye)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t){var r,i=0;if(n(e))for(r=e.length;iT.cacheLength&&delete e[t.shift()],e[n+" "]=r}var t=[];return e}function r(e){return e[P]=!0,e}function i(e){var t=H.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var n=e.split("|"),r=n.length;r--;)T.attrHandle[n[r]]=t}function a(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||V)-(~e.sourceIndex||V);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function s(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function u(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function l(e){return r(function(t){return t=+t,r(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function c(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function f(){}function d(e){for(var t=0,n=e.length,r="";t1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function g(e,n,r){for(var i=0,o=n.length;i-1&&(r[l]=!(a[l]=f))}}else x=m(x===a?x.splice(h,x.length):x),o?o(null,a,x,u):Q.apply(a,x)})}function v(e){for(var t,n,r,i=e.length,o=T.relative[e[0].type],a=o||T.relative[" "],s=o?1:0,u=p(function(e){return e===t},a,!0),l=p(function(e){return ee(t,e)>-1},a,!0),c=[function(e,n,r){var i=!o&&(r||n!==A)||((t=n).nodeType?u(e,n,r):l(e,n,r));return t=null,i}];s1&&h(c),s>1&&d(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(se,"$1"),n,s0,o=e.length>0,a=function(r,a,s,u,l){var c,f,d,p=0,h="0",g=r&&[],y=[],v=A,x=r||o&&T.find.TAG("*",l),b=W+=null==v?1:Math.random()||.1,w=x.length;for(l&&(A=a===H||a||l);h!==w&&null!=(c=x[h]);h++){if(o&&c){for(f=0,a||c.ownerDocument===H||(L(c),s=!_);d=e[f++];)if(d(c,a||H,s)){u.push(c);break}l&&(W=b)}i&&((c=!d&&c)&&p--,r&&g.push(c))}if(p+=h,i&&h!==p){for(f=0;d=n[f++];)d(g,y,a,s);if(r){if(p>0)for(;h--;)g[h]||y[h]||(y[h]=G.call(u));y=m(y)}Q.apply(u,y),l&&!r&&y.length>0&&p+n.length>1&&t.uniqueSort(u)}return l&&(W=b,A=v),g};return i?r(a):a}var b,w,T,C,E,N,k,S,A,D,j,L,H,q,_,F,M,O,R,P="sizzle"+1*new Date,B=e.document,W=0,I=0,$=n(),z=n(),X=n(),U=function(e,t){return e===t&&(j=!0),0},V=1<<31,Y={}.hasOwnProperty,J=[],G=J.pop,K=J.push,Q=J.push,Z=J.slice,ee=function(e,t){for(var n=0,r=e.length;n+~]|"+ne+")"+ne+"*"),ce=new RegExp("="+ne+"*([^\\]'\"]*?)"+ne+"*\\]","g"),fe=new RegExp(oe),de=new RegExp("^"+re+"$"),pe={ID:new RegExp("^#("+re+")"),CLASS:new RegExp("^\\.("+re+")"),TAG:new RegExp("^("+re+"|[*])"),ATTR:new RegExp("^"+ie),PSEUDO:new RegExp("^"+oe),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ne+"*(even|odd|(([+-]|)(\\d*)n|)"+ne+"*(?:([+-]|)"+ne+"*(\\d+)|))"+ne+"*\\)|)","i"),bool:new RegExp("^(?:"+te+")$","i"),needsContext:new RegExp("^"+ne+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ne+"*((?:-\\d)?\\d*)"+ne+"*\\)|)(?=[^-]|$)","i")},he=/^(?:input|select|textarea|button)$/i,ge=/^h\d$/i,me=/^[^{]+\{\s*\[native \w/,ye=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ve=/[+~]/,xe=/'|\\/g,be=new RegExp("\\\\([\\da-f]{1,6}"+ne+"?|("+ne+")|.)","ig"),we=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},Te=function(){L()};try{Q.apply(J=Z.call(B.childNodes),B.childNodes),J[B.childNodes.length].nodeType}catch(Ce){Q={apply:J.length?function(e,t){K.apply(e,Z.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}w=t.support={},E=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},L=t.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:B;return r!==H&&9===r.nodeType&&r.documentElement?(H=r,q=H.documentElement,_=!E(H),(n=H.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",Te,!1):n.attachEvent&&n.attachEvent("onunload",Te)),w.attributes=i(function(e){return e.className="i",!e.getAttribute("className")}),w.getElementsByTagName=i(function(e){return e.appendChild(H.createComment("")),!e.getElementsByTagName("*").length}),w.getElementsByClassName=me.test(H.getElementsByClassName),w.getById=i(function(e){return q.appendChild(e).id=P,!H.getElementsByName||!H.getElementsByName(P).length}),w.getById?(T.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&_){var n=t.getElementById(e);return n?[n]:[]}},T.filter.ID=function(e){var t=e.replace(be,we);return function(e){return e.getAttribute("id")===t}}):(delete T.find.ID,T.filter.ID=function(e){var t=e.replace(be,we);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}}),T.find.TAG=w.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):w.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},T.find.CLASS=w.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&_)return t.getElementsByClassName(e)},M=[],F=[],(w.qsa=me.test(H.querySelectorAll))&&(i(function(e){q.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&F.push("[*^$]="+ne+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||F.push("\\["+ne+"*(?:value|"+te+")"),e.querySelectorAll("[id~="+P+"-]").length||F.push("~="),e.querySelectorAll(":checked").length||F.push(":checked"),e.querySelectorAll("a#"+P+"+*").length||F.push(".#.+[+~]")}),i(function(e){var t=H.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&F.push("name"+ne+"*[*^$|!~]?="),e.querySelectorAll(":enabled").length||F.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),F.push(",.*:")})),(w.matchesSelector=me.test(O=q.matches||q.webkitMatchesSelector||q.mozMatchesSelector||q.oMatchesSelector||q.msMatchesSelector))&&i(function(e){w.disconnectedMatch=O.call(e,"div"),O.call(e,"[s!='']:x"),M.push("!=",oe)}),F=F.length&&new RegExp(F.join("|")),M=M.length&&new RegExp(M.join("|")),t=me.test(q.compareDocumentPosition),R=t||me.test(q.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},U=t?function(e,t){if(e===t)return j=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n?n:(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&n||!w.sortDetached&&t.compareDocumentPosition(e)===n?e===H||e.ownerDocument===B&&R(B,e)?-1:t===H||t.ownerDocument===B&&R(B,t)?1:D?ee(D,e)-ee(D,t):0:4&n?-1:1)}:function(e,t){if(e===t)return j=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,s=[e],u=[t];if(!i||!o)return e===H?-1:t===H?1:i?-1:o?1:D?ee(D,e)-ee(D,t):0;if(i===o)return a(e,t);for(n=e;n=n.parentNode;)s.unshift(n);for(n=t;n=n.parentNode;)u.unshift(n);for(;s[r]===u[r];)r++;return r?a(s[r],u[r]):s[r]===B?-1:u[r]===B?1:0},H):H},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==H&&L(e),n=n.replace(ce,"='$1']"),w.matchesSelector&&_&&!X[n+" "]&&(!M||!M.test(n))&&(!F||!F.test(n)))try{var r=O.call(e,n);if(r||w.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return t(n,H,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==H&&L(e),R(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==H&&L(e);var n=T.attrHandle[t.toLowerCase()],r=n&&Y.call(T.attrHandle,t.toLowerCase())?n(e,t,!_):void 0;return void 0!==r?r:w.attributes||!_?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},t.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},t.uniqueSort=function(e){var t,n=[],r=0,i=0;if(j=!w.detectDuplicates,D=!w.sortStable&&e.slice(0),e.sort(U),j){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return D=null,e},C=t.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=C(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r++];)n+=C(t);return n},T=t.selectors={cacheLength:50,createPseudo:r,match:pe,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(be,we),e[3]=(e[3]||e[4]||e[5]||"").replace(be,we),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||t.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return pe.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&fe.test(n)&&(t=N(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(be,we).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=$[e+" "];return t||(t=new RegExp("(^|"+ne+")"+e+"("+ne+"|$)"))&&$(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,n,r){return function(i){var o=t.attr(i,e);return null==o?"!="===n:!n||(o+="","="===n?o===r:"!="===n?o!==r:"^="===n?r&&0===o.indexOf(r):"*="===n?r&&o.indexOf(r)>-1:"$="===n?r&&o.slice(-r.length)===r:"~="===n?(" "+o.replace(ae," ")+" ").indexOf(r)>-1:"|="===n&&(o===r||o.slice(0,r.length+1)===r+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,d,p,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s,x=!1;if(m){if(o){for(;g;){for(d=t;d=d[g];)if(s?d.nodeName.toLowerCase()===y:1===d.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){for(d=m,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),l=c[e]||[],p=l[0]===W&&l[1],x=p&&l[2], +d=p&&m.childNodes[p];d=++p&&d&&d[g]||(x=p=0)||h.pop();)if(1===d.nodeType&&++x&&d===t){c[e]=[W,p,x];break}}else if(v&&(d=t,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),l=c[e]||[],p=l[0]===W&&l[1],x=p),x===!1)for(;(d=++p&&d&&d[g]||(x=p=0)||h.pop())&&((s?d.nodeName.toLowerCase()!==y:1!==d.nodeType)||!++x||(v&&(f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),c[e]=[W,x]),d!==t)););return x-=i,x===r||x%r===0&&x/r>=0}}},PSEUDO:function(e,n){var i,o=T.pseudos[e]||T.setFilters[e.toLowerCase()]||t.error("unsupported pseudo: "+e);return o[P]?o(n):o.length>1?(i=[e,e,"",n],T.setFilters.hasOwnProperty(e.toLowerCase())?r(function(e,t){for(var r,i=o(e,n),a=i.length;a--;)r=ee(e,i[a]),e[r]=!(t[r]=i[a])}):function(e){return o(e,0,i)}):o}},pseudos:{not:r(function(e){var t=[],n=[],i=k(e.replace(se,"$1"));return i[P]?r(function(e,t,n,r){for(var o,a=i(e,null,r,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,r,o){return t[0]=e,i(t,null,o,n),t[0]=null,!n.pop()}}),has:r(function(e){return function(n){return t(e,n).length>0}}),contains:r(function(e){return e=e.replace(be,we),function(t){return(t.textContent||t.innerText||C(t)).indexOf(e)>-1}}),lang:r(function(e){return de.test(e||"")||t.error("unsupported lang: "+e),e=e.replace(be,we).toLowerCase(),function(t){var n;do if(n=_?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===q},focus:function(e){return e===H.activeElement&&(!H.hasFocus||H.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!T.pseudos.empty(e)},header:function(e){return ge.test(e.nodeName)},input:function(e){return he.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:l(function(){return[0]}),last:l(function(e,t){return[t-1]}),eq:l(function(e,t,n){return[n<0?n+t:n]}),even:l(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:l(function(e,t,n){for(var r=n<0?n+t:n;++r2&&"ID"===(a=o[0]).type&&w.getById&&9===t.nodeType&&_&&T.relative[o[1].type]){if(t=(T.find.ID(a.matches[0].replace(be,we),t)||[])[0],!t)return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=pe.needsContext.test(e)?0:o.length;i--&&(a=o[i],!T.relative[s=a.type]);)if((u=T.find[s])&&(r=u(a.matches[0].replace(be,we),ve.test(o[0].type)&&c(t.parentNode)||t))){if(o.splice(i,1),e=r.length&&d(o),!e)return Q.apply(n,r),n;break}}return(l||k(e,f))(r,t,!_,n,!t||ve.test(e)&&c(t.parentNode)||t),n},w.sortStable=P.split("").sort(U).join("")===P,w.detectDuplicates=!!j,L(),w.sortDetached=i(function(e){return 1&e.compareDocumentPosition(H.createElement("div"))}),i(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||o("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),w.attributes&&i(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||o("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),i(function(e){return null==e.getAttribute("disabled")})||o(te,function(e,t,n){var r;if(!n)return e[t]===!0?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),t}(e);pe.find=ve,pe.expr=ve.selectors,pe.expr[":"]=pe.expr.pseudos,pe.uniqueSort=pe.unique=ve.uniqueSort,pe.text=ve.getText,pe.isXMLDoc=ve.isXML,pe.contains=ve.contains;var xe=function(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&pe(e).is(n))break;r.push(e)}return r},be=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},we=pe.expr.match.needsContext,Te=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,Ce=/^.[^:#\[\.,]*$/;pe.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?pe.find.matchesSelector(r,e)?[r]:[]:pe.find.matches(e,pe.grep(t,function(e){return 1===e.nodeType}))},pe.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(pe(e).filter(function(){for(t=0;t1?pe.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},filter:function(e){return this.pushStack(r(this,e||[],!1))},not:function(e){return this.pushStack(r(this,e||[],!0))},is:function(e){return!!r(this,"string"==typeof e&&we.test(e)?pe(e):e||[],!1).length}});var Ee,Ne=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,ke=pe.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||Ee,"string"==typeof e){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:Ne.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof pe?t[0]:t,pe.merge(this,pe.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:re,!0)),Te.test(r[1])&&pe.isPlainObject(t))for(r in t)pe.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}if(i=re.getElementById(r[2]),i&&i.parentNode){if(i.id!==r[2])return Ee.find(e);this.length=1,this[0]=i}return this.context=re,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):pe.isFunction(e)?"undefined"!=typeof n.ready?n.ready(e):e(pe):(void 0!==e.selector&&(this.selector=e.selector,this.context=e.context),pe.makeArray(e,this))};ke.prototype=pe.fn,Ee=pe(re);var Se=/^(?:parents|prev(?:Until|All))/,Ae={children:!0,contents:!0,next:!0,prev:!0};pe.fn.extend({has:function(e){var t,n=pe(e,this),r=n.length;return this.filter(function(){for(t=0;t-1:1===n.nodeType&&pe.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?pe.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?pe.inArray(this[0],pe(e)):pe.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(pe.uniqueSort(pe.merge(this.get(),pe(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),pe.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return xe(e,"parentNode")},parentsUntil:function(e,t,n){return xe(e,"parentNode",n)},next:function(e){return i(e,"nextSibling")},prev:function(e){return i(e,"previousSibling")},nextAll:function(e){return xe(e,"nextSibling")},prevAll:function(e){return xe(e,"previousSibling")},nextUntil:function(e,t,n){return xe(e,"nextSibling",n)},prevUntil:function(e,t,n){return xe(e,"previousSibling",n)},siblings:function(e){return be((e.parentNode||{}).firstChild,e)},children:function(e){return be(e.firstChild)},contents:function(e){return pe.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:pe.merge([],e.childNodes)}},function(e,t){pe.fn[e]=function(n,r){var i=pe.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=pe.filter(r,i)),this.length>1&&(Ae[e]||(i=pe.uniqueSort(i)),Se.test(e)&&(i=i.reverse())),this.pushStack(i)}});var De=/\S+/g;pe.Callbacks=function(e){e="string"==typeof e?o(e):pe.extend({},e);var t,n,r,i,a=[],s=[],u=-1,l=function(){for(i=e.once,r=t=!0;s.length;u=-1)for(n=s.shift();++u-1;)a.splice(n,1),n<=u&&u--}),this},has:function(e){return e?pe.inArray(e,a)>-1:a.length>0},empty:function(){return a&&(a=[]),this},disable:function(){return i=s=[],a=n="",this},disabled:function(){return!a},lock:function(){return i=!0,n||c.disable(),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=n||[],n=[e,n.slice?n.slice():n],s.push(n),t||l()),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},pe.extend({Deferred:function(e){var t=[["resolve","done",pe.Callbacks("once memory"),"resolved"],["reject","fail",pe.Callbacks("once memory"),"rejected"],["notify","progress",pe.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return pe.Deferred(function(n){pe.each(t,function(t,o){var a=pe.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&pe.isFunction(e.promise)?e.promise().progress(n.notify).done(n.resolve).fail(n.reject):n[o[0]+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?pe.extend(e,r):r}},i={};return r.pipe=r.then,pe.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t,n,r,i=0,o=ie.call(arguments),a=o.length,s=1!==a||e&&pe.isFunction(e.promise)?a:0,u=1===s?e:pe.Deferred(),l=function(e,n,r){return function(i){n[e]=this,r[e]=arguments.length>1?ie.call(arguments):i,r===t?u.notifyWith(n,r):--s||u.resolveWith(n,r)}};if(a>1)for(t=new Array(a),n=new Array(a),r=new Array(a);i0||(je.resolveWith(re,[pe]),pe.fn.triggerHandler&&(pe(re).triggerHandler("ready"),pe(re).off("ready"))))}}),pe.ready.promise=function(t){if(!je)if(je=pe.Deferred(),"complete"===re.readyState||"loading"!==re.readyState&&!re.documentElement.doScroll)e.setTimeout(pe.ready);else if(re.addEventListener)re.addEventListener("DOMContentLoaded",s),e.addEventListener("load",s);else{re.attachEvent("onreadystatechange",s),e.attachEvent("onload",s);var n=!1;try{n=null==e.frameElement&&re.documentElement}catch(r){}n&&n.doScroll&&!function i(){if(!pe.isReady){try{n.doScroll("left")}catch(t){return e.setTimeout(i,50)}a(),pe.ready()}}()}return je.promise(t)},pe.ready.promise();var Le;for(Le in pe(fe))break;fe.ownFirst="0"===Le,fe.inlineBlockNeedsLayout=!1,pe(function(){var e,t,n,r;n=re.getElementsByTagName("body")[0],n&&n.style&&(t=re.createElement("div"),r=re.createElement("div"),r.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",n.appendChild(r).appendChild(t),"undefined"!=typeof t.style.zoom&&(t.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",fe.inlineBlockNeedsLayout=e=3===t.offsetWidth,e&&(n.style.zoom=1)),n.removeChild(r))}),function(){var e=re.createElement("div");fe.deleteExpando=!0;try{delete e.test}catch(t){fe.deleteExpando=!1}e=null}();var He=function(e){var t=pe.noData[(e.nodeName+" ").toLowerCase()],n=+e.nodeType||1;return(1===n||9===n)&&(!t||t!==!0&&e.getAttribute("classid")===t)},qe=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,_e=/([A-Z])/g;pe.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?pe.cache[e[pe.expando]]:e[pe.expando],!!e&&!l(e)},data:function(e,t,n){return c(e,t,n)},removeData:function(e,t){return f(e,t)},_data:function(e,t,n){return c(e,t,n,!0)},_removeData:function(e,t){return f(e,t,!0)}}),pe.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=pe.data(o),1===o.nodeType&&!pe._data(o,"parsedAttrs"))){for(n=a.length;n--;)a[n]&&(r=a[n].name,0===r.indexOf("data-")&&(r=pe.camelCase(r.slice(5)),u(o,r,i[r])));pe._data(o,"parsedAttrs",!0)}return i}return"object"==typeof e?this.each(function(){pe.data(this,e)}):arguments.length>1?this.each(function(){pe.data(this,e,t)}):o?u(o,e,pe.data(o,e)):void 0},removeData:function(e){return this.each(function(){pe.removeData(this,e)})}}),pe.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=pe._data(e,t),n&&(!r||pe.isArray(n)?r=pe._data(e,t,pe.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=pe.queue(e,t),r=n.length,i=n.shift(),o=pe._queueHooks(e,t),a=function(){pe.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return pe._data(e,n)||pe._data(e,n,{empty:pe.Callbacks("once memory").add(function(){pe._removeData(e,t+"queue"),pe._removeData(e,n)})})}}),pe.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length
                    a",fe.leadingWhitespace=3===e.firstChild.nodeType,fe.tbody=!e.getElementsByTagName("tbody").length,fe.htmlSerialize=!!e.getElementsByTagName("link").length,fe.html5Clone="<:nav>"!==re.createElement("nav").cloneNode(!0).outerHTML,n.type="checkbox",n.checked=!0,t.appendChild(n),fe.appendChecked=n.checked,e.innerHTML="",fe.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue,t.appendChild(e),n=re.createElement("input"),n.setAttribute("type","radio"),n.setAttribute("checked","checked"),n.setAttribute("name","t"),e.appendChild(n),fe.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,fe.noCloneEvent=!!e.addEventListener,e[pe.expando]=1,fe.attributes=!e.getAttribute(pe.expando)}();var Xe={option:[1,""],legend:[1,"
                    ","
                    "],area:[1,"",""],param:[1,"",""],thead:[1,"","
                    "],tr:[2,"","
                    "],col:[2,"","
                    "],td:[3,"","
                    "],_default:fe.htmlSerialize?[0,"",""]:[1,"X
                    ","
                    "]};Xe.optgroup=Xe.option,Xe.tbody=Xe.tfoot=Xe.colgroup=Xe.caption=Xe.thead,Xe.th=Xe.td;var Ue=/<|&#?\w+;/,Ve=/-1&&(h=p.split("."),p=h.shift(),h.sort()),a=p.indexOf(":")<0&&"on"+p,t=t[pe.expando]?t:new pe.Event(p,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=h.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=r),n=null==n?[t]:pe.makeArray(n,[t]),l=pe.event.special[p]||{},i||!l.trigger||l.trigger.apply(r,n)!==!1)){if(!i&&!l.noBubble&&!pe.isWindow(r)){for(u=l.delegateType||p,Ke.test(u+p)||(s=s.parentNode);s;s=s.parentNode)d.push(s),c=s;c===(r.ownerDocument||re)&&d.push(c.defaultView||c.parentWindow||e)}for(f=0;(s=d[f++])&&!t.isPropagationStopped();)t.type=f>1?u:l.bindType||p,o=(pe._data(s,"events")||{})[t.type]&&pe._data(s,"handle"),o&&o.apply(s,n),o=a&&s[a],o&&o.apply&&He(s)&&(t.result=o.apply(s,n),t.result===!1&&t.preventDefault());if(t.type=p,!i&&!t.isDefaultPrevented()&&(!l._default||l._default.apply(d.pop(),n)===!1)&&He(r)&&a&&r[p]&&!pe.isWindow(r)){c=r[a],c&&(r[a]=null),pe.event.triggered=p;try{r[p]()}catch(g){}pe.event.triggered=void 0,c&&(r[a]=c)}return t.result}},dispatch:function(e){e=pe.event.fix(e);var t,n,r,i,o,a=[],s=ie.call(arguments),u=(pe._data(this,"events")||{})[e.type]||[],l=pe.event.special[e.type]||{};if(s[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){for(a=pe.event.handlers.call(this,e,u),t=0;(i=a[t++])&&!e.isPropagationStopped();)for(e.currentTarget=i.elem,n=0;(o=i.handlers[n++])&&!e.isImmediatePropagationStopped();)e.rnamespace&&!e.rnamespace.test(o.namespace)||(e.handleObj=o,e.data=o.data,r=((pe.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s),void 0!==r&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()));return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,a=[],s=t.delegateCount,u=e.target;if(s&&u.nodeType&&("click"!==e.type||isNaN(e.button)||e.button<1))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(r=[],n=0;n-1:pe.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&a.push({elem:u,handlers:r})}return s]","i"),tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,nt=/\s*$/g,at=p(re),st=at.appendChild(re.createElement("div"));pe.extend({htmlPrefilter:function(e){return e.replace(tt,"<$1>")},clone:function(e,t,n){var r,i,o,a,s,u=pe.contains(e.ownerDocument,e);if(fe.html5Clone||pe.isXMLDoc(e)||!et.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(st.innerHTML=e.outerHTML,st.removeChild(o=st.firstChild)),!(fe.noCloneEvent&&fe.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||pe.isXMLDoc(e)))for(r=h(o),s=h(e),a=0;null!=(i=s[a]);++a)r[a]&&k(i,r[a]);if(t)if(n)for(s=s||h(e),r=r||h(o),a=0;null!=(i=s[a]);a++)N(i,r[a]);else N(e,o);return r=h(o,"script"),r.length>0&&g(r,!u&&h(e,"script")),r=s=i=null,o},cleanData:function(e,t){for(var n,r,i,o,a=0,s=pe.expando,u=pe.cache,l=fe.attributes,c=pe.event.special;null!=(n=e[a]);a++)if((t||He(n))&&(i=n[s],o=i&&u[i])){if(o.events)for(r in o.events)c[r]?pe.event.remove(n,r):pe.removeEvent(n,r,o.handle);u[i]&&(delete u[i],l||"undefined"==typeof n.removeAttribute?n[s]=void 0:n.removeAttribute(s),ne.push(i))}}}),pe.fn.extend({domManip:S,detach:function(e){return A(this,e,!0)},remove:function(e){return A(this,e)},text:function(e){return Pe(this,function(e){return void 0===e?pe.text(this):this.empty().append((this[0]&&this[0].ownerDocument||re).createTextNode(e))},null,e,arguments.length)},append:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.appendChild(e)}})},prepend:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&pe.cleanData(h(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&pe.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return pe.clone(this,e,t)})},html:function(e){return Pe(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e)return 1===t.nodeType?t.innerHTML.replace(Ze,""):void 0;if("string"==typeof e&&!nt.test(e)&&(fe.htmlSerialize||!et.test(e))&&(fe.leadingWhitespace||!$e.test(e))&&!Xe[(We.exec(e)||["",""])[1].toLowerCase()]){e=pe.htmlPrefilter(e);try{for(;nt",l.childNodes[0].style.borderCollapse="separate",t=l.getElementsByTagName("td"),t[0].style.cssText="margin:0;border:0;padding:0;display:none",o=0===t[0].offsetHeight,o&&(t[0].style.display="",t[1].style.display="none",o=0===t[0].offsetHeight)),f.removeChild(u)}var n,r,i,o,a,s,u=re.createElement("div"),l=re.createElement("div");l.style&&(l.style.cssText="float:left;opacity:.5",fe.opacity="0.5"===l.style.opacity,fe.cssFloat=!!l.style.cssFloat,l.style.backgroundClip="content-box",l.cloneNode(!0).style.backgroundClip="",fe.clearCloneStyle="content-box"===l.style.backgroundClip,u=re.createElement("div"),u.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",l.innerHTML="",u.appendChild(l),fe.boxSizing=""===l.style.boxSizing||""===l.style.MozBoxSizing||""===l.style.WebkitBoxSizing,pe.extend(fe,{reliableHiddenOffsets:function(){return null==n&&t(),o},boxSizingReliable:function(){return null==n&&t(),i},pixelMarginRight:function(){return null==n&&t(),r},pixelPosition:function(){return null==n&&t(),n},reliableMarginRight:function(){return null==n&&t(),a},reliableMarginLeft:function(){return null==n&&t(),s}}))}();var ht,gt,mt=/^(top|right|bottom|left)$/;e.getComputedStyle?(ht=function(t){var n=t.ownerDocument.defaultView;return n&&n.opener||(n=e),n.getComputedStyle(t)},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n.getPropertyValue(t)||n[t]:void 0,""!==a&&void 0!==a||pe.contains(e.ownerDocument,e)||(a=pe.style(e,t)),n&&!fe.pixelMarginRight()&&ft.test(a)&&ct.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o),void 0===a?a:a+""}):pt.currentStyle&&(ht=function(e){return e.currentStyle},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n[t]:void 0,null==a&&s&&s[t]&&(a=s[t]),ft.test(a)&&!mt.test(t)&&(r=s.left,i=e.runtimeStyle,o=i&&i.left,o&&(i.left=e.currentStyle.left),s.left="fontSize"===t?"1em":a,a=s.pixelLeft+"px",s.left=r,o&&(i.left=o)),void 0===a?a:a+""||"auto"});var yt=/alpha\([^)]*\)/i,vt=/opacity\s*=\s*([^)]*)/i,xt=/^(none|table(?!-c[ea]).+)/,bt=new RegExp("^("+Fe+")(.*)$","i"),wt={position:"absolute",visibility:"hidden",display:"block"},Tt={letterSpacing:"0",fontWeight:"400"},Ct=["Webkit","O","Moz","ms"],Et=re.createElement("div").style;pe.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=gt(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":fe.cssFloat?"cssFloat":"styleFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=pe.camelCase(t),u=e.style;if(t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:u[t];if(o=typeof n,"string"===o&&(i=Me.exec(n))&&i[1]&&(n=d(e,t,i),o="number"),null!=n&&n===n&&("number"===o&&(n+=i&&i[3]||(pe.cssNumber[s]?"":"px")),fe.clearCloneStyle||""!==n||0!==t.indexOf("background")||(u[t]="inherit"),!(a&&"set"in a&&void 0===(n=a.set(e,n,r)))))try{u[t]=n}catch(l){}}},css:function(e,t,n,r){var i,o,a,s=pe.camelCase(t);return t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],a&&"get"in a&&(o=a.get(e,!0,n)),void 0===o&&(o=gt(e,t,r)),"normal"===o&&t in Tt&&(o=Tt[t]),""===n||n?(i=parseFloat(o),n===!0||isFinite(i)?i||0:o):o}}),pe.each(["height","width"],function(e,t){pe.cssHooks[t]={get:function(e,n,r){if(n)return xt.test(pe.css(e,"display"))&&0===e.offsetWidth?dt(e,wt,function(){return M(e,t,r)}):M(e,t,r)},set:function(e,n,r){var i=r&&ht(e);return _(e,n,r?F(e,t,r,fe.boxSizing&&"border-box"===pe.css(e,"boxSizing",!1,i),i):0)}}}),fe.opacity||(pe.cssHooks.opacity={get:function(e,t){return vt.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=pe.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===pe.trim(o.replace(yt,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=yt.test(o)?o.replace(yt,i):o+" "+i)}}),pe.cssHooks.marginRight=L(fe.reliableMarginRight,function(e,t){if(t)return dt(e,{display:"inline-block"},gt,[e,"marginRight"])}),pe.cssHooks.marginLeft=L(fe.reliableMarginLeft,function(e,t){if(t)return(parseFloat(gt(e,"marginLeft"))||(pe.contains(e.ownerDocument,e)?e.getBoundingClientRect().left-dt(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}):0))+"px"}),pe.each({margin:"",padding:"",border:"Width"},function(e,t){pe.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+Oe[r]+t]=o[r]||o[r-2]||o[0];return i}},ct.test(e)||(pe.cssHooks[e+t].set=_)}),pe.fn.extend({css:function(e,t){return Pe(this,function(e,t,n){var r,i,o={},a=0;if(pe.isArray(t)){for(r=ht(e),i=t.length;a1)},show:function(){return q(this,!0)},hide:function(){return q(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){Re(this)?pe(this).show():pe(this).hide()})}}),pe.Tween=O,O.prototype={constructor:O,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||pe.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(pe.cssNumber[n]?"":"px")},cur:function(){var e=O.propHooks[this.prop];return e&&e.get?e.get(this):O.propHooks._default.get(this)},run:function(e){var t,n=O.propHooks[this.prop];return this.options.duration?this.pos=t=pe.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):O.propHooks._default.set(this),this}},O.prototype.init.prototype=O.prototype,O.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=pe.css(e.elem,e.prop,""),t&&"auto"!==t?t:0)},set:function(e){pe.fx.step[e.prop]?pe.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[pe.cssProps[e.prop]]&&!pe.cssHooks[e.prop]?e.elem[e.prop]=e.now:pe.style(e.elem,e.prop,e.now+e.unit)}}},O.propHooks.scrollTop=O.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},pe.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},pe.fx=O.prototype.init,pe.fx.step={};var Nt,kt,St=/^(?:toggle|show|hide)$/,At=/queueHooks$/;pe.Animation=pe.extend($,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return d(n.elem,e,Me.exec(t),n),n}]},tweener:function(e,t){pe.isFunction(e)?(t=e,e=["*"]):e=e.match(De);for(var n,r=0,i=e.length;r
                    a",e=n.getElementsByTagName("a")[0],t.setAttribute("type","checkbox"),n.appendChild(t),e=n.getElementsByTagName("a")[0],e.style.cssText="top:1px",fe.getSetAttribute="t"!==n.className,fe.style=/top/.test(e.getAttribute("style")),fe.hrefNormalized="/a"===e.getAttribute("href"),fe.checkOn=!!t.value,fe.optSelected=i.selected,fe.enctype=!!re.createElement("form").enctype,r.disabled=!0,fe.optDisabled=!i.disabled,t=re.createElement("input"),t.setAttribute("value",""),fe.input=""===t.getAttribute("value"),t.value="t",t.setAttribute("type","radio"),fe.radioValue="t"===t.value}();var Dt=/\r/g,jt=/[\x20\t\r\n\f]+/g;pe.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=pe.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,pe(this).val()):e,null==i?i="":"number"==typeof i?i+="":pe.isArray(i)&&(i=pe.map(i,function(e){return null==e?"":e+""})),t=pe.valHooks[this.type]||pe.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return t=pe.valHooks[i.type]||pe.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:(n=i.value,"string"==typeof n?n.replace(Dt,""):null==n?"":n)}}}),pe.extend({valHooks:{option:{get:function(e){var t=pe.find.attr(e,"value");return null!=t?t:pe.trim(pe.text(e)).replace(jt," ")}},select:{get:function(e){for(var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||i<0,a=o?null:[],s=o?i+1:r.length,u=i<0?s:o?i:0;u-1)try{r.selected=n=!0}catch(s){r.scrollHeight}else r.selected=!1;return n||(e.selectedIndex=-1),i}}}}),pe.each(["radio","checkbox"],function(){pe.valHooks[this]={set:function(e,t){if(pe.isArray(t))return e.checked=pe.inArray(pe(e).val(),t)>-1}},fe.checkOn||(pe.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Lt,Ht,qt=pe.expr.attrHandle,_t=/^(?:checked|selected)$/i,Ft=fe.getSetAttribute,Mt=fe.input;pe.fn.extend({attr:function(e,t){return Pe(this,pe.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){pe.removeAttr(this,e)})}}),pe.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?pe.prop(e,t,n):(1===o&&pe.isXMLDoc(e)||(t=t.toLowerCase(),i=pe.attrHooks[t]||(pe.expr.match.bool.test(t)?Ht:Lt)),void 0!==n?null===n?void pe.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:(r=pe.find.attr(e,t),null==r?void 0:r))},attrHooks:{type:{set:function(e,t){if(!fe.radioValue&&"radio"===t&&pe.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(De);if(o&&1===e.nodeType)for(;n=o[i++];)r=pe.propFix[n]||n,pe.expr.match.bool.test(n)?Mt&&Ft||!_t.test(n)?e[r]=!1:e[pe.camelCase("default-"+n)]=e[r]=!1:pe.attr(e,n,""),e.removeAttribute(Ft?n:r)}}),Ht={set:function(e,t,n){return t===!1?pe.removeAttr(e,n):Mt&&Ft||!_t.test(n)?e.setAttribute(!Ft&&pe.propFix[n]||n,n):e[pe.camelCase("default-"+n)]=e[n]=!0,n}},pe.each(pe.expr.match.bool.source.match(/\w+/g),function(e,t){var n=qt[t]||pe.find.attr;Mt&&Ft||!_t.test(t)?qt[t]=function(e,t,r){var i,o;return r||(o=qt[t],qt[t]=i,i=null!=n(e,t,r)?t.toLowerCase():null,qt[t]=o),i}:qt[t]=function(e,t,n){if(!n)return e[pe.camelCase("default-"+t)]?t.toLowerCase():null}}),Mt&&Ft||(pe.attrHooks.value={set:function(e,t,n){return pe.nodeName(e,"input")?void(e.defaultValue=t):Lt&&Lt.set(e,t,n)}}),Ft||(Lt={set:function(e,t,n){var r=e.getAttributeNode(n);if(r||e.setAttributeNode(r=e.ownerDocument.createAttribute(n)),r.value=t+="","value"===n||t===e.getAttribute(n))return t}},qt.id=qt.name=qt.coords=function(e,t,n){var r;if(!n)return(r=e.getAttributeNode(t))&&""!==r.value?r.value:null},pe.valHooks.button={get:function(e,t){var n=e.getAttributeNode(t);if(n&&n.specified)return n.value},set:Lt.set},pe.attrHooks.contenteditable={set:function(e,t,n){Lt.set(e,""!==t&&t,n)}},pe.each(["width","height"],function(e,t){pe.attrHooks[t]={set:function(e,n){if(""===n)return e.setAttribute(t,"auto"),n}}})),fe.style||(pe.attrHooks.style={get:function(e){return e.style.cssText||void 0},set:function(e,t){return e.style.cssText=t+""}});var Ot=/^(?:input|select|textarea|button|object)$/i,Rt=/^(?:a|area)$/i;pe.fn.extend({prop:function(e,t){return Pe(this,pe.prop,e,t,arguments.length>1)},removeProp:function(e){return e=pe.propFix[e]||e,this.each(function(){try{this[e]=void 0,delete this[e]}catch(t){}})}}),pe.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&pe.isXMLDoc(e)||(t=pe.propFix[t]||t,i=pe.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=pe.find.attr(e,"tabindex");return t?parseInt(t,10):Ot.test(e.nodeName)||Rt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),fe.hrefNormalized||pe.each(["href","src"],function(e,t){pe.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),fe.optSelected||(pe.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),pe.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){pe.propFix[this.toLowerCase()]=this}),fe.enctype||(pe.propFix.enctype="encoding");var Pt=/[\t\r\n\f]/g;pe.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).addClass(e.call(this,t,z(this)))});if("string"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(" "+i+" ").replace(Pt," ")){for(a=0;o=t[a++];)r.indexOf(" "+o+" ")<0&&(r+=o+" ");s=pe.trim(r),i!==s&&pe.attr(n,"class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).removeClass(e.call(this,t,z(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(" "+i+" ").replace(Pt," ")){for(a=0;o=t[a++];)for(;r.indexOf(" "+o+" ")>-1;)r=r.replace(" "+o+" "," ");s=pe.trim(r),i!==s&&pe.attr(n,"class",s)}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):pe.isFunction(e)?this.each(function(n){pe(this).toggleClass(e.call(this,n,z(this),t),t)}):this.each(function(){var t,r,i,o;if("string"===n)for(r=0,i=pe(this),o=e.match(De)||[];t=o[r++];)i.hasClass(t)?i.removeClass(t):i.addClass(t);else void 0!==e&&"boolean"!==n||(t=z(this),t&&pe._data(this,"__className__",t),pe.attr(this,"class",t||e===!1?"":pe._data(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;for(t=" "+e+" ";n=this[r++];)if(1===n.nodeType&&(" "+z(n)+" ").replace(Pt," ").indexOf(t)>-1)return!0;return!1}}),pe.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){pe.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),pe.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}});var Bt=e.location,Wt=pe.now(),It=/\?/,$t=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;pe.parseJSON=function(t){if(e.JSON&&e.JSON.parse)return e.JSON.parse(t+"");var n,r=null,i=pe.trim(t+"");return i&&!pe.trim(i.replace($t,function(e,t,i,o){return n&&t&&(r=0),0===r?e:(n=i||t,r+=!o-!i,"")}))?Function("return "+i)():pe.error("Invalid JSON: "+t)},pe.parseXML=function(t){var n,r;if(!t||"string"!=typeof t)return null;try{e.DOMParser?(r=new e.DOMParser,n=r.parseFromString(t,"text/xml")):(n=new e.ActiveXObject("Microsoft.XMLDOM"),n.async="false",n.loadXML(t))}catch(i){n=void 0}return n&&n.documentElement&&!n.getElementsByTagName("parsererror").length||pe.error("Invalid XML: "+t),n};var zt=/#.*$/,Xt=/([?&])_=[^&]*/,Ut=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Vt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Yt=/^(?:GET|HEAD)$/,Jt=/^\/\//,Gt=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Kt={},Qt={},Zt="*/".concat("*"),en=Bt.href,tn=Gt.exec(en.toLowerCase())||[];pe.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:en,type:"GET",isLocal:Vt.test(tn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Zt,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":pe.parseJSON,"text xml":pe.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?V(V(e,pe.ajaxSettings),t):V(pe.ajaxSettings,e)},ajaxPrefilter:X(Kt),ajaxTransport:X(Qt),ajax:function(t,n){function r(t,n,r,i){var o,f,v,x,w,C=n;2!==b&&(b=2,u&&e.clearTimeout(u),c=void 0,s=i||"",T.readyState=t>0?4:0,o=t>=200&&t<300||304===t,r&&(x=Y(d,T,r)),x=J(d,x,T,o),o?(d.ifModified&&(w=T.getResponseHeader("Last-Modified"),w&&(pe.lastModified[a]=w),w=T.getResponseHeader("etag"),w&&(pe.etag[a]=w)),204===t||"HEAD"===d.type?C="nocontent":304===t?C="notmodified":(C=x.state,f=x.data,v=x.error,o=!v)):(v=C,!t&&C||(C="error",t<0&&(t=0))),T.status=t,T.statusText=(n||C)+"",o?g.resolveWith(p,[f,C,T]):g.rejectWith(p,[T,C,v]),T.statusCode(y),y=void 0,l&&h.trigger(o?"ajaxSuccess":"ajaxError",[T,d,o?f:v]),m.fireWith(p,[T,C]),l&&(h.trigger("ajaxComplete",[T,d]),--pe.active||pe.event.trigger("ajaxStop")))}"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,d=pe.ajaxSetup({},n),p=d.context||d,h=d.context&&(p.nodeType||p.jquery)?pe(p):pe.event,g=pe.Deferred(),m=pe.Callbacks("once memory"),y=d.statusCode||{},v={},x={},b=0,w="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!f)for(f={};t=Ut.exec(s);)f[t[1].toLowerCase()]=t[2];t=f[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?s:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=x[n]=x[n]||e,v[e]=t),this},overrideMimeType:function(e){return b||(d.mimeType=e),this},statusCode:function(e){var t;if(e)if(b<2)for(t in e)y[t]=[y[t],e[t]];else T.always(e[T.status]);return this},abort:function(e){var t=e||w;return c&&c.abort(t),r(0,t),this}};if(g.promise(T).complete=m.add,T.success=T.done,T.error=T.fail,d.url=((t||d.url||en)+"").replace(zt,"").replace(Jt,tn[1]+"//"),d.type=n.method||n.type||d.method||d.type,d.dataTypes=pe.trim(d.dataType||"*").toLowerCase().match(De)||[""],null==d.crossDomain&&(i=Gt.exec(d.url.toLowerCase()),d.crossDomain=!(!i||i[1]===tn[1]&&i[2]===tn[2]&&(i[3]||("http:"===i[1]?"80":"443"))===(tn[3]||("http:"===tn[1]?"80":"443")))),d.data&&d.processData&&"string"!=typeof d.data&&(d.data=pe.param(d.data,d.traditional)),U(Kt,d,n,T),2===b)return T;l=pe.event&&d.global,l&&0===pe.active++&&pe.event.trigger("ajaxStart"),d.type=d.type.toUpperCase(),d.hasContent=!Yt.test(d.type),a=d.url,d.hasContent||(d.data&&(a=d.url+=(It.test(a)?"&":"?")+d.data,delete d.data),d.cache===!1&&(d.url=Xt.test(a)?a.replace(Xt,"$1_="+Wt++):a+(It.test(a)?"&":"?")+"_="+Wt++)),d.ifModified&&(pe.lastModified[a]&&T.setRequestHeader("If-Modified-Since",pe.lastModified[a]),pe.etag[a]&&T.setRequestHeader("If-None-Match",pe.etag[a])),(d.data&&d.hasContent&&d.contentType!==!1||n.contentType)&&T.setRequestHeader("Content-Type",d.contentType),T.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+("*"!==d.dataTypes[0]?", "+Zt+"; q=0.01":""):d.accepts["*"]);for(o in d.headers)T.setRequestHeader(o,d.headers[o]);if(d.beforeSend&&(d.beforeSend.call(p,T,d)===!1||2===b))return T.abort();w="abort";for(o in{success:1,error:1,complete:1})T[o](d[o]);if(c=U(Qt,d,n,T)){if(T.readyState=1,l&&h.trigger("ajaxSend",[T,d]),2===b)return T;d.async&&d.timeout>0&&(u=e.setTimeout(function(){T.abort("timeout")},d.timeout));try{b=1,c.send(v,r)}catch(C){if(!(b<2))throw C;r(-1,C)}}else r(-1,"No Transport");return T},getJSON:function(e,t,n){return pe.get(e,t,n,"json")},getScript:function(e,t){return pe.get(e,void 0,t,"script")}}),pe.each(["get","post"],function(e,t){pe[t]=function(e,n,r,i){return pe.isFunction(n)&&(i=i||r,r=n,n=void 0),pe.ajax(pe.extend({url:e,type:t,dataType:i,data:n,success:r},pe.isPlainObject(e)&&e))}}),pe._evalUrl=function(e){return pe.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},pe.fn.extend({wrapAll:function(e){if(pe.isFunction(e))return this.each(function(t){pe(this).wrapAll(e.call(this,t))});if(this[0]){var t=pe(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstChild&&1===e.firstChild.nodeType;)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return pe.isFunction(e)?this.each(function(t){pe(this).wrapInner(e.call(this,t))}):this.each(function(){var t=pe(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=pe.isFunction(e);return this.each(function(n){pe(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){pe.nodeName(this,"body")||pe(this).replaceWith(this.childNodes)}).end()}}),pe.expr.filters.hidden=function(e){return fe.reliableHiddenOffsets()?e.offsetWidth<=0&&e.offsetHeight<=0&&!e.getClientRects().length:K(e)},pe.expr.filters.visible=function(e){return!pe.expr.filters.hidden(e)};var nn=/%20/g,rn=/\[\]$/,on=/\r?\n/g,an=/^(?:submit|button|image|reset|file)$/i,sn=/^(?:input|select|textarea|keygen)/i;pe.param=function(e,t){var n,r=[],i=function(e,t){t=pe.isFunction(t)?t():null==t?"":t,r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(void 0===t&&(t=pe.ajaxSettings&&pe.ajaxSettings.traditional),pe.isArray(e)||e.jquery&&!pe.isPlainObject(e))pe.each(e,function(){i(this.name,this.value)});else for(n in e)Q(n,e[n],t,i);return r.join("&").replace(nn,"+")},pe.fn.extend({serialize:function(){return pe.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=pe.prop(this,"elements");return e?pe.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!pe(this).is(":disabled")&&sn.test(this.nodeName)&&!an.test(e)&&(this.checked||!Be.test(e))}).map(function(e,t){var n=pe(this).val();return null==n?null:pe.isArray(n)?pe.map(n,function(e){return{name:t.name,value:e.replace(on,"\r\n")}}):{name:t.name,value:n.replace(on,"\r\n")}}).get()}}),pe.ajaxSettings.xhr=void 0!==e.ActiveXObject?function(){return this.isLocal?ee():re.documentMode>8?Z():/^(get|post|head|put|delete|options)$/i.test(this.type)&&Z()||ee()}:Z;var un=0,ln={},cn=pe.ajaxSettings.xhr();e.attachEvent&&e.attachEvent("onunload",function(){for(var e in ln)ln[e](void 0,!0)}),fe.cors=!!cn&&"withCredentials"in cn,cn=fe.ajax=!!cn,cn&&pe.ajaxTransport(function(t){if(!t.crossDomain||fe.cors){var n;return{send:function(r,i){var o,a=t.xhr(),s=++un;if(a.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(o in t.xhrFields)a[o]=t.xhrFields[o];t.mimeType&&a.overrideMimeType&&a.overrideMimeType(t.mimeType),t.crossDomain||r["X-Requested-With"]||(r["X-Requested-With"]="XMLHttpRequest");for(o in r)void 0!==r[o]&&a.setRequestHeader(o,r[o]+"");a.send(t.hasContent&&t.data||null),n=function(e,r){var o,u,l;if(n&&(r||4===a.readyState))if(delete ln[s],n=void 0,a.onreadystatechange=pe.noop,r)4!==a.readyState&&a.abort();else{l={},o=a.status,"string"==typeof a.responseText&&(l.text=a.responseText);try{u=a.statusText}catch(c){u=""}o||!t.isLocal||t.crossDomain?1223===o&&(o=204):o=l.text?200:404}l&&i(o,u,l,a.getAllResponseHeaders())},t.async?4===a.readyState?e.setTimeout(n):a.onreadystatechange=ln[s]=n:n()},abort:function(){n&&n(void 0,!0)}}}}),pe.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return pe.globalEval(e),e}}}),pe.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),pe.ajaxTransport("script",function(e){if(e.crossDomain){var t,n=re.head||pe("head")[0]||re.documentElement;return{send:function(r,i){t=re.createElement("script"),t.async=!0,e.scriptCharset&&(t.charset=e.scriptCharset),t.src=e.url,t.onload=t.onreadystatechange=function(e,n){(n||!t.readyState||/loaded|complete/.test(t.readyState))&&(t.onload=t.onreadystatechange=null,t.parentNode&&t.parentNode.removeChild(t),t=null,n||i(200,"success"))},n.insertBefore(t,n.firstChild)},abort:function(){t&&t.onload(void 0,!0)}}}});var fn=[],dn=/(=)\?(?=&|$)|\?\?/;pe.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=fn.pop()||pe.expando+"_"+Wt++;return this[e]=!0,e}}),pe.ajaxPrefilter("json jsonp",function(t,n,r){var i,o,a,s=t.jsonp!==!1&&(dn.test(t.url)?"url":"string"==typeof t.data&&0===(t.contentType||"").indexOf("application/x-www-form-urlencoded")&&dn.test(t.data)&&"data");if(s||"jsonp"===t.dataTypes[0])return i=t.jsonpCallback=pe.isFunction(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(dn,"$1"+i):t.jsonp!==!1&&(t.url+=(It.test(t.url)?"&":"?")+t.jsonp+"="+i),t.converters["script json"]=function(){return a||pe.error(i+" was not called"),a[0]},t.dataTypes[0]="json",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?pe(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,fn.push(i)),a&&pe.isFunction(o)&&o(a[0]),a=o=void 0}),"script"}),pe.parseHTML=function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||re;var r=Te.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=y([e],t,i),i&&i.length&&pe(i).remove(),pe.merge([],r.childNodes))};var pn=pe.fn.load;return pe.fn.load=function(e,t,n){if("string"!=typeof e&&pn)return pn.apply(this,arguments);var r,i,o,a=this,s=e.indexOf(" ");return s>-1&&(r=pe.trim(e.slice(s,e.length)),e=e.slice(0,s)),pe.isFunction(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),a.length>0&&pe.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?pe("
                    ").append(pe.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},pe.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){pe.fn[t]=function(e){return this.on(t,e)}}),pe.expr.filters.animated=function(e){return pe.grep(pe.timers,function(t){return e===t.elem}).length},pe.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l,c=pe.css(e,"position"),f=pe(e),d={};"static"===c&&(e.style.position="relative"),s=f.offset(),o=pe.css(e,"top"),u=pe.css(e,"left"),l=("absolute"===c||"fixed"===c)&&pe.inArray("auto",[o,u])>-1,l?(r=f.position(),a=r.top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),pe.isFunction(t)&&(t=t.call(e,n,pe.extend({},s))),null!=t.top&&(d.top=t.top-s.top+a),null!=t.left&&(d.left=t.left-s.left+i),"using"in t?t.using.call(e,d):f.css(d)}},pe.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){pe.offset.setOffset(this,e,t)});var t,n,r={top:0,left:0},i=this[0],o=i&&i.ownerDocument;if(o)return t=o.documentElement,pe.contains(t,i)?("undefined"!=typeof i.getBoundingClientRect&&(r=i.getBoundingClientRect()),n=te(o),{top:r.top+(n.pageYOffset||t.scrollTop)-(t.clientTop||0),left:r.left+(n.pageXOffset||t.scrollLeft)-(t.clientLeft||0)}):r},position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===pe.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),pe.nodeName(e[0],"html")||(n=e.offset()),n.top+=pe.css(e[0],"borderTopWidth",!0),n.left+=pe.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-pe.css(r,"marginTop",!0),left:t.left-n.left-pe.css(r,"marginLeft",!0)}}},offsetParent:function(){ +return this.map(function(){for(var e=this.offsetParent;e&&!pe.nodeName(e,"html")&&"static"===pe.css(e,"position");)e=e.offsetParent;return e||pt})}}),pe.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,t){var n=/Y/.test(t);pe.fn[e]=function(r){return Pe(this,function(e,r,i){var o=te(e);return void 0===i?o?t in o?o[t]:o.document.documentElement[r]:e[r]:void(o?o.scrollTo(n?pe(o).scrollLeft():i,n?i:pe(o).scrollTop()):e[r]=i)},e,r,arguments.length,null)}}),pe.each(["top","left"],function(e,t){pe.cssHooks[t]=L(fe.pixelPosition,function(e,n){if(n)return n=gt(e,t),ft.test(n)?pe(e).position()[t]+"px":n})}),pe.each({Height:"height",Width:"width"},function(e,t){pe.each({padding:"inner"+e,content:t,"":"outer"+e},function(n,r){pe.fn[r]=function(r,i){var o=arguments.length&&(n||"boolean"!=typeof r),a=n||(r===!0||i===!0?"margin":"border");return Pe(this,function(t,n,r){var i;return pe.isWindow(t)?t.document.documentElement["client"+e]:9===t.nodeType?(i=t.documentElement,Math.max(t.body["scroll"+e],i["scroll"+e],t.body["offset"+e],i["offset"+e],i["client"+e])):void 0===r?pe.css(t,n,a):pe.style(t,n,r,a)},t,o?r:void 0,o,null)}})}),pe.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),pe.fn.size=function(){return this.length},pe.fn.andSelf=pe.fn.addBack,layui.define(function(e){layui.$=pe,e("jquery",pe)}),pe});!function(e,t){"use strict";var i,n,a=e.layui&&layui.define,o={getPath:function(){var t=document.currentScript?document.currentScript.src:function(){for(var e,t=document.scripts,i=t.length-1,n=i;n>0;n--)if("interactive"===t[n].readyState){e=t[n].src;break}return e||t[i].src}(),i=e.LAYUI_GLOBAL||{};return i.layer_dir||t.substring(0,t.lastIndexOf("/")+1)}(),config:{},end:{},minIndex:0,minLeft:[],btn:["确定","取消"],type:["dialog","page","iframe","loading","tips"],getStyle:function(t,i){var n=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return n[n.getPropertyValue?"getPropertyValue":"getAttribute"](i)},link:function(t,i,n){if(r.path){var a=document.getElementsByTagName("head")[0],s=document.createElement("link");"string"==typeof i&&(n=i);var l=(n||t).replace(/\.|\//g,""),f="layuicss-"+l,c="creating",u=0;s.rel="stylesheet",s.href=r.path+t,s.id=f,document.getElementById(f)||a.appendChild(s),"function"==typeof i&&!function d(t){var n=100,a=document.getElementById(f);return++u>1e4/n?e.console&&console.error(l+".css: Invalid"):void(1989===parseInt(o.getStyle(a,"width"))?(t===c&&a.removeAttribute("lay-status"),a.getAttribute("lay-status")===c?setTimeout(d,n):i()):(a.setAttribute("lay-status",c),setTimeout(function(){d(c)},n)))}()}}},r={v:"3.5.1",ie:function(){var t=navigator.userAgent.toLowerCase();return!!(e.ActiveXObject||"ActiveXObject"in e)&&((t.match(/msie\s(\d+)/)||[])[1]||"11")}(),index:e.layer&&e.layer.v?1e5:0,path:o.getPath,config:function(e,t){return e=e||{},r.cache=o.config=i.extend({},o.config,e),r.path=o.config.path||r.path,"string"==typeof e.extend&&(e.extend=[e.extend]),o.config.path&&r.ready(),e.extend?(a?layui.addcss("modules/layer/"+e.extend):o.link("theme/"+e.extend),this):this},ready:function(e){var t="layer",i="",n=(a?"modules/layer/":"theme/")+"default/layer.css?v="+r.v+i;return a?layui.addcss(n,e,t):o.link(n,e,t),this},alert:function(e,t,n){var a="function"==typeof t;return a&&(n=t),r.open(i.extend({content:e,yes:n},a?{}:t))},confirm:function(e,t,n,a){var s="function"==typeof t;return s&&(a=n,n=t),r.open(i.extend({content:e,btn:o.btn,yes:n,btn2:a},s?{}:t))},msg:function(e,n,a){var s="function"==typeof n,f=o.config.skin,c=(f?f+" "+f+"-msg":"")||"layui-layer-msg",u=l.anim.length-1;return s&&(a=n),r.open(i.extend({content:e,time:3e3,shade:!1,skin:c,title:!1,closeBtn:!1,btn:!1,resize:!1,end:a},s&&!o.config.skin?{skin:c+" layui-layer-hui",anim:u}:function(){return n=n||{},(n.icon===-1||n.icon===t&&!o.config.skin)&&(n.skin=c+" "+(n.skin||"layui-layer-hui")),n}()))},load:function(e,t){return r.open(i.extend({type:3,icon:e||0,resize:!1,shade:.01},t))},tips:function(e,t,n){return r.open(i.extend({type:4,content:[e,t],closeBtn:!1,time:3e3,shade:!1,resize:!1,fixed:!1,maxWidth:260},n))}},s=function(e){var t=this,a=function(){t.creat()};t.index=++r.index,t.config.maxWidth=i(n).width()-30,t.config=i.extend({},t.config,o.config,e),document.body?a():setTimeout(function(){a()},30)};s.pt=s.prototype;var l=["layui-layer",".layui-layer-title",".layui-layer-main",".layui-layer-dialog","layui-layer-iframe","layui-layer-content","layui-layer-btn","layui-layer-close"];l.anim=["layer-anim-00","layer-anim-01","layer-anim-02","layer-anim-03","layer-anim-04","layer-anim-05","layer-anim-06"],l.SHADE="layui-layer-shade",l.MOVE="layui-layer-move",s.pt.config={type:0,shade:.3,fixed:!0,move:l[1],title:"信息",offset:"auto",area:"auto",closeBtn:1,time:0,zIndex:19891014,maxWidth:360,anim:0,isOutAnim:!0,minStack:!0,icon:-1,moveType:1,resize:!0,scrollbar:!0,tips:2},s.pt.vessel=function(e,t){var n=this,a=n.index,r=n.config,s=r.zIndex+a,f="object"==typeof r.title,c=r.maxmin&&(1===r.type||2===r.type),u=r.title?'
                    '+(f?r.title[0]:r.title)+"
                    ":"";return r.zIndex=s,t([r.shade?'
                    ':"",'
                    '+(e&&2!=r.type?"":u)+'
                    '+(0==r.type&&r.icon!==-1?'':"")+(1==r.type&&e?"":r.content||"")+'
                    '+function(){var e=c?'':"";return r.closeBtn&&(e+=''),e}()+""+(r.btn?function(){var e="";"string"==typeof r.btn&&(r.btn=[r.btn]);for(var t=0,i=r.btn.length;t'+r.btn[t]+"";return'
                    '+e+"
                    "}():"")+(r.resize?'':"")+"
                    "],u,i('
                    ')),n},s.pt.creat=function(){var e=this,t=e.config,a=e.index,s=t.content,f="object"==typeof s,c=i("body");if(!t.id||!i("#"+t.id)[0]){switch("string"==typeof t.area&&(t.area="auto"===t.area?["",""]:[t.area,""]),t.shift&&(t.anim=t.shift),6==r.ie&&(t.fixed=!1),t.type){case 0:t.btn="btn"in t?t.btn:o.btn[0],r.closeAll("dialog");break;case 2:var s=t.content=f?t.content:[t.content||"","auto"];t.content='';break;case 3:delete t.title,delete t.closeBtn,t.icon===-1&&0===t.icon,r.closeAll("loading");break;case 4:f||(t.content=[t.content,"body"]),t.follow=t.content[1],t.content=t.content[0]+'',delete t.title,t.tips="object"==typeof t.tips?t.tips:[t.tips,!0],t.tipsMore||r.closeAll("tips")}if(e.vessel(f,function(n,r,u){c.append(n[0]),f?function(){2==t.type||4==t.type?function(){i("body").append(n[1])}():function(){s.parents("."+l[0])[0]||(s.data("display",s.css("display")).show().addClass("layui-layer-wrap").wrap(n[1]),i("#"+l[0]+a).find("."+l[5]).before(r))}()}():c.append(n[1]),i("#"+l.MOVE)[0]||c.append(o.moveElem=u),e.layero=i("#"+l[0]+a),e.shadeo=i("#"+l.SHADE+a),t.scrollbar||l.html.css("overflow","hidden").attr("layer-full",a)}).auto(a),e.shadeo.css({"background-color":t.shade[1]||"#000",opacity:t.shade[0]||t.shade}),2==t.type&&6==r.ie&&e.layero.find("iframe").attr("src",s[0]),4==t.type?e.tips():function(){e.offset(),parseInt(o.getStyle(document.getElementById(l.MOVE),"z-index"))||function(){e.layero.css("visibility","hidden"),r.ready(function(){e.offset(),e.layero.css("visibility","visible")})}()}(),t.fixed&&n.on("resize",function(){e.offset(),(/^\d+%$/.test(t.area[0])||/^\d+%$/.test(t.area[1]))&&e.auto(a),4==t.type&&e.tips()}),t.time<=0||setTimeout(function(){r.close(e.index)},t.time),e.move().callback(),l.anim[t.anim]){var u="layer-anim "+l.anim[t.anim];e.layero.addClass(u).one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend",function(){i(this).removeClass(u)})}t.isOutAnim&&e.layero.data("isOutAnim",!0)}},s.pt.auto=function(e){var t=this,a=t.config,o=i("#"+l[0]+e);""===a.area[0]&&a.maxWidth>0&&(r.ie&&r.ie<8&&a.btn&&o.width(o.innerWidth()),o.outerWidth()>a.maxWidth&&o.width(a.maxWidth));var s=[o.innerWidth(),o.innerHeight()],f=o.find(l[1]).outerHeight()||0,c=o.find("."+l[6]).outerHeight()||0,u=function(e){e=o.find(e),e.height(s[1]-f-c-2*(0|parseFloat(e.css("padding-top"))))};switch(a.type){case 2:u("iframe");break;default:""===a.area[1]?a.maxHeight>0&&o.outerHeight()>a.maxHeight?(s[1]=a.maxHeight,u("."+l[5])):a.fixed&&s[1]>=n.height()&&(s[1]=n.height(),u("."+l[5])):u("."+l[5])}return t},s.pt.offset=function(){var e=this,t=e.config,i=e.layero,a=[i.outerWidth(),i.outerHeight()],o="object"==typeof t.offset;e.offsetTop=(n.height()-a[1])/2,e.offsetLeft=(n.width()-a[0])/2,o?(e.offsetTop=t.offset[0],e.offsetLeft=t.offset[1]||e.offsetLeft):"auto"!==t.offset&&("t"===t.offset?e.offsetTop=0:"r"===t.offset?e.offsetLeft=n.width()-a[0]:"b"===t.offset?e.offsetTop=n.height()-a[1]:"l"===t.offset?e.offsetLeft=0:"lt"===t.offset?(e.offsetTop=0,e.offsetLeft=0):"lb"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=0):"rt"===t.offset?(e.offsetTop=0,e.offsetLeft=n.width()-a[0]):"rb"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=n.width()-a[0]):e.offsetTop=t.offset),t.fixed||(e.offsetTop=/%$/.test(e.offsetTop)?n.height()*parseFloat(e.offsetTop)/100:parseFloat(e.offsetTop),e.offsetLeft=/%$/.test(e.offsetLeft)?n.width()*parseFloat(e.offsetLeft)/100:parseFloat(e.offsetLeft),e.offsetTop+=n.scrollTop(),e.offsetLeft+=n.scrollLeft()),i.attr("minLeft")&&(e.offsetTop=n.height()-(i.find(l[1]).outerHeight()||0),e.offsetLeft=i.css("left")),i.css({top:e.offsetTop,left:e.offsetLeft})},s.pt.tips=function(){var e=this,t=e.config,a=e.layero,o=[a.outerWidth(),a.outerHeight()],r=i(t.follow);r[0]||(r=i("body"));var s={width:r.outerWidth(),height:r.outerHeight(),top:r.offset().top,left:r.offset().left},f=a.find(".layui-layer-TipsG"),c=t.tips[0];t.tips[1]||f.remove(),s.autoLeft=function(){s.left+o[0]-n.width()>0?(s.tipLeft=s.left+s.width-o[0],f.css({right:12,left:"auto"})):s.tipLeft=s.left},s.where=[function(){s.autoLeft(),s.tipTop=s.top-o[1]-10,f.removeClass("layui-layer-TipsB").addClass("layui-layer-TipsT").css("border-right-color",t.tips[1])},function(){s.tipLeft=s.left+s.width+10,s.tipTop=s.top,f.removeClass("layui-layer-TipsL").addClass("layui-layer-TipsR").css("border-bottom-color",t.tips[1])},function(){s.autoLeft(),s.tipTop=s.top+s.height+10,f.removeClass("layui-layer-TipsT").addClass("layui-layer-TipsB").css("border-right-color",t.tips[1])},function(){s.tipLeft=s.left-o[0]-10,s.tipTop=s.top,f.removeClass("layui-layer-TipsR").addClass("layui-layer-TipsL").css("border-bottom-color",t.tips[1])}],s.where[c-1](),1===c?s.top-(n.scrollTop()+o[1]+16)<0&&s.where[2]():2===c?n.width()-(s.left+s.width+o[0]+16)>0||s.where[3]():3===c?s.top-n.scrollTop()+s.height+o[1]+16-n.height()>0&&s.where[0]():4===c&&o[0]+16-s.left>0&&s.where[1](),a.find("."+l[5]).css({"background-color":t.tips[1],"padding-right":t.closeBtn?"30px":""}),a.css({left:s.tipLeft-(t.fixed?n.scrollLeft():0),top:s.tipTop-(t.fixed?n.scrollTop():0)})},s.pt.move=function(){var e=this,t=e.config,a=i(document),s=e.layero,l=s.find(t.move),f=s.find(".layui-layer-resize"),c={};return t.move&&l.css("cursor","move"),l.on("mousedown",function(e){e.preventDefault(),t.move&&(c.moveStart=!0,c.offset=[e.clientX-parseFloat(s.css("left")),e.clientY-parseFloat(s.css("top"))],o.moveElem.css("cursor","move").show())}),f.on("mousedown",function(e){e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],c.area=[s.outerWidth(),s.outerHeight()],o.moveElem.css("cursor","se-resize").show()}),a.on("mousemove",function(i){if(c.moveStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1],l="fixed"===s.css("position");if(i.preventDefault(),c.stX=l?0:n.scrollLeft(),c.stY=l?0:n.scrollTop(),!t.moveOut){var f=n.width()-s.outerWidth()+c.stX,u=n.height()-s.outerHeight()+c.stY;af&&(a=f),ou&&(o=u)}s.css({left:a,top:o})}if(t.resize&&c.resizeStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1];i.preventDefault(),r.style(e.index,{width:c.area[0]+a,height:c.area[1]+o}),c.isResize=!0,t.resizing&&t.resizing(s)}}).on("mouseup",function(e){c.moveStart&&(delete c.moveStart,o.moveElem.hide(),t.moveEnd&&t.moveEnd(s)),c.resizeStart&&(delete c.resizeStart,o.moveElem.hide())}),e},s.pt.callback=function(){function e(){var e=a.cancel&&a.cancel(t.index,n);e===!1||r.close(t.index)}var t=this,n=t.layero,a=t.config;t.openLayer(),a.success&&(2==a.type?n.find("iframe").on("load",function(){a.success(n,t.index,t)}):a.success(n,t.index,t)),6==r.ie&&t.IE6(n),n.find("."+l[6]).children("a").on("click",function(){var e=i(this).index();if(0===e)a.yes?a.yes(t.index,n):a.btn1?a.btn1(t.index,n):r.close(t.index);else{var o=a["btn"+(e+1)]&&a["btn"+(e+1)](t.index,n);o===!1||r.close(t.index)}}),n.find("."+l[7]).on("click",e),a.shadeClose&&t.shadeo.on("click",function(){r.close(t.index)}),n.find(".layui-layer-min").on("click",function(){var e=a.min&&a.min(n,t.index);e===!1||r.min(t.index,a)}),n.find(".layui-layer-max").on("click",function(){i(this).hasClass("layui-layer-maxmin")?(r.restore(t.index),a.restore&&a.restore(n,t.index)):(r.full(t.index,a),setTimeout(function(){a.full&&a.full(n,t.index)},100))}),a.end&&(o.end[t.index]=a.end)},o.reselect=function(){i.each(i("select"),function(e,t){var n=i(this);n.parents("."+l[0])[0]||1==n.attr("layer")&&i("."+l[0]).length<1&&n.removeAttr("layer").show(),n=null})},s.pt.IE6=function(e){i("select").each(function(e,t){var n=i(this);n.parents("."+l[0])[0]||"none"===n.css("display")||n.attr({layer:"1"}).hide(),n=null})},s.pt.openLayer=function(){var e=this;r.zIndex=e.config.zIndex,r.setTop=function(e){var t=function(){r.zIndex++,e.css("z-index",r.zIndex+1)};return r.zIndex=parseInt(e[0].style.zIndex),e.on("mousedown",t),r.zIndex}},o.record=function(e){var t=[e.width(),e.height(),e.position().top,e.position().left+parseFloat(e.css("margin-left"))];e.find(".layui-layer-max").addClass("layui-layer-maxmin"),e.attr({area:t})},o.rescollbar=function(e){l.html.attr("layer-full")==e&&(l.html[0].style.removeProperty?l.html[0].style.removeProperty("overflow"):l.html[0].style.removeAttribute("overflow"),l.html.removeAttr("layer-full"))},e.layer=r,r.getChildFrame=function(e,t){return t=t||i("."+l[4]).attr("times"),i("#"+l[0]+t).find("iframe").contents().find(e)},r.getFrameIndex=function(e){return i("#"+e).parents("."+l[4]).attr("times")},r.iframeAuto=function(e){if(e){var t=r.getChildFrame("html",e).outerHeight(),n=i("#"+l[0]+e),a=n.find(l[1]).outerHeight()||0,o=n.find("."+l[6]).outerHeight()||0;n.css({height:t+a+o}),n.find("iframe").css({height:t})}},r.iframeSrc=function(e,t){i("#"+l[0]+e).find("iframe").attr("src",t)},r.style=function(e,t,n){var a=i("#"+l[0]+e),r=a.find(".layui-layer-content"),s=a.attr("type"),f=a.find(l[1]).outerHeight()||0,c=a.find("."+l[6]).outerHeight()||0;a.attr("minLeft");s!==o.type[3]&&s!==o.type[4]&&(n||(parseFloat(t.width)<=260&&(t.width=260),parseFloat(t.height)-f-c<=64&&(t.height=64+f+c)),a.css(t),c=a.find("."+l[6]).outerHeight(),s===o.type[2]?a.find("iframe").css({height:parseFloat(t.height)-f-c}):r.css({height:parseFloat(t.height)-f-c-parseFloat(r.css("padding-top"))-parseFloat(r.css("padding-bottom"))}))},r.min=function(e,t){t=t||{};var a=i("#"+l[0]+e),s=i("#"+l.SHADE+e),f=a.find(l[1]).outerHeight()||0,c=a.attr("minLeft")||181*o.minIndex+"px",u=a.css("position"),d={width:180,height:f,position:"fixed",overflow:"hidden"};o.record(a),o.minLeft[0]&&(c=o.minLeft[0],o.minLeft.shift()),t.minStack&&(d.left=c,d.top=n.height()-f,a.attr("minLeft")||o.minIndex++,a.attr("minLeft",c)),a.attr("position",u),r.style(e,d,!0),a.find(".layui-layer-min").hide(),"page"===a.attr("type")&&a.find(l[4]).hide(),o.rescollbar(e),s.hide()},r.restore=function(e){var t=i("#"+l[0]+e),n=i("#"+l.SHADE+e),a=t.attr("area").split(",");t.attr("type");r.style(e,{width:parseFloat(a[0]),height:parseFloat(a[1]),top:parseFloat(a[2]),left:parseFloat(a[3]),position:t.attr("position"),overflow:"visible"},!0),t.find(".layui-layer-max").removeClass("layui-layer-maxmin"),t.find(".layui-layer-min").show(),"page"===t.attr("type")&&t.find(l[4]).show(),o.rescollbar(e),n.show()},r.full=function(e){var t,a=i("#"+l[0]+e);o.record(a),l.html.attr("layer-full")||l.html.css("overflow","hidden").attr("layer-full",e),clearTimeout(t),t=setTimeout(function(){var t="fixed"===a.css("position");r.style(e,{top:t?0:n.scrollTop(),left:t?0:n.scrollLeft(),width:n.width(),height:n.height()},!0),a.find(".layui-layer-min").hide()},100)},r.title=function(e,t){var n=i("#"+l[0]+(t||r.index)).find(l[1]);n.html(e)},r.close=function(e,t){var n=i("#"+l[0]+e),a=n.attr("type"),s="layer-anim-close";if(n[0]){var f="layui-layer-wrap",c=function(){if(a===o.type[1]&&"object"===n.attr("conType")){n.children(":not(."+l[5]+")").remove();for(var r=n.find("."+f),s=0;s<2;s++)r.unwrap();r.css("display",r.data("display")).removeClass(f)}else{if(a===o.type[2])try{var c=i("#"+l[4]+e)[0];c.contentWindow.document.write(""),c.contentWindow.close(),n.find("."+l[5])[0].removeChild(c)}catch(u){}n[0].innerHTML="",n.remove()}"function"==typeof o.end[e]&&o.end[e](),delete o.end[e],"function"==typeof t&&t()};n.data("isOutAnim")&&n.addClass("layer-anim "+s),i("#layui-layer-moves, #"+l.SHADE+e).remove(),6==r.ie&&o.reselect(),o.rescollbar(e),n.attr("minLeft")&&(o.minIndex--,o.minLeft.push(n.attr("minLeft"))),r.ie&&r.ie<10||!n.data("isOutAnim")?c():setTimeout(function(){c()},200)}},r.closeAll=function(e,t){"function"==typeof e&&(t=e,e=null);var n=i("."+l[0]);i.each(n,function(a){var o=i(this),s=e?o.attr("type")===e:1;s&&r.close(o.attr("times"),a===n.length-1?t:null),s=null}),0===n.length&&"function"==typeof t&&t()};var f=r.cache||{},c=function(e){return f.skin?" "+f.skin+" "+f.skin+"-"+e:""};r.prompt=function(e,t){var a="";if(e=e||{},"function"==typeof e&&(t=e),e.area){var o=e.area;a='style="width: '+o[0]+"; height: "+o[1]+';"',delete e.area}var s,l=2==e.formType?'":function(){return''}(),f=e.success;return delete e.success,r.open(i.extend({type:1,btn:["确定","取消"],content:l,skin:"layui-layer-prompt"+c("prompt"),maxWidth:n.width(),success:function(t){s=t.find(".layui-layer-input"),s.val(e.value||"").focus(),"function"==typeof f&&f(t)},resize:!1,yes:function(i){var n=s.val();""===n?s.focus():n.length>(e.maxlength||500)?r.tips("最多输入"+(e.maxlength||500)+"个字数",s,{tips:1}):t&&t(n,i,s)}},e))},r.tab=function(e){e=e||{};var t=e.tab||{},n="layui-this",a=e.success;return delete e.success,r.open(i.extend({type:1,skin:"layui-layer-tab"+c("tab"),resize:!1,title:function(){var e=t.length,i=1,a="";if(e>0)for(a=''+t[0].title+"";i"+t[i].title+"";return a}(),content:'
                      '+function(){var e=t.length,i=1,a="";if(e>0)for(a='
                    • '+(t[0].content||"no content")+"
                    • ";i'+(t[i].content||"no content")+"";return a}()+"
                    ",success:function(t){var o=t.find(".layui-layer-title").children(),r=t.find(".layui-layer-tabmain").children();o.on("mousedown",function(t){t.stopPropagation?t.stopPropagation():t.cancelBubble=!0;var a=i(this),o=a.index();a.addClass(n).siblings().removeClass(n),r.eq(o).show().siblings().hide(),"function"==typeof e.change&&e.change(o)}),"function"==typeof a&&a(t)}},e))},r.photos=function(t,n,a){function o(e,t,i){var n=new Image;return n.src=e,n.complete?t(n):(n.onload=function(){n.onload=null,t(n)},void(n.onerror=function(e){n.onerror=null,i(e)}))}var s={};if(t=t||{},t.photos){var l=!("string"==typeof t.photos||t.photos instanceof i),f=l?t.photos:{},u=f.data||[],d=f.start||0;s.imgIndex=(0|d)+1,t.img=t.img||"img";var y=t.success;if(delete t.success,l){if(0===u.length)return r.msg("没有图片")}else{var p=i(t.photos),h=function(){u=[],p.find(t.img).each(function(e){var t=i(this);t.attr("layer-index",e),u.push({alt:t.attr("alt"),pid:t.attr("layer-pid"),src:t.attr("layer-src")||t.attr("src"),thumb:t.attr("src")})})};if(h(),0===u.length)return;if(n||p.on("click",t.img,function(){h();var e=i(this),n=e.attr("layer-index");r.photos(i.extend(t,{photos:{start:n,data:u,tab:t.tab},full:t.full}),!0)}),!n)return}s.imgprev=function(e){s.imgIndex--,s.imgIndex<1&&(s.imgIndex=u.length),s.tabimg(e)},s.imgnext=function(e,t){s.imgIndex++,s.imgIndex>u.length&&(s.imgIndex=1,t)||s.tabimg(e)},s.keyup=function(e){if(!s.end){var t=e.keyCode;e.preventDefault(),37===t?s.imgprev(!0):39===t?s.imgnext(!0):27===t&&r.close(s.index)}},s.tabimg=function(e){if(!(u.length<=1))return f.start=s.imgIndex-1,r.close(s.index),r.photos(t,!0,e)},s.event=function(){s.bigimg.find(".layui-layer-imgprev").on("click",function(e){e.preventDefault(),s.imgprev(!0)}),s.bigimg.find(".layui-layer-imgnext").on("click",function(e){e.preventDefault(),s.imgnext(!0)}),i(document).on("keyup",s.keyup)},s.loadi=r.load(1,{shade:!("shade"in t)&&.9,scrollbar:!1}),o(u[d].src,function(n){r.close(s.loadi),a&&(t.anim=-1),s.index=r.open(i.extend({type:1,id:"layui-layer-photos",area:function(){var a=[n.width,n.height],o=[i(e).width()-100,i(e).height()-100];if(!t.full&&(a[0]>o[0]||a[1]>o[1])){var r=[a[0]/o[0],a[1]/o[1]];r[0]>r[1]?(a[0]=a[0]/r[0],a[1]=a[1]/r[0]):r[0]'+(u[d].alt||'+function(){return u.length>1?'
                    '+(u[d].alt||"")+""+s.imgIndex+" / "+u.length+"
                    ":""}()+"
                    ",success:function(e,i){s.bigimg=e.find(".layui-layer-phimg"),s.imgsee=e.find(".layui-layer-imgbar"),s.event(e),t.tab&&t.tab(u[d],e),"function"==typeof y&&y(e)},end:function(){s.end=!0,i(document).off("keyup",s.keyup)}},t))},function(){r.close(s.loadi),r.msg("当前图片地址异常
                    是否继续查看下一张?",{time:3e4,btn:["下一张","不看了"],yes:function(){u.length>1&&s.imgnext(!0,!0)}})})}},o.run=function(t){i=t,n=i(e),l.html=i("html"),r.open=function(e){var t=new s(e);return t.index}},e.layui&&layui.define?(r.ready(),layui.define("jquery",function(t){r.path=layui.cache.dir,o.run(layui.$),e.layer=r,t("layer",r)})):"function"==typeof define&&define.amd?define(["jquery"],function(){return o.run(e.jQuery),r}):function(){r.ready(),o.run(e.jQuery)}()}(window);layui.define("jquery",function(e){"use strict";var t=layui.$,i=layui.hint(),n={fixbar:function(e){var i,n,r="layui-fixbar",a="layui-fixbar-top",o=t(document),l=t("body");e=t.extend({showHeight:200},e),e.bar1=e.bar1===!0?"":e.bar1,e.bar2=e.bar2===!0?"":e.bar2,e.bgcolor=e.bgcolor?"background-color:"+e.bgcolor:"";var c=[e.bar1,e.bar2,""],g=t(['
                      ',e.bar1?'
                    • '+c[0]+"
                    • ":"",e.bar2?'
                    • '+c[1]+"
                    • ":"",'
                    • '+c[2]+"
                    • ","
                    "].join("")),u=g.find("."+a),s=function(){var t=o.scrollTop();t>=e.showHeight?i||(u.show(),i=1):i&&(u.hide(),i=0)};t("."+r)[0]||("object"==typeof e.css&&g.css(e.css),l.append(g),s(),g.find("li").on("click",function(){var i=t(this),n=i.attr("lay-type");"top"===n&&t("html,body").animate({scrollTop:0},200),e.click&&e.click.call(this,n)}),o.on("scroll",function(){clearTimeout(n),n=setTimeout(function(){s()},100)}))},countdown:function(e,t,i){var n=this,r="function"==typeof t,a=new Date(e).getTime(),o=new Date(!t||r?(new Date).getTime():t).getTime(),l=a-o,c=[Math.floor(l/864e5),Math.floor(l/36e5)%24,Math.floor(l/6e4)%60,Math.floor(l/1e3)%60];r&&(i=t);var g=setTimeout(function(){n.countdown(e,o+1e3,i)},1e3);return i&&i(l>0?c:[0,0,0,0],t,g),l<=0&&clearTimeout(g),g},timeAgo:function(e,t){var i=this,n=[[],[]],r=(new Date).getTime()-new Date(e).getTime();return r>26784e5?(r=new Date(e),n[0][0]=i.digit(r.getFullYear(),4),n[0][1]=i.digit(r.getMonth()+1),n[0][2]=i.digit(r.getDate()),t||(n[1][0]=i.digit(r.getHours()),n[1][1]=i.digit(r.getMinutes()),n[1][2]=i.digit(r.getSeconds())),n[0].join("-")+" "+n[1].join(":")):r>=864e5?(r/1e3/60/60/24|0)+"\u5929\u524d":r>=36e5?(r/1e3/60/60|0)+"\u5c0f\u65f6\u524d":r>=18e4?(r/1e3/60|0)+"\u5206\u949f\u524d":r<0?"\u672a\u6765":"\u521a\u521a"},digit:function(e,t){var i="";e=String(e),t=t||2;for(var n=e.length;n/g,">").replace(/'/g,"'").replace(/"/g,""")},unescape:function(e){return String(e||"").replace(/\&/g,"&").replace(/\</g,"<").replace(/\>/g,">").replace(/\'/,"'").replace(/\"/,'"')},toVisibleArea:function(e){if(e=t.extend({margin:160,duration:200,type:"y"},e),e.scrollElem[0]&&e.thisElem[0]){var i=e.scrollElem,n=e.thisElem,r="y"===e.type,a=r?"scrollTop":"scrollLeft",o=r?"top":"left",l=i[a](),c=i[r?"height":"width"](),g=i.offset()[o],u=n.offset()[o]-g,s={};(u>c-e.margin||u0&&t.unshift(""),t.join(" ")}()+">"+(a.title||"unnaming")+"";return s[0]?s.before(r):n.append(r),o.append('
                    '+(a.content||"")+"
                    "),b.hideTabMore(!0),b.tabAuto(),this},s.prototype.tabDelete=function(t,a){var e=".layui-tab-title",l=i(".layui-tab[lay-filter="+t+"]"),n=l.children(e),s=n.find('>li[lay-id="'+a+'"]');return b.tabDelete(null,s),this},s.prototype.tabChange=function(t,a){var e=".layui-tab-title",l=i(".layui-tab[lay-filter="+t+"]"),n=l.children(e),s=n.find('>li[lay-id="'+a+'"]');return b.tabClick.call(s[0],null,null,s),this},s.prototype.tab=function(t){t=t||{},m.on("click",t.headerElem,function(a){var e=i(this).index();b.tabClick.call(this,a,e,null,t)})},s.prototype.progress=function(t,a){var e="layui-progress",l=i("."+e+"[lay-filter="+t+"]"),n=l.find("."+e+"-bar"),s=n.find("."+e+"-text");return n.css("width",a).attr("lay-percent",a),s.text(a),this};var o=".layui-nav",r="layui-nav-item",c="layui-nav-bar",u="layui-nav-tree",y="layui-nav-child",d="layui-nav-child-c",f="layui-nav-more",h="layui-icon-down",p="layui-anim layui-anim-upbit",b={tabClick:function(t,a,s,o){o=o||{};var r=s||i(this),a=a||r.parent().children("li").index(r),c=o.headerElem?r.parent():r.parents(".layui-tab").eq(0),u=o.bodyElem?i(o.bodyElem):c.children(".layui-tab-content").children(".layui-tab-item"),y=r.find("a"),d="javascript:;"!==y.attr("href")&&"_blank"===y.attr("target"),f="string"==typeof r.attr("lay-unselect"),h=c.attr("lay-filter");d||f||(r.addClass(l).siblings().removeClass(l),u.eq(a).addClass(n).siblings().removeClass(n)),layui.event.call(this,e,"tab("+h+")",{elem:c,index:a})},tabDelete:function(t,a){var n=a||i(this).parent(),s=n.index(),o=n.parents(".layui-tab").eq(0),r=o.children(".layui-tab-content").children(".layui-tab-item"),c=o.attr("lay-filter");n.hasClass(l)&&(n.next()[0]?b.tabClick.call(n.next()[0],null,s+1):n.prev()[0]&&b.tabClick.call(n.prev()[0],null,s-1)),n.remove(),r.eq(s).remove(),setTimeout(function(){b.tabAuto()},50),layui.event.call(this,e,"tabDelete("+c+")",{elem:o,index:s})},tabAuto:function(){var t="layui-tab-more",e="layui-tab-bar",l="layui-tab-close",n=this;i(".layui-tab").each(function(){var s=i(this),o=s.children(".layui-tab-title"),r=(s.children(".layui-tab-content").children(".layui-tab-item"),'lay-stope="tabmore"'),c=i('');if(n===window&&8!=a.ie&&b.hideTabMore(!0),s.attr("lay-allowClose")&&o.find("li").each(function(){var t=i(this);if(!t.find("."+l)[0]){var a=i('');a.on("click",b.tabDelete),t.append(a)}}),"string"!=typeof s.attr("lay-unauto"))if(o.prop("scrollWidth")>o.outerWidth()+1){if(o.find("."+e)[0])return;o.append(c),s.attr("overflow",""),c.on("click",function(i){o[this.title?"removeClass":"addClass"](t),this.title=this.title?"":"\u6536\u7f29"})}else o.find("."+e).remove(),s.removeAttr("overflow")})},hideTabMore:function(t){var a=i(".layui-tab-title");t!==!0&&"tabmore"===i(t.target).attr("lay-stope")||(a.removeClass("layui-tab-more"),a.find(".layui-tab-bar").attr("title",""))},clickThis:function(){var t=i(this),a=t.parents(o),n=a.attr("lay-filter"),s=t.parent(),c=t.siblings("."+y),d="string"==typeof s.attr("lay-unselect");"javascript:;"!==t.attr("href")&&"_blank"===t.attr("target")||d||c[0]||(a.find("."+l).removeClass(l),s.addClass(l)),a.hasClass(u)&&(c.removeClass(p),c[0]&&(s["none"===c.css("display")?"addClass":"removeClass"](r+"ed"),"all"===a.attr("lay-shrink")&&s.siblings().removeClass(r+"ed"))),layui.event.call(this,e,"nav("+n+")",t)},collapse:function(){var t=i(this),a=t.find(".layui-colla-icon"),l=t.siblings(".layui-colla-content"),s=t.parents(".layui-collapse").eq(0),o=s.attr("lay-filter"),r="none"===l.css("display");if("string"==typeof s.attr("lay-accordion")){var c=s.children(".layui-colla-item").children("."+n);c.siblings(".layui-colla-title").children(".layui-colla-icon").html(""),c.removeClass(n)}l[r?"addClass":"removeClass"](n),a.html(r?"":""),layui.event.call(this,e,"collapse("+o+")",{title:t,content:l,show:r})}};s.prototype.init=function(t,e){var l=function(){return e?'[lay-filter="'+e+'"]':""}(),s={tab:function(){b.tabAuto.call({})},nav:function(){var t=200,e={},s={},v={},m="layui-nav-title",C=function(l,o,r){var c=i(this),h=c.find("."+y);if(o.hasClass(u)){if(!h[0]){var b=c.children("."+m);l.css({top:c.offset().top-o.offset().top,height:(b[0]?b:c).outerHeight(),opacity:1})}}else h.addClass(p),h.hasClass(d)&&h.css({left:-(h.outerWidth()-c.width())/2}),h[0]?l.css({left:l.position().left+l.width()/2,width:0,opacity:0}):l.css({left:c.position().left+parseFloat(c.css("marginLeft")),top:c.position().top+c.height()-l.height()}),e[r]=setTimeout(function(){l.css({width:h[0]?0:c.width(),opacity:h[0]?0:1})},a.ie&&a.ie<10?0:t),clearTimeout(v[r]),"block"===h.css("display")&&clearTimeout(s[r]),s[r]=setTimeout(function(){h.addClass(n),c.find("."+f).addClass(f+"d")},300)};i(o+l).each(function(a){var l=i(this),o=i(''),d=l.find("."+r);l.find("."+c)[0]||(l.append(o),(l.hasClass(u)?d.find("dd,>."+m):d).on("mouseenter",function(){C.call(this,o,l,a)}).on("mouseleave",function(){l.hasClass(u)?o.css({height:0,opacity:0}):(clearTimeout(s[a]),s[a]=setTimeout(function(){l.find("."+y).removeClass(n),l.find("."+f).removeClass(f+"d")},300))}),l.on("mouseleave",function(){clearTimeout(e[a]),v[a]=setTimeout(function(){l.hasClass(u)||o.css({width:0,left:o.position().left+o.width()/2,opacity:0})},t)})),d.find("a").each(function(){var t=i(this),a=(t.parent(),t.siblings("."+y));a[0]&&!t.children("."+f)[0]&&t.append(''),t.off("click",b.clickThis).on("click",b.clickThis)})})},breadcrumb:function(){var t=".layui-breadcrumb";i(t+l).each(function(){var t=i(this),a="lay-separator",e=t.attr(a)||"/",l=t.find("a");l.next("span["+a+"]")[0]||(l.each(function(t){t!==l.length-1&&i(this).after(""+e+"")}),t.css("visibility","visible"))})},progress:function(){var t="layui-progress";i("."+t+l).each(function(){var a=i(this),e=a.find(".layui-progress-bar"),l=e.attr("lay-percent");e.css("width",function(){return/^.+\/.+$/.test(l)?100*new Function("return "+l)()+"%":l}()),a.attr("lay-showPercent")&&setTimeout(function(){e.html(''+l+"")},350)})},collapse:function(){var t="layui-collapse";i("."+t+l).each(function(){var t=i(this).find(".layui-colla-item");t.each(function(){var t=i(this),a=t.find(".layui-colla-title"),e=t.find(".layui-colla-content"),l="none"===e.css("display");a.find(".layui-colla-icon").remove(),a.append(''+(l?"":"")+""),a.off("click",b.collapse).on("click",b.collapse)})})}};return s[t]?s[t]():layui.each(s,function(t,i){i()})},s.prototype.render=s.prototype.init;var v=new s,m=i(document);i(function(){v.render()});var C=".layui-tab-title li";m.on("click",C,b.tabClick),m.on("click",b.hideTabMore),i(window).on("resize",b.tabAuto),t(e,v)});layui.define("layer",function(e){"use strict";var t=layui.$,i=layui.layer,n=layui.hint(),o=layui.device(),a={config:{},set:function(e){var i=this;return i.config=t.extend({},i.config,e),i},on:function(e,t){return layui.onevent.call(this,r,e,t)}},l=function(){var e=this;return{upload:function(t){e.upload.call(e,t)},reload:function(t){e.reload.call(e,t)},config:e.config}},r="upload",u="layui-upload-file",c="layui-upload-form",f="layui-upload-iframe",s="layui-upload-choose",p=function(e){var i=this;i.config=t.extend({},i.config,a.config,e),i.render()};p.prototype.config={accept:"images",exts:"",auto:!0,bindAction:"",url:"",field:"file",acceptMime:"",method:"post",data:{},drag:!0,size:0,number:0,multiple:!1},p.prototype.render=function(e){var i=this,e=i.config;e.elem=t(e.elem),e.bindAction=t(e.bindAction),i.file(),i.events()},p.prototype.file=function(){var e=this,i=e.config,n=e.elemFile=t(['"].join("")),a=i.elem.next();(a.hasClass(u)||a.hasClass(c))&&a.remove(),o.ie&&o.ie<10&&i.elem.wrap('
                    '),e.isFile()?(e.elemFile=i.elem,i.field=i.elem[0].name):i.elem.after(n),o.ie&&o.ie<10&&e.initIE()},p.prototype.initIE=function(){var e=this,i=e.config,n=t(''),o=t(['
                    ',"
                    "].join(""));t("#"+f)[0]||t("body").append(n),i.elem.next().hasClass(c)||(e.elemFile.wrap(o),i.elem.next("."+c).append(function(){var e=[];return layui.each(i.data,function(t,i){i="function"==typeof i?i():i,e.push('')}),e.join("")}()))},p.prototype.msg=function(e){return i.msg(e,{icon:2,shift:6})},p.prototype.isFile=function(){var e=this.config.elem[0];if(e)return"input"===e.tagName.toLocaleLowerCase()&&"file"===e.type},p.prototype.preview=function(e){var t=this;window.FileReader&&layui.each(t.chooseFiles,function(t,i){var n=new FileReader;n.readAsDataURL(i),n.onload=function(){e&&e(t,i,this.result)}})},p.prototype.upload=function(e,i){var n,a=this,l=a.config,r=a.elemFile[0],u=function(){var i=0,n=0,o=e||a.files||a.chooseFiles||r.files,u=function(){l.multiple&&i+n===a.fileLength&&"function"==typeof l.allDone&&l.allDone({total:a.fileLength,successful:i,aborted:n})};layui.each(o,function(e,o){var r=new FormData;r.append(l.field,o),layui.each(l.data,function(e,t){t="function"==typeof t?t():t,r.append(e,t)});var c={url:l.url,type:"post",data:r,contentType:!1,processData:!1,dataType:"json",headers:l.headers||{},success:function(t){i++,d(e,t),u()},error:function(){n++,a.msg("\u8bf7\u6c42\u4e0a\u4f20\u63a5\u53e3\u51fa\u73b0\u5f02\u5e38"),m(e),u()}};"function"==typeof l.progress&&(c.xhr=function(){var i=t.ajaxSettings.xhr();return i.upload.addEventListener("progress",function(t){if(t.lengthComputable){var i=Math.floor(t.loaded/t.total*100);l.progress(i,l.item?l.item[0]:l.elem[0],t,e)}}),i}),t.ajax(c)})},c=function(){var e=t("#"+f);a.elemFile.parent().submit(),clearInterval(p.timer),p.timer=setInterval(function(){var t,i=e.contents().find("body");try{t=i.text()}catch(n){a.msg("\u83b7\u53d6\u4e0a\u4f20\u540e\u7684\u54cd\u5e94\u4fe1\u606f\u51fa\u73b0\u5f02\u5e38"),clearInterval(p.timer),m()}t&&(clearInterval(p.timer),i.html(""),d(0,t))},30)},d=function(e,t){if(a.elemFile.next("."+s).remove(),r.value="","object"!=typeof t)try{t=JSON.parse(t)}catch(i){return t={},a.msg("\u8bf7\u5bf9\u4e0a\u4f20\u63a5\u53e3\u8fd4\u56de\u6709\u6548JSON")}"function"==typeof l.done&&l.done(t,e||0,function(e){a.upload(e)})},m=function(e){l.auto&&(r.value=""),"function"==typeof l.error&&l.error(e||0,function(e){a.upload(e)})},h=l.exts,v=function(){var t=[];return layui.each(e||a.chooseFiles,function(e,i){t.push(i.name)}),t}(),g={preview:function(e){a.preview(e)},upload:function(e,t){var i={};i[e]=t,a.upload(i)},pushFile:function(){return a.files=a.files||{},layui.each(a.chooseFiles,function(e,t){a.files[e]=t}),a.files},resetFile:function(e,t,i){var n=new File([t],i);a.files=a.files||{},a.files[e]=n}},y=function(){if(!(("choose"===i||l.auto)&&(l.choose&&l.choose(g),"choose"===i)||l.before&&l.before(g)===!1))return o.ie?o.ie>9?u():c():void u()};if(v=0===v.length?r.value.match(/[^\/\\]+\..+/g)||[]||"":v,0!==v.length){switch(l.accept){case"file":if(h&&!RegExp("\\w\\.("+h+")$","i").test(escape(v)))return a.msg("\u9009\u62e9\u7684\u6587\u4ef6\u4e2d\u5305\u542b\u4e0d\u652f\u6301\u7684\u683c\u5f0f"),r.value="";break;case"video":if(!RegExp("\\w\\.("+(h||"avi|mp4|wma|rmvb|rm|flash|3gp|flv")+")$","i").test(escape(v)))return a.msg("\u9009\u62e9\u7684\u89c6\u9891\u4e2d\u5305\u542b\u4e0d\u652f\u6301\u7684\u683c\u5f0f"),r.value="";break;case"audio":if(!RegExp("\\w\\.("+(h||"mp3|wav|mid")+")$","i").test(escape(v)))return a.msg("\u9009\u62e9\u7684\u97f3\u9891\u4e2d\u5305\u542b\u4e0d\u652f\u6301\u7684\u683c\u5f0f"),r.value="";break;default:if(layui.each(v,function(e,t){RegExp("\\w\\.("+(h||"jpg|png|gif|bmp|jpeg$")+")","i").test(escape(t))||(n=!0)}),n)return a.msg("\u9009\u62e9\u7684\u56fe\u7247\u4e2d\u5305\u542b\u4e0d\u652f\u6301\u7684\u683c\u5f0f"),r.value=""}if(a.fileLength=function(){var t=0,i=e||a.files||a.chooseFiles||r.files;return layui.each(i,function(){t++}),t}(),l.number&&a.fileLength>l.number)return a.msg("\u540c\u65f6\u6700\u591a\u53ea\u80fd\u4e0a\u4f20\u7684\u6570\u91cf\u4e3a\uff1a"+l.number);if(l.size>0&&!(o.ie&&o.ie<10)){var F;if(layui.each(a.chooseFiles,function(e,t){if(t.size>1024*l.size){var i=l.size/1024;i=i>=1?i.toFixed(2)+"MB":l.size+"KB",r.value="",F=i}}),F)return a.msg("\u6587\u4ef6\u4e0d\u80fd\u8d85\u8fc7"+F)}y()}},p.prototype.reload=function(e){e=e||{},delete e.elem,delete e.bindAction;var i=this,e=i.config=t.extend({},i.config,a.config,e),n=e.elem.next();n.attr({name:e.name,accept:e.acceptMime,multiple:e.multiple})},p.prototype.events=function(){var e=this,i=e.config,a=function(t){e.chooseFiles={},layui.each(t,function(t,i){var n=(new Date).getTime();e.chooseFiles[n+"-"+t]=i})},l=function(t,n){var o=e.elemFile,a=(i.item?i.item:i.elem,t.length>1?t.length+"\u4e2a\u6587\u4ef6":(t[0]||{}).name||o[0].value.match(/[^\/\\]+\..+/g)||[]||"");o.next().hasClass(s)&&o.next().remove(),e.upload(null,"choose"),e.isFile()||i.choose||o.after(''+a+"")};i.elem.off("upload.start").on("upload.start",function(){var o=t(this),a=o.attr("lay-data");if(a)try{a=new Function("return "+a)(),e.config=t.extend({},i,a)}catch(l){n.error("Upload element property lay-data configuration item has a syntax error: "+a)}e.config.item=o,e.elemFile[0].click()}),o.ie&&o.ie<10||i.elem.off("upload.over").on("upload.over",function(){var e=t(this);e.attr("lay-over","")}).off("upload.leave").on("upload.leave",function(){var e=t(this);e.removeAttr("lay-over")}).off("upload.drop").on("upload.drop",function(n,o){var r=t(this),u=o.originalEvent.dataTransfer.files||[];r.removeAttr("lay-over"),a(u),i.auto?e.upload(u):l(u)}),e.elemFile.off("upload.change").on("upload.change",function(){var t=this.files||[];a(t),i.auto?e.upload():l(t)}),i.bindAction.off("upload.action").on("upload.action",function(){e.upload()}),i.elem.data("haveEvents")||(e.elemFile.on("change",function(){t(this).trigger("upload.change")}),i.elem.on("click",function(){e.isFile()||t(this).trigger("upload.start")}),i.drag&&i.elem.on("dragover",function(e){e.preventDefault(),t(this).trigger("upload.over")}).on("dragleave",function(e){t(this).trigger("upload.leave")}).on("drop",function(e){e.preventDefault(),t(this).trigger("upload.drop",e)}),i.bindAction.on("click",function(){t(this).trigger("upload.action")}),i.elem.data("haveEvents",!0))},a.render=function(e){var t=new p(e);return l.call(t)},e(r,a)});layui.define(["jquery","laytpl","lay"],function(e){"use strict";var i=layui.$,n=layui.laytpl,t=layui.hint(),a=layui.device(),l=a.mobile?"click":"mousedown",r="dropdown",o="layui_"+r+"_index",u={config:{},index:layui[r]?layui[r].index+1e4:0,set:function(e){var n=this;return n.config=i.extend({},n.config,e),n},on:function(e,i){return layui.onevent.call(this,r,e,i)}},d=function(){var e=this,i=e.config,n=i.id;return d.that[n]=e,{config:i,reload:function(i){e.reload.call(e,i)}}},s="layui-dropdown",m="layui-menu-item-up",c="layui-menu-item-down",p="layui-menu-body-title",y="layui-menu-item-group",f="layui-menu-item-parent",v="layui-menu-item-divider",g="layui-menu-item-checked",h="layui-menu-item-checked2",w="layui-menu-body-panel",C="layui-menu-body-panel-left",V="."+y+">."+p,k=function(e){var n=this;n.index=++u.index,n.config=i.extend({},n.config,u.config,e),n.init()};k.prototype.config={trigger:"click",content:"",className:"",style:"",show:!1,isAllowSpread:!0,isSpreadItem:!0,data:[],delay:300},k.prototype.reload=function(e){var n=this;n.config=i.extend({},n.config,e),n.init(!0)},k.prototype.init=function(e){var n=this,t=n.config,a=t.elem=i(t.elem);if(a.length>1)return layui.each(a,function(){u.render(i.extend({},t,{elem:this}))}),n;if(!e&&a[0]&&a.data(o)){var l=d.getThis(a.data(o));if(!l)return;return l.reload(t)}t.id="id"in t?t.id:n.index,t.show&&n.render(e),n.events()},k.prototype.render=function(e){var t=this,a=t.config,r=i("body"),s=function(){var e=i('
                      ');return a.data.length>0?m(e,a.data):e.html('
                    • no menu
                    • '),e},m=function(e,t){return layui.each(t,function(t,l){var r=l.child&&l.child.length>0,o="isSpreadItem"in l?l.isSpreadItem:a.isSpreadItem,u=l.templet?n(l.templet).render(l):a.templet?n(a.templet).render(l):l.title,d=function(){return r&&(l.type=l.type||"parent"),l.type?{group:"group",parent:"parent","-":"-"}[l.type]||"parent":""}();if("-"===d||l.title||l.id||r){var s=i(["",function(){var e="href"in l?''+u+"":u;return r?'
                      '+e+function(){return"parent"===d?'':"group"===d&&a.isAllowSpread?'':""}()+"
                      ":'
                      '+e+"
                      "}(),""].join(""));if(s.data("item",l),r){var c=i('
                      '),y=i("
                        ");"parent"===d?(c.append(m(y,l.child)),s.append(c)):s.append(m(y,l.child))}e.append(s)}}),e},c=['
                        ',"
                        "].join("");("contextmenu"===a.trigger||lay.isTopElem(a.elem[0]))&&(e=!0),!e&&a.elem.data(o+"_opened")||(t.elemView=i(c),t.elemView.append(a.content||s()),a.className&&t.elemView.addClass(a.className),a.style&&t.elemView.attr("style",a.style),u.thisId=a.id,t.remove(),r.append(t.elemView),a.elem.data(o+"_opened",!0),t.position(),d.prevElem=t.elemView,d.prevElem.data("prevElem",a.elem),t.elemView.find(".layui-menu").on(l,function(e){layui.stope(e)}),t.elemView.find(".layui-menu li").on("click",function(e){var n=i(this),l=n.data("item")||{},r=l.child&&l.child.length>0;r||"-"===l.type||(t.remove(),"function"==typeof a.click&&a.click(l,n))}),t.elemView.find(V).on("click",function(e){var n=i(this),t=n.parent(),l=t.data("item")||{};"group"===l.type&&a.isAllowSpread&&d.spread(t)}),"mouseenter"===a.trigger&&t.elemView.on("mouseenter",function(){clearTimeout(d.timer)}).on("mouseleave",function(){t.delayRemove()}))},k.prototype.position=function(e){var i=this,n=i.config;lay.position(n.elem[0],i.elemView[0],{position:n.position,e:i.e,clickType:"contextmenu"===n.trigger?"right":null,align:n.align||null})},k.prototype.remove=function(){var e=this,i=(e.config,d.prevElem);i&&(i.data("prevElem")&&i.data("prevElem").data(o+"_opened",!1),i.remove())},k.prototype.delayRemove=function(){var e=this,i=e.config;clearTimeout(d.timer),d.timer=setTimeout(function(){e.remove()},i.delay)},k.prototype.events=function(){var e=this,i=e.config;"hover"===i.trigger&&(i.trigger="mouseenter"),e.prevElem&&e.prevElem.off(i.trigger,e.prevElemCallback),e.prevElem=i.elem,e.prevElemCallback=function(n){clearTimeout(d.timer),e.e=n,e.render(),n.preventDefault(),"function"==typeof i.ready&&i.ready(e.elemView,i.elem,e.e.target)},i.elem.on(i.trigger,e.prevElemCallback),"mouseenter"===i.trigger&&i.elem.on("mouseleave",function(){e.delayRemove()})},d.that={},d.getThis=function(e){var i=d.that[e];return i||t.error(e?r+" instance with ID '"+e+"' not found":"ID argument required"),i},d.spread=function(e){var i=e.children("."+p).find(".layui-icon");e.hasClass(m)?(e.removeClass(m).addClass(c),i.removeClass("layui-icon-down").addClass("layui-icon-up")):(e.removeClass(c).addClass(m),i.removeClass("layui-icon-up").addClass("layui-icon-down"))},!function(){var e=i(window),n=i(document);e.on("resize",function(){if(u.thisId){var e=d.getThis(u.thisId);if(e){if(!e.elemView[0]||!i("."+s)[0])return!1;var n=e.config;"contextmenu"===n.trigger?e.remove():e.position()}}}),n.on(l,function(e){if(u.thisId){var i=d.getThis(u.thisId);if(i){var n=i.config;!lay.isTopElem(n.elem[0])&&"contextmenu"!==n.trigger&&(e.target===n.elem[0]||n.elem.find(e.target)[0]||e.target===i.elemView[0]||i.elemView&&i.elemView.find(e.target)[0])||i.remove()}}});var t=".layui-menu:not(.layui-dropdown-menu) li";n.on("click",t,function(e){var n=i(this),t=n.parents(".layui-menu").eq(0),a=n.hasClass(y)||n.hasClass(f),l=t.attr("lay-filter")||t.attr("id"),o=lay.options(this);n.hasClass(v)||a||(t.find("."+g).removeClass(g),t.find("."+h).removeClass(h),n.addClass(g),n.parents("."+f).addClass(h),layui.event.call(this,r,"click("+l+")",o))}),n.on("click",t+V,function(e){var n=i(this),t=n.parents("."+y+":eq(0)"),a=lay.options(t[0]);"isAllowSpread"in a&&!a.isAllowSpread||d.spread(t)});var a=".layui-menu ."+f;n.on("mouseenter",a,function(n){var t=i(this),a=t.find("."+w);if(a[0]){var l=a[0].getBoundingClientRect();l.right>e.width()&&(a.addClass(C),l=a[0].getBoundingClientRect(),l.left<0&&a.removeClass(C)),l.bottom>e.height()&&a.eq(0).css("margin-top",-(l.bottom-e.height()))}}).on("mouseleave",a,function(e){var n=i(this),t=n.children("."+w);t.removeClass(C),t.css("margin-top",0)})}(),u.reload=function(e,i){var n=d.getThis(e);return n?(n.reload(i),d.call(n)):this},u.render=function(e){var i=new k(e);return d.call(i)},e(r,u)});layui.define("jquery",function(e){"use strict";var i=layui.jquery,t={config:{},index:layui.slider?layui.slider.index+1e4:0,set:function(e){var t=this;return t.config=i.extend({},t.config,e),t},on:function(e,i){return layui.onevent.call(this,n,e,i)}},a=function(){var e=this,i=e.config;return{setValue:function(t,a){return i.value=t,e.slide("set",t,a||0)},config:i}},n="slider",l="layui-disabled",s="layui-slider",r="layui-slider-bar",o="layui-slider-wrap",u="layui-slider-wrap-btn",d="layui-slider-tips",v="layui-slider-input",c="layui-slider-input-txt",p="layui-slider-input-btn",m="layui-slider-hover",f=function(e){var a=this;a.index=++t.index,a.config=i.extend({},a.config,t.config,e),a.render()};f.prototype.config={type:"default",min:0,max:100,value:0,step:1,showstep:!1,tips:!0,input:!1,range:!1,height:200,disabled:!1,theme:"#009688"},f.prototype.render=function(){var e=this,t=e.config;if(t.step<1&&(t.step=1),t.maxt.min?a:t.min,t.value[1]=n>t.min?n:t.min,t.value[0]=t.value[0]>t.max?t.max:t.value[0],t.value[1]=t.value[1]>t.max?t.max:t.value[1];var r=Math.floor((t.value[0]-t.min)/(t.max-t.min)*100),v=Math.floor((t.value[1]-t.min)/(t.max-t.min)*100),p=v-r+"%";r+="%",v+="%"}else{"object"==typeof t.value&&(t.value=Math.min.apply(null,t.value)),t.valuet.max&&(t.value=t.max);var p=Math.floor((t.value-t.min)/(t.max-t.min)*100)+"%"}var m=t.disabled?"#c2c2c2":t.theme,f='
                        '+(t.tips?'
                        ':"")+'
                        '+(t.range?'
                        ':"")+"
                        ",h=i(t.elem),y=h.next("."+s);if(y[0]&&y.remove(),e.elemTemp=i(f),t.range?(e.elemTemp.find("."+o).eq(0).data("value",t.value[0]),e.elemTemp.find("."+o).eq(1).data("value",t.value[1])):e.elemTemp.find("."+o).data("value",t.value),h.html(e.elemTemp),"vertical"===t.type&&e.elemTemp.height(t.height+"px"),t.showstep){for(var g=(t.max-t.min)/t.step,b="",x=1;x
                      ')}e.elemTemp.append(b)}if(t.input&&!t.range){var w=i('
                      ');h.css("position","relative"),h.append(w),h.find("."+c).children("input").val(t.value),"vertical"===t.type?w.css({left:0,top:-48}):e.elemTemp.css("margin-right",w.outerWidth()+15)}t.disabled?(e.elemTemp.addClass(l),e.elemTemp.find("."+u).addClass(l)):e.slide(),e.elemTemp.find("."+u).on("mouseover",function(){var a="vertical"===t.type?t.height:e.elemTemp[0].offsetWidth,n=e.elemTemp.find("."+o),l="vertical"===t.type?a-i(this).parent()[0].offsetTop-n.height():i(this).parent()[0].offsetLeft,s=l/a*100,r=i(this).parent().data("value"),u=t.setTips?t.setTips(r):r;e.elemTemp.find("."+d).html(u),"vertical"===t.type?e.elemTemp.find("."+d).css({bottom:s+"%","margin-bottom":"20px",display:"inline-block"}):e.elemTemp.find("."+d).css({left:s+"%",display:"inline-block"})}).on("mouseout",function(){e.elemTemp.find("."+d).css("display","none")})},f.prototype.slide=function(e,t,a){var n=this,l=n.config,s=n.elemTemp,f=function(){return"vertical"===l.type?l.height:s[0].offsetWidth},h=s.find("."+o),y=s.next("."+v),g=y.children("."+c).children("input").val(),b=100/((l.max-l.min)/Math.ceil(l.step)),x=function(e,i){e=Math.ceil(e)*b>100?Math.ceil(e)*b:Math.round(e)*b,e=e>100?100:e,h.eq(i).css("vertical"===l.type?"bottom":"left",e+"%");var t=T(h[0].offsetLeft),a=l.range?T(h[1].offsetLeft):0;"vertical"===l.type?(s.find("."+d).css({bottom:e+"%","margin-bottom":"20px"}),t=T(f()-h[0].offsetTop-h.height()),a=l.range?T(f()-h[1].offsetTop-h.height()):0):s.find("."+d).css("left",e+"%"),t=t>100?100:t,a=a>100?100:a;var n=Math.min(t,a),o=Math.abs(t-a);"vertical"===l.type?s.find("."+r).css({height:o+"%",bottom:n+"%"}):s.find("."+r).css({width:o+"%",left:n+"%"});var u=l.min+Math.round((l.max-l.min)*e/100);if(g=u,y.children("."+c).children("input").val(g),h.eq(i).data("value",u),s.find("."+d).html(l.setTips?l.setTips(u):u),l.range){var v=[h.eq(0).data("value"),h.eq(1).data("value")];v[0]>v[1]&&v.reverse()}l.change&&l.change(l.range?v:u)},T=function(e){var i=e/f()*100/b,t=Math.round(i)*b;return e==f()&&(t=Math.ceil(i)*b),t},w=i(['
                      f()&&(r=f());var o=r/f()*100/b;x(o,e),t.addClass(m),s.find("."+d).show(),i.preventDefault()},o=function(){t.removeClass(m),s.find("."+d).hide()};M(r,o)})}),s.on("click",function(e){var t=i("."+u);if(!t.is(event.target)&&0===t.has(event.target).length&&t.length){var a,n="vertical"===l.type?f()-e.clientY+i(this).offset().top:e.clientX-i(this).offset().left;n<0&&(n=0),n>f()&&(n=f());var s=n/f()*100/b;a=l.range?"vertical"===l.type?Math.abs(n-parseInt(i(h[0]).css("bottom")))>Math.abs(n-parseInt(i(h[1]).css("bottom")))?1:0:Math.abs(n-h[0].offsetLeft)>Math.abs(n-h[1].offsetLeft)?1:0:0,x(s,a),e.preventDefault()}}),y.children("."+p).children("i").each(function(e){i(this).on("click",function(){g=y.children("."+c).children("input").val(),g=1==e?g-l.stepl.max?l.max:Number(g)+l.step;var i=(g-l.min)/(l.max-l.min)*100/b;x(i,0)})});var q=function(){var e=this.value;e=isNaN(e)?0:e,e=el.max?l.max:e,this.value=e;var i=(e-l.min)/(l.max-l.min)*100/b;x(i,0)};y.children("."+c).children("input").on("keydown",function(e){13===e.keyCode&&(e.preventDefault(),q.call(this))}).on("change",q)},f.prototype.events=function(){var e=this;e.config},t.render=function(e){var i=new f(e);return a.call(i)},e(n,t)});layui.define(["jquery","lay"],function(e){"use strict";var i=layui.jquery,r=layui.lay,o=layui.device(),n=o.mobile?"click":"mousedown",l={config:{},index:layui.colorpicker?layui.colorpicker.index+1e4:0,set:function(e){var r=this;return r.config=i.extend({},r.config,e),r},on:function(e,i){return layui.onevent.call(this,"colorpicker",e,i)}},t=function(){var e=this,i=e.config;return{config:i}},c="colorpicker",a="layui-show",s="layui-colorpicker",f=".layui-colorpicker-main",d="layui-icon-down",u="layui-icon-close",p="layui-colorpicker-trigger-span",g="layui-colorpicker-trigger-i",v="layui-colorpicker-side",h="layui-colorpicker-side-slider",b="layui-colorpicker-basis",k="layui-colorpicker-alpha-bgcolor",y="layui-colorpicker-alpha-slider",m="layui-colorpicker-basis-cursor",x="layui-colorpicker-main-input",P=function(e){var i={h:0,s:0,b:0},r=Math.min(e.r,e.g,e.b),o=Math.max(e.r,e.g,e.b),n=o-r;return i.b=o,i.s=0!=o?255*n/o:0,0!=i.s?e.r==o?i.h=(e.g-e.b)/n:e.g==o?i.h=2+(e.b-e.r)/n:i.h=4+(e.r-e.g)/n:i.h=-1,o==r&&(i.h=0),i.h*=60,i.h<0&&(i.h+=360),i.s*=100/255,i.b*=100/255,i},C=function(e){var e=e.indexOf("#")>-1?e.substring(1):e;if(3==e.length){var i=e.split("");e=i[0]+i[0]+i[1]+i[1]+i[2]+i[2]}e=parseInt(e,16);var r={r:e>>16,g:(65280&e)>>8,b:255&e};return P(r)},B=function(e){var i={},r=e.h,o=255*e.s/100,n=255*e.b/100;if(0==o)i.r=i.g=i.b=n;else{var l=n,t=(255-o)*n/255,c=(l-t)*(r%60)/60;360==r&&(r=0),r<60?(i.r=l,i.b=t,i.g=t+c):r<120?(i.g=l,i.b=t,i.r=l-c):r<180?(i.g=l,i.r=t,i.b=t+c):r<240?(i.b=l,i.r=t,i.g=l-c):r<300?(i.b=l,i.g=t,i.r=t+c):r<360?(i.r=l,i.g=t,i.b=l-c):(i.r=0,i.g=0,i.b=0)}return{r:Math.round(i.r),g:Math.round(i.g),b:Math.round(i.b)}},w=function(e){var r=B(e),o=[r.r.toString(16),r.g.toString(16),r.b.toString(16)];return i.each(o,function(e,i){1==i.length&&(o[e]="0"+i)}),o.join("")},D=function(e){var i=/[0-9]{1,3}/g,r=e.match(i)||[];return{r:r[0],g:r[1],b:r[2]}},j=i(window),E=i(document),F=function(e){var r=this;r.index=++l.index,r.config=i.extend({},r.config,l.config,e),r.render()};F.prototype.config={color:"",size:null,alpha:!1,format:"hex",predefine:!1,colors:["#009688","#5FB878","#1E9FFF","#FF5722","#FFB800","#01AAED","#999","#c00","#ff8c00","#ffd700","#90ee90","#00ced1","#1e90ff","#c71585","rgb(0, 186, 189)","rgb(255, 120, 0)","rgb(250, 212, 0)","#393D49","rgba(0,0,0,.5)","rgba(255, 69, 0, 0.68)","rgba(144, 240, 144, 0.5)","rgba(31, 147, 255, 0.73)"]},F.prototype.render=function(){var e=this,r=e.config,o=i(['
                      ',"",'3&&(r.alpha&&"rgb"==r.format||(e="#"+w(P(D(r.color))))),"background: "+e):e}()+'">','',"","","
                      "].join("")),n=i(r.elem);r.size&&o.addClass("layui-colorpicker-"+r.size),n.addClass("layui-inline").html(e.elemColorBox=o),e.color=e.elemColorBox.find("."+p)[0].style.background,e.events()},F.prototype.renderPicker=function(){var e=this,r=e.config,o=e.elemColorBox[0],n=e.elemPicker=i(['
                      ','
                      ','
                      ','
                      ','
                      ','
                      ',"
                      ",'
                      ','
                      ',"
                      ","
                      ",'
                      ','
                      ','
                      ',"
                      ","
                      ",function(){if(r.predefine){var e=['
                      '];return layui.each(r.colors,function(i,r){e.push(['
                      ','
                      ',"
                      "].join(""))}),e.push("
                      "),e.join("")}return""}(),'
                      ','
                      ','',"
                      ",'
                      ','','',"","
                      "].join(""));e.elemColorBox.find("."+p)[0];i(f)[0]&&i(f).data("index")==e.index?e.removePicker(F.thisElemInd):(e.removePicker(F.thisElemInd),i("body").append(n)),F.thisElemInd=e.index,F.thisColor=o.style.background,e.position(),e.pickerEvents()},F.prototype.removePicker=function(e){var r=this;r.config;return i("#layui-colorpicker"+(e||r.index)).remove(),r},F.prototype.position=function(){var e=this,i=e.config;return r.position(e.bindElem||e.elemColorBox[0],e.elemPicker[0],{position:i.position,align:"center"}),e},F.prototype.val=function(){var e=this,i=(e.config,e.elemColorBox.find("."+p)),r=e.elemPicker.find("."+x),o=i[0],n=o.style.backgroundColor;if(n){var l=P(D(n)),t=i.attr("lay-type");if(e.select(l.h,l.s,l.b),"torgb"===t&&r.find("input").val(n),"rgba"===t){var c=D(n);if(3==(n.match(/[0-9]{1,3}/g)||[]).length)r.find("input").val("rgba("+c.r+", "+c.g+", "+c.b+", 1)"),e.elemPicker.find("."+y).css("left",280);else{r.find("input").val(n);var a=280*n.slice(n.lastIndexOf(",")+1,n.length-1);e.elemPicker.find("."+y).css("left",a)}e.elemPicker.find("."+k)[0].style.background="linear-gradient(to right, rgba("+c.r+", "+c.g+", "+c.b+", 0), rgb("+c.r+", "+c.g+", "+c.b+"))"}}else e.select(0,100,100),r.find("input").val(""),e.elemPicker.find("."+k)[0].style.background="",e.elemPicker.find("."+y).css("left",280)},F.prototype.side=function(){var e=this,r=e.config,o=e.elemColorBox.find("."+p),n=o.attr("lay-type"),l=e.elemPicker.find("."+v),t=e.elemPicker.find("."+h),c=e.elemPicker.find("."+b),a=e.elemPicker.find("."+m),s=e.elemPicker.find("."+k),f=e.elemPicker.find("."+y),C=t[0].offsetTop/180*360,w=100-(a[0].offsetTop+3)/180*100,E=(a[0].offsetLeft+3)/260*100,F=Math.round(f[0].offsetLeft/280*100)/100,H=e.elemColorBox.find("."+g),M=e.elemPicker.find(".layui-colorpicker-pre").children("div"),Y=function(i,l,t,c){e.select(i,l,t);var a=B({h:i,s:l,b:t});if(H.addClass(d).removeClass(u),o[0].style.background="rgb("+a.r+", "+a.g+", "+a.b+")","torgb"===n&&e.elemPicker.find("."+x).find("input").val("rgb("+a.r+", "+a.g+", "+a.b+")"),"rgba"===n){var p=0;p=280*c,f.css("left",p),e.elemPicker.find("."+x).find("input").val("rgba("+a.r+", "+a.g+", "+a.b+", "+c+")"),o[0].style.background="rgba("+a.r+", "+a.g+", "+a.b+", "+c+")",s[0].style.background="linear-gradient(to right, rgba("+a.r+", "+a.g+", "+a.b+", 0), rgb("+a.r+", "+a.g+", "+a.b+"))"}r.change&&r.change(e.elemPicker.find("."+x).find("input").val())},I=i(['
                      '].join("")),L=function(e){i("#LAY-colorpicker-moving")[0]||i("body").append(I),I.on("mousemove",e),I.on("mouseup",function(){I.remove()}).on("mouseleave",function(){I.remove()})};t.on("mousedown",function(e){var i=this.offsetTop,r=e.clientY,o=function(e){var o=i+(e.clientY-r),n=l[0].offsetHeight;o<0&&(o=0),o>n&&(o=n);var t=o/180*360;C=t,Y(t,E,w,F),e.preventDefault()};L(o),e.preventDefault()}),l.on("click",function(e){var r=e.clientY-i(this).offset().top;r<0&&(r=0),r>this.offsetHeight&&(r=this.offsetHeight);var o=r/180*360;C=o,Y(o,E,w,F),e.preventDefault()}),a.on("mousedown",function(e){var i=this.offsetTop,r=this.offsetLeft,o=e.clientY,n=e.clientX,l=function(e){var l=i+(e.clientY-o),t=r+(e.clientX-n),a=c[0].offsetHeight-3,s=c[0].offsetWidth-3;l<-3&&(l=-3),l>a&&(l=a),t<-3&&(t=-3),t>s&&(t=s);var f=(t+3)/260*100,d=100-(l+3)/180*100;w=d,E=f,Y(C,f,d,F),e.preventDefault()};layui.stope(e),L(l),e.preventDefault()}),c.on("mousedown",function(e){var r=e.clientY-i(this).offset().top-3+j.scrollTop(),o=e.clientX-i(this).offset().left-3+j.scrollLeft();r<-3&&(r=-3),r>this.offsetHeight-3&&(r=this.offsetHeight-3),o<-3&&(o=-3),o>this.offsetWidth-3&&(o=this.offsetWidth-3);var n=(o+3)/260*100,l=100-(r+3)/180*100;w=l,E=n,Y(C,n,l,F),layui.stope(e),e.preventDefault(),a.trigger(e,"mousedown")}),f.on("mousedown",function(e){var i=this.offsetLeft,r=e.clientX,o=function(e){var o=i+(e.clientX-r),n=s[0].offsetWidth;o<0&&(o=0),o>n&&(o=n);var l=Math.round(o/280*100)/100;F=l,Y(C,E,w,l),e.preventDefault()};L(o),e.preventDefault()}),s.on("click",function(e){var r=e.clientX-i(this).offset().left;r<0&&(r=0),r>this.offsetWidth&&(r=this.offsetWidth);var o=Math.round(r/280*100)/100;F=o,Y(C,E,w,o),e.preventDefault()}),M.each(function(){i(this).on("click",function(){i(this).parent(".layui-colorpicker-pre").addClass("selected").siblings().removeClass("selected");var e,r=this.style.backgroundColor,o=P(D(r)),n=r.slice(r.lastIndexOf(",")+1,r.length-1);C=o.h,E=o.s,w=o.b,3==(r.match(/[0-9]{1,3}/g)||[]).length&&(n=1),F=n,e=280*n,Y(o.h,o.s,o.b,n)})})},F.prototype.select=function(e,i,r,o){var n=this,l=(n.config,w({h:e,s:100,b:100})),t=w({h:e,s:i,b:r}),c=e/360*180,a=180-r/100*180-3,s=i/100*260-3;n.elemPicker.find("."+h).css("top",c),n.elemPicker.find("."+b)[0].style.background="#"+l,n.elemPicker.find("."+m).css({top:a,left:s}),"change"!==o&&n.elemPicker.find("."+x).find("input").val("#"+t)},F.prototype.pickerEvents=function(){var e=this,r=e.config,o=e.elemColorBox.find("."+p),n=e.elemPicker.find("."+x+" input"),l={clear:function(i){o[0].style.background="",e.elemColorBox.find("."+g).removeClass(d).addClass(u),e.color="",r.done&&r.done(""),e.removePicker()},confirm:function(i,l){var t=n.val(),c=t,a={};if(t.indexOf(",")>-1){if(a=P(D(t)),e.select(a.h,a.s,a.b),o[0].style.background=c="#"+w(a),(t.match(/[0-9]{1,3}/g)||[]).length>3&&"rgba"===o.attr("lay-type")){var s=280*t.slice(t.lastIndexOf(",")+1,t.length-1);e.elemPicker.find("."+y).css("left",s),o[0].style.background=t,c=t}}else a=C(t),o[0].style.background=c="#"+w(a),e.elemColorBox.find("."+g).removeClass(u).addClass(d);return"change"===l?(e.select(a.h,a.s,a.b,l),void(r.change&&r.change(c))):(e.color=t,r.done&&r.done(t),void e.removePicker())}};e.elemPicker.on("click","*[colorpicker-events]",function(){var e=i(this),r=e.attr("colorpicker-events");l[r]&&l[r].call(this,e)}),n.on("keyup",function(e){var r=i(this);l.confirm.call(this,r,13===e.keyCode?null:"change")})},F.prototype.events=function(){var e=this,r=e.config,o=e.elemColorBox.find("."+p);e.elemColorBox.on("click",function(){e.renderPicker(),i(f)[0]&&(e.val(),e.side())}),r.elem[0]&&!e.elemColorBox[0].eventHandler&&(E.on(n,function(r){if(!i(r.target).hasClass(s)&&!i(r.target).parents("."+s)[0]&&!i(r.target).hasClass(f.replace(/\./g,""))&&!i(r.target).parents(f)[0]&&e.elemPicker){if(e.color){var n=P(D(e.color));e.select(n.h,n.s,n.b)}else e.elemColorBox.find("."+g).removeClass(d).addClass(u);o[0].style.background=e.color||"",e.removePicker()}}),j.on("resize",function(){return!(!e.elemPicker||!i(f)[0])&&void e.position()}),e.elemColorBox[0].eventHandler=!0)},l.render=function(e){var i=new F(e);return t.call(i)},e(c,l)});layui.define("layer",function(e){"use strict";var t=layui.$,i=layui.layer,a=layui.hint(),n=layui.device(),l="form",r=".layui-form",o="layui-this",s="layui-hide",c="layui-disabled",u=function(){this.config={verify:{required:[/[\S]+/,"\u5fc5\u586b\u9879\u4e0d\u80fd\u4e3a\u7a7a"],phone:[/^1\d{10}$/,"\u8bf7\u8f93\u5165\u6b63\u786e\u7684\u624b\u673a\u53f7"],email:[/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/,"\u90ae\u7bb1\u683c\u5f0f\u4e0d\u6b63\u786e"],url:[/^(#|(http(s?)):\/\/|\/\/)[^\s]+\.[^\s]+$/,"\u94fe\u63a5\u683c\u5f0f\u4e0d\u6b63\u786e"],number:function(e){if(!e||isNaN(e))return"\u53ea\u80fd\u586b\u5199\u6570\u5b57"},date:[/^(\d{4})[-\/](\d{1}|0\d{1}|1[0-2])([-\/](\d{1}|0\d{1}|[1-2][0-9]|3[0-1]))*$/,"\u65e5\u671f\u683c\u5f0f\u4e0d\u6b63\u786e"],identity:[/(^\d{15}$)|(^\d{17}(x|X|\d)$)/,"\u8bf7\u8f93\u5165\u6b63\u786e\u7684\u8eab\u4efd\u8bc1\u53f7"]},autocomplete:null}};u.prototype.set=function(e){var i=this;return t.extend(!0,i.config,e),i},u.prototype.verify=function(e){var i=this;return t.extend(!0,i.config.verify,e),i},u.prototype.on=function(e,t){return layui.onevent.call(this,l,e,t)},u.prototype.val=function(e,i){var a=this,n=t(r+'[lay-filter="'+e+'"]');return n.each(function(e,a){var n=t(this);layui.each(i,function(e,t){var i,a=n.find('[name="'+e+'"]');a[0]&&(i=a[0].type,"checkbox"===i?a[0].checked=t:"radio"===i?a.each(function(){this.value==t&&(this.checked=!0)}):a.val(t))})}),f.render(null,e),a.getValue(e)},u.prototype.getValue=function(e,i){i=i||t(r+'[lay-filter="'+e+'"]').eq(0);var a={},n={},l=i.find("input,select,textarea");return layui.each(l,function(e,i){var l;t(this);if(i.name=(i.name||"").replace(/^\s*|\s*&/,""),i.name){if(/^.*\[\]$/.test(i.name)){var r=i.name.match(/^(.*)\[\]$/g)[0];a[r]=0|a[r],l=i.name.replace(/^(.*)\[\]$/,"$1["+a[r]++ +"]")}/^checkbox|radio$/.test(i.type)&&!i.checked||(n[l||i.name]=i.value)}}),n},u.prototype.render=function(e,i){var n=this,u=n.config,d=t(r+function(){return i?'[lay-filter="'+i+'"]':""}()),f={input:function(){var e=d.find("input,textarea");u.autocomplete&&e.attr("autocomplete",u.autocomplete)},select:function(){var e,i="\u8bf7\u9009\u62e9",a="layui-form-select",n="layui-select-title",r="layui-select-none",u="",f=d.find("select"),v=function(i,l){t(i.target).parent().hasClass(n)&&!l||(t("."+a).removeClass(a+"ed "+a+"up"),e&&u&&e.val(u)),e=null},y=function(i,d,f){var y,p=t(this),m=i.find("."+n),g=m.find("input"),k=i.find("dl"),x=k.children("dd"),b=this.selectedIndex;if(!d){var C=function(){var e=i.offset().top+i.outerHeight()+5-h.scrollTop(),t=k.outerHeight();b=p[0].selectedIndex,i.addClass(a+"ed"),x.removeClass(s),y=null,x.eq(b).addClass(o).siblings().removeClass(o),e+t>h.height()&&e>=t&&i.addClass(a+"up"),T()},w=function(e){i.removeClass(a+"ed "+a+"up"),g.blur(),y=null,e||$(g.val(),function(e){var i=p[0].selectedIndex;e&&(u=t(p[0].options[i]).html(),0===i&&u===g.attr("placeholder")&&(u=""),g.val(u||""))})},T=function(){var e=k.children("dd."+o);if(e[0]){var t=e.position().top,i=k.height(),a=e.height();t>i&&k.scrollTop(t+k.scrollTop()-i+a-5),t<0&&k.scrollTop(t+k.scrollTop()-5)}};m.on("click",function(e){i.hasClass(a+"ed")?w():(v(e,!0),C()),k.find("."+r).remove()}),m.find(".layui-edge").on("click",function(){g.focus()}),g.on("keyup",function(e){var t=e.keyCode;9===t&&C()}).on("keydown",function(e){var t=e.keyCode;9===t&&w();var i=function(t,a){var n,l;e.preventDefault();var r=function(){var e=k.children("dd."+o);if(k.children("dd."+s)[0]&&"next"===t){var i=k.children("dd:not(."+s+",."+c+")"),n=i.eq(0).index();if(n>=0&&n\u65e0\u5339\u914d\u9879

                      '):k.find("."+r).remove()},"keyup"),""===t&&k.find("."+r).remove(),void T())};f&&g.on("keyup",q).on("blur",function(i){var a=p[0].selectedIndex;e=g,u=t(p[0].options[a]).html(),0===a&&u===g.attr("placeholder")&&(u=""),setTimeout(function(){$(g.val(),function(e){u||g.val("")},"blur")},200)}),x.on("click",function(){var e=t(this),a=e.attr("lay-value"),n=p.attr("lay-filter");return!e.hasClass(c)&&(e.hasClass("layui-select-tips")?g.val(""):(g.val(e.text()),e.addClass(o)),e.siblings().removeClass(o),p.val(a).removeClass("layui-form-danger"),layui.event.call(this,l,"select("+n+")",{elem:p[0],value:a,othis:i}),w(!0),!1)}),i.find("dl>dt").on("click",function(e){return!1}),t(document).off("click",v).on("click",v)}};f.each(function(e,l){var r=t(this),s=r.next("."+a),u=this.disabled,d=l.value,f=t(l.options[l.selectedIndex]),v=l.options[0];if("string"==typeof r.attr("lay-ignore"))return r.show();var h="string"==typeof r.attr("lay-search"),p=v?v.value?i:v.innerHTML||i:i,m=t(['
                      ','
                      ','','
                      ','
                      ',function(e){var a=[];return layui.each(e,function(e,n){0!==e||n.value?"optgroup"===n.tagName.toLowerCase()?a.push("
                      "+n.label+"
                      "):a.push('
                      '+t.trim(n.innerHTML)+"
                      "):a.push('
                      '+t.trim(n.innerHTML||i)+"
                      ")}),0===a.length&&a.push('
                      \u6ca1\u6709\u9009\u9879
                      '),a.join("")}(r.find("*"))+"
                      ","
                      "].join(""));s[0]&&s.remove(),r.after(m),y.call(this,m,u,h)})},checkbox:function(){var e={checkbox:["layui-form-checkbox","layui-form-checked","checkbox"],_switch:["layui-form-switch","layui-form-onswitch","switch"]},i=d.find("input[type=checkbox]"),a=function(e,i){var a=t(this);e.on("click",function(){var t=a.attr("lay-filter"),n=(a.attr("lay-text")||"").split("|");a[0].disabled||(a[0].checked?(a[0].checked=!1,e.removeClass(i[1]).find("em").text(n[1])):(a[0].checked=!0,e.addClass(i[1]).find("em").text(n[0])),layui.event.call(a[0],l,i[2]+"("+t+")",{elem:a[0],value:a[0].value,othis:e}))})};i.each(function(i,n){var l=t(this),r=l.attr("lay-skin"),o=(l.attr("lay-text")||"").split("|"),s=this.disabled;"switch"===r&&(r="_"+r);var u=e[r]||e.checkbox;if("string"==typeof l.attr("lay-ignore"))return l.show();var d=l.next("."+u[0]),f=t(['
                      ",function(){var e=n.title.replace(/\s/g,""),t={checkbox:[e?""+n.title+"":"",''].join(""),_switch:""+((n.checked?o[0]:o[1])||"")+""};return t[r]||t.checkbox}(),"
                      "].join(""));d[0]&&d.remove(),l.after(f),a.call(this,f,u)})},radio:function(){var e="layui-form-radio",i=["",""],a=d.find("input[type=radio]"),n=function(a){var n=t(this),o="layui-anim-scaleSpring";a.on("click",function(){var s=n[0].name,c=n.parents(r),u=n.attr("lay-filter"),d=c.find("input[name="+s.replace(/(\.|#|\[|\])/g,"\\$1")+"]");n[0].disabled||(layui.each(d,function(){var a=t(this).next("."+e);this.checked=!1,a.removeClass(e+"ed"),a.find(".layui-icon").removeClass(o).html(i[1])}),n[0].checked=!0,a.addClass(e+"ed"),a.find(".layui-icon").addClass(o).html(i[0]),layui.event.call(n[0],l,"radio("+u+")",{elem:n[0],value:n[0].value,othis:a}))})};a.each(function(a,l){var r=t(this),o=r.next("."+e),s=this.disabled;if("string"==typeof r.attr("lay-ignore"))return r.show();o[0]&&o.remove();var u=t(['
                      ',''+i[l.checked?0:1]+"","
                      "+function(){var e=l.title||"";return"string"==typeof r.next().attr("lay-radio")&&(e=r.next().html()),e}()+"
                      ","
                      "].join(""));r.after(u),n.call(this,u)})}};return e?f[e]?f[e]():a.error('\u4e0d\u652f\u6301\u7684 "'+e+'" \u8868\u5355\u6e32\u67d3'):layui.each(f,function(e,t){t()}),n};var d=function(){var e=null,a=f.config.verify,o="layui-form-danger",s={},c=t(this),u=c.parents(r).eq(0),d=u.find("*[lay-verify]"),h=c.parents("form")[0],y=c.attr("lay-filter");return layui.each(d,function(l,r){var s=t(this),c=s.attr("lay-verify").split("|"),u=s.attr("lay-verType"),d=s.val();if(s.removeClass(o),layui.each(c,function(t,l){var c,f="",h="function"==typeof a[l];if(a[l]){var c=h?f=a[l](d,r):!a[l][0].test(d),y="select"===r.tagName.toLowerCase()||/^checkbox|radio$/.test(r.type);if(f=f||a[l][1],"required"===l&&(f=s.attr("lay-reqText")||f),c)return"tips"===u?i.tips(f,function(){return"string"!=typeof s.attr("lay-ignore")&&y?s.next():s}(),{tips:1}):"alert"===u?i.alert(f,{title:"\u63d0\u793a",shadeClose:!0}):/\bstring|number\b/.test(typeof f)&&i.msg(f,{icon:5,shift:6}),n.mobile?v.scrollTop(function(){try{return(y?s.next():s).offset().top-15}catch(e){return 0}}()):setTimeout(function(){(y?s.next().find("input"):r).focus()},7),s.addClass(o),e=!0}}),e)return e}),!e&&(s=f.getValue(null,u),layui.event.call(this,l,"submit("+y+")",{elem:this,form:h,field:s}))},f=new u,v=t(document),h=t(window);t(function(){f.render()}),v.on("reset",r,function(){var e=t(this).attr("lay-filter");setTimeout(function(){f.render(null,e)},50)}),v.on("submit",r,d).on("click","*[lay-submit]",d),e(l,f)});layui.define("form",function(e){"use strict";var i=layui.$,a=layui.form,n=layui.layer,t="tree",r={config:{},index:layui[t]?layui[t].index+1e4:0,set:function(e){var a=this;return a.config=i.extend({},a.config,e),a},on:function(e,i){return layui.onevent.call(this,t,e,i)}},l=function(){var e=this,i=e.config,a=i.id||e.index;return l.that[a]=e,l.config[a]=i,{config:i,reload:function(i){e.reload.call(e,i)},getChecked:function(){return e.getChecked.call(e)},setChecked:function(i){return e.setChecked.call(e,i)}}},c="layui-hide",d="layui-disabled",s="layui-tree-set",o="layui-tree-iconClick",h="layui-icon-addition",u="layui-icon-subtraction",p="layui-tree-entry",f="layui-tree-main",y="layui-tree-txt",v="layui-tree-pack",C="layui-tree-spread",k="layui-tree-setLineShort",m="layui-tree-showLine",x="layui-tree-lineExtend",b=function(e){var a=this;a.index=++r.index,a.config=i.extend({},a.config,r.config,e),a.render()};b.prototype.config={data:[],showCheckbox:!1,showLine:!0,accordion:!1,onlyIconControl:!1,isJump:!1,edit:!1,text:{defaultNodeName:"\u672a\u547d\u540d",none:"\u65e0\u6570\u636e"}},b.prototype.reload=function(e){var a=this;layui.each(e,function(e,i){"array"===layui._typeof(i)&&delete a.config[e]}),a.config=i.extend(!0,{},a.config,e),a.render()},b.prototype.render=function(){var e=this,a=e.config;e.checkids=[];var n=i('
                      ');e.tree(n);var t=a.elem=i(a.elem);if(t[0]){if(e.key=a.id||e.index,e.elem=n,e.elemNone=i('
                      '+a.text.none+"
                      "),t.html(e.elem),0==e.elem.find(".layui-tree-set").length)return e.elem.append(e.elemNone);a.showCheckbox&&e.renderForm("checkbox"),e.elem.find(".layui-tree-set").each(function(){var e=i(this);e.parent(".layui-tree-pack")[0]||e.addClass("layui-tree-setHide"),!e.next()[0]&&e.parents(".layui-tree-pack").eq(1).hasClass("layui-tree-lineExtend")&&e.addClass(k),e.next()[0]||e.parents(".layui-tree-set").eq(0).next()[0]||e.addClass(k)}),e.events()}},b.prototype.renderForm=function(e){a.render(e,"LAY-tree-"+this.index)},b.prototype.tree=function(e,a){var n=this,t=n.config,r=a||t.data;layui.each(r,function(a,r){var l=r.children&&r.children.length>0,o=i('
                      "),h=i(['
                      ','
                      ','
                      ',function(){return t.showLine?l?'':'':''}(),function(){return t.showCheckbox?'':""}(),function(){return t.isJump&&r.href?''+(r.title||r.label||t.text.defaultNodeName)+"":''+(r.title||r.label||t.text.defaultNodeName)+""}(),"
                      ",function(){if(!t.edit)return"";var e={add:'',update:'',del:''},i=['
                      '];return t.edit===!0&&(t.edit=["update","del"]),"object"==typeof t.edit?(layui.each(t.edit,function(a,n){i.push(e[n]||"")}),i.join("")+"
                      "):void 0}(),"
                      "].join(""));l&&(h.append(o),n.tree(o,r.children)),e.append(h),h.prev("."+s)[0]&&h.prev().children(".layui-tree-pack").addClass("layui-tree-showLine"),l||h.parent(".layui-tree-pack").addClass("layui-tree-lineExtend"),n.spread(h,r),t.showCheckbox&&(r.checked&&n.checkids.push(r.id),n.checkClick(h,r)),t.edit&&n.operate(h,r)})},b.prototype.spread=function(e,a){var n=this,t=n.config,r=e.children("."+p),l=r.children("."+f),c=r.find("."+o),k=r.find("."+y),m=t.onlyIconControl?c:l,x="";m.on("click",function(i){var a=e.children("."+v),n=m.children(".layui-icon")[0]?m.children(".layui-icon"):m.find(".layui-tree-icon").children(".layui-icon");if(a[0]){if(e.hasClass(C))e.removeClass(C),a.slideUp(200),n.removeClass(u).addClass(h);else if(e.addClass(C),a.slideDown(200),n.addClass(u).removeClass(h),t.accordion){var r=e.siblings("."+s);r.removeClass(C),r.children("."+v).slideUp(200),r.find(".layui-tree-icon").children(".layui-icon").removeClass(u).addClass(h)}}else x="normal"}),k.on("click",function(){var n=i(this);n.hasClass(d)||(x=e.hasClass(C)?t.onlyIconControl?"open":"close":t.onlyIconControl?"close":"open",t.click&&t.click({elem:e,state:x,data:a}))})},b.prototype.setCheckbox=function(e,i,a){var n=this,t=(n.config,a.prop("checked"));if(!a.prop("disabled")){if("object"==typeof i.children||e.find("."+v)[0]){var r=e.find("."+v).find('input[same="layuiTreeCheck"]');r.each(function(){this.disabled||(this.checked=t)})}var l=function(e){if(e.parents("."+s)[0]){var i,a=e.parent("."+v),n=a.parent(),r=a.prev().find('input[same="layuiTreeCheck"]');t?r.prop("checked",t):(a.find('input[same="layuiTreeCheck"]').each(function(){this.checked&&(i=!0)}),i||r.prop("checked",!1)),l(n)}};l(e),n.renderForm("checkbox")}},b.prototype.checkClick=function(e,a){var n=this,t=n.config,r=e.children("."+p),l=r.children("."+f);l.on("click",'input[same="layuiTreeCheck"]+',function(r){layui.stope(r);var l=i(this).prev(),c=l.prop("checked");l.prop("disabled")||(n.setCheckbox(e,a,l),t.oncheck&&t.oncheck({elem:e,checked:c,data:a}))})},b.prototype.operate=function(e,a){var t=this,r=t.config,l=e.children("."+p),d=l.children("."+f);l.children(".layui-tree-btnGroup").on("click",".layui-icon",function(l){layui.stope(l);var f=i(this).data("type"),b=e.children("."+v),g={data:a,type:f,elem:e};if("add"==f){b[0]||(r.showLine?(d.find("."+o).addClass("layui-tree-icon"),d.find("."+o).children(".layui-icon").addClass(h).removeClass("layui-icon-file")):d.find(".layui-tree-iconArrow").removeClass(c),e.append('
                      '));var w=r.operate&&r.operate(g),N={};if(N.title=r.text.defaultNodeName,N.id=w,t.tree(e.children("."+v),[N]),r.showLine)if(b[0])b.hasClass(x)||b.addClass(x),e.find("."+v).each(function(){i(this).children("."+s).last().addClass(k)}),b.children("."+s).last().prev().hasClass(k)?b.children("."+s).last().prev().removeClass(k):b.children("."+s).last().removeClass(k),!e.parent("."+v)[0]&&e.next()[0]&&b.children("."+s).last().removeClass(k);else{var T=e.siblings("."+s),L=1,I=e.parent("."+v);layui.each(T,function(e,a){i(a).children("."+v)[0]||(L=0)}),1==L?(T.children("."+v).addClass(m),T.children("."+v).children("."+s).removeClass(k),e.children("."+v).addClass(m),I.removeClass(x),I.children("."+s).last().children("."+v).children("."+s).last().addClass(k)):e.children("."+v).children("."+s).addClass(k)}if(!r.showCheckbox)return;if(d.find('input[same="layuiTreeCheck"]')[0].checked){var A=e.children("."+v).children("."+s).last();A.find('input[same="layuiTreeCheck"]')[0].checked=!0}t.renderForm("checkbox")}else if("update"==f){var F=d.children("."+y).html();d.children("."+y).html(""),d.append(''),d.children(".layui-tree-editInput").val(F).focus();var j=function(e){var i=e.val().trim();i=i?i:r.text.defaultNodeName,e.remove(),d.children("."+y).html(i),g.data.title=i,r.operate&&r.operate(g)};d.children(".layui-tree-editInput").blur(function(){j(i(this))}),d.children(".layui-tree-editInput").on("keydown",function(e){13===e.keyCode&&(e.preventDefault(),j(i(this)))})}else n.confirm('\u786e\u8ba4\u5220\u9664\u8be5\u8282\u70b9 "'+(a.title||"")+'" \u5417\uff1f',function(a){if(r.operate&&r.operate(g),g.status="remove",n.close(a),!e.prev("."+s)[0]&&!e.next("."+s)[0]&&!e.parent("."+v)[0])return e.remove(),void t.elem.append(t.elemNone);if(e.siblings("."+s).children("."+p)[0]){if(r.showCheckbox){var l=function(e){if(e.parents("."+s)[0]){var a=e.siblings("."+s).children("."+p),n=e.parent("."+v).prev(),r=n.find('input[same="layuiTreeCheck"]')[0],c=1,d=0;0==r.checked&&(a.each(function(e,a){var n=i(a).find('input[same="layuiTreeCheck"]')[0];0!=n.checked||n.disabled||(c=0),n.disabled||(d=1)}),1==c&&1==d&&(r.checked=!0,t.renderForm("checkbox"),l(n.parent("."+s))))}};l(e)}if(r.showLine){var d=e.siblings("."+s),h=1,f=e.parent("."+v);layui.each(d,function(e,a){i(a).children("."+v)[0]||(h=0)}),1==h?(b[0]||(f.removeClass(x),d.children("."+v).addClass(m),d.children("."+v).children("."+s).removeClass(k)),e.next()[0]?f.children("."+s).last().children("."+v).children("."+s).last().addClass(k):e.prev().children("."+v).children("."+s).last().addClass(k),e.next()[0]||e.parents("."+s)[1]||e.parents("."+s).eq(0).next()[0]||e.prev("."+s).addClass(k)):!e.next()[0]&&e.hasClass(k)&&e.prev().addClass(k)}}else{var y=e.parent("."+v).prev();if(r.showLine){y.find("."+o).removeClass("layui-tree-icon"),y.find("."+o).children(".layui-icon").removeClass(u).addClass("layui-icon-file");var w=y.parents("."+v).eq(0);w.addClass(x),w.children("."+s).each(function(){i(this).children("."+v).children("."+s).last().addClass(k)})}else y.find(".layui-tree-iconArrow").addClass(c);e.parents("."+s).eq(0).removeClass(C),e.parent("."+v).remove()}e.remove()})})},b.prototype.events=function(){var e=this,a=e.config;e.elem.find(".layui-tree-checkedFirst");e.setChecked(e.checkids),e.elem.find(".layui-tree-search").on("keyup",function(){var n=i(this),t=n.val(),r=n.nextAll(),l=[];r.find("."+y).each(function(){var e=i(this).parents("."+p);if(i(this).html().indexOf(t)!=-1){l.push(i(this).parent());var a=function(e){e.addClass("layui-tree-searchShow"),e.parent("."+v)[0]&&a(e.parent("."+v).parent("."+s))};a(e.parent("."+s))}}),r.find("."+p).each(function(){var e=i(this).parent("."+s);e.hasClass("layui-tree-searchShow")||e.addClass(c)}),0==r.find(".layui-tree-searchShow").length&&e.elem.append(e.elemNone),a.onsearch&&a.onsearch({elem:l})}),e.elem.find(".layui-tree-search").on("keydown",function(){i(this).nextAll().find("."+p).each(function(){var e=i(this).parent("."+s);e.removeClass("layui-tree-searchShow "+c)}),i(".layui-tree-emptyText")[0]&&i(".layui-tree-emptyText").remove()})},b.prototype.getChecked=function(){var e=this,a=e.config,n=[],t=[];e.elem.find(".layui-form-checked").each(function(){n.push(i(this).prev()[0].value)});var r=function(e,a){layui.each(e,function(e,t){layui.each(n,function(e,n){if(t.id==n){var l=i.extend({},t);return delete l.children,a.push(l),t.children&&(l.children=[],r(t.children,l.children)),!0}})})};return r(i.extend({},a.data),t),t},b.prototype.setChecked=function(e){var a=this;a.config;a.elem.find("."+s).each(function(a,n){var t=i(this).data("id"),r=i(n).children("."+p).find('input[same="layuiTreeCheck"]'),l=r.next();if("number"==typeof e){if(t==e)return r[0].checked||l.click(),!1}else"object"==typeof e&&layui.each(e,function(e,i){if(i==t&&!r[0].checked)return l.click(),!0})})},l.that={},l.config={},r.reload=function(e,i){var a=l.that[e];return a.reload(i),l.call(a)},r.getChecked=function(e){var i=l.that[e];return i.getChecked()},r.setChecked=function(e,i){var a=l.that[e];return a.setChecked(i)},r.render=function(e){var i=new b(e);return l.call(i)},e(t,r)});layui.define(["laytpl","form"],function(e){"use strict";var a=layui.$,t=layui.laytpl,i=layui.form,n="transfer",l={config:{},index:layui[n]?layui[n].index+1e4:0,set:function(e){var t=this;return t.config=a.extend({},t.config,e),t},on:function(e,a){return layui.onevent.call(this,n,e,a)}},r=function(){var e=this,a=e.config,t=a.id||e.index;return r.that[t]=e,r.config[t]=a,{config:a,reload:function(a){e.reload.call(e,a)},getData:function(){return e.getData.call(e)}}},c="layui-hide",o="layui-btn-disabled",d="layui-none",s="layui-transfer-box",u="layui-transfer-header",h="layui-transfer-search",f="layui-transfer-active",y="layui-transfer-data",p=function(e){return e=e||{},['
                      ','
                      ','","
                      ","{{# if(d.data.showSearch){ }}",'","{{# } }}",'
                        ',"
                        "].join("")},v=['
                        ',p({index:0,checkAllName:"layTransferLeftCheckAll"}),'
                        ','",'","
                        ",p({index:1,checkAllName:"layTransferRightCheckAll"}),"
                        "].join(""),x=function(e){var t=this;t.index=++l.index,t.config=a.extend({},t.config,l.config,e),t.render()};x.prototype.config={title:["\u5217\u8868\u4e00","\u5217\u8868\u4e8c"],width:200,height:360,data:[],value:[],showSearch:!1,id:"",text:{none:"\u65e0\u6570\u636e",searchNone:"\u65e0\u5339\u914d\u6570\u636e"}},x.prototype.reload=function(e){var t=this;t.config=a.extend({},t.config,e),t.render()},x.prototype.render=function(){var e=this,i=e.config,n=e.elem=a(t(v).render({data:i,index:e.index})),l=i.elem=a(i.elem);l[0]&&(i.data=i.data||[],i.value=i.value||[],e.key=i.id||e.index,l.html(e.elem),e.layBox=e.elem.find("."+s),e.layHeader=e.elem.find("."+u),e.laySearch=e.elem.find("."+h),e.layData=n.find("."+y),e.layBtn=n.find("."+f+" .layui-btn"),e.layBox.css({width:i.width,height:i.height}),e.layData.css({height:function(){return i.height-e.layHeader.outerHeight()-e.laySearch.outerHeight()-2}()}),e.renderData(),e.events())},x.prototype.renderData=function(){var e=this,a=(e.config,[{checkName:"layTransferLeftCheck",views:[]},{checkName:"layTransferRightCheck",views:[]}]);e.parseData(function(e){var t=e.selected?1:0,i=["
                      • ",'',"
                      • "].join("");a[t].views.push(i),delete e.selected}),e.layData.eq(0).html(a[0].views.join("")),e.layData.eq(1).html(a[1].views.join("")),e.renderCheckBtn()},x.prototype.renderForm=function(e){i.render(e,"LAY-transfer-"+this.index)},x.prototype.renderCheckBtn=function(e){var t=this,i=t.config;e=e||{},t.layBox.each(function(n){var l=a(this),r=l.find("."+y),d=l.find("."+u).find('input[type="checkbox"]'),s=r.find('input[type="checkbox"]'),h=0,f=!1;if(s.each(function(){var e=a(this).data("hide");(this.checked||this.disabled||e)&&h++,this.checked&&!e&&(f=!0)}),d.prop("checked",f&&h===s.length),t.layBtn.eq(n)[f?"removeClass":"addClass"](o),!e.stopNone){var p=r.children("li:not(."+c+")").length;t.noneView(r,p?"":i.text.none)}}),t.renderForm("checkbox")},x.prototype.noneView=function(e,t){var i=a('

                        '+(t||"")+"

                        ");e.find("."+d)[0]&&e.find("."+d).remove(),t.replace(/\s/g,"")&&e.append(i)},x.prototype.setValue=function(){var e=this,t=e.config,i=[];return e.layBox.eq(1).find("."+y+' input[type="checkbox"]').each(function(){var e=a(this).data("hide");e||i.push(this.value)}),t.value=i,e},x.prototype.parseData=function(e){var t=this,i=t.config,n=[];return layui.each(i.data,function(t,l){l=("function"==typeof i.parseData?i.parseData(l):l)||l,n.push(l=a.extend({},l)),layui.each(i.value,function(e,a){a==l.value&&(l.selected=!0)}),e&&e(l)}),i.data=n,t},x.prototype.getData=function(e){var a=this,t=a.config,i=[];return a.setValue(),layui.each(e||t.value,function(e,a){layui.each(t.data,function(e,t){delete t.selected,a==t.value&&i.push(t)})}),i},x.prototype.events=function(){var e=this,t=e.config;e.elem.on("click",'input[lay-filter="layTransferCheckbox"]+',function(){var t=a(this).prev(),i=t[0].checked,n=t.parents("."+s).eq(0).find("."+y);t[0].disabled||("all"===t.attr("lay-type")&&n.find('input[type="checkbox"]').each(function(){this.disabled||(this.checked=i)}),e.renderCheckBtn({stopNone:!0}))}),e.layBtn.on("click",function(){var i=a(this),n=i.data("index"),l=e.layBox.eq(n),r=[];if(!i.hasClass(o)){e.layBox.eq(n).each(function(t){var i=a(this),n=i.find("."+y);n.children("li").each(function(){var t=a(this),i=t.find('input[type="checkbox"]'),n=i.data("hide");i[0].checked&&!n&&(i[0].checked=!1,l.siblings("."+s).find("."+y).append(t.clone()),t.remove(),r.push(i[0].value)),e.setValue()})}),e.renderCheckBtn();var c=l.siblings("."+s).find("."+h+" input");""===c.val()||c.trigger("keyup"),t.onchange&&t.onchange(e.getData(r),n)}}),e.laySearch.find("input").on("keyup",function(){var i=this.value,n=a(this).parents("."+h).eq(0).siblings("."+y),l=n.children("li");l.each(function(){var e=a(this),t=e.find('input[type="checkbox"]'),n=t[0].title.indexOf(i)!==-1;e[n?"removeClass":"addClass"](c),t.data("hide",!n)}),e.renderCheckBtn();var r=l.length===n.children("li."+c).length;e.noneView(n,r?t.text.searchNone:"")})},r.that={},r.config={},l.reload=function(e,a){var t=r.that[e];return t.reload(a),r.call(t)},l.getData=function(e){var a=r.that[e];return a.getData()},l.render=function(e){var a=new x(e);return r.call(a)},e(n,l)});layui.define(["lay","laytpl","laypage","layer","form","util"],function(e){"use strict";var t=layui.$,i=(layui.lay,layui.laytpl),a=layui.laypage,l=layui.layer,n=layui.form,o=layui.util,r=layui.hint(),d=layui.device(),c={config:{checkName:"LAY_CHECKED",indexName:"LAY_TABLE_INDEX"},cache:{},index:layui.table?layui.table.index+1e4:0,set:function(e){var i=this;return i.config=t.extend({},i.config,e),i},on:function(e,t){return layui.onevent.call(this,h,e,t)}},s=function(){var e=this,t=e.config,i=t.id||t.index;return i&&(s.that[i]=e,s.config[i]=t),{config:t,reload:function(t,i){e.reload.call(e,t,i)},setColsWidth:function(){e.setColsWidth.call(e)},resize:function(){e.resize.call(e)}}},u=function(e){var t=s.config[e];return t||r.error(e?"The table instance with ID '"+e+"' not found":"ID argument required"),t||null},y=function(e,a,l,n){var r=this.config||{};r.escape&&(a=o.escape(a));var d=e.templet?function(){return"function"==typeof e.templet?e.templet(l):i(t(e.templet).html()||String(a)).render(l)}():a;return n?t("
                        "+d+"
                        ").text():d},h="table",f=".layui-table",p="layui-hide",v="layui-none",m="layui-table-view",g=".layui-table-tool",b=".layui-table-box",x=".layui-table-init",k=".layui-table-header",C=".layui-table-body",w=".layui-table-main",T=".layui-table-fixed",N=".layui-table-fixed-l",L=".layui-table-fixed-r",S=".layui-table-total",_=".layui-table-page",A=".layui-table-sort",R="layui-table-edit",W="layui-table-hover",z=function(e){var t='{{#if(item2.colspan){}} colspan="{{item2.colspan}}"{{#} if(item2.rowspan){}} rowspan="{{item2.rowspan}}"{{#}}}';return e=e||{},['',"","{{# layui.each(d.data.cols, function(i1, item1){ }}","","{{# layui.each(item1, function(i2, item2){ }}",'{{# if(item2.fixed && item2.fixed !== "right"){ left = true; } }}','{{# if(item2.fixed === "right"){ right = true; } }}',function(){return e.fixed&&"right"!==e.fixed?'{{# if(item2.fixed && item2.fixed !== "right"){ }}':"right"===e.fixed?'{{# if(item2.fixed === "right"){ }}':""}(),"{{# var isSort = !(item2.colGroup) && item2.sort; }}",'",e.fixed?"{{# }; }}":"","{{# }); }}","","{{# }); }}","","
                        ','
                        ','{{# if(item2.type === "checkbox"){ }}','',"{{# } else { }}",'{{item2.title||""}}',"{{# if(isSort){ }}",'',"{{# } }}","{{# } }}","
                        ","
                        "].join("")},E=['',"","
                        "].join(""),F=['
                        ',"{{# if(d.data.toolbar){ }}",'
                        ','
                        ','
                        ',"
                        ","{{# } }}",'
                        ',"{{# if(d.data.loading){ }}",'
                        ','',"
                        ","{{# } }}","{{# var left, right; }}",'
                        ',z(),"
                        ",'
                        ',E,"
                        ","{{# if(left){ }}",'
                        ','
                        ',z({fixed:!0}),"
                        ",'
                        ',E,"
                        ","
                        ","{{# }; }}","{{# if(right){ }}",'
                        ','
                        ',z({fixed:"right"}),'
                        ',"
                        ",'
                        ',E,"
                        ","
                        ","{{# }; }}","
                        ","{{# if(d.data.totalRow){ }}",'
                        ','','',"
                        ","
                        ","{{# } }}","{{# if(d.data.page){ }}",'
                        ','
                        ',"
                        ","{{# } }}","","
                        "].join(""),I=t(window),j=t(document),H=function(e){var i=this;i.index=++c.index,i.config=t.extend({},i.config,c.config,e),i.render()};H.prototype.config={limit:10,loading:!0,cellMinWidth:60,defaultToolbar:["filter","exports","print"],autoSort:!0,text:{none:"\u65e0\u6570\u636e"}},H.prototype.render=function(){var e=this,a=e.config;if(a.elem=t(a.elem),a.where=a.where||{},a.id=a.id||a.elem.attr("id")||e.index,a.request=t.extend({pageName:"page",limitName:"limit"},a.request),a.response=t.extend({statusName:"code",statusCode:0,msgName:"msg",dataName:"data",totalRowName:"totalRow",countName:"count"},a.response),"object"==typeof a.page&&(a.limit=a.page.limit||a.limit,a.limits=a.page.limits||a.limits,e.page=a.page.curr=a.page.curr||1,delete a.page.elem,delete a.page.jump),!a.elem[0])return e;a.height&&/^full-\d+$/.test(a.height)&&(e.fullHeightGap=a.height.split("-")[1],a.height=I.height()-e.fullHeightGap),e.setInit();var l=a.elem,n=l.next("."+m),o=e.elem=t(i(F).render({VIEW_CLASS:m,data:a,index:e.index}));if(a.index=e.index,e.key=a.id||a.index,n[0]&&n.remove(),l.after(o),e.layTool=o.find(g),e.layBox=o.find(b),e.layHeader=o.find(k),e.layMain=o.find(w),e.layBody=o.find(C),e.layFixed=o.find(T),e.layFixLeft=o.find(N),e.layFixRight=o.find(L),e.layTotal=o.find(S),e.layPage=o.find(_),e.renderToolbar(),e.fullSize(),a.cols.length>1){var r=e.layFixed.find(k).find("th");r.height(e.layHeader.height()-1-parseFloat(r.css("padding-top"))-parseFloat(r.css("padding-bottom")))}e.pullData(e.page),e.events()},H.prototype.initOpts=function(e){var t=this,i=(t.config,{checkbox:48,radio:48,space:15,numbers:40});e.checkbox&&(e.type="checkbox"),e.space&&(e.type="space"),e.type||(e.type="normal"),"normal"!==e.type&&(e.unresize=!0,e.width=e.width||i[e.type])},H.prototype.setInit=function(e){var t=this,i=t.config;return i.clientWidth=i.width||function(){var e=function(t){var a,l;t=t||i.elem.parent(),a=t.width();try{l="none"===t.css("display")}catch(n){}return!t[0]||a&&!l?a:e(t.parent())};return e()}(),"width"===e?i.clientWidth:void layui.each(i.cols,function(e,a){layui.each(a,function(l,n){if(!n)return void a.splice(l,1);if(n.key=e+"-"+l,n.hide=n.hide||!1,n.colGroup||n.colspan>1){var o=0;layui.each(i.cols[e+1],function(t,i){i.HAS_PARENT||o>1&&o==n.colspan||(i.HAS_PARENT=!0,i.parentKey=e+"-"+l,o+=parseInt(i.colspan>1?i.colspan:1))}),n.colGroup=!0}t.initOpts(n)})})},H.prototype.renderToolbar=function(){var e=this,a=e.config,l=['
                        ','
                        ','
                        '].join(""),n=e.layTool.find(".layui-table-tool-temp");if("default"===a.toolbar)n.html(l);else if("string"==typeof a.toolbar){var o=t(a.toolbar).html()||"";o&&n.html(i(o).render(a))}var r={filter:{title:"\u7b5b\u9009\u5217",layEvent:"LAYTABLE_COLS",icon:"layui-icon-cols"},exports:{title:"\u5bfc\u51fa",layEvent:"LAYTABLE_EXPORT",icon:"layui-icon-export"},print:{title:"\u6253\u5370",layEvent:"LAYTABLE_PRINT",icon:"layui-icon-print"}},d=[];"object"==typeof a.defaultToolbar&&layui.each(a.defaultToolbar,function(e,t){var i="string"==typeof t?r[t]:t;i&&d.push('
                        ')}),e.layTool.find(".layui-table-tool-self").html(d.join(""))},H.prototype.setParentCol=function(e,t){var i=this,a=i.config,l=i.layHeader.find('th[data-key="'+a.index+"-"+t+'"]'),n=parseInt(l.attr("colspan"))||0;if(l[0]){var o=t.split("-"),r=a.cols[o[0]][o[1]];e?n--:n++,l.attr("colspan",n),l[n<1?"addClass":"removeClass"](p),r.colspan=n,r.hide=n<1;var d=l.data("parentkey");d&&i.setParentCol(e,d)}},H.prototype.setColsPatch=function(){var e=this,t=e.config;layui.each(t.cols,function(t,i){layui.each(i,function(t,i){i.hide&&e.setParentCol(i.hide,i.parentKey)})})},H.prototype.setColsWidth=function(){var e=this,t=e.config,i=0,a=0,l=0,n=0,o=e.setInit("width");e.eachCols(function(e,t){t.hide||i++}),o=o-function(){return"line"===t.skin||"nob"===t.skin?2:i+1}()-e.getScrollWidth(e.layMain[0])-1;var r=function(e){layui.each(t.cols,function(i,r){layui.each(r,function(i,d){var c=0,s=d.minWidth||t.cellMinWidth;return d?void(d.colGroup||d.hide||(e?l&&ln&&a&&(l=(o-n)/a)};r(),r(!0),e.autoColNums=a,e.eachCols(function(i,a){var n=a.minWidth||t.cellMinWidth;a.colGroup||a.hide||(0===a.width?e.getCssRule(t.index+"-"+a.key,function(e){e.style.width=Math.floor(l>=n?l:n)+"px"}):/\d+%$/.test(a.width)&&e.getCssRule(t.index+"-"+a.key,function(e){e.style.width=Math.floor(parseFloat(a.width)/100*o)+"px"}))});var d=e.layMain.width()-e.getScrollWidth(e.layMain[0])-e.layMain.children("table").outerWidth();if(e.autoColNums&&d>=-i&&d<=i){var c=function(t){var i;return t=t||e.layHeader.eq(0).find("thead th:last-child"),i=t.data("field"),!i&&t.prev()[0]?c(t.prev()):t},s=c(),u=s.data("key");e.getCssRule(u,function(t){var i=t.style.width||s.outerWidth();t.style.width=parseFloat(i)+d+"px",e.layMain.height()-e.layMain.prop("clientHeight")>0&&(t.style.width=parseFloat(t.style.width)-1+"px")})}e.loading(!0)},H.prototype.resize=function(){var e=this;e.fullSize(),e.setColsWidth(),e.scrollPatch()},H.prototype.reload=function(e,i){var a=this;e=e||{},delete a.haveInit,layui.each(e,function(e,t){"array"===layui._typeof(t)&&delete a.config[e]}),a.config=t.extend(i,{},a.config,e),a.render()},H.prototype.errorView=function(e){var i=this,a=i.layMain.find("."+v),l=t('
                        '+(e||"Error")+"
                        ");a[0]&&(i.layNone.remove(),a.remove()),i.layFixed.addClass(p),i.layMain.find("tbody").html(""),i.layMain.append(i.layNone=l),c.cache[i.key]=[]},H.prototype.page=1,H.prototype.pullData=function(e){var i=this,a=i.config,l=a.request,n=a.response,o=function(){"object"==typeof a.initSort&&i.sort(a.initSort.field,a.initSort.type)};if(i.startTime=(new Date).getTime(),a.url){var r={};r[l.pageName]=e,r[l.limitName]=a.limit;var d=t.extend(r,a.where);a.contentType&&0==a.contentType.indexOf("application/json")&&(d=JSON.stringify(d)),i.loading(),t.ajax({type:a.method||"get",url:a.url,contentType:a.contentType,data:d,dataType:"json",headers:a.headers||{},success:function(t){"function"==typeof a.parseData&&(t=a.parseData(t)||t),t[n.statusName]!=n.statusCode?(i.renderForm(),i.errorView(t[n.msgName]||'\u8fd4\u56de\u7684\u6570\u636e\u4e0d\u7b26\u5408\u89c4\u8303\uff0c\u6b63\u786e\u7684\u6210\u529f\u72b6\u6001\u7801\u5e94\u4e3a\uff1a"'+n.statusName+'": '+n.statusCode)):(i.renderData(t,e,t[n.countName]),o(),a.time=(new Date).getTime()-i.startTime+" ms"),i.setColsWidth(),"function"==typeof a.done&&a.done(t,e,t[n.countName])},error:function(e,t){i.errorView("\u8bf7\u6c42\u5f02\u5e38\uff0c\u9519\u8bef\u63d0\u793a\uff1a"+t),i.renderForm(),i.setColsWidth(),"function"==typeof a.error&&a.error(e,t)}})}else if("array"===layui._typeof(a.data)){var c={},s=e*a.limit-a.limit;c[n.dataName]=a.data.concat().splice(s,a.limit),c[n.countName]=a.data.length,"object"==typeof a.totalRow&&(c[n.totalRowName]=t.extend({},a.totalRow)),i.renderData(c,e,c[n.countName]),o(),i.setColsWidth(),"function"==typeof a.done&&a.done(c,e,c[n.countName])}},H.prototype.eachCols=function(e){var t=this;return c.eachCols(null,e,t.config.cols),t},H.prototype.renderData=function(e,n,o,r){var d=this,s=d.config,u=e[s.response.dataName]||[],h=e[s.response.totalRowName],f=[],m=[],g=[],b=function(){var e;return!r&&d.sortKey?d.sort(d.sortKey.field,d.sortKey.sort,!0):(layui.each(u,function(a,l){var o=[],u=[],h=[],v=a+s.limit*(n-1)+1;"array"===layui._typeof(l)&&0===l.length||(r||(l[c.config.indexName]=a),d.eachCols(function(n,r){var f=r.field||n,m=s.index+"-"+r.key,g=l[f];if(void 0!==g&&null!==g||(g=""),!r.colGroup){var b=['','
                        '+function(){var n=t.extend(!0,{LAY_INDEX:v,LAY_COL:r},l),o=c.config.checkName;switch(r.type){case"checkbox":return'";case"radio":return n[o]&&(e=a),'';case"numbers":return v}return r.toolbar?i(t(r.toolbar).html()||"").render(n):y.call(d,r,g,n)}(),"
                        "].join("");o.push(b),r.fixed&&"right"!==r.fixed&&u.push(b),"right"===r.fixed&&h.push(b)}}),f.push(''+o.join("")+""),m.push(''+u.join("")+""),g.push(''+h.join("")+""))}),d.layBody.scrollTop(0),d.layMain.find("."+v).remove(),d.layMain.find("tbody").html(f.join("")),d.layFixLeft.find("tbody").html(m.join("")),d.layFixRight.find("tbody").html(g.join("")),d.renderForm(),"number"==typeof e&&d.setThisRowChecked(e),d.syncCheckAll(),d.haveInit?d.scrollPatch():setTimeout(function(){d.scrollPatch()},50),d.haveInit=!0,l.close(d.tipsIndex),s.HAS_SET_COLS_PATCH||d.setColsPatch(),void(s.HAS_SET_COLS_PATCH=!0))};return c.cache[d.key]=u,d.layPage[0==o||0===u.length&&1==n?"addClass":"removeClass"](p),0===u.length?(d.renderForm(),d.errorView(s.text.none)):(d.layFixed.removeClass(p),r?b():(b(),d.renderTotal(u,h),void(s.page&&(s.page=t.extend({elem:"layui-table-page"+s.index,count:o,limit:s.limit,limits:s.limits||[10,20,30,40,50,60,70,80,90],groups:3,layout:["prev","page","next","skip","count","limit"],prev:'',next:'',jump:function(e,t){t||(d.page=e.curr,s.limit=e.limit,d.pullData(e.curr))}},s.page),s.page.count=o,a.render(s.page)))))},H.prototype.renderTotal=function(e,a){var l=this,n=l.config,o={};if(n.totalRow){layui.each(e,function(e,t){"array"===layui._typeof(t)&&0===t.length||l.eachCols(function(e,i){var a=i.field||e,l=t[a];i.totalRow&&(o[a]=(o[a]||0)+(parseFloat(l)||0))})}),l.dataTotal={};var r=[];l.eachCols(function(e,d){var c=d.field||e,s=function(){var e,t=d.totalRowText||"",i=parseFloat(o[c]).toFixed(2),n={};return n[c]=i,e=d.totalRow?y.call(l,d,i,n)||t:t,a?a[d.field]||e:e}(),u=['','
                        '+function(){var e=d.totalRow||n.totalRow;return"string"==typeof e?i(e).render(t.extend({TOTAL_NUMS:s},d)):s}(),"
                        "].join("");d.field&&(l.dataTotal[c]=s),r.push(u)}),l.layTotal.find("tbody").html(""+r.join("")+"")}},H.prototype.getColElem=function(e,t){var i=this,a=i.config;return e.eq(0).find(".laytable-cell-"+(a.index+"-"+t)+":eq(0)")},H.prototype.renderForm=function(e){var t=this,i=(t.config,t.elem.attr("lay-filter"));n.render(e,i)},H.prototype.setThisRowChecked=function(e){var t=this,i=(t.config,"layui-table-click"),a=t.layBody.find('tr[data-index="'+e+'"]');a.addClass(i).siblings("tr").removeClass(i)},H.prototype.sort=function(e,i,a,l){var n,o,d=this,s={},u=d.config,y=u.elem.attr("lay-filter"),f=c.cache[d.key];"string"==typeof e&&(n=e,d.layHeader.find("th").each(function(i,a){var l=t(this),o=l.data("field");if(o===e)return e=l,n=o,!1}));try{var n=n||e.data("field"),p=e.data("key");if(d.sortKey&&!a&&n===d.sortKey.field&&i===d.sortKey.sort)return;var v=d.layHeader.find("th .laytable-cell-"+p).find(A);d.layHeader.find("th").find(A).removeAttr("lay-sort"),v.attr("lay-sort",i||null),d.layFixed.find("th")}catch(m){r.error("Table modules: sort field '"+n+"' not matched")}d.sortKey={field:n,sort:i},u.autoSort&&("asc"===i?o=layui.sort(f,n):"desc"===i?o=layui.sort(f,n,!0):(o=layui.sort(f,c.config.indexName),delete d.sortKey)),s[u.response.dataName]=o||f,d.renderData(s,d.page,d.count,!0),l&&layui.event.call(e,h,"sort("+y+")",{field:n,type:i})},H.prototype.loading=function(e){var i=this,a=i.config;a.loading&&(e?(i.layInit&&i.layInit.remove(),delete i.layInit,i.layBox.find(x).remove()):(i.layInit=t(['
                        ','',"
                        "].join("")),i.layBox.append(i.layInit)))},H.prototype.setCheckData=function(e,t){var i=this,a=i.config,l=c.cache[i.key];l[e]&&"array"!==layui._typeof(l[e])&&(l[e][a.checkName]=t)},H.prototype.syncCheckAll=function(){var e=this,t=e.config,i=e.layHeader.find('input[name="layTableCheckbox"]'),a=function(i){return e.eachCols(function(e,a){"checkbox"===a.type&&(a[t.checkName]=i)}),i};i[0]&&(c.checkStatus(e.key).isAll?(i[0].checked||(i.prop("checked",!0),e.renderForm("checkbox")),a(!0)):(i[0].checked&&(i.prop("checked",!1),e.renderForm("checkbox")),a(!1)))},H.prototype.getCssRule=function(e,t){var i=this,a=i.elem.find("style")[0],l=a.sheet||a.styleSheet||{},n=l.cssRules||l.rules;layui.each(n,function(i,a){if(a.selectorText===".laytable-cell-"+e)return t(a),!0})},H.prototype.fullSize=function(){var e,t=this,i=t.config,a=i.height;t.fullHeightGap&&(a=I.height()-t.fullHeightGap,a<135&&(a=135),t.elem.css("height",a)),a&&(e=parseFloat(a)-(t.layHeader.outerHeight()||38),i.toolbar&&(e-=t.layTool.outerHeight()||50),i.totalRow&&(e-=t.layTotal.outerHeight()||40),i.page&&(e-=t.layPage.outerHeight()||41),t.layMain.css("height",e-2))},H.prototype.getScrollWidth=function(e){var t=0;return e?t=e.offsetWidth-e.clientWidth:(e=document.createElement("div"),e.style.width="100px",e.style.height="100px",e.style.overflowY="scroll",document.body.appendChild(e),t=e.offsetWidth-e.clientWidth,document.body.removeChild(e)),t},H.prototype.scrollPatch=function(){var e=this,i=e.layMain.children("table"),a=e.layMain.width()-e.layMain.prop("clientWidth"),l=e.layMain.height()-e.layMain.prop("clientHeight"),n=(e.getScrollWidth(e.layMain[0]),i.outerWidth()-e.layMain.width()),o=function(e){if(a&&l){if(e=e.eq(0),!e.find(".layui-table-patch")[0]){var i=t('
                        ');i.find("div").css({width:a}),e.find("tr").append(i)}}else e.find(".layui-table-patch").remove()};o(e.layHeader),o(e.layTotal);var r=e.layMain.height(),d=r-l;e.layFixed.find(C).css("height",i.height()>=d?d:"auto"),e.layFixRight[n>0?"removeClass":"addClass"](p),e.layFixRight.css("right",a-1)},H.prototype.events=function(){var e,i=this,a=i.config,o=t("body"),r={},s=i.layHeader.find("th"),u=".layui-table-cell",f=a.elem.attr("lay-filter");i.layTool.on("click","*[lay-event]",function(e){var o=t(this),r=o.attr("lay-event"),s=function(e){var l=t(e.list),n=t('
                          ');n.html(l),a.height&&n.css("max-height",a.height-(i.layTool.outerHeight()||50)),o.find(".layui-table-tool-panel")[0]||o.append(n),i.renderForm(),n.on("click",function(e){layui.stope(e)}),e.done&&e.done(n,l)};switch(layui.stope(e),j.trigger("table.tool.panel.remove"),l.close(i.tipsIndex),r){case"LAYTABLE_COLS":s({list:function(){var e=[];return i.eachCols(function(t,i){i.field&&"normal"==i.type&&e.push('
                        • ')}),e.join("")}(),done:function(){n.on("checkbox(LAY_TABLE_TOOL_COLS)",function(e){var l=t(e.elem),n=this.checked,o=l.data("key"),r=l.data("parentkey");layui.each(a.cols,function(e,t){layui.each(t,function(t,l){if(e+"-"+t===o){var d=l.hide;l.hide=!n,i.elem.find('*[data-key="'+a.index+"-"+o+'"]')[n?"removeClass":"addClass"](p),d!=l.hide&&i.setParentCol(!n,r),i.resize()}})})})}});break;case"LAYTABLE_EXPORT":d.ie?l.tips("\u5bfc\u51fa\u529f\u80fd\u4e0d\u652f\u6301 IE\uff0c\u8bf7\u7528 Chrome \u7b49\u9ad8\u7ea7\u6d4f\u89c8\u5668\u5bfc\u51fa",this,{tips:3}):s({list:function(){return['
                        • \u5bfc\u51fa\u5230 Csv \u6587\u4ef6
                        • ','
                        • \u5bfc\u51fa\u5230 Excel \u6587\u4ef6
                        • '].join("")}(),done:function(e,l){l.on("click",function(){var e=t(this).data("type");c.exportFile.call(i,a.id,null,e)})}});break;case"LAYTABLE_PRINT":var u=window.open("\u6253\u5370\u7a97\u53e3","_blank"),y=[""].join(""),v=t(i.layHeader.html());v.append(i.layMain.find("table").html()),v.append(i.layTotal.find("table").html()),v.find("th.layui-table-patch").remove(),v.find(".layui-table-col-special").remove(),u.document.write(y+v.prop("outerHTML")),u.document.close(),u.print(),u.close()}layui.event.call(this,h,"toolbar("+f+")",t.extend({event:r,config:a},{}))}),s.on("mousemove",function(e){var i=t(this),a=i.offset().left,l=e.clientX-a;i.data("unresize")||r.resizeStart||(r.allowResize=i.width()-l<=10,o.css("cursor",r.allowResize?"col-resize":""))}).on("mouseleave",function(){t(this);r.resizeStart||o.css("cursor","")}).on("mousedown",function(e){var l=t(this);if(r.allowResize){var n=l.data("key");e.preventDefault(),r.resizeStart=!0,r.offset=[e.clientX,e.clientY],i.getCssRule(n,function(e){var t=e.style.width||l.outerWidth();r.rule=e,r.ruleWidth=parseFloat(t),r.minWidth=l.data("minwidth")||a.cellMinWidth})}}),j.on("mousemove",function(t){if(r.resizeStart){if(t.preventDefault(),r.rule){var a=r.ruleWidth+t.clientX-r.offset[0];a');return n[0].value=i.data("content")||l.text(),i.find("."+R)[0]||i.append(n),n.focus(),void layui.stope(e)}}).on("mouseenter","td",function(){b.call(this)}).on("mouseleave","td",function(){b.call(this,"hide")});var g="layui-table-grid-down",b=function(e){var i=t(this),a=i.children(u);if(!i.data("off"))if(e)i.find(".layui-table-grid-down").remove();else if(a.prop("scrollWidth")>a.outerWidth()){if(a.find("."+g)[0])return;i.append('
                          ')}};i.layBody.on("click","."+g,function(e){var n=t(this),o=n.parent(),r=o.children(u);i.tipsIndex=l.tips(['
                          ',r.html(),"
                          ",''].join(""),r[0],{tips:[3,""],time:-1,anim:-1,maxWidth:d.ios||d.android?300:i.elem.width()/2,isOutAnim:!1,skin:"layui-table-tips",success:function(e,t){e.find(".layui-table-tips-c").on("click",function(){l.close(t)})}}),layui.stope(e)}),i.layBody.on("click","*[lay-event]",function(){var e=t(this),a=e.parents("tr").eq(0).data("index");layui.event.call(this,h,"tool("+f+")",v.call(this,{event:e.attr("lay-event")})),i.setThisRowChecked(a)}),i.layMain.on("scroll",function(){var e=t(this),a=e.scrollLeft(),n=e.scrollTop();i.layHeader.scrollLeft(a),i.layTotal.scrollLeft(a),i.layFixed.find(C).scrollTop(n),l.close(i.tipsIndex)}),I.on("resize",function(){i.resize()})},function(){j.on("click",function(){j.trigger("table.remove.tool.panel")}),j.on("table.remove.tool.panel",function(){t(".layui-table-tool-panel").remove()})}(),c.init=function(e,i){i=i||{};var a=this,l=t(e?'table[lay-filter="'+e+'"]':f+"[lay-data]"),n="Table element property lay-data configuration item has a syntax error: ";return l.each(function(){var a=t(this),l=a.attr("lay-data");try{l=new Function("return "+l)()}catch(o){r.error(n+l,"error")}var d=[],s=t.extend({elem:this,cols:[],data:[],skin:a.attr("lay-skin"),size:a.attr("lay-size"),even:"string"==typeof a.attr("lay-even")},c.config,i,l);e&&a.hide(),a.find("thead>tr").each(function(e){s.cols[e]=[],t(this).children().each(function(i){var a=t(this),l=a.attr("lay-data");try{l=new Function("return "+l)()}catch(o){return r.error(n+l)}var c=t.extend({title:a.text(),colspan:a.attr("colspan")||0,rowspan:a.attr("rowspan")||0},l);c.colspan<2&&d.push(c),s.cols[e].push(c)})}),a.find("tbody>tr").each(function(e){var i=t(this),a={};i.children("td").each(function(e,i){var l=t(this),n=l.data("field");if(n)return a[n]=l.html()}),layui.each(d,function(e,t){var l=i.children("td").eq(e);a[t.field]=l.html()}),s.data[e]=a}),c.render(s)}),a},s.that={},s.config={},c.eachCols=function(e,i,a){var l=s.config[e]||{},n=[],o=0;a=t.extend(!0,[],a||l.cols),layui.each(a,function(e,t){layui.each(t,function(t,i){if(i.colGroup){var l=0;o++,i.CHILD_COLS=[],layui.each(a[e+1],function(e,t){t.PARENT_COL_INDEX||l>1&&l==i.colspan||(t.PARENT_COL_INDEX=o,i.CHILD_COLS.push(t),l+=parseInt(t.colspan>1?t.colspan:1))})}i.PARENT_COL_INDEX||n.push(i)})});var r=function(e){layui.each(e||n,function(e,t){return t.CHILD_COLS?r(t.CHILD_COLS):void("function"==typeof i&&i(e,t))})};r()},c.checkStatus=function(e){var t=0,i=0,a=[],l=c.cache[e]||[];return layui.each(l,function(e,l){return"array"===layui._typeof(l)?void i++:void(l[c.config.checkName]&&(t++,a.push(c.clearCacheKey(l))))}),{data:a,isAll:!!l.length&&t===l.length-i}},c.getData=function(e){var t=[],i=c.cache[e]||[];return layui.each(i,function(e,i){"array"!==layui._typeof(i)&&t.push(c.clearCacheKey(i))}),t},c.exportFile=function(e,t,i){var a=this;t=t||c.clearCacheKey(c.cache[e]),i=i||"csv";var l=s.that[e],n=s.config[e]||{},o={csv:"text/csv",xls:"application/vnd.ms-excel"}[i],u=document.createElement("a");return d.ie?r.error("IE_NOT_SUPPORT_EXPORTS"):(u.href="data:"+o+";charset=utf-8,\ufeff"+encodeURIComponent(function(){var i=[],n=[],o=[];return layui.each(t,function(t,a){var o=[];"object"==typeof e?(layui.each(e,function(e,a){0==t&&i.push(a||"")}),layui.each(c.clearCacheKey(a),function(e,t){o.push('"'+(t||"")+'"')})):c.eachCols(e,function(e,n){if(n.field&&"normal"==n.type&&!n.hide){ +var r=a[n.field];void 0!==r&&null!==r||(r=""),0==t&&i.push(n.title||""),o.push('"'+y.call(l,n,r,a,"text")+'"')}}),n.push(o.join(","))}),layui.each(a.dataTotal,function(e,t){o.push(t)}),i.join(",")+"\r\n"+n.join("\r\n")+"\r\n"+o.join(",")}()),u.download=(n.title||"table_"+(n.index||""))+"."+i,document.body.appendChild(u),u.click(),void document.body.removeChild(u))},c.resize=function(e){if(e){var t=u(e);if(!t)return;s.that[e].resize()}else layui.each(s.that,function(){this.resize()})},c.reload=function(e,t,i){var a=u(e);if(a){var l=s.that[e];return l.reload(t,i),s.call(l)}},c.render=function(e){var t=new H(e);return s.call(t)},c.clearCacheKey=function(e){return e=t.extend({},e),delete e[c.config.checkName],delete e[c.config.indexName],e},t(function(){c.init()}),e(h,c)});layui.define("jquery",function(e){"use strict";var i=layui.$,n=(layui.hint(),layui.device(),{config:{},set:function(e){var n=this;return n.config=i.extend({},n.config,e),n},on:function(e,i){return layui.onevent.call(this,t,e,i)}}),t="carousel",a="layui-this",l=">*[carousel-item]>*",o="layui-carousel-left",r="layui-carousel-right",d="layui-carousel-prev",s="layui-carousel-next",u="layui-carousel-arrow",c="layui-carousel-ind",m=function(e){var t=this;t.config=i.extend({},t.config,n.config,e),t.render()};m.prototype.config={width:"600px",height:"280px",full:!1,arrow:"hover",indicator:"inside",autoplay:!0,interval:3e3,anim:"",trigger:"click",index:0},m.prototype.render=function(){var e=this,n=e.config;n.elem=i(n.elem),n.elem[0]&&(e.elemItem=n.elem.find(l),n.index<0&&(n.index=0),n.index>=e.elemItem.length&&(n.index=e.elemItem.length-1),n.interval<800&&(n.interval=800),n.full?n.elem.css({position:"fixed",width:"100%",height:"100%",zIndex:9999}):n.elem.css({width:n.width,height:n.height}),n.elem.attr("lay-anim",n.anim),e.elemItem.eq(n.index).addClass(a),e.elemItem.length<=1||(e.indicator(),e.arrow(),e.autoplay(),e.events()))},m.prototype.reload=function(e){var n=this;clearInterval(n.timer),n.config=i.extend({},n.config,e),n.render()},m.prototype.prevIndex=function(){var e=this,i=e.config,n=i.index-1;return n<0&&(n=e.elemItem.length-1),n},m.prototype.nextIndex=function(){var e=this,i=e.config,n=i.index+1;return n>=e.elemItem.length&&(n=0),n},m.prototype.addIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index+e,n.index>=i.elemItem.length&&(n.index=0)},m.prototype.subIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index-e,n.index<0&&(n.index=i.elemItem.length-1)},m.prototype.autoplay=function(){var e=this,i=e.config;i.autoplay&&(clearInterval(e.timer),e.timer=setInterval(function(){e.slide()},i.interval))},m.prototype.arrow=function(){var e=this,n=e.config,t=i(['",'"].join(""));n.elem.attr("lay-arrow",n.arrow),n.elem.find("."+u)[0]&&n.elem.find("."+u).remove(),n.elem.append(t),t.on("click",function(){var n=i(this),t=n.attr("lay-type");e.slide(t)})},m.prototype.indicator=function(){var e=this,n=e.config,t=e.elemInd=i(['
                            ',function(){var i=[];return layui.each(e.elemItem,function(e){i.push("")}),i.join("")}(),"
                          "].join(""));n.elem.attr("lay-indicator",n.indicator),n.elem.find("."+c)[0]&&n.elem.find("."+c).remove(),n.elem.append(t),"updown"===n.anim&&t.css("margin-top",-(t.height()/2)),t.find("li").on("hover"===n.trigger?"mouseover":n.trigger,function(){var t=i(this),a=t.index();a>n.index?e.slide("add",a-n.index):al.length&&(l.value=l.length),parseInt(l.value)!==l.value&&(l.half||(l.value=Math.ceil(l.value)-l.value<.5?Math.ceil(l.value):Math.floor(l.value)));for(var n='
                            ",s=1;s<=l.length;s++){var r='
                          • ";l.half&&parseInt(l.value)!==l.value&&s==Math.ceil(l.value)?n=n+'
                          • ":n+=r}n+="
                          "+(l.text?''+l.value+"\u661f":"")+"";var c=l.elem,f=c.next("."+t);f[0]&&f.remove(),e.elemTemp=a(n),l.span=e.elemTemp.next("span"),l.setText&&l.setText(l.value),c.html(e.elemTemp),c.addClass("layui-inline"),l.readonly||e.action()},v.prototype.setvalue=function(e){var a=this,l=a.config;l.value=e,a.render()},v.prototype.action=function(){var e=this,l=e.config,i=e.elemTemp,n=i.find("i").width();i.children("li").each(function(e){var t=e+1,v=a(this);v.on("click",function(e){if(l.value=t,l.half){var o=e.pageX-a(this).offset().left;o<=n/2&&(l.value=l.value-.5)}l.text&&i.next("span").text(l.value+"\u661f"),l.choose&&l.choose(l.value),l.setText&&l.setText(l.value)}),v.on("mousemove",function(e){if(i.find("i").each(function(){a(this).addClass(o).removeClass(r)}),i.find("i:lt("+t+")").each(function(){a(this).addClass(u).removeClass(f)}),l.half){var c=e.pageX-a(this).offset().left;c<=n/2&&v.children("i").addClass(s).removeClass(u)}}),v.on("mouseleave",function(){i.find("i").each(function(){a(this).addClass(o).removeClass(r)}),i.find("i:lt("+Math.floor(l.value)+")").each(function(){a(this).addClass(u).removeClass(f)}),l.half&&parseInt(l.value)!==l.value&&i.children("li:eq("+Math.floor(l.value)+")").children("i").addClass(s).removeClass(c)})})},v.prototype.events=function(){var e=this;e.config},l.render=function(e){var a=new v(e);return i.call(a)},e(n,l)});layui.define("jquery",function(e){"use strict";var l=layui.$,o=function(e){},t='';o.prototype.load=function(e){var o,i,n,r,a=this,c=0;e=e||{};var m=l(e.elem);if(m[0]){var f=l(e.scrollElem||document),u=e.mb||50,s=!("isAuto"in e)||e.isAuto,y=e.end||"\u6ca1\u6709\u66f4\u591a\u4e86",v=e.scrollElem&&e.scrollElem!==document,d="\u52a0\u8f7d\u66f4\u591a",h=l('");m.find(".layui-flow-more")[0]||m.append(h);var p=function(e,t){e=l(e),h.before(e),t=0==t||null,t?h.html(y):h.find("a").html(d),i=t,o=null,n&&n()},g=function(){o=!0,h.find("a").html(t),"function"==typeof e.done&&e.done(++c,p)};if(g(),h.find("a").on("click",function(){l(this);i||o||g()}),e.isLazyimg)var n=a.lazyimg({elem:e.elem+" img",scrollElem:e.scrollElem});return s?(f.on("scroll",function(){var e=l(this),t=e.scrollTop();r&&clearTimeout(r),!i&&m.width()&&(r=setTimeout(function(){var i=v?e.height():l(window).height(),n=v?e.prop("scrollHeight"):document.documentElement.scrollHeight;n-t-i<=u&&(o||g())},100))}),a):a}},o.prototype.lazyimg=function(e){var o,t=this,i=0;e=e||{};var n=l(e.scrollElem||document),r=e.elem||"img",a=e.scrollElem&&e.scrollElem!==document,c=function(e,l){var o=n.scrollTop(),r=o+l,c=a?function(){return e.offset().top-n.offset().top+o}():e.offset().top;if(c>=o&&c<=r&&e.attr("lay-src")){var f=e.attr("lay-src");layui.img(f,function(){var l=t.lazyimg.elem.eq(i);e.attr("src",f).removeAttr("lay-src"),l[0]&&m(l),i++},function(){t.lazyimg.elem.eq(i);e.removeAttr("lay-src")})}},m=function(e,o){var m=a?(o||n).height():l(window).height(),f=n.scrollTop(),u=f+m;if(t.lazyimg.elem=l(r),e)c(e,m);else for(var s=0;su)break}};if(m(),!o){var f;n.on("scroll",function(){var e=l(this);f&&clearTimeout(f),f=setTimeout(function(){m(null,e)},50)}),o=!0}return m},e("flow",new o)});layui.define(["layer","form"],function(t){"use strict";var e=layui.$,i=layui.layer,a=layui.form,l=(layui.hint(),layui.device()),n="layedit",o="layui-show",r="layui-disabled",c=function(){var t=this;t.index=0,t.config={tool:["strong","italic","underline","del","|","left","center","right","|","link","unlink","face","image"],hideTool:[],height:280}};c.prototype.set=function(t){var i=this;return e.extend(!0,i.config,t),i},c.prototype.on=function(t,e){return layui.onevent(n,t,e)},c.prototype.build=function(t,i){i=i||{};var a=this,n=a.config,r="layui-layedit",c=e("string"==typeof t?"#"+t:t),u="LAY_layedit_"+ ++a.index,d=c.next("."+r),y=e.extend({},n,i),f=function(){var t=[],e={};return layui.each(y.hideTool,function(t,i){e[i]=!0}),layui.each(y.tool,function(i,a){C[a]&&!e[a]&&t.push(C[a])}),t.join("")}(),m=e(['
                          ','
                          '+f+"
                          ",'
                          ','',"
                          ","
                          "].join(""));return l.ie&&l.ie<8?c.removeClass("layui-hide").addClass(o):(d[0]&&d.remove(),s.call(a,m,c[0],y),c.addClass("layui-hide").after(m),a.index)},c.prototype.getContent=function(t){var e=u(t);if(e[0])return d(e[0].document.body.innerHTML)},c.prototype.getText=function(t){var i=u(t);if(i[0])return e(i[0].document.body).text()},c.prototype.setContent=function(t,i,a){var l=u(t);l[0]&&(a?e(l[0].document.body).append(i):e(l[0].document.body).html(i),layedit.sync(t))},c.prototype.sync=function(t){var i=u(t);if(i[0]){var a=e("#"+i[1].attr("textarea"));a.val(d(i[0].document.body.innerHTML))}},c.prototype.getSelection=function(t){var e=u(t);if(e[0]){var i=m(e[0].document);return document.selection?i.text:i.toString()}};var s=function(t,i,a){var l=this,n=t.find("iframe");n.css({height:a.height}).on("load",function(){var o=n.contents(),r=n.prop("contentWindow"),c=o.find("head"),s=e([""].join("")),u=o.find("body");c.append(s),u.attr("contenteditable","true").css({"min-height":a.height}).html(i.value||""),y.apply(l,[r,n,i,a]),g.call(l,r,t,a)})},u=function(t){var i=e("#LAY_layedit_"+t),a=i.prop("contentWindow");return[a,i]},d=function(t){return 8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),t},y=function(t,a,n,o){var r=t.document,c=e(r.body);c.on("keydown",function(t){var e=t.keyCode;if(13===e){var a=m(r),l=p(a),n=l.parentNode;if("pre"===n.tagName.toLowerCase()){if(t.shiftKey)return;return i.msg("\u8bf7\u6682\u65f6\u7528shift+enter"),!1}r.execCommand("formatBlock",!1,"

                          ")}}),e(n).parents("form").on("submit",function(){var t=c.html();8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),n.value=t}),c.on("paste",function(e){r.execCommand("formatBlock",!1,"

                          "),setTimeout(function(){f.call(t,c),n.value=c.html()},100)})},f=function(t){var i=this;i.document;t.find("*[style]").each(function(){var t=this.style.textAlign;this.removeAttribute("style"),e(this).css({"text-align":t||""})}),t.find("table").addClass("layui-table"),t.find("script,link").remove()},m=function(t){return t.selection?t.selection.createRange():t.getSelection().getRangeAt(0)},p=function(t){return t.endContainer||t.parentElement().childNodes[0]},v=function(t,i,a){var l=this.document,n=document.createElement(t);for(var o in i)n.setAttribute(o,i[o]);if(n.removeAttribute("text"),l.selection){var r=a.text||i.text;if("a"===t&&!r)return;r&&(n.innerHTML=r),a.pasteHTML(e(n).prop("outerHTML")),a.select()}else{var r=a.toString()||i.text;if("a"===t&&!r)return;r&&(n.innerHTML=r),a.deleteContents(),a.insertNode(n)}},h=function(t,i){var a=this.document,l="layedit-tool-active",n=p(m(a)),o=function(e){return t.find(".layedit-tool-"+e)};i&&i[i.hasClass(l)?"removeClass":"addClass"](l),t.find(">i").removeClass(l),o("unlink").addClass(r),e(n).parents().each(function(){var t=this.tagName.toLowerCase(),e=this.style.textAlign;"b"!==t&&"strong"!==t||o("b").addClass(l),"i"!==t&&"em"!==t||o("i").addClass(l),"u"===t&&o("u").addClass(l),"strike"===t&&o("d").addClass(l),"p"===t&&("center"===e?o("center").addClass(l):"right"===e?o("right").addClass(l):o("left").addClass(l)),"a"===t&&(o("link").addClass(l),o("unlink").removeClass(r))})},g=function(t,a,l){var n=t.document,o=e(n.body),c={link:function(i){var a=p(i),l=e(a).parent();b.call(o,{href:l.attr("href"),target:l.attr("target")},function(e){var a=l[0];"A"===a.tagName?a.href=e.url:v.call(t,"a",{target:e.target,href:e.url,text:e.url},i)})},unlink:function(t){n.execCommand("unlink")},face:function(e){x.call(this,function(i){v.call(t,"img",{src:i.src,alt:i.alt},e)})},image:function(a){var n=this;layui.use("upload",function(o){var r=l.uploadImage||{};o.render({url:r.url,method:r.type,elem:e(n).find("input")[0],done:function(e){0==e.code?(e.data=e.data||{},v.call(t,"img",{src:e.data.src,alt:e.data.title},a)):i.msg(e.msg||"\u4e0a\u4f20\u5931\u8d25")}})})},code:function(e){k.call(o,function(i){v.call(t,"pre",{text:i.code,"lay-lang":i.lang},e)})},help:function(){i.open({type:2,title:"\u5e2e\u52a9",area:["600px","380px"],shadeClose:!0,shade:.1,skin:"layui-layer-msg",content:["","no"]})}},s=a.find(".layui-layedit-tool"),u=function(){var i=e(this),a=i.attr("layedit-event"),l=i.attr("lay-command");if(!i.hasClass(r)){o.focus();var u=m(n);u.commonAncestorContainer;l?(n.execCommand(l),/justifyLeft|justifyCenter|justifyRight/.test(l)&&n.execCommand("formatBlock",!1,"

                          "),setTimeout(function(){o.focus()},10)):c[a]&&c[a].call(this,u),h.call(t,s,i)}},d=/image/;s.find(">i").on("mousedown",function(){var t=e(this),i=t.attr("layedit-event");d.test(i)||u.call(this)}).on("click",function(){var t=e(this),i=t.attr("layedit-event");d.test(i)&&u.call(this)}),o.on("click",function(){h.call(t,s),i.close(x.index)})},b=function(t,e){var l=this,n=i.open({type:1,id:"LAY_layedit_link",area:"350px",shade:.05,shadeClose:!0,moveType:1,title:"\u8d85\u94fe\u63a5",skin:"layui-layer-msg",content:['

                            ','
                          • ','','
                            ','',"
                            ","
                          • ",'
                          • ','','
                            ','",'","
                            ","
                          • ",'
                          • ','','',"
                          • ","
                          "].join(""),success:function(t,n){var o="submit(layedit-link-yes)";a.render("radio"),t.find(".layui-btn-primary").on("click",function(){i.close(n),l.focus()}),a.on(o,function(t){i.close(b.index),e&&e(t.field)})}});b.index=n},x=function(t){var a=function(){var t=["[\u5fae\u7b11]","[\u563b\u563b]","[\u54c8\u54c8]","[\u53ef\u7231]","[\u53ef\u601c]","[\u6316\u9f3b]","[\u5403\u60ca]","[\u5bb3\u7f9e]","[\u6324\u773c]","[\u95ed\u5634]","[\u9119\u89c6]","[\u7231\u4f60]","[\u6cea]","[\u5077\u7b11]","[\u4eb2\u4eb2]","[\u751f\u75c5]","[\u592a\u5f00\u5fc3]","[\u767d\u773c]","[\u53f3\u54fc\u54fc]","[\u5de6\u54fc\u54fc]","[\u5618]","[\u8870]","[\u59d4\u5c48]","[\u5410]","[\u54c8\u6b20]","[\u62b1\u62b1]","[\u6012]","[\u7591\u95ee]","[\u998b\u5634]","[\u62dc\u62dc]","[\u601d\u8003]","[\u6c57]","[\u56f0]","[\u7761]","[\u94b1]","[\u5931\u671b]","[\u9177]","[\u8272]","[\u54fc]","[\u9f13\u638c]","[\u6655]","[\u60b2\u4f24]","[\u6293\u72c2]","[\u9ed1\u7ebf]","[\u9634\u9669]","[\u6012\u9a82]","[\u4e92\u7c89]","[\u5fc3]","[\u4f24\u5fc3]","[\u732a\u5934]","[\u718a\u732b]","[\u5154\u5b50]","[ok]","[\u8036]","[good]","[NO]","[\u8d5e]","[\u6765]","[\u5f31]","[\u8349\u6ce5\u9a6c]","[\u795e\u9a6c]","[\u56e7]","[\u6d6e\u4e91]","[\u7ed9\u529b]","[\u56f4\u89c2]","[\u5a01\u6b66]","[\u5965\u7279\u66fc]","[\u793c\u7269]","[\u949f]","[\u8bdd\u7b52]","[\u8721\u70db]","[\u86cb\u7cd5]"],e={};return layui.each(t,function(t,i){e[i]=layui.cache.dir+"images/face/"+t+".gif"}),e}();return x.hide=x.hide||function(t){"face"!==e(t.target).attr("layedit-event")&&i.close(x.index)},x.index=i.tips(function(){var t=[];return layui.each(a,function(e,i){t.push('
                        • '+e+'
                        • ')}),'
                            '+t.join("")+"
                          "}(),this,{tips:1,time:0,skin:"layui-box layui-util-face",maxWidth:500,success:function(l,n){l.css({marginTop:-4,marginLeft:-10}).find(".layui-clear>li").on("click",function(){t&&t({src:a[this.title],alt:this.title}),i.close(n)}),e(document).off("click",x.hide).on("click",x.hide)}})},k=function(t){var e=this,l=i.open({type:1,id:"LAY_layedit_code",area:"550px",shade:.05,shadeClose:!0,moveType:1,title:"\u63d2\u5165\u4ee3\u7801",skin:"layui-layer-msg",content:['
                            ','
                          • ','','
                            ','","
                            ","
                          • ",'
                          • ','','
                            ','',"
                            ","
                          • ",'
                          • ','','',"
                          • ","
                          "].join(""),success:function(l,n){var o="submit(layedit-code-yes)";a.render("select"),l.find(".layui-btn-primary").on("click",function(){i.close(n),e.focus()}),a.on(o,function(e){i.close(k.index),t&&t(e.field)})}});k.index=l},C={html:'',strong:'',italic:'',underline:'',del:'',"|":'',left:'',center:'',right:'',link:'',unlink:'',face:'',image:'',code:'',help:''},L=new c;t(n,L)});layui.define("jquery",function(a){"use strict";var e=layui.$;a("code",function(a){var l=[];a=a||{},a.elem=e(a.elem||".layui-code"),a.lang="lang"in a?a.lang:"code",a.elem.each(function(){l.push(this)}),layui.each(l.reverse(),function(l,i){var t=e(i),c=t.html();(t.attr("lay-encode")||a.encode)&&(c=c.replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,""")),t.html('
                          1. '+c.replace(/[\r\t\n]+/g,"
                          2. ")+"
                          "),t.find(">.layui-code-h3")[0]||t.prepend('

                          '+(t.attr("lay-title")||a.title||"</>")+''+(t.attr("lay-lang")||a.lang||"")+"

                          ");var n=t.find(">.layui-code-ol");t.addClass("layui-box layui-code-view"),(t.attr("lay-skin")||a.skin)&&t.addClass("layui-code-"+(t.attr("lay-skin")||a.skin)),(n.find("li").length/100|0)>0&&n.css("margin-left",(n.find("li").length/100|0)+"px"),(t.attr("lay-height")||a.height)&&n.css("max-height",t.attr("lay-height")||a.height)})})}).addcss("modules/code.css?v=2","skincodecss"); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/pages/index.html b/iot-server/server-starter/src/main/webapp/pages/index.html new file mode 100644 index 00000000..c8a39831 --- /dev/null +++ b/iot-server/server-starter/src/main/webapp/pages/index.html @@ -0,0 +1,10 @@ + + + + + Title + + +123 ${word!""} + + \ No newline at end of file From 53d1c0e8268d2b23e8a8450312178b7c0ad62f1c Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 8 Dec 2021 14:41:39 +0800 Subject: [PATCH 709/763] [feat]: some fix --- .gitignore | 2 +- .../zmops/zeus/iot/web/config/IoTConfig.java | 2 + .../iot/web/controller/IndexController.java | 156 +++++++++++++++++- .../iot/domain/messages/NoticeRecord.java | 16 +- 4 files changed, 165 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 028472b4..835bdf1d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,6 @@ **/target/* .vscode **/node_modules/* -dist/ +**/dist/* zeus-starter/src/main/resources/public/ .bdb/ diff --git a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/config/IoTConfig.java b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/config/IoTConfig.java index c35c776f..a7827aee 100644 --- a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/config/IoTConfig.java +++ b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/config/IoTConfig.java @@ -10,6 +10,8 @@ public class IoTConfig extends WebConfig { @Override public void configConstant(Constants constants) { constants.setDevMode(true); + constants.setMaxPostSize(1024 * 1024 * 100); + constants.setBaseUploadPath("D:\\666\\upload"); } @Override diff --git a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/IndexController.java b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/IndexController.java index 2b8df1da..cc9af17e 100644 --- a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/IndexController.java +++ b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/IndexController.java @@ -1,7 +1,25 @@ package com.zmops.zeus.iot.web.controller; +import com.alipay.sofa.ark.api.ArkClient; +import com.alipay.sofa.ark.api.ClientResponse; +import com.google.gson.Gson; +import com.zmops.zeus.iot.server.receiver.ProtocolAction; +import com.zmops.zeus.iot.server.receiver.ProtocolEnum; +import com.zmops.zeus.iot.server.receiver.module.CamelReceiverModule; +import com.zmops.zeus.iot.server.receiver.routes.*; +import com.zmops.zeus.iot.server.receiver.service.CamelContextHolderService; +import com.zmops.zeus.server.library.module.ModuleManager; import com.zmops.zeus.server.library.web.core.Controller; import com.zmops.zeus.server.library.web.core.Path; +import com.zmops.zeus.server.library.web.upload.UploadFile; +import com.zmops.zeus.server.library.web.util.HttpKit; +import lombok.Getter; +import lombok.Setter; +import org.apache.camel.builder.RouteBuilder; + +import java.io.File; +import java.io.IOException; +import java.util.Map; /** * @author nantian created at 2021/11/23 23:24 @@ -10,7 +28,141 @@ @Path(value = "/123", viewPath = "/") public class IndexController extends Controller { - public void hello() { - renderJson("hello", "world"); + + private final Gson gson = new Gson(); + + public void upload() { + UploadFile file = getFile(); + + try { + String filePath = file.getFile().getCanonicalPath(); + + renderJson("filePath", filePath); + } catch (IOException e) { + e.printStackTrace(); + } + } + + + public void installArk() { + + try { + ClientResponse response = ArkClient.installBiz(new File("D:\\666\\zeus-ark-hello2-1.0-beta-ark-biz.jar")); + +// ClientResponse response1 = ArkClient.checkBiz("zeus-ark-hello", "1.0-beta"); + + renderJson(response); + + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public void uninstallArk() { + try { + ClientResponse response = ArkClient.uninstallBiz("zeus-ark-hello", "1.0-beta"); + renderJson(response); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + + public void stopRoute() { + + String routeId = getPara("routeId"); + + CamelContextHolderService camelContextHolderService = ModuleManager.getInstance() + .find(CamelReceiverModule.NAME).provider().getService(CamelContextHolderService.class); + + camelContextHolderService.routeShutDown(routeId); + + renderNull(); + + } + + + public void startRoute() { + + String routeId = getPara("routeId"); + + CamelContextHolderService camelContextHolderService = ModuleManager.getInstance() + .find(CamelReceiverModule.NAME).provider().getService(CamelContextHolderService.class); + + + camelContextHolderService.routeStartUp(routeId); + + renderNull(); + } + + + public void createRoute() { + + + String json = HttpKit.readData(getRequest()); + + + ProtocolService protocol = gson.fromJson(json, ProtocolService.class); + String routeId = protocol.getRouteId(); + Map options = protocol.getOptions(); + +// SofaStarter sofaStarter = new SofaStarter(); +// ReferenceClient referenceClient = sofaStarter.getSofaRuntimeContext().getClientFactory().getClient(ReferenceClient.class); +// +// ReferenceParam referenceParam = new ReferenceParam<>(); +// referenceParam.setInterfaceType(SayHelloFacade.class); +// referenceParam.setUniqueId("198909118"); +// SayHelloFacade facade = referenceClient.reference(referenceParam); +// +// facade.hello(" zmops is great !!!! "); + + CamelContextHolderService camelContextHolderService = ModuleManager.getInstance() + .find(CamelReceiverModule.NAME).provider().getService(CamelContextHolderService.class); + + + RouteBuilder route = null; + switch (protocol.getProtocol()) { + case HttpServer: + route = new HttpRouteBuilder(routeId, options); + break; + case MqttClient: + route = new MqttClientRouteBuilder(routeId, options); + break; + case TcpServer: + route = new TcpServerRouteBuilder(routeId, options); + break; + case UdpServer: + route = new UdpServerRouteBuilder(routeId, options); + break; + case CoapServer: + route = new CoapServerRouteBuilder(routeId, options); + break; + case WebSocketServer: + route = new WebSocketServerRouteBuilder(routeId, options); + break; + default: + break; + } + + if (route != null) { + camelContextHolderService.addRoutes(route); + } + + + renderNull(); + } + + + @Getter + @Setter + static class ProtocolService { + + private String routeId; + + private ProtocolEnum protocol; + + private ProtocolAction action; + + private Map options; } } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/messages/NoticeRecord.java b/zeus-common/src/main/java/com/zmops/iot/domain/messages/NoticeRecord.java index 65947ae4..4be249bb 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/messages/NoticeRecord.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/messages/NoticeRecord.java @@ -22,13 +22,13 @@ @Table(name = "notice_record") public class NoticeRecord { @Id - private Integer recordId; - private Long userId; - private String problemId; - private Integer noticeType; - private String noticeStatus; - private String noticeMsg; + private Integer recordId; + private Long userId; + private String problemId; + private Integer noticeType; + private String noticeStatus; + private String noticeMsg; private LocalDateTime creatTime; - private String alarmInfo; - private String receiveAccount; + private String alarmInfo; + private String receiveAccount; } From 9d64ef41429844ea96b604dfeb1cb03bd32063ba Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 8 Dec 2021 16:53:18 +0800 Subject: [PATCH 710/763] [feat]: add professional module --- .gitignore | 1 + dist-material/bin/sql/zeus-iot.sql | 608 ++++++++++++------ iot-server/server-bootstrap/pom.xml | 12 +- iot-server/server-camel-receiver/pom.xml | 4 +- iot-server/server-starter/pom.xml | 2 +- iot-server/server-storage-plugin/pom.xml | 3 +- .../server-influxdb-plugin/pom.xml | 37 ++ .../plugin/jdbc/influxdb/InfluxClient.java | 239 +++++++ .../jdbc/influxdb/InfluxStorageConfig.java | 39 ++ .../jdbc/influxdb/InfluxStorageProvider.java | 88 +++ .../plugin/jdbc/influxdb/dao/BatchDAO.java | 61 ++ .../influxdb/dao/InfluxInsertRequest.java | 77 +++ .../jdbc/influxdb/dao/InfluxStorageDAO.java | 39 ++ .../plugin/jdbc/influxdb/dao/RecordDAO.java | 45 ++ ....zeus.server.library.module.ModuleProvider | 20 + iot-server/server-web/pom.xml | 6 +- .../iot/domain/alarm/MediaTypeSetting.java | 2 + .../com/zmops/iot/domain/device/ApiParam.java | 28 + .../com/zmops/iot/domain/device/Device.java | 6 + .../zmops/iot/domain/device/DeviceGroup.java | 1 + .../iot/domain/device/DeviceOnlineReport.java | 1 + .../iot/domain/device/EventTriggerRecord.java | 3 + .../domain/device/ScenesTriggerRecord.java | 3 + .../domain/device/ServiceExecuteRecord.java | 3 + .../iot/domain/messages/MailSetting.java | 1 + .../com/zmops/iot/domain/product/Product.java | 4 +- .../iot/domain/product/ProductAttribute.java | 2 +- .../iot/domain/product/ProductEvent.java | 13 +- .../zmops/iot/domain/product/ProductType.java | 2 + .../com/zmops/iot/domain/proxy/Proxy.java | 30 + .../com/zmops/iot/domain/sys/SysLoginLog.java | 2 + .../zmops/iot/domain/sys/SysOperationLog.java | 2 + .../com/zmops/iot/domain/sys/SysUser.java | 3 + .../zmops/iot/domain/sys/SysUserGroup.java | 1 + .../zmops/iot/domain/tenant/TenantInfo.java | 56 ++ .../iot/model/cache/TenantNameCache.java | 21 + .../model/cache/filter/CachedValueFilter.java | 5 + .../zmops/iot/model/cache/filter/DicType.java | 1 + .../exception/enums/CoreExceptionEnum.java | 3 +- .../com/zmops/iot/model/node/TreeNode.java | 2 + .../com/zmops/iot/util/DefinitionsUtil.java | 12 + .../java/com/zmops/iot/util/ToolUtil.java | 13 +- .../iot/core/auth/filter/CommonFilter.java | 29 + .../CommonHttpServletRequestWrapper.java | 93 +++ .../core/auth/filter/CommonInterceptor.java | 75 +++ .../core/auth/filter/NoneAuthedResources.java | 2 + .../zmops/iot/core/auth/model/LoginUser.java | 5 + .../core/auth/util/FixLengthLinkedList.java | 33 + .../zmops/zeus/driver/entity/Interface.java | 35 + .../zmops/zeus/driver/entity/ItemParam.java | 14 + .../zmops/zeus/driver/entity/SendParam.java | 13 + .../zeus/driver/service/TransferKit.java | 87 +++ .../zmops/zeus/driver/service/ZbxConfig.java | 32 + .../zeus/driver/service/ZbxHistoryGet.java | 1 - .../zmops/zeus/driver/service/ZbxHost.java | 11 +- .../zeus/driver/service/ZbxInterface.java | 25 + .../zmops/zeus/driver/service/ZbxItem.java | 8 +- .../zmops/zeus/driver/service/ZbxProxy.java | 51 ++ .../zmops/zeus/driver/service/ZbxTrigger.java | 4 +- .../resources/api-json/host/host.create.ftl | 15 + .../resources/api-json/host/host.update.ftl | 15 + .../hostinterface/hostinterface.get.ftl | 9 + .../api-json/item/item.trapper.create.ftl | 6 + .../api-json/item/item.trapper.update.ftl | 6 + .../resources/api-json/proxy/proxy.create.ftl | 10 + .../resources/api-json/proxy/proxy.delete.ftl | 13 + .../resources/api-json/proxy/proxy.get.ftl | 11 + .../resources/api-json/transfer/create.ftl | 53 ++ .../com/zmops/iot/media/AlarmCallback.java | 2 +- .../com/zmops/iot/media/WebhookCallback.java | 2 +- .../media/dingtalk/DingtalkHookCallback.java | 4 +- .../dingtalk/DingtalkSettingService.java | 25 +- .../iot/media/feishu/FeishuHookCallback.java | 4 +- .../media/feishu/FeishuSettingService.java | 25 +- .../iot/media/wechat/WechatHookCallback.java | 4 +- .../media/wechat/WechatSettingService.java | 22 +- .../iot/media/welink/WeLinkHookCallback.java | 4 +- .../media/welink/WeLinkSettingService.java | 2 +- .../controller/SocketIoController.java | 10 +- zeus-webapp/pom.xml | 4 + .../MediaTypeSettingController.java | 7 + .../iot/web/alarm/service/AlarmService.java | 24 +- .../alarm/service/MailSettingServiceImpl.java | 22 +- .../iot/web/analyse/service/HomeService.java | 58 +- .../web/analyse/service/LatestService.java | 1 + .../com/zmops/iot/web/auth/AuthService.java | 5 +- .../controller/DeviceApiController.java | 73 +++ .../device/controller/DeviceController.java | 8 +- .../DeviceEventTriggerController.java | 2 +- .../controller/DeviceServiceController.java | 2 + .../MultipleDeviceEventTriggerController.java | 9 + .../zmops/iot/web/device/dto/DeviceDto.java | 9 +- .../iot/web/device/dto/DeviceGroupDto.java | 9 + .../device/dto/MultipleDeviceEventDto.java | 7 +- .../device/dto/MultipleDeviceEventRule.java | 2 + .../device/dto/MultipleDeviceServiceDto.java | 1 + .../device/dto/param/DeviceGroupParam.java | 2 + .../schedule/DeviceOnlineReprotSchedule.java | 34 +- .../service/DeviceEventRuleService.java | 45 +- .../device/service/DeviceGroupService.java | 20 +- .../web/device/service/DeviceLogService.java | 22 +- .../device/service/DeviceModelService.java | 112 ++-- .../iot/web/device/service/DeviceService.java | 26 +- .../web/device/service/DeviceSvrService.java | 8 + .../MultipleDeviceEventRuleService.java | 11 +- .../service/work/DeviceEventLogWorker.java | 4 +- .../service/work/DeviceServiceLogWorker.java | 13 +- .../service/work/SaveAttributeWorker.java | 4 +- .../service/work/SaveDeviceGrpWorker.java | 8 +- .../device/service/work/SaveDeviceWorker.java | 5 +- .../device/service/work/SaveOtherWorker.java | 4 +- .../device/service/work/SaveTagWorker.java | 8 +- .../service/work/SaveZbxHostWorker.java | 23 +- .../device/service/work/ScenesLogWorker.java | 7 +- .../service/work/UpdateAttrZbxIdWorker.java | 8 +- .../service/work/UpdateDeviceZbxIdWorker.java | 8 +- .../service/work/UpdateZbxTagWorker.java | 4 +- .../pgEvent/service/AlarmEventProcess.java | 23 +- .../pgEvent/service/IncidentEventProcess.java | 2 + .../pgEvent/service/ServiceEventProcess.java | 6 +- .../exception/aop/GlobalExceptionHandler.java | 19 +- .../web/exception/enums/BizExceptionEnum.java | 29 +- .../com/zmops/iot/web/log/aop/LogAop.java | 2 +- .../zmops/iot/web/log/factory/LogFactory.java | 6 +- .../iot/web/log/factory/LogTaskFactory.java | 20 +- .../iot/web/product/dto/ProductAttrDto.java | 4 +- .../iot/web/product/dto/ProductBasicInfo.java | 2 + .../zmops/iot/web/product/dto/ProductDto.java | 7 +- .../iot/web/product/dto/ProductEventDto.java | 7 + .../product/dto/ProductStatusFunctionDto.java | 1 + .../product/dto/param/ProductAttrParam.java | 1 + .../product/dto/param/ProductTypeParam.java | 2 + .../service/ProductAttributeEventService.java | 62 +- .../product/service/ProductModelService.java | 35 +- .../web/product/service/ProductService.java | 11 +- .../product/service/ProductTypeService.java | 15 +- .../web/proxy/controller/ProxyController.java | 89 +++ .../com/zmops/iot/web/proxy/dto/ProxyDto.java | 57 ++ .../iot/web/proxy/dto/ProxyMonitorInfo.java | 41 ++ .../zmops/iot/web/proxy/dto/ZbxProxyInfo.java | 17 + .../iot/web/proxy/dto/ZbxServerInfo.java | 19 + .../iot/web/proxy/dto/param/ProxyParam.java | 15 + .../iot/web/proxy/service/ProxyService.java | 276 ++++++++ .../web/sys/controller/TenantController.java | 134 ++++ .../zmops/iot/web/sys/dto/LoginUserDto.java | 2 + .../zmops/iot/web/sys/dto/SysLoginLogDto.java | 2 + .../iot/web/sys/dto/SysOperationLogDto.java | 2 + .../zmops/iot/web/sys/dto/TenantInfoDto.java | 65 ++ .../com/zmops/iot/web/sys/dto/UserDto.java | 2 + .../zmops/iot/web/sys/dto/UserGroupDto.java | 3 + .../web/sys/dto/param/TenantInfoParam.java | 59 ++ .../iot/web/sys/factory/UserFactory.java | 1 + .../iot/web/sys/service/LoginLogService.java | 5 + .../web/sys/service/OperationLogService.java | 5 + .../web/sys/service/SysUserGroupService.java | 36 +- .../iot/web/sys/service/SysUserService.java | 17 +- .../iot/web/sys/service/Tenantervice.java | 209 ++++++ .../controller/TransferController.java | 78 +++ .../zmops/iot/web/transfer/dto/ConfigDto.java | 17 + .../zmops/iot/web/transfer/dto/StatusDto.java | 74 +++ .../iot/web/transfer/dto/TransferDto.java | 45 ++ .../web/transfer/dto/param/TransferParam.java | 20 + .../web/transfer/service/TransferService.java | 155 +++++ 163 files changed, 4058 insertions(+), 521 deletions(-) create mode 100644 iot-server/server-storage-plugin/server-influxdb-plugin/pom.xml create mode 100644 iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/InfluxClient.java create mode 100644 iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/InfluxStorageConfig.java create mode 100644 iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/InfluxStorageProvider.java create mode 100644 iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/dao/BatchDAO.java create mode 100644 iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/dao/InfluxInsertRequest.java create mode 100644 iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/dao/InfluxStorageDAO.java create mode 100644 iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/dao/RecordDAO.java create mode 100644 iot-server/server-storage-plugin/server-influxdb-plugin/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/device/ApiParam.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/proxy/Proxy.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/tenant/TenantInfo.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/model/cache/TenantNameCache.java create mode 100644 zeus-core/src/main/java/com/zmops/iot/core/auth/filter/CommonFilter.java create mode 100644 zeus-core/src/main/java/com/zmops/iot/core/auth/filter/CommonHttpServletRequestWrapper.java create mode 100644 zeus-core/src/main/java/com/zmops/iot/core/auth/filter/CommonInterceptor.java create mode 100644 zeus-core/src/main/java/com/zmops/iot/core/auth/util/FixLengthLinkedList.java create mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/entity/Interface.java create mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ItemParam.java create mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/entity/SendParam.java create mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/service/TransferKit.java create mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxConfig.java create mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInterface.java create mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProxy.java create mode 100644 zeus-driver/src/main/resources/api-json/hostinterface/hostinterface.get.ftl create mode 100644 zeus-driver/src/main/resources/api-json/proxy/proxy.create.ftl create mode 100644 zeus-driver/src/main/resources/api-json/proxy/proxy.delete.ftl create mode 100644 zeus-driver/src/main/resources/api-json/proxy/proxy.get.ftl create mode 100644 zeus-driver/src/main/resources/api-json/transfer/create.ftl create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceApiController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/proxy/controller/ProxyController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/ProxyDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/ProxyMonitorInfo.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/ZbxProxyInfo.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/ZbxServerInfo.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/param/ProxyParam.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/proxy/service/ProxyService.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/TenantController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/TenantInfoDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/TenantInfoParam.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/Tenantervice.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/transfer/controller/TransferController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/transfer/dto/ConfigDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/transfer/dto/StatusDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/transfer/dto/TransferDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/transfer/dto/param/TransferParam.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/transfer/service/TransferService.java diff --git a/.gitignore b/.gitignore index 835bdf1d..759d66a7 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ **/dist/* zeus-starter/src/main/resources/public/ .bdb/ +zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/Test.java diff --git a/dist-material/bin/sql/zeus-iot.sql b/dist-material/bin/sql/zeus-iot.sql index df8a3711..2bf9a4b8 100644 --- a/dist-material/bin/sql/zeus-iot.sql +++ b/dist-material/bin/sql/zeus-iot.sql @@ -5,14 +5,14 @@ Source Server Type : PostgreSQL Source Server Version : 130004 Source Host : 172.16.60.130:5432 - Source Catalog : zeus-iot-开源空库不要删 + Source Catalog : zeus-iot-专业版空库不要删 Source Schema : public Target Server Type : PostgreSQL Target Server Version : 130004 File Encoding : 65001 - Date: 02/12/2021 16:03:24 + Date: 02/12/2021 16:03:58 */ @@ -265,7 +265,9 @@ CREATE TABLE "public"."device" ( "zbx_id" varchar(32) COLLATE "pg_catalog"."default", "addr" varchar(255) COLLATE "pg_catalog"."default", "position" varchar(64) COLLATE "pg_catalog"."default", - "online" int2, + "proxy_id" int8, + "online" int2 DEFAULT 1, + "tenant_id" int8, "latest_online" timestamp(6) ) ; @@ -282,7 +284,9 @@ COMMENT ON COLUMN "public"."device"."type" IS '设备类型'; COMMENT ON COLUMN "public"."device"."zbx_id" IS 'zbx主机ID'; COMMENT ON COLUMN "public"."device"."addr" IS '设备地址'; COMMENT ON COLUMN "public"."device"."position" IS '地址坐标'; +COMMENT ON COLUMN "public"."device"."proxy_id" IS '代理ID'; COMMENT ON COLUMN "public"."device"."online" IS '是否在线 1是 0否'; +COMMENT ON COLUMN "public"."device"."tenant_id" IS '租户ID'; COMMENT ON COLUMN "public"."device"."latest_online" IS '最近在线时间'; -- ---------------------------- @@ -301,7 +305,8 @@ CREATE TABLE "public"."device_group" ( "create_user" int8, "create_time" timestamp(6), "update_user" int8, - "update_time" timestamp(6) + "update_time" timestamp(6), + "tenant_id" int8 ) ; COMMENT ON COLUMN "public"."device_group"."device_group_id" IS '主机组ID'; @@ -312,6 +317,7 @@ COMMENT ON COLUMN "public"."device_group"."create_user" IS '创建人'; COMMENT ON COLUMN "public"."device_group"."create_time" IS '创建时间'; COMMENT ON COLUMN "public"."device_group"."update_user" IS '更新人'; COMMENT ON COLUMN "public"."device_group"."update_time" IS '更新时间'; +COMMENT ON COLUMN "public"."device_group"."tenant_id" IS '租户ID'; -- ---------------------------- -- Records of device_group @@ -326,12 +332,14 @@ CREATE TABLE "public"."device_online_report" ( "create_time" varchar(10) COLLATE "pg_catalog"."default", "online" int4, "offline" int4, - "type" int2 + "type" int2, + "tenant_id" int8 ) ; COMMENT ON COLUMN "public"."device_online_report"."online" IS '在线数'; COMMENT ON COLUMN "public"."device_online_report"."offline" IS '离线数'; COMMENT ON COLUMN "public"."device_online_report"."type" IS '设备类型'; +COMMENT ON COLUMN "public"."device_online_report"."tenant_id" IS '租户ID'; -- ---------------------------- -- Records of device_online_report @@ -365,6 +373,7 @@ CREATE TABLE "public"."event_trigger_record" ( "event_value" varchar(255) COLLATE "pg_catalog"."default", "device_id" varchar(64) COLLATE "pg_catalog"."default", "create_time" timestamp(6), + "tenant_id" int8, "key" varchar(64) COLLATE "pg_catalog"."default" ) ; @@ -372,6 +381,7 @@ COMMENT ON COLUMN "public"."event_trigger_record"."event_name" IS '事件名称' COMMENT ON COLUMN "public"."event_trigger_record"."event_value" IS '事件发生时的值'; COMMENT ON COLUMN "public"."event_trigger_record"."device_id" IS '设备ID'; COMMENT ON COLUMN "public"."event_trigger_record"."create_time" IS '发生时间'; +COMMENT ON COLUMN "public"."event_trigger_record"."tenant_id" IS '租户ID'; COMMENT ON COLUMN "public"."event_trigger_record"."key" IS '事件标识'; -- ---------------------------- @@ -392,7 +402,8 @@ CREATE TABLE "public"."mail_setting" ( "tls" int4 NOT NULL DEFAULT 0, "severity" varchar(255) COLLATE "pg_catalog"."default" DEFAULT ''::character varying, "silent" int2 NOT NULL DEFAULT 3, - "id" int4 NOT NULL DEFAULT nextval('mail_setting_id_seq'::regclass) + "id" int4 NOT NULL DEFAULT nextval('mail_setting_id_seq'::regclass), + "tenant_id" int8 ) ; COMMENT ON COLUMN "public"."mail_setting"."host" IS 'smtp服务器地址'; @@ -402,11 +413,11 @@ COMMENT ON COLUMN "public"."mail_setting"."password" IS 'smtp密码'; COMMENT ON COLUMN "public"."mail_setting"."sender" IS '发送邮箱'; COMMENT ON COLUMN "public"."mail_setting"."ssl" IS '1-是 0-否'; COMMENT ON COLUMN "public"."mail_setting"."tls" IS '1-是 0-否'; +COMMENT ON COLUMN "public"."mail_setting"."tenant_id" IS '租户ID'; -- ---------------------------- -- Records of mail_setting -- ---------------------------- -INSERT INTO "public"."mail_setting" VALUES ('172.16.2.221', 587, 'sanshi@zmops.cn', 'Zmops@0610', 'sanshi@zmops.cn', 0, 1, '54', 3, 1); -- ---------------------------- -- Table structure for media_type_setting @@ -428,25 +439,25 @@ COMMENT ON COLUMN "public"."media_type_setting"."tenant_id" IS '租户ID'; -- ---------------------------- -- Records of media_type_setting -- ---------------------------- -INSERT INTO "public"."media_type_setting" VALUES (1, 'wechat', ' -{ - "content": "广州今日天气:29度,大部分多云,降雨概率:80%", - "mentioned_list":["wangqing","@all"], - "mentioned_mobile_list":["13800001111","@all"] - } -', '{"url":"https://oapi.dingtalk.com/robot/send?access_token=dd0f8a3340c15ec0f1d54b91980584c1127abe6dd143a964d44385647bc15124"}', NULL); -INSERT INTO "public"."media_type_setting" VALUES (2, 'dingtalk', '{ - "msgtype":"text", - "text": { - "content":"%s" - } -}', '{"url":"https://oapi.dingtalk.com/robot/send?access_token=dd","secret":"5c60"}', NULL); INSERT INTO "public"."media_type_setting" VALUES (3, 'feishu', '{ "msg_type":"text", "content": { "text":"%s" } -}', '{"url":"https://open.feishu.cn/open-apis/bot/v2/hook/c43e56f","secret":"xoaP"}', NULL); +}', '{"url":"https://open.feishu.cn/open-apis/bot/v2/hook/c43e56f3-bdc9-4abb-ba4c-17afc6147f73","secret":"xoaP9dPKLeQIeDk5jZnEdg"}', NULL); +INSERT INTO "public"."media_type_setting" VALUES (2, 'dingtalk', '{ + "msgtype":"text", + "text": { + "content":"%s" + } +}', '{"url":"https://oapi.dingtalk.com/robot/send?access_token=dd0f8a3340c15ec0f1d54b91980584c1127abe6dd143a964d44385647bc15124","secret":"SECb9675c586801a915b955888ebe88da7ae8bb55b9061e3e14d1424509a5dd5c60"}', NULL); +INSERT INTO "public"."media_type_setting" VALUES (1, 'wechat', ' +{ + "content": "广州今日天气:29度,大部分多云,降雨概率:80%", + "mentioned_list":["wangqing","@all"], + "mentioned_mobile_list":["13800001111","@all"] + } +', '{"url":"https://oapi.dingtalk.com/robot/send?access_token=dd0f8a3340c15ec0f1d54b91980584c1127abe6dd143a964d44385647bc15124"}', NULL); -- ---------------------------- -- Table structure for messages @@ -528,7 +539,7 @@ DROP TABLE IF EXISTS "public"."product"; CREATE TABLE "public"."product" ( "product_id" int8 NOT NULL, "group_id" int8, - "name" varchar(255) COLLATE "pg_catalog"."default", + "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, "type" varchar(64) COLLATE "pg_catalog"."default", "manufacturer" varchar(255) COLLATE "pg_catalog"."default", "model" varchar(255) COLLATE "pg_catalog"."default", @@ -539,6 +550,7 @@ CREATE TABLE "public"."product" ( "update_user" int8, "product_code" varchar(255) COLLATE "pg_catalog"."default", "zbx_id" varchar(32) COLLATE "pg_catalog"."default", + "tenant_id" int8, "icon" text COLLATE "pg_catalog"."default" ) ; @@ -555,6 +567,7 @@ COMMENT ON COLUMN "public"."product"."update_time" IS '更新时间'; COMMENT ON COLUMN "public"."product"."update_user" IS '更新人'; COMMENT ON COLUMN "public"."product"."product_code" IS '产品编号'; COMMENT ON COLUMN "public"."product"."zbx_id" IS 'Zabbix对应模板ID'; +COMMENT ON COLUMN "public"."product"."tenant_id" IS '租户ID'; COMMENT ON COLUMN "public"."product"."icon" IS '图片'; -- ---------------------------- @@ -676,6 +689,7 @@ CREATE TABLE "public"."product_event" ( "event_notify" varchar(1) COLLATE "pg_catalog"."default", "status" varchar(8) COLLATE "pg_catalog"."default", "classify" varchar(2) COLLATE "pg_catalog"."default", + "tenant_id" int8, "task_id" int4, "trigger_type" int2 ) @@ -687,6 +701,7 @@ COMMENT ON COLUMN "public"."product_event"."remark" IS '备注'; COMMENT ON COLUMN "public"."product_event"."exp_logic" IS 'and 或者 or'; COMMENT ON COLUMN "public"."product_event"."event_notify" IS '0 否 1 是'; COMMENT ON COLUMN "public"."product_event"."classify" IS '0 告警 1场景联动'; +COMMENT ON COLUMN "public"."product_event"."tenant_id" IS '租户ID'; COMMENT ON COLUMN "public"."product_event"."task_id" IS '任务ID'; COMMENT ON COLUMN "public"."product_event"."trigger_type" IS '触发类型 0-条件触发 1-定时触发'; @@ -938,6 +953,7 @@ CREATE TABLE "public"."product_type" ( "name" varchar(32) COLLATE "pg_catalog"."default", "remark" varchar(255) COLLATE "pg_catalog"."default", "pids" varchar(255) COLLATE "pg_catalog"."default", + "tenant_id" int8, "create_user" int8, "create_time" timestamp(6), "update_user" int8, @@ -947,6 +963,7 @@ CREATE TABLE "public"."product_type" ( COMMENT ON COLUMN "public"."product_type"."name" IS '分类名称'; COMMENT ON COLUMN "public"."product_type"."remark" IS '备注'; COMMENT ON COLUMN "public"."product_type"."pids" IS '所有父ID'; +COMMENT ON COLUMN "public"."product_type"."tenant_id" IS '租户ID'; COMMENT ON COLUMN "public"."product_type"."create_user" IS '创建人'; COMMENT ON COLUMN "public"."product_type"."create_time" IS '创建时间'; COMMENT ON COLUMN "public"."product_type"."update_user" IS '更新人'; @@ -955,7 +972,42 @@ COMMENT ON COLUMN "public"."product_type"."update_time" IS '更新时间'; -- ---------------------------- -- Records of product_type -- ---------------------------- -INSERT INTO "public"."product_type" VALUES (1, 0, '默认产品分组', NULL, '[0],', NULL, NULL, NULL, NULL); +INSERT INTO "public"."product_type" VALUES (244, 0, '默认产品分组', NULL, '[0],', 1442678404265623552, NULL, NULL, NULL, NULL); + +-- ---------------------------- +-- Table structure for proxy +-- ---------------------------- +DROP TABLE IF EXISTS "public"."proxy"; +CREATE TABLE "public"."proxy" ( + "id" int8 NOT NULL, + "name" varchar(64) COLLATE "pg_catalog"."default", + "mode" varchar(16) COLLATE "pg_catalog"."default" DEFAULT '0'::character varying, + "address" varchar(32) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "tls_accept" int4 DEFAULT 1, + "create_time" timestamp(6), + "create_user" int8, + "update_time" timestamp(6), + "update_user" int8, + "zbx_id" varchar(16) COLLATE "pg_catalog"."default", + "tenant_id" int8 +) +; +COMMENT ON COLUMN "public"."proxy"."name" IS '代理名称'; +COMMENT ON COLUMN "public"."proxy"."mode" IS '代理模式'; +COMMENT ON COLUMN "public"."proxy"."address" IS '代理服务器地址'; +COMMENT ON COLUMN "public"."proxy"."remark" IS '描述'; +COMMENT ON COLUMN "public"."proxy"."tls_accept" IS '加密方式'; +COMMENT ON COLUMN "public"."proxy"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."proxy"."create_user" IS '创建者'; +COMMENT ON COLUMN "public"."proxy"."update_time" IS '系统时间'; +COMMENT ON COLUMN "public"."proxy"."update_user" IS '修改者'; +COMMENT ON COLUMN "public"."proxy"."zbx_id" IS 'zbx ID'; +COMMENT ON COLUMN "public"."proxy"."tenant_id" IS '租户ID'; + +-- ---------------------------- +-- Records of proxy +-- ---------------------------- -- ---------------------------- -- Table structure for scenes_trigger_record @@ -965,6 +1017,7 @@ CREATE TABLE "public"."scenes_trigger_record" ( "id" int8 NOT NULL DEFAULT nextval('scenes_trigger_record_id_seq'::regclass), "create_time" timestamp(6), "rule_name" varchar(64) COLLATE "pg_catalog"."default", + "tenant_id" int8, "rule_id" int8, "trigger_type" varchar(16) COLLATE "pg_catalog"."default", "trigger_user" int8 @@ -972,6 +1025,7 @@ CREATE TABLE "public"."scenes_trigger_record" ( ; COMMENT ON COLUMN "public"."scenes_trigger_record"."create_time" IS '触发时间'; COMMENT ON COLUMN "public"."scenes_trigger_record"."rule_name" IS '场景联动名称'; +COMMENT ON COLUMN "public"."scenes_trigger_record"."tenant_id" IS '租户ID'; COMMENT ON COLUMN "public"."scenes_trigger_record"."rule_id" IS '场景联动ID'; COMMENT ON COLUMN "public"."scenes_trigger_record"."trigger_type" IS '触发类型 手动 自动'; COMMENT ON COLUMN "public"."scenes_trigger_record"."trigger_user" IS '触发人'; @@ -990,6 +1044,7 @@ CREATE TABLE "public"."service_execute_record" ( "service_name" varchar(64) COLLATE "pg_catalog"."default", "param" varchar(255) COLLATE "pg_catalog"."default", "device_id" varchar(64) COLLATE "pg_catalog"."default", + "tenant_id" int8, "execute_type" varchar(16) COLLATE "pg_catalog"."default", "execute_user" int8, "execute_rule_id" int8 @@ -998,6 +1053,7 @@ CREATE TABLE "public"."service_execute_record" ( COMMENT ON COLUMN "public"."service_execute_record"."service_name" IS '服务名称'; COMMENT ON COLUMN "public"."service_execute_record"."param" IS '执行参数'; COMMENT ON COLUMN "public"."service_execute_record"."device_id" IS '设备ID'; +COMMENT ON COLUMN "public"."service_execute_record"."tenant_id" IS '租户ID'; COMMENT ON COLUMN "public"."service_execute_record"."execute_type" IS '执行方式 手动触发 场景触发'; COMMENT ON COLUMN "public"."service_execute_record"."execute_user" IS '执行人 执行方式未手动触发时有值'; COMMENT ON COLUMN "public"."service_execute_record"."execute_rule_id" IS '执行场景ID'; @@ -1041,22 +1097,22 @@ COMMENT ON COLUMN "public"."sys_config"."status" IS '是否可修改 ENABLE可 -- ---------------------------- -- Records of sys_config -- ---------------------------- -INSERT INTO "public"."sys_config" VALUES (1143324237579165697, '验证码开关', 'ZEUS_KAPTCHA_OPEN', 'Y', 1106120265689055233, 'DISABLE', '是否开启验证码', 1, 1, '2019-06-24 12:46:43', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370502, '获取token的header标识', 'ZEUS_TOKEN_HEADER_NAME', 'N', NULL, 'Authorization', '获取token的header标识', 1, 1, '2019-10-16 23:02:39', '2021-08-03 16:38:12.432', 'DISABLE'); INSERT INTO "public"."sys_config" VALUES (1143468689664876546, '管理系统名称', 'ZEUS_SYSTEM_NAME', 'N', NULL, 'ZEUS-IOT', '管理系统名称', 1, 1, '2019-06-25 18:39:15', '2021-08-09 17:17:30.189', 'ENABLE'); -INSERT INTO "public"."sys_config" VALUES (1143468867767607207, '默认租户角色ID', 'ZEUS_TENANT_ROLE_ID', 'N', NULL, '1', '默认租户角色ID', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); -INSERT INTO "public"."sys_config" VALUES (1143468867767607208, '单点登录开关', 'ZEUS_SIGN_IN', 'N', NULL, 'DISABLE', '是否启用单点登录', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); -INSERT INTO "public"."sys_config" VALUES (1143468867767607297, '默认系统密码', 'ZEUS_DEFAULT_PASSWORD', 'N', NULL, '111111', '默认系统密码', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); -INSERT INTO "public"."sys_config" VALUES (1143468867767607298, '用户角色ID', 'ZEUS_ADMIN_ROLE_ID', 'N', NULL, '3', '用户角色ID', 1, 1, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370501, '获取系统地密钥过期时间', 'ZEUS_JWT_SECRET_EXPIRE', 'N', NULL, '86400', '获取系统地密钥过期时间(单位:秒),默认1天', 1, 1, '2019-10-16 23:02:39', '2021-08-03 16:38:12.432', 'ENABLE'); INSERT INTO "public"."sys_config" VALUES (1143469008025133058, 'OAuth2登录用户的账号标识', 'ZEUS_OAUTH2_PREFIX', 'N', NULL, 'oauth2', 'OAuth2登录用户的账号标识', 1, 1, '2019-06-25 18:40:31', '2021-08-03 16:38:12.432', 'ENABLE'); -INSERT INTO "public"."sys_config" VALUES (1145915627211370496, '全局主机组Id', 'ZEUS_HOST_GROUP_ID', 'Y', NULL, '19', '全局主机和模板组ID', NULL, NULL, NULL, NULL, 'DISABLE'); -INSERT INTO "public"."sys_config" VALUES (1145915627211370497, '离线回调ActionId', 'ZEUS_OFFLINE_ACTION_ID', 'Y', NULL, '7', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); -INSERT INTO "public"."sys_config" VALUES (1145915627211370498, 'Zeus发布的编号', 'ZEUS_SYSTEM_RELEASE_VERSION', 'N', NULL, '10', '用于防止浏览器缓存相关的js和css', 1, 1, '2019-07-02 12:42:30', '2021-08-03 16:38:12.432', 'ENABLE'); INSERT INTO "public"."sys_config" VALUES (1145915627211370499, '文件上传路径', 'ZEUS_FILE_UPLOAD_PATH', 'N', NULL, '/tmp', '文件上传默认目录', 1, 1, '2019-08-30 09:10:40', '2021-08-03 16:38:12.432', 'ENABLE'); -INSERT INTO "public"."sys_config" VALUES (1145915627211370501, '获取系统地密钥过期时间', 'ZEUS_JWT_SECRET_EXPIRE', 'N', NULL, '86400', '获取系统地密钥过期时间(单位:秒),默认1天', 1, 1, '2019-10-16 23:02:39', '2021-08-03 16:38:12.432', 'ENABLE'); -INSERT INTO "public"."sys_config" VALUES (1145915627211370502, '获取token的header标识', 'ZEUS_TOKEN_HEADER_NAME', 'N', NULL, 'Authorization', '获取token的header标识', 1, 1, '2019-10-16 23:02:39', '2021-08-03 16:38:12.432', 'DISABLE'); -INSERT INTO "public"."sys_config" VALUES (1145915627211370503, '告警回调ActionId', 'ZEUS_ALARM_ACTION_ID', 'Y', NULL, '8', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); -INSERT INTO "public"."sys_config" VALUES (1145915627211370504, '动作回调ActionId', 'ZEUS_EXEC_ACTION_ID', 'Y', NULL, '9', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); -INSERT INTO "public"."sys_config" VALUES (1145915627211370505, '事件回调ActionId', 'ZEUS_EVENT_ACTION_ID', 'Y', NULL, '10', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1143324237579165697, '验证码开关', 'ZEUS_KAPTCHA_OPEN', 'Y', 1106120265689055233, 'DISABLE', '是否开启验证码', 1, 1, '2019-06-24 12:46:43', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370498, 'Zeus发布的编号', 'ZEUS_SYSTEM_RELEASE_VERSION', 'N', NULL, '10', '用于防止浏览器缓存相关的js和css', 1, 1, '2019-07-02 12:42:30', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468867767607297, '默认系统密码', 'ZEUS_DEFAULT_PASSWORD', 'N', NULL, '111111', '默认系统密码', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468867767607208, '单点登录开关', 'ZEUS_SIGN_IN', 'N', NULL, 'ENABLE', '是否启用单点登录', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468867767607207, '默认租户角色ID', 'ZEUS_TENANT_ROLE_ID', 'N', NULL, '2', '默认租户角色ID', 1, 122, '2019-06-25 18:39:57', '2021-09-28 09:46:39.421', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370496, '全局主机组Id', 'ZEUS_HOST_GROUP_ID', 'Y', NULL, '19', '全局主机和模板组ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468867767607298, '用户角色ID', 'ZEUS_ADMIN_ROLE_ID', 'N', NULL, '3', '用户角色ID', 1, 1, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370497, '离线回调ActionId', 'ZEUS_OFFLINE_ACTION_ID', 'Y', NULL, '15', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370503, '告警回调ActionId', 'ZEUS_ALARM_ACTION_ID', 'Y', NULL, '16', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370504, '动作回调ActionId', 'ZEUS_EXEC_ACTION_ID', 'Y', NULL, '17', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370505, '事件回调ActionId', 'ZEUS_EVENT_ACTION_ID', 'Y', NULL, '18', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); -- ---------------------------- -- Table structure for sys_dict @@ -1127,29 +1183,15 @@ INSERT INTO "public"."sys_dict" VALUES (1423897784372199424, 1423840415470653440 INSERT INTO "public"."sys_dict" VALUES (1423897784372199425, 1160532886713155587, 'wechat', '企业微信', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199426, 1160532886713155587, 'dingtalk', '钉钉', 'ENABLE', 2, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199427, 1160532886713155587, 'feishu', '飞书', 'ENABLE', 3, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199428, 1160532886713155588, '2', '主动上报', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199430, 1160532886713155588, '18', '根据单个属性预处理', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199431, 1160532886713155590, '3', '整数', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199432, 1160532886713155590, '0', '小数', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199433, 1160532886713155590, '1', '字符', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199434, 1160532886713155590, '4', '文本', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199435, 1160532886713155589, '%', '百分比', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199436, 1160532886713155589, 'count', '次', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199437, 1160532886713155589, 'r/min', '转每分钟', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199438, 1160532886713155589, 'nm', '纳米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199439, 1160532886713155589, 'μm', '微米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199440, 1160532886713155589, 'mm', '毫米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199441, 1160532886713155589, 'cm', '厘米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199442, 1160532886713155589, 'm', '米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199443, 1160532886713155589, 'km', '千米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199444, 1160532886713155589, 'mm²', '平方毫米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199445, 1160532886713155589, 'cm²', '平方厘米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199446, 1160532886713155589, 'm²', '平方米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199447, 1160532886713155589, 'km²', '平方千米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199448, 1160532886713155589, 'hm²', '公顷', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199449, 1160532886713155589, 'd', '天', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199450, 1160532886713155589, 'h', '小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199451, 1160532886713155589, 'min', '分钟', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199470, 1160532886713155589, 'mg', '毫克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199471, 1160532886713155589, 'g', '克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199472, 1160532886713155589, 'kg', '千克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199473, 1160532886713155589, 't', '吨', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199474, 1160532886713155589, 'Pa', '帕斯卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '压力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199475, 1160532886713155589, 'kPa', '千帕斯卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '压力单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199452, 1160532886713155589, 's', '秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199453, 1160532886713155589, 'ms', '毫秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199454, 1160532886713155589, 'μs', '微秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); @@ -1167,23 +1209,42 @@ INSERT INTO "public"."sys_dict" VALUES (1423897784372199465, 1160532886713155589 INSERT INTO "public"."sys_dict" VALUES (1423897784372199466, 1160532886713155589, 'cm³/h', '立方厘米每小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199467, 1160532886713155589, 'l/h', '升每小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199468, 1160532886713155589, 'mL', '毫升', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '容积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199469, 1160532886713155589, 'L', '升', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '容积单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199470, 1160532886713155589, 'mg', '毫克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199471, 1160532886713155589, 'g', '克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199472, 1160532886713155589, 'kg', '千克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199473, 1160532886713155589, 't', '吨', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199474, 1160532886713155589, 'Pa', '帕斯卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '压力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199475, 1160532886713155589, 'kPa', '千帕斯卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '压力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199476, 1160532886713155589, 'N', '牛顿', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199477, 1160532886713155589, 'N.m', '牛·米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199478, 1160532886713155589, 'K', '开尔文', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199479, 1160532886713155589, '℃', '摄氏度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199480, 1160532886713155589, '℉', '华氏度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199481, 1160532886713155589, 'J', '焦耳', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能量单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199482, 1160532886713155589, 'cal', '卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能量单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199483, 1160532886713155589, 'W', '瓦特', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '功率单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199484, 1160532886713155589, 'kW', '千瓦特', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '功率单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199485, 1160532886713155589, 'rad', '弧度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199435, 1160532886713155589, '%', '百分比', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199432, 1160532886713155590, '0', '浮点数', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199437, 1160532886713155589, 'r/min', '转每分钟', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199438, 1160532886713155589, 'nm', '纳米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199439, 1160532886713155589, 'μm', '微米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199440, 1160532886713155589, 'mm', '毫米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199441, 1160532886713155589, 'cm', '厘米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199442, 1160532886713155589, 'm', '米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199443, 1160532886713155589, 'km', '千米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199444, 1160532886713155589, 'mm²', '平方毫米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199445, 1160532886713155589, 'cm²', '平方厘米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199446, 1160532886713155589, 'm²', '平方米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199447, 1160532886713155589, 'km²', '平方千米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199448, 1160532886713155589, 'hm²', '公顷', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199449, 1160532886713155589, 'd', '天', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199450, 1160532886713155589, 'h', '小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199451, 1160532886713155589, 'min', '分钟', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199428, 1160532886713155588, '2', '主动上报', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199430, 1160532886713155588, '18', '根据单个属性预处理', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199436, 1160532886713155589, 'count', '次', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199506, 1160532886713155591, '25', 'Replace', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199507, 1160532886713155591, '4', 'Trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199508, 1160532886713155591, '2', 'Right trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199509, 1160532886713155591, '3', 'Left trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199510, 1160532886713155591, '11', 'XML XPath', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '结构化数据'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199511, 1160532886713155591, '12', 'JSONPath', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '结构化数据'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199514, 1160532886713155591, '1', '自定义倍数', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '自定义计算'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199517, 1160532886713155591, '7', '八进制转十进制', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '数制转换'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199518, 1160532886713155591, '8', '十六进制转十进制', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '数制转换'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199519, 1160532886713155591, '21', 'JavaScript', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '自定义脚本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199500, 1160532886713155589, 'Ω', '欧姆', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199501, 1160532886713155589, 'KΩ', '千欧', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199502, 1160532886713155589, 'MΩ', '兆欧', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199503, 1160532886713155589, 'eV', '电子伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199504, 1160532886713155589, 'kW·h', '千瓦·时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199505, 1160532886713155589, 'kgce', 'Kg标准煤', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能源单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199486, 1160532886713155589, '°', '度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199487, 1160532886713155589, '′', '[角]分', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199488, 1160532886713155589, '″', '[角]秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); @@ -1198,34 +1259,30 @@ INSERT INTO "public"."sys_dict" VALUES (1423897784372199496, 1160532886713155589 INSERT INTO "public"."sys_dict" VALUES (1423897784372199497, 1160532886713155589, 'mV', '毫伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199498, 1160532886713155589, 'μV', '微伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); INSERT INTO "public"."sys_dict" VALUES (1423897784372199499, 1160532886713155589, 'A', '安培', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199500, 1160532886713155589, 'Ω', '欧姆', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199501, 1160532886713155589, 'KΩ', '千欧', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199502, 1160532886713155589, 'MΩ', '兆欧', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199503, 1160532886713155589, 'eV', '电子伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199504, 1160532886713155589, 'kW·h', '千瓦·时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199505, 1160532886713155589, 'kgce', 'Kg标准煤', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能源单位'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199506, 1160532886713155591, '25', 'Replace', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199507, 1160532886713155591, '4', 'Trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199508, 1160532886713155591, '2', 'Right trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199509, 1160532886713155591, '3', 'Left trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199510, 1160532886713155591, '11', 'XML XPath', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '结构化数据'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199511, 1160532886713155591, '12', 'JSONPath', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '结构化数据'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199469, 1160532886713155589, 'L', '升', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '容积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199476, 1160532886713155589, 'N', '牛顿', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199477, 1160532886713155589, 'N.m', '牛·米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199478, 1160532886713155589, 'K', '开尔文', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199479, 1160532886713155589, '℃', '摄氏度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199480, 1160532886713155589, '℉', '华氏度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199481, 1160532886713155589, 'J', '焦耳', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199482, 1160532886713155589, 'cal', '卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199483, 1160532886713155589, 'W', '瓦特', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '功率单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199484, 1160532886713155589, 'kW', '千瓦特', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '功率单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199485, 1160532886713155589, 'rad', '弧度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); +INSERT INTO "public"."sys_dict" VALUES (1428599180229115911, 1428599180229115904, '0', '', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1428599180229115912, 1428599180229115904, '1', '是', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1429987619034984449, 1142859918022911591, '1', '异步', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1429987619034984450, 1142859918022911591, '0', '同步', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199512, 1160532886713155591, '13', 'In range', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '验证'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199514, 1160532886713155591, '1', '自定义倍数', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '自定义计算'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199517, 1160532886713155591, '7', '八进制转十进制', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '数制转换'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199518, 1160532886713155591, '8', '十六进制转十进制', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '数制转换'); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199519, 1160532886713155591, '21', 'JavaScript', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '自定义脚本'); +INSERT INTO "public"."sys_dict" VALUES (1440492197892923392, 1440492197679013888, 'SSm5lxzi', '三石Test3OrlDb', 'DISABLE', 99, NULL, '2021-09-22 09:44:37.685', '2021-09-22 09:44:37.755', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199531, 1160532886713155588, '0', 'Agent 采集', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199525, 1440492220332449792, '5', '紧急', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199526, 1440492220332449792, '4', '高级', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199527, 1440492220332449792, '3', '中级', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199528, 1440492220332449792, '1', '信息', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO "public"."sys_dict" VALUES (1423897784372199529, 1440492220332449792, '2', '低级', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1423897784372199531, 1160532886713155588, '0', 'Agent 采集', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1428599180229115911, 1428599180229115904, '0', '', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1428599180229115912, 1428599180229115904, '1', '是', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1429987619034984449, 1142859918022911591, '1', '异步', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1429987619034984450, 1142859918022911591, '0', '同步', 'ENABLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL); -INSERT INTO "public"."sys_dict" VALUES (1440492197892923392, 1440492197679013888, 'SSm5lxzi', '三石Test3OrlDb', 'DISABLE', 99, NULL, '2021-09-22 09:44:37.685', '2021-09-22 09:44:37.755', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1455808814382129152, 1455807294571880448, '22', '12', 'ENABLE', NULL, '22', '2021-11-03 16:07:23.625', '2021-11-03 16:08:10.475', 1, 1, NULL); -- ---------------------------- -- Table structure for sys_dict_type @@ -1261,24 +1318,25 @@ COMMENT ON TABLE "public"."sys_dict_type" IS '字典类型表'; -- ---------------------------- -- Records of sys_dict_type -- ---------------------------- -INSERT INTO "public"."sys_dict_type" VALUES (1106120208097067009, 'SEX', '性别', '', 'Y', 'ENABLE', 4, '2019-03-14 17:09:43', 1, NULL, NULL); INSERT INTO "public"."sys_dict_type" VALUES (1106120265689055233, 'STATUS', '状态', '', 'Y', 'ENABLE', 3, '2019-03-14 17:09:57', 1, NULL, NULL); INSERT INTO "public"."sys_dict_type" VALUES (1106120322450571266, 'ACCOUNT_STATUS', '账号状态', '', 'Y', 'ENABLE', 40, '2019-03-14 17:10:10', 1, '2019-08-11 20:46:38', 1); INSERT INTO "public"."sys_dict_type" VALUES (1106120388036902914, 'DEL_FLAG', '是否删除', '', 'Y', 'ENABLE', 2, '2019-03-14 17:10:26', 1, '2019-03-27 16:26:31', 1); -INSERT INTO "public"."sys_dict_type" VALUES (1142859918022911591, 'EXECUTE_TYPE', '服务执行方式', '服务执行方式', 'N', 'ENABLE', 1, NULL, NULL, '2021-09-10 15:56:14.127', 1); INSERT INTO "public"."sys_dict_type" VALUES (1149217131989069826, 'SYSTEM_TYPE', '系统分类', '系统所有分类的维护', 'Y', 'ENABLE', 50, '2019-07-11 15:21:30', 1, '2019-08-11 20:46:47', 1); INSERT INTO "public"."sys_dict_type" VALUES (1160532704105742337, 'FLOW_CATEGARY', '工作流分类', '工作流分类', 'Y', 'ENABLE', 60, '2019-08-11 20:45:33', 1, NULL, NULL); INSERT INTO "public"."sys_dict_type" VALUES (1160532775455047681, 'FLOW_KEY', '工作流标识', '工作流标识', 'Y', 'ENABLE', 70, '2019-08-11 20:45:50', 1, NULL, NULL); INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155585, 'LEAVE_TYPE', '请假类型', '请假类型', 'Y', 'ENABLE', 80, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); -INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155586, 'DEVICE_TYPE', '设备类型', '设备类型', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1106120208097067009, 'SEX', '性别', '', 'Y', 'ENABLE', 4, '2019-03-14 17:09:43', 1, NULL, NULL); +INSERT INTO "public"."sys_dict_type" VALUES (1423160140530053120, 'DICTTYPE', '字典类型', '测试', 'N', 'ENABLE', NULL, '2021-08-05 13:53:13.196', 1, '2021-08-05 13:53:13.196', 1); INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155587, 'MEDIA_TYPE', '通知类型', '通知类型', 'N', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155586, 'DEVICE_TYPE', '设备类型', '设备类型', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155588, 'ATTR_TYPE', '产品属性类型', '产品属性类型', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155589, 'UNITS', '产品属性单位', '产品属性单位', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155590, 'DATA_TYPE', '产品属性值类型', '产品属性值类型', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155591, 'DATA_PRE_TYPE', '数据预处理方法名称', '数据预处理方法名称', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); -INSERT INTO "public"."sys_dict_type" VALUES (1423160140530053120, 'DICTTYPE', '字典类型', '测试', 'N', 'ENABLE', NULL, '2021-08-05 13:53:13.196', 1, '2021-08-05 13:53:13.196', 1); -INSERT INTO "public"."sys_dict_type" VALUES (1428599180229115904, 'WHETHER', '是否', '是否', 'N', 'ENABLE', NULL, '2021-08-20 14:06:01.311', 1, '2021-08-20 14:06:01.311', 1); INSERT INTO "public"."sys_dict_type" VALUES (1440492220332449792, 'EVENT_LEVEL', '告警级别', '告警级别', 'N', 'ENABLE', NULL, '2021-09-22 09:44:43.035', 1, '2021-09-22 09:44:43.102', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1455807294571880448, '456456', '456456', '', 'N', 'ENABLE', NULL, '2021-11-03 16:01:21.274', 1, '2021-11-03 16:01:21.274', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1142859918022911591, 'EXECUTE_TYPE', '服务执行方式', '服务执行方式', 'N', 'ENABLE', 1, NULL, NULL, '2021-09-10 15:56:14.127', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1428599180229115904, 'WHETHER', '是否', '是否', 'N', 'ENABLE', NULL, '2021-08-20 14:06:01.311', 1, '2021-08-20 14:06:01.311', 1); -- ---------------------------- -- Table structure for sys_login_log @@ -1291,9 +1349,11 @@ CREATE TABLE "public"."sys_login_log" ( "message" text COLLATE "pg_catalog"."default", "ip_address" varchar(255) COLLATE "pg_catalog"."default", "create_time" timestamp(6), - "login_log_id" int8 NOT NULL + "login_log_id" int8 NOT NULL, + "tenant_id" int8 ) ; +COMMENT ON COLUMN "public"."sys_login_log"."tenant_id" IS '租户ID'; -- ---------------------------- -- Records of sys_login_log @@ -1344,75 +1404,89 @@ COMMENT ON COLUMN "public"."sys_menu"."admin_flag" IS '是否是超级管理员 -- ---------------------------- -- Records of sys_menu -- ---------------------------- -INSERT INTO "public"."sys_menu" VALUES (105, 'system', '0', '[0],', '系统管理', 'layui-icon layui-icon-set', '/system', 20, 1, 'Y', NULL, 'ENABLE', NULL, '2019-03-29 16:32:27', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (106, 'userMgr', '0', '[0],', '用户管理', '', '/userMgr', 10, 1, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (107, 'mgr_add', 'mgr', '[0],[system],[mgr],', '添加用户', NULL, '/mgr/add', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (108, 'mgr_edit', 'mgr', '[0],[system],[mgr],', '修改用户', NULL, '/mgr/edit', 2, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (109, 'mgr_delete', 'mgr', '[0],[system],[mgr],', '删除用户', NULL, '/mgr/delete', 3, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (110, 'reset', 'mgr', '[0],[system],[mgr],', '重置密码', NULL, '/mgr/reset', 4, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (113, 'mgr_setRole', 'mgr', '[0],[system],[mgr],', '分配角色', NULL, '/mgr/setRole', 7, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (114, 'role', 'system', '[0],[system],', '角色管理', '', '/system/role', 20, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (115, 'role_add', 'role', '[0],[system],[role],', '添加角色', NULL, '/role/add', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (116, 'role_edit', 'role', '[0],[system],[role],', '修改角色', NULL, '/role/edit', 2, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (117, 'role_remove', 'role', '[0],[system],[role],', '删除角色', NULL, '/role/remove', 3, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (119, 'menu', 'system', '[0],[system],', '菜单管理', '', '/menu', 50, 2, 'Y', NULL, 'DISABLE', NULL, '2019-06-30 13:48:25', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (128, 'businessLog', 'log', '[0],[log],', '业务日志', '', '/log/businessLog', 70, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:39', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (132, 'dict', 'system', '[0],[system],', '字典管理', '', '/system/dictType', 40, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (133, 'loginLog', 'log', '[0],[log],', '登录日志', '', '/log/loginLog', 60, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:49:29', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (138, 'dict_add', 'dict', '[0],[system],[dict],', '添加字典', NULL, '/dictType/addItem', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (139, 'dict_update', 'dict', '[0],[system],[dict],', '修改字典', NULL, '/dictType/editItem', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (140, 'dict_delete', 'dict', '[0],[system],[dict],', '删除字典', NULL, '/dictType/delete', 1, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (151, 'menu_list', 'menu', '[0],[system],[menu],', '菜单列表', '', '/menu/list', 5, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:25', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (156, 'dict_list', 'dict', '[0],[system],[dict],', '字典列表', '', '/dict/list', 5, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:49:04', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (158, 'log_list', 'log', '[0],[system],[log],', '日志列表', '', '/log/list', 2, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:39', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (164, 'role_list', 'role', '[0],[system],[role],', '角色列表', '', '/role/list', 7, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (167, 'mgr_list', 'mgr', '[0],[system],[mgr],', '用户列表', '', '/mgr/list', 10, 3, 'N', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (168, 'usrGrp', 'userMgr', '[0],[userMgr],', '用户组管理', NULL, '/userMgr/userGroup', 9, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (169, 'analyse', '0', '[0],', '统计分析', NULL, '/analyse', 1, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (170, 'dev_mgr', '0', '[0],', '设备管理', NULL, '/deviceMgr', 2, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (171, 'product_mgr', '0', '[0],', '产品管理', NULL, '/productMgr', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (173, 'view', '0', '[0],', '可视化', NULL, '/view', 3, 1, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (174, 'auth', '0', '[0],', '平台授权', NULL, '/auth', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (176, 'dev_log', 'analyse', '[0],[analyse],', '设备日志', NULL, '/analyse/devLog', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (177, 'dev', 'dev_mgr', '[0],[dev_mgr],', '设备', NULL, '/deviceMgr/device', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (178, 'dev_group', 'dev_mgr', '[0],[dev_mgr],', '设备组', NULL, '/deviceMgr/deviceGroup', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (179, 'alarmList', 'alarm', '[0],[alarm],', '告警记录', NULL, '/alarm/alarmList', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (180, 'product', 'product_mgr', '[0],[product_mgr],', '产品', NULL, '/productMgr/product', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (181, 'product_type', 'product_mgr', '[0],[product_mgr],', '产品分类', NULL, '/productMgr/productType', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (183, 'grafana', 'view', '[0],[view],', 'Grafana配置', NULL, '/view/grafana', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (184, 'log', '0', '[0]', '日志管理', NULL, '/log', 4, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (186, 'sysParam', 'system', '[0],[system],', '系统参数', '', '/system/sysParam', 10, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'Y'); -INSERT INTO "public"."sys_menu" VALUES (187, 'media', 'system', '[0],[system],', '通知配置', '', '/system/media', 80, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:50:06', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (189, 'home', 'analyse', '[0],[analyse],', '全局概览', NULL, '/analyse/home', 1, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (190, 'latest', 'analyse', '[0],[analyse],', '最新数据', NULL, '/analyse/latest', 1, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (113, 'mgr_setRole', 'mgr', '[0],[userMgr],[mgr],', '分配角色', NULL, '/mgr/setRole', 7, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (119, 'menu', 'system', '[0],[system],', '菜单管理', NULL, '/menu', 50, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (167, 'mgr_list', 'mgr', '[0],[userMgr],[mgr],', '用户列表', NULL, '/mgr/list', 10, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (120, 'menu_add', 'menu', '[0],[system],[menu],', '添加菜单', NULL, '/menu/add', 1, 3, 'N', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (173, 'view', '0', '[0],', '可视化', NULL, '/view', 99, 1, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (164, 'role_list', 'role', '[0],[system],[role],', '角色列表', NULL, '/role/list', 7, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); INSERT INTO "public"."sys_menu" VALUES (191, 'alarmAnalyse', 'alarm', '[0],[alarm],', '告警分析', NULL, '/alarm/analyse', 3, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (192, 'alarm', '0', '[0],', '告警管理', NULL, '/alarm', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (183, 'grafana', 'view', '[0],[view],', 'Grafana配置', NULL, '/view/grafana', 3, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (121, 'menu_edit', 'menu', '[0],[system],[menu],', '修改菜单', NULL, '/menu/edit', 2, 3, 'N', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (115, 'role_add', 'role', '[0],[system],[role],', '添加角色', NULL, '/role/add', 1, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (122, 'menu_remove', 'menu', '[0],[system],[menu],', '删除菜单', NULL, '/menu/remove', 3, 3, 'N', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (179, 'alarmList', 'alarm', '[0],[alarm],', '告警记录', NULL, '/alarm/alarmList', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (109, 'mgr_delete', 'mgr', '[0],[userMgr],[mgr],', '删除用户', NULL, '/mgr/delete', 3, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (116, 'role_edit', 'role', '[0],[system],[role],', '修改角色', NULL, '/role/edit', 2, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (117, 'role_remove', 'role', '[0],[system],[role],', '删除角色', NULL, '/role/remove', 3, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (118, 'role_setAuthority', 'role', '[0],[system],[role],', '配置菜单', NULL, '/role/setAuthority', 4, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (140, 'dict_delete', 'dict', '[0],[system],[dict],', '删除字典', NULL, '/dictType/delete', 1, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (151, 'menu_list', 'menu', '[0],[system],[menu],', '菜单列表', NULL, '/menu/list', 5, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (156, 'dict_list', 'dict', '[0],[system],[dict],', '字典列表', NULL, '/dict/list', 5, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (138, 'dict_add', 'dict', '[0],[system],[dict],', '添加字典', NULL, '/dictType/addItem', 1, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (169, 'analyse', '0', '[0],', '统计分析', NULL, '/analyse', 1, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (139, 'dict_update', 'dict', '[0],[system],[dict],', '修改字典', NULL, '/dictType/editItem', 1, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (107, 'mgr_add', 'mgr', '[0],[userMgr],[mgr],', '添加用户', NULL, '/mgr/add', 1, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (197, 'about', '0', '[0],', '关于我们', NULL, '/about', 99, 1, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (108, 'mgr_edit', 'mgr', '[0],[userMgr],[mgr],', '修改用户', NULL, '/mgr/edit', 2, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (207, 'product_add', 'product', '[0],[product_mgr],[product],', '增加产品', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (189, 'home', 'analyse', '[0],[analyse],', '全局概览', NULL, '/analyse/home', 1, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (206, 'dev_detail', 'dev', '[0],[dev_mgr],[dev],', '设备详情', NULL, '/deviceMgr/device/detail', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (205, 'dev_list', 'dev', '[0],[dev_mgr],[dev],', '设备列表', NULL, '/deviceMgr/device/list', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (204, 'dev_delete', 'dev', '[0],[dev_mgr],[dev],', '删除设备', NULL, '/deviceMgr/device/delete', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (203, 'dev_update', 'dev', '[0],[dev_mgr],[dev],', '修改设备', NULL, '/deviceMgr/device/update', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (202, 'dev_add', 'dev', '[0],[dev_mgr],[dev],', '增加设备', NULL, '/deviceMgr/device/add', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (158, 'log_list', 'log', '[0],[system],[log],', '日志列表', NULL, '/log/list', 2, 3, 'N', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (213, 'tenant_add', 'tenant', '[0],[system],', '租户增加', NULL, '/system/tenant', 10, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (214, 'tenant_update', 'tenant', '[0],[system],', '租户修改', NULL, '/system/tenant', 10, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (215, 'tenant_list', 'tenant', '[0],[system],', '租户列表', NULL, '/system/tenant', 10, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (216, 'tenant_delete', 'tenant', '[0],[system],', '租户删除', NULL, '/system/tenant', 10, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); INSERT INTO "public"."sys_menu" VALUES (193, 'scene ', 'rule', '[0],[rule],', '场景联动', NULL, '/rule/scene', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (194, 'rule', '0', '[0],', '规则引擎', NULL, '/rule', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (195, 'nodeRed', 'rule', '[0],[rule],', 'Node-Red', NULL, '/rule/nodeRed', 3, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (196, 'api', 'dev_mgr', '[0],[dev_mgr],', '设备调试', NULL, '/deviceMgr/debug', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (197, 'about', '0', '[0],', '关于我们', NULL, '/about', 2, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (198, 'proxy', 'system', '[0],', '边缘采集', '', '/proxy', 20, 1, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (199, 'proxyInfo', 'system', '[0],[proxy],', '代理管理', '', '/proxy/proxyInfo', 20, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (200, 'proxyMonitor', 'system', '[0],[proxy],', '代理监控', '', '/proxy/proxyMonitor', 20, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:12', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (201, 'grafana', 'analyse', '[0],[analyse],', 'Grafana 演示大屏', NULL, '/analyse/grafana', 5, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (202, 'dev_add', 'dev', '[0],[dev_mgr],[dev]', '增加设备', NULL, '/deviceMgr/device/add', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (203, 'dev_update', 'dev', '[0],[dev_mgr],[dev]', '修改设备', NULL, '/deviceMgr/device/update', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (204, 'dev_delete', 'dev', '[0],[dev_mgr],[dev]', '删除设备', NULL, '/deviceMgr/device/delete', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (205, 'dev_list', 'dev', '[0],[dev_mgr],[dev]', '设备列表', NULL, '/deviceMgr/device/list', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (206, 'dev_detail', 'dev', '[0],[dev_mgr],[dev]', '设备详情', NULL, '/deviceMgr/device/detail', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (207, 'product_add', 'product', '[0],[product_mgr],[product]', '增加产品', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (208, 'product_update', 'product', '[0],[product_mgr],[product]', '修改产品', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (209, 'product_delete', 'product', '[0],[product_mgr],[product]', '删除产品', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (210, 'product_list', 'product', '[0],[product_mgr],[product]', '产品列表', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (211, 'product_detail', 'product', '[0],[product_mgr],[product]', '产品详情', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -INSERT INTO "public"."sys_menu" VALUES (212, 'tenant', 'system', '[0],[system],', '租户管理', '', '/system/tenant', 10, 2, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (213, 'tenant_add', 'tenant', '[0],[system],', '租户增加', '', '/system/tenant', 10, 3, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (214, 'tenant_update', 'tenant', '[0],[system],', '租户修改', '', '/system/tenant', 10, 3, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (215, 'tenant_list', 'tenant', '[0],[system],', '租户列表', '', '/system/tenant', 10, 3, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (216, 'tenant_delete', 'tenant', '[0],[system],', '租户删除', '', '/system/tenant', 10, 3, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (217, 'mgr', 'userMgr', '[0],[userMgr],', '用户', '', '/userMgr/user', 10, 1, 'Y', NULL, 'ENABLE', NULL, '2019-06-30 13:48:07', NULL, 1, 'N'); -INSERT INTO "public"."sys_menu" VALUES (218, 'distributed', 'dev_mgr', '[0],[dev_mgr],', '设备分布', NULL, '/deviceMgr/distributed', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (217, 'mgr', 'userMgr', '[0],[userMgr],', '用户', NULL, '/userMgr/user', 101, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (187, 'media', 'system', '[0],[system],', '通知配置', NULL, '/system/media', 115, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (133, 'loginLog', 'log', '[0],[log],', '登录日志', NULL, '/log/loginLog', 92, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (201, 'grafana', 'analyse', '[0],[analyse],', '数据大屏', NULL, '/analyse/grafana', 5, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (190, 'latest', 'analyse', '[0],[analyse],', '最新数据', NULL, '/analyse/latest', 1, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (212, 'tenant', 'system', '[0],[system],', '租户管理', NULL, '/system/tenant', 112, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (198, 'realTime', '0', '[0],', '平台监控', NULL, '/realTime', 7, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (110, 'reset', 'mgr', '[0],[userMgr],[mgr],', '重置密码', NULL, '/mgr/reset', 4, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (174, 'auth', 'system', '[0],[system],', '平台授权', NULL, '/system/auth', 60, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (200, 'proxyMonitor', 'realTime', '[0],[realTime],', '代理监控', NULL, '/realTime/proxy', 82, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (199, 'proxyInfo', 'system', '[0],[system],', '代理配置', NULL, '/system/proxyInfo', 116, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (105, 'system', '0', '[0],', '系统管理', NULL, '/system', 11, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (106, 'userMgr', '0', '[0],', '用户管理', NULL, '/userMgr', 10, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (128, 'businessLog', 'log', '[0],[log],', '业务日志', NULL, '/log/businessLog', 91, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (132, 'dict', 'system', '[0],[system],', '系统字典', NULL, '/system/dictType', 113, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (168, 'usrGrp', 'userMgr', '[0],[userMgr],', '用户组管理', NULL, '/userMgr/userGroup', 102, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (170, 'dev_mgr', '0', '[0],', '设备管理', NULL, '/deviceMgr', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (171, 'product_mgr', '0', '[0],', '产品管理', NULL, '/productMgr', 4, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (176, 'dev_log', 'analyse', '[0],[analyse],', '设备日志', NULL, '/analyse/devLog', 3, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (177, 'dev', 'dev_mgr', '[0],[dev_mgr],', '设备', NULL, '/deviceMgr/device', 41, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (180, 'product', 'product_mgr', '[0],[product_mgr],', '产品', NULL, '/productMgr/product', 51, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (181, 'product_type', 'product_mgr', '[0],[product_mgr],', '产品分类', NULL, '/productMgr/productType', 52, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (184, 'log', '0', '[0],', '系统日志', NULL, '/log', 9, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (186, 'sysParam', 'system', '[0],[system],', '系统参数', NULL, '/system/sysParam', 114, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (192, 'alarm', '0', '[0],', '告警管理', NULL, '/alarm', 6, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (194, 'rule', '0', '[0],', '规则引擎', NULL, '/rule', 5, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (196, 'api', 'dev_mgr', '[0],[dev_mgr],', '设备调试', NULL, '/deviceMgr/debug', 43, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (211, 'product_detail', 'product', '[0],[product_mgr],[product],', '产品详情', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (210, 'product_list', 'product', '[0],[product_mgr],[product],', '产品列表', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (209, 'product_delete', 'product', '[0],[product_mgr],[product],', '删除产品', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (208, 'product_update', 'product', '[0],[product_mgr],[product],', '修改产品', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (195, 'process', 'rule', '[0],[rule],', '流程配置', NULL, '/rule/process', 4, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (219, 'distributed', 'dev_mgr', '[0],[dev_mgr],', '设备分布', NULL, '/deviceMgr/distributed', 3, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (220, 'platformLog', '0', '[0],', '平台日志', NULL, '/platformLog', 8, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (221, 'platformLog_event', 'platformLog', '[0],[platformLog],', '事件日志', NULL, '/platformLog/event', 34, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (222, 'platformLog_service', 'platformLog', '[0],[platformLog],', '服务日志', NULL, '/platformLog/service', 33, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (223, 'platformLog_alert', 'platformLog', '[0],[platformLog],', '告警日志', NULL, '/platformLog/alert', 31, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (224, 'platformLog_linkage', 'platformLog', '[0],[platformLog],', '联动日志', NULL, '/platformLog/linkage', 32, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (225, 'visualization', '0', '[0],', '可视化', NULL, '/visualization', 2, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (226, 'visualization_distributed', 'visualization', '[0],[visualization],', '设备分布', NULL, '/visualization/distributed', 21, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (227, 'visualization_grafana', 'visualization', '[0],[visualization],', 'Grafana', NULL, '/visualization/grafana', 22, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (228, 'visualization_building', 'visualization', '[0],[visualization],', '楼宇场景', NULL, '/visualization/building', 23, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (114, 'role', 'system', '[0],[system],', '角色管理', NULL, '/system/role', 111, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (178, 'dev_group', 'dev_mgr', '[0],[dev_mgr],', '设备组', NULL, '/deviceMgr/deviceGroup', 42, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (218, 'platform', 'realTime', '[0],[realTime],', '主服务监控', NULL, '/realTime/platform', 81, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); -- ---------------------------- -- Table structure for sys_operation_log @@ -1427,7 +1501,8 @@ CREATE TABLE "public"."sys_operation_log" ( "method" varchar(255) COLLATE "pg_catalog"."default", "create_time" timestamp(6), "succeed" varchar(32) COLLATE "pg_catalog"."default", - "message" text COLLATE "pg_catalog"."default" + "message" text COLLATE "pg_catalog"."default", + "tenant_id" int8 ) ; COMMENT ON COLUMN "public"."sys_operation_log"."operation_log_id" IS '操作日志ID'; @@ -1439,6 +1514,7 @@ COMMENT ON COLUMN "public"."sys_operation_log"."method" IS '方法名称'; COMMENT ON COLUMN "public"."sys_operation_log"."create_time" IS '创建时间'; COMMENT ON COLUMN "public"."sys_operation_log"."succeed" IS '是否成功【字典】'; COMMENT ON COLUMN "public"."sys_operation_log"."message" IS '备注'; +COMMENT ON COLUMN "public"."sys_operation_log"."tenant_id" IS '租户ID'; -- ---------------------------- -- Records of sys_operation_log @@ -1463,7 +1539,9 @@ CREATE TABLE "public"."sys_role" ( -- ---------------------------- -- Records of sys_role -- ---------------------------- -INSERT INTO "public"."sys_role" VALUES (1, '超级管理员', 'administrator', 1, NULL, 1, NULL, '2021-08-17 10:57:36.612'); +INSERT INTO "public"."sys_role" VALUES (1, '超级管理员', 'administrator', 1, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_role" VALUES (2, '租户管理员', '', NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_role" VALUES (1443419927773007872, '租户用户', '租户里的普通用户。', NULL, 1, 1, '2021-09-30 11:38:22.882', '2021-09-30 11:50:37.275'); -- ---------------------------- -- Table structure for sys_role_menu @@ -1478,6 +1556,35 @@ CREATE TABLE "public"."sys_role_menu" ( -- ---------------------------- -- Records of sys_role_menu -- ---------------------------- +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 169); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 190); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 189); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 176); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 201); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 170); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 196); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 178); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 177); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 202); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 203); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 204); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 205); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 206); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 171); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 180); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 211); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 207); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 208); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 209); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 210); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 181); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 194); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 193); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 192); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 179); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 184); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 133); +INSERT INTO "public"."sys_role_menu" VALUES (1443419927773007872, 128); INSERT INTO "public"."sys_role_menu" VALUES (1, 169); INSERT INTO "public"."sys_role_menu" VALUES (1, 170); INSERT INTO "public"."sys_role_menu" VALUES (1, 171); @@ -1498,6 +1605,7 @@ INSERT INTO "public"."sys_role_menu" VALUES (1, 184); INSERT INTO "public"."sys_role_menu" VALUES (1, 128); INSERT INTO "public"."sys_role_menu" VALUES (1, 133); INSERT INTO "public"."sys_role_menu" VALUES (1, 132); +INSERT INTO "public"."sys_role_menu" VALUES (1, 217); INSERT INTO "public"."sys_role_menu" VALUES (1, 201); INSERT INTO "public"."sys_role_menu" VALUES (1, 202); INSERT INTO "public"."sys_role_menu" VALUES (1, 203); @@ -1507,11 +1615,13 @@ INSERT INTO "public"."sys_role_menu" VALUES (1, 206); INSERT INTO "public"."sys_role_menu" VALUES (1, 207); INSERT INTO "public"."sys_role_menu" VALUES (1, 208); INSERT INTO "public"."sys_role_menu" VALUES (1, 209); -INSERT INTO "public"."sys_role_menu" VALUES (1, 211); INSERT INTO "public"."sys_role_menu" VALUES (1, 210); +INSERT INTO "public"."sys_role_menu" VALUES (1, 211); INSERT INTO "public"."sys_role_menu" VALUES (1, 212); -INSERT INTO "public"."sys_role_menu" VALUES (1, 217); -INSERT INTO "public"."sys_role_menu" VALUES (1, 219); +INSERT INTO "public"."sys_role_menu" VALUES (1, 213); +INSERT INTO "public"."sys_role_menu" VALUES (1, 214); +INSERT INTO "public"."sys_role_menu" VALUES (1, 215); +INSERT INTO "public"."sys_role_menu" VALUES (1, 216); INSERT INTO "public"."sys_role_menu" VALUES (1, 105); INSERT INTO "public"."sys_role_menu" VALUES (1, 106); INSERT INTO "public"."sys_role_menu" VALUES (1, 107); @@ -1519,6 +1629,53 @@ INSERT INTO "public"."sys_role_menu" VALUES (1, 108); INSERT INTO "public"."sys_role_menu" VALUES (1, 109); INSERT INTO "public"."sys_role_menu" VALUES (1, 110); INSERT INTO "public"."sys_role_menu" VALUES (1, 111); +INSERT INTO "public"."sys_role_menu" VALUES (1, 106); +INSERT INTO "public"."sys_role_menu" VALUES (1, 217); +INSERT INTO "public"."sys_role_menu" VALUES (1, 168); +INSERT INTO "public"."sys_role_menu" VALUES (2, 169); +INSERT INTO "public"."sys_role_menu" VALUES (2, 190); +INSERT INTO "public"."sys_role_menu" VALUES (2, 189); +INSERT INTO "public"."sys_role_menu" VALUES (2, 176); +INSERT INTO "public"."sys_role_menu" VALUES (2, 201); +INSERT INTO "public"."sys_role_menu" VALUES (2, 170); +INSERT INTO "public"."sys_role_menu" VALUES (2, 196); +INSERT INTO "public"."sys_role_menu" VALUES (2, 178); +INSERT INTO "public"."sys_role_menu" VALUES (2, 177); +INSERT INTO "public"."sys_role_menu" VALUES (2, 202); +INSERT INTO "public"."sys_role_menu" VALUES (2, 203); +INSERT INTO "public"."sys_role_menu" VALUES (2, 204); +INSERT INTO "public"."sys_role_menu" VALUES (2, 205); +INSERT INTO "public"."sys_role_menu" VALUES (2, 206); +INSERT INTO "public"."sys_role_menu" VALUES (2, 171); +INSERT INTO "public"."sys_role_menu" VALUES (2, 180); +INSERT INTO "public"."sys_role_menu" VALUES (2, 211); +INSERT INTO "public"."sys_role_menu" VALUES (2, 207); +INSERT INTO "public"."sys_role_menu" VALUES (2, 208); +INSERT INTO "public"."sys_role_menu" VALUES (2, 209); +INSERT INTO "public"."sys_role_menu" VALUES (2, 210); +INSERT INTO "public"."sys_role_menu" VALUES (2, 181); +INSERT INTO "public"."sys_role_menu" VALUES (2, 194); +INSERT INTO "public"."sys_role_menu" VALUES (2, 193); +INSERT INTO "public"."sys_role_menu" VALUES (2, 192); +INSERT INTO "public"."sys_role_menu" VALUES (2, 179); +INSERT INTO "public"."sys_role_menu" VALUES (2, 184); +INSERT INTO "public"."sys_role_menu" VALUES (2, 133); +INSERT INTO "public"."sys_role_menu" VALUES (2, 128); +INSERT INTO "public"."sys_role_menu" VALUES (2, 106); +INSERT INTO "public"."sys_role_menu" VALUES (2, 168); +INSERT INTO "public"."sys_role_menu" VALUES (2, 217); +INSERT INTO "public"."sys_role_menu" VALUES (2, 107); +INSERT INTO "public"."sys_role_menu" VALUES (2, 108); +INSERT INTO "public"."sys_role_menu" VALUES (2, 109); +INSERT INTO "public"."sys_role_menu" VALUES (2, 110); +INSERT INTO "public"."sys_role_menu" VALUES (2, 113); +INSERT INTO "public"."sys_role_menu" VALUES (2, 167); +INSERT INTO "public"."sys_role_menu" VALUES (2, 105); +INSERT INTO "public"."sys_role_menu" VALUES (2, 199); +INSERT INTO "public"."sys_role_menu" VALUES (2, 187); +INSERT INTO "public"."sys_role_menu" VALUES (1, 109); +INSERT INTO "public"."sys_role_menu" VALUES (1, 110); +INSERT INTO "public"."sys_role_menu" VALUES (1, 113); INSERT INTO "public"."sys_role_menu" VALUES (1, 112); INSERT INTO "public"."sys_role_menu" VALUES (1, 113); INSERT INTO "public"."sys_role_menu" VALUES (1, 114); @@ -1530,6 +1687,21 @@ INSERT INTO "public"."sys_role_menu" VALUES (1, 119); INSERT INTO "public"."sys_role_menu" VALUES (1, 120); INSERT INTO "public"."sys_role_menu" VALUES (1, 121); INSERT INTO "public"."sys_role_menu" VALUES (1, 122); +INSERT INTO "public"."sys_role_menu" VALUES (1, 167); +INSERT INTO "public"."sys_role_menu" VALUES (1, 107); +INSERT INTO "public"."sys_role_menu" VALUES (1, 108); +INSERT INTO "public"."sys_role_menu" VALUES (1, 218); +INSERT INTO "public"."sys_role_menu" VALUES (1, 200); +INSERT INTO "public"."sys_role_menu" VALUES (1, 219); +INSERT INTO "public"."sys_role_menu" VALUES (1, 220); +INSERT INTO "public"."sys_role_menu" VALUES (1, 221); +INSERT INTO "public"."sys_role_menu" VALUES (1, 222); +INSERT INTO "public"."sys_role_menu" VALUES (1, 223); +INSERT INTO "public"."sys_role_menu" VALUES (1, 224); +INSERT INTO "public"."sys_role_menu" VALUES (1, 225); +INSERT INTO "public"."sys_role_menu" VALUES (1, 226); +INSERT INTO "public"."sys_role_menu" VALUES (1, 227); +INSERT INTO "public"."sys_role_menu" VALUES (1, 228); INSERT INTO "public"."sys_role_menu" VALUES (1, 185); INSERT INTO "public"."sys_role_menu" VALUES (1, 186); INSERT INTO "public"."sys_role_menu" VALUES (1, 187); @@ -1543,13 +1715,15 @@ INSERT INTO "public"."sys_role_menu" VALUES (1, 194); INSERT INTO "public"."sys_role_menu" VALUES (1, 195); INSERT INTO "public"."sys_role_menu" VALUES (1, 196); INSERT INTO "public"."sys_role_menu" VALUES (1, 197); -INSERT INTO "public"."sys_role_menu" VALUES (1, 213); -INSERT INTO "public"."sys_role_menu" VALUES (1, 214); -INSERT INTO "public"."sys_role_menu" VALUES (1, 215); -INSERT INTO "public"."sys_role_menu" VALUES (1, 216); +INSERT INTO "public"."sys_role_menu" VALUES (1, 140); +INSERT INTO "public"."sys_role_menu" VALUES (1, 156); +INSERT INTO "public"."sys_role_menu" VALUES (1, 138); +INSERT INTO "public"."sys_role_menu" VALUES (1, 139); +INSERT INTO "public"."sys_role_menu" VALUES (1, 164); +INSERT INTO "public"."sys_role_menu" VALUES (1, 167); +INSERT INTO "public"."sys_role_menu" VALUES (1, 106); INSERT INTO "public"."sys_role_menu" VALUES (1, 198); INSERT INTO "public"."sys_role_menu" VALUES (1, 199); -INSERT INTO "public"."sys_role_menu" VALUES (1, 200); -- ---------------------------- -- Table structure for sys_user @@ -1572,6 +1746,7 @@ CREATE TABLE "public"."sys_user" ( "user_id" int8 NOT NULL DEFAULT nextval('sys_user_user_id_seq'::regclass), "zbx_token" varchar(255) COLLATE "pg_catalog"."default", "zbx_id" varchar(64) COLLATE "pg_catalog"."default", + "tenant_id" int8, "remark" varchar(255) COLLATE "pg_catalog"."default" ) ; @@ -1591,13 +1766,13 @@ COMMENT ON COLUMN "public"."sys_user"."update_time" IS '更新时间'; COMMENT ON COLUMN "public"."sys_user"."user_id" IS '用户ID'; COMMENT ON COLUMN "public"."sys_user"."zbx_token" IS 'zabbix 登陆 token'; COMMENT ON COLUMN "public"."sys_user"."zbx_id" IS 'zabbix 用户ID'; +COMMENT ON COLUMN "public"."sys_user"."tenant_id" IS '租户ID'; COMMENT ON COLUMN "public"."sys_user"."remark" IS '备注'; -- ---------------------------- -- Records of sys_user -- ---------------------------- -INSERT INTO "public"."sys_user" VALUES ('root', '17db03c22596b7609c7c9704f16663e0', 'abcdef', '超级管理员', '888888@qq.com', '13812345678', 1, 1437232484602372096, 'ENABLE', 1, 1, '2021-07-30 21:43:02.686', '2021-07-30 21:43:02.686', 1, '5859e004e8d2a23e6c330c3f9cd277e2', '4', NULL); -INSERT INTO "public"."sys_user" VALUES ('Admin', 'cbde417443393372dbac9c185a6ec159', 'gt3zs', '超级管理员', '', '', 1, 1437232484602372096, 'ENABLE', 1, 1, '2021-09-28 09:38:33.668', '2021-09-28 09:38:33.668', 122, 'f6ce31c5f70bf40fae2067087254202c', '1', NULL); +INSERT INTO "public"."sys_user" VALUES ('Admin', 'cbde417443393372dbac9c185a6ec159', 'gt3zs', '超级管理员', '', '', 1, 1437232484602372096, 'ENABLE', 1, 1, '2021-09-28 09:38:33.668', '2021-09-28 09:38:33.668', 1, '5613ff8a39fe5998d61873ccd450edae', '1', NULL, NULL); -- ---------------------------- -- Table structure for sys_user_group @@ -1612,13 +1787,16 @@ CREATE TABLE "public"."sys_user_group" ( "update_time" timestamp(0), "update_user" int8, "status" varchar(32) COLLATE "pg_catalog"."default" DEFAULT 1, - "user_group_id" int8 NOT NULL + "user_group_id" int8 NOT NULL, + "tenant_id" int8 ) ; +COMMENT ON COLUMN "public"."sys_user_group"."tenant_id" IS '租户ID'; -- ---------------------------- -- Records of sys_user_group -- ---------------------------- +INSERT INTO "public"."sys_user_group" VALUES ('超级管理员组', '7', NULL, NULL, 1, '2021-10-11 11:40:12', 1, 'ENABLE', 1437232484602372096, NULL); -- ---------------------------- -- Table structure for sys_usrgrp_devicegrp @@ -1702,19 +1880,47 @@ COMMENT ON COLUMN "public"."task_info"."executor_param" IS '任务执行参数'; -- Records of task_info -- ---------------------------- +-- ---------------------------- +-- Table structure for tenant_info +-- ---------------------------- +DROP TABLE IF EXISTS "public"."tenant_info"; +CREATE TABLE "public"."tenant_info" ( + "tenant_id" int8 NOT NULL, + "name" varchar(64) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "create_time" timestamp(0), + "create_user" int8, + "update_time" timestamp(0), + "update_user" int8, + "account" varchar(32) COLLATE "pg_catalog"."default", + "contact" varchar(16) COLLATE "pg_catalog"."default", + "phone" varchar(16) COLLATE "pg_catalog"."default", + "status" varchar(8) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."tenant_info"."name" IS '租户名称'; +COMMENT ON COLUMN "public"."tenant_info"."account" IS '租户管理员 账号'; +COMMENT ON COLUMN "public"."tenant_info"."contact" IS '联系人'; +COMMENT ON COLUMN "public"."tenant_info"."phone" IS '电话'; +COMMENT ON COLUMN "public"."tenant_info"."status" IS '状态'; + +-- ---------------------------- +-- Records of tenant_info +-- ---------------------------- + -- ---------------------------- -- Alter sequences owned by -- ---------------------------- ALTER SEQUENCE "public"."device_online_report_id_seq" OWNED BY "public"."device_online_report"."id"; -SELECT setval('"public"."device_online_report_id_seq"', 21, true); +SELECT setval('"public"."device_online_report_id_seq"', 118, true); -- ---------------------------- -- Alter sequences owned by -- ---------------------------- ALTER SEQUENCE "public"."devices_groups_id_seq" OWNED BY "public"."devices_groups"."id"; -SELECT setval('"public"."devices_groups_id_seq"', 183, true); +SELECT setval('"public"."devices_groups_id_seq"', 582, true); -- ---------------------------- -- Alter sequences owned by @@ -1735,14 +1941,14 @@ SELECT setval('"public"."mail_setting_id_seq"', 2, false); -- ---------------------------- ALTER SEQUENCE "public"."media_type_setting_id_seq" OWNED BY "public"."media_type_setting"."id"; -SELECT setval('"public"."media_type_setting_id_seq"', 2, false); +SELECT setval('"public"."media_type_setting_id_seq"', 76, true); -- ---------------------------- -- Alter sequences owned by -- ---------------------------- ALTER SEQUENCE "public"."messages_id_seq" OWNED BY "public"."messages"."id"; -SELECT setval('"public"."messages_id_seq"', 234, true); +SELECT setval('"public"."messages_id_seq"', 6009, true); -- ---------------------------- -- Alter sequences owned by @@ -1756,7 +1962,7 @@ SELECT setval('"public"."notice_record_record_id_seq"', 2, false); -- ---------------------------- ALTER SEQUENCE "public"."product_event_relation_id_seq" OWNED BY "public"."product_event_relation"."id"; -SELECT setval('"public"."product_event_relation_id_seq"', 62, true); +SELECT setval('"public"."product_event_relation_id_seq"', 551, true); -- ---------------------------- -- Alter sequences owned by @@ -1777,49 +1983,49 @@ SELECT setval('"public"."product_event_time_interval_event_time_id_seq"', 9, tru -- ---------------------------- ALTER SEQUENCE "public"."product_service_relation_id_seq" OWNED BY "public"."product_service_relation"."id"; -SELECT setval('"public"."product_service_relation_id_seq"', 24, true); +SELECT setval('"public"."product_service_relation_id_seq"', 177, true); -- ---------------------------- -- Alter sequences owned by -- ---------------------------- ALTER SEQUENCE "public"."product_status_function_relation_id_seq" OWNED BY "public"."product_status_function_relation"."id"; -SELECT setval('"public"."product_status_function_relation_id_seq"', 8, true); +SELECT setval('"public"."product_status_function_relation_id_seq"', 135, true); -- ---------------------------- -- Alter sequences owned by -- ---------------------------- ALTER SEQUENCE "public"."product_type_product_type_id_seq" OWNED BY "public"."product_type"."id"; -SELECT setval('"public"."product_type_product_type_id_seq"', 226, true); +SELECT setval('"public"."product_type_product_type_id_seq"', 348, true); -- ---------------------------- -- Alter sequences owned by -- ---------------------------- ALTER SEQUENCE "public"."scenes_trigger_record_id_seq" OWNED BY "public"."scenes_trigger_record"."id"; -SELECT setval('"public"."scenes_trigger_record_id_seq"', 3, false); +SELECT setval('"public"."scenes_trigger_record_id_seq"', 2, false); -- ---------------------------- -- Alter sequences owned by -- ---------------------------- ALTER SEQUENCE "public"."service_execute_record_id_seq" OWNED BY "public"."service_execute_record"."id"; -SELECT setval('"public"."service_execute_record_id_seq"', 2, false); +SELECT setval('"public"."service_execute_record_id_seq"', 87, true); -- ---------------------------- -- Alter sequences owned by -- ---------------------------- ALTER SEQUENCE "public"."service_id_seq" OWNED BY "public"."product_service"."id"; -SELECT setval('"public"."service_id_seq"', 33, true); +SELECT setval('"public"."service_id_seq"', 78, true); -- ---------------------------- -- Alter sequences owned by -- ---------------------------- ALTER SEQUENCE "public"."service_param_id_seq" OWNED BY "public"."product_service_param"."id"; -SELECT setval('"public"."service_param_id_seq"', 19, true); +SELECT setval('"public"."service_param_id_seq"', 50, true); -- ---------------------------- -- Alter sequences owned by @@ -1833,21 +2039,21 @@ SELECT setval('"public"."sys_user_group_user_group_id_seq"', 30, true); -- ---------------------------- ALTER SEQUENCE "public"."sys_user_user_id_seq" OWNED BY "public"."sys_user"."user_id"; -SELECT setval('"public"."sys_user_user_id_seq"', 123, true); +SELECT setval('"public"."sys_user_user_id_seq"', 190, true); -- ---------------------------- -- Alter sequences owned by -- ---------------------------- ALTER SEQUENCE "public"."tag_id_seq" OWNED BY "public"."tag"."id"; -SELECT setval('"public"."tag_id_seq"', 196, true); +SELECT setval('"public"."tag_id_seq"', 329, true); -- ---------------------------- -- Alter sequences owned by -- ---------------------------- ALTER SEQUENCE "public"."task_info_id_seq" OWNED BY "public"."task_info"."id"; -SELECT setval('"public"."task_info_id_seq"', 3, true); +SELECT setval('"public"."task_info_id_seq"', 7, true); -- ---------------------------- -- Primary Key structure for table device @@ -1979,6 +2185,11 @@ ALTER TABLE "public"."product_status_function_relation" ADD CONSTRAINT "product_ -- ---------------------------- ALTER TABLE "public"."product_type" ADD CONSTRAINT "product_type_pkey" PRIMARY KEY ("id"); +-- ---------------------------- +-- Primary Key structure for table proxy +-- ---------------------------- +ALTER TABLE "public"."proxy" ADD CONSTRAINT "proxy_pkey" PRIMARY KEY ("id"); + -- ---------------------------- -- Primary Key structure for table scenes_trigger_record -- ---------------------------- @@ -2043,3 +2254,8 @@ ALTER TABLE "public"."tag" ADD CONSTRAINT "tag_pkey" PRIMARY KEY ("id"); -- Primary Key structure for table task_info -- ---------------------------- ALTER TABLE "public"."task_info" ADD CONSTRAINT "task_info_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table tenant_info +-- ---------------------------- +ALTER TABLE "public"."tenant_info" ADD CONSTRAINT "tenant_pkey" PRIMARY KEY ("tenant_id"); diff --git a/iot-server/server-bootstrap/pom.xml b/iot-server/server-bootstrap/pom.xml index c0c41eee..091fd0b4 100644 --- a/iot-server/server-bootstrap/pom.xml +++ b/iot-server/server-bootstrap/pom.xml @@ -87,12 +87,12 @@ - - com.zmops.hello - zeus-ark-hello - 1.0-beta - ark-biz - + + + + + + @@ -42,7 +42,7 @@ com.zmops library-module - 1.0.2-RELEASE + 1.0.3-RELEASE com.zmops diff --git a/iot-server/server-web/pom.xml b/iot-server/server-web/pom.xml index 1a185011..9cdcd773 100644 --- a/iot-server/server-web/pom.xml +++ b/iot-server/server-web/pom.xml @@ -20,24 +20,24 @@ com.zmops library-web - 1.0.2-RELEASE + 1.0.3-RELEASE com.zmops runtime-server - 1.0.2-RELEASE + 1.0.3-RELEASE com.zmops zeus-commons - 1.0.2-RELEASE + 1.0.3-RELEASE com.zmops library-module - 1.0.2-RELEASE + 1.0.3-RELEASE compile diff --git a/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java b/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java index 468760d1..02027f6c 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java @@ -19,6 +19,9 @@ import java.security.MessageDigest; import java.text.SimpleDateFormat; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.function.Predicate; /** * @author nantian created at 2021/7/29 17:03 @@ -447,4 +450,15 @@ public static boolean validCron(String cron){ public static boolean validDeviceName(String content){ return content.contains("\\") || content.contains("/"); } + + /** + * List> 根据相同key的值去重 + * @param keyExtractor + * @param + * @return + */ + public static Predicate distinctByKey(Function keyExtractor) { + Map seen = new ConcurrentHashMap<>(); + return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; + } } diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index dff0033d..7b777cb4 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -50,7 +50,7 @@ forest: zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} zbxServerPort: ${ZEUS_ZABBIX_PORT:80} zbxApiUrl: ${ZEUS_ZABBIX_API_URL:/zabbix/api_jsonrpc.php} - zbxApiToken: 479bcb20ab773c8b85f78a710fd56eca80aaec03c2337ad59263d568b0e9f938 + zbxApiToken: bd3eee6676ef363b4627c1d1f9ab83d5edc8ca741e56c7bd5a6cf64c3b4f7615 ## tdengine http request address taosUrl: http://${ZEUS_TAOS_HOST:127.0.0.1}:${ZEUS_TAOS_REST_PORT:6041}/rest/sql/zeus_data diff --git a/zeus-webapp/pom.xml b/zeus-webapp/pom.xml index 19c7f8e2..deff865e 100644 --- a/zeus-webapp/pom.xml +++ b/zeus-webapp/pom.xml @@ -35,7 +35,7 @@ com.zmops toolkit-async - 1.0.2-RELEASE + 1.0.3-RELEASE org.springframework.boot From 1b89cc47d38d0a5723a5c5a4bad4452ad95b4900 Mon Sep 17 00:00:00 2001 From: nantian Date: Thu, 9 Dec 2021 10:22:32 +0800 Subject: [PATCH 712/763] [feat]: webconsole dispacther --- .../zeus/iot/web/controller/WebConsole.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/WebConsole.java diff --git a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/WebConsole.java b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/WebConsole.java new file mode 100644 index 00000000..a712ec14 --- /dev/null +++ b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/WebConsole.java @@ -0,0 +1,22 @@ +package com.zmops.zeus.iot.web.controller; + +import com.zmops.zeus.server.library.web.core.ActionKey; +import com.zmops.zeus.server.library.web.core.Controller; +import com.zmops.zeus.server.library.web.core.Path; + +/** + * @author nantian created at 2021/12/1 22:10 + */ +@Path("/") +public class WebConsole extends Controller { + + public void index() { + redirect("/zeus/index.html"); + } + + + @ActionKey("/zeus") + public void zeus() { + redirect("/zeus/index.html"); + } +} From faec5b498a48fd450dba0a37548ad26ea1f1a2b2 Mon Sep 17 00:00:00 2001 From: yefei Date: Thu, 9 Dec 2021 16:07:39 +0800 Subject: [PATCH 713/763] [fix]: fix self monitor --- .../com/zmops/iot/constant/Constants.java | 19 + .../java/com/zmops/iot/util/ArgusMap.java | 62 ++ .../zmops/iot/util/CommonRegexpResolver.java | 88 +++ .../java/com/zmops/iot/util/ObjectUtils.java | 679 ++++++++++++++++++ .../analyse/service/SelfMonitorService.java | 37 +- 5 files changed, 868 insertions(+), 17 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/constant/Constants.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/util/ArgusMap.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/util/CommonRegexpResolver.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/util/ObjectUtils.java diff --git a/zeus-common/src/main/java/com/zmops/iot/constant/Constants.java b/zeus-common/src/main/java/com/zmops/iot/constant/Constants.java new file mode 100644 index 00000000..c28b4a42 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/constant/Constants.java @@ -0,0 +1,19 @@ +package com.zmops.iot.constant; + +public class Constants { + + public static final int SEC_PER_MIN = 60; + public static final int SEC_PER_HOUR = 3600; + public static final int SEC_PER_DAY = 86400; + public static final int SEC_PER_WEEK = 604800; + public static final int SEC_PER_MONTH = 2592000; + public static final int SEC_PER_YEAR = 31536000; + + public static final String DATE_TIME_FORMAT_SECONDS = "yyyy-MM-dd HH:mm:ss"; + + public static final Integer ARGUS_UNITS_ROUNDOFF_UPPER_LIMIT = 2; + + + public static final Integer ITEM_CONVERT_WITH_UNITS = 0; + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/util/ArgusMap.java b/zeus-common/src/main/java/com/zmops/iot/util/ArgusMap.java new file mode 100644 index 00000000..835b6365 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/util/ArgusMap.java @@ -0,0 +1,62 @@ +package com.zmops.iot.util; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * HashMap Builder + * + * @author yefei + * @param + * @param + */ +public abstract class ArgusMap implements Serializable { + + private static final long serialVersionUID = 1L; + + public static HashMapBuilder builder() { + return new HashMapBuilder(); + } + + public static LinkedHashMapBuilder linkedHashMapBuilder() { + return new LinkedHashMapBuilder(); + } + + public static class HashMapBuilder { + + private Map t; + + public HashMapBuilder(){ + this.t = new HashMap<>(); + } + + public HashMapBuilder put(K key, V value) { + this.t.put(key, value); + return this; + } + + public Map build() { + return this.t; + } + } + + public static class LinkedHashMapBuilder { + + private Map t; + + public LinkedHashMapBuilder(){ + this.t = new LinkedHashMap<>(); + } + + public LinkedHashMapBuilder put(K key, V value) { + this.t.put(key, value); + return this; + } + + public Map build() { + return this.t; + } + } +} diff --git a/zeus-common/src/main/java/com/zmops/iot/util/CommonRegexpResolver.java b/zeus-common/src/main/java/com/zmops/iot/util/CommonRegexpResolver.java new file mode 100644 index 00000000..c5716749 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/util/CommonRegexpResolver.java @@ -0,0 +1,88 @@ +package com.zmops.iot.util; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 通用正则解析器 + * + * @author yefei + */ +public class CommonRegexpResolver { + + /** + * @param regexp 正则表达式 + * @param input 待匹配的字符串 + * @param groupNames 分组名 + * @return + */ + public static Map> resolve(String regexp, String input, List groupNames) { + if (input == null) { + return new HashMap<>(); + } + Multimap res = ArrayListMultimap.create(); + Pattern pattern = Pattern.compile(regexp); + Matcher matcher = pattern.matcher(input); + if (Pattern.matches(regexp, input)) { + while (matcher.find()) { + groupNames.forEach(o -> { + if (matcher.group(o) != null) { + res.put(o, matcher.group(o)); + } + for (int i = 0; i <= matcher.groupCount(); i++) { + res.put(String.valueOf(i), matcher.group(i)); + } + }); + } + } else { + int i = 0; + while (matcher.find()) { + res.put(String.valueOf(i++), matcher.group()); + } + } + return res.asMap(); + } + + public static Map> resolve(String regexp, String input) { + if (input == null) { + return new HashMap>(); + } + Multimap res = ArrayListMultimap.create(); + Pattern pattern = Pattern.compile(regexp); + Matcher matcher = pattern.matcher(input); + if (Pattern.matches(regexp, input)) { + while (matcher.find()) { + for (int i = 0; i <= matcher.groupCount(); i++) { + res.put(i, matcher.group(i)); + } + } + } else { + int i = 0; + while (matcher.find()) { + res.put(i++, matcher.group()); + } + } + return res.asMap(); + } + + + // public static void main(String[] args) { + // final String regexp = + // "^(?[\\-+])?(?(\\d)+)(?[smhdw])?$"; + // Map> matches = + // CommonRegexpResolver.resolve(regexp, "-5m", + // Arrays.asList("sign","number","suffix")); + // matches.entrySet().forEach(o->{ + // System.out.println(o.getKey()+"->"+o.getValue()); + // }); + // } + + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/util/ObjectUtils.java b/zeus-common/src/main/java/com/zmops/iot/util/ObjectUtils.java new file mode 100644 index 00000000..2a5d37bc --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/util/ObjectUtils.java @@ -0,0 +1,679 @@ +package com.zmops.iot.util; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.zmops.iot.constant.Constants; +import org.springframework.util.StringUtils; + +import java.beans.IntrospectionException; +import java.beans.PropertyDescriptor; +import java.io.*; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.sql.Date; +import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.util.*; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ObjectUtils { + + public static List> digitUnits = new ArrayList<>(); + + /** + * 获取指定实体对象中字段的值 + * + * @param o 实体对象 + * @param c 实体类 + * @param fieldName 字段名称 + * @return + */ + public static Object getFieldValue(Object o, Class c, String fieldName) { + // 获取类中的全部定义字段 + Field[] fields = c.getDeclaredFields(); + // 循环遍历字段,获取字段相应的属性值 + for (Field field : fields) { + // 设置字段可见,就可以用get方法获取属性值。 + field.setAccessible(true); + try { + if (fieldName.equals(field.getName())) { + return field.get(o); + } + } catch (Exception e) { + return null; + } + } + return null; + } + + public static Object getFieldValue(Object o, String fieldName) { + return getFieldValue(o, o.getClass(), fieldName); + } + + public static void setFieldValue(Object o, Class c, String fieldName, Object value) { + Field[] fields = c.getDeclaredFields(); + for (Field field : fields) { + field.setAccessible(true); + if (field.getName().equals(fieldName)) { + try { + PropertyDescriptor pd = new PropertyDescriptor(fieldName, c); + Method wM = pd.getWriteMethod(); + wM.invoke(o, value); + } catch (IntrospectionException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) { + e.printStackTrace(); + } + + } + } + } + + public static void setFieldValue(Object o, String fieldName, Object value) { + setFieldValue(o, o.getClass(), fieldName, value); + } + + /** + * 实体对象转成Map       + * + * @param obj 实体对象     + * @return       + */ + public static Map object2Map(Object obj) { + Map map = new HashMap<>(); + if (obj == null) { + return map; + } + Field[] fields = obj.getClass().getDeclaredFields(); + try { + for (Field field : fields) { + field.setAccessible(true); + map.put(field.getName(), field.get(obj)); + } + } catch (Exception e) { + e.printStackTrace(); + } + return map; + } + + /** + * 检查IP地址是否合法 + * + * @param ipAddress + * @return + */ + public static boolean isIpv4(String ipAddress) { + + String ip = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\." + + "(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." + + "(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." + + "(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$"; + + Pattern pattern = Pattern.compile(ip); + Matcher matcher = pattern.matcher(ipAddress); + return matcher.matches(); + + } + + /** + * 检查秘钥是否合法 + * + * @param psk + * @return + */ + public static boolean validatePSK(String psk) { + String pskpatern = "^([0-9a-f]{2})+$"; + Pattern pattern = Pattern.compile(pskpatern); + Matcher matcher = pattern.matcher(psk); + return matcher.matches(); + } + + /** + * 检查字符串是不是数字 + * + * @param str + * @return + */ + public static boolean isInteger(String str) { + Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$"); + return pattern.matcher(str).matches(); + } + + /** + * 根据数字生成字母 + * + * @param + * @return + */ + public static String num2letter(int number) { + int start = 65; + int base = 26; + String str = ""; + int level = 0; + do { + if (level++ > 0) { + number--; + } + int remainder = number % base; + number = (number - remainder) / base; + str = (char) (start + remainder) + str; + } while (0 != number); + return str; + } + + /** + * 返回两个list的去重并集 + * + * @param output + * @param extend + * @return + */ + public static List outputExtend(List output, List extend) { + + if (output.size() == 1 && output.get(0).equals("extend")) { + return output; + } + Set result = new HashSet<>(); + for (R o : output) { + result.add(o); + } + for (R e : extend) { + result.add(e); + } + return new ArrayList<>(result); + } + + /** + * 返回两个list的交集 + * + * @param array1 + * @param array2 + * @return + */ + public static List arrayIntersectKey(List array1, List array2) { + array1.retainAll(array2); + return array1; + } + + /** + * Convert timestamp to string representation. Return 'Never' if 0. + * + * @return + */ + public static String date2str(String format, String seconds) { + if (seconds == null || seconds.isEmpty() || seconds.equals("null")) { + return ""; + } + if (format == null || format.isEmpty()) { + format = "yyyy-MM-dd HH:mm:ss"; + } + SimpleDateFormat sdf = new SimpleDateFormat(format); + return sdf.format(new Date(Long.valueOf(seconds + "000"))); + } + + public static String convertUnits(String value, String units) { + int convert = Constants.ITEM_CONVERT_WITH_UNITS; + @SuppressWarnings("unused") + boolean byteStep = false, pow = false, ignoreMillisec = false, length = false; + if ("unixtime".equals(units)) { + return date2str(Constants.DATE_TIME_FORMAT_SECONDS, value); + } + // special processing of uptime + if ("uptime".equals(units)) { + return convertUnitsUptime(value); + } + + if ("s".equals(units)) { + return convertUnitsS(value, false); + } + // black list of units that should have no multiplier prefix (K, M, G + // etc) applied + List blackList = Lists.newArrayList("%", "ms", "rpm", "RPM"); + + // add to the blacklist if unit is prefixed with '!' + if (units != null && units.startsWith("!")) { + units = units.substring(1); + blackList.add(units); + } + if (blackList.contains(units) || !StringUtils.hasText(units)) { + if (!CommonRegexpResolver.resolve("\\.\\d+$", "0.01").isEmpty()) { + BigDecimal decimal = new BigDecimal(value); + value = decimal + .setScale(decimal.abs().compareTo(new BigDecimal(0.01)) == 1 ? 2 : 6, RoundingMode.HALF_UP) + .toString(); + } + value = value.replaceAll("^([\\-0-9]+)(\\.)([0-9]*?)[0]+$", "$1$2$3"); + if (value.endsWith(".")) { + value = value.substring(0, value.length() - 1); + } + return value + " " + units; + } + int step; + // if one or more items is B or Bps, then Y-scale use base 8 and + // calculated in bytes + if (byteStep) { + step = 1024; + } else { + switch (units) { + case "Bps": + case "B": + step = 1024; + convert = convert != 0 ? convert : 1; + break; + case "b": + case "bps": + convert = convert != 0 ? convert : 1; + default: + step = 1000; + break; + } + } + + BigDecimal abs = new BigDecimal(value).abs(); + if (abs.compareTo(new BigDecimal(1)) == -1) { + value = new BigDecimal(value).setScale(2, RoundingMode.HALF_UP).toString(); + if (length && abs.compareTo(new BigDecimal(0)) != 0) { + + } + return (value + " " + units).trim(); + } + + List steps = Arrays.asList("", "K", "M", "G", "T", "P", "E", "Z", "Y"); + BigDecimal values = new BigDecimal(value); + int i = 0; + while (values.divide(new BigDecimal(step)).longValue() > 1 && i < steps.size()) { + values = values.divide(new BigDecimal(step)); + i++; + } + if (values.intValue() == step) { + values = values.divide(new BigDecimal(step)); + i++; + } + value = values.setScale(10, RoundingMode.HALF_UP).toString().replaceAll("^([\\-0-9]+)(\\.)([0-9]*?)[0]+$", + "$1$2$3"); + if (value.endsWith(".")) { + value = value.substring(0, value.length() - 1); + } + if (value.contains(".")) { + int idx = value.lastIndexOf('.') + 3; + if (idx < value.length()) { + value = value.substring(0, idx); + } + } + return value + " " + steps.get(i) + units; + + } + + // @SuppressWarnings("unused") + // String step = ""; + // int convert = Constants.ITEM_CONVERT_WITH_UNITS; + // // special processing for unix timestamps + // if ("unixtime".equals(units)) { + // return date2str(Constants.DATE_TIME_FORMAT_SECONDS, value); + // } + // // special processing of uptime + // if ("uptime".equals(units)) { + // return convertUnitsUptime(value); + // } + // + // if ("s".equals(units)) { + // return convertUnitsS(value, false); + // } + // // black list of units that should have no multiplier prefix (K, M, G + // // etc) applied + // List blackList = Arrays.asList("% ", "ms ", "rpm ", "RPM "); + // // add to the blacklist if unit is prefixed with '!' + // if (!StringUtils.isBlank(units) && units.startsWith("!")) { + // blackList.add(units.substring(0, 1)); + // } + // // any other unit + // if (blackList.contains(units) || StringUtils.isBlank(units)) { + // if (CommonRegexpResolver.resolve("\\.\\d*$", value).size() > 0) { + // String format = Math.abs(Double.parseDouble( + // value)) >= Constants.ARGUS_UNITS_ROUNDOFF_THRESHOLD ? "%." + // + Constants.ARGUS_UNITS_ROUNDOFF_UPPER_LIMIT + // + "f" : "%." + // + Constants.ARGUS_UNITS_ROUNDOFF_LOWER_LIMIT + // + "f"; + // value = formt(format, value); + // } + // value = value.replaceAll("^([\\-0-9]+)(\\.)([0-9]*)[0]+$", "$1$2$3"); + // value = value.split("\\.")[0]; + // return value.trim(); + // } + // switch (units) { + // case "Bps": + // case "B": + // step = Constants.ARGUS_KIBIBYTE; + // break; + // case "b": + // case "bps": + // default: + // step = "1000"; + // } + // double abs = 0.0; + // if (Double.parseDouble(value) < 0) { + // abs = Math.abs(Double.parseDouble(value)); + // } else { + // abs = Double.parseDouble(value); + // } + // if (abs < 1) { + // value = String.valueOf(round(value, + // Constants.ARGUS_UNITS_ROUNDOFF_MIDDLE_LIMIT)); + // return value + " " + units; + // } + // + // if (isEmpty(digitUnits)) { + // initDigitUnits(); + // for (Map map : digitUnits) { + // map.put("value", String.valueOf((long) Math.pow(1024, (int) + // map.get("pow")))); + // } + // } + // Map valUnit = new HashMap<>(); + // valUnit.put("pow", 0); + // valUnit.put("short", ""); + // valUnit.put("value", value); + // if (Double.parseDouble(value) == 0) { + // for (Map map : digitUnits) { + // if (abs >= Double.parseDouble(value)) { + // valUnit = map; + // } else { + // break; + // } + // } + // } + // if (round(value, Constants.ARGUS_UNITS_ROUNDOFF_MIDDLE_LIMIT).intValue() + // > 0) { + // double newVal = new BigDecimal(formt("%.10f", value)) + // .divide(new BigDecimal(formt("%.10f", + // String.valueOf(valUnit.get("value")))), + // Constants.ARGUS_PRECISION_10, + // BigDecimal.ROUND_HALF_UP) + // .doubleValue(); + // valUnit.put("value", newVal); + // } else { + // valUnit.put("value", 0); + // } + // String desc = ""; + // switch (convert) { + // case 0: + // units = units.trim(); + // case 1: + // desc = String.valueOf(valUnit.get("short")); + // break; + // } + // value = String.valueOf(round(String.valueOf(valUnit.get("value")), + // Constants.ARGUS_UNITS_ROUNDOFF_UPPER_LIMIT)) + // .replaceAll("^([\\-0-9]+)(\\.)([0-9]*)[0]+$", "$1$2$3"); + // + // value = value.split("\\.")[0]; + // + // if (Double.parseDouble(value) == 0) { + // value = "0"; + // } + // return value + " " + desc + units; + // } + + @SuppressWarnings("unused") + private static void initDigitUnits() { + Map obj = new HashMap<>(); + obj.put("pow", 0); + obj.put("short", ""); + digitUnits.add(obj); + obj = new HashMap<>(); + obj.put("pow", 1); + obj.put("short", "K"); + digitUnits.add(obj); + obj = new HashMap<>(); + obj.put("pow", 2); + obj.put("short", "M"); + digitUnits.add(obj); + obj = new HashMap<>(); + obj.put("pow", 3); + obj.put("short", "G"); + digitUnits.add(obj); + obj = new HashMap<>(); + obj.put("pow", 4); + obj.put("short", "T"); + digitUnits.add(obj); + obj = new HashMap<>(); + obj.put("pow", 5); + obj.put("short", "P"); + digitUnits.add(obj); + obj = new HashMap<>(); + obj.put("pow", 6); + obj.put("short", "E"); + digitUnits.add(obj); + obj = new HashMap<>(); + obj.put("pow", 7); + obj.put("short", "Z"); + digitUnits.add(obj); + obj = new HashMap<>(); + obj.put("pow", 8); + obj.put("short", "Y"); + digitUnits.add(obj); + } + + + /** + * 将时间段转换为可读格式。 使用以下单位:年、月、日、小时、分钟、秒和毫秒。 仅显示三个最高单位:y m d,m d h,d h mm等等。 + * 如果某个值等于零,则忽略该值。例如,如果周期为1y0m4d,它将显示为 1Y 4D,非1Y 0M 4D或1Y 4D H。 + * + * @param value + * @param ignore_millisec + * @return + */ + private static String convertUnitsS(String value, boolean ignore_millisec) { + BigDecimal secs = round(new BigDecimal(value).multiply(BigDecimal.valueOf(1000)), + Constants.ARGUS_UNITS_ROUNDOFF_UPPER_LIMIT).divide(BigDecimal.valueOf(1000)); + long sec = secs.longValue(); + String str = ""; + if (sec < 0) { + sec = -sec; + str = "-"; + } + int[] steps = new int[]{ + Constants.SEC_PER_YEAR, Constants.SEC_PER_MONTH, + Constants.SEC_PER_DAY, Constants.SEC_PER_HOUR, + Constants.SEC_PER_MIN + }; + List unitsEn = new ArrayList<>(units.keySet()); + Map values = new LinkedHashMap<>(); + for (int s = 0; s < steps.length; s++) { + int v = steps[s]; + if (sec < v) { + continue; + } + long n = sec / v; + sec %= v; + values.put(unitsEn.get(s), n); + } + if (sec != 0) { + values.put("s", sec); + } + if (!ignore_millisec) { + values.put("ms", secs.subtract(BigDecimal.valueOf(secs.longValue())).multiply(BigDecimal.valueOf(1000)).longValue()); + } + int size = 0; + for (Entry ent : values.entrySet()) { + str += " " + ent.getValue() + units.get(ent.getKey()); + if (++size == 3) { + break; + } + } + return !StringUtils.hasText(str) ? "0" : str.trim(); + } + + public static void main(String[] args) { + System.out.println(convertUnitsS("86411.1", false)); + } + + private final static Map units = ArgusMap.linkedHashMapBuilder().put("y", "年").put("m", "月") + .put("d", "天").put("h", "小时").put("mm", "分").put("s", "秒").put("ms", "毫秒").build(); + + private static String convertUnitsUptime(String value) { + int secs = round(value, 0).intValue(); + if (secs < 0) { + value = "-"; + secs = -secs; + } else { + value = ""; + } + int days = new BigDecimal(secs).divide(new BigDecimal(Constants.SEC_PER_DAY), RoundingMode.DOWN).intValue(); + secs -= days * Constants.SEC_PER_DAY; + + int hours = new BigDecimal(secs).divide(new BigDecimal(Constants.SEC_PER_HOUR), RoundingMode.DOWN).intValue(); + secs -= hours * Constants.SEC_PER_HOUR; + + int mins = new BigDecimal(secs).divide(new BigDecimal(Constants.SEC_PER_MIN), RoundingMode.DOWN).intValue(); + secs -= mins * Constants.SEC_PER_MIN; + + if (days != 0) { + value += days + "天,"; + } + value += LocalDateTimeUtils.formatTime(LocalDateTime.now().withHour(hours).withMinute(mins).withSecond(secs), + "HH:mm:ss"); + return value; + } + + /** + * 计算差值 并保留digits位小数 + * + * @param last + * @param prev + * @param digits + * @return + */ + public static double bcsub(String last, String prev, int digits) { + double lastVal = Double.parseDouble(last); + double prevVal = Double.parseDouble(prev); + + double res = lastVal - prevVal; + if (digits == 0) { + return res; + } else { + BigDecimal bg = new BigDecimal(res); + double f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); + return f1; + } + } + + /** + * 格式化value 保留r位小数并四舍五入 + * + * @param value + * @param r + * @return + */ + public static BigDecimal round(String value, int r) { + if (!StringUtils.hasText(value)) { + return new BigDecimal("0"); + } + BigDecimal bvalue = new BigDecimal(value); + return round(bvalue, r); + } + + public static BigDecimal round(BigDecimal value, int r) { + return value.divide(new BigDecimal("1"), r, BigDecimal.ROUND_HALF_UP); + } + + /** + * 根据format 格式化value 小数点位数 + * + * @param format + * @param value + * @return + */ + public static String formt(String format, String value) { + Formatter fmt = new Formatter(); + value = fmt.format(format, Double.parseDouble(value)).toString(); + fmt.close(); + return value; + } + + public static List deepCopy(List src) throws IOException, ClassNotFoundException { + ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(byteOut); + out.writeObject(src); + ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); + ObjectInputStream in = new ObjectInputStream(byteIn); + @SuppressWarnings("unchecked") + List dest = (List) in.readObject(); + return dest; + } + + public static Map deepCopy(Map src) throws IOException, ClassNotFoundException { + ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(byteOut); + out.writeObject(src); + ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); + ObjectInputStream in = new ObjectInputStream(byteIn); + @SuppressWarnings("unchecked") + Map dest = (Map) in.readObject(); + return dest; + } + + /** + * 根据map键值的交集 返回map1中的值 + * + * @param map + * @param map2 + * @return + */ + public static Map mapIntersectKey(Map map, Map map2) { + Set bigMapKey = map.keySet(); + Set smallMapKey = map2.keySet(); + Set differenceSet = Sets.intersection(bigMapKey, smallMapKey); + Map result = Maps.newHashMap(); + for (Key key : differenceSet) { + result.put(key, map.get(key)); + } + return result; + } + + /** + * 根据map键值的差集 返回map1中的值 + * + * @param map + * @param map2 + * @return + */ + public static Map mapDiffKey(Map map, Map map2) { + Set bigMapKey = map.keySet(); + Set smallMapKey = map2.keySet(); + Set differenceSet = Sets.difference(bigMapKey, smallMapKey); + Map result = Maps.newHashMap(); + for (Key key : differenceSet) { + result.put(key, map.get(key)); + } + return result; + } + + public static String substr_replace(String source, String replacement, int start, Integer length) { + if (length == null) { + return new StringBuilder(source.substring(0, start)).append(replacement).toString(); + } + // 如果start <0 表示从source结尾处n个开始替换 + if (start < 0) { + start = source.length() + start; + } + if (length >= 0) { + return new StringBuilder(source.substring(0, start)).append(replacement) + .append(source.substring(start + length)).toString(); + } + return new StringBuilder(source.substring(0, start)).append(replacement) + .append(source.substring(source.length() + length)).toString(); + + } + + public static String substr_replace(String source, String replacement, int start) { + return substr_replace(source, replacement, start, null); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/SelfMonitorService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/SelfMonitorService.java index e187aaf2..8c646178 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/SelfMonitorService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/SelfMonitorService.java @@ -3,6 +3,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.util.LocalDateTimeUtils; +import com.zmops.iot.util.ObjectUtils; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.analyse.dto.LatestDto; import com.zmops.iot.web.analyse.enums.CpuLoadEnum; @@ -50,33 +51,33 @@ public class SelfMonitorService { public Map getMemInfo() { Map resMap = new HashMap<>(3); - getItemValue(getHostId("Zabbix server"), MemoryUtilizationEnum.utilization.getCode(), MemoryUtilizationEnum.utilization.getMessage(), 0, resMap); - getItemValue(getHostId("Zabbix server"), MemoryUtilizationEnum.total.getCode(), MemoryUtilizationEnum.total.getMessage(), 3, resMap); - getItemValue(getHostId("Zabbix server"), MemoryUtilizationEnum.available.getCode(), MemoryUtilizationEnum.available.getMessage(), 3, resMap); + getItemValue(getHostId("Zabbix server"), MemoryUtilizationEnum.utilization.getCode(), MemoryUtilizationEnum.utilization.getMessage(), 0, "%", resMap); + getItemValue(getHostId("Zabbix server"), MemoryUtilizationEnum.total.getCode(), MemoryUtilizationEnum.total.getMessage(), 3, "B", resMap); + getItemValue(getHostId("Zabbix server"), MemoryUtilizationEnum.available.getCode(), MemoryUtilizationEnum.available.getMessage(), 3, "B", resMap); - resMap.put("trends", getTrendsData(getHostId("Zabbix server"), itemMap.get(MemoryUtilizationEnum.utilization.getMessage()), 0)); + resMap.put("trends", getTrendsData(getHostId("Zabbix server"), itemMap.get(MemoryUtilizationEnum.utilization.getMessage()), 0, "%")); return resMap; } public Map getCpuLoadInfo() { Map resMap = new HashMap<>(3); - getItemValue(getHostId("Zabbix server"), CpuLoadEnum.avg1.getCode(), CpuLoadEnum.avg1.getMessage(), 0, resMap); - getItemValue(getHostId("Zabbix server"), CpuLoadEnum.avg5.getCode(), CpuLoadEnum.avg5.getMessage(), 0, resMap); - getItemValue(getHostId("Zabbix server"), CpuLoadEnum.avg15.getCode(), CpuLoadEnum.avg15.getMessage(), 0, resMap); + getItemValue(getHostId("Zabbix server"), CpuLoadEnum.avg1.getCode(), CpuLoadEnum.avg1.getMessage(), 0, "%", resMap); + getItemValue(getHostId("Zabbix server"), CpuLoadEnum.avg5.getCode(), CpuLoadEnum.avg5.getMessage(), 0, "%", resMap); + getItemValue(getHostId("Zabbix server"), CpuLoadEnum.avg15.getCode(), CpuLoadEnum.avg15.getMessage(), 0, "%", resMap); - resMap.put("trends", getTrendsData(getHostId("Zabbix server"), itemMap.get(CpuLoadEnum.avg1.getMessage()), 0)); + resMap.put("trends", getTrendsData(getHostId("Zabbix server"), itemMap.get(CpuLoadEnum.avg1.getMessage()), 0, "%")); return resMap; } public Map getProcessInfo() { Map resMap = new HashMap<>(3); - getItemValue(getHostId("Zabbix server"), ProcessEnum.num.getCode(), ProcessEnum.num.getMessage(), 3, resMap); - getItemValue(getHostId("Zabbix server"), ProcessEnum.run.getCode(), ProcessEnum.run.getMessage(), 3, resMap); - getItemValue(getHostId("Zabbix server"), ProcessEnum.max.getCode(), ProcessEnum.max.getMessage(), 3, resMap); + getItemValue(getHostId("Zabbix server"), ProcessEnum.num.getCode(), ProcessEnum.num.getMessage(), 3, "个", resMap); + getItemValue(getHostId("Zabbix server"), ProcessEnum.run.getCode(), ProcessEnum.run.getMessage(), 3, "个", resMap); + getItemValue(getHostId("Zabbix server"), ProcessEnum.max.getCode(), ProcessEnum.max.getMessage(), 3, "个", resMap); - resMap.put("trends", getTrendsData(getHostId("Zabbix server"), itemMap.get(ProcessEnum.run.getMessage()), 3)); + resMap.put("trends", getTrendsData(getHostId("Zabbix server"), itemMap.get(ProcessEnum.run.getMessage()), 3, "个")); return resMap; } @@ -86,7 +87,7 @@ public List> getCpuUtilization() { if (ToolUtil.isEmpty(itemId)) { return Collections.emptyList(); } - return getTrendsData(getHostId("Zabbix server"), itemId, 0); + return getTrendsData(getHostId("Zabbix server"), itemId, 0, "%"); } @@ -98,7 +99,7 @@ public List> getCpuUtilization() { * @param itemValueType 监控项值类型 * @return */ - private List> getTrendsData(String hostId, String itemId, int itemValueType) { + private List> getTrendsData(String hostId, String itemId, int itemValueType, String unit) { long timeTill = LocalDateTimeUtils.getSecondsByTime(LocalDateTime.now()); long timeFrom = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.minu(LocalDateTime.now(), 1L, ChronoUnit.HOURS)); @@ -107,7 +108,8 @@ private List> getTrendsData(String hostId, String itemId, in return latestDtos.stream().map(o -> { Map tmpMap = new HashMap<>(2); tmpMap.put("date", LocalDateTimeUtils.convertTimeToString(Integer.parseInt(o.getClock()), "yyyy-MM-dd HH:mm:ss")); - tmpMap.put("val", o.getValue()); + String value = ObjectUtils.convertUnits(o.getValue(), unit); + tmpMap.put("val", value); return tmpMap; }).collect(Collectors.toList()); } @@ -121,7 +123,7 @@ private List> getTrendsData(String hostId, String itemId, in * @param itemValueType 监控项值类型 * @param resMap map */ - private void getItemValue(String hostId, String key, String name, int itemValueType, Map resMap) { + private void getItemValue(String hostId, String key, String name, int itemValueType, String unit, Map resMap) { String itemId = getItemId(hostId, name, key); if (ToolUtil.isEmpty(itemId)) { @@ -131,7 +133,8 @@ private void getItemValue(String hostId, String key, String name, int itemValueT List latestDtos = JSONObject.parseArray(res, LatestDto.class); if (ToolUtil.isNotEmpty(latestDtos)) { - resMap.put(name, latestDtos.get(0).getValue()); + String value = ObjectUtils.convertUnits(latestDtos.get(0).getValue(), unit); + resMap.put(name, value); } } From f8944430b3120c1740ce1a1233212e5d16ff8bf1 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 11 Dec 2021 15:56:22 +0800 Subject: [PATCH 714/763] [ver]: update ebean and camel version --- iot-server-bom/pom.xml | 8 ++++---- iot-server/pom.xml | 4 ++-- iot-server/server-camel-receiver/pom.xml | 4 ++-- .../iot/server/receiver/handler/ark/ArkBizComponent.java | 2 +- .../iot/server/receiver/handler/ark/ArkBizConsumer.java | 2 +- .../iot/server/receiver/handler/ark/ArkBizEndpoint.java | 4 +++- .../iot/server/receiver/handler/ark/ArkBizProducer.java | 2 +- .../receiver/handler/zabbix/ZabbixSenderComponent.java | 2 +- .../receiver/handler/zabbix/ZabbixSenderConsumer.java | 2 +- .../receiver/handler/zabbix/ZabbixSenderEndpoint.java | 2 +- .../receiver/handler/zabbix/ZabbixTrapperProducer.java | 4 +++- zeus-common/pom.xml | 2 +- zeus-starter/pom.xml | 2 +- zeus-webapp-bom/pom.xml | 2 +- zeus-webapp/pom.xml | 2 +- 15 files changed, 24 insertions(+), 20 deletions(-) diff --git a/iot-server-bom/pom.xml b/iot-server-bom/pom.xml index b650f486..312516d1 100644 --- a/iot-server-bom/pom.xml +++ b/iot-server-bom/pom.xml @@ -16,7 +16,7 @@ IoT Server 协议解析层 - 2.25.4 + 3.11.4 1.18.20 2.13.3 25.1-jre @@ -83,12 +83,12 @@ --> org.apache.camel - camel-netty4-http + camel-netty-http ${camel.version} org.apache.camel - camel-netty4 + camel-netty ${camel.version} @@ -99,7 +99,7 @@ org.apache.camel - camel-mqtt + camel-paho-mqtt5 ${camel.version} diff --git a/iot-server/pom.xml b/iot-server/pom.xml index cfd01210..9c4f174b 100644 --- a/iot-server/pom.xml +++ b/iot-server/pom.xml @@ -107,7 +107,7 @@ org.apache.camel - camel-netty4 + camel-netty io.netty @@ -121,7 +121,7 @@ org.apache.camel - camel-mqtt + camel-paho-mqtt5 com.h2database diff --git a/iot-server/server-camel-receiver/pom.xml b/iot-server/server-camel-receiver/pom.xml index 306601c9..67617da7 100644 --- a/iot-server/server-camel-receiver/pom.xml +++ b/iot-server/server-camel-receiver/pom.xml @@ -36,12 +36,12 @@ org.apache.camel - camel-netty4-http + camel-netty-http org.apache.camel camel-pgevent - 2.25.4 + 3.11.4 org.postgresql diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizComponent.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizComponent.java index 84a90b5a..cf60a6dc 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizComponent.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizComponent.java @@ -2,7 +2,7 @@ import com.zmops.zeus.server.library.module.ModuleManager; import org.apache.camel.Endpoint; -import org.apache.camel.impl.DefaultComponent; +import org.apache.camel.support.DefaultComponent; import java.util.Map; diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizConsumer.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizConsumer.java index c48534cc..a81401ea 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizConsumer.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizConsumer.java @@ -2,7 +2,7 @@ import org.apache.camel.Endpoint; import org.apache.camel.Processor; -import org.apache.camel.impl.DefaultConsumer; +import org.apache.camel.support.DefaultConsumer; /** * @author nantian created at 2021/12/2 22:35 diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizEndpoint.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizEndpoint.java index a2f235e2..a7dac2db 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizEndpoint.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizEndpoint.java @@ -5,7 +5,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; -import org.apache.camel.impl.DefaultEndpoint; + + +import org.apache.camel.support.DefaultEndpoint; /** * @author nantian created at 2021/12/2 22:34 diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizProducer.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizProducer.java index 09dfbb01..0dab47c3 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizProducer.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizProducer.java @@ -9,7 +9,7 @@ import com.zmops.zeus.server.runtime.api.client.param.ReferenceParam; import org.apache.camel.Endpoint; import org.apache.camel.Exchange; -import org.apache.camel.impl.DefaultProducer; +import org.apache.camel.support.DefaultProducer; import java.util.Collections; import java.util.List; diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderComponent.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderComponent.java index 008855a6..dd00c429 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderComponent.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderComponent.java @@ -2,7 +2,7 @@ import com.zmops.zeus.server.library.module.ModuleManager; import org.apache.camel.Endpoint; -import org.apache.camel.impl.DefaultComponent; +import org.apache.camel.support.DefaultComponent; import java.util.Map; diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderConsumer.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderConsumer.java index fc74bd2b..0b81da8a 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderConsumer.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderConsumer.java @@ -2,7 +2,7 @@ import org.apache.camel.Endpoint; import org.apache.camel.Processor; -import org.apache.camel.impl.DefaultConsumer; +import org.apache.camel.support.DefaultConsumer; /** * @author nantian created at 2021/8/16 22:47 diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderEndpoint.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderEndpoint.java index 8b9452fd..0704329e 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderEndpoint.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderEndpoint.java @@ -5,7 +5,7 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; -import org.apache.camel.impl.DefaultEndpoint; +import org.apache.camel.support.DefaultEndpoint; /** * @author nantian created at 2021/8/16 22:45 diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapperProducer.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapperProducer.java index 5614f9a5..a50cf01f 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapperProducer.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapperProducer.java @@ -5,10 +5,11 @@ import com.zmops.zeus.iot.server.receiver.handler.zabbix.worker.ItemDataTransferWorker; import com.zmops.zeus.server.library.module.ModuleManager; import com.zmops.zeus.server.library.util.StringUtil; +import lombok.extern.slf4j.Slf4j; import org.apache.camel.Endpoint; import org.apache.camel.Exchange; import org.apache.camel.Message; -import org.apache.camel.impl.DefaultProducer; +import org.apache.camel.support.DefaultProducer; import java.util.List; import java.util.concurrent.ExecutorService; @@ -19,6 +20,7 @@ *

                          * to("Zabbix") */ +@Slf4j public class ZabbixTrapperProducer extends DefaultProducer { private final ModuleManager moduleManager; diff --git a/zeus-common/pom.xml b/zeus-common/pom.xml index b536fb02..772384f4 100644 --- a/zeus-common/pom.xml +++ b/zeus-common/pom.xml @@ -31,7 +31,7 @@ io.ebean querybean-generator - 12.13.0 + 12.13.1 com.google.guava diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index 1bcfd9a8..40aa8e4b 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -53,7 +53,7 @@ org.apache.camel camel-pgevent - 2.25.4 + 3.11.4 diff --git a/zeus-webapp-bom/pom.xml b/zeus-webapp-bom/pom.xml index 32b6a12b..2fbf608f 100644 --- a/zeus-webapp-bom/pom.xml +++ b/zeus-webapp-bom/pom.xml @@ -151,7 +151,7 @@ io.ebean ebean - 12.13.0 + 12.13.1 diff --git a/zeus-webapp/pom.xml b/zeus-webapp/pom.xml index deff865e..dd2dcaf5 100644 --- a/zeus-webapp/pom.xml +++ b/zeus-webapp/pom.xml @@ -59,7 +59,7 @@ org.apache.camel camel-core - 2.25.4 + 3.11.4 compile From e39c20ddb541a0dc77245cfc9ba1096a10af0f41 Mon Sep 17 00:00:00 2001 From: nantian Date: Sat, 11 Dec 2021 15:57:32 +0800 Subject: [PATCH 715/763] [feat]: update zeus-iot-ui version --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index a826f2e7..41f42450 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit a826f2e7538303f66a88b1b62a26b3ba8af55c13 +Subproject commit 41f42450d3c186ab321f145c9b0e0d0e0b121216 From 3021582ea5666672ac0e3a3241a6fd8fc7831526 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 13 Dec 2021 17:32:35 +0800 Subject: [PATCH 716/763] [feat]: add protocol manage --- .gitignore | 1 + .../service/CamelContextHolderService.java | 23 ++- iot-server/server-starter/pom.xml | 3 +- .../zmops/zeus/iot/web/config/IoTConfig.java | 3 +- .../iot/web/controller/IndexController.java | 10 +- .../domain/protocol/ProtocolComponent.java | 29 ++++ .../iot/domain/protocol/ProtocolGateway.java | 31 ++++ .../domain/protocol/ProtocolGatewayMqtt.java | 27 +++ .../iot/domain/protocol/ProtocolService.java | 33 ++++ .../zmops/zeus/driver/service/ZeusServer.java | 24 +++ .../web/exception/enums/BizExceptionEnum.java | 11 +- .../ProtocolComponentController.java | 160 ++++++++++++++++++ .../controller/ProtocolGatewayController.java | 131 ++++++++++++++ .../controller/ProtocolServiceController.java | 83 +++++++++ .../protocol/dto/ProtocolComponentDto.java | 36 ++++ .../web/protocol/dto/ProtocolGatewayDto.java | 47 +++++ .../iot/web/protocol/dto/ProtocolOption.java | 19 +++ .../web/protocol/dto/ProtocolServiceDto.java | 39 +++++ .../dto/param/ProtocolComponentParam.java | 30 ++++ .../dto/param/ProtocolGatewayParam.java | 31 ++++ .../dto/param/ProtocolServiceParam.java | 33 ++++ .../iot/web/protocol/enums/ProtocolEnum.java | 38 +++++ .../service/ProtocolComponentService.java | 87 ++++++++++ .../service/ProtocolGatewayService.java | 147 ++++++++++++++++ .../protocol/service/ProtocolSvrService.java | 80 +++++++++ 25 files changed, 1138 insertions(+), 18 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolComponent.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolGateway.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolGatewayMqtt.java create mode 100644 zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolService.java create mode 100644 zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZeusServer.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolComponentController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolGatewayController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolServiceController.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolComponentDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolGatewayDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolOption.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolServiceDto.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolComponentParam.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolGatewayParam.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolServiceParam.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/protocol/enums/ProtocolEnum.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolComponentService.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolGatewayService.java create mode 100644 zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolSvrService.java diff --git a/.gitignore b/.gitignore index 759d66a7..52886cd1 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ zeus-starter/src/main/resources/public/ .bdb/ zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/Test.java +logs/ diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/CamelContextHolderService.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/CamelContextHolderService.java index 97d18b65..6dbc2370 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/CamelContextHolderService.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/CamelContextHolderService.java @@ -6,7 +6,6 @@ import org.apache.camel.CamelContext; import org.apache.camel.Route; import org.apache.camel.RoutesBuilder; -import org.apache.camel.impl.EventDrivenConsumerRoute; import org.apache.camel.model.FromDefinition; import java.util.List; @@ -47,17 +46,17 @@ public void addRoutes(RoutesBuilder builder) { * @param routeId 路由ID */ public void routeShutDown(String routeId) { - EventDrivenConsumerRoute route = (EventDrivenConsumerRoute) camelContext.getRoute(routeId); - List fromDefinitions = camelContext.getRouteDefinition(routeId).getInputs(); - - - try { - camelContext.stopRoute(routeId); - camelContext.removeRoute(routeId); -// camelContext.removeRouteDefinition(camelContext.getRouteDefinition(routeId)); - } catch (Exception e) { - e.printStackTrace(); - } +// EventDrivenConsumerRoute route = (EventDrivenConsumerRoute) camelContext.getRoute(routeId); +// List fromDefinitions = camelContext.getRouteDefinition(routeId).getInputs(); +// +// +// try { +// camelContext.stopRoute(routeId); +// camelContext.removeRoute(routeId); +//// camelContext.removeRouteDefinition(camelContext.getRouteDefinition(routeId)); +// } catch (Exception e) { +// e.printStackTrace(); +// } // if (route == null) { diff --git a/iot-server/server-starter/pom.xml b/iot-server/server-starter/pom.xml index 6035d6e4..8af079b2 100644 --- a/iot-server/server-starter/pom.xml +++ b/iot-server/server-starter/pom.xml @@ -84,7 +84,8 @@ - D:\\666 + + /opt/zeus/zeus-iot-bin src/main/webapp diff --git a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/config/IoTConfig.java b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/config/IoTConfig.java index a7827aee..fb081283 100644 --- a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/config/IoTConfig.java +++ b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/config/IoTConfig.java @@ -11,7 +11,8 @@ public class IoTConfig extends WebConfig { public void configConstant(Constants constants) { constants.setDevMode(true); constants.setMaxPostSize(1024 * 1024 * 100); - constants.setBaseUploadPath("D:\\666\\upload"); +// constants.setBaseUploadPath("D:\\666\\upload"); + constants.setBaseUploadPath("//opt//zeus//zeus-iot-bin//upload"); } @Override diff --git a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/IndexController.java b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/IndexController.java index cc9af17e..e6f51351 100644 --- a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/IndexController.java +++ b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/IndexController.java @@ -25,7 +25,7 @@ * @author nantian created at 2021/11/23 23:24 */ -@Path(value = "/123", viewPath = "/") +@Path(value = "/protocol", viewPath = "/") public class IndexController extends Controller { @@ -46,11 +46,15 @@ public void upload() { public void installArk() { - try { - ClientResponse response = ArkClient.installBiz(new File("D:\\666\\zeus-ark-hello2-1.0-beta-ark-biz.jar")); + String fileName = getPara("fileName"); + try { +// ClientResponse response = ArkClient.installBiz(new File("D:\\666\\zeus-ark-hello2-1.0-beta-ark-biz.jar")); // ClientResponse response1 = ArkClient.checkBiz("zeus-ark-hello", "1.0-beta"); +// ClientResponse response = ArkClient.installBiz(new File("D:\\666\\upload\\" + fileName)); + ClientResponse response = ArkClient.installBiz(new File("//opt//zeus//zeus-iot-bin//upload//" + fileName)); + renderJson(response); } catch (Throwable e) { diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolComponent.java b/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolComponent.java new file mode 100644 index 00000000..1360d8ef --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolComponent.java @@ -0,0 +1,29 @@ +package com.zmops.iot.domain.protocol; + +import com.zmops.iot.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "protocol_component") +public class ProtocolComponent extends BaseEntity { + + @Id + private Long protocolComponentId; + + private String name; + private String effectProxy; + private String status; + private String remark; + private Long tenantId; + private String fileName; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolGateway.java b/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolGateway.java new file mode 100644 index 00000000..7f198383 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolGateway.java @@ -0,0 +1,31 @@ +package com.zmops.iot.domain.protocol; + +import com.zmops.iot.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "protocol_gateway") +public class ProtocolGateway extends BaseEntity { + + @Id + private Long protocolGatewayId; + + private String name; + private String protocolType; + private Long protocolServiceId; + private Long protocolComponentId; + private String status; + private String remark; + private Long tenantId; + private Integer qos; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolGatewayMqtt.java b/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolGatewayMqtt.java new file mode 100644 index 00000000..e79e6e52 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolGatewayMqtt.java @@ -0,0 +1,27 @@ +package com.zmops.iot.domain.protocol; + +import com.zmops.iot.domain.BaseEntity; +import lombok.*; + +import javax.persistence.Entity; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "protocol_gateway_mqtt") +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProtocolGatewayMqtt { + + private Long protocolGatewayId; + + private Long protocolComponentId; + + private String topic; + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolService.java b/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolService.java new file mode 100644 index 00000000..809654a1 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolService.java @@ -0,0 +1,33 @@ +package com.zmops.iot.domain.protocol; + +import com.zmops.iot.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "protocol_service") +public class ProtocolService extends BaseEntity { + + @Id + private Long protocolServiceId; + + private String name; + private String effectProxy; + private String protocolType; + private String remark; + private Long tenantId; + private String url; + private String ip; + private Integer port; + private Integer msgLength; + private String clientId; +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZeusServer.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZeusServer.java new file mode 100644 index 00000000..e77f1195 --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZeusServer.java @@ -0,0 +1,24 @@ +package com.zmops.zeus.driver.service; + +import com.dtflys.forest.annotation.DataFile; +import com.dtflys.forest.annotation.Post; +import com.dtflys.forest.annotation.Var; +import com.dtflys.forest.callback.OnProgress; +import org.springframework.web.multipart.MultipartFile; + +/** + * @author yefei + **/ +public interface ZeusServer { + + /** + * 上传 协议包 + * + * @param ip 服务器IP + * @param file 文件 + * @param onProgress 进度处理 + * @return map + */ + @Post(url = "http://${ip}:12800/protocol/upload") + void upload(@Var("ip") String ip, @DataFile("file") MultipartFile file, OnProgress onProgress); +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index 23e107a6..759f748e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -206,7 +206,16 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { PROXY_EXISTS(2001, "代理服务已存在"), PROXY_NOT_EXISTS(2002, "代理服务不存在"), - + /** + * 协议相关 + */ + PROTOCOL_COMPONENT_EXISTS(2301,"协议组件名称已存在"), + PROTOCOL_COMPONENT_NOT_EXISTS(2302,"协议组件不存在"), + PROTOCOL_COMPONENT_HAS_BIND_GATEWAY(2303,"协议组件已绑定协议网关,不能删除"), + PROTOCOL_SERVICE_EXISTS(2304,"通信服务名称已存在"), + PROTOCOL_SERVICE_NOT_EXISTS(2305,"通信服务不存在"), + PROTOCOL_SERVICE_HAS_BIND_GATEWAY(2306,"通信服务已绑定协议网关,不能删除"), + PROTOCOL_GATEWAY_NOT_EXISTS(2307,"协议网关不存在"), /** * 数据转换相关 * diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolComponentController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolComponentController.java new file mode 100644 index 00000000..2ca462ed --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolComponentController.java @@ -0,0 +1,160 @@ +package com.zmops.iot.web.protocol.controller; + +import com.dtflys.forest.Forest; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.protocol.ProtocolComponent; +import com.zmops.iot.domain.protocol.query.QProtocolComponent; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.protocol.dto.ProtocolComponentDto; +import com.zmops.iot.web.protocol.dto.param.ProtocolComponentParam; +import com.zmops.iot.web.protocol.service.ProtocolComponentService; +import com.zmops.zeus.driver.service.ZeusServer; +import io.ebean.DB; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.Map; + +/** + * 协议组件 + * + * @author yefei + **/ +@RestController +@RequestMapping("/protocol/component") +public class ProtocolComponentController { + + @Autowired + ProtocolComponentService protocolComponentService; + + @Autowired + ZeusServer zeusServer; + + /** + * 协议组件分页列表 + */ + @RequestMapping("/getProtocolComponentByPage") + public Pager getProtocolComponentByPage(@RequestBody ProtocolComponentParam protocolComponentParam) { + return protocolComponentService.getProtocolComponentByPage(protocolComponentParam); + } + + /** + * 协议组件列表 + */ + @RequestMapping("/list") + public ResponseData list(@RequestBody ProtocolComponentParam protocolComponentParam) { + return ResponseData.success(protocolComponentService.list(protocolComponentParam)); + } + + + /** + * 协议组件创建 + */ + @RequestMapping("/create") + public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody ProtocolComponentParam protocolComponentParam) { + int count = new QProtocolComponent().name.eq(protocolComponentParam.getName()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_COMPONENT_EXISTS); + } + return ResponseData.success(protocolComponentService.create(protocolComponentParam)); + } + + /** + * 协议组件修改 + */ + @RequestMapping("/update") + public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody ProtocolComponentParam protocolComponentParam) { + int count = new QProtocolComponent().name.eq(protocolComponentParam.getName()).protocolComponentId.ne(protocolComponentParam.getProtocolComponentId()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_COMPONENT_EXISTS); + } + return ResponseData.success(protocolComponentService.update(protocolComponentParam)); + } + + /** + * 协议组件上传 + */ + @RequestMapping("/upload") + public ResponseData upload(@RequestParam("file") MultipartFile file, @RequestParam("protocolComponentId") Long protocolComponentId, HttpServletRequest request) throws IOException, URISyntaxException { + ProtocolComponent protocolComponent = new QProtocolComponent().protocolComponentId.eq(protocolComponentId).findOne(); + if (protocolComponent == null) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_COMPONENT_NOT_EXISTS); + } + try { + zeusServer.upload("127.0.0.1", file, progress -> { + System.out.println("total bytes: " + progress.getTotalBytes()); // 文件大小 + System.out.println("current bytes: " + progress.getCurrentBytes()); // 已上传字节数 + System.out.println("progress: " + Math.round(progress.getRate() * 100) + "%"); // 已上传百分比 + if (progress.isDone()) { // 是否上传完成 + System.out.println("-------- Upload Completed! --------"); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + protocolComponent.setStatus("1"); + protocolComponent.setFileName(file.getOriginalFilename()); + DB.update(protocolComponent); + return ResponseData.success(); + } + + /** + * 协议组件删除 + */ + @RequestMapping("/delete") + public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody ProtocolComponentParam protocolComponentParam) { + protocolComponentService.delete(protocolComponentParam.getProtocolComponentIds()); + return ResponseData.success(protocolComponentParam.getProtocolComponentIds()); + } + + /** + * 协议组件发布 + */ + @RequestMapping("/publish") + public ResponseData publish(@RequestParam("protocolComponentId") Long protocolComponentId) { + ProtocolComponent protocolComponent = new QProtocolComponent().protocolComponentId.eq(protocolComponentId).findOne(); + if (protocolComponent == null) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_COMPONENT_NOT_EXISTS); + } + protocolComponent.setStatus("2"); + DB.update(protocolComponent); + //TODO 调用服务发布 + + Map params = new HashMap<>(1); + params.put("fileName", protocolComponent.getFileName()); + Forest.post("/protocol/installArk").host("127.0.0.1").port(12800).addBody(params, "text/html;charset=utf-8").execute(); + + return ResponseData.success(); + } + + /** + * 协议组件取消发布 + */ + @RequestMapping("/unPublish") + public ResponseData unPublish(@RequestParam("protocolComponentId") Long protocolComponentId) { + ProtocolComponent protocolComponent = new QProtocolComponent().protocolComponentId.eq(protocolComponentId).findOne(); + if (protocolComponent == null) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_COMPONENT_NOT_EXISTS); + } + protocolComponent.setStatus("1"); + DB.update(protocolComponent); + + Map params = new HashMap<>(1); + params.put("fileName", protocolComponent.getFileName()); + Forest.post("/protocol/uninstallArk").host("127.0.0.1").port(12800).addBody(params, "text/html;charset=utf-8").execute(); + + return ResponseData.success(); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolGatewayController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolGatewayController.java new file mode 100644 index 00000000..35a21b8f --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolGatewayController.java @@ -0,0 +1,131 @@ +package com.zmops.iot.web.protocol.controller; + +import com.dtflys.forest.Forest; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.protocol.ProtocolGateway; +import com.zmops.iot.domain.protocol.query.QProtocolComponent; +import com.zmops.iot.domain.protocol.query.QProtocolGateway; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.protocol.dto.ProtocolGatewayDto; +import com.zmops.iot.web.protocol.dto.param.ProtocolGatewayParam; +import com.zmops.iot.web.protocol.service.ProtocolGatewayService; +import com.zmops.zeus.driver.service.ZeusServer; +import io.ebean.DB; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + +/** + * 协议网关 + * + * @author yefei + **/ +@RestController +@RequestMapping("/protocol/gateway") +public class ProtocolGatewayController { + + @Autowired + ProtocolGatewayService protocolGatewayService; + + @Autowired + ZeusServer zeusServer; + + /** + * 协议网关分页列表 + */ + @RequestMapping("/getProtocolGatewayByPage") + public Pager getProtocolGatewayByPage(@RequestBody ProtocolGatewayParam protocolGatewayParam) { + return protocolGatewayService.getProtocolGatewayByPage(protocolGatewayParam); + } + + /** + * 协议网关列表 + */ + @RequestMapping("/list") + public ResponseData list(@RequestBody ProtocolGatewayParam protocolGatewayParam) { + return ResponseData.success(protocolGatewayService.list(protocolGatewayParam)); + } + + /** + * 协议网关创建 + */ + @RequestMapping("/create") + public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody ProtocolGatewayParam protocolGatewayParam) { + int count = new QProtocolComponent().name.eq(protocolGatewayParam.getName()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_COMPONENT_EXISTS); + } + return ResponseData.success(protocolGatewayService.create(protocolGatewayParam)); + } + + /** + * 协议网关修改 + */ + @RequestMapping("/update") + public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody ProtocolGatewayParam protocolGatewayParam) { + int count = new QProtocolComponent().name.eq(protocolGatewayParam.getName()).protocolComponentId.ne(protocolGatewayParam.getProtocolComponentId()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_COMPONENT_EXISTS); + } + return ResponseData.success(protocolGatewayService.update(protocolGatewayParam)); + } + + + /** + * 协议网关删除 + */ + @RequestMapping("/delete") + public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody ProtocolGatewayParam protocolGatewayParam) { + protocolGatewayService.delete(protocolGatewayParam.getProtocolGatewayIds()); + return ResponseData.success(protocolGatewayParam.getProtocolGatewayIds()); + } + + /** + * 协议网关启动 + */ + @RequestMapping("/start") + public ResponseData start(@RequestParam("protocolGatewayId") Long protocolGatewayId) { + ProtocolGateway protocolGateway = new QProtocolGateway().protocolGatewayId.eq(protocolGatewayId).findOne(); + if (protocolGateway == null) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_GATEWAY_NOT_EXISTS); + } + protocolGateway.setStatus("1"); + DB.update(protocolGateway); + + Map params = new HashMap<>(1); + params.put("routeId", protocolGatewayId + ""); + Forest.post("/protocol/startRoute").host("127.0.0.1").port(12800).addBody(params,"text/html;charset=utf-8").execute(); + + return ResponseData.success(); + } + + /** + * 协议网关停止 + */ + @RequestMapping("/stop") + public ResponseData stop(@RequestParam("protocolGatewayId") Long protocolGatewayId) { + ProtocolGateway protocolGateway = new QProtocolGateway().protocolGatewayId.eq(protocolGatewayId).findOne(); + if (protocolGateway == null) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_GATEWAY_NOT_EXISTS); + } + protocolGateway.setStatus("0"); + DB.update(protocolGateway); + + + Map params = new HashMap<>(1); + params.put("routeId", protocolGatewayId + ""); + Forest.post("/protocol/stopRoute").host("127.0.0.1").port(12800).addBody(params,"text/html;charset=utf-8").execute(); + + return ResponseData.success(); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolServiceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolServiceController.java new file mode 100644 index 00000000..ac3362b7 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolServiceController.java @@ -0,0 +1,83 @@ +package com.zmops.iot.web.protocol.controller; + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.protocol.query.QProtocolComponent; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.protocol.dto.ProtocolServiceDto; +import com.zmops.iot.web.protocol.dto.param.ProtocolComponentParam; +import com.zmops.iot.web.protocol.dto.param.ProtocolServiceParam; +import com.zmops.iot.web.protocol.service.ProtocolSvrService; +import com.zmops.zeus.driver.service.ZeusServer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 协议服务 + * + * @author yefei + **/ +@RestController +@RequestMapping("/protocol/service") +public class ProtocolServiceController { + + @Autowired + ProtocolSvrService protocolSvrService; + + /** + * 协议组件分页列表 + */ + @RequestMapping("/getProtocolServiceByPage") + public Pager getProtocolComponentByPage(@RequestBody ProtocolServiceParam protocolServiceParam) { + return protocolSvrService.getProtocolServiceByPage(protocolServiceParam); + } + + /** + * 协议组件列表 + */ + @RequestMapping("/list") + public ResponseData list(@RequestBody ProtocolServiceParam protocolServiceParam) { + return ResponseData.success(protocolSvrService.list(protocolServiceParam)); + } + + + /** + * 协议组件创建 + */ + @RequestMapping("/create") + public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody ProtocolServiceParam protocolServiceParam) { + int count = new QProtocolComponent().name.eq(protocolServiceParam.getName()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_SERVICE_EXISTS); + } + return ResponseData.success(protocolSvrService.create(protocolServiceParam)); + } + + /** + * 协议组件修改 + */ + @RequestMapping("/update") + public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody ProtocolServiceParam protocolServiceParam) { + int count = new QProtocolComponent().name.eq(protocolServiceParam.getName()).protocolComponentId.ne(protocolServiceParam.getProtocolServiceId()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_SERVICE_EXISTS); + } + return ResponseData.success(protocolSvrService.update(protocolServiceParam)); + } + + + /** + * 协议组件删除 + */ + @RequestMapping("/delete") + public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody ProtocolServiceParam protocolServiceParam) { + protocolSvrService.delete(protocolServiceParam.getProtocolServiceIds()); + return ResponseData.success(protocolServiceParam.getProtocolServiceIds()); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolComponentDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolComponentDto.java new file mode 100644 index 00000000..6e783155 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolComponentDto.java @@ -0,0 +1,36 @@ +package com.zmops.iot.web.protocol.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author yefei + **/ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class ProtocolComponentDto { + private Long protocolComponentId; + private String name; + private String effectProxy; + @CachedValue(value = "PROTOCOL_COMPONENT_STATUS", fieldName = "statusName") + private String status; + private String remark; + private String fileName; + LocalDateTime createTime; + + LocalDateTime updateTime; + + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") + Long createUser; + + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") + Long updateUser; + + @CachedValue(type = DicType.Tenant, fieldName = "tenantName") + Long tenantId; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolGatewayDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolGatewayDto.java new file mode 100644 index 00000000..23e7ea82 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolGatewayDto.java @@ -0,0 +1,47 @@ +package com.zmops.iot.web.protocol.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.protocol.ProtocolGatewayMqtt; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.time.LocalDateTime; +import java.util.List; + +/** + * @author yefei + **/ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class ProtocolGatewayDto { + private Long protocolGatewayId; + @NotBlank(groups = {BaseEntity.Create.class}) + private String name; + private String protocolType; + // @CachedValue(type = DicType.PROTOCOL_SERVICE, fieldName = "protocolServiceName") + private Long protocolServiceId; + @CachedValue(value = "PROTOCOL_GATEWAY_STATUS", fieldName = "statusName") + private String status; + private Long protocolComponentId; + private String remark; + private Integer qos; + + LocalDateTime createTime; + + LocalDateTime updateTime; + + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") + Long createUser; + + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") + Long updateUser; + + @CachedValue(type = DicType.Tenant, fieldName = "tenantName") + Long tenantId; + + private List protocolGatewayMqttList; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolOption.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolOption.java new file mode 100644 index 00000000..e2f76afe --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolOption.java @@ -0,0 +1,19 @@ +package com.zmops.iot.web.protocol.dto; + +import lombok.Data; + +import java.util.Map; + +/** + * @author yefei + **/ +@Data +public class ProtocolOption { + private String routeId; + + private String protocol; + +// private ProtocolAction action; + + private Map options; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolServiceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolServiceDto.java new file mode 100644 index 00000000..75579fc9 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolServiceDto.java @@ -0,0 +1,39 @@ +package com.zmops.iot.web.protocol.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author yefei + **/ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class ProtocolServiceDto { + private Long protocolServiceId; + private String name; + private String effectProxy; + @CachedValue(value = "PROTOCOL_TYPE", fieldName = "protocolTypeName") + private String protocolType; + private String remark; + private String url; + private String ip; + private Integer port; + private Integer msgLength; + LocalDateTime createTime; + + LocalDateTime updateTime; + + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") + Long createUser; + + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") + Long updateUser; + + @CachedValue(type = DicType.Tenant, fieldName = "tenantName") + Long tenantId; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolComponentParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolComponentParam.java new file mode 100644 index 00000000..bcf1faa7 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolComponentParam.java @@ -0,0 +1,30 @@ +package com.zmops.iot.web.protocol.dto.param; + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class ProtocolComponentParam extends BaseQueryParam { + @NotNull(groups = BaseEntity.Update.class) + private Long protocolComponentId; + @NotBlank(groups = {BaseEntity.Create.class}) + private String name; + @NotBlank(groups = {BaseEntity.Update.class}) + private String effectProxy; + private String source; + private String status; + private String remark; + private Long tenantId; + private String fileName; + + @NotNull(groups = BaseEntity.Delete.class) + private List protocolComponentIds; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolGatewayParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolGatewayParam.java new file mode 100644 index 00000000..1eaa1dbf --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolGatewayParam.java @@ -0,0 +1,31 @@ +package com.zmops.iot.web.protocol.dto.param; + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.protocol.ProtocolGatewayMqtt; +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class ProtocolGatewayParam extends BaseQueryParam { + @NotNull(groups = BaseEntity.Update.class) + private Long protocolGatewayId; + @NotBlank(groups = {BaseEntity.Create.class}) + private String name; + private String protocolType; + private Long protocolServiceId; + private Long protocolComponentId; + private List protocolGatewayMqttList; + private String remark; + private Long tenantId; + private Integer qos; + + @NotNull(groups = BaseEntity.Delete.class) + private List protocolGatewayIds; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolServiceParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolServiceParam.java new file mode 100644 index 00000000..d77d1caf --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolServiceParam.java @@ -0,0 +1,33 @@ +package com.zmops.iot.web.protocol.dto.param; + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class ProtocolServiceParam extends BaseQueryParam { + @NotNull(groups = BaseEntity.Update.class) + private Long protocolServiceId; + @NotBlank(groups = {BaseEntity.Create.class}) + private String name; + @NotBlank(groups = {BaseEntity.Update.class}) + private String effectProxy; + private String protocolType; + private String remark; + private Long tenantId; + private String url; + private String ip; + private Integer port; + private Integer msgLength; + private String clientId; + + @NotNull(groups = BaseEntity.Delete.class) + private List protocolServiceIds; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/enums/ProtocolEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/enums/ProtocolEnum.java new file mode 100644 index 00000000..40d27e03 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/enums/ProtocolEnum.java @@ -0,0 +1,38 @@ +package com.zmops.iot.web.protocol.enums; + +import lombok.Getter; + +/** + * @author yefei + **/ +public enum ProtocolEnum { + HttpServer("5","HttpServer"), + MqttClient("1","MqttClient"), + TcpServer("2","TcpServer"), + UdpServer("4","UdpServer"), + CoapServer("9","CoapServer"), + WebSocketServer("7","WebSocketServer"); + + @Getter + String code; + @Getter + String message; + + ProtocolEnum(String code, String message) { + this.code = code; + this.message = message; + } + + public static String getDescription(String status) { + if (status == null) { + return ""; + } else { + for (ProtocolEnum s : ProtocolEnum.values()) { + if (s.getCode().equals(status)) { + return s.getMessage(); + } + } + return ""; + } + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolComponentService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolComponentService.java new file mode 100644 index 00000000..b58fee52 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolComponentService.java @@ -0,0 +1,87 @@ +package com.zmops.iot.web.protocol.service; + +import com.zmops.iot.domain.protocol.ProtocolComponent; +import com.zmops.iot.domain.protocol.query.QProtocolComponent; +import com.zmops.iot.domain.protocol.query.QProtocolGateway; +import com.zmops.iot.domain.protocol.query.QProtocolGatewayMqtt; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.protocol.dto.ProtocolComponentDto; +import com.zmops.iot.web.protocol.dto.param.ProtocolComponentParam; +import io.ebean.DB; +import io.ebean.PagedList; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author yefei + **/ +@Service +public class ProtocolComponentService { + + public Pager getProtocolComponentByPage(ProtocolComponentParam protocolComponentParam) { + QProtocolComponent qProtocolComponent = new QProtocolComponent(); + + if (ToolUtil.isNotEmpty(protocolComponentParam.getName())) { + qProtocolComponent.name.contains(protocolComponentParam.getName()); + } + + if (ToolUtil.isNotEmpty(protocolComponentParam.getStatus())) { + qProtocolComponent.status.eq(protocolComponentParam.getStatus()); + } + + PagedList pagedList = qProtocolComponent.setFirstRow((protocolComponentParam.getPage() - 1) * protocolComponentParam.getMaxRow()) + .setMaxRows(protocolComponentParam.getMaxRow()).findPagedList(); + + List protocolComponentDtoList = ToolUtil.convertBean(pagedList.getList(), ProtocolComponentDto.class); + + return new Pager<>(protocolComponentDtoList, pagedList.getTotalCount()); + } + + public List list(ProtocolComponentParam protocolComponentParam) { + QProtocolComponent qProtocolComponent = new QProtocolComponent(); + qProtocolComponent.status.eq("2"); + if (ToolUtil.isNotEmpty(protocolComponentParam.getName())) { + qProtocolComponent.name.contains(protocolComponentParam.getName()); + } + + if (ToolUtil.isNotEmpty(protocolComponentParam.getStatus())) { + qProtocolComponent.status.eq(protocolComponentParam.getStatus()); + } + return qProtocolComponent.findList(); + } + + public ProtocolComponent create(ProtocolComponentParam protocolComponentParam) { + ProtocolComponent protocolComponent = new ProtocolComponent(); + ToolUtil.copyProperties(protocolComponentParam, protocolComponent); + protocolComponent.setStatus("0"); + DB.insert(protocolComponent); + return protocolComponent; + } + + public ProtocolComponent update(ProtocolComponentParam protocolComponentParam) { + ProtocolComponent protocolComponent = new ProtocolComponent(); + ToolUtil.copyProperties(protocolComponentParam, protocolComponent); + DB.update(protocolComponent); + return protocolComponent; + } + + public void delete(List protocolComponentIds) { + int count = new QProtocolGateway().protocolComponentId.in(protocolComponentIds).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_COMPONENT_HAS_BIND_GATEWAY); + } + + count = new QProtocolGatewayMqtt().protocolComponentId.in(protocolComponentIds).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_COMPONENT_HAS_BIND_GATEWAY); + } + + new QProtocolComponent().protocolComponentId.in(protocolComponentIds).delete(); + } + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolGatewayService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolGatewayService.java new file mode 100644 index 00000000..2c912fc8 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolGatewayService.java @@ -0,0 +1,147 @@ +package com.zmops.iot.web.protocol.service; + +import com.alibaba.fastjson.JSON; +import com.dtflys.forest.Forest; +import com.zmops.iot.domain.protocol.ProtocolComponent; +import com.zmops.iot.domain.protocol.ProtocolGateway; +import com.zmops.iot.domain.protocol.ProtocolGatewayMqtt; +import com.zmops.iot.domain.protocol.ProtocolService; +import com.zmops.iot.domain.protocol.query.QProtocolGateway; +import com.zmops.iot.domain.protocol.query.QProtocolGatewayMqtt; +import com.zmops.iot.domain.protocol.query.QProtocolService; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.protocol.dto.ProtocolGatewayDto; +import com.zmops.iot.web.protocol.dto.ProtocolOption; +import com.zmops.iot.web.protocol.dto.param.ProtocolGatewayParam; +import com.zmops.iot.web.protocol.enums.ProtocolEnum; +import io.ebean.DB; +import io.ebean.PagedList; +import io.ebean.annotation.Transactional; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + **/ +@Service +public class ProtocolGatewayService { + + public Pager getProtocolGatewayByPage(ProtocolGatewayParam protocolGatewayParam) { + QProtocolGateway qProtocolGateway = new QProtocolGateway(); + + if (ToolUtil.isNotEmpty(protocolGatewayParam.getName())) { + qProtocolGateway.name.contains(protocolGatewayParam.getName()); + } + + if (ToolUtil.isNotEmpty(protocolGatewayParam.getProtocolType())) { + qProtocolGateway.protocolType.eq(protocolGatewayParam.getProtocolType()); + } + + PagedList pagedList = qProtocolGateway.setFirstRow((protocolGatewayParam.getPage() - 1) * protocolGatewayParam.getMaxRow()) + .setMaxRows(protocolGatewayParam.getMaxRow()).findPagedList(); + + List protocolGatewayDtoList = ToolUtil.convertBean(pagedList.getList(), ProtocolGatewayDto.class); + + //关联mqtt协议组件 + List ids = protocolGatewayDtoList.parallelStream().map(ProtocolGatewayDto::getProtocolGatewayId).collect(Collectors.toList()); + List topicList = new QProtocolGatewayMqtt().protocolGatewayId.in(ids).findList(); + Map> topicMap = topicList.parallelStream().collect(Collectors.groupingBy(ProtocolGatewayMqtt::getProtocolGatewayId)); + + protocolGatewayDtoList.forEach(protocolGatewayDto -> { + if (ToolUtil.isNotEmpty(topicMap.get(protocolGatewayDto.getProtocolGatewayId()))) { + protocolGatewayDto.setProtocolGatewayMqttList(topicMap.get(protocolGatewayDto.getProtocolGatewayId())); + } + }); + + return new Pager<>(protocolGatewayDtoList, pagedList.getTotalCount()); + } + + public List list(ProtocolGatewayParam protocolGatewayParam) { + QProtocolGateway qProtocolGateway = new QProtocolGateway(); + if (ToolUtil.isNotEmpty(protocolGatewayParam.getName())) { + qProtocolGateway.name.contains(protocolGatewayParam.getName()); + } + + if (ToolUtil.isNotEmpty(protocolGatewayParam.getProtocolType())) { + qProtocolGateway.protocolType.eq(protocolGatewayParam.getProtocolType()); + } + return qProtocolGateway.findList(); + } + + @Transactional + public ProtocolGateway create(ProtocolGatewayParam protocolGatewayParam) { + ProtocolGateway ProtocolGateway = new ProtocolGateway(); + ToolUtil.copyProperties(protocolGatewayParam, ProtocolGateway); + ProtocolGateway.setStatus("0"); + DB.insert(ProtocolGateway); + + saveMqtt(protocolGatewayParam.getProtocolGatewayMqttList(), protocolGatewayParam.getProtocolGatewayId()); + + Map option = initOptionMap(protocolGatewayParam); + + ProtocolOption protocolOption = new ProtocolOption(); + protocolOption.setRouteId(ProtocolGateway.getProtocolGatewayId() + ""); + protocolOption.setProtocol(ProtocolEnum.getDescription(protocolGatewayParam.getProtocolType())); + protocolOption.setOptions(option); + + Forest.post("/protocol/createRoute").host("127.0.0.1").port(12800).contentTypeJson().addBody(JSON.toJSON(protocolOption)).execute(); + return ProtocolGateway; + } + + private Map initOptionMap(ProtocolGatewayParam protocolGatewayParam) { + Map option = new HashMap<>(3); + ProtocolService protocolService = new QProtocolService().protocolServiceId.eq(protocolGatewayParam.getProtocolServiceId()).findOne(); + option.put("hostIp", protocolService.getIp()); + option.put("port", protocolService.getPort()); + if (ToolUtil.isNotEmpty(protocolGatewayParam.getProtocolGatewayMqttList())) { + String topics = protocolGatewayParam.getProtocolGatewayMqttList().parallelStream().map(ProtocolGatewayMqtt::getTopic).collect(Collectors.joining(";")); + option.put("topicNames", topics); + } + + option.put("port", protocolService.getPort()); + + + return option; + } + + @Transactional + public ProtocolComponent update(ProtocolGatewayParam protocolGatewayParam) { + ProtocolComponent protocolComponent = new ProtocolComponent(); + ToolUtil.copyProperties(protocolGatewayParam, protocolComponent); + DB.update(protocolComponent); + + new QProtocolGatewayMqtt().protocolGatewayId.eq(protocolGatewayParam.getProtocolGatewayId()).delete(); + saveMqtt(protocolGatewayParam.getProtocolGatewayMqttList(), protocolGatewayParam.getProtocolGatewayId()); + + return protocolComponent; + } + + private void saveMqtt(List protocolGatewayMqtts, Long protocolGatewayId) { + if (ToolUtil.isNotEmpty(protocolGatewayMqtts)) { + List protocolGatewayMqttList = new ArrayList<>(); + protocolGatewayMqtts.forEach(mqtt -> { + mqtt.setProtocolGatewayId(protocolGatewayId); + protocolGatewayMqttList.add(mqtt); + }); + DB.insertAll(protocolGatewayMqttList); + } + } + + public void delete(List protocolGatewayIds) { +// int count = new QProtocolGateway().protocolServiceId.in(protocolServiceIds).findCount(); +// if (count > 0) { +// throw new ServiceException(BizExceptionEnum.PROTOCOL_SERVICE_HAS_BIND_GATEWAY); +// } + + new QProtocolGateway().protocolGatewayId.in(protocolGatewayIds).delete(); + new QProtocolGatewayMqtt().protocolGatewayId.in(protocolGatewayIds).delete(); + } + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolSvrService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolSvrService.java new file mode 100644 index 00000000..5c42cf01 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolSvrService.java @@ -0,0 +1,80 @@ +package com.zmops.iot.web.protocol.service; + +import com.zmops.iot.domain.protocol.ProtocolComponent; +import com.zmops.iot.domain.protocol.ProtocolService; +import com.zmops.iot.domain.protocol.query.QProtocolGateway; +import com.zmops.iot.domain.protocol.query.QProtocolService; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.protocol.dto.ProtocolServiceDto; +import com.zmops.iot.web.protocol.dto.param.ProtocolServiceParam; +import io.ebean.DB; +import io.ebean.PagedList; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author yefei + **/ +@Service +public class ProtocolSvrService { + + public Pager getProtocolServiceByPage(ProtocolServiceParam protocolServiceParam) { + QProtocolService qProtocolService = new QProtocolService(); + + if (ToolUtil.isNotEmpty(protocolServiceParam.getName())) { + qProtocolService.name.contains(protocolServiceParam.getName()); + } + + if (ToolUtil.isNotEmpty(protocolServiceParam.getProtocolType())) { + qProtocolService.protocolType.eq(protocolServiceParam.getProtocolType()); + } + + PagedList pagedList = qProtocolService.setFirstRow((protocolServiceParam.getPage() - 1) * protocolServiceParam.getMaxRow()) + .setMaxRows(protocolServiceParam.getMaxRow()).findPagedList(); + + List protocolComponentDtoList = ToolUtil.convertBean(pagedList.getList(), ProtocolServiceDto.class); + + return new Pager<>(protocolComponentDtoList, pagedList.getTotalCount()); + } + + public List list(ProtocolServiceParam protocolServiceParam) { + QProtocolService qProtocolService = new QProtocolService(); + if (ToolUtil.isNotEmpty(protocolServiceParam.getName())) { + qProtocolService.name.contains(protocolServiceParam.getName()); + } + + if (ToolUtil.isNotEmpty(protocolServiceParam.getProtocolType())) { + qProtocolService.protocolType.eq(protocolServiceParam.getProtocolType()); + } + return qProtocolService.findList(); + } + + public ProtocolService create(ProtocolServiceParam protocolServiceParam) { + ProtocolService ProtocolService = new ProtocolService(); + ToolUtil.copyProperties(protocolServiceParam, ProtocolService); + DB.insert(ProtocolService); + return ProtocolService; + } + + public ProtocolService update(ProtocolServiceParam protocolServiceParam) { + ProtocolService ProtocolService = new ProtocolService(); + ToolUtil.copyProperties(protocolServiceParam, ProtocolService); + DB.insert(ProtocolService); + return ProtocolService; + } + + public void delete(List protocolServiceIds) { + int count = new QProtocolGateway().protocolServiceId.in(protocolServiceIds).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_SERVICE_HAS_BIND_GATEWAY); + } + + new QProtocolService().protocolServiceId.in(protocolServiceIds).delete(); + } + + +} From 0809d925483b7c2b821f1b7e28e45767dc36f159 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 13 Dec 2021 17:49:24 +0800 Subject: [PATCH 717/763] [fix]: remove forest retry --- iot-server/server-starter/pom.xml | 2 +- zeus-starter/src/main/resources/application.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/iot-server/server-starter/pom.xml b/iot-server/server-starter/pom.xml index 8af079b2..a91aec22 100644 --- a/iot-server/server-starter/pom.xml +++ b/iot-server/server-starter/pom.xml @@ -85,7 +85,7 @@ - /opt/zeus/zeus-iot-bin + //opt//zeus//zeus-iot-bin src/main/webapp diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index 7b777cb4..c25e6159 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -43,8 +43,8 @@ spring: forest: log-enabled: true timeout: 5000 - max-retry-count: 3 # 最大请求重试次数,默认为 0 次 - max-retry-interval: 10 # 为最大重试时间间隔, 单位为毫秒,默认为 0 毫秒 +# max-retry-count: 3 # 最大请求重试次数,默认为 0 次 +# max-retry-interval: 10 # 为最大重试时间间隔, 单位为毫秒,默认为 0 毫秒 variables: ## Zabbix API IP And ServerIp and ServerPort zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} From 6f868e65d50411bd8c6204c18e8666698d7d1cc1 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 14 Dec 2021 10:18:44 +0800 Subject: [PATCH 718/763] [fix]: fix protocol --- .../iot/model/cache/ProtocolServiceCache.java | 24 +++++++++++++++++++ .../model/cache/filter/CachedValueFilter.java | 5 ++++ .../zmops/iot/model/cache/filter/DicType.java | 1 + .../com/zmops/iot/util/DefinitionsUtil.java | 12 ++++++++++ .../web/protocol/dto/ProtocolGatewayDto.java | 17 ++++++------- .../web/protocol/dto/ProtocolServiceDto.java | 1 + .../service/ProtocolGatewayService.java | 13 +++++----- .../protocol/service/ProtocolSvrService.java | 24 ++++++++++++++++--- 8 files changed, 79 insertions(+), 18 deletions(-) create mode 100644 zeus-common/src/main/java/com/zmops/iot/model/cache/ProtocolServiceCache.java diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/ProtocolServiceCache.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/ProtocolServiceCache.java new file mode 100644 index 00000000..5ceec310 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/ProtocolServiceCache.java @@ -0,0 +1,24 @@ +package com.zmops.iot.model.cache; + + +import java.util.Map; +import java.util.Optional; + +/** + * @author yefei + **/ +public class ProtocolServiceCache extends AbstractCache { + + public ProtocolServiceCache() { + super(); + } + + public void updateName(Map map) { + update(map); + } + + public String getName(Long id) { + return Optional.ofNullable(get(id)).orElse(null); + } + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java index 421735a7..e0ce4e41 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java @@ -115,6 +115,11 @@ private String getCachedValue(CachedValue cachedValue, Object value) { return DefinitionsUtil.getDeviceName((String) value); } break; + case ProtocolService: + if (value instanceof Long) { + return DefinitionsUtil.getProtocolServiceName((long) value); + } + break; default: return null; } diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/DicType.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/DicType.java index 9c069681..065c3bf2 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/DicType.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/DicType.java @@ -12,6 +12,7 @@ public enum DicType { ProdType, Tenant, Device, + ProtocolService, Dictionary; diff --git a/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java b/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java index b313b740..e71797ca 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java @@ -53,6 +53,10 @@ public class DefinitionsUtil { @Setter private static ProductEventCache productEventCache = new ProductEventCache(); + @Getter + @Setter + private static ProtocolServiceCache protocolServiceCache = new ProtocolServiceCache(); + public static void updateDictionaries(Table dictionarys) { dictionaryCache.updateDictionaries(dictionarys); } @@ -121,4 +125,12 @@ public static void updateProductEventCache(Map map) { public static String getTriggerName(Long value) { return productEventCache.getTriggerName(value); } + + public static void updateProtocolServiceCache(Map map) { + protocolServiceCache.updateName(map); + } + + public static String getProtocolServiceName(Long value) { + return protocolServiceCache.getName(value); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolGatewayDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolGatewayDto.java index 23e7ea82..77c888d7 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolGatewayDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolGatewayDto.java @@ -18,16 +18,17 @@ @Data @JsonSerialize(using = CachedValueFilter.class) public class ProtocolGatewayDto { - private Long protocolGatewayId; + private Long protocolGatewayId; @NotBlank(groups = {BaseEntity.Create.class}) - private String name; - private String protocolType; - // @CachedValue(type = DicType.PROTOCOL_SERVICE, fieldName = "protocolServiceName") - private Long protocolServiceId; + private String name; + @CachedValue(value = "PROTOCOL_SERVICE_TYPE", fieldName = "protocolTypeName") + private String protocolType; + @CachedValue(type = DicType.ProtocolService, fieldName = "protocolServiceName") + private Long protocolServiceId; @CachedValue(value = "PROTOCOL_GATEWAY_STATUS", fieldName = "statusName") - private String status; - private Long protocolComponentId; - private String remark; + private String status; + private Long protocolComponentId; + private String remark; private Integer qos; LocalDateTime createTime; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolServiceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolServiceDto.java index 75579fc9..6a446631 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolServiceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolServiceDto.java @@ -24,6 +24,7 @@ public class ProtocolServiceDto { private String ip; private Integer port; private Integer msgLength; + private String clientId; LocalDateTime createTime; LocalDateTime updateTime; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolGatewayService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolGatewayService.java index 2c912fc8..288d3479 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolGatewayService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolGatewayService.java @@ -2,7 +2,6 @@ import com.alibaba.fastjson.JSON; import com.dtflys.forest.Forest; -import com.zmops.iot.domain.protocol.ProtocolComponent; import com.zmops.iot.domain.protocol.ProtocolGateway; import com.zmops.iot.domain.protocol.ProtocolGatewayMqtt; import com.zmops.iot.domain.protocol.ProtocolService; @@ -81,7 +80,7 @@ public ProtocolGateway create(ProtocolGatewayParam protocolGatewayParam) { ProtocolGateway.setStatus("0"); DB.insert(ProtocolGateway); - saveMqtt(protocolGatewayParam.getProtocolGatewayMqttList(), protocolGatewayParam.getProtocolGatewayId()); + saveMqtt(protocolGatewayParam.getProtocolGatewayMqttList(), ProtocolGateway.getProtocolGatewayId()); Map option = initOptionMap(protocolGatewayParam); @@ -111,15 +110,15 @@ private Map initOptionMap(ProtocolGatewayParam protocolGatewayPa } @Transactional - public ProtocolComponent update(ProtocolGatewayParam protocolGatewayParam) { - ProtocolComponent protocolComponent = new ProtocolComponent(); - ToolUtil.copyProperties(protocolGatewayParam, protocolComponent); - DB.update(protocolComponent); + public ProtocolGateway update(ProtocolGatewayParam protocolGatewayParam) { + ProtocolGateway protocolGateway = new ProtocolGateway(); + ToolUtil.copyProperties(protocolGatewayParam, protocolGateway); + DB.update(protocolGateway); new QProtocolGatewayMqtt().protocolGatewayId.eq(protocolGatewayParam.getProtocolGatewayId()).delete(); saveMqtt(protocolGatewayParam.getProtocolGatewayMqttList(), protocolGatewayParam.getProtocolGatewayId()); - return protocolComponent; + return protocolGateway; } private void saveMqtt(List protocolGatewayMqtts, Long protocolGatewayId) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolSvrService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolSvrService.java index 5c42cf01..83b4960d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolSvrService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolSvrService.java @@ -1,26 +1,29 @@ package com.zmops.iot.web.protocol.service; -import com.zmops.iot.domain.protocol.ProtocolComponent; import com.zmops.iot.domain.protocol.ProtocolService; import com.zmops.iot.domain.protocol.query.QProtocolGateway; import com.zmops.iot.domain.protocol.query.QProtocolService; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.protocol.dto.ProtocolServiceDto; import com.zmops.iot.web.protocol.dto.param.ProtocolServiceParam; import io.ebean.DB; import io.ebean.PagedList; +import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Service; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @author yefei **/ @Service -public class ProtocolSvrService { +public class ProtocolSvrService implements CommandLineRunner { public Pager getProtocolServiceByPage(ProtocolServiceParam protocolServiceParam) { QProtocolService qProtocolService = new QProtocolService(); @@ -57,13 +60,17 @@ public ProtocolService create(ProtocolServiceParam protocolServiceParam) { ProtocolService ProtocolService = new ProtocolService(); ToolUtil.copyProperties(protocolServiceParam, ProtocolService); DB.insert(ProtocolService); + + updateProtocolServiceEvent(); return ProtocolService; } public ProtocolService update(ProtocolServiceParam protocolServiceParam) { ProtocolService ProtocolService = new ProtocolService(); ToolUtil.copyProperties(protocolServiceParam, ProtocolService); - DB.insert(ProtocolService); + DB.update(ProtocolService); + + updateProtocolServiceEvent(); return ProtocolService; } @@ -74,7 +81,18 @@ public void delete(List protocolServiceIds) { } new QProtocolService().protocolServiceId.in(protocolServiceIds).delete(); + updateProtocolServiceEvent(); } + public void updateProtocolServiceEvent() { + List serviceList = new QProtocolService().findList(); + Map map = serviceList.parallelStream().collect(Collectors.toMap(ProtocolService::getProtocolServiceId, ProtocolService::getName)); + DefinitionsUtil.updateProtocolServiceCache(map); + } + + @Override + public void run(String... args) throws Exception { + updateProtocolServiceEvent(); + } } From 36bba0f5ba4956f42ea4e5c2f230dffd6f58ad30 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 14 Dec 2021 14:40:19 +0800 Subject: [PATCH 719/763] [fix]: build server-start ui --- iot-server/server-starter/pom.xml | 40 ++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/iot-server/server-starter/pom.xml b/iot-server/server-starter/pom.xml index a91aec22..5ed0b96c 100644 --- a/iot-server/server-starter/pom.xml +++ b/iot-server/server-starter/pom.xml @@ -9,6 +9,11 @@ 4.0.0 + + 1.11.0 + ./src/main/webapp/assets + + server-starter @@ -78,6 +83,39 @@ + + com.github.eirslett + frontend-maven-plugin + ${frontend-maven-plugin.version} + + ${ui.path} + v8.17.0 + + + + install node and npm + + install-node-and-npm + + + + npm install + + npm + + + install --registry=https://registry.npm.taobao.org/ --unsafe-perm + + + + build + + gulp + + + + + org.apache.maven.plugins maven-resources-plugin @@ -85,7 +123,7 @@ - //opt//zeus//zeus-iot-bin + /opt/zeus/zeus-iot-bin src/main/webapp From e8b3ccb84ec4982caba04a0a7b07cbe665acab74 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 14 Dec 2021 14:58:34 +0800 Subject: [PATCH 720/763] [fix]: fix pom --- iot-server/server-starter/pom.xml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/iot-server/server-starter/pom.xml b/iot-server/server-starter/pom.xml index 5ed0b96c..0d9795a0 100644 --- a/iot-server/server-starter/pom.xml +++ b/iot-server/server-starter/pom.xml @@ -107,6 +107,15 @@ install --registry=https://registry.npm.taobao.org/ --unsafe-perm + + npm install gulp + + npm + + + install --global gulp-cli + + build @@ -123,7 +132,7 @@ - /opt/zeus/zeus-iot-bin + /opt/zeus/zeus-iot-bin/ src/main/webapp From c87355d93119b308d5cd9868ca8d692a662fafcc Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 14 Dec 2021 15:20:10 +0800 Subject: [PATCH 721/763] [fix] fix pom --- iot-server/server-starter/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iot-server/server-starter/pom.xml b/iot-server/server-starter/pom.xml index 0d9795a0..0653f39d 100644 --- a/iot-server/server-starter/pom.xml +++ b/iot-server/server-starter/pom.xml @@ -132,7 +132,7 @@ - /opt/zeus/zeus-iot-bin/ + ${project.basedir}/ src/main/webapp From 0609594c67b2cd57e36a5c1ffcf99c9b46c48e15 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 14 Dec 2021 21:17:18 +0800 Subject: [PATCH 722/763] [feat]: add ignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 52886cd1..6ef74f47 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ zeus-starter/src/main/resources/public/ .bdb/ zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/Test.java logs/ +**/assets/node/* +iot-server/server-starter/assets/* +iot-server/server-starter/pages/* From ba72612c28e436d25d9adec4dd453bd0b652728d Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 14 Dec 2021 21:17:38 +0800 Subject: [PATCH 723/763] [feat]: update zeus ui --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index 41f42450..e4d2f536 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit 41f42450d3c186ab321f145c9b0e0d0e0b121216 +Subproject commit e4d2f5366566beacd8d04347f35a423de891b246 From 989a09743701aa4bd91028509734cdefe483e2cb Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 15 Dec 2021 13:35:47 +0800 Subject: [PATCH 724/763] remove submodule zabbix-agent --- camel-zabbix-agent | 1 - 1 file changed, 1 deletion(-) delete mode 160000 camel-zabbix-agent diff --git a/camel-zabbix-agent b/camel-zabbix-agent deleted file mode 160000 index 167deeab..00000000 --- a/camel-zabbix-agent +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 167deeabf366e045629fd0b950b09ee643ac6541 From 75a1b78a8e8c0f56975cc68877b47f55c6ae5dd0 Mon Sep 17 00:00:00 2001 From: nantian Date: Wed, 15 Dec 2021 14:13:49 +0800 Subject: [PATCH 725/763] [feat]: remove gateway web console --- .../src/main/webapp/assets/gulpfile.js | 170 - .../src/main/webapp/assets/package-lock.json | 3808 ----------------- .../src/main/webapp/assets/package.json | 23 - .../src/main/webapp/assets/src/config.js | 153 - .../webapp/assets/src/controller/common.js | 40 - .../webapp/assets/src/controller/console.js | 335 -- .../webapp/assets/src/controller/contlist.js | 166 - .../webapp/assets/src/controller/forum.js | 125 - .../webapp/assets/src/controller/sample.js | 299 -- .../webapp/assets/src/controller/senior.js | 1153 ----- .../main/webapp/assets/src/controller/set.js | 155 - .../main/webapp/assets/src/controller/user.js | 52 - .../webapp/assets/src/controller/useradmin.js | 184 - .../webapp/assets/src/controller/workorder.js | 70 - .../src/main/webapp/assets/src/index.js | 213 - .../src/main/webapp/assets/src/lib/admin.js | 861 ---- .../webapp/assets/src/lib/extend/echarts.js | 39 - .../assets/src/lib/extend/echartsTheme.js | 267 -- .../layim/layim-assets/html/chatlog.html | 98 - .../extend/layim/layim-assets/html/find.html | 43 - .../layim/layim-assets/html/getmsg.json | 72 - .../layim/layim-assets/html/msgbox.html | 218 - .../layim/layim-assets/images/default.png | Bin 6727 -> 0 bytes .../layim/layim-assets/images/face/0.gif | Bin 2689 -> 0 bytes .../layim/layim-assets/images/face/1.gif | Bin 5514 -> 0 bytes .../layim/layim-assets/images/face/10.gif | Bin 2797 -> 0 bytes .../layim/layim-assets/images/face/11.gif | Bin 4121 -> 0 bytes .../layim/layim-assets/images/face/12.gif | Bin 3361 -> 0 bytes .../layim/layim-assets/images/face/13.gif | Bin 7425 -> 0 bytes .../layim/layim-assets/images/face/14.gif | Bin 2375 -> 0 bytes .../layim/layim-assets/images/face/15.gif | Bin 1793 -> 0 bytes .../layim/layim-assets/images/face/16.gif | Bin 6721 -> 0 bytes .../layim/layim-assets/images/face/17.gif | Bin 4439 -> 0 bytes .../layim/layim-assets/images/face/18.gif | Bin 3017 -> 0 bytes .../layim/layim-assets/images/face/19.gif | Bin 3040 -> 0 bytes .../layim/layim-assets/images/face/2.gif | Bin 3222 -> 0 bytes .../layim/layim-assets/images/face/20.gif | Bin 5144 -> 0 bytes .../layim/layim-assets/images/face/21.gif | Bin 5191 -> 0 bytes .../layim/layim-assets/images/face/22.gif | Bin 9823 -> 0 bytes .../layim/layim-assets/images/face/23.gif | Bin 3792 -> 0 bytes .../layim/layim-assets/images/face/24.gif | Bin 8096 -> 0 bytes .../layim/layim-assets/images/face/25.gif | Bin 3127 -> 0 bytes .../layim/layim-assets/images/face/26.gif | Bin 3291 -> 0 bytes .../layim/layim-assets/images/face/27.gif | Bin 4377 -> 0 bytes .../layim/layim-assets/images/face/28.gif | Bin 2793 -> 0 bytes .../layim/layim-assets/images/face/29.gif | Bin 4854 -> 0 bytes .../layim/layim-assets/images/face/3.gif | Bin 4017 -> 0 bytes .../layim/layim-assets/images/face/30.gif | Bin 2555 -> 0 bytes .../layim/layim-assets/images/face/31.gif | Bin 2002 -> 0 bytes .../layim/layim-assets/images/face/32.gif | Bin 3481 -> 0 bytes .../layim/layim-assets/images/face/33.gif | Bin 2454 -> 0 bytes .../layim/layim-assets/images/face/34.gif | Bin 3700 -> 0 bytes .../layim/layim-assets/images/face/35.gif | Bin 1800 -> 0 bytes .../layim/layim-assets/images/face/36.gif | Bin 2331 -> 0 bytes .../layim/layim-assets/images/face/37.gif | Bin 1513 -> 0 bytes .../layim/layim-assets/images/face/38.gif | Bin 3615 -> 0 bytes .../layim/layim-assets/images/face/39.gif | Bin 6495 -> 0 bytes .../layim/layim-assets/images/face/4.gif | Bin 5689 -> 0 bytes .../layim/layim-assets/images/face/40.gif | Bin 3154 -> 0 bytes .../layim/layim-assets/images/face/41.gif | Bin 3644 -> 0 bytes .../layim/layim-assets/images/face/42.gif | Bin 5305 -> 0 bytes .../layim/layim-assets/images/face/43.gif | Bin 2674 -> 0 bytes .../layim/layim-assets/images/face/44.gif | Bin 4126 -> 0 bytes .../layim/layim-assets/images/face/45.gif | Bin 3417 -> 0 bytes .../layim/layim-assets/images/face/46.gif | Bin 3007 -> 0 bytes .../layim/layim-assets/images/face/47.gif | Bin 2333 -> 0 bytes .../layim/layim-assets/images/face/48.gif | Bin 2689 -> 0 bytes .../layim/layim-assets/images/face/49.gif | Bin 2315 -> 0 bytes .../layim/layim-assets/images/face/5.gif | Bin 4567 -> 0 bytes .../layim/layim-assets/images/face/50.gif | Bin 5866 -> 0 bytes .../layim/layim-assets/images/face/51.gif | Bin 2785 -> 0 bytes .../layim/layim-assets/images/face/52.gif | Bin 777 -> 0 bytes .../layim/layim-assets/images/face/53.gif | Bin 2127 -> 0 bytes .../layim/layim-assets/images/face/54.gif | Bin 2196 -> 0 bytes .../layim/layim-assets/images/face/55.gif | Bin 1971 -> 0 bytes .../layim/layim-assets/images/face/56.gif | Bin 2034 -> 0 bytes .../layim/layim-assets/images/face/57.gif | Bin 2705 -> 0 bytes .../layim/layim-assets/images/face/58.gif | Bin 2258 -> 0 bytes .../layim/layim-assets/images/face/59.gif | Bin 10311 -> 0 bytes .../layim/layim-assets/images/face/6.gif | Bin 2213 -> 0 bytes .../layim/layim-assets/images/face/60.gif | Bin 3245 -> 0 bytes .../layim/layim-assets/images/face/61.gif | Bin 2495 -> 0 bytes .../layim/layim-assets/images/face/62.gif | Bin 2017 -> 0 bytes .../layim/layim-assets/images/face/63.gif | Bin 5871 -> 0 bytes .../layim/layim-assets/images/face/64.gif | Bin 6448 -> 0 bytes .../layim/layim-assets/images/face/65.gif | Bin 3576 -> 0 bytes .../layim/layim-assets/images/face/66.gif | Bin 3029 -> 0 bytes .../layim/layim-assets/images/face/67.gif | Bin 2701 -> 0 bytes .../layim/layim-assets/images/face/68.gif | Bin 1424 -> 0 bytes .../layim/layim-assets/images/face/69.gif | Bin 2431 -> 0 bytes .../layim/layim-assets/images/face/7.gif | Bin 3398 -> 0 bytes .../layim/layim-assets/images/face/70.gif | Bin 4590 -> 0 bytes .../layim/layim-assets/images/face/71.gif | Bin 5304 -> 0 bytes .../layim/layim-assets/images/face/8.gif | Bin 4050 -> 0 bytes .../layim/layim-assets/images/face/9.gif | Bin 4221 -> 0 bytes .../lib/extend/layim/layim-assets/layim.css | 2 - .../layim/layim-assets/lib/layer-mobile.js | 2 - .../layim-assets/lib/layim-mobile-open.js | 2 - .../layim/layim-assets/lib/layim-mobile.js | 2 - .../extend/layim/layim-assets/lib/zepto.js | 2 - .../lib/extend/layim/layim-assets/mobile.css | 2 - .../lib/extend/layim/layim-assets/skin/1.jpg | Bin 19399 -> 0 bytes .../lib/extend/layim/layim-assets/skin/2.jpg | Bin 11883 -> 0 bytes .../lib/extend/layim/layim-assets/skin/3.jpg | Bin 18610 -> 0 bytes .../lib/extend/layim/layim-assets/skin/4.jpg | Bin 39279 -> 0 bytes .../lib/extend/layim/layim-assets/skin/5.jpg | Bin 45901 -> 0 bytes .../layim/layim-assets/voice/default.mp3 | Bin 9341 -> 0 bytes .../assets/src/lib/extend/layim/layim.js | 3 - .../src/main/webapp/assets/src/lib/view.js | 344 -- .../main/webapp/assets/src/style/admin.css | 522 --- .../main/webapp/assets/src/style/login.css | 51 - .../webapp/assets/src/style/res/bg-none.jpg | Bin 832 -> 0 bytes .../assets/src/style/res/layui-logo.jpg | Bin 2871 -> 0 bytes .../assets/src/style/res/logo-black.png | Bin 455 -> 0 bytes .../main/webapp/assets/src/style/res/logo.png | Bin 457 -> 0 bytes .../src/style/res/template/character.jpg | Bin 6727 -> 0 bytes .../assets/src/style/res/template/huge.jpg | Bin 12627 -> 0 bytes .../src/style/res/template/portrait.png | Bin 6727 -> 0 bytes .../main/webapp/assets/src/style/template.css | 182 - .../assets/src/views/app/content/comment.html | 107 - .../src/views/app/content/contform.html | 20 - .../assets/src/views/app/content/list.html | 151 - .../src/views/app/content/listform.html | 67 - .../assets/src/views/app/content/tags.html | 65 - .../src/views/app/content/tagsform.html | 17 - .../assets/src/views/app/forum/list.html | 124 - .../assets/src/views/app/forum/listform.html | 53 - .../assets/src/views/app/forum/replys.html | 99 - .../src/views/app/forum/replysform.html | 34 - .../assets/src/views/app/message/detail.html | 42 - .../assets/src/views/app/message/index.html | 176 - .../assets/src/views/app/workorder/list.html | 89 - .../src/views/app/workorder/listform.html | 59 - .../views/app/\350\257\264\346\230\216.txt" | 2 - .../src/views/component/anim/index.html | 108 - .../src/views/component/auxiliar/index.html | 103 - .../src/views/component/badge/index.html | 103 - .../src/views/component/button/index.html | 178 - .../src/views/component/carousel/index.html | 219 - .../src/views/component/code/index.html | 141 - .../views/component/colorpicker/index.html | 190 - .../src/views/component/dropdown/index.html | 571 --- .../src/views/component/flow/index.html | 124 - .../src/views/component/form/element.html | 237 - .../src/views/component/form/group.html | 291 -- .../assets/src/views/component/grid/all.html | 80 - .../assets/src/views/component/grid/list.html | 122 - .../src/views/component/grid/mobile-pc.html | 80 - .../src/views/component/grid/mobile.html | 112 - .../src/views/component/grid/speed-dial.html | 84 - .../src/views/component/grid/stack.html | 143 - .../src/views/component/laydate/demo1.html | 324 -- .../src/views/component/laydate/demo2.html | 276 -- .../views/component/laydate/special-demo.html | 74 - .../src/views/component/laydate/theme.html | 173 - .../src/views/component/layer/list.html | 491 --- .../views/component/layer/special-demo.html | 174 - .../src/views/component/layer/theme.html | 82 - .../src/views/component/laypage/demo1.html | 158 - .../src/views/component/laypage/demo2.html | 159 - .../src/views/component/laytpl/index.html | 34 - .../assets/src/views/component/nav/index.html | 206 - .../src/views/component/panel/index.html | 181 - .../src/views/component/progress/index.html | 159 - .../src/views/component/rate/index.html | 177 - .../src/views/component/slider/index.html | 216 - .../src/views/component/table/auto.html | 49 - .../src/views/component/table/cellEdit.html | 56 - .../src/views/component/table/cellEvent.html | 67 - .../src/views/component/table/checkbox.html | 50 - .../src/views/component/table/data.html | 141 - .../src/views/component/table/fixed.html | 53 - .../src/views/component/table/form.html | 82 - .../src/views/component/table/height.html | 51 - .../src/views/component/table/initSort.html | 48 - .../src/views/component/table/onrow.html | 67 - .../src/views/component/table/operate.html | 107 - .../src/views/component/table/page.html | 57 - .../src/views/component/table/parseData.html | 65 - .../src/views/component/table/radio.html | 70 - .../src/views/component/table/reload.html | 87 - .../src/views/component/table/resetPage.html | 58 - .../src/views/component/table/simple.html | 48 - .../src/views/component/table/static.html | 309 -- .../src/views/component/table/style.html | 63 - .../src/views/component/table/thead.html | 96 - .../src/views/component/table/toolbar.html | 109 - .../src/views/component/table/tostatic.html | 75 - .../src/views/component/table/totalRow.html | 78 - .../src/views/component/tabs/index.html | 188 - .../src/views/component/timeline/index.html | 121 - .../src/views/component/transfer/index.html | 185 - .../src/views/component/tree/index.html | 432 -- .../src/views/component/upload/demo1.html | 199 - .../src/views/component/upload/demo2.html | 187 - .../src/views/component/util/index.html | 90 - .../component/\350\257\264\346\230\216.txt" | 2 - .../assets/src/views/home/homepage1.html | 194 - .../assets/src/views/home/homepage2.html | 306 -- .../assets/src/views/iframe/layer/iframe.html | 83 - .../assets/src/views/iframe/link/baidu.html | 3 - .../iframe/\350\257\264\346\230\216.txt" | 3 - .../main/webapp/assets/src/views/index.html | 391 -- .../main/webapp/assets/src/views/layout.html | 200 - .../assets/src/views/senior/echarts/bar.html | 108 - .../assets/src/views/senior/echarts/line.html | 102 - .../assets/src/views/senior/echarts/map.html | 34 - .../assets/src/views/senior/im/index.html | 427 -- .../senior/\350\257\264\346\230\216.txt" | 2 - .../assets/src/views/set/system/email.html | 69 - .../assets/src/views/set/system/website.html | 95 - .../assets/src/views/set/user/info.html | 98 - .../assets/src/views/set/user/password.html | 53 - .../views/set/\350\257\264\346\230\216.txt" | 2 - .../webapp/assets/src/views/system/about.html | 17 - .../webapp/assets/src/views/system/more.html | 22 - .../webapp/assets/src/views/system/theme.html | 43 - .../system/\350\257\264\346\230\216.txt" | 3 - .../main/webapp/assets/src/views/temp.html | 51 - .../src/views/template/addresslist.html | 370 -- .../assets/src/views/template/caller.html | 195 - .../assets/src/views/template/goodslist.html | 410 -- .../assets/src/views/template/msgboard.html | 97 - .../src/views/template/personalpage.html | 425 -- .../assets/src/views/template/search.html | 97 - .../assets/src/views/template/tips/404.html | 15 - .../assets/src/views/template/tips/error.html | 13 - .../assets/src/views/template/tips/test.html | 13 - .../src/views/template/user/forget.html | 30 - .../assets/src/views/template/user/login.html | 69 - .../assets/src/views/template/user/reg.html | 30 - .../template/\350\257\264\346\230\216.txt" | 2 - .../views/user/administrators/adminform.html | 66 - .../src/views/user/administrators/list.html | 161 - .../src/views/user/administrators/role.html | 127 - .../views/user/administrators/roleform.html | 59 - .../webapp/assets/src/views/user/forget.html | 138 - .../webapp/assets/src/views/user/login.html | 121 - .../webapp/assets/src/views/user/reg.html | 120 - .../assets/src/views/user/user/list.html | 150 - .../assets/src/views/user/user/userform.html | 72 - .../views/user/\350\257\264\346\230\216.txt" | 2 - .../src/main/webapp/assets/zeus/index.html | 28 - .../assets/zeus/json/console/prograss.js | 36 - .../assets/zeus/json/console/top-card.js | 76 - .../assets/zeus/json/console/top-search.js | 46 - .../assets/zeus/json/content/comment.js | 56 - .../webapp/assets/zeus/json/content/list.js | 62 - .../webapp/assets/zeus/json/content/tags.js | 21 - .../webapp/assets/zeus/json/forum/list.js | 62 - .../webapp/assets/zeus/json/forum/replys.js | 69 - .../webapp/assets/zeus/json/layer/photos.js | 39 - .../webapp/assets/zeus/json/layim/getList.js | 96 - .../assets/zeus/json/layim/getMembers.js | 22 - .../webapp/assets/zeus/json/mall/order.js | 42 - .../src/main/webapp/assets/zeus/json/menu.js | 400 -- .../webapp/assets/zeus/json/message/all.js | 46 - .../webapp/assets/zeus/json/message/detail.js | 10 - .../webapp/assets/zeus/json/message/direct.js | 46 - .../webapp/assets/zeus/json/message/new.js | 7 - .../webapp/assets/zeus/json/message/notice.js | 46 - .../webapp/assets/zeus/json/table/demo.js | 96 - .../webapp/assets/zeus/json/table/demo2.js | 61 - .../webapp/assets/zeus/json/table/demo3.js | 96 - .../webapp/assets/zeus/json/table/user.js | 2 - .../webapp/assets/zeus/json/table/user30.js | 2 - .../webapp/assets/zeus/json/upload/demo.js | 7 - .../webapp/assets/zeus/json/user/forget.js | 7 - .../webapp/assets/zeus/json/user/login.js | 7 - .../webapp/assets/zeus/json/user/logout.js | 5 - .../main/webapp/assets/zeus/json/user/reg.js | 7 - .../webapp/assets/zeus/json/user/resetpass.js | 7 - .../webapp/assets/zeus/json/user/session.js | 9 - .../main/webapp/assets/zeus/json/user/sms.js | 7 - .../assets/zeus/json/useradmin/mangadmin.js | 78 - .../webapp/assets/zeus/json/useradmin/role.js | 54 - .../assets/zeus/json/useradmin/webuser.js | 143 - .../webapp/assets/zeus/json/workorder/demo.js | 78 - .../zeus/json/\350\257\264\346\230\216.txt" | 3 - .../webapp/assets/zeus/layui/css/layui.css | 1 - .../assets/zeus/layui/css/modules/code.css | 1 - .../css/modules/laydate/default/laydate.css | 1 - .../css/modules/layer/default/icon-ext.png | Bin 5911 -> 0 bytes .../layui/css/modules/layer/default/icon.png | Bin 11493 -> 0 bytes .../layui/css/modules/layer/default/layer.css | 1 - .../css/modules/layer/default/loading-0.gif | Bin 5793 -> 0 bytes .../css/modules/layer/default/loading-1.gif | Bin 701 -> 0 bytes .../css/modules/layer/default/loading-2.gif | Bin 1787 -> 0 bytes .../assets/zeus/layui/font/iconfont.eot | Bin 46684 -> 0 bytes .../assets/zeus/layui/font/iconfont.svg | 554 --- .../assets/zeus/layui/font/iconfont.ttf | Bin 46508 -> 0 bytes .../assets/zeus/layui/font/iconfont.woff | Bin 30628 -> 0 bytes .../assets/zeus/layui/font/iconfont.woff2 | Bin 25964 -> 0 bytes .../main/webapp/assets/zeus/layui/layui.js | 5 - .../src/main/webapp/pages/index.html | 10 - 295 files changed, 27363 deletions(-) delete mode 100644 iot-server/server-starter/src/main/webapp/assets/gulpfile.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/package-lock.json delete mode 100644 iot-server/server-starter/src/main/webapp/assets/package.json delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/config.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/common.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/console.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/contlist.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/forum.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/sample.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/senior.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/set.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/user.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/useradmin.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/controller/workorder.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/index.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/admin.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/echarts.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/echartsTheme.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/chatlog.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/find.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/getmsg.json delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/msgbox.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/default.png delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/0.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/1.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/10.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/11.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/12.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/13.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/14.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/15.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/16.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/17.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/18.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/19.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/2.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/20.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/21.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/22.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/23.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/24.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/25.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/26.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/27.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/28.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/29.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/3.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/30.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/31.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/32.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/33.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/34.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/35.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/36.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/37.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/38.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/39.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/4.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/40.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/41.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/42.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/43.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/44.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/45.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/46.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/47.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/48.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/49.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/5.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/50.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/51.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/52.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/53.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/54.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/55.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/56.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/57.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/58.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/59.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/6.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/60.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/61.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/62.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/63.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/64.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/65.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/66.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/67.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/68.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/69.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/7.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/70.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/71.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/8.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/9.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/layim.css delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/layer-mobile.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/layim-mobile-open.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/layim-mobile.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/zepto.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/mobile.css delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/1.jpg delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/2.jpg delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/3.jpg delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/4.jpg delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/5.jpg delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/voice/default.mp3 delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/lib/view.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/admin.css delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/login.css delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/res/bg-none.jpg delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/res/layui-logo.jpg delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/res/logo-black.png delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/res/logo.png delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/res/template/character.jpg delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/res/template/huge.jpg delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/res/template/portrait.png delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/style/template.css delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/content/comment.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/content/contform.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/content/list.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/content/listform.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/content/tags.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/content/tagsform.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/list.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/listform.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/replys.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/replysform.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/message/detail.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/message/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/workorder/list.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/app/workorder/listform.html delete mode 100644 "iot-server/server-starter/src/main/webapp/assets/src/views/app/\350\257\264\346\230\216.txt" delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/anim/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/auxiliar/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/badge/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/button/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/carousel/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/code/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/colorpicker/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/dropdown/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/flow/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/form/element.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/form/group.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/all.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/list.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/mobile-pc.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/mobile.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/speed-dial.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/stack.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/demo1.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/demo2.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/special-demo.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/theme.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/list.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/special-demo.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/theme.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/laypage/demo1.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/laypage/demo2.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/laytpl/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/nav/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/panel/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/progress/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/rate/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/slider/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/auto.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/cellEdit.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/cellEvent.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/checkbox.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/data.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/fixed.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/form.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/height.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/initSort.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/onrow.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/operate.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/page.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/parseData.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/radio.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/reload.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/resetPage.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/simple.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/static.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/style.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/thead.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/toolbar.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/tostatic.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/table/totalRow.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/tabs/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/timeline/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/transfer/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/tree/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/upload/demo1.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/upload/demo2.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/component/util/index.html delete mode 100644 "iot-server/server-starter/src/main/webapp/assets/src/views/component/\350\257\264\346\230\216.txt" delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/home/homepage1.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/home/homepage2.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/iframe/layer/iframe.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/iframe/link/baidu.html delete mode 100644 "iot-server/server-starter/src/main/webapp/assets/src/views/iframe/\350\257\264\346\230\216.txt" delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/layout.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/bar.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/line.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/map.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/senior/im/index.html delete mode 100644 "iot-server/server-starter/src/main/webapp/assets/src/views/senior/\350\257\264\346\230\216.txt" delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/set/system/email.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/set/system/website.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/set/user/info.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/set/user/password.html delete mode 100644 "iot-server/server-starter/src/main/webapp/assets/src/views/set/\350\257\264\346\230\216.txt" delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/system/about.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/system/more.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/system/theme.html delete mode 100644 "iot-server/server-starter/src/main/webapp/assets/src/views/system/\350\257\264\346\230\216.txt" delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/temp.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/addresslist.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/caller.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/goodslist.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/msgboard.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/personalpage.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/search.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/404.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/error.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/test.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/user/forget.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/user/login.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/template/user/reg.html delete mode 100644 "iot-server/server-starter/src/main/webapp/assets/src/views/template/\350\257\264\346\230\216.txt" delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/adminform.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/list.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/role.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/roleform.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/user/forget.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/user/login.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/user/reg.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/user/user/list.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/src/views/user/user/userform.html delete mode 100644 "iot-server/server-starter/src/main/webapp/assets/src/views/user/\350\257\264\346\230\216.txt" delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/index.html delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/console/prograss.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/console/top-card.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/console/top-search.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/content/comment.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/content/list.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/content/tags.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/forum/list.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/forum/replys.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/layer/photos.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/layim/getList.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/layim/getMembers.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/mall/order.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/menu.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/message/all.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/message/detail.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/message/direct.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/message/new.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/message/notice.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo2.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo3.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/table/user.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/table/user30.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/upload/demo.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/user/forget.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/user/login.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/user/logout.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/user/reg.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/user/resetpass.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/user/session.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/user/sms.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/mangadmin.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/role.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/webuser.js delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/json/workorder/demo.js delete mode 100644 "iot-server/server-starter/src/main/webapp/assets/zeus/json/\350\257\264\346\230\216.txt" delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/layui.css delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/code.css delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/laydate/default/laydate.css delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/icon-ext.png delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/icon.png delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/layer.css delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/loading-0.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/loading-1.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/loading-2.gif delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.eot delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.svg delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.ttf delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.woff delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.woff2 delete mode 100644 iot-server/server-starter/src/main/webapp/assets/zeus/layui/layui.js delete mode 100644 iot-server/server-starter/src/main/webapp/pages/index.html diff --git a/iot-server/server-starter/src/main/webapp/assets/gulpfile.js b/iot-server/server-starter/src/main/webapp/assets/gulpfile.js deleted file mode 100644 index d5e6354a..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/gulpfile.js +++ /dev/null @@ -1,170 +0,0 @@ - -/*! - layuiAdmin pro 构建 -*/ - -var pkg = require('./package.json'); -var inds = pkg.independents; - -var gulp = require('gulp'); -var uglify = require('gulp-uglify'); -var minify = require('gulp-minify-css'); -var concat = require('gulp-concat'); -var rename = require('gulp-rename'); -var replace = require('gulp-replace'); -var header = require('gulp-header'); -var del = require('del'); -var gulpif = require('gulp-if'); -var minimist = require('minimist'); - -//获取参数 -var argv = require('minimist')(process.argv.slice(2), { - default: { - ver: 'all' - } -}) - -//注释 -,note = [ - // '/** <%= pkg.name %>-v<%= pkg.version %> <%= pkg.license %> License */\n <%= js %>' - ,'' - ,{pkg: pkg, js: ';'} -] - -,destDir = './dist' //构建的目标目录 -,releaseDir = '../pack/layuiAdmin.pack/'+ pkg.name +'-v' + pkg.version //发行版本目录 - -//任务 -,task = { - //压缩 JS - minjs: function(){ - var src = [ - './src/**/*.js' - ,'!./src/config.js' - ,'!./src/lib/extend/**/*.js' - ]; - - return gulp.src(src).pipe(uglify({ - output: { - ascii_only: true //escape Unicode characters in strings and regexps - } - })) - .pipe(header.apply(null, note)) - .pipe(gulp.dest(destDir)); - } - - //压缩 CSS - ,mincss: function(){ - var src = [ - './src/**/*.css' - ] - ,noteNew = JSON.parse(JSON.stringify(note)); - - - noteNew[1].js = ''; - - return gulp.src(src).pipe(minify({ - compatibility: 'ie7' - })).pipe(header.apply(null, noteNew)) - .pipe(gulp.dest(destDir)); - } - - //复制文件夹 - ,mv: function(){ - gulp.src('./src/config.js') - .pipe(gulp.dest(destDir)); - - gulp.src('./src/lib/extend/**/*') - .pipe(gulp.dest(destDir + '/lib/extend')); - - gulp.src('./src/style/res/**/*') - .pipe(gulp.dest(destDir + '/style/res')); - - return gulp.src('./src/views/**/*') - .pipe(gulp.dest(destDir + '/views')); - } -}; - -gulp.task('minjs', task.minjs); -gulp.task('mincss', task.mincss); -gulp.task('mv', task.mv); - -//清理 -gulp.task('clear', function(cb) { - return del(['./dist/*'], cb); -}); - -//构建核心源文件(发行版) -gulp.task('default', ['clear'], function(){ //命令:gulp - for(var key in task){ - task[key](); - } -}); - - - -/** - * 开发模式 - */ - -//清理 src -gulp.task('clearSrc', function(cb) { - return del(['./src/*'], cb); -}); - -//复制 src -gulp.task('src', ['clearSrc'], function(){ - return gulp.src('./dev-src/**/*') - .pipe(gulp.dest('./src')); -}); - -//构建核心源文件(开发版) -gulp.task('dev', ['clear', 'src'], function(){ //命令:gulp dev - for(var key in task){ - task[key](); - } -}); - -//发行文件 -gulp.task('release', function(){ //命令:gulp && gulp release - - //复制核心文件 - gulp.src('./dist/**/*') - .pipe(gulp.dest(releaseDir + '/dist')); - - gulp.src('./src/**/*') - .pipe(gulp.dest(releaseDir + '/src')); - - //复制 json - gulp.src('./dev/json/**/*') - .pipe(gulp.dest('./json')) - .pipe(gulp.dest('./start/json')) - .pipe(gulp.dest(releaseDir + '/start/json')); - - //复制并转义宿主页面 - gulp.src('./dev/index.html') - .pipe(replace(/\<\!-- clear s --\>([\s\S]*?)\<\!-- clear e --\>/, '')) - .pipe(replace('//local.res.layui.com/layui/src', 'layui')) - .pipe(replace("base: '../dev-src/'", "base: '../dist/'")) - .pipe(replace('@@version@@', pkg.version)) - .pipe(gulp.dest('./start')) - .pipe(gulp.dest(releaseDir + '/start')); - - //复制帮助文件 - gulp.src([ - './帮助/*' - ]).pipe(gulp.dest(releaseDir)); - - - //复制 gulpfile - gulp.src([ - 'gulpfile.js' - ,'package.json' - ]).pipe(gulp.dest(releaseDir)); - - //复制 layui - return gulp.src('../../../../res/layui/rc/**/*') - .pipe(gulp.dest('./start/layui')) - .pipe(gulp.dest(releaseDir + '/start/layui')) -}); - diff --git a/iot-server/server-starter/src/main/webapp/assets/package-lock.json b/iot-server/server-starter/src/main/webapp/assets/package-lock.json deleted file mode 100644 index f44c04c3..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/package-lock.json +++ /dev/null @@ -1,3808 +0,0 @@ -{ - "name": "layuiAdmin.pro", - "version": "1.7.2", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@dabh/diagnostics": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", - "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", - "dev": true, - "requires": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0" - } - }, - "@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/formatio": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", - "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^3.1.0" - } - }, - "@sinonjs/samsam": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", - "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.3.0", - "array-from": "^2.1.1", - "lodash": "^4.17.15" - }, - "dependencies": { - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - } - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, - "array-from": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", - "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", - "dev": true - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", - "dev": true - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "dev": true - }, - "binaryextensions": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-1.0.1.tgz", - "integrity": "sha1-HmN0iLNbWL2l9HdL+WpSEqjJB1U=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "dev": true - }, - "bufferstreams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.0.1.tgz", - "integrity": "sha1-z7GtlWjTujz+k1upq92VLeiKqyo=", - "dev": true, - "requires": { - "readable-stream": "^1.0.33" - } - }, - "build": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/build/-/build-0.1.4.tgz", - "integrity": "sha1-cH/gJv/O3crL/c3zVur9pk8VEEY=", - "dev": true, - "requires": { - "cssmin": "0.3.x", - "jsmin": "1.x", - "jxLoader": "*", - "moo-server": "*", - "promised-io": "*", - "timespan": "2.x", - "uglify-js": "1.x", - "walker": "1.x", - "winston": "*", - "wrench": "1.3.x" - }, - "dependencies": { - "uglify-js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-1.3.5.tgz", - "integrity": "sha1-S1v/+Rhu/7qoiOTJ6UvZ/EyUkp0=", - "dev": true - } - } - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true - }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - } - }, - "chai": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", - "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "clean-css": { - "version": "3.4.28", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", - "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=", - "dev": true, - "requires": { - "commander": "2.8.x", - "source-map": "0.4.x" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", - "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", - "dev": true, - "requires": { - "color-convert": "^1.9.3", - "color-string": "^1.6.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "color-string": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz", - "integrity": "sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==", - "dev": true, - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true - }, - "colorspace": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", - "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", - "dev": true, - "requires": { - "color": "^3.1.3", - "text-hex": "1.0.x" - } - }, - "commander": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", - "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", - "dev": true, - "requires": { - "graceful-readlink": ">= 1.0.0" - } - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-with-sourcemaps": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", - "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "cssmin": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/cssmin/-/cssmin-0.3.2.tgz", - "integrity": "sha1-3c5MVHtRCuDVlKjx+/iq+OLFwA0=", - "dev": true - }, - "dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", - "dev": true - }, - "deap": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deap/-/deap-1.0.1.tgz", - "integrity": "sha512-k75KYNZMvwAwes2xIPry/QTffXIchjD8QfABvvfTr80P85jv5ZcKqcoDo+vMe71nNnVnXYe8MA28weyqcf/DKw==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "requires": { - "type-detect": "^4.0.0" - } - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "dev": true, - "requires": { - "globby": "^5.0.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "rimraf": "^2.2.8" - } - }, - "deprecated": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", - "dev": true - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "diff": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", - "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", - "dev": true - }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "~1.1.9" - } - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - }, - "dependencies": { - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "enabled": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", - "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", - "dev": true - }, - "end-of-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", - "dev": true, - "requires": { - "once": "~1.3.0" - }, - "dependencies": { - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, - "requires": { - "wrappy": "1" - } - } - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - } - }, - "fecha": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz", - "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==", - "dev": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "find-index": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", - "dev": true - }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - } - }, - "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true - }, - "flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true - }, - "fn.name": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", - "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", - "dev": true - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "fork-stream": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", - "integrity": "sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA=", - "dev": true - }, - "formatio": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", - "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs=", - "dev": true, - "requires": { - "samsam": "1.x" - } - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "gaze": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true, - "requires": { - "globule": "~0.1.0" - } - }, - "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-stream": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", - "dev": true, - "requires": { - "glob": "^4.3.1", - "glob2base": "^0.0.12", - "minimatch": "^2.0.1", - "ordered-read-streams": "^0.1.0", - "through2": "^0.6.1", - "unique-stream": "^1.0.0" - }, - "dependencies": { - "glob": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^2.0.1", - "once": "^1.3.0" - } - }, - "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true, - "requires": { - "brace-expansion": "^1.0.0" - } - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - } - } - }, - "glob-watcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true, - "requires": { - "gaze": "^0.5.1" - } - }, - "glob2base": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true, - "requires": { - "find-index": "^0.1.1" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "globule": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", - "dev": true, - "requires": { - "glob": "~3.1.21", - "lodash": "~1.0.1", - "minimatch": "~0.2.11" - }, - "dependencies": { - "glob": { - "version": "3.1.21", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true, - "requires": { - "graceful-fs": "~1.2.0", - "inherits": "1", - "minimatch": "~0.2.11" - } - }, - "graceful-fs": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", - "dev": true - }, - "inherits": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", - "dev": true - }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" - } - } - } - }, - "glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } - }, - "graceful-fs": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.12.tgz", - "integrity": "sha512-J55gaCS4iTTJfTXIxSVw3EMQckcqkpdRv3IR7gu6sq0+tbC363Zx6KH/SEwXASK9JRbhyZmVjJEVJIOxYsB3Qg==", - "dev": true, - "requires": { - "natives": "^1.1.3" - } - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, - "growl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", - "dev": true - }, - "gulp": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", - "dev": true, - "requires": { - "archy": "^1.0.0", - "chalk": "^1.0.0", - "deprecated": "^0.0.1", - "gulp-util": "^3.0.0", - "interpret": "^1.0.0", - "liftoff": "^2.1.0", - "minimist": "^1.1.0", - "orchestrator": "^0.3.0", - "pretty-hrtime": "^1.0.0", - "semver": "^4.1.0", - "tildify": "^1.0.0", - "v8flags": "^2.0.2", - "vinyl-fs": "^0.3.0" - } - }, - "gulp-concat": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", - "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", - "dev": true, - "requires": { - "concat-with-sourcemaps": "^1.0.0", - "through2": "^2.0.0", - "vinyl": "^2.0.0" - }, - "dependencies": { - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", - "dev": true - }, - "vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", - "dev": true, - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - } - } - } - }, - "gulp-header": { - "version": "1.8.12", - "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", - "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", - "dev": true, - "requires": { - "concat-with-sourcemaps": "*", - "lodash.template": "^4.4.0", - "through2": "^2.0.0" - }, - "dependencies": { - "lodash.template": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", - "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", - "dev": true, - "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.templatesettings": "^4.0.0" - } - }, - "lodash.templatesettings": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", - "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", - "dev": true, - "requires": { - "lodash._reinterpolate": "^3.0.0" - } - } - } - }, - "gulp-if": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz", - "integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=", - "dev": true, - "requires": { - "gulp-match": "^1.0.3", - "ternary-stream": "^2.0.1", - "through2": "^2.0.1" - } - }, - "gulp-match": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.1.0.tgz", - "integrity": "sha512-DlyVxa1Gj24DitY2OjEsS+X6tDpretuxD6wTfhXE/Rw2hweqc1f6D/XtsJmoiCwLWfXgR87W9ozEityPCVzGtQ==", - "dev": true, - "requires": { - "minimatch": "^3.0.3" - } - }, - "gulp-minify-css": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/gulp-minify-css/-/gulp-minify-css-1.2.4.tgz", - "integrity": "sha1-thZJV2Auon+eWtiCJ2ld0gV3jAY=", - "dev": true, - "requires": { - "clean-css": "^3.3.3", - "gulp-util": "^3.0.5", - "object-assign": "^4.0.1", - "readable-stream": "^2.0.0", - "vinyl-bufferstream": "^1.0.1", - "vinyl-sourcemaps-apply": "^0.2.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "gulp-rename": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.4.0.tgz", - "integrity": "sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg==", - "dev": true - }, - "gulp-replace": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-0.6.1.tgz", - "integrity": "sha1-Eb+Mj85TPjPi9qjy9DC5VboL4GY=", - "dev": true, - "requires": { - "istextorbinary": "1.0.2", - "readable-stream": "^2.0.1", - "replacestream": "^4.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "gulp-uglify": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-1.5.4.tgz", - "integrity": "sha1-UkeI2HZm0J+dDCH7IXf5ADmmWMk=", - "dev": true, - "requires": { - "deap": "^1.0.0", - "fancy-log": "^1.0.0", - "gulp-util": "^3.0.0", - "isobject": "^2.0.0", - "through2": "^2.0.0", - "uglify-js": "2.6.4", - "uglify-save-license": "^0.4.1", - "vinyl-sourcemaps-apply": "^0.2.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "dev": true, - "requires": { - "array-differ": "^1.0.0", - "array-uniq": "^1.0.2", - "beeper": "^1.0.0", - "chalk": "^1.0.0", - "dateformat": "^2.0.0", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.0.0", - "minimist": "^1.1.0", - "multipipe": "^0.1.2", - "object-assign": "^3.0.0", - "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" - }, - "dependencies": { - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "^1.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true - }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "dev": true - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-core-module": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", - "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true - }, - "is-path-in-cwd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", - "dev": true, - "requires": { - "is-path-inside": "^1.0.0" - } - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, - "requires": { - "path-is-inside": "^1.0.1" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "requires": { - "is-unc-path": "^1.0.0" - } - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "requires": { - "unc-path-regex": "^0.1.2" - } - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "istextorbinary": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-1.0.2.tgz", - "integrity": "sha1-rOGTVNGpoBc+/rEITOD4ewrX3s8=", - "dev": true, - "requires": { - "binaryextensions": "~1.0.0", - "textextensions": "~1.0.0" - } - }, - "js-yaml": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-0.3.7.tgz", - "integrity": "sha1-1znY7oZGHlSzVNan19HyrZoWf2I=", - "dev": true - }, - "jsmin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/jsmin/-/jsmin-1.0.1.tgz", - "integrity": "sha1-570NzWSWw79IYyNb9GGj2YqjuYw=", - "dev": true - }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true - }, - "just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true - }, - "jxLoader": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jxLoader/-/jxLoader-0.1.1.tgz", - "integrity": "sha1-ATTqUUTlM7WU/B/yX/GU4jXFPs0=", - "dev": true, - "requires": { - "js-yaml": "0.3.x", - "moo-server": "1.3.x", - "promised-io": "*", - "walker": "1.x" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "kuler": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", - "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", - "dev": true - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - }, - "liftoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "findup-sync": "^2.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - } - }, - "lodash": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", - "dev": true - }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "^3.0.0", - "lodash.keys": "^3.0.0" - } - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basecreate": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", - "dev": true - }, - "lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", - "dev": true - }, - "lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", - "dev": true - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "lodash._reescape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", - "dev": true - }, - "lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", - "dev": true - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, - "lodash.create": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", - "dev": true, - "requires": { - "lodash._baseassign": "^3.0.0", - "lodash._basecreate": "^3.0.0", - "lodash._isiterateecall": "^3.0.0" - } - }, - "lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true, - "requires": { - "lodash._root": "^3.0.0" - } - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } - }, - "lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", - "dev": true - }, - "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true, - "requires": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" - } - }, - "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true, - "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" - } - }, - "logform": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.3.0.tgz", - "integrity": "sha512-graeoWUH2knKbGthMtuG1EfaSPMZFZBIrhuJHhkS5ZseFBrc7DupCzihOQAzsK/qIKPQaPJ/lFQFctILUY5ARQ==", - "dev": true, - "requires": { - "colors": "^1.2.1", - "fecha": "^4.2.0", - "ms": "^2.1.1", - "safe-stable-stringify": "^1.1.0", - "triple-beam": "^1.3.0" - }, - "dependencies": { - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - } - } - }, - "lolex": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", - "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", - "dev": true - }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "requires": { - "tmpl": "1.0.5" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "mocha": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", - "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.9.0", - "debug": "2.6.8", - "diff": "3.2.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.1", - "growl": "1.9.2", - "he": "1.1.1", - "json3": "3.3.2", - "lodash.create": "3.1.1", - "mkdirp": "0.5.1", - "supports-color": "3.1.2" - }, - "dependencies": { - "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "requires": { - "graceful-readlink": ">= 1.0.0" - } - }, - "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.2", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "moo-server": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/moo-server/-/moo-server-1.3.0.tgz", - "integrity": "sha1-XceVaVZaENbv7VQ5SR5p0jkuWPE=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "dev": true, - "requires": { - "duplexer2": "0.0.2" - } - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "native-promise-only": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", - "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=", - "dev": true - }, - "natives": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.6.tgz", - "integrity": "sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==", - "dev": true - }, - "nise": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.3.tgz", - "integrity": "sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ==", - "dev": true, - "requires": { - "@sinonjs/formatio": "^3.2.1", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "lolex": "^5.0.1", - "path-to-regexp": "^1.7.0" - }, - "dependencies": { - "lolex": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", - "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - } - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "one-time": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", - "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", - "dev": true, - "requires": { - "fn.name": "1.x.x" - } - }, - "orchestrator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", - "dev": true, - "requires": { - "end-of-stream": "~0.1.5", - "sequencify": "~0.0.7", - "stream-consume": "~0.1.0" - } - }, - "ordered-read-streams": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } - }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "^0.1.0" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "requires": { - "isarray": "0.0.1" - } - }, - "pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "promised-io": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/promised-io/-/promised-io-0.3.6.tgz", - "integrity": "sha512-bNwZusuNIW4m0SPR8jooSyndD35ggirHlxVl/UhIaZD/F0OBv9ebfc6tNmbpZts3QXHggkjIBH8lvtnzhtcz0A==", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "replacestream": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.3.tgz", - "integrity": "sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.3", - "object-assign": "^4.0.1", - "readable-stream": "^2.0.2" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "requires": { - "align-text": "^0.1.1" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "safe-stable-stringify": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz", - "integrity": "sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==", - "dev": true - }, - "samsam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", - "dev": true - }, - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true - }, - "sequencify": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, - "simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "dev": true, - "requires": { - "is-arrayish": "^0.3.1" - } - }, - "sinon": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-3.3.0.tgz", - "integrity": "sha512-/flfGfIxIRXSvZBHJzIf3iAyGYkmMQq6SQjA0cx9SOuVuq+4ZPPO4LJtH1Ce0Lznax1KSG1U6Dad85wIcSW19w==", - "dev": true, - "requires": { - "build": "^0.1.4", - "diff": "^3.1.0", - "formatio": "1.2.0", - "lodash.get": "^4.4.2", - "lolex": "^2.1.2", - "native-promise-only": "^0.8.1", - "nise": "^1.0.1", - "path-to-regexp": "^1.7.0", - "samsam": "^1.1.3", - "text-encoding": "0.6.4", - "type-detect": "^4.0.0" - } - }, - "sinon-chai": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-2.14.0.tgz", - "integrity": "sha512-9stIF1utB0ywNHNT7RgiXbdmen8QDCRsrTjw+G9TgKt1Yexjiv8TOWZ6WHsTPz57Yky3DIswZvEqX8fpuHNDtQ==", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "dev": true - }, - "sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "stream-consume": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", - "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", - "dev": true - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "dev": true, - "requires": { - "first-chunk-stream": "^1.0.0", - "is-utf8": "^0.2.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "ternary-stream": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.1.1.tgz", - "integrity": "sha512-j6ei9hxSoyGlqTmoMjOm+QNvUKDOIY6bNl4Uh1lhBvl6yjPW2iLqxDUYyfDPZknQ4KdRziFl+ec99iT4l7g0cw==", - "dev": true, - "requires": { - "duplexify": "^3.5.0", - "fork-stream": "^0.0.4", - "merge-stream": "^1.0.0", - "through2": "^2.0.1" - } - }, - "text-encoding": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", - "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", - "dev": true - }, - "text-hex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", - "dev": true - }, - "textextensions": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-1.0.2.tgz", - "integrity": "sha1-ZUhjk+4fK7A5pgy7oFsLaL2VAdI=", - "dev": true - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "tildify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "timespan": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz", - "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", - "dev": true - }, - "tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "triple-beam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", - "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==", - "dev": true - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "uglify-js": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.4.tgz", - "integrity": "sha1-ZeovswWck5RpLxX+2HwrNsFrmt8=", - "dev": true, - "requires": { - "async": "~0.2.6", - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - } - }, - "uglify-save-license": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/uglify-save-license/-/uglify-save-license-0.4.1.tgz", - "integrity": "sha1-lXJsF8xv0XHDYX479NjYKqjEzOE=", - "dev": true - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unique-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", - "dev": true - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true, - "requires": { - "user-home": "^1.1.1" - } - }, - "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - }, - "vinyl-bufferstream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vinyl-bufferstream/-/vinyl-bufferstream-1.0.1.tgz", - "integrity": "sha1-BTeGn1gO/6TKRay0dXnkuf5jCBo=", - "dev": true, - "requires": { - "bufferstreams": "1.0.1" - } - }, - "vinyl-fs": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", - "dev": true, - "requires": { - "defaults": "^1.0.0", - "glob-stream": "^3.1.5", - "glob-watcher": "^0.0.6", - "graceful-fs": "^3.0.0", - "mkdirp": "^0.5.0", - "strip-bom": "^1.0.0", - "through2": "^0.6.1", - "vinyl": "^0.4.0" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" - } - } - } - }, - "vinyl-sourcemaps-apply": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", - "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true, - "requires": { - "source-map": "^0.5.1" - } - }, - "walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "requires": { - "makeerror": "1.0.12" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true - }, - "winston": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", - "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", - "dev": true, - "requires": { - "@dabh/diagnostics": "^2.0.2", - "async": "^3.1.0", - "is-stream": "^2.0.0", - "logform": "^2.2.0", - "one-time": "^1.0.0", - "readable-stream": "^3.4.0", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.4.0" - }, - "dependencies": { - "async": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz", - "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==", - "dev": true - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } - } - } - }, - "winston-transport": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", - "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", - "dev": true, - "requires": { - "readable-stream": "^2.3.7", - "triple-beam": "^1.2.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "wrench": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/wrench/-/wrench-1.3.9.tgz", - "integrity": "sha1-bxPsNRRTF+spLKX2UxORskQRFBE=", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - } - } - } -} diff --git a/iot-server/server-starter/src/main/webapp/assets/package.json b/iot-server/server-starter/src/main/webapp/assets/package.json deleted file mode 100644 index cc87238f..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "layuiAdmin.pro", - "version": "1.7.2", - "description": "通用纯静态网页 UI 界面模板", - "license": "LGPL", - "homepage": "", - "devDependencies": { - "chai": "^4.1.1", - "del": "^2.2.2", - "gulp": "^3.9.1", - "gulp-concat": "^2.6.0 ", - "gulp-header": "^1.8.8", - "gulp-if": "^2.0.1", - "gulp-minify-css": "^1.2.4", - "gulp-rename": "^1.2.2", - "gulp-replace": "^0.6.1", - "gulp-uglify": "^1.5.4", - "minimist": "^1.2.0", - "mocha": "^3.2.0", - "sinon": "^3.2.1", - "sinon-chai": "^2.13.0" - } -} diff --git a/iot-server/server-starter/src/main/webapp/assets/src/config.js b/iot-server/server-starter/src/main/webapp/assets/src/config.js deleted file mode 100644 index 1225eea8..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/config.js +++ /dev/null @@ -1,153 +0,0 @@ -/*! - * 全局配置 - */ - -layui.define(['laytpl', 'layer', 'element', 'util'], function (exports) { - exports('setter', { - container: 'LAY_app' //容器ID - , base: layui.cache.base //记录layuiAdmin文件夹所在路径 - , views: layui.cache.base + 'views/' //视图所在目录 - , entry: 'index' //默认视图文件名 - , engine: '.html' //视图文件后缀名 - , pageTabs: false //是否开启页面选项卡功能。单页版不推荐开启 - - , name: 'layuiAdmin' - , tableName: 'layuiAdmin' //本地存储表名 - , MOD_NAME: 'admin' //模块事件名 - - , debug: true //是否开启调试模式。如开启,接口异常时会抛出异常 URL 等信息 - - , interceptor: false //是否开启未登入拦截 - - //自定义请求字段 - , request: { - tokenName: 'access_token' //自动携带 token 的字段名。可设置 false 不携带。 - } - - //自定义响应字段 - , response: { - statusName: 'code' //数据状态的字段名称 - , statusCode: { - ok: 0 //数据状态一切正常的状态码 - , logout: 1001 //登录状态失效的状态码 - } - , msgName: 'msg' //状态信息的字段名称 - , dataName: 'data' //数据详情的字段名称 - } - - //独立页面路由,可随意添加(无需写参数) - , indPage: [ - '/user/login' //登入页 - , '/user/reg' //注册页 - , '/user/forget' //找回密码 - , '/template/tips/test' //独立页的一个测试 demo - ] - - //扩展的模块(相对于 lib/extend 目录) - , extend: { - echarts: 'echarts', //第三方 echarts 核心包 - echartsTheme: 'echartsTheme', //第三方 echarts 主题 - layim: 'layim/layim' //layim - } - - //主题配置 - , theme: { - //内置主题配色方案 - color: [{ - main: '#20222A' //主题色 - , selected: '#009688' //选中色 - , alias: 'default' //默认别名 - }, { - main: '#03152A' - , selected: '#3B91FF' - , alias: 'dark-blue' //藏蓝 - }, { - main: '#2E241B' - , selected: '#A48566' - , alias: 'coffee' //咖啡 - }, { - main: '#50314F' - , selected: '#7A4D7B' - , alias: 'purple-red' //紫红 - }, { - main: '#344058' - , logo: '#1E9FFF' - , selected: '#1E9FFF' - , alias: 'ocean' //海洋 - }, { - main: '#3A3D49' - , logo: '#2F9688' - , selected: '#5FB878' - , alias: 'green' //墨绿 - }, { - main: '#20222A' - , logo: '#F78400' - , selected: '#F78400' - , alias: 'red' //橙色 - }, { - main: '#28333E' - , logo: '#AA3130' - , selected: '#AA3130' - , alias: 'fashion-red' //时尚红 - }, { - main: '#24262F' - , logo: '#3A3D49' - , selected: '#009688' - , alias: 'classic-black' //经典黑 - }, { - logo: '#226A62' - , header: '#2F9688' - , alias: 'green-header' //墨绿头 - }, { - main: '#344058' - , logo: '#0085E8' - , selected: '#1E9FFF' - , header: '#1E9FFF' - , alias: 'ocean-header' //海洋头 - }, { - header: '#393D49' - , alias: 'classic-black-header' //经典黑 - }, { - main: '#50314F' - , logo: '#50314F' - , selected: '#7A4D7B' - , header: '#50314F' - , alias: 'purple-red-header' //紫红头 - }, { - main: '#28333E' - , logo: '#28333E' - , selected: '#AA3130' - , header: '#AA3130' - , alias: 'fashion-red-header' //时尚红头 - }, { - main: '#28333E' - , logo: '#009688' - , selected: '#009688' - , header: '#009688' - , alias: 'green-header' //墨绿头 - }, { - main: '#393D49' - , logo: '#393D49' - , selected: '#009688' - , header: '#23262E' - , alias: 'Classic-style1' //经典风格1 - }, { - main: '#001529' - , logo: '#001529' - , selected: '#1890FF' - , header: '#1890FF' - , alias: 'Classic-style2' //经典风格2 - }, { - main: '#25282A' - , logo: '#25282A' - , selected: '#35BDB2' - , header: '#35BDB2' - , alias: 'Classic-style3' //经典风格3 - }] - - //初始的颜色索引,对应上面的配色方案数组索引 - //如果本地已经有主题色记录,则以本地记录为优先,除非请求本地数据(localStorage) - , initColorIndex: 0 - } - }); -}); diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/common.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/common.js deleted file mode 100644 index 36f8867b..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/controller/common.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - - @Name:layuiAdmin 公共业务 - - - @License:LPPL - - */ - -layui.define(function (exports) { - var $ = layui.$ - , layer = layui.layer - , laytpl = layui.laytpl - , setter = layui.setter - , view = layui.view - , admin = layui.admin - - //公共业务的逻辑处理可以写在此处,切换任何页面都会执行 - //…… - - - //退出 - admin.events.logout = function () { - //执行退出接口 - admin.req({ - url: './json/user/logout.js' - , type: 'get' - , data: {} - , done: function (res) { //这里要说明一下:done 是只有 response 的 code 正常才会执行。而 succese 则是只要 http 为 200 就会执行 - - //清空本地记录的 token,并跳转到登入页 - admin.exit(); - } - }); - }; - - - //对外暴露的接口 - exports('common', {}); -}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/console.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/console.js deleted file mode 100644 index 66dce2c1..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/controller/console.js +++ /dev/null @@ -1,335 +0,0 @@ -/*! - * 主页 - */ - - -layui.define(function (exports) { - - /* - 下面通过 layui.use 分段加载不同的模块,实现不同区域的同时渲染,从而保证视图的快速呈现 - */ - - - //区块轮播切换 - layui.use(['admin', 'carousel'], function () { - var $ = layui.$ - , admin = layui.admin - , carousel = layui.carousel - , element = layui.element - , device = layui.device(); - - //轮播切换 - $('.layadmin-carousel').each(function () { - var othis = $(this); - carousel.render({ - elem: this - , width: '100%' - , arrow: 'none' - , interval: othis.data('interval') - , autoplay: othis.data('autoplay') === true - , trigger: (device.ios || device.android) ? 'click' : 'hover' - , anim: othis.data('anim') - }); - }); - - element.render('progress'); - - }); - - //数据概览 - layui.use(['admin', 'carousel', 'echarts'], function () { - var $ = layui.$ - , admin = layui.admin - , carousel = layui.carousel - , echarts = layui.echarts; - - var echartsApp = [], options = [ - //今日流量趋势 - { - title: { - text: '今日流量趋势', - x: 'center', - textStyle: { - fontSize: 14 - } - }, - tooltip: { - trigger: 'axis' - }, - legend: { - data: ['', ''] - }, - xAxis: [{ - type: 'category', - boundaryGap: false, - data: ['06:00', '06:30', '07:00', '07:30', '08:00', '08:30', '09:00', '09:30', '10:00', '11:30', '12:00', '12:30', '13:00', '13:30', '14:00', '14:30', '15:00', '15:30', '16:00', '16:30', '17:00', '17:30', '18:00', '18:30', '19:00', '19:30', '20:00', '20:30', '21:00', '21:30', '22:00', '22:30', '23:00', '23:30'] - }], - yAxis: [{ - type: 'value' - }], - series: [{ - name: 'PV', - type: 'line', - smooth: true, - itemStyle: {normal: {areaStyle: {type: 'default'}}}, - data: [111, 222, 333, 444, 555, 666, 3333, 33333, 55555, 66666, 33333, 3333, 6666, 11888, 26666, 38888, 56666, 42222, 39999, 28888, 17777, 9666, 6555, 5555, 3333, 2222, 3111, 6999, 5888, 2777, 1666, 999, 888, 777] - }, { - name: 'UV', - type: 'line', - smooth: true, - itemStyle: {normal: {areaStyle: {type: 'default'}}}, - data: [11, 22, 33, 44, 55, 66, 333, 3333, 5555, 12666, 3333, 333, 666, 1188, 2666, 3888, 6666, 4222, 3999, 2888, 1777, 966, 655, 555, 333, 222, 311, 699, 588, 277, 166, 99, 88, 77] - }] - }, - - /* - //访客浏览器分布 - { - title : { - text: '访客浏览器分布', - x: 'center', - textStyle: { - fontSize: 14 - } - }, - tooltip : { - trigger: 'item', - formatter: "{a}
                          {b} : {c} ({d}%)" - }, - legend: { - orient : 'vertical', - x : 'left', - data:['Chrome','Firefox','IE 8.0','Safari','其它浏览器'] - }, - series : [{ - name:'访问来源', - type:'pie', - radius : '55%', - center: ['50%', '50%'], - data:[ - {value:9052, name:'Chrome'}, - {value:1610, name:'Firefox'}, - {value:3200, name:'IE 8.0'}, - {value:535, name:'Safari'}, - {value:1700, name:'其它浏览器'} - ] - }] - }, - */ - - //新增的用户量 - { - title: { - text: '最近一周新增的用户量', - x: 'center', - textStyle: { - fontSize: 14 - } - }, - tooltip: { //提示框 - trigger: 'axis', - formatter: "{b}
                          新增用户:{c}" - }, - xAxis: [{ //X轴 - type: 'category', - data: ['11-07', '11-08', '11-09', '11-10', '11-11', '11-12', '11-13'] - }], - yAxis: [{ //Y轴 - type: 'value' - }], - series: [{ //内容 - type: 'line', - data: [200, 300, 400, 610, 150, 270, 380], - }] - } - ] - , elemDataView = $('#LAY-index-dataview').children('div') - , renderDataView = function (index) { - echartsApp[index] = echarts.init(elemDataView[index], layui.echartsTheme); - echartsApp[index].setOption(options[index]); - //window.onresize = echartsApp[index].resize; - admin.resize(function () { - echartsApp[index].resize(); - }); - }; - - - //没找到DOM,终止执行 - if (!elemDataView[0]) return; - - - renderDataView(0); - - //触发数据概览轮播 - var carouselIndex = 0; - carousel.on('change(LAY-index-dataview)', function (obj) { - renderDataView(carouselIndex = obj.index); - }); - - //触发侧边伸缩 - layui.admin.on('side', function () { - setTimeout(function () { - renderDataView(carouselIndex); - }, 300); - }); - - //触发路由 - layui.admin.on('hash(tab)', function () { - layui.router().path.join('') || renderDataView(carouselIndex); - }); - }); - - //地图 - layui.use(['carousel', 'echarts'], function () { - var $ = layui.$ - , carousel = layui.carousel - , echarts = layui.echarts; - - var echartsApp = [], options = [ - { - title: { - text: '访客地区分布', - subtext: '不完全统计' - }, - tooltip: { - trigger: 'item' - }, - dataRange: { - orient: 'horizontal', - min: 0, - max: 60000, - text: ['高', '低'], - splitNumber: 0 - }, - series: [ - { - name: '访客地区分布', - type: 'map', - mapType: 'china', - selectedMode: 'multiple', - itemStyle: { - normal: {label: {show: true}}, - emphasis: {label: {show: true}} - }, - data: [ - {name: '西藏', value: 60}, - {name: '青海', value: 167}, - {name: '宁夏', value: 210}, - {name: '海南', value: 252}, - {name: '甘肃', value: 502}, - {name: '贵州', value: 570}, - {name: '新疆', value: 661}, - {name: '云南', value: 8890}, - {name: '重庆', value: 10010}, - {name: '吉林', value: 5056}, - {name: '山西', value: 2123}, - {name: '天津', value: 9130}, - {name: '江西', value: 10170}, - {name: '广西', value: 6172}, - {name: '陕西', value: 9251}, - {name: '黑龙江', value: 5125}, - {name: '内蒙古', value: 1435}, - {name: '安徽', value: 9530}, - {name: '北京', value: 51919}, - {name: '福建', value: 3756}, - {name: '上海', value: 59190}, - {name: '湖北', value: 37109}, - {name: '湖南', value: 8966}, - {name: '四川', value: 31020}, - {name: '辽宁', value: 7222}, - {name: '河北', value: 3451}, - {name: '河南', value: 9693}, - {name: '浙江', value: 62310}, - {name: '山东', value: 39231}, - {name: '江苏', value: 35911}, - {name: '广东', value: 55891} - ] - } - ] - } - ] - , elemDataView = $('#LAY-index-pagethree-home').children('div') - , renderDataView = function (index) { - echartsApp[index] = echarts.init(elemDataView[index], layui.echartsTheme); - echartsApp[index].setOption(options[index]); - window.onresize = echartsApp[index].resize; - }; - //没找到DOM,终止执行 - if (!elemDataView[0]) return; - - renderDataView(0); - }); - - - //table - layui.use('table', function () { - var $ = layui.$ - , table = layui.table; - - //今日热搜 - table.render({ - elem: '#LAY-index-topSearch' - , url: './json/console/top-search.js' //模拟接口 - , page: true - , cols: [[ - {type: 'numbers', fixed: 'left'} - , { - field: 'keywords', - title: '关键词', - minWidth: 300, - templet: '

                          ' - } - , {field: 'frequency', title: '搜索次数', minWidth: 120, sort: true} - , {field: 'userNums', title: '用户数', sort: true} - ]] - , skin: 'line' - }); - - //今日热贴 - table.render({ - elem: '#LAY-index-topCard' - , url: './json/console/top-card.js' //模拟接口 - , page: true - , cellMinWidth: 120 - , cols: [[ - {type: 'numbers', fixed: 'left'} - , { - field: 'title', - title: '标题', - minWidth: 300, - templet: '' - } - , {field: 'username', title: '发帖者'} - , {field: 'channel', title: '类别'} - , {field: 'crt', title: '点击率', sort: true} - ]] - , skin: 'line' - }); - - //项目进展 - table.render({ - elem: '#LAY-home-homepage-console' - , url: './json/console/prograss.js' //模拟接口 - , cols: [[ - {type: 'checkbox', fixed: 'left'} - , {field: 'prograss', title: '任务'} - , {field: 'time', title: '所需时间'} - , { - field: 'complete', title: '完成情况' - , templet: function (d) { - if (d.complete == '已完成') { - return '' + d.complete + '' - } else if (d.complete == '进行中') { - return '' + d.complete + '' - } else { - return '' + d.complete + '' - } - } - } - ]] - , skin: 'line' - }); - }); - - exports('console', {}) -}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/contlist.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/contlist.js deleted file mode 100644 index 7dfd42d5..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/controller/contlist.js +++ /dev/null @@ -1,166 +0,0 @@ -/** - - @Name:layuiAdmin 内容系统 - @Author:star1029 - - @License:LPPL - - */ - - -layui.define(['table', 'form'], function (exports) { - var $ = layui.$ - , admin = layui.admin - , view = layui.view - , table = layui.table - , form = layui.form; - - //文章管理 - table.render({ - elem: '#LAY-app-content-list' - , url: './json/content/list.js' //模拟接口 - , cols: [[ - {type: 'checkbox', fixed: 'left'} - , {field: 'id', width: 100, title: '文章ID', sort: true} - , {field: 'label', title: '文章标签', minWidth: 100} - , {field: 'title', title: '文章标题'} - , {field: 'author', title: '作者'} - , {field: 'uploadtime', title: '上传时间', sort: true} - , {field: 'status', title: '发布状态', templet: '#buttonTpl', minWidth: 80, align: 'center'} - , {title: '操作', minWidth: 150, align: 'center', fixed: 'right', toolbar: '#table-content-list'} - ]] - , page: true - , limit: 10 - , limits: [10, 15, 20, 25, 30] - , text: '对不起,加载出现异常!' - }); - - //工具条 - table.on('tool(LAY-app-content-list)', function (obj) { - var data = obj.data; - if (obj.event === 'del') { - layer.confirm('确定删除此文章?', function (index) { - obj.del(); - layer.close(index); - }); - } else if (obj.event === 'edit') { - admin.popup({ - title: '编辑文章' - , area: ['550px', '550px'] - , id: 'LAY-popup-content-edit' - , success: function (layero, index) { - view(this.id).render('app/content/listform', data).done(function () { - form.render(null, 'layuiadmin-app-form-list'); - - //提交 - form.on('submit(layuiadmin-app-form-submit)', function (data) { - var field = data.field; //获取提交的字段 - - //提交 Ajax 成功后,关闭当前弹层并重载表格 - //$.ajax({}); - layui.table.reload('LAY-app-content-list'); //重载表格 - layer.close(index); //执行关闭 - }); - }); - } - }); - } - }); - - //分类管理 - table.render({ - elem: '#LAY-app-content-tags' - , url: './json/content/tags.js' //模拟接口 - , cols: [[ - {type: 'numbers', fixed: 'left'} - , {field: 'id', width: 100, title: 'ID', sort: true} - , {field: 'tags', title: '分类名', minWidth: 100} - , {title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#layuiadmin-app-cont-tagsbar'} - ]] - , text: '对不起,加载出现异常!' - }); - - //工具条 - table.on('tool(LAY-app-content-tags)', function (obj) { - var data = obj.data; - if (obj.event === 'del') { - layer.confirm('确定删除此分类?', function (index) { - obj.del(); - layer.close(index); - }); - } else if (obj.event === 'edit') { - admin.popup({ - title: '编辑分类' - , area: ['450px', '200px'] - , id: 'LAY-popup-content-tags' - , success: function (layero, index) { - view(this.id).render('app/content/tagsform', data).done(function () { - form.render(null, 'layuiadmin-form-tags'); - - //提交 - form.on('submit(layuiadmin-app-tags-submit)', function (data) { - var field = data.field; //获取提交的字段 - - //提交 Ajax 成功后,关闭当前弹层并重载表格 - //$.ajax({}); - layui.table.reload('LAY-app-content-tags'); //重载表格 - layer.close(index); //执行关闭 - }); - }); - } - }); - } - }); - - //评论管理 - table.render({ - elem: '#LAY-app-content-comm' - , url: './json/content/comment.js' //模拟接口 - , cols: [[ - {type: 'checkbox', fixed: 'left'} - , {field: 'id', width: 100, title: 'ID', sort: true} - , {field: 'reviewers', title: '评论者', minWidth: 100} - , {field: 'content', title: '评论内容', minWidth: 100} - , {field: 'commtime', title: '评论时间', minWidth: 100, sort: true} - , {title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#table-content-com'} - ]] - , page: true - , limit: 10 - , limits: [10, 15, 20, 25, 30] - , text: '对不起,加载出现异常!' - }); - - //工具条 - table.on('tool(LAY-app-content-comm)', function (obj) { - var data = obj.data; - if (obj.event === 'del') { - layer.confirm('确定删除此条评论?', function (index) { - obj.del(); - layer.close(index); - }); - } else if (obj.event === 'edit') { - admin.popup({ - title: '编辑评论' - , area: ['450px', '300px'] - , id: 'LAY-popup-content-comm' - , success: function (layero, index) { - view(this.id).render('app/content/contform', data).done(function () { - form.render(null, 'layuiadmin-form-comment'); - - //提交 - form.on('submit(layuiadmin-app-com-submit)', function (data) { - var field = data.field; //获取提交的字段 - - //提交 Ajax 成功后,关闭当前弹层并重载表格 - //$.ajax({}); - layui.table.reload('LAY-app-content-comm'); //重载表格 - layer.close(index); //执行关闭 - }); - }); - } - }); - } - }); - - exports('contlist', {}) -}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/forum.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/forum.js deleted file mode 100644 index a6913277..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/controller/forum.js +++ /dev/null @@ -1,125 +0,0 @@ -/** - - @Name:layuiAdmin 社区系统 - @Author:star1029 - - @License:LPPL - - */ - - -layui.define(['table', 'form'], function (exports) { - var $ = layui.$ - , admin = layui.admin - , view = layui.view - , table = layui.table - , form = layui.form; - - //帖子管理 - table.render({ - elem: '#LAY-app-forum-list' - , url: './json/forum/list.js' //模拟接口 - , cols: [[ - {type: 'checkbox', fixed: 'left'} - , {field: 'id', width: 100, title: 'ID', sort: true} - , {field: 'poster', title: '发帖人'} - , {field: 'avatar', title: '头像', width: 100, templet: '#imgTpl'} - , {field: 'content', title: '发帖内容'} - , {field: 'posttime', title: '发帖时间', sort: true} - , {field: 'top', title: '置顶', templet: '#buttonTpl', minWidth: 80, align: 'center'} - , {title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#table-forum-list'} - ]] - , page: true - , limit: 10 - , limits: [10, 15, 20, 25, 30] - , text: '对不起,加载出现异常!' - }); - - //工具条 - table.on('tool(LAY-app-forum-list)', function (obj) { - var data = obj.data; - if (obj.event === 'del') { - layer.confirm('确定删除此条帖子?', function (index) { - obj.del(); - layer.close(index); - }); - } else if (obj.event === 'edit') { - admin.popup({ - title: '编辑帖子' - , area: ['550px', '450px'] - , id: 'LAY-popup-forum-edit' - , resize: false - , success: function (layero, index) { - view(this.id).render('app/forum/listform', data).done(function () { - form.render(null, 'layuiadmin-form-list'); - - //提交 - form.on('submit(layuiadmin-app-forum-submit)', function (data) { - var field = data.field; //获取提交的字段 - - //提交 Ajax 成功后,关闭当前弹层并重载表格 - //$.ajax({}); - layui.table.reload('LAY-app-forum-list'); //重载表格 - layer.close(index); //执行关闭 - }); - }); - } - }); - } - }); - - //回帖管理 - table.render({ - elem: '#LAY-app-forumreply-list' - , url: './json/forum/replys.js' //模拟接口 - , cols: [[ - {type: 'checkbox', fixed: 'left'} - , {field: 'id', width: 100, title: 'ID', sort: true} - , {field: 'replyer', title: '回帖人'} - , {field: 'cardid', title: '回帖ID', sort: true} - , {field: 'avatar', title: '头像', width: 100, templet: '#imgTpl'} - , {field: 'content', title: '回帖内容', width: 200} - , {field: 'replytime', title: '回帖时间', sort: true} - , {title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#table-forum-replys'} - ]] - , page: true - , limit: 10 - , limits: [10, 15, 20, 25, 30] - , text: '对不起,加载出现异常!' - }); - - //工具条 - table.on('tool(LAY-app-forumreply-list)', function (obj) { - var data = obj.data; - if (obj.event === 'del') { - layer.confirm('确定删除此条评论?', function (index) { - obj.del(); - layer.close(index); - }); - } else if (obj.event === 'edit') { - admin.popup({ - title: '编辑回帖' - , area: ['550px', '400px'] - , id: 'LAY-popup-forum-edit' - , resize: false - , success: function (layero, index) { - view(this.id).render('app/forum/replysform', data).done(function () { - form.render(null, 'layuiadmin-app-forum-reply'); - - //提交 - form.on('submit(layuiadmin-app-forumreply-submit)', function (data) { - var field = data.field; //获取提交的字段 - - //提交 Ajax 成功后,关闭当前弹层并重载表格 - //$.ajax({}); - layui.table.reload('LAY-app-forumreply-list'); //重载表格 - layer.close(index); //执行关闭 - }); - }); - } - }); - } - }); - - exports('forum', {}) -}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/sample.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/sample.js deleted file mode 100644 index 1a20eefe..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/controller/sample.js +++ /dev/null @@ -1,299 +0,0 @@ -/** - - @Name:layuiAdmin 主页示例 - @Author:star1029 - - @License:GPL-2 - - */ - - -layui.define(function(exports){ - var admin = layui.admin; - - //区块轮播切换 - layui.use(['admin', 'carousel'], function(){ - var $ = layui.$ - ,admin = layui.admin - ,carousel = layui.carousel - ,element = layui.element - ,device = layui.device(); - - //轮播切换 - $('.layadmin-carousel').each(function(){ - var othis = $(this); - carousel.render({ - elem: this - ,width: '100%' - ,arrow: 'none' - ,interval: othis.data('interval') - ,autoplay: othis.data('autoplay') === true - ,trigger: (device.ios || device.android) ? 'click' : 'hover' - ,anim: othis.data('anim') - }); - }); - - element.render('progress'); - - }); - - //八卦新闻 - layui.use(['carousel', 'echarts'], function(){ - var $ = layui.$ - ,carousel = layui.carousel - ,echarts = layui.echarts; - - var echartsApp = [], options = [ - { - title : { - subtext: '完全实况球员数据', - textStyle: { - fontSize: 14 - } - }, - tooltip : { - trigger: 'axis' - }, - legend: { - x : 'left', - data:['罗纳尔多','舍普琴科'] - }, - polar : [ - { - indicator : [ - {text : '进攻', max : 100}, - {text : '防守', max : 100}, - {text : '体能', max : 100}, - {text : '速度', max : 100}, - {text : '力量', max : 100}, - {text : '技巧', max : 100} - ], - radius : 130 - } - ], - series : [ - { - type: 'radar', - center : ['50%', '50%'], - itemStyle: { - normal: { - areaStyle: { - type: 'default' - } - } - }, - data:[ - {value : [97, 42, 88, 94, 90, 86], name : '舍普琴科'}, - {value : [97, 32, 74, 95, 88, 92], name : '罗纳尔多'} - ] - } - ] - } - ] - ,elemDataView = $('#LAY-index-pageone').children('div') - ,renderDataView = function(index){ - echartsApp[index] = echarts.init(elemDataView[index], layui.echartsTheme); - echartsApp[index].setOption(options[index]); - window.onresize = echartsApp[index].resize; - }; - //没找到DOM,终止执行 - if(!elemDataView[0]) return; - - renderDataView(0); - }); - - //访问量 - layui.use(['carousel', 'echarts'], function(){ - var $ = layui.$ - ,carousel = layui.carousel - ,echarts = layui.echarts; - - var echartsApp = [], options = [ - { - tooltip : { - trigger: 'axis' - }, - calculable : true, - legend: { - data:['访问量','下载量','平均访问量'] - }, - - xAxis : [ - { - type : 'category', - data : ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'] - } - ], - yAxis : [ - { - type : 'value', - name : '访问量', - axisLabel : { - formatter: '{value} 万' - } - }, - { - type : 'value', - name : '下载量', - axisLabel : { - formatter: '{value} 万' - } - } - ], - series : [ - { - name:'访问量', - type:'line', - data:[900, 850, 950, 1000, 1100, 1050, 1000, 1150, 1250, 1370, 1250, 1100] - }, - { - name:'下载量', - type:'line', - yAxisIndex: 1, - data:[850, 850, 800, 950, 1000, 950, 950, 1150, 1100, 1240, 1000, 950] - }, - { - name:'平均访问量', - type:'line', - data:[870, 850, 850, 950, 1050, 1000, 980, 1150, 1000, 1300, 1150, 1000] - } - ] - } - ] - ,elemDataView = $('#LAY-index-pagetwo').children('div') - ,renderDataView = function(index){ - echartsApp[index] = echarts.init(elemDataView[index], layui.echartsTheme); - echartsApp[index].setOption(options[index]); - window.onresize = echartsApp[index].resize; - }; - //没找到DOM,终止执行 - if(!elemDataView[0]) return; - renderDataView(0); - - }); - - //地图 - layui.use(['carousel', 'echarts'], function(){ - var $ = layui.$ - ,carousel = layui.carousel - ,echarts = layui.echarts; - - var echartsApp = [], options = [ - { - title : { - text: '访客地区分布', - subtext: '不完全统计' - }, - tooltip : { - trigger: 'item' - }, - dataRange: { - orient: 'horizontal', - min: 0, - max: 60000, - text:['高','低'], - splitNumber:0 - }, - series : [ - { - name: '访客地区分布', - type: 'map', - mapType: 'china', - selectedMode : 'multiple', - itemStyle:{ - normal:{label:{show:true}}, - emphasis:{label:{show:true}} - }, - data:[ - {name:'西藏', value:60}, - {name:'青海', value:167}, - {name:'宁夏', value:210}, - {name:'海南', value:252}, - {name:'甘肃', value:502}, - {name:'贵州', value:570}, - {name:'新疆', value:661}, - {name:'云南', value:8890}, - {name:'重庆', value:10010}, - {name:'吉林', value:5056}, - {name:'山西', value:2123}, - {name:'天津', value:9130}, - {name:'江西', value:10170}, - {name:'广西', value:6172}, - {name:'陕西', value:9251}, - {name:'黑龙江', value:5125}, - {name:'内蒙古', value:1435}, - {name:'安徽', value:9530}, - {name:'北京', value:51919}, - {name:'福建', value:3756}, - {name:'上海', value:59190}, - {name:'湖北', value:37109}, - {name:'湖南', value:8966}, - {name:'四川', value:31020}, - {name:'辽宁', value:7222}, - {name:'河北', value:3451}, - {name:'河南', value:9693}, - {name:'浙江', value:62310}, - {name:'山东', value:39231}, - {name:'江苏', value:35911}, - {name:'广东', value:55891} - ] - } - ] - } - ] - ,elemDataView = $('#LAY-index-pagethree').children('div') - ,renderDataView = function(index){ - echartsApp[index] = echarts.init(elemDataView[index], layui.echartsTheme); - echartsApp[index].setOption(options[index]); - window.onresize = echartsApp[index].resize; - }; - //没找到DOM,终止执行 - if(!elemDataView[0]) return; - - renderDataView(0); - }); - - //项目进展 - layui.use('table', function(){ - var $ = layui.$ - ,table = layui.table; - - table.render({ - elem: '#LAY-home-homepage2' - ,url: './json/console/prograss.js' //模拟接口 - ,cols: [[ - {type: 'checkbox', fixed: 'left'} - ,{field: 'prograss', title: '任务'} - ,{field: 'time', title: '所需时间'} - ,{field: 'complete', title: '完成情况' - ,templet: function(d){ - if(d.complete == '已完成'){ - return ''+ d.complete +'' - }else if(d.complete == '进行中'){ - return ''+ d.complete +'' - }else{ - return ''+ d.complete +'' - } - } - } - ]] - ,skin: 'line' - }); - }); - - //回复留言 - admin.events.replyNote = function(othis){ - var nid = othis.data('id'); - layer.prompt({ - title: '回复留言 ID:'+ nid - ,formType: 2 - }, function(value, index){ - //这里可以请求 Ajax - //… - layer.msg('得到:'+ value); - layer.close(index); - }); - }; - - exports('sample', {}) -}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/senior.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/senior.js deleted file mode 100644 index 15b5df3a..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/controller/senior.js +++ /dev/null @@ -1,1153 +0,0 @@ -/** - - @Name:layuiAdmin Echarts集成 - @Author:star1029 - - @License:GPL-2 - - */ - - -layui.define(function(exports){ - - //区块轮播切换 - layui.use(['admin', 'carousel'], function(){ - var $ = layui.$ - ,admin = layui.admin - ,carousel = layui.carousel - ,element = layui.element - ,device = layui.device(); - - //轮播切换 - $('.layadmin-carousel').each(function(){ - var othis = $(this); - carousel.render({ - elem: this - ,width: '100%' - ,arrow: 'none' - ,interval: othis.data('interval') - ,autoplay: othis.data('autoplay') === true - ,trigger: (device.ios || device.android) ? 'click' : 'hover' - ,anim: othis.data('anim') - }); - }); - - }); - - //折线图 - layui.use(['echarts'], function(){ - var $ = layui.$ - ,echarts = layui.echarts; - - //标准折线图 - var echnormline = [], normline = [ - { - title : { - text: '未来一周气温变化', - subtext: '纯属虚构' - }, - tooltip : { - trigger: 'axis' - }, - legend: { - data:['最高气温','最低气温'] - }, - calculable : true, - xAxis : [ - { - type : 'category', - boundaryGap : false, - data : ['周一','周二','周三','周四','周五','周六','周日'] - } - ], - yAxis : [ - { - type : 'value', - axisLabel : { - formatter: '{value} °C' - } - } - ], - series : [ - { - name:'最高气温', - type:'line', - data:[11, 11, 15, 13, 12, 13, 10], - markPoint : { - data : [{type : 'max', name: '最大值'},{type : 'min', name: '最小值'}] - }, - markLine : { - data : [{type : 'average', name: '平均值'}] - } - }, - { - name:'最低气温', - type:'line', - data:[1, -2, 2, 5, 3, 2, 0], - markPoint : { - data : [{name : '周最低', value : -2, xAxis: 1, yAxis: -1.5}] - }, - markLine : { - data : [{type : 'average', name : '平均值'}] - } - } - ] - } - ] - ,elemnormline = $('#LAY-index-normline').children('div') - ,rendernormline = function(index){ - echnormline[index] = echarts.init(elemnormline[index], layui.echartsTheme); - echnormline[index].setOption(normline[index]); - window.onresize = echnormline[index].resize; - }; - if(!elemnormline[0]) return; - rendernormline(0); - - //堆积折线图 - var echheapline = [], heapline = [ - { - tooltip : { - trigger: 'axis' - }, - legend: {data:['邮件营销','联盟广告','视频广告','直接访问','搜索引擎']}, - calculable : true, - xAxis : [ - { - type : 'category', - boundaryGap : false, - data : ['周一','周二','周三','周四','周五','周六','周日'] - } - ], - yAxis : [ - { - type : 'value' - } - ], - series : [ - { - name:'邮件营销', - type:'line', - stack: '总量', - data:[120, 132, 101, 134, 90, 230, 210] - }, - { - name:'联盟广告', - type:'line', - stack: '总量', - data:[220, 182, 191, 234, 290, 330, 310] - }, - { - name:'视频广告', - type:'line', - stack: '总量', - data:[150, 232, 201, 154, 190, 330, 410] - }, - { - name:'直接访问', - type:'line', - stack: '总量', - data:[320, 332, 301, 334, 390, 330, 320] - }, - { - name:'搜索引擎', - type:'line', - stack: '总量', - data:[820, 932, 901, 934, 1290, 1330, 1320] - } - ] - } - ] - ,elemheapline = $('#LAY-index-heapline').children('div') - ,renderheapline = function(index){ - echheapline[index] = echarts.init(elemheapline[index], layui.echartsTheme); - echheapline[index].setOption(heapline[index]); - window.onresize = echheapline[index].resize; - }; - if(!elemheapline[0]) return; - renderheapline(0); - - //不等距折线图 - var echdiffline = [], diffline = [ - { - title : { - text: '双数值轴折线', - subtext: '纯属虚构' - }, - tooltip : { - trigger: 'axis', - axisPointer:{ - show: true, - type : 'cross', - lineStyle: { - type : 'dashed', - width : 1 - } - }, - formatter : function (params) { - return params.seriesName + ' : [ '+ params.value[0] + ', ' + params.value[1] + ' ]'; - } - }, - legend: { - data:['数据1','数据2'] - }, - calculable : true, - xAxis : [ - { - type: 'value' - } - ], - yAxis : [ - { - type: 'value', - axisLine: { - lineStyle: { color: '#dc143c' } - } - } - ], - series : [ - { - name:'数据1', - type:'line', - data:[ - [1.5, 10], [5, 7], [8, 8], [12, 6], [11, 12], [16, 9], [14, 6], [17, 4], [19, 9] - ], - markPoint : { - data : [ - // 纵轴,默认 - {type : 'max', name: '最大值',symbol: 'emptyCircle', itemStyle:{normal:{color:'#dc143c',label:{position:'top'}}}}, - {type : 'min', name: '最小值',symbol: 'emptyCircle', itemStyle:{normal:{color:'#dc143c',label:{position:'bottom'}}}}, - // 横轴 - {type : 'max', name: '最大值', valueIndex: 0, symbol: 'emptyCircle', itemStyle:{normal:{color:'#1e90ff',label:{position:'right'}}}}, - {type : 'min', name: '最小值', valueIndex: 0, symbol: 'emptyCircle', itemStyle:{normal:{color:'#1e90ff',label:{position:'left'}}}} - ] - }, - markLine : { - data : [ - // 纵轴,默认 - {type : 'max', name: '最大值', itemStyle:{normal:{color:'#dc143c'}}}, - {type : 'min', name: '最小值', itemStyle:{normal:{color:'#dc143c'}}}, - {type : 'average', name : '平均值', itemStyle:{normal:{color:'#dc143c'}}}, - // 横轴 - {type : 'max', name: '最大值', valueIndex: 0, itemStyle:{normal:{color:'#1e90ff'}}}, - {type : 'min', name: '最小值', valueIndex: 0, itemStyle:{normal:{color:'#1e90ff'}}}, - {type : 'average', name : '平均值', valueIndex: 0, itemStyle:{normal:{color:'#1e90ff'}}} - ] - } - }, - { - name:'数据2', - type:'line', - data:[ - [1, 2], [2, 3], [4, 2], [7, 5], [11, 2], [18, 3] - ] - } - ] - } - ] - ,elemdiffline = $('#LAY-index-diffline').children('div') - ,renderdiffline = function(index){ - echdiffline[index] = echarts.init(elemdiffline[index], layui.echartsTheme); - echdiffline[index].setOption(diffline[index]); - window.onresize = echdiffline[index].resize; - }; - if(!elemdiffline[0]) return; - renderdiffline(0); - - //堆积面积图 - var echheaparea = [], heaparea = [ - { - tooltip : { - trigger: 'axis' - }, - legend: { - data:['邮件营销','联盟广告','视频广告','直接访问','搜索引擎'] - }, - calculable : true, - xAxis : [ - { - type : 'category', - boundaryGap : false, - data : ['周一','周二','周三','周四','周五','周六','周日'] - } - ], - yAxis : [ - { - type : 'value' - } - ], - series : [ - { - name:'邮件营销', - type:'line', - stack: '总量', - itemStyle: {normal: {areaStyle: {type: 'default'}}}, - data:[120, 132, 101, 134, 90, 230, 210] - }, - { - name:'联盟广告', - type:'line', - stack: '总量', - itemStyle: {normal: {areaStyle: {type: 'default'}}}, - data:[220, 182, 191, 234, 290, 330, 310] - }, - { - name:'视频广告', - type:'line', - stack: '总量', - itemStyle: {normal: {areaStyle: {type: 'default'}}}, - data:[150, 232, 201, 154, 190, 330, 410] - }, - { - name:'直接访问', - type:'line', - stack: '总量', - itemStyle: {normal: {areaStyle: {type: 'default'}}}, - data:[320, 332, 301, 334, 390, 330, 320] - }, - { - name:'搜索引擎', - type:'line', - stack: '总量', - itemStyle: {normal: {areaStyle: {type: 'default'}}}, - data:[820, 932, 901, 934, 1290, 1330, 1320] - } - ] - } - ] - ,elemheaparea = $('#LAY-index-heaparea').children('div') - ,renderheaparea = function(index){ - echheaparea[index] = echarts.init(elemheaparea[index], layui.echartsTheme); - echheaparea[index].setOption(heaparea[index]); - window.onresize = echheaparea[index].resize; - }; - if(!elemheaparea[0]) return; - renderheaparea(0); - - //面积图 - var echarea = [], area = [ - { - title : { - text: '雨量流量关系图', - x: 'center' - }, - tooltip : { - trigger: 'axis', - formatter: function(params) { - return params[0].name + '
                          ' + params[0].seriesName + ' : ' + params[0].value + ' (m^3/s)
                          ' - + params[1].seriesName + ' : ' + -params[1].value + ' (mm)'; - } - }, - legend: { - data:['流量','降雨量'], - x: 'left' - }, - dataZoom : { - show : true, - realtime : true, - start : 0, - end : 100 - }, - xAxis : [ - { - type : 'category', - boundaryGap : false, - axisLine: {onZero: false}, - data : [ - '2009/6/12 2:00', '2009/6/12 3:00', '2009/6/12 4:00', '2009/6/12 5:00', '2009/6/12 6:00', '2009/6/12 7:00', '2009/6/12 8:00', '2009/6/12 9:00', '2009/6/12 10:00', '2009/6/12 11:00', '2009/6/12 12:00', '2009/6/12 13:00', '2009/6/12 14:00', '2009/6/12 15:00', '2009/6/12 16:00', '2009/6/12 17:00', '2009/6/12 18:00', '2009/6/12 19:00', '2009/6/12 20:00', '2009/6/12 21:00', '2009/6/12 22:00', '2009/6/12 23:00', - '2009/6/13 0:00', '2009/6/13 1:00', '2009/6/13 2:00', '2009/6/13 3:00', '2009/6/13 4:00', '2009/6/13 5:00', '2009/6/13 6:00', '2009/6/13 7:00', '2009/6/13 8:00', '2009/6/13 9:00', '2009/6/13 10:00', '2009/6/13 11:00', '2009/6/13 12:00', '2009/6/13 13:00', '2009/6/13 14:00', '2009/6/13 15:00', '2009/6/13 16:00', '2009/6/13 17:00', '2009/6/13 18:00', '2009/6/13 19:00', '2009/6/13 20:00', '2009/6/13 21:00', '2009/6/13 22:00', '2009/6/13 23:00', - '2009/6/14 0:00', '2009/6/14 1:00', '2009/6/14 2:00', '2009/6/14 3:00', '2009/6/14 4:00', '2009/6/14 5:00', '2009/6/14 6:00', '2009/6/14 7:00', '2009/6/14 8:00', '2009/6/14 9:00', '2009/6/14 10:00', '2009/6/14 11:00', '2009/6/14 12:00', '2009/6/14 13:00', '2009/6/14 14:00', '2009/6/14 15:00', '2009/6/14 16:00', '2009/6/14 17:00', '2009/6/14 18:00', '2009/6/14 19:00', '2009/6/14 20:00', '2009/6/14 21:00', '2009/6/14 22:00', '2009/6/14 23:00', - '2009/6/15 0:00', '2009/6/15 1:00', '2009/6/15 2:00', '2009/6/15 3:00', '2009/6/15 4:00', '2009/6/15 5:00', '2009/6/15 6:00', '2009/6/15 7:00', '2009/6/15 8:00', '2009/6/15 9:00', '2009/6/15 10:00', '2009/6/15 11:00', '2009/6/15 12:00', '2009/6/15 13:00', '2009/6/15 14:00', '2009/6/15 15:00', '2009/6/15 16:00', '2009/6/15 17:00', '2009/6/15 18:00', '2009/6/15 19:00', '2009/6/15 20:00', '2009/6/15 21:00', '2009/6/15 22:00', '2009/6/15 23:00', - '2009/6/15 0:00', '2009/6/16 1:00', '2009/6/16 2:00', '2009/6/16 3:00', '2009/6/16 4:00', '2009/6/16 5:00', '2009/6/16 6:00', '2009/6/16 7:00', '2009/6/16 8:00', '2009/6/16 9:00', '2009/6/16 10:00', '2009/6/16 11:00', '2009/6/16 12:00', '2009/6/16 13:00', '2009/6/16 14:00', '2009/6/16 15:00', '2009/6/16 16:00', '2009/6/16 17:00', '2009/6/16 18:00', '2009/6/16 19:00', '2009/6/16 20:00', '2009/6/16 21:00', '2009/6/16 22:00', '2009/6/16 23:00', - '2009/6/15 0:00', '2009/6/17 1:00', '2009/6/17 2:00', '2009/6/17 3:00', '2009/6/17 4:00', '2009/6/17 5:00', '2009/6/17 6:00', '2009/6/17 7:00', '2009/6/17 8:00', '2009/6/17 9:00', '2009/6/17 10:00', '2009/6/17 11:00', '2009/6/17 12:00', '2009/6/17 13:00', '2009/6/17 14:00', '2009/6/17 15:00', '2009/6/17 16:00', '2009/6/17 17:00', '2009/6/17 18:00', '2009/6/17 19:00', '2009/6/17 20:00', '2009/6/17 21:00', '2009/6/17 22:00', '2009/6/17 23:00', - '2009/6/18 0:00', '2009/6/18 1:00', '2009/6/18 2:00', '2009/6/18 3:00', '2009/6/18 4:00', '2009/6/18 5:00', '2009/6/18 6:00', '2009/6/18 7:00', '2009/6/18 8:00', '2009/6/18 9:00', '2009/6/18 10:00', '2009/6/18 11:00', '2009/6/18 12:00', '2009/6/18 13:00', '2009/6/18 14:00', '2009/6/18 15:00', '2009/6/18 16:00', '2009/6/18 17:00', '2009/6/18 18:00', '2009/6/18 19:00', '2009/6/18 20:00', '2009/6/18 21:00', '2009/6/18 22:00', '2009/6/18 23:00', - '2009/6/15 0:00', '2009/6/19 1:00', '2009/6/19 2:00', '2009/6/19 3:00', '2009/6/19 4:00', '2009/6/19 5:00', '2009/6/19 6:00', '2009/6/19 7:00', '2009/6/19 8:00', '2009/6/19 9:00', '2009/6/19 10:00', '2009/6/19 11:00', '2009/6/19 12:00', '2009/6/19 13:00', '2009/6/19 14:00', '2009/6/19 15:00', '2009/6/19 16:00', '2009/6/19 17:00', '2009/6/19 18:00', '2009/6/19 19:00', '2009/6/19 20:00', '2009/6/19 21:00', '2009/6/19 22:00', '2009/6/19 23:00', - '2009/6/20 0:00', '2009/6/20 1:00', '2009/6/20 2:00', '2009/6/20 3:00', '2009/6/20 4:00', '2009/6/20 5:00', '2009/6/20 6:00', '2009/6/20 7:00', '2009/6/20 8:00', '2009/6/20 9:00', '2009/6/20 10:00', '2009/6/20 11:00', '2009/6/20 12:00', '2009/6/20 13:00', '2009/6/20 14:00', '2009/6/20 15:00', '2009/6/20 16:00', '2009/6/20 17:00', '2009/6/20 18:00', '2009/6/20 19:00', '2009/6/20 20:00', '2009/6/20 21:00', '2009/6/20 22:00', '2009/6/20 23:00', - '2009/6/21 0:00', '2009/6/21 1:00', '2009/6/21 2:00', '2009/6/21 3:00', '2009/6/21 4:00', '2009/6/21 5:00', '2009/6/21 6:00', '2009/6/21 7:00', '2009/6/21 8:00', '2009/6/21 9:00', '2009/6/21 10:00', '2009/6/21 11:00', '2009/6/21 12:00', '2009/6/21 13:00', '2009/6/21 14:00', '2009/6/21 15:00', '2009/6/21 16:00', '2009/6/21 17:00', '2009/6/21 18:00', '2009/6/21 19:00', '2009/6/21 20:00', '2009/6/21 21:00', '2009/6/21 22:00', '2009/6/21 23:00', - '2009/6/22 0:00', '2009/6/22 1:00', '2009/6/22 2:00', '2009/6/22 3:00', '2009/6/22 4:00', '2009/6/22 5:00', '2009/6/22 6:00', '2009/6/22 7:00', '2009/6/22 8:00', '2009/6/22 9:00', '2009/6/22 10:00', '2009/6/22 11:00', '2009/6/22 12:00', '2009/6/22 13:00', '2009/6/22 14:00', '2009/6/22 15:00', '2009/6/22 16:00', '2009/6/22 17:00', '2009/6/22 18:00', '2009/6/22 19:00', '2009/6/22 20:00', '2009/6/22 21:00', '2009/6/22 22:00', '2009/6/22 23:00', - '2009/6/23 0:00', '2009/6/23 1:00', '2009/6/23 2:00', '2009/6/23 3:00', '2009/6/23 4:00', '2009/6/23 5:00', '2009/6/23 6:00', '2009/6/23 7:00', '2009/6/23 8:00', '2009/6/23 9:00', '2009/6/23 10:00', '2009/6/23 11:00', '2009/6/23 12:00', '2009/6/23 13:00', '2009/6/23 14:00', '2009/6/23 15:00', '2009/6/23 16:00', '2009/6/23 17:00', '2009/6/23 18:00', '2009/6/23 19:00', '2009/6/23 20:00', '2009/6/23 21:00', '2009/6/23 22:00', '2009/6/23 23:00', - '2009/6/24 0:00', '2009/6/24 1:00', '2009/6/24 2:00', '2009/6/24 3:00', '2009/6/24 4:00', '2009/6/24 5:00', '2009/6/24 6:00', '2009/6/24 7:00', '2009/6/24 8:00', '2009/6/24 9:00', '2009/6/24 10:00', '2009/6/24 11:00', '2009/6/24 12:00', '2009/6/24 13:00', '2009/6/24 14:00', '2009/6/24 15:00', '2009/6/24 16:00', '2009/6/24 17:00', '2009/6/24 18:00', '2009/6/24 19:00', '2009/6/24 20:00', '2009/6/24 21:00', '2009/6/24 22:00', '2009/6/24 23:00', - '2009/6/25 0:00', '2009/6/25 1:00', '2009/6/25 2:00', '2009/6/25 3:00', '2009/6/25 4:00', '2009/6/25 5:00', '2009/6/25 6:00', '2009/6/25 7:00', '2009/6/25 8:00', '2009/6/25 9:00', '2009/6/25 10:00', '2009/6/25 11:00', '2009/6/25 12:00', '2009/6/25 13:00', '2009/6/25 14:00', '2009/6/25 15:00', '2009/6/25 16:00', '2009/6/25 17:00', '2009/6/25 18:00', '2009/6/25 19:00', '2009/6/25 20:00', '2009/6/25 21:00', '2009/6/25 22:00', '2009/6/25 23:00', - '2009/6/26 0:00', '2009/6/26 1:00', '2009/6/26 2:00', '2009/6/26 3:00', '2009/6/26 4:00', '2009/6/26 5:00', '2009/6/26 6:00', '2009/6/26 7:00', '2009/6/26 8:00', '2009/6/26 9:00', '2009/6/26 10:00', '2009/6/26 11:00', '2009/6/26 12:00', '2009/6/26 13:00', '2009/6/26 14:00', '2009/6/26 15:00', '2009/6/26 16:00', '2009/6/26 17:00', '2009/6/26 18:00', '2009/6/26 19:00', '2009/6/26 20:00', '2009/6/26 21:00', '2009/6/26 22:00', '2009/6/26 23:00', - '2009/6/27 0:00', '2009/6/27 1:00', '2009/6/27 2:00', '2009/6/27 3:00', '2009/6/27 4:00', '2009/6/27 5:00', '2009/6/27 6:00', '2009/6/27 7:00', '2009/6/27 8:00', '2009/6/27 9:00', '2009/6/27 10:00', '2009/6/27 11:00', '2009/6/27 12:00', '2009/6/27 13:00', '2009/6/27 14:00', '2009/6/27 15:00', '2009/6/27 16:00', '2009/6/27 17:00', '2009/6/27 18:00', '2009/6/27 19:00', '2009/6/27 20:00', '2009/6/27 21:00', '2009/6/27 22:00', '2009/6/27 23:00', - '2009/6/28 0:00', '2009/6/28 1:00', '2009/6/28 2:00', '2009/6/28 3:00', '2009/6/28 4:00', '2009/6/28 5:00', '2009/6/28 6:00', '2009/6/28 7:00', '2009/6/28 8:00', '2009/6/28 9:00', '2009/6/28 10:00', '2009/6/28 11:00', '2009/6/28 12:00', '2009/6/28 13:00', '2009/6/28 14:00', '2009/6/28 15:00', '2009/6/28 16:00', '2009/6/28 17:00', '2009/6/28 18:00', '2009/6/28 19:00', '2009/6/28 20:00', '2009/6/28 21:00', '2009/6/28 22:00', '2009/6/28 23:00', - '2009/6/29 0:00', '2009/6/29 1:00', '2009/6/29 2:00', '2009/6/29 3:00', '2009/6/29 4:00', '2009/6/29 5:00', '2009/6/29 6:00', '2009/6/29 7:00', '2009/6/29 8:00', '2009/6/29 9:00', '2009/6/29 10:00', '2009/6/29 11:00', '2009/6/29 12:00', '2009/6/29 13:00', '2009/6/29 14:00', '2009/6/29 15:00', '2009/6/29 16:00', '2009/6/29 17:00', '2009/6/29 18:00', '2009/6/29 19:00', '2009/6/29 20:00', '2009/6/29 21:00', '2009/6/29 22:00', '2009/6/29 23:00', - '2009/6/30 0:00', '2009/6/30 1:00', '2009/6/30 2:00', '2009/6/30 3:00', '2009/6/30 4:00', '2009/6/30 5:00', '2009/6/30 6:00', '2009/6/30 7:00', '2009/6/30 8:00', '2009/6/30 9:00', '2009/6/30 10:00', '2009/6/30 11:00', '2009/6/30 12:00', '2009/6/30 13:00', '2009/6/30 14:00', '2009/6/30 15:00', '2009/6/30 16:00', '2009/6/30 17:00', '2009/6/30 18:00', '2009/6/30 19:00', '2009/6/30 20:00', '2009/6/30 21:00', '2009/6/30 22:00', '2009/6/30 23:00', - '2009/7/1 0:00', '2009/7/1 1:00', '2009/7/1 2:00', '2009/7/1 3:00', '2009/7/1 4:00', '2009/7/1 5:00', '2009/7/1 6:00', '2009/7/1 7:00', '2009/7/1 8:00', '2009/7/1 9:00', '2009/7/1 10:00', '2009/7/1 11:00', '2009/7/1 12:00', '2009/7/1 13:00', '2009/7/1 14:00', '2009/7/1 15:00', '2009/7/1 16:00', '2009/7/1 17:00', '2009/7/1 18:00', '2009/7/1 19:00', '2009/7/1 20:00', '2009/7/1 21:00', '2009/7/1 22:00', '2009/7/1 23:00', - '2009/7/2 0:00', '2009/7/2 1:00', '2009/7/2 2:00', '2009/7/2 3:00', '2009/7/2 4:00', '2009/7/2 5:00', '2009/7/2 6:00', '2009/7/2 7:00', '2009/7/2 8:00', '2009/7/2 9:00', '2009/7/2 10:00', '2009/7/2 11:00', '2009/7/2 12:00', '2009/7/2 13:00', '2009/7/2 14:00', '2009/7/2 15:00', '2009/7/2 16:00', '2009/7/2 17:00', '2009/7/2 18:00', '2009/7/2 19:00', '2009/7/2 20:00', '2009/7/2 21:00', '2009/7/2 22:00', '2009/7/2 23:00', - '2009/7/3 0:00', '2009/7/3 1:00', '2009/7/3 2:00', '2009/7/3 3:00', '2009/7/3 4:00', '2009/7/3 5:00', '2009/7/3 6:00', '2009/7/3 7:00', '2009/7/3 8:00', '2009/7/3 9:00', '2009/7/3 10:00', '2009/7/3 11:00', '2009/7/3 12:00', '2009/7/3 13:00', '2009/7/3 14:00', '2009/7/3 15:00', '2009/7/3 16:00', '2009/7/3 17:00', '2009/7/3 18:00', '2009/7/3 19:00', '2009/7/3 20:00', '2009/7/3 21:00', '2009/7/3 22:00', '2009/7/3 23:00', - '2009/7/4 0:00', '2009/7/4 1:00', '2009/7/4 2:00', '2009/7/4 3:00', '2009/7/4 4:00', '2009/7/4 5:00', '2009/7/4 6:00', '2009/7/4 7:00', '2009/7/4 8:00', '2009/7/4 9:00', '2009/7/4 10:00', '2009/7/4 11:00', '2009/7/4 12:00', '2009/7/4 13:00', '2009/7/4 14:00', '2009/7/4 15:00', '2009/7/4 16:00', '2009/7/4 17:00', '2009/7/4 18:00', '2009/7/4 19:00', '2009/7/4 20:00', '2009/7/4 21:00', '2009/7/4 22:00', '2009/7/4 23:00', - '2009/7/5 0:00', '2009/7/5 1:00', '2009/7/5 2:00', '2009/7/5 3:00', '2009/7/5 4:00', '2009/7/5 5:00', '2009/7/5 6:00', '2009/7/5 7:00', '2009/7/5 8:00', '2009/7/5 9:00', '2009/7/5 10:00', '2009/7/5 11:00', '2009/7/5 12:00', '2009/7/5 13:00', '2009/7/5 14:00', '2009/7/5 15:00', '2009/7/5 16:00', '2009/7/5 17:00', '2009/7/5 18:00', '2009/7/5 19:00', '2009/7/5 20:00', '2009/7/5 21:00', '2009/7/5 22:00', '2009/7/5 23:00', - '2009/7/6 0:00', '2009/7/6 1:00', '2009/7/6 2:00', '2009/7/6 3:00', '2009/7/6 4:00', '2009/7/6 5:00', '2009/7/6 6:00', '2009/7/6 7:00', '2009/7/6 8:00', '2009/7/6 9:00', '2009/7/6 10:00', '2009/7/6 11:00', '2009/7/6 12:00', '2009/7/6 13:00', '2009/7/6 14:00', '2009/7/6 15:00', '2009/7/6 16:00', '2009/7/6 17:00', '2009/7/6 18:00', '2009/7/6 19:00', '2009/7/6 20:00', '2009/7/6 21:00', '2009/7/6 22:00', '2009/7/6 23:00', - '2009/7/7 0:00', '2009/7/7 1:00', '2009/7/7 2:00', '2009/7/7 3:00', '2009/7/7 4:00', '2009/7/7 5:00', '2009/7/7 6:00', '2009/7/7 7:00', '2009/7/7 8:00', '2009/7/7 9:00', '2009/7/7 10:00', '2009/7/7 11:00', '2009/7/7 12:00', '2009/7/7 13:00', '2009/7/7 14:00', '2009/7/7 15:00', '2009/7/7 16:00', '2009/7/7 17:00', '2009/7/7 18:00', '2009/7/7 19:00', '2009/7/7 20:00', '2009/7/7 21:00', '2009/7/7 22:00', '2009/7/7 23:00', - '2009/7/8 0:00', '2009/7/8 1:00', '2009/7/8 2:00', '2009/7/8 3:00', '2009/7/8 4:00', '2009/7/8 5:00', '2009/7/8 6:00', '2009/7/8 7:00', '2009/7/8 8:00', '2009/7/8 9:00', '2009/7/8 10:00', '2009/7/8 11:00', '2009/7/8 12:00', '2009/7/8 13:00', '2009/7/8 14:00', '2009/7/8 15:00', '2009/7/8 16:00', '2009/7/8 17:00', '2009/7/8 18:00', '2009/7/8 19:00', '2009/7/8 20:00', '2009/7/8 21:00', '2009/7/8 22:00', '2009/7/8 23:00', - '2009/7/9 0:00', '2009/7/9 1:00', '2009/7/9 2:00', '2009/7/9 3:00', '2009/7/9 4:00', '2009/7/9 5:00', '2009/7/9 6:00', '2009/7/9 7:00', '2009/7/9 8:00', '2009/7/9 9:00', '2009/7/9 10:00', '2009/7/9 11:00', '2009/7/9 12:00', '2009/7/9 13:00', '2009/7/9 14:00', '2009/7/9 15:00', '2009/7/9 16:00', '2009/7/9 17:00', '2009/7/9 18:00', '2009/7/9 19:00', '2009/7/9 20:00', '2009/7/9 21:00', '2009/7/9 22:00', '2009/7/9 23:00', - '2009/7/10 0:00', '2009/7/10 1:00', '2009/7/10 2:00', '2009/7/10 3:00', '2009/7/10 4:00', '2009/7/10 5:00', '2009/7/10 6:00', '2009/7/10 7:00', '2009/7/10 8:00', '2009/7/10 9:00', '2009/7/10 10:00', '2009/7/10 11:00', '2009/7/10 12:00', '2009/7/10 13:00', '2009/7/10 14:00', '2009/7/10 15:00', '2009/7/10 16:00', '2009/7/10 17:00', '2009/7/10 18:00', '2009/7/10 19:00', '2009/7/10 20:00', '2009/7/10 21:00', '2009/7/10 22:00', '2009/7/10 23:00', - '2009/7/11 0:00', '2009/7/11 1:00', '2009/7/11 2:00', '2009/7/11 3:00', '2009/7/11 4:00', '2009/7/11 5:00', '2009/7/11 6:00', '2009/7/11 7:00', '2009/7/11 8:00', '2009/7/11 9:00', '2009/7/11 10:00', '2009/7/11 11:00', '2009/7/11 12:00', '2009/7/11 13:00', '2009/7/11 14:00', '2009/7/11 15:00', '2009/7/11 16:00', '2009/7/11 17:00', '2009/7/11 18:00', '2009/7/11 19:00', '2009/7/11 20:00', '2009/7/11 21:00', '2009/7/11 22:00', '2009/7/11 23:00', - '2009/7/12 0:00', '2009/7/12 1:00', '2009/7/12 2:00', '2009/7/12 3:00', '2009/7/12 4:00', '2009/7/12 5:00', '2009/7/12 6:00', '2009/7/12 7:00', '2009/7/12 8:00', '2009/7/12 9:00', '2009/7/12 10:00', '2009/7/12 11:00', '2009/7/12 12:00', '2009/7/12 13:00', '2009/7/12 14:00', '2009/7/12 15:00', '2009/7/12 16:00', '2009/7/12 17:00', '2009/7/12 18:00', '2009/7/12 19:00', '2009/7/12 20:00', '2009/7/12 21:00', '2009/7/12 22:00', '2009/7/12 23:00', - '2009/7/13 0:00', '2009/7/13 1:00', '2009/7/13 2:00', '2009/7/13 3:00', '2009/7/13 4:00', '2009/7/13 5:00', '2009/7/13 6:00', '2009/7/13 7:00', '2009/7/13 8:00', '2009/7/13 9:00', '2009/7/13 10:00', '2009/7/13 11:00', '2009/7/13 12:00', '2009/7/13 13:00', '2009/7/13 14:00', '2009/7/13 15:00', '2009/7/13 16:00', '2009/7/13 17:00', '2009/7/13 18:00', '2009/7/13 19:00', '2009/7/13 20:00', '2009/7/13 21:00', '2009/7/13 22:00', '2009/7/13 23:00', - '2009/7/14 0:00', '2009/7/14 1:00', '2009/7/14 2:00', '2009/7/14 3:00', '2009/7/14 4:00', '2009/7/14 5:00', '2009/7/14 6:00', '2009/7/14 7:00', '2009/7/14 8:00', '2009/7/14 9:00', '2009/7/14 10:00', '2009/7/14 11:00', '2009/7/14 12:00', '2009/7/14 13:00', '2009/7/14 14:00', '2009/7/14 15:00', '2009/7/14 16:00', '2009/7/14 17:00', '2009/7/14 18:00', '2009/7/14 19:00', '2009/7/14 20:00', '2009/7/14 21:00', '2009/7/14 22:00', '2009/7/14 23:00', - '2009/7/15 0:00', '2009/7/15 1:00', '2009/7/15 2:00', '2009/7/15 3:00', '2009/7/15 4:00', '2009/7/15 5:00', '2009/7/15 6:00', '2009/7/15 7:00', '2009/7/15 8:00', '2009/7/15 9:00', '2009/7/15 10:00', '2009/7/15 11:00', '2009/7/15 12:00', '2009/7/15 13:00', '2009/7/15 14:00', '2009/7/15 15:00', '2009/7/15 16:00', '2009/7/15 17:00', '2009/7/15 18:00', '2009/7/15 19:00', '2009/7/15 20:00', '2009/7/15 21:00', '2009/7/15 22:00', '2009/7/15 23:00', - '2009/7/16 0:00', '2009/7/16 1:00', '2009/7/16 2:00', '2009/7/16 3:00', '2009/7/16 4:00', '2009/7/16 5:00', '2009/7/16 6:00', '2009/7/16 7:00', '2009/7/16 8:00', '2009/7/16 9:00', '2009/7/16 10:00', '2009/7/16 11:00', '2009/7/16 12:00', '2009/7/16 13:00', '2009/7/16 14:00', '2009/7/16 15:00', '2009/7/16 16:00', '2009/7/16 17:00', '2009/7/16 18:00', '2009/7/16 19:00', '2009/7/16 20:00', '2009/7/16 21:00', '2009/7/16 22:00', '2009/7/16 23:00', - '2009/7/17 0:00', '2009/7/17 1:00', '2009/7/17 2:00', '2009/7/17 3:00', '2009/7/17 4:00', '2009/7/17 5:00', '2009/7/17 6:00', '2009/7/17 7:00', '2009/7/17 8:00', '2009/7/17 9:00', '2009/7/17 10:00', '2009/7/17 11:00', '2009/7/17 12:00', '2009/7/17 13:00', '2009/7/17 14:00', '2009/7/17 15:00', '2009/7/17 16:00', '2009/7/17 17:00', '2009/7/17 18:00', '2009/7/17 19:00', '2009/7/17 20:00', '2009/7/17 21:00', '2009/7/17 22:00', '2009/7/17 23:00', - '2009/7/18 0:00', '2009/7/18 1:00', '2009/7/18 2:00', '2009/7/18 3:00', '2009/7/18 4:00', '2009/7/18 5:00', '2009/7/18 6:00', '2009/7/18 7:00', '2009/7/18 8:00', '2009/7/18 9:00', '2009/7/18 10:00', '2009/7/18 11:00', '2009/7/18 12:00', '2009/7/18 13:00', '2009/7/18 14:00', '2009/7/18 15:00', '2009/7/18 16:00', '2009/7/18 17:00', '2009/7/18 18:00', '2009/7/18 19:00', '2009/7/18 20:00', '2009/7/18 21:00', '2009/7/18 22:00', '2009/7/18 23:00', - '2009/7/19 0:00', '2009/7/19 1:00', '2009/7/19 2:00', '2009/7/19 3:00', '2009/7/19 4:00', '2009/7/19 5:00', '2009/7/19 6:00', '2009/7/19 7:00', '2009/7/19 8:00', '2009/7/19 9:00', '2009/7/19 10:00', '2009/7/19 11:00', '2009/7/19 12:00', '2009/7/19 13:00', '2009/7/19 14:00', '2009/7/19 15:00', '2009/7/19 16:00', '2009/7/19 17:00', '2009/7/19 18:00', '2009/7/19 19:00', '2009/7/19 20:00', '2009/7/19 21:00', '2009/7/19 22:00', '2009/7/19 23:00', - '2009/7/20 0:00', '2009/7/20 1:00', '2009/7/20 2:00', '2009/7/20 3:00', '2009/7/20 4:00', '2009/7/20 5:00', '2009/7/20 6:00', '2009/7/20 7:00', '2009/7/20 8:00', '2009/7/20 9:00', '2009/7/20 10:00', '2009/7/20 11:00', '2009/7/20 12:00', '2009/7/20 13:00', '2009/7/20 14:00', '2009/7/20 15:00', '2009/7/20 16:00', '2009/7/20 17:00', '2009/7/20 18:00', '2009/7/20 19:00', '2009/7/20 20:00', '2009/7/20 21:00', '2009/7/20 22:00', '2009/7/20 23:00', - '2009/7/21 0:00', '2009/7/21 1:00', '2009/7/21 2:00', '2009/7/21 3:00', '2009/7/21 4:00', '2009/7/21 5:00', '2009/7/21 6:00', '2009/7/21 7:00', '2009/7/21 8:00', '2009/7/21 9:00', '2009/7/21 10:00', '2009/7/21 11:00', '2009/7/21 12:00', '2009/7/21 13:00', '2009/7/21 14:00', '2009/7/21 15:00', '2009/7/21 16:00', '2009/7/21 17:00', '2009/7/21 18:00', '2009/7/21 19:00', '2009/7/21 20:00', '2009/7/21 21:00', '2009/7/21 22:00', '2009/7/21 23:00', - '2009/7/22 0:00', '2009/7/22 1:00', '2009/7/22 2:00', '2009/7/22 3:00', '2009/7/22 4:00', '2009/7/22 5:00', '2009/7/22 6:00', '2009/7/22 7:00', '2009/7/22 8:00', '2009/7/22 9:00', '2009/7/22 10:00', '2009/7/22 11:00', '2009/7/22 12:00', '2009/7/22 13:00', '2009/7/22 14:00', '2009/7/22 15:00', '2009/7/22 16:00', '2009/7/22 17:00', '2009/7/22 18:00', '2009/7/22 19:00', '2009/7/22 20:00', '2009/7/22 21:00', '2009/7/22 22:00', '2009/7/22 23:00', - '2009/7/23 0:00', '2009/7/23 1:00', '2009/7/23 2:00', '2009/7/23 3:00', '2009/7/23 4:00', '2009/7/23 5:00', '2009/7/23 6:00', '2009/7/23 7:00', '2009/7/23 8:00', '2009/7/23 9:00', '2009/7/23 10:00', '2009/7/23 11:00', '2009/7/23 12:00', '2009/7/23 13:00', '2009/7/23 14:00', '2009/7/23 15:00', '2009/7/23 16:00', '2009/7/23 17:00', '2009/7/23 18:00', '2009/7/23 19:00', '2009/7/23 20:00', '2009/7/23 21:00', '2009/7/23 22:00', '2009/7/23 23:00', - '2009/7/24 0:00', '2009/7/24 1:00', '2009/7/24 2:00', '2009/7/24 3:00', '2009/7/24 4:00', '2009/7/24 5:00', '2009/7/24 6:00', '2009/7/24 7:00', '2009/7/24 8:00', '2009/7/24 9:00', '2009/7/24 10:00', '2009/7/24 11:00', '2009/7/24 12:00', '2009/7/24 13:00', '2009/7/24 14:00', '2009/7/24 15:00', '2009/7/24 16:00', '2009/7/24 17:00', '2009/7/24 18:00', '2009/7/24 19:00', '2009/7/24 20:00', '2009/7/24 21:00', '2009/7/24 22:00', '2009/7/24 23:00', - '2009/7/25 0:00', '2009/7/25 1:00', '2009/7/25 2:00', '2009/7/25 3:00', '2009/7/25 4:00', '2009/7/25 5:00', '2009/7/25 6:00', '2009/7/25 7:00', '2009/7/25 8:00', '2009/7/25 9:00', '2009/7/25 10:00', '2009/7/25 11:00', '2009/7/25 12:00', '2009/7/25 13:00', '2009/7/25 14:00', '2009/7/25 15:00', '2009/7/25 16:00', '2009/7/25 17:00', '2009/7/25 18:00', '2009/7/25 19:00', '2009/7/25 20:00', '2009/7/25 21:00', '2009/7/25 22:00', '2009/7/25 23:00', - '2009/7/26 0:00', '2009/7/26 1:00', '2009/7/26 2:00', '2009/7/26 3:00', '2009/7/26 4:00', '2009/7/26 5:00', '2009/7/26 6:00', '2009/7/26 7:00', '2009/7/26 8:00', '2009/7/26 9:00', '2009/7/26 10:00', '2009/7/26 11:00', '2009/7/26 12:00', '2009/7/26 13:00', '2009/7/26 14:00', '2009/7/26 15:00', '2009/7/26 16:00', '2009/7/26 17:00', '2009/7/26 18:00', '2009/7/26 19:00', '2009/7/26 20:00', '2009/7/26 21:00', '2009/7/26 22:00', '2009/7/26 23:00', - '2009/7/27 0:00', '2009/7/27 1:00', '2009/7/27 2:00', '2009/7/27 3:00', '2009/7/27 4:00', '2009/7/27 5:00', '2009/7/27 6:00', '2009/7/27 7:00', '2009/7/27 8:00', '2009/7/27 9:00', '2009/7/27 10:00', '2009/7/27 11:00', '2009/7/27 12:00', '2009/7/27 13:00', '2009/7/27 14:00', '2009/7/27 15:00', '2009/7/27 16:00', '2009/7/27 17:00', '2009/7/27 18:00', '2009/7/27 19:00', '2009/7/27 20:00', '2009/7/27 21:00', '2009/7/27 22:00', '2009/7/27 23:00', - '2009/7/28 0:00', '2009/7/28 1:00', '2009/7/28 2:00', '2009/7/28 3:00', '2009/7/28 4:00', '2009/7/28 5:00', '2009/7/28 6:00', '2009/7/28 7:00', '2009/7/28 8:00', '2009/7/28 9:00', '2009/7/28 10:00', '2009/7/28 11:00', '2009/7/28 12:00', '2009/7/28 13:00', '2009/7/28 14:00', '2009/7/28 15:00', '2009/7/28 16:00', '2009/7/28 17:00', '2009/7/28 18:00', '2009/7/28 19:00', '2009/7/28 20:00', '2009/7/28 21:00', '2009/7/28 22:00', '2009/7/28 23:00', - '2009/7/29 0:00', '2009/7/29 1:00', '2009/7/29 2:00', '2009/7/29 3:00', '2009/7/29 4:00', '2009/7/29 5:00', '2009/7/29 6:00', '2009/7/29 7:00', '2009/7/29 8:00', '2009/7/29 9:00', '2009/7/29 10:00', '2009/7/29 11:00', '2009/7/29 12:00', '2009/7/29 13:00', '2009/7/29 14:00', '2009/7/29 15:00', '2009/7/29 16:00', '2009/7/29 17:00', '2009/7/29 18:00', '2009/7/29 19:00', '2009/7/29 20:00', '2009/7/29 21:00', '2009/7/29 22:00', '2009/7/29 23:00', - '2009/7/30 0:00', '2009/7/30 1:00', '2009/7/30 2:00', '2009/7/30 3:00', '2009/7/30 4:00', '2009/7/30 5:00', '2009/7/30 6:00', '2009/7/30 7:00', '2009/7/30 8:00', '2009/7/30 9:00', '2009/7/30 10:00', '2009/7/30 11:00', '2009/7/30 12:00', '2009/7/30 13:00', '2009/7/30 14:00', '2009/7/30 15:00', '2009/7/30 16:00', '2009/7/30 17:00', '2009/7/30 18:00', '2009/7/30 19:00', '2009/7/30 20:00', '2009/7/30 21:00', '2009/7/30 22:00', '2009/7/30 23:00', - '2009/7/31 0:00', '2009/7/31 1:00', '2009/7/31 2:00', '2009/7/31 3:00', '2009/7/31 4:00', '2009/7/31 5:00', '2009/7/31 6:00', '2009/7/31 7:00', '2009/7/31 8:00', '2009/7/31 9:00', '2009/7/31 10:00', '2009/7/31 11:00', '2009/7/31 12:00', '2009/7/31 13:00', '2009/7/31 14:00', '2009/7/31 15:00', '2009/7/31 16:00', '2009/7/31 17:00', '2009/7/31 18:00', '2009/7/31 19:00', '2009/7/31 20:00', '2009/7/31 21:00', '2009/7/31 22:00', '2009/7/31 23:00', - '2009/8/1 0:00', '2009/8/1 1:00', '2009/8/1 2:00', '2009/8/1 3:00', '2009/8/1 4:00', '2009/8/1 5:00', '2009/8/1 6:00', '2009/8/1 7:00', '2009/8/1 8:00', '2009/8/1 9:00', '2009/8/1 10:00', '2009/8/1 11:00', '2009/8/1 12:00', '2009/8/1 13:00', '2009/8/1 14:00', '2009/8/1 15:00', '2009/8/1 16:00', '2009/8/1 17:00', '2009/8/1 18:00', '2009/8/1 19:00', '2009/8/1 20:00', '2009/8/1 21:00', '2009/8/1 22:00', '2009/8/1 23:00', '2009/8/2 0:00', '2009/8/2 1:00', '2009/8/2 2:00', '2009/8/2 3:00', '2009/8/2 4:00', '2009/8/2 5:00', '2009/8/2 6:00', '2009/8/2 7:00', '2009/8/2 8:00', '2009/8/2 9:00', '2009/8/2 10:00', '2009/8/2 11:00', '2009/8/2 12:00', '2009/8/2 13:00', '2009/8/2 14:00', '2009/8/2 15:00', '2009/8/2 16:00', '2009/8/2 17:00', '2009/8/2 18:00', '2009/8/2 19:00', '2009/8/2 20:00', '2009/8/2 21:00', '2009/8/2 22:00', '2009/8/2 23:00', '2009/8/3 0:00', '2009/8/3 1:00', '2009/8/3 2:00', '2009/8/3 3:00', '2009/8/3 4:00', '2009/8/3 5:00', '2009/8/3 6:00', '2009/8/3 7:00', '2009/8/3 8:00', '2009/8/3 9:00', '2009/8/3 10:00', '2009/8/3 11:00', '2009/8/3 12:00', '2009/8/3 13:00', '2009/8/3 14:00', '2009/8/3 15:00', '2009/8/3 16:00', '2009/8/3 17:00', '2009/8/3 18:00', '2009/8/3 19:00', '2009/8/3 20:00', '2009/8/3 21:00', '2009/8/3 22:00', '2009/8/3 23:00', '2009/8/4 0:00', '2009/8/4 1:00', '2009/8/4 2:00', '2009/8/4 3:00', '2009/8/4 4:00', '2009/8/4 5:00', '2009/8/4 6:00', '2009/8/4 7:00', '2009/8/4 8:00', '2009/8/4 9:00', '2009/8/4 10:00', '2009/8/4 11:00', '2009/8/4 12:00', '2009/8/4 13:00', '2009/8/4 14:00', '2009/8/4 15:00', '2009/8/4 16:00', '2009/8/4 17:00', '2009/8/4 18:00', '2009/8/4 19:00', '2009/8/4 20:00', '2009/8/4 21:00', '2009/8/4 22:00', '2009/8/4 23:00', '2009/8/5 0:00', '2009/8/5 1:00', '2009/8/5 2:00', '2009/8/5 3:00', '2009/8/5 4:00', '2009/8/5 5:00', '2009/8/5 6:00', '2009/8/5 7:00', '2009/8/5 8:00', '2009/8/5 9:00', '2009/8/5 10:00', '2009/8/5 11:00', '2009/8/5 12:00', '2009/8/5 13:00', '2009/8/5 14:00', '2009/8/5 15:00', '2009/8/5 16:00', '2009/8/5 17:00', '2009/8/5 18:00', '2009/8/5 19:00', '2009/8/5 20:00', '2009/8/5 21:00', '2009/8/5 22:00', '2009/8/5 23:00', '2009/8/6 0:00', '2009/8/6 1:00', '2009/8/6 2:00', '2009/8/6 3:00', '2009/8/6 4:00', '2009/8/6 5:00', '2009/8/6 6:00', '2009/8/6 7:00', '2009/8/6 8:00', '2009/8/6 9:00', '2009/8/6 10:00', '2009/8/6 11:00', '2009/8/6 12:00', '2009/8/6 13:00', '2009/8/6 14:00', '2009/8/6 15:00', '2009/8/6 16:00', '2009/8/6 17:00', '2009/8/6 18:00', '2009/8/6 19:00', '2009/8/6 20:00', '2009/8/6 21:00', '2009/8/6 22:00', '2009/8/6 23:00', '2009/8/7 0:00', '2009/8/7 1:00', '2009/8/7 2:00', '2009/8/7 3:00', '2009/8/7 4:00', '2009/8/7 5:00', '2009/8/7 6:00', '2009/8/7 7:00', '2009/8/7 8:00', '2009/8/7 9:00', '2009/8/7 10:00', '2009/8/7 11:00', '2009/8/7 12:00', '2009/8/7 13:00', '2009/8/7 14:00', '2009/8/7 15:00', '2009/8/7 16:00', '2009/8/7 17:00', '2009/8/7 18:00', '2009/8/7 19:00', '2009/8/7 20:00', '2009/8/7 21:00', '2009/8/7 22:00', '2009/8/7 23:00', '2009/8/8 0:00', '2009/8/8 1:00', '2009/8/8 2:00', '2009/8/8 3:00', '2009/8/8 4:00', '2009/8/8 5:00', '2009/8/8 6:00', '2009/8/8 7:00', '2009/8/8 8:00', '2009/8/8 9:00', '2009/8/8 10:00', '2009/8/8 11:00', '2009/8/8 12:00', '2009/8/8 13:00', '2009/8/8 14:00', '2009/8/8 15:00', '2009/8/8 16:00', '2009/8/8 17:00', '2009/8/8 18:00', '2009/8/8 19:00', '2009/8/8 20:00', '2009/8/8 21:00', '2009/8/8 22:00', '2009/8/8 23:00', '2009/8/9 0:00', '2009/8/9 1:00', '2009/8/9 2:00', '2009/8/9 3:00', '2009/8/9 4:00', '2009/8/9 5:00', '2009/8/9 6:00', '2009/8/9 7:00', '2009/8/9 8:00', '2009/8/9 9:00', '2009/8/9 10:00', '2009/8/9 11:00', '2009/8/9 12:00', '2009/8/9 13:00', '2009/8/9 14:00', '2009/8/9 15:00', '2009/8/9 16:00', '2009/8/9 17:00', '2009/8/9 18:00', '2009/8/9 19:00', '2009/8/9 20:00', '2009/8/9 21:00', '2009/8/9 22:00', '2009/8/9 23:00', '2009/8/10 0:00', '2009/8/10 1:00', '2009/8/10 2:00', '2009/8/10 3:00', '2009/8/10 4:00', '2009/8/10 5:00', '2009/8/10 6:00', '2009/8/10 7:00', '2009/8/10 8:00', '2009/8/10 9:00', '2009/8/10 10:00', '2009/8/10 11:00', '2009/8/10 12:00', '2009/8/10 13:00', '2009/8/10 14:00', '2009/8/10 15:00', '2009/8/10 16:00', '2009/8/10 17:00', '2009/8/10 18:00', '2009/8/10 19:00', '2009/8/10 20:00', '2009/8/10 21:00', '2009/8/10 22:00', '2009/8/10 23:00', '2009/8/11 0:00', '2009/8/11 1:00', '2009/8/11 2:00', '2009/8/11 3:00', '2009/8/11 4:00', '2009/8/11 5:00', '2009/8/11 6:00', '2009/8/11 7:00', '2009/8/11 8:00', '2009/8/11 9:00', '2009/8/11 10:00', '2009/8/11 11:00', '2009/8/11 12:00', '2009/8/11 13:00', '2009/8/11 14:00', '2009/8/11 15:00', '2009/8/11 16:00', '2009/8/11 17:00', '2009/8/11 18:00', '2009/8/11 19:00', '2009/8/11 20:00', '2009/8/11 21:00', '2009/8/11 22:00', '2009/8/11 23:00', '2009/8/12 0:00', '2009/8/12 1:00', '2009/8/12 2:00', '2009/8/12 3:00', '2009/8/12 4:00', '2009/8/12 5:00', '2009/8/12 6:00', '2009/8/12 7:00', '2009/8/12 8:00', '2009/8/12 9:00', '2009/8/12 10:00', '2009/8/12 11:00', '2009/8/12 12:00', '2009/8/12 13:00', '2009/8/12 14:00', '2009/8/12 15:00', '2009/8/12 16:00', '2009/8/12 17:00', '2009/8/12 18:00', '2009/8/12 19:00', '2009/8/12 20:00', '2009/8/12 21:00', '2009/8/12 22:00', '2009/8/12 23:00', '2009/8/13 0:00', '2009/8/13 1:00', '2009/8/13 2:00', '2009/8/13 3:00', '2009/8/13 4:00', '2009/8/13 5:00', '2009/8/13 6:00', '2009/8/13 7:00', '2009/8/13 8:00', '2009/8/13 9:00', '2009/8/13 10:00', '2009/8/13 11:00', '2009/8/13 12:00', '2009/8/13 13:00', '2009/8/13 14:00', '2009/8/13 15:00', '2009/8/13 16:00', '2009/8/13 17:00', '2009/8/13 18:00', '2009/8/13 19:00', '2009/8/13 20:00', '2009/8/13 21:00', '2009/8/13 22:00', '2009/8/13 23:00', '2009/8/14 0:00', '2009/8/14 1:00', '2009/8/14 2:00', '2009/8/14 3:00', '2009/8/14 4:00', '2009/8/14 5:00', '2009/8/14 6:00', '2009/8/14 7:00', '2009/8/14 8:00', '2009/8/14 9:00', '2009/8/14 10:00', '2009/8/14 11:00', '2009/8/14 12:00', '2009/8/14 13:00', '2009/8/14 14:00', '2009/8/14 15:00', '2009/8/14 16:00', '2009/8/14 17:00', '2009/8/14 18:00', '2009/8/14 19:00', '2009/8/14 20:00', '2009/8/14 21:00', '2009/8/14 22:00', '2009/8/14 23:00', '2009/8/15 0:00', '2009/8/15 1:00', '2009/8/15 2:00', '2009/8/15 3:00', '2009/8/15 4:00', '2009/8/15 5:00', '2009/8/15 6:00', '2009/8/15 7:00', '2009/8/15 8:00', '2009/8/15 9:00', '2009/8/15 10:00', '2009/8/15 11:00', '2009/8/15 12:00', '2009/8/15 13:00', '2009/8/15 14:00', '2009/8/15 15:00', '2009/8/15 16:00', '2009/8/15 17:00', '2009/8/15 18:00', '2009/8/15 19:00', '2009/8/15 20:00', '2009/8/15 21:00', '2009/8/15 22:00', '2009/8/15 23:00', '2009/8/16 0:00', '2009/8/16 1:00', '2009/8/16 2:00', '2009/8/16 3:00', '2009/8/16 4:00', '2009/8/16 5:00', '2009/8/16 6:00', '2009/8/16 7:00', '2009/8/16 8:00', '2009/8/16 9:00', '2009/8/16 10:00', '2009/8/16 11:00', '2009/8/16 12:00', '2009/8/16 13:00', '2009/8/16 14:00', '2009/8/16 15:00', '2009/8/16 16:00', '2009/8/16 17:00', '2009/8/16 18:00', '2009/8/16 19:00', '2009/8/16 20:00', '2009/8/16 21:00', '2009/8/16 22:00', '2009/8/16 23:00', '2009/8/17 0:00', '2009/8/17 1:00', '2009/8/17 2:00', '2009/8/17 3:00', '2009/8/17 4:00', '2009/8/17 5:00', '2009/8/17 6:00', '2009/8/17 7:00', '2009/8/17 8:00', '2009/8/17 9:00', '2009/8/17 10:00', '2009/8/17 11:00', '2009/8/17 12:00', '2009/8/17 13:00', '2009/8/17 14:00', '2009/8/17 15:00', '2009/8/17 16:00', '2009/8/17 17:00', '2009/8/17 18:00', '2009/8/17 19:00', '2009/8/17 20:00', '2009/8/17 21:00', '2009/8/17 22:00', '2009/8/17 23:00', '2009/8/18 0:00', '2009/8/18 1:00', '2009/8/18 2:00', '2009/8/18 3:00', '2009/8/18 4:00', '2009/8/18 5:00', '2009/8/18 6:00', '2009/8/18 7:00', '2009/8/18 8:00', '2009/8/18 9:00', '2009/8/18 10:00', '2009/8/18 11:00', '2009/8/18 12:00', '2009/8/18 13:00', '2009/8/18 14:00', '2009/8/18 15:00', '2009/8/18 16:00', '2009/8/18 17:00', '2009/8/18 18:00', '2009/8/18 19:00', '2009/8/18 20:00', '2009/8/18 21:00', '2009/8/18 22:00', '2009/8/18 23:00', '2009/8/19 0:00', '2009/8/19 1:00', '2009/8/19 2:00', '2009/8/19 3:00', '2009/8/19 4:00', '2009/8/19 5:00', '2009/8/19 6:00', '2009/8/19 7:00', '2009/8/19 8:00', '2009/8/19 9:00', '2009/8/19 10:00', '2009/8/19 11:00', '2009/8/19 12:00', '2009/8/19 13:00', '2009/8/19 14:00', '2009/8/19 15:00', '2009/8/19 16:00', '2009/8/19 17:00', '2009/8/19 18:00', '2009/8/19 19:00', '2009/8/19 20:00', '2009/8/19 21:00', '2009/8/19 22:00', '2009/8/19 23:00', '2009/8/20 0:00', '2009/8/20 1:00', '2009/8/20 2:00', '2009/8/20 3:00', '2009/8/20 4:00', '2009/8/20 5:00', '2009/8/20 6:00', '2009/8/20 7:00', '2009/8/20 8:00', '2009/8/20 9:00', '2009/8/20 10:00', '2009/8/20 11:00', '2009/8/20 12:00', '2009/8/20 13:00', '2009/8/20 14:00', '2009/8/20 15:00', '2009/8/20 16:00', '2009/8/20 17:00', '2009/8/20 18:00', '2009/8/20 19:00', '2009/8/20 20:00', '2009/8/20 21:00', '2009/8/20 22:00', '2009/8/20 23:00', '2009/8/21 0:00', '2009/8/21 1:00', '2009/8/21 2:00', '2009/8/21 3:00', '2009/8/21 4:00', '2009/8/21 5:00', '2009/8/21 6:00', '2009/8/21 7:00', '2009/8/21 8:00', '2009/8/21 9:00', '2009/8/21 10:00', '2009/8/21 11:00', '2009/8/21 12:00', '2009/8/21 13:00', '2009/8/21 14:00', '2009/8/21 15:00', '2009/8/21 16:00', '2009/8/21 17:00', '2009/8/21 18:00', '2009/8/21 19:00', '2009/8/21 20:00', '2009/8/21 21:00', '2009/8/21 22:00', '2009/8/21 23:00', '2009/8/22 0:00', '2009/8/22 1:00', '2009/8/22 2:00', '2009/8/22 3:00', '2009/8/22 4:00', '2009/8/22 5:00', '2009/8/22 6:00', '2009/8/22 7:00', '2009/8/22 8:00', '2009/8/22 9:00', '2009/8/22 10:00', '2009/8/22 11:00', '2009/8/22 12:00', '2009/8/22 13:00', '2009/8/22 14:00', '2009/8/22 15:00', '2009/8/22 16:00', '2009/8/22 17:00', '2009/8/22 18:00', '2009/8/22 19:00', '2009/8/22 20:00', '2009/8/22 21:00', '2009/8/22 22:00', '2009/8/22 23:00', '2009/8/23 0:00', '2009/8/23 1:00', '2009/8/23 2:00', '2009/8/23 3:00', '2009/8/23 4:00', '2009/8/23 5:00', '2009/8/23 6:00', '2009/8/23 7:00', '2009/8/23 8:00', '2009/8/23 9:00', '2009/8/23 10:00', '2009/8/23 11:00', '2009/8/23 12:00', '2009/8/23 13:00', '2009/8/23 14:00', '2009/8/23 15:00', '2009/8/23 16:00', '2009/8/23 17:00', '2009/8/23 18:00', '2009/8/23 19:00', '2009/8/23 20:00', '2009/8/23 21:00', '2009/8/23 22:00', '2009/8/23 23:00', '2009/8/24 0:00', '2009/8/24 1:00', '2009/8/24 2:00', '2009/8/24 3:00', '2009/8/24 4:00', '2009/8/24 5:00', '2009/8/24 6:00', '2009/8/24 7:00', '2009/8/24 8:00', '2009/8/24 9:00', '2009/8/24 10:00', '2009/8/24 11:00', '2009/8/24 12:00', '2009/8/24 13:00', '2009/8/24 14:00', '2009/8/24 15:00', '2009/8/24 16:00', '2009/8/24 17:00', '2009/8/24 18:00', '2009/8/24 19:00', '2009/8/24 20:00', '2009/8/24 21:00', '2009/8/24 22:00', '2009/8/24 23:00', '2009/8/25 0:00', '2009/8/25 1:00', '2009/8/25 2:00', '2009/8/25 3:00', '2009/8/25 4:00', '2009/8/25 5:00', '2009/8/25 6:00', '2009/8/25 7:00', '2009/8/25 8:00', '2009/8/25 9:00', '2009/8/25 10:00', '2009/8/25 11:00', '2009/8/25 12:00', '2009/8/25 13:00', '2009/8/25 14:00', '2009/8/25 15:00', '2009/8/25 16:00', '2009/8/25 17:00', '2009/8/25 18:00', '2009/8/25 19:00', '2009/8/25 20:00', '2009/8/25 21:00', '2009/8/25 22:00', '2009/8/25 23:00', '2009/8/26 0:00', '2009/8/26 1:00', '2009/8/26 2:00', '2009/8/26 3:00', '2009/8/26 4:00', '2009/8/26 5:00', '2009/8/26 6:00', '2009/8/26 7:00', '2009/8/26 8:00', '2009/8/26 9:00', '2009/8/26 10:00', '2009/8/26 11:00', '2009/8/26 12:00', '2009/8/26 13:00', '2009/8/26 14:00', '2009/8/26 15:00', '2009/8/26 16:00', '2009/8/26 17:00', '2009/8/26 18:00', '2009/8/26 19:00', '2009/8/26 20:00', '2009/8/26 21:00', '2009/8/26 22:00', '2009/8/26 23:00', '2009/8/27 0:00', '2009/8/27 1:00', '2009/8/27 2:00', '2009/8/27 3:00', '2009/8/27 4:00', '2009/8/27 5:00', '2009/8/27 6:00', '2009/8/27 7:00', '2009/8/27 8:00', '2009/8/27 9:00', '2009/8/27 10:00', '2009/8/27 11:00', '2009/8/27 12:00', '2009/8/27 13:00', '2009/8/27 14:00', '2009/8/27 15:00', '2009/8/27 16:00', '2009/8/27 17:00', '2009/8/27 18:00', '2009/8/27 19:00', '2009/8/27 20:00', '2009/8/27 21:00', '2009/8/27 22:00', '2009/8/27 23:00', '2009/8/28 0:00', '2009/8/28 1:00', '2009/8/28 2:00', '2009/8/28 3:00', '2009/8/28 4:00', '2009/8/28 5:00', '2009/8/28 6:00', '2009/8/28 7:00', '2009/8/28 8:00', '2009/8/28 9:00', '2009/8/28 10:00', '2009/8/28 11:00', '2009/8/28 12:00', '2009/8/28 13:00', '2009/8/28 14:00', '2009/8/28 15:00', '2009/8/28 16:00', '2009/8/28 17:00', '2009/8/28 18:00', '2009/8/28 19:00', '2009/8/28 20:00', '2009/8/28 21:00', '2009/8/28 22:00', '2009/8/28 23:00', '2009/8/29 0:00', '2009/8/29 1:00', '2009/8/29 2:00', '2009/8/29 3:00', '2009/8/29 4:00', '2009/8/29 5:00', '2009/8/29 6:00', '2009/8/29 7:00', '2009/8/29 8:00', '2009/8/29 9:00', '2009/8/29 10:00', '2009/8/29 11:00', '2009/8/29 12:00', '2009/8/29 13:00', '2009/8/29 14:00', '2009/8/29 15:00', '2009/8/29 16:00', '2009/8/29 17:00', '2009/8/29 18:00', '2009/8/29 19:00', '2009/8/29 20:00', '2009/8/29 21:00', '2009/8/29 22:00', '2009/8/29 23:00', '2009/8/30 0:00', '2009/8/30 1:00', '2009/8/30 2:00', '2009/8/30 3:00', '2009/8/30 4:00', '2009/8/30 5:00', '2009/8/30 6:00', '2009/8/30 7:00', '2009/8/30 8:00', '2009/8/30 9:00', '2009/8/30 10:00', '2009/8/30 11:00', '2009/8/30 12:00', '2009/8/30 13:00', '2009/8/30 14:00', '2009/8/30 15:00', '2009/8/30 16:00', '2009/8/30 17:00', '2009/8/30 18:00', '2009/8/30 19:00', '2009/8/30 20:00', '2009/8/30 21:00', '2009/8/30 22:00', '2009/8/30 23:00', '2009/8/31 0:00', '2009/8/31 1:00', '2009/8/31 2:00', '2009/8/31 3:00', '2009/8/31 4:00', '2009/8/31 5:00', '2009/8/31 6:00', '2009/8/31 7:00', '2009/8/31 8:00', '2009/8/31 9:00', '2009/8/31 10:00', '2009/8/31 11:00', '2009/8/31 12:00', '2009/8/31 13:00', '2009/8/31 14:00', '2009/8/31 15:00', '2009/8/31 16:00', '2009/8/31 17:00', '2009/8/31 18:00', '2009/8/31 19:00', '2009/8/31 20:00', '2009/8/31 21:00', '2009/8/31 22:00', '2009/8/31 23:00', - '2009/9/1 0:00', '2009/9/1 1:00', '2009/9/1 2:00', '2009/9/1 3:00', '2009/9/1 4:00', '2009/9/1 5:00', '2009/9/1 6:00', '2009/9/1 7:00', '2009/9/1 8:00', '2009/9/1 9:00', '2009/9/1 10:00', '2009/9/1 11:00', '2009/9/1 12:00', '2009/9/1 13:00', '2009/9/1 14:00', '2009/9/1 15:00', '2009/9/1 16:00', '2009/9/1 17:00', '2009/9/1 18:00', '2009/9/1 19:00', '2009/9/1 20:00', '2009/9/1 21:00', '2009/9/1 22:00', '2009/9/1 23:00', '2009/9/2 0:00', '2009/9/2 1:00', '2009/9/2 2:00', '2009/9/2 3:00', '2009/9/2 4:00', '2009/9/2 5:00', '2009/9/2 6:00', '2009/9/2 7:00', '2009/9/2 8:00', '2009/9/2 9:00', '2009/9/2 10:00', '2009/9/2 11:00', '2009/9/2 12:00', '2009/9/2 13:00', '2009/9/2 14:00', '2009/9/2 15:00', '2009/9/2 16:00', '2009/9/2 17:00', '2009/9/2 18:00', '2009/9/2 19:00', '2009/9/2 20:00', '2009/9/2 21:00', '2009/9/2 22:00', '2009/9/2 23:00', '2009/9/3 0:00', '2009/9/3 1:00', '2009/9/3 2:00', '2009/9/3 3:00', '2009/9/3 4:00', '2009/9/3 5:00', '2009/9/3 6:00', '2009/9/3 7:00', '2009/9/3 8:00', '2009/9/3 9:00', '2009/9/3 10:00', '2009/9/3 11:00', '2009/9/3 12:00', '2009/9/3 13:00', '2009/9/3 14:00', '2009/9/3 15:00', '2009/9/3 16:00', '2009/9/3 17:00', '2009/9/3 18:00', '2009/9/3 19:00', '2009/9/3 20:00', '2009/9/3 21:00', '2009/9/3 22:00', '2009/9/3 23:00', '2009/9/4 0:00', '2009/9/4 1:00', '2009/9/4 2:00', '2009/9/4 3:00', '2009/9/4 4:00', '2009/9/4 5:00', '2009/9/4 6:00', '2009/9/4 7:00', '2009/9/4 8:00', '2009/9/4 9:00', '2009/9/4 10:00', '2009/9/4 11:00', '2009/9/4 12:00', '2009/9/4 13:00', '2009/9/4 14:00', '2009/9/4 15:00', '2009/9/4 16:00', '2009/9/4 17:00', '2009/9/4 18:00', '2009/9/4 19:00', '2009/9/4 20:00', '2009/9/4 21:00', '2009/9/4 22:00', '2009/9/4 23:00', '2009/9/5 0:00', '2009/9/5 1:00', '2009/9/5 2:00', '2009/9/5 3:00', '2009/9/5 4:00', '2009/9/5 5:00', '2009/9/5 6:00', '2009/9/5 7:00', '2009/9/5 8:00', '2009/9/5 9:00', '2009/9/5 10:00', '2009/9/5 11:00', '2009/9/5 12:00', '2009/9/5 13:00', '2009/9/5 14:00', '2009/9/5 15:00', '2009/9/5 16:00', '2009/9/5 17:00', '2009/9/5 18:00', '2009/9/5 19:00', '2009/9/5 20:00', '2009/9/5 21:00', '2009/9/5 22:00', '2009/9/5 23:00', '2009/9/6 0:00', '2009/9/6 1:00', '2009/9/6 2:00', '2009/9/6 3:00', '2009/9/6 4:00', '2009/9/6 5:00', '2009/9/6 6:00', '2009/9/6 7:00', '2009/9/6 8:00', '2009/9/6 9:00', '2009/9/6 10:00', '2009/9/6 11:00', '2009/9/6 12:00', '2009/9/6 13:00', '2009/9/6 14:00', '2009/9/6 15:00', '2009/9/6 16:00', '2009/9/6 17:00', '2009/9/6 18:00', '2009/9/6 19:00', '2009/9/6 20:00', '2009/9/6 21:00', '2009/9/6 22:00', '2009/9/6 23:00', '2009/9/7 0:00', '2009/9/7 1:00', '2009/9/7 2:00', '2009/9/7 3:00', '2009/9/7 4:00', '2009/9/7 5:00', '2009/9/7 6:00', '2009/9/7 7:00', '2009/9/7 8:00', '2009/9/7 9:00', '2009/9/7 10:00', '2009/9/7 11:00', '2009/9/7 12:00', '2009/9/7 13:00', '2009/9/7 14:00', '2009/9/7 15:00', '2009/9/7 16:00', '2009/9/7 17:00', '2009/9/7 18:00', '2009/9/7 19:00', '2009/9/7 20:00', '2009/9/7 21:00', '2009/9/7 22:00', '2009/9/7 23:00', '2009/9/8 0:00', '2009/9/8 1:00', '2009/9/8 2:00', '2009/9/8 3:00', '2009/9/8 4:00', '2009/9/8 5:00', '2009/9/8 6:00', '2009/9/8 7:00', '2009/9/8 8:00', '2009/9/8 9:00', '2009/9/8 10:00', '2009/9/8 11:00', '2009/9/8 12:00', '2009/9/8 13:00', '2009/9/8 14:00', '2009/9/8 15:00', '2009/9/8 16:00', '2009/9/8 17:00', '2009/9/8 18:00', '2009/9/8 19:00', '2009/9/8 20:00', '2009/9/8 21:00', '2009/9/8 22:00', '2009/9/8 23:00', '2009/9/9 0:00', '2009/9/9 1:00', '2009/9/9 2:00', '2009/9/9 3:00', '2009/9/9 4:00', '2009/9/9 5:00', '2009/9/9 6:00', '2009/9/9 7:00', '2009/9/9 8:00', '2009/9/9 9:00', '2009/9/9 10:00', '2009/9/9 11:00', '2009/9/9 12:00', '2009/9/9 13:00', '2009/9/9 14:00', '2009/9/9 15:00', '2009/9/9 16:00', '2009/9/9 17:00', '2009/9/9 18:00', '2009/9/9 19:00', '2009/9/9 20:00', '2009/9/9 21:00', '2009/9/9 22:00', '2009/9/9 23:00', '2009/9/10 0:00', '2009/9/10 1:00', '2009/9/10 2:00', '2009/9/10 3:00', '2009/9/10 4:00', '2009/9/10 5:00', '2009/9/10 6:00', '2009/9/10 7:00', '2009/9/10 8:00', '2009/9/10 9:00', '2009/9/10 10:00', '2009/9/10 11:00', '2009/9/10 12:00', '2009/9/10 13:00', '2009/9/10 14:00', '2009/9/10 15:00', '2009/9/10 16:00', '2009/9/10 17:00', '2009/9/10 18:00', '2009/9/10 19:00', '2009/9/10 20:00', '2009/9/10 21:00', '2009/9/10 22:00', '2009/9/10 23:00', '2009/9/11 0:00', '2009/9/11 1:00', '2009/9/11 2:00', '2009/9/11 3:00', '2009/9/11 4:00', '2009/9/11 5:00', '2009/9/11 6:00', '2009/9/11 7:00', '2009/9/11 8:00', '2009/9/11 9:00', '2009/9/11 10:00', '2009/9/11 11:00', '2009/9/11 12:00', '2009/9/11 13:00', '2009/9/11 14:00', '2009/9/11 15:00', '2009/9/11 16:00', '2009/9/11 17:00', '2009/9/11 18:00', '2009/9/11 19:00', '2009/9/11 20:00', '2009/9/11 21:00', '2009/9/11 22:00', '2009/9/11 23:00', '2009/9/12 0:00', '2009/9/12 1:00', '2009/9/12 2:00', '2009/9/12 3:00', '2009/9/12 4:00', '2009/9/12 5:00', '2009/9/12 6:00', '2009/9/12 7:00', '2009/9/12 8:00', '2009/9/12 9:00', '2009/9/12 10:00', '2009/9/12 11:00', '2009/9/12 12:00', '2009/9/12 13:00', '2009/9/12 14:00', '2009/9/12 15:00', '2009/9/12 16:00', '2009/9/12 17:00', '2009/9/12 18:00', '2009/9/12 19:00', '2009/9/12 20:00', '2009/9/12 21:00', '2009/9/12 22:00', '2009/9/12 23:00', '2009/9/13 0:00', '2009/9/13 1:00', '2009/9/13 2:00', '2009/9/13 3:00', '2009/9/13 4:00', '2009/9/13 5:00', '2009/9/13 6:00', '2009/9/13 7:00', '2009/9/13 8:00', '2009/9/13 9:00', '2009/9/13 10:00', '2009/9/13 11:00', '2009/9/13 12:00', '2009/9/13 13:00', '2009/9/13 14:00', '2009/9/13 15:00', '2009/9/13 16:00', '2009/9/13 17:00', '2009/9/13 18:00', '2009/9/13 19:00', '2009/9/13 20:00', '2009/9/13 21:00', '2009/9/13 22:00', '2009/9/13 23:00', '2009/9/14 0:00', '2009/9/14 1:00', '2009/9/14 2:00', '2009/9/14 3:00', '2009/9/14 4:00', '2009/9/14 5:00', '2009/9/14 6:00', '2009/9/14 7:00', '2009/9/14 8:00', '2009/9/14 9:00', '2009/9/14 10:00', '2009/9/14 11:00', '2009/9/14 12:00', '2009/9/14 13:00', '2009/9/14 14:00', '2009/9/14 15:00', '2009/9/14 16:00', '2009/9/14 17:00', '2009/9/14 18:00', '2009/9/14 19:00', '2009/9/14 20:00', '2009/9/14 21:00', '2009/9/14 22:00', '2009/9/14 23:00', '2009/9/15 0:00', '2009/9/15 1:00', '2009/9/15 2:00', '2009/9/15 3:00', '2009/9/15 4:00', '2009/9/15 5:00', '2009/9/15 6:00', '2009/9/15 7:00', '2009/9/15 8:00', '2009/9/15 9:00', '2009/9/15 10:00', '2009/9/15 11:00', '2009/9/15 12:00', '2009/9/15 13:00', '2009/9/15 14:00', '2009/9/15 15:00', '2009/9/15 16:00', '2009/9/15 17:00', '2009/9/15 18:00', '2009/9/15 19:00', '2009/9/15 20:00', '2009/9/15 21:00', '2009/9/15 22:00', '2009/9/15 23:00', '2009/9/16 0:00', '2009/9/16 1:00', '2009/9/16 2:00', '2009/9/16 3:00', '2009/9/16 4:00', '2009/9/16 5:00', '2009/9/16 6:00', '2009/9/16 7:00', '2009/9/16 8:00', '2009/9/16 9:00', '2009/9/16 10:00', '2009/9/16 11:00', '2009/9/16 12:00', '2009/9/16 13:00', '2009/9/16 14:00', '2009/9/16 15:00', '2009/9/16 16:00', '2009/9/16 17:00', '2009/9/16 18:00', '2009/9/16 19:00', '2009/9/16 20:00', '2009/9/16 21:00', '2009/9/16 22:00', '2009/9/16 23:00', '2009/9/17 0:00', '2009/9/17 1:00', '2009/9/17 2:00', '2009/9/17 3:00', '2009/9/17 4:00', '2009/9/17 5:00', '2009/9/17 6:00', '2009/9/17 7:00', '2009/9/17 8:00', '2009/9/17 9:00', '2009/9/17 10:00', '2009/9/17 11:00', '2009/9/17 12:00', '2009/9/17 13:00', '2009/9/17 14:00', '2009/9/17 15:00', '2009/9/17 16:00', '2009/9/17 17:00', '2009/9/17 18:00', '2009/9/17 19:00', '2009/9/17 20:00', '2009/9/17 21:00', '2009/9/17 22:00', '2009/9/17 23:00', '2009/9/18 0:00', '2009/9/18 1:00', '2009/9/18 2:00', '2009/9/18 3:00', '2009/9/18 4:00', '2009/9/18 5:00', '2009/9/18 6:00', '2009/9/18 7:00', '2009/9/18 8:00', '2009/9/18 9:00', '2009/9/18 10:00', '2009/9/18 11:00', '2009/9/18 12:00', '2009/9/18 13:00', '2009/9/18 14:00', '2009/9/18 15:00', '2009/9/18 16:00', '2009/9/18 17:00', '2009/9/18 18:00', '2009/9/18 19:00', '2009/9/18 20:00', '2009/9/18 21:00', '2009/9/18 22:00', '2009/9/18 23:00', '2009/9/19 0:00', '2009/9/19 1:00', '2009/9/19 2:00', '2009/9/19 3:00', '2009/9/19 4:00', '2009/9/19 5:00', '2009/9/19 6:00', '2009/9/19 7:00', '2009/9/19 8:00', '2009/9/19 9:00', '2009/9/19 10:00', '2009/9/19 11:00', '2009/9/19 12:00', '2009/9/19 13:00', '2009/9/19 14:00', '2009/9/19 15:00', '2009/9/19 16:00', '2009/9/19 17:00', '2009/9/19 18:00', '2009/9/19 19:00', '2009/9/19 20:00', '2009/9/19 21:00', '2009/9/19 22:00', '2009/9/19 23:00', '2009/9/20 0:00', '2009/9/20 1:00', '2009/9/20 2:00', '2009/9/20 3:00', '2009/9/20 4:00', '2009/9/20 5:00', '2009/9/20 6:00', '2009/9/20 7:00', '2009/9/20 8:00', '2009/9/20 9:00', '2009/9/20 10:00', '2009/9/20 11:00', '2009/9/20 12:00', '2009/9/20 13:00', '2009/9/20 14:00', '2009/9/20 15:00', '2009/9/20 16:00', '2009/9/20 17:00', '2009/9/20 18:00', '2009/9/20 19:00', '2009/9/20 20:00', '2009/9/20 21:00', '2009/9/20 22:00', '2009/9/20 23:00', '2009/9/21 0:00', '2009/9/21 1:00', '2009/9/21 2:00', '2009/9/21 3:00', '2009/9/21 4:00', '2009/9/21 5:00', '2009/9/21 6:00', '2009/9/21 7:00', '2009/9/21 8:00', '2009/9/21 9:00', '2009/9/21 10:00', '2009/9/21 11:00', '2009/9/21 12:00', '2009/9/21 13:00', '2009/9/21 14:00', '2009/9/21 15:00', '2009/9/21 16:00', '2009/9/21 17:00', '2009/9/21 18:00', '2009/9/21 19:00', '2009/9/21 20:00', '2009/9/21 21:00', '2009/9/21 22:00', '2009/9/21 23:00', '2009/9/22 0:00', '2009/9/22 1:00', '2009/9/22 2:00', '2009/9/22 3:00', '2009/9/22 4:00', '2009/9/22 5:00', '2009/9/22 6:00', '2009/9/22 7:00', '2009/9/22 8:00', '2009/9/22 9:00', '2009/9/22 10:00', '2009/9/22 11:00', '2009/9/22 12:00', '2009/9/22 13:00', '2009/9/22 14:00', '2009/9/22 15:00', '2009/9/22 16:00', '2009/9/22 17:00', '2009/9/22 18:00', '2009/9/22 19:00', '2009/9/22 20:00', '2009/9/22 21:00', '2009/9/22 22:00', '2009/9/22 23:00', '2009/9/23 0:00', '2009/9/23 1:00', '2009/9/23 2:00', '2009/9/23 3:00', '2009/9/23 4:00', '2009/9/23 5:00', '2009/9/23 6:00', '2009/9/23 7:00', '2009/9/23 8:00', '2009/9/23 9:00', '2009/9/23 10:00', '2009/9/23 11:00', '2009/9/23 12:00', '2009/9/23 13:00', '2009/9/23 14:00', '2009/9/23 15:00', '2009/9/23 16:00', '2009/9/23 17:00', '2009/9/23 18:00', '2009/9/23 19:00', '2009/9/23 20:00', '2009/9/23 21:00', '2009/9/23 22:00', '2009/9/23 23:00', '2009/9/24 0:00', '2009/9/24 1:00', '2009/9/24 2:00', '2009/9/24 3:00', '2009/9/24 4:00', '2009/9/24 5:00', '2009/9/24 6:00', '2009/9/24 7:00', '2009/9/24 8:00', '2009/9/24 9:00', '2009/9/24 10:00', '2009/9/24 11:00', '2009/9/24 12:00', '2009/9/24 13:00', '2009/9/24 14:00', '2009/9/24 15:00', '2009/9/24 16:00', '2009/9/24 17:00', '2009/9/24 18:00', '2009/9/24 19:00', '2009/9/24 20:00', '2009/9/24 21:00', '2009/9/24 22:00', '2009/9/24 23:00', '2009/9/25 0:00', '2009/9/25 1:00', '2009/9/25 2:00', '2009/9/25 3:00', '2009/9/25 4:00', '2009/9/25 5:00', '2009/9/25 6:00', '2009/9/25 7:00', '2009/9/25 8:00', '2009/9/25 9:00', '2009/9/25 10:00', '2009/9/25 11:00', '2009/9/25 12:00', '2009/9/25 13:00', '2009/9/25 14:00', '2009/9/25 15:00', '2009/9/25 16:00', '2009/9/25 17:00', '2009/9/25 18:00', '2009/9/25 19:00', '2009/9/25 20:00', '2009/9/25 21:00', '2009/9/25 22:00', '2009/9/25 23:00', '2009/9/26 0:00', '2009/9/26 1:00', '2009/9/26 2:00', '2009/9/26 3:00', '2009/9/26 4:00', '2009/9/26 5:00', '2009/9/26 6:00', '2009/9/26 7:00', '2009/9/26 8:00', '2009/9/26 9:00', '2009/9/26 10:00', '2009/9/26 11:00', '2009/9/26 12:00', '2009/9/26 13:00', '2009/9/26 14:00', '2009/9/26 15:00', '2009/9/26 16:00', '2009/9/26 17:00', '2009/9/26 18:00', '2009/9/26 19:00', '2009/9/26 20:00', '2009/9/26 21:00', '2009/9/26 22:00', '2009/9/26 23:00', '2009/9/27 0:00', '2009/9/27 1:00', '2009/9/27 2:00', '2009/9/27 3:00', '2009/9/27 4:00', '2009/9/27 5:00', '2009/9/27 6:00', '2009/9/27 7:00', '2009/9/27 8:00', '2009/9/27 9:00', '2009/9/27 10:00', '2009/9/27 11:00', '2009/9/27 12:00', '2009/9/27 13:00', '2009/9/27 14:00', '2009/9/27 15:00', '2009/9/27 16:00', '2009/9/27 17:00', '2009/9/27 18:00', '2009/9/27 19:00', '2009/9/27 20:00', '2009/9/27 21:00', '2009/9/27 22:00', '2009/9/27 23:00', '2009/9/28 0:00', '2009/9/28 1:00', '2009/9/28 2:00', '2009/9/28 3:00', '2009/9/28 4:00', '2009/9/28 5:00', '2009/9/28 6:00', '2009/9/28 7:00', '2009/9/28 8:00', '2009/9/28 9:00', '2009/9/28 10:00', '2009/9/28 11:00', '2009/9/28 12:00', '2009/9/28 13:00', '2009/9/28 14:00', '2009/9/28 15:00', '2009/9/28 16:00', '2009/9/28 17:00', '2009/9/28 18:00', '2009/9/28 19:00', '2009/9/28 20:00', '2009/9/28 21:00', '2009/9/28 22:00', '2009/9/28 23:00', '2009/9/29 0:00', '2009/9/29 1:00', '2009/9/29 2:00', '2009/9/29 3:00', '2009/9/29 4:00', '2009/9/29 5:00', '2009/9/29 6:00', '2009/9/29 7:00', '2009/9/29 8:00', '2009/9/29 9:00', '2009/9/29 10:00', '2009/9/29 11:00', '2009/9/29 12:00', '2009/9/29 13:00', '2009/9/29 14:00', '2009/9/29 15:00', '2009/9/29 16:00', '2009/9/29 17:00', '2009/9/29 18:00', '2009/9/29 19:00', '2009/9/29 20:00', '2009/9/29 21:00', '2009/9/29 22:00', '2009/9/29 23:00', '2009/9/30 0:00', '2009/9/30 1:00', '2009/9/30 2:00', '2009/9/30 3:00', '2009/9/30 4:00', '2009/9/30 5:00', '2009/9/30 6:00', '2009/9/30 7:00', '2009/9/30 8:00', '2009/9/30 9:00', '2009/9/30 10:00', '2009/9/30 11:00', '2009/9/30 12:00', '2009/9/30 13:00', '2009/9/30 14:00', '2009/9/30 15:00', '2009/9/30 16:00', '2009/9/30 17:00', '2009/9/30 18:00', '2009/9/30 19:00', '2009/9/30 20:00', '2009/9/30 21:00', '2009/9/30 22:00', '2009/9/30 23:00', - '2009/10/1 0:00', '2009/10/1 1:00', '2009/10/1 2:00', '2009/10/1 3:00', '2009/10/1 4:00', '2009/10/1 5:00', '2009/10/1 6:00', '2009/10/1 7:00', '2009/10/1 8:00', '2009/10/1 9:00', '2009/10/1 10:00', '2009/10/1 11:00', '2009/10/1 12:00', '2009/10/1 13:00', '2009/10/1 14:00', '2009/10/1 15:00', '2009/10/1 16:00', '2009/10/1 17:00', '2009/10/1 18:00', '2009/10/1 19:00', '2009/10/1 20:00', '2009/10/1 21:00', '2009/10/1 22:00', '2009/10/1 23:00', '2009/10/2 0:00', '2009/10/2 1:00', '2009/10/2 2:00', '2009/10/2 3:00', '2009/10/2 4:00', '2009/10/2 5:00', '2009/10/2 6:00', '2009/10/2 7:00', '2009/10/2 8:00', '2009/10/2 9:00', '2009/10/2 10:00', '2009/10/2 11:00', '2009/10/2 12:00', '2009/10/2 13:00', '2009/10/2 14:00', '2009/10/2 15:00', '2009/10/2 16:00', '2009/10/2 17:00', '2009/10/2 18:00', '2009/10/2 19:00', '2009/10/2 20:00', '2009/10/2 21:00', '2009/10/2 22:00', '2009/10/2 23:00', '2009/10/3 0:00', '2009/10/3 1:00', '2009/10/3 2:00', '2009/10/3 3:00', '2009/10/3 4:00', '2009/10/3 5:00', '2009/10/3 6:00', '2009/10/3 7:00', '2009/10/3 8:00', '2009/10/3 9:00', '2009/10/3 10:00', '2009/10/3 11:00', '2009/10/3 12:00', '2009/10/3 13:00', '2009/10/3 14:00', '2009/10/3 15:00', '2009/10/3 16:00', '2009/10/3 17:00', '2009/10/3 18:00', '2009/10/3 19:00', '2009/10/3 20:00', '2009/10/3 21:00', '2009/10/3 22:00', '2009/10/3 23:00', '2009/10/4 0:00', '2009/10/4 1:00', '2009/10/4 2:00', '2009/10/4 3:00', '2009/10/4 4:00', '2009/10/4 5:00', '2009/10/4 6:00', '2009/10/4 7:00', '2009/10/4 8:00', '2009/10/4 9:00', '2009/10/4 10:00', '2009/10/4 11:00', '2009/10/4 12:00', '2009/10/4 13:00', '2009/10/4 14:00', '2009/10/4 15:00', '2009/10/4 16:00', '2009/10/4 17:00', '2009/10/4 18:00', '2009/10/4 19:00', '2009/10/4 20:00', '2009/10/4 21:00', '2009/10/4 22:00', '2009/10/4 23:00', '2009/10/5 0:00', '2009/10/5 1:00', '2009/10/5 2:00', '2009/10/5 3:00', '2009/10/5 4:00', '2009/10/5 5:00', '2009/10/5 6:00', '2009/10/5 7:00', '2009/10/5 8:00', '2009/10/5 9:00', '2009/10/5 10:00', '2009/10/5 11:00', '2009/10/5 12:00', '2009/10/5 13:00', '2009/10/5 14:00', '2009/10/5 15:00', '2009/10/5 16:00', '2009/10/5 17:00', '2009/10/5 18:00', '2009/10/5 19:00', '2009/10/5 20:00', '2009/10/5 21:00', '2009/10/5 22:00', '2009/10/5 23:00', '2009/10/6 0:00', '2009/10/6 1:00', '2009/10/6 2:00', '2009/10/6 3:00', '2009/10/6 4:00', '2009/10/6 5:00', '2009/10/6 6:00', '2009/10/6 7:00', '2009/10/6 8:00', '2009/10/6 9:00', '2009/10/6 10:00', '2009/10/6 11:00', '2009/10/6 12:00', '2009/10/6 13:00', '2009/10/6 14:00', '2009/10/6 15:00', '2009/10/6 16:00', '2009/10/6 17:00', '2009/10/6 18:00', '2009/10/6 19:00', '2009/10/6 20:00', '2009/10/6 21:00', '2009/10/6 22:00', '2009/10/6 23:00', '2009/10/7 0:00', '2009/10/7 1:00', '2009/10/7 2:00', '2009/10/7 3:00', '2009/10/7 4:00', '2009/10/7 5:00', '2009/10/7 6:00', '2009/10/7 7:00', '2009/10/7 8:00', '2009/10/7 9:00', '2009/10/7 10:00', '2009/10/7 11:00', '2009/10/7 12:00', '2009/10/7 13:00', '2009/10/7 14:00', '2009/10/7 15:00', '2009/10/7 16:00', '2009/10/7 17:00', '2009/10/7 18:00', '2009/10/7 19:00', '2009/10/7 20:00', '2009/10/7 21:00', '2009/10/7 22:00', '2009/10/7 23:00', '2009/10/8 0:00', '2009/10/8 1:00', '2009/10/8 2:00', '2009/10/8 3:00', '2009/10/8 4:00', '2009/10/8 5:00', '2009/10/8 6:00', '2009/10/8 7:00', '2009/10/8 8:00', '2009/10/8 9:00', '2009/10/8 10:00', '2009/10/8 11:00', '2009/10/8 12:00', '2009/10/8 13:00', '2009/10/8 14:00', '2009/10/8 15:00', '2009/10/8 16:00', '2009/10/8 17:00', '2009/10/8 18:00', '2009/10/8 19:00', '2009/10/8 20:00', '2009/10/8 21:00', '2009/10/8 22:00', '2009/10/8 23:00', '2009/10/9 0:00', '2009/10/9 1:00', '2009/10/9 2:00', '2009/10/9 3:00', '2009/10/9 4:00', '2009/10/9 5:00', '2009/10/9 6:00', '2009/10/9 7:00', '2009/10/9 8:00', '2009/10/9 9:00', '2009/10/9 10:00', '2009/10/9 11:00', '2009/10/9 12:00', '2009/10/9 13:00', '2009/10/9 14:00', '2009/10/9 15:00', '2009/10/9 16:00', '2009/10/9 17:00', '2009/10/9 18:00', '2009/10/9 19:00', '2009/10/9 20:00', '2009/10/9 21:00', '2009/10/9 22:00', '2009/10/9 23:00', '2009/10/10 0:00', '2009/10/10 1:00', '2009/10/10 2:00', '2009/10/10 3:00', '2009/10/10 4:00', '2009/10/10 5:00', '2009/10/10 6:00', '2009/10/10 7:00', '2009/10/10 8:00', '2009/10/10 9:00', '2009/10/10 10:00', '2009/10/10 11:00', '2009/10/10 12:00', '2009/10/10 13:00', '2009/10/10 14:00', '2009/10/10 15:00', '2009/10/10 16:00', '2009/10/10 17:00', '2009/10/10 18:00', '2009/10/10 19:00', '2009/10/10 20:00', '2009/10/10 21:00', '2009/10/10 22:00', '2009/10/10 23:00', '2009/10/11 0:00', '2009/10/11 1:00', '2009/10/11 2:00', '2009/10/11 3:00', '2009/10/11 4:00', '2009/10/11 5:00', '2009/10/11 6:00', '2009/10/11 7:00', '2009/10/11 8:00', '2009/10/11 9:00', '2009/10/11 10:00', '2009/10/11 11:00', '2009/10/11 12:00', '2009/10/11 13:00', '2009/10/11 14:00', '2009/10/11 15:00', '2009/10/11 16:00', '2009/10/11 17:00', '2009/10/11 18:00', '2009/10/11 19:00', '2009/10/11 20:00', '2009/10/11 21:00', '2009/10/11 22:00', '2009/10/11 23:00', '2009/10/12 0:00', '2009/10/12 1:00', '2009/10/12 2:00', '2009/10/12 3:00', '2009/10/12 4:00', '2009/10/12 5:00', '2009/10/12 6:00', '2009/10/12 7:00', '2009/10/12 8:00', '2009/10/12 9:00', '2009/10/12 10:00', '2009/10/12 11:00', '2009/10/12 12:00', '2009/10/12 13:00', '2009/10/12 14:00', '2009/10/12 15:00', '2009/10/12 16:00', '2009/10/12 17:00', '2009/10/12 18:00', '2009/10/12 19:00', '2009/10/12 20:00', '2009/10/12 21:00', '2009/10/12 22:00', '2009/10/12 23:00', '2009/10/13 0:00', '2009/10/13 1:00', '2009/10/13 2:00', '2009/10/13 3:00', '2009/10/13 4:00', '2009/10/13 5:00', '2009/10/13 6:00', '2009/10/13 7:00', '2009/10/13 8:00', '2009/10/13 9:00', '2009/10/13 10:00', '2009/10/13 11:00', '2009/10/13 12:00', '2009/10/13 13:00', '2009/10/13 14:00', '2009/10/13 15:00', '2009/10/13 16:00', '2009/10/13 17:00', '2009/10/13 18:00', '2009/10/13 19:00', '2009/10/13 20:00', '2009/10/13 21:00', '2009/10/13 22:00', '2009/10/13 23:00', '2009/10/14 0:00', '2009/10/14 1:00', '2009/10/14 2:00', '2009/10/14 3:00', '2009/10/14 4:00', '2009/10/14 5:00', '2009/10/14 6:00', '2009/10/14 7:00', '2009/10/14 8:00', '2009/10/14 9:00', '2009/10/14 10:00', '2009/10/14 11:00', '2009/10/14 12:00', '2009/10/14 13:00', '2009/10/14 14:00', '2009/10/14 15:00', '2009/10/14 16:00', '2009/10/14 17:00', '2009/10/14 18:00', '2009/10/14 19:00', '2009/10/14 20:00', '2009/10/14 21:00', '2009/10/14 22:00', '2009/10/14 23:00', '2009/10/15 0:00', '2009/10/15 1:00', '2009/10/15 2:00', '2009/10/15 3:00', '2009/10/15 4:00', '2009/10/15 5:00', '2009/10/15 6:00', '2009/10/15 7:00', '2009/10/15 8:00', '2009/10/15 9:00', '2009/10/15 10:00', '2009/10/15 11:00', '2009/10/15 12:00', '2009/10/15 13:00', '2009/10/15 14:00', '2009/10/15 15:00', '2009/10/15 16:00', '2009/10/15 17:00', '2009/10/15 18:00', '2009/10/15 19:00', '2009/10/15 20:00', '2009/10/15 21:00', '2009/10/15 22:00', '2009/10/15 23:00', '2009/10/16 0:00', '2009/10/16 1:00', '2009/10/16 2:00', '2009/10/16 3:00', '2009/10/16 4:00', '2009/10/16 5:00', '2009/10/16 6:00', '2009/10/16 7:00', '2009/10/16 8:00', '2009/10/16 9:00', '2009/10/16 10:00', '2009/10/16 11:00', '2009/10/16 12:00', '2009/10/16 13:00', '2009/10/16 14:00', '2009/10/16 15:00', '2009/10/16 16:00', '2009/10/16 17:00', '2009/10/16 18:00', '2009/10/16 19:00', '2009/10/16 20:00', '2009/10/16 21:00', '2009/10/16 22:00', '2009/10/16 23:00', '2009/10/17 0:00', '2009/10/17 1:00', '2009/10/17 2:00', '2009/10/17 3:00', '2009/10/17 4:00', '2009/10/17 5:00', '2009/10/17 6:00', '2009/10/17 7:00', '2009/10/17 8:00', '2009/10/17 9:00', '2009/10/17 10:00', '2009/10/17 11:00', '2009/10/17 12:00', '2009/10/17 13:00', '2009/10/17 14:00', '2009/10/17 15:00', '2009/10/17 16:00', '2009/10/17 17:00', '2009/10/17 18:00', '2009/10/17 19:00', '2009/10/17 20:00', '2009/10/17 21:00', '2009/10/17 22:00', '2009/10/17 23:00', '2009/10/18 0:00', '2009/10/18 1:00', '2009/10/18 2:00', '2009/10/18 3:00', '2009/10/18 4:00', '2009/10/18 5:00', '2009/10/18 6:00', '2009/10/18 7:00', '2009/10/18 8:00' - ] - } - ], - yAxis : [ - { - name : '流量(m^3/s)', - type : 'value', - max : 500 - }, - { - name : '降雨量(mm)', - type : 'value', - axisLabel : { - formatter: function(v){ - return - v; - } - } - } - ], - series : [ - { - name:'流量', - type:'line', - itemStyle: {normal: {areaStyle: {type: 'default'}}}, - data:[ - 0.97,0.96,0.96,0.95,0.95,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.93,0.92,0.91,0.9,0.89,0.88,0.87,0.87,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.87,0.88,0.9,0.93,0.96,0.99,1.03,1.06,1.1,1.14,1.17,1.2,1.23,1.26,1.29,1.33,1.36,1.4,1.43,1.45,1.48,1.49,1.51,1.51,1.5,1.49,1.47,1.44,1.41,1.37,1.34,1.3,1.27,1.24,1.22,1.2,1.19,1.18,1.16,1.15,1.14,1.13,1.12,1.11,1.11,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.09,1.09,1.08,1.07,1.06,1.05,1.04,1.03,1.03,1.02,1.01,1.01,1,0.99,0.98,0.97,0.96,0.96,0.95,0.95,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.93,0.92,0.91,0.9,0.89,0.88,0.87,0.87,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.85,0.84,0.83,0.82,0.81,0.8,0.8,0.79,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.77,0.75,0.73,0.71,0.68,0.65,0.63,0.61,0.59,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.57,0.57,0.57,0.56,0.55,0.55,0.54,0.54,0.53,0.52,0.52,0.51,0.51,0.5,0.5,0.49,0.48,0.48,0.47,0.47,0.47,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.52,0.67,0.9,1.19,1.52,1.87,2.22,2.55,2.84,3.07,3.22,3.28,3.28,3.28,3.28,3.28,3.28,3.28,3.28,3.28,3.28,3.28,3.28,3.28,3.24,3.13,2.97,2.77,2.54,2.3,2.05,1.82,1.62,1.46,1.35,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.31,1.3,1.26,1.21,1.14,1.06,0.97,0.89,0.81,0.74,0.69,0.65,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.63,0.63,0.62,0.62,0.61,0.6,0.59,0.59,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.59,0.61,0.63,0.65,0.68,0.71,0.73,0.75,0.77,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.77,0.75,0.73,0.71,0.68,0.65,0.63,0.61,0.59,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.58,0.59,0.59,0.6,0.61,0.62,0.62,0.63,0.63,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.65,0.66,0.68,0.69,0.71,0.73,0.74,0.76,0.77,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.79,0.81,0.82,0.84,0.86,0.88,0.9,0.92,0.93,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.94,0.93,0.92,0.91,0.9,0.89,0.88,0.87,0.87,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.86,0.85,0.84,0.82,0.8,0.78,0.76,0.75,0.73,0.72,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.72,0.73,0.74,0.76,0.78,0.79,0.82,0.84,0.86,0.89,0.91,0.94,0.97,1,1.02,1.05,1.08,1.11,1.14,1.17,1.19,1.22,1.25,1.27,1.29,1.31,1.33,1.35,1.36,1.38,1.39,1.39,1.4,1.4,1.4,1.39,1.37,1.35,1.32,1.29,1.26,1.22,1.18,1.14,1.1,1.05,1.01,0.97,0.93,0.89,0.85,0.82,0.78,0.76,0.74,0.72,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.72,0.73,0.74,0.75,0.77,0.78,0.8,0.82,0.84,0.87,0.89,0.92,0.94,0.97,0.99,1.02,1.05,1.08,1.1,1.13,1.16,1.18,1.21,1.23,1.26,1.28,1.3,1.32,1.34,1.35,1.37,1.38,1.39,1.4,1.41,1.41,1.42,1.42,1.43,1.43,1.43,1.44,1.44,1.44,1.44,1.45,1.45,1.45,1.46,1.46,1.46,1.47,1.47,1.48,1.48,1.49,1.5,1.51,1.54,1.62,1.73,1.88,2.05,2.24,2.45,2.67,2.89,3.11,3.31,3.51,3.69,3.86,4.03,4.18,4.33,4.48,4.62,4.76,4.89,5.02,5.16,5.29,5.43,5.57,5.71,5.86,6.02,6.18,6.36,6.54,6.73,6.93,7.15,7.38,7.62,7.88,8.16,8.46,8.77,9.11,9.46,9.84,10.24,10.67,11.12,11.6,12.3,13.66,16,38.43,82.21,146.6,218.7,226,225.23,223.08,219.78,212,199.82,184.6,168,151.65,137.21,126.31,119.94,115.52,112.06,108.92,105.44,101,94.56,86.36,77.67,69.76,63.9,60.38,57.41,54.84,52.57,50.56,48.71,46.97,45.25,43.48,41.6,39.5,37.19,34.81,32.46,30.27,28.36,26.85,25.86,25.5,25.5,25.5,25.5,25.5,25.5,25.5,25.5,25.5,25.5,25.5,25.5,25.5,25.27,24.65,23.7,22.52,21.17,19.75,18.33,16.98,15.8,14.85,14.23,14,14.02,14.08,14.17,14.29,14.44,14.61,14.8,15.01,15.23,15.47,15.71,15.95,16.19,16.43,16.67,16.89,17.1,17.29,17.46,17.61,17.73,17.82,17.88,17.9,17.63,16.88,15.75,14.33,12.71,10.98,9.23,7.56,6.05,4.81,3.92,3.47,3.28,3.1,2.93,2.76,2.61,2.46,2.32,2.19,2.07,1.96,1.85,1.75,1.66,1.58,1.51,1.44,1.39,1.34,1.29,1.26,1.23,1.22,1.2,1.2,1.2,1.2,1.2,1.2,1.21,1.21,1.21,1.21,1.22,1.22,1.22,1.23,1.23,1.23,1.24,1.24,1.25,1.25,1.25,1.26,1.26,1.27,1.27,1.27,1.28,1.28,1.28,1.29,1.29,1.29,1.29,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.29,1.29,1.29,1.29,1.28,1.28,1.28,1.27,1.27,1.26,1.25,1.25,1.24,1.23,1.23,1.22,1.21,1.2,1.16,1.06,0.95,0.83,0.74,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.71,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.69,0.69,0.69,0.69,0.69,0.69,0.69,0.69,0.68,0.68,0.68,0.68,0.68,0.68,0.67,0.67,0.67,0.67,0.67,0.67,0.67,0.66,0.66,0.66,0.66,0.66,0.66,0.66,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.65,0.66,0.68,0.69,0.71,0.73,0.74,0.76,0.77,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.78,0.8,0.86,0.95,1.08,1.25,1.46,1.7,1.97,2.28,2.63,3.01,3.42,3.87,4.35,4.86,5.4,5.98,6.59,7.92,10.49,14.04,18.31,23.04,27.98,32.87,37.45,41.46,44.64,46.74,47.5,46.86,45.16,42.77,40.04,37.33,35,32.74,30.21,27.7,25.5,23.9,23.2,23.06,22.94,22.84,22.77,22.72,22.7,22.8,23.23,23.95,24.91,26.04,27.3,28.76,30.7,33.39,37.12,42.15,48.77,65.22,252.1,257,237.32,221.19,212,208.67,206.89,205.2,202.15,189.82,172,165.3,160.49,156.8,153.44,149.62,144.6,138.27,131,123.11,114.9,106.69,98.79,91.5,85.13,80,75.53,71.03,66.65,62.54,58.85,55.73,53.31,51.75,51.2,56.53,68.25,80,91.01,102.03,109,112.37,115.29,117.68,119.48,120.61,121,119.45,115.57,110.52,105.47,101.58,100,99.97,99.94,99.92,99.9,99.88,99.86,99.85,99.84,99.83,99.82,99.81,99.81,99.8,99.8,99.8,122.15,163.65,186,182.96,175.15,164.56,153.18,143,136,131.37,126.98,122.81,118.85,115.09,111.52,108.13,104.9,101.83,98.9,96.11,93.44,90.87,88.41,86.04,83.74,81.51,79.33,77.2,75.1,73.02,70.95,68.88,66.8,64.87,63.14,61.4,59.53,57.67,56,54.6,53.36,52.2,51.05,49.85,48.5,46.87,44.92,42.74,40.42,38.04,35.69,33.46,31.44,29.72,28.38,27.51,27.2,27.2,27.2,27.2,27.2,27.2,27.2,27.2,27.2,27.2,27.2,27.2,27.2,27.14,26.97,26.7,26.35,25.95,25.49,25.02,24.53,24.04,23.58,23.16,22.8,22.46,22.11,21.75,21.39,21.03,20.69,20.36,20.05,19.78,19.54,19.35,19.2,19.09,19,18.92,18.85,18.79,18.74,18.68,18.62,18.56,18.49,18.4,18.3,18.17,18.02,17.83,17.63,17.41,17.18,16.93,16.68,16.43,16.18,15.93,15.7,15.47,15.22,14.97,14.71,14.45,14.18,13.93,13.68,13.44,13.21,13,12.8,12.62,12.46,12.31,12.16,12.03,11.89,11.76,11.62,11.48,11.33,11.17,11,10.81,10.59,10.36,10.12,9.86,9.61,9.36,9.12,8.89,8.68,8.5,8.35,8.21,8.08,7.94,7.81,7.68,7.56,7.46,7.36,7.29,7.23,7.19,7.18,7.51,8.42,9.81,11.58,13.63,15.86,18.16,20.44,22.58,24.49,26.06,27.2,28.08,28.95,29.81,30.65,31.48,32.28,33.07,33.82,34.55,35.25,35.92,36.56,37.15,37.71,38.23,38.7,39.13,39.5,39.83,40.1,40.31,40.47,40.57,40.6,40.49,40.16,39.64,38.94,38.09,37.1,36,34.79,33.51,32.17,30.79,29.39,27.99,26.6,25.25,23.96,22.75,21.63,20.63,19.76,19.04,18.49,18.14,18,17.97,17.95,17.94,17.92,17.91,17.9,17.89,17.88,17.87,17.85,17.83,17.8,17.7,17.46,17.13,16.7,16.21,15.68,15.13,14.57,14.04,13.56,13.14,12.8,12.52,12.27,12.02,11.79,11.57,11.37,11.16,10.97,10.78,10.59,10.39,10.2,10.01,9.81,9.63,9.44,9.26,9.08,8.9,8.73,8.56,8.39,8.22,8.06,7.9,7.73,7.57,7.41,7.25,7.09,6.94,6.79,6.65,6.52,6.4,6.28,6.17,6.08,5.98,5.9,5.81,5.73,5.65,5.57,5.49,5.41,5.32,5.23,5.14,5.04,4.94,4.84,4.74,4.63,4.53,4.43,4.33,4.23,4.13,4.03,3.93,3.81,3.69,3.57,3.45,3.33,3.22,3.12,3.04,2.98,2.93,2.92,2.92,2.92,2.92,2.92,2.92,2.92,2.92,2.92,2.92,2.92,2.92,2.92,2.9,2.86,2.8,2.71,2.62,2.52,2.42,2.33,2.24,2.18,2.14,2.12,2.12,2.12,2.12,2.12,2.12,2.12,2.12,2.12,2.12,2.12,2.12,2.12,2.1,2.06,2,1.91,1.82,1.71,1.61,1.5,1.4,1.32,1.25,1.2,1.16,1.13,1.1,1.06,1.03,1,0.97,0.93,0.9,0.87,0.85,0.82,0.79,0.77,0.74,0.72,0.69,0.67,0.65,0.63,0.61,0.59,0.58,0.56,0.54,0.53,0.52,0.51,0.5,0.49,0.48,0.48,0.47,0.47,0.46,0.46,0.47,0.48,0.5,0.53,0.56,0.59,0.62,0.64,0.67,0.69,0.7,0.71,0.71,0.71,0.71,0.7,0.7,0.7,0.69,0.69,0.69,0.68,0.68,0.67,0.67,0.67,0.66,0.66,0.65,0.65,0.65,0.65,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.64,0.65,0.65,0.65,0.66,0.66,0.67,0.68,0.69,0.69,0.7,0.71,0.73,0.74,0.75,0.76,0.78,0.8,0.81,0.83,0.85,0.87,0.89,0.92,0.94,0.97,0.99,1.02,1.05,1.08,1.11,1.15,1.18,1.32,1.66,2.21,2.97,3.94,5.11,6.5,8.1,9.9,11.92,14.15,16.6,22.3,22.8,24.48,30.38,35.74,42.4,57.14,94.04,112.9,123.4,130.4,130,119.4,120.7,116.8,118.1,119.4,124.8,143.5,204,294,319.2,328.4,365,350.8,347.6,347.6,325,331.6,319.2,308,308,308,308,296.8,300,281,278.4,270.6,271,253.6,233.5,219.2,207.8,205.9,204,189.6,178.8,173.4,160,154.4,146,145,140.5,130.4,126.2,116.8,112.9,106.5,101.6,98.51,82.67,67.3,80.05,76.12,72.3,71.02,69.78,67.3,67.3,68.54,57.6,71.02,66.06,59.12,57.14,55.16,55.16,52.19,52.19,51.2,48.56,44.16,43,45.92,49.44,44.16,36.48,35.74,35,32.36,37.22,32.36,32.36,32.36,33.68,32.36,31.7,35.74,29.72,32.36,30.38,29.72,28.4,28.4,28.4,27.28,25.6,25.04,23.92,22.3,21.8,21.8,21.8,22.8,21.8,25.6,22.8,22.8,17.8,16.04,16.04,16.04,16.04,16.04,16.04,16.04,16.04,16.04,16.04,15.02,14,14.03,14.11,14.25,14.45,14.72,15.06,15.46,15.95,16.51,17.15,17.87,18.69,19.59,20.59,21.69,22.88,24.18,25.59,27.1,28.73,30.48,32.34,34.33,36.44,38.69,41.06,43.57,46.22,49.01,51.95,55.04,58.27,61.66,65.21,68.92,72.8,88.09,104.9,105.7,110.3,111.6,110.3,106.5,105.7,103.3,100,97.02,98.8,91.07,83.98,88.09,81.36,78.74,77.43,77.43,73.5,74.81,72.63,68.58,66.4,68.54,69.78,67.3,64.82,61.1,59.12,56.15,53.18,50.32,49.44,44.16,36.5,42.4,37.96,37.22,33.68,36.48,35.74,35,35,37.22,37.22,39.44,32.6,34.54,36.48,35.74,34.34,33.68,33.02,31.04,29.72,29.72,29.72,26.16,25.6,29.72,18.3,22.3,21.3,21.8,21.8,20.3,20.8,25.04,25.04,25.6,25.6,25.04,25.6,25.04,25.6,23.92,25.04,21.3,21.8,22.3,21.8,20.8,16.1,20.3,18.3,13.22,19.3,19.3,18.3,14.4,13.86,13.36,12.9,12.48,12.1,11.75,11.43,11.15,10.9,10.67,10.48,10.31,10.16,10.04,9.93,9.85,9.78,9.73,9.69,9.67,9.65,9.65,12.08,8.67,11.7,11.38,10.65,9.84,9.32,9.07,8.85,8.66,8.49,8.35,8.22,8.1,7.98,7.86,7.74,7.61,7.47,7.31,7.14,6.96,6.78,6.58,6.39,6.19,5.99,5.78,5.58,5.39,5.2,5.01,4.83,4.67,4.51,4.37,4.24,4.12,4.02,3.95,3.89,3.85,3.84,4.41,5.77,7.39,8.75,9.32,9.18,9,8.94,8.88,8.83,8.78,8.73,8.68,8.64,8.6,8.56,8.53,8.5,8.47,8.45,8.42,8.4,8.39,8.37,8.36,8.35,8.35,8.34,8.34,8.67,9.65,9.62,9.53,9.4,9.21,8.98,8.7,8.4,8.06,7.69,7.3,6.89,6.47,6.03,5.59,5.14,4.7,4.26,3.83,3.42,3.02,2.65,2.3,1.98,1.7,1.45,1.25,1.09,0.99,0.94,0.92,0.91,0.89,0.87,0.85,0.84,0.82,0.81,0.79,0.78,0.77,0.75,0.74,0.73,0.72,0.71,0.7,0.69,0.68,0.67,0.66,0.65,0.64,0.64,0.63,0.63,0.62,0.62,0.61,0.61,0.61,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.61,0.61,0.61,0.61,0.61,0.61,0.62,0.62,0.62,0.62,0.63,0.63,0.63,0.63,0.63,0.64,0.64,0.64,0.64,0.64,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.65,0.64,0.63,0.62,0.6,0.59,0.57,0.55,0.54,0.53,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.51,0.51,0.51,0.5,0.5,0.49,0.48,0.47,0.47,0.46,0.45,0.45,0.44,0.43,0.42,0.42,0.41,0.41,0.41,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.41,0.42,0.43,0.44,0.46,0.48,0.5,0.53,0.55,0.58,0.61,0.64,0.67,0.7,0.73,0.77,0.8,0.83,0.87,0.9,0.93,0.96,0.99,1.02,1.05,1.08,1.1,1.12,1.14,1.16,1.17,1.18,1.19,1.2,1.2,1.2,1.19,1.17,1.15,1.12,1.09,1.06,1.02,0.98,0.94,0.9,0.86,0.82,0.78,0.74,0.7,0.66,0.63,0.6,0.57,0.55,0.53,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.52,0.51,0.51,0.5,0.5,0.49,0.49,0.48,0.47,0.47,0.47,0.46,0.46,0.45,0.45,0.45,0.44,0.44,0.44,0.43,0.43,0.43,0.42,0.42,0.42,0.41,0.41,0.41,0.41,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.41,0.41,0.41,0.41,0.41,0.41,0.41,0.41,0.41,0.41,0.41,0.41,0.41,0.41,0.41,0.42,0.42,0.42,0.42,0.42,0.42,0.42,0.42,0.42,0.43,0.43,0.43,0.43,0.43,0.43,0.44,0.44,0.44,0.44,0.44,0.44,0.45,0.45,0.45 - ] - }, - { - name:'降雨量', - type:'line', - yAxisIndex:1, - itemStyle: {normal: {areaStyle: {type: 'default'}}}, - data: (function(){ - var oriData = [ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005,0.017,0.017,0.017,0.017,0.011,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.021,0.026,0.03,0.036,0.036,0.195,0.221,0.019,0.013,0.017,0.03,0.03,0.03,0.046,0.045,0.038,0.084,0.045,0.045,0.037,0.034,0.035,0.036,0.044,0.052,0.048,0.109,0.033,0.029,0.04,0.042,0.042,0.042,0.073,0.076,0.062,0.066,0.066,0.075,0.096,0.128,0.121,0.128,0.14,0.226,0.143,0.097,0.018,0,0,0,0,0,0.018,0.047,0.054,0.054,0.054,0.036,0.185,0.009,0.038,0.061,0.077,0.091,0.126,0.69,0.182,0.349,0.231,0.146,0.128,0.167,0.1,0.075,0.071,0.071,0.117,0.01,0.002,0.002,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005,0.026,0.038,0.038,0.038,0.076,0.086,0.109,0.213,0.276,0.288,0.297,0.642,1.799,1.236,2.138,0.921,0.497,0.685,0.828,0.41,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.018,0.024,0.024,0.024,0.024,0.006,0.003,0.046,0.046,0.046,0.046,0.043,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.204,0.303,1.028,1.328,1.524,1.41,1.362,1.292,1.191,0.529,0.501,0.944,1.81,2.899,0.859,0.126,0.087,0.047,0,0,0,0,0.011,0.028,0.028,0.028,0.028,0.017,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.099,0.159,0.297,0.309,0.309,0.614,0.818,1.436,1.195,0.553,0.542,0.955,0.898,0.466,0.386,0.556,0.388,0.221,0.192,0.192,0.187,0.166,0.18,0.302,0.158,0.009,0.009,0.009,0.009,0.009,0.007,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.004,0.032,0.032,0.032,0.032,0.082,0.149,0.204,0.247,0.262,0.49,0.51,0.533,0.746,0.847,2.393,1.188,1.114,0.475,0.043,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.017,0.017,0.021,0.042,0.079,0.111,0.126,0.122,0.133,0.846,0.102,0.077,0.067,0.056,0.005,0,0,0,0,0,0,0,0,0,0,0,0,0,0.011,0.017,0.017,0.017,0.017,0.006,0,0,0,0,0,0.01,0.03,0.054,0.067,0.07,0.25,0.251,0.494,0.065,0.054,0.054,0.064,0.084,0.077,0.101,0.132,0.248,0.069,0.117,0.115,0.087,0.326,0.036,0.009,0.009,0.009,0.009,0.009,0.004,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.02,0.039,0.04,0.04,0.04,0.229,0.079,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.023,0.069,0.082,0.082,0.082,0.503,0.774,0.038,0.012,0.012,0.012,0.016,0.02,0.028,0.051,0.06,0.064,0.19,0.15,0.164,0.139,0.13,0.085,0.031,0.023,0.022,0.007,0.005,0.005,0.001,0,0.02,0.048,0.048,0.053,0.056,0.036,0.008,0.008,0.004,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.013,0.017,0.036,0.068,0.095,0.233,0.272,0.377,0.722,1.494,3.756,0.954,0.439,0.442,0.462,0.373,0.249,0.214,0.1,0.044,0.037,0.023,0.002,0,0,0,0,0,0,0.02,0.024,0.024,0.024,0.024,0.004,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.008,0.017,0.017,0.045,0.186,0.308,0.241,0.241,0.893,4.067,4.494,5.015,3.494,2.057,1.411,0.718,0.407,0.313,0.339,1.537,1.105,0.218,0.136,0.03,0.005,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.037,0.448,1.2,1.309,1.309,1.425,1.223,0.471,0.767,0.423,0.273,0.412,0.646,0.481,0.239,0.131,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.044,0.15,0.223,0.388,0.513,0.883,2.828,4.786,5.959,4.95,6.434,6.319,3.35,2.806,4.204,1.395,1.015,1.015,0.836,0.74,0.72,0.615,0.477,0.192,0.046,0.007,0.007,0.007,0.007,0.007,0.007,0.007,0.008,0.005,0.005,0.005,0.005,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.001,0.012,0.012,0.012,0.012,0.011,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.002,0.012,0.028,0.028,0.028,0.138,0.092,0.082,0.082,0.096,0.719,0.155,0.042,0.047,0.129,0.021,0.021,0.014,0.009,0.029,0.067,0.088,0.095,0.095,0.138,0.091,0.032,0.025,0.025,0.003,0,0,0,0,0,0,0,0,0,0,0,0,0.002,0.045,0.228,0.297,0.325,0.339,0.581,1.244,0.796,0.517,0.227,0.053,0.006,0,0,0,0,0,0,0,0,0,0.003,0.005,0.005,0.005,0.005,0.081,0.129,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.014,0.041,0.041,0.041,0.041,0.027,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.009,0.017,0.017,0.017,0.017,0.355,0.174,0.009,0.009,0.012,0.136,0.208,0.208,0.208,0.215,7.359,1.858,0.458,0.053,0.053,0.047,0.045,0.045,0.059,0.136,0.188,0.206,0.21,0.588,1.517,6.02,4.688,4.42,0.624,0.326,0.359,0.553,0.899,0.94,2.95,9.415,5.752,1.092,0.096,0.035,0.026,0.018,0.015,0.011,0.011,0.011,0,0,0,0,0,0,0,0,0,0,0,0.056,0.27,0.314,0.351,0.354,0.609,0.796,1.857,0.848,0.538,0.214,0.178,0.178,0.201,0.231,0.227,0.272,0.397,0.45,1.014,2.917,1.675,0.081,0.059,0.059,0.148,0.075,0.075,0.078,0.236,0.784,0.784,0.784,0.784,0.741,0.115,0.058,0.058,0.058,0.029,0.015,0.015,0.015,0.015,0.012,0.008,0.604,0.985,1.305,2.273,2.528,2.336,2.496,2.281,1.397,1.713,3.259,1.167,0.745,0.548,1.058,0.684,0.728,0.392,0.179,0.283,0.283,0.46,0.08,0.099,0.099,0.099,0.1,0.143,0.137,0.238,0.317,0.262,0.225,0.792,0.426,0.332,0.261,0.11,0.093,0.102,0.171,0.292,0.504,0.605,1.745,2.485,1.964,0.33,0.171,0.259,0.242,0.215,0.366,0.354,0.205,0.203,0.262,0.153,0.13,0.137,0.362,0.691,0.295,0.433,0.154,0.056,0.053,0.053,0.053,0.051,0.047,0.065,0.078,0.091,0.206,0.813,0.102,0.151,0.05,0.024,0.004,0.001,0,0,0,0.021,0.021,0.021,0.021,0.021,0.013,0.013,0.013,0.013,0.013,0.013,0.013,0.013,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.008,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.018,0.021,0.021,0.021,0.021,0.003,0,0,0,0,0,0,0,0,0,0.024,0.173,0.261,0.267,0.267,0.534,1.354,1.772,0.72,0.218,0.018,0.018,0.028,0.036,0.032,0.194,0.082,0.035,0.286,0.027,0.038,0.038,0.027,0.021,0.014,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.016,0.017,0.017,0.031,0.047,0.043,0.056,0.104,0.149,0.179,0.205,0.328,0.998,0.522,1.851,3.727,3.273,2.204,1.169,1.006,1.179,0.74,0.741,1.065,0.925,0.671,0.497,0.431,0.327,0.277,0.126,0.581,0.207,0.359,2.485,0.038,0.036,0.003,0.003,0.003,0.003,0.004,0.098,0.023,0.021,0.021,0.022,0.041,0.041,0.043,0.045,0.043,0.014,0.014,0.014,0.014,0.014,0.014,0.014,0.031,0.046,0.063,0.119,0.107,0.092,0.085,0.065,0.06,0.054,0.042,0.039,0.046,0.044,0.028,0.028,0.02,0.013,0.013,0.013,0.013,0.016,0.032,0.031,0.031,0.031,0.028,0.011,0.011,0.011,0.011,0.011,0.023,0.024,0.024,0.024,0.019,0.015,0.015,0.015,0.015,0.015,0.015,0.013,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.001,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.011,0.017,0.024,0.026,0.061,0.172,0.206,0.213,0.267,0.511,0.668,0.157,0.017,0.017,0.017,0.046,0.054,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.001,0.017,0.017,0.017,0.017,0.016,0,0,0,0,0,0,0,0,0,0.01,0.017,0.017,0.017,0.017,0.012,0.017,0.017,0.017,0.017,0.012,0,0,0,0,0,0.003,0.031,0.066,0.093,0.112,0.122,0.202,0.068,0.041,0.022,0.011,0,0,0,0,0,0,0,0,0,0,0,0.002,0.005,0.012,0.021,0.021,0.019,0.033,0.03,0.026,0.026,0.034,0.095,0.024,0.024,0.024,0.023,0.019,0.018,0.018,0.018,0.011,0.03,0.045,0.044,0.044,0.044,0.022,0.009,0.024,0.033,0.033,0.033,0.024,0.009,0,0,0,0,0,0,0.003,0.017,0.017,0.017,0.017,0.014,0,0,0,0,0,0.032,0.032,0.032,0.032,0.032,0.005,0.008,0.009,0.014,0.014,0.009,0.005,0.004,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.007,0.009,0.009,0.009,0.009,0.043,0.063,0.084,0.098,0.101,0.213,0.334,0.383,0.43,0.448,0.511,0.801,0.835,1.642,1.614,1.496,1.496,1.476,1.068,0.481,0.22,0.119,0.099,0.07,0.072,0.063,0.076,0.14,0.205,0.28,0.297,0.3,0.479,0.877,1.098,1.611,1.629,1.686,1.686,1.631,1.528,1.862,1.703,1.531,2.196,0.395,0.416,0.453,0.728,0.917,0.986,1.17,2.171,3.011,2.909,3.301,1.377,0.778,0.799,0.947,1.039,0.879,0.76,1.372,1.674,1.674,1.68,1.823,1.793,1.162,0.783,0.216,0.152,0.152,0.152,0.049,0,0,0,0.117,0.127,0.127,0.127,0.127,0.127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.003,0.005,0.005,0.005,0.005,0.003,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.309,0.364,0.364,0.364,0.364,0.063,0.01,0.01,0.01,0.012,0.015,0.015,0.11,0.55,0.824,0.825,0.829,1.39,1.429,1.342,1.43,1.636,1.717,2.135,2.203,3.191,3.022,1.589,0.86,0.807,0.645,0.595,0.588,0.557,0.552,1.271,0.708,0.677,0.629,0.714,0.203,0.133,0.061,0.062,0.018,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.001,0.072,0.29,0.438,0.53,0.557,0.873,1.039,1.04,0.208,0.049,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.03,0.039,0.039,0.039,0.039,0.098,0.008,0.007,0.007,0.007,0.007,0.007,0.007,0.007,0.007,0.007,0.056,0.062,0.065,0.065,0.065,0.047,0.216,0.256,0.315,0.4,0.502,0.449,0.47,0.571,0.814,1.153,0.774,0.202,0.086,0.075,0.071,0.032,0.019,0.003,0.004,0.004,0.004,0.004,0.004,0.004,0.007,0.072,0.153,0.256,0.306,0.404,0.698,0.733,0.823,0.715,0.563,0.404,0.293,0.217,0.213,0.202,0.202,0.294,0.704,0.797,1.359,1.101,0.72,0.514,0.539,0.434,0.389,0.387,0.386,0.375,0.369,0.319,0.239,0.183,0.136,0.062,0.052,0.096,0.119,0.119,0.114,0.127,0.132,0.139,0.169,0.191,0.278,0.254,0.214,0.237,0.221,0.143,0.129,0.125,0.109,0.1,0.087,0.06,0.038,0.029,0.029,0.028,0.048,0.053,0.053,0.111,0.125,0.102,0.097,0.097,0.039,0.02,0.02,0.02,0.014,0.004,0.031,0.043,0.047,0.052,0.08,0.144,0.182,0.176,0.171,0.149,0.112,0.025,0,0,0,0,0,0,0,0.016,0.031,0.031,0.031,0.031,0.015,0,0,0,0,0,0.005,0.005,0.005,0.005,0.005,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005,0.005,0.005,0.005,0.005,0.001,0,0,0 - ]; - var len = oriData.length; - while(len--) { - oriData[len] *= -1; - } - return oriData; - })() - } - ] - } - ] - ,elemarea = $('#LAY-index-area').children('div') - ,renderarea = function(index){ - echarea[index] = echarts.init(elemarea[index], layui.echartsTheme); - echarea[index].setOption(area[index]); - window.onresize = echarea[index].resize; - }; - if(!elemarea[0]) return; - renderarea(0); - - //对数轴 - var echlogline = [], logline = [ - { - title: { - text: "对数轴示例", - x: "center" - }, - tooltip: { - trigger: "item", - formatter: "{a}
                          {b} : {c}" - }, - legend: { - x: 'left', - data: ["2的指数", "3的指数"] - }, - xAxis: [ - { - type: "category", - name: "x", - splitLine: {show: false}, - data: ["一", "二", "三", "四", "五", "六", "七", "八", "九"] - } - ], - yAxis: [ - { - type: "log", - name: "y" - } - ], - calculable: true, - series: [ - { - name: "3的指数", - type: "line", - data: [1, 3, 9, 27, 81, 247, 741, 2223, 6669] - }, - { - name: "2的指数", - type: "line", - data: [1, 2, 4, 8, 16, 32, 64, 128, 256] - } - ] - } - ] - ,elemlogline = $('#LAY-index-logline').children('div') - ,renderlogline = function(index){ - echlogline[index] = echarts.init(elemlogline[index], layui.echartsTheme); - echlogline[index].setOption(logline[index]); - window.onresize = echlogline[index].resize; - }; - if(!elemlogline[0]) return; - renderlogline(0); - }); - - - //柱状图 - layui.use(['echarts'], function(){ - var $ = layui.$ - ,echarts = layui.echarts; - - //标准柱状图 - var echnormcol = [], normcol = [ - { - title : { - text: '某地区蒸发量和降水量', - subtext: '纯属虚构' - }, - tooltip : { - trigger: 'axis' - }, - legend: { - data:['蒸发量','降水量'] - }, - calculable : true, - xAxis : [ - { - type : 'category', - data : ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'] - } - ], - yAxis : [ - { - type : 'value' - } - ], - series : [ - { - name:'蒸发量', - type:'bar', - data:[2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3], - markPoint : { - data : [ - {type : 'max', name: '最大值'}, - {type : 'min', name: '最小值'} - ] - }, - markLine : { - data : [{type : 'average', name: '平均值'}] - } - }, - { - name:'降水量', - type:'bar', - data:[2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3], - markPoint : { - data : [ - {name : '年最高', value : 182.2, xAxis: 7, yAxis: 183, symbolSize:18}, - {name : '年最低', value : 2.3, xAxis: 11, yAxis: 3} - ] - }, - markLine : { - data : [ - {type : 'average', name : '平均值'} - ] - } - } - ] - } - ] - ,elemNormcol = $('#LAY-index-normcol').children('div') - ,renderNormcol = function(index){ - echnormcol[index] = echarts.init(elemNormcol[index], layui.echartsTheme); - echnormcol[index].setOption(normcol[index]); - window.onresize = echnormcol[index].resize; - }; - if(!elemNormcol[0]) return; - renderNormcol(0); - - //堆积柱状图 - var echheapcol = [], heapcol = [ - { - tooltip : { - trigger: 'axis', - axisPointer : { // 坐标轴指示器,坐标轴触发有效 - type : 'shadow' // 默认为直线,可选为:'line' | 'shadow' - } - }, - legend: { - data:['直接访问','邮件营销','联盟广告','视频广告','搜索引擎','百度','谷歌','必应','其他'] - }, - calculable : true, - xAxis : [ - { - type : 'category', - data : ['周一','周二','周三','周四','周五','周六','周日'] - } - ], - yAxis : [ - { - type : 'value' - } - ], - series : [ - { - name:'直接访问', - type:'bar', - data:[320, 332, 301, 334, 390, 330, 320] - }, - { - name:'邮件营销', - type:'bar', - stack: '广告', - data:[120, 132, 101, 134, 90, 230, 210] - }, - { - name:'联盟广告', - type:'bar', - stack: '广告', - data:[220, 182, 191, 234, 290, 330, 310] - }, - { - name:'视频广告', - type:'bar', - stack: '广告', - data:[150, 232, 201, 154, 190, 330, 410] - }, - { - name:'搜索引擎', - type:'bar', - data:[862, 1018, 964, 1026, 1679, 1600, 1570], - markLine : { - itemStyle:{ - normal:{ - lineStyle:{ - type: 'dashed' - } - } - }, - data : [ - [{type : 'min'}, {type : 'max'}] - ] - } - }, - { - name:'百度', - type:'bar', - barWidth : 5, - stack: '搜索引擎', - data:[620, 732, 701, 734, 1090, 1130, 1120] - }, - { - name:'谷歌', - type:'bar', - stack: '搜索引擎', - data:[120, 132, 101, 134, 290, 230, 220] - }, - { - name:'必应', - type:'bar', - stack: '搜索引擎', - data:[60, 72, 71, 74, 190, 130, 110] - }, - { - name:'其他', - type:'bar', - stack: '搜索引擎', - data:[62, 82, 91, 84, 109, 110, 120] - } - ] - } - ] - ,elemHeapcol = $('#LAY-index-heapcol').children('div') - ,renderHeapcol = function(index){ - echheapcol[index] = echarts.init(elemHeapcol[index], layui.echartsTheme); - echheapcol[index].setOption(heapcol[index]); - window.onresize = echheapcol[index].resize; - }; - if(!elemHeapcol[0]) return; - renderHeapcol(0); - - //不等距柱形图 - var echdiffcol = [], diffcol = [ - { - title : { - text: '双数值柱形图', - subtext: '纯属虚构' - }, - tooltip : { - trigger: 'axis', - axisPointer:{ - show: true, - type : 'cross', - lineStyle: { - type : 'dashed', - width : 1 - } - }, - formatter : function (params) { - return params.seriesName + ' : [ ' + params.value[0] + ', ' + params.value[1] + ' ]'; - } - }, - legend: { - data:['数据1','数据2'] - }, - calculable : true, - xAxis : [ - { - type : 'value' - } - ], - yAxis : [ - { - type : 'value', - axisLine: { - lineStyle: { - color: '#dc143c' - } - } - } - ], - series : [ - { - name:'数据1', - type:'bar', - data:[ - [1.5, 10], [5, 7], [8, 8], [12, 6], [11, 12], [16, 9], [14, 6], [17, 4], [19, 9] - ], - markPoint : { - data : [ - // 纵轴,默认 - {type : 'max', name: '最大值',symbol: 'emptyCircle', itemStyle:{normal:{color:'#dc143c',label:{position:'top'}}}}, - {type : 'min', name: '最小值',symbol: 'emptyCircle', itemStyle:{normal:{color:'#dc143c',label:{position:'bottom'}}}}, - // 横轴 - {type : 'max', name: '最大值', valueIndex: 0, symbol: 'emptyCircle', itemStyle:{normal:{color:'#1e90ff',label:{position:'right'}}}}, - {type : 'min', name: '最小值', valueIndex: 0, symbol: 'emptyCircle', itemStyle:{normal:{color:'#1e90ff',label:{position:'left'}}}} - ] - }, - markLine : { - data : [ - // 纵轴,默认 - {type : 'max', name: '最大值', itemStyle:{normal:{color:'#dc143c'}}}, - {type : 'min', name: '最小值', itemStyle:{normal:{color:'#dc143c'}}}, - {type : 'average', name : '平均值', itemStyle:{normal:{color:'#dc143c'}}}, - // 横轴 - {type : 'max', name: '最大值', valueIndex: 0, itemStyle:{normal:{color:'#1e90ff'}}}, - {type : 'min', name: '最小值', valueIndex: 0, itemStyle:{normal:{color:'#1e90ff'}}}, - {type : 'average', name : '平均值', valueIndex: 0, itemStyle:{normal:{color:'#1e90ff'}}} - ] - } - }, - { - name:'数据2', - type:'bar', - barHeight:10, - data:[ - [1, 2], [2, 3], [4, 4], [7, 5], [11, 11], [18, 15] - ] - } - ] - } - ] - ,elemDiffcol = $('#LAY-index-diffcol').children('div') - ,renderDiffcol = function(index){ - echdiffcol[index] = echarts.init(elemDiffcol[index], layui.echartsTheme); - echdiffcol[index].setOption(diffcol[index]); - window.onresize = echdiffcol[index].resize; - }; - if(!elemDiffcol[0]) return; - renderDiffcol(0); - - //彩虹柱形图 - var echcolorline = [], colorline = [ - { - title: { - x: 'center', - text: 'ECharts例子个数统计', - subtext: 'Rainbow bar example', - link: 'http://echarts.baidu.com/doc/example.html' - }, - tooltip: { - trigger: 'item' - }, - calculable: true, - grid: { - borderWidth: 0, - y: 80, - y2: 60 - }, - xAxis: [ - { - type: 'category', - show: false, - data: ['Line', 'Bar', 'Scatter', 'K', 'Pie', 'Radar', 'Chord', 'Force', 'Map', 'Gauge', 'Funnel'] - } - ], - yAxis: [ - { - type: 'value', - show: false - } - ], - series: [ - { - name: 'ECharts例子个数统计', - type: 'bar', - itemStyle: { - normal: { - color: function(params) { - // build a color map as your need. - var colorList = [ - '#C1232B','#B5C334','#FCCE10','#E87C25','#27727B', - '#FE8463','#9BCA63','#FAD860','#F3A43B','#60C0DD', - '#D7504B','#C6E579','#F4E001','#F0805A','#26C0C0' - ]; - return colorList[params.dataIndex] - }, - label: { - show: true, - position: 'top', - formatter: '{b}\n{c}' - } - } - }, - data: [12,21,10,4,12,5,6,5,25,23,7], - markPoint: { - tooltip: { - trigger: 'item', - backgroundColor: 'rgba(0,0,0,0)', - formatter: function(params){ - return ''; - } - }, - data: [ - {xAxis:0, y: 350, name:'Line', symbolSize:20}, - {xAxis:1, y: 350, name:'Bar', symbolSize:20}, - {xAxis:2, y: 350, name:'Scatter', symbolSize:20}, - {xAxis:3, y: 350, name:'K', symbolSize:20}, - {xAxis:4, y: 350, name:'Pie', symbolSize:20}, - {xAxis:5, y: 350, name:'Radar', symbolSize:20}, - {xAxis:6, y: 350, name:'Chord', symbolSize:20}, - {xAxis:7, y: 350, name:'Force', symbolSize:20}, - {xAxis:8, y: 350, name:'Map', symbolSize:20}, - {xAxis:9, y: 350, name:'Gauge', symbolSize:20}, - {xAxis:10, y: 350, name:'Funnel', symbolSize:20}, - ] - } - } - ] - } - ] - ,elemColorline = $('#LAY-index-colorline').children('div') - ,renderColorline = function(index){ - echcolorline[index] = echarts.init(elemColorline[index], layui.echartsTheme); - echcolorline[index].setOption(colorline[index]); - window.onresize = echcolorline[index].resize; - }; - if(!elemColorline[0]) return; - renderColorline(0); - - //标准条形图 - var echnormbar = [], normbar = [ - { - title : { - text: '世界人口总量', - subtext: '数据来自网络' - }, - tooltip : { - trigger: 'axis' - }, - legend: { - data:['2011年', '2012年'] - }, - calculable : true, - xAxis : [ - { - type : 'value', - boundaryGap : [0, 0.01] - } - ], - yAxis : [ - { - type : 'category', - data : ['巴西','印尼','美国','印度','中国','世界人口(万)'] - } - ], - series : [ - { - name:'2011年', - type:'bar', - data:[18203, 23489, 29034, 104970, 131744, 630230] - }, - { - name:'2012年', - type:'bar', - data:[19325, 23438, 31000, 121594, 134141, 681807] - } - ] - } - ] - ,elemNormbar = $('#LAY-index-normbar').children('div') - ,renderNormbar = function(index){ - echnormbar[index] = echarts.init(elemNormbar[index], layui.echartsTheme); - echnormbar[index].setOption(normbar[index]); - window.onresize = echnormbar[index].resize; - }; - if(!elemNormbar[0]) return; - renderNormbar(0); - - //堆积条形图 - var echheapbar = [], heapbar = [ - { - tooltip : { - trigger: 'axis', - axisPointer : { // 坐标轴指示器,坐标轴触发有效 - type : 'shadow' // 默认为直线,可选为:'line' | 'shadow' - } - }, - legend: { - data:['直接访问', '邮件营销','联盟广告','视频广告','搜索引擎'] - }, - calculable : true, - xAxis : [ - { - type : 'value' - } - ], - yAxis : [ - { - type : 'category', - data : ['周一','周二','周三','周四','周五','周六','周日'] - } - ], - series : [ - { - name:'直接访问', - type:'bar', - stack: '总量', - itemStyle : { normal: {label : {show: true, position: 'insideRight'}}}, - data:[320, 302, 301, 334, 390, 330, 320] - }, - { - name:'邮件营销', - type:'bar', - stack: '总量', - itemStyle : { normal: {label : {show: true, position: 'insideRight'}}}, - data:[120, 132, 101, 134, 90, 230, 210] - }, - { - name:'联盟广告', - type:'bar', - stack: '总量', - itemStyle : { normal: {label : {show: true, position: 'insideRight'}}}, - data:[220, 182, 191, 234, 290, 330, 310] - }, - { - name:'视频广告', - type:'bar', - stack: '总量', - itemStyle : { normal: {label : {show: true, position: 'insideRight'}}}, - data:[150, 212, 201, 154, 190, 330, 410] - }, - { - name:'搜索引擎', - type:'bar', - stack: '总量', - itemStyle : { normal: {label : {show: true, position: 'insideRight'}}}, - data:[820, 832, 901, 934, 1290, 1330, 1320] - } - ] - } - ] - ,elemheapbar = $('#LAY-index-heapbar').children('div') - ,renderheapbar = function(index){ - echheapbar[index] = echarts.init(elemheapbar[index], layui.echartsTheme); - echheapbar[index].setOption(heapbar[index]); - window.onresize = echheapbar[index].resize; - }; - if(!elemheapbar[0]) return; - renderheapbar(0); - - //旋风条形图 - var echwindline = [], labelRight = {normal: {label : {position: 'right'}}}, windline = [ - { - title: { - text: '交错正负轴标签', - subtext: 'From ExcelHome', - sublink: 'http://e.weibo.com/1341556070/AjwF2AgQm' - }, - tooltip : { - trigger: 'axis', - axisPointer : { // 坐标轴指示器,坐标轴触发有效 - type : 'shadow' // 默认为直线,可选为:'line' | 'shadow' - } - }, - grid: { - y: 80, - y2: 30 - }, - xAxis : [ - { - type : 'value', - position: 'top', - splitLine: {lineStyle:{type:'dashed'}}, - } - ], - yAxis : [ - { - type : 'category', - axisLine: {show: false}, - axisLabel: {show: false}, - axisTick: {show: false}, - splitLine: {show: false}, - data : ['ten', 'nine', 'eight', 'seven', 'six', 'five', 'four', 'three', 'two', 'one'] - } - ], - series : [ - { - name:'生活费', - type:'bar', - stack: '总量', - itemStyle : { normal: { - color: 'orange', - borderRadius: 5, - label : { - show: true, - position: 'left', - formatter: '{b}' - } - }}, - data:[ - {value:-0.07, itemStyle:labelRight}, - {value:-0.09, itemStyle:labelRight}, - 0.2, 0.44, - {value:-0.23, itemStyle:labelRight}, - 0.08, - {value:-0.17, itemStyle:labelRight}, - 0.47, - {value:-0.36, itemStyle:labelRight}, - 0.18 - ] - } - ] - } - ] - ,elemwindline = $('#LAY-index-windline').children('div') - ,renderwindline = function(index){ - echwindline[index] = echarts.init(elemwindline[index], layui.echartsTheme); - echwindline[index].setOption(windline[index]); - window.onresize = echwindline[index].resize; - }; - if(!elemwindline[0]) return; - renderwindline(0); - }); - - - //地图 - layui.use(['echarts'], function(){ - var $ = layui.$ - ,echarts = layui.echarts; - - var echplat = [], plat = [ - { - title : { - text: '2011全国GDP(亿元)', - subtext: '数据来自国家统计局' - }, - tooltip : { - trigger: 'item' - }, - dataRange: { - orient: 'horizontal', - min: 0, - max: 55000, - text:['高','低'], // 文本,默认为数值文本 - splitNumber:0 - }, - series : [ - { - name: '2011全国GDP分布', - type: 'map', - mapType: 'china', - mapLocation: { - x: 'center' - }, - selectedMode : 'multiple', - itemStyle:{ - normal:{label:{show:true}}, - emphasis:{label:{show:true}} - }, - data:[ - {name:'西藏', value:605.83}, - {name:'青海', value:1670.44}, - {name:'宁夏', value:2102.21}, - {name:'海南', value:2522.66}, - {name:'甘肃', value:5020.37}, - {name:'贵州', value:5701.84}, - {name:'新疆', value:6610.05}, - {name:'云南', value:8893.12}, - {name:'重庆', value:10011.37}, - {name:'吉林', value:10568.83}, - {name:'山西', value:11237.55}, - {name:'天津', value:11307.28}, - {name:'江西', value:11702.82}, - {name:'广西', value:11720.87}, - {name:'陕西', value:12512.3}, - {name:'黑龙江', value:12582}, - {name:'内蒙古', value:14359.88}, - {name:'安徽', value:15300.65}, - {name:'北京', value:16251.93, selected:true}, - {name:'福建', value:17560.18}, - {name:'上海', value:19195.69, selected:true}, - {name:'湖北', value:19632.26}, - {name:'湖南', value:19669.56}, - {name:'四川', value:21026.68}, - {name:'辽宁', value:22226.7}, - {name:'河北', value:24515.76}, - {name:'河南', value:26931.03}, - {name:'浙江', value:32318.85}, - {name:'山东', value:45361.85}, - {name:'江苏', value:49110.27}, - {name:'广东', value:53210.28, selected:true} - ] - } - ] - } - ] - ,elemplat = $('#LAY-index-plat').children('div') - ,renderplat = function(index){ - echplat[index] = echarts.init(elemplat[index], layui.echartsTheme); - echplat[index].setOption(plat[index]); - window.onresize = echplat[index].resize; - }; - if(!elemplat[0]) return; - renderplat(0); - }); - - exports('senior', {}) - -}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/set.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/set.js deleted file mode 100644 index 55233788..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/controller/set.js +++ /dev/null @@ -1,155 +0,0 @@ -/** - - @Name:layuiAdmin 设置 - - - @License: LPPL - - */ - -layui.define(['form', 'upload'], function(exports){ - var $ = layui.$ - ,layer = layui.layer - ,laytpl = layui.laytpl - ,setter = layui.setter - ,view = layui.view - ,admin = layui.admin - ,form = layui.form - ,upload = layui.upload; - - var $body = $('body'); - - form.render(); - - //自定义验证 - form.verify({ - nickname: function(value, item){ //value:表单的值、item:表单的DOM对象 - if(!new RegExp("^[a-zA-Z0-9_\u4e00-\u9fa5\\s·]+$").test(value)){ - return '用户名不能有特殊字符'; - } - if(/(^\_)|(\__)|(\_+$)/.test(value)){ - return '用户名首尾不能出现下划线\'_\''; - } - if(/^\d+\d+\d$/.test(value)){ - return '用户名不能全为数字'; - } - } - - //我们既支持上述函数式的方式,也支持下述数组的形式 - //数组的两个值分别代表:[正则匹配、匹配不符时的提示文字] - ,pass: [ - /^[\S]{6,12}$/ - ,'密码必须6到12位,且不能出现空格' - ] - - //确认密码 - ,repass: function(value){ - if(value !== $('#LAY_password').val()){ - return '两次密码输入不一致'; - } - } - }); - - //网站设置 - form.on('submit(set_website)', function(obj){ - layer.msg(JSON.stringify(obj.field)); - - //提交修改 - /* - admin.req({ - url: '' - ,data: obj.field - ,success: function(){ - - } - }); - */ - return false; - }); - - //邮件服务 - form.on('submit(set_system_email)', function(obj){ - layer.msg(JSON.stringify(obj.field)); - - //提交修改 - /* - admin.req({ - url: '' - ,data: obj.field - ,success: function(){ - - } - }); - */ - return false; - }); - - - //设置我的资料 - form.on('submit(setmyinfo)', function(obj){ - layer.msg(JSON.stringify(obj.field)); - - //提交修改 - /* - admin.req({ - url: '' - ,data: obj.field - ,success: function(){ - - } - }); - */ - return false; - }); - - //上传头像 - var avatarSrc = $('#LAY_avatarSrc'); - upload.render({ - url: '/api/upload/' - ,elem: '#LAY_avatarUpload' - ,done: function(res){ - if(res.status == 0){ - avatarSrc.val(res.url); - } else { - layer.msg(res.msg, {icon: 5}); - } - } - }); - - //查看头像 - admin.events.avartatPreview = function(othis){ - var src = avatarSrc.val(); - layer.photos({ - photos: { - "title": "查看头像" //相册标题 - ,"data": [{ - "src": src //原图地址 - }] - } - ,shade: 0.01 - ,closeBtn: 1 - ,anim: 5 - }); - }; - - - //设置密码 - form.on('submit(setmypass)', function(obj){ - layer.msg(JSON.stringify(obj.field)); - - //提交修改 - /* - admin.req({ - url: '' - ,data: obj.field - ,success: function(){ - - } - }); - */ - return false; - }); - - //对外暴露的接口 - exports('set', {}); -}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/user.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/user.js deleted file mode 100644 index bb433e40..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/controller/user.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - - @Name:layuiAdmin 用户登入和注册等 - - - @License: LPPL - - */ - -layui.define('form', function(exports){ - var $ = layui.$ - ,layer = layui.layer - ,laytpl = layui.laytpl - ,setter = layui.setter - ,view = layui.view - ,admin = layui.admin - ,form = layui.form; - - var $body = $('body'); - - //自定义验证 - form.verify({ - nickname: function(value, item){ //value:表单的值、item:表单的DOM对象 - if(!new RegExp("^[a-zA-Z0-9_\u4e00-\u9fa5\\s·]+$").test(value)){ - return '用户名不能有特殊字符'; - } - if(/(^\_)|(\__)|(\_+$)/.test(value)){ - return '用户名首尾不能出现下划线\'_\''; - } - if(/^\d+\d+\d$/.test(value)){ - return '用户名不能全为数字'; - } - } - - //我们既支持上述函数式的方式,也支持下述数组的形式 - //数组的两个值分别代表:[正则匹配、匹配不符时的提示文字] - ,pass: [ - /^[\S]{6,12}$/ - ,'密码必须6到12位,且不能出现空格' - ] - }); - - - //更换图形验证码 - $body.on('click', '#LAY-user-get-vercode', function(){ - var othis = $(this); - this.src = 'https://www.oschina.net/action/user/captcha?t='+ new Date().getTime() - }); - - //对外暴露的接口 - exports('user', {}); -}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/useradmin.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/useradmin.js deleted file mode 100644 index 1eaf315f..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/controller/useradmin.js +++ /dev/null @@ -1,184 +0,0 @@ -/** - - @Name:layuiAdmin 用户管理 管理员管理 角色管理 - @Author:star1029 - - @License:LPPL - - */ - - -layui.define(['table', 'form'], function(exports){ - var $ = layui.$ - ,admin = layui.admin - ,view = layui.view - ,table = layui.table - ,form = layui.form; - - //用户管理 - table.render({ - elem: '#LAY-user-manage' - ,url: './json/useradmin/webuser.js' //模拟接口 - ,cols: [[ - {type: 'checkbox', fixed: 'left'} - ,{field: 'id', width: 100, title: 'ID', sort: true} - ,{field: 'username', title: '用户名', minWidth: 100} - ,{field: 'avatar', title: '头像', width: 100, templet: '#imgTpl'} - ,{field: 'phone', title: '手机'} - ,{field: 'email', title: '邮箱'} - ,{field: 'sex', width: 80, title: '性别'} - ,{field: 'ip', title: 'IP'} - ,{field: 'jointime', title: '加入时间', sort: true} - ,{title: '操作', width: 150, align:'center', fixed: 'right', toolbar: '#table-useradmin-webuser'} - ]] - ,page: true - ,limit: 30 - ,height: 'full-320' - ,text: '对不起,加载出现异常!' - }); - - //工具条 - table.on('tool(LAY-user-manage)', function(obj){ - var data = obj.data; - if(obj.event === 'del'){ - layer.prompt({ - formType: 1 - ,title: '敏感操作,请验证口令' - }, function(value, index){ - layer.close(index); - - layer.confirm('真的删除行么', function(index){ - obj.del(); - layer.close(index); - }); - }); - } else if(obj.event === 'edit'){ - admin.popup({ - title: '编辑用户' - ,area: ['500px', '450px'] - ,id: 'LAY-popup-user-add' - ,success: function(layero, index){ - view(this.id).render('user/user/userform', data).done(function(){ - form.render(null, 'layuiadmin-form-useradmin'); - - //提交 - form.on('submit(LAY-user-front-submit)', function(data){ - var field = data.field; //获取提交的字段 - - //提交 Ajax 成功后,关闭当前弹层并重载表格 - //$.ajax({}); - layui.table.reload('LAY-user-manage'); //重载表格 - layer.close(index); //执行关闭 - }); - }); - } - }); - } - }); - - //管理员管理 - table.render({ - elem: '#LAY-user-back-manage' - ,url: './json/useradmin/mangadmin.js' //模拟接口 - ,cols: [[ - {type: 'checkbox', fixed: 'left'} - ,{field: 'id', width: 80, title: 'ID', sort: true} - ,{field: 'loginname', title: '登录名'} - ,{field: 'telphone', title: '手机'} - ,{field: 'email', title: '邮箱'} - ,{field: 'role', title: '角色'} - ,{field: 'jointime', title: '加入时间', sort: true} - ,{field: 'check', title:'审核状态', templet: '#buttonTpl', minWidth: 80, align: 'center'} - ,{title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#table-useradmin-admin'} - ]] - ,text: '对不起,加载出现异常!' - }); - - //工具条 - table.on('tool(LAY-user-back-manage)', function(obj){ - var data = obj.data; - if(obj.event === 'del'){ - layer.prompt({ - formType: 1 - ,title: '敏感操作,请验证口令' - }, function(value, index){ - layer.close(index); - layer.confirm('确定删除此管理员?', function(index){ - console.log(obj) - obj.del(); - layer.close(index); - }); - }); - }else if(obj.event === 'edit'){ - admin.popup({ - title: '编辑管理员' - ,area: ['420px', '450px'] - ,id: 'LAY-popup-user-add' - ,success: function(layero, index){ - view(this.id).render('user/administrators/adminform', data).done(function(){ - form.render(null, 'layuiadmin-form-admin'); - - //提交 - form.on('submit(LAY-user-back-submit)', function(data){ - var field = data.field; //获取提交的字段 - - //提交 Ajax 成功后,关闭当前弹层并重载表格 - //$.ajax({}); - layui.table.reload('LAY-user-back-manage'); //重载表格 - layer.close(index); //执行关闭 - }); - }); - } - }); - } - }); - - //角色管理 - table.render({ - elem: '#LAY-user-back-role' - ,url: './json/useradmin/role.js' //模拟接口 - ,cols: [[ - {type: 'checkbox', fixed: 'left'} - ,{field: 'id', width: 80, title: 'ID', sort: true} - ,{field: 'rolename', title: '角色名'} - ,{field: 'limits', title: '拥有权限'} - ,{field: 'descr', title: '具体描述'} - ,{title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#table-useradmin-admin'} - ]] - ,text: '对不起,加载出现异常!' - }); - - //工具条 - table.on('tool(LAY-user-back-role)', function(obj){ - var data = obj.data; - if(obj.event === 'del'){ - layer.confirm('确定删除此角色?', function(index){ - obj.del(); - layer.close(index); - }); - }else if(obj.event === 'edit'){ - admin.popup({ - title: '添加新角色' - ,area: ['500px', '480px'] - ,id: 'LAY-popup-user-add' - ,success: function(layero, index){ - view(this.id).render('user/administrators/roleform', data).done(function(){ - form.render(null, 'layuiadmin-form-role'); - - //提交 - form.on('submit(LAY-user-role-submit)', function(data){ - var field = data.field; //获取提交的字段 - - //提交 Ajax 成功后,关闭当前弹层并重载表格 - //$.ajax({}); - layui.table.reload('LAY-user-back-role'); //重载表格 - layer.close(index); //执行关闭 - }); - }); - } - }); - } - }); - - exports('useradmin', {}) -}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/controller/workorder.js b/iot-server/server-starter/src/main/webapp/assets/src/controller/workorder.js deleted file mode 100644 index 3e94d8ac..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/controller/workorder.js +++ /dev/null @@ -1,70 +0,0 @@ -/** - - @Name:layuiAdmin 工单系统 - @Author:star1029 - - @License:GPL-2 - - */ - - -layui.define(['table', 'form', 'element'], function(exports){ - var $ = layui.$ - ,admin = layui.admin - ,view = layui.view - ,table = layui.table - ,form = layui.form - ,element = layui.element; - - table.render({ - elem: '#LAY-app-workorder' - ,url: './json/workorder/demo.js' //模拟接口 - ,cols: [[ - {type: 'numbers', fixed: 'left'} - ,{field: 'orderid', width: 100, title: '工单号', sort: true} - ,{field: 'attr', width: 100, title: '业务性质'} - ,{field: 'title', width: 100, title: '工单标题', width: 300} - ,{field: 'progress', title: '进度', width: 200, align: 'center', templet: '#progressTpl'} - ,{field: 'submit', width: 100, title: '提交者'} - ,{field: 'accept', width: 100, title: '受理人员'} - ,{field: 'state', title: '工单状态', templet: '#buttonTpl', minWidth: 80, align: 'center'} - ,{title: '操作', align: 'center', fixed: 'right', toolbar: '#table-system-order'} - ]] - ,page: true - ,limit: 10 - ,limits: [10, 15, 20, 25, 30] - ,text: '对不起,加载出现异常!' - ,done: function(){ - element.render('progress'); - } - }); - - //工具条 - table.on('tool(LAY-app-workorder)', function(obj){ - var data = obj.data; - if(obj.event === 'edit'){ - admin.popup({ - title: '编辑工单' - ,area: ['450px', '450px'] - ,id: 'LAY-popup-workorder-add' - ,success: function(layero, index){ - view(this.id).render('app/workorder/listform').done(function(){ - form.render(null, 'layuiadmin-form-workorder'); - - //提交 - form.on('submit(LAY-app-workorder-submit)', function(data){ - var field = data.field; //获取提交的字段 - - //提交 Ajax 成功后,关闭当前弹层并重载表格 - //$.ajax({}); - layui.table.reload('LAY-app-workorder'); //重载表格 - layer.close(index); //执行关闭 - }); - }); - } - }); - } - }); - - exports('workorder', {}) -}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/index.js b/iot-server/server-starter/src/main/webapp/assets/src/index.js deleted file mode 100644 index 44c0aea0..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/index.js +++ /dev/null @@ -1,213 +0,0 @@ -/*! - * 界面入口模块 - */ - -layui.extend({ - setter: 'config' //配置文件 - , admin: 'lib/admin' //核心模块 - , view: 'lib/view' //核心模块 -}).define(['setter', 'admin'], function (exports) { - var setter = layui.setter - , element = layui.element - , admin = layui.admin - , tabsPage = admin.tabsPage - , view = layui.view - - //根据路由渲染页面 - , renderPage = function () { - var router = layui.router() - , path = router.path - , pathURL = admin.correctRouter(router.path.join('/')) - - - //默认读取主页 - if (!path.length) path = ['']; - - //如果最后一项为空字符,则读取默认文件 - if (path[path.length - 1] === '') { - path[path.length - 1] = setter.entry; - } - - /* - layui.config({ - base: setter.base + 'controller/' - }); - */ - - //重置状态 - var reset = function (type) { - //renderPage.haveInit && layer.closeAll(); - if (renderPage.haveInit) { - $('.layui-layer').each(function () { - var othis = $(this), - index = othis.attr('times'); - if (!(othis.hasClass('layui-layim') || othis.hasClass('layui-layim-chat'))) { - layer.close(index); - } - }); - } - renderPage.haveInit = true; - - $(APP_BODY).scrollTop(0); - delete tabsPage.type; //重置页面标签的来源类型 - }; - - //如果路由来自于 tab 切换,则不重新请求视图 - if (tabsPage.type === 'tab') { - //切换到非主页、或者切换到主页且主页必须有内容。方可阻止请求 - if (pathURL !== '/' || (pathURL === '/' && admin.tabsBody().html())) { - admin.tabsBodyChange(tabsPage.index); - return reset(tabsPage.type); - } - } - - //请求视图渲染 - view().render(path.join('/')).then(function (res) { - - //遍历页签选项卡 - var matchTo - , tabs = $('#LAY_app_tabsheader>li'); - - tabs.each(function (index) { - var li = $(this) - , layid = li.attr('lay-id'); - - if (layid === pathURL) { - matchTo = true; - tabsPage.index = index; - } - }); - - //如果未在选项卡中匹配到,则追加选项卡 - if (setter.pageTabs && pathURL !== '/') { - if (!matchTo) { - $(APP_BODY).append('
                          '); - tabsPage.index = tabs.length; - element.tabAdd(FILTER_TAB_TBAS, { - title: '' + (res.title || '新标签页') + '' - , id: pathURL - , attr: router.href - }); - } - } - - this.container = admin.tabsBody(tabsPage.index); - setter.pageTabs || this.container.scrollTop(0); //如果不开启标签页,则跳转时重置滚动条 - - //定位当前tabs - element.tabChange(FILTER_TAB_TBAS, pathURL); - admin.tabsBodyChange(tabsPage.index); - - }).done(function () { - layui.use('common', layui.cache.callback.common); - $win.on('resize', layui.data.resize); - - element.render('breadcrumb', 'breadcrumb'); - - //容器 scroll 事件,剔除吸附层 - admin.tabsBody(tabsPage.index).on('scroll', function () { - var othis = $(this) - , elemDate = $('.layui-laydate') - , layerOpen = $('.layui-layer')[0]; - - //关闭 layDate - if (elemDate[0]) { - elemDate.each(function () { - var thisElemDate = $(this); - thisElemDate.hasClass('layui-laydate-static') || thisElemDate.remove(); - }); - othis.find('input').blur(); - } - - //关闭 Tips 层 - layerOpen && layer.closeAll('tips'); - }); - }); - - reset(); - } - - //入口页面 - , entryPage = function (fn) { - var router = layui.router() - , container = view(setter.container) - , pathURL = admin.correctRouter(router.path.join('/')) - , isIndPage; - - //检查是否属于独立页面 - layui.each(setter.indPage, function (index, item) { - if (pathURL === item) { - return isIndPage = true; - } - }); - - //将模块根路径设置为 controller 目录 - layui.config({ - base: setter.base + 'controller/' - }); - - //独立页面 - if (isIndPage || pathURL === '/user/login') { //此处单独判断登入页,是为了兼容旧版(即未在 config.js 配置 indPage 的情况) - container.render(router.path.join('/')).done(function () { - admin.pageType = 'alone'; - }); - } else { //后台框架页面 - - //强制拦截未登入 - if (setter.interceptor) { - var local = layui.data(setter.tableName); - if (!local[setter.request.tokenName]) { - return location.hash = '/user/login/redirect=' + encodeURIComponent(pathURL); //跳转到登入页 - } - } - - //渲染后台结构 - if (admin.pageType === 'console') { //后台主体页 - renderPage(); - } else { //初始控制台结构 - container.render('layout').done(function () { - renderPage(); - layui.element.render(); - - if (admin.screen() < 2) { - admin.sideFlexible(); - } - admin.pageType = 'console'; - }); - } - - } - } - - , APP_BODY = '#LAY_app_body', FILTER_TAB_TBAS = 'layadmin-layout-tabs' - , $ = layui.$, $win = $(window); - - //初始主体结构 - layui.link( - setter.base + 'style/admin.css?v=' + (admin.v + '-1') - , function () { - entryPage() - } - , 'layuiAdmin' - ); - - //Hash改变 - window.onhashchange = function () { - entryPage(); - //执行 {setter.MOD_NAME}.hash 下的事件 - layui.event.call(this, setter.MOD_NAME, 'hash({*})', layui.router()); - }; - - //扩展 lib 目录下的其它模块 - layui.each(setter.extend, function (key, value) { - var mods = {} - , _isArray = setter.extend.constructor === Array; - mods[_isArray ? value : key] = '{/}' + setter.base + 'lib/extend/' + value; - layui.extend(mods); - }); - - //对外输出 - exports('index', { - render: renderPage - }); -}); diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/admin.js b/iot-server/server-starter/src/main/webapp/assets/src/lib/admin.js deleted file mode 100644 index ea81176d..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/lib/admin.js +++ /dev/null @@ -1,861 +0,0 @@ - -/*! - * 界面核心模块 - */ - -layui.define(['view', 'table', 'upload'], function(exports){ - var $ = layui.jquery - ,laytpl = layui.laytpl - ,element = layui.element - ,table = layui.table - ,upload = layui.upload - ,setter = layui.setter - ,view = layui.view - ,device = layui.device() - - ,$win = $(window), $body = $('body') - ,container = $('#'+ setter.container) - - ,SHOW = 'layui-show', HIDE = 'layui-hide', THIS = 'layui-this', DISABLED = 'layui-disabled', TEMP = 'template' - ,APP_BODY = '#LAY_app_body', APP_FLEXIBLE = 'LAY_app_flexible' - ,FILTER_TAB_TBAS = 'layadmin-layout-tabs' - ,APP_SPREAD_SM = 'layadmin-side-spread-sm', TABS_BODY = 'layadmin-tabsbody-item' - ,ICON_SHRINK = 'layui-icon-shrink-right', ICON_SPREAD = 'layui-icon-spread-left' - ,SIDE_SHRINK = 'layadmin-side-shrink', SIDE_MENU = 'LAY-system-side-menu' - - //通用方法 - ,admin = { - v: '1.7.2 pro' - - //数据的异步请求 - ,req: view.req - - //清除本地 token,并跳转到登入页 - ,exit: view.exit - - //xss 转义 - ,escape: function(html){ - return String(html || '').replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&') - .replace(//g, '>') - .replace(/'/g, ''').replace(/"/g, '"'); - } - - //事件 - ,on: function(events, callback){ - return layui.onevent.call(this, setter.MOD_NAME, events, callback); - } - - //弹出面板 - ,popup: view.popup - - //右侧面板 - ,popupRight: function(options){ - //layer.close(admin.popup.index); - return admin.popup.index = layer.open($.extend({ - type: 1 - ,id: 'LAY_adminPopupR' - ,anim: -1 - ,title: false - ,closeBtn: false - ,offset: 'r' - ,shade: 0.1 - ,shadeClose: true - ,skin: 'layui-anim layui-anim-rl layui-layer-adminRight' - ,area: '300px' - }, options)); - } - - //发送验证码 - ,sendAuthCode: function(options){ - options = $.extend({ - seconds: 60 - ,elemPhone: '#LAY_phone' - ,elemVercode: '#LAY_vercode' - }, options); - - var seconds = options.seconds - ,token = null - ,timer, countDown = function(loop){ - var btn = $(options.elem) - seconds--; - if(seconds < 0){ - btn.removeClass(DISABLED).html('获取验证码'); - seconds = options.seconds; - clearInterval(timer); - } else { - btn.addClass(DISABLED).html(seconds + '秒后重获'); - } - - if(!loop){ - timer = setInterval(function(){ - countDown(true); - }, 1000); - } - }; - - $body.off('click', options.elem).on('click', options.elem, function(){ - options.elemPhone = $(options.elemPhone); - options.elemVercode = $(options.elemVercode); - - var elemPhone = options.elemPhone - ,value = elemPhone.val(); - - if(seconds !== options.seconds || $(this).hasClass(DISABLED)) return; - - if(!/^1\d{10}$/.test(value)){ - elemPhone.focus(); - return layer.msg('请输入正确的手机号') - }; - - if(typeof options.ajax === 'object'){ - var success = options.ajax.success; - delete options.ajax.success; - } - - admin.req($.extend(true, { - url: '/auth/code' - ,type: 'get' - ,data: { - phone: value - } - ,success: function(res){ - layer.msg('验证码已发送至你的手机,请注意查收', { - icon: 1 - ,shade: 0 - }); - options.elemVercode.focus(); - countDown(); - success && success(res); - } - }, options.ajax)); - }); - } - - //屏幕类型 - ,screen: function(){ - var width = $win.width(); - if(width > 1200){ - return 3; //大屏幕 - } else if(width > 992){ - return 2; //中屏幕 - } else if(width > 768){ - return 1; //小屏幕 - } else { - return 0; //超小屏幕 - } - } - - //侧边伸缩 - ,sideFlexible: function(status){ - var app = container - ,iconElem = $('#'+ APP_FLEXIBLE) - ,screen = admin.screen(); - - //设置状态,PC:默认展开、移动:默认收缩 - if(status === 'spread'){ - //切换到展开状态的 icon,箭头:← - iconElem.removeClass(ICON_SPREAD).addClass(ICON_SHRINK); - - //移动:从左到右位移;PC:清除多余选择器恢复默认 - if(screen < 2){ - app.addClass(APP_SPREAD_SM); - } else { - app.removeClass(APP_SPREAD_SM); - } - - app.removeClass(SIDE_SHRINK) - } else { - //切换到搜索状态的 icon,箭头:→ - iconElem.removeClass(ICON_SHRINK).addClass(ICON_SPREAD); - - //移动:清除多余选择器恢复默认;PC:从右往左收缩 - if(screen < 2){ - app.removeClass(SIDE_SHRINK); - } else { - app.addClass(SIDE_SHRINK); - } - - app.removeClass(APP_SPREAD_SM) - } - - layui.event.call(this, setter.MOD_NAME, 'side({*})', { - status: status - }); - } - - //重置主体区域表格尺寸 - ,resizeTable: function(delay){ - var that = this, runResizeTable = function(){ - that.tabsBody(admin.tabsPage.index).find('.layui-table-view').each(function(){ - var tableID = $(this).attr('lay-id'); - layui.table.resize(tableID); - }); - }; - if(!layui.table) return; - delay ? setTimeout(runResizeTable, delay) : runResizeTable(); - } - - //主题设置 - ,theme: function(options){ - var theme = setter.theme - ,local = layui.data(setter.tableName) - ,id = 'LAY_layadmin_theme' - ,style = document.createElement('style') - ,styleText = laytpl([ - //主题色 - '.layui-side-menu,' - ,'.layadmin-pagetabs .layui-tab-title li:after,' - ,'.layadmin-pagetabs .layui-tab-title li.layui-this:after,' - ,'.layui-layer-admin .layui-layer-title,' - ,'.layadmin-side-shrink .layui-side-menu .layui-nav>.layui-nav-item>.layui-nav-child' - ,'{background-color:{{d.color.main}} !important;}' - - //选中色 - ,'.layui-nav-tree .layui-this,' - ,'.layui-nav-tree .layui-this>a,' - ,'.layui-nav-tree .layui-nav-child dd.layui-this,' - ,'.layui-nav-tree .layui-nav-child dd.layui-this a' - ,'{background-color:{{d.color.selected}} !important;}' - - //logo - ,'.layui-layout-admin .layui-logo{background-color:{{d.color.logo || d.color.main}} !important;}' - - //头部色 - ,'{{# if(d.color.header){ }}' - ,'.layui-layout-admin .layui-header{background-color:{{ d.color.header }};}' - ,'.layui-layout-admin .layui-header a,' - ,'.layui-layout-admin .layui-header a cite{color: #f8f8f8;}' - ,'.layui-layout-admin .layui-header a:hover{color: #fff;}' - ,'.layui-layout-admin .layui-header .layui-nav .layui-nav-more{border-top-color: #fbfbfb;}' - ,'.layui-layout-admin .layui-header .layui-nav .layui-nav-mored{border-color: transparent; border-bottom-color: #fbfbfb;}' - ,'.layui-layout-admin .layui-header .layui-nav .layui-this:after, .layui-layout-admin .layui-header .layui-nav-bar{background-color: #fff; background-color: rgba(255,255,255,.5);}' - ,'.layadmin-pagetabs .layui-tab-title li:after{display: none;}' - ,'{{# } }}' - ].join('')).render(options = $.extend({}, local.theme, options)) - ,styleElem = document.getElementById(id); - - //添加主题样式 - if('styleSheet' in style){ - style.setAttribute('type', 'text/css'); - style.styleSheet.cssText = styleText; - } else { - style.innerHTML = styleText; - } - style.id = id; - - styleElem && $body[0].removeChild(styleElem); - $body[0].appendChild(style); - $body.attr('layadmin-themealias', options.color.alias); - - //本地存储记录 - local.theme = local.theme || {}; - layui.each(options, function(key, value){ - local.theme[key] = value; - }); - layui.data(setter.tableName, { - key: 'theme' - ,value: local.theme - }); - } - - //初始化主题 - ,initTheme: function(index){ - var theme = setter.theme; - index = index || 0; - if(theme.color[index]){ - theme.color[index].index = index; - admin.theme({ - color: theme.color[index] - }); - } - } - - //记录最近一次点击的页面标签数据 - ,tabsPage: {} - - //获取标签页的头元素 - ,tabsHeader: function(index){ - return $('#LAY_app_tabsheader').children('li').eq(index || 0); - } - - //获取页面标签主体元素 - ,tabsBody: function(index){ - return $(APP_BODY).find('.'+ TABS_BODY).eq(index || 0); - } - - //切换页面标签主体 - ,tabsBodyChange: function(index){ - admin.tabsHeader(index).attr('lay-attr', layui.router().href); - admin.tabsBody(index).addClass(SHOW).siblings().removeClass(SHOW); - events.rollPage('auto', index); - } - - //resize事件管理 - ,resize: function(fn){ - var router = layui.router() - ,key = router.path.join('-'); - - if(admin.resizeFn[key]){ - $win.off('resize', admin.resizeFn[key]); - delete admin.resizeFn[key]; - } - - if(fn === 'off') return; //如果是清除 resize 事件,则终止往下执行 - - fn(), admin.resizeFn[key] = fn; - $win.on('resize', admin.resizeFn[key]); - } - ,resizeFn: {} - ,runResize: function(){ - var router = layui.router() - ,key = router.path.join('-'); - admin.resizeFn[key] && admin.resizeFn[key](); - } - ,delResize: function(){ - this.resize('off'); - } - - //关闭当前 pageTabs - ,closeThisTabs: function(){ - if(!admin.tabsPage.index) return; - $(TABS_HEADER).eq(admin.tabsPage.index).find('.layui-tab-close').trigger('click'); - } - - //全屏 - ,fullScreen: function(){ - var ele = document.documentElement - ,reqFullScreen = ele.requestFullScreen || ele.webkitRequestFullScreen - || ele.mozRequestFullScreen || ele.msRequestFullscreen; - if(typeof reqFullScreen !== 'undefined' && reqFullScreen) { - reqFullScreen.call(ele); - }; - } - - //退出全屏 - ,exitScreen: function(){ - var ele = document.documentElement - if (document.exitFullscreen) { - document.exitFullscreen(); - } else if (document.mozCancelFullScreen) { - document.mozCancelFullScreen(); - } else if (document.webkitCancelFullScreen) { - document.webkitCancelFullScreen(); - } else if (document.msExitFullscreen) { - document.msExitFullscreen(); - } - } - - //纠正单页路由格式 - ,correctRouter: function(href){ - if(!/^\//.test(href)) href = '/' + href; - - //纠正首尾 - return href.replace(/^(\/+)/, '/') - .replace(new RegExp('\/' + setter.entry + '$'), '/'); //过滤路由最后的默认视图文件名(如:index) - } - - //…… - }; - - //事件 - var events = admin.events = { - //伸缩 - flexible: function(othis){ - var iconElem = othis.find('#'+ APP_FLEXIBLE) - ,isSpread = iconElem.hasClass(ICON_SPREAD); - admin.sideFlexible(isSpread ? 'spread' : null); //控制伸缩 - admin.resizeTable(350); - } - - //刷新 - ,refresh: function(){ - layui.index.render(); - } - - //输入框搜索 - ,serach: function(othis){ - othis.off('keypress').on('keypress',function(e){ - if(!this.value.replace(/\s/g, '')) return; - //回车跳转 - if(e.keyCode === 13){ - var href = othis.attr('lay-action') - ,text = othis.attr('lay-text') || '搜索'; - - href = href + this.value; - text = text + ' '+ admin.escape(this.value) +''; - - //打开标签页 - location.hash = admin.correctRouter(href) - - //如果搜索关键词已经打开,则刷新页面即可 - events.serach.keys || (events.serach.keys = {}); - events.serach.keys[admin.tabsPage.index] = this.value; - if(this.value === events.serach.keys[admin.tabsPage.index]){ - events.refresh(othis); - } - - //清空输入框 - this.value = ''; - } - }); - } - - //点击消息 - ,message: function(othis){ - othis.find('.layui-badge-dot').remove(); - } - - //弹出主题面板 - ,theme: function(){ - admin.popupRight({ - id: 'LAY_adminPopupTheme' - ,success: function(){ - view(this.id).render('system/theme') - } - }); - } - - //便签 - ,note: function(othis){ - var mobile = admin.screen() < 2 - ,note = layui.data(setter.tableName).note; - - events.note.index = admin.popup({ - title: '便签' - ,shade: 0 - ,offset: [ - '41px' - ,(mobile ? null : (othis.offset().left - 250) + 'px') - ] - ,anim: -1 - ,id: 'LAY_adminNote' - ,skin: 'layadmin-note layui-anim layui-anim-upbit' - ,content: '' - ,resize: false - ,success: function(layero, index){ - var textarea = layero.find('textarea') - ,value = note === undefined ? '便签中的内容会存储在本地,这样即便你关掉了浏览器,在下次打开时,依然会读取到上一次的记录。是个非常小巧实用的本地备忘录' : note; - - textarea.val(value).focus().on('keyup', function(){ - layui.data(setter.tableName, { - key: 'note' - ,value: this.value - }); - }); - } - }) - } - - //全屏 - ,fullscreen: function(othis){ - var SCREEN_FULL = 'layui-icon-screen-full' - ,SCREEN_REST = 'layui-icon-screen-restore' - ,iconElem = othis.children("i"); - - if(iconElem.hasClass(SCREEN_FULL)){ - admin.fullScreen(); - iconElem.addClass(SCREEN_REST).removeClass(SCREEN_FULL); - } else { - admin.exitScreen(); - iconElem.addClass(SCREEN_FULL).removeClass(SCREEN_REST); - } - } - - //弹出关于面板 - ,about: function(){ - admin.popupRight({ - id: 'LAY_adminPopupAbout' - ,success: function(){ - view(this.id).render('system/about') - } - }); - } - - //弹出更多面板 - ,more: function(){ - admin.popupRight({ - id: 'LAY_adminPopupMore' - ,success: function(){ - view(this.id).render('system/more') - } - }); - } - - //返回上一页 - ,back: function(){ - history.back(); - } - - //主题设置 - ,setTheme: function(othis){ - var index = othis.data('index') - ,nextIndex = othis.siblings('.layui-this').data('index'); - - if(othis.hasClass(THIS)) return; - - othis.addClass(THIS).siblings('.layui-this').removeClass(THIS); - admin.initTheme(index); - } - - //左右滚动页面标签 - ,rollPage: function(type, index){ - var tabsHeader = $('#LAY_app_tabsheader') - ,liItem = tabsHeader.children('li') - ,scrollWidth = tabsHeader.prop('scrollWidth') - ,outerWidth = tabsHeader.outerWidth() - ,tabsLeft = parseFloat(tabsHeader.css('left')); - - //右左往右 - if(type === 'left'){ - if(!tabsLeft && tabsLeft <=0) return; - - //当前的left减去可视宽度,用于与上一轮的页标比较 - var prefLeft = -tabsLeft - outerWidth; - - liItem.each(function(index, item){ - var li = $(item) - ,left = li.position().left; - - if(left >= prefLeft){ - tabsHeader.css('left', -left); - return false; - } - }); - } else if(type === 'auto'){ //自动滚动 - (function(){ - var thisLi = liItem.eq(index), thisLeft; - - if(!thisLi[0]) return; - thisLeft = thisLi.position().left; - - //当目标标签在可视区域左侧时 - if(thisLeft < -tabsLeft){ - return tabsHeader.css('left', -thisLeft); - } - - //当目标标签在可视区域右侧时 - if(thisLeft + thisLi.outerWidth() >= outerWidth - tabsLeft){ - var subLeft = thisLeft + thisLi.outerWidth() - (outerWidth - tabsLeft); - liItem.each(function(i, item){ - var li = $(item) - ,left = li.position().left; - - //从当前可视区域的最左第二个节点遍历,如果减去最左节点的差 > 目标在右侧不可见的宽度,则将该节点放置可视区域最左 - if(left + tabsLeft > 0){ - if(left - tabsLeft > subLeft){ - tabsHeader.css('left', -left); - return false; - } - } - }); - } - }()); - } else { - //默认向左滚动 - liItem.each(function(i, item){ - var li = $(item) - ,left = li.position().left; - - if(left + li.outerWidth() >= outerWidth - tabsLeft){ - tabsHeader.css('left', -left); - return false; - } - }); - } - } - - //向右滚动页面标签 - ,leftPage: function(){ - events.rollPage('left'); - } - - //向左滚动页面标签 - ,rightPage: function(){ - events.rollPage(); - } - - //关闭当前标签页 - ,closeThisTabs: function(){ - admin.closeThisTabs(); - } - - //关闭其它标签页 - ,closeOtherTabs: function(type){ - var TABS_REMOVE = 'LAY-system-pagetabs-remove'; - if(type === 'all'){ - $(TABS_HEADER+ ':gt(0)').remove(); - $(APP_BODY).find('.'+ TABS_BODY+ ':gt(0)').remove(); - } else { - $(TABS_HEADER).each(function(index, item){ - if(index && index != admin.tabsPage.index){ - $(item).addClass(TABS_REMOVE); - admin.tabsBody(index).addClass(TABS_REMOVE); - } - }); - $('.'+ TABS_REMOVE).remove(); - } - } - - //关闭全部标签页 - ,closeAllTabs: function(){ - events.closeOtherTabs('all'); - location.hash = ''; - } - - //遮罩 - ,shade: function(){ - admin.sideFlexible(); - } - }; - - //初始 - !function(){ - //主题初始化,本地主题记录优先,其次为 initColorIndex - var local = layui.data(setter.tableName); - if(local.theme){ - admin.theme(local.theme); - } else if(setter.theme){ - admin.initTheme(setter.theme.initColorIndex); - } - - //禁止水平滚动 - $body.addClass('layui-layout-body'); - - //移动端强制不开启页面标签功能 - if(admin.screen() < 1){ - delete setter.pageTabs; - } - - //不开启页面标签时 - if(!setter.pageTabs){ - container.addClass('layadmin-tabspage-none'); - } - - //低版本IE提示 - if(device.ie && device.ie < 10){ - view.error('IE'+ device.ie + '下访问可能不佳,推荐使用:Chrome / Firefox / Edge 等高级浏览器', { - offset: 'auto' - ,id: 'LAY_errorIE' - }); - } - - }(); - - //admin.prevRouter = {}; //上一个路由 - - // hash 改变侧边状态 - admin.on('hash(side)', function(router){ - var path = router.path, getData = function(item){ - return { - list: item.children('.layui-nav-child') - ,name: item.data('name') - ,jump: item.data('jump') - } - } - ,sideMenu = $('#'+ SIDE_MENU) - ,SIDE_NAV_ITEMD = 'layui-nav-itemed' - - //捕获对应菜单 - ,matchMenu = function(list){ - var pathURL = admin.correctRouter(path.join('/')); - list.each(function(index1, item1){ - var othis1 = $(item1) - ,data1 = getData(othis1) - ,listChildren1 = data1.list.children('dd') - ,matched1 = path[0] == data1.name || (index1 === 0 && !path[0]) - || (data1.jump && pathURL == admin.correctRouter(data1.jump)); - - listChildren1.each(function(index2, item2){ - var othis2 = $(item2) - ,data2 = getData(othis2) - ,listChildren2 = data2.list.children('dd') - ,matched2 = (path[0] == data1.name && path[1] == data2.name) - || (data2.jump && pathURL == admin.correctRouter(data2.jump)); - - listChildren2.each(function(index3, item3){ - var othis3 = $(item3) - ,data3 = getData(othis3) - ,matched3 = (path[0] == data1.name && path[1] == data2.name && path[2] == data3.name) - || (data3.jump && pathURL == admin.correctRouter(data3.jump)) - - if(matched3){ - var selected = data3.list[0] ? SIDE_NAV_ITEMD : THIS; - othis3.addClass(selected).siblings().removeClass(selected); //标记选择器 - return false; - } - - }); - - if(matched2){ - var selected = data2.list[0] ? SIDE_NAV_ITEMD : THIS; - othis2.addClass(selected).siblings().removeClass(selected); //标记选择器 - return false - } - - }); - - if(matched1){ - var selected = data1.list[0] ? SIDE_NAV_ITEMD : THIS; - othis1.addClass(selected).siblings().removeClass(selected); //标记选择器 - return false; - } - - }); - } - - //重置状态 - sideMenu.find('.'+ THIS).removeClass(THIS); - - //移动端点击菜单时自动收缩 - if(admin.screen() < 2) admin.sideFlexible(); - - //开始捕获 - matchMenu(sideMenu.children('li')); - }); - - //侧边导航点击事件 - element.on('nav(layadmin-system-side-menu)', function(elem){ - if(elem.siblings('.layui-nav-child')[0] && container.hasClass(SIDE_SHRINK)){ - admin.sideFlexible('spread'); - layer.close(elem.data('index')); - }; - admin.tabsPage.type = 'nav'; - }); - - //选项卡的更多操作 - element.on('nav(layadmin-pagetabs-nav)', function(elem){ - var dd = elem.parent(); - dd.removeClass(THIS); - dd.parent().removeClass(SHOW); - }); - - //同步路由 - var setThisRouter = function(othis){ - var layid = othis.attr('lay-id') - ,attr = othis.attr('lay-attr') - ,index = othis.index(); - - location.hash = layid === setter.entry ? '/' : (attr || '/'); - admin.tabsBodyChange(index); - } - ,TABS_HEADER = '#LAY_app_tabsheader>li'; - - //页面标签点击 - $body.on('click', TABS_HEADER, function(){ - var othis = $(this) - ,index = othis.index(); - - admin.tabsPage.type = 'tab'; - admin.tabsPage.index = index; - - //如果是iframe类型的标签页 - if(othis.attr('lay-attr') === 'iframe'){ - return admin.tabsBodyChange(index); - }; - - - setThisRouter(othis); //同步路由 - admin.runResize(); //执行resize事件,如果存在的话 - admin.resizeTable(); //重置当前主体区域的表格尺寸 - }); - - // tabspage 删除 - element.on('tabDelete(layadmin-layout-tabs)', function(obj){ - var othis = $(TABS_HEADER+ '.layui-this'); - - obj.index && admin.tabsBody(obj.index).remove(); - setThisRouter(othis); - - //移除resize事件 - admin.delResize(); - }); - - //页面跳转 - $body.on('click', '*[lay-href]', function(){ - var othis = $(this) - ,href = othis.attr('lay-href') - ,router = layui.router(); - - admin.tabsPage.elem = othis; - //admin.prevRouter[router.path[0]] = router.href; //记录上一次各菜单的路由信息 - - //执行跳转 - location.hash = admin.correctRouter(href); - - //如果为当前页,则执行刷新 - if(admin.correctRouter(href) === router.href){ - admin.events.refresh(); - } - }); - - //点击事件 - $body.on('click', '*[layadmin-event]', function(){ - var othis = $(this) - ,attrEvent = othis.attr('layadmin-event'); - events[attrEvent] && events[attrEvent].call(this, othis); - }); - - //tips - $body.on('mouseenter', '*[lay-tips]', function(){ - var othis = $(this); - - if(othis.parent().hasClass('layui-nav-item') && !container.hasClass(SIDE_SHRINK)) return; - - var tips = othis.attr('lay-tips') - ,offset = othis.attr('lay-offset') - ,direction = othis.attr('lay-direction') - ,index = layer.tips(tips, this, { - tips: direction || 1 - ,time: -1 - ,success: function(layero, index){ - if(offset){ - layero.css('margin-left', offset + 'px'); - } - } - }); - othis.data('index', index); - }).on('mouseleave', '*[lay-tips]', function(){ - layer.close($(this).data('index')); - }); - - //窗口resize事件 - var resizeSystem = layui.data.resizeSystem = function(){ - //layer.close(events.note.index); - layer.closeAll('tips'); - - if(!resizeSystem.lock){ - setTimeout(function(){ - admin.sideFlexible(admin.screen() < 2 ? '' : 'spread'); - delete resizeSystem.lock; - }, 100); - } - - resizeSystem.lock = true; - } - $win.on('resize', layui.data.resizeSystem); - - - //设置组件全局 token - ;!function(){ - var request = setter.request; - if(request.tokenName){ - var obj = {}; - obj[request.tokenName] = layui.data(setter.tableName)[request.tokenName] || '' - - //table - table.set({ - headers: obj, //通过 request 头传递 - where: obj //通过参数传递 - }); - //upload - upload.set({ - headers: obj, //通过 request 头传递 - data: obj //通过参数传递 - }); - } - }(); - - - //接口输出 - exports('admin', admin); -}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/echarts.js b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/echarts.js deleted file mode 100644 index 7af448cd..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/echarts.js +++ /dev/null @@ -1,39 +0,0 @@ -!function(e){var t,i;!function(){function e(e,t){if(!t)return e;if(0===e.indexOf(".")){var i=t.split("/"),n=e.split("/"),a=i.length-1,o=n.length,r=0,s=0;e:for(var l=0;o>l;l++)switch(n[l]){case"..":if(!(a>r))break e;r++,s++;break;case".":s++;break;default:break e}return i.length=a-r,n=n.slice(s),i.concat(n).join("/")}return e}function n(t){function i(i,r){if("string"==typeof i){var s=n[i];return s||(s=o(e(i,t)),n[i]=s),s}i instanceof Array&&(r=r||function(){},r.apply(this,a(i,r,t)))}var n={};return i}function a(i,n,a){for(var s=[],l=r[a],h=0,m=Math.min(i.length,n.length);m>h;h++){var V,U=e(i[h],a);switch(U){case"require":V=l&&l.require||t;break;case"exports":V=l.exports;break;case"module":V=l;break;default:V=o(U)}s.push(V)}return s}function o(e){var t=r[e];if(!t)throw new Error("No "+e);if(!t.defined){var i=t.factory,n=i.apply(this,a(t.deps||[],i,e));"undefined"!=typeof n&&(t.exports=n),t.defined=1}return t.exports}var r={};i=function(e,t,i){r[e]={id:e,deps:t,factory:i,defined:0,exports:{},require:n(e)}},t=n("")}(),i("echarts",["echarts/echarts"],function(e){return e}),i("echarts/echarts",["require","./config","zrender/tool/util","zrender/tool/event","zrender/tool/env","zrender","zrender/config","./chart/island","./component/toolbox","./component","./component/title","./component/tooltip","./component/legend","./util/ecData","./chart","zrender/tool/color","./component/timeline","zrender/shape/Image","zrender/loadingEffect/Bar","zrender/loadingEffect/Bubble","zrender/loadingEffect/DynamicLine","zrender/loadingEffect/Ring","zrender/loadingEffect/Spin","zrender/loadingEffect/Whirling","./theme/macarons","./theme/infographic"],function(e){function t(){r.Dispatcher.call(this)}function i(e){e.innerHTML="",this._themeConfig={},this.dom=e,this._connected=!1,this._status={dragIn:!1,dragOut:!1,needRefresh:!1},this._curEventType=!1,this._chartList=[],this._messageCenter=new t,this._messageCenterOutSide=new t,this.resize=this.resize(),this._init()}function n(e,t,i,n,a){for(var o=e._chartList,r=o.length;r--;){var s=o[r];"function"==typeof s[t]&&s[t](i,n,a)}}var a=e("./config"),o=e("zrender/tool/util"),r=e("zrender/tool/event"),s={},l=e("zrender/tool/env").canvasSupported,h=new Date-0,m={},V="_echarts_instance_";s.version="2.2.7",s.dependencies={zrender:"2.1.1"},s.init=function(t,n){var a=e("zrender");a.version.replace(".","")-0r;r++){var l=d[r],h=U[l];o[h]="_on"+l.toLowerCase(),i.on(h,this._onzrevent)}this.chart={},this.component={};var m=e("./chart/island");this._island=new m(this._themeConfig,this._messageCenter,i,{},this),this.chart.island=this._island;var V=e("./component/toolbox");this._toolbox=new V(this._themeConfig,this._messageCenter,i,{},this),this.component.toolbox=this._toolbox;var p=e("./component");p.define("title",e("./component/title")),p.define("tooltip",e("./component/tooltip")),p.define("legend",e("./component/legend")),(0===i.getWidth()||0===i.getHeight())&&console.error("Dom’s width & height should be ready before init.")},__onevent:function(e){e.__echartsId=e.__echartsId||this.id;var t=e.__echartsId===this.id;switch(this._curEventType||(this._curEventType=e.type),e.type){case a.EVENT.LEGEND_SELECTED:this._onlegendSelected(e);break;case a.EVENT.DATA_ZOOM:if(!t){var i=this.component.dataZoom;i&&(i.silence(!0),i.absoluteZoom(e.zoom),i.silence(!1))}this._ondataZoom(e);break;case a.EVENT.DATA_RANGE:t&&this._ondataRange(e);break;case a.EVENT.MAGIC_TYPE_CHANGED:if(!t){var n=this.component.toolbox;n&&(n.silence(!0),n.setMagicType(e.magicType),n.silence(!1))}this._onmagicTypeChanged(e);break;case a.EVENT.DATA_VIEW_CHANGED:t&&this._ondataViewChanged(e);break;case a.EVENT.TOOLTIP_HOVER:t&&this._tooltipHover(e);break;case a.EVENT.RESTORE:this._onrestore();break;case a.EVENT.REFRESH:t&&this._onrefresh(e);break;case a.EVENT.TOOLTIP_IN_GRID:case a.EVENT.TOOLTIP_OUT_GRID:if(t){if(this._connected){var o=this.component.grid;o&&(e.x=(e.event.zrenderX-o.getX())/o.getWidth(),e.y=(e.event.zrenderY-o.getY())/o.getHeight())}}else{var o=this.component.grid;o&&this._zr.trigger("mousemove",{connectTrigger:!0,zrenderX:o.getX()+e.x*o.getWidth(),zrenderY:o.getY()+e.y*o.getHeight()})}}if(this._connected&&t&&this._curEventType===e.type){for(var r in this._connected)this._connected[r].connectedEventHandler(e);this._curEventType=null}(!t||!this._connected&&t)&&(this._curEventType=null)},_onclick:function(e){if(n(this,"onclick",e),e.target){var t=this._eventPackage(e.target);t&&null!=t.seriesIndex&&this._messageCenter.dispatch(a.EVENT.CLICK,e.event,t,this)}},_ondblclick:function(e){if(n(this,"ondblclick",e),e.target){var t=this._eventPackage(e.target);t&&null!=t.seriesIndex&&this._messageCenter.dispatch(a.EVENT.DBLCLICK,e.event,t,this)}},_onmouseover:function(e){if(e.target){var t=this._eventPackage(e.target);t&&null!=t.seriesIndex&&this._messageCenter.dispatch(a.EVENT.HOVER,e.event,t,this)}},_onmouseout:function(e){if(e.target){var t=this._eventPackage(e.target);t&&null!=t.seriesIndex&&this._messageCenter.dispatch(a.EVENT.MOUSEOUT,e.event,t,this)}},_ondragstart:function(e){this._status={dragIn:!1,dragOut:!1,needRefresh:!1},n(this,"ondragstart",e)},_ondragenter:function(e){n(this,"ondragenter",e)},_ondragover:function(e){n(this,"ondragover",e)},_ondragleave:function(e){n(this,"ondragleave",e)},_ondrop:function(e){n(this,"ondrop",e,this._status),this._island.ondrop(e,this._status)},_ondragend:function(e){if(n(this,"ondragend",e,this._status),this._timeline&&this._timeline.ondragend(e,this._status),this._island.ondragend(e,this._status),this._status.needRefresh){this._syncBackupData(this._option);var t=this._messageCenter;t.dispatch(a.EVENT.DATA_CHANGED,e.event,this._eventPackage(e.target),this),t.dispatch(a.EVENT.REFRESH,null,null,this)}},_onlegendSelected:function(e){this._status.needRefresh=!1,n(this,"onlegendSelected",e,this._status),this._status.needRefresh&&this._messageCenter.dispatch(a.EVENT.REFRESH,null,null,this)},_ondataZoom:function(e){this._status.needRefresh=!1,n(this,"ondataZoom",e,this._status),this._status.needRefresh&&this._messageCenter.dispatch(a.EVENT.REFRESH,null,null,this)},_ondataRange:function(e){this._clearEffect(),this._status.needRefresh=!1,n(this,"ondataRange",e,this._status),this._status.needRefresh&&this._zr.refreshNextFrame()},_onmagicTypeChanged:function(){this._clearEffect(),this._render(this._toolbox.getMagicOption())},_ondataViewChanged:function(e){this._syncBackupData(e.option),this._messageCenter.dispatch(a.EVENT.DATA_CHANGED,null,e,this),this._messageCenter.dispatch(a.EVENT.REFRESH,null,null,this)},_tooltipHover:function(e){var t=[];n(this,"ontooltipHover",e,t)},_onrestore:function(){this.restore()},_onrefresh:function(e){this._refreshInside=!0,this.refresh(e),this._refreshInside=!1},_syncBackupData:function(e){this.component.dataZoom&&this.component.dataZoom.syncBackupData(e)},_eventPackage:function(t){if(t){var i=e("./util/ecData"),n=i.get(t,"seriesIndex"),a=i.get(t,"dataIndex");return a=-1!=n&&this.component.dataZoom?this.component.dataZoom.getRealDataIndex(n,a):a,{seriesIndex:n,seriesName:(i.get(t,"series")||{}).name,dataIndex:a,data:i.get(t,"data"),name:i.get(t,"name"),value:i.get(t,"value"),special:i.get(t,"special")}}},_noDataCheck:function(e){for(var t=e.series,i=0,n=t.length;n>i;i++)if(t[i].type==a.CHART_TYPE_MAP||t[i].data&&t[i].data.length>0||t[i].markPoint&&t[i].markPoint.data&&t[i].markPoint.data.length>0||t[i].markLine&&t[i].markLine.data&&t[i].markLine.data.length>0||t[i].nodes&&t[i].nodes.length>0||t[i].links&&t[i].links.length>0||t[i].matrix&&t[i].matrix.length>0||t[i].eventList&&t[i].eventList.length>0)return!1;var o=this._option&&this._option.noDataLoadingOption||this._themeConfig.noDataLoadingOption||a.noDataLoadingOption||{text:this._option&&this._option.noDataText||this._themeConfig.noDataText||a.noDataText,effect:this._option&&this._option.noDataEffect||this._themeConfig.noDataEffect||a.noDataEffect};return this.clear(),this.showLoading(o),!0},_render:function(t){if(this._mergeGlobalConifg(t),!this._noDataCheck(t)){var i=t.backgroundColor;if(i)if(l||-1==i.indexOf("rgba"))this.dom.style.backgroundColor=i;else{var n=i.split(",");this.dom.style.filter="alpha(opacity="+100*n[3].substring(0,n[3].lastIndexOf(")"))+")",n.length=3,n[0]=n[0].replace("a",""),this.dom.style.backgroundColor=n.join(",")+")"}this._zr.clearAnimation(),this._chartList=[];var o=e("./chart"),r=e("./component");(t.xAxis||t.yAxis)&&(t.grid=t.grid||{},t.dataZoom=t.dataZoom||{});for(var s,h,m,V=["title","legend","tooltip","dataRange","roamController","grid","dataZoom","xAxis","yAxis","polar"],U=0,d=V.length;d>U;U++)h=V[U],m=this.component[h],t[h]?(m?m.refresh&&m.refresh(t):(s=r.get(/^[xy]Axis$/.test(h)?"axis":h),m=new s(this._themeConfig,this._messageCenter,this._zr,t,this,h),this.component[h]=m),this._chartList.push(m)):m&&(m.dispose(),this.component[h]=null,delete this.component[h]);for(var p,c,u,y={},U=0,d=t.series.length;d>U;U++)c=t.series[U].type,c?y[c]||(y[c]=!0,p=o.get(c),p?(this.chart[c]?(u=this.chart[c],u.refresh(t)):u=new p(this._themeConfig,this._messageCenter,this._zr,t,this),this._chartList.push(u),this.chart[c]=u):console.error(c+" has not been required.")):console.error("series["+U+"] chart type has not been defined.");for(c in this.chart)c==a.CHART_TYPE_ISLAND||y[c]||(this.chart[c].dispose(),this.chart[c]=null,delete this.chart[c]);this.component.grid&&this.component.grid.refixAxisShape(this.component),this._island.refresh(t),this._toolbox.refresh(t),t.animation&&!t.renderAsImage?this._zr.refresh():this._zr.render();var g="IMG"+this.id,b=document.getElementById(g);t.renderAsImage&&l?(b?b.src=this.getDataURL(t.renderAsImage):(b=this.getImage(t.renderAsImage),b.id=g,b.style.position="absolute",b.style.left=0,b.style.top=0,this.dom.firstChild.appendChild(b)),this.un(),this._zr.un(),this._disposeChartList(),this._zr.clear()):b&&b.parentNode.removeChild(b),b=null,this._option=t}},restore:function(){this._clearEffect(),this._option=o.clone(this._optionRestore),this._disposeChartList(),this._island.clear(),this._toolbox.reset(this._option,!0),this._render(this._option)},refresh:function(e){this._clearEffect(),e=e||{};var t=e.option;!this._refreshInside&&t&&(t=this.getOption(),o.merge(t,e.option,!0),o.merge(this._optionRestore,e.option,!0),this._toolbox.reset(t)),this._island.refresh(t),this._toolbox.refresh(t),this._zr.clearAnimation();for(var i=0,n=this._chartList.length;n>i;i++)this._chartList[i].refresh&&this._chartList[i].refresh(t);this.component.grid&&this.component.grid.refixAxisShape(this.component),this._zr.refresh()},_disposeChartList:function(){this._clearEffect(),this._zr.clearAnimation();for(var e=this._chartList.length;e--;){var t=this._chartList[e];if(t){var i=t.type;this.chart[i]&&delete this.chart[i],this.component[i]&&delete this.component[i],t.dispose&&t.dispose()}}this._chartList=[]},_mergeGlobalConifg:function(t){for(var i=["backgroundColor","calculable","calculableColor","calculableHolderColor","nameConnector","valueConnector","animation","animationThreshold","animationDuration","animationDurationUpdate","animationEasing","addDataAnimation","symbolList","DRAG_ENABLE_TIME"],n=i.length;n--;){var o=i[n];null==t[o]&&(t[o]=null!=this._themeConfig[o]?this._themeConfig[o]:a[o])}var r=t.color;r&&r.length||(r=this._themeConfig.color||a.color),this._zr.getColor=function(t){var i=e("zrender/tool/color");return i.getColor(t,r)},l||(t.animation=!1,t.addDataAnimation=!1)},setOption:function(e,t){return e.timeline?this._setTimelineOption(e):this._setOption(e,t)},_setOption:function(e,t,i){return!t&&this._option?this._option=o.merge(this.getOption(),o.clone(e),!0):(this._option=o.clone(e),!i&&this._timeline&&this._timeline.dispose()),this._optionRestore=o.clone(this._option),this._option.series&&0!==this._option.series.length?(this.component.dataZoom&&(this._option.dataZoom||this._option.toolbox&&this._option.toolbox.feature&&this._option.toolbox.feature.dataZoom&&this._option.toolbox.feature.dataZoom.show)&&this.component.dataZoom.syncOption(this._option),this._toolbox.reset(this._option),this._render(this._option),this):void this._zr.clear()},getOption:function(){function e(e){var n=i._optionRestore[e];if(n)if(n instanceof Array)for(var a=n.length;a--;)t[e][a].data=o.clone(n[a].data);else t[e].data=o.clone(n.data)}var t=o.clone(this._option),i=this;return e("xAxis"),e("yAxis"),e("series"),t},setSeries:function(e,t){return t?(this._option.series=e,this.setOption(this._option,t)):this.setOption({series:e}),this},getSeries:function(){return this.getOption().series},_setTimelineOption:function(t){this._timeline&&this._timeline.dispose();var i=e("./component/timeline"),n=new i(this._themeConfig,this._messageCenter,this._zr,t,this);return this._timeline=n,this.component.timeline=this._timeline,this},addData:function(e,t,i,n,r){function s(){if(V._zr){V._zr.clearAnimation();for(var e=0,t=X.length;t>e;e++)X[e].motionlessOnce=h.addDataAnimation&&X[e].addDataAnimation;V._messageCenter.dispatch(a.EVENT.REFRESH,null,{option:h},V)}}for(var l=e instanceof Array?e:[[e,t,i,n,r]],h=this.getOption(),m=this._optionRestore,V=this,U=0,d=l.length;d>U;U++){e=l[U][0],t=l[U][1],i=l[U][2],n=l[U][3],r=l[U][4];var p=m.series[e],c=i?"unshift":"push",u=i?"pop":"shift";if(p){var y=p.data,g=h.series[e].data;if(y[c](t),g[c](t),n||(y[u](),t=g[u]()),null!=r){var b,f;if(p.type===a.CHART_TYPE_PIE&&(b=m.legend)&&(f=b.data)){var k=h.legend.data;if(f[c](r),k[c](r),!n){var x=o.indexOf(f,t.name);-1!=x&&f.splice(x,1),x=o.indexOf(k,t.name),-1!=x&&k.splice(x,1)}}else if(null!=m.xAxis&&null!=m.yAxis){var _,L,W=p.xAxisIndex||0;(null==m.xAxis[W].type||"category"===m.xAxis[W].type)&&(_=m.xAxis[W].data,L=h.xAxis[W].data,_[c](r),L[c](r),n||(_[u](),L[u]())),W=p.yAxisIndex||0,"category"===m.yAxis[W].type&&(_=m.yAxis[W].data,L=h.yAxis[W].data,_[c](r),L[c](r),n||(_[u](),L[u]()))}}this._option.series[e].data=h.series[e].data}}this._zr.clearAnimation();for(var X=this._chartList,v=0,w=function(){v--,0===v&&s()},U=0,d=X.length;d>U;U++)h.addDataAnimation&&X[U].addDataAnimation&&(v++,X[U].addDataAnimation(l,w));return this.component.dataZoom&&this.component.dataZoom.syncOption(h),this._option=h,h.addDataAnimation||setTimeout(s,0),this},addMarkPoint:function(e,t){return this._addMark(e,t,"markPoint")},addMarkLine:function(e,t){return this._addMark(e,t,"markLine")},_addMark:function(e,t,i){var n,a=this._option.series;if(a&&(n=a[e])){var r=this._optionRestore.series,s=r[e],l=n[i],h=s[i];l=n[i]=l||{data:[]},h=s[i]=h||{data:[]};for(var m in t)"data"===m?(l.data=l.data.concat(t.data),h.data=h.data.concat(t.data)):"object"!=typeof t[m]||null==l[m]?l[m]=h[m]=t[m]:(o.merge(l[m],t[m],!0),o.merge(h[m],t[m],!0));var V=this.chart[n.type];V&&V.addMark(e,t,i)}return this},delMarkPoint:function(e,t){return this._delMark(e,t,"markPoint")},delMarkLine:function(e,t){return this._delMark(e,t,"markLine")},_delMark:function(e,t,i){var n,a,o,r=this._option.series;if(!(r&&(n=r[e])&&(a=n[i])&&(o=a.data)))return this;t=t.split(" > ");for(var s=-1,l=0,h=o.length;h>l;l++){var m=o[l];if(m instanceof Array){if(m[0].name===t[0]&&m[1].name===t[1]){s=l;break}}else if(m.name===t[0]){s=l;break}}if(s>-1){o.splice(s,1),this._optionRestore.series[e][i].data.splice(s,1);var V=this.chart[n.type];V&&V.delMark(e,t.join(" > "),i)}return this},getDom:function(){return this.dom},getZrender:function(){return this._zr},getDataURL:function(e){if(!l)return"";if(0===this._chartList.length){var t="IMG"+this.id,i=document.getElementById(t);if(i)return i.src}var n=this.component.tooltip;switch(n&&n.hideTip(),e){case"jpeg":break;default:e="png"}var a=this._option.backgroundColor;return a&&"rgba(0,0,0,0)"===a.replace(" ","")&&(a="#fff"),this._zr.toDataURL("image/"+e,a)},getImage:function(e){var t=this._optionRestore.title,i=document.createElement("img");return i.src=this.getDataURL(e),i.title=t&&t.text||"ECharts",i},getConnectedDataURL:function(t){if(!this.isConnected())return this.getDataURL(t);var i=this.dom,n={self:{img:this.getDataURL(t),left:i.offsetLeft,top:i.offsetTop,right:i.offsetLeft+i.offsetWidth,bottom:i.offsetTop+i.offsetHeight}},a=n.self.left,o=n.self.top,r=n.self.right,s=n.self.bottom;for(var l in this._connected)i=this._connected[l].getDom(),n[l]={img:this._connected[l].getDataURL(t),left:i.offsetLeft,top:i.offsetTop,right:i.offsetLeft+i.offsetWidth,bottom:i.offsetTop+i.offsetHeight},a=Math.min(a,n[l].left),o=Math.min(o,n[l].top),r=Math.max(r,n[l].right),s=Math.max(s,n[l].bottom);var h=document.createElement("div");h.style.position="absolute",h.style.left="-4000px",h.style.width=r-a+"px",h.style.height=s-o+"px",document.body.appendChild(h);var m=e("zrender").init(h),V=e("zrender/shape/Image");for(var l in n)m.addShape(new V({style:{x:n[l].left-a,y:n[l].top-o,image:n[l].img}}));m.render();var U=this._option.backgroundColor;U&&"rgba(0,0,0,0)"===U.replace(/ /g,"")&&(U="#fff");var d=m.toDataURL("image/png",U);return setTimeout(function(){m.dispose(),h.parentNode.removeChild(h),h=null},100),d},getConnectedImage:function(e){var t=this._optionRestore.title,i=document.createElement("img");return i.src=this.getConnectedDataURL(e),i.title=t&&t.text||"ECharts",i},on:function(e,t){return this._messageCenterOutSide.bind(e,t,this),this},un:function(e,t){return this._messageCenterOutSide.unbind(e,t),this},connect:function(e){if(!e)return this;if(this._connected||(this._connected={}),e instanceof Array)for(var t=0,i=e.length;i>t;t++)this._connected[e[t].id]=e[t];else this._connected[e.id]=e;return this},disConnect:function(e){if(!e||!this._connected)return this;if(e instanceof Array)for(var t=0,i=e.length;i>t;t++)delete this._connected[e[t].id];else delete this._connected[e.id];for(var n in this._connected)return this;return this._connected=!1,this},connectedEventHandler:function(e){e.__echartsId!=this.id&&this._onevent(e)},isConnected:function(){return!!this._connected},showLoading:function(t){var i={bar:e("zrender/loadingEffect/Bar"),bubble:e("zrender/loadingEffect/Bubble"),dynamicLine:e("zrender/loadingEffect/DynamicLine"),ring:e("zrender/loadingEffect/Ring"),spin:e("zrender/loadingEffect/Spin"),whirling:e("zrender/loadingEffect/Whirling")};this._toolbox.hideDataView(),t=t||{};var n=t.textStyle||{};t.textStyle=n;var r=o.merge(o.merge(o.clone(n),this._themeConfig.textStyle),a.textStyle);n.textFont=r.fontStyle+" "+r.fontWeight+" "+r.fontSize+"px "+r.fontFamily,n.text=t.text||this._option&&this._option.loadingText||this._themeConfig.loadingText||a.loadingText,null!=t.x&&(n.x=t.x),null!=t.y&&(n.y=t.y),t.effectOption=t.effectOption||{},t.effectOption.textStyle=n;var s=t.effect;return("string"==typeof s||null==s)&&(s=i[t.effect||this._option&&this._option.loadingEffect||this._themeConfig.loadingEffect||a.loadingEffect]||i.spin),this._zr.showLoading(new s(t.effectOption)),this},hideLoading:function(){return this._zr.hideLoading(),this},setTheme:function(t){if(t){if("string"==typeof t)switch(t){case"macarons":t=e("./theme/macarons");break;case"infographic":t=e("./theme/infographic");break;default:t={}}else t=t||{};this._themeConfig=t}if(!l){var i=this._themeConfig.textStyle;i&&i.fontFamily&&i.fontFamily2&&(i.fontFamily=i.fontFamily2),i=a.textStyle,i.fontFamily=i.fontFamily2}this._timeline&&this._timeline.setTheme(!0),this._optionRestore&&this.restore()},resize:function(){var e=this;return function(){if(e._clearEffect(),e._zr.resize(),e._option&&e._option.renderAsImage&&l)return e._render(e._option),e;e._zr.clearAnimation(),e._island.resize(),e._toolbox.resize(),e._timeline&&e._timeline.resize();for(var t=0,i=e._chartList.length;i>t;t++)e._chartList[t].resize&&e._chartList[t].resize();return e.component.grid&&e.component.grid.refixAxisShape(e.component),e._zr.refresh(),e._messageCenter.dispatch(a.EVENT.RESIZE,null,null,e),e}},_clearEffect:function(){this._zr.modLayer(a.EFFECT_ZLEVEL,{motionBlur:!1}),this._zr.painter.clearLayer(a.EFFECT_ZLEVEL)},clear:function(){return this._disposeChartList(),this._zr.clear(),this._option={},this._optionRestore={},this.dom.style.backgroundColor=null,this},dispose:function(){var e=this.dom.getAttribute(V);e&&delete m[e],this._island.dispose(),this._toolbox.dispose(),this._timeline&&this._timeline.dispose(),this._messageCenter.unbind(),this.clear(),this._zr.dispose(),this._zr=null}},s}),i("echarts/config",[],function(){var e={CHART_TYPE_LINE:"line",CHART_TYPE_BAR:"bar",CHART_TYPE_SCATTER:"scatter",CHART_TYPE_PIE:"pie",CHART_TYPE_RADAR:"radar",CHART_TYPE_VENN:"venn",CHART_TYPE_TREEMAP:"treemap",CHART_TYPE_TREE:"tree",CHART_TYPE_MAP:"map",CHART_TYPE_K:"k",CHART_TYPE_ISLAND:"island",CHART_TYPE_FORCE:"force",CHART_TYPE_CHORD:"chord",CHART_TYPE_GAUGE:"gauge",CHART_TYPE_FUNNEL:"funnel",CHART_TYPE_EVENTRIVER:"eventRiver",CHART_TYPE_WORDCLOUD:"wordCloud",CHART_TYPE_HEATMAP:"heatmap",COMPONENT_TYPE_TITLE:"title",COMPONENT_TYPE_LEGEND:"legend",COMPONENT_TYPE_DATARANGE:"dataRange",COMPONENT_TYPE_DATAVIEW:"dataView",COMPONENT_TYPE_DATAZOOM:"dataZoom",COMPONENT_TYPE_TOOLBOX:"toolbox",COMPONENT_TYPE_TOOLTIP:"tooltip",COMPONENT_TYPE_GRID:"grid",COMPONENT_TYPE_AXIS:"axis",COMPONENT_TYPE_POLAR:"polar",COMPONENT_TYPE_X_AXIS:"xAxis",COMPONENT_TYPE_Y_AXIS:"yAxis",COMPONENT_TYPE_AXIS_CATEGORY:"categoryAxis",COMPONENT_TYPE_AXIS_VALUE:"valueAxis",COMPONENT_TYPE_TIMELINE:"timeline",COMPONENT_TYPE_ROAMCONTROLLER:"roamController",backgroundColor:"rgba(0,0,0,0)",color:["#ff7f50","#87cefa","#da70d6","#32cd32","#6495ed","#ff69b4","#ba55d3","#cd5c5c","#ffa500","#40e0d0","#1e90ff","#ff6347","#7b68ee","#00fa9a","#ffd700","#6699FF","#ff6666","#3cb371","#b8860b","#30e0e0"],markPoint:{clickable:!0,symbol:"pin",symbolSize:10,large:!1,effect:{show:!1,loop:!0,period:15,type:"scale",scaleSize:2,bounceDistance:10},itemStyle:{normal:{borderWidth:2,label:{show:!0,position:"inside"}},emphasis:{label:{show:!0}}}},markLine:{clickable:!0,symbol:["circle","arrow"],symbolSize:[2,4],smoothness:.2,precision:2,effect:{show:!1,loop:!0,period:15,scaleSize:2},bundling:{enable:!1,maxTurningAngle:45},itemStyle:{normal:{borderWidth:1.5,label:{show:!0,position:"end"},lineStyle:{type:"dashed"}},emphasis:{label:{show:!1},lineStyle:{}}}},textStyle:{decoration:"none",fontFamily:"Arial, Verdana, sans-serif",fontFamily2:"微软雅黑",fontSize:12,fontStyle:"normal",fontWeight:"normal"},EVENT:{REFRESH:"refresh",RESTORE:"restore",RESIZE:"resize",CLICK:"click",DBLCLICK:"dblclick",HOVER:"hover",MOUSEOUT:"mouseout",DATA_CHANGED:"dataChanged",DATA_ZOOM:"dataZoom",DATA_RANGE:"dataRange",DATA_RANGE_SELECTED:"dataRangeSelected",DATA_RANGE_HOVERLINK:"dataRangeHoverLink",LEGEND_SELECTED:"legendSelected",LEGEND_HOVERLINK:"legendHoverLink",MAP_SELECTED:"mapSelected",PIE_SELECTED:"pieSelected",MAGIC_TYPE_CHANGED:"magicTypeChanged",DATA_VIEW_CHANGED:"dataViewChanged",TIMELINE_CHANGED:"timelineChanged",MAP_ROAM:"mapRoam",FORCE_LAYOUT_END:"forceLayoutEnd",TOOLTIP_HOVER:"tooltipHover",TOOLTIP_IN_GRID:"tooltipInGrid",TOOLTIP_OUT_GRID:"tooltipOutGrid",ROAMCONTROLLER:"roamController"},DRAG_ENABLE_TIME:120,EFFECT_ZLEVEL:10,effectBlendAlpha:.95,symbolList:["circle","rectangle","triangle","diamond","emptyCircle","emptyRectangle","emptyTriangle","emptyDiamond"],loadingEffect:"spin",loadingText:"数据读取中...",noDataEffect:"bubble",noDataText:"暂无数据",calculable:!1,calculableColor:"rgba(255,165,0,0.6)",calculableHolderColor:"#ccc",nameConnector:" & ",valueConnector:": ",animation:!0,addDataAnimation:!0,animationThreshold:2e3,animationDuration:2e3,animationDurationUpdate:500,animationEasing:"ExponentialOut"};return e}),i("zrender/tool/util",["require","../dep/excanvas"],function(e){function t(e){return e&&1===e.nodeType&&"string"==typeof e.nodeName}function i(e){if("object"==typeof e&&null!==e){var n=e;if(e instanceof Array){n=[];for(var a=0,o=e.length;o>a;a++)n[a]=i(e[a])}else if(!y[g.call(e)]&&!t(e)){n={};for(var r in e)e.hasOwnProperty(r)&&(n[r]=i(e[r]))}return n}return e}function n(e,i,n,o){if(i.hasOwnProperty(n)){var r=e[n];"object"!=typeof r||y[g.call(r)]||t(r)?!o&&n in e||(e[n]=i[n]):a(e[n],i[n],o)}}function a(e,t,i){for(var a in t)n(e,t,a,i);return e}function o(){if(!U)if(e("../dep/excanvas"),window.G_vmlCanvasManager){var t=document.createElement("div");t.style.position="absolute",t.style.top="-1000px",document.body.appendChild(t),U=G_vmlCanvasManager.initElement(t).getContext("2d")}else U=document.createElement("canvas").getContext("2d");return U}function r(e,t){if(e.indexOf)return e.indexOf(t);for(var i=0,n=e.length;n>i;i++)if(e[i]===t)return i;return-1}function s(e,t){function i(){}var n=e.prototype;i.prototype=t.prototype,e.prototype=new i;for(var a in n)e.prototype[a]=n[a];e.constructor=e}function l(e,t,i){if(e&&t)if(e.forEach&&e.forEach===p)e.forEach(t,i);else if(e.length===+e.length)for(var n=0,a=e.length;a>n;n++)t.call(i,e[n],n,e);else for(var o in e)e.hasOwnProperty(o)&&t.call(i,e[o],o,e)}function h(e,t,i){if(e&&t){if(e.map&&e.map===c)return e.map(t,i);for(var n=[],a=0,o=e.length;o>a;a++)n.push(t.call(i,e[a],a,e));return n}}function m(e,t,i){if(e&&t){if(e.filter&&e.filter===u)return e.filter(t,i);for(var n=[],a=0,o=e.length;o>a;a++)t.call(i,e[a],a,e)&&n.push(e[a]);return n}}function V(e,t){return function(){e.apply(t,arguments)}}var U,d=Array.prototype,p=d.forEach,c=d.map,u=d.filter,y={"[object Function]":1,"[object RegExp]":1,"[object Date]":1,"[object Error]":1,"[object CanvasGradient]":1},g=Object.prototype.toString;return{inherits:s,clone:i,merge:a,getContext:o,indexOf:r,each:l,map:h,filter:m,bind:V}}),i("zrender/tool/event",["require","../mixin/Eventful"],function(e){"use strict";function t(e){return"undefined"!=typeof e.zrenderX&&e.zrenderX||"undefined"!=typeof e.offsetX&&e.offsetX||"undefined"!=typeof e.layerX&&e.layerX||"undefined"!=typeof e.clientX&&e.clientX}function i(e){return"undefined"!=typeof e.zrenderY&&e.zrenderY||"undefined"!=typeof e.offsetY&&e.offsetY||"undefined"!=typeof e.layerY&&e.layerY||"undefined"!=typeof e.clientY&&e.clientY}function n(e){return"undefined"!=typeof e.zrenderDelta&&e.zrenderDelta||"undefined"!=typeof e.wheelDelta&&e.wheelDelta||"undefined"!=typeof e.detail&&-e.detail}var a=e("../mixin/Eventful"),o="function"==typeof window.addEventListener?function(e){e.preventDefault(),e.stopPropagation(),e.cancelBubble=!0}:function(e){e.returnValue=!1,e.cancelBubble=!0};return{getX:t,getY:i,getDelta:n,stop:o,Dispatcher:a}}),i("zrender/tool/env",[],function(){function e(e){var t=this.os={},i=this.browser={},n=e.match(/Web[kK]it[\/]{0,1}([\d.]+)/),a=e.match(/(Android);?[\s\/]+([\d.]+)?/),o=e.match(/(iPad).*OS\s([\d_]+)/),r=e.match(/(iPod)(.*OS\s([\d_]+))?/),s=!o&&e.match(/(iPhone\sOS)\s([\d_]+)/),l=e.match(/(webOS|hpwOS)[\s\/]([\d.]+)/),h=l&&e.match(/TouchPad/),m=e.match(/Kindle\/([\d.]+)/),V=e.match(/Silk\/([\d._]+)/),U=e.match(/(BlackBerry).*Version\/([\d.]+)/),d=e.match(/(BB10).*Version\/([\d.]+)/),p=e.match(/(RIM\sTablet\sOS)\s([\d.]+)/),c=e.match(/PlayBook/),u=e.match(/Chrome\/([\d.]+)/)||e.match(/CriOS\/([\d.]+)/),y=e.match(/Firefox\/([\d.]+)/),g=e.match(/MSIE ([\d.]+)/),b=n&&e.match(/Mobile\//)&&!u,f=e.match(/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/)&&!u,g=e.match(/MSIE\s([\d.]+)/);return(i.webkit=!!n)&&(i.version=n[1]),a&&(t.android=!0,t.version=a[2]),s&&!r&&(t.ios=t.iphone=!0,t.version=s[2].replace(/_/g,".")),o&&(t.ios=t.ipad=!0,t.version=o[2].replace(/_/g,".")),r&&(t.ios=t.ipod=!0,t.version=r[3]?r[3].replace(/_/g,"."):null),l&&(t.webos=!0,t.version=l[2]),h&&(t.touchpad=!0),U&&(t.blackberry=!0,t.version=U[2]),d&&(t.bb10=!0,t.version=d[2]),p&&(t.rimtabletos=!0,t.version=p[2]),c&&(i.playbook=!0),m&&(t.kindle=!0,t.version=m[1]),V&&(i.silk=!0,i.version=V[1]),!V&&t.android&&e.match(/Kindle Fire/)&&(i.silk=!0),u&&(i.chrome=!0,i.version=u[1]),y&&(i.firefox=!0,i.version=y[1]),g&&(i.ie=!0,i.version=g[1]),b&&(e.match(/Safari/)||t.ios)&&(i.safari=!0),f&&(i.webview=!0),g&&(i.ie=!0,i.version=g[1]),t.tablet=!!(o||c||a&&!e.match(/Mobile/)||y&&e.match(/Tablet/)||g&&!e.match(/Phone/)&&e.match(/Touch/)),t.phone=!(t.tablet||t.ipod||!(a||s||l||U||d||u&&e.match(/Android/)||u&&e.match(/CriOS\/([\d.]+)/)||y&&e.match(/Mobile/)||g&&e.match(/Touch/))),{browser:i,os:t,canvasSupported:document.createElement("canvas").getContext?!0:!1}}return e(navigator.userAgent)}),i("zrender",["zrender/zrender"],function(e){return e}),i("zrender/zrender",["require","./dep/excanvas","./tool/util","./tool/log","./tool/guid","./Handler","./Painter","./Storage","./animation/Animation","./tool/env"],function(e){function t(e){return function(){e._needsRefreshNextFrame&&e.refresh()}}e("./dep/excanvas");var i=e("./tool/util"),n=e("./tool/log"),a=e("./tool/guid"),o=e("./Handler"),r=e("./Painter"),s=e("./Storage"),l=e("./animation/Animation"),h={},m={};m.version="2.1.1",m.init=function(e){var t=new V(a(),e);return h[t.id]=t,t},m.dispose=function(e){if(e)e.dispose();else{for(var t in h)h[t].dispose();h={}}return m},m.getInstance=function(e){return h[e]},m.delInstance=function(e){return delete h[e],m};var V=function(i,n){this.id=i,this.env=e("./tool/env"),this.storage=new s,this.painter=new r(n,this.storage),this.handler=new o(n,this.storage,this.painter),this.animation=new l({stage:{update:t(this)}}),this.animation.start();var a=this;this.painter.refreshNextFrame=function(){a.refreshNextFrame()},this._needsRefreshNextFrame=!1;var a=this,h=this.storage,m=h.delFromMap;h.delFromMap=function(e){var t=h.get(e);a.stopAnimation(t),m.call(h,e)}};return V.prototype.getId=function(){return this.id},V.prototype.addShape=function(e){return this.addElement(e),this},V.prototype.addGroup=function(e){return this.addElement(e),this},V.prototype.delShape=function(e){return this.delElement(e),this},V.prototype.delGroup=function(e){return this.delElement(e),this},V.prototype.modShape=function(e,t){return this.modElement(e,t),this},V.prototype.modGroup=function(e,t){return this.modElement(e,t),this},V.prototype.addElement=function(e){return this.storage.addRoot(e),this._needsRefreshNextFrame=!0,this},V.prototype.delElement=function(e){return this.storage.delRoot(e),this._needsRefreshNextFrame=!0,this},V.prototype.modElement=function(e,t){return this.storage.mod(e,t),this._needsRefreshNextFrame=!0,this},V.prototype.modLayer=function(e,t){return this.painter.modLayer(e,t),this._needsRefreshNextFrame=!0,this},V.prototype.addHoverShape=function(e){return this.storage.addHover(e),this},V.prototype.render=function(e){return this.painter.render(e),this._needsRefreshNextFrame=!1,this},V.prototype.refresh=function(e){return this.painter.refresh(e),this._needsRefreshNextFrame=!1,this},V.prototype.refreshNextFrame=function(){return this._needsRefreshNextFrame=!0,this},V.prototype.refreshHover=function(e){return this.painter.refreshHover(e),this},V.prototype.refreshShapes=function(e,t){return this.painter.refreshShapes(e,t),this},V.prototype.resize=function(){return this.painter.resize(),this},V.prototype.animate=function(e,t,a){var o=this;if("string"==typeof e&&(e=this.storage.get(e)),e){var r;if(t){for(var s=t.split("."),l=e,h=0,m=s.length;m>h;h++)l&&(l=l[s[h]]);l&&(r=l)}else r=e;if(!r)return void n('Property "'+t+'" is not existed in element '+e.id); - -null==e.__animators&&(e.__animators=[]);var V=e.__animators,U=this.animation.animate(r,{loop:a}).during(function(){o.modShape(e)}).done(function(){var t=i.indexOf(e.__animators,U);t>=0&&V.splice(t,1)});return V.push(U),U}n("Element not existed")},V.prototype.stopAnimation=function(e){if(e.__animators){for(var t=e.__animators,i=t.length,n=0;i>n;n++)t[n].stop();t.length=0}return this},V.prototype.clearAnimation=function(){return this.animation.clear(),this},V.prototype.showLoading=function(e){return this.painter.showLoading(e),this},V.prototype.hideLoading=function(){return this.painter.hideLoading(),this},V.prototype.getWidth=function(){return this.painter.getWidth()},V.prototype.getHeight=function(){return this.painter.getHeight()},V.prototype.toDataURL=function(e,t,i){return this.painter.toDataURL(e,t,i)},V.prototype.shapeToImage=function(e,t,i){var n=a();return this.painter.shapeToImage(n,e,t,i)},V.prototype.on=function(e,t,i){return this.handler.on(e,t,i),this},V.prototype.un=function(e,t){return this.handler.un(e,t),this},V.prototype.trigger=function(e,t){return this.handler.trigger(e,t),this},V.prototype.clear=function(){return this.storage.delRoot(),this.painter.clear(),this},V.prototype.dispose=function(){this.animation.stop(),this.clear(),this.storage.dispose(),this.painter.dispose(),this.handler.dispose(),this.animation=this.storage=this.painter=this.handler=null,m.delInstance(this.id)},m}),i("zrender/config",[],function(){var e={EVENT:{RESIZE:"resize",CLICK:"click",DBLCLICK:"dblclick",MOUSEWHEEL:"mousewheel",MOUSEMOVE:"mousemove",MOUSEOVER:"mouseover",MOUSEOUT:"mouseout",MOUSEDOWN:"mousedown",MOUSEUP:"mouseup",GLOBALOUT:"globalout",DRAGSTART:"dragstart",DRAGEND:"dragend",DRAGENTER:"dragenter",DRAGOVER:"dragover",DRAGLEAVE:"dragleave",DROP:"drop",touchClickDelay:300},elementClassName:"zr-element",catchBrushException:!1,debugMode:0,devicePixelRatio:Math.max(window.devicePixelRatio||1,1)};return e}),i("echarts/chart/island",["require","./base","zrender/shape/Circle","../config","../util/ecData","zrender/tool/util","zrender/tool/event","zrender/tool/color","../util/accMath","../chart"],function(e){function t(e,t,n,a,r){i.call(this,e,t,n,a,r),this._nameConnector,this._valueConnector,this._zrHeight=this.zr.getHeight(),this._zrWidth=this.zr.getWidth();var l=this;l.shapeHandler.onmousewheel=function(e){var t=e.target,i=e.event,n=s.getDelta(i);n=n>0?-1:1,t.style.r-=n,t.style.r=t.style.r<5?5:t.style.r;var a=o.get(t,"value"),r=a*l.option.island.calculateStep;a=r>1?Math.round(a-r*n):+(a-r*n).toFixed(2);var h=o.get(t,"name");t.style.text=h+":"+a,o.set(t,"value",a),o.set(t,"name",h),l.zr.modShape(t.id),l.zr.refreshNextFrame(),s.stop(i)}}var i=e("./base"),n=e("zrender/shape/Circle"),a=e("../config");a.island={zlevel:0,z:5,r:15,calculateStep:.1};var o=e("../util/ecData"),r=e("zrender/tool/util"),s=e("zrender/tool/event");return t.prototype={type:a.CHART_TYPE_ISLAND,_combine:function(t,i){var n=e("zrender/tool/color"),a=e("../util/accMath"),r=a.accAdd(o.get(t,"value"),o.get(i,"value")),s=o.get(t,"name")+this._nameConnector+o.get(i,"name");t.style.text=s+this._valueConnector+r,o.set(t,"value",r),o.set(t,"name",s),t.style.r=this.option.island.r,t.style.color=n.mix(t.style.color,i.style.color)},refresh:function(e){e&&(e.island=this.reformOption(e.island),this.option=e,this._nameConnector=this.option.nameConnector,this._valueConnector=this.option.valueConnector)},getOption:function(){return this.option},resize:function(){var e=this.zr.getWidth(),t=this.zr.getHeight(),i=e/(this._zrWidth||e),n=t/(this._zrHeight||t);if(1!==i||1!==n){this._zrWidth=e,this._zrHeight=t;for(var a=0,o=this.shapeList.length;o>a;a++)this.zr.modShape(this.shapeList[a].id,{style:{x:Math.round(this.shapeList[a].style.x*i),y:Math.round(this.shapeList[a].style.y*n)}})}},add:function(e){var t=o.get(e,"name"),i=o.get(e,"value"),a=null!=o.get(e,"series")?o.get(e,"series").name:"",r=this.getFont(this.option.island.textStyle),s=this.option.island,l={zlevel:s.zlevel,z:s.z,style:{x:e.style.x,y:e.style.y,r:this.option.island.r,color:e.style.color||e.style.strokeColor,text:t+this._valueConnector+i,textFont:r},draggable:!0,hoverable:!0,onmousewheel:this.shapeHandler.onmousewheel,_type:"island"};"#fff"===l.style.color&&(l.style.color=e.style.strokeColor),this.setCalculable(l),l.dragEnableTime=0,o.pack(l,{name:a},-1,i,-1,t),l=new n(l),this.shapeList.push(l),this.zr.addShape(l)},del:function(e){this.zr.delShape(e.id);for(var t=[],i=0,n=this.shapeList.length;n>i;i++)this.shapeList[i].id!=e.id&&t.push(this.shapeList[i]);this.shapeList=t},ondrop:function(e,t){if(this.isDrop&&e.target){var i=e.target,n=e.dragged;this._combine(i,n),this.zr.modShape(i.id),t.dragIn=!0,this.isDrop=!1}},ondragend:function(e,t){var i=e.target;this.isDragend?t.dragIn&&(this.del(i),t.needRefresh=!0):t.dragIn||(i.style.x=s.getX(e.event),i.style.y=s.getY(e.event),this.add(i),t.needRefresh=!0),this.isDragend=!1}},r.inherits(t,i),e("../chart").define("island",t),t}),i("echarts/component/toolbox",["require","./base","zrender/shape/Line","zrender/shape/Image","zrender/shape/Rectangle","../util/shape/Icon","../config","zrender/tool/util","zrender/config","zrender/tool/event","./dataView","../component"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.dom=o.dom,this._magicType={},this._magicMap={},this._isSilence=!1,this._iconList,this._iconShapeMap={},this._featureTitle={},this._featureIcon={},this._featureColor={},this._featureOption={},this._enableColor="red",this._disableColor="#ccc",this._markShapeList=[];var r=this;r._onMark=function(e){r.__onMark(e)},r._onMarkUndo=function(e){r.__onMarkUndo(e)},r._onMarkClear=function(e){r.__onMarkClear(e)},r._onDataZoom=function(e){r.__onDataZoom(e)},r._onDataZoomReset=function(e){r.__onDataZoomReset(e)},r._onDataView=function(e){r.__onDataView(e)},r._onRestore=function(e){r.__onRestore(e)},r._onSaveAsImage=function(e){r.__onSaveAsImage(e)},r._onMagicType=function(e){r.__onMagicType(e)},r._onCustomHandler=function(e){r.__onCustomHandler(e)},r._onmousemove=function(e){return r.__onmousemove(e)},r._onmousedown=function(e){return r.__onmousedown(e)},r._onmouseup=function(e){return r.__onmouseup(e)},r._onclick=function(e){return r.__onclick(e)}}var i=e("./base"),n=e("zrender/shape/Line"),a=e("zrender/shape/Image"),o=e("zrender/shape/Rectangle"),r=e("../util/shape/Icon"),s=e("../config");s.toolbox={zlevel:0,z:6,show:!1,orient:"horizontal",x:"right",y:"top",color:["#1e90ff","#22bb22","#4b0082","#d2691e"],disableColor:"#ddd",effectiveColor:"red",backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,padding:5,itemGap:10,itemSize:16,showTitle:!0,feature:{mark:{show:!1,title:{mark:"辅助线开关",markUndo:"删除辅助线",markClear:"清空辅助线"},lineStyle:{width:1,color:"#1e90ff",type:"dashed"}},dataZoom:{show:!1,title:{dataZoom:"区域缩放",dataZoomReset:"区域缩放后退"}},dataView:{show:!1,title:"数据视图",readOnly:!1,lang:["数据视图","关闭","刷新"]},magicType:{show:!1,title:{line:"折线图切换",bar:"柱形图切换",stack:"堆积",tiled:"平铺",force:"力导向布局图切换",chord:"和弦图切换",pie:"饼图切换",funnel:"漏斗图切换"},type:[]},restore:{show:!1,title:"还原"},saveAsImage:{show:!1,title:"保存为图片",type:"png",lang:["点击保存"]}}};var l=e("zrender/tool/util"),h=e("zrender/config"),m=e("zrender/tool/event"),V="stack",U="tiled";return t.prototype={type:s.COMPONENT_TYPE_TOOLBOX,_buildShape:function(){this._iconList=[];var e=this.option.toolbox;this._enableColor=e.effectiveColor,this._disableColor=e.disableColor;var t=e.feature,i=[];for(var n in t)if(t[n].show)switch(n){case"mark":i.push({key:n,name:"mark"}),i.push({key:n,name:"markUndo"}),i.push({key:n,name:"markClear"});break;case"magicType":for(var a=0,o=t[n].type.length;o>a;a++)t[n].title[t[n].type[a]+"Chart"]=t[n].title[t[n].type[a]],t[n].option&&(t[n].option[t[n].type[a]+"Chart"]=t[n].option[t[n].type[a]]),i.push({key:n,name:t[n].type[a]+"Chart"});break;case"dataZoom":i.push({key:n,name:"dataZoom"}),i.push({key:n,name:"dataZoomReset"});break;case"saveAsImage":this.canvasSupported&&i.push({key:n,name:"saveAsImage"});break;default:i.push({key:n,name:n})}if(i.length>0){for(var r,n,a=0,o=i.length;o>a;a++)r=i[a].name,n=i[a].key,this._iconList.push(r),this._featureTitle[r]=t[n].title[r]||t[n].title,t[n].icon&&(this._featureIcon[r]=t[n].icon[r]||t[n].icon),t[n].color&&(this._featureColor[r]=t[n].color[r]||t[n].color),t[n].option&&(this._featureOption[r]=t[n].option[r]||t[n].option);this._itemGroupLocation=this._getItemGroupLocation(),this._buildBackground(),this._buildItem();for(var a=0,o=this.shapeList.length;o>a;a++)this.zr.addShape(this.shapeList[a]);this._iconShapeMap.mark&&(this._iconDisable(this._iconShapeMap.markUndo),this._iconDisable(this._iconShapeMap.markClear)),this._iconShapeMap.dataZoomReset&&0===this._zoomQueue.length&&this._iconDisable(this._iconShapeMap.dataZoomReset)}},_buildItem:function(){var t,i,n,o,s=this.option.toolbox,l=this._iconList.length,h=this._itemGroupLocation.x,m=this._itemGroupLocation.y,V=s.itemSize,U=s.itemGap,d=s.color instanceof Array?s.color:[s.color],p=this.getFont(s.textStyle);"horizontal"===s.orient?(i=this._itemGroupLocation.y/this.zr.getHeight()<.5?"bottom":"top",n=this._itemGroupLocation.x/this.zr.getWidth()<.5?"left":"right",o=this._itemGroupLocation.y/this.zr.getHeight()<.5?"top":"bottom"):i=this._itemGroupLocation.x/this.zr.getWidth()<.5?"right":"left",this._iconShapeMap={};for(var c=this,u=0;l>u;u++){switch(t={type:"icon",zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:h,y:m,width:V,height:V,iconType:this._iconList[u],lineWidth:1,strokeColor:this._featureColor[this._iconList[u]]||d[u%d.length],brushType:"stroke"},highlightStyle:{lineWidth:1,text:s.showTitle?this._featureTitle[this._iconList[u]]:void 0,textFont:p,textPosition:i,strokeColor:this._featureColor[this._iconList[u]]||d[u%d.length]},hoverable:!0,clickable:!0},this._featureIcon[this._iconList[u]]&&(t.style.image=this._featureIcon[this._iconList[u]].replace(new RegExp("^image:\\/\\/"),""),t.style.opacity=.8,t.highlightStyle.opacity=1,t.type="image"),"horizontal"===s.orient&&(0===u&&"left"===n&&(t.highlightStyle.textPosition="specific",t.highlightStyle.textAlign=n,t.highlightStyle.textBaseline=o,t.highlightStyle.textX=h,t.highlightStyle.textY="top"===o?m+V+10:m-10),u===l-1&&"right"===n&&(t.highlightStyle.textPosition="specific",t.highlightStyle.textAlign=n,t.highlightStyle.textBaseline=o,t.highlightStyle.textX=h+V,t.highlightStyle.textY="top"===o?m+V+10:m-10)),this._iconList[u]){case"mark":t.onclick=c._onMark;break;case"markUndo":t.onclick=c._onMarkUndo;break;case"markClear":t.onclick=c._onMarkClear;break;case"dataZoom":t.onclick=c._onDataZoom;break;case"dataZoomReset":t.onclick=c._onDataZoomReset;break;case"dataView":if(!this._dataView){var y=e("./dataView");this._dataView=new y(this.ecTheme,this.messageCenter,this.zr,this.option,this.myChart)}t.onclick=c._onDataView;break;case"restore":t.onclick=c._onRestore;break;case"saveAsImage":t.onclick=c._onSaveAsImage;break;default:this._iconList[u].match("Chart")?(t._name=this._iconList[u].replace("Chart",""),t.onclick=c._onMagicType):t.onclick=c._onCustomHandler}"icon"===t.type?t=new r(t):"image"===t.type&&(t=new a(t)),this.shapeList.push(t),this._iconShapeMap[this._iconList[u]]=t,"horizontal"===s.orient?h+=V+U:m+=V+U}},_buildBackground:function(){var e=this.option.toolbox,t=this.reformCssArray(this.option.toolbox.padding);this.shapeList.push(new o({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._itemGroupLocation.x-t[3],y:this._itemGroupLocation.y-t[0],width:this._itemGroupLocation.width+t[3]+t[1],height:this._itemGroupLocation.height+t[0]+t[2],brushType:0===e.borderWidth?"fill":"both",color:e.backgroundColor,strokeColor:e.borderColor,lineWidth:e.borderWidth}}))},_getItemGroupLocation:function(){var e=this.option.toolbox,t=this.reformCssArray(this.option.toolbox.padding),i=this._iconList.length,n=e.itemGap,a=e.itemSize,o=0,r=0;"horizontal"===e.orient?(o=(a+n)*i-n,r=a):(r=(a+n)*i-n,o=a);var s,l=this.zr.getWidth();switch(e.x){case"center":s=Math.floor((l-o)/2);break;case"left":s=t[3]+e.borderWidth;break;case"right":s=l-o-t[1]-e.borderWidth;break;default:s=e.x-0,s=isNaN(s)?0:s}var h,m=this.zr.getHeight();switch(e.y){case"top":h=t[0]+e.borderWidth;break;case"bottom":h=m-r-t[2]-e.borderWidth;break;case"center":h=Math.floor((m-r)/2);break;default:h=e.y-0,h=isNaN(h)?0:h}return{x:s,y:h,width:o,height:r}},__onmousemove:function(e){this._marking&&(this._markShape.style.xEnd=m.getX(e.event),this._markShape.style.yEnd=m.getY(e.event),this.zr.addHoverShape(this._markShape)),this._zooming&&(this._zoomShape.style.width=m.getX(e.event)-this._zoomShape.style.x,this._zoomShape.style.height=m.getY(e.event)-this._zoomShape.style.y,this.zr.addHoverShape(this._zoomShape),this.dom.style.cursor="crosshair",m.stop(e.event)),this._zoomStart&&"pointer"!=this.dom.style.cursor&&"move"!=this.dom.style.cursor&&(this.dom.style.cursor="crosshair")},__onmousedown:function(e){if(!e.target){this._zooming=!0;var t=m.getX(e.event),i=m.getY(e.event),n=this.option.dataZoom||{};return this._zoomShape=new o({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:t,y:i,width:1,height:1,brushType:"both"},highlightStyle:{lineWidth:2,color:n.fillerColor||s.dataZoom.fillerColor,strokeColor:n.handleColor||s.dataZoom.handleColor,brushType:"both"}}),this.zr.addHoverShape(this._zoomShape),!0}},__onmouseup:function(){if(!this._zoomShape||Math.abs(this._zoomShape.style.width)<10||Math.abs(this._zoomShape.style.height)<10)return this._zooming=!1,!0;if(this._zooming&&this.component.dataZoom){this._zooming=!1;var e=this.component.dataZoom.rectZoom(this._zoomShape.style);e&&(this._zoomQueue.push({start:e.start,end:e.end,start2:e.start2,end2:e.end2}),this._iconEnable(this._iconShapeMap.dataZoomReset),this.zr.refreshNextFrame())}return!0},__onclick:function(e){if(!e.target)if(this._marking)this._marking=!1,this._markShapeList.push(this._markShape),this._iconEnable(this._iconShapeMap.markUndo),this._iconEnable(this._iconShapeMap.markClear),this.zr.addShape(this._markShape),this.zr.refreshNextFrame();else if(this._markStart){this._marking=!0;var t=m.getX(e.event),i=m.getY(e.event);this._markShape=new n({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{xStart:t,yStart:i,xEnd:t,yEnd:i,lineWidth:this.query(this.option,"toolbox.feature.mark.lineStyle.width"),strokeColor:this.query(this.option,"toolbox.feature.mark.lineStyle.color"),lineType:this.query(this.option,"toolbox.feature.mark.lineStyle.type")}}),this.zr.addHoverShape(this._markShape)}},__onMark:function(e){var t=e.target;if(this._marking||this._markStart)this._resetMark(),this.zr.refreshNextFrame();else{this._resetZoom(),this.zr.modShape(t.id,{style:{strokeColor:this._enableColor}}),this.zr.refreshNextFrame(),this._markStart=!0;var i=this;setTimeout(function(){i.zr&&i.zr.on(h.EVENT.CLICK,i._onclick)&&i.zr.on(h.EVENT.MOUSEMOVE,i._onmousemove)},10)}return!0},__onMarkUndo:function(){if(this._marking)this._marking=!1;else{var e=this._markShapeList.length;if(e>=1){var t=this._markShapeList[e-1];this.zr.delShape(t.id),this.zr.refreshNextFrame(),this._markShapeList.pop(),1===e&&(this._iconDisable(this._iconShapeMap.markUndo),this._iconDisable(this._iconShapeMap.markClear))}}return!0},__onMarkClear:function(){this._marking&&(this._marking=!1);var e=this._markShapeList.length;if(e>0){for(;e--;)this.zr.delShape(this._markShapeList.pop().id);this._iconDisable(this._iconShapeMap.markUndo),this._iconDisable(this._iconShapeMap.markClear),this.zr.refreshNextFrame()}return!0},__onDataZoom:function(e){var t=e.target;if(this._zooming||this._zoomStart)this._resetZoom(),this.zr.refreshNextFrame(),this.dom.style.cursor="default";else{this._resetMark(),this.zr.modShape(t.id,{style:{strokeColor:this._enableColor}}),this.zr.refreshNextFrame(),this._zoomStart=!0;var i=this;setTimeout(function(){i.zr&&i.zr.on(h.EVENT.MOUSEDOWN,i._onmousedown)&&i.zr.on(h.EVENT.MOUSEUP,i._onmouseup)&&i.zr.on(h.EVENT.MOUSEMOVE,i._onmousemove)},10),this.dom.style.cursor="crosshair"}return!0},__onDataZoomReset:function(){return this._zooming&&(this._zooming=!1),this._zoomQueue.pop(),this._zoomQueue.length>0?this.component.dataZoom.absoluteZoom(this._zoomQueue[this._zoomQueue.length-1]):(this.component.dataZoom.rectZoom(),this._iconDisable(this._iconShapeMap.dataZoomReset),this.zr.refreshNextFrame()),!0},_resetMark:function(){this._marking=!1,this._markStart&&(this._markStart=!1,this._iconShapeMap.mark&&this.zr.modShape(this._iconShapeMap.mark.id,{style:{strokeColor:this._iconShapeMap.mark.highlightStyle.strokeColor}}),this.zr.un(h.EVENT.CLICK,this._onclick),this.zr.un(h.EVENT.MOUSEMOVE,this._onmousemove))},_resetZoom:function(){this._zooming=!1,this._zoomStart&&(this._zoomStart=!1,this._iconShapeMap.dataZoom&&this.zr.modShape(this._iconShapeMap.dataZoom.id,{style:{strokeColor:this._iconShapeMap.dataZoom.highlightStyle.strokeColor}}),this.zr.un(h.EVENT.MOUSEDOWN,this._onmousedown),this.zr.un(h.EVENT.MOUSEUP,this._onmouseup),this.zr.un(h.EVENT.MOUSEMOVE,this._onmousemove))},_iconDisable:function(e){"image"!=e.type?this.zr.modShape(e.id,{hoverable:!1,clickable:!1,style:{strokeColor:this._disableColor}}):this.zr.modShape(e.id,{hoverable:!1,clickable:!1,style:{opacity:.3}})},_iconEnable:function(e){"image"!=e.type?this.zr.modShape(e.id,{hoverable:!0,clickable:!0,style:{strokeColor:e.highlightStyle.strokeColor}}):this.zr.modShape(e.id,{hoverable:!0,clickable:!0,style:{opacity:.8}})},__onDataView:function(){return this._dataView.show(this.option),!0},__onRestore:function(){return this._resetMark(),this._resetZoom(),this.messageCenter.dispatch(s.EVENT.RESTORE,null,null,this.myChart),!0},__onSaveAsImage:function(){var e=this.option.toolbox.feature.saveAsImage,t=e.type||"png";"png"!=t&&"jpeg"!=t&&(t="png");var i;i=this.myChart.isConnected()?this.myChart.getConnectedDataURL(t):this.zr.toDataURL("image/"+t,this.option.backgroundColor&&"rgba(0,0,0,0)"===this.option.backgroundColor.replace(" ","")?"#fff":this.option.backgroundColor);var n=document.createElement("div");n.id="__echarts_download_wrap__",n.style.cssText="position:fixed;z-index:99999;display:block;top:0;left:0;background-color:rgba(33,33,33,0.5);text-align:center;width:100%;height:100%;line-height:"+document.documentElement.clientHeight+"px;";var a=document.createElement("a");a.href=i,a.setAttribute("download",(e.name?e.name:this.option.title&&(this.option.title.text||this.option.title.subtext)?this.option.title.text||this.option.title.subtext:"ECharts")+"."+t),a.innerHTML='图片另存为":e.lang?e.lang[0]:"点击保存")+'"/>',n.appendChild(a),document.body.appendChild(n),a=null,n=null,setTimeout(function(){var e=document.getElementById("__echarts_download_wrap__");e&&(e.onclick=function(){var e=document.getElementById("__echarts_download_wrap__");e.onclick=null,e.innerHTML="",document.body.removeChild(e),e=null},e=null)},500)},__onMagicType:function(e){this._resetMark();var t=e.target._name;return this._magicType[t]||(this._magicType[t]=!0,t===s.CHART_TYPE_LINE?this._magicType[s.CHART_TYPE_BAR]=!1:t===s.CHART_TYPE_BAR&&(this._magicType[s.CHART_TYPE_LINE]=!1),t===s.CHART_TYPE_PIE?this._magicType[s.CHART_TYPE_FUNNEL]=!1:t===s.CHART_TYPE_FUNNEL&&(this._magicType[s.CHART_TYPE_PIE]=!1),t===s.CHART_TYPE_FORCE?this._magicType[s.CHART_TYPE_CHORD]=!1:t===s.CHART_TYPE_CHORD&&(this._magicType[s.CHART_TYPE_FORCE]=!1),t===V?this._magicType[U]=!1:t===U&&(this._magicType[V]=!1),this.messageCenter.dispatch(s.EVENT.MAGIC_TYPE_CHANGED,e.event,{magicType:this._magicType},this.myChart)),!0},setMagicType:function(e){this._resetMark(),this._magicType=e,!this._isSilence&&this.messageCenter.dispatch(s.EVENT.MAGIC_TYPE_CHANGED,null,{magicType:this._magicType},this.myChart)},__onCustomHandler:function(e){var t=e.target.style.iconType,i=this.option.toolbox.feature[t].onclick;"function"==typeof i&&i.call(this,this.option)},reset:function(e,t){if(t&&this.clear(),this.query(e,"toolbox.show")&&this.query(e,"toolbox.feature.magicType.show")){var i=e.toolbox.feature.magicType.type,n=i.length;for(this._magicMap={};n--;)this._magicMap[i[n]]=!0;n=e.series.length;for(var a,o;n--;)a=e.series[n].type,this._magicMap[a]&&(o=e.xAxis instanceof Array?e.xAxis[e.series[n].xAxisIndex||0]:e.xAxis,o&&"category"===(o.type||"category")&&(o.__boundaryGap=null!=o.boundaryGap?o.boundaryGap:!0),o=e.yAxis instanceof Array?e.yAxis[e.series[n].yAxisIndex||0]:e.yAxis,o&&"category"===o.type&&(o.__boundaryGap=null!=o.boundaryGap?o.boundaryGap:!0),e.series[n].__type=a,e.series[n].__itemStyle=l.clone(e.series[n].itemStyle||{})),(this._magicMap[V]||this._magicMap[U])&&(e.series[n].__stack=e.series[n].stack)}this._magicType=t?{}:this._magicType||{};for(var r in this._magicType)if(this._magicType[r]){this.option=e,this.getMagicOption();break}var s=e.dataZoom;if(s&&s.show){var h=null!=s.start&&s.start>=0&&s.start<=100?s.start:0,m=null!=s.end&&s.end>=0&&s.end<=100?s.end:100;h>m&&(h+=m,m=h-m,h-=m),this._zoomQueue=[{start:h,end:m,start2:0,end2:100}]}else this._zoomQueue=[]},getMagicOption:function(){var e,t;if(this._magicType[s.CHART_TYPE_LINE]||this._magicType[s.CHART_TYPE_BAR]){for(var i=this._magicType[s.CHART_TYPE_LINE]?!1:!0,n=0,a=this.option.series.length;a>n;n++)t=this.option.series[n].type,(t==s.CHART_TYPE_LINE||t==s.CHART_TYPE_BAR)&&(e=this.option.xAxis instanceof Array?this.option.xAxis[this.option.series[n].xAxisIndex||0]:this.option.xAxis,e&&"category"===(e.type||"category")&&(e.boundaryGap=i?!0:e.__boundaryGap),e=this.option.yAxis instanceof Array?this.option.yAxis[this.option.series[n].yAxisIndex||0]:this.option.yAxis,e&&"category"===e.type&&(e.boundaryGap=i?!0:e.__boundaryGap));this._defaultMagic(s.CHART_TYPE_LINE,s.CHART_TYPE_BAR)}if(this._defaultMagic(s.CHART_TYPE_CHORD,s.CHART_TYPE_FORCE),this._defaultMagic(s.CHART_TYPE_PIE,s.CHART_TYPE_FUNNEL),this._magicType[V]||this._magicType[U])for(var n=0,a=this.option.series.length;a>n;n++)this._magicType[V]?(this.option.series[n].stack="_ECHARTS_STACK_KENER_2014_",t=V):this._magicType[U]&&(this.option.series[n].stack=null,t=U),this._featureOption[t+"Chart"]&&l.merge(this.option.series[n],this._featureOption[t+"Chart"]||{},!0);return this.option},_defaultMagic:function(e,t){if(this._magicType[e]||this._magicType[t])for(var i=0,n=this.option.series.length;n>i;i++){var a=this.option.series[i].type;(a==e||a==t)&&(this.option.series[i].type=this._magicType[e]?e:t,this.option.series[i].itemStyle=l.clone(this.option.series[i].__itemStyle),a=this.option.series[i].type,this._featureOption[a+"Chart"]&&l.merge(this.option.series[i],this._featureOption[a+"Chart"]||{},!0))}},silence:function(e){this._isSilence=e},resize:function(){this._resetMark(),this.clear(),this.option&&this.option.toolbox&&this.option.toolbox.show&&this._buildShape(),this._dataView&&this._dataView.resize()},hideDataView:function(){this._dataView&&this._dataView.hide()},clear:function(e){this.zr&&(this.zr.delShape(this.shapeList),this.shapeList=[],e||(this.zr.delShape(this._markShapeList),this._markShapeList=[]))},onbeforDispose:function(){this._dataView&&(this._dataView.dispose(),this._dataView=null),this._markShapeList=null},refresh:function(e){e&&(this._resetMark(),this._resetZoom(),e.toolbox=this.reformOption(e.toolbox),this.option=e,this.clear(!0),e.toolbox.show&&this._buildShape(),this.hideDataView())}},l.inherits(t,i),e("../component").define("toolbox",t),t}),i("echarts/component",[],function(){var e={},t={};return e.define=function(i,n){return t[i]=n,e},e.get=function(e){return t[e]},e}),i("echarts/component/title",["require","./base","zrender/shape/Text","zrender/shape/Rectangle","../config","zrender/tool/util","zrender/tool/area","zrender/tool/color","../component"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Rectangle"),o=e("../config");o.title={zlevel:0,z:6,show:!0,text:"",subtext:"",x:"left",y:"top",backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,padding:5,itemGap:5,textStyle:{fontSize:18,fontWeight:"bolder",color:"#333"},subtextStyle:{color:"#aaa"}};var r=e("zrender/tool/util"),s=e("zrender/tool/area"),l=e("zrender/tool/color");return t.prototype={type:o.COMPONENT_TYPE_TITLE,_buildShape:function(){if(this.titleOption.show){this._itemGroupLocation=this._getItemGroupLocation(),this._buildBackground(),this._buildItem();for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e])}},_buildItem:function(){var e=this.titleOption.text,t=this.titleOption.link,i=this.titleOption.target,a=this.titleOption.subtext,o=this.titleOption.sublink,r=this.titleOption.subtarget,s=this.getFont(this.titleOption.textStyle),h=this.getFont(this.titleOption.subtextStyle),m=this._itemGroupLocation.x,V=this._itemGroupLocation.y,U=this._itemGroupLocation.width,d=this._itemGroupLocation.height,p={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{y:V,color:this.titleOption.textStyle.color,text:e,textFont:s,textBaseline:"top"},highlightStyle:{color:l.lift(this.titleOption.textStyle.color,1),brushType:"fill"},hoverable:!1};t&&(p.hoverable=!0,p.clickable=!0,p.onclick=function(){i&&"self"==i?window.location=t:window.open(t)});var c={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{y:V+d,color:this.titleOption.subtextStyle.color,text:a,textFont:h,textBaseline:"bottom"},highlightStyle:{color:l.lift(this.titleOption.subtextStyle.color,1),brushType:"fill"},hoverable:!1};switch(o&&(c.hoverable=!0,c.clickable=!0,c.onclick=function(){r&&"self"==r?window.location=o:window.open(o)}),this.titleOption.x){case"center":p.style.x=c.style.x=m+U/2,p.style.textAlign=c.style.textAlign="center";break;case"left":p.style.x=c.style.x=m,p.style.textAlign=c.style.textAlign="left";break;case"right":p.style.x=c.style.x=m+U,p.style.textAlign=c.style.textAlign="right";break;default:m=this.titleOption.x-0,m=isNaN(m)?0:m,p.style.x=c.style.x=m}this.titleOption.textAlign&&(p.style.textAlign=c.style.textAlign=this.titleOption.textAlign),this.shapeList.push(new n(p)),""!==a&&this.shapeList.push(new n(c))},_buildBackground:function(){var e=this.reformCssArray(this.titleOption.padding);this.shapeList.push(new a({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._itemGroupLocation.x-e[3],y:this._itemGroupLocation.y-e[0],width:this._itemGroupLocation.width+e[3]+e[1],height:this._itemGroupLocation.height+e[0]+e[2],brushType:0===this.titleOption.borderWidth?"fill":"both",color:this.titleOption.backgroundColor,strokeColor:this.titleOption.borderColor,lineWidth:this.titleOption.borderWidth}}))},_getItemGroupLocation:function(){var e,t=this.reformCssArray(this.titleOption.padding),i=this.titleOption.text,n=this.titleOption.subtext,a=this.getFont(this.titleOption.textStyle),o=this.getFont(this.titleOption.subtextStyle),r=Math.max(s.getTextWidth(i,a),s.getTextWidth(n,o)),l=s.getTextHeight(i,a)+(""===n?0:this.titleOption.itemGap+s.getTextHeight(n,o)),h=this.zr.getWidth();switch(this.titleOption.x){case"center":e=Math.floor((h-r)/2);break;case"left":e=t[3]+this.titleOption.borderWidth;break;case"right":e=h-r-t[1]-this.titleOption.borderWidth;break;default:e=this.titleOption.x-0,e=isNaN(e)?0:e}var m,V=this.zr.getHeight();switch(this.titleOption.y){case"top":m=t[0]+this.titleOption.borderWidth;break;case"bottom":m=V-l-t[2]-this.titleOption.borderWidth;break;case"center":m=Math.floor((V-l)/2);break;default:m=this.titleOption.y-0,m=isNaN(m)?0:m}return{x:e,y:m,width:r,height:l}},refresh:function(e){e&&(this.option=e,this.option.title=this.reformOption(this.option.title),this.titleOption=this.option.title,this.titleOption.textStyle=this.getTextStyle(this.titleOption.textStyle),this.titleOption.subtextStyle=this.getTextStyle(this.titleOption.subtextStyle)),this.clear(),this._buildShape()}},r.inherits(t,i),e("../component").define("title",t),t}),i("echarts/component/tooltip",["require","./base","../util/shape/Cross","zrender/shape/Line","zrender/shape/Rectangle","../config","../util/ecData","zrender/config","zrender/tool/event","zrender/tool/area","zrender/tool/color","zrender/tool/util","zrender/shape/Base","../component"],function(e){function t(e,t,o,r,s){i.call(this,e,t,o,r,s),this.dom=s.dom;var l=this;l._onmousemove=function(e){return l.__onmousemove(e)},l._onglobalout=function(e){return l.__onglobalout(e)},this.zr.on(h.EVENT.MOUSEMOVE,l._onmousemove),this.zr.on(h.EVENT.GLOBALOUT,l._onglobalout),l._hide=function(e){return l.__hide(e)},l._tryShow=function(e){return l.__tryShow(e)},l._refixed=function(e){return l.__refixed(e)},l._setContent=function(e,t){return l.__setContent(e,t)},this._tDom=this._tDom||document.createElement("div"),this._tDom.onselectstart=function(){return!1},this._tDom.onmouseover=function(){l._mousein=!0},this._tDom.onmouseout=function(){l._mousein=!1},this._tDom.className="echarts-tooltip",this._tDom.style.position="absolute",this.hasAppend=!1,this._axisLineShape&&this.zr.delShape(this._axisLineShape.id),this._axisLineShape=new a({zlevel:this.getZlevelBase(),z:this.getZBase(),invisible:!0,hoverable:!1}),this.shapeList.push(this._axisLineShape),this.zr.addShape(this._axisLineShape),this._axisShadowShape&&this.zr.delShape(this._axisShadowShape.id),this._axisShadowShape=new a({zlevel:this.getZlevelBase(),z:1,invisible:!0,hoverable:!1}),this.shapeList.push(this._axisShadowShape),this.zr.addShape(this._axisShadowShape),this._axisCrossShape&&this.zr.delShape(this._axisCrossShape.id),this._axisCrossShape=new n({zlevel:this.getZlevelBase(),z:this.getZBase(),invisible:!0,hoverable:!1}),this.shapeList.push(this._axisCrossShape),this.zr.addShape(this._axisCrossShape),this.showing=!1,this.refresh(r)}var i=e("./base"),n=e("../util/shape/Cross"),a=e("zrender/shape/Line"),o=e("zrender/shape/Rectangle"),r=new o({}),s=e("../config");s.tooltip={zlevel:1,z:8,show:!0,showContent:!0,trigger:"item",islandFormatter:"{a}
                          {b} : {c}",showDelay:20,hideDelay:100,transitionDuration:.4,enterable:!1,backgroundColor:"rgba(0,0,0,0.7)",borderColor:"#333",borderRadius:4,borderWidth:0,padding:5,axisPointer:{type:"line",lineStyle:{color:"#48b",width:2,type:"solid"},crossStyle:{color:"#1e90ff",width:1,type:"dashed"},shadowStyle:{color:"rgba(150,150,150,0.3)",width:"auto",type:"default"}},textStyle:{color:"#fff"}};var l=e("../util/ecData"),h=e("zrender/config"),m=e("zrender/tool/event"),V=e("zrender/tool/area"),U=e("zrender/tool/color"),d=e("zrender/tool/util"),p=e("zrender/shape/Base");return t.prototype={type:s.COMPONENT_TYPE_TOOLTIP,_gCssText:"position:absolute;display:block;border-style:solid;white-space:nowrap;",_style:function(e){if(!e)return"";var t=[];if(e.transitionDuration){var i="left "+e.transitionDuration+"s,top "+e.transitionDuration+"s";t.push("transition:"+i),t.push("-moz-transition:"+i),t.push("-webkit-transition:"+i),t.push("-o-transition:"+i)}e.backgroundColor&&(t.push("background-Color:"+U.toHex(e.backgroundColor)),t.push("filter:alpha(opacity=70)"),t.push("background-Color:"+e.backgroundColor)),null!=e.borderWidth&&t.push("border-width:"+e.borderWidth+"px"),null!=e.borderColor&&t.push("border-color:"+e.borderColor),null!=e.borderRadius&&(t.push("border-radius:"+e.borderRadius+"px"),t.push("-moz-border-radius:"+e.borderRadius+"px"),t.push("-webkit-border-radius:"+e.borderRadius+"px"),t.push("-o-border-radius:"+e.borderRadius+"px"));var n=e.textStyle;n&&(n.color&&t.push("color:"+n.color),n.decoration&&t.push("text-decoration:"+n.decoration),n.align&&t.push("text-align:"+n.align),n.fontFamily&&t.push("font-family:"+n.fontFamily),n.fontSize&&t.push("font-size:"+n.fontSize+"px"),n.fontSize&&t.push("line-height:"+Math.round(3*n.fontSize/2)+"px"),n.fontStyle&&t.push("font-style:"+n.fontStyle),n.fontWeight&&t.push("font-weight:"+n.fontWeight));var a=e.padding;return null!=a&&(a=this.reformCssArray(a),t.push("padding:"+a[0]+"px "+a[1]+"px "+a[2]+"px "+a[3]+"px")),t=t.join(";")+";"},__hide:function(){this._lastDataIndex=-1,this._lastSeriesIndex=-1,this._lastItemTriggerId=-1,this._tDom&&(this._tDom.style.display="none");var e=!1;this._axisLineShape.invisible||(this._axisLineShape.invisible=!0, -this.zr.modShape(this._axisLineShape.id),e=!0),this._axisShadowShape.invisible||(this._axisShadowShape.invisible=!0,this.zr.modShape(this._axisShadowShape.id),e=!0),this._axisCrossShape.invisible||(this._axisCrossShape.invisible=!0,this.zr.modShape(this._axisCrossShape.id),e=!0),this._lastTipShape&&this._lastTipShape.tipShape.length>0&&(this.zr.delShape(this._lastTipShape.tipShape),this._lastTipShape=!1,this.shapeList.length=2),e&&this.zr.refreshNextFrame(),this.showing=!1},_show:function(e,t,i,n){var a=this._tDom.offsetHeight,o=this._tDom.offsetWidth;e&&("function"==typeof e&&(e=e([t,i])),e instanceof Array&&(t=e[0],i=e[1])),t+o>this._zrWidth&&(t-=o+40),i+a>this._zrHeight&&(i-=a-20),20>i&&(i=0),this._tDom.style.cssText=this._gCssText+this._defaultCssText+(n?n:"")+"left:"+t+"px;top:"+i+"px;",(10>a||10>o)&&setTimeout(this._refixed,20),this.showing=!0},__refixed:function(){if(this._tDom){var e="",t=this._tDom.offsetHeight,i=this._tDom.offsetWidth;this._tDom.offsetLeft+i>this._zrWidth&&(e+="left:"+(this._zrWidth-i-20)+"px;"),this._tDom.offsetTop+t>this._zrHeight&&(e+="top:"+(this._zrHeight-t-10)+"px;"),""!==e&&(this._tDom.style.cssText+=e)}},__tryShow:function(){var e,t;if(this._curTarget){if("island"===this._curTarget._type&&this.option.tooltip.show)return void this._showItemTrigger();var i=l.get(this._curTarget,"series"),n=l.get(this._curTarget,"data");e=this.deepQuery([n,i,this.option],"tooltip.show"),null!=i&&null!=n&&e?(t=this.deepQuery([n,i,this.option],"tooltip.trigger"),"axis"===t?this._showAxisTrigger(i.xAxisIndex,i.yAxisIndex,l.get(this._curTarget,"dataIndex")):this._showItemTrigger()):(clearTimeout(this._hidingTicket),clearTimeout(this._showingTicket),this._hidingTicket=setTimeout(this._hide,this._hideDelay))}else this._findPolarTrigger()||this._findAxisTrigger()},_findAxisTrigger:function(){if(!this.component.xAxis||!this.component.yAxis)return void(this._hidingTicket=setTimeout(this._hide,this._hideDelay));for(var e,t,i=this.option.series,n=0,a=i.length;a>n;n++)if("axis"===this.deepQuery([i[n],this.option],"tooltip.trigger"))return e=i[n].xAxisIndex||0,t=i[n].yAxisIndex||0,this.component.xAxis.getAxis(e)&&this.component.xAxis.getAxis(e).type===s.COMPONENT_TYPE_AXIS_CATEGORY?void this._showAxisTrigger(e,t,this._getNearestDataIndex("x",this.component.xAxis.getAxis(e))):this.component.yAxis.getAxis(t)&&this.component.yAxis.getAxis(t).type===s.COMPONENT_TYPE_AXIS_CATEGORY?void this._showAxisTrigger(e,t,this._getNearestDataIndex("y",this.component.yAxis.getAxis(t))):void this._showAxisTrigger(e,t,-1);"cross"===this.option.tooltip.axisPointer.type&&this._showAxisTrigger(-1,-1,-1)},_findPolarTrigger:function(){if(!this.component.polar)return!1;var e,t=m.getX(this._event),i=m.getY(this._event),n=this.component.polar.getNearestIndex([t,i]);return n?(e=n.valueIndex,n=n.polarIndex):n=-1,-1!=n?this._showPolarTrigger(n,e):!1},_getNearestDataIndex:function(e,t){var i=-1,n=m.getX(this._event),a=m.getY(this._event);if("x"===e){for(var o,r,s=this.component.grid.getXend(),l=t.getCoordByIndex(i);s>l&&(r=l,n>=l);)o=l,l=t.getCoordByIndex(++i);return 0>=i?i=0:r-n>=n-o?i-=1:null==t.getNameByIndex(i)&&(i-=1),i}for(var h,V,U=this.component.grid.getY(),l=t.getCoordByIndex(i);l>U&&(h=l,l>=a);)V=l,l=t.getCoordByIndex(++i);return 0>=i?i=0:a-h>=V-a?i-=1:null==t.getNameByIndex(i)&&(i-=1),i},_showAxisTrigger:function(e,t,i){if(!this._event.connectTrigger&&this.messageCenter.dispatch(s.EVENT.TOOLTIP_IN_GRID,this._event,null,this.myChart),null==this.component.xAxis||null==this.component.yAxis||null==e||null==t)return clearTimeout(this._hidingTicket),clearTimeout(this._showingTicket),void(this._hidingTicket=setTimeout(this._hide,this._hideDelay));var n,a,o,r,l=this.option.series,h=[],V=[],U="";if("axis"===this.option.tooltip.trigger){if(!this.option.tooltip.show)return;a=this.option.tooltip.formatter,o=this.option.tooltip.position}var d,p,c=-1!=e&&this.component.xAxis.getAxis(e).type===s.COMPONENT_TYPE_AXIS_CATEGORY?"xAxis":-1!=t&&this.component.yAxis.getAxis(t).type===s.COMPONENT_TYPE_AXIS_CATEGORY?"yAxis":!1;if(c){var u="xAxis"==c?e:t;n=this.component[c].getAxis(u);for(var y=0,g=l.length;g>y;y++)this._isSelected(l[y].name)&&l[y][c+"Index"]===u&&"axis"===this.deepQuery([l[y],this.option],"tooltip.trigger")&&(r=this.query(l[y],"tooltip.showContent")||r,a=this.query(l[y],"tooltip.formatter")||a,o=this.query(l[y],"tooltip.position")||o,U+=this._style(this.query(l[y],"tooltip")),null!=l[y].stack&&"xAxis"==c?(h.unshift(l[y]),V.unshift(y)):(h.push(l[y]),V.push(y)));this.messageCenter.dispatch(s.EVENT.TOOLTIP_HOVER,this._event,{seriesIndex:V,dataIndex:i},this.myChart);var b;"xAxis"==c?(d=this.subPixelOptimize(n.getCoordByIndex(i),this._axisLineWidth),p=m.getY(this._event),b=[d,this.component.grid.getY(),d,this.component.grid.getYend()]):(d=m.getX(this._event),p=this.subPixelOptimize(n.getCoordByIndex(i),this._axisLineWidth),b=[this.component.grid.getX(),p,this.component.grid.getXend(),p]),this._styleAxisPointer(h,b[0],b[1],b[2],b[3],n.getGap(),d,p)}else d=m.getX(this._event),p=m.getY(this._event),this._styleAxisPointer(l,this.component.grid.getX(),p,this.component.grid.getXend(),p,0,d,p),i>=0?this._showItemTrigger(!0):(clearTimeout(this._hidingTicket),clearTimeout(this._showingTicket),this._tDom.style.display="none");if(h.length>0){if(this._lastItemTriggerId=-1,this._lastDataIndex!=i||this._lastSeriesIndex!=V[0]){this._lastDataIndex=i,this._lastSeriesIndex=V[0];var f,k;if("function"==typeof a){for(var x=[],y=0,g=h.length;g>y;y++)f=h[y].data[i],k=this.getDataFromOption(f,"-"),x.push({seriesIndex:V[y],seriesName:h[y].name||"",series:h[y],dataIndex:i,data:f,name:n.getNameByIndex(i),value:k,0:h[y].name||"",1:n.getNameByIndex(i),2:k,3:f});this._curTicket="axis:"+i,this._tDom.innerHTML=a.call(this.myChart,x,this._curTicket,this._setContent)}else if("string"==typeof a){this._curTicket=0/0,a=a.replace("{a}","{a0}").replace("{b}","{b0}").replace("{c}","{c0}");for(var y=0,g=h.length;g>y;y++)a=a.replace("{a"+y+"}",this._encodeHTML(h[y].name||"")),a=a.replace("{b"+y+"}",this._encodeHTML(n.getNameByIndex(i))),f=h[y].data[i],f=this.getDataFromOption(f,"-"),a=a.replace("{c"+y+"}",f instanceof Array?f:this.numAddCommas(f));this._tDom.innerHTML=a}else{this._curTicket=0/0,a=this._encodeHTML(n.getNameByIndex(i));for(var y=0,g=h.length;g>y;y++)a+="
                          "+this._encodeHTML(h[y].name||"")+" : ",f=h[y].data[i],f=this.getDataFromOption(f,"-"),a+=f instanceof Array?f:this.numAddCommas(f);this._tDom.innerHTML=a}}if(r===!1||!this.option.tooltip.showContent)return;this.hasAppend||(this._tDom.style.left=this._zrWidth/2+"px",this._tDom.style.top=this._zrHeight/2+"px",this.dom.firstChild.appendChild(this._tDom),this.hasAppend=!0),this._show(o,d+10,p+10,U)}},_showPolarTrigger:function(e,t){if(null==this.component.polar||null==e||null==t||0>t)return!1;var i,n,a,o=this.option.series,r=[],s=[],l="";if("axis"===this.option.tooltip.trigger){if(!this.option.tooltip.show)return!1;i=this.option.tooltip.formatter,n=this.option.tooltip.position}for(var h=this.option.polar[e].indicator[t].text,V=0,U=o.length;U>V;V++)this._isSelected(o[V].name)&&o[V].polarIndex===e&&"axis"===this.deepQuery([o[V],this.option],"tooltip.trigger")&&(a=this.query(o[V],"tooltip.showContent")||a,i=this.query(o[V],"tooltip.formatter")||i,n=this.query(o[V],"tooltip.position")||n,l+=this._style(this.query(o[V],"tooltip")),r.push(o[V]),s.push(V));if(r.length>0){for(var d,p,c,u=[],V=0,U=r.length;U>V;V++){d=r[V].data;for(var y=0,g=d.length;g>y;y++)p=d[y],this._isSelected(p.name)&&(p=null!=p?p:{name:"",value:{dataIndex:"-"}},c=this.getDataFromOption(p.value[t]),u.push({seriesIndex:s[V],seriesName:r[V].name||"",series:r[V],dataIndex:t,data:p,name:p.name,indicator:h,value:c,0:r[V].name||"",1:p.name,2:c,3:h}))}if(u.length<=0)return;if(this._lastItemTriggerId=-1,this._lastDataIndex!=t||this._lastSeriesIndex!=s[0])if(this._lastDataIndex=t,this._lastSeriesIndex=s[0],"function"==typeof i)this._curTicket="axis:"+t,this._tDom.innerHTML=i.call(this.myChart,u,this._curTicket,this._setContent);else if("string"==typeof i){i=i.replace("{a}","{a0}").replace("{b}","{b0}").replace("{c}","{c0}").replace("{d}","{d0}");for(var V=0,U=u.length;U>V;V++)i=i.replace("{a"+V+"}",this._encodeHTML(u[V].seriesName)),i=i.replace("{b"+V+"}",this._encodeHTML(u[V].name)),i=i.replace("{c"+V+"}",this.numAddCommas(u[V].value)),i=i.replace("{d"+V+"}",this._encodeHTML(u[V].indicator));this._tDom.innerHTML=i}else{i=this._encodeHTML(u[0].name)+"
                          "+this._encodeHTML(u[0].indicator)+" : "+this.numAddCommas(u[0].value);for(var V=1,U=u.length;U>V;V++)i+="
                          "+this._encodeHTML(u[V].name)+"
                          ",i+=this._encodeHTML(u[V].indicator)+" : "+this.numAddCommas(u[V].value);this._tDom.innerHTML=i}if(a===!1||!this.option.tooltip.showContent)return;return this.hasAppend||(this._tDom.style.left=this._zrWidth/2+"px",this._tDom.style.top=this._zrHeight/2+"px",this.dom.firstChild.appendChild(this._tDom),this.hasAppend=!0),this._show(n,m.getX(this._event),m.getY(this._event),l),!0}},_showItemTrigger:function(e){if(this._curTarget){var t,i,n,a=l.get(this._curTarget,"series"),o=l.get(this._curTarget,"seriesIndex"),r=l.get(this._curTarget,"data"),h=l.get(this._curTarget,"dataIndex"),V=l.get(this._curTarget,"name"),U=l.get(this._curTarget,"value"),d=l.get(this._curTarget,"special"),p=l.get(this._curTarget,"special2"),c=[r,a,this.option],u="";if("island"!=this._curTarget._type){var y=e?"axis":"item";this.option.tooltip.trigger===y&&(t=this.option.tooltip.formatter,i=this.option.tooltip.position),this.query(a,"tooltip.trigger")===y&&(n=this.query(a,"tooltip.showContent")||n,t=this.query(a,"tooltip.formatter")||t,i=this.query(a,"tooltip.position")||i,u+=this._style(this.query(a,"tooltip"))),n=this.query(r,"tooltip.showContent")||n,t=this.query(r,"tooltip.formatter")||t,i=this.query(r,"tooltip.position")||i,u+=this._style(this.query(r,"tooltip"))}else this._lastItemTriggerId=0/0,n=this.deepQuery(c,"tooltip.showContent"),t=this.deepQuery(c,"tooltip.islandFormatter"),i=this.deepQuery(c,"tooltip.islandPosition");this._lastDataIndex=-1,this._lastSeriesIndex=-1,this._lastItemTriggerId!==this._curTarget.id&&(this._lastItemTriggerId=this._curTarget.id,"function"==typeof t?(this._curTicket=(a.name||"")+":"+h,this._tDom.innerHTML=t.call(this.myChart,{seriesIndex:o,seriesName:a.name||"",series:a,dataIndex:h,data:r,name:V,value:U,percent:d,indicator:d,value2:p,indicator2:p,0:a.name||"",1:V,2:U,3:d,4:p,5:r,6:o,7:h},this._curTicket,this._setContent)):"string"==typeof t?(this._curTicket=0/0,t=t.replace("{a}","{a0}").replace("{b}","{b0}").replace("{c}","{c0}"),t=t.replace("{a0}",this._encodeHTML(a.name||"")).replace("{b0}",this._encodeHTML(V)).replace("{c0}",U instanceof Array?U:this.numAddCommas(U)),t=t.replace("{d}","{d0}").replace("{d0}",d||""),t=t.replace("{e}","{e0}").replace("{e0}",l.get(this._curTarget,"special2")||""),this._tDom.innerHTML=t):(this._curTicket=0/0,this._tDom.innerHTML=a.type===s.CHART_TYPE_RADAR&&d?this._itemFormatter.radar.call(this,a,V,U,d):a.type===s.CHART_TYPE_EVENTRIVER?this._itemFormatter.eventRiver.call(this,a,V,U,r):""+(null!=a.name?this._encodeHTML(a.name)+"
                          ":"")+(""===V?"":this._encodeHTML(V)+" : ")+(U instanceof Array?U:this.numAddCommas(U))));var g=m.getX(this._event),b=m.getY(this._event);this.deepQuery(c,"tooltip.axisPointer.show")&&this.component.grid?this._styleAxisPointer([a],this.component.grid.getX(),b,this.component.grid.getXend(),b,0,g,b):this._hide(),n!==!1&&this.option.tooltip.showContent&&(this.hasAppend||(this._tDom.style.left=this._zrWidth/2+"px",this._tDom.style.top=this._zrHeight/2+"px",this.dom.firstChild.appendChild(this._tDom),this.hasAppend=!0),this._show(i,g+20,b-20,u))}},_itemFormatter:{radar:function(e,t,i,n){var a="";a+=this._encodeHTML(""===t?e.name||"":t),a+=""===a?"":"
                          ";for(var o=0;o";return a},chord:function(e,t,i,n,a){if(null==a)return this._encodeHTML(t)+" ("+this.numAddCommas(i)+")";var o=this._encodeHTML(t),r=this._encodeHTML(n);return""+(null!=e.name?this._encodeHTML(e.name)+"
                          ":"")+o+" -> "+r+" ("+this.numAddCommas(i)+")
                          "+r+" -> "+o+" ("+this.numAddCommas(a)+")"},eventRiver:function(e,t,i,n){var a="";a+=this._encodeHTML(""===e.name?"":e.name+" : "),a+=this._encodeHTML(t),a+=""===a?"":"
                          ",n=n.evolution;for(var o=0,r=n.length;r>o;o++)a+='
                          ");return a}},_styleAxisPointer:function(e,t,i,n,a,o,r,s){if(e.length>0){var l,h,m=this.option.tooltip.axisPointer,V=m.type,U={line:{},cross:{},shadow:{}};for(var d in U)U[d].color=m[d+"Style"].color,U[d].width=m[d+"Style"].width,U[d].type=m[d+"Style"].type;for(var p=0,c=e.length;c>p;p++)l=e[p],h=this.query(l,"tooltip.axisPointer.type"),V=h||V,h&&(U[h].color=this.query(l,"tooltip.axisPointer."+h+"Style.color")||U[h].color,U[h].width=this.query(l,"tooltip.axisPointer."+h+"Style.width")||U[h].width,U[h].type=this.query(l,"tooltip.axisPointer."+h+"Style.type")||U[h].type);if("line"===V){var u=U.line.width,y=t==n;this._axisLineShape.style={xStart:y?this.subPixelOptimize(t,u):t,yStart:y?i:this.subPixelOptimize(i,u),xEnd:y?this.subPixelOptimize(n,u):n,yEnd:y?a:this.subPixelOptimize(a,u),strokeColor:U.line.color,lineWidth:u,lineType:U.line.type},this._axisLineShape.invisible=!1,this.zr.modShape(this._axisLineShape.id)}else if("cross"===V){var g=U.cross.width;this._axisCrossShape.style={brushType:"stroke",rect:this.component.grid.getArea(),x:this.subPixelOptimize(r,g),y:this.subPixelOptimize(s,g),text:("( "+this.component.xAxis.getAxis(0).getValueFromCoord(r)+" , "+this.component.yAxis.getAxis(0).getValueFromCoord(s)+" )").replace(" , "," ").replace(" , "," "),textPosition:"specific",strokeColor:U.cross.color,lineWidth:g,lineType:U.cross.type},this.component.grid.getXend()-r>100?(this._axisCrossShape.style.textAlign="left",this._axisCrossShape.style.textX=r+10):(this._axisCrossShape.style.textAlign="right",this._axisCrossShape.style.textX=r-10),s-this.component.grid.getY()>50?(this._axisCrossShape.style.textBaseline="bottom",this._axisCrossShape.style.textY=s-10):(this._axisCrossShape.style.textBaseline="top",this._axisCrossShape.style.textY=s+10),this._axisCrossShape.invisible=!1,this.zr.modShape(this._axisCrossShape.id)}else"shadow"===V&&((null==U.shadow.width||"auto"===U.shadow.width||isNaN(U.shadow.width))&&(U.shadow.width=o),t===n?Math.abs(this.component.grid.getX()-t)<2?(U.shadow.width/=2,t=n+=U.shadow.width/2):Math.abs(this.component.grid.getXend()-t)<2&&(U.shadow.width/=2,t=n-=U.shadow.width/2):i===a&&(Math.abs(this.component.grid.getY()-i)<2?(U.shadow.width/=2,i=a+=U.shadow.width/2):Math.abs(this.component.grid.getYend()-i)<2&&(U.shadow.width/=2,i=a-=U.shadow.width/2)),this._axisShadowShape.style={xStart:t,yStart:i,xEnd:n,yEnd:a,strokeColor:U.shadow.color,lineWidth:U.shadow.width},this._axisShadowShape.invisible=!1,this.zr.modShape(this._axisShadowShape.id));this.zr.refreshNextFrame()}},__onmousemove:function(e){if(clearTimeout(this._hidingTicket),clearTimeout(this._showingTicket),!this._mousein||!this._enterable){var t=e.target,i=m.getX(e.event),n=m.getY(e.event);if(t){this._curTarget=t,this._event=e.event,this._event.zrenderX=i,this._event.zrenderY=n;var a;if(this._needAxisTrigger&&this.component.polar&&-1!=(a=this.component.polar.isInside([i,n])))for(var o=this.option.series,l=0,h=o.length;h>l;l++)if(o[l].polarIndex===a&&"axis"===this.deepQuery([o[l],this.option],"tooltip.trigger")){this._curTarget=null;break}this._showingTicket=setTimeout(this._tryShow,this._showDelay)}else this._curTarget=!1,this._event=e.event,this._event.zrenderX=i,this._event.zrenderY=n,this._needAxisTrigger&&this.component.grid&&V.isInside(r,this.component.grid.getArea(),i,n)?this._showingTicket=setTimeout(this._tryShow,this._showDelay):this._needAxisTrigger&&this.component.polar&&-1!=this.component.polar.isInside([i,n])?this._showingTicket=setTimeout(this._tryShow,this._showDelay):(!this._event.connectTrigger&&this.messageCenter.dispatch(s.EVENT.TOOLTIP_OUT_GRID,this._event,null,this.myChart),this._hidingTicket=setTimeout(this._hide,this._hideDelay))}},__onglobalout:function(){clearTimeout(this._hidingTicket),clearTimeout(this._showingTicket),this._hidingTicket=setTimeout(this._hide,this._hideDelay)},__setContent:function(e,t){this._tDom&&(e===this._curTicket&&(this._tDom.innerHTML=t),setTimeout(this._refixed,20))},ontooltipHover:function(e,t){if(!this._lastTipShape||this._lastTipShape&&this._lastTipShape.dataIndex!=e.dataIndex){this._lastTipShape&&this._lastTipShape.tipShape.length>0&&(this.zr.delShape(this._lastTipShape.tipShape),this.shapeList.length=2);for(var i=0,n=t.length;n>i;i++)t[i].zlevel=this.getZlevelBase(),t[i].z=this.getZBase(),t[i].style=p.prototype.getHighlightStyle(t[i].style,t[i].highlightStyle),t[i].draggable=!1,t[i].hoverable=!1,t[i].clickable=!1,t[i].ondragend=null,t[i].ondragover=null,t[i].ondrop=null,this.shapeList.push(t[i]),this.zr.addShape(t[i]);this._lastTipShape={dataIndex:e.dataIndex,tipShape:t}}},ondragend:function(){this._hide()},onlegendSelected:function(e){this._selectedMap=e.selected},_setSelectedMap:function(){this._selectedMap=this.component.legend?d.clone(this.component.legend.getSelectedMap()):{}},_isSelected:function(e){return null!=this._selectedMap[e]?this._selectedMap[e]:!0},showTip:function(e){if(e){var t,i=this.option.series;if(null!=e.seriesIndex)t=e.seriesIndex;else for(var n=e.seriesName,a=0,o=i.length;o>a;a++)if(i[a].name===n){t=a;break}var r=i[t];if(null!=r){var m=this.myChart.chart[r.type],V="axis"===this.deepQuery([r,this.option],"tooltip.trigger");if(m)if(V){var U=e.dataIndex;switch(m.type){case s.CHART_TYPE_LINE:case s.CHART_TYPE_BAR:case s.CHART_TYPE_K:case s.CHART_TYPE_RADAR:if(null==this.component.polar||r.data[0].value.length<=U)return;var d=r.polarIndex||0,p=this.component.polar.getVector(d,U,"max");this._event={zrenderX:p[0],zrenderY:p[1]},this._showPolarTrigger(d,U)}}else{var c,u,y=m.shapeList;switch(m.type){case s.CHART_TYPE_LINE:case s.CHART_TYPE_BAR:case s.CHART_TYPE_K:case s.CHART_TYPE_TREEMAP:case s.CHART_TYPE_SCATTER:for(var U=e.dataIndex,a=0,o=y.length;o>a;a++)if(null==y[a]._mark&&l.get(y[a],"seriesIndex")==t&&l.get(y[a],"dataIndex")==U){this._curTarget=y[a],c=y[a].style.x,u=m.type!=s.CHART_TYPE_K?y[a].style.y:y[a].style.y[0];break}break;case s.CHART_TYPE_RADAR:for(var U=e.dataIndex,a=0,o=y.length;o>a;a++)if("polygon"===y[a].type&&l.get(y[a],"seriesIndex")==t&&l.get(y[a],"dataIndex")==U){this._curTarget=y[a];var p=this.component.polar.getCenter(r.polarIndex||0);c=p[0],u=p[1];break}break;case s.CHART_TYPE_PIE:for(var g=e.name,a=0,o=y.length;o>a;a++)if("sector"===y[a].type&&l.get(y[a],"seriesIndex")==t&&l.get(y[a],"name")==g){this._curTarget=y[a];var b=this._curTarget.style,f=(b.startAngle+b.endAngle)/2*Math.PI/180;c=this._curTarget.style.x+Math.cos(f)*b.r/1.5,u=this._curTarget.style.y-Math.sin(f)*b.r/1.5;break}break;case s.CHART_TYPE_MAP:for(var g=e.name,k=r.mapType,a=0,o=y.length;o>a;a++)if("text"===y[a].type&&y[a]._mapType===k&&y[a].style._name===g){this._curTarget=y[a],c=this._curTarget.style.x+this._curTarget.position[0],u=this._curTarget.style.y+this._curTarget.position[1];break}break;case s.CHART_TYPE_CHORD:for(var g=e.name,a=0,o=y.length;o>a;a++)if("sector"===y[a].type&&l.get(y[a],"name")==g){this._curTarget=y[a];var b=this._curTarget.style,f=(b.startAngle+b.endAngle)/2*Math.PI/180;return c=this._curTarget.style.x+Math.cos(f)*(b.r-2),u=this._curTarget.style.y-Math.sin(f)*(b.r-2),void this.zr.trigger(h.EVENT.MOUSEMOVE,{zrenderX:c,zrenderY:u})}break;case s.CHART_TYPE_FORCE:for(var g=e.name,a=0,o=y.length;o>a;a++)if("circle"===y[a].type&&l.get(y[a],"name")==g){this._curTarget=y[a],c=this._curTarget.position[0],u=this._curTarget.position[1];break}}null!=c&&null!=u&&(this._event={zrenderX:c,zrenderY:u},this.zr.addHoverShape(this._curTarget),this.zr.refreshHover(),this._showItemTrigger())}}}},hideTip:function(){this._hide()},refresh:function(e){if(this._zrHeight=this.zr.getHeight(),this._zrWidth=this.zr.getWidth(),this._lastTipShape&&this._lastTipShape.tipShape.length>0&&this.zr.delShape(this._lastTipShape.tipShape),this._lastTipShape=!1,this.shapeList.length=2,this._lastDataIndex=-1,this._lastSeriesIndex=-1,this._lastItemTriggerId=-1,e){this.option=e,this.option.tooltip=this.reformOption(this.option.tooltip),this.option.tooltip.textStyle=d.merge(this.option.tooltip.textStyle,this.ecTheme.textStyle),this._needAxisTrigger=!1,"axis"===this.option.tooltip.trigger&&(this._needAxisTrigger=!0);for(var t=this.option.series,i=0,n=t.length;n>i;i++)if("axis"===this.query(t[i],"tooltip.trigger")){this._needAxisTrigger=!0;break}this._showDelay=this.option.tooltip.showDelay,this._hideDelay=this.option.tooltip.hideDelay,this._defaultCssText=this._style(this.option.tooltip),this._setSelectedMap(),this._axisLineWidth=this.option.tooltip.axisPointer.lineStyle.width,this._enterable=this.option.tooltip.enterable,!this._enterable&&this._tDom.className.indexOf(h.elementClassName)<0&&(this._tDom.className+=" "+h.elementClassName)}if(this.showing){var a=this;setTimeout(function(){a.zr.trigger(h.EVENT.MOUSEMOVE,a.zr.handler._event)},50)}},onbeforDispose:function(){this._lastTipShape&&this._lastTipShape.tipShape.length>0&&this.zr.delShape(this._lastTipShape.tipShape),clearTimeout(this._hidingTicket),clearTimeout(this._showingTicket),this.zr.un(h.EVENT.MOUSEMOVE,this._onmousemove),this.zr.un(h.EVENT.GLOBALOUT,this._onglobalout),this.hasAppend&&this.dom.firstChild&&this.dom.firstChild.removeChild(this._tDom),this._tDom=null},_encodeHTML:function(e){return String(e).replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}},d.inherits(t,i),e("../component").define("tooltip",t),t}),i("echarts/component/legend",["require","./base","zrender/shape/Text","zrender/shape/Rectangle","zrender/shape/Sector","../util/shape/Icon","../util/shape/Candle","../config","zrender/tool/util","zrender/tool/area","../component"],function(e){function t(e,t,n,a,o){if(!this.query(a,"legend.data"))return void console.error("option.legend.data has not been defined.");i.call(this,e,t,n,a,o);var r=this;r._legendSelected=function(e){r.__legendSelected(e)},r._dispatchHoverLink=function(e){return r.__dispatchHoverLink(e)},this._colorIndex=0,this._colorMap={},this._selectedMap={},this._hasDataMap={},this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Rectangle"),o=e("zrender/shape/Sector"),r=e("../util/shape/Icon"),s=e("../util/shape/Candle"),l=e("../config");l.legend={zlevel:0,z:4,show:!0,orient:"horizontal",x:"center",y:"top",backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,padding:5,itemGap:10,itemWidth:20,itemHeight:14,textStyle:{color:"#333"},selectedMode:!0};var h=e("zrender/tool/util"),m=e("zrender/tool/area");t.prototype={type:l.COMPONENT_TYPE_LEGEND,_buildShape:function(){if(this.legendOption.show){this._itemGroupLocation=this._getItemGroupLocation(),this._buildBackground(),this._buildItem();for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e])}},_buildItem:function(){var e,t,i,a,o,s,l,V,U=this.legendOption.data,d=U.length,p=this.legendOption.textStyle,c=this.zr.getWidth(),u=this.zr.getHeight(),y=this._itemGroupLocation.x,g=this._itemGroupLocation.y,b=this.legendOption.itemWidth,f=this.legendOption.itemHeight,k=this.legendOption.itemGap;"vertical"===this.legendOption.orient&&"right"===this.legendOption.x&&(y=this._itemGroupLocation.x+this._itemGroupLocation.width-b);for(var x=0;d>x;x++)o=h.merge(U[x].textStyle||{},p),s=this.getFont(o),e=this._getName(U[x]),l=this._getFormatterName(e),""!==e?(t=U[x].icon||this._getSomethingByName(e).type,V=this.getColor(e),"horizontal"===this.legendOption.orient?200>c-y&&b+5+m.getTextWidth(l,s)+(x===d-1||""===U[x+1]?0:k)>=c-y&&(y=this._itemGroupLocation.x,g+=f+k):200>u-g&&f+(x===d-1||""===U[x+1]?0:k)>=u-g&&("right"===this.legendOption.x?y-=this._itemGroupLocation.maxWidth+k:y+=this._itemGroupLocation.maxWidth+k,g=this._itemGroupLocation.y),i=this._getItemShapeByType(y,g,b,f,this._selectedMap[e]&&this._hasDataMap[e]?V:"#ccc",t,V),i._name=e,i=new r(i),a={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:y+b+5,y:g+f/2,color:this._selectedMap[e]?"auto"===o.color?V:o.color:"#ccc",text:l,textFont:s,textBaseline:"middle"},highlightStyle:{color:V,brushType:"fill"},hoverable:!!this.legendOption.selectedMode,clickable:!!this.legendOption.selectedMode},"vertical"===this.legendOption.orient&&"right"===this.legendOption.x&&(a.style.x-=b+10,a.style.textAlign="right"),a._name=e,a=new n(a),this.legendOption.selectedMode&&(i.onclick=a.onclick=this._legendSelected,i.onmouseover=a.onmouseover=this._dispatchHoverLink,i.hoverConnect=a.id,a.hoverConnect=i.id),this.shapeList.push(i),this.shapeList.push(a),"horizontal"===this.legendOption.orient?y+=b+5+m.getTextWidth(l,s)+k:g+=f+k):"horizontal"===this.legendOption.orient?(y=this._itemGroupLocation.x,g+=f+k):("right"===this.legendOption.x?y-=this._itemGroupLocation.maxWidth+k:y+=this._itemGroupLocation.maxWidth+k,g=this._itemGroupLocation.y);"horizontal"===this.legendOption.orient&&"center"===this.legendOption.x&&g!=this._itemGroupLocation.y&&this._mLineOptimize()},_getName:function(e){return"undefined"!=typeof e.name?e.name:e},_getFormatterName:function(e){var t,i=this.legendOption.formatter;return t="function"==typeof i?i.call(this.myChart,e):"string"==typeof i?i.replace("{name}",e):e},_getFormatterNameFromData:function(e){var t=this._getName(e);return this._getFormatterName(t)},_mLineOptimize:function(){for(var e=[],t=this._itemGroupLocation.x,i=2,n=this.shapeList.length;n>i;i++)this.shapeList[i].style.x===t?e.push((this._itemGroupLocation.width-(this.shapeList[i-1].style.x+m.getTextWidth(this.shapeList[i-1].style.text,this.shapeList[i-1].style.textFont)-t))/2):i===n-1&&e.push((this._itemGroupLocation.width-(this.shapeList[i].style.x+m.getTextWidth(this.shapeList[i].style.text,this.shapeList[i].style.textFont)-t))/2);for(var a=-1,i=1,n=this.shapeList.length;n>i;i++)this.shapeList[i].style.x===t&&a++,0!==e[a]&&(this.shapeList[i].style.x+=e[a])},_buildBackground:function(){var e=this.reformCssArray(this.legendOption.padding);this.shapeList.push(new a({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._itemGroupLocation.x-e[3],y:this._itemGroupLocation.y-e[0],width:this._itemGroupLocation.width+e[3]+e[1],height:this._itemGroupLocation.height+e[0]+e[2],brushType:0===this.legendOption.borderWidth?"fill":"both",color:this.legendOption.backgroundColor,strokeColor:this.legendOption.borderColor,lineWidth:this.legendOption.borderWidth}}))},_getItemGroupLocation:function(){var e=this.legendOption.data,t=e.length,i=this.legendOption.itemGap,n=this.legendOption.itemWidth+5,a=this.legendOption.itemHeight,o=this.legendOption.textStyle,r=this.getFont(o),s=0,l=0,V=this.reformCssArray(this.legendOption.padding),U=this.zr.getWidth()-V[1]-V[3],d=this.zr.getHeight()-V[0]-V[2],p=0,c=0;if("horizontal"===this.legendOption.orient){l=a;for(var u=0;t>u;u++)if(""!==this._getName(e[u])){var y=m.getTextWidth(this._getFormatterNameFromData(e[u]),e[u].textStyle?this.getFont(h.merge(e[u].textStyle||{},o)):r);p+n+y+i>U?(p-=i,s=Math.max(s,p),l+=a+i,p=0):(p+=n+y+i,s=Math.max(s,p-i))}else p-=i,s=Math.max(s,p),l+=a+i,p=0}else{for(var u=0;t>u;u++)c=Math.max(c,m.getTextWidth(this._getFormatterNameFromData(e[u]),e[u].textStyle?this.getFont(h.merge(e[u].textStyle||{},o)):r));c+=n,s=c;for(var u=0;t>u;u++)""!==this._getName(e[u])?p+a+i>d?(s+=c+i,p-=i,l=Math.max(l,p),p=0):(p+=a+i,l=Math.max(l,p-i)):(s+=c+i,p-=i,l=Math.max(l,p),p=0)}U=this.zr.getWidth(),d=this.zr.getHeight();var g;switch(this.legendOption.x){case"center":g=Math.floor((U-s)/2);break;case"left":g=V[3]+this.legendOption.borderWidth;break;case"right":g=U-s-V[1]-V[3]-2*this.legendOption.borderWidth;break;default:g=this.parsePercent(this.legendOption.x,U)}var b;switch(this.legendOption.y){case"top":b=V[0]+this.legendOption.borderWidth;break;case"bottom":b=d-l-V[0]-V[2]-2*this.legendOption.borderWidth;break;case"center":b=Math.floor((d-l)/2);break;default:b=this.parsePercent(this.legendOption.y,d)}return{x:g,y:b,width:s,height:l,maxWidth:c}},_getSomethingByName:function(e){for(var t,i=this.option.series,n=0,a=i.length;a>n;n++){if(i[n].name===e)return{type:i[n].type,series:i[n],seriesIndex:n,data:null,dataIndex:-1};if(i[n].type===l.CHART_TYPE_PIE||i[n].type===l.CHART_TYPE_RADAR||i[n].type===l.CHART_TYPE_CHORD||i[n].type===l.CHART_TYPE_FORCE||i[n].type===l.CHART_TYPE_FUNNEL||i[n].type===l.CHART_TYPE_TREEMAP){t=i[n].categories||i[n].data||i[n].nodes;for(var o=0,r=t.length;r>o;o++)if(t[o].name===e)return{type:i[n].type,series:i[n],seriesIndex:n,data:t[o],dataIndex:o}}}return{type:"bar",series:null,seriesIndex:-1,data:null,dataIndex:-1}},_getItemShapeByType:function(e,t,i,n,a,o,r){var s,h="#ccc"===a?r:a,m={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{iconType:"legendicon"+o,x:e,y:t,width:i,height:n,color:a,strokeColor:a,lineWidth:2},highlightStyle:{color:h,strokeColor:h,lineWidth:1},hoverable:this.legendOption.selectedMode,clickable:this.legendOption.selectedMode};if(o.match("image")){var s=o.replace(new RegExp("^image:\\/\\/"),"");o="image"}switch(o){case"line":m.style.brushType="stroke",m.highlightStyle.lineWidth=3;break;case"radar":case"venn":case"tree":case"treemap":case"scatter":m.highlightStyle.lineWidth=3;break;case"k":m.style.brushType="both",m.highlightStyle.lineWidth=3,m.highlightStyle.color=m.style.color=this.deepQuery([this.ecTheme,l],"k.itemStyle.normal.color")||"#fff",m.style.strokeColor="#ccc"!=a?this.deepQuery([this.ecTheme,l],"k.itemStyle.normal.lineStyle.color")||"#ff3200":a;break;case"image":m.style.iconType="image",m.style.image=s,"#ccc"===a&&(m.style.opacity=.5)}return m},__legendSelected:function(e){var t=e.target._name;if("single"===this.legendOption.selectedMode)for(var i in this._selectedMap)this._selectedMap[i]=!1;this._selectedMap[t]=!this._selectedMap[t],this.messageCenter.dispatch(l.EVENT.LEGEND_SELECTED,e.event,{selected:this._selectedMap,target:t},this.myChart)},__dispatchHoverLink:function(e){this.messageCenter.dispatch(l.EVENT.LEGEND_HOVERLINK,e.event,{target:e.target._name},this.myChart)},refresh:function(e){if(e){this.option=e||this.option,this.option.legend=this.reformOption(this.option.legend),this.legendOption=this.option.legend;var t,i,n,a,o=this.legendOption.data||[];if(this.legendOption.selected)for(var r in this.legendOption.selected)this._selectedMap[r]="undefined"!=typeof this._selectedMap[r]?this._selectedMap[r]:this.legendOption.selected[r];for(var s=0,h=o.length;h>s;s++)t=this._getName(o[s]),""!==t&&(i=this._getSomethingByName(t),i.series?(this._hasDataMap[t]=!0,a=!i.data||i.type!==l.CHART_TYPE_PIE&&i.type!==l.CHART_TYPE_FORCE&&i.type!==l.CHART_TYPE_FUNNEL?[i.series]:[i.data,i.series],n=this.getItemStyleColor(this.deepQuery(a,"itemStyle.normal.color"),i.seriesIndex,i.dataIndex,i.data),n&&i.type!=l.CHART_TYPE_K&&this.setColor(t,n),this._selectedMap[t]=null!=this._selectedMap[t]?this._selectedMap[t]:!0):this._hasDataMap[t]=!1)}this.clear(),this._buildShape()},getRelatedAmount:function(e){for(var t,i=0,n=this.option.series,a=0,o=n.length;o>a;a++)if(n[a].name===e&&i++,n[a].type===l.CHART_TYPE_PIE||n[a].type===l.CHART_TYPE_RADAR||n[a].type===l.CHART_TYPE_CHORD||n[a].type===l.CHART_TYPE_FORCE||n[a].type===l.CHART_TYPE_FUNNEL){t=n[a].type!=l.CHART_TYPE_FORCE?n[a].data:n[a].categories;for(var r=0,s=t.length;s>r;r++)t[r].name===e&&"-"!=t[r].value&&i++}return i},setColor:function(e,t){this._colorMap[e]=t},getColor:function(e){return this._colorMap[e]||(this._colorMap[e]=this.zr.getColor(this._colorIndex++)),this._colorMap[e]},hasColor:function(e){return this._colorMap[e]?this._colorMap[e]:!1},add:function(e,t){ -for(var i=this.legendOption.data,n=0,a=i.length;a>n;n++)if(this._getName(i[n])===e)return;this.legendOption.data.push(e),this.setColor(e,t),this._selectedMap[e]=!0,this._hasDataMap[e]=!0},del:function(e){for(var t=this.legendOption.data,i=0,n=t.length;n>i;i++)if(this._getName(t[i])===e)return this.legendOption.data.splice(i,1)},getItemShape:function(e){if(null!=e)for(var t,i=0,n=this.shapeList.length;n>i;i++)if(t=this.shapeList[i],t._name===e&&"text"!=t.type)return t},setItemShape:function(e,t){for(var i,n=0,a=this.shapeList.length;a>n;n++)i=this.shapeList[n],i._name===e&&"text"!=i.type&&(this._selectedMap[e]||(t.style.color="#ccc",t.style.strokeColor="#ccc"),this.zr.modShape(i.id,t))},isSelected:function(e){return"undefined"!=typeof this._selectedMap[e]?this._selectedMap[e]:!0},getSelectedMap:function(){return this._selectedMap},setSelected:function(e,t){if("single"===this.legendOption.selectedMode)for(var i in this._selectedMap)this._selectedMap[i]=!1;this._selectedMap[e]=t,this.messageCenter.dispatch(l.EVENT.LEGEND_SELECTED,null,{selected:this._selectedMap,target:e},this.myChart)},onlegendSelected:function(e,t){var i=e.selected;for(var n in i)this._selectedMap[n]!=i[n]&&(t.needRefresh=!0),this._selectedMap[n]=i[n]}};var V={line:function(e,t){var i=t.height/2;e.moveTo(t.x,t.y+i),e.lineTo(t.x+t.width,t.y+i)},pie:function(e,t){var i=t.x,n=t.y,a=t.width,r=t.height;o.prototype.buildPath(e,{x:i+a/2,y:n+r+2,r:r,r0:6,startAngle:45,endAngle:135})},eventRiver:function(e,t){var i=t.x,n=t.y,a=t.width,o=t.height;e.moveTo(i,n+o),e.bezierCurveTo(i+a,n+o,i,n+4,i+a,n+4),e.lineTo(i+a,n),e.bezierCurveTo(i,n,i+a,n+o-4,i,n+o-4),e.lineTo(i,n+o)},k:function(e,t){var i=t.x,n=t.y,a=t.width,o=t.height;s.prototype.buildPath(e,{x:i+a/2,y:[n+1,n+1,n+o-6,n+o],width:a-6})},bar:function(e,t){var i=t.x,n=t.y+1,a=t.width,o=t.height-2,r=3;e.moveTo(i+r,n),e.lineTo(i+a-r,n),e.quadraticCurveTo(i+a,n,i+a,n+r),e.lineTo(i+a,n+o-r),e.quadraticCurveTo(i+a,n+o,i+a-r,n+o),e.lineTo(i+r,n+o),e.quadraticCurveTo(i,n+o,i,n+o-r),e.lineTo(i,n+r),e.quadraticCurveTo(i,n,i+r,n)},force:function(e,t){r.prototype.iconLibrary.circle(e,t)},radar:function(e,t){var i=6,n=t.x+t.width/2,a=t.y+t.height/2,o=t.height/2,r=2*Math.PI/i,s=-Math.PI/2,l=n+o*Math.cos(s),h=a+o*Math.sin(s);e.moveTo(l,h),s+=r;for(var m=0,V=i-1;V>m;m++)e.lineTo(n+o*Math.cos(s),a+o*Math.sin(s)),s+=r;e.lineTo(l,h)}};V.chord=V.pie,V.map=V.bar;for(var U in V)r.prototype.iconLibrary["legendicon"+U]=V[U];return h.inherits(t,i),e("../component").define("legend",t),t}),i("echarts/util/ecData",[],function(){function e(e,t,i,n,a,o,r,s){var l;return"undefined"!=typeof n&&(l=null==n.value?n:n.value),e._echartsData={_series:t,_seriesIndex:i,_data:n,_dataIndex:a,_name:o,_value:l,_special:r,_special2:s},e._echartsData}function t(e,t){var i=e._echartsData;if(!t)return i;switch(t){case"series":case"seriesIndex":case"data":case"dataIndex":case"name":case"value":case"special":case"special2":return i&&i["_"+t]}return null}function i(e,t,i){switch(e._echartsData=e._echartsData||{},t){case"series":case"seriesIndex":case"data":case"dataIndex":case"name":case"value":case"special":case"special2":e._echartsData["_"+t]=i}}function n(e,t){t._echartsData={_series:e._echartsData._series,_seriesIndex:e._echartsData._seriesIndex,_data:e._echartsData._data,_dataIndex:e._echartsData._dataIndex,_name:e._echartsData._name,_value:e._echartsData._value,_special:e._echartsData._special,_special2:e._echartsData._special2}}return{pack:e,set:i,get:t,clone:n}}),i("echarts/chart",[],function(){var e={},t={};return e.define=function(i,n){return t[i]=n,e},e.get=function(e){return t[e]},e}),i("zrender/tool/color",["require","../tool/util"],function(e){function t(e){D=e}function i(){D=N}function n(e,t){return e=0|e,t=t||D,t[e%t.length]}function a(e){B=e}function o(){H=B}function r(){return B}function s(e,t,i,n,a,o,r){O||(O=P.getContext());for(var s=O.createRadialGradient(e,t,i,n,a,o),l=0,h=r.length;h>l;l++)s.addColorStop(r[l][0],r[l][1]);return s.__nonRecursion=!0,s}function l(e,t,i,n,a){O||(O=P.getContext());for(var o=O.createLinearGradient(e,t,i,n),r=0,s=a.length;s>r;r++)o.addColorStop(a[r][0],a[r][1]);return o.__nonRecursion=!0,o}function h(e,t,i){e=p(e),t=p(t),e=I(e),t=I(t);for(var n=[],a=(t[0]-e[0])/i,o=(t[1]-e[1])/i,r=(t[2]-e[2])/i,s=(t[3]-e[3])/i,l=0,h=e[0],m=e[1],U=e[2],d=e[3];i>l;l++)n[l]=V([S(Math.floor(h),[0,255]),S(Math.floor(m),[0,255]),S(Math.floor(U),[0,255]),d.toFixed(4)-0],"rgba"),h+=a,m+=o,U+=r,d+=s;return h=t[0],m=t[1],U=t[2],d=t[3],n[l]=V([h,m,U,d],"rgba"),n}function m(e,t){var i=[],n=e.length;if(void 0===t&&(t=20),1===n)i=h(e[0],e[0],t);else if(n>1)for(var a=0,o=n-1;o>a;a++){var r=h(e[a],e[a+1],t);o-1>a&&r.pop(),i=i.concat(r)}return i}function V(e,t){if(t=t||"rgb",e&&(3===e.length||4===e.length)){if(e=C(e,function(e){return e>1?Math.ceil(e):e}),t.indexOf("hex")>-1)return"#"+((1<<24)+(e[0]<<16)+(e[1]<<8)+ +e[2]).toString(16).slice(1);if(t.indexOf("hs")>-1){var i=C(e.slice(1,3),function(e){return e+"%"});e[1]=i[0],e[2]=i[1]}return t.indexOf("a")>-1?(3===e.length&&e.push(1),e[3]=S(e[3],[0,1]),t+"("+e.slice(0,4).join(",")+")"):t+"("+e.slice(0,3).join(",")+")"}}function U(e){e=L(e),e.indexOf("rgba")<0&&(e=p(e));var t=[],i=0;return e.replace(/[\d.]+/g,function(e){e=3>i?0|e:+e,t[i++]=e}),t}function d(e,t){if(!E(e))return e;var i=I(e),n=i[3];return"undefined"==typeof n&&(n=1),e.indexOf("hsb")>-1?i=F(i):e.indexOf("hsl")>-1&&(i=T(i)),t.indexOf("hsb")>-1||t.indexOf("hsv")>-1?i=A(i):t.indexOf("hsl")>-1&&(i=M(i)),i[3]=n,V(i,t)}function p(e){return d(e,"rgba")}function c(e){return d(e,"rgb")}function u(e){return d(e,"hex")}function y(e){return d(e,"hsva")}function g(e){return d(e,"hsv")}function b(e){return d(e,"hsba")}function f(e){return d(e,"hsb")}function k(e){return d(e,"hsla")}function x(e){return d(e,"hsl")}function _(e){for(var t in G)if(u(G[t])===u(e))return t;return null}function L(e){return String(e).replace(/\s+/g,"")}function W(e){if(G[e]&&(e=G[e]),e=L(e),e=e.replace(/hsv/i,"hsb"),/^#[\da-f]{3}$/i.test(e)){e=parseInt(e.slice(1),16);var t=(3840&e)<<8,i=(240&e)<<4,n=15&e;e="#"+((1<<24)+(t<<4)+t+(i<<4)+i+(n<<4)+n).toString(16).slice(1)}return e}function X(e,t){if(!E(e))return e;var i=t>0?1:-1;"undefined"==typeof t&&(t=0),t=Math.abs(t)>1?1:Math.abs(t),e=c(e);for(var n=I(e),a=0;3>a;a++)n[a]=1===i?n[a]*(1-t)|0:(255-n[a])*t+n[a]|0;return"rgb("+n.join(",")+")"}function v(e){if(!E(e))return e;var t=I(p(e));return t=C(t,function(e){return 255-e}),V(t,"rgb")}function w(e,t,i){if(!E(e)||!E(t))return e;"undefined"==typeof i&&(i=.5),i=1-S(i,[0,1]);for(var n=2*i-1,a=I(p(e)),o=I(p(t)),r=a[3]-o[3],s=((n*r===-1?n:(n+r)/(1+n*r))+1)/2,l=1-s,h=[],m=0;3>m;m++)h[m]=a[m]*s+o[m]*l;var U=a[3]*i+o[3]*(1-i);return U=Math.max(0,Math.min(1,U)),1===a[3]&&1===o[3]?V(h,"rgb"):(h[3]=U,V(h,"rgba"))}function K(){return"#"+(Math.random().toString(16)+"0000").slice(2,8)}function I(e){e=W(e);var t=e.match(R);if(null===t)throw new Error("The color format error");var i,n,a,o=[];if(t[2])i=t[2].replace("#","").split(""),a=[i[0]+i[1],i[2]+i[3],i[4]+i[5]],o=C(a,function(e){return S(parseInt(e,16),[0,255])});else if(t[4]){var r=t[4].split(",");n=r[3],a=r.slice(0,3),o=C(a,function(e){return e=Math.floor(e.indexOf("%")>0?2.55*parseInt(e,0):e),S(e,[0,255])}),"undefined"!=typeof n&&o.push(S(parseFloat(n),[0,1]))}else if(t[5]||t[6]){var s=(t[5]||t[6]).split(","),l=parseInt(s[0],0)/360,h=s[1],m=s[2];n=s[3],o=C([h,m],function(e){return S(parseFloat(e)/100,[0,1])}),o.unshift(l),"undefined"!=typeof n&&o.push(S(parseFloat(n),[0,1]))}return o}function J(e,t){if(!E(e))return e;null===t&&(t=1);var i=I(p(e));return i[3]=S(Number(t).toFixed(4),[0,1]),V(i,"rgba")}function C(e,t){if("function"!=typeof t)throw new TypeError;for(var i=e?e.length:0,n=0;i>n;n++)e[n]=t(e[n]);return e}function S(e,t){return e<=t[0]?e=t[0]:e>=t[1]&&(e=t[1]),e}function E(e){return e instanceof Array||"string"==typeof e}function F(e){var t,i,n,a=e[0],o=e[1],r=e[2];if(0===o)t=255*r,i=255*r,n=255*r;else{var s=6*a;6===s&&(s=0);var l=0|s,h=r*(1-o),m=r*(1-o*(s-l)),V=r*(1-o*(1-(s-l))),U=0,d=0,p=0;0===l?(U=r,d=V,p=h):1===l?(U=m,d=r,p=h):2===l?(U=h,d=r,p=V):3===l?(U=h,d=m,p=r):4===l?(U=V,d=h,p=r):(U=r,d=h,p=m),t=255*U,i=255*d,n=255*p}return[t,i,n]}function T(e){var t,i,n,a=e[0],o=e[1],r=e[2];if(0===o)t=255*r,i=255*r,n=255*r;else{var s;s=.5>r?r*(1+o):r+o-o*r;var l=2*r-s;t=255*z(l,s,a+1/3),i=255*z(l,s,a),n=255*z(l,s,a-1/3)}return[t,i,n]}function z(e,t,i){return 0>i&&(i+=1),i>1&&(i-=1),1>6*i?e+6*(t-e)*i:1>2*i?t:2>3*i?e+(t-e)*(2/3-i)*6:e}function A(e){var t,i,n=e[0]/255,a=e[1]/255,o=e[2]/255,r=Math.min(n,a,o),s=Math.max(n,a,o),l=s-r,h=s;if(0===l)t=0,i=0;else{i=l/s;var m=((s-n)/6+l/2)/l,V=((s-a)/6+l/2)/l,U=((s-o)/6+l/2)/l;n===s?t=U-V:a===s?t=1/3+m-U:o===s&&(t=2/3+V-m),0>t&&(t+=1),t>1&&(t-=1)}return t=360*t,i=100*i,h=100*h,[t,i,h]}function M(e){var t,i,n=e[0]/255,a=e[1]/255,o=e[2]/255,r=Math.min(n,a,o),s=Math.max(n,a,o),l=s-r,h=(s+r)/2;if(0===l)t=0,i=0;else{i=.5>h?l/(s+r):l/(2-s-r);var m=((s-n)/6+l/2)/l,V=((s-a)/6+l/2)/l,U=((s-o)/6+l/2)/l;n===s?t=U-V:a===s?t=1/3+m-U:o===s&&(t=2/3+V-m),0>t&&(t+=1),t>1&&(t-=1)}return t=360*t,i=100*i,h=100*h,[t,i,h]}var O,P=e("../tool/util"),D=["#ff9277"," #dddd00"," #ffc877"," #bbe3ff"," #d5ffbb","#bbbbff"," #ddb000"," #b0dd00"," #e2bbff"," #ffbbe3","#ff7777"," #ff9900"," #83dd00"," #77e3ff"," #778fff","#c877ff"," #ff77ab"," #ff6600"," #aa8800"," #77c7ff","#ad77ff"," #ff77ff"," #dd0083"," #777700"," #00aa00","#0088aa"," #8400dd"," #aa0088"," #dd0000"," #772e00"],N=D,B="rgba(255,255,0,0.5)",H=B,R=/^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i,G={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#0ff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000",blanchedalmond:"#ffebcd",blue:"#00f",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#0ff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgrey:"#a9a9a9",darkgreen:"#006400",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#f0f",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",grey:"#808080",green:"#008000",greenyellow:"#adff2f",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgrey:"#d3d3d3",lightgreen:"#90ee90",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#789",lightslategrey:"#789",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#0f0",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#f0f",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370d8",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#d87093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#f00",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#fff",whitesmoke:"#f5f5f5",yellow:"#ff0",yellowgreen:"#9acd32"};return{customPalette:t,resetPalette:i,getColor:n,getHighlightColor:r,customHighlight:a,resetHighlight:o,getRadialGradient:s,getLinearGradient:l,getGradientColors:m,getStepColors:h,reverse:v,mix:w,lift:X,trim:L,random:K,toRGB:c,toRGBA:p,toHex:u,toHSL:x,toHSLA:k,toHSB:f,toHSBA:b,toHSV:g,toHSVA:y,toName:_,toColor:V,toArray:U,alpha:J,getData:I}}),i("echarts/component/timeline",["require","./base","zrender/shape/Rectangle","../util/shape/Icon","../util/shape/Chain","../config","zrender/tool/util","zrender/tool/area","zrender/tool/event","../component"],function(e){function t(e,t,i,a,o){n.call(this,e,t,i,a,o);var r=this;if(r._onclick=function(e){return r.__onclick(e)},r._ondrift=function(e,t){return r.__ondrift(this,e,t)},r._ondragend=function(){return r.__ondragend()},r._setCurrentOption=function(){var e=r.timelineOption;r.currentIndex%=e.data.length;var t=r.options[r.currentIndex]||{};r.myChart._setOption(t,e.notMerge,!0),r.messageCenter.dispatch(s.EVENT.TIMELINE_CHANGED,null,{currentIndex:r.currentIndex,data:null!=e.data[r.currentIndex].name?e.data[r.currentIndex].name:e.data[r.currentIndex]},r.myChart)},r._onFrame=function(){r._setCurrentOption(),r._syncHandleShape(),r.timelineOption.autoPlay&&(r.playTicket=setTimeout(function(){return r.currentIndex+=1,!r.timelineOption.loop&&r.currentIndex>=r.timelineOption.data.length?(r.currentIndex=r.timelineOption.data.length-1,void r.stop()):void r._onFrame()},r.timelineOption.playInterval))},this.setTheme(!1),this.options=this.option.options,this.currentIndex=this.timelineOption.currentIndex%this.timelineOption.data.length,this.timelineOption.notMerge||0===this.currentIndex||(this.options[this.currentIndex]=l.merge(this.options[this.currentIndex],this.options[0])),this.timelineOption.show&&(this._buildShape(),this._syncHandleShape()),this._setCurrentOption(),this.timelineOption.autoPlay){var r=this;this.playTicket=setTimeout(function(){r.play()},null!=this.ecTheme.animationDuration?this.ecTheme.animationDuration:s.animationDuration)}}function i(e,t){var i=2,n=t.x+i,a=t.y+i+2,r=t.width-i,s=t.height-i,l=t.symbol;if("last"===l)e.moveTo(n+r-2,a+s/3),e.lineTo(n+r-2,a),e.lineTo(n+2,a+s/2),e.lineTo(n+r-2,a+s),e.lineTo(n+r-2,a+s/3*2),e.moveTo(n,a),e.lineTo(n,a);else if("next"===l)e.moveTo(n+2,a+s/3),e.lineTo(n+2,a),e.lineTo(n+r-2,a+s/2),e.lineTo(n+2,a+s),e.lineTo(n+2,a+s/3*2),e.moveTo(n,a),e.lineTo(n,a);else if("play"===l)if("stop"===t.status)e.moveTo(n+2,a),e.lineTo(n+r-2,a+s/2),e.lineTo(n+2,a+s),e.lineTo(n+2,a);else{var h="both"===t.brushType?2:3;e.rect(n+2,a,h,s),e.rect(n+r-h-2,a,h,s)}else if(l.match("image")){var m="";m=l.replace(new RegExp("^image:\\/\\/"),""),l=o.prototype.iconLibrary.image,l(e,{x:n,y:a,width:r,height:s,image:m})}}var n=e("./base"),a=e("zrender/shape/Rectangle"),o=e("../util/shape/Icon"),r=e("../util/shape/Chain"),s=e("../config");s.timeline={zlevel:0,z:4,show:!0,type:"time",notMerge:!1,realtime:!0,x:80,x2:80,y2:0,height:50,backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,padding:5,controlPosition:"left",autoPlay:!1,loop:!0,playInterval:2e3,lineStyle:{width:1,color:"#666",type:"dashed"},label:{show:!0,interval:"auto",rotate:0,textStyle:{color:"#333"}},checkpointStyle:{symbol:"auto",symbolSize:"auto",color:"auto",borderColor:"auto",borderWidth:"auto",label:{show:!1,textStyle:{color:"auto"}}},controlStyle:{itemSize:15,itemGap:5,normal:{color:"#333"},emphasis:{color:"#1e90ff"}},symbol:"emptyDiamond",symbolSize:4,currentIndex:0};var l=e("zrender/tool/util"),h=e("zrender/tool/area"),m=e("zrender/tool/event");return t.prototype={type:s.COMPONENT_TYPE_TIMELINE,_buildShape:function(){if(this._location=this._getLocation(),this._buildBackground(),this._buildControl(),this._chainPoint=this._getChainPoint(),this.timelineOption.label.show)for(var e=this._getInterval(),t=0,i=this._chainPoint.length;i>t;t+=e)this._chainPoint[t].showLabel=!0;this._buildChain(),this._buildHandle();for(var t=0,n=this.shapeList.length;n>t;t++)this.zr.addShape(this.shapeList[t])},_getLocation:function(){var e,t=this.timelineOption,i=this.reformCssArray(this.timelineOption.padding),n=this.zr.getWidth(),a=this.parsePercent(t.x,n),o=this.parsePercent(t.x2,n);null==t.width?(e=n-a-o,o=n-o):(e=this.parsePercent(t.width,n),o=a+e);var r,s,l=this.zr.getHeight(),h=this.parsePercent(t.height,l);return null!=t.y?(r=this.parsePercent(t.y,l),s=r+h):(s=l-this.parsePercent(t.y2,l),r=s-h),{x:a+i[3],y:r+i[0],x2:o-i[1],y2:s-i[2],width:e-i[1]-i[3],height:h-i[0]-i[2]}},_getReformedLabel:function(e){var t=this.timelineOption,i=null!=t.data[e].name?t.data[e].name:t.data[e],n=t.data[e].formatter||t.label.formatter;return n&&("function"==typeof n?i=n.call(this.myChart,i):"string"==typeof n&&(i=n.replace("{value}",i))),i},_getInterval:function(){var e=this._chainPoint,t=this.timelineOption,i=t.label.interval;if("auto"===i){var n=t.label.textStyle.fontSize,a=t.data,o=t.data.length;if(o>3){var r,s,l=!1;for(i=0;!l&&o>i;){i++,l=!0;for(var m=i;o>m;m+=i){if(r=e[m].x-e[m-i].x,0!==t.label.rotate)s=n;else if(a[m].textStyle)s=h.getTextWidth(e[m].name,e[m].textFont);else{var V=e[m].name+"",U=(V.match(/\w/g)||"").length,d=V.length-U;s=U*n*2/3+d*n}if(s>r){l=!1;break}}}}else i=1}else i=i-0+1;return i},_getChainPoint:function(){function e(e){return null!=h[e].name?h[e].name:h[e]+""}var t,i=this.timelineOption,n=i.symbol.toLowerCase(),a=i.symbolSize,o=i.label.rotate,r=i.label.textStyle,s=this.getFont(r),h=i.data,m=this._location.x,V=this._location.y+this._location.height/4*3,U=this._location.x2-this._location.x,d=h.length,p=[];if(d>1){var c=U/d;if(c=c>50?50:20>c?5:c,U-=2*c,"number"===i.type)for(var u=0;d>u;u++)p.push(m+c+U/(d-1)*u);else{p[0]=new Date(e(0).replace(/-/g,"/")),p[d-1]=new Date(e(d-1).replace(/-/g,"/"))-p[0];for(var u=1;d>u;u++)p[u]=m+c+U*(new Date(e(u).replace(/-/g,"/"))-p[0])/p[d-1];p[0]=m+c}}else p.push(m+U/2);for(var y,g,b,f,k,x=[],u=0;d>u;u++)m=p[u],y=h[u].symbol&&h[u].symbol.toLowerCase()||n,y.match("empty")?(y=y.replace("empty",""),b=!0):b=!1,y.match("star")&&(g=y.replace("star","")-0||5,y="star"),t=h[u].textStyle?l.merge(h[u].textStyle||{},r):r,f=t.align||"center",o?(f=o>0?"right":"left",k=[o*Math.PI/180,m,V-5]):k=!1,x.push({x:m,n:g,isEmpty:b,symbol:y,symbolSize:h[u].symbolSize||a,color:h[u].color,borderColor:h[u].borderColor,borderWidth:h[u].borderWidth,name:this._getReformedLabel(u),textColor:t.color,textAlign:f,textBaseline:t.baseline||"middle",textX:m,textY:V-(o?5:0),textFont:h[u].textStyle?this.getFont(t):s,rotation:k,showLabel:!1});return x},_buildBackground:function(){var e=this.timelineOption,t=this.reformCssArray(this.timelineOption.padding),i=this._location.width,n=this._location.height;(0!==e.borderWidth||"rgba(0,0,0,0)"!=e.backgroundColor.replace(/\s/g,""))&&this.shapeList.push(new a({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._location.x-t[3],y:this._location.y-t[0],width:i+t[1]+t[3],height:n+t[0]+t[2],brushType:0===e.borderWidth?"fill":"both",color:e.backgroundColor,strokeColor:e.borderColor,lineWidth:e.borderWidth}}))},_buildControl:function(){var e=this,t=this.timelineOption,i=t.lineStyle,n=t.controlStyle;if("none"!==t.controlPosition){var a,r=n.itemSize,s=n.itemGap;"left"===t.controlPosition?(a=this._location.x,this._location.x+=3*(r+s)):(a=this._location.x2-(3*(r+s)-s),this._location.x2-=3*(r+s));var h=this._location.y,m={zlevel:this.getZlevelBase(),z:this.getZBase()+1,style:{iconType:"timelineControl",symbol:"last",x:a,y:h,width:r,height:r,brushType:"stroke",color:n.normal.color,strokeColor:n.normal.color,lineWidth:i.width},highlightStyle:{color:n.emphasis.color,strokeColor:n.emphasis.color,lineWidth:i.width+1},clickable:!0};this._ctrLastShape=new o(m),this._ctrLastShape.onclick=function(){e.last()},this.shapeList.push(this._ctrLastShape),a+=r+s,this._ctrPlayShape=new o(l.clone(m)),this._ctrPlayShape.style.brushType="fill",this._ctrPlayShape.style.symbol="play",this._ctrPlayShape.style.status=this.timelineOption.autoPlay?"playing":"stop",this._ctrPlayShape.style.x=a,this._ctrPlayShape.onclick=function(){"stop"===e._ctrPlayShape.style.status?e.play():e.stop()},this.shapeList.push(this._ctrPlayShape),a+=r+s,this._ctrNextShape=new o(l.clone(m)),this._ctrNextShape.style.symbol="next",this._ctrNextShape.style.x=a,this._ctrNextShape.onclick=function(){e.next()},this.shapeList.push(this._ctrNextShape)}},_buildChain:function(){var e=this.timelineOption,t=e.lineStyle;this._timelineShae={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:this._location.x,y:this.subPixelOptimize(this._location.y,t.width),width:this._location.x2-this._location.x,height:this._location.height,chainPoint:this._chainPoint,brushType:"both",strokeColor:t.color,lineWidth:t.width,lineType:t.type},hoverable:!1,clickable:!0,onclick:this._onclick},this._timelineShae=new r(this._timelineShae),this.shapeList.push(this._timelineShae)},_buildHandle:function(){var e=this._chainPoint[this.currentIndex],t=e.symbolSize+1;t=5>t?5:t,this._handleShape={zlevel:this.getZlevelBase(),z:this.getZBase()+1,hoverable:!1,draggable:!0,style:{iconType:"diamond",n:e.n,x:e.x-t,y:this._location.y+this._location.height/4-t,width:2*t,height:2*t,brushType:"both",textPosition:"specific",textX:e.x,textY:this._location.y-this._location.height/4,textAlign:"center",textBaseline:"middle"},highlightStyle:{},ondrift:this._ondrift,ondragend:this._ondragend},this._handleShape=new o(this._handleShape),this.shapeList.push(this._handleShape)},_syncHandleShape:function(){if(this.timelineOption.show){var e=this.timelineOption,t=e.checkpointStyle,i=this._chainPoint[this.currentIndex];this._handleShape.style.text=t.label.show?i.name:"",this._handleShape.style.textFont=i.textFont,this._handleShape.style.n=i.n,"auto"===t.symbol?this._handleShape.style.iconType="none"!=i.symbol?i.symbol:"diamond":(this._handleShape.style.iconType=t.symbol,t.symbol.match("star")&&(this._handleShape.style.n=t.symbol.replace("star","")-0||5,this._handleShape.style.iconType="star"));var n;"auto"===t.symbolSize?(n=i.symbolSize+2,n=5>n?5:n):n=t.symbolSize-0,this._handleShape.style.color="auto"===t.color?i.color?i.color:e.controlStyle.emphasis.color:t.color,this._handleShape.style.textColor="auto"===t.label.textStyle.color?this._handleShape.style.color:t.label.textStyle.color,this._handleShape.highlightStyle.strokeColor=this._handleShape.style.strokeColor="auto"===t.borderColor?i.borderColor?i.borderColor:"#fff":t.borderColor,this._handleShape.style.lineWidth="auto"===t.borderWidth?i.borderWidth?i.borderWidth:0:t.borderWidth-0,this._handleShape.highlightStyle.lineWidth=this._handleShape.style.lineWidth+1,this.zr.animate(this._handleShape.id,"style").when(500,{x:i.x-n,textX:i.x,y:this._location.y+this._location.height/4-n,width:2*n,height:2*n}).start("ExponentialOut")}},_findChainIndex:function(e){var t=this._chainPoint,i=t.length;if(e<=t[0].x)return 0;if(e>=t[i-1].x)return i-1;for(var n=0;i-1>n;n++)if(e>=t[n].x&&e<=t[n+1].x)return Math.abs(e-t[n].x)=n[a-1].x-n[a-1].symbolSize?(e.style.x=n[a-1].x-n[a-1].symbolSize,i=a-1):(e.style.x+=t,i=this._findChainIndex(e.style.x));var o=n[i],r=o.symbolSize+2;if(e.style.iconType=o.symbol,e.style.n=o.n,e.style.textX=e.style.x+r/2,e.style.y=this._location.y+this._location.height/4-r,e.style.width=2*r,e.style.height=2*r,e.style.text=o.name,i===this.currentIndex)return!0;if(this.currentIndex=i,this.timelineOption.realtime){clearTimeout(this.playTicket);var s=this;this.playTicket=setTimeout(function(){s._setCurrentOption()},200)}return!0},__ondragend:function(){this.isDragend=!0},ondragend:function(e,t){this.isDragend&&e.target&&(!this.timelineOption.realtime&&this._setCurrentOption(),t.dragOut=!0,t.dragIn=!0,t.needRefresh=!1,this.isDragend=!1,this._syncHandleShape())},last:function(){return this.timelineOption.autoPlay&&this.stop(),this.currentIndex-=1,this.currentIndex<0&&(this.currentIndex=this.timelineOption.data.length-1),this._onFrame(),this.currentIndex},next:function(){return this.timelineOption.autoPlay&&this.stop(),this.currentIndex+=1,this.currentIndex>=this.timelineOption.data.length&&(this.currentIndex=0),this._onFrame(),this.currentIndex},play:function(e,t){return this._ctrPlayShape&&"playing"!=this._ctrPlayShape.style.status&&(this._ctrPlayShape.style.status="playing",this.zr.modShape(this._ctrPlayShape.id),this.zr.refreshNextFrame()),this.timelineOption.autoPlay=null!=t?t:!0,this.timelineOption.autoPlay||clearTimeout(this.playTicket),this.currentIndex=null!=e?e:this.currentIndex+1,this.currentIndex>=this.timelineOption.data.length&&(this.currentIndex=0),this._onFrame(),this.currentIndex},stop:function(){return this._ctrPlayShape&&"stop"!=this._ctrPlayShape.style.status&&(this._ctrPlayShape.style.status="stop",this.zr.modShape(this._ctrPlayShape.id),this.zr.refreshNextFrame()),this.timelineOption.autoPlay=!1,clearTimeout(this.playTicket),this.currentIndex},resize:function(){this.timelineOption.show&&(this.clear(),this._buildShape(),this._syncHandleShape())},setTheme:function(e){this.timelineOption=this.reformOption(l.clone(this.option.timeline)),this.timelineOption.label.textStyle=this.getTextStyle(this.timelineOption.label.textStyle),this.timelineOption.checkpointStyle.label.textStyle=this.getTextStyle(this.timelineOption.checkpointStyle.label.textStyle),this.myChart.canvasSupported||(this.timelineOption.realtime=!1),this.timelineOption.show&&e&&(this.clear(),this._buildShape(),this._syncHandleShape())},onbeforDispose:function(){clearTimeout(this.playTicket)}},o.prototype.iconLibrary.timelineControl=i,l.inherits(t,n),e("../component").define("timeline",t),t}),i("zrender/shape/Image",["require","./Base","../tool/util"],function(e){var t=e("./Base"),i=function(e){t.call(this,e)};return i.prototype={type:"image",brush:function(e,t,i){var n=this.style||{};t&&(n=this.getHighlightStyle(n,this.highlightStyle||{}));var a=n.image,o=this;if(this._imageCache||(this._imageCache={}),"string"==typeof a){var r=a;this._imageCache[r]?a=this._imageCache[r]:(a=new Image,a.onload=function(){a.onload=null,o.modSelf(),i()},a.src=r,this._imageCache[r]=a)}if(a){if("IMG"==a.nodeName.toUpperCase())if(window.ActiveXObject){if("complete"!=a.readyState)return}else if(!a.complete)return;var s=n.width||a.width,l=n.height||a.height,h=n.x,m=n.y;if(!a.width||!a.height)return;if(e.save(),this.doClip(e),this.setContext(e,n),this.setTransform(e),n.sWidth&&n.sHeight){var V=n.sx||0,U=n.sy||0;e.drawImage(a,V,U,n.sWidth,n.sHeight,h,m,s,l)}else if(n.sx&&n.sy){var V=n.sx,U=n.sy,d=s-V,p=l-U;e.drawImage(a,V,U,d,p,h,m,s,l)}else e.drawImage(a,h,m,s,l);n.width||(n.width=s),n.height||(n.height=l),this.style.width||(this.style.width=s),this.style.height||(this.style.height=l),this.drawText(e,n,this.style),e.restore()}},getRect:function(e){return{x:e.x,y:e.y,width:e.width,height:e.height}},clearCache:function(){this._imageCache={}}},e("../tool/util").inherits(i,t),i}),i("zrender/loadingEffect/Bar",["require","./Base","../tool/util","../tool/color","../shape/Rectangle"],function(e){function t(e){i.call(this,e)}var i=e("./Base"),n=e("../tool/util"),a=e("../tool/color"),o=e("../shape/Rectangle");return n.inherits(t,i),t.prototype._start=function(e,t){var i=n.merge(this.options,{textStyle:{color:"#888"},backgroundColor:"rgba(250, 250, 250, 0.8)",effectOption:{x:0,y:this.canvasHeight/2-30,width:this.canvasWidth,height:5,brushType:"fill",timeInterval:100}}),r=this.createTextShape(i.textStyle),s=this.createBackgroundShape(i.backgroundColor),l=i.effectOption,h=new o({highlightStyle:n.clone(l)});return h.highlightStyle.color=l.color||a.getLinearGradient(l.x,l.y,l.x+l.width,l.y+l.height,[[0,"#ff6400"],[.5,"#ffe100"],[1,"#b1ff00"]]),null!=i.progress?(e(s),h.highlightStyle.width=this.adjust(i.progress,[0,1])*i.effectOption.width,e(h),e(r),void t()):(h.highlightStyle.width=0,setInterval(function(){e(s),h.highlightStyle.widthc;c++){var u="random"==l.color?a.alpha(a.random(),.3):l.color;U[c]=new o({highlightStyle:{x:Math.ceil(Math.random()*d),y:Math.ceil(Math.random()*p),r:Math.ceil(40*Math.random()),brushType:m,color:u,strokeColor:u,lineWidth:V},animationY:Math.ceil(20*Math.random())})}return setInterval(function(){e(s);for(var i=0;h>i;i++){var n=U[i].highlightStyle;n.y-U[i].animationY+n.r<=0&&(U[i].highlightStyle.y=p+n.r,U[i].highlightStyle.x=Math.ceil(Math.random()*d)),U[i].highlightStyle.y-=U[i].animationY,e(U[i])}e(r),t()},l.timeInterval)},t}),i("zrender/loadingEffect/DynamicLine",["require","./Base","../tool/util","../tool/color","../shape/Line"],function(e){function t(e){i.call(this,e)}var i=e("./Base"),n=e("../tool/util"),a=e("../tool/color"),o=e("../shape/Line");return n.inherits(t,i),t.prototype._start=function(e,t){for(var i=n.merge(this.options,{textStyle:{color:"#fff"},backgroundColor:"rgba(0, 0, 0, 0.8)",effectOption:{n:30,lineWidth:1,color:"random",timeInterval:100}}),r=this.createTextShape(i.textStyle),s=this.createBackgroundShape(i.backgroundColor),l=i.effectOption,h=l.n,m=l.lineWidth,V=[],U=this.canvasWidth,d=this.canvasHeight,p=0;h>p;p++){var c=-Math.ceil(1e3*Math.random()),u=Math.ceil(400*Math.random()),y=Math.ceil(Math.random()*d),g="random"==l.color?a.random():l.color;V[p]=new o({highlightStyle:{xStart:c,yStart:y,xEnd:c+u,yEnd:y,strokeColor:g,lineWidth:m},animationX:Math.ceil(100*Math.random()),len:u})}return setInterval(function(){e(s);for(var i=0;h>i;i++){var n=V[i].highlightStyle;n.xStart>=U&&(V[i].len=Math.ceil(400*Math.random()),n.xStart=-400,n.xEnd=-400+V[i].len,n.yStart=Math.ceil(Math.random()*d),n.yEnd=n.yStart),n.xStart+=V[i].animationX,n.xEnd+=V[i].animationX,e(V[i])}e(r),t()},l.timeInterval)},t}),i("zrender/loadingEffect/Ring",["require","./Base","../tool/util","../tool/color","../shape/Ring","../shape/Sector"],function(e){function t(e){i.call(this,e)}var i=e("./Base"),n=e("../tool/util"),a=e("../tool/color"),o=e("../shape/Ring"),r=e("../shape/Sector");return n.inherits(t,i),t.prototype._start=function(e,t){var i=n.merge(this.options,{textStyle:{color:"#07a"},backgroundColor:"rgba(250, 250, 250, 0.8)",effect:{x:this.canvasWidth/2,y:this.canvasHeight/2,r0:60,r:100,color:"#bbdcff",brushType:"fill",textPosition:"inside",textFont:"normal 30px verdana",textColor:"rgba(30, 144, 255, 0.6)",timeInterval:100}}),s=i.effect,l=i.textStyle; - -null==l.x&&(l.x=s.x),null==l.y&&(l.y=s.y+(s.r0+s.r)/2-5);for(var h=this.createTextShape(i.textStyle),m=this.createBackgroundShape(i.backgroundColor),V=s.x,U=s.y,d=s.r0+6,p=s.r-6,c=s.color,u=a.lift(c,.1),y=new o({highlightStyle:n.clone(s)}),g=[],b=a.getGradientColors(["#ff6400","#ffe100","#97ff00"],25),f=15,k=240,x=0;16>x;x++)g.push(new r({highlightStyle:{x:V,y:U,r0:d,r:p,startAngle:k-f,endAngle:k,brushType:"fill",color:u},_color:a.getLinearGradient(V+d*Math.cos(k,!0),U-d*Math.sin(k,!0),V+d*Math.cos(k-f,!0),U-d*Math.sin(k-f,!0),[[0,b[2*x]],[1,b[2*x+1]]])})),k-=f;k=360;for(var x=0;4>x;x++)g.push(new r({highlightStyle:{x:V,y:U,r0:d,r:p,startAngle:k-f,endAngle:k,brushType:"fill",color:u},_color:a.getLinearGradient(V+d*Math.cos(k,!0),U-d*Math.sin(k,!0),V+d*Math.cos(k-f,!0),U-d*Math.sin(k-f,!0),[[0,b[2*x+32]],[1,b[2*x+33]]])})),k-=f;var _=0;if(null!=i.progress){e(m),_=100*this.adjust(i.progress,[0,1]).toFixed(2)/5,y.highlightStyle.text=5*_+"%",e(y);for(var x=0;20>x;x++)g[x].highlightStyle.color=_>x?g[x]._color:u,e(g[x]);return e(h),void t()}return setInterval(function(){e(m),_+=_>=20?-20:1,e(y);for(var i=0;20>i;i++)g[i].highlightStyle.color=_>i?g[i]._color:u,e(g[i]);e(h),t()},s.timeInterval)},t}),i("zrender/loadingEffect/Spin",["require","./Base","../tool/util","../tool/color","../tool/area","../shape/Sector"],function(e){function t(e){i.call(this,e)}var i=e("./Base"),n=e("../tool/util"),a=e("../tool/color"),o=e("../tool/area"),r=e("../shape/Sector");return n.inherits(t,i),t.prototype._start=function(e,t){var i=n.merge(this.options,{textStyle:{color:"#fff",textAlign:"start"},backgroundColor:"rgba(0, 0, 0, 0.8)"}),s=this.createTextShape(i.textStyle),l=10,h=o.getTextWidth(s.highlightStyle.text,s.highlightStyle.textFont),m=o.getTextHeight(s.highlightStyle.text,s.highlightStyle.textFont),V=n.merge(this.options.effect||{},{r0:9,r:15,n:18,color:"#fff",timeInterval:100}),U=this.getLocation(this.options.textStyle,h+l+2*V.r,Math.max(2*V.r,m));V.x=U.x+V.r,V.y=s.highlightStyle.y=U.y+U.height/2,s.highlightStyle.x=V.x+V.r+l;for(var d=this.createBackgroundShape(i.backgroundColor),p=V.n,c=V.x,u=V.y,y=V.r0,g=V.r,b=V.color,f=[],k=Math.round(180/p),x=0;p>x;x++)f[x]=new r({highlightStyle:{x:c,y:u,r0:y,r:g,startAngle:k*x*2,endAngle:k*x*2+k,color:a.alpha(b,(x+1)/p),brushType:"fill"}});var _=[0,c,u];return setInterval(function(){e(d),_[0]-=.3;for(var i=0;p>i;i++)f[i].rotation=_,e(f[i]);e(s),t()},V.timeInterval)},t}),i("zrender/loadingEffect/Whirling",["require","./Base","../tool/util","../tool/area","../shape/Ring","../shape/Droplet","../shape/Circle"],function(e){function t(e){i.call(this,e)}var i=e("./Base"),n=e("../tool/util"),a=e("../tool/area"),o=e("../shape/Ring"),r=e("../shape/Droplet"),s=e("../shape/Circle");return n.inherits(t,i),t.prototype._start=function(e,t){var i=n.merge(this.options,{textStyle:{color:"#888",textAlign:"start"},backgroundColor:"rgba(250, 250, 250, 0.8)"}),l=this.createTextShape(i.textStyle),h=10,m=a.getTextWidth(l.highlightStyle.text,l.highlightStyle.textFont),V=a.getTextHeight(l.highlightStyle.text,l.highlightStyle.textFont),U=n.merge(this.options.effect||{},{r:18,colorIn:"#fff",colorOut:"#555",colorWhirl:"#6cf",timeInterval:50}),d=this.getLocation(this.options.textStyle,m+h+2*U.r,Math.max(2*U.r,V));U.x=d.x+U.r,U.y=l.highlightStyle.y=d.y+d.height/2,l.highlightStyle.x=U.x+U.r+h;var p=this.createBackgroundShape(i.backgroundColor),c=new r({highlightStyle:{a:Math.round(U.r/2),b:Math.round(U.r-U.r/6),brushType:"fill",color:U.colorWhirl}}),u=new s({highlightStyle:{r:Math.round(U.r/6),brushType:"fill",color:U.colorIn}}),y=new o({highlightStyle:{r0:Math.round(U.r-U.r/3),r:U.r,brushType:"fill",color:U.colorOut}}),g=[0,U.x,U.y];return c.highlightStyle.x=u.highlightStyle.x=y.highlightStyle.x=g[1],c.highlightStyle.y=u.highlightStyle.y=y.highlightStyle.y=g[2],setInterval(function(){e(p),e(y),g[0]-=.3,c.rotation=g,e(c),e(u),e(l),t()},U.timeInterval)},t}),i("echarts/theme/macarons",[],function(){var e={color:["#2ec7c9","#b6a2de","#5ab1ef","#ffb980","#d87a80","#8d98b3","#e5cf0d","#97b552","#95706d","#dc69aa","#07a2a4","#9a7fd1","#588dd5","#f5994e","#c05050","#59678c","#c9ab00","#7eb00a","#6f5553","#c14089"],title:{textStyle:{fontWeight:"normal",color:"#008acd"}},dataRange:{itemWidth:15,color:["#5ab1ef","#e0ffff"]},toolbox:{color:["#1e90ff","#1e90ff","#1e90ff","#1e90ff"],effectiveColor:"#ff4500"},tooltip:{backgroundColor:"rgba(50,50,50,0.5)",axisPointer:{type:"line",lineStyle:{color:"#008acd"},crossStyle:{color:"#008acd"},shadowStyle:{color:"rgba(200,200,200,0.2)"}}},dataZoom:{dataBackgroundColor:"#efefff",fillerColor:"rgba(182,162,222,0.2)",handleColor:"#008acd"},grid:{borderColor:"#eee"},categoryAxis:{axisLine:{lineStyle:{color:"#008acd"}},splitLine:{lineStyle:{color:["#eee"]}}},valueAxis:{axisLine:{lineStyle:{color:"#008acd"}},splitArea:{show:!0,areaStyle:{color:["rgba(250,250,250,0.1)","rgba(200,200,200,0.1)"]}},splitLine:{lineStyle:{color:["#eee"]}}},polar:{axisLine:{lineStyle:{color:"#ddd"}},splitArea:{show:!0,areaStyle:{color:["rgba(250,250,250,0.2)","rgba(200,200,200,0.2)"]}},splitLine:{lineStyle:{color:"#ddd"}}},timeline:{lineStyle:{color:"#008acd"},controlStyle:{normal:{color:"#008acd"},emphasis:{color:"#008acd"}},symbol:"emptyCircle",symbolSize:3},bar:{itemStyle:{normal:{barBorderRadius:5},emphasis:{barBorderRadius:5}}},line:{smooth:!0,symbol:"emptyCircle",symbolSize:3},k:{itemStyle:{normal:{color:"#d87a80",color0:"#2ec7c9",lineStyle:{color:"#d87a80",color0:"#2ec7c9"}}}},scatter:{symbol:"circle",symbolSize:4},radar:{symbol:"emptyCircle",symbolSize:3},map:{itemStyle:{normal:{areaStyle:{color:"#ddd"},label:{textStyle:{color:"#d87a80"}}},emphasis:{areaStyle:{color:"#fe994e"}}}},force:{itemStyle:{normal:{linkStyle:{color:"#1e90ff"}}}},chord:{itemStyle:{normal:{borderWidth:1,borderColor:"rgba(128, 128, 128, 0.5)",chordStyle:{lineStyle:{color:"rgba(128, 128, 128, 0.5)"}}},emphasis:{borderWidth:1,borderColor:"rgba(128, 128, 128, 0.5)",chordStyle:{lineStyle:{color:"rgba(128, 128, 128, 0.5)"}}}}},gauge:{axisLine:{lineStyle:{color:[[.2,"#2ec7c9"],[.8,"#5ab1ef"],[1,"#d87a80"]],width:10}},axisTick:{splitNumber:10,length:15,lineStyle:{color:"auto"}},splitLine:{length:22,lineStyle:{color:"auto"}},pointer:{width:5}},textStyle:{fontFamily:"微软雅黑, Arial, Verdana, sans-serif"}};return e}),i("echarts/theme/infographic",[],function(){var e={color:["#C1232B","#B5C334","#FCCE10","#E87C25","#27727B","#FE8463","#9BCA63","#FAD860","#F3A43B","#60C0DD","#D7504B","#C6E579","#F4E001","#F0805A","#26C0C0"],title:{textStyle:{fontWeight:"normal",color:"#27727B"}},dataRange:{x:"right",y:"center",itemWidth:5,itemHeight:25,color:["#C1232B","#FCCE10"]},toolbox:{color:["#C1232B","#B5C334","#FCCE10","#E87C25","#27727B","#FE8463","#9BCA63","#FAD860","#F3A43B","#60C0DD"],effectiveColor:"#ff4500"},tooltip:{backgroundColor:"rgba(50,50,50,0.5)",axisPointer:{type:"line",lineStyle:{color:"#27727B",type:"dashed"},crossStyle:{color:"#27727B"},shadowStyle:{color:"rgba(200,200,200,0.3)"}}},dataZoom:{dataBackgroundColor:"rgba(181,195,52,0.3)",fillerColor:"rgba(181,195,52,0.2)",handleColor:"#27727B"},grid:{borderWidth:0},categoryAxis:{axisLine:{lineStyle:{color:"#27727B"}},splitLine:{show:!1}},valueAxis:{axisLine:{show:!1},splitArea:{show:!1},splitLine:{lineStyle:{color:["#ccc"],type:"dashed"}}},polar:{axisLine:{lineStyle:{color:"#ddd"}},splitArea:{show:!0,areaStyle:{color:["rgba(250,250,250,0.2)","rgba(200,200,200,0.2)"]}},splitLine:{lineStyle:{color:"#ddd"}}},timeline:{lineStyle:{color:"#27727B"},controlStyle:{normal:{color:"#27727B"},emphasis:{color:"#27727B"}},symbol:"emptyCircle",symbolSize:3},line:{itemStyle:{normal:{borderWidth:2,borderColor:"#fff",lineStyle:{width:3}},emphasis:{borderWidth:0}},symbol:"circle",symbolSize:3.5},k:{itemStyle:{normal:{color:"#C1232B",color0:"#B5C334",lineStyle:{width:1,color:"#C1232B",color0:"#B5C334"}}}},scatter:{itemStyle:{normal:{borderWidth:1,borderColor:"rgba(200,200,200,0.5)"},emphasis:{borderWidth:0}},symbol:"star4",symbolSize:4},radar:{symbol:"emptyCircle",symbolSize:3},map:{itemStyle:{normal:{areaStyle:{color:"#ddd"},label:{textStyle:{color:"#C1232B"}}},emphasis:{areaStyle:{color:"#fe994e"},label:{textStyle:{color:"rgb(100,0,0)"}}}}},force:{itemStyle:{normal:{linkStyle:{color:"#27727B"}}}},chord:{itemStyle:{normal:{borderWidth:1,borderColor:"rgba(128, 128, 128, 0.5)",chordStyle:{lineStyle:{color:"rgba(128, 128, 128, 0.5)"}}},emphasis:{borderWidth:1,borderColor:"rgba(128, 128, 128, 0.5)",chordStyle:{lineStyle:{color:"rgba(128, 128, 128, 0.5)"}}}}},gauge:{center:["50%","80%"],radius:"100%",startAngle:180,endAngle:0,axisLine:{show:!0,lineStyle:{color:[[.2,"#B5C334"],[.8,"#27727B"],[1,"#C1232B"]],width:"40%"}},axisTick:{splitNumber:2,length:5,lineStyle:{color:"#fff"}},axisLabel:{textStyle:{color:"#fff",fontWeight:"bolder"}},splitLine:{length:"5%",lineStyle:{color:"#fff"}},pointer:{width:"40%",length:"80%",color:"#fff"},title:{offsetCenter:[0,-20],textStyle:{color:"auto",fontSize:20}},detail:{offsetCenter:[0,0],textStyle:{color:"auto",fontSize:40}}},textStyle:{fontFamily:"微软雅黑, Arial, Verdana, sans-serif"}};return e}),i("zrender/dep/excanvas",["require"],function(){return document.createElement("canvas").getContext?G_vmlCanvasManager=!1:!function(){function e(){return this.context_||(this.context_=new f(this))}function t(e,t){var i=O.call(arguments,2);return function(){return e.apply(t,i.concat(O.call(arguments)))}}function i(e){return String(e).replace(/&/g,"&").replace(/"/g,""")}function n(e,t,i){e.namespaces[t]||e.namespaces.add(t,i,"#default#VML")}function a(e){if(n(e,"g_vml_","urn:schemas-microsoft-com:vml"),n(e,"g_o_","urn:schemas-microsoft-com:office:office"),!e.styleSheets.ex_canvas_){var t=e.createStyleSheet();t.owningElement.id="ex_canvas_",t.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}"}}function o(e){var t=e.srcElement;switch(e.propertyName){case"width":t.getContext().clearRect(),t.style.width=t.attributes.width.nodeValue+"px",t.firstChild.style.width=t.clientWidth+"px";break;case"height":t.getContext().clearRect(),t.style.height=t.attributes.height.nodeValue+"px",t.firstChild.style.height=t.clientHeight+"px"}}function r(e){var t=e.srcElement;t.firstChild&&(t.firstChild.style.width=t.clientWidth+"px",t.firstChild.style.height=t.clientHeight+"px")}function s(){return[[1,0,0],[0,1,0],[0,0,1]]}function l(e,t){for(var i=s(),n=0;3>n;n++)for(var a=0;3>a;a++){for(var o=0,r=0;3>r;r++)o+=e[n][r]*t[r][a];i[n][a]=o}return i}function h(e,t){t.fillStyle=e.fillStyle,t.lineCap=e.lineCap,t.lineJoin=e.lineJoin,t.lineWidth=e.lineWidth,t.miterLimit=e.miterLimit,t.shadowBlur=e.shadowBlur,t.shadowColor=e.shadowColor,t.shadowOffsetX=e.shadowOffsetX,t.shadowOffsetY=e.shadowOffsetY,t.strokeStyle=e.strokeStyle,t.globalAlpha=e.globalAlpha,t.font=e.font,t.textAlign=e.textAlign,t.textBaseline=e.textBaseline,t.scaleX_=e.scaleX_,t.scaleY_=e.scaleY_,t.lineScale_=e.lineScale_}function m(e){var t=e.indexOf("(",3),i=e.indexOf(")",t+1),n=e.substring(t+1,i).split(",");return(4!=n.length||"a"!=e.charAt(3))&&(n[3]=1),n}function V(e){return parseFloat(e)/100}function U(e,t,i){return Math.min(i,Math.max(t,e))}function d(e){var t,i,n,a,o,r;if(a=parseFloat(e[0])/360%360,0>a&&a++,o=U(V(e[1]),0,1),r=U(V(e[2]),0,1),0==o)t=i=n=r;else{var s=.5>r?r*(1+o):r+o-r*o,l=2*r-s;t=p(l,s,a+1/3),i=p(l,s,a),n=p(l,s,a-1/3)}return"#"+D[Math.floor(255*t)]+D[Math.floor(255*i)]+D[Math.floor(255*n)]}function p(e,t,i){return 0>i&&i++,i>1&&i--,1>6*i?e+6*(t-e)*i:1>2*i?t:2>3*i?e+(t-e)*(2/3-i)*6:e}function c(e){if(e in R)return R[e];var t,i=1;if(e=String(e),"#"==e.charAt(0))t=e;else if(/^rgb/.test(e)){for(var n,a=m(e),t="#",o=0;3>o;o++)n=-1!=a[o].indexOf("%")?Math.floor(255*V(a[o])):+a[o],t+=D[U(n,0,255)];i=+a[3]}else if(/^hsl/.test(e)){var a=m(e);t=d(a),i=a[3]}else t=H[e]||e;return R[e]={color:t,alpha:i}}function u(e){if(Y[e])return Y[e];var t,i=document.createElement("div"),n=i.style;try{n.font=e,t=n.fontFamily.split(",")[0]}catch(a){}return Y[e]={style:n.fontStyle||G.style,variant:n.fontVariant||G.variant,weight:n.fontWeight||G.weight,size:n.fontSize||G.size,family:t||G.family}}function y(e,t){var i={};for(var n in e)i[n]=e[n];var a=parseFloat(t.currentStyle.fontSize),o=parseFloat(e.size);return i.size="number"==typeof e.size?e.size:-1!=e.size.indexOf("px")?o:-1!=e.size.indexOf("em")?a*o:-1!=e.size.indexOf("%")?a/100*o:-1!=e.size.indexOf("pt")?o/.75:a,i}function g(e){return e.style+" "+e.variant+" "+e.weight+" "+e.size+"px '"+e.family+"'"}function b(e){return Q[e]||"square"}function f(e){this.m_=s(),this.mStack_=[],this.aStack_=[],this.currentPath_=[],this.strokeStyle="#000",this.fillStyle="#000",this.lineWidth=1,this.lineJoin="miter",this.lineCap="butt",this.miterLimit=1*A,this.globalAlpha=1,this.font="12px 微软雅黑",this.textAlign="left",this.textBaseline="alphabetic",this.canvas=e;var t="width:"+e.clientWidth+"px;height:"+e.clientHeight+"px;overflow:hidden;position:absolute",i=e.ownerDocument.createElement("div");i.style.cssText=t,e.appendChild(i);var n=i.cloneNode(!1);n.style.backgroundColor="#fff",n.style.filter="alpha(opacity=0)",e.appendChild(n),this.element_=i,this.scaleX_=1,this.scaleY_=1,this.lineScale_=1}function k(e,t,i,n){e.currentPath_.push({type:"bezierCurveTo",cp1x:t.x,cp1y:t.y,cp2x:i.x,cp2y:i.y,x:n.x,y:n.y}),e.currentX_=n.x,e.currentY_=n.y}function x(e,t){var i=c(e.strokeStyle),n=i.color,a=i.alpha*e.globalAlpha,o=e.lineScale_*e.lineWidth;1>o&&(a*=o),t.push("')}function _(e,t,i,n){var a=e.fillStyle,o=e.scaleX_,r=e.scaleY_,s=n.x-i.x,l=n.y-i.y;if(a instanceof v){var h=0,m={x:0,y:0},V=0,U=1;if("gradient"==a.type_){var d=a.x0_/o,p=a.y0_/r,u=a.x1_/o,y=a.y1_/r,g=L(e,d,p),b=L(e,u,y),f=b.x-g.x,k=b.y-g.y;h=180*Math.atan2(f,k)/Math.PI,0>h&&(h+=360),1e-6>h&&(h=0)}else{var g=L(e,a.x0_,a.y0_);m={x:(g.x-i.x)/s,y:(g.y-i.y)/l},s/=o*A,l/=r*A;var x=C.max(s,l);V=2*a.r0_/x,U=2*a.r1_/x-V}var _=a.colors_;_.sort(function(e,t){return e.offset-t.offset});for(var W=_.length,X=_[0].color,K=_[W-1].color,I=_[0].alpha*e.globalAlpha,J=_[W-1].alpha*e.globalAlpha,S=[],E=0;W>E;E++){var F=_[E];S.push(F.offset*U+V+" "+F.color)}t.push('')}else if(a instanceof w){if(s&&l){var T=-i.x,z=-i.y;t.push("')}}else{var M=c(e.fillStyle),O=M.color,P=M.alpha*e.globalAlpha;t.push('')}}function L(e,t,i){var n=e.m_;return{x:A*(t*n[0][0]+i*n[1][0]+n[2][0])-M,y:A*(t*n[0][1]+i*n[1][1]+n[2][1])-M}}function W(e){return isFinite(e[0][0])&&isFinite(e[0][1])&&isFinite(e[1][0])&&isFinite(e[1][1])&&isFinite(e[2][0])&&isFinite(e[2][1])}function X(e,t,i){if(W(t)&&(e.m_=t,e.scaleX_=Math.sqrt(t[0][0]*t[0][0]+t[0][1]*t[0][1]),e.scaleY_=Math.sqrt(t[1][0]*t[1][0]+t[1][1]*t[1][1]),i)){var n=t[0][0]*t[1][1]-t[0][1]*t[1][0];e.lineScale_=z(T(n))}}function v(e){this.type_=e,this.x0_=0,this.y0_=0,this.r0_=0,this.x1_=0,this.y1_=0,this.r1_=0,this.colors_=[]}function w(e,t){switch(I(e),t){case"repeat":case null:case"":this.repetition_="repeat";break;case"repeat-x":case"repeat-y":case"no-repeat":this.repetition_=t;break;default:K("SYNTAX_ERR")}this.src_=e.src,this.width_=e.width,this.height_=e.height}function K(e){throw new J(e)}function I(e){e&&1==e.nodeType&&"IMG"==e.tagName||K("TYPE_MISMATCH_ERR"),"complete"!=e.readyState&&K("INVALID_STATE_ERR")}function J(e){this.code=this[e],this.message=e+": DOM Exception "+this.code}var C=Math,S=C.round,E=C.sin,F=C.cos,T=C.abs,z=C.sqrt,A=10,M=A/2,O=(+navigator.userAgent.match(/MSIE ([\d.]+)?/)[1],Array.prototype.slice);a(document);var P={init:function(e){var i=e||document;i.createElement("canvas"),i.attachEvent("onreadystatechange",t(this.init_,this,i))},init_:function(e){for(var t=e.getElementsByTagName("canvas"),i=0;iN;N++)for(var B=0;16>B;B++)D[16*N+B]=N.toString(16)+B.toString(16);var H={aliceblue:"#F0F8FF",antiquewhite:"#FAEBD7",aquamarine:"#7FFFD4",azure:"#F0FFFF",beige:"#F5F5DC",bisque:"#FFE4C4",black:"#000000",blanchedalmond:"#FFEBCD",blueviolet:"#8A2BE2",brown:"#A52A2A",burlywood:"#DEB887",cadetblue:"#5F9EA0",chartreuse:"#7FFF00",chocolate:"#D2691E",coral:"#FF7F50",cornflowerblue:"#6495ED",cornsilk:"#FFF8DC",crimson:"#DC143C",cyan:"#00FFFF",darkblue:"#00008B",darkcyan:"#008B8B",darkgoldenrod:"#B8860B",darkgray:"#A9A9A9",darkgreen:"#006400",darkgrey:"#A9A9A9",darkkhaki:"#BDB76B",darkmagenta:"#8B008B",darkolivegreen:"#556B2F",darkorange:"#FF8C00",darkorchid:"#9932CC",darkred:"#8B0000",darksalmon:"#E9967A",darkseagreen:"#8FBC8F",darkslateblue:"#483D8B",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",darkturquoise:"#00CED1",darkviolet:"#9400D3",deeppink:"#FF1493",deepskyblue:"#00BFFF",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1E90FF",firebrick:"#B22222",floralwhite:"#FFFAF0",forestgreen:"#228B22",gainsboro:"#DCDCDC",ghostwhite:"#F8F8FF",gold:"#FFD700",goldenrod:"#DAA520",grey:"#808080",greenyellow:"#ADFF2F",honeydew:"#F0FFF0",hotpink:"#FF69B4",indianred:"#CD5C5C",indigo:"#4B0082",ivory:"#FFFFF0",khaki:"#F0E68C",lavender:"#E6E6FA",lavenderblush:"#FFF0F5",lawngreen:"#7CFC00",lemonchiffon:"#FFFACD",lightblue:"#ADD8E6",lightcoral:"#F08080",lightcyan:"#E0FFFF",lightgoldenrodyellow:"#FAFAD2",lightgreen:"#90EE90",lightgrey:"#D3D3D3",lightpink:"#FFB6C1",lightsalmon:"#FFA07A",lightseagreen:"#20B2AA",lightskyblue:"#87CEFA",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#B0C4DE",lightyellow:"#FFFFE0",limegreen:"#32CD32",linen:"#FAF0E6",magenta:"#FF00FF",mediumaquamarine:"#66CDAA",mediumblue:"#0000CD",mediumorchid:"#BA55D3",mediumpurple:"#9370DB",mediumseagreen:"#3CB371",mediumslateblue:"#7B68EE",mediumspringgreen:"#00FA9A",mediumturquoise:"#48D1CC",mediumvioletred:"#C71585",midnightblue:"#191970",mintcream:"#F5FFFA",mistyrose:"#FFE4E1",moccasin:"#FFE4B5",navajowhite:"#FFDEAD",oldlace:"#FDF5E6",olivedrab:"#6B8E23",orange:"#FFA500",orangered:"#FF4500",orchid:"#DA70D6",palegoldenrod:"#EEE8AA",palegreen:"#98FB98",paleturquoise:"#AFEEEE",palevioletred:"#DB7093",papayawhip:"#FFEFD5",peachpuff:"#FFDAB9",peru:"#CD853F",pink:"#FFC0CB",plum:"#DDA0DD",powderblue:"#B0E0E6",rosybrown:"#BC8F8F",royalblue:"#4169E1",saddlebrown:"#8B4513",salmon:"#FA8072",sandybrown:"#F4A460",seagreen:"#2E8B57",seashell:"#FFF5EE",sienna:"#A0522D",skyblue:"#87CEEB",slateblue:"#6A5ACD",slategray:"#708090",slategrey:"#708090",snow:"#FFFAFA",springgreen:"#00FF7F",steelblue:"#4682B4",tan:"#D2B48C",thistle:"#D8BFD8",tomato:"#FF6347",turquoise:"#40E0D0",violet:"#EE82EE",wheat:"#F5DEB3",whitesmoke:"#F5F5F5",yellowgreen:"#9ACD32"},R={},G={style:"normal",variant:"normal",weight:"normal",size:12,family:"微软雅黑"},Y={},Q={butt:"flat",round:"round"},Z=f.prototype;Z.clearRect=function(){this.textMeasureEl_&&(this.textMeasureEl_.removeNode(!0),this.textMeasureEl_=null),this.element_.innerHTML=""},Z.beginPath=function(){this.currentPath_=[]},Z.moveTo=function(e,t){var i=L(this,e,t);this.currentPath_.push({type:"moveTo",x:i.x,y:i.y}),this.currentX_=i.x,this.currentY_=i.y},Z.lineTo=function(e,t){var i=L(this,e,t);this.currentPath_.push({type:"lineTo",x:i.x,y:i.y}),this.currentX_=i.x,this.currentY_=i.y},Z.bezierCurveTo=function(e,t,i,n,a,o){var r=L(this,a,o),s=L(this,e,t),l=L(this,i,n);k(this,s,l,r)},Z.quadraticCurveTo=function(e,t,i,n){var a=L(this,e,t),o=L(this,i,n),r={x:this.currentX_+2/3*(a.x-this.currentX_),y:this.currentY_+2/3*(a.y-this.currentY_)},s={x:r.x+(o.x-this.currentX_)/3,y:r.y+(o.y-this.currentY_)/3};k(this,r,s,o)},Z.arc=function(e,t,i,n,a,o){i*=A;var r=o?"at":"wa",s=e+F(n)*i-M,l=t+E(n)*i-M,h=e+F(a)*i-M,m=t+E(a)*i-M;s!=h||o||(s+=.125);var V=L(this,e,t),U=L(this,s,l),d=L(this,h,m);this.currentPath_.push({type:r,x:V.x,y:V.y,radius:i,xStart:U.x,yStart:U.y,xEnd:d.x,yEnd:d.y})},Z.rect=function(e,t,i,n){this.moveTo(e,t),this.lineTo(e+i,t),this.lineTo(e+i,t+n),this.lineTo(e,t+n),this.closePath()},Z.strokeRect=function(e,t,i,n){var a=this.currentPath_;this.beginPath(),this.moveTo(e,t),this.lineTo(e+i,t),this.lineTo(e+i,t+n),this.lineTo(e,t+n),this.closePath(),this.stroke(),this.currentPath_=a},Z.fillRect=function(e,t,i,n){var a=this.currentPath_;this.beginPath(),this.moveTo(e,t),this.lineTo(e+i,t),this.lineTo(e+i,t+n),this.lineTo(e,t+n),this.closePath(),this.fill(),this.currentPath_=a},Z.createLinearGradient=function(e,t,i,n){var a=new v("gradient");return a.x0_=e,a.y0_=t,a.x1_=i,a.y1_=n,a},Z.createRadialGradient=function(e,t,i,n,a,o){var r=new v("gradientradial");return r.x0_=e,r.y0_=t,r.r0_=i,r.x1_=n,r.y1_=a,r.r1_=o,r},Z.drawImage=function(e){var t,i,n,a,o,r,s,l,h=e.runtimeStyle.width,m=e.runtimeStyle.height;e.runtimeStyle.width="auto",e.runtimeStyle.height="auto";var V=e.width,U=e.height;if(e.runtimeStyle.width=h,e.runtimeStyle.height=m,3==arguments.length)t=arguments[1],i=arguments[2],o=r=0,s=n=V,l=a=U;else if(5==arguments.length)t=arguments[1],i=arguments[2],n=arguments[3],a=arguments[4],o=r=0,s=V,l=U;else{if(9!=arguments.length)throw Error("Invalid number of arguments");o=arguments[1],r=arguments[2],s=arguments[3],l=arguments[4],t=arguments[5],i=arguments[6],n=arguments[7],a=arguments[8]}var d=L(this,t,i),p=[],c=10,u=10,y=b=1;if(p.push(" '),(o||r)&&p.push('
                          '),p.push('
                          '),(o||r)&&p.push("
                          "),p.push("
                          "),this.element_.insertAdjacentHTML("BeforeEnd",p.join(""))},Z.stroke=function(e){var t=[],i=10,n=10;t.push("o.x)&&(o.x=l.x),(null==a.y||l.yo.y)&&(o.y=l.y))}t.push(' ">'),e?_(this,t,a,o):x(this,t),t.push(""),this.element_.insertAdjacentHTML("beforeEnd",t.join(""))},Z.fill=function(){this.stroke(!0)},Z.closePath=function(){this.currentPath_.push({type:"close"})},Z.save=function(){var e={};h(this,e),this.aStack_.push(e),this.mStack_.push(this.m_),this.m_=l(s(),this.m_)},Z.restore=function(){this.aStack_.length&&(h(this.aStack_.pop(),this),this.m_=this.mStack_.pop())},Z.translate=function(e,t){var i=[[1,0,0],[0,1,0],[e,t,1]];X(this,l(i,this.m_),!1)},Z.rotate=function(e){var t=F(e),i=E(e),n=[[t,i,0],[-i,t,0],[0,0,1]];X(this,l(n,this.m_),!1)},Z.scale=function(e,t){var i=[[e,0,0],[0,t,0],[0,0,1]];X(this,l(i,this.m_),!0)},Z.transform=function(e,t,i,n,a,o){var r=[[e,t,0],[i,n,0],[a,o,1]];X(this,l(r,this.m_),!0)},Z.setTransform=function(e,t,i,n,a,o){var r=[[e,t,0],[i,n,0],[a,o,1]];X(this,r,!0)},Z.drawText_=function(e,t,n,a,o){var r=this.m_,s=1e3,l=0,h=s,m={x:0,y:0},V=[],U=y(u(this.font),this.element_),d=g(U),p=this.element_.currentStyle,c=this.textAlign.toLowerCase();switch(c){case"left":case"center":case"right":break;case"end":c="ltr"==p.direction?"right":"left";break;case"start":c="rtl"==p.direction?"right":"left";break;default:c="left"}switch(this.textBaseline){case"hanging":case"top":m.y=U.size/1.75;break;case"middle":break;default:case null:case"alphabetic":case"ideographic":case"bottom":m.y=-U.size/2.25}switch(c){case"right":l=s,h=.05;break;case"center":l=h=s/2}var b=L(this,t+m.x,n+m.y);V.push(''),o?x(this,V):_(this,V,{x:-l,y:0},{x:h,y:U.size});var f=r[0][0].toFixed(3)+","+r[1][0].toFixed(3)+","+r[0][1].toFixed(3)+","+r[1][1].toFixed(3)+",0,0",k=S(b.x/A)+","+S(b.y/A);V.push('','',''),this.element_.insertAdjacentHTML("beforeEnd",V.join(""))},Z.fillText=function(e,t,i,n){this.drawText_(e,t,i,n,!1)},Z.strokeText=function(e,t,i,n){this.drawText_(e,t,i,n,!0)},Z.measureText=function(e){if(!this.textMeasureEl_){var t='';this.element_.insertAdjacentHTML("beforeEnd",t),this.textMeasureEl_=this.element_.lastChild}var i=this.element_.ownerDocument;this.textMeasureEl_.innerHTML="";try{this.textMeasureEl_.style.font=this.font}catch(n){}return this.textMeasureEl_.appendChild(i.createTextNode(e)),{width:this.textMeasureEl_.offsetWidth}},Z.clip=function(){},Z.arcTo=function(){},Z.createPattern=function(e,t){return new w(e,t)},v.prototype.addColorStop=function(e,t){t=c(t),this.colors_.push({offset:e,color:t.color,alpha:t.alpha})};var q=J.prototype=new Error;q.INDEX_SIZE_ERR=1,q.DOMSTRING_SIZE_ERR=2,q.HIERARCHY_REQUEST_ERR=3,q.WRONG_DOCUMENT_ERR=4,q.INVALID_CHARACTER_ERR=5,q.NO_DATA_ALLOWED_ERR=6,q.NO_MODIFICATION_ALLOWED_ERR=7,q.NOT_FOUND_ERR=8,q.NOT_SUPPORTED_ERR=9,q.INUSE_ATTRIBUTE_ERR=10,q.INVALID_STATE_ERR=11,q.SYNTAX_ERR=12,q.INVALID_MODIFICATION_ERR=13,q.NAMESPACE_ERR=14,q.INVALID_ACCESS_ERR=15,q.VALIDATION_ERR=16,q.TYPE_MISMATCH_ERR=17,G_vmlCanvasManager=P,CanvasRenderingContext2D=f,CanvasGradient=v,CanvasPattern=w,DOMException=J}(),G_vmlCanvasManager}),i("zrender/mixin/Eventful",["require"],function(){var e=function(){this._handlers={}};return e.prototype.one=function(e,t,i){var n=this._handlers;return t&&e?(n[e]||(n[e]=[]),n[e].push({h:t,one:!0,ctx:i||this}),this):this},e.prototype.bind=function(e,t,i){var n=this._handlers;return t&&e?(n[e]||(n[e]=[]),n[e].push({h:t,one:!1,ctx:i||this}),this):this},e.prototype.unbind=function(e,t){var i=this._handlers;if(!e)return this._handlers={},this;if(t){if(i[e]){for(var n=[],a=0,o=i[e].length;o>a;a++)i[e][a].h!=t&&n.push(i[e][a]);i[e]=n}i[e]&&0===i[e].length&&delete i[e]}else delete i[e];return this},e.prototype.dispatch=function(e){if(this._handlers[e]){var t=arguments,i=t.length;i>3&&(t=Array.prototype.slice.call(t,1));for(var n=this._handlers[e],a=n.length,o=0;a>o;){switch(i){case 1:n[o].h.call(n[o].ctx);break;case 2:n[o].h.call(n[o].ctx,t[1]);break;case 3:n[o].h.call(n[o].ctx,t[1],t[2]);break;default:n[o].h.apply(n[o].ctx,t)}n[o].one?(n.splice(o,1),a--):o++}}return this},e.prototype.dispatchWithContext=function(e){if(this._handlers[e]){var t=arguments,i=t.length;i>4&&(t=Array.prototype.slice.call(t,1,t.length-1));for(var n=t[t.length-1],a=this._handlers[e],o=a.length,r=0;o>r;){switch(i){case 1:a[r].h.call(n);break;case 2:a[r].h.call(n,t[1]);break;case 3:a[r].h.call(n,t[1],t[2]);break;default:a[r].h.apply(n,t)}a[r].one?(a.splice(r,1),o--):r++}}return this},e}),i("zrender/tool/log",["require","../config"],function(e){var t=e("../config");return function(){if(0!==t.debugMode)if(1==t.debugMode)for(var e in arguments)throw new Error(arguments[e]);else if(t.debugMode>1)for(var e in arguments)console.log(arguments[e])}}),i("zrender/tool/guid",[],function(){var e=2311;return function(){return"zrender__"+e++}}),i("zrender/Handler",["require","./config","./tool/env","./tool/event","./tool/util","./tool/vector","./tool/matrix","./mixin/Eventful"],function(e){"use strict";function t(e,t){return function(i,n){return e.call(t,i,n)}}function i(e,t){return function(i,n,a){return e.call(t,i,n,a)}}function n(e){for(var i=d.length;i--;){var n=d[i];e["_"+n+"Handler"]=t(c[n],e)}}function a(e,t,i){if(this._draggingTarget&&this._draggingTarget.id==e.id||e.isSilent())return!1;var n=this._event;if(e.isCover(t,i)){e.hoverable&&this.storage.addHover(e);for(var a=e.parent;a;){if(a.clipShape&&!a.clipShape.isCover(this._mouseX,this._mouseY))return!1;a=a.parent}return this._lastHover!=e&&(this._processOutShape(n),this._processDragLeave(n),this._lastHover=e,this._processDragEnter(n)),this._processOverShape(n),this._processDragOver(n),this._hasfound=1,!0}return!1}var o=e("./config"),r=e("./tool/env"),s=e("./tool/event"),l=e("./tool/util"),h=e("./tool/vector"),m=e("./tool/matrix"),V=o.EVENT,U=e("./mixin/Eventful"),d=["resize","click","dblclick","mousewheel","mousemove","mouseout","mouseup","mousedown","touchstart","touchend","touchmove"],p=function(e){if(window.G_vmlCanvasManager)return!0;e=e||window.event;var t=e.toElement||e.relatedTarget||e.srcElement||e.target;return t&&t.className.match(o.elementClassName)},c={resize:function(e){e=e||window.event,this._lastHover=null,this._isMouseDown=0,this.dispatch(V.RESIZE,e)},click:function(e,t){if(p(e)||t){e=this._zrenderEventFixed(e);var i=this._lastHover;(i&&i.clickable||!i)&&this._clickThreshold<5&&this._dispatchAgency(i,V.CLICK,e),this._mousemoveHandler(e)}},dblclick:function(e,t){if(p(e)||t){e=e||window.event,e=this._zrenderEventFixed(e);var i=this._lastHover;(i&&i.clickable||!i)&&this._clickThreshold<5&&this._dispatchAgency(i,V.DBLCLICK,e),this._mousemoveHandler(e)}},mousewheel:function(e,t){if(p(e)||t){e=this._zrenderEventFixed(e);var i=e.wheelDelta||-e.detail,n=i>0?1.1:1/1.1,a=!1,o=this._mouseX,r=this._mouseY;this.painter.eachBuildinLayer(function(t){var i=t.position;if(t.zoomable){t.__zoom=t.__zoom||1;var l=t.__zoom;l*=n,l=Math.max(Math.min(t.maxZoom,l),t.minZoom),n=l/t.__zoom,t.__zoom=l,i[0]-=(o-i[0])*(n-1),i[1]-=(r-i[1])*(n-1),t.scale[0]*=n,t.scale[1]*=n,t.dirty=!0,a=!0,s.stop(e)}}),a&&this.painter.refresh(),this._dispatchAgency(this._lastHover,V.MOUSEWHEEL,e),this._mousemoveHandler(e)}},mousemove:function(e,t){if((p(e)||t)&&!this.painter.isLoading()){e=this._zrenderEventFixed(e),this._lastX=this._mouseX,this._lastY=this._mouseY,this._mouseX=s.getX(e),this._mouseY=s.getY(e);var i=this._mouseX-this._lastX,n=this._mouseY-this._lastY;this._processDragStart(e),this._hasfound=0,this._event=e,this._iterateAndFindHover(),this._hasfound||((!this._draggingTarget||this._lastHover&&this._lastHover!=this._draggingTarget)&&(this._processOutShape(e), -this._processDragLeave(e)),this._lastHover=null,this.storage.delHover(),this.painter.clearHover());var a="default";if(this._draggingTarget)this.storage.drift(this._draggingTarget.id,i,n),this._draggingTarget.modSelf(),this.storage.addHover(this._draggingTarget),this._clickThreshold++;else if(this._isMouseDown){var o=!1;this.painter.eachBuildinLayer(function(e){e.panable&&(a="move",e.position[0]+=i,e.position[1]+=n,o=!0,e.dirty=!0)}),o&&this.painter.refresh()}this._draggingTarget||this._hasfound&&this._lastHover.draggable?a="move":this._hasfound&&this._lastHover.clickable&&(a="pointer"),this.root.style.cursor=a,this._dispatchAgency(this._lastHover,V.MOUSEMOVE,e),(this._draggingTarget||this._hasfound||this.storage.hasHoverShape())&&this.painter.refreshHover()}},mouseout:function(e,t){if(p(e)||t){e=this._zrenderEventFixed(e);var i=e.toElement||e.relatedTarget;if(i!=this.root)for(;i&&9!=i.nodeType;){if(i==this.root)return void this._mousemoveHandler(e);i=i.parentNode}e.zrenderX=this._lastX,e.zrenderY=this._lastY,this.root.style.cursor="default",this._isMouseDown=0,this._processOutShape(e),this._processDrop(e),this._processDragEnd(e),this.painter.isLoading()||this.painter.refreshHover(),this.dispatch(V.GLOBALOUT,e)}},mousedown:function(e,t){if(p(e)||t){if(this._clickThreshold=0,2==this._lastDownButton)return this._lastDownButton=e.button,void(this._mouseDownTarget=null);this._lastMouseDownMoment=new Date,e=this._zrenderEventFixed(e),this._isMouseDown=1,this._mouseDownTarget=this._lastHover,this._dispatchAgency(this._lastHover,V.MOUSEDOWN,e),this._lastDownButton=e.button}},mouseup:function(e,t){(p(e)||t)&&(e=this._zrenderEventFixed(e),this.root.style.cursor="default",this._isMouseDown=0,this._mouseDownTarget=null,this._dispatchAgency(this._lastHover,V.MOUSEUP,e),this._processDrop(e),this._processDragEnd(e))},touchstart:function(e,t){(p(e)||t)&&(e=this._zrenderEventFixed(e,!0),this._lastTouchMoment=new Date,this._mobileFindFixed(e),this._mousedownHandler(e))},touchmove:function(e,t){(p(e)||t)&&(e=this._zrenderEventFixed(e,!0),this._mousemoveHandler(e),this._isDragging&&s.stop(e))},touchend:function(e,t){if(p(e)||t){e=this._zrenderEventFixed(e,!0),this._mouseupHandler(e);var i=new Date;i-this._lastTouchMoment=0;o--){var r=n[o];if(t!==r.zlevel&&(i=this.painter.getLayer(r.zlevel,i),a[0]=this._mouseX,a[1]=this._mouseY,i.needTransform&&(m.invert(e,i.transform),h.applyTransform(a,a,e))),this._findHover(r,a[0],a[1]))break}}}();var y=[{x:10},{x:-20},{x:10,y:10},{y:-20}];return u.prototype._mobileFindFixed=function(e){this._lastHover=null,this._mouseX=e.zrenderX,this._mouseY=e.zrenderY,this._event=e,this._iterateAndFindHover();for(var t=0;!this._lastHover&&ts;s++){var h=e[s];if(n!==h.zlevel&&(i&&(i.needTransform&&o.restore(),o.flush&&o.flush()),n=h.zlevel,i=this.getLayer(n),i.isBuildin||r("ZLevel "+n+" has been used by unkown layer "+i.id),o=i.ctx,i.unusedCount=0,(i.dirty||t)&&i.clear(),i.needTransform&&(o.save(),i.setTransform(o))),(i.dirty||t)&&!h.invisible&&(!h.onbrush||h.onbrush&&!h.onbrush(o,!1)))if(a.catchBrushException)try{h.brush(o,!1,this.refreshNextFrame)}catch(m){r(m,"brush error of "+h.type,h)}else h.brush(o,!1,this.refreshNextFrame);h.__dirty=!1}i&&(i.needTransform&&o.restore(),o.flush&&o.flush()),this.eachBuildinLayer(this._postProcessLayer)},h.prototype.getLayer=function(e){var t=this._layers[e];return t||(t=new l(e,this),t.isBuildin=!0,this._layerConfig[e]&&o.merge(t,this._layerConfig[e],!0),t.updateTransform(),this.insertLayer(e,t),t.initContext()),t},h.prototype.insertLayer=function(e,t){if(this._layers[e])return void r("ZLevel "+e+" has been used already");if(!n(t))return void r("Layer of zlevel "+e+" is not valid");var i=this._zlevelList.length,a=null,o=-1;if(i>0&&e>this._zlevelList[0]){for(o=0;i-1>o&&!(this._zlevelList[o]e);o++);a=this._layers[this._zlevelList[o]]}this._zlevelList.splice(o+1,0,e);var s=a?a.dom:this._bgDom;s.nextSibling?s.parentNode.insertBefore(t.dom,s.nextSibling):s.parentNode.appendChild(t.dom),this._layers[e]=t},h.prototype.eachLayer=function(e,t){for(var i=0;in;n++){var o=e[n],r=o.zlevel,s=t[r];if(s){if(s.elCount++,s.dirty)continue;s.dirty=o.__dirty}}this.eachBuildinLayer(function(e,t){i[t]!==e.elCount&&(e.dirty=!0)})},h.prototype.refreshShapes=function(e,t){for(var i=0,n=e.length;n>i;i++){var a=e[i];a.modSelf()}return this.refresh(t),this},h.prototype.setLoadingEffect=function(e){return this._loadingEffect=e,this},h.prototype.clear=function(){return this.eachBuildinLayer(this._clearLayer),this},h.prototype._clearLayer=function(e){e.clear()},h.prototype.modLayer=function(e,t){if(t){this._layerConfig[e]?o.merge(this._layerConfig[e],t,!0):this._layerConfig[e]=t;var i=this._layers[e];i&&o.merge(i,this._layerConfig[e],!0)}},h.prototype.delLayer=function(e){var t=this._layers[e];t&&(this.modLayer(e,{position:t.position,rotation:t.rotation,scale:t.scale}),t.dom.parentNode.removeChild(t.dom),delete this._layers[e],this._zlevelList.splice(o.indexOf(this._zlevelList,e),1))},h.prototype.refreshHover=function(){this.clearHover();for(var e=this.storage.getHoverShapes(!0),t=0,i=e.length;i>t;t++)this._brushHover(e[t]);var n=this._layers.hover.ctx;return n.flush&&n.flush(),this.storage.delHover(),this},h.prototype.clearHover=function(){var e=this._layers.hover;return e&&e.clear(),this},h.prototype.showLoading=function(e){return this._loadingEffect&&this._loadingEffect.stop(),e&&this.setLoadingEffect(e),this._loadingEffect.start(this),this.loading=!0,this},h.prototype.hideLoading=function(){return this._loadingEffect.stop(),this.clearHover(),this.loading=!1,this},h.prototype.isLoading=function(){return this.loading},h.prototype.resize=function(){var e=this._domRoot;e.style.display="none";var t=this._getWidth(),i=this._getHeight();if(e.style.display="",this._width!=t||i!=this._height){this._width=t,this._height=i,e.style.width=t+"px",e.style.height=i+"px";for(var n in this._layers)this._layers[n].resize(t,i);this.refresh(null,!0)}return this},h.prototype.clearLayer=function(e){var t=this._layers[e];t&&t.clear()},h.prototype.dispose=function(){this.isLoading()&&this.hideLoading(),this.root.innerHTML="",this.root=this.storage=this._domRoot=this._layers=null},h.prototype.getDomHover=function(){return this._layers.hover.dom},h.prototype.toDataURL=function(e,t,i){if(window.G_vmlCanvasManager)return null;var n=new l("image",this);this._bgDom.appendChild(n.dom),n.initContext();var o=n.ctx;n.clearColor=t||"#fff",n.clear();var s=this;this.storage.iterShape(function(e){if(!e.invisible&&(!e.onbrush||e.onbrush&&!e.onbrush(o,!1)))if(a.catchBrushException)try{e.brush(o,!1,s.refreshNextFrame)}catch(t){r(t,"brush error of "+e.type,e)}else e.brush(o,!1,s.refreshNextFrame)},{normal:"up",update:!0});var h=n.dom.toDataURL(e,i);return o=null,this._bgDom.removeChild(n.dom),h},h.prototype.getWidth=function(){return this._width},h.prototype.getHeight=function(){return this._height},h.prototype._getWidth=function(){var e=this.root,t=e.currentStyle||document.defaultView.getComputedStyle(e);return((e.clientWidth||parseInt(t.width,10))-parseInt(t.paddingLeft,10)-parseInt(t.paddingRight,10)).toFixed(0)-0},h.prototype._getHeight=function(){var e=this.root,t=e.currentStyle||document.defaultView.getComputedStyle(e);return((e.clientHeight||parseInt(t.height,10))-parseInt(t.paddingTop,10)-parseInt(t.paddingBottom,10)).toFixed(0)-0},h.prototype._brushHover=function(e){var t=this._layers.hover.ctx;if(!e.onbrush||e.onbrush&&!e.onbrush(t,!0)){var i=this.getLayer(e.zlevel);if(i.needTransform&&(t.save(),i.setTransform(t)),a.catchBrushException)try{e.brush(t,!0,this.refreshNextFrame)}catch(n){r(n,"hoverBrush error of "+e.type,e)}else e.brush(t,!0,this.refreshNextFrame);i.needTransform&&t.restore()}},h.prototype._shapeToImage=function(t,i,n,a,o){var r=document.createElement("canvas"),s=r.getContext("2d");r.style.width=n+"px",r.style.height=a+"px",r.setAttribute("width",n*o),r.setAttribute("height",a*o),s.clearRect(0,0,n*o,a*o);var l={position:i.position,rotation:i.rotation,scale:i.scale};i.position=[0,0,0],i.rotation=0,i.scale=[1,1],i&&i.brush(s,!1);var h=e("./shape/Image"),m=new h({id:t,style:{x:0,y:0,image:r}});return null!=l.position&&(m.position=i.position=l.position),null!=l.rotation&&(m.rotation=i.rotation=l.rotation),null!=l.scale&&(m.scale=i.scale=l.scale),m},h.prototype._createShapeToImageProcessor=function(){if(window.G_vmlCanvasManager)return i;var e=this;return function(t,i,n,o){return e._shapeToImage(t,i,n,o,a.devicePixelRatio)}},h}),i("zrender/Storage",["require","./tool/util","./Group"],function(e){"use strict";function t(e,t){return e.zlevel==t.zlevel?e.z==t.z?e.__renderidx-t.__renderidx:e.z-t.z:e.zlevel-t.zlevel}var i=e("./tool/util"),n=e("./Group"),a={hover:!1,normal:"down",update:!1},o=function(){this._elements={},this._hoverElements=[],this._roots=[],this._shapeList=[],this._shapeListOffset=0};return o.prototype.iterShape=function(e,t){if(t||(t=a),t.hover)for(var i=0,n=this._hoverElements.length;n>i;i++){var o=this._hoverElements[i];if(o.updateTransform(),e(o))return this}switch(t.update&&this.updateShapeList(),t.normal){case"down":for(var n=this._shapeList.length;n--;)if(e(this._shapeList[n]))return this;break;default:for(var i=0,n=this._shapeList.length;n>i;i++)if(e(this._shapeList[i]))return this}return this},o.prototype.getHoverShapes=function(e){for(var i=[],n=0,a=this._hoverElements.length;a>n;n++){i.push(this._hoverElements[n]);var o=this._hoverElements[n].hoverConnect;if(o){var r;o=o instanceof Array?o:[o];for(var s=0,l=o.length;l>s;s++)r=o[s].id?o[s]:this.get(o[s]),r&&i.push(r)}}if(i.sort(t),e)for(var n=0,a=i.length;a>n;n++)i[n].updateTransform();return i},o.prototype.getShapeList=function(e){return e&&this.updateShapeList(),this._shapeList},o.prototype.updateShapeList=function(){this._shapeListOffset=0;for(var e=0,i=this._roots.length;i>e;e++){var n=this._roots[e];this._updateAndAddShape(n)}this._shapeList.length=this._shapeListOffset;for(var e=0,i=this._shapeList.length;i>e;e++)this._shapeList[e].__renderidx=e;this._shapeList.sort(t)},o.prototype._updateAndAddShape=function(e,t){if(!e.ignore)if(e.updateTransform(),e.clipShape&&(e.clipShape.parent=e,e.clipShape.updateTransform(),t?(t=t.slice(),t.push(e.clipShape)):t=[e.clipShape]),"group"==e.type){for(var i=0;i0},o.prototype.addRoot=function(e){this._elements[e.id]||(e instanceof n&&e.addChildrenToStorage(this),this.addToMap(e),this._roots.push(e))},o.prototype.delRoot=function(e){if("undefined"==typeof e){for(var t=0;tt;t++)this.delRoot(e[t]);else{var r;r="string"==typeof e?this._elements[e]:e;var s=i.indexOf(this._roots,r);s>=0&&(this.delFromMap(r.id),this._roots.splice(s,1),r instanceof n&&r.delChildrenFromStorage(this))}},o.prototype.addToMap=function(e){return e instanceof n&&(e._storage=this),e.modSelf(),this._elements[e.id]=e,this},o.prototype.get=function(e){return this._elements[e]},o.prototype.delFromMap=function(e){var t=this._elements[e];return t&&(delete this._elements[e],t instanceof n&&(t._storage=null)),this},o.prototype.dispose=function(){this._elements=this._renderList=this._roots=this._hoverElements=null},o}),i("zrender/animation/Animation",["require","./Clip","../tool/color","../tool/util","../tool/event"],function(e){"use strict";function t(e,t){return e[t]}function i(e,t,i){e[t]=i}function n(e,t,i){return(t-e)*i+e}function a(e,t,i,a,o){var r=e.length;if(1==o)for(var s=0;r>s;s++)a[s]=n(e[s],t[s],i);else for(var l=e[0].length,s=0;r>s;s++)for(var h=0;l>h;h++)a[s][h]=n(e[s][h],t[s][h],i)}function o(e){switch(typeof e){case"undefined":case"string":return!1}return"undefined"!=typeof e.length}function r(e,t,i,n,a,o,r,l,h){var m=e.length;if(1==h)for(var V=0;m>V;V++)l[V]=s(e[V],t[V],i[V],n[V],a,o,r);else for(var U=e[0].length,V=0;m>V;V++)for(var d=0;U>d;d++)l[V][d]=s(e[V][d],t[V][d],i[V][d],n[V][d],a,o,r)}function s(e,t,i,n,a,o,r){var s=.5*(i-e),l=.5*(n-t);return(2*(t-i)+s+l)*r+(-3*(t-i)-2*s-l)*o+s*a+t}function l(e){if(o(e)){var t=e.length;if(o(e[0])){for(var i=[],n=0;t>n;n++)i.push(c.call(e[n]));return i}return c.call(e)}return e}function h(e){return e[0]=Math.floor(e[0]),e[1]=Math.floor(e[1]),e[2]=Math.floor(e[2]),"rgba("+e.join(",")+")"}var m=e("./Clip"),V=e("../tool/color"),U=e("../tool/util"),d=e("../tool/event").Dispatcher,p=window.requestAnimationFrame||window.msRequestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||function(e){setTimeout(e,16)},c=Array.prototype.slice,u=function(e){e=e||{},this.stage=e.stage||{},this.onframe=e.onframe||function(){},this._clips=[],this._running=!1,this._time=0,d.call(this)};u.prototype={add:function(e){this._clips.push(e)},remove:function(e){if(e.__inStep)e.__needsRemove=!0;else{var t=U.indexOf(this._clips,e);t>=0&&this._clips.splice(t,1)}},_update:function(){for(var e=(new Date).getTime(),t=e-this._time,i=this._clips,n=i.length,a=[],o=[],r=0;n>r;r++){var s=i[r];s.__inStep=!0;var l=s.step(e);s.__inStep=!1,l&&(a.push(l),o.push(s))}for(var r=0;n>r;)i[r].__needsRemove?(i[r]=i[n-1],i.pop(),n--):r++;n=a.length;for(var r=0;n>r;r++)o[r].fire(a[r]);this._time=e,this.onframe(t),this.dispatch("frame",t),this.stage.update&&this.stage.update()},start:function(){function e(){t._running&&(p(e),t._update())}var t=this;this._running=!0,this._time=(new Date).getTime(),p(e)},stop:function(){this._running=!1},clear:function(){this._clips=[]},animate:function(e,t){t=t||{};var i=new y(e,t.loop,t.getter,t.setter);return i.animation=this,i},constructor:u},U.merge(u.prototype,d.prototype,!0);var y=function(e,n,a,o){this._tracks={},this._target=e,this._loop=n||!1,this._getter=a||t,this._setter=o||i,this._clipCount=0,this._delay=0,this._doneList=[],this._onframeList=[],this._clipList=[]};return y.prototype={when:function(e,t){for(var i in t)this._tracks[i]||(this._tracks[i]=[],0!==e&&this._tracks[i].push({time:0,value:l(this._getter(this._target,i))})),this._tracks[i].push({time:parseInt(e,10),value:t[i]});return this},during:function(e){return this._onframeList.push(e),this},start:function(e){var t=this,i=this._setter,l=this._getter,U="spline"===e,d=function(){if(t._clipCount--,0===t._clipCount){t._tracks={};for(var e=t._doneList.length,i=0;e>i;i++)t._doneList[i].call(t)}},p=function(p,c){var u=p.length;if(u){var y=p[0].value,g=o(y),b=!1,f=g&&o(y[0])?2:1;p.sort(function(e,t){return e.time-t.time});var k;if(u){k=p[u-1].time;for(var x=[],_=[],L=0;u>L;L++){x.push(p[L].time/k);var W=p[L].value;"string"==typeof W&&(W=V.toArray(W),0===W.length&&(W[0]=W[1]=W[2]=0,W[3]=1),b=!0),_.push(W)}var X,L,v,w,K,I,J,C=0,S=0;if(b)var E=[0,0,0,0];var F=function(e,o){if(S>o){for(X=Math.min(C+1,u-1),L=X;L>=0&&!(x[L]<=o);L--);L=Math.min(L,u-2)}else{for(L=C;u>L&&!(x[L]>o);L++);L=Math.min(L-1,u-2)}C=L,S=o;var m=x[L+1]-x[L];if(0!==m){if(v=(o-x[L])/m,U)if(K=_[L],w=_[0===L?L:L-1],I=_[L>u-2?u-1:L+1],J=_[L>u-3?u-1:L+2],g)r(w,K,I,J,v,v*v,v*v*v,l(e,c),f);else{var V;b?(V=r(w,K,I,J,v,v*v,v*v*v,E,1),V=h(E)):V=s(w,K,I,J,v,v*v,v*v*v),i(e,c,V)}else if(g)a(_[L],_[L+1],v,l(e,c),f);else{var V;b?(a(_[L],_[L+1],v,E,1),V=h(E)):V=n(_[L],_[L+1],v),i(e,c,V)}for(L=0;L=t[1]&&(e=t[1]),e},t.prototype.getLocation=function(e,t,i){var n=null!=e.x?e.x:"center";switch(n){case"center":n=Math.floor((this.canvasWidth-t)/2);break;case"left":n=0;break;case"right":n=this.canvasWidth-t}var a=null!=e.y?e.y:"center";switch(a){case"center":a=Math.floor((this.canvasHeight-i)/2);break;case"top":a=0;break;case"bottom":a=this.canvasHeight-i}return{x:n,y:a,width:t,height:i}},t}),i("zrender/Layer",["require","./mixin/Transformable","./tool/util","./config"],function(e){function t(){return!1}function i(e,t,i){var n=document.createElement(t),a=i.getWidth(),o=i.getHeight();return n.style.position="absolute",n.style.left=0,n.style.top=0,n.style.width=a+"px",n.style.height=o+"px",n.width=a*r.devicePixelRatio,n.height=o*r.devicePixelRatio,n.setAttribute("data-zr-dom-id",e),n}var n=e("./mixin/Transformable"),a=e("./tool/util"),o=window.G_vmlCanvasManager,r=e("./config"),s=function(e,a){this.id=e,this.dom=i(e,"canvas",a),this.dom.onselectstart=t,this.dom.style["-webkit-user-select"]="none",this.dom.style["user-select"]="none",this.dom.style["-webkit-touch-callout"]="none",this.dom.style["-webkit-tap-highlight-color"]="rgba(0,0,0,0)",this.dom.className=r.elementClassName,o&&o.initElement(this.dom),this.domBack=null,this.ctxBack=null,this.painter=a,this.unusedCount=0,this.config=null,this.dirty=!0,this.elCount=0,this.clearColor=0,this.motionBlur=!1,this.lastFrameAlpha=.7,this.zoomable=!1,this.panable=!1,this.maxZoom=1/0,this.minZoom=0,n.call(this)};return s.prototype.initContext=function(){this.ctx=this.dom.getContext("2d");var e=r.devicePixelRatio;1!=e&&this.ctx.scale(e,e)},s.prototype.createBackBuffer=function(){if(!o){this.domBack=i("back-"+this.id,"canvas",this.painter),this.ctxBack=this.domBack.getContext("2d");var e=r.devicePixelRatio;1!=e&&this.ctxBack.scale(e,e)}},s.prototype.resize=function(e,t){var i=r.devicePixelRatio;this.dom.style.width=e+"px",this.dom.style.height=t+"px",this.dom.setAttribute("width",e*i),this.dom.setAttribute("height",t*i),1!=i&&this.ctx.scale(i,i),this.domBack&&(this.domBack.setAttribute("width",e*i),this.domBack.setAttribute("height",t*i),1!=i&&this.ctxBack.scale(i,i))},s.prototype.clear=function(){var e=this.dom,t=this.ctx,i=e.width,n=e.height,a=this.clearColor&&!o,s=this.motionBlur&&!o,l=this.lastFrameAlpha,h=r.devicePixelRatio;if(s&&(this.domBack||this.createBackBuffer(),this.ctxBack.globalCompositeOperation="copy",this.ctxBack.drawImage(e,0,0,i/h,n/h)),t.clearRect(0,0,i/h,n/h),a&&(t.save(),t.fillStyle=this.clearColor,t.fillRect(0,0,i/h,n/h),t.restore()),s){var m=this.domBack;t.save(),t.globalAlpha=l,t.drawImage(m,0,0,i/h,n/h),t.restore()}},a.merge(s.prototype,n.prototype),s}),i("zrender/shape/Text",["require","../tool/area","./Base","../tool/util"],function(e){ -var t=e("../tool/area"),i=e("./Base"),n=function(e){i.call(this,e)};return n.prototype={type:"text",brush:function(e,i){var n=this.style;if(i&&(n=this.getHighlightStyle(n,this.highlightStyle||{})),"undefined"!=typeof n.text&&n.text!==!1){e.save(),this.doClip(e),this.setContext(e,n),this.setTransform(e),n.textFont&&(e.font=n.textFont),e.textAlign=n.textAlign||"start",e.textBaseline=n.textBaseline||"middle";var a,o=(n.text+"").split("\n"),r=t.getTextHeight("国",n.textFont),s=this.getRect(n),l=n.x;a="top"==n.textBaseline?s.y:"bottom"==n.textBaseline?s.y+r:s.y+r/2;for(var h=0,m=o.length;m>h;h++){if(n.maxWidth)switch(n.brushType){case"fill":e.fillText(o[h],l,a,n.maxWidth);break;case"stroke":e.strokeText(o[h],l,a,n.maxWidth);break;case"both":e.fillText(o[h],l,a,n.maxWidth),e.strokeText(o[h],l,a,n.maxWidth);break;default:e.fillText(o[h],l,a,n.maxWidth)}else switch(n.brushType){case"fill":e.fillText(o[h],l,a);break;case"stroke":e.strokeText(o[h],l,a);break;case"both":e.fillText(o[h],l,a),e.strokeText(o[h],l,a);break;default:e.fillText(o[h],l,a)}a+=r}e.restore()}},getRect:function(e){if(e.__rect)return e.__rect;var i=t.getTextWidth(e.text,e.textFont),n=t.getTextHeight(e.text,e.textFont),a=e.x;"end"==e.textAlign||"right"==e.textAlign?a-=i:"center"==e.textAlign&&(a-=i/2);var o;return o="top"==e.textBaseline?e.y:"bottom"==e.textBaseline?e.y-n:e.y-n/2,e.__rect={x:a,y:o,width:i,height:n},e.__rect}},e("../tool/util").inherits(n,i),n}),i("zrender/shape/Rectangle",["require","./Base","../tool/util"],function(e){var t=e("./Base"),i=function(e){t.call(this,e)};return i.prototype={type:"rectangle",_buildRadiusPath:function(e,t){var i,n,a,o,r=t.x,s=t.y,l=t.width,h=t.height,m=t.radius;"number"==typeof m?i=n=a=o=m:m instanceof Array?1===m.length?i=n=a=o=m[0]:2===m.length?(i=a=m[0],n=o=m[1]):3===m.length?(i=m[0],n=o=m[1],a=m[2]):(i=m[0],n=m[1],a=m[2],o=m[3]):i=n=a=o=0;var V;i+n>l&&(V=i+n,i*=l/V,n*=l/V),a+o>l&&(V=a+o,a*=l/V,o*=l/V),n+a>h&&(V=n+a,n*=h/V,a*=h/V),i+o>h&&(V=i+o,i*=h/V,o*=h/V),e.moveTo(r+i,s),e.lineTo(r+l-n,s),0!==n&&e.quadraticCurveTo(r+l,s,r+l,s+n),e.lineTo(r+l,s+h-a),0!==a&&e.quadraticCurveTo(r+l,s+h,r+l-a,s+h),e.lineTo(r+o,s+h),0!==o&&e.quadraticCurveTo(r,s+h,r,s+h-o),e.lineTo(r,s+i),0!==i&&e.quadraticCurveTo(r,s,r+i,s)},buildPath:function(e,t){t.radius?this._buildRadiusPath(e,t):(e.moveTo(t.x,t.y),e.lineTo(t.x+t.width,t.y),e.lineTo(t.x+t.width,t.y+t.height),e.lineTo(t.x,t.y+t.height),e.lineTo(t.x,t.y)),e.closePath()},getRect:function(e){if(e.__rect)return e.__rect;var t;return t="stroke"==e.brushType||"fill"==e.brushType?e.lineWidth||1:0,e.__rect={x:Math.round(e.x-t/2),y:Math.round(e.y-t/2),width:e.width+t,height:e.height+t},e.__rect}},e("../tool/util").inherits(i,t),i}),i("zrender/tool/area",["require","./util","./curve"],function(e){"use strict";function t(e){return e%=C,0>e&&(e+=C),e}function i(e,t,i,o){if(!t||!e)return!1;var r=e.type;L=L||W.getContext();var s=n(e,t,i,o);if("undefined"!=typeof s)return s;if(e.buildPath&&L.isPointInPath)return a(e,L,t,i,o);switch(r){case"ellipse":return!0;case"trochoid":var l="out"==t.location?t.r1+t.r2+t.d:t.r1-t.r2+t.d;return d(t,i,o,l);case"rose":return d(t,i,o,t.maxr);default:return!1}}function n(e,t,i,n){var a=e.type;switch(a){case"bezier-curve":return"undefined"==typeof t.cpX2?l(t.xStart,t.yStart,t.cpX1,t.cpY1,t.xEnd,t.yEnd,t.lineWidth,i,n):s(t.xStart,t.yStart,t.cpX1,t.cpY1,t.cpX2,t.cpY2,t.xEnd,t.yEnd,t.lineWidth,i,n);case"line":return r(t.xStart,t.yStart,t.xEnd,t.yEnd,t.lineWidth,i,n);case"polyline":return m(t.pointList,t.lineWidth,i,n);case"ring":return V(t.x,t.y,t.r0,t.r,i,n);case"circle":return d(t.x,t.y,t.r,i,n);case"sector":var o=t.startAngle*Math.PI/180,h=t.endAngle*Math.PI/180;return t.clockWise||(o=-o,h=-h),p(t.x,t.y,t.r0,t.r,o,h,!t.clockWise,i,n);case"path":return t.pathArray&&k(t.pathArray,Math.max(t.lineWidth,5),t.brushType,i,n);case"polygon":case"star":case"isogon":return c(t.pointList,i,n);case"text":var u=t.__rect||e.getRect(t);return U(u.x,u.y,u.width,u.height,i,n);case"rectangle":case"image":return U(t.x,t.y,t.width,t.height,i,n)}}function a(e,t,i,n,a){return t.beginPath(),e.buildPath(t,i),t.closePath(),t.isPointInPath(n,a)}function o(e,t,n,a){return!i(e,t,n,a)}function r(e,t,i,n,a,o,r){if(0===a)return!1;var s=Math.max(a,5),l=0,h=e;if(r>t+s&&r>n+s||t-s>r&&n-s>r||o>e+s&&o>i+s||e-s>o&&i-s>o)return!1;if(e===i)return Math.abs(o-e)<=s/2;l=(t-n)/(e-i),h=(e*n-i*t)/(e-i);var m=l*o-r+h,V=m*m/(l*l+1);return s/2*s/2>=V}function s(e,t,i,n,a,o,r,s,l,h,m){if(0===l)return!1;var V=Math.max(l,5);if(m>t+V&&m>n+V&&m>o+V&&m>s+V||t-V>m&&n-V>m&&o-V>m&&s-V>m||h>e+V&&h>i+V&&h>a+V&&h>r+V||e-V>h&&i-V>h&&a-V>h&&r-V>h)return!1;var U=X.cubicProjectPoint(e,t,i,n,a,o,r,s,h,m,null);return V/2>=U}function l(e,t,i,n,a,o,r,s,l){if(0===r)return!1;var h=Math.max(r,5);if(l>t+h&&l>n+h&&l>o+h||t-h>l&&n-h>l&&o-h>l||s>e+h&&s>i+h&&s>a+h||e-h>s&&i-h>s&&a-h>s)return!1;var m=X.quadraticProjectPoint(e,t,i,n,a,o,s,l,null);return h/2>=m}function h(e,i,n,a,o,r,s,l,h){if(0===s)return!1;var m=Math.max(s,5);l-=e,h-=i;var V=Math.sqrt(l*l+h*h);if(V-m>n||n>V+m)return!1;if(Math.abs(a-o)>=C)return!0;if(r){var U=a;a=t(o),o=t(U)}else a=t(a),o=t(o);a>o&&(o+=C);var d=Math.atan2(h,l);return 0>d&&(d+=C),d>=a&&o>=d||d+C>=a&&o>=d+C}function m(e,t,i,n){for(var t=Math.max(t,10),a=0,o=e.length-1;o>a;a++){var s=e[a][0],l=e[a][1],h=e[a+1][0],m=e[a+1][1];if(r(s,l,h,m,t,i,n))return!0}return!1}function V(e,t,i,n,a,o){var r=(a-e)*(a-e)+(o-t)*(o-t);return n*n>r&&r>i*i}function U(e,t,i,n,a,o){return a>=e&&e+i>=a&&o>=t&&t+n>=o}function d(e,t,i,n,a){return i*i>(n-e)*(n-e)+(a-t)*(a-t)}function p(e,t,i,n,a,o,r,s,l){return h(e,t,(i+n)/2,a,o,r,n-i,s,l)}function c(e,t,i){for(var n=e.length,a=0,o=0,r=n-1;n>o;o++){var s=e[r][0],l=e[r][1],h=e[o][0],m=e[o][1];a+=u(s,l,h,m,t,i),r=o}return 0!==a}function u(e,t,i,n,a,o){if(o>t&&o>n||t>o&&n>o)return 0;if(n==t)return 0;var r=t>n?1:-1,s=(o-t)/(n-t),l=s*(i-e)+e;return l>a?r:0}function y(){var e=E[0];E[0]=E[1],E[1]=e}function g(e,t,i,n,a,o,r,s,l,h){if(h>t&&h>n&&h>o&&h>s||t>h&&n>h&&o>h&&s>h)return 0;var m=X.cubicRootAt(t,n,o,s,h,S);if(0===m)return 0;for(var V,U,d=0,p=-1,c=0;m>c;c++){var u=S[c],g=X.cubicAt(e,i,a,r,u);l>g||(0>p&&(p=X.cubicExtrema(t,n,o,s,E),E[1]1&&y(),V=X.cubicAt(t,n,o,s,E[0]),p>1&&(U=X.cubicAt(t,n,o,s,E[1]))),d+=2==p?uV?1:-1:uU?1:-1:U>s?1:-1:uV?1:-1:V>s?1:-1)}return d}function b(e,t,i,n,a,o,r,s){if(s>t&&s>n&&s>o||t>s&&n>s&&o>s)return 0;var l=X.quadraticRootAt(t,n,o,s,S);if(0===l)return 0;var h=X.quadraticExtremum(t,n,o);if(h>=0&&1>=h){for(var m=0,V=X.quadraticAt(t,n,o,h),U=0;l>U;U++){var d=X.quadraticAt(e,i,a,S[U]);r>d||(m+=S[U]V?1:-1:V>o?1:-1)}return m}var d=X.quadraticAt(e,i,a,S[0]);return r>d?0:t>o?1:-1}function f(e,i,n,a,o,r,s,l){if(l-=i,l>n||-n>l)return 0;var h=Math.sqrt(n*n-l*l);if(S[0]=-h,S[1]=h,Math.abs(a-o)>=C){a=0,o=C;var m=r?1:-1;return s>=S[0]+e&&s<=S[1]+e?m:0}if(r){var h=a;a=t(o),o=t(h)}else a=t(a),o=t(o);a>o&&(o+=C);for(var V=0,U=0;2>U;U++){var d=S[U];if(d+e>s){var p=Math.atan2(l,d),m=r?1:-1;0>p&&(p=C+p),(p>=a&&o>=p||p+C>=a&&o>=p+C)&&(p>Math.PI/2&&p<1.5*Math.PI&&(m=-m),V+=m)}}return V}function k(e,t,i,n,a){var o=0,m=0,V=0,U=0,d=0,p=!0,c=!0;i=i||"fill";for(var y="stroke"===i||"both"===i,k="fill"===i||"both"===i,x=0;x0&&(k&&(o+=u(m,V,U,d,n,a)),0!==o))return!0;U=L[L.length-2],d=L[L.length-1],p=!1,c&&"A"!==_.command&&(c=!1,m=U,V=d)}switch(_.command){case"M":m=L[0],V=L[1];break;case"L":if(y&&r(m,V,L[0],L[1],t,n,a))return!0;k&&(o+=u(m,V,L[0],L[1],n,a)),m=L[0],V=L[1];break;case"C":if(y&&s(m,V,L[0],L[1],L[2],L[3],L[4],L[5],t,n,a))return!0;k&&(o+=g(m,V,L[0],L[1],L[2],L[3],L[4],L[5],n,a)),m=L[4],V=L[5];break;case"Q":if(y&&l(m,V,L[0],L[1],L[2],L[3],t,n,a))return!0;k&&(o+=b(m,V,L[0],L[1],L[2],L[3],n,a)),m=L[2],V=L[3];break;case"A":var W=L[0],X=L[1],v=L[2],w=L[3],K=L[4],I=L[5],J=Math.cos(K)*v+W,C=Math.sin(K)*w+X;c?(c=!1,U=J,d=C):o+=u(m,V,J,C);var S=(n-W)*w/v+W;if(y&&h(W,X,w,K,K+I,1-L[7],t,S,a))return!0;k&&(o+=f(W,X,w,K,K+I,1-L[7],S,a)),m=Math.cos(K+I)*v+W,V=Math.sin(K+I)*w+X;break;case"z":if(y&&r(m,V,U,d,t,n,a))return!0;p=!0}}return k&&(o+=u(m,V,U,d,n,a)),0!==o}function x(e,t){var i=e+":"+t;if(v[i])return v[i];L=L||W.getContext(),L.save(),t&&(L.font=t),e=(e+"").split("\n");for(var n=0,a=0,o=e.length;o>a;a++)n=Math.max(L.measureText(e[a]).width,n);return L.restore(),v[i]=n,++K>J&&(K=0,v={}),n}function _(e,t){var i=e+":"+t;if(w[i])return w[i];L=L||W.getContext(),L.save(),t&&(L.font=t),e=(e+"").split("\n");var n=(L.measureText("国").width+2)*e.length;return L.restore(),w[i]=n,++I>J&&(I=0,w={}),n}var L,W=e("./util"),X=e("./curve"),v={},w={},K=0,I=0,J=5e3,C=2*Math.PI,S=[-1,-1,-1],E=[-1,-1];return{isInside:i,isOutside:o,getTextWidth:x,getTextHeight:_,isInsidePath:k,isInsidePolygon:c,isInsideSector:p,isInsideCircle:d,isInsideLine:r,isInsideRect:U,isInsidePolyline:m,isInsideCubicStroke:s,isInsideQuadraticStroke:l}}),i("zrender/shape/Base",["require","../tool/matrix","../tool/guid","../tool/util","../tool/log","../mixin/Transformable","../mixin/Eventful","../tool/area","../tool/color"],function(e){function t(t,n,a,o,r,s,l){r&&(t.font=r),t.textAlign=s,t.textBaseline=l;var h=i(n,a,o,r,s,l);n=(n+"").split("\n");var m=e("../tool/area").getTextHeight("国",r);switch(l){case"top":o=h.y;break;case"bottom":o=h.y+m;break;default:o=h.y+m/2}for(var V=0,U=n.length;U>V;V++)t.fillText(n[V],a,o),o+=m}function i(t,i,n,a,o,r){var s=e("../tool/area"),l=s.getTextWidth(t,a),h=s.getTextHeight("国",a);switch(t=(t+"").split("\n"),o){case"end":case"right":i-=l;break;case"center":i-=l/2}switch(r){case"top":break;case"bottom":n-=h*t.length;break;default:n-=h*t.length/2}return{x:i,y:n,width:l,height:h*t.length}}var n=window.G_vmlCanvasManager,a=e("../tool/matrix"),o=e("../tool/guid"),r=e("../tool/util"),s=e("../tool/log"),l=e("../mixin/Transformable"),h=e("../mixin/Eventful"),m=function(e){e=e||{},this.id=e.id||o();for(var t in e)this[t]=e[t];this.style=this.style||{},this.highlightStyle=this.highlightStyle||null,this.parent=null,this.__dirty=!0,this.__clipShapes=[],l.call(this),h.call(this)};m.prototype.invisible=!1,m.prototype.ignore=!1,m.prototype.zlevel=0,m.prototype.draggable=!1,m.prototype.clickable=!1,m.prototype.hoverable=!0,m.prototype.z=0,m.prototype.brush=function(e,t){var i=this.beforeBrush(e,t);switch(e.beginPath(),this.buildPath(e,i),i.brushType){case"both":e.fill();case"stroke":i.lineWidth>0&&e.stroke();break;default:e.fill()}this.drawText(e,i,this.style),this.afterBrush(e)},m.prototype.beforeBrush=function(e,t){var i=this.style;return this.brushTypeOnly&&(i.brushType=this.brushTypeOnly),t&&(i=this.getHighlightStyle(i,this.highlightStyle||{},this.brushTypeOnly)),"stroke"==this.brushTypeOnly&&(i.strokeColor=i.strokeColor||i.color),e.save(),this.doClip(e),this.setContext(e,i),this.setTransform(e),i},m.prototype.afterBrush=function(e){e.restore()};var V=[["color","fillStyle"],["strokeColor","strokeStyle"],["opacity","globalAlpha"],["lineCap","lineCap"],["lineJoin","lineJoin"],["miterLimit","miterLimit"],["lineWidth","lineWidth"],["shadowBlur","shadowBlur"],["shadowColor","shadowColor"],["shadowOffsetX","shadowOffsetX"],["shadowOffsetY","shadowOffsetY"]];m.prototype.setContext=function(e,t){for(var i=0,n=V.length;n>i;i++){var a=V[i][0],o=t[a],r=V[i][1];"undefined"!=typeof o&&(e[r]=o)}};var U=a.create();return m.prototype.doClip=function(e){if(this.__clipShapes&&!n)for(var t=0;t=i.x&&e<=i.x+i.width&&t>=i.y&&t<=i.y+i.height},m.prototype.drawText=function(e,i,n){if("undefined"!=typeof i.text&&i.text!==!1){var a=i.textColor||i.color||i.strokeColor;e.fillStyle=a;var o,r,s,l,h=10,m=i.textPosition||this.textPosition||"top";switch(m){case"inside":case"top":case"bottom":case"left":case"right":if(this.getRect){var V=(n||i).__rect||this.getRect(n||i);switch(m){case"inside":s=V.x+V.width/2,l=V.y+V.height/2,o="center",r="middle","stroke"!=i.brushType&&a==i.color&&(e.fillStyle="#fff");break;case"left":s=V.x-h,l=V.y+V.height/2,o="end",r="middle";break;case"right":s=V.x+V.width+h,l=V.y+V.height/2,o="start",r="middle";break;case"top":s=V.x+V.width/2,l=V.y-h,o="center",r="bottom";break;case"bottom":s=V.x+V.width/2,l=V.y+V.height+h,o="center",r="top"}}break;case"start":case"end":var U=i.pointList||[[i.xStart||0,i.yStart||0],[i.xEnd||0,i.yEnd||0]],d=U.length;if(2>d)return;var p,c,u,y;switch(m){case"start":p=U[1][0],c=U[0][0],u=U[1][1],y=U[0][1];break;case"end":p=U[d-2][0],c=U[d-1][0],u=U[d-2][1],y=U[d-1][1]}s=c,l=y;var g=Math.atan((u-y)/(c-p))/Math.PI*180;0>c-p?g+=180:0>u-y&&(g+=360),h=5,g>=30&&150>=g?(o="center",r="bottom",l-=h):g>150&&210>g?(o="right",r="middle",s-=h):g>=210&&330>=g?(o="center",r="top",l+=h):(o="left",r="middle",s+=h);break;case"specific":s=i.textX||0,l=i.textY||0,o="start",r="middle"}null!=s&&null!=l&&t(e,i.text,s,l,i.textFont,i.textAlign||o,i.textBaseline||r)}},m.prototype.modSelf=function(){this.__dirty=!0,this.style&&(this.style.__rect=null),this.highlightStyle&&(this.highlightStyle.__rect=null)},m.prototype.isSilent=function(){return!(this.hoverable||this.draggable||this.clickable||this.onmousemove||this.onmouseover||this.onmouseout||this.onmousedown||this.onmouseup||this.onclick||this.ondragenter||this.ondragover||this.ondragleave||this.ondrop)},r.merge(m.prototype,l.prototype,!0),r.merge(m.prototype,h.prototype,!0),m}),i("zrender/tool/curve",["require","./vector"],function(e){function t(e){return e>-u&&u>e}function i(e){return e>u||-u>e}function n(e,t,i,n,a){var o=1-a;return o*o*(o*e+3*a*t)+a*a*(a*n+3*o*i)}function a(e,t,i,n,a){var o=1-a;return 3*(((t-e)*o+2*(i-t)*a)*o+(n-i)*a*a)}function o(e,i,n,a,o,r){var s=a+3*(i-n)-e,l=3*(n-2*i+e),h=3*(i-e),m=e-o,V=l*l-3*s*h,U=l*h-9*s*m,d=h*h-3*l*m,p=0;if(t(V)&&t(U))if(t(l))r[0]=0;else{var c=-h/l;c>=0&&1>=c&&(r[p++]=c)}else{var u=U*U-4*V*d;if(t(u)){var b=U/V,c=-l/s+b,f=-b/2;c>=0&&1>=c&&(r[p++]=c),f>=0&&1>=f&&(r[p++]=f)}else if(u>0){var k=Math.sqrt(u),x=V*l+1.5*s*(-U+k),_=V*l+1.5*s*(-U-k);x=0>x?-Math.pow(-x,g):Math.pow(x,g),_=0>_?-Math.pow(-_,g):Math.pow(_,g);var c=(-l-(x+_))/(3*s);c>=0&&1>=c&&(r[p++]=c)}else{var L=(2*V*l-3*s*U)/(2*Math.sqrt(V*V*V)),W=Math.acos(L)/3,X=Math.sqrt(V),v=Math.cos(W),c=(-l-2*X*v)/(3*s),f=(-l+X*(v+y*Math.sin(W)))/(3*s),w=(-l+X*(v-y*Math.sin(W)))/(3*s);c>=0&&1>=c&&(r[p++]=c),f>=0&&1>=f&&(r[p++]=f),w>=0&&1>=w&&(r[p++]=w)}}return p}function r(e,n,a,o,r){var s=6*a-12*n+6*e,l=9*n+3*o-3*e-9*a,h=3*n-3*e,m=0;if(t(l)){if(i(s)){var V=-h/s;V>=0&&1>=V&&(r[m++]=V)}}else{var U=s*s-4*l*h;if(t(U))r[0]=-s/(2*l);else if(U>0){var d=Math.sqrt(U),V=(-s+d)/(2*l),p=(-s-d)/(2*l);V>=0&&1>=V&&(r[m++]=V),p>=0&&1>=p&&(r[m++]=p)}}return m}function s(e,t,i,n,a,o){var r=(t-e)*a+e,s=(i-t)*a+t,l=(n-i)*a+i,h=(s-r)*a+r,m=(l-s)*a+s,V=(m-h)*a+h;o[0]=e,o[1]=r,o[2]=h,o[3]=V,o[4]=V,o[5]=m,o[6]=l,o[7]=n}function l(e,t,i,a,o,r,s,l,h,m,V){var U,d=.005,p=1/0;b[0]=h,b[1]=m;for(var y=0;1>y;y+=.05){f[0]=n(e,i,o,s,y),f[1]=n(t,a,r,l,y);var g=c.distSquare(b,f);p>g&&(U=y,p=g)}p=1/0;for(var x=0;32>x&&!(u>d);x++){var _=U-d,L=U+d;f[0]=n(e,i,o,s,_),f[1]=n(t,a,r,l,_);var g=c.distSquare(f,b);if(_>=0&&p>g)U=_,p=g;else{k[0]=n(e,i,o,s,L),k[1]=n(t,a,r,l,L);var W=c.distSquare(k,b);1>=L&&p>W?(U=L,p=W):d*=.5}}return V&&(V[0]=n(e,i,o,s,U),V[1]=n(t,a,r,l,U)),Math.sqrt(p)}function h(e,t,i,n){var a=1-n;return a*(a*e+2*n*t)+n*n*i}function m(e,t,i,n){return 2*((1-n)*(t-e)+n*(i-t))}function V(e,n,a,o,r){var s=e-2*n+a,l=2*(n-e),h=e-o,m=0;if(t(s)){if(i(l)){var V=-h/l;V>=0&&1>=V&&(r[m++]=V)}}else{var U=l*l-4*s*h;if(t(U)){var V=-l/(2*s);V>=0&&1>=V&&(r[m++]=V)}else if(U>0){var d=Math.sqrt(U),V=(-l+d)/(2*s),p=(-l-d)/(2*s);V>=0&&1>=V&&(r[m++]=V),p>=0&&1>=p&&(r[m++]=p)}}return m}function U(e,t,i){var n=e+i-2*t;return 0===n?.5:(e-t)/n}function d(e,t,i,n,a){var o=(t-e)*n+e,r=(i-t)*n+t,s=(r-o)*n+o;a[0]=e,a[1]=o,a[2]=s,a[3]=s,a[4]=r,a[5]=i}function p(e,t,i,n,a,o,r,s,l){var m,V=.005,U=1/0;b[0]=r,b[1]=s;for(var d=0;1>d;d+=.05){f[0]=h(e,i,a,d),f[1]=h(t,n,o,d);var p=c.distSquare(b,f);U>p&&(m=d,U=p)}U=1/0;for(var y=0;32>y&&!(u>V);y++){var g=m-V,x=m+V;f[0]=h(e,i,a,g),f[1]=h(t,n,o,g);var p=c.distSquare(f,b);if(g>=0&&U>p)m=g,U=p;else{k[0]=h(e,i,a,x),k[1]=h(t,n,o,x);var _=c.distSquare(k,b);1>=x&&U>_?(m=x,U=_):V*=.5}}return l&&(l[0]=h(e,i,a,m),l[1]=h(t,n,o,m)),Math.sqrt(U)}var c=e("./vector"),u=1e-4,y=Math.sqrt(3),g=1/3,b=c.create(),f=c.create(),k=c.create();return{cubicAt:n,cubicDerivativeAt:a,cubicRootAt:o,cubicExtrema:r,cubicSubdivide:s,cubicProjectPoint:l,quadraticAt:h,quadraticDerivativeAt:m,quadraticRootAt:V,quadraticExtremum:U,quadraticSubdivide:d,quadraticProjectPoint:p}}),i("zrender/mixin/Transformable",["require","../tool/matrix","../tool/vector"],function(e){"use strict";function t(e){return e>-s&&s>e}function i(e){return e>s||-s>e}var n=e("../tool/matrix"),a=e("../tool/vector"),o=[0,0],r=n.translate,s=5e-5,l=function(){this.position||(this.position=[0,0]),"undefined"==typeof this.rotation&&(this.rotation=[0,0,0]),this.scale||(this.scale=[1,1,0,0]),this.needLocalTransform=!1,this.needTransform=!1};return l.prototype={constructor:l,updateNeedTransform:function(){this.needLocalTransform=i(this.rotation[0])||i(this.position[0])||i(this.position[1])||i(this.scale[0]-1)||i(this.scale[1]-1)},updateTransform:function(){this.updateNeedTransform();var e=this.parent&&this.parent.needTransform;if(this.needTransform=this.needLocalTransform||e,this.needTransform){var t=this.transform||n.create();if(n.identity(t),this.needLocalTransform){var a=this.scale;if(i(a[0])||i(a[1])){o[0]=-a[2]||0,o[1]=-a[3]||0;var s=i(o[0])||i(o[1]);s&&r(t,t,o),n.scale(t,t,a),s&&(o[0]=-o[0],o[1]=-o[1],r(t,t,o))}if(this.rotation instanceof Array){if(0!==this.rotation[0]){o[0]=-this.rotation[1]||0,o[1]=-this.rotation[2]||0;var s=i(o[0])||i(o[1]);s&&r(t,t,o),n.rotate(t,t,this.rotation[0]),s&&(o[0]=-o[0],o[1]=-o[1],r(t,t,o))}}else 0!==this.rotation&&n.rotate(t,t,this.rotation);(i(this.position[0])||i(this.position[1]))&&r(t,t,this.position)}e&&(this.needLocalTransform?n.mul(t,this.parent.transform,t):n.copy(t,this.parent.transform)),this.transform=t,this.invTransform=this.invTransform||n.create(),n.invert(this.invTransform,t)}},setTransform:function(e){if(this.needTransform){var t=this.transform;e.transform(t[0],t[1],t[2],t[3],t[4],t[5])}},lookAt:function(){var e=a.create();return function(i){this.transform||(this.transform=n.create());var o=this.transform;if(a.sub(e,i,this.position),!t(e[0])||!t(e[1])){a.normalize(e,e);var r=this.scale;o[2]=e[0]*r[1],o[3]=e[1]*r[1],o[0]=e[1]*r[0],o[1]=-e[0]*r[0],o[4]=this.position[0],o[5]=this.position[1],this.decomposeTransform()}}}(),decomposeTransform:function(){if(this.transform){var e=this.transform,t=e[0]*e[0]+e[1]*e[1],n=this.position,a=this.scale,o=this.rotation;i(t-1)&&(t=Math.sqrt(t));var r=e[2]*e[2]+e[3]*e[3];i(r-1)&&(r=Math.sqrt(r)),n[0]=e[4],n[1]=e[5],a[0]=t,a[1]=r,a[2]=a[3]=0,o[0]=Math.atan2(-e[1]/r,e[0]/t),o[1]=o[2]=0}},transformCoordToLocal:function(e,t){var i=[e,t];return this.needTransform&&this.invTransform&&a.applyTransform(i,i,this.invTransform),i}},l}),i("zrender/Group",["require","./tool/guid","./tool/util","./mixin/Transformable","./mixin/Eventful"],function(e){var t=e("./tool/guid"),i=e("./tool/util"),n=e("./mixin/Transformable"),a=e("./mixin/Eventful"),o=function(e){e=e||{},this.id=e.id||t();for(var i in e)this[i]=e[i];this.type="group",this.clipShape=null,this._children=[],this._storage=null,this.__dirty=!0,n.call(this),a.call(this)};return o.prototype.ignore=!1,o.prototype.children=function(){return this._children.slice()},o.prototype.childAt=function(e){return this._children[e]},o.prototype.addChild=function(e){e!=this&&e.parent!=this&&(e.parent&&e.parent.removeChild(e),this._children.push(e),e.parent=this,this._storage&&this._storage!==e._storage&&(this._storage.addToMap(e),e instanceof o&&e.addChildrenToStorage(this._storage)))},o.prototype.removeChild=function(e){var t=i.indexOf(this._children,e);t>=0&&this._children.splice(t,1),e.parent=null,this._storage&&(this._storage.delFromMap(e.id),e instanceof o&&e.delChildrenFromStorage(this._storage))},o.prototype.clearChildren=function(){for(var e=0;et)){t=Math.min(t,1);var n="string"==typeof this.easing?i[this.easing]:this.easing,a="function"==typeof n?n(t):t;return this.fire("frame",a),1==t?this.loop?(this.restart(),"restart"):(this.__needsRemove=!0,"destroy"):null}},restart:function(){var e=(new Date).getTime(),t=(e-this._startTime)%this._life;this._startTime=(new Date).getTime()-t+this.gap,this.__needsRemove=!1},fire:function(e,t){for(var i=0,n=this._targetPool.length;n>i;i++)this["on"+e]&&this["on"+e](this._targetPool[i],t)},constructor:t},t}),i("zrender/animation/easing",[],function(){var e={Linear:function(e){return e},QuadraticIn:function(e){return e*e},QuadraticOut:function(e){return e*(2-e)},QuadraticInOut:function(e){return(e*=2)<1?.5*e*e:-.5*(--e*(e-2)-1)},CubicIn:function(e){return e*e*e},CubicOut:function(e){return--e*e*e+1},CubicInOut:function(e){return(e*=2)<1?.5*e*e*e:.5*((e-=2)*e*e+2)},QuarticIn:function(e){return e*e*e*e},QuarticOut:function(e){return 1- --e*e*e*e},QuarticInOut:function(e){return(e*=2)<1?.5*e*e*e*e:-.5*((e-=2)*e*e*e-2)},QuinticIn:function(e){return e*e*e*e*e},QuinticOut:function(e){return--e*e*e*e*e+1},QuinticInOut:function(e){return(e*=2)<1?.5*e*e*e*e*e:.5*((e-=2)*e*e*e*e+2)},SinusoidalIn:function(e){return 1-Math.cos(e*Math.PI/2)},SinusoidalOut:function(e){return Math.sin(e*Math.PI/2)},SinusoidalInOut:function(e){return.5*(1-Math.cos(Math.PI*e))},ExponentialIn:function(e){return 0===e?0:Math.pow(1024,e-1)},ExponentialOut:function(e){return 1===e?1:1-Math.pow(2,-10*e)},ExponentialInOut:function(e){return 0===e?0:1===e?1:(e*=2)<1?.5*Math.pow(1024,e-1):.5*(-Math.pow(2,-10*(e-1))+2)},CircularIn:function(e){return 1-Math.sqrt(1-e*e)},CircularOut:function(e){return Math.sqrt(1- --e*e)},CircularInOut:function(e){return(e*=2)<1?-.5*(Math.sqrt(1-e*e)-1):.5*(Math.sqrt(1-(e-=2)*e)+1)},ElasticIn:function(e){var t,i=.1,n=.4;return 0===e?0:1===e?1:(!i||1>i?(i=1,t=n/4):t=n*Math.asin(1/i)/(2*Math.PI),-(i*Math.pow(2,10*(e-=1))*Math.sin(2*(e-t)*Math.PI/n)))},ElasticOut:function(e){var t,i=.1,n=.4;return 0===e?0:1===e?1:(!i||1>i?(i=1,t=n/4):t=n*Math.asin(1/i)/(2*Math.PI),i*Math.pow(2,-10*e)*Math.sin(2*(e-t)*Math.PI/n)+1)},ElasticInOut:function(e){var t,i=.1,n=.4;return 0===e?0:1===e?1:(!i||1>i?(i=1,t=n/4):t=n*Math.asin(1/i)/(2*Math.PI),(e*=2)<1?-.5*i*Math.pow(2,10*(e-=1))*Math.sin(2*(e-t)*Math.PI/n):i*Math.pow(2,-10*(e-=1))*Math.sin(2*(e-t)*Math.PI/n)*.5+1)},BackIn:function(e){var t=1.70158;return e*e*((t+1)*e-t)},BackOut:function(e){var t=1.70158;return--e*e*((t+1)*e+t)+1},BackInOut:function(e){var t=2.5949095;return(e*=2)<1?.5*e*e*((t+1)*e-t):.5*((e-=2)*e*((t+1)*e+t)+2)},BounceIn:function(t){return 1-e.BounceOut(1-t)},BounceOut:function(e){return 1/2.75>e?7.5625*e*e:2/2.75>e?7.5625*(e-=1.5/2.75)*e+.75:2.5/2.75>e?7.5625*(e-=2.25/2.75)*e+.9375:7.5625*(e-=2.625/2.75)*e+.984375},BounceInOut:function(t){return.5>t?.5*e.BounceIn(2*t):.5*e.BounceOut(2*t-1)+.5}};return e}),i("echarts/chart/base",["require","zrender/shape/Image","../util/shape/Icon","../util/shape/MarkLine","../util/shape/Symbol","zrender/shape/Polyline","zrender/shape/ShapeBundle","../config","../util/ecData","../util/ecAnimation","../util/ecEffect","../util/accMath","../component/base","../layout/EdgeBundling","zrender/tool/util","zrender/tool/area"],function(e){function t(e){return null!=e.x&&null!=e.y}function i(e,t,i,n,a){p.call(this,e,t,i,n,a);var o=this;this.selectedMap={},this.lastShapeList=[],this.shapeHandler={onclick:function(){o.isClick=!0},ondragover:function(e){var t=e.target;t.highlightStyle=t.highlightStyle||{};var i=t.highlightStyle,n=i.brushTyep,a=i.strokeColor,r=i.lineWidth;i.brushType="stroke",i.strokeColor=o.ecTheme.calculableColor||h.calculableColor,i.lineWidth="icon"===t.type?30:10,o.zr.addHoverShape(t),setTimeout(function(){i&&(i.brushType=n,i.strokeColor=a,i.lineWidth=r)},20)},ondrop:function(e){null!=m.get(e.dragged,"data")&&(o.isDrop=!0)},ondragend:function(){o.isDragend=!0}}}var n=e("zrender/shape/Image"),a=e("../util/shape/Icon"),o=e("../util/shape/MarkLine"),r=e("../util/shape/Symbol"),s=e("zrender/shape/Polyline"),l=e("zrender/shape/ShapeBundle"),h=e("../config"),m=e("../util/ecData"),V=e("../util/ecAnimation"),U=e("../util/ecEffect"),d=e("../util/accMath"),p=e("../component/base"),c=e("../layout/EdgeBundling"),u=e("zrender/tool/util"),y=e("zrender/tool/area");return i.prototype={setCalculable:function(e){return e.dragEnableTime=this.ecTheme.DRAG_ENABLE_TIME||h.DRAG_ENABLE_TIME,e.ondragover=this.shapeHandler.ondragover,e.ondragend=this.shapeHandler.ondragend,e.ondrop=this.shapeHandler.ondrop,e},ondrop:function(e,t){if(this.isDrop&&e.target&&!t.dragIn){var i,n=e.target,a=e.dragged,o=m.get(n,"seriesIndex"),r=m.get(n,"dataIndex"),s=this.series,l=this.component.legend;if(-1===r){if(m.get(a,"seriesIndex")==o)return t.dragOut=t.dragIn=t.needRefresh=!0,void(this.isDrop=!1);i={value:m.get(a,"value"),name:m.get(a,"name")},this.type===h.CHART_TYPE_PIE&&i.value<0&&(i.value=0);for(var V=!1,U=s[o].data,p=0,c=U.length;c>p;p++)U[p].name===i.name&&"-"===U[p].value&&(s[o].data[p].value=i.value,V=!0);!V&&s[o].data.push(i),l&&l.add(i.name,a.style.color||a.style.strokeColor)}else i=s[o].data[r]||"-",null!=i.value?(s[o].data[r].value="-"!=i.value?d.accAdd(s[o].data[r].value,m.get(a,"value")):m.get(a,"value"),(this.type===h.CHART_TYPE_FUNNEL||this.type===h.CHART_TYPE_PIE)&&(l&&1===l.getRelatedAmount(i.name)&&this.component.legend.del(i.name),i.name+=this.option.nameConnector+m.get(a,"name"),l&&l.add(i.name,a.style.color||a.style.strokeColor))):s[o].data[r]="-"!=i?d.accAdd(s[o].data[r],m.get(a,"value")):m.get(a,"value");t.dragIn=t.dragIn||!0,this.isDrop=!1;var u=this;setTimeout(function(){u.zr.trigger("mousemove",e.event)},300)}},ondragend:function(e,t){if(this.isDragend&&e.target&&!t.dragOut){var i=e.target,n=m.get(i,"seriesIndex"),a=m.get(i,"dataIndex"),o=this.series;if(null!=o[n].data[a].value){o[n].data[a].value="-";var r=o[n].data[a].name,s=this.component.legend;s&&0===s.getRelatedAmount(r)&&s.del(r)}else o[n].data[a]="-";t.dragOut=!0,t.needRefresh=!0,this.isDragend=!1}},onlegendSelected:function(e,t){var i=e.selected;for(var n in this.selectedMap)this.selectedMap[n]!=i[n]&&(t.needRefresh=!0),this.selectedMap[n]=i[n]},_buildPosition:function(){this._symbol=this.option.symbolList,this._sIndex2ShapeMap={},this._sIndex2ColorMap={},this.selectedMap={},this.xMarkMap={};for(var e,t,i,n,a=this.series,o={top:[],bottom:[],left:[],right:[],other:[]},r=0,s=a.length;s>r;r++)a[r].type===this.type&&(a[r]=this.reformOption(a[r]),this.legendHoverLink=a[r].legendHoverLink||this.legendHoverLink,e=a[r].xAxisIndex,t=a[r].yAxisIndex,i=this.component.xAxis.getAxis(e),n=this.component.yAxis.getAxis(t),i.type===h.COMPONENT_TYPE_AXIS_CATEGORY?o[i.getPosition()].push(r):n.type===h.COMPONENT_TYPE_AXIS_CATEGORY?o[n.getPosition()].push(r):o.other.push(r));for(var l in o)o[l].length>0&&this._buildSinglePosition(l,o[l]);this.addShapeList()},_buildSinglePosition:function(e,t){var i=this._mapData(t),n=i.locationMap,a=i.maxDataLength;if(0!==a&&0!==n.length){switch(e){case"bottom":case"top":this._buildHorizontal(t,a,n,this.xMarkMap);break;case"left":case"right":this._buildVertical(t,a,n,this.xMarkMap);break;case"other":this._buildOther(t,a,n,this.xMarkMap)}for(var o=0,r=t.length;r>o;o++)this.buildMark(t[o])}},_mapData:function(e){for(var t,i,n,a,o=this.series,r=0,s={},l="__kener__stack__",m=this.component.legend,V=[],U=0,d=0,p=e.length;p>d;d++){if(t=o[e[d]],n=t.name,this._sIndex2ShapeMap[e[d]]=this._sIndex2ShapeMap[e[d]]||this.query(t,"symbol")||this._symbol[d%this._symbol.length],m){if(this.selectedMap[n]=m.isSelected(n),this._sIndex2ColorMap[e[d]]=m.getColor(n),a=m.getItemShape(n)){var c=a.style;if(this.type==h.CHART_TYPE_LINE)c.iconType="legendLineIcon",c.symbol=this._sIndex2ShapeMap[e[d]];else if(t.itemStyle.normal.barBorderWidth>0){var u=a.highlightStyle;c.brushType="both",c.x+=1,c.y+=1,c.width-=2,c.height-=2,c.strokeColor=u.strokeColor=t.itemStyle.normal.barBorderColor,u.lineWidth=3}m.setItemShape(n,a)}}else this.selectedMap[n]=!0,this._sIndex2ColorMap[e[d]]=this.zr.getColor(e[d]);this.selectedMap[n]&&(i=t.stack||l+e[d],null==s[i]?(s[i]=r,V[r]=[e[d]],r++):V[s[i]].push(e[d])),U=Math.max(U,t.data.length)}return{locationMap:V,maxDataLength:U}},_calculMarkMapXY:function(e,t,i){for(var n=this.series,a=0,o=t.length;o>a;a++)for(var r=0,s=t[a].length;s>r;r++){var l=t[a][r],h="xy"==i?0:"",m=this.component.grid,V=e[l];if("-1"!=i.indexOf("x")){V["counter"+h]>0&&(V["average"+h]=V["sum"+h]/V["counter"+h]);var U=this.component.xAxis.getAxis(n[l].xAxisIndex||0).getCoord(V["average"+h]);V["averageLine"+h]=[[U,m.getYend()],[U,m.getY()]],V["minLine"+h]=[[V["minX"+h],m.getYend()],[V["minX"+h],m.getY()]],V["maxLine"+h]=[[V["maxX"+h],m.getYend()],[V["maxX"+h],m.getY()]],V.isHorizontal=!1}if(h="xy"==i?1:"","-1"!=i.indexOf("y")){V["counter"+h]>0&&(V["average"+h]=V["sum"+h]/V["counter"+h]);var d=this.component.yAxis.getAxis(n[l].yAxisIndex||0).getCoord(V["average"+h]);V["averageLine"+h]=[[m.getX(),d],[m.getXend(),d]],V["minLine"+h]=[[m.getX(),V["minY"+h]],[m.getXend(),V["minY"+h]]],V["maxLine"+h]=[[m.getX(),V["maxY"+h]],[m.getXend(),V["maxY"+h]]],V.isHorizontal=!0}}},addLabel:function(e,t,i,n,a){var o=[i,t],r=this.deepMerge(o,"itemStyle.normal.label"),s=this.deepMerge(o,"itemStyle.emphasis.label"),l=r.textStyle||{},h=s.textStyle||{}; - -if(r.show){var m=e.style;m.text=this._getLabelText(t,i,n,"normal"),m.textPosition=null==r.position?"horizontal"===a?"right":"top":r.position,m.textColor=l.color,m.textFont=this.getFont(l),m.textAlign=l.align,m.textBaseline=l.baseline}if(s.show){var V=e.highlightStyle;V.text=this._getLabelText(t,i,n,"emphasis"),V.textPosition=r.show?e.style.textPosition:null==s.position?"horizontal"===a?"right":"top":s.position,V.textColor=h.color,V.textFont=this.getFont(h),V.textAlign=h.align,V.textBaseline=h.baseline}return e},_getLabelText:function(e,t,i,n){var a=this.deepQuery([t,e],"itemStyle."+n+".label.formatter");a||"emphasis"!==n||(a=this.deepQuery([t,e],"itemStyle.normal.label.formatter"));var o=this.getDataFromOption(t,"-");return a?"function"==typeof a?a.call(this.myChart,{seriesName:e.name,series:e,name:i,value:o,data:t,status:n}):"string"==typeof a?a=a.replace("{a}","{a0}").replace("{b}","{b0}").replace("{c}","{c0}").replace("{a0}",e.name).replace("{b0}",i).replace("{c0}",this.numAddCommas(o)):void 0:o instanceof Array?null!=o[2]?this.numAddCommas(o[2]):o[0]+" , "+o[1]:this.numAddCommas(o)},buildMark:function(e){var t=this.series[e];this.selectedMap[t.name]&&(t.markLine&&this._buildMarkLine(e),t.markPoint&&this._buildMarkPoint(e))},_buildMarkPoint:function(e){for(var t,i,n=(this.markAttachStyle||{})[e],a=this.series[e],o=u.clone(a.markPoint),r=0,s=o.data.length;s>r;r++)t=o.data[r],i=this.getMarkCoord(e,t),t.x=null!=t.x?t.x:i[0],t.y=null!=t.y?t.y:i[1],!t.type||"max"!==t.type&&"min"!==t.type||(t.value=i[3],t.name=t.name||t.type,t.symbolSize=t.symbolSize||y.getTextWidth(i[3],this.getFont())/2+5);for(var l=this._markPoint(e,o),r=0,s=l.length;s>r;r++){var m=l[r];m.zlevel=a.zlevel,m.z=a.z+1;for(var V in n)m[V]=u.clone(n[V]);this.shapeList.push(m)}if(this.type===h.CHART_TYPE_FORCE||this.type===h.CHART_TYPE_CHORD)for(var r=0,s=l.length;s>r;r++)this.zr.addShape(l[r])},_buildMarkLine:function(e){for(var t,i=(this.markAttachStyle||{})[e],n=this.series[e],a=u.clone(n.markLine),o=0,r=a.data.length;r>o;o++){var s=a.data[o];!s.type||"max"!==s.type&&"min"!==s.type&&"average"!==s.type?t=[this.getMarkCoord(e,s[0]),this.getMarkCoord(e,s[1])]:(t=this.getMarkCoord(e,s),a.data[o]=[u.clone(s),{}],a.data[o][0].name=s.name||s.type,a.data[o][0].value="average"!==s.type?t[3]:+t[3].toFixed(null!=a.precision?a.precision:this.deepQuery([this.ecTheme,h],"markLine.precision")),t=t[2],s=[{},{}]),null!=t&&null!=t[0]&&null!=t[1]&&(a.data[o][0].x=null!=s[0].x?s[0].x:t[0][0],a.data[o][0].y=null!=s[0].y?s[0].y:t[0][1],a.data[o][1].x=null!=s[1].x?s[1].x:t[1][0],a.data[o][1].y=null!=s[1].y?s[1].y:t[1][1])}var m=this._markLine(e,a),V=a.large;if(V){var U=new l({style:{shapeList:m}}),d=m[0];if(d){u.merge(U.style,d.style),u.merge(U.highlightStyle={},d.highlightStyle),U.style.brushType="stroke",U.zlevel=n.zlevel,U.z=n.z+1,U.hoverable=!1;for(var p in i)U[p]=u.clone(i[p])}this.shapeList.push(U),this.zr.addShape(U),U._mark="largeLine";var c=a.effect;c.show&&(U.effect=c)}else{for(var o=0,r=m.length;r>o;o++){var y=m[o];y.zlevel=n.zlevel,y.z=n.z+1;for(var p in i)y[p]=u.clone(i[p]);this.shapeList.push(y)}if(this.type===h.CHART_TYPE_FORCE||this.type===h.CHART_TYPE_CHORD)for(var o=0,r=m.length;r>o;o++)this.zr.addShape(m[o])}},_markPoint:function(e,t){var i=this.series[e],n=this.component;u.merge(u.merge(t,u.clone(this.ecTheme.markPoint||{})),u.clone(h.markPoint)),t.name=i.name;var a,o,r,s,l,V,U,d=[],p=t.data,c=n.dataRange,y=n.legend,g=this.zr.getWidth(),b=this.zr.getHeight();if(t.large)a=this.getLargeMarkPointShape(e,t),a._mark="largePoint",a&&d.push(a);else for(var f=0,k=p.length;k>f;f++)null!=p[f].x&&null!=p[f].y&&(r=null!=p[f].value?p[f].value:"",y&&(o=y.getColor(i.name)),c&&(o=isNaN(r)?o:c.getColor(r),s=[p[f],t],l=this.deepQuery(s,"itemStyle.normal.color")||o,V=this.deepQuery(s,"itemStyle.emphasis.color")||l,null==l&&null==V)||(o=null==o?this.zr.getColor(e):o,p[f].tooltip=p[f].tooltip||t.tooltip||{trigger:"item"},p[f].name=null!=p[f].name?p[f].name:"",p[f].value=r,a=this.getSymbolShape(t,e,p[f],f,p[f].name,this.parsePercent(p[f].x,g),this.parsePercent(p[f].y,b),"pin",o,"rgba(0,0,0,0)","horizontal"),a._mark="point",U=this.deepMerge([p[f],t],"effect"),U.show&&(a.effect=U),i.type===h.CHART_TYPE_MAP&&(a._geo=this.getMarkGeo(p[f])),m.pack(a,i,e,p[f],f,p[f].name,r),d.push(a)));return d},_markLine:function(){function e(e,t){e[t]=e[t]instanceof Array?e[t].length>1?e[t]:[e[t][0],e[t][0]]:[e[t],e[t]]}return function(i,n){var a=this.series[i],o=this.component,r=o.dataRange,s=o.legend;u.merge(u.merge(n,u.clone(this.ecTheme.markLine||{})),u.clone(h.markLine));var l=s?s.getColor(a.name):this.zr.getColor(i);e(n,"symbol"),e(n,"symbolSize"),e(n,"symbolRotate");for(var V=n.data,U=[],d=this.zr.getWidth(),p=this.zr.getHeight(),y=0;yy;y++){var K=U[y],I=K.rawEdge||K,g=I.rawData,x=null!=g.value?g.value:"",J=this.getMarkLineShape(n,i,g,y,K.points,W,I.color);J._mark="line";var C=this.deepMerge([g[0],g[1],n],"effect");C.show&&(J.effect=C,J.effect.large=n.large),a.type===h.CHART_TYPE_MAP&&(J._geo=[this.getMarkGeo(g[0]),this.getMarkGeo(g[1])]),m.pack(J,a,i,g[0],y,g[0].name+(""!==g[1].name?" > "+g[1].name:""),x),v.push(J)}return v}}(),getMarkCoord:function(){return[0,0]},getSymbolShape:function(e,t,i,o,r,s,l,h,V,U,d){var p=[i,e],c=this.getDataFromOption(i,"-");h=this.deepQuery(p,"symbol")||h;var u=this.deepQuery(p,"symbolSize");u="function"==typeof u?u(c):u,"number"==typeof u&&(u=[u,u]);var y=this.deepQuery(p,"symbolRotate"),g=this.deepMerge(p,"itemStyle.normal"),b=this.deepMerge(p,"itemStyle.emphasis"),f=null!=g.borderWidth?g.borderWidth:g.lineStyle&&g.lineStyle.width;null==f&&(f=h.match("empty")?2:0);var k=null!=b.borderWidth?b.borderWidth:b.lineStyle&&b.lineStyle.width;null==k&&(k=f+2);var x=this.getItemStyleColor(g.color,t,o,i),_=this.getItemStyleColor(b.color,t,o,i),L=u[0],W=u[1],X=new a({style:{iconType:h.replace("empty","").toLowerCase(),x:s-L,y:l-W,width:2*L,height:2*W,brushType:"both",color:h.match("empty")?U:x||V,strokeColor:g.borderColor||x||V,lineWidth:f},highlightStyle:{color:h.match("empty")?U:_||x||V,strokeColor:b.borderColor||g.borderColor||_||x||V,lineWidth:k},clickable:this.deepQuery(p,"clickable")});return h.match("image")&&(X.style.image=h.replace(new RegExp("^image:\\/\\/"),""),X=new n({style:X.style,highlightStyle:X.highlightStyle,clickable:this.deepQuery(p,"clickable")})),null!=y&&(X.rotation=[y*Math.PI/180,s,l]),h.match("star")&&(X.style.iconType="star",X.style.n=h.replace("empty","").replace("star","")-0||5),"none"===h&&(X.invisible=!0,X.hoverable=!1),X=this.addLabel(X,e,i,r,d),h.match("empty")&&(null==X.style.textColor&&(X.style.textColor=X.style.strokeColor),null==X.highlightStyle.textColor&&(X.highlightStyle.textColor=X.highlightStyle.strokeColor)),m.pack(X,e,t,i,o,r),X._x=s,X._y=l,X._dataIndex=o,X._seriesIndex=t,X},getMarkLineShape:function(e,t,i,n,a,r,l){var h=null!=i[0].value?i[0].value:"-",m=null!=i[1].value?i[1].value:"-",V=[i[0].symbol||e.symbol[0],i[1].symbol||e.symbol[1]],U=[i[0].symbolSize||e.symbolSize[0],i[1].symbolSize||e.symbolSize[1]];U[0]="function"==typeof U[0]?U[0](h):U[0],U[1]="function"==typeof U[1]?U[1](m):U[1];var d=[this.query(i[0],"symbolRotate")||e.symbolRotate[0],this.query(i[1],"symbolRotate")||e.symbolRotate[1]],p=[i[0],i[1],e],c=this.deepMerge(p,"itemStyle.normal");c.color=this.getItemStyleColor(c.color,t,n,i);var u=this.deepMerge(p,"itemStyle.emphasis");u.color=this.getItemStyleColor(u.color,t,n,i);var y=c.lineStyle,g=u.lineStyle,b=y.width;null==b&&(b=c.borderWidth);var f=g.width;null==f&&(f=null!=u.borderWidth?u.borderWidth:b+2);var k=this.deepQuery(p,"smoothness");this.deepQuery(p,"smooth")||(k=0);var x=r?s:o,_=new x({style:{symbol:V,symbolSize:U,symbolRotate:d,brushType:"both",lineType:y.type,shadowColor:y.shadowColor||y.color||c.borderColor||c.color||l,shadowBlur:y.shadowBlur,shadowOffsetX:y.shadowOffsetX,shadowOffsetY:y.shadowOffsetY,color:c.color||l,strokeColor:y.color||c.borderColor||c.color||l,lineWidth:b,symbolBorderColor:c.borderColor||c.color||l,symbolBorder:c.borderWidth},highlightStyle:{shadowColor:g.shadowColor,shadowBlur:g.shadowBlur,shadowOffsetX:g.shadowOffsetX,shadowOffsetY:g.shadowOffsetY,color:u.color||c.color||l,strokeColor:g.color||y.color||u.borderColor||c.borderColor||u.color||c.color||l,lineWidth:f,symbolBorderColor:u.borderColor||c.borderColor||u.color||c.color||l,symbolBorder:null==u.borderWidth?c.borderWidth+2:u.borderWidth},clickable:this.deepQuery(p,"clickable")}),L=_.style;return r?(L.pointList=a,L.smooth=k):(L.xStart=a[0][0],L.yStart=a[0][1],L.xEnd=a[1][0],L.yEnd=a[1][1],L.curveness=k,_.updatePoints(_.style)),_=this.addLabel(_,e,i[0],i[0].name+" : "+i[1].name)},getLargeMarkPointShape:function(e,t){var i,n,a,o,s,l,h=this.series[e],m=this.component,V=t.data,U=m.dataRange,d=m.legend,p=[V[0],t];if(d&&(n=d.getColor(h.name)),!U||(a=null!=V[0].value?V[0].value:"",n=isNaN(a)?n:U.getColor(a),o=this.deepQuery(p,"itemStyle.normal.color")||n,s=this.deepQuery(p,"itemStyle.emphasis.color")||o,null!=o||null!=s)){n=this.deepMerge(p,"itemStyle.normal").color||n;var c=this.deepQuery(p,"symbol")||"circle";c=c.replace("empty","").replace(/\d/g,""),l=this.deepMerge([V[0],t],"effect");var u=window.devicePixelRatio||1;return i=new r({style:{pointList:V,color:n,strokeColor:n,shadowColor:l.shadowColor||n,shadowBlur:(null!=l.shadowBlur?l.shadowBlur:8)*u,size:this.deepQuery(p,"symbolSize"),iconType:c,brushType:"fill",lineWidth:1},draggable:!1,hoverable:!1}),l.show&&(i.effect=l),i}},backupShapeList:function(){this.shapeList&&this.shapeList.length>0?(this.lastShapeList=this.shapeList,this.shapeList=[]):this.lastShapeList=[]},addShapeList:function(){var e,t,i=this.option.animationThreshold/(this.canvasSupported?2:4),n=this.lastShapeList,a=this.shapeList,o=n.length>0,r=o?this.query(this.option,"animationDurationUpdate"):this.query(this.option,"animationDuration"),s=this.query(this.option,"animationEasing"),l={},m={};if(this.option.animation&&!this.option.renderAsImage&&a.lengthV;V++)t=this._getAnimationKey(n[V]),t.match("undefined")?this.zr.delShape(n[V].id):(t+=n[V].type,l[t]?this.zr.delShape(n[V].id):l[t]=n[V]);for(var V=0,U=a.length;U>V;V++)t=this._getAnimationKey(a[V]),t.match("undefined")?this.zr.addShape(a[V]):(t+=a[V].type,m[t]=a[V]);for(t in l)m[t]||this.zr.delShape(l[t].id);for(t in m)l[t]?(this.zr.delShape(l[t].id),this._animateMod(l[t],m[t],r,s,0,o)):(e=this.type!=h.CHART_TYPE_LINE&&this.type!=h.CHART_TYPE_RADAR||0===t.indexOf("icon")?0:r/2,this._animateMod(!1,m[t],r,s,e,o));this.zr.refresh(),this.animationEffect()}else{this.motionlessOnce=!1,this.zr.delShape(n);for(var V=0,U=a.length;U>V;V++)this.zr.addShape(a[V])}},_getAnimationKey:function(e){return this.type!=h.CHART_TYPE_MAP&&this.type!=h.CHART_TYPE_TREEMAP&&this.type!=h.CHART_TYPE_VENN&&this.type!=h.CHART_TYPE_TREE?m.get(e,"seriesIndex")+"_"+m.get(e,"dataIndex")+(e._mark?e._mark:"")+(this.type===h.CHART_TYPE_RADAR?m.get(e,"special"):""):m.get(e,"seriesIndex")+"_"+m.get(e,"dataIndex")+(e._mark?e._mark:"undefined")},_animateMod:function(e,t,i,n,a,o){switch(t.type){case"polyline":case"half-smooth-polygon":V.pointList(this.zr,e,t,i,n);break;case"rectangle":V.rectangle(this.zr,e,t,i,n);break;case"image":case"icon":V.icon(this.zr,e,t,i,n,a);break;case"candle":o?this.zr.addShape(t):V.candle(this.zr,e,t,i,n);break;case"ring":case"sector":case"circle":o?"sector"===t.type?V.sector(this.zr,e,t,i,n):this.zr.addShape(t):V.ring(this.zr,e,t,i+(m.get(t,"dataIndex")||0)%20*100,n);break;case"text":V.text(this.zr,e,t,i,n);break;case"polygon":o?V.pointList(this.zr,e,t,i,n):V.polygon(this.zr,e,t,i,n);break;case"ribbon":V.ribbon(this.zr,e,t,i,n);break;case"gauge-pointer":V.gaugePointer(this.zr,e,t,i,n);break;case"mark-line":V.markline(this.zr,e,t,i,n);break;case"bezier-curve":case"line":V.line(this.zr,e,t,i,n);break;default:this.zr.addShape(t)}},animationMark:function(e,t,i){for(var i=i||this.shapeList,n=0,a=i.length;a>n;n++)i[n]._mark&&this._animateMod(!1,i[n],e,t,0,!0);this.animationEffect(i)},animationEffect:function(e){if(!e&&this.clearEffectShape(),e=e||this.shapeList,null!=e){var t=h.EFFECT_ZLEVEL;this.canvasSupported&&this.zr.modLayer(t,{motionBlur:!0,lastFrameAlpha:this.option.effectBlendAlpha||h.effectBlendAlpha});for(var i,n=0,a=e.length;a>n;n++)i=e[n],i._mark&&i.effect&&i.effect.show&&U[i._mark]&&(U[i._mark](this.zr,this.effectList,i,t),this.effectList[this.effectList.length-1]._mark=i._mark)}},clearEffectShape:function(e){var t=this.effectList;if(this.zr&&t&&t.length>0){e&&this.zr.modLayer(h.EFFECT_ZLEVEL,{motionBlur:!1}),this.zr.delShape(t);for(var i=0;il;l++)this.zr.addShape(this.shapeList[l]);this.zr.refreshNextFrame()}n[i].data=r}},delMark:function(e,t,i){i=i.replace("mark","").replace("large","").toLowerCase();var n=this.series[e];if(this.selectedMap[n.name]){for(var a=!1,o=[this.shapeList,this.effectList],r=2;r--;)for(var s=0,l=o[r].length;l>s;s++)if(o[r][s]._mark==i&&m.get(o[r][s],"seriesIndex")==e&&m.get(o[r][s],"name")==t){this.zr.delShape(o[r][s].id),o[r].splice(s,1),a=!0;break}a&&this.zr.refreshNextFrame()}}},u.inherits(i,p),i}),i("zrender/shape/Circle",["require","./Base","../tool/util"],function(e){"use strict";var t=e("./Base"),i=function(e){t.call(this,e)};return i.prototype={type:"circle",buildPath:function(e,t){e.moveTo(t.x+t.r,t.y),e.arc(t.x,t.y,t.r,0,2*Math.PI,!0)},getRect:function(e){if(e.__rect)return e.__rect;var t;return t="stroke"==e.brushType||"fill"==e.brushType?e.lineWidth||1:0,e.__rect={x:Math.round(e.x-e.r-t/2),y:Math.round(e.y-e.r-t/2),width:2*e.r+t,height:2*e.r+t},e.__rect}},e("../tool/util").inherits(i,t),i}),i("echarts/util/accMath",[],function(){function e(e,t){var i=e.toString(),n=t.toString(),a=0;try{a=n.split(".")[1].length}catch(o){}try{a-=i.split(".")[1].length}catch(o){}return(i.replace(".","")-0)/(n.replace(".","")-0)*Math.pow(10,a)}function t(e,t){var i=e.toString(),n=t.toString(),a=0;try{a+=i.split(".")[1].length}catch(o){}try{a+=n.split(".")[1].length}catch(o){}return(i.replace(".","")-0)*(n.replace(".","")-0)/Math.pow(10,a)}function i(e,t){var i=0,n=0;try{i=e.toString().split(".")[1].length}catch(a){}try{n=t.toString().split(".")[1].length}catch(a){}var o=Math.pow(10,Math.max(i,n));return(Math.round(e*o)+Math.round(t*o))/o}function n(e,t){return i(e,-t)}return{accDiv:e,accMul:t,accAdd:i,accSub:n}}),i("echarts/util/shape/Icon",["require","zrender/tool/util","zrender/shape/Star","zrender/shape/Heart","zrender/shape/Droplet","zrender/shape/Image","zrender/shape/Base"],function(e){function t(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i,n+t.height),e.lineTo(i+5*a,n+14*o),e.lineTo(i+t.width,n+3*o),e.lineTo(i+13*a,n),e.lineTo(i+2*a,n+11*o),e.lineTo(i,n+t.height),e.moveTo(i+6*a,n+10*o),e.lineTo(i+14*a,n+2*o),e.moveTo(i+10*a,n+13*o),e.lineTo(i+t.width,n+13*o),e.moveTo(i+13*a,n+10*o),e.lineTo(i+13*a,n+t.height)}function i(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i,n+t.height),e.lineTo(i+5*a,n+14*o),e.lineTo(i+t.width,n+3*o),e.lineTo(i+13*a,n),e.lineTo(i+2*a,n+11*o),e.lineTo(i,n+t.height),e.moveTo(i+6*a,n+10*o),e.lineTo(i+14*a,n+2*o),e.moveTo(i+10*a,n+13*o),e.lineTo(i+t.width,n+13*o)}function n(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i+4*a,n+15*o),e.lineTo(i+9*a,n+13*o),e.lineTo(i+14*a,n+8*o),e.lineTo(i+11*a,n+5*o),e.lineTo(i+6*a,n+10*o),e.lineTo(i+4*a,n+15*o),e.moveTo(i+5*a,n),e.lineTo(i+11*a,n),e.moveTo(i+5*a,n+o),e.lineTo(i+11*a,n+o),e.moveTo(i,n+2*o),e.lineTo(i+t.width,n+2*o),e.moveTo(i,n+5*o),e.lineTo(i+3*a,n+t.height),e.lineTo(i+13*a,n+t.height),e.lineTo(i+t.width,n+5*o)}function a(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i,n+3*o),e.lineTo(i+6*a,n+3*o),e.moveTo(i+3*a,n),e.lineTo(i+3*a,n+6*o),e.moveTo(i+3*a,n+8*o),e.lineTo(i+3*a,n+t.height),e.lineTo(i+t.width,n+t.height),e.lineTo(i+t.width,n+3*o),e.lineTo(i+8*a,n+3*o)}function o(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i+6*a,n),e.lineTo(i+2*a,n+3*o),e.lineTo(i+6*a,n+6*o),e.moveTo(i+2*a,n+3*o),e.lineTo(i+14*a,n+3*o),e.lineTo(i+14*a,n+11*o),e.moveTo(i+2*a,n+5*o),e.lineTo(i+2*a,n+13*o),e.lineTo(i+14*a,n+13*o),e.moveTo(i+10*a,n+10*o),e.lineTo(i+14*a,n+13*o),e.lineTo(i+10*a,n+t.height)}function r(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16,r=t.width/2;e.lineWidth=1.5,e.arc(i+r,n+r,r-a,0,2*Math.PI/3),e.moveTo(i+3*a,n+t.height),e.lineTo(i+0*a,n+12*o),e.lineTo(i+5*a,n+11*o),e.moveTo(i,n+8*o),e.arc(i+r,n+r,r-a,Math.PI,5*Math.PI/3),e.moveTo(i+13*a,n),e.lineTo(i+t.width,n+4*o),e.lineTo(i+11*a,n+5*o)}function s(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i,n),e.lineTo(i,n+t.height),e.lineTo(i+t.width,n+t.height),e.moveTo(i+2*a,n+14*o),e.lineTo(i+7*a,n+6*o),e.lineTo(i+11*a,n+11*o),e.lineTo(i+15*a,n+2*o)}function l(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i,n),e.lineTo(i,n+t.height),e.lineTo(i+t.width,n+t.height),e.moveTo(i+3*a,n+14*o),e.lineTo(i+3*a,n+6*o),e.lineTo(i+4*a,n+6*o),e.lineTo(i+4*a,n+14*o),e.moveTo(i+7*a,n+14*o),e.lineTo(i+7*a,n+2*o),e.lineTo(i+8*a,n+2*o),e.lineTo(i+8*a,n+14*o),e.moveTo(i+11*a,n+14*o),e.lineTo(i+11*a,n+9*o),e.lineTo(i+12*a,n+9*o),e.lineTo(i+12*a,n+14*o)}function h(e,t){var i=t.x,n=t.y,a=t.width-2,o=t.height-2,r=Math.min(a,o)/2;n+=2,e.moveTo(i+r+3,n+r-3),e.arc(i+r+3,n+r-3,r-1,0,-Math.PI/2,!0),e.lineTo(i+r+3,n+r-3),e.moveTo(i+r,n),e.lineTo(i+r,n+r),e.arc(i+r,n+r,r,-Math.PI/2,2*Math.PI,!0),e.lineTo(i+r,n+r),e.lineWidth=1.5}function m(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;n-=o,e.moveTo(i+1*a,n+2*o),e.lineTo(i+15*a,n+2*o),e.lineTo(i+14*a,n+3*o),e.lineTo(i+2*a,n+3*o),e.moveTo(i+3*a,n+6*o),e.lineTo(i+13*a,n+6*o),e.lineTo(i+12*a,n+7*o),e.lineTo(i+4*a,n+7*o),e.moveTo(i+5*a,n+10*o),e.lineTo(i+11*a,n+10*o),e.lineTo(i+10*a,n+11*o),e.lineTo(i+6*a,n+11*o),e.moveTo(i+7*a,n+14*o),e.lineTo(i+9*a,n+14*o),e.lineTo(i+8*a,n+15*o),e.lineTo(i+7*a,n+15*o)}function V(e,t){var i=t.x,n=t.y,a=t.width,o=t.height,r=a/16,s=o/16,l=2*Math.min(r,s);e.moveTo(i+r+l,n+s+l),e.arc(i+r,n+s,l,Math.PI/4,3*Math.PI),e.lineTo(i+7*r-l,n+6*s-l),e.arc(i+7*r,n+6*s,l,Math.PI/4*5,4*Math.PI),e.arc(i+7*r,n+6*s,l/2,Math.PI/4*5,4*Math.PI),e.moveTo(i+7*r-l/2,n+6*s+l),e.lineTo(i+r+l,n+14*s-l),e.arc(i+r,n+14*s,l,-Math.PI/4,2*Math.PI),e.moveTo(i+7*r+l/2,n+6*s),e.lineTo(i+14*r-l,n+10*s-l/2),e.moveTo(i+16*r,n+10*s),e.arc(i+14*r,n+10*s,l,0,3*Math.PI),e.lineWidth=1.5}function U(e,t){var i=t.x,n=t.y,a=t.width,o=t.height,r=Math.min(a,o)/2;e.moveTo(i+a,n+o/2),e.arc(i+r,n+r,r,0,2*Math.PI),e.arc(i+r,n,r,Math.PI/4,Math.PI/5*4),e.arc(i,n+r,r,-Math.PI/3,Math.PI/3),e.arc(i+a,n+o,r,Math.PI,Math.PI/2*3),e.lineWidth=1.5}function d(e,t){for(var i=t.x,n=t.y,a=t.width,o=t.height,r=Math.round(o/3),s=Math.round((r-2)/2),l=3;l--;)e.rect(i,n+r*l+s,a,2)}function p(e,t){for(var i=t.x,n=t.y,a=t.width,o=t.height,r=Math.round(a/3),s=Math.round((r-2)/2),l=3;l--;)e.rect(i+r*l+s,n,2,o)}function c(e,t){var i=t.x,n=t.y,a=t.width/16;e.moveTo(i+a,n),e.lineTo(i+a,n+t.height),e.lineTo(i+15*a,n+t.height),e.lineTo(i+15*a,n),e.lineTo(i+a,n),e.moveTo(i+3*a,n+3*a),e.lineTo(i+13*a,n+3*a),e.moveTo(i+3*a,n+6*a),e.lineTo(i+13*a,n+6*a),e.moveTo(i+3*a,n+9*a),e.lineTo(i+13*a,n+9*a),e.moveTo(i+3*a,n+12*a),e.lineTo(i+9*a,n+12*a)}function u(e,t){var i=t.x,n=t.y,a=t.width/16,o=t.height/16;e.moveTo(i,n),e.lineTo(i,n+t.height),e.lineTo(i+t.width,n+t.height),e.lineTo(i+t.width,n),e.lineTo(i,n),e.moveTo(i+4*a,n),e.lineTo(i+4*a,n+8*o),e.lineTo(i+12*a,n+8*o),e.lineTo(i+12*a,n),e.moveTo(i+6*a,n+11*o),e.lineTo(i+6*a,n+13*o),e.lineTo(i+10*a,n+13*o),e.lineTo(i+10*a,n+11*o),e.lineTo(i+6*a,n+11*o)}function y(e,t){var i=t.x,n=t.y,a=t.width,o=t.height;e.moveTo(i,n+o/2),e.lineTo(i+a,n+o/2),e.moveTo(i+a/2,n),e.lineTo(i+a/2,n+o)}function g(e,t){var i=t.width/2,n=t.height/2,a=Math.min(i,n);e.moveTo(t.x+i+a,t.y+n),e.arc(t.x+i,t.y+n,a,0,2*Math.PI),e.closePath()}function b(e,t){e.rect(t.x,t.y,t.width,t.height),e.closePath()}function f(e,t){var i=t.width/2,n=t.height/2,a=t.x+i,o=t.y+n,r=Math.min(i,n);e.moveTo(a,o-r),e.lineTo(a+r,o+r),e.lineTo(a-r,o+r),e.lineTo(a,o-r),e.closePath()}function k(e,t){var i=t.width/2,n=t.height/2,a=t.x+i,o=t.y+n,r=Math.min(i,n);e.moveTo(a,o-r),e.lineTo(a+r,o),e.lineTo(a,o+r),e.lineTo(a-r,o),e.lineTo(a,o-r),e.closePath()}function x(e,t){var i=t.x,n=t.y,a=t.width/16;e.moveTo(i+8*a,n),e.lineTo(i+a,n+t.height),e.lineTo(i+8*a,n+t.height/4*3),e.lineTo(i+15*a,n+t.height),e.lineTo(i+8*a,n),e.closePath()}function _(t,i){var n=e("zrender/shape/Star"),a=i.width/2,o=i.height/2;n.prototype.buildPath(t,{x:i.x+a,y:i.y+o,r:Math.min(a,o),n:i.n||5})}function L(t,i){var n=e("zrender/shape/Heart");n.prototype.buildPath(t,{x:i.x+i.width/2,y:i.y+.2*i.height,a:i.width/2,b:.8*i.height})}function W(t,i){var n=e("zrender/shape/Droplet");n.prototype.buildPath(t,{x:i.x+.5*i.width,y:i.y+.5*i.height,a:.5*i.width,b:.8*i.height})}function X(e,t){var i=t.x,n=t.y-t.height/2*1.5,a=t.width/2,o=t.height/2,r=Math.min(a,o);e.arc(i+a,n+o,r,Math.PI/5*4,Math.PI/5),e.lineTo(i+a,n+o+1.5*r),e.closePath()}function v(t,i,n){var a=e("zrender/shape/Image");this._imageShape=this._imageShape||new a({style:{}});for(var o in i)this._imageShape.style[o]=i[o];this._imageShape.brush(t,!1,n)}function w(e){I.call(this,e)}var K=e("zrender/tool/util"),I=e("zrender/shape/Base");return w.prototype={type:"icon",iconLibrary:{mark:t,markUndo:i,markClear:n,dataZoom:a,dataZoomReset:o,restore:r,lineChart:s,barChart:l,pieChart:h,funnelChart:m,forceChart:V,chordChart:U,stackChart:d,tiledChart:p,dataView:c,saveAsImage:u,cross:y,circle:g,rectangle:b,triangle:f,diamond:k,arrow:x,star:_,heart:L,droplet:W,pin:X,image:v},brush:function(t,i,n){var a=i?this.highlightStyle:this.style;a=a||{};var o=a.iconType||this.style.iconType;if("image"===o){var r=e("zrender/shape/Image");r.prototype.brush.call(this,t,i,n)}else{var a=this.beforeBrush(t,i);switch(t.beginPath(),this.buildPath(t,a,n),a.brushType){case"both":t.fill();case"stroke":a.lineWidth>0&&t.stroke();break;default:t.fill()}this.drawText(t,a,this.style),this.afterBrush(t)}},buildPath:function(e,t,i){this.iconLibrary[t.iconType]?this.iconLibrary[t.iconType].call(this,e,t,i):(e.moveTo(t.x,t.y),e.lineTo(t.x+t.width,t.y),e.lineTo(t.x+t.width,t.y+t.height),e.lineTo(t.x,t.y+t.height),e.lineTo(t.x,t.y),e.closePath())},getRect:function(e){return e.__rect?e.__rect:(e.__rect={x:Math.round(e.x),y:Math.round(e.y-("pin"==e.iconType?e.height/2*1.5:0)),width:e.width,height:e.height*("pin"===e.iconType?1.25:1)},e.__rect)},isCover:function(e,t){var i=this.transformCoordToLocal(e,t);e=i[0],t=i[1];var n=this.style.__rect;n||(n=this.style.__rect=this.getRect(this.style));var a=n.height<8||n.width<8?4:0;return e>=n.x-a&&e<=n.x+n.width+a&&t>=n.y-a&&t<=n.y+n.height+a}},K.inherits(w,I),w}),i("echarts/util/shape/MarkLine",["require","zrender/shape/Base","./Icon","zrender/shape/Line","zrender/shape/BezierCurve","zrender/tool/area","zrender/shape/util/dashedLineTo","zrender/tool/util","zrender/tool/curve"],function(e){function t(e){i.call(this,e),this.style.curveness>0&&this.updatePoints(this.style),this.highlightStyle.curveness>0&&this.updatePoints(this.highlightStyle)}var i=e("zrender/shape/Base"),n=e("./Icon"),a=e("zrender/shape/Line"),o=new a({}),r=e("zrender/shape/BezierCurve"),s=new r({}),l=e("zrender/tool/area"),h=e("zrender/shape/util/dashedLineTo"),m=e("zrender/tool/util"),V=e("zrender/tool/curve");return t.prototype={type:"mark-line",brush:function(e,t){var i=this.style;t&&(i=this.getHighlightStyle(i,this.highlightStyle||{})),e.save(),this.setContext(e,i),this.setTransform(e),e.save(),e.beginPath(),this.buildPath(e,i),e.stroke(),e.restore(),this.brushSymbol(e,i,0),this.brushSymbol(e,i,1),this.drawText(e,i,this.style),e.restore()},buildPath:function(e,t){var i=t.lineType||"solid";if(e.moveTo(t.xStart,t.yStart),t.curveness>0){var n=null;switch(i){case"dashed":n=[5,5];break;case"dotted":n=[1,1]}n&&e.setLineDash&&e.setLineDash(n),e.quadraticCurveTo(t.cpX1,t.cpY1,t.xEnd,t.yEnd)}else if("solid"==i)e.lineTo(t.xEnd,t.yEnd);else{var a=(t.lineWidth||1)*("dashed"==t.lineType?5:1);h(e,t.xStart,t.yStart,t.xEnd,t.yEnd,a)}},updatePoints:function(e){var t=e.curveness||0,i=1,n=e.xStart,a=e.yStart,o=e.xEnd,r=e.yEnd,s=(n+o)/2-i*(a-r)*t,l=(a+r)/2-i*(o-n)*t;e.cpX1=s,e.cpY1=l},brushSymbol:function(e,t,i){if("none"!=t.symbol[i]){e.save(),e.beginPath(),e.lineWidth=t.symbolBorder,e.strokeStyle=t.symbolBorderColor;var a=t.symbol[i].replace("empty","").toLowerCase();t.symbol[i].match("empty")&&(e.fillStyle="#fff");var o=t.xStart,r=t.yStart,s=t.xEnd,l=t.yEnd,h=0===i?o:s,m=0===i?r:l,U=t.curveness||0,d=null!=t.symbolRotate[i]?t.symbolRotate[i]-0:0;if(d=d/180*Math.PI,"arrow"==a&&0===d)if(0===U){var p=0===i?-1:1;d=Math.PI/2+Math.atan2(p*(l-r),p*(s-o))}else{var c=t.cpX1,u=t.cpY1,y=V.quadraticDerivativeAt,g=y(o,c,s,i),b=y(r,u,l,i);d=Math.PI/2+Math.atan2(b,g)}e.translate(h,m),0!==d&&e.rotate(d);var f=t.symbolSize[i];n.prototype.buildPath(e,{x:-f,y:-f,width:2*f,height:2*f,iconType:a}),e.closePath(),e.fill(),e.stroke(),e.restore()}},getRect:function(e){return e.curveness>0?s.getRect(e):o.getRect(e),e.__rect},isCover:function(e,t){var i=this.transformCoordToLocal(e,t);return e=i[0],t=i[1],this.isCoverRect(e,t)?this.style.curveness>0?l.isInside(s,this.style,e,t):l.isInside(o,this.style,e,t):!1}},m.inherits(t,i),t}),i("echarts/util/shape/Symbol",["require","zrender/shape/Base","zrender/shape/Polygon","zrender/tool/util","./normalIsCover"],function(e){function t(e){i.call(this,e)}var i=e("zrender/shape/Base"),n=e("zrender/shape/Polygon"),a=new n({}),o=e("zrender/tool/util");return t.prototype={type:"symbol",buildPath:function(e,t){var i=t.pointList,n=i.length;if(0!==n)for(var a,o,r,s,l,h=1e4,m=Math.ceil(n/h),V=i[0]instanceof Array,U=t.size?t.size:2,d=U,p=U/2,c=2*Math.PI,u=0;m>u;u++){e.beginPath(),a=u*h,o=a+h,o=o>n?n:o;for(var y=a;o>y;y++)if(t.random&&(r=t["randomMap"+y%20]/100,d=U*r*r,p=d/2),V?(s=i[y][0],l=i[y][1]):(s=i[y].x,l=i[y].y),3>d)e.rect(s-p,l-p,d,d);else switch(t.iconType){case"circle":e.moveTo(s,l),e.arc(s,l,p,0,c,!0);break;case"diamond":e.moveTo(s,l-p),e.lineTo(s+p/3,l-p/3),e.lineTo(s+p,l),e.lineTo(s+p/3,l+p/3),e.lineTo(s,l+p),e.lineTo(s-p/3,l+p/3),e.lineTo(s-p,l),e.lineTo(s-p/3,l-p/3),e.lineTo(s,l-p);break;default:e.rect(s-p,l-p,d,d)}if(e.closePath(),m-1>u)switch(t.brushType){case"both":e.fill(),t.lineWidth>0&&e.stroke();break;case"stroke":t.lineWidth>0&&e.stroke();break;default:e.fill()}}},getRect:function(e){return e.__rect||a.getRect(e)},isCover:e("./normalIsCover")},o.inherits(t,i),t}),i("zrender/shape/Polyline",["require","./Base","./util/smoothSpline","./util/smoothBezier","./util/dashedLineTo","./Polygon","../tool/util"],function(e){var t=e("./Base"),i=e("./util/smoothSpline"),n=e("./util/smoothBezier"),a=e("./util/dashedLineTo"),o=function(e){this.brushTypeOnly="stroke",this.textPosition="end",t.call(this,e)};return o.prototype={type:"polyline",buildPath:function(e,t){var n=t.pointList;if(!(n.length<2)){var o=Math.min(t.pointList.length,Math.round(t.pointListLength||t.pointList.length));if(t.smooth&&"spline"!==t.smooth){t.controlPointList||this.updateControlPoints(t);var r=t.controlPointList;e.moveTo(n[0][0],n[0][1]);for(var s,l,h,m=0;o-1>m;m++)s=r[2*m],l=r[2*m+1],h=n[m+1],e.bezierCurveTo(s[0],s[1],l[0],l[1],h[0],h[1])}else if("spline"===t.smooth&&(n=i(n),o=n.length),t.lineType&&"solid"!=t.lineType){if("dashed"==t.lineType||"dotted"==t.lineType){var V=(t.lineWidth||1)*("dashed"==t.lineType?5:1);e.moveTo(n[0][0],n[0][1]);for(var m=1;o>m;m++)a(e,n[m-1][0],n[m-1][1],n[m][0],n[m][1],V)}}else{e.moveTo(n[0][0],n[0][1]);for(var m=1;o>m;m++)e.lineTo(n[m][0],n[m][1])}}},updateControlPoints:function(e){e.controlPointList=n(e.pointList,e.smooth,!1,e.smoothConstraint)},getRect:function(t){return e("./Polygon").prototype.getRect(t)}},e("../tool/util").inherits(o,t),o}),i("zrender/shape/ShapeBundle",["require","./Base","../tool/util"],function(e){var t=e("./Base"),i=function(e){t.call(this,e)};return i.prototype={constructor:i,type:"shape-bundle",brush:function(e,t){var i=this.beforeBrush(e,t);e.beginPath();for(var n=0;n0&&e.stroke();break;default:e.fill()}this.drawText(e,i,this.style),this.afterBrush(e)},getRect:function(e){if(e.__rect)return e.__rect;for(var t=1/0,i=-(1/0),n=1/0,a=-(1/0),o=0;oh;h++)o[h]=[r[h][0],l];else for(var m=r[0][0],h=0;s>h;h++)o[h]=[m,r[h][1]];"half-smooth-polygon"==i.type&&(o[s-1]=p.clone(r[s-1]),o[s-2]=p.clone(r[s-2])),t={style:{pointList:o}}}o=t.style.pointList;var V=o.length;i.style.pointList=V==s?o:s>V?o.concat(r.slice(V)):o.slice(0,s),e.addShape(i),i.__animating=!0,e.animate(i.id,"style").when(n,{pointList:r}).during(function(){i.updateControlPoints&&i.updateControlPoints(i.style)}).done(function(){i.__animating=!1}).start(a)}function i(e,t){for(var i=arguments.length,n=2;i>n;n++){var a=arguments[n];e.style[a]=t.style[a]}}function n(e,t,n,a,o){var r=n.style;t||(t={position:n.position,style:{x:r.x,y:"vertical"==n._orient?r.y+r.height:r.y,width:"vertical"==n._orient?r.width:0,height:"vertical"!=n._orient?r.height:0}});var s=r.x,l=r.y,h=r.width,m=r.height,V=[n.position[0],n.position[1]];i(n,t,"x","y","width","height"),n.position=t.position,e.addShape(n),(V[0]!=t.position[0]||V[1]!=t.position[1])&&e.animate(n.id,"").when(a,{position:V}).start(o),n.__animating=!0,e.animate(n.id,"style").when(a,{x:s,y:l,width:h,height:m}).done(function(){n.__animating=!1}).start(o)}function a(e,t,i,n,a){if(!t){var o=i.style.y;t={style:{y:[o[0],o[0],o[0],o[0]]}}}var r=i.style.y;i.style.y=t.style.y,e.addShape(i),i.__animating=!0,e.animate(i.id,"style").when(n,{y:r}).done(function(){i.__animating=!1}).start(a)}function o(e,t,i,n,a){var o=i.style.x,r=i.style.y,s=i.style.r0,l=i.style.r;i.__animating=!0,"r"!=i._animationAdd?(i.style.r0=0,i.style.r=0,i.rotation=[2*Math.PI,o,r],e.addShape(i),e.animate(i.id,"style").when(n,{r0:s,r:l}).done(function(){i.__animating=!1}).start(a),e.animate(i.id,"").when(n,{rotation:[0,o,r]}).start(a)):(i.style.r0=i.style.r,e.addShape(i),e.animate(i.id,"style").when(n,{r0:s}).done(function(){i.__animating=!1}).start(a))}function r(e,t,n,a,o){t||(t="r"!=n._animationAdd?{ -style:{startAngle:n.style.startAngle,endAngle:n.style.startAngle}}:{style:{r0:n.style.r}});var r=n.style.startAngle,s=n.style.endAngle;i(n,t,"startAngle","endAngle"),e.addShape(n),n.__animating=!0,e.animate(n.id,"style").when(a,{startAngle:r,endAngle:s}).done(function(){n.__animating=!1}).start(o)}function s(e,t,n,a,o){t||(t={style:{x:"left"==n.style.textAlign?n.style.x+100:n.style.x-100,y:n.style.y}});var r=n.style.x,s=n.style.y;i(n,t,"x","y"),e.addShape(n),n.__animating=!0,e.animate(n.id,"style").when(a,{x:r,y:s}).done(function(){n.__animating=!1}).start(o)}function l(t,i,n,a,o){var r=e("zrender/shape/Polygon").prototype.getRect(n.style),s=r.x+r.width/2,l=r.y+r.height/2;n.scale=[.1,.1,s,l],t.addShape(n),n.__animating=!0,t.animate(n.id,"").when(a,{scale:[1,1,s,l]}).done(function(){n.__animating=!1}).start(o)}function h(e,t,n,a,o){t||(t={style:{source0:0,source1:n.style.source1>0?360:-360,target0:0,target1:n.style.target1>0?360:-360}});var r=n.style.source0,s=n.style.source1,l=n.style.target0,h=n.style.target1;t.style&&i(n,t,"source0","source1","target0","target1"),e.addShape(n),n.__animating=!0,e.animate(n.id,"style").when(a,{source0:r,source1:s,target0:l,target1:h}).done(function(){n.__animating=!1}).start(o)}function m(e,t,i,n,a){t||(t={style:{angle:i.style.startAngle}});var o=i.style.angle;i.style.angle=t.style.angle,e.addShape(i),i.__animating=!0,e.animate(i.id,"style").when(n,{angle:o}).done(function(){i.__animating=!1}).start(a)}function V(e,t,i,a,o,r){if(i.style._x=i.style.x,i.style._y=i.style.y,i.style._width=i.style.width,i.style._height=i.style.height,t)n(e,t,i,a,o);else{var s=i._x||0,l=i._y||0;i.scale=[.01,.01,s,l],e.addShape(i),i.__animating=!0,e.animate(i.id,"").delay(r).when(a,{scale:[1,1,s,l]}).done(function(){i.__animating=!1}).start(o||"QuinticOut")}}function U(e,t,n,a,o){t||(t={style:{xStart:n.style.xStart,yStart:n.style.yStart,xEnd:n.style.xStart,yEnd:n.style.yStart}});var r=n.style.xStart,s=n.style.xEnd,l=n.style.yStart,h=n.style.yEnd;i(n,t,"xStart","xEnd","yStart","yEnd"),e.addShape(n),n.__animating=!0,e.animate(n.id,"style").when(a,{xStart:r,xEnd:s,yStart:l,yEnd:h}).done(function(){n.__animating=!1}).start(o)}function d(e,t,i,n,a){a=a||"QuinticOut",i.__animating=!0,e.addShape(i);var o=i.style,r=function(){i.__animating=!1},s=o.xStart,l=o.yStart,h=o.xEnd,m=o.yEnd;if(o.curveness>0){i.updatePoints(o);var V={p:0},U=o.cpX1,d=o.cpY1,p=[],u=[],y=c.quadraticSubdivide;e.animation.animate(V).when(n,{p:1}).during(function(){y(s,U,h,V.p,p),y(l,d,m,V.p,u),o.cpX1=p[1],o.cpY1=u[1],o.xEnd=p[2],o.yEnd=u[2],e.modShape(i)}).done(r).start(a)}else e.animate(i.id,"style").when(0,{xEnd:s,yEnd:l}).when(n,{xEnd:h,yEnd:m}).done(r).start(a)}var p=e("zrender/tool/util"),c=e("zrender/tool/curve");return{pointList:t,rectangle:n,candle:a,ring:o,sector:r,text:s,polygon:l,ribbon:h,gaugePointer:m,icon:V,line:U,markline:d}}),i("echarts/util/ecEffect",["require","../util/ecData","zrender/shape/Circle","zrender/shape/Image","zrender/tool/curve","../util/shape/Icon","../util/shape/Symbol","zrender/shape/ShapeBundle","zrender/shape/Polyline","zrender/tool/vector","zrender/tool/env"],function(e){function t(e,t,i,n){var a,r=i.effect,l=r.color||i.style.strokeColor||i.style.color,m=r.shadowColor||l,V=r.scaleSize,U=r.bounceDistance,d="undefined"!=typeof r.shadowBlur?r.shadowBlur:V;"image"!==i.type?(a=new h({zlevel:n,style:{brushType:"stroke",iconType:"droplet"!=i.style.iconType?i.style.iconType:"circle",x:d+1,y:d+1,n:i.style.n,width:i.style._width*V,height:i.style._height*V,lineWidth:1,strokeColor:l,shadowColor:m,shadowBlur:d},draggable:!1,hoverable:!1}),"pin"==i.style.iconType&&(a.style.y+=a.style.height/2*1.5),p&&(a.style.image=e.shapeToImage(a,a.style.width+2*d+2,a.style.height+2*d+2).style.image,a=new s({zlevel:a.zlevel,style:a.style,draggable:!1,hoverable:!1}))):a=new s({zlevel:n,style:i.style,draggable:!1,hoverable:!1}),o.clone(i,a),a.position=i.position,t.push(a),e.addShape(a);var c="image"!==i.type?window.devicePixelRatio||1:1,u=(a.style.width/c-i.style._width)/2;a.style.x=i.style._x-u,a.style.y=i.style._y-u,"pin"==i.style.iconType&&(a.style.y-=i.style.height/2*1.5);var y=100*(r.period+10*Math.random());e.modShape(i.id,{invisible:!0});var g=a.style.x+a.style.width/2/c,b=a.style.y+a.style.height/2/c;"scale"===r.type?(e.modShape(a.id,{scale:[.1,.1,g,b]}),e.animate(a.id,"",r.loop).when(y,{scale:[1,1,g,b]}).done(function(){i.effect.show=!1,e.delShape(a.id)}).start()):e.animate(a.id,"style",r.loop).when(y,{y:a.style.y-U}).when(2*y,{y:a.style.y}).done(function(){i.effect.show=!1,e.delShape(a.id)}).start()}function i(e,t,i,n){var a=i.effect,o=a.color||i.style.strokeColor||i.style.color,r=a.scaleSize,s=a.shadowColor||o,l="undefined"!=typeof a.shadowBlur?a.shadowBlur:2*r,h=window.devicePixelRatio||1,V=new m({zlevel:n,position:i.position,scale:i.scale,style:{pointList:i.style.pointList,iconType:i.style.iconType,color:o,strokeColor:o,shadowColor:s,shadowBlur:l*h,random:!0,brushType:"fill",lineWidth:1,size:i.style.size},draggable:!1,hoverable:!1});t.push(V),e.addShape(V),e.modShape(i.id,{invisible:!0});for(var U=Math.round(100*a.period),d={},p={},c=0;20>c;c++)V.style["randomMap"+c]=0,d={},d["randomMap"+c]=100,p={},p["randomMap"+c]=0,V.style["randomMap"+c]=100*Math.random(),e.animate(V.id,"style",!0).when(U,d).when(2*U,p).when(3*U,d).when(4*U,d).delay(Math.random()*U*c).start()}function n(e,t,i,n,a){var s=i.effect,h=i.style,m=s.color||h.strokeColor||h.color,V=s.shadowColor||h.strokeColor||m,c=h.lineWidth*s.scaleSize,u="undefined"!=typeof s.shadowBlur?s.shadowBlur:c,y=new r({zlevel:n,style:{x:u,y:u,r:c,color:m,shadowColor:V,shadowBlur:u},hoverable:!1}),g=0;if(p&&!a){var n=y.zlevel;y=e.shapeToImage(y,2*(c+u),2*(c+u)),y.zlevel=n,y.hoverable=!1,g=u}a||(o.clone(i,y),y.position=i.position,t.push(y),e.addShape(y));var b=function(){a||(i.effect.show=!1,e.delShape(y.id)),y.effectAnimator=null};if(i instanceof U){for(var f=[0],k=0,x=h.pointList,_=h.controlPointList,L=1;L0){var F=h.cpX1-g,T=h.cpY1-g;y.effectAnimator=e.animation.animate(y,{loop:s.loop}).when(E,{p:1}).during(function(t,i){y.style.x=l.quadraticAt(K,F,J,i),y.style.y=l.quadraticAt(I,T,C,i),a||e.modShape(y)}).done(b).start()}else y.effectAnimator=e.animation.animate(y.style,{loop:s.loop}).when(E,{x:J,y:C}).during(function(){a||e.modShape(y)}).done(b).start();y.effectAnimator.duration=E}return y}function a(e,t,i,a){var o=new V({style:{shapeList:[]},zlevel:a,hoverable:!1}),r=i.style.shapeList,s=i.effect;o.position=i.position;for(var l=0,h=[],m=0;ml&&(l=d.duration),0===m&&(o.style.color=U.style.color,o.style.shadowBlur=U.style.shadowBlur,o.style.shadowColor=U.style.shadowColor),h.push(d)}t.push(o),e.addShape(o);var p=function(){for(var e=0;e=0;o--)t=s.type==i.CHART_TYPE_PIE||s.type==i.CHART_TYPE_FUNNEL?n.get(s.shapeList[o],"name"):(n.get(s.shapeList[o],"series")||{}).name,t!=a||s.shapeList[o].invisible||s.shapeList[o].__animating||s.zr.addHoverShape(s.shapeList[o])},t&&t.bind(i.EVENT.LEGEND_HOVERLINK,this._onlegendhoverlink)}var i=e("../config"),n=e("../util/ecData"),a=e("../util/ecQuery"),o=e("../util/number"),r=e("zrender/tool/util");return t.prototype={canvasSupported:e("zrender/tool/env").canvasSupported,_getZ:function(e){if(null!=this[e])return this[e];var t=this.ecTheme[this.type];return t&&null!=t[e]?t[e]:(t=i[this.type],t&&null!=t[e]?t[e]:0)},getZlevelBase:function(){return this._getZ("zlevel")},getZBase:function(){return this._getZ("z")},reformOption:function(e){return e=r.merge(r.merge(e||{},r.clone(this.ecTheme[this.type]||{})),r.clone(i[this.type]||{})),this.z=e.z,this.zlevel=e.zlevel,e},reformCssArray:function(e){if(!(e instanceof Array))return[e,e,e,e];switch(e.length+""){case"4":return e;case"3":return[e[0],e[1],e[2],e[1]];case"2":return[e[0],e[1],e[0],e[1]];case"1":return[e[0],e[0],e[0],e[0]];case"0":return[0,0,0,0]}},getShapeById:function(e){for(var t=0,i=this.shapeList.length;i>t;t++)if(this.shapeList[t].id===e)return this.shapeList[t];return null},getFont:function(e){var t=this.getTextStyle(r.clone(e));return t.fontStyle+" "+t.fontWeight+" "+t.fontSize+"px "+t.fontFamily},getTextStyle:function(e){return r.merge(r.merge(e||{},this.ecTheme.textStyle),i.textStyle)},getItemStyleColor:function(e,t,i,n){return"function"==typeof e?e.call(this.myChart,{seriesIndex:t,series:this.series[t],dataIndex:i,data:n}):e},getDataFromOption:function(e,t){return null!=e?null!=e.value?e.value:e:t},subPixelOptimize:function(e,t){return e=t%2===1?Math.floor(e)+.5:Math.round(e)},resize:function(){this.refresh&&this.refresh(),this.clearEffectShape&&this.clearEffectShape(!0);var e=this;setTimeout(function(){e.animationEffect&&e.animationEffect()},200)},clear:function(){this.clearEffectShape&&this.clearEffectShape(),this.zr&&this.zr.delShape(this.shapeList),this.shapeList=[]},dispose:function(){this.onbeforDispose&&this.onbeforDispose(),this.clear(),this.shapeList=null,this.effectList=null,this.messageCenter&&this.messageCenter.unbind(i.EVENT.LEGEND_HOVERLINK,this._onlegendhoverlink),this.onafterDispose&&this.onafterDispose()},query:a.query,deepQuery:a.deepQuery,deepMerge:a.deepMerge,parsePercent:o.parsePercent,parseCenter:o.parseCenter,parseRadius:o.parseRadius,numAddCommas:o.addCommas,getPrecision:o.getPrecision},t}),i("echarts/layout/EdgeBundling",["require","../data/KDTree","zrender/tool/vector"],function(e){function t(e,t){e=e.array,t=t.array;var i=t[0]-e[0],n=t[1]-e[1],a=t[2]-e[2],o=t[3]-e[3];return i*i+n*n+a*a+o*o}function i(e){this.points=[e.mp0,e.mp1],this.group=e}function n(e){var t=e.points;t[0][1]0&&t(e[o],n[a-1])||(n[a++]=U(e[o]));return i[0]&&!t(n[0],i[0])&&(n=n.reverse()),n}for(var a=this._iterate(e),o=0;o++f&&(f=W,k=L,V(g,c),V(y,p),b=u)}if(k){s+=f;var X;k.group||(X=new a,o.push(X),X.addEdge(k)),X=k.group,V(X.mp0,y),V(X.mp1,g),X.ink=b,k.group.addEdge(m)}else{var X=new a;o.push(X),V(X.mp0,m.getStartPoint()),V(X.mp1,m.getEndPoint()),X.ink=m.ink,X.addEdge(m)}}}return{groups:o,edges:i,savedInk:s}},_calculateEdgeEdgeInk:function(){var e=[],t=[];return function(i,n,a,o){e[0]=i.getStartPoint(),e[1]=n.getStartPoint(),t[0]=i.getEndPoint(),t[1]=n.getEndPoint(),this._calculateMeetPoints(e,t,a,o);var r=m(e[0],a)+m(a,o)+m(o,t[0])+m(e[1],a)+m(o,t[1]);return r}}(),_calculateGroupEdgeInk:function(e,t,i,n){for(var a=[],o=[],r=0;rl;l++)s.add(e,e,i[l]);s.scale(e,e,1/r),r=n.length;for(var l=0;r>l;l++)s.add(t,t,n[l]);s.scale(t,t,1/r),this._limitTurningAngle(i,e,t,a),this._limitTurningAngle(n,t,e,o)}}(),_limitTurningAngle:function(){var e=l(),t=l(),i=l(),n=l();return function(a,o,r,l){var V=Math.cos(this.maxTurningAngle),U=Math.tan(this.maxTurningAngle);s.sub(e,o,r),s.normalize(e,e),s.copy(l,o);for(var d=0,p=0;py){s.scaleAndAdd(i,o,e,u*y);var g=m(i,c),b=g/U;s.scaleAndAdd(n,i,e,-b);var f=h(n,o);f>d&&(d=f,s.copy(l,n))}}}}()},o}),i("zrender/shape/Star",["require","../tool/math","./Base","../tool/util"],function(e){var t=e("../tool/math"),i=t.sin,n=t.cos,a=Math.PI,o=e("./Base"),r=function(e){o.call(this,e)};return r.prototype={type:"star",buildPath:function(e,t){var o=t.n;if(o&&!(2>o)){var r=t.x,s=t.y,l=t.r,h=t.r0;null==h&&(h=o>4?l*n(2*a/o)/n(a/o):l/3);var m=a/o,V=-a/2,U=r+l*n(V),d=s+l*i(V);V+=m;var p=t.pointList=[];p.push([U,d]);for(var c,u=0,y=2*o-1;y>u;u++)c=u%2===0?h:l,p.push([r+c*n(V),s+c*i(V)]),V+=m;p.push([U,d]),e.moveTo(p[0][0],p[0][1]);for(var u=0;ur;r+=2)e[0]=Math.min(e[0],e[0],o[r]),e[1]=Math.min(e[1],e[1],o[r+1]),i[0]=Math.max(i[0],i[0],o[r]),i[1]=Math.max(i[1],i[1],o[r+1]);break;case"Q":for(var r=0;4>r;r+=2)e[0]=Math.min(e[0],e[0],o[r]),e[1]=Math.min(e[1],e[1],o[r+1]),i[0]=Math.max(i[0],i[0],o[r]),i[1]=Math.max(i[1],i[1],o[r+1]);break;case"A":var s=o[0],l=o[1],h=o[2],m=o[3];e[0]=Math.min(e[0],e[0],s-h),e[1]=Math.min(e[1],e[1],l-m),i[0]=Math.max(i[0],i[0],s+h),i[1]=Math.max(i[1],i[1],l+m)}}return{x:e[0],y:e[1],width:i[0]-e[0],height:i[1]-e[1]}},n.prototype.begin=function(e){return this._ctx=e||null,this.pathCommands.length=0,this},n.prototype.moveTo=function(e,t){return this.pathCommands.push(new i("M",[e,t])),this._ctx&&this._ctx.moveTo(e,t),this},n.prototype.lineTo=function(e,t){return this.pathCommands.push(new i("L",[e,t])),this._ctx&&this._ctx.lineTo(e,t),this},n.prototype.bezierCurveTo=function(e,t,n,a,o,r){return this.pathCommands.push(new i("C",[e,t,n,a,o,r])),this._ctx&&this._ctx.bezierCurveTo(e,t,n,a,o,r),this},n.prototype.quadraticCurveTo=function(e,t,n,a){return this.pathCommands.push(new i("Q",[e,t,n,a])),this._ctx&&this._ctx.quadraticCurveTo(e,t,n,a),this},n.prototype.arc=function(e,t,n,a,o,r){return this.pathCommands.push(new i("A",[e,t,n,n,a,o-a,0,r?0:1])),this._ctx&&this._ctx.arc(e,t,n,a,o,r),this},n.prototype.arcTo=function(e,t,i,n,a){return this._ctx&&this._ctx.arcTo(e,t,i,n,a),this},n.prototype.rect=function(e,t,i,n){return this._ctx&&this._ctx.rect(e,t,i,n),this},n.prototype.closePath=function(){return this.pathCommands.push(new i("z")),this._ctx&&this._ctx.closePath(),this},n.prototype.isEmpty=function(){return 0===this.pathCommands.length},n.PathSegment=i,n}),i("zrender/shape/Line",["require","./Base","./util/dashedLineTo","../tool/util"],function(e){var t=e("./Base"),i=e("./util/dashedLineTo"),n=function(e){this.brushTypeOnly="stroke",this.textPosition="end",t.call(this,e)};return n.prototype={type:"line",buildPath:function(e,t){if(t.lineType&&"solid"!=t.lineType){if("dashed"==t.lineType||"dotted"==t.lineType){var n=(t.lineWidth||1)*("dashed"==t.lineType?5:1);i(e,t.xStart,t.yStart,t.xEnd,t.yEnd,n)}}else e.moveTo(t.xStart,t.yStart),e.lineTo(t.xEnd,t.yEnd)},getRect:function(e){if(e.__rect)return e.__rect;var t=e.lineWidth||1;return e.__rect={x:Math.min(e.xStart,e.xEnd)-t,y:Math.min(e.yStart,e.yEnd)-t,width:Math.abs(e.xStart-e.xEnd)+t,height:Math.abs(e.yStart-e.yEnd)+t},e.__rect}},e("../tool/util").inherits(n,t),n}),i("zrender/shape/BezierCurve",["require","./Base","../tool/util"],function(e){"use strict";var t=e("./Base"),i=function(e){this.brushTypeOnly="stroke",this.textPosition="end",t.call(this,e)};return i.prototype={type:"bezier-curve",buildPath:function(e,t){e.moveTo(t.xStart,t.yStart),"undefined"!=typeof t.cpX2&&"undefined"!=typeof t.cpY2?e.bezierCurveTo(t.cpX1,t.cpY1,t.cpX2,t.cpY2,t.xEnd,t.yEnd):e.quadraticCurveTo(t.cpX1,t.cpY1,t.xEnd,t.yEnd)},getRect:function(e){if(e.__rect)return e.__rect;var t=Math.min(e.xStart,e.xEnd,e.cpX1),i=Math.min(e.yStart,e.yEnd,e.cpY1),n=Math.max(e.xStart,e.xEnd,e.cpX1),a=Math.max(e.yStart,e.yEnd,e.cpY1),o=e.cpX2,r=e.cpY2;"undefined"!=typeof o&&"undefined"!=typeof r&&(t=Math.min(t,o),i=Math.min(i,r),n=Math.max(n,o),a=Math.max(a,r));var s=e.lineWidth||1;return e.__rect={x:t-s,y:i-s,width:n-t+s,height:a-i+s},e.__rect}},e("../tool/util").inherits(i,t),i}),i("zrender/shape/util/dashedLineTo",[],function(){var e=[5,5];return function(t,i,n,a,o,r){if(t.setLineDash)return e[0]=e[1]=r,t.setLineDash(e),t.moveTo(i,n),void t.lineTo(a,o);r="number"!=typeof r?5:r;var s=a-i,l=o-n,h=Math.floor(Math.sqrt(s*s+l*l)/r);s/=h,l/=h;for(var m=!0,V=0;h>V;++V)m?t.moveTo(i,n):t.lineTo(i,n),m=!m,i+=s,n+=l;t.lineTo(a,o)}}),i("zrender/shape/Polygon",["require","./Base","./util/smoothSpline","./util/smoothBezier","./util/dashedLineTo","../tool/util"],function(e){var t=e("./Base"),i=e("./util/smoothSpline"),n=e("./util/smoothBezier"),a=e("./util/dashedLineTo"),o=function(e){t.call(this,e)};return o.prototype={type:"polygon",buildPath:function(e,t){var o=t.pointList;if(!(o.length<2)){if(t.smooth&&"spline"!==t.smooth){var r=n(o,t.smooth,!0,t.smoothConstraint);e.moveTo(o[0][0],o[0][1]);for(var s,l,h,m=o.length,V=0;m>V;V++)s=r[2*V],l=r[2*V+1],h=o[(V+1)%m],e.bezierCurveTo(s[0],s[1],l[0],l[1],h[0],h[1])}else if("spline"===t.smooth&&(o=i(o,!0)),t.lineType&&"solid"!=t.lineType){if("dashed"==t.lineType||"dotted"==t.lineType){var U=t._dashLength||(t.lineWidth||1)*("dashed"==t.lineType?5:1);t._dashLength=U,e.moveTo(o[0][0],o[0][1]);for(var V=1,d=o.length;d>V;V++)a(e,o[V-1][0],o[V-1][1],o[V][0],o[V][1],U);a(e,o[o.length-1][0],o[o.length-1][1],o[0][0],o[0][1],U)}}else{e.moveTo(o[0][0],o[0][1]);for(var V=1,d=o.length;d>V;V++)e.lineTo(o[V][0],o[V][1]);e.lineTo(o[0][0],o[0][1])}e.closePath()}},getRect:function(e){if(e.__rect)return e.__rect;for(var t=Number.MAX_VALUE,i=Number.MIN_VALUE,n=Number.MAX_VALUE,a=Number.MIN_VALUE,o=e.pointList,r=0,s=o.length;s>r;r++)o[r][0]i&&(i=o[r][0]),o[r][1]a&&(a=o[r][1]);var l;return l="stroke"==e.brushType||"fill"==e.brushType?e.lineWidth||1:0,e.__rect={x:Math.round(t-l/2),y:Math.round(n-l/2),width:i-t+l,height:a-n+l},e.__rect}},e("../tool/util").inherits(o,t),o}),i("echarts/util/shape/normalIsCover",[],function(){return function(e,t){var i=this.transformCoordToLocal(e,t);return e=i[0],t=i[1],this.isCoverRect(e,t)}}),i("zrender/shape/util/smoothSpline",["require","../../tool/vector"],function(e){function t(e,t,i,n,a,o,r){var s=.5*(i-e),l=.5*(n-t);return(2*(t-i)+s+l)*r+(-3*(t-i)-2*s-l)*o+s*a+t}var i=e("../../tool/vector");return function(e,n){for(var a=e.length,o=[],r=0,s=1;a>s;s++)r+=i.distance(e[s-1],e[s]);var l=r/5;l=a>l?a:l;for(var s=0;l>s;s++){var h,m,V,U=s/(l-1)*(n?a:a-1),d=Math.floor(U),p=U-d,c=e[d%a];n?(h=e[(d-1+a)%a],m=e[(d+1)%a],V=e[(d+2)%a]):(h=e[0===d?d:d-1],m=e[d>a-2?a-1:d+1],V=e[d>a-3?a-1:d+2]);var u=p*p,y=p*u;o.push([t(h[0],c[0],m[0],V[0],p,u,y),t(h[1],c[1],m[1],V[1],p,u,y)])}return o}}),i("zrender/shape/util/smoothBezier",["require","../../tool/vector"],function(e){var t=e("../../tool/vector");return function(e,i,n,a){var o,r,s,l,h=[],m=[],V=[],U=[],d=!!a;if(d){s=[1/0,1/0],l=[-(1/0),-(1/0)];for(var p=0,c=e.length;c>p;p++)t.min(s,s,e[p]),t.max(l,l,e[p]);t.min(s,s,a[0]),t.max(l,l,a[1])}for(var p=0,c=e.length;c>p;p++){var o,r,u=e[p];if(n)o=e[p?p-1:c-1],r=e[(p+1)%c];else{if(0===p||p===c-1){h.push(t.clone(e[p]));continue}o=e[p-1],r=e[p+1]}t.sub(m,r,o),t.scale(m,m,i);var y=t.distance(u,o),g=t.distance(u,r),b=y+g;0!==b&&(y/=b,g/=b),t.scale(V,m,-y),t.scale(U,m,g);var f=t.add([],u,V),k=t.add([],u,U);d&&(t.max(f,f,s),t.min(f,f,l),t.max(k,k,s),t.min(k,k,l)),h.push(f),h.push(k)}return n&&h.push(t.clone(h.shift())),h}}),i("echarts/util/ecQuery",["require","zrender/tool/util"],function(e){function t(e,t){if("undefined"!=typeof e){if(!t)return e;t=t.split(".");for(var i=t.length,n=0;i>n;){if(e=e[t[n]],"undefined"==typeof e)return;n++}return e}}function i(e,i){for(var n,a=0,o=e.length;o>a;a++)if(n=t(e[a],i),"undefined"!=typeof n)return n}function n(e,i){for(var n,o=e.length;o--;){var r=t(e[o],i);"undefined"!=typeof r&&("undefined"==typeof n?n=a.clone(r):a.merge(n,r,!0))}return n}var a=e("zrender/tool/util");return{query:t,deepQuery:i,deepMerge:n}}),i("echarts/util/number",[],function(){function e(e){return e.replace(/^\s+/,"").replace(/\s+$/,"")}function t(t,i){return"string"==typeof t?e(t).match(/%$/)?parseFloat(t)/100*i:parseFloat(t):t}function i(e,i){return[t(i[0],e.getWidth()),t(i[1],e.getHeight())]}function n(e,i){i instanceof Array||(i=[0,i]);var n=Math.min(e.getWidth(),e.getHeight())/2;return[t(i[0],n),t(i[1],n)]}function a(e){return isNaN(e)?"-":(e=(e+"").split("."),e[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g,"$1,")+(e.length>1?"."+e[1]:""))}function o(e){for(var t=1,i=0;Math.round(e*t)/t!==e;)t*=10,i++;return i}return{parsePercent:t,parseCenter:i,parseRadius:n,addCommas:a,getPrecision:o}}),i("echarts/data/KDTree",["require","./quickSelect"],function(e){function t(e,t){this.left=null,this.right=null,this.axis=e,this.data=t}var i=e("./quickSelect"),n=function(e,t){e.length&&(t||(t=e[0].array.length),this.dimension=t,this.root=this._buildTree(e,0,e.length-1,0),this._stack=[],this._nearstNList=[])};return n.prototype._buildTree=function(e,n,a,o){if(n>a)return null;var r=Math.floor((n+a)/2);r=i(e,n,a,r,function(e,t){return e.array[o]-t.array[o]});var s=e[r],l=new t(o,s);return o=(o+1)%this.dimension,a>n&&(l.left=this._buildTree(e,n,r-1,o),l.right=this._buildTree(e,r+1,a,o)),l},n.prototype.nearest=function(e,t){var i=this.root,n=this._stack,a=0,o=1/0,r=null;for(i.data!==e&&(o=t(i.data,e),r=i),e.array[i.axis]s,h=!1;s*=s,o>s&&(s=t(i.data,e),o>s&&i.data!==e&&(o=s,r=i),h=!0),l?(h&&i.right&&(n[a++]=i.right),i.left&&(n[a++]=i.left)):(h&&i.left&&(n[a++]=i.left),i.right&&(n[a++]=i.right))}return r.data},n.prototype._addNearest=function(e,t,i){for(var n=this._nearstNList,a=e-1;a>0&&!(t>=n[a-1].dist);a--)n[a].dist=n[a-1].dist,n[a].node=n[a-1].node;n[a].dist=t,n[a].node=i},n.prototype.nearestN=function(e,t,i,n){if(0>=t)return n.length=0,n;for(var a=this.root,o=this._stack,r=0,s=this._nearstNList,l=0;t>l;l++)s[l]||(s[l]={}),s[l].dist=0,s[l].node=null;var h=i(a.data,e),m=0;for(a.data!==e&&(m++,this._addNearest(m,h,a)),e.array[a.axis]h,U=!1;h*=h,(t>m||hm||hm&&m++,this._addNearest(m,h,a)),U=!0),V?(U&&a.right&&(o[r++]=a.right),a.left&&(o[r++]=a.left)):(U&&a.left&&(o[r++]=a.left),a.right&&(o[r++]=a.right))}for(var l=0;m>l;l++)n[l]=s[l].node.data;return n.length=m,n},n}),i("echarts/data/quickSelect",["require"],function(){function e(e,t){return e-t}function t(e,t,i){var n=e[t];e[t]=e[i],e[i]=n}function i(e,i,n,a,o){for(var r=i;n>i;){var r=Math.round((n+i)/2),s=e[r];t(e,r,n),r=i;for(var l=i;n-1>=l;l++)o(s,e[l])>=0&&(t(e,l,r),r++);if(t(e,n,r),r===a)return r;a>r?i=r+1:n=r-1}return i}function n(t,n,a,o,r){return arguments.length<=3&&(o=n,r=2==arguments.length?e:a,n=0,a=t.length-1),i(t,n,a,o,r)}return n}),i("echarts/component/dataView",["require","./base","../config","zrender/tool/util","../component"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.dom=o.dom,this._tDom=document.createElement("div"),this._textArea=document.createElement("textArea"),this._buttonRefresh=document.createElement("button"),this._buttonRefresh.setAttribute("type","button"),this._buttonClose=document.createElement("button"),this._buttonClose.setAttribute("type","button"),this._hasShow=!1,this._zrHeight=n.getHeight(),this._zrWidth=n.getWidth(),this._tDom.className="echarts-dataview",this.hide(),this.dom.firstChild.appendChild(this._tDom),window.addEventListener?(this._tDom.addEventListener("click",this._stop),this._tDom.addEventListener("mousewheel",this._stop),this._tDom.addEventListener("mousemove",this._stop),this._tDom.addEventListener("mousedown",this._stop),this._tDom.addEventListener("mouseup",this._stop),this._tDom.addEventListener("touchstart",this._stop),this._tDom.addEventListener("touchmove",this._stop),this._tDom.addEventListener("touchend",this._stop)):(this._tDom.attachEvent("onclick",this._stop),this._tDom.attachEvent("onmousewheel",this._stop),this._tDom.attachEvent("onmousemove",this._stop),this._tDom.attachEvent("onmousedown",this._stop),this._tDom.attachEvent("onmouseup",this._stop))}var i=e("./base"),n=e("../config"),a=e("zrender/tool/util");return t.prototype={type:n.COMPONENT_TYPE_DATAVIEW,_lang:["Data View","close","refresh"],_gCssText:"position:absolute;display:block;overflow:hidden;transition:height 0.8s,background-color 1s;-moz-transition:height 0.8s,background-color 1s;-webkit-transition:height 0.8s,background-color 1s;-o-transition:height 0.8s,background-color 1s;z-index:1;left:0;top:0;",hide:function(){this._sizeCssText="width:"+this._zrWidth+"px;height:0px;background-color:#f0ffff;",this._tDom.style.cssText=this._gCssText+this._sizeCssText},show:function(e){this._hasShow=!0;var t=this.query(this.option,"toolbox.feature.dataView.lang")||this._lang;this.option=e,this._tDom.innerHTML='

                          '+(t[0]||this._lang[0])+"

                          ";var i=this.query(this.option,"toolbox.feature.dataView.optionToContent");"function"!=typeof i?this._textArea.value=this._optionToContent():(this._textArea=document.createElement("div"),this._textArea.innerHTML=i(this.option)),this._textArea.style.cssText="display:block;margin:0 0 8px 0;padding:4px 6px;overflow:auto;width:100%;height:"+(this._zrHeight-100)+"px;",this._tDom.appendChild(this._textArea),this._buttonClose.style.cssText="float:right;padding:1px 6px;",this._buttonClose.innerHTML=t[1]||this._lang[1];var n=this;this._buttonClose.onclick=function(){n.hide()},this._tDom.appendChild(this._buttonClose),this.query(this.option,"toolbox.feature.dataView.readOnly")===!1?(this._buttonRefresh.style.cssText="float:right;margin-right:10px;padding:1px 6px;",this._buttonRefresh.innerHTML=t[2]||this._lang[2],this._buttonRefresh.onclick=function(){n._save()},this._textArea.readOnly=!1,this._textArea.style.cursor="default"):(this._buttonRefresh.style.cssText="display:none", -this._textArea.readOnly=!0,this._textArea.style.cursor="text"),this._tDom.appendChild(this._buttonRefresh),this._sizeCssText="width:"+this._zrWidth+"px;height:"+this._zrHeight+"px;background-color:#fff;",this._tDom.style.cssText=this._gCssText+this._sizeCssText},_optionToContent:function(){var e,t,i,a,o,r,s=[],l="";if(this.option.xAxis)for(s=this.option.xAxis instanceof Array?this.option.xAxis:[this.option.xAxis],e=0,a=s.length;a>e;e++)if("category"==(s[e].type||"category")){for(r=[],t=0,i=s[e].data.length;i>t;t++)r.push(this.getDataFromOption(s[e].data[t]));l+=r.join(", ")+"\n\n"}if(this.option.yAxis)for(s=this.option.yAxis instanceof Array?this.option.yAxis:[this.option.yAxis],e=0,a=s.length;a>e;e++)if("category"==s[e].type){for(r=[],t=0,i=s[e].data.length;i>t;t++)r.push(this.getDataFromOption(s[e].data[t]));l+=r.join(", ")+"\n\n"}var h,m=this.option.series;for(e=0,a=m.length;a>e;e++){for(r=[],t=0,i=m[e].data.length;i>t;t++)o=m[e].data[t],h=m[e].type==n.CHART_TYPE_PIE||m[e].type==n.CHART_TYPE_MAP?(o.name||"-")+":":"",m[e].type==n.CHART_TYPE_SCATTER&&(o=this.getDataFromOption(o).join(", ")),r.push(h+this.getDataFromOption(o));l+=(m[e].name||"-")+" : \n",l+=r.join(m[e].type==n.CHART_TYPE_SCATTER?"\n":", "),l+="\n\n"}return l},_save:function(){var e=this.query(this.option,"toolbox.feature.dataView.contentToOption");if("function"!=typeof e){for(var t=this._textArea.value.split("\n"),i=[],a=0,o=t.length;o>a;a++)t[a]=this._trim(t[a]),""!==t[a]&&i.push(t[a]);this._contentToOption(i)}else e(this._textArea,this.option);this.hide();var r=this;setTimeout(function(){r.messageCenter&&r.messageCenter.dispatch(n.EVENT.DATA_VIEW_CHANGED,null,{option:r.option},r.myChart)},r.canvasSupported?800:100)},_contentToOption:function(e){var t,i,a,o,r,s,l,h=[],m=0;if(this.option.xAxis)for(h=this.option.xAxis instanceof Array?this.option.xAxis:[this.option.xAxis],t=0,o=h.length;o>t;t++)if("category"==(h[t].type||"category")){for(s=e[m].split(","),i=0,a=h[t].data.length;a>i;i++)l=this._trim(s[i]||""),r=h[t].data[i],"undefined"!=typeof h[t].data[i].value?h[t].data[i].value=l:h[t].data[i]=l;m++}if(this.option.yAxis)for(h=this.option.yAxis instanceof Array?this.option.yAxis:[this.option.yAxis],t=0,o=h.length;o>t;t++)if("category"==h[t].type){for(s=e[m].split(","),i=0,a=h[t].data.length;a>i;i++)l=this._trim(s[i]||""),r=h[t].data[i],"undefined"!=typeof h[t].data[i].value?h[t].data[i].value=l:h[t].data[i]=l;m++}var V=this.option.series;for(t=0,o=V.length;o>t;t++)if(m++,V[t].type==n.CHART_TYPE_SCATTER)for(var i=0,a=V[t].data.length;a>i;i++)s=e[m],l=s.replace(" ","").split(","),"undefined"!=typeof V[t].data[i].value?V[t].data[i].value=l:V[t].data[i]=l,m++;else{s=e[m].split(",");for(var i=0,a=V[t].data.length;a>i;i++)l=(s[i]||"").replace(/.*:/,""),l=this._trim(l),l="-"!=l&&""!==l?l-0:"-","undefined"!=typeof V[t].data[i].value?V[t].data[i].value=l:V[t].data[i]=l;m++}},_trim:function(e){var t=new RegExp("(^[\\s\\t\\xa0\\u3000]+)|([\\u3000\\xa0\\s\\t]+$)","g");return e.replace(t,"")},_stop:function(e){e=e||window.event,e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},resize:function(){this._zrHeight=this.zr.getHeight(),this._zrWidth=this.zr.getWidth(),this._tDom.offsetHeight>10&&(this._sizeCssText="width:"+this._zrWidth+"px;height:"+this._zrHeight+"px;background-color:#fff;",this._tDom.style.cssText=this._gCssText+this._sizeCssText,this._textArea.style.cssText="display:block;margin:0 0 8px 0;padding:4px 6px;overflow:auto;width:100%;height:"+(this._zrHeight-100)+"px;")},dispose:function(){window.removeEventListener?(this._tDom.removeEventListener("click",this._stop),this._tDom.removeEventListener("mousewheel",this._stop),this._tDom.removeEventListener("mousemove",this._stop),this._tDom.removeEventListener("mousedown",this._stop),this._tDom.removeEventListener("mouseup",this._stop),this._tDom.removeEventListener("touchstart",this._stop),this._tDom.removeEventListener("touchmove",this._stop),this._tDom.removeEventListener("touchend",this._stop)):(this._tDom.detachEvent("onclick",this._stop),this._tDom.detachEvent("onmousewheel",this._stop),this._tDom.detachEvent("onmousemove",this._stop),this._tDom.detachEvent("onmousedown",this._stop),this._tDom.detachEvent("onmouseup",this._stop)),this._buttonRefresh.onclick=null,this._buttonClose.onclick=null,this._hasShow&&(this._tDom.removeChild(this._textArea),this._tDom.removeChild(this._buttonRefresh),this._tDom.removeChild(this._buttonClose)),this._textArea=null,this._buttonRefresh=null,this._buttonClose=null,this.dom.firstChild.removeChild(this._tDom),this._tDom=null}},a.inherits(t,i),e("../component").define("dataView",t),t}),i("echarts/util/shape/Cross",["require","zrender/shape/Base","zrender/shape/Line","zrender/tool/util","./normalIsCover"],function(e){function t(e){i.call(this,e)}var i=e("zrender/shape/Base"),n=e("zrender/shape/Line"),a=e("zrender/tool/util");return t.prototype={type:"cross",buildPath:function(e,t){var i=t.rect;t.xStart=i.x,t.xEnd=i.x+i.width,t.yStart=t.yEnd=t.y,n.prototype.buildPath(e,t),t.xStart=t.xEnd=t.x,t.yStart=i.y,t.yEnd=i.y+i.height,n.prototype.buildPath(e,t)},getRect:function(e){return e.rect},isCover:e("./normalIsCover")},a.inherits(t,i),t}),i("zrender/shape/Sector",["require","../tool/math","../tool/computeBoundingBox","../tool/vector","./Base","../tool/util"],function(e){var t=e("../tool/math"),i=e("../tool/computeBoundingBox"),n=e("../tool/vector"),a=e("./Base"),o=n.create(),r=n.create(),s=n.create(),l=n.create(),h=function(e){a.call(this,e)};return h.prototype={type:"sector",buildPath:function(e,i){var n=i.x,a=i.y,o=i.r0||0,r=i.r,s=i.startAngle,l=i.endAngle,h=i.clockWise||!1;s=t.degreeToRadian(s),l=t.degreeToRadian(l),h||(s=-s,l=-l);var m=t.cos(s),V=t.sin(s);e.moveTo(m*o+n,V*o+a),e.lineTo(m*r+n,V*r+a),e.arc(n,a,r,s,l,!h),e.lineTo(t.cos(l)*o+n,t.sin(l)*o+a),0!==o&&e.arc(n,a,o,l,s,h),e.closePath()},getRect:function(e){if(e.__rect)return e.__rect;var a=e.x,h=e.y,m=e.r0||0,V=e.r,U=t.degreeToRadian(e.startAngle),d=t.degreeToRadian(e.endAngle),p=e.clockWise;return p||(U=-U,d=-d),m>1?i.arc(a,h,m,U,d,!p,o,s):(o[0]=s[0]=a,o[1]=s[1]=h),i.arc(a,h,V,U,d,!p,r,l),n.min(o,o,r),n.max(s,s,l),e.__rect={x:o[0],y:o[1],width:s[0]-o[0],height:s[1]-o[1]},e.__rect}},e("../tool/util").inherits(h,a),h}),i("echarts/util/shape/Candle",["require","zrender/shape/Base","zrender/tool/util","./normalIsCover"],function(e){function t(e){i.call(this,e)}var i=e("zrender/shape/Base"),n=e("zrender/tool/util");return t.prototype={type:"candle",_numberOrder:function(e,t){return t-e},buildPath:function(e,t){var i=n.clone(t.y).sort(this._numberOrder);e.moveTo(t.x,i[3]),e.lineTo(t.x,i[2]),e.moveTo(t.x-t.width/2,i[2]),e.rect(t.x-t.width/2,i[2],t.width,i[1]-i[2]),e.moveTo(t.x,i[1]),e.lineTo(t.x,i[0])},getRect:function(e){if(!e.__rect){var t=0;("stroke"==e.brushType||"fill"==e.brushType)&&(t=e.lineWidth||1);var i=n.clone(e.y).sort(this._numberOrder);e.__rect={x:Math.round(e.x-e.width/2-t/2),y:Math.round(i[3]-t/2),width:e.width+t,height:i[0]-i[3]+t}}return e.__rect},isCover:e("./normalIsCover")},n.inherits(t,i),t}),i("zrender/tool/computeBoundingBox",["require","./vector","./curve"],function(e){function t(e,t,i){if(0!==e.length){for(var n=e[0][0],a=e[0][0],o=e[0][1],r=e[0][1],s=1;sa&&(a=l[0]),l[1]r&&(r=l[1])}t[0]=n,t[1]=o,i[0]=a,i[1]=r}}function i(e,t,i,n,a,r){var s=[];o.cubicExtrema(e[0],t[0],i[0],n[0],s);for(var l=0;l=2*Math.PI)return m[0]=e-i,m[1]=t-i,V[0]=e+i,void(V[1]=t+i);if(r[0]=Math.cos(n)*i+e,r[1]=Math.sin(n)*i+t,s[0]=Math.cos(o)*i+e,s[1]=Math.sin(o)*i+t,a.min(m,r,s),a.max(V,r,s),n%=2*Math.PI,0>n&&(n+=2*Math.PI),o%=2*Math.PI,0>o&&(o+=2*Math.PI),n>o&&!h?o+=2*Math.PI:o>n&&h&&(n+=2*Math.PI),h){var U=o;o=n,n=U}for(var d=0;o>d;d+=Math.PI/2)d>n&&(l[0]=Math.cos(d)*i+e,l[1]=Math.sin(d)*i+t,a.min(m,l,m),a.max(V,l,V))};return t.cubeBezier=i,t.quadraticBezier=n,t.arc=h,t}),i("echarts/util/shape/Chain",["require","zrender/shape/Base","./Icon","zrender/shape/util/dashedLineTo","zrender/tool/util","zrender/tool/matrix"],function(e){function t(e){i.call(this,e)}var i=e("zrender/shape/Base"),n=e("./Icon"),a=e("zrender/shape/util/dashedLineTo"),o=e("zrender/tool/util"),r=e("zrender/tool/matrix");return t.prototype={type:"chain",brush:function(e,t){var i=this.style;t&&(i=this.getHighlightStyle(i,this.highlightStyle||{})),e.save(),this.setContext(e,i),this.setTransform(e),e.save(),e.beginPath(),this.buildLinePath(e,i),e.stroke(),e.restore(),this.brushSymbol(e,i),e.restore()},buildLinePath:function(e,t){var i=t.x,n=t.y+5,o=t.width,r=t.height/2-10;if(e.moveTo(i,n),e.lineTo(i,n+r),e.moveTo(i+o,n),e.lineTo(i+o,n+r),e.moveTo(i,n+r/2),t.lineType&&"solid"!=t.lineType){if("dashed"==t.lineType||"dotted"==t.lineType){var s=(t.lineWidth||1)*("dashed"==t.lineType?5:1);a(e,i,n+r/2,i+o,n+r/2,s)}}else e.lineTo(i+o,n+r/2)},brushSymbol:function(e,t){var i=t.y+t.height/4;e.save();for(var a,o=t.chainPoint,r=0,s=o.length;s>r;r++){if(a=o[r],"none"!=a.symbol){e.beginPath();var l=a.symbolSize;n.prototype.buildPath(e,{iconType:a.symbol,x:a.x-l,y:i-l,width:2*l,height:2*l,n:a.n}),e.fillStyle=a.isEmpty?"#fff":t.strokeColor,e.closePath(),e.fill(),e.stroke()}a.showLabel&&(e.font=a.textFont,e.fillStyle=a.textColor,e.textAlign=a.textAlign,e.textBaseline=a.textBaseline,a.rotation?(e.save(),this._updateTextTransform(e,a.rotation),e.fillText(a.name,a.textX,a.textY),e.restore()):e.fillText(a.name,a.textX,a.textY))}e.restore()},_updateTextTransform:function(e,t){var i=r.create();if(r.identity(i),0!==t[0]){var n=t[1]||0,a=t[2]||0;(n||a)&&r.translate(i,i,[-n,-a]),r.rotate(i,i,t[0]),(n||a)&&r.translate(i,i,[n,a])}e.transform.apply(e,i)},isCover:function(e,t){var i=this.style;return e>=i.x&&e<=i.x+i.width&&t>=i.y&&t<=i.y+i.height?!0:!1}},o.inherits(t,i),t}),i("zrender/shape/Ring",["require","./Base","../tool/util"],function(e){var t=e("./Base"),i=function(e){t.call(this,e)};return i.prototype={type:"ring",buildPath:function(e,t){e.arc(t.x,t.y,t.r,0,2*Math.PI,!1),e.moveTo(t.x+t.r0,t.y),e.arc(t.x,t.y,t.r0,0,2*Math.PI,!0)},getRect:function(e){if(e.__rect)return e.__rect;var t;return t="stroke"==e.brushType||"fill"==e.brushType?e.lineWidth||1:0,e.__rect={x:Math.round(e.x-e.r-t/2),y:Math.round(e.y-e.r-t/2),width:2*e.r+t,height:2*e.r+t},e.__rect}},e("../tool/util").inherits(i,t),i}),i("echarts/component/axis",["require","./base","zrender/shape/Line","../config","../util/ecData","zrender/tool/util","zrender/tool/color","./categoryAxis","./valueAxis","../component"],function(e){function t(e,t,n,a,o,r){i.call(this,e,t,n,a,o),this.axisType=r,this._axisList=[],this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Line"),a=e("../config"),o=e("../util/ecData"),r=e("zrender/tool/util"),s=e("zrender/tool/color");return t.prototype={type:a.COMPONENT_TYPE_AXIS,axisBase:{_buildAxisLine:function(){var e=this.option.axisLine.lineStyle.width,t=e/2,i={_axisShape:"axisLine",zlevel:this.getZlevelBase(),z:this.getZBase()+3,hoverable:!1},a=this.grid;switch(this.option.position){case"left":i.style={xStart:a.getX()-t,yStart:a.getYend(),xEnd:a.getX()-t,yEnd:a.getY(),lineCap:"round"};break;case"right":i.style={xStart:a.getXend()+t,yStart:a.getYend(),xEnd:a.getXend()+t,yEnd:a.getY(),lineCap:"round"};break;case"bottom":i.style={xStart:a.getX(),yStart:a.getYend()+t,xEnd:a.getXend(),yEnd:a.getYend()+t,lineCap:"round"};break;case"top":i.style={xStart:a.getX(),yStart:a.getY()-t,xEnd:a.getXend(),yEnd:a.getY()-t,lineCap:"round"}}var o=i.style;""!==this.option.name&&(o.text=this.option.name,o.textPosition=this.option.nameLocation,o.textFont=this.getFont(this.option.nameTextStyle),this.option.nameTextStyle.align&&(o.textAlign=this.option.nameTextStyle.align),this.option.nameTextStyle.baseline&&(o.textBaseline=this.option.nameTextStyle.baseline),this.option.nameTextStyle.color&&(o.textColor=this.option.nameTextStyle.color)),o.strokeColor=this.option.axisLine.lineStyle.color,o.lineWidth=e,this.isHorizontal()?o.yStart=o.yEnd=this.subPixelOptimize(o.yEnd,e):o.xStart=o.xEnd=this.subPixelOptimize(o.xEnd,e),o.lineType=this.option.axisLine.lineStyle.type,i=new n(i),this.shapeList.push(i)},_axisLabelClickable:function(e,t){return e?(o.pack(t,void 0,-1,void 0,-1,t.style.text),t.hoverable=!0,t.clickable=!0,t.highlightStyle={color:s.lift(t.style.color,1),brushType:"fill"},t):t},refixAxisShape:function(e,t){if(this.option.axisLine.onZero){var i;if(this.isHorizontal()&&null!=t)for(var n=0,a=this.shapeList.length;a>n;n++)"axisLine"===this.shapeList[n]._axisShape?(this.shapeList[n].style.yStart=this.shapeList[n].style.yEnd=this.subPixelOptimize(t,this.shapeList[n].stylelineWidth),this.zr.modShape(this.shapeList[n].id)):"axisTick"===this.shapeList[n]._axisShape&&(i=this.shapeList[n].style.yEnd-this.shapeList[n].style.yStart,this.shapeList[n].style.yStart=t-i,this.shapeList[n].style.yEnd=t,this.zr.modShape(this.shapeList[n].id));if(!this.isHorizontal()&&null!=e)for(var n=0,a=this.shapeList.length;a>n;n++)"axisLine"===this.shapeList[n]._axisShape?(this.shapeList[n].style.xStart=this.shapeList[n].style.xEnd=this.subPixelOptimize(e,this.shapeList[n].stylelineWidth),this.zr.modShape(this.shapeList[n].id)):"axisTick"===this.shapeList[n]._axisShape&&(i=this.shapeList[n].style.xEnd-this.shapeList[n].style.xStart,this.shapeList[n].style.xStart=e,this.shapeList[n].style.xEnd=e+i,this.zr.modShape(this.shapeList[n].id))}},getPosition:function(){return this.option.position},isHorizontal:function(){return"bottom"===this.option.position||"top"===this.option.position}},reformOption:function(e){if(!e||e instanceof Array&&0===e.length?e=[{type:a.COMPONENT_TYPE_AXIS_VALUE}]:e instanceof Array||(e=[e]),e.length>2&&(e=[e[0],e[1]]),"xAxis"===this.axisType){(!e[0].position||"bottom"!=e[0].position&&"top"!=e[0].position)&&(e[0].position="bottom"),e.length>1&&(e[1].position="bottom"===e[0].position?"top":"bottom");for(var t=0,i=e.length;i>t;t++)e[t].type=e[t].type||"category",e[t].xAxisIndex=t,e[t].yAxisIndex=-1}else{(!e[0].position||"left"!=e[0].position&&"right"!=e[0].position)&&(e[0].position="left"),e.length>1&&(e[1].position="left"===e[0].position?"right":"left");for(var t=0,i=e.length;i>t;t++)e[t].type=e[t].type||"value",e[t].xAxisIndex=-1,e[t].yAxisIndex=t}return e},refresh:function(t){var i;t&&(this.option=t,"xAxis"===this.axisType?(this.option.xAxis=this.reformOption(t.xAxis),i=this.option.xAxis):(this.option.yAxis=this.reformOption(t.yAxis),i=this.option.yAxis),this.series=t.series);for(var n=e("./categoryAxis"),a=e("./valueAxis"),o=Math.max(i&&i.length||0,this._axisList.length),r=0;o>r;r++)!this._axisList[r]||!t||i[r]&&this._axisList[r].type==i[r].type||(this._axisList[r].dispose&&this._axisList[r].dispose(),this._axisList[r]=!1),this._axisList[r]?this._axisList[r].refresh&&this._axisList[r].refresh(i?i[r]:!1,this.series):i&&i[r]&&(this._axisList[r]="category"===i[r].type?new n(this.ecTheme,this.messageCenter,this.zr,i[r],this.myChart,this.axisBase):new a(this.ecTheme,this.messageCenter,this.zr,i[r],this.myChart,this.axisBase,this.series))},getAxis:function(e){return this._axisList[e]},getAxisCount:function(){return this._axisList.length},clear:function(){for(var e=0,t=this._axisList.length;t>e;e++)this._axisList[e].dispose&&this._axisList[e].dispose();this._axisList=[]}},r.inherits(t,i),e("../component").define("axis",t),t}),i("echarts/component/grid",["require","./base","zrender/shape/Rectangle","../config","zrender/tool/util","../component"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Rectangle"),a=e("../config");a.grid={zlevel:0,z:0,x:80,y:60,x2:80,y2:60,backgroundColor:"rgba(0,0,0,0)",borderWidth:1,borderColor:"#ccc"};var o=e("zrender/tool/util");return t.prototype={type:a.COMPONENT_TYPE_GRID,getX:function(){return this._x},getY:function(){return this._y},getWidth:function(){return this._width},getHeight:function(){return this._height},getXend:function(){return this._x+this._width},getYend:function(){return this._y+this._height},getArea:function(){return{x:this._x,y:this._y,width:this._width,height:this._height}},getBbox:function(){return[[this._x,this._y],[this.getXend(),this.getYend()]]},refixAxisShape:function(e){for(var t,i,n,o=e.xAxis._axisList.concat(e.yAxis?e.yAxis._axisList:[]),r=o.length;r--;)n=o[r],n.type==a.COMPONENT_TYPE_AXIS_VALUE&&n._min<0&&n._max>=0&&(n.isHorizontal()?t=n.getCoord(0):i=n.getCoord(0));if("undefined"!=typeof t||"undefined"!=typeof i)for(r=o.length;r--;)o[r].refixAxisShape(t,i)},refresh:function(e){if(e||this._zrWidth!=this.zr.getWidth()||this._zrHeight!=this.zr.getHeight()){this.clear(),this.option=e||this.option,this.option.grid=this.reformOption(this.option.grid);var t=this.option.grid;this._zrWidth=this.zr.getWidth(),this._zrHeight=this.zr.getHeight(),this._x=this.parsePercent(t.x,this._zrWidth),this._y=this.parsePercent(t.y,this._zrHeight);var i=this.parsePercent(t.x2,this._zrWidth),a=this.parsePercent(t.y2,this._zrHeight);this._width="undefined"==typeof t.width?this._zrWidth-this._x-i:this.parsePercent(t.width,this._zrWidth),this._width=this._width<=0?10:this._width,this._height="undefined"==typeof t.height?this._zrHeight-this._y-a:this.parsePercent(t.height,this._zrHeight),this._height=this._height<=0?10:this._height,this._x=this.subPixelOptimize(this._x,t.borderWidth),this._y=this.subPixelOptimize(this._y,t.borderWidth),this.shapeList.push(new n({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._x,y:this._y,width:this._width,height:this._height,brushType:t.borderWidth>0?"both":"fill",color:t.backgroundColor,strokeColor:t.borderColor,lineWidth:t.borderWidth}})),this.zr.addShape(this.shapeList[0])}}},o.inherits(t,i),e("../component").define("grid",t),t}),i("echarts/component/dataZoom",["require","./base","zrender/shape/Rectangle","zrender/shape/Polygon","../util/shape/Icon","../config","../util/date","zrender/tool/util","../component"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o);var r=this;r._ondrift=function(e,t){return r.__ondrift(this,e,t)},r._ondragend=function(){return r.__ondragend()},this._fillerSize=30,this._isSilence=!1,this._zoom={},this.option.dataZoom=this.reformOption(this.option.dataZoom),this.zoomOption=this.option.dataZoom,this._handleSize=this.zoomOption.handleSize,this.myChart.canvasSupported||(this.zoomOption.realtime=!1),this._location=this._getLocation(),this._zoom=this._getZoom(),this._backupData(),this.option.dataZoom.show&&this._buildShape(),this._syncData()}var i=e("./base"),n=e("zrender/shape/Rectangle"),a=e("zrender/shape/Polygon"),o=e("../util/shape/Icon"),r=e("../config");r.dataZoom={zlevel:0,z:4,show:!1,orient:"horizontal",backgroundColor:"rgba(0,0,0,0)",dataBackgroundColor:"#eee",fillerColor:"rgba(144,197,237,0.2)",handleColor:"rgba(70,130,180,0.8)",handleSize:8,showDetail:!0,realtime:!0};var s=e("../util/date"),l=e("zrender/tool/util");return t.prototype={type:r.COMPONENT_TYPE_DATAZOOM,_buildShape:function(){this._buildBackground(),this._buildFiller(),this._buildHandle(),this._buildFrame();for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e]);this._syncFrameShape()},_getLocation:function(){var e,t,i,n,a=this.component.grid;return"horizontal"==this.zoomOption.orient?(i=this.zoomOption.width||a.getWidth(),n=this.zoomOption.height||this._fillerSize,e=null!=this.zoomOption.x?this.zoomOption.x:a.getX(),t=null!=this.zoomOption.y?this.zoomOption.y:this.zr.getHeight()-n-2):(i=this.zoomOption.width||this._fillerSize,n=this.zoomOption.height||a.getHeight(),e=null!=this.zoomOption.x?this.zoomOption.x:2,t=null!=this.zoomOption.y?this.zoomOption.y:a.getY()),{x:e,y:t,width:i,height:n}},_getZoom:function(){var e=this.option.series,t=this.option.xAxis;!t||t instanceof Array||(t=[t],this.option.xAxis=t);var i=this.option.yAxis;!i||i instanceof Array||(i=[i],this.option.yAxis=i);var n,a,o=[],s=this.zoomOption.xAxisIndex;if(t&&null==s){n=[];for(var l=0,h=t.length;h>l;l++)("category"==t[l].type||null==t[l].type)&&n.push(l)}else n=s instanceof Array?s:null!=s?[s]:[];if(s=this.zoomOption.yAxisIndex,i&&null==s){a=[];for(var l=0,h=i.length;h>l;l++)"category"==i[l].type&&a.push(l)}else a=s instanceof Array?s:null!=s?[s]:[];for(var m,l=0,h=e.length;h>l;l++)if(m=e[l],m.type==r.CHART_TYPE_LINE||m.type==r.CHART_TYPE_BAR||m.type==r.CHART_TYPE_SCATTER||m.type==r.CHART_TYPE_K){for(var V=0,U=n.length;U>V;V++)if(n[V]==(m.xAxisIndex||0)){o.push(l);break}for(var V=0,U=a.length;U>V;V++)if(a[V]==(m.yAxisIndex||0)){o.push(l);break}null==this.zoomOption.xAxisIndex&&null==this.zoomOption.yAxisIndex&&m.data&&this.getDataFromOption(m.data[0])instanceof Array&&(m.type==r.CHART_TYPE_SCATTER||m.type==r.CHART_TYPE_LINE||m.type==r.CHART_TYPE_BAR)&&o.push(l)}var d=null!=this._zoom.start?this._zoom.start:null!=this.zoomOption.start?this.zoomOption.start:0,p=null!=this._zoom.end?this._zoom.end:null!=this.zoomOption.end?this.zoomOption.end:100;d>p&&(d+=p,p=d-p,d-=p);var c=Math.round((p-d)/100*("horizontal"==this.zoomOption.orient?this._location.width:this._location.height));return{start:d,end:p,start2:0,end2:100,size:c,xAxisIndex:n,yAxisIndex:a,seriesIndex:o,scatterMap:this._zoom.scatterMap||{}}},_backupData:function(){this._originalData={xAxis:{},yAxis:{},series:{}};for(var e=this.option.xAxis,t=this._zoom.xAxisIndex,i=0,n=t.length;n>i;i++)this._originalData.xAxis[t[i]]=e[t[i]].data;for(var a=this.option.yAxis,o=this._zoom.yAxisIndex,i=0,n=o.length;n>i;i++)this._originalData.yAxis[o[i]]=a[o[i]].data;for(var s,l=this.option.series,h=this._zoom.seriesIndex,i=0,n=h.length;n>i;i++)s=l[h[i]],this._originalData.series[h[i]]=s.data,s.data&&this.getDataFromOption(s.data[0])instanceof Array&&(s.type==r.CHART_TYPE_SCATTER||s.type==r.CHART_TYPE_LINE||s.type==r.CHART_TYPE_BAR)&&(this._backupScale(),this._calculScatterMap(h[i]))},_calculScatterMap:function(t){this._zoom.scatterMap=this._zoom.scatterMap||{},this._zoom.scatterMap[t]=this._zoom.scatterMap[t]||{};var i=e("../component"),n=i.get("axis"),a=l.clone(this.option.xAxis);"category"==a[0].type&&(a[0].type="value"),a[1]&&"category"==a[1].type&&(a[1].type="value");var o=new n(this.ecTheme,null,!1,{xAxis:a,series:this.option.series},this,"xAxis"),r=this.option.series[t].xAxisIndex||0;this._zoom.scatterMap[t].x=o.getAxis(r).getExtremum(),o.dispose(),a=l.clone(this.option.yAxis),"category"==a[0].type&&(a[0].type="value"),a[1]&&"category"==a[1].type&&(a[1].type="value"),o=new n(this.ecTheme,null,!1,{yAxis:a,series:this.option.series},this,"yAxis"),r=this.option.series[t].yAxisIndex||0,this._zoom.scatterMap[t].y=o.getAxis(r).getExtremum(),o.dispose()},_buildBackground:function(){var e=this._location.width,t=this._location.height;this.shapeList.push(new n({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._location.x,y:this._location.y,width:e,height:t,color:this.zoomOption.backgroundColor}}));for(var i=0,o=this._originalData.xAxis,s=this._zoom.xAxisIndex,l=0,h=s.length;h>l;l++)i=Math.max(i,o[s[l]].length);for(var m=this._originalData.yAxis,V=this._zoom.yAxisIndex,l=0,h=V.length;h>l;l++)i=Math.max(i,m[V[l]].length);for(var U,d=this._zoom.seriesIndex[0],p=this._originalData.series[d],c=Number.MIN_VALUE,u=Number.MAX_VALUE,l=0,h=p.length;h>l;l++)U=this.getDataFromOption(p[l],0),this.option.series[d].type==r.CHART_TYPE_K&&(U=U[1]),isNaN(U)&&(U=0),c=Math.max(c,U),u=Math.min(u,U);var y=c-u,g=[],b=e/(i-(i>1?1:0)),f=t/(i-(i>1?1:0)),k=1;"horizontal"==this.zoomOption.orient&&1>b?k=Math.floor(3*i/e):"vertical"==this.zoomOption.orient&&1>f&&(k=Math.floor(3*i/t));for(var l=0,h=i;h>l;l+=k)U=this.getDataFromOption(p[l],0),this.option.series[d].type==r.CHART_TYPE_K&&(U=U[1]),isNaN(U)&&(U=0),g.push("horizontal"==this.zoomOption.orient?[this._location.x+b*l,this._location.y+t-1-Math.round((U-u)/y*(t-10))]:[this._location.x+1+Math.round((U-u)/y*(e-10)),this._location.y+f*(h-l-1)]);"horizontal"==this.zoomOption.orient?(g.push([this._location.x+e,this._location.y+t]),g.push([this._location.x,this._location.y+t])):(g.push([this._location.x,this._location.y]),g.push([this._location.x,this._location.y+t])),this.shapeList.push(new a({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{pointList:g,color:this.zoomOption.dataBackgroundColor},hoverable:!1}))},_buildFiller:function(){this._fillerShae={zlevel:this.getZlevelBase(),z:this.getZBase(),draggable:!0,ondrift:this._ondrift,ondragend:this._ondragend,_type:"filler"},this._fillerShae.style="horizontal"==this.zoomOption.orient?{x:this._location.x+Math.round(this._zoom.start/100*this._location.width)+this._handleSize,y:this._location.y,width:this._zoom.size-2*this._handleSize,height:this._location.height,color:this.zoomOption.fillerColor,text:":::",textPosition:"inside"}:{x:this._location.x,y:this._location.y+Math.round(this._zoom.start/100*this._location.height)+this._handleSize,width:this._location.width,height:this._zoom.size-2*this._handleSize,color:this.zoomOption.fillerColor,text:"::",textPosition:"inside"},this._fillerShae.highlightStyle={brushType:"fill",color:"rgba(0,0,0,0)"},this._fillerShae=new n(this._fillerShae),this.shapeList.push(this._fillerShae)},_buildHandle:function(){var e=this.zoomOption.showDetail?this._getDetail():{start:"",end:""};this._startShape={zlevel:this.getZlevelBase(),z:this.getZBase(),draggable:!0,style:{iconType:"rectangle",x:this._location.x,y:this._location.y,width:this._handleSize,height:this._handleSize,color:this.zoomOption.handleColor,text:"=",textPosition:"inside"},highlightStyle:{text:e.start,brushType:"fill",textPosition:"left"},ondrift:this._ondrift,ondragend:this._ondragend},"horizontal"==this.zoomOption.orient?(this._startShape.style.height=this._location.height,this._endShape=l.clone(this._startShape),this._startShape.style.x=this._fillerShae.style.x-this._handleSize,this._endShape.style.x=this._fillerShae.style.x+this._fillerShae.style.width,this._endShape.highlightStyle.text=e.end,this._endShape.highlightStyle.textPosition="right"):(this._startShape.style.width=this._location.width,this._endShape=l.clone(this._startShape),this._startShape.style.y=this._fillerShae.style.y+this._fillerShae.style.height,this._startShape.highlightStyle.textPosition="bottom",this._endShape.style.y=this._fillerShae.style.y-this._handleSize,this._endShape.highlightStyle.text=e.end,this._endShape.highlightStyle.textPosition="top"),this._startShape=new o(this._startShape),this._endShape=new o(this._endShape),this.shapeList.push(this._startShape),this.shapeList.push(this._endShape)},_buildFrame:function(){var e=this.subPixelOptimize(this._location.x,1),t=this.subPixelOptimize(this._location.y,1);this._startFrameShape={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:e,y:t,width:this._location.width-(e>this._location.x?1:0),height:this._location.height-(t>this._location.y?1:0),lineWidth:1,brushType:"stroke",strokeColor:this.zoomOption.handleColor}},this._endFrameShape=l.clone(this._startFrameShape),this._startFrameShape=new n(this._startFrameShape),this._endFrameShape=new n(this._endFrameShape),this.shapeList.push(this._startFrameShape),this.shapeList.push(this._endFrameShape)},_syncHandleShape:function(){"horizontal"==this.zoomOption.orient?(this._startShape.style.x=this._fillerShae.style.x-this._handleSize,this._endShape.style.x=this._fillerShae.style.x+this._fillerShae.style.width,this._zoom.start=(this._startShape.style.x-this._location.x)/this._location.width*100,this._zoom.end=(this._endShape.style.x+this._handleSize-this._location.x)/this._location.width*100):(this._startShape.style.y=this._fillerShae.style.y+this._fillerShae.style.height,this._endShape.style.y=this._fillerShae.style.y-this._handleSize,this._zoom.start=(this._location.y+this._location.height-this._startShape.style.y)/this._location.height*100,this._zoom.end=(this._location.y+this._location.height-this._endShape.style.y-this._handleSize)/this._location.height*100),this.zr.modShape(this._startShape.id),this.zr.modShape(this._endShape.id),this._syncFrameShape(),this.zr.refreshNextFrame()},_syncFillerShape:function(){var e,t;"horizontal"==this.zoomOption.orient?(e=this._startShape.style.x,t=this._endShape.style.x,this._fillerShae.style.x=Math.min(e,t)+this._handleSize,this._fillerShae.style.width=Math.abs(e-t)-this._handleSize,this._zoom.start=(Math.min(e,t)-this._location.x)/this._location.width*100,this._zoom.end=(Math.max(e,t)+this._handleSize-this._location.x)/this._location.width*100):(e=this._startShape.style.y,t=this._endShape.style.y,this._fillerShae.style.y=Math.min(e,t)+this._handleSize,this._fillerShae.style.height=Math.abs(e-t)-this._handleSize,this._zoom.start=(this._location.y+this._location.height-Math.max(e,t))/this._location.height*100,this._zoom.end=(this._location.y+this._location.height-Math.min(e,t)-this._handleSize)/this._location.height*100),this.zr.modShape(this._fillerShae.id),this._syncFrameShape(),this.zr.refreshNextFrame()},_syncFrameShape:function(){"horizontal"==this.zoomOption.orient?(this._startFrameShape.style.width=this._fillerShae.style.x-this._location.x,this._endFrameShape.style.x=this._fillerShae.style.x+this._fillerShae.style.width,this._endFrameShape.style.width=this._location.x+this._location.width-this._endFrameShape.style.x):(this._startFrameShape.style.y=this._fillerShae.style.y+this._fillerShae.style.height,this._startFrameShape.style.height=this._location.y+this._location.height-this._startFrameShape.style.y,this._endFrameShape.style.height=this._fillerShae.style.y-this._location.y),this.zr.modShape(this._startFrameShape.id),this.zr.modShape(this._endFrameShape.id)},_syncShape:function(){this.zoomOption.show&&("horizontal"==this.zoomOption.orient?(this._startShape.style.x=this._location.x+this._zoom.start/100*this._location.width,this._endShape.style.x=this._location.x+this._zoom.end/100*this._location.width-this._handleSize,this._fillerShae.style.x=this._startShape.style.x+this._handleSize,this._fillerShae.style.width=this._endShape.style.x-this._startShape.style.x-this._handleSize):(this._startShape.style.y=this._location.y+this._location.height-this._zoom.start/100*this._location.height,this._endShape.style.y=this._location.y+this._location.height-this._zoom.end/100*this._location.height-this._handleSize,this._fillerShae.style.y=this._endShape.style.y+this._handleSize,this._fillerShae.style.height=this._startShape.style.y-this._endShape.style.y-this._handleSize),this.zr.modShape(this._startShape.id),this.zr.modShape(this._endShape.id),this.zr.modShape(this._fillerShae.id),this._syncFrameShape(),this.zr.refresh())},_syncData:function(e){var t,i,n,a,o;for(var s in this._originalData){t=this._originalData[s];for(var l in t)o=t[l],null!=o&&(a=o.length,i=Math.floor(this._zoom.start/100*a),n=Math.ceil(this._zoom.end/100*a),this.getDataFromOption(o[0])instanceof Array&&this.option[s][l].type!=r.CHART_TYPE_K?(this._setScale(),this.option[s][l].data=this._synScatterData(l,o)):this.option[s][l].data=o.slice(i,n))}this._isSilence||!this.zoomOption.realtime&&!e||this.messageCenter.dispatch(r.EVENT.DATA_ZOOM,null,{zoom:this._zoom},this.myChart)},_synScatterData:function(e,t){if(0===this._zoom.start&&100==this._zoom.end&&0===this._zoom.start2&&100==this._zoom.end2)return t;var i,n,a,o,r,s=[],l=this._zoom.scatterMap[e]; - -"horizontal"==this.zoomOption.orient?(i=l.x.max-l.x.min,n=this._zoom.start/100*i+l.x.min,a=this._zoom.end/100*i+l.x.min,i=l.y.max-l.y.min,o=this._zoom.start2/100*i+l.y.min,r=this._zoom.end2/100*i+l.y.min):(i=l.x.max-l.x.min,n=this._zoom.start2/100*i+l.x.min,a=this._zoom.end2/100*i+l.x.min,i=l.y.max-l.y.min,o=this._zoom.start/100*i+l.y.min,r=this._zoom.end/100*i+l.y.min);var h;(h=l.x.dataMappingMethods)&&(n=h.coord2Value(n),a=h.coord2Value(a)),(h=l.y.dataMappingMethods)&&(o=h.coord2Value(o),r=h.coord2Value(r));for(var m,V=0,U=t.length;U>V;V++)m=t[V].value||t[V],m[0]>=n&&m[0]<=a&&m[1]>=o&&m[1]<=r&&s.push(t[V]);return s},_setScale:function(){var e=0!==this._zoom.start||100!==this._zoom.end||0!==this._zoom.start2||100!==this._zoom.end2,t={xAxis:this.option.xAxis,yAxis:this.option.yAxis};for(var i in t)for(var n=0,a=t[i].length;a>n;n++)t[i][n].scale=e||t[i][n]._scale},_backupScale:function(){var e={xAxis:this.option.xAxis,yAxis:this.option.yAxis};for(var t in e)for(var i=0,n=e[t].length;n>i;i++)e[t][i]._scale=e[t][i].scale},_getDetail:function(){for(var e=["xAxis","yAxis"],t=0,i=e.length;i>t;t++){var n=this._originalData[e[t]];for(var a in n){var o=n[a];if(null!=o){var r=o.length,l=Math.floor(this._zoom.start/100*r),h=Math.ceil(this._zoom.end/100*r);return h-=h>0?1:0,{start:this.getDataFromOption(o[l]),end:this.getDataFromOption(o[h])}}}}e="horizontal"==this.zoomOption.orient?"xAxis":"yAxis";var m=this._zoom.seriesIndex[0],V=this.option.series[m][e+"Index"]||0,U=this.option[e][V].type,d=this._zoom.scatterMap[m][e.charAt(0)].min,p=this._zoom.scatterMap[m][e.charAt(0)].max,c=p-d;if("value"==U)return{start:d+c*this._zoom.start/100,end:d+c*this._zoom.end/100};if("time"==U){p=d+c*this._zoom.end/100,d+=c*this._zoom.start/100;var u=s.getAutoFormatter(d,p).formatter;return{start:s.format(u,d),end:s.format(u,p)}}return{start:"",end:""}},__ondrift:function(e,t,i){this.zoomOption.zoomLock&&(e=this._fillerShae);var n="filler"==e._type?this._handleSize:0;if("horizontal"==this.zoomOption.orient?e.style.x+t-n<=this._location.x?e.style.x=this._location.x+n:e.style.x+t+e.style.width+n>=this._location.x+this._location.width?e.style.x=this._location.x+this._location.width-e.style.width-n:e.style.x+=t:e.style.y+i-n<=this._location.y?e.style.y=this._location.y+n:e.style.y+i+e.style.height+n>=this._location.y+this._location.height?e.style.y=this._location.y+this._location.height-e.style.height-n:e.style.y+=i,"filler"==e._type?this._syncHandleShape():this._syncFillerShape(),this.zoomOption.realtime&&this._syncData(),this.zoomOption.showDetail){var a=this._getDetail();this._startShape.style.text=this._startShape.highlightStyle.text=a.start,this._endShape.style.text=this._endShape.highlightStyle.text=a.end,this._startShape.style.textPosition=this._startShape.highlightStyle.textPosition,this._endShape.style.textPosition=this._endShape.highlightStyle.textPosition}return!0},__ondragend:function(){this.zoomOption.showDetail&&(this._startShape.style.text=this._endShape.style.text="=",this._startShape.style.textPosition=this._endShape.style.textPosition="inside",this.zr.modShape(this._startShape.id),this.zr.modShape(this._endShape.id),this.zr.refreshNextFrame()),this.isDragend=!0},ondragend:function(e,t){this.isDragend&&e.target&&(!this.zoomOption.realtime&&this._syncData(),t.dragOut=!0,t.dragIn=!0,this._isSilence||this.zoomOption.realtime||this.messageCenter.dispatch(r.EVENT.DATA_ZOOM,null,{zoom:this._zoom},this.myChart),t.needRefresh=!1,this.isDragend=!1)},ondataZoom:function(e,t){t.needRefresh=!0},absoluteZoom:function(e){this._zoom.start=e.start,this._zoom.end=e.end,this._zoom.start2=e.start2,this._zoom.end2=e.end2,this._syncShape(),this._syncData(!0)},rectZoom:function(e){if(!e)return this._zoom.start=this._zoom.start2=0,this._zoom.end=this._zoom.end2=100,this._syncShape(),this._syncData(!0),this._zoom;var t=this.component.grid.getArea(),i={x:e.x,y:e.y,width:e.width,height:e.height};if(i.width<0&&(i.x+=i.width,i.width=-i.width),i.height<0&&(i.y+=i.height,i.height=-i.height),i.x>t.x+t.width||i.y>t.y+t.height)return!1;i.xt.x+t.width&&(i.width=t.x+t.width-i.x),i.y+i.height>t.y+t.height&&(i.height=t.y+t.height-i.y);var n,a=(i.x-t.x)/t.width,o=1-(i.x+i.width-t.x)/t.width,r=1-(i.y+i.height-t.y)/t.height,s=(i.y-t.y)/t.height;return"horizontal"==this.zoomOption.orient?(n=this._zoom.end-this._zoom.start,this._zoom.start+=n*a,this._zoom.end-=n*o,n=this._zoom.end2-this._zoom.start2,this._zoom.start2+=n*r,this._zoom.end2-=n*s):(n=this._zoom.end-this._zoom.start,this._zoom.start+=n*r,this._zoom.end-=n*s,n=this._zoom.end2-this._zoom.start2,this._zoom.start2+=n*a,this._zoom.end2-=n*o),this._syncShape(),this._syncData(!0),this._zoom},syncBackupData:function(e){for(var t,i,n=this._originalData.series,a=e.series,o=0,r=a.length;r>o;o++){i=a[o].data||a[o].eventList,t=n[o]?Math.floor(this._zoom.start/100*n[o].length):0;for(var s=0,l=i.length;l>s;s++)n[o]&&(n[o][s+t]=i[s])}},syncOption:function(e){this.silence(!0),this.option=e,this.option.dataZoom=this.reformOption(this.option.dataZoom),this.zoomOption=this.option.dataZoom,this.myChart.canvasSupported||(this.zoomOption.realtime=!1),this.clear(),this._location=this._getLocation(),this._zoom=this._getZoom(),this._backupData(),this.option.dataZoom&&this.option.dataZoom.show&&this._buildShape(),this._syncData(),this.silence(!1)},silence:function(e){this._isSilence=e},getRealDataIndex:function(e,t){if(!this._originalData||0===this._zoom.start&&100==this._zoom.end)return t;var i=this._originalData.series;return i[e]?Math.floor(this._zoom.start/100*i[e].length)+t:-1},resize:function(){this.clear(),this._location=this._getLocation(),this._zoom=this._getZoom(),this.option.dataZoom.show&&this._buildShape()}},l.inherits(t,i),e("../component").define("dataZoom",t),t}),i("echarts/component/categoryAxis",["require","./base","zrender/shape/Text","zrender/shape/Line","zrender/shape/Rectangle","../config","zrender/tool/util","zrender/tool/area","../component"],function(e){function t(e,t,n,a,o,r){if(a.data.length<1)return void console.error("option.data.length < 1.");i.call(this,e,t,n,a,o),this.grid=this.component.grid;for(var s in r)this[s]=r[s];this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Line"),o=e("zrender/shape/Rectangle"),r=e("../config");r.categoryAxis={zlevel:0,z:0,show:!0,position:"bottom",name:"",nameLocation:"end",nameTextStyle:{},boundaryGap:!0,axisLine:{show:!0,onZero:!0,lineStyle:{color:"#48b",width:2,type:"solid"}},axisTick:{show:!0,interval:"auto",inside:!1,length:5,lineStyle:{color:"#333",width:1}},axisLabel:{show:!0,interval:"auto",rotate:0,margin:8,textStyle:{color:"#333"}},splitLine:{show:!0,lineStyle:{color:["#ccc"],width:1,type:"solid"}},splitArea:{show:!1,areaStyle:{color:["rgba(250,250,250,0.3)","rgba(200,200,200,0.3)"]}}};var s=e("zrender/tool/util"),l=e("zrender/tool/area");return t.prototype={type:r.COMPONENT_TYPE_AXIS_CATEGORY,_getReformedLabel:function(e){var t=this.getDataFromOption(this.option.data[e]),i=this.option.data[e].formatter||this.option.axisLabel.formatter;return i&&("function"==typeof i?t=i.call(this.myChart,t):"string"==typeof i&&(t=i.replace("{value}",t))),t},_getInterval:function(){var e=this.option.axisLabel.interval;if("auto"==e){var t=this.option.axisLabel.textStyle.fontSize,i=this.option.data,n=this.option.data.length;if(this.isHorizontal())if(n>3){var a,o,r=this.getGap(),h=!1,m=Math.floor(.5/r);for(m=1>m?1:m,e=Math.floor(15/r);!h&&n>e;){e+=m,h=!0,a=Math.floor(r*e);for(var V=Math.floor((n-1)/e)*e;V>=0;V-=e){if(0!==this.option.axisLabel.rotate)o=t;else if(i[V].textStyle)o=l.getTextWidth(this._getReformedLabel(V),this.getFont(s.merge(i[V].textStyle,this.option.axisLabel.textStyle)));else{var U=this._getReformedLabel(V)+"",d=(U.match(/\w/g)||"").length,p=U.length-d;o=d*t*2/3+p*t}if(o>a){h=!1;break}}}}else e=1;else if(n>3){var r=this.getGap();for(e=Math.floor(11/r);t>r*e-6&&n>e;)e++}else e=1}else e="function"==typeof e?1:e-0+1;return e},_buildShape:function(){if(this._interval=this._getInterval(),this.option.show){this.option.splitArea.show&&this._buildSplitArea(),this.option.splitLine.show&&this._buildSplitLine(),this.option.axisLine.show&&this._buildAxisLine(),this.option.axisTick.show&&this._buildAxisTick(),this.option.axisLabel.show&&this._buildAxisLabel();for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e])}},_buildAxisTick:function(){var e,t=this.option.data,i=this.option.data.length,n=this.option.axisTick,o=n.length,r=n.lineStyle.color,s=n.lineStyle.width,l="function"==typeof n.interval?n.interval:"auto"==n.interval&&"function"==typeof this.option.axisLabel.interval?this.option.axisLabel.interval:!1,h=l?1:"auto"==n.interval?this._interval:n.interval-0+1,m=n.onGap,V=m?this.getGap()/2:"undefined"==typeof m&&this.option.boundaryGap?this.getGap()/2:0,U=V>0?-h:0;if(this.isHorizontal())for(var d,p="bottom"==this.option.position?n.inside?this.grid.getYend()-o-1:this.grid.getYend()+1:n.inside?this.grid.getY()+1:this.grid.getY()-o-1,c=U;i>c;c+=h)(!l||l(c,t[c]))&&(d=this.subPixelOptimize(this.getCoordByIndex(c)+(c>=0?V:0),s),e={_axisShape:"axisTick",zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:d,yStart:p,xEnd:d,yEnd:p+o,strokeColor:r,lineWidth:s}},this.shapeList.push(new a(e)));else for(var u,y="left"==this.option.position?n.inside?this.grid.getX()+1:this.grid.getX()-o-1:n.inside?this.grid.getXend()-o-1:this.grid.getXend()+1,c=U;i>c;c+=h)(!l||l(c,t[c]))&&(u=this.subPixelOptimize(this.getCoordByIndex(c)-(c>=0?V:0),s),e={_axisShape:"axisTick",zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:y,yStart:u,xEnd:y+o,yEnd:u,strokeColor:r,lineWidth:s}},this.shapeList.push(new a(e)))},_buildAxisLabel:function(){var e,t,i=this.option.data,a=this.option.data.length,o=this.option.axisLabel,r=o.rotate,l=o.margin,h=o.clickable,m=o.textStyle,V="function"==typeof o.interval?o.interval:!1;if(this.isHorizontal()){var U,d;"bottom"==this.option.position?(U=this.grid.getYend()+l,d="top"):(U=this.grid.getY()-l,d="bottom");for(var p=0;a>p;p+=this._interval)V&&!V(p,i[p])||""===this._getReformedLabel(p)||(t=s.merge(i[p].textStyle||{},m),e={zlevel:this.getZlevelBase(),z:this.getZBase()+3,hoverable:!1,style:{x:this.getCoordByIndex(p),y:U,color:t.color,text:this._getReformedLabel(p),textFont:this.getFont(t),textAlign:t.align||"center",textBaseline:t.baseline||d}},r&&(e.style.textAlign=r>0?"bottom"==this.option.position?"right":"left":"bottom"==this.option.position?"left":"right",e.rotation=[r*Math.PI/180,e.style.x,e.style.y]),this.shapeList.push(new n(this._axisLabelClickable(h,e))))}else{var c,u;"left"==this.option.position?(c=this.grid.getX()-l,u="right"):(c=this.grid.getXend()+l,u="left");for(var p=0;a>p;p+=this._interval)V&&!V(p,i[p])||""===this._getReformedLabel(p)||(t=s.merge(i[p].textStyle||{},m),e={zlevel:this.getZlevelBase(),z:this.getZBase()+3,hoverable:!1,style:{x:c,y:this.getCoordByIndex(p),color:t.color,text:this._getReformedLabel(p),textFont:this.getFont(t),textAlign:t.align||u,textBaseline:t.baseline||0===p&&""!==this.option.name?"bottom":p==a-1&&""!==this.option.name?"top":"middle"}},r&&(e.rotation=[r*Math.PI/180,e.style.x,e.style.y]),this.shapeList.push(new n(this._axisLabelClickable(h,e))))}},_buildSplitLine:function(){var e,t=this.option.data,i=this.option.data.length,n=this.option.splitLine,o=n.lineStyle.type,r=n.lineStyle.width,s=n.lineStyle.color;s=s instanceof Array?s:[s];var l=s.length,h="function"==typeof this.option.axisLabel.interval?this.option.axisLabel.interval:!1,m=n.onGap,V=m?this.getGap()/2:"undefined"==typeof m&&this.option.boundaryGap?this.getGap()/2:0;if(i-=m||"undefined"==typeof m&&this.option.boundaryGap?1:0,this.isHorizontal())for(var U,d=this.grid.getY(),p=this.grid.getYend(),c=0;i>c;c+=this._interval)(!h||h(c,t[c]))&&(U=this.subPixelOptimize(this.getCoordByIndex(c)+V,r),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:U,yStart:d,xEnd:U,yEnd:p,strokeColor:s[c/this._interval%l],lineType:o,lineWidth:r}},this.shapeList.push(new a(e)));else for(var u,y=this.grid.getX(),g=this.grid.getXend(),c=0;i>c;c+=this._interval)(!h||h(c,t[c]))&&(u=this.subPixelOptimize(this.getCoordByIndex(c)-V,r),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:y,yStart:u,xEnd:g,yEnd:u,strokeColor:s[c/this._interval%l],lineType:o,lineWidth:r}},this.shapeList.push(new a(e)))},_buildSplitArea:function(){var e,t=this.option.data,i=this.option.splitArea,n=i.areaStyle.color;if(n instanceof Array){var a=n.length,r=this.option.data.length,s="function"==typeof this.option.axisLabel.interval?this.option.axisLabel.interval:!1,l=i.onGap,h=l?this.getGap()/2:"undefined"==typeof l&&this.option.boundaryGap?this.getGap()/2:0;if(this.isHorizontal())for(var m,V=this.grid.getY(),U=this.grid.getHeight(),d=this.grid.getX(),p=0;r>=p;p+=this._interval)s&&!s(p,t[p])&&r>p||(m=r>p?this.getCoordByIndex(p)+h:this.grid.getXend(),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:d,y:V,width:m-d,height:U,color:n[p/this._interval%a]}},this.shapeList.push(new o(e)),d=m);else for(var c,u=this.grid.getX(),y=this.grid.getWidth(),g=this.grid.getYend(),p=0;r>=p;p+=this._interval)s&&!s(p,t[p])&&r>p||(c=r>p?this.getCoordByIndex(p)-h:this.grid.getY(),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:u,y:c,width:y,height:g-c,color:n[p/this._interval%a]}},this.shapeList.push(new o(e)),g=c)}else e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this.grid.getX(),y:this.grid.getY(),width:this.grid.getWidth(),height:this.grid.getHeight(),color:n}},this.shapeList.push(new o(e))},refresh:function(e){e&&(this.option=this.reformOption(e),this.option.axisLabel.textStyle=this.getTextStyle(this.option.axisLabel.textStyle)),this.clear(),this._buildShape()},getGap:function(){var e=this.option.data.length,t=this.isHorizontal()?this.grid.getWidth():this.grid.getHeight();return this.option.boundaryGap?t/e:t/(e>1?e-1:1)},getCoord:function(e){for(var t=this.option.data,i=t.length,n=this.getGap(),a=this.option.boundaryGap?n/2:0,o=0;i>o;o++){if(this.getDataFromOption(t[o])==e)return a=this.isHorizontal()?this.grid.getX()+a:this.grid.getYend()-a;a+=n}},getCoordByIndex:function(e){if(0>e)return this.isHorizontal()?this.grid.getX():this.grid.getYend();if(e>this.option.data.length-1)return this.isHorizontal()?this.grid.getXend():this.grid.getY();var t=this.getGap(),i=this.option.boundaryGap?t/2:0;return i+=e*t,i=this.isHorizontal()?this.grid.getX()+i:this.grid.getYend()-i},getNameByIndex:function(e){return this.getDataFromOption(this.option.data[e])},getIndexByName:function(e){for(var t=this.option.data,i=t.length,n=0;i>n;n++)if(this.getDataFromOption(t[n])==e)return n;return-1},getValueFromCoord:function(){return""},isMainAxis:function(e){return e%this._interval===0}},s.inherits(t,i),e("../component").define("categoryAxis",t),t}),i("echarts/component/valueAxis",["require","./base","zrender/shape/Text","zrender/shape/Line","zrender/shape/Rectangle","../config","../util/date","zrender/tool/util","../util/smartSteps","../util/accMath","../util/smartLogSteps","../component"],function(e){function t(e,t,n,a,o,r,s){if(!s||0===s.length)return void console.err("option.series.length == 0.");i.call(this,e,t,n,a,o),this.series=s,this.grid=this.component.grid;for(var l in r)this[l]=r[l];this.refresh(a,s)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Line"),o=e("zrender/shape/Rectangle"),r=e("../config");r.valueAxis={zlevel:0,z:0,show:!0,position:"left",name:"",nameLocation:"end",nameTextStyle:{},boundaryGap:[0,0],axisLine:{show:!0,onZero:!0,lineStyle:{color:"#48b",width:2,type:"solid"}},axisTick:{show:!1,inside:!1,length:5,lineStyle:{color:"#333",width:1}},axisLabel:{show:!0,rotate:0,margin:8,textStyle:{color:"#333"}},splitLine:{show:!0,lineStyle:{color:["#ccc"],width:1,type:"solid"}},splitArea:{show:!1,areaStyle:{color:["rgba(250,250,250,0.3)","rgba(200,200,200,0.3)"]}}};var s=e("../util/date"),l=e("zrender/tool/util");return t.prototype={type:r.COMPONENT_TYPE_AXIS_VALUE,_buildShape:function(){if(this._hasData=!1,this._calculateValue(),this._hasData&&this.option.show){this.option.splitArea.show&&this._buildSplitArea(),this.option.splitLine.show&&this._buildSplitLine(),this.option.axisLine.show&&this._buildAxisLine(),this.option.axisTick.show&&this._buildAxisTick(),this.option.axisLabel.show&&this._buildAxisLabel();for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e])}},_buildAxisTick:function(){var e,t=this._valueList,i=this._valueList.length,n=this.option.axisTick,o=n.length,r=n.lineStyle.color,s=n.lineStyle.width;if(this.isHorizontal())for(var l,h="bottom"===this.option.position?n.inside?this.grid.getYend()-o-1:this.grid.getYend()+1:n.inside?this.grid.getY()+1:this.grid.getY()-o-1,m=0;i>m;m++)l=this.subPixelOptimize(this.getCoord(t[m]),s),e={_axisShape:"axisTick",zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:l,yStart:h,xEnd:l,yEnd:h+o,strokeColor:r,lineWidth:s}},this.shapeList.push(new a(e));else for(var V,U="left"===this.option.position?n.inside?this.grid.getX()+1:this.grid.getX()-o-1:n.inside?this.grid.getXend()-o-1:this.grid.getXend()+1,m=0;i>m;m++)V=this.subPixelOptimize(this.getCoord(t[m]),s),e={_axisShape:"axisTick",zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:U,yStart:V,xEnd:U+o,yEnd:V,strokeColor:r,lineWidth:s}},this.shapeList.push(new a(e))},_buildAxisLabel:function(){var e,t=this._valueList,i=this._valueList.length,a=this.option.axisLabel.rotate,o=this.option.axisLabel.margin,r=this.option.axisLabel.clickable,s=this.option.axisLabel.textStyle;if(this.isHorizontal()){var l,h;"bottom"===this.option.position?(l=this.grid.getYend()+o,h="top"):(l=this.grid.getY()-o,h="bottom");for(var m=0;i>m;m++)e={zlevel:this.getZlevelBase(),z:this.getZBase()+3,hoverable:!1,style:{x:this.getCoord(t[m]),y:l,color:"function"==typeof s.color?s.color(t[m]):s.color,text:this._valueLabel[m],textFont:this.getFont(s),textAlign:s.align||"center",textBaseline:s.baseline||h}},a&&(e.style.textAlign=a>0?"bottom"===this.option.position?"right":"left":"bottom"===this.option.position?"left":"right",e.rotation=[a*Math.PI/180,e.style.x,e.style.y]),this.shapeList.push(new n(this._axisLabelClickable(r,e)))}else{var V,U;"left"===this.option.position?(V=this.grid.getX()-o,U="right"):(V=this.grid.getXend()+o,U="left");for(var m=0;i>m;m++)e={zlevel:this.getZlevelBase(),z:this.getZBase()+3,hoverable:!1,style:{x:V,y:this.getCoord(t[m]),color:"function"==typeof s.color?s.color(t[m]):s.color,text:this._valueLabel[m],textFont:this.getFont(s),textAlign:s.align||U,textBaseline:s.baseline||(0===m&&""!==this.option.name?"bottom":m===i-1&&""!==this.option.name?"top":"middle")}},a&&(e.rotation=[a*Math.PI/180,e.style.x,e.style.y]),this.shapeList.push(new n(this._axisLabelClickable(r,e)))}},_buildSplitLine:function(){var e,t=this._valueList,i=this._valueList.length,n=this.option.splitLine,o=n.lineStyle.type,r=n.lineStyle.width,s=n.lineStyle.color;s=s instanceof Array?s:[s];var l=s.length;if(this.isHorizontal())for(var h,m=this.grid.getY(),V=this.grid.getYend(),U=0;i>U;U++)h=this.subPixelOptimize(this.getCoord(t[U]),r),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:h,yStart:m,xEnd:h,yEnd:V,strokeColor:s[U%l],lineType:o,lineWidth:r}},this.shapeList.push(new a(e));else for(var d,p=this.grid.getX(),c=this.grid.getXend(),U=0;i>U;U++)d=this.subPixelOptimize(this.getCoord(t[U]),r),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{xStart:p,yStart:d,xEnd:c,yEnd:d,strokeColor:s[U%l],lineType:o,lineWidth:r}},this.shapeList.push(new a(e))},_buildSplitArea:function(){var e,t=this.option.splitArea.areaStyle.color;if(t instanceof Array){var i=t.length,n=this._valueList,a=this._valueList.length;if(this.isHorizontal())for(var r,s=this.grid.getY(),l=this.grid.getHeight(),h=this.grid.getX(),m=0;a>=m;m++)r=a>m?this.getCoord(n[m]):this.grid.getXend(),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:h,y:s,width:r-h,height:l,color:t[m%i]}},this.shapeList.push(new o(e)),h=r;else for(var V,U=this.grid.getX(),d=this.grid.getWidth(),p=this.grid.getYend(),m=0;a>=m;m++)V=a>m?this.getCoord(n[m]):this.grid.getY(),e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:U,y:V,width:d,height:p-V,color:t[m%i]}},this.shapeList.push(new o(e)),p=V}else e={zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this.grid.getX(),y:this.grid.getY(),width:this.grid.getWidth(),height:this.grid.getHeight(),color:t}},this.shapeList.push(new o(e))},_calculateValue:function(){if(isNaN(this.option.min-0)||isNaN(this.option.max-0)){for(var e,t,i={},n=this.component.legend,a=0,o=this.series.length;o>a;a++)!(this.series[a].type!=r.CHART_TYPE_LINE&&this.series[a].type!=r.CHART_TYPE_BAR&&this.series[a].type!=r.CHART_TYPE_SCATTER&&this.series[a].type!=r.CHART_TYPE_K&&this.series[a].type!=r.CHART_TYPE_EVENTRIVER||n&&!n.isSelected(this.series[a].name)||(e=this.series[a].xAxisIndex||0,t=this.series[a].yAxisIndex||0,this.option.xAxisIndex!=e&&this.option.yAxisIndex!=t||!this._calculSum(i,a)));var s;for(var a in i){s=i[a];for(var l=0,h=s.length;h>l;l++)if(!isNaN(s[l])){this._hasData=!0,this._min=s[l],this._max=s[l];break}if(this._hasData)break}for(var a in i){s=i[a];for(var l=0,h=s.length;h>l;l++)isNaN(s[l])||(this._min=Math.min(this._min,s[l]),this._max=Math.max(this._max,s[l]))}var m="log"!==this.option.type?this.option.boundaryGap:[0,0],V=Math.abs(this._max-this._min);this._min=isNaN(this.option.min-0)?this._min-Math.abs(V*m[0]):this.option.min-0,this._max=isNaN(this.option.max-0)?this._max+Math.abs(V*m[1]):this.option.max-0,this._min===this._max&&(0===this._max?this._max=1:this._max>0?this._min=this._max/this.option.splitNumber!=null?this.option.splitNumber:5:this._max=this._max/this.option.splitNumber!=null?this.option.splitNumber:5),"time"===this.option.type?this._reformTimeValue():"log"===this.option.type?this._reformLogValue():this._reformValue(this.option.scale)}else this._hasData=!0,this._min=this.option.min-0,this._max=this.option.max-0,"time"===this.option.type?this._reformTimeValue():"log"===this.option.type?this._reformLogValue():this._customerValue()},_calculSum:function(e,t){var i,n,a=this.series[t].name||"kener";if(this.series[t].stack){var o="__Magic_Key_Positive__"+this.series[t].stack,l="__Magic_Key_Negative__"+this.series[t].stack;e[o]=e[o]||[],e[l]=e[l]||[],e[a]=e[a]||[],n=this.series[t].data;for(var h=0,m=n.length;m>h;h++)i=this.getDataFromOption(n[h]),"-"!==i&&(i-=0,i>=0?null!=e[o][h]?e[o][h]+=i:e[o][h]=i:null!=e[l][h]?e[l][h]+=i:e[l][h]=i,this.option.scale&&e[a].push(i))}else if(e[a]=e[a]||[],this.series[t].type!=r.CHART_TYPE_EVENTRIVER){n=this.series[t].data;for(var h=0,m=n.length;m>h;h++)i=this.getDataFromOption(n[h]),this.series[t].type===r.CHART_TYPE_K?(e[a].push(i[0]),e[a].push(i[1]),e[a].push(i[2]),e[a].push(i[3])):i instanceof Array?(-1!=this.option.xAxisIndex&&e[a].push("time"!=this.option.type?i[0]:s.getNewDate(i[0])),-1!=this.option.yAxisIndex&&e[a].push("time"!=this.option.type?i[1]:s.getNewDate(i[1]))):e[a].push(i)}else{n=this.series[t].data;for(var h=0,m=n.length;m>h;h++)for(var V=n[h].evolution,U=0,d=V.length;d>U;U++)e[a].push(s.getNewDate(V[U].time))}},_reformValue:function(t){var i=e("../util/smartSteps"),n=this.option.splitNumber;!t&&this._min>=0&&this._max>=0&&(this._min=0),!t&&this._min<=0&&this._max<=0&&(this._max=0);var a=i(this._min,this._max,n);n=null!=n?n:a.secs,this._min=a.min,this._max=a.max,this._valueList=a.pnts,this._reformLabelData()},_reformTimeValue:function(){var e=null!=this.option.splitNumber?this.option.splitNumber:5,t=s.getAutoFormatter(this._min,this._max,e),i=t.formatter,n=t.gapValue;this._valueList=[s.getNewDate(this._min)];var a;switch(i){case"week":a=s.nextMonday(this._min);break;case"month":a=s.nextNthOnMonth(this._min,1);break;case"quarter":a=s.nextNthOnQuarterYear(this._min,1);break;case"half-year":a=s.nextNthOnHalfYear(this._min,1);break;case"year":a=s.nextNthOnYear(this._min,1);break;default:72e5>=n?a=(Math.floor(this._min/n)+1)*n:(a=s.getNewDate(this._min- -n),a.setHours(6*Math.round(a.getHours()/6)),a.setMinutes(0),a.setSeconds(0))}for(a-this._min=0&&(("month"==i||"quarter"==i||"half-year"==i||"year"==i)&&t.setDate(1),!(this._max-t=a;a++)this._valueList.push(t.accAdd(this._min,t.accMul(n,a)));this._reformLabelData()},_reformLogValue:function(){var t=this.option,i=e("../util/smartLogSteps")({dataMin:this._min,dataMax:this._max,logPositive:t.logPositive,logLabelBase:t.logLabelBase,splitNumber:t.splitNumber});this._min=i.dataMin,this._max=i.dataMax,this._valueList=i.tickList,this._dataMappingMethods=i.dataMappingMethods,this._reformLabelData(i.labelFormatter)},_reformLabelData:function(e){this._valueLabel=[];var t=this.option.axisLabel.formatter;if(t)for(var i=0,n=this._valueList.length;n>i;i++)"function"==typeof t?this._valueLabel.push(e?t.call(this.myChart,this._valueList[i],e):t.call(this.myChart,this._valueList[i])):"string"==typeof t&&this._valueLabel.push(e?s.format(t,this._valueList[i]):t.replace("{value}",this._valueList[i]));else for(var i=0,n=this._valueList.length;n>i;i++)this._valueLabel.push(e?e(this._valueList[i]):this.numAddCommas(this._valueList[i]))},getExtremum:function(){this._calculateValue();var e=this._dataMappingMethods;return{min:this._min,max:this._max,dataMappingMethods:e?l.merge({},e):null}},refresh:function(e,t){e&&(this.option=this.reformOption(e),this.option.axisLabel.textStyle=l.merge(this.option.axisLabel.textStyle||{},this.ecTheme.textStyle),this.series=t),this.zr&&(this.clear(),this._buildShape())},getCoord:function(e){this._dataMappingMethods&&(e=this._dataMappingMethods.value2Coord(e)),e=ethis._max?this._max:e;var t;return t=this.isHorizontal()?this.grid.getX()+(e-this._min)/(this._max-this._min)*this.grid.getWidth():this.grid.getYend()-(e-this._min)/(this._max-this._min)*this.grid.getHeight()},getCoordSize:function(e){return Math.abs(this.isHorizontal()?e/(this._max-this._min)*this.grid.getWidth():e/(this._max-this._min)*this.grid.getHeight())},getValueFromCoord:function(e){var t;return this.isHorizontal()?(e=ethis.grid.getXend()?this.grid.getXend():e,t=this._min+(e-this.grid.getX())/this.grid.getWidth()*(this._max-this._min)):(e=ethis.grid.getYend()?this.grid.getYend():e,t=this._max-(e-this.grid.getY())/this.grid.getHeight()*(this._max-this._min)),this._dataMappingMethods&&(t=this._dataMappingMethods.coord2Value(t)),t.toFixed(2)-0},isMaindAxis:function(e){for(var t=0,i=this._valueList.length;i>t;t++)if(this._valueList[t]===e)return!0;return!1}},l.inherits(t,i),e("../component").define("valueAxis",t),t}),i("echarts/util/date",[],function(){function e(e,t,i){i=i>1?i:2;for(var n,a,o,r,s=0,l=m.length;l>s;s++)if(n=m[s].value,a=Math.ceil(t/n)*n-Math.floor(e/n)*n,Math.round(a/n)<=1.2*i){o=m[s].formatter,r=m[s].value;break}return null==o&&(o="year",n=317088e5,a=Math.ceil(t/n)*n-Math.floor(e/n)*n,r=Math.round(a/(i-1)/n)*n),{formatter:o,gapValue:r}}function t(e){return 10>e?"0"+e:e}function i(e,i){("week"==e||"month"==e||"quarter"==e||"half-year"==e||"year"==e)&&(e="MM - dd\nyyyy");var n=h(i),a=n.getFullYear(),o=n.getMonth()+1,r=n.getDate(),s=n.getHours(),l=n.getMinutes(),m=n.getSeconds();return e=e.replace("MM",t(o)),e=e.toLowerCase(),e=e.replace("yyyy",a),e=e.replace("yy",a%100),e=e.replace("dd",t(r)),e=e.replace("d",r),e=e.replace("hh",t(s)),e=e.replace("h",s),e=e.replace("mm",t(l)),e=e.replace("m",l),e=e.replace("ss",t(m)),e=e.replace("s",m)}function n(e){return e=h(e),e.setDate(e.getDate()+8-e.getDay()),e}function a(e,t,i){return e=h(e),e.setMonth(Math.ceil((e.getMonth()+1)/i)*i),e.setDate(t),e}function o(e,t){return a(e,t,1)}function r(e,t){return a(e,t,3)}function s(e,t){return a(e,t,6)}function l(e,t){return a(e,t,12)}function h(e){return e instanceof Date?e:new Date("string"==typeof e?e.replace(/-/g,"/"):e)}var m=[{formatter:"hh : mm : ss",value:1e3},{formatter:"hh : mm : ss",value:5e3},{formatter:"hh : mm : ss",value:1e4},{formatter:"hh : mm : ss",value:15e3},{formatter:"hh : mm : ss",value:3e4},{formatter:"hh : mm\nMM - dd",value:6e4},{formatter:"hh : mm\nMM - dd",value:3e5},{formatter:"hh : mm\nMM - dd",value:6e5},{formatter:"hh : mm\nMM - dd",value:9e5},{formatter:"hh : mm\nMM - dd",value:18e5},{formatter:"hh : mm\nMM - dd",value:36e5},{formatter:"hh : mm\nMM - dd",value:72e5},{formatter:"hh : mm\nMM - dd",value:216e5},{formatter:"hh : mm\nMM - dd",value:432e5},{formatter:"MM - dd\nyyyy",value:864e5},{formatter:"week",value:6048e5},{formatter:"month",value:26784e5},{formatter:"quarter",value:8208e6},{formatter:"half-year",value:16416e6},{formatter:"year",value:32832e6}];return{getAutoFormatter:e,getNewDate:h,format:i,nextMonday:n,nextNthPerNmonth:a,nextNthOnMonth:o,nextNthOnQuarterYear:r,nextNthOnHalfYear:s,nextNthOnYear:l}}),i("echarts/util/smartSteps",[],function(){function e(e){return X.log(I(e))/X.LN10}function t(e){return X.pow(10,e)}function i(e){return e===w(e)}function n(e,t,n,a){b=a||{},f=b.steps||L,k=b.secs||W,n=v(+n||0)%99,e=+e||0,t=+t||0,x=_=0,"min"in b&&(e=+b.min||0,x=1),"max"in b&&(t=+b.max||0,_=1),e>t&&(t=[e,e=t][0]);var o=t-e;if(x&&_)return g(e,t,n);if((n||5)>o){if(i(e)&&i(t))return d(e,t,n);if(0===o)return p(e,t,n)}return h(e,t,n)}function a(e,i,n,a){a=a||0;var s=o((i-e)/n,-1),l=o(e,-1,1),h=o(i,-1),m=X.min(s.e,l.e,h.e);0===l.c?m=X.min(s.e,h.e):0===h.c&&(m=X.min(s.e,l.e)),r(s,{c:0,e:m}),r(l,s,1),r(h,s),a+=m,e=l.c,i=h.c;for(var V=(i-e)/n,U=t(a),d=0,p=[],c=n+1;c--;)p[c]=(e+V*c)*U;if(0>a){d=u(U),V=+(V*U).toFixed(d),e=+(e*U).toFixed(d),i=+(i*U).toFixed(d);for(var c=p.length;c--;)p[c]=p[c].toFixed(d),0===+p[c]&&(p[c]="0")}else e*=U,i*=U,V*=U;return k=0,f=0,b=0,{min:e,max:i,secs:n,step:V,fix:d,exp:a,pnts:p}}function o(n,a,o){a=v(a%10)||2,0>a&&(i(n)?a=(""+I(n)).replace(/0+$/,"").length||1:(n=n.toFixed(15).replace(/0+$/,""),a=n.replace(".","").replace(/^[-0]+/,"").length,n=+n));var r=w(e(n))-a+1,s=+(n*t(-r)).toFixed(15)||0;return s=o?w(s):K(s),!s&&(r=0),(""+I(s)).length>a&&(r+=1,s/=10),{c:s,e:r}}function r(e,i,n){var a=i.e-e.e;a&&(e.e+=a,e.c*=t(-a),e.c=n?w(e.c):K(e.c))}function s(e,t,i){e.et[n];)n++;if(!t[n])for(i/=10,e.e+=1,n=0;i>t[n];)n++;return e.c=t[n],e}function h(e,t,n){var s,h=n||+k.slice(-1),p=l((t-e)/h,f),u=o(t-e),g=o(e,-1,1),b=o(t,-1);if(r(u,p),r(g,p,1),r(b,p),n?s=V(g,b,h):h=m(g,b),i(e)&&i(t)&&e*t>=0){if(h>t-e)return d(e,t,h);h=U(e,t,n,g,b,h)}var L=c(e,t,g.c,b.c);return g.c=L[0],b.c=L[1],(x||_)&&y(e,t,g,b),a(g.c,b.c,h,b.e)}function m(e,i){for(var n,a,o,r,s=[],h=k.length;h--;)n=k[h],a=l((i.c-e.c)/n,f),a=a.c*t(a.e),o=w(e.c/a)*a,r=K(i.c/a)*a,s[h]={min:o,max:r,step:a,span:r-o};return s.sort(function(e,t){var i=e.span-t.span;return 0===i&&(i=e.step-t.step),i}),s=s[0],n=s.span/s.step,e.c=s.min,i.c=s.max,3>n?2*n:n}function V(e,i,n){for(var a,o,r=i.c,s=(i.c-e.c)/n-1;r>e.c;)s=l(s+1,f),s=s.c*t(s.e),a=s*n,o=K(i.c/s)*s,r=o-a;var h=e.c-r,m=o-i.c,V=h-m;return V>1.1*s&&(V=v(V/s/2)*s,r+=V,o+=V),e.c=r,i.c=o,s}function U(e,n,a,o,r,s){var l=r.c-o.c,h=l/s*t(r.e);if(!i(h)&&(h=w(h),l=h*s,n-e>l&&(h+=1,l=h*s,!a&&h*(s-1)>=n-e&&(s-=1,l=h*s)),l>=n-e)){var m=l-(n-e);o.c=v(e-m/2),r.c=v(n+m/2),o.e=0,r.e=0}return s}function d(e,t,i){if(i=i||5,x)t=e+i;else if(_)e=t-i;else{var n=i-(t-e),o=v(e-n/2),r=v(t+n/2),s=c(e,t,o,r);e=s[0],t=s[1]}return a(e,t,i)}function p(e,t,i){i=i||5;var n=X.min(I(t/i),i)/2.1;return x?t=e+n:_?e=t-n:(e-=n,t+=n),h(e,t,i)}function c(e,t,i,n){ -return e>=0&&0>i?(n-=i,i=0):0>=t&&n>0&&(i-=n,n=0),[i,n]}function u(e){return e=(+e).toFixed(15).split("."),e.pop().replace(/0+$/,"").length}function y(e,t,i,n){if(x){var a=o(e,4,1);i.e-a.e>6&&(a={c:0,e:i.e}),s(i,a),s(n,a),n.c+=a.c-i.c,i.c=a.c}else if(_){var r=o(t,4);n.e-r.e>6&&(r={c:0,e:n.e}),s(i,r),s(n,r),i.c+=r.c-n.c,n.c=r.c}}function g(e,t,i){var n=i?[i]:k,s=t-e;if(0===s)return t=o(t,3),i=n[0],t.c=v(t.c+i/2),a(t.c-i,t.c,i,t.e);I(t/s)<1e-6&&(t=0),I(e/s)<1e-6&&(e=0);var l,h,m,V=[[5,10],[10,2],[50,10],[100,2]],U=[],d=[],p=o(t-e,3),c=o(e,-1,1),u=o(t,-1);r(c,p,1),r(u,p),s=u.c-c.c,p.c=s;for(var y=n.length;y--;){i=n[y],l=K(s/i),h=l*i-s,m=3*(h+3),m+=2*(i-n[0]+2),i%5===0&&(m-=10);for(var g=V.length;g--;)l%V[g][0]===0&&(m/=V[g][1]);d[y]=[i,l,h,m].join(),U[y]={secs:i,step:l,delta:h,score:m}}return U.sort(function(e,t){return e.score-t.score}),U=U[0],c.c=v(c.c-U.delta/2),u.c=v(u.c+U.delta/2),a(c.c,u.c,U.secs,p.e)}var b,f,k,x,_,L=[10,20,25,50],W=[4,5,6],X=Math,v=X.round,w=X.floor,K=X.ceil,I=X.abs;return n}),i("echarts/util/smartLogSteps",["require","./number"],function(e){function t(e){return i(),u=e||{},n(),a(),[o(),i()][0]}function i(){U=u=g=c=b=f=y=k=d=p=null}function n(){d=u.logLabelBase,null==d?(p="plain",d=10,c=I):(d=+d,1>d&&(d=10),p="exponent",c=L(d)),y=u.splitNumber,null==y&&(y=E);var e=parseFloat(u.dataMin),t=parseFloat(u.dataMax);isFinite(e)||isFinite(t)?isFinite(e)?isFinite(t)?e>t&&(t=[e,e=t][0]):t=e:e=t:e=t=1,U=u.logPositive,null==U&&(U=t>0||0===e),b=U?e:-t,f=U?t:-e,S>b&&(b=S),S>f&&(f=S)}function a(){function e(){y>m&&(y=m);var e=w(l(m/y)),t=v(l(m/e)),i=e*t,n=(i-U)/2,a=w(l(r-n));V(a-r)&&(a-=1),g=-a*c;for(var s=a;o>=s-e;s+=e)k.push(W(d,s))}function t(){for(var e=i(h,0),t=e+2;t>e&&a(e+1)+n(e+1)*Ct&&a(l-1)+n(l-1)*C>o;)l--;g=-(a(e)*I+n(e)*J);for(var m=e;l>=m;m++){var V=a(m),U=n(m);k.push(W(10,V)*W(2,U))}}function i(e,t){return 3*e+t}function n(e){return e-3*a(e)}function a(e){return w(l(e/3))}k=[];var o=l(L(f)/c),r=l(L(b)/c),s=v(o),h=w(r),m=s-h,U=o-r;"exponent"===p?e():F>=m&&y>F?t():e()}function o(){for(var e=[],t=0,i=k.length;i>t;t++)e[t]=(U?1:-1)*k[t];!U&&e.reverse();var n=s(),a=n.value2Coord,o=a(e[0]),l=a(e[e.length-1]);return o===l&&(o-=1,l+=1),{dataMin:o,dataMax:l,tickList:e,logPositive:U,labelFormatter:r(),dataMappingMethods:n}}function r(){if("exponent"===p){var e=d,t=c;return function(i){if(!isFinite(parseFloat(i)))return"";var n="";return 0>i&&(i=-i,n="-"),n+e+m(L(i)/t)}}return function(e){return isFinite(parseFloat(e))?x.addCommas(h(e)):""}}function s(){var e=U,t=g;return{value2Coord:function(i){return null==i||isNaN(i)||!isFinite(i)?i:(i=parseFloat(i),isFinite(i)?e&&S>i?i=S:!e&&i>-S&&(i=-S):i=S,i=X(i),(e?1:-1)*(L(i)+t))},coord2Value:function(i){return null==i||isNaN(i)||!isFinite(i)?i:(i=parseFloat(i),isFinite(i)||(i=S),e?W(K,i-t):-W(K,-i+t))}}}function l(e){return+Number(+e).toFixed(14)}function h(e){return Number(e).toFixed(15).replace(/\.?0*$/,"")}function m(e){e=h(Math.round(e));for(var t=[],i=0,n=e.length;n>i;i++){var a=e.charAt(i);t.push(T[a]||"")}return t.join("")}function V(e){return e>-S&&S>e}var U,d,p,c,u,y,g,b,f,k,x=e("./number"),_=Math,L=_.log,W=_.pow,X=_.abs,v=_.ceil,w=_.floor,K=_.E,I=_.LN10,J=_.LN2,C=J/I,S=1e-9,E=5,F=2,T={0:"⁰",1:"¹",2:"²",3:"³",4:"⁴",5:"⁵",6:"⁶",7:"⁷",8:"⁸",9:"⁹","-":"⁻"};return t}),i("echarts/chart/line",["require","./base","zrender/shape/Polyline","../util/shape/Icon","../util/shape/HalfSmoothPolygon","../component/axis","../component/grid","../component/dataZoom","../config","../util/ecData","zrender/tool/util","zrender/tool/color","../chart"],function(e){function t(e,t,i,a,o){n.call(this,e,t,i,a,o),this.refresh(a)}function i(e,t,i){var n=t.x,a=t.y,r=t.width,s=t.height,l=s/2;t.symbol.match("empty")&&(e.fillStyle="#fff"),t.brushType="both";var h=t.symbol.replace("empty","").toLowerCase();h.match("star")?(l=h.replace("star","")-0||5,a-=1,h="star"):("rectangle"===h||"arrow"===h)&&(n+=(r-s)/2,r=s);var m="";if(h.match("image")&&(m=h.replace(new RegExp("^image:\\/\\/"),""),h="image",n+=Math.round((r-s)/2)-1,r=s+=2),h=o.prototype.iconLibrary[h]){var V=t.x,U=t.y;e.moveTo(V,U+l),e.lineTo(V+5,U+l),e.moveTo(V+t.width-5,U+l),e.lineTo(V+t.width,U+l);var d=this;h(e,{x:n+4,y:a+4,width:r-8,height:s-8,n:l,image:m},function(){d.modSelf(),i()})}else e.moveTo(n,a+l),e.lineTo(n+r,a+l)}var n=e("./base"),a=e("zrender/shape/Polyline"),o=e("../util/shape/Icon"),r=e("../util/shape/HalfSmoothPolygon");e("../component/axis"),e("../component/grid"),e("../component/dataZoom");var s=e("../config");s.line={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,xAxisIndex:0,yAxisIndex:0,dataFilter:"nearest",itemStyle:{normal:{label:{show:!1},lineStyle:{width:2,type:"solid",shadowColor:"rgba(0,0,0,0)",shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0}},emphasis:{label:{show:!1}}},symbolSize:2,showAllSymbol:!1};var l=e("../util/ecData"),h=e("zrender/tool/util"),m=e("zrender/tool/color");return t.prototype={type:s.CHART_TYPE_LINE,_buildShape:function(){this.finalPLMap={},this._buildPosition()},_buildHorizontal:function(e,t,i,n){for(var a,o,r,s,l,h,m,V,U,d=this.series,p=i[0][0],c=d[p],u=this.component.xAxis.getAxis(c.xAxisIndex||0),y={},g=0,b=t;b>g&&null!=u.getNameByIndex(g);g++){o=u.getCoordByIndex(g);for(var f=0,k=i.length;k>f;f++){a=this.component.yAxis.getAxis(d[i[f][0]].yAxisIndex||0),l=s=m=h=a.getCoord(0);for(var x=0,_=i[f].length;_>x;x++)p=i[f][x],c=d[p],V=c.data[g],U=this.getDataFromOption(V,"-"),y[p]=y[p]||[],n[p]=n[p]||{min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY,sum:0,counter:0,average:0},"-"!==U?(U>=0?(s-=x>0?a.getCoordSize(U):l-a.getCoord(U),r=s):0>U&&(h+=x>0?a.getCoordSize(U):a.getCoord(U)-m,r=h),y[p].push([o,r,g,u.getNameByIndex(g),o,l]),n[p].min>U&&(n[p].min=U,n[p].minY=r,n[p].minX=o),n[p].max0&&(this.finalPLMap[p]=this.finalPLMap[p]||[],this.finalPLMap[p].push(y[p]),y[p]=[])}s=this.component.grid.getY();for(var L,f=0,k=i.length;k>f;f++)for(var x=0,_=i[f].length;_>x;x++)p=i[f][x],c=d[p],V=c.data[g],U=this.getDataFromOption(V,"-"),"-"==U&&this.deepQuery([V,c,this.option],"calculable")&&(L=this.deepQuery([V,c],"symbolSize"),s+=2*L+5,r=s,this.shapeList.push(this._getCalculableItem(p,g,u.getNameByIndex(g),o,r,"horizontal")))}for(var W in y)y[W].length>0&&(this.finalPLMap[W]=this.finalPLMap[W]||[],this.finalPLMap[W].push(y[W]),y[W]=[]);this._calculMarkMapXY(n,i,"y"),this._buildBorkenLine(e,this.finalPLMap,u,"horizontal")},_buildVertical:function(e,t,i,n){for(var a,o,r,s,l,h,m,V,U,d=this.series,p=i[0][0],c=d[p],u=this.component.yAxis.getAxis(c.yAxisIndex||0),y={},g=0,b=t;b>g&&null!=u.getNameByIndex(g);g++){r=u.getCoordByIndex(g);for(var f=0,k=i.length;k>f;f++){a=this.component.xAxis.getAxis(d[i[f][0]].xAxisIndex||0),l=s=m=h=a.getCoord(0);for(var x=0,_=i[f].length;_>x;x++)p=i[f][x],c=d[p],V=c.data[g],U=this.getDataFromOption(V,"-"),y[p]=y[p]||[],n[p]=n[p]||{min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY,sum:0,counter:0,average:0},"-"!==U?(U>=0?(s+=x>0?a.getCoordSize(U):a.getCoord(U)-l,o=s):0>U&&(h-=x>0?a.getCoordSize(U):m-a.getCoord(U),o=h),y[p].push([o,r,g,u.getNameByIndex(g),l,r]),n[p].min>U&&(n[p].min=U,n[p].minX=o,n[p].minY=r),n[p].max0&&(this.finalPLMap[p]=this.finalPLMap[p]||[],this.finalPLMap[p].push(y[p]),y[p]=[])}s=this.component.grid.getXend();for(var L,f=0,k=i.length;k>f;f++)for(var x=0,_=i[f].length;_>x;x++)p=i[f][x],c=d[p],V=c.data[g],U=this.getDataFromOption(V,"-"),"-"==U&&this.deepQuery([V,c,this.option],"calculable")&&(L=this.deepQuery([V,c],"symbolSize"),s-=2*L+5,o=s,this.shapeList.push(this._getCalculableItem(p,g,u.getNameByIndex(g),o,r,"vertical")))}for(var W in y)y[W].length>0&&(this.finalPLMap[W]=this.finalPLMap[W]||[],this.finalPLMap[W].push(y[W]),y[W]=[]);this._calculMarkMapXY(n,i,"x"),this._buildBorkenLine(e,this.finalPLMap,u,"vertical")},_buildOther:function(e,t,i,n){for(var a,o=this.series,r={},s=0,l=i.length;l>s;s++)for(var h=0,m=i[s].length;m>h;h++){var V=i[s][h],U=o[V];a=this.component.xAxis.getAxis(U.xAxisIndex||0);var d=this.component.yAxis.getAxis(U.yAxisIndex||0),p=d.getCoord(0);r[V]=r[V]||[],n[V]=n[V]||{min0:Number.POSITIVE_INFINITY,min1:Number.POSITIVE_INFINITY,max0:Number.NEGATIVE_INFINITY,max1:Number.NEGATIVE_INFINITY,sum0:0,sum1:0,counter0:0,counter1:0,average0:0,average1:0};for(var c=0,u=U.data.length;u>c;c++){var y=U.data[c],g=this.getDataFromOption(y,"-");if(g instanceof Array){var b=a.getCoord(g[0]),f=d.getCoord(g[1]);r[V].push([b,f,c,g[0],b,p]),n[V].min0>g[0]&&(n[V].min0=g[0],n[V].minY0=f,n[V].minX0=b),n[V].max0g[1]&&(n[V].min1=g[1],n[V].minY1=f,n[V].minX1=b),n[V].max10&&(this.finalPLMap[k]=this.finalPLMap[k]||[],this.finalPLMap[k].push(r[k]),r[k]=[]);this._calculMarkMapXY(n,i,"xy"),this._buildBorkenLine(e,this.finalPLMap,a,"other")},_buildBorkenLine:function(e,t,i,n){for(var o,s="other"==n?"horizontal":n,V=this.series,U=e.length-1;U>=0;U--){var d=e[U],p=V[d],c=t[d];if(p.type===this.type&&null!=c)for(var u=this._getBbox(d,s),y=this._sIndex2ColorMap[d],g=this.query(p,"itemStyle.normal.lineStyle.width"),b=this.query(p,"itemStyle.normal.lineStyle.type"),f=this.query(p,"itemStyle.normal.lineStyle.color"),k=this.getItemStyleColor(this.query(p,"itemStyle.normal.color"),d,-1),x=null!=this.query(p,"itemStyle.normal.areaStyle"),_=this.query(p,"itemStyle.normal.areaStyle.color"),L=0,W=c.length;W>L;L++){var X=c[L],v="other"!=n&&this._isLarge(s,X);if(v)X=this._getLargePointList(s,X,p.dataFilter);else for(var w=0,K=X.length;K>w;w++)o=p.data[X[w][2]],(this.deepQuery([o,p,this.option],"calculable")||this.deepQuery([o,p],"showAllSymbol")||"categoryAxis"===i.type&&i.isMainAxis(X[w][2])&&"none"!=this.deepQuery([o,p],"symbol"))&&this.shapeList.push(this._getSymbol(d,X[w][2],X[w][3],X[w][0],X[w][1],s));var I=new a({zlevel:p.zlevel,z:p.z,style:{miterLimit:g,pointList:X,strokeColor:f||k||y,lineWidth:g,lineType:b,smooth:this._getSmooth(p.smooth),smoothConstraint:u,shadowColor:this.query(p,"itemStyle.normal.lineStyle.shadowColor"),shadowBlur:this.query(p,"itemStyle.normal.lineStyle.shadowBlur"),shadowOffsetX:this.query(p,"itemStyle.normal.lineStyle.shadowOffsetX"),shadowOffsetY:this.query(p,"itemStyle.normal.lineStyle.shadowOffsetY")},hoverable:!1,_main:!0,_seriesIndex:d,_orient:s});if(l.pack(I,V[d],d,0,L,V[d].name),this.shapeList.push(I),x){var J=new r({zlevel:p.zlevel,z:p.z,style:{miterLimit:g,pointList:h.clone(X).concat([[X[X.length-1][4],X[X.length-1][5]],[X[0][4],X[0][5]]]),brushType:"fill",smooth:this._getSmooth(p.smooth),smoothConstraint:u,color:_?_:m.alpha(y,.5)},highlightStyle:{brushType:"fill"},hoverable:!1,_main:!0,_seriesIndex:d,_orient:s});l.pack(J,V[d],d,0,L,V[d].name),this.shapeList.push(J)}}}},_getBbox:function(e,t){var i=this.component.grid.getBbox(),n=this.xMarkMap[e];return null!=n.minX0?[[Math.min(n.minX0,n.maxX0,n.minX1,n.maxX1),Math.min(n.minY0,n.maxY0,n.minY1,n.maxY1)],[Math.max(n.minX0,n.maxX0,n.minX1,n.maxX1),Math.max(n.minY0,n.maxY0,n.minY1,n.maxY1)]]:("horizontal"===t?(i[0][1]=Math.min(n.minY,n.maxY),i[1][1]=Math.max(n.minY,n.maxY)):(i[0][0]=Math.min(n.minX,n.maxX),i[1][0]=Math.max(n.minX,n.maxX)),i)},_isLarge:function(e,t){return t.length<2?!1:"horizontal"===e?Math.abs(t[0][0]-t[1][0])<.5:Math.abs(t[0][1]-t[1][1])<.5},_getLargePointList:function(e,t,i){var n;n="horizontal"===e?this.component.grid.getWidth():this.component.grid.getHeight();var a=t.length,o=[];if("function"!=typeof i)switch(i){case"min":i=function(e){return Math.max.apply(null,e)};break;case"max":i=function(e){return Math.min.apply(null,e)};break;case"average":i=function(e){for(var t=0,i=0;is;s++){var l=Math.floor(a/n*s),h=Math.min(Math.floor(a/n*(s+1)),a);if(!(l>=h)){for(var m=l;h>m;m++)r[m-l]="horizontal"===e?t[m][1]:t[m][0];r.length=h-l;for(var V=i(r),U=-1,d=1/0,m=l;h>m;m++){var p="horizontal"===e?t[m][1]:t[m][0],c=Math.abs(p-V);d>c&&(U=m,d=c)}var u=t[U].slice();"horizontal"===e?u[1]=V:u[0]=V,o.push(u)}}return o},_getSmooth:function(e){return e?.3:0},_getCalculableItem:function(e,t,i,n,a,o){var r=this.series,l=r[e].calculableHolderColor||this.ecTheme.calculableHolderColor||s.calculableHolderColor,h=this._getSymbol(e,t,i,n,a,o);return h.style.color=l,h.style.strokeColor=l,h.rotation=[0,0],h.hoverable=!1,h.draggable=!1,h.style.text=void 0,h},_getSymbol:function(e,t,i,n,a,o){var r=this.series,s=r[e],l=s.data[t],h=this.getSymbolShape(s,e,l,t,i,n,a,this._sIndex2ShapeMap[e],this._sIndex2ColorMap[e],"#fff","vertical"===o?"horizontal":"vertical");return h.zlevel=s.zlevel,h.z=s.z+1,this.deepQuery([l,s,this.option],"calculable")&&(this.setCalculable(h),h.draggable=!0),h},getMarkCoord:function(e,t){var i=this.series[e],n=this.xMarkMap[e],a=this.component.xAxis.getAxis(i.xAxisIndex),o=this.component.yAxis.getAxis(i.yAxisIndex);if(t.type&&("max"===t.type||"min"===t.type||"average"===t.type)){var r=null!=t.valueIndex?t.valueIndex:null!=n.maxX0?"1":"";return[n[t.type+"X"+r],n[t.type+"Y"+r],n[t.type+"Line"+r],n[t.type+r]]}return["string"!=typeof t.xAxis&&a.getCoordByIndex?a.getCoordByIndex(t.xAxis||0):a.getCoord(t.xAxis||0),"string"!=typeof t.yAxis&&o.getCoordByIndex?o.getCoordByIndex(t.yAxis||0):o.getCoord(t.yAxis||0)]},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()},ontooltipHover:function(e,t){for(var i,n,a=e.seriesIndex,o=e.dataIndex,r=a.length;r--;)if(i=this.finalPLMap[a[r]])for(var s=0,l=i.length;l>s;s++){n=i[s];for(var h=0,m=n.length;m>h;h++)o===n[h][2]&&t.push(this._getSymbol(a[r],n[h][2],n[h][3],n[h][0],n[h][1],"horizontal"))}},addDataAnimation:function(e,t){function i(){c--,0===c&&t&&t()}function n(e){e.style.controlPointList=null}for(var a=this.series,o={},r=0,s=e.length;s>r;r++)o[e[r][0]]=e[r];for(var l,h,m,V,U,d,p,c=0,r=this.shapeList.length-1;r>=0;r--)if(U=this.shapeList[r]._seriesIndex,o[U]&&!o[U][3]){if(this.shapeList[r]._main&&this.shapeList[r].style.pointList.length>1){if(d=this.shapeList[r].style.pointList,h=Math.abs(d[0][0]-d[1][0]),V=Math.abs(d[0][1]-d[1][1]),p="horizontal"===this.shapeList[r]._orient,o[U][2]){if("half-smooth-polygon"===this.shapeList[r].type){var u=d.length;this.shapeList[r].style.pointList[u-3]=d[u-2],this.shapeList[r].style.pointList[u-3][p?0:1]=d[u-4][p?0:1],this.shapeList[r].style.pointList[u-2]=d[u-1]}this.shapeList[r].style.pointList.pop(),p?(l=h,m=0):(l=0,m=-V)}else{if(this.shapeList[r].style.pointList.shift(),"half-smooth-polygon"===this.shapeList[r].type){var y=this.shapeList[r].style.pointList.pop();p?y[0]=d[0][0]:y[1]=d[0][1],this.shapeList[r].style.pointList.push(y)}p?(l=-h,m=0):(l=0,m=V)}this.shapeList[r].style.controlPointList=null,this.zr.modShape(this.shapeList[r])}else{if(o[U][2]&&this.shapeList[r]._dataIndex===a[U].data.length-1){this.zr.delShape(this.shapeList[r].id);continue}if(!o[U][2]&&0===this.shapeList[r]._dataIndex){this.zr.delShape(this.shapeList[r].id);continue}}this.shapeList[r].position=[0,0],c++,this.zr.animate(this.shapeList[r].id,"").when(this.query(this.option,"animationDurationUpdate"),{position:[l,m]}).during(n).done(i).start()}c||t&&t()}},o.prototype.iconLibrary.legendLineIcon=i,h.inherits(t,n),e("../chart").define("line",t),t}),i("echarts/util/shape/HalfSmoothPolygon",["require","zrender/shape/Base","zrender/shape/util/smoothBezier","zrender/tool/util","zrender/shape/Polygon"],function(e){function t(e){i.call(this,e)}var i=e("zrender/shape/Base"),n=e("zrender/shape/util/smoothBezier"),a=e("zrender/tool/util");return t.prototype={type:"half-smooth-polygon",buildPath:function(t,i){var a=i.pointList;if(!(a.length<2))if(i.smooth){var o=n(a.slice(0,-2),i.smooth,!1,i.smoothConstraint);t.moveTo(a[0][0],a[0][1]);for(var r,s,l,h=a.length,m=0;h-3>m;m++)r=o[2*m],s=o[2*m+1],l=a[m+1],t.bezierCurveTo(r[0],r[1],s[0],s[1],l[0],l[1]);t.lineTo(a[h-2][0],a[h-2][1]),t.lineTo(a[h-1][0],a[h-1][1]),t.lineTo(a[0][0],a[0][1])}else e("zrender/shape/Polygon").prototype.buildPath(t,i)}},a.inherits(t,i),t}),i("echarts/chart/bar",["require","./base","zrender/shape/Rectangle","../component/axis","../component/grid","../component/dataZoom","../config","../util/ecData","zrender/tool/util","zrender/tool/color","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Rectangle");e("../component/axis"),e("../component/grid"),e("../component/dataZoom");var a=e("../config");a.bar={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,xAxisIndex:0,yAxisIndex:0,barMinHeight:0,barGap:"30%",barCategoryGap:"20%",itemStyle:{normal:{barBorderColor:"#fff",barBorderRadius:0,barBorderWidth:0,label:{show:!1}},emphasis:{barBorderColor:"#fff",barBorderRadius:0,barBorderWidth:0,label:{show:!1}}}};var o=e("../util/ecData"),r=e("zrender/tool/util"),s=e("zrender/tool/color");return t.prototype={type:a.CHART_TYPE_BAR,_buildShape:function(){this._buildPosition()},_buildNormal:function(e,t,i,o,r){for(var s,l,h,m,V,U,d,p,c,u,y,g,b=this.series,f=i[0][0],k=b[f],x="horizontal"==r,_=this.component.xAxis,L=this.component.yAxis,W=x?_.getAxis(k.xAxisIndex):L.getAxis(k.yAxisIndex),X=this._mapSize(W,i),v=X.gap,w=X.barGap,K=X.barWidthMap,I=X.barMaxWidthMap,J=X.barWidth,C=X.barMinHeightMap,S=X.interval,E=this.deepQuery([this.ecTheme,a],"island.r"),F=0,T=t;T>F&&null!=W.getNameByIndex(F);F++){x?m=W.getCoordByIndex(F)-v/2:V=W.getCoordByIndex(F)+v/2;for(var z=0,A=i.length;A>z;z++){var M=b[i[z][0]].yAxisIndex||0,O=b[i[z][0]].xAxisIndex||0;s=x?L.getAxis(M):_.getAxis(O),d=U=c=p=s.getCoord(0);for(var P=0,D=i[z].length;D>P;P++)f=i[z][P],k=b[f],y=k.data[F],g=this.getDataFromOption(y,"-"),o[f]=o[f]||{min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY,sum:0,counter:0,average:0},h=Math.min(I[f]||Number.MAX_VALUE,K[f]||J),"-"!==g&&(g>0?(l=P>0?s.getCoordSize(g):x?d-s.getCoord(g):s.getCoord(g)-d,1===D&&C[f]>l&&(l=C[f]),x?(U-=l,V=U):(m=U,U+=l)):0>g?(l=P>0?s.getCoordSize(g):x?s.getCoord(g)-c:c-s.getCoord(g),1===D&&C[f]>l&&(l=C[f]),x?(V=p,p+=l):(p-=l,m=p)):(l=0,x?(U-=l,V=U):(m=U,U+=l)),o[f][F]=x?m+h/2:V-h/2,o[f].min>g&&(o[f].min=g,x?(o[f].minY=V,o[f].minX=o[f][F]):(o[f].minX=m+l,o[f].minY=o[f][F])),o[f].maxP;P++)f=i[z][P],k=b[f],y=k.data[F],g=this.getDataFromOption(y,"-"),h=Math.min(I[f]||Number.MAX_VALUE,K[f]||J),"-"==g&&this.deepQuery([y,k,this.option],"calculable")&&(x?(U-=E,V=U):(m=U,U+=E),u=this._getBarItem(f,F,W.getNameByIndex(F),m,V-(x?0:h),x?h:E,x?E:h,x?"vertical":"horizontal"),u.hoverable=!1,u.draggable=!1,u.style.lineWidth=1,u.style.brushType="stroke",u.style.strokeColor=k.calculableHolderColor||this.ecTheme.calculableHolderColor||a.calculableHolderColor,this.shapeList.push(new n(u)));x?m+=h+w:V-=h+w}}this._calculMarkMapXY(o,i,x?"y":"x")},_buildHorizontal:function(e,t,i,n){return this._buildNormal(e,t,i,n,"horizontal")},_buildVertical:function(e,t,i,n){return this._buildNormal(e,t,i,n,"vertical")},_buildOther:function(e,t,i,a){for(var o=this.series,r=0,s=i.length;s>r;r++)for(var l=0,h=i[r].length;h>l;l++){var m=i[r][l],V=o[m],U=V.xAxisIndex||0,d=this.component.xAxis.getAxis(U),p=d.getCoord(0),c=V.yAxisIndex||0,u=this.component.yAxis.getAxis(c),y=u.getCoord(0);a[m]=a[m]||{min0:Number.POSITIVE_INFINITY,min1:Number.POSITIVE_INFINITY,max0:Number.NEGATIVE_INFINITY,max1:Number.NEGATIVE_INFINITY,sum0:0,sum1:0,counter0:0,counter1:0,average0:0,average1:0};for(var g=0,b=V.data.length;b>g;g++){var f=V.data[g],k=this.getDataFromOption(f,"-");if(k instanceof Array){var x,_,L=d.getCoord(k[0]),W=u.getCoord(k[1]),X=[f,V],v=this.deepQuery(X,"barWidth")||10,w=this.deepQuery(X,"barHeight");null!=w?(x="horizontal",k[0]>0?(v=L-p,L-=v):v=k[0]<0?p-L:0,_=this._getBarItem(m,g,k[0],L,W-w/2,v,w,x)):(x="vertical",k[1]>0?w=y-W:k[1]<0?(w=W-y,W-=w):w=0,_=this._getBarItem(m,g,k[0],L-v/2,W,v,w,x)),this.shapeList.push(new n(_)),L=d.getCoord(k[0]),W=u.getCoord(k[1]),a[m].min0>k[0]&&(a[m].min0=k[0],a[m].minY0=W,a[m].minX0=L),a[m].max0k[1]&&(a[m].min1=k[1],a[m].minY1=W,a[m].minX1=L),a[m].max1=a&&(d=Math.floor(t.length/n),a=1);else if(n="string"==typeof U&&U.match(/%$/)?(e.getGap()*(100-parseFloat(U))/100).toFixed(2)-0:e.getGap()-U,"string"==typeof V&&V.match(/%$/)?(V=parseFloat(V)/100,a=+((n-m)/((t.length-1)*V+t.length-h)).toFixed(2),V=a*V):(V=parseFloat(V),a=+((n-m-V*(t.length-1))/(t.length-h)).toFixed(2)),0>=a)return this._mapSize(e,t,!0)}else if(n=h>1?"string"==typeof U&&U.match(/%$/)?+(e.getGap()*(100-parseFloat(U))/100).toFixed(2):e.getGap()-U:m,a=0,V=h>1?+((n-m)/(h-1)).toFixed(2):0,0>V)return this._mapSize(e,t,!0);return this._recheckBarMaxWidth(t,r,s,l,n,a,V,d)},_findSpecialBarSzie:function(e,t){for(var i,n,a,o,r=this.series,s={},l={},h={},m=0,V=0,U=0,d=e.length;d>U;U++)for(var p={barWidth:!1,barMaxWidth:!1},c=0,u=e[U].length;u>c;c++){var y=e[U][c],g=r[y];if(!t){if(p.barWidth)s[y]=i;else if(i=this.query(g,"barWidth"),null!=i){s[y]=i,V+=i,m++,p.barWidth=!0;for(var b=0,f=c;f>b;b++){var k=e[U][b];s[k]=i}}if(p.barMaxWidth)l[y]=n;else if(n=this.query(g,"barMaxWidth"),null!=n){l[y]=n,p.barMaxWidth=!0;for(var b=0,f=c;f>b;b++){var k=e[U][b];l[k]=n}}}h[y]=this.query(g,"barMinHeight"),a=null!=a?a:this.query(g,"barGap"),o=null!=o?o:this.query(g,"barCategoryGap")}return{barWidthMap:s,barMaxWidthMap:l,barMinHeightMap:h,sBarWidth:i,sBarMaxWidth:n,sBarWidthCounter:m,sBarWidthTotal:V,barGap:a,barCategoryGap:o}},_recheckBarMaxWidth:function(e,t,i,n,a,o,r,s){for(var l=0,h=e.length;h>l;l++){var m=e[l][0];i[m]&&i[m]0&&b.height>g&&b.width>g?(b.y+=g/2,b.height-=g,b.x+=g/2,b.width-=g):b.brushType="fill",m.highlightStyle.textColor=m.highlightStyle.color,m=this.addLabel(m,U,d,i,h);for(var f=[b,m.highlightStyle],k=0,x=f.length;x>k;k++){var _=f[k].textPosition;if("insideLeft"===_||"insideRight"===_||"insideTop"===_||"insideBottom"===_){var L=5;switch(_){case"insideLeft":f[k].textX=b.x+L,f[k].textY=b.y+b.height/2,f[k].textAlign="left",f[k].textBaseline="middle";break;case"insideRight":f[k].textX=b.x+b.width-L,f[k].textY=b.y+b.height/2,f[k].textAlign="right",f[k].textBaseline="middle";break;case"insideTop":f[k].textX=b.x+b.width/2,f[k].textY=b.y+L/2,f[k].textAlign="center",f[k].textBaseline="top";break;case"insideBottom":f[k].textX=b.x+b.width/2,f[k].textY=b.y+b.height-L/2,f[k].textAlign="center",f[k].textBaseline="bottom"}f[k].textPosition="specific",f[k].textColor=f[k].textColor||"#fff"}}return this.deepQuery([d,U,this.option],"calculable")&&(this.setCalculable(m),m.draggable=!0),o.pack(m,V[e],e,V[e].data[t],t,i),m},getMarkCoord:function(e,t){var i,n,a=this.series[e],o=this.xMarkMap[e],r=this.component.xAxis.getAxis(a.xAxisIndex),s=this.component.yAxis.getAxis(a.yAxisIndex);if(!t.type||"max"!==t.type&&"min"!==t.type&&"average"!==t.type)if(o.isHorizontal){i="string"==typeof t.xAxis&&r.getIndexByName?r.getIndexByName(t.xAxis):t.xAxis||0;var l=o[i];l=null!=l?l:"string"!=typeof t.xAxis&&r.getCoordByIndex?r.getCoordByIndex(t.xAxis||0):r.getCoord(t.xAxis||0),n=[l,s.getCoord(t.yAxis||0)]}else{i="string"==typeof t.yAxis&&s.getIndexByName?s.getIndexByName(t.yAxis):t.yAxis||0;var h=o[i];h=null!=h?h:"string"!=typeof t.yAxis&&s.getCoordByIndex?s.getCoordByIndex(t.yAxis||0):s.getCoord(t.yAxis||0),n=[r.getCoord(t.xAxis||0),h]}else{var m=null!=t.valueIndex?t.valueIndex:null!=o.maxX0?"1":"";n=[o[t.type+"X"+m],o[t.type+"Y"+m],o[t.type+"Line"+m],o[t.type+m]]}return n},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()},addDataAnimation:function(e,t){function i(){c--,0===c&&t&&t()}for(var n=this.series,a={},r=0,s=e.length;s>r;r++)a[e[r][0]]=e[r];for(var l,h,m,V,U,d,p,c=0,r=this.shapeList.length-1;r>=0;r--)if(d=o.get(this.shapeList[r],"seriesIndex"),a[d]&&!a[d][3]&&"rectangle"===this.shapeList[r].type){if(p=o.get(this.shapeList[r],"dataIndex"),U=n[d],a[d][2]&&p===U.data.length-1){this.zr.delShape(this.shapeList[r].id);continue}if(!a[d][2]&&0===p){this.zr.delShape(this.shapeList[r].id);continue}"horizontal"===this.shapeList[r]._orient?(V=this.component.yAxis.getAxis(U.yAxisIndex||0).getGap(),m=a[d][2]?-V:V,l=0):(h=this.component.xAxis.getAxis(U.xAxisIndex||0).getGap(),l=a[d][2]?h:-h,m=0),this.shapeList[r].position=[0,0],c++,this.zr.animate(this.shapeList[r].id,"").when(this.query(this.option,"animationDurationUpdate"),{position:[l,m]}).done(i).start()}c||t&&t()}},r.inherits(t,i),e("../chart").define("bar",t),t}),i("echarts/chart/scatter",["require","./base","../util/shape/Symbol","../component/axis","../component/grid","../component/dataZoom","../component/dataRange","../config","zrender/tool/util","zrender/tool/color","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e("./base"),n=e("../util/shape/Symbol");e("../component/axis"),e("../component/grid"),e("../component/dataZoom"),e("../component/dataRange");var a=e("../config");a.scatter={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,xAxisIndex:0,yAxisIndex:0,symbolSize:4,large:!1,largeThreshold:2e3,itemStyle:{normal:{label:{show:!1}},emphasis:{label:{show:!1}}}};var o=e("zrender/tool/util"),r=e("zrender/tool/color");return t.prototype={type:a.CHART_TYPE_SCATTER,_buildShape:function(){var e=this.series;this._sIndex2ColorMap={},this._symbol=this.option.symbolList,this._sIndex2ShapeMap={},this.selectedMap={},this.xMarkMap={};for(var t,i,n,o,s=this.component.legend,l=[],h=0,m=e.length;m>h;h++)if(t=e[h],i=t.name,t.type===a.CHART_TYPE_SCATTER){if(e[h]=this.reformOption(e[h]),this.legendHoverLink=e[h].legendHoverLink||this.legendHoverLink,this._sIndex2ShapeMap[h]=this.query(t,"symbol")||this._symbol[h%this._symbol.length],s){if(this.selectedMap[i]=s.isSelected(i),this._sIndex2ColorMap[h]=r.alpha(s.getColor(i),.5),n=s.getItemShape(i)){var o=this._sIndex2ShapeMap[h];n.style.brushType=o.match("empty")?"stroke":"both",o=o.replace("empty","").toLowerCase(),o.match("rectangle")&&(n.style.x+=Math.round((n.style.width-n.style.height)/2),n.style.width=n.style.height),o.match("star")&&(n.style.n=o.replace("star","")-0||5,o="star"),o.match("image")&&(n.style.image=o.replace(new RegExp("^image:\\/\\/"),""),n.style.x+=Math.round((n.style.width-n.style.height)/2),n.style.width=n.style.height,o="image"),n.style.iconType=o,s.setItemShape(i,n)}}else this.selectedMap[i]=!0,this._sIndex2ColorMap[h]=r.alpha(this.zr.getColor(h),.5);this.selectedMap[i]&&l.push(h)}this._buildSeries(l),this.addShapeList()},_buildSeries:function(e){if(0!==e.length){for(var t,i,n,a,o,r,s,l,h=this.series,m={},V=0,U=e.length;U>V;V++)if(t=e[V],i=h[t],0!==i.data.length){o=this.component.xAxis.getAxis(i.xAxisIndex||0),r=this.component.yAxis.getAxis(i.yAxisIndex||0),m[t]=[];for(var d=0,p=i.data.length;p>d;d++)n=i.data[d],a=this.getDataFromOption(n,"-"),"-"===a||a.length<2||(s=o.getCoord(a[0]),l=r.getCoord(a[1]),m[t].push([s,l,d,n.name||""]));this.xMarkMap[t]=this._markMap(o,r,i.data,m[t]),this.buildMark(t)}this._buildPointList(m)}},_markMap:function(e,t,i,n){for(var a,o={min0:Number.POSITIVE_INFINITY,max0:Number.NEGATIVE_INFINITY,sum0:0,counter0:0,average0:0,min1:Number.POSITIVE_INFINITY,max1:Number.NEGATIVE_INFINITY,sum1:0,counter1:0,average1:0},r=0,s=n.length;s>r;r++)a=i[n[r][2]].value||i[n[r][2]],o.min0>a[0]&&(o.min0=a[0],o.minY0=n[r][1],o.minX0=n[r][0]),o.max0a[1]&&(o.min1=a[1],o.minY1=n[r][1],o.minX1=n[r][0]),o.max1t.largeThreshold)this.shapeList.push(this._getLargeSymbol(t,i,this.getItemStyleColor(this.query(t,"itemStyle.normal.color"),r,-1)||this._sIndex2ColorMap[r]));else for(var s=0,l=i.length;l>s;s++)n=i[s],a=this._getSymbol(r,n[2],n[3],n[0],n[1]),a&&this.shapeList.push(a)},_getSymbol:function(e,t,i,n,a){var o,r=this.series,s=r[e],l=s.data[t],h=this.component.dataRange;if(h){if(o=isNaN(l[2])?this._sIndex2ColorMap[e]:h.getColor(l[2]),!o)return null}else o=this._sIndex2ColorMap[e];var m=this.getSymbolShape(s,e,l,t,i,n,a,this._sIndex2ShapeMap[e],o,"rgba(0,0,0,0)","vertical");return m.zlevel=s.zlevel,m.z=s.z,m._main=!0,m},_getLargeSymbol:function(e,t,i){return new n({zlevel:e.zlevel,z:e.z,_main:!0,hoverable:!1,style:{pointList:t,color:i,strokeColor:i},highlightStyle:{pointList:[]}})},getMarkCoord:function(e,t){var i,n=this.series[e],a=this.xMarkMap[e],o=this.component.xAxis.getAxis(n.xAxisIndex),r=this.component.yAxis.getAxis(n.yAxisIndex);if(!t.type||"max"!==t.type&&"min"!==t.type&&"average"!==t.type)i=["string"!=typeof t.xAxis&&o.getCoordByIndex?o.getCoordByIndex(t.xAxis||0):o.getCoord(t.xAxis||0),"string"!=typeof t.yAxis&&r.getCoordByIndex?r.getCoordByIndex(t.yAxis||0):r.getCoord(t.yAxis||0)];else{var s=null!=t.valueIndex?t.valueIndex:1;i=[a[t.type+"X"+s],a[t.type+"Y"+s],a[t.type+"Line"+s],a[t.type+s]]}return i},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()},ondataRange:function(e,t){this.component.dataRange&&(this.refresh(),t.needRefresh=!0)}},o.inherits(t,i),e("../chart").define("scatter",t),t}),i("echarts/component/dataRange",["require","./base","zrender/shape/Text","zrender/shape/Rectangle","../util/shape/HandlePolygon","../config","zrender/tool/util","zrender/tool/event","zrender/tool/area","zrender/tool/color","../component"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o);var s=this;s._ondrift=function(e,t){return s.__ondrift(this,e,t)},s._ondragend=function(){return s.__ondragend()},s._dataRangeSelected=function(e){return s.__dataRangeSelected(e)},s._dispatchHoverLink=function(e){return s.__dispatchHoverLink(e)},s._onhoverlink=function(e){return s.__onhoverlink(e); - -},this._selectedMap={},this._range={},this.refresh(a),t.bind(r.EVENT.HOVER,this._onhoverlink)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Rectangle"),o=e("../util/shape/HandlePolygon"),r=e("../config");r.dataRange={zlevel:0,z:4,show:!0,orient:"vertical",x:"left",y:"bottom",backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,padding:5,itemGap:10,itemWidth:20,itemHeight:14,precision:0,splitNumber:5,splitList:null,calculable:!1,selectedMode:!0,hoverLink:!0,realtime:!0,color:["#006edd","#e0ffff"],textStyle:{color:"#333"}};var s=e("zrender/tool/util"),l=e("zrender/tool/event"),h=e("zrender/tool/area"),m=e("zrender/tool/color");return t.prototype={type:r.COMPONENT_TYPE_DATARANGE,_textGap:10,_buildShape:function(){if(this._itemGroupLocation=this._getItemGroupLocation(),this._buildBackground(),this._isContinuity()?this._buildGradient():this._buildItem(),this.dataRangeOption.show)for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e]);this._syncShapeFromRange()},_buildItem:function(){var e,t,i,o,r=this._valueTextList,s=r.length,l=this.getFont(this.dataRangeOption.textStyle),m=this._itemGroupLocation.x,V=this._itemGroupLocation.y,U=this.dataRangeOption.itemWidth,d=this.dataRangeOption.itemHeight,p=this.dataRangeOption.itemGap,c=h.getTextHeight("国",l);"vertical"==this.dataRangeOption.orient&&"right"==this.dataRangeOption.x&&(m=this._itemGroupLocation.x+this._itemGroupLocation.width-U);var u=!0;this.dataRangeOption.text&&(u=!1,this.dataRangeOption.text[0]&&(i=this._getTextShape(m,V,this.dataRangeOption.text[0]),"horizontal"==this.dataRangeOption.orient?m+=h.getTextWidth(this.dataRangeOption.text[0],l)+this._textGap:(V+=c+this._textGap,i.style.y+=c/2+this._textGap,i.style.textBaseline="bottom"),this.shapeList.push(new n(i))));for(var y=0;s>y;y++)e=r[y],o=this.getColorByIndex(y),t=this._getItemShape(m,V,U,d,this._selectedMap[y]?o:"#ccc"),t._idx=y,t.onmousemove=this._dispatchHoverLink,this.dataRangeOption.selectedMode&&(t.clickable=!0,t.onclick=this._dataRangeSelected),this.shapeList.push(new a(t)),u&&(i={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:m+U+5,y:V,color:this._selectedMap[y]?this.dataRangeOption.textStyle.color:"#ccc",text:r[y],textFont:l,textBaseline:"top"},highlightStyle:{brushType:"fill"}},"vertical"==this.dataRangeOption.orient&&"right"==this.dataRangeOption.x&&(i.style.x-=U+10,i.style.textAlign="right"),i._idx=y,i.onmousemove=this._dispatchHoverLink,this.dataRangeOption.selectedMode&&(i.clickable=!0,i.onclick=this._dataRangeSelected),this.shapeList.push(new n(i))),"horizontal"==this.dataRangeOption.orient?m+=U+(u?5:0)+(u?h.getTextWidth(e,l):0)+p:V+=d+p;!u&&this.dataRangeOption.text[1]&&("horizontal"==this.dataRangeOption.orient?m=m-p+this._textGap:V=V-p+this._textGap,i=this._getTextShape(m,V,this.dataRangeOption.text[1]),"horizontal"!=this.dataRangeOption.orient&&(i.style.y-=5,i.style.textBaseline="top"),this.shapeList.push(new n(i)))},_buildGradient:function(){var t,i,o=this.getFont(this.dataRangeOption.textStyle),r=this._itemGroupLocation.x,s=this._itemGroupLocation.y,l=this.dataRangeOption.itemWidth,m=this.dataRangeOption.itemHeight,V=h.getTextHeight("国",o),U=10,d=!0;this.dataRangeOption.text&&(d=!1,this.dataRangeOption.text[0]&&(i=this._getTextShape(r,s,this.dataRangeOption.text[0]),"horizontal"==this.dataRangeOption.orient?r+=h.getTextWidth(this.dataRangeOption.text[0],o)+this._textGap:(s+=V+this._textGap,i.style.y+=V/2+this._textGap,i.style.textBaseline="bottom"),this.shapeList.push(new n(i))));for(var p=e("zrender/tool/color"),c=1/(this.dataRangeOption.color.length-1),u=[],y=0,g=this.dataRangeOption.color.length;g>y;y++)u.push([y*c,this.dataRangeOption.color[y]]);"horizontal"==this.dataRangeOption.orient?(t={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:r,y:s,width:l*U,height:m,color:p.getLinearGradient(r,s,r+l*U,s,u)},hoverable:!1},r+=l*U+this._textGap):(t={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:r,y:s,width:l,height:m*U,color:p.getLinearGradient(r,s,r,s+m*U,u)},hoverable:!1},s+=m*U+this._textGap),this.shapeList.push(new a(t)),this._calculableLocation=t.style,this.dataRangeOption.calculable&&(this._buildFiller(),this._bulidMask(),this._bulidHandle()),this._buildIndicator(),!d&&this.dataRangeOption.text[1]&&(i=this._getTextShape(r,s,this.dataRangeOption.text[1]),this.shapeList.push(new n(i)))},_buildIndicator:function(){var e,t,i=this._calculableLocation.x,n=this._calculableLocation.y,a=this._calculableLocation.width,r=this._calculableLocation.height,s=5;"horizontal"==this.dataRangeOption.orient?"bottom"!=this.dataRangeOption.y?(e=[[i,n+r],[i-s,n+r+s],[i+s,n+r+s]],t="bottom"):(e=[[i,n],[i-s,n-s],[i+s,n-s]],t="top"):"right"!=this.dataRangeOption.x?(e=[[i+a,n],[i+a+s,n-s],[i+a+s,n+s]],t="right"):(e=[[i,n],[i-s,n-s],[i-s,n+s]],t="left"),this._indicatorShape={style:{pointList:e,color:"#fff",__rect:{x:Math.min(e[0][0],e[1][0]),y:Math.min(e[0][1],e[1][1]),width:s*("horizontal"==this.dataRangeOption.orient?2:1),height:s*("horizontal"==this.dataRangeOption.orient?1:2)}},highlightStyle:{brushType:"fill",textPosition:t,textColor:this.dataRangeOption.textStyle.color},hoverable:!1},this._indicatorShape=new o(this._indicatorShape)},_buildFiller:function(){this._fillerShape={zlevel:this.getZlevelBase(),z:this.getZBase()+1,style:{x:this._calculableLocation.x,y:this._calculableLocation.y,width:this._calculableLocation.width,height:this._calculableLocation.height,color:"rgba(255,255,255,0)"},highlightStyle:{strokeColor:"rgba(255,255,255,0.5)",lineWidth:1},draggable:!0,ondrift:this._ondrift,ondragend:this._ondragend,onmousemove:this._dispatchHoverLink,_type:"filler"},this._fillerShape=new a(this._fillerShape),this.shapeList.push(this._fillerShape)},_bulidHandle:function(){var e,t,i,n,a,r,s,l,m=this._calculableLocation.x,V=this._calculableLocation.y,U=this._calculableLocation.width,d=this._calculableLocation.height,p=this.getFont(this.dataRangeOption.textStyle),c=h.getTextHeight("国",p),u=Math.max(h.getTextWidth(this._textFormat(this.dataRangeOption.max),p),h.getTextWidth(this._textFormat(this.dataRangeOption.min),p))+2;"horizontal"==this.dataRangeOption.orient?"bottom"!=this.dataRangeOption.y?(e=[[m,V],[m,V+d+c],[m-c,V+d+c],[m-1,V+d],[m-1,V]],t=m-u/2-c,i=V+d+c/2+2,n={x:m-u-c,y:V+d,width:u+c,height:c},a=[[m+U,V],[m+U,V+d+c],[m+U+c,V+d+c],[m+U+1,V+d],[m+U+1,V]],r=m+U+u/2+c,s=i,l={x:m+U,y:V+d,width:u+c,height:c}):(e=[[m,V+d],[m,V-c],[m-c,V-c],[m-1,V],[m-1,V+d]],t=m-u/2-c,i=V-c/2-2,n={x:m-u-c,y:V-c,width:u+c,height:c},a=[[m+U,V+d],[m+U,V-c],[m+U+c,V-c],[m+U+1,V],[m+U+1,V+d]],r=m+U+u/2+c,s=i,l={x:m+U,y:V-c,width:u+c,height:c}):(u+=c,"right"!=this.dataRangeOption.x?(e=[[m,V],[m+U+c,V],[m+U+c,V-c],[m+U,V-1],[m,V-1]],t=m+U+u/2+c/2,i=V-c/2,n={x:m+U,y:V-c,width:u+c,height:c},a=[[m,V+d],[m+U+c,V+d],[m+U+c,V+c+d],[m+U,V+1+d],[m,V+d+1]],r=t,s=V+d+c/2,l={x:m+U,y:V+d,width:u+c,height:c}):(e=[[m+U,V],[m-c,V],[m-c,V-c],[m,V-1],[m+U,V-1]],t=m-u/2-c/2,i=V-c/2,n={x:m-u-c,y:V-c,width:u+c,height:c},a=[[m+U,V+d],[m-c,V+d],[m-c,V+c+d],[m,V+1+d],[m+U,V+d+1]],r=t,s=V+d+c/2,l={x:m-u-c,y:V+d,width:u+c,height:c})),this._startShape={style:{pointList:e,text:this._textFormat(this.dataRangeOption.max),textX:t,textY:i,textFont:p,color:this.getColor(this.dataRangeOption.max),rect:n,x:e[0][0],y:e[0][1],_x:e[0][0],_y:e[0][1]}},this._startShape.highlightStyle={strokeColor:this._startShape.style.color,lineWidth:1},this._endShape={style:{pointList:a,text:this._textFormat(this.dataRangeOption.min),textX:r,textY:s,textFont:p,color:this.getColor(this.dataRangeOption.min),rect:l,x:a[0][0],y:a[0][1],_x:a[0][0],_y:a[0][1]}},this._endShape.highlightStyle={strokeColor:this._endShape.style.color,lineWidth:1},this._startShape.zlevel=this._endShape.zlevel=this.getZlevelBase(),this._startShape.z=this._endShape.z=this.getZBase()+1,this._startShape.draggable=this._endShape.draggable=!0,this._startShape.ondrift=this._endShape.ondrift=this._ondrift,this._startShape.ondragend=this._endShape.ondragend=this._ondragend,this._startShape.style.textColor=this._endShape.style.textColor=this.dataRangeOption.textStyle.color,this._startShape.style.textAlign=this._endShape.style.textAlign="center",this._startShape.style.textPosition=this._endShape.style.textPosition="specific",this._startShape.style.textBaseline=this._endShape.style.textBaseline="middle",this._startShape.style.width=this._endShape.style.width=0,this._startShape.style.height=this._endShape.style.height=0,this._startShape.style.textPosition=this._endShape.style.textPosition="specific",this._startShape=new o(this._startShape),this._endShape=new o(this._endShape),this.shapeList.push(this._startShape),this.shapeList.push(this._endShape)},_bulidMask:function(){var e=this._calculableLocation.x,t=this._calculableLocation.y,i=this._calculableLocation.width,n=this._calculableLocation.height;this._startMask={zlevel:this.getZlevelBase(),z:this.getZBase()+1,style:{x:e,y:t,width:"horizontal"==this.dataRangeOption.orient?0:i,height:"horizontal"==this.dataRangeOption.orient?n:0,color:"#ccc"},hoverable:!1},this._endMask={zlevel:this.getZlevelBase(),z:this.getZBase()+1,style:{x:"horizontal"==this.dataRangeOption.orient?e+i:e,y:"horizontal"==this.dataRangeOption.orient?t:t+n,width:"horizontal"==this.dataRangeOption.orient?0:i,height:"horizontal"==this.dataRangeOption.orient?n:0,color:"#ccc"},hoverable:!1},this._startMask=new a(this._startMask),this._endMask=new a(this._endMask),this.shapeList.push(this._startMask),this.shapeList.push(this._endMask)},_buildBackground:function(){var e=this.reformCssArray(this.dataRangeOption.padding);this.shapeList.push(new a({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._itemGroupLocation.x-e[3],y:this._itemGroupLocation.y-e[0],width:this._itemGroupLocation.width+e[3]+e[1],height:this._itemGroupLocation.height+e[0]+e[2],brushType:0===this.dataRangeOption.borderWidth?"fill":"both",color:this.dataRangeOption.backgroundColor,strokeColor:this.dataRangeOption.borderColor,lineWidth:this.dataRangeOption.borderWidth}}))},_getItemGroupLocation:function(){var e=this._valueTextList,t=e.length,i=this.dataRangeOption.itemGap,n=this.dataRangeOption.itemWidth,a=this.dataRangeOption.itemHeight,o=0,r=0,s=this.getFont(this.dataRangeOption.textStyle),l=h.getTextHeight("国",s),m=10;if("horizontal"==this.dataRangeOption.orient){if(this.dataRangeOption.text||this._isContinuity())o=(this._isContinuity()?n*m+i:t*(n+i))+(this.dataRangeOption.text&&"undefined"!=typeof this.dataRangeOption.text[0]?h.getTextWidth(this.dataRangeOption.text[0],s)+this._textGap:0)+(this.dataRangeOption.text&&"undefined"!=typeof this.dataRangeOption.text[1]?h.getTextWidth(this.dataRangeOption.text[1],s)+this._textGap:0);else{n+=5;for(var V=0;t>V;V++)o+=n+h.getTextWidth(e[V],s)+i}o-=i,r=Math.max(l,a)}else{var U;if(this.dataRangeOption.text||this._isContinuity())r=(this._isContinuity()?a*m+i:t*(a+i))+(this.dataRangeOption.text&&"undefined"!=typeof this.dataRangeOption.text[0]?this._textGap+l:0)+(this.dataRangeOption.text&&"undefined"!=typeof this.dataRangeOption.text[1]?this._textGap+l:0),U=Math.max(h.getTextWidth(this.dataRangeOption.text&&this.dataRangeOption.text[0]||"",s),h.getTextWidth(this.dataRangeOption.text&&this.dataRangeOption.text[1]||"",s)),o=Math.max(n,U);else{r=(a+i)*t,n+=5,U=0;for(var V=0;t>V;V++)U=Math.max(U,h.getTextWidth(e[V],s));o=n+U}r-=i}var d,p=this.reformCssArray(this.dataRangeOption.padding),c=this.zr.getWidth();switch(this.dataRangeOption.x){case"center":d=Math.floor((c-o)/2);break;case"left":d=p[3]+this.dataRangeOption.borderWidth;break;case"right":d=c-o-p[1]-this.dataRangeOption.borderWidth;break;default:d=this.parsePercent(this.dataRangeOption.x,c),d=isNaN(d)?0:d}var u,y=this.zr.getHeight();switch(this.dataRangeOption.y){case"top":u=p[0]+this.dataRangeOption.borderWidth;break;case"bottom":u=y-r-p[2]-this.dataRangeOption.borderWidth;break;case"center":u=Math.floor((y-r)/2);break;default:u=this.parsePercent(this.dataRangeOption.y,y),u=isNaN(u)?0:u}if(this.dataRangeOption.calculable){var g=Math.max(h.getTextWidth(this.dataRangeOption.max,s),h.getTextWidth(this.dataRangeOption.min,s))+l;"horizontal"==this.dataRangeOption.orient?(g>d&&(d=g),d+o+g>c&&(d-=g)):(l>u&&(u=l),u+r+l>y&&(u-=l))}return{x:d,y:u,width:o,height:r}},_getTextShape:function(e,t,i){return{zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:"horizontal"==this.dataRangeOption.orient?e:this._itemGroupLocation.x+this._itemGroupLocation.width/2,y:"horizontal"==this.dataRangeOption.orient?this._itemGroupLocation.y+this._itemGroupLocation.height/2:t,color:this.dataRangeOption.textStyle.color,text:i,textFont:this.getFont(this.dataRangeOption.textStyle),textBaseline:"horizontal"==this.dataRangeOption.orient?"middle":"top",textAlign:"horizontal"==this.dataRangeOption.orient?"left":"center"},hoverable:!1}},_getItemShape:function(e,t,i,n,a){return{zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:e,y:t+1,width:i,height:n-2,color:a},highlightStyle:{strokeColor:a,lineWidth:1}}},__ondrift:function(e,t,i){var n=this._calculableLocation.x,a=this._calculableLocation.y,o=this._calculableLocation.width,r=this._calculableLocation.height;return"horizontal"==this.dataRangeOption.orient?e.style.x+t<=n?e.style.x=n:e.style.x+t+e.style.width>=n+o?e.style.x=n+o-e.style.width:e.style.x+=t:e.style.y+i<=a?e.style.y=a:e.style.y+i+e.style.height>=a+r?e.style.y=a+r-e.style.height:e.style.y+=i,"filler"==e._type?this._syncHandleShape():this._syncFillerShape(e),this.dataRangeOption.realtime&&this._dispatchDataRange(),!0},__ondragend:function(){this.isDragend=!0},ondragend:function(e,t){this.isDragend&&e.target&&(t.dragOut=!0,t.dragIn=!0,this.dataRangeOption.realtime||this._dispatchDataRange(),t.needRefresh=!1,this.isDragend=!1)},_syncShapeFromRange:function(){var e=this.dataRangeOption.range||{},t=e.start,i=e.end;if(t>i&&(t=[i,i=t][0]),this._range.end=null!=t?t:null!=this._range.end?this._range.end:0,this._range.start=null!=i?i:null!=this._range.start?this._range.start:100,100!=this._range.start||0!==this._range.end){if("horizontal"==this.dataRangeOption.orient){var n=this._fillerShape.style.width;this._fillerShape.style.x+=n*(100-this._range.start)/100,this._fillerShape.style.width=n*(this._range.start-this._range.end)/100}else{var a=this._fillerShape.style.height;this._fillerShape.style.y+=a*(100-this._range.start)/100,this._fillerShape.style.height=a*(this._range.start-this._range.end)/100}this.zr.modShape(this._fillerShape.id),this._syncHandleShape()}},_syncHandleShape:function(){var e=this._calculableLocation.x,t=this._calculableLocation.y,i=this._calculableLocation.width,n=this._calculableLocation.height;"horizontal"==this.dataRangeOption.orient?(this._startShape.style.x=this._fillerShape.style.x,this._startMask.style.width=this._startShape.style.x-e,this._endShape.style.x=this._fillerShape.style.x+this._fillerShape.style.width,this._endMask.style.x=this._endShape.style.x,this._endMask.style.width=e+i-this._endShape.style.x,this._range.start=Math.ceil(100-(this._startShape.style.x-e)/i*100),this._range.end=Math.floor(100-(this._endShape.style.x-e)/i*100)):(this._startShape.style.y=this._fillerShape.style.y,this._startMask.style.height=this._startShape.style.y-t,this._endShape.style.y=this._fillerShape.style.y+this._fillerShape.style.height,this._endMask.style.y=this._endShape.style.y,this._endMask.style.height=t+n-this._endShape.style.y,this._range.start=Math.ceil(100-(this._startShape.style.y-t)/n*100),this._range.end=Math.floor(100-(this._endShape.style.y-t)/n*100)),this._syncShape()},_syncFillerShape:function(e){var t,i,n=this._calculableLocation.x,a=this._calculableLocation.y,o=this._calculableLocation.width,r=this._calculableLocation.height;"horizontal"==this.dataRangeOption.orient?(t=this._startShape.style.x,i=this._endShape.style.x,e.id==this._startShape.id&&t>=i?(i=t,this._endShape.style.x=t):e.id==this._endShape.id&&t>=i&&(t=i,this._startShape.style.x=t),this._fillerShape.style.x=t,this._fillerShape.style.width=i-t,this._startMask.style.width=t-n,this._endMask.style.x=i,this._endMask.style.width=n+o-i,this._range.start=Math.ceil(100-(t-n)/o*100),this._range.end=Math.floor(100-(i-n)/o*100)):(t=this._startShape.style.y,i=this._endShape.style.y,e.id==this._startShape.id&&t>=i?(i=t,this._endShape.style.y=t):e.id==this._endShape.id&&t>=i&&(t=i,this._startShape.style.y=t),this._fillerShape.style.y=t,this._fillerShape.style.height=i-t,this._startMask.style.height=t-a,this._endMask.style.y=i,this._endMask.style.height=a+r-i,this._range.start=Math.ceil(100-(t-a)/r*100),this._range.end=Math.floor(100-(i-a)/r*100)),this._syncShape()},_syncShape:function(){this._startShape.position=[this._startShape.style.x-this._startShape.style._x,this._startShape.style.y-this._startShape.style._y],this._startShape.style.text=this._textFormat(this._gap*this._range.start+this.dataRangeOption.min),this._startShape.style.color=this._startShape.highlightStyle.strokeColor=this.getColor(this._gap*this._range.start+this.dataRangeOption.min),this._endShape.position=[this._endShape.style.x-this._endShape.style._x,this._endShape.style.y-this._endShape.style._y],this._endShape.style.text=this._textFormat(this._gap*this._range.end+this.dataRangeOption.min),this._endShape.style.color=this._endShape.highlightStyle.strokeColor=this.getColor(this._gap*this._range.end+this.dataRangeOption.min),this.zr.modShape(this._startShape.id),this.zr.modShape(this._endShape.id),this.zr.modShape(this._startMask.id),this.zr.modShape(this._endMask.id),this.zr.modShape(this._fillerShape.id),this.zr.refreshNextFrame()},_dispatchDataRange:function(){this.messageCenter.dispatch(r.EVENT.DATA_RANGE,null,{range:{start:this._range.end,end:this._range.start}},this.myChart)},__dataRangeSelected:function(e){if("single"===this.dataRangeOption.selectedMode)for(var t in this._selectedMap)this._selectedMap[t]=!1;var i=e.target._idx;this._selectedMap[i]=!this._selectedMap[i];var n,a;this._useCustomizedSplit()?(n=this._splitList[i].max,a=this._splitList[i].min):(n=(this._colorList.length-i)*this._gap+this.dataRangeOption.min,a=n-this._gap),this.messageCenter.dispatch(r.EVENT.DATA_RANGE_SELECTED,e.event,{selected:this._selectedMap,target:i,valueMax:n,valueMin:a},this.myChart),this.messageCenter.dispatch(r.EVENT.REFRESH,null,null,this.myChart)},__dispatchHoverLink:function(e){var t,i;if(this.dataRangeOption.calculable){var n,a=this.dataRangeOption.max-this.dataRangeOption.min;n="horizontal"==this.dataRangeOption.orient?(1-(l.getX(e.event)-this._calculableLocation.x)/this._calculableLocation.width)*a:(1-(l.getY(e.event)-this._calculableLocation.y)/this._calculableLocation.height)*a,t=n-.05*a,i=n+.05*a}else if(this._useCustomizedSplit()){var o=e.target._idx;i=this._splitList[o].max,t=this._splitList[o].min}else{var o=e.target._idx;i=(this._colorList.length-o)*this._gap+this.dataRangeOption.min,t=i-this._gap}this.messageCenter.dispatch(r.EVENT.DATA_RANGE_HOVERLINK,e.event,{valueMin:t,valueMax:i},this.myChart)},__onhoverlink:function(e){if(this.dataRangeOption.show&&this.dataRangeOption.hoverLink&&this._indicatorShape&&e&&null!=e.seriesIndex&&null!=e.dataIndex){var t=e.value;if(""===t||isNaN(t))return;tthis.dataRangeOption.max&&(t=this.dataRangeOption.max),this._indicatorShape.position="horizontal"==this.dataRangeOption.orient?[(this.dataRangeOption.max-t)/(this.dataRangeOption.max-this.dataRangeOption.min)*this._calculableLocation.width,0]:[0,(this.dataRangeOption.max-t)/(this.dataRangeOption.max-this.dataRangeOption.min)*this._calculableLocation.height],this._indicatorShape.style.text=this._textFormat(e.value),this._indicatorShape.style.color=this.getColor(t),this.zr.addHoverShape(this._indicatorShape)}},_textFormat:function(e,t){var i=this.dataRangeOption;if(e!==-Number.MAX_VALUE&&(e=(+e).toFixed(i.precision)),null!=t&&t!==Number.MAX_VALUE&&(t=(+t).toFixed(i.precision)),i.formatter){if("string"==typeof i.formatter)return i.formatter.replace("{value}",e===-Number.MAX_VALUE?"min":e).replace("{value2}",t===Number.MAX_VALUE?"max":t);if("function"==typeof i.formatter)return i.formatter.call(this.myChart,e,t)}return null==t?e:e===-Number.MAX_VALUE?"< "+t:t===Number.MAX_VALUE?"> "+e:e+" - "+t},_isContinuity:function(){var e=this.dataRangeOption;return!(e.splitList?e.splitList.length>0:e.splitNumber>0)||e.calculable},_useCustomizedSplit:function(){var e=this.dataRangeOption;return e.splitList&&e.splitList.length>0},_buildColorList:function(e){if(this._colorList=m.getGradientColors(this.dataRangeOption.color,Math.max((e-this.dataRangeOption.color.length)/(this.dataRangeOption.color.length-1),0)+1),this._colorList.length>e){for(var t=this._colorList.length,i=[this._colorList[0]],n=t/(e-1),a=1;e-1>a;a++)i.push(this._colorList[Math.floor(a*n)]);i.push(this._colorList[t-1]),this._colorList=i}if(this._useCustomizedSplit())for(var o=this._splitList,a=0,t=o.length;t>a;a++)o[a].color&&(this._colorList[a]=o[a].color)},_buildGap:function(e){if(!this._useCustomizedSplit()){var t=this.dataRangeOption.precision;for(this._gap=(this.dataRangeOption.max-this.dataRangeOption.min)/e;this._gap.toFixed(t)-0!=this._gap&&5>t;)t++;this.dataRangeOption.precision=t,this._gap=((this.dataRangeOption.max-this.dataRangeOption.min)/e).toFixed(t)-0}},_buildDataList:function(e){for(var t=this._valueTextList=[],i=this.dataRangeOption,n=this._useCustomizedSplit(),a=0;e>a;a++){this._selectedMap[a]=!0;var o="";if(n){var r=this._splitList[e-1-a];o=null!=r.label?r.label:null!=r.single?this._textFormat(r.single):this._textFormat(r.min,r.max)}else o=this._textFormat(a*this._gap+i.min,(a+1)*this._gap+i.min);t.unshift(o)}},_buildSplitList:function(){if(this._useCustomizedSplit())for(var e=this.dataRangeOption.splitList,t=this._splitList=[],i=0,n=e.length;n>i;i++){var a=e[i];if(!a||null==a.start&&null==a.end)throw new Error("Empty item exists in splitList!");var o={label:a.label,color:a.color};o.min=a.start,o.max=a.end,o.min>o.max&&(o.min=[o.max,o.max=o.min][0]),o.min===o.max&&(o.single=o.max),null==o.min&&(o.min=-Number.MAX_VALUE),null==o.max&&(o.max=Number.MAX_VALUE),t.push(o)}},refresh:function(e){if(e){this.option=e,this.option.dataRange=this.reformOption(this.option.dataRange);var t=this.dataRangeOption=this.option.dataRange;if(!this._useCustomizedSplit()&&(null==t.min||null==t.max))throw new Error("option.dataRange.min or option.dataRange.max has not been defined.");this.myChart.canvasSupported||(t.realtime=!1);var i=this._isContinuity()?100:this._useCustomizedSplit()?t.splitList.length:t.splitNumber;this._buildSplitList(),this._buildColorList(i),this._buildGap(i),this._buildDataList(i)}this.clear(),this._buildShape()},getColor:function(e){if(isNaN(e))return null;var t;if(this._useCustomizedSplit()){for(var i=this._splitList,n=0,a=i.length;a>n;n++)if(i[n].min<=e&&i[n].max>=e){t=n;break}}else{if(this.dataRangeOption.min==this.dataRangeOption.max)return this._colorList[0];if(ethis.dataRangeOption.max&&(e=this.dataRangeOption.max),this.dataRangeOption.calculable&&(e-(this._gap*this._range.start+this.dataRangeOption.min)>5e-5||e-(this._gap*this._range.end+this.dataRangeOption.min)<-5e-5))return null;t=this._colorList.length-Math.ceil((e-this.dataRangeOption.min)/(this.dataRangeOption.max-this.dataRangeOption.min)*this._colorList.length),t==this._colorList.length&&t--}return this._selectedMap[t]?this._colorList[t]:null},getColorByIndex:function(e){return e>=this._colorList.length?e=this._colorList.length-1:0>e&&(e=0),this._colorList[e]},onbeforDispose:function(){this.messageCenter.unbind(r.EVENT.HOVER,this._onhoverlink)}},s.inherits(t,i),e("../component").define("dataRange",t),t}),i("echarts/util/shape/HandlePolygon",["require","zrender/shape/Base","zrender/shape/Polygon","zrender/tool/util"],function(e){function t(e){i.call(this,e)}var i=e("zrender/shape/Base"),n=e("zrender/shape/Polygon"),a=e("zrender/tool/util");return t.prototype={type:"handle-polygon",buildPath:function(e,t){n.prototype.buildPath(e,t)},isCover:function(e,t){var i=this.transformCoordToLocal(e,t);e=i[0],t=i[1];var n=this.style.rect;return e>=n.x&&e<=n.x+n.width&&t>=n.y&&t<=n.y+n.height?!0:!1}},a.inherits(t,i),t}),i("echarts/chart/k",["require","./base","../util/shape/Candle","../component/axis","../component/grid","../component/dataZoom","../config","../util/ecData","zrender/tool/util","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e("./base"),n=e("../util/shape/Candle");e("../component/axis"),e("../component/grid"),e("../component/dataZoom");var a=e("../config");a.k={zlevel:0,z:2,clickable:!0,hoverable:!0,legendHoverLink:!1,xAxisIndex:0,yAxisIndex:0,itemStyle:{normal:{color:"#fff",color0:"#00aa11",lineStyle:{width:1,color:"#ff3200",color0:"#00aa11"},label:{show:!1}},emphasis:{label:{show:!1}}}};var o=e("../util/ecData"),r=e("zrender/tool/util");return t.prototype={type:a.CHART_TYPE_K,_buildShape:function(){var e=this.series;this.selectedMap={};for(var t,i={top:[],bottom:[]},n=0,o=e.length;o>n;n++)e[n].type===a.CHART_TYPE_K&&(e[n]=this.reformOption(e[n]),this.legendHoverLink=e[n].legendHoverLink||this.legendHoverLink,t=this.component.xAxis.getAxis(e[n].xAxisIndex),t.type===a.COMPONENT_TYPE_AXIS_CATEGORY&&i[t.getPosition()].push(n));for(var r in i)i[r].length>0&&this._buildSinglePosition(r,i[r]);this.addShapeList()},_buildSinglePosition:function(e,t){var i=this._mapData(t),n=i.locationMap,a=i.maxDataLength;if(0!==a&&0!==n.length){this._buildHorizontal(t,a,n);for(var o=0,r=t.length;r>o;o++)this.buildMark(t[o])}},_mapData:function(e){for(var t,i,n=this.series,a=this.component.legend,o=[],r=0,s=0,l=e.length;l>s;s++)t=n[e[s]],i=t.name,this.selectedMap[i]=a?a.isSelected(i):!0,this.selectedMap[i]&&o.push(e[s]),r=Math.max(r,t.data.length);return{locationMap:o,maxDataLength:r}},_buildHorizontal:function(e,t,i){for(var n,a,o,r,s,l,h,m,V,U,d=this.series,p={},c=0,u=i.length;u>c;c++){n=i[c],a=d[n],o=a.xAxisIndex||0,r=this.component.xAxis.getAxis(o),h=a.barWidth||Math.floor(r.getGap()/2),U=a.barMaxWidth,U&&h>U&&(h=U),s=a.yAxisIndex||0,l=this.component.yAxis.getAxis(s),p[n]=[];for(var y=0,g=t;g>y&&null!=r.getNameByIndex(y);y++)m=a.data[y],V=this.getDataFromOption(m,"-"),"-"!==V&&4==V.length&&p[n].push([r.getCoordByIndex(y),h,l.getCoord(V[0]),l.getCoord(V[1]),l.getCoord(V[2]),l.getCoord(V[3]),y,r.getNameByIndex(y)])}this._buildKLine(e,p)},_buildKLine:function(e,t){for(var i,n,o,r,s,l,h,m,V,U,d,p,c,u,y,g,b,f=this.series,k=0,x=e.length;x>k;k++)if(b=e[k],d=f[b],u=t[b],this._isLarge(u)&&(u=this._getLargePointList(u)),d.type===a.CHART_TYPE_K&&null!=u){p=d,i=this.query(p,"itemStyle.normal.lineStyle.width"),n=this.query(p,"itemStyle.normal.lineStyle.color"),o=this.query(p,"itemStyle.normal.lineStyle.color0"),r=this.query(p,"itemStyle.normal.color"),s=this.query(p,"itemStyle.normal.color0"),l=this.query(p,"itemStyle.emphasis.lineStyle.width"),h=this.query(p,"itemStyle.emphasis.lineStyle.color"),m=this.query(p,"itemStyle.emphasis.lineStyle.color0"),V=this.query(p,"itemStyle.emphasis.color"),U=this.query(p,"itemStyle.emphasis.color0");for(var _=0,L=u.length;L>_;_++)y=u[_],c=d.data[y[6]],p=c,g=y[3]a;a++)n[a]=e[Math.floor(i/t*a)];return n},_getCandle:function(e,t,i,a,r,s,l,h,m,V,U,d,p,c,u){var y=this.series,g=y[e],b=g.data[t],f=[b,g],k={zlevel:g.zlevel,z:g.z,clickable:this.deepQuery(f,"clickable"),hoverable:this.deepQuery(f,"hoverable"),style:{x:a,y:[s,l,h,m],width:r,color:V,strokeColor:d,lineWidth:U,brushType:"both"},highlightStyle:{color:p,strokeColor:u,lineWidth:c},_seriesIndex:e};return k=this.addLabel(k,g,b,i),o.pack(k,g,e,b,t,i),k=new n(k)},getMarkCoord:function(e,t){var i=this.series[e],n=this.component.xAxis.getAxis(i.xAxisIndex),a=this.component.yAxis.getAxis(i.yAxisIndex);return["string"!=typeof t.xAxis&&n.getCoordByIndex?n.getCoordByIndex(t.xAxis||0):n.getCoord(t.xAxis||0),"string"!=typeof t.yAxis&&a.getCoordByIndex?a.getCoordByIndex(t.yAxis||0):a.getCoord(t.yAxis||0)]},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()},addDataAnimation:function(e,t){function i(){p--,0===p&&t&&t()}for(var n=this.series,a={},r=0,s=e.length;s>r;r++)a[e[r][0]]=e[r];for(var l,h,m,V,U,d,p=0,r=0,s=this.shapeList.length;s>r;r++)if(U=this.shapeList[r]._seriesIndex,a[U]&&!a[U][3]&&"candle"===this.shapeList[r].type){if(d=o.get(this.shapeList[r],"dataIndex"),V=n[U],a[U][2]&&d===V.data.length-1){this.zr.delShape(this.shapeList[r].id);continue}if(!a[U][2]&&0===d){this.zr.delShape(this.shapeList[r].id);continue}h=this.component.xAxis.getAxis(V.xAxisIndex||0).getGap(),l=a[U][2]?h:-h,m=0,p++,this.zr.animate(this.shapeList[r].id,"").when(this.query(this.option,"animationDurationUpdate"),{position:[l,m]}).done(i).start()}p||t&&t()}},r.inherits(t,i),e("../chart").define("k",t),t}),i("echarts/chart/pie",["require","./base","zrender/shape/Text","zrender/shape/Ring","zrender/shape/Circle","zrender/shape/Sector","zrender/shape/Polyline","../config","../util/ecData","zrender/tool/util","zrender/tool/math","zrender/tool/color","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o);var r=this;r.shapeHandler.onmouseover=function(e){var t=e.target,i=h.get(t,"seriesIndex"),n=h.get(t,"dataIndex"),a=h.get(t,"special"),o=[t.style.x,t.style.y],s=t.style.startAngle,l=t.style.endAngle,m=((l+s)/2+360)%360,V=t.highlightStyle.color,U=r.getLabel(i,n,a,o,m,V,!0);U&&r.zr.addHoverShape(U);var d=r.getLabelLine(i,n,o,t.style.r0,t.style.r,m,V,!0);d&&r.zr.addHoverShape(d)},this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Ring"),o=e("zrender/shape/Circle"),r=e("zrender/shape/Sector"),s=e("zrender/shape/Polyline"),l=e("../config");l.pie={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,center:["50%","50%"],radius:[0,"75%"],clockWise:!0,startAngle:90,minAngle:0,selectedOffset:10,itemStyle:{normal:{borderColor:"rgba(0,0,0,0)",borderWidth:1,label:{show:!0,position:"outer"},labelLine:{show:!0,length:20,lineStyle:{width:1,type:"solid"}}},emphasis:{borderColor:"rgba(0,0,0,0)",borderWidth:1,label:{show:!1},labelLine:{show:!1,length:20,lineStyle:{width:1,type:"solid"}}}}};var h=e("../util/ecData"),m=e("zrender/tool/util"),V=e("zrender/tool/math"),U=e("zrender/tool/color");return t.prototype={type:l.CHART_TYPE_PIE,_buildShape:function(){var e=this.series,t=this.component.legend;this.selectedMap={},this._selected={};var i,n,r;this._selectedMode=!1;for(var s,m=0,V=e.length;V>m;m++)if(e[m].type===l.CHART_TYPE_PIE){if(e[m]=this.reformOption(e[m]),this.legendHoverLink=e[m].legendHoverLink||this.legendHoverLink,s=e[m].name||"",this.selectedMap[s]=t?t.isSelected(s):!0,!this.selectedMap[s])continue;i=this.parseCenter(this.zr,e[m].center),n=this.parseRadius(this.zr,e[m].radius),this._selectedMode=this._selectedMode||e[m].selectedMode,this._selected[m]=[],this.deepQuery([e[m],this.option],"calculable")&&(r={zlevel:e[m].zlevel,z:e[m].z,hoverable:!1,style:{x:i[0],y:i[1],r0:n[0]<=10?0:n[0]-10,r:n[1]+10,brushType:"stroke",lineWidth:1,strokeColor:e[m].calculableHolderColor||this.ecTheme.calculableHolderColor||l.calculableHolderColor}},h.pack(r,e[m],m,void 0,-1),this.setCalculable(r),r=n[0]<=10?new o(r):new a(r),this.shapeList.push(r)),this._buildSinglePie(m),this.buildMark(m)}this.addShapeList()},_buildSinglePie:function(e){for(var t,i=this.series,n=i[e],a=n.data,o=this.component.legend,r=0,s=0,l=0,h=Number.NEGATIVE_INFINITY,m=[],V=0,U=a.length;U>V;V++)t=a[V].name, -this.selectedMap[t]=o?o.isSelected(t):!0,this.selectedMap[t]&&!isNaN(a[V].value)&&(0!==+a[V].value?r++:s++,l+=+a[V].value,h=Math.max(h,+a[V].value));if(0!==l){for(var d,p,c,u,y,g,b=100,f=n.clockWise,k=(n.startAngle.toFixed(2)-0+360)%360,x=n.minAngle||.01,_=360-x*r-.01*s,L=n.roseType,V=0,U=a.length;U>V;V++)if(t=a[V].name,this.selectedMap[t]&&!isNaN(a[V].value)){if(p=o?o.getColor(t):this.zr.getColor(V),b=a[V].value/l,d="area"!=L?f?k-b*_-(0!==b?x:.01):b*_+k+(0!==b?x:.01):f?k-360/U:360/U+k,d=d.toFixed(2)-0,b=(100*b).toFixed(2),c=this.parseCenter(this.zr,n.center),u=this.parseRadius(this.zr,n.radius),y=+u[0],g=+u[1],"radius"===L?g=a[V].value/h*(g-y)*.8+.2*(g-y)+y:"area"===L&&(g=Math.sqrt(a[V].value/h)*(g-y)+y),f){var W;W=k,k=d,d=W}this._buildItem(m,e,V,b,a[V].selected,c,y,g,k,d,p),f||(k=d)}this._autoLabelLayout(m,c,g);for(var V=0,U=m.length;U>V;V++)this.shapeList.push(m[V]);m=null}},_buildItem:function(e,t,i,n,a,o,r,s,l,m,V){var U=this.series,d=((m+l)/2+360)%360,p=this.getSector(t,i,n,a,o,r,s,l,m,V);h.pack(p,U[t],t,U[t].data[i],i,U[t].data[i].name,n),e.push(p);var c=this.getLabel(t,i,n,o,d,V,!1),u=this.getLabelLine(t,i,o,r,s,d,V,!1);u&&(h.pack(u,U[t],t,U[t].data[i],i,U[t].data[i].name,n),e.push(u)),c&&(h.pack(c,U[t],t,U[t].data[i],i,U[t].data[i].name,n),c._labelLine=u,e.push(c))},getSector:function(e,t,i,n,a,o,s,l,h,m){var d=this.series,p=d[e],c=p.data[t],u=[c,p],y=this.deepMerge(u,"itemStyle.normal")||{},g=this.deepMerge(u,"itemStyle.emphasis")||{},b=this.getItemStyleColor(y.color,e,t,c)||m,f=this.getItemStyleColor(g.color,e,t,c)||("string"==typeof b?U.lift(b,-.2):b),k={zlevel:p.zlevel,z:p.z,clickable:this.deepQuery(u,"clickable"),style:{x:a[0],y:a[1],r0:o,r:s,startAngle:l,endAngle:h,brushType:"both",color:b,lineWidth:y.borderWidth,strokeColor:y.borderColor,lineJoin:"round"},highlightStyle:{color:f,lineWidth:g.borderWidth,strokeColor:g.borderColor,lineJoin:"round"},_seriesIndex:e,_dataIndex:t};if(n){var x=((k.style.startAngle+k.style.endAngle)/2).toFixed(2)-0;k.style._hasSelected=!0,k.style._x=k.style.x,k.style._y=k.style.y;var _=this.query(p,"selectedOffset");k.style.x+=V.cos(x,!0)*_,k.style.y-=V.sin(x,!0)*_,this._selected[e][t]=!0}else this._selected[e][t]=!1;return this._selectedMode&&(k.onclick=this.shapeHandler.onclick),this.deepQuery([c,p,this.option],"calculable")&&(this.setCalculable(k),k.draggable=!0),(this._needLabel(p,c,!0)||this._needLabelLine(p,c,!0))&&(k.onmouseover=this.shapeHandler.onmouseover),k=new r(k)},getLabel:function(e,t,i,a,o,r,s){var l=this.series,h=l[e],U=h.data[t];if(this._needLabel(h,U,s)){var d,p,c,u=s?"emphasis":"normal",y=m.merge(m.clone(U.itemStyle)||{},h.itemStyle),g=y[u].label,b=g.textStyle||{},f=a[0],k=a[1],x=this.parseRadius(this.zr,h.radius),_="middle";g.position=g.position||y.normal.label.position,"center"===g.position?(d=f,p=k,c="center"):"inner"===g.position||"inside"===g.position?(x=(x[0]+x[1])*(g.distance||.5),d=Math.round(f+x*V.cos(o,!0)),p=Math.round(k-x*V.sin(o,!0)),r="#fff",c="center"):(x=x[1]- -y[u].labelLine.length,d=Math.round(f+x*V.cos(o,!0)),p=Math.round(k-x*V.sin(o,!0)),c=o>=90&&270>=o?"right":"left"),"center"!=g.position&&"inner"!=g.position&&"inside"!=g.position&&(d+="left"===c?20:-20),U.__labelX=d-("left"===c?5:-5),U.__labelY=p;var L=new n({zlevel:h.zlevel,z:h.z+1,hoverable:!1,style:{x:d,y:p,color:b.color||r,text:this.getLabelText(e,t,i,u),textAlign:b.align||c,textBaseline:b.baseline||_,textFont:this.getFont(b)},highlightStyle:{brushType:"fill"}});return L._radius=x,L._labelPosition=g.position||"outer",L._rect=L.getRect(L.style),L._seriesIndex=e,L._dataIndex=t,L}},getLabelText:function(e,t,i,n){var a=this.series,o=a[e],r=o.data[t],s=this.deepQuery([r,o],"itemStyle."+n+".label.formatter");return s?"function"==typeof s?s.call(this.myChart,{seriesIndex:e,seriesName:o.name||"",series:o,dataIndex:t,data:r,name:r.name,value:r.value,percent:i}):"string"==typeof s?(s=s.replace("{a}","{a0}").replace("{b}","{b0}").replace("{c}","{c0}").replace("{d}","{d0}"),s=s.replace("{a0}",o.name).replace("{b0}",r.name).replace("{c0}",r.value).replace("{d0}",i)):void 0:r.name},getLabelLine:function(e,t,i,n,a,o,r,l){var h=this.series,U=h[e],d=U.data[t];if(this._needLabelLine(U,d,l)){var p=l?"emphasis":"normal",c=m.merge(m.clone(d.itemStyle)||{},U.itemStyle),u=c[p].labelLine,y=u.lineStyle||{},g=i[0],b=i[1],f=a,k=this.parseRadius(this.zr,U.radius)[1]- -u.length,x=V.cos(o,!0),_=V.sin(o,!0);return new s({zlevel:U.zlevel,z:U.z+1,hoverable:!1,style:{pointList:[[g+f*x,b-f*_],[g+k*x,b-k*_],[d.__labelX,d.__labelY]],strokeColor:y.color||r,lineType:y.type,lineWidth:y.width},_seriesIndex:e,_dataIndex:t})}},_needLabel:function(e,t,i){return this.deepQuery([t,e],"itemStyle."+(i?"emphasis":"normal")+".label.show")},_needLabelLine:function(e,t,i){return this.deepQuery([t,e],"itemStyle."+(i?"emphasis":"normal")+".labelLine.show")},_autoLabelLayout:function(e,t,i){for(var n=[],a=[],o=0,r=e.length;r>o;o++)("outer"===e[o]._labelPosition||"outside"===e[o]._labelPosition)&&(e[o]._rect._y=e[o]._rect.y,e[o]._rect.xa;a++)if(e[a]._rect.y+=n,e[a].style.y+=n,e[a]._labelLine&&(e[a]._labelLine.style.pointList[1][1]+=n,e[a]._labelLine.style.pointList[2][1]+=n),a>t&&i>a+1&&e[a+1]._rect.y>e[a]._rect.y+e[a]._rect.height)return void o(a,n/2);o(i-1,n/2)}function o(t,i){for(var n=t;n>=0&&(e[n]._rect.y-=i,e[n].style.y-=i,e[n]._labelLine&&(e[n]._labelLine.style.pointList[1][1]-=i,e[n]._labelLine.style.pointList[2][1]-=i),!(n>0&&e[n]._rect.y>e[n-1]._rect.y+e[n-1]._rect.height));n--);}function r(e,t,i,n,a){for(var o,r,s,l=i[0],h=i[1],m=a>0?t?Number.MAX_VALUE:0:t?Number.MAX_VALUE:0,V=0,U=e.length;U>V;V++)r=Math.abs(e[V]._rect.y-h),s=e[V]._radius-n,o=n+s>r?Math.sqrt((n+s+20)*(n+s+20)-Math.pow(e[V]._rect.y-h,2)):Math.abs(e[V]._rect.x+(a>0?0:e[V]._rect.width)-l),t&&o>=m&&(o=m-10),!t&&m>=o&&(o=m+10),e[V]._rect.x=e[V].style.x=l+o*a,e[V]._labelLine&&(e[V]._labelLine.style.pointList[2][0]=l+(o-5)*a,e[V]._labelLine.style.pointList[1][0]=l+(o-20)*a),m=o}e.sort(function(e,t){return e._rect.y-t._rect.y});for(var s,l=0,h=e.length,m=[],V=[],U=0;h>U;U++)s=e[U]._rect.y-l,0>s&&a(U,h,-s,n),l=e[U]._rect.y+e[U]._rect.height;this.zr.getHeight()-l<0&&o(h-1,l-this.zr.getHeight());for(var U=0;h>U;U++)e[U]._rect.y>=t[1]?V.push(e[U]):m.push(e[U]);r(V,!0,t,i,n),r(m,!1,t,i,n)},reformOption:function(e){var t=m.merge;return e=t(t(e||{},m.clone(this.ecTheme.pie||{})),m.clone(l.pie)),e.itemStyle.normal.label.textStyle=this.getTextStyle(e.itemStyle.normal.label.textStyle),e.itemStyle.emphasis.label.textStyle=this.getTextStyle(e.itemStyle.emphasis.label.textStyle),this.z=e.z,this.zlevel=e.zlevel,e},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()},addDataAnimation:function(e,t){function i(){s--,0===s&&t&&t()}for(var n=this.series,a={},o=0,r=e.length;r>o;o++)a[e[o][0]]=e[o];var s=0,h={},m={},V={},U=this.shapeList;this.shapeList=[];for(var d,p,c,u={},o=0,r=e.length;r>o;o++)d=e[o][0],p=e[o][2],c=e[o][3],n[d]&&n[d].type===l.CHART_TYPE_PIE&&(p?(c||(h[d+"_"+n[d].data.length]="delete"),u[d]=1):c?u[d]=0:(h[d+"_-1"]="delete",u[d]=-1),this._buildSinglePie(d));for(var y,g,o=0,r=this.shapeList.length;r>o;o++)switch(d=this.shapeList[o]._seriesIndex,y=this.shapeList[o]._dataIndex,g=d+"_"+y,this.shapeList[o].type){case"sector":h[g]=this.shapeList[o];break;case"text":m[g]=this.shapeList[o];break;case"polyline":V[g]=this.shapeList[o]}this.shapeList=[];for(var b,o=0,r=U.length;r>o;o++)if(d=U[o]._seriesIndex,a[d]){if(y=U[o]._dataIndex+u[d],g=d+"_"+y,b=h[g],!b)continue;if("sector"===U[o].type)"delete"!=b?(s++,this.zr.animate(U[o].id,"style").when(400,{startAngle:b.style.startAngle,endAngle:b.style.endAngle}).done(i).start()):(s++,this.zr.animate(U[o].id,"style").when(400,u[d]<0?{startAngle:U[o].style.startAngle}:{endAngle:U[o].style.endAngle}).done(i).start());else if("text"===U[o].type||"polyline"===U[o].type)if("delete"===b)this.zr.delShape(U[o].id);else switch(U[o].type){case"text":s++,b=m[g],this.zr.animate(U[o].id,"style").when(400,{x:b.style.x,y:b.style.y}).done(i).start();break;case"polyline":s++,b=V[g],this.zr.animate(U[o].id,"style").when(400,{pointList:b.style.pointList}).done(i).start()}}this.shapeList=U,s||t&&t()},onclick:function(e){var t=this.series;if(this.isClick&&e.target){this.isClick=!1;for(var i,n=e.target,a=n.style,o=h.get(n,"seriesIndex"),r=h.get(n,"dataIndex"),s=0,m=this.shapeList.length;m>s;s++)if(this.shapeList[s].id===n.id){if(o=h.get(n,"seriesIndex"),r=h.get(n,"dataIndex"),a._hasSelected)n.style.x=n.style._x,n.style.y=n.style._y,n.style._hasSelected=!1,this._selected[o][r]=!1;else{var U=((a.startAngle+a.endAngle)/2).toFixed(2)-0;n.style._hasSelected=!0,this._selected[o][r]=!0,n.style._x=n.style.x,n.style._y=n.style.y,i=this.query(t[o],"selectedOffset"),n.style.x+=V.cos(U,!0)*i,n.style.y-=V.sin(U,!0)*i}this.zr.modShape(n.id)}else this.shapeList[s].style._hasSelected&&"single"===this._selectedMode&&(o=h.get(this.shapeList[s],"seriesIndex"),r=h.get(this.shapeList[s],"dataIndex"),this.shapeList[s].style.x=this.shapeList[s].style._x,this.shapeList[s].style.y=this.shapeList[s].style._y,this.shapeList[s].style._hasSelected=!1,this._selected[o][r]=!1,this.zr.modShape(this.shapeList[s].id));this.messageCenter.dispatch(l.EVENT.PIE_SELECTED,e.event,{selected:this._selected,target:h.get(n,"name")},this.myChart),this.zr.refreshNextFrame()}}},m.inherits(t,i),e("../chart").define("pie",t),t}),i("echarts/chart/radar",["require","./base","zrender/shape/Polygon","../component/polar","../config","../util/ecData","zrender/tool/util","zrender/tool/color","../util/accMath","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Polygon");e("../component/polar");var a=e("../config");a.radar={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,polarIndex:0,itemStyle:{normal:{label:{show:!1},lineStyle:{width:2,type:"solid"}},emphasis:{label:{show:!1}}},symbolSize:2};var o=e("../util/ecData"),r=e("zrender/tool/util"),s=e("zrender/tool/color");return t.prototype={type:a.CHART_TYPE_RADAR,_buildShape:function(){this.selectedMap={},this._symbol=this.option.symbolList,this._queryTarget,this._dropBoxList=[],this._radarDataCounter=0;for(var e,t=this.series,i=this.component.legend,n=0,o=t.length;o>n;n++)t[n].type===a.CHART_TYPE_RADAR&&(this.serie=this.reformOption(t[n]),this.legendHoverLink=t[n].legendHoverLink||this.legendHoverLink,e=this.serie.name||"",this.selectedMap[e]=i?i.isSelected(e):!0,this.selectedMap[e]&&(this._queryTarget=[this.serie,this.option],this.deepQuery(this._queryTarget,"calculable")&&this._addDropBox(n),this._buildSingleRadar(n),this.buildMark(n)));this.addShapeList()},_buildSingleRadar:function(e){for(var t,i,n,a,o=this.component.legend,r=this.serie.data,s=this.deepQuery(this._queryTarget,"calculable"),l=0;lr;r++)n=this.getDataFromOption(t.value[r]),i="-"!=n?o.getVector(e,r,n):!1,i&&a.push(i);return a},_addSymbol:function(e,t,i,n,a){for(var r,s=this.series,l=this.component.polar,h=0,m=e.length;m>h;h++)r=this.getSymbolShape(this.deepMerge([s[n].data[i],s[n]]),n,s[n].data[i].value[h],h,l.getIndicatorText(a,h),e[h][0],e[h][1],this._symbol[this._radarDataCounter%this._symbol.length],t,"#fff","vertical"),r.zlevel=this.getZlevelBase(),r.z=this.getZBase()+1,o.set(r,"data",s[n].data[i]),o.set(r,"value",s[n].data[i].value),o.set(r,"dataIndex",i),o.set(r,"special",h),this.shapeList.push(r)},_addDataShape:function(e,t,i,a,r,l){var h=this.series,m=[i,this.serie],V=this.getItemStyleColor(this.deepQuery(m,"itemStyle.normal.color"),a,r,i),U=this.deepQuery(m,"itemStyle.normal.lineStyle.width"),d=this.deepQuery(m,"itemStyle.normal.lineStyle.type"),p=this.deepQuery(m,"itemStyle.normal.areaStyle.color"),c=this.deepQuery(m,"itemStyle.normal.areaStyle"),u={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{pointList:e,brushType:c?"both":"stroke",color:p||V||("string"==typeof t?s.alpha(t,.5):t),strokeColor:V||t,lineWidth:U,lineType:d},highlightStyle:{brushType:this.deepQuery(m,"itemStyle.emphasis.areaStyle")||c?"both":"stroke",color:this.deepQuery(m,"itemStyle.emphasis.areaStyle.color")||p||V||("string"==typeof t?s.alpha(t,.5):t),strokeColor:this.getItemStyleColor(this.deepQuery(m,"itemStyle.emphasis.color"),a,r,i)||V||t,lineWidth:this.deepQuery(m,"itemStyle.emphasis.lineStyle.width")||U,lineType:this.deepQuery(m,"itemStyle.emphasis.lineStyle.type")||d}};o.pack(u,h[a],a,i,r,i.name,this.component.polar.getIndicator(h[a].polarIndex)),l&&(u.draggable=!0,this.setCalculable(u)),u=new n(u),this.shapeList.push(u)},_addDropBox:function(e){var t=this.series,i=this.deepQuery(this._queryTarget,"polarIndex");if(!this._dropBoxList[i]){var n=this.component.polar.getDropBox(i);n.zlevel=this.getZlevelBase(),n.z=this.getZBase(),this.setCalculable(n),o.pack(n,t,e,void 0,-1),this.shapeList.push(n),this._dropBoxList[i]=!0}},ondragend:function(e,t){var i=this.series;if(this.isDragend&&e.target){var n=e.target,a=o.get(n,"seriesIndex"),r=o.get(n,"dataIndex");this.component.legend&&this.component.legend.del(i[a].data[r].name),i[a].data.splice(r,1),t.dragOut=!0,t.needRefresh=!0,this.isDragend=!1}},ondrop:function(t,i){var n=this.series;if(this.isDrop&&t.target){var a,r,s=t.target,l=t.dragged,h=o.get(s,"seriesIndex"),m=o.get(s,"dataIndex"),V=this.component.legend;if(-1===m)a={value:o.get(l,"value"),name:o.get(l,"name")},n[h].data.push(a),V&&V.add(a.name,l.style.color||l.style.strokeColor);else{var U=e("../util/accMath");a=n[h].data[m],V&&V.del(a.name),a.name+=this.option.nameConnector+o.get(l,"name"),r=o.get(l,"value");for(var d=0;dh;h++)t=m.polar2cartesian(s,o*Math.PI/180+r*h),l.push({vector:[t[1],-t[0]]})},_getRadius:function(){var e=this.polar[this._index];return this.parsePercent(e.radius,Math.min(this.zr.getWidth(),this.zr.getHeight())/2)},_buildSpiderWeb:function(e){var t=this.polar[e],i=t.__ecIndicator,n=t.splitArea,a=t.splitLine,o=this.getCenter(e),r=t.splitNumber,s=a.lineStyle.color,l=a.lineStyle.width,h=a.show,m=this.deepQuery(this._queryTarget,"axisLine");this._addArea(i,r,o,n,s,l,h),m.show&&this._addLine(i,o,m)},_addAxisLabel:function(t){for(var i,a,o,r,a,s,l,m,V,U,d=e("../util/accMath"),p=this.polar[t],c=this.deepQuery(this._queryTarget,"indicator"),u=p.__ecIndicator,y=this.deepQuery(this._queryTarget,"splitNumber"),g=this.getCenter(t),b=0;b=x;x+=U+1)r=h.merge({},o),l=d.accAdd(s.min,d.accMul(s.step,x)),l="function"==typeof k?k(l):"string"==typeof k?k.replace("{a}","{a0}").replace("{a0}",l):this.numAddCommas(l),r.text=l,r.x=x*a[0]/y+Math.cos(m)*V+g[0],r.y=x*a[1]/y+Math.sin(m)*V+g[1],this.shapeList.push(new n({zlevel:this.getZlevelBase(),z:this.getZBase(),style:r,draggable:!1,hoverable:!1}))}},_buildText:function(e){for(var t,i,a,o,r,s,l,h=this.polar[e],m=h.__ecIndicator,V=this.deepQuery(this._queryTarget,"indicator"),U=this.getCenter(e),d=0,p=0,c=0;c0?"left":Math.round(t[0])<0?"right":"center",null==o.margin?t=this._mapVector(t,U,1.1):(s=o.margin,d=t[0]>0?s:-s,p=t[1]>0?s:-s,d=0===t[0]?0:d,p=0===t[1]?0:p,t=this._mapVector(t,U,1)),i.textAlign=a,i.x=t[0]+d,i.y=t[1]+p,r=o.rotate?[o.rotate/180*Math.PI,t[0],t[1]]:[0,0,0],this.shapeList.push(new n({zlevel:this.getZlevelBase(),z:this.getZBase(),style:i,draggable:!1,hoverable:!1,rotation:r})))},getIndicatorText:function(e,t){return this.polar[e]&&this.polar[e].__ecIndicator[t]&&this.polar[e].__ecIndicator[t].text},getDropBox:function(e){var t,i,e=e||0,n=this.polar[e],a=this.getCenter(e),o=n.__ecIndicator,r=o.length,s=[],l=n.type;if("polygon"==l){for(var h=0;r>h;h++)t=o[h].vector,s.push(this._mapVector(t,a,1.2));i=this._getShape(s,"fill","rgba(0,0,0,0)","",1)}else"circle"==l&&(i=this._getCircle("",1,1.2,a,"fill","rgba(0,0,0,0)"));return i},_addArea:function(e,t,i,n,a,o,r){for(var s,l,h,m,V=this.deepQuery(this._queryTarget,"type"),U=0;t>U;U++)l=(t-U)/t,r&&("polygon"==V?(m=this._getPointList(e,l,i),s=this._getShape(m,"stroke","",a,o)):"circle"==V&&(s=this._getCircle(a,o,l,i,"stroke")),this.shapeList.push(s)),n.show&&(h=(t-U-1)/t,this._addSplitArea(e,n,l,h,i,U))},_getCircle:function(e,t,i,n,a,o){var s=this._getRadius();return new r({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:n[0],y:n[1],r:s*i,brushType:a,strokeColor:e,lineWidth:t,color:o},hoverable:!1,draggable:!1})},_getRing:function(e,t,i,n){var a=this._getRadius();return new s({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:n[0],y:n[1],r:t*a,r0:i*a,color:e,brushType:"fill"},hoverable:!1,draggable:!1})},_getPointList:function(e,t,i){for(var n,a=[],o=e.length,r=0;o>r;r++)n=e[r].vector,a.push(this._mapVector(n,i,t));return a},_getShape:function(e,t,i,n,a){return new o({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{pointList:e,brushType:t,color:i,strokeColor:n,lineWidth:a},hoverable:!1,draggable:!1})},_addSplitArea:function(e,t,i,n,a,o){var r,s,l,h,m,V=e.length,U=t.areaStyle.color,d=[],V=e.length,p=this.deepQuery(this._queryTarget,"type");if("string"==typeof U&&(U=[U]),s=U.length,r=U[o%s],"polygon"==p)for(var c=0;V>c;c++)d=[],l=e[c].vector,h=e[(c+1)%V].vector,d.push(this._mapVector(l,a,i)),d.push(this._mapVector(l,a,n)),d.push(this._mapVector(h,a,n)),d.push(this._mapVector(h,a,i)),m=this._getShape(d,"fill",r,"",1),this.shapeList.push(m);else"circle"==p&&(m=this._getRing(r,i,n,a),this.shapeList.push(m))},_mapVector:function(e,t,i){return[e[0]*i+t[0],e[1]*i+t[1]]},getCenter:function(e){var e=e||0;return this.parseCenter(this.zr,this.polar[e].center)},_addLine:function(e,t,i){for(var n,a,o=e.length,r=i.lineStyle,s=r.color,l=r.width,h=r.type,m=0;o>m;m++)a=e[m].vector,n=this._getLine(t[0],t[1],a[0]+t[0],a[1]+t[1],s,l,h),this.shapeList.push(n)},_getLine:function(e,t,i,n,o,r,s){return new a({zlevel:this.getZlevelBase(),z:this.getZBase(),style:{xStart:e,yStart:t,xEnd:i,yEnd:n,strokeColor:o,lineWidth:r,lineType:s},hoverable:!1})},_adjustIndicatorValue:function(t){for(var i,n,a,o=this.polar[t],r=this.deepQuery(this._queryTarget,"indicator"),s=r.length,l=o.__ecIndicator,h=this._getSeriesData(t),m=o.boundaryGap,V=o.splitNumber,U=o.scale,d=e("../util/smartSteps"),p=0;s>p;p++){if("number"==typeof r[p].max)i=r[p].max,n=r[p].min||0,a={max:i,min:n};else{var c=this._findValue(h,p,V,m);n=c.min,i=c.max}!U&&n>=0&&i>=0&&(n=0),!U&&0>=n&&0>=i&&(i=0);var u=d(n,i,V,a);l[p].value={min:u.min,max:u.max,step:u.step}}},_getSeriesData:function(e){for(var t,i,n,a=[],o=this.component.legend,r=0;ro||void 0===o)&&(o=e),(r>e||void 0===r)&&(r=e)}var o,r,s;if(e&&0!==e.length){if(1==e.length&&(r=0),1!=e.length)for(var l=0;l0?r=o/i:o/=i),{max:o,min:r}}},getVector:function(e,t,i){e=e||0,t=t||0;var n=this.polar[e].__ecIndicator;if(!(t>=n.length)){var a,o=this.polar[e].__ecIndicator[t],r=this.getCenter(e),s=o.vector,l=o.value.max,h=o.value.min;if("undefined"==typeof i)return r;switch(i){case"min":i=h;break;case"max":i=l;break;case"center":i=(l+h)/2}return a=l!=h?(i-h)/(l-h):.5,this._mapVector(s,r,a)}},isInside:function(e){var t=this.getNearestIndex(e);return t?t.polarIndex:-1},getNearestIndex:function(e){for(var t,i,n,a,o,r,s,l,h,V=0;Va[0])return{polarIndex:V,valueIndex:Math.floor((h+l/2)/l)%s}}},getIndicator:function(e){var e=e||0;return this.polar[e].indicator},refresh:function(e){e&&(this.option=e,this.polar=this.option.polar,this.series=this.option.series),this.clear(),this._buildShape()}},h.inherits(t,i),e("../component").define("polar",t),t}),i("echarts/util/coordinates",["require","zrender/tool/math"],function(e){function t(e,t){return[e*n.sin(t),e*n.cos(t)]}function i(e,t){return[Math.sqrt(e*e+t*t),Math.atan(t/e)]}var n=e("zrender/tool/math");return{polar2cartesian:t,cartesian2polar:i}}),i("echarts/chart/chord",["require","./base","zrender/shape/Text","zrender/shape/Line","zrender/shape/Sector","../util/shape/Ribbon","../util/shape/Icon","zrender/shape/BezierCurve","../config","../util/ecData","zrender/tool/util","zrender/tool/vector","../data/Graph","../layout/Chord","../chart"],function(e){"use strict";function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.scaleLineLength=4,this.scaleUnitAngle=4,this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Line"),o=e("zrender/shape/Sector"),r=e("../util/shape/Ribbon"),s=e("../util/shape/Icon"),l=e("zrender/shape/BezierCurve"),h=e("../config");h.chord={zlevel:0,z:2,clickable:!0,radius:["65%","75%"],center:["50%","50%"],padding:2,sort:"none",sortSub:"none",startAngle:90,clockWise:!0,ribbonType:!0,minRadius:10,maxRadius:20,symbol:"circle",showScale:!1,showScaleText:!1,itemStyle:{normal:{borderWidth:0,borderColor:"#000",label:{show:!0,rotate:!1,distance:5},chordStyle:{width:1,color:"black",borderWidth:1,borderColor:"#999",opacity:.5}},emphasis:{borderWidth:0,borderColor:"#000",chordStyle:{width:1,color:"black",borderWidth:1,borderColor:"#999"}}}};var m=e("../util/ecData"),V=e("zrender/tool/util"),U=e("zrender/tool/vector"),d=e("../data/Graph"),p=e("../layout/Chord");return t.prototype={type:h.CHART_TYPE_CHORD,_init:function(){var e=this.series;this.selectedMap={};for(var t={},i={},n=0,a=e.length;a>n;n++)if(e[n].type===this.type){var o=this.isSelected(e[n].name);this.selectedMap[e[n].name]=o,o&&this.buildMark(n),this.reformOption(e[n]),t[e[n].name]=e[n]}for(var n=0,a=e.length;a>n;n++)if(e[n].type===this.type)if(e[n].insertToSerie){var r=t[e[n].insertToSerie];e[n]._referenceSerie=r}else i[e[n].name]=[e[n]];for(var n=0,a=e.length;a>n;n++)if(e[n].type===this.type&&e[n].insertToSerie){for(var s=e[n]._referenceSerie;s&&s._referenceSerie;)s=s._referenceSerie;i[s.name]&&this.selectedMap[e[n].name]&&i[s.name].push(e[n])}for(var l in i)this._buildChords(i[l]);this.addShapeList()},_getNodeCategory:function(e,t){return e.categories&&e.categories[t.category||0]},_getNodeQueryTarget:function(e,t){var i=this._getNodeCategory(e,t);return[t,i,e]},_getEdgeQueryTarget:function(e,t,i){return i=i||"normal",[t.itemStyle&&t.itemStyle[i],e.itemStyle[i].chordStyle]},_buildChords:function(e){for(var t=[],i=e[0],n=function(e){return e.layout.size>0},a=function(e){return function(t){return e.getEdge(t.node2,t.node1)}},o=0;oa;a++){var r=n[a];if(r&&!r.ignore){var s=this._getNodeCategory(t,r),l=s?s.name:r.name;if(this.selectedMap[l]=this.isSelected(l),this.selectedMap[l]){var h=i.addNode(r.name,r);h.rawIndex=a}}}for(var a=0,o=e.links.length;o>a;a++){var m=e.links[a],V=m.source,U=m.target;"number"==typeof V&&(V=n[V],V&&(V=V.name)),"number"==typeof U&&(U=n[U],U&&(U=U.name));var p=i.addEdge(V,U,m);p&&(p.rawIndex=a)}return i.eachNode(function(e){var i=e.data.value;if(null==i)if(i=0,t.ribbonType)for(var n=0;n0&&(p.style.brushType="both"),p.highlightStyle.lineWidth>0&&(p.highlightStyle.brushType="both"),m.pack(p,e,t,i.data,i.rawIndex,i.id,i.category),this.shapeList.push(p),i.shape=p},this)},_buildNodeIcons:function(e,t,i,n){var a=this.parseCenter(this.zr,n.center),o=this.parseRadius(this.zr,n.radius),r=o[1];i.eachNode(function(i){var o=i.layout.startAngle,l=i.layout.endAngle,h=(o+l)/2,V=r*Math.cos(h),U=r*Math.sin(h),d=this._getNodeQueryTarget(n,i.data),p=this._getNodeCategory(n,i.data),c=this.deepQuery(d,"itemStyle.normal.color");c||(c=this.getColor(p?p.name:i.id));var u=new s({zlevel:e.zlevel,z:e.z+1,style:{x:-i.layout.size,y:-i.layout.size,width:2*i.layout.size,height:2*i.layout.size,iconType:this.deepQuery(d,"symbol"),color:c,brushType:"both",lineWidth:this.deepQuery(d,"itemStyle.normal.borderWidth"),strokeColor:this.deepQuery(d,"itemStyle.normal.borderColor")},highlightStyle:{color:this.deepQuery(d,"itemStyle.emphasis.color"),lineWidth:this.deepQuery(d,"itemStyle.emphasis.borderWidth"),strokeColor:this.deepQuery(d,"itemStyle.emphasis.borderColor")},clickable:n.clickable,position:[V+a[0],U+a[1]]});m.pack(u,e,t,i.data,i.rawIndex,i.id,i.category),this.shapeList.push(u),i.shape=u},this)},_buildLabels:function(e,t,i,a){var o=this.query(a,"itemStyle.normal.label.rotate"),r=this.query(a,"itemStyle.normal.label.distance"),s=this.parseCenter(this.zr,a.center),l=this.parseRadius(this.zr,a.radius),h=a.clockWise,m=h?1:-1; - -i.eachNode(function(t){var i=t.layout.startAngle/Math.PI*180*m,h=t.layout.endAngle/Math.PI*180*m,V=(i*-m+h*-m)/2;V%=360,0>V&&(V+=360);var d=90>=V||V>=270;V=V*Math.PI/180;var p=[Math.cos(V),-Math.sin(V)],c=0;c=a.ribbonType?a.showScaleText?35+r:r:r+t.layout.size;var u=U.scale([],p,l[1]+c);U.add(u,u,s);var y={zlevel:e.zlevel,z:e.z+1,hoverable:!1,style:{text:null==t.data.label?t.id:t.data.label,textAlign:d?"left":"right"}};o?(y.rotation=d?V:Math.PI+V,y.style.x=d?l[1]+c:-l[1]-c,y.style.y=0,y.position=s.slice()):(y.style.x=u[0],y.style.y=u[1]),y.style.color=this.deepQuery([t.data,a],"itemStyle.normal.label.textStyle.color")||"#000000",y.style.textFont=this.getFont(this.deepQuery([t.data,a],"itemStyle.normal.label.textStyle")),y=new n(y),this.shapeList.push(y),t.labelShape=y},this)},_buildRibbons:function(e,t,i,n){var a=e[t],o=this.parseCenter(this.zr,n.center),s=this.parseRadius(this.zr,n.radius);i.eachEdge(function(l,h){var V,U=i.getEdge(l.node2,l.node1);if(U&&!l.shape){if(U.shape)return void(l.shape=U.shape);var d=l.layout.startAngle/Math.PI*180,p=l.layout.endAngle/Math.PI*180,c=U.layout.startAngle/Math.PI*180,u=U.layout.endAngle/Math.PI*180;V=this.getColor(1===e.length?l.layout.weight<=U.layout.weight?l.node1.id:l.node2.id:a.name);var y,g,b=this._getEdgeQueryTarget(a,l.data),f=this._getEdgeQueryTarget(a,l.data,"emphasis"),k=new r({zlevel:a.zlevel,z:a.z,style:{x:o[0],y:o[1],r:s[0],source0:d,source1:p,target0:c,target1:u,brushType:"both",opacity:this.deepQuery(b,"opacity"),color:V,lineWidth:this.deepQuery(b,"borderWidth"),strokeColor:this.deepQuery(b,"borderColor"),clockWise:n.clockWise},clickable:n.clickable,highlightStyle:{brushType:"both",opacity:this.deepQuery(f,"opacity"),lineWidth:this.deepQuery(f,"borderWidth"),strokeColor:this.deepQuery(f,"borderColor")}});l.layout.weight<=U.layout.weight?(y=U.node1,g=U.node2):(y=l.node1,g=l.node2),m.pack(k,a,t,l.data,null==l.rawIndex?h:l.rawIndex,l.data.name||y.id+"-"+g.id,y.id,g.id),this.shapeList.push(k),l.shape=k}},this)},_buildEdgeCurves:function(e,t,i,n,a){var o=e[t],r=this.parseCenter(this.zr,n.center);i.eachEdge(function(e,i){var n=a.getNodeById(e.node1.id),s=a.getNodeById(e.node2.id),h=n.shape,V=s.shape,U=this._getEdgeQueryTarget(o,e.data),d=this._getEdgeQueryTarget(o,e.data,"emphasis"),p=new l({zlevel:o.zlevel,z:o.z,style:{xStart:h.position[0],yStart:h.position[1],xEnd:V.position[0],yEnd:V.position[1],cpX1:r[0],cpY1:r[1],lineWidth:this.deepQuery(U,"width"),strokeColor:this.deepQuery(U,"color"),opacity:this.deepQuery(U,"opacity")},highlightStyle:{lineWidth:this.deepQuery(d,"width"),strokeColor:this.deepQuery(d,"color"),opacity:this.deepQuery(d,"opacity")}});m.pack(p,o,t,e.data,null==e.rawIndex?i:e.rawIndex,e.data.name||e.node1.id+"-"+e.node2.id,e.node1.id,e.node2.id),this.shapeList.push(p),e.shape=p},this)},_buildScales:function(e,t,i){var o,r,s=e.clockWise,l=this.parseCenter(this.zr,e.center),h=this.parseRadius(this.zr,e.radius),m=s?1:-1,V=0,d=-(1/0);e.showScaleText&&(i.eachNode(function(e){var t=e.data.value;t>d&&(d=t),V+=t}),d>1e10?(o="b",r=1e-9):d>1e7?(o="m",r=1e-6):d>1e4?(o="k",r=.001):(o="",r=1));var p=V/(360-e.padding);i.eachNode(function(t){for(var i=t.layout.startAngle/Math.PI*180,V=t.layout.endAngle/Math.PI*180,d=i;;){if(s&&d>V||!s&&V>d)break;var c=d/180*Math.PI,u=[Math.cos(c),Math.sin(c)],y=U.scale([],u,h[1]+1);U.add(y,y,l);var g=U.scale([],u,h[1]+this.scaleLineLength);U.add(g,g,l);var b=new a({zlevel:e.zlevel,z:e.z-1,hoverable:!1,style:{xStart:y[0],yStart:y[1],xEnd:g[0],yEnd:g[1],lineCap:"round",brushType:"stroke",strokeColor:"#666",lineWidth:1}});this.shapeList.push(b),d+=m*this.scaleUnitAngle}if(e.showScaleText)for(var f=i,k=5*p*this.scaleUnitAngle,x=0;;){if(s&&f>V||!s&&V>f)break;var c=f;c%=360,0>c&&(c+=360);var _=90>=c||c>=270,L=new n({zlevel:e.zlevel,z:e.z-1,hoverable:!1,style:{x:_?h[1]+this.scaleLineLength+4:-h[1]-this.scaleLineLength-4,y:0,text:Math.round(10*x)/10+o,textAlign:_?"left":"right"},position:l.slice(),rotation:_?[-c/180*Math.PI,0,0]:[-(c+180)/180*Math.PI,0,0]});this.shapeList.push(L),x+=k*r,f+=m*this.scaleUnitAngle*5}},this)},refresh:function(e){if(e&&(this.option=e,this.series=e.series),this.legend=this.component.legend,this.legend)this.getColor=function(e){return this.legend.getColor(e)},this.isSelected=function(e){return this.legend.isSelected(e)};else{var t={},i=0;this.getColor=function(e){return t[e]?t[e]:(t[e]||(t[e]=this.zr.getColor(i++)),t[e])},this.isSelected=function(){return!0}}this.backupShapeList(),this._init()},reformOption:function(e){var t=V.merge;e=t(t(e||{},this.ecTheme.chord),h.chord),e.itemStyle.normal.label.textStyle=this.getTextStyle(e.itemStyle.normal.label.textStyle),this.z=e.z,this.zlevel=e.zlevel}},V.inherits(t,i),e("../chart").define("chord",t),t}),i("echarts/util/shape/Ribbon",["require","zrender/shape/Base","zrender/shape/util/PathProxy","zrender/tool/util","zrender/tool/area"],function(e){function t(e){i.call(this,e),this._pathProxy=new n}var i=e("zrender/shape/Base"),n=e("zrender/shape/util/PathProxy"),a=e("zrender/tool/util"),o=e("zrender/tool/area");return t.prototype={type:"ribbon",buildPath:function(e,t){var i=t.clockWise||!1,n=this._pathProxy;n.begin(e);var a=t.x,o=t.y,r=t.r,s=t.source0/180*Math.PI,l=t.source1/180*Math.PI,h=t.target0/180*Math.PI,m=t.target1/180*Math.PI,V=a+Math.cos(s)*r,U=o+Math.sin(s)*r,d=a+Math.cos(l)*r,p=o+Math.sin(l)*r,c=a+Math.cos(h)*r,u=o+Math.sin(h)*r,y=a+Math.cos(m)*r,g=o+Math.sin(m)*r;n.moveTo(V,U),n.arc(a,o,t.r,s,l,!i),n.bezierCurveTo(.7*(a-d)+d,.7*(o-p)+p,.7*(a-c)+c,.7*(o-u)+u,c,u),(t.source0!==t.target0||t.source1!==t.target1)&&(n.arc(a,o,t.r,h,m,!i),n.bezierCurveTo(.7*(a-y)+y,.7*(o-g)+g,.7*(a-V)+V,.7*(o-U)+U,V,U))},getRect:function(e){return e.__rect?e.__rect:(this._pathProxy.isEmpty()||this.buildPath(null,e),this._pathProxy.fastBoundingRect())},isCover:function(e,t){var i=this.getRect(this.style);return e>=i.x&&e<=i.x+i.width&&t>=i.y&&t<=i.y+i.height?o.isInsidePath(this._pathProxy.pathCommands,0,"fill",e,t):void 0}},a.inherits(t,i),t}),i("echarts/data/Graph",["require","zrender/tool/util"],function(e){var t=e("zrender/tool/util"),i=function(e){this._directed=e||!1,this.nodes=[],this.edges=[],this._nodesMap={},this._edgesMap={}};i.prototype.isDirected=function(){return this._directed},i.prototype.addNode=function(e,t){if(this._nodesMap[e])return this._nodesMap[e];var n=new i.Node(e,t);return this.nodes.push(n),this._nodesMap[e]=n,n},i.prototype.getNodeById=function(e){return this._nodesMap[e]},i.prototype.addEdge=function(e,t,n){if("string"==typeof e&&(e=this._nodesMap[e]),"string"==typeof t&&(t=this._nodesMap[t]),e&&t){var a=e.id+"-"+t.id;if(this._edgesMap[a])return this._edgesMap[a];var o=new i.Edge(e,t,n);return this._directed&&(e.outEdges.push(o),t.inEdges.push(o)),e.edges.push(o),e!==t&&t.edges.push(o),this.edges.push(o),this._edgesMap[a]=o,o}},i.prototype.removeEdge=function(e){var i=e.node1,n=e.node2,a=i.id+"-"+n.id;this._directed&&(i.outEdges.splice(t.indexOf(i.outEdges,e),1),n.inEdges.splice(t.indexOf(n.inEdges,e),1)),i.edges.splice(t.indexOf(i.edges,e),1),i!==n&&n.edges.splice(t.indexOf(n.edges,e),1),delete this._edgesMap[a],this.edges.splice(t.indexOf(this.edges,e),1)},i.prototype.getEdge=function(e,t){return"string"!=typeof e&&(e=e.id),"string"!=typeof t&&(t=t.id),this._directed?this._edgesMap[e+"-"+t]:this._edgesMap[e+"-"+t]||this._edgesMap[t+"-"+e]},i.prototype.removeNode=function(e){if("string"!=typeof e||(e=this._nodesMap[e])){delete this._nodesMap[e.id],this.nodes.splice(t.indexOf(this.nodes,e),1);for(var i=0;in;)e.call(t,this.nodes[n],n)?n++:(this.removeNode(this.nodes[n]),i--)},i.prototype.filterEdge=function(e,t){for(var i=this.edges.length,n=0;i>n;)e.call(t,this.edges[n],n)?n++:(this.removeEdge(this.edges[n]),i--)},i.prototype.eachNode=function(e,t){for(var i=this.nodes.length,n=0;i>n;n++)this.nodes[n]&&e.call(t,this.nodes[n],n)},i.prototype.eachEdge=function(e,t){for(var i=this.edges.length,n=0;i>n;n++)this.edges[n]&&e.call(t,this.edges[n],n)},i.prototype.clear=function(){this.nodes.length=0,this.edges.length=0,this._nodesMap={},this._edgesMap={}},i.prototype.breadthFirstTraverse=function(e,t,i,n){if("string"==typeof t&&(t=this._nodesMap[t]),t){var a="edges";"out"===i?a="outEdges":"in"===i&&(a="inEdges");for(var o=0;or;r++){var s=o.addNode(e[r].id,e[r]);s.data.value=0,n&&(s.data.outValue=s.data.inValue=0)}for(var r=0;a>r;r++)for(var l=0;a>l;l++){var h=t[r][l];n&&(o.nodes[r].data.outValue+=h,o.nodes[l].data.inValue+=h),o.nodes[r].data.value+=h,o.nodes[l].data.value+=h}for(var r=0;a>r;r++)for(var l=r;a>l;l++){var h=t[r][l];if(0!==h){var m=o.nodes[r],V=o.nodes[l],U=o.addEdge(m,V,{});if(U.data.weight=h,r!==l&&n&&t[l][r]){var d=o.addEdge(V,m,{});d.data.weight=t[l][r]}}}return o}},i}),i("echarts/layout/Chord",["require"],function(){var e=function(e){e=e||{},this.sort=e.sort||null,this.sortSub=e.sortSub||null,this.padding=.05,this.startAngle=e.startAngle||0,this.clockWise=null==e.clockWise?!1:e.clockWise,this.center=e.center||[0,0],this.directed=!0};e.prototype.run=function(e){e instanceof Array||(e=[e]);var n=e.length;if(n){for(var a=e[0],o=a.nodes.length,r=[],s=0,l=0;o>l;l++){var h=a.nodes[l],m={size:0,subGroups:[],node:h};r.push(m);for(var V=0,U=0;Ul;l++){var m=r[l];m.node.layout.startAngle=f,m.node.layout.endAngle=f+k*m.size*b,m.node.layout.subGroups=[];for(var u=0;un;n++){var o=i[n];if(o.type===d.CHART_TYPE_FORCE){if(i[n]=this.reformOption(i[n]),e=i[n].name||"",this.selectedMap[e]=t?t.isSelected(e):!0,!this.selectedMap[e])continue;this.buildMark(n),this._initSerie(o,n);break}}this.animationEffect()},_getNodeCategory:function(e,t){return e.categories&&e.categories[t.category||0]},_getNodeQueryTarget:function(e,t,i){i=i||"normal";var n=this._getNodeCategory(e,t)||{};return[t.itemStyle&&t.itemStyle[i],n&&n.itemStyle&&n.itemStyle[i],e.itemStyle[i].nodeStyle]},_getEdgeQueryTarget:function(e,t,i){return i=i||"normal",[t.itemStyle&&t.itemStyle[i],e.itemStyle[i].linkStyle]},_initSerie:function(e,t){this._temperature=1,e.matrix?this._graph=this._getSerieGraphFromDataMatrix(e):e.links&&(this._graph=this._getSerieGraphFromNodeLinks(e)),this._buildLinkShapes(e,t),this._buildNodeShapes(e,t);var i=e.roam===!0||"move"===e.roam,n=e.roam===!0||"scale"===e.roam;this.zr.modLayer(this.getZlevelBase(),{panable:i,zoomable:n}),(this.query("markPoint.effect.show")||this.query("markLine.effect.show"))&&this.zr.modLayer(d.EFFECT_ZLEVEL,{panable:i,zoomable:n}),this._initLayout(e),this._step()},_getSerieGraphFromDataMatrix:function(e){for(var t=[],i=0,n=[],a=0;an;n++){var o=i[n];if(o&&!o.ignore){var r=this._getNodeCategory(e,o),l=r?r.name:o.name;if(this.selectedMap[l]=this.isSelected(l),this.selectedMap[l]){var h=t.addNode(o.name,o);h.rawIndex=n}}}for(var n=0,a=e.links.length;a>n;n++){var m=e.links[n],V=m.source,U=m.target;"number"==typeof V&&(V=i[V],V&&(V=V.name)),"number"==typeof U&&(U=i[U],U&&(U=U.name));var d=t.addEdge(V,U,m);d&&(d.rawIndex=n)}return t.eachNode(function(e){var t=e.data.value;if(null==t){t=0;for(var i=0;ih;h++){var m=t.nodes[h];l=Math.max(m.layout.size,l),s=Math.min(m.layout.size,s)}for(var V=l-s,h=0;i>h;h++){var m=t.nodes[h];V>0?(m.layout.size=(m.layout.size-s)*(a-n)/V+n,m.layout.mass=m.layout.size/a):(m.layout.size=(a-n)/2,m.layout.mass=.5)}for(var h=0;i>h;h++){var m=t.nodes[h];if("undefined"!=typeof this.__nodePositionMap[m.id])m.layout.position=y.create(),y.copy(m.layout.position,this.__nodePositionMap[m.id]);else if("undefined"!=typeof m.data.initial)m.layout.position=y.create(),y.copy(m.layout.position,m.data.initial);else{var U=this._layout.center,d=Math.min(this._layout.width,this._layout.height);m.layout.position=o(U[0],U[1],.8*d)}var p=m.shape.style,c=m.layout.size;p.width=p.width||2*c,p.height=p.height||2*c,p.x=-p.width/2,p.y=-p.height/2,y.copy(m.shape.position,m.layout.position)}i=t.edges.length,l=-(1/0);for(var h=0;i>h;h++){var u=t.edges[h];u.layout.weight>l&&(l=u.layout.weight)}for(var h=0;i>h;h++){var u=t.edges[h];u.layout.weight/=l}this._layout.init(t,e.useWorker)},_buildNodeShapes:function(e,t){var i=this._graph,n=this.query(e,"categories");i.eachNode(function(i){var a=this._getNodeCategory(e,i.data),o=[i.data,a,e],r=this._getNodeQueryTarget(e,i.data),s=this._getNodeQueryTarget(e,i.data,"emphasis"),l=new U({style:{x:0,y:0,color:this.deepQuery(r,"color"),brushType:"both",strokeColor:this.deepQuery(r,"strokeColor")||this.deepQuery(r,"borderColor"),lineWidth:this.deepQuery(r,"lineWidth")||this.deepQuery(r,"borderWidth")},highlightStyle:{color:this.deepQuery(s,"color"),strokeColor:this.deepQuery(s,"strokeColor")||this.deepQuery(s,"borderColor"),lineWidth:this.deepQuery(s,"lineWidth")||this.deepQuery(s,"borderWidth")},clickable:e.clickable,zlevel:this.getZlevelBase(),z:this.getZBase()});l.style.color||(l.style.color=this.getColor(a?a.name:i.id)),l.style.iconType=this.deepQuery(o,"symbol");var h=this.deepQuery(o,"symbolSize")||0;"number"==typeof h&&(h=[h,h]),l.style.width=2*h[0],l.style.height=2*h[1],l.style.iconType.match("image")&&(l.style.image=l.style.iconType.replace(new RegExp("^image:\\/\\/"),""),l=new V({style:l.style,highlightStyle:l.highlightStyle,clickable:l.clickable,zlevel:this.getZlevelBase(),z:this.getZBase()})),this.deepQuery(o,"itemStyle.normal.label.show")&&(l.style.text=null==i.data.label?i.id:i.data.label,l.style.textPosition=this.deepQuery(o,"itemStyle.normal.label.position"),l.style.textColor=this.deepQuery(o,"itemStyle.normal.label.textStyle.color"),l.style.textFont=this.getFont(this.deepQuery(o,"itemStyle.normal.label.textStyle")||{})),this.deepQuery(o,"itemStyle.emphasis.label.show")&&(l.highlightStyle.textPosition=this.deepQuery(o,"itemStyle.emphasis.label.position"),l.highlightStyle.textColor=this.deepQuery(o,"itemStyle.emphasis.label.textStyle.color"),l.highlightStyle.textFont=this.getFont(this.deepQuery(o,"itemStyle.emphasis.label.textStyle")||{})),this.deepQuery(o,"draggable")&&(this.setCalculable(l),l.dragEnableTime=0,l.draggable=!0,l.ondragstart=this.shapeHandler.ondragstart,l.ondragover=null);var m="";if("undefined"!=typeof i.category){var a=n[i.category];m=a&&a.name||""}p.pack(l,e,t,i.data,i.rawIndex,i.data.name||"",i.category),this.shapeList.push(l),this.zr.addShape(l),i.shape=l},this)},_buildLinkShapes:function(e,t){for(var i=this._graph,n=i.edges.length,a=0;n>a;a++){var o=i.edges[a],r=o.data,s=o.node1,l=o.node2,V=i.getEdge(l,s),d=this._getEdgeQueryTarget(e,r),u=this.deepQuery(d,"type");e.linkSymbol&&"none"!==e.linkSymbol&&(u="line");var y="line"===u?h:m,g=new y({style:{xStart:0,yStart:0,xEnd:0,yEnd:0},clickable:this.query(e,"clickable"),highlightStyle:{},zlevel:this.getZlevelBase(),z:this.getZBase()});if(V&&V.shape&&(g.style.offset=4,V.shape.style.offset=4),c.merge(g.style,this.query(e,"itemStyle.normal.linkStyle"),!0),c.merge(g.highlightStyle,this.query(e,"itemStyle.emphasis.linkStyle"),!0),"undefined"!=typeof r.itemStyle&&(r.itemStyle.normal&&c.merge(g.style,r.itemStyle.normal,!0),r.itemStyle.emphasis&&c.merge(g.highlightStyle,r.itemStyle.emphasis,!0)),g.style.lineWidth=g.style.lineWidth||g.style.width,g.style.strokeColor=g.style.strokeColor||g.style.color,g.highlightStyle.lineWidth=g.highlightStyle.lineWidth||g.highlightStyle.width,g.highlightStyle.strokeColor=g.highlightStyle.strokeColor||g.highlightStyle.color,p.pack(g,e,t,o.data,null==o.rawIndex?a:o.rawIndex,o.data.name||s.id+" - "+l.id,s.id,l.id),this.shapeList.push(g),this.zr.addShape(g),o.shape=g,e.linkSymbol&&"none"!==e.linkSymbol){var b=new U({style:{x:-5,y:0,width:e.linkSymbolSize[0],height:e.linkSymbolSize[1],iconType:e.linkSymbol,brushType:"fill",color:g.style.strokeColor},highlightStyle:{brushType:"fill"},position:[0,0],rotation:0,zlevel:this.getZlevelBase(),z:this.getZBase()});g._symbolShape=b,this.shapeList.push(b),this.zr.addShape(b)}}},_updateLinkShapes:function(){for(var e=y.create(),t=y.create(),i=y.create(),n=y.create(),a=this._graph.edges,o=0,r=a.length;r>o;o++){var s=a[o],l=s.node1.shape,h=s.node2.shape;y.copy(i,l.position),y.copy(n,h.position);var m=s.shape.style;if(y.sub(e,i,n),y.normalize(e,e),m.offset?(t[0]=e[1],t[1]=-e[0],y.scaleAndAdd(i,i,t,m.offset),y.scaleAndAdd(n,n,t,m.offset)):"bezier-curve"===s.shape.type&&(m.cpX1=(i[0]+n[0])/2-(n[1]-i[1])/4,m.cpY1=(i[1]+n[1])/2-(i[0]-n[0])/4),m.xStart=i[0],m.yStart=i[1],m.xEnd=n[0],m.yEnd=n[1],s.shape.modSelf(),s.shape._symbolShape){var V=s.shape._symbolShape;y.copy(V.position,n),y.scaleAndAdd(V.position,V.position,e,h.style.width/2+2);var U=Math.atan2(e[1],e[0]);V.rotation=Math.PI/2-U,V.modSelf()}}},_syncNodePositions:function(){for(var e=this._graph,t=0;t.01?this._layout.step(this._steps):this.messageCenter.dispatch(d.EVENT.FORCE_LAYOUT_END,{},{},this.myChart)},refresh:function(e){if(e&&(this.option=e,this.series=this.option.series),this.legend=this.component.legend,this.legend)this.getColor=function(e){return this.legend.getColor(e)},this.isSelected=function(e){return this.legend.isSelected(e)};else{var t={},i=0;this.getColor=function(e){return t[e]?t[e]:(t[e]||(t[e]=this.zr.getColor(i++)),t[e])},this.isSelected=function(){return!0}}this._init()},dispose:function(){this.clear(),this.shapeList=null,this.effectList=null,this._layout.dispose(),this._layout=null,this.__nodePositionMap={}},getPosition:function(){var e=[];return this._graph.eachNode(function(t){t.layout&&e.push({name:t.data.name,position:Array.prototype.slice.call(t.layout.position)})}),e}},c.inherits(t,r),e("../chart").define("force",t),t}),i("echarts/layout/Force",["require","./forceLayoutWorker","zrender/tool/vector"],function(e){function t(){if("undefined"!=typeof Worker&&"undefined"!=typeof Blob)try{var e=new Blob([n.getWorkerCode()]);i=window.URL.createObjectURL(e)}catch(t){i=""}return i}var i,n=e("./forceLayoutWorker"),a=e("zrender/tool/vector"),o=window.requestAnimationFrame||window.msRequestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||function(e){setTimeout(e,16)},r="undefined"==typeof Float32Array?Array:Float32Array,s=function(e){"undefined"==typeof i&&t(),e=e||{},this.width=e.width||500,this.height=e.height||500,this.center=e.center||[this.width/2,this.height/2],this.ratioScaling=e.ratioScaling||!1,this.scaling=e.scaling||1,this.gravity="undefined"!=typeof e.gravity?e.gravity:1,this.large=e.large||!1,this.preventNodeOverlap=e.preventNodeOverlap||!1,this.preventNodeEdgeOverlap=e.preventNodeEdgeOverlap||!1,this.maxSpeedIncrease=e.maxSpeedIncrease||1,this.onupdate=e.onupdate||function(){},this.temperature=e.temperature||1,this.coolDown=e.coolDown||.99,this._layout=null,this._layoutWorker=null;var n=this,a=this._$onupdate;this._$onupdate=function(e){a.call(n,e)}};return s.prototype.updateConfig=function(){var e=this.width,t=this.height,i=Math.min(e,t),n={center:this.center,width:this.ratioScaling?e:i,height:this.ratioScaling?t:i,scaling:this.scaling||1,gravity:this.gravity||1,barnesHutOptimize:this.large,preventNodeOverlap:this.preventNodeOverlap,preventNodeEdgeOverlap:this.preventNodeEdgeOverlap,maxSpeedIncrease:this.maxSpeedIncrease};if(this._layoutWorker)this._layoutWorker.postMessage({cmd:"updateConfig",config:n});else for(var a in n)this._layout[a]=n[a]},s.prototype.init=function(e,t){if(this._layoutWorker&&(this._layoutWorker.terminate(),this._layoutWorker=null),i&&t)try{this._layoutWorker||(this._layoutWorker=new Worker(i),this._layoutWorker.onmessage=this._$onupdate),this._layout=null}catch(a){this._layoutWorker=null,this._layout||(this._layout=new n)}else this._layout||(this._layout=new n);this.temperature=1,this.graph=e;for(var o=e.nodes.length,s=new r(2*o),l=new r(o),h=new r(o),m=0;o>m;m++){var V=e.nodes[m];s[2*m]=V.layout.position[0],s[2*m+1]=V.layout.position[1],l[m]="undefined"==typeof V.layout.mass?1:V.layout.mass,h[m]="undefined"==typeof V.layout.size?1:V.layout.size,V.layout.__index=m}o=e.edges.length;for(var U=new r(2*o),d=new r(o),m=0;o>m;m++){var p=e.edges[m];U[2*m]=p.node1.layout.__index,U[2*m+1]=p.node2.layout.__index,d[m]=p.layout.weight||1}this._layoutWorker?this._layoutWorker.postMessage({cmd:"init",nodesPosition:s,nodesMass:l,nodesSize:h,edges:U,edgesWeight:d}):(this._layout.initNodes(s,l,h),this._layout.initEdges(U,d)),this.updateConfig()},s.prototype.step=function(e){var t=this.graph.nodes;if(this._layoutWorker){for(var i=new r(2*t.length),n=0;nn;n++)this.temperature*=this.coolDown}else{o(this._$onupdate);for(var n=0;nn;n++)this._layout.temperature=this.temperature,this._layout.update(),this.temperature*=this.coolDown}},s.prototype._$onupdate=function(e){if(this._layoutWorker){for(var t=new Float32Array(e.data),i=0;i0&&(a=1/Math.sqrt(a),e[0]=t[0]*a,e[1]=t[1]*a),e},negate:function(e,t){return e[0]=-t[0],e[1]=-t[1],e},copy:function(e,t){return e[0]=t[0],e[1]=t[1],e},set:function(e,t,i){return e[0]=t,e[1]=i,e}}:e("zrender/tool/vector");var l="undefined"==typeof Float32Array?Array:Float32Array;if(t.prototype.beforeUpdate=function(){for(var e=0;e=e&&this.bbox[1]<=t&&this.bbox[3]>=t},t.prototype.setBBox=function(e,t,i,n){this.bbox[0]=e,this.bbox[1]=t,this.bbox[2]=i,this.bbox[3]=n,this.size=(i-e+n-t)/2},t.prototype._newSubRegion=function(){var e=this.subRegions[this.nSubRegions];return e||(e=new t,this.subRegions[this.nSubRegions]=e),this.nSubRegions++,e},t.prototype._addNodeToSubRegion=function(e){var t=this.findSubRegion(e.position[0],e.position[1]),i=this.bbox;if(!t){var n=(i[0]+i[2])/2,a=(i[1]+i[3])/2,o=(i[2]-i[0])/2,r=(i[3]-i[1])/2,s=e.position[0]>=n?1:0,l=e.position[1]>=a?1:0,t=this._newSubRegion();t.setBBox(s*o+i[0],l*r+i[1],(s+1)*o+i[0],(l+1)*r+i[1])}t.addNode(e)},t.prototype._updateCenterOfMass=function(e){null==this.centerOfMass&&(this.centerOfMass=r.create());var t=this.centerOfMass[0]*this.mass,i=this.centerOfMass[1]*this.mass;t+=e.position[0]*e.mass,i+=e.position[1]*e.mass,this.mass+=e.mass,this.centerOfMass[0]=t/this.mass,this.centerOfMass[1]=i/this.mass},a.prototype.nodeToNodeRepulsionFactor=function(e,t,i){return i*i*e/t},a.prototype.edgeToNodeRepulsionFactor=function(e,t,i){return i*e/t},a.prototype.attractionFactor=function(e,t,i){return e*t/i},a.prototype.initNodes=function(e,t,n){this.temperature=1;var a=e.length/2;this.nodes.length=0;for(var o="undefined"!=typeof n,r=0;a>r;r++){var s=new i;s.position[0]=e[2*r],s.position[1]=e[2*r+1],s.mass=t[r],o&&(s.size=n[r]),this.nodes.push(s)}this._massArr=t,o&&(this._sizeArr=n)},a.prototype.initEdges=function(e,t){var i=e.length/2;this.edges.length=0;for(var a="undefined"!=typeof t,o=0;i>o;o++){var r=e[2*o],s=e[2*o+1],l=this.nodes[r],h=this.nodes[s];if(l&&h){l.outDegree++,h.inDegree++;var m=new n(l,h);a&&(m.weight=t[o]),this.edges.push(m)}}},a.prototype.update=function(){var e=this.nodes.length;if(this.updateBBox(),this._k=.4*this.scaling*Math.sqrt(this.width*this.height/e),this.barnesHutOptimize){this._rootRegion.setBBox(this.bbox[0],this.bbox[1],this.bbox[2],this.bbox[3]),this._rootRegion.beforeUpdate();for(var t=0;e>t;t++)this._rootRegion.addNode(this.nodes[t]);this._rootRegion.afterUpdate()}else{var i=0,n=this._rootRegion.centerOfMass;r.set(n,0,0);for(var t=0;e>t;t++){var a=this.nodes[t];i+=a.mass,r.scaleAndAdd(n,n,a.position,a.mass); - -}i>0&&r.scale(n,n,1/i)}this.updateForce(),this.updatePosition()},a.prototype.updateForce=function(){for(var e=this.nodes.length,t=0;e>t;t++){var i=this.nodes[t];r.copy(i.forcePrev,i.force),r.copy(i.speedPrev,i.speed),r.set(i.force,0,0)}this.updateNodeNodeForce(),this.gravity>0&&this.updateGravityForce(),this.updateEdgeForce(),this.preventNodeEdgeOverlap&&this.updateNodeEdgeForce()},a.prototype.updatePosition=function(){for(var e=this.nodes.length,t=r.create(),i=0;e>i;i++){var n=this.nodes[i],a=n.speed;r.scale(n.force,n.force,1/30);var o=r.len(n.force)+.1,s=Math.min(o,500)/o;r.scale(n.force,n.force,s),r.add(a,a,n.force),r.scale(a,a,this.temperature),r.sub(t,a,n.speedPrev);var l=r.len(t);if(l>0){r.scale(t,t,1/l);var h=r.len(n.speedPrev);h>0&&(l=Math.min(l/h,this.maxSpeedIncrease)*h,r.scaleAndAdd(a,n.speedPrev,t,l))}var m=r.len(a),s=Math.min(m,100)/(m+.1);r.scale(a,a,s),r.add(n.position,n.position,a)}},a.prototype.updateNodeNodeForce=function(){for(var e=this.nodes.length,t=0;e>t;t++){var i=this.nodes[t];if(this.barnesHutOptimize)this.applyRegionToNodeRepulsion(this._rootRegion,i);else for(var n=t+1;e>n;n++){var a=this.nodes[n];this.applyNodeToNodeRepulsion(i,a,!1)}}},a.prototype.updateGravityForce=function(){for(var e=0;ethis.barnesHutTheta*t.size*t.size){var a=this._k*this._k*(i.mass+t.mass)/(n+1);r.scaleAndAdd(i.force,i.force,e,2*a)}else for(var o=0;o0?o=this.nodeToNodeRepulsionFactor(s,l,this._k):0>=l&&(o=this._k*this._k*10*s)):o=this.nodeToNodeRepulsionFactor(s,l,this._k),n||r.scaleAndAdd(t.force,t.force,e,2*o),r.scaleAndAdd(i.force,i.force,e,2*-o)}}}}(),a.prototype.applyEdgeAttraction=function(){var e=r.create();return function(t){var i=t.node1,n=t.node2;r.sub(e,i.position,n.position);var a,o=r.len(e);a=0===this.edgeWeightInfluence?1:1==this.edgeWeightInfluence?t.weight:Math.pow(t.weight,this.edgeWeightInfluence);var s;if(!(this.preventOverlap&&(o=o-i.size-n.size,0>=o))){var s=this.attractionFactor(a,o,this._k);r.scaleAndAdd(i.force,i.force,e,-s),r.scaleAndAdd(n.force,n.force,e,s)}}}(),a.prototype.applyNodeGravity=function(){var e=r.create();return function(t){r.sub(e,this.center,t.position),this.width>this.height?e[1]*=this.width/this.height:e[0]*=this.height/this.width;var i=r.len(e)/100;this.strongGravity?r.scaleAndAdd(t.force,t.force,e,i*this.gravity*t.mass):r.scaleAndAdd(t.force,t.force,e,this.gravity*t.mass/(i+1))}}(),a.prototype.applyEdgeToNodeRepulsion=function(){var e=r.create(),t=r.create(),i=r.create();return function(n,a){var o=n.node1,s=n.node2;if(o!==a&&s!==a){r.sub(e,s.position,o.position),r.sub(t,a.position,o.position);var l=r.len(e);r.scale(e,e,1/l);var h=r.dot(e,t);if(!(0>h||h>l)){r.scaleAndAdd(i,o.position,e,h);var m=r.dist(i,a.position)-a.size,V=this.edgeToNodeRepulsionFactor(a.mass,Math.max(m,.1),100);r.sub(e,a.position,i),r.normalize(e,e),r.scaleAndAdd(a.force,a.force,e,V),r.scaleAndAdd(o.force,o.force,e,-V),r.scaleAndAdd(s.force,s.force,e,-V)}}}}(),a.prototype.updateBBox=function(){for(var e=1/0,t=1/0,i=-(1/0),n=-(1/0),a=0;an;n++){var o=h.nodes[n];o.position[0]=t[2*n],o.position[1]=t[2*n+1]}}else switch(e.data.cmd){case"init":h||(h=new a),h.initNodes(e.data.nodesPosition,e.data.nodesMass,e.data.nodesSize),h.initEdges(e.data.edges,e.data.edgesWeight);break;case"updateConfig":if(h)for(var r in e.data.config)h[r]=e.data.config[r];break;case"update":var s=e.data.steps;if(h){var i=h.nodes.length,t=new Float32Array(2*i);h.temperature=e.data.temperature;for(var n=0;s>n;n++)h.update(),h.temperature*=e.data.coolDown;for(var n=0;i>n;n++){var o=h.nodes[n];t[2*n]=o.position[0],t[2*n+1]=o.position[1]}self.postMessage(t.buffer,[t.buffer])}else{var l=new Float32Array;self.postMessage(l.buffer,[l.buffer])}}}}return a}),i("echarts/chart/map",["require","./base","zrender/shape/Text","zrender/shape/Path","zrender/shape/Circle","zrender/shape/Rectangle","zrender/shape/Line","zrender/shape/Polygon","zrender/shape/Ellipse","zrender/shape/Image","../component/dataRange","../component/roamController","../layer/heatmap","../config","../util/ecData","zrender/tool/util","zrender/config","zrender/tool/event","../util/mapData/params","../util/mapData/textFixed","../util/mapData/geoCoord","../util/projection/svg","../util/projection/normal","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o);var r=this;r._onmousewheel=function(e){return r.__onmousewheel(e)},r._onmousedown=function(e){return r.__onmousedown(e)},r._onmousemove=function(e){return r.__onmousemove(e)},r._onmouseup=function(e){return r.__onmouseup(e)},r._onroamcontroller=function(e){return r.__onroamcontroller(e)},r._ondrhoverlink=function(e){return r.__ondrhoverlink(e)},this._isAlive=!0,this._selectedMode={},this._activeMapType={},this._clickable={},this._hoverable={},this._showLegendSymbol={},this._selected={},this._mapTypeMap={},this._mapDataMap={},this._nameMap={},this._specialArea={},this._refreshDelayTicket,this._mapDataRequireCounter,this._markAnimation=!1,this._hoverLinkMap={},this._roamMap={},this._scaleLimitMap={},this._mx,this._my,this._mousedown,this._justMove,this._curMapType,this.refresh(a),this.zr.on(c.EVENT.MOUSEWHEEL,this._onmousewheel),this.zr.on(c.EVENT.MOUSEDOWN,this._onmousedown),t.bind(U.EVENT.ROAMCONTROLLER,this._onroamcontroller),t.bind(U.EVENT.DATA_RANGE_HOVERLINK,this._ondrhoverlink)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Path"),o=e("zrender/shape/Circle"),r=e("zrender/shape/Rectangle"),s=e("zrender/shape/Line"),l=e("zrender/shape/Polygon"),h=e("zrender/shape/Ellipse"),m=e("zrender/shape/Image");e("../component/dataRange"),e("../component/roamController");var V=e("../layer/heatmap"),U=e("../config");U.map={zlevel:0,z:2,mapType:"china",showLegendSymbol:!0,dataRangeHoverLink:!0,hoverable:!0,clickable:!0,itemStyle:{normal:{borderColor:"rgba(0,0,0,0)",borderWidth:1,areaStyle:{color:"#ccc"},label:{show:!1,textStyle:{color:"rgb(139,69,19)"}}},emphasis:{borderColor:"rgba(0,0,0,0)",borderWidth:1,areaStyle:{color:"rgba(255,215,0,0.8)"},label:{show:!1,textStyle:{color:"rgb(100,0,0)"}}}}};var d=e("../util/ecData"),p=e("zrender/tool/util"),c=e("zrender/config"),u=e("zrender/tool/event"),y=e("../util/mapData/params").params,g=e("../util/mapData/textFixed"),b=e("../util/mapData/geoCoord");return t.prototype={type:U.CHART_TYPE_MAP,_buildShape:function(){var e=this.series;this.selectedMap={},this._activeMapType={};for(var t,i,n,a,o=this.component.legend,r={},s={},l={},h={},m=0,V=e.length;V>m;m++)if(e[m].type==U.CHART_TYPE_MAP&&(e[m]=this.reformOption(e[m]),i=e[m].mapType,s[i]=s[i]||{},s[i][m]=!0,l[i]=l[i]||e[m].mapValuePrecision,this._scaleLimitMap[i]=this._scaleLimitMap[i]||{},e[m].scaleLimit&&p.merge(this._scaleLimitMap[i],e[m].scaleLimit,!0),this._roamMap[i]=e[m].roam||this._roamMap[i],(null==this._hoverLinkMap[i]||this._hoverLinkMap[i])&&(this._hoverLinkMap[i]=e[m].dataRangeHoverLink),this._nameMap[i]=this._nameMap[i]||{},e[m].nameMap&&p.merge(this._nameMap[i],e[m].nameMap,!0),this._activeMapType[i]=!0,e[m].textFixed&&p.merge(g,e[m].textFixed,!0),e[m].geoCoord&&p.merge(b,e[m].geoCoord,!0),this._selectedMode[i]=this._selectedMode[i]||e[m].selectedMode,(null==this._hoverable[i]||this._hoverable[i])&&(this._hoverable[i]=e[m].hoverable),(null==this._clickable[i]||this._clickable[i])&&(this._clickable[i]=e[m].clickable),(null==this._showLegendSymbol[i]||this._showLegendSymbol[i])&&(this._showLegendSymbol[i]=e[m].showLegendSymbol),h[i]=h[i]||e[m].mapValueCalculation,t=e[m].name,this.selectedMap[t]=o?o.isSelected(t):!0,this.selectedMap[t])){r[i]=r[i]||{},n=e[m].data;for(var d=0,c=n.length;c>d;d++){a=this._nameChange(i,n[d].name),r[i][a]=r[i][a]||{seriesIndex:[],valueMap:{},precision:0};for(var u in n[d])"value"!=u?r[i][a][u]=n[d][u]:isNaN(n[d].value)||(null==r[i][a].value&&(r[i][a].value=0),r[i][a].precision=Math.max(this.getPrecision(+n[d].value),r[i][a].precision),r[i][a].value+=+n[d].value,r[i][a].valueMap[m]=+n[d].value);r[i][a].seriesIndex.push(m)}}this._mapDataRequireCounter=0;for(var f in r)this._mapDataRequireCounter++;this._clearSelected(),0===this._mapDataRequireCounter&&(this.clear(),this.zr&&this.zr.delShape(this.lastShapeList),this.lastShapeList=[]);for(var f in r){for(var c in r[f]){"average"==h[f]&&(r[f][c].value/=r[f][c].seriesIndex.length);var k=r[f][c].value;null!=k&&(r[f][c].value=k.toFixed(null==l[f]?r[f][c].precision:l[f])-0)}this._mapDataMap[f]=this._mapDataMap[f]||{},this._mapDataMap[f].mapData?this._mapDataCallback(f,r[f],s[f])(this._mapDataMap[f].mapData):y[f.replace(/\|.*/,"")].getGeoJson&&(this._specialArea[f]=y[f.replace(/\|.*/,"")].specialArea||this._specialArea[f],y[f.replace(/\|.*/,"")].getGeoJson(this._mapDataCallback(f,r[f],s[f])))}},_mapDataCallback:function(t,i,n){var a=this;return function(o){a._isAlive&&null!=a._activeMapType[t]&&(-1!=t.indexOf("|")&&(o=a._getSubMapData(t,o)),a._mapDataMap[t].mapData=o,o.firstChild?(a._mapDataMap[t].rate=1,a._mapDataMap[t].projection=e("../util/projection/svg")):(a._mapDataMap[t].rate=.75,a._mapDataMap[t].projection=e("../util/projection/normal")),a._buildMap(t,a._getProjectionData(t,o,n),i,n),a._buildMark(t,n),--a._mapDataRequireCounter<=0&&(a.addShapeList(),a.zr.refreshNextFrame()),a._buildHeatmap(t))}},_clearSelected:function(){for(var e in this._selected)this._activeMapType[this._mapTypeMap[e]]||(delete this._selected[e],delete this._mapTypeMap[e])},_getSubMapData:function(e,t){for(var i=e.replace(/^.*\|/,""),n=t.features,a=0,o=n.length;o>a;a++)if(n[a].properties&&n[a].properties.name==i){n=n[a],"United States of America"==i&&n.geometry.coordinates.length>1&&(n={geometry:{coordinates:n.geometry.coordinates.slice(5,6),type:n.geometry.type},id:n.id,properties:n.properties,type:n.type});break}return{type:"FeatureCollection",features:[n]}},_getProjectionData:function(e,t,i){var n,a=this._mapDataMap[e].projection,o=[],r=this._mapDataMap[e].bbox||a.getBbox(t,this._specialArea[e]);n=this._mapDataMap[e].hasRoam?this._mapDataMap[e].transform:this._getTransform(r,i,this._mapDataMap[e].rate);var s,l=this._mapDataMap[e].lastTransform||{scale:{}};n.left!=l.left||n.top!=l.top||n.scale.x!=l.scale.x||n.scale.y!=l.scale.y?(s=a.geoJson2Path(t,n,this._specialArea[e]),l=p.clone(n)):(n=this._mapDataMap[e].transform,s=this._mapDataMap[e].pathArray),this._mapDataMap[e].bbox=r,this._mapDataMap[e].transform=n,this._mapDataMap[e].lastTransform=l,this._mapDataMap[e].pathArray=s;for(var h=[n.left,n.top],m=0,V=s.length;V>m;m++)o.push(this._getSingleProvince(e,s[m],h));if(this._specialArea[e])for(var U in this._specialArea[e])o.push(this._getSpecialProjectionData(e,t,U,this._specialArea[e][U],h));if("china"==e){var d=this.geo2pos(e,b["南海诸岛"]||y["南海诸岛"].textCoord),c=n.scale.x/10.5,u=[32*c+d[0],83*c+d[1]];g["南海诸岛"]&&(u[0]+=g["南海诸岛"][0],u[1]+=g["南海诸岛"][1]),o.push({name:this._nameChange(e,"南海诸岛"),path:y["南海诸岛"].getPath(d,c),position:h,textX:u[0],textY:u[1]})}return o},_getSpecialProjectionData:function(t,i,n,a,o){i=this._getSubMapData("x|"+n,i);var r=e("../util/projection/normal"),s=r.getBbox(i),l=this.geo2pos(t,[a.left,a.top]),h=this.geo2pos(t,[a.left+a.width,a.top+a.height]),m=Math.abs(h[0]-l[0]),V=Math.abs(h[1]-l[1]),U=s.width,d=s.height,p=m/.75/U,c=V/d;p>c?(p=.75*c,m=U*p):(c=p,p=.75*c,V=d*c);var u={OffsetLeft:l[0],OffsetTop:l[1],scale:{x:p,y:c}},y=r.geoJson2Path(i,u);return this._getSingleProvince(t,y[0],o)},_getSingleProvince:function(e,t,i){var n,a=t.properties.name,o=g[a]||[0,0];if(b[a])n=this.geo2pos(e,b[a]);else if(t.cp)n=[t.cp[0]+o[0],t.cp[1]+o[1]];else{var r=this._mapDataMap[e].bbox;n=this.geo2pos(e,[r.left+r.width/2,r.top+r.height/2]),n[0]+=o[0],n[1]+=o[1]}return t.name=this._nameChange(e,a),t.position=i,t.textX=n[0],t.textY=n[1],t},_getTransform:function(e,t,i){var n,a,o,r,s,l,h,m=this.series,V=this.zr.getWidth(),U=this.zr.getHeight(),d=Math.round(.02*Math.min(V,U));for(var p in t)n=m[p].mapLocation||{},o=n.x||o,s=n.y||s,l=n.width||l,h=n.height||h;a=this.parsePercent(o,V),a=isNaN(a)?d:a,r=this.parsePercent(s,U),r=isNaN(r)?d:r,l=null==l?V-a-2*d:this.parsePercent(l,V),h=null==h?U-r-2*d:this.parsePercent(h,U);var c=e.width,u=e.height,y=l/i/c,g=h/u;if(y>g?(y=g*i,l=c*y):(g=y,y=g*i,h=u*g),isNaN(o))switch(o=o||"center",o+""){case"center":a=Math.floor((V-l)/2);break;case"right":a=V-l}if(isNaN(s))switch(s=s||"center",s+""){case"center":r=Math.floor((U-h)/2);break;case"bottom":r=U-h}return{left:a,top:r,width:l,height:h,baseScale:1,scale:{x:y,y:g}}},_buildMap:function(e,t,i,m){for(var V,c,u,y,g,b,f,k,x,_,L,W=this.series,X=this.component.legend,v=this.component.dataRange,w=0,K=t.length;K>w;w++){if(k=p.clone(t[w]),x={name:k.name,path:k.path,position:p.clone(k.position)},c=k.name,u=i[c]){g=[u],V="";for(var I=0,J=u.seriesIndex.length;J>I;I++){var C=W[u.seriesIndex[I]];g.push(C),V+=C.name+" ",X&&this._showLegendSymbol[e]&&X.hasColor(C.name)&&this.shapeList.push(new o({zlevel:C.zlevel,z:C.z+1,position:p.clone(k.position),_mapType:e,style:{x:k.textX+3+7*I,y:k.textY-10,r:3,color:X.getColor(C.name)},hoverable:!1}))}y=u.value}else{u={name:c,value:"-"},V="",g=[];for(var S in m)g.push(W[S]);y="-"}switch(this.ecTheme.map&&g.push(this.ecTheme.map),g.push(U.map),b=v&&!isNaN(y)?v.getColor(y):null,k.color=k.color||b||this.getItemStyleColor(this.deepQuery(g,"itemStyle.normal.color"),u.seriesIndex,-1,u)||this.deepQuery(g,"itemStyle.normal.areaStyle.color"),k.strokeColor=k.strokeColor||this.deepQuery(g,"itemStyle.normal.borderColor"),k.lineWidth=k.lineWidth||this.deepQuery(g,"itemStyle.normal.borderWidth"),x.color=this.getItemStyleColor(this.deepQuery(g,"itemStyle.emphasis.color"),u.seriesIndex,-1,u)||this.deepQuery(g,"itemStyle.emphasis.areaStyle.color")||k.color,x.strokeColor=this.deepQuery(g,"itemStyle.emphasis.borderColor")||k.strokeColor,x.lineWidth=this.deepQuery(g,"itemStyle.emphasis.borderWidth")||k.lineWidth,k.brushType=x.brushType=k.brushType||"both",k.lineJoin=x.lineJoin="round",k._name=x._name=c,f=this.deepQuery(g,"itemStyle.normal.label.textStyle"),L={zlevel:this.getZlevelBase(),z:this.getZBase()+1,position:p.clone(k.position),_mapType:e,_geo:this.pos2geo(e,[k.textX,k.textY]),style:{brushType:"fill",x:k.textX,y:k.textY,text:this.getLabelText(c,y,g,"normal"),_name:c,textAlign:"center",color:this.deepQuery(g,"itemStyle.normal.label.show")?this.deepQuery(g,"itemStyle.normal.label.textStyle.color"):"rgba(0,0,0,0)",textFont:this.getFont(f)}},L._style=p.clone(L.style),L.highlightStyle=p.clone(L.style),this.deepQuery(g,"itemStyle.emphasis.label.show")?(L.highlightStyle.text=this.getLabelText(c,y,g,"emphasis"),L.highlightStyle.color=this.deepQuery(g,"itemStyle.emphasis.label.textStyle.color")||L.style.color,f=this.deepQuery(g,"itemStyle.emphasis.label.textStyle")||f,L.highlightStyle.textFont=this.getFont(f)):L.highlightStyle.color="rgba(0,0,0,0)",_={zlevel:this.getZlevelBase(),z:this.getZBase(),position:p.clone(k.position),style:k,highlightStyle:x,_style:p.clone(k),_mapType:e},null!=k.scale&&(_.scale=p.clone(k.scale)),L=new n(L),_.style.shapeType){case"rectangle":_=new r(_);break;case"line":_=new s(_);break;case"circle":_=new o(_);break;case"polygon":_=new l(_);break;case"ellipse":_=new h(_);break;default:_=new a(_),_.buildPathArray&&(_.style.pathArray=_.buildPathArray(_.style.path))}(this._selectedMode[e]&&this._selected[c]&&u.selected!==!1||u.selected===!0)&&(L.style=L.highlightStyle,_.style=_.highlightStyle),L.clickable=_.clickable=this._clickable[e]&&(null==u.clickable||u.clickable),this._selectedMode[e]&&(this._selected[c]=null!=this._selected[c]?this._selected[c]:u.selected,this._mapTypeMap[c]=e,(null==u.selectable||u.selectable)&&(_.clickable=L.clickable=!0,_.onclick=L.onclick=this.shapeHandler.onclick)),this._hoverable[e]&&(null==u.hoverable||u.hoverable)?(L.hoverable=_.hoverable=!0,_.hoverConnect=L.id,L.hoverConnect=_.id):L.hoverable=_.hoverable=!1,d.pack(L,{name:V,tooltip:this.deepQuery(g,"tooltip")},0,u,0,c),this.shapeList.push(L),d.pack(_,{name:V,tooltip:this.deepQuery(g,"tooltip")},0,u,0,c),this.shapeList.push(_)}},_buildMark:function(e,t){this._seriesIndexToMapType=this._seriesIndexToMapType||{},this.markAttachStyle=this.markAttachStyle||{};var i=[this._mapDataMap[e].transform.left,this._mapDataMap[e].transform.top];"none"==e&&(i=[0,0]);for(var n in t)this._seriesIndexToMapType[n]=e,this.markAttachStyle[n]={position:i,_mapType:e},this.buildMark(n)},_buildHeatmap:function(e){for(var t=this.series,i=0,n=t.length;n>i;i++)if(t[i].heatmap){var a=t[i].heatmap.data;if(t[i].heatmap.needsTransform===!1){for(var o=[],r=0,s=a.length;s>r;++r)o.push([a[r][3],a[r][4],a[r][2]]);var l=[0,0]}else{var h=t[i].heatmap._geoData;if(void 0===h){t[i].heatmap._geoData=[];for(var r=0,s=a.length;s>r;++r)t[i].heatmap._geoData[r]=a[r];h=t[i].heatmap._geoData}for(var s=a.length,U=0;s>U;++U)a[U]=this.geo2pos(e,[h[U][0],h[U][1]]);var l=[this._mapDataMap[e].transform.left,this._mapDataMap[e].transform.top]}var d=new V(t[i].heatmap),p=d.getCanvas(a[0][3]?o:a,this.zr.getWidth(),this.zr.getHeight()),c=new m({zlevel:this.getZlevelBase(),z:this.getZBase()+1,position:l,scale:[1,1],hoverable:!1,style:{x:0,y:0,image:p,width:p.width,height:p.height}});c.type="heatmap",c._mapType=e,this.shapeList.push(c),this.zr.addShape(c)}},getMarkCoord:function(e,t){return t.geoCoord||b[t.name]?this.geo2pos(this._seriesIndexToMapType[e],t.geoCoord||b[t.name]):[0,0]},getMarkGeo:function(e){return e.geoCoord||b[e.name]},_nameChange:function(e,t){return this._nameMap[e][t]||t},getLabelText:function(e,t,i,n){var a=this.deepQuery(i,"itemStyle."+n+".label.formatter");return a?"function"==typeof a?a.call(this.myChart,e,t):"string"==typeof a?(a=a.replace("{a}","{a0}").replace("{b}","{b0}"),a=a.replace("{a0}",e).replace("{b0}",t)):void 0:e},_findMapTypeByPos:function(e,t){var i,n,a,o,r;for(var s in this._mapDataMap)if(i=this._mapDataMap[s].transform,i&&this._roamMap[s]&&this._activeMapType[s]&&(n=i.left,a=i.top,o=i.width,r=i.height,e>=n&&n+o>=e&&t>=a&&a+r>=t))return s},__onmousewheel:function(e){function t(e,t){for(var i=0;in;n++){var o=this.shapeList[n];if(o.__animating)return}var r,s,l=e.event,h=u.getX(l),m=u.getY(l),V=u.getDelta(l),d=e.mapTypeControl;d||(d={},s=this._findMapTypeByPos(h,m),s&&this._roamMap[s]&&"move"!=this._roamMap[s]&&(d[s]=!0));var p=!1;for(s in d)if(d[s]){p=!0;var c=this._mapDataMap[s].transform,y=c.left,g=c.top,b=c.width,f=c.height,k=this.pos2geo(s,[h-y,m-g]);if(V>0){if(r=1.2,null!=this._scaleLimitMap[s].max&&c.baseScale>=this._scaleLimitMap[s].max)continue}else if(r=1/1.2,null!=this._scaleLimitMap[s].min&&c.baseScale<=this._scaleLimitMap[s].min)continue;c.baseScale*=r,c.scale.x*=r,c.scale.y*=r,c.width=b*r,c.height=f*r,this._mapDataMap[s].hasRoam=!0,this._mapDataMap[s].transform=c,k=this.geo2pos(s,k),c.left-=k[0]-(h-y),c.top-=k[1]-(m-g),this._mapDataMap[s].transform=c,this.clearEffectShape(!0);for(var n=0,a=this.shapeList.length;a>n;n++){var o=this.shapeList[n];if(o._mapType==s){var x=o.type,_=o.style;switch(o.position[0]=c.left,o.position[1]=c.top,x){case"path":case"symbol":case"circle":case"rectangle":case"polygon":case"line":case"ellipse":case"heatmap":o.scale[0]*=r,o.scale[1]*=r;break;case"mark-line":i(_,r);break;case"polyline":t(_,r);break;case"shape-bundle":for(var L=0;L<_.shapeList.length;L++){var W=_.shapeList[L];"mark-line"==W.type?i(W.style,r):"polyline"==W.type&&t(W.style,r)}break;case"icon":case"image":k=this.geo2pos(s,o._geo),_.x=_._x=k[0]-_.width/2,_.y=_._y=k[1]-_.height/2;break;default:k=this.geo2pos(s,o._geo),_.x=k[0],_.y=k[1],"text"==x&&(o._style.x=o.highlightStyle.x=k[0],o._style.y=o.highlightStyle.y=k[1])}this.zr.modShape(o.id)}}}if(p){u.stop(l),this.zr.refreshNextFrame();var X=this;clearTimeout(this._refreshDelayTicket),this._refreshDelayTicket=setTimeout(function(){X&&X.shapeList&&X.animationEffect()},100),this.messageCenter.dispatch(U.EVENT.MAP_ROAM,e.event,{type:"scale"},this.myChart)}}},__onmousedown:function(e){if(!(this.shapeList.length<=0)){var t=e.target;if(!t||!t.draggable){var i=e.event,n=u.getX(i),a=u.getY(i),o=this._findMapTypeByPos(n,a);if(o&&this._roamMap[o]&&"scale"!=this._roamMap[o]){this._mousedown=!0,this._mx=n,this._my=a,this._curMapType=o,this.zr.on(c.EVENT.MOUSEUP,this._onmouseup);var r=this;setTimeout(function(){r.zr.on(c.EVENT.MOUSEMOVE,r._onmousemove)},100)}}}},__onmousemove:function(e){if(this._mousedown&&this._isAlive){var t=e.event,i=u.getX(t),n=u.getY(t),a=this._mapDataMap[this._curMapType].transform;a.hasRoam=!0,a.left-=this._mx-i,a.top-=this._my-n,this._mx=i,this._my=n,this._mapDataMap[this._curMapType].transform=a;for(var o=0,r=this.shapeList.length;r>o;o++)this.shapeList[o]._mapType==this._curMapType&&(this.shapeList[o].position[0]=a.left,this.shapeList[o].position[1]=a.top,this.zr.modShape(this.shapeList[o].id));this.messageCenter.dispatch(U.EVENT.MAP_ROAM,e.event,{type:"move"},this.myChart),this.clearEffectShape(!0),this.zr.refreshNextFrame(),this._justMove=!0,u.stop(t)}},__onmouseup:function(e){var t=e.event;this._mx=u.getX(t),this._my=u.getY(t),this._mousedown=!1;var i=this;setTimeout(function(){i._justMove&&i.animationEffect(),i._justMove=!1,i.zr.un(c.EVENT.MOUSEMOVE,i._onmousemove),i.zr.un(c.EVENT.MOUSEUP,i._onmouseup)},120)},__onroamcontroller:function(e){var t=e.event;t.zrenderX=this.zr.getWidth()/2,t.zrenderY=this.zr.getHeight()/2;var i=e.mapTypeControl,n=0,a=0,o=e.step;switch(e.roamType){case"scaleUp":return t.zrenderDelta=1,void this.__onmousewheel({event:t,mapTypeControl:i});case"scaleDown":return t.zrenderDelta=-1,void this.__onmousewheel({event:t,mapTypeControl:i});case"up":n=-o;break;case"down":n=o;break;case"left":a=-o;break;case"right":a=o}var r,s;for(s in i)this._mapDataMap[s]&&this._activeMapType[s]&&(r=this._mapDataMap[s].transform,r.hasRoam=!0,r.left-=a,r.top-=n,this._mapDataMap[s].transform=r);for(var l=0,h=this.shapeList.length;h>l;l++)s=this.shapeList[l]._mapType,i[s]&&this._activeMapType[s]&&(r=this._mapDataMap[s].transform,this.shapeList[l].position[0]=r.left,this.shapeList[l].position[1]=r.top,this.zr.modShape(this.shapeList[l].id));this.messageCenter.dispatch(U.EVENT.MAP_ROAM,e.event,{type:"move"},this.myChart),this.clearEffectShape(!0),this.zr.refreshNextFrame(),clearTimeout(this.dircetionTimer);var m=this;this.dircetionTimer=setTimeout(function(){m.animationEffect()},150)},__ondrhoverlink:function(e){for(var t,i,n=0,a=this.shapeList.length;a>n;n++)t=this.shapeList[n]._mapType,this._hoverLinkMap[t]&&this._activeMapType[t]&&(i=d.get(this.shapeList[n],"value"),null!=i&&i>=e.valueMin&&i<=e.valueMax&&this.zr.addHoverShape(this.shapeList[n]))},onclick:function(e){if(this.isClick&&e.target&&!this._justMove&&"icon"!=e.target.type){this.isClick=!1;var t=e.target,i=t.style._name,n=this.shapeList.length,a=t._mapType||"";if("single"==this._selectedMode[a])for(var o in this._selected)if(this._selected[o]&&this._mapTypeMap[o]==a){for(var r=0;n>r;r++)this.shapeList[r].style._name==o&&this.shapeList[r]._mapType==a&&(this.shapeList[r].style=this.shapeList[r]._style,this.zr.modShape(this.shapeList[r].id));o!=i&&(this._selected[o]=!1)}this._selected[i]=!this._selected[i];for(var r=0;n>r;r++)this.shapeList[r].style._name==i&&this.shapeList[r]._mapType==a&&(this.shapeList[r].style=this._selected[i]?this.shapeList[r].highlightStyle:this.shapeList[r]._style,this.zr.modShape(this.shapeList[r].id));this.messageCenter.dispatch(U.EVENT.MAP_SELECTED,e.event,{selected:this._selected,target:i},this.myChart),this.zr.refreshNextFrame();var s=this;setTimeout(function(){s.zr.trigger(c.EVENT.MOUSEMOVE,e.event)},100)}},refresh:function(e){e&&(this.option=e,this.series=e.series),this._mapDataRequireCounter>0?this.clear():this.backupShapeList(),this._buildShape(),this.zr.refreshHover()},ondataRange:function(e,t){this.component.dataRange&&(this.refresh(),t.needRefresh=!0)},pos2geo:function(e,t){return this._mapDataMap[e].transform?this._mapDataMap[e].projection.pos2geo(this._mapDataMap[e].transform,t):null},getGeoByPos:function(e,t){if(!this._mapDataMap[e].transform)return null;var i=[this._mapDataMap[e].transform.left,this._mapDataMap[e].transform.top];return t instanceof Array?(t[0]-=i[0],t[1]-=i[1]):(t.x-=i[0],t.y-=i[1]),this.pos2geo(e,t)},geo2pos:function(e,t){return this._mapDataMap[e].transform?this._mapDataMap[e].projection.geo2pos(this._mapDataMap[e].transform,t):null},getPosByGeo:function(e,t){if(!this._mapDataMap[e].transform)return null;var i=this.geo2pos(e,t);return i[0]+=this._mapDataMap[e].transform.left,i[1]+=this._mapDataMap[e].transform.top,i},getMapPosition:function(e){return this._mapDataMap[e].transform?[this._mapDataMap[e].transform.left,this._mapDataMap[e].transform.top]:null},onbeforDispose:function(){this._isAlive=!1,this.zr.un(c.EVENT.MOUSEWHEEL,this._onmousewheel),this.zr.un(c.EVENT.MOUSEDOWN,this._onmousedown),this.messageCenter.unbind(U.EVENT.ROAMCONTROLLER,this._onroamcontroller),this.messageCenter.unbind(U.EVENT.DATA_RANGE_HOVERLINK,this._ondrhoverlink)}},p.inherits(t,i),e("../chart").define("map",t),t}),i("zrender/shape/Path",["require","./Base","./util/PathProxy","../tool/util"],function(e){var t=e("./Base"),i=e("./util/PathProxy"),n=i.PathSegment,a=function(e){return Math.sqrt(e[0]*e[0]+e[1]*e[1])},o=function(e,t){return(e[0]*t[0]+e[1]*t[1])/(a(e)*a(t))},r=function(e,t){return(e[0]*t[1]0&&""===d[0]&&d.shift();for(var p=0;p0&&!isNaN(d[0]);){var c,u,y,g,b,f,k,x,_=null,L=[],W=h,X=m;switch(U){case"l":h+=d.shift(),m+=d.shift(),_="L",L.push(h,m);break;case"L":h=d.shift(),m=d.shift(),L.push(h,m);break;case"m":h+=d.shift(),m+=d.shift(),_="M",L.push(h,m),U="l";break;case"M":h=d.shift(),m=d.shift(),_="M",L.push(h,m),U="L";break;case"h":h+=d.shift(),_="L",L.push(h,m);break;case"H":h=d.shift(),_="L",L.push(h,m);break;case"v":m+=d.shift(),_="L",L.push(h,m);break;case"V":m=d.shift(),_="L",L.push(h,m);break;case"C":L.push(d.shift(),d.shift(),d.shift(),d.shift()),h=d.shift(),m=d.shift(),L.push(h,m);break;case"c":L.push(h+d.shift(),m+d.shift(),h+d.shift(),m+d.shift()),h+=d.shift(),m+=d.shift(),_="C",L.push(h,m);break;case"S":c=h,u=m,y=l[l.length-1],"C"===y.command&&(c=h+(h-y.points[2]),u=m+(m-y.points[3])),L.push(c,u,d.shift(),d.shift()),h=d.shift(),m=d.shift(),_="C",L.push(h,m);break;case"s":c=h,u=m,y=l[l.length-1],"C"===y.command&&(c=h+(h-y.points[2]),u=m+(m-y.points[3])),L.push(c,u,h+d.shift(),m+d.shift()),h+=d.shift(),m+=d.shift(),_="C",L.push(h,m);break;case"Q":L.push(d.shift(),d.shift()),h=d.shift(),m=d.shift(),L.push(h,m);break;case"q":L.push(h+d.shift(),m+d.shift()),h+=d.shift(),m+=d.shift(),_="Q",L.push(h,m);break;case"T":c=h,u=m,y=l[l.length-1],"Q"===y.command&&(c=h+(h-y.points[0]),u=m+(m-y.points[1])),h=d.shift(),m=d.shift(),_="Q",L.push(c,u,h,m);break;case"t":c=h,u=m,y=l[l.length-1],"Q"===y.command&&(c=h+(h-y.points[0]),u=m+(m-y.points[1])),h+=d.shift(),m+=d.shift(),_="Q",L.push(c,u,h,m);break;case"A":g=d.shift(),b=d.shift(),f=d.shift(),k=d.shift(),x=d.shift(),W=h,X=m,h=d.shift(),m=d.shift(),_="A",L=this._convertPoint(W,X,h,m,k,x,g,b,f);break;case"a":g=d.shift(),b=d.shift(),f=d.shift(),k=d.shift(),x=d.shift(),W=h,X=m,h+=d.shift(),m+=d.shift(),_="A",L=this._convertPoint(W,X,h,m,k,x,g,b,f)}for(var v=0,w=L.length;w>v;v+=2)L[v]+=t,L[v+1]+=i;l.push(new n(_||U,L))}("z"===U||"Z"===U)&&l.push(new n("z",[]))}return l},_convertPoint:function(e,t,i,n,a,s,l,h,m){var V=m*(Math.PI/180),U=Math.cos(V)*(e-i)/2+Math.sin(V)*(t-n)/2,d=-1*Math.sin(V)*(e-i)/2+Math.cos(V)*(t-n)/2,p=U*U/(l*l)+d*d/(h*h);p>1&&(l*=Math.sqrt(p),h*=Math.sqrt(p));var c=Math.sqrt((l*l*h*h-l*l*d*d-h*h*U*U)/(l*l*d*d+h*h*U*U));a===s&&(c*=-1),isNaN(c)&&(c=0);var u=c*l*d/h,y=c*-h*U/l,g=(e+i)/2+Math.cos(V)*u-Math.sin(V)*y,b=(t+n)/2+Math.sin(V)*u+Math.cos(V)*y,f=r([1,0],[(U-u)/l,(d-y)/h]),k=[(U-u)/l,(d-y)/h],x=[(-1*U-u)/l,(-1*d-y)/h],_=r(k,x);return o(k,x)<=-1&&(_=Math.PI),o(k,x)>=1&&(_=0),0===s&&_>0&&(_-=2*Math.PI),1===s&&0>_&&(_+=2*Math.PI),[g,b,l,h,f,_,V,s]},buildPath:function(e,t){var i=t.path,n=t.x||0,a=t.y||0;t.pathArray=t.pathArray||this.buildPathArray(i,n,a);for(var o=t.pathArray,r=t.pointList=[],s=[],l=0,h=o.length;h>l;l++){"M"==o[l].command.toUpperCase()&&(s.length>0&&r.push(s),s=[]);for(var m=o[l].points,V=0,U=m.length;U>V;V+=2)s.push([m[V],m[V+1]])}s.length>0&&r.push(s);for(var l=0,h=o.length;h>l;l++){var d=o[l].command,m=o[l].points;switch(d){case"L":e.lineTo(m[0],m[1]);break;case"M":e.moveTo(m[0],m[1]);break;case"C":e.bezierCurveTo(m[0],m[1],m[2],m[3],m[4],m[5]);break;case"Q":e.quadraticCurveTo(m[0],m[1],m[2],m[3]);break;case"A":var p=m[0],c=m[1],u=m[2],y=m[3],g=m[4],b=m[5],f=m[6],k=m[7],x=u>y?u:y,_=u>y?1:u/y,L=u>y?y/u:1;e.translate(p,c),e.rotate(f),e.scale(_,L),e.arc(0,0,x,g,g+b,1-k),e.scale(1/_,1/L),e.rotate(-f),e.translate(-p,-c);break;case"z":e.closePath()}}},getRect:function(e){if(e.__rect)return e.__rect;var t;t="stroke"==e.brushType||"fill"==e.brushType?e.lineWidth||1:0;for(var i=Number.MAX_VALUE,n=Number.MIN_VALUE,a=Number.MAX_VALUE,o=Number.MIN_VALUE,r=e.x||0,s=e.y||0,l=e.pathArray||this.buildPathArray(e.path),h=0;hn&&(n=m[V])):(m[V]+so&&(o=m[V]));var U;return U=i===Number.MAX_VALUE||n===Number.MIN_VALUE||a===Number.MAX_VALUE||o===Number.MIN_VALUE?{x:0,y:0,width:0,height:0}:{x:Math.round(i-t/2),y:Math.round(a-t/2),width:n-i+t,height:o-a+t},e.__rect=U,U}},e("../tool/util").inherits(s,t),s}),i("zrender/shape/Ellipse",["require","./Base","../tool/util"],function(e){var t=e("./Base"),i=function(e){t.call(this,e)};return i.prototype={type:"ellipse",buildPath:function(e,t){var i=.5522848,n=t.x,a=t.y,o=t.a,r=t.b,s=o*i,l=r*i;e.moveTo(n-o,a),e.bezierCurveTo(n-o,a-l,n-s,a-r,n,a-r),e.bezierCurveTo(n+s,a-r,n+o,a-l,n+o,a),e.bezierCurveTo(n+o,a+l,n+s,a+r,n,a+r),e.bezierCurveTo(n-s,a+r,n-o,a+l,n-o,a),e.closePath()},getRect:function(e){if(e.__rect)return e.__rect;var t;return t="stroke"==e.brushType||"fill"==e.brushType?e.lineWidth||1:0,e.__rect={x:Math.round(e.x-e.a-t/2), -y:Math.round(e.y-e.b-t/2),width:2*e.a+t,height:2*e.b+t},e.__rect}},e("../tool/util").inherits(i,t),i}),i("echarts/component/roamController",["require","./base","zrender/shape/Rectangle","zrender/shape/Sector","zrender/shape/Circle","../config","zrender/tool/util","zrender/tool/color","zrender/tool/event","../component"],function(e){function t(e,t,n,a,o){if(this.rcOption={},a.roamController&&a.roamController.show){if(!a.roamController.mapTypeControl)return void console.error("option.roamController.mapTypeControl has not been defined.");i.call(this,e,t,n,a,o),this.rcOption=a.roamController;var r=this;this._drictionMouseDown=function(e){return r.__drictionMouseDown(e)},this._drictionMouseUp=function(e){return r.__drictionMouseUp(e)},this._drictionMouseMove=function(e){return r.__drictionMouseMove(e)},this._drictionMouseOut=function(e){return r.__drictionMouseOut(e)},this._scaleHandler=function(e){return r.__scaleHandler(e)},this.refresh(a)}}var i=e("./base"),n=e("zrender/shape/Rectangle"),a=e("zrender/shape/Sector"),o=e("zrender/shape/Circle"),r=e("../config");r.roamController={zlevel:0,z:4,show:!0,x:"left",y:"top",width:80,height:120,backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,padding:5,handleColor:"#6495ed",fillerColor:"#fff",step:15,mapTypeControl:null};var s=e("zrender/tool/util"),l=e("zrender/tool/color"),h=e("zrender/tool/event");return t.prototype={type:r.COMPONENT_TYPE_ROAMCONTROLLER,_buildShape:function(){if(this.rcOption.show){this._itemGroupLocation=this._getItemGroupLocation(),this._buildBackground(),this._buildItem();for(var e=0,t=this.shapeList.length;t>e;e++)this.zr.addShape(this.shapeList[e])}},_buildItem:function(){this.shapeList.push(this._getDirectionShape("up")),this.shapeList.push(this._getDirectionShape("down")),this.shapeList.push(this._getDirectionShape("left")),this.shapeList.push(this._getDirectionShape("right")),this.shapeList.push(this._getScaleShape("scaleUp")),this.shapeList.push(this._getScaleShape("scaleDown"))},_getDirectionShape:function(e){var t=this._itemGroupLocation.r,i=this._itemGroupLocation.x+t,n=this._itemGroupLocation.y+t,o={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:i,y:n,r:t,startAngle:-45,endAngle:45,color:this.rcOption.handleColor,text:">",textX:i+t/2+4,textY:n-.5,textAlign:"center",textBaseline:"middle",textPosition:"specific",textColor:this.rcOption.fillerColor,textFont:Math.floor(t/2)+"px arial"},highlightStyle:{color:l.lift(this.rcOption.handleColor,-.2),brushType:"fill"},clickable:!0};switch(e){case"up":o.rotation=[Math.PI/2,i,n];break;case"left":o.rotation=[Math.PI,i,n];break;case"down":o.rotation=[-Math.PI/2,i,n]}return o=new a(o),o._roamType=e,o.onmousedown=this._drictionMouseDown,o.onmouseup=this._drictionMouseUp,o.onmousemove=this._drictionMouseMove,o.onmouseout=this._drictionMouseOut,o},_getScaleShape:function(e){var t=this._itemGroupLocation.width,i=this._itemGroupLocation.height-t;i=0>i?20:i;var n=Math.min(t/2-5,i)/2,a=this._itemGroupLocation.x+("scaleDown"===e?t-n:n),r=this._itemGroupLocation.y+this._itemGroupLocation.height-n,s={zlevel:this.getZlevelBase(),z:this.getZBase(),style:{x:a,y:r,r:n,color:this.rcOption.handleColor,text:"scaleDown"===e?"-":"+",textX:a,textY:r-2,textAlign:"center",textBaseline:"middle",textPosition:"specific",textColor:this.rcOption.fillerColor,textFont:Math.floor(n)+"px verdana"},highlightStyle:{color:l.lift(this.rcOption.handleColor,-.2),brushType:"fill"},clickable:!0};return s=new o(s),s._roamType=e,s.onmousedown=this._scaleHandler,s},_buildBackground:function(){var e=this.reformCssArray(this.rcOption.padding);this.shapeList.push(new n({zlevel:this.getZlevelBase(),z:this.getZBase(),hoverable:!1,style:{x:this._itemGroupLocation.x-e[3],y:this._itemGroupLocation.y-e[0],width:this._itemGroupLocation.width+e[3]+e[1],height:this._itemGroupLocation.height+e[0]+e[2],brushType:0===this.rcOption.borderWidth?"fill":"both",color:this.rcOption.backgroundColor,strokeColor:this.rcOption.borderColor,lineWidth:this.rcOption.borderWidth}}))},_getItemGroupLocation:function(){var e,t=this.reformCssArray(this.rcOption.padding),i=this.rcOption.width,n=this.rcOption.height,a=this.zr.getWidth(),o=this.zr.getHeight();switch(this.rcOption.x){case"center":e=Math.floor((a-i)/2);break;case"left":e=t[3]+this.rcOption.borderWidth;break;case"right":e=a-i-t[1]-t[3]-2*this.rcOption.borderWidth;break;default:e=this.parsePercent(this.rcOption.x,a)}var r;switch(this.rcOption.y){case"top":r=t[0]+this.rcOption.borderWidth;break;case"bottom":r=o-n-t[0]-t[2]-2*this.rcOption.borderWidth;break;case"center":r=Math.floor((o-n)/2);break;default:r=this.parsePercent(this.rcOption.y,o)}return{x:e,y:r,r:i/2,width:i,height:n}},__drictionMouseDown:function(e){this.mousedown=!0,this._drictionHandlerOn(e)},__drictionMouseUp:function(e){this.mousedown=!1,this._drictionHandlerOff(e)},__drictionMouseMove:function(e){this.mousedown&&this._drictionHandlerOn(e)},__drictionMouseOut:function(e){this._drictionHandlerOff(e)},_drictionHandlerOn:function(e){this._dispatchEvent(e.event,e.target._roamType),clearInterval(this.dircetionTimer);var t=this;this.dircetionTimer=setInterval(function(){t._dispatchEvent(e.event,e.target._roamType)},100),h.stop(e.event)},_drictionHandlerOff:function(){clearInterval(this.dircetionTimer)},__scaleHandler:function(e){this._dispatchEvent(e.event,e.target._roamType),h.stop(e.event)},_dispatchEvent:function(e,t){this.messageCenter.dispatch(r.EVENT.ROAMCONTROLLER,e,{roamType:t,mapTypeControl:this.rcOption.mapTypeControl,step:this.rcOption.step},this.myChart)},refresh:function(e){e&&(this.option=e||this.option,this.option.roamController=this.reformOption(this.option.roamController),this.rcOption=this.option.roamController),this.clear(),this._buildShape()}},s.inherits(t,i),e("../component").define("roamController",t),t}),i("echarts/layer/heatmap",["require"],function(){function e(e){if(this.option=e,e)for(var i in t)this.option[i]=void 0!==e[i]?e[i]:t[i];else this.option=t}var t={blurSize:30,gradientColors:["blue","cyan","lime","yellow","red"],minAlpha:.05,valueScale:1,opacity:1},i=20,n=256;return e.prototype={getCanvas:function(e,t,a){var o=this._getBrush(),r=this._getGradient(),s=i+this.option.blurSize,l=document.createElement("canvas");l.width=t,l.height=a;for(var h=l.getContext("2d"),m=e.length,V=0;m>V;++V){var U=e[V],d=U[0],p=U[1],c=U[2],u=Math.min(1,Math.max(c*this.option.valueScale||this.option.minAlpha,this.option.minAlpha));h.globalAlpha=u,h.drawImage(o,d-s,p-s)}for(var y=h.getImageData(0,0,l.width,l.height),g=y.data,m=g.length/4;m--;){var b=4*m+3,u=g[b]/256,f=Math.floor(u*(n-1));g[b-3]=r[4*f],g[b-2]=r[4*f+1],g[b-1]=r[4*f+2],g[b]*=this.option.opacity}return h.putImageData(y,0,0),l},_getBrush:function(){if(!this._brushCanvas){this._brushCanvas=document.createElement("canvas");var e=i+this.option.blurSize,t=2*e;this._brushCanvas.width=t,this._brushCanvas.height=t;var n=this._brushCanvas.getContext("2d");n.shadowOffsetX=t,n.shadowBlur=this.option.blurSize,n.shadowColor="black",n.beginPath(),n.arc(-e,e,i,0,2*Math.PI,!0),n.closePath(),n.fill()}return this._brushCanvas},_getGradient:function(){if(!this._gradientPixels){var e=n,t=document.createElement("canvas");t.width=1,t.height=e;for(var i=t.getContext("2d"),a=i.createLinearGradient(0,0,0,e),o=this.option.gradientColors.length,r=0;o>r;++r)"string"==typeof this.option.gradientColors[r]?a.addColorStop((r+1)/o,this.option.gradientColors[r]):a.addColorStop(this.option.gradientColors[r].offset,this.option.gradientColors[r].color);i.fillStyle=a,i.fillRect(0,0,1,e),this._gradientPixels=i.getImageData(0,0,1,e).data}return this._gradientPixels}},e}),i("echarts/util/mapData/params",["require"],function(e){function t(e){if(!e.UTF8Encoding)return e;for(var t=e.features,n=0;n>1^-(1&r),s=s>>1^-(1&s),r+=n,s+=a,n=r,a=s,i.push([r/1024,s/1024])}return i}var n={none:{getGeoJson:function(e){e({type:"FeatureCollection",features:[{type:"Feature",geometry:{coordinates:[],encodeOffsets:[],type:"Polygon"},properties:{}}]})}},world:{getGeoJson:function(i){e(["./geoJson/world_geo"],function(e){i(t(e))})}},china:{getGeoJson:function(i){e(["./geoJson/china_geo"],function(e){i(t(e))})}},"南海诸岛":{textCoord:[126,25],getPath:function(e,t){for(var i=[[[0,3.5],[7,11.2],[15,11.9],[30,7],[42,.7],[52,.7],[56,7.7],[59,.7],[64,.7],[64,0],[5,0],[0,3.5]],[[13,16.1],[19,14.7],[16,21.7],[11,23.1],[13,16.1]],[[12,32.2],[14,38.5],[15,38.5],[13,32.2],[12,32.2]],[[16,47.6],[12,53.2],[13,53.2],[18,47.6],[16,47.6]],[[6,64.4],[8,70],[9,70],[8,64.4],[6,64.4]],[[23,82.6],[29,79.8],[30,79.8],[25,82.6],[23,82.6]],[[37,70.7],[43,62.3],[44,62.3],[39,70.7],[37,70.7]],[[48,51.1],[51,45.5],[53,45.5],[50,51.1],[48,51.1]],[[51,35],[51,28.7],[53,28.7],[53,35],[51,35]],[[52,22.4],[55,17.5],[56,17.5],[53,22.4],[52,22.4]],[[58,12.6],[62,7],[63,7],[60,12.6],[58,12.6]],[[0,3.5],[0,93.1],[64,93.1],[64,0],[63,0],[63,92.4],[1,92.4],[1,3.5],[0,3.5]]],n="",a=e[0],o=e[1],r=0,s=i.length;s>r;r++){n+="M "+((i[r][0][0]*t+a).toFixed(2)-0)+" "+((i[r][0][1]*t+o).toFixed(2)-0)+" ";for(var l=1,h=i[r].length;h>l;l++)n+="L "+((i[r][l][0]*t+a).toFixed(2)-0)+" "+((i[r][l][1]*t+o).toFixed(2)-0)+" "}return n+" Z"}},"新疆":{getGeoJson:function(i){e(["./geoJson/xin_jiang_geo"],function(e){i(t(e))})}},"西藏":{getGeoJson:function(i){e(["./geoJson/xi_zang_geo"],function(e){i(t(e))})}},"内蒙古":{getGeoJson:function(i){e(["./geoJson/nei_meng_gu_geo"],function(e){i(t(e))})}},"青海":{getGeoJson:function(i){e(["./geoJson/qing_hai_geo"],function(e){i(t(e))})}},"四川":{getGeoJson:function(i){e(["./geoJson/si_chuan_geo"],function(e){i(t(e))})}},"黑龙江":{getGeoJson:function(i){e(["./geoJson/hei_long_jiang_geo"],function(e){i(t(e))})}},"甘肃":{getGeoJson:function(i){e(["./geoJson/gan_su_geo"],function(e){i(t(e))})}},"云南":{getGeoJson:function(i){e(["./geoJson/yun_nan_geo"],function(e){i(t(e))})}},"广西":{getGeoJson:function(i){e(["./geoJson/guang_xi_geo"],function(e){i(t(e))})}},"湖南":{getGeoJson:function(i){e(["./geoJson/hu_nan_geo"],function(e){i(t(e))})}},"陕西":{getGeoJson:function(i){e(["./geoJson/shan_xi_1_geo"],function(e){i(t(e))})}},"广东":{getGeoJson:function(i){e(["./geoJson/guang_dong_geo"],function(e){i(t(e))})}},"吉林":{getGeoJson:function(i){e(["./geoJson/ji_lin_geo"],function(e){i(t(e))})}},"河北":{getGeoJson:function(i){e(["./geoJson/he_bei_geo"],function(e){i(t(e))})}},"湖北":{getGeoJson:function(i){e(["./geoJson/hu_bei_geo"],function(e){i(t(e))})}},"贵州":{getGeoJson:function(i){e(["./geoJson/gui_zhou_geo"],function(e){i(t(e))})}},"山东":{getGeoJson:function(i){e(["./geoJson/shan_dong_geo"],function(e){i(t(e))})}},"江西":{getGeoJson:function(i){e(["./geoJson/jiang_xi_geo"],function(e){i(t(e))})}},"河南":{getGeoJson:function(i){e(["./geoJson/he_nan_geo"],function(e){i(t(e))})}},"辽宁":{getGeoJson:function(i){e(["./geoJson/liao_ning_geo"],function(e){i(t(e))})}},"山西":{getGeoJson:function(i){e(["./geoJson/shan_xi_2_geo"],function(e){i(t(e))})}},"安徽":{getGeoJson:function(i){e(["./geoJson/an_hui_geo"],function(e){i(t(e))})}},"福建":{getGeoJson:function(i){e(["./geoJson/fu_jian_geo"],function(e){i(t(e))})}},"浙江":{getGeoJson:function(i){e(["./geoJson/zhe_jiang_geo"],function(e){i(t(e))})}},"江苏":{getGeoJson:function(i){e(["./geoJson/jiang_su_geo"],function(e){i(t(e))})}},"重庆":{getGeoJson:function(i){e(["./geoJson/chong_qing_geo"],function(e){i(t(e))})}},"宁夏":{getGeoJson:function(i){e(["./geoJson/ning_xia_geo"],function(e){i(t(e))})}},"海南":{getGeoJson:function(i){e(["./geoJson/hai_nan_geo"],function(e){i(t(e))})}},"台湾":{getGeoJson:function(i){e(["./geoJson/tai_wan_geo"],function(e){i(t(e))})}},"北京":{getGeoJson:function(i){e(["./geoJson/bei_jing_geo"],function(e){i(t(e))})}},"天津":{getGeoJson:function(i){e(["./geoJson/tian_jin_geo"],function(e){i(t(e))})}},"上海":{getGeoJson:function(i){e(["./geoJson/shang_hai_geo"],function(e){i(t(e))})}},"香港":{getGeoJson:function(i){e(["./geoJson/xiang_gang_geo"],function(e){i(t(e))})}},"澳门":{getGeoJson:function(i){e(["./geoJson/ao_men_geo"],function(e){i(t(e))})}}};return{decode:t,params:n}}),i("echarts/util/mapData/textFixed",[],function(){return{"广东":[0,-10],"香港":[10,10],"澳门":[-10,18],"黑龙江":[0,20],"天津":[5,5],"深圳市":[-35,0],"红河哈尼族彝族自治州":[0,20],"楚雄彝族自治州":[-5,15],"石河子市":[-5,5],"五家渠市":[0,-10],"昌吉回族自治州":[10,10],"昌江黎族自治县":[0,20],"陵水黎族自治县":[0,20],"东方市":[0,20],"渭南市":[0,20]}}),i("echarts/util/mapData/geoCoord",[],function(){return{Russia:[100,60],"United States of America":[-99,38]}}),i("echarts/util/projection/svg",["require","zrender/shape/Path"],function(e){function t(e){return parseFloat(e||0)}function i(e){for(var i=e.firstChild;"svg"!=i.nodeName.toLowerCase()||1!=i.nodeType;)i=i.nextSibling;var n=t(i.getAttribute("x")),a=t(i.getAttribute("y")),o=t(i.getAttribute("width")),r=t(i.getAttribute("height"));return{left:n,top:a,width:o,height:r}}function n(e,t){function i(e){var t=e.tagName;if(m[t]){var o=m[t](e,n);o&&(o.scale=n,o.properties={name:e.getAttribute("name")||""},o.id=e.id,s(o,e),a.push(o))}for(var r=e.childNodes,l=0,h=r.length;h>l;l++)i(r[l])}var n=[t.scale.x,t.scale.y],a=[];return i(e),a}function a(e,t){var i=t instanceof Array?[1*t[0],1*t[1]]:[1*t.x,1*t.y];return[i[0]/e.scale.x,i[1]/e.scale.y]}function o(e,t){var i=t instanceof Array?[1*t[0],1*t[1]]:[1*t.x,1*t.y];return[i[0]*e.scale.x,i[1]*e.scale.y]}function r(e){return e.replace(/^\s\s*/,"").replace(/\s\s*$/,"")}function s(e,t){var i=t.getAttribute("fill"),n=t.getAttribute("stroke"),a=t.getAttribute("stroke-width"),o=t.getAttribute("opacity");i&&"none"!=i?(e.color=i,n?(e.brushType="both",e.strokeColor=n):e.brushType="fill"):n&&"none"!=n&&(e.strokeColor=n,e.brushType="stroke"),a&&"none"!=a&&(e.lineWidth=parseFloat(a)),o&&"none"!=o&&(e.opacity=parseFloat(o))}function l(e){for(var t=r(e).replace(/,/g," ").split(/\s+/),i=[],n=0;no;o++)if(n=a[o],!n.properties.name||!t[n.properties.name])switch(n.type){case"Feature":r[n.geometry.type](n.geometry.coordinates);break;case"GeometryCollection":i=n.geometries;for(var l=0,h=i.length;h>l;l++)r[i[l].type](i[l].coordinates)}return e.srcSize={left:1*r.xmin.toFixed(4),top:1*r.ymin.toFixed(4),width:1*(r.xmax-r.xmin).toFixed(4),height:1*(r.ymax-r.ymin).toFixed(4)},e}function i(e,i,n){function a(e,t){c=e.type,u=e.coordinates,o._bbox={xmin:360,xmax:-360,ymin:180,ymax:-180},y=o[c](u),m.push({path:y,cp:o.makePoint(t.properties.cp?t.properties.cp:[(o._bbox.xmin+o._bbox.xmax)/2,(o._bbox.ymin+o._bbox.ymax)/2]),properties:t.properties,id:t.id})}n=n||{},o.scale=null,o.offset=null,e.srcSize||t(e,n),i.offset={x:e.srcSize.left,y:e.srcSize.top,left:i.OffsetLeft||0,top:i.OffsetTop||0},o.scale=i.scale,o.offset=i.offset;for(var r,s,l,h=e.features,m=[],V=0,U=h.length;U>V;V++)if(l=h[V],!l.properties.name||!n[l.properties.name])if("Feature"==l.type)a(l.geometry,l);else if("GeometryCollection"==l.type){r=l.geometries;for(var d=0,p=r.length;p>d;d++)s=r[d],a(s,s)}var c,u,y;return m}function n(e,t){var i,n;return t instanceof Array?(i=1*t[0],n=1*t[1]):(i=1*t.x,n=1*t.y),i=i/e.scale.x+e.offset.x-168.5,i=i>180?i-360:i,n=90-(n/e.scale.y+e.offset.y),[i,n]}function a(e,t){return o.offset=e.offset,o.scale=e.scale,o.makePoint(t instanceof Array?[1*t[0],1*t[1]]:[1*t.x,1*t.y])}var o={formatPoint:function(e){return[(e[0]<-168.5&&e[1]>63.8?e[0]+360:e[0])+168.5,90-e[1]]},makePoint:function(e){var t=this,i=t.formatPoint(e);t._bbox.xmin>e[0]&&(t._bbox.xmin=e[0]),t._bbox.xmaxe[1]&&(t._bbox.ymin=e[1]),t._bbox.ymaxn;n++)t=o.makePoint(e[n]),i=0===n?"M"+t.join(","):i+"L"+t.join(",");return i},Polygon:function(e){for(var t="",i=0,n=e.length;n>i;i++)t=t+o.LineString(e[i])+"z";return t},MultiPoint:function(e){for(var t=[],i=0,n=e.length;n>i;i++)t.push(o.Point(e[i]));return t},MultiLineString:function(e){for(var t="",i=0,n=e.length;n>i;i++)t+=o.LineString(e[i]);return t},MultiPolygon:function(e){for(var t="",i=0,n=e.length;n>i;i++)t+=o.Polygon(e[i]);return t}},r={formatPoint:o.formatPoint,makePoint:function(e){var t=this,i=t.formatPoint(e),n=i[0],a=i[1];t.xmin>n&&(t.xmin=n),t.xmaxa&&(t.ymin=a),t.ymaxt;t++)this.makePoint(e[t])},Polygon:function(e){for(var t=0,i=e.length;i>t;t++)this.LineString(e[t])},MultiPoint:function(e){for(var t=0,i=e.length;i>t;t++)this.Point(e[t])},MultiLineString:function(e){for(var t=0,i=e.length;i>t;t++)this.LineString(e[t])},MultiPolygon:function(e){for(var t=0,i=e.length;i>t;t++)this.Polygon(e[t])}};return{getBbox:e,geoJson2Path:i,pos2geo:n,geo2pos:a}}),i("echarts/util/mapData/geoJson/an_hui_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"3415",properties:{name:"六安市",cp:[116.3123,31.8329],childNum:6},geometry:{type:"Polygon",coordinates:["@@„„nJ‚UXUVƒ°U„ÑnU@mlLVaVln@@bn@VU@xlb@lšLnKlšƒVI„JšUVxnI@lVL@b„Ž°VX@˜b„x„nVVUnVVnU‚›@kX@VwV@„al¥UUnUWa@ƒ@wĸU„LU¥lKUa@aUI@alLVaUƒ¯anƒWkUKm@XV@VaXlW@aU_UWVUƒI¯@ma¯W¯™™I@UU@WWU@U@@UU@VkV@@WUUm@UaU@„lK@IUK„L@KWmXUWaXI@ƒ@a@a@U@U@KV¥lw„k°b²JVIVKlV@UX„la„Ul`œUVLVVVUšJ„U@Lnm@_VK@KUIW@™J@Xk@WW@U—ƒmm™XmWk@kK@aUUƒVmmkUwUmWL™@WmU@™UJmUULkKWakLWVkIƒlƒwULƒW@X°lUJ@°ULƒWV—wmJ@bmb¯Vkm@@WkWm¯wƒL@lkXƒWmXym¯UImJUbkV™@Vn¯„@V@lUbƒ@mk@maUxmlUbULWn@J—LmKUkWKkwUKƒbm„X„WxkVUKmLkVV@JUUWL@xkJUUƒV@X@VVlUbVX@xk¤šx‚¼œxWxn„‚nn@Þ¼„JVb°aVn„@šmlnXU„JlbVlkz@‚lUŽlXJmxVxXnWxXÈWlUŽ@šUxU@VX@xUL@šUÆmLnV@lWXk@@JlbXblnlJ"],encodeOffsets:[[118710,33351]]}},{type:"Feature",id:"3408",properties:{name:"安庆市",cp:[116.7517,30.5255],childNum:9},geometry:{type:"Polygon",coordinates:["@@n°‚znW„XlW@k„K°xXn‚l@Xn@l‚°Una@anI˜xXU„ŽVK@¯VIkW¯X@‚„VK„x„klJXUlKXblLVKnVVIšŽV@Xn‚@šŽXKVnVxlŽnn„UlmV@²óUkV™lW„b„lƒšƒn@VVVIn@lw@WVIXblV„@Èx‚aUaVIVVnKVLšK„ƒln@b²K@»U£ƒÑķƒġÝÅb™K™a@Im@ۍ„@kWÓkkmKÅnóJƒUÅ£›W@w„ĕ@wĉţ¯¯ƒUkK±l¯Uƒ¥UÑkÝUķ»Ý¥¯™JƒIUŽVbUl¯ÈV¼VJU¼Vb@bkLUl@„VJ@bUXǚ@lkVmXmKkLVxš‚Ž„VƒL@VkVVVlzW˜kbmLUUUbVbUV™šlÒnJlUnLllUL@bU„Vx„l‚LXVƦÈVU¦WJ"],encodeOffsets:[[118834,31759]]}},{type:"Feature",id:"3411",properties:{name:"滁州市",cp:[118.1909,32.536],childNum:7},geometry:{type:"Polygon",coordinates:["@@š„@`nnl@„xšK@X°KXV˜IXVlbXVWnX‚lL@šÈ»‚LVan@VJ„êVVn@‚X@laÞbVaƒyn@„_‚xnWVXnWl@VnUVkI@l‚nXKVLVV@V@kW@LlVô„@J@bVnnKnkVa@»lç@ƒnwšKma™UUUVњ@n™mWXalI@alVn@VwUaVU„@„nlaôJnU„VVXlJšaXXVK@UšV@VWx@nXVWšXVšUlLUbV‚ULVVnUVbUbVbš@@a„KÆnnKVK@U@UU@@a„@Vƒ°¯ÈJVIlķ@aa˜UaVKU_@mkxUI@aƒUlyU@@™wkKWmUbUnUVWbkJW_J@bƒn@Vm@@KULk@V@@bVbÅm@LW@UVVbkK@UkKWL@VULUKWIUJUbkK@_WVXU›Jka@XƒVa@kšy@aVIUUW@@m„UlLœKWÑUKVan@UkVmmIXKƒaVaUwVU@UmykU¯@±UUL@WUIVUU@KkIWaƒaU@kUUaǃUó»mKƒk¯@y@kWK@bkI¯`mn™l¯XWlkVUzUJlbUbVJl@nnm„@VULV`XnWƗbmUUn™JmUknƒJ¯km@ƒyk@kU›xL@VUbmnn¤lX@`™z@JmaULUVl@Xn@xllkXWa—aW@UVmUbƒ@mVXšWxXbWbUŽƒÒnVVnVVUL"],encodeOffsets:[[120004,33520]]}},{type:"Feature",id:"3418",properties:{name:"宣城市",cp:[118.8062,30.6244],childNum:7},geometry:{type:"Polygon",coordinates:["@@Vb@„XL˜JXxlIXxlVlV@I²¤šnlUnVšU@VULWVUJ@Lnb@lV@UnV@@VVVlLnbnJ‚UVkUUVWn@@anUVnVJVIV‚@@nUJVbUb‚„@VUbVK@bn@VbnIlxkllXVlXKWUXUlL°¤UVVb@bš„UlkXW‚ƒxXz@‚„Ila„UlƒnUlJVInVÆJ„U„LVUnV„K°@VnlVnxV@XLlK@wVL@KnUlJXU˜bnKVLX„lUw@VWlLXKm@@a„@VLnmlIVVnKn@škVašVlwk@@a@k@ƒVIUa™@maUa@wna@kmWƒ™UUmVUIVǗ@aƒKm™aƒ™kU™J@InmUUaVa„k‚lX@Vk@m@VU@wnK@alKVUkUkKƒbmUkmƒ@U£WVk@@UÝbbƒaÇx@b@WVUa¯ƒ@wVwUUV@VwnK@KWaŁ@KšIUyUI@WmXó™UbWaKm™@km@IUyƒIUaWKƒx@zUKUL@llVUnkLVVkJWX@VUKUVƒIkVWakb@VWb@n@JkXUlmL@xkL@`VxšLUÈUJ@Vm@@bmIUlUL@VUVVbknm@mKUw™KVÈ@J@LV±kkJUIƒl"],encodeOffsets:[[120803,31247]]}},{type:"Feature",id:"3412",properties:{name:"阜阳市",cp:[115.7629,32.9919],childNum:6},geometry:{type:"Polygon",coordinates:["@@V™nƒš@ša„k°aš±@‚¥@UUI@aUmlwUUx›b@¥XU@mmI@a@Kn@@_W@@W„I@mšUVVXUl@XaV@‚K@I@a„LX@aVI°K@KVL„UUw‚yXkšK@kšKÆbXnlK@k@a„JlU@w@U@»@aXKWƒn_‚JXkVKnƒ@°LlKXƒW@¯Uƒ@aUK@kmJUw™VƒIUJ™„kŽmL™K@kka@wUVm@@am@UkUbkK@nmVƒÒ¯VU„WVVmIƒƒULk@ƒƒma@kkKƒƒ@nUbUamU™`UUVUkKVkkƒW@@bkmƒnƒmUXVKXVƒL@VƒbU„m‚™bVXJ@nmKÅI@KWKUXVJUL@VUKUX@KUKWL@LUJmaXXm@kVVV@L@VUL@VlK@L@V@LUK@VUb@UUU@°@nVxU`‚Lkn@`@XVJ@X™Vm„k@UKmV¯LVVn±Wm@Ub@JlLUl„@VLk„@lmVVn@bnV@V°IV™šaVJXI°K°V@XXVlVVU„nšKVlUš„bWXnV@bV`U„„@@m@@‚ƒ@nxmn@bXVlL@¤nb„Ul¦šVVUnJVU„Vl@@bÞL"],encodeOffsets:[[118418,34392]]}},{type:"Feature",id:"3413",properties:{name:"宿州市",cp:[117.5208,33.6841],childNum:5},geometry:{type:"Polygon",coordinates:["@@@UWU@bkW@aWU@aUIkWV™lLXb„lVIUVV@‚mn@V_n@VaUK@I‚@UašanJVU„@lV„UVnnKVVlaUa„I@wnK‚Lnll@nVlk@wVKXkl@@b„bUJ@V‚U@U„UUyVk@aVUXwlWXX‚WU¹@aU™@WUI@mlUšn„J@Il@šaXbV@VKl@XxVL@W„IšJlb„@„al@„IUUm@@aVK@¥¯—@mUķ¯bWƒk£Vm@akm@VaÅ@UVWaƒ@UJWkƒJ—UƒbWbU@UlƒXk@ƒamV@K¯nk@ƒlU@Uxmz@bU`ÇbUbÅVm£U@Ww™x@akLUK@UlakwUJWVkLmaUal@n_ƒmVUnKVUUmÅXWa™@kJmx@XUJ@bVLXxl@VVUVV„UbkLWbU@@lUVV„VVX„›K@XkJ@nU@@bV@VxUVlb„U@xXLWŽn@UxVbVĊ„V@b@XV`mnkJ@kUKmbƒaU@VbnbÆx@XU@@`k@@bl„™@@bkL@WƒakXWaU@Vmkx@XWW@@wUUUbƒJ™U¯V™@¯ÞU@WxXŽlL@bkb@ŽlVlnb™JW@kkU@mbkaWJ—IVlmz¯`UnU@mb™@@„ƒ`@bkVlœnV@b@šV@„aVxn@Vx‚KXnl@nbVK„bVK@a„_V@Vƒ„w@W„LlwnK@UmIU@VWš@šUÈ@lKnal„wš@@V°@šaUmlUUw@„ƒV@@UXK"],encodeOffsets:[[119836,35061]]}},{type:"Feature",id:"3410",properties:{name:"黄山市",cp:[118.0481,29.9542],childNum:5},geometry:{type:"Polygon",coordinates:["@@lXnlWX@VUJVnUJVzXJVx„kVJlI²l‚U@K@IUǚLVxnLn@lmUaVU@UVKVknJ@an@@UVIVǙKUw@_lK@wnKVklW@I@mXa@UlaXblU„JVUVL@UXWlIUUlKVmkU@kVKVL@y„wXLVb„JVz@Jlnš@nŽ‚LXbVaôšnW@la@UVWUa@@a@mk@WIk@VwUa¯¥m@UUVK@ImK@aX£ƒkK›ÅV™a™™ƒ_@±ƒakXWW—LƒƒƒnU@@a@¯mK@L™JUWwUV™VmbXX@lWLn`mzUJUb™Lƒ„k@makVWmkX™ambkKknƒaƒ@ƒaƒb@‚U@Unm@—ƒWVƒ@VbUbUJWIk@@lmL@°UVUVm„nš™@@kmWkb@xƒ_m@@aU@b@JlŽUz™lWxXn„@‚b²@l`„IVl„UlL@VšK„nVbUl@VlIn@@b„bVWUk‚@@bX@Valb@bnb°Vn@„xVKlbVnV@V‚x„L@ln@UXVV‚L˜"],encodeOffsets:[[120747,31095]]}},{type:"Feature",id:"3414",properties:{name:"巢湖市",cp:[117.7734,31.4978],childNum:5},geometry:{type:"Polygon",coordinates:["@@VV@blL@ŽXlWnnšnŽ˜„@VXXl@@WšIX@VJ@LšxŎxlnšŽ@bXJVblX@VVbUVn@VbUVlb@LnJVbVLV‚XLšÒVL„ÒšV„bVIVylUXk°Wšknm°_lJ@aXL@l‚z°@„lnLô¼V‚È„VUUaVKU@WW@@UUa@knmVLlaV@„a@kšak±@UmwkKmk™lj™ÝUUkL@mlIVmnÝWkkUÝ@KƑĉ™a@»ƒmma@mX™¤¯Uƒw@ƒ@UU@bU±±L@akmƒ„™LUKmLUUUJVbbÇwƒ@kUWaUJ@Xkxm@UJUUm@™„k„ƒ‚ƒakXUšVl±ôU@kn"],encodeOffsets:[[119847,32007]]}},{type:"Feature",id:"3416",properties:{name:"亳州市",cp:[116.1914,33.4698],childNum:4},geometry:{type:"Polygon",coordinates:["@@lU@Un@@anUlw@KVmUwlaX_lKna@KU@@kWKUU@ankW™XK˜@@V²VVIÈU@al@VaÈamK@wU™@klaUƒV@XƒVUU»WUUbkmUkVmk@aÈw@mWU@VkIkVWKUÑķXȭºU¯lƒ@kkLWmÅa™L@l™LWlzVxƒVUK@L¯LUJ@bWƒK@b@JLU@Wbk@WVUU™V@nƒJ@XX@@`m@@L@bnJ@nWV@¦œa‚wVVkxVn@bVJ@V¦@Ž™²¯bƒl™b™@m„UšUŽƒŽ@¼ƒ¦Xb‚UV`@nnxUxWLkUkVWKkV@XV@@VVL@VX„@lVV@L@blL@`šL@xXKVL‚@„VnUš@lwnU@ml@XnV@@UVW°LnalƒUI@aUK@a‚a@U„kXW@I@mWL@UXK@UVW@U‚@@k„Wn‚@@V„@XblaVxšL@bVKXb„IlJ"],encodeOffsets:[[119183,34594]]}},{type:"Feature",id:"3417",properties:{name:"池州市",cp:[117.3889,30.2014],childNum:4},geometry:{type:"Polygon",coordinates:["@@„V°°ĊŤ@xƒĖ@xœXƤ„VôIÆmnLllXÔ@lƒÜŽn@@JšbšLÆaĢÞĸ„°VVUUKVanK@UV@VL„VVn„ln@‚xnklxXamk@WV@Xa˜@naVk„Klk™@mkUWwkJWw—IWK@ƒUaUwWIUyVIUmVI@UXWmkkW‚—KUUVWm@@kƒKw@U‚UUmkaULƒwm@¯Uma@akaUbW@@a@VlUXƒa@am@kJ@UVkUaƒm™L@UkKƒVUkƒJk_±@aƒ@WmXwÇkkaVaUa±ƒœwV@VkƒwnyUaW@UU¯amLk@m™@kmmU™™¯K@L@lUX¯ƒWlkXƒŽVb„bƒVUL@J@LVKnlJXnlb@`nXlalV@bnL@Vnb˜¼@lXbWlkL™K@zUJmIUxUVUVmX","@@llUL@VlxšL@a@UƒwXa¯@"],encodeOffsets:[[119543,30781],[120061,31152]]}},{type:"Feature",id:"3401",properties:{name:"合肥市",cp:[117.29,32.0581],childNum:4},geometry:{type:"Polygon",coordinates:["@@„L„xV‚ĊLÞkšVlVVXaWaXwW™nU„@‚anVVUX@˜bXblWkk@wWmk@VUVKnb@Išy@_kWm£nmVa@U‚KœwlVl@„zn@°l„IlmnVšIVmnV˜aXÅWmU_VK@Unƒmmk@UIVakaƒa™UƒÑUK™ÑWKUUKUamI@KkaVUUam@VUUa@UkWUaWI@a™kmōw™wUL@`mn@KƒV™IUVUUUK›Vk_ƒVkbWƒ@VkUULUJ±I¯aƒlkxU¦@L@V@V@b@b@„WJXbWVXn@LƒKVL@JkLƒŽV@Vbn@VV@XU@UlV@@VV@V@XXV@@VšJ°š°Xnb°@„JUVVXV`@bkXWŽUbU@WŽn@VLXlm„°bV„UbkK@bVJ@bVbkLV¦ƒKķV@x@„XbmVVVk¦"],encodeOffsets:[[119678,33323]]}},{type:"Feature",id:"3403",properties:{name:"蚌埠市",cp:[117.4109,33.1073],childNum:4},geometry:{type:"Polygon",coordinates:["@@VÒXLlUlJ@UXV@nÇx@bnlUVllnVaXVV¼UVW„U@V„²wVV@Vl@„VnwlIš@XbÆWVnUVmLUV„nm`k@VbnblKXUVIlxkb@VVLlK@bšwXxV@n¤ÆUVaÈaV_@anyVwV@„kl@°m@LnU„bl@„WVkV@Xa„a˜V„IXl‚IV‚„@XbVUÆ@XKWwUkmW@_UmnIlJXkWKXmV@‚w@_XV@Kl@kU@KlX@@UUUUKWLm@klJVUUmk@mXUWmXwƒ`m@„zUbÝakbW@m@UUƒéUIm@UbKǼ@™kKWXmWUkaWU—JWU¯L@W™Lƒwk@mm@_™ƒÅl™UVkmWUnV@VWLUb™bƑĬ¯l"],encodeOffsets:[[119543,33722]]}},{type:"Feature",id:"3402",properties:{name:"芜湖市",cp:[118.3557,31.0858],childNum:4},geometry:{type:"Polygon",coordinates:["@@„bVaV@XllLXU°ŽlL@V@VUnVl¯Ikš›VUVU@@b@lUXUWmb„n@¼šbƒĊ‚LÞ@lVXlmÞUnkJ@nlKVVšÞXklWVaVI@aUKn»lL@Kn@‚XXwlm@mn°@„V@Wy„wXlWVk™ƒ@aUaVU¯£kKWVXVWLUkkWlkkwmJUam@@aULVa@UƒVaUaVI@m‚@UUJUIUmmV@bm@UXVVUlVmImakKUU@UU@VmU@@kma@KVIXUVK@U™VmUkV™m±£@JkU@nlšk‚ƒLUlmb—@WbU@@XnlWb"],encodeOffsets:[[120814,31585]]}},{type:"Feature",id:"3406",properties:{name:"淮北市",cp:[116.6968,33.6896],childNum:3},geometry:{type:"MultiPolygon",coordinates:[["@@lnnK@¦n@@V‚V„@@VV@nIV„V@VW²a@b@bVnUVVV@V™z@lš@°UšV„IVaVV@x@ŽXX@WlwUnV@XblW„b@XlK@aš@kƒ@al@@_V@@WÅwmaUaV@„bnaVL@llInmU_@W@aƒUUĉUaVwm@XWK@wƒVkaVUUwU@@aV@@mlI@WœLWƒUUUƒVU@kV@XalKVaUƒVUUUk@WwUK@aVI@WƒUk@@UUU±xkb@lVš@xnLÇbUbk@@bÇVUJ±U@U—@WLXšml@bVVXL@lV@@LmbkLW`kbVxUn@LkxmV@bm@@VkV"],["@@VVVkV@¥@UV@U@VUUJƒkWakKUšlXVJ@bXV@blX@aXV@V"]],encodeOffsets:[[[119183,34594]],[[119836,35061]]]}},{type:"Feature",id:"3404",properties:{name:"淮南市",cp:[116.7847,32.7722],childNum:2},geometry:{type:"Polygon",coordinates:["@@°kƒīšaVaXK@U‚UVmnXUlšVÆkVKUUUmmU„ÑkU™UÝlĉKUƒwƒKƒbU@UxW@@lœmVUUVmUUƒmƒw—aW„kL¯K@Žm„ULWlIm`X„WL@b@¼@V@xkVƒI@b@l@lk„V°Ȯ¹ĸW"],encodeOffsets:[[119543,33722]]}},{type:"Feature",id:"3405",properties:{name:"马鞍山市",cp:[118.6304,31.5363],childNum:2},geometry:{type:"Polygon",coordinates:["@@šNJnllLnxV@laXLVKma„aXbVI„bVKVVVIVyn@n_ƒƒW@@ƒ„UnJlUVVXlLnaUWlV@VV„IXW@_W@XK@K@UVUUwVamÑXmmwƒw™KUnUK™çU@ƒJƒU¯@mŽ@nknWxWm@@LkKm¼VL@bUJUbkXWl"],encodeOffsets:[[121219,32288]]}},{type:"Feature",id:"3407",properties:{name:"铜陵市",cp:[117.9382,30.9375],childNum:3},geometry:{type:"MultiPolygon",coordinates:[["@@„ÒV¤@¼V²@aVV@Ž@„„x°Vš£nW‚@nbnaVXVW@k@aV@VUœUl™°JUkVm@U@UkK¯WVkKWkU@Ubƒakwmlwm@ƒkUmƒUUKU@@VmLUbVLUV¯U"],["@@LllUL@VlxšL@a@UƒwXamK"]],encodeOffsets:[[[120522,31529]],[[120094,31146]]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/ao_men_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"8200",properties:{name:"澳门",cp:[113.5715,22.1583],childNum:1},geometry:{type:"Polygon",coordinates:["@@HQFMDIDGBI@E@EEKEGCEIGGEKEMGSEU@CBEDAJAP@F@LBT@JCHMPOdADCFADAB@LFLDFFP@DAB@@AF@D@B@@FBD@FADHBBHAD@FAJ@JEDCJI`gFIJW"],encodeOffsets:[[116325,22699]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/bei_jing_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"110228",properties:{name:"密云县",cp:[117.0923,40.5121],childNum:1},geometry:{type:"Polygon",coordinates:["@@vIHZDZQtDLNMXIbHRCXXITbJ@H`LGPRDDJNCLHTOCWFGvGBUJMKGFO^IHWXITQCI’Y^AXGfRˆDXF`DJOLB~G\\DZIHHpErUVMhHb]\\M†BVF@FTP`@zTbD\\@~M\\K`H^EVODWICAakAQXoIcCOCIgGYNWFWNGGKKGaJEGMEIKYJUT_J_Go@_SyQaSFMEGTcYOQLIIi@EKAUPCV[EEXQCW|aMUMAaYCYNIDGGACIMGGSKDQGaF_C[GaB@GOIiOKAYL“mI@CN]F[SWWAcKKI@HMUimEKbeYQYISNUOcBKPIFBNgvDPGZYFSf]CMSIWGEUFgDIQ[MeDMJS@RR@LphFPCHaBAJKF@J]IBJO@HlO@@RKAMPJHCNDJTHFP@ZGNANBRFH@J_fM^ONJNF\\VTDJHDON@XRND\\XRCPVETCLBVKDFJINHRGPRV@\\CLJN@VbXbLVT"],encodeOffsets:[[119561,41684]]}},{type:"Feature",id:"110116",properties:{name:"怀柔区",cp:[116.6377,40.6219],childNum:1},geometry:{type:"Polygon",coordinates:["@@JHTVHXCHPfnDJGHNDJSB[JSBGVSAOH@PMPuDEHHXZN@PHF@ZLJ@LHVYJA\\OFWP]BMtMBSRGV[JeVAPQVIFENMD¡–@^NV\\JH@NNL@NM\\kTQ\\I^FNIpBHGTBFFAZQfKDIXQTLXFXNNVMVHRGpCFLlRLEVBBH`IVO\\G`RDPAXLXBXORHZEHTDLLN@VGTMrQNFPeASKG@GMOAKBYMK@GTUHUXSHMVDNMOUEOZMJML@^KRACMZEZMRQLUHE@OFENPR@DI\\ChMHIDG\\GJMDWHCKGMDCIQCHO_K@GaIJSWWQDaGWJMNCKRsCYGYuJUSaKaW@UIMDK@[QUHOGQJMEILCAUDKFSOUQD[WMC‚Q@WPMGCCIUSE[IMPMN]`e@IEGAQBMHM@YEOSGCIDMIGNOLB@QP@GkP@AI^J@ILEBIbADGEOog@KQQWSekWQQUOFKZLF@PUNmIaHIUeBCTSHENcJa@_IWSaGu`GLSBKJQFOXGDXVQVOBIHcDSJWBEFGTMH[^mLaXcHiKElTRKtFXZ`MHMPCNRDxZˆB\\ICIHK@KŽHbIVFZ@BPnGTGbDXRDJaZKRiGEFSFEJhjFNZFjn"],encodeOffsets:[[119314,41552]]}},{type:"Feature",id:"110111",properties:{name:"房山区",cp:[115.8453,39.7163],childNum:1},geometry:{type:"Polygon",coordinates:["@@h@bl@HRJDZ``TA\\VVD^H`\\pF\\JŒ`JGv@ZO\\GPSTEjPTR`FnEbDTDHEhLFMTK@ETSPULKEI@OVISKSJACEQNQbV˜IXGDIN@dMB[IIBcN]ZHNLP@XOWCFWŠCNRHTpATD@^NVNLED@Rh@jCEF}E[OOHUEW]W@QGGDIQSH_MmFmCUT_K]i@MHCMW—FCF‹E{BMHMPOHKS]CFNGBELDH_@BcAKOACESAOBELaXAROB@FODMEDWJAG[aE@UM@DImEWJMC@OeCA{aE[@{L@MINUCQXKfUJORCHqJBF@TCXWNQX]M[EAJO@@KMBQJIC]EWMCCUBEBFHKDOTMBGNGF]MWDBRDdMDQVyE@LPVHDCP@JVVMTG~HNSH[CmRUvHPHBbA\\PTNRC\\YNJ€PRARPJDDR"],encodeOffsets:[[118343,40770]]}},{type:"Feature",id:"110229",properties:{name:"延庆县",cp:[116.1543,40.5286],childNum:1},geometry:{type:"Polygon",coordinates:["@@^AXOPEB[ZIGU@KKI@YGE@OYMGWFGvCNO@OPGTBHUTA\\ITACIGMIHmCOeDGGWSUIGimYEEMgiFITEFEjHLQbYCIWQaCSHmHAOY@UEaJG@LGLDJ[J‡AwYQCDMNONGY_EWLsSQFkMO[NWAIGaIYL@HMBOKiOQDWEUDMQSF_QIUBWdg@[NaAKQ@M]OQ@WhgLUMMFYQDIRCEUZOOCIOJ[KIUMKL@HIDKVEBM`HJAJSJUdBLGNEdMBMO[BYEWJSNKNaD]PE\\SjOT_RQVEZPpƒNQXfŠNA~lNG`@PNLp¼RFLfbdKbATUh@FSNWjGFZVLFHVA~X¨PPROfFJbNJPLFbENJPrEFNPFRHDDJdENJLVEPBJTVTHGHFRFH@PXP\\ORQHW\\BjWFDERLPPBbB\\E`B\\D\\L`@F]FCnJ^AZL"],encodeOffsets:[[119262,41751]]}},{type:"Feature",id:"110109",properties:{name:"门头沟区",cp:[115.8,39.9957],childNum:1},geometry:{type:"Polygon",coordinates:["@@V@XMnGPY²‰JQNEhH\\AZMPDVTTDZCPiJkHSHCjIdFtEHITCNITQEKUAMCEIKCECABYESKFWAKBEIIHABGDCKCAIHMHALKEI\\CFIBILIJQZS]BBEECS@E@@C]COKI@CABAAEEDMGƒCH]A[M@CJWH—JaUMRFRBDTITLUJ@PFJKLOVST@FSLENgKGFSCaCmF_ESQiOSFOT[HYPu@IH‹_[IoE_[]GUC[USB__CYQI@Gakg@qZeHQNMNV\\FVLPgJAFJPRLCH[XcPELUT[JiV_EELFTADBXRTRLJC@fHXHHbPd`fR@NfT`@TLplHMpCEJHJBVLFŽ@JT‚VnG^KXDXHNVGRLRXFJVdDHSNWLGfEzA"],encodeOffsets:[[118635,41113]]}},{type:"Feature",id:"110114",properties:{name:"昌平区",cp:[116.1777,40.2134],childNum:1},geometry:{type:"Polygon",coordinates:["@@VNLJI\\JPPDYPFVQDCJZRNEVNhKXgR@^P@NLRbB\\Mh@XcVARJE`RTCNFV€XRCjPPLNA@GZKbJJHXB\\MNPjLdGbWnK\\]NGHSFEXATIdCJGPARUWUHCPWRELITAHKv_E@iYCaW_BQ\\Y@QIO@QDCIGZCEMWGFMFAFgHEDOCSqKCCFGAMKEAC@ODGCGs@WH@KQA@EE@CE@GEA@EH@GGUEEJEAYD@JM@@DAA@FHD@FTJEHUC@JUBKCKG@G[CIIQReAYhO@OXGDO@@FF@IHJFCPEBACBIAAKDOABXARHPNEHGbQAAKQFGIAM[C@WHKaGiCEGOA‹HUKCIokSCUSOCYN[BgGMFIR±ŠOZmHWNU@ShbbXDHVXXGJ^lZ@PZ\\Nb@\\FHJAD"], -encodeOffsets:[[118750,41232]]}},{type:"Feature",id:"110115",properties:{name:"大兴区",cp:[116.4716,39.6352],childNum:1},geometry:{type:"Polygon",coordinates:["@@F\\E~DFN@BDFEpHFCHBBEGCDCJBHUDSBB@ELCPbF@B\\J@BJVAFJ\\ADKTCBGECFMT@BMN@@FH@DaNBEnvB@FPBATK@FHEFIAKFBFL@@PKBFJHC@FXBRAFCDMPDTOL@JIVFDHH@DDH@BGRFCDLD@N^@@CNA@KNOAEBCECFEGCFGMGFIPMOEJOLBADBBHGG@GCHIECY@INC@DMGS\\AIOZAAEYA@GT@KKMBEETCGMVINFxA@MJADB@FlA@HJA@NND@DFA@DVAZBBOFKH_JA@K^GBC@EFE„G@gAENMXKJigC@IbSJMqGOP£RGSMGE@kbQFDPEFiBSGGSBK]I{CDWCIDOic[C_G@SuSO@EWKCO@MNY@\\uZOPENQD[LKESSKGBKEG@EJGAGHoH¥CqhifeJkX_XFFGHFNEDFPENKHM^IFIVL^S`DVEnNnG`RTCJHH@R^XFXGVPP"],encodeOffsets:[[119042,40704]]}},{type:"Feature",id:"110113",properties:{name:"顺义区",cp:[116.7242,40.1619],childNum:1},geometry:{type:"Polygon",coordinates:["@@EhEBENXHFNYDJHCD@RJP@R[ZARX`DbjZF@bHXT`Jb@dIFMTGDSfAJVbGnJVM@OKELYPERVXRflXTT@NIfC\\NJRhCVEHFJXNT^DTeZEHYCOhuAMJELOdAVPTMOWBWNMNEJgl]@WGUFIC[T{EEDEHGCIGMI@SECUQI[D{A{GQESPUH]CsiMCmHUeoHENcAaDGCMDGMQCACCBaCGLMAHB@DIEQLOAAEEJ@CW@CDINGAAGKQOCgV@LG@BEGDKNeREFBNCFIDOPKD[@YRW@GFWDAFE@EHDDrLDTCPGF","@@KrJEH[\\B@FF@CHFBHUN‹AJKADGECBCMAG^E@EbI@BEGP"],encodeOffsets:[[119283,41084],[119377,41046]]}},{type:"Feature",id:"110117",properties:{name:"平谷区",cp:[117.1706,40.2052],childNum:1},geometry:{type:"Polygon",coordinates:["@@ZJZRafFLjn€VGNJ@LLBdXX\\T^EDMJ@”nZKLBjPPJ@HbA\\H`DbERHLCFK^BZaFWXQLAGMHa\\OLO@SBIpBdCLƒVQfElO@GSAKEDQTC@GEBKG@ORIJBDAPDFA@CaOq@GGQAAEJK@KMUGAAGEAa@MGMBGCGSIIW@WSUCMDOJeWOM@IUF{WMWaDIMgIoRoCOKeEOEAG_I[cg@wLIFENQFDVTFJ@HNDJGHCFFFS|D\\EJHV@Xk^IhMFMNAXPX"],encodeOffsets:[[119748,41190]]}},{type:"Feature",id:"110112",properties:{name:"通州区",cp:[116.7297,39.8131],childNum:1},geometry:{type:"Polygon",coordinates:["@@FDAJTGDNDCTDDEDBBE@DT@@EHCDGJ@EIZ@@FDBR@ATFBBVFFE@@HNA\\VE@CLIFNJFNJBCP]A@LJFA@HJEDD\\C@DBCHLAEPF@@DH@APHAERDF\\GIxDTM@CFLBBFJ@CNUPMHECGDBF]BMFPDLRBHHBJMDCX@@DFIBFPBRKJF@CGANBHKbDDABDRDHNNCHDbCdBFMpGHiOYMefKJMC}HWAUNW\\NNBNA„kNU|]HMTMN@MZBLFFF@RIRUT‘BMFIEGaAGGAOIIUGTSFcYKS@MSLYPKRUBU]EWDOI]CKGASgW@MTWKIMCS@uMAKKADMECGAKVUTSDy@IjWLMNBF@hƒHEF@FAD]H@LIBG`ELAPYAUB@CEB@CMC@MIB@GkB@ECAIB@NwBMEUJHNSDFFNALLS@@HZBBFYBJP[BHTCND@JMZ@FDGJHDH@GHAABCKAIPPFONEJNHEHHDEFFDADBFMP@L"],encodeOffsets:[[119329,40782]]}},{type:"Feature",id:"110105",properties:{name:"朝阳区",cp:[116.4977,39.949],childNum:2},geometry:{type:"MultiPolygon",coordinates:[["@@bFGHBHFBFIVFHHG@@FFB@HDFF@@FRB@LXGt@DHCH@PBDLFBNF@BEXCHEX@ZQ\\@LCPOJCDEAMFEfQLMHCAFH@@KhUNE^AAEHCFDNGVODMI@AEKADEN@CSJw[HCEFQGBBOG@@CE@FOKBDGCAD@C[FCGIB@IE@K^BDOIAEMMIJEDKF@[UMB@GF@EEAUEABSQ@CA@EY@FJI@CHGD@FS@@CAFCACFSCCDCMSHBIECMB@D]@@MKCDCQEAHG@CCG@CGUEIJK@SPOCCNEDQBDNDB@DJCDLFCBBALJB@BVGPBKVO@KHCCCD@FE@BNA@FNCTDDJA@FGB@NBDW@CL@hT@@ZHHQDDDAFSAANBC@HG@EFS@@DE@@PCB@Ue@CADNJB@FCBWA@LI^ix@FIHrH"],["@@HUN‹AJKADGECBCMAG^E@EbI@BEGPKrJEH[\\B@FF@CHFB"]],encodeOffsets:[[[119169,40992]],[[119398,41063]]]}},{type:"Feature",id:"110108",properties:{name:"海淀区",cp:[116.2202,40.0239],childNum:1},geometry:{type:"Polygon",coordinates:["@@plDJVLŒGPBFHjDbHGL@X\\DBNHJREBLRBHaFGŽMGOBQAWPBLCBBAJBDFADOIEJGE@@EP@HCPWP@ZgfBRQJJ\\D@HLHLDVA@IVDFGSI@EGC@EBB@CN@@IZCAGHGaEqGJG@EjwJ]@K@GSA@e_I@NE@CA@Kg@KC@ENCFƒAKQAW@WIMK@V‹@I@@F@^EDFB@HcIaDYCBRRDCHD@EFLN@FE@CJUPEJOJMTBPEDIFCMIAKNOGMRFJNDVBFLSRMJSDGJsFcEiJGDGTIlOjYD"],encodeOffsets:[[118834,41050]]}},{type:"Feature",id:"110106",properties:{name:"丰台区",cp:[116.2683,39.8309],childNum:1},geometry:{type:"Polygon",coordinates:["@@hMN@NFTQCFRCBJFA@HJ@@HJ@HJ\\FTACDŒ@@UNLXJX@@MA@@IECAQlDFEHBDI~D@GXCFMVDFCH@@NF@ANJC@FnAB@AMF@@EDCDDLGP@LUOAUH@AIABKAAEDCKID@CCACMWA@EGDEILA@OK@AELEJBFEEGL@BSOA@EuAFmMACbG@@EM@ANS@ENFDAHSDCL[BEIUBAII@A[E@OaKD@FAACTGVIACDHDAFGAEDoGEFACM@i€g@@QFCMKMU@]SCoBGSMQ‰DEXXDWPO@MKYGM^AdJJA\\cNB\\G^„DNHFCBFABDBJ@PL^D@DF@T@FDAF^A"],encodeOffsets:[[118958,40846]]}},{type:"Feature",id:"110107",properties:{name:"石景山区",cp:[116.1887,39.9346],childNum:1},geometry:{type:"Polygon",coordinates:["@@NQPHLMJBDNJEFCAONSPIFIVODIF@@EKMFEC@DGQCAQZDbCdJ@GEAFC@]@EJ@DCSB[EGII@@GI@@GEBAIQDDESRMEM@gNYTIRKJAJEJ[DFJKLGBGNBJLDCDAHGBJJAFBLEXTLZFBAFDLD"],encodeOffsets:[[118940,40953]]}},{type:"Feature",id:"110102",properties:{name:"西城区",cp:[116.3631,39.9353],childNum:1},geometry:{type:"Polygon",coordinates:["@@XBDA@EIACM@IJAD]BC@SFABISAD]H@@OAEDQEW@BLE„MD@FLDh@@LDBF@@M`J@fTB@H"],encodeOffsets:[[119175,40932]]}},{type:"Feature",id:"110101",properties:{name:"东城区",cp:[116.418,39.9367],childNum:1},geometry:{type:"Polygon",coordinates:["@@DBf@@VDA@OF@@CT@FEH@@GADBMTBBECCRCGG@YS@@gDK@A‘C@PG@C^TBAJEB@TADC^IB@J"],encodeOffsets:[[119182,40921]]}},{type:"Feature",id:"110104",properties:{name:"宣武区",cp:[116.3603,39.8852],childNum:1},geometry:{type:"Polygon",coordinates:["@@RBX@RFFCŽBFU@aK@WA}CCJGAEFkCBRFD@JB@@N"],encodeOffsets:[[119118,40855]]}},{type:"Feature",id:"110103",properties:{name:"崇文区",cp:[116.4166,39.8811],childNum:1},geometry:{type:"Polygon",coordinates:["@@XBL@@bEV’D@BX@AC@MHA@EIBCCDSEMmB@EIDBME@@MG@EDUCENWD@H"],encodeOffsets:[[119175,40829]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/china_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"xin_jiang",properties:{name:"新疆",cp:[84.9023,41.748],childNum:18},geometry:{type:"Polygon",coordinates:["@@@›ρȁôƧƦóəʵסʵóƪԫʵѵͩƧͩړ›υࡓɛʵ@ȃ@óᇑѵƨɝɚôóНѺͩɜ̏ԭʵôƧɞñ@υƩ—݇ȂóƩƧ@ѵȂυœƥŌਗ—॥ɛóʵѵƧѹ˜݇̍ࢯ˜əɞυ˜ρͩ̏óਙƨƧŋôōóš̍ͩóʵן›óŋړͪƧѶ@ɜԭ—ԫƦɛȄ̍›ɝȄöςƩȂ̏œñȀ̏œƩóóŎə˜@Ő̎@ɞȀɝŎôƨóנѵȄƧ@óŏɝœóɜôŎ̍ͨςŎ@ƨóôƨɞ݈ʶóƨφó̎Ȁƨ̍ԮòѸԮמ@ѺȀ@ƪၬֆòȂñ̐òȂɜ˜óƨ̒Ŏ̑߼@φρȀ@Ő๐ς̎Ƨφ@ɝφڔ೦Ԯǿࢰ@ƦŏԮƨƨȄƧ۬ɜʶڔŐɚɚóŐôƨ߼˜ôƧƧó̐ƥóŏѺǿƦȁφƧς˜ƨƧ̒@ɜƥƦυ̐ɛƪͩƩəƪʷ̑ə@ȃƨʵנŋྸōਚԭԪ—@ɝƨŋ̒օςʵôƧ"],encodeOffsets:[[98730,43786]]}},{type:"Feature",id:"xi_zang",properties:{name:"西藏",cp:[88.7695,31.6846],childNum:7},geometry:{type:"Polygon",coordinates:["@@ôŌנœôʶ̎ͪô™óŎƨŌਚƧ̐ôςͪφ—ɚɝࢰ—݈̎Ѻ—Ѷƨôʶ०ɜਘ˜Ʀŋφ›Ѷȁ̍—ôŏɚŋ@̑ə—@ŏò̍ɜ›óƥôʷƧ̍φѹԪ̍ע@Ѹʷɜ@ôñנ@Ѷɛɞô̐ŏѶƨѸƧƥōƦœôŏô—@ƧôƩ̒ŋƨŌƦǿô̎ɜȁ̒—óʶѶôôО̒›ςƥɜНφσɛȁ̎υƨఱƧŏ@ʵƥœ@ŌóóóͩƨƧóŋ̑õóɞóɝԩͪɝρôƧ̍ƧѹͨڑŎ̑ōóƧࢭͩ̏ѵɝóఱóóԪυô@̒ƥŌ̏Ƨ̑Ȅ݇ŎƧ›ѵӏ@ɛõŏɛȄôӒƧŌѵǿɝ˜Ƨŋԫ@̏ʴƥ@óǿ̑Ȁóǿ̍ςóóυô@ʶɛñρƦƩŐó̎óœѵó̑ͪࢯОóɜן˜Ƨ̏ƥȄ߻̎̏̐ןŎɝɜöɞƩȀôöɛȀóͪ̐ƨƪ̍̎ȂƥԪυО@φɞ˜ôƪ"],encodeOffsets:[[80911,35146]]}},{type:"Feature",id:"nei_meng_gu",properties:{name:"内蒙古",cp:[117.5977,44.3408],childNum:12},geometry:{type:"Polygon",coordinates:["@@ኊȁ૊ö߼ƩɜɛנñԮɛѶóԮô@ȁѸóמ̎ගѺၬ@߼ʶԮӒ߼̎@ŐѹӒ̒Ԫƨöග̑ѶȄ̒ς।œѶɚöɞɜʴڔôôȂ̎—ѺȀς—ƨ˜ƪóԪ—ɜôɛОਕڔԭ˜ѵ̍ѹȂԫ›ɛƥ̍Ȃóɜ̎ô@ʶ݊ੲࢮʵږͪנƨôȂƧ˜̐ͪ@ŐƦƨφԬѶɜôƦ@ŐƧôôƦəŐ̏›@ŐڒѶԬô̐ʳԩНςōôŏɞ@ƨȂѶəóƧ̒ػ̎ó̐Őנóƨô̒@ƨɚɚ@עԫɛɛ@ȁυͩƥʳòևρ—̑ࡗƧͪ༃ॣԮփ̎Ʀ@ôô@ôō@š@ȁѵóƨ̍υȃóʵɛƨƥóυȂóəƪ›̐ρƧͩɜԭڔȄ̎عƧȁ̐ŏó̍ɛ›ƥƧ̑óρŐ@Ƨ̏˜ɝəɛ˜߻ͩ̍ͩɝО̍ƪƧóóӓƨóƧʳ݇@ɝςƪœ@ʴƩ—ƧƦôƨɛȄə›Ƨŋυ›óͩѵ@ɝǿóŌן̍ɛ˜óО̍œ̑̏ôȁ̍ŏòȁñóƦͩ@ǿə@ɛƧ̑˜ρȁυô̍օѹœóȃə™@ȂσʵѷƪòƩ̍—ôó߻ۯôʳƧ™óšõʵѵóѹɜ̍ȂѹôɛŌφֈƩͨρóυӑóޟఱ̑݇ͪóƪƨŌóȄڔԬƩςםñ̑ȃѵŐԭŏƨȁɛǿρôõɚɛóƧОə@ѹ̐ѵöԪͨôͪɛ̒ןŏƧƥóôƥƧɛŌôóɝó@̒݇Ӓ̒Ō@Ŏԭࢰ"],encodeOffsets:[[99540,43830]]}},{type:"Feature",id:"qing_hai",properties:{name:"青海",cp:[96.2402,35.4199],childNum:8},geometry:{type:"Polygon",coordinates:["@@ƨ@ôƪ݈ȁƪ˜@φɝòóƨԮʶɛ̐ѹͪôОəóƧɞᇒѶ@ôږô@ǿѶ›ƪȁςœɜͩφ˜ςŋɞôѶɛƨŌɞ—@ɚςŐñԪॢͩƨȂɞóƨŐ̎ŏעӏ̎óƧƦôœ̒ȁɜ›ςͩ̒œɚɛƨôƨɝφɛóȁƨŋóóɚͩƨóóƩ@ƧəŋƦƩ̍@ƧƧôǿυ̑@ȁɞǿõŏρƥסɚƧóτԫɞœôƧƦ@ñȃòñƥóυôôѹѵ—@ŏ̏Ȅɝó@ȂəŌóəѹƦ@Ő̍Ōυ݈ԩŐƧóôƧ̑›ôʵɞƧ̑ѵôƩɞƧ̑œóНѵóôʵ̑˜ɛȂó̍ƥȀƧŋ̑Ōóƪ@ƨó˜óŐƥ›ƦŎѷƨѵƧ̏Őɝóѵɜן@óòɛ@ѷʸס@ԩ̎υѺƨ̎óʸôƦɛœñ̎@Őɚ˜@̒əŌóŐ̎˜"],encodeOffsets:[[91890,36945]]}},{type:"Feature",id:"si_chuan",properties:{name:"四川",cp:[102.9199,30.1904],childNum:21},geometry:{type:"Polygon",coordinates:["@@ô˜ôŋó̑Ԯ̒ɛОמͪƨōöͫ߼ƥôȃƨóóñôƧóƧôōڔŏƨŐ@Ŏô˜òƥѺŎ@ōɜóנ˜ôǿô›ƦôԮ̍ɜôɚ›Ƨ—ñɛɚȁ̍Ƨɛևυ@óóôŋρԭɝ@Ƨʸ̍ŏυɜƧƧóƧƨȁρ̍ƨȃɚ—ôʵφóô̑̏Ȃ̑ʵɜʵɞ@ƨʳסƩóŎə—óɜƧôƩƧρ˜óôôô@ŎƧƨƨƪѹ˜ó̍̍Ʃ@̏ѹНôޟ̍Ʃóƪυɝɛ—əƨôŎɛȀ@Ȃ@ñɝʶ@Ōρנ̏—õóɛͨƨȂѵОɛʵ@̏ƩŐó߼Ƨల̍φɜȂυτɛОρƦɝƨóƪ̒Ѷɝƨóʶ̒œóƨƨôԪŏφ݇̎ŋ@ŏѺƥôɚɚŋ@ȁɞô̐ȃ@ŐѶ˜óѺφóƦôñòòȄ"],encodeOffsets:[[104220,34336]]}},{type:"Feature",id:"hei_long_jiang",properties:{name:"黑龙江",cp:[128.1445,48.5156],childNum:13},geometry:{type:"Polygon",coordinates:["@@ᇔȂਚНƨŐѶŏöƥςŏñƧƦóƨȁ@óƨ—óȁφӑóóƨ˜óǿ̎̑ôНɞ—ó̑ɜə߼›̎ǿ̒ôڒӑφ@Ƨȁ̎̏ƥƩ̎ρశ˜ôȂςƨφ@נɞ݈˜̑ƥƧɛƨʵƧȃƥ@Ƨƥ@ŏ̑ԩôɝρρóɛƧ›ƩͩƧó߻ʸ̍ʷѹƥɞڕõ̍öɝυ—̍ȂƧ̐̑ŏóƨñŋѹóóȁ̍›̏Ԭõʸ̏ŏ@ǿ̍@ƧОυ@ñƨòȀƥŎ̑ŐѵóɛŌóȂԫōƧŎѹñ̍ʶóОן@Ƨ̎Ѷô@Ȃ@™óŎó@@ó̍ƥԭք༄।ƨͩ̒ࡘς˜ñֈƦʴφͪ@ȂɜɜסԬə@Ƨə̑@Ƨóןô̏ŏ̍ô̑ؼôƨѵɚƧȁɝ@óŐρŎԪО̏ʴ"],encodeOffsets:[[124380,54630]]}},{type:"Feature",id:"gan_su",properties:{name:"甘肃",cp:[95.7129,40.166],childNum:14},geometry:{type:"Polygon",coordinates:["@@ڔôԮࢯ@ō̑ŋ݈ӑ@̑ɞôóôɜŋƦƨôóƨƦנŐɜ̑óͩԩͧѶõѺ̏ɚ@ƨНɜôöəςóɜȀƧȂԮŐѶŏ̒ȄמòƪρړԫôȃƧŋôƩ݈ͩɚ@@ǿɜ@φͩóŏɜӑƧōôǿ̎›ôƥƪóõ›ö@ô—ƨ˜ôƧƦôó̒ɜ@ɞŌõʶ̏Ő@ȀóôƨȂ@ʶע@@ƥ୾ӑó̑óŋôʵóɛړ@@ƩöóƩóρ—ɛƨ̑@óʷƥƥ̎ɛƧ›ôōƧǿôͩѵôɝȃɞȁõƧρóó—@ōƧŏړŐóŎôƨóƨôòƧôóȄ߻ƦõͬƧŎםͩɜНԭ̑ô̒óŌó—ƥ@óƨɝ›σԬƨôעəςƦöŐɝȀ@Ȃφ̒óȀƨƨ̎@ƥƪɚŌ@ƨôƪƧôəͪôôƧŌôȂυɜƧɞƧóəɜ̑›ρͪɛœ̑Ȃó›ƨƥ̍ôסӐ̍ŐƧŏɝôƧȁॡͪòԩρŏ@əɝ˜ƧŋѵɜɝóρŌυ—ɛͪρ›ƩȂѵœ@Ȁڕó@ȄɜʶφࡔڔœƨͪѶͪԬʶôƩעʶɚʶƥôóƨςȂ"],encodeOffsets:[[98730,43740]]}},{type:"Feature",id:"yun_nan",properties:{name:"云南",cp:[101.8652,25.1807],childNum:16},geometry:{type:"Polygon",coordinates:["@@ôɞôɝ̒öôŌƧƨôͪôô@ŋƦ›@ʶƨŐô߻ƪŏ@̐ɜʶѶНƧȁɜͧöô̐˜ςן@ŋɞʵ@ò@ȁɜǿóōɚƧɜ˜φɞôƩ̎ƪóޠѺО@̐̎ƪô̎Ѻ—ƧƩƨƧ@ōóóôóς—ƪƨƨóôɛó̑ԭ—ƥŌɛǿɝƨɛͩô›@ǿƨȁѺŌɚɛ̍ןѶНɛƧôóƥȁƦͩôŎɞ—ƨ̑ɜ—òôφ@ƨʵ@ɛѹōóȃəƨυǿóʵρƧƧŌƩɛ̏ȄñƧƧȀɝ̍ԩʶƧ̑υ—óŌƥʳɚӑóНƥô̑›óӒѵʵѹœƧӐןôƪφõŌƪ̒ԫŌƧؼƨƨס›ρȁƧœƨȂóʶó@@ʴƨôôφ̎Ŏ@Ȁƨ—ƪɚƨœóƨôôôςóޤƧŌƩŋƧԪ"],encodeOffsets:[[100530,28800]]}},{type:"Feature",id:"guang_xi",properties:{name:"广西",cp:[108.2813,23.6426],childNum:14},geometry:{type:"Polygon",coordinates:["@@ƦŋѺ̎ڔʵƨŐ@ƦמȄƪôóȂɜŌɚͩɜ@öóɜôôȂƦôɜȁ@ɞφ›óȄ̎›ƨʶɞŋƨʴɚǿ̐̎Ԭ@ôñ@̏ƨ›ρ۫ô›ɚƨƨНƪŐ̎›ƥóƦʵƥŋ@ȃóƥƧ@@ŏɝǿôυƧȁѵɛ@əóŏ̑@@ə̍›óƧó—@ȁƩ˜ρóòНƥô@Ӓ̑@óŎ̍ƥσŎυ@̍ƨ@Ō̑ôóͪƨ̒óŌړœ̏Ŏ@ŌôȄѺŎ@ɜƧʶυ@ñóɛ˜Ƨ̒ɝ˜óōƥͪ"],encodeOffsets:[[107011,25335]]}},{type:"Feature",id:"hu_nan",properties:{name:"湖南",cp:[111.5332,27.3779],childNum:14},geometry:{type:"Polygon",coordinates:["@@@քɜОƨ@öŐמóƪôƩɚ̒Ő߼ȁςͩɜòƪ—ɜȀò—ñɝò—Ѻͪ@ŏƨŋóɝôǿƨ™ɚȃóəƨȃѵͩó̍@ȃƨóóƥƨƧ@ʵƦ›óͩɜ—ɛóñԭɛōυȂ̍ƧƦō@ɛƥ—ɛȀ̑œóʷóō̍œƩŏƧОəƧóœς۬Ƨœ@̐óòԫ@̏̍əȀƧʳɝŌóɞƧ˜ƨɜóŐƨò@ȄƧŌρŋóôԪОóʶ@̎óȄ"],encodeOffsets:[[111870,29161]]}},{type:"Feature",id:"shan_xi_1",properties:{name:"陕西",cp:[109.5996,35.6396],childNum:10},geometry:{type:"Polygon",coordinates:["@@ςôöƨɝȂɞȄѶóóͪƨȀóŎƨœ̍ɜƦƦôʸ̒@ɜƧς˜ƪôõô@ƪڔ@ôɜóʶôŌô̒୽Ӓ@Ʀ@Ѻ̎ɜѺɛѶôöʶô™ƨšóʴ߼۰óô̎˜ñƪѸƩτʶ@ȁòŋəѹóǿ̑ʵ@ȁ̒ʷυփô݉ôН̏ط@ȁƨóô̏ƪõ@ʳ̐ʵ@ɝɛŋƩŌɛóןôƧŋ̒ó@ŏ̐ƥ@ŏυ@ƧƧôן̏@ƥȂѹɜəœɛóԭ̎ƥóóœóȀן—ɛô@ŎѹōñƦ"],encodeOffsets:[[108001,33705]]}},{type:"Feature",id:"guang_dong",properties:{name:"广东",cp:[113.4668,22.8076],childNum:21},geometry:{type:"Polygon",coordinates:["@@@Ȃô˜ôƨ̎œ@ɚ̒@ôŐ@ɚѶɜƨȂóφɞȀ@Őƨ@ôƦ@ȄƦŌƥʶƦôôŎôʸ̒›ɜǿƦ˜@ɜƥŎ̎ƨφȁɜŎòƥԮŎƨōóŏɛƧɝəɞƧ߼ɜςȃñȄƦŎ̒ōôòƨəƨ˜ɚН@əƨ̏ƪʵυŌəɛóəԭŏəœóŏѹœρʵɝƦ̏™ƥʳѶ›öō̑óóŋρȀυƧƥɛѹōƧôן—ɛŏѵ@óŋôʵɝ›ƪԩõ@Ƨō̍@Ƨ@@ƦɝԮƪО@@","@@X¯aWĀ„@l"],encodeOffsets:[[112411,21916],[116325,22697]]}},{type:"Feature",id:"ji_lin",properties:{name:"吉林",cp:[126.4746,43.5938],childNum:9},geometry:{type:"Polygon",coordinates:["@@נ@ôН̎ʵѺòƨōԬŎôȁɜŋѶô̒ŏƦōñǿòƧφ@ƨН̎@@Ȁ̐Őöʷ̐ԫ̎œôȂѺôòŌôƧ̒Őƨ̏̎ȁφ˜@ŋƩͩםȃƨ—@ȁ̑ʶ@Ōóôɛœƥѹ̑—συ݇@ɜρƧȃࢯƨôœəȂɛōƩɛ̏υρóõœƪʴυφ@ʶôŌóœρք@ɜƧ@ɝǿƧͪρȀƩó̏ŐƨȂ̍غړȃɛԮƨͪ̏ςƩœôɚφȁƦôɜƧôʶφȄ"],encodeOffsets:[[126181,47341]]}},{type:"Feature",id:"he_bei",properties:{name:"河北",cp:[115.4004,37.9688],childNum:11},geometry:{type:"MultiPolygon",coordinates:[["@@Ʃ̒̏ŌѺ̒Ʃ˜óȄƧŌƥͪòôñȂ̎ŐóȂ̒̐̎›ôНɜ—נ̎ôŋɞȀѶ@ôͪφœƨŌɚœɜȃóƧƨƥƪ˜@ʳƩ›ɞρ݈@υНφʵɜ˜ƦρƨƧ̍ɝóɛѹ̍ρŏ̑ôóƨ@œƧƦôƨɛ@ƥƨ@ȂƦ@@ôəŐƧʶƨŌυœ̍̎ɛŋôōɝ@óƧ̍›ƦʵѵʳôʵɜŏςôƪŋƨŌɚ@ôНƥƧ@ōѸɛ̐ô̎ʵѵНԭ@̍̍Ƨò@ȁɝ@əρυͩƪ̏ƩõƧŎƧōóšॡȄɛʶɜȀ@ɞςѶƧœƥςɛŐ@ɚɜɜ@Ŏôôςœƪς"],["@@õə@Ƨɛ˜@ŐóƦφô"]],encodeOffsets:[[[117271,40455]],[[120061,41040]]]}},{type:"Feature",id:"hu_bei",properties:{name:"湖北",cp:[112.2363,31.1572],childNum:17},geometry:{type:"Polygon",coordinates:["@@ñȄυƦöŐƩ˜óנƨƨφ@@Ő̏Ʀ@Ő̑ôƨŌנóɜôƪŋɜŌѶօڔə݈òɞōɜŎôӏƦóƨô̒óôȃƨó̎ŐôƧƪ@ƨȁςƧə̑̎Н@̍Ƨŏρôԭͩԫ—̍ʵƧšóȀôɞƧŌ@Őѹͩñ˜òɞñ˜ɛǿƩ˜ɛñρͪ߻Ȃ̑ŏƪəƩóםôõŏƧ@ɛНƥȄó›̑ѺƧ›ôφóƨƨƦƪóɜŐôóòôƨóφ̐ƨóƦ̎"],encodeOffsets:[[112860,31905]]}},{type:"Feature",id:"gui_zhou",properties:{name:"贵州",cp:[106.6113,26.9385],childNum:9},geometry:{type:"Polygon",coordinates:["@@ɜȀƦŋԮ˜ô̒ɚ˜ôōעƪƧʴɝ@ɛʶ̒ʶ̐ȁƦœóȂô@ôŏ@ōô—ƨʶѸô@ʶƨ˜ɞó@ōτöòυƨ@@əƨô@ɛ̒@Ʀɜôȃ@̍ôʵԩНôóςŌƨŋ@ȃƧñôŏƧɛƨ—ôɝƧʵ̍œôȃυœ@ɝɛȂƥóóȁɛóõôɛ@əͪɛŋôȁƩóםȃ@ƥƧŏړʶѹ̍ƥŌƦȂóôɜƨѵО̎נəɜѹŋƧȂ@ȀóœɜͪɞƧ"],encodeOffsets:[[106651,27901]]}},{type:"Feature",id:"shan_dong",properties:{name:"山东",cp:[118.7402,36.4307],childNum:17},geometry:{type:"Polygon",coordinates:["@@Ʃ̐φͪɚςɞ@@Ȃƨñ̎̎Ԯ@ѶОƨƧڔ@φН̑ŋ@Ʃ̒ǿ̎@ƨɜԬςôʶ̐ʶöԫƨƧנƥɜŎôō̎@ôŏóρƧŏԫôóƧԩó@ƥɜƧԭóƨʵɛƨ߻ӑɜНԩ˜óô̑óƧʳə™óɛƧ@õȀƧœ̍ȃɛŐóŏυО̍—óɝƩ—ԩ@ƧɚԫȄɚʶƨ˜ɞʶԪ̐ړɛƪ̒"],encodeOffsets:[[118261,37036]]}},{type:"Feature",id:"jiang_xi",properties:{name:"江西",cp:[116.0156,27.29],childNum:11},geometry:{type:"Polygon",coordinates:["@@ƧȄôɚəȄ̎ʶԬ˜ԮͪςóƨŐƪ›τɞƦōƥƧ@ŏςôóŐôô̒ʷѶ—ƪƩƩǿ@ō̒ɛôυ@—Ƨȁѹɛəƨѹ̑ƨ̏óƥѵʷô̍ɛȁôŏɝǿƧԫƧ›ôʳƥōòȃρȄ߻ɛɝƨɞɚɜƨôŐƧŎԭōñƦòԮɜôɛ˜ôͪƥœ@ʶƧƨôƦƧô@Ȅô̎Ѷͪ"],encodeOffsets:[[117e3,29025]]}},{type:"Feature",id:"he_nan",properties:{name:"河南",cp:[113.4668,33.8818],childNum:17},geometry:{type:"Polygon",coordinates:["@@φ˜̎ƪ̐˜ɞȄɚ@@Ȃעó̎ŌѺ̒ôֆॢȃô™ƨŎƨōƪöƩ̑ڔɜԩ̏ɝʵƧ—əʵԬȃƨəԪ@@Ƨ̒ŏô̍υȁƧɚ̍ôóŋ@ɝƧŋõ̑σ—@ŏɜŋôɝ̒ƧɚôôطρóóɛƩ@óƨ̍ŏƧôóȄ̑ôƧóƥôóӐɛōɝŎ݇ñړɚѵֆ@ɞ̏ʶ@ʴƩöó̐"],encodeOffsets:[[113040,35416]]}},{type:"Feature",id:"liao_ning",properties:{name:"辽宁",cp:[122.3438,41.0889],childNum:14},geometry:{type:"Polygon",coordinates:["@@ƨʴƧôôӔƨô̎ƩɞН̎ͪ߼ͪɜ—ɞɚ̐—@ƨςŏ̒ôƦƨɜœô̎ƪôςǿƨͩɞȀƨ@@ɛςփô›óŋ@ʵφυƩʳö›॥փρѹס@əɛ@ͩࢯ@ѹʵρ—ƩʶφȀƧ݈̒۬óʸɝŎѵ@ԭԫןɛƧƨƥςɛ—υʶφО"],encodeOffsets:[[122131,42301]]}},{type:"Feature",id:"shan_xi_2",properties:{name:"山西",cp:[112.4121,37.6611],childNum:11},geometry:{type:"Polygon",coordinates:["@@ɚѺñŌɚšôȄѺ›̎ֆφóςȂ̒—ɜƨɚ@@Ȁƨŋôȃƪ—ѹ̑̐ŋƪ̑Ʃρρ›óó@ōɛɛ@əɜŏƦρƨ›ρѵ@ɝɛǿɜʵóօѹ̑̍ŋסô@ȁə@ɝȃ̏—̍Ʃυ—Ƨô@Ȃ̐ظóОó݊φք̑ʸ@Ȃ̒ʶôȀ"],encodeOffsets:[[113581,39645]]}},{type:"Feature",id:"an_hui",properties:{name:"安徽",cp:[117.2461,32.0361],childNum:17},geometry:{type:"Polygon",coordinates:["@@ó̎̑Ő@ƨƪ˜Ѷǿɜ̑φ—Ʀʵ̐˜Ƨѵôóƪôôυς—ƨȂɞŏ@̍ԫôò̑ƥ—óȃѶͩƧƥôŏѺœôŏƦ—@›ƥͩƧ—ôȁυó@̑ƧɛѵʵƩƪѵ˜̑ʸóóôŏρó@ŐƦƨƥŎσɝƩœ@̎̍Оɚ̒ρƨƧȂôɜςôóظəó̑ƨóɞɛŌ@Őτ˜ö̒ƨŌ@ɞôŌ̎óƨəφȂ"],encodeOffsets:[[119431,34741]]}},{type:"Feature",id:"fu_jian",properties:{name:"福建",cp:[118.3008,25.9277],childNum:9},geometry:{type:"Polygon",coordinates:["@@̎›óȁƨӑ̒—̎ɚƨͩφŐƨɝ̎ŋóŏρ—@ōƨ›òʳəóƨō̏˜õɛƧ@ƨѵƧōəŏóŋƧô̑ɝɛʳƥ@@óɛõ@Ƨ̑ƧóȁəƧ̑—Ƨ̐@ɚəОƧ—Ƨɚóñ̑ŎóʴƨœƨԬɞȀóŐɜȂó̎ѶʸôƦƧ̐Ѻ̒ɚƧѺɜƨȂ"],encodeOffsets:[[121321,28981]]}},{type:"Feature",id:"zhe_jiang",properties:{name:"浙江",cp:[120.498,29.0918],childNum:11},geometry:{type:"Polygon",coordinates:["@@Ѷʶƨɜ@̒φôóȂƨ˜Ʀͪ@œ̐˜Ѹ̍τȂ̒̑נŐמôƪƧôӑ̑›@ƥρͩƨօ̏@@υɝó@ŋɛ@ôƩəóƧѵυó@ƩɜŋƧ@̍ŌƧɞυŏƧͪ̍ə̑˜ƧӒôȂ̍œ@˜óφ̑ɜ@ŎƪȀ"],encodeOffsets:[[121051,30105]]}},{type:"Feature",id:"jiang_su",properties:{name:"江苏",cp:[120.0586,32.915],childNum:13},geometry:{type:"Polygon",coordinates:["@@ôɞ̎˜φНôŐɜŏ̎Ȅƨ›öǿƨ@ôɜɚšƨʴ̒ôôó@Ƨ̎əԮȃԪૉöͩ̐ƧòʵφƧôʵ@óړɜóŏɜǿƧ›ɝρσȁѷ̎̏—ƥ˜óŐѹ›óŐƨƦѵͪôȄƦ˜ñ̒Ԭó@̎ɝŐƧȁρ˜óφƩóóôƨѶ̏—ƥʶυ˜ɛ̒ѵȀ"],encodeOffsets:[[119161,35460]]}},{type:"Feature",id:"chong_qing",properties:{name:"重庆",cp:[107.7539,30.1904],childNum:40},geometry:{type:"Polygon",coordinates:["@@əȂòɜƨ˜ѺɛƦȁ̐@ƪ—õŏφƥòȃƥ̍Ƨôυ̏ƧôñóóôɛŏƩôƧƥôƧóυƨœ̒ѹôœƦȃ@փƥɛ̑@@ɜƧó@ɚƧ@ñφσõ@ŎɝôƧ—@ʵѷóƧʵó˜@ŎóŐó@ôȁƥ›ó̒υôóʶə˜ƧȄς̎ƧȂôƨƨƨφɛ̎Őƨʷɞ@ςԮóŌôôφ@ɜֈ̎ƨ"],encodeOffsets:[[111150,32446]]}},{type:"Feature",id:"ning_xia",properties:{name:"宁夏",cp:[105.9961,37.3096],childNum:5},geometry:{type:"Polygon",coordinates:["@@ల̒ôޠφӒςôƪͧυևɜŋѺó̎ȁ̍ɛ@ѹס@@ʵƧȁôó@ǿ̐ŏöʵɝŋɛ@ô̑ƥóóƨƧ—ó˜ôœó@ƩôóƦ̍œóȀƨŎɛӒôŐυͪɛ@@Ȁə@"],encodeOffsets:[[106831,38340]]}},{type:"Feature",id:"hai_nan",properties:{name:"海南",cp:[109.9512,19.2041],childNum:18},geometry:{type:"Polygon",coordinates:["@@φɜƦʶ̐ôφô̎@ƨŎö@τʵƦ˜ԩ۫õН̏óƥȃƧ@Ʃəםƨ̑Ʀ@ޤ"],encodeOffsets:[[111240,19846]]}},{type:"Feature",id:"tai_wan",properties:{name:"台湾",cp:[121.0254,23.5986],childNum:1},geometry:{type:"Polygon",coordinates:["@@ô—ƩɝöƧɝѵəޣ̏ρƩԭóōóͪρɞƧОôԪ݈ଦѶɜ̒ɛ"],encodeOffsets:[[124831,25650]]}},{type:"Feature",id:"bei_jing",properties:{name:"北京",cp:[116.4551,40.2539],childNum:19},geometry:{type:"Polygon",coordinates:["@@óóó›υóôƥ@ŏóóə@ƧŋƩŌρóɛŐóʶѶʴƥʶ̎œôƨɞ@óŎɜŌ̎̍φ›Ƨŋƨʵ"],encodeOffsets:[[120241,41176]]}},{type:"Feature",id:"tian_jin",properties:{name:"天津",cp:[117.4219,39.4189],childNum:18},geometry:{type:"Polygon",coordinates:["@@ôôɜ—@ƨöɚôœôôɚŏ@óƥ@@ȁƦƧɜ@óƧƨƥ@›ƧóəН̏óѷɜ@ŎƦƨóО"],encodeOffsets:[[119610,40545]]}},{type:"Feature",id:"shang_hai",properties:{name:"上海",cp:[121.4648,31.2891],childNum:19},geometry:{type:"Polygon",coordinates:["@@ɞςƨœɛȀôŐڔɛóυô̍ןŏ̑̒"],encodeOffsets:[[123840,31771]]}},{type:"Feature",id:"xiang_gang",properties:{name:"香港",cp:[114.2578,22.3242],childNum:1},geometry:{type:"Polygon",coordinates:["@@óɛƩ@ρ@óœôȀɚŎƨ@ö@@ōƨ@"],encodeOffsets:[[117361,22950]]}},{type:"Feature",id:"ao_men",properties:{name:"澳门",cp:[113.5547,22.1484],childNum:1},geometry:{type:"Polygon",coordinates:["@@X¯aWĀ„@l"],encodeOffsets:[[116325,22697]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/chong_qing_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"500242",properties:{name:"酉阳土家族苗族自治县",cp:[108.8196,28.8666],childNum:1},geometry:{type:"Polygon",coordinates:["@@XJ°œlJX@lbl@XbV@VLnJlxnbšƒUU@IVK@lVIVwnJlU@n@J@L@Jn@l_nWVLVln@@blLšmV@@xœÔ‚`nœ™xV‚ÈLlx„LVxVVšƒV_U»VWn_m¥XwVmnX°ƒlmUUVwÞaVƒk@a@mmIUa@™mwk@™ƒm@@U¯a@UV@@K™@ykkmwkV@kU@ƒÑƒVkKWLÅamaUm@kyU@WkU@Ua™IUašVaUUmUUa@aVLXKWa¯UUbmJXnWnX`l@@xkzWÆ@V„LU¦‚x@b@JkIkJ@LmbUamJwm@óxƒnk@V„@x„ŽVnUVmVUVŽUbVlUbkXWŽ"],encodeOffsets:[[110914,29695]]}},{type:"Feature",id:"500236",properties:{name:"奉节县",cp:[109.3909,30.9265],childNum:1},geometry:{type:"Polygon",coordinates:["@@WVXb‚UnK@x@b‚²kxmKkl¯_ƒVV°™VU@bnKVVV@@nkŽ@n›bn‚@š°@VLČUš@°WV@V™nU@InKVl@nU„b˜KnX„WlknLlKUwnalLša„VlUXmWk@UU@UWWIUyķ¹XaWW@X™ƒKUIVm„U@W@UVU@KV@n»VkUkÇmUmVIUmULUbm@ƒwUaƒKkkm¯ÑUL@bWVnx@VmxUI@„klmkkK@aƒK@IlJ@I¯ƒk@mak@mnkJVL@bV@Ub„„W`UUUV™I@VƒU@VVbUJVLUVVbUX„VVxk¦VJUnVxnVVUšJV@Ubl@@bXV@L"],encodeOffsets:[[111781,31658]]}},{type:"Feature",id:"500238",properties:{name:"巫溪县",cp:[109.3359,31.4813],childNum:1},geometry:{type:"Polygon",coordinates:["@@nLWbX‚VLVU„V@KšIVl@b„@lbšU„VnU@JÆU@V@n°KĢUl@VbÞKšVš@„_„V‚KXU‚U@KXƒ@wlkkU@mWKUU@UôJ@XV@œaVmÞIVaVLƒƒ@»kmƒ@ƒUkL™U@aU@WWƒLUUU™™KkbƒwWa@KU@kaƒXmW—LƒamVk@UmL@JmVUšU@¯X™@ċVUK¯@ÅnWK™LkKULWK@UXK@wW@™LkV@bVLƒlXn›`¯xU„°LnŽlV@n°Lnl"],encodeOffsets:[[111488,32361]]}},{type:"Feature",id:"500234",properties:{name:"开县",cp:[108.4131,31.2561],childNum:1},geometry:{type:"Polygon",coordinates:["@@n@na‚I„wš@@VVK„LVbVxnVÆUnanKWXamKmk¯K@mkUm¯KVƒ°w@Wm@UIUUlKUU@a¯KWanwmUXamKkUWUnU@KƒkUwWKXaWLUWkImaUUUƒƒKka±k@lƒ¯w™wmbUƒ™ƒkXm@UJkIW‚XXƒbƒmƒ„UJ™XUV@°šKlšlVXV@xmbnV@blV@VšœU`UL@V™a@bULlb°VXbܚ@V@bƒL@J„xnLVb@lVb@V@@z˜bXWšX„KVLV‚š@@bUVVL@b„„lVna@ll@„zl@@J"],encodeOffsets:[[111150,32434]]}},{type:"Feature",id:"500243",properties:{name:"彭水苗族土家族自治县",cp:[108.2043,29.3994],childNum:1},geometry:{type:"Polygon",coordinates:["@@„Jlb@nVV@bXb@ÆlL„Ul`nVKU¼VxkbW„nlUxlXX‚@°°WnnJ@VUn@J„k°L@VlV@nUJ„x@bVVVz@VnLla„KnalVlIUŽ„¼@nV@@anKUwVal@UlJœƒlI@akU@UWXKVI‚¯Uak@@KmkXWÜkXWykIWwXw@laXamkVUUym_XmlkkmmakwmIUKU@Wak@kaW@kI¯›WIk¦VŽƒUUƒmaUV@XkVUV±aUb¯b¯¥m@@ImJ—@mƒmL@kUKUkkJƒbV¦"],encodeOffsets:[[110408,29729]]}},{type:"Feature",id:"500235",properties:{name:"云阳县",cp:[108.8306,31.0089],childNum:1},geometry:{type:"Polygon",coordinates:["@@lb„LV„VVnblJVXXKWbXLVx„l@LmVXVVl‚nLWbnVmxXb°L@bVVkLVVVJn@@X‚‚œ_Wm„kUK@alUšKX@@xWL@VXLVKlLšKXLÆm@™mœa@ml@mU@UUmL@aVšUU¯„U°`lknLlw±@a@wmLVWaXU@KWU@ak@VaU@™IUVmUUwVmUIl¥UwƒUVWUaVUUKVIUa@UUUUJƒUUm™kƒ„nl@„@VWV@L¯aUb™Ulxƒ@@b@VULUx@VUxVV™U@bU@mxU„U@mUVŽklkkƒ@WxknlxK@amLƒKU„K"],encodeOffsets:[[111016,31742]]}},{type:"Feature",id:"500101",properties:{name:"万州区",cp:[108.3911,30.6958],childNum:1},geometry:{type:"Polygon",coordinates:["@@ĸĊVI„ƒ„n„aWWXlJVIn@lWš„V„našx°xk„l@²Ž‚LVƒ„LnK@b‚LkwlmXw„@lllkUnVV@VƒnwV@@ašVUUVw@UVwVK@U@a„@kwšVVa°b@KXU@U@ƒmk„ƒÇсaml™kUVmn@VULU˜m@kUVkUaƒwUWm@Uw¯„mKUUmVUUULUKU„W@XbWVkaWwkUU™ƒ™k@maUbmbVlk¦ƒxUVUIWVU„kJVVkL@UmJ™UUVU@lLUVU„lx„@@VbƒJ™U™L¯¤@Vƒ„"],encodeOffsets:[[110464,31551]]}},{type:"Feature",id:"500229",properties:{name:"城口县",cp:[108.7756,31.9098],childNum:1},geometry:{type:"Polygon",coordinates:["@@VK@w¯L@m@UÅV@ImVƒU™Vkaƒ@@aUk™J@LƒUUVUKmLmbÅVmUUwUaƒKUL@U™@ƒxJmbm@nVJ@X@VkV‚n™lƒLXx™@ƒb@bUVƒLU`UnƒbU@@ŽmVVX@JX@VLVVšklV—„‚`@bUL@V„LVKn@‚U@„UJkn@lmLmK@X@Jn@mb„nÞWVXnJ‚k„KČÑÆ@VK@knaÜmXlUČW°kôÇƁ@a@yÞ_VmƒUnU@K"],encodeOffsets:[[111893,32513]]}},{type:"Feature",id:"500116",properties:{name:"江津区",cp:[106.2158,28.9874],childNum:1},geometry:{type:"Polygon",coordinates:["@@„InWUUlU@LVašlX@°²lÒXxlK@Ul@@Un@UaVJ@I@W@UƒUUVUwVIUKUa‚UUVwn@Üx@XUlnn‚bœJ@¥VklKUUlk@ynU@kVƒUUVWnI@¥V£VWVIUKU@UVƒa@n@Vm@@nlUaVkUwƒJ@blLkLW@XWmXkmmLn™@m@U@UVm@™„UVUUlakUVa„ƒVkV@@wnaWUk@VwkƒlmVIkUUxmJ@U„™@KƒIkx±V@IUm@K@IUKkbWKUbn„m„@bmVnbmb@xkxUJ@ULW`@bX@WVXL@Vƒš¯„mk¯@UJ@VmLUaWnX@WJ@nkKkxW@UIV@@KkImmkK@UW@XaWIU@U‚ƒIkbWb„xXŽlLVbnV@bWlX@VxVLnl@nÆÞVÜ"],encodeOffsets:[[108585,30032]]}},{type:"Feature",id:"500240",properties:{name:"石柱土家族自治县",cp:[108.2813,30.1025],childNum:1},geometry:{type:"Polygon",coordinates:["@@„š@kl@š¼UbmVXJ@bV@nxVIVJULVVk@@LWbnJVU@bVbUJ@blLXnWV—@mbnV‚@V„„bn@VJVLnaVanbl@„šVšlVXxlbXUWaX@VƒUUVwUUVm@I@WmI@a„mlLœ™lK@alwnUV@kóVaƒÝk@UlbVK@™VU»VUUVWUƒ@U`ULkwm@@KmU@knKƒ»VkJkUmbƒLkbmK@UUyUU@aƒwm@@XXJ@VVLVVUbVnUJVX@K„„k`WXXJWXUbmW@bkL™Um`Xnƒb@JVL@LU@™°VVXKVnUxVLUbmJ"],encodeOffsets:[[110588,30769]]}},{type:"Feature",id:"500237",properties:{name:"巫山县",cp:[109.8853,31.1188],childNum:1},geometry:{type:"Polygon",coordinates:["@@kVƒU™bkKmbVxkLmKkllbV@@LXb„xlašLVšVV„KXXV@@bšVlK„V„@ln@¼°KXa„U@Ulw°JXalIUa„ÝWXW@kVU@ƒVUVWUUUamUw@aVamwn@VUUƒlLXWm£@wÇĉkKklmLUÒ¯ƒWn™@ğ±kwmaWm¼U@@LUV@V@XƒVUnVJ„LWš@‚XXWbĸºVzXJVXV@@VXlWn"],encodeOffsets:[[112399,31917]]}},{type:"Feature",id:"500102",properties:{name:"涪陵区",cp:[107.3364,29.6796],childNum:1},geometry:{type:"Polygon",coordinates:["@@nèVblĖVVnLšŽ„@šx‚V„n@nšJ@L„UVVX@lbUJV@@nn@VVVK@z„˜V@nzVJVUlmX@@_VVVbnaVal@@knW@wnaƒVK@aVI„J@£kUVW@‚wXUVJ„amƒ@Ikƒƒƒƒ_X¥ƒ@WwkKkwmŽ™šƒkUxƒnÅmm¥™WV@Um@UlVL@JU@@Xƒ@UVkKVk™KVk™Kkb@bmJVXU„VVUbU@@`W_UV¯b"],encodeOffsets:[[109508,30207]]}},{type:"Feature",id:"500230",properties:{name:"丰都县",cp:[107.8418,29.9048],childNum:1},geometry:{type:"Polygon",coordinates:["@@Þè@XUK@LlV@blbUJ@„„V@bnV‚@VVVXU@ƒlbXal@VXnKV@maXUރ@amk@aVKXV‚anbš£°mnIVaUKVwUmWLUUš¯V@@KUK@I„aWmn_šVlK@anXVaXWWIXWl_ƒƒ@LUWVIUmVaUUUK@UWI@Wn@VI@mkU@U¯Kƒl@ImVÅLƒwU¤óbUU@wWXkmm@LU@@VUIWVUL@JUnƒaƒx@Jn„ƒbUIWVx@ŽUXlV@¤ƒIUJ@bUL„Žmb@xmX@lk@UbmbUaUU@`W@kn"],encodeOffsets:[[110048,30713]]}},{type:"Feature",id:"500232",properties:{name:"武隆县",cp:[107.655,29.35],childNum:1},geometry:{type:"Polygon",coordinates:["@@l„„w„bVm@IVKXUVJ@UV@@KnnWlX@xVVôaV£„xÆKnUVm@UmIXm¯¯@WkWVwmkXƒlaUwV»ULmk_ƒVkK@ÅWa@aUU@mkaƒIƒb@‚n¼ƒnm‚_@mmK@UƒLUVVmI@aUJ@XWJ@U`UIkm±kk@@lULmUmKUnVšnlUVmI@VkVlx™bkIƒVmLUxkKUŽ‚Xš‚n¦Æn„mVw„lš™nlxlLXx„@W¦„`„„"],encodeOffsets:[[110262,30291]]}},{type:"Feature",id:"500119",properties:{name:"南川区",cp:[107.1716,29.1302],childNum:1},geometry:{type:"Polygon",coordinates:["@@VšUbVJVUn@VLX@WVXVVI@VUVWxU@mš@ĊX@@¼V°aVUX`@_V@VaUUVƒUWnI@alašLUlšLUllLVU„@@WV@@IUKVkn@@VlLVwnK„UlJšakwlU@UnJVUmkU™VmXa@wVK@UUw™@VƒVI@akƒ@alInwlKXUmaUW@wWLk™™KVak_ÇaUƒƒV@šXbƒLVxUlWIk@UK@V™@ƒkU@VbUVUlVnƒLUV@lVXmxkV@L@V@Vk@WbUwmL@JUI@xVxkx"],encodeOffsets:[[109463,29830]]}},{type:"Feature",id:"500241",properties:{name:"秀山土家族苗族自治县",cp:[109.0173,28.5205],childNum:1},geometry:{type:"Polygon",coordinates:["@@XlV@lzn@VŽnbÆbXKlL„U„ÒV@@llUnxll@zšŽ@LU@@V°b@Vn@š„l@VÑUƒnK@UšU@aUaƒkVm@K¯wƒklmnn„Ul`nI@almkIUwmWVkUaƒkkJmUUa@K@aU@@_m@@wUyVUUa@Umƒ@awl@Wka±„UkUykIWV™b@bUVk@›aU@UXU‚UIWakUWmUxUV@nUVWbšŽ@XXVVŽmXXŽ@VƒbVLkVWx"],encodeOffsets:[[111330,29183]]}},{type:"Feature",id:"500114",properties:{name:"黔江区",cp:[108.7207,29.4708],childNum:1},geometry:{type:"Polygon",coordinates:["@@VX@V@LV@VJUL@lVnnxlb@VXV‚XV@@W„@UIVK@kUKna@£VWUaVUUalIVJVIUW„_lm@bXKV@mn@J„UUw@KnIVll@VanLVmUkVKXLVKUIVamw@UaU_lw„KlwUWV_Ua@aUa@KUšwm›_›Ó@wU@™nkK@am@UkUKmXk`m@@I@K@I@mkVmIUxUJ@kUL@JVV™„lnklWnn`VzUVnlWbkb@WxXxlJXzWŽÛlWXnl@Ll@Vb°UJWLX@VlV@bkJ"],encodeOffsets:[[111106,30420]]}},{type:"Feature",id:"500117",properties:{name:"合川区",cp:[106.3257,30.108],childNum:1},geometry:{type:"Polygon",coordinates:["@@XKVXlK„ƒVL@UnV@aValXXK„U@WVwUaVU@IV@@aVW„L@U@anVV@@bVK@UVL@bnJWL@VnUnb˜@@JnIlVl‚@@bXIWbn@UKVLVKXLlaV@VVnK@bVL„m„IVƒ@KmknUUWVI@aVJ@_„WU_VmUwƒU@K™ƒVak@am¯mJU_UJUkU@WkIV`UI@JV@LmmU@@mƒbUzś™@„VK@nUKƒ„ƒb™akb@UWK@bkVVbV„Û@@`ƒXk@WŽ@n@lXL@bmb@VVJUn@JnUlnUlmX@`XLlbkJW@kzlb@`@b@b"],encodeOffsets:[[108529,31101]]}},{type:"Feature",id:"500222",properties:{name:"綦江县",cp:[106.6553,28.8171],childNum:1},geometry:{type:"Polygon",coordinates:["@@@¦‚@X„lVX@@UVKl„VUX@lanVlUVbXWVXVƒ„VVUnKVUlwUwU@UJ@nmVkUV™lwXam@VaUUUw@W@kk»mV@UmKkwVKVUU@@LUKVI@mV@XVWxnXVKUUUK@wWU@UUWnUlLXa‚mUI„am@wI@K@amIm‚UUkI@m‚akUkKWUUanƒ@wƒamLVxk@UVmUUL@Vm@kV@I@ak@@bWVXJlLVbVL@š@bn@@`Un„@WbUKULWVXbƒ@UVmbX„WVƒb@bVmxUKUƒV@šUn@V@V@nmšnKlnnWWXX@lKkK@a„IVxUlVb‚k@mn@@U@m„bVUV@VLUJUXU¤"],encodeOffsets:[[109137,29779]]}},{type:"Feature",id:"500233",properties:{name:"忠县",cp:[107.8967,30.3223],childNum:1},geometry:{type:"Polygon",coordinates:["@@VLÞĊ„U@Wš@¼V‚„@lk@w²mlšVUœ„llšVnI@VlKUUlIVƒXUVJVU„wl¥UkUKUIm@ƒaUƒ@mUna˜@XUWmkK@aVIUa@aUVmIXa@Kl@UUVKUIUJmwU@@aWInUVa™»k@@lƒ™¯n™¤mabWUUL@bnl@b݄WVnbU@mLUWk@Wbka@„WVUU@UmUmVkUULV„lVUx„l@L@VƒbÈÒlb"],encodeOffsets:[[110239,31146]]}},{type:"Feature",id:"500228",properties:{name:"梁平县",cp:[107.7429,30.6519],childNum:1},geometry:{type:"Polygon",coordinates:["@@XLV@VV@b°°nšƒnkb@bƒšnJWVXblIUVšxWnUJnVVLVU„JlUnLVK@UnUVJš²nKVbVKla@aXlJ„k„Klb„ƒ@U°£šKšV„IUa@ƒ@kwVƒVUkKV@VUkk›ƒUVk™±n@xklƒ@U@»™‚@XƒVÝĉUJnxWb@UX›KkVUbUKWUkVmkkLU`›b"],encodeOffsets:[[109980,31247]]}},{type:"Feature",id:"500113",properties:{name:"巴南区",cp:[106.7322,29.4214],childNum:1},geometry:{type:"Polygon",coordinates:["@@nxnVlJlUXLƒ¦@x@Vl@nKVVX@V_V@@KlVXU„@lKlxXIl@ÈĊ@Vl@n_VJlŽnVlnb„²VVVJVVmUUkĕUamçU@»W@@ĉn™V@XwVU@UUJWUXUW@UKm@UVUIVaU™UVmLUVƒUU„UWWXUakVmUkbW@UVkƒUL@VW@kUWƒ@mJUXVVU„@lmV@zklVVkLUl@¦›I"],encodeOffsets:[[108990,30061]]}},{type:"Feature",id:"500223",properties:{name:"潼南县",cp:[105.7764,30.1135],childNum:1},geometry:{type:"Polygon",coordinates:["@@@a@a@_kalyX@lIkaWK@_nWVkkmmV@IVmUI@Una@aWK@k@mkbWaknmJUk@mk@@kUal@Uaš@Wa@aXLlwUKlkkƒ@KmI@VUJ@Lk@@VUUmL@amJU£kKUaWakLmU@bVVUbnbWV@xkL@bUb‚xUxVbXJVbUVWIUVU@kLWxkKWV@n¯VUbU@@VVX@VmaUL@VUK@VVbn@lVnI‚@@lnLULm@Ub@Žl@na„@lK@XVVkJ@b@zl@@VnV@bVb@J@bnXV`lXXmVI@W@InbV@@aVKUblKVLUanLlmnLlK"],encodeOffsets:[[108529,31101]]}},{type:"Feature",id:"500118",properties:{name:"永川区",cp:[105.8643,29.2566],childNum:1},geometry:{type:"Polygon",coordinates:["@@@b܄nWVLX„lxV„VxXxlVn@@bVblK@a@UnLVJV@@UnLVU@VXaVKVXš@n`WUÿ@IUKlaUUUkWyUÛÅÝ@mmkUKUwW@Xk@amUUakKWƒwXaƒK@VVLklƒXVlkxV„UL@bm@Vxn`ƒIVxUVkLVšUšl@@lkXmmƒVUn@VV@Xb"],encodeOffsets:[[108192,30038]]}},{type:"Feature",id:"500231",properties:{name:"垫江县",cp:[107.4573,30.2454],childNum:1},geometry:{type:"Polygon",coordinates:["@@šĊ°¤nҘ¼œaV_lKnllUXVVLValUœLVW‚@XamwVIUKkaÇфa@U@KƒkVwkUUƒVKlVnU@aƒU@ƒVIka@akU@KVL@WÝçUV@Vmbů@L™KƒnnJW„ƒVkxlL@VX@VxmnXVWxUb@bkn"],encodeOffsets:[[109812,30961]]}},{type:"Feature",id:"500112",properties:{name:"渝北区",cp:[106.7212,29.8499],childNum:1},geometry:{type:"Polygon",coordinates:["@@@bVVXL‚a@lnbWn@L„@XVlK@VVLUVlbkLUKVVVL@VšnX‚VL@VV@UbVb@x@¦UxVb@bUJƒL@L„VVxlK@™nk@U@W„UVLlKXV„@VblU@UUKVU@wn@VJVanLlkX@VaVK™¯@a@U@U@ƒVaUK„kUUƒ±maUkm@UUkbm@@Vk@@JƒwU@Ub@I@JmwUL@aƒ@@KkVÇLkƒWkƒ@kUU@@xUVmKUnllUb"],encodeOffsets:[[109013,30381]]}},{type:"Feature",id:"500115",properties:{name:"长寿区",cp:[107.1606,29.9762],childNum:1},geometry:{type:"Polygon",coordinates:["@@VVšU„bX‚lX„¥l@XnVmlxUx„@@blVnnôĀlm@aVaXwWUnmUwW@@UkKlw„UXƒmI„mšL@KÆ°na@UUImyU@ƒ—@yULUUm@@mU@VIkaW@UUƒV@K™I@mƒmU™wƒ@™mKUnU‚UIƒlVLUb@„@V@V@bš°ULUbW@klmKUbUIm@@xUVVL"],encodeOffsets:[[109429,30747]]}},{type:"Feature",id:"500225",properties:{name:"大足县",cp:[105.7544,29.6136],childNum:1},geometry:{type:"Polygon",coordinates:["@@XUmaVaUU@anVlKXbValU@aV@@IXKš@@bV@VxVK@UXLlUšJXa@_‚@@aVK—ÅWVkwWaƒƒwUa@am@kUWLU@kWmX@ykI@W@UV@na@LlLV@UƒkwWƒUKmXX`mIVl@bXLWVkbkkƒx@`VXm@@J@U@UUKUxk@WbUIVl@VXLW„ƒJUkUlUImxXlmb@X@VUJUnVbšW@UV@@VVX@bnW@LVxUnlJUV@n„@VxVIn@l`„UVVVL"],encodeOffsets:[[108270,30578]]}},{type:"Feature",id:"500224",properties:{name:"铜梁县",cp:[106.0291,29.8059],childNum:1},geometry:{type:"Polygon",coordinates:["@@VblLV¤nI@bnKVV@Ul@@KVI@UnJ@Ll„klVLkxWK@bXb™@Vbk@Vb@ll@@nVlnIlmXblaXl@„W@_Ü@UƒUalU@aXL@Vlašb„a„ƒVL@mUL@ƒUUƒƒÇXUW›X_WaƒƒUƒ»m_™@UWULWb@UUVmK@VU@UImK@V@bkL„x‚„XblxXU˜ÆUL@b@@`Wb™IkVWK@VULUwU@@a™@WL@JU@@bkVUb"],encodeOffsets:[[108316,30527]]}},{type:"Feature",id:"500226",properties:{name:"荣昌县",cp:[105.5127,29.4708],childNum:1},geometry:{type:"Polygon",coordinates:["@@VI@U@WnaWknwVJVkVl„IXƒWK@UUkVJXal@VwVL@V@V@In@UW@_„wlllaXUWK@aUknJW_ۃ@aWaU@@UVm„UUaUImJVnÅUmVUm`kUUVWLnVU@VVmXƒK@„nxmŽULkx™ImJ@nU`@X@Vkn@`@nlV@nVJVaX„VLnK@bVV@nV@lbXWš@"],encodeOffsets:[[108012,30392]]}},{type:"Feature",id:"500227",properties:{name:"璧山县",cp:[106.2048,29.5807],childNum:1},geometry:{type:"Polygon",coordinates:["@@XzVlVVkbVL@JVĀXŽ‚¼V„„„XbW`XœWVȎ„„VVšŽVkV@@UXa@alK@IƒƒU@UKWUyUI@wVUUWVak@VUkƒW¹@WXI@yVIUK@kWwkѯ±W@™kUb@KkVVVmXƒJ"],encodeOffsets:[[108585,30032]]}},{type:"Feature",id:"500109",properties:{name:"北碚区",cp:[106.5674,29.8883],childNum:1},geometry:{type:"Polygon",coordinates:["@@X‚VLV@„„@JkL@bWb@VU@UlƜVy„a@nV@nn@KU@IVJU_lJXV@VlVIV`nIn°@b‚lUbš„„KVI@aUaVw@¥@wUaVaU@@UUKW™m@UUKUUVLlKkaVUUK@UkLWUƒ@@KXmma@kbWKUU@aUamLnÞ@VWLk@@Wm@ULU@@U™KUVWI"],encodeOffsets:[[108855,30449]]}},{type:"Feature",id:"500110",properties:{name:"万盛区",cp:[106.908,28.9325],childNum:1},geometry:{type:"Polygon",coordinates:["@@VIV@@wVJ@InKVxXal@@U@U@KlUnwUW@kVU„KUmVkUa@I@KW@@bk@@mƒU@m@k@a@aƒIUxmJk@ƒwULƒwkKmVVX@VXV@xVLVVULmWXwWUU@@nUJVL@KV@UVULlxnL@VnUl¼@l@XVxVVUbn@WbkxUšlVnU@m"],encodeOffsets:[[109452,29779]]}},{type:"Feature",id:"500107",properties:{name:"九龙坡区",cp:[106.3586,29.4049],childNum:1},geometry:{type:"Polygon",coordinates:["@@XK‚L@Vš@XbV@lW@UV@@VXIV@U™VKlL@KnnJ@VV@VU@I„@@mVUVWUUmL@V¯LUK@UV@UU@a@U@yU@WLUK@X@KUVmL@ƒ@aXI@w@ammVk@WÛwm@UxVVVbVLUJVxVU„V@V@X@JUIVbm@@Vk@@VkL@lVLUJ@zWJ@X"],encodeOffsets:[[108799,30241]]}},{type:"Feature",id:"500106",properties:{name:"沙坪坝区",cp:[106.3696,29.6191],childNum:1},geometry:{type:"Polygon",coordinates:["@@Xºl„UVl@UbVXUV@xVJVzXJVUšL@VV@VKn@@Xl@XK@UmÝnKVbVakkVm@k„ƒUK@UmIm@LkKULVšU@WJ@UU@@VkXU@Wa™@@UKWL"],encodeOffsets:[[108799,30241]]}},{type:"Feature",id:"500108",properties:{name:"南岸区",cp:[106.6663,29.5367],childNum:1},geometry:{type:"Polygon",coordinates:["@@VV„JVL@bUVVnl`XIlwXJlw°nnl‚IXW@UÇĉk@WJkwkLƒ@WVkU@LU@U`W@UXUV@n"],encodeOffsets:[[109092,30241]]}},{type:"Feature",id:"500105",properties:{name:"江北区",cp:[106.8311,29.6191],childNum:1},geometry:{type:"Polygon",coordinates:["@@nLVU@wV@lV„@Xll„ÈKlU@L„@@bVKnx@I@JVaV@„x@Il@@Un@laVVn@mkUIm`k@WXJmk¯mkxWIkxWJk_UmVUUKƒ@UU™@ƒ„@l"],encodeOffsets:[[109013,30319]]}},{type:"Feature",id:"500104",properties:{name:"大渡口区",cp:[106.4905,29.4214],childNum:1},geometry:{type:"Polygon",coordinates:["@@k@@U@w„¥WKkVkImUmwa@b@xWJ@b@„nKVU@L@WVLXKV@@z@V@bVVU@@VVL°K@U"],encodeOffsets:[[109080,30190]]}},{type:"Feature",id:"500111",properties:{name:"双桥区",cp:[105.7874,29.4928],childNum:1},geometry:{type:"Polygon",coordinates:["@@WwUwU@kK@KmbU@@V@XlJ@znWlXV@XK"],encodeOffsets:[[108372,30235]]}},{type:"Feature",id:"500103",properties:{name:"渝中区",cp:[106.5344,29.5477],childNum:1},geometry:{type:"Polygon",coordinates:["@@VLš@VV„@VL@aUKƒIUUƒ@@JUVU@"],encodeOffsets:[[109036,30257]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/fu_jian_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"3507",properties:{name:"南平市",cp:[118.136,27.2845],childNum:10},geometry:{type:"Polygon",coordinates:["@@@knyƒk@ƒKU¥šwV@nkƒWƒzUmk@@lKUa@aVI@UƒKUamKUUVaUI‚@Xƒ@UV@K±IUVVlUbUbUL@KWUXmWk@KkXmmkŃKUƒ™a@amUƒbkUkKWUnwUƒÇwV™UUƒÝUKV£U™@ƒnKWwXLVKm¥@wUXkmWk@ƒ@wX@lU„@šyVImaXwVƒƒ@kŽƒnU@mbk@mlUXƒmU@mV@n@bnW@bUIWJ—ImVUKWbUK@nkKƒaU@W_VUUmWmL@UU@™bUWUL@V@bmVUz@`mUUVVbXL@V™L@lmLUxmVamXkW@xWbU„VbUxkU±@ÅUmmkLUbW@@`kLknVlV@lbXxlVUXVV™ŽU„U@UbWŽkIWVUUUJkI@llbUxVL@V™VƒUU°ULUmWXUV@VULWb@™xm@UaVLVKUa@ƒw@V›bkmVambUUm@@VkK@„@b„xlxX@‚„n¤@Xƒ@@lkLWV@Žn„V„kb@bWJXLWx@nkxmm™bXn@VWVUn@VnJ@bVXl@„™VJXnWbX`lL„UlJVI@Žœ@VXV@Vl@bn@@Æmn@VšxXU@mVIlxšVššnI„l@nVJ‚aXI@mlU@aXkVm°klmnVV_naš°@V@xܦXK„V‚nnUlVXbVK‚LXKV@naV@@VVl@@lXblXšWnLlbVK²nš@@‚VLUnlV@lƒXxô°‚V@UnaUUlKXLVUVVUbVVlUnJVX„@VW@an@lb„@nl@VU@anƒšUVW@kƒaUm@InVVKVU@kUW@Uam@km@kVa@a@™nwšU@WlI@mVI@WXaW_nƒ@™nƒlkkW@U‚¥@kV@Uw@wUƒ@@IXK‚¥VIn@nU@`@Xl@VV„LnašW‚bVaUwnU„@VIšKlV"],encodeOffsets:[[122119,28086]]}},{type:"Feature",id:"3504",properties:{name:"三明市",cp:[117.5317,26.3013],childNum:11},geometry:{type:"Polygon",coordinates:["@@lL@Un@VVna‚bnUlœa@U‚x@„VbULUKVbn@šw‚@XaVK@UVUXWVnVKV¯„VšU@UUKVwka@klJVIVVXUlJXVaV@VƒšUUVWkUWwkaU@UklmlK@_X@ValKnnÆV²@lVVwUaVƒXa@wlXnW‚bnUVwnK@kšK@UWKUaVUnV@_VynU@a@UVKVXšaV@@VnKnXVV‚UX`V@„blL@mVLXaVLnU˜JXIVJ@amX@a@mnUV@„nVWnkl@naV@„ml„@@KmKUam@UU@ƒ@UlKU™Vk™U™K@aVaUwV™U¥UIkJ@wmI@‚mbkwkVW@UXƒKULU`™IVKUa@LƒkkVmUU@WlULUWÅU@I@ƒWW™nU@@w@a@ƒUam_XyVIVWkkƒ@mwVKXUV@nw˜VXkWƒÅ™U@ƒaƒU¯KUnƒK@ƒ¯šmUƒLXŽVLnWVbVbUVm@Ub¯¼W@amƒ`kb™amLUUUƒ™aUXV`@x@XmJ@n@L@xkJUU@kU@mWm@kUUwUUVWl@VUkIƒy@kkaVUUm™IWVXbWxU@k„mVkK@nWVX¦WxU@@bkx@VU@WŽk@™kUbmJUUmkUW@_kKWKƒ@knV¤kIUKWLUbV‚@Wbk@@VWL@VkI@lUXVxUVU@@mWIƒV@a¯nUaƒaUV@„ƒJ™b@bÞ°VbUš@X™aUVmL@‚VXblŽnV„°˜n@Vnx„@VUUUlK@InJVb@„Vlnn@V™L@VWJU„x@XlJUVVVl@LUUUJ@Lƒ„@lUL°¦k˜V„VnV@„xV„„l@blLnlšLVaXll@šnVUn@‚xn@nml°‚X@lb"], -encodeOffsets:[[119858,27754]]}},{type:"Feature",id:"3508",properties:{name:"龙岩市",cp:[116.8066,25.2026],childNum:7},geometry:{type:"Polygon",coordinates:["@@ša„I@ƒVU„bVb°m@b„UXJ@nV@VUUwVW@klJ@UXK@Ul@Xa‚@UVaXKVLlJU£lm„@XLlL@`VXnlVVnIVašll@XV@@Ulw@aV@XwW¥XU@mlLnUlƒV@XwWaXUšJVnUVlb@l„zlJUVk@UXVVVxlVn@nXV@@lVVlI@w@K@mnI@W@wU_VWšbV„VVnKšbla„_n‚bX@°»Van@VUUaUamXUKW„K@a@Ukƒ@wWkXƒWW@wUU™Kw@_lyƒwUkU@@Uƒ@kamVmƒXašUVUka@Wk@»UUUVƒKkbWU™VUbk@mkƒxkƒƒKnIVUmW@kUKmXUmVaU@kU@m@KUWVkIWJ@ŽU@UI@wUUUa@KW»nU@mVkUmm@XwWU@ƒUUmL@ƒw@mnƒVUU@aWak@@amxU@UxULWVXbVLU`mbUImVU„ƒbn‚V@@bVn@bnVWxLmyUbƒIUKƒ@aƒVm™akbV‚UXW„UlKWbkV@„WLUlk@@nšbƒb@lkKmU@ƒUIWJkw¯UUVVxm@@XkbWx—›XKƒlUzWJkUUL@bmKkVƒ@@VUIUlWV@X„K@VkbWx°xUb@LUbk@@VWb@LXJ@VWXU@@bUVV„VVn@VVlLn„@l„@‚xk¦Vx@bVJXbƒn@JlnXxV@@„nJ@X@V@lmx„bUn@xVL@VVKlL@l„„nLVaVL@xkl@LƒxVl°š„X„WVX„Vl„œJWnxlJ"],encodeOffsets:[[119194,26657]]}},{type:"Feature",id:"3509",properties:{name:"宁德市",cp:[119.6521,26.9824],childNum:9},geometry:{type:"Polygon",coordinates:["@@@LVKVaVaUkVU²J@LVU„@@W‚VJUbVVnLVb„L@VUJ@bVbkL@Žl@Vn„y„XmlU@™xV¦„L@Ž„lmz@lnL@bVVšbVb@l„nšKVk„Vl¤@zXV@šl@XJVLVKnXVK‚VnU@wUm@šKUƒ@UlVlw@U@U@ƒUaUKlU@kXKlmXIWKXaVIVUVK@KU@@k„JVUnLVJUL@V‚IVa@VnLšKUnl`Vb„V„V@š‚Vbn@Vzn@lKnVlI„VVKUalkXJl@XXVWVLVUUmVU@Unm„£lK@Uk@WUXK@U@WVwVkšƒĠkĢÇ°aUÅUwmaţƒɱUÇa™w„±V¹XalKôx„@„UVaÜʓͿVóbÅLƒJm„¯Vk¦ƒŽk@mamXkKUƒUL›akbk@mV@LkJWb@Vk„mXk@UVmaUV@amLUKUamI@KUaU@WbU@UUUƒUIWJUkm@šƒw™Kk„VJm@kxǁVƒUK@mUVUkmlkkVm@amwƒLVWU@UbVLkšUbƒ@VƒmK@XaVWU_VJnwV@@kUmWakxƒ@kwWakIWxnbUJ™zƒ@kVW@@x@„XllnVW@xn¦ULWKXxmL@„VšU¤VL„ÞVVUšÈxV„mxXVlLlV„anV@bšbV„„LlÆnnlW@LXlWnXV"],encodeOffsets:[[121816,27816]]}},{type:"Feature",id:"3501",properties:{name:"福州市",cp:[119.4543,25.9222],childNum:9},geometry:{type:"Polygon",coordinates:["@@lxna@nJ@xlIVJV¦UšVxUb@bšLšVUlVškL@V@„VVn@Vb‚Ln‚@LU„lJXblx„@lwXbVn@lU@mxUIV`UXWb@‚nLU„„@Val™UKVaV@UX„Knx‚bn@lUkllnUVnV‚@VLU„È‚lwn@UIlƒšL„x‚™n@VlXIVJV„VVV@XaV@Vb@LnJVbVLnK@bVUnbVUl@nWlƒ@UXalI@KnUl@laœbVKV„lLnWnbl@„l¥°Unƒ„IÆKôa΀U„a@UUwÇWǓIUWUÅVkƨm@ƒ@£@KmLU¤ULˣJ™kUƒVǟUUķ@ĉVƒKUk@Ñ°wôǚç@īšé@Åţ¥mīÛkm¼Å@ƒVķVó°ō¦U°ƒn@bVJXVVL@bUŽƒakLmx@xmxXzW`XbWnXV@bWLÛ@™aƒ@ƒaXbWVkaÝwU@mlWKkLWWkLUKULW@kVmVUU݁UamV—¤›n@xUVUzkJV¦lJU„"],encodeOffsets:[[121253,26511]]}},{type:"Feature",id:"3506",properties:{name:"漳州市",cp:[117.5757,24.3732],childNum:10},geometry:{type:"Polygon",coordinates:["@@@bl@Xb@bVVUŽm„@n„x‚@nKVV@„XVWxn@VnUl@nmVX¼@LVbVV@xVJV@@XIlJXU‚V@Ln‚@lVV@UbVnnWVL@lnXUVmJ„Ll„„wnll@VašUXVla„LVUVV@¼Xl@lbUV™VWbn„nUlb„@@VV@„aVUšmlUašUny@kU@Wkk@WaUVk@@ammk@@U@UlU@aUa@wl@šmXLllnL‚U@anVnU@L@VVV@KlXnWVnVanUšw@w@wm›nÅ@wƒaUam@Uk„mUl@@a„a@U@¥škôK‚wȯ°w@ŻkwǕaK›ÑÛk@ĕōřċ£ĵƒUKW»kÅŻLU@Ulġw@¤Vz™VUbkKUbmLmlULU¼UxmbXl@bWVƒb@bUnV‚UšVbULU@@VkbVL@`U@WX@ŽXV@b°„@b¯š@¤@Xm@@b@`U„VVUL"],encodeOffsets:[[119712,24953]]}},{type:"Feature",id:"3505",properties:{name:"泉州市",cp:[118.3228,25.1147],childNum:9},geometry:{type:"Polygon",coordinates:["@@Vl„xkz@`‚xšLVV@xXXW„Xl@xl„@V@bnV°™@„„LVm°L„V„bV@ƚX„Wl—UmxU@WVULnx„@llUXUJWzn`Vb@„@b@xV@šmXX@„@JÆVVXVKXkV@nVlU„l@KVbULšJV_VK„LVWX@lUVƒkIU¥lIVyVU@wœm˜£nUVWU@aƒm@UmWw@UX@@am™VUn@@aUUlUVanaWUXWmUnkšK@VšUlVVUUwš@XLWWX™ma@knm‚bVb„VXbVL‚@XJlInlšL„w˜mXóšw@çV»ÇçŋaķƧóƅóKġ°nÅUķƑUÇW@—¯xÇ°öÆlV„n@llšaš@„Lšbƒ`™@™„VšXVƒVx@V@bULVJUk‚Ç@ƒ¼ƒXUKk@mmULkaWbk@ƒx@UkL@a@K@U@UmKmbU@kV@UmVUbUmmXkW@LUU@U@KmVmU@bVmKkkWK™nk@@xVb@bkV@V@Vl@nn@bl@VUXbl@XlV@@lmz™VVbkŽ™nUVƒb"],encodeOffsets:[[120398,25797]]}},{type:"Feature",id:"3503",properties:{name:"莆田市",cp:[119.0918,25.3455],childNum:2},geometry:{type:"Polygon",coordinates:["@@VbނVVnUlUX@VKVLlKXXlKXL‚‚nkV@ÞxlbXUWa„b„@šbÜ@XK@aWUXmWaX_Wynw@wnwlK„bV@aUKWUUI@a„mV¯Ŏ¥ô¯ĸU„UÆ@n»¯aƿé@ţ¯nĉĬÝK™óó@™ÑU¼@è™xWô—nƒx™KmkkJWI@UKWaƒUUaamn@lnbWšXXWK™@VxUVkU™V@U™LmlnVWXXVmbUbkVVV@bm@UVnš@bW@@VXx‚n@V„n@bV‚UX"],encodeOffsets:[[121388,26264]]}},{type:"Feature",id:"3502",properties:{name:"厦门市",cp:[118.1689,24.6478],childNum:1},geometry:{type:"Polygon",coordinates:["@@@VlUV@nanL@V@V@L@blK@V„wl@XalbVKnnl@VL„W„»È@lVUIVK@a@UUw„WUU™šƒš@„_™aƒK™@™bkkm@UƒkõŁxóL™l@¦@Vƒb@bk@VŽƒnVln@Vb„b@xmÆnœ@x@x™x"],encodeOffsets:[[120747,25465]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/gan_su_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"6209",properties:{name:"酒泉市",cp:[96.2622,40.4517],childNum:8},geometry:{type:"Polygon",coordinates:["@@ÇnÅaĉ@ƒU¯¥›UŹ‚ƒ£™WUýUU±JkkUw‚yÞIČxĊĕĊ¯š¥ÆUkţ™UÅÓ±¼™IUx¯UƒÒƑ‚ݐŰƒKÝnğ°ÅU@Žƒ@Vn@þš¼¯šWnŎ°XLWlnVnbWnƒVXxmbƒa—bóUƒlǕUUa™IUmlU™ƒš¥™kƒ¥ĉwkkƒÝɛa@¯™™U¯°mVƒkVnKlƒōÑÇÑU@kl™UġŽkUŻnUW™@š¯ƒk»šmWV£UKnUƒmUw‚w@ƒUIVaX™šwm»Èmmwn¯ċ™¯LĉŽUƒJUalka±Va@U‚k@ƒÛф¯WmnUaɝ¤Ûmƒn¯m±x@wóxÛLġÒUx¯VƒÈ™JUbóz݃ÇKĉ¯ōlÝUŎWl¯nťbÝ@¯ǩLġmV@ƯĢkÆm™ĊkVťLɃmÝXó°@„ĢbVŽóVݦɱ@Ƨaġ„UV„ĠÇÈV¼UVţwmbJÇwˋa™XmǯKkkmŽƒbXšm¼V¼ǬŚ²¤ôŰÆƴô̐ŤǪnɆӨ¼ɆLÆłUĊšxŎƞȘǔˎǬǪnƨŮǬö°»šġ„„ÞÜÆĸÒĊ„ǀbƾèôÈ@¼¯þŤĸƧ°VĀ¯b@lÈĊ‚šʠń̐„ȘKǀŽֲॗţÿǕý@ʊǓƨóÆÑǖŃôw@΋ʈƆÅÈVVĊV„óĊÅ@ÞƒĬV@Þīš@°Ž„V@ĸĢƒ°XτƜĠ@ÈaÜ¥Őƅ‚™nğóĕVġUůƿŋ—ĕƒa±V—UťÇğÑ"],encodeOffsets:[[101892,40821]]}},{type:"Feature",id:"6207",properties:{name:"张掖市",cp:[99.7998,38.7433],childNum:9},geometry:{type:"Polygon",coordinates:["@@ÈÒŎÒk„mLUŽlŽU„¯nV°šš@°ɜb„ÞĠaÈ»ĸl‚š„LVUÈ@Ċ@ýUm„@@ÆVĠ¯Þm„LƯޏƒ„Ñ°VVwšJ²»ÆԚVlŤÅV™¦ĉ°ĉĖċwÝJzVxll²IVVVþšX„¤źœV°¦„VĊ@ÆbÈmǔLĸĠ¯Ģaô¯ĸmÆÛUƒlÇĸk°XyĊUǔV„ǩnmV»ƒa@ýnK°n@l¥@»ż„Ċ¤m皃@£ČU@mƒmVkÞUƐ±²¹°‚ĠwÅƑŃU¯™›V¯aÈŁšƒÇ»™ġn_°xŎKlxœklx„@Þw‚„„@Æm²b‚DzLlkšWXať¯ĊaœÑšK±w@wƒUÅçV±Uk™@@„¯š¯xƒU™±±UU°ōxVxÅÔō°ó¯UÝ¦óbÝþƒ@ĉÈóUV‚Ux„„@VŽUVÝwÅÈǎóVkk¯JǐkmmL@„™KÇx@bkš™@U°ķ²ó`ƒš™šmn¯°ƒUwlÅkUƒ`™¦ɛô™Žķz@ŽÅnÇ°U¼¯KmVk²ƒJƒ¼ƏÞķôš¤ULƒ@mnğ`™šÇnUxÇ@Ûÿ™U@ƒƒkŻŽ@x@móJkŃ¥VŹĉóÒĉlċ°ķ„Uƽ܃@›x"],encodeOffsets:[[99720,40090]]}},{type:"Feature",id:"6230",properties:{name:"甘南藏族自治州",cp:[102.9199,34.6893],childNum:9},geometry:{type:"Polygon",coordinates:["@@ލš™nKlnšwX¥WÝXk˜xÞUnƒ°aĊVnUUKlÞĶWXnĠ¥ô»„™@nmVL@¤°™Vz„JšanU@aÆwna@k›ƒU¯šyX_›aĉb™ƒ„wƒéXkWwÅaš¯V¥mƒ¯UƒƒI@ƒš@„mšb°aÈçšUš¥@»‚knwɜƇ°I°ÑÈmVU™¯Xa@w‚W@wšV¯Č¥l¯Uwnm@k˜aUaóKkk@™Ça™b@ŽÒWa¯IÇxÛam¼™VUƒxÒl‚@zÝÒ¯bÝaĉVĉwDŽW›zJ™mJn²mܯUƒ¯ĉ@ġ¤Åb@²nšmlƒ@@Ž„„U„ƒLVxšV™„U¼Ålma™b@ƒ°™l@WIUƒ¯@mƒ™@™™ó„™„@U›zţyƒXÇU™ÇVUUVLkbWakVWmUbkkƒKUÆ»nƒ°Knk@aƒUVmšnk»l¯Ģ›lw@_kKVU@ƒnaƒ@lUk@¯¥mV@kmbW™b¯Åõa@mkU@kƒÇŽkU@›`@™óó—bl¼Uxƒn„¼šlVȄx@blVkVVnƒ`XÈġÈ@ǃK£ÝJmUUnUĖmlU„mKUn™VÅaUw›Uĉ`¯n¯wW¼nxVŽ™š@bĉnƒ‚kIċŘkXUŽ±Ò™xšÈ@ŽX°`l„œV˜IȯĊV„ƒšVVan@VašUVażVmšblkÈW„ƒWIXa„alL@wVb„„V„¦lL@lĠ™n҄U‚nk‚šL@ÆÞkšÞšK‚bñþW¦Û„ċVƒ„ULUºkÈlŎUxÆxÞUUxšÒ‚x„@XbšL@lÆ@„ÒlXVln@„bm¼ƒJ@„Ån„šƒx@bnšĠm„xVXmbÈè@ŽĊ£ČW˜w"],encodeOffsets:[[105210,36349]]}},{type:"Feature",id:"6206",properties:{name:"武威市",cp:[103.0188,38.1061],childNum:4},geometry:{type:"Polygon",coordinates:["@@±¯¥@klwU»ƒƒÞÝmwKm¯™™ç@™kVÇUL¯lVUKġ„ġm@a@U„@X£°l°LŎÇ@aōVÝw™ÔƒKUŽÅš„WJ¯lm@ÛVWa™@klĉUmaƒLUanaƒ™ƒk¯J„™™±KkXóÜÅxƒ²Ç‚@„„nUÒĊb°@™ÆkL™Ž™XÇÆ@xÝn—xWxţ„¯¤ƒI@Æn„ƒVV„VlU²Æè„V@x²x™L›ÒĉbŦ°Wb™Xklބš@l¤šXĊ`„wl@ĢÈŎm@bšnV‚Ubƒ„@șÆÛLƒèǚUÒŦlĸ™`°ĮʟÆǓbĉôϚĊƚĢnŤé΀ÑĸĀĊ¦„@@l°lœ¦Ȯ¦ɆÞĊKŤ™ĵĸů„»mŁyġ™ķŭ@Çɱȭ¯mƧUĊķnŁŻ»UaU™˜ƛɞÝƨů"],encodeOffsets:[[106336,38543]]}},{type:"Feature",id:"6212",properties:{name:"陇南市",cp:[105.304,33.5632],childNum:9},geometry:{type:"Polygon",coordinates:["@@šÈÞ@l`UmVƒ¼œŽ‚@nnÆwVlnVVa„LVƒÈ_‚ÿރ@n„a„xÆ@„lš_š@VxnK@llLnxmÈŎJnbUxšI°Žl@n¦‚lÈIlmX¥„k°@šk‚J„k²é˜@klaUaVaU@@ÝnIWnmnx‚k„ºÞ„„aV™°„V@nw‚KšxôbÞ£šVšU„bšþšLn»mƒVw„IšJ°Ž@„nb@°°I„ġUkÇKVƒ™™@ů»lƒ„Lnmƒ£@anK@Ñ܍n@»mL@£™yk„UUmbUÞÝ@kyÇbó»™XUxƒWVzb±mÝbXaƒwUamL¯»@wUKVwm¯ĵJ°ÅUWVk„KVk°wÈVšVуlUšƒ¥škmVamknƒUw¯¯ƒbċ¥ÅKƒk™Kk„™VċVk£kKVw‚Ñ„a@kóyÛ¯ÇVk™ów›š—Xō¥Ç¼ów™Ž¯U±‚k„ƒ@x›IĉÒÅVmÈnšÜ@n°„bUbÝV‚ŽUnnJ¯Į@‚m¦nV܃@„„L°JXb‚Ñ@šaÈb@šllôLVb—b@lmnVxk°ċ¦U°™Ž@xX@xWbš°UVÇn¯Ò¯Jɛƈmxl@¼"],encodeOffsets:[[106527,34943]]}},{type:"Feature",id:"6210",properties:{name:"庆阳市",cp:[107.5342,36.2],childNum:8},geometry:{type:"Polygon",coordinates:["@@kw‚ĉ—»VamƒƒV¯wƒIóVkl¯™Km™Vō¯ÝWkL@bÝKō¦@Ž™„@š™Lx›@b@l™a@km@@l¯nm@UaÅ@ƒ„óWUXm¥™nƒw`@UUxķôÇ°ğ¦@„VJš_n‚‚IVŽnalxkX„JWn¯šnVƒLšxl¤nnVbklVX@xnxmV@bUK@nm@@xƒV—°±aÅnƒŽkUWnUaƒx@m™n@ƒ¯LƒššmUĀlU@lV@blLUblxklkIÇx¯°‚UXbšaVŽUnšV@°‚LUlnbšX@`°nVmbnÆmV‚kLmK™¦UŽ@X„y@kl@U„°K@¼XbW„ƒš@b„WnLVa„VšƒVz@xlVČ¥lbUxލlV„U@nÆWôn²™VJlU„Ƨ„LnmÜLXa˜n@mœw@wlUlV²mšblwšVȃlLލ„±@lVnUlxnkma@mškšJ@kXV‚U@mn@š¼VXUƒVƒlLnmVbôaVnWV»ÈUl°È¯ÆIn›ÆU@kk»mKkÆġk¯@»mƒk—¯@óÇlÇ@—Vykkl™Uml¯Þ™@w"],encodeOffsets:[[111229,36383]]}},{type:"Feature",id:"6204",properties:{name:"白银市",cp:[104.8645,36.5076],childNum:6},geometry:{type:"Polygon",coordinates:["@@VKUȚl@šè°šnŽ‚LnxÝބ„V¼kx@l‚¦²°ĊóĠ„™Ċ»š@ÈxšaĊxlwÈVŤa@¯²aÇ£ƒJk£lƒnUÞ@°šô™@y„wl»lIX¥Ǫnw@ÑÞWla„ÅlL@ƒUwĉakƒl@ƒš¯mwna°J„V¯nUVÓÞÑm£²óWaUƒÇ@óÝUçV»ÈkkW@¯‚xV@XlK@wX@Vmm_@wÈݙKU¯ÇwVwÅK¯VƒkƒJ™™™XkWVaƒImŽ¯Uk„ÇlVšœĀV°mxóšk„@¼ó„WxĉÜU@Ub‚zÛJÇk@‚ÆnVlԙ@kŽ„x™ô@ĬWL¯ƒƒK@aÛImm™@ƒIUaƒ@™™UŽÇêU¤VÒÇx¯ÒV„šš™lk@Wbĉ¦UbkWV_‚y¯Lƒaó„kŽ@b@nmbkx„°"],encodeOffsets:[[106077,37885]]}},{type:"Feature",id:"6211",properties:{name:"定西市",cp:[104.5569,35.0848],childNum:7},geometry:{type:"Polygon",coordinates:["@@„a‚V²wVJV_@„LlanÅllŦçÜӚ_šlnƒWaôk„xUš„bmV@È°lèšnk°l¦„`@nnL‚@ÈlÜIyVaV@ĊÛXwôƒ@»lƒô™nwU¯›ÿU™Èklƒ°Vn„JUblXšWšš„I„l°U„ƒVƒš—@aVVVmnL@„lƒ„UUw‚mkƒš£„bV¥VUVwۂƒlaÇÝރmk£ƒLUy¯L@WlkKW_XaWƒ—mƒ„ġU@a™k™‚ƒakXkmVwmŹVƒU™b™WƒónmwnWW£„KÈnV¥ƒ¥„ƒÆ_k™lW„bU¯„V°aôbnaVwmaōInÇmwkK@kmLUw™@™`ƒkÅ@ƒwƒb@m݄ĀÇ`U„ƒKUbmUUkÅxmm@›„»nUVk_Ý@™Ç™¦™VÇè¯b™aƒn™@@„„JV„°Žn„U¦™°ÆbXxWl„êƒxš„ĊaœbW`™zV°œ„@lmbÅx@bmV™bƒI™`™¦@ÒUVUI@ƃL@bš¼@ššŽ@„šlmxnL„°ULƒŽƒÞğޛ°kLUŽƒL™°™xVŽ„n„KVƒl@šzX@"],encodeOffsets:[[106122,36794]]}},{type:"Feature",id:"6205",properties:{name:"天水市",cp:[105.6445,34.6289],childNum:6},geometry:{type:"Polygon",coordinates:["@@UyȍVƒVUnn@ƒVU„`UblzšJnk‚@Vb„KU„°l„wš„„W°„nkVŽ‚UÈlš£°V@n¥šV„kl™kU˜±U„ƒn™ƒlw¯UkwmKUlmkUmnkym@ō@U„mWÈU°l°anlJškUKlU„¯Èm@kmWV»kkÝLUWUx±b™@¯ma@ƒ¯™IƒJUxn„m¼™K™ýƒa™V™Uݤóa™wLmxU@¯ƒUšƒb݃ƒ¹lmwmnXŽmJ@ÞV@UbVbkblŽ—@±êƒlI™l¯@ƒlW¦knÇJkm¥k@¯™Jmbóa¯bƒUV°ƒakXlšÅ`ƒ„„¦U¦ÇmƒLX¤mXnxm‚„ôšXša„VźUnŽUxlnlW„bššl@bĢV„ƒ˜nX„WbX`lLXk@Ž°KVz„Kl¤„nÞ݂Èkb„‚܁"],encodeOffsets:[[108180,35984]]}},{type:"Feature",id:"6201",properties:{name:"兰州市",cp:[103.5901,36.3043],childNum:5},geometry:{type:"MultiPolygon",coordinates:[["@@lW²LššƒŽ°I„l„šmbVb„KnbĊVlkš@XbÜU@Žkn°‚XIƒÆ™V„LšÓÞxŎUlôƒ„b°KzU`lXVaĊ¥Xal@šk™™Uƒ°ÑÈwUтV£ÈéVšš„@Vb„Jš@nnÜJ@b„L°„XK@īšóƒwlš@kÓmUÅmK@mƒ_k¥l¯™mkçǯ@nUƒaV™ƒwólXbm„™k™`ÛÔťèkkmÆkbƒK@U`UI±xUƒbWlX„mbVbÅÒólkƒƒIWJkšƒ@ƒz—KŻ¼™@™xUx󎃄¯LWb@ŽÅ҄„±¦U`nbťĀUšVb„LšŽ„U"],["@@ƒ¯lwna@mōȯK¯kW¤ƒ@@V@bĢnĢƒVLU‚°k"]],encodeOffsets:[[[105188,37649]],[[106077,37885]]]}},{type:"Feature",id:"6208",properties:{name:"平凉市",cp:[107.0728,35.321],childNum:7},geometry:{type:"Polygon",coordinates:["@@ÆLUxÈxV°šLÇÞ@xn`Ü@X@nĊŽÆwnJmwUx‚aUkšw@V@w„aVmlLXÝl@X‚VĢmV°@nl@UUUWK@w„ÿVI²Òlmš@nÝĊýVV@nšJ°„„šUłm@kV¼nK›ĢȤôK„blnKllVk²aĠ¥È¯ĸóVw@V‚_„xšmn¦VWôX„ƒÆ@Vbn@°m@kn@@lšb@k‚aœ@‚wšK@™šƒ@UlKVaƒWX™W²¹lӄw@_°›n@@_lKōķW™@ŽmLUWƒn™»Û@›l_Ç`ƒÛmm°ÅbWb@š—VWbƒUUKDŽÅaġlmkUġlƒ»—Lƒl™Um¦@Ž¯U™¤ÇkVUml¯ƒƒX™ƒƒx¯kVƒƒLUa@ml™IkyVaƒ_UV@„mmUVU„ÇŽVzUxUVU¦ƒa™¤l„nVxƒVk„@ƒmKUnUU@b™˜U„ƒ„","@@@Žż@™mlkƒġk"],encodeOffsets:[[107877,36338],[108439,36265]]}},{type:"Feature",id:"6229",properties:{name:"临夏回族自治州",cp:[103.2715,35.5737],childNum:8},geometry:{type:"Polygon",coordinates:["@@š@ż»˜L„y„@l™XI„Jl„ôkÆÑUanaWƒXkW@™yk@U„ƒLƒmUšwš¯„KVlKœ¯Ġ݄݄VKƒ¯mKnw™k@ƒ™@™™»@a„K@ÅVJVU@њ¥š_Uy¯š@£UKmn@‚ƒšó¼ğ¦WmĵXݎkŽVLmVĉU¯bm„ÝV—wWlXÞW¦™xkmmL™šÝŽœ„±U@Vގ™š@„ÅÈW°X„ܼƨyUĮnŽWŽnXÝxUx°lVXJlôV"],encodeOffsets:[[105548,37075]]}},{type:"Feature",id:"6203",properties:{name:"金昌市",cp:[102.074,38.5126],childNum:2},geometry:{type:"Polygon",coordinates:["@@šĢȼ™„Çł°bœU°šV‚ƒń‚ÆǖŰnšÆ„ōĬǔaʠůĭš_kķÆ¥VÑș„çÜKšÅ@DŽƒVaU™m@aōnġÇk@ƒxĉ_™Wk£™@݃±KÈ±aÅnƒ@ƒÝxƒ@kw›lkwōL¯wm`"],encodeOffsets:[[103849,38970]]}},{type:"Feature",id:"6202",properties:{name:"嘉峪关市",cp:[98.1738,39.8035],childNum:1},geometry:{type:"Polygon",coordinates:["@@llĊx„¦šl™¦š„kVVnšJVbǖV„kôV˜a„bnaWw„UXmmamUXkWKō¯Xm°™™»ĉÇ@UVƒK™ķkǼğb"],encodeOffsets:[[100182,40664]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/guang_dong_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"4418",properties:{name:"清远市",cp:[112.9175,24.3292],childNum:8},geometry:{type:"Polygon",coordinates:["@@lǯkÿƒaV¯™VaÈU„¥ÆDŽIlxšmnb‚Uœxl™„Uôl°kš„„Wl„š@ô™VwUanUl@„xVkšaX¥‚kU»„aš¯±@kka@ƒUwmUkwƒJk™˜„±k@ƒ™™L@ÝWUwV݃—xÇU¯ŽÇX@m™Åƒ@@yĉ£VmUwȗ»ÇšUn„lUnWU¯`Ukƒ@@„™x„Ž@bÇxX¼ƒVVš¯LšĀk‚ÝLƒ„¯@VŽƒĀ¯lnĊW¦kVÇôkUDŽUK@ţ™U@a™™ó܃UU»ƒ@™¦k@Vx„KVb„n‚š@„Æ™„l„@xšƒbWšnlU„lxÈlV„È°Æ„@¼™„@x„šWxœŎ‚V„šK°„š¥ššnƒÆkŎ@ÈÑm™„K@¥šk@™ô@„nôV"],encodeOffsets:[[115707,25527]]}},{type:"Feature",id:"4402",properties:{name:"韶关市",cp:[113.7964,24.7028],childNum:8},geometry:{type:"Polygon",coordinates:["@@W™Xk±Ñ@ƒUw™mUwĉwlmn@Æwn£mkIš¥ÇÅ@¥šaƒón£nWWwš£V`Þ@šnVml@xô¼„IV¥ƒkUmkamUkVWwÛ»móƒ£UVÅKmn@x™@kbmm¯a™Xka›VĉaUb݃ƒ²—‚lš„IlxnVVx@„lb@l²™°ƒbV¼lW¦™bUlƒwk@mVVbUxóš™@kƒƒX™ƒ¯lókƒVkš›wVma™nkwƒJÅȃ¦ÇVUbšŽU°„blĀ°ŽkÈ@x™¦Æܙ°@„°„¦óa™VUôlUlbXl@nÜV„„nKlŽnIVÞ°Wš„°U@bnm@¥šIVƒ²Ulƒ°VnalzXyl_Vyƒ¦lƒœLlxš„@ŽÞbšKm„knVWanwƒÑVwČº˜@n_ÞV„aVŽÜIœl@„˜KȚ„VJ@aš£È@˜™@km™„aV¯W@_ƒa¯KmbkÇkLmwƒ@Å¥"],encodeOffsets:[[117147,25549]]}},{type:"Feature",id:"4408",properties:{name:"湛江市",cp:[110.3577,20.9894],childNum:6},geometry:{type:"Polygon",coordinates:["@@@ƒkXƒ™@a„UUċlk„Jƒk„™@wVJXUWk°W@nKnwlUlš²ƒ„blU@‚lI„l@„XbW„šxnm@lW@w„wU‚JX¯VU°`ŎóˋkÝÝkÅ@ÇmğÈřmw™aĵV›xUہ»°™ĠǷnýmóX¥ɅĵҏÇ@°²ĊUĖ±ĮU¤Ç°™Ā¯ɐnżUĊĊĬV@脎@ԃÒU¼l¤nƒĠb„êVĠ°Èy„zVaV‚nUÆL„ašbVl„wÆ@"],encodeOffsets:[[113040,22416]]}},{type:"Feature",id:"4414",properties:{name:"梅州市",cp:[116.1255,24.1534],childNum:8},geometry:{type:"Polygon",coordinates:["@@„‚nԚlW¼x‚¦@lœVl™lLkè„a@zš¤ƒĖ„¼UxlnUKUbÝlU¼lb@„Vx„V„klJÈwV¯š@ĠlÛĖšnƒbkšÆźÞƒUÈôklmšL„¥‚LœW˜„„™nKUkVa°V„x@IVV@x°bUk„a™a@mV@„@y„w‚L„ÑUwVUšV„‚„U‚bÞVVann‚@XwÇÿš¯²aVamkXaÆ»@»nw@¥›UXaƒkbWa¯KUw@¥m@kwmLU»UU™J@kmU@UUWUƒ@ƒyƒanwmçÛl¯ƒŽ¯UƒmKUmƒwVkmÝXbW@XWÝbƒk¯@±‚w@»U@W¯Å@ƒÇ¥UƒU@ƒƒ™IU™ƒakJƒĀ„ꃰšþƒXkamŽ@Žƒ_J°m‚@X"],encodeOffsets:[[118125,24419]]}},{type:"Feature",id:"4416",properties:{name:"河源市",cp:[114.917,23.9722],childNum:6},geometry:{type:"Polygon",coordinates:["@@°VlmX¹laĢÒlm„@„„šVš£‚‚@¦Ģklynn¼lW°z„W„„°VbÈV@lÆbnn‚JškX„šVÆašÅ„W@™ƒUUw@ƒkaV»ÞkVaVLkmVwƒ»„ĕ™£@yƒblçkKkš›U@k¥‚wX»™kmӃ@Wn¯‚I„`@nlb„W™ý„¯ƒé„ÿlI@™XUmWUwƒ@@UJU„Ç„mKUV@x™„ţk¯¯LWƒƒnUxK@ű»Vwa¯š@¤WX@ŽÛ¦@¤ÇIȼWxXŽƒ@Wx—w›ŽUnVbÅèmVa±²UWl@Žk„lȄ¤nôܼXxlUnVlbVn„lU¦ƒJó»@wnkmU™‚Ý@U_™¤XxmXm¤„ô™b@¦Èƙ¦lJn"],encodeOffsets:[[117057,25167]]}},{type:"Feature",id:"4412",properties:{name:"肇庆市",cp:[112.1265,23.5822],childNum:7},geometry:{type:"Polygon",coordinates:["@@l@š¥„@V¼„Vôۚš@bšV@ŤVLȃlVÈólUX¥mĉ°k„ÿU°@„ƒÞKl™ÿ°KU™„UW»Èw@aƒšw@ƒ„@nm@w›£kÓVUVn„Kš™k¥™£Vamƒ@nkKkbÆǫma—kmLU¥™UmƒÛwmVU™mUƒJ—ÇaUxÇIn`mb@Þ¯b@„nJ@nl„U‚V„lVU„L›W¯—Û`Ç_¯`mš¯I™bĉWċzx±J™xš¯ÆUƒƒ_k@™šƒJ@Umb„šXôlLš˜n¦@¼ĊxlUXŽ˜xUbL‚Ġ„UnVĊwlšUš„b@lW„X„‚m²˜@ÞWxXš‚Unb"],encodeOffsets:[[114627,24818]]}},{type:"Feature",id:"4413",properties:{name:"惠州市",cp:[114.6204,23.1647],childNum:4},geometry:{type:"Polygon",coordinates:["@@lbšW°bnnlaš@@wnmÆLVUkÇlƒ@Xk‚V²±‚bnUÆçUaVmœ˜xXw„@WXwÇ»ÈJ@£Ü¥@XW@£°™‚bUx²¼@ƂLVw„mX„°K°Ťlšƒ@wVUnLȃVƒVIky±wkƒKU¯ƒÅkƒ™XġÑۃlwUwlm@m„nKWašÅm›¯óÇmğb¯alĉUwķbmb@lÞÒVn—šmĀŹ@VŽƒbVŽUnmakLm`@xĉkklVÔVJVn—lV„UnmJmaLUbl‚™zmŽkL™a™‚ō@@zš‚V¦UŽV²kJ„nÜU@˜VXUŽL@„lJƒL@bݤUnVŽ—b@xVnlK²„Vx°V„xlI„lkVl²k¤@n"],encodeOffsets:[[116776,24492]]}},{type:"Feature",id:"4409",properties:{name:"茂名市",cp:[111.0059,22.0221],childNum:5},geometry:{type:"Polygon",coordinates:["@@‚LnÇlk„KnkÆL„ƒUm™ÈxlUœJló°n@ššanŽš„„a@ƒ˜@X_@mÝóóU@a™aU¯mL¯ƒƒkV¯™ÇVwkw@V±Ŏ£@™™@šalw±Vk@m„Åm¯™ÿŃƧIÇ`ōô¯_UVW°IV‚ƒx@xkX@Žmn™wXƒWa@ƒƒkkJ@kVƒa±„k™kVmxmL@‚¯XXlWVUI@xƒš„lƒIklVȃV@b„šlW@„@nUxVblVxkôlx™n„‚y„šnIƻư„aXwlK„bVnƒŽXb‚L„¤„k‚L—èƒVV¼ƒŽ²IlĠVX„ynz°KVx°@VlœLlblKœš"],encodeOffsets:[[113761,23237]]}},{type:"Feature",id:"4407",properties:{name:"江门市",cp:[112.6318,22.1484],childNum:5},geometry:{type:"Polygon",coordinates:["@@lUXx°JWnnƚXVš„W„X@„šºVLV¯nU‚Vnb™ô„x‚aXmW™XIšŽUb°xlK„l¯œK˜xXÞ°ŽšXÈ¥Ü@„ĉޏU™‚çš»nóƒVma—x‚¯UÅU¥Ý¯@ƒƒç@ș@çĉÅUmU籃ĉKÝxÝ_ÅJƒk¯»ó¯nmèkǀšŽWxœ¼mnUÜġ°@¦@ƒxƒLkŽÇaVnUxV„™šVlnIlbnÆÆKX¦"],encodeOffsets:[[114852,22928]]}},{type:"Feature",id:"4417",properties:{name:"阳江市",cp:[111.8298,22.0715],childNum:4},geometry:{type:"Polygon",coordinates:["@@°„nKV°šb@bôVÞô@n„VlÒôÆUnlnn@lmkmVkƒaÈkÆƄ™k¥‚ÅÞ»ÆKXkW¥ÅLmÅkamJUkš™UƒVwUmÈbl„K„w‚@@¥Ģ¯VÛnm›»Xw™lƿ™@kbW™—aʵ@óL›l¯ƽ@™ƒƒLn°ƒÆ@nUl‚²kx™b@‚š@šō¤U²@ŽlxUxšÈU°lŽ„"],encodeOffsets:[[114053,22782]]}},{type:"Feature",id:"4453",properties:{name:"云浮市",cp:[111.7859,22.8516],childNum:5},geometry:{type:"Polygon",coordinates:["@@@V„Iš™l@„`V„°Å™šw²I‚wČyĊXša°Jn™°_È`Ü_°˜œX‚KVƒkUUƒVkƒ@mmI@ƒ°a@Ýnam_ÈJVwlĉX@„šlUšómaUmVU°UK™¹@ƒƒWƒXU™™WmÅXm¯IWwkVWlÅLݼÆl¦ƒšÅÅÇl„bUllnknm@kmVmóÅkуUW`—@@„ƒb™ƒm™b@™¯mkô›IkVÇwnš„VƒÅKmlƒLklmȁKƒšVĊK°²„`n˜¤n„U„bWl„xVx™LUx@°nXm`VklVxmnnx"],encodeOffsets:[[114053,23873]]}},{type:"Feature",id:"4401",properties:{name:"广州市",cp:[113.5107,23.2196],childNum:13},geometry:{type:"Polygon",coordinates:["@@Ș¼VxUnĊ¤@z„@šÆ@nÈW°ÈV˜w„ŽUÞVxÞX@ŽšK„šl@ބVaĊbœU@ml£k±lUƒkkJƒw¯UUw±ƒkLUm@w˜aUVmÞ£@a„KkI@ƒ‚KVUW@—ÛVƒmlIU±VU¥™@yğzƧǃƒšƽĠřšÅnī±m@ƒ²¯lƒ°@nÝÆóUll@XnÝVU¦mVV°—„V¼™Jƒn„b@°mbn„ƒ‚@²¯‚¯wVwƒ@@nmxX¤¯L@ŽVLU„m@@l"],encodeOffsets:[[115673,24019]]}},{type:"Feature",id:"4415",properties:{name:"汕尾市",cp:[115.5762,23.0438],childNum:4},geometry:{type:"Polygon",coordinates:["@@@‚„@VxnXWV@š„bVššJ„„V@ÞÅU¥Ċxš£UWU‚wÅUU¥WVUkĊÇnkV`°LV™„wƒƒnU@™„ƒlbĊ¯„Vnalšš@@çkUÝ¥ġaó¯ÅaÅLŻÆUýmy¯ó@ĉÆó„ȯw™ÆXbmLƒ‚@nknVxkx܄ĢҚW„Æl„V°„Ll‚²xlz"],encodeOffsets:[[118193,23806]]}},{type:"Feature",id:"4452",properties:{name:"揭阳市",cp:[116.1255,23.313],childNum:5},geometry:{type:"Polygon",coordinates:["@@V„Ȧ„Æ@X°V@@¼‚x²°@„lÞaWXX@‚aÞWlnUŽ„xVnnL„‚°V„@k‚mĢl@„ak™@mlk°aXƒ±„nwm±™²¯JV²@ƒwW˜—_mƒa„V»ƒU@m¯ĉUф™šJl™„ašbVn„lĸLlƅÛDZwÝ@ĉxó@è™@k™mbƒUĉ°kaƒ„@šmV„„ƒxUš¯KU_mlĉÈVlXUV¦ÆVxVŽVX™¤ĉwV¦ÝÆ"],encodeOffsets:[[118384,24036]]}},{type:"Feature",id:"4404",properties:{name:"珠海市",cp:[113.7305,22.1155],childNum:1},geometry:{type:"Polygon",coordinates:["@@„è@„Þ°V¦VƁ°˜wnb„UÆ»nçƏ@nxܤ²llU°VnÈJސ°UôéšķUklƒô£VVˌKÞV°£n¥ƒ£ȗ™Ýy¯¯mÅkw¯bÇĔğ@Ýn¯ĊƒVğōŁŻƒķJ@Ț","@@X¯kmèVbnJ‚™"],encodeOffsets:[[115774,22602],[116325,22697]]}},{type:"Feature",id:"4406",properties:{name:"佛山市",cp:[112.8955,23.1097],childNum:1},geometry:{type:"Polygon",coordinates:["@@Èb˜Ž„InVVšnUÜxn„šVV¦nK˜lnbÅǬlalL@mn„Ubš¤l¦™šƒLUmUVlԜ¤@xmnVl°_XVVmƒkVmș@kn@VƒUK@°KW£nw@m„@Ux°x°@±„mƒna@¯ƒa„mšIU»˜ƒU¯nUV¥ÞUWmk@Vk¯™Ukn›ÑWݐƒĊÛ@Ǧ™W¯Wݗw›Lk°ƒkL¯wVa™WJXšWnbƒwkVƒ™W@kĊ"],encodeOffsets:[[115088,23316]]}},{type:"Feature",id:"4451",properties:{name:"潮州市",cp:[116.7847,23.8293],childNum:3},geometry:{type:"Polygon",coordinates:["@@°ŽÜknèmx„b„z„@V‚VX@VnV@lšIVVV¼nKlxn@@¦Vx°LXbla„ŽWbœV°£¯™W@nW@™‚aUñVœwWš»@¥ŤÅUÝǓÝóV@ńǎkUVmƒIUwÅVWÇX¹›—@W„¯bkl@nlšƒb@‚kġŽn@l"],encodeOffsets:[[119161,24306]]}},{type:"Feature",id:"4405",properties:{name:"汕头市",cp:[117.1692,23.3405],childNum:2},geometry:{type:"Polygon",coordinates:["@@‚@U±°Iš±n²mx²ƒ˜@œWºXÈÆUVx„JUnlVȍ@ŃôUǔÞVçn»VyĢÛVm@»kaÝUǼóšÛÈķKċ¥X„¥Wwğk™ƒ¯@ƒwķKƒkUm™aƒbkš™IƒšVÒ°Ċ@n„VU¼ƒ‚„bn˜`X—„x"],encodeOffsets:[[119251,24059]]}},{type:"Feature",id:"4403",properties:{name:"深圳市",cp:[114.5435,22.5439],childNum:1},geometry:{type:"Polygon",coordinates:["@@ÞLš„@xšbV„šVšK°™X°Kô¥Vw@anU„胐š‚lkĊl@wn_lKnbVmU„aUź@nÿ˜™UmÝѯUƒbk„@ÆkxŻ@™aÇX—wƒJƒƒ¯LķÝUĕ™ó™ĸóêWº@b²nmĬ™Æ"],encodeOffsets:[[116404,23265]]}},{type:"Feature",id:"4419",properties:{name:"东莞市",cp:[113.8953,22.901],childNum:1},geometry:{type:"Polygon",coordinates:["@@Ŏ@ššblKnšykVa‚KnbnIVmUƒ˜kUmUIUә„ƒçmV@bUxó¦¯LW‚¯š™L™UUƒ™a@w™ƒÝKğŚ™ƾ„„ƨÈĠy"],encodeOffsets:[[116573,23670]]}},{type:"Feature",id:"4420",properties:{name:"中山市",cp:[113.4229,22.478],childNum:1},geometry:{type:"Polygon",coordinates:["@@‚XœÒlmšV°ôÞÅ@m„¯°k„±‚@@aX¹¯VݏÇIUmV¯kk‚±Û£mw@‚Őmèżmô™¼èVš"],encodeOffsets:[[115887,23209]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/guang_xi_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"4510",properties:{name:"百色市",cp:[106.6003,23.9227],childNum:12},geometry:{type:"Polygon",coordinates:["@@lklWXL@VšI‚l@XnJn@VUUalk@mK@kny@UlU@a°™„ƒUU@VmaU@Ua@UWw@ƒn@KmLm@alkšmnI‚m@an@VIUamWÅImwU@@a@K„X@JVL„UVmUaVkUa@m„@@Ulmkk°ƒUaVUlKXbVwVIkaVmUk@KVk@a„aW¯m@w„¥laœX@KmaškVmnUl@nxVKšInU@yVaVIV@na°KlxX@@_lmXšUV`VIV™V@„n@lšbn@@WUkValK@²yl@„„VUV@@K°L@KU@@UVaXIVVV@naVkVa@K@UUK@UUa™LWa—w@m@K@UVVƒ@mVUUVKnL„mVL„K‚bVK@UUIk›mI@mUIVK@IUK@VkLƒ@WU@mU@WmUk@ƒI@VƒJk@WwX_@amK@UUWkIƒ„ƒK@LVb@mVmakL@J@bU@Ux@xƒbmI@`ƒIwm@UbmKUaUWa¯UkJWV@XƒJUU¯LUmV@ma@kkamKwƒLUUmWVkkm@aVUUkVKnVVUmXK@UW@km@Ukkm@@W@U™kUy@I@aUUmbƒ¤U@kUmL@bmJU@Ua@wkLWWkL@Uƒ@VaU@ƒLUakKWbkUWVkKkLVLUV@JVbƒz@Vƒ„@ƒVmUU@kVmK¯@VƒU_™VWakVmIUKUaU@@bml@XU@@V@LmKUV„mVUKƒƒKƒbkaUXƒKUL@x@V@l@„mxU¦„V@ŽlL@V@Ln@@VV@„nlKUaV@nLUbmJnL@VWLkbmV„@@L„W‚„XLlx„VVIVV@x@V²blUVm„LVUœK@kWWXUlV@Xl`„LX„l@@VšŽƒn@VnbVš@lVUVUÈVbš@@`UXU`l@@XUVm@kš@xmVknUJVXUbmKULmbx@VlJ@LVbkKUbVLÇUUVƒUVmU@VaUkUKƒVUwmLkUUVVlƒbka™XmwƒKUšVVU@@V±Uk@VWUUm»XamU™bƒKk™`ƒ„™U@UnWW_kKmbUVUVmnUV@„nJVUlšUbU@UV@n@JmI@VmbnVUXlx¯ŽkKmnVV@L@V™bkV™Umm™@Ub¯LmlUƒL@VWLkmkLmmn£WmnKU_mW™š™bnbmxƒ@U¦UJU„@Xmlk¦@‚mnUUm@@Jn@lV„ÔVJnIVW„I@a„ƒÆK@I@aVK„IlŽÞnnl@nl`nbÆX²l@xV„@llbVn²ŽVVl@nn„V@IlW@Un@@kVa°KšnÈmVaVXUlaVƒÈU„VlwôUlynIVašan@lVXb‚Iš@n¥la@Kš_n‚@bÆx@XnJV„nKVz@`VXVšU`@bƒ¦UV@VšIlx„UnV‚K„XÈbšVllšbVbnVn@"],encodeOffsets:[[109126,25684]]}},{type:"Feature",id:"4512",properties:{name:"河池市",cp:[107.8638,24.5819],childNum:11},geometry:{type:"Polygon",coordinates:["@@lLVl„bVV@nXVlI@JVX„mšn„W°b„IVV@‚ln„@nalVUb„nW‚@kVkÒlbVKn²°bUŽlV²@˜X@`nb„aUI@ƒ°wlU@aXJVI@aVK@wUamIXm‚@XUV@@bV@Vm„ImnUUwVaVKXU‚nVK@akƒVwV@nL@UV`n@@X‚lnIUJl@X¦˜V@aUIVm@anƒV@UwnL@VlbVL@KVVXUWƒ„wUUVUka@UVJnUlbnalbVVn@°„„LV`Þ@šXVxV@@bVlUVVbXnWlXnmlš@XXWVXJmbUI@V„llUVkn@@VWV@Vnb„@VXUJVnn`lLVk„a„»lVšLnw@WV@lInw@WnU@U@m‚knUVó„K‚wUmUXUƒU@@wVJVIl@XKVVVbVI„J@Un@lŽVLnm„b@U@Ul@nUš°VUVJnnVJV@„@mVU@ƒ@wkUVwkKWk™yUUkU@alkÈ@lJ@x„Ilƒ@UUWVkUw@Kn@@kmaƒVUl™UUL™ÇƒUUKl@UUmL@aXU@mlUUwmKkUUVKVUƒaƒKUnK@U@Vl@XUWU„KlwX@šb@K‚@XkV@UwWJka@aUwmV@U™@@U@wUm@»kLWVkIWŽXnmV@VkbmKƒLUbk™Va@aƒa@@aVU@aVak£@ƒ±UkVU¯V™UUƒJVƒUIƒ@kxmUmWUbL›w@K@aU@@aVU@Kma@aka@_VWkk@UWVUKULWKULUš@KUnƒwVaUKƒxU@UmaƒL—m@kVmVa@UkƒmI@ƒ@KmIkxU@@K™U@mmakI@VƒLkmWkkJ™_U‚@V@L@n˜xXbšKVb@VVL@V@LUbUlmbU@UUWJUb@VV@@L¯K@LU@UVƒƒk@±z@‚kLUbVl@Xm@™akm@ƒU@UšUJU_™VWŽkn@`W@kw¯LmbU@UJUb@zmV™JULmwk@mVUn™lnb@L›Wkbƒ¦@x°nXŽƒb@bUl@LVlUnlbUJUxWakLUVVb¯„llkn@Vƒ@@nVbUlVbUnƒVUK@IƒW@L@bV@nxÆJnXVbUJm@@bnmJ™nkl@b‚nnK@L„m‚@Xx@VVbV@nb@UVVƒ„¯š@bkV@Vmz@lnLl@kŽVbUVm@mI@Wk™J@UWKkXkl"],encodeOffsets:[[109126,25684]]}},{type:"Feature",id:"4503",properties:{name:"桂林市",cp:[110.5554,25.318],childNum:13},geometry:{type:"Polygon",coordinates:["@@nU@J‚X@`XLm¦Vb`lšVXXWš@VblČnVšŽlanLnmVLšK@_Vaƒ¥@kUa„@VmVb„aV@XVVzlVVK@knKVmX£VKšLlbnš@b@llL@xĊôXaV@°È@¤„bn„V@@Wl_„V„U@W„nVamw„wVbn@„K‚VšLX@VmVUxlV@šnVV_nK@m‚I@Wn@@IšUĊ@@wVWX@@I°VVm@wmU@m@IUƒV™kƒlkUmmkÅV@@aV@@Wn_UKla@kšaV„šlVanb@k„@@KlVn@@aV@nIWW™UUaVU@™kKmwU@UImKk@UU@w@W@‚™k@™UkWƒ@mk_W@Ua@a™ƒƒ@—¯ƒmV£@mƒUUam@—kWakƒVama@UUm@nw@alaUmnUlVlIœV‚™šLVyk£Vm@k@UUJkƒK@kmKUw™KkWK@UXImyVwnI@m‚ƒkUlkUKkUVmƒw@kkJWUÈm@_k@@aƒaW@U„UJUwU@@IWKkƒmUUV@nVl@bVb@bU‚UXƒakw@ƒWUkbkKƒbm@™xUlkLm@@wmKUX@‚™UaVW™XVmU@@UUUƒxkmWXkKkUWaUaUb™L@`UL@LV`UXmK@VmakLVbkL‚xUJUIVbUVVb¯KƒV@Xnl@lVXbmÒnV@L@VWKkVUIWJkIƒŽUamUUbm@U„kU@JUbW@X„WxUam@kbVVUnUJmUUV@bƒU@UUV™@ƒVk@ƒbƒmULV¦U@V„U`VLUL@xVbn@UJ@nWJXXVŽVV@bkxVbUx‚Lšš@x„¦@šU‚lXUVVlULV@@šnŽU„ƒb@xl„nJVnlVknUlVUbmŽU@ƒbVš„x"],encodeOffsets:[[112399,26500]]}},{type:"Feature",id:"4501",properties:{name:"南宁市",cp:[108.479,23.1152],childNum:7},geometry:{type:"Polygon",coordinates:["@@lKnbnU‚@Ua@K„L„ƒlJVX@VnL@bW`Xxl@„I@U„Jl@nV@X‚V@nXV„@lK@UVL@JULVJ@nnJlœVJ@VULaƒLUKƒnmKULVVUŽ@nU„š`lIXlln„K@UlJnb@nšV@LV@lwnJ@L@„nJl„@VUbUn@l˜n„KnbVŽV@„wVLUb„xVm@LV™VKXLVKVLXU@VllUX@`lb@bnb‚L@ŽUV@bV@@b@Lœx‚KVanXVƒUUmVUUUaVUky‚UUa„ImK@mUUVUkKU_@W@UVVVIUW„UVaVU@UUKnƒ@k@al@ll@bnL@b„VUV˜X@Vœ@@b‚Knblmn@V_@aUalL@a@akK@kVKUKlwUUnV¥VmU_VWVIVaX@Va„alńK@LVJnalL@LnK„wlVUw‚mX@VXšƒlLUVnblaUmVUVwXU@Wm¯Va@ÞKnw@w™mšk„»‚UVW²a@_mW@U@I„y„LVUUKW@@™„LX@VUV@@yVU@UV@nwUUmJka@IU@ƒmƒVkaW@UwUX@`ƒ@kLWUk@mƒkUUm@k‚UUWkUƒkWxk@@VƒK@nV@UVaƒUUJmIkVƒ@UamLUbkVmamLka™@ƒ‚kmL¯WI@wJmwƒx@akU@aUKmbkaW_nW@_U@Wm@a@wkwUKmƒk@ƒbkb›w@mKUkkU@J@bW@kVWz@bVUa›VUx@„ULkJWbXVVXƒ`@œmJUVU@@Lk@WbU@UJlnXlm„Vx@Ln@‚b@K„LX„WJUUW@kƒaUVUbmV@nnV@n@lVLƒVmLX‚mXkV±@kxÅL›šUbJWIÅJ@I‚mXalkUamKkškL±aVwKƒUU@mÞnbWJX„m„@lbmKULWUUVkaƒbnn@Vl@VVV@VƒbVbnLWLXJWxXLV@@VV"],encodeOffsets:[[109958,23806]]}},{type:"Feature",id:"4502",properties:{name:"柳州市",cp:[109.3799,24.9774],childNum:7},geometry:{type:"Polygon",coordinates:["@@ƒwU™„aV@nVaUVklmkUUmmIkƒ@w„aVƒm@™U@VKUkVUkWV@™ƒ¥@w™™KVwUalw@aUUUWWXI@mVIm@Ua@wVKUKV_UƒV@U¥VK„n„al@„Uš@VU@V„V@aVUnVVIVmUUlan@VbXwWƒX@Va@IlVVƒn@VanVVb„lJXIVJlUXL@U@KmUnÑWakU@mkƒJUI@mk™@wUmmUV@JXaWIXWmaUIƒJƒkk@W„nJ@„ƒaUak@›kkJ@kUKU_ƒ@myUóWUkm¥kUmL@KUKm@k_UmVa@ƒk@@UmU@mm_—JWIUVUŽWLUlbVUJÇVUIVwƒKUVk@mU@n@lUL@Km@@l@L™VƒzJmUU¤m@UbV²U`U@@¼Vn@x@Vš@@VnUVx@blbXIVxU@Wl@@L™aW@kxƒLXVWVk@@U@VmLVŽ„L„bUVULVV‚lnLVxkV@nWV@bnKVVk@VL„VšÈVKšVVk„Unb@lm@@LVxUlVX@Vk„ƒJ@wkIÇ@kl@blVVVšzXllLUxlV@x@„UV@nƒ‚U@UImmUIUV™¯mVk@@V@VƒamnUKkm@@VƒIUJUaUUWLk@UJUI@xV@V„VWVnxƒLUômVV„@VkVVVUnV@UVkL@VVV@bVxla@bkXVJVn„`nU@bƒb@bVL@VnJ@„l@šV„aU@@_lW@UUU@Unƒlll@XLl@@UX@°bVWVanLlknVV@VVX@VVƒnUŽVLmbXJ@nllXX@`VXƒlmaXVWk@Wkƒw—J@„VL@J‚bnU@bn@@bVKUnVJVIVVVL²a@bV@@Vl@nUVakalmš„UL@VUL@V‚a@mXl@nK@UlK„L@Vl@@nkllb@š„Vnn@‚šnV„™V°l„šVInwlKXxlU°Žn@@ƒ‚I@UnVlakUJWkUK@anUWK@_ÞJ@U"],encodeOffsets:[[112399,26500]]}},{type:"Feature",id:"4514",properties:{name:"崇左市",cp:[107.3364,22.4725],childNum:7},geometry:{type:"Polygon",coordinates:["@@@JVzšl@V@Xn@ll@VlnX@@VWLnŽUVmUULVlUV@blnUlnXVV„K‚xnLlb@lnbU@Vn°KVV„I@WXUlI°VXb‚VVbnLVan@‚x„J@_nJ„a@wVwV@@a@IU@UU@WKXwWIXKmKUa„a@U‚UUUk@@Umm„albVUXVVKnL‚a@knƒWƒXImanÝV@„V‚LUx²blKl™nLVbklWbn@JÆIXJ‚IVaœ™ÆKlw²@lUnWWnK„UUK@k@mmU@mnUVaVU„b@lVXVXIWƒƒK@Lam@@KUwnƒWkkmVIV@Xal@@KV@VUnI@›„_UWWUkam@kkm@ka@mƒk@wkJWIUU@WXkW™XkWWLUUƒ@UakLƒW™XV±VIVWUU@anUWaUK@IU@Vak@@UUKWaƒ@m@ak@@wUkla@mUaUklakwVƒ¯¯@WWUkLkKmaƒ™kLUnV`UxWX@Jkn@bmlƒakkk@ƒb@l¯bm„ƒbJ›b@VXn„bVV@„ƒbƒJUkkKWVU@mœÛVUUW@UVUJWXkVkKmUL@WW@U„Vl@XXKW„XJ@XVlmbUxnnm@UlVnV@XVm¦VJb@šmLkKÇbXblVkn@l@bWnX`V@@IVV@ŽV„V°n@@_naÆVVbUVVbUJnzlVUl‚XkV@Vlx@X„VnxƒbƒKUK@b¯VVUV™L"],encodeOffsets:[[109227,23440]]}},{type:"Feature",id:"4513",properties:{name:"来宾市",cp:[109.7095,23.8403],childNum:6},geometry:{type:"Polygon",coordinates:["@@nVlw„@VJU„„IVVUšV°lU²V@„l¤Ub@bUV@b‚@„b@bUblšVa„KnLla@UnUWmXlJXUlKV@V_U±Van@V£nV‚I„yšU@K@kn@@LVK@k@mnVl@VU„LUxVJÈUVIU‚aVkXKVVUXJ˜In`@nnV@Vl@@„UbVnl`n@VL@LnKlVn¦VlôXV‚nz„@V`VL@llIœll@Vb„b@ƒmIXƒl@„l„IVJnbWXXJWb@IU‚nVVn@xlš@nVJ„I@W„U°LUaVUUaVJVIwlKUalKnb@UnLVWU_@KVK@_šKVa„@VKU¯VLVKn@la„aUkU@maVU„J@k™@Um@XmbkyVaUIUU@KV@laVn@KXKWUkUk@ƒaW™UUVw@aXKmƒVaUUkšmIƒlUU@wUa™xUmmU™¯™U@WƒLUmVIUym@UVmUa@wmw@çm@aWLU„™JUIUamKmL@™aƒx¯¥ƒkU¥U@±„k„UVmKU_mJUbkKm„ƒLÅǙ_@WWUXUmaVUkK™„UWW@nVxkUƒxmL@KkKmbUI@KƒLkƃbUbW@UbUJUXV`UnU¦mŽVVkxVLUL@llL@b@bkKVb@bU`m@knmaL@a›@@U—WVUƒU@amK@akkk@@b@lm„VL@VUVUbƒVVXUJUU@V@XV`lLUVVV@nnLƒJVbVlzUVVbVVnUVVU„"],encodeOffsets:[[111083,24599]]}},{type:"Feature",id:"4509",properties:{name:"玉林市",cp:[110.2148,22.3792],childNum:6},geometry:{type:"Polygon",coordinates:["@@VJUXVVXlWX@V™xVnX@@`ššULWŽUXÅbWK@mULUUmJ@n¯b@l@VULVx„x‚XU`VXXJVI„V@nm`@nUŽVXn@lWVn@b@Jn@nU@Lm`@Xn@WJƒ¦U@@VnL„lV@@Xl`nIlJnkVL„w@KVK@UšaVL@bVKX™lUUKVK@I„VšL„a@U@WšLUlVL@bU@@blb@VlbUxVbXUVJ@xVL„U„lV@VU„bVLnKl„XJ@L‚b@an@VanL@`VLšKV_UWl@U_„a@WVInlVUUUVm@I@W@wVakIWm@U@ƒXwlaVbnI@ƒm»Va@aXaVLšU„»@aVa@k™KkL@KmU@WƒzUK@wU@VWUUVUUKUa@mKmbUK@_nWVaUkVaUaVUVLXKVƒVUVmVI@UkKkLm`UkW@UwWW_„UaU@WakXmK@xUXƒJkƒUUWUk@Wl—mJ@km@@aUKzmyVk„a@kkWVUU¯lmU@@w‚kkmV@Vk@mÅIƒ‚Ukƒaƒ@Ub@m@UUU`mUbWaWmb™X™XKWIXUWm@љ@y@UkIUJUUWLUWƒL@UkVUxW@kaWbKWnXxW¦n„m`XLVlUbVbUx™I@JmLUKUb@VW@@bkL@b@VlU@xkš@L@lƒxXxWXX°V@VVVbUVV@UVVbULVnVJUb²b‚aUb@VVVVInlV@VnXaVUšlI„VUb"],encodeOffsets:[[112478,22872]]}},{type:"Feature",id:"4504",properties:{name:"梧州市",cp:[110.9949,23.5052],childNum:6},geometry:{type:"Polygon",coordinates:["@@VbXblVlLXWln„wVV@VV@UnšWUXVbš‚@VWXa@kVK„UaVaVkšUlyX@Vaƒ—VmUwUaVU@UÈymI@aU°@š™nWV@VaVaw@IV@VmnLVK@kmmna@™„™VbVI@aV@XbW`U„„LUVVx„@VbUV@bl@VLXblJn¦lL„°°@n™@K@UlLnK„a°LWbnJ„¦UÒV„UllLlVnKnbWnn„V`„w‚@@Xa±™n™l@XKV_„WVkVa@kVyUa@wU£UW@UIVW‚@@a—wWaX_WKkVmUULmak@UJUI@±m»™—k@m»VyUIm™nmmwnkUmVaVIUn_mW@»Vk„@VwkmmUXa@IƒaVm—mƒ@Wm_U@mIUWóLmUk@laXmmkUK@UmKULUUmWULƒ@VakU™@Ub@bƒ¼™VUKWb@bUbn¼@„mJUakbWx@„@VXnlJUb@x@X@JUnVVUVmkUJ@XƒbV`k@VXU`™LUK@_mKUbm@@b@„U`@nlV@b„UnbVbn@@`VbUbVV¯bm@@mJXb@bVnUllVXUlbUl@LU¦VVmŽkLVb@b™l@V@XlK@V@nUJUz„°mŽwmLmlXbWVU@UUUlƒIU@VVmV@@¦‚bXbWxX„WlXVWL@LUmkbU@@LVVVJUblzna@WVnš@@lƒIUVnbV@Vlƒbkbm@ULUKV°ULƒ@"],encodeOffsets:[[112973,24863]]}},{type:"Feature",id:"4511",properties:{name:"贺州市",cp:[111.3135,24.4006],childNum:4},geometry:{type:"Polygon",coordinates:["@@nL@xn@lKVkšwn@„alLlaXV@„lx„bVWV@aUa@aUk@mVUnVl„XL@JV@VxVIVƒX@„b@bl@@`ÇnXVlI@l„xUnlVVLkllV„@nmJUxnzWJ@VXLlŽšLVxnL@l„LlŽVI@V@lUnl¤Uz™Kš@„Vl@š„L‚l„Lnš‚b@VnVVU@k„a‚Knxn@VkVJ@ńUlakmWIUaVanm@_UK@UVWUa@klXam™U@Vmƒ™VIXW„@lUVknVlKVLXŽVXšW@b@VlšnnVL@KXL‚Kn@lb@UnW°@Va„X„WVb°aVa@I¯aUkUaVKVwƒaXk@a„a‚™@wkm@alanUVw@alK@Umkw@UƒaUmU@WXUaUK@UW@UaVWI@¥Xa@w@WWšVƒXwƒU@mKUXUWVU@a¯kl@akU@UULmK¯VUVW@U_m`U@@xVbUz@lUbUlƒXU`WLk@mš²šWb@Ž@ƒxU_mƒXmmamLkUkKVkUƒVу¥mIXa¯KƒbmLkK@V@Lmš¯@ƒ¯kKm¥kIWaUKk@@aVUUaƒ@UwVUƒKVƒX_WaU@@bUJUaƒš@šmbnn@lULmKUnU@@J‚xUbUbU@mX™š¯@VŽ@bnJÇz@VUVVbVxUn„˜UbW@kz™VUlUbVbƒŽUL@lWb"],encodeOffsets:[[113220,24947]]}},{type:"Feature",id:"4507",properties:{name:"钦州市",cp:[109.0283,22.0935],childNum:3},geometry:{type:"Polygon",coordinates:["@@@IlVVlnL‚@œxla„al@n„VLlx@x@bXnV@@`mXX`lbnaVL@blV@b„wnx‚I@xXJ°nK‚l„š@lbnKnblUVanKVb„@lUnJVI„VUb@V‚U@m„L@Ul@Xw„llVVXV@lVnlVn„l@XVlK„@@_VWVxX@lb„U„nV@@JlbnIlmnVV@UwVK@U@k°a@mnIVVVK@nXLÆaVWXVK™™@_W@Umšw@UXWWkUUVWUIVaƒUkJ™UVWbUmU@mkUJUU@UVab±aVaUIUmVKUaVUU@VUUaUUU@W¯XWWw„w@k@Kl™@wkV@U@alK@aX@@UmIUWUIƒ@mmkXU`U_WJUnUJmUk@@amLU@UVW@UkU@@VƒbUWVUk@@wmKkUWLUWX@JmIƒlUkkKWKkLWU@UKWa@bU@@a@_UKWƒUUUmJmw@nV_@ġğKóLmbU¼VÆ@xUXƒ@Um@wklVnUn›lkaUV@„lV²WVklWXXbWlkVkIm`UUƒLƒUU@UWƒx@XU@@lWLU@kbUbV`UXllUV@bmb@LnKVbULm‚šnVVIV`X@"],encodeOffsets:[[110881,22742]]}},{type:"Feature",id:"4508",properties:{name:"贵港市",cp:[109.9402,23.3459],childNum:3},geometry:{type:"Polygon",coordinates:["@@n@VzUJ‚nVŽ„K@XšVš°nVVnšwVb@xVV„knJl™VVUbn„WL@bUxVVXš„bl@lVXkWƒXwWaa@¥‚@nUUUV@„JVkVVV@XUWanknK‚xnƒ¯VyVI@m@UkL@W@Ušk@aUalKnUUV¥@KVkkaWVkUVkUm@aWanI@n@°aUUVaUa@_m@UamaƒV@akU@mV_@ƒa@KWIkƒmLUKƒaUVU@ƒkƒVUK@wUIWVUaVwka@Uka@aV@@aUKVk™K@X@Vƒb™KƒU@JULVLkVWšUL@aUK™b@VUL@LƒxUKmlkImJk_@WU@ƒkmK@UV@„¥XIm@@Wn_@KmVm@@I@aUmkXm@UWV@mn_@mƒUUJWIUWV_WƒwU@mUknVVmxU@@VUV@zU@UVW@ƒK@šX@VLUVƒKƒz@J@VnX@`±bUXVƒ¼™lšn@xmxÝL@‚Ubn°@XWVUxUVVnkbWVXV@Xš`ÆȄKnƒlLVanIV`nLVUlƒ²ƒV@V¦„l°¦„w‚b@šnKnLVbVJšIVƒXK@b‚n@ènx@xVbUnV‚"],encodeOffsets:[[112568,24255]]}},{type:"Feature",id:"4506",properties:{name:"防城港市",cp:[108.0505,21.9287],childNum:3},geometry:{type:"Polygon",coordinates:["@@XV@X°°U„lxkbVlVb@nkbVl@xl@@b@n„‚XbVL@Vl@UbV@@JVLXbmV@bVVUXUJU²šW„XlKVb„@VVXKlXšWlXXWV@VXJlI@x„l@nlbn@lln@lbXalIVK@ƒVwœUVb‚U@aXylUX@@aW@U_UJmU™nVKUamL@Kna@aVUkkVWU_ValaV@XK@kV@@W„wVXV@„V„KVVn_lJlUXkWaXWlkXU‚±kU@ƒVUlbœkVmUmlk™¯Ý™™W@mb@¦VxULm™kJUU@ma¯wƒmkX@VóJ±bUVUXÝWk™lWXXlƒxUaƒbƒIğ™Ç@U@mVUKkkm@UJm@XnWV@x"],encodeOffsets:[[110070,22174]]}},{type:"Feature",id:"4505",properties:{name:"北海市",cp:[109.314,21.6211],childNum:2},geometry:{type:"Polygon",coordinates:["@@VaVLnK@IšJVwUaVaUkWKn_mƒX¥WwXm‚LXalbU£UyV„Å@ݙwm@™°l›LÅUƒmk™mwÛaƑLÝUUm@ȣƃV_„Ó@£UƒƒUVƒ„™¼U°W̄™ÞVbXbôx@b@bmV@ǃ™UÝ@@ĢU`m@ŽnxnIVV‚VX„VL@`@bV@@aXbVL‚@XVlKXLlLVl„knJ@I‚WVXXKlVnL@xl@UVVX„a@UV@VlX@VUV@nK@bl@nVVIVmXIV`V_lWnn„@VJVXnJ"],encodeOffsets:[[112242,22444]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/gui_zhou_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"5203",properties:{name:"遵义市",cp:[106.908,28.1744],childNum:14},geometry:{type:"MultiPolygon",coordinates:[["@@@UnUlJn„w‚JU°VL@bnVšU„wlJ@XƒŽXVlU@klVUJknl„UllL@bUJ@xULUlƒ„UblVkblbnw‚UXmla@„wV@VK@L@UXaVKVLXWƒUVa@U@Im@@W@£UKUakKWIXU@al@@llUnL@W@Un@@VlUV@VIUanKl@Xb@lmxVb@b°bb@nlJVVnnJ@b@L‚V@ln„@LmV@Vx@blnVK„nlJXIlw„J@҄b@nlK@Un@UL@VVVVUUUVK„l„@VUVL„J@UVUUw„@Wm@™„UV„ÈVlbUb@JšLlŽX@@x„„ƒLmŽk@@nlx@bUJUzVJ„@@LVxUV@bWxnLnVVK@_‚K²xVbV@n¥@aVI@b„@l@Va„Knb@n‚`n„mmý„W@ƒU_šwV@VlVV@Vn@n„˜@nI@Jn@°¦VaUU@™„mVVWVaUńU@aVKnƒVbVUmmU@a@kUw™m@aUUmUUJ¯lakU‚aXaWUUaVƒkk„amkmUnVlULƒVlJ@XU@UJWUUw„k@aU@WbkWƒL@U@WU@@XUKmV@aUVwUĕUJUamUUVUÑm™nIVJ@kl@XalJVn@KVLœ¥@UWIXWmU@mVUKnUWLUKUaWUUKVU@U@anUny@UlUkK@w@a@aVUƒ»UkVw@Wmk—JƒÅmUUVmwXalLXWWUnam@XkƒJ@UVU@U@W„@@U@I@Wl@Ènlw@KXLWb„lVUkalKUU„VVaV@@wnIlaUmkUƒKWU@KkUkLWaƒKUUWUn@VƒK@LnnWJUIƒVkUWVnV@V™@@XƒK@VUIUJ@IWJkX@VVJ™IƒVkK@I@UVaUWk@m„@wnUWKk@mxk@@„lV@b„xmb@x@VUmLkUƒJ@nVV@b@VkLVbU`¯I›l@™U_UW@UU@™™ƒK¯wm@™xƒL¯¥kIƒ™ƒ‚@bkbƒ@Ua@ƒm@kkW@XVbmV@ŽkV@bWbUbV@„¦ƒxXlmVk@ƒ¦™bkaWL@KUImK@wUK@VUI™b@bmK@LÅy@akXW@kbWlXblL@ŽULUbƒ`@U™kUymX¯@mšUJUUJƒL@Lm@@WX@lU„VlšXll„@l@Èk°V°Ž„X@VU@UVll@XUJVXUVm@@VXLWlnV@Xƒšk@mVULnxV@@bm‚kL@VWLUbU@UVm@ƒb@ķ¥UnmJ@UUVƒkkJUšlÔU`UIW@ƒ°kLUlUI@WVI™U@mWKkXk@ƒ‚WU@bXšW„@J@xX@l@LVl@xšLVxXX@x‚KnxVknb‚KVV@U„L„WlXU`@nUlšX@llVXšVU„KlkUKlI@anKVLXKVaUIVWV_VK@VnLlU„»VKVL„m"],["@@@KlKkUUVVX"]], -encodeOffsets:[[[108799,29239]],[[110532,27822]]]}},{type:"Feature",id:"5226",properties:{name:"黔东南苗族侗族自治州",cp:[108.4241,26.4166],childNum:17},geometry:{type:"MultiPolygon",coordinates:[["@@VV@XkV@bUbWJU¼Vb@Vnb@bš„@J@bƒL@LV@UVƒlUI@a™KULVb@bkJmx„šlLVxknVJk„‚xnKmnnL@bn`WIXlWLU@UxVbUVmKV„XI@JVIVJ@U„L@Wš@@UmUXUlV„UVJXImm@K„L@UVmVXV‚„LXblKlV@LXV„LlVVnkbmJ@xnXl@šbXa‚@Vana„ÒšL„m‚VnIl‚Þ¦°k@b„@@lV„nJlUnš‚VX_„@lVlK„šV„UUxVLVWVIXJšUlnnWlI@KUaUUVKn@VaVXV@na@ƒmw¯@mUkJUamI@lk@@am@@I„ƒUmVImUUw˜™@anUVaUU@LU@WaWUXWW„wV@VwnU@L@ynbl@@X@a„J@nW@@Vn@„lVLlxnI„lš@@UWKUƒnIlJXIVllIVVš¼XK@aVI„V‚@@bn@VKXLVKVVVInw„J@UWI@mX@WKnI@KmU„UVJUL@V„KW@@k„@aU@@W@InJWUXwWI@Wƒ@¯wkaVaUIl@nŽValIXWWI@UUm@anwWkXWWIUbk@UJmIUamKVUUUVVama¯VkIVVUlKnXVwX@@WVaUUVa@IlƒaVmƒkna›wk™UU@ƒU@mUVƒšUVwœl°LVbnJVU™¯la@mX@@UWKXU@aV_V@@JlkUƒ¯@V™nK@km¯k„U@ƒWUW@mmƒU@™kmlU@wkL@WƒUkL@VmLƒJ@b@V@bknUUVK@UVKUK@Uk@Wa@LUVVnUbmVk@@UU@@aƒV¯K@U@UU@WmUL@aU@WV—w@ƒ˜I„xXll@UX‚K@KXXVJna@wWaƒ£naUKV„m@UU@mUmalm@@XkVm@U@VƒLmWU@kkWxU@@bVV@VkXVlƒVƒ@UUk@@ƒmI@KUw„m@UmVƒUUwU@lwkV@IUa@mUaVIVKVa@w@U@™UJkb@n@bmJ@XmlVUxWXkJmUkUUVW™xUlU@ƒaULUšmbU@@‚WXkmƒL@xUV@nUxÇm@„XLWbnlƒnV‚nnUV˜U‚nVVz„@lbUVVlULVb@V@nUJkwm@Ux@bWbUK@UULka›JbƒU™U@U@lUK@XUJmn™J@bU@UwWa™x@zkJWnUJUUVšVV@bXn@xVb@J™L™m@X™w@`@bkb@VmXUV¯L@mW@@n@V@‚ƒL@K—IW@@aƒaUx¯@U„m@XbW@@L„V@bnVWVkKUzlV@bÆa@lnI@VV@@LnVVKUaV_VJVbnU@bn@‚‚nX@yVIVxXKVLlUVaXU°J","@@@KlKkUUVVX"],["@@UUVUkUmV@ln@VXVK@K"]],encodeOffsets:[[[110318,27214],[110532,27822]],[[112219,27394]]]}},{type:"Feature",id:"5224",properties:{name:"毕节地区",cp:[105.1611,27.0648],childNum:8},geometry:{type:"Polygon",coordinates:["@@UkVƒ@k‚W@Xn@@K„KVIVVIn™°@nWVzšl@V„_VaVK@kKWaXklaX@lW@bÆz@KnL@ašaVJ@UVL@xnLVJ@LXKlbša„¥l@nUWk„wƒ¥U@VaXa@amLkUƒKmƒ¯kƒmkIUaƒKUIWƒkKm@anw@mlwXIƒmƒUk¯@a@amUƒ`kkKWVkxmUUak_mJmw@w„mXUW¯X›_@WnI@aVwkWWýŃU@WLkU™aUbVV@lUVVnm@kUmV¯™kK™LƒwmVUUaWV™aaWw¯wƒÈ@VULUVUUƒK@nWJkI™l@Umxnbm@kbUJƒa¯bUbVxmLUV™aU@VUUWxkVVV@bUV@XWbnlUbƒbUJlbUV¯b@z„`WbXnmbƒaƒwUwVWUƒbUxmbU@Uam™@Vƒk™VaƒwVaUƒWI@mUKóz@lUlÅ@WIƒb@xXxml@XklULWKUmwUa¯KUXWJkaULmKkLWbkKUVƒImƒƒWa@kUaULƒW¯LƒK¯@kbƒL@b™x@J@bmnnlUšlzU`U@@Uƒb@„m‚n¦°bU„Vx@bkVm¼mx@mk™mVV@bkxVn„aVV@bU@mL@b²`lIVV@lXLlš„bVxn@@bl@XllIVšnbVšn°°wlbXw@mVa°lVnU@mš™VLVbn@@b„@@WVnUV@Xlxn`VznJVb@L@bV`V@šUnwšU„@WUXKV@UUlmUUlaXalLšm„bšIVbnJVIlVVaUUnWVXn‚VL‚k@ƒnWnblnlb²x„xVKVXlVXLVW„LlUVJna@wVL„¼@JVX@`@nnx@nWJU@Vx@XXKšŽUblxUš°„LVKVVlL@KnbVUnJ„IlUšƒnKl£VW„x„IlJ@nšVÞUVVnb‚VX@V_°lnK","@@@UmWUwkU@Um@@VkL@V@„„‚V„VkV@nbVa@ƒ"],encodeOffsets:[[108552,28412],[107213,27445]]}},{type:"Feature",id:"5227",properties:{name:"黔南布依族苗族自治州",cp:[107.2485,25.8398],childNum:12},geometry:{type:"Polygon",coordinates:["@@‚V@IöalK@UV@@KUaVIVVœLlaVbVWnX@‚@LnUlxl@naVLXVVaVU„J@lUUanWWI„@VlV@Xbƒb@V„n@VmVVbk@kU@V›V@X„J@zn`ULW@kK@_WVUK@LUb@Jlxn@nnWlU@@b„x@XVVU@UbVb‚@n`VI@VVLUlUIUV@KmL@VV@XIV@@lVLVmXV„@WLXLW@U`šnkb@Vl@UL@VVV„L„llX@`lIXb„J˜IXW„L‚aVL@ŽXXW‚Ģ™b@bmK@L@°@Vnxmxšn„K@xVn@VkL@V™Lƒakbl`VnnxVnUlššV@@VVXV`@šœk°JV_UalK@U@aUU@m„IlVnK‚V@U@wnaƒw@akU@ƒl@nwl@XLmV@xnƒl@VXUb@V@JlL„UšJUI@UlWUƒnLVUUaVwV@XKWkXJm_@amKnmmLwlƒUIlmUwkKƒ™nwlI@aUaVKšL@bVJ„kVUU@@K„K@a@I™ƒ@ama@UUaV»XIVa@alU@WUU¯IWVUbkVUKWLUwUJ@zmWm@@amVUaUIU`VbULmU@KU@@UmJ@kÅb@akUVylLXUmU@aƒU@KX@Wan@Vƒ°@Vw„b@bX@˜J@L„K@@U@mX@@n°KVUnW@Ula@a@_šx@WšnšK@IUa@wWm@aUUU™VVVIXmlI@yšwXbVxV@@ašInmVI@WVL@k@VšV„V‚aœIlbVK@VVLXa@aVwn@lxVI@m@UUaVKUkVUkaƒ@UymUV—VUmmU„mmkXaWK@ƒÈnVw@mVU@w„KlnXW@V@naV™VKUk@KVIUWƒ@mk@KXU@Um@@lVƒk@UVJna@UWaƒL@a@ƒXa@kmmVUUk@mkkƒamJ—ImJUUmIm±aUUkambkamVUU@VlbUbVVƒxX„WVUU@VUakU@UmUV‚U@mnUVVnUbVJ@b—UW¥kLVamVkUaWJU_UVWKk@@nl„UVVJUXm@Vm@UnVlmbnmJUbULU@@UUKWVIWxnJVb@xUL@bUJWIkxƒbkb@xVJƒbmU@kW±LkKUkVa@a¯am¥ULkalÑlKXUWƒXƒaVakImVƒ@ka@UUƒJ¯aƒX™mmb—KWU@wUUƒaUa™KmU@UXlWb—¼WLUKUb°„UlVbkbVL@VƒšƒJ@nVlUbUXmJ@VX@lbUbU@@bWb@VnLVJ@bVVUz„ŽVL@lnL@b™VVVULmKUk™Jkbm@ƒxVb@V—kƒKVnnV@b@ŽWXU‚„nV„l‚VVXVJUXlVXbWV@VU@Ubk@@KWbUUmL@JnXV°XJ@_‚`UbkXVVlÆkbƒ@VLXVV@‚V@k„KXX@`V@@n"],encodeOffsets:[[108912,26905]]}},{type:"Feature",id:"5222",properties:{name:"铜仁地区",cp:[108.6218,28.0096],childNum:10},geometry:{type:"Polygon",coordinates:["@@°a@aÈbVUlU@aVKnVV„VUlyX¹lWVa@U™VƒnUVU@m™@mUl@„mÞw„@‚xnIVbna@KVI‚J@kwV¥ƒUXÇVkVW@kkKWU@aXUWmnIVa°VXbmL@VVbnVVVUb™VbšJVbVKXkVKVanU@aWnWUWa@U™nk@mVIVK@wXxlLXbVJVlKœbl@VI@mšaXalVV„VbX@@ašalnkx@b@V‚b@Vnx@bVVUXn¤WXn@Vl@Vlzn@š`@I@KUU@ƒV£namVkXa@aVK‚nnU@anVlKƒa@UUU@amk@»kƒU¯@aš„VWnkWmkImU@akaVm@»VUV@UKnkW¯XWlkUKnIWaš@nmlIXmWUnwUwWm@wULmaUJkIUaƒaWa—klwkwmJmU@bkJ@XUJ¯W@XbWbUKUkWJUUVKnn@UmmXUWa@mU@@UI@WmXVykwm@kaULWwU@¯ƒlKUUVU@mU@UkmaUbmV@b—š‚xVnVUJVnƒ„@Jn@@bl@@knJVblInV°@nx@„mbU@UWUbm@ULVVVb@LkJmXkm™VWIUJUXUKVwƒV™UƒŽkLkUƒ@W`Um™kVmIUƒ@kƒ@@a¯lÝ¥kmJUƒn™KƒÑmbUb@Wb™ak@mWU@UbƒUVVkLlbUVƒkXaWK@LkxÇmk@@X@J@Vƒ@@X@VUV@V„IWln@mbXVWXkKWbnxVUnV„ƘInl@XUxVl„¼UV@b@b@xlLkV@VmzmV@b@VUVVLXVVbVLXKmVVLU‚@nnVWXXJ@V›¦UK@LUmkIWbk@@lUImJnšVÒVUnVVbVIVĖUxV‚@bnUVL@WV@@X@V„KlXXaV@@bƒlVxXVVIV@@WkI„UVKUkVmlnnŽƒbllU„VbXVWbblVkb°ŽVInVVV@bšnVx@l@bnVVnUŽUam„UL@bƒVVÆUbUXU‚ƒn@šVVUb"],encodeOffsets:[[110667,29785]]}},{type:"Feature",id:"5223",properties:{name:"黔西南布依族苗族自治州",cp:[105.5347,25.3949],childNum:8},geometry:{type:"Polygon",coordinates:["@@VL@Vl@@IXW@kVUVbnW@XlKVVnU„VlL@b„aVbƒb@xX‚°ÔUxV@kbm@VxkxWJœ„V¦ƒŽ@ÈnšVKšxWXJmV@n„Ò@xVbn@@blLk`VX@bššla²JVUlnn@U±lw@wnw@mlwVIX@@m@klKnk‚a„KnwmmXkƍVm„Uš¥l@nb°n@„aVwVmVIVnI@a„¯@mšU°ƒl@@VnI@JV@UV@b@IUbVJmXöºƒzllUbVa@aXUl@„U@llLnKVaUa@UmK@UšwV„bnKV@VwVK@UXƒV@Vbn@‚w@U„WnX‚@„a@m„I„™@UUKlaUaVk¯ƒVaVLXK˜»XaWk¯mƒkğwmW@mIƒVkwƒJUIšÇVwU™UkVKkƒm@UkmU@WÅwm£Vƒ„m¤¯IkJWa™_™lUbmJzÝJk„ƒUÇVU„ƒ‚@bU„Ýn™m¯LUb@`mL@VkL@VƒUmmk@UU±Umka@kUƒ@ķymUkk@mmkÝmUaUakImV@V@VÅLƒ¦ƒJUXmJXšWb@n°Æœx‚¼nV@LlbUŽUbmL¯@ÞbV¤nbVx@bUVlblIœ™@KVVUnVJUn@VlLUlmLUUUxmK@I@@VW@@bU@UJmUkLVVUl@b@V"],encodeOffsets:[[107157,25965]]}},{type:"Feature",id:"5202",properties:{name:"六盘水市",cp:[104.7546,26.0925],childNum:5},geometry:{type:"MultiPolygon",coordinates:[["@@ôyVL@nXJV„Ub„x‚bUŽlšU„@ŽšnŽVbV@naVw„a‚VUXVx„x„bnaWmXaƒ_@y°aVUkaVI„aVamkXa@WVU@aUUlUXwVV@UVšbVUnKUwVa°a„bVIlan@manw@VšklJXI@m„LVVVUVK@U„ǃk@KUa@UkaVU@UVWV_XWVXVWlLXKlLXaÆKšwVL@akKm@Uwƒ@@XUVk@VUI@wWK@aUV™I@UkK@ƒmL™Wƒ@kImJƒUÅVmkXUW@UJkx@nmx@xkxV²m@kmUV±Ikb™™@aUWl_kK@am@Ua@wƒÑ@mnUWIX™wULm™@DŽU¥›ƒXIlwUwn@laU@Vw¯ÓW@w„aUaƒb@akKƒUmVUUkL@WmXUaUV@lWX@Jk@@UUKULmLUJmzkKmVX°VšUnWKUL™ƒƒL@mU@UnVJ@b@„UV@Xƒ`m_@l@@bmbXJmnnš@°˜wnn@ŽVLX@V‚@nVl@nk@@b‚l@nn°WlXzW`XXVKnUlxVbUb@‚V„Xb@Ž‚VxÈbVlnbmn@ŽkVUL@„ƒŽmLUVVL"],["@@@ƒ@UmWUwkU@Um@@VkL@V@„„‚@„V@VkV@nbVa"]],encodeOffsets:[[[107089,27181]],[[107213,27479]]]}},{type:"Feature",id:"5204",properties:{name:"安顺市",cp:[105.9082,25.9882],childNum:6},geometry:{type:"Polygon",coordinates:["@@lL@bUK™xÅLWbkKWLkKUXUWWXU`UX@VUVlb@VVb@L„l°xXx‚bšbXUVb‚VnU„xšKlL°šnUlVn@UmVU@kUUVašblVXKV@ƄXþlXUxnU@mVK@_@ml@UU„@šblU@KnLVyUw„@@UmkšWVw@UVK@VXzVK@n„VVUUW@kVJnlaš@nKW™kaWL@U—™õb@JU@mU@@_WWƒL@lUU@WUUK„@lakÅUUlWVa_@`WIU¯mW@InKVVXa@Ll@VaV@@UXUWakUVWUIUW‚UkUƒƒmVXW@@amUUm„L˜l@UUa„wn@lašIVlnLVKUUšU@amK@kUKƒVyUU@aUImK@UXa@aV@VakaW@@UnIVWVaUkƒb@mWƒX@Vxm@UaU@W„@VULUxU@mLƒaUŽ™x@VnL@VVbUbmLkK@kƒVk@WV@bUbVakk„yõ¹nWUIVa@J@aVUU@@ImJ@Uk@¯„™V@nƒ°@bmJUUJUnUxƒbm@¯Žmak@™¦ƒVUnŎWlnnmxƒLbmlkL@l@nWVnlÆU„VnIlJ„@šXnK@„lL@VšJVU@bXL@xVJUl@VU@W„@Vxn@"],encodeOffsets:[[108237,26792]]}},{type:"Feature",id:"5201",properties:{name:"贵阳市",cp:[106.6992,26.7682],childNum:5},geometry:{type:"Polygon",coordinates:["@@nŽlLX„VJ„LVblJ„n°ln„„LlVnKlU@nUUa@WlX@l„n@‚Vb„@la@a„„šlJ°¦„Kšwn@°x„LVkUmmwUmk_la„bšK@UlK@UUm@wƒL™mnwmw@U@¯@KnL@aša‚ġXWW@UKbƒKWX—JƒIWakJ@_kWƒkƒKUU@UVKk@@Ula™mV_X@WKXKƒ@WUUnUK@kU@WJU@@UnK@LVUVJVkUK@UUJm_@UaVaV@UU@Wƒw@aV@Xkmmm@kw@IVa@KVLXU@`lLX@VKm_@yƒI@WœU@UlVl@UanU@Uƒm@U„aWaU@Ukƒ@XJmXVbkV@ŽƒIUVUbWUUKmbk@kwmV@K@mWUXUakb›KUUUJVb@LU@@VkL˜š@VXKlbXšmL™@kbm‚UI@lVXUVƒU@mULWy@UUL@VUx™Xnl@Vƒ@VxUzmK@LkV™aƒ@VVk@@n@`UL@nmV@bmJ@Xœ`WX°WVƒn@xnxnIl`VbnVlwXUlLl‚„_nV@b@bl°„V„nWJkx@nmx@b"],encodeOffsets:[[108945,27760]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/hai_nan_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"469003",properties:{name:"儋州市",cp:[109.3291,19.5653],childNum:1},geometry:{type:"Polygon",coordinates:["@@஼jpnr’``ŽpRVHʘ̤žZt^JÖA˜[†CâlTébQhRPOhMBcRSQiROE[FYdGNOEIH]MgEAMLLIAG_WMCSL@ED]PCLYC[ZIHgjSxJTMbHNEFCMEE_HSDFHSLECRNSFDRICHNADGPI\\RZGIJTIAHLDQOHG`GTNCOIC@eIGDWHIS[kiE[FMbECZS@KKS[FDWsCeRuU_DUQNOE[LKGUBM¨EDQP@HWHGDImXƒCog_~‹I_fGDG|QDUWKBC\\ore|}[KLsISBHVXHCN`lNdQLOnFJSXcUEJMCKSHOUMDIm_‹DI`kNDIGEYFM\\YPEEIPMSGLIKOVAU_EBGQ@CIk`WGGDUM_XcIOLCJphHT_NCISG_R@V]\\OjSGAQSAKF]@q^mGFKSW^cQUC[]T}SGD@^_ˆaRUTO@OHATŸ”"],encodeOffsets:[[111506,20018]]}},{type:"Feature",id:"469005",properties:{name:"文昌市",cp:[110.8905,19.7823],childNum:1},geometry:{type:"Polygon",coordinates:["@@€hIJ¤Ī¯LQDaFßL[VQìw€G‚F~Z^Ab[€¹ZYöpFº lN®D´INQQk]U‘[GSU©S_­c‹}aoSiA£cŁ¡©EiQeU­qWoESKSSOmwŸćõWkàmJMAAMMCWHGoM]gA[FGZLZCTURFNBncVOXCdGB@TSbk\\gDOKMNKWQHIvXDJ\\VDTXPERHJMFNj@OwX@LOTGzL^GHN^@RPHPE^KTDhhtBjZL[Pg@MNGLEdHV[HbRb@JHEV_NKLBRTPZhERHJcH^HDRlZJOPGdDJPOpXTETaV[GOZXTARQTRLBLWDa^QAF`ENUPBP…\\Eji`yºEvåà"],encodeOffsets:[[113115,20665]]}},{type:"Feature",id:"469033",properties:{name:"乐东黎族自治县",cp:[109.0283,18.6301],childNum:1},geometry:{type:"Polygon",coordinates:["@@ªVLP`@PEdNRAHOPEAKHEVL`GZBJfvdTAXNNTZJFPrHHNpKTD\\ILHbEVd^J‚OHLh@NNBnHP`\\xH@NBRLJTlŽNv_^CTLd@bNDVFbxdFV€UPBTKOGEOUO@OEBXQP[H_EI\\EbeYa@UO_J‹MEJ_IEDKJUGMDcNUd_FMTEJSGoZ]EIYGO[YW‘gEQ]a@WHEDQKUSDUGAbYBUpSCYNiWqOSQEoF[UcQISWWNMSDe_cLQ_UBiKQOOASQAWgS­ā]ZaŽSPÝZ]XMXSŒ[^oVËNgNKlE RôEø"],encodeOffsets:[[111263,19164]]}},{type:"Feature",id:"4602",properties:{name:"三亚市",cp:[109.3716,18.3698],childNum:1},geometry:{type:"Polygon",coordinates:["@@®ĂhTBXTRPBRPjLVAR`dKf`TC‚NXMTXRJVdE\\FpTRrPjXZMTDVoZABaVHTCLVCRGF@X^bFR’hZXP\\ZHHMA[^wBWXJlW¤EJ[bCTOF‹WWMm@ILMGWQ@DQ^QNWFSHEbF`OXNbO„VNKTEPDTLTCCVTREfvfEHNbRAENH^RJXCFHNFRpVGHWISDOTMVCZeGamaLoLÛD¹¹ėgsia{OųE—Tt‰lɂwr}jŸR±E{L}j]HąKÃT[P"],encodeOffsets:[[111547,18737]]}},{type:"Feature",id:"469036",properties:{name:"琼中黎族苗族自治县",cp:[109.8413,19.0736],childNum:1},geometry:{type:"Polygon",coordinates:["@@bRFnHNbHŒgN@NPEnbXP@bND`NT\\@\\QZb@`@J]V@XhžDpW„nCJGHGXO@CR§FANHVKLF\\MPVR`CvVfQtDPKpGHG@S`WJP~^dSTHWX\\RHTFACQTIAUPOU@MG__IaYSFQK‘NSbORHXCZeTFJg„B`YBMNMFi~IVDV[tGJWXGDQRGF]ˆJrALgESLSAYDGIaFeXQLS\\MKSLSQYJY}eKO[EHiGSaK[Yw[bmdURgEK^_kcSGEOHKIAS]aFSU@Y]IWFUTYlkP_CUOUEkmYbSQK@EMWUuAU\\M@EpK^_ZMDQ^OXwC_ZODBrERURGVVZ\\DTXcFWNIAWJWAYUUFYEWLQQaCIZeDM`cLKRGpanJZQd"],encodeOffsets:[[112153,19488]]}},{type:"Feature",id:"469007",properties:{name:"东方市",cp:[108.8498,19.0414],childNum:1},geometry:{type:"Polygon",coordinates:["@@ºŸx‹JYZQ”IŠYXLl@dR\\WZEn]bA\\S~F`KXaDeTiNO^EEKWEDQXITBXaWaDQMUJOIaTWf@NJV@dSxGZ‰Fu_@WMKAUˆ}AQ@MwG_[GOAmMMg@GKP]IUcaFKG[JSCoLGMqGEOYIMSWMSBucIeYA_HUKGFBLOFGPQBcMOF_@KO©UAtERadwZQ\\@ÊJÒgòUĪRlR°KĮVŽLJ"],encodeOffsets:[[111208,19833]]}},{type:"Feature",id:"4601",properties:{name:"海口市",cp:[110.3893,19.8516],childNum:1},geometry:{type:"Polygon",coordinates:["@@ńZƂtĢ¬æßFuz¹j_Fi†[AOVOFME_RBb]XCAKQKRSBQWSPY\\HbUFSWSPoIOcCOHIPkYCQ]GdGGIFQYgSOAQLK`MFUIGa@aQ\\GGUFcHKNMh@\\OYKAigsCgLSF]GOQO]@GM]HyKSHKPW@Pxi@EMINYREXWRQ@MQcFGWIAwXGRH\\yDI`KJIdOCGRNPNtd\\UTMbQYi@]JeYOWaL[EcICMUJqWGDNZEXGJWFEXNbZRELFV]XQbAZFrYVUBCLNFCHmJaMIDDHXHEhQNXZ_TARFHVB@DTQIRR@YHAJVnAbKFUEMLd\\c^ÍÞ"],encodeOffsets:[[112711,20572]]}},{type:"Feature",id:"469006",properties:{name:"万宁市",cp:[110.3137,18.8388],childNum:1},geometry:{type:"Polygon",coordinates:["@@^J@ZTVbET^JBGLFPTHld]`FLQhcVanx\\\\ZbLHTGj\\FLP~fIZRZPVTQFSVAFJE^NDLEE[~LjsxVTG\\NZZNGlLRRGLJTV@hPZANN^@T\\NEPPbDZXO`d^HSvcJDIV\\XZAJUFCLNP@PQ¤@[ïKLÑIÏ]ÇE±I{uƒ­YśUćFcYUmsVeBSVgB[RO@aYYPO^]@UVaNeDShMLG\\EfFVE\\F`"],encodeOffsets:[[112657,19182]]}},{type:"Feature",id:"469027",properties:{name:"澄迈县",cp:[109.9937,19.7314],childNum:1},geometry:{type:"Polygon",coordinates:["@@T\\GJCXJH@fJDDPNCNJENN^NLHBNSx@DDYbBLLDRbjZTj@`XXTlG^Xr@PJLW\\WLTlWR@HDJTD@X_PO@STMDNTMVV@NLDM`M\\XM\\JNBH[PYZ‡úYzŸ`Ċ\\ÎÝd]c[NKVFLEBaUmBIZGQ@JQSR@CUAEGBQ`SWYRMFgWGCGJCbNnIDGMEDKVAZUEqBYRa^WEUFKYQMaFWXEHIFWMYHCrXVIIiaK@aMCUYNSIISTwXALKH@XWXIEIJQCG[IEQDE_XSBaa[AIPW@]RS[FWS[CD]PEBYNGFSaSyJG]@ugEUDQlGHiBKHUIoNSKqHFaPMICK]UUHIPDJMuCA[SCPIDIOILGAEmU[POPBVSJDREBGS[QXWSGcT}]IO_X@TGHoHOLCX\\ELT@LYTD‚aFENF\\lj"],encodeOffsets:[[112385,19987]]}},{type:"Feature",id:"469030",properties:{name:"白沙黎族自治县",cp:[109.3703,19.211],childNum:1},geometry:{type:"Polygon",coordinates:["@@D\\RV]dTXELnHr]^@LETBBRTHPi^[@U`QTHDJ`MGSogDIPKdJ`WVNHCXHl_DJR@AH`FBVPUJLHKNTJOFFZON[ZEHFCJlMJ_ŒCn`CJVNGPLTNDFIdVTWEIPmRKMc_kDMWGGUTAtJLK~\\f{pqD[LAVXRCH{HC`eŒJ`}@W^U@I@_Ya[R[@MSC_aMO@aWFmMOM@‹haGGMEmaQ[@MESHaIQJQ……MckBIw[AOSKKAMPSDSLOAV_@@`KJRbKRDfMdHZERgAWVsDMTUHqOUr@VQXTT@Tƒfg‚L^NH\\@heTCZaESNObHPƒHeZF\\X^ElM^F^"],encodeOffsets:[[111665,19890]]}},{type:"Feature",id:"469002",properties:{name:"琼海市",cp:[110.4208,19.224],childNum:1},geometry:{type:"Polygon",coordinates:["@@TP\\pATHTGlZDJGAQjE\\Rb@jVBDCN`JZ[NCNHNXbULPrP\\KNbMTLjJJRFP`“pNLZz^FLRHjVPZ@hxVKbHBHMNNJFRlLzGPnNHhIrHHADcPWdUAmEMVQDSKYHY\\EhBN^HpXGNDBNNBnIß‹Å_g{³So]ã@ORO@KMEDIVYB[WJUICudGTc]P_YWaCOOMFS[]@MMYBgOU@ISHKQQkKMHYY[MSHwUit}KF\\KFMCF]EIUBETSROUKTLT[NKTWREfJbCHBZKTFTKh"],encodeOffsets:[[112763,19595]]}},{type:"Feature",id:"469031",properties:{name:"昌江黎族自治县",cp:[109.0407,19.2137],childNum:1},geometry:{type:"Polygon",coordinates:["@@`ZĤd–`òüˆ˜ “BSPGP@VSbQ`‡@]HC~T^SE]N]FkW]E[fY„GGOPaTMbFDYfS@g[MGK]h„e@SSSRW@UVqrPVGNStCXUhBFQGYNcCeLQQaLI@_`@EUwcEaCUaMc@SK]Du`MSkKI‡~BVNL@X`‚EvYŠwHcTU@MIe@SXJbIPNVCRXbWbSAWJCRXFFL]FMPSjCfWb_L}E[TaBm^YF[XcQk@WK‰Z“JYRIZwŒ¹ "],encodeOffsets:[[111208,19833]]}},{type:"Feature",id:"469028",properties:{name:"临高县",cp:[109.6957,19.8063],childNum:1},geometry:{type:"Polygon",coordinates:["@@jD`hNd\\^dZädĒH´Op@ˆùZY\\OAGIMN[[W_NCNMKU@NUMSNCTSP@`O@WSCCI@GXQSkXKX[IK@OWqH]SkWW@_SiiYQaKCAKZaCCw@MTGAMKM]FMMIMDSM_HGHRPKCBGSJJIYH[QOJCHMBDGQJECMTDQKFGTCEGTF`NFEDMFaGSNwIiTGhYJD\\KZODC^@FTKND`XBHKJNKFBNhG^FJMPcHEZF\\QPRjQTAdgNOPgQaRSê"],encodeOffsets:[[112122,20431]]}},{type:"Feature",id:"469034",properties:{name:"陵水黎族自治县",cp:[109.9924,18.5415],childNum:1},geometry:{type:"Polygon",coordinates:["@@R]NC`YL]FoN@V[vBXVFNL@TRZalnVFVP`DlOZkVSXEE_F[EUFeH[NKTgfCbMVU^@P]ZObZP@\\QhATUfAtUasñiāEoI]eYǯ@aKmaeƒWuCºKÜKpnbHbYfUDSNCPJTRAHJTDJSfDNLHXC``VBNGTYCQDIXMDSP@xLNEFRNXBIpVNLXah@RgF@`qOML@LJNSPLbaHAh@Jdj"],encodeOffsets:[[112409,19261]]}},{type:"Feature",id:"469026",properties:{name:"屯昌县",cp:[110.0377,19.362],childNum:1},geometry:{type:"Polygon",coordinates:["@@\\OnVBFKHPJCJOJTDB\\vDINOCGJVVL^JDONEbrGTLpMVJLGjAHGRkVChF@vH^zIbTETMHAZOFC^\\DXT\\EffAP\\PdAV@UIYfS|S@YPICMeM@sC[_A]VQEwyHSMuNcAUlQJMVGMS@mVBZPFO\\CSFQK[LqDMACiUa@[QiFBRIHYCHkGSBS[oSOqB‡IE^QHCRWHIXsHU\\UC}JEjMNAN_ZƒAIhSEYfWDQGaPMTL’ERZTJb``NHV@"],encodeOffsets:[[112513,19852]]}},{type:"Feature",id:"469025",properties:{name:"定安县",cp:[110.3384,19.4698],childNum:1},geometry:{type:"Polygon",coordinates:["@@JjDNdJ\\FbKPXfZ^Ij@RZNaVSc[MsMOHQPDJcLIJ_zCG[HQxWJBHXdENRR@XQFWZQQGOFSWUCI[WCJuRGLXNMPLhCl[Ta@SqGgJMGOmyHkKEQMINMAGaGULgwY@UOGiKQ]EYyMK”oO_QEIIKiNSMa[LqOKOaVMWMGMDY\\_IKrL\\ERT[DEPYOUA@nNTUHINkRBVMdNvGTxzRF^U`BD\\@tfNDNOJ@Z{TeTJZ@VU€cB[OBOeeQT@^OXBJb\\AbWTF`RCJFH\\RDJIJFXW@WLGBKxWTSJJMTVZND@bbL"],encodeOffsets:[[112903,20139]]}},{type:"Feature",id:"469035",properties:{name:"保亭黎族苗族自治县",cp:[109.6284,18.6108],childNum:1},geometry:{type:"Polygon",coordinates:["@@FJp@fxpQ\\ApN\\GNPNBM`HLMrXLXj\\PEHnI@WUCEM\\GTc\\GZYHTPBHRCPTd€H\\K\\@HXi–BJILJJAVNTOZJNtFPC`YxDPWci@IBgbGKaTOIM@KNKrP@_hE@QbgKWUMJoWAQMFEKM@wTONCJWRCZDHSAM_UD_GWMKeCITSCGIQBGXUHQoMEEGWDQIG]FMQBMaFGueFeSQDUSDSKOCSFMLƒUaPWM_PaEGFETMX]RCRR@HXKN@JNnXXEŒSPaDI\\£FkXWIAX]xB\\GN"],encodeOffsets:[[112031,19071]]}},{type:"Feature",id:"469001",properties:{name:"五指山市",cp:[109.5282,18.8299],childNum:1},geometry:{type:"Polygon",coordinates:["@@TCNOLBTLBPx\\AJdl†NR†RIbJTGNF\\@RcIYbmHoLQdKN_fCJYbDRRXKZFVEZVXBXIJBXMdESW[CUYHUVQFQAqsEIMPYMSBUIIJKAIj•GW[@[LGScDOGQOAGSYZ[HSd[HFNVD@XmJFG[OWiWKNqGKN_MAMO[HoM[BoRewo@Y^HpITSFENc`MVCdHNIVCLJFI`NFIŒP`@VZbaf[FFJG`O\\WRFA@PVPFPPH"],encodeOffsets:[[111973,19401]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/hei_long_jiang_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"2311",properties:{name:"黑河市",cp:[127.1448,49.2957],childNum:6},geometry:{type:"Polygon",coordinates:["@@VÈÞ@Žkx˜nXŽ°VÈa°V@kôw„b‚š„JVškXlVUx„„@ŽlL@xkVV°ƒ„VbxlVUnVxk@ƒ„ƒKkŽVb„Il„@°kVl„@„™lÆnkll@@V„VXƒŽš@V„²bUlƒVlV„U„VÇn@nkJšŽlkVbœ@›x²V@n°VUnlKU„n`@n°bWLnVUblVUVVbknV`°kkŽl@@V°@nz„J@XšxlWXb°n@bƒĠlbXb™bVbƒJ@Všb„a@„„@lbUbšVmnœ@lšVmnIW‚œ@WbÞ@„n@x°@š„ĢaƐéϚnœ„‚lČ¯ĠŻÈwm@ôçU™mm£Xy°UV™›@wÈ£Ǫ¯kõÝçUњ™Uķ‚ƒĢkVфÆšÞU°nŎ¥ČUĊx°m°¦żVƐœx°ƒÇ£@y„UônރÆ@Èĉ°Kô¦šW„kWU—bÇ»@™ÈĕWÇÈ£ŤU@›n£ÆUUKVamanwŃmÝJ¯k@JƒIkaVaUUÇbkaÆÑkWmÝUۙ™Ý@™ƒwnU±ƒ@kkV¯KUkƒJƒ¼U¦ƒšÅ@ówķaķůV¥Uaó@Åwmƒƒ_kVƒwĉ‚ĉmmn_V»™a@U™ƒVwķóƒ‚U¦LǫéóXÇmōLǓÇķxÝkƒƒĉ™kmakbUĶ°@W¼„@bƒšÈÆ@Ė™L„l@„°J¯„mkl¯L݃±L—amJ@¼ƒ„™VƧUó„™UX˜ċb¯ńVbkÆÝI@llx„k°V²šV@Uxގ˜L@b„@b™`ƒšÇzkókݤ@ğ¯Wƒ™LĉǙLmmnċVkbUaƒL@Ž¯„‚bU°ğL݂Ý@"],encodeOffsets:[[127744,50102]]}},{type:"Feature",id:"2327",properties:{name:"大兴安岭地区",cp:[124.1016,52.2345],childNum:3},geometry:{type:"Polygon",coordinates:["@@k›ƒϙmƏêġb™ƒ¯@@wƒmÝ@XV@IlŽl@bUxl¯VlV™bV@ULVlUV™_kx™VVV™ÈÝJ@„¯šU„™lm¯x@xóÒĉ¼m„¯Wƒxţ@Uz¯ƒWwnUwťƒ@knƒWƒ£óVƒUUwğyó¦WI—Vmm™I@±kwÇ@@bƒ@ĉ¼ó@¯wó@¯aó¼›KՃaUwmWUwÅI@aƒKó@Ua™LƒaƒVÅwō¼UUÝl±I—¤VxÇx@zkJmnn‚mbnz™xlŽƒl¯ČkJl™°@„kb„Žmx@x™@kêmVnŽWxôXšxU°„bWLóJnÇWĵ„V¦™ŽƒUUb™b™ÆġK™šk¯™VU±aXmċÑUwĉKġ„k„™ŽVxk„ÇKkbƒIƒ‚ÛXWl¯bƒŽ™X¯K™bĊš„„ÞVƚnŽĸ²lxUŽ°n°òÈb‚¦—xVbƒŽƒ@¯„Vx@¯VķÞČlĊ°KĸŽȘI°¤ČIôŽò»ƨnȰKǬ¦ôWŎÈƨwlƒnKVXmbX`lbšwkVW‚XXŽ„L°a„ƾaĊ£nƒ°@°¥ŎzÞ¥‚»œalwôkƒJ„a@ĶK„£„bU°ĊxźVÈUĠ¥ƨ™VI@XU°x°Ln¥šw°UmwXm݁V¥ĢŽ°@nU@mÆ£š¯lKœšÜw@aÅU‚¥UaÝIkmV²‚nn@Ķ»@Uk¥VKÞ@ÞÛ@ƒkVmĢa@_ƒJómƒǖ¯Æw—óÇa@alƒUwšwĢřšk@wÆWXUWXƒWa™m@_ƒ»ÇéXaĸwVa@ÝKkUWkX‚kšKXxƒn@lĊV@¯m¯nřÆwš¥"],encodeOffsets:[[130084,52206]]}},{type:"Feature",id:"2301",properties:{name:"哈尔滨市",cp:[127.9688,45.368],childNum:11},geometry:{type:"Polygon",coordinates:["@@°`„_šJlUšŽ@„„@V¦°JUšŽnLôlnŤ@@šÈaUÒVbkbl¤ƒzk°ÇVÛô°IlVUVôU„xÆU„Ž@bźĀ„º@¦šb@l²‚UVlœ@°ÒĠxšnXxÆVô¼Þ@Üx²KލlƒVÑ°UȰôlwô@²ƒĸ°„lanV@„šVŎUll@bÈnÜm„wĢ@la@ÝÞb°UXb˜lŎ²ÆškšV‚I@ŽnJnĠŽ°knƒÜbĢwna@a˜kÞKƒĀ„a‚™œ‚‚IVbU¥wĠwkô˜xnLƒċVçkaUƒ±IUmnġW„°WôĉšalƒÞÅĵ¯@W¹XÝaƒb¯a±X¯ºLƒaVƒmkLóƒƒbkaƒVUKVkkKV_@aÝykk±L@ƒÅU@yV_™aU¥ówÇx™@UkVƒn@lƒkÅlwšWVwUkĉmkklW@šašbVwnWWƒ—wWL™™@Ušƒ™UƒÇLšÇmƒ„@wƒJĉƒL¥@ƒÝ_@a¯y„UWw¯ƒ¯Uġx¯aÝXVmaU£ó±›¯nwƒa¯óÅVƒXman™„Uƒ›lUXkWa@mkI„›ğaƒm™IklÇU™„kĊƒƒzkKƒš„lU„ōĬlš™„@ŽnX°@llUxŹ²mKĉVWwk@UbUK@bmVmI—ƒVmwaWxXlWȁšmºšÞÆbUxV@ĵńWÆĉLkWUbƒaWzkbĉ`U„±LklōwUVÝ£™UW`Uwk@mk¯VkaõVX@WbL™K@XƧºWzxƒK@lmX@bkVVÆk¼Vbk@Vn"],encodeOffsets:[[128712,46604]]}},{type:"Feature",id:"2302",properties:{name:"齐齐哈尔市",cp:[124.541,47.5818],childNum:11},geometry:{type:"Polygon",coordinates:["@@Þ@ށĠKV¯a°ƒ@„KVblaČU‚mnnšKĊȚKX„°ŽĠ@Þ£ôllÈy„™š_@a‚ƒ@a—KݍVwU@±™¯Uƒlkw@kÞJlÅUa°ŃČaW—šVôƒƨVšU„ƒ@»nI˜b²Kބ°Klkn°ƒ¯I@ƒƒkšK@ĕÇń™@aƒX»¯@VĵlaÿVamI@aÅÝउýƒĊȗJƒôȁÅkmƑۃ@kxġ@@l™aVk¯»ƒīŹaƒkƒ¥Å¯™JUaWU@@w™aƒ»„KUkÆkUm„UmwÛ±±UUbUŽUXƒwWwÆÝk™lkUanaWwnKl™kal¯ka™ƽa›kÅx™a¯@™amb¯V™lÇwÛĀ™V@x™šmêVƜVV‚aôV„wÈx@šˌx„¦VÞ¯VšlmX@‚ƒL@¯Ua¯LmV@„„°X„ċK™V™ƒ@UƒÈ@‚¥@w—ƒġIU™km¥Źwƒ¦¯lmn@°kxVV@¦óam„n¦l@nx™lĉVóšmx™n™ÒĉĀĊ¼„þ„šǔêÞ°ˌĠÞÒ°ĀɲĀƨźˤȤƨĊ°w@£nymwnkUUV¥ôÑVmkÆmUUVa™mVIkmô„lxkXÞþƒbl„ƒl@kV„ƆƒV„xV@š¼VÒ@šŽUŽšnnނJ"],encodeOffsets:[[127744,50102]]}},{type:"Feature",id:"2310",properties:{name:"牡丹江市",cp:[129.7815,44.7089],childNum:7},geometry:{type:"Polygon",coordinates:["@@U`lLUlVL„Ulb„aô„lKnŽU„„b‚K°¹²W°b„aÞb˜knyUlUkamř²L@m°@lšmš²n`ôÅlK„x„ÜKnxV@„l@œƒ›ÅXyW_k@™wm™ŹĕmƒX™»‚ƒÛ™l°ƒôšÈ„»š—ô˜ô_WW@Uœal»šwU@@wšUVƒš@VƒXI@w‚Ģ͑ÞȻ›aU_@mUkly@¯óV»XmWUXUWmnm¥nUUaWLk»Æ²IÇa™wÅaÝ°¯nUa±a™ƒ™@¦õÆğ„@„™@Åb›xU܁nÇłlb¯¦„ôó»mƒ—@±ƒUk@Wwƒa¯xU„V°ƒxXbǎŁUV™™ƒK@¹ƒKUaȯ@ōݙXƒal™ƒlÛkalÇUǫÇńÇakbÝƆ¯nlš¯Ž@¼™VUx@x¯W¼™Æ¯šmĖ„Ĭ¯ČƒVk‚ķÅmxœ°ô²V¤‚bUnÞW°bĢw°V°„XxƒV°z@bÞ`@„‚¦„KĊŽ„I@xƒŽn„™ÈÈK‚„šV™„@VššXK˜xX„mXUx™a™b@‚kXllĊnVlUx™XkxlÆk„m@U„Vlš@ÈwôxV¦šbU`@zÆV@„²KllÞz@b"],encodeOffsets:[[132672,46936]]}},{type:"Feature",id:"2312",properties:{name:"绥化市",cp:[126.7163,46.8018],childNum:10},geometry:{type:"Polygon",coordinates:["@@ऊþÆÞ@bnJUb‚ĀnblŽĊš„„ÞlĸwǔÈŎKÈnôWǬê‚KV¥„ĸôUxš„@VšbU¼m`nnĊŽĊ„xlUšmkaVÿšLšwš@°»UmbKmݙUšwUmVknKUUl¯ƒKU™ƒUȃ‚™nK@ĠkX±lX„°„L@¯¥@wV_m›ĵ¯Ww™L¯ƒUkōƒÇVU™l›w—V󁱃¯aƒVka°wVk°mÞ¯Ŧřƙl™²™Ŏk™U@ƒmUkb¯ƒķŽ±„ó@kxȯó¯VUÒk„ÝŽ±LÛwÝ@ó»ÅUWw™mğw¯Ñ›@UkV±@k™a@¥ƒ¹Źÿ@aƒÅVƒwóVVUkU¯JÜóÈUl¯„yk£laUaVÑÇb@™ţ@kmómK™V¯IU¥ƒ@@ƒ™kV™Iƒ`@ô™¼„blU„lƒ™bÈb@xÇKkĢɳaÅɆō@ƒŽVƒK@z™@@¥ÆKnÜ@@aۏUw›wnU‚ķ@ƒ_ƒV°Ž@„klVššnULVVÞbVl@°™@nx™n°LŚÆlV„ȃmU²@VmĠLƒx„n¯xkWƒzšJ‚wnLmbXbW°šÆ‚™²™@™Žšx@JVx„L‚Ā²Æ°I¯º‚È@ÒnÈ"],encodeOffsets:[[128352,48421]]}},{type:"Feature",id:"2307",properties:{name:"伊春市",cp:[129.1992,47.9608],childNum:3},geometry:{type:"Polygon",coordinates:["@@ƒKƒ¯kWW²ğl@ŽmLšÇ„„VVš„Lk°VVmLUlVn™xšVnނLnaVŽ¯¼™@™x™KUĀlb™n„`n„Æxô@VbU¦ĸŰĸbôxÆ@„™V¥„»„IVl°LUŽll@²„mV„x@ššÞܚÞVnŽlXÅÒlbÈaVVUblb„J@I°lÞIn‚Æ„mxnbUbVLÅVm¤@œţVǤXÈÇĖ@šÈ¼˜aXVÜaXbWŽnzŎašř„KôbšUlw@¯naÆKnUU¯Üa@mkkVUĊm„™żÝ‚ǖŽ‚K„™°L²lÆI@ƒ¯¥ĉƛVaÞk@ÝVaĠlnUVwƒœómaƒ@™wĉ@™a™VƒxamX@aƒ@UaÅLƒaVWƒ_nWm£nWm_ÅV¯ƒm@m„󤁚ݦƒ¯ÅalmX£ƒ™VWUŚw™mÇ@@IV™„WUw@ašI@„k@wŎ»Wƒ„ƒ™ÅVaœK›Ika@¥lUkUlwÅwVyÈwWU@a¯U°m—Ç@UçƒaVa¯mV»ÅwÝUlƒUk™V@k„mUk‚X£šw°@@ǃaÝIƒƒam™Ûam„¯lğmmI@J™U™l±ÅōŽ—kWa¯VÝa@Þkbġ@ƒxÛnÇm@akkōVōl±škšÅšťŚÝ°¯nUl¯xlb„U°b²„ô‚˜Uœxšk‚VÈUŎ„Vl°„šKXxĶ°nœU`@x°¦@"],encodeOffsets:[[131637,48556]]}},{type:"Feature",id:"2308",properties:{name:"佳木斯市",cp:[133.0005,47.5763],childNum:7},geometry:{type:"Polygon",coordinates:["@@nš„b‚„ÞJ„b@ȯ@™xW¤Vlƒn@lšUVlk„ÞVÆxU¼°nUb„bVèÈ@˜ŽnIn‚@šĢmlUw°™żƒ‚VUn@lnL@VôbšwĊ‚lœ„JķĸĢl„wôwƨxVVUƒŦšxšLź™Èš°`nnĠwŎJސĶwôJ„@¤Xn܄ĸlšn°¼È°lŽ„„Uš‚b„xš@„l@ÞÞÈm°„lôwšL°¼ĸ‚°Þ²nĠ@ôwÞ`ŤI„V„ÒĠU„„@„VJĸbƄ²@°ŽĊKšœ„JĶaĢȰ@ô¥°nš¤‚bČUš@Vx„mUw@a݁ţƒÇ™ķƒ@ĕķīU¯²@ÆmVÑô¯X¥ċç@™ĉ»U¥ÝţKWVÅkUVÝŎUmǍÝx¯aķxÛUóL¯a±óōb¯™ƒÑŃVÿƒ_Åķ„a@UƒK@wm@Van@UmmLVa—@VImmXUWƒÝUřƒKUwÝUUƒkVƒk@l¯X›‚Å_ƒJ¯k™Jm„ÅLƒa@¥U@¯Vƒz¯@ƒ`@¼šmxƥšŏKÛk@±laÛ@@Xm@™ƒ@xƽ@WŎnšˣĕÅ@@aÅ@@nÝbǏ¯@ƒ_U›kUWƒkb™wÝU@ç„Wlw@anIƒ¯lyœX°m°VšašÛšm@„mVwÞK°ƒšXlaXmm_ƒ@UƒkwÝK@ƒVI™ƒXmV»ƒI@aƒ¯ğW™bġaU_¯JU¯ġŽƒ„ĉ„k„ō`±nÝÆk„™bóĊ¯Xƒ‚ĢX‚mVn²JV„lbUè„ČmK—wlóğx‚xV¦UaJ›šƒbƑÿÝL—l@bmbġx"],encodeOffsets:[[132615,47740]]}},{type:"Feature",id:"2303",properties:{name:"鸡西市",cp:[132.7917,45.7361],childNum:4},geometry:{type:"Polygon",coordinates:["@@‚LšKVVnkšbVšÈb‚²U°VnklVlaÈL@anU°ÜmXV`œnôLƒèšxlŽšLX„˜L²ašVVmÈX@ķ˜lnU„Èl`ȹš@ŤŽ°U@x„KnnV„mlnnUl‚lVnnaŎwlVÞ҄@n¦šLVŽ°lšwVk„Lšaގl„n҄š@xmLÞ¤Wnœ¼‚WÈLVVUxlÈô„„WVaU_VKšKXUÆbn™‚nôK„bÞw°bÆWXamVwœK˜™Uw¯WUk„UlJUwVUa™@@kmyzm›ĉw@kVwškƒW¯ÅKU_Vmƒƒ™xU@aW@@kK@w„a@Kƒ@@kVUƒaky°_Vm™kna¯K@™ƒL™wġk@@IÇóX™ƒwVakmV@mwXUWanƒlĉ@ǙUw™KƒƒóšܛNJۄm°@›w—Å@ƒ±b¯Wƒ¹„WVwŹĕ¯kVmōb¯w@aƒwmV™UUb™V™IkaVwķ™xk¼›b@VXXó`󗙘ƒ¼Çó™¯„kŽÜš„š¼WŽn„źĖnššxl@X`WzœÆ"],encodeOffsets:[[133921,46716]]}},{type:"Feature",id:"2305",properties:{name:"双鸭山市",cp:[133.5938,46.7523],childNum:5},geometry:{type:"Polygon",coordinates:["@@™UƒƒUwó™mÑÞÑUÝÝUkmmŃyV¯ī„¥ƒUÿĉ¯mÇkaWbÅX¯aÝxƒaóLmmšÅaWV™LULV`UbƒXóƒkÇVwUUÇKX›»XmÝ£nK@wƒ™mÑkƒÝ™bƒKUl™x¯kU™Km¥ƒ@ÝÑkUōxmbUmkVkmmnkUƒmmƒL@w¯Vţ™@Ǻk_ƒÇmV—k@ĸVx‚VÈ°lLkllšUbōwƒnVW¼nlUx¯XmWUnÝ@™xÝUó¼¯J@LVbkJWnkb™W¯„ÝLUxƒn@‚™n™Ü™b¯U¯n›Wkz„°mJ@bkxƒX@èÞVšxlaX„lVVœ„`°@ȐÞa@mÆ@@bÆ@ˤĖm™Xōƾ@@wš„n@@WÜ@kb@²ÜlŐLƦ™nw™@»„_°@„y°UV@@¦„bÆKnƒšI°l„IÆ`œ°W@k„llUV„ÞVVx„LƚÞVX„WVnnUJ˜@UbnKVnm@Ubn@@x„L@VƒbÆĸ„`UĀƄ„Ò°šŎa²ô°bôKÜVĸw°bÞwȎVnÞōVUÆlXU"],encodeOffsets:[[137577,48578]]}},{type:"Feature",id:"2306",properties:{name:"大庆市",cp:[124.7717,46.4282],childNum:5},geometry:{type:"Polygon",coordinates:["@@mÇ@сǰ¹¯J±ÅÿƒKUw‚I@™wšš@š±Å‚™X¯WanamKx™I„ylX°wƒm„wğKUn±@nVDŽUƒÅkƙ¯Kšmmwš@@¯UkÝaUUVK™mU™lk@ƒ¯„U„`ĸ@V‚mœxVxܐ@bÛ@m‚ÅL@¦š@@y„L‚U„Ŏ@ÆɅɴblġÈL@wÇaša„ƒkkVƒaš»@ó¯_ÝJ™wÇaÅXny›U¯¥Å„@w™bÝa™Lmm@@ƒVUŽlbğVmš™¯Xƒm_ƒ`¯_Ux™m™L™a¯b@mƒaó¦Çk™¤V„@bóJknVx™VXx±aƒLUbVxkLVlLWlƒ@nX@VÅbWlÈnƒx„bWšÅbmŽ@xœbml°b™„XbW„XVmnn`ƒLmšnbmb@šk@mwU@@š¯Jlbk°lbkšmLXxmbVbkllšÅނxX„xVWVVa²VܲnxƒVVnÅlVlƒL„¼šb@xV@XŽVbšIÆ°„¦„lźb„Ĭ°¼Ulšb@kĢ@lw„@ƒÜlnȂƄóȘI„ĉ"],encodeOffsets:[[128352,48421]]}},{type:"Feature",id:"2304",properties:{name:"鹤岗市",cp:[130.4407,47.7081],childNum:3},geometry:{type:"Polygon",coordinates:["@@Þ¥‚™ô£nƒn@°„ÆUn`mXn¤mX„`UX„bÆKVb„@@bnW‚b„wšUšbĊ@šx„@nbšWVmƒ_mm@ó»Um„ŘWXkĠ»²¯‚¯nķšwŎ@ĊšŎK°bĸUnјKȦĠÈbÆknJššÆUĢV°IšŽšVƾƒwaV™ƒƒkÇ¯¯»™mķkۃWm@£ƒóIĵxݏōIğxmm¯_ǙŹš™K™wťŽ„UVUŽƧwóxƒxġkĸķƒIk›ĉ™xóa@UmK@kVmUŻ„¯šVxkŽġn™‚@mmJ¯n°V@bXVÇxUzÆxkxlVkV@¦lbœJ›LUbšÆƒ„X„ō¼@xƒl@™J@bVxƒXUš@JÈ@šn™xVÆUXš‚„W¤knÆb„°"],encodeOffsets:[[132998,49478]]}},{type:"Feature",id:"2309",properties:{name:"七台河市",cp:[131.2756,45.9558],childNum:2},geometry:{type:"Polygon",coordinates:["@@²mŎ_lƒĊƒ„ƒĢV°°IV`ĢbšaĠX„°@b„JU¼Wnš„UJ@„ÞLlxV„„@n`lIUa@K°Iô»ÞVšwÞ@VmnX°WVwmkX»‚U„mŎxVak™lkkKǯUUwÇWUn™U±b—KWƒ™Kk™w„çóK›mU_nW¯ÛmV@bÇKkbkUml¯U±VÇaU™™amlUU™LK›„k@ƒU@mwÛLƒŽƒwkLóÆm_™±™nkŽ¯@@n±KnŚlbkVV‚mz—lWXº@Ķ°"],encodeOffsets:[[133369,47228]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/he_bei_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"1308",properties:{name:"承德市",cp:[117.5757,41.4075],childNum:11},geometry:{type:"Polygon",coordinates:["@@lLnlmxn„„IVVlUnb@VVxXJWL@LގVnnV„J˜_@wkmšK„b‚x„wXk˜WXXšKlb²K@nVVVb„L@WlU²„lKVnUJVz@VVb@lżmVUVnbôaVX@°Ub@lWbXš@b@bVb°x„@VxÈLVlšaÆ@Þb²k°@lVUŽ@Xn@VW‚LXb@¤VXšKVVVLnm°_ƨ¤@aUIVa„alkX›°k„™V@„alwUVy„U@k󙰃na°UVUUmUÆw@mkLVUƒWVI„WšLnn@xlVnK„myU@ƒU°UXaV@U¥ƒU@Uƙ@aVUkWU¯ƒaU@WLUV@bkbmKULmKkUVUkmVIUwlWV²™Uml°U@W„LUwVm@UUK@_ƒKUUÜaXw@ƒVKUU@mVIUUlmnIVVVbÈVlKnbVKš@nI˜@nVnwVLVK„K„„˜Vnb@aUIVW@In™°@lVnIš@lWĢ@°UVL@b„@VyUUƒa@w@WUnU@Wǯ™K@UkkJWaÛbmk@mVaÞU@amkWƒ@mXUKkÿƒ£@a„kl@Um°UXwla„al@nmlXnW°znW@aƒwV™@ƒakbĉ¥VmU@ƒIƒVƒUƒJkUmWU™KbmkUaƒKkUVU@KV@@klw—™WaU@kmƒXVènbmlUUƒKƒX¯JkbƒI@JmIUWU@ƒLml@XkJ@U™kƒK@aVKwWa—IWwƒmUƒ@mU@J@UaċU™aUUƒVkI±ƒk@UUƒ@UbVVm@UVKƒLƒlkIWaULUWƒXUJU„ƒ@WbUb@lkXUxm@@JVn@J@b„nƒb@Vkx@bšLU‚Æn„JšaVXnKVVmzX‚°V@_lJXxWXƒK¯bÅamUƒ@lUI›bñJ@LÇKkIÇ`kxWL@„ƒ@@bUVUb¯xWKk„Å„VlULW@ƒŽn¦Ul@I™lmUUUVm@kWƒnkKma¯XUKWmnwVwÝL„mŽ™VUbUVWb@Lnxm„xVŽmbXx›¦@„nb@`™„ƒVƒ@kbƒLU„mVUlkbVXkºmnm@@xk¦šbĢÜlš"],encodeOffsets:[[118868,42784]]}},{type:"Feature",id:"1307",properties:{name:"张家口市",cp:[115.1477,40.8527],childNum:15},geometry:{type:"Polygon",coordinates:["@@k™ġۙal¥@wn@nml¹UWlaVknUVƒ„Kla„@„Ušƒ@_ma@ƒœ¥WwnaU‚wnƒmw@KXaVUVašUnmWUk°™lƒnUVUXWVw™IWVóKUI@WXƒxUU@mma@kUKWLkw@yk@ƒaVkUUċaUU@Wk@Unm@UVmLm±IUƒkJ™kWƒ@a„I@m@U„ƒVƒ„Ula„@VXVƒXmVwnkWKƒKU_k@m¥ƒmX_™JmnU@km@U@KmU™VƒU@U™@Umk@@LƒmW@Û£Wƒka@wk™@aƒI@mmk@mUa@UmUƒIƒwW@aWUƒbU@kbÇ@kwƒ@makVUk™U@aƒm@aU@mxkUƒbƒKUXUƒ±KXVWLUK@wkU@V™@WXUa@WbUxƒJIƒŽ@¦VèVVX@±ê¯KUIƒ`¯UULVx@Vƒ@UKƒIƒVkLmVkKmš@nUJÝbkIUJVXšVVxVbU„VJ„Un™°bV„mlU°„XnK@Ul@lVÈVUXšx@W„@VXšV‚KÞb„n@VnbV„m`ƒUx™kW@UVkL™Km¼@lUnUJVnV„XV@Vm@@LV„klƒIkl@VƒWlŽULWKUL@mJ„@blbUVUlmzUJUxm@UUbċÜk@Ub@VšLVV„¦ôbVŽmšUKUkU@m„„@VlVn¼WbUJ¯@@„°šnIllÈl˜@nXšWlLœk‚J@bkxlxkxlXUlklJƒšXL@bW„n`@nƎXxlL@xl@Xb‚LœKlVlIXblVUbUJW@lX@VL@VVŽšXšJšw„n@WnL°K„bVbl@VI@K„@U@nmVmV@XUWI@aXm@™VUUkWmn@lmUUk@mUmK@UnwVĉ@ƒƒmU_V@XJôVVUšLVUn@šllUnJl_n@šml@XŽlLlw²LVJUL@VmbVblVXmVnlš@Ť¦„nn@܎@bšl„@@XV`„Unb@VlLVb²J‚Xn¥ÆÑ@¥Þ@"],encodeOffsets:[[118868,42784]]}},{type:"Feature",id:"1306",properties:{name:"保定市",cp:[115.0488,39.0948],childNum:23},geometry:{type:"Polygon",coordinates:["@@VbXWš@@UlV@xVLXKWU²LV„VW„L„alVnwV@@b„n@bšVVllUnb„@lxÈ@laV@„aXV@b‚X„x„J‚nV@VVb@nnl@n„J@blšl@„ašƒU_VWUwVUškUm™Ukb±mVwœU@VIUW@UWk„@VU@ynL„m@IV@‚bnK„LVaVmnIlaXwV@@WVL°@@xnX„@V`V@VbUVVLVKnwnL@ll@@_V@VVnaÆ@œKVXÆ@nƒ@wƒKmU—™Wm@km@kÜKXU@ÑW±nIUwVƒ„Kla@I°wU±kškmm¯mƒ_ƒJnƒaƒwW@IVaUama@wƒUƒmU@mVw@aXk@mWa@£km@aƒ_kVmUnWW@¯bƒkUmk@ƒVÇm@@kUU™KUU™@UVUamVUaWIkb@xU@@amUkKƒVkam@@kVUkUWmKmUkLUb@xmJƒ™U@UImVÛVmnUwƒJƒU@VƒX@UWm@Ub°¦UšmxklmX@`ULU@@UW@@xkn¯@makV™UmxUb™°ƒlUšƒbUbƒnUJƒUUVƒa™LkbUU›JUU@mUUUƒJkaƒ@™xUIWJƒUnƒJ@V™zƒ@kb@`@bln@l™bƒŽ@X@š@š„@Xl‚bnbVb„@„„VJlInlšbVw@U„K„l@lbnan@Vb‚JôLn‚UzlV@lÈLVbVK@LVx—VWXX`WxXz‚bV`UXV¤nx@„bVlVnVlUL"],encodeOffsets:[[117304,40512]]}},{type:"Feature",id:"1302",properties:{name:"唐山市",cp:[118.4766,39.6826],childNum:11},geometry:{type:"Polygon",coordinates:["@@„@VVl@²„lJ„UVVšbČVVb‚@@InV„@‚V„nXx˜JXb‚xUL@b„Lšl@VlI@Wnk„KV@VXnJ@I„Jla°I„W„LVVnkmaUç„WVkôaܯ„@nV°wnJlaV@VUnUUaW¯wXWWwna@£UaWKU¯ƒ¯@aVUkKUamUUƒn»‚an™„IVwUWlkš@„LlWVakU@K„_lƒšbÞU°@šy°n„@„KÈkWW™ţ¥ĉōƒkġWUw¯£¯ƒÇwţwƒ@kK@kƒ¥ÝwÅbǤېťV™lW°@ĸ™x@VVVULVLkl@V@Xƒ`Ub@Xm@UWbƒk@ÆVbnLWV@lnXUbl‚@X¯lmU™VkKWLkK@_UK@U@UmmUxmVXLWVULkU@`W@ULUK@XlJXzV@@xml@VU@UX@Kk@WbUK@Xn`ƒXmJnšmškxUVbUVlVVxUbV@nKlL„kVKÞbVKXI°KVšmVUIUKULVxVJVLkV@Vƒ@UbU@WUU@UbUK@b@nƒV@VkLmb@b"],encodeOffsets:[[120398,41159]]}},{type:"Feature",id:"1309",properties:{name:"沧州市",cp:[116.8286,38.2104],childNum:15},geometry:{type:"Polygon",coordinates:["@@@ln@UȄŽl@Vn„l°aX@mXnVlU„`@bln@¤Xb@nWl@bUx@nnV‚„„V@xnbVbUb@J‚X„x„b‚mXa@k„UVwlW„k„KôVm@w™kkK@kl»Èƒm™VKXkla°@XVV@VI@ml@@Vn@VX@V@J„@VxUzVVšš²blVk¦@šĠ@@»š@VK@VÈLlK@XnJ@alIUl„a„VVbš@„n@a„U@WUIV@mUn@mKXml@lL@LnWšb@XV@@a„VVb„V„@VV„IVWÈb˜IÈ»ƒǟlWšaVUÅUƒƒ™Um@kVU™WVkaUwmaóUƒJUU¯ÑU¥mk™¯UaƒKÅnÇyóXmWÛX¯aċbÛa›J—W™ÝU¯»ƒaóóUm@IƒšVVl@bƒLUJWLX@@xšXUxl¤V@V„nVUV„XVbVš@Ž„@@VVn„°VŽ@ţU¯VƒUmƒUWV@mUXƒaƒbUKUwUaÇKn„ƒVk¦Wb@VnLmV@bkV@n„xW`Å_UVƒV@bƒUklVX@VmlUƒx@VVL@x—VWVL@VW@UUm@"],encodeOffsets:[[118485,39280]]}},{type:"Feature",id:"1301",properties:{name:"石家庄市",cp:[114.4995,38.1006],childNum:19},geometry:{type:"Polygon",coordinates:["@@la„@šy@U„I‚m„VXIVJšw„@lb„IVVnV‚@VVœIVVlašK„bVU„VVI„mVa„aV™„kš¯VanwšVlUnb°@lm@wX@@VV@VK@_nWlknwV™¯¥Van@VX‚@„W@U„V„IVxnmÜUnUVJV@„šnI@wValKnV@k‚mU£na@mVk°K„LVa@UU@UƒmknWWkXU@aWW@@km@UaU@@klK@UkaWaUnamm@U„a¯wWU@UkƒL@ŽUn@x™V™lUXVJUb™LmU@aUWUkmKkLUUm@mW—XƒaƒmmkkWUm@@U¯JUUm™kU¯@mKĉxÝwÝ¥LƒUóŽmwkUUUWVkKm™kKmLX„lxVLVxXJ@nVJnz@VWL@`nX@šƒxƒ@kVUUmJmIXx„JV„ƒnUVƒ@UVV„@LUšƒ`UXVVƒ„ƒlXL@l@b@VmX@b™xn°™UƒbkKWLXlW@@bƒK„mKULmakLUlmb@šXb@xmXU`V„b@`lLx@nWVXL@‚°WlXnlb„KVK„XVb@˜X@l_lJ@V@XnŽ„I"],encodeOffsets:[[116562,39691]]}},{type:"Feature",id:"1305",properties:{name:"邢台市",cp:[114.8071,37.2821],childNum:18},geometry:{type:"Polygon",coordinates:["@@nKlLnšlLXUVVlVnxô„V‚KÞ¦ÞxĊwnL°@lVnšVV°I@Vn@V‚lXnl„n„b˜WnXn@VVlKnLVlVX@bnVšKVaUIVWškšU@wVm@¯@U¥VmU_°lšK„k‚w@LX‚Va„U@wšUƒUUKlUóW@UVUœUlƒ°K„wlKU_na„KVnlKkkšWWa@IœJVa@IlJnU@„KVUUmVlaXUl@lm@kXWÝÑnkƒ™±™k@wğ›@@U@mKĉLmVJ@zmlnŽWLUÝJU_ƒ@@šmJkXUVlbklÝ@Ýa™b¯@¯±JÅwġaUU@ƒkU™@mVI±bUKƒL™WUXƒJkaƒLóKULWbUVkKmnk@@bmLUŽƒl@b@mnmJkUULƒaƒbnŽmn@lVV@¦n@„l@b‚znx@`Vz@b„xnV@xl„lbnKVx"],encodeOffsets:[[116764,38346]]}},{type:"Feature",id:"1304",properties:{name:"邯郸市",cp:[114.4775,36.535],childNum:18},geometry:{type:"Polygon",coordinates:["@@„bVKlVnInm‚@@a„kVnK@al@nmlLVUXaVKôL„Klb„IVWšX„KVL²a‚JnUš@lV@„VVĢbÆx²I°Ž°@šaÞbÞ@lkkaVUlWnI@™„@V`ÞI‚VXKmnk@y‚InUĊKƒÇkUUamUUkƒƒ@aU@U™ƒk@WUwVkVJVkkw°a@„mK@UX@VV„LVW@wšwVa@¯Xm@@lUIWaU@UWkXWmU@UwmUkKmn@lkVƒ²™VƒaULUVmJUUUwƒLma@™UmkIUm›L—mVšmx@b™LUamKÅL@VmbkU¯KÝamzkJUb±Vkb™L@lU@WIkJƒzkKmKƒnUalWkkKW@@nkbk@WW¯XUVUJ@XlJ@Xƒ@XlWLkUƒ`VUnaWa„UV@UVIƒaUxUUmVƒK@I@W@DŽU@@U@bƒ‚@nmKXmx™@UxkVWUX„@`VLlL@`™zX‚Ýb@b‚„@VUVkIUJVz°KVlnLlKnL„xlLVVUVlXUJ@nn‚„I@mVUlbn@@Žm„@bV„nV"],encodeOffsets:[[116528,37885]]}},{type:"Feature",id:"1303",properties:{name:"秦皇岛市",cp:[119.2126,40.0232],childNum:5},geometry:{type:"Polygon",coordinates:["@@lnV@Xb˜škx@lU@@LUVlV„LVbnl‚ašLXVVn‚l„I„V„U„JV@UnĊ¦la„bš@nJ°UmƒV@„wn@VU„JVI°bnWlXnWVLVK²b‚akk„lI@aUaVƒUwVUUalaVwnUVak¥šX@W‚kœLVÓm„mUK@_lWš@n_UK@alÅ@ğÅƑŃݍmƒ@їţÇlƒLƒ@¯m™z¯@ÝV™ak„ƒ`@LlVUbkXƒK™@klVXUxƒJmšbm¼V„nVVblLUV@b„°V°XLVb@¤mbXxWX°xXŽVbmVUVU@kbmI¯xmUƒ@Û°óbUl"],encodeOffsets:[[121411,41254]]}},{type:"Feature",id:"1311",properties:{name:"衡水市",cp:[115.8838,37.7161],childNum:11},geometry:{type:"Polygon",coordinates:["@@„KVlV@X°xƒb@VnnmbVŽXblb@VkL@lV@Vbn@@l‚@XX@bWVXlmXnlV„V@@VUbƒK¯LUl@nmbV¤n@l‚LXnlVUV@ln@lb„UlLnV@bV@@wlaXJVbnUVbVUš@VVšLVVn@VVX@@U‚KXU˜U@wUK@U„wVnk@UUWlk„V@a„UVUÆ`X_ƒw@mlU@anUmK@UXal¥„UmƒÈLVbVxVL„a„bVW@nXU‚Vn„„V°UŤV@Uƒ¯Um@Uƒ@@U™UaƒWVUmUUƒU@k£Vw™W@wW@XKƒIUa@wU@@al@UK@_mKXKƒbUU@aVKmš@Xmƒƒ±@kbÇakLğVaUw@a@ƒmkUJƒk@ykw@£ƒWX@lknk@WVkbUŽVnUVƒL@‚mVkI@JUb›I@JXb™XllkLUmƒLmbV`kLƒx¯Lk„›VUV@VôXkVVL„V™V@xƒVUbW@Kxƒl™L¯kV`UnV¦°@"],encodeOffsets:[[118024,38549]]}},{type:"Feature",id:"1310",properties:{name:"廊坊市",cp:[116.521,39.0509],childNum:9},geometry:{type:"MultiPolygon",coordinates:[["@@la„Ušš@šUnL@VWbklWxnIVV„V@X„JlbUlšXVbn@@K„mV@@X°WVInJmn²@lmVbnL@amKV_kwlmX@@LVamaXaƒaVU@UnJVanLlUkaW@UaVakK@IlKUU@an@ln@alKUƒkIVa@a@klaUKUV@UkUV¯šKVƒV@kUmƒU@@a¯ImJUU@VV@UL@Uƒ@@WXUWa@Ukwm™@ƒX@@w@al@@aVIUmVUUUVWUknK@I@™l¥kU±a™™UUVyUwƒ@@I@UUWm@@Uk@@nUJU@WU¯@kbWlULnšÇ„k¼@llLšl@xUnóŽƒLƒlkXUxƒV@lWb„I„`°nnn™llŽV²¯x@JkbƒLU„VxmJX²@ÒWVÛL@lln@‚Xn˜šnV„L"],["@@@kX@Valaa@KWI@UXW@WanaUIW@UaUKķŽk_W@UVUKUš@bƒ@UamxVXnJUbWVXLVbn@W°kb@U@Wó¼mIU¼k`V„@bVbl@„lX@lUôVlUœIV`lX„Vn@lUlVn@„l@UVaƒIUWl£Um™VWU@@UUKlUUUnƒVL@KšUnLVWUa›@™U"]],encodeOffsets:[[[119037,40467]],[[119970,40776]]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/he_nan_geo",[],function(){ -return{type:"FeatureCollection",features:[{type:"Feature",id:"4113",properties:{name:"南阳市",cp:[112.4011,33.0359],childNum:12},geometry:{type:"Polygon",coordinates:["@@lKl@nVV@„bn„@VVnm‚nL‚LXx@š„‚VLlKVU„IXWÜ@șlbl@XUĊUlwnW„LÞw‚m@ÞUVmnVl@nX‚JXLm@VnnJla„I@VkxVb„@VŽln„J@knKVn„@°aVanal@XK°b„‚@š¯VJXIš„VK@al@nV„k‚@nK„a‚b„@XL@blVVKVLXK„@VaVI°mVaX@V_@a@yUkVw„VšIVašJ°™@anIlaV@nKnXÆm@wUUV±UUWUKnaWwXUWmŁ¯Vƒam@kakImƒUKƒ»lan@VXXa˜W@@UlUUa@a@UlwUƒV@Xal@@anIVaUK@V™XmwVmUmV„LXl‚@nalLnal@„šnKlkV@@UnJ‚UXnl@nVl¦V@@VnJ@nUVVVVIn@Va„JƗn@@K@m„kƒa@kmWVaUI@a@™k@@aUL@mmaVIUKUVƒ@@IU@mƒUmmL@K@UUUU@mW@@nU@ğ»mVmbk@klW@UXnV@LƒJm„™lUnUJ™UUUWƒƒ@UnkKƒxmLa@ƒ@@lUU™bmUVWk@@nkUmam@UakJU_ƒVm@ÅlÇLUVmVUwULƒKU@ƒk@UƒVUlU@@Uƒ@UaUUWaŎƒzJƒaWLkl™b@bmL@„kKƒabWŽUVƒ_@mV@b¯JmXUbUK™¤ÇLUU@b@JkLWmkUWIkJ@VmX@JUbVXU`¯VV¯blK@LXKl„UV@Um@@Uk@kxWŽkbƒL@KkbmL@‚UXmaU@@l@x@blX@xUJ@bULUlULÇ@@VšnU`W@@nÛ¼U@@VmKUkm@VVX@@xǚ@bUbVb@VX@@x‚LUb@lƒ¼XLlbUlVVU„Ub@n"],encodeOffsets:[[113671,34364]]}},{type:"Feature",id:"4115",properties:{name:"信阳市",cp:[114.8291,32.0197],childNum:9},geometry:{type:"Polygon",coordinates:["@@VllInJlknJVkVU@mXlUÞ`VnV™VU@U@y„@nXlKV„nJVkXKWaXI‚b@yVk„VUkVwn@‚K@nW@k„KlUXVVUlbnUV`n@V_V@llX@@V„b@bV@@nlVUb¯‚WLnbmb@ŽnLnK˜b„U„bVWnLlaX@VVUX@Vln@`kL@ll@VXVJÈIVl@XÞJ°Una„LlylU@UXKlnn@lanLWWnbVI@KXKVL@LVWVL@UVKUIVWX@@XÆJ@In`@lJVI@a„WšÛnK@UlK@UU@VK„nlm„nXal„UllLUbVVšknJ@nV@Vm@a„l@@xnV„„lJVUU@™w@aƒk„@XW@_mWnUlŁUmVKV@VXwW»XƒWaUwnkWUkVUƒU@@@WlaUkkaƒIWVkm¯xmIUmƒLUVƒaUIó»m@mmwXk@a›mk¯¯l™@wƒmkLmmU@UbkUWJ@XUbƒJ@b@l@znÆmK@Xk@Ub@lm@ƒI@akmVKUUVUkU@U±JUbkƒ@IWmkxƒa@UUV™UWVkIUaW@UlLWn@VkJƒI@VkK@L@bmKƒkJmUUaUKWXk¼VxnJ@„V@@VULV¼ƒ@@UkaUlWL@U@W@IkKmL@KULUWULWKUXUJmIƒb—KƒŽƒ²UW™nWKUUkLUƒmUUam@UU™@ƒmUL@xkV@„VV@bmV@Vk@mwkUƒVUx@mbX‚ÇnVb„‚UL¯šWŽnUVLVb@xnlWnU@UVUVVUbVVlVkn@llVUXUWUXVbUJ@bmLUJnb@nVK@bl@@š@bVJUbnX@l„b"],encodeOffsets:[[116551,33385]]}},{type:"Feature",id:"4103",properties:{name:"洛阳市",cp:[112.0605,34.3158],childNum:11},geometry:{type:"Polygon",coordinates:["@@VVUllLXl@LWn@J„@bƒKUVmnL@`VblLnbV@„b@JmL@LnV@VV@¯„VJVnXL˜@nm@aÞ@‚a„k@m„IšmVbXL‚ynLšk°@°aVJnUV@UVVXk@WJ@VXLlUnJVnnƒ°U@»°U„wl@šb„WmUXƒÆ@VLXU@m@U„a@I›mkb™a@naWW@_@WXUV@@U‚ƒ²@„K@I±U@¥kKWLóLlƒa@£Um@kWKXU@mlLXUVKUU±J¯_@`UL¯Wmk@Wa„kkƒlUnƒVUVaU@KUU@mmK@_ƒa@KX@VaUIm±™k„aVKVUkw™@kaƒƒW@kbkL±UUaƒK@UUKVak£ƒ@UmmL@lƒIkmUƒ@Ualw@UƒJkbmIUmn@WKImWk@mUUnÝV@ŽnÝxƒKmXkxĉVWVk@kaċšÛ@WXƒJUV@zŽm„VWnbUbVbšLlUnŽ‚lUÒnWV—VWnk@@Vm@kxm@Un™l@Ll@@V@šXnƒškJV„šV@nlVXx˜U@l„n@aš@VLnWĊ¦nxš@lbVKXLl@ރVLƒ„XJl@XXl`lIXVl@Xl‚XUVšK„wV@lanx„zUbVJ@VVX@b"],encodeOffsets:[[114683,35551]]}},{type:"Feature",id:"4117",properties:{name:"驻马店市",cp:[114.1589,32.9041],childNum:10},geometry:{type:"Polygon",coordinates:["@@n@„b°UƂXnVlnLÜ@VLœm@n˜@na@J„„m@k„@lVšVxXX@„V`lLV„XVV@VVÞLVV°„²@lašbnxV@@b„Lšmlm„_VWnIWUna@lšLšbnV°ƒVL@KšV„LVUVaVLXK@mÆXna@wVm„a‚@Xw@KlL@a„@Va@wUkaWnIVƒla@Kn@Vn@VUl@nKVn„J@LnK@aVkVUUWƒ@VakUVanI‚²X‚W@UUU°KnUVLl@XaVK@ašU@KUI@W@_lm@KkLUKV_Uƒ@»@UVJ@XV@@mVL@K@U@Kk@VwUUm@kmWL@VkVkzƒKmb¯VÝI@WUkÇJUIUWk@@klK@_km@UVWUUW@kbmKUXƒaƒV—amLmK@namaXK°VakU@mU@@aƒa@UW@kkU@U`m@U_mVkaUVWUkVƒL@lmX@ŽLm@UxVlƒUUl@zaWJXbWLUlmIUƒkLmWƒ@@z@VUVUšUmÝ_kVWŽ@nUVUlmIklmIkJUkƒl@n@Lm@؃IUbm@UJUUVU@mmI@UU@k¥mUk@WmVmI@VU@klmLƒ™k@mbkKmb@WkƒKUŽVnUnnxšW@UVLUbmJ@bk@WbU@V„kx@V@bVbkV@V‚@‚—XWbUWm@kb„¼VLn„lJlb"],encodeOffsets:[[115920,33863]]}},{type:"Feature",id:"4116",properties:{name:"周口市",cp:[114.873,33.6951],childNum:10},geometry:{type:"Polygon",coordinates:["@@lšnb@xlJ@UnLlKXUlJl_„KnV@xVL@bkbVVUè@šWb@„Ubmš„ŽkšVšmbX„VJnUl@„a°@@b„LVbƒlXx˜InmnLVw‚anJÆw²IlmnXVl°VVbÈaVb„@lkn@VWnLlUVmÞUUklƒkƒVkUaVaVaUw™K@kkaVWmw„_„‚l@nU„VVb@b„aV@VV@zXJl@@kl@šlœk°WVnÆbnbUšVJ„Iš@VKVm@k™K@_kK@a@aU@@wW@@k@aUW@IUWVUnLlUlVXKVwmk@W@—VWa„¥@k@lnƒUIÇKUaU@ƒUUVmIUV™Uk¥ƒVma@¯k@Wanwmƒ„@@n@@m@UIVƒkUVamUXWƒaV™U_™@ƒmUVUImW@aUIĉK@VmI™b@lU@@n™JƒkU™@KƒIUmmLk@UVm@UŽm@@LkbU„mJXlbV‚@xUbƒ@@bkK@LWx@ƒbUn@xmbÅW@nWLUKUbUVƒK™U@LUK¯„mU@šVV@xULUŽVL@bU`WšUz¯aUamKUaƒ@@xkX@x"],encodeOffsets:[[116832,34527]]}},{type:"Feature",id:"4114",properties:{name:"商丘市",cp:[115.741,34.2828],childNum:8},geometry:{type:"Polygon",coordinates:["@@XVl@lLȃ„@VkV@V»UanƒWX@VaÆÇô@ÈaVX@xVJXUÞU‚aVLĸbXKl„V@šm°Vn_ny˜XX»mUk¥lK@a„_@yšInaVKVa°_@WXI@ƒ@K‚VnIlbnaV@„l„@‚a@_w@ƒlwUKm™Xa@UV@š»Vƒšw@kUKVUUm@w±VUXUKUwmJUUƒ@km@@±mXkmUI™@mm™KUwkbWakLWaUIkJmŽƒX@l@@VUX@JWbX@VbULWbƒlUVULknlV@bVJk„mb¯KknWmk@@nmVkx™@ƒVmU¯KUnUL™@ƒJUIV™maÅaUm¯X›l™kk@@lk@WI@yUUU@ƒb@aUaƒUmVk@ƒƒ`nxUXlb@lšLVxUbUbVbUll„k„VlÝVUnkVmKUXm@klƒ@ƒnUx@xnxƒn@`VX@V²x@V@b@„Wl@zU`VUVVb„L@Vƒb™W@bkXllkLWV@V„@VVÈwlVœ@@X˜K²Llb„WnnÆL@VnJWn"],encodeOffsets:[[118024,35680]]}},{type:"Feature",id:"4112",properties:{name:"三门峡市",cp:[110.8301,34.3158],childNum:6},geometry:{type:"Polygon",coordinates:["@@WKUmUI°ƒU@@UmU@KnK@IƒaU@makKUa@_‚KnmVU„L@a‚ƒ@IXm@KWkkKVkUU@aUW@UUIVaƒymwkbU@ƒx™LVUWWkk@WUkJk_WWk@WI„ƒUK݄k@WKULka™@mwĉ¥mXUK™@@bƒm@k—VWwkU@m™UUƒlI„™Wm@™@Uk@@KškVmn@lwn@@Ul@Xm˜UXUmVсkmkV™KUaVamaUXnƒ‚@ykLUKƒ@™WwKmKnUm@UmƒƒaU@mUk@kL@lƒxċxUnkVmnXxWb@`kzWJ@V—LmVUn™lmUL@lW@Ub@VšXUbš`VLUbUJ@nmnUlUUm@@bUJlnU„š‚U@lxkbƒ@@XƒJUnƒ@kb¯VVVmlXXlJlzn@VlkVW@bkK™bmškŽUbVb„lƒXVxšKÈnšwÞlĊKlšVnKlwX@lL@xlUnVn„@šl@lmX@ƄÈb°¼ÈwVJlx„_°xšašlšUÈxlUnbVxnL@lllšbm„n@nb‚@@V„L@V„@@„VLšJnIVVlKnV„_"],encodeOffsets:[[114661,35911]]}},{type:"Feature",id:"4107",properties:{name:"新乡市",cp:[114.2029,35.3595],childNum:9},geometry:{type:"Polygon",coordinates:["@@XVlL„K°bUblbUbšl@nX@W„XVVKVkš@@Žmb@„Ubn„W`kL„LƒV@VVLnKlVXIlVš@@a„@l£nWlƒkVa„@°bnUlLVlna‚bnUVUXKlU@ƒ@lk@a„I°y„@ôkUU@wšmôšnkWakml™UkVmkUlmUUm@nkUKWanamU„LXW@U‚VnUln„`l„œblL°KXV@ĠJ@L°„šJšUVw„anK@UUImmƒkK@¯±Um@IVmUmmÅnWaUK¯aUk„w@W±kVƒx™U™VƒwƒnÅJUIWaÝJóI—bm`ÝbÅImJUI¯¥¯@mU¯UƒJmnUVóUkl±V@zXl„bWVXL@bm„mº@@XmJUXU°llk„@nWJk@U„@¦U`m¯ŽWx"],encodeOffsets:[[116100,36349]]}},{type:"Feature",id:"4104",properties:{name:"平顶山市",cp:[112.9724,33.739],childNum:8},geometry:{type:"Polygon",coordinates:["@@l¤UbVL@V„LVb²VlKlaX@„„lbš@lxUVULƒbšln²VJUbW@@L„b@`nL@nVV@LVŽUbUVm„kVl„ƒlXbl@Xn°ŽVK@_°`²IVVV@VUVJnInaWK@Uš@„K„LÆ@nmlXXWVUUw@klKVa@knyVkVanI‚JXUl@XbVUl@@aša@mXk‚bnK@UlK@UUUVaXaWmkUm¥n—WmXaWaœkl@VmÞb„KVL@aVI@mUwVm„@KōméUL™KVaUk@kUK@U˜WXI@VlKXU‚@VVnInVV@VLlK@UUƒkKU_@ƒWWUwU™@klƒn@ƒƒ@Imb—@@m›nUKÛ@mKUkWVXxmbVLXŽVVU²VV@xÅnmWmLU@kbmJ@b¯š™IUb™JƒUUxVl@z@bU`W@Ub¯nUJUbƒ@WLUKULkU@aWKƒ@aƒbmL@ƒlmUk@@bUL™ƒWJUI™°@ƒŽ¯aWLk@mbUb¯b"],encodeOffsets:[[114942,34527]]}},{type:"Feature",id:"4101",properties:{name:"郑州市",cp:[113.4668,34.6234],childNum:8},geometry:{type:"Polygon",coordinates:["@@@nWVUKÅ@W„nVnI‚ŽV@œkƂšwV@šnn@lxÞlnôJ˜zXJl@nalUČVlƒl@²UlkôVVUnm„I°VnV°@°¦VJnIÆJÞan_VmU@ama™@kU˜¥kaUklw@UIV¥kVUI@ƒmmUÅmUlƒwVU@amU—JWbUakVƒ—Vé¯Im`ƒk—@ƒwVWmLkU¯ŽƒXkWmLmx@UUƒbm@@x™J@LbW@UUVWUkVKƒ@ka™IUamKUkkmmLƒUkJUVWXkWmnÅ@ƒKƒL™@@VXLmbmJUIUVU@ULWVkK@nWVXL@lVn@¤„b‚kôKXKlL@¦²V@JƒL±@„@VU@WV@X@`XXmb@Žšblaœn@Jƒb@V"],encodeOffsets:[[115617,35584]]}},{type:"Feature",id:"4105",properties:{name:"安阳市",cp:[114.5325,36.0022],childNum:6},geometry:{type:"Polygon",coordinates:["@@°kVaV¥kVmUkWkWVkVKUwkkmKUU@a„wWWXWakKWkXmlašIVmX¥ƒU@a„@WnK@kƒƒ™V™I¯ƒ@KğI@WU¯LkK›akƒƒ_kmmVU@VWXƒKnVmbXbVLmln@VVknlVUnVlkšlnXbmlmlXblnÈlWbn@@nšK@V„L„bVV°VVzšlnš@V™xƒI™b™ŽU@WLUa¯V™UkWõ@¯kkmxk¼l‚„XUlVbVLnlULmU@lƒLkVUlƒX@xW@¯mUƒ@UmIUW™L@aXa˜kU™¯anƒWk°@k™kKmmUIWaambUkkKmV¯aƒ@UblŽk„mXk¤ƒ@@b™@UbULWVnb@lUVVnmšnVVU„J@bWXX@WJkL@blVU°UV@XlWnXUbW@UVkVšVWbnLUJWLUK@Lnn@blVU‚„nUblxVUVJXU„a˜@Ub„LnUVV@mVIVVn@UbV@‚XbmbUV„_lVXUWanJVI@WkI@WVIVU°WXXl@la@mX@lLXl‚kVbœm‚X„ylIXJV@@kšKla²UVa„IVyÞb°LlVna@UÆKnLVbšK@anwU™"],encodeOffsets:[[117676,36917]]}},{type:"Feature",id:"4102",properties:{name:"开封市",cp:[114.5764,34.6124],childNum:6},geometry:{type:"Polygon",coordinates:["@@lUVbXa˜InV@bUV„x‚knVVÆnn@„VJlUU¦VJ@kxVllb—¦lVš@nb@bVŽUn˜aôJÞIXbVJÆI„m„xšUšV„w‚U²l@XƒxVl°bVLXb‚`XklUnmVblLœ@lmšx°LVK@UXIVašWlL@Ukƒ°KkVaVUXmmI@UÅKmmƒXka±K—L@W›@kUÇxUUƒ@@UXUlKkklW@ašX„a@UƒKUaVUUV_@yXk@ƒ@a@U±w@UUW@_„mmw@wVw„mUaÇbUa¯UUkmWkn±JÅxmIbUxmKmn—JWw„kUaƒK@a¯@ƒbk@mVUIWƒ—Lmwm@Ua@WJUb@LUl™@UUmLUbWJ@VL@VmXWWzUJUꄘ"],encodeOffsets:[[116641,35280]]}},{type:"Feature",id:"4108",properties:{name:"焦作市",cp:[112.8406,35.1508],childNum:8},geometry:{type:"Polygon",coordinates:["@@V@VL@x@bXŽWV@XkššlUŽWX@J„@nI@KlL„KšUVaV@œJlL@KUk@KÞL‚l²_‚@nWlL„UVVš@nLWVUJVn@anV@a„wÞUVLVx„b„@lW„@lbXn‚Vn@@¼šL°mšKVn@bnl@nVK@blb„L„W„U@VWLXV@nlKn@lVVbXw°nV_@¥Vƒl@XI@mlƒkkV¯VWnI@W‚@n¹nƒ@aWKXUƒaWk@yk@k„ċUkVmbk@WI—yóImÝkkwm@™mU@™xŁ›lU@mJƒX™ak@ƒx¯V@¼¯Vm„UmmIkVWK@UXIl@UWVUU@mVUI¯b¯@™lmKzWKUa™nƒJ@nƒlbÝ@@b"],encodeOffsets:[[114728,35888]]}},{type:"Feature",id:"4110",properties:{name:"许昌市",cp:[113.6975,34.0466],childNum:6},geometry:{type:"Polygon",coordinates:["@@lI„VnKlnVlnLVbšJlb„@ULVlUXVVX@‚a@KšI@wn@„aVV‚@nwnKlX„W°lVnKUX„x˜@„ln_°JVIXy‚XnW@U‚K@UXIVanKVVš@Vk@KVaXI‚@Vbn@nx˜KnaU™l™ƒn™Va@ƒXa@™VçUUla@aUK@wmUƒLk`kIWVkLmK@V@XUlƒn@JXV@nm„™bU‚óIƒmUa±@@ÑóVUUk@UlKVU@akWVUUlUUaUK@UUKWbUkÅJ@XWaƒ@XbmJ@nUJ@bUKƒLÝaUnk@›lXbWbXnm˜n¦lVXnWbUbVV@VkL@VmLaWl@n™b@bk@UVWak@WVImJUbUlmz@lUbkL@lVx"],encodeOffsets:[[115797,35089]]}},{type:"Feature",id:"4109",properties:{name:"濮阳市",cp:[115.1917,35.799],childNum:6},geometry:{type:"Polygon",coordinates:["@@lLXbW‚XXƒx@bVVnLllVxULUl‚XXlVlUnlŽU¦Ub¯l˜nœK@V‚bVb@šXbVL„KVxVVnIlašb„a„¥lU@wnalLnVVlVLXnlWVXn@@lVI@WnU@mƒÅW¥—aW_k@WwXy@kmƒ@wU„mš„š¦šlUxVLV@UwšJ°xš@VX„@Vb„@š`VX@VX@llšIVbnJlI„bšV„l„˜J@ƒmѯLóa@ƒƒKUa„k™ƒ™Xƒ@UK@wU@ƒlWUUݯImW¯aƒLUKU@ƒkƒ»k@mƒwƒa@UnKWI@ƒUU@akVWK—k@a±ƒbóUWKXUmk™KUmLƒbUx„„@lmLXŽƒ@@b„VW¦Un™JkbWnXl"],encodeOffsets:[[117642,36501]]}},{type:"Feature",id:"4111",properties:{name:"漯河市",cp:[113.8733,33.6951],childNum:3},geometry:{type:"Polygon",coordinates:["@@@Lƒ‚UnVxnIWa„@Xb@WÆIVlXaVL@VVLVbkVVŽUVlX@bUVkLV‚l@VVôU@Ò²@Vb„nôJVšanƒ@mWU@I„mVk@WkI@wmak™@wlW@w„@VbnLVb°bVyX™V_@aUKVVK@wUU@™™a™K@kmbXVmJUXƒ`kn™nƒK@aU@mw™akb±@¯ƒUUÝKUUU@WU@VkLUKU@mUmJUU@WVkL@UWJ—X@VVL@lVlUbšLVKnêƎ"],encodeOffsets:[[116348,34431]]}},{type:"Feature",id:"4106",properties:{name:"鹤壁市",cp:[114.3787,35.744],childNum:3},geometry:{type:"Polygon",coordinates:["@@ó™™n@xVVólƒ@¯zƒJ@bkl@@„kVWLUVmVXbVJnnlLlš¯@Xlm„°bVš—lWb@bšKVXnJ@VV„°nX@@w„WVklU„K@knVVKmkUKUaVkƒWkl»nwlŽ°lö@lXšV°UVbXKV@šša„Jšw@Um™™kUy¯UUUƒaƒK@U™L@mm@XaÇkkmWank"],encodeOffsets:[[117158,36338]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/hu_bei_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"4228",properties:{name:"恩施土家族苗族自治州",cp:[109.5007,30.2563],childNum:8},geometry:{type:"Polygon",coordinates:["@@VK‚bX@lbUVnL°„@VlVnUl@VUX@„aVƒmaXƒlašUUU@wmaVUn@Vƒnmmk@m™U@kna™aU¥Vam™X_@WƒU™mW@_kƒVaVKnL‚lœ@VVal@k¥@kUW@kUKVUlUVсW@kÇaU»ValmkUVUVak™@aƒV¯_@W‚UkmVUlU@aœƒƒalI@akkVWUaWXUWwœWVbÆ@„„l„alIVK@U™m@UU„W@al²a‚¯UağÇm@ƒbkk@wƒ@@W™aULmxƒIU‚™ƒb¯@U`UX™JmL¯aƒKX›WUL@aknmK™@aWUXaWm@I@UÅmVU@™™aUV@b™VƒI@WkU›bXkm@VakwUKULWKXmJ@XUK@ƒmL@KUwVaUI@KU@mmn™mXka@»V@@UUaƒw¯yVk@ƒUUVmmkÛÈU@mWUnmx„šmlUbV¦UlbWVUL@UUƒ™IUmÇKV„VbUVVxkn™LUxV`VX@š„„kJVVUXWaUVVlUnmKUbkI@WULmK@L@LVlƒLnmUIWV@aknƒ`VXUJIVlUVVbUX@¤mbnLm‚m@UXk@mm@Ukaƒ¥@kV@@KkU@aUKWbkLWVkIVŽk@UbVlmX@bU@@mmL@bn`@Ln@llVLVk„@XVVU@`VXUš‚¼k`VULka@VllVIn¤VU@@bl܃bkx@bkL›škKƒn@bn@@b@JUnV`UnVbVKlVXUlbn@°ƒVx„@@b„nVbUllVn@V—VK@UnW@UVUšlnk‚VÈޚxVb„VVI„xVaÆ@@aka@UVaU@@a„k@Wl@nbVIƎ@Jk@„L@VlXnlla@VJnw@UmwXU@aVK°ÒnllnLlb„xnKVaV@l¦²nVl@llL„x@XVVœ‚Ķš@našx@U@al™XUVa‚LÈþV°XxWXkK@šmLnlUb@b‚xnLVlVVkb@UJ@xWXXš"],encodeOffsets:[[112816,32052]]}},{type:"Feature",id:"4203",properties:{name:"十堰市",cp:[110.5115,32.3877],childNum:9},geometry:{type:"MultiPolygon",coordinates:[["@@@a@w@kV@nbVK@ƒnUla„@la„Ål@nlVakwWX@WkLšaVmšwV@anK@UlIXmWkk@@mmLkWlwk@U_mKXwWK@U¯K@UU@ƒVUa™kmƒkI™yUUVUmanU@mlwkƒ@_mWXaƒUWU@ǃ@U@aUaVwUKUIƒVkK@UWIXƒmaV@k@Vm@UnwlƒUamk@V@„ULUamxUJkU@Iƒ`WkkK¯XWak@@W@IUV™LWJkXkaÇVUKƒ@kUmbmUUƒUKƒbkKWUkI@ƒkKÝ@@aƒUm»nI@mƒU@UnWV_@aUmWbkLUl¯b@a›kkk@WkkJm_k@UV±@J@b›nU@@WÝIUJVbXL@nlJkx@„Wn@VkJmb—LmUƒ`VbUL@xVn„@XVƒŽ@„mVVnnJVbU„ƒx@„V„nVUbVVƒx@šn„™bUK@bƒ„@bƒJ„šm²„VU‚lbXzVJV„„JVbn@@Xmb@V@bVJÈ@‚Vnkn@°aVVV@šX„KnalLVmšUnnVKVlnLWlXX„Klk°š™šXŽWškLUVVV@nU@ml¯nmbk@W`Å@mb—LWm¯UƒxnêVèk@mbƒVƒnUK™@kKmXk@@JUI›lÛLllnbVnlJ@LULnlÆaVLnŽV@nkVJ„@lkô@²bÆm°w„L„WV@VXšKšVXI@W°ÆVšK„b°U„JVIVV„¦XKVL@l‚InaVÝnUl@@bX@‚™nmVL@lVL„lVLVUnbVW@xXn˜bœU°¤V@š™„a@kWKUUn@VlnL@UV@Ü»@mX@V_ƒakaÞ@VK‚¯@kkW"],["@@mUkUUm@nllVKXXVK"]],encodeOffsets:[[[113918,33739]],[[113817,32811]]]}},{type:"Feature",id:"4205",properties:{name:"宜昌市",cp:[111.1707,30.7617],childNum:9},geometry:{type:"Polygon",coordinates:["@@°`„U@blšUbUVlVkn‚ŽUbV¼Èb@l‚XUÒkVUVVL@lVX@ll¦k@UbU‚›@kmKULUbl„@`nXšŽ„V@XW`nšUbV¦šbmb@lšV@nnlmnU„m@UVnb@xVV™VkbW„nb‚VnVa@an@UaVU‚JXnWlXX@l„¦@ŽlKÆX„bX‚V@VV„@°¯°xXx‚XV@nV°UVWU_VWXkmaVnWVkn@lln@lb@UVLXWlnX@˜aXUmaVK@UXU„U@WVI‚W„XXV‚U@¥VKœ@‚Uގ„„‚a²LlV@kV@UanKma@UVUnK@UVLXyVL‚knJ@UV@@UXKWUXaV@Vb@mVLnKW„m@aUUm@@UkK@Ula„LXKWaXI@alKlmUk@wVKXL@m@WWn@UVa@K@wna@aW_XWWkXbVW@k@U¯WWwka@UUaVIVƒkU@m±@U@@wVKkaš_@VV@XUVwU¥‚šyUkm@V±ÈUKk»ÇL„m˜mLk@ó£kmWwƒm@U„IkWKXwWU@ƒkLƒwkbmaƒbkK@VƒLkmWIUKkUUƒÇIǫJ™XÅJULVŽÇLUVƒ@UK™@kI@WVI@UaƒWmXVVUL`±kÅLmKkƒƒkƒÅ@Ua›XXxWVXŽVbUXll@bkJ„b›„@bkVUVlnV@X"],encodeOffsets:[[112906,30961]]}},{type:"Feature",id:"4206",properties:{name:"襄樊市",cp:[111.9397,31.9263],childNum:7},geometry:{type:"Polygon",coordinates:["@@@Xl@Xb°WlLXl„_@JlVVInwVbVK@ƒ@UnlVbk„mx@VUnl@U@nbW„XJ@VlL„UVJVLUxVb@b@VȄ‚@XV„VWbnX@`l„kx@nmVnbUVVVšzlJn„šlVb„UV@@V°L@VXLWxnLV`l@kxlXnK@nl@XlWn„`Xnl@@UVa@VÈKš£VLVanW°U@UVU„@„`VIn‚mV@„nV@Xa@aVW@UšalkXKšblI„yƍXnlJXbl@@VV@nklU@`„nVK„LVKVb@V„U@UÈK„UVKšIlUX@V`lIVbn@nblVVmV@@XXJšUVV@knKVn@`@X‚VnK„wlLVmUUU@ƒU@aXL@WlU@UUW@UmU@KkLWaXkWmXUWm@U@ƒnk@UmK@U@UaUVUUKV_@al@namWUI@KUƒK@aV@WUIƒbƒ¥ULUJkIm™ƒK@U@K™V@U@a@UkU@K@wVaUwlU@mUƒULmKUkV@@anIWmUK@I¯„mKkl@LUb±lUakLmk@WwUKÝVUIm`¯n@Uk@makJU_@ƒƒJma¯ImwUVkKƒb™aUÅ@wWaU@VU@mXIVmmUkJkwm@mIlUKWzUK@VmLUV@VnbmLVbU@@lkU±KbƒƒÝV›@UL@¦VWUƒWXUJ@XƒVWV@VULnbWV—bW@kmWXUK@Vkam@kkm@UlmXUŽnbWlUXV`UX¯VmUU@Ul@Lll@nnJ@LƒnWmbmš@b™`ƒš","@@kUUm@nllVKXXVKmU"],encodeOffsets:[[113423,32597],[113794,32800]]}},{type:"Feature",id:"4211",properties:{name:"黄冈市",cp:[115.2686,30.6628],childNum:10},geometry:{type:"Polygon",coordinates:["@@VVUnWVXnVJ@„‚U@V@VXŽV@@IVJUnŽ@V@L@KlIVlVanLVbnVlI„ƒn@@a@Kl@@I„JlI@aXU@KlK„kVblJXU„VlU@V„bVkVKXn@VlxVa²I@VlVUxln@bšJXklaVWnLmÅ@y@k@ašI@W@aXIlVVaV@nnlKnLVW@IUa@a@K„UVVlI@wXKVV@IUƒla„@lUXwWƒnƒnalLlxXLll°@XwVKVaXIl™nb˜@nln@Va@U@k°ƒUmÆUVaXI„JV¯ÇUmmkU@WaKmakVm@U@aVKkkmKkVmIkÇ°£@aUUVaVVnKlkX‚mkƒ@ƒlUVaX@@Um@‚™UmlUXV„UVU@w‚K²¥Ua@I@UV™l@U™V±UIUÇ°»VkUmVI@a@U™m™ĉ™¯V±bŹĖğaÇL¯lmŽkX@‚óĀ@ŽmšÝêb±WkLƒn@xXx@Ž@b@V@LW@UbƒlţXƒ`kxWnXô¯¦ÆV@L@JVLƒxkK@V@bkz°l‚lXz@J„UlVla@XUV„bVKXnW`XXV@laVV@V„X@V¯xƒx@xULVbUJ@n@LU@VmmakbUK@b™IWWUUVkUmkLm@VJkb@nUJƒ@`V@kX™aUaVmmLkUmJ@Uk@U„±lkzmJUb@b„VUxVXU¤ƒL@JƒX@VlL@JkLUVU@mnUl„¦@V"],encodeOffsets:[[117181,32063]]}},{type:"Feature",id:"4210",properties:{name:"荆州市",cp:[113.291,30.0092],childNum:7},geometry:{type:"Polygon",coordinates:["@@ÈJV„lVVLXJln„K@UlL„anbla„xlK@„XVWxXLlƒJ@V„nXxlnô¤l@nKn—‚ƒÈKl¼VL²Ç‚Un@Vl™zŽV¦UxWVU@@U™`lbUL@xV@²@@nlVU„UJVb@VlbXx°XVWX_VKUwVKVa@UVKUUVk@KnblaUU@wnWl@UX@lÆ@@a„IVmUk„™šxVJ„U„bܙ@Uk@WWnk@Vƒ„™Vm@I@m@Un@m™XUlVlUnJ@knJVU°@@aÆLX@ƒllL@¦nJV@XblLVa²U@UlWš@VX@`@LV@@bXJlIXml_lJœU°b„KÆLnVVl‚@ö—Vƒ‚mXaVIĢllUlVnLVlX@@b‚ašnnxšV„L‚bn@°ÆXmmkĉƒ¯w±™™™Uċ@KÝÅƧŃÝ癙Uw¯ƒm™¯k@W‚kV@¯UIUJW¼kb™Uƒwk@W`@¦Uônb@VƚlÈ@VU@ƒƒ£UWWnUÆUnmJkUÇ£VWUI@aUU@WkI@Uƒa@JW@k£kaWVUKmnkKƒb™kkVWb—VmUUmwU@kk›@UakUUa@V@nlx@lUb±lUbnnWLUyk@UamœUK™@mlk@Wb@VXL@x@xWI@a¯Ž¯V@bVn@LkKmL@`XmKmVU@@bkL@V±bk@Uaƒa™L™KUVƒIƒ„™W™XamVVbUK@b@Lm@UWkxULWVUnm@UlUX"],encodeOffsets:[[113918,30764]]}},{type:"Feature",id:"4208",properties:{name:"荆门市",cp:[112.6758,30.9979],childNum:4},geometry:{type:"Polygon",coordinates:["@@n@lxlInVUnWJ@nUVV@Xb@xVƚb„alLVUnx°Jnb„I@„V`lInbl@@V°mn_VJÞUVLXx‚@nllKVb²kVa@KlknL°ƒ@JVLXnmJ@bU@VlnLVKV„@nX@lUšKVaXal@VKn@¥°L@Unw˜bnašV@KV@VUX@lVXI@KW@@IXWV@laVL„„KlaXUVVnkVWV@lwXblIXWVkVmšaU£VaUmVIkU@y@WakKUamU@UUK@kmK@w@@mK@LƒV¯™U@WwkmULƒamVVUU@ƒƒIƒbUKUa™kmƒm@UakLmxU@UÒWlULţÿmwkIUm@a‚kÈblW@UVƒUUk@JW@XkWWUkUKUIlw@aUWknWUUmnIWƒ™aUwVaۚƒaƒVUI™wƒšVlUnƒJ@bÅ@@kVWk@mX@xVVkbma@LUlVVUL@VUbULVxULW`UX@V@lUXWaXlWXX`@bmb@x@LUb@VmŽXX@‚@nWKUL@xVlknkL@bWJXbWLƒKkb@VlL@Vn@VV@bƒnX‚mLUK@nUaU@WbXVWL@VU@@V"],encodeOffsets:[[114548,31984]]}},{type:"Feature",id:"4212",properties:{name:"咸宁市",cp:[114.2578,29.6631],childNum:6},geometry:{type:"Polygon",coordinates:["@@ÞƂLČ@šV‚š²š°xĊ„nlWnŎ¯m@aƒK@„„°‚n„Jšwn™VIUaÆJšÅ@wšwV™XW@aV_l@²V°lĊwlaXLšwlUkalVVaX@lVXI@a˜UXJ@U°UU¥VIVKVklanLVa@VÈIVV@nk@aVa@mV_@a„K@klKUa@UnKWk@@lU@@UW@@nUWUwmaVIXƒ„lV@mLXblJ@kV@kk@KU@WƒkUWVÅwkLmW@UmL@lUL™KULƒak@maUUÝwUJƒIb›KUUƒ@š™aWK@kUWVkUwVw@™mÝ@™I@wkW@a›ww@LU¥™kƒJ@nVJƒIkVVnkV›UkyUIUl@xWUkaW@@°kz„ŽWxkLUWmzk@@bVVVš„b@‚@XlVœ@Vl@bVbUn™`Wn—@Wb„VVI@`„LVbXLV`mnU@@lƒL@LUŽƒak@ƒLk@WbUJn¦@lVb@xVb@n"],encodeOffsets:[[116303,30567]]}},{type:"Feature",id:"4213",properties:{name:"随州市",cp:[113.4338,31.8768],childNum:2},geometry:{type:"Polygon",coordinates:["@@„@nš`lw„k„ƒ„UmUVWX@lk„@VanUĠ¼V@@mX@@nVV‚VXLmJVLnK@b„V@@J„@VUn@VaVUUUVWVLV@@Kk_@almaVkUU@WVƒVUVLXmmk@wUaUKUV@°™@kmaUaÈmW„mUƒVklaX@lVnxl@@UnaUk@ƒVUVwVK„nš@VVn@VbVJUknUmmVmk_Vw„KUUm™Vak¥@UVKVIkW@UmIVWkIVƒkmmLkwmVUƒ@LƒUU@VVXL@JmLUbmK@UUKmkKUUmVUaUnÇlk¯™mJUnmLUaUJUaWL@UkJ™ƒUƒ@ƒaklkU@¯@KWLUmUUWVkbƒLƒŽUKkbU@WX@JX@@LWJkUW@UVU@@L™Umb—amx@V¯K@¦mŽULk@WbUb™LkVW@kVVxUb@x@LlV@V@b@VšU@L@V„LnšlJVIVK„¦„aVJ@XUŽ@b„LV‚@LVJnXmbk@@bU`VLUVV‚b@V@VnL@Vml@„@VXnWVXnWlXblK@LnV@VVX@VkV@XWK@b„VV@VV"],encodeOffsets:[[115830,33154]]}},{type:"Feature",id:"4209",properties:{name:"孝感市",cp:[113.9502,31.1188],childNum:7},geometry:{type:"Polygon",coordinates:["@@VnXK@L@°lVlk„b„@„VšlI@VXKVbVIVbnKVmnI°šlŽÈkVmVbnUVVlLnVL@VnLVanK@IWKUUV@„V@KV„nUlxnKlnU„lJUXnJ@VlXUJUL@Vl¦UbnšVVƒLUxl`UnnnmVVlnVK„bšmVX@a°Ý°LšaXJV@VUnKVXVK@LnKlLUbVVX@VwVJVn„@@UU¥V@@UUK@ƒmaUVUkkJ@L@K@UmVUI@JU@W@U@UV@ƒUIWmXUVmUUÇ@UVmIlmnmakK@akaW@UwVUkKVnUlKVwk™ƒVU_WKUkVW@UXaWkUa@w@VU@XaW±@IkbƒKƒb¯L@WƒXkWƒ@UakL@UV@UmVUmL@UXWVL@ašUƒVUUUVU@yUUƒIUa@wUKWVU@kƒ™™Wk¯UkwVKƒLUx™K@nVxUlUUWVUmw@wƒUUyXWlX¦WbUV@„U‚@blbUVVbXXƒl@lVL@bk@lxkVVnVx™¦ƒ`UnkL@V@L@Ž‚@@xnL@lVL@VnVVblLXb@‚@zlVUJVnUbV¤™bUnUlWXkJWakxU@UXml"],encodeOffsets:[[116033,32091]]}},{type:"Feature",id:"4201",properties:{name:"武汉市",cp:[114.3896,30.6628],childNum:1},geometry:{type:"Polygon",coordinates:["@@nbnm‚knJVUÈ@@Uƒ¥VknmV@VUlK@IkK@U„W@I„KV£UWVwƒU@aVanIly²kVƒl@@VnIlVnKUnVbšblWU@@_„‚VI@mlaUIn@lKVnUlVVXXšJ@aVLlanbUnV@@K@mVIUaVK@w„w°w@UƒW@UUUkbU@WWX_WmULƒaVU@WkbkUƒV@IWyk¯kly@a@UlL„wUK@I@KÅUW@ѱUm@wl¥kaƒ@@_Vw@ķƒa@akw@ƒkKW£XVUVwVwUaU@VUU™™xWKkbĉx¯k±Uk@U`@bWXUš™x@x™ÆÅIVbUJmš™xƒImƒ¯@ƒ™Umx™nUVVbnJV„@Lƒ@@ŽkV@bVnƒ@UVULlx°VXlššl„V@XUVL@xVb„JVV@zUVVVUV„™V@bUKWX@VnKUVVnU@@VlKVb„@lX„W@X°K„a„Lla@JX²Wb@ŽUV@@xVbXlWb@VUXVlXLV`Uš„lŽUxkLmVUŽlLUVVxX@lb@blL"],encodeOffsets:[[117e3,32097]]}},{type:"Feature",id:"4202",properties:{name:"黄石市",cp:[115.0159,29.9213],childNum:3},geometry:{type:"Polygon",coordinates:["@@VšUVV@VbUx„aWUœblUVmnKlX@bXJVIlVUxVVVIU‚zlx¯š@‚VbnL@x‚x@UVaXK„b˜@Xk‚WU_Vm²klW„XVK„Žl@nXV@@w„mlK²X‚aÞén™@ôÿ@lWn°kUKmmUљUmm@ƒwkImWU@UakL@bVLUVċ@™bUK@alIXKWK@™nXnKmkUVwƒ@¯b@L„lUL±W™n@KULUaW@kL@lƒL@bU`@nUb@bmlU@UÇJ@UUbmKkblŽUULUJV¦¯V@VWI—V@bWJkUW@UbkUlbkV"],encodeOffsets:[[117282,30685]]}},{type:"Feature",id:"429021",properties:{name:"神农架林区",cp:[110.4565,31.5802],childNum:1},geometry:{type:"Polygon",coordinates:["@@n`lIXll@lœl@b°aVklKXaVn@bU`mX@V„V@nmJn¼„V@bÞ@lL@„lJXVlL„aVLV„nVnalV„@VLÈUlblWXIšKVU@J„™š_‚@an™na‚X„m@KmI@mkk@KVkWWw¯w¯°ƒ@UUU@WƒaÅWkL@ƒ¥@kWWXkWmIUVVbm@@bUbmUU„ƒbW@UVk@mVkU@U¯ƒmKVUkaW@aULƒÆVbƒb@VÅ@Un@VƒLWl¯Lš„"],encodeOffsets:[[112624,32266]]}},{type:"Feature",id:"429006",properties:{name:"天门市",cp:[113.0273,30.6409],childNum:1},geometry:{type:"Polygon",coordinates:["@@@K@UlKVm„_š¥UwUmlUkwl@@aUK@k„kWWUaVUka@aV@ƒVUXaW¥Xk@WWIklm@ÅxmI™VÝUkxkaƒ„@bWJaUL@„W@™l¯UULU‚ƒbƒkV™Ua¯bm¤UnÇUkmUšUx˜b@VkXÇal@bVnlJnxŤĀVKXkVÑV@nwlKVbn@n„šlVbVL„a„J@„VV‚UnU„bVKlnXxV@°š„U@KnL"],encodeOffsets:[[116056,31636]]}},{type:"Feature",id:"429004",properties:{name:"仙桃市",cp:[113.3789,30.3003],childNum:1},geometry:{type:"Polygon",coordinates:["@@VK°VškX@@ƒVK‚bXI@a„ƒlblwÞVšUnJÆwn@lkXJ@X‚WVz„V@xnx‚VXUVVVkUw@mšLVw„KVU„@Um@alU@„@@KUƒmIUaVUšmnwmw™mb@aW@UkmKkUkVġkUJWbnU„õ˜@UkmUÅKƒL¯a›VkIk`WnkJƒ@xVLUVVbUbk@WlXbm„VxnxUblbUV™@@VUV@nVL"],encodeOffsets:[[115662,31259]]}},{type:"Feature",id:"429005",properties:{name:"潜江市",cp:[112.7637,30.3607],childNum:1},geometry:{type:"Polygon",coordinates:["@@UbVxšbX„mJVnXVlmVX@bkxVJVLVlXXWlX@@IVl„V‚U—aVwV™lnÈVVmn£°aVbUš„l„aVUK@mVU@Uš@VUkaVamwUwnƒWaXkl@VaUaVUUK@w„WI@aU@@K@_UW™@kX@V±VUbkKWaU@mI@¥kK„kW@ÅK@b¯@UVmI@lmIkVkUWVnšm@@V@n@JUnƒšU„@ŽmlXXl@@V"],encodeOffsets:[[115234,31118]]}},{type:"Feature",id:"4207",properties:{name:"鄂州市",cp:[114.7302,30.4102],childNum:1},geometry:{type:"Polygon",coordinates:["@@°¥WóXmlw„_ŤW„kVaX@@K@U@a@WwU@mWk@ƒULƒWkX±lUnV`XWl—@ƒaWLUb@Vw@wmKUa@°™kw‚yVUJUUVwkUUJWI@akWmLUnkV›aXVƒbUxUVWX¤lL@„lx@b„b@ĸUx@`„@lbk¦@x‚n²VƄX@"],encodeOffsets:[[117541,31349]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/hu_nan_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"4312",properties:{name:"怀化市",cp:[109.9512,27.4438],childNum:12},geometry:{type:"Polygon",coordinates:["@@@n„‚@b@XnJ@k°x@aVUnl‚UXnV@@VnJWUJV„nIVV°ŽUbVVVL@Ž²LUVa°V@aV@nm‚UXblLXWVXVmVLVK@an_„`@X@l°„VlXXW`nX@Jmn@b„@nV@Lm`„bUb‚n@VUVl@nIVbUlƒV@LkJUnVV@xVblVUbU@ƒzUKU@mx@xUnn@@WV@lbUb@šnVWXX‚V@VIV@VUnJ@VUz@JWbXllI@VXVVL@ŽVn@„„Wlb@„Žl„XVlL„aV@VJ@XX`„kVwVl@bk„‚bUŽlVXIlƒnLVa„mVwV@@nV@XaVJVbX@lwV@n„@nV@VWnIVVUŽÆ@Xx‚a@I„UUKmk@mVƒ„IXmWUš™VJnUVU@anaVwk™›U@UXa@W™@m_@a¯@@K@UVƒ„bnK@blIlbXa@WW_n@VƒU@¯bmyƒUkUJÇÅ@WU@kWKÅwƒnm°KVkmankVWnXVWV@UƒƒwXkV@mƒ„UlLnaƒVaX@VUn@VnVK@xlnXWšU@a™@@klak™Vw™mUaV@™wmIÛ`m—@mVUXmlIXƒV‚I@K@aU@UaV_UK@wkUmmUKWXŽmVkUƒL@mƒƒU_nK‚™@aVU@Ukak»@U™™@ymUƒ„¯™ƒUUƒVKkam@™nka@ƒmwkLWb¯mkaƒ_VaVKUƒ™IUw@kKmU@WK@UnƒmaULkU@wUalWV¹U@@WUI@WU@‚_@W@U@mƒU@WbbUK@Um@@UmbUwWWkk@WU„a@anUUwlWUwUU@wlJVUnnV@@mnI@m‚K@U@w„a@wUm@_mƒVUUaVUkƒƒƒ_kċUk™VWLƒ@mlU@kn¥W@UwUWV@VÝU@lXLWVUbVLXlVIl‚knmU@VUJk@@„ƒ@™kVmwmVkxU@@XmVUb@xnKVLl@VxUxkIU`@bWVXX@JWL@bkb„¤@bmUUU¯Kƒkmb@V™VU„VVn@@„Vb@`lnœxmb„lUn‚bk„@xU„mV@bmWbUV@VJ„Il@nVUb‚K@nn@VbnJVIlJVkXJ@X@lmx@bnnWVXJWXU@UlU@mk@@llb°x„IUbnJ@VWbXVmI@JVX@bk‚@bWL@JUXUK@U@Uƒ`n@@Xm@XVW@@nX@@`ƒImxU@@JUI@KƒLmK@UÅUUV@VW@™¯kUU@UamVUUmJ@n„xmLKƒkmJkwkKm_mKXU@aƒU@b@Wk@ma@zUJVUmbUlU@™xnXlWlXXblK„¤V@@nUVVLkVš„l@Xb@VVK‚nXKVx@znW@X‚@@lVK@X@JXbWbnn@JUamLVVXIVxnK@aWUX@˜x@VnI@WlI@anV„IVxk‚l@lbXXšxVVVJVInbV@@ln¦ml@XXVWbkJWb","@@XLVKVXVKUa@UUUmV@l"],encodeOffsets:[[112050,28384],[112174,27394]]}},{type:"Feature",id:"4311",properties:{name:"永州市",cp:[111.709,25.752],childNum:10},geometry:{type:"Polygon",coordinates:["@@lxUXV‚lXUVnlVĢ„JVbUXVJV@XUW¯„VIUK@klW@Un@„nl@V`XUVL@l@šVx@„XXW`UnUbšxUlVnUšV„lb@VnJšUVVVInJlUšVnwVklKnw„LVJVšV@nIV@nbVa@KVVVUUa„KV_nVVJ@_VW„nV@n¥lI@anƒl¥X_VKlwVlULUVVVš@šU@VXL˜ƒ@IUmn@VU@wmKXUWU@m²šl@VIXWWkWUkWlkIVamUXamUnmWUU@@Un™lK@XJl@kVUk@mWKXkl@@aVU@UVWUUVa„In`VUVLnw@U@K@Uƒƒ@w@UVmUUƒ™°K@UnV@bV@Xk@KVm@amk„aU£VWUUmUUwm`UbULka›KXU@kVmU™@aV_UWVIn@˜y„XXK@klmV„V_kWVUn@WUU@UƒmaU@™wnwWanUmmXkƒam@UakLmK@b™xUUUU@Km¥Vaƒ¯@ƒkUaVUlm„UU@mUUÇmUk™Uyƒb™bUa™XUWWbÅLmL@V™aL@WWXUKmmk@a@UUK™XW¥kU@VƒUkxmVkUWbUJnVJ@nVJXzWxkŽ@lVbUX@VVL@`mbUnšŽUn™VV¼k@Ulm@mwLƒb@lmLUK@UamƒWkƒK@£Ua@ƒ›UkJkUmbVlkX@bWbUŽVŽnnUVl„@bšbVK@VX@lb„V@nU¤šx‚²„Knblb@x„V„ô@šlŽ@b@l@XWxnVl@„VV@XLVl‚LUŽUXV`šbXXmJU@@bm@UUkLW@UlUKWUUb™wUm™L@nklVVmVXXm@@bUKlÆn„‚XkllVUVVL@nUbV‚@V@nnV@xUn¯U@JW@UX@xĉ@™`m@@LV@b"],encodeOffsets:[[113671,26989]]}},{type:"Feature",id:"4305",properties:{name:"邵阳市",cp:[110.9619,26.8121],childNum:10},geometry:{type:"Polygon",coordinates:["@@XIlJšI„VVK@n@VVVKnLVwVmnLVK@U„@šw„J@wVIƚ°X@ÜȄUÈxll@kn@VwVaXJWXn@@WVL@UUKVKV_U@@aVK„x@U„aV@lk„@XylbUaV_šVnal@W„U@a„I@aV@@aVUl@Xm‚UXWaXml@@kk@ma@V_UnUV™UUWJUa@kkaWLUmk@@LUVWUkJWkK@¼UnWJƒIkV@b@JUIm@Ul™V™m@Uw@a@kWƒXWKUknW@ƒWUU@k™mx™UkVmIUJUU™VmI@UkaUƒV™UmVk™wVaVmX_WW@ƒUw@™@kUKWVU_k@ƒmm@@VkX@lVLUJƒX°WVU@UIVWUaƒIUġmkVUkWUVWkwWXk`mI@¥kUVƒUƒUn±@m›XkWknV„UVmmU@@XƒVƒUk`@Xƒƒƒk@¥¯»mbĉó@mkU@kU™ƒƒ™KmX@˜UnmL@lULkKUƒWUU@ƒbUaUnƒ@Vb@l„¦Ub@l™@UKmnƒKUnl„UVVbUVn„@`Vn@xƒb@x@VL@nmJ@nU@mmUVkI@xVVVxkXVxmV@bƒbXVl@Xl‚XVxna@Vn@@VVL‚aXaV@n„‚@@V@X`V@@XVJ@XV@UºkXVb@xlVVKnbm„@VXLV@n‚lL@VxšJV„ULUb„`lb°nXalKnx@„lbšmn@lbULV„„V°š„ƒnV@zšš@Vl¼lb@VUV@bšmLV`„„@n„KlVnU‚XWVLnnlV@xVLU`VbV@"],encodeOffsets:[[113535,28322]]}},{type:"Feature",id:"4310",properties:{name:"郴州市",cp:[113.2361,25.8673],childNum:10},geometry:{type:"Polygon",coordinates:["@@²zVaVlnVl@nšVk„Jl_XJlIVmnL@mV@VXn@lV@‚XzV@lyV¯²U@UlJ@XVKnVVIXl@UVLV`@n@J„I@mlI„KVLnUlVUVVLXašKVLl@nb@ŽW„XV°KUnVV„L@xVJ„L@b@LUVVVU„˜VXbmbVbn@@lUbm@x@XVVVŽ@@˜@bkImx@Vm@Xbƒb@l°XU¤„a‚L„mnL@bl@@™VUX@VxnV˜anLnƒWƒ¥XKVwnUWXmVIUWÆLVx„L„w@wVmlU@¥XƒWUkwlÇn_Uw„WV@VU°wnU—ƒy@aVškVlnL@lVn„w@VlJ@b„X„x@bVKnb@U@WVUl@@Vnbl@XLlK@aVLVKnxÞn@a„LlmUaVU™ƒm@ÅknUmaUKmVk@m™kk@UlWUkVm@w@kUU@W™U¯™¥@w„Ç@aVIlUV@kUWU@UUm»@k@mKVkUKUwƒaUaUa›@k„kUWJkImaU@UK™@maUzk`@zƒy@XmJkL@UUJmUkV@z›@kŽkVmK@¦UbWL@a@UbmKmwUK™Xk›VUUkmVkw@UUKmL@WUIWa—JW_k@@WmI@mk@WkWULUUVKUUVm@šU„bš@‚nUǃ@U@w„™V@Ua@aƒL@ak„›l@k™UƒJƒwó@@L@V@„™`@œƒJ@xnn™šmV@bkJmUó@ƒn—JW„UUmƒU@UV@Lk„WlnnmVXbmxšxV@nbV„V@XVm@UVlXU`ƒUŽkn@lWLƒW—zm@UJVXU`@bVšUn@lWVœLlbVKVan_VxnVVVUXV¤ƒbnl@bUn@LWlU@@amU@V¯L„šVVUn@V@x„„@V@L@VmxUKUVm_ƒJUbVV"],encodeOffsets:[[114930,26747]]}},{type:"Feature",id:"4307",properties:{name:"常德市",cp:[111.4014,29.2676],childNum:8},geometry:{type:"Polygon",coordinates:["@@l™U™mkUwUyV™@VW@¯Va—VmUU@KVUVUVLnaWƒnkUÓV_@mVU@݄w@ƒka@kVmƒUmK@IkaUamKkXWaUW@WUk„™@@KVU@aU@™L@J@XÇVUKVak_mWkLWakVUbmLUUmlUVKUU@kUWW@UImJ@xkLkKm@@Xƒ@ó݃@UUk@UKƒV™ƒULƒKƒXkWWbkaƒIUƒWU@mUk@WLaUJġ™ƒ@@XÈÆVIl‚„Vnz°aV@U„m@X`@XWbkakJ@amLƒaU„@V@L°@@bn`š@@XWb@VœVlšUxmb@bUVmVUI™šXVWnƒJU„@nnlVLƒV@JbWzk`m@UVK²V‚x„k„LVl„@Vn@V„„°xVKVkœVVlUblx@bU„‚Æœ@@nVnUll„kx@VW@@VkLWxUL@bÝ@kKkVõV@bkXVVUVƒ@ƒVkUkV›LkV™a™@@™ƒ¯xUxmX@JVb°WXkK@Vm@k„Vb™bn¤‚xUXkJƒblxnXÆK²l‚_@Wnašn@ŽUL@b‚JnIlV„@lUœ@@¯ô@lWȂIVKVm„U@aXaV@lwVXn@@K@UVKUUnU‚bn@lWšX„ƒlJnUšLšKV@„„l@²a@UlK@aV@naVX„WV_nKlL@KUm@a°U°@VXL@a@wWmXal@„k„@VLn›V@@bl@VnX@mwVa²aVU@mk@"],encodeOffsets:[[114976,30201]]}},{type:"Feature",id:"4331",properties:{name:"湘西土家族苗族自治州",cp:[109.7864,28.6743],childNum:8},geometry:{type:"Polygon",coordinates:["@@@KšL@wnK±nƒnm‚—@WUk„ƒÜÈn@n»@mVamk„mšU„„l@V™nmmU@wUan¯VKšLn„VWlInyWUœI@WWk@KXU˜n@mnUmU@WœƒmkV@ƒkXašaVaUm‚Ikƒƒ@kaƒX@ƒUm@UKWU@UkJWkXa@IVy@UmIUVU@UJU@WXWmU@™VakaU@@Xm@Vm@wnwV@VL„yV@VakUUa@wUUVmlI@K„UVkUamJk@VU@UmVaƒan_@KmUƒ@@anm@ImWX_WWUk¯ƒ@k@Wƒ_m`@bULUKUnUWWXkKWaVmnU@@b¯UUbVŽ±K@UKUUVa¯UUmJUƒVIXmI@UU@WmVmkUV@b¯w@lmI@W@aƒ@m¯LXbmJVLklWL@V@XXŽmbVVU@@VU²Ul@VlX@bš`Xx›zUmkUVÒlŽ@bXLWxXVlš@V„bkLma@nmVmULVbmVUb@lnzmbUÒVl@°nLV„lJkn@bmJk_ƒVmmkblxÈx@LUb„xVb@V™n@JmLVŽUš@„nV@¦VbnJ@lVVbkx™bm@UxVLV@n`UnVVV„kl°z„xVb@VU@@ÆlXnWm¦nbVK@XVVUVVl@X„KUV@nVL@WnIWŽXLVKVLlxUbVKXVWbn@@UnKVLVb„JšU@aVU°b"],encodeOffsets:[[112354,30325]]}},{type:"Feature",id:"4304",properties:{name:"衡阳市",cp:[112.4121,26.7902],childNum:9},geometry:{type:"Polygon",coordinates:["@@lšV@XV@„mXVlXL„W‚X@l@bVxn@šŽšUVkn@VJ@I@alU„JXIVm@»‚LXllIXVVU@Kl@VnXKlb@lVbXIVVUšmVVU`@nbl@@lXLVVVKVbnXWJ@VXbWxXb„Ul™VK„¦nLVVUVVbšb„K@U˜LnK@Un@VxlUV`UnnL@VVL@JV@VUnxnKVbV@@VšIVUnJUVUl@nW„XllIUa„KVbÞLV¼²`V@VIUwlaVmXa@IWanK@U@m„kVƒVUVaX@lšnaVLÈ@‚¥@kkJUWJUaƒXkaUm‚wVXJ@_lWUU@¥n_‚KkamUK„™@amKƒnKƒbV£¯W@k„aWan@@UnwlJ@a@—@UUU@W‚wn@Va@km@UanaWa—UVƒUUVU@K@aƒKUI@wƒKUUVm¯LWUXƒ@mak@UK™LWbUKVUkUmVUKƒLkJ@nƒJ@I@mU_UK@VWkUJmUUL@WkI@V±VU°kzU@Wy@kUm@UWU@@nmKUnkJWIk`ƒIUlm™k@mUUkUb±yUX@VUV@bk@WlXL@nVlUl‚k@WI@ŽkLmš@VV@XVmnnVWbnVUblJXkVl‚XXlWXUJk@±™@nXVWVnL@xUVm@Vn@J—„WK@U™V™@UUVUVKUkkxULW`k¦m„@bkJm¦U@ƒmUX@`UImUU`ƒLVbUVUU@LUbmaU@mJU@U™UIƒKmxkLUl"],encodeOffsets:[[114222,27484]]}},{type:"Feature",id:"4306",properties:{name:"岳阳市",cp:[113.2361,29.1357],childNum:7},geometry:{type:"Polygon",coordinates:["@@@wUklmUUmU@@UVm@wUaV_mmUKmwkIkJmUUnm@™™@UUƒbUKUƒmÛamm¯xVLkbÇƃUƒVUzkVUlƒUUKWLX¦W@ƒVUUUaƒKUbmLKm„@akU@aƒmVaUUVIVWkk@wkƒƒ@@xmLlmÅwmbVlXlÝIWVkK@kkVƒL@VWKU@Ublnaƒƒm@b@bšnW`@XUJk@UUWKƒk@UKƒnn‚@xmLUVm@kbVbV„nV@V„b‚@KnV„LWšXŽÆVĢ¦VblŽš„n„UJWz@ƙVóUVbkV™aÅx@¦lVUbVVknWKƒ„k@ƒwƒK™VU„Å„ƒl@zkb@`m_mJ@xX„mbVbœ@llV@n„@llbXL˜UXalUšl„alVnwnLVKlšVbX@@I„V@blJ@bVL@VVVUXȤ‚VnkVÑXmlbnš‚„VKkÑř@UmaVç@±XUlI„xlV„@VaX¯lUVVUšVJn—V@°°nŽ°„Vxĸł°¦šb²¦lJ@U@aUK@kUm@_m±VIXal@„Kl@„bV@K„K@k„m@UmUUaƒK@_UJƒaXU˜@Xmš_VmUk@WUk›@kU@a@m@UƒaUUU@al@ny‚XXWWwkly@¯n@@bnV@k@mVI‚„œVlUUmlU„JUw„I‚bXƒVaUal@K„b@ƒVKVkXVl@VkUU@ylUœVVaVL"],encodeOffsets:[[116888,29526]]}},{type:"Feature",id:"4309",properties:{name:"益阳市",cp:[111.731,28.3832],childNum:5},geometry:{type:"Polygon",coordinates:["@@„ŽÆxXL@l‚V„@ĢšVI‚bXKl@nVV@„XVŽ„JlbXalX„W„LVKš„„UVLl@VV„@ôބ@@Wn@lLlK@wnIVJX@VX@lVVUL‚VnkVVnKValUXblKnXl`UbVLÈU@W@IšKV@@bUV@Lš@lƒXV‚@VXXblWnLVblb@JnL„VUn@llb@„ƒx@ÞUV@nU`VÔmlX„mbUKUVUV@LVVUn˜ŽUb@°UXš@U‚VzVxnlVškšVnlVnaWƒ@wnIn`@_la@y„kƃVƒšU„L„xl@„ƒXLlmUUVakU@¥ÆwšblUUaôVšU@ÅXyVImƒ™ƒkUaġ¥ÅUWX™ƒKmU@Lƒa@UmUUƒUalan@VUnK@wm„m‚L@V„lXLVVl@VI@WX_™m@a™¯mKUkwW¥UK@_UWWLUVkUWL@WUIkVƒU@JƒwkLUUmJVI@WkXm@VmkKUIU@mmm_@VUV™@™„kJċwUU@KUWkkW@IWW@km@klwkWVkkU™V¯m@kWLU`mIkmkXm@@`@L@xUKWkU@VL@JUU@mbUKVa¯WVnL@`lXUVkU@xW@UbUWVU@UJ@„lnU@m‚nÈmVƒa@bUL™wUb™@@VkxmUUƒ™UV›K@IƒUƒmk@akm@wmIƒŽkK@b™VWXkm@wULUmm@UVW@Ub„mbkKƒVn„U@Wl„xV„U@UXmWUXmlnbUl¯Lmn"],encodeOffsets:[[113378,28981]]}},{type:"Feature",id:"4301",properties:{name:"长沙市",cp:[113.0823,28.2568],childNum:5},geometry:{type:"Polygon",coordinates:["@@lVUllXkx@lln@‚XX@JlXXl‚V@LVVČxlIšƒš@VU@Un`nnV@VJlLUnn@lW@XUJnIVVlK„x@I„VlUVJ@XXKlVVUXKVX@`VLX¦lxVŽnLš°‚an@„„‚bkmVaV@XL@U„KlU@llLXUÞJWkUknaÆxnŽ‚knK@w„@l„@xllUXUJVVUb„n@blV@bnƒ‚LnKVa„LVbVV„UX@W¥XKVL„VVklUVy„U„VÈÅlaUK°wnnÜbn‚V„VL„aVVš@šn@VmnVlIlJna„@Valkn@na@amwm@„UXw˜K@aUUVUUaVa—wWK@kU@UaW@kKUUƒƒ@k™W¯XWan@k„™mmÅ@@I@U@KmLkaVUƒKkLWVUƒk@UVmU@am@kkk¥ƒUƒVUK™„maUb@ŽUb™I@aƒKkkWm@W¯K¯b@VmaULVxUXlVk@UxVJVbUb@xULƒ@ULWW—LƒĕmxVVL@šVb™KUwƒaŲWwX@@WƒUWLU@VbkV@aU@@VUnmJ@VUn@VƒLUK@U‚mUIk@UÇmU@@UW@J@LƒbUmVI@aUmW@@bkXUx@lmLUbm@UbkJ@V@XmlUbkKm@ma@kUaVU@aUK@mImJUIkVƒUƒVUakbWwka@UWKkLUamKUXm`Å_U˜ƒULmaU@@lUV@X"],encodeOffsets:[[114582,28694]]}},{type:"Feature",id:"4302",properties:{name:"株洲市",cp:[113.5327,27.0319],childNum:6},geometry:{type:"Polygon",coordinates:["@@X‚‚Unw„Ė˜KXXVK„@VK@wVaUaUIVwl@kUVWUwVKnb@U°a°LXŽ‚@Xnll„L@bšJVa@VanbšƒVL„U„V@al@@UV¯ÅÇ@Ummk™w@¯ƒyVwnUVVVUkmWV—nKVUƒa@WXkVKn@lUVU„VVVXIlV°VnI@VlKnV@mwVm@LXKWkU¥wWwƒƒ@k@m„X@KX¯V@VUVa@VnKWkœƒV@VUkm@aWa@wkUWwkmV£VÿXUVL@mVIXaò@nW@ašUš@@am™@aUU„UmXmWUk@ƒƒnUW@_maVm™wUkamaUL@aƒwƒW@akI@UƒxUm@kmKUk™lUŽ@b„zV˜m¯xUVU@ƒXVxm`kÈlxXVW„@¦kVUn@xƒxƒKUwÅKVXUJWnXŽmVUxWL„¦XŽm„mK—bmUUwW@UV@šk@ƒšVLnŽlbLm`@¦VVkX@`WIUŽxVnlb„WVbXIV‚lI@l¦Ç@UKmbk™W@UbUVU„ƒl@n@VmLXb@JWbUnkbVxUJUxWXXlWL@V@V@XXJWx„zUVVVVKnXW`@bkIUl‚„nLVJUbUIWVXlWV@XklVbnn@xlš"],encodeOffsets:[[115774,28587]]}},{type:"Feature",id:"4308",properties:{name:"张家界市",cp:[110.5115,29.328],childNum:3},geometry:{type:"Polygon",coordinates:["@@@InWVw°wš„@š@šblUœKlUlV„U„@VUUUlW@aöUlUlLÞ@@aVKXwlK@UX@@UlwkƒVkUm@m›@ÅVƒ@akwVaUk›UUlUL¯wƒƒ@UUmƒ@UkƒKƒlw±UULVn@l_XyWwÅ@VUUmJUXU@@mmƒU@kxW@UaUIWbU@@mU@UxƒnUbmKk„WJkUValƒ@aUkUxƒlW_@WUIU@ƒbkKWUJVnUb™bWb„lU@nl›„@XnVmV@n—mWV@LXl@X›JXVmzkJUXmƒ™KULm°Vb@xnVmnUšk@ƒƒ™VƒnnlUb@nm¼m@Ûǃ„Vl@X˜mnm„²ŽmL@x™K@LUl@nULÆx@V@VXVWbXX˜l„@nLlm@bVKœX‚W„L°bnUš@VaVUš@šmšVw„JnwVK°zn@V‚Vb„a„@Ċ¼"],encodeOffsets:[[113288,30471]]}},{type:"Feature",id:"4313",properties:{name:"娄底市",cp:[111.6431,27.7185],childNum:5},geometry:{type:"Polygon",coordinates:["@@lL„nJ@xln@bnlV„‚„@JœLVUšŽV„nVlw@Uš@VašxVK@a„bnUmÇnV@km@ƒ‚I@VUVVXVaX@@wlVVUkW@_mKXU°‚UbVLnaV@‚V@IUKV@XlVL@w@K@_n@lWlnnJV_XK@l°nšU@WVU@kV@nbVK„V—lƒ@nLlƒ„LXU@ƒlmkw@nW@UKVa¯IVn@@aVUUKl@nXVKVn²a˜ŽXblKnLlmVI@KUU@akLUaVa‚UXm@aƒ@wVUVKnLnWlXl‚n@@U@anUVm@U‚Inm@IUK@UmKVmU_kVUwm@@VmL—K@VƒL™aUaVUUUmKƒ¥ULkšƒVWaXwWa@UXImWUaULUUWKk@WnXbWŽVWnk@UV@bU@@bƒJ@bƒV@XkŽmb™UU`VbkaWzƒ@klU@ƒb@VƒwUL@bV@U`ULVL@VUK@Xm@XWWIUbUxm@@lkkÇwƒVÛÇW@¯Å™UJ@xƒI™xƒ@@VULmKUnUxmKULUUm@@‚ULƒU™JkIWJ@b@LJUW„kJWnUV@nn˜Ü_nJšxU@VbšnUxlškb@lš@"],encodeOffsets:[[113682,28699]]}},{type:"Feature",id:"4303",properties:{name:"湘潭市",cp:[112.5439,27.7075],childNum:4},geometry:{type:"Polygon",coordinates:["@@Æ`n_VWnLVblKXL@VlbXxlaVb„U„VlUVJnInJ‚@VL@bUVVb@lnbn@lLVank@W@UlIVan@VanK@kVwlW@aX@Vn@bUJVn„a@K‚IX@@VV@nŽVÈl@VJn@VVL„K@UVm@UnIVm@UV@@blUUaV@XK„V@XW@XxƱ„bVxšLUa@™UKWk™@wmmUalk@WXUWkXUVJVaUImKƒVklJ@aX_mWULUUVUƒyXwWI@W@U@UXKWkXWVwU@±_U»ÝKUaƒLVbkJkƒWmXk@UVVŽmIUV™J@UU@UamLmwUVU@mnJ@VUnmV@b@Vm@kkWmXmKULUV@x„Ž@bWnVUbVblK@bVV@LUJknmKkLWa—±bUmULmWk@VLUV@bm@U°JUbVLX@@mlxkn@„WVƒKk„mK@k„"],encodeOffsets:[[114683,28576]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/jiang_su_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"3209",properties:{name:"盐城市",cp:[120.2234,33.5577],childNum:8},geometry:{type:"Polygon",coordinates:["@@„n@‚°ĀÞ°@¦ULWKkx@bkLWb@lUlVXXJVbƒnUKmxXV@bm@@Xš‚„LޚܦXlVnš‚mzVJ@n@‚²ÞôkƃÞaȰĉ‚wnljÜó„éVÛnĊīČlj‚ĉ@ō@KÞUlU@ƒkklÇÈњÑlġXɛ@UġƒƒaU@U_ƒW@n™@kaUL@VW@kKmkUV@bkbWW@bkzma@ƒJWI@KUKULƒ@U¦™`@XUJ™U@KmXƒw¯KXkmy@aUIWJXXmV@K¯UU@@bVL@¤VLXbV@@JVXVK@„„JVn@bkKmakVVXUVVVlI@`U@nzVVƒb@¤n@@UlKXLVVšI@V@nV@V‚@ÈUx@šóVōšƒkÅWó@mU@bk@Ýwk@WbXxm@@J@zV@kVƒbV‚nLWVUX™WUXUŽWLUŽ@Wl°z@VkxU@UVWIxWJkbƒĬ„nW@@bUl"], -encodeOffsets:[[122344,34504]]}},{type:"Feature",id:"3203",properties:{name:"徐州市",cp:[117.5208,34.3268],childNum:7},geometry:{type:"Polygon",coordinates:["@@XKVX@WnIVx@K°Lnll@@I°K„nVašU°x²mlxš@VanU@aƒk@akmV@@w™@Ua@aUwVwUw@w›@UK@£kaĉlóIÇVkŽ±@@kUKmVkIkxW@Ua¯UUm@UVI@WVI„JV@ƒ@Um@Uana„U@m‚I@J@XV@XaVlkXƒVaUUWLUyVIXmWak@ƒXkJókƒJUL@KWkk@ULU@Wa™lUIkJmI™mk„VbVš@lV°kXUKWKULU„mb@VUlVnƒb@VV@IVKUUmU@ak@@bmV@xklƒUƒU@UKmV@nƒJVbkXƒKUamLUJ¯UUVmI™bVV—Ll`@LƒLU`m@kXUVU@V„lxUK@xkIWbUKƒx@V‚kVVn™b¯@@U™@ƒxk‚mbkLÇK™b™@@XnJ@LmVklƒ@@XƒlUƒVkxƒakVVb@bVnUbU@@x˜VUšVb@š„ŽnIĊ`šXVVôJš_„K@xlU²Klk„U„@VaVVÈm@kVUVmnamUUaVƒXIVJ„@‚ç@¥nkVLn›„@@XVK@VUX@JVUV@UnVJVLUJVLUVlšnI„b‚KnU@m°™VanI@anV‚KVL„an„lK„blš„KÞk@¦@¤@„VKnLVK„L„KVzlWšLX@VmV@VbnU°@Ualk™˜WXLVU„KWkUUWšƒ@£Wa"],encodeOffsets:[[121005,35213]]}},{type:"Feature",id:"3206",properties:{name:"南通市",cp:[121.1023,32.1625],childNum:7},geometry:{type:"Polygon",coordinates:["@@VJ@bnzWl°L„xnW@LšVVI@Wš_V¥„@VKVL@LXJ„I‚@nbly@aXXla@aVUnllLX@@UVKlbš@@m„XV`V@„bĢ„lkČÇƃȘ¯šwnĕVĉVÿšUƒUĠƒŦğlXÑVǵ@±ōLʵĖ¯lÇbÝÞ¯xk@Çkķé™n¯@ğŽġƴǫ@kVVlUbƒL@xULǂóLUl¤@nkVV°VLkxVb@l™aUXUKWĖklVX@¤UšƒUkb"],encodeOffsets:[[123087,33385]]}},{type:"Feature",id:"3208",properties:{name:"淮安市",cp:[118.927,33.4039],childNum:5},geometry:{type:"Polygon",coordinates:["@@šnźUôÒɴ胚l¦nĖV‚kbmš„X@xVlVL@xUb@bUJVnUx‚šœ„lKVLÈx‚m„zXV@lW@XV‚b@bȚVxnb‚ƒVIXa°L„aÆVVaXUlK@aXIƄVlXKVUlIXalK@alwXLVK@¥Ý¯¯ÿ@ƒmVk@aX@ƒm„īlaXI‚wXJVUV@lw@U¯yb›UaƒUġUÅaUKVknaġm@kUm@wÆIV±nLÆw„ÇnUUkƒ@ƅÝU¯JÝI¯¦Ul@bƒ@@VVL@l@LƒLÅmƒL@b™@UaVaUWmLUKV¹KƒLWKX¥WI@mXk@UmaUVUU@VmL@W™bkIUWƒUmVóIkbmm™@UbVLUxmJkU@bkJWbnXU`Wz™KUÞÈlVb™Lmx@„kè@Æ"],encodeOffsets:[[121062,33975]]}},{type:"Feature",id:"3205",properties:{name:"苏州市",cp:[120.6519,31.3989],childNum:6},geometry:{type:"Polygon",coordinates:["@@ôèĊVnX°¤²„lxƒÈÜ@²x@J@b@X‚`nIUƙUUV@bl@VVnL@L@xƒJ@X@blJXnW@@`XbW„kVƒ@UbVxƒXUxkV@LóxVbUVWš²šVJĸklUǬ@ĢƳĠ°@šmƒī°»ÈÇ¥ULUU±a@bU@¯ƒU@KnImUVWUk™mXUVU@lIVaUUVWKUbUkWKU¥n£WakJUkUL›K¯L™KkƒVIn@VaUƒVUUƒ›UkVk@ƒU@amUkJƒ@UUlwX¥W@@UkVmk@JUakL›@kk¯ÝmJUn@nmVXlmbVVkn@„UJ@±WUxV¯a¯KōbżÇxUxƒšUUlWL"],encodeOffsets:[[122794,31917]]}},{type:"Feature",id:"3213",properties:{name:"宿迁市",cp:[118.5535,33.7775],childNum:4},geometry:{type:"Polygon",coordinates:["@@XbWnUJVzXKVVUbW„klUWbU@@W@IJ@nƒVmbVbn@@V@„UŽƒIUJ@XUJ@VVn°VVbX@lwlJnUVL@l²@lÈUôJĊklb@¤VLœ@@xVxUxVx@bVbš@@xU@ln„mnX˜mXLVmV@X@lxVnVJôL„LXa‚x@b„@@KVL@bn@@m@™@alLUUVaU¥nIV±‚I@mXI@aWWXU@LlUXWW_XWmaUwǙ@aaWUX@@kWUƒynÇwUKkL›ƒ™VwUmVI@aVa@wUKUk@wƒWn™laUmĕk¥„™ɳçóÑŹV™mmzkVmm@a@Ióƒk@@LWU@`—„WbXLWlkImJVn@`nXVbXŽmL@Vn@‚l@nUVl°Xx°U@LVĠ@z°˜@¦UV@Xn@VJmV"],encodeOffsets:[[121005,34560]]}},{type:"Feature",id:"3207",properties:{name:"连云港市",cp:[119.1248,34.552],childNum:5},geometry:{type:"Polygon",coordinates:["@@@‚lzXxmÆV„„@@¦„@l`XnlKšXXm‚KnLla„b„@„xmbm@kL@V@Vl@@VUXšJX„mbš@@„°Æ@èÈzlW°XĢJlÈ`lInbšWV_@mš™@UUķnƒôw°ÆmnaVƒVÛVmĸ»Ģw±Ý@@mUIny™UmWkۥݙƒK™@Wn@@aWUnwVL„mUaWIUWVk@kkJUVWLUkŃWJ@bkLWVUbÅUƒb¯KWbUJ„WXX`WXkV@KWVXX@bWJ@nJU²mJV¦UbVVkK@b@š@nm@@aUK@Lƒ@@awWbƒKóKUIUmkwW@U@UnWK—nmWƒn@b„l@bmVUb™@kw±n¯w™VUb"],encodeOffsets:[[121253,35264]]}},{type:"Feature",id:"3210",properties:{name:"扬州市",cp:[119.4653,32.8162],childNum:5},geometry:{type:"Polygon",coordinates:["@@VUXblVVV„b@xV@kz„V@l‚wVLUbVV@VU@VbUbl‚b@nkĶ°IÞV@Ɔ„VlmVƒÈÅxmKU²ÅJ@xVn@lĢnmbUlVLÆbĢV„V‚bœV‚aXk‚@VXKVVWšXVWXUmKU„aWaU@™¥@£XW‚UUV@@ynam_VWkUVUna@ÆV@mnkWmXkWU„W@k„@@akklƒlWUI@UnKl¥™I@VVma@a@I@U@a@anK@UmK@ÅVUnJl™kI@aVwka@mVIUW@UWL@WÅbmIƒƒULka™UWƒUxkLUKWlXL@VƒImƒÅVƒU™mĉL™Uól¯I±l@ÒUbVbUVVXUJUnVV@lnbl@"],encodeOffsets:[[121928,33244]]}},{type:"Feature",id:"3201",properties:{name:"南京市",cp:[118.8062,31.9208],childNum:3},geometry:{type:"Polygon",coordinates:["@@k@ma@kUUVmVIUWVUUaVa@Ѳk°Jôk@Wmk¯KmX¯aUakKƒƒWU„@XU‚LXaV@@mUaVUUl@VmkaUXm@ƒWUUna°IlmV™m™IUW‚@Uk@@aV@VVX@„V‚I°»nm„U@VKVan@m»UaU@U_@WlIUa™aVaUala@¯n@‚ƒkaUkUUWKU@mwkUUmmL@K@ƒLmUUVƒKƒVÅImU—JƒƒVkVVLšèVLVU@W„L„V„š@nVÜULVŽUL@bW@XbWbkJƒUUVUxVXmVk@WUUkVmIƒV@„nbnVWbƒJU„kUULƒa@Jma@XkK@VVL@L@JƒLUVU@V¼ƒnXlƒbm@kbUKmn@lVb@VXXV‚UV@b@LVbÆxXbl@@lV@U„VV@XVK²VlIš`„UbVbUlVVn@WXn@@VUV@„@KmbVLXқLkKƒV@nX@VVUV@b™nVllbšmnb„IWVXU@`lLlknVnmlLlbUmVInK°nUƒU@l@VU@Vn@„ƒ@alI„`VIXaVaVa"],encodeOffsets:[[121928,33244]]}},{type:"Feature",id:"3212",properties:{name:"泰州市",cp:[120.0586,32.5525],childNum:5},geometry:{type:"Polygon",coordinates:["@@lUU@@y@In@WwXal@Þxl@@anVô@ÆX„lŎ™ôU@™Vw@ÇUU@@m@U™JUUWKkL@Vm@@£„aUUmyV@@_kJUUVUUWlUnblL@aUmƒI@ƒULUW@IU@WaUK@£UK@aV@°V@LnUWWXIla„VV™@£UWlkXĕVLVWšb@kUalwUKU¯lU@mk£VôKȁVK@w„KVaUkķlUI±™ğ¥ÝUŹš™Ž¯ôm¦ƒĸ™‚@XXK@VVXUJ@nlbUx@blJkšmIUV@ÆnL@VmL@b@b@V@J@bnb‚U@UšJk¦mL@VVJkXk„ll@bƒ@@lƒXXVWlXnml@nÅU@ŽmbUVlVUXn`mb@zU@V‚VWX@¤š¦V@Xb"],encodeOffsets:[[122592,34015]]}},{type:"Feature",id:"3202",properties:{name:"无锡市",cp:[120.3442,31.5527],childNum:3},geometry:{type:"Polygon",coordinates:["@@nLƒÒlxUVkL™am@™ƒkVWUULUxVVVbUV@bVLU‚nnź™ÞVĠ¦X™VUUaôw@KlUVw„WUwVa„@lUXƒWa@_X@WmkI@a@W„I@w@KmKUUk@@aVUšVVÅmJ_@W@a@I±wÛ@ƑÇkw±ƒ¯£mWĉUóçƒK¯VkUWK@XkV¯UWabƒmUa™UUb™lln@b@xƒbXŽWX`@„VxUblL@bn@Vb@`m@XbWnn@l¤„n@xnVlU„™VLÆWœkV@VbÞJ‚_nƒl@nKVU@aU™U@mVk°WVLUV¯bVXŽ˜bXlVn@VmL@x—V@bl„š‚@œnW@X@VVJ@²VJVU"],encodeOffsets:[[123064,32513]]}},{type:"Feature",id:"3204",properties:{name:"常州市",cp:[119.4543,31.5582],childNum:3},geometry:{type:"Polygon",coordinates:["@@„L˜ŽnxUbVVƒL@xnnW‚nn@VVXn@‚yœImx„„°ƒšL„a‚¥n@VkšKVw„W@nX„VJ@b‚@UVn„ƒ@UnUV@L‚b@`VLklVÞn„Æ@VaXLl™ÈJšmmVUK@aVUUaUUVwVKXVlUš„n@šblKVUkw„ÑmKUVUI@±UI@U@WmX@›™kƒ@a˜U@wnK@UUmWk—aWU°aVUUK¯XUl@nVŽVš@bUVmLk@m„`ÝIUaU@›lÅXUKƒškVmU@wƒmk£m@XmWan@@_Uam@@akKVaUw@ƒW_XW„a@w@akmm@mL@UJmnUKƒ@@XnJWLkKUb@„Vxk„WƒL—aWVUImVULUK@L@lkLVVVllb„m@@°kbVbUbšbVbkJ@XV`V@Vbn¼"],encodeOffsets:[[122097,32389]]}},{type:"Feature",id:"3211",properties:{name:"镇江市",cp:[119.4763,31.9702],childNum:4},geometry:{type:"Polygon",coordinates:["@@šVĊKšn„VÆUn„„J@UWKXkVLlKVwX„šVlbVK„„nJÆaš„ķn¥°óÇIkšWKUbÅ@mƒUÝlkUK@_a@KVUVm„@mƒVU@@aUIWƒ@mƒXUx™LUlm@¦ƒb™K¯„ƒƒnw›Jzm@UW@UmmXmm@w„KUUVamw—ƒKm@UbUL@ŽƒVmn¯¼JƒUW@UUU@@bl@@VŽVXšJšnnU‚‚k¯JmbVV„Xn@VWlbUnk@VVUŽVb@nU@WbKWVƒ@XV„„lLVb°bnW°Lnl@X"],encodeOffsets:[[122097,32997]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/jiang_xi_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"3607",properties:{name:"赣州市",cp:[115.2795,25.8124],childNum:18},geometry:{type:"Polygon",coordinates:["@@„`l@Èbln„@„KVLl@„V@bȎlnšKXkVlVL@„lJnb„¦VKVVnX„W@w°@VU„mln„UV`šU„bVUV@„xnKVI°KXKVkVL@al@Xa„LVlULWV™VVL@b„x@VXVmb@x@V™VV@nn¤„šlb°b°KXXWbX`lbXx‚z@x„`VIVUnK„L‚x„WXLVKVbVLVU@wnW°b„@nalX„‚mXVJn@U²mKkVl„U@@xlnœaVmlKnœ@JVLlŽnVššl@XXÆèVlUX@xVLXVšb°W@wnUWmXk@K‚LVwUmUkUKUw@wVaVK@kƒ@WnkUKWkwlmXL@KVUlLVKXmWU„L@ašL@malaVk@aa‚ašƒnXš@VVUblb„Jn˜ƒXa„V‚wn£„K@UWmUk@ƒUaWIV@b™JW@KmmU@aUUUkmKkVKlUU™nKVU„lVaV£Å¥WUUK@UkUUw@m@mIkƒƒUUWƒLƒK¯Uw°¯@wUKUbƒKmƒ@kkKUL@UUKV¥U@manw@k@U@Wm@@U@Wwkm„wWaUU@UUmV¯kwƒ@@kmƒkKkUW@UK@ÅV@XWWkXa@Ul@Va@KVaUUU@ƒaXwla@UkVWaXk@K@lmkUmV@Vmbk@ƒ»XIƒ¥VUkƒVUVU@anKVUƒKUalU@wX@˜™@a@K—@ÝwƒL@ŽUnÇlUIkJmn@ŽƒbVVb@VmnkLƒV¯U@ƒ±l—IWmƒ@kaUI@aÇU@K@KUIkbWbƒJUIUyƒX¯ƒUbU@méUUmUk„WK—xWIkJm@V¥U_UJUwmVkšƒUU@ƒƒƒ@knƒwm@UmkWJkL@n@VW@@‚U@knm@kUml@xÅxƒ@@XUJlb„@VX„JVxn@lbV„@lULnV@VlnV@bWV@bXL@lVLVb„V@blLn@Vl„K@xln@bX@lašLVbnKUVVb„KlXVVkxƒV@nnVUb‚lV@@z—°WWkbƒIk‚WL@LUJ@bUI@b™`@UmI@mkK¯XW™™mUV¯@UUVUUam@@VULWUJƒIm`IUJ›KUkW@Uxn‚WbnnmlXbmIUVmV@Vnb@V™LUKWLnÒVVV@V„UL@„kJUV@bƒÈ@ŽšV°šŽ@XVV@l@xUz"],encodeOffsets:[[116753,26596]]}},{type:"Feature",id:"3608",properties:{name:"吉安市",cp:[114.884,26.9659],childNum:12},geometry:{type:"Polygon",coordinates:["@@lxnb@V@bV@ln@‚n„‚lInš@blVXK‚nk¼@VUKWL@b™L@`UXU`ƒ@V¦XLĠ@lJ„¦@„nV@l°nn@‚mVXnaš@nb‚K„n@l„IVƒš@VanJ@_lKVVnš„L@L‚K@Vn@VbšUVanKlLnbnJVbšnWVnVVanI@‚Vb@L„bVKVanXVbVJVU@aXLll„bôlƼXxVLVK@Xn@ƒxnVVVmb@LnVVKVXV@@mnaVXUVnV˜K@_UaUmšwnKV_‚anKVLš»„K@¯ÝU@›™U@kWlUn™lknK‚VnaUkma@ƒUIUwl»Åw@ƒVwV@n™‚n@ÈXlKVmna@kVw@anm‚@n_WWk@™™mUkUK@Im›kLUn›bkm@wV@kƒlUnLV±m@UInWƒkWmbƒ@¯amX@xUVUKUaULWKƒXwƒKmLUVUJƒ_@wyWwkaW_XaWW¯L¯akaƒ™m£@mUUš@U@wnaWU@Uƒw@aUKšUXUVKUkƒKWbk@@bUKUlWL¯LUJmLƒwU@UVƒa™VU_ƒVkmƒnUV¯@@xƒXmWUUULƒ¥makI@ƒUKUkWl™LkmǍ@aƒUk@UKƒLƒ@kmÇak@ƒ_VlkL@`lbnšlLVanLnbmVÆln@škJlbknmKUbÝmmwULUK@bkLWKULUUma@Kk@UV@L@llbVzšxUxnl@bVLmŽšŽ@IVJXœVlƒLV`@bn²@J™@™V@Xmbñ@WbUJ@bm@@LUĬU‚„¦lV@xXb@blnUV"],encodeOffsets:[[116652,27608]]}},{type:"Feature",id:"3611",properties:{name:"上饶市",cp:[117.8613,28.7292],childNum:12},geometry:{type:"Polygon",coordinates:["@@„„@„V‚š„„I°`nm¤²@bVJUVVXUl@Vmb@xV@XbmVVœ@lkLmbn`VbnU‚@Va„UnbVllUXV„a@w°VW@_VWšLššnVlbšLVbnl„KšnVK@IUW@_@am@™‚ÑUólK@U@WU@VwU@UI@aUU‚aXƒƒ@kwmJV@yX@k‚anƒƒ@mkwVmmI@aUU@aUUW@kVkV@@anKš»„XVWnIVUl`@_„W@wlUœV@UWKnU‚bnŽ°InJl„UV@VnI‚b„Wn@VklL@l@Vn²m@U`kI@bWJƒnV@°VXnJm„XVmx@VVL@bkLmWULUmU@ƒbWXb@llnX@‚xkxVV„nVV@¤nL‚nVxnJVXX@˜ššbn`VI„b„@„blmlLnaV@„blWXnlUnbl@„ƒšKVanUVmm_XK@kWWnašU@UnaWUXa›ƒXamUkKmXUWƒLX¯WakKm™nUWwXa@KW_„aXWW_@WnIVl@XU‚LnWVknK@ImyUUÆbXK„Û@W@IÆUnƒVÝlkVK@mUIVwkUVaUm@aVIVyXIƒaÈwmmk@UnanVUmÅaó»lwšW@kkUVmUK@WKLƒUmWULkamK™Lk@Wa@wk@UU@U@mbUIWVKUXWmkUmVm›U@LkakKƒw@w@U™¯ƒ‚ƒUUn¯l@bmn@xkJWxkL@VkI@mƒkmJUI@V@b@VVxnbWlkÈkVƒLƒbkKmVƒL@V@²nxW‚kLUL@xlKVx„bXmVnšWJ@ޙ°@n™xUKUw±`UImVmnU@kalm@akwƒU@UUJmxU@@Uƒ@kU@Um@@Kn™ƒVm@k™KmkU@@WUnkLWxkVUwmKmLkU™bmKUbVŽ@xUnkJ@n±ŽšUxVXUšWJ@LUb™lUnm@ƒW@nknUJUVm@kXllknVbÆK„VVbš¼V„@šUl"],encodeOffsets:[[119194,29751]]}},{type:"Feature",id:"3604",properties:{name:"九江市",cp:[115.4224,29.3774],childNum:12},geometry:{type:"Polygon",coordinates:["@@WUkVUkmaƒVUb@mVUam_nalK@kU›nUWaU@@wna@UVkUWVUUI@a‚±n£m¯_ƒJ™ƒU@ƒƒƒĉ¦Ul@UV™Km™mLlm@ğ¹m`Uk¯@@UVK¯™@UUK@amkmKkVVUa@UkUƒKƒŽUa™L@VVXUJ™@ƒnƒ@™š™WUbƒnVb¯V@LÅlÝIƒJÅkݙm@Ua™WUU@UmUXmmwVUUKWUX±mUam@kWƒzUaVmÇw@aÅLmKXƒ‚UWKkL@W¯IƒwVw™lkUƒJ@Um@ÛÈWŽKUxWkƒaUU@KkLVl@„UKUX±KUb@nVVUbUVmaUlUL@„ƒaUL@‚@nUlWzX`@„V@lx²„@Vlb@bšVÞ@°nl@UxVL@lUbVV@n²xVUVmnUÞb‚a„J@IšV°xnbl@nbÆ@VwnK@VnXlK°xnUlVX„V@Vl@L@lk@W_XK@KƒkWxUL@J„nVx@aX@VVUa˜IXlmL@bVVX@VbnK‚a²XVWƒk°a„@UnV¤nbmLmW@XbmJUbVL„aÞK„L@K@U@aVKlbV@nXlJœxV@VnšŽVȚ„ÞKôbźĕČmV@ĊšŽ²xÆIšV@Þ¦ĸ¼ÞVlŽVÞnxln°Jœk‚LXWVUVUVwnJVI@yn@lXlaXmWI@w—»ma@UmK@akKkXmW@_kaWakKWk@@K@IšWƒkUa„ƒ"],encodeOffsets:[[119487,30319]]}},{type:"Feature",id:"3610",properties:{name:"抚州市",cp:[116.4441,27.4933],childNum:11},geometry:{type:"Polygon",coordinates:["@@°V°UnÜ@n@lnLlV@bšV°L„lnLllVzVVXlV„V@@L@xX@WlX„m@UVƒL@V@n„°škVmVUnKlaXxVbšnlU@lVVnaVI@aX@V„šJš@V„@b„b@šVbš‚@X@lUL@Ž@VlIVm@wUVanLšalVnKnLVxlUXwlKVm@k@Una@mWIXKWUÛVƒk@a@UVWn@@kl@@W„XlW@_Um@UVK@a„LnalInWV@@xnI@¥‚K„—šm@kKmƒnk@mlI„¤laXbVblknV@U‚KXVlUXa‚@@Unw@±mU@ak_±a@ƒUJUIƒVKW_Xa@aWU™šK@mmUVa@IXa@UWmšannlmX¯WKXwVUVwƒ@XUlK@klJXa@kƒkmm@Uwƒw@¯ƒW¯kw@WmbULƒaUUU@mVUU™WmkUb™KmkkK@aƒkUƒ¯¥Uƒl—ƒm@akU@mš@KVIVV@KUkUVUkaƒUWb—„mƒIkaVaUU™@mW™„b‚b@bUlkb‚b@n™K@bƒKXVWnULkKUV@LWKknlxXŽVLml@X„Ž@lULUb@xVxVLVlVnUxK@LWlXnmV@x¯X™aWUUK@wVWUkÅçm`@mn@bUx@lmbUnkLÇWm@mšU@Ux@„Æxk¼VxVJ@„nbVlmbUmLklmškVlX@‚VœšV@°Þ"],encodeOffsets:[[118508,28396]]}},{type:"Feature",id:"3609",properties:{name:"宜春市",cp:[115.0159,28.3228],childNum:10},geometry:{type:"Polygon",coordinates:["@@@VlbnK@b@JšLlUnx±ĀXxÆW„X@lš@V„@@blJ@nX@˜xUbVVUbVV@b—VmnmJœ„@bmbm@klUbƒLmbœš@lVb@xUX@bVVVbV¤@LVV„bXlVw‚LXÜÇn@@V„IlVškUx„x°J@XlKXLV„‚WnLÆK@bÈxUnVb„ylXn@Vbn‚W²XV‚LVVUŽnxWnnV@VVVšXVbn@ޚÆl„IÞJÆk@K°UUa„mVa@UUUš»@wV@VƒkkUKUVW£U@UmW@@aXkVUnVlKVV„UUkVmU™@kWaUanU„VVamIX¥W@@aUaUVW@_mW@UnIVVn@VbVm@bVL@anKVUkƒWK„UXV‚Ikx‚@na„bVK„b@nVJ„_V›@Vw„‚VUVVXUlUUaV@X@VblašbnKlkVaXaƒ¯@m@U„KVUn@WƒXkW@@w@KU@UƒWkUUUykkmKƒk¯K™U@akUmK@k@mmÛ¯V¯U@‚ƒL™¼UKmLbU`mL™xVnVb@`—LmUVUUWmb@nU@UWULmU@KnaUUmU„wmJ¯IUJWIkVkaWVUIUlWaUIUVkKmbUIƒÒlVUnnŽ@VlLUJ@bUX¯@ƒaWVUKUXƒKUbm@UwKWa@a@VkUWn™@Uak@mbX„WJXbm@mL—aWVk@™wƒL@WmanU@knwWmkaWL—KWUXaƒU@¥l„UVVVbnwƒ¥nKV™»@aUk@a@UƒJ@kƒmLma™@mbUWnm@ULǺ@LXnmxUŽm@UbkbW@@akLmWk@UXmJmUkV@VUXVlULmKUxkL@lmXnJ@X‚l°Vnb@bU@WbKUX@VmKUX"],encodeOffsets:[[116652,28666]]}},{type:"Feature",id:"3601",properties:{name:"南昌市",cp:[116.0046,28.6633],childNum:6},geometry:{type:"Polygon",coordinates:["@@šXš™„@„mš@VIUW@UšKVb„„LlV@VVbUŽlUnLnl@bVL@V°šUL@V°@Vln_Ġºn@‚knKnššLVU@VkĊ¥Vk@™Uƒ™»UaƒUÅLUalmkklWn@VUVIlm@m„Xn@VmškVa@KXIV™UWVw‚™²@m@U@VK@k@W™Ua@™ƒa@aUƒ™@™IUƒW@@bUJmbUU@kkV™mUaWwkbmLUVUn™lWbUbklmL™akbUaW@U@VbkVWVUUUVƒUx@‚Uœƒ`UI@mƒaULƒamb@lwJWUƒVXLl„UVmL@bUK@aUnUam@UUmJ@VnX@`UXVŽVb@bX@W¦nJUbƒUmVVbXb@lVšUnVlƒVUUkLmUUVWl@bX@VnV@X¤VUVLllU„U@@x™¼VV@V"],encodeOffsets:[[118249,29700]]}},{type:"Feature",id:"3602",properties:{name:"景德镇市",cp:[117.334,29.3225],childNum:3},geometry:{type:"Polygon",coordinates:["@@VVX@Vbmz„xUlU@mbmL@V²xVbUVVblbX@šVškVykValKVI@bn@n`lVWnX@l„L@™WKnƒVIVa@¯nK@alIXJVIVWUw‚ƒn@nU˜„nK@alI@a@anKm_™a—™W@UWmIUwmmK@£UUƒmUUlwwW@km@kWaX„aV@VnVKnXlK@aUK@UnwWUnƒmIUW@¯mU„XI@alJV_n@m±@U@kkKUlm@ƒXamJ@UVUkƒmI¯JmamVXL@V›UkV@xƒX@`k_UVmJUXƒW™¼mL@bU@UllX@VV@bVV@bnJUnlx@n„Žm„b@lWŽ@zU‚nIlx„@W„bVV@bVJV@UxV@@X@VkLVôÒ‚šn@@b@`VX@J"],encodeOffsets:[[119903,30409]]}},{type:"Feature",id:"3603",properties:{name:"萍乡市",cp:[113.9282,27.4823],childNum:4},geometry:{type:"Polygon",coordinates:["@@VWnL@UVW‚LXaV@@ama¯Uk@WmInW@klKVwnLVKUkVW@UlUnVnIVWl@nXlK@bX@laVan@VnwWm@KȹVK¯m@kmU@ƒƒ¥kIğ@WKU¥„@V_VW@_šK@aXKVL@Ul»mWLkU@am™kJƒm@kmU@@a@UmakwU@›„Xlƒ@VXk`UIW¼kWWX@‚œ@l‚xV¦XlW@Ubn„@ŽmUkL@UmJ¯UkUWVUaƒUlm@UXWl„nUJ@LmLU˜nXll@bUVUUmVUn„Ž@¦šxlŽnn@VÆÈU°kbV„VxllnL@VnVVUl@V„„anL"],encodeOffsets:[[116652,28666]]}},{type:"Feature",id:"3606",properties:{name:"鹰潭市",cp:[117.0813,28.2349],childNum:3},geometry:{type:"Polygon",coordinates:["@@@XV@nlšL@lUnš„mŽ@Ln@@VlV„@@VV@nwVI@V„Vlx@bknlbV@nmnUVJ‚_²‚VxVLšw@mš¯@ÝXIm™nUWƒaUwkL@wVKlKXmw@±@U„KnUlL„a„KlUlÇXkmaUw@U@a@Uƒ™UkwUJ@zWJ™w@WbkVWUL@VmUklUaWakbƒ£kJ@nmln„lL@Ž™nƒ˜L@¦mJ@wU@mXkJmbƒK@bUL@VVn@`kXƒW@Xk@@lm@UX@V@b„lÜUXVWLXJ@nmb@V@l"],encodeOffsets:[[119599,29025]]}},{type:"Feature",id:"3605",properties:{name:"新余市",cp:[114.95,27.8174],childNum:2},geometry:{type:"Polygon",coordinates:["@@m@@WULUKWwÅ»ókƒakkWK@bUVUIUamWUbULƒa@KUa@mJUbmUXU™mUamImakKmLUb™VUam@@UL@KƒKm™UUkL@`mIUb™@U„@V@bVl@bš¼UŽmL„¦mxUaUUƒVkŽ@¦„VWbXV˜LXKlbXnmx@lmVnb@X„Kšxl@XU˜bnKn@WaXIWƒnal@Vbš@XmlV@U@bXb‚LVxn@Va„LVWVLXU„b°@VW@aVIkK@UmVmkU„ÑVJnalLVUVJXbVkVJXUlblUXJVI°JnI"],encodeOffsets:[[118182,28542]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/ji_lin_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"2224",properties:{name:"延边朝鲜族自治州",cp:[129.397,43.2587],childNum:8},geometry:{type:"Polygon",coordinates:["@@Wxĵ„mš@„ó¤VX@@xܼƨš²xWxƒV„V@„XVƒ„„„ƒbWšXllaÞU°Ċ„@ô¼„LôÝWanV¥ƒÑnĉ°¥šÅX¥°¯@w°w@»°k£°mÈŹ‚mÈbƃŎ¦„K°z@Žkxl¦UbU¤šššklV„KŤÞȰ@@bšV@nVVUlÞ¦lUllœVlU°ÑU¯Vƒ°w„bXxl@VŽ²„˜@n„ô¼ƒó°™kmVk²ĕ‚w@wV™ÞÞ@@Ġƒö»˜¯œ@‚„šbnb°mÞ¯°V°„ÈJmX¥mam™UřƒUƒlaU¯™ƒ@w™Kk—l±n@@wƒkÝVUUl±¯I¯b™a™lƒ@™kLmakbƒ@ġƒŹé°™Þb°šékƒƒLm™„wX™‚aÅb@bVlƒbVb—ÒVbUb›UUanwƒakbVŽUV›ak„¯„UŽƒLmxV°UxnôŻX@J„Xkl‚bkbĉaƒbƒWU„ƒ@ƒk„WUU¯@@klmƒ@@™Å@aƒwWXlKkI@WbUaVIUanUƒƒ@ĕƒ¯K™„mUnWUwm@£ċèkUmbUmm@@nkJUalwk@@nmWUan_óaWmnw±KœIƒwl@UmƒI@an@@mlUÅmV_™KUkƒ@U`@_ƒKUmU™@U¯™mmb¯@kb™ImV¯ƒƒLkbƒKƒƒÛ@ÇnɱJóaÝĢkb@„›x—ÒÇllœ@‚Ž²V‚„ÆUVV„UÇ°X„óxlV¯„lV@bƒV@n—x›@—¤@„șŎnxV¼knšJ‚nšKX°˜¦UlnVbUbÆVnÞWVX¦llšb@l°œVJôÒnLVbšbXŽ"],encodeOffsets:[[131086,44798]]}},{type:"Feature",id:"2202",properties:{name:"吉林市",cp:[126.8372,43.6047],childNum:6},geometry:{type:"Polygon",coordinates:["@@ôl‚zšaÈV°„šK@„mŽ—LWl™nšVxUV‚È@ŽÝĬUÈn‚ôLša‚„²VmĀkV@„ĠĊnU@b„V@b˜@nl°UVnÞaôJ@bš™V„¦mlkššbmVXx¯@Vxm„nbƒ„šbÈK‚V@bÈL„wĠyônšmnbÜ@nn„V˜x@n²K‚„„J@k„al@nxÞU„Lź±Vwkw¯LWWUš™kŎīVwƒw„°y„Vĕ°wÈVlkÛ»@wW@Uô£@ƒn™ĶƒXwW™aUamKóÑUI¯›@k™akkW¥XUmÝÅUVaUa‚mVk—¥W¯™Lm™IlmU»mwȚō@ƒ˜£kJUÇk@am¯y¯UVwƒa@wġx¦ƒKƒƒ¯X°Ċ¯¦U°ċWULÅa±b¯@UkÅWmVƒ™ƒkIUlóŽċ¹™`óIƒlX„WŽXxmbUƒLݏƒbƧ@ƒx¯bƒÈ—l@xƒš¯zƒaݤ@nšm„VWb²bmn¯J¯Ò@n„š"],encodeOffsets:[[128701,44303]]}},{type:"Feature",id:"2208",properties:{name:"白城市",cp:[123.0029,45.2637],childNum:5},geometry:{type:"Polygon",coordinates:["@@ó™ǩŁ@WlwUaƑwÛÅÇéĉamKƒōÇ@Iƒ™ôġVƒȁÑŹçƒ™ÝUƧċĉwóóÝ@Ƒ»ğL¯ll²@ƆÅV@¦m‚Åb@nmlU²VxšlUn™@VbnW„bÇbk҃š„n@èlnlšU҄Ž°Lšx@¼ĉb@҄šUŽċxՃènLVxƒÒƒbÅJ±a@_ÅJÅnƒŽVb„Kl„nUÜĊ@„Uš™xXVÆn„mšVššJÞ¯V™ĠwšƒXw°xWL„x„KV¦ôU„wVÝǬóÞޙ¼‚‚„ÞkŽVôȘxބU„lVn¦ÞšĊa°w„b°@šbÆw„lŤL²`„z°@V@@™nJVnl@@¥nUmmn„@mwnmmUnk@mlwUaƒLnƒ›wn¯°anƒWakI„ƒÇmXwÆamUXUlJXa‚UUklKUknmÞV@‚K@VWÞ@VkUwVƒ"],encodeOffsets:[[127350,46553]]}},{type:"Feature",id:"2207",properties:{name:"松原市",cp:[124.0906,44.7198],childNum:5},geometry:{type:"Polygon",coordinates:["@@„šźèȂÒU„óĢ„š@JŎȄ‚‚LnŽĊbÈêÜƃxVbkx@XǪłôš„kÞ`„šW„b@n°ašbšKšnVw°`š_X`W„š¦„ĊIkmVšakw‚K„x°UÞb„U@lšƒl@°¦œVW„šaÞbšxÞI@mVI@ƒVkŚUWK„¥nL‚a@ƒ„@ȍ„@°ƒÆ@nU@KÞalkUwVékUWw„™kU›VkkƒJk¯@»ókƒV¯ÆÇI@bĉô¯@™ķw¯nmmÅL¯wƒVƒUÞy@UówÇLkmm@@UóxkkĉmL¯wVwkWWX™mLõm@kűV_ƒƒô»ÛƒÆ¯@™Va™VšaĠVlmğwķUóÝƽ£ÇJkbǫaƽLW@nxݤkzƒy¯XɅm@VšôÇX¯Ė¯ºÝnUŽnLVlUÔmV"],encodeOffsets:[[126068,45580]]}},{type:"Feature",id:"2201",properties:{name:"长春市",cp:[125.8154,44.2584],childNum:5},geometry:{type:"Polygon",coordinates:["@@„U°xÆKnn°mĸxš°@Ċó@aÈJ°Å„Uôl@¼l°„IllœUlVƒšXxlVUêVxkllnÈUVll@Vx²IÞ¤VUlVnIôlރlwô_„›„bVaĶLXÅÞÇ@K˜¯@wÛaƒçn¥š¯WXyW¯XwƒUmmÛ@ma™nómğzƒxÇK@aUÇL™a„ƒmanƒUw°@WwnU™al™nkƒ¥šU™@aóIÝbUm¯Vmk—@@aƒU@amVğĉ@ƒlUnÿ±Uƒ™bóKmVÇÞī@ÇVUUw‚™šmXk˜Kn@ƒ™L¯ƒÇU™byókōè@b‚n@lÝX@x¯ô@ƙUV_maXm@aóƒJWxnX@ŽVVnĖVnUJ@nōÆǼV¼kxƒLklÝw@xƒx@zV`ÅbmxU±xU„nnm‚kn‚ŽğU™bUŽ‚šUb@šÅ°Ü„󼄄U`Ʋ@lön‚KšnXWlXUx°xnKĊllôw@Vn@lnÈKôx@VÝz„V"],encodeOffsets:[[128262,45940]]}},{type:"Feature",id:"2206",properties:{name:"白山市",cp:[127.2217,42.0941],childNum:5},geometry:{type:"Polygon",coordinates:["@@Ušl¦kÒÆ°„IlÒU¤ôz„¼lJš„U„n‚ÆXVl°@²aÆbVKČXV¯°¥¯ĉ°W„„„L‚¥Ģw@x„bUx°V°zn‚‚b@ÈlVŽlIœ@˜w@m„U@akU°ƒkUôwWƒÈ¯VUƒVUƒÅ±U›@kÈk˜Ñœw@ƒlaÞġƒUÞ£@ƅ‚KnÑĢ¯@W‚aUaVUVkkw@a¯@¯™Ý™ƒVXnW@@WkXmK@xkKUb@bW@Uw¯„mmb@WKUbmUbUaWbƒJĉIVW@I—l±LkšmU™bUm™@ƒnkKWa¯n™@„`Ubma™„ĉL@bƚ—@W`ƒL@n¯‚Xb‚@kb@x™Lƒ„™@V‚kL±™™mlUIU¥mL@lÅx@_laƒƒ@U—aƒV@kmmƒK„£ƒƒLƒƒmKUnÅKVbmXVlèĉUUbml„ĢŤƒIlŽ¯bǦœl‚@ô¼Ģ„@x°„l¤„n„a„l@x™b"],encodeOffsets:[[129567,43262]]}},{type:"Feature",id:"2205",properties:{name:"通化市",cp:[125.9583,41.8579],childNum:7},geometry:{type:"Polygon",coordinates:["@@ÆlXnĠxĢ°lÈ°š„K„°kXm‚@¦Vbk„ŤJšnݤk„VÞVVkȄb°y„™@w˜k„Ç°a„wƨ@„aސ„K‚VnaWwXWƒ„kôJš_ČºôVkƒ»óyV£kуJůlÑk¥V™ša@wƒkƒbƒmk£¯ƒ@wġƒó»@›kÈ¥°ak„JÆ£ƒġnkVaĊVkçWUnUaÆLVmnL„„‚KU™±@—„m@a¯U„bmV¯m@_ƒK™™U™ƒaƒÅ™Wó¹ƒ@UanmWak@@wmI@y™@mk„JVa™@UaƒIkJ@n™@Um±kkxƒm™Ik„ƒbÇm@Ž°bXn„V@Ž°ÈmlÞ¼¯XVº¯Lm„kWWXLmVVlknƒ@@lnWƙ„Vxbmšnšm„¯lÝaVȁè@¼V„„b™„ÆŽ°ÞUVšJ„„kx›I—xƒƒƒIV¤™ÒXxmn"],encodeOffsets:[[128273,43330]]}},{type:"Feature",id:"2203",properties:{name:"四平市",cp:[124.541,43.4894],childNum:5},geometry:{type:"Polygon",coordinates:["@@Ɇn°W„zlyÞ£mwX@ƾKǬblaÈIƾ¤ôÞĸVĠxnmmVƒ²w‚VnwÆaU_@y„w@wÞxlk„KlwU»È»ŎÅ@mVIUmmĕUU@mWXw„Iô‚@bWnnbU`‚šV@Å°ó@wÞW@km@aŎ烙@m°Ñ°Inm±aXaƒU™n@mƑšU¦@šÇŽ¯aU£šaU™ġ¦ÅҙJōUŻókUÇ@™¥¯ak¯mUVak@@aċçÅaUƒm¦Ý`XbƄ@n`ƒI™xĊÞōÞml@šUb@Wl™_¯JkšÇUÝÆÅb@n™„llUb¯„±a@ƒ—ƒWĉJġĀ¯™Unóšm¤œxôaVnƒxôI@x„V@bmƙ„@lnLmޯޙxVb¯þ"],encodeOffsets:[[126293,45124]]}},{type:"Feature",id:"2204",properties:{name:"辽源市",cp:[125.343,42.7643],childNum:3},geometry:{type:"Polygon",coordinates:["@@żôŎVšIÆÑĢ¥Vš™bV¤°bȍ@™V¥ƒ™Þ£lÇUUUÝlƒÞ£™mţIlƒUa@¥nlWƒ¯ƒL¯™kÇġ¯ğwWmÅk¯UƒVU„„bWlXlmnƒbUx¯xVVknlŽUbV„ÇKUb@„™VnbmlnzUº±bmJUbWÈnèm҄š@X`WL"],encodeOffsets:[[127879,44168]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/liao_ning_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"2102",properties:{name:"大连市",cp:[122.2229,39.4409],childNum:5},geometry:{type:"Polygon",coordinates:["@@‚IÞmVk@wXWÜbnwlLnU„@‚nLlbXW@a‚wnbl@XL‚aš@Ċ¥@LULnJ@xVnmV@VXXV@VJkn@VÜKXXôJlb„xl@„IVbnJVLUbn‚lnVw„JVU@ƒXU‚aUUlwn@°ƒn„VKnV°_VJšwl@nwlV„IXWlIVVnK@IWmkIVaVU@WÈUlmU@U„WUalkXġŻ@kIƒ»mm™akUm›ĉUŁV»²ġVĕ@aUU؍IɃ`ȃ@kƒw@ƒUƒmwĉ™@ƒWķсIĉÇbÝLkymbIƒwÇmÛbmbU„¯ÜõÈkÆVbŎxnXVÆnšǪ¦„bš¤Uš™xÝnĉÒmĊVȄ¤Èš„bƼ„Ā„„ÆÆބźb„VVbX„‚°²¤"],encodeOffsets:[[124786,41102]]}},{type:"Feature",id:"2113",properties:{name:"朝阳市",cp:[120.0696,41.4899],childNum:6},geometry:{type:"Polygon",coordinates:["@@na@UVI@m„ÑW™kaV¥UI@wl@„aÈbšm@wVašk„@@K@kƒ™@a@UUmƒUUalmU@KÇUű¯@±kUKVkUaƒaU@¥m@@¯k@WLUmkn@mmIkm@amU@wVmkU@Klk@U—m˜aXIWWUL™aULVbƒmk@UUmUk±™_Uym@mbkImaX¯WW™xWKzU@WƒkJWwkV™@Um@UbVVVVXb@VWX—@WŽ@Vkb@V™nUK±aUUlwX™ÇWKknU@mmUkƒLUVƒVUUVƒUaƒw™bkKmwnIƒ™kJ@nmbƒ`kmVkLWwUm@UUU™K@UmaUa@UUaWK@mUƒ¯Wkk¯VmUUŽ„xVXUVmL¯ymXkWUbmXUKƒVknWx¯JVnkLƒl@VVxnxlĀVL²WlX„l@bÝVUn@bnlÜaXblIVl@šš@Ȧ@VmbXV‚@@x„VVnUn@`°@VnXU@K@„VV@VmbnVn@ln@b„xƒ°Ub@bšLV`Ånƒ„W@@lUšnnWVU@Vbkl@Xl`XxV„UblŽkX@Ž°¦V„UVVbUlkV›@UbVbkLUxmJkXšš@b‚bœxVKÆlXX˜bnŽnala@ƒUk@U„VVklKVUXKVU°KVan@VUnLšKVL„WVaU_@mmUXa@m˜wXwVkVWXk‚k@›„k@klm@wXKl@U@KVUUUVaUƒV@„alL„xUx@b°°VnnVšxlIXJmx„LUVlV@bnX@Všb„aVx‚@XJ@b‚n@VŽVXȄl@llX@lU„Vô°°@ބVbn@‚V„k„@VW"],encodeOffsets:[[123919,43262]]}},{type:"Feature",id:"2106",properties:{name:"丹东市",cp:[124.541,40.4242],childNum:4},geometry:{type:"Polygon",coordinates:["@@lzXJ‚U@š²x‚@@Vš„@bUVmKUn„°n@lnVK„„nV@n@VlV„°WbXn@‚VzƒJ@¦@bkb‚bUl@bkbƒJ¯zƒWULWbklV„nb™¦VJ@„„K°U„kl@@W„bVn°@„Všm²U˜nX`„UÜLXmVXlKVbUVVnUbn˜ƒX@VUL@lUbWxš@²kl`n@Vlb„@nUVWVLVU@aV@²bl@ÈmšxWX„VÈU„JV„l@„„la„WnX‚KÈkÈ@Va°bÆm„@XV°IVV°UnalƒVUn@UwVU„@@VVJ„I@bl@XK@wWmXU‚UVbkJVXnJVI@mƒknwlKXL@`l@VI@UUaVKÞn„aVm@aÇ£XW„U@aÇUU@mbkKm£™@WW™ƒL@@Kk@kl›U—bWKUkUU¯UõÛƒmUUaVU„U@WU_W@kVkJƒ_WKkV@bUL™¯¯ƒ±mk¯ġƒğÑ@UmwƒKUakƒ™ƒa@a„m¥ÝƒIUWmk@w™mţ—L›KʝbȗKWĢklVbƒX@VV‚knÇV@XUVUblJXn@J"],encodeOffsets:[[126372,40967]]}},{type:"Feature",id:"2112",properties:{name:"铁岭市",cp:[124.2773,42.7423],childNum:7},geometry:{type:"Polygon",coordinates:["@@XJm@¯šmXUlnVbUJƒU@bV@UJWL@VXLmJVbkXlJXxVL@b@V@n@b@`Vbk@lxknV@VV™V@bUL@bV@@bVK@VXLWLXJ@LV@nbWJ@IUV„x@LVJUXVxVx@VV@@LXJWL@VU@@L@VnL@bVVmVX@@VVInJmbnLWVnVULVVU@VVmX@@JVz‚l@„nVVKVXރ@mk_lm„UUWV_nJlUÞÑÞVVUVƒVL„UVJ@I„Vna‚@@KV@XwWknwnKlalU„w„aĉݚwšJl_@aUaƒKUUU@WU@WXUÆ@@UVK@n@UnVVšblK@bœllb@b„bW@Xbl@UlnLl°°bš¦nKlVnI„V@UWU@WXkƒw@am@nm@aVw@I@KUaVIm±XÑlknJVnVJšaX_VaUaVKmwnkmmn@lU@U@mnašXlKUmUIVmklaUK@UlUVUW@U™kVm™a@UUU@JmUU@@bmb—KWV¯XUKm@ka@UVKVk@aUKmLkKUUÝUmbXbÇJ@k@WU_@m™™@klm@UXKVaUI@KWUXaƒÇWk™aWUkWUL±U@lUU@ƒUJƒI@V¯JmIm@@aU@Uwƒa™@UV@VkI›V¯aUkƒWkb@bVL„@@VVVUXW@Uaƒ@@b—‚ÝbUV݄@ŽƒLmUkVUbVllLUV@LššXŽWbUXm@U`@„kxlnnJlbnIllšLX„lVlUXmVK„n‚V@L"],encodeOffsets:[[126720,43572]]}},{type:"Feature",id:"2101",properties:{name:"沈阳市",cp:[123.1238,42.1216],childNum:5},geometry:{type:"Polygon",coordinates:["@@ȚĊÜ°„b„L‚lÞxUbUn±‚@ÈnVÆL@xnLšlUVƒbƒxkImJkn@V±LUxkV@bšbšKVKnzVl@L°@Va„xÞUlbôxVVœ@@V±bnŽ@llXL˜ŽöXĶŽnal@nkVJVI@aU@@aVK@ašUUUU@lmkwl@Ua@_@a@m@U@aUKWwkIlWUanIWK@UXKVIU@@a„VVIUa‚mVknW°™n@WI@KUƒmULWnkVkUWƒ™KkkmJkamIkmlw@ƒV_n@VWXaW™™@KVUkKUkValUnV„K@ÞƒVUÞa˜@a„@VbX@VWUU@Uƒ@UK@ala@IkKmUUa@U@ƒVƒkk™WVwU_@KÜUXbl@V¥XUVmƒƒƒXa‚kŃlUUkIm`UIUJW@UIKmkm@UUJƒImmU@ƒVUXU`mIUbUK@LƒJUU™l@Xƒ@UbƒJ™kU@ƒŽn„m@Uam@@ƒ™aUmLKƒwƒ™mWXUK@kUaÇa@JUIUa@aƒKVUƒUXmƒUy™_@lmbkLUKWLX`‚n@bVL@JXL„‚WX@Vnb@Vm@UbnVmL@V@x@LUbVV@V@LƒUVl@mb¯U@xU@UVVV@X@VVblJ@bn„VKUn„x@llnL±¤™b@k`VXÆK@„kV@¼kl@bWIUl@VmLnbm@@JXXmb"],encodeOffsets:[[125359,43139]]}},{type:"Feature",id:"2104",properties:{name:"抚顺市",cp:[124.585,41.8579],childNum:4},geometry:{type:"Polygon",coordinates:["@@„XVl°bœUlJ@UVUš@„bVxV@@bn@nJ°I@U„J‚I„VV@V@k²VVKlXXVšb‚lÈX„ŽWbXV@LVJUbWL@Vkn@lšš@nV`@X@lÈIWanaÞVVVlLnKVL@bUlUL@Vlbn@VL°WXU˜Lna@aV@nV@IVV@VšbUnšl@V‚XnKVa@U„UnyWkXaƒaVk@ašašbnm@_WKXmWanU@alaU—l@XJVLVxX@˜wnKnVlwƒƒ™@V_@a¯¥@UkKWUaUU‚anK@IƒaU@WUaVw@klUVyUUVUUÇ@Iôbša@mnUma@kXa@UWak@Wa—l@a›@WUƒLmU@U`mIUU™`mUk@@UUK±nkJƒbUam@kwm@@a@UU@Ua@@K@ƒVK@kmKU_UKƒUUaĉWmkkL@`™LƒnmlkLkbmK@k™@Ulmb@b™„@Ž„xUVƒIUlmVXXƒxm@™JUUk@WUk@ƒakx±@¯x¯Umb™KUUVmUU¯UmVVn™WkÆ„lWb„„„ŽUnWVU¦k@WaÛV@LV`UxšXllU„@„@VVbnVlL@J"],encodeOffsets:[[126754,42992]]}},{type:"Feature",id:"2114",properties:{name:"葫芦岛市",cp:[120.1575,40.578],childNum:4},geometry:{type:"Polygon",coordinates:["@@ll°X„ŽnV‚@XLVb@VVbnb@VšLVV@VVnXxlKnU‚l„_na@mlI„šmJnxlLša„xVbU„VV„UVU„KVlnnV@lmXLšÈWŽkxVV²bVLšm@Ula@UX˜@XW@UWaUUUUVan@V‚š@lUXxlIX„V@‚yXLšw‚ŽXXW°nblJnan@Vzš`l²nVVVl@„nUaVKšbVKnXVaUaVUšyšnXK@kVK‚@X@m@m‚LXa„LWƒU¯„w@™ƒa@UVw„¥°™ó¯¯y¯ƒUǯ»›w¯Iƒm—¯Ç™UUl™¯»ţKċÑţķm¯w@mU_ómk¼VnU`±IkbVlƒnnŽU¼±Lk`@X™Wl¦UbmVUxkXVlkbllU„Vb@bkVmx@XVV@Jb±aULkKWXkWmX¯aUJmIkVm@ƒxU@n„"],encodeOffsets:[[122097,41575]]}},{type:"Feature",id:"2109",properties:{name:"阜新市",cp:[122.0032,42.2699],childNum:4},geometry:{type:"Polygon",coordinates:["@@šXnb°lš„VlnXVJ„LlVnl@zÆxnK@b„blKVLn@@V„aVLVK@L@Vl@XVVInVVKVwlUXwlKšL„ššVVb@aV@X„lUXbVW@n„lWnXKV@@V@XUVVLUVV@@bVVV@@ln@VbVUXV‚I„xVanJ@UšIVWšL@UV@@¤V@nInw˜W„k„lnIVx‚lnzUVÇJ¦VVÜLĸUnW@aV_šWĊXXa‚Knkl@nm™L™a@alUVw²K@UlmnIlJ„w„aVU™kmK@wÅKmU@DzVmVaÝwkƒKƒaÛ¯șĉķ¥ğ¥ƒ@kUWkƏī݃ƒ@@akU„K@KWIUm¯nƒU¯JmwUVmIkJÇLm@™UImJUU@aW@U@@nUb™JƒaƒbXVWn@UVmX@V@b„š@l@Lƒ@™lUb@x™nÇaƒbk@@xVJU¦lbXšƒÒ@nUJ@Vmb"],encodeOffsets:[[123919,43262]]}},{type:"Feature",id:"2107",properties:{name:"锦州市",cp:[121.6626,41.4294],childNum:5},geometry:{type:"Polygon",coordinates:["@@nJ@nlmVnXKl@@°n@@¦‚V„bVbUlVL²l°@ƲÈV@LV‚knVb„VVnnWVU‚@XmWU„a„bšIVa@mV@X@@bVVnIVJ@š‚nÈKlInJVUnx°I„V°mVnXJ@LƒLlV@b„@ބƐĬXllV„@Ġ¦ĸ¦naWW@In@manK@UVkXJ@alk@»lU@ƒÅLUWl_@ša²£‚Kkm@kƒwVmULmƒ@akIUa@U@WUUVU™aÝ@ğ›wkƒƒmĉ£UWƒ@@bÇL@m—a@_mKƒlƒXUwKƒLţÓ@UWw@K@U„I@m™U@UV¥„@°UnJ°@@_™KUwƒW@UnaWUmmI@m™ķwUaÇLóVĵwݙUUW™¯šƒ¦Ux@V„b@šƒxV°X„ƒKWbK@n@nW‚@UL@lWL™m™zUVVbUbmWXXWJ—b˜n@Vkl@LlVUn@xnV@bln"],encodeOffsets:[[123694,42391]]}},{type:"Feature",id:"2103",properties:{name:"鞍山市",cp:[123.0798,40.6055],childNum:4},geometry:{type:"Polygon",coordinates:["@@l„œxĠŽÞ@šbV@@w°Vna‚@Uk„V@K@UUUVa@K@w@UnKmUVan@@Uma@UXWƒWK@IUK@amW_XKVLlKna@kmKVak@VU„@VmšU@anIÆan@‚a„šUVnb@blLV`ÞLlU„bna‚Kn@naVU@¥°IVK@anUUKVaƒUVak™@mJƒkXƒ™UVwkƒVUUa°U@Wƒ@WlkXWlIXUlJlaœx‚IVVXLšll@nLV@lLXl„KĊzš¥maUƒlkXaVK„X°y„Ila@aVkala@a@¥„IUy@WmXaƒ¯kU@U@mmUƒƒULkmm@ƒ¯VmnLVU@a™ƒ@U@±w@™VWIkymLUUkJWXƒJkUmxk@™xUI¯`mUULmƒ¯„m@kxVVbWV@„UVƒIUx@bkšVšVVšxUbVV@V@zšJVXU‚lnk@@lkLƒlƒLUU±Jkšm@UIUVƒLUVU@™K@UƒnnV@l@Ll„ƒaUJ@zn`@nWlƒIUVUUUV±Ln‚@nmL@VUVkLVlUxVLVlÅXma™@@akLmWUX@JUnVJVkXJ@X@`WX„VUVUIlb„W@bVUVL@`Un@¦U`@bUV@z@Jm@@XV`„LUL¯J@IVKmKÅI@J™nWVnLnšVxV¤™z@bmV@VUV@bUL"],encodeOffsets:[[125123,42447]]}},{type:"Feature",id:"2105",properties:{name:"本溪市",cp:[124.1455,41.1987],childNum:3},geometry:{type:"Polygon",coordinates:["@@lb@Vn„lnVVUb@šVJ@nnJ@bmXUx@xVbkbkŽWLUxnl@Ul@„xWx@nUV@¼Ull„knkK@bmbnl‚LVJX@VIVJn_lJVVšXUmnU°VVVUnVVšLna°V°w²@lw„bl@XVl@VVšIn@„wWWnUVk„JVUƒw@šƒ@anaVkš@@lnLlalKnk„mšK@_lKnlĊXVb„VVLV`nL@lUL@„@L@‚VbV@@V@bn@lxn@Vb„alI²mVL@Vl@nVš_VVnJV_‚@nV„K‚V@Xœ‚@b˜kXbl@XblylUUkš™@Xa@UVIlK@UUWVU„Llm@UUUnKWU@K@UXm„XVa@U°KVUUWUk@ašUVKkaWkƒKUknaWa@U—@m@mk@ƒaUJk@@_WKkLmx„l@nUJmIUWlIUaVWVXn@xWLk@@aƒJUI@Uƒ@UVVxm@UVk„mb¯VUU¯JWUƒ@Ån¯aUbÇ@ÇlLmWƒXkbƒƒk@UƒƒIÇVƒUXW™wÇnk@±aU@@bUVUKUXmVƒ@kaUm@k_±l™@XwVa@kVK@U„Wm—VaUmVUUakLUWWnÛKƒVW_—m±V™nƒU¯@Umƒa@Xk@ƒl¯V"],encodeOffsets:[[126552,41839]]}},{type:"Feature",id:"2108",properties:{name:"营口市",cp:[122.4316,40.4297],childNum:4},geometry:{type:"Polygon",coordinates:["@@ĊĖƐn¤„„°Ċ¯ŎWšô„@xXb‚wnKl@nX@VUVƒKmL@VU@Ux݄@Vlb„x„U@VUb@b‚kœ`‚IUlVUn„V@@UV@@JnXlK@bš@nbÆWUkUKVwUklKVU@UnK@mm²KVUVVVU„JXk@mm_@yVI„bkƒ@K@kmU„m@VšLV@VU„KVUVJn@l™²IVV„K„klK@kl@kmVUW™I@y@UUUVa™wUUU™l™@akmmVaUKmIUaƒJk@ƒwkaóIWWÛL@UlmUIU@WW@UnUUm@wmIVK@Kĉ¦™@bWKk@max@bWXkamKƒ@mVkKmxÛaWX@xUlÝnJ"],encodeOffsets:[[124786,41102]]}},{type:"Feature",id:"2110",properties:{name:"辽阳市",cp:[123.4094,41.1383],childNum:5},geometry:{type:"Polygon",coordinates:["@@š`Vz„‚Wn„VUV„L@bVbVJ@IÈbVb@lVLXW‚n„š„x‚LnKVŽšb@„n@Vbn@mƒ„V@šl„IVa„@@WškVV„I@KVLVanJV_VW„UV@nn„JVI‚Vn@na@alLlmkƒVk@»VU@mXwƒwk@@VmkVwXKllaUa@wVwnW@amI@mUI@™VaUUkmmƒ@UkaƒL@ƒUIĉyƒLWkkKU@mKk@™kWKUUJ›wkbkIWVkJWXkl@X„‚@X¯VVbUVl„UxšVW„„lnIš@l‚Ub„VUbVLmV@bUL¯J@¦UVmbm@LmbƒakVÝKU_kK@amaVUƒ™bm@ÅbmJ@b™VUnƒ@UVl@UbnL"],encodeOffsets:[[125562,42194]]}},{type:"Feature",id:"2111",properties:{name:"盘锦市",cp:[121.9482,41.0449],childNum:3},geometry:{type:"Polygon",coordinates:["@@Vbĸx‚š@nnJVnXŽmb@V„XVxšL@`¯@mI¯Vƒ@U¦@VšV@nƒJ@V@LXx@VŤÔ„K‚LVx„W„knL@`˜b@nÈK@a„@VXĊ¤„nVK@aVU@UnU@ašyU£Uwm™mKXUšm@IÆJnLUL@J°IVKƒKU_@Wn@@I@yVU@aV_@¥Vm@_UKUV@aƒXkaVJVUƒUXW@_@WWIUlUIVm@IVW@IU@@VU@mƒUVVkJ›_l@aVa@UƒVƒwka@UރVwV@@UnK„LVU@UmWk@mLxWa@wóƒUVUIÇÆĉ¦¯¦¯xʟJ"],encodeOffsets:[[124392,41822]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/nei_meng_gu_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"1507",properties:{name:"呼伦贝尔市",cp:[120.8057,50.2185],childNum:13},geometry:{type:"Polygon",coordinates:["@@„m@Łkƒ™Žƒklƒôƒ@£kJ°ý™ɅķÑó¤ğLĉÅlÇğŁW¯¯›™ƥóÿlwkţÈéÝƛó™°ÞÅxV¤ĉĖWƒ¯lȭţυ̃ɱÿķƅˋğɱřÝţϙȍƧĊţ@¯kWKUKm¹Å@ķJU@ƧÑƧ„ō¥˹Ɔ@L@„Þ‚VLnš@VōČWJX¦@JŻbU@ţÞmVU@ȁýóbkWWLƒƒÅ™¯UWġkmóƒ±UŹôV¼ƽ¼ƒł̥ĖƽǬʉxĉŽŻȗKΕ̛ʵƨʟÞ˹»Ƨţ»Ǖō˷Ȍ±ȚʊĠUɾɜɨmÜ֞߼˸ƅȂ¯ǖKˢğÈÒǔnƾŎՂ@šĊbôô̐¼ƒ@ĊôĊŽÞĀ™xšĖƧL±ŽœŽ‚Uš°U„°ĬƒČ°ÜƒêɴȂVł°@ƒ„nxŎèƒbȄÞȌ΀ǸlŽ²IlxĊl²ÒmšôĖ™Èl„ĵºm„ÈêVþ„xɛČʉÇĵVmš„ÒƒÈɆôƐŰǀĊ°ÆǬĮƾb„yĊ@ĠšƒXǀċm»ôw°Ûk¥Çm¯ç™kkÇǫţǕéX_ĶWǖīŎaÆĵĸĊ@ȚȘ‚™ĊLĢĉ„VÆĉʊÇĕóaU¥šĉ°mkÅ°ġUĠřk°mƒÑČÿ˜ÛƒWĸ£ʠšÆxÈÞŎÞ»ʈ²ĊÇČalÒ°Ť±ĸz„ŽĊKȲm¤Ŏ@Ò°¼nyȂUźīǖƳÈē°@šÝĶƒ@ƒÈkl¥Ççkxk™›JXÇƒUÅ@˜£k»„óƿīÛ@lÅJl¥óý@¯ƽġƍÅan™ċ™°é¯¹"],encodeOffsets:[[128194,51014]]}},{type:"Feature",id:"1529",properties:{name:"阿拉善盟",cp:[102.019,40.1001],childNum:3},geometry:{type:"Polygon",coordinates:["@@™ƏnǟƨʫšŹɆÿ°¯ÆV²ˢ™żÿ@ÝÆŁȰ¯ȀƳĉó™™@ğkyš¹@īš›ƒwl£Źƒƒ¯Ŧé@™ÇÇxŋĉƩUUŃōL™Ç™ĵóÝnƒóç@™™ó@ġƒƱ„¥ƒç™WUçÆōƒ@é—çťK™çȭVһƽ̻aW¥ȁ£ʵNJǓƲɳޗǔlżÞmĠóĬȂɲȮ@ÈĢŮźÔnĶŻǠšŎȭœгŃċóȭţΗÆƑÞƧÅΫóȘǫɱȁġlÛkÇ°ȁÈnšõl¯ô„ÞɛÝkĢóWĊ„zÇɼʝ@ÇÈķlUČÅÜķnέƒǓKȮŎŎb°ĢǀŌ@ȼôĬmĠğŰōĖƧbЇƧōx@ķó£Ål±ĀƧīXÝġƃêĉK°Ýʇƅ@ΌʉżÅÒϱʈ@˺ƾ֛।࡬ţશóЈèʞUš¤Ґ_޸Ƒʠɽ̦ÝɜL׈ɛϜóȂJϚÈ@ǟͪaÞ»Ȯź"],encodeOffsets:[[107764,42750]]}},{type:"Feature",id:"1525",properties:{name:"锡林郭勒盟",cp:[115.6421,44.176],childNum:12},geometry:{type:"Polygon",coordinates:["@@ʶĬĊIȘƨƨŽ@ĬÛĢșŤĉĬƒĀóšU‚ÈŚÜènŦƐȤȄłϰUƨťƾÑ܆ğɲƜǔÈèʈƲĊƞƒšɆ¯̼V˺Ò˺ȂŤVĢêU܃x„Āˌ˘ƨ„Æ°ѢmÞżU¼ÆlŎ@ĊçŎnÈÒͪŎźƒĸU°lżwUb°°°Vš£ÞlĠĉĊLޏɆnźÞ„n¦ĊaȂīġŃ¯Iĉůl»kƒ„™Çý„¥Ŏ¯ƒén£ġљÝȭxƒÇ™@Åçķ»óƱŎ¥™çWÿmlóa£Çb™yVÅČÇV»ÝU¯™KĉýǕċţnġ¯»ÇōUm»ğƒÑ™wƏbċÇŎċwˋÈÛÿʉÑ°Łkw@óÇ»ĉw™¥VÑŹU™mW»ğğljVÿŤÅźī@ř¯ğnõƐ@ÞÅnŁVljóJƒwĊÑkĕÝw¯nk¥ŏaó¦ĉƒV¦Å`ğуÑÝ@mwn¯m±@óƒÛKˍƏǓ±UšÝ™a¯lƒōšșk„èƒĬގn@ŤġŰk°ċx@œĉ`Ƨĕ°@ţÒĉwmĉ@ƒƒnƒƒa„™¥ķnƒÞĉVóÆókĉŽķ@ÝkƧƧÛaƒ°Ç@ÝÈU˜óbݼ@„ÛÒV°™@V¼ˋL™ÞɅŤŹǠVÞȗŤÇĖŚōbȁƜ"],encodeOffsets:[[113817,44421]]}},{type:"Feature",id:"1506",properties:{name:"鄂尔多斯市",cp:[108.9734,39.2487],childNum:8},geometry:{type:"Polygon",coordinates:["@@ĶL²ĬVłƑkkl@Ȏ™ŘWńÈĬȗ¯™ºlz@ĠššĊôŦô„ÒĠ°kÞܚ™n@¤„UĸèĸbŌÈXŽĸLlÒĢxɲÆ¤ÈÛƾJÈÝ°UšÅĶ»²VW¯ĸJôšbk‚V@ôlbnĊyÈzVôašb@ĸ‚ÞUl°yǬ²Ǭm°ššk„±lbn°@È»˜JX„VŎÑÆJ@k„LšƒÆl²™Ġ²ʊůĊġ‚řóƛÞÅ@m„ƒmLUÿóĉƧ@™»L@„›`ČĸmšȗÑţů±ĉğl¯Ā™wǎƒçƧŤÛI@±ÜĉǓçō°Uwô™ǫůķƳř±bÅ£™ÓÇwnÑó@ȁƽ@™ƒÇƧĢón»ŏĕóĊ¯b„Å™™VȯÅImƒōKU„™LǓ±Ýxċ—ŋ˜V±Āȗ°™„Źl±šÛ@WÒȁŚŹНŚÅèŌô„¼°ȰɞȂVĊ"],encodeOffsets:[[109542,39983]]}},{type:"Feature",id:"1504",properties:{name:"赤峰市",cp:[118.6743,43.2642],childNum:10},geometry:{type:"Polygon",coordinates:["@@ɲŁĢljĊwƾōÞĭ°_ŎŃźȹƒUČÿl»¯ôķVÿǬƽ™ɅġÅÑǫ»̐ʟȣU™¯wVWݍÈġW»Þ¹m݃ɛŎÿŎōͩůV¹›ō™éċ™óŹÅVVĢǩʈ@Ėċ@ķšÛšV°¯xÇÅţ¥™»°Ûô™ĉʟ„¥WýČ¥™w‚灻±mnÅķ¥ˋVƒbUÒġ»ÅxğLƧ™ƒbWĖÅxš¦U°ÝVóŰlô²@š¥ÜÞÛô„V@²±`š¦™„™¯Ý@„ŽÅ„VÒō¼ôš™¤V²ŹĬÇĊƑƒţxƒç¯Lk»ʟlƽýmłÝÆƏ@mö°Ġ@ŚŹĬţÆUĀĠNJĠŽX¼šnźVUҚ¦Ċxȼ@ôlx¯łʊÒÜĀˌÇČxƍČÈƐašx„ÒĠŽn¼ŎVȐ‚¼Ģ°ŤmǖČĊþšLV°ÞŽU¼ċÈUƚzÈa‚¤ôbkŽ‚nXĀšè"],encodeOffsets:[[122232,46328]]}},{type:"Feature",id:"1508",properties:{name:"巴彦淖尔市",cp:[107.5562,41.3196],childNum:7},geometry:{type:"Polygon",coordinates:["@@²@Ζǀݴʶհĸ„˜ƒ¦Ķ™̒Uˌ¼ӾÇƾ¼̨UÞĉ˜Ƨ—éÝ»ƒĕĉ—ƐȍœōǪakó‚ó¯a@™ôţ™aV¯Þ¯°@²él¥ĵğťwōxó¯k±š—Vó@™aóbUÇyĉzmŽkaóŽU@l™aó‚ķIX°±Uĵ¼™Æ¯VÇÞƽIÇÜÅ£ɱŽġwkÑķKWŋÇķaķçƒV@£šmۙlÝğ¯ƒÑťóǿƴȯ°Åł@ÞŻĀˡš±ŽÅU¯°ɅĀ™źƧʬmǠšƐ"],encodeOffsets:[[107764,42750]]}},{type:"Feature",id:"1505",properties:{name:"通辽市",cp:[121.4758,43.9673],childNum:8},geometry:{type:"Polygon",coordinates:["@@ôƲĸ¼Æèš@„ÈȮwƾ»ʠĢ¥VÆ@²¥@»Ŏњ¯ĊJŤ£k»ÆÇX¯̼ōšī°aX£ôƒƾȁź¥„ƒ™aôŤ™ĢL°ƒĸ@Ȯ¼ÈÒʈŚôVXůÆaĠƛÈKƒķšĉôÿ@ğÈĉ™»ÇVn™ĉV›wXĠÝ°šČÿĸwVƒ™¯¯ǵ±™ĉ‚ǫ™ÅÅm»²Ż±ƽIm¥ţÈķ@¯šƧJV»ÞUÝç¯UġºU£ţŽóaÅÅlƒƒ™Ƨī¯K¯Þ݃ğL̑ȍƽ@ōŎōĀƑɜnÞݺX¼ÇĢގUX°xVšʠȤ̏Ǭ¼ÆÒɆĢšŽǫƾUĀóĸ°‚k¼ċĀƑVŹȺōń¯`ÝĮƽŎĉxġNJɱłō¦"],encodeOffsets:[[122097,46379]]}},{type:"Feature",id:"1509",properties:{name:"乌兰察布市",cp:[112.5769,41.77],childNum:11},geometry:{type:"Polygon",coordinates:["@@ʠǠÞĸɲȺƒÒȂƛŎaƙÈĕȘţUÝźǟɆţšÝˌKU»š@U¯ÜÑ@ƒÞ»ôaV—ÞÇÈ@„¯ÜbƨƨÞlĸ@ĊôlôÅĊU„Ýĸmš¦ƒŽ„bm„„„Ċ@n‚ĊxŤÑ@¯‚ƨĖĊ_@›Čwl¯™ƒȭL›Ý„»ƽ¯ķů„Ǔ@ÇǓbċ™ÅÅÆwÿĠÇU£óaƒ¥¯aŎğĠţkw°»¯ůlÝĵkǻݰɱƧǫaóôɱ»Çk¯ŃóƒʇŐŻ›ĉNJŻĢ„Ž¯ÒÈUl°ƒx°n„Ò™Ĭón™Ċğ°ÇŚĉ¦ʵVƒ°°ĬÛżÇJȁńʇʹó˂ƽŎ›Æţ¦"],encodeOffsets:[[112984,43763]]}},{type:"Feature",id:"1522",properties:{name:"兴安盟",cp:[121.3879,46.1426],childNum:6},geometry:{type:"Polygon",coordinates:["@@ÆXnlŎ°@LVLĠþœxĊUȮĊnU„ĠV@żaW¯XIŎġƒ¥Ý@K@w@K@I˺ŻŎ¦ƨƒƨÒŎIÆ@X@VºnX°lŎ@ƾĉˤƒȘǷȘÑÝݚÞbVţĸÿŤxÈĖƐŽêÇKnĸ¥ô@›ķÞUnÒl@UŚaƒīˋƒ¯ÑƧx@±kXřƐƏÛéV™ˋ»lō¯ĉ„ÅÇÓǫޗĖġV@ğ»›°ĵ„ÇÞǓ¼¯m˜ÛÅŃĉĠÇƾb²çƒ™šéż¯VƒƒğÞml»ōÑV痻V¯™¯šĕÆU¯y°k¯¯V»ôDŽѰa@Źk™ġKţšóŽšbƒ„Ź¦ƽȂó„W¤¯b™Ĭ̻ŎW°ÅÈl¼ţ¤ĉI™°ōÒ@¼±¦Å@UŽġ¦ʟŽƽ¼šÞĢÒm¤„êō°ƒ¦Èþƒšl„k¼ĊŰ°JĢńȁĬ„°ƒżn‚ÇbV„ݼ@¼óĸţ¤@°Ånšl"],encodeOffsets:[[122412,48482]]}},{type:"Feature",id:"1502",properties:{name:"包头市",cp:[110.3467,41.4899],childNum:5},geometry:{type:"Polygon",coordinates:["@@źxżĀǔÆǬVȘĀŤ¥œÅƾōôˁʈͳȂŃÈIÜŻ¯ī„¯ōm™¯ɱĖ¯ƒķÒÝIÝ»ÅV™ƒlÅôфġ™ğVmÞnnƒWçkW܁XƝÆwU»Șĕš£ĉÑ𱱚Åk™„ƒK@lÅIō҃UW‚—IǼ¯@m‚kaƒ²™l¯™ǫnǫ±¯zkŽÝVķUô™˜l²ô°ŎwŦxĶĠk¦±ê¯@Ý°U°šbóŤ@š°bôlôǩb›ŎƏȎĊ˜„ĖÞ¼˜ê—ƨÝĊ"],encodeOffsets:[[112017,43465]]}},{type:"Feature",id:"1501", -properties:{name:"呼和浩特市",cp:[111.4124,40.4901],childNum:6},geometry:{type:"Polygon",coordinates:["@@ʶUĊ¥ÈřĠ¯šĉômšīƒÑ¯m„wk¯ÇV°ÑƒżġĊljǓɱţǓ›ƝóX¯ƒɛÒóa@nÝÆôƜŚĉĢʉŰĊҙ¤ȗĖV¼ÅxWƞۂlXXèm„ÝmUnšĠƒĢóÒkƚ„ÆUÞ¼ÞJĸÑ°„ɲĕš°Ŏn"],encodeOffsets:[[114098,42312]]}},{type:"Feature",id:"1503",properties:{name:"乌海市",cp:[106.886,39.4739],childNum:1},geometry:{type:"Polygon",coordinates:["@@Ș°ÇīXњŗ@ȍlkƒlUŁ±īĵKō¼VŽÇôXĸ¯Ž@šťê„°ź„k¤„x™œ@Ĭ"],encodeOffsets:[[109317,40799]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/ning_xia_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"6403",properties:{name:"吴忠市",cp:[106.853,37.3755],childNum:4},geometry:{type:"Polygon",coordinates:["@@nLV‚@šVLšaÞbn@@l˜š@bUVlUV„zVx™¤kÞVèšXnš‚@nm°a@UƒÑ„@VŽXnV@Va„UšŽVKUUU@@U‚@@KVa@U²@‚wXkWnk„±lLnU@UmmVKnIVWnI@UK›@UK@@UVKXkmWLWUXmlkVwUyVa@w„w@aVI„K@aVÈw„KlLVV@LnV„VVnU‚ܲ°WÈIUÆ@nÞ¼‚‚@¦™@UÞUVW@UxUxVn„b„K‚b¯ÞU`VbǬ™V@XXÆVVl°InmnUôƒ°¯‚anam£œWVX‚KXmškôaVU@ƒVak@@wmaƒn@K@UÛUWKXUƒÇƒ@UI™b@alW@akLUKV@@Ukw±Iš›nL@kmwkWmk@JUIƒůVmnnU@m@UƒK„VKlkUwkƒƒnVUKmbkI±š—KƒkmVkKƒb@U@aƒVkUmn™`kIlaUK@UUKmbUIݚUa@mUa@aƒ„m@UUULUK@bmKkbWI@WXwlkXƒWa@k@kKƒLVkkK@L@JUVmzUKlwUUnW˜£XVlKUwVU@aXI@aWaUw@W@_nam@¯‚UkWVkUWaU@nwmJkUVkWVUmUkJ@ImbUaƒ@@WÅ_mJknmak@@mƒXƒaUV@„ƒxUšƒ„@‚ƒ„@VUnkVƒ@Vn@`ULUbWLXVW@kbUJ@XW`@ƒnÅĖWJƒ@—m°@xƒxšbnUa‚w²lƒÞ°xŤIVVULۂWbšbkVVXÆ`UbVL„@kx°LlV@Vœ„WbƒJn@bl¤ULV„°@lmL@ƒƒ£U@@aUwmKULVxUVVx@„™@kU™@mK¯LÇa¯@"],encodeOffsets:[[108124,38605]]}},{type:"Feature",id:"6405",properties:{name:"中卫市",cp:[105.4028,36.9525],childNum:3},geometry:{type:"Polygon",coordinates:["@@°@Èb°KnLš@lVš@@ƒUwVUUwVKnLVx@bV@„¤@„nK@k‚¯UƒVKk£@a‚m„IXa›ƒ@UkU¯Klwƒ@UKVaÅ_UWlU™aXa܁VKUUţJ¯w„ݱkxVbmŽ™a„w@wn¯˜„@XIÆĕ„m‚@X_@WVIlaX@WUXKVaVK@_Um„@lUVm@U„ƒ@„ƒV™„w@ƒVUÛwm@@W@ImKUkU@Ua‚aXƒ@wWaUKkw@UVaUamLU™nk@»±`¯@k—W@Ua™ykbƒI„„@VWJkLWUkJƒwU@ƒn¤mL¯wm@Umƒ²XVWbnV@bmxƒVkxUblLUV@kVWKU¼ƒŽkUƒ@mn@JnV@bUnmJUn@„k‚@XlxšLVVnKlLVV@š@LkKULVbk`WL@lkXW@kVƒ@UÞUlÇX™lkaUbmV¯@@L@šƒV@bkb@xƒlW„—bƒbW@—±@UJ@IU@mVk„VxV@@l„Illœn@Vm@ƒVUbl„@JLmKÛXmVkU›KULU`@LĉwƒKUX„lVUl@Vb„JX¦̼bÞxŎxɜĖĠ„Ŏaô@"],encodeOffsets:[[108124,38605]]}},{type:"Feature",id:"6404",properties:{name:"固原市",cp:[106.1389,35.9363],childNum:6},geometry:{type:"MultiPolygon",coordinates:[["@@Vnn@°xnK‚£„mV@„xlIXVlKXI@Uƒƒ„JlašzVbX@l˜°@²_@¼mlVšnKVbUb@VlxVLXb@xW„bVbV@VlnL@J@Xn@Üx„b„W@nl@nblmnIÆ`@X„@Vbna@aVUUWVkƒ@kbWakbU@VwšW@_l@nmn@@alVlk@UkmVak@@a‚UXaƒL@¯@KVa@axWI@KnkVaVJn_lJ@„X@‚m@nVanUVb@mXLlJ„VWnLla„VVaVX@KXVVkVKlknKVa@aVU@KXb@klJUknUmƒ@K@_UW@alIUamaU¯kJma@IUK@U„@@UW@@aXLVƒVJVaXIƒKlaUkUV@ambUUJkIWJ@wUI™V@JU@UwV@@Um@™nU`@UkUmVUxWUUV@aÅb@aWXkKUUƒUUaWK@wnm@IVU@aXwm@UmVaUalk@anKUwlƒUwlkK@wmaƒUkmmIk@VmkUUbW@UVUnW@kV@xkVmbVnU‚™@UbUV@a›k@kkW@„kLW¤@„nV@VU@W_UV™UU`VLUV@IUVõVULU@UUUJ@wmkUJ@šWI@l@bkKkbVVƒbVbUL@UUJ@Vm@@L@xbVVVLVlVwX@Vb@bmUkbk@@JWIUVÅw@Km@UkWKXxWLÅ@UVUnWK@xkVW„@KULwWVXVWzXVVKVXkV›V@VUbV@U„VV@š@LXxVL@V„b‚Ž„LnKVLVxXVmb@l"],["@@@J@aƒU@LWK¯UUxVVn@Ġ„„LUW@UbUUUa@KUX"]],encodeOffsets:[[[108023,37052]],[[108541,36299]]]}},{type:"Feature",id:"6401",properties:{name:"银川市",cp:[106.3586,38.1775],childNum:4},geometry:{type:"Polygon",coordinates:["@@šUšwVK@UVWÞUšbšw„V@knV˜@@KU_VK@K„ƒn@W_XWlL@Vn@Ċw@Ulaœ@Wanamī@aƒ»ŋó@aÆÅɲÿUaV_°ÝaƒLƒaUmVwVwX@VUVݚ@@¥Ý»@mVÅÇJ¯XÛ±VUmƒUmU@KUUkKƒLÇxUŽ@bƒLUJ@bƒx@xUbVzUxklWnXV‚KnXWlUL@V@ŽVLœ@VL@ŽmJUXmJULnn@VmVkKƒ²mlXWlx±@@VUb@L@@VV@VVUL™ƒVUbU@WmUƒ@„Ò@V¯bmn@VŽƒ„@lVnUšnVWŽXVl@¦VVUn@x‚š@‚XL@¦‚lXxš„Vb"],encodeOffsets:[[108563,39803]]}},{type:"Feature",id:"6402",properties:{name:"石嘴山市",cp:[106.4795,39.0015],childNum:2},geometry:{type:"Polygon",coordinates:["@@U¯ķó±ÇÛ¯™ķmbXb›@kb@Vĉxm@@UkKWXX`m@ƒ„@LULV`@L—@mU@lƒU™x™aÝVUX@VUL™x™VkLWVšš@J„nVLXVlŽUV@zl‚VL@V@b„„n@lU²WVLlLVbUŽVxUx@xǀL˜xôҜk‚K²ŽVa‚U@wXa@W™ÈĉUa@‚bÈk„m@¯"],encodeOffsets:[[109542,39938]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/qing_hai_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"6328",properties:{name:"海西蒙古族藏族自治州",cp:[94.9768,37.1118],childNum:7},geometry:{type:"MultiPolygon",coordinates:[["@@„V£°š@laœXô±źwš™ô@„Ulƒża܍n™Kƒw@U„aƒ™ša²L‚mÈLƚÈxlaUa„wÞmÜbÞUšnJ°a„kôƒ‚ÑkwÝVğwÇ@ÝkkV¯¥@ò„»„nŤ¥XImw@mVwša@Åw™mLkaW—wƒ¥l»kçƒó„»@ƒWÑĉŽğ@ĉ„™‚Ń„UwóřVómĵ»™™Ý@VǕ¯kšÝĊÅk™°ÓUklkU±šI„ÇÞkƒ±@šƽJƒ™@UġIk@W¦™VÑșÓÅnťKULnŽ¯X›ƒ@¯mUÛ@WřmóKknōbƒxÝ@ƒŽU@kw@ÿÇLţšÝUkšmwƒŽk™lċVŚU¦™ŽƒLkUWlÅÑ@aƒ@ÅѱUóġŹ¼ƒÈĉmŻ@@wkw™Kl¯U™ġ@—„lÇU™Ó¯_ƒ‚Waĉ²Åló¼VbknƒKǎÅ@ƧĢō°Ý@ğ„W™ÅxUUm@™‚ÝXۂW„ULUè¯@mbUaƒLƒbUWġxIUJWz™a¯b™y™@ōÈóLU`ÇXUl™UĉV¯n›mÛbǕLklƒUĉVƒšóaġ„ƏbġKţnkbÝmmnÝWȭȃŽÝXţWókUÇl¯U¯‚ġUɅĀ@°¯„„š¯„VÆnmJ@ĊķnóJUbÝXUlVškL@lVxnnmb@¤Vzš`ÞÞŤ@„VnÆJV„°b„UôJkzlŽkl@²óš@ÆÇ°kĖƒšÇbÛU@lmb™XV˜kzƒV™ŽɅĀXˢlń„ĬŹ@›éÅ@ĉńÆ°ğbUšlŽɜ_°‚@xŦ˜škbVbƒKĢ„ŤVŎŽ°@żÈźlĊ„ôKôb@nôxŦ„Æ@ôŽŎL@þÆb@šnnšWˌbÈx‚InaŎxlU@Ѳ±ƒğVUĢƒƨbɲ@Þ¥ôUUķWVô¯ĊWʶnôaŤˁ@£nmnIôŽǪK°xUXô@Ŧa°m‚kXÆÞVŎkĊ°ÞLȄôyVašIlwX°UVwĢÑÜKôw@nV@œm°nmŽn„Ü‚ɞ£VbmŽXnƒ°ÜÒ@xx@V‚b²UlbkxVnšJUnVVĊ°KȚm°nxÇnn¤±¦@ŽUXVV@„lV„„bmVVȁŽVxšÒ™°šIšbźaȃšbVwš@šƒVL„™ƾÑ@ƒŦô¯ĊkôÑ"],["@@„@šƒ„@n„òVœa‚w²bVxšxÜaČVô_ĊJšIVmšL„a°@Ŏ¥XlK@ƒšk„l„KVbUb˜@nUĢn‚aÈ@lmǬ»Ġ¯œn‚mnƒƨVy™Ñǖ™Ġ»ɲInŽ‚@@ÅĢƳ@¯°™ôV„KÈbVIÇ¥¯@Ýó„™@ÑnīWKšƒk™‚k@¥š™¯™Åa™Xƒ±VÅw@±Ġ¯@»™š™n™Wmw@ƒ™@¯ƒVƒUUWçƒKĉ„a±VkkƒV¯w™x@šUJ‚x@bknÇb™mÅ@Uw±U¯¦UŽ™Kmš¯I¯Žť¼ğĊ™@ǃŹÈ¯@Ý»ÇnˡJƒbÛèÇnƒ„ÅK¯„ġĠŹW¼Ålm„@¤n²ƒŽÝb@b„š¯lƒ¯@ƒšÅ¤W„™¼nV@x„„°@Vx„@lbUblbX¼W‚œšÇ²lšUŽ@¼ŽV¦@bÇlVxUbVxÞbVšœbm¦ƒVV„"]],encodeOffsets:[[[100452,39719]],[[91980,35742]]]}},{type:"Feature",id:"6327",properties:{name:"玉树藏族自治州",cp:[93.5925,33.9368],childNum:6},geometry:{type:"Polygon",coordinates:["@@ɆÿĢV°°VÈklVôŤXÞW„ȮÇÞXnmÞnlaŤmĢLƐaĢƒôb„™ĊU„VlkǖKÜaœn°mĊUšVVkÈWV_ôKŎǚ@šz°ašbXyVI‚JĢwVX„a„KVbna°@VçVKXƒÜÞWšn@VVÆwXšĠƒÞ@Ŏ¯ƨġÆ@ȍ„LlmUaô»ÆkĊ±Xb„°`šÔV‚kȘƒĢ@Všk°šLlx@xż@Ċn„Çź»ôĢ²VÆ҄@@bÆÒXklV„KšV¥Æ™ČUšk‚l„nxl™çƒ¥ċç@±m¥ƒwÅJƒ@™™™Vƒ„mÈIléÈa°U¥™™@kÞV‚K²ÑWƒ°w²Ñ‚K²ñšyƐ„ÝšVmw„»kkWĉ—JWUƒVÅwƒL™mÅ@@ƒmw„kn¥Vу»°™°@@»„¯„Lla„JônV‚UůƒU@W¯Umѯ¯k@WykU@¯„wV¥ƒkVwţƒk»šwWǜĉĶçšK„ƒÞ™ÇaĉbƒI™lUƒ@kwƒWƒXUƒ°w™±@UšKn£Wĉ—KWxƒkĕVƒšamwXw™@™„Wmnk@aƒVkƒ™bĉLƒl™Imm„wUÇ‚Wx™nÝJn@¥Æ™kwƒaXƒÜĉ™¯ÅV¯¤mkƒx¯kķܙ²VWôŹVUƒƒ@V£™¥@ƒ°wn@™m@¯@UbUôķŽmn@ÆÛ@ÇýVaUÇĊVƒ@Çlğ—¯xÝŤ™lVÈÈVƒx„ƒ¤Vx™„kK@™@ƒx@„kVƒĖġ¥kIWbXŽŎx@nƒxÅUW`ƒ_—@±ŽUa™LUxƒK¯„WbkVlb—bmŽƒLÛÆWIUwƒWkwÝV@kI›ŽéUb›UUk™V¯Km¯k@Umݐ¯m¯›m—L›Þĉ‚ÛUm™ġ£UxkKm°™Lw›šk@kšƒVm„ƒKVUk›@¯a¯Ģ™móKUU™x™ImlÅn™™ÇbXèVVU„°„@ŽšŽ@„‚xXnmš™ššŽ@¼ğ°@²ÆxU‚„²šWÆb°š™š@¦llš™„XLmĬ@҃šÞô°@ȦUJÇaƒLóU¯š@°ġƴ@Ɓ@mɱJğ¼ǕššÒUzƧ‚m„n›mğ°ǫ¼knÇ@bġmmV—@VaUaƒLƒk™l@„kLW‚ō¦¯@ƒb™KUn™JĉIó`ċUÛb™wUw±ax›bñUmƒƒ@™„ƒ@—bƒaƒbǏÅXm˜„ƒÝ„ÅôVbގ™bl„UšÞVޚ„U‚°„VUxƒ@U„V„@l`™¼nL@Ċ„LW„„¤kXķWġXUVVVķ„UbVb@°kVVxÈa‚@ȦĊbšaźJ„U@Ț„„˜Vœƒlš@XkôaWƒĢ™Þ@laĸUÆb²mÞLĠ™ÞÑôbšÒĊa„JVbm¦"],encodeOffsets:[[93285,37030]]}},{type:"Feature",id:"6326",properties:{name:"果洛藏族自治州",cp:[99.3823,34.0466],childNum:6},geometry:{type:"Polygon",coordinates:["@@ÞVŤ™ÈK@ĀlxV@„Þ@„wŎalmôLšnXÆÜ@nV‚°@œ„°WmVKŦLÆmȚԂҚUX¥l@ĢJVš@„ŽƾI@w™W°™™Ån¥›kÅÝVwôƒÈç„@lÑĊĕša„JnaÆLVw°kny°UnkÆVȍĊll¦„Vƾ@@™nUźƒÈǂIn°X„wÞKô¦VWV£„@£°ókċ±I™™am¯Va™»ČĉV¥°™@m„k„¥l@„Ċm@ašU™mwXƒ@wÆxšmĢ_„`VnÆbšKVw„@@ƒnUVğVmVVöIlŽl@@çÛmƒ£UDŽw°@VUƒ¯»m¯ƒJōĖÅLƒa@»ĉĢ±`U_k`ÇçšóƒkX™lK@ƒakÝރš£WċkÝ™kxƒJݯÅw™xķxmIÅx„@k±J@ýŋš›¤UœkŽmV™°ÅÝxkwmġƒnÝVU„š¦ƒŤlmšóXk¤™UKƒç™@mVkK@klīƒ£mš¯VUbƒW¯¼ċb¯ĵam¼mVX„m@k¤ÇX‚ÇbƒUƒ„¯J¯„¯È@˜™bVXVҙ¤V¼kxݚV„@l‚V—„WxÛ¦Wš¯šmKnlŽkŽ‚šU‚@nƑUĉ„Ý@ǺۄċUĉ¥™UƒÞŏ™z±òL±Ò¯xX„±ÒLÝU@lššV¦¯‚ÇbkêÇJƒnU„šš@š„‚ÆI„xn¦‚‚@²Č脦‚è"],encodeOffsets:[[99709,36130]]}},{type:"Feature",id:"6325",properties:{name:"海南藏族自治州",cp:[100.3711,35.9418],childNum:5},geometry:{type:"Polygon",coordinates:["@@VxƒŽńƒš@ĊĠŽĊXÒ°UƾĕÞm°£nb@‚@LUUW„Ûº@nlÆǬšĠ£ÞV°UXb‚VȂǵ„éƒ@kWanm°@™x„z„K°¯ĠVšƒVƒkw™Lnm°kÞxÆa„¥@‚wnĉƏ@™œ_l›š_VwšmĸèŤÅČU@™˜Wn@ÑmKU™nğƒK@ƒ°¯UÿV£nmšLl™„UƒUÛé±óókkmƒnƒakV@Ç°óÝXƒWəÞťIţxmm™VÛUVȂÓnWyȁĉkƒVš°WnkĊa„¥‚_œK°ÿWna@ƒmU¯wƒlÝIU¤UXó¥ÝLƒx¯WmJÇÈŹ„mV@šƽ@ƒUk¥ĉkċŽÅUml¯Vmz¯lUxÅKmbƒI™bĉĖk҃@Çèó„UxÆޜlm¦šÆ¯ššX@x™Ž@Ž„²ÝlƒÈ™JV²klVl¯ÔlšĉƙްlUǖÞ@ššĶ¼nŽUôôŚ"],encodeOffsets:[[101712,37632]]}},{type:"Feature",id:"6322",properties:{name:"海北藏族自治州",cp:[100.3711,37.9138],childNum:4},geometry:{type:"Polygon",coordinates:["@@ōmġxƽUm±Lǿþġԙ@kxmWƒb¯I¯‚mIUx@bƒbŹVǎƒkĵbƒlĉI¯¥ƒUšm@ƒÆ¯È@šašóšUlƒČ»@w›œ»›wXaƒƒó°ţç݄kUƒaV¥ÅbÝw¯lmnšKlxU„™„ğU¯°ƒLƒyšw¯@mnXb‚l„@ƒêȁǶUWa¯VÝUğ¤ǫ™kÅ@mܹXƒVV@K@ma¯¤ÝnƽĖ¯V@„ƒ¼„ôlèk¼„¦˜xXŽlbnKšÆx@Ž™bUx@nnxWJţ¦ƒmƒ¼ñ@Ž°¦lUÞlÈ@ĠxÞUlxÒó„ƒl¯bmI™ŽÝVÛaÝnƒxVbkbÇwřÇKn±K™b„šƒb@V„xšLmŽÛŽŻbk„ƒVó@™šŹxó²›Wkb™@¯U¤ƒźĊ@lUX„°lÆôU„ƒlLX‚aœV°wšxUb°xÜôÈKVkÈmlwškÈKšwšK™™VUŤĉŎ»„»„Il¥na°LV»²¯Üy@wĢƒ°ĸwlwĢw°±„_lVkš@°ƒbƒÆ¯zƒ‚„š„@l_„@Ģ±lŚVlUaރ„LVƒnKlnȏ°IllČa˜wÞÑ°x„UU™@wƒVkmĠLô»„KÞýôaÞ¥ôĀÞmƁ„™‚mUƒŎV¥Èl°²°a²¥V„@@w„amm@Ñn@Æ£żƒVƒĠ£@W„¯Þƒšl@š»@Uk@"],encodeOffsets:[[105087,37992]]}},{type:"Feature",id:"6323",properties:{name:"黄南藏族自治州",cp:[101.5686,35.1178],childNum:4},geometry:{type:"Polygon",coordinates:["@@ôl²ôÜê„VƒVkš™KmnU¤VĀ¯°@„„LmĠVšnLÈL@alb@al@n°Vš_XmWUÈamaVIn@n‚aV£œóVWƒ™U£°ašxÈ¥@™‚aĊwȹ@óša™ƒğbm@k„w@mƒaÆw@ƒ„In¯mmƒ@UkkWƒÑÅ@@kċÅçVkÝJÅkVykŹl¥@¯š™ĢU܃X¥òý—mmX™ÝÅlmU@£™Wly™XW»Åbƒl@aI›»k@klm@UxUUƒVƒ¼¯Xƒl™aUnķ‚ƒI@x™@¯„ƒK™„ĉUU`óšlČ¯ô@¤ƒÞJ„k°xVŽ„n@ŽmbXŽ¯Ā›L`ƒ¦ĉbml¯X™ŽUŽl„ȂĊXzm‚ȁÔU‚ÜVšUnnŤwŦJɚ݄XÞW¯ô@ÈlU„b„mln"],encodeOffsets:[[103984,36344]]}},{type:"Feature",id:"6321",properties:{name:"海东地区",cp:[102.3706,36.2988],childNum:6},geometry:{type:"Polygon",coordinates:["@@@҄bš¤ÆI°ôU¼š°UŽnnWx™š@b¯L@lUUWbXxWl„ƨnxVUllš„XVŽUŽnL@lȀý²KVnƾ‚ĢwV»ƒ@mÞ£nÆƒÞÑmL™ƒKUaVżĕƒWVk²ƒƒÆÝ@ƒXw°@„ô™@a°wóUUmIk™™aVmÞwmknyƒ¹VÿƧnŏm£X»˜™naV±„Ýw@ašb@aƒm¯„ĉVó¦kÝWKUU@WanU™b@ôǺĉxb@šÇ¦™w¯bV¤„šUX›ôU¤bmm@UJnbÇbXVWn™`¯Umk@@bka@bÇK"],encodeOffsets:[[104108,37030]]}},{type:"Feature",id:"6301",properties:{name:"西宁市",cp:[101.4038,36.8207],childNum:4},geometry:{type:"Polygon",coordinates:["@@@kmKVUƒWk™VkUmwƒƧXkWwXaVV@k°K@aš™XwmmV™¯V»¯óÅJ™£ƒamŽ—X@šċVţÆķç™nUx™`kœ›`@šÅmĊx@Žƒ¦U¦„blVރŤèô¯„„Wbœx›¼œŽ@xċ¼k„™V™ô™bÇ@Å°@„™n„V°¦ĊJ„kĶa„lȍźU„a@aVwnJ°°J„anXlwš@ĢÓ"],encodeOffsets:[[104356,38042]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/shang_hai_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"310230",properties:{name:"崇明县",cp:[121.5637,31.5383],childNum:1},geometry:{type:"Polygon",coordinates:["@@uŏu»GPIV±ÐɃŜ{\\qJmC[W\\t„¾ÕjÕp‡nα|ěÔe`²„ †nZzZ~V|B^IpUbU†{bs\\a\\OvQ’Kªs†Mň£RAhQĤ‹lA`GĂA@ĥWĝO“"],encodeOffsets:[[124908,32105]]}},{type:"Feature",id:"310119",properties:{name:"南汇区",cp:[121.8755,30.954],childNum:1},geometry:{type:"Polygon",coordinates:["@@`y”ĉNǕDwǏ»ƒÖLxCdJ`HB@LBTD@CPFXANC@@PGBKNECCBB@EBFHEDDDSNKAUNBDMNqf[HcDCCcF…@EFGLEBa@ACoCCDDD@LGHD@DJFBBJED@BGAEGGFKIGDBDLBAD@FHBEF@RFDMLE@SGANFFJBANPH@@E@FJjRIACDMDOEKLFD@DbDAJI@AP@BGHFBCBGDCC@DCA@CECGH@FKCEHFJGBFDIHACEDNJDCVFBDCRKRLDLITB@CjNJI^DBCfNVDHDFKHAFGDIICDWBIF@@CFAjFJNJBBHD@CJ@AEFJ@@DH@BFBCPDBMFEQGDIFCNDHIP@HDABFACBJFHEBSZC@DP@@JDBƤ~"],encodeOffsets:[[124854,31907]]}},{type:"Feature",id:"310120",properties:{name:"奉贤区",cp:[121.5747,30.8475],childNum:1},geometry:{type:"Polygon",coordinates:["@@~T~JjZdDbLXDLCB_J@@FHFZJJIAGH@HGR@BENBLID@@LFCDF\\FpDBDb@FAHKFE†@dEDDdC\\GreNMACVMLBTMCCFCEGFAA@DAFDLMHA@OD@BMEWDOC@AS@KGAI_DcKw„ÕísƝ‘åĆctKbMBQ@EGEBEJ@@MBKL@BJB@FIBGKE@ABG@@FMFCPL@AjCD@ZOFCJIDICIlKJHNGJALH@@FPDCTJDGDBNCn"],encodeOffsets:[[124274,31722]]}},{type:"Feature",id:"310115",properties:{name:"浦东新区",cp:[121.6928,31.2561],childNum:1},geometry:{type:"Polygon",coordinates:["@@EN@JJLNHjLJNR^GRYVBNZJRBV@PDvbLNDN@LGNER@nCNQNuT_TIVFV\\Z\\XnDrI|[Ʉś²ÏJUHOƣ}CA@IO@@CYDATGFIEDAEBBAGCO@GJMCEDCJRHEFANOCADAEG@@CI@FE@BDIC@AGIAIMiEEB@DE@AJCXJDCJEHGBELGCUCeMAD]CIJiM@DSAKJKCLQDQACUECDMIFCBDJGECHAEIWCK@GLMCCGEACNKCEJG@MMBMC@@CIJUINT@JAJSTEPZZCP"],encodeOffsets:[[124383,31915]]}},{type:"Feature",id:"310116",properties:{name:"金山区",cp:[121.2657,30.8112],childNum:1},geometry:{type:"Polygon",coordinates:["@@L@BIHFN@@EE@@EFBDGDAADVDD@@EF@CA@IIsRE@GDAF@BF@CV@|FBCHBLCNHAFCADBMDCFZXHILBVEEQA@MWFARJJ@DCX@@TEFBLHAAERE@AJABRPBNK\\BrJ\\VHGND@CNADKDADQjGAGNC@GJ@FCFFHC@JF@@dLBDSFADHVG\\DTEPDDHJALIJkJDJCDIPE@YDCBiK@DONE@EH@BAF@HLJA@EIA@ALKNA@@FIFAFHR@NALadsæąyQY@ƒA±DʼnXUVI^BF@FFF@HBJEDFFGFEBSRkVEXGHFBMFIVW@GAEEFOIAIPKABGWEKFSCQLQBSEIBC\\FdBLRR@JGACFDDEF@AWB@LJJYNABBA@CUEGPaO_AIE@MYMFIGAEFECHSAAKAO\\[JEDB@E@MMA@@AGBKMGDFFCDDFEDFJF@NPBAFLHFH@EDDHBADDC@DDCDHHCDDFDABDAD@FEFOBCJ[D@HEDDNJBDDHABJIBBvGLBJAH"],encodeOffsets:[[123901,31695]]}},{type:"Feature",id:"310118",properties:{name:"青浦区",cp:[121.1751,31.1909],childNum:1},geometry:{type:"Polygon",coordinates:["@@RUNKdOFDJCbRFMLAHPLDN@JGL@@APBWYCKN@TU@SHGCEJIDIJKVIZVNM`iNY@CIE@CA@KBOEGEUFCCSADEIEFCDDDIDDHC@CKIeDCG@IG@DHWFEEGCH@@GO@@O]CNpeEQDBFME[JC]DGF@CKOA@QSB@GB@@GW@@ED@AQIJIAAFE@@DO@CFI@KNG@CDACAFEGKGBEGBDCCAIFCCLIECFI@MBCLDHGNAHSF@DMB@EEKBA@@C]DEICFG@ADBHGFKCDAKKHKD@@FHGAANGEEFCHKCECBCKG@ADKCNE\\[A[I@@mGBDQQEO@BCE@AI[AML@JGACLOAFKEMM@EQKC@CUCBCCBCHEA@FF@@FM@GEAJK@GNF@EXPH@FD@M^@HIADJCFDBER@DK@@DE@CAKFOCCBDHIBCNSB@GFC@GQEEOWFICGDUAEJIDBTAHJHEB@DIF@NE@H|HBDBEH@DKBAHEF@HEEUB@FGFGCCCE@AHOB@NH@PRLVNNFBX@RC€PbAvMtBfH@DJF@ELBFA@EH@HNED@FFB@HLC@CJ@@DJ@PIRf@HE@CFF@GPHD@DKE@FFBEFFD@DEFCA@DD@IjCRFBAHFDKD@HF@@PM@H@BlbDJDBFEF@DLXB@HCD@@IFCBIFEJD@FDC@FBALLF@PAACJERACAJCBD@EL@JD"],encodeOffsets:[[124061,32028]]}},{type:"Feature",id:"310117",properties:{name:"松江区",cp:[121.1984,31.0268],childNum:1},geometry:{type:"Polygon",coordinates:["@@@DLDFRN@FNELPBDKHB@INK\\BBJF@ADP@RFCRHA@nJ@B\\[\\MFLDBCH@DLDADFGLEDFFMHBBGH@EC@GLLLCBLDHEAGBCH@DEFJ^C@DB@LAFFA@CNE@GTMBGHKCAD@NEJFDKJDDJEDBCDHAAFLHFHBEBDDCH@LMJ@DEP@@CF@BEJBJIBRC@@FX@@HA@@HTA@RPBDLE@CHD^\\INFAERCfFMo^D@PP@@HG@HDFFXECGH@@JDHfCLJ@DGDCCCJCCEDJFCFTBDDVEHFPFLAB@NBFCFKFC@CHIACNOHWHCAAFIDD@CDAGEI@ACFMF@R@R_@GQED@EGFEQEDE_IAHKAEXCQUOQCUDEN@ZI\\DDmAMHCICDSOC@EG@BKHIGMIBCGOCSF[CUHCGEBCTKA@cE@@IGDEEEDI@@HMDBHiHCRCBCLMB@DMCGH[UqI[AMLOAAQIB@BQFBFGBAKFE@SW@CDI@QIEBNXB@FRUFKAGJYWDENCCADBBEMGKDGAAD{EU@@DAEE@CB@HQFJt@JDBE@@FC@"],encodeOffsets:[[123933,31687]]}},{type:"Feature",id:"310114",properties:{name:"嘉定区",cp:[121.2437,31.3625],childNum:1},geometry:{type:"Polygon",coordinates:["@@F@LI@IDKJADKIEJICADGACFECCJ@HKCAFOHAJI@aCBEE@ICAEB[GFGCKL@FGEIFADMLCAEJM@ELQECEIG@BE^QKKLQCA@EHBIGQ[GEHOMGGDHKH@JOECFCjCBEFDNCACMBCILGTABDLEEOEIG@GFIMM@CGKFBFCDE@@GEAGEEACIcGaHMFITIHDN[AKF@FS@OA@BK@IHM@KCGOKBENaQIDECcPMLQVFHFB@BFBKLGD@FAJOVGIACQ@A`LPCB@JEF@RU@ANS@@RCL\\HIFpRBFRBBDKLLDADJDGBFDABHBEDNF@DGBBBADKDAHC@\\JJFBDEH[DEFDH\\LX@XLBLbT@DNJLDCEL@VJABJNDHB@HBHYFBAA@GNFB@@AFB@AFABFLFBHFCL@HJBAFBLC@DN@HN"],encodeOffsets:[[124213,32254]]}},{type:"Feature",id:"310113",properties:{name:"宝山区",cp:[121.4346,31.4051],childNum:1},geometry:{type:"Polygon",coordinates:["@@ˆmÖoÖiƒ½[s[YEUJU`SCIEBCCWJY_LIICDWU@@FaBCJIB[ICH[@@CDKEE@MK@@IMCAEBCH@AMFI@SMGEFGB@FK@BHCAIFJNQD@FEBDFMBKGACG@ECWH@@CDDTOEEBGEK@GC@EE@GPHFR\\JHGA@FDBKRLL]RAFH@FJFDKR@FINBFKDCNEBFJEHK@DLEH\\HFADB@JFFDA@bIJGBEPDBGLI@DDEFBDCHDBIJJFCLIBCL@JKJE@ADHDBHJ@HIBBDFHBBAEIJ@BJFAVL¢ˆ"],encodeOffsets:[[124300,32302]]}},{type:"Feature",id:"310112",properties:{name:"闵行区",cp:[121.4992,31.0838],childNum:1},geometry:{type:"Polygon",coordinates:["@@T@@ELE\\BCMJGJSNEbGdHDJFBJAFIEIFCEWG@@gMENSFCVJFAxR~B@IH@AIiI@GE@FGEAFQPDRiV[\\DFSGMHAXHDOMCJCDETBBNVJJI@DD@ANNNH@FILDDMFBDHNDHKL@XDFGLD@EHGFD@DDB@CDDHCDAEAHG@ABOJ@BIaC@CECLKPFNCDCJBiQEIF@@@OGBMIAEEBMTHF@NKEC@QFEGA@EBCKAACHCLJHEFHHB@AFCAIEACIC@HG@KCCDC[ECEED@KC@KJMAAFQ@GHG@BHIJYIGE@EI@A`KDWCaKcCiY}I}S[CYJM@CFDVPRRVWDFžLBBG`JCFRFEFFHC@RF@HQ`Q@E@ENBDJ@HFCB@DCCEJBBGDGXMPBDGJ@DEDELEDMA@DJF@DMZ_jMNYUUJILCJIJDFGH@TSVM@DLXZ"],encodeOffsets:[[124165,32010]]}},{type:"Feature",id:"310110",properties:{name:"杨浦区",cp:[121.528,31.2966],childNum:1},geometry:{type:"Polygon",coordinates:["@@V@CXJDKJZ`XIDDFADJvSRMDM@mFQHM@KCMKMuaOCU@BDAJSX@HKJGD@PNJCJWAGT@R"],encodeOffsets:[[124402,32064]]}},{type:"Feature",id:"310107",properties:{name:"普陀区",cp:[121.3879,31.2602],childNum:1},geometry:{type:"Polygon",coordinates:["@@F@@FHDL@HFFAPFCSDC@@XGFDH@BDLHNACEFA@ERCIMJEDBAGL@@EHAFENHHJ\\ONQBQCIBC[MKACKI@GGGH@I_G@CW@[DMHCDIBMTDHN@JNHEH@FJFPKFACSBKHDJNABDMDECAFiDEDFDIPG@GLHCNH"],encodeOffsets:[[124248,32045]]}},{type:"Feature",id:"310104",properties:{name:"徐汇区",cp:[121.4333,31.1607],childNum:1},geometry:{type:"Polygon",coordinates:["@@RADL\\NCPHFfLJaJ@FWLGMGIK@IFMDOYYFOTSBI@IMSAMSACFIDNDCPWGGBHNET[CU\\QjOCERFBEHF@@HjJBJG@@J"],encodeOffsets:[[124327,31941]]}},{type:"Feature",id:"310105",properties:{name:"长宁区",cp:[121.3852,31.2115],childNum:1},geometry:{type:"Polygon",coordinates:["@@HFFB@HF@DCAELENSJADCNG\\CX@@D`H@JHGHHJ@BINBFUGEDO[MCKQB}AwQEBUIEDMTNF@hH@FXEDFJEJIB"],encodeOffsets:[[124250,31987]]}},{type:"Feature",id:"310108",properties:{name:"闸北区",cp:[121.4511,31.2794],childNum:1},geometry:{type:"Polygon",coordinates:["@@CSG@BQGODUPWTOBQAAFMECKBGEMFKEOHADDJARMR[PGI@TEJBNG@ADBFND@JL@@NFFCL@D\\@DG\\JJADI"],encodeOffsets:[[124385,32068]]}},{type:"Feature",id:"310109",properties:{name:"虹口区",cp:[121.4882,31.2788],childNum:1},geometry:{type:"Polygon",coordinates:["@@bA@E@QHSXBDIMI@OHCLI@GTWBIACQAYIOFGCENBBARSPOXCVHPARH@DT"],encodeOffsets:[[124385,32068]]}},{type:"Feature",id:"310101",properties:{name:"黄浦区",cp:[121.4868,31.219],childNum:1},geometry:{type:"Polygon",coordinates:["@@NEHFLAFDHDPEAMZUHQQ]IMKJG@EPERABHBGRUCCNGV"],encodeOffsets:[[124379,31992]]}},{type:"Feature",id:"310103",properties:{name:"卢湾区",cp:[121.4758,31.2074],childNum:1},geometry:{type:"Polygon",coordinates:["@@VDHQGABAFQFOH@LIiKKHEXI@IbAFZB"],encodeOffsets:[[124385,31974]]}},{type:"Feature",id:"310106",properties:{name:"静安区",cp:[121.4484,31.2286],childNum:1},geometry:{type:"Polygon",coordinates:["@@DLLB\\NPGLFHUDMYABEeKEVMAAJ"],encodeOffsets:[[124343,31979]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/shan_dong_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"3706",properties:{name:"烟台市",cp:[120.7397,37.5128],childNum:9},geometry:{type:"Polygon",coordinates:["@@ŤLšLllVń²è°xżĢĠÆl҄šŤbœ„V¤ĊXnŽlĢVĊ„Òš„È°ĊŰÞè˜L„±@џn»VUźċ²»ÆkôVɆkĊŃ²kŤVVwUUVmUaƒ@KkU@ƒmUmmk@UwUkmW@UVIXa@ƒmw@a™KULƒaƒx@Uk@UbWU@yULmK¯@kXƒVUwm@@JUUknWKUVƒLUbU@™wWykIƒa@w@mUI@ašUVynIWa„k„@@W„bl@@knmƒK@wnIl™°Kna@V¥ğ@ġUķ»™¥@UōJƒX¯¤k@™wmI¯‚k@mwƒak@@šlX@bUJ@VƒbknWxkLkxlŽšLVlkLmŽšb@bU@ƒbU@VbU`Vb@n„L@Žmb—U@˜VnUVmnU@mm™@kIUWVIUK›VkkUJUnmL@VmLUaVWaXamU@™™U@KUUmVƒU—JƒU™VÇwğn™mƒ@mXĉV@l¯xnô"],encodeOffsets:[[122446,38042]]}},{type:"Feature",id:"3713",properties:{name:"临沂市",cp:[118.3118,35.2936],childNum:10},geometry:{type:"Polygon",coordinates:["@@˜bXlƒl@zlV@lXXmŽkbVVlš„U@Vn@@Vmb@XšKšVX„WJ@XXl@„‚ŽÈbVLšUl`„@XXV@VVUxVbUxVbš¦„@‚WnXVJ@bnVUzl@„°Æx„U„KlU@mUUnUlUVWVUnVV@XX°V@Všll@Vk„aXVl@Ux@bmbXLlKlb@b@bUJn@@„„b@n°x°K@an@@UlLVKVbXb@bVVnK°LVa@UVa@™Xw‚KVxnLšU°@naV@UWUkWƒULmV—wÝKUUla@aó_@mƒK@aUU@ƒWUkwVm@aVI°W„@@IUw@a±¯@¥kUVUm@a‚wkw™@ƒK@kVKk@maXalI@alL„WXblaVLVU„V@LnKš@„l@w˜aXašLlnUl„LšmV@n°J@_VmnIVym£UKmI@WnIVm@anUVmÇ_kġIÅWUXÇm@U@ݯÅ@ƒ™@naWƒ™IVW@IkK@klKn@naWIƒmk@ƒaƒbkKkLWn™WkLWmk_ƒ@UaVƒUKmLUw@mn£WwUmU™ƒaóV@UkUm@UKULUwmJUX@WW@XҙzVblJXŽWXk@UVWK—X‚¤UL@xU@ƒ@ƒVUaU@@XmVkLmWkXUyÝLmKXnVŽ@n@l™x@bWLnVVn™`knULmxUl„„WLXŽVb@VƒK@z¯x¯¼Wx™KUn@bk@ƒlƒVVVz"],encodeOffsets:[[120241,36119]]}},{type:"Feature",id:"3707",properties:{name:"潍坊市",cp:[119.0918,36.524],childNum:9},geometry:{type:"Polygon",coordinates:["@@l@@UšK@Ž@L@bX@@VlL@JƒLUVnX@`ÜXn`V²mJ@bU@@n„b@l°xnnĸVƚ°@„ƒĊ£Þ@lWnÑnkʶJmó°w@kk»V@»ƒ¥k@V@kw@wVm„a˜Å„mšaô£ŎƒXI@mln„Kla@mV_UKƒ@kUkw@alW™IU»™mƒ—@WUIl±UUÅU›bkJƒ@a@wUKUaVIÆmXIWaka@m@Ul£XKVw@ƒUIƒJUkmJ™ƒVkU@a„ƒWK—ImVƒ@UxmL@bX`WXU@U`ÇkUak@@°UblXk‚mLUKmL@VULóƒƒVk@@Vlbn@Ub@ċaUJUbƒIUlVLUVVbVKX„VlVXU@mb¯@™VmKUwLWx@šUb@VUb¯KmLUU@aWaUaULkK@Vm@@b¯L¯w@mƒa@ƒm@UUU@U¦lJUXƒVƒmkb@nm„XVWŽkb™IVxUV@VUbWLXVƒLW`Ux@nk@Vn@x@VkJ@œV`mXkŽ@V„xV@lVššI@VULš˜VU„IV`°bVXXx„V@VWVnL@xV„Ub"],encodeOffsets:[[121332,37840]]}},{type:"Feature",id:"3702",properties:{name:"青岛市",cp:[120.4651,36.3373],childNum:6},geometry:{type:"Polygon",coordinates:["@@„@nU˜JXLƒ„@blVU‚š„nIVl„IVJ@„UxWLk¤@V@nlbXbWJÅnUJVbVL@x@b„ŽlIœaÆVVVk²VJ@X„˜šnV¼šJkX@blxlV„@VLU`@nkbƒLkm@nWJō„ó¤™bƒn—ƃbUn@xlxU@l@„¦@¼UŽl¼ĊUnW„@šnĠmÈxšU„V˜I„VnUVV@LšV@šnVWbXb‚UVbnK@UnKVmVIllœUVLUJVXlJš@nnV@nmVUUm@—˜Vna@ƒK@mUaV_UaV@„aV@@a™anlKUk™KklwlKXwlm„a@UVI@akW@™l@„bnxl@°nJšxl@°£„WŎIUÑn»lašmô¹Ŏ¥VaUUkƒmkġWɱIUUŹ`›@kk@ĉƨřV¥_Ç@™Ĭƒ¤ÝL¯m¯£ƽóķwUW±ī¯kōaĉĕ™kğmó°ƒbW@UKkLUaƒVmz@V@ŽUxVn"],encodeOffsets:[[122389,36580]]}},{type:"Feature",id:"3717",properties:{name:"菏泽市",cp:[115.6201,35.2057],childNum:9},geometry:{type:"Polygon",coordinates:["@@@¥šIVUÈmÞ»@UlU@Un@VW@UVmkk@aVUUKVÝ@UVknK@UV@VVnIVƒ@wnƒmwmKXaWaXI@UV@Vy²blkVKkam™U@kb@Um@VmUkmƒKmkXKWwkU@Ulƒ@UnK@UVUUm‚KXwšUVL„w‚K„U„@@Wl@@wUkV¥—@@I@W@_V@VWUw@UUa@aƒaWa—@@_mKUw™l¯amzmV—@WK™nU@kƒWLķaUKbÝVmV@UWÇbÛ@ƒX™°UbW@XŽm„Vlk²UJUbmLÇxÅWUzl‚¯Ll„@VkK™XUbWJ@bU@¯@™ƒkbƒLmKka™„@l™_WšXºVbUz@J‚n²V@¤lX„Ž„nV°šLn`WbXLôVlKVUšxXn˜lXLlU@bVV@„XJWLUVnVV@„„@n‚l„°nn‚V„KÈbVXÆJU°VnXV„kV@@xVL„@šWlb"],encodeOffsets:[[118654,36726]]}},{type:"Feature",id:"3708",properties:{name:"济宁市",cp:[116.8286,35.3375],childNum:11},geometry:{type:"Polygon",coordinates:["@@nam_nKlVLXa„Il`š_@KVVXI@m@w‚ƒ„@@k@Kšnô@n`VbV@@L„L@KVVn@VX@‚VL„Jl„š@VUUƒU@Uam@Uk„wšKWaXamkJmIUVUÈblašUnV@kVKl@@lXL°kVJ@VÈnVJUX@V‚LXl@xVLnU‚@VK„V@a„IUaV@„bĊU„x„K‚kVJXUlV„ƒ„UVašI@WUI@KlUnw„mWk@WXIWƒ™U™L@Wna@Um@@UƒVk™UUlanWW@kkU@y„kWk—aWVUlÝbUU@kƒJUIU@@ƒ™JmaókƒLKǃUUkKWLk@WbkUUaƒbmKn¯°¥V@XwV@VanaVaU_@Wlk@WÈ@VUÈVVۂm„aklKȯlLVUX@lK@aX@@kV@VmV@VwnJV_UWUwƒX™am@kW@wVUkKVIUUVmU@UV@IVK@aUL@aƒV@Lm„UKmx@ŽômLkUWJ@šnXmlUxUL@Vkn›VUšU„@V™L™`Ub±LkV@kUKÇbÛ@ƒU™Wó_mJƒ@Wk@@Xƒ@ƒVLƒxUK™VWxLVnUV@VmL@Vk„@VlVXxWLnl‚Ln„VlUnn@@VlaV@nšlbULkl±aUzU@@VWJXbWbnLnxm„@xU„mJUUU@@VmLUl@VUÞVLUV@bllUn@VUXm@@VkV@VݼÇnUV™J@¦nnƒlnVlL@„Þb°KVV"],encodeOffsets:[[118834,36844]]}},{type:"Feature",id:"3714",properties:{name:"德州市",cp:[116.6858,37.2107],childNum:11},geometry:{type:"Polygon",coordinates:["@@„¤@VmbVXnVVbVJššX@Žll@z„lVInl@„@bVxUbĠ‚l@Èbla„IšxXVWb@L™@n‚ULWVXXšWWLnL@`@LUVVL@lVn„JšU@UUk‚a„™nš‚Vôô„b°¼V‚ސXš˜‚œIÜbČa˜bôW„XÞWÈzÆmnLVJ°ÈnlV²lbnW@™@UƒUV™šmnwmkkKWƒkla@mVIUKUa™aUwmn™JU@@amIk@@bVlkX@mmUklUUƒƒa@_UaUUƒV@wƒw™WkXmW@I@WUaÝU@UXaWUU@UUVW@UUUWUn¥nUVa@m@k@alU@wk™LWa@UUm@@wnmU™wla@anKn_@alK@ݙ_ƒ@@WUUUmlkaƒIƒyU@UwU_Wa¯yU_mWUwkImm@InWWUk@@UVWV—kW¯U@VƒL@b¯b@l±¦@šVV@lUbV„@škxVnUšl¼XV@b@lV@nIWxnbƒ‚™@UU™LƒxÅxm¯ƒaUƒ™wU@mUÅVÝKULm@bmKUXó@"],encodeOffsets:[[118542,37801]]}},{type:"Feature",id:"3716",properties:{name:"滨州市",cp:[117.8174,37.4963],childNum:7},geometry:{type:"Polygon",coordinates:["@@Vb@`„bV„kVlnV@nlWUk@al@nJ@bV@šInmVxšbVbVLUJ@nkb‚lX„lLnlmx™nUš„V@V@šmXn˜lbĸ@nnVx‚b@lnXV@UJ@nVxšxnxVbÆVn¯ƒĕ‚@@wÈçUÇlķVIœb‚@„Çmk@¥k@UkUK@aWakUóJW_UW@wkkWK@U@Kš@XUƒƒUkmUUalKXala@U@kkWlkÈl@kšV„mVIVmU_‚a„ƒƒwnwVW@wƒwUƒ@wU£ƒwkJWIyUI±bk‚VUJ@nmV™Ukl„Xmx@lnbW„kVƒUkLWŽƒxkKUUmUkb™J±—LÇxUKmkUmkkW™™a„mUaVkšJÆ_²KĠ@U„W@w„U‚¥nUWwK@aÝUkÅVaVK@akLWƒƒƒ¯I@bnbVx¯JW„ñšWbUL@šƒŽnV@VmbkUUV@IÇak@@bWak@WJUœJWL@bXV@„‚@„V„Jlb@zUlUŽUImšnbV‚mz@°UV@V™bV@@V@L@xLmKUnmJVX„J@VkLW@UVUL@b"],encodeOffsets:[[120083,38442]]}},{type:"Feature",id:"3715",properties:{name:"聊城市",cp:[115.9167,36.4032],childNum:8},geometry:{type:"Polygon",coordinates:["@@ô@VWnL‚an@VKÞLÆUnVV@šxV„„bn°Æw„wšKVVš@„maXwmJU@@k@aWUk»V™Umlw@™UƒVa@kUU@™²¥@k°a@a„K@U›ƒU@mmm@ów—ѱ¥¯@@w™Kmw—I›¥kU¯UmakJmIUaƒVkKUkm@VUUa™Uƒ@UaƒKUK¯@™w™UVŽUIUKVw™k™¥™wƒbVŽ@xn„@lWnXxlL@`„XlJX¦l°XxW¦@¦Ul™n@Ž™@@Um@@VXVmx@¯bllUnUJ@VULVn@b„xV‚VL@b„„VlnVVblV„ÈnVlIVJœLô„lJ@xl²„"],encodeOffsets:[[118542,37801]]}},{type:"Feature",id:"3705",properties:{name:"东营市",cp:[118.7073,37.5513],childNum:5},geometry:{type:"Polygon",coordinates:["@@ͬUǪlô@°Uœw°ōĠ¯š»Ģ炻XÇ@w™wƑa™ÇƒkwVƑ¯@řķUmm¯w@kƒa@mV@@anIU±m_ÛW@_mWVU„K@IkK@UW@@a@K@™L@Vk@±U@UV@lm@mUU@kLm„„xV¤@xV„„x@xUXmx„xƒ„bV`UnUJƒn™U@lÇkkllX@l@VkbWbkLVbnVVl„„WV™@@L@VXLll@xVXX`ôIlVXb@bVLVll@@¦nlƒÈ@›aUJkĸVÈÇè@x"],encodeOffsets:[[121005,39066]]}},{type:"Feature",id:"3701",properties:{name:"济南市",cp:[117.1582,36.8701],childNum:5},geometry:{type:"Polygon",coordinates:["@@²¦˜Òôxn@nn‚@V‚œ„°VlXU˜UX@Vl@XVmX@JnnlJVxnXV`°zXbV`VxV@„z„JlbkŽVnVV@X„@š`@ÞkL@bm`mL@bkbšxnVm@xn@VV‚@XbšKl@xkV@b@l@nUbmVm¦XVVV@VUXVVV@XVWb@VÞVVb@X@JnXlWšX„x@x„UVV@aVKVUX@lK@UƒIUWnIVmnL‚K@w@K@UU@ša@UVU@¯nyUman™VJVVk@ykaƒIƒU@@ƒWU@aXK‚IV›XIl@Xb@al@Èb@JVUlVna@UmU„@™VKXaò™Xƒ°IUwma@aU@UU@wVW@фw@a™I±`kbƒUkw™UmJ@UkmÇUUkmKknUVƒ@mJUkaWkƒa@KmKkUƒLmyXa¯_@WmImmbƒLmUkVUbUVƒJ™bƒUkkWJkUƒl™IUm™k™Lƒ›„lK@knaVmkI@mWaƒLUK™UU@@VmLUVLWK@UUUƒWUkkVmx@„Vl™¦"],encodeOffsets:[[119014,37041]]}},{type:"Feature",id:"3709",properties:{name:"泰安市",cp:[117.0264,36.0516],childNum:5},geometry:{type:"Polygon",coordinates:["@@n¼šŽW„nxšL@x°@š¥Uk@ƒnwlUVl„XVV@VXL‚KVUnK@UV@šVVL„KXb@nlJUnmb@lkLƒ‚„œšKšlVnšJ„klVXIll„Vša„IVUValUnV„K‚annnJ@X°`Wbnz„KlVnL‚Ž@L„bXl‚bVlnI„@VUU@UmVƒ@U@Uš¥@VmV@@_Ua@m°@@ƒ„kmUUm@UVmn@nX‚@@a„anJVUVL„mlIVJn@nkVLVa@KVmVLXVVLš@@U°bn@VaV@@K@aVkœbWaXUVymU@aUImWXƒ@™¥UaVwUaVwUUU@WWƒ@k_™VUKÇa@ƒƒnmxkV@LVJ@X™JUbƒVƒ„kUWVUIlƒLƒwĉVƒaU@VbƒJ@bƒUUL@mVUK@wWkK@UVWUIÇm@UUI¯lWK@kk@UL@lmU™VkbÇaUVVnJlIn‚WbXb™LƒxVln@VbV@V„UV™@kƒƒIUK@UWm@UU@LƒK@KU@Uam_ó@™m@L@lƒ@„@x@nWJUU@L™`k_ƒJWbUKkmLn`mb"],encodeOffsets:[[118834,36844]]}},{type:"Feature",id:"3710",properties:{name:"威海市",cp:[121.9482,37.1393],childNum:4},geometry:{type:"Polygon",coordinates:["@@VbUnVVUxĊ¼š¼ô@Þф¯‚WǬLŎUÆW„¹Uǃō¯ÑƒÝkţ™™ţóġ™óL™ł̥U™wm¥kÝmkkKóbÝ@U¦@‚mb¯LkšmJ@x„Lmn@lk@ƒa@Xƒ@ƒlXbmJUz™V@bVJ@n@x„blJXzšxV@Va„KVUXLlmVV@In@Vx„UlW°@nLVK@zXVVal@@V„w„bVKšL@bnx@„WbUJ@VnXVlVxl@nnnV@„lV@L„‚"],encodeOffsets:[[124842,38312]]}},{type:"Feature",id:"3711",properties:{name:"日照市",cp:[119.2786,35.5023],childNum:3},geometry:{type:"Polygon",coordinates:["@@UaVUUKVk„JVaVIČb@Vam@ka@Ul@„Uô„VK@UnKVLnKlkWVa@¯l@VbÈlV_V@XWW_@anKVwUmVw@@Uny„UVblKVLX@„aô¯ó¥mÛĊÿÈ¥š™Þ¹lUīƒ¯Kĉ¼ʟbÇV™U™ŽUŽ™XmakJUnmV@bUnmJ@XnJVLn¤UzmJUn@`¯ImŽU@™nƒKVkkm™KWb—b@xƒk™@mL@KƒUUVUKkbWaƒXkK@bkJWbnbl@UL@l„Lš@lxx@b‚nUVlV@¦²°@bVx@Jƒ@¯XUJ@bUnlxVŽ„X@‚VV@b„L@nô`@bkbVVÞL˜xnU"],encodeOffsets:[[121883,36895]]}},{type:"Feature",id:"3703",properties:{name:"淄博市",cp:[118.0371,36.6064],childNum:4},geometry:{type:"Polygon",coordinates:["@@nƒlKV@nVn@@kVU‚@²VVaUƒ@wmKXU@UƒUWwUW¯aU_ƒJUV™—VK@U™JU™@kUƒw@UlnWU_@›lI@U@wUml@@mVwX_„KWUXKVa@UVUUwšJlaXWUnƒ@mla„n„UVWkIV¥V@VVVI@a@akakLWKna@aVwk@WUƒbUlk@™k@U¯UWWU@mUUVUXkVmVVV@nkVƒLƒVÅwƒ¯k@WVXb›aUl@bV@@b@xkVVXVxkJ@nk@@ŽVLUlVb‚VXUVVUzV‚™LVbUbV„VWVkLmškJ@n±@UxU„VVkV@bƒx@ÒUX@xVVV@°J„„X„lK@bULUblÆÞV@b‚LXxmV¦ƒV@xƒXVŽğ@±LÅ`™IUlVbƒnšbXšllVnnlVLÈw˜K²ŽšIlanVVVlL„wXlK„VlUXƒma@knwƒWlkšVnU@mVIUl²aVJ‚zXJlI"],encodeOffsets:[[121129,37891]]}},{type:"Feature",id:"3704",properties:{name:"枣庄市",cp:[117.323,34.8926],childNum:2},geometry:{type:"Polygon",coordinates:["@@‚yUU„U„kl@@aVmšLXw°»°w@y„L@UUaWXKƒƒVknwVKlmš_UmmUXK@ašw@k@mUWmUL@ƒ@™@£@KƒbÝV@akw™aULmƒƒbUK™LUU@lm@—°mL@nUJVxVXU`mIUxU@UnU@@lW@@bkLW@UVkKÇ°kLlŽƒbnUÜÇUUVÇ@@Xkl@XV`UbmbUbU@WxU@¯¦m°nL„aVblVXal@XKlLVVȄ‚L„KôlnbšI@„V@VJ„I@lVVÞaVkXU"],encodeOffsets:[[120241,36119]]}},{type:"Feature",id:"3712",properties:{name:"莱芜市",cp:[117.6526,36.2714],childNum:1},geometry:{type:"Polygon",coordinates:["@@lmnLVlÈVln@VnIšVlx„Vla²_šJlUUUVƒVw²@@mlIn™lKXU‚UUƒVaUašKUVyUUWVUUaVkUK@l@@mlIUwUWlU@w@aU@@LU@Ubm@¯a@V™@UKWUUKUn@LUbUKmlm@UIkJƒnUKUVmIƒb@b@mWm@Un@VVnnVƒl@„¯@@nVb@`U@Un@Ž™¦@V@VU„VnV@"],encodeOffsets:[[120173,37334]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/shan_xi_1_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"6108",properties:{name:"榆林市",cp:[109.8743,38.205],childNum:12},geometry:{type:"Polygon",coordinates:["@@™ýVƒnIW»ƒW@»kUÇL—݃U¯¥ÇIUWWїUWwX¯mƒ@»n@ÜÈķô™@a±kȱƒw„ÑmwçċmU»ÆkkVyIm™ĉÿ@ƒÝ¹ƒWnwÇVš™Åaƒzmmĉ¦ó™kVmx™xU¼VškVm_UlVlk„°IV‚kmJa›¦k™™LmmV@XmKnšlUô›VXbƒbƒ@UaÇLğܙ™Åwƒ£mKnmċwÅ@UkƒbmaVƒƒƒn@m¯aU™Jm_k˜@kWXyl@@kÅamw™LU™Þ™ƒ™mWÅzUKƒš™Uk±@™b@nnK‚bX¤mzVšŽVxÇn„‚¯„@ÒknWƒƒVUbkķÈÑWkk@Va™™U@„mUkbƒÝÅ@Ý¥ÇbkĬ™XV`kLǍVmalUUa™nV±nwmkƒJ@Inƒ°KVw¯UnÅ@¥™ƒ™U±bUU˜±œmWbÛKWnUm`UƒVK@bmnœm‚Èż@V„L@xƒxmš„Ť°nŽ@VmK™²VlšlKk„ô@„êÜV@VXLlmš¦UššV°Ș¯²ÿ@¥š@ƁĊ˜²IšmĶnnb°b„KVƒĸLl„Þ@UȮš™Ü°IVƒÞÝސlŽœx@ŽķĀWŽ„Ux„èƐ@š°ŽXnšlĊĖ°m„nƒšV„²V°ÒƦ„aބ„˜@zll@bÞĀšlš¼nKĊ¼óȂb²±šIǪÒ¯ĖV@„lxnVlk„JlaXwŌĉ„„@VnŽššlÆĕ„UÆLœèŌŤôxȚlUœ@šxlaUċĕXm„IWmnkšVVƒ„VW_@aÈWUUmk@ƒ¯çVm»™±W¯n¥V™mkXw±ÇVwƒ"],encodeOffsets:[[113592,39645]]}},{type:"Feature",id:"6106",properties:{name:"延安市",cp:[109.1052,36.4252],childNum:13},geometry:{type:"Polygon",coordinates:["@@@kkÇmIšmUwVkUƒƒU²WmšVkm@m`mIĢĕUƒVa@™mXƒƒÿVVkyUýšĕ@l_UmnƒW„KVkţ™™¥™aƒwğ@™@aôƒ„ƒWa„kUmƒa¯¯™a±£kx™mmxUwÝ@xmU™b¯K™wó„Ý@kmm¹Ub@lklVbmnnVUV@x›UknƧJUX@ŽƒLÇWkw™LķƧÅwWJk„ƒLkþĉxWz™JUnǚkš@Ɛk¼ÜÔÈKšè@°lșÆk¦l„n@l¼@l¯L™°UU™VÇ°ƒ¹—`m¼mXk‚™bUaƒV@U¯x@¦™Ç™„UUmlmUVm„nnmlkw™@@šƒ¦Å‚ÇLmx¯Iklš„@¦mÆ°VUx¯Lm„@J„InlmxU²šmVbkV‚bUnȎlKU_šWlīÈaÞ¦Æ@„ÞlanV@ƒšVšUbl@XlÇÒĸlŽVa„UX„lm@Ñ°ƒƒÈmUw‚U™nyW£amL@mša²@lšV„™VLÆynX„šÝšVššKnxÆb@lk@WzXŽ@ll—n`šIV‚°b@n„m„„‚Unb„aVlÆ@ČxmnnL„¤ÆxššĠÛÈKVb„@„aWaœU‚ókVm™nL@W‚UnnšKlšœ¥‚bnIlU¯JlƒUkVkn`lUU™V»šwnwlUôšĊ¥nn„yÆb"],encodeOffsets:[[113074,37862]]}},{type:"Feature",id:"6107",properties:{name:"汉中市",cp:[106.886,33.0139],childNum:11},geometry:{type:"Polygon",coordinates:["@@lKnb@n„lWb°bkxĸwVb@ł„nlŽ„ƒĊ¥šL@XŽl™ÈƒVblÈK‚b„akVwôml²`‚nœ@‚nVKœl˜k²xŎƒ°¦VU„JĊw@çnWçރVkUóÛ@¥kwš™šUmƒX¯WšÑkƒ@UymIUwlUn¥‚mUk²a°¯V»@™ÝVș„ÝċÅÅVl»@l@a°±@_kammÅb™a@ƒƒm@ż™KknõĠ—@mšƒ„¯LÅw›‚—LVxmb@¼kV™@mw¯wVakKW»X±¼¯Vkxƒb„¼WŽ@nx@x±bóakbƒ@ÝmU™@ķÓÛL™kƒVUm™k¯¤ÝLUlÝ@Ýz™š„x@x™°™™™bƒmƒX¯aUJW¯—k@bÇWƒwÛwWxƒ@XWlb@Žƒ„VŽÈUlwšLnl°VlUô¦œU°¤VšUxVXUxlbkVVlƒI„°„ÅVlU°m@k„ÇU¯xUlƒLUlVL@b™°ĠInĠ°ÈnK‚„@xÞa²n‚aUyšXUKVkšWô¼Èa‚z°JXUVÇV_„JVƒšz@Žnb"],encodeOffsets:[[109137,34392]]}},{type:"Feature",id:"6109",properties:{name:"安康市",cp:[109.1162,32.7722],childNum:10},geometry:{type:"Polygon",coordinates:["@@„bĊaƨèšwôô„¼šb°ašXVƒÞVUÞ@‚aXƒm¥kImx¯¯ƒV@anU@UÇéğL@ƒ¯¥V£mƒ@ÝÈb„K‚™„X°wČÿ˜ƒ„b@xÈblxȯĊ„„mÆUVƒ„nÈ@ƨÜLĢ¥ƒŹnƒ°Vnn˜K„aô_ȃšwU‚aXmnW‚¯kl›LXƒÇ™ō¦ÝaÅVmbğUn¥±wÅéVƒan¥ƒ„U„»°am¥„£ƒÝ@ƒ„wVw™¥nU„уUmmVwmķIÅaóVWxkblb@ból@œğÒĉ¤ċXƒ˜¯X™xk„Ç@óÆÅx@š™xķ_kmݎǣkblb@`¯²@bk‚‚@k¼ÆUČƃÞǚÞU@šU¼¯°±bVlnm¦kVVxnJVz@‚l„™ÒXW°n„™V™šlx@¦ôÜVUl݄Xèm@è"],encodeOffsets:[[110644,34521]]}},{type:"Feature",id:"6110",properties:{name:"商洛市",cp:[109.8083,33.761],childNum:7},geometry:{type:"Polygon",coordinates:["@@²nl‚ôbš„°aVwnKÞIš`°wšXôw°VĊ°@ŽÅš„ÞÆV„zÞK@xšŽ@a‚LŚ@b@ŽnLlƒ@šln„mnLVw„a„bVƒ‚VnbU¼„Vƒ°„bl„šbÈ@ĶŦb˜@nÇ@amIyUI@ĠVmôƒU™ƒVwkwlanJ„¯lwó¥@an°Jš_„‚@š™nóƒó@£l¥UwmašÑ@ƒUm±V_ƒJ—£›J—UW¥¯@ƒ_k¯¼mUƒVUè¯b@wmL™»ğVmağI¯¤ċIUW™XƒKĵ¦ķaƒJUb™IƒlUóVmk@WÅÅÇ@ƒmU„ÅVƒnĉƒÇ°kwÇa@wƒa—„ċĀ¯xƒWšƒLÇa@Þn„U¤°¦@„ĠKÈê@VmV@b„U°°nwlJn¦W„bÝ@VŽ"],encodeOffsets:[[111454,34628]]}},{type:"Feature",id:"6103",properties:{name:"宝鸡市",cp:[107.1826,34.3433],childNum:10},geometry:{type:"Polygon",coordinates:["@@@ƒ„£@›°Išb@¯°ynŹƒaUƒlƒU£„Umšĵĉ@@ylUÞ@@£kWU¯WaU£¯ÇV¥ƒ@kb¯wƒn™¥ÇkUÇnUƒ@¯±›kULm›@m±_kŽónUxlŽƒbaÇLkŽUaDŽkšW@™Kĉ¦ƒ„kƒm@ŁUaķxlw¯aXaƒk@mmakL@šmšÛŽ@¼m„@l„XV`ƒn™KUš°°@²š¤UÈ@VxmôƒxKl„VV²aVw„Xla„Vlx@UVnŽÇnk°ƒVVL™lkI™šƒJÇk¯V@šknƘn@lznmlVkzVŽ„VVxš@Ux„z@x±¼VxxU„l‚kb˜@„¼Čk˜VXlĠkôV²w‚LUKlwœJ@a‚IV¥Þƒn¯Ün„‚„@nk˜l²kÆ@š°„aVbnI@™š‚Ťn"],encodeOffsets:[[110408,35815]]}},{type:"Feature",id:"6105",properties:{name:"渭南市",cp:[109.7864,35.0299],childNum:11},geometry:{type:"Polygon",coordinates:["@@@ÈôL„xUŽ°„Þ@mŽÈnl¤nUôL‚wX`@ÞÝL™ŽUšmLô„„ŽôbVbnºlnÞ@ôƒšx°LšanV‚wÞ@Vxnwšnlw²¤šb°°„bVnƒlXbƒ„ó„@bš‚Ġ@„xšbš¦ŤšV™Xġ„£W¥ƽɽƒó@ýóƝÝ»„£X™mƅšĊkUƒ„@™™šó„kťaĵŽÇ@™akƒƒa„¯ƒUV»maUU„ƒaƒbUxmKƒnkm@™k„mK@ƒxó@¯n¯KǦ@ôÅèlxkx°nƒƾ¯KU¯WķL@VÝIUb™yWbX¼Ç°"],encodeOffsets:[[111589,35657]]}},{type:"Feature",id:"6104",properties:{name:"咸阳市",cp:[108.4131,34.8706],childNum:14},geometry:{type:"Polygon",coordinates:["@@šIXyĊwlý„KlƒXIVaķƒ™»a›£„¯aVU@a™‚wÈō‚ašL²»‚VœUln°WȯW»XašzVaÞJ@Uƒ»@¯Ýbğwly@£kÑţ±Wу@ka™IUƒƒnƒ@¯ƒómţU™b™U¯lÇIÝb@¤Ý@kV@zĊ@™ĶnƒVV¤k„V„„bmź¯z@°™a¯J@œƒ¤@„„bUx™bƒ„@`™xUÔ±ºVXœW‚„UnUJ‚LĢ¯ÈKlblmÈXŎ°šU„°LšŽlkÞKš@Èxl_°ĶUÒkblš"],encodeOffsets:[[111229,36394]]}},{type:"Feature",id:"6101",properties:{name:"西安市",cp:[109.1162,34.2004],childNum:5},geometry:{type:"Polygon",coordinates:["@@°²@‚„mVVÈÈlš¦„m°xla„@U¦°ÈV¤XbV°lXÞaÈJ°kšVšaŤVôn°„„@„mV„šJlb„@XÒŤ²lÒ@¤kzĠxÞa@°„¼ĸK°XV‚°L„ƽ¯mlwkwÆç@óÈ¥°L°mô@„w@aƙK@b™@wÝLƒyÅUƒÝƙ@ĉ¯¯Uóx™W¯x™_ÝJmLUx¯b™ƒóak±mÝUU„™W¯b™aƒ»óó™xƧçĉbƒaĉxƒIUV¯¥ō„±w—l"],encodeOffsets:[[110206,34532]]}},{type:"Feature",id:"6102",properties:{name:"铜川市",cp:[109.0393,35.1947],childNum:2},geometry:{type:"Polygon",coordinates:["@@ÆxĸƨšKlxÈX„K@VWƨIlmœV@wVUmUnmUalk@kVaUaóaƒóƒnKV™šÞK@ÝW_xóKmVk£ÇmnÝ@¯ƒVƒwóK@ǯXkm›VU±¼™KbÇŎx‚š@bUV°bƒœ¤‚bš¼ĸ„Ub"],encodeOffsets:[[111477,36192]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/shan_xi_2_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"1409",properties:{name:"忻州市",cp:[112.4561,38.8971],childNum:14},geometry:{type:"Polygon",coordinates:["@@Vx@lnbn¦WlnnUšmš°š²VšV‚VVVnUn„ºlz@l„„@Jƒ@kXWVXl@Lƒa@„ƒKUL„ŽlbnKlLnK‚LnKÆXn°šbVV@bUVl°Un@LnaVJUbW@UX²l‚@ČwlVVIšWnkÆa°„„anV‚Kn°™UW¯@™aVUVk@Un@„aV@ValwUanmWU„k@WVUUanaVwnLVl°@nk@mVU@UVK@w„LVKVU@ƒ„K@UUKVUV@@bnL„a‚V„aôšlIXmlKX_°KVV@bVV„@šzV`kblI„V„Ul‚šL@bnV@V„Ċll„„VlIXW@k„a‚U²blKšVnIlJ„albXXlWVn°JnšnL@l@XlJlaX@„X˜W²@l_VmnKšU„blU@mnkVK„¯@U@ƒma@kX¥VƒmakkƒLƒa@aƒ@WIUUVXWWnk@a°a@kkm@kUUmJm@WUUUIk`m@V—kaWWkX™KmƒXk¯ƒ@WKƒLkak@±bƒw@ƒaƒa@akaƒ@ma¯@ƒL—KÇÅkKWbkmġ™±ÅUƒLUK™VVkƒm¯LUVVbƒ„UwUW¯bm„ƒULƒxWJ—@ƒklmkUm@@KnwVkVK@akwƒ@@a¯bƒKkn›VUI™b¯mmbk@UbmKUL@xUUƒ@klmLUŽlVXI‚VVVUVUœU`mLXVWbXnW`Ų°xmŽxU@mĉƒƒwU@mbU@UƒmbkVW¦kJ™@ƒX@`¯Im@UlUVVnb@bWJXnmbƒJUU™UUaƒ@UamIkaƒxƒ@@x@b"], -encodeOffsets:[[113614,39657]]}},{type:"Feature",id:"1411",properties:{name:"吕梁市",cp:[111.3574,37.7325],childNum:13},geometry:{type:"Polygon",coordinates:["@@@a@w„@„wlbnJVb„@VbšVVV„InaWmXI@a‚aUmVUVkn@°J@_„Wš@lIX¥lUnaV„V@naV@„xĊ„n‚V@‚wn¯wƱX_WmXaWUnKV_V›VUUUUWJkUVnKlk¯™@@kmKUaŁ±KkU@WmI@WUIlUUmVwXƒ‚w@ƒUlUVwœV‚@„Lnb‚W@anU@UšaVkô@l»n@na˜JnUÈLVaƃUUVm„VKVƒ²L@mU_lK@UVWkU‚a@a@U¯aUaƒÑóÑUb™„ƒKk@@aƒk¯mVaUwVƒÑkWUmK@UUKmXUWÝwUa™LUU@aWJUUU@Ua݄U@WL@VKVaVI@WnU@alIVKƒƒ@kIƒmIkJ@™m@ƒ™@@_™K@xƒ@kaW@U„@Vmn@ŽUK@mIƒJUXV¤XXWlkKƒkkK@XmJVakImJU@ó™¯LWKUV@nUVƒLkxmKkLma@kXKmmƒLƒab™LmK@V@mXVÆUxƒX@`nL„aV@@VmLUVnLlLš˜„b@„šŽ°²nx@b‚VUxlb@V¯bUV@zV‚XVĊXVx@lVn@VnnmŽUš@LlJXVƒz¯VWVXbšV@bmn™VUVk„Çþń@XVxmbUlV„Uln„W„@„Xl‚@VLXÒ@bÞJ°¦„L˜ò„@nU‚b@°„X@ŽXbmVU„V„nb@x‚x"],encodeOffsets:[[113614,39657]]}},{type:"Feature",id:"1410",properties:{name:"临汾市",cp:[111.4783,36.1615],childNum:17},geometry:{type:"Polygon",coordinates:["@@nW‚@@UnLšK‚a„b„KnnWL@lnblKnLlw„KVU@mVUXL°KôšV@nIlJUbnI@WlL„llLXkWWU£VW„InJ‚@VL@nm@UVƒX@lb„@@wšL@`‚@„šn@V@lw„@n„VmVX„WmwnUlƒœa@_lK„wVlUn°xVKVXXWlUšVVI@K@K„n°KœwlVlU@kna@V_„Wn‚m„UVm@kXml_@m„LlKXw°m@_ôJVUV@X™l@UaV@Va°I„lk»VwUkVmwUmmVn@V¯@KƒU—wmK@U¯wUVÝ@mJƒU—nWK™@@UnKVa„_lykUmKÛnm@™x@ƒUUlwVk™ƒXW@ƒa@Uƒ@@K@ƒkIV™nammVakUlƒ@wX@@kƒ™¯@ƒVVbml@„„°UbULmlVbnbÅK±VƒKVXUJWa@ULWaUU@@U@aWK@UkxUKƒLUUUJ±UkL@V±kk@kam@UV@l@LWl@n@VVUx„LlUUx@VUV™U@aƒIUl™L@°mLU‚ƒbkUUaWUUaUU@aWK—LWJ@bUL@VUVVbU@m@a@kmKmnĉlUK™XƒWUblb—xmIkƒƒU@xWb@lkšVx™LXŽmzVV@bklVVUzm˜@bk„@Vx@xlŽU„@lUbVnl@„Wxnl@n@ŽUbV„mL‚mƒb@`X@lUX@@xlnkLWaUJnnWV™Vn@l„@bULVV@l™V@XnJVX"],encodeOffsets:[[113063,37784]]}},{type:"Feature",id:"1407",properties:{name:"晋中市",cp:[112.7747,37.37],childNum:11},geometry:{type:"Polygon",coordinates:["@@@šlInJ„lJ„@‚„ULkJ@bmV@XUJUb‚L@UXKV@ރVbV@VVXI@bVVšKVbÞxVXnWVL@VnLV‚lX„ÒUŽVxUb°n„l@bl@„LšƒVaô҄ÒVb°b@VnLnnV@lmn@lb„U„V@„‚JœUVV‚Xkl@lUzmJ@xšXkl‚bUn„JVšUb„nU‚lb„V@nlLX@lakšV`Ub°š@XVJnU‚L²KlxnI@KV@lbUbVV„KnVl@„zlm@Uš@nŽšI@WUaVl@@mVU„@XkW@ƒnkVKVƒ„_Vw„y@knwVa‚@XalU„@šVnml@„X@V„L‚KVaÞbnnlJšI„mVKn„VVVInVlU„@„m@™mXK@UmyUI@mWUUakamw@wUwmLkakwVƒmK™w@wUam£y@am_ƒW@™UU@knmm„amU@WUa@knw@ƒUUUUV@nƒJm@mVUkKVUUUkKmwƒKULƒKUImV@lUn™nŽm@mbUK@°™bUnmbUmkkƒWUb@am@UXkK@a±@™V™@ĉř„V‚UXVxUVkLWl¯@@bULUlm@@nm`—XƒlWakIkm›VUbUL@Vm@kIƒ@@Kšm@—VaX‚I@W@aU@kUƒVU_™KƒbƒJkkǎ™b@nkKmL™wÅW@kVUUƒVU@WUIƒJmIXmma@_kyVaUUlkUm@ƒkU›x¯Lƒm@L@LUJ™UkVWXUWUL¯wVmUkƒxkL@`›bk„mVnxƒXUWUnmƒƒ@kxU@"],encodeOffsets:[[114087,37682]]}},{type:"Feature",id:"1408",properties:{name:"运城市",cp:[111.1487,35.2002],childNum:13},geometry:{type:"Polygon",coordinates:["@@„Vl„nJ˜wkaVa„XšWVLĊknmnL‚l@@bn‚V@UaVU@UVK@aXI˜KXL@bVVVbXVVblV„aVnK@¯šKVk„J@bšVVU@UVwkVƒKVwUUm@@Xk@K@kVUn@lbl@²l@UlK²VVIVV„KVLlw@VXL@b@VV@VŽXbVK‚@XbVIUW„L‚U²ÆLmaUankVKVaƒ¯@ƒnkUa„U°@„š‚n@@kWa„UVaXUW@IXKVw@U™ƒ„™WU@W@@UUƒU@mn@ƒ`m@UUULkUmJ™IUƒ@@UƒK@U@›anƒ™ak_@wmKUwmakV™kmK™V™k¯b™wƒ`kwUIÇx¯»ÇaŃmn@@™mƒmUkV@wkKW@kxmL™UkĉLÝk™xÝw¯lóVU„mV@ĀVVX¦W¤kz@`Vx°„²ĸ‚š@„Ul@x„êĸNJ°¤V„VlXLWnXxmV@nUl@„"],encodeOffsets:[[113232,36597]]}},{type:"Feature",id:"1402",properties:{name:"大同市",cp:[113.7854,39.8035],childNum:8},geometry:{type:"Polygon",coordinates:["@@²£šyl@Ȑ˜Ė@bĸŽĢbĸ„˜X„a‚KŤnn@ŎôllÈx„nVnÞDŽV@b‚nXllL°KšbVb@J@b—„‚„@ŽU„„xlKXLlKlXk„@Ulk„JlkUƒVKXUƒÇVIVm@_nǚLšašl‚w„VnU@UUwma@aƒaÝaLmUk@@Wƒ@U@@X™wVWÝUUUk@@VmLƒKV»nwUw™aUL@`mzƒJUIVƒUaUw™KUaVIlJôanÑlLVUn@ša„@VV„@@UUwVK°Vn_lJÆLœéW@UUUÅ@»lm@aÞIVwXW˜UUkkm@U@aƒU@mwU£VWU_kWmƒXwW_°yUkkK@UÇK@kkUVymóK—U@KWIƒbUak@mJ@bkbmLkŽ™UmƒkVU„W¦@lnb@„@Vƒ°ULml@nkVƒa™VmLUnk`±@—XƒWW@kbǦXŽ¯„WxI@xmbmxXlWV„„@bŎUz@J‚b@bÞb™ŽU@Wbk@ƒxk@WX¯VۙƒWÝbÝUkVUU@alI@a@akLWa™m@U¯UUmÇL@K@aU@¯VUkƒKmX@`@œkJ@nV‚Ub@lbVÆXVW„ULU`VbkLUV@XWl@bXJ˜@VbV@Vl"],encodeOffsets:[[115335,41209]]}},{type:"Feature",id:"1404",properties:{name:"长治市",cp:[112.8625,36.4746],childNum:12},geometry:{type:"Polygon",coordinates:["@@Uk™Lky@I‚JVa@mÞaWšy@_W@_WƒXVlUVwš@nw°K@m„UƒVaƒmVkU@mmmnLVUmKXa™U@IlKVUnK@UmWkX@WV_Vƒ@akU@a„KWIXyƒIUVmUn™Ua@WaXUVKVmkUWVkUƒLU@@VƒbƒKbƒIUmƒ@mbVL—x›WUUkn±V¯wƒbÅJUbmLkbmKÅKƒbVnUbƒV™KUb™KUbmLKmƒb™aƒKkUm@UŽnn‚VnxUVlUxl¼ƒk¯JUbU@Vbk@WšU@UVóI@`¯nWxkLƒK@nk`Wn@lUnƒVnm‚ƒXU`@mb@lkV@„VnklVVUblz@`nbWnnJ„IVJ@XUVV„UV@lÆXšxnKlL@mšaȍll„I„ašLV`„UlVV@@b@XJWUb@˜™n@L„@lJn@@UVKVaœUlnlJXb„k˜Wn_@mn@VkVK@a°@XklKVUUwVWUšƒĊƚ@šU²@@blLVWn@@bVa„XllVnnaVmša@¯VLnan@‚šmVm@knUVJ"],encodeOffsets:[[116269,37637]]}},{type:"Feature",id:"1406",properties:{name:"朔州市",cp:[113.0713,39.6991],childNum:5},geometry:{type:"Polygon",coordinates:["@@XXWVXVWnnlnn@èƼ@„„xlš„ŽV„nblšššVŽÈUVl‚š@„blnœL܃ĊmUkU@Ua‚—@WI@aXk@WVUlKUaV_VKXƒWUUÅka@VaU@mlI@›@_nW„LVl°UV@@b@LÈKVn°V@VšnXblK@b@bkJ@bVVlUÞVÞa„Xܚ°UXWl@„wl@XaV@šÝa@aa@IVyƍ@aƒƒXUWknwna@w‚JXw°ƒWÈ¥kI@W@kmKm™¯IUmkXWWkaƒbkImJ™UkL±aVƒb@lWXkJƒUkƒĉkƒ@UmU@a™KkƒVƒUkJlaU_™yƒ@UU@aUU¯LW`kLWnkJó™ƒbUƒbmK@aU@UVVL@VƒL@„UVULƒK@xUL@VUV@nml¯@UkmKUxmbVbUV@XƒlXVmnVbkxUbU@ƒbm@@VUlUVšb°@VX¯šm‚"],encodeOffsets:[[114615,40562]]}},{type:"Feature",id:"1405",properties:{name:"晋城市",cp:[112.7856,35.6342],childNum:6},geometry:{type:"Polygon",coordinates:["@@lV„Lšb„an‚LnKVašLVašL„UVaUm„aÆLnLlanKVaÆI„a°x²UlmVVœX˜wUKna„@Vn„J‚a„L„a@UV@@alUkKVKnkmmVwUk„w@ƒ™@kxWUXƒW@@mƒk@aUa@a¯aƒLkKmwkUm@kL@K@aWIXmƒVƒXƒWkUVakL@UVKƒw@aUK@UUKmLU@¯n™KUwVƒUIWJUWmka™@UXƒJƒk@UkmW@kLWKVƒx@bmI@VUaVU@a¯@UUmVKmX@±`kÝKVxUL±akL@V™bƒLkKmVƒ@XWVUbƒVXb@lm@@lW@@xk„lVUbnnmbUšlJ@„@L„@@V„b@‚WXš„UlkxVV@„šwn@ÜmnLlVkzƒ`UbmL@Vš@XL˜m„VnIÞ@VU°x@VnL˜x„V@LU°"],encodeOffsets:[[115223,36895]]}},{type:"Feature",id:"1401",properties:{name:"太原市",cp:[112.3352,37.9413],childNum:5},geometry:{type:"Polygon",coordinates:["@@„@VV@wVKnLVal@na°nšaVJœUlm„L°a@b„@lx@bULUlmx@Ln@lVkn„l˜@XI„w‚K„Vnƒ°aVXVx„ƒUaVU°K„nUlšUVL„KÆVš²Ģ‚lnXalLÈƘL„KUaVkUanmWU™a@WwkUWU¯y¯Ñ@anIl@@aVU„m„I„ymUƒLUUVakaU@@LmJkw±LKmVUI@W¯™VaU_l™kbW@kK@mƒUkaVƒmVaU™ƒIVmalk™W@wnIVy@klkWUU›VI@ƒƒUƒVkam@knU@mmmK@bblVUX@VkLV`@n±KU„ULƒ‚UnVVńUbÇKmV—Imbm@k¼ó@Ul™b@VmV@bXmaƒK@›UUxkV‚V@„xW„UxVnkVVJ@XnJ@XlV²LƂVbnL@lš@°"],encodeOffsets:[[114503,39134]]}},{type:"Feature",id:"1403",properties:{name:"阳泉市",cp:[113.4778,38.0951],childNum:3},geometry:{type:"Polygon",coordinates:["@@°@nb„@lb@b„b„b‚@„x²al@lb„KXU@m‚kUWkkmUUƒVwV@XUW@™naVklKXblKnL‚ƒnLVanImaXKlL„ašV@U@KUKW„alƒXK@£WKXUV@VU„ƒUUVW„_V™@W@@K„@šƒUƒƒIWmXUmƒULƒn™JkImmÝaUbLƒK@UƒWk@mn™Uƒ@kVWb@Ubmx@lƒzUxƒ`U„ULml@„XWlƒ@UV@nk@U‚Vb@X™Jm™@@Vknƒyk@ƒzƒJƒnUV@bk@mJ@b°Ò°zXVlVXx‚@šbXVmnVbUlVb"],encodeOffsets:[[115864,39336]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/si_chuan_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"5133",properties:{name:"甘孜藏族自治州",cp:[99.9207,31.0803],childNum:18},geometry:{type:"Polygon",coordinates:["@@ƒaXamƒ¯wm@±°wUwV@UaVw²Kš™„U@UƒU„¥‚a„ƒ@£Þ™ôx‚Knkm™X¥™IUƒÝUwlk°V„@ƒÈ™‚KUwlkUyV¹„mšx²Xll„ÑW»š„l„w°UŎ„nƒ„„˜Jœƒl¯°V@wôIVÇn™nUllšLšVǚLô¼XW£@±„@¥k_ÇJƒkUéƒkšƒƒwXa@ƒšLlw²™Vx„b‚mš¼ÈxlLȃ„VWÞn¯mǙÑUÝlÛkwlĉmƒULmwUJ™ç@wkm@ÑlUX™ƒÑôġƒVa™ƒUф¯@wķÓkbV„mnU@@y¯IķKƒV@¹šaƒé@k„mÞU°¥@a¯@anKlblU„¥@óğç@Çw@wkla„çݱk¯±@ğÝUÛmݯwƒ@kb±¯akXWÜkXUÆÇUš¤X_Ɛw„V@¤ƒXU‚ƒbUƒŽƒIUlÇUkŽġ@™aXČmlUlèUV@„mVk¦Vxš@¦±š¯ƒƒ¯¯anlWš¯nƒƒÅw@w°KVak£m@klƒKknÇU™»óKšīlaUaV£@™™¯@ƙU™VƒÛÝÇXƒÇl—ÓlŹ„»WUğJ¯£mx™Lĵô›ºX„VlUll²bl„„lŽƒxónn°ÝšU¼mJUš¯nƒƒƒV@êĉ°Uĸ™w™@mƒ@¯kmXamѯaUwÝKU¥„mÅn¥Wmn™ƒ¹n±ƑƆÇôXê±NJnšƒ‚UôlĖkȂVÒ¯¼VnƒȮ¯ĀnƆ˜Ģ@Žk°V°¯ĢVlkšVxm¼X²™Ŏ@ŽVxknWÜ°U‚¯n™Æݜ@`„ôݲÒƒ‚Çzn‚mX@x„è°K°Å„UČĬóĖ݄ƒ˜ó¼ÅêƒÒƒbmšk@V„Ž˜„@ҁl@nĉܛê—x@Ėml՛J¯¦óxȭ°ÝmŽ¯Lĵè›Ā@Ɓ„l°żƒ‚šX@xmŽkV@z@‚„°blŽnÞ°J@bn@ƼUVƒUóŽóLƒ°X°ÝLƒxUn„°ƒĬƒn@lnL@ŽÆ@šn„KÆxnUnV˜InĬmÆnxŎ¼ĊIĢóÞ@ĊƒƨbUƒ‚mV¥lkƒ‚wnL„mšÅÆ¥Xƒ˜wU@w‚wUÞ™@alUUŚU™Vkkm°aU—°Ó°w°U„ƒ„b°aš²K˜¯œĕ˜@ÈbޏĊaš»„XVm°In„‚Ĭk¼Vb„ašJšôš£VĊan™‚k„ů™™nƒÜU@anKnĮ‚bÈmƎš»nI‚霣Ġ™"],encodeOffsets:[[103073,33295]]}},{type:"Feature",id:"5132",properties:{name:"阿坝藏族羌族自治州",cp:[102.4805,32.4536],childNum:13},geometry:{type:"Polygon",coordinates:["@@l@@þ²I@lƒ„VL°wnJ°Uĸ™Ŏè„Ilw„V°¤nĮ™¤Ý„lè„L@„ƒ„@x„l™è²ôĊ_ĊġVÈôJżīlbXšÆÈVŽkxÇVƒ„n°„¦Üb@è@nn@@°šUÈ¥WDŽ_Uala¯¯UǙkƒ»„mVwk»˜k²°VxlL@¤œ_@x‚`ȍ‚Ėöb˜š@l²alX„a@bnK°¦VK@nnWmx@nUnl@@lƒlĉk°l°UXkmW@Unš`k„ÇL„ŽW„ÛÈVxšVVlVk@l„IXb@ylXÈW˜Į„WŤzœy@šmIƒŽ²šJ‚š@nŽ°@V„„J°a„Å@ƒŎkVǚk™aUw„KVw™™Vƒ„@nkm™@±ôkô™ĊJš¼šInÑm±nIššÞ‚XȃĊxĊUÈbÜyÈ£Vkw@kVUV™„m@ša„»ÜbÈmƒUXwÝxƒUn¥@°ġ™Å‚aœJVk™aW¯Û@W¥—UŏĶ™@¯kUƒŃ@ašI@mmanwސ‚W@œ™mw°»Uřk¹±W„xVx¯¦U°ƒzţW™w@°ÇVÑk¯@„y°aš£š@šmšnl¼„ašÝÝakwUƒ±aĉImlĵn@ƒm@kkVƒ¯Ñm™ĸ™°x„l™œ@˜ƒXVÞmlÛݙĉUÅ¥mwÅ¥VaUw›™XġċaVůÛŹlwU¯U™ó±™xÛV±¯¯n¯mċƒLmnĊm‚™@™_kJWaXmwUƒĉK™»™@mwX݃UDŽkKÇw™»nƒaUw±škx™K@„Wb„x™„„lVê„lÈIl`@¦ƒŽ@²X¤Wó»™KUșŽ™KkkmVmšUÈóJ@x¯Uk°›„—Iƒƒm„ōƒ¯Vƒxƒk™ŽX¼ƒÒkk±W™wƒnUºVzklVxLǚ@„ƒŽ¯UklVxސV„šJW¦nšmlLówݚ@¤ƒ„bƒ¦„V@VƒV™š±LUxVbU@Vx¯x@²n‚°xn„Wb„b"],encodeOffsets:[[103073,33295]]}},{type:"Feature",id:"5134",properties:{name:"凉山彝族自治州",cp:[101.9641,27.6746],childNum:17},geometry:{type:"Polygon",coordinates:["@@ĶóšKnw°¤ĠIXVƒ¼kź˜Ôk‚„ÈWŽÞȄÜUVšÅš°@šš‚@U¤Vbkb™ĬôLš¼ÈVlm„Llkn@l¤Ub¯L@xÆx„„°mX™mk°b„°°„²™@¥‚™Uwl¥nU@ƒVUkçVnkWċšbĢ@lÈVVk„J„‚V„aV„W@£ƒUƏxW`™£ÈVVÅlWXÛlW°b²la„@°xnÞVÜĠÞ²@l°Þ²ƒèkblŽ@xÈx@Ġènal£nU‚Dz@‚ÞK„nn¤@¼˜°U¼„nV‚šXU‚šbn™ĠUVbUlVš°LX„@lV„èÜUnK@_ƒyXVyUwmIU»Vƒ„kÇ¥šÿkkV¯m±n@ƒn¯ÜanVVƄz@Ž‚bœwÜb„m@wša@kƒmk»@™a@VUUó„w˜@nb°mš„XŽmnVbގVôanwšJ‚ak£lw„˜šLšÅnÝ@wl¥IÇӃ@U™™Lƒ¼kVǃÅó¯kVmmw@ƒn_‚Vn»°LÅ»@éÇçŹīVÇÝ@ÝğU™ƒaVݙ™š¯ķlŭġlƒ@óÞۂċ@¯nkUӄ—m±™IVġUwóKUn±¯—K›w»ƒKݐV„nl@„óxUwţ›£ĉƒUmŗÇ݃K™„ÝUlmKƒ£UVŽ@ÞȎW¦„Ò@Ĭšnny‚@nÒmœVŽ—¼@°Vbl@VlnUUwl™°a@„œ„@llnk°lbnKWĀnŽU„VxUŽ‚²Å‚m¦Û›ÇŚƒaU„Vbš@¦m`móX™Umm™xÅ@±Þn虲™U¯»m™ƒV—m@wƒU@wݚÝmLƒa@„™VÇUk„l°¯„VlkVƒ¦UšmxƒaULUèVx@„kIUxmWV¼¯VmȯšU„nl›È—@m»Å™ƒVWxÅbÅğW@kƒm@kVV¦mlnn@‚ō„l¦Åƙxkœ"],encodeOffsets:[[102466,28756]]}},{type:"Feature",id:"5107",properties:{name:"绵阳市",cp:[104.7327,31.8713],childNum:8},geometry:{type:"Polygon",coordinates:["@@„ńlV°š@Őĵ˜VX»ÆUĊќJ‚w„@È»m»š£°Kšk@ÇnÑƍš@„w°JUwnw@wšbVbš@VlźLUw„aƒ»„aUklyUUVakwWXwWƒUxkLƒmn¥mšwk™˜UX™lJ„w@aƒIk°X„¥Wƒ²l¥šaU™„IlmkklƒÈL@m°nlWU™aW—š@Vƒ„@UaV¥@ašk@Çk¹ƒK@a™K@kƒKkšÇX@VU@kx±V™èkIWwUVUkkKÇ@ƒa@wkml¯@kUWn£Wa„aVwnaV݃w¯@UaWx—n›JńUxUšma@L@„mbUŽU±VVnkxUƙ„VŽm@kkKW°„X@¤ÇUkÆÇnU¦¯ŽkƒmLVwÅK@UóbÇƁVƒ¦™L@‚±êX¦mVޚkÜÝnWU—„›@kšƒŽ¯wķšnš°ÒU„lln@@„ĶmnkĊJ²bV„lxÞb™Þƒbk»™m™n™@™¤¯bƒz@Žl°UÒ¯È@ŽšxŤX„yV¯°¥Uwƒw²XlºVŚ¯¼nx›š@ŽXݏmxnb@n™J@b"],encodeOffsets:[[106448,33694]]}},{type:"Feature",id:"5117",properties:{name:"达州市",cp:[107.6111,31.333],childNum:7},geometry:{type:"Polygon",coordinates:["@@Uxn°‚bnŽlUnÒƃnn@n‚¤„LnxlU„ššV@„Æl„x°XXxl`XœƒVW‚œL˜è—„±nÈbƒŽ°b@š²x°Kܼ°ĉ„V¦lJnU@¦šÞ‚JÞğ„mšLÞ»šxU„lb„VÆann„alŽ„VƍX@lnŎV„mU™maÅXƒa@aWmœ@‚£@wĉJVƒkk‚kkmƒnk@ƒmna@šal„Kš™‚J@Þwm‚ÅŃ@ambkUƒƒ@™™KUġKU@m‚ak¯±ƒ„a@aĉÑÅaVwšXlwƒ±—V¥l@@a™kƒ›@@£šmƒĉÝónWV@ŽnÝÇÇx—UmbƒaVkkk@m„@m°ƒÝýXm›akÅīƒ@@ƒmb@@xmšnbƒ@mxšŽkWL@ƒ¯b@WUXmWœWKkbm@kx™Xmm@LUl„xlêóK™nUš„all™LƒlLó°m¯JVšU„K„„@x˜K²Āô¦l°"],encodeOffsets:[[109519,31917]]}},{type:"Feature",id:"5108",properties:{name:"广元市",cp:[105.6885,32.2284],childNum:5},geometry:{type:"Polygon",coordinates:["@@ÆL„Ċx°»Ŧ¦˜W„™šLȄ@xÞKÜ°ÞnVxÅĀlÒnJ°a@w„V¯l@XWknKnw˜VȚ°XXa˜lX°VI°b„W„nšaššš¥@ƒw°™n@šyÆ@nkÞ@°¯lJn„°IÈl‚UšlXÅ@ķlUV¥VUUÝޙUUƒ@UwƒJUkĉm@ýƒƒlk™WUwVwWJk@VUK™lUkaVƒUƒmLk„m@ƒƒ@Uƒ›Ik`@„™UmlUkV¯ÇXKÝ_mm¯@Uƒ`kwmƒl¼±KV¯—¯Vk±Vk±kzma™KUnDZ™bk¦±ŽX„ƒ¦¯Wl„J@bƒxkIWš—Vlš™xnŽm¦„nlKVwX„WxXŽlxUbVVkzVlƒb„¼ƒbVxŹKUk™@Ua™a@xmxVx¯Iƒx™@ŎmÒ@șl¯L™¤n¼"],encodeOffsets:[[107146,33452]]}},{type:"Feature",id:"5118",properties:{name:"雅安市",cp:[102.6672,29.8938],childNum:8},geometry:{type:"Polygon",coordinates:["@@ln@xšèVInxVKn„‚ĊklxkÜVޚÒnÈm°nxš@š¼ĊLV„nx‚WXblIš`š@nmĉn‚KȄôÅlUÑmU„K²¹@ÇÅVÓůVýÞW„‚UVmX„ÆbnwšKUÿ‚™@UmmIUb¯¥Uwƒ™¯™Çmš™„çmanUm»UUƒl—kƒ¤ƒa¯bV™U_WĕmÇŚ±ĢUlƒUl™ÛVƒçkUƒ@WŽ¯KU™VkUağVmš™aV™WUƒmV»—¯@»m£ƒmÝLŽ±@ÈmVk¤mb@ôƒ¦kVkamL@b°‚@b¯¦ÝVƒn@l„ê™b@º„UĸL°J@zV@nmUƒlaĸÔ@xƒ°VҚ„Ub„‚óĢ„ÒWškV@Ò"],encodeOffsets:[[104727,30797]]}},{type:"Feature",id:"5115",properties:{name:"宜宾市",cp:[104.6558,28.548],childNum:10},geometry:{type:"Polygon",coordinates:["@@VlÈnl‚XnWLX`m„²nV‚@b°xĢçlnšVm‚nn„@@„°‚UzšlV°nޘÒkxl„w„`UnVb„mšL@albÞKÈۚmܼ°@Xǚ@wmW@ńKĊL„lV„šLVŎçÞL²±‚ğkw@Uƒy@¹lKX™lKVa@w™™Č@‚w@a˜ÇU¯n™@@wġak—™aō‚ƒƒK@Å»VakUWmķwkbğ¥mL™akš™@ġރ°¯xVVÞ@VšxVš—VWx„XlxU‚™@k²WVŃULmèULVĊklĠ„VœJVx±nŃ¯¦mwğ@mƒƒlğkkl±@kšUk@¯±Ç™Kƒ—kxl¤b™Imx"],encodeOffsets:[[106099,29279]]}},{type:"Feature",id:"5111",properties:{name:"乐山市",cp:[103.5791,29.1742],childNum:9},geometry:{type:"Polygon",coordinates:["@@kšVŽk„ššÆkšV²UlºÈIlxƒLXèÜlU„„XU‚mkƒbVè„x°@„@¼°Knnn@m˜ÆIUbnJ@bVI°b°±@nK@mVakkƒKl¯nbšmĸ„èl@VnÈl‚UUw„wmwnm°¥„L„™lLnU@Va™ImbkƒmK„ƒƒnk@mƒb™ƒƒLV„JVUUƒ„VnkVmb@a¯JUaÆkk¥„IW¥„Klw—ÑmÝU¯™kVy¯@ƒƒ@mmn™Ukmġè¯w@aU±mnƒW_XKWmkÇmUkóbUÝUanmW™ƒ¯nma—@ƒxVôUV@šb@‚l¼„n@l™b@xƒnÛa›xa@ƒyUÅmUÛbm°@„m‚n²U°ll™ĀȦƒlU„V¼nJVxUz‚W„z@`mL"],encodeOffsets:[[105480,29993]]}},{type:"Feature",id:"5113",properties:{name:"南充市",cp:[106.2048,31.1517],childNum:7},geometry:{type:"Polygon",coordinates:["@@ȲVmšLnblyl²²UUl˜°U°²L‚»„knlx„_VŽ°@nnÞ`WL°ÈUŽVlnkšV@ƒl_œJV„‚@„„n@lƒnKV£™Çšƒ„UV¯šm„@laX˜U„‚UbVx„@VkôJU°Jn™@™‚wUk°wnUƒV_nJmknmm¯Vwk¯ó¥±ÿ—L@wƒƒƒLVU™kU›bX¯mykI@a±Kk¦ULmaXƒƒVm¯ƒK—z±ƒklUIVbÇJšƒkL¯™l™ƒU™ÿ™UƒlUkJƒUmŽUUkVVklKk@@a™U@„™J„²ƒxƒ¦kĬ@¼±ºXnWb—xƒU@xƒx@lšL@b„Llº@șl@bU¦Vbƒ@U„™@X˜‚bVškX¯m@nÇKk„llknƒJVš"],encodeOffsets:[[107989,32282]]}},{type:"Feature",id:"5119",properties:{name:"巴中市",cp:[107.0618,31.9977],childNum:4},geometry:{type:"Polygon",coordinates:["@@V„U„lbkVšŽVLUŽl@XI‚ŽUxVxšXkl„„@þĊnVl„IVx„@VVݚVÞUVU¦kV@ĸWÆô²š@VÞnš@Vaôb²W@‚K@XUmÑUW°¯°Ina@y„_lWn¼lLUbô¼„Kla@™nkUyô—Æx°@šn£™Ý@¥mVkIU¥Ċƒ‚¯Û»¯L±w@™¯a„Ça²m˜ƒ—ç›KX„UW›k_Ww¯WƒwÅk@ƒ™Uƒ™kVmwƒK£@mmmńmÑkVmamnnlmIU`V„m¯xVlx@šmš¯IV‚óIUlƒ@UwVaƒ—VW‚kbƒ@™nU°ƒV™„šÈU¤"],encodeOffsets:[[108957,32569]]}},{type:"Feature",id:"5105",properties:{name:"泸州市",cp:[105.4578,28.493],childNum:5},geometry:{type:"Polygon",coordinates:["@@VVXwVKn„˜wnVƒn„l@b¯xmKUbVn°°X°@blLšènV„@Vn‚l@U„LnmmUna„VV_ĶV@wnJ„„l@@kkKVólaUwnJm„wUlm@ašUaôKVnJWbޚ@VšwVLX¥VVš_Þ`šw„WƒÞŹmmnIn¥Wƒ@k„WV¯@ƒ°kI™ŽƒLk¼Ç@k¤±Xk˜™nmݯUlÅÛKWV¯kƒlUwkLƒÓ™@U—@ƒ‚w@ġXV„˜WX„š@UbVbšV›š_kÇV™lU°lnwŎ¦ÞaƯnmm¯šU„™m¥nkVmkƒl_ó¥¯UÇl¯@™ƒ™L™kƒ`¯ķLUy¯@mw—¼ķ°ġ_řU°mlšnÇVUޚ„@‚ƒš_ƒJUnV‚UXšbl˜Ģb@x@mšV°—È‚b@‚xċ@šš@xUbkLWškL@º„zV‚@lxĠ±²"],encodeOffsets:[[107674,29639]]}},{type:"Feature",id:"5101",properties:{name:"成都市",cp:[103.9526,30.7617],childNum:11},geometry:{type:"Polygon",coordinates:["@@°n°m²°ÜUšw²ŽôVš°ŽVkxÜźUŰČb‚ŽĢlaÈL„»ƒ@k„wVǂ@„ƒnÛƻșUÝ°Kl_„V°Uš`Vbn@VbÈLšaVU@ƨ»V™nIl™šUUa„±lIk±š@VnKmÅ@WaƒK¦™lVōškK™Ý@maXÇmw¯IU‚@kƒVƒwUmVIƒƒƒç—ÿƒU±ŽÅ@¯È@xƒK@wƒLUbÇKō@mÝ£@yóUóóUxkI@WlIUaƒbƒaŽVĀ™LmxÅaWƒUnVƒÝXUþÆ°UÔÈÆ@±ºƒLnVVÒkóÆ"],encodeOffsets:[[105492,31534]]}},{type:"Feature",id:"5120",properties:{name:"资阳市",cp:[104.9744,30.1575],childNum:4},geometry:{type:"Polygon",coordinates:["@@„è„„UJVn„x„U@lV°JnxWÈnbÞ@šŽlLŎ™Ušk‚¥„LXbÆ@nŽmLU‚@zlbXmlnVynL„çšJVb‚UnómUnamU„an¥lKV_²aValWô„n@nƒ‚bVœK°¯VblW@kkƒlUnlV£°W@w„UXk°KVwƒmVkwVyVI@wkmƒVÅ_Umm@Uÿmbk£™xUaVw±V¼V¤kLWxU@Uk™bƒyƒXšómƒ°V@@zÝÒkKƒn™±U@@_VVkƒÇaVwnLWalm@@kkVVl™¦kIV`±n@w„Kƒƒk²™aƒVUUV¤™nkxmUkVWVnLUbVbƒ`kUU„mLU‚mX@`ÅbǚXbWLXŽ›n"],encodeOffsets:[[106695,31062]]}},{type:"Feature",id:"5104",properties:{name:"攀枝花市",cp:[101.6895,26.7133],childNum:3},geometry:{type:"Polygon",coordinates:["@@„b‚KÞnޙ@x„V@x˜n„Unš°¼šVš±mç²ÝÆ@šwnnšVWŽnôn_@¥‚™UaVƒ„bƙœÈ܎n¥Æ±VUwVƒmXÿmLkal¯km@k›ƒ@ƒ¯bkšVxmVUkk@Ua@¯˜»Un›mс@mz™m@īƒÑX¥Ç@ݙxU¦ƒšÅŽÇUkx@šlb„UWVX„mV@xĵĖ±@@Ž¯xUšÆLnÆm„šx@nXL±lUUVwKWak@WxkbšÞƒŽĉbUn@‚ƒ@@xó¦„Ŏ"],encodeOffsets:[[103602,27816]]}},{type:"Feature",id:"5114",properties:{name:"眉山市",cp:[103.8098,30.0146],childNum:6},geometry:{type:"Polygon",coordinates:["@@„šVx°¦VanJVnš@„b„aVbkJ@XlJVwôôôV@zÞ¤@nƎÈLVa„K@x„L@w°ÇÆ@²„V˜ĀœmWXKWașÆa@_nWVnKVƒlV„_UaVamKXUWwnmmwœÑm£@ynUƒkWƒĉUkWVkkV±çkJmkKƒšƒK¯¦mnnxƒxVxVÇkUmk@ƒçķ™nmak°„LllUb@nmL@‚¯²¯aUJ@amIVaÅJn—m@mm¯L@»ƒŽ¯@ƒwUç„anlVƒWVƒÛkWç„KkwÇJk¹±V™UÅl™™ġV™²ÈƂnXĖV`Uš°a„b„£˜l„kVVn¼mVnbƒè™šÈn°š"],encodeOffsets:[[105683,30685]]}},{type:"Feature",id:"5116",properties:{name:"广安市",cp:[106.6333,30.4376],childNum:5},geometry:{type:"Polygon",coordinates:["@@„VlIV‚„kšVšĀ„Vkš°šlK™„ÈIUaVJlk²„˜y„Ln°„UW„nbVKl¥²L@blJnzW°œalV°Inô¯‚K„kšKkkƒbV™šmôLkéƒwVk@KnnšWlwn@laXL›ŽnXVW@X°a@„XKl™nw„@man™@w‚@na@„„@ƒw™ĕġġ™wUkUWb@mk@™¦ƒ¥mUÛb±yÅn@bml@kV@„ƒlknVbmVnlmš—bÇk¯bWyk@V_UamJ@I—@WaƒVXamIVWkUkbVaƒUUxƒ@VnkVU¼›bkKUxmK™„@WšƒxnV@n"],encodeOffsets:[[108518,31208]]}},{type:"Feature",id:"5106",properties:{name:"德阳市",cp:[104.48,31.1133],childNum:6},geometry:{type:"Polygon",coordinates:["@@nUW¥²é@šK„¥‚UÈÅôa@VÆLUxnKl„°V¥ÈmlÅÈV@£ƒWX¯lLln@UšƒVÅlwUm²U‚VVna@ƒ@KnbV™VwƃœI˜mXwWƒkIVwÝĕVUa™IƒèmKUzkmWnka@y™@l²kJƒ²Vb™VkšmJUšƧ¼@UV™bÇKUam@Ua™_¯VƒUk`¯LVÞǚżm܃„@Uȃx@l„ƒ¼ÇKkbWŽœšVxUbƦnxƦĊV"],encodeOffsets:[[106594,32457]]}},{type:"Feature",id:"5110",properties:{name:"内江市",cp:[104.8535,29.6136],childNum:4},geometry:{type:"Polygon",coordinates:["@@²èlUUllXĊVX„„lmV@zn¤›ÒnxmnXxlUnVlwšmU£VV„Ušbl±„„ƒL@x²mU_lJš¥UklU@ln@‚kXbmKUxÈbl„UU@`V@š²„mlLÞÑ@yU@„¯ôn‚™„W„zšaVlV@XwlKU£‚»—aVaUwm@mwUVUwkƒlVDzLlƒ„KV™m_@ykUmƒ@mU™çkKmxkIU‚Ý„@LUJ@n±„kº‚LXb™¼@mmIXa™@mamnkW™ƒKUƒƒxƒ_U`UklwUw™mUbƒV™²ƒakbƒmkn@`„UmҙšVxUb™I™`UƒaÝÈ"],encodeOffsets:[[106774,30342]]}},{type:"Feature",id:"5109",properties:{name:"遂宁市",cp:[105.5347,30.6683],childNum:4},geometry:{type:"Polygon",coordinates:["@@ÞĖUxlJX„Vb°@„xUÞmbUxƒbXbm¤VX@lk°ln@x„bÈ@lLVlVUXxlJšç²UlwV@@UÈWl™„L„w@w„V˜wXaWm²¹@»lī„¥„wƒ±šI@ƒšV@bl@kLUllUVVn@mmU„wX™ċbVb@VUkbmamšW@kƒa@™™k@ƒlaUa™@¯b@šmmwó@@lkXUa¯°›LU‚am„m@óƒkXUb±bU`kLm¦ƒbnVmbnVmô"],encodeOffsets:[[107595,31270]]}},{type:"Feature",id:"5103",properties:{name:"自贡市",cp:[104.6667,29.2786],childNum:3},geometry:{type:"Polygon",coordinates:["@@lIÞDŽbVŽš_šJVaUwš™nуV@_lm„nla„bš±„UVašnVxkxVlV_„`„wV„„LšlXnmnbš@WbnJ@nš»WaKl¹²ƒ@mVI@KރVlJnw@aW¯¯¯UmVanL°w@aƒk„mmU—xmƒULWxUUÝKōèU™KUƒƒkĉKƒL@ÆnX@x™‚Wȯ@Û»™nÇÜÝLka@b™KƒnUaVmƒ_ƒxkƒLX¦ƒJl¦ÅlVb°I@bnaUŽmlƒUV„UVƒIUŽ„Kš„„a@nml„„ƒŽnLl„našJUbV@"],encodeOffsets:[[106752,30347]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/tai_wan_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"7100",properties:{name:"台湾",cp:[121.0295,23.6082],childNum:1},geometry:{type:"Polygon",coordinates:["@@\\sŽ@pS}aekgKSu™SsMß`¡CqZ·be@Q^o@‹gieMp‹‰]}•}Ľc_Kk…{™ù“A¡r‰[uom@эĥJiq©mʼnq¯Bq]ÙYgSåk_gwU­isTE…“‘ĕiqiUEkue_‰OSsZ‹aWKo¡­q“ycY£w}‹ĩ™ĕS§Z©S™N¥SyLÑ¡±Ks^IY‰PdƒY[Uo†Fp}´\\¬\\j]ˆe܍ò‹¤¡–ā a\\bn™U㺹Ìs¼j®[cíȈEŽĝĆ`ļf¶Š®K|VØDdKGpVnU‚FjpH—F`†B’[pMºxÖjbpÎxp€¬‚|ΟÜÒCŠ²®‚ÜAp„ZG~€Šd˜ÞàV¨|¸€`|Œ²tx~\\~|dFf^zG€ĄŚhœdL\\hĸž¼†ŠOªP®lV`p\\]Xpll˜æ¤œCpQ|oF}fMRi†NSon_²qämœM„NM‹\\•"],encodeOffsets:[[124853,25650]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/tian_jin_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"120225",properties:{name:"蓟县",cp:[117.4672,40.004],childNum:1},geometry:{type:"Polygon",coordinates:["@@EUDAEI@WNMNCBFAHFFNACDJDPBD@@GD@DIFFHEFGDBDEQOFG@EI_KG@OcJQM]RMEKBGPG@[LaCIICBWKCEEG@WBQHCDFD@HSLEJI@IHWECFGAAEKCGDBFCBSBIDCKKHEADMJMFABKOKEQAA@IEEG@GIQAEK@OZEESMOL“lu@SLUTYFQCMG@@SQUAYKAACA@IB@BDB@B@DC@@BGAEFAA@BEGKJCC@AGAIHA@@JC@QEIP@@A@EGIDC@O@C@@@@CJCWKABFLBBEBSQGBAAMIEM@AKBcJEN@BEBCFMAEFEF@J@BG@BFABECKFG@AFQ@@F@BEB@@A@@AAAKAE@GFGDECEFEECBKIKDELDFEDYH@EIACDCHKBEB@BAAC@ADBHABKJIAIJICEDGDCD@@A@A@DHCHJHDFEFGBKRKBGIK@GIMHSBCH_BOJECCJCFKKMD@DNJEDEGC@OJCJHRUL@HRJ@H[DCNKDZHCTFDHCFFKR`TANVDFZRDLFARB@HPAPG`ILAR@TERNDFNHDLCLDDCXDYbHF@FEB@LDDVE@JPNfXPINCVDJJD@NJPAJHLXHDNANHhB@DPNLRMTBFRBHHr@`NBFEBOCCBIAQJDHCHLHFA@HSDCRLFTB@HEFLNF@PELBDJALFLTC@EPFLLP@tUHQJDfIHGTB^JTCPDLKAIBATFPADIEGECEMJ@JIAIHGECFEAGDI\\SPOXAFCL@BQTQBBTMZECYGAHA@GJAE@HCAEME@IECFKJADDBABLTHHG@ILEAMNDJCDHEBF@@JNFJELDFKTOT@JETBFFHBHEHKI@@IJEJ@XKEOUMS@AF@CEB"],encodeOffsets:[[120575,41009]]}},{type:"Feature",id:"120114",properties:{name:"武清区",cp:[117.0621,39.4121],childNum:1},geometry:{type:"Polygon",coordinates:["@@FWôµ@IFCLIB@EHNBp]AGEAKAEDMGZKFGBGME@ILGP@HEFB@BXMEAHUGC@IHCLOD@X[NWHWPKAEF[@EKIOL@EKGBNMJ@EIEHKBIC@BAKMIACCFQZCF]DB@ERAKADIHGEIBCGIIECFaGLZO@EFCNGAGDGAKL@BMG@IE@ADSDEH[JGC@CGA@BMDeK@EIACFE@@GG@FIAMM@CCGC@EM@ADE@CFMAAGHBDKIEAJG@DOGCDEKAGIS@KFCHKAEHIE]BeKNO[IFIOELC@A]GMBKVYCDDgGAICARc@MW@AQE@DGI@@AQ@@BKBAIQQYEFW@CEADIGGBCEIiMEMF_LGEKMBBDWEBGRC@E_CHYGCH_IAED@FFBQh@FGJaJ}AHRAREF@bE\\C@CT`FHC@\\BBF@BID@HGDDJ@@FAHKBARECKDAZBJIVNHCTA@EREAMLHDAFFBVFFC@RNRETHD@FOJMACH@CAB@P@DF@@FGDWE@FFSIEMKQDYCCHKb^JADOCIDGNDBdBCFJB@EC\\A@BJEA@JAAAD@HHD@LFBCFF@BERDHNhZQHMBGHOACCEBWEGD@PSJKCGEUD@CINLFGHE@AJK@HDABBHTB@F`DBFLBBHEDARCFG@ABJBAPVFE^FBGLGCFG_BMLEXGAAFE@@JNRVJHFALFBEHQJCTbNDHCF@PlFLJSXCHFHfVBTNJ\\BPJXC^FAVNFCHFB@FFH@JF@\\ABCFD\\BDMCAAJKQBGAILOEGHILECQLWFENJHADC@QxNHFJNLDFA@CBA@D˜UÂmR@FBL@BD"],encodeOffsets:[[119959,40574]]}},{type:"Feature",id:"120115",properties:{name:"宝坻区",cp:[117.4274,39.5913],childNum:1},geometry:{type:"Polygon",coordinates:["@@TZbB@JHD@DODCLM@AP@LL@BNH@ETFN@`E@DNG@CHLBCJA@AICFKDDBKA@\\N@AFNAGRBFjFFFL@DHLBLFQPcXAZMJ]GAVHAIZJFNE@JpDRRDCLFDGXA@EFF@CFFPDfEBDB@DCHCFCJDJIJBLI@I@CB@@ADBB@FALADGDC@@H@BB@FZGFCCE@@FMLALJDAFFFEFDFCB@@AHCF@L@@BBB@BB@FC@E@@R@BEL@HEFD@G@AH@AIB@@@FEFEBALDDEFAFO^IF@JCBBFPNJJ@D@PRDCEKBAXL@BIFD@T@JE@BHHJORFDI@@B@JGH@@B@BDDLIFFHCD@D@DEE@BAAAB@DAF@B@H@NGLJLMRDNMfGIEPMI@GDAKK@KIDIJ@GE@CFDN@FE@GFEPGV@TCDFKHBBF@RW@DD@@ID@TJFKIKLI@EP@IGBCLAEKLEN@KSHIGYACSD@SEAMBBMGEBMQBCMIGKFB[D@HDLPHDBC@IFITDLG@IIIFGVBNJDLN@VIRI@YIAIHIC@CLKZCBEE@JECEIHEAKGDGECBGEEM@@DA@CCCBBEGA[GEDBBoNAAH]MKiIAWKQoIIPMFQAEEDMH@FMSUYIeF@EK@BIOEKJEBICFKaKPFAFSE@LWCCFMHDDEKESBOGBKIEIODLG@CCDEQCEDWEMDIEIB@EHGEEDAEAa@@HqDEJGF[AECCFa@WCEIKAAEQB@FCAE^YDERDDJBLNABD@AJGLJF@FNIAMLH@FPKLJ@FE\\BFOLGXMXW\\C@KPGD@JHDGVFBWN@AEAGFO@KH@JNFAHEHYLNHFCLBFBBHo^MAFGA@KJED@Jó¶EX"],encodeOffsets:[[119959,40574]]}},{type:"Feature",id:"120223",properties:{name:"静海县",cp:[116.9824,38.8312],childNum:1},geometry:{type:"Polygon",coordinates:["@@NGFMDATCNDR@CCbINEHNJA@C\\EEGVE@IhE–[˜w”epc¢·²›^QEKIEKIgiQDkehY£uSDBMkUDOJDHC@GF@CAFBFEN@C‹Q@BeP@@G@HD@@MHQKi@[IGCOCESE@GMA_OcCGDu`aˆ@VZzKDkJBLNXGDqKEWE@cFEFA@ƒISIi@@KMABJGBcMuFEzGVH\\ATSEUBeALCEMG@CEBUHUCGXaBPtUBBFIBFTDFF@DDKBFNGBJPHXDDMDCLJ^mBIHIL@LR\\@LCR[@@z@NFD@LLBNb@RHDBNTPT\\F@BJF@BXCFBHHBDLFB@HODADE@@JHVXCPDHCFTLBBFNCDCCCU@@GAABEHHZHBCAEdEjFDD@GfD@DXFCHF@ERFDLBH@"],encodeOffsets:[[119688,40010]]}},{type:"Feature",id:"120221",properties:{name:"宁河县",cp:[117.6801,39.3853],childNum:1},geometry:{type:"Polygon",coordinates:["@@BFLBFJXDb@DEFD\\BHEFIrC@Gb@FBCBFFGH@FJAJFNCXFFCRDCFDDH@CKJPJFALPHTALFCFGCENDDKXF@ETEBO‚bLELJDFALIPFAJL@@FfEZJTVENG@CNFFRBNEJOpJLRBXjJNLG^BBpMAAFC\\HHBAFDADDB@@CN@FFAHFDCHLHFBJGFCFUNKJJTD\\XUXF\\^F@DDDQXXBRLRCBDFEVCDLVDpUl@LEDJHAPRFGL@CETGPBTCDDVI@CFF@GFDCCVGLKEK[Y@MECISG@BKNSCGCKWEAaEBEKNGFSECO@GGM@GYI@DÅCMLHPTF@DJHAVVNKEGDETJ^[TJNNd@NOAMFYJ@@GFANDPEJB^aOadSTQSI@MHBDIEOKCG@EEFCKCqXO@@DMFENCDDHCCGJ]AKFoDaGGHYFDHKJiCMFGC@EQ@AEHGAC@IEAATKOHGIC@IXIFEoƒGE[JCFCDHNmRADFZMF[EEBMO{GU@AOW@@]ZeHBDEHBKEfQkuIWBs‡@EC@d[@[^EDMTKCEEcI@cDAB@FCBCACmOCG{PYHeBgPwPFDDALFFFCHQGSD@BHFAR[TaFYXMASUiGFL@DQNCJI@@D@PLDN`ETEFIGMCGBCE‘~CAIFDPEHGEQPHJADFJGHCJLB"],encodeOffsets:[[120145,40295]]}},{type:"Feature",id:"120109",properties:{name:"大港区",cp:[117.3875,38.757],childNum:1},geometry:{type:"Polygon",coordinates:["@@JFFL°_`ONJKDDFIFZN xlb~yFVNRŒrdJGzDPVFBCTNND\\UR@E`F@@Ip@IWGUoawOEE@ÏDgK{İEEMFëC—b…™@—KwOCDHHKBDJCDEEEAGHOABFABMCgDLSQ@CFEB‰MgYIDQINE@AUSwSAdYEHQMEyK[KI@GRMLE@@OqOoBOnpJ@BmEAFHL^FDB[C@BBDVFAHFJENB@sNEjQAMYsUgCSBGDJH@\\LjGR@NC@@G@HO@AfR@DŒM@EFEADBE@@HGDICCPlVANTC¤vgZlfRChjLJ"],encodeOffsets:[[120065,39771]]}},{type:"Feature",id:"120107",properties:{name:"塘沽区",cp:[117.6801,38.9987],childNum:1},geometry:{type:"Polygon",coordinates:["@@|ODHnPBDADEDA@CB@ddJFFLDNSFC\\]\\@@cFDˆ@nACOMW@M@ITURBRZNHNWRQšoO•j½f‡cqŸAqeiDÿÍyÓįFL|Ch@ÐFFxPpbHVJXo@@JCTR^BPABQA]^MB@bE@@FQBFVJRH@FXtPNZSBAja@@NƒDTŽLJrQTHFXZFB`"],encodeOffsets:[[120391,40118]]}},{type:"Feature",id:"120111",properties:{name:"西青区",cp:[117.1829,39.0022],childNum:1},geometry:{type:"Polygon",coordinates:["@@@LHAHRHATh`LHNHDG`HDGZ`D@FQDAHXFACNAFLVRTBFOfHDCVBFQH@HSXHEPFB@LDBF[bDbLFKJBFLADBDjLvCPEI]FGEIGCBEUSjcFiBIVWfaHCjN^HtwBBFGPBJGjFBEGECGDONMFAP]TDHQOWCMGAMHKIJEIGQ]aDlUG]VGEGDC„{PEbBZmE@@GH@BCA@FMQCFMYMJECELCMI_P¯`]R±œ¡¸od“f—x•\\gF@JUFFH[F@DIBGMMFaJDDQ@MCSDCBENMH"],encodeOffsets:[[119688,40010]]}},{type:"Feature",id:"120113",properties:{name:"北辰区",cp:[117.1761,39.2548],childNum:1},geometry:{type:"Polygon",coordinates:["@@ROHFFGCOJEDB’}DFHANDJHFEFSM_KC@O@CJ@DIRM@CEKKA…L…FKACHoLSJSIBETDJaEIIE]E]K[MYUYQILC@GF[MGNKEK@A@BCWECAIFEFYAGFOMI[OFuDiKACBCEKIAELaKaCE\\CA@KEAFOWGGTG@ERUACDeGEPSAUQKHE`FNjNFJADHHCJFB@DEXZFRRBJLA@AR@@BJ@CHF@BRX@@NQdDBBJhHCCZDLUNA^H@BKDPFEJ\\JMPfL^AJFFGLBDGLET@HJLBCFHDCPH@BIJFCLGABHNBDEF@BCN@@FHDDDN@BNEJH@@HF@DEJB@FfLNC@AHB@DHD\\IFGTCBCF@@JNH@ALKHBHCHBDMFEP@KYbHDEJF"],encodeOffsets:[[120139,40273]]}},{type:"Feature",id:"120110",properties:{name:"东丽区",cp:[117.4013,39.1223],childNum:1},geometry:{type:"Polygon",coordinates:["@@ZV\\N^L^FJFFJIbSCAFTJTIpKDGLB†E†KLBjHTVNBZWbE\\SBQGE@ATCRHDGEEKECBECxOhOfAZGA_YEEWSGqRKIS„C@Mb@BiTAMYsOEWG@IQEURA@EF@@acUOXQRYCUDCHDTEF[SUEgAYDcVGJM`iAWDWLQRMHUHgDsDBLHJFCFDFGHBFFVEAGHCJN@RJF‡PIhBD\\FENCPWA@LFBAFHBEJUEARCDIAEDQBRNa^"],encodeOffsets:[[120048,40134]]}},{type:"Feature",id:"120108",properties:{name:"汉沽区",cp:[117.8888,39.2191],childNum:1},geometry:{type:"Polygon",coordinates:["@@LMEI\\MTABKN@FCDMH@COAcH[AoēA™M¡Wa[Meq™pQRMXMGQYQASV@J@NNXDPmBAtJXlveRLFGACFGAYf@^X@BPV@|HNPFA\\FNEEYBCnQGMDCDE\\IHFp„EFWJ@JJDGHLPBSFB@JBDGHBFR@@FHDNEjDLICGZEHGbHpCLE^BHIDDCGDCFMNE@CP@rWLDEDFFH@"],encodeOffsets:[[120859,40235]]}},{type:"Feature",id:"120112",properties:{name:"津南区",cp:[117.3958,38.9603],childNum:1},geometry:{type:"Polygon",coordinates:["@@TLv@CNHFFBHGZFETNPhCVGNGRQXKXCjBN_HIdUZChBVF\\TFECSDGVCZDRQPWdVNA^]RBBAAOQ]DSE@F_Q@[VMCSMADUECOHycI‹qMQEU}zkaŸwENRDENB@ADG@@HF@YnaAOFƒ|CDFHUHH^kVbCR^JHIFLJNGHBDNPXGRSCO^EBMNCPDHHFAFiEIHOAEH"],encodeOffsets:[[120045,39982]]}},{type:"Feature",id:"120103",properties:{name:"河西区",cp:[117.2365,39.0804],childNum:1},geometry:{type:"Polygon",coordinates:["@@d@hZNFdcLYXKRCtCMOFSYEGHEAGEDMu@SKAAsx]GMTGt"],encodeOffsets:[[119992,40041]]}},{type:"Feature",id:"120102",properties:{name:"河东区",cp:[117.2571,39.1209],childNum:1},geometry:{type:"Polygon",coordinates:["@@ZBVFFIGABEEA@KXBDOFM[EACJgˆOIE@QIMGDBHUFEEGAEHECEDGIAKQDWLKZcdQPEP@FOFBJTJ@HNORJf@DBCN"],encodeOffsets:[[120063,40098]]}},{type:"Feature",id:"120104",properties:{name:"南开区",cp:[117.1527,39.1065],childNum:1},geometry:{type:"Polygon",coordinates:["@@NMVDCG\\E^B@HlB@YEDS@C…HsNSiMGDebUXAJEjidVTAFHDFJ"],encodeOffsets:[[119940,40093]]}},{type:"Feature",id:"120105",properties:{name:"河北区",cp:[117.2145,39.1615],childNum:1},geometry:{type:"Polygon",coordinates:["@@DBXFADB@L@LFHM\\NHED@JKZRb]QMRAFCJBDCBQYADMCAe@QIMP@GSIAIPE@E[EGH@ZEF]^HJAXK@KF"],encodeOffsets:[[119980,40125]]}},{type:"Feature",id:"120106",properties:{name:"红桥区",cp:[117.1596,39.1663],childNum:1},geometry:{type:"Polygon",coordinates:["@@J\\PNHEZBFEJELEL@BWGI^]FEkA@G]A[FDHUCMNEHJ^"],encodeOffsets:[[119942,40112]]}},{type:"Feature",id:"120101",properties:{name:"和平区",cp:[117.2008,39.1189],childNum:1},geometry:{type:"Polygon",coordinates:["@@D†T@FCHG\\FFOROMEgYc@"],encodeOffsets:[[119992,40041]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/world_geo",[],function(){return{type:"FeatureCollection",offset:{x:170,y:90},features:[{type:"Feature",id:"AFG",properties:{name:"Afghanistan"},geometry:{type:"Polygon",coordinates:["@@ࡪ͇وŐǬϠڐŶӂʮǚڦ۾njƀ̚ІɣʪҴMوǯʲĹ،˒˰Nj˖ϪԈiżŬĘͺβ̈Ҕȏĝʱʪ¡ý۷ͪ˟̊ǰώĊԼϖׂ×ࢀAƬʋӧĥяƹ७ĭࣗǭӫλȤΣĪллΛ–͑ɳ̡ߛ€ͦ։՗ɅΥԕ²ԋ͡ɿ̳þٝŋğɻسDҵӇ‡܍થΓבôǝȁԇņ࠿űටіހހåզُƚßՔ˟ڢάҢιŮɲؒ΂ਸ"],encodeOffsets:[[62680,36506]]}},{type:"Feature",id:"AGO",properties:{name:"Angola"},geometry:{type:"MultiPolygon",coordinates:[["@@ȸصʌԋȘ˕͐ѯ֊æˤŠҬşŲɀɂӨԶ®ƤіHñ̡৴RfՉǞ͕ūԑÖԫ˪̷­ৃȼüκsԴŴϦ¹ĘʹĩСƨϿů̿î́ყZᦵ֤ۋպԽ໳΁᎝Š׋Ж₭—ŵÏԃϞկ~ԉƝЙDžÿՈŜ݊̂ޒªΰ˚ݶȨΆӘռːϐĘج«ӊʣ̜ɡԚȵԎ®Ǩʶͬʭ߼ǣ֚сՐĄǎΌŔʒg̎ĸៜ["],["@@ɉėɣلͼδʪƘ̀˽̩ǯƍɍλ"]],encodeOffsets:[[[16719,-6018]],[[12736,-5820]]]}},{type:"Feature",id:"ALB",properties:{name:"Albania"},geometry:{type:"Polygon",coordinates:["@@Ń˷ŢέΒȳiə˗ŧ»˙ϷСƛÐgȂү˰ñАîֶŖʼƗƂÉˌθаÂƿɨôǴɥȪďȨ̂"],encodeOffsets:[[21085,42860]]}},{type:"Feature",id:"ARE",properties:{name:"United Arab Emirates"},geometry:{type:"Polygon",coordinates:["@@Ƭ¤ŒɱڂƂ۞uԖ{ֺ֪ظՠՎԮdž˹ŖڑѕGçճƪŝϝǑE΅ʓΏuͷǝDZᡋъ͏࡚Ț"],encodeOffsets:[[52818,24828]]}},{type:"Feature",id:"ARG",properties:{name:"Argentina"},geometry:{type:"MultiPolygon",coordinates:[["@@ߗ§ѓ̔ԑx࣑@Aሞ͒ϵрؿનԋ୲ȿϙп"],["@@Ӵ؇͠ڰॠ“ƊǷ໶ോۊŷਆاࡾ͡Ŧχࠡ౧ࡒɭ़ŷڔƈނ٢ƎݐжLjфӝiڣۻҩ֟΁ॅࠃ૭ଧȽڥɣࡹT࠷ǽȇÝիËѫ੨ܙŗ׃Հν§Ч߯ઁఛ҉။ǩउĎǰԅǣػƺщԋ̏ࡱř̪͕߱ɗŜ࠳֨ʧҠˆʢѧޛʻڭԹūࡋȣ҇ߏEڃљʋؿؙࠞߦǝ˿ݭ঳Ӄձটލͧ΅Ͽ˔ࢍ֔ӡΟ¨ީƀ᎓ŒΑӪhؾ֓Ą̃̏óࢺ٤φˈՒĭьѾܔ̬૘ěӲξDŽę̈́ϵǚˢΜϛ͈ȝॺ͸Ǣƙ਀ȠࡲɤݢԊ̨ʭࠐEޚَոo۰ӒࠎDޜɓƶϭฐԬࡺÿࠀ̜ބռ߂צԺʥ͢Ǭ˔ඔࣶд̀ࢎĹɂ۬ݺશȱ"]],encodeOffsets:[[[-67072,-56524]],[[-66524,-22605]]]}},{type:"Feature",id:"ARM",properties:{name:"Armenia"},geometry:{type:"Polygon",coordinates:["@@୞ƀǨə͌ƣǛɁ҄˽ʁˋΦɫϘƏl׋̣}΃ӢHżχCʝɤǩuͧʖرȼĄФƛ̒"],encodeOffsets:[[44629,42079]]}},{type:"Feature",id:"ATF",properties:{name:"French Southern and Antarctic Lands"},geometry:{type:"Polygon",coordinates:["@@ը˃ߐĿˆDžɽϣಇÃq҂ŮΎÊǢ"],encodeOffsets:[[70590,-49792]]}},{type:"Feature",id:"AUS",properties:{name:"Australia"},geometry:{type:"MultiPolygon",coordinates:[["@@ߺ́ҜŘپNJԎÉÐঽ˽́ēگ̉ɰ׍בǧ®ԫ€ԭܘŗֈӝܸtϬռõ"],["@@̢ڇբ̈́˦ΡЖ͟đϋǴܛŸнɄĹɬܕąѥ˖֭࣬ѭצЋ֞λŋȯӔՃࣧ͜ͲȂ;ηȴźƢࢹ׬ԩϸ͋ڀڹʀڭtӏËԳА܋µݓơϵɩݡjӕǕ׻χއثЭ̫ٱ˫гʝܧ͕нɅػʼnׁªˇӕ̇व‰ޡ·ϫ͙ԕέ۟ψԥƪżѬҝǃ݁؉ܩɪӉƄӑÔ߿ʐիԮƻْțьЭ;߱ĸˢРȯزЧ׉ݝƷѮҬŶӞ͘ЬãجہܑԿ˽͏ڛٽΊ~ҀԿ،ѹ̀ǂȘઃԚןz߯Цຓāછ̝ख़˫ߡÈࢻљܯȗljѱ̳Ϳ܉qՅõݑƶ׿ğֽԁ҃ʕœуʁЗˋؕ֛Bࢽ՜ҋDŽlӖкŘƚȒ‡̠ĺאģӼѻࡖƏӒ˜ӎͭնsʚϋͰĽڄӓڔřΪτε˳ެиʑʞ͗aјеڎă˄țʦĠӠǢȸŘрęӮΎ؀Úٕ΢׀ۀˬЦΪٜ̰ϤàɴĻڎ̺ԚĤŶȀɞüҬoࢨʖҚώɊ҆ӲѐœͲvҘט܎ΠܩΦǚ̗Ј˂ТψǻĸٖҠаȮͨцƜ`ɼτĭdɂτŦОŔبϫҲӽՂMՖÿDZҦДڪϜɘſȾκӒԘ̒јıۺǂeі؛ˢ҂Ū֎ȻҀ·ۼɋʈĐԶʵӬʊ͂ñȠNJϬеɡ͉҇ͻ˿ƒĮͱʙп̗ЭÔʁڜҫ٨ˏѠ́؈ӻʂBѰɍŶʷߤ˵ֈ˼ǐҊǠόľҤʰڞŝОÔʔīӔŌنLjǠŽˬȮѾdžҦtʈ̸̾ʂЩÎՃȾķ˜Λ̨ёÚӇ‡̥"]],encodeOffsets:[[[148888,-41771]],[[147008,-14093]]]}},{type:"Feature",id:"AUT",properties:{name:"Austria"},geometry:{type:"Polygon",coordinates:["@@Û΃ӁCǎǻ˧էLJƗܽsщȏۛÞயɐȉ̊ࠧƣĭDžԗŢѕxϝƶźȴƬʪ²ьɹŤɜݎ•׸ƮЖ}ˀǣþƜšո̠ń̒ϰز˓ӀΆ̐ÚٶʱЂªϰǁãŃČ̅"],encodeOffsets:[[17388,49279]]}},{type:"Feature",id:"AZE",properties:{name:"Azerbaijan"},geometry:{type:"MultiPolygon",coordinates:[["@@ʞɣψDGŻ΄ӡֽŒщϰƃ͆Ǫv"],["@@ϊËƞɈԈͺѴѵђ׭ϺŸʸɧۗãƣٵƟ̭̍ȝvзȽ¥ԻѲ̂дʝʚ̿×যإk׌ϗƐΥɬʂˌ҃˾ǜɂ͋ƤǧɚȶƎضʍҐ¹ŘIJбҔɔŚʀ…׀ԙ"]],encodeOffsets:[[[46083,40694]],[[48511,42210]]]}},{type:"Feature",id:"BDI",properties:{name:"Burundi"},geometry:{type:"Polygon",coordinates:["@@Á০ɃϢԜßʲӎҀŸͧǸȏT˗ȹǭ͛ѫ̧̥΍Ÿ"],encodeOffsets:[[30045,-4607]]}},{type:"Feature",id:"BEL",properties:{name:"Belgium"},geometry:{type:"Polygon",coordinates:["@@؜áުǪՐοҦȝħ֧ɕĝһܿϦћßדІϷͶϷ`ũ̒ڪǔ"],encodeOffsets:[[3395,52579]]}},{type:"Feature",id:"BEN",properties:{name:"Benin"},geometry:{type:"Polygon",coordinates:["@@ۛįȹ׆žኞǛǦЮ̇̌ʱʞņѶ̀ĨǠξЪĀȀʤˮʘ̠F٘ә˩ȎӽǓͷĘɧСԳʵʳǁՉt՗µണ"],encodeOffsets:[[2757,6410]]}},{type:"Feature",id:"BFA",properties:{name:"Burkina Faso"},geometry:{type:"Polygon",coordinates:["@@ֹɐϽ‹̍Ƀϗǰƥ˦ϙǾÅӦɮΤo˴ښۢŬּɲȴОœΚǢŘɎٴϖdžˀ޼ΒҦŢɀLJՠJáСŔϣӀչ€НॺȏmֻǿʣЩÿǟν˿ħ݁lϳâ˓ƉωÖร¡qӉŘم"],encodeOffsets:[[-2895,9874]]}},{type:"Feature",id:"BGD",properties:{name:"Bangladesh"},geometry:{type:"Polygon",coordinates:["@@i׽̉ŶÆگʉѬµєDžКΕӨޟ’ü΋˃ҳΧǠũƵʃĠ͗øŽۖ̅لƜԒԫɤȆ̪Հ̼؅Ѽ֮̔ږεВ£ô׏ߞřު^Ӟƛϯ܅ϕµʷӍҢѥƎ՞ɶFѶ೯"],encodeOffsets:[[94897,22571]]}},{type:"Feature",id:"BGR",properties:{name:"Bulgaria"},geometry:{type:"Polygon",coordinates:["@@ʎΉ͚Ö٦ſ௾«иɌবȜ̩ؒӴĕѥΏ̫׹˔ӏܣŒࡥ˃Uлޅÿס̊ڧɱة|Ñ֊сːƒŢĝĴƘˌ͌ˀСδ÷̬ȸȐ"],encodeOffsets:[[23201,45297]]}},{type:"Feature",id:"BHS",properties:{name:"The Bahamas"},geometry:{type:"MultiPolygon",coordinates:[["@@ȵ£ɇӜ̿ʐǾՔʨ‘ۣ̎Jӥ"],["@@ࣷƅÏ̴Ђäֈ{~ɕ"],["@@ƟׯƷņ`ѮϓͪCĪڐϗ"]],encodeOffsets:[[[-79395,24330]],[[-79687,27218]],[[-78848,27229]]]}},{type:"Feature",id:"BIH",properties:{name:"Bosnia and Herzegovina"},geometry:{type:"Polygon",coordinates:["@@̦FȿσМ͓ūЃȡ™ƽû˙țūҥݓ͈ͅΘ͋Ȅϭ̾ǻʺЩϾǬΒ̞ȕǼǨϾnܠƓ׈\\Ϟȅ"],encodeOffsets:[[19462,45937]]}},{type:"Feature",id:"BLR",properties:{name:"Belarus"},geometry:{type:"Polygon",coordinates:["@@߼Mࣰ̈́ȚӄېːÿϔԜƚ͖ࣘࢮɁŢȻѲĴࠒȧĊЁǷɧՄս΂Ƴ»Ʊ֦Ʃʎɡ͝ǿڳˆljÿȠ˧ȸ՝ܝ¹ʵȁÃхͭĆݷ¡əȞ̿ƥ́ŨڍjफȬࡕàٱmҡɩГeϐʷϴԌǢLͰɷ͌™ϊ"],encodeOffsets:[[24048,55207]]}},{type:"Feature",id:"BLZ",properties:{name:"Belize"},geometry:{type:"Polygon",coordinates:["@@OŮĸžƴı̞ԔDŽZHūDŽGaɭƋεôŻĕ̝ÀăīщǓɟƱǓ̅ʣ@àॆPژ"],encodeOffsets:[[-91282,18236]]}},{type:"Feature",id:"BMU",properties:{name:"Bermuda"},geometry:{type:"Polygon",coordinates:["@@OEMA]NOGNG\\Q^McMOI_OK@CQSGa@WNLVWHFLJXVFGJ`ZRTDLeeWKIHGIK@@[MQNi`]VDTBHCJAPBJLVFjT^LV\\RJZRn^RH`TfJjZHHOTTFJP_NOX[EYQQKMEJOLANJH@HQHAARF@ZEPS[U_IcRQXE@EEKKOCGGCQCOGISKYGUC"],encodeOffsets:[[-66334,33083]]}},{type:"Feature",id:"BOL",properties:{name:"Bolivia"},geometry:{type:"Polygon",coordinates:["@@य़”͟گӳ؈વȲ۫ݹ؅ŗ͡୆ҋऺˆ߾ѳ΢ŏ؆ЫֲՌ࣢αۺȖ˰ƭ̶͠рh܎¤נǸ˶ܩഠزíѠnȈʪ݀;Ѷ͂સƚęؽļ͓ãࣰ֛ݫऴƑ̻ͦ֨ǕΐʑՈTӦʟšӟǐʕZγʓa͒এྖ“ūӟĜͧҞɽȤԹƫڋɯρĄӏʿǥaʶ޳јޭ^ัʓЕ݋sҋͥ৕ƉǸ"],encodeOffsets:[[-64354,-22563]]}},{type:"Feature",id:"BRA",properties:{name:"Brazil"},geometry:{type:"Polygon",coordinates:["@@૮ନॆࠄ֠΂ۼҪjڤуӞеLJǒӜŖӼBҦ̡ƴ̿Ƌ̻œį͔ýޔƿʤ֥ɪ΃ǏࢱLjÈଜʝҴˀǦăӐɰςƬڌȣԺҝɾěͨŬӠྕ”͑ঐʔbYδǏʖ™ӠӥʠՇSΏʒ֧ǖ̼ͥळƒ࣯ݬä֜Ļ͔Ěؾષƙѵ́ܿͽȇʩџmرîӃƟϡĪÈ౨ۏӷݏv҄ͅ֏¶DzΰұԞΓݴɜƶA΢ԖʎċҔɊ̈Ôϼ०ֲێNJŔŴݴŸϚᘰpθſӔύ̬LؐӀƒǚē†͐ӯĔYՀ࿖k˦̂ɸˉǐӷǂļҨѻٸÆnjʲشȞΊƐĮΤ׸ʆ¯Ǯ܅ðśՊ’֞ϓɒǀþجŅڜȿʐȤ؀žल̮͎̾ŏʂѪšȜȗʼnσ̀ŵȖϷɷ̏ƅ܏ɌыÔϳԬϿЮ¥Ģǒˆ˜ϠƦ˚ɢҬíȲŠҚçøǢƗǘĎʐͺõЈĒӔDZξǥʺɪȊ•ŘɿДÒ͒͊ʴؤӼޒ˺¢ȺҫҼ฽҈Ƒxׅمەʾʩ๤ƁŠࡃٔր੐̟ඊԡШӱƏҫ঎ʶ࿐ѹఴŽఔ۝੸व٪ʏܖ‘̦˅˸੭Ɣԗͯ൹ёշஅୡՙोثܯȿgɻءÒ༽ɹಓęօˇͧƫ૱࡛઱ƛࢁڹηȟԋ࣯Fೕ͓סύवʗ঩ڝ܅࠯ũطƔҫƽࡓȏЧחҥट๕݉ڗ֯Ͻϥߛ։ӑɷӈψЊӟֲڇҬࡹՠ̹{ࡅٰձę"], -encodeOffsets:[[-59008,-30941]]}},{type:"Feature",id:"BRN",properties:{name:"Brunei"},geometry:{type:"Polygon",coordinates:["@@ͬ̾܎Ң›Я·՛Б€ǭ˹ϥѦ"],encodeOffsets:[[116945,4635]]}},{type:"Feature",id:"BTN",properties:{name:"Bhutan"},geometry:{type:"Polygon",coordinates:["@@΂ˍÏԩۇ{ۿÈՇſޅ͊kǚ֌زҒɈ׸șѺqπɥ"],encodeOffsets:[[93898,28439]]}},{type:"Feature",id:"BWA",properties:{name:"Botswana"},geometry:{type:"Polygon",coordinates:["@@ǜƭ˄ӡॎइήĝD̑ʚՑٰŹ՚ϝ஑أݭع˩֓ʧ́ҙãƧГďʽ՝țہ¤БɾΟĸХșȵГЉʧпϑ׻đȇ̐üԠӽߚɧŲAរࠤˆ|Ჾش„ಖ͎̎΍՜ͤʮDӂȎưÙ͔ڣ"],encodeOffsets:[[26265,-18980]]}},{type:"Feature",id:"CAF",properties:{name:"Central African Republic"},geometry:{type:"Polygon",coordinates:["@@ۜÚƺɎƔgȾȏ੔͐Τ͠Ѭ̌ĉ̐ʂüߺ½߆ϴ؊ࣺю;ՐƜĪΫӜԿF΃ƋΓÄʻ̆ʍٖοҢͻT˗֠ѫΖεɆԋغͩƊˉˣęաpكĘ̹ïųȱ˕}ͧDzधнϥĎŗÝʥԕطǐؙĊ՗̴ۓ˸҉˓͛яùדգ²֩Ƙԅѻѯޱėʐ›Ϧϧ˔̳Ѡï̠ЇѮæʢċΞÞٴȬƴц࡜"],encodeOffsets:[[15647,7601]]}},{type:"Feature",id:"CAN",properties:{name:"Canada"},geometry:{type:"MultiPolygon",coordinates:[["@@؎œުxЯ΅̵Å੥Φȿˬ͆ʸ̎С"],["@@Хcઝ˂ޯІ̄î૆Ɂ࡮Η|Ʒ"],["@@хŝൡϢʥ̘ݩ̌Ưʈࡻư͕ҜðȚࢨǿԨŵ߄ė˺̃дЋ࠼΍Όҩ"],["@@։ܿո˴֠ǵ̏̉ݚɱϰȴ࠼ʵʹ؛טƞņѿʼԷΝ݉ϝ‹փǂǾیɻńইܯԅ†צЂ߫Ȳࣙ¹࿅~ŹʠԼ̐λɬ۸Ԓࢄ೾Զӎܲ̂϶™Njɫ҅Չ"],["@@@@@@@@߰äʥ॓ܶگͯDԑϪ̵ϮчʾƻτºˎЂŋ"],["@@͡ѳχîəʢ Î͖ʦΆkɈǣ"],["@@ঝҧץnǿɪزϲ଼SiǍ"],["@@ƼυјżӨɗं˽४ʽöЍؤÞ׶˥ݙ˃ಳȬҽϚ࠭ҁ஡ѣ˿Ӯଗăܴдņڌ˺ޔ؈å"],["@@ष¥ȿЪΦҼޖŜپɷXέħřձʛ"],["@@Է̍ଉʬۃğଫϘ݊ʼטζࢼʃԎƯʦDžԠ͍"],["@@G࡭૰ڄ৐եʡح߾֥࢚؈ؖܨ°ईஞÝఔūૼй¼зس҃פ҇ŃУ࿩חୡŻࢃʨʣуߵ۽ʓοই֩ளÇڏΡÇձ঍Ŀਉڻ࣭ु͙ڏ±উంƕϜ޻ϼّ୲ǔ༞εࡀ͋׺Ѕ੆ɳࢸΟ൶µࣴąƍܫʼࡋ،ळనߗ٨˚ҔࡺѭೢףѶഎЀ॒לҮהç֭֘܌৷لলࢤνݾ˫ಾגȘ෸ɫࡸć۠ɚ޴˵ਚӣʮ͙ຄÛ}۷˪ਜ਼ގſ،ӵ௖Ұߦऔ֌ϸٺݣબੳघ৙͵Յ૤Ӂݰӓംɏբˍͬ܃ټŏͶͅÖऻ؍́׽̏൯̗੏ۑ෇ƋᅛǮుPࢇÍ۱׽ੳω௉૗ॵޡ܌Ɛഘૄᄈ۪సČݔЫߍ֟ˊࣟ˜هતп൸ŨࡆीÎ؍ժ̥ਣսᇷԁ࠯ͽय؁ٓ֍܆ฤ۞഍ƒणĹջӆBନύʐ֛ƛ˧ɚٙىʱٹ̕ϡΥŽˏ¥čȹ໽A౥MϛƷࢵ؃Ŀßˍ͝ޗBࠛGϛƅƊǑøʯeďષлࡽſউ҅Ɂ@˷ƂĥŦnĔȂ̎ЂҦʘӺǙܴǵނ࢕ЂľƬūĺɳ@ǛƆ¥ȤǍēɥ€¾ĊȡĊćɚٵːڹ˪ࠑ͘߁̨ݧʃ˝Sਕɔڻʼnࠁʺ࡫Ɔו¾ʻƜƫҤ˳IE͓჏BᮝA᭯@ᡃ@ᠿ@៙@ᢡ@ࠛ@᠁@ᛷ@őF྽ࠜ׵δຽΐҳݖŤԨ੻ΨƧڴ৭؎iѠҲКwՌෙ՘࡭ॠՁ׾ޑϚ֣ΈѿѢࡇ˕ࠇҹݛւדπࠋɸࠟ|JⷎNᷲ༬ȭ೘Й࢘û݆ΖৰˀఢĹ఼τ൘Ⱦ־ΑظȠȊЄ׈ęෆݫ૦֬ŖّਔƐ͆ʖৰ·౼Λዸ̭ୄƛࠖÄଊэ஁зຶǷᗘIJܒƦࣆԋࣴьࡩΦժ˼৾žڦĎڴȩࡊҗरä๢ϛಬƄ௬oĭԺݞƦದ˵KߑՖڠڰuϞࡊ࣑԰কͺäघশ؎ૌƇࡘχଞॅݗЭ༠ǝ"],["@@нϿሎʬୠщॊіސ˟یࠛфΒ׭ࡰ݊Ŭ࠲Ƈश͹ՆࠉʼץථеະЉĝσൡã՚͓˱ູ̯Ƃฃɪঋ»ཅ˷ᒃű๻āҕІଫɮݙģਛږ֔ĚಘƜஈ›રƦྷȞᅗã஗jѷ̴ዎͲಗ[ืɚ۶ـגͮᖬԠ࡬Nj"],["@@݉ևಹך˸Ş૸’ٔȁ"],["@@öɵࢿ|ࣟjࣿőʑ¼ऍѾ˜̠ИÈነěชң"],["@@ڎԽޤڴᒆΈ෺ࢅůջဒʒߒͮሀыୄЏŊν༚Ȑ࢘՗᎐ܸͩ͹ߐ޻໯ϹጘչೲȁீޙೖÇʽכ้ঋਗά೓߲ઙĿŁӕࢪӥଜϯΌɟմࠩ́׿੕ɪᑏڨஎܣ࢔ԕƎ̉ᗱͲᅩӤ৳Ц̌ʂయќ௥Т`ʑᝡƅ܃˾ֆؤ཈dႸņ˫̜̊оચࠊɳϊ͕˾౿Рၳ˺՞ɆࢷԺ݋´ڏ˸҇ʛ຿ŅᵝȈᄫʚഹŴۥ̐࢞Ϧ஝Hˉ࡚٦ݨࡺ΄ᓪɢأի"],["@@৊ǯຄńɖʑ޷Е౜αƱݳ൝͗߳ê׉͎ᐡٮjˎ႖ĽएռসР"],["@@࣓عय़ŒԽ݆`кѮΨ࠰ɮც‡ྈȱళݟ৉Ǎ"],["@@ᕍЙѷςኹѺήΤ׌ؘܰւࠑԦᭊƀ஬ǧᒰ±ࠄʑࣖΝ੍ɃᏝןਫי@ν"],["@@ҙ͙௝Øৱɖ҂Ϛீɨܼ̬̍ˇ"],["@@ٞϵ€љϣس൱đࣗƈjӬ൝ÝÁٮࣜౌ˺ஂµÜŎ"],["@@̙͢ݠƘࢢ™ƪЩԝЋ᭗Žᑯη౩mŅ˜პϊ④ij୯Ʈପࠐ߈ɾᛄ˳๶ӻฺÛறߨޔ̪ࢄĭ˲Џ"],["@@ढ˓ကFܨˡȑ́८ȍՔȧଊ™௬ë೸ǼႊðീÏ࣒ͅȊ΍ԽɟభǷ੽ĸᜱŻႫcഫļᖁ˔̃ҦĹжࡇξ჋ĺঅʼ͂ΈႾÁ"],["@@ŗ٣٩̇޹£༝Ϋ഍ŹଗǼ@@ුؼႮծಆ[ସŬ"],["@@ϣy༽Âɡɼၜ]מƻĵĩ"],["@@༩ʋఝ˔ڼˎ௮Đஈſ˩ʥ"],["@@৽ǏඉBbŤࡴʦҌદǝ"],["@@కǥۃȚέ͂áΎજ‘ӪÅ৐̇ɫ̣"],["@@͜Ε൏Ĥ൩˘ሏŒߺʠ৫ȮÕ͐࿶ŕᗢ̫ٞЍ"],["@@০˕ଽʟ༇ك๥Óდņࣗ΄^̦ڔɢ໡Oए˨ՑϠ׌ώ׊ʲࡴÎοȖዜ¨੶҅මǵ൞ǃڒև"],["@@ᖢßᅮŅ໤ɫ™ɡᏅη᎙ǟݻȉᆬJጡԙേʃ෯ۇႿƓՙǡᡷěୈĿׇƭ۞бߙ˽ಛʃЋ͡୫ʣŞȏ෬lȳᖟԋᔧɴឿŻధĸཟªĿЖ༊Ȑб؆ԢÐᖤγ଩բഹLjڼ͘๰Ȩʄ̊஋͠ΥѠᘞ—ڒĝ಼̪ቃĬ᰽Á๣˸۩ͼগʘȁ˺దLjঘ‚࿲ƌం̺ਬ©ࣤɽٔҒૐƈບĢᢲ–Ҁĝ᝚ƚᆔÁᆒÁ"]],encodeOffsets:[[[-65192,47668]],[[-63289,50284]],[[-126474,49675]],[[-57481,51904]],[[-135895,55337]],[[-81168,63651]],[[-83863,64216]],[[-87205,67234]],[[-77686,68761]],[[-97943,70767]],[[-92720,71166]],[[-116907,74877]],[[-107008,75183]],[[-78172,74858]],[[-88639,74914]],[[-102764,75617]],[[-95433,74519]],[[-123351,73097]],[[-95859,76780]],[[-100864,78562]],[[-110808,78031]],[[-96956,78949]],[[-118987,79509]],[[-96092,79381]],[[-112831,79562]],[[-112295,80489]],[[-98130,79931]],[[-102461,80205]],[[-89108,81572]],[[-70144,85101]]]}},{type:"Feature",id:"CHE",properties:{name:"Switzerland"},geometry:{type:"Polygon",coordinates:["@@ƫŹȳϞƵіwá΅χƙةŀǻ͹ЏơƄһ˵Л¡αǶ˽ςБſ^ϠؚҾɈϤûɲƞ܎MǦǼ࣒ʱ"],encodeOffsets:[[9825,48666]]}},{type:"Feature",id:"CHL",properties:{name:"Chile"},geometry:{type:"MultiPolygon",coordinates:[["@@Bም࣒@Ԓw˧ͻܛʻЭ‚ӻä؏ʨ࢟ŨੑҸ࡫Ҏୃशۘǭ୼֗૜̟ѢϬ˘ֺޠΎװı"],["@@͢୅؆ŘĺɁ˿ࢍࣵг€ඓǫ˓ʦ͡ץԹջ߁̛ރĀ߿ԫࡹϮฏɔƵCޛӑࠍpۯٍշFޙʮࠏԉ̧ɣݡȟࡱƚ৿ͷǡȞॹϜ͇ˡΛ϶ǙĚ̓νǃĜӱ̫૗ѽܓĮыˇՑ٣υôࢹ̧̐֔ÄgؽΒө᎔őުſݝPЙȷݷ̣Ɖ޹Σoॅ˚१ג@@ਲ਼ӔˁՒʄӰх֒Ņ෤Φ߰ࢴٰౣʔߞݒ˸ඊत̏Ѯგ֝ɠʿ਻ՉŠ˂ல˺༒ϮָʍࠎéूΠ„Ԩപ׈എΤబȗ఼ʤۚĵਞӮਆưྺ˒ნˀሤÕ൘ǩ஄ќɌɦњЬֱŐ؅ѴΡ˅߽Ҍह"]],encodeOffsets:[[[-70281,-53899]],[[-69857,-22010]]]}},{type:"Feature",id:"CHN",properties:{name:"China"},geometry:{type:"MultiPolygon",coordinates:[["@@ԑഓΫۏѷ܂ĩخӶࠜڦَϨʡƣԓ","@@ܩЗۏʺyܢаϠࣾɾӚoȊ͍σσșӟ"],["@@ฬˍ঺ׯͼ߃౨Cܰͨ൸ʜѳݱ͙̭˽ः֡ࠇ৵ƪܝ̑ɜܙť঳ѕwLяթӺͯһಙαƀѹܩŒЍ˂ֽ׭ऑҋۃա୭ʑأϽࣝɭ҂ϴǭ͞ږ֠ѹѲܷ̓ॉ׏ԫթ࠙¡ѓϻѸ֩یƏ„ϕڔʕस׶ݚ͝լuƌѱஓɻϻҏࠇућיࣜҥͦࠝԞޓ֮٥_دՅɯȪ҃ӶʻŻۃɇڗҷ÷ؗࣧڹિޭোିޡୟۻृĩԣύ̃˘Ӈй୭сࢵŹ˻ࢱҭ·ə؎Ȧ͘ૻːЇƍࡍɔЏ΀ƄӜޏƶЙܑ̀҃ࠇīڡJ҉ȳѥūŶ॥҃x÷Ȣ}Ύ؝ʓεƸر͂ʔۤՏǎȧޜࢱƓĴাߔۮ”ۚ{٠νȨ˭ӶӭÙࣟŲ˴ΜϿԺ׳Ν۵ȸॷ՗އسڳĿοɦѹr׷Țґɇ֋رëڌԟǭওĈोȖڿτٵǔ˯ЖҽŦࡓոکʴΑȩଢ଼טࠛՒɽऐ׾ő‚іͭјĐۆࣙঠ൧ͼʝ٦ةϼƫʌųӎˆ͜ԛȔ˟ďɇިʈȔśȠߤЈ׈ǐࢸő͆՜ંIJͮ̚೜ҔŠȐãӐּɔݱฦဘͲјȈ؆ຒဠˡҲϞ¢ࡆۦĀٖ֔͢èɚו۸ѽப̿׆ڱ͕ঙ̢ηূƝଆŝ৪ԻԲġϤޟӲӿऒnჄȉ૤Ŝࠦůఔԛ৮BόʽঐҌബ̈ాŒঘ̒׾҈ך˰Ƌˤˍ͔ѴըӀùࡺǝ࠸Ѿ౲͚؞֊נʆ௠ŐڐĥĠ̘ݿזګː٥̳ࠣžӇŃɏΆר࠾Цو৚̓ஆՎQτݸࢾҲːWҪңȦۜмਰƲ૜vసʡ݈̱԰ࡏ̀α̊ԩ̶ࠕ"]],encodeOffsets:[[[124701,24980],[112988,19127]],[[130722,50955]]]}},{type:"Feature",id:"CIV",properties:{name:"Ivory Coast"},geometry:{type:"Polygon",coordinates:["@@ϣUוǒ՟Wহƥ׍ʍ̯ࠫNjvÞۖĄŀ}ͨΣΚˉÈʕɲǾώčО ʔƄB¸ξÝnjĄŜ̸ĶȹڨȗΎæ˸ǘÞŊúɸųٮOƸʖƢgʎĦžΫȞłΌŰϚǽƦ˥Ϙǯ̎ɄϾŒֺɏɠ஡Ο۷ɕेθܣ›ͧ"],encodeOffsets:[[-2924,5115]]}},{type:"Feature",id:"CMR",properties:{name:"Cameroon"},geometry:{type:"Polygon",coordinates:["@@Ľ°ӻŇԝŒЋÅ൅nŬڒ͟֊ϧƚǟϖɋŦXɶɎתЎ߸ʒRԄӮ͈bҾΉ־˲ĀΔȌͺžь҆ΊǞךDzȊŢѨɜ՚۾ٲ¬˨ĠƲͫͰ‚ˌʂ¶ͮ՟Ê֏‹֏ҜޅҷTʁÏϥČǻЅӸөμƛŠΏˆ׃ſɩх࡛ȫƳÝٳČΝåʡЈѭð̴̟џϨ˓œϥĘʏÓґڛȤڷɜ੗"],encodeOffsets:[[13390,2322]]}},{type:"Feature",id:"COD",properties:{name:"Democratic Republic of the Congo"},geometry:{type:"Polygon",coordinates:["@@»ঙͶŕˑ̗͓ɟ͍ѫǯϷ±ګț͍Oهʍɹ‹ԃŗÝýҟɄϡÂ৥ưޝċѧǘӣӤҹҒ੕ͥĒ૿ƙɣĵʇՙȊχƫষĻࡇɨƫט͝ɲƴìٟࣟR·Ҧ̳ΨٟŠȋѰԣ˅ڧŞ˫ϢՕüϽqµʾ́rϥºԳųιtȻû®ৄ˩̸ÕԬŬԒǝ͖eՊ৳Qò̢ѕG­ƣԵɁӧűȿҫŠˣş։å͏Ѱȗ˖ʋԌȷض៛\\̍ķʑh΋œşʼɊʀμƎɎ̪ǰɚđ˼͐ҜSÄʃ̼ƩӶՄӨШɆːƒ۔θࠆϬўքМĪˌt̰Ǝ̆«ӊŀݖǐԾʦ҈¸Ԕúה͜ѐҊ˔۔˷՘ؚ̳ĉظǏʦԖŘÞϦčनоͨDZ˖~ŴȲ̺ðلėբoˤĚԘۙϘķɤƖϲÅҶDzȦΫ݊֏"],encodeOffsets:[[31574,3594]]}},{type:"Feature",id:"COG",properties:{name:"Republic of the Congo"},geometry:{type:"Polygon",coordinates:["@@̿˾ʩƗͻγۏࢸٖҪ̓֌˾ɂ֦ĺäό҆Зݐ•ʴЈł֒ĝڀЉӺζ঄ȽǘسçɻѢÔξ੘ڸɛڜȣÔҒѰ޲ԆѼ֪Ɨդ±·ԓʥ҇ǏԽĿݕ¬Ӊƍ̅s̯ĩˋփЛϫѝηࠅ„ۓɅˏӧЧӵՃ̻ƪÃʄқT˻͏əĒ"],encodeOffsets:[[13308,-4895]]}},{type:"Feature",id:"COL",properties:{name:"Colombia"},geometry:{type:"Polygon",coordinates:["@@ΫȤЭ˨ʅƅ܉Ŝȱΰƽ_࠿Ӓŕʺ̼ڛтȢ̦иÊΞՆ͐Ѵ̳ȦDŽӦȏސǸɚƃ܄ͻ҄ņТ˔ÑǂʠțӶĺŬѢـהΌĚT˦ƺ܂ӖϸՊfäǪڂéڌъ͞ȊОК̖»ɚɛǍ˱գƕɇп͗ʋʓ̷Ĺ׵ɷӭѢÇņϭȄȁâ͹ij̵ˆǫȸéȨ̉ઊĄӦŃעܡͼĚ؂­ӐĪ̔ƟƱҍȇ˯ß׻ǜ֑ʆʟ†ȉэл̨ȃɠ̋ʰ࠹ǁĻǏӸɷˊ˥́࿕lZԿӰē…͏ǙĔҿƑK؏ώ̫ƀӓoηϙᘯп҂ʣpժࡤٟϾԍị̈ƤҧɝصŀӵࢤϳɐˍІ֑Њɡā"],encodeOffsets:[[-77182,-155]]}},{type:"Feature",id:"CRI",properties:{name:"Costa Rica"},geometry:{type:"Polygon",coordinates:["@@җȆǟǮĬƤ‰ȄɷȪͥǔ́ņÅʖəƮÄʑǗȩȓɸˑĊŗǞLʮŎˆʁŠȖnjŴňֆɝȖŊˊéƔǥʜÇȪDzɈҙ͖ͷЂΩ͗õLͷǪűűıƱëǟ©Ǖ"],encodeOffsets:[[-84956,8423]]}},{type:"Feature",id:"CUB",properties:{name:"Cuba"},geometry:{type:"Polygon",coordinates:["@@ܨÑڊW߄˹̭ͮ޺Ĩ̔ȡ܈ԳԺϛˢ\\ԆǟÕʁئ“ٌ΅ıȟ֑Ń֡¥׃âளą֜Ҷ΁ɔէÈ̃ʐȥӎӃ޵ɦʥǬભž̋ǐ̀ɀࠗ¨׿ѧΏ[ťȳеğΫĂѺʸǼ̤ϞȈіǎَĄȰĢ"],encodeOffsets:[[-84242,23746]]}},{type:"Feature",id:"-99",properties:{name:"Northern Cyprus"},geometry:{type:"Polygon",coordinates:["@@ÐJŨȮ؄Yކʢ֧ΧÔƿęˆLJÙűj¥iĎѾNjVɫïƿ¬"],encodeOffsets:[[33518,35984]]}},{type:"Feature",id:"CYP",properties:{name:"Cyprus"},geometry:{type:"Polygon",coordinates:["@@€ãࡱͿЩŊȟͶЎŒǀ«ɬðnjUÒ½j覎ŲiLjÚ̇"],encodeOffsets:[[34789,35900]]}},{type:"Feature",id:"CZE",properties:{name:"Czech Republic"},geometry:{type:"Polygon",coordinates:["@@ϯǂЁ©ٵʲ̏Ùҿ΅ر˔ӃΰѕȬėΠƧʠؒǾ̸Ⱦ׾ǎɂdžɜīϒĖЊ˓ؼñ¿ɳҘǧŲɒּĥĄʿز»ϮЯʡCŽƯȕ—ÅȑLJ¡wý˹ēϋbšȁ"],encodeOffsets:[[17368,49764]]}},{type:"Feature",id:"DEU",properties:{name:"Germany"},geometry:{type:"Polygon",coordinates:["@@d͗ࡔțS̗ࡢǂҾɰॊͧІˋȞёɹɣ̨̙Ⱥ҅ß́Έ՛ϑĕɛĬɁDž׽Ǎ̷ȽؑǽƨʟĘΟіȫӄί̑ϯ̟ŃŢշýƛʿǤЕ~׷ƭݍ–ţɛыɺʩ±࣑ʲǥǻ܍Nń״ьֺ௅ƸЇɘ´ςǗȐĨ֨ƗࢢԎ@Ɉ͂Ⱦޔƿ˴ǐDz۰°Ƽȃ֮вȓ̀ӈٌōՠŸ"],encodeOffsets:[[10161,56303]]}},{type:"Feature",id:"DJI",properties:{name:"Djibouti"},geometry:{type:"Polygon",coordinates:["@@ȤʹΑӏȩήɯ̱҇ȅƬȭÏҷb_ʮßɶ˴Ѐ̐ϊήñʪȴ"],encodeOffsets:[[44116,13005]]}},{type:"Feature",id:"DNK",properties:{name:"Denmark"},geometry:{type:"MultiPolygon",coordinates:[["@@ԋڹ࢟ӄŝΒ௼˨ˎу"],["@@ȵ̓ʡĞ؁؁ɮХ՟ŷًŎͽҲ}࡬Ɣɪʌʦ݌À̐ɴڮʂƒѝʟ˙ĶɽҘŵ"]],encodeOffsets:[[[12995,56945]],[[11175,57814]]]}},{type:"Feature",id:"DOM",properties:{name:"Dominican Republic"},geometry:{type:"Polygon",coordinates:["@@ŀƞپIӾɏɜtƴ̕Ҡhʡϐ‰Ю̷̯ͿЍǼϫ•ˡ¢ƱƵ͑½ŷȲˣťͳֻɏƆ§ʎjɬɍʦȲƚÞ͒óҜ"],encodeOffsets:[[-73433,20188]]}},{type:"Feature",id:"DZA",properties:{name:"Algeria"},geometry:{type:"Polygon",coordinates:["@@ᮩཽᝩ࿷இϑटćU՘ϵƌԹʊȧЀᬻᆴᬻᆴṕᎠfnj@ÊQ঺ബب࠼Ÿێɦ͎тচͪ˜جӢòϞ̶સƚƸ͜ɛDz̃ࢲ¹Ԟ́ՠ߰ҠࣦƢՌΎ߶ʰ෎Ƭർæшůߊͨ࣌P΀ȝֺ¾ǟћƄߟȡۙԭҵôمۊԃRȯԮ͹Ϊຝ˖ݏ°ϵƧۇÔϥŃҟòՇͫΗӺؓŽέ̘ҵϼƸڒϷςՃ"],encodeOffsets:[[12288,24035]]}},{type:"Feature",id:"ECU",properties:{name:"Ecuador"},geometry:{type:"Polygon",coordinates:["@@҂غǻξ͍ϵԉςǞʀƙބ̎ŴƺԼ͆զÍ΄ҢǸ׀Ͱࡀӑƾ`Ȳί܊śʆƆЮ˧άȣŞٓʽճࣷ࢟য়ͧԥܵǃ֣Ӆ΋ΙъͻĞ΍áw̮ʈȨıΔ"],encodeOffsets:[[-82229,-3486]]}},{type:"Feature",id:"EGY",properties:{name:"Egypt"},geometry:{type:"Polygon",coordinates:["@@ɽͷǹىɫѩȝƥ˩˔ϛϒ׵ஸđùΐࢯԪࡋٌವ̴ҙ˒ӃݮछǗƣ‚ճ঒ݭƨǣΏ@Ὁ@⁩@@ᶶ@Ჴʥڲɐ԰Żά̤Ж૦b߲ɝ࠲ʛϴſ٨ˊΌʊݎêװŃɮеȜ˜ڨȣټ³аɄւ෽"],encodeOffsets:[[35761,30210]]}},{type:"Feature",id:"ERI",properties:{name:"Eritrea"},geometry:{type:"Polygon",coordinates:["@@˻˖ΉӰϋ˒ɏܷ̄ͶֻXȭǬӯȡԛϢʽط঑ǬęʹβఀĊ֒ˆʴؤƐьӒӦঃɴޗҢУବߏҲӍҖӝˀ˿аʧʩȳέò"],encodeOffsets:[[43368,12844]]}},{type:"Feature",id:"ESP",properties:{name:"Spain"},geometry:{type:"Polygon",coordinates:["@@¦״΃θஒ؆ਊƱ૾NࣂƝۦªമƒͰ͛໺ϡ̨ǺीϝআŊ®ӥߓ֓ઁǯõ˱ԩү͕ہ͞ӑӟϑǹճىǗש٥੧_ߟhՃ͍̓ͅЩê̵˴ʃӚ޷žé˦̶̀Śɬ̃ʢɶրͳԌδè’ЈƎŬZپϲɪɻфөˆƝŁӹCɁЬ΃ū̥ɇ"],encodeOffsets:[[-9251,42886]]}},{type:"Feature",id:"EST",properties:{name:"Estonia"},geometry:{type:"Polygon",coordinates:["@@ĮӸ̱ŁՓ̘ñӘਫ਼ɼ੔Ũ࣮Ƒࢂ|Ŵƣׯӝʞ޵ΫˉۙDܡ̸ρļ܏Ʃ"],encodeOffsets:[[24897,59181]]}},{type:"Feature",id:"ETH",properties:{name:"Ethiopia"},geometry:{type:"Polygon",coordinates:["@@ԜϡӰȢȮǫּWܸ͵ɐ̃όˑΊӯ˼˕̏ω˳Ͽàɵ`ʭҸaȮÐȆƫǽ̴̕ҧ̴Й̛͎ᩨঽۺNᛛᡃફ™ݟףաeɯ˅ַB͹˴ލΙʝΓ֕àȃĬȟwˇT੟܌ב@˹ˢ@ҾѧƘӻࣴϥȚƧʹэЦԧÒ˸ӐҀrŲʰ[ݲʞࢠЊɾĎ΄ήٜԔи΀ࠠƆܠ঒ǫʾظ"],encodeOffsets:[[38816,15319]]}},{type:"Feature",id:"FIN",properties:{name:"Finland"},geometry:{type:"Polygon",coordinates:["@@ūיಀ֓ޡى঎ख़֡ܛݴس΅յఘֻ́ѓޭӟᅡੵໃá๑̯ൃǯӡҞ߿ˠȈࠢСݶАӪނՆ኎࣮֖Ǭē΢ୟЈ˳͜uಒ಻ֲ૩ЪԊɞतѻલ¦ࣘȭߠϊЬ؞ಬ˶઄ͯΡכ"],encodeOffsets:[[29279,70723]]}},{type:"Feature",id:"FJI",properties:{name:"Fiji"},geometry:{type:"MultiPolygon",coordinates:[["@@̂ʍƓѭԳŗҩļąτ͖̀ϤĻȼƐ"],["@@՛ǯŅ̼оǤˊ°Ӱˀ@ЧՕȷ"],["@@é­@ШǨžĽЗ"]],encodeOffsets:[[[182655,-17756]],[[183669,-17204]],[[-184235,-16897]]]}},{type:"Feature",id:"FLK",properties:{name:"Falkland Islands"},geometry:{type:"Polygon",coordinates:["@@৘Ԍ܎ȿԌʹڦϙʥ̋ଋʥϙ̌܋ϙпϚ"],encodeOffsets:[[-62668,-53094]]}},{type:"Feature",id:"FRA",properties:{name:"France"},geometry:{type:"MultiPolygon",coordinates:[["@@ˣ٭ϡǠș֢ǜ̺ը͎Ɯܛ"],["@@הЅќà݀ϥȊñʎjЈɗெƷыֹŃ׳ɱƝϣü‚ɇؙҽ]ϟВƀ˾ρ“ʁʚ̿̅ʯɐٱҖŃĩηݿӅစɬ௧˗ĩԑঅʼnिϞ̧ǹ໹Ϣͯ͜ѢԎdžူࢁࢤإю౹͒čؖઠǾථɏˇॎߌέዠپʨێܾǞŪ̑ϸ_ϸ͵"]],encodeOffsets:[[[9790,43165]],[[3675,51589]]]}},{type:"Feature",id:"GAB",properties:{name:"Gabon"},geometry:{type:"Polygon",coordinates:["@@ࡹࡔ։ۚԙࢄ‚˨ǾˎȲؔǜخ˴¶௢SOৠЌÆԞőӼňľ¯ÓνɼѡشèȾǗεঃЊӹĞٿŁ֑ʳЇݏ–҅Иãϋ֥Ĺ˽Ɂ̈́֋ٕҩ"],encodeOffsets:[[11361,-4074]]}},{type:"Feature",id:"GBR",properties:{name:"United Kingdom"},geometry:{type:"MultiPolygon",coordinates:[["@@҉ֽًǦԱ[ǦҊǥ҈۴–ࣔԳ"],["@@࣋ࣧࡦŘऄIɕۅݯݩࢄÃäĕݠ঱ֺƇԬढ़ʈͧৰDžķ՝ѓʗͲѣݱѯ૳Rෝɱϻǒ։ϿޥĪם͍ҁǘ௼ࢨݪǺOBಽƔʃͰ࢜ʺҡҐdžռఢ÷D@ŮӤ֛Ԯ_\\৵ƨȧɬ̨ϒˡɴҍЇ·߶щє̨ࢆٶھڤá০ì"]],encodeOffsets:[[[-5797,55864]],[[-3077,60043]]]}},{type:"Feature",id:"GEO",properties:{name:"Georgia"},geometry:{type:"Polygon",coordinates:["@@Ųάȿִӟ̲ҭĬ̯ʴĺIJ܄ƝఆƋଦЕƦƻԚƂ޶ǭʴ·Նșɓřвғŗıҏºصʎȵƍଢ଼ſ߳Юࣅ¡"],encodeOffsets:[[42552,42533]]}},{type:"Feature",id:"GHA",properties:{name:"Ghana"},geometry:{type:"Polygon",coordinates:["@@೉ӯҳ˽ݳʑݡʆœͨηܤɖैΠ۸ɟ஢ŗنrӊฤ¢ϊÕ˔ƊϴáÕʿΖџC؍Ąڍɂ̫ȅݳäйɢՓȈ̍"],encodeOffsets:[[1086,6072]]}},{type:"Feature",id:"GIN",properties:{name:"Guinea"},geometry:{type:"Polygon",coordinates:["@@ʃtǡͷʁJǏǴÈͶΗԨɕħǵmɳ³V̮Ƈɘ‚ʔǻΜɹ̜ڥDțǁɵoƝǷīɹ҅σρӼ͛͢ɋŊȿǖħϊūȂʓƐώЦʮeɖƘȄDƄŎï˨ĢĖd˶МU؀ȱȄlÚĤҜáŨ´¶̭ƆBɖŒƔƒɸɇάãɲǺ˖ŒȬŠǚuȈȁĴɳΆΙǣɏ˙ǴĊŀį«ʡʲʍǗÝå˷Ș΍Ⱥڧ̷ĵăśÞNj·νƃA"],encodeOffsets:[[-8641,7871]]}},{type:"Feature",id:"GMB",properties:{name:"Gambia"},geometry:{type:"Polygon",coordinates:["@@ņόࣶzȎȦˊ`ͨȷʼIˢƚǞʏεȋιdέǰ̷ȗƭQȫŝއl"],encodeOffsets:[[-17245,13468]]}},{type:"Feature",id:"GNB",properties:{name:"Guinea Bissau"},geometry:{type:"Polygon",coordinates:["@@҅ΘΝÈȕʀLŸʯǴÁǶѼƌ˦ɦĨ༈•c˵ġĕð˧ƃōȃCɕƗʭfύХ"],encodeOffsets:[[-15493,11306]]}},{type:"Feature",id:"GNQ",properties:{name:"Equatorial Guinea"},geometry:{type:"Polygon",coordinates:["@@ƿŴ़̀െmPয়௡T˳µ"],encodeOffsets:[[9721,1035]]}},{type:"Feature",id:"GRC",properties:{name:"Greece"},geometry:{type:"MultiPolygon",coordinates:[["@@Ҡ˱ٺ¶شÑqƣҜĶĿʛ௃íTƒਁǎƺΦ"],["@@ʹՁȥĥԟ|ѫĀৱɓ׌ҿяƋҳAѻўƿȁȊԅрЁ̓ǿҴϯжʑ^ӅޥɠʜѕՓĕ͈ݏ֏Yۍμ̿ڦƧ֒͝ϮљӐÉʆϸТ¼˚˘Ũjɚռö͌ȀҖgƒƦdž„ت{ڨɲע̉ކĀVмЦɝ"]],encodeOffsets:[[[24269,36562]],[[27243,42560]]]}},{type:"Feature",id:"GRL",properties:{name:"Greenland"},geometry:{type:"Polygon",coordinates:["@@ᬜԆ᱒›ੴ̴ᲈĄ䀦Ŀ㉊ڗ༅͕ộ™⭏ćшƫᲐĠᡚ́࿈ʴۦ̝इӧᒞ̺✘͚ᠼNjҾΫ⃝ױӃȕ᧑ơወ¡ছؕگկ€ध৚շಽ“൧ˇ༂ѽȢ܋࣍ýઞܡህÑঈ΁˟̑இŽ୥E੆֩\\Ϗပΐћɣଌȿ઼ԣ͈ڱກlj٫͖ਣӘ˼֭উѵᕖ•୆¯ᖯܵᗿڏឧ́ओIࢅ͓ୟࢱᅵכׅ“૧ȷ஽ȝܛԱ[כыտോڧͺٿϗ۝љࠍஅ½఍ۈဿLࠁҢ֕ࠐฝਲэոŗݮ୓ޢ̢ئ֗̒ࠪচొ̺ͨΘǬڀॡ̕қůݯţਏ˜Éְ͢҂ެ\\႔ɟ෿Քݩ˾࠷ş۫ȼम޴ԝ̺ڗ׈ৡࢼ੯͚XΚᖷӮᄻÖᖟ‘Ꮕ×ইˌวՈᕂ˄ၚ¬≹ɖ቉΄Ś͜ẊИᶎИ̪͘ᗗ̠ܺͰ᯲ז௢ĚΓϘጲɜᣚƂᣖRࣺʽᕺҨፘ̽୺áპ˙ፅҐŘή"],encodeOffsets:[[-47886,84612]]}},{type:"Feature",id:"GTM",properties:{name:"Guatemala"},geometry:{type:"Polygon",coordinates:["@@ћƦԻfϩǖҍΌrʖĮȠšƾКۆ઄Ft˸Ƌ¾ġǺ̵Ț̹ˬϜDBӂ޸BަUOڗßॅʤ@˚ƱòŰʘŃϥ͍ЉɻÏljâǑǧɇȟ½¬ıƿġ˽Ƀ}ŭ"],encodeOffsets:[[-92257,14065]]}},{type:"Feature",id:"GUF",properties:{name:"French Guiana"},geometry:{type:"Polygon",coordinates:["@@͉͑ГÑŗʀȉ–ʹɩνǦɈΪòϤƢή͛ӸáֺѪܠ˸ğؤȥࢸۿƔ·ӻޑʳأ"],encodeOffsets:[[-53817,2565]]}},{type:"Feature",id:"GUY",properties:{name:"Guyana"},geometry:{type:"Polygon",coordinates:["@@ր̯Դյzџ̈́o҈Чͪ̇Ƈݱԛɕ°ȣƹџϊ؏ːAŎӃԢܳȱ‰ҫî˙ɡϟƥ˅—ġǑЭ¦ԫЀÓϴɋьƆܐɸ̐ȕϸ˿ŶŊτțȘѩ™ْ֩ɬɲiϲԬƊȾƾ˽̸ô̬ږӲ"],encodeOffsets:[[-61192,8568]]}},{type:"Feature",id:"HND",properties:{name:"Honduras"},geometry:{type:"Polygon",coordinates:["@@ơˀʭòÐʹŗĞǣÒσij‹ŔʩƈǷǚʛìǨɈáǒÐNJЊɼϦ͎ĔȂƨʊ\\þ垦ϸùϲv˒ĢİĦˎ©ȪÉɘnǖòϨśƄkʲƿʐį̏Źɜɳ˽jśŕ̇ŋɃAȅŃǙœƛźĕ{ŇȩăRaǥ̉ɳƹıđĽʛǞǹɣǫPȟqlЭūQĿȓʽ“"],encodeOffsets:[[-89412,13297]]}},{type:"Feature",id:"HRV",properties:{name:"Croatia"},geometry:{type:"Polygon",coordinates:["@@Ȳ͗ˊʇ͓̓ϝȆׇ[ܟƔϽmǻǧ̝ȖǫΑЪϽǼʹϮ̽͌ȃ͆Ηݔ͇ġƛ߃̶ӣ̢ޑʠ۹ؤǞØϥΞe˲եƄʱγʝˮn̆Šbג…Ƹƚ˸ƍͤgGɼ̈ĒĈͺڞɠˊĻؼέۜlj̼Ų"],encodeOffsets:[[19282,47011]]}},{type:"Feature",id:"HTI",properties:{name:"Haiti"},geometry:{type:"Polygon",coordinates:["@@Ԣ™ܰƁôқÝ͑ȱƙɎʥiɫ֏ƜЅÍԡÔϽƿ҉ʾö˔ޜśيã̢ȈϧθP͎ՋžȌɶ"],encodeOffsets:[[-74946,20394]]}},{type:"Feature",id:"HUN",properties:{name:"Hungary"},geometry:{type:"Polygon",coordinates:["@@˨ըǍǼӂDÜ΄ђɋ̲ğ۸ļäǚͮ~ЦžĜÃЂŀȠȢˠ¼࣒ʭǴĒҲɭÎɣԡǭЉ֫ԕ֭کǁԽš١ə̻űۛNJػήˉļǍ˴ƗV"],encodeOffsets:[[16592,47977]]}},{type:"Feature",id:"IDN",properties:{name:"Indonesia"},geometry:{type:"MultiPolygon",coordinates:[["@@Λe૝ך޴ǒѴʭ̎ʭ»ɩ"],["@@ܙȁijĶø˸ΰԢࠨͬĐǓfʫշع"],["@@̢ɣԲèȼΥॿǛ׉őҍP̀ӚҤPɤ̖"],["@@ūұ౅ʅૣľE̬ښǪՂʥ֔Üݬ̮"],["@@ྔċȂΌ༘З̪կీƵਐӿय़͋ऍ͸ݻwࢍØ޻ưঅ͎؝ČΓŁ໕ΌƣΰޑØּߤ৶·ڴ͡ΒÛŘ̗"],["@@ѝֱćنƬ̠Ǭ˴ȒʗCЏ"],["@@̿˥ׅƸǏΰࡘ¢Ⱦˣ"],["@@̨ٝۿΌۯìӃÅׇˆȦҦਠ”ऎʕ"],["@@ɼയ࢈ԉ۰ࢼ८ԔݜBܘ̉خ̛ࣘLJbᩑbᩑݟې࡟ǜȷʇ੡}ΦۂՈɺɕࣲЕ۸࿃܆ۗêృަʛУ͑óȏ̮GκٛЮ̢ࣞ״gëɠ௵DͩԄݥƺΡдଈȰњ˜ഘ·Ƃ̹"],["@@ڭ࠭كlj߱ǐඓ¥ܽŧţٍݪݛҒϠ༪˸çϯλŪιӯ͙݉ߒ੿Ƶ˿ݲॻQտ҅ʙ̐͡Мی࠙͗ȻɶŊ͖؅ӲØࠌ֕ʭîও”றՓũίʚʌޜŽ߸ΛPʻֺΎվŤښф౎ǮΎ܎ذپʛ੖śॴ–ࠨ؎Ʀȉ"],["@@©ܽџĈŷԝΌѷɽĵ͹Ւʟ੺ǚڤ˨̨ÔҝӸóĀ΃"],["@@सާহį˫ֵšݿַ߱u࠷͕౻ŭ̚ॕϙͫԤ׳´лːৃ̟̩Оս¯ۗĬŹૺнɺЕܘŝ݀ĮުԂ֐Ɩָ֗ӅըǠ՜ÑӪъЖôߒɽۆǶњୠ͔̈̆क़ॲ@ܰƙӍݷآߓơϭ"],["@@छkۻ۰અۊέԚٍۄзؾٕ୴۪݅ʙܠ̳ڀݵՊѭܘمҺࢗऒóђզ‘ಢNjݔࠓٮ֫ҪΓߔࣙࡢ_ۺֹӠ۳٘ϥͳۉӖ̞̅sƜו̊ҵؠõФՏɁ਱‘ಟ"]],encodeOffsets:[[[123613,-10485]],[[127423,-10383]],[[120730,-8289]],[[125854,-8288]],[[111231,-6940]],[[137959,-6363]],[[130304,-3542]],[[133603,-3168]],[[137363,-1179]],[[128247,1454]],[[131777,1160]],[[120705,1872]],[[108358,-5992]]]}},{type:"Feature",id:"IND",properties:{name:"India"},geometry:{type:"Polygon",coordinates:["@@ࣚটďۅͮїѕ׽ŒɾएࠜՑ୞חՑϟ͛޻ࠀͅߊЭરһସʼnӜёٮāৠȝ۪bĪͪŋՖÞβԠǮìڋlǙކ͉Ոƀ܀Çۈ|ÐԪ΁ˎڴŀވشॸ՘۶ȷ״ΞЀԹ˳Λ࣠űÜ͇̍Ʒèԫ׷Ʋછׅ~ӓҩ۵§ХϏۗځȒࢇȏ˹ĚΣгȥѵ೰ɵEƍ՝ҡѦʸӎϖ¶ϰ܆ӝƜީ]ߝŚóאБ¤ڕζ֭̓؆ѻԿ̻ȅ̩Ԭɣƛԑ̆كžەţֱ̫Zਛǩ´ك҃ӻ௃֡ळ঩كՋ࠷ջCϭлȹݳ̝Ͻ«ʥٙǪધ®ۡΣߙI෗ѣ¡ϣٙʰˣދʃ˱֯͵ʍߑ޸ϳ୴͑ࡒ̍Јѿ߰ȻੂơՀޅ଼Α࿀ʣ੾HৰǍ޾௣ԉףĶ઱৲И̤ʝͤড܊֖֔ᇜCǗܞҽюĩ٨ջϘऒࢢঊÙ࢞ࢢՄ࡞ࠄࡈ_״ܒӠڳд֪݂̇̕Ьβ౤ȱपŰߺ۸"],encodeOffsets:[[79706,36346]]}},{type:"Feature",id:"IRL",properties:{name:"Ireland"},geometry:{type:"Polygon",coordinates:["@@ƒ׷ًݣ๯ӹ஑Ŷڼ࢚ѭࡢତڄٌϼǦ҇ǥ҉Բ\\ٌǥ"],encodeOffsets:[[-6346,55161]]}},{type:"Feature",id:"IRN",properties:{name:"Iran"},geometry:{type:"Polygon",coordinates:["@@݈njװӔ֚{τƾװýघэڤğ।ݓظ‰òۻ΁਷ɱؑκŭΫҡˠڡàՓِƙæեݿݿжѵ͸ԓߦυx݉ДƋêϯ௉ѡ̓উཌྷʪࣷȖेŊΧਐЕƪ٣ƭࡑНਇ˦ࡑ٦߳ʈ֗ߘا૪ҍƋՕ˦̻͝ҭѴS҂ˍ@Ɛ،ѝٔ਍Ң׉ߜȜپц̂ÙӬտʨխ৊ҟڨǐʼʿ६ּʈƄͅъϯ־ő̤~রئ̀Øʞʙ́гԼѱȾ¦ˈإߖǩ׎у஠ƟಾɞĄȞ"],encodeOffsets:[[55216,38092]]}},{type:"Feature",id:"IRQ",properties:{name:"Iraq"},geometry:{type:"Polygon",coordinates:["@@րʧÚӫх́țٽ׊ߛ਎ҡўٓƏ؋ˎ@TҁҮѳӿ¤֟ê؝߭༟äᛍၖఫךৡɪ͹৾ᇶ࢔͆৬āؘҢȺјԾΰž঎Ň̐ɉЖƚծ৉"],encodeOffsets:[[46511,36842]]}},{type:"Feature",id:"ISL",properties:{name:"Iceland"},geometry:{type:"Polygon",coordinates:["@@șիॊֵથٙᝓֹܣƵૉŮᚑˈࠠψᆧЪ๪ǎ—ʘᄋȜ֨նౠŰಸ֭౨Ҝ੒ʃൌ҄ආÑ"],encodeOffsets:[[-14856,68051]]}},{type:"Feature",id:"ISR",properties:{name:"Israel"},geometry:{type:"Polygon",coordinates:["@@ƥ˅̣Ŝǫ֓ɂĥɋř—ɛЄŖp͛нഉց෾ʔˢ˶ɞϼǠيŤɆzVˬCþƦɤ\\`·ŕŵhM"],encodeOffsets:[[36578,33495]]}},{type:"Feature",id:"ITA",properties:{name:"Italy"},geometry:{type:"MultiPolygon",coordinates:[["@@̟ڋŲʹǭѝٝ̈́ёĞ୩ѐŞќজûࡪĠْò"],["@@Ԍ׭ş૕ϣÂ΁˫͇ɞ‘২ȓӒҨ¥рʼ"],["@@ரɏĝЯȬΧڝŪہ̗²зĻʇˠё߀чцۛदڱچLȲȃɽǗݪ̥ؠʩܜѫĔƿƽ̛үϼܳƐΝի؈̷ıѫΗ¹҅ܛΕÝHʲǢҊǼǶ͝ӤʱшΑŀʛδգƴεͶثÆٿϜޑմ֯ӜʿࠪйĮہˤϯŕӝϵΓÕĪθҕńɏٲ̆ʰʙ̀”ʂβǵМ¢Ҽ˶ƢƃА€ǼͺتĿψƚâΆԘšĮdžࠨƤȊ̉"]],encodeOffsets:[[[15893,39149]],[[9432,42200]],[[12674,47890]]]}},{type:"Feature",id:"JAM",properties:{name:"Jamaica"},geometry:{type:"Polygon",coordinates:["@@֢÷ҀȫƔɯןeʭƗҹƊӑ̪ĶȔΜÎȒƒ"],encodeOffsets:[[-79431,18935]]}},{type:"Feature",id:"JOR",properties:{name:"Jordan"},geometry:{type:"Polygon",coordinates:["@@Ʀˆपͫ࿪ࣆͺ৽Džų၅у࠸࠿ˣƛƑ˭ٙřȩ̡εʵधƆƒŨоഊo͜Ůʚ@Ԥ"],encodeOffsets:[[36399,33172]]}},{type:"Feature",id:"JPN",properties:{name:"Japan"},geometry:{type:"MultiPolygon",coordinates:[["@@ņ˽ҿԕΉːљțɝӭշʈRЊҬԆӌīΊΜؠǹ"],["@@́ڡƤсѩף੹Ѓ๏½ணॡ͔֡“غษȃষЃঝe࡞أ֗෗իΝН͜ȶݶՏʒͿ־ߐʶѲՈࡌѢ؞ָာʤ࣎ǣࢠ๺֔Б௾ࡀӌ͜ՈਈƟा΢ՎࣀƸҞୗ}ڻޥࡍbࢁ"],["@@נǵרΤȈहఝɯ݁࠱೓ָқँण]ř࠴д٨࣌²ʖ୐ʜټন࢓٤˯"]],encodeOffsets:[[[137870,34969]],[[144360,38034]],[[147365,45235]]]}},{type:"Feature",id:"KAZ",properties:{name:"Kazakhstan"},geometry:{type:"Polygon",coordinates:["@@ӕƹ્דο׹̹KɱЊ੫‚ǡێХNÚࡆ৓ؘ෷ßডũߣݶۋ͆ಥ׼ƽðᓗӹᶽљ£יچ֧ɼॕǩχ˧±ȲȶΖDž̊অ˺ϛݮҩɆ…˜ࠊāŽؘ܎ƎܼűƲࠎƭԲ࠿£܍ȴঃσ޵ǭяƌĐўՙ֘دw܉֬ӞِʕǢڢऊࡺӣŀؘჄࣴಾtᇢ׉঺ͻࢼΠ೰j੺ѥʔʠ୼—ɂЊഷ׀߮Цƿɮ߮ɔ؅ֺϬ˼Ḯ̈ШȺᑆ̴ݰΒຢǹ˄ࢉ࢚Ȳઆ˹éҝ߮´ᑌߎ̭ˁ੶٭ሠᒑ҄ѰୄӛீɎҪƯКӟטNjΨΥ઎ŒѾԣٕ֓ۥÿ¡ࡅұϝဟˢ؅ຑїȇဗͱݲลֻɓäӏԭŬу̠ఝĖඃx̧ġ஥ΞӉǧŽӹ൩̂փşȉρ"],encodeOffsets:[[72666,43281]]}},{type:"Feature",id:"KEN",properties:{name:"Kenya"},geometry:{type:"Polygon",coordinates:["@@ӾۙיͱȹΕ̿Õšףˑ͹Ǐ֑ͷ˥஻ࡀËӤᵁႌƙĢSࢺʊ;а֌̨ؔσ॰įтЉ׎ԬԈ֬ֆѨƗ@ҽ˺ˡג@੠܋ˈSȠxȄī֖ßʞΔގΚͺ˳ָAܽ॑Xᵣ"],encodeOffsets:[[41977,-878]]}},{type:"Feature",id:"KGZ",properties:{name:"Kyrgyzstan"},geometry:{type:"Polygon",coordinates:["@@ȊςքŠ൪́žӺӊǨ஦Ν̨Ģ඄wఞĕф̟Ԯūşȏ೛ғ̙ͭઁıͅ՛ࢷŒׇǏߣЇŜȟʇȓཟŵਡ˘࣫ÝĂӜࣴƕ̮ʸٖĉ੾؂঻ѸױȽإ͂۶ծʟĊ"],encodeOffsets:[[72666,43281]]}},{type:"Feature",id:"KHM",properties:{name:"Cambodia"},geometry:{type:"Polygon",coordinates:["@@΁Ѭыࢄȣ২ՠۨઘdž߀ťۚ͡Ϟׄݖ̱Ȝ֕Ļ৕ඳ٧τԙࢥÓܫͷ۱Ū"],encodeOffsets:[[105982,10888]]}},{type:"Feature",id:"KOR",properties:{name:"South Korea"},geometry:{type:"Polygon",coordinates:["@@ܨযȺխPॷ̓ҥݽljڥΏݳïĥҚƼـχ࢔ذƚֻܘÂúϒ‡͞Ϝצ¢ΨÈŨȮ"],encodeOffsets:[[131431,39539]]}},{type:"Feature",id:"CS-KM",properties:{name:"Kosovo"},geometry:{type:"Polygon",coordinates:["@@›ǣŃPĘ́ȩĐdzɦƾȌȪÒŜ˨ư²Ţşƾ¿ŌƅƒŸǎƻŢLĥȳijij„×ȉӹŻ"],encodeOffsets:[[21261,43062]]}},{type:"Feature",id:"KWT",properties:{name:"Kuwait"},geometry:{type:"Polygon",coordinates:["@@Ǭχõȓ˔هשuȽАݟĆ؞߮֠é"],encodeOffsets:[[49126,30696]]}},{type:"Feature",id:"LAO",properties:{name:"Laos"},geometry:{type:"Polygon",coordinates:["@@˚Ϝœ܆ڹܸ¿ٕࠦھٍÎǛ̉ӯyʣƨࢯԅoݬȸࢮ֧ž³ԎηʸǴ̲ܐնøȡ҄wŵ०ѦŬӮڏϖޅਚO͚ܹ՝ɗʉ̟৔ԉۦ঳Ռ݋َ׏ɄץƵ࠿ݕ̲ϝ׃ۙ͢"],encodeOffsets:[[107745,14616]]}},{type:"Feature",id:"LBN",properties:{name:"Lebanon"},geometry:{type:"Polygon",coordinates:["@@ɣ[ýƥ˫D̘ۄмעfˆϘ§Ɛͣқ̓ȷҟ"],encodeOffsets:[[36681,34077]]}},{type:"Feature",id:"LBR",properties:{name:"Liberia"},geometry:{type:"Polygon",coordinates:["@@ɗQࡽАޅٖ܏Ң֣ըȪː¬ʔϜҘϺϺǶnɖĨΘԧÇ͵ǐdzʂIǢ͸ʄsŸʓĎНǽύʖɱˊÇΤΙ~ͧăĿÝە"],encodeOffsets:[[-7897,4470]]}},{type:"Feature",id:"LBY",properties:{name:"Libya"},geometry:{type:"Polygon",coordinates:["@@ק̷ҿҤ೧βρՄڑϸϻƷ̗ҶήӹؔͬΘñՈńҠÓϦƨۈ¯϶˕ݐШȜðΠėΒ־͔ʶːЦʌ´٦দ́ΜðۮƓ૞ϓЀݛݮǍஆΙࣆйЦɔЖϮț٠˂Ф؄ЀׂŘ଒ǣ˺ϑ̺Iˌƛ࠴ıȲˣ̣ЕżΫɏԯʦڱ@Ჳ@ᶵ@့ॱGYΙ‧ྐ‧ྒࡓҟ"],encodeOffsets:[[15208,23412]]}},{type:"Feature",id:"LKA",properties:{name:"Sri Lanka"},geometry:{type:"Polygon",coordinates:["@@ų࢓ΙʇܵȓЍڜƫீϠ഼׆ұϺסО࢓"],encodeOffsets:[[83751,7704]]}},{type:"Feature",id:"LSO",properties:{name:"Lesotho"},geometry:{type:"Polygon",coordinates:["@@̆ʩʳУƛ˛ҳſƹˍ̛ċؿ٨҄ՐҖ͢ϼǠξʵ"],encodeOffsets:[[29674,-29650]]}},{type:"Feature",id:"LTU",properties:{name:"Lithuania"},geometry:{type:"Polygon",coordinates:["@@ãɊĚɲχƄࢡƨDZ۸२ʴඬÁࠜĊŞǩ҂Ã߲СĀϓۏˏșӃ࣯̓߻NȫʶљĜ"],encodeOffsets:[[23277,55632]]}},{type:"Feature",id:"LUX",properties:{name:"Luxembourg"},geometry:{type:"Polygon",coordinates:["@@ǘȏ³ρʍiȉòĞҼɖŽ"],encodeOffsets:[[6189,51332]]}},{type:"Feature",id:"LVA",properties:{name:"Latvia"},geometry:{type:"Polygon",coordinates:["@@†نЮՆߊ˼ڜعڪhNJ٤ܐƪςĻܢ̷ۚCКȕîС˒ӷ͕ࣗԛƙ߱ТҁÄŝǪࠛĉණÂ१ʳ"],encodeOffsets:[[21562,57376]]}},{type:"Feature",id:"MAR",properties:{name:"Morocco"},geometry:{type:"Polygon",coordinates:["@@ԒΥߜÎࢊȃκU͂՟ºԝ̄ࢱɜDZƷ͛ષƙϝ̵ӡñ—ثঙ͍ͩсۍɥ࠻ŷഫاRহŷ@@@p҉Ա˓ȑϡ@̥Ŋ۹ě˛ٻʿÕЁ੕ୟ࣡ˣୋ΅ϗĵ̡ቅãaD ϶͒ɮ˞ѪÃ˶̀פҴՖ˲ƊɞӬp҂̤Բ̪֔Ւ࡬f\\ц͔ްĢڎָтɠۮۮȿਸ਼͊ܢŔѶդ֨ࡈϦخΐ֘࢈˄ԪؤI"],encodeOffsets:[[-5318,36614]]}},{type:"Feature",id:"MDA",properties:{name:"Moldova"},geometry:{type:"Polygon",coordinates:["@@ȨŮ֒ĊؤʽΊϞɥÑ˵̪ƏŨΗ̊ɇÏűƾčɝ×ӷ|ĉŜǫãÒƭɱˍƥ˽ɁĝƯϦĘΪςӝԂˉΠʹʠʯĈ"],encodeOffsets:[[27259,49379]]}},{type:"Feature",id:"MDG",properties:{name:"Madagascar"},geometry:{type:"Polygon",coordinates:["@@ɠΥȺ։Ɗঢ়ɒϽĉЗƩʙ˷ӰǁʝLjثõΥɵȗ¿܅ͧওб୅ԯཧ͑ୟϛইہȣܻΡӛɊڙ̜ɳѺÇݘ̑ڠù؂Ʈ؄ϰƢD˪Дِø՚șЈǃՌãޠ̊ҺŔՒмŒҶǤ̶Ʋτ\\ӐӎۖԮʦцŗάΦĵҪ׎fԐ˦ϔ̊ί"],encodeOffsets:[[50733,-12769]]}},{type:"Feature",id:"MEX",properties:{name:"Mexico"},geometry:{type:"Polygon",coordinates:["@@͙݅ƥ؁Õ૷ąЧƤқʺЧǚٳ֎سȞӏ͢бࢾɝΐΙ݄ɾٚĎؼưՊƠՖ΂ȨӬè۸Ƣʖ֬ɚࢶȚݔ‡ԚîȬDZ…ЙҋԁȥԝƸƥűγɁٽɅɎǭcǃY̝ԓƳIJķPŭޥV޷AAӁϛC̺˫̶șĢǹƌ½s˷ઃEЙۅŢƽĭȟqʕ्ࣞџ˘ۇɖҷÓګ́чĉץɜؿDŽ޹ϬؿŠ्ϸ۱ВɃɤҹº࡯ˈΓϦࣗӊсՌȧЦ˪ĈđʈȖɔJ̄˱Ϙùͮ˭ъ݋࠴ࡋڀУԼܝ΄ƷȴŸԲѓȞӹФȽהҍæӣѸϿФ™ˀҍو̓٠^͔؇ͬ˫™ӑɴƇͿƔЕĆف̀΋خׁƒȡŸÓŎ˽Ƭ\\ǜթʮɇǴ̕Նё˨ޯʠρɸϿ²ѷКƒͶϡ̨ϑqƭΝ̱ƫJɛԞջӎ؃РїɈ„ؚŵҖЏʺֿϒŏŇɃɖԭȰӷӦÖÚΊ³̸̼ŽϜ٩׶ӱɶ̱Հ̷վϳڦͿݲॖÞ੪ĞÿǑ౔СኀףဪPژ@DΌผ@̪̕јˇԀσ˨ѭȾҥѢʩۤʥՊڒۊhפͱфֹ̄ӯӸӏȂחɾЃپʹ׮ȁ͞|"],encodeOffsets:[[-99471,26491]]}},{type:"Feature",id:"MKD",properties:{name:"Macedonia"},geometry:{type:"Polygon",coordinates:["@@ńOœǤӺżȊ˺¶ϴbтˏÒ։DžƒƑƥҕh͋ǿջõΑȴšήń˸"],encodeOffsets:[[21085,42860]]}},{type:"Feature",id:"MLI",properties:{name:"Mali"},geometry:{type:"Polygon",coordinates:["@@˰ƶƘӶˊpזɻӄǖ͖ÇŴȈ⁚^ȈךƣļЛ⋈Л⋆౾dᬼᆳᬼᆳȨϿԺʉ϶ƋV՗ठĈFካҟ֗íԭݛƃ଩ï̳̗ա՟IȿLjҥš޻ΑDžʿٳϕŗɍΙǡНŔɱȳūֻڙۡp˳ɭΣÆӥ΋ůȝŁŽάʍĥơhƷʕ٭PɷŴʼnùʱʎ¬ʢĿİdzĉ˚Ǥɐ΅ΚijɴȇȂǙvȫş˕őɱǹΫäɷɈƓ„ɕőƅAµ̮žʾí̽͘ʀǓӔԺ"],encodeOffsets:[[-12462,14968]]}},{type:"Feature",id:"MMR",properties:{name:"Myanmar"},geometry:{type:"Polygon",coordinates:["@@ӫηץ›ϥࣥΟƳО݅ՔؗΈօ̭ܵ̃ƹȪу֖ڙĪҷ_ϵ͠ދң޵Сࡷăذʴ٠˯ӼæࣸͽѤ˛৔Ʊਗ਼εۢօуॕ׳ҽöԳȠ̂ਪǫ޾څॺļ̢ӭņ׭ۆÅڰ̊ŵj׾дȦęΤȐ˺Ž࢈ڂȑϐۘ¨ЦҪ۶}Ӕજ׆׸ƱçԬ̎ƸÛ͈ӮÚˮӵξȧ|ٟ“ۙߓۭijঽࢲƔȨޛՐǍʓۣز́ζƷ؞ʔ~΍܏յdẕӓȗ"],encodeOffsets:[[101933,20672]]}},{type:"Feature",id:"MNE",properties:{name:"Montenegro"},geometry:{type:"Polygon",coordinates:["@@ÁǀηЯÊˋǫÞɽ˞εǖĢƜŬҦ˚ȜƾüɠƟŬśˠě͌ǧçïƽȋɧó"],encodeOffsets:[[20277,43521]]}},{type:"Feature",id:"MNG",properties:{name:"Mongolia"},geometry:{type:"Polygon",coordinates:["@@ࢮƢ྄ܤ౬Єܴʳ࢚]֘Ͻ࠼‰ௐɁࠈגͿӶࢊࢊश΍ނįনɍLjؿஜΛߐƺਫ਼ŌࡆōࠖЗԚѕެT੒Ƌޜȼૈƒ௸פԌĝѰ˭ৌêХهק࠽ɐ΅ӈńࠤŽ٦̴ڬˏހוğ̗ڏĦ௟ŏןʅ؝։౱͙࠷ѽࡹǞҿúѳէˎ͓ƌˣי˯׽҇গ̑ఽ‹ഫ̇এҋϋʾ৭AఓԜࠥŰૣśჃȊऑmӱԀϣޠԱĢ৩ԼଅŞুƞ̡θ͖চׅڲன̀۷Ѿəז"],encodeOffsets:[[89858,50481]]}},{type:"Feature",id:"MOZ",properties:{name:"Mozambique"},geometry:{type:"Polygon",coordinates:["@@لæ৞ʁɖńגt̚ʦԌaऀ͜ڞӤƊϕ“࠷ľ݅ಿƨЫʣ׷͙׍՗Եޏ͉ृСॉ͓ࣕƵוׯ΋ȗí׳ЌُǔӱZʣƪ¦{ࠗƋϷȤƝűΓΗ̗ۗ˳য়ҕρ̳ðΟɊÉíѵّRïϊůϖí̠ƬपɓװГஂࢬ॔ɜ؆ŶúĨӶƉʞ˜غǐ׌E੠ѥ˒ЏÔǹȼϳǰ۫gÅ̼āװᢈۘӚЕɴüͨɅ¸͵ǯϷØסոԱʲ׌ζǰíઊΙ؈̣˖̅]ɽદɾٔ"],encodeOffsets:[[35390,-11796]]}},{type:"Feature",id:"MRT",properties:{name:"Mauritania"},geometry:{type:"Polygon",coordinates:["@@և־ԗؤ֍ɞГʚҵUЧǽйð˽ˏïҐɺаŀߊģࠨĵкČмɑЎѵδǾˬᾔMǃ௎ȴќ߀øᒸ᪂©F౞Ṗ᎟౽cМ⋅М⋇ƤĻȇי⁙]ųȇ͕ÈӃǕוɼˉoƗӵ˯Ƶ"],encodeOffsets:[[-12462,14968]]}},{type:"Feature",id:"MWI",properties:{name:"Malawi"},geometry:{type:"Polygon",coordinates:["@@ɽٓɾથ̆^̤˕Κ؇îઉεǯʱ׋շԲ×עǰϸ·ͶͧɆɳûәЖѵɔʮޮ˄̈LJۢǚڼƞɪɉ܌Ѕϐ࠘ƽǜɵ˶Ϲɾଡ"],encodeOffsets:[[35390,-11796]]}},{type:"Feature",id:"MYS",properties:{name:"Malaysia"},geometry:{type:"MultiPolygon",coordinates:[["@@àћֈĶ˞ΈȘýӸԓΜ֛¶֣ęϡĆ˿Öӻ̒ɵͤݑe˳׫Éߑخ঵ښįђӟ֚ś̡۠ҜĠؔȃΤƤƮۈρ"],["@@أ˹ܯƚॱ@̅ॗ͓̇љୟۅǵߑɾЕóөщ՛Òէǟַӆƕ֘؜˽ٮǀǜ܆άǂ৖Ǻ׾ڔЬՐϦѥǮ˺В¸՜œа٪אшڀͼHќыžιֆɻ۬ʧÑ֝͡¥ƮЧ"]],encodeOffsets:[[[103502,6354]],[[121466,4586]]]}},{type:"Feature",id:"NAM",properties:{name:"Namibia"},geometry:{type:"Polygon",coordinates:["@@رٌؖ͡ȃࠊȷ،˯ಒm৒ŅҞ͛Όѡۜѳ৘ǽՆۃࠐ»٢КdžԊƞհ}ԄϝŶÐ₮˜׌Е᎞ş໴΂یȒհµͨȍPéӁȍʭC՛͍ͣΎಕ̍سƒ{Ჽࠣ‡BយA᷋ݣѕҋÕՇDŽϗÔƗάͩɰГг"],encodeOffsets:[[16738,-29262]]}},{type:"Feature",id:"NCL",properties:{name:"New Caledonia"},geometry:{type:"Polygon",coordinates:["@@ېԵѨϭ͉ȫҥɪ׹ϚէѼ։פś˶β[Һ˹φ˷ˎɻ"],encodeOffsets:[[169759,-21585]]}},{type:"Feature",id:"NER",properties:{name:"Niger"},geometry:{type:"Polygon",coordinates:["@@nּॹȐОҿպœϤâТբ̴̘ପðݜƄîԮҠ֘Eኬஈϒᝪ࿸᮪ཾ೨αӀңר̸ȸಯ̾ɓ`ˋΔ˽ǻί͕ၻ«ધੳߋγૉΔ̵CեբmčЃʁµˋƻm֩ंȟ’ځҷٱʔҍ¸ʏşӯ~ӷΧѓq৯ѢЉȵѓb̿͆ࡅ̼ࣗıɕǻşӗʋ͹ÍݣٗӚ̟E˭ʗ"],encodeOffsets:[[2207,12227]]}},{type:"Feature",id:"NGA",properties:{name:"Nigeria"},geometry:{type:"Polygon",coordinates:["@@ࢍ̡͉¬͓ȉڥl҇Ղˡ؊שֆكYݍB¶തs՘ǂՊʶʴТԴėɨǔ͸ȍӾ˪ÎݤʌͺŠӘɖǼࣘIJࡆ̻̀ͅєaЊȶৰѡєrӸΨӰ}ʐŠҎ·ٲʓڂҸȠ‘֪ँƼnͬͯğƱ«˧۽ٱɛՙšѧDZȉǝי҅ΉŽыȋ͹ÿΓֽ˱ҽΊ͇aԃӭʑQЍ߷ɍש"],encodeOffsets:[[8705,4887]]}},{type:"Feature",id:"NIC",properties:{name:"Nicaragua"},geometry:{type:"Polygon",coordinates:["@@̃ˆϽͺȁ˲Ο˄сϜĤžƒŵÚÒʾ”ŀȔŬRkЮȠrǬOǺɤʜǝĒľƺIJ̊ɴbǦĄQňȪĖ|ƜŹǚ›ȆńɄB̈ŌŜŖ˾iïă§ȉĐ̫ȗ˹ěͷυ®ɏtϙŹĉýΫÌɛǣɋ ɩźƏȩDZʛÈƓǦˉêȕʼnօɞųŇ"],encodeOffsets:[[-87769,11355]]}},{type:"Feature",id:"NLD",properties:{name:"Netherlands"},geometry:{type:"Polygon",coordinates:["@@ۦyǀ˳Ƚޓɇ́ԍ@ƘࢡҥȞՏπީǩ؛âѠɲ݀ఆଲΘ"],encodeOffsets:[[6220,54795]]}},{type:"Feature",id:"NOR",properties:{name:"Norway"},geometry:{type:"MultiPolygon",coordinates:[["@@᥆ؙઍɣऄՅෛ͵ڵû΢לઃͰಫ˵Ы؝ߟωࣗȮ઱¥णѼԉɝԷ“ūփནƊɝҵ߭Hևױ࠿झಫ஁̨˹̇ͫ࠯bձ޿¾૟՞э˥ধֻۧυӛ֝Ԫဋঁ૫ȟ୏є̛ࣚˇ኶ޞզᕠ۶ဌࢂ໤୦፺ྴඦلᘼ੊ᇎπ൪­౮ۢ໖›ພǘ"],["@@ም΅๝Ȝ׆ɐԕˎეǚͮ̿ொȍ"],["@@᪖صᑟͥұأ݅ǁЍۡৣᅵԢނ̘ఽʐ࿕܂ٷڄᘎ̜Ң̋஦\\͊˼௾ˆ੖̋"],["@@࿮̏ఝҍ᝱ı៙ƖƫɴஹdँϬᣴɼ௞ȫࡘʤᑺȽ"]],encodeOffsets:[[[28842,72894]],[[25318,79723]],[[18690,81615]],[[26059,82338]]]}},{type:"Feature",id:"NPL",properties:{name:"Nepal"},geometry:{type:"Polygon",coordinates:["@@ÝαŌՕĩͩ۩aয়Ȟ٭ĂӛђଷŊયҼ߉Ю߿͆͜޼ՒϠΒȪڪʳࡔշҾť˰ЕٶǓۀσौȕঔć"],encodeOffsets:[[90236,28546]]}},{type:"Feature",id:"NZL",properties:{name:"New Zealand"},geometry:{type:"MultiPolygon",coordinates:[["@@Ȓ΋װ;ʐΡBΝ̹ϳչإїͷ̴З٭Yܗ̓ɣջӋࡗڇϓнʇޝlխˢࣱÐƗ̰Ҍذ੐ࠦժǀ׾͌ܜѰԎѦώظ͈ɆŰҶלϴȆΧ"],["@@،ࢫlָϜɯŲًڰ˛֨ãӒ͎юĭȯݗʯӫٛjɡʭþαūƻͅҏзֹ٭ͯƟɘΕŨӞ۔˟ҨࣛͲz̦؈̌ƚ٨Ÿլͻ֜vƪБΎڋݔΗת̸àҚұٺɑʂݡ"]],encodeOffsets:[[[177173,-41901]],[[178803,-37024]]]}},{type:"Feature",id:"OMN",properties:{name:"Oman"},geometry:{type:"MultiPolygon",coordinates:[["@@ֹ̻ϟªǩȧƉэļ֗ÿĻϯFԽ̻ćХȓǯԹP͡ɃJͻПɷҩĂ֗˳ϱ³˝טٿ൴ᠾ࠾֖၂ϩתv͸ʔΐFΆϞǒƩŞèմіHϖֵҸ̧؞ŋӼƳϜӕɨ˧̞ŃCȉ̩ԃƅɽΟˏ"],["@@ʼnƳDž˺ʔ˺ľñā΍"]],encodeOffsets:[[[60274,21621]],[[57745,26518]]]}},{type:"Feature",id:"PAK",properties:{name:"Pakistan"},geometry:{type:"Polygon",coordinates:["@@تϻʞ٥൨ͻ߹۷ऩůౣȲЫα̖݁̈֩ڴгܑӟ`׳ࠃࡇՃ࡝࢝ࢡউÚऑࢡռϗĪ٧ҾэǘܝᇛD֓֕؛Ɇʣ؀٭٘໻ǁിeஃŝ̈́ঊொѢéϰГƌw݊ߥφͷԔеѶඨѕࡀŲԈŅǞȂגóદĈ܎ҶӈشCĠɼٞŌ̴ý͢ʀ±ԌΦԖ՘Ɇͥ֊ߜɴ̢•͒мΜĩмȣΤӬμࣘǮ८ĮѐƺӨĦ"],encodeOffsets:[[76962,38025]]}},{type:"Feature",id:"PAN",properties:{name:"Panama"},geometry:{type:"Polygon",coordinates:["@@˫ʎǵҒȺɢɅÎƿˤлɸοÁǝ̇ͻɁǽ‡ĉǩВҗɯŅŧŭϷ©ơԈŋƛˡ¸ǝ͸·ÈɓİέCǻĩŶªǖìǠƲŲIJǩŲK͸͘ö̠̝iDZͲ›ĀæɴȵЮÔΨɄԜǞ˺ʤҬ·‹ĉҶ…ώơ˜ʧ̈́ɵĹūȜӵǁʟ˓ÒŅС"],encodeOffsets:[[-79750,7398]]}},{type:"Feature",id:"PER",properties:{name:"Peru"},geometry:{type:"Polygon",coordinates:["@@ɥљћɋࡅӘñΈရࡊທࣾ٫԰ΏۜƐʎ܅ાࠣ༄ߍီ΅Ϥ˃ؤٷպױͼ˖ϒПߢʼךڢՎIJΓʇȧx̭ΎâͼĝΚщӆΌDŽ֤ԦܶৠͨࣸࢠʾմŝٔɢĂ֒ЉˎЅϴɏӶࢣضĿҨɞ̤ƣԎð٠Ͻթࡣʤoрҁݳ œųۍlj॥ֱÓϻɉ̇ČғԕʍBΡɛƵΔݳҲԝDZί֐µ͆҃ݐuېӸÇ౧ϢĩӄƠܪടǷ˵£ןg܍͟пƮ̵ȕ˯β۹Ջ࣡"],encodeOffsets:[[-71260,-18001]]}},{type:"Feature",id:"PHL",properties:{name:"Philippines"},geometry:{type:"MultiPolygon",coordinates:[["@@Đ֏ºҽ˹ޑ̫ࡨϽэˎإʉϿ঩Ӧɿ؊ʰЎՑЈˁΑЃثҵƑʖ͢۾ՌʀҜ̈́̔ϝٔɰƎϒרv·ٰڼЋêхÐ̱"],["@@̟ˡˁՍ˃ʝԫ׈ǦɤɂɾĢԸҨ¸Ɖ֣جߺāߡ"],["@@ૣߕЬט؈԰Ԏ׊Ѱ࠲Ʈۅևҧѳֿ"],["@@Ԏʹ՘BgΗϳΣՕʧ‡ϸÒєŽА"],["@@ʀभ٫ɞj˭ȶԯЍȋ•עʧªƁԘӶãY͈ԣٜ߮mɴ̻"],["@@ɟܩέоѓ٘ܚ‰̡̈"],["@@ԮʉʶɖüɇƍΑ˼׻ɛۥӷ˥ƁڳȊڝѾġϊIJਾүăҙ˜ȫēϯٻЮ̵Ѵɍ̯՗ԊރůлȆ¨ΎˀɊʣȘŇ̡бӚűμߨͺˡĔೄ˜ހԘA"]],encodeOffsets:[[[129410,8617]],[[126959,10526]],[[121349,9540]],[[124809,12178]],[[128515,12455]],[[124445,13384]],[[124234,18949]]]}},{type:"Feature",id:"PNG",properties:{name:"Papua New Guinea"},geometry:{type:"MultiPolygon",coordinates:[["@@ɽčε͔ρՔǷ٘ŜĆĜʡʬȏРՑЈ˵ŝɽ"],["@@ѯçƃɽҟȱћȟѽBۏʔӑɺêʺݬũҠàŶЖŦrĆѽӐÜʂ˼Ҹ̚ġӸԌfǜƏgү˯ԡ"],["@@ݤտղࢻӖ„‘ω٬ƛʥǁࣀΝġʏ֋ÏȷɔܟĦࡕŴٷ՚ӉҦѧ݀ભπ܇ʇԡˣńإڇ˿һƖࢅ–aᩒaᩒภ׃༊ӓׄїҴхŸӵඔԱȲѽޛěȄ֕"],["@@ʿɡǁӸȝ͘ϝ˞ӍΪ؇ʚɺȮҒɻ˸ȁΜȫʹΛ͊ˏĶѧ"]],encodeOffsets:[[[159622,-6983]],[[155631,-5609]],[[150725,-7565]],[[156816,-4607]]]}},{type:"Feature",id:"POL",properties:{name:"Poland"},geometry:{type:"Polygon",coordinates:["@@·՜à̂ȹ̧҆̚ɺɤȝђָʘ಼ϴ੒˴࠼ƙÚȱ߸Yਚħ໶^њěȬʵšωɸ͋KͯԋǡʸϳfϏцܻěɽзįރۥɒϗǿ¶ߙ͔؁šЇĒӹǵч̖Ήŕ³¼ϭаر¼ăˀֻĦűɑҗǨÀɴػòЉ˔"],encodeOffsets:[[15378,52334]]}},{type:"Feature",id:"PRI",properties:{name:"Puerto Rico"},geometry:{type:"Polygon",coordinates:["@@јõưǕɋɃمLӫ‡·άŢŬیK"],encodeOffsets:[[-67873,18960]]}},{type:"Feature",id:"PRK",properties:{name:"North Korea"},geometry:{type:"Polygon",coordinates:["@@Şƥ͉ºη˵ʣ˷Ž׽ѣȅƫƧ̓ʝ֓ƏηɥηįġͰƋӈσŧȭΧÇץ¡͝ϛϑˆÁùСdžĵƿʙé‡ǀɑüɥƆɰφȤİõƶɆҒÅƎөĠЇɤۄբऒҌ־׮Ўˁܪ‹ſѺಚβͰҼժӹ"],encodeOffsets:[[133776,43413]]}},{type:"Feature",id:"PRT",properties:{name:"Portugal"},geometry:{type:"Polygon",coordinates:["@@̦Ɉ΄ŬɂЫӺDƞłӪ‡ɼуϱɩYٽƍū‘Їγçʹԋɵտ̄ʡřɫ̵̿ê˥ͷɓѷŠџġŸڂÿԬϓþȩ͈äռͰ̨ÒͼǪԎkΤǙ̠™˲"],encodeOffsets:[[-9251,42886]]}},{type:"Feature",id:"PRY",properties:{name:"Paraguay"},geometry:{type:"Polygon",coordinates:["@@ͦ৖tҌЖ݌าʔޮ]޴їbʵʞҳÇଛࢲLJ΄ǐ֦ɩǀʣþޓİ͓̼›̀ƌ̢ƳAҥŕӻǑӛƍݏށ١ړƇऻŸࡑɮࠢ౨ťψࡽ͢ਅبۉŸ໵ൌ"],encodeOffsets:[[-64189,-22783]]}},{type:"Feature",id:"QAT",properties:{name:"Qatar"},geometry:{type:"Polygon",coordinates:["@@ÇؔɨѲɰĜʬˁdӯǽӳɵÑʫǖ"],encodeOffsets:[[52030,25349]]}},{type:"Feature",id:"ROU",properties:{name:"Romania"},geometry:{type:"Polygon",coordinates:["@@δǶԴġՠGϸȳ˺źبĄɄȠΠ@ʰćʺʟˊΟӞԁ€ρėΩưϥϒƹЂƊϠƟpɏПǹʯĀɻ৥ӳĖ̪ؑফțзɋ௽¬٥ƀ͙ÕʍΊƵƦȚƘȷŀ˃ȋөʔßΌԟȢĥˌҕͤڪǂԖ֮Њ֬ԢǮ"],encodeOffsets:[[23256,49032]]}},{type:"Feature",id:"RUS",properties:{name:"Russia"},geometry:{type:"MultiPolygon",coordinates:[["@@ࡌ๫కˤԫ்ࠌࡳyוُԒսٱƻ۸Ĥࠊħ࣢Țٌš૴ӯࠜôରަϮͭϴϐŠɔ։̆ߵuࠟΎࡑ"],["@@໵]ਙĨȒτ୊˚ࢢƧψƃęɱäɉ"],["@@֦Ƚțؐᗸű࿨޻࠭λ൛ēsࠑͳǩ޽~ٗ̊ૣʖȉθ࡟Ǝॗʼnҗ̎Ǽ̸৓ȥϚЃӉΣ@„Ꮪٛᔺ࠳ïԷ"],["@@ः©ƭˌੲΖ@ַ"],["@@ળ»@ָň–܈E௒ʉïŗࡽȩ"],["@@ౡMႣĤƧ¬ߘͪੀþஞ͏ĸə"],["@@ॿͩഉø༛ͨȪ˖༨ųᑔɗ"],["@@ډرᶽzඃȣမղҎ׀૎ǂᕞ™ᴬѽ"],["@@ӹóᩣŊɟώູɦūҒ࡮Ƕ…Ҟသܒޙĺ፨݆ɩϢሤѺ᪪բ᫠ǀ෴̸࿐Ŋאͩ֟ʻᲗз᢭Џᤙߝఫࠍ೉߱Ǡۥྎۏ"],["@@ɨгސȲឤYቈЧڬ̿ȽѧङʝᕅүفʟਬşఖɃݴDŽєաτɔഊƂ᧪ƑȴϽ↲ů´ٜᄼƥഄLബѷϮ՝ӹΙੌڋ೔Ϳ߸ࢦഖϙ෢ɦྼʵؤʀൖş؅ޮૐζ䢀ձܐӿᔲٛ₎DŽာƑ۪΍Ĺؙਜʇ૴Ǥ๰vཚǑཪĢะݛਪˎڷ՞ϐώᧆɻფºᝂБ୲ν@”MKઇσઝÖݶҁԄەϲɧĮΏɑɝ༧Ǿ᚝مݛĭ౽ן௛ԧ̱ϣய׊ᔗڇϣ̸ߵΫ૱Ř˓ց৙߽Šͻड़ȋő௣ޭ‹Ϋ۱Δα฽ѕ̅ॡభȳʥ࡟ே޳ׂ̳έ௬ҵለИ୘܀ԆªϾರȊຊ੒คࡺຢڢڮஆ৷ëԍۗᒉइۍਖᓧ˷ᑃටۚԧሙɕಝēÔ؊ಯŶ਩ЭᢵƠ᪏ʟᨩ࿛ủጝ೚ŁаՃࠄȅ՞оईÃௌऍ†܍ځ࠽ë্ϛഉ్௓˯ׇଙ঑ଇॻթӹ૩ӱՉYՇФૻؙſ˩ŝƦKѐіxŦ঴ɛܚܞ̒৶Ʃ֢ࠈ˾ऄ͚̮Ѵݲ൷ʛܯͧ౧Dͻ߄হװหˎ̵ࠖ̉Ԫ̿βԯࡐ̲݇షʢ૛uਯƱۛлҤȥXҩұˑݷࢻRσஅՍ৙̈́োéѯˮԋĞ௷ףેƑޛȻੑƌޫSԙіࠕИࡅŎ੝ŋߏƹ஛ΜLJـধɎށİवΎࢉࢉ΀ӵࠇב௏ɂ࠻Š֗Ͼ࢙^ܳʴ౫Ѓྃܣࢭơ͡çѽԤઍőΧΦחnjЙӠҩưிɍୃӜ҃ѯሟᒒੵٮ̮˂ᑋߍ߭³êҞઅ˺࢙ȱ˃ࢊມǺݯΑᑅ̳Чȹḭ̇ϫ˻؆ֹ߭ɓǀɭ߭ХസֿɁЉ୻˜ʓʟ੹Ѧ೯iࢻΟহͼᇡ׊ಽsჃࣳĿؗࡹӤڡउʖǡӝُ܊֫ذx՚֗ďѝѐƋϥӽ߿Ƒ࠳ࢁކߕĉ֣ࣼফԇ͹ƝɇωÌֿԚɿ†ՅȚʳΈ޵ǮԙƁƥƼଥЖఅƌ܃ƞĹıੱ܂य़̈́ܩӴؒƈۤ۰ҹͪఌ΄uȀݯƉ‚ώѠɼ߼ÖƄ˪ȅҪ΀ѰWʚఉ˚ӭUԯЀ١ƃ੩̐lǒ̗θڟ¤éʼɀǞ՝ӈࢋąʭ¦Ƀȑ̽”ȷ՞ȟ˨NJĀڴ‡͞Ȁʍɢ֥ƪ¼Ʋ΁ƴՃվǸɨĉЂࠑȨѱijšȼࢭɂˑӸíТЙȖάˊʝ޶װӞųƤक़ҬࢡЎᅢ੶ޮӠ͂єగּΆնݳش֢ܜ঍ग़ޢي౿֔ŬךڶüොͶࢀ̈൦ԕᘨȧṺो٤ЋÆ֓टѳ൏ɡ⏷ٔ؟Ńൌ؛ÂϵÆ࡫ઌʯڂɓňРԑΰ՘͈᎖Թ۾Ȳ֣؜ዦࠖޢµ޸̋Ӫ׀۫ԄЪԊءԶᚠˑӔҹ੡ĻNҳڌ˽ಜǼȶ՚ჶАᰪܞي£ࠣԙਬĕ׼˼༾xఢΐफ़ԏॖ֌ࢡӢѪˤ២ʫ୒ʿᴾॣ֚ѰࡡѺ{ǴৣĈˢЌ҅ټ}ː༄ݾրކزǒᕮɛǬұߕڽԺˋ˒חȏଵऒԧέ֕࿫஝०ŭ̢ͮऎɎɞжܮЎөӌϼֈࣿêȫҲڢࡈણۆຒ֦șװмnѴүͧ߷࣐Ƶϥ؄ඤͦლ¬༈ӏݛ۪ċࣆศǞ፾™ᆘŌہѮংւॲx࿎иᕠŐ˪ɲᕂþیȋሴҀ໲aɶδߤΨጤΈ෸˗ଥȷበŹ"],["@@ⵙ͕ໞીےĦقÃᒈӋʟͿ"],["@@૽ōݱÛśƏঙƑ࣫ȦӐʾል~࿞ƶ౨XǢɧӘȬߊƐఞǿ͗ŷ"],["@@ᆳĿᚉʎඅ͎٣׾଩ǔᔆָᆎȎ࿌чኬ߻ȹݯ"]],encodeOffsets:[[[147096,51966]],[[23277,55632]],[[-179214,68183]],[[184320,72533]],[[-182982,72595]],[[147051,74970]],[[154350,76887]],[[148569,77377]],[[58917,72418]],[[109538,78822]],[[107598,80187]],[[52364,82481]],[[102339,80775]]]}},{type:"Feature",id:"RWA",properties:{name:"Rwanda"},geometry:{type:"Polygon",coordinates:["@@ͬӃµӵʏŁѿÆʱӍԛàþҠŘތԄʎɺȰďԈʸ"],encodeOffsets:[[31150,-1161]]}},{type:"Feature",id:"ESH",properties:{name:"Western Sahara"},geometry:{type:"Polygon",coordinates:["@@oҊŸ@@ÉeNjEౝ᪁ª‚ᒷ޿÷ȳћDŽ்ᾓNǽ˫˜΢bCቆäĶ̢ΆϘˤୌୠ࣢Ђ੖ˀÖ˜ټۺĜ̦ʼnϢ@˔ȒԲ‚"],encodeOffsets:[[-9005,27772]]}},{type:"Feature",id:"SAU",properties:{name:"Saudi Arabia"},geometry:{type:"Polygon",coordinates:["@@ʼnΪʩʨÝͲѡ̞҃۴ʁۆׇ׀ϑƐ֋ߠīא–ӾӕञϿ͠ґǨˡӖ°ȎɹѦʕȊ͝زԟڴѓ־лIžҦœ̌ļͲनƅζʶȪ̢ٚŚƒˮˤƜ࠷ࡀ၆фdžŴৢɩబיᛎၕ༠ãݠąȾЏתv͠ܥаȓƠִ̏Λ¼΍ċ˩ł˯ʎɽŐ˟ŲȵʬǕɶÒdž͍Žș࡙͐ᡌщǞDzϪש֕၁ᠽ࠽ᝑ͑޷ϙ׻ࢥϹƕɁˬ͏§߻ĎƷČॹmɫùΉɔɝЭĒΟρˋ"],encodeOffsets:[[43807,16741]]}},{type:"Feature",id:"SDN",properties:{name:"Sudan"},geometry:{type:"Polygon",coordinates:["@@śhdмĵ̀џͨĵ؄ĶبϳÌÍȇԍ©Ȭʕðԍңңл؅џđ۹Ӫͅǥđʓџǃ…ǥ࠵@řǦ؃†̡ƝɳîѝӬƟɲ؃ŗɱϵɏݣ˿ǁʳğå ̅ʎÃʼƌΔE΄ӛՀĩάZȰ̱ʜUӦǭ͖̍µĎ̰ɒΖħΐˢʴǫȞɞ԰ϨئܦÏ¥ ZΚॲH@း@Ὂ@ῼ@˔ࠗȁƳŪࡻ্̰͌ȷҠ̳ыӑأƏ˅ʳĉ֑α௿ĚͳƅܟͿࠟԓзέٛč΃Љɽʝ࢟Dij"],encodeOffsets:[[34779,9692]]}},{type:"Feature",id:"SDS",properties:{name:"South Sudan"},geometry:{type:"Polygon",coordinates:["@@Xٽűʯѿq˷ӏԨÑюХƨͳϦșӼࣳ֫օԫԇԫϭסFگȟՕȊ΋ɭ݉֐ȥάҵDZϱÆɣƕϗĸԗۚƉˊعͪɅԌΕζ֟ѬS˘ҡͼ֯͠ʴĠ̀ǂɐݤɲ϶؄ŘƠɱўӫɴí̢ƞ؄…Śǥ࠶@†ǦѠDŽĒʔ͆ǦۺөѠĒм؆ҤҤïԎȫʖԎªÎȈϴËĵاĶ؃ѠͧĶ˿cлŜg"],encodeOffsets:[[34779,9692]]}},{type:"Feature",id:"SEN",properties:{name:"Senegal"},geometry:{type:"Polygon",coordinates:["@@΍ٺн̚φDŽРמȦќ˾ːкïШǾҶVДʙ֎ɝԘأֈֽžԹǔӓ̾ɿî͗ʽŧ³қâÙģȃk׿ȲЛV༇–ɥħ˥‚ѻƋƏ٢ވkȬŞƮR̸ȘήǯκcζȌǝʐˡƙʻJͧȸˉ_ȍȥࣵy"],encodeOffsets:[[-17114,13922]]}},{type:"Feature",id:"SLB",properties:{name:"Solomon Islands"},geometry:{type:"MultiPolygon",coordinates:[["@@ɾ˿חN͉ԬԈȯǜ‰"],["@@͝mԧĎǫżÀͮֈƁ˜ǭƎə"],["@@ųƹحܰǫԈ˺@̠ڥʹЗ"],["@@–ǛڅΦҟ̠̿˪ŰĐϮȫېϭȢˉ"],["@@Ǘ³οȒ·Ί¨ƖԈΡͰ˛"]],encodeOffsets:[[[166010,-10734]],[[164713,-10109]],[[165561,-9830]],[[163713,-8537]],[[161320,-7524]]]}},{type:"Feature",id:"SLE",properties:{name:"Sierra Leone"},geometry:{type:"Polygon",coordinates:["@@ɧØ؁ͺѩ҈Ƨ̬Ĺت҆τĬɺƞǸɶpȜǂڦCɺ̛ǼˁʓƈɗṶɴ´ϹϹϛҗ«ʓȩˏ"],encodeOffsets:[[-11713,6949]]}},{type:"Feature",id:"SLV",properties:{name:"El Salvador"},geometry:{type:"Polygon",coordinates:["@@ġȡӡ^̡Ą΍ǘұÀʃǶ~Ů˾ɄǀĢ«IJȠ¾ʜëǸǙʪƇŒœτĴǤÑŘĝÏͳ"],encodeOffsets:[[-89900,13706]]}},{type:"Feature",id:"-99",properties:{name:"Somaliland"},geometry:{type:"Polygon",coordinates:["@@ϛԩד۫۹Mᩧা͍̜̳К̳ҨǾ̖̲҈˚ƹǒΏϜΗкGߊɌࣴĴ݌ʼиÆ̚ƶӎˆKaE΋Aࡑ@ѫ"], -encodeOffsets:[[50113,9679]]}},{type:"Feature",id:"SOM",properties:{name:"Somalia"},geometry:{type:"Polygon",coordinates:["@@ѼĎЊ˾͈FpɵýӧHѳǯ̣ʁࣥЙयԱ੷ܝ௷ܓवধ଩ࡁڹష࠯޳ٕँৱȗѷȍȣӽۚWᵤܾ॒ɰˆբfݠפબšᛜᡄה۬ϜԪ@ѬBࡒFΌLbːhϰŰ"],encodeOffsets:[[50923,11857]]}},{type:"Feature",id:"SRB",properties:{name:"Republic of Serbia"},geometry:{type:"Polygon",coordinates:["@@Ԡȡà΋Ӫʓ˄ȌȸĿșƗƶƥȷȏø̫Тγ͋ʿƗˋĞijƑšϳa˹µƒØĴĴĦȴšKǍƼƑ ŋƆƽÀšŠƯ±ś˧ȩÑèð͋Ǩ˟ĜūŜɟƠȢšŬЄЛ͔ɀτ̥Ë͔́ˉʈȱ͘٢ɚԾ™ҖͣĦˋ"],encodeOffsets:[[21376,46507]]}},{type:"Feature",id:"SUR",properties:{name:"Suriname"},geometry:{type:"Polygon",coordinates:["@@৔ǙĞưڶÔࣚɥѩܟâֹͤӽƥίóϩɉΛӓDzЇđ͹öčʏƘǗ÷ǡҙèԡܴōӄˏBωؐƺѠ¯ȤԜɖƈݲ"],encodeOffsets:[[-58518,6117]]}},{type:"Feature",id:"SVK",properties:{name:"Slovakia"},geometry:{type:"Polygon",coordinates:["@@´»ΊŖш̕ӺǶЈđ؂Ţߚ͓ɷɓǏ͹dzđ࣑ʮ˟»ȟȡЁĿěÄХŽͭ}ãǙ۷Ļ̱ĠёɌċ̆äńŢȂόa˺ĔxþLj¢ÆȒȖ˜žưʢD"],encodeOffsets:[[19306,50685]]}},{type:"Feature",id:"SVN",properties:{name:"Slovenia"},geometry:{type:"Polygon",coordinates:["@@ۜÝъȐܾtLjƘƘUǎ˳ڝɟć͹̇đHɻͣh˷ƎƷƙב†ȈúȫΨĞа"],encodeOffsets:[[14138,47626]]}},{type:"Feature",id:"SWE",properties:{name:"Sweden"},geometry:{type:"Polygon",coordinates:["@@ࠁוƀԥ೹ڭྱܡؓஃײףߦүޗॅ࢑ȝ͍තӋ޿৳ĆӅڗঃˉߐ۳॔ٓஐφӜּۨ˦ন՝ю½ૠղ߀࠰ä̧ͬ˺ಬஂࡀञֈײ߮GɞҶཔƉŬքԸ”૪Щ಼ֱv಑˴͛ฃʃ"],encodeOffsets:[[22716,67302]]}},{type:"Feature",id:"SWZ",properties:{name:"Swaziland"},geometry:{type:"Polygon",coordinates:["@@ǡύӭěԅҖS̄ɰ̀ĂʔʐÒшƵŰϕðω"],encodeOffsets:[[32842,-27375]]}},{type:"Feature",id:"SYR",properties:{name:"Syria"},geometry:{type:"Polygon",coordinates:["@@࿩ࣅऩͬgNŖŶ_ΈȸҠҜ̈́Əͤϗ¨ÿٞȶΌɤȀɤȀ°Ҹ˞Ǐऎɺ҂ƿۖFॴ̀Ґaक़žїԽҡȹĂؗͅ৫ᇵ࢓"],encodeOffsets:[[39724,34180]]}},{type:"Feature",id:"TCD",properties:{name:"Chad"},geometry:{type:"Polygon",coordinates:["@@ĎЄաnDզΓ̶δ૊ੴߌ¬ન͖ၼǼΰΓ˾_ˌ̽ɔȷರࡔҠ…ྑ…ྏ¦ ܥÐϧإɝԯǬȝˡʳĨΏɑΕč̯̎¶Ǯ͕Vӥ̲ʛYȯՏƛэͽ؉ࣹ߅ϳ߹¾ʁûĊ̏ѫ̋Σ͟੓͏ȽȐƓhƹɍۛÙƀɪ˅ׄşΐλƜӷӪǼІϦċʂÐҸSқކŒ֐É֐ͭՠ"],encodeOffsets:[[14844,13169]]}},{type:"Feature",id:"TGO",properties:{name:"Togo"},geometry:{type:"Polygon",coordinates:["@@ڱdzȇ̎ɡՔãкȆݴɁ̬ăڎD؎ΕѠÖˀ݂kŅѵʲʝ̈̋ŽЭǜǥኝȺׅ"],encodeOffsets:[[1911,6290]]}},{type:"Feature",id:"THA",properties:{name:"Thailand"},geometry:{type:"Polygon",coordinates:["@@ݭϬܗeŬڈ݉Káऋґ௯˙ݏÌ؋ն΀ދưܭҶӓԚĭѤѧ˝·ևĵßќۇςƣƭͧ͒ƝжҁӄПЌƏӳǃҲĠԾʚ߬ТࡸҤ޶͟ތ`϶ĩҸ֕ښȩф̄ƺ̮ܶ·ֆՓؘН݆ΠƴϦࣦצœӬθӔȘθʷ´ԍ֨ȷࢭpݫࢰԆʤƧӰzǜَ̊ÍٖڽÀࠥںܷ›܅˙ϛ޿ŦગDž՟ۧȤ১"],encodeOffsets:[[105047,12480]]}},{type:"Feature",id:"TJK",properties:{name:"Tajikistan"},geometry:{type:"Polygon",coordinates:["@@̭ʷࣳƖāӛ࣬Þਢ˗འŶɈާˠĐԜȓ‡͛ŴӍࡿBׁØԻϕύĉ̉ǯͩˠþ۸ʩ¢ĞʲғȐα̇ė͹Żūԇj˕ϩ˯nj؋ˑʱĺӀࡘǹض؟ȨɔφۮŸЌҬˌբ૲ȜǩϵŤɹΎv"],encodeOffsets:[[72719,41211]]}},{type:"Feature",id:"TKM",properties:{name:"Turkmenistan"},geometry:{type:"Polygon",coordinates:["@@ñۼطŠॣݔڣĠगюׯþσƽ֙|ׯӓ݇NjƻרŪ࢞ٽ˶Ɏֺ֏¸Ȇ۾ߊȵ݈ˎؓԎʉӔڱɋď؛ʿհψ˨ॖǪ֨ɻךڅњ¤ॆ\\Əцܖ̂۾ӦଆѹĜڡ͐ǣࣦžˮƳаࡽ०ׇոЃ࢞Щ૤Ϋwԥʩ€Ѕɤſ̙۽NjǙڥӁʭڏŵǫϟهŏࡩ͈"],encodeOffsets:[[62680,36506]]}},{type:"Feature",id:"TLS",properties:{name:"East Timor"},geometry:{type:"Polygon",coordinates:["@@IJȤܢȌז†ˀŀ͆Ľ̯ɫ࢕ο۳ʋeʬďǔ"],encodeOffsets:[[127968,-9106]]}},{type:"Feature",id:"TTO",properties:{name:"Trinidad and Tobago"},geometry:{type:"Polygon",coordinates:["@@ӚŊǮ‡‘صۭġƯúʒɲiͪ"],encodeOffsets:[[-63160,11019]]}},{type:"Feature",id:"TUN",properties:{name:"Tunisia"},geometry:{type:"Polygon",coordinates:["@@ΩພԭͺQȰۉԄóنԮҶȢۚƃߠǠќࣶͺךĵ}ы܊̲ÒljпЫMϱ̆ȽōܫփхDŽқѤaɄЍ͊ſ³٥Хʋʵˏֽ͓ĘΑïΟЧț"],encodeOffsets:[[9710,31035]]}},{type:"Feature",id:"TUR",properties:{name:"Turkey"},geometry:{type:"MultiPolygon",coordinates:[["@@஺͗ঐżܤõলѬࣆ¢ߴЭƜ̑ăУزȻͨʕֻʇˀ५ǏʻҠڧЕƙ̏Ɋ঍ňίŽॗŽҏbॳ̿ەEҁǀऍɹ˝ǐ¯ҷɣǿɣǿ̱Ϡ͈͂ԟí۱ȖֿәౣĥڹҊࣟ†ȗΑׇij߻҄ࣻeӽ࠶ؗҰЦٸՓВठߨಒ’Μྀٔŏ৞հ঒ʄർlุף"],["@@۫ҏ˃Ϻ\\ǦȦĦʺՂХɞࡦ˄ܤőĴ͓ܼ˓Ƶȵি±Ωʷ"]],encodeOffsets:[[[37800,42328]],[[27845,41668]]]}},{type:"Feature",id:"TZA",properties:{name:"United Republic of Tanzania"},geometry:{type:"Polygon",coordinates:["@@ƚġᵂႋÌӣ஼࠿ϱਙ¸Ӊՠ̩~ɓɳԓ¶ʭÇГ̌Ճΐ̰ࠡǿڝӣࣿ͛ԋb̙ʥבsɕŃঢ়ʂكåɽଢ˵ϺǛɶࠗƾӉʨՕƘͯƘΗɈґ੖ӣҺǗӤČѨƯޞΎ ̨̦͜ѬȺǮS˘ǷȐ·ͨʐł¶Ӷͫӄ̎Ķऄ[ႎà"],encodeOffsets:[[34718,-972]]}},{type:"Feature",id:"UGA",properties:{name:"Uganda"},geometry:{type:"Polygon",coordinates:["@@ः\\̍ĵԇʷȯĐPوȜ͎²ڬǰϸ͎Ѭ͔ɠ˒̘͵Ŗ¼চΌɮՖȉڰȠעEԬϮЊ׍İсτ९̧ؓЯ֋ʉͽTࢹႍß"],encodeOffsets:[[32631,-1052]]}},{type:"Feature",id:"UKR",properties:{name:"Ukraine"},geometry:{type:"Polygon",coordinates:["@@̾“ɄȒʮ¥ࢌĆ՞Ӈȿǝêʻڠ£̘ηkǑ੪̏٢Ƅ԰ϿӮVఊ˙XʙͿѯȆҩƃ˩߻Õџɻύڡã֑˕޽«ܣ̻¸ԹЪȭࡨ¼Ǐ̛ँơଛӟұǠȄЂࣽʘƨLjߪ˪ʑȔಯɆË̼ީĻ̷ҧٱةϟƠЁƉϑƺɂĞƦ˾ɲˎÑƮǬäĊśӸ{ɞØƽĎÐŲ̉ɈŧΘ̩ƐÒ˶ϝɦΉŽأʾ֑ĉȧŭΟ@Ƀȟاă˹ŹϷȴ՟HԳĢγǵÍɤұɮǐͺɸɔȀµɑϘބۦиİĜɾхܼДҢɪٲnࡖßबȫڎi͂ŧ̀Ʀɚȝݸ¢ͮąÄцʶȂܞº"],encodeOffsets:[[32549,53353]]}},{type:"Feature",id:"URY",properties:{name:"Uruguay"},geometry:{type:"Polygon",coordinates:["@@ղĚࡆٯ̺|ࡺ՟ڈҫӠֱχЉɸӇεՇॉұاǚғěޥΰ֫ԟҬÞլǾȈS࠸ɤࡺȾڦ"],encodeOffsets:[[-59008,-30941]]}},{type:"Feature",id:"USA",properties:{name:"United States of America"},geometry:{type:"MultiPolygon",coordinates:[["@@ũƕȽŤ|ɾƓ̨¦ĤƤƎÍǔ¸þÜe͐ƙƬñƌőɊ̍q¯͟ǵˏſ"],["@@˭ÑƟǮīèQÀĈî̘āɘŹëĵ"],["@@ĝ҉|Úĸа•"],["@@­µÓŻˆŃȒ’ɤŚêÃʐ˥"],["@@ıĉ˱ƴªÖŸĈȘijȝ"],["@@Ƭңʼƛז½࡬ƅࠂʹڼŊਖɓ˞Tݨʄ߂̧ࠒ͗ں˩ٶˏĈəȢĉ½ĉɦǎĔ¦ȣǜƅɴ@ŬĹĽƫ࢖ЁǶށǚܳʗӹЁҥȁ̍mēĦť˸Ɓɂ@ঊ҆ࡾƀસмfĐ÷ʰƉǒϜƆࠜHޘAˎ͞ŀàࢶ؄ϜƸ౦N໾BĎȺː¦Φž̖Ϣʲٺٚي˨ə֜ƜώʏAଧռӅƢ˝࣋Пࡷ̃ࢱʝѻӿƛȋSѽˤѽΒsė̬ʦȇãʇ֥ƋЗhةƥλ¥ӥ¥۫ʏఀǂʠǃ୳ʥ՗C|ĺʭɷʚǹ׽ؑ٧×Ɏȁª˟ɀǪҍȼƭ^ͅˏ͛ҿڡûʺֲѕ͎įۦljεǴՑևƀׂ˓˜ߛʊÍĖ̃ŠࡁՕدࢇʝցӱнÁэ̱ţ˭इձӁЍЅӽŻׯƪ׍ˬܗώשLεЊঅ֥—͛ȿԡʣŃЯĺƁς͋ȖѻܢϹٞű͢Ǥ֐ɽҦٻ۲͟źࡑϡƭ¦СϼՃȺोŁݗĤٙÍΏſƲɟaͽǴǓLJō̵Ů́ǃ؍€طѺܻĿ؏ȚԹÏۻȝއح࠳γҝБȕϗUׅ¨ЕDŽ˹͝{׭ȂٽʺɽЄȁטӷӐ̃ӰуֺףͲۉgՉڑۣʦѡʪȽҦ˧Ѯӿτїˈ̩̖ป@C΋ڗ@ဩOቿפ౓ТĀǒ੩ĝॕÝƙіխӚϻĴğʌһ¦̝ɪޭĊɉƌĹҢࠁࡊ۩ୠˆȚχˤٯ۴řۆ҃ҞȀۢ…ܜˍ٢͠ߊĸނĺނƱૼˇܘʓ϶ĸǐ௒˷҂ߋȺɜƇې˷ێᛸ@᠂@ࠜ@ᢢ@៚@ᡀ@ᡄ@᭰@ᮞBაAF͔˴J"],["@@࠽͋ѕɐŽЀބ̘҆Ÿ֐ÉΤʻܫЍ"],["@@ԧŽսƾԛɮࠦƞښùĂ͑"],["@@԰DžԾĒڸɛ࠲őéĝُDZٕǾ͋Ʋݍµȧôº̈́"],["@@؊ϛώnjහ»¹ȕ౾ƛࡨČᄚ˅ྤā٨ʼn૦Ǝౢʧࣲŝ@@MᷱIⷍࠠ{ࠌɵהρݜցࠈҺࡈ˖Ҁѡ֤·ޒϙՂ׽࡮य़ේ՗xՋұЙҥ͂ݍˌʃܺએںҍߎ߯Ä೷rটʌ჉ࢎߩDŽ฽̜୑í࿻ϬৃΨटǯǦ׏ҫÁঁǫ݉˱झdzťӶϚࠚࣀʶɱɂੱҵֵ֑௅ױؚСߏ׿ࣗΗࡁʱȻωಽѡ˅ϿছΫֽÞ޷ɻ࡝˹ۧ˫෹ʉſƘऀϾࠔʸࣆҠਬĨвΈ୘ԊȈǚب̒ƢْђӸॹʫ˓Ơҕ̧շюɧ̝̽м࠿ͳԩBïԄƲ̮ե̚થLJ܁ЀַȬIӈ٩Ϊ͘ӘۆҸ̚њںÖ־ƇڴМ؎ï٘ʼƻϨҹưج͖ԩWࢻǽʯȃڏȄஏĥ௷ȬΛ͸੟Ӧ୾ΘመШ۔@ŕнᄢŽڽԶਕ͌ױр߫ΨଽˈҺѲ๰‚ਗ਼ϦȨФ࡬ЎࠊĪཪώޜÉಐ҄ౚǭ"]],encodeOffsets:[[[-159275,19542]],[[-159825,21140]],[[-160520,21686]],[[-161436,21834]],[[-163169,22510]],[[-97093,50575]],[[-156678,58487]],[[-169553,61348]],[[-175853,65314]],[[-158789,72856]]]}},{type:"Feature",id:"UZB",properties:{name:"Uzbekistan"},geometry:{type:"Polygon",coordinates:["@@xԦૣά࢝ЪշЄ॥׈Яࡾ˭ƴࣥ͏ǤěڢଅѺ۽ӥܕ́Ɛхॅ[ᶾᓘӺƾïದ׻یͅߤݵঢŪ෸à৔ؗÙࡅЦMǢۍ੬ɲЉ̺Lπ׺૎הӖƺʠĉ۵խئ́ײȾ়ѷ੽؁ٕĊ΍uţɺǪ϶૱țˋաЋҫۭ ɓυؠȧǺصҿࡗهǰҳN"],encodeOffsets:[[68116,38260]]}},{type:"Feature",id:"VEN",properties:{name:"Venezuela"},geometry:{type:"Polygon",coordinates:["@@yȣӱĭ˜ϡYѭυӥ͆ڙδÆȌ؈ʻ̒§َਸ਼΀řІ̎ˆ̞ןל_մҵ˧ݮQ࣌ĔӖϕٞĻҼʾXɄਨ¼৖\\܉ʛ˼Їڦ×ِЯƆڧѬn͢ȣڕӱó̫˾̷ȽƽԫƉjϱɫɱّ֪Őʁ̭͍ऱ̽׿Žʏȣڛɀثņƿýϔɑ‘֝ŜՉ܆ï°ǭ׷ʅĭΣΉƏسȝNjʱٷÅҧѼʯ࠺ɟ̧̌Ȅюм…ȊʅʠǛ֒à׼Ȉ˰ƲҎ̓Ơӏĩ؁®ͻęסܢӥńઉăȧ̊ȷê‡ǬĴ̶áͺȃȂŅϮѡÈɸӮĺ׶ʔ̸͘ʌɈрդƖ"],encodeOffsets:[[-73043,12059]]}},{type:"Feature",id:"VNM",properties:{name:"Vietnam"},geometry:{type:"Polygon",coordinates:["@@૭ܗ۫ߍȁ׍٠ࢭ޺ળނԱԞګϪ།ŕ๓۫փ१եۇ۫਷ޱ̧ՠʀ֬دӌܬ͸ࢦÔσԚප٨ļ৖ț֖ƶࡀɃצٍאՋ݌ۥ঴৓Ԋʊ̠՞ɘ͙ܺਙPϕކӭڐҊȴڢIࠈĬܒ҄К̿ސƵƃӛАͿࡎɓ"],encodeOffsets:[[110644,22070]]}},{type:"Feature",id:"VUT",properties:{name:"Vanuatu"},geometry:{type:"MultiPolygon",coordinates:[["@@ˣō˭ςŒɤՆӗ"],["@@ƌڱɥŀǩ­ťɴi٢Дʵ"]],encodeOffsets:[[[171874,-16861]],[[171119,-15292]]]}},{type:"Feature",id:"PSE",properties:{name:"West Bank"},geometry:{type:"Polygon",coordinates:["@@@ԣŭʙЃŕ˜ɜɌŚɁĦǬ̤֔ś"],encodeOffsets:[[36399,33172]]}},{type:"Feature",id:"YEM",properties:{name:"Yemen"},geometry:{type:"Polygon",coordinates:["@@؉ɥNjύo˹࠷Οഇϻݩףυ±ʥºӭΑ՗lj۷©ɃµǿɛəÕŻɇеlˍœ׉¨ɓӬzҠƍʜǑتʋΊǚ¤đϨĸNJ™ξςˌđΠɞЮΊɓɬúॺnƸċ߼č͐¨ɂ˫ϺƖ׼ࢦ޸Ϛᝒ͒ڀ൳˞ח"],encodeOffsets:[[54384,17051]]}},{type:"Feature",id:"ZAF",properties:{name:"South Africa"},geometry:{type:"Polygon",coordinates:["@@ǏŧΣяɻћӇ׻ोࢁףԋًϣ࢛͙ѓ«ŇɷԛŰеDž࣫NJԙĹΏ¬ࡿͩܓƃԱͅϡoΣ̚˳fαϒŸśŏɦLӰ˙֞˔ƴs٤ս޼х܈AF׽તДдͪɯƘΫϘÓՈǃҌÖݤіB᷌ɨűӾߙûԟȈ̏׼ĒрϒЊʨȶДЦȚΠķВɽۂ£՞ȜĐʾƨДҚäʨ͂˪֔ݮغஒؤ΂UОƛ˲Ķ҂ċД஁ɔׯƫऩî̟чƶʏÑāʓɯ̿T̃ԆҕӮĜǢώْQȿؑıۥɑϛֵщ","@@νʶϻǟҕ҃͡Տـ٧̜ČƺˎҴƀƜ˜ʴФ̅ʪ"],encodeOffsets:[[32278,-29959],[29674,-29650]]}},{type:"Feature",id:"ZMB",properties:{name:"Zambia"},geometry:{type:"Polygon",coordinates:["@@ІϏɊ܋ƝɩǙڻLjۡ˃̇ʭޭѶɓᢇۗĂׯٍřӍͯĹ̛̅ßܵۓҭխ˳o˗ĬऱĠƯÚOêͧȎկ¶ۋȑչԾ֣یžᦶშYí̂Ű̀ƧЀĪТėʺ̂q¶ʽϾrՖûˬϡڨŝԤˆȌѯ٠ş̴ΧΈҥ٠Që࣠ɱƳח͞ɧƬļࡈƬসȉψʈ՚ɤĶ଀ƚͦđΘɇͰƗՖƗӊʧ"],encodeOffsets:[[33546,-9452]]}},{type:"Feature",id:"ZWE",properties:{name:"Zimbabwe"},geometry:{type:"Polygon",coordinates:["@@ҁČ˱ĵНƜ΁VՙϞٯźʙՒC̒έĞ्ई˃ӢǛƮ͓ڤलğ˘ī˴pҮծܶ۔̜àĺ̆ӎͰَŚÆ̻۬hϴǯǺȻАÓѦˑF੟Ǐ׋—عƊʝħӵŵùɛ؅ࢫ॓"],encodeOffsets:[[31941,-22785]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/xiang_gang_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"8100",properties:{name:"香港",cp:[114.2784,22.3057],childNum:1},geometry:{type:"Polygon",coordinates:["@@™@}ScTʟ@cWuJÁ–]„l¦RLj¼BĄà˜ ŽH@TOHCTDDDHDNAT@PEHDDNJLX@BABALHFF@DKHADBBLDHHFBLEJB@GDBBFBADDB@@KFAFBBJJA@BB@@FFDDADFF@FADDDBJC@AFBD@@DDD@DAA@D@DB@DHHBFJBBFEHDFAN@DGDC@DLCBDDCFDlAFBFCBEF@BC@GDAB@FD@DZJ‚X´HĐMja@Ý`p_PCZ@lLnRGSDMFK|a\\Y}­ƒ§™Mën"],encodeOffsets:[[117078,22678]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/xin_jiang_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"6528",properties:{name:"巴音郭楞蒙古自治州",cp:[88.1653,39.6002],childNum:9},geometry:{type:"Polygon",coordinates:["@@˜@ÈÒĊanwŎV„™Ȯ¦ͪŃĢ„ÜōȂçČéƐżLɆóĊ‚ĊaʊŁ±¯²Um»ˌmÈ»V™ʠţWÑůǓ郙ôƑƒğÆīŎī@Ƿ™wô™˺LÞ¯ƨVǪуšĢ™ȘV°wĢŽôk°¯ƒ»΀@Ȃ»ĸŽǔ@΀ƒ͔ôôLɆó̐ÝɜLɲōͪƒƨóŤK@ī@IU܃ÛmȻţǩÝ˹ÛljťǓǫō@Ɲ²¯VçōKͿŁΗÇţ»ƽ™ɅƑLÓŏÅÅɱV@ÝĊU¯ÑĊĭÞLšÞŎJ±̃XȣˌōlƒUÈ¯ŎKÆƅ°™XÑܱnŗġV¯™óaUƒƧUōŁ„Ñ™±„çɲ¥lĉkğ°ƒk¥˜ƒnğţL¯ÝÝUƽĬ΁lķ°@„ō„XÿݯV»ŹLʉÞɱŤĉó°ÝJ™¦ÝKÝ£ţܙÈĉ@ƒxǩUċƑ@ky͓¹™`U²ĉVġ»ğa¯¥ť@ĉ™‚ó@ŻÛÛJƒw¯nó¯ġWƽʩķÝɛwĉĕݼȭÞķō@ó£Å΀ƑŽ¯ôȯÞ¯Ȱ™ÆōèĉXǼó@ݚnºƒĸ„ÞVƜĸȚUʶõˀĵĖɱŎÝĖVࢰӒѢ°˘nϚVˌ™ÈmɼĵŦW¤öʊõʔ@°ÈXVŽ™ènŎȁb¯ǫĉ„±Èğ`ġwōÔğ»mVVŽ„Ý¥ó@™ĸķô@ššbX„ĶmV²²`Þ_˜˜ɴbͪÈ°„ÞWĸÈŌmބškɲŽÈUÆ»n¼ǬVķĸźô¯°n¦ɄǜÈ"],encodeOffsets:[[86986,44534]]}},{type:"Feature",id:"6532",properties:{name:"和田地区",cp:[81.167,36.9855],childNum:8},geometry:{type:"Polygon",coordinates:["@@ƨ¥šèź٨ΘƑᩄbUࢯÞĕɲōĶĕöʿVʵķșUƛƒÝ„ķm¹Þ™ô@È»ĊWŎçšÅ°ȯȰÝ°óƒÆͿĉ»̽çnƒmɱĵƧºóU™™ƽ@±wóL¯°̻L±Æ¯Vƴķb¯VÇ¥ğ²Ǖbk¥ÇKlÅɱġ@у™óK@™ÇaÝXğţxĉČǫķê¯K@уaŹ„ƑKƒ¼¯Vóaónġw™óÞéU™ġbóĉğÇl¹™aUóğKW„Vůn›ÇŋƑ›ķnʇ»óxĉw™çÇ°Åw™°ċ„XŽ™„ób±ƒkÈÇJ—ƒm²ţx@ÒݎšŦǺn„ó¼n°ÇbUÒ±¼XĸĠłƽXmwĉºƒzÈÜmnxmx²ĖmҚbnŽƧêUºĊêÆVóĖóUĉ¼ÅĬƑ°ɆƆŻŚlłÞLš¼nĠƒ¼@ޙšÞź@ŎÞ°VšɄɴжϼِ͈Ŏ„"],encodeOffsets:[[81293,39764]]}},{type:"Feature",id:"6522",properties:{name:"哈密地区",cp:[93.7793,42.9236],childNum:3},geometry:{type:"Polygon",coordinates:["@@WnŐÆĶLĢ¦ţºź„lxÅĸƽŚ‚Ʉ—Į˜è@ô²ÞUĔƐńV°¯ĸX¦Ɛm̐bƒ»Ɇa΀šĢ™ƐLˤ™ȘÑnƒІljĸÿn¯ĶaŎ¯ĢĕȘ¯°΂œla¯¥™ǕǔwˤӱlťО̻nŻmɃĕċţUw°WUóƨÅţķ°ýV±óÅǓéʉ¯ƽŁƒéōǖȁÝƏůǕw˹ǫȗǓƧǕVý™é@ĬţLƧôͩ„ɱŎɛK̏ÞɅôóK@²@°ōؚ¼lŦ¯ŰóƜÛlV¼ķ¼ƒ°kȰ™Ű„ĠƒǬ™ŚÝŎmĖ`@ÇÜn„"],encodeOffsets:[[93387,44539]]}},{type:"Feature",id:"6529",properties:{name:"阿克苏地区",cp:[82.9797,41.0229],childNum:10},geometry:{type:"Polygon",coordinates:["@@VƚxˌŎÞŎƒ°n„ȂÒ°²VĊ¯VğƾˍǬƨÞÞKÈÞĊVźôɆÞĢèŌôWČ²ŤVÞĸʶbl‚¯ôn_VÆĸlmÞnVź_ĸ¼Ȯmǖ„šéĸW°°„ĸJ„kʠ¼Æw°¤ÈƒlxɆzČºĶI²ÆǔUš°ô@Þ¦‚ƒUnUĠ¼ŎÓĢxĠ_²ÇĊƒǬ°ŽȂamōšçUÇW@¯öʓõʉX£ĶťnɻšÇUˋmϙ¯˗ӑѡᩃaΗƒœɜ°xWƴUxɃÒˣ¤Ʌwğ„ʉōóÝŹ±°ȗ@¯„ƃ²¼","@@ō™гwȁ¥Ƨ°ŹÑķV™¼ÞêĊ»‚lĵšm¦ÅW@ĀôÈźaɜxÈbÞÆĶIОŘnIÇŃÛÝĊÑĠƏ"],encodeOffsets:[[80022,41294],[83914,41474]]}},{type:"Feature",id:"6543",properties:{name:"阿勒泰地区",cp:[88.2971,47.0929],childNum:7},geometry:{type:"Polygon",coordinates:["@@ɲˣĊIÈ¥‚ÅU±Ċýkō°ƒĉƽó»ĶƽXóʵʵ™ȯƑÅȁɅ¯ĉ@ÇሗK֛@@ˤV֜ʵрƒǬVĸƑŎ@ƆϯÑóŽķ@ʇ»ķ¦έmlÈĸĊX¼WźÛÞÝѸ‚ĢČþ„ĀĊôάVö¼ĊUƨ°°èŎČUÜƐóôVôôŽ²êȘlˌç°`n²ǬŽĊaš™ƒÛ°±kğmm»š@°ÝɆÛÅÇVaݍVm͔ğôÝÈb‚„@„ƒ™n¯š™ÜUĢÑĊ@źīżWŤÈǖWôŁÆI²ÓƨL@ŽĊX„mmÑÆ»ȰÑkƒĶō@ý°m—¯"],encodeOffsets:[[92656,48460]]}},{type:"Feature",id:"6531",properties:{name:"喀什地区",cp:[77.168,37.8534],childNum:13},geometry:{type:"Polygon",coordinates:["@@Č@°ƒĠ„ôÓô@Ŏĉ@Ƴĸ@Ť£ĢlVôWVóřXĉŤêÞ@ƐÒĢÑlèÈV@šĠIk°ÆŘ@ÈÈĀ@ǶťÒğ@š„@ÒĉlŻ_@šƧĖÅĬōÆ@bźÞnƒƒlVœÝĬšWƼʇ„ƒÝÅ@ÇÅÈwWóĉ±ğz‚ĬČƨƂÝIĉݯbÇÑĉƒ¯ʈV°xUŰĊ¤ƪ_ôÓɚI@lȚXȮ™ŎlɴȘ՘š„¦ɲÆʈ_ɴŽźŽôÞʊŎĠƒɆxˤ£ɄÑVwXƳ¯w›ɛŹ٧™çƧ¦ōƒُ͇еϻɃɳU™Ý¯@ōÝŹš™@݄»mğ™»ÝKkŁżřɅƅƒ¯ÆīĊ»ôVôĕÅUĉéV¹ƨém™anѱĕnwmwnÇۄyĉ¹ŹlŏkĵèķmōÞġKñÔċKÅèĉzƒŽ„ômxȗÿƿI@þÅČÝKÝ°@¼ÈVºš@ÅĢšÆUċłn„ÝÆǕČĵJm£ÝJ¦@ĊƒxV°ƏLċ¼ǩ™@™m@ÅĢómÇÆğ¹Çš™ÆšĖÞKšx„wô¦ÆÑÆL²ÆƾŽU„Ž±ŚÅŻĖ@ĬŤÈñ„@ǔÇx„Èǃ","@@VÇ™ţ°ğUĠ¯mk¯ó¥ķIġÿƏbƒ„ĉa±ÒĸĀlKU„_m»nwšŽ„m@ÈŤ¦ĉbÞ°±Þżł̦°ĢŁVé"],encodeOffsets:[[76624,39196],[81507,40877]]}},{type:"Feature",id:"6542",properties:{name:"塔城地区",cp:[86.6272,45.8514],childNum:7},geometry:{type:"Polygon",coordinates:["@@ήnĸ¥ʈ¼ĸ@ôϰÒ@ƅƒōUķƑǫʶпU֛܃LګK@΋ĸ@Æ£ÞġÅĠċšLV݄»™@Å»Ýnm¯š»nŻĊ@nķŃ@¯ómóÛÝǟ¯aÝóȭ¥ƒšōUmxĉbÇї@›bUº¯X¯ÆƧbVÒĉnǕw¯°ƑŽV„—ŽÇ@kx±Uƒšɱn™ŽÅKƒ„¯ƒĠǠU°ɜL@°ƒxnĬ‚ĀŋŎÇLƒŽğšϱÞέƜkôÅĀǕłƒĸĊŤUŰĢ°„¦ȂϰÜɨ°x@°żǠÆƈČVĠ»ČL°ÇšbĊÑ̐óÞlĶwބɆVÞwǬxǪţȼÜLŐĶˢ@","@@óKĵĀV͈ĉłƾNJÆŤƒzXl°ƒÆL²¼źŽôÈĢǔ™¦l„ô°ɜÞʊĠğŃm»ʵƳƑʝȗīV¥¯ĉ°Ñ@ŃÅI™»ĉmğn™ƒašƒċƨbš™Vğ—w›ġ¯@Uōa™ĉÝJğÑÆŎkŎÞĀlźƒ¦"],encodeOffsets:[[87593,48184],[86884,45760]]}},{type:"Feature",id:"6523",properties:{name:"昌吉回族自治州",cp:[89.6814,44.4507],childNum:7},geometry:{type:"MultiPolygon",coordinates:[["@@መL@È°ĊȂɆƒÆĊ£„ťôWÓɆbĢÅŎƒÆ¦ČÑW¥°ķU¯ƏŃVē±Ý@ó—ç˜ĭɃƾřÆķkwŹƒŤ¹ġ¥ĵKŏÅXmˍщwǓ¤Ƒ@wóōVķ£ɱšġôÛa±Òȁ„óèţIVŽƽ¼k¤ó¹ġJmx—»ÝUƒ²™@ÅƃĸǫŎ„ĊmŎǬ՘"],["@@Þô°bÞǠôÜôn@°ĸń˜Ƕkłƒ¼UޙKğȂÆÝĢŤķ@@ΌڬL܄K@ˣȂ˭lĉńW¥ĵVÆý@ŃÞēUŃȗƅ@ŹƩǕĉ»k»Ç™VğóřX™ŻKƏŽċêȁèÛŎġƒͩń"]],encodeOffsets:[[[90113,46080]],[[87638,44579]]]}},{type:"Feature",id:"6530",properties:{name:"克孜勒苏柯尔克孜自治州",cp:[74.6301,39.5233],childNum:4},geometry:{type:"Polygon",coordinates:["@@ˎǫĠƽ°UUĉ¯±ȁÑmƒ„¯Ýōˋō™wUű»ÅƑ°ƒȘ@²¯ɳʇ`ɱŃ¥՗™ɳȗōkȭšșW@kəJóÔƩ`ĉ£Vů¯wU°ʇĊ„ÈÒ°aĊÞÞJŁċƧīĠyĊ²XôÇxÈÆÆ@„ÞʈƒÅ»™XÞīU›Ƒkm„ŹÝ@aŎÅÆīƨĕ@™ż`Ċk@љƒĠ@ŦÑ@ǵÇÿ@ÇÅŗl¯ğJ@™ÇUkçġÒƏÑÝ@ţéWĊôŚUŽóXUġkţ¤ķ@@ƴōĊó@óÔğƒ¯„ċ@@Қ¤kôˣŰ͓„k»ƒKX¯ċwƧôğɐšÒôIVƙš¯UķǬķšnŽ™¼ôb°ÒȰVVÈÞ°ƒĸó¤V¼°„V°²êƒlĢ҂Uƨ¦ôȰƴĊVV¼ǖIċĊ„ÞɜéšnČW˸Ǹša„řÈw±īšçĸ¤ĊšôšwšŽĸUĢ¦˜éǖĬ„Āô¼lÞkÒ°x°ƆÞx„šÆV²ǔ»„b°wގȘ¥°n„šŎV@°„„ʠè‚ŰȂb"],encodeOffsets:[[80269,42396]]}},{type:"Feature",id:"6521",properties:{name:"吐鲁番地区",cp:[89.6375,42.4127],childNum:3},geometry:{type:"Polygon",coordinates:["@@ôK„ĉǪa²¼lÜô@ʠê°Ĭ™ôȂƒ²ÑÜbĢóɲ™ĸ¤ŎUô@xƒŽǔ£ъxˎmƒÈÛ@‚_nĕÞōšř„ǫƒğšůlȯ„¯ĸ»U»Ükôƛ°ůkť™»Ŏŗ@¯@±͓óͿ„Ǔ@ķȁ¼Ϳ@Ƒ¼¯°ólġ¯xȗUġšƑ™ǩÒƧUÝ°˹Kóššx@ǸōĬÅĬƑĠ󃄚ǔêÆ°XÒʟŤUšÇ¼ˋnn¼±V²°ȂUŌݜbʟǔɅô@żǬaҎÈ"],encodeOffsets:[[90248,44371]]}},{type:"Feature",id:"6540",properties:{name:"伊犁哈萨克自治州",cp:[82.5513,43.5498],childNum:10},geometry:{type:"MultiPolygon",coordinates:[["@@ĉ„ÆŘȁ̐mÞ¯ĀX°±¼@ƾ¯ƴ°ŎÝþŋ¦WÜÞbȂĉźUœÇmwVUȂóô@ȰÝ΀nÆJn™ƾ™ʠ™ŌLČóǪ¯œ¥ǔaǖšŌaôÝĢLšx„ƒÆLšɲm„™²VlwÈ@˜Uƒƒ°¯ǖxĊmUÑƨa°Å°WV¹œa›ÇɃÈm¥°¯ŹóĸķǫUm»Å¼ÇVɱ™l݃ŋnķÇÝX¯ƒͩÇɳa——Ý`±_U±ĵnWƒ™a@™ĸóšķ™¯ǓV±ÅĵJċ¹ɅykwDŽ¯£Åxʟ»ƒlķI¯ƒX¯ķ‚™êǕƒȭnķ»Ź`±„kÞ@Žš„Ýô@Þ°xšŤŎIƨÆUxōš¯²ǔĬǬlUŚ"],["@@ÞĀlźƒ¦¯ĸŤKޙšƒċƨbš™Vğ—w›ġ¯@ţƽJ"]],encodeOffsets:[[[82722,44337]],[[86817,45456]]]}},{type:"Feature",id:"6527",properties:{name:"博尔塔拉蒙古自治州",cp:[81.8481,44.6979],childNum:3},geometry:{type:"Polygon",coordinates:["@@ήƛϲÝĠ™„ÈKŌōÿmī„w@¯ɛKV¯ğǟ°Ƒ™wġKóÞŋbǕ™Ǔb›¦ǩ°ċôŋKʟšƽšmšÅImŽͿŽȯÞó@ȁôUVnx›ÈŹVȁĊÝabŻ£¯°l„óxȂŤĸkĊšÞyĊêĊmĢxV„ƨÈŽĠX„ŽΘÆĠÔź‚Ɇţ°LXƾŤŤb"],encodeOffsets:[[84555,46311]]}},{type:"Feature",id:"6501",properties:{name:"乌鲁木齐市",cp:[87.9236,43.5883],childNum:4},geometry:{type:"Polygon",coordinates:["@@šŽWŽôŚUĠȚl¼Ċ¼ƪǖ@źȘƆ@ýlܚXVŘޙš¦V¼kĖó҃èkĊȁˮ֜@ǫ՗nōƒĉǬō„ķÆŚ@„±ÞV˜¼nwĢIôºl£ƾ»UŤJôçšó¯īʟéó@kÛ±»ǩbƒĊóLҍÇǫb@ŻɆóʠǓ›aŋÞȁVʉłĉbĉɅô"],encodeOffsets:[[88887,44146]]}},{type:"Feature",id:"6502",properties:{name:"克拉玛依市",cp:[85.2869,45.5054],childNum:2},geometry:{type:"MultiPolygon",coordinates:[["@@ɜÞʊĊýVaŃm»ʵƳƑʝȗīV¥¯ĉ°Ñ@ŃÅI™»ĉmğn™ƒaݚţL°ķóKĵĀV͈ĉłƾNJÆŤƒzXl°ƒÆL²¼źŽôÈĢǔ™¦l„ô°"],["@@ƾIŤ@UUwōa™ĉÝJğÑÆŎkŎ"]],encodeOffsets:[[[87424,47245]],[[86817,45456]]]}},{type:"Feature",id:"659002",properties:{name:"阿拉尔市",cp:[81.2769,40.6549],childNum:1},geometry:{type:"Polygon",coordinates:["@@nIÇŃÛÝĊÑĠƏō™гwȁ¥Ƨ°ŹÑķV™¼ÞêĊ»‚lĵšm¦ÅW@ĀôÈźaɜxÈbÞÆĶIОŘ"],encodeOffsets:[[83824,41929]]}},{type:"Feature",id:"659003",properties:{name:"图木舒克市",cp:[79.1345,39.8749],childNum:1},geometry:{type:"Polygon",coordinates:["@@VéVÇ™ţ°ğUĠ¯mk¯ó¥ķIġÿƏbƒ„ĉa±ÒĸĀlKU„_m»nwšŽ„m@ÈŤ¦ĉbÞ°±Þżł̦°ĢŁ"],encodeOffsets:[[81496,40962]]}},{type:"Feature",id:"659004",properties:{name:"五家渠市",cp:[87.5391,44.3024],childNum:1},geometry:{type:"Polygon",coordinates:["@@„çôÑlĕU»™¥ÝšUŗ™WkÛ@þVńÝĔ@ńÅþĶUX¦Æƒ"],encodeOffsets:[[89674,45636]]}},{type:"Feature",id:"659001",properties:{name:"石河子市",cp:[86.0229,44.2914],childNum:1},geometry:{type:"Polygon",coordinates:["@@lŁ—ǵm‚ĉ@mż™¼n°ÞmƼš@"],encodeOffsets:[[88178,45529]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/xi_zang_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"5424",properties:{name:"那曲地区",cp:[88.1982,33.3215],childNum:10},geometry:{type:"Polygon",coordinates:["@@ƨʔĸbܺÞwnxźbÞ°ô@„ĶŽĸIȼĊJŎÈôUšÝƒ¤ǔLސŎ@ĢŽȘblƒôL„ÇźçȤôLš¥ÞIÞ¯Ķxʊťƨ™ƿÑĉXVķŦ¯ȂKÇǕšÑ¯IUš£¯Óƿ£VĕōÞÿÆwƒƑ„£ǖxÞĕ±ÇÝaUÑȃU¯‚UōÈ݃wWŁĵ™±Ý„óĢÿ°IÞ±mÅĢ¯mÿ„¥°UnÑŤĢĕĶwǬŻͪwŎ¼źÇĢ„ĠĕˎŁ°óƨ¼Èa‚m@¥°wǔ„ǖ°ŽƨÇŤœšġƨ„ŎŃôbÈÛŎĊ°@Ġw²ÑÞJƃÆb²ƒ°êĊUނlȲƒV„ÈKĊÒĸĉ›»ÅôťUÅǃk¯@ǂÑklǁÅl™Ģ™VÑóƒ@°@„ÛĸƒV¯ƒÇĊ™n¯Uĕšƽ¯m›¯b™È@Ò°Ĭƒbĵ›¼„‚kxķýÇJk£ÝaUÑÅóĶǟkÓʉnĉƒÝ¼Ƒ„ó»Þmn£m™Č¯@ƒȮÿV¯ĸƒ™k@Ýówƒ»ğ„ġ±ǓLō„ƒšV¼Əèķĉ™è±b@Òţ„UÑóakƒl£™Ó@¯L@™ÇlUóȁš¯aġÈÅĕÝLķ¯Ė¯@WĬ—x‚ÒÈnW°ţôU²ǓÓġ²V°¯ôƒǔÝL—ċšk™š»Ý»Ýš¯ÞƒVƒwۄÝÇōͩÈĉċ»ĉm¯£W¥ţKkóġƏW@¯±kōŽÈ›b@җšÇaƒÆ¯a™„ƒkóŽÛƒÇ¦Ýa¯šÝ™ĉ@ǻۄmƒǓxķƛ¯lVĀÅÞġb™™ÇJUÅV™ĖƑW™zō»ōšƒW™n@è¯ÞóVkwƩnkźÇބҙޯƒƒýğÇUxÆÈnè±bĉÝ»ÈуwšwÞ@m»ÈV@ýÇ°ķ™xƒa„ݯXċ¥ƒÈóW@ôkxlnxVÈóĊkŤġ¼@°¯ŰƑL̻۱ŎÝV—Þ›VƒÇÞŎÇakƞ‚š@èğŎĸżšƾ°ÒšLÞôĠKȰĖźVÈÒĠ„¤™VôšŽU„ÈþťL@ôǬÞlÜÈnÇÒUŚ™@šĊƨW°™°Xƒ‚@ČÇþ„ƴĉÒķ¦@ŽĢôWĀôłUÞĢǬ™ź°¼š@ƒôV°„bUÆnzm¤ƽĸƒÈ"],encodeOffsets:[[88133,36721]]}},{type:"Feature",id:"5425",properties:{name:"阿里地区",cp:[82.3645,32.7667],childNum:7},geometry:{type:"Polygon",coordinates:["@@„Çƾķn£myVŃaU¯„ó™@¯»šŹġǫVÝóŁXÿġó@ĸ¥ĊуƳÈý@ċ„Wš¯X¯ĉƧ‚™š@VřÈÑÇmkÛǫÝ@óŦKÇýVƒ™U󚏃£ğÇÑŹUȯĕğLÝó™K¯Ñ™ƽķŻĠō@灙lƝÈbƍÈ݂„œU˜ÝÞU²ō̼ůƒK°ů@¯UK±—ĊƧbōÇmçÈġƒóšÅób™™źóš¥kīƯól™ç™KôĵUƒÅ„VŃķ¥nÅŏm¯¹Å‚™»@ÑǍóxÝkʇȤU¤ķb@ƒ¯ĊÇx¯ĸĉKm°šĀk¦l„„KnĬȀƾÛ¦WÆŐmNJĉ°ōUţ¤UšŎ°šŎKÞłÆ„Ǔ¦ƒÞ™‚™„ř¯bmUÝl¯Um™ğl¯£șwŎǫaÝnĉĶƒk@¯™K™šō»ĉn™aÞ»ťnkml™ĸ¥UŚŻkÑťƒĉV™ôó°LôīĠU„ÿĉǕÅz±Kƒ¤„²ō¤¯Ė¯UÝ¥Vĵ™óÈťÝwķșÑk¤ó„™ƒWýĵĕ™„VĠƒV󍃎Ǔ„ķ°k±VU±ţ¦UǟÝřJVљ¥XUċUŎlÛƆǕÆȗƆ¯wŏÞÅ@™šĉl݁óŽƒÒ™nUôńlxólÝôێ±™™LÛôÝL@‚ġ¯X¯ÇUżóa󤛼XÒġŎóLk¦‚ôżĸĠ™¼™KġƆô¦„ÆƑÔĉĶ¯ImÒ°¦n°¯Þl˜ÝČn„ƒÒšKĠޚĕkƒlýƾťœšôI‚ĖŤÒnƜm¼¯lnżóÞ@Ůó¦™ôƽĖċŚn°Ý°ôÈUƜƒblÞóŽ@Žǖô°UÈƆ°X„þôŽô‚lѢšŽ²Ėm¦°š@¤™XŽĊblܚzkºƒĖmX„šŎWVšóÞn°lĠxȚa°»żLźƒ„b@Æ°XĠÝȚxĊĕŤaȚ‚°È@„„@èŤ¦Ü¼œW˜ÞkŽÈ@V°lŤkŎ±²¦ƐUšlj°aÈÑŎbĢƒŎbÆ¥ÞIȘlššôVÈU‚™šb„kɲĶn„mnXb̼òƾĖŎ@ĢȂÑôÓĠĖʊšĊÔ"],encodeOffsets:[[88133,36721]]}},{type:"Feature",id:"5423",properties:{name:"日喀则地区",cp:[86.2427,29.5093],childNum:18},geometry:{type:"Polygon",coordinates:["@@ĶĖXþš„ôƒl£šÒĸÇÞxÇŦšôUĶÞ¦°V°ĕŎ£ƒ±„£²LÆyĊǖƒĀğVóĬ¯KóôUš‚ĊŦ„lҙżVÆķ¦kšlnŦmݼšbĊmŎ¼š™šL@°„lĊĵÞmǬbƍȚx°¤Ġknš°VÞkVn°aƒŚš‚š„Ýǔ¥ÅƒÝŁōL¯™ōV™Ť£ŎVĊ¯nljƏXÅÜ¥ǿƽmīƒLkƒl¥™ÿn¯ĊL°ķÈw°ĉ@ƑĸaV£ʈȣÞlôwȎ@Қ¼Æ°ºŐnmÆĸ¦UńƃV„óĶšLšèôkÅ°lĬ™¦Źôššôa™Æ„ôÇĢnèŎÈƨa˜ĉ²‚VLĢ»lţôĉUǂwkmlw@óôX„ÇȦ°WƒÞ„b‚wĸšÈ¯@þÇUn¼Ý@™x„xÇńÞ¼ĊŽ²amçÅÇVwĠȄþ°„šÝƒÑÈÝlŹƪmlxôU°Ý@çšm„XŎ™Ŏ¼šyƒXšĕÆUVÈIššĢaÆÝUÿ°kĸƜǔwn„܃ȼĊ@ޚ°™Þbȥ܄ô„lšƒ°b„ÅÈb˜™@ќa‚ǯUU¯Vġš»ƒ™¯aV¯Ç°Å™mnÑŤçǬVǬ™±ĉ¯¥Vĕ¯Ýk£˜ō—w@±ġÛ°ÇVїƒ@ۘa@ČL™Ƴ™„ƒÇa¯¤ÝIĵ¼U¥ƿōķÅţŻókÝóĕ‚¥¯™U»Æ£X¯ġŃÛkÝ°V°ó¼¯èWôÞĖ„ȎƒŽkĀƧĀówm¥¯JŹÝJݙōVVŁaݐƑ@ƒ˜ğŭǂ¯_ƒ˜ĵ—›VnxŃón›ƒĵxÇĖĉVÝÈğV™Ò󃯐±Żĉ£ķÆÅL™Ljĉý˜ţۃ¯VƒnV¤ÝÈ@°ÅÞݤ™ŰğŁm¦ÝxóKƒ¥ɱÈUĠôêVôÛ¼ÇWÝçĵaō¦óĖƧlÇĢƑŽnŎDŽV¼¼‚ºÛ@m¦ƽ„ĉmm¯ÝKÛç¯bŏłĬ™bƒ¼ÅLmŽ„xť°ÅU™šÝXkŽÝmĉ¦W„¯K„ÒknÝaV„Ýè¯KɅńÝKnÞ¯¼"],encodeOffsets:[[84117,30927]]}},{type:"Feature",id:"5426",properties:{name:"林芝地区",cp:[95.4602,29.1138],childNum:7},geometry:{type:"Polygon",coordinates:["@@‚VÈłVôÈk@š°K@ŽšÔk¤l„ôbVÒŤƒ@ѲašçĸĊƐçU»„™ŎƒǔKĢ²Ġƒ„¼ôx@ޚlƨĬ„Ul¯ÈLV‚šÞJ„°Ünʊ„wÜbXê‚VÞ¯°ššanaU°wƼɴÑWÑ°mÈýÈam¥Þ£Ť@„¥ôblÞĢ„ź¥ôxÈÅmݚ™ƒĕŃV»ĉōŤōnóƒ»ÈīķIUƒĠÑ°ġĸLÞ¯VÒƂ@Ābš¼WôÈ@V¼ôóŤKÈÑU»šwVǫżnWÒÈx™¼‚lŦ£ĊōŤx²¯@ƒÆƒU¯šçÆ@„¤°£„é°k°lšůÈó@¯ŤÇÈĉƒkkÿó¥ÝXķљÜ@ÒóŚÝ¯°ĉówÇ±¦ÅJUÒĉĀķw¯°mĖ¯„±akxÝÅnƒ™»lуK@¯lU™¯UVѯóĊ¯mōğVǓƅƒÞƒWÝÈÛ@ƿô¯ÜġzÅþ¯ólmôʇġĊÅUͿřŏȁˋŁóÇˡōƧƒÇb™w°Ķôk¦šÒƒnUþġҙÔkǔķèó@ƒ²@ŘōńĵyƒzġaݤÅIƒ¤Ƀť¦ğѯ¤ķbóš¯ó±ŽU²°¤ČÜVnÈƂ„ŚŎ°ôĢ„þÆzèVĀǎĀǘƒXŹÑ¯¤ówċķk¦šłUÒġzÇ@ƒ™ÆÝx@²Þ@Ƥ„Uô¦Uš°x„U"],encodeOffsets:[[94737,30809]]}},{type:"Feature",id:"5421",properties:{name:"昌都地区",cp:[97.0203,30.7068],childNum:11},geometry:{type:"Polygon",coordinates:["@@™ŽVĖm°ĉš„ÈU°ķ„ƒÜ¯@@ô„UÒġškš‚ÆkÈlŽÒ@Èl°È„VÆóŦƂœ¼‚a„ÅĢ™Ʉwnōw@¥Ŏ¦°ŹÞmVš°wnÿƒw„wÝw@¯šmÞŗ°wĠ˜ĸkÞğlĔ²¦°@„ĕĸwVóšal@nĢÇĊn°@¦šŽźUXçǔůĸVš™ÆK„ÈÝĠš²ÅĔô@lšŽÈ_m˜„zǖl„šaU¼ôwV°¯¦‚ĬÈa„l@Čǎ„¼™„nŽ˜I„xô»ɜ@ƨ¥ɆŁ„ŃǪȁkƛƨȍʊȡóĭ›@—ÈÇVƒůރĸƅmēƨť™ÅÈʉVǵ°ġVŭÅɧ°ÿnɛš£mƒķ²ŃóÑUĉ°mÇ»¯@mxUĀ¯èţ°ȁÝç„ġU¯ÆÇţÈ@°Çô™Ű¯k¯lƒê¯¤ƒ£Å@™èV°Å„@„±°ţwĉŎť¤kš»ÇwXÑŻmUǬ™xV¼ÇÒţLóôU»Ç@X󙻂a@ÿŁUÑÝ°ķK¯ĢğÒV„ĸJÇĬ„¼môţŎĊŎU¼Æ„„Ė™šnÞÇÆówŹ¦ġƒkÝóaƒ¦ţ@ݤn¦ÇbÇþ¯nXÒɳÒÅ»¯xVmb™b¯™Ý°UWéÛaƒxʉÛmƒ¯ÝI™‚UÇKk°ƒVƧīķ„U°ȭĀ@„ċ°nšm¤Ýnô¼ƒƒÞ»Ċ„ʊmlÔĵǠÆôVÒÞbl¤ÈIĸþlwƒœ»ĶŽ„a¯ī@њǰanœƾ°"],encodeOffsets:[[97302,31917]]}},{type:"Feature",id:"5422",properties:{name:"山南地区",cp:[92.2083,28.3392],childNum:12},geometry:{type:"Polygon",coordinates:["@@°ÞUĖ°¦²ĊôÇÜLǖĀɜŽȘŰÞLĸźêÞ@UÜUŤ°ɞ¯Ü„°WŦĀmŎ„¦ĢyVљŁl¥Čĸôx°£źÒ„Wȗ‚ÿȍUÿ‚çÅyƒýóġō¯ƒřŁmÇÛUċŽ¯£V±²°ôô™ĸa°£ĠÒŦ¥ɄŽ„£ÆJÞ£Ģb„yĶzŎŃ@ŗ„±ô@ĸçlǓšÓĢÑVý„m™Ñl¥ĵó‚¯̻̥™ƛǫÝһÇƧĉyţ¼ҍēVĶĉŎ°ĸmšÞVÝĸ™ÒÛaċ„ó™ŹĖƒèÈÈl¼k¤ÝX@`ސŏ¼Æō¼ÇçĉKUÝÝ£ğ¤@¦ġl¯Òġĉ¯óš™móxÝÞğVšƴċK@—b@ܘ„UÒ¯ÈĢÜ@²˜x—Ŏl¤"],encodeOffsets:[[92363,29672]]}},{type:"Feature",id:"5401",properties:{name:"拉萨市",cp:[91.1865,30.1465],childNum:8},geometry:{type:"Polygon",coordinates:["@@Ŏ²l@°‚XĢƐlôŤLX¦°¤ĊnČ¼ÇĊŎͪÞÈ܃„x„U°Ýޙ޼™¼lšČ™˜ŽÞK„Ǔ°óU¯Ģ±ǔÔV±ŤóX¯ÇmÑ˜wXī°@°ĕĸÞKÆĖĢÇ°bȂ™ÇŁUƒV¯wV™ó¥ƒVÅ£Ý@@±ÞwšÅ‚„È@ƒ¥nōťÿ¯Xۃɝ°ţ¯ÛVVÝ@ŹéķÝKȗůɛǕÿÛKóÈǫšǫUţèmҚn¯Æ°ÈU‚°b„š™¼UĢV°°V"],encodeOffsets:[[92059,30696]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/yun_nan_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"5308",properties:{name:"普洱市",cp:[100.7446,23.4229],childNum:10},geometry:{type:"Polygon",coordinates:["@@U‚ô²‚a@Ž²²Ķ¥œV°šĶ²bl¤kVxl‚@œ°‚Ś²@˜„„y„@ô¦¯„@xƒxVxU„VššbVšÜm¼Ŏ„„ĢmºXXWÆ@ĀœšmŽmXU°ÅÒm¼Þx°w„@°‚XêĠ°»nV°U„l@k„@V±ôī@£‚ƒČŃÆ£„KÞý@¥‚k@y„a@—nWV„UVƒšwƒmƒ£Jƒknm@wmkn‚X„˜šX„¥mUUlUnbš¯°ŽnkƒVInlIUw°n™mk@@mlanXlanmšk@wVWUw™_@éĠašnmUaÜ£ƒmXƒ¥¯@@„óUmݯ¯ÞÝlKnxô£š»„»Ġ„J°aV„UÝÿV¥ÛbƒI@wmŽón¯yÛL@ƒWkŎmș`IWa¯K@¯mUnmaXm™bmak„¯ŽƒĢ™ÒÝm¯mV¯KÇb¯KۜWW™X@a™V™knċLUWV™kXóW@k™a@ƒób¯Uƒwmb¥UUlaU¥U£maķšƒKXkƒmÝ@kwmѯk±ċbUUVakaġ¦ƒƒkL@`ƒœ™a¯xƒm™Åƒ™LUWƒ@ċnŎUV°LkL@b°°@¤š²ƒ‚šnôôk„l°kè›ÒÈzV¤È„WôôƒnV@„ƒ¦@¼Ux"],encodeOffsets:[[101903,23637]]}},{type:"Feature",id:"5325",properties:{name:"红河哈尼族彝族自治州",cp:[103.0408,23.6041],childNum:13},geometry:{type:"Polygon",coordinates:["@@°°nÞôV@ƒ°@„¦WŽ„nÛ¤Vbmn™ğb@êš`VxUX@xš„ƏÞUnn˜WÞĸĢƒšÈ@ŽÇè@zÛÜWšÅêlš²„˜KnV¯ĖĊx@bk@@„°JÆ£Èbl„nnm°nlUkVUUwVm„Kn„‚nVŽÞxVLX¥laX@@xl@VzȎVmšk@b°šÈĸmŽV¦`W„XšƒbUb‚bX¼°x@ašVVkn@lþnXUlVxŤÅ„y‚IUƒka‚IŎĊ@lXx@b„z@‚ô„ƒ¥„_V@l‚n@„ôy@al_l`nmƒÈ»@kƒmXwWK™U¯»™a™Å@wƒmUÝKUa™UUƒ™wWƒ@w²»@kƃV£—mm£VKkÑV@@»nwƒ¥™ƒ@kƙnllIVlnLVakalknJšWmnaUaVÑVVލn¥m@ƒ„¯Uÿl™@™™™VçƒaXaV¯UyVLVkš@nJlšXLlŽkxlbla²Òl@nVJVkšx„KlkUaVķÝÑU@Åm¯@±™Uó°ğńķĠmU™Ñ@ǯ¯Å¼@nml@°¯¯`@w™£@¯Çƒk@ƒ»nmċ¯U»™I™Ž¯LÇĶÛn@bó°™U›šwmŽ¯„™Umǯa„™ƒ™ƒI@ykIƒVUŽ¯bƒIğŽƒ¼™¼ó¤mwkLÝÞ"],encodeOffsets:[[104243,23429]]}},{type:"Feature",id:"5326",properties:{name:"文山壮族苗族自治州",cp:[104.8865,23.5712],childNum:8},geometry:{type:"Polygon",coordinates:["@@šwô„š@²¯maUmôUÆxš@Xš˜bÞInlVUVw„JVaU„K°¥„xmÞXnlKlnna°@ĊČ„ÆwUmnkl@°ƒƒ£nyn@VV@Vak™ƒ@@kÞ݄bmx°Vnw°klÞInĖÞVlKl™@Xa°„„KlV„U@šJnx‚U@ÈĢbUKlm@ak_‚wšanWUk°ƒl»„k@Wk@lwU_ƒ@UalóU¥ƒÇnƒ™kJWƒ@mVXx±bƒK@nV±a@™Åa™£ÝK²ƒWknamKknǏk¯ƒaV™™V¯ĀƒU™„™Ò¥ƒI@mm¯¯xōW@@`k@ó»ƒUU¯lm£ÅWlĵ„w@mmwÅmWU@y±U—xmwU„¯Uƒ¥Ý¥¯£m@kŽÇVUV°VbklƒL™wUlUIm‚k@±ÑkbkalwkWKk™mI™@UlUKVzU°Wb„bU蚚@škšVĀƒ°@„n‚m¦ÝŽUUUÒVbmbXn™‚mIkllbUbmKUkkJmkŚ@lš„„¦mx@¼U@lÒULn¤˜nU¤Å„@l±¼@xX„šxV„šVVbÞLVŽ„n@xšÆšb°¼šV"],encodeOffsets:[[106504,25037]]}},{type:"Feature",id:"5303",properties:{name:"曲靖市",cp:[103.9417,25.7025],childNum:9},geometry:{type:"Polygon",coordinates:["@@ȦlKÞĕUV¯Um¯„ÇVUnVVUƒĉn™ĊÇƾLn°°È„JÆw„@lbÞa„¦V„XJ°¯W¯„aÞJVkUša„ƒ@lKnÅmWUk¯a¯»@m±@уkkbWWX_WÓU»_l™kÑm@U»m@l@IWċn¯l@VanV„UV™UVwVx„KȄVmUē‚@„ƒn@VÝÆL„w„VVwnVlmkUVÑÇ°ka@k™ÿÝaÞUl£™›—ċĕX±±ĉƒa@UnVnalónk@wl™UVmkÝJ—aW™™@ÅwóVVnnb±°™@óƒ™xXLWx„n@lǼn„m‚k_k`@bózƒ‚m@kU@ƒ`„¦óƒ@nWš@ÜÅXWw@ƒyƒb¦@ÒlnUb@x™lܐk‚@²Ç@Uƒ¯bmy@kV@bƒb„¦U`lLVx@b—Ll¼Þ¤@„°VVބU@WސUb›J@nnš@lnnm„šxUŽƒUUbƒK@šÇwklkUƒVWakn@ŽlbU@@„ULVxkKUn‚°¯Ò@¼™„kmƒ¦m@kl™Ȱ@lU„l¦„@Vl°wšnnþĊUÆbUx™b„ŽV„šĖU°„a‚nnašV„al@@b"],encodeOffsets:[[106099,27653]]}},{type:"Feature",id:"5323",properties:{name:"楚雄彝族自治州",cp:[101.6016,25.3619],childNum:10},geometry:{type:"Polygon",coordinates:["@@mҁXU`Wnšš™@Xl±¦š„Uxnbl°knmKUx„„ƒxVôUx°¼ôÒȄ°JlnÞKĠœW°¦ƒ„Vx²JVwš_°¥@UV@@wnymknK¯I@‚™²b°ƒš£V¥šwU‚V„¤nLškÆJÈwôô°„l»Č¯ƒġVƒUU@@ƒ°ƒƒÝXl@U»°Å„@U„¯@w±¯VmUUlm@m™„ÑnIVyUwmak£Vwm±—@Çw@nƒ@UxkwlÇnL‚mkř@±Žk™ka@kóJV¯Ç»U£lw¯™Xalbl¥¯UXƒ@a˜™UaÈL@ÇVIVƒkaU¯mm™akLWkUJ¯Umxnšƒ@ƒkUx¯xƒ„mWÅīÝkkbƒŤƒbkxWmXwWk¯wƒKkƒƒLŤċń„@¤óĬU²ƒ@@lƒk¯VmU¯¼@xV@k°l°kbUš°nm‚VnUš@°„š„UVèރÆbUÒÞnU¦›V—¼lô„@Vl"],encodeOffsets:[[103433,26196]]}},{type:"Feature",id:"5329",properties:{name:"大理白族自治州",cp:[99.9536,25.6805],childNum:12},geometry:{type:"Polygon",coordinates:["@@lbœKVIUa˜@²m@b™xôÒÜxXLmbnšl@š„„K°šš¼k„Uô‚xôlV¦nJ„Uš™Ænšm„@šx„ÆwšbXšÆôô„LUVwôK@wlmšaVwœ@WknmƒIUmlnJla@_™@kÝmKUašÑm¯Xw°aUaVl»²JV„bÆJkôĶĀ²VVk„mšbVwUó„wƒƒVwnLlmk¯maVw™ƒ²¥Wkš@™™XmV_‚WnÑUkƒ@k󘻜UV¥ÝmVÑÅa݄UçƒVƒ™@¯V™Umn¯mV™lak¯l¯U@@wğŽW鯁ƒ@¯xÝw¯š¯Jċa¯U¥mLU¤„bÞȤƒbÇLWUwmIUVW¼kbš`U„Vb¯L±ĊÛkƒÿÝKkwƒKţê™UĉþƒÈƒV¯ÞVbUŽ°KVšk²Ý‚mI—ƒmV@kƒm™UkšVxm„¯KXÈķJU¦V°ULWxšL@môƒšb@bkx±LnVUŽVLnkÜWnwlLŃmW@kkJU_ƒV„šWĊ„Þ"],encodeOffsets:[[101408,26770]]}},{type:"Feature",id:"5309",properties:{name:"临沧市",cp:[99.613,24.0546],childNum:8},geometry:{type:"Polygon",coordinates:["@@‚xĢ„l`²X°ŽV„šx@x°Þ°KXašğUњW‚bnIl`X²°b„xl°„„šV@xVxk¦mb„l@xšXV‚ÆzX¤™Æ˜k°„kx@lźêlaX»VUnJVx‚XÈK„aÝȣƒaV£nKV¦°‚Čb°I°™n»ÆÑV¯nWn›™@ÿXÅWWn¹ƒġōƒn»‚ÛU™™aU™VƒUw„w@w°ƒó¥ƒ@ƒz—ƒ±@ř›¯@kUwlk£±aĵŽ¯™›Uĵ¦±±@bó±VÝ@ó¤ƒw¯I@mńóm±XŽ¯IólƒK@š°Ullb™zkKlln@@ԙºƒUmVk²ôҙx™ŎUVóLƒb„ŽmÈnŽmbnl‚a„x@z„@Ǝ„¦kš"],encodeOffsets:[[101251,24734]]}},{type:"Feature",id:"5334",properties:{name:"迪庆藏族自治州",cp:[99.4592,27.9327],childNum:3},geometry:{type:"Polygon",coordinates:["@@W™Xwƒ™@akk@y›—k°īX¥›Uóķ¯w@n»UaVaUۃ¯ƒmV¼k‚™Þċô@n¯xÛÒm„V‚¯Ô@xƒ‚@šk™wm™Åa@ƒUa‚݁¯VŃyV„a@ÿšn»ÝVmank™mmÞÅôƒ@n£±›ğzÇmU¦™Vm„nÜmbn@°nV@xmzÅ@mºV¦k°ln¤š¼õô„n@xkƃIUxUš@Ťƒ¦VšmVkmkXW¤XzVx@ƚx™¼ƒÞ¯b@lVš™ĸގV„m¼XŽm¦V„ŽÞ@Ǝš¹Vón¥ÆKn„‚KX¯x@èĊȱłXšaÆxnlV@UÛlȻkğV¥„m²ljmÅÞĕƒƛm°„ÆmX¤mznƃŽV¦ÞVVb°bnÞWbnŽ°l@V„È@„‚VĵĊ±@ó„InxÆw„¥@£Þ›W¯ĸ£UƒUK‚ƒk±akkkbmWmÈķ„aÆÇU—ȃÆW@wmknmU¯"],encodeOffsets:[[102702,28401]]}},{type:"Feature",id:"5306",properties:{name:"昭通市",cp:[104.0955,27.6031],childNum:11},geometry:{type:"Polygon",coordinates:["@@mƒnK@wmƒUř¥mšóXǓŏmX@Ž—VƒmL@xţ™nk@mlUšŻÒğŋ@ƒL@mmLkm™š@b™XŎW¼ka¯lÇŹ¯aÇ»™ÝÝ_@m„@@a™@UklwUm@ak@ƒb™UmbmƒbV¯™ĕUƒƒšaVwÅaĉVmý™m¯xUkƒ@k¥VƒUXƒ¤VÈm`@„—ńÇÜ@Ākn‚ĔkƞÆĠ„™Þš‚U„VôƆÞI@ŽUxƦn„l@ĊĊnxUÒ°¦Vb¯WUnWŽIml@xn„Ubô¤‚¼ÈxlI„»šKVš„@ÈԂJkšUĖ±ÆVb@nœ„VÜVUVƒšL„wĠl„kn„Ġ@nx°¥Æ„²mUwƒ@m™mÅUl¯UњÑUm„Lll„Il±š@VkwƒW@w°@U»™kUóI°ƒ„»ĢтL„™š`nUĠ²lm„bôV@n„JUxƦX¦l@š‚ŎUƒV„@lV„KVřV£UaÞU™ƒnW@¯VU@ó™"],encodeOffsets:[[107787,28244]]}},{type:"Feature",id:"5301",properties:{name:"昆明市",cp:[102.9199,25.4663],childNum:11},geometry:{type:"Polygon",coordinates:["@@n@Vk‚VUn²°@xƒ°Vƒ@¯ÆV¼k@WŽ„Þ¯„@„@‚VVU„„Ģċ°k¼V„Ċxœ¤Ōœx°mVkƒÑȏšL‚°„x°Xœ°VmĊLVxUĖ°bX¦VW@kšȯlkn@„¥lnšƒ@»°Ñ¯VmlLUwVK@ƒV@ka@lmXb„UlVlkÈx@™„LVa„VV™wnƒmm@km™@mœIVaݏ@XƒVUݯU@ƒÝ£k»˜K@aUwkKV_ƒ¥„a@alU@nz°aV„È@@±lÛšk@wVakm@т¥„a„z‚@XxÆW@ÛX™@m@ƒy@aWw@kōĉJlbV„JƒzţÆUwVkmWkým@Ul™U@b¯wVºƒU™VUêšĠƒXUaUbVĊUŽWXUmkK™™WnUUU™V™ƒƒVV™Ý@kk±‚™¯ƒƒLkƒš±WkXlVklƒ@ƒwXbmLƒ›VUIVmk@Ubma@kkaVKUƒ™kmlXLWn™J¯ÒĊ°@zkºlLUŤn@@n›ô@lƁnmKkÈlxVw„@@mÈx˜@n²Uxl¤nbVxUzmJƒÒnš"],encodeOffsets:[[104828,25999]]}},{type:"Feature",id:"5307",properties:{name:"丽江市",cp:[100.448,26.955],childNum:5},geometry:{type:"Polygon",coordinates:["@@l@™„@w°ÓUnƒÜÑ°w@mČóšÝlU»n°„„VÜUbVbm¼@Ž°xôĸœVW¦¯Ĭlœ˜@zll@b„šWxXš‚a„X@ÆĠÆaXwl@XaƦn¼˜Jn@mnKW¯È»V¯°ak™VanXVwl@VyUĕVU„bÈīlaUk°ƒk¯lƒ²V˜Ukƛô@ƒ„I@mVwĊa„™ƒVaka„™ÆbUŽVLšaXIWKUw™ƒ„aWÑÅKUaVk°ƒ@Uw„ƒ¯¥›XğÝLkm¯Iǃóѯ»™aƒnUl±UĵÿlóÅIƒaU‚±Ik¼UŽVb¯bWxn°™ÒVbnLlޚ@@`kbmIkŽVn„JmnXl›@Ux™bkn@xóLUxVŽƒKóóŐW™™aÅxƒŽ™wƒ@™nÅm™šƒV™„ƒôX„ƒLlVU¤ƒb¦m¼™Ž@ĀƒbU‚„zUƂ°ÞVb@„Æbnššx"],encodeOffsets:[[101937,28227]]}},{type:"Feature",id:"5328",properties:{name:"西双版纳傣族自治州",cp:[100.8984,21.8628],childNum:3},geometry:{type:"Polygon",coordinates:["@@l²°ŽnÒlxÞ@„nWl„Lĸ™nbV¤V¦kbVV‚¦na„x°Vôa@„šb@lôXlWUšVXČKlmššU@bšWXXܛ°LÈa°LnU°‚ÞnšÑ„ġ°lƒnbšaƒ¯¯KWƒœó@kmK@UšĉV@k°„VV¹„a@y‚_ċl_nÓlL@anI@ƒóWl£VU—ƒl™kĕl™šKVw„U@™kVƒam¯ÅL@bƒ‚Ýk@Vn„UbÇbÝwÅ@ċ¥¯lk‚¼ÅŽ™Ò°b@¦nlUn@ŽÇV„mƁbWôU@ÝÅōm™¯ƒaU™™mk™WWw—@±ƒ™n¯U™è™a™Lƒ¯mƒL™škwƒl@°mnÈÒ¯šów@V™xƒĀU¤°Įƒ°Xl"],encodeOffsets:[[102376,22579]]}},{type:"Feature",id:"5305",properties:{name:"保山市",cp:[99.0637,24.9884],childNum:5},geometry:{type:"Polygon",coordinates:["@@X°„Il‚@¦ƒŽÈ¼m¼ÞaÞÅl„ÈxV¼šlVôÈÆlLޣȺlkUƒ‚ƒUw„¯UĕVwĊ@n¦mlnVĸIWÇ°LnƒUwl™šV„n@lnU˜„nJށl±U™¯LVUa°Ý„U„ÇĊýšVŤé„LlxÞL„ĀÜl²ĉ°KUaVƒ™_Źé@klw¯ƒlÅ—šW£ÅyU™W@wƒknal¥Uw@w™Uƒƒk¯ƒw¯aW±k_mJa™XVҙĠWb¯L¯Ý@w™wUƒ¯±Wk_ġƒwƒwōKmb@¤„bk°lĖƒô„UJƒšVnÅlťUš¯°VbnbWxX„m„ÞššWUĀ™L™yWzÛKmbUxVKkn݃kŽVšĀċ¤Ux„@Ž¯Žm@ƒ¦"],encodeOffsets:[[100440,25943]]}},{type:"Feature",id:"5304",properties:{name:"玉溪市",cp:[101.9312,23.8898],childNum:9},geometry:{type:"Polygon",coordinates:["@@l„„L°xXlWxXnlw„a„ţlaÞlÆĬnX„ƒ°wVw„l„@m™nw°VVIXllKšbnnV°lbU„UJ@ÈÇKVb—š@bW„°Vk¦kaWb°škxV¤È¼U°ôI@llblš²š@‚@œó@mm@VţkKl¹@yĉ¯°ÑšIXmWKnkšlV„ULlb@lnbVal@UnVJœU‚„nKWa„x„@lkkUlW²X„™‚l„K°„šl²@lšÞUŽ„U‚„UšVšVVXmššlLVnXWVUĉVaVb„W™ğVéšU„VU¹W»aVa„aW™Xƒ‚_U¥nÇķ¯™@a™lUnǍUyk@@wW@kbW¦UKÝwUmmƒƒLUnVxUVVlk¯mmnƒmkÇaŤ¯I@ƒl@@aĉw°ĕmU—L±ƒk™ÆéX™ÜÛ@yÈç@™Çġ„Ýķ—XmmÝVՙƒ™lmnkbmWkb@nl@nŽmš¯VxkJmUJ„ml¯™°makVVnVƒ¦™Wƒ—Wmnl@xmn„l‚I„¤„n™xU„ƒVUŽmX@˜ƒb@zl@¦Ýþ"],encodeOffsets:[[103703,24874]]}},{type:"Feature",id:"5333",properties:{name:"怒江傈僳族自治州",cp:[99.1516,26.5594],childNum:4},geometry:{type:"Polygon",coordinates:["@@WyX£lWlnnUU™„¥@ţV™Vw„JlÅ@wƒmö󙻂£kml¯U¥n¹Æ@ny@wmU@¯mnamÛnƒšUV¥ÈnĠy²œm¤„@ÆónݚnmlnbÞU‚¥„aV£kU„KWƒ„óšƒmIU¥ókwVólƒ™»¯™ƒL™ƒk@m™naWKÛwóњw@a±n—@VbUJ›LkaƒÝXĉƒ™„UV`lI@lnXÆƑkKmxÛXmlUKVmU²Klw@a™aó„@n™KXwVKU¯V¥mUnkm¥ĉ@UxVĖƒ°Vx„V„klmޙkKWĀkVWšnl°Lnm@°ŽUxlV@nk¦™JVÈ°ŽVÒ@nX°@ÆlUômlnôƒ²nxmłnVV„¯x@Èm°XblVUšl°@xkXU¤WXX‚W„Xƃ„mkÅJmށw±bƒxUīkKmÅVUĖÝèV„kx@š›lX„lnk¤ƒLkŽ‚Ėk¦‚xUššL°‚¯Ė@LnK@b°xVI„¥Ua°Ñ@»nm@¹‚KŎÞÈWln²n"],encodeOffsets:[[101071,28891]]}},{type:"Feature",id:"5331",properties:{name:"德宏傣族景颇族自治州",cp:[98.1299,24.5874],childNum:5},geometry:{type:"Polygon",coordinates:["@@„¥n@°@ƒVwČ£™ÿUlÞ„lmULVwnaÜLXyšzšKVÿ™XݙnƒWƒXwmaUa°¯V™ŦŽÆkUm„™VIƒ„ókĕl¯ƒa@£nama™@¯m¯œó@óyţbġkÅm±ÛammVkƒLwU`Wk@VƒkUmŃlUUKmbkkUVUwƒ¦óŽ°¼šbn°ô¦lºƒz@xšŽ¯„™@UŽ°nƒšU¤ţU„°VƆ@ÈmlnzÞl°¦Æa„xUxƒLkxWƒn@‚š²ŰšW„™‚@°ÈXl°Llx"],encodeOffsets:[[100440,25943]]}}],UTF8Encoding:!0}}),i("echarts/util/mapData/geoJson/zhe_jiang_geo",[],function(){return{type:"FeatureCollection",features:[{type:"Feature",id:"3311",properties:{name:"丽水市",cp:[119.5642,28.1854],childNum:9},geometry:{type:"Polygon",coordinates:["@@@V‚bVl@Xn‚UXƒKVŽ@¦nxlUXV‚n„KVmnL‚UV@bn¤lLXK˜²„`nnlJXIVJ‚I„Vnn°KnnVll@VLXWV@UkVaVK„zV@„ƒšVVaUK@U»VUl@@WnUUƒ@wVLn@Vwl@XW°LVbn@VU‚@X„l`@XnKVbkl@XVJlUnlV„„xlL@lnXl„@VšUnV°°„@a„UVLXblWVXn@VVUV@Lš¤VLV„U‚VbnalLUUVX_laVa„WVzXKV@@a@KUmImmXama@kU@yVIUK‚aVa@kXK@aWU@VIUmW@kkVm„Uš@VwUa@K@k@Uƒ`@kUKVk@UV@VaUm²Vy@klUUWUkVmUa@_ƒKVaXa›XmƒU@mUlWkaUXƒ@mmkL@w™JƒnVVÅbWKXa™@@I@aƒJUUÇ@V„UL™W@akLmb@K@a™XXw@mƒVmUVkUy@£@aU@@VkUWm@kUKƒXUWU_mW@wkkmJUUkLWWUXƒW@IkJ@k@mW_kӃ_Ul™Lƒm@I@aUa¯m@kƒa¯LUJƒ@mVVxUb™a@LUKkXƒbm@Uak@@a@Um`ƒIUbUJ@nUVW@@LnVV@lšUbVlUX@`š@blXklW„Ušm„Xlm¦U@@V¯bml@š@nUb@llnn@VbX@lV@ŽUVULmU@JVn„bVbkb™VWxU@@nUVk@"],encodeOffsets:[[121546,28992]]}},{type:"Feature",id:"3301",properties:{name:"杭州市",cp:[119.5313,29.8773],childNum:6},geometry:{type:"Polygon",coordinates:["@@X@l„°KXXlW„b@²„`šššb‚I„šX`l@„@bWl@n@VnLUV@V„@°¦@šl@XVlU@š@xVbUb@Vkb@‚@XVJVz™J@Lޚ@VmLUxUJ@LU„Vx‚b„xXUl@VaÈw„b‚aÞa@Vl@XUVx@V@V„LlbnV„al@lb„Vnn‚LnKnL@VlbVJXalIšb@KUU@mVInJ˜„U„Vl@xUšVLnUš@UÞaV@lkV@UanK„L@UlKVUnbÆmn@@nUlVnVJl@@UXU„L@WVIVJVxVLXV@IÜKnbn@V¥V@@I@ƒƒ„y°b@UUwnk°ÆƨVlUšçXm›£aƒÇ™IkVƒ@WV@@aWIUWUIkb@WW@UnƒK@UU@kaWVkƒVIVVnU@UWVUV@VmVkKkWIkVWaULU`UImJUImm—U@ƒƒwmwUV™IUWVkUamaU@mV—kƒb@KVU@aVU@anKULVJ‚U@kÛU™JUV›kkƒVakU@ƒaVwkW@UWkXmWaULUaUK@XƒJUUmƒVU@UVƒUkJ@ImwmKU@k„@lU„W@@akKm„kamIkWl_UwVm@UkaVUUaƒ@UamakbWlkL@aUalU@mkL@U@U™lmK@XkKm@Ýakb@xƒnXbƒ`ƒnUUU@›™U@™wU@@ƒmKkkƒV¯U@lULUbVbUb@V‚a@L™ºÝb@bLmK™x@VUL@bk@mxULWl"],encodeOffsets:[[121185,30184]]}},{type:"Feature",id:"3303",properties:{name:"温州市",cp:[120.498,27.8119],childNum:9},geometry:{type:"Polygon",coordinates:["@@ll@xnXV`VX„WVL@lXnlV@UV@@b@¤VzUlnV„U@nWxšW@b@LnalK@bšXVKUƒÈ@VV„I@b@Jš@WbXLÆaUU„mšI@xlKnn„@VWlbkXV‚@n„VWnœ‚WbUb„L@`VbUnVlVXkV@lUz±‚VnUbU@@VUlVL@l„_@V@l@LVbV@XLV`VÈlxn@lU@aœaVV‚k„@XJ@nl@@LU`°LVb„L°a@a„UVy@anI@a„a‚nV@²wÜJX@VšVV°k„na@WVk„aWwU@m@™ƒkƒaUĕ™ÝšÝŤnÈa„aóI›»@±X™WkUķ@kV±kw™ƒUkWw„™UƒÝ»ÛkɳlImaUaWóXÿǬk‚UnWVmmk™KţnŏÞğl™„UlUx@XWb„V@JkXƒ°mb@VULVxUVk@@LWWk@WIkšƒUkJmUkVmI@yƒ@Ua™kLm‚U@mUUUkaVk™@mK@UlUU@UmKmbUUUJ@n@KVLUL@VkJWXX`mnULWlkL@JVLVb@°kxkU@LVŽ™V@„VLV`UL@VUX"],encodeOffsets:[[122502,28334]]}},{type:"Feature",id:"3302",properties:{name:"宁波市",cp:[121.5967,29.6466],childNum:6},geometry:{type:"Polygon",coordinates:["@@Ċ¦ĸĀ°‚nXÞVšKškƨƑźÿ°»n„@wô¥ÜbœU°ÆXÞWóçĉݱIUƒÈ¥@U°wÆ»²mm_@aXƒVKÞVlk@akk›̅@£X»VwƏXWa¯aȗb™KƽۃĊ™xƒLóŽk@ƒƒƒ@¯nƒKUL@xkL›ÑkWULUUmJUXVŽU@mŽUX¯@V`mbXbV@@nn¤WXšx@škJ@nVVUVl²UbÝVUVk@Wx@V@„ƒVXzmlaƒL@VlLU`„XUVVVUnl@VbnJlnUVVnƒlUKkbmnn„VxlJnxmbU@UL@KUV™X@xmb@lk@mnVVUš™è"],encodeOffsets:[[123784,30977]]}},{type:"Feature",id:"3309",properties:{name:"舟山市",cp:[122.2559,30.2234],childNum:3},geometry:{type:"Polygon",coordinates:["@@l΢ƒʠþÆVĢLĊƒǬXĊ܄XôV„ÑÆw„ƒlšƏÈóVĭVǓ@ƒĉwɛkmK@ĉXīWaĉUĵÝmƒ¯ĉƒwĉ±±nż¯x@VǦV„²JĊÞôèÝXÅW¯›VÛaó¦@xƒŽmŽ¯¼ŹĀ"], -encodeOffsets:[[124437,30983]]}},{type:"Feature",id:"3310",properties:{name:"台州市",cp:[121.1353,28.6688],childNum:7},geometry:{type:"Polygon",coordinates:["@@lV„IVWVz@bXJl@Xal@°„nLll@nVxnV„K@UJVbƒ¦°„k`UIWJXnƚ@bUJ„Xl@lb„Wn@UzVV@bVVšmVnnJVXna‚bšKUKnUVVUnVLlKVLXa„Jm£@mU@WanaU_°@VWnV@UVWnIVVVKlXœÒlK@wVK„L°m„@„„l@ô„Kšw„ĉƾůUƒl£@»UƒVk„m@ƅUƒƒaÛIŏmUk@m„w@a™£ƒWk@ţšƒIm±@ankôUlaU™Uw¯ƒōaƒbÇbţm™ÞšÞVĖ„b„l@š@n‚VXxƒbUl@XmbƒŽ¯lUUU™W@ÛI±xU@mƒb@bmJ@bUzƒV@b¯bƒKUa¯KV_@Kk@@mWIƒ@lUU›b@bkVm@kwUÇU_WKU@Ux™@ƒVUnllX@Vn‚J@UXV@bWL@lUbbVLUJ@z‚V@lnbWbnnnJVŽ@L"],encodeOffsets:[[123312,29526]]}},{type:"Feature",id:"3307",properties:{name:"金华市",cp:[120.0037,29.1028],childNum:8},geometry:{type:"Polygon",coordinates:["@@nbVb„@VbUVlb@VUnVxk`lXnJlbnƒlL@bX@Vƒ@klƒV@nLnx@JlI„V‚U@VUVn„VV„I@WVLVbVKXbWnXl@VlXUx„b@ŽlVUbl„œlVUšIÜVnalKX@@bV@@aUUlUƒwUw„@naWW„UVaUUšaVb„LlxXJVk°ƒUƒlkU¥@k„a@LVlXLVlšVWznVn@lxšJl_@WX_@mVa„a@alU@kVVna„KVLlK„b@UUaVašbnUWmXU@k@yVI@ařWmXIVJl_¯ƒ„¥UaVI@ƒLmUUw@mkkmK¯ƒk@Wbk@WI@aUyUXƒJkU@bU@WLUyƒXUbkbW`UVVkKmbUaVUƒUK™£@KVUUUm@UWkXWaUKƒV@b¯ƒ¯mU™V@UkƒmW@kkKƒwUƒmkkVUI@WlkUamL@Wk_Wƒ@UVm@Ua¯KWXk@Uxm@UK@xV„mV@Xk@UVV¼@‚VLUb™Uƒ„U@ƒyULUbVlU@@XlVUVVbƒU@lXXVW@XUVl@@VUVƒÈn@VVU„@lVa@„U„mL@`X@`WL@VUX@lUL@xlx"],encodeOffsets:[[122119,29948]]}},{type:"Feature",id:"3308",properties:{name:"衢州市",cp:[118.6853,28.8666],childNum:5},geometry:{type:"Polygon",coordinates:["@@XkVKnwl@@aVK@UšwnL‚K@aÞaš¹@Kb@UVaUaVaVK@k°V„UllnL@„V@šxV@œšV@VV„m„_Wa„m@wlaÞbn@lL@WnLšk@V@VlK@nkVVb@blKXklakw@wVK@kVW@UXK@_‚W@_nKVƒ@ƒUb@kVƒUUm@„ÇVU@Uk@VU@WUXWW@k„VUaVUkU@WWXUKk@Ukmm¯LmmƒUJUIWJkImmƒ_—±WLkKm£@aVUmKUnƒLmWUkVmw@¥U„LVWm@WUka@UmmLmm@@bUX™@@WUIm@UVUK@UVUUU™VVJmb@b„Xn‚mVƒ¼nnn¦mJUVƒL„V@VW@UzUlVnUbl`UnVl@XU@kl@bmÈUx™Vk@@J@„ƒ¼W@ÅaVVnzmVƒ„@WJk@kWJ@ƒlXbWbXxmVnšlLXb@°lKVXnWšbWV„„X„mbV@Xl‚bšI@Kn@@x@šVLlm"],encodeOffsets:[[121185,30184]]}},{type:"Feature",id:"3306",properties:{name:"绍兴市",cp:[120.564,29.7565],childNum:6},geometry:{type:"Polygon",coordinates:["@@„x@„˜VnnVJnIVJV_VKXblUXJlŽlLUŽUnU@UVVX@ŽmVUUUJl„XUlbV@@V„LVmX@@XlaVJVXXJ@b‚@XU„@lUšJ„È‚bœ¤Ō„JšçV™UUnml@@kna@wšWVU@LVKV@namwkIUwmƒnmlaVL„kUmVUkmmIUak@VmUUVUƒWV_kK@U„K‚bnkWy„U@ƒ@UXwl@VUÞUVak±VUUU@mlI@™™wXWƒIWbUKkLUKVmUUmVVL™LambUWmIUm™nUU@aUUVym@ƒXkak@ƒW@z@lWVXnmV™aUbVb@VƒakLUKƒLmbUU@lkV@bƒbUb@nW`@Xk`™Ikwm@mUXy™UUkWKUk@Kƒb@lV¦klV„¯„UlWIkwƒKUa™bVVUbƒVXXmbƒ@Vx„xkVVV@bU@@aW@kLmb@lVUIVKmL@bUV@bUV@L„a˜lnUV@nbVbUlVXšJVUnx"],encodeOffsets:[[122997,30561]]}},{type:"Feature",id:"3304",properties:{name:"嘉兴市",cp:[120.9155,30.6354],childNum:6},geometry:{type:"Polygon",coordinates:["@@@blIX@@VÜVUnn@l‚k„lKnI°Þl`²LVKVbnbVaVLUVn@W¦@VkVVb„@VI„`@blLnL‚aX@„VVb@U‚@XlVa„@@kVaUKV»U_lWXUƒƒ@alb„k@VllnLVKn@@UVIUw@y°IVVXU@VV@lw„m@wVkƾaœJ‚LkΡƧƒ™l™LÝUmW¯ķÿĉ¥ƒIŋŽWn™èkVƧU¯ÅmlVx@V¯aƒz„Ž@„@JU@U¦m@@šnVmn@V„LV‚"],encodeOffsets:[[123233,31382]]}},{type:"Feature",id:"3305",properties:{name:"湖州市",cp:[119.8608,30.7782],childNum:4},geometry:{type:"Polygon",coordinates:["@@kLlƒkm@VmÛU@UW@kJ@aUƒK@UnmmU@™maÛL@JWUUKUwUIUJ@XƒKWV@Vk@UIUmVk@mm@ÅnmaUVkL@VƒKmLVbU@klU@ÝbV™@mVUKV™@wUkVƒ—ƒmIUJ@nVV@L™akJWbUIka@UmKmLKmmƒUUVk@@nmLX`WXUV@Ž@nUl™kmlU@Ub„„ƒxVVšIlV„Žšnn„@@n˜„UҚ@„°n@@xmb@„VbnV@šš„@b@`@L@L@x@blVklVbnnV@‚aXb°VlU@W„b°U„LXWVUV™„™VwÈwÜ»ĸaĠnUVw²X@V@lVU@wlaUUVm@knUV›"],encodeOffsets:[[123379,31500]]}}],UTF8Encoding:!0}}),i("echarts/chart/gauge",["require","./base","../util/shape/GaugePointer","zrender/shape/Text","zrender/shape/Line","zrender/shape/Rectangle","zrender/shape/Circle","zrender/shape/Sector","../config","../util/ecData","../util/accMath","zrender/tool/util","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e("./base"),n=e("../util/shape/GaugePointer"),a=e("zrender/shape/Text"),o=e("zrender/shape/Line"),r=e("zrender/shape/Rectangle"),s=e("zrender/shape/Circle"),l=e("zrender/shape/Sector"),h=e("../config");h.gauge={zlevel:0,z:2,center:["50%","50%"],clickable:!0,legendHoverLink:!0,radius:"75%",startAngle:225,endAngle:-45,min:0,max:100,splitNumber:10,axisLine:{show:!0,lineStyle:{color:[[.2,"#228b22"],[.8,"#48b"],[1,"#ff4500"]],width:30}},axisTick:{show:!0,splitNumber:5,length:8,lineStyle:{color:"#eee",width:1,type:"solid"}},axisLabel:{show:!0,textStyle:{color:"auto"}},splitLine:{show:!0,length:30,lineStyle:{color:"#eee",width:2,type:"solid"}},pointer:{show:!0,length:"80%",width:8,color:"auto"},title:{show:!0,offsetCenter:[0,"-40%"],textStyle:{color:"#333",fontSize:15}},detail:{show:!0,backgroundColor:"rgba(0,0,0,0)",borderWidth:0,borderColor:"#ccc",width:100,height:40,offsetCenter:[0,"40%"],textStyle:{color:"auto",fontSize:30}}};var m=e("../util/ecData"),V=e("../util/accMath"),U=e("zrender/tool/util");return t.prototype={type:h.CHART_TYPE_GAUGE,_buildShape:function(){var e=this.series;this._paramsMap={},this.selectedMap={};for(var t=0,i=e.length;i>t;t++)e[t].type===h.CHART_TYPE_GAUGE&&(this.selectedMap[e[t].name]=!0,e[t]=this.reformOption(e[t]),this.legendHoverLink=e[t].legendHoverLink||this.legendHoverLink,this._buildSingleGauge(t),this.buildMark(t));this.addShapeList()},_buildSingleGauge:function(e){var t=this.series[e];this._paramsMap[e]={center:this.parseCenter(this.zr,t.center),radius:this.parseRadius(this.zr,t.radius),startAngle:t.startAngle.toFixed(2)-0,endAngle:t.endAngle.toFixed(2)-0},this._paramsMap[e].totalAngle=this._paramsMap[e].startAngle-this._paramsMap[e].endAngle,this._colorMap(e),this._buildAxisLine(e),this._buildSplitLine(e),this._buildAxisTick(e),this._buildAxisLabel(e),this._buildPointer(e),this._buildTitle(e),this._buildDetail(e)},_buildAxisLine:function(e){var t=this.series[e];if(t.axisLine.show)for(var i,n,a=t.min,o=t.max-a,r=this._paramsMap[e],s=r.center,l=r.startAngle,h=r.totalAngle,V=r.colorArray,U=t.axisLine.lineStyle,d=this.parsePercent(U.width,r.radius[1]),p=r.radius[1],c=p-d,u=l,y=0,g=V.length;g>y;y++)n=l-h*(V[y][0]-a)/o,i=this._getSector(s,c,p,n,u,V[y][1],U,t.zlevel,t.z),u=n,i._animationAdd="r",m.set(i,"seriesIndex",e),m.set(i,"dataIndex",y),this.shapeList.push(i)},_buildSplitLine:function(e){var t=this.series[e];if(t.splitLine.show)for(var i,n,a,r=this._paramsMap[e],s=t.splitNumber,l=t.min,h=t.max-l,m=t.splitLine,V=this.parsePercent(m.length,r.radius[1]),U=m.lineStyle,d=U.color,p=r.center,c=r.startAngle*Math.PI/180,u=r.totalAngle*Math.PI/180,y=r.radius[1],g=y-V,b=0;s>=b;b++)i=c-u/s*b,n=Math.sin(i),a=Math.cos(i),this.shapeList.push(new o({zlevel:t.zlevel,z:t.z+1,hoverable:!1,style:{xStart:p[0]+a*y,yStart:p[1]-n*y,xEnd:p[0]+a*g,yEnd:p[1]-n*g,strokeColor:"auto"===d?this._getColor(e,l+h/s*b):d,lineType:U.type,lineWidth:U.width,shadowColor:U.shadowColor,shadowBlur:U.shadowBlur,shadowOffsetX:U.shadowOffsetX,shadowOffsetY:U.shadowOffsetY}}))},_buildAxisTick:function(e){var t=this.series[e];if(t.axisTick.show)for(var i,n,a,r=this._paramsMap[e],s=t.splitNumber,l=t.min,h=t.max-l,m=t.axisTick,V=m.splitNumber,U=this.parsePercent(m.length,r.radius[1]),d=m.lineStyle,p=d.color,c=r.center,u=r.startAngle*Math.PI/180,y=r.totalAngle*Math.PI/180,g=r.radius[1],b=g-U,f=0,k=s*V;k>=f;f++)f%V!==0&&(i=u-y/k*f,n=Math.sin(i),a=Math.cos(i),this.shapeList.push(new o({zlevel:t.zlevel,z:t.z+1,hoverable:!1,style:{xStart:c[0]+a*g,yStart:c[1]-n*g,xEnd:c[0]+a*b,yEnd:c[1]-n*b,strokeColor:"auto"===p?this._getColor(e,l+h/k*f):p,lineType:d.type,lineWidth:d.width,shadowColor:d.shadowColor,shadowBlur:d.shadowBlur,shadowOffsetX:d.shadowOffsetX,shadowOffsetY:d.shadowOffsetY}})))},_buildAxisLabel:function(e){var t=this.series[e];if(t.axisLabel.show)for(var i,n,o,r,s=t.splitNumber,l=t.min,h=t.max-l,m=t.axisLabel.textStyle,U=this.getFont(m),d=m.color,p=this._paramsMap[e],c=p.center,u=p.startAngle,y=p.totalAngle,g=p.radius[1]-this.parsePercent(t.splitLine.length,p.radius[1])-5,b=0;s>=b;b++)r=V.accAdd(l,V.accMul(V.accDiv(h,s),b)),i=u-y/s*b,n=Math.sin(i*Math.PI/180),o=Math.cos(i*Math.PI/180),i=(i+360)%360,this.shapeList.push(new a({zlevel:t.zlevel,z:t.z+1,hoverable:!1,style:{x:c[0]+o*g,y:c[1]-n*g,color:"auto"===d?this._getColor(e,r):d,text:this._getLabelText(t.axisLabel.formatter,r),textAlign:i>=110&&250>=i?"left":70>=i||i>=290?"right":"center",textBaseline:i>=10&&170>=i?"top":i>=190&&350>=i?"bottom":"middle",textFont:U,shadowColor:m.shadowColor,shadowBlur:m.shadowBlur,shadowOffsetX:m.shadowOffsetX,shadowOffsetY:m.shadowOffsetY}}))},_buildPointer:function(e){var t=this.series[e];if(t.pointer.show){var i=t.max-t.min,a=t.pointer,o=this._paramsMap[e],r=this.parsePercent(a.length,o.radius[1]),l=this.parsePercent(a.width,o.radius[1]),h=o.center,V=this._getValue(e);V=V2?2:l/2,color:"#fff"}});m.pack(p,this.series[e],e,this.series[e].data[0],0,this.series[e].data[0].name,V),this.shapeList.push(p),this.shapeList.push(new s({zlevel:t.zlevel,z:t.z+2,hoverable:!1,style:{x:h[0],y:h[1],r:a.width/2.5,color:"#fff"}}))}},_buildTitle:function(e){var t=this.series[e];if(t.title.show){var i=t.data[0],n=null!=i.name?i.name:"";if(""!==n){var o=t.title,r=o.offsetCenter,s=o.textStyle,l=s.color,h=this._paramsMap[e],m=h.center[0]+this.parsePercent(r[0],h.radius[1]),V=h.center[1]+this.parsePercent(r[1],h.radius[1]);this.shapeList.push(new a({zlevel:t.zlevel,z:t.z+(Math.abs(m-h.center[0])+Math.abs(V-h.center[1])<2*s.fontSize?2:1),hoverable:!1,style:{x:m,y:V,color:"auto"===l?this._getColor(e):l,text:n,textAlign:"center",textFont:this.getFont(s),shadowColor:s.shadowColor,shadowBlur:s.shadowBlur,shadowOffsetX:s.shadowOffsetX,shadowOffsetY:s.shadowOffsetY}}))}}},_buildDetail:function(e){var t=this.series[e];if(t.detail.show){var i=t.detail,n=i.offsetCenter,a=i.backgroundColor,o=i.textStyle,s=o.color,l=this._paramsMap[e],h=this._getValue(e),m=l.center[0]-i.width/2+this.parsePercent(n[0],l.radius[1]),V=l.center[1]+this.parsePercent(n[1],l.radius[1]);this.shapeList.push(new r({zlevel:t.zlevel,z:t.z+(Math.abs(m+i.width/2-l.center[0])+Math.abs(V+i.height/2-l.center[1])r;r++)o.push([a[r][0]*n+i,a[r][1]]);this._paramsMap[e].colorArray=o},_getColor:function(e,t){null==t&&(t=this._getValue(e));for(var i=this._paramsMap[e].colorArray,n=0,a=i.length;a>n;n++)if(i[n][0]>=t)return i[n][1];return i[i.length-1][1]},_getSector:function(e,t,i,n,a,o,r,s,h){return new l({zlevel:s,z:h,hoverable:!1,style:{x:e[0],y:e[1],r0:t,r:i,startAngle:n,endAngle:a,brushType:"fill",color:o,shadowColor:r.shadowColor,shadowBlur:r.shadowBlur,shadowOffsetX:r.shadowOffsetX,shadowOffsetY:r.shadowOffsetY}})},_getLabelText:function(e,t){if(e){if("function"==typeof e)return e.call(this.myChart,t);if("string"==typeof e)return e.replace("{value}",t)}return t},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()}},U.inherits(t,i),e("../chart").define("gauge",t),t}),i("echarts/util/shape/GaugePointer",["require","zrender/shape/Base","zrender/tool/util","./normalIsCover"],function(e){function t(e){i.call(this,e)}var i=e("zrender/shape/Base"),n=e("zrender/tool/util");return t.prototype={type:"gauge-pointer",buildPath:function(e,t){var i=t.r,n=t.width,a=t.angle,o=t.x-Math.cos(a)*n*(n>=i/3?1:2),r=t.y+Math.sin(a)*n*(n>=i/3?1:2);a=t.angle-Math.PI/2,e.moveTo(o,r),e.lineTo(t.x+Math.cos(a)*n,t.y-Math.sin(a)*n),e.lineTo(t.x+Math.cos(t.angle)*i,t.y-Math.sin(t.angle)*i),e.lineTo(t.x-Math.cos(a)*n,t.y+Math.sin(a)*n),e.lineTo(o,r)},getRect:function(e){if(e.__rect)return e.__rect;var t=2*e.width,i=e.x,n=e.y,a=i+Math.cos(e.angle)*e.r,o=n-Math.sin(e.angle)*e.r;return e.__rect={x:Math.min(i,a)-t,y:Math.min(n,o)-t,width:Math.abs(i-a)+t,height:Math.abs(n-o)+t},e.__rect},isCover:e("./normalIsCover")},n.inherits(t,i),t}),i("echarts/chart/funnel",["require","./base","zrender/shape/Text","zrender/shape/Line","zrender/shape/Polygon","../config","../util/ecData","../util/number","zrender/tool/util","zrender/tool/color","zrender/tool/area","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Line"),o=e("zrender/shape/Polygon"),r=e("../config");r.funnel={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,x:80,y:60,x2:80,y2:60,min:0,max:100,minSize:"0%",maxSize:"100%",sort:"descending",gap:0,funnelAlign:"center",itemStyle:{normal:{borderColor:"#fff",borderWidth:1,label:{show:!0,position:"outer"},labelLine:{show:!0,length:10,lineStyle:{width:1,type:"solid"}}},emphasis:{borderColor:"rgba(0,0,0,0)",borderWidth:1,label:{show:!0},labelLine:{show:!0}}}};var s=e("../util/ecData"),l=e("../util/number"),h=e("zrender/tool/util"),m=e("zrender/tool/color"),V=e("zrender/tool/area");return t.prototype={type:r.CHART_TYPE_FUNNEL,_buildShape:function(){var e=this.series,t=this.component.legend;this._paramsMap={},this._selected={},this.selectedMap={};for(var i,n=0,a=e.length;a>n;n++)if(e[n].type===r.CHART_TYPE_FUNNEL){if(e[n]=this.reformOption(e[n]),this.legendHoverLink=e[n].legendHoverLink||this.legendHoverLink,i=e[n].name||"",this.selectedMap[i]=t?t.isSelected(i):!0,!this.selectedMap[i])continue;this._buildSingleFunnel(n),this.buildMark(n)}this.addShapeList()},_buildSingleFunnel:function(e){var t=this.component.legend,i=this.series[e],n=this._mapData(e),a=this._getLocation(e);this._paramsMap[e]={location:a,data:n};for(var o,r=0,s=[],h=0,m=n.length;m>h;h++)o=n[h].name,this.selectedMap[o]=t?t.isSelected(o):!0,this.selectedMap[o]&&!isNaN(n[h].value)&&(s.push(n[h]),r++);if(0!==r){for(var V,U,d,p,c=this._buildFunnelCase(e),u=i.funnelAlign,y=i.gap,g=r>1?(a.height-(r-1)*y)/r:a.height,b=a.y,f="descending"===i.sort?this._getItemWidth(e,s[0].value):l.parsePercent(i.minSize,a.width),k="descending"===i.sort?1:0,x=a.centerX,_=[],h=0,m=s.length;m>h;h++)if(o=s[h].name,this.selectedMap[o]&&!isNaN(s[h].value)){switch(V=m-2>=h?this._getItemWidth(e,s[h+k].value):"descending"===i.sort?l.parsePercent(i.minSize,a.width):l.parsePercent(i.maxSize,a.width),u){case"left":U=a.x;break;case"right":U=a.x+a.width-f;break;default:U=x-f/2}d=this._buildItem(e,s[h]._index,t?t.getColor(o):this.zr.getColor(s[h]._index),U,b,f,V,g,u),b+=g+y,p=d.style.pointList,_.unshift([p[0][0]-10,p[0][1]]),_.push([p[1][0]+10,p[1][1]]),0===h&&(0===f?(p=_.pop(),"center"==u&&(_[0][0]+=10),"right"==u&&(_[0][0]=p[0]),_[0][1]-="center"==u?10:15,1==m&&(p=d.style.pointList)):(_[_.length-1][1]-=5,_[0][1]-=5)),f=V}c&&(_.unshift([p[3][0]-10,p[3][1]]),_.push([p[2][0]+10,p[2][1]]),0===f?(p=_.pop(),"center"==u&&(_[0][0]+=10),"right"==u&&(_[0][0]=p[0]),_[0][1]+="center"==u?10:15):(_[_.length-1][1]+=5,_[0][1]+=5),c.style.pointList=_)}},_buildFunnelCase:function(e){var t=this.series[e];if(this.deepQuery([t,this.option],"calculable")){var i=this._paramsMap[e].location,n=10,a={hoverable:!1,style:{pointListd:[[i.x-n,i.y-n],[i.x+i.width+n,i.y-n],[i.x+i.width+n,i.y+i.height+n],[i.x-n,i.y+i.height+n]],brushType:"stroke",lineWidth:1,strokeColor:t.calculableHolderColor||this.ecTheme.calculableHolderColor||r.calculableHolderColor}};return s.pack(a,t,e,void 0,-1),this.setCalculable(a),a=new o(a),this.shapeList.push(a),a}},_getLocation:function(e){var t=this.series[e],i=this.zr.getWidth(),n=this.zr.getHeight(),a=this.parsePercent(t.x,i),o=this.parsePercent(t.y,n),r=null==t.width?i-a-this.parsePercent(t.x2,i):this.parsePercent(t.width,i);return{x:a,y:o,width:r,height:null==t.height?n-o-this.parsePercent(t.y2,n):this.parsePercent(t.height,n),centerX:a+r/2}},_mapData:function(e){function t(e,t){return"-"===e.value?1:"-"===t.value?-1:t.value-e.value}function i(e,i){return-t(e,i)}for(var n=this.series[e],a=h.clone(n.data),o=0,r=a.length;r>o;o++)a[o]._index=o;return"none"!=n.sort&&a.sort("descending"===n.sort?t:i),a},_buildItem:function(e,t,i,n,a,o,r,l,h){var m=this.series,V=m[e],U=V.data[t],d=this.getPolygon(e,t,i,n,a,o,r,l,h);s.pack(d,m[e],e,m[e].data[t],t,m[e].data[t].name),this.shapeList.push(d);var p=this.getLabel(e,t,i,n,a,o,r,l,h);s.pack(p,m[e],e,m[e].data[t],t,m[e].data[t].name),this.shapeList.push(p),this._needLabel(V,U,!1)||(p.invisible=!0);var c=this.getLabelLine(e,t,i,n,a,o,r,l,h);this.shapeList.push(c),this._needLabelLine(V,U,!1)||(c.invisible=!0);var u=[],y=[];return this._needLabelLine(V,U,!0)&&(u.push(c.id),y.push(c.id)),this._needLabel(V,U,!0)&&(u.push(p.id),y.push(d.id)),d.hoverConnect=u,p.hoverConnect=y,d},_getItemWidth:function(e,t){var i=this.series[e],n=this._paramsMap[e].location,a=i.min,o=i.max,r=l.parsePercent(i.minSize,n.width),s=l.parsePercent(i.maxSize,n.width);return(t-a)*(s-r)/(o-a)+r},getPolygon:function(e,t,i,n,a,r,s,l,h){var V,U=this.series[e],d=U.data[t],p=[d,U],c=this.deepMerge(p,"itemStyle.normal")||{},u=this.deepMerge(p,"itemStyle.emphasis")||{},y=this.getItemStyleColor(c.color,e,t,d)||i,g=this.getItemStyleColor(u.color,e,t,d)||("string"==typeof y?m.lift(y,-.2):y);switch(h){case"left":V=n;break;case"right":V=n+(r-s);break;default:V=n+(r-s)/2}var b={zlevel:U.zlevel,z:U.z,clickable:this.deepQuery(p,"clickable"),style:{pointList:[[n,a],[n+r,a],[V+s,a+l],[V,a+l]],brushType:"both",color:y,lineWidth:c.borderWidth,strokeColor:c.borderColor},highlightStyle:{color:g,lineWidth:u.borderWidth,strokeColor:u.borderColor}};return this.deepQuery([d,U,this.option],"calculable")&&(this.setCalculable(b),b.draggable=!0),new o(b)},getLabel:function(e,t,i,a,o,r,s,l,U){var d,p=this.series[e],c=p.data[t],u=this._paramsMap[e].location,y=h.merge(h.clone(c.itemStyle)||{},p.itemStyle),g="normal",b=y[g].label,f=b.textStyle||{},k=y[g].labelLine.length,x=this.getLabelText(e,t,g),_=this.getFont(f),L=i;b.position=b.position||y.normal.label.position,"inner"===b.position||"inside"===b.position||"center"===b.position?(d=U,L=Math.max(r,s)/2>V.getTextWidth(x,_)?"#fff":m.reverse(i)):d="left"===b.position?"right":"left";var W={zlevel:p.zlevel,z:p.z+1,style:{x:this._getLabelPoint(b.position,a,u,r,s,k,U),y:o+l/2,color:f.color||L,text:x,textAlign:f.align||d,textBaseline:f.baseline||"middle",textFont:_}};return g="emphasis",b=y[g].label||b,f=b.textStyle||f,k=y[g].labelLine.length||k,b.position=b.position||y.normal.label.position,x=this.getLabelText(e,t,g),_=this.getFont(f),L=i,"inner"===b.position||"inside"===b.position||"center"===b.position?(d=U,L=Math.max(r,s)/2>V.getTextWidth(x,_)?"#fff":m.reverse(i)):d="left"===b.position?"right":"left",W.highlightStyle={x:this._getLabelPoint(b.position,a,u,r,s,k,U),color:f.color||L,text:x,textAlign:f.align||d,textFont:_,brushType:"fill"},new n(W)},getLabelText:function(e,t,i){var n=this.series,a=n[e],o=a.data[t],r=this.deepQuery([o,a],"itemStyle."+i+".label.formatter");return r?"function"==typeof r?r.call(this.myChart,{seriesIndex:e,seriesName:a.name||"",series:a,dataIndex:t,data:o,name:o.name,value:o.value}):"string"==typeof r?r=r.replace("{a}","{a0}").replace("{b}","{b0}").replace("{c}","{c0}").replace("{a0}",a.name).replace("{b0}",o.name).replace("{c0}",o.value):void 0:o.name},getLabelLine:function(e,t,i,n,o,r,s,l,m){var V=this.series[e],U=V.data[t],d=this._paramsMap[e].location,p=h.merge(h.clone(U.itemStyle)||{},V.itemStyle),c="normal",u=p[c].labelLine,y=p[c].labelLine.length,g=u.lineStyle||{},b=p[c].label;b.position=b.position||p.normal.label.position;var f={zlevel:V.zlevel,z:V.z+1,hoverable:!1,style:{xStart:this._getLabelLineStartPoint(n,d,r,s,m),yStart:o+l/2,xEnd:this._getLabelPoint(b.position,n,d,r,s,y,m),yEnd:o+l/2,strokeColor:g.color||i,lineType:g.type,lineWidth:g.width}};return c="emphasis",u=p[c].labelLine||u,y=p[c].labelLine.length||y,g=u.lineStyle||g,b=p[c].label||b,b.position=b.position,f.highlightStyle={xEnd:this._getLabelPoint(b.position,n,d,r,s,y,m),strokeColor:g.color||i,lineType:g.type,lineWidth:g.width},new a(f)},_getLabelPoint:function(e,t,i,n,a,o,r){switch(e="inner"===e||"inside"===e?"center":e){case"center":return"center"==r?t+n/2:"left"==r?t+10:t+n-10;case"left":return"auto"===o?i.x-10:"center"==r?i.centerX-Math.max(n,a)/2-o:"right"==r?t-(a>n?a-n:0)-o:i.x-o;default:return"auto"===o?i.x+i.width+10:"center"==r?i.centerX+Math.max(n,a)/2+o:"right"==r?i.x+i.width+o:t+Math.max(n,a)+o}},_getLabelLineStartPoint:function(e,t,i,n,a){return"center"==a?t.centerX:n>i?e+Math.min(i,n)/2:e+Math.max(i,n)/2},_needLabel:function(e,t,i){return this.deepQuery([t,e],"itemStyle."+(i?"emphasis":"normal")+".label.show")},_needLabelLine:function(e,t,i){return this.deepQuery([t,e],"itemStyle."+(i?"emphasis":"normal")+".labelLine.show")},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()}},h.inherits(t,i),e("../chart").define("funnel",t),t}),i("echarts/chart/eventRiver",["require","./base","../layout/eventRiver","zrender/shape/Polygon","../component/axis","../component/grid","../component/dataZoom","../config","../util/ecData","../util/date","zrender/tool/util","zrender/tool/color","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o);var r=this;r._ondragend=function(){r.isDragend=!0},this.refresh(a)}var i=e("./base"),n=e("../layout/eventRiver"),a=e("zrender/shape/Polygon");e("../component/axis"),e("../component/grid"),e("../component/dataZoom");var o=e("../config");o.eventRiver={zlevel:0,z:2,clickable:!0,legendHoverLink:!0,itemStyle:{normal:{borderColor:"rgba(0,0,0,0)",borderWidth:1,label:{show:!0,position:"inside",formatter:"{b}"}},emphasis:{borderColor:"rgba(0,0,0,0)",borderWidth:1,label:{show:!0}}}};var r=e("../util/ecData"),s=e("../util/date"),l=e("zrender/tool/util"),h=e("zrender/tool/color");return t.prototype={type:o.CHART_TYPE_EVENTRIVER,_buildShape:function(){var e=this.series;this.selectedMap={},this._dataPreprocessing();for(var t=this.component.legend,i=[],a=0;an;n++)if(i[n].type===this.type){e=this.component.xAxis.getAxis(i[n].xAxisIndex||0);for(var o=0,r=i[n].data.length;r>o;o++){t=i[n].data[o].evolution;for(var l=0,h=t.length;h>l;l++)t[l].timeScale=e.getCoord(s.getNewDate(t[l].time)-0),t[l].valueScale=Math.pow(t[l].value,.8)}}this._intervalX=Math.round(this.component.grid.getWidth()/40)},_drawEventRiver:function(){for(var e=this.series,t=0;ta)){for(var o=[],r=[],s=0;a>s;s++)o.push(n[s].timeScale),r.push(n[s].valueScale);var l=[];l.push([o[0],i]);var s=0;for(s=0;a-1>s;s++)l.push([(o[s]+o[s+1])/2,r[s]/-2+i]);for(l.push([(o[s]+(o[s]+t))/2,r[s]/-2+i]),l.push([o[s]+t,i]),l.push([(o[s]+(o[s]+t))/2,r[s]/2+i]),s=a-1;s>0;s--)l.push([(o[s]+o[s-1])/2,r[s-1]/2+i]);return l}},ondragend:function(e,t){this.isDragend&&e.target&&(t.dragOut=!0,t.dragIn=!0,t.needRefresh=!1,this.isDragend=!1)},refresh:function(e){e&&(this.option=e,this.series=e.series),this.backupShapeList(),this._buildShape()}},l.inherits(t,i),e("../chart").define("eventRiver",t),t}),i("echarts/layout/eventRiver",["require"],function(){function e(e,i,o){function r(e,t){var i=e.importance,n=t.importance;return i>n?-1:n>i?1:0}for(var s=4,l=0;l=e)return[0];for(var t=[];e--;)t.push(0);return t}(),u=c.slice(0),y=[],g=0,b=0,l=0;l.5?.5:1,r=t.y,s=(t.height-n)/i,l=0,h=e.length;h>l;l++){var m=e[l];m.y=r+s*m.y+m._offset*o,delete m.time,delete m.value,delete m.xpx,delete m.ypx,delete m._offset;for(var V=m.evolution,U=0,d=V.length;d>U;U++)V[U].valueScale*=s}}function i(e,t,i,n){if(e===i)throw new Error("x0 is equal with x1!!!");if(t===n)return function(){return t};var a=(t-n)/(e-i),o=(n*e-t*i)/(e-i);return function(e){return a*e+o}}function n(e,t,n){var a=~~t,o=e.time.length;e.xpx=[],e.ypx=[];for(var r,s=0,l=0,h=0,m=0,V=0;o>s;s++){l=~~e.time[s],m=e.value[s]/2,s===o-1?(h=l+a,V=0):(h=~~e.time[s+1],V=e.value[s+1]/2),r=i(l,m,h,V);for(var U=l;h>U;U++)e.xpx.push(U-n),e.ypx.push(r(U))}e.xpx.push(h-n),e.ypx.push(V)}function a(e,t,i){for(var n,a=0,o=t.xpx.length,r=0;o>r;r++)n=i(t,r),a=Math.max(a,n+e[t.xpx[r]]);for(r=0;o>r;r++)n=i(t,r),e[t.xpx[r]]=a+n;return a}return e}),i("echarts/chart/venn",["require","./base","zrender/shape/Text","zrender/shape/Circle","zrender/shape/Path","../config","../util/ecData","zrender/tool/util","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a)}var i=e("./base"),n=e("zrender/shape/Text"),a=e("zrender/shape/Circle"),o=e("zrender/shape/Path"),r=e("../config");r.venn={zlevel:0,z:1,calculable:!1};var s=e("../util/ecData"),l=e("zrender/tool/util");return t.prototype={type:r.CHART_TYPE_VENN,_buildShape:function(){this.selectedMap={},this._symbol=this.option.symbolList,this._queryTarget,this._dropBoxList=[],this._vennDataCounter=0;for(var e=this.series,t=this.component.legend,i=0;ia[1].value?(t=this.zr.getHeight()/3,i=t*Math.sqrt(a[1].value)/Math.sqrt(a[0].value)):(i=this.zr.getHeight()/3,t=i*Math.sqrt(a[0].value)/Math.sqrt(a[1].value));var o=this.zr.getWidth()/2-t,r=(t+i)/2*Math.sqrt(a[2].value)/Math.sqrt((a[0].value+a[1].value)/2),s=t+i;0!==a[2].value&&(s=this._getCoincideLength(a[0].value,a[1].value,a[2].value,t,i,r,Math.abs(t-i),t+i));var l=o+s,h=this.zr.getHeight()/2;if(this._buildItem(e,0,a[0],o,h,t),this._buildItem(e,1,a[1],l,h,i),0!==a[2].value&&a[2].value!==a[0].value&&a[2].value!==a[1].value){var m=(t*t-i*i)/(2*s)+s/2,V=s/2-(t*t-i*i)/(2*s),U=Math.sqrt(t*t-m*m),d=0,p=0;a[0].value>a[1].value&&o+m>l&&(p=1),a[0].valuel&&(d=1),this._buildCoincideItem(e,2,a[2],o+m,h-U,h+U,t,i,d,p)}},_getCoincideLength:function(e,t,i,n,a,o,r,s){var l=(n*n-a*a)/(2*o)+o/2,h=o/2-(n*n-a*a)/(2*o),m=Math.acos(l/n),V=Math.acos(h/a),U=n*n*Math.PI,d=m*n*n-l*n*Math.sin(m)+V*a*a-h*a*Math.sin(V),p=d/U,c=i/e,u=Math.abs(p/c);return u>.999&&1.001>u?o:.999>=u?(s=o,o=(o+r)/2,this._getCoincideLength(e,t,i,n,a,o,r,s)):(r=o,o=(o+s)/2,this._getCoincideLength(e,t,i,n,a,o,r,s))},_buildItem:function(e,t,i,n,a,o){var r=this.series,l=r[e],h=this.getCircle(e,t,i,n,a,o);if(s.pack(h,l,e,i,t,i.name),this.shapeList.push(h),l.itemStyle.normal.label.show){var m=this.getLabel(e,t,i,n,a,o);s.pack(m,l,e,l.data[t],t,l.data[t].name),this.shapeList.push(m)}},_buildCoincideItem:function(e,t,i,n,a,r,l,h,m,V){var U=this.series,d=U[e],p=[i,d],c=this.deepMerge(p,"itemStyle.normal")||{},u=this.deepMerge(p,"itemStyle.emphasis")||{},y=c.color||this.zr.getColor(t),g=u.color||this.zr.getColor(t),b="M"+n+","+a+"A"+l+","+l+",0,"+m+",1,"+n+","+r+"A"+h+","+h+",0,"+V+",1,"+n+","+a,f={color:y,path:b},k={zlevel:d.zlevel,z:d.z,style:f,highlightStyle:{color:g,lineWidth:u.borderWidth,strokeColor:u.borderColor}};k=new o(k),k.buildPathArray&&(k.style.pathArray=k.buildPathArray(f.path)),s.pack(k,U[e],0,i,t,i.name),this.shapeList.push(k)},getCircle:function(e,t,i,n,o,r){var s=this.series[e],l=[i,s],h=this.deepMerge(l,"itemStyle.normal")||{},m=this.deepMerge(l,"itemStyle.emphasis")||{},V=h.color||this.zr.getColor(t),U=m.color||this.zr.getColor(t),d={zlevel:s.zlevel,z:s.z,clickable:!0,style:{x:n,y:o,r:r,brushType:"fill",opacity:1,color:V},highlightStyle:{color:U,lineWidth:m.borderWidth,strokeColor:m.borderColor}};return this.deepQuery([i,s,this.option],"calculable")&&(this.setCalculable(d),d.draggable=!0),new a(d)},getLabel:function(e,t,i,a,o,r){var s=this.series[e],l=s.itemStyle,h=[i,s],m=this.deepMerge(h,"itemStyle.normal")||{},V="normal",U=l[V].label,d=U.textStyle||{},p=this.getLabelText(t,i,V),c=this.getFont(d),u=m.color||this.zr.getColor(t),y=d.fontSize||12,g={zlevel:s.zlevel,z:s.z,style:{x:a,y:o-r-y,color:d.color||u,text:p,textFont:c,textAlign:"center"}};return new n(g)},getLabelText:function(e,t,i){var n=this.series,a=n[0],o=this.deepQuery([t,a],"itemStyle."+i+".label.formatter");return o?"function"==typeof o?o(a.name,t.name,t.value):"string"==typeof o?(o=o.replace("{a}","{a0}").replace("{b}","{b0}").replace("{c}","{c0}"),o=o.replace("{a0}",a.name).replace("{b0}",t.name).replace("{c0}",t.value)):void 0:t.name},refresh:function(e){e&&(this.option=e,this.series=e.series),this._buildShape()}},l.inherits(t,i),e("../chart").define("venn",t),t}),i("echarts/chart/treemap",["require","./base","zrender/tool/area","zrender/shape/Rectangle","zrender/shape/Text","zrender/shape/Line","../layout/TreeMap","../data/Tree","../config","../util/ecData","zrender/config","zrender/tool/event","zrender/tool/util","zrender/tool/color","../chart"],function(e){function t(e,t,n,a,o){i.call(this,e,t,n,a,o),this.refresh(a);var r=this;r._onclick=function(e){return r.__onclick(e)},r.zr.on(V.EVENT.CLICK,r._onclick)}var i=e("./base"),n=e("zrender/tool/area"),a=e("zrender/shape/Rectangle"),o=e("zrender/shape/Text"),r=e("zrender/shape/Line"),s=e("../layout/TreeMap"),l=e("../data/Tree"),h=e("../config");h.treemap={zlevel:0,z:1,calculable:!1,clickable:!0,center:["50%","50%"],size:["80%","80%"],root:"",itemStyle:{normal:{label:{ -show:!0,x:5,y:12,textStyle:{align:"left",color:"#000",fontFamily:"Arial",fontSize:13,fontStyle:"normal",fontWeight:"normal"}},breadcrumb:{show:!0,textStyle:{}},borderWidth:1,borderColor:"#ccc",childBorderWidth:1,childBorderColor:"#ccc"},emphasis:{}}};var m=e("../util/ecData"),V=e("zrender/config"),U=(e("zrender/tool/event"),e("zrender/tool/util")),d=e("zrender/tool/color");return t.prototype={type:h.CHART_TYPE_TREEMAP,refresh:function(e){this.clear(),e&&(this.option=e,this.series=this.option.series),this._treesMap={};for(var t=this.series,i=this.component.legend,n=0;nt.width||e.normal.label.y+U>t.height)&&(h=""):h="",e.emphasis.label.show?(s.x+u>t.width||s.y+y>t.height)&&(p=""):p="";var g={style:{textX:t.x+e.normal.label.x,textY:t.y+e.normal.label.y,text:h,textPosition:"specific",textColor:o.color,textFont:m},highlightStyle:{textX:t.x+e.emphasis.label.x,textY:t.y+e.emphasis.label.y,text:p,textColor:s.color,textPosition:"specific"}};return g},getLabelText:function(e,t,i){return i?"function"==typeof i?i.call(this.myChart,e,t):"string"==typeof i?(i=i.replace("{b}","{b0}").replace("{c}","{c0}"),i=i.replace("{b0}",e).replace("{c0}",t)):void 0:e},_buildChildrenTreemap:function(e,t,i,n){for(var a=i.width*i.height,o=0,r=[],l=0;l ":"")},V),clickable:!0,highlightStyle:p});m.set(u,"seriesIndex",t),m.set(u,"name",a[c]),i+=u.getRect(u.style).width,this.shapeList.push(u)}},__onclick:function(e){var t=e.target;if(t){var i=m.get(t,"seriesIndex"),n=m.get(t,"name"),a=this._treesMap[i],o=a.getNodeById(n);o&&o.children.length&&this._buildTreemap(o,i)}}},U.inherits(t,i),e("../chart").define("treemap",t),t}),i("echarts/layout/TreeMap",["require"],function(){function e(e){({x:e.x,y:e.y,width:e.width,height:e.height});this.x=e.x,this.y=e.y,this.width=e.width,this.height=e.height}return e.prototype.run=function(e){var t=[];return this._squarify(e,{x:this.x,y:this.y,width:this.width,height:this.height},t),t},e.prototype._squarify=function(e,t,i){var n="VERTICAL",a=t.width,o=t.height;t.widthl;l++)r[s].y+=r[l].height}var h={};if("VERTICAL"==n){for(var m=0;ml;l++){var h=i*e[l]/o;a.push({width:s,height:h})}return a},e.prototype._isFirstBetter=function(e,t){var i=e[0].height/e[0].width;i=i>1?1/i:i;var n=t[0].height/t[0].width;return n=n>1?1/n:n,Math.abs(i-1)<=Math.abs(n-1)?!0:!1},e}),i("echarts/data/Tree",["require","zrender/tool/util"],function(e){function t(e,t){this.id=e,this.depth=0,this.height=0,this.children=[],this.parent=null,this.data=t||null}function i(e){this.root=new t(e)}var n=e("zrender/tool/util");return t.prototype.add=function(e){var t=this.children;e.parent!==this&&(t.push(e),e.parent=this)},t.prototype.remove=function(e){var t=this.children,i=n.indexOf(t,e);i>=0&&(t.splice(i,1),e.parent=null)},t.prototype.traverse=function(e,t){e.call(t,this);for(var i=0;it&&(t=n.height)}this.height=t+1},t.prototype.getNodeById=function(e){if(this.id===e)return this;for(var t=0;t0&&this._buildLink(i,e)},this);var n=e.roam===!0||"move"===e.roam,a=e.roam===!0||"scale"===e.roam;this.zr.modLayer(this.getZlevelBase(),{panable:n,zoomable:a}),(this.query("markPoint.effect.show")||this.query("markLine.effect.show"))&&this.zr.modLayer(m.EFFECT_ZLEVEL,{panable:n,zoomable:a}),this.addShapeList()},_buildItem:function(e,t,i){var n=[e.data,t],r=this.deepQuery(n,"symbol"),s=this.deepMerge(n,"itemStyle.normal")||{},l=this.deepMerge(n,"itemStyle.emphasis")||{},h=s.color||this.zr.getColor(),m=l.color||this.zr.getColor(),U=-e.layout.angle||0;e.id===this.tree.root.id&&(U=0);var d="right";Math.abs(U)>=Math.PI/2&&Math.abs(U)<3*Math.PI/2&&(U+=Math.PI,d="left");var p=[U,e.layout.position[0],e.layout.position[1]],c=new a({zlevel:this.getZlevelBase(),z:this.getZBase()+1,rotation:p,clickable:this.deepQuery(n,"clickable"),style:{x:e.layout.position[0]-.5*e.layout.width,y:e.layout.position[1]-.5*e.layout.height,width:e.layout.width,height:e.layout.height,iconType:r,color:h,brushType:"both",lineWidth:s.borderWidth,strokeColor:s.borderColor},highlightStyle:{color:m,lineWidth:l.borderWidth,strokeColor:l.borderColor}});c.style.iconType.match("image")&&(c.style.image=c.style.iconType.replace(new RegExp("^image:\\/\\/"),""),c=new o({rotation:p,style:c.style,highlightStyle:c.highlightStyle,clickable:c.clickable,zlevel:this.getZlevelBase(),z:this.getZBase()})),this.deepQuery(n,"itemStyle.normal.label.show")&&(c.style.text=null==e.data.label?e.id:e.data.label,c.style.textPosition=this.deepQuery(n,"itemStyle.normal.label.position"),"radial"===t.orient&&"inside"!==c.style.textPosition&&(c.style.textPosition=d),c.style.textColor=this.deepQuery(n,"itemStyle.normal.label.textStyle.color"),c.style.textFont=this.getFont(this.deepQuery(n,"itemStyle.normal.label.textStyle")||{})),this.deepQuery(n,"itemStyle.emphasis.label.show")&&(c.highlightStyle.textPosition=this.deepQuery(n,"itemStyle.emphasis.label.position"),c.highlightStyle.textColor=this.deepQuery(n,"itemStyle.emphasis.label.textStyle.color"),c.highlightStyle.textFont=this.getFont(this.deepQuery(n,"itemStyle.emphasis.label.textStyle")||{})),V.pack(c,t,i,e.data,0,e.id),this.shapeList.push(c)},_buildLink:function(e,t){var i=t.itemStyle.normal.lineStyle;if("broken"===i.type)return void this._buildBrokenLine(e,i,t);for(var n=0;nr&&(t=r),r>n&&(n=r)}e.layout.position[0]=e.children.length>0?(t+n)/2:0;var s=this._layerOffsets[e.depth]||0;if(s>e.layout.position[0]){var l=s-e.layout.position[0];this._shiftSubtree(e,l);for(var a=e.depth+1;ai;i++)this._buildTextShape(e[i],0,i);this.addShapeList()},_buildTextShape:function(e,t,i){var a=this.series,o=a[t],s=o.name||"",h=o.data[i],m=[h,o],V=this.component.legend,U=V?V.getColor(s):this.zr.getColor(t),d=this.deepMerge(m,"itemStyle.normal")||{},p=this.deepMerge(m,"itemStyle.emphasis")||{},c=this.getItemStyleColor(d.color,t,i,h)||U,u=this.getItemStyleColor(p.color,t,i,h)||("string"==typeof c?l.lift(c,-.2):c),y=new n({zlevel:o.zlevel,z:o.z,hoverable:!0,clickable:this.deepQuery(m,"clickable"),style:{x:0,y:0,text:e.text,color:c,textFont:[e.style,e.weight,e.size+"px",e.font].join(" "),textBaseline:"alphabetic",textAlign:"center"},highlightStyle:{brushType:p.borderWidth?"both":"fill",color:u,lineWidth:p.borderWidth||0,strokeColor:p.borderColor},position:[e.x,e.y],rotation:[-e.rotate/180*Math.PI,0,0]});r.pack(y,o,t,h,i,h.name),this.shapeList.push(y)}},s.inherits(t,i),e("../chart").define("wordCloud",t),t}),i("echarts/layout/WordCloud",["require","../layout/WordCloudRectZero","zrender/tool/util"],function(e){function t(e){this._init(e)}var i=e("../layout/WordCloudRectZero"),n=e("zrender/tool/util");return t.prototype={start:function(){function e(){p.totalArea=r,U.autoSizeCal.enable&&p._autoCalTextSize(m,r,a,o,U.autoSizeCal.minSize),V.timer&&clearInterval(V.timer),V.timer=setInterval(t,0),t()}function t(){for(var e,t=+new Date,i=m.length;+new Date-t>1,e.y=d[1]>>1,p._cloudSprite(e,m,s),e.hasText&&p._place(n,e,h)&&(l.push(e),e.x-=d[0]>>1,e.y-=d[1]>>1);s>=i&&(p.stop(),p._fixTagPosition(l),V.endcallback(l))}var n=null,a=0,o=0,r=0,s=-1,l=[],h=null,m=this.wordsdata,V=this.defaultOption,U=V.wordletype,d=V.size,p=this,c=new i({type:U.type,width:d[0],height:d[1]});return c.calculate(function(t){n=t.initarr,a=t.maxWit,o=t.maxHit,r=t.area,h=t.imgboard,e()},this),this},_fixTagPosition:function(e){for(var t=this.defaultOption.center,i=0,n=e.length;n>i;i++)e[i].x+=t[0],e[i].y+=t[1]},stop:function(){return this.defaultOption.timer&&(clearInterval(this.defaultOption.timer),this.defaultOption.timer=null),this},end:function(e){return e&&(this.defaultOption.endcallback=e),this},_init:function(e){this.defaultOption={},this._initProperty(e),this._initMethod(e),this._initCanvas(),this._initData(e.data)},_initData:function(e){var t=this,i=t.defaultOption;this.wordsdata=e.map(function(e,n){return e.text=i.text.call(t,e,n),e.font=i.font.call(t,e,n),e.style=i.fontStyle.call(t,e,n),e.weight=i.fontWeight.call(t,e,n),e.rotate=i.rotate.call(t,e,n),e.size=~~i.fontSize.call(t,e,n),e.padding=i.padding.call(t,e,n),e}).sort(function(e,t){return t.value-e.value})},_initMethod:function(e){function t(e){return e.name}function i(){return"sans-serif"}function n(){return"normal"}function a(e){return e.value}function o(){return 0}function r(e){return function(){return e[Math.round(Math.random()*(e.length-1))]}}function s(){return 0}function l(e){var t=e[0]/e[1];return function(e){return[t*(e*=.1)*Math.cos(e),e*Math.sin(e)]}}function h(e){var t=4,i=t*e[0]/e[1],n=0,a=0;return function(e){var o=0>e?-1:1;switch(Math.sqrt(1+4*o*e)-o&3){case 0:n+=i;break;case 1:a+=t;break;case 2:n-=i;break;default:a-=t}return[n,a]}}function m(e){return"function"==typeof e?e:function(){return e}}var V=this.defaultOption;V.text=e.text?m(e.text):t,V.font=e.font?m(e.font):i,V.fontSize=e.fontSize?m(e.fontSize):a,V.fontStyle=e.fontStyle?m(e.fontStyle):n,V.fontWeight=e.fontWeight?m(e.fontWeight):n,V.rotate=e.rotate?r(e.rotate):o,V.padding=e.padding?m(e.padding):s,V.center=e.center,V.spiral=l,V.endcallback=function(){},V.rectangularSpiral=h,V.archimedeanSpiral=l},_initProperty:function(e){var t=this.defaultOption;t.size=e.size||[256,256],t.wordletype=e.wordletype,t.words=e.words||[],t.timeInterval=1/0,t.timer=null,t.spirals={archimedean:t.archimedeanSpiral,rectangular:t.rectangularSpiral},n.merge(t,{size:[256,256],wordletype:{type:"RECT",areaPresent:.058,autoSizeCal:{enable:!0,minSize:12}}})},_initCanvas:function(){var e,t=Math.PI/180,i=64,n=2048,a=1;"undefined"!=typeof document?(e=document.createElement("canvas"),e.width=1,e.height=1,a=Math.sqrt(e.getContext("2d").getImageData(0,0,1,1).data.length>>2),e.width=(i<<5)/a,e.height=n/a):e=new Canvas(i<<5,n);var o=e.getContext("2d");o.fillStyle=o.strokeStyle="red",o.textAlign="center",this.defaultOption.c=o,this.defaultOption.cw=i,this.defaultOption.ch=n,this.defaultOption.ratio=a,this.defaultOption.cloudRadians=t},_cloudSprite:function(e,t,i){if(!e.sprite){var n=this.defaultOption.cw,a=this.defaultOption.ch,o=this.defaultOption.c,r=this.defaultOption.ratio,s=this.defaultOption.cloudRadians;o.clearRect(0,0,(n<<5)/r,a/r);var l=0,h=0,m=0,V=t.length;for(--i;++i>5<<5,d=~~Math.max(Math.abs(y+g),Math.abs(y-g))}else U=U+31>>5<<5;if(d>m&&(m=d),l+U>=n<<5&&(l=0,h+=m,m=0),h+d>=a)break;o.translate((l+(U>>1))/r,(h+(d>>1))/r),e.rotate&&o.rotate(e.rotate*s),o.fillText(e.text,0,0),e.padding&&(o.lineWidth=2*e.padding,o.strokeText(e.text,0,0)),o.restore(),e.width=U,e.height=d,e.xoff=l,e.yoff=h,e.x1=U>>1,e.y1=d>>1,e.x0=-e.x1,e.y0=-e.y1,e.hasText=!0,l+=U}for(var f=o.getImageData(0,0,(n<<5)/r,a/r).data,k=[];--i>=0;)if(e=t[i],e.hasText){for(var U=e.width,x=U>>5,d=e.y1-e.y0,_=0;d*x>_;_++)k[_]=0;if(l=e.xoff,null==l)return;h=e.yoff;for(var L=0,W=-1,X=0;d>X;X++){for(var _=0;U>_;_++){var v=x*X+(_>>5),w=f[(h+X)*(n<<5)+(l+_)<<2]?1<<31-_%32:0;k[v]|=w,L|=w}L?W=X:(e.y0++,d--,X--,h++)}e.y1=e.y0+W,e.sprite=k.slice(0,(e.y1-e.y0)*x)}}},_place:function(e,t,i){function n(e,t,i){i>>=5;for(var n,a=e.sprite,o=e.width>>5,r=e.x-(o<<4),s=127&r,l=32-s,h=e.y1-e.y0,m=(e.y+e.y0)*i+(r>>5),V=0;h>V;V++){n=0;for(var U=0;o>=U;U++)if((n<U?(n=a[V*o+U])>>>s:0))&t[m+U])return!0;m+=i}return!1}function a(e,t){return t.row[e.y]&&t.cloumn[e.x]&&e.x>=t.row[e.y].start&&e.x<=t.row[e.y].end&&e.y>=t.cloumn[e.x].start&&e.y<=t.cloumn[e.x].end}for(var o,r,s,l=this.defaultOption.size,h=([{x:0,y:0},{x:l[0],y:l[1]}],t.x),m=t.y,V=Math.sqrt(l[0]*l[0]+l[1]*l[1]),U=this.defaultOption.spiral(l),d=Math.random()<.5?1:-1,p=-d;(o=U(p+=d))&&(r=~~o[0],s=~~o[1],!(Math.min(r,s)>V));)if(t.x=h+r,t.y=m+s,!(t.x+t.x0<0||t.y+t.y0<0||t.x+t.x1>l[0]||t.y+t.y1>l[1])&&!n(t,e,l[0])&&a(t,i)){for(var c,u=t.sprite,y=t.width>>5,g=l[0]>>5,b=t.x-(y<<4),f=127&b,k=32-f,x=t.y1-t.y0,_=(t.y+t.y0)*g+(b>>5),L=0;x>L;L++){c=0;for(var W=0;y>=W;W++)e[_+W]|=c<W?(c=u[L*y+W])>>>f:0);_+=g}return delete t.sprite,!0}return!1},_autoCalTextSize:function(e,t,i,n,a){function o(e){c.clearRect(0,0,(d<<5)/u,p/u),c.save(),c.font=e.style+" "+e.weight+" "+~~((e.size+1)/u)+"px "+e.font;var t=c.measureText(e.text+"m").width*u,r=e.size<<1;t=t+31>>5<<5,c.restore(),e.aw=t,e.ah=r;var s,l,h;if(e.rotate){var m=Math.sin(e.rotate*y),V=Math.cos(e.rotate*y),g=t*V,b=t*m,f=r*V,k=r*m;l=Math.max(Math.abs(g+k),Math.abs(g-k))+31>>5<<5,h=~~Math.max(Math.abs(b+f),Math.abs(b-f))}return e.size<=U||e.rotate&&t*r<=e.area&&i>=l&&n>=h||t*r<=e.area&&i>=t&&n>=r?void(e.area=t*r):(s=e.rotate&&l>i&&h>n?Math.min(i/l,n/h):t>i||r>n?Math.min(i/t,n/r):Math.sqrt(e.area/(e.aw*e.ah)),e.size=~~(s*e.size),e.sizel?l:V:l,s.area=t*s.areapre,s.totalarea=t,o(s)}},t}),i("echarts/layout/WordCloudRectZero",["require"],function(){function e(e){this.defaultOption={type:"RECT"},this._init(e)}return e.prototype={RECT:"_calculateRect",_init:function(e){this._initOption(e),this._initCanvas()},_initOption:function(e){for(k in e)this.defaultOption[k]=e[k]},_initCanvas:function(){var e=document.createElement("canvas");e.width=1,e.height=1;var t=Math.sqrt(e.getContext("2d").getImageData(0,0,1,1).data.length>>2);if(e.width=this.defaultOption.width,e.height=this.defaultOption.height,e.getContext)var i=e.getContext("2d");this.canvas=e,this.ctx=i,this.ratio=t},calculate:function(e,t){var i=this.defaultOption.type,n=this[i];this[n].call(this,e,t)},_calculateReturn:function(e,t,i){t.call(i,e)},_calculateRect:function(e,t){var i={},n=this.defaultOption.width>>5<<5,a=this.defaultOption.height;i.initarr=this._rectZeroArray(n*a),i.area=n*a,i.maxHit=a,i.maxWit=n,i.imgboard=this._rectBoard(n,a),this._calculateReturn(i,e,t)},_rectBoard:function(e,t){for(var i=[],n=0;t>n;n++)i.push({y:n,start:0,end:e});for(var a=[],n=0;e>n;n++)a.push({x:n,start:0,end:t});return{row:i,cloumn:a}},_rectZeroArray:function(e){for(var t=[],i=e,n=-1;++ni;++i)if(e[i].type===a.CHART_TYPE_HEATMAP){e[i]=this.reformOption(e[i]);var o=new n(e[i]),s=o.getCanvas(e[i].data,this.zr.getWidth(),this.zr.getHeight()),l=new r({position:[0,0],scale:[1,1],hoverable:this.option.hoverable,style:{x:0,y:0,image:s,width:s.width,height:s.height}});this.shapeList.push(l)}this.addShapeList()}},o.inherits(t,i),e("../chart").define("heatmap",t),t});var n=t("zrender");n.tool={color:t("zrender/tool/color"),math:t("zrender/tool/math"),util:t("zrender/tool/util"),vector:t("zrender/tool/vector"),area:t("zrender/tool/area"),event:t("zrender/tool/event")},n.animation={Animation:t("zrender/animation/Animation"),Cip:t("zrender/animation/Clip"),easing:t("zrender/animation/easing")};var a=t("echarts");a.config=t("echarts/config"),a.util={mapData:{params:t("echarts/util/mapData/params")}},t("echarts/chart/line"),t("echarts/chart/bar"),t("echarts/chart/scatter"),t("echarts/chart/k"),t("echarts/chart/pie"),t("echarts/chart/radar"),t("echarts/chart/chord"),t("echarts/chart/force"),t("echarts/chart/map"),t("echarts/chart/gauge"),t("echarts/chart/funnel"),t("echarts/chart/eventRiver"),t("echarts/chart/venn"),t("echarts/chart/treemap"),t("echarts/chart/tree"),t("echarts/chart/wordCloud"),t("echarts/chart/heatmap"),e.echarts=a,e.zrender=n}(window); - -layui.define('echartsTheme', function(exports){ - exports('echarts', echarts); -}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/echartsTheme.js b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/echartsTheme.js deleted file mode 100644 index ef8a2eda..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/echartsTheme.js +++ /dev/null @@ -1,267 +0,0 @@ -/** - - @Name:echarts 主题 - - - @License:GPL-2 - - */ - - -layui.define(function(exports) { - exports('echartsTheme', { - // 默认色板 - color: [ - '#009688','#1E9FFF','#5FB878','#FFB980','#D87A80', - '#8d98b3','#e5cf0d','#97b552','#95706d','#dc69aa', - '#07a2a4','#9a7fd1','#588dd5','#f5994e','#c05050', - '#59678c','#c9ab00','#7eb00a','#6f5553','#c14089' - ], - - // 图表标题 - title: { - textStyle: { - fontWeight: 'normal', - color: '#666' // 主标题文字颜色 - } - }, - - // 值域 - dataRange: { - itemWidth: 15, - color: ['#009688','#e0ffff'] - }, - - // 工具箱 - toolbox: { - color : ['#1e90ff', '#1e90ff', '#1e90ff', '#1e90ff'], - effectiveColor : '#ff4500' - }, - - // 提示框 - tooltip: { - backgroundColor: 'rgba(50,50,50,0.5)', // 提示背景颜色,默认为透明度为0.7的黑色 - axisPointer : { // 坐标轴指示器,坐标轴触发有效 - type : 'line', // 默认为直线,可选为:'line' | 'shadow' - lineStyle : { // 直线指示器样式设置 - color: '#009688' - }, - crossStyle: { - color: '#008acd' - }, - shadowStyle : { // 阴影指示器样式设置 - color: 'rgba(200,200,200,0.2)' - } - } - }, - - // 区域缩放控制器 - dataZoom: { - dataBackgroundColor: '#efefff', // 数据背景颜色 - fillerColor: 'rgba(182,162,222,0.2)', // 填充颜色 - handleColor: '#008acd' // 手柄颜色 - }, - - // 网格 - grid: { - borderColor: '#eee' - }, - - // 类目轴 - X轴 - categoryAxis: { - axisLine: { // 坐标轴线 - lineStyle: { // 属性lineStyle控制线条样式 - color: '#009688' - } - }, - axisTick: { //小标记 - show: false - }, - splitLine: { // 分隔线 - lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式 - color: ['#eee'] - } - } - }, - - // 数值型坐标轴默认参数 - Y轴 - valueAxis: { - axisLine: { // 坐标轴线 - lineStyle: { // 属性lineStyle控制线条样式 - color: '#009688' - } - }, - splitArea : { - show : true, - areaStyle : { - color: ['rgba(250,250,250,0.1)','rgba(200,200,200,0.1)'] - } - }, - splitLine: { // 分隔线 - lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式 - color: ['#eee'] - } - } - }, - - polar : { - axisLine: { // 坐标轴线 - lineStyle: { // 属性lineStyle控制线条样式 - color: '#ddd' - } - }, - splitArea : { - show : true, - areaStyle : { - color: ['rgba(250,250,250,0.2)','rgba(200,200,200,0.2)'] - } - }, - splitLine : { - lineStyle : { - color : '#ddd' - } - } - }, - - timeline : { - lineStyle : { - color : '#009688' - }, - controlStyle : { - normal : { color : '#009688'}, - emphasis : { color : '#009688'} - }, - symbol : 'emptyCircle', - symbolSize : 3 - }, - - // 柱形图默认参数 - bar: { - itemStyle: { - normal: { - barBorderRadius: 2 - }, - emphasis: { - barBorderRadius: 2 - } - } - }, - - // 折线图默认参数 - line: { - smooth : true, - symbol: 'emptyCircle', // 拐点图形类型 - symbolSize: 3 // 拐点图形大小 - }, - - // K线图默认参数 - k: { - itemStyle: { - normal: { - color: '#d87a80', // 阳线填充颜色 - color0: '#2ec7c9', // 阴线填充颜色 - lineStyle: { - color: '#d87a80', // 阳线边框颜色 - color0: '#2ec7c9' // 阴线边框颜色 - } - } - } - }, - - // 散点图默认参数 - scatter: { - symbol: 'circle', // 图形类型 - symbolSize: 4 // 图形大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2 - }, - - // 雷达图默认参数 - radar : { - symbol: 'emptyCircle', // 图形类型 - symbolSize:3 - //symbol: null, // 拐点图形类型 - //symbolRotate : null, // 图形旋转控制 - }, - - map: { - itemStyle: { - normal: { - areaStyle: { - color: '#ddd' - }, - label: { - textStyle: { - color: '#d87a80' - } - } - }, - emphasis: { // 也是选中样式 - areaStyle: { - color: '#fe994e' - } - } - } - }, - - force : { - itemStyle: { - normal: { - linkStyle : { - color : '#1e90ff' - } - } - } - }, - - chord : { - itemStyle : { - normal : { - borderWidth: 1, - borderColor: 'rgba(128, 128, 128, 0.5)', - chordStyle : { - lineStyle : { - color : 'rgba(128, 128, 128, 0.5)' - } - } - }, - emphasis : { - borderWidth: 1, - borderColor: 'rgba(128, 128, 128, 0.5)', - chordStyle : { - lineStyle : { - color : 'rgba(128, 128, 128, 0.5)' - } - } - } - } - }, - - gauge : { - axisLine: { // 坐标轴线 - lineStyle: { // 属性lineStyle控制线条样式 - color: [[0.2, '#2ec7c9'],[0.8, '#5ab1ef'],[1, '#d87a80']], - width: 10 - } - }, - axisTick: { // 坐标轴小标记 - splitNumber: 10, // 每份split细分多少段 - length :15, // 属性length控制线长 - lineStyle: { // 属性lineStyle控制线条样式 - color: 'auto' - } - }, - splitLine: { // 分隔线 - length :22, // 属性length控制线长 - lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式 - color: 'auto' - } - }, - pointer : { - width : 5 - } - }, - - textStyle: { - fontFamily: '微软雅黑, Arial, Verdana, sans-serif' - } - }); -}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/chatlog.html b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/chatlog.html deleted file mode 100644 index 04d17f18..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/chatlog.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - -聊天记录 - - - - - - -
                          -
                            -
                            - -
                            - - - - - - - - - - - diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/find.html b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/find.html deleted file mode 100644 index 5a66d6e0..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/find.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - -发现 - - - - - - -
                            -
                            此为自定义的【查找】页面,因需求不一,所以官方暂不提供该模版结构与样式,实际使用时,可移至该文件到你的项目中,对页面自行把控。 -
                            文件所在目录(相对于layui.js):/layim-assets/html/find.html
                            -
                            - - - - - - - diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/getmsg.json b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/getmsg.json deleted file mode 100644 index c4ef35fa..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/getmsg.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "code": 0, - "pages": 1, - "data": [ - { - "id": 76, - "content": "申请添加你为好友", - "uid": 168, - "from": 166488, - "from_group": 0, - "type": 1, - "remark": "test1", - "href": null, - "read": 1, - "time": "刚刚", - "user": { - "id": 166488, - "avatar": "http://q.qlogo.cn/qqapp/101235792/B704597964F9BD0DB648292D1B09F7E8/100", - "username": "测试111", - "sign": null - } - }, - { - "id": 75, - "content": "申请添加你为好友", - "uid": 168, - "from": 347592, - "from_group": 0, - "type": 1, - "remark": "test2", - "href": null, - "read": 1, - "time": "刚刚", - "user": { - "id": 347592, - "avatar": "http://q.qlogo.cn/qqapp/101235792/B78751375E0531675B1272AD994BA875/100", - "username": "测试222", - "sign": null - } - }, - { - "id": 62, - "content": "测试333 拒绝了你的好友申请", - "uid": 168, - "from": null, - "from_group": null, - "type": 1, - "remark": null, - "href": null, - "read": 1, - "time": "10天前", - "user": { - "id": null - } - }, - { - "id": 60, - "content": "测试666 已经同意你的好友申请", - "uid": 168, - "from": null, - "from_group": null, - "type": 1, - "remark": null, - "href": null, - "read": 1, - "time": "10天前", - "user": { - "id": null - } - } - ] -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/msgbox.html b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/msgbox.html deleted file mode 100644 index f56d0f74..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/html/msgbox.html +++ /dev/null @@ -1,218 +0,0 @@ - - - - - - - -消息盒子 - - - - - - -
                              - -
                              -
                              注意:这些都是模拟数据,实际使用时,需将其中的模拟接口改为你的项目真实接口。 -
                              该模版文件所在目录(相对于 layim.js):/html/msgbox.html
                              -
                              - - - - - - - - - - diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/default.png b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/default.png deleted file mode 100644 index 33c7691aa62991324afeed6acfd220e0b3ae4e85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6727 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 CBC!|% diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/1.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/1.gif deleted file mode 100644 index b2b78b218996f70773540d0d3a8649d3c2d199a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5514 zcmeI0X;f2Z8pm%|0tv}wF|q`>VUY-kh?astAQA;dB?6_fabYVUO9#+)7)Q(s2}KDA zighC_TBPE*AR-hSAO%6du#{TxXn-QNiVcVgN|Fij%v8I5oO9-!+)ww*d!7%!|9hVI z{|nx@!P_T>2oQmXY@j$fRCS-Fst#8Fl-Ji<_wt8B#oMn7hHBnZ4SIK-bRDmyJo~XxHIe<@S;}yGsph#%R&3pM=?m3xsA@drb+`R>L5S-6 zz>yk^YAiuB+oYNAZ_LF?#Sxmh?wKCnks9lU+z5q2ar+DGPfeziHw@J?S6jsf&!0cP zdJv^~b+7qw%%v2U$@--gvCCCsdk<_PHte%$Jmk_-lRDCrG;npxi~bPRgV?D7zN#&_ zCe2g*w7m0(@9fi`>xz@w^U1XtK2y!sP1)pEFP~|YwX*|ZH)_kL?|yde{AtyLq;?6r zrS5!RPuG*%o2S}r6<3x__s6NL<5VMzZyPSC`gf@xv3stwub#tO^-JmF&hTmZ_Q|h(Unn2|LQqcJljcz`CqNT-d#=P4TsI+`$f9Ch+HH6_=gXNx+LO~J;=#8M2bsj0pAsmE~jpC z+e9r#gRZAtL!FaYC?7{MaSw`>N^<&&ALWFFS+Qsk`6z^CS-}uaQG8o7OPH^h*N!^J zB?bn*FiR_2UPN3N6Xq3j4@!m%=yWd_((FOaO!^t=l&v`jJMzn0XXJy!`5gR078K1v9z+wE}3v}$MR=6 zIFTWuo=H)j?LKN}v%e&C+c=j~Y*=?dE}h{YLpr1Us*A?L@@)yGj!AMTkYgK|JtLTp zUWYwtNqJJ#_vQJ4FS9uod6LmbIk@-lL+QNel<(bl-msVKb!gj$+4V_uU<(q(x}GL@ zP{By=zzPD^M&24#*nggXldXc+BNE$8YZmMYeZm}wO7Pr>N#jQ-B(?~MM===Y3%&*=Az{%xjzo9W+X z`aYxYGyeyD21WR52Y^Qx#cLG+wFnJr4M0ddVvCPf0r+fTZ3%Hb=^BdjXJOs64!{j- z=8t&W0hH)!X479OfRW#}%z;G(K(o*q2{@ATH=C@;d9$e&vFpb-3t_8bq(m%AT5@Bi zGKi3|JlPKn^yD5RScM;yAK_GS4BiW0*wZ&o;~|Z$kQjO8WbdgJcAJw{tw!Ydd%mLV z?5ZPx4kl~B=EBi-Yvfii`n%!vDN)FMpTt8(Ew_zvl;e_+rl=Jxb0hxKtiGzC91`BW zqTyE4hbwpcrhAe4$e0eaKLebbF8(+pE&#b81IH#>A%oS!(rt_mamlx3=#H zfJ`;IZGvzuAmC!j{5rHu0AsnC&xJqi665{5&Q?zcb2^b9QInYSv`~04FS!aFd?!vT z?KXphV}y6&glQ}sz4LCID8Gpl_h}Ya87wsNA?=`Nl$ZW;|K?|kRPTx)u)uh~1X4b8 z&WAd9zsAXep^cMydzlIptr}~=83}fgrZaeGbNI#uc}5V>o9Fz&=fwToM4rGRP+`G| nqjLpT%jon>&iI|hI5DGFNqSH|Meaf1bVU=!q}mt-2YmkxGX3TC diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/10.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/10.gif deleted file mode 100644 index 556c7e326801a0ea090bd693ca43807925d3cbc2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2797 zcmd^A`#)6c8Xsolx+O`H%Q93$nTyL{n9MM)A-684%gM}GWn?bROqpmGJGZ^Fi(PxC zQc0BVBpao@iAv-WQX~e2E`%;_^UgXmoi68xeb(o*-uGGG@ArA0^?g3?^6~R_ zc3~Q#3{evksAPYm+ldxe`B>25hYY5H$5ilyap#a4=-C9i!a--i^?{+Kq>xB__^Jl4Vn&qDieZbVwCxhx2@ zILKOvg+lCu6V~AQ`is#P@}Y#M=jR}wYR+vn|5TiK@RaXU!OgY6vPDVqMt==D71BV~Djr?Wup*KT5)s0Nt z1Ea;`y*Z$Vg^U%+NAu)^dy4m>3*sq2x(&3`O809f`!AG_6@bUi^1&ZV_v?Zdd(dFk zaB1^UmD5ngJo#|eL{F^zWjuI$5Ol4%mt`$$vYF`IF#R$WJTyT@^O32h{2hyB4HojL z=IPO!U?>rcovq1KN5(EAA1kK%5`D7*2eJ&VEMP|C>Q*F(8D`a)X#VL03k>m1L zNkAHLnrro;Eo8bcxh+q#qdYo0+G?;|YpN42;h4%E5#%GMLHA}^^K#ikNY-R6d*oOs zTKf3>vYC2QS))~Z!7^DZ^;7j+S>2+dJsMN@jAc!@>Domz^^oi_W2V7c*5V2pOc4Y@ z&2m{F+Cg67VV?A0FFQODt)hS_LhA#AAqG>-R6O0>B?2aUJ1mA+@HP&QihXzMZ!E-# zq+-`O1`-1Wo^TY$H%P1BC+l(AvXy{!WD2~F%yz-V|XHpgowuN zu~vo&Sm-lEyq$`rD_=m$oSu9k3_0TMZP`Q;2_lp6BnL+_nY043Ba-Y0M8!?EB{@(W z$rL*$=*xvwWD`birGzrPzvNQvsMsj6SU@2VVq;_RvG#bra2tW-;^Lyzu(PvOAZ$gu zd19u-mM60Os=$CnY#~P==J0utQjy8x?-Wz9ic0_80$1=&mM6l0ZU@iia|sfrfIz|% zl`VY*1_u6bD3|*UEfR;q-|PLa!lLlq0+> z3;A5=bJG;g?6o+|s`rH(IeRURvvLWFVhBoW|HJC9A;tVCm){0gvH3RoFi$b>Ld9UK zAaWp^nVy=Q`1J9^`|+{ScO%1Z-@JY`G&u0`MSowfw5R)d*R#%!r%&1+x3#uBYHn(5 zcvxTep!WW~yEWB!sw)5f>vqMho8@Jtf0o=RzFt&#?dp}wmo8o?IDalb?`-awoYSXH zW}i5IEbHhWzaKgLTV}?ggTJO9_~qxc)Rg3;{XZop?A!a}p7^-klGt54#UkMj0iVZ> z*&fY_+O`#rWV4tNTmHFu)5Z<|Sif%Vn((mDkl@upfdQ-h{d|4Ay%?Szbej80s+%jt z#o3AM=wNS0A`&{X=-C5hG6x_Mhp(KcU9@@YgLMeldR?axtN zwEd5V&Z~-T*Iv@rI8N2DD@?W3Rvb>{t;?G1!&v7sZ$i}`xn`>FQLpFZa5oZbQ!WU# z6N0id*ekoxJ8V?Re!96gG%&ojbC{6bC=zRL(qC9 z9AVRaGo3jGR+2<4BiUquM~)5rObdsjH=o&{j`7Fgq#-%QIg)q|V7l8WN}3~Mr^HPsnv zYBVTkuWYI`!P&3tY=gmCJ!#Glz7;G6+M758sp#>>(`c$v8b;e4Wr3n58|AJ_HBZ4M zKkT%FdUFzk{<}(CnOdM}KuhNHXeOR1V!?SZ4Gh!>qiTZn!)^dLP>z z5V6E{^;KymZ80qbv*Od_xEFz6_>=chubAD346L#aA6UNh2+PBUmt8$z7(H-o8%=4b z+W)tqA(h_^MWGdj)+!Cv!1vT~=&*>=JeMuyj@YH oWz4#Y8lWniX5g=81^=RXq3ldhwpWFqvq6_o40028>wtN;K2 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/11.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/11.gif deleted file mode 100644 index 2bfc58be8c70d512f4371b50b2b98c7b8adbe719..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4121 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 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/15.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/15.gif deleted file mode 100644 index c9f25fa1d25412e2e929347c0db0878b0b641d58..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1793 zcmZ?wbhEHb6k`x$cvjC)UFLjcxo+2{sU44AEqro)?t{~@-b%N3XFR-Hwxr+ulK%oH+No|8@joUb;8o>khO;% z-pt54c=5$f_l$zz1xIF9ZC!k8rPSX?m75>!3YoF0@6_@yw?fNicKtc8QFZZ3q7CQQ zJ28K6dKNF8dwdf2>Dz5FoA&JK_I!S*#c%QM(+{R^st_tYd#Py0=A#ot|K1Au_q1vD z6!%ScSEOWk{yZ-7e1G7dQxZR(%&R%HD{|8GPuFK(p3ArTeE-+$eg#|BB~~S$dA0ra zCi@?c7ri|%pb4sD-Qd^>BZ@TkN^$;DL)19`Dfod@V3w#!8pDhc-E$->ITP|u(PWCJ5fjDdmu ze?xs!vs8YWOpZ)hzDjdnpQuc^mXOXgX{{oe-u@~|ZFy%{R@dafm z@IQa9kQKz2C85GpugPS}VD;TfljXPO4=V=Kgd@?P4xMV}iXHU$+K4vH=vCN_(f6?!dfWS6n2`SY^jFjF5#yp%}dht@+k^lQ5mUcOp* zcs?^%!Geg4gAHe92$#NpR-1INsfoGiRz$%hw=FUkg|bMf)@r}A%N=>H&t=-OGD)%dJ&%aS1;>?S28-4y56)#MguSwF{Wn{Bi0wrzT;!uy3&oA(_^ zP4_wBW87?f(kHzUYzsfa7D1pbvq83K2{lV=HFwoZ*)}QIN_Dj=yXlz=G?~}CDNBnw z0PXZuXlB-166sJM;cnU891&3uiN0ojaP%=)9kJ4E);wy(ATN9lXld$sVfl^MZ`{0f z`<5JUy@-h7JMl*sta~4a6oo18!%LOf$q&}sITYaYiet1X;M?G&Sqt4V`0s%?q;x>VWruo zITPfDMZ!^SQHzD;+gGnyyKeo4jrC#{^>Vzt^*iM1EyS8U1jSr=;w_HEA1-Lp7hf0JU8dSF%T&D%E<+7ylUKYC)M*n|{ZEMUu7fY$3aNE)ViSQzrOwtGm1);sbf z_Dz^%r|aYuqCS15lTnC&w5K1hmuJ8d&l*pEtR`qRKwZ!p-%_Ak4|D*~1b>MAGiJ?5 Y2vsx^3s|^#p`syH?V}DDY9U|^06Jl%MgRZ+ diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/16.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/16.gif deleted file mode 100644 index 34f28e4cde0cd13acdbbd7482282eb306f5b21e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6721 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 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/17.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/17.gif deleted file mode 100644 index 39cd03538a5bc595fbc46c97cf2b06c8bd8dadd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4439 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 IdD(dV7kW}yvj6}9 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/18.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/18.gif deleted file mode 100644 index 7bce2997f86e477a6008fb1cae8dd03cda10abf6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3017 zcmeH}`&W`_9>8Dl1yK_aL;=Ob3nGb&N=AwoykI7&SsFG?;bls#Q?`m}L+3&8mQre& zIhILwGPi9z*=?-c$}De97tM;9W?i*RZLH05$~M7$)uy&if585*zr8;^=RME!`JU(V zdBVcQg2f3|kQMY4K>D$L6S^e*VCwsu-ujWeGlg;bq3@?|+D^5LdymJCUa~Y8^!gsY z{z2f>E#`2~Uw$8|*Z2Aw-rjh4oPRNYo?+rb`(D}^h4Ei=yw2tG^*=}Kj3iFKyRZM} zw>>}ZHeB#+uVQcHV~3jDI;&&G?pO8JbDnoe441zu5^60UJokvzr zv@PhaVNYFm*7q#wK9SmdwCvfV*1neFSKZ$}>n?nC)p6=?;rbSj_t$KHAL}3PEa<7l z>mRPT*&x4NGr#As@2yM6pSLjn(Y*dj>7NEpTfVv_{OyY4+Zz^dS_zZCtkypa)!&IX zoLZ*8lhA*0#ic^$@t)+qlbrW=g8yD6d*A8Wcf0xDy12e8^3j1`$4=T$Pfs(a%_2ir zt_T)IhkCm6j8G5+G2g)$PY6J6$Tu=1D+n^4RsxkeFTbELWWAf4sj1ugkixtW)6Ecv zWNS;}U`@q)+|pne3uOy!gtTyu*sY)rX4J3DCQt+`soayN)bb+?bUm^900+)sKxuL{ z8%=Mmr~F_`>6A0*Shk9_(VXAA|H04URGZCwbQ%k!hM3(&Bw}bBN2+@$iK77J6p;J1m6pocLCoTxg|5!y ze0Aaf=r6G|2gf1@CqP8x;N4093&QL$)a(tQM5EzQI10xor(GH%kwT&%jUNV^Cc!$Qr>))HJJ+FdjJP<~NCyx1LPaqE_63aOSL zgJ#3zZC@Ma=aC`_vIgR0DmB(FDmg1eWaa-$x(nHA>C)vM+xn(*6BFAkVVCoQt)yUc zi`;qCl*tU^fl7hP3x0~0)j?;Ir{@K}9Dr56MqFM(BC4y7VU+0E<@FR@0E;H2X%)v} z@f=?+L)W;zvo>&cXtSq;Arxc*kv?21kSdccVylbQVo%pZV7DqhphS%gSiH`C74Qou zvSgKjLh&Xz#rpvTd8hh^c&7$$;F+OHld7a#6W1_8So~tSn(GC`T+gsL@33|2Jmpdm zS>YrI@jDy0{X2rUlOH+5eK0+6lrp`Ee8TDsDT5j z{-{H!`6`2m$W+<;CXJK>VGkKG6H^utqr~ZXveDXw4q44brq@gD?PV95b>qfeAzVB@vs@)69ynJ_({9pf zhXVH+nX;txC(7&P0o&fLE>_-)ne&9@%ylt>um~*^gjS9cFwg+8GeA@d_$)LQ;uHZi zgD)qu=rnE_w5OnwK~M8frDxL6Wr(NuN%zy8qu5)>%nUU;MT(Z%M9@8KPp(5}(^nwq}4<2ejm;;1)1H#-RipPvSpCYvuGQVrc%(rF&-pS>snM~eV|J%Sv zVq-^GX)VgPl2}_>75Xf-Tx#V}ke21+QxWOo&{t9T)y@1L%_lUNxjB7y$3Ez%ct$^V zbNYej{G*ulPYDA+6bhIzPzGY4;_7%OZ-TeLGlR7lNL7qa5<4|1H190@IRAMg5(j8}L?(phY-y`50aH_-& z8U{DVAdq$){Y{AivqB20s8-wpxRcT?Z`FaicaB1cs)H@ zqu@!rE~yt8sHR{M}v6=UaO z1;V8&kz9rTSSvM(4H%a_|H#z?Bv%Z^7s2BH^hL48W|DP0J3FWiUv6)uh@L!>i#eM%g!m2b=EomsZoMrFNGwm%(_p IDGd4k2Wv_t&Hw-a diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/19.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/19.gif deleted file mode 100644 index adac542fd33e152fc08baf165d1c5a467f0c2747..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3040 zcmeH}`&Uxg9>5Q86bs~`fKmvGN=OJ=XsCdSFDfllZ)I9iBDJa+pA|D35dp&{&8Do( zY;4M!>h`{Mb4u-@Ju!RP^cd|iS-0+W(rKJY^ny7y&FUYxYu(?@4||=p&*yvg=d)wt z6ylJDZjc-F6M$^5zP`10c7JD6)#SchlXsnjv(6| z>EJc5=N)_dp6s#Rns#?z&_7FEhJL*;)OV`2igr|s`EHfycxjOBUP9S){P1tLZ9k?D zotoBK?YlGx{p=*K^F;QQZAq_hZ@zN8_Vs1ut=;}ZXX5Vf!w&stkF7!6_vF~~Q_e42 zQwFd5Z7rPp{N$7umsj06{^iwb7u)?=E$cCNcT@WxZGL;VwCh{n!S+dC&tvtpE@`a} z>AzoKJ09@5IkaXOckr_N+m5)tp0@s5Nzbou89I^r`sNqsEVLj0A>Wii8n{S$u_w6y z;-m-7>#a51!Sg=0j@TRfa~i*`czOR^-;MN_H%xDu*n0ImrrWFwyHC$LZSv{uP`$H8K03&4+LrO|lK-RYjlXxMJUUzOqWi(CgUsRKVXtA_ zjOgUqk+Q^SAzy%iK@jBi8xkdi0K~ID+lS-^L6~73(3coWjV2JaB*57@AYe(9xkTZN z;gUT)$y{i;^9ECZf)YoQcu0yM3<{+QFxGSV)MPOQUzEI`@%O_e`5K6ki{etYdJ-TM z;*2K0#2-UvmP|bqDW)S>ja&4r@f$q3$u32Ab{dUSUB|Z%WYr@|umzzS z8QeEhTIEOcJk%^~L;JWA>!g)T<+^(M3`J&BCNvYLYXAONR(5JEH6pX5PP3yhWsM7pwJ6#Sc%<&*+cVb)n|V zh-4;ne&?aZnDT9c#FhGX)TQZ0^OACDKVgbXM=viAc2#xr(0#$lKv*R*bgH0gibqRJ zbzDV+@}yMTVz^!khmDZOJIG@pIE00ecJg$cSRz3KBcQUm)Ka6COO6(qHUb{N6n|&g#oQ7BP0T2A!<>-(?d%YZ0Y)3g*%^dbs`F=VP_01?5WkkRBu3`YSH!tr@T1}2Wn1C6=y;p(WM zWE@W9o>0S$Q{{;k;1YeipWs%ri5L|d|K#7jL8K?~x~|Wy-Mz)(-0;z7` zrq|^&C|BA1fvl{xrB3eEY3+&ZHWU{hzbx~cNWxl5Xx@XQzMs|^32qyeiQk+<6h}x? z_II}EitEth^oI8CsGdy`U+SRBH;ZD-!C)=1mzno+V$iIU%#{_E@PxslwJZbq4VGTz5S8EOsyqc)urqel zLWyG*BFPf<0W+yl>L!t_yn1dTA@k6anYFyaiw{<@{N!+aVi=*V?=k+epF6+(RAd(( z2A|h5E5En3wRQqb>vyVhPme{ilEq*Wj(NvoV4v$%pGgY{aO8Bi*F9@9+vY3G!!EQ9 z12dT;M{Nw-pPfBwCg2DZum@_nB|u?M6tE}Cemk;o2C_C$fvM3wl%!KSf9 zA%G)N){#hEY(p^qk|_q`<4|=5kCv+8YJ(nzps^Vmtng>=7LRFx7yXhJHOCRe!9jzE zcNW7Crh=jKD<4PUHXvs|!gh=#OaH3QTz?@FKFxJVTePUyiG&MusvD@%=~@}t`h^1` x&iYmvvfx#bmpT3`PtF^0k?a@iE%))*1NVySmZizF-M!R86}DbhY`;HF`!D7eFhu|W diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/2.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/2.gif deleted file mode 100644 index 7edbb58a843cec27a1641a5c9b6d30b8fc1f8c26..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3222 zcmeH}Sx{4F97iv?30p`p30s7afI%Y0usQ~*kRTvo39F(M9fDyo)qyIGxZdPOAXfuw zMXOZ@MT%f;N3m|GEf6fID6)v4qTr4|g<*?Gl4b#gPG5ZI?R!4|GvE0w;|8(3`Bs1x z@CE`_yJD2}b|0SX8E<8)R4Qff@v))So3@t97s9rhpC4WH_pkwL!xySPHq{)oZ7p>h zzvrkPIQOBeShx`LV*^5%D6C%`ebEiEl~ zk7CE4B~|Y;QY-4zgO`-;+$Y!56kQ@|0&T3P_~I^%dg!{c*>mvT;;r*BVqy5BGo%N1 z>y$4yj<eSIAsOnz$S)c;g7`UNK{5a%gXzk9w@* zb+!N1Z*Z#q(|tE>A72qE-$~S?mF?$QKjr5tH)lqBI}f!)-Psh@T^p)=9MN)#S6{a5 z)5GBNdp(u?=bL}eIw4v-(&%^nXp+1*wON*U)QfoKAiI@LkEEj?KB(WsGWwPb_Q~x# z%Pj_))}E%~{$aCw?}kb3!SMzc<>;fP!fzD)jmqa~!+lLXRgS8nQwfW3qmScXUR|)( z58qz3wdeK<)!QANf2Y5%2`s^ZidsvxTJ505@&aRHmU1EkJ(zBw0RR9FAJG_700J1A zx8_Jz0AQpRL9k>=GRa;_N?sz#%Zsq5<3pC>LV|oY+spD{Qbe2&7lU`gW43MM#*2ar*Rwx+$e-nGQen7iJ*HH&6s0DE)T16NM@URLM4sVjkz-7 zEVM@ox@)%#;|K;6VBO^yGDT45hL=an%;wJ9`Sg_goSH(sqv#czn<8!~#3sD~%K0_n zM8E1+ZQZBKnoC0ED>;cRViOmBxv=BT@LrSCmTmn8?91ocFUGXRDmGPv$5s+|%)PO4 zu!z}lmB=t-ZS|%1LinMQX;MOwcmS^G?9*u1hBP-+<}$vIIbo+9TL7Q-4AIssuw z=N}TG(+?p~3br$0y?OA2c(7hNM6a9{%@o_D&;*eH}6v}Ak*0_@l)tisouy=(k7zah6uVrZhe;O``p=gyk5s|!3?bZf88ne*I%R2?0u zS@(sfB0s%2$%Th?;siz>TCk?_9ePuuvyJQQP8vMj7X;0X5*K4F3?nP3QSNhuu{urs z84)e)87pS2n6YB!ulU@SnZM$z3t}))Q*A*^DVoWmscAMP6tU3N6pmY^9V;nttf6+O z=$l~2j(DK-Bo4lc`8k zQg{>bzl{g&%nN?YhqNV#O ztd%y!jg0~xk-W}^+K#6lpv-gGpDC^eLab>noeHkN6PT!JRZZ+!1SKWgcK&*DT0tgB zXm^Ef+`*7`+buyz`jvr4Q3^sy@c+#WJ(tOup_y~jhsI<}!D%hkERC;dDT30s^pD^v pEloJ|-EsmUGDRV$ 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 TKb&t*bx4GV=Q(`>7FhdV^sO<; diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/21.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/21.gif deleted file mode 100644 index b98421282467fb377dced2eabd72bcc5525f3e8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5191 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 TguQ+mZP{ha!SUN*Q#T$ZGKvWRLv@}vHJ9z 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 Lls229f${$VzcBA< diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/25.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/25.gif deleted file mode 100644 index 0b4a88322946c1b65e9236657d6f42c71e412a94..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3127 zcmeH}Sy)r~8OBdG60(?tEF?im2r+;L1lbWy5OoM5NLU65Q$b)@h6?I*ijH!^Ie`Ra zC+-{I0$SlgMa2~iD4?}c!BMND2!czsN^wC=U``U8YM-`Oz34^na(Djk_j{LoC12#{ zpTq{(z%U3*yz6*VPh5@91jVmp9hk*h_ue zPJQ3W9I7V2)w{mF$m+;*>u>N~s}C$^0`3@1m;r!i)ctaNxQyEFz(9+eC`^XN3!8BQIW zt(<1eq0t%6P)gK1?i~Ktd>1RgD&R3clgnP50)~j$^r-=)g}=2U`P7FrwO!vqU_*lU zFw_kbR;~X&u~yc;$&E*};A ze5@dpf)h2mKgvz4`5VTT6Y|IUpn?~B`O!Xow+E^_0HQ)fRwZ|q!mi;yyT(Q|dNO5( z(vaIEBo^5_+8bJG6foKk?C;Q)qcmHc(BdBLY_wYC6rS^a^2noz&3GFqSXDV4J%vAC z=ygah&ds5MJuT_7^Jnmlu+);;JL9n6_Cf`txBd`g4RhfCW$xgc}fq5F^bFhU|C@tyaSPrXmiWx_-;j z5{OH5aS8B-y#rjF!nZ?Npn#VKr||^yXmubK7N3GoHlI6xp_vXT&t-${;6-psCed4Z zju{@l@;WGkgg5K1S4V?6;eLXa^J0PgH(&%T2jlBr%DGT{sEszJRRQMz+ZQ1&fFZ;L zTCD{?98kf}EP*W8;ThJXyzh2EtH5btM3@+smE~CvCcpxi0iQZ?p|$PAT1a%k0lb8~ zN*V1XM=G=P7E0aLQrUW{8%L`2wu_dUPcC+qVwegWOwJEdU(ghkP-diGnZMYcPcW7@VbmOIpx>pYmRCzed%2X+OamT;YIX&wUMpf-{_n-e{s zN%$P^C$0a3oe}+cXRJY+JA)~xIrynF;Ke9!5mD7YqETbKiJ6Anb{rbZpvC2^4Zc{! z@Rbq`?@=ki6uJ~mORT8L#Gz4nS%;41Un!I3?CJ-SYA;dAvBLTW)x%B-Lr`6rn?L$k zUQFOV%IqF#gC5}Bdi>;-4rr1qs0)dcpyspYF!zUWfX;B1Pw|1=G5GRA`1$l9>H$VDpJQo!fe^lQ++|HN)tdbJB?X#PIO)x4gJ8!2~2 z#cM>{Dvru&7`$UFnDf{c`}j!Jz`M*RZyV@ z^7Pj#MM@!7tHBCOaFE%PsLDbV6GZ%IZL;I;y%5Uc#Be!-<|=i7Qv73~>`5Pbu))rF z4u;KN_alhm#Gf?TP=UVBjrl==;SVbw#biM?3VSySG~J$pUOaa$xC~86cY`RyE~c(y z;VHb7q8o$qEoz*V&^-!AW>ZrGnNNZrm(c~e^_=&;`>AxV)ar!vH+7{Dj`*x8YjbMB zHIxKdFw=fb%KE~K|CGA|=P)WgdLGg&yjf|cZgHZsr#XXx0-Pulm#|#GXl8gM;4(!x zK_DnH%g;`r(Zn=Kf+dqU&=N`%R>FP2!cLyzQz()2zGiX$kx5}ne_g7o0A|~ha|cB7 zLV~2(5Gkyw#S&tyLY|H|Y{a_6+>X-?Jf!k$DT*zx1Tt9>YjOOZusexEd`ajc0VncO z5C&z(?hjceaQeanUKQm*8~Y?)J-YnWH9d5H%9D_3Gk;f#^_)%f$Z?0hy@IC_R`#iE1Ud98@p~5HAYTDuK4U(zc<#GppqcpSq`GsG$aR6;x2k0_?6-$i z7m=~qrPV9qZVTWbdZ diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/26.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/26.gif deleted file mode 100644 index 45c4fb5563081d684f00cc3560df41b803cf7bbf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3291 zcmeHI`#;p_7awFU=3N(!aa z)@F63%VJeZ7o=9ZQnt0-6xqs9JUi^x?ho7dFZh0*&+GMhp7S~9ywBzRI**T^H`7C4 z2s4C@Ps2a}4)C#HI~NoigHSB6*8!HOC}Tq)*G;fC2OKPj(FGJVaMc0jhEI`juo?%# zaMPRdAVYurYr<3!zjB>V21i&gak{lAP5J_jKOvfu-^l)FrbJJ zYMHdu?mXbW<6M<|Y| zA7M8>`ZC!V2bA`phykRIr;IV+AX^n{3v%H74Duba8K{B=jqE_49XJ^VR%_n&!S)dB z9_rY26KnuO1C-jd*p-SfdSR<_g2Or}K^W7S`c_1>>H(0|FnoE2Dtn+MKt7mk-&j=y~ypsn%lmxoVC zdZ5H|I>KavivdiXQX}mqD?~$B*i#4WNk77aw9K>q-nW-Wl{i>Tyn5Y}zx7_pjuXpm z-amiVI}dkG5I%)vQPqK4LQ?mp&HY5Z8&QJyH1vm&(Xlk* z^NW`zUCN#(D_Jix)u)Q(37JxkRKCK&g@>X)-I7O%@1c zF(Q_FKO=S~L$fN%L^j!T<_9!`=_ON$Aa{zZQ!JH6gXnY$&CQ)or#V6{RGN!3RsGVP zXl^WbI?IIt{r!;DXbNE*E12i~Hba%90aga>y%$4%zw(V#U%Kf!(Zyzdy@QnyeH^V?};EHd*b1A{Gl- z3|Bs#>dBzWidmzAMzk)=-blj~^x{RO9d8z5QeC&FIMMSHmw~Jb(7|_o3gO{5tsf(ZIw0Uw(ej z_tX7*y?1-MyYAe+b+hxv^^R*-ueATz*4pyJGV% z-LO7InXFhRmq{f_iEG6P@o^$yY>Xg!&FZMgi14sgD_1NJ4G9hkTo&N})zT$?zCPZ3 zo)_1Xvv?7E;R2QilR>co;>YZj#w?Q2>&na`qI z;P6A9*UbBTGj5qHeb0NMbcesk>yo7nt>&=64j3%Gu)bZ(E-AD_%hEo&CC|scp>@Z? zB&#mGyRfCTjNaG9(VE+vk+&0#)yRV{sBXxHXUVS)?Mav<;AeZMGt;}7F;7r07;<#B zcYzt6SxCK7!7kZSa~aA~zn0s5Gh?nELQ$(3%P%ybUKFn@4$Lx4U+a6kuT_ag6*8M`RjFL!A)XSUC?DQd$IFpPS^kjr2)m5Fadb!#?~ zU?17hwYm<~GGKB$Q+BxvfZm2h8moZb!vTPlnm{-Fbvs zTiy8VW>&3@PL@xR?~6<-^j{c3F!98{F|xnG&BMSuQmipmE8=;oyT7A{X96tV-m~NL8l~6+F7aUlOIu@M5({Ic8FO>gh^2MGk_!BcJ BI{yFw diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/27.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/27.gif deleted file mode 100644 index 7a4c0131dc926ee932804276038bf053a5cc1634..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4377 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 G^ZyND2?^l< diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/3.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/3.gif deleted file mode 100644 index 86df67b7aad1ac80079562c74945d9c4ced3c397..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4017 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 Z`!_Z%27Br#6>oByc-ZnwM>1&V{{f6`u%rM0 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/30.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/30.gif deleted file mode 100644 index b751f98abcf8173ae3c08402c99ae885a0dfe162..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2555 zcmdUwc~}!?9>)iAFa!`LOhOofIcy-3h(J)HKuAD9Q)EFv5yNtL0Y&A|EuzjFW+oA} z2-c(8b>)!tq&`UN!D20lT8o8>2UW{@U^)6c;!=eLSB{;)cI)=({IdpI$gndSdG1E4g9u7Kk=fnzh!YjXGM{2YZ^|e3#yL(c{iXHsdc2e|HKVee-(s8?PJtL@yqm z7<-&@^N`)c`i$Os+ZP=lO^kds)|K0RK{eJH_wx3}9~zK}A8YPjyV!eP(DUg2m3^@j zLrrh`Pme!8a4yfL?Xd5}>-I}qoV#nWt0kVp{rB3A{{C@CTLX@b|KqQ92dUxCg1_Hh z)Nvl~zZO!HhkTaL>usS1JB|C3pzdo0w@zmC-`zDj*m8agum7_9*yGHnpD3tA|DmqR z(R&MD-H9FUttm_OZa)%qdb6Z<3;eq8Peb?D_4jsleZHzH6CQcA?eH3OWZ=>8!xc~J zcmwU}<9+zp{m8CQ+@D_&{jF{Nz!#Fv#vOwXHVxg9uE=(5_?&s~pu!0~+@|wxwKmbzG-!vpX1ldd&0YOIP&z@U6J3opnDM@EAmTq38 zQ|u|+`oV4jNe^BU=n>$Mu+5E|P%!)O?37?-j)#M<&euWXrnKkRkQ?|Lcrw+JAl;%= zri>Te&_sH=B8%BRvS8gZ**z&MTIlCVxJL5~r~!|i9>is!m|V*9x65}0>t`S+j?Ld0 z-x$+W&KBZQpXH5LTg#o-aAKgQ?hlH%Zqf{O#na+)TfVqf@NHIlXk}{BPz`dO>7L<%|AZ#`LURRFInZ#CTaY__H((0 z25aW3TuE`U5$0wEX!crEj+T*>fj6yhex&JkA!dPZ_8)IWx* zn)vVZKD+ro3ja)s0kI%^h)t97GbW-UU^2O56ozAwW{`#hF{U?&OAQC~A{1qp+8hDd z;@zb_di95;W>y6#dbXEm=$GkV)CPNm(M_M5N5k3ZMk`>*hvL(;19F4G|D=z`KA7+ydek6N*?5kWOio zP>z7qIe6qiq+7u|E21?HKo`VSsn#h86_SPp%9eoSS%qJ-R3J$v1~~BPQ2n_xTP7sf zA`&6O4J3=mQ{bKP9nl%Da0M9+oHJOkaOG2p^~bhAXnzH|u7}yAfU31VW<%+0GqNj? zwN5rAN^h=yk60&xouW7#=Fjd~(GU;_rrld_1VCun9RYkT+uM=kZ*tQFfFK8f#t%{w zcG1opmo*v>!8WdoONu{mEBIa9ryMt6zw*<#%oHJT3R-j}xD*NsS4fxn=K@=&T%rFN zLYd^J6t)uIv|lFf2p{g~bh7&%)rkq@EA}sb%3A>OK>OTkuD}jdtL3b#q zA~*2dRZGap)+AjmP-VejnJn!R>jL0e(8f*&+=LcX$^$bHnlKj56Yw51$dRZuEO~>T zEdxk)g9vvnm$BKAxFQd%ppnZvW{rdq5GRDqQI9;UFj|G+@YjOxE1@E|jT8W& zl0qBdv-a1#yG+-uxtcYX~;Qjsq zEmctoWUMMmilLd5j|hDaNY$7eBje{|I0|s}B@FQZ;gRUc&(G0wq(wyF>`1VJY#0A4 z(k@eS)99YEq2&}tYwMZxXybXsEQHNgF{zRm`@P7Aa{?D=O^GhtEHiLU-04MYs!UTY z@r(7|#!U#1UXO6+I4(3J>6+ErP?tIL933|bR;QcX9YdYXK)W*0tFnp%qJO=_|6>c2 zrZXWXJ>V^~MN7{X6=5<1xsPnST*|`nwXx;z zq4&($hYY~QaeMtr=9D#)MXez#$Pu!mi>{`Nx~>F;5(30Cz=9~E&5VGBPxfi6?ZXU75!+H>X!yX}Zmv>%~_@QnOlG zvt?4TOhegPQE7Dy6 z7vMe!SSLGX`Y25YGRMZoEDv<=e|^OASA)4;@(DFndr5ik(&uFgTm|Ad_ zN7dG;bC$+Hqs~ibd}iw0WbTYu*L>f6Q*3>4)jTA>)o3@`6)`bbwLh8I(~x8tE$*#Z zWWJNOWff}X8h7lRqw35F%Y({O+tE+1tn{wDx;Fv;!dPt4hNx~#^|c&1*!jJwS@f(w z(sXvoOs{L*M(2W)=U;Y{rUq8iKX0@Am}|ZjAFMt(^E2z$p0x1`?t3FJ);}*Cy7%Ju z6Jm4yJEOg6M>kO)^sJn^7Iewfd-tUCE<>Byq+WIKx-QRSXWXLgA&7CqTbfkdy=Gp2 z{o-c^2lKV9&pU~h=N+B9NzaFq%vWN~zr>k`!Y$2Nrqkqy?Tp9$n+*G<#*y2120BMC zBtLsPY5bmleqyFz-?qOex?0ZV9=q8#d5LMYTItqBF`;YXrIOfCe;;3@4FCZ2mngIY z00Lb24MTDP09&g9gi53vX#oK=+D2(fRaHbl5GLEfI~yb16tHs_M2nyZ{YVrFhEDYJ zOQaprU<6u*_kM~_kQ&%j;u?q{kuVsB!#+lBdn#{j2{*+47pBkY&wbVucn)*I3L)Nl zkx|6YyGY=Vjmh#{Snq-MGBFaFFOtzozKEwtz8EJzF|xB1yYyjG&kn-jKIc#PKj!yL z8u~okP}*>twmnh^MHiN%6vpmdRM0=GS(ARrF+iSqS$OJQLnInkoj-oIIxv!MfZj9rxD zJs4}iLS(!}tS16Ch_{yw;xdze^+B)*s4v6{?Vopi({b*L32hN+k~M0SI8M8znzh}G zVL^WYd(c%|#Y2~eO3E1e^rI{EosW)EK0s*p5ROzF7|dk)>c_L&Z813%;RZq*&uy8b zC@AS#o22St@9L;KS8uPTEdU_^C;$yCf`JGWAQgmIt7RVm8GgOwTit%g%ruy zQgFSh8kFr1VGAlt0Zt;(zYfGDQhnUCI0-eSu?|O#2lbU`uWc-9-7=~dJW2bLONVx4 zmy4ke9oZLMXA4G0o_}N5LW?G6TQoOpM|nl%&Z-I~D%*Rm1hsxxu99ERm*r6y1exY= z9y^y;HV+?p2KfV9np~0~gA%q9iKz(?65A@L?30yab1H zvL(6=apdxkw=8jX4*tUyJE~%{H*e;=jSCK58Z*#vw=3;1(up||W4KEWfUREN!o@m4q;jv|o@v$u3w5bt&Jms^ZGx}wOIe3o$uT69T)^E-x5)s=H z=vu-hrow)aPIuQ{=fH*FtqZX?7OcJK^C_&?Lpl7FV6w+MQ&YaMOHZfpXkhtemUmBth#X8Z8v3sGvA{+U1^Ds&IB<^t{+BF`)5L`}FDl8C|trWVv^& z?_IId-jg#rkON)8G3CSOTQt|h%8|B?Bh?yBWDOA)r_H&S*@;C57gY*lkE+}c;seyT z75N<~9Xs>2LwWy7wEIEm@J-%pi5}nfO`o2|!xE*ul4x@^>(lWCiE8Du5;d%bB|@7P zBpQGv%6UT~?t(<74hg3|=06evutbiq0D!Fw?&Iubg47^JSgH=O-_7)a=KBb(7i|#1 z7YQQpzxhUnx0ii_M1IB>sS(GIZ}0$_vetz4TcOmqz6E6=b5%#bLi{>96po(71V_V= z1nPN0kb^e^Bm5GA0ci@>LUVw0au`lildt-RCcGT<;AgbLQ}bF{!931<@~cz)I{E)x zdM+9PAOR=94*rjTc|SpfYKJmNl2TqSNs@%^D$Q7)l!6vRNKp;?ivu;K=;bMeTIG9% PVIGYo?8G3j7+CoagEQ7O>?(uXTGVv{2OmNO}-$!E(`Ck*wdUtF23>Oy)#aEiMyAY z3?u`=l1}R-q4`pqY3(`X!2+b@mHpBSJ#m@JaJkm9_{8$qHR)WlFa#NOsD5`i}lg~zv1$x(I%JfI~zyKtR=50OCJKpDmIVRZOsi$+pM{5f4zglfx&_0*i}EFymyNNmkA9IkK}7yQuvh*A{0<6Q-_B$1rr zr83&!H$M>5o~8b#&}O!0e|H)CbB)oAkgzoQV5p7rrEdMlGRv{&gvmDdqLap=hg&_- z#>3@yv(Ge{FkqsBjN7q!p@UlMvTL{uABmNlXdz7qy^2n3?|Ni6EaY{RGhdh5-{Ec) zUV(mU4jyU??|K?P-ssZ#IJ)s(^jz=3$~0(eCj5ScUdDcv*4wVX?pL2~wCyY*h#YWj z1^C<@YhP9R4GF{N-yZn0&26Za-Fn$P2nEc&3mJZSxUCqRp0?xAZ=?71vPsP~g+E0~1x-mZr09wIW$Hviw~x=`~$-Xkcp>N5O5%q0NH2hig4wS zSOI~KN4cy$N8P*`M}rwSCdAGbY!iu(4CREf_%v{2Xh;|jA4!1Fm~1)=FZ*8EhC{$# zP58kC2yx{Aypof|=CZ(+FiR){fkcC?a4@7L5{*TggDnt96dZwqBT-PK1s;LJBQ3$- z9*8U(m+6Q1B2&NRlC21k06w3Chr=TxB480H7@O-4N8)feIKl#MVF8s{KzT>P__Ro9 z7|-Z?1Tu@q;0AK|f$T8wN< zhOY4XYR%(&vHphfkJdczBODgoi^XFf<}z3^bEEIhvfBOcL@S0eGkAYWr@K+84MHy%0Qz1pmZD#3uVeGfo36SXcQI!`R333|CSCe0|j5v$$#nQ`<6_M zE1!Q&fo$>D9I?V=!^4$LiJWvt<{0jY{XKC@YUD<~qx z)1r`8XKpjCh)fqHYMQ#uO&%KZ=u0(^xsIOFjCa)7MmUO|e|U3H-6vCvc%IkSa86!X zWbe3L`Cm=3{>4#A4yT;89i4WnLpOa)zJyY^3ffrW*K*1~?}Rt{aKA&BC+Z4l)WLKe zU=h%G-hv(v`mLB5`Ej!2W7b6k&Xz#z9C9+*<`Km|+75d8t2^$3&%DXSHJ32%nZ;() zd0b6FdXXp}@~ByNQvgCg*C_bng^rwI{r2LR=a(#`Vct{XojMsmJ)+;ZRI9QfL+K)B zegoI&i*59B(9c0Sr?YtCSQw=+K8hL+TMX))+-;<+k65gY&TJ#rWqmpREV+BgpJ6>a zjuTwAs;Z=>MIVn83^g3Eo|g8!DLi0D?=%$ZNDPX$9m5!;C+S(PGmTq^=`|5<^%G?G zouD^A5I_=VQ2mgl|m zz&}M!o2}WkVPgx2V~t6CM0Q%OuG$)W0vg)w9VoZS<$AYsf4oY|N#|?JKc3;3ou|aF zRG9y`Xs`hj)Ll5$O|LqU2-`=^k8>$8w7^I^a)RILY&okS|F;em03{hIbs4Ekz^vTW zmkMiFNg)*kwkPb*gFH7V_E&-39)aa*-N9NXgESUA>NtayiJJbPd6Qd-=QnP)9^a*H z;+C^fH%(Yvc1|-j3p+5md1OO?XErurnzXP-+shN>7azXXyVJn=&bUX$9wn!XxU1vW zdqxt}46q@+KIX?T&`dMVoxY+u%(!o|?qdJD^UnHf)KrxyHN zx6C7BLRN*ab`^-K42Yr(2o#XK1Rk=t$$+Sy%;|Rr6XQVhX3U|&L*%4I-G$Gu;W4}Y zbNu4DpO8R9%zsl+mPJsLMGyccA;Lp!dyw{I=PCVc8mU;h_jk2pm$ON7+QazmkyfMc z%h$D}-1exZXIR-E*S>{#u8&5 zAY$$n$T=O^=lE+lIU(hQ`gV_9;_R$`qvd)H+gydsSdDpuAz_Xn>tb{^@tRMBt3#$HIgh{RL{mnt3!oiwRwTB@MuXN1V$VCO--UbTdnC!L^xK`*x*7HD zZZgk!!pRvl1(;sxhOD#;&KBkW=O*&$u{qM7C%AT#60h~_m`8oH|b z-ge+M?fv~XFD%XBVRpN5bP23vZGA!LTl>oppXq&d+s+yssvdoN%}QDA31+0H;#%Fr z!D`8ZlJ00h_}NXEkQr-;QMib7wcOs#oRmO`r~5(o^M@V|NBcsG&hS6Z_{*R3CX5X9 z{xp%8lLQES6La_R_(hx|L)5q?$34dE~)6j`o^v%)|5WcMCtBO<9_u4Cf9bMx&8qB*sUkB(Diii1hQ} znV}#E;w)gysStp?P5&lIbO^#5l>k<+-sndp`uS~Kt*)(&C9WgnS$O2R@HP``w6I^S z11}X#a3G*lQ%PI>j<&ck+8sPRydBVV2Jeg7OSMD8EtlpP9CawkC%gAyl1yP$;!WBaBg!+6fOEhRjt zl~ZL;XQmvOCc`Rg#s%!v{#F!ZhJ#Xk`Pp}e>qx;*2(O;wt1-^KZ1Ges%&_#Iy3&q> zt2IvCbQkt&jD~2ps>ogR=+SB-T6~ra{m>c*+hl~#?{D3ru`*-JVv(EE7%Uou=6JMJ zlN?YFrA25-LW{U*WPd7K zo;i(q7?xvL<@-qK=j5ue2+q5yj<2>9v+@%$^E$>$7@M1tEdmGH_Mf=wbXZLmqjEE^^QOzWC`i#KY#e++)+=kcPO-BuB4oA8w%Jew49p?-rFBjqT34 zDemDNb&T=*CM3L7!^UBc>PVsOd-wUQ>1N+d8nn=O>)G7D@xWtP5bnV`=7BjgR=$Zr#n#pOAZ>sK@`Z!^l}E2 zK#@fzX9)nJ)?_IVgaqMm5J}71*U*HRJ8vKmHWVYN#m%j9Er^J4_wo5F1zGE3=N^%0 zr(NF5Ud7)duw3aGAm)bB0W*KaibVIIAP^-=X8GESJ>_8_&~Ca=o8T!cow3IkekYYO znVn!;l#J#k<4PT0A;K)7;c)o2De+$C?Bdt610C6i!>|^?#a*W!I=M0$#Zfs=kZLUC zZToJ#V{a#xPHCJTd^PsBhR&jdg)>jB8&mXX)cb?5xH&vz0a=v^*w^K2@ z5}7a@FLv{#iSj>%y<+1(|5b(LY2kx$9Me z#pMHJarg*=BR7!w_54OMu725~Nrc|q`guKAG$}`lU3O5Z7|(cQQ6@v4P{F0LD(z_^ zOY`M7Og`&ukaSjhx?A!@e!+@FyZXW?knDEPEo~w&(C%@k(@If{eW@FDq7z{nfYgw8 zBD+Iky$h)>OT3jEmp~d(xTwi>am{>OytPnU``fVCkhDn?oXJ%SPo5_G# ze4Ig8>Tn6@8zl(x2Y^S=00K|rAB33r-XB;K9)(dPsKb$4$$UCU<+qV>$Rb}V@{cZv zv@AsP0g$qp;a`05GJ{DETU_fZZIEfLT#Q(T2{T{*(8MS365!a}WM3AbVnBXDLB1X0 zSuUcc&zdR#f#`e6*SnQX7WVNuE&R2_{xGStB&DP{TSGAt=u@9peWVKG?!0leu61qA zZb`#&|D>6Il(#s(?ExnnKN2zGNZ-~qJ%+Oq7%}K2Ky!!)ksx!^EM=yVz`;O-7YC>d zcY>AW)G{}kSPi%tpo~>n$%+wU;Lvihy&H=K(vtD&NPHS7J(w0CDgm}qYdlRIBWi0( z%Alt8H{ujHcuR#%27a&!4!Z;XFp#A<>H9c4P%e^DJz*~aECQ^3F?e-(xtLZD(~|1| z6E8amyB*9>OF?oPpq)y_E656LMMmqCJGiJHYz~GU(P{qDN-{0buTh8OgA8XVGO9`j41zqUnuD!zf%9`|@!m;SF z<^+DU-dMxWqUCzv4{M+c2TUdceQu()ftoX0gcB)19|h>K6@JWr6rnYKZ4)qd4rtd| z>UIML{eYokZxeCCj|HOn3g8WSx%Z6dbCYPbXQ9h~;)Y&-sl#NECh+lY*>RX~>caT* zQ^5SKxu=_^oJ?3vMmI2<)T&oM75l7I=BCd&cKrZUX&WpO;{c+ z2R^U_bMJtD@9CBkz$8aFSNwIl2k1K>oV_F%jTJ6d0q+hziiI?=m4LU-FOs(l_&bFk zqJaJb{dw@Ef!x)RbHL1-g${4wV*Nbdr=!^Cs*fTtNE5BJ^i_vlbO*2Toq*BMmTNmi zpPR>PZ0`p^gcC6{{EQ;1qG-8hwG9spQLj^#hpG>)ypO9qCiSlT@SOm8;pEw?UJ|S0 zg~FLDz@HPHx7@q#99jGHY`Xiha3(v~TS+*2S~wa}%ajv+=}f19zP>-U((C`V%j$KB z&mSk@9XH%p+wJ)GP5{fZ&9Tb7OsU0}7QBRlTX&91*G=V)>$<(w$Hzx{mnYwfmVOnEo-6l*0B;=cpHOXzR9+iCEBp}i zrN?`PZ#PmKT0vJ_ducOYM=uG43KpMNgzEvX@xb8G<&kSEA9CuL(!e{9waJ^yZ<&4Z zsP-&_wc*g!{-F8i*1*_lU?TP|RkHsBrm#q~Ao`x@ zP?|@yi>H6|34ikdq>VMgGLjG(!V00WsffssU`7}r(h5lpVEWMr;_>=23W@k;!aiYz zB(85D)^n1Wp)`c4$u47mGzNpf<4rI)Q#>AHgutRPSQJ|P;*Bvlf+?PW-HrJEAjR22 z1C9~g$qwIhiDy>GAU2ytK%pWcB1|H7nJ_~GQ5bV`^Ys{5tg+a_I4p|6rbZew!t{Sc zAk)J9L+LCwoykC~N2K~O!`W6yaixDj2w_nue+OoSnS29e;?E30MN(NPj0qYQ60(l# zn{^o5o%ZiC{?R(jGm1q+xzoa!;i3LCvAO;aXL0ZTd!ltiaW#bfp>#1R)L=5xKRkrS zU^|hmkm4Pa0D1rcy~|A8#oajcZY&yahQXMT?d(W)4i2VhlKpP8-Q*uJ{>hhYZf9?f zGk37Z;p{OOdyLrKj*PJ*+7Yp)4tP`i4__xn7@NxQr~SxF7w7%%YyV$;38YXOmCX$G zWHN()D8My{$!3NHFkB*93Hl2!nHEYvMGJ5UWriTWb(lc^hYGMn z91)8*HOHELM~=l3$!2Eucn6{#+Q9*h{O%j@|LGb^TnuVm9{(YiA4_5lt`Gkfzj*TZ z@u4xqXC_p9IKUzyAo#kry7J}o^3tD+3-g~o&dttDPfbpYkBxp986J8+IMDyDulMbn zoc(~PFZP5 z@$Fkhg#|ZnT+hFD^~&X+^DgCH%*oEm%(#%AmYR}$J}EIFK8|xP_UxI{G0{!zSbG7{yvetKbRHS} zprKIl8H|Qw4|6-`3vCUMS`T`=hRGQ)$D*xVzCx;F7P_bUL(T;kRW+9Iyb$8KsoK>1YWoHSEvZ~?a249_n#7`7 z2mIt`)GLg>Zg-c2j0U`+fdglGB&l9M?c2C9O5jh~g}U73AgBA*ohUUO9OSI9^%1pI z!E~QqmL#v73sL8ihvZ@C8Ysue$EdOu+pLIFlsFF0YK2z&b|zwcd^?+=cP#a#BpS?a z?^Qakjo{!O7C_~9KEy#&4cs3{q&wbqCAH&QUTnUdp|nM#~@8`u49gSF zN~^2`4+TJ0yqpW|FgoUR|fsXl=YHPFPe%MSc9$Fo7b zM?a+(P-W$mn$EJoUgNq_s9bnK3wL-x+v3RS$UAXa&!iY4GgbjYI+>iJCLu@s-zXqr zniRw+eg>%tYAX|^vtvbjDd=qUx%31Tqss>2Q%6-Jw)Zd3SAIMSipc3t?7S7X=U0eM z5xH$~KR*wG)56tP-a1A}5C!+7caf6htYKO~n&IqYP3 zlxupXpN*FGD4wURCH+G_TQqF07;4^t0?Zq9Wked z;Z3}HgamA-K%;(OLqs&hx+QP;{RObJD0?y+p{T=QbE76njCyH~g?ovh6zP+`B{oT^ z3NfD~VIA$6VBR^LmcJ>En=dH6739V#HX71%OKr5^%;4ZLuWg6oA%~%!MN9X2bqb`} z{1x{p>69P~+=^^H1tA6B(o^De@jhd~T%j$waFq#?wWn5rh=mXA)Z``70*JRbFY444 z^ktwq-~03J$o*CQx+1H^)yL~KKdTF7Lv|inVb&|D;A(a#dbG;iNZj19b=6~{#YWb% zKl|j#v4J`z$vw^4?6_u##98PQ?}xN=_3n}LTXrT&I@XaalF{;64u}+pHIz)fjj)H2 z_Q)&EZ%0##b>xedn(5SQrHWvD+1H=%2Ya8s(x1g2mdTdJNT7l|mL!v;DNdFK1Pw=U ze=MBq>JEx)tYsz4lKl*_cv1`r-~zv-KHu`W!XI}GUr0Wjhz)TE6#jz?Nii2Hpmj7) z#P`F#Ef0L--K`mL_`%dR2uHQ7O8>*i-ptsTClpKelxUU*UHR`y+XY0 zJFqRr`w`NQjB=8;pBN!~YZ#=QkEL6HI?2s0TQrAS1^%vI?q!01N(xGjE7_MAy8$AG l)uAA-tlfHKsB?-$+#F$6_SLH}u0mabl=hK3dejzV@juM^X14$U diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/35.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/35.gif deleted file mode 100644 index a9322643dae616390d8263e8cf1bc4d9fdfa03ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1800 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 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/38.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/38.gif deleted file mode 100644 index 8b1c88a3e8658cde7b25b6e063d23d010f7ed86a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3615 zcmeHIc~ld39-o=q5R!1nAxDM?f(RjrT#0}Q2{9;W1Xl3ang9_}4T&Mv=qe;!f?|nR zi+8-Swp;6Jz1lSiqLiwQXzQ(@Xwia#r2;hxJ3+DAee1q`uYc@6J2UUi%x}Ku@ALV7 zW@?%+fi3k0ynz87P&M7p-d3J?AIn+ z>TyrbxZA#)FnHd}b|u>W(>nV@wWIg2{Ri%ajee)AiT3NMw#(yxJVmhGTlDd~G4_Y= z5BHyP{A_;NmS+1l@b)J-OU)QZ&;A_?Ny9^J*AK^BXb8W5)XV;Tyko#*d$RTF{)il= z`-@AHtviAo&vu@ujdk=Mt;=$CJlopZ;M()G|Mi2uJxxK6kNey{Q`G%!`q0x)zN(Kp zQ61iSlKy!mudgltrIM8&!g3GsE`hxY)Zk z8H>Z7T$npN*g9})?)n^(Y1{0cmZWbE$sI%Y`mITQch|jaBDd`#{n{E(HU;W?uz#T0 zy~85Ca#xzP4>$E%C9mmO;k<$3j8ne+T|&dFVJ+vEC^yOsStfi=#7RV&meNkuZzFWJNQOD=vx| z!-SMH-EY6CJ&5*)saFNpz*UFq+9`vz;+mtSH1H zs$_YwMyib}E*Uo(K_Dy1SIbozxw05`MwI3$muiw|NTsh^P^jL9EiR#tv_sEVDx$Sg zRWy^%aJDpRn33_HO%;l_)+L%u*>Cm!+rTB+%T==IOj(I?sXAYVn2&R&QgQfdnN*`x zXDgM9M|V+Nq|_)&ij*ptpA`p(XGrtq#m#wR zpTdqwWyPej83HCVm6^hh6$<0nf>?G8Q^?@QjQR?c`AZeDV$G;;!Ee5?@AP$&L7_r2 z3uJ2f2eJa8TB(3Xn&!ygT?^}-@!t3ryt|f3@AQpEiivhY`%h4hE+PDJKE5R`^75AY zvSNhqYJ}L}u)}V9_3O~!z{_9ye}2)|`}|o?_fJosbp81FQRl-49qsq;-Mw@B*3BE& zfB62|)wV0v?=D}u_-*SqEf>x=pKG$1O=ti9^;c(3pE`Ns%j3uXcJzxQpa1om48{W zT)XUprJ54;5|y%8v3Sw@@}k0pvV#0Psbs->f1W>Y?ws75*?-E;%A6&hIU^%|`m{9B zRAH)spTgr#Nlr?f%wZ?Q$Hm4>Vlf%f^r*;*5fj40#)pQCqXom%puhnCv3|Zj-ebHx zJ=`f|k{i+0g@DIlF=!No$V2cDnot1ffJmoiIe(%6ei#4=0eISKEDj&r2{4aHn?gwj zajw4k+?sfg0|}BYin!K8uuzmssj!S8#aIGz4XG9ULf+%q`g2pSb7?79okFtGb1QR9*h8c^l8IGmiuNVyF8j;l5v zXX-)M@fmlp33o$GxG*uH*Lg0BJCBmgh2WLt;yv+sHmM7P;`TB<(bNTQn0slDODoe zmZWkkKJyVi3oIL7LuqMht@aMJ`dXp=)5se=#-k}*V~R(RE)(6@TUgsb(j2>Hr0}7u zr^+I9B2ZKbV$1M&yw$AJV{k-G!}NA?1(2_38RX49@8#Dx3)gPLp(+S*KrF!ZHw8k+ z6|TnHTlG|wTS1wx!`wuD&^&qIrKgmyaxHTa^fnnGEV1n9g3sG0r|74cXC>Bm{cO}x zpMF14HPADHnHad$VVq8V(e~X>0}i;!?mrpd$){2(+ne>cHUqD0po(Eac@s6|q+qW2 zT$K-9wSXE719~dwm{knL69Ev7-`AM8Mj|kzs7Rrvs#=$8MSG!njk+dGAVFgxClKL% zhKNR>62s`fVI_pmH<&j1%!l`E$ev9Qah(`p{t!kYCq`yztw-_-d;+DZ!fQfKf)(${ zwXFRJwYw`4ECg%G)N-phvuXwobbSx+7jDsQrm~7k^(
                            • ap0JjxBHsOrGeE$JcnI zS~f>dOrO?3;R1S>G%YaA-DshLASW_Bg;iaN3ViA~G%{(tQpsj_3EzPHvctZ7wVJ0p z8VA&PyJ=%|iAxDKvq@6!#&t8a&Yt+H0(bdSyKfQjY9@LLkzpI+8?}8Mr^YRAS9HwO z-zP>$C?5v!G1yX?*I<)>b44=QWpE=H^tEMacd1K3ix|Kd14*a*!Qqu(t?D7OE}s2@ zZ>&$IR060m?`h2-5z`sJ0FO$Pn7LtH6bLOO&Z$Y;#^i6PPuM2Lhl;X0_61>h7#48Fvq&~;x1xH^TG=L)4O-x0)ws8p{UR{oe9H>DX z5RpTVh+K6!Nc7s>u7@|Eu^#CF+9=ODFarcw);vMmt`SLtD2Sw;B#la1y2MnT=BWp7 z#SxB3%8@yd2ng*5Ay*FwgNFGj01SJ3P_~SlMSCq^d=<1dEXcpm#8p*#h6#7Z&~qQB z*ORB!)zMp|d@x=YnV1{Z+f<#5d7v^zA)BaQ1jLi@Bg`D>m8Y>U{KtQ;n2JQQOlAV6GtZ$><(8|m_pLh)#&W@nXftiFOeo8k;bwh zYmFNO2B!fvySa#r`-*fbJf96sC8o77*KlFC+KXwT&WD(U0L(%YWkk})1Qm(9JBxN%Dn0{oaM#MwsQZeGcL!r z@=RZ4SSn+C_HeuFR~WB)n8x!=Hxq_i1m@2_Fn=L4Kh$3;b2ojp);!%}8j*&ihpn=Ay;5?yG=T9FzeB+iX(a67ZqNgE~Czjq})5=V}5$&$#|pj3eD6J z^sJlmLvQBHCFho0`%~NSPll2n4;6lUW2bpYZ@eCG_q_a8You8(=|3QP)=4*C-}>D- zhNV+?yDH#er`Lma_P3WKOgE4p?(TZp={V6AWPa8@)Z}#FcXKQkb=NDMhwEI2+lnmT zbX=+pogU2YKPtQ4oNl_dw11y?_~fdYiHgV9BJP|F=|561+*&x+CbL*9EQ?*@qO{a# zN%A6oFb~2209enlL;_HNK=d~Xi3$MTqEx8V5o-muwgSQ02z6D}N_Q?jj}Vo&ylA`a z(p_r**!8kVDjj&r*2ns67JMRDN~fhS0`XB>J*ij{|9Dm5=1>wPi0U0hi1((7Dd#sA zs&QDSuE@o`R}!vWccS1_(rg;XIUGNS?wyy958p^5aTr-r1&*?1s$dyE^kCrR$@U~w zspnnW74!3(N{_F?rgs4yrnlbDStuv$@s2A8eQbG|xTd+1gt?%c7BhQ3b@j{8$S4}D z`s2s%FKbkms4&a`bDM0Sv3-|&4oAn_ufb}WuH^+73Tvv=Hlr(JH2>}*6^q!{FaXB! zd*&qdVK+@@UEb$|H0&LnIV)Dfj<8r+)WNDyFP!Uw*eEAmYBsW+)-_4g5S}*|JGV`) zF#!5HUHm{tTPU7D&NaH8&ITbvVz{LmTnfedro?cISS`K4nbt>QzME;l;SyER)t+g| z1OPZigaMc5Af$buh?{&{1nBHUji{*!r@ZgAp!r7r_<))`wa`dcMs)#y|Fr(6F&Cpu zVk<1%{~@eQot`&6F8v!=t&@q)9JoOzJXxJp4BLB=l;Dvjnu=G%p|CV?O)3;swnAS5 z+dFs|c9S(-gkp>b+$$0^?wIKDV2T?tEBe7|NUw+aVjEg7S&vYf#!B9`!qV}T&036` zp0Gn2(ZYNQ3$sR?ItiTrJyrz#b6MW@RZAii}J*cefB#xgu%F9}sT?I}gmohp*ziwiaXMgMxX1D|+QDxH$NMNA76o383TS!-j!@0~J$)GWG1% z>??MpiGmnV-O)|3qof=W*0T(5WNd-)x5Z7W3ZCC?-l%qsFXZIPl{Y1??e1d+GKBIC z(b7nE9D)#1Bz}9ii{HUw+Doo#?HqzRv>HPtY|q@D|9nGd3&cp;`$^!LA*{^VT}I8F zW_ADqIVo2(lPbkv9o&Bx@BYHDxdH#n)B@^uC6=zYllk~Aez^HF(W9dBk9 z0StVin4|;uPCNUtUC!kTw)o$h7)x!_wSCyYzQ8c zgU5elVQm4D%f$5Gl@cXH5h4lP1Ml>LD#<7M3BxjMPC4kA1mW6jp~C zwzn${M8TnjTXO1k&o@2a_s{NYp$l0pBd^yirZPsf4 h={Yi6wb`o84#@w?^8b}p?O*=GIQz7IYo68-e+6CIWJLe~ diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/4.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/4.gif deleted file mode 100644 index d52200c51ee924f0b91132e5cd3737fadcf40ef8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5689 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 E2fD;K%>V!Z diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/42.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/42.gif deleted file mode 100644 index 0eb1434b4e81d4437098efe06cb4e1ab44a86211..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5305 zcmeH~Ygkj~0mo0^kOXo&KnQ_Au3TbK#w}bT)dT{>Ajri^K(Gmy8kCK&isJR;LP$U^ zkqSk0YrG-a+6lUjwbVgCMJo$M$H`}j>#dkk(v3$GV{6*}BFogLpYc0=u zKR>~-Jn6LD+if0BwA`ZyF>EB(yK615x?nd;V zkF(F}WncgC7d>^znVFf&rS|QWQ8Qz^F6|@k@jx{eP(~{%ERT7eL*BjtR{s)r*-F7F|Ic4F_%#>Q{@-nzWU<6+;@FF#!;2?VbE)@$TkUDu(F{Rab{ zj>xqV_J=Cp+vnDtP{#JY{`!;Ax~JbheE7xI8*MRH58y{m2Yl5|ynp}x-^TY0o{Y7O z@9L}%KkQ4|>W6s#dHUGze0%DNmS_z<3TiIsq`S*!pdSL;?WRoB~#w?QxscUMI-QzHu z9RfFt7+c({YgNI?1e!k?L%@)Wi~Y9-|K_~_X=(u>Fwl!okSfiLI;q|k#b6fXMPxfP zWJlzIZvIi*)S+(cq(Ugdb9;klgiuHX@S!SSF~^MzqM#h=W@^q~z*dhkUw9+OgYF|l zIPaA}t+)ArkBpaJ*8a`aY9@;pDSq6|cL+%OV6|KxQ;CLH8}y+j3Ao&wqLWFx(l7^b zTw*OGHLcQnvRA5jgK3vVNL2ozGS^-|G%>1RdgzeyZW_SSbJUk z$B+c*`WQ{YtbMo?Ej#6G+>fiF zQ;MG5NExrIbjNwF3^L}Pt0P@?SS)QTh?#Qt1NZSDuzM0)jI5Y8*!MmCc6h1zE&wRY zpP`}YlvRH^dzkmX!17J|9@ctZ@Na^XK`FG;Mr$WTT>pYrZsN`eltY7)r(I(1OIjfU zVPwSih6qnc5VAn)mvSg4+)67v$MnnM1zbT0s)XDM#-gzVJ3X*x^kVb!(5h-+)Ra`S z81<{5NWYfz6cjyvh`qk68x3=fLE?+`2rqAJf-dN>zYs_CFE}%D(WeJZELII2s6Ve& z24K&ylRkb@g`gF-pg*}OI$WuxsqC7e8)W&N5YuCC z#<-Ez`fb`JjnO-Te5gsr*Ptkjj>1h_y+0{sITre1O-z%v1Oa|)C{r5VG2lbiRhwK# z`Q_ns#nA9rXDSLn`{)uBT?xEHc^HXSJn4nYkQoasGLXv((^cs~US0(6jGXYmhVYyWZ>ks7XK-x`2II^ZVXSyC zBEIvzqw%ne#>6ujDOaiyZ`*&?^a~*7iR?Lq^G4Nv`}{6;Byclf2ubG?#IYF7t*qrF300 zAW&(@H;!-P^HG9<09?GWo4=+uIVztMe&uTU^++%IKY=p8|fRqn49 zmG`|BdlYkxv)FQ^aVnvz{PLEL>eRmzdGk6 zNVYb~_q{JtiwFpzjP9{&V`vpjOZfla(xZ(XpOgf7bio~uqS|J)(Qa;O5=Ojt#Ftu^}7U&!WricKDW0ccoQSQQT;IoEgc;-VL~uu zB2OCf!=|uBQ-s<8_D!HOeLZqi8XYV~lqbw^iYkT+q}J~HE%3VjdZO(C7wKd zj&>nYT(nOxv(Dc=P#~x9l~o=uIj5)#OK(Y1 zb{|}=4ZwzM$d?~gqwrMW%IBvG22~Eus-hvXk8#C{f5?AkBHxgXQ9zuy9TSgHRkc*% zBl>`W&$>>h=%4=62(nAKUhOGAbt8mv- %FKWjtVdL1P%I)BVn;-eLqw9kid`E}a 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 Sh@V0@dM8BG^xew?0{#K$QUnA5 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/44.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/44.gif deleted file mode 100644 index ad44497691d150ea5d02a900231e48ff519d9616..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4126 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 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/45.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/45.gif deleted file mode 100644 index 6837fcaf214a394d8efb68f5d48c9ec6f9ea1fa3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3417 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 Be_#Lr diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/47.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/47.gif deleted file mode 100644 index 58a083611d7c1afd95d136e3a7fa798c86d0c2ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2333 zcmeH|YfMuI7>2)d+R_WymLAH@(krc}g@UaIXysZc6v|DCFw{lML_tx9cp184*`ZL1 z8relh&=?dGG3o?08na|UL^p_06A@IL<1U+y4ZKZ27)xB1?B{;%hyT9c&-c9VYf4Gd z>GQq88%FK$%pZF7=(9wa`2rr;b`38_u1Ni#YoJ?-PQ<{Q1Mt)dw;~qzlI6dI!E6&; zR4S&=!}MYJULot>=bAnPrxl7WG3{Y~-ZMS?R7Fmx;JV!ZrqlUU4ZS8>Z=`Gh;F>w* zWhsn$!lPWuh!*)(43jHi(gHKv;NC*y$D;Kw)BTS}1Ph!lJ4eqYW z{g%g>PJ`Dq@YVr0ZM$bS!gWJbUl8S%5Sg+-e-LyD{YIE@A&eMd!^;HdTx;!1^10x_ zc$`oDtrVHP22a+a6LRQY#Ggupb_~Y&@Tv?ZN#um07ao2`LhsAe+>VK!o12r&xo0FU z&rUEbOVoxerXTCRc;d(gnBusp#@^!YJb!2 zEjv?U4%vf|HLNuvF}0Gq+TAmiuS;9EgNm>?9F_(VG~2`EI{r7h$iiJ^X3FI&h0z%4 zL6hltEXxP6ib9p1!Xj|?EmBaZ#MNqCo0Ah8sZwch=Bm7K5>qgR3O1d7XW6dOArs4w zeTi$Z#&Hh_i;mYzcq1Kd6%cVmEO9zGLXsFOmM(H|d63aejf+oa1m%s#@d~JB5|f|p zkhEvl9ORZ>`lH{%a6?t;-40NlJkhCOSOwY!SO8(U=fBerAgKw)j~WY_$x-8%lobMT zW7F7yst~s7Xu+w;z)Ft$W}2Y_4NP#ueD06(iH`OLp_|x4(cOjy1niZi9*xp*|H8+7 zhYy*DhrPq+6`BzeOuFpBOEN^>#J7Aurs3C{ZP@)Gp7QeZ;u1*0eVkjWV_tTGL5lLsZ%QmVr#~iiiTQ&bn%& zAUN6hdnd%DpD^<88eN#Qi{-iWM!ilP=s2j$lAgWD8yu=<+sn3hwix!OON`05TM$!!`a0qYQ+D0Gm zjNQ!D;g+hwM9lVZCZ`~Ozsn=@Xkban)%L+;Zpe$0I!N|e`gP{GrlKDW&>WlF*Kz-^fm&{KNpQTa;MH3VbMTSO)Iy`7$cc!}$F;)1yn)K77`oAz1q&dbPwMcqZS4-Gw#0WxD0%0Pa38b|9mayJf#kALK}E#J$BBuS_BN>|>~!Pl rL2H#EiEFFJCp(ZsP5Wj&2CVH=rzDGc@3T0Qspp*aTJ3^`42b*_XAT7W diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/48.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/48.gif deleted file mode 100644 index 7ffd1613b5fa36c3ffa7daca94e7e8cd6f8d82ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2689 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 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/5.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/5.gif deleted file mode 100644 index 4e8b09f15101f3e3fad0777ad068fb559ed483a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4567 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 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/51.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/51.gif deleted file mode 100644 index ad3f4d3a8158106dbfa48e521084e6c56fc6406f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2785 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 Y?y9hKVE|Dl+bifDKf^#>4e-@}0Qq7Ywg3PC diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/52.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/52.gif deleted file mode 100644 index 39f8a22846945358446ed010e2b9bd50dfcc7a25..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 777 zcmV+k1NQt!Nk%w1VHN-u0Oo%H_RysE&7t_xrK?&j)|+hq+_3!Ft?IFT)0AV!c0$aC zRqD8h_|TsJ>&E)ltKOw@>9vIN%AU!BNyvIc?7@=%;kM9?T>taZ_{^H%oM+RGRsZhF z`r5JEo^R2GQ{9+i_}Q%gdgjaz^&bp0Z&w@W+~| zS1ZnjO~rUYx^+wGxrybje(A1!?Z1)y)1|L4Q~-nP||Tg`+@%Y8|vQYP4yVcL>g zvt~NObU**!w6tnI+^U8B*sH*IM&_z|#eGZp)T8>;r>$c?$Bk&qfJV7zHKbH2=(mZ+ zgI36gSAsHn*{k%yj=+0P^2nRuqi?otLDrynz;{Fc`{2HH zLjBdIzja5VP9(HtHTc)8{no1Ese0nAeZ78I+ml?_ms$MWwEzGAA^8LW004ggEC2ui z02Tli000O7fPaF6gnvseg^7xP76J~4i-a$bjEyHm@r9@V1n%lQKHaE#3h9gAw5QHw^!C@58A-z#?=7-ZCbD#S>_nhy%@3*|?JLj$r zU5vC!qK3OKOyIjL&=f_HLf;KT*4p zQZHIL*>mDv-L`YvVqf%rGdps+K56x(eBtbHo$;}uzd}0JS}|NHxm~Bf|9!#3hMa)| zDaI$A1BX-3rLP^W*F9<~ynSN(aJBl!)R389s$bvw?#gaq-51dF?#kK0W4(oOk6Vjd zl)UkdlJ?B7ryW&o`i)(Mab3EYQ(Gg(4dpMdA02BcGLHN()!#I5aO>55Th64cdC-(| zwOC--@u~4nqj9|JV(vQQqt;8=(I;hVCN5SESIegd&yKZyJy4;Xxn48%Yi)PVrrDum zwVPMYj&|Ov(T&s>bmqnO6vK~ON+vEGtV;-P&x!A?*#7eJ{->>_51Vs-Z`$|ZOwr`k zQzuiRjZ=f?cYHSW^ZuKa>Y;{;!RoB3YgL!?HW>SkyuMb`y;nRv)bQ$7qwz+=!{*|X zim<)|Dg70x&o7rxc9a*g78|FA2CFj9?@E{%ta~+Ff2TU_Zf%CqXmm4LNAO~zIqXOt znLsk12LJ$KS|1(>as_Gu^7RkYC- zP{Pp}5i!DyWFb?83tR>IYgihoLJF$|phhZ@saTo-oIoUxhgrzjWG3RkHxPAl0FG^1 z08KGDawQB>34Xpp5(I%X8UdnEX*9?OB$FUAk%YW7Ux>n@(pY3V`0l|W(UhVstSB!3 zT`Xi4fJ;=X6)Yk#EiH|Z=0}h#6NnI#$u#*OlYJ3{uPR-p7HE8BD*T)WF02wN#R|1p zE(1*-1@ZC}bpQ^@^lb@JMR@po$1)Y+O+f^qTuRgk6hw$XB1)yEy568w>L~a>X?zf^ zib+?%#3)!LPf-eC1dg90Bij9WAQKSDhP75HMm9wt;mU<6Qdp)A-l=L?+7Ba#f;S0dk^gpjWs+ zD3+NF-lh$DTQ3(@ic?_`Un!S@Zxm*UKac^%j|uTeTr!FOzbb#r75zV|5s_qwruO)+ zc9}CFJ!l%fZ+>L*{`kN$I5A-hEE2{GHgEc3W88+%KU=@WKC$uYCez431$Zct_tv9$zn3-G%Cf943UTgU!N7ry}dk_dAQ?oZlLSO zE`RyRd8yM9$Hfkd?Coq9E|_m)ZH2{HqEQy+X2=!eHf@1*0JMM)a@!!k0Y?C^G-hda zIt)gi?Vp>kx0Ypw>SM!KI2GiF%B@^;w6Q!MswCgqRYTBm(HyWU*Wbpa`euwQ`( z?ld}ph9XzSBFsm1-tb@LJnV#;e?cw?yRuZ+b(fAQtFN7aB`_E zNo`e`D+i->_KEXu((}=12xIHxlF_CMVxWVt_~h+fx(#$2+s{26mvxzO&0IWFah{&+ zHZ~Ycu#012!K9HY_Ixv&V3Zp+BG}70G0sXSEHbzCdVyK*#_hCN*q4 S8f7`(nZXDyt@tenSosGvnoLjt diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/54.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/54.gif deleted file mode 100644 index e289d929b9552beb7be70329b7cbefb1d0618008..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2196 zcmbW2X;@QN8i2zdHUU9)$4j6T6|#|pkg|m=0&O4yDyY*Ek}CwrViIH#8X#;!fP&G% z;({n0L5fgC!J;fx7EuSJ6skCc5iO!DMeEQ(dwT=o^oP?QbD#S>_nhy1>wCU)?zUhi z*_&gHutq$QBVOLB89$TJt%#ne&wlbv@m#0sX>;C<%y8&wJ2chSpS2xY=pHNs@2L{U zzf2e|2=B-Ug`Qu7rmsG0DeB4I(UlVN=EvrdNtcv+MjPfjj@?zpydF6ZJ!*j_uRN|hID75rRAc^~Lwn{g zW4=?uQ?iy3^hE$T7wu+`$(t{dFyU>5G{}eRaK6)a#zgz&_Klf^|wk3%H z&0HOBIJ`7;daF>sZ5x-zo0fVGFF$U1Gu=AVrh0z$2sD4~a)OV#K1W@jyZBwz z-Lm+*M}&*lmC*QwpW4d1vUbi~DTmaT=Gx1kpKnamruP=@8z_ib8me0!se>ji&30Fg zoe*`)7_)6(K(ig==j2ljiifoahK@-F%E0cd2nd3lAmdO*WCV@MX5i6S9W4X`0gIwo zY=F*@ap13yf2x?nO$22?EEvZZ`l9B)?LYy1o-b+_k%eW6X<$4*C|v?Zq=!aw(-XPg zJe0p5;FC&86^I3(j02T32z@IoX&h33!eF+;$<>1 z1%pXRNkON0qD7K849?rzTjK+d_kcA#q-jDKC)GnJbzbv82c=vIUo7K`gn-5)Csvd! z^F_g#u9hGWvsmvO3#I6lg3w%%0F%lQV{m9JMj+7CwW2MRg@gZ1lKn6Y#&mc2AaX1Dp(3{9)lDz3eZvu{qr4iO_ zgN0HVN5}=&;_~6RZ*6gZYD=L>K#oi#i4=*F);fS4FOrF*@ggxmiy#4REDo11)Ce|f zHfXh8Iw;{E0C`M_NC2!5rtsgB0fFF+V_@lcEc1U=zG}<+f2d*LWH6fc_(Qv_iQpd8 z4Bs_BJb8C~Kp}i)B=F(Tf_{7Rdig)UF8%w}FE3v#{=6_hH~akA%+u+go;;p<^shdJ$t6+boHr|CyrNrd93npM~|ouSCoHIR$8JgE;>|Lke`>U$jQ!< zf1a6fFg-0bE+QwwiX@S%Le?MQJk0{<`FA|a9iN|3vXb<S)7PjMJ~WhE@nU!X3VC;NO5X0$~7U$#WEPGlS39 z&90mn}`MmRFg6x+I1XVw*+WNk9Lpx7AVlVoRR zbl_uKZEe*S8+U9{^bUPHJ6~TLa|I(L+0-GKhP1$7kZ3BEKoAbewLt`SI}(WroEI3Q zo$Y_w5SintW9>snreds-dlwkSI?lK0XZs3zx=T0GT$-wEwTkTQcV=W&It3Z6w~dP` zoT66TEY*Esb*=%Rv5mBy8mBAyUEL)P^dDMdnw)wqwD`LHh-|LX&=L{rR$^hGpJiz2 z_j-XH$}HWa|I!vacypk@EJbX-fUODC!zvP{rqxr(LWCAUKi7hm6Og6P3vF+v1_?^7 zw}z|6I;+EU%uPes|4rGyebcC2z;H-TQS)rxf zYik)q%Pq8U)-^#`x@Ig*P99e}`hRa8Q1ex>%_cvw8c=iSc}6k%BZGrohK^QRp4uiz z=X~94glXULAg*F?x2eZYmpXBPmLA}i71`NzR&?5atL_KU%{2`5t*G7P>yO>c5g+{y DWiE05 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/55.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/55.gif deleted file mode 100644 index 4351083ac8e0e65a64ff362cbd480f2c86eab4fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1971 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 O9M diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/57.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/57.gif deleted file mode 100644 index 0bf130f0d930a1fb72ca83265bb504304cb08090..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2705 zcmd_rYc$(=8o=?tHVAr&EryxV4b`qo$MkfjMYWnBM5zY7pcssCsY_gop*9h>q^2$n z;+mvEw{eNVL1;+QkRTYPTe3ZES{2fRy0p}&{$}>gp54`bwS715es7*PpYwd5pR
                              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 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/6.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/6.gif deleted file mode 100644 index f7715bf52817bc577c0d33cd0cbd17da898848a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2213 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 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/61.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/61.gif deleted file mode 100644 index f092d7e351cb195eaf707dbec74d32ced42f432f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2495 zcmZvddpwls0>@{J%gYR7j4+up;~ps-g^~<|amh}yl}_7Y+vT7Wvfa*3b5mn-Xw(QEPFk@m^%H;^Pm=R@3$tBn3-FJp|Pv^7m^UwSD_xb+5kGGGPlXIvZOb_;w z4hu>WRu9bO^{zf1oIGFNTQT^7Th-I``h94IsJwfkq%pUy5n8e4q73P$oDwNA;h+TRVnUA`_FJACO6c)M++_wCByGB~^fmi{J_E`ZV%ux@x^UqeupTcd6~3D0Ton_H_0dMVc-Ceds;7_7Op3fM?JF4-(bWew!@<4uipnOUf!5Fgk22^bcK<9t@@i zGUzOJ!o^FRL@r%h`{;L9cxhLT+S;;hHGHjda`bQ9$hGqE`;ukr>qwwg1iB)Ba1E>= zIQo{*H$+bQXPwkpP7f2#7?1(FWFz!_ND+*?I0CmU!Y%?{_}D zgB9YeWcn`vZu)Kp4uqR3Ift;0s3_^+y^owVpxk|gF^N>x?KB?ea#FcF4ONmD~V zOSFv{O=Ol(xcPUxJUjIaHyf_N$Ui51Du&lY#~(285j^#0 z+p)y$5wMc&90YA8OG+(0$;KU54((qFY0GR#-E>RB_@<5BWT5+m-*`@lH`jD>3>hhz zO~73TLx7mVd9In)PVrDkF?$jV7g=gyLt50aTFVsNwqKcC>~5umE*o)@KCH9I?^-I1 zneX=3MJU0PVLC93;v#%wA)ts0iChFHIM&yQOGI(gh+HEG+aj=;={M8#GNt0Ik;)Iwz)ZYnw*K#u=Ajy&HMWM(0U$r z8WcwtvX<6=aIbLZ?X}1*j+C92WHcJL^@OhOiBq^avgOX`vt{m75!@Q6lt`x;`D%um z?Jn0NMjJ)kEy>0Fh*CkaD%CyCN!$K7PU~y;^Q(&xo3w3TlqNDEHdnE60n`H)%qPm< zipFzoO~l+H3u8)cb!gM39T?sXK*x=f9A)oD8L(0jeU7z{R|c?*%fVLe>6YAlQ!cOi zD<#NKxt}PxpPyiX%)1Dg$8`<72${F8-8KH2c1C;@iq9t!`EpKj;qLyZ5UzYpw)%!O z*%YSPZ0>k$J(D9)C5odx@fG2tVqgz{w$-kxU{cj& zQ`HSX+q^LqYmT2w6K16$uolXvd78?9fsqdv4jq^pfTBc1g@vvj=GIqKdz z>}2-8ad;CGJZ?`4i9pK^M8;a*G;+zN5lBHrIj+bG*TAx%sI?v6t5pDvGO9(PYHNwa z+K)gxyA(j%)_@KTe*$#s%{tI@xp^zAa-P0oCN(TEbFaCMl|SI##?#UGbFB8zSkvTV zjm{^`NJxel)l|G4qskPctFUi2#n9TR60Z&Clq&4QMUFn{ETAVB8$^~0ZmLoXA^Ubj zLiQEzqAf%A-9GlPRI$uTx_Mb%Q!(?Is=w-kvOI#N_TQnIhg!$-^3&(&W4wIWDJ*=n zD>5SH_I#u^`C373Y>nE|@)|V_fY&IcAkhG}#wm=P!cdCyN*22z zDC{HyrbKL8n1Bb&E>X^f6c)Fp6N*t=3SeBV&1Ae2C8p%%Rb_kbbSG1!s$q=Y{1YZr zBE}%dY#mbQiz^%}>TvCk?!9erOiccHgSq00G{hJ8OKsB&D?W|QM@i-wbUNU@UEhku z(%0Ya4RFKvAzk(Msa{jvr{{{?7f$y@X3%k4b#LjO!qIY(zCJ~CV>M)K&2~J2p6kP9 zd8t(**0*4*=}hVpw~ zk>4iKC;9E}`7^(Cw7Eno`6R#7|DRt=YQ#S*Joc_vr63V;(D;a;NlNliR7Kb&hNt4? zZ&a6}DrHbrO4^{Rl(}$cpsH*=IpmK)Kvi+D0P^xn16W1s6NxyeDm*OpGcqqGyy?>J tNMrII%;*&@oa8uz=YCKFxNClV+=*Obvw`TNkx8belN0|*V!~j%{{ZDj7zF?T diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/62.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/62.gif deleted file mode 100644 index 7fe49840bf69219fa40585741f901fa0b187c044..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2017 zcmb7E2~<-@6b%XriWPA~E&7S5U?CeMKrqS@kf@<3s92X0ldnl3i^)eK*p}kPCV~ix zfJKFXfD#rh3MxeF%Bm~@$`%k=RFE|W0{x-ja#}p6bLO0xdGqdl@7;N4Hc}idt!Rr7 zix6#oh~B}G&K^Ze*N58H!N&G6xk4GARi+#rdr?2s-mN$Zt8|D2&!)bX9 z@fj60tpjNVjWOA^RZV?0ErU@hrAfEy&WTE&RlgllC~rT09U&^daj!XAEKSO4Z0OE?(wdM}k@xJCRMvO;(u1r*Sz~*@ zq`Y0$DZiRi^Q5v@Qr1~s|L**?@+fgtLCM?PXKk_BwY9CiaoN&K;!4HHXkmFrbBA21 z9KBQYI=!&*?6v1`Er`#C!PsnP2RB!HTNei$3Nu{|zJg8eR2P6ugJ|%&ZiA3VqkDo7 zupd0g;*gNtdH0b3i$Ox}#8WX;o;}E9Ir;KIS6^p0y00hQih}inbI*>EI=Tju;zFI0c!%_ zFjyQK15bh})|`kZ5OEg3#6ZH)_>2R@ZDhxZSn!F2WI_;+h(`PP_@I2uP+a~&G}g+> zO2vW0nZh2Xf+HM=CN$*;R!%aIK>?l5;z2Af2T(E6_H(@<5)#hzpAy)-kF*>CYP=j2 zoy$fGX*@I*g;A9>=}4u1-IdM$=q-S@fuHjIPhx@F5gv%%1`4>|d^!lbuT+KN5$*XP z4dU|MxLmJE6^PHtOFLFmUsf*4rhUJu(PwYFgL?aV#!>(Hyh+YlUT+lEN)7ysu|ckI5HXJ zvkrp{M?RMgj2BI0O_>YMaZ0`kEMw|iFjHdDa58As(|-2UlP0)-RNIe@3m-nVKFERl zoewv*+SsUaWLWV*J~TMc-`D%Tr~BR8H(i|_?XTNjwYJEbn;IMH|EjC4kyck#R=j*s zURGLCT=e|e($a^f-#b&cY~Dn1+UV#&wzspj*|46p z&YEatX+gl7o8hn+G|JTEyS2tfYgVr^T!}OQRxH>5cG=P;dW#n=TrgjEp3dBF=4j8J zrKLG@hKBm|Y4G=8@IhT`0m2VqqWVNspEzRXh`(RJvEwIBo(c>K4hiuvHMQOtdR#}q zFwx(=H_}f>UlZqsTW+Eky2fa^dRm$zKn^rB_L`5MHH*J~PM-F`%<2aO_;S@38RMvJ~yY(nXQh9H$#C+X_N6J7*$<3$?X(0mkzJForwl@3YZR zD(7ypEO`2UwUg#jKaV}(l2@CjA#_$wOK5tyC3Nl~OJ>c>w!&a-TDZC%g`ap*7qR1L z3eZjo)z+#wr(=^XLRhaYF-#~^4@uA#A)`uxOotZCF_r@COs07jYnjoR41IHx^3z(23>`O(`)4x0N+N9Ug7`A4=;!*$FD3vz)I&(EtPkek$P3WH+wR>*i|S;@u67A}zhS~gjRlsT&q z>2ep_vPiupx+%s62_mZ6VYfJn&1J1cwzHwYdCiDZL26Es7v)%gW`st7wp5Hko~cZ8 fzaAzQ7Zd=~XY>c^Z;pPWn-TRQb#LAp9fbAYHD_Zj diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/63.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/63.gif deleted file mode 100644 index cf8e23e5b2e83bf4f383cd994510a7a04a74f57c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5871 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 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/64.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/64.gif deleted file mode 100644 index a7797198af0f3bb98361b1b8737784d0a8c2cba0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6448 zcmeI0X;f3^zQ%VZ2qdtR5HK<(pvXKbhCxV3m=zf!f?x{)6ev;=6!c&-hlDYVMnwrh zCQB<$tpmCO0>%+g%dwu`78EU>qh8`v=&|+eB;Z|kxNF_D?uUNxTfXhQ|KIz(&-45v zqQa^E85V#A@Q4Ep^)_U;-@4IJ@bCifP6SGv{B%g5xl#Y*T;Z!L zqObj2@7&ki@7;Xld^9aSk-!;iz|#S zCkN0JLq5dv1iM+)?(Km_F7d^u%3S)6b>#&R2d;hp@NCJKJ6CAbRsGC0X=!PX zYfE}Eyc09GJsPRijPTcy4C0+B>;Rv;wSvMm#0gdFgKIr6C)y5df*Wt_h)UghjAof@ zj1Z>GUfHsyz|)ahe+Pwri8MIc7b_DI#w1n2JU zD%m~Jx_)k;r)s;Tz99c}o01Y&qbyo|Dc^U`#)OLvsV?aUryf0j`}Qs6EhaXMmB^sS zh52}RAz%OiQ09?F#sCL!gMLGhEC9gpEtg|v5f&82=J2CH3o{N86or8#Gq5Vm0%Vi+ z9RSVfDKv%!X+`BeI*nir()S$)@)3!MEOG}556?0r*kr-2Q7MeFOw%-~sW&!1kLqTc zALyQElLODowe<*abqy%Oy06=^C7b!sAK?@e^NEd-83Sdss!rSpz>8dC?zObtr&nE! zB84{ve50UOn^^herz_}0=fo8`-`Y2n<7(Zk<%%jFH0VZK?C_y=gg=cCGXnJ4M%`LQHI+82~b z10iU4^-xU25Tna5sM13^zx{#OXwPdxT;afKv1{^iTOc`IrC9cvA>dw?}RWcqqqD+K4#&A?&ValUM$|HgW$A)9ne@XAR@XboU)(q{-@7Mg`z& z9oiVF;p5BVyC!lT3}34vz?5G2D^s<6O!TQ_8&?I$$Jjgd_t6#o2bZ8NoY2TW=A*@v z!sc*DBrwH{vp^#R1O*nLS(KbECk5(xz~!KpQ19n*K+nR);(bDT7M8yuq=&IgPYCO- zN5lYy&@BLd3Y!0SQIcD3k+{Mzvfk-X4lXyL!(f$PzPgVGYmM)S?Xb_TxNhw&cw;gp zQ!&0sJsZ$6v3A{HuHd^lvw}2u$>Rxp%1f@Hqc=v3WzGBq0_ICfGkEnVnv^Ft zwz@7Y1cYAf5t&AMExsMV6P`;{oz(|dgM}MATky)0fu+x9c5-JQZMm`3dGZJjw>_N> zZX&$#4!DyhrFy|>jgfUcF-FqsBj0qNzwd!>Br{`h2xf>x6W^SLOYy)cms**P`TO9e5VS@ent?zB z+e(%)CMcQ5?V3E+kOtd$hD!pHddDH9K#?6XUhY+>nhI5RW97|fCOiE91&__g$)Al#`60OA zGHx7wr~!lakl^a3L?)KS=)0skC)^(s`XHXaym&tN&IjN5;5+}D?-1UPY+Jb;zCb7v zmrKM%lC+uxg4GfznAO#bwFV*=YYpSDNITLaLQ5!M9TmV=Sy}Z7%Hr34#rO0>o_Dyg z@_g(Xzqlcn%c`rv=Q*LF8KahF8%8-B|2}%}Zqh%#!fy_{%jfA{)ZcvjfeQ^*G{YU43Vy}LNqW8`r z{p~S?L18G}Ky_(W2!&#rZnC-@D}-#lN%-zaSF`f5LxRO~iJ%xKwp~K# zgmVR+A`cJm2vInc`~;>jE6)~O0A!vQ=&=T&ZEb@Qp`p8(XKGs$TU%1IO({!OT6s^!+1Cfbs z+D!VGQo7VPTT%+N^SQ>WJ&nHs#`&YxE*?H3)cXPh8@S&`)Z7x`K&wL$+ZrfbR$=0_ zk~N2mio9Zi=8z>aS;Wv1FVDx_aT%FM$RP%6o#qqS;gT+2kGr!|nR(-M^DH%&M;@vo zZcm^#5juNiPC~4cH~B#>6c3Z&)C+N<(9JACR&V zn>I2o)GXT&+XW&FsLYiWu|n#^)?<1m5Rs$sh>+U429#EbH{-rNF1W#UM*K?FFkOja zODn&uyDDyNxwq+=$vFYd+;wB$oGu-g8$eu=kJ}@WoBPXPw=)IYb*nw|xH)wc1{yhb zB>v>YB?F=xGQWRphme=JbotfzLi(x^yjOT`_pD~{rU}|EI0vtpR=1F#S|wEuI@y@J z9QueX%LtX$GndG;%!G~jZF}eXrrK+G#?k4jNmAEP6;5V{!4o=9;Lzq+bvM}o&&T;D zsG>B<140*K97C2ty8;i9lJ`jv4yp%)jYr?~?07h8=x>a3ibTHBX8UM2^@a1R0p}&S zw8)jOqh3OlE2~d=zQVje{8#M8;tcBH$JXbF^OxFVY!QS0E}=L>*k!<+T4=0qW7yw` z1EsBFT4GXtRc7lGKbus?mM)aDs77tzKiJf0wwU;py1?Jv)d)cM{eOD$d-RMJd-CGL z$*2jEkpPIFM~F~N(7rgWZSAou=Zdm!g3-;kkyJ)@L~qJz8hTE^6go%uB<)UDMUcER zy#wAjw*mV+d<;n~lVd6Y#>O?N_%@d;Y{|NI;Q0Rb%he5*T)Tl3M88!iqDQ9lnGYA`^xWfzMwM5&c{hUU+8C(;e7F8gGW<^*I@KEYQemKRd0aA*UpIwxN-IL(Clb#WW)U!aU} zYcC~FcD;NY5~+>+WMA7rPOv(jOXFFiKPBc~nCzIZA|!DUvK_Dil!KAQ>AeZR@X>hs zYoy=vhyhVp1@ec1qQepU0?l2V6mE8VvyqJm7Hu@-Pf7rX{TpW0x{~%DGO!aucA&Gf zWuc?B>4<^!-p>C!vZrAJQHl=OVTE#qNvl}mz2PxW2-URyid7gPkenEOC|WcC)wBVz zdF43$E|7XgZJoZI&p?14#l6V`>ljy8svEsCeIshE2&-tP)G|uA2_fL?Qp5@!sy;2M zTnLr?qZY=n=o?Z5Yi|3FAGM2(g3?z%w++VZXPrsd>oErhZ|F!tv^-(bTN#Cd2{!4)z5|6 z;!GXM{82A18Dh$$0O=E*HXB+NZsd9z7OCyabx2OL!d#7(R2MRbF-S*fFIAo-tv871c%bYH>tsjxNdVKp_LdlRwt`f;9qHIw08g+hBkN@Ir`p|rZ9*&CZVnr6AuaG~^8h~t@OFATYjn3egs zO)sn{8ZeH(?_d6-6(!oi~Kd#BBNqxB)ICB!z-#7Veq3B_S>;LPDiA<1s+l%E~RZEURh8 zre&t4X>6Ls%*v*w#S5j4 z9m(dqMaSBb_LRBYJ{VxWGtYcs`m@0T)3a*R%K_89kIlF9dbKX*r{O==pnv@|=+QCi z_~qh(29Had2)*mr=JO82UvW*hf-iUDP0w1)&kw))bM~wI3iD9N@PTCWAJfil<(S5I zJ{&%J??lvtOZ!eYlkXf!Hr>tJD|b4xbJ5NIx`%ypZ}o6qobesnoip7O<>a`LzVWqvUK_UYzZ-{zdrp)ViEetxZCY-stt^S-a13tl}f zdGv?%aG%%MPpRe++4zIhzwdQF9uB*>xA5^G`u;`2ol}^jtC422*~e^`6qk|Ci%E$K z3#B7q002NsS;7<&U!)X4ztOX+QPf}8v zu(DE;zA`C8ys}KpDkRUIMT)LsS4rhkiBd$Wl9pE}*i{^|s8F_8!iJtL%QP}+VvDkj zLyochL9+Pd$toqJ$k6Z*F`dC6F`1!^h)5=r5ljlBGs0+e=*tXYM6e^7?64W6*B>(E zt+KF)oyHfu_65Ch$R$dpoK2&xSg|5>MR=&JvY5tTu~-(3u&@wlM~I@jLMf^WsZjV% zDexrAoSt_d_SrkQ!Wy_QtG8E}#3R3wS*$PGIL^`2jnUq!~lG7NWbW2K88->FE zzf~%Ivs!562SwL0cLW49(KocUnEQ1o2~ed;>1@@&!w^TnnnypnZ*2S7WbPqpoqX-OxyOs#&|n2idWSNJO@7 zRC`d+XzWfbmSWtd@(6Orb2rSHmVQdTVVG@|WX}Zhip42Ws1RQ7LkFEDnQ_+q{ zpakG@9n#(Q0lf@LEE;)gGe9JD^K{Nf@a3dLN?$`Mvl&CAZ;xpf!%Fx)5wRy$1B61% zD7UU}HNrbWa1cIrqtk$%mf=~z*k;23q60JNqV1~HIJgcCFX-AYE;pE?7jmm%BLg^j zBHr;?8fl`Cwo`?)1#nOyITMBCrQ2&%inIW|sv6axl2a*-JZvM#59&zn0D&%zVxgj5 zABav`7O6+mv*$OUFkM2wE?nd4|5daH93Vx-gknj(y+%{w1O^0f^(sDy!JtqZ))F^T z>6CV2Cy(4-M5R!&+d(niH7IDe*tODT_Z~SPP}kU(1grwnU;&y4_A(N7m3*ll=dvK1 zf(`K3v)Y_+lnIr7*ua(sN&ZxnW}7UH99>Av0r1*K;&a7_UqO4 z5b|v*QWu2#77!wRR|3Bcwr?K+@4X%YKZGc>E)6qGBK`@X2+BWQGfB69V6-b~*=%)a zsOMZyPtadX&z6zYvFUcx?}MS@XbeV&b##OS$^3vM6!Mmb3eT0p3u?QZ(riEJ!Ta@- z7C`Kd{!)j<5M9g5-6q+s>g=hFP3mye0Us4C<@sjfHM$pPy{SO^ZI5O0apGv^9W&u(e>Ou_Ueb(P*`R&d4+vwFHlK8t9ys zK#imuoug+&CI-1y8?E>b!dxmnUuPE(ivlqRg&KPR9!H@QQ40%nUOsMaAjLCNi}1Bi z#WP)(X6q1M83Y2jBFN}8EzmkJa7CxTzq7T!SZA;ra}JfSOSXGHy{HN27z^ZFbV0q- z4O;*WU;uk4u%rp@YHIA$^EGNeKlU=YQ57eGL+5?7n6ZdOBqY_h82dOO^87aLfDa7Lk)(%k5 zpWRqLICQbjn3=go`;ODMgTLc_q3Q*#t;W0#fvPNC7{9q?t8hE3q9Q+kd%fWEZk8$> z1r479PCX~{>qAS_G5K^lH9tzj$*0n*1Tl3nGAx=Bk5l2|>1ga(?V#HQ0dA%6s+;hf zE{3$+%}rW{bz6Sd_+WWZQc}=zmwV5-CAB~d!lrhOij<`TM6n#s%F(3>yHX~{>p$+P z@7@u!Wk= zt_4|YHCPZHuFYg+qLAxQtZ-^oLBW!GY6mriwIs8vin?Vw3)C$SOU!hs8h#*tAUyS E1xN?}xc~qF diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/66.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/66.gif deleted file mode 100644 index bb6d077504e3b39871f72150c1f5fa43d4e18bfe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3029 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 n_4QGfNp-c(#;#v)!?fJ=R?7`D2^Hm diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/67.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/67.gif deleted file mode 100644 index 6e33f7c4f762b5c4eda2a630793d681345423734..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2701 zcmeHHX;@Qd7QP`wAR!P4LKMNv4ag!{fe<2l0wNMfff>RmQ$ung5we&B2sE}NQQ0hl z0##@QM5-uS7zc}jV`Pm>RVw1%Vylj=ZLzi0Qai)kFhb|YIKSsdzvp|N`+eu0_dVx) zXIZ;0ksTp&2i$>2dSD!leuTm7o^ZHfYuo>&Z`mPt!x{U-cRY5C*l#mC41LSmbHT;( zUGkI2nA2#Rrb`|(j*iO1cHQ?pn>;WFZ!LY-f^QrJJ1>S+WVvi^!dIWSuQ{>0b;9GY z9lH1^R@7iOPITRW)o1$v;bH{m?OsCtkax=nP1QzdzT*05X7UsP*FHsTpY$DAMmjku zHJ&8a40_cKyS{&MMd$Uv!e*DAJDlB@v7OgebU^t17Vx9nkfdcv>K1JA{$-LT+^>20 z*PhFU9}1p=KA*p=ujus4GGL#0dDncr?3a|ZhSRZ=1VYCp|7s4ldSK}bF7J8PhFLnj z>w4I+JCvP6u7>XATl;W>Unkd$;tqWpd@ms2%JYp!ZuyKpf*;VCr@mm{{^?CcEAB@( zx33b`9=e<|HY094!#O-AZXH=K-Q{|9M)S;X)z$<44FiFZSoG=!L84kW$5MoU&$>XH+5?|RuZc&g_t5tDm zw33n%YDoxHsm`Y{A|fKJ984w!(V%Eb6l7NT zNFj#T@uDDvgDR6rIAIZS^zd+cNJ1Es%U~oh;#mwPJ3cOs7akWE9~Kw7faNL0MRHi7 zUBF6y!-l>VYb^%33bD+C)v{t(lBib7!TF#$ve)~s zFNl!(u^tx-7r88!KCD3MU5ykrYVM!^`1R#4vp>Ih{?m`oe)#_B%y-{@^W^KV9{>H( z!v|k}aew;r&+gs5bNklK8&lUOuYEdk^~&W>E?vBE-ZDNmIx;+T&V2T7X9fpOpX&ek zWZz#;{H3?&qvOZAj~?kdeCWf@gB=Ij+gkU3@P144zP;}?H8$+oU0=7W_T8N|)m4=h zJGO5#84cy{yuDTbR#~a8q_{|{QEyQx74pJ@%`$0z9xM^(iZ;FZ=bVij{**1u`r{um zGt%D>q^0sx)+et^TAP@_xD9-fyB-6$pG36_y?M{(1_q6hr8^^LS-#_kcH}58IGV?6=MdMD+5tUHk&0(>?g&0>`2iA*g?VMdC zmdaRm(jLeZy-5U`hE1NFpy2)?1KNnSCyiL>(s4(Os~bURs4yDQHnyRo9cFXYNIGc+ z2pWb^k*-f4kC~d!HQq2r>t@r}blF69IS`U4(--l}tGJdA<(@ATpV^Rn%cCu8r)H*y zXJ*^F24{JO`Q$h_FC=Fvu=G`Oaw*$$jg{LdK^2uoN{&7$7w~EV$Z4s1O07Phh&(;P zi7c;3?jY#3wHQ5$fI{nY1UVqkhjNOl%+DnD^*I6KUdCi}PyuZ8SChsXNkzrQMJbbP z&$HsoB}DcV&l6UA7AQy$)S2Q?E>}s-%cII9FJ&8%K{F=ojVJH2ccCY(D4jSsf~(-W zdI!dCx2=jSjZe8Bl8{_!$~YioOMS3AJ)9Y-*=>w5H{8ngl|A$y4q_@wuWq_~{zQIS zs9x9Ieyv05ygZZ{kkf2Pb@4V<6V}B)v}v(%;|n6T7^|ynU?vzJvZJP|MYuUd2HD`6 zOi+Hm&_WL2x-moYw(a$Kc+P|g7G~-Mh7)u*?!>io2`ZH#lbLZlN1QCU3@6uz?6Qi{de e&Ns&5+yCAe|96dnSxgQJK<1box?FDn*8B_Be&pBy diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/68.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/68.gif deleted file mode 100644 index 1a6c400d2aee3c2bf384ea98105ea143a7be97a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1424 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 ig6vPE;(vp8vN=19VTuwMWT7@8^o diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/7.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/7.gif deleted file mode 100644 index e6d4db80572a8321fa233d7efd82636fd896bf49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3398 zcmd^>X;@Qd7RPTELI_!bkd;Wn76gSL8VCjmtHxL~xKN`N+n}hegVj>h8D8>cxj_Xi zSjVMQtw_~*7^&k@lqw)n5L%Qf;?}a%$_S(4Sc^ztZUR`_vClK#=R=++pYA>9{D0^C zZu0D;h{zS5h$r$BKyDljeeg~Gzpv>>pPpV9$sVltd~rxR`uyh5zR4p4e|vFC+O#|H zv~`i~-j?S%p|-YZRTls5(~6<90^7Bykw*t_{yoLk9^2PA*Vd`G-JE0VS^KObdni9- zrJysV)|MRV zaBJYG?OEYU%}|A8=;|Avr3>mxX52f;8N5DkxF+IZrSRUFsV^@0bbS{2%grTUf2o$GyCOZ|TCDz;sYyO{G90Ih5#fO`;Ud>i6G9Sc>o%d*M-cshOA3A78FdM{l3e3 z=iv1o5zA&zFEoa5a1lOUE(8}Z0nH~Xq%>s4f(3602*DW{)Gyc(>Ix$sVT<^*41ecb ze}Y$%isPfk8w2pXi+Yb!A2;jyVLW~SpYku+tU=qPli8pW=;!x4wjSv$pR&(F+B z_YEXRt-{9|pf4I)HIeQ!AzOyucb@(bM=` z(PEI~p50sx_;3Nc9 z5xKbS5K0$YDtkL?YQ-f1a9u?2idnO)BD(NSXl0^lvMR{K`%0sstSMecA>VpCmWdB^ z@(>jtRYRiLFa{*W4kQjCV$D&p_HwZHqNP}SnKaZqq4a2a~w^|4;5dy4mPab+0 z@VU$0XQ*Ye@MVyO=Y)qZjsZ(tUFW#U_<&P=UIrJ=CC(>K`nsukk{Tw!D5MIx2HKYc zBoPM^@!4k+E#||T@_s1pJ1iuZQyxDx{C3t%$E@qIVmLUg7y%7+kPk8Nv2wxU0{nWd0|dEHQp6|+bed(ZJD^M+%YPXeg< z6m|}mqJlK4fJ}`HEkT=%@he;Igy!|N?h2UV^j_`sm712_GyXK<@;ive8awt1M6WUg zUttK?8A2_YhYx{qhAP?cw+z`4I>+BPh7d+j(>cJu#l0HCdkIiacX&I7&!dHl0sG-& zcVOoSC*Xn9XHL@Yp4v%)%FVsZx5?Y+bfE|TY}bM0V=;8$(mRb;uk6Bmr5gIVty( z*3rs1?|2L_`#PWd<0PV`j&%l^G`RF|{_l-Q8s7*$=lf0> zkGpU#m=7kwKH|ekY95k6Bt{`{aA0Vi1JVHSj2pOC0oIHR4z%rp`lwn0V+d)tfSZtNXQOIQR zHj`(XLTM6{ghJBRI5GJ!nW9xHNg7j1%Arc&2DBuK6Ds+~ISQ&PHt8;SYBft&kjUgWbx@~;SRvvy;0@rWbt?pvmb>Pe*9vuRaX&t0 zpsy_?GY`Z8li6Yl&o-@Aps9d^x|`BSg`mhHHY??HI$5!LwOF}-zmP;(A^coUP7^CC z=zxBl0!sHE*NI6dPYcOaCZ$lR)#3Xyby_@m+qPkM0*+oFwZGrfJm%=S6h3H2pyl(Iu2|m8IIiYIUBrX7AZE zQl{fthK+q4Onm%wVLeU=8N4)dA=~m>BSSoI--MB&!^qnlLWT|@e>5)S^S=`^_|?dr z_VW*ZRdP3`WZ-bJC78J}iSdy%zMZRZM<^b?EMkV;0463JGl1C78#6$y%Gq5-Z~1Y> zlg?IxSn*`{`mBpJyApMu4sSXUhl2uoM90$bmD{~p^3kWU-ihR^iLgxn=0E@wiTV!_ Ch@v0> diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/70.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/70.gif deleted file mode 100644 index 416c5c14a19fbdaf8fb8d6baf5cf7e31e54f751a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4590 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 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/71.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/71.gif deleted file mode 100644 index c17d60cbd15e80d83629b2220b562a224eec5554..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5304 zcmeHKc~q0vwogJPk}xJ9B1#BhCgjTmNeq~YNd}{UqP0pUB^5{vVQ?&AEC?7ukz(-% zv`B#}B2rM$Flj)Lh+M>hDwb<4daKoHY425DXlvj5qpNSdx7J&$Z>@g+eBU`|@BQ2R z{Pyph^@T@m+2gq6oKWyd4Y z=SwsHF+KhD{rim~>xTS{-p^`JWF-A7jdOax;-~rfx!KuX3Z*_8V`yzX7>sx{J$+C_ zZaetl0Tyh$zx&DT?1^YhQ4nhUQu}@YxuDzjQmvkzoVH$vA65| ztBi~f1Hkv$lnycWs|t@Vw%{H=eq0!2p#>mM!dD&&K^zLfj7p{bELINPrgXLMO)b8R zgXw5!*iVK`6%wuu8DG78nL~y&th1Zx>Z;@+5A&>QBdv{F#TRVsUOavJGLG2KPLal zD|CM&e#N8)+j-`6cS}nS&3cSYDP_azqA(*_%g6V*E@U}>Env>Se)V8{ynT~h^Wg)g z;o;A#N`Df2jP2RmMf5xtZhdBh?WK;kneLwP(a|ZIe-$5jXW&91-Qp^ZdSJD0l>jl} zzU)o1&&A5zxw*Mv8G4w_9^bd`8i!LrhhA)J9UB^|2}K?YM-5P^L;d}u!NGl@;Xh<$ zU8vMPQ7ZS7!2gU4{{F>_3NHM+Cr_Haw#Rmv>d>eV;%)5sjXI{rXU_ zWeF2{E*??Bf}TsXZ&+h>%G^IuuyPK3gu^*1wCvo9J-RitYOC-?W~LUf_>c_I2HHOf z=bWvre3Koya6j+uPN#)B+1ss73#JWk4yV0M4|!X?W#R75g{j0h9|XQRk+)DtS~!!r zFd&mm21TK?9`OBbar+y zK`c{B6&%&|4id|t<&RospRB!@^oc}S}Hf2yT5Zb@7*5* zEgG7$VXsju%%q4@gi2{fsys~-DGVlh;*RQ^R`Qp3h z&%XWV(8Cm(%y|-nl(>Yx3_CH^*<7#;%W!TpJ!TUcE9n(BIc< zxO}On`{ISJ&M!L7x1Vb}+j{2o=Pk`mpEaIp`1It7`a1pJj@N#2tmfnDqg6)^S5_R- z9V{;^Jy25oQBh$*eqOFN=fnN`_U_reD?2MQLzAxFsZyq;rtJ7Yk-UAITqc!>leTVo zfAf2rHYRRZpAa9nZmnodY)o|2>d1)juu!3Z&*QEN3FfS1vzS4F3_6WU0muO)e?MOz zZ!b>|qC3G2@48~S%QEMsPD>mea9DdgTN`UD3>syLM8IKC3yArwar+T!i2^Nv{LROX z`95|8fshNJ1xuHRR()?C^qVe$QI&M5z{>7U&egFnVIFbC{GK0j212#;kKSJys_n}o zrzHb8IZ5~V)&l^KU(ljkvbp7{i(g{B00KuPBKdvIh;#4x=XgFANs@f=754Px=i*3W z=Jr|Dj{t+$@qQQdZLbKnyxIx9NsE#+Mm4~^(n_CrY^ybRTKoGjv<0{tc@5{|`OolG z7NL;Z=w?0PcCl-;XQa*)eYDwWr+tD-v|8WAASLbV)@TX-VcxXyRGTlT(K6CbOi(26c}lt9ld2|2N5UUjw`BcbrCdh)SAY7 zXbc5|@nx+W7XiAHD4JTjylk$9IgUfx(CgQ9l?O z%`Jn$V9-CN35oS=*GA9u?R}oYq(?mL?b&4$5siz;n>rtd^XAMyEDYnXorK)}={yok zj5nfo^$reSKbz~pCMM}~3h>14-N41c-0iv69`FVT!H1UzcdZgivcjy7+N{CK?jDJH z;EG8wX^YS59UAe47i61M53h7?kxW{qJTz3S#U@77ZEP5-EUraKSR$fns2$~7Q9Iu& ztAJXLYPw47yw<`HpF(Tiy9t@}a%mT3C$<_aQ1Voen|;pACkDH_9m3=d=$ex4O(mEU z*wCVnk$1w%Y#-;EK9Pu^DV?)YtdZ#8J7yc*2C=BdE9 z{>Ucq@fg27b1M5Psqt`lx%H8|-#uD(T=jpaB+LJ)l8{*67OypK{AI6a2h)>v19@3* zR_OHJI{4Wgr@Tek&j+o_^6Oh*ZLfCNc}6tq9A4xeI8rNxMQI`oTrip!k^L$u^FZhr zbopvbG)%ZI7j6~eUp(+_sY`&X-qYCOchs=TsY!2vmGb;VJWR$=`-6e9ojn6B*r@^S zrzbpHb^LSDm0nnm!+=^Jp|4ap#1mJ3mp4STw6FO_?cg3;kFs8EN&lh&*0P3~T=%>+ zNsGV@-vRN7pnjIty(6{QblQ>bFc$ByG|a2Snr7Et=ImyI)v*Tk$SKtj;s~$SH#HfY z6Ws_7fRViA4TnJot0@*aRWak-q?Z}Oe6G{_*Ap{D|EoHmgD%T`zxZl2h%?g& z?&rd~0kq9hDA&?em|YnTN_o7q$R`ZPHNp0^h{8}0WVR!|*FhE#7Z=sdGS?-zlUnu- znHYocG2#X8Qk?}DqDWSWknodvAa_5a`7e*$O(+1n5oJ6E)>g%}Vz_V((1}Emi2L8l tXu@la*v!%E+p0y5_RRmq(VvW?ziy=eFE`R(Qu>o0cYjIg&myIj{{av3`u+d_ diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/8.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/8.gif deleted file mode 100644 index 66f967b48da173b68cbfc92986e4426ea35ade74..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4050 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 JEmCgizW{zshWG#g diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/9.gif b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/images/face/9.gif deleted file mode 100644 index 60447400d31b035f56554b29af1aefc76bda1698..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4221 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 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/layim.css b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/layim.css deleted file mode 100644 index face39b4..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/layim.css +++ /dev/null @@ -1,2 +0,0 @@ -/** WebIMUI-v3.9.8 */ - html #layuicss-skinlayimcss{display:none;position:absolute;width:1989px}body .layui-layim,body .layui-layim-chat{border:1px solid #D9D9D9;border-color:rgba(0,0,0,.05);background-repeat:no-repeat;background-color:#F6F6F6;color:#333;font-family:\5FAE\8F6F\96C5\9ED1}body .layui-layim-chat{background-size:cover}body .layui-layim .layui-layer-title{height:110px;border-bottom:none;background:0 0}.layui-layim-main{position:relative;top:-98px;left:0}body .layui-layim .layui-layer-content,body .layui-layim-chat .layui-layer-content{overflow:visible}.layui-layim cite,.layui-layim em,.layui-layim-chat cite,.layui-layim-chat em{font-style:normal}.layui-layim-info{height:50px;font-size:0;padding:0 15px}.layui-layim-info *{font-size:14px}.layim-tab-content li h5 *,.layui-layim-info div,.layui-layim-skin li,.layui-layim-tab li,.layui-layim-tool li{display:inline-block;vertical-align:top;*zoom:1;*display:inline}.layim-tab-content li h5 span,.layui-layim-info .layui-layim-user,.layui-layim-list li p,.layui-layim-list li span,.layui-layim-remark{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.layui-layim-info .layui-layim-user{max-width:150px;margin-right:5px;font-size:16px}.layui-layim-status{position:relative;top:2px;line-height:19px;cursor:pointer}.layim-status-online{color:#3FDD86}.layim-status-hide{color:#DD691D}.layim-menu-box{display:none;position:absolute;z-index:100;top:24px;left:-31px;padding:5px 0;width:85px;border:1px solid #E2E2E2;border-radius:2px;background-color:#fff;box-shadow:1px 1px 20px rgba(0,0,0,.1)}.layim-menu-box li{position:relative;line-height:22px;padding-left:30px;font-size:12px}.layim-menu-box li cite{padding-right:5px;font-size:14px}.layim-menu-box li i{display:none;position:absolute;left:8px;top:0;font-weight:700;color:#5FB878}.layim-menu-box .layim-this i{display:block}.layim-menu-box li:hover{background-color:#eee}.layui-layim-remark{position:relative;left:-6px;display:block;width:100%;border:1px solid transparent;margin-top:8px;padding:0 5px;height:26px;line-height:26px;background:0 0;border-radius:2px}.layui-layim-remark:focus,.layui-layim-remark:hover{border:1px solid #d2d2d2;border-color:rgba(0,0,0,.15)}.layui-layim-remark:focus{background-color:#fff}.layui-layim-tab{margin-top:10px;padding:9px 0;font-size:0}.layui-layim-tab li{position:relative;width:33.33%;height:24px;line-height:24px;font-size:22px;text-align:center;color:#666;color:rgba(0,0,0,.6);cursor:pointer}.layim-tab-two li{width:50%}.layui-layim-tab li.layim-this:after{content:'';position:absolute;left:0;bottom:-9px;width:100%;height:3px;background-color:#3FDD86}.layui-layim-tab li.layim-hide{display:none}.layui-layim-tab li:hover{opacity:.8;filter:Alpha(opacity=80)}.layim-tab-content{display:none;padding:10px 0;height:349px;overflow:hidden;background-color:#fff;background-color:rgba(255,255,255,.9)}.layim-tab-content:hover{overflow-y:auto}.layim-tab-content li h5{position:relative;margin-right:15px;padding-left:30px;height:28px;line-height:28px;cursor:pointer;font-size:0;white-space:nowrap;overflow:hidden}.layim-tab-content li h5 *{font-size:14px}.layim-tab-content li h5 span{max-width:125px}.layim-tab-content li h5 i{position:absolute;left:12px;top:0;color:#C9BDBB}.layim-tab-content li h5 em{padding-left:5px;color:#999}.layim-tab-content li h5[lay-type=true] i{top:2px}.layim-tab-content li ul{display:none;margin-bottom:10px}.layui-layim-list li{position:relative;height:42px;padding:5px 15px 5px 60px;font-size:0;cursor:pointer}.layui-layim-list li:hover{background-color:#F2F2F2;background-color:rgba(0,0,0,.05)}.layui-layim-list li.layim-null{height:20px;line-height:20px;padding:0;font-size:14px;color:#999;text-align:center;cursor:default}.layui-layim-list li.layim-null:hover{background:0 0}.layui-layim-list li *{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:14px}.layui-layim-list li span{margin-top:4px;max-width:155px}.layui-layim-list li img{position:absolute;left:15px;top:8px;width:36px;height:36px;border-radius:100%}.layui-layim-list li p{display:block;padding-right:30px;line-height:18px;font-size:12px;color:#999}.layui-layim-list li .layim-msg-status{display:none;position:absolute;right:10px;bottom:7px;padding:0 5px;height:16px;line-height:16px;border-radius:16px;text-align:center;font-size:10px;background-color:#F74C31;color:#fff}.layim-list-gray{-webkit-filter:grayscale(100%);-ms-filter:grayscale(100%);filter:grayscale(100%);filter:gray}.layui-layim-tool{padding:0 10px;font-size:0;background-color:#F6F6F6;border-radius:0 0 2px 2px}.layui-layim-tool li{position:relative;width:48px;height:37px;line-height:40px;text-align:center;font-size:22px;cursor:pointer}.layui-layim-tool li:active{background-color:#e2e2e2}.layui-layim-tool .layim-tool-msgbox{line-height:37px}.layui-layim-tool .layim-tool-find{line-height:38px}.layui-layim-tool .layim-tool-skin{font-size:26px}.layim-tool-msgbox span{display:none;position:absolute;left:12px;top:-12px;height:20px;line-height:20px;padding:0 10px;border-radius:2px;background-color:#33DF83;color:#fff;font-size:12px;-webkit-animation-duration:1s;animation-duration:1s}.layim-tool-msgbox .layer-anim-05{display:block}.layui-layim-search{display:none;position:absolute;bottom:5px;left:5px;height:28px;line-height:28px}.layui-layim-search input{width:210px;padding:0 30px 0 10px;height:30px;line-height:30px;border:none;border-radius:3px;background-color:#ddd}.layui-layim-search label{position:absolute;right:6px;top:4px;font-size:20px;cursor:pointer;color:#333;font-weight:400}.layui-layim-skin{margin:10px 0 0 10px;font-size:0}.layui-layim-skin li{margin:0 10px 10px 0;line-height:60px;text-align:center;background-color:#f6f6f6}.layui-layim-skin li,.layui-layim-skin li img{width:86px;height:60px;cursor:pointer}.layui-layim-skin li img:hover{opacity:.8;filter:Alpha(opacity=80)}.layui-layim-skin li cite{font-size:14px;font-style:normal}body .layui-layim-chat{background-color:#fff}body .layui-layim-chat-list{width:760px}body .layui-layim-chat .layui-layer-title{height:80px;border-bottom:none;background-color:#F8F8F8;background-color:rgba(245,245,245,.7)}body .layui-layim-chat .layui-layer-content{background:0 0}.layim-chat-list li *,.layui-layim-min .layui-layer-content *{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:14px}.layim-chat-list{display:none;position:absolute;z-index:1000;top:-80px;width:200px;height:100%;background-color:#D9D9D9;overflow:hidden;font-size:0}.layim-chat-list:hover{overflow-y:auto}.layim-chat-list li,.layui-layim-min .layui-layer-content{position:relative;margin:5px;padding:5px 30px 5px 5px;line-height:40px;cursor:pointer;border-radius:3px}.layim-chat-list li img,.layui-layim-min .layui-layer-content img{width:40px;height:40px;border-radius:100%}.layui-layim-photos{cursor:crosshair}.layim-chat-list li{white-space:nowrap}.layim-chat-list li span,.layui-layim-min .layui-layer-content span{width:100px;padding-left:10px;font-size:16px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.layim-chat-list li span cite{color:#999;padding-left:10px}.layim-chat-list li:hover{background-color:#E2E2E2}.layim-chat-list li.layim-this{background-color:#F3F3F3}.layim-chat-list li .layui-icon{display:none;position:absolute;right:5px;top:7px;color:#555;font-size:22px}.layim-chat-list li .layui-icon:hover{color:#c00}.layim-chat-list li:hover .layui-icon{display:inline-block}.layim-chat-system{margin:10px 0;text-align:center}.layim-chat-system span{display:inline-block;line-height:30px;padding:0 15px;border-radius:3px;background-color:#e2e2e2;cursor:default;font-size:14px}.layim-chat{display:none;position:relative;background-color:#fff;background-color:rgba(255,255,255,.9)}.layim-chat-title{position:absolute;top:-80px;height:80px}.layim-chat-other{position:relative;top:15px;left:15px;padding-left:60px;cursor:default}.layim-chat-other img{position:absolute;left:0;top:0;width:50px;height:50px;border-radius:100%}.layim-chat-username{position:relative;top:5px;font-size:18px}.layim-chat-status{margin-top:6px;font-size:14px;color:#999}.layim-chat-group .layim-chat-other .layim-chat-username{cursor:pointer}.layim-chat-group .layim-chat-other .layim-chat-username em{padding:0 10px;color:#999}.layim-chat-main{height:262px;padding:15px 15px 5px;overflow-x:hidden;overflow-y:auto}.layim-chat-main ul li{position:relative;font-size:0;margin-bottom:10px;padding-left:60px;min-height:68px}.layim-chat-text,.layim-chat-user{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:14px}.layim-chat-user{position:absolute;left:3px}.layim-chat-user img{width:40px;height:40px;border-radius:100%}.layim-chat-user cite{position:absolute;left:60px;top:-2px;width:500px;line-height:24px;font-size:12px;white-space:nowrap;color:#999;text-align:left;font-style:normal}.layim-chat-user cite i{padding-left:15px;font-style:normal}.layim-chat-text{position:relative;line-height:22px;margin-top:25px;padding:8px 15px;background-color:#e2e2e2;border-radius:3px;color:#333;word-break:break-all;max-width:462px\9}.layim-chat-text:after{content:'';position:absolute;left:-10px;top:13px;width:0;height:0;border-style:solid dashed dashed;border-color:#e2e2e2 transparent transparent;overflow:hidden;border-width:10px}.layim-chat-text a{color:#33DF83}.layim-chat-text img{max-width:100%;vertical-align:middle}.layim-chat-text .layui-layim-file,.layui-layim-file{display:block;text-align:center}.layim-chat-text .layui-layim-file{color:#333}.layui-layim-file:hover{opacity:.9}.layui-layim-file i{font-size:80px;line-height:80px}.layui-layim-file cite{display:block;line-height:20px;font-size:14px}.layui-layim-audio{text-align:center;cursor:pointer}.layui-layim-audio .layui-icon{position:relative;top:5px;font-size:24px}.layui-layim-audio p{margin-top:3px}.layui-layim-video{width:120px;height:80px;line-height:80px;background-color:#333;text-align:center;border-radius:3px}.layui-layim-video .layui-icon{font-size:36px;cursor:pointer;color:#fff}.layim-chat-main ul .layim-chat-system{min-height:0;padding:0}.layim-chat-main ul .layim-chat-mine{text-align:right;padding-left:0;padding-right:60px}.layim-chat-mine .layim-chat-user{left:auto;right:3px}.layim-chat-mine .layim-chat-user cite{left:auto;right:60px;text-align:right}.layim-chat-mine .layim-chat-user cite i{padding-left:0;padding-right:15px}.layim-chat-mine .layim-chat-text{margin-left:0;text-align:left;background-color:#5FB878;color:#fff}.layim-chat-mine .layim-chat-text:after{left:auto;right:-10px;border-top-color:#5FB878}.layim-chat-mine .layim-chat-text a{color:#fff}.layim-chat-footer{border-top:1px solid #F1F1F1}.layim-chat-tool{position:relative;padding:0 8px;height:38px;line-height:38px;font-size:0}.layim-chat-tool span{position:relative;margin:0 10px;display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:24px;cursor:pointer}.layim-chat-tool .layim-tool-log{position:absolute;right:5px;font-size:14px}.layim-tool-log i{position:relative;top:2px;margin-right:5px;font-size:20px;color:#999}.layim-tool-image input{position:absolute;font-size:0;left:0;top:0;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}body .layui-layim-face{margin:10px 0 0 -18px;border:none;background:0 0}body .layui-layim-face .layui-layer-content{padding:0;background-color:#fff;color:#666;box-shadow:none}.layui-layim-face .layui-layer-TipsG{display:none}.layui-layim-face ul{position:relative;width:372px;padding:10px;border:1px solid #D9D9D9;background-color:#fff;box-shadow:0 0 20px rgba(0,0,0,.2)}.layui-layim-face ul li{cursor:pointer;float:left;border:1px solid #e8e8e8;height:22px;width:26px;overflow:hidden;margin:-1px 0 0 -1px;padding:4px 2px;text-align:center}.layui-layim-face ul li:hover{position:relative;z-index:2;border:1px solid #eb7350;background:#fff9ec}.layim-chat-textarea{margin-left:10px}.layim-chat-textarea textarea{display:block;width:100%;padding:5px 0 0;height:68px;line-height:20px;border:none;overflow:auto;resize:none;background:0 0}.layim-chat-textarea textarea:focus{outline:0}.layim-chat-bottom{position:relative;height:46px}.layim-chat-send{position:absolute;right:15px;top:3px;height:32px;line-height:32px;font-size:0;cursor:pointer}.layim-chat-send span{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:14px;line-height:32px;margin-left:5px;padding:0 20px;background-color:#5FB878;color:#fff;border-radius:3px}.layim-chat-send span:hover{background-color:#69BC80}.layim-chat-send span:active{background-color:#59B573}.layim-chat-send .layim-send-btn{border-radius:3px 0 0 3px}.layim-chat-send .layim-send-set{position:relative;width:30px;height:32px;margin-left:0;padding:0;border-left:1px solid #85C998;border-radius:0 3px 3px 0}.layim-send-set .layui-edge{position:absolute;top:14px;left:9px;border-width:6px;border-top-style:solid;border-top-color:#fff}.layim-chat-send .layim-menu-box{left:auto;right:0;top:33px;width:180px;padding:10px 0}.layim-chat-send .layim-menu-box li{padding-right:15px;line-height:28px}body .layui-layim-min{border:1px solid #D9D9D9}.layui-layim-min .layui-layer-content{margin:0 5px;padding:5px 10px;white-space:nowrap}.layui-layim-close .layui-layer-content span{width:auto;max-width:120px}body .layui-layim-members{margin:25px 0 0 -75px;border:none;background:0 0}body .layui-layim-members .layui-layer-content{padding:0;background:0 0;color:#666;box-shadow:none}.layui-layim-members .layui-layer-TipsG{display:none}.layui-layim-members ul{position:relative;width:578px;height:200px;padding:10px 10px 0;border:1px solid #D9D9D9;background-color:#fff;background-color:rgba(255,255,255,.9);box-shadow:none;overflow:hidden;font-size:0}.layui-layim-members ul:hover{overflow:auto}.layim-add-img,.layim-add-remark,.layui-layim-members li{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:14px}.layui-layim-members li{width:112px;margin:10px 0;text-align:center}.layui-layim-members li a{position:relative;display:inline-block;max-width:100%}.layui-layim-members li a:after{content:'';position:absolute;width:46px;height:46px;left:50%;margin-left:-23px;top:0;border:1px solid #eee;border-color:rgba(0,0,0,.1);border-radius:100%}.layui-layim-members li img{width:48px;height:48px;border-radius:100%}.layui-layim-members li:hover{opacity:.9}.layui-layim-members li a cite{display:block;padding:0 3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}body .layui-layim-contextmenu{margin:70px 0 0 30px;width:200px;padding:5px 0;border:1px solid #ccc;background:#fff;border-radius:0;box-shadow:0 0 5px rgba(0,0,0,.2)}body .layui-layim-contextmenu .layui-layer-content{padding:0;background-color:#fff;color:#333;font-size:14px;box-shadow:none}.layui-layim-contextmenu .layui-layer-TipsG{display:none}.layui-layim-contextmenu li{padding:0 15px 0 35px;cursor:pointer;line-height:30px}.layui-layim-contextmenu li:hover{background-color:#F2F2F2}.layim-add-box{margin:15px;font-size:0}.layim-add-img img,.layim-add-remark p{margin-bottom:10px}.layim-add-img{width:100px;margin-right:20px;text-align:center}.layim-add-img img{width:100px;height:100px}.layim-add-remark{width:280px}.layim-add-remark .layui-select{width:100%;margin-bottom:10px}.layim-add-remark .layui-textarea{height:80px;min-height:80px;resize:none}.layim-tab-content,.layui-layim-face ul,.layui-layim-tab{margin-bottom:0}.layim-tab-content li h5{margin-top:0;margin-bottom:0},.layui-layim-face img{vertical-align:bottom}.layim-chat-other span{color:#444}.layim-chat-other span cite{padding:0 15px;color:#999}.layim-chat-other:hover{text-decoration:none} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/layer-mobile.js b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/layer-mobile.js deleted file mode 100644 index 0eb5d52b..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/layer-mobile.js +++ /dev/null @@ -1,2 +0,0 @@ -/** WebIMUI-v3.9.8 */ - ;layui.define(function(e){"use strict";var t=(window,document),i="querySelectorAll",n="getElementsByClassName",a=function(e){return t[i](e)},s={type:0,shade:!0,shadeClose:!0,fixed:!0,anim:"scale"},l={extend:function(e){var t=JSON.parse(JSON.stringify(s));for(var i in e)t[i]=e[i];return t},timer:{},end:{}};l.touch=function(e,t){e.addEventListener("click",function(e){t.call(this,e)},!1)};var o=0,r=["layui-m-layer"],d=function(e){var t=this;t.config=l.extend(e),t.view()};d.prototype.view=function(){var e=this,i=e.config,s=t.createElement("div");e.id=s.id=r[0]+o,s.setAttribute("class",r[0]+" "+r[0]+(i.type||0)),s.setAttribute("index",o);var l=function(){var e="object"==typeof i.title;return i.title?'

                              '+(e?i.title[0]:i.title)+"

                              ":""}(),d=function(){"string"==typeof i.btn&&(i.btn=[i.btn]);var e,t=(i.btn||[]).length;return 0!==t&&i.btn?(e=''+i.btn[0]+"",2===t&&(e=''+i.btn[1]+""+e),'
                              '+e+"
                              "):""}();if(i.fixed||(i.top=i.hasOwnProperty("top")?i.top:100,i.style=i.style||"",i.style+=" top:"+(t.body.scrollTop+i.top)+"px"),2===i.type&&(i.content='

                              '+(i.content||"")+"

                              "),i.skin&&(i.anim="up"),"msg"===i.skin&&(i.shade=!1),s.innerHTML=(i.shade?"
                              ':"")+'
                              "+l+'
                              '+i.content+"
                              "+d+"
                              ",!i.type||2===i.type){var y=t[n](r[0]+i.type),u=y.length;u>=1&&c.close(y[0].getAttribute("index"))}document.body.appendChild(s);var m=e.elem=a("#"+e.id)[0];i.success&&i.success(m),e.index=o++,e.action(i,m)},d.prototype.action=function(e,t){var i=this;e.time&&(l.timer[i.index]=setTimeout(function(){c.close(i.index)},1e3*e.time));var a=function(){var t=this.getAttribute("type");0==t?(e.no&&e.no(),c.close(i.index)):e.yes?e.yes(i.index):c.close(i.index)};if(e.btn)for(var s=t[n]("layui-m-layerbtn")[0].children,o=s.length,r=0;r
                              {{ data.username||data.groupname||data.name||"\u4f5a\u540d" }}

                              {{ data.remark||data.sign||"" }}

                              new
                            • ',"{{# }); if(length === 0){ }}",'
                            • '+(i[a.type]||"\u6682\u65e0\u6570\u636e")+"
                            • ","{{# } }}"].join("")},p=function(a,i,e){return['
                              ','
                              ',"

                              ",e?'':"",'{{ d.title || d.base.title }}',"{{# if(d.data){ }}",'{{# if(d.data.type === "group"){ }}','',"{{# } }}","{{# } }}","

                              ","
                              ",'
                              ',a,"
                              ","
                              "].join("")},f=['
                              ','
                              ','
                                ','
                                  ',y({type:"history"}),"
                                ","
                              ","
                              ",'
                              ','
                                ',"{{# if(d.base.isNewFriend){ }}",'
                              • \u65b0\u7684\u670b\u53cb
                              • ',"{{# } if(d.base.isgroup){ }}",'
                              • \u7fa4\u804a
                              • ',"{{# } }}","
                              ",'
                                ','{{# layui.each(d.friend, function(index, item){ var spread = d.local["spread"+index]; }}',"
                              • ",'
                                {{# if(spread === "true"){ }}{{# } else { }}{{# } }}{{ item.groupname||"\u672a\u547d\u540d\u5206\u7ec4"+index }}( {{ (item.list||[]).length }})
                                ','
                                  ',y({type:"friend",item:"item.list",index:"index"}),"
                                ","
                              • ","{{# }); if(d.friend.length === 0){ }}",'
                                • \u6682\u65e0\u8054\u7cfb\u4eba
                                ',"{{# } }}","
                              ","
                              ",'
                              ','
                                ',"{{# layui.each(d.base.moreList, function(index, item){ }}",'
                              • ','{{item.iconUnicode||""}}{{item.title}}',"
                              • ","{{# }); if(!d.base.copyright){ }}",'
                              • \u5173\u4e8e
                              • ',"{{# } }}","
                              ","
                              ","
                              ",'
                                ','
                              • \u6d88\u606f
                              • ','
                              • \u8054\u7cfb\u4eba
                              • ','
                              • \u66f4\u591a
                              • ',"
                              "].join(""),h=['
                              ','
                              ',"
                                ","
                                ",'","
                                "].join(""),v=function(a){return a<10?"0"+(0|a):a};layui.data.date=function(a){var i=new Date(a||new Date);return v(i.getMonth()+1)+"-"+v(i.getDate())+" "+v(i.getHours())+":"+v(i.getMinutes())},layui.data.content=function(a){var i=function(a){return new RegExp("\\n*\\["+(a||"")+"(pre|div|p|table|thead|th|tbody|tr|td|ul|li|ol|li|dl|dt|dd|h2|h3|h4|h5)([\\s\\S]*?)\\]\\n*","g")};return a=(a||"").replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,""").replace(/@(\S+)(\s+?|$)/g,'@
                                $1$2').replace(/face\[([^\s\[\]]+?)\]/g,function(a){var i=a.replace(/^face/g,"");return''+i+''}).replace(/img\[([^\s]+?)\]/g,function(a){return''}).replace(/file\([\s\S]+?\)\[[\s\S]*?\]/g,function(a){var i=(a.match(/file\(([\s\S]+?)\)\[/)||[])[1],e=(a.match(/\)\[([\s\S]*?)\]/)||[])[1];return i?''+(e||i)+"":a}).replace(/audio\[([^\s]+?)\]/g,function(a){return'

                                \u97f3\u9891\u6d88\u606f

                                '}).replace(/video\[([^\s]+?)\]/g,function(a){return'
                                '}).replace(/a\([\s\S]+?\)\[[\s\S]*?\]/g,function(a){var i=(a.match(/a\(([\s\S]+?)\)\[/)||[])[1],e=(a.match(/\)\[([\s\S]*?)\]/)||[])[1];return i?''+(e||i)+"":a}).replace(i(),"<$1 $2>").replace(i("/"),"").replace(/\n/g,"
                                ")};var g,b,x=['
                              • ','
                                {{ d.uid || d.id }}','{{ d.username||"\u4f5a\u540d" }}',"
                                ",'
                                {{ layui.data.content(d.content||" ") }}
                                ',"
                              • "].join(""),w={message:{},chat:[]},C=function(a){var i=a.init||{};return mine=i.mine||{},local=layui.data("layim-mobile")[mine.id]||{},obj={base:a,local:local,mine:mine,history:local.history||[]},create=function(i){var n=i.mine||{},l=layui.data("layim-mobile")[n.id]||{},s={base:a,local:l,mine:n,friend:i.friend||[],group:i.group||[],history:l.history||[]};s.sortHistory=T(s.history,"historyTime"),w=e.extend(w,s),k(t(p(f)).render(s)),layui.each(d.ready,function(a,i){i&&i(s)})},w=e.extend(w,obj),a.brief?layui.each(d.ready,function(a,i){i&&i(obj)}):void create(i)},k=function(a){return n.open({type:1,shade:!1,shadeClose:!1,anim:-1,content:a,success:function(a){g=e(a),N(g.find(".layui-layim")),w.base.tabIndex&&R.tab(e(".layui-layim-tab>li").eq(w.base.tabIndex))}})},A=function(a,i){a=a||{};var l=e.extend({},w,{title:a.title||"",data:a.data});return n.open({type:1,shade:!1,shadeClose:!1,anim:-1,content:t(p(a.tpl,i!==-1,!0)).render(l),success:function(i){var t=e(i);t.prev().find(".layim-panel").addClass("layui-m-anim-lout"),a.success&&a.success(i),a.isChat||N(t.find(".layim-content"))},end:a.end})},S=function(a,i,t){return a=a||{},a.id?(n.close(S.index),S.index=A({tpl:h,data:a,title:a.name,isChat:!0,success:function(i){b=e(i),Y(),F(),delete w.message[a.type+a.id],P("Msg");var t=L(),n=t.elem.find(".layim-chat-main");layui.each(d.chatChange,function(a,i){i&&i(t)}),N(n),t.textarea.on("focus",function(){setTimeout(function(){n.scrollTop(n[0].scrollHeight+1e3)},500)})},end:function(){b=null,H.time=0}},i)):n.msg("\u975e\u6cd5\u7528\u6237")},N=function(a){l.ios&&a.on("touchmove",function(i){var e=a.scrollTop();e<=0&&(a.scrollTop(1),i.preventDefault(i)),this.scrollHeight-e-a.height()<=0&&(a.scrollTop(a.scrollTop()-1),i.preventDefault(i))})},L=function(){if(!b)return{};var a=b.find(".layim-chat"),i=JSON.parse(decodeURIComponent(a.find(".layim-chat-tool").data("json")));return{elem:a,data:i,textarea:a.find("input")}},T=function(a,i,e){var t=[],n=function(a,e){var t=a[i],n=e[i];return nt?1:0};return layui.each(a,function(a,i){t.push(i)}),t.sort(n),e&&t.reverse(),t},j=function(a){var i=layui.data("layim-mobile")[w.mine.id]||{},e={},n=i.history||{};n[a.type+a.id];if(g){var l=g.find(".layim-list-history");a.historyTime=(new Date).getTime(),a.sign=a.content,n[a.type+a.id]=a,i.history=n,layui.data("layim-mobile",{key:w.mine.id,value:i});var o=l.find(".layim-"+a.type+a.id),c=(w.message[a.type+a.id]||[]).length,d=function(){o=l.find(".layim-"+a.type+a.id),o.find("p").html(a.content),c>0&&o.find(".layim-msg-status").html(c).addClass(s)};if(o.length>0)d(),l.prepend(o.clone()),o.remove();else{e[a.type+a.id]=a;var r=t(y({type:"history",item:"d.data"})).render({data:e});l.prepend(r),d(),l.find(".layim-null").remove()}P("Msg")}},P=function(a,i){if(!i){var i;layui.each(w.message,function(){return i=!0,!1})}e("#LAY_layimNew"+a)[i?"addClass":"removeClass"](s)},H=function(){var a={username:w.mine?w.mine.username:"\u8bbf\u5ba2",avatar:w.mine?w.mine.avatar:layui.cache.layimAssetsPath+"images/default.png",id:w.mine?w.mine.id:null,mine:!0},i=L(),e=i.elem.find(".layim-chat-main ul"),l=i.data,s=w.base.maxLength||3e3,o=(new Date).getTime(),c=i.textarea;if(a.content=c.val(),""!==a.content){if(a.content.length>s)return n.msg("\u5185\u5bb9\u6700\u957f\u4e0d\u80fd\u8d85\u8fc7"+s+"\u4e2a\u5b57\u7b26");o-(H.time||0)>6e4&&(e.append('
                              • '+layui.data.date()+"
                              • "),H.time=o),e.append(t(x).render(a));var r={mine:a,to:l},u={username:r.mine.username,avatar:r.mine.avatar||layui.cache.layimAssetsPath+"images/default.png",id:l.id,type:l.type,content:r.mine.content,timestamp:o,mine:!0};_(u),layui.each(d.sendMessage,function(a,i){i&&i(r)}),l.content=a.content,j(l),O(),c.val(""),c.next().addClass("layui-disabled")}},q=function(){var a=document.createElement("audio");a.src=layui.cache.layimAssetsPath+"voice/"+w.base.voice,a.play()},I={},D=function(a){a=a||{};var i={},n=L(),l=n.data||{},s=l.id==a.id&&l.type==a.type;a.timestamp=a.timestamp||(new Date).getTime(),a.system||_(a),console.log(a),I=JSON.parse(JSON.stringify(a)),w.base.voice&&q(),(!b&&a.content||!s)&&(w.message[a.type+a.id]?w.message[a.type+a.id].push(a):w.message[a.type+a.id]=[a]);var i={};if("friend"===a.type){var o;layui.each(w.friend,function(i,e){if(layui.each(e.list,function(i,e){if(e.id==a.id)return a.type="friend",a.name=e.username,o=!0}),o)return!0}),o||(a.temporary=!0)}else"group"===a.type?layui.each(w.group,function(e,t){if(t.id==a.id)return a.type="group",a.name=a.groupname=t.groupname,i.avatar=t.avatar||layui.cache.layimAssetsPath+"images/default.png",!0}):a.name=a.name||a.username||a.groupname;var c=e.extend({},a,{avatar:i.avatar||a.avatar||layui.cache.layimAssetsPath+"images/default.png"});if("group"===a.type&&delete c.username,j(c),b&&s){var d=b.find(".layim-chat"),r=d.find(".layim-chat-main ul");a.system?r.append('
                              • '+a.content+"
                              • "):""!==a.content.replace(/\s/g,"")&&(a.timestamp-(H.time||0)>6e4&&(r.append('
                              • '+layui.data.date(a.timestamp)+"
                              • "),H.time=a.timestamp),r.append(t(x).render(a))),O()}},_=function(a){var i=layui.data("layim-mobile")[w.mine.id]||{},e=i.chatlog||{};e[a.type+a.id]?(e[a.type+a.id].push(a),e[a.type+a.id].length>c&&e[a.type+a.id].shift()):e[a.type+a.id]=[a],i.chatlog=e,layui.data("layim-mobile",{key:w.mine.id,value:i})},F=function(){var a=layui.data("layim-mobile")[w.mine.id]||{},i=L(),e=a.chatlog||{},n=i.elem.find(".layim-chat-main ul");layui.each(e[i.data.type+i.data.id],function(a,i){(new Date).getTime()>i.timestamp&&i.timestamp-(H.time||0)>6e4&&(n.append('
                              • '+layui.data.date(i.timestamp)+"
                              • "),H.time=i.timestamp),n.append(t(x).render(i))}),O()},M=function(a){var i,e={},l=g.find(".layim-list-"+a.type);if(w[a.type])if("friend"===a.type)layui.each(w.friend,function(t,l){if(a.groupid==l.id)return layui.each(w.friend[t].list,function(e,t){if(t.id==a.id)return i=!0}),i?n.msg("\u597d\u53cb ["+(a.username||"")+"] \u5df2\u7ecf\u5b58\u5728\u5217\u8868\u4e2d",{anim:6}):(w.friend[t].list=w.friend[t].list||[],e[w.friend[t].list.length]=a,a.groupIndex=t,w.friend[t].list.push(a),!0)});else if("group"===a.type){if(layui.each(w.group,function(e,t){if(t.id==a.id)return i=!0}),i)return n.msg("\u60a8\u5df2\u662f ["+(a.groupname||"")+"] \u7684\u7fa4\u6210\u5458",{anim:6});e[w.group.length]=a,w.group.push(a)}if(!i){var s=t(y({type:a.type,item:"d.data",index:"friend"===a.type?"data.groupIndex":null})).render({data:e});if("friend"===a.type){var o=l.children("li").eq(a.groupIndex);o.find(".layui-layim-list").append(s),o.find(".layim-count").html(w.friend[a.groupIndex].list.length),o.find(".layim-null")[0]&&o.find(".layim-null").remove()}else"group"===a.type&&(l.append(s),l.find(".layim-null")[0]&&l.find(".layim-null").remove())}},$=function(a){var i=g.find(".layim-list-"+a.type);w[a.type]&&("friend"===a.type?layui.each(w.friend,function(e,t){layui.each(t.list,function(t,n){if(a.id==n.id){var l=i.children("li").eq(e);l.find(".layui-layim-list").children("li");return l.find(".layui-layim-list").children("li").eq(t).remove(),w.friend[e].list.splice(t,1),l.find(".layim-count").html(w.friend[e].list.length),0===w.friend[e].list.length&&l.find(".layui-layim-list").html('
                              • \u8be5\u5206\u7ec4\u4e0b\u5df2\u65e0\u597d\u53cb\u4e86
                              • '),!0}})}):"group"===a.type&&layui.each(w.group,function(e,t){if(a.id==t.id)return i.children("li").eq(e).remove(),w.group.splice(e,1),0===w.group.length&&i.html('
                              • \u6682\u65e0\u7fa4\u7ec4
                              • '),!0}))},O=function(){var a=L(),i=a.elem.find(".layim-chat-main"),e=i.find("ul"),t=e.children(".layim-chat-li");if(t.length>=c){var n=t.eq(0);n.prev().remove(),e.prev().hasClass("layim-chat-system")||e.before('
                                \u67e5\u770b\u66f4\u591a\u8bb0\u5f55
                                '),n.remove()}i.scrollTop(i[0].scrollHeight+1e3)},Y=function(){var a=L(),i=a.textarea,e=i.next();i.off("keyup").on("keyup",function(a){var t=a.keyCode;13===t&&(a.preventDefault(),H()),e[""===i.val()?"addClass":"removeClass"]("layui-disabled")})},J=function(){var a=["[\u5fae\u7b11]","[\u563b\u563b]","[\u54c8\u54c8]","[\u53ef\u7231]","[\u53ef\u601c]","[\u6316\u9f3b]","[\u5403\u60ca]","[\u5bb3\u7f9e]","[\u6324\u773c]","[\u95ed\u5634]","[\u9119\u89c6]","[\u7231\u4f60]","[\u6cea]","[\u5077\u7b11]","[\u4eb2\u4eb2]","[\u751f\u75c5]","[\u592a\u5f00\u5fc3]","[\u767d\u773c]","[\u53f3\u54fc\u54fc]","[\u5de6\u54fc\u54fc]","[\u5618]","[\u8870]","[\u59d4\u5c48]","[\u5410]","[\u54c8\u6b20]","[\u62b1\u62b1]","[\u6012]","[\u7591\u95ee]","[\u998b\u5634]","[\u62dc\u62dc]","[\u601d\u8003]","[\u6c57]","[\u56f0]","[\u7761]","[\u94b1]","[\u5931\u671b]","[\u9177]","[\u8272]","[\u54fc]","[\u9f13\u638c]","[\u6655]","[\u60b2\u4f24]","[\u6293\u72c2]","[\u9ed1\u7ebf]","[\u9634\u9669]","[\u6012\u9a82]","[\u4e92\u7c89]","[\u5fc3]","[\u4f24\u5fc3]","[\u732a\u5934]","[\u718a\u732b]","[\u5154\u5b50]","[ok]","[\u8036]","[good]","[NO]","[\u8d5e]","[\u6765]","[\u5f31]","[\u8349\u6ce5\u9a6c]","[\u795e\u9a6c]","[\u56e7]","[\u6d6e\u4e91]","[\u7ed9\u529b]","[\u56f4\u89c2]","[\u5a01\u6b66]","[\u5965\u7279\u66fc]","[\u793c\u7269]","[\u949f]","[\u8bdd\u7b52]","[\u8721\u70db]","[\u86cb\u7cd5]"],i={};return layui.each(a,function(a,e){i[e]=layui.cache.layimAssetsPath+"images/face/"+a+".gif"}),i}(),B=layui.stope,E=function(a,i,e){var t,n=a.value;e||a.focus(),document.selection?(t=document.selection.createRange(),document.selection.empty(),t.text=i):(t=[n.substring(0,a.selectionStart),i,n.substr(a.selectionEnd)],e||a.focus(),a.value=t.join(""))},R={chat:function(a){var i=layui.data("layim-mobile")[w.mine.id]||{},t=a.data("type"),n=a.data("index"),l=a.attr("data-list")||a.index(),o={};"friend"===t?o=w[t][n].list[l]:"group"===t?o=w[t][l]:"history"===t&&(o=(i.history||{})[n]||{}),o.name=o.name||o.username||o.groupname,"history"!==t&&(o.type=t),S(o,!0),e(".layim-"+o.type+o.id).find(".layim-msg-status").removeClass(s)},spread:function(a){var i=a.attr("lay-type"),e="true"===i?"false":"true",t=layui.data("layim-mobile")[w.mine.id]||{};a.next()["true"===i?"removeClass":"addClass"](s),t["spread"+a.parent().index()]=e,layui.data("layim-mobile",{key:w.mine.id,value:t}),a.attr("lay-type",e),a.find(".layui-icon").html("true"===e?"":"")},tab:function(a){var i=a.index(),e=".layim-tab-content";a.addClass(o).siblings().removeClass(o),g.find(e).eq(i).addClass(s).siblings(e).removeClass(s)},back:function(a){var i=a.parents(".layui-m-layer").eq(0),e=i.attr("index"),t=".layim-panel";setTimeout(function(){n.close(e)},300),a.parents(t).eq(0).removeClass("layui-m-anim-left").addClass("layui-m-anim-rout"),i.prev().find(t).eq(0).removeClass("layui-m-anim-lout").addClass("layui-m-anim-right"),layui.each(d.back,function(a,i){setTimeout(function(){i&&i()},200)})},send:function(){H()},face:function(a,i){var t="",l=L(),s=l.textarea;layui.each(J,function(a,i){t+='
                              • '}),t='
                                  '+t+"
                                ",n.popBottom({content:t,success:function(a){var i=e(a).find(".layui-layim-face").children("li");u(i,function(){return E(s[0],"face"+this.title+" ",!0),s.next()[""===s.val()?"addClass":"removeClass"]("layui-disabled"),!1})}});var o=e(document);m?u(o,function(){R.faceHide()}):o.off("click",R.faceHide).on("click",R.faceHide),B(i)},faceHide:function(){n.close(n.popBottom.index),e(document).off("touchend",R.faceHide).off("click",R.faceHide)},image:function(a){var i=a.data("type")||"images",e={images:"uploadImage",file:"uploadFile"},t=L(),l=w.base[e[i]]||{};layui.upload.render({url:l.url||"",method:l.type,elem:a.find("input")[0],accept:i,done:function(a){0==a.code?(a.data=a.data||{},"images"===i?E(t.textarea[0],"img["+(a.data.src||"")+"]"):"file"===i&&E(t.textarea[0],"file("+(a.data.src||"")+")["+(a.data.name||"\u4e0b\u8f7d\u6587\u4ef6")+"]"),H()):n.msg(a.msg||"\u4e0a\u4f20\u5931\u8d25")}})},extend:function(a){var i=a.attr("lay-filter"),e=L();layui.each(d["tool("+i+")"],function(i,t){t&&t.call(a,function(a){E(e.textarea[0],a)},H,e)})},newFriend:function(){layui.each(d.newFriend,function(a,i){i&&i()})},group:function(){A({title:"\u7fa4\u804a",tpl:['
                                ',y({type:"group",item:"d.group"}),"
                                "].join(""),data:{}})},detail:function(){var a=L();layui.each(d.detail,function(i,e){e&&e(a.data)})},playAudio:function(a){var i=a.data("audio"),e=i||document.createElement("audio"),t=function(){e.pause(),a.removeAttr("status"),a.find("i").html("")};return a.data("error")?n.msg("\u64ad\u653e\u97f3\u9891\u6e90\u5f02\u5e38"):e.play?void(a.attr("status")?t():(i||(e.src=a.data("src")),e.play(),a.attr("status","pause"),a.data("audio",e),a.find("i").html(""),e.onended=function(){t()},e.onerror=function(){n.msg("\u64ad\u653e\u97f3\u9891\u6e90\u5f02\u5e38"),a.data("error",!0),t()})):n.msg("\u60a8\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301audio")},playVideo:function(a){var i=a.data("src"),e=document.createElement("video");return e.play?(n.close(R.playVideo.index),void(R.playVideo.index=n.open({type:1,anim:!1,style:"width: 100%; height: 50%;",content:'
                                '}))):n.msg("\u60a8\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301video")},chatLog:function(a){var i=L();layui.each(d.chatlog,function(a,e){e&&e(i.data,i.elem.find(".layim-chat-main>ul"))})},moreList:function(a){var i=a.attr("lay-filter");layui.each(d.moreList,function(a,e){e&&e({alias:i})})},about:function(){n.open({content:'

                                \u7248\u672c\uff1a v'+i+"

                                ",className:"layim-about",shadeClose:!1,btn:"\u6211\u77e5\u9053\u4e86"})}};a("layim-mobile",new r)}).link(layui.cache.layimAssetsPath+"mobile.css","skinlayim-mobilecss"); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/zepto.js b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/zepto.js deleted file mode 100644 index 6d8e6439..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/lib/zepto.js +++ /dev/null @@ -1,2 +0,0 @@ -/** WebIMUI-v3.9.8 */ - ;layui.define(function(t){var e=function(){function t(t){return null==t?String(t):J[W.call(t)]||"object"}function e(e){return"function"==t(e)}function n(t){return null!=t&&t==t.window}function r(t){return null!=t&&t.nodeType==t.DOCUMENT_NODE}function i(e){return"object"==t(e)}function o(t){return i(t)&&!n(t)&&Object.getPrototypeOf(t)==Object.prototype}function a(t){var e=!!t&&"length"in t&&t.length,r=T.type(t);return"function"!=r&&!n(t)&&("array"==r||0===e||"number"==typeof e&&e>0&&e-1 in t)}function s(t){return A.call(t,function(t){return null!=t})}function u(t){return t.length>0?T.fn.concat.apply([],t):t}function c(t){return t.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function l(t){return t in F?F[t]:F[t]=new RegExp("(^|\\s)"+t+"(\\s|$)")}function f(t,e){return"number"!=typeof e||k[c(t)]?e:e+"px"}function h(t){var e,n;return $[t]||(e=L.createElement(t),L.body.appendChild(e),n=getComputedStyle(e,"").getPropertyValue("display"),e.parentNode.removeChild(e),"none"==n&&(n="block"),$[t]=n),$[t]}function p(t){return"children"in t?D.call(t.children):T.map(t.childNodes,function(t){if(1==t.nodeType)return t})}function d(t,e){var n,r=t?t.length:0;for(n=0;n]*>/,R=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,Z=/^(?:body|html)$/i,q=/([A-Z])/g,H=["val","css","html","text","data","width","height","offset"],I=["after","prepend","before","append"],V=L.createElement("table"),_=L.createElement("tr"),B={tr:L.createElement("tbody"),tbody:V,thead:V,tfoot:V,td:_,th:_,"*":L.createElement("div")},U=/complete|loaded|interactive/,X=/^[\w-]*$/,J={},W=J.toString,Y={},G=L.createElement("div"),K={tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},Q=Array.isArray||function(t){return t instanceof Array};return Y.matches=function(t,e){if(!e||!t||1!==t.nodeType)return!1;var n=t.matches||t.webkitMatchesSelector||t.mozMatchesSelector||t.oMatchesSelector||t.matchesSelector;if(n)return n.call(t,e);var r,i=t.parentNode,o=!i;return o&&(i=G).appendChild(t),r=~Y.qsa(i,e).indexOf(t),o&&G.removeChild(t),r},C=function(t){return t.replace(/-+(.)?/g,function(t,e){return e?e.toUpperCase():""})},N=function(t){return A.call(t,function(e,n){return t.indexOf(e)==n})},Y.fragment=function(t,e,n){var r,i,a;return R.test(t)&&(r=T(L.createElement(RegExp.$1))),r||(t.replace&&(t=t.replace(z,"<$1>")),e===E&&(e=M.test(t)&&RegExp.$1),e in B||(e="*"),a=B[e],a.innerHTML=""+t,r=T.each(D.call(a.childNodes),function(){a.removeChild(this)})),o(n)&&(i=T(r),T.each(n,function(t,e){H.indexOf(t)>-1?i[t](e):i.attr(t,e)})),r},Y.Z=function(t,e){return new d(t,e)},Y.isZ=function(t){return t instanceof Y.Z},Y.init=function(t,n){var r;if(!t)return Y.Z();if("string"==typeof t)if(t=t.trim(),"<"==t[0]&&M.test(t))r=Y.fragment(t,RegExp.$1,n),t=null;else{if(n!==E)return T(n).find(t);r=Y.qsa(L,t)}else{if(e(t))return T(L).ready(t);if(Y.isZ(t))return t;if(Q(t))r=s(t);else if(i(t))r=[t],t=null;else if(M.test(t))r=Y.fragment(t.trim(),RegExp.$1,n),t=null;else{if(n!==E)return T(n).find(t);r=Y.qsa(L,t)}}return Y.Z(r,t)},T=function(t,e){return Y.init(t,e)},T.extend=function(t){var e,n=D.call(arguments,1);return"boolean"==typeof t&&(e=t,t=n.shift()),n.forEach(function(n){m(t,n,e)}),t},Y.qsa=function(t,e){var n,r="#"==e[0],i=!r&&"."==e[0],o=r||i?e.slice(1):e,a=X.test(o);return t.getElementById&&a&&r?(n=t.getElementById(o))?[n]:[]:1!==t.nodeType&&9!==t.nodeType&&11!==t.nodeType?[]:D.call(a&&!r&&t.getElementsByClassName?i?t.getElementsByClassName(o):t.getElementsByTagName(e):t.querySelectorAll(e))},T.contains=L.documentElement.contains?function(t,e){return t!==e&&t.contains(e)}:function(t,e){for(;e&&(e=e.parentNode);)if(e===t)return!0;return!1},T.type=t,T.isFunction=e,T.isWindow=n,T.isArray=Q,T.isPlainObject=o,T.isEmptyObject=function(t){var e;for(e in t)return!1;return!0},T.isNumeric=function(t){var e=Number(t),n=typeof t;return null!=t&&"boolean"!=n&&("string"!=n||t.length)&&!isNaN(e)&&isFinite(e)||!1},T.inArray=function(t,e,n){return O.indexOf.call(e,t,n)},T.camelCase=C,T.trim=function(t){return null==t?"":String.prototype.trim.call(t)},T.uuid=0,T.support={},T.expr={},T.noop=function(){},T.map=function(t,e){var n,r,i,o=[];if(a(t))for(r=0;r=0?t:t+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){null!=this.parentNode&&this.parentNode.removeChild(this)})},each:function(t){return O.every.call(this,function(e,n){return t.call(e,n,e)!==!1}),this},filter:function(t){return e(t)?this.not(this.not(t)):T(A.call(this,function(e){return Y.matches(e,t)}))},add:function(t,e){return T(N(this.concat(T(t,e))))},is:function(t){return this.length>0&&Y.matches(this[0],t)},not:function(t){var n=[];if(e(t)&&t.call!==E)this.each(function(e){t.call(this,e)||n.push(this)});else{var r="string"==typeof t?this.filter(t):a(t)&&e(t.item)?D.call(t):T(t);this.forEach(function(t){r.indexOf(t)<0&&n.push(t)})}return T(n)},has:function(t){return this.filter(function(){return i(t)?T.contains(this,t):T(this).find(t).size()})},eq:function(t){return t===-1?this.slice(t):this.slice(t,+t+1)},first:function(){var t=this[0];return t&&!i(t)?t:T(t)},last:function(){var t=this[this.length-1];return t&&!i(t)?t:T(t)},find:function(t){var e,n=this;return e=t?"object"==typeof t?T(t).filter(function(){var t=this;return O.some.call(n,function(e){return T.contains(e,t)})}):1==this.length?T(Y.qsa(this[0],t)):this.map(function(){return Y.qsa(this,t)}):T()},closest:function(t,e){var n=[],i="object"==typeof t&&T(t);return this.each(function(o,a){for(;a&&!(i?i.indexOf(a)>=0:Y.matches(a,t));)a=a!==e&&!r(a)&&a.parentNode;a&&n.indexOf(a)<0&&n.push(a)}),T(n)},parents:function(t){for(var e=[],n=this;n.length>0;)n=T.map(n,function(t){if((t=t.parentNode)&&!r(t)&&e.indexOf(t)<0)return e.push(t),t});return v(e,t)},parent:function(t){return v(N(this.pluck("parentNode")),t)},children:function(t){return v(this.map(function(){return p(this)}),t)},contents:function(){return this.map(function(){return this.contentDocument||D.call(this.childNodes)})},siblings:function(t){return v(this.map(function(t,e){return A.call(p(e.parentNode),function(t){return t!==e})}),t)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(t){return T.map(this,function(e){return e[t]})},show:function(){return this.each(function(){"none"==this.style.display&&(this.style.display=""),"none"==getComputedStyle(this,"").getPropertyValue("display")&&(this.style.display=h(this.nodeName))})},replaceWith:function(t){return this.before(t).remove()},wrap:function(t){var n=e(t);if(this[0]&&!n)var r=T(t).get(0),i=r.parentNode||this.length>1;return this.each(function(e){T(this).wrapAll(n?t.call(this,e):i?r.cloneNode(!0):r)})},wrapAll:function(t){if(this[0]){T(this[0]).before(t=T(t));for(var e;(e=t.children()).length;)t=e.first();T(t).append(this)}return this},wrapInner:function(t){var n=e(t);return this.each(function(e){var r=T(this),i=r.contents(),o=n?t.call(this,e):t;i.length?i.wrapAll(o):r.append(o)})},unwrap:function(){return this.parent().each(function(){T(this).replaceWith(T(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(t){return this.each(function(){var e=T(this);(t===E?"none"==e.css("display"):t)?e.show():e.hide()})},prev:function(t){return T(this.pluck("previousElementSibling")).filter(t||"*")},next:function(t){return T(this.pluck("nextElementSibling")).filter(t||"*")},html:function(t){return 0 in arguments?this.each(function(e){var n=this.innerHTML;T(this).empty().append(g(this,t,e,n))}):0 in this?this[0].innerHTML:null},text:function(t){return 0 in arguments?this.each(function(e){var n=g(this,t,e,this.textContent);this.textContent=null==n?"":""+n}):0 in this?this.pluck("textContent").join(""):null},attr:function(t,e){var n;return"string"!=typeof t||1 in arguments?this.each(function(n){if(1===this.nodeType)if(i(t))for(j in t)y(this,j,t[j]);else y(this,t,g(this,e,n,this.getAttribute(t)))}):0 in this&&1==this[0].nodeType&&null!=(n=this[0].getAttribute(t))?n:E},removeAttr:function(t){return this.each(function(){1===this.nodeType&&t.split(" ").forEach(function(t){y(this,t)},this)})},prop:function(t,e){return t=K[t]||t,1 in arguments?this.each(function(n){this[t]=g(this,e,n,this[t])}):this[0]&&this[0][t]},removeProp:function(t){return t=K[t]||t,this.each(function(){delete this[t]})},data:function(t,e){var n="data-"+t.replace(q,"-$1").toLowerCase(),r=1 in arguments?this.attr(n,e):this.attr(n);return null!==r?b(r):E},val:function(t){return 0 in arguments?(null==t&&(t=""),this.each(function(e){this.value=g(this,t,e,this.value)})):this[0]&&(this[0].multiple?T(this[0]).find("option").filter(function(){return this.selected}).pluck("value"):this[0].value)},offset:function(t){if(t)return this.each(function(e){var n=T(this),r=g(this,t,e,n.offset()),i=n.offsetParent().offset(),o={top:r.top-i.top,left:r.left-i.left};"static"==n.css("position")&&(o.position="relative"),n.css(o)});if(!this.length)return null;if(L.documentElement!==this[0]&&!T.contains(L.documentElement,this[0]))return{top:0,left:0};var e=this[0].getBoundingClientRect();return{left:e.left+window.pageXOffset,top:e.top+window.pageYOffset,width:Math.round(e.width),height:Math.round(e.height)}},css:function(e,n){if(arguments.length<2){var r=this[0];if("string"==typeof e){if(!r)return;return r.style[C(e)]||getComputedStyle(r,"").getPropertyValue(e)}if(Q(e)){if(!r)return;var i={},o=getComputedStyle(r,"");return T.each(e,function(t,e){i[e]=r.style[C(e)]||o.getPropertyValue(e)}),i}}var a="";if("string"==t(e))n||0===n?a=c(e)+":"+f(e,n):this.each(function(){this.style.removeProperty(c(e))});else for(j in e)e[j]||0===e[j]?a+=c(j)+":"+f(j,e[j])+";":this.each(function(){this.style.removeProperty(c(j))});return this.each(function(){this.style.cssText+=";"+a})},index:function(t){return t?this.indexOf(T(t)[0]):this.parent().children().indexOf(this[0])},hasClass:function(t){return!!t&&O.some.call(this,function(t){return this.test(x(t))},l(t))},addClass:function(t){return t?this.each(function(e){if("className"in this){S=[];var n=x(this),r=g(this,t,e,n);r.split(/\s+/g).forEach(function(t){T(this).hasClass(t)||S.push(t)},this),S.length&&x(this,n+(n?" ":"")+S.join(" "))}}):this},removeClass:function(t){return this.each(function(e){if("className"in this){if(t===E)return x(this,"");S=x(this),g(this,t,e,S).split(/\s+/g).forEach(function(t){S=S.replace(l(t)," ")}),x(this,S.trim())}})},toggleClass:function(t,e){return t?this.each(function(n){var r=T(this),i=g(this,t,n,x(this));i.split(/\s+/g).forEach(function(t){(e===E?!r.hasClass(t):e)?r.addClass(t):r.removeClass(t)})}):this},scrollTop:function(t){if(this.length){var e="scrollTop"in this[0];return t===E?e?this[0].scrollTop:this[0].pageYOffset:this.each(e?function(){this.scrollTop=t}:function(){this.scrollTo(this.scrollX,t)})}},scrollLeft:function(t){if(this.length){var e="scrollLeft"in this[0];return t===E?e?this[0].scrollLeft:this[0].pageXOffset:this.each(e?function(){this.scrollLeft=t}:function(){this.scrollTo(t,this.scrollY)})}},position:function(){if(this.length){var t=this[0],e=this.offsetParent(),n=this.offset(),r=Z.test(e[0].nodeName)?{top:0,left:0}:e.offset();return n.top-=parseFloat(T(t).css("margin-top"))||0,n.left-=parseFloat(T(t).css("margin-left"))||0,r.top+=parseFloat(T(e[0]).css("border-top-width"))||0,r.left+=parseFloat(T(e[0]).css("border-left-width"))||0,{top:n.top-r.top,left:n.left-r.left}}},offsetParent:function(){return this.map(function(){for(var t=this.offsetParent||L.body;t&&!Z.test(t.nodeName)&&"static"==T(t).css("position");)t=t.offsetParent;return t})}},T.fn.detach=T.fn.remove,["width","height"].forEach(function(t){var e=t.replace(/./,function(t){return t[0].toUpperCase()});T.fn[t]=function(i){var o,a=this[0];return i===E?n(a)?a["inner"+e]:r(a)?a.documentElement["scroll"+e]:(o=this.offset())&&o[t]:this.each(function(e){a=T(this),a.css(t,g(this,i,e,a[t]()))})}}),I.forEach(function(e,n){var r=n%2;T.fn[e]=function(){var e,i,o=T.map(arguments,function(n){var r=[];return e=t(n),"array"==e?(n.forEach(function(t){return t.nodeType!==E?r.push(t):T.zepto.isZ(t)?r=r.concat(t.get()):void(r=r.concat(Y.fragment(t)))}),r):"object"==e||null==n?n:Y.fragment(n)}),a=this.length>1;return o.length<1?this:this.each(function(t,e){i=r?e:e.parentNode,e=0==n?e.nextSibling:1==n?e.firstChild:2==n?e:null;var s=T.contains(L.documentElement,i);o.forEach(function(t){if(a)t=t.cloneNode(!0);else if(!i)return T(t).remove();i.insertBefore(t,e),s&&w(t,function(t){if(!(null==t.nodeName||"SCRIPT"!==t.nodeName.toUpperCase()||t.type&&"text/javascript"!==t.type||t.src)){var e=t.ownerDocument?t.ownerDocument.defaultView:window;e.eval.call(e,t.innerHTML)}})})})},T.fn[r?e+"To":"insert"+(n?"Before":"After")]=function(t){return T(t)[e](this),this}}),Y.Z.prototype=d.prototype=T.fn,Y.uniq=N,Y.deserializeValue=b,T.zepto=Y,T}();!function(t){function e(t){return t._zid||(t._zid=h++)}function n(t,n,o,a){if(n=r(n),n.ns)var s=i(n.ns);return(v[e(t)]||[]).filter(function(t){return t&&(!n.e||t.e==n.e)&&(!n.ns||s.test(t.ns))&&(!o||e(t.fn)===e(o))&&(!a||t.sel==a)})}function r(t){var e=(""+t).split(".");return{e:e[0],ns:e.slice(1).sort().join(" ")}}function i(t){return new RegExp("(?:^| )"+t.replace(" "," .* ?")+"(?: |$)")}function o(t,e){return t.del&&!y&&t.e in x||!!e}function a(t){return b[t]||y&&x[t]||t}function s(n,i,s,u,l,h,p){var d=e(n),m=v[d]||(v[d]=[]);i.split(/\s/).forEach(function(e){if("ready"==e)return t(document).ready(s);var i=r(e);i.fn=s,i.sel=l,i.e in b&&(s=function(e){var n=e.relatedTarget;if(!n||n!==this&&!t.contains(this,n))return i.fn.apply(this,arguments)}),i.del=h;var d=h||s;i.proxy=function(t){if(t=c(t),!t.isImmediatePropagationStopped()){t.data=u;var e=d.apply(n,t._args==f?[t]:[t].concat(t._args));return e===!1&&(t.preventDefault(),t.stopPropagation()),e}},i.i=m.length,m.push(i),"addEventListener"in n&&n.addEventListener(a(i.e),i.proxy,o(i,p))})}function u(t,r,i,s,u){var c=e(t);(r||"").split(/\s/).forEach(function(e){n(t,e,i,s).forEach(function(e){delete v[c][e.i],"removeEventListener"in t&&t.removeEventListener(a(e.e),e.proxy,o(e,u))})})}function c(e,n){return!n&&e.isDefaultPrevented||(n||(n=e),t.each(T,function(t,r){var i=n[t];e[t]=function(){return this[r]=w,i&&i.apply(n,arguments)},e[r]=E}),e.timeStamp||(e.timeStamp=Date.now()),(n.defaultPrevented!==f?n.defaultPrevented:"returnValue"in n?n.returnValue===!1:n.getPreventDefault&&n.getPreventDefault())&&(e.isDefaultPrevented=w)),e}function l(t){var e,n={originalEvent:t};for(e in t)j.test(e)||t[e]===f||(n[e]=t[e]);return c(n,t)}var f,h=1,p=Array.prototype.slice,d=t.isFunction,m=function(t){return"string"==typeof t},v={},g={},y="onfocusin"in window,x={focus:"focusin",blur:"focusout"},b={mouseenter:"mouseover",mouseleave:"mouseout"};g.click=g.mousedown=g.mouseup=g.mousemove="MouseEvents",t.event={add:s,remove:u},t.proxy=function(n,r){var i=2 in arguments&&p.call(arguments,2);if(d(n)){var o=function(){return n.apply(r,i?i.concat(p.call(arguments)):arguments)};return o._zid=e(n),o}if(m(r))return i?(i.unshift(n[r],n),t.proxy.apply(null,i)):t.proxy(n[r],n);throw new TypeError("expected function")},t.fn.bind=function(t,e,n){return this.on(t,e,n)},t.fn.unbind=function(t,e){return this.off(t,e)},t.fn.one=function(t,e,n,r){return this.on(t,e,n,r,1)};var w=function(){return!0},E=function(){return!1},j=/^([A-Z]|returnValue$|layer[XY]$|webkitMovement[XY]$)/,T={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};t.fn.delegate=function(t,e,n){return this.on(e,t,n)},t.fn.undelegate=function(t,e,n){return this.off(e,t,n)},t.fn.live=function(e,n){return t(document.body).delegate(this.selector,e,n),this},t.fn.die=function(e,n){return t(document.body).undelegate(this.selector,e,n),this},t.fn.on=function(e,n,r,i,o){var a,c,h=this;return e&&!m(e)?(t.each(e,function(t,e){h.on(t,n,r,e,o)}),h):(m(n)||d(i)||i===!1||(i=r,r=n,n=f),i!==f&&r!==!1||(i=r,r=f),i===!1&&(i=E),h.each(function(f,h){o&&(a=function(t){return u(h,t.type,i),i.apply(this,arguments)}),n&&(c=function(e){var r,o=t(e.target).closest(n,h).get(0);if(o&&o!==h)return r=t.extend(l(e),{currentTarget:o,liveFired:h}),(a||i).apply(o,[r].concat(p.call(arguments,1)))}),s(h,e,i,r,n,c||a)}))},t.fn.off=function(e,n,r){var i=this;return e&&!m(e)?(t.each(e,function(t,e){i.off(t,n,e)}),i):(m(n)||d(r)||r===!1||(r=n,n=f),r===!1&&(r=E),i.each(function(){u(this,e,r,n)}))},t.fn.trigger=function(e,n){return e=m(e)||t.isPlainObject(e)?t.Event(e):c(e),e._args=n,this.each(function(){e.type in x&&"function"==typeof this[e.type]?this[e.type]():"dispatchEvent"in this?this.dispatchEvent(e):t(this).triggerHandler(e,n)})},t.fn.triggerHandler=function(e,r){var i,o;return this.each(function(a,s){i=l(m(e)?t.Event(e):e),i._args=r,i.target=s,t.each(n(s,e.type||e),function(t,e){if(o=e.proxy(i),i.isImmediatePropagationStopped())return!1})}),o},"focusin focusout focus blur load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(e){t.fn[e]=function(t){return 0 in arguments?this.bind(e,t):this.trigger(e)}}),t.Event=function(t,e){m(t)||(e=t,t=e.type);var n=document.createEvent(g[t]||"Events"),r=!0;if(e)for(var i in e)"bubbles"==i?r=!!e[i]:n[i]=e[i];return n.initEvent(t,r,!0),c(n)}}(e),function(t){function e(e,n,r){var i=t.Event(n);return t(e).trigger(i,r),!i.isDefaultPrevented()}function n(t,n,r,i){if(t.global)return e(n||x,r,i)}function r(e){e.global&&0===t.active++&&n(e,null,"ajaxStart")}function i(e){e.global&&!--t.active&&n(e,null,"ajaxStop")}function o(t,e){var r=e.context;return e.beforeSend.call(r,t,e)!==!1&&n(e,r,"ajaxBeforeSend",[t,e])!==!1&&void n(e,r,"ajaxSend",[t,e])}function a(t,e,r,i){var o=r.context,a="success";r.success.call(o,t,a,e),i&&i.resolveWith(o,[t,a,e]),n(r,o,"ajaxSuccess",[e,r,t]),u(a,e,r)}function s(t,e,r,i,o){var a=i.context;i.error.call(a,r,e,t),o&&o.rejectWith(a,[r,e,t]),n(i,a,"ajaxError",[r,i,t||e]),u(e,r,i)}function u(t,e,r){var o=r.context;r.complete.call(o,e,t),n(r,o,"ajaxComplete",[e,r]),i(r)}function c(t,e,n){if(n.dataFilter==l)return t;var r=n.context;return n.dataFilter.call(r,t,e)}function l(){}function f(t){return t&&(t=t.split(";",2)[0]),t&&(t==T?"html":t==j?"json":w.test(t)?"script":E.test(t)&&"xml")||"text"}function h(t,e){return""==e?t:(t+"&"+e).replace(/[&?]{1,2}/,"?")}function p(e){e.processData&&e.data&&"string"!=t.type(e.data)&&(e.data=t.param(e.data,e.traditional)),!e.data||e.type&&"GET"!=e.type.toUpperCase()&&"jsonp"!=e.dataType||(e.url=h(e.url,e.data),e.data=void 0)}function d(e,n,r,i){return t.isFunction(n)&&(i=r,r=n,n=void 0),t.isFunction(r)||(i=r,r=void 0),{url:e,data:n,success:r,dataType:i}}function m(e,n,r,i){var o,a=t.isArray(n),s=t.isPlainObject(n);t.each(n,function(n,u){o=t.type(u),i&&(n=r?i:i+"["+(s||"object"==o||"array"==o?n:"")+"]"),!i&&a?e.add(u.name,u.value):"array"==o||!r&&"object"==o?m(e,u,r,n):e.add(n,u)})}var v,g,y=+new Date,x=window.document,b=/)<[^<]*)*<\/script>/gi,w=/^(?:text|application)\/javascript/i,E=/^(?:text|application)\/xml/i,j="application/json",T="text/html",S=/^\s*$/,C=x.createElement("a");C.href=window.location.href,t.active=0,t.ajaxJSONP=function(e,n){if(!("type"in e))return t.ajax(e);var r,i,u=e.jsonpCallback,c=(t.isFunction(u)?u():u)||"Zepto"+y++,l=x.createElement("script"),f=window[c],h=function(e){t(l).triggerHandler("error",e||"abort")},p={abort:h};return n&&n.promise(p),t(l).on("load error",function(o,u){clearTimeout(i),t(l).off().remove(),"error"!=o.type&&r?a(r[0],p,e,n):s(null,u||"error",p,e,n),window[c]=f,r&&t.isFunction(f)&&f(r[0]),f=r=void 0}),o(p,e)===!1?(h("abort"),p):(window[c]=function(){r=arguments},l.src=e.url.replace(/\?(.+)=\?/,"?$1="+c),x.head.appendChild(l),e.timeout>0&&(i=setTimeout(function(){h("timeout")},e.timeout)),p)},t.ajaxSettings={type:"GET",beforeSend:l,success:l,error:l,complete:l,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript, application/x-javascript",json:j,xml:"application/xml, text/xml",html:T,text:"text/plain"},crossDomain:!1,timeout:0,processData:!0,cache:!0,dataFilter:l},t.ajax=function(e){var n,i,u=t.extend({},e||{}),d=t.Deferred&&t.Deferred();for(v in t.ajaxSettings)void 0===u[v]&&(u[v]=t.ajaxSettings[v]);r(u),u.crossDomain||(n=x.createElement("a"),n.href=u.url,n.href=n.href,u.crossDomain=C.protocol+"//"+C.host!=n.protocol+"//"+n.host),u.url||(u.url=window.location.toString()),(i=u.url.indexOf("#"))>-1&&(u.url=u.url.slice(0,i)),p(u);var m=u.dataType,y=/\?.+=\?/.test(u.url);if(y&&(m="jsonp"),u.cache!==!1&&(e&&e.cache===!0||"script"!=m&&"jsonp"!=m)||(u.url=h(u.url,"_="+Date.now())),"jsonp"==m)return y||(u.url=h(u.url,u.jsonp?u.jsonp+"=?":u.jsonp===!1?"":"callback=?")),t.ajaxJSONP(u,d);var b,w=u.accepts[m],E={},j=function(t,e){E[t.toLowerCase()]=[t,e]},T=/^([\w-]+:)\/\//.test(u.url)?RegExp.$1:window.location.protocol,N=u.xhr(),O=N.setRequestHeader;if(d&&d.promise(N),u.crossDomain||j("X-Requested-With","XMLHttpRequest"),j("Accept",w||"*/*"),(w=u.mimeType||w)&&(w.indexOf(",")>-1&&(w=w.split(",",2)[0]),N.overrideMimeType&&N.overrideMimeType(w)),(u.contentType||u.contentType!==!1&&u.data&&"GET"!=u.type.toUpperCase())&&j("Content-Type",u.contentType||"application/x-www-form-urlencoded"),u.headers)for(g in u.headers)j(g,u.headers[g]);if(N.setRequestHeader=j,N.onreadystatechange=function(){if(4==N.readyState){N.onreadystatechange=l,clearTimeout(b);var e,n=!1;if(N.status>=200&&N.status<300||304==N.status||0==N.status&&"file:"==T){if(m=m||f(u.mimeType||N.getResponseHeader("content-type")),"arraybuffer"==N.responseType||"blob"==N.responseType)e=N.response;else{e=N.responseText;try{e=c(e,m,u),"script"==m?(0,eval)(e):"xml"==m?e=N.responseXML:"json"==m&&(e=S.test(e)?null:t.parseJSON(e))}catch(r){n=r}if(n)return s(n,"parsererror",N,u,d)}a(e,N,u,d)}else s(N.statusText||null,N.status?"error":"abort",N,u,d)}},o(N,u)===!1)return N.abort(),s(null,"abort",N,u,d),N;var P=!("async"in u)||u.async;if(N.open(u.type,u.url,P,u.username,u.password),u.xhrFields)for(g in u.xhrFields)N[g]=u.xhrFields[g];for(g in E)O.apply(N,E[g]);return u.timeout>0&&(b=setTimeout(function(){N.onreadystatechange=l,N.abort(),s(null,"timeout",N,u,d)},u.timeout)),N.send(u.data?u.data:null),N},t.get=function(){return t.ajax(d.apply(null,arguments))},t.post=function(){var e=d.apply(null,arguments);return e.type="POST",t.ajax(e)},t.getJSON=function(){var e=d.apply(null,arguments);return e.dataType="json",t.ajax(e)},t.fn.load=function(e,n,r){if(!this.length)return this;var i,o=this,a=e.split(/\s/),s=d(e,n,r),u=s.success;return a.length>1&&(s.url=a[0],i=a[1]),s.success=function(e){o.html(i?t("
                                ").html(e.replace(b,"")).find(i):e),u&&u.apply(o,arguments)},t.ajax(s),this};var N=encodeURIComponent;t.param=function(e,n){var r=[];return r.add=function(e,n){t.isFunction(n)&&(n=n()),null==n&&(n=""),this.push(N(e)+"="+N(n))},m(r,e,n),r.join("&").replace(/%20/g,"+")}}(e),function(t){t.fn.serializeArray=function(){var e,n,r=[],i=function(t){return t.forEach?t.forEach(i):void r.push({name:e,value:t})};return this[0]&&t.each(this[0].elements,function(r,o){n=o.type,e=o.name,e&&"fieldset"!=o.nodeName.toLowerCase()&&!o.disabled&&"submit"!=n&&"reset"!=n&&"button"!=n&&"file"!=n&&("radio"!=n&&"checkbox"!=n||o.checked)&&i(t(o).val())}),r},t.fn.serialize=function(){var t=[];return this.serializeArray().forEach(function(e){t.push(encodeURIComponent(e.name)+"="+encodeURIComponent(e.value))}),t.join("&")},t.fn.submit=function(e){if(0 in arguments)this.bind("submit",e);else if(this.length){var n=t.Event("submit");this.eq(0).trigger(n),n.isDefaultPrevented()||this.get(0).submit()}return this}}(e),function(){try{getComputedStyle(void 0)}catch(t){var e=getComputedStyle;window.getComputedStyle=function(t,n){try{return e(t,n)}catch(r){return null}}}}(),t("zepto",e)}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/mobile.css b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/mobile.css deleted file mode 100644 index 5a7c113d..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/mobile.css +++ /dev/null @@ -1,2 +0,0 @@ -/** WebIMUI-v3.9.8 */ - .layim-panel,.layui-m-layerchild{-webkit-animation-fill-mode:both}html #layuicss-skinlayim-mobilecss{display:none;position:absolute;width:1989px}blockquote,body,button,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,input,legend,li,ol,p,td,textarea,th,ul{margin:0;padding:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}html{font:12px 'Helvetica Neue','PingFang SC',STHeitiSC-Light,Helvetica,Arial,sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}a,button,input{-webkit-tap-highlight-color:rgba(255,0,0,0)}a{text-decoration:none;background:0 0}a:active,a:hover{outline:0}table{border-collapse:collapse;border-spacing:0}li{list-style:none}b,strong{font-weight:700}h1,h2,h3,h4,h5,h6{font-weight:500}address,cite,dfn,em,var{font-style:normal}dfn{font-style:italic}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}img{border:0;vertical-align:bottom}.layui-inline,input,label{vertical-align:middle}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0;outline:0}button,select{text-transform:none}select{-webkit-appearance:none;border:none}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}.layui-box,.layui-box *{-webkit-box-sizing:content-box!important;-moz-box-sizing:content-box!important;box-sizing:content-box!important}.layim-chat-main,.layui-border-box,.layui-border-box *{-webkit-box-sizing:border-box!important;-moz-box-sizing:border-box!important}.layui-border-box,.layui-border-box *{box-sizing:border-box!important}.layui-inline{position:relative;display:inline-block;*display:inline;*zoom:1}.layui-edge,.layui-upload-iframe{position:absolute;width:0;height:0}.layui-edge{border-style:dashed;border-color:transparent;overflow:hidden}.layui-elip{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-unselect{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-disabled,.layui-disabled:active{background-color:#d2d2d2!important;color:#fff!important;cursor:not-allowed!important}.layui-circle{border-radius:100%}.layui-show{display:block!important}.layui-hide{display:none!important}.layui-upload-iframe{border:0;visibility:hidden}.layui-upload-enter{border:1px solid #009E94;background-color:#009E94;color:#fff;-webkit-transform:scale(1.1);transform:scale(1.1)}@-webkit-keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}.layui-m-anim-scale{animation-name:layui-m-anim-scale;-webkit-animation-name:layui-m-anim-scale}@-webkit-keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}.layui-m-anim-up{-webkit-animation-name:layui-m-anim-up;animation-name:layui-m-anim-up}@-webkit-keyframes layui-m-anim-left{0%{-webkit-transform:translateX(100%);transform:translateX(100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes layui-m-anim-left{0%{-webkit-transform:translateX(100%);transform:translateX(100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}.layui-m-anim-left{-webkit-animation-name:layui-m-anim-left;animation-name:layui-m-anim-left}@-webkit-keyframes layui-m-anim-right{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes layui-m-anim-right{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}.layui-m-anim-right{-webkit-animation-name:layui-m-anim-right;animation-name:layui-m-anim-right}@-webkit-keyframes layui-m-anim-lout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}@keyframes layui-m-anim-lout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}.layui-m-anim-lout{-webkit-animation-name:layui-m-anim-lout;animation-name:layui-m-anim-lout}@-webkit-keyframes layui-m-anim-rout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(100%);transform:translateX(100%)}}@keyframes layui-m-anim-rout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(100%);transform:translateX(100%)}}.layui-m-anim-rout{-webkit-animation-name:layui-m-anim-rout;animation-name:layui-m-anim-rout}.layui-m-layer{position:relative;z-index:19891014}.layui-m-layer *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.layui-m-layermain,.layui-m-layershade{position:fixed;left:0;top:0;width:100%;height:100%}.layui-m-layershade{background-color:rgba(0,0,0,.7);pointer-events:auto}.layui-m-layermain{display:table;font-family:Helvetica,arial,sans-serif;pointer-events:none}.layui-m-layermain .layui-m-layersection{display:table-cell;vertical-align:middle;text-align:center}.layui-m-layerchild{position:relative;display:inline-block;text-align:left;background-color:#fff;font-size:14px;border-radius:5px;box-shadow:0 0 8px rgba(0,0,0,.1);pointer-events:auto;-webkit-overflow-scrolling:touch;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}.layim-tab-content li h5 span,.layui-layim-list li p,.layui-layim-list li span,.layui-m-layerbtn span,.layui-m-layerchild h3{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.layui-m-layer0 .layui-m-layerchild{width:90%;max-width:640px}.layui-m-layer1 .layui-m-layerchild{border:none;border-radius:0}.layui-m-layer2 .layui-m-layerchild{width:auto;max-width:260px;min-width:40px;border:none;background:0 0;box-shadow:none;color:#fff}.layui-m-layerchild h3{padding:0 10px;height:60px;line-height:60px;font-size:16px;font-weight:400;border-radius:5px 5px 0 0;text-align:center}.layui-m-layercont{padding:50px 30px;line-height:22px;text-align:center}.layui-m-layer1 .layui-m-layercont{padding:0;text-align:left}.layui-m-layer2 .layui-m-layercont{text-align:center;padding:0;line-height:0}.layui-m-layer2 .layui-m-layercont i{width:25px;height:25px;margin-left:8px;display:inline-block;background-color:#fff;border-radius:100%;-webkit-animation:layui-m-anim-loading 1.4s infinite ease-in-out;animation:layui-m-anim-loading 1.4s infinite ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-m-layerbtn,.layui-m-layerbtn span{position:relative;border-radius:0 0 5px 5px;text-align:center}.layui-m-layer2 .layui-m-layercont p{margin-top:20px}@-webkit-keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}@keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}.layui-m-layer2 .layui-m-layercont i:first-child{margin-left:0;-webkit-animation-delay:-.32s;animation-delay:-.32s}.layui-m-layer2 .layui-m-layercont i.layui-m-layerload{-webkit-animation-delay:-.16s;animation-delay:-.16s}.layui-m-layer2 .layui-m-layercont>div{line-height:22px;padding-top:7px;margin-bottom:20px;font-size:14px}.layui-m-layerbtn{display:box;display:-moz-box;display:-webkit-box;width:100%;height:50px;line-height:50px;font-size:0;border-top:1px solid #D0D0D0;background-color:#F2F2F2}.layui-m-layerbtn span{display:block;-moz-box-flex:1;box-flex:1;-webkit-box-flex:1;font-size:14px;cursor:pointer}.layui-m-layerbtn span[yes]{color:#40AFFE}.layui-m-layerbtn span[no]{border-right:1px solid #D0D0D0;border-radius:0 0 0 5px}.layui-m-layerbtn span:active{background-color:#F6F6F6}.layui-m-layerend{position:absolute;right:7px;top:10px;width:30px;height:30px;border:0;font-weight:400;background:0 0;cursor:pointer;-webkit-appearance:none;font-size:30px}.layim-tab-content li h5,.layui-layim-list li{border-bottom:1px solid #f2f2f2;cursor:pointer}.layui-m-layerend::after,.layui-m-layerend::before{position:absolute;left:5px;top:15px;content:'';width:18px;height:1px;background-color:#999;transform:rotate(45deg);-webkit-transform:rotate(45deg);border-radius:3px}.layui-m-layerend::after{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}body .layui-m-layer .layui-m-layer-footer{position:fixed;width:95%;max-width:100%;margin:0 auto;left:0;right:0;bottom:10px;background:0 0}.layui-m-layer-footer .layui-m-layercont{padding:20px;border-radius:5px 5px 0 0;background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn{display:block;height:auto;background:0 0;border-top:none}.layui-m-layer-footer .layui-m-layerbtn span{background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn span[no]{color:#FD482C;border-top:1px solid #c2c2c2;border-radius:0 0 5px 5px}.layui-m-layer-footer .layui-m-layerbtn span[yes]{margin-top:10px;border-radius:5px}body .layui-m-layer .layui-m-layer-msg{width:auto;max-width:90%;margin:0 auto;bottom:-150px;background-color:rgba(0,0,0,.7);color:#fff}.layui-m-layer-msg .layui-m-layercont{padding:10px 20px}.layim-tab-content li h5 *,.layui-layim-skin li,.layui-layim-tab li,.layui-layim-tool li{display:inline-block;vertical-align:top;*zoom:1;*display:inline}.layui-layim-tab{position:absolute;bottom:0;left:0;right:0;height:50px;border-top:1px solid #f2f2f2;background-color:#fff}.layui-layim-tab li{position:relative;width:33.33%;height:50px;text-align:center;color:#666;color:rgba(0,0,0,.6);cursor:pointer}.layui-layim-tab li .layui-icon{position:relative;top:7px;font-size:25px}.layui-layim-tab li span{position:relative;bottom:-3px;display:block;font-size:12px}.layui-layim-tab li[lay-type=more] .layui-icon{top:4px;font-size:22px}.layui-layim-tab li.layim-this{color:#3FDD86}.layim-new{display:none;position:absolute;top:5px;left:50%;margin-left:15px;width:10px;height:10px;border-radius:10px;background-color:#F74C31;color:#fff}.layim-list-top .layim-new{position:relative;vertical-align:top;top:10px;left:initial;margin-left:5px}.layim-list-top i.layui-show{display:inline-block!important}.layim-tab-content,.layim-tab-content li ul{display:none}.layui-layim{position:fixed;left:0;right:0;top:50px;bottom:50px;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch}.layim-tab-content li h5{position:relative;padding-left:35px;height:45px;line-height:45px;font-size:0;white-space:nowrap;overflow:hidden}.layim-tab-content li h5 *{font-size:17px}.layim-tab-content li h5 span{max-width:80%}.layim-tab-content li h5 i{position:absolute;left:12px;top:0;color:#C9BDBB}.layim-tab-content li h5 em{padding-left:5px;color:#999}.layim-list-friend,.layim-list-group{background-color:#fff}.layui-layim-list li{position:relative;height:42px;padding:5px 15px 5px 60px;font-size:0}.layui-layim-list li:active{background-color:#F2F2F2;background-color:rgba(0,0,0,.05)}.layui-layim-list li.layim-null{height:20px;line-height:20px;padding:10px 0;color:#999;text-align:center;cursor:default;font-size:14px}.layim-list-history li.layim-null{padding:30px 0;border-bottom:none;background-color:#eee}.layui-layim-list li *{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:17px}.layui-layim-list li span{margin-top:2px;max-width:155px;font-size:17px}.layui-layim-list li img{position:absolute;left:12px;top:8px;width:36px;height:36px;border-radius:100%}.layui-layim-list li p{display:block;padding-right:30px;line-height:18px;font-size:13px;color:#999}.layui-layim-list li .layim-msg-status{display:none;position:absolute;right:10px;bottom:7px;padding:0 5px;height:17px;line-height:17px;border-radius:17px;text-align:center;font-size:10px;background-color:#F74C31;color:#fff}.layim-list-gray{-webkit-filter:grayscale(100%);-ms-filter:grayscale(100%);filter:grayscale(100%);filter:gray}.layim-list-top{background-color:#fff;font-size:17px}.layim-list-top li{position:relative;padding:0 15px 0 50px;line-height:45px;border-bottom:1px solid #f2f2f2;cursor:pointer}.layim-list-top li:last-child{margin-bottom:10px;border-bottom:none}.layim-list-top li .layui-icon{position:absolute;left:12px;top:0;margin-right:10px;color:#36373C;font-size:24px}.layim-list-top li[layim-event=newFriend] .layui-icon{left:15px}.layim-panel,.layim-title{position:fixed;left:0;right:0;top:0}.layim-list-top li[layim-event=group] .layui-icon{font-size:20px}.layim-list-top li[layim-event=about] .layui-icon{font-size:25px}.layim-panel{bottom:0;background-color:#eee;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}.layim-title{height:50px;line-height:50px;padding:0 15px;background-color:#36373C;color:#fff;font-size:18px}.layim-chat-status{padding-left:15px;font-size:14px;opacity:.7}.layim-title .layim-chat-back{display:inline-block;vertical-align:middle;position:relative;padding:0 15px;margin-left:-10px;top:0;font-size:24px;cursor:pointer}.layim-chat-detail{position:absolute;right:0;top:0;padding:0 15px;font-size:18px;cursor:pointer}.layim-chat-main,.layim-content{position:fixed;top:50px;left:0;right:0;overflow-y:auto;overflow-x:hidden}.layim-chat-detail:active,.layim-title .layim-chat-back:active{opacity:.8}.layui-layim .layim-title{text-align:left}.layui-layim .layim-title p{padding:0 15px}.layim-content{bottom:0}.layim-chat-main{width:100%;bottom:85px;padding:15px;box-sizing:border-box!important}.layim-chat-main ul{overflow-x:hidden}.layim-chat-main ul li{position:relative;font-size:0;margin-bottom:10px;padding-left:60px;min-height:68px}.layim-chat-text,.layim-chat-user{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:15px}.layim-chat-user{position:absolute;left:3px}.layim-chat-user img{width:40px;height:40px;border-radius:100%}.layim-chat-user cite{position:absolute;left:60px;top:-2px;width:500px;line-height:24px;font-size:12px;white-space:nowrap;color:#999;text-align:left;font-style:normal}.layim-chat-user cite i{padding-left:15px;font-style:normal}.layim-chat-text{position:relative;min-height:22px;line-height:22px;margin-top:25px;padding:8px 15px;background-color:#fff;border-radius:3px;color:#333;word-break:break-all}.layim-chat-text:after{content:'';position:absolute;left:-10px;top:13px;width:0;height:0;border-style:solid dashed dashed;border-color:#fff transparent transparent;overflow:hidden;border-width:10px}.layim-chat-text a{color:#33DF83}.layim-chat-text img{max-width:100%;vertical-align:middle}.layim-chat-text .layui-layim-file,.layui-layim-file{display:block;text-align:center}.layim-chat-text .layui-layim-file{color:#333}.layui-layim-file:active{opacity:.9}.layui-layim-file i{font-size:80px;line-height:80px}.layui-layim-file cite{display:block;line-height:20px;font-size:17px}.layui-layim-audio{text-align:center;cursor:pointer}.layui-layim-audio .layui-icon{position:relative;top:5px;font-size:24px}.layui-layim-audio p{margin-top:3px}.layui-layim-video{width:120px;height:80px;line-height:80px;background-color:#333;text-align:center;border-radius:3px}.layui-layim-video .layui-icon{font-size:36px;cursor:pointer;color:#fff}.layim-chat-main ul .layim-chat-mine{text-align:right;padding-left:0;padding-right:60px}.layim-chat-mine .layim-chat-user{left:auto;right:3px}.layim-chat-mine .layim-chat-user cite{left:auto;right:60px;text-align:right}.layim-chat-mine .layim-chat-user cite i{padding-left:0;padding-right:15px}.layim-chat-mine .layim-chat-text{margin-left:0;text-align:left;background-color:#5FB878;color:#fff}.layim-chat-mine .layim-chat-text:after{left:auto;right:-10px;border-top-color:#5FB878}.layim-chat-mine .layim-chat-text a{color:#fff}.layim-chat-main ul .layim-chat-system{min-height:0;margin:20px 0 5px;padding:0}.layim-chat-system{margin:10px 0;text-align:center}.layim-chat-system span{display:inline-block;line-height:30px;padding:0 15px;border-radius:3px;background-color:#ddd;color:#fff;font-size:14px;cursor:pointer}.layim-chat-footer{position:fixed;bottom:0;left:10px;right:10px;height:80px}.layim-chat-send{display:-webkit-box;display:-webkit-flex;display:flex}.layim-chat-send input{-webkit-box-flex:1;-webkit-flex:1;flex:1;height:40px;padding-left:5px;border:0;background-color:#fff;border-radius:3px}.layim-chat-send button{border-radius:3px;height:40px;padding:0 20px;border:0;margin-left:10px;background-color:#5FB878;color:#fff}.layim-chat-tool{position:relative;width:100%;overflow-x:auto;padding:0;height:38px;line-height:38px;margin-top:3px;font-size:0;white-space:nowrap}.layim-chat-tool span{position:relative;margin:0 15px;display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:28px;cursor:pointer}.layim-chat-tool .layim-tool-log{position:absolute;right:5px;font-size:14px}.layim-tool-log i{position:relative;top:2px;margin-right:5px;font-size:20px;color:#999}.layim-tool-image input{position:absolute;font-size:0;left:0;top:0;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layim-layer{position:fixed;bottom:85px;left:10px;right:10px;margin:0 auto}.layui-layim-face{position:relative;max-height:180px;overflow:auto;padding:10px;font-size:0}.layui-layim-face li{cursor:pointer;display:inline-block;vertical-align:bottom;padding:5px 2px;text-align:center;width:10%;-webkit-box-sizing:border-box!important;-moz-box-sizing:border-box!important;box-sizing:border-box!important}.layui-layim-face li img{width:22px;height:22px}.layim-about{font-size:17px}.layim-about .layui-m-layercont{text-align:left}.layim-about .layui-m-layercont p{line-height:30px}.layim-about .layui-m-layercont a{color:#01AAED} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/1.jpg b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/1.jpg deleted file mode 100644 index 60f6a154e307f1ca11e4f740a11eabaa829715b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19399 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 Qqm@m#%f|z;!CyB13ue9iV6#hiej-> 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 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/3.jpg b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/3.jpg deleted file mode 100644 index 53ba9216283a962b6d325965a4a11c7504056e54..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18610 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 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/5.jpg b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/skin/5.jpg deleted file mode 100644 index f0e3b369197e5b498c0a8b8c2e4d02b0743b272c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45901 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 E2VAoQp8x;= diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/voice/default.mp3 b/iot-server/server-starter/src/main/webapp/assets/src/lib/extend/layim/layim-assets/voice/default.mp3 deleted file mode 100644 index 90013c5a2120567db77c1fc6d00160e88af4d46b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9341 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 iguvlh0?dAaU|Np{{ data.username||data.groupname||data.name||"\u4f5a\u540d" }}

                                  {{ data.remark||data.sign||"" }}

                                  new',"{{# }); if(length === 0){ }}",'
                                • '+(i[a.type]||"\u6682\u65e0\u6570\u636e")+"
                                • ","{{# } }}"].join("")},y=['
                                  ','
                                  ','
                                  {{ d.mine.username }}
                                  ','
                                  ','{{# if(d.mine.status === "online"){ }}','','{{# } else if(d.mine.status === "hide") { }}','',"{{# } }}",'
                                    ','
                                  • \u5728\u7ebf
                                  • ','
                                  • \u9690\u8eab
                                  • ',"
                                  ","
                                  ",'',"
                                  ",'
                                    ','
                                  • ','
                                  • ','
                                  • ',"
                                  ",'
                                    ','{{# layui.each(d.friend, function(index, item){ var spread = d.local["spread"+index]; }}',"
                                  • ",'
                                    {{# if(spread === "true"){ }}{{# } else { }}{{# } }}{{ item.groupname||"\u672a\u547d\u540d\u5206\u7ec4"+index }}( {{ (item.list||[]).length }})
                                    ','
                                      ',r({type:"friend",item:"item.list",index:"index"}),"
                                    ","
                                  • ","{{# }); if(d.friend.length === 0){ }}",'
                                    • \u6682\u65e0\u8054\u7cfb\u4eba
                                    ',"{{# } }}","
                                  ",'
                                    ',"
                                  • ",'
                                      ',r({type:"group"}),"
                                    ","
                                  • ","
                                  ",'
                                    ',"
                                  • ",'
                                      ',r({type:"history"}),"
                                    ","
                                  • ","
                                  ",'
                                    ',"
                                  • ",'',"
                                  • ","
                                  ",'
                                    ','',"{{# if(d.base.msgbox){ }}",'
                                  • ',"{{# } }}","{{# if(d.base.find){ }}",'
                                  • ',"{{# } }}",'
                                  • ',"{{# if(!d.base.copyright){ }}",'
                                  • ',"{{# } }}","
                                  ",'',"
                                  "].join(""),m=['
                                    ',"{{# layui.each(d.skin, function(index, item){ }}",'
                                  • ',"{{# }); }}",'
                                  • \u7b80\u7ea6
                                  • ',"
                                  "].join(""),f=['
                                  ','
                                  ','
                                  ','{{ d.data.name||"\u4f5a\u540d" }} {{d.data.temporary ? "\u4e34\u65f6\u4f1a\u8bdd" : ""}} {{# if(d.data.type==="group"){ }} {{# } }}','

                                  ',"
                                  ","
                                  ",'
                                  ',"
                                    ","
                                    ",'","
                                    "].join(""),p=['
                                    ','

                                    {{ d.data.name||"" }}

                                    ','
                                    ','{{# if(d.data.type === "friend" && d.type === "setGroup"){ }}',"

                                    \u9009\u62e9\u5206\u7ec4

                                    ",'{{# } if(d.data.type === "friend"){ }}','","{{# } }}",'{{# if(d.data.type === "group"){ }}',"

                                    \u8bf7\u8f93\u5165\u9a8c\u8bc1\u4fe1\u606f

                                    ",'{{# } if(d.type !== "setGroup"){ }}','',"{{# } }}","
                                    ","
                                    "].join(""),h=['
                                  • ','
                                    ',"{{# if(d.mine){ }}",'{{ layui.data.date(d.timestamp) }}{{ d.username||"\u4f5a\u540d" }}',"{{# } else { }}",'{{ d.username||"\u4f5a\u540d" }}{{ layui.data.date(d.timestamp) }}',"{{# } }}","
                                    ",'
                                    {{ layui.data.content(d.content||" ") }}
                                    ',"
                                  • "].join(""),g='
                                  • {{ d.data.name||"\u4f5a\u540d" }}{{# if(!d.base.brief){ }}{{# } }}
                                  • ',v=function(a){return a<10?"0"+(0|a):a};layui.data.date=function(a){var i=new Date(a||new Date);return i.getFullYear()+"-"+v(i.getMonth()+1)+"-"+v(i.getDate())+" "+v(i.getHours())+":"+v(i.getMinutes())+":"+v(i.getSeconds())},layui.data.content=function(a){var i=function(a){return new RegExp("\\n*\\["+(a||"")+"(code|pre|div|span|p|table|thead|th|tbody|tr|td|ul|li|ol|li|dl|dt|dd|h2|h3|h4|h5)([\\s\\S]*?)\\]\\n*","g")};return a=(a||"").replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,""").replace(/@(\S+)(\s+?|$)/g,'@
                                    $1$2').replace(/face\[([^\s\[\]]+?)\]/g,function(a){var i=a.replace(/^face/g,"");return''+i+''}).replace(/img\[([^\s]+?)\]/g,function(a){return''}).replace(/file\([\s\S]+?\)\[[\s\S]*?\]/g,function(a){var i=(a.match(/file\(([\s\S]+?)\)\[/)||[])[1],e=(a.match(/\)\[([\s\S]*?)\]/)||[])[1];return i?''+(e||i)+"":a}).replace(/audio\[([^\s]+?)\]/g,function(a){return'

                                    \u97f3\u9891\u6d88\u606f

                                    '}).replace(/video\[([^\s]+?)\]/g,function(a){return'
                                    '}).replace(/a\([\s\S]+?\)\[[\s\S]*?\]/g,function(a){var i=(a.match(/a\(([\s\S]+?)\)\[/)||[])[1],e=(a.match(/\)\[([\s\S]*?)\]/)||[])[1];return i?''+(e||i)+"":a}).replace(i(),"<$1 $2>").replace(i("/"),"").replace(/\n/g,"
                                    ")};var x,b,w,k,C,A=function(a,i,n){return a=a||{},e.ajax({url:a.url,type:a.type||"get",data:a.data,dataType:a.dataType||"json",headers:a.headers||{},cache:!1,success:function(a){0==a.code?i&&i(a.data||{}):t.msg(a.msg||(n||"Error")+": LAYIM_NOT_GET_DATA",{time:5e3})},error:function(a,i){window.console&&console.log&&console.error("LAYIM_DATE_ERROR\uff1a"+i)}})},S={message:{},chat:[]},P=function(a){var i=a.init||{};return mine=i.mine||{},local=layui.data("layim")[mine.id]||{},obj={base:a,local:local,mine:mine,history:local.history||{}},create=function(i){var t=i.mine||{},l=layui.data("layim")[t.id]||{},s={base:a,local:l,mine:t,friend:i.friend||[],group:i.group||[],history:l.history||{}};S=e.extend(S,s),H(n(y).render(s)),(l.close||a.min)&&L(),layui.each(u.ready,function(a,i){i&&i(s)})},S=e.extend(S,obj),a.brief?layui.each(u.ready,function(a,i){i&&i(obj)}):void(i.url?A(i,create,"INIT"):create(i))},H=function(a){return t.open({type:1,area:["260px","520px"],skin:"layui-box layui-layim",title:"​",offset:"rb",id:"layui-layim",shade:!1,anim:2,resize:!1,content:a,success:function(a){x=a,R(a),S.base.right&&a.css("margin-left","-"+S.base.right),b&&t.close(b.attr("times"));var i=[],n=a.find(".layim-list-history");n.find("li").each(function(){i.push(e(this).prop("outerHTML"))}),i.length>0&&(i.reverse(),n.html(i.join(""))),j(),ta.sign()},cancel:function(a){L();var i=layui.data("layim")[S.mine.id]||{};return i.close=!0,layui.data("layim",{key:S.mine.id,value:i}),!1}})},j=function(){x.on("contextmenu",function(a){return a.cancelBubble=!0,a.returnValue=!1,!1});var a=function(){t.closeAll("tips")};x.find(".layim-list-history").on("contextmenu","li",function(i){var n=e(this),l='
                                    • \u79fb\u9664\u8be5\u4f1a\u8bdd
                                    • \u6e05\u7a7a\u5168\u90e8\u4f1a\u8bdd\u5217\u8868
                                    ';n.hasClass("layim-null")||(t.tips(l,this,{tips:1,time:0,anim:5,fixed:!0,skin:"layui-box layui-layim-contextmenu",success:function(a){var i=function(a){aa(a)};a.off("mousedown",i).on("mousedown",i)}}),e(document).off("mousedown",a).on("mousedown",a),e(window).off("resize",a).on("resize",a))})},L=function(a){return b&&t.close(b.attr("times")),x&&x.hide(),S.mine=S.mine||{},t.open({type:1,title:!1,id:"layui-layim-close",skin:"layui-box layui-layim-min layui-layim-close",shade:!1,closeBtn:!1,anim:2,offset:"rb",resize:!1,content:''+(a||S.base.title||"\u6211\u7684 IM")+"",move:"#layui-layim-close img",success:function(a,i){b=a,S.base.right&&a.css("margin-left","-"+S.base.right),a.on("click",function(){t.close(i),x.show();var a=layui.data("layim")[S.mine.id]||{};delete a.close,layui.data("layim",{key:S.mine.id,value:a})})}})},T=function(a){a=a||{};var i=e("#layui-layim-chat"),l={data:a,base:S.base,local:S.local};if(!a.id)return t.msg("\u975e\u6cd5\u7528\u6237");if(i[0]){var s=w.find(".layim-chat-list"),o=s.find(".layim-chatlist-"+a.type+a.id),d=w.find(".layui-layer-max").hasClass("layui-layer-maxmin"),c=i.children(".layim-chat-box");return"none"===w.css("display")&&w.show(),k&&t.close(k.attr("times")),1!==s.find("li").length||o[0]||(d||w.css("width",800),s.css({height:w.height()}).show(),c.css("margin-left","200px")),o[0]||(s.append(n(g).render(l)),c.append(n(f).render(l)),z(a),E()),M(s.find(".layim-chatlist-"+a.type+a.id)),o[0]||B(),_(a),Q(),C}l.first=!0;var r=C=t.open({type:1,area:"600px",skin:"layui-box layui-layim-chat",id:"layui-layim-chat",title:"​",shade:!1,maxmin:!0,offset:a.offset||"auto",anim:a.anim||0,closeBtn:!S.base.brief&&1,content:n('
                                      '+g+'
                                    '+f+"
                                    ").render(l),success:function(i){w=i,i.css({"min-width":"500px","min-height":"420px"}),z(a),"function"==typeof a.success&&a.success(i),Q(),R(i),_(a),B(),O(),layui.each(u.chatChange,function(a,i){i&&i(q())}),i.on("dblclick",".layui-layim-photos",function(){var a=this.src;t.close(T.photosIndex),t.photos({photos:{data:[{alt:"\u5927\u56fe\u6a21\u5f0f",src:a}]},shade:.01,closeBtn:2,anim:0,resize:!1,success:function(a,i){T.photosIndex=i}})})},full:function(a){t.style(r,{width:"100%",height:"100%"},!0),E()},resizing:E,restore:E,min:function(){return I(),!1},end:function(){t.closeAll("tips"),w=null}});return r},z=function(a){e(".layim-"+a.type+a.id).each(function(){e(this).hasClass("layim-list-gray")&&layui.layim.setFriendStatus(a.id,"offline")})},E=function(){var a=w.find(".layim-chat-list"),i=w.find(".layim-chat-main"),e=w.height();a.css({height:e}),i.css({height:e-20-80-158})},I=function(a){var i=a||q().data,n=layui.layim.cache().base;w&&!a&&w.hide(),t.close(I.index),I.index=t.open({type:1,title:!1,skin:"layui-box layui-layim-min",shade:!1,closeBtn:!1,anim:i.anim||2,offset:"b",move:"#layui-layim-min",resize:!1,area:["182px","50px"],content:''+i.name+"",success:function(i,l){a||(k=i),n.minRight&&t.style(l,{left:e(window).width()-i.outerWidth()-parseFloat(n.minRight)}),i.find(".layui-layer-content span").on("click",function(){t.close(l),a?layui.each(S.chat,function(a,i){T(i)}):w.show(),a&&(S.chat=[],Z())}),i.find(".layui-layer-content img").on("click",function(a){aa(a)})}})},N=function(a,i){return a=a||{},t.close(N.index),N.index=t.open({type:1,area:"430px",title:{friend:"\u6dfb\u52a0\u597d\u53cb",group:"\u52a0\u5165\u7fa4\u7ec4"}[a.type]||"",shade:!1,resize:!1,btn:i?["\u786e\u8ba4","\u53d6\u6d88"]:["\u53d1\u9001\u7533\u8bf7","\u5173\u95ed"],content:n(p).render({data:{name:a.username||a.groupname,avatar:a.avatar||layui.cache.layimAssetsPath+"images/default.png",group:a.group||parent.layui.layim.cache().friend||[],type:a.type},type:i}),yes:function(e,t){var n=t.find("#LAY_layimGroup"),l=t.find("#LAY_layimRemark");i?a.submit&&a.submit(n.val(),e):a.submit&&a.submit(n.val(),l.val(),e)}})},M=function(a,i){a=a||e(".layim-chat-list ."+o);var n=a.index()===-1?0:a.index(),l=".layim-chat",d=w.find(l).eq(n),c=w.find(".layui-layer-max").hasClass("layui-layer-maxmin");if(i){a.hasClass(o)&&M(0===n?a.next():a.prev());var r=w.find(l).length;return 1===r?t.close(C):(a.remove(),d.remove(),2===r&&(w.find(".layim-chat-list").hide(),c||w.css("width","600px"),w.find(".layim-chat-box").css("margin-left",0)),!1)}a.addClass(o).siblings().removeClass(o),d.addClass(s).siblings(l).removeClass(s),d.find("textarea").focus(),layui.each(u.chatChange,function(a,i){i&&i(q())}),O()},O=function(){var a=q(),i=S.message[a.data.type+a.data.id];i&&delete S.message[a.data.type+a.data.id]},q=c.prototype.thisChat=function(){if(w){var a=e(".layim-chat-list ."+o).index(),i=w.find(".layim-chat").eq(a),t=JSON.parse(decodeURIComponent(i.find(".layim-chat-tool").data("json")));return{elem:i,data:t,textarea:i.find("textarea")}}},R=function(a){var i=layui.data("layim")[S.mine.id]||{},e=i.skin;a.css({"background-image":e?"url("+e+")":function(){return S.base.initSkin?"url("+(layui.cache.layimAssetsPath+"skin/"+S.base.initSkin)+")":"none"}()})},_=function(a){var i=layui.data("layim")[S.mine.id]||{},e={},t=i.history||{},l=t[a.type+a.id];if(x){var s=x.find(".layim-list-history");if(a.historyTime=(new Date).getTime(),t[a.type+a.id]=a,i.history=t,layui.data("layim",{key:S.mine.id,value:i}),!l){e[a.type+a.id]=a;var o=n(r({type:"history",item:"d.data"})).render({data:e});s.prepend(o),s.find(".layim-null").remove()}}},$=function(){var a={username:S.mine?S.mine.username:"\u8bbf\u5ba2",avatar:S.mine?S.mine.avatar:layui.cache.layimAssetsPath+"images/default.png",id:S.mine?S.mine.id:null,mine:!0},i=q(),e=i.elem.find(".layim-chat-main ul"),l=S.base.maxLength||3e3;if(a.content=i.textarea.val(),""!==a.content.replace(/\s/g,"")){if(a.content.length>l)return t.msg("\u5185\u5bb9\u6700\u957f\u4e0d\u80fd\u8d85\u8fc7"+l+"\u4e2a\u5b57\u7b26");e.append(n(h).render(a));var s={mine:a,to:i.data},o={username:s.mine.username,avatar:s.mine.avatar||layui.cache.layimAssetsPath+"images/default.png",id:s.to.id,type:s.to.type,content:s.mine.content,timestamp:(new Date).getTime(),mine:!0};V(o),layui.each(u.sendMessage,function(a,i){i&&i(s)})}Z(),i.textarea.val("").focus()},D=function(a){if(a=a||{},window.Notification)if("granted"===Notification.permission){new Notification(a.title||"",{body:a.content||"",icon:a.avatar||layui.cache.layimAssetsPath+"images/default.png"})}else Notification.requestPermission()},J=function(){if(!(l.ie&&l.ie<9)){var a=document.createElement("audio");a.src=layui.cache.layimAssetsPath+"voice/"+S.base.voice,a.play()}},F={},G=function(a){a=a||{};var i=e(".layim-chatlist-"+a.type+a.id),t={},l=i.index();if(a.timestamp=a.timestamp||(new Date).getTime(),a.fromid==S.mine.id&&(a.mine=!0),a.system||V(a),F=JSON.parse(JSON.stringify(a)),S.base.voice&&J(),!w&&a.content||l===-1){if(S.message[a.type+a.id])S.message[a.type+a.id].push(a);else if(S.message[a.type+a.id]=[a],"friend"===a.type){var s;layui.each(S.friend,function(i,e){if(layui.each(e.list,function(i,e){if(e.id==a.id)return e.type="friend",e.name=e.username,S.chat.push(e),s=!0}),s)return!0}),s||(a.name=a.username,a.temporary=!0,S.chat.push(a))}else if("group"===a.type){var o;layui.each(S.group,function(i,e){if(e.id==a.id)return e.type="group",e.name=e.groupname,S.chat.push(e),o=!0}),o||(a.name=a.groupname,S.chat.push(a))}else a.name=a.name||a.username||a.groupname,S.chat.push(a);if("group"===a.type&&layui.each(S.group,function(i,e){if(e.id==a.id)return t.avatar=e.avatar||layui.cache.layimAssetsPath+"images/default.png",!0}),!a.system)return S.base.notice&&D({title:"\u6765\u81ea "+a.username+" \u7684\u6d88\u606f",content:a.content,avatar:t.avatar||a.avatar||layui.cache.layimAssetsPath+"images/default.png"}),I({name:"\u6536\u5230\u65b0\u6d88\u606f",avatar:t.avatar||a.avatar||layui.cache.layimAssetsPath+"images/default.png",anim:6})}if(w){var d=q();d.data.type+d.data.id!==a.type+a.id&&(i.addClass("layui-anim layer-anim-06"),setTimeout(function(){i.removeClass("layui-anim layer-anim-06")},300));var u=w.find(".layim-chat").eq(l),c=u.find(".layim-chat-main ul");a.system?l!==-1&&c.append('
                                  • '+a.content+"
                                  • "):""!==a.content.replace(/\s/g,"")&&c.append(n(h).render(a)),Z()}},K="layui-anim-loop layer-anim-05",Y=function(a){var i=x.find(".layim-tool-msgbox");i.find("span").addClass(K).html(a)},V=function(a){var i=layui.data("layim")[S.mine.id]||{};i.chatlog=i.chatlog||{};var e=i.chatlog[a.type+a.id];if(e){var t;layui.each(e,function(i,e){e.timestamp===a.timestamp&&e.type===a.type&&e.id===a.id&&e.content===a.content&&(t=!0)}),t||a.fromid==S.mine.id||e.push(a),e.length>d&&e.shift()}else i.chatlog[a.type+a.id]=[a];layui.data("layim",{key:S.mine.id,value:i})},B=function(){var a=layui.data("layim")[S.mine.id]||{},i=q(),e=a.chatlog||{},t=i.elem.find(".layim-chat-main ul");layui.each(e[i.data.type+i.data.id],function(a,i){t.append(n(h).render(i))}),Z()},U=function(a){var i,e={},l=x.find(".layim-list-"+a.type);if(S[a.type])if("friend"===a.type)layui.each(S.friend,function(n,l){if(a.groupid==l.id)return layui.each(S.friend[n].list,function(e,t){if(t.id==a.id)return i=!0}),i?t.msg("\u597d\u53cb ["+(a.username||"")+"] \u5df2\u7ecf\u5b58\u5728\u5217\u8868\u4e2d",{anim:6}):(S.friend[n].list=S.friend[n].list||[],e[S.friend[n].list.length]=a,a.groupIndex=n,S.friend[n].list.push(a),!0)});else if("group"===a.type){if(layui.each(S.group,function(e,t){if(t.id==a.id)return i=!0}),i)return t.msg("\u60a8\u5df2\u662f ["+(a.groupname||"")+"] \u7684\u7fa4\u6210\u5458",{anim:6});e[S.group.length]=a,S.group.push(a)}if(!i){var s=n(r({type:a.type,item:"d.data",index:"friend"===a.type?"data.groupIndex":null})).render({data:e});if("friend"===a.type){var o=l.find(">li").eq(a.groupIndex);o.find(".layui-layim-list").append(s),o.find(".layim-count").html(S.friend[a.groupIndex].list.length),o.find(".layim-null")[0]&&o.find(".layim-null").remove()}else"group"===a.type&&(l.append(s),l.find(".layim-null")[0]&&l.find(".layim-null").remove())}},W=function(a){var i=x.find(".layim-list-"+a.type);S[a.type]&&("friend"===a.type?layui.each(S.friend,function(e,t){layui.each(t.list,function(t,n){if(a.id==n.id){var l=i.find(">li").eq(e);l.find(".layui-layim-list>li");return l.find(".layui-layim-list>li").eq(t).remove(),S.friend[e].list.splice(t,1),l.find(".layim-count").html(S.friend[e].list.length),0===S.friend[e].list.length&&l.find(".layui-layim-list").html('
                                  • \u8be5\u5206\u7ec4\u4e0b\u5df2\u65e0\u597d\u53cb\u4e86
                                  • '),!0}})}):"group"===a.type&&layui.each(S.group,function(e,t){if(a.id==t.id)return i.find(">li").eq(e).remove(),S.group.splice(e,1),0===S.group.length&&i.html('
                                  • \u6682\u65e0\u7fa4\u7ec4
                                  • '),!0}))},Z=function(){var a=q(),i=a.elem.find(".layim-chat-main"),e=i.find("ul"),t=e.find("li").length;if(t>=d){var n=e.find("li").eq(0);e.prev().hasClass("layim-chat-system")||e.before('
                                    \u67e5\u770b\u66f4\u591a\u8bb0\u5f55
                                    '),t>d&&n.remove()}i.scrollTop(i[0].scrollHeight+1e3),i.find("ul li:last").find("img").load(function(){i.scrollTop(i[0].scrollHeight+1e3)})},Q=function(){var a=q(),i=a.textarea;i.focus(),i.off("keydown").on("keydown",function(a){var e=layui.data("layim")[S.mine.id]||{},t=a.keyCode;if("Ctrl+Enter"===e.sendHotKey)return void(a.ctrlKey&&13===t&&$());if(13===t){if(a.ctrlKey)return i.val(i.val()+"\n");if(a.shiftKey)return;a.preventDefault(),$()}})},X=function(){var a=["[\u5fae\u7b11]","[\u563b\u563b]","[\u54c8\u54c8]","[\u53ef\u7231]","[\u53ef\u601c]","[\u6316\u9f3b]","[\u5403\u60ca]","[\u5bb3\u7f9e]","[\u6324\u773c]","[\u95ed\u5634]","[\u9119\u89c6]","[\u7231\u4f60]","[\u6cea]","[\u5077\u7b11]","[\u4eb2\u4eb2]","[\u751f\u75c5]","[\u592a\u5f00\u5fc3]","[\u767d\u773c]","[\u53f3\u54fc\u54fc]","[\u5de6\u54fc\u54fc]","[\u5618]","[\u8870]","[\u59d4\u5c48]","[\u5410]","[\u54c8\u6b20]","[\u62b1\u62b1]","[\u6012]","[\u7591\u95ee]","[\u998b\u5634]","[\u62dc\u62dc]","[\u601d\u8003]","[\u6c57]","[\u56f0]","[\u7761]","[\u94b1]","[\u5931\u671b]","[\u9177]","[\u8272]","[\u54fc]","[\u9f13\u638c]","[\u6655]","[\u60b2\u4f24]","[\u6293\u72c2]","[\u9ed1\u7ebf]","[\u9634\u9669]","[\u6012\u9a82]","[\u4e92\u7c89]","[\u5fc3]","[\u4f24\u5fc3]","[\u732a\u5934]","[\u718a\u732b]","[\u5154\u5b50]","[ok]","[\u8036]","[good]","[NO]","[\u8d5e]","[\u6765]","[\u5f31]","[\u8349\u6ce5\u9a6c]","[\u795e\u9a6c]","[\u56e7]","[\u6d6e\u4e91]","[\u7ed9\u529b]","[\u56f4\u89c2]","[\u5a01\u6b66]","[\u5965\u7279\u66fc]","[\u793c\u7269]","[\u949f]","[\u8bdd\u7b52]","[\u8721\u70db]","[\u86cb\u7cd5]"],i={};return layui.each(a,function(a,e){i[e]=layui.cache.layimAssetsPath+"images/face/"+a+".gif"}),i}(),aa=layui.stope,ia=function(a,i){var e,t=a.value;a.focus(),document.selection?(e=document.selection.createRange(),document.selection.empty(),e.text=i):(e=[t.substring(0,a.selectionStart),i,t.substr(a.selectionEnd)],a.focus(),a.value=e.join(""))},ea="layui-anim-upbit",ta={status:function(a,i){var t=function(){a.next().hide().removeClass(ea)},n=a.attr("lay-type");if("show"===n)aa(i),a.next().show().addClass(ea),e(document).off("click",t).on("click",t);else{var l=a.parent().prev();a.addClass(o).siblings().removeClass(o),l.html(a.find("cite").html()),l.removeClass("layim-status-"+("online"===n?"hide":"online")).addClass("layim-status-"+n),layui.each(u.online,function(a,i){i&&i(n)})}},sign:function(){var a=x.find(".layui-layim-remark");a.on("change",function(){var a=this.value;layui.each(u.sign,function(i,e){e&&e(a)})}),a.on("keyup",function(a){var i=a.keyCode;13===i&&this.blur()})},tab:function(a){var i,e=".layim-tab-content",t=x.find(".layui-layim-tab>li");"number"==typeof a?(i=a,a=t.eq(i)):i=a.index(),i>2?t.removeClass(o):(ta.tab.index=i,a.addClass(o).siblings().removeClass(o)),x.find(e).eq(i).addClass(s).siblings(e).removeClass(s)},spread:function(a){var i=a.attr("lay-type"),e="true"===i?"false":"true",t=layui.data("layim")[S.mine.id]||{};a.next()["true"===i?"removeClass":"addClass"](s),t["spread"+a.parent().index()]=e,layui.data("layim",{key:S.mine.id,value:t}),a.attr("lay-type",e),a.find(".layui-icon").html("true"===e?"":"")},search:function(a){var i=x.find(".layui-layim-search"),e=x.find("#layui-layim-search"),t=i.find("input"),n=function(a){var i=t.val().replace(/\s/);if(""===i)ta.tab(0|ta.tab.index);else{for(var n=[],l=S.friend||[],s=S.group||[],o="",d=0;d0)for(var r=0;r'+(n[r].username||n[r].groupname||"\u4f5a\u540d")+"

                                    "+(n[r].remark||n[r].sign||"")+"

                                    ";else o='
                                  • \u65e0\u641c\u7d22\u7ed3\u679c
                                  • ';e.html(o),ta.tab(3)}};!S.base.isfriend&&S.base.isgroup?ta.tab.index=1:S.base.isfriend||S.base.isgroup||(ta.tab.index=2),i.show(),t.focus(),t.off("keyup",n).on("keyup",n)},closeSearch:function(a){a.parent().hide(),ta.tab(0|ta.tab.index)},msgbox:function(){var a=x.find(".layim-tool-msgbox");return t.close(ta.msgbox.index),a.find("span").removeClass(K).html(""),ta.msgbox.index=t.open({type:2,title:"\u6d88\u606f\u76d2\u5b50",shade:!1,maxmin:!0,area:["600px","520px"],skin:"layui-box layui-layer-border",resize:!1,content:S.base.msgbox})},find:function(){return t.close(ta.find.index),ta.find.index=t.open({type:2,title:"\u67e5\u627e",shade:!1,maxmin:!0,area:["1000px","520px"],skin:"layui-box layui-layer-border",resize:!1,content:S.base.find})},skin:function(){t.open({type:1,title:"\u66f4\u6362\u80cc\u666f",shade:!1,area:"300px",skin:"layui-box layui-layer-border",id:"layui-layim-skin",zIndex:66666666,resize:!1,content:n(m).render({skin:S.base.skin})})},about:function(){t.alert("\u7248\u672c\uff1a v"+i,{title:"\u5173\u4e8e",shade:!1})},setSkin:function(a){var i=a.attr("src"),e=layui.data("layim")[S.mine.id]||{};e.skin=i,i||delete e.skin,layui.data("layim",{key:S.mine.id,value:e});try{x.css({"background-image":i?"url("+i+")":"none"}),w.css({"background-image":i?"url("+i+")":"none"})}catch(t){}layui.each(u.setSkin,function(a,e){var t=(i||"").replace(layui.cache.layimAssetsPath+"skin/","");e&&e(t,i)})},chat:function(a){var i=layui.data("layim")[S.mine.id]||{},e=a.data("type"),t=a.data("index"),n=a.attr("data-list")||a.index(),l={}; -"friend"===e?l=S[e][t].list[n]:"group"===e?l=S[e][n]:"history"===e&&(l=(i.history||{})[t]||{}),l.name=l.name||l.username||l.groupname,"history"!==e&&(l.type=e),T(l)},tabChat:function(a){M(a)},closeChat:function(a,i){M(a.parent(),1),aa(i)},closeThisChat:function(){M(null,1)},groupMembers:function(a,i){var n=a.find(".layui-icon"),l=function(){n.html(""),a.data("down",null),t.close(ta.groupMembers.index)},s=function(a){aa(a)};a.data("down")?l():(n.html(""),a.data("down",!0),ta.groupMembers.index=t.tips('
                                      ',a,{tips:3,time:0,anim:5,fixed:!0,skin:"layui-box layui-layim-members",success:function(i){var t=S.base.members||{},n=q(),s=i.find(".layim-members-list"),o="",d={},c=w.find(".layui-layer-max").hasClass("layui-layer-maxmin"),r="none"===w.find(".layim-chat-list").css("display");c&&s.css({width:e(window).width()-22-(r||200)}),t.data=e.extend(t.data,{id:n.data.id}),A(t,function(i){layui.each(i.list,function(a,i){o+='
                                    • '+i.username+"
                                    • ",d[i.id]=i}),s.html(o),a.find(".layim-chat-members").html(i.members||(i.list||[]).length+"\u4eba"),s.find("li").on("click",function(){var a=e(this).data("uid"),i=d[a];T({name:i.username,type:"friend",avatar:i.avatar||layui.cache.layimAssetsPath+"images/default.png",id:i.id}),l()}),layui.each(u.members,function(a,e){e&&e(i)})}),i.on("mousedown",function(a){aa(a)})}}),e(document).off("mousedown",l).on("mousedown",l),e(window).off("resize",l).on("resize",l),a.off("mousedown",s).on("mousedown",s))},send:function(){$()},setSend:function(a,i){var t=ta.setSend.box=a.siblings(".layim-menu-box"),n=a.attr("lay-type");if("show"===n)aa(i),t.show().addClass(ea),e(document).off("click",ta.setSendHide).on("click",ta.setSendHide);else{a.addClass(o).siblings().removeClass(o);var l=layui.data("layim")[S.mine.id]||{};l.sendHotKey=n,layui.data("layim",{key:S.mine.id,value:l}),ta.setSendHide(i,a.parent())}},setSendHide:function(a,i){(i||ta.setSend.box).hide().removeClass(ea)},face:function(a,i){var n="",l=q();for(var s in X)n+='
                                    • ';n='
                                        '+n+"
                                      ",ta.face.index=t.tips(n,a,{tips:1,time:0,fixed:!0,skin:"layui-box layui-layim-face",success:function(a){a.find(".layim-face-list>li").on("mousedown",function(a){aa(a)}).on("click",function(){ia(l.textarea[0],"face"+this.title+" "),t.close(ta.face.index)})}}),e(document).off("mousedown",ta.faceHide).on("mousedown",ta.faceHide),e(window).off("resize",ta.faceHide).on("resize",ta.faceHide),aa(i)},faceHide:function(){t.close(ta.face.index)},image:function(a){var i=a.data("type")||"images",e={images:"uploadImage",file:"uploadFile"},n=q(),l=S.base[e[i]]||{};layui.upload.render({url:l.url||"",method:l.type,elem:a.find("input")[0],accept:i,done:function(a){0==a.code?(a.data=a.data||{},"images"===i?ia(n.textarea[0],"img["+(a.data.src||"")+"]"):"file"===i&&ia(n.textarea[0],"file("+(a.data.src||"")+")["+(a.data.name||"\u4e0b\u8f7d\u6587\u4ef6")+"]"),$()):t.msg(a.msg||"\u4e0a\u4f20\u5931\u8d25")}})},media:function(a){var i=a.data("type"),n={audio:"\u97f3\u9891",video:"\u89c6\u9891"},l=q();t.prompt({title:"\u8bf7\u8f93\u5165\u7f51\u7edc"+n[i]+"\u5730\u5740",shade:!1,offset:[a.offset().top-e(window).scrollTop()-158+"px",a.offset().left+"px"]},function(a,e){ia(l.textarea[0],i+"["+a+"]"),$(),t.close(e)})},extend:function(a){var i=a.attr("lay-filter"),e=q();layui.each(u["tool("+i+")"],function(i,t){t&&t.call(a,function(a){ia(e.textarea[0],a)},$,e)})},playAudio:function(a){var i=a.data("audio"),e=i||document.createElement("audio"),n=function(){e.pause(),a.removeAttr("status"),a.find("i").html("")};return a.data("error")?t.msg("\u64ad\u653e\u97f3\u9891\u6e90\u5f02\u5e38"):e.play?void(a.attr("status")?n():(i||(e.src=a.data("src")),e.play(),a.attr("status","pause"),a.data("audio",e),a.find("i").html(""),e.onended=function(){n()},e.onerror=function(){t.msg("\u64ad\u653e\u97f3\u9891\u6e90\u5f02\u5e38"),a.data("error",!0),n()})):t.msg("\u60a8\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301audio")},playVideo:function(a){var i=a.data("src"),e=document.createElement("video");return e.play?(t.close(ta.playVideo.index),void(ta.playVideo.index=t.open({type:1,title:"\u64ad\u653e\u89c6\u9891",area:["460px","300px"],maxmin:!0,shade:!1,content:'
                                      '}))):t.msg("\u60a8\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301video")},chatLog:function(a){var i=q();return S.base.chatLog?(t.close(ta.chatLog.index),ta.chatLog.index=t.open({type:2,maxmin:!0,title:"\u4e0e "+i.data.name+" \u7684\u804a\u5929\u8bb0\u5f55",area:["450px","100%"],shade:!1,offset:"rb",skin:"layui-box",anim:2,id:"layui-layim-chatlog",content:S.base.chatLog+"?id="+i.data.id+"&type="+i.data.type})):t.msg("\u672a\u5f00\u542f\u66f4\u591a\u804a\u5929\u8bb0\u5f55")},menuHistory:function(a,i){var n=layui.data("layim")[S.mine.id]||{},l=a.parent(),s=a.data("type"),o=x.find(".layim-list-history"),d='
                                    • \u6682\u65e0\u5386\u53f2\u4f1a\u8bdd
                                    • ';if("one"===s){var u=n.history;delete u[l.data("index")],n.history=u,layui.data("layim",{key:S.mine.id,value:n}),e(".layim-list-history li.layim-"+l.data("index")).remove(),0===o.find("li").length&&o.html(d)}else"all"===s&&(delete n.history,layui.data("layim",{key:S.mine.id,value:n}),o.html(d));t.closeAll("tips")}};a("layim",new c)}).link(layui.cache.layimAssetsPath+"layim.css","skinlayimcss"); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/lib/view.js b/iot-server/server-starter/src/main/webapp/assets/src/lib/view.js deleted file mode 100644 index 017ce703..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/lib/view.js +++ /dev/null @@ -1,344 +0,0 @@ - -/*! - * 界面视图模块 - */ - -layui.define(['laytpl', 'layer'], function(exports){ - var $ = layui.jquery - ,laytpl = layui.laytpl - ,layer = layui.layer - ,setter = layui.setter - ,device = layui.device() - ,hint = layui.hint() - - //对外接口 - ,view = function(id){ - return new Class(id); - } - - ,SHOW = 'layui-show', LAY_BODY = 'LAY_app_body' - - //构造器 - ,Class = function(id){ - this.id = id; - this.container = $('#'+(id || LAY_BODY)); - }; - - //加载中 - view.loading = function(elem){ - elem.append( - this.elemLoad = $('') - ); - }; - - //移除加载 - view.removeLoad = function(){ - this.elemLoad && this.elemLoad.remove(); - }; - - //清除 token,并跳转到登入页 - view.exit = function(){ - //清空本地记录的 token - layui.data(setter.tableName, { - key: setter.request.tokenName - ,remove: true - }); - - //跳转到登入页 - location.hash = '/user/login'; - }; - - //Ajax请求 - view.req = function(options){ - var that = this - ,success = options.success - ,error = options.error - ,request = setter.request - ,response = setter.response - ,debug = function(){ - return setter.debug - ? '
                                      URL:' + options.url - : ''; - }; - - options.data = options.data || {}; - options.headers = options.headers || {}; - - if(request.tokenName){ - var sendData = typeof options.data === 'string' - ? JSON.parse(options.data) - : options.data; - - //自动给参数传入默认 token - options.data[request.tokenName] = request.tokenName in sendData - ? options.data[request.tokenName] - : (layui.data(setter.tableName)[request.tokenName] || ''); - - //自动给 Request Headers 传入 token - options.headers[request.tokenName] = request.tokenName in options.headers - ? options.headers[request.tokenName] - : (layui.data(setter.tableName)[request.tokenName] || ''); - } - - delete options.success; - delete options.error; - - return $.ajax($.extend({ - type: 'get' - ,dataType: 'json' - ,success: function(res){ - var statusCode = response.statusCode; - - //只有 response 的 code 一切正常才执行 done - if(res[response.statusName] == statusCode.ok) { - typeof options.done === 'function' && options.done(res); - } - - //登录状态失效,清除本地 access_token,并强制跳转到登入页 - else if(res[response.statusName] == statusCode.logout){ - view.exit(); - } - - //其它异常 - else { - var errorText = [ - 'Error: ' + (res[response.msgName] || '返回状态码异常') - ,debug() - ].join(''); - view.error(errorText); - } - - //只要 http 状态码正常,无论 response 的 code 是否正常都执行 success - typeof success === 'function' && success(res); - } - ,error: function(e, code){ - var errorText = [ - '请求异常,请重试
                                      错误信息:'+ code - ,debug() - ].join(''); - view.error(errorText); - - typeof error === 'function' && error.apply(this, arguments); - } - }, options)); - }; - - //弹窗 - view.popup = function(options){ - var success = options.success - ,skin = options.skin; - - delete options.success; - delete options.skin; - - return layer.open($.extend({ - type: 1 - ,title: '提示' - ,content: '' - ,id: 'LAY-system-view-popup' - ,skin: 'layui-layer-admin' + (skin ? ' ' + skin : '') - ,shadeClose: true - ,closeBtn: false - ,success: function(layero, index){ - var elemClose = $(''); - layero.append(elemClose); - elemClose.on('click', function(){ - layer.close(index); - }); - typeof success === 'function' && success.apply(this, arguments); - } - }, options)) - }; - - //异常提示 - view.error = function(content, options){ - return view.popup($.extend({ - content: content - ,maxWidth: 300 - //,shade: 0.01 - ,offset: 't' - ,anim: 6 - ,id: 'LAY_adminError' - }, options)) - }; - - - //请求模板文件渲染 - Class.prototype.render = function(views, params){ - var that = this, router = layui.router(); - views = setter.views + views + setter.engine; - - $('#'+ LAY_BODY).children('.layadmin-loading').remove(); - view.loading(that.container); //loading - - //请求模板 - $.ajax({ - url: views - ,type: 'get' - ,dataType: 'html' - ,data: { - v: layui.cache.version - } - ,success: function(html){ - html = '
                                      ' + html + '
                                      '; - - var elemTitle = $(html).find('title') - ,title = elemTitle.text() || (html.match(/\([\s\S]*)\<\/title>/)||[])[1]; - - var res = { - title: title - ,body: html - }; - - elemTitle.remove(); - that.params = params || {}; //获取参数 - - if(that.then){ - that.then(res); - delete that.then; - } - - that.parse(html); - view.removeLoad(); - - if(that.done){ - that.done(res); - delete that.done; - } - - } - ,error: function(e){ - view.removeLoad(); - - if(that.render.isError){ - return view.error('请求视图文件异常,状态:'+ e.status); - }; - - if(e.status === 404){ - that.render('template/tips/404'); - } else { - that.render('template/tips/error'); - } - - that.render.isError = true; - } - }); - return that; - }; - - //解析模板 - Class.prototype.parse = function(html, refresh, callback){ - var that = this - ,isScriptTpl = typeof html === 'object' //是否模板元素 - ,elem = isScriptTpl ? html : $(html) - ,elemTemp = isScriptTpl ? html : elem.find('*[template]') - ,fn = function(options){ - var tpl = laytpl(options.dataElem.html()) - ,res = $.extend({ - params: router.params - }, options.res); - - options.dataElem.after(tpl.render(res)); - typeof callback === 'function' && callback(); - - try { - options.done && new Function('d', options.done)(res); - } catch(e){ - console.error(options.dataElem[0], '\n存在错误回调脚本\n\n', e) - } - } - ,router = layui.router(); - - elem.find('title').remove(); - that.container[refresh ? 'after' : 'html'](elem.children()); - - router.params = that.params || {}; - - //遍历模板区块 - for(var i = elemTemp.length; i > 0; i--){ - (function(){ - var dataElem = elemTemp.eq(i - 1) - ,layDone = dataElem.attr('lay-done') || dataElem.attr('lay-then') //获取回调 - ,url = laytpl(dataElem.attr('lay-url')|| '').render(router) //接口 url - ,data = laytpl(dataElem.attr('lay-data')|| '').render(router) //接口参数 - ,headers = laytpl(dataElem.attr('lay-headers')|| '').render(router); //接口请求的头信息 - - try { - data = new Function('return '+ data + ';')(); - } catch(e) { - hint.error('lay-data: ' + e.message); - data = {}; - }; - - try { - headers = new Function('return '+ headers + ';')(); - } catch(e) { - hint.error('lay-headers: ' + e.message); - headers = headers || {} - }; - - if(url){ - view.req({ - type: dataElem.attr('lay-type') || 'get' - ,url: url - ,data: data - ,dataType: 'json' - ,headers: headers - ,success: function(res){ - fn({ - dataElem: dataElem - ,res: res - ,done: layDone - }); - } - }); - } else { - fn({ - dataElem: dataElem - ,done: layDone - }); - } - }()); - } - - return that; - }; - - //直接渲染字符 - Class.prototype.send = function(views, data){ - var tpl = laytpl(views || this.container.html()).render(data || {}); - this.container.html(tpl); - return this; - }; - - //局部刷新模板 - Class.prototype.refresh = function(callback){ - var that = this - ,next = that.container.next() - ,templateid = next.attr('lay-templateid'); - - if(that.id != templateid) return that; - - that.parse(that.container, 'refresh', function(){ - that.container.siblings('[lay-templateid="'+ that.id +'"]:last').remove(); - typeof callback === 'function' && callback(); - }); - - return that; - }; - - //视图请求成功后的回调 - Class.prototype.then = function(callback){ - this.then = callback; - return this; - }; - - //视图渲染完毕后的回调 - Class.prototype.done = function(callback){ - this.done = callback; - return this; - }; - - //对外接口 - exports('view', view); -}); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/style/admin.css b/iot-server/server-starter/src/main/webapp/assets/src/style/admin.css deleted file mode 100644 index f0627bf7..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/style/admin.css +++ /dev/null @@ -1,522 +0,0 @@ - -/** - * admin.css - */ - -html #layuicss-layuiAdmin{display: none; position: absolute; width: 1989px;} - - -/* 系统 */ -::-webkit-input-placeholder{color: #ccc} - -/** 滚动条 **/ -/* -::-webkit-scrollbar{width: 10px; height: 10px;} -::-webkit-scrollbar-button:vertical{display: none;} -::-webkit-scrollbar-track, ::-webkit-scrollbar-corner{background-color: #e2e2e2;} -::-webkit-scrollbar-thumb{border-radius: 0; background-color: rgba(0,0,0,.3);} -::-webkit-scrollbar-thumb:vertical:hover{background-color: rgba(0,0,0,.35);} -::-webkit-scrollbar-thumb:vertical:active{background-color: rgba(0,0,0,.38);} -*/ - - -/* 全局 */ -html{background-color: #f2f2f2; color: #666;} -*[template], -.layadmin-tabsbody-item{display: none;} -*[lay-href], -*[lay-tips], -*[layadmin-event]{cursor: pointer;} - -/* 重置布局结构 */ -.layui-layout-admin .layui-header{position: fixed; top: 0; left: 0; width: 100%; height: 50px;} - -/* -.layui-layout-admin .layui-header .layui-layout-right .layui-nav-item a{color: #fff;} -.layui-layout-admin .layui-header .layui-layout-right .layui-nav-item a cite{color: rgba(255,255,255,.7);} -*/ - -.layui-layout-admin .layui-header .layui-nav .layui-nav-child a{color: #333;} -.layui-layout-admin .layui-side{width: 220px; top: 0; z-index: 1001;} -.layui-layout-admin .layui-logo, -.layui-layout-admin .layui-header .layui-nav .layui-nav-item{height: 50px; line-height: 50px;} -.layui-layout-admin .layui-logo{position: fixed; left: 0; top: 0; z-index: 1002; width: 220px; height: 49px; padding: 0 15px; box-sizing: border-box; overflow: hidden; font-weight: 300; background-repeat: no-repeat; background-position: center center;} -.layui-layout-admin .layui-layout-left, -.layadmin-pagetabs, -.layui-layout-admin .layui-body, -.layui-layout-admin .layui-footer{left: 220px;} -.layadmin-pagetabs{position: fixed; top: 50px; right: 0; z-index: 999;} -.layadmin-pagetabs .layui-breadcrumb{padding: 0 15px;} -.layui-layout-admin .layui-body{position: fixed; top: 90px; bottom: 0;} -.layui-layout-admin .layui-body .layadmin-tabsbody-item{position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow: hidden; overflow-y: auto;} -.layui-layout-admin .layui-header .layui-nav-img{width: 26px; height: 26px;} -.layui-layout-admin .layui-header .layui-nav-child{top: 55px;} -.layui-layout-admin .layui-header .layui-layout-right .layui-nav-child{left: auto; right: 0;} -.layui-layout-admin .layui-header .layui-nav .layui-nav-child dd.layui-this a, -.layui-layout-admin .layui-header .layui-nav .layui-nav-child dd.layui-this{background: none} - -/* 统一动画 */ -.layui-layout-admin .layui-header .layui-nav .layui-nav-item, -.layui-layout-admin .layui-layout-left, -.layadmin-pagetabs, -.layui-layout-admin .layui-body, -.layui-layout-admin .layui-footer, -.layui-layout-admin .layui-side, -.layui-layout-admin .layui-logo, -.layui-layout-admin .layui-header .layui-layout-right{transition: all .3s; -webkit-transition: all .3s;} - -/* 图标 */ -.layui-icon-login-qq{color: #3492ED;} -.layui-icon-login-wechat{color: #4DAF29;} -.layui-icon-login-weibo{color: #CF1900;} - -/* 重置表格风格 */ -/* -.layui-table th, -.layui-table td, -.layui-table[lay-skin="line"], -.layui-table[lay-skin="row"], -.layui-table-view, -.layui-table-header, -.layui-table-tool, -.layui-table-page, -.layui-table-fixed-r, -.layui-table-tips-main{border-color: #f6f6f6;} - -.layui-table thead tr, -.layui-table-header, -.layui-table-tool, -.layui-table-patch, -.layui-table-mend{background-color: #fff;} - -.layui-table[lay-even] tr:nth-child(even), -.layui-table tbody tr:hover, -.layui-table-hover, -.layui-table-click{background-color: #f8f8f8;} -*/ - -/* 表单 */ -.layui-form[wid100] .layui-form-label{width: 100px;} -.layui-form[wid100] .layui-input-block{margin-left: 130px;} -@media screen and (max-width: 450px){ - .layui-form[wid100] .layui-form-item .layui-input-inline{margin-left: 132px;} - .layui-form[wid100] .layui-form-item .layui-input-inline+.layui-form-mid{margin-left: 130px;} -} -.layui-form-item .layui-input-company{width: auto; padding-right: 10px; line-height: 38px;} - -/* 辅助 */ -.layadmin-flexible{} -.layui-bg-white{background-color: #fff;} -.layadmin-loading{position: absolute; left: 50%; top: 50%; margin: -16px -15px; font-size: 30px; color: #c2c2c2;} -.layadmin-fixed{position: fixed; left: 0; top: 0; z-index: 999;} -.layadmin-link{color: #029789!important;} -.layadmin-link:hover{opacity: 0.8;} - -/* 弹出面板 */ -.layui-layer-admin .layui-layer-title{height: 50px; line-height: 50px; border: none 0; background-color: #20222A; color: #fff;} -.layui-layer-admin i[close]{position: absolute; padding: 5px; right: 10px; top: 12px; color: #fff; cursor: pointer;} -.layui-layer-admin .layui-layer-content{padding: 20px; line-height: 22px;} -.layui-layer-admin .layui-layer-content cite{font-style: normal; color: #FF5722;} - -/* 右侧面板 */ -.layui-layer-adminRight{top: 50px !important; bottom: 0; box-shadow: 1px 1px 10px rgba(0,0,0,.1); border-radius: 0; overflow: auto;} - -/* 弹出便签 */ -.layadmin-note .layui-layer-content{padding: 0;} -.layadmin-note textarea{display: block; width: 300px; height: 132px; min-width: 300px; min-height: 132px; line-height: 20px; padding: 10px 20px; border: none; box-sizing: border-box; color: #666; word-wrap: break-word;} - -/* 头部导航 */ -.layui-layout-admin .layui-layout-left{padding: 0 10px;} -.layui-layout-admin .layui-layout-left .layui-nav-item{margin: 0 20px;} -.layui-layout-admin .layui-input-search{display: inline-block; vertical-align: middle; height: 32px; border: none; cursor: text;} -.layui-layout-admin .layui-layout-left a{padding: 0;} -.layui-layout-admin .layui-layout-right{padding: 0;} -.layui-header .layui-nav-item:hover{} -.layui-header .layui-layout-right .layui-badge-dot{margin-left: 0px;} -.layui-header .layui-nav .layui-this:after, -.layui-layout-admin .layui-header .layui-nav-bar{top: 0 !important; bottom: auto; height: 3px; background-color: #fff; background-color: rgba(255,255,255,.3);} - -/* 遮罩 */ -.layadmin-body-shade{position: fixed; display: none; left: 0; right: 0; top: 0; bottom: 0; background-color: rgba(0,0,0,.3); z-index: 1000;} - -/* 侧边菜单 */ -.layui-side-menu .layui-side-scroll{width: 240px;} -.layui-side-menu .layui-nav{width: 220px; margin-top: 50px; background: none;} -.layui-side-menu .layui-nav .layui-nav-item a{padding-left: 45px; padding-right: 30px;} -.layui-side-menu .layui-nav .layui-nav-item a:hover{background: none;} -.layui-side-menu .layui-nav .layui-nav-itemed > .layui-nav-child{padding: 5px 0;} -.layui-side-menu .layui-nav>.layui-nav-item .layui-icon:first-child{position: absolute; top: 50%; left: 20px; margin-top: -19px;} -.layui-side-menu .layui-nav .layui-nav-child .layui-nav-child{background: none!important;} -.layui-side-menu .layui-nav .layui-nav-child .layui-nav-child a{padding-left: 60px} - -/* 侧边菜单 - 平板移动设备 */ -@media screen and (max-width: 992px) { - .layui-layout-admin .layui-side{transform: translate3d(-220px, 0, 0); -webkit-transform: translate3d(-220px, 0, 0); width: 220px;} - .layui-layout-admin .layui-layout-left, - .layadmin-pagetabs, - .layui-layout-admin .layui-body, - .layui-layout-admin .layui-footer{left: 0;} -} - -/* 侧边收缩模式 */ -.layadmin-side-shrink .layui-layout-admin .layui-logo{width: 60px; background-image: url(res/logo.png); /*background-size: 20px;)*/} -.layadmin-side-shrink .layui-layout-admin .layui-logo span{display: none;} -.layadmin-side-shrink .layui-side{left: 0; width: 60px;} -.layadmin-side-shrink .layui-layout-admin .layui-layout-left, -.layadmin-side-shrink .layadmin-pagetabs, -.layadmin-side-shrink .layui-layout-admin .layui-body, -.layadmin-side-shrink .layui-layout-admin .layui-footer{left: 60px;} -.layadmin-side-shrink .layui-side-menu .layui-nav{position: static; width: 60px;} -.layadmin-side-shrink .layui-side-menu .layui-nav-item{position: static;} -.layadmin-side-shrink .layui-side-menu .layui-nav-item>a{padding-right: 0;} -.layadmin-side-shrink .layui-side-menu .layui-nav-item cite, -.layadmin-side-shrink .layui-side-menu .layui-nav > .layui-nav-item > a .layui-nav-more, -.layadmin-side-shrink .layui-side-menu .layui-nav > .layui-nav-item > .layui-nav-child{display: none; padding: 8px 0; width: 200px;} -.layadmin-side-shrink .layui-side-menu .layui-nav > .layui-nav-itemed>a{background: rgba(0,0,0,.3);} - -/* 移动端展开模式 */ -.layadmin-side-spread-sm .layui-layout-admin .layui-layout-left, -.layadmin-side-spread-sm .layadmin-pagetabs, -.layadmin-side-spread-sm .layui-layout-admin .layui-body, -.layadmin-side-spread-sm .layui-layout-admin .layui-footer{left: 0; transform: translate3d(220px, 0, 0); -webkit-transform: translate3d(220px, 0, 0);} -.layadmin-side-spread-sm .layui-layout-admin .layui-layout-right{transform: translate3d(220px, 0, 0); -webkit-transform: translate3d(220px, 0, 0);} -.layadmin-side-spread-sm .layui-side{transform: translate3d(0, 0, 0); -webkit-transform: translate3d(0, 0, 0);} -.layadmin-side-spread-sm .layadmin-body-shade{display: block; } - - -/* 页面标签 */ -.layadmin-pagetabs{height: 40px; line-height: 40px; padding: 0 80px 0 40px; /*border-bottom: 2px solid #292B34;*/ background-color: #fff; box-sizing: border-box; box-shadow: 0 1px 2px 0 rgba(0,0,0,.1);} -.layadmin-pagetabs .layadmin-tabs-control{position: absolute; top: 0; width: 40px; height: 100%; text-align: center; cursor: pointer; transition: all .3s; -webkit-transition: all .3s; box-sizing: border-box; border-left: 1px solid #f6f6f6;} -.layadmin-pagetabs .layadmin-tabs-control:hover{background-color: #f6f6f6;} -.layadmin-pagetabs .layui-icon-prev{left: 0; border-left: none; border-right: 1px solid #f6f6f6;} -.layadmin-pagetabs .layui-icon-next{right: 40px; right: 40px;} -.layadmin-pagetabs .layui-icon-down{right: 0;} -.layadmin-tabs-select.layui-nav{position: absolute; left: 0; top: 0; width: 100%; height: 100%; padding: 0; background: none;} -.layadmin-tabs-select.layui-nav .layui-nav-item{line-height: 40px;} -.layadmin-tabs-select.layui-nav .layui-nav-item>a{height: 40px;} -.layadmin-tabs-select.layui-nav .layui-nav-item a{color: #666;} -.layadmin-tabs-select.layui-nav .layui-nav-child{top: 40px; left: auto; right: 0;} -.layadmin-tabs-select.layui-nav .layui-nav-child dd.layui-this, -.layadmin-tabs-select.layui-nav .layui-nav-child dd.layui-this a{background-color: #f2f2f2!important; color: #333;} -.layadmin-tabs-select.layui-nav .layui-nav-more, -.layadmin-tabs-select.layui-nav .layui-nav-bar{display: none;} - -.layadmin-pagetabs .layui-tab{margin: 0; overflow: hidden;} -.layadmin-pagetabs .layui-tab-title{height: 40px; border: none;} -.layadmin-pagetabs .layui-tab-title li{min-width: 0; line-height: 40px; max-width: 160px; text-overflow: ellipsis; padding-right: 40px; overflow: hidden; border-right: 1px solid #f6f6f6; vertical-align: top;} -.layadmin-pagetabs .layui-tab-title li:first-child{ padding-right: 15px;} -.layadmin-pagetabs .layui-tab-title li:first-child .layui-tab-close{display: none;} -.layadmin-pagetabs .layui-tab-title li .layui-tab-close{position: absolute; right: 8px; top: 50%; margin: -7px 0 0 0; width: 16px; height: 16px; line-height: 16px; border-radius: 50%; font-size: 12px;} -.layadmin-pagetabs .layui-tab-title li:after{content:''; position: absolute; top: 0; left: 0; width: 0; height: 2px; border-radius: 0; background-color: #292B34; transition: all .3s; -webkit-transition: all .3s;} -.layadmin-pagetabs .layui-tab-title li:hover:after{width: 100%;} -.layadmin-pagetabs .layui-tab-title li:hover, -.layadmin-pagetabs .layui-tab-title li.layui-this{background-color: #f6f6f6;} -.layadmin-pagetabs .layui-tab-title li.layui-this:after{width: 100%; border: none; height: 2px; background-color: #292B34;} - -/* 不开启页面标签时 */ -.layadmin-tabspage-none .layui-layout-admin .layui-header{border-bottom: none; box-shadow: 0 1px 2px 0 rgba(0,0,0,.05);} -.layadmin-tabspage-none .layui-layout-admin .layui-body{top: 50px;} -.layadmin-tabspage-none .layadmin-header{display: block;} -.layadmin-tabspage-none .layadmin-header .layui-breadcrumb{border-top: 1px solid #f6f6f6;} - -/* 底部固定区域 */ -.layui-layout-admin .layui-footer{padding: 10px 0; text-align: center;} - -/* 默认主题修饰 */ -.layui-layout-admin .layui-header{border-bottom: 1px solid #f6f6f6; box-sizing: border-box; background-color: #fff;} -.layui-layout-admin .layui-header a, -.layui-layout-admin .layui-header a cite{color: #333;} -.layui-layout-admin .layui-header a:hover{color: #000;} -.layui-layout-admin .layui-header .layui-nav .layui-nav-more{border-top-color: #666} -.layui-layout-admin .layui-header .layui-nav .layui-nav-mored{border-color: transparent; border-bottom-color: #666;} -.layui-layout-admin .layui-header .layui-nav .layui-this:after, -.layui-layout-admin .layui-header .layui-nav-bar{height: 2px; background-color: #20222A} -.layui-layout-admin .layui-logo{background-color: #20222A; box-shadow: 0 1px 2px 0 rgba(0,0,0,.15);} -.layui-layout-admin .layui-logo, -.layui-layout-admin .layui-logo a{color: #fff; color: rgba(255,255,255,.8)} -.layui-side-menu{box-shadow: 1px 0 2px 0 rgba(0,0,0,.05);} -.layui-layout-admin .layui-footer{box-shadow: 0 -1px 2px 0 rgba(0,0,0,.05);} - -.layui-side-menu, -.layadmin-setTheme-side{background-color: #20222A; color: #fff;} -.layadmin-setTheme-header{background-color: #fff;} - -.layui-layout-admin .layui-footer{background-color: #fff;} -.layui-tab-admin .layui-tab-title{background-color: #393D49; color: #fff;} - - -/* - - 格局 - -*/ - -.layui-fluid{padding: 15px;} -.layadmin-header{display: none; height: 50px; line-height: 50px; margin-bottom: 0; border-radius: 0;} -.layadmin-header .layui-breadcrumb{padding: 0 15px;} -.layui-card-header{position: relative;} -.layui-card-header .layui-icon{line-height: initial; position: absolute; right: 15px; top: 50%; margin-top: -7px;} -.layadmin-iframe{position: absolute; width: 100%; height: 100%; left: 0; top: 0; right: 0; bottom: 0;} - - -/* - - 控制台 - -*/ - - -/* 重置轮播样式 */ -.layadmin-carousel{height: 185px !important; background-color: #fff;} -.layadmin-carousel .layui-carousel-ind li{background-color: #e2e2e2;} -.layadmin-carousel .layui-carousel-ind li:hover{background-color: #c2c2c2;} -.layadmin-carousel .layui-carousel-ind li.layui-this{background-color: #999;} -.layadmin-carousel .layui-carousel, -.layadmin-carousel > *[carousel-item] > *{background-color: #fff;} -.layadmin-carousel .layui-col-space10{margin: 0;} -.layadmin-carousel .layui-carousel-ind{position: absolute; top: -41px; text-align: right;} -.layadmin-carousel .layui-carousel-ind ul{background: none;} - -/* 重置tab样式 */ -.layui-card .layui-tab-brief .layui-tab-title{height: 42px; border-bottom-color: #f6f6f6;} -.layui-card .layui-tab-brief .layui-tab-title li{margin: 0 15px; padding: 0; line-height: 42px;} -.layui-card .layui-tab-brief .layui-tab-title li.layui-this{color: #333;} -.layui-card .layui-tab-brief .layui-tab-title .layui-this:after{height: 43px;} -.layui-card .layui-tab-brief .layui-tab-content{padding: 15px;} -.layui-card .layui-table-view{margin: 0;} - -/* 快捷方式 */ -.layadmin-shortcut li{text-align: center;} -.layadmin-shortcut li .layui-icon{display: inline-block; width: 100%; height: 60px; line-height: 60px; text-align: center; border-radius: 2px; font-size: 30px; background-color: #F8F8F8; color: #333; transition: all .3s; -webkit-transition: all .3s;} -.layadmin-shortcut li cite{position: relative; top: 2px; display: block; color: #666; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; font-size: 14px;} -.layadmin-shortcut li:hover .layui-icon{background-color: #f2f2f2;} - -/* 待办事项 */ -.layadmin-backlog .layadmin-backlog-body{display: block; padding: 10px 15px; background-color: #f8f8f8; color: #999; border-radius: 2px; transition: all .3s; -webkit-transition: all .3s;} -.layadmin-backlog-body h3{padding-bottom: 10px; font-size: 12px;} -.layadmin-backlog-body p cite{font-style: normal; font-size: 30px; font-weight: 300; color: #009688;} -.layadmin-backlog-body:hover{background-color: #f2f2f2; color: #888;} - -/* 版本信息 */ -.layadmin-version .layui-table{padding: 6px 0;} -.layadmin-version .layui-table td, -.layadmin-version .layui-table th{line-height: 25px;} - -/* 数据概览 */ -.layadmin-dataview{height: 332px !important;} -.layadmin-dataview>*[carousel-item]:before{display: none;} -.layadmin-dataview>*[carousel-item]>div{height: 332px;} - -/* 控制台效果报告 */ -.layadmin-takerates{padding-top: 5px;} -.layadmin-takerates .layui-progress{margin: 50px 0 60px;} -.layadmin-takerates .layui-progress:last-child{margin-bottom: 10px;} -.layadmin-takerates .layui-progress h3{position: absolute; right: 0; top: -35px; color: #999; font-size: 14px;} -.layadmin-takerates .layui-progress-bar{text-align: left;} -.layadmin-takerates .layui-progress-text{top: -35px; line-height: 26px; font-size: 26px;} - -/* 产品动态 */ -.layadmin-news{height: 60px !important; padding: 5px 0;} -.layadmin-news a{display: block; line-height: 60px; text-align: center;} -.layadmin-news .layui-carousel-ind{height: 45px;} - -/* 文字列表 */ -.layadmin-list li{margin-bottom: 6px; padding-bottom: 6px; border-bottom-color: #f6f6f6; list-style-position: inside; list-style-type: disc;} -.layadmin-list li{text-overflow: ellipsis; overflow: hidden; white-space: nowrap;} -.layadmin-list li a{color: #666;} -.layadmin-list li a:hover{color: #009688;} -.layadmin-list li:last-child{border: none; padding: 0; margin: 0;} - -/* 文本区域 */ -.layadmin-text p{margin-bottom: 10px; text-indent: 2em;} -.layadmin-text p:last-child{margin: 0;} -.layadmin-font-em{font-size: 13px; color: #758697;} - - - - -/******************************** - - 其它主页开始 - -*******************************/ - -/* 主页示例一 */ -/* 进行中的项目 */ -.layui-card-header .layui-a-tips{position: absolute; right: 15px; color: #01AAED;} -.layuiadmin-card-text{background-color: #f8f8f8; color: #777; padding: 24px;} -.layuiadmin-card-text .layui-text-top{padding-bottom: 10px;} -.layuiadmin-card-text .layui-text-top i{margin-right: 10px; font-size: 24px; color: #009688;} -.layuiadmin-card-text .layui-text-top a{line-height: 24px; font-size: 16px; vertical-align: top;} -.layuiadmin-card-text .layui-text-center{height: 44px; line-height: 22px; margin-bottom: 10px; overflow: hidden;} -.layuiadmin-card-text .layui-text-bottom{position: relative;} -.layuiadmin-card-text .layui-text-bottom a{color: #777; font-size: 12px; text-overflow: ellipsis; word-break: break-all;} -.layuiadmin-card-text .layui-text-bottom span{color: #CCC; font-size: 12px; position: absolute; right: 0;} -.layuiadmin-card-text a:hover, -.layuiadmin-card-link a:hover, -.layuiadmin-card-team li a:hover{color: #01AAED; transition: all 300ms;} - -/* 动态 */ -.layuiadmin-card-status{padding: 0 10px 10px 10px;} -.layuiadmin-card-status dd{padding: 15px 0; border-bottom: 1px solid #EEE; display: -webkit-flex; display: flex;} -.layuiadmin-card-status dd:last-child{border: none;} -.layuiadmin-card-status dd div.layui-status-img, -.layuiadmin-card-team .layui-team-img{width: 32px; height: 32px; border-radius: 50%; background-color: #009688; margin-right: 15px;} -.layuiadmin-card-status dd div.layui-status-img a{width: 100%; height: 100%; display: inline-block; text-align: center; line-height: 32px;} -.layuiadmin-card-status dd div.layui-status-img img, -.layuiadmin-card-team .layui-team-img img{width: 50%; height: 50%;} -.layuiadmin-card-status dd div a{color: #01AAED;} -.layuiadmin-card-status dd div span{color: #BBB;} - -/* 便捷导航 */ -.layuiadmin-card-link{padding-left: 10px; font-size: 0} -.layuiadmin-card-link a{display: inline-block; width: 25%; color: #666; font-size: 14px; margin-bottom: 12px;} -.layuiadmin-card-link button{vertical-align: top;} -.layuiadmin-card-link button:hover{color: #009688;} - -/* 团队 */ -.layuiadmin-card-team li{padding: 10px 0 10px 10px;} -.layuiadmin-card-team .layui-team-img{display: inline-block; margin-right: 8px; width: 24px; height: 24px; text-align: center; line-height: 24px;} -.layuiadmin-card-team span{color: #777;} - - -/* 主页示例二 */ -.layuiadmin-badge{position: absolute; top: 50%; margin-top: -9px; right: 15px; color: #01AAED; } -.layuiadmin-card-list{padding: 15px;} -.layuiadmin-card-list p.layuiadmin-big-font{font-size: 36px; color: #666; line-height: 36px; padding: 5px 0 10px; overflow: hidden; text-overflow: ellipsis; word-break: break-all; white-space: nowrap;} -.layuiadmin-card-list p.layuiadmin-normal-font{padding-bottom: 10px; font-size: 20px; color: #666; line-height: 24px;} -.layuiadmin-span-color{font-size: 14px; position: absolute; right: 15px;} -.layuiadmin-span-color i{padding-left: 5px;} -.layuiadmin-btn-group{position: absolute; right: 15px;} - -.layuiadmin-card-status li{position: relative; padding: 10px 0; border-bottom: 1px solid #EEE;} -.layuiadmin-card-status li h3{padding-bottom: 5px; font-weight: 700;} -.layuiadmin-card-status li p{padding-bottom: 10px;} -.layuiadmin-card-status li>span{color: #999;} -.layuiadmin-home2-usernote .layuiadmin-reply{display: none; position: absolute; right: 0; bottom: 12px;} -.layuiadmin-home2-usernote li:hover .layuiadmin-reply{display: block;} - -.layuiadmin-page-table td span{color: #2F4056;} -.layuiadmin-page-table td span.first{color: #FF5722;} -.layuiadmin-page-table td span.second{color: #FFB800;} -.layuiadmin-page-table td span.third{color: #5FB878;} - - -/****** 其它主页结束 ******/ - - - - -/* - - 应用 - -*/ - - -/* 消息中心 */ -.layuiAdmin-msg-detail h1{font-size: 16px;} -.layuiAdmin-msg-detail .layui-card-header{height: auto; line-height: 30px; padding: 15px;} -.layuiAdmin-msg-detail .layui-card-header span{padding: 0 5px; color: #999;} -.layuiAdmin-msg-detail .layui-card-header span:first-child{padding-left: 0;} -.layuiAdmin-msg-detail .layui-card-body{padding: 15px;} - -/* 文章列表 */ -.layuiadmin-content-bread{padding-bottom: 20px;} - -/* 进度条样式 */ -.layuiadmin-order-progress{position: relative; top: 12px;} - - - - -/* - - 系统 - -*/ - - -/* 头部图标重置 */ -.layui-card-header.layuiadmin-card-header-auto{padding-top: 15px; padding-bottom: 15px; height: auto;} -.layuiadmin-card-header-auto i.layuiadmin-button-btn{position: relative; right: 0; top: 0; vertical-align: middle;} -.layuiadmin-card-header-auto .layui-form-item:last-child{margin-bottom: 0;} - - -/* 主题设置 */ -.layadmin-setTheme{padding: 15px; overflow-x: hidden;} -.layadmin-setTheme>h5{padding: 20px 0 10px; color: #000;} -.layadmin-setTheme>h5:first-child{padding-top: 0;} -.layadmin-setTheme-color{width: 330px; font-size: 0;} -.layadmin-setTheme-color li{position: relative; display: inline-block; vertical-align: top; width: 80px; height: 50px; margin: 0 15px 15px 0; background-color: #f2f2f2; cursor: pointer; font-size: 12px; color: #666;} -.layadmin-setTheme-color li:after{content: ''; position: absolute; z-index: 20; top: 50%; left: 50%; width: 1px; height: 0; border: 1px solid #f2f2f2; transition: all .3s; -webkit-transition: all .3s; opacity: 0;} -.layadmin-setTheme-color li.layui-this:after, -.layadmin-setTheme-color li:hover:after{width: 100%; height: 100%; padding: 4px; top: -5px; left: -5px; border-color: #5FB878; opacity: 1;} - -.layadmin-setTheme-header{position: relative; z-index: 10; height: 10px; border-top: 1px solid #f2f2f2; border-right: 1px solid #f2f2f2;} -.layadmin-setTheme-side{position: absolute; left: 0; top: 0; width: 20px; height: 100%; z-index: 11; box-shadow: 1px 0 2px 0 rgba(0,0,0,.05);} -.layadmin-setTheme-logo{position: absolute; left: 0; top: 0; width: 100%; height: 10px; box-shadow: 0 1px 2px 0 rgba(0,0,0,.15);} -.layadmin-form-right{text-align: right;} - - -/* 关于 */ -.layadmin-about p{margin-bottom: 10px;} - -/* 菜单列表 */ -.layadmin-menu-list .layui-card-header{height: 50px; line-height: 50px; font-size: 16px;} -.layadmin-menu-list .layui-card-header:active{background-color: #f2f2f2;} -.layadmin-menu-list .layui-card-header .layui-icon{position: relative; top: 1px; left: 0; display: inline-block; margin: 0 10px 0; font-size: 18px;} - - -/* 动画 */ -@-webkit-keyframes layui-rl{ /* 从右往左滑入 */ - from {-webkit-transform: translate3d(100%, 0, 0);} - to {-webkit-transform: translate3d(0, 0, 0);} -} -@keyframes layui-rl{ - from {transform: translate3d(100%, 0, 0);} - to {transform: translate3d(0, 0, 0);} -} -.layui-anim-rl{-webkit-animation-name: layui-rl; animation-name: layui-rl;} - -@-webkit-keyframes layui-lr{ /* 从右往左滑入 */ - from {-webkit-transform: translate3d(0 0, 0); opacity: 1;} - to {-webkit-transform: translate3d(100%, 0, 0); opacity: 1;} -} -@keyframes layui-lr{ - from {transform: translate3d(0, 0, 0);} - to {transform: translate3d(100%, 0, 0);} -} -.layui-anim-lr{-webkit-animation-name: layui-lr; animation-name: layui-lr;} - -.layui-anim-rl.layer-anim-close{-webkit-animation-name: layui-lr; animation-name: layui-lr;} - - -/* 提示页 */ -.layadmin-tips{margin-top: 30px; text-align: center;} -.layadmin-tips .layui-icon[face]{display: inline-block; font-size: 300px; color: #393D49;} -.layadmin-tips .layui-text{width: 500px; margin: 30px auto; padding-top: 20px; border-top: 5px solid #009688; font-size: 16px;} -.layadmin-tips h1{font-size: 100px; line-height: 100px; color: #009688;} -.layadmin-tips .layui-text .layui-anim{display: inline-block;} - - -/* - - 响应式补充 - -*/ - -@media screen and (max-width: 768px) { - - /* 产品清单模板 */ - .layadmin-panel-selection{margin: 0; width: auto;} - - /* 导航 */ - .layui-body .layui-nav .layui-nav-item{display: block;} - - /* 主体容器 */ - .layui-layout-admin .layui-body .layadmin-tabsbody-item{-webkit-overflow-scrolling: touch; overflow: auto;} -} - - - diff --git a/iot-server/server-starter/src/main/webapp/assets/src/style/login.css b/iot-server/server-starter/src/main/webapp/assets/src/style/login.css deleted file mode 100644 index a666b4bb..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/style/login.css +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * admin.login.css - */ - -html,body,#LAY_app{height:100%;} -.layui-layout-body{overflow: auto;} - -#LAY-user-login, -.layadmin-user-display-show{display: block !important;} -.layadmin-user-login{position: relative; left: 0; top: 0; padding: 110px 0; min-height: 100%; box-sizing: border-box;} -.layadmin-user-login-main{width: 375px; margin: 0 auto; box-sizing: border-box;} -.layadmin-user-login-box{padding: 20px;} -.layadmin-user-login-header{text-align: center;} -.layadmin-user-login-header h2{margin-bottom: 10px; font-weight: 300; font-size: 30px; color: #000;} -.layadmin-user-login-header p{font-weight: 300; color: #999;} - -.layadmin-user-login-body .layui-form-item{position: relative;} -.layadmin-user-login-icon{position: absolute; left: 1px; top: 1px; width: 38px; line-height: 36px; text-align: center; color: #d2d2d2;} -.layadmin-user-login-body .layui-form-item .layui-input{padding-left: 38px;} -.layadmin-user-login-codeimg{max-height: 38px; width: 100%; cursor: pointer; box-sizing: border-box;} - -.layadmin-user-login-other{position: relative; font-size: 0; line-height: 38px; padding-top: 20px;} -.layadmin-user-login-other>*{display: inline-block; vertical-align: middle; margin-right: 10px; font-size: 14px;} -.layadmin-user-login-other .layui-icon{position: relative; top: 2px; font-size: 26px;} -.layadmin-user-login-other a:hover{opacity: 0.8;} - -.layadmin-user-jump-change{float: right;} - -.layadmin-user-login-footer{position: absolute; left: 0; bottom: 0; width: 100%; line-height: 30px; padding: 20px; text-align: center; box-sizing: border-box; color: rgba(0,0,0,.5)} -.layadmin-user-login-footer span{padding: 0 5px;} -.layadmin-user-login-footer a{padding: 0 5px; color: rgba(0,0,0,.5);} -.layadmin-user-login-footer a:hover{color: rgba(0,0,0,1);} - -/* 有背景图时 */ -.layadmin-user-login-main[bgimg]{background-color: #fff; box-shadow: 0 0 5px rgba(0,0,0,0.05);} - -/* 主题背景 */ -.ladmin-user-login-theme{position: fixed; bottom: 0; left: 0; width: 100%; text-align: center;} -.ladmin-user-login-theme ul{display: inline-block; padding: 5px; background-color: #fff;} -.ladmin-user-login-theme ul li{display: inline-block; vertical-align: top; width: 64px; height: 43px; cursor: pointer; transition: all .3s; -webkit-transition: all .3s; background-color: #f2f2f2;} -.ladmin-user-login-theme ul li:hover{opacity: 0.9} - -@media screen and (max-width: 768px) { - .layadmin-user-login{padding-top: 60px;} - .layadmin-user-login-main{width: 300px;} - .layadmin-user-login-box{padding: 10px;} -} - - - diff --git a/iot-server/server-starter/src/main/webapp/assets/src/style/res/bg-none.jpg b/iot-server/server-starter/src/main/webapp/assets/src/style/res/bg-none.jpg deleted file mode 100644 index b7c9e7b864d9354ae00404bb74f1e144ab57e03b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 832 zcmex=76T7ZFOwj%ATaE{cASwgX5%^7Y|PA-aBzk}8jk@^fh}&{hLSo* zQZ@@t1{wl#DNZ;Zwm-mu+Vl>Q_HtgT*9|CH2iZ&kqzz#o5}<- z^#Yj5j9@Y`vDq^@LqriwMn<6MsZ(iN6OA^_TpQuDW?6Qau(sx`t1Z{osD%ZauI8LN zXOKo}2X-UI-(5y<5L diff --git a/iot-server/server-starter/src/main/webapp/assets/src/style/res/layui-logo.jpg b/iot-server/server-starter/src/main/webapp/assets/src/style/res/layui-logo.jpg deleted file mode 100644 index da24fdfc9a047daea9128a967bc13a3766aea200..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2871 zcmds%X;hN=8o*yfvD^ulO4PE&%<(#|xr8*;xTI*Nv}mIfnyD$K=7y$C-LlldYi_v& zR~aq_w?a@xL@vl-t(UGJm>kpzvuTpAO6yA z=>VW{$jQ|S0D(Y2oa_OlJm3HTk(ZZOkcTKJK-NQKuktzwWSz2#l9IBLl8T1PAEBY5 zrmmr`rUHX$YQkV}U0q%HmM`%c0#Z~|R8>*ksG+fOvldiq^Oxp-nn<4j&~+dP2m%H{ z0XZlL3vPxc2 zR{uHoGZ*TmumQH!9P-1dY%Lj;@|3N)ZT}I>C2hm)R?&k~rP3ZiMW!JK1w#QOuw1xx z-xufqgJgY?UIFoho1a!S9QKGEI*LYZqICCGIO$_{Umq>+q6SWUdT^mu5`kJGrBOsa z?z@^Jl8y=9XMRXN>|=59+Y2DxopWRbxGWXov=`@6!bGoaj3Q1+ZYB~I6IXnTJL)T{ z6Z-v}1kN|yoXQ?n#^AkGuD)UOT*>#1N9+6@;ybm;(FOaTV1}S!CXA((&w_4j5(}X{A+U2kZn-hQL|rgMpLhigR+16CJlfTB*W?OEKdcBV_(+b zP5cNC7>0YfRrNJKJ$~5Q@iOi%yc8(oygz?(uj6D^ytw(J@cUG36Cr6Xv7HnqwD;Dd zj&F-sM@+}g#&?D>aF$DE5ooj*b~4piL)yz%TIYB{Iw3#FtX5R_;nZ==Qm!_*X|Tn;@pGYh0<;5wr7jspCY(=oL=K7yN7K?s_3GT^heB^&NRK?I{h5a zaIR2d(vN+X=)=#u+>B1)d+AGob%7C~^hyrb@^MNPJ_BVA%{`y?^zd5S?(p_=;UYw8 znGyHaZahAoR@2vV3|YP7h=$^x$iwEonf@=la&#_n42rfhD+WJC@+xaF@IEsDQ0s{Z zCZSTk(-|xj;GZuryGybuwr=s|yN9eMX}A^MgQ&^LUZf~M`*_o!&@naR^~#noYu{f{ zl3D*q#4YyB6`0+few;PoJ zP#*85#D)+cxYl%g+sTQ38`GCUYsXE^a#ww1kbclV)}ny*4h}kW?$4y4zMUyvugHX| zr2QX<(}sSgs3QFpC(M#()u`jo;ZZ1jn15HNYQb4fh9>S)b?k#d$c0v=hxL_h5DUS(_xbZRK0lTSN-=yRU_P`14$-c&LhOjPLDYk0R;nN!Any8yz>|}krs!o z^G6V^H@pZ106nX@4{tGb7X${y-6vYm3~coj@p1$r6dRmDqh;501nBhR^X*ovq(E3$ z<{mSY^g;`pb%qd<3o{n{<_u#j^XvK4NJ#gFbRsj+Bc_L6}-P`y2Nnd6B(g!su{4 zLJPLH2x*lnw9HU#`FcN)tei!&)0blR;0ckJ+lh}>$iCRVwn;7%pF1a(-F){1pHHXJ zX%Az4ja$4K{|1paFsK~oqo#9;XH^q^K1!8Th>}WcaHz*qwa~B5E?Fl6B;#`#emO__GG)C zRz+^QR?H1WwA^6;{f1!YC?I$`8I?<7R71RzpI;5`rm15{Rwx|%5SiX3{b5^>`?6xp&Ji+P}JoHzSf`ms{oDt LmH+Q&(s#cDsUr%7 diff --git a/iot-server/server-starter/src/main/webapp/assets/src/style/res/logo-black.png b/iot-server/server-starter/src/main/webapp/assets/src/style/res/logo-black.png deleted file mode 100644 index 73e5ebcb43833eeb621ff764dc7e44323c9afe10..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 455 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~q!3HGX7W?Z1DVAa<&kznEsNqQI0P;BtJR*x3 z7=(O5nDO)UBg=t;VkNE-CC){ui6xo&c?uz!xv30>hWbX9`iACTwud+YRmgx;1m~xf zlqVLYGB~E>C#5R5WfrBD=NDxcD>w(6z1XvIwhi*x%GkhWbX9`iACTwud+YRmgx;1m~xf zlqVLYGB~E>C#5R5WfrBD=NDxcD>w(6z1Xv?mq)LJVQ&Orvhh3ZhBjJwL{si@i8$Z~hZfH6NoY=UdxG=(8f}dx% z_2%ldXJ^60g?*18$|4;XJS`KiBE zP^;Mbm-T|g=Ve?zOF2#{gdNR$^iinwM)`p_p9$`fza4ayELhkM@D;Fx{Arb3@buj6 zXVt~~qEFvp%WIezUgCPGyY7R|%E5ZPMa}8-t3p_tY z``aAc)A=}%`4wlAYjl6(8WjtMYm2)ZlZ@m}-}uo`n;@XFmMQ#zo6_yck!&@AFSa~; u)bDs{X{bSo?#XMB;jRpJjpgF&>zVIg*(;naCF>3hR0dC1KbLh*2~7ZTNv#_I diff --git a/iot-server/server-starter/src/main/webapp/assets/src/style/res/template/character.jpg b/iot-server/server-starter/src/main/webapp/assets/src/style/res/template/character.jpg deleted file mode 100644 index 33c7691aa62991324afeed6acfd220e0b3ae4e85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6727 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 YMAsk3Colp2V*^C?oswj!xbcVo13N#e{r~^~ diff --git a/iot-server/server-starter/src/main/webapp/assets/src/style/res/template/portrait.png b/iot-server/server-starter/src/main/webapp/assets/src/style/res/template/portrait.png deleted file mode 100644 index 33c7691aa62991324afeed6acfd220e0b3ae4e85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6727 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评论管理 - - - -
                                      -
                                      -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      -
                                      -
                                      -
                                      -
                                      - -
                                      -
                                      - -
                                      -
                                      -
                                      - - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/contform.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/contform.html deleted file mode 100644 index fc24c49e..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/contform.html +++ /dev/null @@ -1,20 +0,0 @@ - - -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/list.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/list.html deleted file mode 100644 index 126882cb..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/list.html +++ /dev/null @@ -1,151 +0,0 @@ - - - 文章列表 - -
                                      - -
                                      - -
                                      -
                                      -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      -
                                      -
                                      - -
                                      -
                                      - - -
                                      -
                                      - - -
                                      -
                                      -
                                      - - diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/listform.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/listform.html deleted file mode 100644 index c916f443..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/listform.html +++ /dev/null @@ -1,67 +0,0 @@ -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      - -
                                      - -
                                      - -
                                      -
                                      -
                                      diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/tags.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/tags.html deleted file mode 100644 index ad15f3fa..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/tags.html +++ /dev/null @@ -1,65 +0,0 @@ -分类管理 - - - -
                                      -
                                      -
                                      - -
                                      -
                                      -
                                      - -
                                      -
                                      -
                                      - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/tagsform.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/tagsform.html deleted file mode 100644 index bdd5521c..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/app/content/tagsform.html +++ /dev/null @@ -1,17 +0,0 @@ -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/list.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/list.html deleted file mode 100644 index ad817aaa..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/list.html +++ /dev/null @@ -1,124 +0,0 @@ -帖子列表 - - - -
                                      -
                                      -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      -
                                      -
                                      - -
                                      -
                                      - -
                                      -
                                      - - - -
                                      -
                                      -
                                      - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/listform.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/listform.html deleted file mode 100644 index 95be57fa..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/listform.html +++ /dev/null @@ -1,53 +0,0 @@ -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      - -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/replys.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/replys.html deleted file mode 100644 index 3e3fa07c..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/replys.html +++ /dev/null @@ -1,99 +0,0 @@ - - -回帖列表 - - - -
                                      -
                                      -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      -
                                      -
                                      -
                                      -
                                      - -
                                      -
                                      - - -
                                      -
                                      -
                                      - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/replysform.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/replysform.html deleted file mode 100644 index 08c45b60..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/app/forum/replysform.html +++ /dev/null @@ -1,34 +0,0 @@ -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/message/detail.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/message/detail.html deleted file mode 100644 index 59a34432..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/app/message/detail.html +++ /dev/null @@ -1,42 +0,0 @@ -消息详情 - - - -
                                      -
                                      -
                                      -
                                      -

                                      {{ d.data.title }}

                                      -

                                      - {{ layui.util.timeAgo(d.data.time) }} -

                                      -
                                      -
                                      -
                                      - {{ d.data.content }} -
                                      - - -
                                      -
                                      -
                                      -
                                      - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/message/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/message/index.html deleted file mode 100644 index 85f169f8..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/app/message/index.html +++ /dev/null @@ -1,176 +0,0 @@ - -消息中心 - -
                                      - -
                                      - -
                                      -
                                      -
                                      -
                                        -
                                      • 全部消息
                                      • -
                                      • 通知6
                                      • -
                                      • 私信
                                      • -
                                      -
                                      - -
                                      -
                                      - - - -
                                      - -
                                      -
                                      -
                                      - -
                                      - - - -
                                      - -
                                      -
                                      -
                                      - -
                                      - - - -
                                      - -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/workorder/list.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/workorder/list.html deleted file mode 100644 index 011d884d..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/app/workorder/list.html +++ /dev/null @@ -1,89 +0,0 @@ - - -工单系统 - - - -
                                      -
                                      -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      -
                                      -
                                      -
                                      -
                                      - - - -
                                      -
                                      -
                                      - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/app/workorder/listform.html b/iot-server/server-starter/src/main/webapp/assets/src/views/app/workorder/listform.html deleted file mode 100644 index c66c5ec7..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/app/workorder/listform.html +++ /dev/null @@ -1,59 +0,0 @@ - - -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - -
                                      - -
                                      -
                                      -
                                      - - \ No newline at end of file diff --git "a/iot-server/server-starter/src/main/webapp/assets/src/views/app/\350\257\264\346\230\216.txt" "b/iot-server/server-starter/src/main/webapp/assets/src/views/app/\350\257\264\346\230\216.txt" deleted file mode 100644 index 1f8f3e55..00000000 --- "a/iot-server/server-starter/src/main/webapp/assets/src/views/app/\350\257\264\346\230\216.txt" +++ /dev/null @@ -1,2 +0,0 @@ - -该目录存放【应用】的视图文件 \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/anim/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/anim/index.html deleted file mode 100644 index 7e9abd33..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/anim/index.html +++ /dev/null @@ -1,108 +0,0 @@ - -动画 - -
                                      -
                                      - 主页 - 组件 - 动画 -
                                      -
                                      - - - -
                                      -
                                      -
                                      -
                                      -
                                      点击演示动画
                                      -
                                      - -
                                        -
                                      • -
                                        从最底部往上滑入
                                        -
                                        layui-anim-up
                                        -
                                      • -
                                      • -
                                        微微往上滑入
                                        -
                                        layui-anim-upbit
                                        -
                                      • -
                                      • -
                                        平滑放大
                                        -
                                        layui-anim-scale
                                        -
                                      • -
                                      • -
                                        弹簧式放大
                                        -
                                        layui-anim-scaleSpring
                                        -
                                      • -
                                      -
                                        -
                                      • -
                                        渐现
                                        -
                                        layui-anim-fadein
                                        -
                                      • -
                                      • -
                                        渐隐
                                        -
                                        layui-anim-fadeout
                                        -
                                      • -
                                      • -
                                        360度旋转
                                        -
                                        layui-anim-rotate
                                        -
                                      • -
                                      • -
                                        循环动画
                                        -
                                        追加:layui-anim-loop
                                        -
                                      • -
                                      - -
                                      -
                                      -
                                      -
                                      -
                                      - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/auxiliar/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/auxiliar/index.html deleted file mode 100644 index 4104a5ca..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/auxiliar/index.html +++ /dev/null @@ -1,103 +0,0 @@ - -辅助元素 - -
                                      -
                                      - 主页 - 组件 - 辅助 -
                                      -
                                      - - - -
                                      -
                                      -
                                      -
                                      -
                                      引用区块
                                      -
                                      -
                                      这个貌似不用多介绍,因为你已经在太多的地方都看到
                                      - -
                                      - 猿强,则国强。国强,则猿更强! -
                                      ——孟子(好囖。。其实这特喵的是我说的) -
                                      -
                                      -
                                      -
                                      -
                                      字段集区块
                                      -
                                      - -
                                      - 爱好 -
                                      - 你可以在这里放任何内容,比如表单神马的 -
                                      -
                                      - -
                                      - -
                                      - 带标题的横线 -
                                      - -
                                      -
                                      -
                                      -
                                      分割线
                                      -
                                      - - 默认分割线 -
                                      - - 赤色分割线 -
                                      - - 橙色分割线 -
                                      - - 墨绿分割线 -
                                      - - 青色分割线 -
                                      - - 蓝色分割线 -
                                      - - 黑色分割线 -
                                      - - 灰色分割线 -
                                      - -
                                      -
                                      -
                                      -
                                      纯圆角
                                      -
                                      - -
                                      - -
                                      - -
                                      -
                                      -
                                      -
                                      -
                                      - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/badge/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/badge/index.html deleted file mode 100644 index b1221a42..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/badge/index.html +++ /dev/null @@ -1,103 +0,0 @@ - -徽章 - -
                                      -
                                      - 主页 - 组件 - 徽章 -
                                      -
                                      - - - -
                                      -
                                      -
                                      -
                                      -
                                      小徽章大家族
                                      -
                                      - -
                                      小圆点: - - - - - - - - - -

                                      常规弧形徽章: - - 6 - 99 - 61728 - - - 绿 - - - - - -

                                      边框徽章: - - 6 - Hot - -

                                      - -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      与其它元素的搭配
                                      -
                                      - -
                                      - - - - -

                                      - -
                                        <-- 小Tips:这里有没有发现,设置导航靠右对齐(或居中对齐)其实非常简单 --> -
                                      • - 控制台9 -
                                      • -
                                      • - 个人中心 -
                                      • -
                                      -
                                      - -
                                      -
                                        -
                                      • 网站设置
                                      • -
                                      • 用户管理
                                      • -
                                      • 最新邮件99+
                                      • -
                                      -
                                      -
                                      - -
                                      -
                                      -
                                      -
                                      -
                                      - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/button/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/button/index.html deleted file mode 100644 index 9a6c7e74..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/button/index.html +++ /dev/null @@ -1,178 +0,0 @@ - -按钮 - -
                                      -
                                      - 主页 - 组件 - 按钮 -
                                      -
                                      - -
                                      -
                                      -
                                      -
                                      -
                                      按钮主题
                                      -
                                      -
                                      - - - - - - -
                                      -
                                      -
                                      -
                                      -
                                      按钮尺寸
                                      -
                                      -
                                      - - - - - -
                                      - - - - - - -
                                      - - - - - -
                                      -
                                      -
                                      -
                                      -
                                      按钮图标
                                      -
                                      -
                                      - - - - - - - -
                                      - - - - - - - - -
                                      - - - - - - - - -
                                      - - - - - - - - -
                                      - - - - - - - -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      按钮圆角
                                      -
                                      -
                                      - - - - - - -
                                      -
                                      -
                                      -
                                      -
                                      按钮混搭
                                      -
                                      -
                                      - - 跳转的按钮 - - - -
                                      -
                                      -
                                      -
                                      -
                                      按钮组合
                                      -
                                      -
                                      -
                                      - - - -
                                      -
                                      -
                                      -
                                      - - - - -
                                      -
                                      - - - - -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      按钮铺满
                                      -
                                      -
                                      - - - - -
                                      -
                                      -
                                      -
                                      - -
                                      -
                                      - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/carousel/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/carousel/index.html deleted file mode 100644 index 292111a8..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/carousel/index.html +++ /dev/null @@ -1,219 +0,0 @@ - - - 轮播 - - - -
                                      -
                                      - 主页 - 组件 - 轮播 -
                                      -
                                      - - - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/code/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/code/index.html deleted file mode 100644 index 9027d91a..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/code/index.html +++ /dev/null @@ -1,141 +0,0 @@ - - - 代码修饰 - -
                                      - -
                                      - -
                                      -
                                      -
                                      -
                                      -
                                      默认修饰
                                      -
                                      -
                                      //在里面存放任意的代码
                                      -Lay.fn.event = function(modName, events, params){
                                      -  var that = this, result = null, filter = events.match(/\(.*\)$/)||[];
                                      -  var set = (events = modName + '.'+ events).replace(filter, ''); 
                                      -};
                                      -            
                                      -
                                      -
                                      - -
                                      -
                                      notepad风格
                                      -
                                      -
                                      //代码区域
                                      -Lay.fn.event = function(modName, events, params){
                                      -  var that = this, result = null, filter = events.match(/\(.*\)$/)||[];
                                      -  var set = (events = modName + '.'+ events).replace(filter, ''); 
                                      -};
                                      -            
                                      -
                                      -
                                      - -
                                      -
                                      代码中的代码
                                      -
                                      -
                                      //代码区域
                                      -Lay.fn.event = function(modName, events, params){
                                      -  var that = this, result = null, filter = events.match(/\(.*\)$/)||[];
                                      -  var set = (events = modName + '.'+ events).replace(filter, ''); 
                                      -};
                                      -      
                                      //代码区域
                                      -Lay.fn.event = function(modName, events, params){
                                      -  var that = this, result = null, filter = events.match(/\(.*\)$/)||[];
                                      -  var set = (events = modName + '.'+ events).replace(filter, ''); 
                                      -};
                                      -      
                                      -
                                      - -
                                      //代码区域
                                      -Lay.fn.event = function(modName, events, params){
                                      -  var that = this, result = null, filter = events.match(/\(.*\)$/)||[];
                                      -  var set = (events = modName + '.'+ events).replace(filter, ''); 
                                      -};
                                      -      
                                      //代码区域
                                      -Lay.fn.event = function(modName, events, params){
                                      -  var that = this, result = null, filter = events.match(/\(.*\)$/)||[];
                                      -  var set = (events = modName + '.'+ events).replace(filter, ''); 
                                      -};
                                      -
                                      //代码区域
                                      -Lay.fn.event = function(modName, events, params){
                                      -  var that = this, result = null, filter = events.match(/\(.*\)$/)||[];
                                      -  var set = (events = modName + '.'+ events).replace(filter, ''); 
                                      -};
                                      -
                                      //代码区域
                                      -Lay.fn.event = function(modName, events, params){
                                      -  var that = this, result = null, filter = events.match(/\(.*\)$/)||[];
                                      -  var set = (events = modName + '.'+ events).replace(filter, ''); 
                                      -};
                                      -
                                      //代码区域
                                      -Lay.fn.event = function(modName, events, params){
                                      -  var that = this, result = null, filter = events.match(/\(.*\)$/)||[];
                                      -  var set = (events = modName + '.'+ events).replace(filter, ''); 
                                      -};
                                      -            
                                      -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      - -
                                      -
                                      固定高度
                                      -
                                      -
                                      //代码区域
                                      -Lay.fn.event = function(modName, events, params){
                                      -  var that = this, result = null, filter = events.match(/\(.*\)$/)||[]; //提取事件过滤器
                                      -  var set = (events = modName + '.'+ events).replace(filter, ''); //获取事件本体名
                                      -  var callback = function(_, item){
                                      -    var res = item && item.call(that, params);
                                      -    res === false && result === null && (result = false);
                                      -  };
                                      -  layui.each(config.event[set], callback);
                                      -  filter[0] && layui.each(config.event[events], callback); //执行过滤器中的事件
                                      -  return result;
                                      -};
                                      -            
                                      -
                                      -
                                      - -
                                      -
                                      XXX
                                      -
                                      - -
                                      -
                                      - -
                                      -
                                      XXX
                                      -
                                      - -
                                      -
                                      - -
                                      -
                                      XXX
                                      -
                                      - -
                                      -
                                      - -
                                      -
                                      -
                                      - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/colorpicker/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/colorpicker/index.html deleted file mode 100644 index 76e8cff9..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/colorpicker/index.html +++ /dev/null @@ -1,190 +0,0 @@ - - - 颜色选择器组件 - - - -
                                      -
                                      -
                                      -
                                      -
                                      常规使用
                                      -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      表单赋值
                                      -
                                      -
                                      -
                                      -
                                      - -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      RGB / RGBA 色值
                                      -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      透明度选择
                                      -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      预定义颜色项
                                      -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      全功能和回调的使用
                                      -
                                      - -
                                      -
                                      -
                                      -
                                      -
                                      颜色框尺寸
                                      -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/dropdown/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/dropdown/index.html deleted file mode 100644 index 3f91c9e2..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/dropdown/index.html +++ /dev/null @@ -1,571 +0,0 @@ - - - 下拉菜单 - - - -
                                      -
                                      -
                                      -
                                      -
                                      初演示
                                      -
                                      - -
                                      - - - -
                                      - -
                                      - -
                                      -
                                      - 可以绑定任意元素,比如这段文字 -
                                      - -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      在表格中的应用
                                      -
                                      - -
                                      - - -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      自定义事件
                                      -
                                      - -
                                      - - - -
                                      - -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      右键菜单
                                      -
                                      - -
                                      - 在此区域单击鼠标右键 -
                                      - - -
                                      -
                                      -
                                      -
                                      -
                                      -
                                      重定义风格
                                      -
                                      - -
                                      - - - -
                                      - -
                                      -
                                      -
                                      -
                                      -
                                      - - - diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/flow/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/flow/index.html deleted file mode 100644 index 31b877da..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/flow/index.html +++ /dev/null @@ -1,124 +0,0 @@ - - - 流加载 - - - - -
                                      - -
                                      - -
                                      -
                                      -
                                      -
                                      -
                                      信息流 - 滚动加载
                                      -
                                      -
                                        -
                                        -
                                        -
                                        - -
                                        -
                                        -
                                        信息流 - 手工加载
                                        -
                                        -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          图片懒加载
                                          -
                                          -
                                          - - - - - - - - - - - - - - - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/form/element.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/form/element.html deleted file mode 100644 index 1bfb120a..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/form/element.html +++ /dev/null @@ -1,237 +0,0 @@ - -表单元素 - - - - - -
                                          -
                                          -
                                          -
                                          -
                                          输入框
                                          -
                                          -
                                          - -
                                          -
                                          - -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          下拉选择框
                                          -
                                          -
                                          - -
                                          -
                                          - -
                                          -
                                          - -
                                          -
                                          - -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          复选框
                                          -
                                          -
                                          - - - -
                                          -
                                          - - - - -
                                          -
                                          -
                                          -
                                          -
                                          开关
                                          -
                                          -
                                          - - - - -
                                          -
                                          -
                                          -
                                          -
                                          单选框
                                          -
                                          -
                                          - - - -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          文本域
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          响应式组合
                                          -
                                          -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          - - - - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - - - - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          -
                                          - - -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/form/group.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/form/group.html deleted file mode 100644 index ca39f880..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/form/group.html +++ /dev/null @@ -1,291 +0,0 @@ - -表单组合 - - - -
                                          -
                                          -
                                          表单组合
                                          -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          - -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          请填写6到12位密码
                                          -
                                          - -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          - -
                                          -
                                          - - -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          - -
                                          -
                                          - -
                                          -
                                          - -
                                          -
                                          -
                                          此处只是演示联动排版,并未做联动交互
                                          -
                                          -
                                          -
                                          - -
                                          - -
                                          - - - -
                                          -
                                          - -
                                          - -
                                          - - - -
                                          -
                                          - -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - - - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/all.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/all.html deleted file mode 100644 index d55c8723..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/all.html +++ /dev/null @@ -1,80 +0,0 @@ - -全端复杂组合 - - - - - -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/list.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/list.html deleted file mode 100644 index 28fe1f77..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/list.html +++ /dev/null @@ -1,122 +0,0 @@ - -等比例列表排列 - - - - - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/mobile-pc.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/mobile-pc.html deleted file mode 100644 index 6dab654a..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/mobile-pc.html +++ /dev/null @@ -1,80 +0,0 @@ - -移动桌面组合 - - - - - -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/mobile.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/mobile.html deleted file mode 100644 index b38ffa68..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/mobile.html +++ /dev/null @@ -1,112 +0,0 @@ - -按移动端排列 - - - - - -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/speed-dial.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/speed-dial.html deleted file mode 100644 index 06f6b11d..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/speed-dial.html +++ /dev/null @@ -1,84 +0,0 @@ - -九宫格 - -
                                          - -
                                          - - - -
                                          -
                                          -
                                          - -
                                          -
                                          1
                                          -
                                          -
                                          -
                                          -
                                          -
                                          2
                                          -
                                          -
                                          -
                                          -
                                          -
                                          3
                                          -
                                          -
                                          -
                                          -
                                          -
                                          4
                                          -
                                          -
                                          -
                                          -
                                          -
                                          5
                                          -
                                          -
                                          -
                                          -
                                          -
                                          6
                                          -
                                          -
                                          -
                                          -
                                          -
                                          7
                                          -
                                          -
                                          -
                                          -
                                          -
                                          8
                                          -
                                          -
                                          -
                                          -
                                          -
                                          9
                                          -
                                          -
                                          -
                                          -
                                          - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/stack.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/stack.html deleted file mode 100644 index c0910a5e..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/grid/stack.html +++ /dev/null @@ -1,143 +0,0 @@ - -低于桌面堆叠排列 - - - - - -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/demo1.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/demo1.html deleted file mode 100644 index 5a5fd250..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/demo1.html +++ /dev/null @@ -1,324 +0,0 @@ - - layDate 功能演示一 - -
                                          - -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          常规用法
                                          -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          五大选择器
                                          -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          范围选择
                                          -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          自定义格式
                                          -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          同时绑定多个
                                          -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          - -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - - - -
                                          -
                                          - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/demo2.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/demo2.html deleted file mode 100644 index 220a1acd..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/demo2.html +++ /dev/null @@ -1,276 +0,0 @@ - - - layDate 功能演示二 - -
                                          - -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          公历节日和自定义重要日子
                                          -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          控制可选的日期与时间
                                          -
                                          -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          - 这里以控制在9:30-17:30为例 -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          其它功能示例
                                          -
                                          -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          - -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          - -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/special-demo.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/special-demo.html deleted file mode 100644 index 9fb7c444..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/special-demo.html +++ /dev/null @@ -1,74 +0,0 @@ - - -layDate 日期组件功能演示 - -
                                          - -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          联动范围选择
                                          -
                                          -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          - - -
                                          -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/theme.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/theme.html deleted file mode 100644 index 8103d9fb..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laydate/theme.html +++ /dev/null @@ -1,173 +0,0 @@ - - - layDate 日期组件功能演示 - - - -
                                          - -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          自定义按钮主题
                                          -
                                          -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          - -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          直接嵌套显示
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - - - -
                                          -
                                          - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/list.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/list.html deleted file mode 100644 index c0b8c8ab..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/list.html +++ /dev/null @@ -1,491 +0,0 @@ - -layer 组件功能演示 - - - - - -
                                          -
                                          -
                                          -
                                          -
                                          弹层之美
                                          -
                                          - -
                                          - layer 是 layui 中最广为人知的组件,它可以轻松应对 Web 应用开发中的各类复杂的弹出交互。有人说使用 layer 是一种情怀,一旦用上了,就离不开了。有多少人是因为 layer 才选择 layui 的呢,有一种信仰,叫:无条件相信 -
                                          - -
                                          -
                                          - -
                                          -
                                          弹层类型
                                          -
                                          - -
                                          - - - - - - - - - -
                                          - -
                                          -
                                          -
                                          -
                                          常规使用
                                          -
                                          - -
                                          - - - - - - - - - - - - - - - - -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          信息框
                                          -
                                          - -
                                          - - - - - - - -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          页面层与iframe层
                                          -
                                          - -
                                          - - - -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          加载层
                                          -
                                          - -
                                          - - - - -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          tips层
                                          -
                                          - -
                                          - - - - - -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          其它示例
                                          -
                                          - -
                                          - - -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/special-demo.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/special-demo.html deleted file mode 100644 index 544b6196..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/special-demo.html +++ /dev/null @@ -1,174 +0,0 @@ - -layer 组件特殊示例 - - - - - -
                                          -
                                          -
                                          -
                                          -
                                          场景
                                          -
                                          - -
                                          - - - -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          坐标
                                          -
                                          - -
                                          - - - - - - - - - -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/theme.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/theme.html deleted file mode 100644 index 8bdc0d1b..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/layer/theme.html +++ /dev/null @@ -1,82 +0,0 @@ - -layer 组件风格定制 - - - - - -
                                          -
                                          -
                                          -
                                          -
                                          风格定制
                                          -
                                          - -
                                          - - -
                                          - -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - - 持续增加中 - -
                                          -
                                          -
                                          -
                                          -
                                          - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laypage/demo1.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laypage/demo1.html deleted file mode 100644 index 1b66596c..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laypage/demo1.html +++ /dev/null @@ -1,158 +0,0 @@ - - - 功能演示1 - 通用分页组件 - - - -
                                          -
                                          -
                                          -
                                          -
                                          总页数低于页码总数
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          总页数大于页码总数
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          自定义主题 - 颜色随意定义
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          自定义首页、尾页、上一页、下一页文本
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          不显示首页尾页
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          开启HASH
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          只显示上一页、下一页
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laypage/demo2.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laypage/demo2.html deleted file mode 100644 index d69dbab0..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laypage/demo2.html +++ /dev/null @@ -1,159 +0,0 @@ - - - 功能演示2 - 通用分页组件 - - - -
                                          -
                                          -
                                          -
                                          -
                                          显示完整功能
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          自定义排版
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          自定义每页条数的选择项
                                          -
                                          -
                                          -
                                          -
                                          -
                                          - -
                                          -
                                          -
                                          将一段已知数组分页展示
                                          -
                                          -
                                          -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            - - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laytpl/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/laytpl/index.html deleted file mode 100644 index c62b0c19..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/laytpl/index.html +++ /dev/null @@ -1,34 +0,0 @@ - -模板引擎 - - - - - -
                                            - - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/nav/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/nav/index.html deleted file mode 100644 index 9a5eb6c6..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/nav/index.html +++ /dev/null @@ -1,206 +0,0 @@ - -导航 - -
                                            -
                                            - 主页 - 组件 - 导航 -
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            -
                                            水平导航菜单
                                            - -
                                            -
                                            -
                                            导航带徽章和图片
                                            -
                                            - -
                                            -
                                            - -
                                            - -
                                            - -
                                            -
                                            面包屑
                                            - -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/panel/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/panel/index.html deleted file mode 100644 index 6c46f015..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/panel/index.html +++ /dev/null @@ -1,181 +0,0 @@ - -面板 - -
                                            -
                                            - 主页 - 组件 - 面板 -
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            -
                                            折叠面板
                                            -
                                            -
                                            -
                                            -

                                            为什么JS社区大量采用未发布或者未广泛支持的语言特性?

                                            -
                                            -

                                            有不少其他答案说是因为JS太差。我下面的答案已经说了,这不是根本性的原因。但除此之外,我还要纠正一些对JS具体问题的误解。JS当初是被作为脚本语言设计的,所以某些问题并不是JS设计得差或者是JS设计者的失误。比如var的作用域问题,并不是“错误”,而是当时绝大部分脚本语言都是这样的,如perl/php/sh等。模块的问题也是,脚本语言几乎都没有模块/命名空间功能。弱类型、for-in之类的问题也是,只不过现在用那些老的脚本语言的人比较少,所以很多人都误以为是JS才有的坑。另外有人说JS是半残语言,满足不了开发需求,1999年就该死。半残这个嘛,就夸张了。JS虽然有很多问题,但是设计总体还是优秀的。——来自知乎@贺师俊

                                            -
                                            -
                                            -
                                            -

                                            为什么前端工程师多不愿意用 Bootstrap 框架?

                                            -
                                            -

                                            因为不适合。如果希望开发长期的项目或者制作产品类网站,那么就需要实现特定的设计,为了在维护项目中可以方便地按设计师要求快速修改样式,肯定会逐步编写出各种业务组件、工具类,相当于为项目自行开发一套框架。——来自知乎@Kayo

                                            -
                                            -
                                            -
                                            -

                                            layui 更适合哪些开发者?

                                            -
                                            -

                                            在前端技术快速变革的今天,layui 仍然坚持语义化的组织模式,甚至于模块理念都是采用类AMD组织形式,并非是有意与时代背道而驰。layui 认为以jQuery为核心的开发方式还没有到完全消亡的时候,而早期市面上基于jQuery的UI都普通做得差强人意,所以需要有一个新的UI去重新为这一领域注入活力,并采用一些更科学的架构方式。 -

                                            - 因此准确地说,layui 更多是面向那些追求开发简单的前端工程师们,以及所有层次的服务端程序员。

                                            -
                                            -
                                            -
                                            -

                                            贤心是男是女?

                                            -
                                            -

                                            man! 所以这个问题不要再出现了。。。

                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - -
                                            手风琴折叠
                                            -
                                            -
                                            -
                                            -

                                            layui 更适合哪些开发者?

                                            -
                                            -

                                            在前端技术快速变革的今天,layui 仍然坚持语义化的组织模式,甚至于模块理念都是采用类AMD组织形式,并非是有意与时代背道而驰。layui 认为以jQuery为核心的开发方式还没有到完全消亡的时候,而早期市面上基于jQuery的UI都普通做得差强人意,所以需要有一个新的UI去重新为这一领域注入活力,并采用一些更科学的架构方式。 -
                                            - 因此准确地说,layui 更多是面向那些追求开发简单的前端工程师们,以及所有层次的服务端程序员。

                                            -
                                            -
                                            -
                                            -

                                            为什么JS社区大量采用未发布或者未广泛支持的语言特性?

                                            -
                                            -

                                            有不少其他答案说是因为JS太差。我下面的答案已经说了,这不是根本性的原因。但除此之外,我还要纠正一些对JS具体问题的误解。JS当初是被作为脚本语言设计的,所以某些问题并不是JS设计得差或者是JS设计者的失误。比如var的作用域问题,并不是“错误”,而是当时绝大部分脚本语言都是这样的,如perl/php/sh等。模块的问题也是,脚本语言几乎都没有模块/命名空间功能。弱类型、for-in之类的问题也是,只不过现在用那些老的脚本语言的人比较少,所以很多人都误以为是JS才有的坑。另外有人说JS是半残语言,满足不了开发需求,1999年就该死。半残这个嘛,就夸张了。JS虽然有很多问题,但是设计总体还是优秀的。——来自知乎@贺师俊

                                            -
                                            -
                                            -
                                            -

                                            为什么前端工程师多不愿意用 Bootstrap 框架?

                                            -
                                            -

                                            因为不适合。如果希望开发长期的项目或者制作产品类网站,那么就需要实现特定的设计,为了在维护项目中可以方便地按设计师要求快速修改样式,肯定会逐步编写出各种业务组件、工具类,相当于为项目自行开发一套框架。——来自知乎@Kayo

                                            -
                                            -
                                            -
                                            -

                                            贤心是男是女?

                                            -
                                            -

                                            man! 所以这个问题不要再出现了。。。

                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            折叠面板嵌套
                                            -
                                            -
                                            -
                                            -

                                            文豪

                                            -
                                            - -
                                            -
                                            -

                                            唐代

                                            -
                                            - -
                                            -
                                            -

                                            杜甫

                                            -
                                            - 伟大的诗人 -
                                            -
                                            -
                                            -

                                            李白

                                            -
                                            -

                                            据说是韩国人

                                            -
                                            -
                                            -
                                            -

                                            王勃

                                            -
                                            -

                                            千古绝唱《滕王阁序》

                                            -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            -

                                            宋代

                                            -
                                            -

                                            比如苏轼、李清照

                                            -
                                            -
                                            -
                                            -

                                            当代

                                            -
                                            -

                                            比如贤心

                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -

                                            科学家

                                            -
                                            -

                                            伟大的科学家

                                            -
                                            -
                                            -
                                            -

                                            艺术家

                                            -
                                            -

                                            浑身散发着艺术细胞

                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            卡片面板
                                            -
                                            - 就是当前这个 -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/progress/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/progress/index.html deleted file mode 100644 index aeaeaa2d..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/progress/index.html +++ /dev/null @@ -1,159 +0,0 @@ - -进度条 - -
                                            - -
                                            - - - -
                                            -
                                            -
                                            -
                                            -
                                            默认进度条
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            更多颜色进度条
                                            -
                                            - -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            动态改变进度
                                            -
                                            - -
                                            -
                                            -
                                            - -
                                            - - -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            显示进度比文本
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/rate/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/rate/index.html deleted file mode 100644 index b1e2af43..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/rate/index.html +++ /dev/null @@ -1,177 +0,0 @@ - - - 评分组件 - -
                                            - -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            基础效果
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            显示文字
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            半星效果
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            自定义主题色
                                            -
                                            -
                                              -
                                            • -
                                            • -
                                            • -
                                            • -
                                            • -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            只读
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            自定义内容
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            自定义长度
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/slider/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/slider/index.html deleted file mode 100644 index 73f11a11..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/slider/index.html +++ /dev/null @@ -1,216 +0,0 @@ - - - 滑块组件 - -
                                            - -
                                            - - - -
                                            -
                                            -
                                            -
                                            -
                                            基础效果
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            定义初始值
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            设置最大最小值
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            设置步长
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            设置提示文本
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            开启输入框
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            开启范围选择
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            垂直滑块
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            自定义颜色
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            禁用滑块
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/auto.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/auto.html deleted file mode 100644 index b7568b28..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/auto.html +++ /dev/null @@ -1,49 +0,0 @@ - - - 列宽自动分配 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            列宽自动分配
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/cellEdit.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/cellEdit.html deleted file mode 100644 index bf467bf1..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/cellEdit.html +++ /dev/null @@ -1,56 +0,0 @@ - - - 开启单元格编辑 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            开启单元格编辑
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/cellEvent.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/cellEvent.html deleted file mode 100644 index 51b678cc..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/cellEvent.html +++ /dev/null @@ -1,67 +0,0 @@ - - - 单元格事件 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            单元格事件
                                            -
                                            -
                                            点击下面表格中的【签名列】,以演示单元格事件
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/checkbox.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/checkbox.html deleted file mode 100644 index b1a33091..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/checkbox.html +++ /dev/null @@ -1,50 +0,0 @@ - - - 开启复选框 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            开启复选框
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/data.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/data.html deleted file mode 100644 index 126c03a1..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/data.html +++ /dev/null @@ -1,141 +0,0 @@ - - - 赋值已知数据 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            赋值已知数据
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/fixed.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/fixed.html deleted file mode 100644 index fedaed33..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/fixed.html +++ /dev/null @@ -1,53 +0,0 @@ - - - 固定列 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            固定列
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/form.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/form.html deleted file mode 100644 index 467009f9..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/form.html +++ /dev/null @@ -1,82 +0,0 @@ - - - 加入表单元素 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            加入表单元素
                                            -
                                            -
                                            - - - - - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/height.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/height.html deleted file mode 100644 index 2649dc87..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/height.html +++ /dev/null @@ -1,51 +0,0 @@ - - - 高度最大适应 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            高度最大适应
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/initSort.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/initSort.html deleted file mode 100644 index 66acc1f3..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/initSort.html +++ /dev/null @@ -1,48 +0,0 @@ - - - 设置初始排序 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            设置初始排序
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/onrow.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/onrow.html deleted file mode 100644 index 4b6e7920..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/onrow.html +++ /dev/null @@ -1,67 +0,0 @@ - - - 行事件 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            行事件
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/operate.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/operate.html deleted file mode 100644 index 94845258..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/operate.html +++ /dev/null @@ -1,107 +0,0 @@ - - - 数据操作 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            数据操作
                                            -
                                            -
                                            - - - -
                                            - -
                                            - - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/page.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/page.html deleted file mode 100644 index bc765ec0..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/page.html +++ /dev/null @@ -1,57 +0,0 @@ - - - 开启分页 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            开启分页
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/parseData.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/parseData.html deleted file mode 100644 index 8a4756e6..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/parseData.html +++ /dev/null @@ -1,65 +0,0 @@ - - - 解析任意数据格式 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            解析任意数据格式
                                            -
                                            -
                                            - 尽管本示例中的原始数据:./json/table/demo3.js,并不符合 table 组件默认规定的数据格式,但从 layui 2.4.0 开始,新增的 parseData 回调可以将原始的任意格式的数据重新解析成 table 组件规定的数据格式。具体可以点击上方查看代码。 -
                                            - -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/radio.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/radio.html deleted file mode 100644 index 98952175..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/radio.html +++ /dev/null @@ -1,70 +0,0 @@ - - - 开启单选框 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            开启单选框
                                            -
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/reload.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/reload.html deleted file mode 100644 index 2f06619d..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/reload.html +++ /dev/null @@ -1,87 +0,0 @@ - - - 数据表格的重载 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            数据表格的重载
                                            -
                                            - -
                                            - 搜索ID: -
                                            - -
                                            - -
                                            - -
                                            - -
                                            此处由于是静态模拟数据,所以搜索后重载的结果没变,这并非是 BUG。实际使用时改成真实接口并根据搜索的字段筛选出对应的数据即可。
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/resetPage.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/resetPage.html deleted file mode 100644 index 38e2e516..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/resetPage.html +++ /dev/null @@ -1,58 +0,0 @@ - - - 自定义分页 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            自定义分页
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/simple.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/simple.html deleted file mode 100644 index 05ff19a4..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/simple.html +++ /dev/null @@ -1,48 +0,0 @@ - - - 简单用法 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            简单用法
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/static.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/static.html deleted file mode 100644 index 07429218..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/static.html +++ /dev/null @@ -1,309 +0,0 @@ - - - 静态表格 - -
                                            - -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            默认风格
                                            -
                                            - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                            人物民族出场时间格言
                                            贤心汉族1989-10-14人生似修行
                                            张爱玲汉族1920-09-30于千万人之中遇见你所遇见的人,于千万年之中,时间的无涯的荒野里…
                                            Helen Keller拉丁美裔1880-06-27 Life is either a daring adventure or nothing.
                                            岳飞汉族1103-北宋崇宁二年教科书再滥改,也抹不去“民族英雄”的事实
                                            孟子华夏族(汉族)公元前-372年猿强,则国强。国强,则猿更强!
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            行边框风格
                                            -
                                            - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                            人物民族出场时间格言
                                            贤心汉族1989-10-14人生似修行
                                            张爱玲汉族1920-09-30于千万人之中遇见你所遇见的人,于千万年之中,时间的无涯的荒野里…
                                            Helen Keller拉丁美裔1880-06-27 Life is either a daring adventure or nothing.
                                            岳飞汉族1103-北宋崇宁二年教科书再滥改,也抹不去“民族英雄”的事实
                                            孟子华夏族(汉族)公元前-372年猿强,则国强。国强,则猿更强!
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            列边框风格
                                            -
                                            - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                            人物民族出场时间格言
                                            贤心汉族1989-10-14人生似修行
                                            张爱玲汉族1920-09-30于千万人之中遇见你所遇见的人,于千万年之中,时间的无涯的荒野里…
                                            Helen Keller拉丁美裔1880-06-27 Life is either a daring adventure or nothing.
                                            岳飞汉族1103-北宋崇宁二年教科书再滥改,也抹不去“民族英雄”的事实
                                            孟子华夏族(汉族)公元前-372年猿强,则国强。国强,则猿更强!
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            无边框风格
                                            -
                                            - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                            人物民族出场时间格言
                                            贤心汉族1989-10-14人生似修行
                                            张爱玲汉族1920-09-30于千万人之中遇见你所遇见的人,于千万年之中,时间的无涯的荒野里…
                                            Helen Keller拉丁美裔1880-06-27 Life is either a daring adventure or nothing.
                                            岳飞汉族1103-北宋崇宁二年教科书再滥改,也抹不去“民族英雄”的事实
                                            孟子华夏族(汉族)公元前-372年猿强,则国强。国强,则猿更强!
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            其它尺寸
                                            -
                                            - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                            昵称加入时间签名
                                            贤心2016-11-29人生就像是一场修行
                                            许闲心2016-11-28于千万人之中遇见你所遇见的人,于千万年之中,时间的无涯的荒野里…
                                            sentsin2016-11-27 Life is either a daring adventure or nothing.
                                            - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                            昵称加入时间签名
                                            贤心2016-11-29人生就像是一场修行
                                            许闲心2016-11-28于千万人之中遇见你所遇见的人,于千万年之中,时间的无涯的荒野里…
                                            sentsin2016-11-27 Life is either a daring adventure or nothing.
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/style.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/style.html deleted file mode 100644 index cf32b4e0..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/style.html +++ /dev/null @@ -1,63 +0,0 @@ - - - 设置单元格样式 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            设置单元格样式
                                            -
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/thead.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/thead.html deleted file mode 100644 index 0513b82d..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/thead.html +++ /dev/null @@ -1,96 +0,0 @@ - - - 复杂表头 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            复杂表头
                                            -
                                            -
                                            - 常用两级表头 -
                                            - - - - - - - - - - - - - - - - -
                                            联系人地址金额操作
                                            - -
                                            - -
                                            - 更多级表头(可以无限极) -
                                            - - - - - - - - - - - - - - - - - - - - - - -
                                            联系人金额地址1地址2操作
                                            详细
                                            街道小区单元
                                            - - - -
                                            -
                                            注:上述例子读取的均是静态模拟数据
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/toolbar.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/toolbar.html deleted file mode 100644 index 6dcfd146..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/toolbar.html +++ /dev/null @@ -1,109 +0,0 @@ - - - 开启头部工具栏 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            开启头部工具栏
                                            -
                                            -
                                            - - - - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/tostatic.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/tostatic.html deleted file mode 100644 index eb9899ed..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/tostatic.html +++ /dev/null @@ -1,75 +0,0 @@ - - - 转化静态表格 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            转化静态表格
                                            -
                                            - -
                                            - -
                                            - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                            昵称加入时间签名
                                            贤心12016-11-28人生就像是一场修行 A
                                            贤心22016-11-29人生就像是一场修行 B
                                            贤心32016-11-30人生就像是一场修行 C
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/totalRow.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/totalRow.html deleted file mode 100644 index 98b4e660..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/table/totalRow.html +++ /dev/null @@ -1,78 +0,0 @@ - - - 开启合计行 - 数据表格 - - - -
                                            -
                                            -
                                            -
                                            -
                                            开启合计行
                                            -
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/tabs/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/tabs/index.html deleted file mode 100644 index 12ea587c..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/tabs/index.html +++ /dev/null @@ -1,188 +0,0 @@ - -选项卡组件 - -
                                            - -
                                            - - - -
                                            -
                                            -
                                            -
                                            -
                                            默认风格
                                            -
                                            -
                                            -
                                              -
                                            • 网站设置
                                            • -
                                            • 用户管理
                                            • -
                                            • 权限分配
                                            • -
                                            • 商品管理
                                            • -
                                            • 订单管理
                                            • -
                                            -
                                            -
                                            - 1. 高度默认自适应,也可以随意固宽。 -
                                            2. Tab进行了响应式处理,所以无需担心数量多少。 -
                                            -
                                            内容2
                                            -
                                            内容3
                                            -
                                            内容4
                                            -
                                            内容5
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            简洁风格
                                            -
                                            -
                                            -
                                              -
                                            • 网站设置
                                            • -
                                            • 用户管理
                                            • -
                                            • 权限分配
                                            • -
                                            • 商品管理
                                            • -
                                            • 订单管理
                                            • -
                                            -
                                            -
                                            - 你也可以 tab 事件 -
                                            -
                                            内容2
                                            -
                                            内容3
                                            -
                                            内容4
                                            -
                                            内容5
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            卡片风格
                                            -
                                            -
                                            -
                                              -
                                            • 网站设置
                                            • -
                                            • 用户管理
                                            • -
                                            • 权限分配
                                            • -
                                            • 商品管理
                                            • -
                                            • 订单管理
                                            • -
                                            -
                                            -
                                            默认宽度是相对于父元素100%适应的,你也可以固定宽度。
                                            -
                                            2
                                            -
                                            3
                                            -
                                            4
                                            -
                                            5
                                            -
                                            6
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            动态操作
                                            -
                                            -
                                            -
                                              -
                                            • 网站设置
                                            • -
                                            • 用户管理
                                            • -
                                            • 权限分配
                                            • -
                                            • 商品管理
                                            • -
                                            • 订单管理
                                            • -
                                            -
                                            -
                                            内容1
                                            -
                                            内容2
                                            -
                                            内容3
                                            -
                                            -
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            -
                                            记录状态
                                            -
                                            -
                                            -
                                              -
                                            • 网站设置
                                            • -
                                            • 用户管理
                                            • -
                                            • 权限分配
                                            • -
                                            • 商品管理
                                            • -
                                            • 订单管理
                                            • -
                                            -
                                            -
                                            - 点击该Tab的任一标题,观察地址栏变化,再刷新页面。选项卡将会自动定位到上一次切换的项 -
                                            -
                                            内容2
                                            -
                                            内容3
                                            -
                                            内容4
                                            -
                                            内容5
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/timeline/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/timeline/index.html deleted file mode 100644 index 8294ac51..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/timeline/index.html +++ /dev/null @@ -1,121 +0,0 @@ - -时间线 - -
                                            - -
                                            - - - -
                                            -
                                            -
                                            -
                                            -
                                            常规时间线
                                            -
                                            - -
                                              -
                                            • - -
                                              -

                                              12月28日

                                              -

                                              - 一直以来,layui 秉承无偿开源的初心,虔诚致力于服务各层次前后端 Web 开发者,在商业横飞的当今时代,这一信念从未动摇。即便身单力薄,仍然重拾决心,埋头造轮,以尽可能地填补产品本身的缺口。在过去的一段的时间,我一直在寻求持久之道,已维持你眼前所见的一切。而 layuiAdmin 是我们尝试解决的手段之一。我相信真正有爱于 layui 生态的你,定然不会错过这一拥抱吧。 -

                                              -


                                              子曰:君子不用防,小人防不住。请务必通过官网正规渠道,获得 layuiAdmin

                                              -
                                              -
                                            • -
                                            • - -
                                              -

                                              12月25日

                                              -

                                              又是一年 “圣诞节”,2018 向我们正在走来

                                              -
                                                -
                                              • 叮叮当,叮叮当,铃儿响叮当
                                              • -
                                              • 今晚滑雪多快乐,我们坐在雪橇上
                                              • -
                                              -
                                              -
                                            • -
                                            • - -
                                              -

                                              12月24日

                                              -

                                              - 美丽的夜晚,都是祈祷的人们。
                                              他们等待着第二天,收到圣诞老人的礼物。

                                              -

                                              -
                                              平安夜,天赐平安。愿真善美的事物都能永恒。
                                              -
                                              -
                                            • -
                                            • - -
                                              -
                                              过去
                                              -
                                              -
                                            • -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            简约时间线
                                            -
                                            - -
                                              -
                                            • - -
                                              -
                                              - 2018年,layui 5.0 发布,并发展成为中国最受欢迎的前端 UI 框架(期望) -
                                              -
                                              -
                                            • -
                                            • - -
                                              -
                                              2017年,layui 里程碑版本 2.0 发布
                                              -
                                              -
                                            • -
                                            • - -
                                              -
                                              2016年,layui 首个版本发布
                                              -
                                              -
                                            • -
                                            • - -
                                              -
                                              2015年,layui 孵化
                                              -
                                              -
                                            • -
                                            • - -
                                              -
                                              更久前,轮子时代。维护几个独立组件:layer等
                                              -
                                              -
                                            • -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/transfer/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/transfer/index.html deleted file mode 100644 index c89cdbd2..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/transfer/index.html +++ /dev/null @@ -1,185 +0,0 @@ - - - 穿梭框组件 - - - -
                                            -
                                            -
                                            -
                                            -
                                            基础效果
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            定义标题及数据源
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            初始右侧数据集合
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            显示搜索框
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            数据格式解析
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            穿梭时的回调
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            实例调用
                                            -
                                            -
                                            - - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/tree/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/tree/index.html deleted file mode 100644 index 56117339..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/tree/index.html +++ /dev/null @@ -1,432 +0,0 @@ - - - 树形组件 - -
                                            - -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            基本演示
                                            -
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            常规用法
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            无连接线风格
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            仅节点左侧图标控制收缩
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            手风琴模式
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            点击节点新窗口跳转
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            开启复选框
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            开启节点操作图标
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/upload/demo1.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/upload/demo1.html deleted file mode 100644 index 777ca260..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/upload/demo1.html +++ /dev/null @@ -1,199 +0,0 @@ - - - 功能演示一 - 上传组件 - - - - - -
                                            -
                                            -
                                            -
                                            -
                                            普通图片上传
                                            -
                                            -
                                            - -
                                            - -

                                            -
                                            -
                                            -
                                            - 为节省服务器开销,以下示例均未配置真实上传接口,所以每次上传都会报提示:请求上传接口出现异常,这属于正常现象。 -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            上传多张图片
                                            -
                                            -
                                            - -
                                            - 预览图: -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            指定允许上传的文件类型
                                            -
                                            - - - - -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            设定文件大小限制
                                            -
                                            - -
                                            - 这里以限制 60KB 为例 -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            同时绑定多个元素,并将属性设定在元素上
                                            -
                                            - - - -
                                            -
                                            -
                                            - -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/upload/demo2.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/upload/demo2.html deleted file mode 100644 index 1e5b8226..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/upload/demo2.html +++ /dev/null @@ -1,187 +0,0 @@ - - - 功能演示二 - 上传组件 - - - -
                                            -
                                            - -
                                            -
                                            -
                                            高级应用:制作一个多文件列表
                                            -
                                            -
                                            - -
                                            - - - - - - - - - - - - - - - - -
                                            文件名大小上传进度操作
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            选完文件后不自动上传
                                            -
                                            -
                                            - - -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            拖拽上传
                                            -
                                            -
                                            - -

                                            点击上传,或将文件拖拽到此处

                                            -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            绑定原始文件域
                                            -
                                            - -
                                            -
                                            -
                                            - -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/component/util/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/component/util/index.html deleted file mode 100644 index 249ccd63..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/component/util/index.html +++ /dev/null @@ -1,90 +0,0 @@ - - - 工具模块 - 组件 - -
                                            - -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            倒计时
                                            -
                                            - 请选择要计算的日期: -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            某个时间在当前时间的多久前
                                            -
                                            - 请选择要计算的日期: -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            -
                                            - - \ No newline at end of file diff --git "a/iot-server/server-starter/src/main/webapp/assets/src/views/component/\350\257\264\346\230\216.txt" "b/iot-server/server-starter/src/main/webapp/assets/src/views/component/\350\257\264\346\230\216.txt" deleted file mode 100644 index 951755f8..00000000 --- "a/iot-server/server-starter/src/main/webapp/assets/src/views/component/\350\257\264\346\230\216.txt" +++ /dev/null @@ -1,2 +0,0 @@ - -该目录存放【组件】的视图文件 \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/home/homepage1.html b/iot-server/server-starter/src/main/webapp/assets/src/views/home/homepage1.html deleted file mode 100644 index 8a5a402f..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/home/homepage1.html +++ /dev/null @@ -1,194 +0,0 @@ - -主页一 - -
                                            - -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            - 最近更新 - 全部更新 -
                                            -
                                            -
                                            -
                                            -
                                            - -

                                            修复开启 isLazyimg:true 后, 图片懒加载但是图片不存在的报错问题

                                            -

                                            流加载7 天前

                                            -
                                            -
                                            -
                                            -
                                            - -

                                            修复开启 size 参数后,文件超出规定大小时,提示信息有误的问题

                                            -

                                            文件上传7 天前

                                            -
                                            -
                                            -
                                            -
                                            - -

                                            增加 form.val(filter, fields)方法,用于给指定表单集合的元素初始赋值

                                            -

                                            表单7 天前

                                            -
                                            -
                                            -
                                            -
                                            - -

                                            对 select 组件新增上下键(↑ ↓)回车键(Enter)选择功能

                                            -

                                            表单7 天前

                                            -
                                            -
                                            -
                                            -
                                            - -

                                            优化 switch 开关组件,让其能根据文本自由伸缩宽

                                            -

                                            表单7 天前

                                            -
                                            -
                                            -
                                            -
                                            - -

                                            修复 checkbox 复选框组件在高分辨屏下出现的样式不雅问题

                                            -

                                            表单7 天前

                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            动态
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -

                                            纸飞机 在 layuiadmin专区 回答问题

                                            - 几秒前 -
                                            -
                                            -
                                            -
                                            -
                                            -

                                            纸飞机 在 layuiadmin专区 进行了 提问

                                            - 2天前 -
                                            -
                                            -
                                            -
                                            -
                                            -

                                            纸飞机 将 layui 更新至 2.3.0-rc1 版本

                                            - 7天前 -
                                            -
                                            -
                                            -
                                            -
                                            -

                                            纸飞机 在 Fly社区 发布了 建议

                                            - 7天前 -
                                            -
                                            -
                                            -
                                            -
                                            -

                                            纸飞机 在 Fly社区 发布了 建议

                                            - 8天前 -
                                            -
                                            -
                                            -
                                            -
                                            -

                                            纸飞机 在 layuiadmin专区 进行了 提问

                                            - 8天前 -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            快速开始/便捷导航
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            八卦新闻
                                            -
                                            - - - -
                                            -
                                            - -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/home/homepage2.html b/iot-server/server-starter/src/main/webapp/assets/src/views/home/homepage2.html deleted file mode 100644 index 96b3a8cd..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/home/homepage2.html +++ /dev/null @@ -1,306 +0,0 @@ - -主页二 - -
                                            - -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            - 访问量 - -
                                            -
                                            -

                                            99,666

                                            -

                                            - 总计访问量 - 88万 -

                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - 下载 - -
                                            -
                                            -

                                            33,555

                                            -

                                            - 新下载 - 10% -

                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - 点赞 - -
                                            -
                                            - -

                                            999,666

                                            -

                                            - 总赞 - *** -

                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - 活跃用户 - -
                                            -
                                            - -

                                            66,666

                                            -

                                            - 最近一个月 - 15% -

                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - 访问量 -
                                            - - -
                                            -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            -

                                            月访问数

                                            - 同上期增长 -
                                            -
                                            -
                                            -
                                            -
                                            -

                                            月下载数

                                            - 同上期增长 -
                                            -
                                            -
                                            -
                                            -
                                            -

                                            月点赞数

                                            - 同上期增长 -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            用户留言
                                            -
                                            -
                                              -
                                            • -

                                              贤心

                                              -

                                              作为 layui 官方原创的高质量管理系统模板,layuiAdmin 已经逐步成为后端工程师开发管理系统的首选界面模板。

                                              - 5月30日 00:00 - 回复 -
                                            • -
                                            • -

                                              诸葛亮

                                              -

                                              皓首匹夫!苍髯老贼!你枉活九十有六,一生未立寸功,只会摇唇鼓舌!助曹为虐!一条断脊之犬,还敢在我军阵前狺狺狂吠,我从未见过有如此厚颜无耻之人!

                                              - 5月02日 00:00 - 回复 -
                                            • -
                                            • -

                                              纸飞机

                                              -

                                              你以为只要长得漂亮就有男生喜欢?你以为只要有了钱漂亮妹子就自己贴上来了?你以为学霸就能找到好工作?我告诉你吧,这些都是真的!

                                              - 5月11日 00:00 - 回复 -
                                            • -
                                            • -

                                              杜甫

                                              -

                                              人才虽高,不务学问,不能致圣。刘向十日画一水,五日画一石。

                                              - 4月11日 00:00 - 回复 -
                                            • -
                                            • -

                                              鲁迅

                                              -

                                              路本是无所谓有和无的,走的人多了,就没路了。。

                                              - 4月28日 00:00 - 回复 -
                                            • -
                                            • -

                                              张爱玲

                                              -

                                              于千万人之中遇到你所要遇到的人,于千万年之中,时间的无涯的荒野中,没有早一步,也没有晚一步,刚巧赶上了,那也没有别的话好说,唯有轻轻的问一声:“噢,原来你也在这里?”

                                              - 4月11日 00:00 - 回复 -
                                            • -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            本周活跃用户列表
                                            -
                                            - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                            用户名最后登录时间状态获得赞
                                            纸飞机 11:20在线22
                                            纸飞机 10:40在线21
                                            纸飞机 01:30离线66
                                            纸飞机 21:18离线45
                                            纸飞机 09:30在线21
                                            纸飞机 21:18在线45
                                            纸飞机 09:30在线21
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            项目进展
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            访客地区分布
                                            -
                                            -
                                            -
                                            - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                            排名地区人数
                                            1浙江62310
                                            2上海59190
                                            3广东55891
                                            4北京51919
                                            5山东39231
                                            6湖北37109
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/iframe/layer/iframe.html b/iot-server/server-starter/src/main/webapp/assets/src/views/iframe/layer/iframe.html deleted file mode 100644 index a6c20874..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/iframe/layer/iframe.html +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - layer iframe 示例 - - - - - - - - - - -
                                            - - - - -
                                            - - - - - diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/iframe/link/baidu.html b/iot-server/server-starter/src/main/webapp/assets/src/views/iframe/link/baidu.html deleted file mode 100644 index 4995350d..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/iframe/link/baidu.html +++ /dev/null @@ -1,3 +0,0 @@ - -百度 - \ No newline at end of file diff --git "a/iot-server/server-starter/src/main/webapp/assets/src/views/iframe/\350\257\264\346\230\216.txt" "b/iot-server/server-starter/src/main/webapp/assets/src/views/iframe/\350\257\264\346\230\216.txt" deleted file mode 100644 index 621fae53..00000000 --- "a/iot-server/server-starter/src/main/webapp/assets/src/views/iframe/\350\257\264\346\230\216.txt" +++ /dev/null @@ -1,3 +0,0 @@ - -尽管 layuiAdmin 采用的是单页面应用开发模式,但有时你可能需要 iframe 嵌入一个页面,layuiAdmin 对此做了支持。 -该目录存放的就是 iframe 页面的视图文件。 \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/index.html deleted file mode 100644 index 971f2c35..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/index.html +++ /dev/null @@ -1,391 +0,0 @@ -
                                            -
                                            -
                                            -
                                            - - -
                                            -
                                            -
                                            数据概览
                                            -
                                            - - - -
                                            -
                                            - -
                                            -
                                            访客地区分布
                                            -
                                            -
                                            -
                                            - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                            排名地区人数
                                            1浙江62310
                                            2上海59190
                                            3广东55891
                                            4北京51919
                                            5山东39231
                                            6湖北37109
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                              -
                                            • 今日热搜
                                            • -
                                            • 今日热帖
                                            • -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            版本信息
                                            -
                                            - - - - - - - - - - - - - - - - - - - - - - - -
                                            模板名称通用纯静态界面模板
                                            当前版本 - -
                                            UI 版本 - -
                                            主要特色单页面 / 响应式 / 清爽 / 极简
                                            -
                                            -
                                            - -
                                            -
                                            效果报告
                                            -
                                            -
                                            -

                                            转化率(日同比 28% ) -

                                            -
                                            -
                                            -
                                            -

                                            签到率(日同比 11%

                                            -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            进度占用
                                            -
                                            -
                                            -

                                            CPU使用率

                                            -
                                            -
                                            -
                                            -

                                            内存占用率

                                            -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            项目进展
                                            -
                                            -
                                            -
                                            -
                                            - - - -
                                            -
                                            - 模板心语 - -
                                            -
                                            -
                                            -

                                            所谓“单页版”,即 SPA(单页面应用系统)开发模式,也就是所有的页面动作都是在一个宿主页面中完成,通常用于前后端分离。其中视图层全权由前端把控,数据一律走 Ajax - 异步请求。layuiAdmin 内部实现了一套基于 location.hash 的路由和模板机制,这使得你可以很轻松地实现界面的跳转与渲染。另外注意的是,接口鉴权不再适用于传统的 - session 模式,一般需要采用 JWT。总体来说,刚开始使用会相对有些复杂,但使用习惯后,项目会更易维护。

                                            -

                                            子曰:君子不用防,小人防不住。

                                            -

                                            请尊重知识产权,尊重他人劳动成果。

                                            -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            - - - - diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/layout.html b/iot-server/server-starter/src/main/webapp/assets/src/views/layout.html deleted file mode 100644 index 275c469d..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/layout.html +++ /dev/null @@ -1,200 +0,0 @@ - -
                                            -
                                            - - - -
                                            - - -
                                            -
                                            - -
                                            -
                                            - - - - - - - -
                                            -
                                            -
                                            - - -
                                            - -
                                            diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/bar.html b/iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/bar.html deleted file mode 100644 index b13c4ab5..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/bar.html +++ /dev/null @@ -1,108 +0,0 @@ - -柱状图 - - - -
                                            -
                                            -
                                            -
                                            -
                                            标准柱状图
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            堆积柱状图
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            不等距柱形图
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            彩虹柱形图
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            标准条形图
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            堆积条形图
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            旋风条形图
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/line.html b/iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/line.html deleted file mode 100644 index e1e03b99..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/line.html +++ /dev/null @@ -1,102 +0,0 @@ -折线图 - - - -
                                            -
                                            -
                                            -
                                            -
                                            标准折线图
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            堆积折线图
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            不等距折线图
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            堆积面积图
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            面积图
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            对数轴
                                            -
                                            - - - -
                                            -
                                            -
                                            - -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/map.html b/iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/map.html deleted file mode 100644 index 6d6e2a86..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/senior/echarts/map.html +++ /dev/null @@ -1,34 +0,0 @@ -地图 - - - -
                                            -
                                            -
                                            -
                                            -
                                            地图
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/senior/im/index.html b/iot-server/server-starter/src/main/webapp/assets/src/views/senior/im/index.html deleted file mode 100644 index 91557e2e..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/senior/im/index.html +++ /dev/null @@ -1,427 +0,0 @@ - -社交聊天 - - - - -
                                            -
                                            -
                                            -
                                            -
                                            面板外的操作示例
                                            -
                                            - -
                                            - - - - - - -
                                            - - - - - - - - -
                                            - - -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git "a/iot-server/server-starter/src/main/webapp/assets/src/views/senior/\350\257\264\346\230\216.txt" "b/iot-server/server-starter/src/main/webapp/assets/src/views/senior/\350\257\264\346\230\216.txt" deleted file mode 100644 index 559f97d3..00000000 --- "a/iot-server/server-starter/src/main/webapp/assets/src/views/senior/\350\257\264\346\230\216.txt" +++ /dev/null @@ -1,2 +0,0 @@ - -该目录存放【高级】的视图文件 \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/set/system/email.html b/iot-server/server-starter/src/main/webapp/assets/src/views/set/system/email.html deleted file mode 100644 index c6dd9b9d..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/set/system/email.html +++ /dev/null @@ -1,69 +0,0 @@ -邮件服务 - - - -
                                            -
                                            -
                                            -
                                            -
                                            邮件服务
                                            -
                                            - -
                                            -
                                            - -
                                            - -
                                            -
                                            如:smtp.163.com
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            一般为 25 或 465
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/set/system/website.html b/iot-server/server-starter/src/main/webapp/assets/src/views/set/system/website.html deleted file mode 100644 index d905c7d3..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/set/system/website.html +++ /dev/null @@ -1,95 +0,0 @@ -网站设置 - - - -
                                            -
                                            -
                                            -
                                            -
                                            网站设置
                                            -
                                            - -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            分钟
                                            -
                                            本地开发一般推荐设置为 0,线上环境建议设置为 10。
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            KB
                                            -
                                            提示:1 M = 1024 KB
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            - -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/set/user/info.html b/iot-server/server-starter/src/main/webapp/assets/src/views/set/user/info.html deleted file mode 100644 index 2c145387..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/set/user/info.html +++ /dev/null @@ -1,98 +0,0 @@ - -设置我的资料 - - - -
                                            -
                                            -
                                            -
                                            -
                                            设置我的资料
                                            -
                                            - -
                                            -
                                            - -
                                            - -
                                            -
                                            当前角色不可更改为其它角色
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            不可修改。一般用于后台登入名
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            - - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            -
                                            - - -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/set/user/password.html b/iot-server/server-starter/src/main/webapp/assets/src/views/set/user/password.html deleted file mode 100644 index 170a6b12..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/set/user/password.html +++ /dev/null @@ -1,53 +0,0 @@ -设置我的密码 - - - -
                                            -
                                            -
                                            -
                                            -
                                            修改密码
                                            -
                                            - -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            6到16个字符
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git "a/iot-server/server-starter/src/main/webapp/assets/src/views/set/\350\257\264\346\230\216.txt" "b/iot-server/server-starter/src/main/webapp/assets/src/views/set/\350\257\264\346\230\216.txt" deleted file mode 100644 index c40b5158..00000000 --- "a/iot-server/server-starter/src/main/webapp/assets/src/views/set/\350\257\264\346\230\216.txt" +++ /dev/null @@ -1,2 +0,0 @@ - -该目录存放【设置】的视图文件 \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/system/about.html b/iot-server/server-starter/src/main/webapp/assets/src/views/system/about.html deleted file mode 100644 index 2e6d5ff7..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/system/about.html +++ /dev/null @@ -1,17 +0,0 @@ -
                                            版本
                                            -
                                            -
                                            - -
                                            -
                                            - -
                                            关于
                                            -
                                            -
                                            - 一套纯静态的 HTML 网页界面模板,以开源免费的 layui 基础组件和页面模板 Demo 为组成,没有任何后端程序及数据库存储等服务端代码。 -

                                            开发者使用该网页模板,可省去前端的大量工作,从而更高效地开发 Web 应用系统。 -

                                            该模板受国家计算机软件著作权保护(登记号:2018SR410669),禁止公开及传播模板源文件、盗版及非法倒卖等,违者将自行承担相应的法律责任。 -
                                            -
                                            \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/system/more.html b/iot-server/server-starter/src/main/webapp/assets/src/views/system/more.html deleted file mode 100644 index c1f570b6..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/system/more.html +++ /dev/null @@ -1,22 +0,0 @@ - - - diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/system/theme.html b/iot-server/server-starter/src/main/webapp/assets/src/views/system/theme.html deleted file mode 100644 index d3f4617d..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/system/theme.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - diff --git "a/iot-server/server-starter/src/main/webapp/assets/src/views/system/\350\257\264\346\230\216.txt" "b/iot-server/server-starter/src/main/webapp/assets/src/views/system/\350\257\264\346\230\216.txt" deleted file mode 100644 index 46923e05..00000000 --- "a/iot-server/server-starter/src/main/webapp/assets/src/views/system/\350\257\264\346\230\216.txt" +++ /dev/null @@ -1,3 +0,0 @@ - -注意: -该目录存放的是 layuiAdmin 的系统模板碎片,很多界面需要依赖到它,请勿剔除。 \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/temp.html b/iot-server/server-starter/src/main/webapp/assets/src/views/temp.html deleted file mode 100644 index 0a74d9dd..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/temp.html +++ /dev/null @@ -1,51 +0,0 @@ - -标题 - -
                                            -
                                            - 主页 - 组件 - XXX -
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            -
                                            YYY
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            ZZZ
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/addresslist.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/addresslist.html deleted file mode 100644 index 6bcdd744..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/template/addresslist.html +++ /dev/null @@ -1,370 +0,0 @@ - - -通讯录 - - - -
                                            - -
                                            - -
                                            -
                                            - - - - - - - - - -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/caller.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/caller.html deleted file mode 100644 index 4bd5becd..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/template/caller.html +++ /dev/null @@ -1,195 +0,0 @@ -客户列表 - - - - - -
                                            -
                                            -
                                            - - - -
                                            -
                                            -
                                              -
                                            • 所有联系人
                                            • -
                                            • 联系方式
                                            • -
                                            • 联系地址
                                            • -
                                            -
                                            -
                                            -
                                            - -
                                            -

                                            纸飞机 最近联系:1 小时前

                                            -

                                            浙江省广州市越秀区中山六路109

                                            -
                                            - - - -
                                            -
                                            - -
                                            -
                                            - -
                                            -

                                            纸飞机 最近联系:1 小时前

                                            -

                                            浙江省广州市越秀区中山六路109

                                            -
                                            - - - -
                                            -
                                            - -
                                            -
                                            - -
                                            -

                                            纸飞机 最近联系:1 小时前

                                            -

                                            浙江省广州市越秀区中山六路109

                                            -
                                            - - - -
                                            -
                                            - -
                                            -
                                            - -
                                            -

                                            纸飞机 最近联系:1 小时前

                                            -

                                            浙江省广州市越秀区中山六路109

                                            -
                                            - - - -
                                            -
                                            - -
                                            -
                                            - -
                                            -

                                            纸飞机 最近联系:1 小时前

                                            -

                                            浙江省广州市越秀区中山六路109

                                            -
                                            - - - -
                                            -
                                            - -
                                            -
                                            - -
                                            -

                                            纸飞机 最近联系:1 小时前

                                            -

                                            浙江省广州市越秀区中山六路109

                                            -
                                            - - - -
                                            -
                                            - -
                                            -
                                            - -
                                            -

                                            纸飞机 最近联系:1 小时前

                                            -

                                            浙江省广州市越秀区中山六路109

                                            -
                                            - - - -
                                            -
                                            - -
                                            -
                                            - -
                                            -

                                            纸飞机 最近联系:1 小时前

                                            -

                                            浙江省广州市越秀区中山六路109

                                            -
                                            - - - -
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/goodslist.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/goodslist.html deleted file mode 100644 index 1b1ce7b5..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/template/goodslist.html +++ /dev/null @@ -1,410 +0,0 @@ - - -商品列表 - - - - - -
                                            -
                                            - - - - - - - - - - - - - - - - -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/msgboard.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/msgboard.html deleted file mode 100644 index 502208ab..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/template/msgboard.html +++ /dev/null @@ -1,97 +0,0 @@ - - -留言板 - - - -
                                            - -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            - -
                                            -
                                            - -
                                            -
                                            - - - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - - -
                                            -

                                            纸飞机

                                            -

                                            - - - 从移动 - 11分钟前 - -

                                            -
                                            -

                                            历经打磨,@索尼中国 再献新作品—OLED电视A8F完美诞生。很开心一起参加了A8F的“首映礼”![鼓掌]正如我们演员对舞台的热爱,索尼对科技与艺术的追求才创造出了让人惊喜的作品。作为A1兄弟款,A8F沿袭了黑科技“屏幕发声技术”和高清画质,色彩的出众表现和高端音质,让人在体验的时候如同身临其境。A8F,这次的“视帝”要颁发给你! 索尼官网预售: O网页链接 索尼旗舰店预售:

                                            -
                                            -
                                            - - - -
                                            -

                                            纸飞机

                                            -

                                            - - - 从移动 - 11分钟前 - -

                                            -
                                            -

                                            历经打磨,@索尼中国 再献新作品—OLED电视A8F完美诞生。很开心一起参加了A8F的“首映礼”![鼓掌]正如我们演员对舞台的热爱,索尼对科技与艺术的追求才创造出了让人惊喜的作品。作为A1兄弟款,A8F沿袭了黑科技“屏幕发声技术”和高清画质,色彩的出众表现和高端音质,让人在体验的时候如同身临其境。A8F,这次的“视帝”要颁发给你! 索尼官网预售: O网页链接 索尼旗舰店预售:

                                            -
                                            -
                                            - 更多 -
                                            -
                                            - -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/personalpage.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/personalpage.html deleted file mode 100644 index 5a67298a..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/template/personalpage.html +++ /dev/null @@ -1,425 +0,0 @@ - - -个人主页 - - - - - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - -
                                            -

                                            纸飞机

                                            -

                                            中国非知名前端

                                            -
                                            - - - - -
                                            - -
                                            -
                                            -

                                            - 关于我 -

                                            - -
                                            - 纸飞机喜欢摄影,也喜欢写字,他视角独特,充满着奇思妙想。他有着极丰富的情感,和对生活的热情,他能点燃观众心中爱的火焰;纸飞机积极、乐观、坚强,他脚踏实地地做好每一件事,真诚地对待身边每一个人 -
                                            -

                                            - 技能 -

                                            - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -

                                            52K

                                            - 关注 -
                                            -
                                            -

                                            72K

                                            - 以下 -
                                            -
                                            -

                                            5343

                                            - 照片 -
                                            -
                                            -

                                            4.5

                                            - 排行 -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            - - - -
                                            -
                                            -

                                            纸飞机普通照片添加了新的照片

                                            -

                                            - - - 从移动 - 11分钟前 - -

                                            -
                                            -

                                            layer 是一款历年来备受青睐的 Web 弹出层组件,具备全方位的解决方案,面向各个水平段的开发人员,您的页面会轻松地拥有丰富友好的操作体验。在与同类组件的比较中,layer 会更能被开发者所选择。这不仅是凭「脸」取胜,而是它尽可能地在以更少的代码展现更强健的功能,且格外注重性能的提升、易用和实用性,layer 甚至还兼容了包括 IE6 在内的所有主流浏览器。其数量可观的基础属性和方法,使得您可以自定义太多您需要的风格,每一种弹层模式各具特色,广受欢迎。当然,这种「王婆卖瓜」的陈述听起来总是有点难受,因此你需要进一步了解她是否真的如你所愿。

                                            - - - -
                                            -
                                            - - - - -
                                            -
                                            - 纸飞机 - 3月21日 19:56 -
                                            -
                                            一次难忘更难得的拍摄经历 谢谢
                                            -
                                            -
                                            -
                                            - - - -
                                            -
                                            - 纸飞机 - 3月21日 19:56 -
                                            -
                                            一次难忘更难得的拍摄经历 谢谢
                                            -
                                            -
                                            -
                                            - - - -
                                            -
                                            - 纸飞机 - 3月21日 19:56 -
                                            -
                                            一次难忘更难得的拍摄经历 谢谢
                                            -
                                            -
                                            - 更多 -
                                            -
                                            -
                                            -
                                            - - - -
                                            -
                                            -

                                            纸飞机普通照片添加了新的照片

                                            -

                                            - - - 从移动 - 11分钟前 - -

                                            -
                                            -

                                            历经打磨,@索尼中国 再献新作品—OLED电视A8F完美诞生。很开心一起参加了A8F的“首映礼”![鼓掌]正如我们前端对舞台的热爱,索尼对科技与艺术的追求才创造出了让人惊喜的作品。作为A1兄弟款,A8F沿袭了黑科技“屏幕发声技术”和高清画质,色彩的出众表现和高端音质,让人在体验的时候如同身临其境。A8F,这次的“视帝”要颁发给你! 索尼官网预售: O网页链接 索尼旗舰店预售:

                                            - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -

                                            - - 画廊 -

                                            -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            - -
                                            -
                                            - -
                                            -
                                            - -
                                            -
                                            - -
                                            -
                                            - -
                                            -
                                            - -
                                            -
                                            - -
                                            -
                                            - -
                                            -
                                            - 更多 -
                                            -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/search.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/search.html deleted file mode 100644 index f865a6b9..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/template/search.html +++ /dev/null @@ -1,97 +0,0 @@ - - -搜索结果 - - - - - -
                                            -
                                            -
                                            -
                                            -
                                            -

                                            - 关键词 查询到 - 66 个结果 -

                                            -

                                            耗时:350ms

                                            -
                                            -
                                            - -
                                              -
                                            • -
                                              -

                                              前端的进化?

                                              -

                                              在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。

                                              -
                                              -
                                            • -
                                            • - - - -
                                              -

                                              前端 UI

                                              -

                                              UI 设计(或称界面设计)是指对软件的人机交互、操作逻辑、界面美观的整体设计。 UI 设计分为实体 UI和虚拟 UI,互联网常用的 UI 设计是虚拟 UI, UI即 User Interface (用户界面)的简称。

                                              -
                                              -
                                            • -
                                            • -
                                              -

                                              前端的进化?

                                              -

                                              在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。

                                              -

                                              - 前端 - 性别 - -

                                              -
                                              -
                                            • -
                                            • -
                                              -

                                              - 热点 - UI 设计 -

                                              -

                                              UI 设计(或称界面设计)是指对软件的人机交互、操作逻辑、界面美观的整体设计。 UI 设计分为实体 UI和虚拟 UI,互联网常用的 UI 设计是虚拟 UI, UI即 User Interface (用户界面)的简称。

                                              -
                                              -
                                            • -
                                            • -
                                              -

                                              前端的进化?

                                              -

                                              在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。在前端技术的快速发展中找准你的定位,在思考与实践中沉淀。。

                                              -
                                              -
                                            • -
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            - - diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/404.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/404.html deleted file mode 100644 index fc9f1127..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/404.html +++ /dev/null @@ -1,15 +0,0 @@ - -404 页面不存在 - -
                                            -
                                            - -
                                            -

                                            - 4 - 0 - 4 -

                                            -
                                            -
                                            -
                                            \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/error.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/error.html deleted file mode 100644 index 6242c6ad..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/error.html +++ /dev/null @@ -1,13 +0,0 @@ - -出错了 - -
                                            -
                                            - - -
                                            - 好像出错了呢 -
                                            - -
                                            -
                                            \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/test.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/test.html deleted file mode 100644 index 6242c6ad..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/template/tips/test.html +++ /dev/null @@ -1,13 +0,0 @@ - -出错了 - -
                                            -
                                            - - -
                                            - 好像出错了呢 -
                                            - -
                                            -
                                            \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/user/forget.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/user/forget.html deleted file mode 100644 index ca8352e4..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/template/user/forget.html +++ /dev/null @@ -1,30 +0,0 @@ - -忘记密码 - - - - - -
                                            - 即将开放 -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/user/login.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/user/login.html deleted file mode 100644 index a406283f..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/template/user/login.html +++ /dev/null @@ -1,69 +0,0 @@ - -登入页面 - -
                                            -
                                            - 主页 - 模板 - 登入 -
                                            -
                                            - -
                                            -
                                            -
                                            说明:正式登入页面将在 beta3 开放
                                            -
                                            - -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            - layui 怎么念? -
                                            -
                                            -
                                            -
                                            - - - 忘记密码? - -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/template/user/reg.html b/iot-server/server-starter/src/main/webapp/assets/src/views/template/user/reg.html deleted file mode 100644 index 35cccf19..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/template/user/reg.html +++ /dev/null @@ -1,30 +0,0 @@ - -注册页面 - -
                                            -
                                            - 主页 - 模板 - 注册 -
                                            -
                                            - - - -
                                            - 即将开放 -
                                            - - \ No newline at end of file diff --git "a/iot-server/server-starter/src/main/webapp/assets/src/views/template/\350\257\264\346\230\216.txt" "b/iot-server/server-starter/src/main/webapp/assets/src/views/template/\350\257\264\346\230\216.txt" deleted file mode 100644 index a294d398..00000000 --- "a/iot-server/server-starter/src/main/webapp/assets/src/views/template/\350\257\264\346\230\216.txt" +++ /dev/null @@ -1,2 +0,0 @@ - -该目录存放【模板】的视图文件 \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/adminform.html b/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/adminform.html deleted file mode 100644 index f8de6ee0..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/adminform.html +++ /dev/null @@ -1,66 +0,0 @@ - - -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/list.html b/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/list.html deleted file mode 100644 index a6c2e301..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/list.html +++ /dev/null @@ -1,161 +0,0 @@ - - -后台管理员 - - - -
                                            -
                                            -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            - -
                                            -
                                            - - -
                                            - -
                                            - - -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/role.html b/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/role.html deleted file mode 100644 index 9520dcc0..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/role.html +++ /dev/null @@ -1,127 +0,0 @@ - - -角色管理 - - - -
                                            -
                                            -
                                            -
                                            -
                                            - 角色筛选 -
                                            -
                                            - -
                                            -
                                            -
                                            -
                                            -
                                            - - -
                                            - -
                                            - - -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/roleform.html b/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/roleform.html deleted file mode 100644 index b690a74b..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/user/administrators/roleform.html +++ /dev/null @@ -1,59 +0,0 @@ - - -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - - - - - - - - - - - - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - - diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/user/forget.html b/iot-server/server-starter/src/main/webapp/assets/src/views/user/forget.html deleted file mode 100644 index 9c1a0691..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/user/forget.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/user/login.html b/iot-server/server-starter/src/main/webapp/assets/src/views/user/login.html deleted file mode 100644 index 2b9509b8..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/user/login.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/user/reg.html b/iot-server/server-starter/src/main/webapp/assets/src/views/user/reg.html deleted file mode 100644 index 0126388a..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/user/reg.html +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/user/user/list.html b/iot-server/server-starter/src/main/webapp/assets/src/views/user/user/list.html deleted file mode 100644 index 950fdb2e..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/user/user/list.html +++ /dev/null @@ -1,150 +0,0 @@ - - -网站用户 - - - -
                                            -
                                            -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            -
                                            -
                                            - -
                                            -
                                            - - -
                                            - -
                                            - - -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/src/views/user/user/userform.html b/iot-server/server-starter/src/main/webapp/assets/src/views/user/user/userform.html deleted file mode 100644 index 5f5b029b..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/src/views/user/user/userform.html +++ /dev/null @@ -1,72 +0,0 @@ - - -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            - -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - -
                                            - -
                                            -
                                            -
                                            - - \ No newline at end of file diff --git "a/iot-server/server-starter/src/main/webapp/assets/src/views/user/\350\257\264\346\230\216.txt" "b/iot-server/server-starter/src/main/webapp/assets/src/views/user/\350\257\264\346\230\216.txt" deleted file mode 100644 index ba22b0a2..00000000 --- "a/iot-server/server-starter/src/main/webapp/assets/src/views/user/\350\257\264\346\230\216.txt" +++ /dev/null @@ -1,2 +0,0 @@ - -该目录存放【用户】的视图文件 \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/index.html b/iot-server/server-starter/src/main/webapp/assets/zeus/index.html deleted file mode 100644 index 24e2313f..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/index.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - layuiAdmin pro - 通用后台管理模板系统(单页面专业版) - - - - - - - -
                                            - - - - - - diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/console/prograss.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/console/prograss.js deleted file mode 100644 index 13a093bf..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/console/prograss.js +++ /dev/null @@ -1,36 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"count": "100" - ,"data": [{ - "prograss": "开会" - ,"time": "一小时" - ,"complete": "已完成" - ,"LAY_CHECKED": true - },{ - "prograss": "项目开发" - ,"time": "两小时" - ,"complete": "进行中" - ,"LAY_CHECKED": true - },{ - "prograss": "陪吃饭" - ,"time": "一小时" - ,"complete": "未完成" - },{ - "prograss": "修改小bug" - ,"time": "半小时" - ,"complete": "未完成" - },{ - "prograss": "修改大bug" - ,"time": "两小时" - ,"complete": "未完成" - },{ - "prograss": "修改小bug" - ,"time": "半小时" - ,"complete": "未完成" - },{ - "prograss": "修改大bug" - ,"time": "两小时" - ,"complete": "未完成" - }] -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/console/top-card.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/console/top-card.js deleted file mode 100644 index ae52d1c0..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/console/top-card.js +++ /dev/null @@ -1,76 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"count": "100" - ,"data": [{ - "id": 111 - ,"title": "热帖测试" - ,"username": "test" - ,"channel": "公告" - ,"href": "" - ,"crt": 61632 - },{ - "id": 222 - ,"title": "一周年" - ,"username": "猫吃" - ,"channel": "讨论" - ,"href": "" - ,"crt": 61632 - },{ - "id": 333 - ,"title": "四个月的前端" - ,"username": "fd" - ,"channel": "分享" - ,"href": "" - ,"crt": 61632 - },{ - "id": 333 - ,"title": "如何评价前端 UI 框架" - ,"username": "纸飞机" - ,"channel": "提问" - ,"href": "" - ,"crt": 61632 - },{ - "id": 333 - ,"title": "如何评价前端 UI 框架" - ,"username": "纸飞机" - ,"channel": "提问" - ,"href": "" - ,"crt": 61632 - },{ - "id": 333 - ,"title": "如何评价前端 UI 框架" - ,"username": "纸飞机" - ,"channel": "提问" - ,"href": "" - ,"crt": 61632 - },{ - "id": 333 - ,"title": "如何评价前端 UI 框架" - ,"username": "纸飞机" - ,"channel": "提问" - ,"href": "" - ,"crt": 61632 - },{ - "id": 333 - ,"title": "如何评价前端 UI 框架" - ,"username": "纸飞机" - ,"channel": "提问" - ,"href": "" - ,"crt": 61632 - },{ - "id": 333 - ,"title": "如何评价前端 UI 框架" - ,"username": "纸飞机" - ,"channel": "提问" - ,"href": "" - ,"crt": 61632 - },{ - "id": 333 - ,"title": "如何评价前端 UI 框架" - ,"username": "纸飞机" - ,"channel": "提问" - ,"href": "" - ,"crt": 61632 - }] -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/console/top-search.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/console/top-search.js deleted file mode 100644 index 6b9956ba..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/console/top-search.js +++ /dev/null @@ -1,46 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"count": "100" - ,"data": [{ - "keywords": "UI" - ,"frequency": 8520 - ,"userNums": 2216 - },{ - "keywords": "layer 弹出层组件" - ,"frequency": 666 - ,"userNums": 333 - },{ - "keywords": "此表格是静态模拟数据" - ,"frequency": 666 - ,"userNums": 333 - },{ - "keywords": "前端 UI" - ,"frequency": 666 - ,"userNums": 333 - },{ - "keywords": "前端 UI" - ,"frequency": 666 - ,"userNums": 333 - },{ - "keywords": "前端 UI" - ,"frequency": 666 - ,"userNums": 333 - },{ - "keywords": "前端 UI" - ,"frequency": 666 - ,"userNums": 333 - },{ - "keywords": "前端 UI" - ,"frequency": 666 - ,"userNums": 333 - },{ - "keywords": "前端 UI" - ,"frequency": 666 - ,"userNums": 333 - },{ - "keywords": "前端 UI" - ,"frequency": 666 - ,"userNums": 333 - }] -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/content/comment.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/content/comment.js deleted file mode 100644 index 45b8c3fb..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/content/comment.js +++ /dev/null @@ -1,56 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"count": "100" - ,"data": [{ - "id": "001" - ,"reviewers": "赵" - ,"content": "我又爱上编程了" - ,"commtime": 20160312 - },{ - "id": "002" - ,"reviewers": "钱" - ,"content": "女生出门要小心" - ,"commtime": 20160821 - },{ - "id": "003" - ,"reviewers": "孙" - ,"content": "框架就用layui" - ,"commtime": 20161212 - },{ - "id": "004" - ,"reviewers": "李" - ,"content": "心姐么么哒" - ,"commtime": 20170311 - },{ - "id": "005" - ,"reviewers": "周" - ,"content": "希望明天是个好天气" - ,"commtime": 20170612 - },{ - "id": "006" - ,"reviewers": "吴" - ,"content": "我又爱上编程了" - ,"commtime": 20171112 - },{ - "id": "007" - ,"reviewers": "郑" - ,"content": "女生出门要小心" - ,"commtime": 20171230 - },{ - "id": "008" - ,"reviewers": "王" - ,"content": "框架就用layui" - ,"commtime": 20180112 - },{ - "id": "009" - ,"reviewers": "冯" - ,"content": "心姐么么哒" - ,"commtime": 20180221 - },{ - "id": "010" - ,"reviewers": "陈" - ,"content": "希望明天是个好天气" - ,"commtime": 20180312 - }] -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/content/list.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/content/list.js deleted file mode 100644 index b70f3e7e..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/content/list.js +++ /dev/null @@ -1,62 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"count": "100" - ,"data": [{ - "id": "001" - ,"label": "美食" - ,"title": "舌尖上的中国第一季" - ,"author": "作者-1" - ,"content": "通过中华美食的多个侧面,来展现食物给中国人生活带来的仪式、伦理等方面的文化;见识中国特色食材以及与食物相关、构成中国美食特有气质的一系列元素;了解中华饮食文化的精致和源远流长" - ,"uploadtime": 20121204 - ,"status": true - },{ - "id": "002" - ,"label": "美食" - ,"title": "舌尖上的中国第二季" - ,"author": "作者-2" - ,"content": "以食物为窗口,读懂中国——通过美食,使人们可以有滋有味地认知这个古老的东方国度。“一方水土一方人”,本片将通过展示人们日常生活中与美食相关的多重侧面,描绘与感知中国人的文化传统、家族观念、生活态度与故土难离。人们收获、保存、烹饪、生产美食,并在其过程中留存和传承食物所承载的味觉记忆、饮食习俗、文化样态与家常情感。" - ,"uploadtime": 20141204 - ,"status": false - },{ - "id": "003" - ,"label": "美食" - ,"title": "舌尖上的中国第三季" - ,"author": "作者-3" - ,"content": "以食物为窗口,读懂中国——通过美食,使人们可以有滋有味地认知这个古老的东方国度。“一方水土一方人”,本片将通过展示人们日常生活中与美食相关的多重侧面,描绘与感知中国人的文化传统、家族观念、生活态度与故土难离。人们收获、保存、烹饪、生产美食,并在其过程中留存和传承食物所承载的味觉记忆、饮食习俗、文化样态与家常情感将世界美食和中国美食进行比照。春耕、夏耘、秋收、冬藏,天人合一的东方哲学让中国饮食依时而变,智慧灵动,中医营养摄生学说创造了食材运用的新天地,儒家人伦道德则把心意和家的味道端上我们的餐桌。淘洗历史,糅合时光,一代又一代的中国人在天地间升起烟火,用至精至诚的心意烹制食物,一餐一食之间,中国人展示个性,确认归属,构建文明,理解和把握着世界的奥妙。" - ,"uploadtime": 20161204 - ,"status": false - },{ - "id": "004" - ,"label": "历史" - ,"title": "诸葛亮骂王朗" - ,"author": "作者-1" - ,"content": "皓首匹夫!苍髯老贼!你即将命归于九泉之下,届时,有何面目见汉朝二十四代先帝?二臣贼子!你枉活七十有六,一生未立寸功,只会摇唇舞舌,助曹为虐!一条断脊之犬,还敢在我军阵前狺狺狂吠!我从未见过如此厚颜无耻之人!!!" - ,"uploadtime": 20180201 - ,"status": false - },{ - "id": "005" - ,"label": "新闻" - ,"title": "新时代特色中国梦" - ,"author": "作者-1" - ,"content": "今天,我们比历史上任何时期都更接近、更有信心和能力实现中华民族伟大复兴的目标。新时代已经到来,蓝图已经绘就,中国梦离我们越来越近了。" - ,"uploadtime": 20180512 - ,"status": false - },{ - "id": "006" - ,"label": "新闻" - ,"title": "新时代特色中国梦" - ,"author": "作者-2" - ,"content": "梦想不会主动走向我们,只有我们去主动实现梦想。行百里者半九十。虽然中国梦离我们越来越近了,但是要实现中国梦,还要靠我们以永不懈怠的精神状态、功在不舍的坚强意志,不忘初心,继续前进。" - ,"uploadtime": 20180514 - ,"status": false - },{ - "id": "007" - ,"label": "体育" - ,"title": "皇马大战利物浦" - ,"author": "作者-3" - ,"content": "对欧足联而言,更想要产生个新冠军。连续三年都是同一个冠军队,这会毁掉欧冠……”格里姆表态,“皇马有梦幻般的阵容,但从促进竞争的角度而言,另一支球队获胜会更好。" - ,"uploadtime": 20180515 - ,"status": false - }] -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/content/tags.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/content/tags.js deleted file mode 100644 index 6ca85cd1..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/content/tags.js +++ /dev/null @@ -1,21 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"count": "100" - ,"data": [{ - "id": "001" - ,"tags": "美食" - },{ - "id": "002" - ,"tags": "新闻" - },{ - "id": "003" - ,"tags": "八卦" - },{ - "id": "004" - ,"tags": "体育" - },{ - "id": "005" - ,"tags": "音乐" - }] -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/forum/list.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/forum/list.js deleted file mode 100644 index fc8c7c25..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/forum/list.js +++ /dev/null @@ -1,62 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"count": "100" - ,"data": [{ - "id": "1001" - ,"poster": "赵" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"content": "为什么花儿这么么红" - ,"posttime": 20160805 - ,"top": false - },{ - "id": "1002" - ,"poster": "钱" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"content": "喜欢纸飞机,赞赞赞" - ,"posttime": 20161205 - ,"top": true - },{ - "id": "1003" - ,"poster": "孙" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"content": "明天就要考试了,好紧张,求保佑" - ,"posttime": 20170405 - ,"top": false - },{ - "id": "1004" - ,"poster": "李" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"content": "希望明天是个好天气" - ,"posttime": 20171005 - ,"top": false - },{ - "id": "1005" - ,"poster": "周" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"content": "女追男隔层纱,是不是真的" - ,"posttime": 20180205 - ,"top": false - },{ - "id": "1006" - ,"poster": "吴" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"content": "竟然有人跳楼,年轻人想不开啊!" - ,"posttime": 20180512 - ,"top": false - },{ - "id": "1007" - ,"poster": "郑" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"content": "大家一定不能学那个年轻人,珍爱生命啊" - ,"posttime": 20180512 - ,"top": false - },{ - "id": "1008" - ,"poster": "王" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"content": "想知道南昌哪里有好吃的西安肉夹馍" - ,"posttime": 20180514 - ,"top": false - }] -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/forum/replys.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/forum/replys.js deleted file mode 100644 index a7be0d0b..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/forum/replys.js +++ /dev/null @@ -1,69 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"count": "100" - ,"data": [{ - "id": "001" - ,"replyer": "吴" - ,"cardid": "1002" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"content": "有眼光,我也喜欢纸飞机!" - ,"replytime": 20161205 - },{ - "id": "002" - ,"replyer": "郑" - ,"cardid": "1002" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"content": "同上同上。" - ,"replytime": 20161205 - },{ - "id": "003" - ,"replyer": "王" - ,"cardid": "1003" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"content": "能过一定过,不能过紧张也没用" - ,"replytime": 20170405 - },{ - "id": "004" - ,"replyer": "冯" - ,"cardid": "1001" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"content": "可能因为你流鼻血了。" - ,"replytime": 20170405 - },{ - "id": "005" - ,"replyer": "陈" - ,"cardid": "1003" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"content": "加油加油,看好你" - ,"replytime": 20170405 - },{ - "id": "006" - ,"replyer": "褚" - ,"cardid": "1005" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"content": "纯属放屁" - ,"replytime": 20180207 - },{ - "id": "007" - ,"replyer": "卫" - ,"cardid": "1005" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"content": "可以试试" - ,"replytime": 20180207 - },{ - "id": "006" - ,"replyer": "蒋" - ,"cardid": "1006" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"content": "是啊是啊,太恐怖了。" - ,"replytime": 20180512 - },{ - "id": "007" - ,"replyer": "沈" - ,"cardid": "1008" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"content": "魏家凉皮的凉皮就很不错奥。" - ,"replytime": 20180515 - }] -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/layer/photos.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/layer/photos.js deleted file mode 100644 index a1898c17..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/layer/photos.js +++ /dev/null @@ -1,39 +0,0 @@ -{ - "code": 0, - "msg": "", - "title": "JSON请求的相册", - "id": 8, - "start": 0, - "data": [ - { - "alt": "layer", - "pid": 109, - "src": "https://sentsin.gitee.io/res/images/layui/avatar.png", - "thumb": "" - }, - { - "alt": "说好的,一起Fly", - "pid": 110, - "src": "https://wx4.sinaimg.cn/mw1024/5db11ff4gy1fmx4kebemcj20ga09saa1.jpg", - "thumb": "" - }, - { - "alt": "佟丽娅女神", - "pid": 111, - "src": "https://sentsin.gitee.io/res/images/layui/avatar.png", - "thumb": "" - }, - { - "alt": "凤姐是个好人", - "pid": 112, - "src": "https://wx3.sinaimg.cn/mw690/5db11ff4gy1fmx4kec9vuj20b20dwmyk.jpg", - "thumb": "" - }, - { - "alt": "星空如此深邃", - "pid": 113, - "src": "https://sentsin.gitee.io/res/images/layui/avatar.png", - "thumb": "" - } - ] -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/layim/getList.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/layim/getList.js deleted file mode 100644 index 8ea6ab88..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/layim/getList.js +++ /dev/null @@ -1,96 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"data": { - "mine": { - "username": "测试名称" - ,"id": "100000" - ,"status": "online" - ,"sign": "测试" - ,"avatar": "" - } - ,"friend": [{ - "groupname": "测试分组一" - ,"id": 0 - ,"list": [{ - "username": "测试1" - ,"id": "100001" - ,"avatar": "" - ,"sign": "测试内容1" - ,"status": "online" - },{ - "username": "测试2" - ,"id": "100001222" - ,"sign": "测试内容2" - ,"avatar": "" - },{ - "username": "测试3" - ,"id": "10034001" - ,"avatar": "" - ,"sign": "" - },{ - "username": "测试4" - ,"id": "168168" - ,"avatar": "" - ,"sign": "测试内容4" - },{ - "username": "测试5" - ,"id": "666666" - ,"avatar": "" - ,"sign": "测试内容5" - }] - },{ - "groupname": "测试分组二" - ,"id": 1 - ,"list": [{ - "username": "测试6" - ,"id": "121286" - ,"avatar": "" - ,"sign": "测试内容6" - },{ - "username": "测试7" - ,"id": "108101" - ,"avatar": "" - ,"sign": "微电商达人" - },{ - "username": "测试8" - ,"id": "12123454" - ,"avatar": "" - ,"sign": "测试内容8" - },{ - "username": "测试9" - ,"id": "102101" - ,"avatar": "" - ,"sign": "" - },{ - "username": "测试10" - ,"id": "3435343" - ,"avatar": "" - ,"sign": "" - }] - },{ - "groupname": "测试分组三" - ,"id": 2 - ,"list": [{ - "username": "测试11" - ,"id": "76543" - ,"avatar": "" - ,"sign": "测试内容11" - },{ - "username": "测试12" - ,"id": "4803920" - ,"avatar": "" - ,"sign": "测试内容12" - }] - }] - ,"group": [{ - "groupname": "测试群组一" - ,"id": "101" - ,"avatar": "" - },{ - "groupname": "测试群组二" - ,"id": "102" - ,"avatar": "" - }] - } -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/layim/getMembers.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/layim/getMembers.js deleted file mode 100644 index e45872e6..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/layim/getMembers.js +++ /dev/null @@ -1,22 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"data": { - "list": [{ - "username": "测试1" - ,"id": "100001" - ,"avatar": "" - ,"sign": "测试内容" - },{ - "username": "测试6" - ,"id": "121286" - ,"avatar": "" - ,"sign": "测试内容" - },{ - "username": "测试8" - ,"id": "12123454" - ,"avatar": "" - ,"sign": "" - }] - } -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/mall/order.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/mall/order.js deleted file mode 100644 index 9ce29719..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/mall/order.js +++ /dev/null @@ -1,42 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"count": "100" - ,"data": [{ - "invoice": "X123565541" - ,"username": "张小三" - ,"orderDate": "2017-11-10" - ,"amount": 800 - ,"status": 1 - },{ - "invoice": "X123565542" - ,"username": "李小四" - ,"orderDate": "2017-11-10" - ,"amount": 800 - ,"status": 0 - },{ - "invoice": "X123565543" - ,"username": "王老五" - ,"orderDate": "2017-11-10" - ,"amount": 800 - ,"status": 1 - },{ - "invoice": "X123565544" - ,"username": "赵小六" - ,"orderDate": "2017-11-09" - ,"amount": 1600 - ,"status": 1 - },{ - "invoice": "X123565545" - ,"username": "孙小七" - ,"orderDate": "2017-11-09" - ,"amount": 1600 - ,"status": -1 - },{ - "invoice": "X123565546" - ,"username": "周小八" - ,"orderDate": "2017-11-08" - ,"amount": 2600 - ,"status": 1 - }] -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/menu.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/menu.js deleted file mode 100644 index 18385961..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/menu.js +++ /dev/null @@ -1,400 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"data": [{ - "title": "主页" - ,"icon": "layui-icon-home" - ,"list": [{ - "title": "控制台" - ,"jump": "/" - }, { - "name": "homepage1" - ,"title": "主页一" - ,"jump": "home/homepage1" - }, { - "name": "homepage2" - ,"title": "主页二" - ,"jump": "home/homepage2" - }] - }, { - "name": "component" - ,"title": "组件" - ,"icon": "layui-icon-component" - ,"list": [{ - "name": "grid" - ,"title": "栅格" - ,"list": [{ - "name": "list" - ,"title": "等比例列表排列" - },{ - "name": "mobile" - ,"title": "按移动端排列" - },{ - "name": "mobile-pc" - ,"title": "移动桌面端组合" - },{ - "name": "all" - ,"title": "全端复杂组合" - },{ - "name": "stack" - ,"title": "低于桌面堆叠排列" - },{ - "name": "speed-dial" - ,"title": "九宫格" - }] - }, { - "name": "button" - ,"title": "按钮" - }, { - "name": "form" - ,"title": "表单" - ,"list": [{ - "name": "element" - ,"title": "表单元素" - },{ - "name": "group" - ,"title": "表单组合" - }] - }, { - "name": "nav" - ,"title": "导航" - }, { - "name": "tabs" - ,"title": "选项卡" - }, { - "name": "progress" - ,"title": "进度条" - }, { - "name": "panel" - ,"title": "面板" - }, { - "name": "badge" - ,"title": "徽章" - }, { - "name": "timeline" - ,"title": "时间线" - }, { - "name": "anim" - ,"title": "动画" - }, { - "name": "auxiliar" - ,"title": "辅助" - }, { - "name": "layer" - ,"title": "通用弹层" - ,"list": [{ - "name": "list" - ,"title": "功能演示" - },{ - "name": "special-demo" - ,"title": "特殊示例" - },{ - "name": "theme" - ,"title": "风格定制" - }] - }, { - "name": "laydate" - ,"title": "日期时间" - ,"list": [{ - "name": "demo1" - ,"title": "功能演示一" - },{ - "name": "demo2" - ,"title": "功能演示二" - },{ - "name": "theme" - ,"title": "设定主题" - },{ - "name": "special-demo" - ,"title": "特殊示例" - }] - }, { - "name": "table" - ,"title": "表格" - ,"list": [{ - "name": "simple" - ,"title": "简单数据表格" - },{ - "name": "auto" - ,"title": "列宽自动分配" - },{ - "name": "data" - ,"title": "赋值已知数据" - },{ - "name": "tostatic" - ,"title": "转化静态表格" - },{ - "name": "page" - ,"title": "开启分页" - },{ - "name": "resetPage" - ,"title": "自定义分页" - },{ - "name": "toolbar" - ,"title": "开启头部工具栏" - },{ - "name": "totalRow" - ,"title": "开启合计行" - },{ - "name": "height" - ,"title": "高度最大适应" - },{ - "name": "checkbox" - ,"title": "开启复选框" - },{ - "name": "radio" - ,"title": "开启单选框" - },{ - "name": "cellEdit" - ,"title": "开启单元格编辑" - },{ - "name": "form" - ,"title": "加入表单元素" - },{ - "name": "style" - ,"title": "设置单元格样式" - },{ - "name": "fixed" - ,"title": "固定列" - },{ - "name": "operate" - ,"title": "数据操作" - },{ - "name": "parseData" - ,"title": "解析任意数据格式" - },{ - "name": "onrow" - ,"title": "监听行事件" - },{ - "name": "reload" - ,"title": "数据表格的重载" - },{ - "name": "initSort" - ,"title": "设置初始排序" - },{ - "name": "cellEvent" - ,"title": "监听单元格事件" - },{ - "name": "thead" - ,"title": "复杂表头" - }] - }, { - "name": "laypage" - ,"title": "分页" - ,"list": [{ - "name": "demo1" - ,"title": "功能演示一" - },{ - "name": "demo2" - ,"title": "功能演示二" - }] - }, { - "name": "dropdown" - ,"title": "下拉菜单" - }, { - "name": "upload" - ,"title": "上传" - ,"list": [{ - "name": "demo1" - ,"title": "功能演示一" - },{ - "name": "demo2" - ,"title": "功能演示二" - }] - }, { - "name": "transfer" - ,"title": "穿梭框" - }, { - "name": "tree" - ,"title": "树形组件" - }, { - "name": "colorpicker" - ,"title": "颜色选择器" - }, { - "name": "slider" - ,"title": "滑块组件" - }, { - "name": "rate" - ,"title": "评分" - }, { - "name": "carousel" - ,"title": "轮播" - }, { - "name": "flow" - ,"title": "流加载" - }, { - "name": "util" - ,"title": "工具" - }, { - "name": "code" - ,"title": "代码修饰" - }, { - "name": "layim" - ,"title": "即时聊天" - ,"jump": "senior/im/" - }] - }, { - "name": "template" - ,"title": "页面" - ,"icon": "layui-icon-template" - ,"list": [{ - "name": "personalpage" - ,"title": "个人主页" - ,"jump": "template/personalpage" - },{ - "name": "addresslist" - ,"title": "通讯录" - ,"jump": "template/addresslist" - },{ - "name": "caller" - ,"title": "客户列表" - ,"jump": "template/caller" - },{ - "name": "goodslist" - ,"title": "商品列表" - ,"jump": "template/goodslist" - },{ - "name": "msgboard" - ,"title": "留言板" - ,"jump": "template/msgboard" - },{ - "name": "search" - ,"title": "搜索结果" - ,"jump": "template/search" - },{ - "name": "reg" - ,"title": "注册" - ,"jump": "user/reg" - },{ - "name": "login" - ,"title": "登入" - ,"jump": "user/login" - },{ - "name": "forget" - ,"title": "忘记密码" - ,"jump": "user/forget" - },{ - "name": "404" - ,"title": "404" - ,"jump": "template/tips/404" - },{ - "name": "error" - ,"title": "错误提示" - ,"jump": "template/tips/error" - }, { - "name": "" - ,"title": "内嵌页面" - ,"spread": true - ,"list": [{ - "name": "" - ,"title": "百度一下" - ,"jump": "/iframe/link/baidu" - }] - }] - }, { - "name": "app" - ,"title": "应用" - ,"icon": "layui-icon-app" - ,"list": [{ - "name": "content" - ,"title": "内容系统" - ,"list": [{ - "name": "list" - ,"title": "文章列表" - },{ - "name": "tags" - ,"title": "分类管理" - },{ - "name": "comment" - ,"title": "评论管理" - }] - },{ - "name": "forum" - ,"title": "社区系统" - ,"list": [{ - "name": "list" - ,"title": "帖子列表" - },{ - "name": "replys" - ,"title": "回帖列表" - }] - },{ - "name": "message" - ,"title": "消息中心" - },{ - "name": "workorder" - ,"title": "工单系统" - ,"jump": "app/workorder/list" - }] - }, { - "name": "senior" - ,"title": "高级" - ,"icon": "layui-icon-senior" - ,"list": [{ - "name": "im" - ,"title": "WebIM UI" - },{ - "name": "echarts" - ,"title": "Echarts" - ,"list": [{ - "name": "line" - ,"title": "折线图" - },{ - "name": "bar" - ,"title": "柱状图" - },{ - "name": "map" - ,"title": "地图" - }] - }] - }, { - "name": "user" - ,"title": "用户" - ,"icon": "layui-icon-user" - ,"list": [{ - "name": "user" - ,"title": "网站用户" - ,"jump": "user/user/list" - }, { - "name": "administrators-list" - ,"title": "后台管理员" - ,"jump": "user/administrators/list" - }, { - "name": "administrators-rule" - ,"title": "角色管理" - ,"jump": "user/administrators/role" - }] - }, { - "name": "set" - ,"title": "设置" - ,"icon": "layui-icon-set" - ,"list": [{ - "name": "system" - ,"title": "系统设置" - ,"spread": true - ,"list": [{ - "name": "website" - ,"title": "网站设置" - },{ - "name": "email" - ,"title": "邮件服务" - }] - },{ - "name": "user" - ,"title": "我的设置" - ,"spread": true - ,"list": [{ - "name": "info" - ,"title": "基本资料" - },{ - "name": "password" - ,"title": "修改密码" - }] - }] - }, { - "name": "get" - ,"title": "关于" - ,"icon": "layui-icon-auz" - ,"jump": "system/about" - }] -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/all.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/all.js deleted file mode 100644 index e7ac7087..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/all.js +++ /dev/null @@ -1,46 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"count": 60 - ,"data": [{ - "id": 123 - ,"title": "Hello World" - ,"time": 1510363800000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1507447570000 - }] -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/detail.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/detail.js deleted file mode 100644 index 4a5c879b..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/detail.js +++ /dev/null @@ -1,10 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"data": { - "id": 111 - ,"title": "Hello World" - ,"content": "

                                            来自通用型纯静态 UI 界面模板的初识语 & 本地模拟测试消息

                                            " - ,"time": 1510363800000 - } -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/direct.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/direct.js deleted file mode 100644 index d8cbe165..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/direct.js +++ /dev/null @@ -1,46 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"count": 60 - ,"data": [{ - "id": 123 - ,"title": "一段模拟的测试私信" - ,"time": 1510363800000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1507447570000 - }] -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/new.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/new.js deleted file mode 100644 index 668f4b51..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/new.js +++ /dev/null @@ -1,7 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"data": { - "newmsg": 3 - } -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/notice.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/notice.js deleted file mode 100644 index d8cbe165..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/message/notice.js +++ /dev/null @@ -1,46 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"count": 60 - ,"data": [{ - "id": 123 - ,"title": "一段模拟的测试私信" - ,"time": 1510363800000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1510212370000 - }, { - "id": 111 - ,"title": "一段模拟的测试私信" - ,"time": 1507447570000 - }] -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo.js deleted file mode 100644 index c96c09fd..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo.js +++ /dev/null @@ -1,96 +0,0 @@ - -{ - "code": 0 - ,"msg": "" - ,"count": 3000000 - ,"data": [{ - "id": "10001" - ,"username": "杜甫" - ,"email": "test@email.com" - ,"sex": "男" - ,"city": "浙江杭州" - ,"sign": "点击此处,显示更多。当内容超出时,点击单元格会自动显示更多内容。" - ,"experience": "116" - ,"ip": "192.168.0.8" - ,"logins": "108" - ,"joinTime": "2016-10-14" - }, { - "id": "10002" - ,"username": "李白" - ,"email": "test@email.com" - ,"sex": "男" - ,"city": "浙江杭州" - ,"sign": "君不见,黄河之水天上来,奔流到海不复回。 君不见,高堂明镜悲白发,朝如青丝暮成雪。 人生得意须尽欢,莫使金樽空对月。 天生我材必有用,千金散尽还复来。 烹羊宰牛且为乐,会须一饮三百杯。 岑夫子,丹丘生,将进酒,杯莫停。 与君歌一曲,请君为我倾耳听。(倾耳听 一作:侧耳听) 钟鼓馔玉不足贵,但愿长醉不复醒。(不足贵 一作:何足贵;不复醒 一作:不愿醒/不用醒) 古来圣贤皆寂寞,惟有饮者留其名。(古来 一作:自古;惟 通:唯) 陈王昔时宴平乐,斗酒十千恣欢谑。 主人何为言少钱,径须沽取对君酌。 五花马,千金裘,呼儿将出换美酒,与尔同销万古愁。" - ,"experience": "12" - ,"ip": "192.168.0.8" - ,"logins": "106" - ,"joinTime": "2016-10-14" - ,"LAY_CHECKED": true - }, { - "id": "10003" - ,"username": "王勃" - ,"email": "test@email.com" - ,"sex": "男" - ,"city": "浙江杭州" - ,"sign": "人生恰似一场修行" - ,"experience": "65" - ,"ip": "192.168.0.8" - ,"logins": "106" - ,"joinTime": "2016-10-14" - }, { - "id": "10004" - ,"username": "李清照" - ,"email": "test@email.com" - ,"sex": "女" - ,"city": "浙江杭州" - ,"sign": "人生恰似一场修行" - ,"experience": "666" - ,"ip": "192.168.0.8" - ,"logins": "106" - ,"joinTime": "2016-10-14" - }, { - "id": "10005" - ,"username": "冰心" - ,"email": "test@email.com" - ,"sex": "女" - ,"city": "浙江杭州" - ,"sign": "人生恰似一场修行" - ,"experience": "86" - ,"ip": "192.168.0.8" - ,"logins": "106" - ,"joinTime": "2016-10-14" - }, { - "id": "10006" - ,"username": "tester" - ,"email": "test@email.com" - ,"sex": "男" - ,"city": "浙江杭州" - ,"sign": "人生恰似一场修行" - ,"experience": "12" - ,"ip": "192.168.0.8" - ,"logins": "106" - ,"joinTime": "2016-10-14" - }, { - "id": "10007" - ,"username": "tester" - ,"email": "test@email.com" - ,"sex": "男" - ,"city": "浙江杭州" - ,"sign": "人生恰似一场修行" - ,"experience": "16" - ,"ip": "192.168.0.8" - ,"logins": "106" - ,"joinTime": "2016-10-14" - }, { - "id": "10008" - ,"username": "tester" - ,"email": "test@email.com" - ,"sex": "男" - ,"city": "浙江杭州" - ,"sign": "人生恰似一场修行" - ,"experience": "106" - ,"ip": "192.168.0.8" - ,"logins": "106" - ,"joinTime": "2016-10-14" - }] -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo2.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo2.js deleted file mode 100644 index f6fae592..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo2.js +++ /dev/null @@ -1,61 +0,0 @@ - -{ - "code": 0 - ,"msg": "" - ,"count": 66 - ,"data": [{ - "username": "张小三" - ,"amount": 18 - ,"province": "浙江" - ,"city": "杭州" - ,"zone": "西湖区" - ,"street": "西溪街道" - ,"address": "西溪花园" - ,"house": "30栋1单元" - }, { - "username": "李小四" - ,"amount": 39 - ,"province": "江苏" - ,"city": "苏州" - ,"zone": "姑苏区" - ,"street": "丝绸路" - ,"address": "天墅之城" - ,"house": "9幢2单元" - }, { - "username": "王小五" - ,"amount": 8 - ,"province": "江西" - ,"city": "南昌" - ,"zone": "青山湖区" - ,"street": "艾溪湖办事处" - ,"address": "中兴和园" - ,"house": "1幢3单元" - }, { - "username": "赵小六" - ,"amount": 16 - ,"province": "福建" - ,"city": "泉州" - ,"zone": "丰泽区" - ,"street": "南洋街道" - ,"address": "南洋村" - ,"house": "6幢1单元" - }, { - "username": "孙小七" - ,"amount": 12 - ,"province": "湖北" - ,"city": "武汉" - ,"zone": "武昌区" - ,"street": "武昌大道" - ,"address": "两湖花园" - ,"house": "16幢2单元" - }, { - "username": "周小八" - ,"amount": 11 - ,"province": "安徽" - ,"city": "黄山" - ,"zone": "黄山区" - ,"street": "汤口镇" - ,"address": "温泉村" - ,"house": "21号" - }] -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo3.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo3.js deleted file mode 100644 index 4217f5d2..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/demo3.js +++ /dev/null @@ -1,96 +0,0 @@ -{ - "status": 200 - ,"message": "" - ,"total": 8 - ,"rows": { - "item": [{ - "id": "10001" - ,"username": "杜甫" - ,"email": "test@email.com" - ,"sex": "男" - ,"city": "浙江杭州" - ,"sign": "点击此处,显示更多。当内容超出时,点击单元格会自动显示更多内容。" - ,"experience": "116" - ,"ip": "192.168.0.8" - ,"logins": "108" - ,"joinTime": "2016-10-14" - }, { - "id": "10002" - ,"username": "李白" - ,"email": "test@email.com" - ,"sex": "男" - ,"city": "浙江杭州" - ,"sign": "君不见,黄河之水天上来,奔流到海不复回。 君不见,高堂明镜悲白发,朝如青丝暮成雪。 人生得意须尽欢,莫使金樽空对月。 天生我材必有用,千金散尽还复来。 烹羊宰牛且为乐,会须一饮三百杯。 岑夫子,丹丘生,将进酒,杯莫停。 与君歌一曲,请君为我倾耳听。(倾耳听 一作:侧耳听) 钟鼓馔玉不足贵,但愿长醉不复醒。(不足贵 一作:何足贵;不复醒 一作:不愿醒/不用醒) 古来圣贤皆寂寞,惟有饮者留其名。(古来 一作:自古;惟 通:唯) 陈王昔时宴平乐,斗酒十千恣欢谑。 主人何为言少钱,径须沽取对君酌。 五花马,千金裘,呼儿将出换美酒,与尔同销万古愁。" - ,"experience": "12" - ,"ip": "192.168.0.8" - ,"logins": "106" - ,"joinTime": "2016-10-14" - }, { - "id": "10003" - ,"username": "王勃" - ,"email": "test@email.com" - ,"sex": "男" - ,"city": "浙江杭州" - ,"sign": "人生恰似一场修行" - ,"experience": "65" - ,"ip": "192.168.0.8" - ,"logins": "106" - ,"joinTime": "2016-10-14" - }, { - "id": "10004" - ,"username": "李清照" - ,"email": "test@email.com" - ,"sex": "女" - ,"city": "浙江杭州" - ,"sign": "人生恰似一场修行" - ,"experience": "666" - ,"ip": "192.168.0.8" - ,"logins": "106" - ,"joinTime": "2016-10-14" - }, { - "id": "10005" - ,"username": "冰心" - ,"email": "test@email.com" - ,"sex": "女" - ,"city": "浙江杭州" - ,"sign": "人生恰似一场修行" - ,"experience": "86" - ,"ip": "192.168.0.8" - ,"logins": "106" - ,"joinTime": "2016-10-14" - }, { - "id": "10006" - ,"username": "tester" - ,"email": "test@email.com" - ,"sex": "男" - ,"city": "浙江杭州" - ,"sign": "人生恰似一场修行" - ,"experience": "12" - ,"ip": "192.168.0.8" - ,"logins": "106" - ,"joinTime": "2016-10-14" - }, { - "id": "10007" - ,"username": "tester" - ,"email": "test@email.com" - ,"sex": "男" - ,"city": "浙江杭州" - ,"sign": "人生恰似一场修行" - ,"experience": "16" - ,"ip": "192.168.0.8" - ,"logins": "106" - ,"joinTime": "2016-10-14" - }, { - "id": "10008" - ,"username": "tester" - ,"email": "test@email.com" - ,"sex": "男" - ,"city": "浙江杭州" - ,"sign": "人生恰似一场修行" - ,"experience": "106" - ,"ip": "192.168.0.8" - ,"logins": "106" - ,"joinTime": "2016-10-14" - }] - } -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/user.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/user.js deleted file mode 100644 index 240c7aa1..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/user.js +++ /dev/null @@ -1,2 +0,0 @@ - -{"code":0,"msg":"","count":1000,"data":[{"id":10000,"username":"user-0","sex":"女","city":"城市-0","sign":"签名-0","experience":255,"logins":24,"wealth":82830700,"classify":"作家","score":57},{"id":10001,"username":"user-1","sex":"男","city":"城市-1","sign":"签名-1","experience":884,"logins":58,"wealth":64928690,"classify":"词人","score":27},{"id":10002,"username":"user-2","sex":"女","city":"城市-2","sign":"签名-2","experience":650,"logins":77,"wealth":6298078,"classify":"酱油","score":31},{"id":10003,"username":"user-3","sex":"女","city":"城市-3","sign":"签名-3","experience":362,"logins":157,"wealth":37117017,"classify":"诗人","score":68},{"id":10004,"username":"user-4","sex":"男","city":"城市-4","sign":"签名-4","experience":807,"logins":51,"wealth":76263262,"classify":"作家","score":6},{"id":10005,"username":"user-5","sex":"女","city":"城市-5","sign":"签名-5","experience":173,"logins":68,"wealth":60344147,"classify":"作家","score":87},{"id":10006,"username":"user-6","sex":"女","city":"城市-6","sign":"签名-6","experience":982,"logins":37,"wealth":57768166,"classify":"作家","score":34},{"id":10007,"username":"user-7","sex":"男","city":"城市-7","sign":"签名-7","experience":727,"logins":150,"wealth":82030578,"classify":"作家","score":28},{"id":10008,"username":"user-8","sex":"男","city":"城市-8","sign":"签名-8","experience":951,"logins":133,"wealth":16503371,"classify":"词人","score":14},{"id":10009,"username":"user-9","sex":"女","city":"城市-9","sign":"签名-9","experience":484,"logins":25,"wealth":86801934,"classify":"词人","score":75}]} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/user30.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/user30.js deleted file mode 100644 index 0246bbd4..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/table/user30.js +++ /dev/null @@ -1,2 +0,0 @@ - -{"code":0,"msg":"","count":1000,"data":[{"id":10000,"username":"user-0","sex":"女","city":"城市-0","sign":"签名-0","experience":255,"logins":24,"wealth":82830700,"classify":"作家","score":57},{"id":10001,"username":"user-1","sex":"男","city":"城市-1","sign":"签名-1","experience":884,"logins":58,"wealth":64928690,"classify":"词人","score":27},{"id":10002,"username":"user-2","sex":"女","city":"城市-2","sign":"签名-2","experience":650,"logins":77,"wealth":6298078,"classify":"酱油","score":31},{"id":10003,"username":"user-3","sex":"女","city":"城市-3","sign":"签名-3","experience":362,"logins":157,"wealth":37117017,"classify":"诗人","score":68},{"id":10004,"username":"user-4","sex":"男","city":"城市-4","sign":"签名-4","experience":807,"logins":51,"wealth":76263262,"classify":"作家","score":6},{"id":10005,"username":"user-5","sex":"女","city":"城市-5","sign":"签名-5","experience":173,"logins":68,"wealth":60344147,"classify":"作家","score":87},{"id":10006,"username":"user-6","sex":"女","city":"城市-6","sign":"签名-6","experience":982,"logins":37,"wealth":57768166,"classify":"作家","score":34},{"id":10007,"username":"user-7","sex":"男","city":"城市-7","sign":"签名-7","experience":727,"logins":150,"wealth":82030578,"classify":"作家","score":28},{"id":10008,"username":"user-8","sex":"男","city":"城市-8","sign":"签名-8","experience":951,"logins":133,"wealth":16503371,"classify":"词人","score":14},{"id":10009,"username":"user-9","sex":"女","city":"城市-9","sign":"签名-9","experience":484,"logins":25,"wealth":86801934,"classify":"词人","score":75},{"id":10010,"username":"user-10","sex":"女","city":"城市-10","sign":"签名-10","experience":1016,"logins":182,"wealth":71294671,"classify":"诗人","score":34},{"id":10011,"username":"user-11","sex":"女","city":"城市-11","sign":"签名-11","experience":492,"logins":107,"wealth":8062783,"classify":"诗人","score":6},{"id":10012,"username":"user-12","sex":"女","city":"城市-12","sign":"签名-12","experience":106,"logins":176,"wealth":42622704,"classify":"词人","score":54},{"id":10013,"username":"user-13","sex":"男","city":"城市-13","sign":"签名-13","experience":1047,"logins":94,"wealth":59508583,"classify":"诗人","score":63},{"id":10014,"username":"user-14","sex":"男","city":"城市-14","sign":"签名-14","experience":873,"logins":116,"wealth":72549912,"classify":"词人","score":8},{"id":10015,"username":"user-15","sex":"女","city":"城市-15","sign":"签名-15","experience":1068,"logins":27,"wealth":52737025,"classify":"作家","score":28},{"id":10016,"username":"user-16","sex":"女","city":"城市-16","sign":"签名-16","experience":862,"logins":168,"wealth":37069775,"classify":"酱油","score":86},{"id":10017,"username":"user-17","sex":"女","city":"城市-17","sign":"签名-17","experience":1060,"logins":187,"wealth":66099525,"classify":"作家","score":69},{"id":10018,"username":"user-18","sex":"女","city":"城市-18","sign":"签名-18","experience":866,"logins":88,"wealth":81722326,"classify":"词人","score":74},{"id":10019,"username":"user-19","sex":"女","city":"城市-19","sign":"签名-19","experience":682,"logins":106,"wealth":68647362,"classify":"词人","score":51},{"id":10020,"username":"user-20","sex":"男","city":"城市-20","sign":"签名-20","experience":770,"logins":24,"wealth":92420248,"classify":"诗人","score":87},{"id":10021,"username":"user-21","sex":"男","city":"城市-21","sign":"签名-21","experience":184,"logins":131,"wealth":71566045,"classify":"词人","score":99},{"id":10022,"username":"user-22","sex":"男","city":"城市-22","sign":"签名-22","experience":739,"logins":152,"wealth":60907929,"classify":"作家","score":18},{"id":10023,"username":"user-23","sex":"女","city":"城市-23","sign":"签名-23","experience":127,"logins":82,"wealth":14765943,"classify":"作家","score":30},{"id":10024,"username":"user-24","sex":"女","city":"城市-24","sign":"签名-24","experience":212,"logins":133,"wealth":59011052,"classify":"词人","score":76},{"id":10025,"username":"user-25","sex":"女","city":"城市-25","sign":"签名-25","experience":938,"logins":182,"wealth":91183097,"classify":"作家","score":69},{"id":10026,"username":"user-26","sex":"男","city":"城市-26","sign":"签名-26","experience":978,"logins":7,"wealth":48008413,"classify":"作家","score":65},{"id":10027,"username":"user-27","sex":"女","city":"城市-27","sign":"签名-27","experience":371,"logins":44,"wealth":64419691,"classify":"诗人","score":60},{"id":10028,"username":"user-28","sex":"女","city":"城市-28","sign":"签名-28","experience":977,"logins":21,"wealth":75935022,"classify":"作家","score":37},{"id":10029,"username":"user-29","sex":"男","city":"城市-29","sign":"签名-29","experience":647,"logins":107,"wealth":97450636,"classify":"酱油","score":27}]} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/upload/demo.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/upload/demo.js deleted file mode 100644 index acc06a5b..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/upload/demo.js +++ /dev/null @@ -1,7 +0,0 @@ -{ - "code": 0, - "msg": "", - "data": { - "src": "https://sentsin.gitee.io/res/images/layui/avatar.png" - } -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/forget.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/forget.js deleted file mode 100644 index 836bba4e..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/forget.js +++ /dev/null @@ -1,7 +0,0 @@ -{ - "code": 0 - ,"msg": "注册成功" - ,"data": { - - } -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/login.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/login.js deleted file mode 100644 index ff906d5c..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/login.js +++ /dev/null @@ -1,7 +0,0 @@ -{ - "code": 0 - ,"msg": "登入成功" - ,"data": { - "access_token": "c262e61cd13ad99fc650e6908c7e5e65b63d2f32185ecfed6b801ee3fbdd5c0a" - } -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/logout.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/logout.js deleted file mode 100644 index 9fd1ff2c..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/logout.js +++ /dev/null @@ -1,5 +0,0 @@ -{ - "code": 0 - ,"msg": "退出成功" - ,"data": null -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/reg.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/reg.js deleted file mode 100644 index 836bba4e..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/reg.js +++ /dev/null @@ -1,7 +0,0 @@ -{ - "code": 0 - ,"msg": "注册成功" - ,"data": { - - } -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/resetpass.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/resetpass.js deleted file mode 100644 index 836bba4e..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/resetpass.js +++ /dev/null @@ -1,7 +0,0 @@ -{ - "code": 0 - ,"msg": "注册成功" - ,"data": { - - } -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/session.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/session.js deleted file mode 100644 index 491a376b..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/session.js +++ /dev/null @@ -1,9 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"data": { - "username": "tester" - ,"sex": "男" - ,"role": 1 - } -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/sms.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/sms.js deleted file mode 100644 index 836bba4e..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/user/sms.js +++ /dev/null @@ -1,7 +0,0 @@ -{ - "code": 0 - ,"msg": "注册成功" - ,"data": { - - } -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/mangadmin.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/mangadmin.js deleted file mode 100644 index fa2e6369..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/mangadmin.js +++ /dev/null @@ -1,78 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"count": "100" - ,"data": [{ - "id": "1001" - ,"loginname": "admin" - ,"telphone": "11111111111" - ,"email": "111@qq.com" - ,"role": "超级管理员" - ,"jointime": "20150217" - ,"audit": true - },{ - "id": "1002" - ,"loginname": "common-1" - ,"telphone": "22222222222" - ,"email": "222@qq.com" - ,"role": "管理员" - ,"jointime": "20160217" - ,"audit": false - },{ - "id": "1003" - ,"loginname": "common-2" - ,"telphone": "33333333333" - ,"email": "333@qq.com" - ,"role": "管理员" - ,"jointime": "20161012" - ,"audit": false - },{ - "id": "1004" - ,"loginname": "common-3" - ,"telphone": "44444444444" - ,"email": "444@qq.com" - ,"role": "管理员" - ,"jointime": "20170518" - ,"audit": true - },{ - "id": "1005" - ,"loginname": "common-4" - ,"telphone": "55555555555" - ,"email": "555@qq.com" - ,"role": "管理员" - ,"jointime": "20180101" - ,"audit": false - },{ - "id": "1006" - ,"loginname": "common-5" - ,"telphone": "66666666666" - ,"email": "666@qq.com" - ,"role": "管理员" - ,"jointime": "20160217" - ,"audit": false - },{ - "id": "1007" - ,"loginname": "common-6" - ,"telphone": "77777777777" - ,"email": "777@qq.com" - ,"role": "管理员" - ,"jointime": "20161012" - ,"audit": false - },{ - "id": "1008" - ,"loginname": "common-7" - ,"telphone": "88888888888" - ,"email": "888@qq.com" - ,"role": "管理员" - ,"jointime": "20170518" - ,"audit": true - },{ - "id": "1009" - ,"loginname": "common-8" - ,"telphone": "99999999999" - ,"email": "999@qq.com" - ,"role": "管理员" - ,"jointime": "20180101" - ,"audit": false - }] -} diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/role.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/role.js deleted file mode 100644 index 6d5ba5df..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/role.js +++ /dev/null @@ -1,54 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"count": "100" - ,"data": [{ - "id": "1" - ,"rolename": "超级管理员" - ,"limits": "管理所有的管理员" - ,"descr": "拥有至高无上的权利" - ,"check": true - },{ - "id": "2" - ,"rolename": "管理员" - ,"limits": "所有列表的管理" - ,"descr": "事情很多,权力很大" - ,"check": true - },{ - "id": "3" - ,"rolename": "文章撰写员" - ,"limits": "负责文章的编写" - ,"descr": "文采第一的人才集合" - ,"check": false - },{ - "id": "4" - ,"rolename": "纠错员" - ,"limits": "负责文章内容的修改" - ,"descr": "暂无" - ,"check": false - },{ - "id": "5" - ,"rolename": "统计人员" - ,"limits": "对数据进行统计" - ,"descr": "暂无" - ,"check": false - },{ - "id": "6" - ,"rolename": "评估员" - ,"limits": "对统计数据进行评估" - ,"descr": "及时捕捉市场发展动态" - ,"check": false - },{ - "id": "7" - ,"rolename": "采购员" - ,"limits": "负责员工的伙食" - ,"descr": "暂无" - ,"check": false - },{ - "id": "8" - ,"rolename": "推销员" - ,"limits": "介绍销售公司产品" - ,"descr": "暂无" - ,"check": false - }] -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/webuser.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/webuser.js deleted file mode 100644 index 233a47a2..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/useradmin/webuser.js +++ /dev/null @@ -1,143 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"count": "100" - ,"data": [{ - "id": "001" - ,"username": "用户-1" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"phone": 12345678901 - ,"email": "11111@qq.com" - ,"sex": "男" - ,"ip": "1111111" - ,"jointime": 20171204 - },{ - "id": "002" - ,"username": "用户-2" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"phone": 12345678901 - ,"email": "11111@qq.com" - ,"sex": "男" - ,"ip": "1111111" - ,"jointime": 20171204 - },{ - "id": "003" - ,"username": "用户-3" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"phone": 12345678901 - ,"email": "11111@qq.com" - ,"sex": "女" - ,"ip": "1111111" - ,"jointime": 20171011 - ,"LAY_CHECKED": true - },{ - "id": "004" - ,"username": "用户-4" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"phone": 12345678901 - ,"email": "11111@qq.com" - ,"sex": "男" - ,"ip": "1111111" - ,"jointime": 20160505 - },{ - "id": "005" - ,"username": "用户-5" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"phone": 12345678901 - ,"email": "11111@qq.com" - ,"sex": "男" - ,"ip": "1111111" - ,"jointime": 20171204 - },{ - "id": "006" - ,"username": "用户-6" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"phone": 12345678901 - ,"email": "11111@qq.com" - ,"sex": "男" - ,"ip": "1111111" - ,"jointime": 20171204 - },{ - "id": "007" - ,"username": "用户-7" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"phone": 12345678901 - ,"email": "11111@qq.com" - ,"sex": "男" - ,"ip": "1111111" - ,"jointime": 20180210 - },{ - "id": "008" - ,"username": "用户-8" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"phone": 12345678901 - ,"email": "11111@qq.com" - ,"sex": "女" - ,"ip": "1111111" - ,"jointime": 20171204 - },{ - "id": "009" - ,"username": "用户-9" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"phone": 12345678901 - ,"email": "11111@qq.com" - ,"sex": "女" - ,"ip": "1111111" - ,"jointime": 20171204 - },{ - "id": "010" - ,"username": "用户-10" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"phone": 12345678901 - ,"email": "11111@qq.com" - ,"sex": "男" - ,"ip": "1111111" - ,"jointime": 20170719 - },{ - "id": "011" - ,"username": "用户-11" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"phone": 12345678901 - ,"email": "11111@qq.com" - ,"sex": "男" - ,"ip": "1111111" - ,"jointime": 20171204 - },{ - "id": "012" - ,"username": "用户-12" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"phone": 12345678901 - ,"email": "11111@qq.com" - ,"sex": "女" - ,"ip": "1111111" - ,"jointime": 20171204 - },{ - "id": "013" - ,"username": "用户-13" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"phone": 12345678901 - ,"email": "11111@qq.com" - ,"sex": "女" - ,"ip": "1111111" - ,"jointime": 20171204 - ,"LAY_CHECKED": true - },{ - "id": "014" - ,"username": "用户-14" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"phone": 12345678901 - ,"email": "11111@qq.com" - ,"sex": "男" - ,"ip": "1111111" - ,"jointime": 20171204 - },{ - "id": "015" - ,"username": "用户-15" - ,"avatar": "https://sentsin.gitee.io/res/images/layui/avatar.png" - ,"phone": 12345678901 - ,"email": "11111@qq.com" - ,"sex": "男" - ,"ip": "1111111" - ,"jointime": 20171204 - }] -} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/json/workorder/demo.js b/iot-server/server-starter/src/main/webapp/assets/zeus/json/workorder/demo.js deleted file mode 100644 index 70ab5f0c..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/json/workorder/demo.js +++ /dev/null @@ -1,78 +0,0 @@ -{ - "code": 0 - ,"msg": "" - ,"count": "100" - ,"data": [{ - "orderid": 111 - ,"title": "移动支付踏入马来西亚,聚合支付紧随其后" - ,"attr": "公告" - ,"progress": "25%" - ,"submit": "tester" - ,"accept": "员工-1" - ,"state": "处理中" - },{ - "orderid": 222 - ,"title": "凡科拖拽式免费建站神器,享双重优惠!" - ,"attr": "讨论" - ,"progress": "100%" - ,"submit": "猫吃" - ,"accept": "员工-1" - ,"state": "已处理" - },{ - "orderid": 333 - ,"title": "看着别人的老板给员工送汽车有感" - ,"attr": "分享" - ,"progress": "0%" - ,"submit": "纸飞机" - ,"accept": "" - ,"state": "未分配" - },{ - "orderid": 444 - ,"title": "DISCUZ的云平台还有戏吗" - ,"attr": "提问" - ,"progress": "0%" - ,"submit": "纸飞机" - ,"accept": "" - ,"state": "未分配" - },{ - "orderid": 555 - ,"title": "现在个人网站还有必要长期坚持下去吗?" - ,"attr": "提问" - ,"progress": "50%" - ,"submit": "纸飞机" - ,"accept": "员工-2" - ,"state": "处理中" - },{ - "orderid": 666 - ,"title": "求安排一个技术客服?" - ,"attr": "公告" - ,"progress": "25%" - ,"submit": "纸飞机" - ,"accept": "员工-3" - ,"state": "处理中" - },{ - "orderid": 777 - ,"title": "游戏 网页美工,一个月多少工资才正常?" - ,"attr": "提问" - ,"progress": "100%" - ,"submit": "纸飞机" - ,"accept": "员工-1" - ,"state": "已处理" - },{ - "orderid": 888 - ,"title": "几年没来了,蓝色理想帖子这么少了啊" - ,"attr": "提问" - ,"progress": "0%" - ,"submit": "纸飞机" - ,"accept": "" - ,"state": "未分配" - },{ - "orderid": 999 - ,"title": "我的天,求推荐靠谱的学习网站" - ,"attr": "提问" - ,"progress": "50%" - ,"submit": "纸飞机" - ,"accept": "员工-2" - ,"state": "处理中" - }] -} \ No newline at end of file diff --git "a/iot-server/server-starter/src/main/webapp/assets/zeus/json/\350\257\264\346\230\216.txt" "b/iot-server/server-starter/src/main/webapp/assets/zeus/json/\350\257\264\346\230\216.txt" deleted file mode 100644 index ff402e5b..00000000 --- "a/iot-server/server-starter/src/main/webapp/assets/zeus/json/\350\257\264\346\230\216.txt" +++ /dev/null @@ -1,3 +0,0 @@ - -注意:这里是模拟的数据。 -实际应用时,请在模板文件(.html)中的 lay-url="" 和其它相关接口的 url 设置成你真实的接口地址 \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/layui.css b/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/layui.css deleted file mode 100644 index c784a25e..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/layui.css +++ /dev/null @@ -1 +0,0 @@ -.layui-inline,img{display:inline-block;vertical-align:middle}h1,h2,h3,h4,h5,h6{font-weight:400}a,body{color:#333}.layui-edge,.layui-header,.layui-inline,.layui-main{position:relative}.layui-edge,hr{height:0;overflow:hidden}.layui-layout-body,.layui-side,.layui-side-scroll{overflow-x:hidden}.layui-edge,.layui-elip,hr{overflow:hidden}.layui-btn,.layui-edge,.layui-inline,img{vertical-align:middle}.layui-btn,.layui-disabled,.layui-icon,.layui-unselect{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}blockquote,body,button,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,input,li,ol,p,pre,td,textarea,th,ul{margin:0;padding:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}a:active,a:hover{outline:0}img{border:none}li{list-style:none}table{border-collapse:collapse;border-spacing:0}h4,h5,h6{font-size:100%}button,input,optgroup,option,select,textarea{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;outline:0}pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}body{line-height:1.6;color:rgba(0,0,0,.85);font:14px Helvetica Neue,Helvetica,PingFang SC,Tahoma,Arial,sans-serif}hr{line-height:0;margin:10px 0;padding:0;border:none!important;border-bottom:1px solid #eee!important;clear:both;background:0 0}a{text-decoration:none}a:hover{color:#777}a cite{font-style:normal;*cursor:pointer}.layui-border-box,.layui-border-box *{box-sizing:border-box}.layui-box,.layui-box *{box-sizing:content-box}.layui-clear{clear:both;*zoom:1}.layui-clear:after{content:'\20';clear:both;*zoom:1;display:block;height:0}.layui-inline{*display:inline;*zoom:1}.layui-btn,.layui-btn-group,.layui-edge{display:inline-block}.layui-edge{width:0;border-width:6px;border-style:dashed;border-color:transparent}.layui-edge-top{top:-4px;border-bottom-color:#999;border-bottom-style:solid}.layui-edge-right{border-left-color:#999;border-left-style:solid}.layui-edge-bottom{top:2px;border-top-color:#999;border-top-style:solid}.layui-edge-left{border-right-color:#999;border-right-style:solid}.layui-elip{text-overflow:ellipsis;white-space:nowrap}.layui-disabled,.layui-disabled:hover{color:#d2d2d2!important;cursor:not-allowed!important}.layui-circle{border-radius:100%}.layui-show{display:block!important}.layui-hide{display:none!important}.layui-show-v{visibility:visible!important}.layui-hide-v{visibility:hidden!important}@font-face{font-family:layui-icon;src:url(../font/iconfont.eot?v=256);src:url(../font/iconfont.eot?v=256#iefix) format('embedded-opentype'),url(../font/iconfont.woff2?v=256) format('woff2'),url(../font/iconfont.woff?v=256) format('woff'),url(../font/iconfont.ttf?v=256) format('truetype'),url(../font/iconfont.svg?v=256#layui-icon) format('svg')}.layui-icon{font-family:layui-icon!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-icon-reply-fill:before{content:"\e611"}.layui-icon-set-fill:before{content:"\e614"}.layui-icon-menu-fill:before{content:"\e60f"}.layui-icon-search:before{content:"\e615"}.layui-icon-share:before{content:"\e641"}.layui-icon-set-sm:before{content:"\e620"}.layui-icon-engine:before{content:"\e628"}.layui-icon-close:before{content:"\1006"}.layui-icon-close-fill:before{content:"\1007"}.layui-icon-chart-screen:before{content:"\e629"}.layui-icon-star:before{content:"\e600"}.layui-icon-circle-dot:before{content:"\e617"}.layui-icon-chat:before{content:"\e606"}.layui-icon-release:before{content:"\e609"}.layui-icon-list:before{content:"\e60a"}.layui-icon-chart:before{content:"\e62c"}.layui-icon-ok-circle:before{content:"\1005"}.layui-icon-layim-theme:before{content:"\e61b"}.layui-icon-table:before{content:"\e62d"}.layui-icon-right:before{content:"\e602"}.layui-icon-left:before{content:"\e603"}.layui-icon-cart-simple:before{content:"\e698"}.layui-icon-face-cry:before{content:"\e69c"}.layui-icon-face-smile:before{content:"\e6af"}.layui-icon-survey:before{content:"\e6b2"}.layui-icon-tree:before{content:"\e62e"}.layui-icon-ie:before{content:"\e7bb"}.layui-icon-upload-circle:before{content:"\e62f"}.layui-icon-add-circle:before{content:"\e61f"}.layui-icon-download-circle:before{content:"\e601"}.layui-icon-templeate-1:before{content:"\e630"}.layui-icon-util:before{content:"\e631"}.layui-icon-face-surprised:before{content:"\e664"}.layui-icon-edit:before{content:"\e642"}.layui-icon-speaker:before{content:"\e645"}.layui-icon-down:before{content:"\e61a"}.layui-icon-file:before{content:"\e621"}.layui-icon-layouts:before{content:"\e632"}.layui-icon-rate-half:before{content:"\e6c9"}.layui-icon-add-circle-fine:before{content:"\e608"}.layui-icon-prev-circle:before{content:"\e633"}.layui-icon-read:before{content:"\e705"}.layui-icon-404:before{content:"\e61c"}.layui-icon-carousel:before{content:"\e634"}.layui-icon-help:before{content:"\e607"}.layui-icon-code-circle:before{content:"\e635"}.layui-icon-windows:before{content:"\e67f"}.layui-icon-water:before{content:"\e636"}.layui-icon-username:before{content:"\e66f"}.layui-icon-find-fill:before{content:"\e670"}.layui-icon-about:before{content:"\e60b"}.layui-icon-location:before{content:"\e715"}.layui-icon-up:before{content:"\e619"}.layui-icon-pause:before{content:"\e651"}.layui-icon-date:before{content:"\e637"}.layui-icon-layim-uploadfile:before{content:"\e61d"}.layui-icon-delete:before{content:"\e640"}.layui-icon-play:before{content:"\e652"}.layui-icon-top:before{content:"\e604"}.layui-icon-firefox:before{content:"\e686"}.layui-icon-friends:before{content:"\e612"}.layui-icon-refresh-3:before{content:"\e9aa"}.layui-icon-ok:before{content:"\e605"}.layui-icon-layer:before{content:"\e638"}.layui-icon-face-smile-fine:before{content:"\e60c"}.layui-icon-dollar:before{content:"\e659"}.layui-icon-group:before{content:"\e613"}.layui-icon-layim-download:before{content:"\e61e"}.layui-icon-picture-fine:before{content:"\e60d"}.layui-icon-link:before{content:"\e64c"}.layui-icon-diamond:before{content:"\e735"}.layui-icon-log:before{content:"\e60e"}.layui-icon-key:before{content:"\e683"}.layui-icon-rate-solid:before{content:"\e67a"}.layui-icon-fonts-del:before{content:"\e64f"}.layui-icon-unlink:before{content:"\e64d"}.layui-icon-fonts-clear:before{content:"\e639"}.layui-icon-triangle-r:before{content:"\e623"}.layui-icon-circle:before{content:"\e63f"}.layui-icon-radio:before{content:"\e643"}.layui-icon-align-center:before{content:"\e647"}.layui-icon-align-right:before{content:"\e648"}.layui-icon-align-left:before{content:"\e649"}.layui-icon-loading-1:before{content:"\e63e"}.layui-icon-return:before{content:"\e65c"}.layui-icon-fonts-strong:before{content:"\e62b"}.layui-icon-upload:before{content:"\e67c"}.layui-icon-dialogue:before{content:"\e63a"}.layui-icon-video:before{content:"\e6ed"}.layui-icon-headset:before{content:"\e6fc"}.layui-icon-cellphone-fine:before{content:"\e63b"}.layui-icon-add-1:before{content:"\e654"}.layui-icon-face-smile-b:before{content:"\e650"}.layui-icon-fonts-html:before{content:"\e64b"}.layui-icon-screen-full:before{content:"\e622"}.layui-icon-form:before{content:"\e63c"}.layui-icon-cart:before{content:"\e657"}.layui-icon-camera-fill:before{content:"\e65d"}.layui-icon-tabs:before{content:"\e62a"}.layui-icon-heart-fill:before{content:"\e68f"}.layui-icon-fonts-code:before{content:"\e64e"}.layui-icon-ios:before{content:"\e680"}.layui-icon-at:before{content:"\e687"}.layui-icon-fire:before{content:"\e756"}.layui-icon-set:before{content:"\e716"}.layui-icon-fonts-u:before{content:"\e646"}.layui-icon-triangle-d:before{content:"\e625"}.layui-icon-tips:before{content:"\e702"}.layui-icon-picture:before{content:"\e64a"}.layui-icon-more-vertical:before{content:"\e671"}.layui-icon-bluetooth:before{content:"\e689"}.layui-icon-flag:before{content:"\e66c"}.layui-icon-loading:before{content:"\e63d"}.layui-icon-fonts-i:before{content:"\e644"}.layui-icon-refresh-1:before{content:"\e666"}.layui-icon-rmb:before{content:"\e65e"}.layui-icon-addition:before{content:"\e624"}.layui-icon-home:before{content:"\e68e"}.layui-icon-time:before{content:"\e68d"}.layui-icon-user:before{content:"\e770"}.layui-icon-notice:before{content:"\e667"}.layui-icon-chrome:before{content:"\e68a"}.layui-icon-edge:before{content:"\e68b"}.layui-icon-login-weibo:before{content:"\e675"}.layui-icon-voice:before{content:"\e688"}.layui-icon-upload-drag:before{content:"\e681"}.layui-icon-login-qq:before{content:"\e676"}.layui-icon-snowflake:before{content:"\e6b1"}.layui-icon-heart:before{content:"\e68c"}.layui-icon-logout:before{content:"\e682"}.layui-icon-file-b:before{content:"\e655"}.layui-icon-template:before{content:"\e663"}.layui-icon-transfer:before{content:"\e691"}.layui-icon-auz:before{content:"\e672"}.layui-icon-console:before{content:"\e665"}.layui-icon-app:before{content:"\e653"}.layui-icon-prev:before{content:"\e65a"}.layui-icon-website:before{content:"\e7ae"}.layui-icon-next:before{content:"\e65b"}.layui-icon-component:before{content:"\e857"}.layui-icon-android:before{content:"\e684"}.layui-icon-more:before{content:"\e65f"}.layui-icon-login-wechat:before{content:"\e677"}.layui-icon-shrink-right:before{content:"\e668"}.layui-icon-spread-left:before{content:"\e66b"}.layui-icon-camera:before{content:"\e660"}.layui-icon-note:before{content:"\e66e"}.layui-icon-refresh:before{content:"\e669"}.layui-icon-female:before{content:"\e661"}.layui-icon-male:before{content:"\e662"}.layui-icon-screen-restore:before{content:"\e758"}.layui-icon-password:before{content:"\e673"}.layui-icon-senior:before{content:"\e674"}.layui-icon-theme:before{content:"\e66a"}.layui-icon-tread:before{content:"\e6c5"}.layui-icon-praise:before{content:"\e6c6"}.layui-icon-star-fill:before{content:"\e658"}.layui-icon-rate:before{content:"\e67b"}.layui-icon-template-1:before{content:"\e656"}.layui-icon-vercode:before{content:"\e679"}.layui-icon-service:before{content:"\e626"}.layui-icon-cellphone:before{content:"\e678"}.layui-icon-print:before{content:"\e66d"}.layui-icon-cols:before{content:"\e610"}.layui-icon-wifi:before{content:"\e7e0"}.layui-icon-export:before{content:"\e67d"}.layui-icon-rss:before{content:"\e808"}.layui-icon-slider:before{content:"\e714"}.layui-icon-email:before{content:"\e618"}.layui-icon-subtraction:before{content:"\e67e"}.layui-icon-mike:before{content:"\e6dc"}.layui-icon-light:before{content:"\e748"}.layui-icon-gift:before{content:"\e627"}.layui-icon-mute:before{content:"\e685"}.layui-icon-reduce-circle:before{content:"\e616"}.layui-icon-music:before{content:"\e690"}.layui-main{width:1140px;margin:0 auto}.layui-header{z-index:1000;height:60px}.layui-header a:hover{transition:all .5s;-webkit-transition:all .5s}.layui-side{position:fixed;left:0;top:0;bottom:0;z-index:999;width:200px}.layui-side-scroll{position:relative;width:220px;height:100%}.layui-body{position:relative;left:200px;right:0;top:0;bottom:0;z-index:900;width:auto;box-sizing:border-box}.layui-layout-admin .layui-header{position:fixed;top:0;left:0;right:0;background-color:#23262E}.layui-layout-admin .layui-side{top:60px;width:200px;overflow-x:hidden}.layui-layout-admin .layui-body{position:absolute;top:60px;padding-bottom:44px}.layui-layout-admin .layui-main{width:auto;margin:0 15px}.layui-layout-admin .layui-footer{position:fixed;left:200px;right:0;bottom:0;z-index:990;height:44px;line-height:44px;padding:0 15px;box-shadow:-1px 0 4px rgb(0 0 0 / 12%);background-color:#FAFAFA}.layui-layout-admin .layui-logo{position:absolute;left:0;top:0;width:200px;height:100%;line-height:60px;text-align:center;color:#009688;font-size:16px;box-shadow:0 1px 2px 0 rgb(0 0 0 / 15%)}.layui-layout-admin .layui-header .layui-nav{background:0 0}.layui-layout-left{position:absolute!important;left:200px;top:0}.layui-layout-right{position:absolute!important;right:0;top:0}.layui-container{position:relative;margin:0 auto;padding:0 15px;box-sizing:border-box}.layui-fluid{position:relative;margin:0 auto;padding:0 15px}.layui-row:after,.layui-row:before{content:"";display:block;clear:both}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9,.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9,.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9,.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{position:relative;display:block;box-sizing:border-box}.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{float:left}.layui-col-xs1{width:8.33333333%}.layui-col-xs2{width:16.66666667%}.layui-col-xs3{width:25%}.layui-col-xs4{width:33.33333333%}.layui-col-xs5{width:41.66666667%}.layui-col-xs6{width:50%}.layui-col-xs7{width:58.33333333%}.layui-col-xs8{width:66.66666667%}.layui-col-xs9{width:75%}.layui-col-xs10{width:83.33333333%}.layui-col-xs11{width:91.66666667%}.layui-col-xs12{width:100%}.layui-col-xs-offset1{margin-left:8.33333333%}.layui-col-xs-offset2{margin-left:16.66666667%}.layui-col-xs-offset3{margin-left:25%}.layui-col-xs-offset4{margin-left:33.33333333%}.layui-col-xs-offset5{margin-left:41.66666667%}.layui-col-xs-offset6{margin-left:50%}.layui-col-xs-offset7{margin-left:58.33333333%}.layui-col-xs-offset8{margin-left:66.66666667%}.layui-col-xs-offset9{margin-left:75%}.layui-col-xs-offset10{margin-left:83.33333333%}.layui-col-xs-offset11{margin-left:91.66666667%}.layui-col-xs-offset12{margin-left:100%}@media screen and (max-width:768px){.layui-hide-xs{display:none!important}.layui-show-xs-block{display:block!important}.layui-show-xs-inline{display:inline!important}.layui-show-xs-inline-block{display:inline-block!important}}@media screen and (min-width:768px){.layui-container{width:750px}.layui-hide-sm{display:none!important}.layui-show-sm-block{display:block!important}.layui-show-sm-inline{display:inline!important}.layui-show-sm-inline-block{display:inline-block!important}.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9{float:left}.layui-col-sm1{width:8.33333333%}.layui-col-sm2{width:16.66666667%}.layui-col-sm3{width:25%}.layui-col-sm4{width:33.33333333%}.layui-col-sm5{width:41.66666667%}.layui-col-sm6{width:50%}.layui-col-sm7{width:58.33333333%}.layui-col-sm8{width:66.66666667%}.layui-col-sm9{width:75%}.layui-col-sm10{width:83.33333333%}.layui-col-sm11{width:91.66666667%}.layui-col-sm12{width:100%}.layui-col-sm-offset1{margin-left:8.33333333%}.layui-col-sm-offset2{margin-left:16.66666667%}.layui-col-sm-offset3{margin-left:25%}.layui-col-sm-offset4{margin-left:33.33333333%}.layui-col-sm-offset5{margin-left:41.66666667%}.layui-col-sm-offset6{margin-left:50%}.layui-col-sm-offset7{margin-left:58.33333333%}.layui-col-sm-offset8{margin-left:66.66666667%}.layui-col-sm-offset9{margin-left:75%}.layui-col-sm-offset10{margin-left:83.33333333%}.layui-col-sm-offset11{margin-left:91.66666667%}.layui-col-sm-offset12{margin-left:100%}}@media screen and (min-width:992px){.layui-container{width:970px}.layui-hide-md{display:none!important}.layui-show-md-block{display:block!important}.layui-show-md-inline{display:inline!important}.layui-show-md-inline-block{display:inline-block!important}.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9{float:left}.layui-col-md1{width:8.33333333%}.layui-col-md2{width:16.66666667%}.layui-col-md3{width:25%}.layui-col-md4{width:33.33333333%}.layui-col-md5{width:41.66666667%}.layui-col-md6{width:50%}.layui-col-md7{width:58.33333333%}.layui-col-md8{width:66.66666667%}.layui-col-md9{width:75%}.layui-col-md10{width:83.33333333%}.layui-col-md11{width:91.66666667%}.layui-col-md12{width:100%}.layui-col-md-offset1{margin-left:8.33333333%}.layui-col-md-offset2{margin-left:16.66666667%}.layui-col-md-offset3{margin-left:25%}.layui-col-md-offset4{margin-left:33.33333333%}.layui-col-md-offset5{margin-left:41.66666667%}.layui-col-md-offset6{margin-left:50%}.layui-col-md-offset7{margin-left:58.33333333%}.layui-col-md-offset8{margin-left:66.66666667%}.layui-col-md-offset9{margin-left:75%}.layui-col-md-offset10{margin-left:83.33333333%}.layui-col-md-offset11{margin-left:91.66666667%}.layui-col-md-offset12{margin-left:100%}}@media screen and (min-width:1200px){.layui-container{width:1170px}.layui-hide-lg{display:none!important}.layui-show-lg-block{display:block!important}.layui-show-lg-inline{display:inline!important}.layui-show-lg-inline-block{display:inline-block!important}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9{float:left}.layui-col-lg1{width:8.33333333%}.layui-col-lg2{width:16.66666667%}.layui-col-lg3{width:25%}.layui-col-lg4{width:33.33333333%}.layui-col-lg5{width:41.66666667%}.layui-col-lg6{width:50%}.layui-col-lg7{width:58.33333333%}.layui-col-lg8{width:66.66666667%}.layui-col-lg9{width:75%}.layui-col-lg10{width:83.33333333%}.layui-col-lg11{width:91.66666667%}.layui-col-lg12{width:100%}.layui-col-lg-offset1{margin-left:8.33333333%}.layui-col-lg-offset2{margin-left:16.66666667%}.layui-col-lg-offset3{margin-left:25%}.layui-col-lg-offset4{margin-left:33.33333333%}.layui-col-lg-offset5{margin-left:41.66666667%}.layui-col-lg-offset6{margin-left:50%}.layui-col-lg-offset7{margin-left:58.33333333%}.layui-col-lg-offset8{margin-left:66.66666667%}.layui-col-lg-offset9{margin-left:75%}.layui-col-lg-offset10{margin-left:83.33333333%}.layui-col-lg-offset11{margin-left:91.66666667%}.layui-col-lg-offset12{margin-left:100%}}.layui-col-space1{margin:-.5px}.layui-col-space1>*{padding:.5px}.layui-col-space2{margin:-1px}.layui-col-space2>*{padding:1px}.layui-col-space4{margin:-2px}.layui-col-space4>*{padding:2px}.layui-col-space5{margin:-2.5px}.layui-col-space5>*{padding:2.5px}.layui-col-space6{margin:-3px}.layui-col-space6>*{padding:3px}.layui-col-space8{margin:-4px}.layui-col-space8>*{padding:4px}.layui-col-space10{margin:-5px}.layui-col-space10>*{padding:5px}.layui-col-space12{margin:-6px}.layui-col-space12>*{padding:6px}.layui-col-space14{margin:-7px}.layui-col-space14>*{padding:7px}.layui-col-space15{margin:-7.5px}.layui-col-space15>*{padding:7.5px}.layui-col-space16{margin:-8px}.layui-col-space16>*{padding:8px}.layui-col-space18{margin:-9px}.layui-col-space18>*{padding:9px}.layui-col-space20{margin:-10px}.layui-col-space20>*{padding:10px}.layui-col-space22{margin:-11px}.layui-col-space22>*{padding:11px}.layui-col-space24{margin:-12px}.layui-col-space24>*{padding:12px}.layui-col-space25{margin:-12.5px}.layui-col-space25>*{padding:12.5px}.layui-col-space26{margin:-13px}.layui-col-space26>*{padding:13px}.layui-col-space28{margin:-14px}.layui-col-space28>*{padding:14px}.layui-col-space30{margin:-15px}.layui-col-space30>*{padding:15px}.layui-btn,.layui-input,.layui-select,.layui-textarea,.layui-upload-button{outline:0;-webkit-appearance:none;transition:all .3s;-webkit-transition:all .3s;box-sizing:border-box}.layui-elem-quote{margin-bottom:10px;padding:15px;line-height:1.6;border-left:5px solid #5FB878;border-radius:0 2px 2px 0;background-color:#FAFAFA}.layui-quote-nm{border-style:solid;border-width:1px 1px 1px 5px;background:0 0}.layui-elem-field{margin-bottom:10px;padding:0;border-width:1px;border-style:solid}.layui-elem-field legend{margin-left:20px;padding:0 10px;font-size:20px;font-weight:300}.layui-field-title{margin:10px 0 20px;border-width:1px 0 0}.layui-field-box{padding:15px}.layui-field-title .layui-field-box{padding:10px 0}.layui-progress{position:relative;height:6px;border-radius:20px;background-color:#eee}.layui-progress-bar{position:absolute;left:0;top:0;width:0;max-width:100%;height:6px;border-radius:20px;text-align:right;background-color:#5FB878;transition:all .3s;-webkit-transition:all .3s}.layui-progress-big,.layui-progress-big .layui-progress-bar{height:18px;line-height:18px}.layui-progress-text{position:relative;top:-20px;line-height:18px;font-size:12px;color:#666}.layui-progress-big .layui-progress-text{position:static;padding:0 10px;color:#fff}.layui-collapse{border-width:1px;border-style:solid;border-radius:2px}.layui-colla-content,.layui-colla-item{border-top-width:1px;border-top-style:solid}.layui-colla-item:first-child{border-top:none}.layui-colla-title{position:relative;height:42px;line-height:42px;padding:0 15px 0 35px;color:#333;background-color:#FAFAFA;cursor:pointer;font-size:14px;overflow:hidden}.layui-colla-content{display:none;padding:10px 15px;line-height:1.6;color:#666}.layui-colla-icon{position:absolute;left:15px;top:0;font-size:14px}.layui-card-body,.layui-card-header,.layui-form-label,.layui-form-mid,.layui-form-select,.layui-input-block,.layui-input-inline,.layui-panel,.layui-textarea{position:relative}.layui-card{margin-bottom:15px;border-radius:2px;background-color:#fff;box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.layui-form-select dl,.layui-panel{box-shadow:1px 1px 4px rgb(0 0 0 / 8%)}.layui-card:last-child{margin-bottom:0}.layui-card-header{height:42px;line-height:42px;padding:0 15px;border-bottom:1px solid #f6f6f6;color:#333;border-radius:2px 2px 0 0;font-size:14px}.layui-card-body{padding:10px 15px;line-height:24px}.layui-card-body[pad15]{padding:15px}.layui-card-body[pad20]{padding:20px}.layui-card-body .layui-table{margin:5px 0}.layui-card .layui-tab{margin:0}.layui-panel{border-width:1px;border-style:solid;border-radius:2px;background-color:#fff;color:#666}.layui-bg-black,.layui-bg-blue,.layui-bg-cyan,.layui-bg-green,.layui-bg-orange,.layui-bg-red{color:#fff!important}.layui-panel-window{position:relative;padding:15px;border-radius:0;border-top:5px solid #eee;background-color:#fff}.layui-border,.layui-border-black,.layui-border-blue,.layui-border-cyan,.layui-border-green,.layui-border-orange,.layui-border-red{border-width:1px;border-style:solid}.layui-auxiliar-moving{position:fixed;left:0;right:0;top:0;bottom:0;width:100%;height:100%;background:0 0;z-index:9999999999}.layui-bg-red{background-color:#FF5722!important}.layui-bg-orange{background-color:#FFB800!important}.layui-bg-green{background-color:#009688!important}.layui-bg-cyan{background-color:#2F4056!important}.layui-bg-blue{background-color:#1E9FFF!important}.layui-bg-black{background-color:#393D49!important}.layui-bg-gray{background-color:#FAFAFA!important;color:#666!important}.layui-badge-rim,.layui-border,.layui-colla-content,.layui-colla-item,.layui-collapse,.layui-elem-field,.layui-form-pane .layui-form-item[pane],.layui-form-pane .layui-form-label,.layui-input,.layui-layedit,.layui-layedit-tool,.layui-panel,.layui-quote-nm,.layui-select,.layui-tab-bar,.layui-tab-card,.layui-tab-title,.layui-tab-title .layui-this:after,.layui-textarea{border-color:#eee}.layui-border{color:#666!important}.layui-border-red{border-color:#FF5722!important;color:#FF5722!important}.layui-border-orange{border-color:#FFB800!important;color:#FFB800!important}.layui-border-green{border-color:#009688!important;color:#009688!important}.layui-border-cyan{border-color:#2F4056!important;color:#2F4056!important}.layui-border-blue{border-color:#1E9FFF!important;color:#1E9FFF!important}.layui-border-black{border-color:#393D49!important;color:#393D49!important}.layui-timeline-item:before{background-color:#eee}.layui-text{line-height:1.6;font-size:14px;color:#666}.layui-text h1,.layui-text h2,.layui-text h3{font-weight:500;color:#333}.layui-text h1{font-size:30px}.layui-text h2{font-size:24px}.layui-text h3{font-size:18px}.layui-text a:not(.layui-btn){color:#01AAED}.layui-text a:not(.layui-btn):hover{text-decoration:underline}.layui-text ul{padding:5px 0 5px 15px}.layui-text ul li{margin-top:5px;list-style-type:disc}.layui-text em,.layui-word-aux{color:#999!important;padding-left:5px!important;padding-right:5px!important}.layui-text p{margin:10px 0}.layui-text p:first-child{margin-top:0}.layui-font-12{font-size:12px!important}.layui-font-14{font-size:14px!important}.layui-font-16{font-size:16px!important}.layui-font-18{font-size:18px!important}.layui-font-20{font-size:20px!important}.layui-font-red{color:#FF5722!important}.layui-font-orange{color:#FFB800!important}.layui-font-green{color:#009688!important}.layui-font-cyan{color:#2F4056!important}.layui-font-blue{color:#01AAED!important}.layui-font-black{color:#000!important}.layui-font-gray{color:#c2c2c2!important}.layui-btn{height:38px;line-height:38px;border:1px solid transparent;padding:0 18px;background-color:#009688;color:#fff;white-space:nowrap;text-align:center;font-size:14px;border-radius:2px;cursor:pointer}.layui-btn:hover{opacity:.8;filter:alpha(opacity=80);color:#fff}.layui-btn:active{opacity:1;filter:alpha(opacity=100)}.layui-btn+.layui-btn{margin-left:10px}.layui-btn-container{font-size:0}.layui-btn-container .layui-btn{margin-right:10px;margin-bottom:10px}.layui-btn-container .layui-btn+.layui-btn{margin-left:0}.layui-table .layui-btn-container .layui-btn{margin-bottom:9px}.layui-btn-radius{border-radius:100px}.layui-btn .layui-icon{padding:0 2px;vertical-align:middle\9;vertical-align:bottom}.layui-btn-primary{border-color:#d2d2d2;background:0 0;color:#666}.layui-btn-primary:hover{border-color:#009688;color:#333}.layui-btn-normal{background-color:#1E9FFF}.layui-btn-warm{background-color:#FFB800}.layui-btn-danger{background-color:#FF5722}.layui-btn-checked{background-color:#5FB878}.layui-btn-disabled,.layui-btn-disabled:active,.layui-btn-disabled:hover{border-color:#eee!important;background-color:#FBFBFB!important;color:#d2d2d2!important;cursor:not-allowed!important;opacity:1}.layui-btn-lg{height:44px;line-height:44px;padding:0 25px;font-size:16px}.layui-btn-sm{height:30px;line-height:30px;padding:0 10px;font-size:12px}.layui-btn-xs{height:22px;line-height:22px;padding:0 5px;font-size:12px}.layui-btn-xs i{font-size:12px!important}.layui-btn-group{vertical-align:middle;font-size:0}.layui-btn-group .layui-btn{margin-left:0!important;margin-right:0!important;border-left:1px solid rgba(255,255,255,.5);border-radius:0}.layui-btn-group .layui-btn-primary{border-left:none}.layui-btn-group .layui-btn-primary:hover{border-color:#d2d2d2;color:#009688}.layui-btn-group .layui-btn:first-child{border-left:none;border-radius:2px 0 0 2px}.layui-btn-group .layui-btn-primary:first-child{border-left:1px solid #d2d2d2}.layui-btn-group .layui-btn:last-child{border-radius:0 2px 2px 0}.layui-btn-group .layui-btn+.layui-btn{margin-left:0}.layui-btn-group+.layui-btn-group{margin-left:10px}.layui-btn-fluid{width:100%}.layui-input,.layui-select,.layui-textarea{height:38px;line-height:1.3;line-height:38px\9;border-width:1px;border-style:solid;background-color:#fff;color:rgba(0,0,0,.85);border-radius:2px}.layui-input::-webkit-input-placeholder,.layui-select::-webkit-input-placeholder,.layui-textarea::-webkit-input-placeholder{line-height:1.3}.layui-input,.layui-textarea{display:block;width:100%;padding-left:10px}.layui-input:hover,.layui-textarea:hover{border-color:#eee!important}.layui-input:focus,.layui-textarea:focus{border-color:#d2d2d2!important}.layui-textarea{min-height:100px;height:auto;line-height:20px;padding:6px 10px;resize:vertical}.layui-select{padding:0 10px}.layui-form input[type=checkbox],.layui-form input[type=radio],.layui-form select{display:none}.layui-form [lay-ignore]{display:initial}.layui-form-item{margin-bottom:15px;clear:both;*zoom:1}.layui-form-item:after{content:'\20';clear:both;*zoom:1;display:block;height:0}.layui-form-label{float:left;display:block;padding:9px 15px;width:80px;font-weight:400;line-height:20px;text-align:right}.layui-form-label-col{display:block;float:none;padding:9px 0;line-height:20px;text-align:left}.layui-form-item .layui-inline{margin-bottom:5px;margin-right:10px}.layui-input-block{margin-left:110px;min-height:36px}.layui-input-inline{display:inline-block;vertical-align:middle}.layui-form-item .layui-input-inline{float:left;width:190px;margin-right:10px}.layui-form-text .layui-input-inline{width:auto}.layui-form-mid{float:left;display:block;padding:9px 0!important;line-height:20px;margin-right:10px}.layui-form-danger+.layui-form-select .layui-input,.layui-form-danger:focus{border-color:#FF5722!important}.layui-form-select .layui-input{padding-right:30px;cursor:pointer}.layui-form-select .layui-edge{position:absolute;right:10px;top:50%;margin-top:-3px;cursor:pointer;border-width:6px;border-top-color:#c2c2c2;border-top-style:solid;transition:all .3s;-webkit-transition:all .3s}.layui-form-select dl{display:none;position:absolute;left:0;top:42px;padding:5px 0;z-index:899;min-width:100%;border:1px solid #eee;max-height:300px;overflow-y:auto;background-color:#fff;border-radius:2px;box-sizing:border-box}.layui-form-select dl dd,.layui-form-select dl dt{padding:0 10px;line-height:36px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.layui-form-select dl dt{font-size:12px;color:#999}.layui-form-select dl dd{cursor:pointer}.layui-form-select dl dd:hover{background-color:#F6F6F6;-webkit-transition:.5s all;transition:.5s all}.layui-form-select .layui-select-group dd{padding-left:20px}.layui-form-select dl dd.layui-select-tips{padding-left:10px!important;color:#999}.layui-form-select dl dd.layui-this{background-color:#5FB878;color:#fff}.layui-form-checkbox,.layui-form-select dl dd.layui-disabled{background-color:#fff}.layui-form-selected dl{display:block}.layui-form-checkbox,.layui-form-checkbox *,.layui-form-switch{display:inline-block;vertical-align:middle}.layui-form-selected .layui-edge{margin-top:-9px;-webkit-transform:rotate(180deg);transform:rotate(180deg);margin-top:-3px\9}:root .layui-form-selected .layui-edge{margin-top:-9px\0/IE9}.layui-form-selectup dl{top:auto;bottom:42px}.layui-select-none{margin:5px 0;text-align:center;color:#999}.layui-select-disabled .layui-disabled{border-color:#eee!important}.layui-select-disabled .layui-edge{border-top-color:#d2d2d2}.layui-form-checkbox{position:relative;height:30px;line-height:30px;margin-right:10px;padding-right:30px;cursor:pointer;font-size:0;-webkit-transition:.1s linear;transition:.1s linear;box-sizing:border-box}.layui-form-checkbox span{padding:0 10px;height:100%;font-size:14px;border-radius:2px 0 0 2px;background-color:#d2d2d2;color:#fff;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.layui-form-checkbox:hover span{background-color:#c2c2c2}.layui-form-checkbox i{position:absolute;right:0;top:0;width:30px;height:28px;border:1px solid #d2d2d2;border-left:none;border-radius:0 2px 2px 0;color:#fff;font-size:20px;text-align:center}.layui-form-checkbox:hover i{border-color:#c2c2c2;color:#c2c2c2}.layui-form-checked,.layui-form-checked:hover{border-color:#5FB878}.layui-form-checked span,.layui-form-checked:hover span{background-color:#5FB878}.layui-form-checked i,.layui-form-checked:hover i{color:#5FB878}.layui-form-item .layui-form-checkbox{margin-top:4px}.layui-form-checkbox[lay-skin=primary]{height:auto!important;line-height:normal!important;min-width:18px;min-height:18px;border:none!important;margin-right:0;padding-left:28px;padding-right:0;background:0 0}.layui-form-checkbox[lay-skin=primary] span{padding-left:0;padding-right:15px;line-height:18px;background:0 0;color:#666}.layui-form-checkbox[lay-skin=primary] i{right:auto;left:0;width:16px;height:16px;line-height:16px;border:1px solid #d2d2d2;font-size:12px;border-radius:2px;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-checkbox[lay-skin=primary]:hover i{border-color:#5FB878;color:#fff}.layui-form-checked[lay-skin=primary] i{border-color:#5FB878!important;background-color:#5FB878;color:#fff}.layui-checkbox-disabled[lay-skin=primary] span{background:0 0!important;color:#c2c2c2!important}.layui-checkbox-disabled[lay-skin=primary]:hover i{border-color:#d2d2d2}.layui-form-item .layui-form-checkbox[lay-skin=primary]{margin-top:10px}.layui-form-switch{position:relative;height:22px;line-height:22px;min-width:35px;padding:0 5px;margin-top:8px;border:1px solid #d2d2d2;border-radius:20px;cursor:pointer;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch i{position:absolute;left:5px;top:3px;width:16px;height:16px;border-radius:20px;background-color:#d2d2d2;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch em{position:relative;top:0;width:25px;margin-left:21px;padding:0!important;text-align:center!important;color:#999!important;font-style:normal!important;font-size:12px}.layui-form-onswitch{border-color:#5FB878;background-color:#5FB878}.layui-checkbox-disabled,.layui-checkbox-disabled i{border-color:#eee!important}.layui-form-onswitch i{left:100%;margin-left:-21px;background-color:#fff}.layui-form-onswitch em{margin-left:5px;margin-right:21px;color:#fff!important}.layui-checkbox-disabled span{background-color:#eee!important}.layui-checkbox-disabled em{color:#d2d2d2!important}.layui-checkbox-disabled:hover i{color:#fff!important}[lay-radio]{display:none}.layui-form-radio,.layui-form-radio *{display:inline-block;vertical-align:middle}.layui-form-radio{line-height:28px;margin:6px 10px 0 0;padding-right:10px;cursor:pointer;font-size:0}.layui-form-radio *{font-size:14px}.layui-form-radio>i{margin-right:8px;font-size:22px;color:#c2c2c2}.layui-form-radio:hover *,.layui-form-radioed,.layui-form-radioed>i{color:#5FB878}.layui-radio-disabled>i{color:#eee!important}.layui-radio-disabled *{color:#c2c2c2!important}.layui-form-pane .layui-form-label{width:110px;padding:8px 15px;height:38px;line-height:20px;border-width:1px;border-style:solid;border-radius:2px 0 0 2px;text-align:center;background-color:#FAFAFA;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;box-sizing:border-box}.layui-form-pane .layui-input-inline{margin-left:-1px}.layui-form-pane .layui-input-block{margin-left:110px;left:-1px}.layui-form-pane .layui-input{border-radius:0 2px 2px 0}.layui-form-pane .layui-form-text .layui-form-label{float:none;width:100%;border-radius:2px;box-sizing:border-box;text-align:left}.layui-form-pane .layui-form-text .layui-input-inline{display:block;margin:0;top:-1px;clear:both}.layui-form-pane .layui-form-text .layui-input-block{margin:0;left:0;top:-1px}.layui-form-pane .layui-form-text .layui-textarea{min-height:100px;border-radius:0 0 2px 2px}.layui-form-pane .layui-form-checkbox{margin:4px 0 4px 10px}.layui-form-pane .layui-form-radio,.layui-form-pane .layui-form-switch{margin-top:6px;margin-left:10px}.layui-form-pane .layui-form-item[pane]{position:relative;border-width:1px;border-style:solid}.layui-form-pane .layui-form-item[pane] .layui-form-label{position:absolute;left:0;top:0;height:100%;border-width:0 1px 0 0}.layui-form-pane .layui-form-item[pane] .layui-input-inline{margin-left:110px}@media screen and (max-width:450px){.layui-form-item .layui-form-label{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-form-item .layui-inline{display:block;margin-right:0;margin-bottom:20px;clear:both}.layui-form-item .layui-inline:after{content:'\20';clear:both;display:block;height:0}.layui-form-item .layui-input-inline{display:block;float:none;left:-3px;width:auto!important;margin:0 0 10px 112px}.layui-form-item .layui-input-inline+.layui-form-mid{margin-left:110px;top:-5px;padding:0}.layui-form-item .layui-form-checkbox{margin-right:5px;margin-bottom:5px}}.layui-layedit{border-width:1px;border-style:solid;border-radius:2px}.layui-layedit-tool{padding:3px 5px;border-bottom-width:1px;border-bottom-style:solid;font-size:0}.layedit-tool-fixed{position:fixed;top:0;border-top:1px solid #eee}.layui-layedit-tool .layedit-tool-mid,.layui-layedit-tool .layui-icon{display:inline-block;vertical-align:middle;text-align:center;font-size:14px}.layui-layedit-tool .layui-icon{position:relative;width:32px;height:30px;line-height:30px;margin:3px 5px;color:#777;cursor:pointer;border-radius:2px}.layui-layedit-tool .layui-icon:hover{color:#393D49}.layui-layedit-tool .layui-icon:active{color:#000}.layui-layedit-tool .layedit-tool-active{background-color:#eee;color:#000}.layui-layedit-tool .layui-disabled,.layui-layedit-tool .layui-disabled:hover{color:#d2d2d2;cursor:not-allowed}.layui-layedit-tool .layedit-tool-mid{width:1px;height:18px;margin:0 10px;background-color:#d2d2d2}.layedit-tool-html{width:50px!important;font-size:30px!important}.layedit-tool-b,.layedit-tool-code,.layedit-tool-help{font-size:16px!important}.layedit-tool-d,.layedit-tool-face,.layedit-tool-image,.layedit-tool-unlink{font-size:18px!important}.layedit-tool-image input{position:absolute;font-size:0;left:0;top:0;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-layedit-iframe iframe{display:block;width:100%}#LAY_layedit_code{overflow:hidden}.layui-laypage{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;margin:10px 0;font-size:0}.layui-laypage>a:first-child,.layui-laypage>a:first-child em{border-radius:2px 0 0 2px}.layui-laypage>a:last-child,.layui-laypage>a:last-child em{border-radius:0 2px 2px 0}.layui-laypage>:first-child{margin-left:0!important}.layui-laypage>:last-child{margin-right:0!important}.layui-laypage a,.layui-laypage button,.layui-laypage input,.layui-laypage select,.layui-laypage span{border:1px solid #eee}.layui-laypage a,.layui-laypage span{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;padding:0 15px;height:28px;line-height:28px;margin:0 -1px 5px 0;background-color:#fff;color:#333;font-size:12px}.layui-flow-more a *,.layui-laypage input,.layui-table-view select[lay-ignore]{display:inline-block}.layui-laypage a:hover{color:#009688}.layui-laypage em{font-style:normal}.layui-laypage .layui-laypage-spr{color:#999;font-weight:700}.layui-laypage a{text-decoration:none}.layui-laypage .layui-laypage-curr{position:relative}.layui-laypage .layui-laypage-curr em{position:relative;color:#fff}.layui-laypage .layui-laypage-curr .layui-laypage-em{position:absolute;left:-1px;top:-1px;padding:1px;width:100%;height:100%;background-color:#009688}.layui-laypage-em{border-radius:2px}.layui-laypage-next em,.layui-laypage-prev em{font-family:Sim sun;font-size:16px}.layui-laypage .layui-laypage-count,.layui-laypage .layui-laypage-limits,.layui-laypage .layui-laypage-refresh,.layui-laypage .layui-laypage-skip{margin-left:10px;margin-right:10px;padding:0;border:none}.layui-laypage .layui-laypage-limits,.layui-laypage .layui-laypage-refresh{vertical-align:top}.layui-laypage .layui-laypage-refresh i{font-size:18px;cursor:pointer}.layui-laypage select{height:22px;padding:3px;border-radius:2px;cursor:pointer}.layui-laypage .layui-laypage-skip{height:30px;line-height:30px;color:#999}.layui-laypage button,.layui-laypage input{height:30px;line-height:30px;border-radius:2px;vertical-align:top;background-color:#fff;box-sizing:border-box}.layui-laypage input{width:40px;margin:0 10px;padding:0 3px;text-align:center}.layui-laypage input:focus,.layui-laypage select:focus{border-color:#009688!important}.layui-laypage button{margin-left:10px;padding:0 10px;cursor:pointer}.layui-table,.layui-table-view{margin:10px 0}.layui-flow-more{margin:10px 0;text-align:center;color:#999;font-size:14px}.layui-flow-more a{height:32px;line-height:32px}.layui-flow-more a *{vertical-align:top}.layui-flow-more a cite{padding:0 20px;border-radius:3px;background-color:#eee;color:#333;font-style:normal}.layui-flow-more a cite:hover{opacity:.8}.layui-flow-more a i{font-size:30px;color:#737383}.layui-table{width:100%;background-color:#fff;color:#666}.layui-table tr{transition:all .3s;-webkit-transition:all .3s}.layui-table th{text-align:left;font-weight:400}.layui-table tbody tr:hover,.layui-table thead tr,.layui-table-click,.layui-table-header,.layui-table-hover,.layui-table-mend,.layui-table-patch,.layui-table-tool,.layui-table-total,.layui-table-total tr,.layui-table[lay-even] tr:nth-child(even){background-color:#FAFAFA}.layui-table td,.layui-table th,.layui-table-col-set,.layui-table-fixed-r,.layui-table-grid-down,.layui-table-header,.layui-table-page,.layui-table-tips-main,.layui-table-tool,.layui-table-total,.layui-table-view,.layui-table[lay-skin=line],.layui-table[lay-skin=row]{border-width:1px;border-style:solid;border-color:#eee}.layui-table td,.layui-table th{position:relative;padding:9px 15px;min-height:20px;line-height:20px;font-size:14px}.layui-table[lay-skin=line] td,.layui-table[lay-skin=line] th{border-width:0 0 1px}.layui-table[lay-skin=row] td,.layui-table[lay-skin=row] th{border-width:0 1px 0 0}.layui-table[lay-skin=nob] td,.layui-table[lay-skin=nob] th{border:none}.layui-table img{max-width:100px}.layui-table[lay-size=lg] td,.layui-table[lay-size=lg] th{padding:15px 30px}.layui-table-view .layui-table[lay-size=lg] .layui-table-cell{height:40px;line-height:40px}.layui-table[lay-size=sm] td,.layui-table[lay-size=sm] th{font-size:12px;padding:5px 10px}.layui-table-view .layui-table[lay-size=sm] .layui-table-cell{height:20px;line-height:20px}.layui-table[lay-data]{display:none}.layui-table-box{position:relative;overflow:hidden}.layui-table-view .layui-table{position:relative;width:auto;margin:0}.layui-table-view .layui-table[lay-skin=line]{border-width:0 1px 0 0}.layui-table-view .layui-table[lay-skin=row]{border-width:0 0 1px}.layui-table-view .layui-table td,.layui-table-view .layui-table th{padding:5px 0;border-top:none;border-left:none}.layui-table-view .layui-table th.layui-unselect .layui-table-cell span{cursor:pointer}.layui-table-view .layui-table td{cursor:default}.layui-table-view .layui-table td[data-edit=text]{cursor:text}.layui-table-view .layui-form-checkbox[lay-skin=primary] i{width:18px;height:18px}.layui-table-view .layui-form-radio{line-height:0;padding:0}.layui-table-view .layui-form-radio>i{margin:0;font-size:20px}.layui-table-init{position:absolute;left:0;top:0;width:100%;height:100%;text-align:center;z-index:110}.layui-table-init .layui-icon{position:absolute;left:50%;top:50%;margin:-15px 0 0 -15px;font-size:30px;color:#c2c2c2}.layui-table-header{border-width:0 0 1px;overflow:hidden}.layui-table-header .layui-table{margin-bottom:-1px}.layui-table-tool .layui-inline[lay-event]{position:relative;width:26px;height:26px;padding:5px;line-height:16px;margin-right:10px;text-align:center;color:#333;border:1px solid #ccc;cursor:pointer;-webkit-transition:.5s all;transition:.5s all}.layui-table-tool .layui-inline[lay-event]:hover{border:1px solid #999}.layui-table-tool-temp{padding-right:120px}.layui-table-tool-self{position:absolute;right:17px;top:10px}.layui-table-tool .layui-table-tool-self .layui-inline[lay-event]{margin:0 0 0 10px}.layui-table-tool-panel{position:absolute;top:29px;left:-1px;padding:5px 0;min-width:150px;min-height:40px;border:1px solid #d2d2d2;text-align:left;overflow-y:auto;background-color:#fff;box-shadow:0 2px 4px rgba(0,0,0,.12)}.layui-table-cell,.layui-table-tool-panel li{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.layui-table-tool-panel li{padding:0 10px;line-height:30px;-webkit-transition:.5s all;transition:.5s all}.layui-menu li,.layui-menu-body-title a:hover,.layui-menu-body-title>.layui-icon:hover{transition:all .3s}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary]{width:100%;padding-left:28px}.layui-table-tool-panel li:hover{background-color:#F6F6F6}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary] i{position:absolute;left:0;top:0}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary] span{padding:0}.layui-table-tool .layui-table-tool-self .layui-table-tool-panel{left:auto;right:-1px}.layui-table-col-set{position:absolute;right:0;top:0;width:20px;height:100%;border-width:0 0 0 1px;background-color:#fff}.layui-table-sort{width:10px;height:20px;margin-left:5px;cursor:pointer!important}.layui-table-sort .layui-edge{position:absolute;left:5px;border-width:5px}.layui-table-sort .layui-table-sort-asc{top:3px;border-top:none;border-bottom-style:solid;border-bottom-color:#b2b2b2}.layui-table-sort .layui-table-sort-asc:hover{border-bottom-color:#666}.layui-table-sort .layui-table-sort-desc{bottom:5px;border-bottom:none;border-top-style:solid;border-top-color:#b2b2b2}.layui-table-sort .layui-table-sort-desc:hover{border-top-color:#666}.layui-table-sort[lay-sort=asc] .layui-table-sort-asc{border-bottom-color:#000}.layui-table-sort[lay-sort=desc] .layui-table-sort-desc{border-top-color:#000}.layui-table-cell{height:28px;line-height:28px;padding:0 15px;position:relative;box-sizing:border-box}.layui-table-cell .layui-form-checkbox[lay-skin=primary]{top:-1px;padding:0}.layui-table-cell .layui-table-link{color:#01AAED}.laytable-cell-checkbox,.laytable-cell-numbers,.laytable-cell-radio,.laytable-cell-space{padding:0;text-align:center}.layui-table-body{position:relative;overflow:auto;margin-right:-1px;margin-bottom:-1px}.layui-table-body .layui-none{line-height:26px;padding:30px 15px;text-align:center;color:#999}.layui-table-fixed{position:absolute;left:0;top:0;z-index:101}.layui-table-fixed .layui-table-body{overflow:hidden}.layui-table-fixed-l{box-shadow:1px 0 8px rgba(0,0,0,.08)}.layui-table-fixed-r{left:auto;right:-1px;border-width:0 0 0 1px;box-shadow:-1px 0 8px rgba(0,0,0,.08)}.layui-table-fixed-r .layui-table-header{position:relative;overflow:visible}.layui-table-mend{position:absolute;right:-49px;top:0;height:100%;width:50px}.layui-table-tool{position:relative;z-index:890;width:100%;min-height:50px;line-height:30px;padding:10px 15px;border-width:0 0 1px}.layui-table-tool .layui-btn-container{margin-bottom:-10px}.layui-table-page,.layui-table-total{border-width:1px 0 0;margin-bottom:-1px;overflow:hidden}.layui-table-page{position:relative;width:100%;padding:7px 7px 0;height:41px;font-size:12px;white-space:nowrap}.layui-table-page>div{height:26px}.layui-table-page .layui-laypage{margin:0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span{height:26px;line-height:26px;margin-bottom:10px;border:none;background:0 0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span.layui-laypage-curr{padding:0 12px}.layui-table-page .layui-laypage span{margin-left:0;padding:0}.layui-table-page .layui-laypage .layui-laypage-prev{margin-left:-7px!important}.layui-table-page .layui-laypage .layui-laypage-curr .layui-laypage-em{left:0;top:0;padding:0}.layui-table-page .layui-laypage button,.layui-table-page .layui-laypage input{height:26px;line-height:26px}.layui-table-page .layui-laypage input{width:40px}.layui-table-page .layui-laypage button{padding:0 10px}.layui-table-page select{height:18px}.layui-table-patch .layui-table-cell{padding:0;width:30px}.layui-table-edit{position:absolute;left:0;top:0;width:100%;height:100%;padding:0 14px 1px;border-radius:0;box-shadow:1px 1px 20px rgba(0,0,0,.15)}.layui-table-edit:focus{border-color:#5FB878!important}select.layui-table-edit{padding:0 0 0 10px;border-color:#d2d2d2}.layui-table-view .layui-form-checkbox,.layui-table-view .layui-form-radio,.layui-table-view .layui-form-switch{top:0;margin:0;box-sizing:content-box}.layui-colorpicker-alpha-slider,.layui-colorpicker-side-slider,.layui-menu,.layui-menu *,.layui-nav{box-sizing:border-box}.layui-table-view .layui-form-checkbox{top:-1px;height:26px;line-height:26px}.layui-table-view .layui-form-checkbox i{height:26px}.layui-table-grid .layui-table-cell{overflow:visible}.layui-table-grid-down{position:absolute;top:0;right:0;width:26px;height:100%;padding:5px 0;border-width:0 0 0 1px;text-align:center;background-color:#fff;color:#999;cursor:pointer}.layui-table-grid-down .layui-icon{position:absolute;top:50%;left:50%;margin:-8px 0 0 -8px}.layui-table-grid-down:hover{background-color:#fbfbfb}body .layui-table-tips .layui-layer-content{background:0 0;padding:0;box-shadow:0 1px 6px rgba(0,0,0,.12)}.layui-table-tips-main{margin:-44px 0 0 -1px;max-height:150px;padding:8px 15px;font-size:14px;overflow-y:scroll;background-color:#fff;color:#666}.layui-table-tips-c{position:absolute;right:-3px;top:-13px;width:20px;height:20px;padding:3px;cursor:pointer;background-color:#666;border-radius:50%;color:#fff}.layui-table-tips-c:hover{background-color:#777}.layui-table-tips-c:before{position:relative;right:-2px}.layui-upload-file{display:none!important;opacity:.01;filter:Alpha(opacity=1)}.layui-upload-drag,.layui-upload-form,.layui-upload-wrap{display:inline-block}.layui-upload-list{margin:10px 0}.layui-upload-choose{max-width:200px;padding:0 10px;color:#999;font-size:14px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-upload-drag{position:relative;padding:30px;border:1px dashed #e2e2e2;background-color:#fff;text-align:center;cursor:pointer;color:#999}.layui-upload-drag .layui-icon{font-size:50px;color:#009688}.layui-upload-drag[lay-over]{border-color:#009688}.layui-upload-iframe{position:absolute;width:0;height:0;border:0;visibility:hidden}.layui-upload-wrap{position:relative;vertical-align:middle}.layui-upload-wrap .layui-upload-file{display:block!important;position:absolute;left:0;top:0;z-index:10;font-size:100px;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-btn-container .layui-upload-choose{padding-left:0}.layui-menu{position:relative;margin:5px 0;background-color:#fff}.layui-menu li,.layui-menu-body-title a{padding:5px 15px}.layui-menu li{position:relative;margin:1px 0;width:calc(100% + 1px);line-height:26px;color:rgba(0,0,0,.8);font-size:14px;white-space:nowrap;cursor:pointer}.layui-menu li:hover{background-color:#F6F6F6}.layui-menu-item-parent:hover>.layui-menu-body-panel{display:block;animation-name:layui-fadein;animation-duration:.3s;animation-fill-mode:both;animation-delay:.2s}.layui-menu-item-group .layui-menu-body-title,.layui-menu-item-parent .layui-menu-body-title{padding-right:25px}.layui-menu .layui-menu-item-divider:hover,.layui-menu .layui-menu-item-group:hover,.layui-menu .layui-menu-item-none:hover{background:0 0;cursor:default}.layui-menu .layui-menu-item-group>ul{margin:5px 0 -5px}.layui-menu .layui-menu-item-group>.layui-menu-body-title{color:rgba(0,0,0,.35);user-select:none}.layui-menu .layui-menu-item-none{color:rgba(0,0,0,.35);cursor:default;text-align:center}.layui-menu .layui-menu-item-divider{margin:5px 0;padding:0;height:0;line-height:0;border-bottom:1px solid #eee;overflow:hidden}.layui-menu .layui-menu-item-down:hover,.layui-menu .layui-menu-item-up:hover{cursor:pointer}.layui-menu .layui-menu-item-up>.layui-menu-body-title{color:rgba(0,0,0,.8)}.layui-menu .layui-menu-item-up>ul{visibility:hidden;height:0;overflow:hidden}.layui-menu .layui-menu-item-down:hover>.layui-menu-body-title>.layui-icon,.layui-menu .layui-menu-item-up>.layui-menu-body-title:hover>.layui-icon{color:rgba(0,0,0,1)}.layui-menu .layui-menu-item-down>ul{visibility:visible;height:auto}.layui-breadcrumb,.layui-tree-btnGroup{visibility:hidden}.layui-menu .layui-menu-item-checked,.layui-menu .layui-menu-item-checked2{background-color:#F6F6F6!important;color:#5FB878}.layui-menu .layui-menu-item-checked a,.layui-menu .layui-menu-item-checked2 a{color:#5FB878}.layui-menu .layui-menu-item-checked:after{position:absolute;right:0;top:0;bottom:0;border-right:3px solid #5FB878;content:""}.layui-menu-body-title{position:relative;overflow:hidden;text-overflow:ellipsis}.layui-menu-body-title a{display:block;margin:-5px -15px;color:rgba(0,0,0,.8)}.layui-menu-body-title>.layui-icon{position:absolute;right:0;top:0;font-size:14px}.layui-menu-body-title>.layui-icon-right{right:-1px}.layui-menu-body-panel{display:none;position:absolute;top:-7px;left:100%;z-index:1000;margin-left:13px;padding:5px 0}.layui-menu-body-panel:before{content:"";position:absolute;width:20px;left:-16px;top:0;bottom:0}.layui-menu-body-panel-left{left:auto;right:100%;margin:0 13px}.layui-menu-body-panel-left:before{left:auto;right:-16px}.layui-menu-lg li{line-height:32px}.layui-menu-lg .layui-menu-body-title a:hover,.layui-menu-lg li:hover{background:0 0;color:#5FB878}.layui-menu-lg li .layui-menu-body-panel{margin-left:14px}.layui-menu-lg li .layui-menu-body-panel-left{margin:0 15px}.layui-dropdown{position:absolute;left:-999999px;top:-999999px;z-index:66666666;margin:5px 0;min-width:100px}.layui-dropdown:before{content:"";position:absolute;width:100%;height:6px;left:0;top:-6px}.layui-nav{position:relative;padding:0 20px;background-color:#393D49;color:#fff;border-radius:2px;font-size:0}.layui-nav *{font-size:14px}.layui-nav .layui-nav-item{position:relative;display:inline-block;*display:inline;*zoom:1;vertical-align:middle;line-height:60px}.layui-nav .layui-nav-item a{display:block;padding:0 20px;color:#fff;color:rgba(255,255,255,.7);transition:all .3s;-webkit-transition:all .3s}.layui-nav .layui-this:after,.layui-nav-bar{content:"";position:absolute;left:0;top:0;width:0;height:5px;background-color:#5FB878;transition:all .2s;-webkit-transition:all .2s;pointer-events:none}.layui-nav-bar{z-index:1000}.layui-nav[lay-bar=disabled] .layui-nav-bar{display:none}.layui-nav .layui-nav-item a:hover,.layui-nav .layui-this a{color:#fff}.layui-nav .layui-this:after{top:auto;bottom:0;width:100%}.layui-nav-img{width:30px;height:30px;margin-right:10px;border-radius:50%}.layui-nav .layui-nav-more{position:absolute;top:0;right:3px;left:auto!important;margin-top:0;font-size:12px;cursor:pointer;transition:all .2s;-webkit-transition:all .2s}.layui-nav .layui-nav-mored,.layui-nav-itemed>a .layui-nav-more{transform:rotate(180deg)}.layui-nav-child{display:none;position:absolute;left:0;top:65px;min-width:100%;line-height:36px;padding:5px 0;box-shadow:0 2px 4px rgba(0,0,0,.12);border:1px solid #eee;background-color:#fff;z-index:100;border-radius:2px;white-space:nowrap}.layui-nav .layui-nav-child a{color:#666;color:rgba(0,0,0,.8)}.layui-nav .layui-nav-child a:hover{background-color:#F6F6F6;color:rgba(0,0,0,.8)}.layui-nav-child dd{margin:1px 0;position:relative}.layui-nav-child dd.layui-this{background-color:#F6F6F6;color:#000}.layui-nav-child dd.layui-this:after{display:none}.layui-nav-child-r{left:auto;right:0}.layui-nav-child-c{text-align:center}.layui-nav-tree{width:200px;padding:0}.layui-nav-tree .layui-nav-item{display:block;width:100%;line-height:40px}.layui-nav-tree .layui-nav-item a{position:relative;height:40px;line-height:40px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-nav-tree .layui-nav-item>a{padding-top:5px;padding-bottom:5px}.layui-nav-tree .layui-nav-more{right:15px}.layui-nav-tree .layui-nav-item>a .layui-nav-more{padding:5px 0}.layui-nav-tree .layui-nav-bar{width:5px;height:0;background-color:#009688}.layui-side .layui-nav-tree .layui-nav-bar{width:2px}.layui-nav-tree .layui-nav-child dd.layui-this,.layui-nav-tree .layui-nav-child dd.layui-this a,.layui-nav-tree .layui-this,.layui-nav-tree .layui-this>a,.layui-nav-tree .layui-this>a:hover{background-color:#009688;color:#fff}.layui-nav-tree .layui-this:after{display:none}.layui-nav-itemed>a,.layui-nav-tree .layui-nav-title a,.layui-nav-tree .layui-nav-title a:hover{color:#fff!important}.layui-nav-tree .layui-nav-child{position:relative;z-index:0;top:0;border:none;box-shadow:none}.layui-nav-tree .layui-nav-child dd{margin:0}.layui-nav-tree .layui-nav-child a{color:#fff;color:rgba(255,255,255,.7)}.layui-nav-tree .layui-nav-child,.layui-nav-tree .layui-nav-child a:hover{background:0 0;color:#fff}.layui-nav-itemed>.layui-nav-child{display:block;background-color:rgba(0,0,0,.3)!important}.layui-nav-itemed>.layui-nav-child>.layui-this>.layui-nav-child{display:block}.layui-nav-side{position:fixed;top:0;bottom:0;left:0;overflow-x:hidden;z-index:999}.layui-breadcrumb{font-size:0}.layui-breadcrumb>*{font-size:14px}.layui-breadcrumb a{color:#999!important}.layui-breadcrumb a:hover{color:#5FB878!important}.layui-breadcrumb a cite{color:#666;font-style:normal}.layui-breadcrumb span[lay-separator]{margin:0 10px;color:#999}.layui-tab{margin:10px 0;text-align:left!important}.layui-tab[overflow]>.layui-tab-title{overflow:hidden}.layui-tab-title{position:relative;left:0;height:40px;white-space:nowrap;font-size:0;border-bottom-width:1px;border-bottom-style:solid;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;font-size:14px;transition:all .2s;-webkit-transition:all .2s;position:relative;line-height:40px;min-width:65px;padding:0 15px;text-align:center;cursor:pointer}.layui-tab-title li a{display:block;padding:0 15px;margin:0 -15px}.layui-tab-title .layui-this{color:#000}.layui-tab-title .layui-this:after{position:absolute;left:0;top:0;content:"";width:100%;height:41px;border-width:1px;border-style:solid;border-bottom-color:#fff;border-radius:2px 2px 0 0;box-sizing:border-box;pointer-events:none}.layui-tab-bar{position:absolute;right:0;top:0;z-index:10;width:30px;height:39px;line-height:39px;border-width:1px;border-style:solid;border-radius:2px;text-align:center;background-color:#fff;cursor:pointer}.layui-tab-bar .layui-icon{position:relative;display:inline-block;top:3px;transition:all .3s;-webkit-transition:all .3s}.layui-tab-item{display:none}.layui-tab-more{padding-right:30px;height:auto!important;white-space:normal!important}.layui-tab-more li.layui-this:after{border-bottom-color:#eee;border-radius:2px}.layui-tab-more .layui-tab-bar .layui-icon{top:-2px;top:3px\9;-webkit-transform:rotate(180deg);transform:rotate(180deg)}:root .layui-tab-more .layui-tab-bar .layui-icon{top:-2px\0/IE9}.layui-tab-content{padding:15px 0}.layui-tab-title li .layui-tab-close{position:relative;display:inline-block;width:18px;height:18px;line-height:20px;margin-left:8px;top:1px;text-align:center;font-size:14px;color:#c2c2c2;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li .layui-tab-close:hover{border-radius:2px;background-color:#FF5722;color:#fff}.layui-tab-brief>.layui-tab-title .layui-this{color:#009688}.layui-tab-brief>.layui-tab-more li.layui-this:after,.layui-tab-brief>.layui-tab-title .layui-this:after{border:none;border-radius:0;border-bottom:2px solid #5FB878}.layui-tab-brief[overflow]>.layui-tab-title .layui-this:after{top:-1px}.layui-tab-card{border-width:1px;border-style:solid;border-radius:2px;box-shadow:0 2px 5px 0 rgba(0,0,0,.1)}.layui-tab-card>.layui-tab-title{background-color:#FAFAFA}.layui-tab-card>.layui-tab-title li{margin-right:-1px;margin-left:-1px}.layui-tab-card>.layui-tab-title .layui-this{background-color:#fff}.layui-tab-card>.layui-tab-title .layui-this:after{border-top:none;border-width:1px;border-bottom-color:#fff}.layui-tab-card>.layui-tab-title .layui-tab-bar{height:40px;line-height:40px;border-radius:0;border-top:none;border-right:none}.layui-tab-card>.layui-tab-more .layui-this{background:0 0;color:#5FB878}.layui-tab-card>.layui-tab-more .layui-this:after{border:none}.layui-timeline{padding-left:5px}.layui-timeline-item{position:relative;padding-bottom:20px}.layui-timeline-axis{position:absolute;left:-5px;top:0;z-index:10;width:20px;height:20px;line-height:20px;background-color:#fff;color:#5FB878;border-radius:50%;text-align:center;cursor:pointer}.layui-timeline-axis:hover{color:#FF5722}.layui-timeline-item:before{content:"";position:absolute;left:5px;top:0;z-index:0;width:1px;height:100%}.layui-timeline-item:first-child:before{display:block}.layui-timeline-item:last-child:before{display:none}.layui-timeline-content{padding-left:25px}.layui-timeline-title{position:relative;margin-bottom:10px;line-height:22px}.layui-badge,.layui-badge-dot,.layui-badge-rim{position:relative;display:inline-block;padding:0 6px;font-size:12px;text-align:center;background-color:#FF5722;color:#fff;border-radius:2px}.layui-badge{height:18px;line-height:18px}.layui-badge-dot{width:8px;height:8px;padding:0;border-radius:50%}.layui-badge-rim{height:18px;line-height:18px;border-width:1px;border-style:solid;background-color:#fff;color:#666}.layui-btn .layui-badge,.layui-btn .layui-badge-dot{margin-left:5px}.layui-nav .layui-badge,.layui-nav .layui-badge-dot{position:absolute;top:50%;margin:-5px 6px 0}.layui-nav .layui-badge{margin-top:-10px}.layui-tab-title .layui-badge,.layui-tab-title .layui-badge-dot{left:5px;top:-2px}.layui-carousel{position:relative;left:0;top:0;background-color:#f8f8f8}.layui-carousel>[carousel-item]{position:relative;width:100%;height:100%;overflow:hidden}.layui-carousel>[carousel-item]:before{position:absolute;content:'\e63d';left:50%;top:50%;width:100px;line-height:20px;margin:-10px 0 0 -50px;text-align:center;color:#c2c2c2;font-family:layui-icon!important;font-size:30px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-carousel>[carousel-item]>*{display:none;position:absolute;left:0;top:0;width:100%;height:100%;background-color:#f8f8f8;transition-duration:.3s;-webkit-transition-duration:.3s}.layui-carousel-updown>*{-webkit-transition:.3s ease-in-out up;transition:.3s ease-in-out up}.layui-carousel-arrow{display:none\9;opacity:0;position:absolute;left:10px;top:50%;margin-top:-18px;width:36px;height:36px;line-height:36px;text-align:center;font-size:20px;border:0;border-radius:50%;background-color:rgba(0,0,0,.2);color:#fff;-webkit-transition-duration:.3s;transition-duration:.3s;cursor:pointer}.layui-carousel-arrow[lay-type=add]{left:auto!important;right:10px}.layui-carousel:hover .layui-carousel-arrow[lay-type=add],.layui-carousel[lay-arrow=always] .layui-carousel-arrow[lay-type=add]{right:20px}.layui-carousel[lay-arrow=always] .layui-carousel-arrow{opacity:1;left:20px}.layui-carousel[lay-arrow=none] .layui-carousel-arrow{display:none}.layui-carousel-arrow:hover,.layui-carousel-ind ul:hover{background-color:rgba(0,0,0,.35)}.layui-carousel:hover .layui-carousel-arrow{display:block\9;opacity:1;left:20px}.layui-carousel-ind{position:relative;top:-35px;width:100%;line-height:0!important;text-align:center;font-size:0}.layui-carousel[lay-indicator=outside]{margin-bottom:30px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind{top:10px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind ul{background-color:rgba(0,0,0,.5)}.layui-carousel[lay-indicator=none] .layui-carousel-ind{display:none}.layui-carousel-ind ul{display:inline-block;padding:5px;background-color:rgba(0,0,0,.2);border-radius:10px;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind li{display:inline-block;width:10px;height:10px;margin:0 3px;font-size:14px;background-color:#eee;background-color:rgba(255,255,255,.5);border-radius:50%;cursor:pointer;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind li:hover{background-color:rgba(255,255,255,.7)}.layui-carousel-ind li.layui-this{background-color:#fff}.layui-carousel>[carousel-item]>.layui-carousel-next,.layui-carousel>[carousel-item]>.layui-carousel-prev,.layui-carousel>[carousel-item]>.layui-this{display:block}.layui-carousel>[carousel-item]>.layui-this{left:0}.layui-carousel>[carousel-item]>.layui-carousel-prev{left:-100%}.layui-carousel>[carousel-item]>.layui-carousel-next{left:100%}.layui-carousel>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel>[carousel-item]>.layui-carousel-prev.layui-carousel-right{left:0}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-left{left:-100%}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-right{left:100%}.layui-carousel[lay-anim=updown] .layui-carousel-arrow{left:50%!important;top:20px;margin:0 0 0 -18px}.layui-carousel[lay-anim=updown]>[carousel-item]>*,.layui-carousel[lay-anim=fade]>[carousel-item]>*{left:0!important}.layui-carousel[lay-anim=updown] .layui-carousel-arrow[lay-type=add]{top:auto!important;bottom:20px}.layui-carousel[lay-anim=updown] .layui-carousel-ind{position:absolute;top:50%;right:20px;width:auto;height:auto}.layui-carousel[lay-anim=updown] .layui-carousel-ind ul{padding:3px 5px}.layui-carousel[lay-anim=updown] .layui-carousel-ind li{display:block;margin:6px 0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next{top:100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-left{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-right{top:100%}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev{opacity:0}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{opacity:1}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-right{opacity:0}.layui-fixbar{position:fixed;right:15px;bottom:15px;z-index:999999}.layui-fixbar li{width:50px;height:50px;line-height:50px;margin-bottom:1px;text-align:center;cursor:pointer;font-size:30px;background-color:#9F9F9F;color:#fff;border-radius:2px;opacity:.95}.layui-fixbar li:hover{opacity:.85}.layui-fixbar li:active{opacity:1}.layui-fixbar .layui-fixbar-top{display:none;font-size:40px}body .layui-util-face{border:none;background:0 0}body .layui-util-face .layui-layer-content{padding:0;background-color:#fff;color:#666;box-shadow:none}.layui-util-face .layui-layer-TipsG{display:none}.layui-transfer-active,.layui-transfer-box{display:inline-block;vertical-align:middle}.layui-util-face ul{position:relative;width:372px;padding:10px;border:1px solid #D9D9D9;background-color:#fff;box-shadow:0 0 20px rgba(0,0,0,.2)}.layui-util-face ul li{cursor:pointer;float:left;border:1px solid #e8e8e8;height:22px;width:26px;overflow:hidden;margin:-1px 0 0 -1px;padding:4px 2px;text-align:center}.layui-util-face ul li:hover{position:relative;z-index:2;border:1px solid #eb7350;background:#fff9ec}.layui-code{position:relative;margin:10px 0;padding:15px;line-height:20px;border:1px solid #eee;border-left-width:6px;background-color:#FAFAFA;color:#333;font-family:Courier New;font-size:12px}.layui-transfer-box,.layui-transfer-header,.layui-transfer-search{border-width:0;border-style:solid;border-color:#eee}.layui-transfer-box{position:relative;border-width:1px;width:200px;height:360px;border-radius:2px;background-color:#fff}.layui-transfer-box .layui-form-checkbox{width:100%;margin:0!important}.layui-transfer-header{height:38px;line-height:38px;padding:0 10px;border-bottom-width:1px}.layui-transfer-search{position:relative;padding:10px;border-bottom-width:1px}.layui-transfer-search .layui-input{height:32px;padding-left:30px;font-size:12px}.layui-transfer-search .layui-icon-search{position:absolute;left:20px;top:50%;margin-top:-8px;color:#666}.layui-transfer-active{margin:0 15px}.layui-transfer-active .layui-btn{display:block;margin:0;padding:0 15px;background-color:#5FB878;border-color:#5FB878;color:#fff}.layui-transfer-active .layui-btn-disabled{background-color:#FBFBFB;border-color:#eee;color:#d2d2d2}.layui-transfer-active .layui-btn:first-child{margin-bottom:15px}.layui-transfer-active .layui-btn .layui-icon{margin:0;font-size:14px!important}.layui-transfer-data{padding:5px 0;overflow:auto}.layui-transfer-data li{height:32px;line-height:32px;padding:0 10px}.layui-transfer-data li:hover{background-color:#F6F6F6;transition:.5s all}.layui-transfer-data .layui-none{padding:15px 10px;text-align:center;color:#999}.layui-rate,.layui-rate *{display:inline-block;vertical-align:middle}.layui-rate{padding:10px 5px 10px 0;font-size:0}.layui-rate li i.layui-icon{font-size:20px;color:#FFB800;margin-right:5px;transition:all .3s;-webkit-transition:all .3s}.layui-rate li i:hover{cursor:pointer;transform:scale(1.12);-webkit-transform:scale(1.12)}.layui-rate[readonly] li i:hover{cursor:default;transform:scale(1)}.layui-colorpicker{width:26px;height:26px;border:1px solid #eee;padding:5px;border-radius:2px;line-height:24px;display:inline-block;cursor:pointer;transition:all .3s;-webkit-transition:all .3s}.layui-colorpicker:hover{border-color:#d2d2d2}.layui-colorpicker.layui-colorpicker-lg{width:34px;height:34px;line-height:32px}.layui-colorpicker.layui-colorpicker-sm{width:24px;height:24px;line-height:22px}.layui-colorpicker.layui-colorpicker-xs{width:22px;height:22px;line-height:20px}.layui-colorpicker-trigger-bgcolor{display:block;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);border-radius:2px}.layui-colorpicker-trigger-span{display:block;height:100%;box-sizing:border-box;border:1px solid rgba(0,0,0,.15);border-radius:2px;text-align:center}.layui-colorpicker-trigger-i{display:inline-block;color:#FFF;font-size:12px}.layui-colorpicker-trigger-i.layui-icon-close{color:#999}.layui-colorpicker-main{position:absolute;left:-999999px;top:-999999px;z-index:66666666;width:280px;margin:5px 0;padding:7px;background:#FFF;border:1px solid #d2d2d2;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12)}.layui-colorpicker-main-wrapper{height:180px;position:relative}.layui-colorpicker-basis{width:260px;height:100%;position:relative}.layui-colorpicker-basis-white{width:100%;height:100%;position:absolute;top:0;left:0;background:linear-gradient(90deg,#FFF,hsla(0,0%,100%,0))}.layui-colorpicker-basis-black{width:100%;height:100%;position:absolute;top:0;left:0;background:linear-gradient(0deg,#000,transparent)}.layui-colorpicker-basis-cursor{width:10px;height:10px;border:1px solid #FFF;border-radius:50%;position:absolute;top:-3px;right:-3px;cursor:pointer}.layui-colorpicker-side{position:absolute;top:0;right:0;width:12px;height:100%;background:linear-gradient(red,#FF0,#0F0,#0FF,#00F,#F0F,red)}.layui-colorpicker-side-slider{width:100%;height:5px;box-shadow:0 0 1px #888;background:#FFF;border-radius:1px;border:1px solid #f0f0f0;cursor:pointer;position:absolute;left:0}.layui-colorpicker-main-alpha{display:none;height:12px;margin-top:7px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.layui-colorpicker-alpha-bgcolor{height:100%;position:relative}.layui-colorpicker-alpha-slider{width:5px;height:100%;box-shadow:0 0 1px #888;background:#FFF;border-radius:1px;border:1px solid #f0f0f0;cursor:pointer;position:absolute;top:0}.layui-colorpicker-main-pre{padding-top:7px;font-size:0}.layui-colorpicker-pre{width:20px;height:20px;border-radius:2px;display:inline-block;margin-left:6px;margin-bottom:7px;cursor:pointer}.layui-colorpicker-pre:nth-child(11n+1){margin-left:0}.layui-colorpicker-pre-isalpha{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.layui-colorpicker-pre.layui-this{box-shadow:0 0 3px 2px rgba(0,0,0,.15)}.layui-colorpicker-pre>div{height:100%;border-radius:2px}.layui-colorpicker-main-input{text-align:right;padding-top:7px}.layui-colorpicker-main-input .layui-btn-container .layui-btn{margin:0 0 0 10px}.layui-colorpicker-main-input div.layui-inline{float:left;margin-right:10px;font-size:14px}.layui-colorpicker-main-input input.layui-input{width:150px;height:30px;color:#666}.layui-slider{height:4px;background:#eee;border-radius:3px;position:relative;cursor:pointer}.layui-slider-bar{border-radius:3px;position:absolute;height:100%}.layui-slider-step{position:absolute;top:0;width:4px;height:4px;border-radius:50%;background:#FFF;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.layui-slider-wrap{width:36px;height:36px;position:absolute;top:-16px;-webkit-transform:translateX(-50%);transform:translateX(-50%);z-index:10;text-align:center}.layui-slider-wrap-btn{width:12px;height:12px;border-radius:50%;background:#FFF;display:inline-block;vertical-align:middle;cursor:pointer;transition:.3s}.layui-slider-wrap:after{content:"";height:100%;display:inline-block;vertical-align:middle}.layui-slider-wrap-btn.layui-slider-hover,.layui-slider-wrap-btn:hover{transform:scale(1.2)}.layui-slider-wrap-btn.layui-disabled:hover{transform:scale(1)!important}.layui-slider-tips{position:absolute;top:-42px;z-index:66666666;white-space:nowrap;display:none;-webkit-transform:translateX(-50%);transform:translateX(-50%);color:#FFF;background:#000;border-radius:3px;height:25px;line-height:25px;padding:0 10px}.layui-slider-tips:after{content:"";position:absolute;bottom:-12px;left:50%;margin-left:-6px;width:0;height:0;border-width:6px;border-style:solid;border-color:#000 transparent transparent}.layui-slider-input{width:70px;height:32px;border:1px solid #eee;border-radius:3px;font-size:16px;line-height:32px;position:absolute;right:0;top:-14px}.layui-slider-input-btn{position:absolute;top:0;right:0;width:20px;height:100%;border-left:1px solid #eee}.layui-slider-input-btn i{cursor:pointer;position:absolute;right:0;bottom:0;width:20px;height:50%;font-size:12px;line-height:16px;text-align:center;color:#999}.layui-slider-input-btn i:first-child{top:0;border-bottom:1px solid #eee}.layui-slider-input-txt{height:100%;font-size:14px}.layui-slider-input-txt input{height:100%;border:none}.layui-slider-input-btn i:hover{color:#009688}.layui-slider-vertical{width:4px;margin-left:33px}.layui-slider-vertical .layui-slider-bar{width:4px}.layui-slider-vertical .layui-slider-step{top:auto;left:0;-webkit-transform:translateY(50%);transform:translateY(50%)}.layui-slider-vertical .layui-slider-wrap{top:auto;left:-16px;-webkit-transform:translateY(50%);transform:translateY(50%)}.layui-slider-vertical .layui-slider-tips{top:auto;left:2px}@media \0screen{.layui-slider-wrap-btn{margin-left:-20px}.layui-slider-vertical .layui-slider-wrap-btn{margin-left:0;margin-bottom:-20px}.layui-slider-vertical .layui-slider-tips{margin-left:-8px}.layui-slider>span{margin-left:8px}}.layui-tree{line-height:22px}.layui-tree .layui-form-checkbox{margin:0!important}.layui-tree-set{width:100%;position:relative}.layui-tree-pack{display:none;padding-left:20px;position:relative}.layui-tree-iconClick,.layui-tree-main{display:inline-block;vertical-align:middle}.layui-tree-line .layui-tree-pack{padding-left:27px}.layui-tree-line .layui-tree-set .layui-tree-set:after{content:"";position:absolute;top:14px;left:-9px;width:17px;height:0;border-top:1px dotted #c0c4cc}.layui-tree-entry{position:relative;padding:3px 0;height:20px;white-space:nowrap}.layui-tree-entry:hover{background-color:#eee}.layui-tree-line .layui-tree-entry:hover{background-color:rgba(0,0,0,0)}.layui-tree-line .layui-tree-entry:hover .layui-tree-txt{color:#999;text-decoration:underline;transition:.3s}.layui-tree-main{cursor:pointer;padding-right:10px}.layui-tree-line .layui-tree-set:before{content:"";position:absolute;top:0;left:-9px;width:0;height:100%;border-left:1px dotted #c0c4cc}.layui-tree-line .layui-tree-set.layui-tree-setLineShort:before{height:13px}.layui-tree-line .layui-tree-set.layui-tree-setHide:before{height:0}.layui-tree-iconClick{position:relative;height:20px;line-height:20px;margin:0 10px;color:#c0c4cc}.layui-tree-icon{height:12px;line-height:12px;width:12px;text-align:center;border:1px solid #c0c4cc}.layui-tree-iconClick .layui-icon{font-size:18px}.layui-tree-icon .layui-icon{font-size:12px;color:#666}.layui-tree-iconArrow{padding:0 5px}.layui-tree-iconArrow:after{content:"";position:absolute;left:4px;top:3px;z-index:100;width:0;height:0;border-width:5px;border-style:solid;border-color:transparent transparent transparent #c0c4cc;transition:.5s}.layui-tree-btnGroup,.layui-tree-editInput{position:relative;vertical-align:middle;display:inline-block}.layui-tree-spread>.layui-tree-entry>.layui-tree-iconClick>.layui-tree-iconArrow:after{transform:rotate(90deg) translate(3px,4px)}.layui-tree-txt{display:inline-block;vertical-align:middle;color:#555}.layui-tree-search{margin-bottom:15px;color:#666}.layui-tree-btnGroup .layui-icon{display:inline-block;vertical-align:middle;padding:0 2px;cursor:pointer}.layui-tree-btnGroup .layui-icon:hover{color:#999;transition:.3s}.layui-tree-entry:hover .layui-tree-btnGroup{visibility:visible}.layui-tree-editInput{height:20px;line-height:20px;padding:0 3px;border:none;background-color:rgba(0,0,0,.05)}.layui-tree-emptyText{text-align:center;color:#999}.layui-anim{-webkit-animation-duration:.3s;-webkit-animation-fill-mode:both;animation-duration:.3s;animation-fill-mode:both}.layui-anim.layui-icon{display:inline-block}.layui-anim-loop{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.layui-trans,.layui-trans a{transition:all .2s;-webkit-transition:all .2s}@-webkit-keyframes layui-rotate{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(360deg)}}@keyframes layui-rotate{from{transform:rotate(0)}to{transform:rotate(360deg)}}.layui-anim-rotate{-webkit-animation-name:layui-rotate;animation-name:layui-rotate;-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-timing-function:linear;animation-timing-function:linear}@-webkit-keyframes layui-up{from{-webkit-transform:translate3d(0,100%,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-up{from{transform:translate3d(0,100%,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-up{-webkit-animation-name:layui-up;animation-name:layui-up}@-webkit-keyframes layui-upbit{from{-webkit-transform:translate3d(0,15px,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-upbit{from{transform:translate3d(0,15px,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-upbit{-webkit-animation-name:layui-upbit;animation-name:layui-upbit}@keyframes layui-down{0%{opacity:.3;transform:translate3d(0,-100%,0)}100%{opacity:1;transform:translate3d(0,0,0)}}.layui-anim-down{animation-name:layui-down}@keyframes layui-downbit{0%{opacity:.3;transform:translate3d(0,-5px,0)}100%{opacity:1;transform:translate3d(0,0,0)}}.layui-anim-downbit{animation-name:layui-downbit}@-webkit-keyframes layui-scale{0%{opacity:.3;-webkit-transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale{0%{opacity:.3;-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-ms-transform:scale(1);transform:scale(1)}}.layui-anim-scale{-webkit-animation-name:layui-scale;animation-name:layui-scale}@-webkit-keyframes layui-scale-spring{0%{opacity:.5;-webkit-transform:scale(.5)}80%{opacity:.8;-webkit-transform:scale(1.1)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale-spring{0%{opacity:.5;transform:scale(.5)}80%{opacity:.8;transform:scale(1.1)}100%{opacity:1;transform:scale(1)}}.layui-anim-scaleSpring{-webkit-animation-name:layui-scale-spring;animation-name:layui-scale-spring}@keyframes layui-scalesmall{0%{opacity:.3;transform:scale(1.5)}100%{opacity:1;transform:scale(1)}}.layui-anim-scalesmall{animation-name:layui-scalesmall}@keyframes layui-scalesmall-spring{0%{opacity:.3;transform:scale(1.5)}80%{opacity:.8;transform:scale(.9)}100%{opacity:1;transform:scale(1)}}.layui-anim-scalesmall-spring{animation-name:layui-scalesmall-spring}@-webkit-keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}@keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}.layui-anim-fadein{-webkit-animation-name:layui-fadein;animation-name:layui-fadein}@-webkit-keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}@keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}.layui-anim-fadeout{-webkit-animation-name:layui-fadeout;animation-name:layui-fadeout} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/code.css b/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/code.css deleted file mode 100644 index 0fee0c50..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/code.css +++ /dev/null @@ -1 +0,0 @@ -html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-h3,.layui-code-view{position:relative;font-size:12px}.layui-code-view{display:block;margin:10px 0;padding:0;border:1px solid #eee;border-left-width:6px;background-color:#FAFAFA;color:#333;font-family:Courier New}.layui-code-h3{padding:0 10px;height:40px;line-height:40px;border-bottom:1px solid #eee}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 10px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view .layui-code-ol li:first-child{padding-top:10px}.layui-code-view .layui-code-ol li:last-child{padding-bottom:10px}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0C0C0C;border-left-color:#3F3F3F;background-color:#0C0C0C;color:#C2BE9E}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3F3F3F;border-left:none}.layui-code-demo .layui-code{visibility:visible!important;margin:-15px;border-top:none;border-right:none;border-bottom:none}.layui-code-demo .layui-tab-content{padding:15px;border-top:none} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/laydate/default/laydate.css b/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/laydate/default/laydate.css deleted file mode 100644 index c08928b5..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/laydate/default/laydate.css +++ /dev/null @@ -1 +0,0 @@ -.laydate-set-ym,.layui-laydate,.layui-laydate *,.layui-laydate-list{box-sizing:border-box}html #layuicss-laydate{display:none;position:absolute;width:1989px}.layui-laydate *{margin:0;padding:0}.layui-laydate{position:absolute;z-index:66666666;margin:5px 0;border-radius:2px;font-size:14px;-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;animation-name:laydate-downbit}.layui-laydate-main{width:272px}.layui-laydate-content td,.layui-laydate-header *,.layui-laydate-list li{transition-duration:.3s;-webkit-transition-duration:.3s}@keyframes laydate-downbit{0%{opacity:.3;transform:translate3d(0,-5px,0)}100%{opacity:1;transform:translate3d(0,0,0)}}.layui-laydate-static{position:relative;z-index:0;display:inline-block;margin:0;-webkit-animation:none;animation:none}.laydate-ym-show .laydate-next-m,.laydate-ym-show .laydate-prev-m{display:none!important}.laydate-ym-show .laydate-next-y,.laydate-ym-show .laydate-prev-y{display:inline-block!important}.laydate-time-show .laydate-set-ym span[lay-type=month],.laydate-time-show .laydate-set-ym span[lay-type=year],.laydate-time-show .layui-laydate-header .layui-icon,.laydate-ym-show .laydate-set-ym span[lay-type=month]{display:none!important}.layui-laydate-header{position:relative;line-height:30px;padding:10px 70px 5px}.layui-laydate-header *{display:inline-block;vertical-align:bottom}.layui-laydate-header i{position:absolute;top:10px;padding:0 5px;color:#999;font-size:18px;cursor:pointer}.layui-laydate-header i.laydate-prev-y{left:15px}.layui-laydate-header i.laydate-prev-m{left:45px}.layui-laydate-header i.laydate-next-y{right:15px}.layui-laydate-header i.laydate-next-m{right:45px}.laydate-set-ym{width:100%;text-align:center;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.laydate-set-ym span{padding:0 10px;cursor:pointer}.laydate-time-text{cursor:default!important}.layui-laydate-content{position:relative;padding:10px;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-laydate-content table{border-collapse:collapse;border-spacing:0}.layui-laydate-content td,.layui-laydate-content th{width:36px;height:30px;padding:5px;text-align:center}.layui-laydate-content td{position:relative;cursor:pointer}.laydate-day-mark{position:absolute;left:0;top:0;width:100%;line-height:30px;font-size:12px;overflow:hidden}.laydate-day-mark::after{position:absolute;content:'';right:2px;top:2px;width:5px;height:5px;border-radius:50%}.layui-laydate-footer{position:relative;height:46px;line-height:26px;padding:10px}.layui-laydate-footer span{display:inline-block;vertical-align:top;height:26px;line-height:24px;padding:0 10px;border:1px solid #C9C9C9;border-radius:2px;background-color:#fff;font-size:12px;cursor:pointer;white-space:nowrap;transition:all .3s}.layui-laydate-list>li,.layui-laydate-range .layui-laydate-main{display:inline-block;vertical-align:middle}.layui-laydate-footer span:hover{color:#5FB878}.layui-laydate-footer span.layui-laydate-preview{cursor:default;border-color:transparent!important}.layui-laydate-footer span.layui-laydate-preview:hover{color:#666}.layui-laydate-footer span:first-child.layui-laydate-preview{padding-left:0}.laydate-footer-btns{position:absolute;right:10px;top:10px}.laydate-footer-btns span{margin:0 0 0 -1px}.layui-laydate-list{position:absolute;left:0;top:0;width:100%;height:100%;padding:10px;background-color:#fff}.layui-laydate-list>li{position:relative;width:33.3%;height:36px;line-height:36px;margin:3px 0;text-align:center;cursor:pointer}.laydate-month-list>li{width:25%;margin:17px 0}.laydate-time-list>li{height:100%;margin:0;line-height:normal;cursor:default}.laydate-time-list p{position:relative;top:-4px;line-height:29px}.laydate-time-list ol{height:181px;overflow:hidden}.laydate-time-list>li:hover ol{overflow-y:auto}.laydate-time-list ol li{width:130%;padding-left:33px;height:30px;line-height:30px;text-align:left;cursor:pointer}.layui-laydate-hint{position:absolute;top:115px;left:50%;width:250px;margin-left:-125px;line-height:20px;padding:15px;text-align:center;font-size:12px}.layui-laydate-range{width:546px}.layui-laydate-range .laydate-main-list-1 .layui-laydate-content,.layui-laydate-range .laydate-main-list-1 .layui-laydate-header{border-left:1px solid #e2e2e2}.layui-laydate,.layui-laydate-hint{border:1px solid #d2d2d2;box-shadow:0 2px 4px rgba(0,0,0,.12);background-color:#fff;color:#666}.layui-laydate-header{border-bottom:1px solid #e2e2e2}.layui-laydate-header i:hover,.layui-laydate-header span:hover{color:#5FB878}.layui-laydate-content{border-top:none 0;border-bottom:none 0}.layui-laydate-content th{font-weight:400;color:#333}.layui-laydate-content td{color:#666}.layui-laydate-content td.laydate-selected{background-color:#B5FFF8}.laydate-selected:hover{background-color:#00F7DE!important}.layui-laydate-content td:hover,.layui-laydate-list li:hover{background-color:#eee;color:#333}.laydate-time-list li ol{margin:0;padding:0;border:1px solid #e2e2e2;border-left-width:0}.laydate-time-list li:first-child ol{border-left-width:1px}.laydate-time-list>li:hover{background:0 0}.layui-laydate-content .laydate-day-next,.layui-laydate-content .laydate-day-prev{color:#d2d2d2}.laydate-selected.laydate-day-next,.laydate-selected.laydate-day-prev{background-color:#f8f8f8!important}.layui-laydate-footer{border-top:1px solid #e2e2e2}.layui-laydate-hint{color:#FF5722}.laydate-day-mark::after{background-color:#5FB878}.layui-laydate-content td.layui-this .laydate-day-mark::after{display:none}.layui-laydate-footer span[lay-type=date]{color:#5FB878}.layui-laydate .layui-this{background-color:#009688!important;color:#fff!important}.layui-laydate .laydate-disabled,.layui-laydate .laydate-disabled:hover{background:0 0!important;color:#d2d2d2!important;cursor:not-allowed!important;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.laydate-theme-molv{border:none}.laydate-theme-molv.layui-laydate-range{width:548px}.laydate-theme-molv .layui-laydate-main{width:274px}.laydate-theme-molv .layui-laydate-header{border:none;background-color:#009688}.laydate-theme-molv .layui-laydate-header i,.laydate-theme-molv .layui-laydate-header span{color:#f6f6f6}.laydate-theme-molv .layui-laydate-header i:hover,.laydate-theme-molv .layui-laydate-header span:hover{color:#fff}.laydate-theme-molv .layui-laydate-content{border:1px solid #e2e2e2;border-top:none;border-bottom:none}.laydate-theme-molv .laydate-main-list-1 .layui-laydate-content{border-left:none}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li,.laydate-theme-grid .layui-laydate-content td,.laydate-theme-grid .layui-laydate-content thead,.laydate-theme-molv .layui-laydate-footer{border:1px solid #e2e2e2}.laydate-theme-grid .laydate-selected,.laydate-theme-grid .laydate-selected:hover{background-color:#f2f2f2!important;color:#009688!important}.laydate-theme-grid .laydate-selected.laydate-day-next,.laydate-theme-grid .laydate-selected.laydate-day-prev{color:#d2d2d2!important}.laydate-theme-grid .laydate-month-list,.laydate-theme-grid .laydate-year-list{margin:1px 0 0 1px}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li{margin:0 -1px -1px 0}.laydate-theme-grid .laydate-year-list>li{height:43px;line-height:43px}.laydate-theme-grid .laydate-month-list>li{height:71px;line-height:71px} \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/icon-ext.png b/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/icon-ext.png deleted file mode 100644 index bbbb669bb311514baa5db3a6a00b4644d0e280f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5911 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 bWW^%>x7XlHV^#Q1uOX^B?ki3(VEg|7!QHuF diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/loading-1.gif b/iot-server/server-starter/src/main/webapp/assets/zeus/layui/css/modules/layer/default/loading-1.gif deleted file mode 100644 index db3a483e4b74971fbfb1cc0fb6499852cedfe650..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 701 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 NqtXTTr(IH0bTL$Q#&Rt$( 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 WEo6sg2$g9lKpdZ$$_>);_x}MD5#CJz diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.svg b/iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.svg deleted file mode 100644 index 999ca1fe..00000000 --- a/iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.svg +++ /dev/null @@ -1,554 +0,0 @@ - - - - - -Created by iconfont - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.ttf b/iot-server/server-starter/src/main/webapp/assets/zeus/layui/font/iconfont.ttf deleted file mode 100644 index 06e30f9e2a856cbfefff25111ceb4b9c034f35fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46508 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
                                            _X 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"interactive"===n[o].readyState){t=n[o].src;break}return t||n[r].src}();return n.dir=o.dir||t.substring(0,t.lastIndexOf("/")+1)}(),i=function(e,n){n=n||"log",t.console&&console[n]&&console[n]("layui error hint: "+e)},u="undefined"!=typeof opera&&"[object Opera]"===opera.toString(),l=n.builtin={lay:"lay",layer:"layer",laydate:"laydate",laypage:"laypage",laytpl:"laytpl",layedit:"layedit",form:"form",upload:"upload",dropdown:"dropdown",transfer:"transfer",tree:"tree",table:"table",element:"element",rate:"rate",colorpicker:"colorpicker",slider:"slider",carousel:"carousel",flow:"flow",util:"util",code:"code",jquery:"jquery",all:"all","layui.all":"layui.all"};r.prototype.cache=n,r.prototype.define=function(t,e){var r=this,o="function"==typeof t,a=function(){var t=function(t,e){layui[t]=e,n.status[t]=!0};return"function"==typeof e&&e(function(r,o){t(r,o),n.callback[r]=function(){e(t)}}),this};return o&&(e=t,t=[]),r.use(t,a,null,"define"),r},r.prototype.use=function(r,o,c,s){function p(t,e){var r="PLaySTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/;("load"===t.type||r.test((t.currentTarget||t.srcElement).readyState))&&(n.modules[h]=e,v.removeChild(b),function o(){return++m>1e3*n.timeout/4?i(h+" is not a valid module","error"):void(n.status[h]?f():setTimeout(o,4))}())}function f(){c.push(layui[h]),r.length>1?y.use(r.slice(1),o,c,s):"function"==typeof o&&function(){return layui.jquery&&"function"==typeof layui.jquery&&"define"!==s?layui.jquery(function(){o.apply(layui,c)}):void o.apply(layui,c)}()}var y=this,d=n.dir=n.dir?n.dir:a,v=e.getElementsByTagName("head")[0];r=function(){return"string"==typeof r?[r]:"function"==typeof r?(o=r,["all"]):r}(),t.jQuery&&jQuery.fn.on&&(y.each(r,function(t,e){"jquery"===e&&r.splice(t,1)}),layui.jquery=layui.$=jQuery);var h=r[0],m=0;if(c=c||[],n.host=n.host||(d.match(/\/\/([\s\S]+?)\//)||["//"+location.host+"/"])[0],0===r.length||layui["layui.all"]&&l[h])return f(),y;var g=(l[h]?d+"modules/":/^\{\/\}/.test(y.modules[h])?"":n.base||"")+(y.modules[h]||h)+".js";if(g=g.replace(/^\{\/\}/,""),!n.modules[h]&&layui[h]&&(n.modules[h]=g),n.modules[h])!function S(){return++m>1e3*n.timeout/4?i(h+" is not a valid module","error"):void("string"==typeof n.modules[h]&&n.status[h]?f():setTimeout(S,4))}();else{var b=e.createElement("script");b.async=!0,b.charset="utf-8",b.src=g+function(){var t=n.version===!0?n.v||(new Date).getTime():n.version||"";return t?"?v="+t:""}(),v.appendChild(b),!b.attachEvent||b.attachEvent.toString&&b.attachEvent.toString().indexOf("[native code")<0||u?b.addEventListener("load",function(t){p(t,g)},!1):b.attachEvent("onreadystatechange",function(t){p(t,g)}),n.modules[h]=g}return y},r.prototype.getStyle=function(e,n){var r=e.currentStyle?e.currentStyle:t.getComputedStyle(e,null);return r[r.getPropertyValue?"getPropertyValue":"getAttribute"](n)},r.prototype.link=function(t,r,o){var a=this,u=e.getElementsByTagName("head")[0],l=e.createElement("link");"string"==typeof r&&(o=r);var c=(o||t).replace(/\.|\//g,""),s=l.id="layuicss-"+c,p="creating",f=0;return l.rel="stylesheet",l.href=t+(n.debug?"?v="+(new Date).getTime():""),l.media="all",e.getElementById(s)||u.appendChild(l),"function"!=typeof r?a:(function y(o){var u=100,l=e.getElementById(s);return++f>1e3*n.timeout/u?i(t+" timeout"):void(1989===parseInt(a.getStyle(l,"width"))?(o===p&&l.removeAttribute("lay-status"),l.getAttribute("lay-status")===p?setTimeout(y,u):r()):(l.setAttribute("lay-status",p),setTimeout(function(){y(p)},u)))}(),a)},r.prototype.addcss=function(t,e,r){return layui.link(n.dir+"css/"+t,e,r)},n.callback={},r.prototype.factory=function(t){if(layui[t])return"function"==typeof n.callback[t]?n.callback[t]:null},r.prototype.img=function(t,e,n){var r=new Image;return r.src=t,r.complete?e(r):(r.onload=function(){r.onload=null,"function"==typeof e&&e(r)},void(r.onerror=function(t){r.onerror=null,"function"==typeof n&&n(t)}))},r.prototype.config=function(t){t=t||{};for(var e in t)n[e]=t[e];return this},r.prototype.modules=function(){var t={};for(var e in l)t[e]=l[e];return t}(),r.prototype.extend=function(t){var e=this;t=t||{};for(var n in t)e[n]||e.modules[n]?i(n+" Module already exists","error"):e.modules[n]=t[n];return e},r.prototype.router=function(t){var e=this,t=t||location.hash,n={path:[],search:{},hash:(t.match(/[^#](#.*$)/)||[])[1]||""};return/^#\//.test(t)?(t=t.replace(/^#\//,""),n.href="/"+t,t=t.replace(/([^#])(#.*$)/,"$1").split("/")||[],e.each(t,function(t,e){/^\w+=/.test(e)?function(){e=e.split("="),n.search[e[0]]=e[1]}():n.path.push(e)}),n):n},r.prototype.url=function(t){var e=this,n={pathname:function(){var e=t?function(){var e=(t.match(/\.[^.]+?\/.+/)||[])[0]||"";return e.replace(/^[^\/]+/,"").replace(/\?.+/,"")}():location.pathname;return e.replace(/^\//,"").split("/")}(),search:function(){var n={},r=(t?function(){var e=(t.match(/\?.+/)||[])[0]||"";return e.replace(/\#.+/,"")}():location.search).replace(/^\?+/,"").split("&");return e.each(r,function(t,e){var r=e.indexOf("="),o=function(){return r<0?e.substr(0,e.length):0!==r&&e.substr(0,r)}();o&&(n[o]=r>0?e.substr(r+1):null)}),n}(),hash:e.router(function(){return t?(t.match(/#.+/)||[])[0]||"/":location.hash}())};return n},r.prototype.data=function(e,n,r){if(e=e||"layui",r=r||localStorage,t.JSON&&t.JSON.parse){if(null===n)return delete r[e];n="object"==typeof n?n:{key:n};try{var o=JSON.parse(r[e])}catch(a){var o={}}return"value"in n&&(o[n.key]=n.value),n.remove&&delete o[n.key],r[e]=JSON.stringify(o),n.key?o[n.key]:o}},r.prototype.sessionData=function(t,e){return this.data(t,e,sessionStorage)},r.prototype.device=function(e){var n=navigator.userAgent.toLowerCase(),r=function(t){var e=new RegExp(t+"/([^\\s\\_\\-]+)");return t=(n.match(e)||[])[1],t||!1},o={os:function(){return/windows/.test(n)?"windows":/linux/.test(n)?"linux":/iphone|ipod|ipad|ios/.test(n)?"ios":/mac/.test(n)?"mac":void 0}(),ie:function(){return!!(t.ActiveXObject||"ActiveXObject"in t)&&((n.match(/msie\s(\d+)/)||[])[1]||"11")}(),weixin:r("micromessenger")};return e&&!o[e]&&(o[e]=r(e)),o.android=/android/.test(n),o.ios="ios"===o.os,o.mobile=!(!o.android&&!o.ios),o},r.prototype.hint=function(){return{error:i}},r.prototype._typeof=function(t){return null===t?String(t):"object"==typeof t||"function"==typeof t?function(){var e=Object.prototype.toString.call(t).match(/\s(.+)\]$/)||[],n="Function|Array|Date|RegExp|Object|Error|Symbol";return e=e[1]||"Object",new RegExp("\\b("+n+")\\b").test(e)?e.toLowerCase():"object"}():typeof t},r.prototype._isArray=function(e){var n,r=this,o=r._typeof(e);return!(!e||"object"!=typeof e||e===t)&&(n="length"in e&&e.length,"array"===o||0===n||"number"==typeof n&&n>0&&n-1 in e)},r.prototype.each=function(t,e){var n,r=this,o=function(t,n){return e.call(n[t],t,n[t])};if("function"!=typeof e)return r;if(t=t||[],r._isArray(t))for(n=0;no?1:r(t.innerHeight||n.documentElement.clientHeight)},r.style=function(t){t=t||{};var e=r.elem("style"),n=t.text||"",i=t.target||r("body")[0];if(n){"styleSheet"in e?(e.setAttribute("type","text/css"),e.styleSheet.cssText=n):e.innerHTML=n,r.style.index=r.style.index||0,r.style.index++;var o=e.id="LAY-STYLE-"+(t.id||"DF-"+r.style.index),c=r(i).find("#"+o);c[0]&&c.remove(),r(i).append(e)}},r.position=function(e,i,o){if(i){o=o||{},e!==n&&e!==r("body")[0]||(o.clickType="right");var c="right"===o.clickType?function(){var e=o.e||t.event||{};return{left:e.clientX,top:e.clientY,right:e.clientX,bottom:e.clientY}}():e.getBoundingClientRect(),u=i.offsetWidth,a=i.offsetHeight,s=function(t){return t=t?"scrollLeft":"scrollTop",n.body[t]|n.documentElement[t]},l=function(t){return n.documentElement[t?"clientWidth":"clientHeight"]},f=5,h=c.left,p=c.bottom;"center"===o.align?h-=(u-e.offsetWidth)/2:"right"===o.align&&(h=h-u+e.offsetWidth),h+u+f>l("width")&&(h=l("width")-u-f),hl()&&(c.top>a+f?p=c.top-a-2*f:"right"===o.clickType&&(p=l()-a-2*f,p<0&&(p=0)));var y=o.position;if(y&&(i.style.position=y),i.style.left=h+("fixed"===y?0:s(1))+"px",i.style.top=p+("fixed"===y?0:s())+"px",!r.hasScrollbar()){var d=i.getBoundingClientRect();!o.SYSTEM_RELOAD&&d.bottom+f>l()&&(o.SYSTEM_RELOAD=!0,setTimeout(function(){r.position(e,i,o)},50))}}},r.options=function(t,e){var n=r(t),i=e||"lay-options";try{return new Function("return "+(n.attr(i)||"{}"))()}catch(o){return hint.error("parseerror\uff1a"+o,"error"),{}}},r.isTopElem=function(t){var e=[n,r("body")[0]],i=!1;return r.each(e,function(e,n){if(n===t)return i=!0}),i},i.addStr=function(t,e){return t=t.replace(/\s+/," "),e=e.replace(/\s+/," ").split(" "),r.each(e,function(e,n){new RegExp("\\b"+n+"\\b").test(t)||(t=t+" "+n)}),t.replace(/^\s|\s$/,"")},i.removeStr=function(t,e){return t=t.replace(/\s+/," "),e=e.replace(/\s+/," ").split(" "),r.each(e,function(e,n){var r=new RegExp("\\b"+n+"\\b");r.test(t)&&(t=t.replace(r,""))}),t.replace(/\s+/," ").replace(/^\s|\s$/,"")},i.prototype.find=function(t){var e=this,n=0,i=[],o="object"==typeof t;return this.each(function(r,c){for(var u=o?c.contains(t):c.querySelectorAll(t||null);n0)return n[0].style[t]}():n.each(function(n,o){"object"==typeof t?r.each(t,function(t,e){o.style[t]=i(e)}):o.style[t]=i(e)})},i.prototype.width=function(t){var e=this;return void 0===t?function(){if(e.length>0)return e[0].offsetWidth}():e.each(function(n,r){e.css("width",t)})},i.prototype.height=function(t){var e=this;return void 0===t?function(){if(e.length>0)return e[0].offsetHeight}():e.each(function(n,r){e.css("height",t)})},i.prototype.attr=function(t,e){var n=this;return void 0===e?function(){if(n.length>0)return n[0].getAttribute(t)}():n.each(function(n,r){r.setAttribute(t,e)})},i.prototype.removeAttr=function(t){return this.each(function(e,n){n.removeAttribute(t)})},i.prototype.html=function(t){var e=this;return void 0===t?function(){if(e.length>0)return e[0].innerHTML}():this.each(function(e,n){n.innerHTML=t})},i.prototype.val=function(t){var e=this;return void 0===t?function(){if(e.length>0)return e[0].value}():this.each(function(e,n){n.value=t})},i.prototype.append=function(t){return this.each(function(e,n){"object"==typeof t?n.appendChild(t):n.innerHTML=n.innerHTML+t})},i.prototype.remove=function(t){return this.each(function(e,n){t?n.removeChild(t):n.parentNode.removeChild(n)})},i.prototype.on=function(t,e){return this.each(function(n,r){r.attachEvent?r.attachEvent("on"+t,function(t){t.target=t.srcElement,e.call(r,t)}):r.addEventListener(t,e,!1)})},i.prototype.off=function(t,e){return this.each(function(n,r){r.detachEvent?r.detachEvent("on"+t,e):r.removeEventListener(t,e,!1)})},t.lay=r,t.layui&&layui.define&&layui.define(function(t){t(e,r)})}(window,window.document);layui.define(function(e){"use strict";var r={open:"{{",close:"}}"},c={exp:function(e){return new RegExp(e,"g")},query:function(e,c,t){var o=["#([\\s\\S])+?","([^{#}])*?"][e||0];return n((c||"")+r.open+o+r.close+(t||""))},escape:function(e){return String(e||"").replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,""")},error:function(e,r){var c="Laytpl Error: ";return"object"==typeof console&&console.error(c+e+"\n"+(r||"")),c+e}},n=c.exp,t=function(e){this.tpl=e};t.pt=t.prototype,window.errors=0,t.pt.parse=function(e,t){var o=this,p=e,a=n("^"+r.open+"#",""),l=n(r.close+"$","");e=e.replace(/\s+|\r|\t|\n/g," ").replace(n(r.open+"#"),r.open+"# ").replace(n(r.close+"}"),"} "+r.close).replace(/\\/g,"\\\\").replace(n(r.open+"!(.+?)!"+r.close),function(e){return e=e.replace(n("^"+r.open+"!"),"").replace(n("!"+r.close),"").replace(n(r.open+"|"+r.close),function(e){return e.replace(/(.)/g,"\\$1")})}).replace(/(?="|')/g,"\\").replace(c.query(),function(e){return e=e.replace(a,"").replace(l,""),'";'+e.replace(/\\(.)/g,"$1")+';view+="'}).replace(c.query(1),function(e){var c='"+(';return e.replace(/\s/g,"")===r.open+r.close?"":(e=e.replace(n(r.open+"|"+r.close),""),/^=/.test(e)&&(e=e.replace(/^=/,""),c='"+_escape_('),c+e.replace(/\\(.)/g,"$1")+')+"')}),e='"use strict";var view = "'+e+'";return view;';try{return o.cache=e=new Function("d, _escape_",e),e(t,c.escape)}catch(u){return delete o.cache,c.error(u,p)}},t.pt.render=function(e,r){var n,t=this;return e?(n=t.cache?t.cache(e,c.escape):t.parse(t.tpl,e),r?void r(n):n):c.error("no data")};var o=function(e){return"string"!=typeof e?c.error("Template not found"):new t(e)};o.config=function(e){e=e||{};for(var c in e)r[c]=e[c]},o.v="1.2.0",e("laytpl",o)});layui.define(function(e){"use strict";var a=document,t="getElementById",n="getElementsByTagName",i="laypage",r="layui-disabled",u=function(e){var a=this;a.config=e||{},a.config.index=++s.index,a.render(!0)};u.prototype.type=function(){var e=this.config;if("object"==typeof e.elem)return void 0===e.elem.length?2:3},u.prototype.view=function(){var e=this,a=e.config,t=a.groups="groups"in a?0|a.groups:5;a.layout="object"==typeof a.layout?a.layout:["prev","page","next"],a.count=0|a.count,a.curr=0|a.curr||1,a.limits="object"==typeof a.limits?a.limits:[10,20,30,40,50],a.limit=0|a.limit||10,a.pages=Math.ceil(a.count/a.limit)||1,a.curr>a.pages&&(a.curr=a.pages),t<0?t=1:t>a.pages&&(t=a.pages),a.prev="prev"in a?a.prev:"上一页",a.next="next"in a?a.next:"下一页";var n=a.pages>t?Math.ceil((a.curr+(t>1?1:0))/(t>0?t:1)):1,i={prev:function(){return a.prev?''+a.prev+"":""}(),page:function(){var e=[];if(a.count<1)return"";n>1&&a.first!==!1&&0!==t&&e.push(''+(a.first||1)+"");var i=Math.floor((t-1)/2),r=n>1?a.curr-i:1,u=n>1?function(){var e=a.curr+(t-i-1);return e>a.pages?a.pages:e}():t;for(u-r2&&e.push('');r<=u;r++)r===a.curr?e.push('"+r+""):e.push(''+r+"");return a.pages>t&&a.pages>u&&a.last!==!1&&(u+1…'),0!==t&&e.push(''+(a.last||a.pages)+"")),e.join("")}(),next:function(){return a.next?''+a.next+"":""}(),count:'\u5171 '+a.count+" \u6761",limit:function(){var e=['"}(),refresh:['','',""].join(""),skip:function(){return['到第','','页',""].join("")}()};return['
                                            ',function(){var e=[];return layui.each(a.layout,function(a,t){i[t]&&e.push(i[t])}),e.join("")}(),"
                                            "].join("")},u.prototype.jump=function(e,a){if(e){var t=this,i=t.config,r=e.children,u=e[n]("button")[0],l=e[n]("input")[0],p=e[n]("select")[0],c=function(){var e=0|l.value.replace(/\s|\D/g,"");e&&(i.curr=e,t.render())};if(a)return c();for(var o=0,y=r.length;oi.pages||(i.curr=e,t.render())});p&&s.on(p,"change",function(){var e=this.value;i.curr*e>i.count&&(i.curr=Math.ceil(i.count/e)),i.limit=e,t.render()}),u&&s.on(u,"click",function(){c()})}},u.prototype.skip=function(e){if(e){var a=this,t=e[n]("input")[0];t&&s.on(t,"keyup",function(t){var n=this.value,i=t.keyCode;/^(37|38|39|40)$/.test(i)||(/\D/.test(n)&&(this.value=n.replace(/\D/,"")),13===i&&a.jump(e,!0))})}},u.prototype.render=function(e){var n=this,i=n.config,r=n.type(),u=n.view();2===r?i.elem&&(i.elem.innerHTML=u):3===r?i.elem.html(u):a[t](i.elem)&&(a[t](i.elem).innerHTML=u),i.jump&&i.jump(i,e);var s=a[t]("layui-laypage-"+i.index);n.jump(s),i.hash&&!e&&(location.hash="!"+i.hash+"="+i.curr),n.skip(s)};var s={render:function(e){var a=new u(e);return a.index},index:layui.laypage?layui.laypage.index+1e4:0,on:function(e,a,t){return e.attachEvent?e.attachEvent("on"+a,function(a){a.target=a.srcElement,t.call(e,a)}):e.addEventListener(a,t,!1),this}};e(i,s)});!function(e,t){"use strict";var a=e.layui&&layui.define,n={getPath:e.lay&&lay.getPath?lay.getPath:"",link:function(t,a,n){l.path&&e.lay&&lay.layui&&lay.layui.link(l.path+t,a,n)}},i=e.LAYUI_GLOBAL||{},l={v:"5.3.1",config:{},index:e.laydate&&e.laydate.v?1e5:0,path:i.laydate_dir||n.getPath,set:function(e){var t=this;return t.config=lay.extend({},t.config,e),t},ready:function(e){var t="laydate",i="",r=(a?"modules/laydate/":"theme/")+"default/laydate.css?v="+l.v+i;return a?layui.addcss(r,e,t):n.link(r,e,t),this}},r=function(){var e=this,t=e.config,a=t.id;return r.that[a]=e,{hint:function(t){e.hint.call(e,t)},config:e.config}},o="laydate",s=".layui-laydate",y="layui-this",d="laydate-disabled",m=[100,2e5],c="layui-laydate-static",u="layui-laydate-list",h="layui-laydate-hint",f="layui-laydate-footer",p=".laydate-btns-confirm",g="laydate-time-text",v="laydate-btns-time",T="layui-laydate-preview",D=function(e){var t=this;t.index=++l.index,t.config=lay.extend({},t.config,l.config,e),e=t.config,e.id="id"in e?e.id:t.index,l.ready(function(){t.init()})},w="yyyy|y|MM|M|dd|d|HH|H|mm|m|ss|s";r.formatArr=function(e){return(e||"").match(new RegExp(w+"|.","g"))||[]},D.isLeapYear=function(e){return e%4===0&&e%100!==0||e%400===0},D.prototype.config={type:"date",range:!1,format:"yyyy-MM-dd",value:null,isInitValue:!0,min:"1900-1-1",max:"2099-12-31",trigger:"click",show:!1,showBottom:!0,isPreview:!0,btns:["clear","now","confirm"],lang:"cn",theme:"default",position:null,calendar:!1,mark:{},zIndex:null,done:null,change:null},D.prototype.lang=function(){var e=this,t=e.config,a={cn:{weeks:["\u65e5","\u4e00","\u4e8c","\u4e09","\u56db","\u4e94","\u516d"],time:["\u65f6","\u5206","\u79d2"],timeTips:"\u9009\u62e9\u65f6\u95f4",startTime:"\u5f00\u59cb\u65f6\u95f4",endTime:"\u7ed3\u675f\u65f6\u95f4",dateTips:"\u8fd4\u56de\u65e5\u671f",month:["\u4e00","\u4e8c","\u4e09","\u56db","\u4e94","\u516d","\u4e03","\u516b","\u4e5d","\u5341","\u5341\u4e00","\u5341\u4e8c"],tools:{confirm:"\u786e\u5b9a",clear:"\u6e05\u7a7a",now:"\u73b0\u5728"},timeout:"\u7ed3\u675f\u65f6\u95f4\u4e0d\u80fd\u65e9\u4e8e\u5f00\u59cb\u65f6\u95f4
                                            \u8bf7\u91cd\u65b0\u9009\u62e9",invalidDate:"\u4e0d\u5728\u6709\u6548\u65e5\u671f\u6216\u65f6\u95f4\u8303\u56f4\u5185",formatError:["\u65e5\u671f\u683c\u5f0f\u4e0d\u5408\u6cd5
                                            \u5fc5\u987b\u9075\u5faa\u4e0b\u8ff0\u683c\u5f0f\uff1a
                                            ","
                                            \u5df2\u4e3a\u4f60\u91cd\u7f6e"],preview:"\u5f53\u524d\u9009\u4e2d\u7684\u7ed3\u679c"},en:{weeks:["Su","Mo","Tu","We","Th","Fr","Sa"],time:["Hours","Minutes","Seconds"],timeTips:"Select Time",startTime:"Start Time",endTime:"End Time",dateTips:"Select Date",month:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],tools:{confirm:"Confirm",clear:"Clear",now:"Now"},timeout:"End time cannot be less than start Time
                                            Please re-select",invalidDate:"Invalid date",formatError:["The date format error
                                            Must be followed\uff1a
                                            ","
                                            It has been reset"],preview:"The selected result"}};return a[t.lang]||a.cn},D.prototype.init=function(){var t=this,a=t.config,n="static"===a.position,i={year:"yyyy",month:"yyyy-MM",date:"yyyy-MM-dd",time:"HH:mm:ss",datetime:"yyyy-MM-dd HH:mm:ss"};a.elem=lay(a.elem),a.eventElem=lay(a.eventElem),a.elem[0]&&(t.rangeStr=a.range?"string"==typeof a.range?a.range:"-":"","array"===layui._typeof(a.range)&&(t.rangeElem=[lay(a.range[0]),lay(a.range[1])]),i[a.type]||(e.console&&console.error&&console.error("laydate type error:'"+a.type+"' is not supported"),a.type="date"),a.format===i.date&&(a.format=i[a.type]||i.date),t.format=r.formatArr(a.format),t.EXP_IF="",t.EXP_SPLIT="",lay.each(t.format,function(e,a){var n=new RegExp(w).test(a)?"\\d{"+function(){return new RegExp(w).test(t.format[0===e?e+1:e-1]||"")?/^yyyy|y$/.test(a)?4:a.length:/^yyyy$/.test(a)?"1,4":/^y$/.test(a)?"1,308":"1,2"}()+"}":"\\"+a;t.EXP_IF=t.EXP_IF+n,t.EXP_SPLIT=t.EXP_SPLIT+"("+n+")"}),t.EXP_IF_ONE=new RegExp("^"+t.EXP_IF+"$"),t.EXP_IF=new RegExp("^"+(a.range?t.EXP_IF+"\\s\\"+t.rangeStr+"\\s"+t.EXP_IF:t.EXP_IF)+"$"),t.EXP_SPLIT=new RegExp("^"+t.EXP_SPLIT+"$",""),t.isInput(a.elem[0])||"focus"===a.trigger&&(a.trigger="click"),a.elem.attr("lay-key")||(a.elem.attr("lay-key",t.index),a.eventElem.attr("lay-key",t.index)),a.mark=lay.extend({},a.calendar&&"cn"===a.lang?{"0-1-1":"\u5143\u65e6","0-2-14":"\u60c5\u4eba","0-3-8":"\u5987\u5973","0-3-12":"\u690d\u6811","0-4-1":"\u611a\u4eba","0-5-1":"\u52b3\u52a8","0-5-4":"\u9752\u5e74","0-6-1":"\u513f\u7ae5","0-9-10":"\u6559\u5e08","0-9-18":"\u56fd\u803b","0-10-1":"\u56fd\u5e86","0-12-25":"\u5723\u8bde"}:{},a.mark),lay.each(["min","max"],function(e,t){var n=[],i=[];if("number"==typeof a[t]){var l=a[t],r=(new Date).getTime(),o=864e5,s=new Date(l?l0)return!0;var t=lay.elem("div",{"class":"layui-laydate-header"}),i=[function(){var e=lay.elem("i",{"class":"layui-icon laydate-icon laydate-prev-y"});return e.innerHTML="",e}(),function(){var e=lay.elem("i",{"class":"layui-icon laydate-icon laydate-prev-m"});return e.innerHTML="",e}(),function(){var e=lay.elem("div",{"class":"laydate-set-ym"}),t=lay.elem("span"),a=lay.elem("span");return e.appendChild(t),e.appendChild(a),e}(),function(){var e=lay.elem("i",{"class":"layui-icon laydate-icon laydate-next-m"});return e.innerHTML="",e}(),function(){var e=lay.elem("i",{"class":"layui-icon laydate-icon laydate-next-y"});return e.innerHTML="",e}()],l=lay.elem("div",{"class":"layui-laydate-content"}),r=lay.elem("table"),m=lay.elem("thead"),c=lay.elem("tr");lay.each(i,function(e,a){t.appendChild(a)}),m.appendChild(c),lay.each(new Array(6),function(e){var t=r.insertRow(0);lay.each(new Array(7),function(a){if(0===e){var i=lay.elem("th");i.innerHTML=n.weeks[a],c.appendChild(i)}t.insertCell(a)})}),r.insertBefore(m,r.children[0]),l.appendChild(r),o[e]=lay.elem("div",{"class":"layui-laydate-main laydate-main-list-"+e}),o[e].appendChild(t),o[e].appendChild(l),s.push(i),y.push(l),d.push(r)}),lay(m).html(function(){var e=[],t=[];return"datetime"===a.type&&e.push(''+n.timeTips+""),(a.range||"datetime"!==a.type)&&e.push(''),lay.each(a.btns,function(e,l){var r=n.tools[l]||"btn";a.range&&"now"===l||(i&&"clear"===l&&(r="cn"===a.lang?"\u91cd\u7f6e":"Reset"),t.push(''+r+""))}),e.push('"),e.join("")}()),lay.each(o,function(e,t){r.appendChild(t)}),a.showBottom&&r.appendChild(m),/^#/.test(a.theme)){var u=lay.elem("style"),h=["#{{id}} .layui-laydate-header{background-color:{{theme}};}","#{{id}} .layui-this{background-color:{{theme}} !important;}"].join("").replace(/{{id}}/g,e.elemID).replace(/{{theme}}/g,a.theme);"styleSheet"in u?(u.setAttribute("type","text/css"),u.styleSheet.cssText=h):u.innerHTML=h,lay(r).addClass("laydate-theme-molv"),r.appendChild(u)}l.thisId=a.id,e.remove(D.thisElemDate),i?a.elem.append(r):(t.body.appendChild(r),e.position()),e.checkDate().calendar(null,0,"init"),e.changeEvent(),D.thisElemDate=e.elemID,"function"==typeof a.ready&&a.ready(lay.extend({},a.dateTime,{month:a.dateTime.month+1})),e.preview()},D.prototype.remove=function(e){var t=this,a=(t.config,lay("#"+(e||t.elemID)));return a[0]?(a.hasClass(c)||t.checkDate(function(){a.remove()}),t):t},D.prototype.position=function(){var e=this,t=e.config;return lay.position(e.bindElem||t.elem[0],e.elem,{position:t.position}),e},D.prototype.hint=function(e){var t=this,a=(t.config,lay.elem("div",{"class":h}));t.elem&&(a.innerHTML=e||"",lay(t.elem).find("."+h).remove(),t.elem.appendChild(a),clearTimeout(t.hinTimer),t.hinTimer=setTimeout(function(){lay(t.elem).find("."+h).remove()},3e3))},D.prototype.getAsYM=function(e,t,a){return a?t--:t++,t<0&&(t=11,e--),t>11&&(t=0,e++),[e,t]},D.prototype.systemDate=function(e){var t=e||new Date;return{year:t.getFullYear(),month:t.getMonth(),date:t.getDate(),hours:e?e.getHours():0,minutes:e?e.getMinutes():0,seconds:e?e.getSeconds():0}},D.prototype.checkDate=function(e){var t,a,n=this,i=(new Date,n.config),r=n.lang(),o=i.dateTime=i.dateTime||n.systemDate(),s=n.bindElem||i.elem[0],y=(n.isInput(s)?"val":"html",function(){if(n.rangeElem){var e=[n.rangeElem[0].val(),n.rangeElem[1].val()];if(e[0]&&e[1])return e.join(" "+n.rangeStr+" ")}return n.isInput(s)?s.value:"static"===i.position?"":lay(s).attr("lay-date")}()),d=function(e){e.year>m[1]&&(e.year=m[1],a=!0),e.month>11&&(e.month=11,a=!0),e.hours>23&&(e.hours=0,a=!0),e.minutes>59&&(e.minutes=0,e.hours++,a=!0),e.seconds>59&&(e.seconds=0,e.minutes++,a=!0),t=l.getEndDate(e.month+1,e.year),e.date>t&&(e.date=t,a=!0)},c=function(e,t,l){var r=["startTime","endTime"];t=(t.match(n.EXP_SPLIT)||[]).slice(1),l=l||0,i.range&&(n[r[l]]=n[r[l]]||{}),lay.each(n.format,function(o,s){var y=parseFloat(t[o]);t[o].lengthh(i.max)||h(o)h(i.max))&&(n.endDate=lay.extend({},i.max)),e&&e(),n},D.prototype.mark=function(e,t){var a,n=this,i=n.config;return lay.each(i.mark,function(e,n){var i=e.split("-");i[0]!=t[0]&&0!=i[0]||i[1]!=t[1]&&0!=i[1]||i[2]!=t[2]||(a=n||t[2])}),a&&e.html(''+a+""),n},D.prototype.limit=function(e,t,a,n){var i,l=this,r=l.config,o={},s=r[a>41?"endDate":"dateTime"],y=lay.extend({},s,t||{});return lay.each({now:y,min:r.min,max:r.max},function(e,t){o[e]=l.newDate(lay.extend({year:t.year,month:t.month,date:t.date},function(){var e={};return lay.each(n,function(a,n){e[n]=t[n]}),e}())).getTime()}),i=o.nowo.max,e&&e[i?"addClass":"removeClass"](d),i},D.prototype.thisDateTime=function(e){var t=this,a=t.config;return e?t.endDate:a.dateTime},D.prototype.calendar=function(e,t,a){var n,i,r,o=this,s=o.config,t=t?1:0,d=e||o.thisDateTime(t),c=new Date,u=o.lang(),h="date"!==s.type&&"datetime"!==s.type,f=lay(o.table[t]).find("td"),g=lay(o.elemHeader[t][2]).find("span");return d.yearm[1]&&(d.year=m[1],o.hint(u.invalidDate)),o.firstDate||(o.firstDate=lay.extend({},d)),c.setFullYear(d.year,d.month,1),n=c.getDay(),i=l.getEndDate(d.month||12,d.year),r=l.getEndDate(d.month+1,d.year),lay.each(f,function(e,t){var a=[d.year,d.month],l=0;t=lay(t),t.removeAttr("class"),e=n&&e=a.firstDate.year&&(l.month=n.max.month,l.date=n.max.date),a.limit(lay(i),l,t),M++}),lay(m[f?0:1]).attr("lay-ym",M-8+"-"+D[1]).html(E+T+" - "+(M-1+T))}else if("month"===e)lay.each(new Array(12),function(e){var i=lay.elem("li",{"lay-ym":e}),r={year:D[0],month:e};e+1==D[1]&&lay(i).addClass(y),i.innerHTML=l.month[e]+(f?"\u6708":""),o.appendChild(i),D[0]=a.firstDate.year&&(r.date=n.max.date),a.limit(lay(i),r,t)}),lay(m[f?0:1]).attr("lay-ym",D[0]+"-"+D[1]).html(D[0]+T);else if("time"===e){var C=function(){lay(o).find("ol").each(function(e,n){lay(n).find("li").each(function(n,i){a.limit(lay(i),[{hours:n},{hours:a[x].hours,minutes:n},{hours:a[x].hours,minutes:a[x].minutes,seconds:n}][e],t,[["hours"],["hours","minutes"],["hours","minutes","seconds"]][e])})}),n.range||a.limit(lay(a.footer).find(p),a[x],0,["hours","minutes","seconds"])};n.range?a[x]||(a[x]="startTime"===x?i:a.endDate):a[x]=i,lay.each([24,60,60],function(e,t){var n=lay.elem("li"),i=["

                                            "+l.time[e]+"

                                              "];lay.each(new Array(t),function(t){i.push(""+lay.digit(t,2)+"")}),n.innerHTML=i.join("")+"
                                            ",o.appendChild(n)}),C()}if(h&&c.removeChild(h),c.appendChild(o),"year"===e||"month"===e)lay(a.elemMain[t]).addClass("laydate-ym-show"),lay(o).find("li").on("click",function(){var l=0|lay(this).attr("lay-ym");if(!lay(this).hasClass(d)){0===t?(i[e]=l,a.limit(lay(a.footer).find(p),null,0)):a.endDate[e]=l;var s="year"===n.type||"month"===n.type;s?(lay(o).find("."+y).removeClass(y),lay(this).addClass(y),"month"===n.type&&"year"===e&&(a.listYM[t][0]=l,r&&((t?a.endDate:i).year=l),a.list("month",t))):(a.checkDate("limit").calendar(null,t),a.closeList()),a.setBtnStatus(),n.range||("month"===n.type&&"month"===e||"year"===n.type&&"year"===e)&&a.setValue(a.parse()).remove().done(),a.done(null,"change"),lay(a.footer).find("."+v).removeClass(d)}});else{var I=lay.elem("span",{"class":g}),k=function(){lay(o).find("ol").each(function(e){var t=this,n=lay(t).find("li");t.scrollTop=30*(a[x][w[e]]-2),t.scrollTop<=0&&n.each(function(e,a){if(!lay(this).hasClass(d))return t.scrollTop=30*(e-2),!0})})},b=lay(s[2]).find("."+g);k(),I.innerHTML=n.range?[l.startTime,l.endTime][t]:l.timeTips,lay(a.elemMain[t]).addClass("laydate-time-show"),b[0]&&b.remove(),s[2].appendChild(I),lay(o).find("ol").each(function(e){var t=this;lay(t).find("li").on("click",function(){var l=0|this.innerHTML;lay(this).hasClass(d)||(n.range?a[x][w[e]]=l:i[w[e]]=l,lay(t).find("."+y).removeClass(y),lay(this).addClass(y),C(),k(),(a.endDate||"time"===n.type)&&a.done(null,"change"),a.setBtnStatus())})})}return a},D.prototype.listYM=[],D.prototype.closeList=function(){var e=this;e.config;lay.each(e.elemCont,function(t,a){lay(this).find("."+u).remove(),lay(e.elemMain[t]).removeClass("laydate-ym-show laydate-time-show")}),lay(e.elem).find("."+g).remove()},D.prototype.setBtnStatus=function(e,t,a){var n,i=this,l=i.config,r=i.lang(),o=lay(i.footer).find(p);l.range&&"time"!==l.type&&(t=t||l.dateTime,a=a||i.endDate,n=i.newDate(t).getTime()>i.newDate(a).getTime(),i.limit(null,t)||i.limit(null,a)?o.addClass(d):o[n?"addClass":"removeClass"](d),e&&n&&i.hint("string"==typeof e?r.timeout.replace(/\u65e5\u671f/g,e):r.timeout))},D.prototype.parse=function(e,t){var a=this,n=a.config,i=t||("end"==e?lay.extend({},a.endDate,a.endTime):n.range?lay.extend({},n.dateTime,a.startTime):n.dateTime),r=l.parse(i,a.format,1);return n.range&&void 0===e?r+" "+a.rangeStr+" "+a.parse("end"):r},D.prototype.newDate=function(e){return e=e||{},new Date(e.year||1,e.month||0,e.date||1,e.hours||0,e.minutes||0,e.seconds||0)},D.prototype.setValue=function(e){var t=this,a=t.config,n=t.bindElem||a.elem[0];return"static"===a.position?t:(e=e||"",t.isInput(n)?lay(n).val(e):t.rangeElem?(t.rangeElem[0].val(e?t.parse("start"):""),t.rangeElem[1].val(e?t.parse("end"):"")):(0===lay(n).find("*").length&&lay(n).html(e),lay(n).attr("lay-date",e)),t)},D.prototype.preview=function(){var e=this,t=e.config;if(t.isPreview){var a=lay(e.elem).find("."+T),n=t.range?e.endDate?e.parse():"":e.parse();a.html(n).css({color:"#5FB878"}),setTimeout(function(){a.css({color:"#666"})},300)}},D.prototype.done=function(e,t){var a=this,n=a.config,i=lay.extend({},lay.extend(n.dateTime,a.startTime)),l=lay.extend({},lay.extend(a.endDate,a.endTime));return lay.each([i,l],function(e,t){"month"in t&&lay.extend(t,{month:t.month+1})}),a.preview(),e=e||[a.parse(),i,l],"function"==typeof n[t||"done"]&&n[t||"done"].apply(n,e),a},D.prototype.choose=function(e,t){var a=this,n=a.config,i=a.thisDateTime(t),l=(lay(a.elem).find("td"),e.attr("lay-ymd").split("-"));l={year:0|l[0],month:(0|l[1])-1,date:0|l[2]},e.hasClass(d)||(lay.extend(i,l),n.range?(lay.each(["startTime","endTime"],function(e,t){a[t]=a[t]||{hours:0,minutes:0,seconds:0}}),a.calendar(null,t).done(null,"change")):"static"===n.position?a.calendar().done().done(null,"change"):"date"===n.type?a.setValue(a.parse()).remove().done():"datetime"===n.type&&a.calendar().done(null,"change"))},D.prototype.tool=function(e,t){var a=this,n=a.config,i=a.lang(),l=n.dateTime,r="static"===n.position,o={datetime:function(){lay(e).hasClass(d)||(a.list("time",0),n.range&&a.list("time",1),lay(e).attr("lay-type","date").html(a.lang().dateTips))},date:function(){a.closeList(),lay(e).attr("lay-type","datetime").html(a.lang().timeTips)},clear:function(){r&&(lay.extend(l,a.firstDate),a.calendar()),n.range&&(delete n.dateTime,delete a.endDate,delete a.startTime,delete a.endTime),a.setValue("").remove(),a.done(["",{},{}])},now:function(){var e=new Date;lay.extend(l,a.systemDate(),{hours:e.getHours(),minutes:e.getMinutes(),seconds:e.getSeconds()}),a.setValue(a.parse()).remove(),r&&a.calendar(),a.done()},confirm:function(){if(n.range){if(lay(e).hasClass(d))return a.hint("time"===n.type?i.timeout.replace(/\u65e5\u671f/g,"\u65f6\u95f4"):i.timeout)}else if(lay(e).hasClass(d))return a.hint(i.invalidDate);a.done(),a.setValue(a.parse()).remove()}};o[t]&&o[t]()},D.prototype.change=function(e){var t=this,a=t.config,n=t.thisDateTime(e),i=a.range&&("year"===a.type||"month"===a.type),l=t.elemCont[e||0],r=t.listYM[e],o=function(o){var s=lay(l).find(".laydate-year-list")[0],y=lay(l).find(".laydate-month-list")[0];return s&&(r[0]=o?r[0]-15:r[0]+15,t.list("year",e)),y&&(o?r[0]--:r[0]++,t.list("month",e)),(s||y)&&(lay.extend(n,{year:r[0]}),i&&(n.year=r[0]),a.range||t.done(null,"change"),a.range||t.limit(lay(t.footer).find(p),{year:r[0]})),t.setBtnStatus(),s||y};return{prevYear:function(){o("sub")||(n.year--,t.checkDate("limit").calendar(null,e),t.done(null,"change"))},prevMonth:function(){var a=t.getAsYM(n.year,n.month,"sub");lay.extend(n,{year:a[0],month:a[1]}),t.checkDate("limit").calendar(null,e),t.done(null,"change")},nextMonth:function(){var a=t.getAsYM(n.year,n.month);lay.extend(n,{year:a[0],month:a[1]}),t.checkDate("limit").calendar(null,e),t.done(null,"change")},nextYear:function(){o()||(n.year++,t.checkDate("limit").calendar(null,e),t.done(null,"change"))}}},D.prototype.changeEvent=function(){var e=this;e.config;lay(e.elem).on("click",function(e){lay.stope(e)}).on("mousedown",function(e){lay.stope(e)}),lay.each(e.elemHeader,function(t,a){lay(a[0]).on("click",function(a){e.change(t).prevYear()}),lay(a[1]).on("click",function(a){e.change(t).prevMonth()}),lay(a[2]).find("span").on("click",function(a){var n=lay(this),i=n.attr("lay-ym"),l=n.attr("lay-type");i&&(i=i.split("-"),e.listYM[t]=[0|i[0],0|i[1]],e.list(l,t),lay(e.footer).find("."+v).addClass(d))}),lay(a[3]).on("click",function(a){e.change(t).nextMonth()}),lay(a[4]).on("click",function(a){e.change(t).nextYear()})}),lay.each(e.table,function(t,a){var n=lay(a).find("td");n.on("click",function(){e.choose(lay(this),t)})}),lay(e.footer).find("span").on("click",function(){var t=lay(this).attr("lay-type");e.tool(this,t)})},D.prototype.isInput=function(e){return/input|textarea/.test(e.tagName.toLocaleLowerCase())},D.prototype.events=function(){var e=this,t=e.config,a=function(a,n){a.on(t.trigger,function(){n&&(e.bindElem=this),e.render()})};t.elem[0]&&!t.elem[0].eventHandler&&(a(t.elem,"bind"),a(t.eventElem),t.elem[0].eventHandler=!0)},r.that={},r.getThis=function(e){var t=r.that[e];return!t&&a&&layui.hint().error(e?o+" instance with ID '"+e+"' not found":"ID argument required"),t},n.run=function(a){a(t).on("mousedown",function(e){if(l.thisId){var t=r.getThis(l.thisId);if(t){var n=t.config;e.target!==n.elem[0]&&e.target!==n.eventElem[0]&&e.target!==a(n.closeStop)[0]&&t.remove()}}}).on("keydown",function(e){if(l.thisId){var t=r.getThis(l.thisId);t&&13===e.keyCode&&a("#"+t.elemID)[0]&&t.elemID===D.thisElemDate&&(e.preventDefault(),a(t.footer).find(p)[0].click())}}),a(e).on("resize",function(){if(l.thisId){var e=r.getThis(l.thisId);if(e)return!(!e.elem||!a(s)[0])&&void e.position()}})},l.render=function(e){var t=new D(e);return r.call(t)},l.parse=function(e,t,a){return e=e||{},"string"==typeof t&&(t=r.formatArr(t)),t=(t||[]).concat(),lay.each(t,function(n,i){/yyyy|y/.test(i)?t[n]=lay.digit(e.year,i.length):/MM|M/.test(i)?t[n]=lay.digit(e.month+(a||0),i.length):/dd|d/.test(i)?t[n]=lay.digit(e.date,i.length):/HH|H/.test(i)?t[n]=lay.digit(e.hours,i.length):/mm|m/.test(i)?t[n]=lay.digit(e.minutes,i.length):/ss|s/.test(i)&&(t[n]=lay.digit(e.seconds,i.length))}),t.join("")},l.getEndDate=function(e,t){var a=new Date;return a.setFullYear(t||a.getFullYear(),e||a.getMonth()+1,1),new Date(a.getTime()-864e5).getDate()},a?(l.ready(),layui.define("lay",function(e){l.path=layui.cache.dir,n.run(lay),e(o,l)})):"function"==typeof define&&define.amd?define(function(){return n.run(lay),l}):function(){l.ready(),n.run(e.lay),e.laydate=l}()}(window,window.document);!function(e,t){"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){function n(e){var t=!!e&&"length"in e&&e.length,n=pe.type(e);return"function"!==n&&!pe.isWindow(e)&&("array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e)}function r(e,t,n){if(pe.isFunction(t))return pe.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return pe.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(Ce.test(t))return pe.filter(t,e,n);t=pe.filter(t,e)}return pe.grep(e,function(e){return pe.inArray(e,t)>-1!==n})}function i(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function o(e){var t={};return pe.each(e.match(De)||[],function(e,n){t[n]=!0}),t}function a(){re.addEventListener?(re.removeEventListener("DOMContentLoaded",s),e.removeEventListener("load",s)):(re.detachEvent("onreadystatechange",s),e.detachEvent("onload",s))}function s(){(re.addEventListener||"load"===e.event.type||"complete"===re.readyState)&&(a(),pe.ready())}function u(e,t,n){if(void 0===n&&1===e.nodeType){var r="data-"+t.replace(_e,"-$1").toLowerCase();if(n=e.getAttribute(r),"string"==typeof n){try{n="true"===n||"false"!==n&&("null"===n?null:+n+""===n?+n:qe.test(n)?pe.parseJSON(n):n)}catch(i){}pe.data(e,t,n)}else n=void 0}return n}function l(e){var t;for(t in e)if(("data"!==t||!pe.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}function c(e,t,n,r){if(He(e)){var i,o,a=pe.expando,s=e.nodeType,u=s?pe.cache:e,l=s?e[a]:e[a]&&a;if(l&&u[l]&&(r||u[l].data)||void 0!==n||"string"!=typeof t)return l||(l=s?e[a]=ne.pop()||pe.guid++:a),u[l]||(u[l]=s?{}:{toJSON:pe.noop}),"object"!=typeof t&&"function"!=typeof t||(r?u[l]=pe.extend(u[l],t):u[l].data=pe.extend(u[l].data,t)),o=u[l],r||(o.data||(o.data={}),o=o.data),void 0!==n&&(o[pe.camelCase(t)]=n),"string"==typeof t?(i=o[t],null==i&&(i=o[pe.camelCase(t)])):i=o,i}}function f(e,t,n){if(He(e)){var r,i,o=e.nodeType,a=o?pe.cache:e,s=o?e[pe.expando]:pe.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){pe.isArray(t)?t=t.concat(pe.map(t,pe.camelCase)):t in r?t=[t]:(t=pe.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;for(;i--;)delete r[t[i]];if(n?!l(r):!pe.isEmptyObject(r))return}(n||(delete a[s].data,l(a[s])))&&(o?pe.cleanData([e],!0):fe.deleteExpando||a!=a.window?delete a[s]:a[s]=void 0)}}}function d(e,t,n,r){var i,o=1,a=20,s=r?function(){return r.cur()}:function(){return pe.css(e,t,"")},u=s(),l=n&&n[3]||(pe.cssNumber[t]?"":"px"),c=(pe.cssNumber[t]||"px"!==l&&+u)&&Me.exec(pe.css(e,t));if(c&&c[3]!==l){l=l||c[3],n=n||[],c=+u||1;do o=o||".5",c/=o,pe.style(e,t,c+l);while(o!==(o=s()/u)&&1!==o&&--a)}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}function p(e){var t=ze.split("|"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function h(e,t){var n,r,i=0,o="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):void 0;if(!o)for(o=[],n=e.childNodes||e;null!=(r=n[i]);i++)!t||pe.nodeName(r,t)?o.push(r):pe.merge(o,h(r,t));return void 0===t||t&&pe.nodeName(e,t)?pe.merge([e],o):o}function g(e,t){for(var n,r=0;null!=(n=e[r]);r++)pe._data(n,"globalEval",!t||pe._data(t[r],"globalEval"))}function m(e){Be.test(e.type)&&(e.defaultChecked=e.checked)}function y(e,t,n,r,i){for(var o,a,s,u,l,c,f,d=e.length,y=p(t),v=[],x=0;x"!==f[1]||Ve.test(a)?0:u:u.firstChild,o=a&&a.childNodes.length;o--;)pe.nodeName(c=a.childNodes[o],"tbody")&&!c.childNodes.length&&a.removeChild(c);for(pe.merge(v,u.childNodes),u.textContent="";u.firstChild;)u.removeChild(u.firstChild);u=y.lastChild}else v.push(t.createTextNode(a));for(u&&y.removeChild(u),fe.appendChecked||pe.grep(h(v,"input"),m),x=0;a=v[x++];)if(r&&pe.inArray(a,r)>-1)i&&i.push(a);else if(s=pe.contains(a.ownerDocument,a),u=h(y.appendChild(a),"script"),s&&g(u),n)for(o=0;a=u[o++];)Ie.test(a.type||"")&&n.push(a);return u=null,y}function v(){return!0}function x(){return!1}function b(){try{return re.activeElement}catch(e){}}function w(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)w(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),i===!1)i=x;else if(!i)return e;return 1===o&&(a=i,i=function(e){return pe().off(e),a.apply(this,arguments)},i.guid=a.guid||(a.guid=pe.guid++)),e.each(function(){pe.event.add(this,t,i,r,n)})}function T(e,t){return pe.nodeName(e,"table")&&pe.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function C(e){return e.type=(null!==pe.find.attr(e,"type"))+"/"+e.type,e}function E(e){var t=it.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function N(e,t){if(1===t.nodeType&&pe.hasData(e)){var n,r,i,o=pe._data(e),a=pe._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;r1&&"string"==typeof p&&!fe.checkClone&&rt.test(p))return e.each(function(i){var o=e.eq(i);g&&(t[0]=p.call(this,i,o.html())),S(o,t,n,r)});if(f&&(l=y(t,e[0].ownerDocument,!1,e,r),i=l.firstChild,1===l.childNodes.length&&(l=i),i||r)){for(s=pe.map(h(l,"script"),C),a=s.length;c")).appendTo(t.documentElement),t=(ut[0].contentWindow||ut[0].contentDocument).document,t.write(),t.close(),n=D(e,t),ut.detach()),lt[e]=n),n}function L(e,t){return{get:function(){return e()?void delete this.get:(this.get=t).apply(this,arguments)}}}function H(e){if(e in Et)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=Ct.length;n--;)if(e=Ct[n]+t,e in Et)return e}function q(e,t){for(var n,r,i,o=[],a=0,s=e.length;a=0&&n=0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},isPlainObject:function(e){var t;if(!e||"object"!==pe.type(e)||e.nodeType||pe.isWindow(e))return!1;try{if(e.constructor&&!ce.call(e,"constructor")&&!ce.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}if(!fe.ownFirst)for(t in e)return ce.call(e,t);for(t in e);return void 0===t||ce.call(e,t)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?ue[le.call(e)]||"object":typeof e},globalEval:function(t){t&&pe.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(ge,"ms-").replace(me,ye)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t){var r,i=0;if(n(e))for(r=e.length;iT.cacheLength&&delete e[t.shift()],e[n+" "]=r}var t=[];return e}function r(e){return e[P]=!0,e}function i(e){var t=H.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var n=e.split("|"),r=n.length;r--;)T.attrHandle[n[r]]=t}function a(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||V)-(~e.sourceIndex||V);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function s(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function u(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function l(e){return r(function(t){return t=+t,r(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function c(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function f(){}function d(e){for(var t=0,n=e.length,r="";t1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function g(e,n,r){for(var i=0,o=n.length;i-1&&(r[l]=!(a[l]=f))}}else x=m(x===a?x.splice(h,x.length):x),o?o(null,a,x,u):Q.apply(a,x)})}function v(e){for(var t,n,r,i=e.length,o=T.relative[e[0].type],a=o||T.relative[" "],s=o?1:0,u=p(function(e){return e===t},a,!0),l=p(function(e){return ee(t,e)>-1},a,!0),c=[function(e,n,r){var i=!o&&(r||n!==A)||((t=n).nodeType?u(e,n,r):l(e,n,r));return t=null,i}];s1&&h(c),s>1&&d(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(se,"$1"),n,s0,o=e.length>0,a=function(r,a,s,u,l){var c,f,d,p=0,h="0",g=r&&[],y=[],v=A,x=r||o&&T.find.TAG("*",l),b=W+=null==v?1:Math.random()||.1,w=x.length;for(l&&(A=a===H||a||l);h!==w&&null!=(c=x[h]);h++){if(o&&c){for(f=0,a||c.ownerDocument===H||(L(c),s=!_);d=e[f++];)if(d(c,a||H,s)){u.push(c);break}l&&(W=b)}i&&((c=!d&&c)&&p--,r&&g.push(c))}if(p+=h,i&&h!==p){for(f=0;d=n[f++];)d(g,y,a,s);if(r){if(p>0)for(;h--;)g[h]||y[h]||(y[h]=G.call(u));y=m(y)}Q.apply(u,y),l&&!r&&y.length>0&&p+n.length>1&&t.uniqueSort(u)}return l&&(W=b,A=v),g};return i?r(a):a}var b,w,T,C,E,N,k,S,A,D,j,L,H,q,_,F,M,O,R,P="sizzle"+1*new Date,B=e.document,W=0,I=0,$=n(),z=n(),X=n(),U=function(e,t){return e===t&&(j=!0),0},V=1<<31,Y={}.hasOwnProperty,J=[],G=J.pop,K=J.push,Q=J.push,Z=J.slice,ee=function(e,t){for(var n=0,r=e.length;n+~]|"+ne+")"+ne+"*"),ce=new RegExp("="+ne+"*([^\\]'\"]*?)"+ne+"*\\]","g"),fe=new RegExp(oe),de=new RegExp("^"+re+"$"),pe={ID:new RegExp("^#("+re+")"),CLASS:new RegExp("^\\.("+re+")"),TAG:new RegExp("^("+re+"|[*])"),ATTR:new RegExp("^"+ie),PSEUDO:new RegExp("^"+oe),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ne+"*(even|odd|(([+-]|)(\\d*)n|)"+ne+"*(?:([+-]|)"+ne+"*(\\d+)|))"+ne+"*\\)|)","i"),bool:new RegExp("^(?:"+te+")$","i"),needsContext:new RegExp("^"+ne+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ne+"*((?:-\\d)?\\d*)"+ne+"*\\)|)(?=[^-]|$)","i")},he=/^(?:input|select|textarea|button)$/i,ge=/^h\d$/i,me=/^[^{]+\{\s*\[native \w/,ye=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ve=/[+~]/,xe=/'|\\/g,be=new RegExp("\\\\([\\da-f]{1,6}"+ne+"?|("+ne+")|.)","ig"),we=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},Te=function(){L()};try{Q.apply(J=Z.call(B.childNodes),B.childNodes),J[B.childNodes.length].nodeType}catch(Ce){Q={apply:J.length?function(e,t){K.apply(e,Z.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}w=t.support={},E=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},L=t.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:B;return r!==H&&9===r.nodeType&&r.documentElement?(H=r,q=H.documentElement,_=!E(H),(n=H.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",Te,!1):n.attachEvent&&n.attachEvent("onunload",Te)),w.attributes=i(function(e){return e.className="i",!e.getAttribute("className")}),w.getElementsByTagName=i(function(e){return e.appendChild(H.createComment("")),!e.getElementsByTagName("*").length}),w.getElementsByClassName=me.test(H.getElementsByClassName),w.getById=i(function(e){return q.appendChild(e).id=P,!H.getElementsByName||!H.getElementsByName(P).length}),w.getById?(T.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&_){var n=t.getElementById(e);return n?[n]:[]}},T.filter.ID=function(e){var t=e.replace(be,we);return function(e){return e.getAttribute("id")===t}}):(delete T.find.ID,T.filter.ID=function(e){var t=e.replace(be,we);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}}),T.find.TAG=w.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):w.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},T.find.CLASS=w.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&_)return t.getElementsByClassName(e)},M=[],F=[],(w.qsa=me.test(H.querySelectorAll))&&(i(function(e){q.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&F.push("[*^$]="+ne+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||F.push("\\["+ne+"*(?:value|"+te+")"),e.querySelectorAll("[id~="+P+"-]").length||F.push("~="),e.querySelectorAll(":checked").length||F.push(":checked"),e.querySelectorAll("a#"+P+"+*").length||F.push(".#.+[+~]")}),i(function(e){var t=H.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&F.push("name"+ne+"*[*^$|!~]?="),e.querySelectorAll(":enabled").length||F.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),F.push(",.*:")})),(w.matchesSelector=me.test(O=q.matches||q.webkitMatchesSelector||q.mozMatchesSelector||q.oMatchesSelector||q.msMatchesSelector))&&i(function(e){w.disconnectedMatch=O.call(e,"div"),O.call(e,"[s!='']:x"),M.push("!=",oe)}),F=F.length&&new RegExp(F.join("|")),M=M.length&&new RegExp(M.join("|")),t=me.test(q.compareDocumentPosition),R=t||me.test(q.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},U=t?function(e,t){if(e===t)return j=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n?n:(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&n||!w.sortDetached&&t.compareDocumentPosition(e)===n?e===H||e.ownerDocument===B&&R(B,e)?-1:t===H||t.ownerDocument===B&&R(B,t)?1:D?ee(D,e)-ee(D,t):0:4&n?-1:1)}:function(e,t){if(e===t)return j=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,s=[e],u=[t];if(!i||!o)return e===H?-1:t===H?1:i?-1:o?1:D?ee(D,e)-ee(D,t):0;if(i===o)return a(e,t);for(n=e;n=n.parentNode;)s.unshift(n);for(n=t;n=n.parentNode;)u.unshift(n);for(;s[r]===u[r];)r++;return r?a(s[r],u[r]):s[r]===B?-1:u[r]===B?1:0},H):H},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==H&&L(e),n=n.replace(ce,"='$1']"),w.matchesSelector&&_&&!X[n+" "]&&(!M||!M.test(n))&&(!F||!F.test(n)))try{var r=O.call(e,n);if(r||w.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return t(n,H,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==H&&L(e),R(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==H&&L(e);var n=T.attrHandle[t.toLowerCase()],r=n&&Y.call(T.attrHandle,t.toLowerCase())?n(e,t,!_):void 0;return void 0!==r?r:w.attributes||!_?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},t.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},t.uniqueSort=function(e){var t,n=[],r=0,i=0;if(j=!w.detectDuplicates,D=!w.sortStable&&e.slice(0),e.sort(U),j){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return D=null,e},C=t.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=C(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r++];)n+=C(t);return n},T=t.selectors={cacheLength:50,createPseudo:r,match:pe,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(be,we),e[3]=(e[3]||e[4]||e[5]||"").replace(be,we),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||t.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return pe.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&fe.test(n)&&(t=N(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(be,we).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=$[e+" "];return t||(t=new RegExp("(^|"+ne+")"+e+"("+ne+"|$)"))&&$(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,n,r){return function(i){var o=t.attr(i,e);return null==o?"!="===n:!n||(o+="","="===n?o===r:"!="===n?o!==r:"^="===n?r&&0===o.indexOf(r):"*="===n?r&&o.indexOf(r)>-1:"$="===n?r&&o.slice(-r.length)===r:"~="===n?(" "+o.replace(ae," ")+" ").indexOf(r)>-1:"|="===n&&(o===r||o.slice(0,r.length+1)===r+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,d,p,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s,x=!1;if(m){if(o){for(;g;){for(d=t;d=d[g];)if(s?d.nodeName.toLowerCase()===y:1===d.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){for(d=m,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),l=c[e]||[],p=l[0]===W&&l[1],x=p&&l[2], -d=p&&m.childNodes[p];d=++p&&d&&d[g]||(x=p=0)||h.pop();)if(1===d.nodeType&&++x&&d===t){c[e]=[W,p,x];break}}else if(v&&(d=t,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),l=c[e]||[],p=l[0]===W&&l[1],x=p),x===!1)for(;(d=++p&&d&&d[g]||(x=p=0)||h.pop())&&((s?d.nodeName.toLowerCase()!==y:1!==d.nodeType)||!++x||(v&&(f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),c[e]=[W,x]),d!==t)););return x-=i,x===r||x%r===0&&x/r>=0}}},PSEUDO:function(e,n){var i,o=T.pseudos[e]||T.setFilters[e.toLowerCase()]||t.error("unsupported pseudo: "+e);return o[P]?o(n):o.length>1?(i=[e,e,"",n],T.setFilters.hasOwnProperty(e.toLowerCase())?r(function(e,t){for(var r,i=o(e,n),a=i.length;a--;)r=ee(e,i[a]),e[r]=!(t[r]=i[a])}):function(e){return o(e,0,i)}):o}},pseudos:{not:r(function(e){var t=[],n=[],i=k(e.replace(se,"$1"));return i[P]?r(function(e,t,n,r){for(var o,a=i(e,null,r,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,r,o){return t[0]=e,i(t,null,o,n),t[0]=null,!n.pop()}}),has:r(function(e){return function(n){return t(e,n).length>0}}),contains:r(function(e){return e=e.replace(be,we),function(t){return(t.textContent||t.innerText||C(t)).indexOf(e)>-1}}),lang:r(function(e){return de.test(e||"")||t.error("unsupported lang: "+e),e=e.replace(be,we).toLowerCase(),function(t){var n;do if(n=_?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===q},focus:function(e){return e===H.activeElement&&(!H.hasFocus||H.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!T.pseudos.empty(e)},header:function(e){return ge.test(e.nodeName)},input:function(e){return he.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:l(function(){return[0]}),last:l(function(e,t){return[t-1]}),eq:l(function(e,t,n){return[n<0?n+t:n]}),even:l(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:l(function(e,t,n){for(var r=n<0?n+t:n;++r2&&"ID"===(a=o[0]).type&&w.getById&&9===t.nodeType&&_&&T.relative[o[1].type]){if(t=(T.find.ID(a.matches[0].replace(be,we),t)||[])[0],!t)return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=pe.needsContext.test(e)?0:o.length;i--&&(a=o[i],!T.relative[s=a.type]);)if((u=T.find[s])&&(r=u(a.matches[0].replace(be,we),ve.test(o[0].type)&&c(t.parentNode)||t))){if(o.splice(i,1),e=r.length&&d(o),!e)return Q.apply(n,r),n;break}}return(l||k(e,f))(r,t,!_,n,!t||ve.test(e)&&c(t.parentNode)||t),n},w.sortStable=P.split("").sort(U).join("")===P,w.detectDuplicates=!!j,L(),w.sortDetached=i(function(e){return 1&e.compareDocumentPosition(H.createElement("div"))}),i(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||o("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),w.attributes&&i(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||o("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),i(function(e){return null==e.getAttribute("disabled")})||o(te,function(e,t,n){var r;if(!n)return e[t]===!0?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),t}(e);pe.find=ve,pe.expr=ve.selectors,pe.expr[":"]=pe.expr.pseudos,pe.uniqueSort=pe.unique=ve.uniqueSort,pe.text=ve.getText,pe.isXMLDoc=ve.isXML,pe.contains=ve.contains;var xe=function(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&pe(e).is(n))break;r.push(e)}return r},be=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},we=pe.expr.match.needsContext,Te=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,Ce=/^.[^:#\[\.,]*$/;pe.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?pe.find.matchesSelector(r,e)?[r]:[]:pe.find.matches(e,pe.grep(t,function(e){return 1===e.nodeType}))},pe.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(pe(e).filter(function(){for(t=0;t1?pe.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},filter:function(e){return this.pushStack(r(this,e||[],!1))},not:function(e){return this.pushStack(r(this,e||[],!0))},is:function(e){return!!r(this,"string"==typeof e&&we.test(e)?pe(e):e||[],!1).length}});var Ee,Ne=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,ke=pe.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||Ee,"string"==typeof e){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:Ne.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof pe?t[0]:t,pe.merge(this,pe.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:re,!0)),Te.test(r[1])&&pe.isPlainObject(t))for(r in t)pe.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}if(i=re.getElementById(r[2]),i&&i.parentNode){if(i.id!==r[2])return Ee.find(e);this.length=1,this[0]=i}return this.context=re,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):pe.isFunction(e)?"undefined"!=typeof n.ready?n.ready(e):e(pe):(void 0!==e.selector&&(this.selector=e.selector,this.context=e.context),pe.makeArray(e,this))};ke.prototype=pe.fn,Ee=pe(re);var Se=/^(?:parents|prev(?:Until|All))/,Ae={children:!0,contents:!0,next:!0,prev:!0};pe.fn.extend({has:function(e){var t,n=pe(e,this),r=n.length;return this.filter(function(){for(t=0;t-1:1===n.nodeType&&pe.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?pe.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?pe.inArray(this[0],pe(e)):pe.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(pe.uniqueSort(pe.merge(this.get(),pe(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),pe.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return xe(e,"parentNode")},parentsUntil:function(e,t,n){return xe(e,"parentNode",n)},next:function(e){return i(e,"nextSibling")},prev:function(e){return i(e,"previousSibling")},nextAll:function(e){return xe(e,"nextSibling")},prevAll:function(e){return xe(e,"previousSibling")},nextUntil:function(e,t,n){return xe(e,"nextSibling",n)},prevUntil:function(e,t,n){return xe(e,"previousSibling",n)},siblings:function(e){return be((e.parentNode||{}).firstChild,e)},children:function(e){return be(e.firstChild)},contents:function(e){return pe.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:pe.merge([],e.childNodes)}},function(e,t){pe.fn[e]=function(n,r){var i=pe.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=pe.filter(r,i)),this.length>1&&(Ae[e]||(i=pe.uniqueSort(i)),Se.test(e)&&(i=i.reverse())),this.pushStack(i)}});var De=/\S+/g;pe.Callbacks=function(e){e="string"==typeof e?o(e):pe.extend({},e);var t,n,r,i,a=[],s=[],u=-1,l=function(){for(i=e.once,r=t=!0;s.length;u=-1)for(n=s.shift();++u-1;)a.splice(n,1),n<=u&&u--}),this},has:function(e){return e?pe.inArray(e,a)>-1:a.length>0},empty:function(){return a&&(a=[]),this},disable:function(){return i=s=[],a=n="",this},disabled:function(){return!a},lock:function(){return i=!0,n||c.disable(),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=n||[],n=[e,n.slice?n.slice():n],s.push(n),t||l()),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},pe.extend({Deferred:function(e){var t=[["resolve","done",pe.Callbacks("once memory"),"resolved"],["reject","fail",pe.Callbacks("once memory"),"rejected"],["notify","progress",pe.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return pe.Deferred(function(n){pe.each(t,function(t,o){var a=pe.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&pe.isFunction(e.promise)?e.promise().progress(n.notify).done(n.resolve).fail(n.reject):n[o[0]+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?pe.extend(e,r):r}},i={};return r.pipe=r.then,pe.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t,n,r,i=0,o=ie.call(arguments),a=o.length,s=1!==a||e&&pe.isFunction(e.promise)?a:0,u=1===s?e:pe.Deferred(),l=function(e,n,r){return function(i){n[e]=this,r[e]=arguments.length>1?ie.call(arguments):i,r===t?u.notifyWith(n,r):--s||u.resolveWith(n,r)}};if(a>1)for(t=new Array(a),n=new Array(a),r=new Array(a);i0||(je.resolveWith(re,[pe]),pe.fn.triggerHandler&&(pe(re).triggerHandler("ready"),pe(re).off("ready"))))}}),pe.ready.promise=function(t){if(!je)if(je=pe.Deferred(),"complete"===re.readyState||"loading"!==re.readyState&&!re.documentElement.doScroll)e.setTimeout(pe.ready);else if(re.addEventListener)re.addEventListener("DOMContentLoaded",s),e.addEventListener("load",s);else{re.attachEvent("onreadystatechange",s),e.attachEvent("onload",s);var n=!1;try{n=null==e.frameElement&&re.documentElement}catch(r){}n&&n.doScroll&&!function i(){if(!pe.isReady){try{n.doScroll("left")}catch(t){return e.setTimeout(i,50)}a(),pe.ready()}}()}return je.promise(t)},pe.ready.promise();var Le;for(Le in pe(fe))break;fe.ownFirst="0"===Le,fe.inlineBlockNeedsLayout=!1,pe(function(){var e,t,n,r;n=re.getElementsByTagName("body")[0],n&&n.style&&(t=re.createElement("div"),r=re.createElement("div"),r.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",n.appendChild(r).appendChild(t),"undefined"!=typeof t.style.zoom&&(t.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",fe.inlineBlockNeedsLayout=e=3===t.offsetWidth,e&&(n.style.zoom=1)),n.removeChild(r))}),function(){var e=re.createElement("div");fe.deleteExpando=!0;try{delete e.test}catch(t){fe.deleteExpando=!1}e=null}();var He=function(e){var t=pe.noData[(e.nodeName+" ").toLowerCase()],n=+e.nodeType||1;return(1===n||9===n)&&(!t||t!==!0&&e.getAttribute("classid")===t)},qe=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,_e=/([A-Z])/g;pe.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?pe.cache[e[pe.expando]]:e[pe.expando],!!e&&!l(e)},data:function(e,t,n){return c(e,t,n)},removeData:function(e,t){return f(e,t)},_data:function(e,t,n){return c(e,t,n,!0)},_removeData:function(e,t){return f(e,t,!0)}}),pe.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=pe.data(o),1===o.nodeType&&!pe._data(o,"parsedAttrs"))){for(n=a.length;n--;)a[n]&&(r=a[n].name,0===r.indexOf("data-")&&(r=pe.camelCase(r.slice(5)),u(o,r,i[r])));pe._data(o,"parsedAttrs",!0)}return i}return"object"==typeof e?this.each(function(){pe.data(this,e)}):arguments.length>1?this.each(function(){pe.data(this,e,t)}):o?u(o,e,pe.data(o,e)):void 0},removeData:function(e){return this.each(function(){pe.removeData(this,e)})}}),pe.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=pe._data(e,t),n&&(!r||pe.isArray(n)?r=pe._data(e,t,pe.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=pe.queue(e,t),r=n.length,i=n.shift(),o=pe._queueHooks(e,t),a=function(){pe.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return pe._data(e,n)||pe._data(e,n,{empty:pe.Callbacks("once memory").add(function(){pe._removeData(e,t+"queue"),pe._removeData(e,n)})})}}),pe.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length
                                            a",fe.leadingWhitespace=3===e.firstChild.nodeType,fe.tbody=!e.getElementsByTagName("tbody").length,fe.htmlSerialize=!!e.getElementsByTagName("link").length,fe.html5Clone="<:nav>"!==re.createElement("nav").cloneNode(!0).outerHTML,n.type="checkbox",n.checked=!0,t.appendChild(n),fe.appendChecked=n.checked,e.innerHTML="",fe.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue,t.appendChild(e),n=re.createElement("input"),n.setAttribute("type","radio"),n.setAttribute("checked","checked"),n.setAttribute("name","t"),e.appendChild(n),fe.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,fe.noCloneEvent=!!e.addEventListener,e[pe.expando]=1,fe.attributes=!e.getAttribute(pe.expando)}();var Xe={option:[1,""],legend:[1,"
                                            ","
                                            "],area:[1,"",""],param:[1,"",""],thead:[1,"","
                                            "],tr:[2,"","
                                            "],col:[2,"","
                                            "],td:[3,"","
                                            "],_default:fe.htmlSerialize?[0,"",""]:[1,"X
                                            ","
                                            "]};Xe.optgroup=Xe.option,Xe.tbody=Xe.tfoot=Xe.colgroup=Xe.caption=Xe.thead,Xe.th=Xe.td;var Ue=/<|&#?\w+;/,Ve=/-1&&(h=p.split("."),p=h.shift(),h.sort()),a=p.indexOf(":")<0&&"on"+p,t=t[pe.expando]?t:new pe.Event(p,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=h.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=r),n=null==n?[t]:pe.makeArray(n,[t]),l=pe.event.special[p]||{},i||!l.trigger||l.trigger.apply(r,n)!==!1)){if(!i&&!l.noBubble&&!pe.isWindow(r)){for(u=l.delegateType||p,Ke.test(u+p)||(s=s.parentNode);s;s=s.parentNode)d.push(s),c=s;c===(r.ownerDocument||re)&&d.push(c.defaultView||c.parentWindow||e)}for(f=0;(s=d[f++])&&!t.isPropagationStopped();)t.type=f>1?u:l.bindType||p,o=(pe._data(s,"events")||{})[t.type]&&pe._data(s,"handle"),o&&o.apply(s,n),o=a&&s[a],o&&o.apply&&He(s)&&(t.result=o.apply(s,n),t.result===!1&&t.preventDefault());if(t.type=p,!i&&!t.isDefaultPrevented()&&(!l._default||l._default.apply(d.pop(),n)===!1)&&He(r)&&a&&r[p]&&!pe.isWindow(r)){c=r[a],c&&(r[a]=null),pe.event.triggered=p;try{r[p]()}catch(g){}pe.event.triggered=void 0,c&&(r[a]=c)}return t.result}},dispatch:function(e){e=pe.event.fix(e);var t,n,r,i,o,a=[],s=ie.call(arguments),u=(pe._data(this,"events")||{})[e.type]||[],l=pe.event.special[e.type]||{};if(s[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){for(a=pe.event.handlers.call(this,e,u),t=0;(i=a[t++])&&!e.isPropagationStopped();)for(e.currentTarget=i.elem,n=0;(o=i.handlers[n++])&&!e.isImmediatePropagationStopped();)e.rnamespace&&!e.rnamespace.test(o.namespace)||(e.handleObj=o,e.data=o.data,r=((pe.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s),void 0!==r&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()));return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,a=[],s=t.delegateCount,u=e.target;if(s&&u.nodeType&&("click"!==e.type||isNaN(e.button)||e.button<1))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(r=[],n=0;n-1:pe.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&a.push({elem:u,handlers:r})}return s]","i"),tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,nt=/\s*$/g,at=p(re),st=at.appendChild(re.createElement("div"));pe.extend({htmlPrefilter:function(e){return e.replace(tt,"<$1>")},clone:function(e,t,n){var r,i,o,a,s,u=pe.contains(e.ownerDocument,e);if(fe.html5Clone||pe.isXMLDoc(e)||!et.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(st.innerHTML=e.outerHTML,st.removeChild(o=st.firstChild)),!(fe.noCloneEvent&&fe.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||pe.isXMLDoc(e)))for(r=h(o),s=h(e),a=0;null!=(i=s[a]);++a)r[a]&&k(i,r[a]);if(t)if(n)for(s=s||h(e),r=r||h(o),a=0;null!=(i=s[a]);a++)N(i,r[a]);else N(e,o);return r=h(o,"script"),r.length>0&&g(r,!u&&h(e,"script")),r=s=i=null,o},cleanData:function(e,t){for(var n,r,i,o,a=0,s=pe.expando,u=pe.cache,l=fe.attributes,c=pe.event.special;null!=(n=e[a]);a++)if((t||He(n))&&(i=n[s],o=i&&u[i])){if(o.events)for(r in o.events)c[r]?pe.event.remove(n,r):pe.removeEvent(n,r,o.handle);u[i]&&(delete u[i],l||"undefined"==typeof n.removeAttribute?n[s]=void 0:n.removeAttribute(s),ne.push(i))}}}),pe.fn.extend({domManip:S,detach:function(e){return A(this,e,!0)},remove:function(e){return A(this,e)},text:function(e){return Pe(this,function(e){return void 0===e?pe.text(this):this.empty().append((this[0]&&this[0].ownerDocument||re).createTextNode(e))},null,e,arguments.length)},append:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.appendChild(e)}})},prepend:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&pe.cleanData(h(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&pe.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return pe.clone(this,e,t)})},html:function(e){return Pe(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e)return 1===t.nodeType?t.innerHTML.replace(Ze,""):void 0;if("string"==typeof e&&!nt.test(e)&&(fe.htmlSerialize||!et.test(e))&&(fe.leadingWhitespace||!$e.test(e))&&!Xe[(We.exec(e)||["",""])[1].toLowerCase()]){e=pe.htmlPrefilter(e);try{for(;nt",l.childNodes[0].style.borderCollapse="separate",t=l.getElementsByTagName("td"),t[0].style.cssText="margin:0;border:0;padding:0;display:none",o=0===t[0].offsetHeight,o&&(t[0].style.display="",t[1].style.display="none",o=0===t[0].offsetHeight)),f.removeChild(u)}var n,r,i,o,a,s,u=re.createElement("div"),l=re.createElement("div");l.style&&(l.style.cssText="float:left;opacity:.5",fe.opacity="0.5"===l.style.opacity,fe.cssFloat=!!l.style.cssFloat,l.style.backgroundClip="content-box",l.cloneNode(!0).style.backgroundClip="",fe.clearCloneStyle="content-box"===l.style.backgroundClip,u=re.createElement("div"),u.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",l.innerHTML="",u.appendChild(l),fe.boxSizing=""===l.style.boxSizing||""===l.style.MozBoxSizing||""===l.style.WebkitBoxSizing,pe.extend(fe,{reliableHiddenOffsets:function(){return null==n&&t(),o},boxSizingReliable:function(){return null==n&&t(),i},pixelMarginRight:function(){return null==n&&t(),r},pixelPosition:function(){return null==n&&t(),n},reliableMarginRight:function(){return null==n&&t(),a},reliableMarginLeft:function(){return null==n&&t(),s}}))}();var ht,gt,mt=/^(top|right|bottom|left)$/;e.getComputedStyle?(ht=function(t){var n=t.ownerDocument.defaultView;return n&&n.opener||(n=e),n.getComputedStyle(t)},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n.getPropertyValue(t)||n[t]:void 0,""!==a&&void 0!==a||pe.contains(e.ownerDocument,e)||(a=pe.style(e,t)),n&&!fe.pixelMarginRight()&&ft.test(a)&&ct.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o),void 0===a?a:a+""}):pt.currentStyle&&(ht=function(e){return e.currentStyle},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n[t]:void 0,null==a&&s&&s[t]&&(a=s[t]),ft.test(a)&&!mt.test(t)&&(r=s.left,i=e.runtimeStyle,o=i&&i.left,o&&(i.left=e.currentStyle.left),s.left="fontSize"===t?"1em":a,a=s.pixelLeft+"px",s.left=r,o&&(i.left=o)),void 0===a?a:a+""||"auto"});var yt=/alpha\([^)]*\)/i,vt=/opacity\s*=\s*([^)]*)/i,xt=/^(none|table(?!-c[ea]).+)/,bt=new RegExp("^("+Fe+")(.*)$","i"),wt={position:"absolute",visibility:"hidden",display:"block"},Tt={letterSpacing:"0",fontWeight:"400"},Ct=["Webkit","O","Moz","ms"],Et=re.createElement("div").style;pe.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=gt(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":fe.cssFloat?"cssFloat":"styleFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=pe.camelCase(t),u=e.style;if(t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:u[t];if(o=typeof n,"string"===o&&(i=Me.exec(n))&&i[1]&&(n=d(e,t,i),o="number"),null!=n&&n===n&&("number"===o&&(n+=i&&i[3]||(pe.cssNumber[s]?"":"px")),fe.clearCloneStyle||""!==n||0!==t.indexOf("background")||(u[t]="inherit"),!(a&&"set"in a&&void 0===(n=a.set(e,n,r)))))try{u[t]=n}catch(l){}}},css:function(e,t,n,r){var i,o,a,s=pe.camelCase(t);return t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],a&&"get"in a&&(o=a.get(e,!0,n)),void 0===o&&(o=gt(e,t,r)),"normal"===o&&t in Tt&&(o=Tt[t]),""===n||n?(i=parseFloat(o),n===!0||isFinite(i)?i||0:o):o}}),pe.each(["height","width"],function(e,t){pe.cssHooks[t]={get:function(e,n,r){if(n)return xt.test(pe.css(e,"display"))&&0===e.offsetWidth?dt(e,wt,function(){return M(e,t,r)}):M(e,t,r)},set:function(e,n,r){var i=r&&ht(e);return _(e,n,r?F(e,t,r,fe.boxSizing&&"border-box"===pe.css(e,"boxSizing",!1,i),i):0)}}}),fe.opacity||(pe.cssHooks.opacity={get:function(e,t){return vt.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=pe.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===pe.trim(o.replace(yt,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=yt.test(o)?o.replace(yt,i):o+" "+i)}}),pe.cssHooks.marginRight=L(fe.reliableMarginRight,function(e,t){if(t)return dt(e,{display:"inline-block"},gt,[e,"marginRight"])}),pe.cssHooks.marginLeft=L(fe.reliableMarginLeft,function(e,t){if(t)return(parseFloat(gt(e,"marginLeft"))||(pe.contains(e.ownerDocument,e)?e.getBoundingClientRect().left-dt(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}):0))+"px"}),pe.each({margin:"",padding:"",border:"Width"},function(e,t){pe.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+Oe[r]+t]=o[r]||o[r-2]||o[0];return i}},ct.test(e)||(pe.cssHooks[e+t].set=_)}),pe.fn.extend({css:function(e,t){return Pe(this,function(e,t,n){var r,i,o={},a=0;if(pe.isArray(t)){for(r=ht(e),i=t.length;a1)},show:function(){return q(this,!0)},hide:function(){return q(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){Re(this)?pe(this).show():pe(this).hide()})}}),pe.Tween=O,O.prototype={constructor:O,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||pe.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(pe.cssNumber[n]?"":"px")},cur:function(){var e=O.propHooks[this.prop];return e&&e.get?e.get(this):O.propHooks._default.get(this)},run:function(e){var t,n=O.propHooks[this.prop];return this.options.duration?this.pos=t=pe.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):O.propHooks._default.set(this),this}},O.prototype.init.prototype=O.prototype,O.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=pe.css(e.elem,e.prop,""),t&&"auto"!==t?t:0)},set:function(e){pe.fx.step[e.prop]?pe.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[pe.cssProps[e.prop]]&&!pe.cssHooks[e.prop]?e.elem[e.prop]=e.now:pe.style(e.elem,e.prop,e.now+e.unit)}}},O.propHooks.scrollTop=O.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},pe.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},pe.fx=O.prototype.init,pe.fx.step={};var Nt,kt,St=/^(?:toggle|show|hide)$/,At=/queueHooks$/;pe.Animation=pe.extend($,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return d(n.elem,e,Me.exec(t),n),n}]},tweener:function(e,t){pe.isFunction(e)?(t=e,e=["*"]):e=e.match(De);for(var n,r=0,i=e.length;r
                                            a",e=n.getElementsByTagName("a")[0],t.setAttribute("type","checkbox"),n.appendChild(t),e=n.getElementsByTagName("a")[0],e.style.cssText="top:1px",fe.getSetAttribute="t"!==n.className,fe.style=/top/.test(e.getAttribute("style")),fe.hrefNormalized="/a"===e.getAttribute("href"),fe.checkOn=!!t.value,fe.optSelected=i.selected,fe.enctype=!!re.createElement("form").enctype,r.disabled=!0,fe.optDisabled=!i.disabled,t=re.createElement("input"),t.setAttribute("value",""),fe.input=""===t.getAttribute("value"),t.value="t",t.setAttribute("type","radio"),fe.radioValue="t"===t.value}();var Dt=/\r/g,jt=/[\x20\t\r\n\f]+/g;pe.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=pe.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,pe(this).val()):e,null==i?i="":"number"==typeof i?i+="":pe.isArray(i)&&(i=pe.map(i,function(e){return null==e?"":e+""})),t=pe.valHooks[this.type]||pe.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return t=pe.valHooks[i.type]||pe.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:(n=i.value,"string"==typeof n?n.replace(Dt,""):null==n?"":n)}}}),pe.extend({valHooks:{option:{get:function(e){var t=pe.find.attr(e,"value");return null!=t?t:pe.trim(pe.text(e)).replace(jt," ")}},select:{get:function(e){for(var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||i<0,a=o?null:[],s=o?i+1:r.length,u=i<0?s:o?i:0;u-1)try{r.selected=n=!0}catch(s){r.scrollHeight}else r.selected=!1;return n||(e.selectedIndex=-1),i}}}}),pe.each(["radio","checkbox"],function(){pe.valHooks[this]={set:function(e,t){if(pe.isArray(t))return e.checked=pe.inArray(pe(e).val(),t)>-1}},fe.checkOn||(pe.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Lt,Ht,qt=pe.expr.attrHandle,_t=/^(?:checked|selected)$/i,Ft=fe.getSetAttribute,Mt=fe.input;pe.fn.extend({attr:function(e,t){return Pe(this,pe.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){pe.removeAttr(this,e)})}}),pe.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?pe.prop(e,t,n):(1===o&&pe.isXMLDoc(e)||(t=t.toLowerCase(),i=pe.attrHooks[t]||(pe.expr.match.bool.test(t)?Ht:Lt)),void 0!==n?null===n?void pe.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:(r=pe.find.attr(e,t),null==r?void 0:r))},attrHooks:{type:{set:function(e,t){if(!fe.radioValue&&"radio"===t&&pe.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(De);if(o&&1===e.nodeType)for(;n=o[i++];)r=pe.propFix[n]||n,pe.expr.match.bool.test(n)?Mt&&Ft||!_t.test(n)?e[r]=!1:e[pe.camelCase("default-"+n)]=e[r]=!1:pe.attr(e,n,""),e.removeAttribute(Ft?n:r)}}),Ht={set:function(e,t,n){return t===!1?pe.removeAttr(e,n):Mt&&Ft||!_t.test(n)?e.setAttribute(!Ft&&pe.propFix[n]||n,n):e[pe.camelCase("default-"+n)]=e[n]=!0,n}},pe.each(pe.expr.match.bool.source.match(/\w+/g),function(e,t){var n=qt[t]||pe.find.attr;Mt&&Ft||!_t.test(t)?qt[t]=function(e,t,r){var i,o;return r||(o=qt[t],qt[t]=i,i=null!=n(e,t,r)?t.toLowerCase():null,qt[t]=o),i}:qt[t]=function(e,t,n){if(!n)return e[pe.camelCase("default-"+t)]?t.toLowerCase():null}}),Mt&&Ft||(pe.attrHooks.value={set:function(e,t,n){return pe.nodeName(e,"input")?void(e.defaultValue=t):Lt&&Lt.set(e,t,n)}}),Ft||(Lt={set:function(e,t,n){var r=e.getAttributeNode(n);if(r||e.setAttributeNode(r=e.ownerDocument.createAttribute(n)),r.value=t+="","value"===n||t===e.getAttribute(n))return t}},qt.id=qt.name=qt.coords=function(e,t,n){var r;if(!n)return(r=e.getAttributeNode(t))&&""!==r.value?r.value:null},pe.valHooks.button={get:function(e,t){var n=e.getAttributeNode(t);if(n&&n.specified)return n.value},set:Lt.set},pe.attrHooks.contenteditable={set:function(e,t,n){Lt.set(e,""!==t&&t,n)}},pe.each(["width","height"],function(e,t){pe.attrHooks[t]={set:function(e,n){if(""===n)return e.setAttribute(t,"auto"),n}}})),fe.style||(pe.attrHooks.style={get:function(e){return e.style.cssText||void 0},set:function(e,t){return e.style.cssText=t+""}});var Ot=/^(?:input|select|textarea|button|object)$/i,Rt=/^(?:a|area)$/i;pe.fn.extend({prop:function(e,t){return Pe(this,pe.prop,e,t,arguments.length>1)},removeProp:function(e){return e=pe.propFix[e]||e,this.each(function(){try{this[e]=void 0,delete this[e]}catch(t){}})}}),pe.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&pe.isXMLDoc(e)||(t=pe.propFix[t]||t,i=pe.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=pe.find.attr(e,"tabindex");return t?parseInt(t,10):Ot.test(e.nodeName)||Rt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),fe.hrefNormalized||pe.each(["href","src"],function(e,t){pe.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),fe.optSelected||(pe.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),pe.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){pe.propFix[this.toLowerCase()]=this}),fe.enctype||(pe.propFix.enctype="encoding");var Pt=/[\t\r\n\f]/g;pe.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).addClass(e.call(this,t,z(this)))});if("string"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(" "+i+" ").replace(Pt," ")){for(a=0;o=t[a++];)r.indexOf(" "+o+" ")<0&&(r+=o+" ");s=pe.trim(r),i!==s&&pe.attr(n,"class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).removeClass(e.call(this,t,z(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(" "+i+" ").replace(Pt," ")){for(a=0;o=t[a++];)for(;r.indexOf(" "+o+" ")>-1;)r=r.replace(" "+o+" "," ");s=pe.trim(r),i!==s&&pe.attr(n,"class",s)}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):pe.isFunction(e)?this.each(function(n){pe(this).toggleClass(e.call(this,n,z(this),t),t)}):this.each(function(){var t,r,i,o;if("string"===n)for(r=0,i=pe(this),o=e.match(De)||[];t=o[r++];)i.hasClass(t)?i.removeClass(t):i.addClass(t);else void 0!==e&&"boolean"!==n||(t=z(this),t&&pe._data(this,"__className__",t),pe.attr(this,"class",t||e===!1?"":pe._data(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;for(t=" "+e+" ";n=this[r++];)if(1===n.nodeType&&(" "+z(n)+" ").replace(Pt," ").indexOf(t)>-1)return!0;return!1}}),pe.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){pe.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),pe.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}});var Bt=e.location,Wt=pe.now(),It=/\?/,$t=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;pe.parseJSON=function(t){if(e.JSON&&e.JSON.parse)return e.JSON.parse(t+"");var n,r=null,i=pe.trim(t+"");return i&&!pe.trim(i.replace($t,function(e,t,i,o){return n&&t&&(r=0),0===r?e:(n=i||t,r+=!o-!i,"")}))?Function("return "+i)():pe.error("Invalid JSON: "+t)},pe.parseXML=function(t){var n,r;if(!t||"string"!=typeof t)return null;try{e.DOMParser?(r=new e.DOMParser,n=r.parseFromString(t,"text/xml")):(n=new e.ActiveXObject("Microsoft.XMLDOM"),n.async="false",n.loadXML(t))}catch(i){n=void 0}return n&&n.documentElement&&!n.getElementsByTagName("parsererror").length||pe.error("Invalid XML: "+t),n};var zt=/#.*$/,Xt=/([?&])_=[^&]*/,Ut=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Vt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Yt=/^(?:GET|HEAD)$/,Jt=/^\/\//,Gt=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Kt={},Qt={},Zt="*/".concat("*"),en=Bt.href,tn=Gt.exec(en.toLowerCase())||[];pe.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:en,type:"GET",isLocal:Vt.test(tn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Zt,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":pe.parseJSON,"text xml":pe.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?V(V(e,pe.ajaxSettings),t):V(pe.ajaxSettings,e)},ajaxPrefilter:X(Kt),ajaxTransport:X(Qt),ajax:function(t,n){function r(t,n,r,i){var o,f,v,x,w,C=n;2!==b&&(b=2,u&&e.clearTimeout(u),c=void 0,s=i||"",T.readyState=t>0?4:0,o=t>=200&&t<300||304===t,r&&(x=Y(d,T,r)),x=J(d,x,T,o),o?(d.ifModified&&(w=T.getResponseHeader("Last-Modified"),w&&(pe.lastModified[a]=w),w=T.getResponseHeader("etag"),w&&(pe.etag[a]=w)),204===t||"HEAD"===d.type?C="nocontent":304===t?C="notmodified":(C=x.state,f=x.data,v=x.error,o=!v)):(v=C,!t&&C||(C="error",t<0&&(t=0))),T.status=t,T.statusText=(n||C)+"",o?g.resolveWith(p,[f,C,T]):g.rejectWith(p,[T,C,v]),T.statusCode(y),y=void 0,l&&h.trigger(o?"ajaxSuccess":"ajaxError",[T,d,o?f:v]),m.fireWith(p,[T,C]),l&&(h.trigger("ajaxComplete",[T,d]),--pe.active||pe.event.trigger("ajaxStop")))}"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,d=pe.ajaxSetup({},n),p=d.context||d,h=d.context&&(p.nodeType||p.jquery)?pe(p):pe.event,g=pe.Deferred(),m=pe.Callbacks("once memory"),y=d.statusCode||{},v={},x={},b=0,w="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!f)for(f={};t=Ut.exec(s);)f[t[1].toLowerCase()]=t[2];t=f[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?s:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=x[n]=x[n]||e,v[e]=t),this},overrideMimeType:function(e){return b||(d.mimeType=e),this},statusCode:function(e){var t;if(e)if(b<2)for(t in e)y[t]=[y[t],e[t]];else T.always(e[T.status]);return this},abort:function(e){var t=e||w;return c&&c.abort(t),r(0,t),this}};if(g.promise(T).complete=m.add,T.success=T.done,T.error=T.fail,d.url=((t||d.url||en)+"").replace(zt,"").replace(Jt,tn[1]+"//"),d.type=n.method||n.type||d.method||d.type,d.dataTypes=pe.trim(d.dataType||"*").toLowerCase().match(De)||[""],null==d.crossDomain&&(i=Gt.exec(d.url.toLowerCase()),d.crossDomain=!(!i||i[1]===tn[1]&&i[2]===tn[2]&&(i[3]||("http:"===i[1]?"80":"443"))===(tn[3]||("http:"===tn[1]?"80":"443")))),d.data&&d.processData&&"string"!=typeof d.data&&(d.data=pe.param(d.data,d.traditional)),U(Kt,d,n,T),2===b)return T;l=pe.event&&d.global,l&&0===pe.active++&&pe.event.trigger("ajaxStart"),d.type=d.type.toUpperCase(),d.hasContent=!Yt.test(d.type),a=d.url,d.hasContent||(d.data&&(a=d.url+=(It.test(a)?"&":"?")+d.data,delete d.data),d.cache===!1&&(d.url=Xt.test(a)?a.replace(Xt,"$1_="+Wt++):a+(It.test(a)?"&":"?")+"_="+Wt++)),d.ifModified&&(pe.lastModified[a]&&T.setRequestHeader("If-Modified-Since",pe.lastModified[a]),pe.etag[a]&&T.setRequestHeader("If-None-Match",pe.etag[a])),(d.data&&d.hasContent&&d.contentType!==!1||n.contentType)&&T.setRequestHeader("Content-Type",d.contentType),T.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+("*"!==d.dataTypes[0]?", "+Zt+"; q=0.01":""):d.accepts["*"]);for(o in d.headers)T.setRequestHeader(o,d.headers[o]);if(d.beforeSend&&(d.beforeSend.call(p,T,d)===!1||2===b))return T.abort();w="abort";for(o in{success:1,error:1,complete:1})T[o](d[o]);if(c=U(Qt,d,n,T)){if(T.readyState=1,l&&h.trigger("ajaxSend",[T,d]),2===b)return T;d.async&&d.timeout>0&&(u=e.setTimeout(function(){T.abort("timeout")},d.timeout));try{b=1,c.send(v,r)}catch(C){if(!(b<2))throw C;r(-1,C)}}else r(-1,"No Transport");return T},getJSON:function(e,t,n){return pe.get(e,t,n,"json")},getScript:function(e,t){return pe.get(e,void 0,t,"script")}}),pe.each(["get","post"],function(e,t){pe[t]=function(e,n,r,i){return pe.isFunction(n)&&(i=i||r,r=n,n=void 0),pe.ajax(pe.extend({url:e,type:t,dataType:i,data:n,success:r},pe.isPlainObject(e)&&e))}}),pe._evalUrl=function(e){return pe.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},pe.fn.extend({wrapAll:function(e){if(pe.isFunction(e))return this.each(function(t){pe(this).wrapAll(e.call(this,t))});if(this[0]){var t=pe(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstChild&&1===e.firstChild.nodeType;)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return pe.isFunction(e)?this.each(function(t){pe(this).wrapInner(e.call(this,t))}):this.each(function(){var t=pe(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=pe.isFunction(e);return this.each(function(n){pe(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){pe.nodeName(this,"body")||pe(this).replaceWith(this.childNodes)}).end()}}),pe.expr.filters.hidden=function(e){return fe.reliableHiddenOffsets()?e.offsetWidth<=0&&e.offsetHeight<=0&&!e.getClientRects().length:K(e)},pe.expr.filters.visible=function(e){return!pe.expr.filters.hidden(e)};var nn=/%20/g,rn=/\[\]$/,on=/\r?\n/g,an=/^(?:submit|button|image|reset|file)$/i,sn=/^(?:input|select|textarea|keygen)/i;pe.param=function(e,t){var n,r=[],i=function(e,t){t=pe.isFunction(t)?t():null==t?"":t,r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(void 0===t&&(t=pe.ajaxSettings&&pe.ajaxSettings.traditional),pe.isArray(e)||e.jquery&&!pe.isPlainObject(e))pe.each(e,function(){i(this.name,this.value)});else for(n in e)Q(n,e[n],t,i);return r.join("&").replace(nn,"+")},pe.fn.extend({serialize:function(){return pe.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=pe.prop(this,"elements");return e?pe.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!pe(this).is(":disabled")&&sn.test(this.nodeName)&&!an.test(e)&&(this.checked||!Be.test(e))}).map(function(e,t){var n=pe(this).val();return null==n?null:pe.isArray(n)?pe.map(n,function(e){return{name:t.name,value:e.replace(on,"\r\n")}}):{name:t.name,value:n.replace(on,"\r\n")}}).get()}}),pe.ajaxSettings.xhr=void 0!==e.ActiveXObject?function(){return this.isLocal?ee():re.documentMode>8?Z():/^(get|post|head|put|delete|options)$/i.test(this.type)&&Z()||ee()}:Z;var un=0,ln={},cn=pe.ajaxSettings.xhr();e.attachEvent&&e.attachEvent("onunload",function(){for(var e in ln)ln[e](void 0,!0)}),fe.cors=!!cn&&"withCredentials"in cn,cn=fe.ajax=!!cn,cn&&pe.ajaxTransport(function(t){if(!t.crossDomain||fe.cors){var n;return{send:function(r,i){var o,a=t.xhr(),s=++un;if(a.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(o in t.xhrFields)a[o]=t.xhrFields[o];t.mimeType&&a.overrideMimeType&&a.overrideMimeType(t.mimeType),t.crossDomain||r["X-Requested-With"]||(r["X-Requested-With"]="XMLHttpRequest");for(o in r)void 0!==r[o]&&a.setRequestHeader(o,r[o]+"");a.send(t.hasContent&&t.data||null),n=function(e,r){var o,u,l;if(n&&(r||4===a.readyState))if(delete ln[s],n=void 0,a.onreadystatechange=pe.noop,r)4!==a.readyState&&a.abort();else{l={},o=a.status,"string"==typeof a.responseText&&(l.text=a.responseText);try{u=a.statusText}catch(c){u=""}o||!t.isLocal||t.crossDomain?1223===o&&(o=204):o=l.text?200:404}l&&i(o,u,l,a.getAllResponseHeaders())},t.async?4===a.readyState?e.setTimeout(n):a.onreadystatechange=ln[s]=n:n()},abort:function(){n&&n(void 0,!0)}}}}),pe.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return pe.globalEval(e),e}}}),pe.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),pe.ajaxTransport("script",function(e){if(e.crossDomain){var t,n=re.head||pe("head")[0]||re.documentElement;return{send:function(r,i){t=re.createElement("script"),t.async=!0,e.scriptCharset&&(t.charset=e.scriptCharset),t.src=e.url,t.onload=t.onreadystatechange=function(e,n){(n||!t.readyState||/loaded|complete/.test(t.readyState))&&(t.onload=t.onreadystatechange=null,t.parentNode&&t.parentNode.removeChild(t),t=null,n||i(200,"success"))},n.insertBefore(t,n.firstChild)},abort:function(){t&&t.onload(void 0,!0)}}}});var fn=[],dn=/(=)\?(?=&|$)|\?\?/;pe.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=fn.pop()||pe.expando+"_"+Wt++;return this[e]=!0,e}}),pe.ajaxPrefilter("json jsonp",function(t,n,r){var i,o,a,s=t.jsonp!==!1&&(dn.test(t.url)?"url":"string"==typeof t.data&&0===(t.contentType||"").indexOf("application/x-www-form-urlencoded")&&dn.test(t.data)&&"data");if(s||"jsonp"===t.dataTypes[0])return i=t.jsonpCallback=pe.isFunction(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(dn,"$1"+i):t.jsonp!==!1&&(t.url+=(It.test(t.url)?"&":"?")+t.jsonp+"="+i),t.converters["script json"]=function(){return a||pe.error(i+" was not called"),a[0]},t.dataTypes[0]="json",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?pe(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,fn.push(i)),a&&pe.isFunction(o)&&o(a[0]),a=o=void 0}),"script"}),pe.parseHTML=function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||re;var r=Te.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=y([e],t,i),i&&i.length&&pe(i).remove(),pe.merge([],r.childNodes))};var pn=pe.fn.load;return pe.fn.load=function(e,t,n){if("string"!=typeof e&&pn)return pn.apply(this,arguments);var r,i,o,a=this,s=e.indexOf(" ");return s>-1&&(r=pe.trim(e.slice(s,e.length)),e=e.slice(0,s)),pe.isFunction(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),a.length>0&&pe.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?pe("
                                            ").append(pe.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},pe.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){pe.fn[t]=function(e){return this.on(t,e)}}),pe.expr.filters.animated=function(e){return pe.grep(pe.timers,function(t){return e===t.elem}).length},pe.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l,c=pe.css(e,"position"),f=pe(e),d={};"static"===c&&(e.style.position="relative"),s=f.offset(),o=pe.css(e,"top"),u=pe.css(e,"left"),l=("absolute"===c||"fixed"===c)&&pe.inArray("auto",[o,u])>-1,l?(r=f.position(),a=r.top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),pe.isFunction(t)&&(t=t.call(e,n,pe.extend({},s))),null!=t.top&&(d.top=t.top-s.top+a),null!=t.left&&(d.left=t.left-s.left+i),"using"in t?t.using.call(e,d):f.css(d)}},pe.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){pe.offset.setOffset(this,e,t)});var t,n,r={top:0,left:0},i=this[0],o=i&&i.ownerDocument;if(o)return t=o.documentElement,pe.contains(t,i)?("undefined"!=typeof i.getBoundingClientRect&&(r=i.getBoundingClientRect()),n=te(o),{top:r.top+(n.pageYOffset||t.scrollTop)-(t.clientTop||0),left:r.left+(n.pageXOffset||t.scrollLeft)-(t.clientLeft||0)}):r},position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===pe.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),pe.nodeName(e[0],"html")||(n=e.offset()),n.top+=pe.css(e[0],"borderTopWidth",!0),n.left+=pe.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-pe.css(r,"marginTop",!0),left:t.left-n.left-pe.css(r,"marginLeft",!0)}}},offsetParent:function(){ -return this.map(function(){for(var e=this.offsetParent;e&&!pe.nodeName(e,"html")&&"static"===pe.css(e,"position");)e=e.offsetParent;return e||pt})}}),pe.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,t){var n=/Y/.test(t);pe.fn[e]=function(r){return Pe(this,function(e,r,i){var o=te(e);return void 0===i?o?t in o?o[t]:o.document.documentElement[r]:e[r]:void(o?o.scrollTo(n?pe(o).scrollLeft():i,n?i:pe(o).scrollTop()):e[r]=i)},e,r,arguments.length,null)}}),pe.each(["top","left"],function(e,t){pe.cssHooks[t]=L(fe.pixelPosition,function(e,n){if(n)return n=gt(e,t),ft.test(n)?pe(e).position()[t]+"px":n})}),pe.each({Height:"height",Width:"width"},function(e,t){pe.each({padding:"inner"+e,content:t,"":"outer"+e},function(n,r){pe.fn[r]=function(r,i){var o=arguments.length&&(n||"boolean"!=typeof r),a=n||(r===!0||i===!0?"margin":"border");return Pe(this,function(t,n,r){var i;return pe.isWindow(t)?t.document.documentElement["client"+e]:9===t.nodeType?(i=t.documentElement,Math.max(t.body["scroll"+e],i["scroll"+e],t.body["offset"+e],i["offset"+e],i["client"+e])):void 0===r?pe.css(t,n,a):pe.style(t,n,r,a)},t,o?r:void 0,o,null)}})}),pe.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),pe.fn.size=function(){return this.length},pe.fn.andSelf=pe.fn.addBack,layui.define(function(e){layui.$=pe,e("jquery",pe)}),pe});!function(e,t){"use strict";var i,n,a=e.layui&&layui.define,o={getPath:function(){var t=document.currentScript?document.currentScript.src:function(){for(var e,t=document.scripts,i=t.length-1,n=i;n>0;n--)if("interactive"===t[n].readyState){e=t[n].src;break}return e||t[i].src}(),i=e.LAYUI_GLOBAL||{};return i.layer_dir||t.substring(0,t.lastIndexOf("/")+1)}(),config:{},end:{},minIndex:0,minLeft:[],btn:["确定","取消"],type:["dialog","page","iframe","loading","tips"],getStyle:function(t,i){var n=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return n[n.getPropertyValue?"getPropertyValue":"getAttribute"](i)},link:function(t,i,n){if(r.path){var a=document.getElementsByTagName("head")[0],s=document.createElement("link");"string"==typeof i&&(n=i);var l=(n||t).replace(/\.|\//g,""),f="layuicss-"+l,c="creating",u=0;s.rel="stylesheet",s.href=r.path+t,s.id=f,document.getElementById(f)||a.appendChild(s),"function"==typeof i&&!function d(t){var n=100,a=document.getElementById(f);return++u>1e4/n?e.console&&console.error(l+".css: Invalid"):void(1989===parseInt(o.getStyle(a,"width"))?(t===c&&a.removeAttribute("lay-status"),a.getAttribute("lay-status")===c?setTimeout(d,n):i()):(a.setAttribute("lay-status",c),setTimeout(function(){d(c)},n)))}()}}},r={v:"3.5.1",ie:function(){var t=navigator.userAgent.toLowerCase();return!!(e.ActiveXObject||"ActiveXObject"in e)&&((t.match(/msie\s(\d+)/)||[])[1]||"11")}(),index:e.layer&&e.layer.v?1e5:0,path:o.getPath,config:function(e,t){return e=e||{},r.cache=o.config=i.extend({},o.config,e),r.path=o.config.path||r.path,"string"==typeof e.extend&&(e.extend=[e.extend]),o.config.path&&r.ready(),e.extend?(a?layui.addcss("modules/layer/"+e.extend):o.link("theme/"+e.extend),this):this},ready:function(e){var t="layer",i="",n=(a?"modules/layer/":"theme/")+"default/layer.css?v="+r.v+i;return a?layui.addcss(n,e,t):o.link(n,e,t),this},alert:function(e,t,n){var a="function"==typeof t;return a&&(n=t),r.open(i.extend({content:e,yes:n},a?{}:t))},confirm:function(e,t,n,a){var s="function"==typeof t;return s&&(a=n,n=t),r.open(i.extend({content:e,btn:o.btn,yes:n,btn2:a},s?{}:t))},msg:function(e,n,a){var s="function"==typeof n,f=o.config.skin,c=(f?f+" "+f+"-msg":"")||"layui-layer-msg",u=l.anim.length-1;return s&&(a=n),r.open(i.extend({content:e,time:3e3,shade:!1,skin:c,title:!1,closeBtn:!1,btn:!1,resize:!1,end:a},s&&!o.config.skin?{skin:c+" layui-layer-hui",anim:u}:function(){return n=n||{},(n.icon===-1||n.icon===t&&!o.config.skin)&&(n.skin=c+" "+(n.skin||"layui-layer-hui")),n}()))},load:function(e,t){return r.open(i.extend({type:3,icon:e||0,resize:!1,shade:.01},t))},tips:function(e,t,n){return r.open(i.extend({type:4,content:[e,t],closeBtn:!1,time:3e3,shade:!1,resize:!1,fixed:!1,maxWidth:260},n))}},s=function(e){var t=this,a=function(){t.creat()};t.index=++r.index,t.config.maxWidth=i(n).width()-30,t.config=i.extend({},t.config,o.config,e),document.body?a():setTimeout(function(){a()},30)};s.pt=s.prototype;var l=["layui-layer",".layui-layer-title",".layui-layer-main",".layui-layer-dialog","layui-layer-iframe","layui-layer-content","layui-layer-btn","layui-layer-close"];l.anim=["layer-anim-00","layer-anim-01","layer-anim-02","layer-anim-03","layer-anim-04","layer-anim-05","layer-anim-06"],l.SHADE="layui-layer-shade",l.MOVE="layui-layer-move",s.pt.config={type:0,shade:.3,fixed:!0,move:l[1],title:"信息",offset:"auto",area:"auto",closeBtn:1,time:0,zIndex:19891014,maxWidth:360,anim:0,isOutAnim:!0,minStack:!0,icon:-1,moveType:1,resize:!0,scrollbar:!0,tips:2},s.pt.vessel=function(e,t){var n=this,a=n.index,r=n.config,s=r.zIndex+a,f="object"==typeof r.title,c=r.maxmin&&(1===r.type||2===r.type),u=r.title?'
                                            '+(f?r.title[0]:r.title)+"
                                            ":"";return r.zIndex=s,t([r.shade?'
                                            ':"",'
                                            '+(e&&2!=r.type?"":u)+'
                                            '+(0==r.type&&r.icon!==-1?'':"")+(1==r.type&&e?"":r.content||"")+'
                                            '+function(){var e=c?'':"";return r.closeBtn&&(e+=''),e}()+""+(r.btn?function(){var e="";"string"==typeof r.btn&&(r.btn=[r.btn]);for(var t=0,i=r.btn.length;t'+r.btn[t]+"";return'
                                            '+e+"
                                            "}():"")+(r.resize?'':"")+"
                                            "],u,i('
                                            ')),n},s.pt.creat=function(){var e=this,t=e.config,a=e.index,s=t.content,f="object"==typeof s,c=i("body");if(!t.id||!i("#"+t.id)[0]){switch("string"==typeof t.area&&(t.area="auto"===t.area?["",""]:[t.area,""]),t.shift&&(t.anim=t.shift),6==r.ie&&(t.fixed=!1),t.type){case 0:t.btn="btn"in t?t.btn:o.btn[0],r.closeAll("dialog");break;case 2:var s=t.content=f?t.content:[t.content||"","auto"];t.content='';break;case 3:delete t.title,delete t.closeBtn,t.icon===-1&&0===t.icon,r.closeAll("loading");break;case 4:f||(t.content=[t.content,"body"]),t.follow=t.content[1],t.content=t.content[0]+'',delete t.title,t.tips="object"==typeof t.tips?t.tips:[t.tips,!0],t.tipsMore||r.closeAll("tips")}if(e.vessel(f,function(n,r,u){c.append(n[0]),f?function(){2==t.type||4==t.type?function(){i("body").append(n[1])}():function(){s.parents("."+l[0])[0]||(s.data("display",s.css("display")).show().addClass("layui-layer-wrap").wrap(n[1]),i("#"+l[0]+a).find("."+l[5]).before(r))}()}():c.append(n[1]),i("#"+l.MOVE)[0]||c.append(o.moveElem=u),e.layero=i("#"+l[0]+a),e.shadeo=i("#"+l.SHADE+a),t.scrollbar||l.html.css("overflow","hidden").attr("layer-full",a)}).auto(a),e.shadeo.css({"background-color":t.shade[1]||"#000",opacity:t.shade[0]||t.shade}),2==t.type&&6==r.ie&&e.layero.find("iframe").attr("src",s[0]),4==t.type?e.tips():function(){e.offset(),parseInt(o.getStyle(document.getElementById(l.MOVE),"z-index"))||function(){e.layero.css("visibility","hidden"),r.ready(function(){e.offset(),e.layero.css("visibility","visible")})}()}(),t.fixed&&n.on("resize",function(){e.offset(),(/^\d+%$/.test(t.area[0])||/^\d+%$/.test(t.area[1]))&&e.auto(a),4==t.type&&e.tips()}),t.time<=0||setTimeout(function(){r.close(e.index)},t.time),e.move().callback(),l.anim[t.anim]){var u="layer-anim "+l.anim[t.anim];e.layero.addClass(u).one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend",function(){i(this).removeClass(u)})}t.isOutAnim&&e.layero.data("isOutAnim",!0)}},s.pt.auto=function(e){var t=this,a=t.config,o=i("#"+l[0]+e);""===a.area[0]&&a.maxWidth>0&&(r.ie&&r.ie<8&&a.btn&&o.width(o.innerWidth()),o.outerWidth()>a.maxWidth&&o.width(a.maxWidth));var s=[o.innerWidth(),o.innerHeight()],f=o.find(l[1]).outerHeight()||0,c=o.find("."+l[6]).outerHeight()||0,u=function(e){e=o.find(e),e.height(s[1]-f-c-2*(0|parseFloat(e.css("padding-top"))))};switch(a.type){case 2:u("iframe");break;default:""===a.area[1]?a.maxHeight>0&&o.outerHeight()>a.maxHeight?(s[1]=a.maxHeight,u("."+l[5])):a.fixed&&s[1]>=n.height()&&(s[1]=n.height(),u("."+l[5])):u("."+l[5])}return t},s.pt.offset=function(){var e=this,t=e.config,i=e.layero,a=[i.outerWidth(),i.outerHeight()],o="object"==typeof t.offset;e.offsetTop=(n.height()-a[1])/2,e.offsetLeft=(n.width()-a[0])/2,o?(e.offsetTop=t.offset[0],e.offsetLeft=t.offset[1]||e.offsetLeft):"auto"!==t.offset&&("t"===t.offset?e.offsetTop=0:"r"===t.offset?e.offsetLeft=n.width()-a[0]:"b"===t.offset?e.offsetTop=n.height()-a[1]:"l"===t.offset?e.offsetLeft=0:"lt"===t.offset?(e.offsetTop=0,e.offsetLeft=0):"lb"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=0):"rt"===t.offset?(e.offsetTop=0,e.offsetLeft=n.width()-a[0]):"rb"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=n.width()-a[0]):e.offsetTop=t.offset),t.fixed||(e.offsetTop=/%$/.test(e.offsetTop)?n.height()*parseFloat(e.offsetTop)/100:parseFloat(e.offsetTop),e.offsetLeft=/%$/.test(e.offsetLeft)?n.width()*parseFloat(e.offsetLeft)/100:parseFloat(e.offsetLeft),e.offsetTop+=n.scrollTop(),e.offsetLeft+=n.scrollLeft()),i.attr("minLeft")&&(e.offsetTop=n.height()-(i.find(l[1]).outerHeight()||0),e.offsetLeft=i.css("left")),i.css({top:e.offsetTop,left:e.offsetLeft})},s.pt.tips=function(){var e=this,t=e.config,a=e.layero,o=[a.outerWidth(),a.outerHeight()],r=i(t.follow);r[0]||(r=i("body"));var s={width:r.outerWidth(),height:r.outerHeight(),top:r.offset().top,left:r.offset().left},f=a.find(".layui-layer-TipsG"),c=t.tips[0];t.tips[1]||f.remove(),s.autoLeft=function(){s.left+o[0]-n.width()>0?(s.tipLeft=s.left+s.width-o[0],f.css({right:12,left:"auto"})):s.tipLeft=s.left},s.where=[function(){s.autoLeft(),s.tipTop=s.top-o[1]-10,f.removeClass("layui-layer-TipsB").addClass("layui-layer-TipsT").css("border-right-color",t.tips[1])},function(){s.tipLeft=s.left+s.width+10,s.tipTop=s.top,f.removeClass("layui-layer-TipsL").addClass("layui-layer-TipsR").css("border-bottom-color",t.tips[1])},function(){s.autoLeft(),s.tipTop=s.top+s.height+10,f.removeClass("layui-layer-TipsT").addClass("layui-layer-TipsB").css("border-right-color",t.tips[1])},function(){s.tipLeft=s.left-o[0]-10,s.tipTop=s.top,f.removeClass("layui-layer-TipsR").addClass("layui-layer-TipsL").css("border-bottom-color",t.tips[1])}],s.where[c-1](),1===c?s.top-(n.scrollTop()+o[1]+16)<0&&s.where[2]():2===c?n.width()-(s.left+s.width+o[0]+16)>0||s.where[3]():3===c?s.top-n.scrollTop()+s.height+o[1]+16-n.height()>0&&s.where[0]():4===c&&o[0]+16-s.left>0&&s.where[1](),a.find("."+l[5]).css({"background-color":t.tips[1],"padding-right":t.closeBtn?"30px":""}),a.css({left:s.tipLeft-(t.fixed?n.scrollLeft():0),top:s.tipTop-(t.fixed?n.scrollTop():0)})},s.pt.move=function(){var e=this,t=e.config,a=i(document),s=e.layero,l=s.find(t.move),f=s.find(".layui-layer-resize"),c={};return t.move&&l.css("cursor","move"),l.on("mousedown",function(e){e.preventDefault(),t.move&&(c.moveStart=!0,c.offset=[e.clientX-parseFloat(s.css("left")),e.clientY-parseFloat(s.css("top"))],o.moveElem.css("cursor","move").show())}),f.on("mousedown",function(e){e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],c.area=[s.outerWidth(),s.outerHeight()],o.moveElem.css("cursor","se-resize").show()}),a.on("mousemove",function(i){if(c.moveStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1],l="fixed"===s.css("position");if(i.preventDefault(),c.stX=l?0:n.scrollLeft(),c.stY=l?0:n.scrollTop(),!t.moveOut){var f=n.width()-s.outerWidth()+c.stX,u=n.height()-s.outerHeight()+c.stY;af&&(a=f),ou&&(o=u)}s.css({left:a,top:o})}if(t.resize&&c.resizeStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1];i.preventDefault(),r.style(e.index,{width:c.area[0]+a,height:c.area[1]+o}),c.isResize=!0,t.resizing&&t.resizing(s)}}).on("mouseup",function(e){c.moveStart&&(delete c.moveStart,o.moveElem.hide(),t.moveEnd&&t.moveEnd(s)),c.resizeStart&&(delete c.resizeStart,o.moveElem.hide())}),e},s.pt.callback=function(){function e(){var e=a.cancel&&a.cancel(t.index,n);e===!1||r.close(t.index)}var t=this,n=t.layero,a=t.config;t.openLayer(),a.success&&(2==a.type?n.find("iframe").on("load",function(){a.success(n,t.index,t)}):a.success(n,t.index,t)),6==r.ie&&t.IE6(n),n.find("."+l[6]).children("a").on("click",function(){var e=i(this).index();if(0===e)a.yes?a.yes(t.index,n):a.btn1?a.btn1(t.index,n):r.close(t.index);else{var o=a["btn"+(e+1)]&&a["btn"+(e+1)](t.index,n);o===!1||r.close(t.index)}}),n.find("."+l[7]).on("click",e),a.shadeClose&&t.shadeo.on("click",function(){r.close(t.index)}),n.find(".layui-layer-min").on("click",function(){var e=a.min&&a.min(n,t.index);e===!1||r.min(t.index,a)}),n.find(".layui-layer-max").on("click",function(){i(this).hasClass("layui-layer-maxmin")?(r.restore(t.index),a.restore&&a.restore(n,t.index)):(r.full(t.index,a),setTimeout(function(){a.full&&a.full(n,t.index)},100))}),a.end&&(o.end[t.index]=a.end)},o.reselect=function(){i.each(i("select"),function(e,t){var n=i(this);n.parents("."+l[0])[0]||1==n.attr("layer")&&i("."+l[0]).length<1&&n.removeAttr("layer").show(),n=null})},s.pt.IE6=function(e){i("select").each(function(e,t){var n=i(this);n.parents("."+l[0])[0]||"none"===n.css("display")||n.attr({layer:"1"}).hide(),n=null})},s.pt.openLayer=function(){var e=this;r.zIndex=e.config.zIndex,r.setTop=function(e){var t=function(){r.zIndex++,e.css("z-index",r.zIndex+1)};return r.zIndex=parseInt(e[0].style.zIndex),e.on("mousedown",t),r.zIndex}},o.record=function(e){var t=[e.width(),e.height(),e.position().top,e.position().left+parseFloat(e.css("margin-left"))];e.find(".layui-layer-max").addClass("layui-layer-maxmin"),e.attr({area:t})},o.rescollbar=function(e){l.html.attr("layer-full")==e&&(l.html[0].style.removeProperty?l.html[0].style.removeProperty("overflow"):l.html[0].style.removeAttribute("overflow"),l.html.removeAttr("layer-full"))},e.layer=r,r.getChildFrame=function(e,t){return t=t||i("."+l[4]).attr("times"),i("#"+l[0]+t).find("iframe").contents().find(e)},r.getFrameIndex=function(e){return i("#"+e).parents("."+l[4]).attr("times")},r.iframeAuto=function(e){if(e){var t=r.getChildFrame("html",e).outerHeight(),n=i("#"+l[0]+e),a=n.find(l[1]).outerHeight()||0,o=n.find("."+l[6]).outerHeight()||0;n.css({height:t+a+o}),n.find("iframe").css({height:t})}},r.iframeSrc=function(e,t){i("#"+l[0]+e).find("iframe").attr("src",t)},r.style=function(e,t,n){var a=i("#"+l[0]+e),r=a.find(".layui-layer-content"),s=a.attr("type"),f=a.find(l[1]).outerHeight()||0,c=a.find("."+l[6]).outerHeight()||0;a.attr("minLeft");s!==o.type[3]&&s!==o.type[4]&&(n||(parseFloat(t.width)<=260&&(t.width=260),parseFloat(t.height)-f-c<=64&&(t.height=64+f+c)),a.css(t),c=a.find("."+l[6]).outerHeight(),s===o.type[2]?a.find("iframe").css({height:parseFloat(t.height)-f-c}):r.css({height:parseFloat(t.height)-f-c-parseFloat(r.css("padding-top"))-parseFloat(r.css("padding-bottom"))}))},r.min=function(e,t){t=t||{};var a=i("#"+l[0]+e),s=i("#"+l.SHADE+e),f=a.find(l[1]).outerHeight()||0,c=a.attr("minLeft")||181*o.minIndex+"px",u=a.css("position"),d={width:180,height:f,position:"fixed",overflow:"hidden"};o.record(a),o.minLeft[0]&&(c=o.minLeft[0],o.minLeft.shift()),t.minStack&&(d.left=c,d.top=n.height()-f,a.attr("minLeft")||o.minIndex++,a.attr("minLeft",c)),a.attr("position",u),r.style(e,d,!0),a.find(".layui-layer-min").hide(),"page"===a.attr("type")&&a.find(l[4]).hide(),o.rescollbar(e),s.hide()},r.restore=function(e){var t=i("#"+l[0]+e),n=i("#"+l.SHADE+e),a=t.attr("area").split(",");t.attr("type");r.style(e,{width:parseFloat(a[0]),height:parseFloat(a[1]),top:parseFloat(a[2]),left:parseFloat(a[3]),position:t.attr("position"),overflow:"visible"},!0),t.find(".layui-layer-max").removeClass("layui-layer-maxmin"),t.find(".layui-layer-min").show(),"page"===t.attr("type")&&t.find(l[4]).show(),o.rescollbar(e),n.show()},r.full=function(e){var t,a=i("#"+l[0]+e);o.record(a),l.html.attr("layer-full")||l.html.css("overflow","hidden").attr("layer-full",e),clearTimeout(t),t=setTimeout(function(){var t="fixed"===a.css("position");r.style(e,{top:t?0:n.scrollTop(),left:t?0:n.scrollLeft(),width:n.width(),height:n.height()},!0),a.find(".layui-layer-min").hide()},100)},r.title=function(e,t){var n=i("#"+l[0]+(t||r.index)).find(l[1]);n.html(e)},r.close=function(e,t){var n=i("#"+l[0]+e),a=n.attr("type"),s="layer-anim-close";if(n[0]){var f="layui-layer-wrap",c=function(){if(a===o.type[1]&&"object"===n.attr("conType")){n.children(":not(."+l[5]+")").remove();for(var r=n.find("."+f),s=0;s<2;s++)r.unwrap();r.css("display",r.data("display")).removeClass(f)}else{if(a===o.type[2])try{var c=i("#"+l[4]+e)[0];c.contentWindow.document.write(""),c.contentWindow.close(),n.find("."+l[5])[0].removeChild(c)}catch(u){}n[0].innerHTML="",n.remove()}"function"==typeof o.end[e]&&o.end[e](),delete o.end[e],"function"==typeof t&&t()};n.data("isOutAnim")&&n.addClass("layer-anim "+s),i("#layui-layer-moves, #"+l.SHADE+e).remove(),6==r.ie&&o.reselect(),o.rescollbar(e),n.attr("minLeft")&&(o.minIndex--,o.minLeft.push(n.attr("minLeft"))),r.ie&&r.ie<10||!n.data("isOutAnim")?c():setTimeout(function(){c()},200)}},r.closeAll=function(e,t){"function"==typeof e&&(t=e,e=null);var n=i("."+l[0]);i.each(n,function(a){var o=i(this),s=e?o.attr("type")===e:1;s&&r.close(o.attr("times"),a===n.length-1?t:null),s=null}),0===n.length&&"function"==typeof t&&t()};var f=r.cache||{},c=function(e){return f.skin?" "+f.skin+" "+f.skin+"-"+e:""};r.prompt=function(e,t){var a="";if(e=e||{},"function"==typeof e&&(t=e),e.area){var o=e.area;a='style="width: '+o[0]+"; height: "+o[1]+';"',delete e.area}var s,l=2==e.formType?'":function(){return''}(),f=e.success;return delete e.success,r.open(i.extend({type:1,btn:["确定","取消"],content:l,skin:"layui-layer-prompt"+c("prompt"),maxWidth:n.width(),success:function(t){s=t.find(".layui-layer-input"),s.val(e.value||"").focus(),"function"==typeof f&&f(t)},resize:!1,yes:function(i){var n=s.val();""===n?s.focus():n.length>(e.maxlength||500)?r.tips("最多输入"+(e.maxlength||500)+"个字数",s,{tips:1}):t&&t(n,i,s)}},e))},r.tab=function(e){e=e||{};var t=e.tab||{},n="layui-this",a=e.success;return delete e.success,r.open(i.extend({type:1,skin:"layui-layer-tab"+c("tab"),resize:!1,title:function(){var e=t.length,i=1,a="";if(e>0)for(a=''+t[0].title+"";i"+t[i].title+"";return a}(),content:'
                                              '+function(){var e=t.length,i=1,a="";if(e>0)for(a='
                                            • '+(t[0].content||"no content")+"
                                            • ";i'+(t[i].content||"no content")+"";return a}()+"
                                            ",success:function(t){var o=t.find(".layui-layer-title").children(),r=t.find(".layui-layer-tabmain").children();o.on("mousedown",function(t){t.stopPropagation?t.stopPropagation():t.cancelBubble=!0;var a=i(this),o=a.index();a.addClass(n).siblings().removeClass(n),r.eq(o).show().siblings().hide(),"function"==typeof e.change&&e.change(o)}),"function"==typeof a&&a(t)}},e))},r.photos=function(t,n,a){function o(e,t,i){var n=new Image;return n.src=e,n.complete?t(n):(n.onload=function(){n.onload=null,t(n)},void(n.onerror=function(e){n.onerror=null,i(e)}))}var s={};if(t=t||{},t.photos){var l=!("string"==typeof t.photos||t.photos instanceof i),f=l?t.photos:{},u=f.data||[],d=f.start||0;s.imgIndex=(0|d)+1,t.img=t.img||"img";var y=t.success;if(delete t.success,l){if(0===u.length)return r.msg("没有图片")}else{var p=i(t.photos),h=function(){u=[],p.find(t.img).each(function(e){var t=i(this);t.attr("layer-index",e),u.push({alt:t.attr("alt"),pid:t.attr("layer-pid"),src:t.attr("layer-src")||t.attr("src"),thumb:t.attr("src")})})};if(h(),0===u.length)return;if(n||p.on("click",t.img,function(){h();var e=i(this),n=e.attr("layer-index");r.photos(i.extend(t,{photos:{start:n,data:u,tab:t.tab},full:t.full}),!0)}),!n)return}s.imgprev=function(e){s.imgIndex--,s.imgIndex<1&&(s.imgIndex=u.length),s.tabimg(e)},s.imgnext=function(e,t){s.imgIndex++,s.imgIndex>u.length&&(s.imgIndex=1,t)||s.tabimg(e)},s.keyup=function(e){if(!s.end){var t=e.keyCode;e.preventDefault(),37===t?s.imgprev(!0):39===t?s.imgnext(!0):27===t&&r.close(s.index)}},s.tabimg=function(e){if(!(u.length<=1))return f.start=s.imgIndex-1,r.close(s.index),r.photos(t,!0,e)},s.event=function(){s.bigimg.find(".layui-layer-imgprev").on("click",function(e){e.preventDefault(),s.imgprev(!0)}),s.bigimg.find(".layui-layer-imgnext").on("click",function(e){e.preventDefault(),s.imgnext(!0)}),i(document).on("keyup",s.keyup)},s.loadi=r.load(1,{shade:!("shade"in t)&&.9,scrollbar:!1}),o(u[d].src,function(n){r.close(s.loadi),a&&(t.anim=-1),s.index=r.open(i.extend({type:1,id:"layui-layer-photos",area:function(){var a=[n.width,n.height],o=[i(e).width()-100,i(e).height()-100];if(!t.full&&(a[0]>o[0]||a[1]>o[1])){var r=[a[0]/o[0],a[1]/o[1]];r[0]>r[1]?(a[0]=a[0]/r[0],a[1]=a[1]/r[0]):r[0]'+(u[d].alt||'+function(){return u.length>1?'
                                            '+(u[d].alt||"")+""+s.imgIndex+" / "+u.length+"
                                            ":""}()+"
                                            ",success:function(e,i){s.bigimg=e.find(".layui-layer-phimg"),s.imgsee=e.find(".layui-layer-imgbar"),s.event(e),t.tab&&t.tab(u[d],e),"function"==typeof y&&y(e)},end:function(){s.end=!0,i(document).off("keyup",s.keyup)}},t))},function(){r.close(s.loadi),r.msg("当前图片地址异常
                                            是否继续查看下一张?",{time:3e4,btn:["下一张","不看了"],yes:function(){u.length>1&&s.imgnext(!0,!0)}})})}},o.run=function(t){i=t,n=i(e),l.html=i("html"),r.open=function(e){var t=new s(e);return t.index}},e.layui&&layui.define?(r.ready(),layui.define("jquery",function(t){r.path=layui.cache.dir,o.run(layui.$),e.layer=r,t("layer",r)})):"function"==typeof define&&define.amd?define(["jquery"],function(){return o.run(e.jQuery),r}):function(){r.ready(),o.run(e.jQuery)}()}(window);layui.define("jquery",function(e){"use strict";var t=layui.$,i=layui.hint(),n={fixbar:function(e){var i,n,r="layui-fixbar",a="layui-fixbar-top",o=t(document),l=t("body");e=t.extend({showHeight:200},e),e.bar1=e.bar1===!0?"":e.bar1,e.bar2=e.bar2===!0?"":e.bar2,e.bgcolor=e.bgcolor?"background-color:"+e.bgcolor:"";var c=[e.bar1,e.bar2,""],g=t(['
                                              ',e.bar1?'
                                            • '+c[0]+"
                                            • ":"",e.bar2?'
                                            • '+c[1]+"
                                            • ":"",'
                                            • '+c[2]+"
                                            • ","
                                            "].join("")),u=g.find("."+a),s=function(){var t=o.scrollTop();t>=e.showHeight?i||(u.show(),i=1):i&&(u.hide(),i=0)};t("."+r)[0]||("object"==typeof e.css&&g.css(e.css),l.append(g),s(),g.find("li").on("click",function(){var i=t(this),n=i.attr("lay-type");"top"===n&&t("html,body").animate({scrollTop:0},200),e.click&&e.click.call(this,n)}),o.on("scroll",function(){clearTimeout(n),n=setTimeout(function(){s()},100)}))},countdown:function(e,t,i){var n=this,r="function"==typeof t,a=new Date(e).getTime(),o=new Date(!t||r?(new Date).getTime():t).getTime(),l=a-o,c=[Math.floor(l/864e5),Math.floor(l/36e5)%24,Math.floor(l/6e4)%60,Math.floor(l/1e3)%60];r&&(i=t);var g=setTimeout(function(){n.countdown(e,o+1e3,i)},1e3);return i&&i(l>0?c:[0,0,0,0],t,g),l<=0&&clearTimeout(g),g},timeAgo:function(e,t){var i=this,n=[[],[]],r=(new Date).getTime()-new Date(e).getTime();return r>26784e5?(r=new Date(e),n[0][0]=i.digit(r.getFullYear(),4),n[0][1]=i.digit(r.getMonth()+1),n[0][2]=i.digit(r.getDate()),t||(n[1][0]=i.digit(r.getHours()),n[1][1]=i.digit(r.getMinutes()),n[1][2]=i.digit(r.getSeconds())),n[0].join("-")+" "+n[1].join(":")):r>=864e5?(r/1e3/60/60/24|0)+"\u5929\u524d":r>=36e5?(r/1e3/60/60|0)+"\u5c0f\u65f6\u524d":r>=18e4?(r/1e3/60|0)+"\u5206\u949f\u524d":r<0?"\u672a\u6765":"\u521a\u521a"},digit:function(e,t){var i="";e=String(e),t=t||2;for(var n=e.length;n/g,">").replace(/'/g,"'").replace(/"/g,""")},unescape:function(e){return String(e||"").replace(/\&/g,"&").replace(/\</g,"<").replace(/\>/g,">").replace(/\'/,"'").replace(/\"/,'"')},toVisibleArea:function(e){if(e=t.extend({margin:160,duration:200,type:"y"},e),e.scrollElem[0]&&e.thisElem[0]){var i=e.scrollElem,n=e.thisElem,r="y"===e.type,a=r?"scrollTop":"scrollLeft",o=r?"top":"left",l=i[a](),c=i[r?"height":"width"](),g=i.offset()[o],u=n.offset()[o]-g,s={};(u>c-e.margin||u0&&t.unshift(""),t.join(" ")}()+">"+(a.title||"unnaming")+"";return s[0]?s.before(r):n.append(r),o.append('
                                            '+(a.content||"")+"
                                            "),b.hideTabMore(!0),b.tabAuto(),this},s.prototype.tabDelete=function(t,a){var e=".layui-tab-title",l=i(".layui-tab[lay-filter="+t+"]"),n=l.children(e),s=n.find('>li[lay-id="'+a+'"]');return b.tabDelete(null,s),this},s.prototype.tabChange=function(t,a){var e=".layui-tab-title",l=i(".layui-tab[lay-filter="+t+"]"),n=l.children(e),s=n.find('>li[lay-id="'+a+'"]');return b.tabClick.call(s[0],null,null,s),this},s.prototype.tab=function(t){t=t||{},m.on("click",t.headerElem,function(a){var e=i(this).index();b.tabClick.call(this,a,e,null,t)})},s.prototype.progress=function(t,a){var e="layui-progress",l=i("."+e+"[lay-filter="+t+"]"),n=l.find("."+e+"-bar"),s=n.find("."+e+"-text");return n.css("width",a).attr("lay-percent",a),s.text(a),this};var o=".layui-nav",r="layui-nav-item",c="layui-nav-bar",u="layui-nav-tree",y="layui-nav-child",d="layui-nav-child-c",f="layui-nav-more",h="layui-icon-down",p="layui-anim layui-anim-upbit",b={tabClick:function(t,a,s,o){o=o||{};var r=s||i(this),a=a||r.parent().children("li").index(r),c=o.headerElem?r.parent():r.parents(".layui-tab").eq(0),u=o.bodyElem?i(o.bodyElem):c.children(".layui-tab-content").children(".layui-tab-item"),y=r.find("a"),d="javascript:;"!==y.attr("href")&&"_blank"===y.attr("target"),f="string"==typeof r.attr("lay-unselect"),h=c.attr("lay-filter");d||f||(r.addClass(l).siblings().removeClass(l),u.eq(a).addClass(n).siblings().removeClass(n)),layui.event.call(this,e,"tab("+h+")",{elem:c,index:a})},tabDelete:function(t,a){var n=a||i(this).parent(),s=n.index(),o=n.parents(".layui-tab").eq(0),r=o.children(".layui-tab-content").children(".layui-tab-item"),c=o.attr("lay-filter");n.hasClass(l)&&(n.next()[0]?b.tabClick.call(n.next()[0],null,s+1):n.prev()[0]&&b.tabClick.call(n.prev()[0],null,s-1)),n.remove(),r.eq(s).remove(),setTimeout(function(){b.tabAuto()},50),layui.event.call(this,e,"tabDelete("+c+")",{elem:o,index:s})},tabAuto:function(){var t="layui-tab-more",e="layui-tab-bar",l="layui-tab-close",n=this;i(".layui-tab").each(function(){var s=i(this),o=s.children(".layui-tab-title"),r=(s.children(".layui-tab-content").children(".layui-tab-item"),'lay-stope="tabmore"'),c=i('');if(n===window&&8!=a.ie&&b.hideTabMore(!0),s.attr("lay-allowClose")&&o.find("li").each(function(){var t=i(this);if(!t.find("."+l)[0]){var a=i('');a.on("click",b.tabDelete),t.append(a)}}),"string"!=typeof s.attr("lay-unauto"))if(o.prop("scrollWidth")>o.outerWidth()+1){if(o.find("."+e)[0])return;o.append(c),s.attr("overflow",""),c.on("click",function(i){o[this.title?"removeClass":"addClass"](t),this.title=this.title?"":"\u6536\u7f29"})}else o.find("."+e).remove(),s.removeAttr("overflow")})},hideTabMore:function(t){var a=i(".layui-tab-title");t!==!0&&"tabmore"===i(t.target).attr("lay-stope")||(a.removeClass("layui-tab-more"),a.find(".layui-tab-bar").attr("title",""))},clickThis:function(){var t=i(this),a=t.parents(o),n=a.attr("lay-filter"),s=t.parent(),c=t.siblings("."+y),d="string"==typeof s.attr("lay-unselect");"javascript:;"!==t.attr("href")&&"_blank"===t.attr("target")||d||c[0]||(a.find("."+l).removeClass(l),s.addClass(l)),a.hasClass(u)&&(c.removeClass(p),c[0]&&(s["none"===c.css("display")?"addClass":"removeClass"](r+"ed"),"all"===a.attr("lay-shrink")&&s.siblings().removeClass(r+"ed"))),layui.event.call(this,e,"nav("+n+")",t)},collapse:function(){var t=i(this),a=t.find(".layui-colla-icon"),l=t.siblings(".layui-colla-content"),s=t.parents(".layui-collapse").eq(0),o=s.attr("lay-filter"),r="none"===l.css("display");if("string"==typeof s.attr("lay-accordion")){var c=s.children(".layui-colla-item").children("."+n);c.siblings(".layui-colla-title").children(".layui-colla-icon").html(""),c.removeClass(n)}l[r?"addClass":"removeClass"](n),a.html(r?"":""),layui.event.call(this,e,"collapse("+o+")",{title:t,content:l,show:r})}};s.prototype.init=function(t,e){var l=function(){return e?'[lay-filter="'+e+'"]':""}(),s={tab:function(){b.tabAuto.call({})},nav:function(){var t=200,e={},s={},v={},m="layui-nav-title",C=function(l,o,r){var c=i(this),h=c.find("."+y);if(o.hasClass(u)){if(!h[0]){var b=c.children("."+m);l.css({top:c.offset().top-o.offset().top,height:(b[0]?b:c).outerHeight(),opacity:1})}}else h.addClass(p),h.hasClass(d)&&h.css({left:-(h.outerWidth()-c.width())/2}),h[0]?l.css({left:l.position().left+l.width()/2,width:0,opacity:0}):l.css({left:c.position().left+parseFloat(c.css("marginLeft")),top:c.position().top+c.height()-l.height()}),e[r]=setTimeout(function(){l.css({width:h[0]?0:c.width(),opacity:h[0]?0:1})},a.ie&&a.ie<10?0:t),clearTimeout(v[r]),"block"===h.css("display")&&clearTimeout(s[r]),s[r]=setTimeout(function(){h.addClass(n),c.find("."+f).addClass(f+"d")},300)};i(o+l).each(function(a){var l=i(this),o=i(''),d=l.find("."+r);l.find("."+c)[0]||(l.append(o),(l.hasClass(u)?d.find("dd,>."+m):d).on("mouseenter",function(){C.call(this,o,l,a)}).on("mouseleave",function(){l.hasClass(u)?o.css({height:0,opacity:0}):(clearTimeout(s[a]),s[a]=setTimeout(function(){l.find("."+y).removeClass(n),l.find("."+f).removeClass(f+"d")},300))}),l.on("mouseleave",function(){clearTimeout(e[a]),v[a]=setTimeout(function(){l.hasClass(u)||o.css({width:0,left:o.position().left+o.width()/2,opacity:0})},t)})),d.find("a").each(function(){var t=i(this),a=(t.parent(),t.siblings("."+y));a[0]&&!t.children("."+f)[0]&&t.append(''),t.off("click",b.clickThis).on("click",b.clickThis)})})},breadcrumb:function(){var t=".layui-breadcrumb";i(t+l).each(function(){var t=i(this),a="lay-separator",e=t.attr(a)||"/",l=t.find("a");l.next("span["+a+"]")[0]||(l.each(function(t){t!==l.length-1&&i(this).after(""+e+"")}),t.css("visibility","visible"))})},progress:function(){var t="layui-progress";i("."+t+l).each(function(){var a=i(this),e=a.find(".layui-progress-bar"),l=e.attr("lay-percent");e.css("width",function(){return/^.+\/.+$/.test(l)?100*new Function("return "+l)()+"%":l}()),a.attr("lay-showPercent")&&setTimeout(function(){e.html(''+l+"")},350)})},collapse:function(){var t="layui-collapse";i("."+t+l).each(function(){var t=i(this).find(".layui-colla-item");t.each(function(){var t=i(this),a=t.find(".layui-colla-title"),e=t.find(".layui-colla-content"),l="none"===e.css("display");a.find(".layui-colla-icon").remove(),a.append(''+(l?"":"")+""),a.off("click",b.collapse).on("click",b.collapse)})})}};return s[t]?s[t]():layui.each(s,function(t,i){i()})},s.prototype.render=s.prototype.init;var v=new s,m=i(document);i(function(){v.render()});var C=".layui-tab-title li";m.on("click",C,b.tabClick),m.on("click",b.hideTabMore),i(window).on("resize",b.tabAuto),t(e,v)});layui.define("layer",function(e){"use strict";var t=layui.$,i=layui.layer,n=layui.hint(),o=layui.device(),a={config:{},set:function(e){var i=this;return i.config=t.extend({},i.config,e),i},on:function(e,t){return layui.onevent.call(this,r,e,t)}},l=function(){var e=this;return{upload:function(t){e.upload.call(e,t)},reload:function(t){e.reload.call(e,t)},config:e.config}},r="upload",u="layui-upload-file",c="layui-upload-form",f="layui-upload-iframe",s="layui-upload-choose",p=function(e){var i=this;i.config=t.extend({},i.config,a.config,e),i.render()};p.prototype.config={accept:"images",exts:"",auto:!0,bindAction:"",url:"",field:"file",acceptMime:"",method:"post",data:{},drag:!0,size:0,number:0,multiple:!1},p.prototype.render=function(e){var i=this,e=i.config;e.elem=t(e.elem),e.bindAction=t(e.bindAction),i.file(),i.events()},p.prototype.file=function(){var e=this,i=e.config,n=e.elemFile=t(['"].join("")),a=i.elem.next();(a.hasClass(u)||a.hasClass(c))&&a.remove(),o.ie&&o.ie<10&&i.elem.wrap('
                                            '),e.isFile()?(e.elemFile=i.elem,i.field=i.elem[0].name):i.elem.after(n),o.ie&&o.ie<10&&e.initIE()},p.prototype.initIE=function(){var e=this,i=e.config,n=t(''),o=t(['
                                            ',"
                                            "].join(""));t("#"+f)[0]||t("body").append(n),i.elem.next().hasClass(c)||(e.elemFile.wrap(o),i.elem.next("."+c).append(function(){var e=[];return layui.each(i.data,function(t,i){i="function"==typeof i?i():i,e.push('')}),e.join("")}()))},p.prototype.msg=function(e){return i.msg(e,{icon:2,shift:6})},p.prototype.isFile=function(){var e=this.config.elem[0];if(e)return"input"===e.tagName.toLocaleLowerCase()&&"file"===e.type},p.prototype.preview=function(e){var t=this;window.FileReader&&layui.each(t.chooseFiles,function(t,i){var n=new FileReader;n.readAsDataURL(i),n.onload=function(){e&&e(t,i,this.result)}})},p.prototype.upload=function(e,i){var n,a=this,l=a.config,r=a.elemFile[0],u=function(){var i=0,n=0,o=e||a.files||a.chooseFiles||r.files,u=function(){l.multiple&&i+n===a.fileLength&&"function"==typeof l.allDone&&l.allDone({total:a.fileLength,successful:i,aborted:n})};layui.each(o,function(e,o){var r=new FormData;r.append(l.field,o),layui.each(l.data,function(e,t){t="function"==typeof t?t():t,r.append(e,t)});var c={url:l.url,type:"post",data:r,contentType:!1,processData:!1,dataType:"json",headers:l.headers||{},success:function(t){i++,d(e,t),u()},error:function(){n++,a.msg("\u8bf7\u6c42\u4e0a\u4f20\u63a5\u53e3\u51fa\u73b0\u5f02\u5e38"),m(e),u()}};"function"==typeof l.progress&&(c.xhr=function(){var i=t.ajaxSettings.xhr();return i.upload.addEventListener("progress",function(t){if(t.lengthComputable){var i=Math.floor(t.loaded/t.total*100);l.progress(i,l.item?l.item[0]:l.elem[0],t,e)}}),i}),t.ajax(c)})},c=function(){var e=t("#"+f);a.elemFile.parent().submit(),clearInterval(p.timer),p.timer=setInterval(function(){var t,i=e.contents().find("body");try{t=i.text()}catch(n){a.msg("\u83b7\u53d6\u4e0a\u4f20\u540e\u7684\u54cd\u5e94\u4fe1\u606f\u51fa\u73b0\u5f02\u5e38"),clearInterval(p.timer),m()}t&&(clearInterval(p.timer),i.html(""),d(0,t))},30)},d=function(e,t){if(a.elemFile.next("."+s).remove(),r.value="","object"!=typeof t)try{t=JSON.parse(t)}catch(i){return t={},a.msg("\u8bf7\u5bf9\u4e0a\u4f20\u63a5\u53e3\u8fd4\u56de\u6709\u6548JSON")}"function"==typeof l.done&&l.done(t,e||0,function(e){a.upload(e)})},m=function(e){l.auto&&(r.value=""),"function"==typeof l.error&&l.error(e||0,function(e){a.upload(e)})},h=l.exts,v=function(){var t=[];return layui.each(e||a.chooseFiles,function(e,i){t.push(i.name)}),t}(),g={preview:function(e){a.preview(e)},upload:function(e,t){var i={};i[e]=t,a.upload(i)},pushFile:function(){return a.files=a.files||{},layui.each(a.chooseFiles,function(e,t){a.files[e]=t}),a.files},resetFile:function(e,t,i){var n=new File([t],i);a.files=a.files||{},a.files[e]=n}},y=function(){if(!(("choose"===i||l.auto)&&(l.choose&&l.choose(g),"choose"===i)||l.before&&l.before(g)===!1))return o.ie?o.ie>9?u():c():void u()};if(v=0===v.length?r.value.match(/[^\/\\]+\..+/g)||[]||"":v,0!==v.length){switch(l.accept){case"file":if(h&&!RegExp("\\w\\.("+h+")$","i").test(escape(v)))return a.msg("\u9009\u62e9\u7684\u6587\u4ef6\u4e2d\u5305\u542b\u4e0d\u652f\u6301\u7684\u683c\u5f0f"),r.value="";break;case"video":if(!RegExp("\\w\\.("+(h||"avi|mp4|wma|rmvb|rm|flash|3gp|flv")+")$","i").test(escape(v)))return a.msg("\u9009\u62e9\u7684\u89c6\u9891\u4e2d\u5305\u542b\u4e0d\u652f\u6301\u7684\u683c\u5f0f"),r.value="";break;case"audio":if(!RegExp("\\w\\.("+(h||"mp3|wav|mid")+")$","i").test(escape(v)))return a.msg("\u9009\u62e9\u7684\u97f3\u9891\u4e2d\u5305\u542b\u4e0d\u652f\u6301\u7684\u683c\u5f0f"),r.value="";break;default:if(layui.each(v,function(e,t){RegExp("\\w\\.("+(h||"jpg|png|gif|bmp|jpeg$")+")","i").test(escape(t))||(n=!0)}),n)return a.msg("\u9009\u62e9\u7684\u56fe\u7247\u4e2d\u5305\u542b\u4e0d\u652f\u6301\u7684\u683c\u5f0f"),r.value=""}if(a.fileLength=function(){var t=0,i=e||a.files||a.chooseFiles||r.files;return layui.each(i,function(){t++}),t}(),l.number&&a.fileLength>l.number)return a.msg("\u540c\u65f6\u6700\u591a\u53ea\u80fd\u4e0a\u4f20\u7684\u6570\u91cf\u4e3a\uff1a"+l.number);if(l.size>0&&!(o.ie&&o.ie<10)){var F;if(layui.each(a.chooseFiles,function(e,t){if(t.size>1024*l.size){var i=l.size/1024;i=i>=1?i.toFixed(2)+"MB":l.size+"KB",r.value="",F=i}}),F)return a.msg("\u6587\u4ef6\u4e0d\u80fd\u8d85\u8fc7"+F)}y()}},p.prototype.reload=function(e){e=e||{},delete e.elem,delete e.bindAction;var i=this,e=i.config=t.extend({},i.config,a.config,e),n=e.elem.next();n.attr({name:e.name,accept:e.acceptMime,multiple:e.multiple})},p.prototype.events=function(){var e=this,i=e.config,a=function(t){e.chooseFiles={},layui.each(t,function(t,i){var n=(new Date).getTime();e.chooseFiles[n+"-"+t]=i})},l=function(t,n){var o=e.elemFile,a=(i.item?i.item:i.elem,t.length>1?t.length+"\u4e2a\u6587\u4ef6":(t[0]||{}).name||o[0].value.match(/[^\/\\]+\..+/g)||[]||"");o.next().hasClass(s)&&o.next().remove(),e.upload(null,"choose"),e.isFile()||i.choose||o.after(''+a+"")};i.elem.off("upload.start").on("upload.start",function(){var o=t(this),a=o.attr("lay-data");if(a)try{a=new Function("return "+a)(),e.config=t.extend({},i,a)}catch(l){n.error("Upload element property lay-data configuration item has a syntax error: "+a)}e.config.item=o,e.elemFile[0].click()}),o.ie&&o.ie<10||i.elem.off("upload.over").on("upload.over",function(){var e=t(this);e.attr("lay-over","")}).off("upload.leave").on("upload.leave",function(){var e=t(this);e.removeAttr("lay-over")}).off("upload.drop").on("upload.drop",function(n,o){var r=t(this),u=o.originalEvent.dataTransfer.files||[];r.removeAttr("lay-over"),a(u),i.auto?e.upload(u):l(u)}),e.elemFile.off("upload.change").on("upload.change",function(){var t=this.files||[];a(t),i.auto?e.upload():l(t)}),i.bindAction.off("upload.action").on("upload.action",function(){e.upload()}),i.elem.data("haveEvents")||(e.elemFile.on("change",function(){t(this).trigger("upload.change")}),i.elem.on("click",function(){e.isFile()||t(this).trigger("upload.start")}),i.drag&&i.elem.on("dragover",function(e){e.preventDefault(),t(this).trigger("upload.over")}).on("dragleave",function(e){t(this).trigger("upload.leave")}).on("drop",function(e){e.preventDefault(),t(this).trigger("upload.drop",e)}),i.bindAction.on("click",function(){t(this).trigger("upload.action")}),i.elem.data("haveEvents",!0))},a.render=function(e){var t=new p(e);return l.call(t)},e(r,a)});layui.define(["jquery","laytpl","lay"],function(e){"use strict";var i=layui.$,n=layui.laytpl,t=layui.hint(),a=layui.device(),l=a.mobile?"click":"mousedown",r="dropdown",o="layui_"+r+"_index",u={config:{},index:layui[r]?layui[r].index+1e4:0,set:function(e){var n=this;return n.config=i.extend({},n.config,e),n},on:function(e,i){return layui.onevent.call(this,r,e,i)}},d=function(){var e=this,i=e.config,n=i.id;return d.that[n]=e,{config:i,reload:function(i){e.reload.call(e,i)}}},s="layui-dropdown",m="layui-menu-item-up",c="layui-menu-item-down",p="layui-menu-body-title",y="layui-menu-item-group",f="layui-menu-item-parent",v="layui-menu-item-divider",g="layui-menu-item-checked",h="layui-menu-item-checked2",w="layui-menu-body-panel",C="layui-menu-body-panel-left",V="."+y+">."+p,k=function(e){var n=this;n.index=++u.index,n.config=i.extend({},n.config,u.config,e),n.init()};k.prototype.config={trigger:"click",content:"",className:"",style:"",show:!1,isAllowSpread:!0,isSpreadItem:!0,data:[],delay:300},k.prototype.reload=function(e){var n=this;n.config=i.extend({},n.config,e),n.init(!0)},k.prototype.init=function(e){var n=this,t=n.config,a=t.elem=i(t.elem);if(a.length>1)return layui.each(a,function(){u.render(i.extend({},t,{elem:this}))}),n;if(!e&&a[0]&&a.data(o)){var l=d.getThis(a.data(o));if(!l)return;return l.reload(t)}t.id="id"in t?t.id:n.index,t.show&&n.render(e),n.events()},k.prototype.render=function(e){var t=this,a=t.config,r=i("body"),s=function(){var e=i('
                                              ');return a.data.length>0?m(e,a.data):e.html('
                                            • no menu
                                            • '),e},m=function(e,t){return layui.each(t,function(t,l){var r=l.child&&l.child.length>0,o="isSpreadItem"in l?l.isSpreadItem:a.isSpreadItem,u=l.templet?n(l.templet).render(l):a.templet?n(a.templet).render(l):l.title,d=function(){return r&&(l.type=l.type||"parent"),l.type?{group:"group",parent:"parent","-":"-"}[l.type]||"parent":""}();if("-"===d||l.title||l.id||r){var s=i(["",function(){var e="href"in l?''+u+"":u;return r?'
                                              '+e+function(){return"parent"===d?'':"group"===d&&a.isAllowSpread?'':""}()+"
                                              ":'
                                              '+e+"
                                              "}(),""].join(""));if(s.data("item",l),r){var c=i('
                                              '),y=i("
                                                ");"parent"===d?(c.append(m(y,l.child)),s.append(c)):s.append(m(y,l.child))}e.append(s)}}),e},c=['
                                                ',"
                                                "].join("");("contextmenu"===a.trigger||lay.isTopElem(a.elem[0]))&&(e=!0),!e&&a.elem.data(o+"_opened")||(t.elemView=i(c),t.elemView.append(a.content||s()),a.className&&t.elemView.addClass(a.className),a.style&&t.elemView.attr("style",a.style),u.thisId=a.id,t.remove(),r.append(t.elemView),a.elem.data(o+"_opened",!0),t.position(),d.prevElem=t.elemView,d.prevElem.data("prevElem",a.elem),t.elemView.find(".layui-menu").on(l,function(e){layui.stope(e)}),t.elemView.find(".layui-menu li").on("click",function(e){var n=i(this),l=n.data("item")||{},r=l.child&&l.child.length>0;r||"-"===l.type||(t.remove(),"function"==typeof a.click&&a.click(l,n))}),t.elemView.find(V).on("click",function(e){var n=i(this),t=n.parent(),l=t.data("item")||{};"group"===l.type&&a.isAllowSpread&&d.spread(t)}),"mouseenter"===a.trigger&&t.elemView.on("mouseenter",function(){clearTimeout(d.timer)}).on("mouseleave",function(){t.delayRemove()}))},k.prototype.position=function(e){var i=this,n=i.config;lay.position(n.elem[0],i.elemView[0],{position:n.position,e:i.e,clickType:"contextmenu"===n.trigger?"right":null,align:n.align||null})},k.prototype.remove=function(){var e=this,i=(e.config,d.prevElem);i&&(i.data("prevElem")&&i.data("prevElem").data(o+"_opened",!1),i.remove())},k.prototype.delayRemove=function(){var e=this,i=e.config;clearTimeout(d.timer),d.timer=setTimeout(function(){e.remove()},i.delay)},k.prototype.events=function(){var e=this,i=e.config;"hover"===i.trigger&&(i.trigger="mouseenter"),e.prevElem&&e.prevElem.off(i.trigger,e.prevElemCallback),e.prevElem=i.elem,e.prevElemCallback=function(n){clearTimeout(d.timer),e.e=n,e.render(),n.preventDefault(),"function"==typeof i.ready&&i.ready(e.elemView,i.elem,e.e.target)},i.elem.on(i.trigger,e.prevElemCallback),"mouseenter"===i.trigger&&i.elem.on("mouseleave",function(){e.delayRemove()})},d.that={},d.getThis=function(e){var i=d.that[e];return i||t.error(e?r+" instance with ID '"+e+"' not found":"ID argument required"),i},d.spread=function(e){var i=e.children("."+p).find(".layui-icon");e.hasClass(m)?(e.removeClass(m).addClass(c),i.removeClass("layui-icon-down").addClass("layui-icon-up")):(e.removeClass(c).addClass(m),i.removeClass("layui-icon-up").addClass("layui-icon-down"))},!function(){var e=i(window),n=i(document);e.on("resize",function(){if(u.thisId){var e=d.getThis(u.thisId);if(e){if(!e.elemView[0]||!i("."+s)[0])return!1;var n=e.config;"contextmenu"===n.trigger?e.remove():e.position()}}}),n.on(l,function(e){if(u.thisId){var i=d.getThis(u.thisId);if(i){var n=i.config;!lay.isTopElem(n.elem[0])&&"contextmenu"!==n.trigger&&(e.target===n.elem[0]||n.elem.find(e.target)[0]||e.target===i.elemView[0]||i.elemView&&i.elemView.find(e.target)[0])||i.remove()}}});var t=".layui-menu:not(.layui-dropdown-menu) li";n.on("click",t,function(e){var n=i(this),t=n.parents(".layui-menu").eq(0),a=n.hasClass(y)||n.hasClass(f),l=t.attr("lay-filter")||t.attr("id"),o=lay.options(this);n.hasClass(v)||a||(t.find("."+g).removeClass(g),t.find("."+h).removeClass(h),n.addClass(g),n.parents("."+f).addClass(h),layui.event.call(this,r,"click("+l+")",o))}),n.on("click",t+V,function(e){var n=i(this),t=n.parents("."+y+":eq(0)"),a=lay.options(t[0]);"isAllowSpread"in a&&!a.isAllowSpread||d.spread(t)});var a=".layui-menu ."+f;n.on("mouseenter",a,function(n){var t=i(this),a=t.find("."+w);if(a[0]){var l=a[0].getBoundingClientRect();l.right>e.width()&&(a.addClass(C),l=a[0].getBoundingClientRect(),l.left<0&&a.removeClass(C)),l.bottom>e.height()&&a.eq(0).css("margin-top",-(l.bottom-e.height()))}}).on("mouseleave",a,function(e){var n=i(this),t=n.children("."+w);t.removeClass(C),t.css("margin-top",0)})}(),u.reload=function(e,i){var n=d.getThis(e);return n?(n.reload(i),d.call(n)):this},u.render=function(e){var i=new k(e);return d.call(i)},e(r,u)});layui.define("jquery",function(e){"use strict";var i=layui.jquery,t={config:{},index:layui.slider?layui.slider.index+1e4:0,set:function(e){var t=this;return t.config=i.extend({},t.config,e),t},on:function(e,i){return layui.onevent.call(this,n,e,i)}},a=function(){var e=this,i=e.config;return{setValue:function(t,a){return i.value=t,e.slide("set",t,a||0)},config:i}},n="slider",l="layui-disabled",s="layui-slider",r="layui-slider-bar",o="layui-slider-wrap",u="layui-slider-wrap-btn",d="layui-slider-tips",v="layui-slider-input",c="layui-slider-input-txt",p="layui-slider-input-btn",m="layui-slider-hover",f=function(e){var a=this;a.index=++t.index,a.config=i.extend({},a.config,t.config,e),a.render()};f.prototype.config={type:"default",min:0,max:100,value:0,step:1,showstep:!1,tips:!0,input:!1,range:!1,height:200,disabled:!1,theme:"#009688"},f.prototype.render=function(){var e=this,t=e.config;if(t.step<1&&(t.step=1),t.maxt.min?a:t.min,t.value[1]=n>t.min?n:t.min,t.value[0]=t.value[0]>t.max?t.max:t.value[0],t.value[1]=t.value[1]>t.max?t.max:t.value[1];var r=Math.floor((t.value[0]-t.min)/(t.max-t.min)*100),v=Math.floor((t.value[1]-t.min)/(t.max-t.min)*100),p=v-r+"%";r+="%",v+="%"}else{"object"==typeof t.value&&(t.value=Math.min.apply(null,t.value)),t.valuet.max&&(t.value=t.max);var p=Math.floor((t.value-t.min)/(t.max-t.min)*100)+"%"}var m=t.disabled?"#c2c2c2":t.theme,f='
                                                '+(t.tips?'
                                                ':"")+'
                                                '+(t.range?'
                                                ':"")+"
                                                ",h=i(t.elem),y=h.next("."+s);if(y[0]&&y.remove(),e.elemTemp=i(f),t.range?(e.elemTemp.find("."+o).eq(0).data("value",t.value[0]),e.elemTemp.find("."+o).eq(1).data("value",t.value[1])):e.elemTemp.find("."+o).data("value",t.value),h.html(e.elemTemp),"vertical"===t.type&&e.elemTemp.height(t.height+"px"),t.showstep){for(var g=(t.max-t.min)/t.step,b="",x=1;x
                                              ')}e.elemTemp.append(b)}if(t.input&&!t.range){var w=i('
                                              ');h.css("position","relative"),h.append(w),h.find("."+c).children("input").val(t.value),"vertical"===t.type?w.css({left:0,top:-48}):e.elemTemp.css("margin-right",w.outerWidth()+15)}t.disabled?(e.elemTemp.addClass(l),e.elemTemp.find("."+u).addClass(l)):e.slide(),e.elemTemp.find("."+u).on("mouseover",function(){var a="vertical"===t.type?t.height:e.elemTemp[0].offsetWidth,n=e.elemTemp.find("."+o),l="vertical"===t.type?a-i(this).parent()[0].offsetTop-n.height():i(this).parent()[0].offsetLeft,s=l/a*100,r=i(this).parent().data("value"),u=t.setTips?t.setTips(r):r;e.elemTemp.find("."+d).html(u),"vertical"===t.type?e.elemTemp.find("."+d).css({bottom:s+"%","margin-bottom":"20px",display:"inline-block"}):e.elemTemp.find("."+d).css({left:s+"%",display:"inline-block"})}).on("mouseout",function(){e.elemTemp.find("."+d).css("display","none")})},f.prototype.slide=function(e,t,a){var n=this,l=n.config,s=n.elemTemp,f=function(){return"vertical"===l.type?l.height:s[0].offsetWidth},h=s.find("."+o),y=s.next("."+v),g=y.children("."+c).children("input").val(),b=100/((l.max-l.min)/Math.ceil(l.step)),x=function(e,i){e=Math.ceil(e)*b>100?Math.ceil(e)*b:Math.round(e)*b,e=e>100?100:e,h.eq(i).css("vertical"===l.type?"bottom":"left",e+"%");var t=T(h[0].offsetLeft),a=l.range?T(h[1].offsetLeft):0;"vertical"===l.type?(s.find("."+d).css({bottom:e+"%","margin-bottom":"20px"}),t=T(f()-h[0].offsetTop-h.height()),a=l.range?T(f()-h[1].offsetTop-h.height()):0):s.find("."+d).css("left",e+"%"),t=t>100?100:t,a=a>100?100:a;var n=Math.min(t,a),o=Math.abs(t-a);"vertical"===l.type?s.find("."+r).css({height:o+"%",bottom:n+"%"}):s.find("."+r).css({width:o+"%",left:n+"%"});var u=l.min+Math.round((l.max-l.min)*e/100);if(g=u,y.children("."+c).children("input").val(g),h.eq(i).data("value",u),s.find("."+d).html(l.setTips?l.setTips(u):u),l.range){var v=[h.eq(0).data("value"),h.eq(1).data("value")];v[0]>v[1]&&v.reverse()}l.change&&l.change(l.range?v:u)},T=function(e){var i=e/f()*100/b,t=Math.round(i)*b;return e==f()&&(t=Math.ceil(i)*b),t},w=i(['
                                              f()&&(r=f());var o=r/f()*100/b;x(o,e),t.addClass(m),s.find("."+d).show(),i.preventDefault()},o=function(){t.removeClass(m),s.find("."+d).hide()};M(r,o)})}),s.on("click",function(e){var t=i("."+u);if(!t.is(event.target)&&0===t.has(event.target).length&&t.length){var a,n="vertical"===l.type?f()-e.clientY+i(this).offset().top:e.clientX-i(this).offset().left;n<0&&(n=0),n>f()&&(n=f());var s=n/f()*100/b;a=l.range?"vertical"===l.type?Math.abs(n-parseInt(i(h[0]).css("bottom")))>Math.abs(n-parseInt(i(h[1]).css("bottom")))?1:0:Math.abs(n-h[0].offsetLeft)>Math.abs(n-h[1].offsetLeft)?1:0:0,x(s,a),e.preventDefault()}}),y.children("."+p).children("i").each(function(e){i(this).on("click",function(){g=y.children("."+c).children("input").val(),g=1==e?g-l.stepl.max?l.max:Number(g)+l.step;var i=(g-l.min)/(l.max-l.min)*100/b;x(i,0)})});var q=function(){var e=this.value;e=isNaN(e)?0:e,e=el.max?l.max:e,this.value=e;var i=(e-l.min)/(l.max-l.min)*100/b;x(i,0)};y.children("."+c).children("input").on("keydown",function(e){13===e.keyCode&&(e.preventDefault(),q.call(this))}).on("change",q)},f.prototype.events=function(){var e=this;e.config},t.render=function(e){var i=new f(e);return a.call(i)},e(n,t)});layui.define(["jquery","lay"],function(e){"use strict";var i=layui.jquery,r=layui.lay,o=layui.device(),n=o.mobile?"click":"mousedown",l={config:{},index:layui.colorpicker?layui.colorpicker.index+1e4:0,set:function(e){var r=this;return r.config=i.extend({},r.config,e),r},on:function(e,i){return layui.onevent.call(this,"colorpicker",e,i)}},t=function(){var e=this,i=e.config;return{config:i}},c="colorpicker",a="layui-show",s="layui-colorpicker",f=".layui-colorpicker-main",d="layui-icon-down",u="layui-icon-close",p="layui-colorpicker-trigger-span",g="layui-colorpicker-trigger-i",v="layui-colorpicker-side",h="layui-colorpicker-side-slider",b="layui-colorpicker-basis",k="layui-colorpicker-alpha-bgcolor",y="layui-colorpicker-alpha-slider",m="layui-colorpicker-basis-cursor",x="layui-colorpicker-main-input",P=function(e){var i={h:0,s:0,b:0},r=Math.min(e.r,e.g,e.b),o=Math.max(e.r,e.g,e.b),n=o-r;return i.b=o,i.s=0!=o?255*n/o:0,0!=i.s?e.r==o?i.h=(e.g-e.b)/n:e.g==o?i.h=2+(e.b-e.r)/n:i.h=4+(e.r-e.g)/n:i.h=-1,o==r&&(i.h=0),i.h*=60,i.h<0&&(i.h+=360),i.s*=100/255,i.b*=100/255,i},C=function(e){var e=e.indexOf("#")>-1?e.substring(1):e;if(3==e.length){var i=e.split("");e=i[0]+i[0]+i[1]+i[1]+i[2]+i[2]}e=parseInt(e,16);var r={r:e>>16,g:(65280&e)>>8,b:255&e};return P(r)},B=function(e){var i={},r=e.h,o=255*e.s/100,n=255*e.b/100;if(0==o)i.r=i.g=i.b=n;else{var l=n,t=(255-o)*n/255,c=(l-t)*(r%60)/60;360==r&&(r=0),r<60?(i.r=l,i.b=t,i.g=t+c):r<120?(i.g=l,i.b=t,i.r=l-c):r<180?(i.g=l,i.r=t,i.b=t+c):r<240?(i.b=l,i.r=t,i.g=l-c):r<300?(i.b=l,i.g=t,i.r=t+c):r<360?(i.r=l,i.g=t,i.b=l-c):(i.r=0,i.g=0,i.b=0)}return{r:Math.round(i.r),g:Math.round(i.g),b:Math.round(i.b)}},w=function(e){var r=B(e),o=[r.r.toString(16),r.g.toString(16),r.b.toString(16)];return i.each(o,function(e,i){1==i.length&&(o[e]="0"+i)}),o.join("")},D=function(e){var i=/[0-9]{1,3}/g,r=e.match(i)||[];return{r:r[0],g:r[1],b:r[2]}},j=i(window),E=i(document),F=function(e){var r=this;r.index=++l.index,r.config=i.extend({},r.config,l.config,e),r.render()};F.prototype.config={color:"",size:null,alpha:!1,format:"hex",predefine:!1,colors:["#009688","#5FB878","#1E9FFF","#FF5722","#FFB800","#01AAED","#999","#c00","#ff8c00","#ffd700","#90ee90","#00ced1","#1e90ff","#c71585","rgb(0, 186, 189)","rgb(255, 120, 0)","rgb(250, 212, 0)","#393D49","rgba(0,0,0,.5)","rgba(255, 69, 0, 0.68)","rgba(144, 240, 144, 0.5)","rgba(31, 147, 255, 0.73)"]},F.prototype.render=function(){var e=this,r=e.config,o=i(['
                                              ',"",'3&&(r.alpha&&"rgb"==r.format||(e="#"+w(P(D(r.color))))),"background: "+e):e}()+'">','',"","","
                                              "].join("")),n=i(r.elem);r.size&&o.addClass("layui-colorpicker-"+r.size),n.addClass("layui-inline").html(e.elemColorBox=o),e.color=e.elemColorBox.find("."+p)[0].style.background,e.events()},F.prototype.renderPicker=function(){var e=this,r=e.config,o=e.elemColorBox[0],n=e.elemPicker=i(['
                                              ','
                                              ','
                                              ','
                                              ','
                                              ','
                                              ',"
                                              ",'
                                              ','
                                              ',"
                                              ","
                                              ",'
                                              ','
                                              ','
                                              ',"
                                              ","
                                              ",function(){if(r.predefine){var e=['
                                              '];return layui.each(r.colors,function(i,r){e.push(['
                                              ','
                                              ',"
                                              "].join(""))}),e.push("
                                              "),e.join("")}return""}(),'
                                              ','
                                              ','',"
                                              ",'
                                              ','','',"","
                                              "].join(""));e.elemColorBox.find("."+p)[0];i(f)[0]&&i(f).data("index")==e.index?e.removePicker(F.thisElemInd):(e.removePicker(F.thisElemInd),i("body").append(n)),F.thisElemInd=e.index,F.thisColor=o.style.background,e.position(),e.pickerEvents()},F.prototype.removePicker=function(e){var r=this;r.config;return i("#layui-colorpicker"+(e||r.index)).remove(),r},F.prototype.position=function(){var e=this,i=e.config;return r.position(e.bindElem||e.elemColorBox[0],e.elemPicker[0],{position:i.position,align:"center"}),e},F.prototype.val=function(){var e=this,i=(e.config,e.elemColorBox.find("."+p)),r=e.elemPicker.find("."+x),o=i[0],n=o.style.backgroundColor;if(n){var l=P(D(n)),t=i.attr("lay-type");if(e.select(l.h,l.s,l.b),"torgb"===t&&r.find("input").val(n),"rgba"===t){var c=D(n);if(3==(n.match(/[0-9]{1,3}/g)||[]).length)r.find("input").val("rgba("+c.r+", "+c.g+", "+c.b+", 1)"),e.elemPicker.find("."+y).css("left",280);else{r.find("input").val(n);var a=280*n.slice(n.lastIndexOf(",")+1,n.length-1);e.elemPicker.find("."+y).css("left",a)}e.elemPicker.find("."+k)[0].style.background="linear-gradient(to right, rgba("+c.r+", "+c.g+", "+c.b+", 0), rgb("+c.r+", "+c.g+", "+c.b+"))"}}else e.select(0,100,100),r.find("input").val(""),e.elemPicker.find("."+k)[0].style.background="",e.elemPicker.find("."+y).css("left",280)},F.prototype.side=function(){var e=this,r=e.config,o=e.elemColorBox.find("."+p),n=o.attr("lay-type"),l=e.elemPicker.find("."+v),t=e.elemPicker.find("."+h),c=e.elemPicker.find("."+b),a=e.elemPicker.find("."+m),s=e.elemPicker.find("."+k),f=e.elemPicker.find("."+y),C=t[0].offsetTop/180*360,w=100-(a[0].offsetTop+3)/180*100,E=(a[0].offsetLeft+3)/260*100,F=Math.round(f[0].offsetLeft/280*100)/100,H=e.elemColorBox.find("."+g),M=e.elemPicker.find(".layui-colorpicker-pre").children("div"),Y=function(i,l,t,c){e.select(i,l,t);var a=B({h:i,s:l,b:t});if(H.addClass(d).removeClass(u),o[0].style.background="rgb("+a.r+", "+a.g+", "+a.b+")","torgb"===n&&e.elemPicker.find("."+x).find("input").val("rgb("+a.r+", "+a.g+", "+a.b+")"),"rgba"===n){var p=0;p=280*c,f.css("left",p),e.elemPicker.find("."+x).find("input").val("rgba("+a.r+", "+a.g+", "+a.b+", "+c+")"),o[0].style.background="rgba("+a.r+", "+a.g+", "+a.b+", "+c+")",s[0].style.background="linear-gradient(to right, rgba("+a.r+", "+a.g+", "+a.b+", 0), rgb("+a.r+", "+a.g+", "+a.b+"))"}r.change&&r.change(e.elemPicker.find("."+x).find("input").val())},I=i(['
                                              '].join("")),L=function(e){i("#LAY-colorpicker-moving")[0]||i("body").append(I),I.on("mousemove",e),I.on("mouseup",function(){I.remove()}).on("mouseleave",function(){I.remove()})};t.on("mousedown",function(e){var i=this.offsetTop,r=e.clientY,o=function(e){var o=i+(e.clientY-r),n=l[0].offsetHeight;o<0&&(o=0),o>n&&(o=n);var t=o/180*360;C=t,Y(t,E,w,F),e.preventDefault()};L(o),e.preventDefault()}),l.on("click",function(e){var r=e.clientY-i(this).offset().top;r<0&&(r=0),r>this.offsetHeight&&(r=this.offsetHeight);var o=r/180*360;C=o,Y(o,E,w,F),e.preventDefault()}),a.on("mousedown",function(e){var i=this.offsetTop,r=this.offsetLeft,o=e.clientY,n=e.clientX,l=function(e){var l=i+(e.clientY-o),t=r+(e.clientX-n),a=c[0].offsetHeight-3,s=c[0].offsetWidth-3;l<-3&&(l=-3),l>a&&(l=a),t<-3&&(t=-3),t>s&&(t=s);var f=(t+3)/260*100,d=100-(l+3)/180*100;w=d,E=f,Y(C,f,d,F),e.preventDefault()};layui.stope(e),L(l),e.preventDefault()}),c.on("mousedown",function(e){var r=e.clientY-i(this).offset().top-3+j.scrollTop(),o=e.clientX-i(this).offset().left-3+j.scrollLeft();r<-3&&(r=-3),r>this.offsetHeight-3&&(r=this.offsetHeight-3),o<-3&&(o=-3),o>this.offsetWidth-3&&(o=this.offsetWidth-3);var n=(o+3)/260*100,l=100-(r+3)/180*100;w=l,E=n,Y(C,n,l,F),layui.stope(e),e.preventDefault(),a.trigger(e,"mousedown")}),f.on("mousedown",function(e){var i=this.offsetLeft,r=e.clientX,o=function(e){var o=i+(e.clientX-r),n=s[0].offsetWidth;o<0&&(o=0),o>n&&(o=n);var l=Math.round(o/280*100)/100;F=l,Y(C,E,w,l),e.preventDefault()};L(o),e.preventDefault()}),s.on("click",function(e){var r=e.clientX-i(this).offset().left;r<0&&(r=0),r>this.offsetWidth&&(r=this.offsetWidth);var o=Math.round(r/280*100)/100;F=o,Y(C,E,w,o),e.preventDefault()}),M.each(function(){i(this).on("click",function(){i(this).parent(".layui-colorpicker-pre").addClass("selected").siblings().removeClass("selected");var e,r=this.style.backgroundColor,o=P(D(r)),n=r.slice(r.lastIndexOf(",")+1,r.length-1);C=o.h,E=o.s,w=o.b,3==(r.match(/[0-9]{1,3}/g)||[]).length&&(n=1),F=n,e=280*n,Y(o.h,o.s,o.b,n)})})},F.prototype.select=function(e,i,r,o){var n=this,l=(n.config,w({h:e,s:100,b:100})),t=w({h:e,s:i,b:r}),c=e/360*180,a=180-r/100*180-3,s=i/100*260-3;n.elemPicker.find("."+h).css("top",c),n.elemPicker.find("."+b)[0].style.background="#"+l,n.elemPicker.find("."+m).css({top:a,left:s}),"change"!==o&&n.elemPicker.find("."+x).find("input").val("#"+t)},F.prototype.pickerEvents=function(){var e=this,r=e.config,o=e.elemColorBox.find("."+p),n=e.elemPicker.find("."+x+" input"),l={clear:function(i){o[0].style.background="",e.elemColorBox.find("."+g).removeClass(d).addClass(u),e.color="",r.done&&r.done(""),e.removePicker()},confirm:function(i,l){var t=n.val(),c=t,a={};if(t.indexOf(",")>-1){if(a=P(D(t)),e.select(a.h,a.s,a.b),o[0].style.background=c="#"+w(a),(t.match(/[0-9]{1,3}/g)||[]).length>3&&"rgba"===o.attr("lay-type")){var s=280*t.slice(t.lastIndexOf(",")+1,t.length-1);e.elemPicker.find("."+y).css("left",s),o[0].style.background=t,c=t}}else a=C(t),o[0].style.background=c="#"+w(a),e.elemColorBox.find("."+g).removeClass(u).addClass(d);return"change"===l?(e.select(a.h,a.s,a.b,l),void(r.change&&r.change(c))):(e.color=t,r.done&&r.done(t),void e.removePicker())}};e.elemPicker.on("click","*[colorpicker-events]",function(){var e=i(this),r=e.attr("colorpicker-events");l[r]&&l[r].call(this,e)}),n.on("keyup",function(e){var r=i(this);l.confirm.call(this,r,13===e.keyCode?null:"change")})},F.prototype.events=function(){var e=this,r=e.config,o=e.elemColorBox.find("."+p);e.elemColorBox.on("click",function(){e.renderPicker(),i(f)[0]&&(e.val(),e.side())}),r.elem[0]&&!e.elemColorBox[0].eventHandler&&(E.on(n,function(r){if(!i(r.target).hasClass(s)&&!i(r.target).parents("."+s)[0]&&!i(r.target).hasClass(f.replace(/\./g,""))&&!i(r.target).parents(f)[0]&&e.elemPicker){if(e.color){var n=P(D(e.color));e.select(n.h,n.s,n.b)}else e.elemColorBox.find("."+g).removeClass(d).addClass(u);o[0].style.background=e.color||"",e.removePicker()}}),j.on("resize",function(){return!(!e.elemPicker||!i(f)[0])&&void e.position()}),e.elemColorBox[0].eventHandler=!0)},l.render=function(e){var i=new F(e);return t.call(i)},e(c,l)});layui.define("layer",function(e){"use strict";var t=layui.$,i=layui.layer,a=layui.hint(),n=layui.device(),l="form",r=".layui-form",o="layui-this",s="layui-hide",c="layui-disabled",u=function(){this.config={verify:{required:[/[\S]+/,"\u5fc5\u586b\u9879\u4e0d\u80fd\u4e3a\u7a7a"],phone:[/^1\d{10}$/,"\u8bf7\u8f93\u5165\u6b63\u786e\u7684\u624b\u673a\u53f7"],email:[/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/,"\u90ae\u7bb1\u683c\u5f0f\u4e0d\u6b63\u786e"],url:[/^(#|(http(s?)):\/\/|\/\/)[^\s]+\.[^\s]+$/,"\u94fe\u63a5\u683c\u5f0f\u4e0d\u6b63\u786e"],number:function(e){if(!e||isNaN(e))return"\u53ea\u80fd\u586b\u5199\u6570\u5b57"},date:[/^(\d{4})[-\/](\d{1}|0\d{1}|1[0-2])([-\/](\d{1}|0\d{1}|[1-2][0-9]|3[0-1]))*$/,"\u65e5\u671f\u683c\u5f0f\u4e0d\u6b63\u786e"],identity:[/(^\d{15}$)|(^\d{17}(x|X|\d)$)/,"\u8bf7\u8f93\u5165\u6b63\u786e\u7684\u8eab\u4efd\u8bc1\u53f7"]},autocomplete:null}};u.prototype.set=function(e){var i=this;return t.extend(!0,i.config,e),i},u.prototype.verify=function(e){var i=this;return t.extend(!0,i.config.verify,e),i},u.prototype.on=function(e,t){return layui.onevent.call(this,l,e,t)},u.prototype.val=function(e,i){var a=this,n=t(r+'[lay-filter="'+e+'"]');return n.each(function(e,a){var n=t(this);layui.each(i,function(e,t){var i,a=n.find('[name="'+e+'"]');a[0]&&(i=a[0].type,"checkbox"===i?a[0].checked=t:"radio"===i?a.each(function(){this.value==t&&(this.checked=!0)}):a.val(t))})}),f.render(null,e),a.getValue(e)},u.prototype.getValue=function(e,i){i=i||t(r+'[lay-filter="'+e+'"]').eq(0);var a={},n={},l=i.find("input,select,textarea");return layui.each(l,function(e,i){var l;t(this);if(i.name=(i.name||"").replace(/^\s*|\s*&/,""),i.name){if(/^.*\[\]$/.test(i.name)){var r=i.name.match(/^(.*)\[\]$/g)[0];a[r]=0|a[r],l=i.name.replace(/^(.*)\[\]$/,"$1["+a[r]++ +"]")}/^checkbox|radio$/.test(i.type)&&!i.checked||(n[l||i.name]=i.value)}}),n},u.prototype.render=function(e,i){var n=this,u=n.config,d=t(r+function(){return i?'[lay-filter="'+i+'"]':""}()),f={input:function(){var e=d.find("input,textarea");u.autocomplete&&e.attr("autocomplete",u.autocomplete)},select:function(){var e,i="\u8bf7\u9009\u62e9",a="layui-form-select",n="layui-select-title",r="layui-select-none",u="",f=d.find("select"),v=function(i,l){t(i.target).parent().hasClass(n)&&!l||(t("."+a).removeClass(a+"ed "+a+"up"),e&&u&&e.val(u)),e=null},y=function(i,d,f){var y,p=t(this),m=i.find("."+n),g=m.find("input"),k=i.find("dl"),x=k.children("dd"),b=this.selectedIndex;if(!d){var C=function(){var e=i.offset().top+i.outerHeight()+5-h.scrollTop(),t=k.outerHeight();b=p[0].selectedIndex,i.addClass(a+"ed"),x.removeClass(s),y=null,x.eq(b).addClass(o).siblings().removeClass(o),e+t>h.height()&&e>=t&&i.addClass(a+"up"),T()},w=function(e){i.removeClass(a+"ed "+a+"up"),g.blur(),y=null,e||$(g.val(),function(e){var i=p[0].selectedIndex;e&&(u=t(p[0].options[i]).html(),0===i&&u===g.attr("placeholder")&&(u=""),g.val(u||""))})},T=function(){var e=k.children("dd."+o);if(e[0]){var t=e.position().top,i=k.height(),a=e.height();t>i&&k.scrollTop(t+k.scrollTop()-i+a-5),t<0&&k.scrollTop(t+k.scrollTop()-5)}};m.on("click",function(e){i.hasClass(a+"ed")?w():(v(e,!0),C()),k.find("."+r).remove()}),m.find(".layui-edge").on("click",function(){g.focus()}),g.on("keyup",function(e){var t=e.keyCode;9===t&&C()}).on("keydown",function(e){var t=e.keyCode;9===t&&w();var i=function(t,a){var n,l;e.preventDefault();var r=function(){var e=k.children("dd."+o);if(k.children("dd."+s)[0]&&"next"===t){var i=k.children("dd:not(."+s+",."+c+")"),n=i.eq(0).index();if(n>=0&&n\u65e0\u5339\u914d\u9879

                                              '):k.find("."+r).remove()},"keyup"),""===t&&k.find("."+r).remove(),void T())};f&&g.on("keyup",q).on("blur",function(i){var a=p[0].selectedIndex;e=g,u=t(p[0].options[a]).html(),0===a&&u===g.attr("placeholder")&&(u=""),setTimeout(function(){$(g.val(),function(e){u||g.val("")},"blur")},200)}),x.on("click",function(){var e=t(this),a=e.attr("lay-value"),n=p.attr("lay-filter");return!e.hasClass(c)&&(e.hasClass("layui-select-tips")?g.val(""):(g.val(e.text()),e.addClass(o)),e.siblings().removeClass(o),p.val(a).removeClass("layui-form-danger"),layui.event.call(this,l,"select("+n+")",{elem:p[0],value:a,othis:i}),w(!0),!1)}),i.find("dl>dt").on("click",function(e){return!1}),t(document).off("click",v).on("click",v)}};f.each(function(e,l){var r=t(this),s=r.next("."+a),u=this.disabled,d=l.value,f=t(l.options[l.selectedIndex]),v=l.options[0];if("string"==typeof r.attr("lay-ignore"))return r.show();var h="string"==typeof r.attr("lay-search"),p=v?v.value?i:v.innerHTML||i:i,m=t(['
                                              ','
                                              ','','
                                              ','
                                              ',function(e){var a=[];return layui.each(e,function(e,n){0!==e||n.value?"optgroup"===n.tagName.toLowerCase()?a.push("
                                              "+n.label+"
                                              "):a.push('
                                              '+t.trim(n.innerHTML)+"
                                              "):a.push('
                                              '+t.trim(n.innerHTML||i)+"
                                              ")}),0===a.length&&a.push('
                                              \u6ca1\u6709\u9009\u9879
                                              '),a.join("")}(r.find("*"))+"
                                              ","
                                              "].join(""));s[0]&&s.remove(),r.after(m),y.call(this,m,u,h)})},checkbox:function(){var e={checkbox:["layui-form-checkbox","layui-form-checked","checkbox"],_switch:["layui-form-switch","layui-form-onswitch","switch"]},i=d.find("input[type=checkbox]"),a=function(e,i){var a=t(this);e.on("click",function(){var t=a.attr("lay-filter"),n=(a.attr("lay-text")||"").split("|");a[0].disabled||(a[0].checked?(a[0].checked=!1,e.removeClass(i[1]).find("em").text(n[1])):(a[0].checked=!0,e.addClass(i[1]).find("em").text(n[0])),layui.event.call(a[0],l,i[2]+"("+t+")",{elem:a[0],value:a[0].value,othis:e}))})};i.each(function(i,n){var l=t(this),r=l.attr("lay-skin"),o=(l.attr("lay-text")||"").split("|"),s=this.disabled;"switch"===r&&(r="_"+r);var u=e[r]||e.checkbox;if("string"==typeof l.attr("lay-ignore"))return l.show();var d=l.next("."+u[0]),f=t(['
                                              ",function(){var e=n.title.replace(/\s/g,""),t={checkbox:[e?""+n.title+"":"",''].join(""),_switch:""+((n.checked?o[0]:o[1])||"")+""};return t[r]||t.checkbox}(),"
                                              "].join(""));d[0]&&d.remove(),l.after(f),a.call(this,f,u)})},radio:function(){var e="layui-form-radio",i=["",""],a=d.find("input[type=radio]"),n=function(a){var n=t(this),o="layui-anim-scaleSpring";a.on("click",function(){var s=n[0].name,c=n.parents(r),u=n.attr("lay-filter"),d=c.find("input[name="+s.replace(/(\.|#|\[|\])/g,"\\$1")+"]");n[0].disabled||(layui.each(d,function(){var a=t(this).next("."+e);this.checked=!1,a.removeClass(e+"ed"),a.find(".layui-icon").removeClass(o).html(i[1])}),n[0].checked=!0,a.addClass(e+"ed"),a.find(".layui-icon").addClass(o).html(i[0]),layui.event.call(n[0],l,"radio("+u+")",{elem:n[0],value:n[0].value,othis:a}))})};a.each(function(a,l){var r=t(this),o=r.next("."+e),s=this.disabled;if("string"==typeof r.attr("lay-ignore"))return r.show();o[0]&&o.remove();var u=t(['
                                              ',''+i[l.checked?0:1]+"","
                                              "+function(){var e=l.title||"";return"string"==typeof r.next().attr("lay-radio")&&(e=r.next().html()),e}()+"
                                              ","
                                              "].join(""));r.after(u),n.call(this,u)})}};return e?f[e]?f[e]():a.error('\u4e0d\u652f\u6301\u7684 "'+e+'" \u8868\u5355\u6e32\u67d3'):layui.each(f,function(e,t){t()}),n};var d=function(){var e=null,a=f.config.verify,o="layui-form-danger",s={},c=t(this),u=c.parents(r).eq(0),d=u.find("*[lay-verify]"),h=c.parents("form")[0],y=c.attr("lay-filter");return layui.each(d,function(l,r){var s=t(this),c=s.attr("lay-verify").split("|"),u=s.attr("lay-verType"),d=s.val();if(s.removeClass(o),layui.each(c,function(t,l){var c,f="",h="function"==typeof a[l];if(a[l]){var c=h?f=a[l](d,r):!a[l][0].test(d),y="select"===r.tagName.toLowerCase()||/^checkbox|radio$/.test(r.type);if(f=f||a[l][1],"required"===l&&(f=s.attr("lay-reqText")||f),c)return"tips"===u?i.tips(f,function(){return"string"!=typeof s.attr("lay-ignore")&&y?s.next():s}(),{tips:1}):"alert"===u?i.alert(f,{title:"\u63d0\u793a",shadeClose:!0}):/\bstring|number\b/.test(typeof f)&&i.msg(f,{icon:5,shift:6}),n.mobile?v.scrollTop(function(){try{return(y?s.next():s).offset().top-15}catch(e){return 0}}()):setTimeout(function(){(y?s.next().find("input"):r).focus()},7),s.addClass(o),e=!0}}),e)return e}),!e&&(s=f.getValue(null,u),layui.event.call(this,l,"submit("+y+")",{elem:this,form:h,field:s}))},f=new u,v=t(document),h=t(window);t(function(){f.render()}),v.on("reset",r,function(){var e=t(this).attr("lay-filter");setTimeout(function(){f.render(null,e)},50)}),v.on("submit",r,d).on("click","*[lay-submit]",d),e(l,f)});layui.define("form",function(e){"use strict";var i=layui.$,a=layui.form,n=layui.layer,t="tree",r={config:{},index:layui[t]?layui[t].index+1e4:0,set:function(e){var a=this;return a.config=i.extend({},a.config,e),a},on:function(e,i){return layui.onevent.call(this,t,e,i)}},l=function(){var e=this,i=e.config,a=i.id||e.index;return l.that[a]=e,l.config[a]=i,{config:i,reload:function(i){e.reload.call(e,i)},getChecked:function(){return e.getChecked.call(e)},setChecked:function(i){return e.setChecked.call(e,i)}}},c="layui-hide",d="layui-disabled",s="layui-tree-set",o="layui-tree-iconClick",h="layui-icon-addition",u="layui-icon-subtraction",p="layui-tree-entry",f="layui-tree-main",y="layui-tree-txt",v="layui-tree-pack",C="layui-tree-spread",k="layui-tree-setLineShort",m="layui-tree-showLine",x="layui-tree-lineExtend",b=function(e){var a=this;a.index=++r.index,a.config=i.extend({},a.config,r.config,e),a.render()};b.prototype.config={data:[],showCheckbox:!1,showLine:!0,accordion:!1,onlyIconControl:!1,isJump:!1,edit:!1,text:{defaultNodeName:"\u672a\u547d\u540d",none:"\u65e0\u6570\u636e"}},b.prototype.reload=function(e){var a=this;layui.each(e,function(e,i){"array"===layui._typeof(i)&&delete a.config[e]}),a.config=i.extend(!0,{},a.config,e),a.render()},b.prototype.render=function(){var e=this,a=e.config;e.checkids=[];var n=i('
                                              ');e.tree(n);var t=a.elem=i(a.elem);if(t[0]){if(e.key=a.id||e.index,e.elem=n,e.elemNone=i('
                                              '+a.text.none+"
                                              "),t.html(e.elem),0==e.elem.find(".layui-tree-set").length)return e.elem.append(e.elemNone);a.showCheckbox&&e.renderForm("checkbox"),e.elem.find(".layui-tree-set").each(function(){var e=i(this);e.parent(".layui-tree-pack")[0]||e.addClass("layui-tree-setHide"),!e.next()[0]&&e.parents(".layui-tree-pack").eq(1).hasClass("layui-tree-lineExtend")&&e.addClass(k),e.next()[0]||e.parents(".layui-tree-set").eq(0).next()[0]||e.addClass(k)}),e.events()}},b.prototype.renderForm=function(e){a.render(e,"LAY-tree-"+this.index)},b.prototype.tree=function(e,a){var n=this,t=n.config,r=a||t.data;layui.each(r,function(a,r){var l=r.children&&r.children.length>0,o=i('
                                              "),h=i(['
                                              ','
                                              ','
                                              ',function(){return t.showLine?l?'':'':''}(),function(){return t.showCheckbox?'':""}(),function(){return t.isJump&&r.href?''+(r.title||r.label||t.text.defaultNodeName)+"":''+(r.title||r.label||t.text.defaultNodeName)+""}(),"
                                              ",function(){if(!t.edit)return"";var e={add:'',update:'',del:''},i=['
                                              '];return t.edit===!0&&(t.edit=["update","del"]),"object"==typeof t.edit?(layui.each(t.edit,function(a,n){i.push(e[n]||"")}),i.join("")+"
                                              "):void 0}(),"
                                              "].join(""));l&&(h.append(o),n.tree(o,r.children)),e.append(h),h.prev("."+s)[0]&&h.prev().children(".layui-tree-pack").addClass("layui-tree-showLine"),l||h.parent(".layui-tree-pack").addClass("layui-tree-lineExtend"),n.spread(h,r),t.showCheckbox&&(r.checked&&n.checkids.push(r.id),n.checkClick(h,r)),t.edit&&n.operate(h,r)})},b.prototype.spread=function(e,a){var n=this,t=n.config,r=e.children("."+p),l=r.children("."+f),c=r.find("."+o),k=r.find("."+y),m=t.onlyIconControl?c:l,x="";m.on("click",function(i){var a=e.children("."+v),n=m.children(".layui-icon")[0]?m.children(".layui-icon"):m.find(".layui-tree-icon").children(".layui-icon");if(a[0]){if(e.hasClass(C))e.removeClass(C),a.slideUp(200),n.removeClass(u).addClass(h);else if(e.addClass(C),a.slideDown(200),n.addClass(u).removeClass(h),t.accordion){var r=e.siblings("."+s);r.removeClass(C),r.children("."+v).slideUp(200),r.find(".layui-tree-icon").children(".layui-icon").removeClass(u).addClass(h)}}else x="normal"}),k.on("click",function(){var n=i(this);n.hasClass(d)||(x=e.hasClass(C)?t.onlyIconControl?"open":"close":t.onlyIconControl?"close":"open",t.click&&t.click({elem:e,state:x,data:a}))})},b.prototype.setCheckbox=function(e,i,a){var n=this,t=(n.config,a.prop("checked"));if(!a.prop("disabled")){if("object"==typeof i.children||e.find("."+v)[0]){var r=e.find("."+v).find('input[same="layuiTreeCheck"]');r.each(function(){this.disabled||(this.checked=t)})}var l=function(e){if(e.parents("."+s)[0]){var i,a=e.parent("."+v),n=a.parent(),r=a.prev().find('input[same="layuiTreeCheck"]');t?r.prop("checked",t):(a.find('input[same="layuiTreeCheck"]').each(function(){this.checked&&(i=!0)}),i||r.prop("checked",!1)),l(n)}};l(e),n.renderForm("checkbox")}},b.prototype.checkClick=function(e,a){var n=this,t=n.config,r=e.children("."+p),l=r.children("."+f);l.on("click",'input[same="layuiTreeCheck"]+',function(r){layui.stope(r);var l=i(this).prev(),c=l.prop("checked");l.prop("disabled")||(n.setCheckbox(e,a,l),t.oncheck&&t.oncheck({elem:e,checked:c,data:a}))})},b.prototype.operate=function(e,a){var t=this,r=t.config,l=e.children("."+p),d=l.children("."+f);l.children(".layui-tree-btnGroup").on("click",".layui-icon",function(l){layui.stope(l);var f=i(this).data("type"),b=e.children("."+v),g={data:a,type:f,elem:e};if("add"==f){b[0]||(r.showLine?(d.find("."+o).addClass("layui-tree-icon"),d.find("."+o).children(".layui-icon").addClass(h).removeClass("layui-icon-file")):d.find(".layui-tree-iconArrow").removeClass(c),e.append('
                                              '));var w=r.operate&&r.operate(g),N={};if(N.title=r.text.defaultNodeName,N.id=w,t.tree(e.children("."+v),[N]),r.showLine)if(b[0])b.hasClass(x)||b.addClass(x),e.find("."+v).each(function(){i(this).children("."+s).last().addClass(k)}),b.children("."+s).last().prev().hasClass(k)?b.children("."+s).last().prev().removeClass(k):b.children("."+s).last().removeClass(k),!e.parent("."+v)[0]&&e.next()[0]&&b.children("."+s).last().removeClass(k);else{var T=e.siblings("."+s),L=1,I=e.parent("."+v);layui.each(T,function(e,a){i(a).children("."+v)[0]||(L=0)}),1==L?(T.children("."+v).addClass(m),T.children("."+v).children("."+s).removeClass(k),e.children("."+v).addClass(m),I.removeClass(x),I.children("."+s).last().children("."+v).children("."+s).last().addClass(k)):e.children("."+v).children("."+s).addClass(k)}if(!r.showCheckbox)return;if(d.find('input[same="layuiTreeCheck"]')[0].checked){var A=e.children("."+v).children("."+s).last();A.find('input[same="layuiTreeCheck"]')[0].checked=!0}t.renderForm("checkbox")}else if("update"==f){var F=d.children("."+y).html();d.children("."+y).html(""),d.append(''),d.children(".layui-tree-editInput").val(F).focus();var j=function(e){var i=e.val().trim();i=i?i:r.text.defaultNodeName,e.remove(),d.children("."+y).html(i),g.data.title=i,r.operate&&r.operate(g)};d.children(".layui-tree-editInput").blur(function(){j(i(this))}),d.children(".layui-tree-editInput").on("keydown",function(e){13===e.keyCode&&(e.preventDefault(),j(i(this)))})}else n.confirm('\u786e\u8ba4\u5220\u9664\u8be5\u8282\u70b9 "'+(a.title||"")+'" \u5417\uff1f',function(a){if(r.operate&&r.operate(g),g.status="remove",n.close(a),!e.prev("."+s)[0]&&!e.next("."+s)[0]&&!e.parent("."+v)[0])return e.remove(),void t.elem.append(t.elemNone);if(e.siblings("."+s).children("."+p)[0]){if(r.showCheckbox){var l=function(e){if(e.parents("."+s)[0]){var a=e.siblings("."+s).children("."+p),n=e.parent("."+v).prev(),r=n.find('input[same="layuiTreeCheck"]')[0],c=1,d=0;0==r.checked&&(a.each(function(e,a){var n=i(a).find('input[same="layuiTreeCheck"]')[0];0!=n.checked||n.disabled||(c=0),n.disabled||(d=1)}),1==c&&1==d&&(r.checked=!0,t.renderForm("checkbox"),l(n.parent("."+s))))}};l(e)}if(r.showLine){var d=e.siblings("."+s),h=1,f=e.parent("."+v);layui.each(d,function(e,a){i(a).children("."+v)[0]||(h=0)}),1==h?(b[0]||(f.removeClass(x),d.children("."+v).addClass(m),d.children("."+v).children("."+s).removeClass(k)),e.next()[0]?f.children("."+s).last().children("."+v).children("."+s).last().addClass(k):e.prev().children("."+v).children("."+s).last().addClass(k),e.next()[0]||e.parents("."+s)[1]||e.parents("."+s).eq(0).next()[0]||e.prev("."+s).addClass(k)):!e.next()[0]&&e.hasClass(k)&&e.prev().addClass(k)}}else{var y=e.parent("."+v).prev();if(r.showLine){y.find("."+o).removeClass("layui-tree-icon"),y.find("."+o).children(".layui-icon").removeClass(u).addClass("layui-icon-file");var w=y.parents("."+v).eq(0);w.addClass(x),w.children("."+s).each(function(){i(this).children("."+v).children("."+s).last().addClass(k)})}else y.find(".layui-tree-iconArrow").addClass(c);e.parents("."+s).eq(0).removeClass(C),e.parent("."+v).remove()}e.remove()})})},b.prototype.events=function(){var e=this,a=e.config;e.elem.find(".layui-tree-checkedFirst");e.setChecked(e.checkids),e.elem.find(".layui-tree-search").on("keyup",function(){var n=i(this),t=n.val(),r=n.nextAll(),l=[];r.find("."+y).each(function(){var e=i(this).parents("."+p);if(i(this).html().indexOf(t)!=-1){l.push(i(this).parent());var a=function(e){e.addClass("layui-tree-searchShow"),e.parent("."+v)[0]&&a(e.parent("."+v).parent("."+s))};a(e.parent("."+s))}}),r.find("."+p).each(function(){var e=i(this).parent("."+s);e.hasClass("layui-tree-searchShow")||e.addClass(c)}),0==r.find(".layui-tree-searchShow").length&&e.elem.append(e.elemNone),a.onsearch&&a.onsearch({elem:l})}),e.elem.find(".layui-tree-search").on("keydown",function(){i(this).nextAll().find("."+p).each(function(){var e=i(this).parent("."+s);e.removeClass("layui-tree-searchShow "+c)}),i(".layui-tree-emptyText")[0]&&i(".layui-tree-emptyText").remove()})},b.prototype.getChecked=function(){var e=this,a=e.config,n=[],t=[];e.elem.find(".layui-form-checked").each(function(){n.push(i(this).prev()[0].value)});var r=function(e,a){layui.each(e,function(e,t){layui.each(n,function(e,n){if(t.id==n){var l=i.extend({},t);return delete l.children,a.push(l),t.children&&(l.children=[],r(t.children,l.children)),!0}})})};return r(i.extend({},a.data),t),t},b.prototype.setChecked=function(e){var a=this;a.config;a.elem.find("."+s).each(function(a,n){var t=i(this).data("id"),r=i(n).children("."+p).find('input[same="layuiTreeCheck"]'),l=r.next();if("number"==typeof e){if(t==e)return r[0].checked||l.click(),!1}else"object"==typeof e&&layui.each(e,function(e,i){if(i==t&&!r[0].checked)return l.click(),!0})})},l.that={},l.config={},r.reload=function(e,i){var a=l.that[e];return a.reload(i),l.call(a)},r.getChecked=function(e){var i=l.that[e];return i.getChecked()},r.setChecked=function(e,i){var a=l.that[e];return a.setChecked(i)},r.render=function(e){var i=new b(e);return l.call(i)},e(t,r)});layui.define(["laytpl","form"],function(e){"use strict";var a=layui.$,t=layui.laytpl,i=layui.form,n="transfer",l={config:{},index:layui[n]?layui[n].index+1e4:0,set:function(e){var t=this;return t.config=a.extend({},t.config,e),t},on:function(e,a){return layui.onevent.call(this,n,e,a)}},r=function(){var e=this,a=e.config,t=a.id||e.index;return r.that[t]=e,r.config[t]=a,{config:a,reload:function(a){e.reload.call(e,a)},getData:function(){return e.getData.call(e)}}},c="layui-hide",o="layui-btn-disabled",d="layui-none",s="layui-transfer-box",u="layui-transfer-header",h="layui-transfer-search",f="layui-transfer-active",y="layui-transfer-data",p=function(e){return e=e||{},['
                                              ','
                                              ','","
                                              ","{{# if(d.data.showSearch){ }}",'","{{# } }}",'
                                                ',"
                                                "].join("")},v=['
                                                ',p({index:0,checkAllName:"layTransferLeftCheckAll"}),'
                                                ','",'","
                                                ",p({index:1,checkAllName:"layTransferRightCheckAll"}),"
                                                "].join(""),x=function(e){var t=this;t.index=++l.index,t.config=a.extend({},t.config,l.config,e),t.render()};x.prototype.config={title:["\u5217\u8868\u4e00","\u5217\u8868\u4e8c"],width:200,height:360,data:[],value:[],showSearch:!1,id:"",text:{none:"\u65e0\u6570\u636e",searchNone:"\u65e0\u5339\u914d\u6570\u636e"}},x.prototype.reload=function(e){var t=this;t.config=a.extend({},t.config,e),t.render()},x.prototype.render=function(){var e=this,i=e.config,n=e.elem=a(t(v).render({data:i,index:e.index})),l=i.elem=a(i.elem);l[0]&&(i.data=i.data||[],i.value=i.value||[],e.key=i.id||e.index,l.html(e.elem),e.layBox=e.elem.find("."+s),e.layHeader=e.elem.find("."+u),e.laySearch=e.elem.find("."+h),e.layData=n.find("."+y),e.layBtn=n.find("."+f+" .layui-btn"),e.layBox.css({width:i.width,height:i.height}),e.layData.css({height:function(){return i.height-e.layHeader.outerHeight()-e.laySearch.outerHeight()-2}()}),e.renderData(),e.events())},x.prototype.renderData=function(){var e=this,a=(e.config,[{checkName:"layTransferLeftCheck",views:[]},{checkName:"layTransferRightCheck",views:[]}]);e.parseData(function(e){var t=e.selected?1:0,i=["
                                              • ",'',"
                                              • "].join("");a[t].views.push(i),delete e.selected}),e.layData.eq(0).html(a[0].views.join("")),e.layData.eq(1).html(a[1].views.join("")),e.renderCheckBtn()},x.prototype.renderForm=function(e){i.render(e,"LAY-transfer-"+this.index)},x.prototype.renderCheckBtn=function(e){var t=this,i=t.config;e=e||{},t.layBox.each(function(n){var l=a(this),r=l.find("."+y),d=l.find("."+u).find('input[type="checkbox"]'),s=r.find('input[type="checkbox"]'),h=0,f=!1;if(s.each(function(){var e=a(this).data("hide");(this.checked||this.disabled||e)&&h++,this.checked&&!e&&(f=!0)}),d.prop("checked",f&&h===s.length),t.layBtn.eq(n)[f?"removeClass":"addClass"](o),!e.stopNone){var p=r.children("li:not(."+c+")").length;t.noneView(r,p?"":i.text.none)}}),t.renderForm("checkbox")},x.prototype.noneView=function(e,t){var i=a('

                                                '+(t||"")+"

                                                ");e.find("."+d)[0]&&e.find("."+d).remove(),t.replace(/\s/g,"")&&e.append(i)},x.prototype.setValue=function(){var e=this,t=e.config,i=[];return e.layBox.eq(1).find("."+y+' input[type="checkbox"]').each(function(){var e=a(this).data("hide");e||i.push(this.value)}),t.value=i,e},x.prototype.parseData=function(e){var t=this,i=t.config,n=[];return layui.each(i.data,function(t,l){l=("function"==typeof i.parseData?i.parseData(l):l)||l,n.push(l=a.extend({},l)),layui.each(i.value,function(e,a){a==l.value&&(l.selected=!0)}),e&&e(l)}),i.data=n,t},x.prototype.getData=function(e){var a=this,t=a.config,i=[];return a.setValue(),layui.each(e||t.value,function(e,a){layui.each(t.data,function(e,t){delete t.selected,a==t.value&&i.push(t)})}),i},x.prototype.events=function(){var e=this,t=e.config;e.elem.on("click",'input[lay-filter="layTransferCheckbox"]+',function(){var t=a(this).prev(),i=t[0].checked,n=t.parents("."+s).eq(0).find("."+y);t[0].disabled||("all"===t.attr("lay-type")&&n.find('input[type="checkbox"]').each(function(){this.disabled||(this.checked=i)}),e.renderCheckBtn({stopNone:!0}))}),e.layBtn.on("click",function(){var i=a(this),n=i.data("index"),l=e.layBox.eq(n),r=[];if(!i.hasClass(o)){e.layBox.eq(n).each(function(t){var i=a(this),n=i.find("."+y);n.children("li").each(function(){var t=a(this),i=t.find('input[type="checkbox"]'),n=i.data("hide");i[0].checked&&!n&&(i[0].checked=!1,l.siblings("."+s).find("."+y).append(t.clone()),t.remove(),r.push(i[0].value)),e.setValue()})}),e.renderCheckBtn();var c=l.siblings("."+s).find("."+h+" input");""===c.val()||c.trigger("keyup"),t.onchange&&t.onchange(e.getData(r),n)}}),e.laySearch.find("input").on("keyup",function(){var i=this.value,n=a(this).parents("."+h).eq(0).siblings("."+y),l=n.children("li");l.each(function(){var e=a(this),t=e.find('input[type="checkbox"]'),n=t[0].title.indexOf(i)!==-1;e[n?"removeClass":"addClass"](c),t.data("hide",!n)}),e.renderCheckBtn();var r=l.length===n.children("li."+c).length;e.noneView(n,r?t.text.searchNone:"")})},r.that={},r.config={},l.reload=function(e,a){var t=r.that[e];return t.reload(a),r.call(t)},l.getData=function(e){var a=r.that[e];return a.getData()},l.render=function(e){var a=new x(e);return r.call(a)},e(n,l)});layui.define(["lay","laytpl","laypage","layer","form","util"],function(e){"use strict";var t=layui.$,i=(layui.lay,layui.laytpl),a=layui.laypage,l=layui.layer,n=layui.form,o=layui.util,r=layui.hint(),d=layui.device(),c={config:{checkName:"LAY_CHECKED",indexName:"LAY_TABLE_INDEX"},cache:{},index:layui.table?layui.table.index+1e4:0,set:function(e){var i=this;return i.config=t.extend({},i.config,e),i},on:function(e,t){return layui.onevent.call(this,h,e,t)}},s=function(){var e=this,t=e.config,i=t.id||t.index;return i&&(s.that[i]=e,s.config[i]=t),{config:t,reload:function(t,i){e.reload.call(e,t,i)},setColsWidth:function(){e.setColsWidth.call(e)},resize:function(){e.resize.call(e)}}},u=function(e){var t=s.config[e];return t||r.error(e?"The table instance with ID '"+e+"' not found":"ID argument required"),t||null},y=function(e,a,l,n){var r=this.config||{};r.escape&&(a=o.escape(a));var d=e.templet?function(){return"function"==typeof e.templet?e.templet(l):i(t(e.templet).html()||String(a)).render(l)}():a;return n?t("
                                                "+d+"
                                                ").text():d},h="table",f=".layui-table",p="layui-hide",v="layui-none",m="layui-table-view",g=".layui-table-tool",b=".layui-table-box",x=".layui-table-init",k=".layui-table-header",C=".layui-table-body",w=".layui-table-main",T=".layui-table-fixed",N=".layui-table-fixed-l",L=".layui-table-fixed-r",S=".layui-table-total",_=".layui-table-page",A=".layui-table-sort",R="layui-table-edit",W="layui-table-hover",z=function(e){var t='{{#if(item2.colspan){}} colspan="{{item2.colspan}}"{{#} if(item2.rowspan){}} rowspan="{{item2.rowspan}}"{{#}}}';return e=e||{},['',"","{{# layui.each(d.data.cols, function(i1, item1){ }}","","{{# layui.each(item1, function(i2, item2){ }}",'{{# if(item2.fixed && item2.fixed !== "right"){ left = true; } }}','{{# if(item2.fixed === "right"){ right = true; } }}',function(){return e.fixed&&"right"!==e.fixed?'{{# if(item2.fixed && item2.fixed !== "right"){ }}':"right"===e.fixed?'{{# if(item2.fixed === "right"){ }}':""}(),"{{# var isSort = !(item2.colGroup) && item2.sort; }}",'",e.fixed?"{{# }; }}":"","{{# }); }}","","{{# }); }}","","
                                                ','
                                                ','{{# if(item2.type === "checkbox"){ }}','',"{{# } else { }}",'{{item2.title||""}}',"{{# if(isSort){ }}",'',"{{# } }}","{{# } }}","
                                                ","
                                                "].join("")},E=['',"","
                                                "].join(""),F=['
                                                ',"{{# if(d.data.toolbar){ }}",'
                                                ','
                                                ','
                                                ',"
                                                ","{{# } }}",'
                                                ',"{{# if(d.data.loading){ }}",'
                                                ','',"
                                                ","{{# } }}","{{# var left, right; }}",'
                                                ',z(),"
                                                ",'
                                                ',E,"
                                                ","{{# if(left){ }}",'
                                                ','
                                                ',z({fixed:!0}),"
                                                ",'
                                                ',E,"
                                                ","
                                                ","{{# }; }}","{{# if(right){ }}",'
                                                ','
                                                ',z({fixed:"right"}),'
                                                ',"
                                                ",'
                                                ',E,"
                                                ","
                                                ","{{# }; }}","
                                                ","{{# if(d.data.totalRow){ }}",'
                                                ','','',"
                                                ","
                                                ","{{# } }}","{{# if(d.data.page){ }}",'
                                                ','
                                                ',"
                                                ","{{# } }}","","
                                                "].join(""),I=t(window),j=t(document),H=function(e){var i=this;i.index=++c.index,i.config=t.extend({},i.config,c.config,e),i.render()};H.prototype.config={limit:10,loading:!0,cellMinWidth:60,defaultToolbar:["filter","exports","print"],autoSort:!0,text:{none:"\u65e0\u6570\u636e"}},H.prototype.render=function(){var e=this,a=e.config;if(a.elem=t(a.elem),a.where=a.where||{},a.id=a.id||a.elem.attr("id")||e.index,a.request=t.extend({pageName:"page",limitName:"limit"},a.request),a.response=t.extend({statusName:"code",statusCode:0,msgName:"msg",dataName:"data",totalRowName:"totalRow",countName:"count"},a.response),"object"==typeof a.page&&(a.limit=a.page.limit||a.limit,a.limits=a.page.limits||a.limits,e.page=a.page.curr=a.page.curr||1,delete a.page.elem,delete a.page.jump),!a.elem[0])return e;a.height&&/^full-\d+$/.test(a.height)&&(e.fullHeightGap=a.height.split("-")[1],a.height=I.height()-e.fullHeightGap),e.setInit();var l=a.elem,n=l.next("."+m),o=e.elem=t(i(F).render({VIEW_CLASS:m,data:a,index:e.index}));if(a.index=e.index,e.key=a.id||a.index,n[0]&&n.remove(),l.after(o),e.layTool=o.find(g),e.layBox=o.find(b),e.layHeader=o.find(k),e.layMain=o.find(w),e.layBody=o.find(C),e.layFixed=o.find(T),e.layFixLeft=o.find(N),e.layFixRight=o.find(L),e.layTotal=o.find(S),e.layPage=o.find(_),e.renderToolbar(),e.fullSize(),a.cols.length>1){var r=e.layFixed.find(k).find("th");r.height(e.layHeader.height()-1-parseFloat(r.css("padding-top"))-parseFloat(r.css("padding-bottom")))}e.pullData(e.page),e.events()},H.prototype.initOpts=function(e){var t=this,i=(t.config,{checkbox:48,radio:48,space:15,numbers:40});e.checkbox&&(e.type="checkbox"),e.space&&(e.type="space"),e.type||(e.type="normal"),"normal"!==e.type&&(e.unresize=!0,e.width=e.width||i[e.type])},H.prototype.setInit=function(e){var t=this,i=t.config;return i.clientWidth=i.width||function(){var e=function(t){var a,l;t=t||i.elem.parent(),a=t.width();try{l="none"===t.css("display")}catch(n){}return!t[0]||a&&!l?a:e(t.parent())};return e()}(),"width"===e?i.clientWidth:void layui.each(i.cols,function(e,a){layui.each(a,function(l,n){if(!n)return void a.splice(l,1);if(n.key=e+"-"+l,n.hide=n.hide||!1,n.colGroup||n.colspan>1){var o=0;layui.each(i.cols[e+1],function(t,i){i.HAS_PARENT||o>1&&o==n.colspan||(i.HAS_PARENT=!0,i.parentKey=e+"-"+l,o+=parseInt(i.colspan>1?i.colspan:1))}),n.colGroup=!0}t.initOpts(n)})})},H.prototype.renderToolbar=function(){var e=this,a=e.config,l=['
                                                ','
                                                ','
                                                '].join(""),n=e.layTool.find(".layui-table-tool-temp");if("default"===a.toolbar)n.html(l);else if("string"==typeof a.toolbar){var o=t(a.toolbar).html()||"";o&&n.html(i(o).render(a))}var r={filter:{title:"\u7b5b\u9009\u5217",layEvent:"LAYTABLE_COLS",icon:"layui-icon-cols"},exports:{title:"\u5bfc\u51fa",layEvent:"LAYTABLE_EXPORT",icon:"layui-icon-export"},print:{title:"\u6253\u5370",layEvent:"LAYTABLE_PRINT",icon:"layui-icon-print"}},d=[];"object"==typeof a.defaultToolbar&&layui.each(a.defaultToolbar,function(e,t){var i="string"==typeof t?r[t]:t;i&&d.push('
                                                ')}),e.layTool.find(".layui-table-tool-self").html(d.join(""))},H.prototype.setParentCol=function(e,t){var i=this,a=i.config,l=i.layHeader.find('th[data-key="'+a.index+"-"+t+'"]'),n=parseInt(l.attr("colspan"))||0;if(l[0]){var o=t.split("-"),r=a.cols[o[0]][o[1]];e?n--:n++,l.attr("colspan",n),l[n<1?"addClass":"removeClass"](p),r.colspan=n,r.hide=n<1;var d=l.data("parentkey");d&&i.setParentCol(e,d)}},H.prototype.setColsPatch=function(){var e=this,t=e.config;layui.each(t.cols,function(t,i){layui.each(i,function(t,i){i.hide&&e.setParentCol(i.hide,i.parentKey)})})},H.prototype.setColsWidth=function(){var e=this,t=e.config,i=0,a=0,l=0,n=0,o=e.setInit("width");e.eachCols(function(e,t){t.hide||i++}),o=o-function(){return"line"===t.skin||"nob"===t.skin?2:i+1}()-e.getScrollWidth(e.layMain[0])-1;var r=function(e){layui.each(t.cols,function(i,r){layui.each(r,function(i,d){var c=0,s=d.minWidth||t.cellMinWidth;return d?void(d.colGroup||d.hide||(e?l&&ln&&a&&(l=(o-n)/a)};r(),r(!0),e.autoColNums=a,e.eachCols(function(i,a){var n=a.minWidth||t.cellMinWidth;a.colGroup||a.hide||(0===a.width?e.getCssRule(t.index+"-"+a.key,function(e){e.style.width=Math.floor(l>=n?l:n)+"px"}):/\d+%$/.test(a.width)&&e.getCssRule(t.index+"-"+a.key,function(e){e.style.width=Math.floor(parseFloat(a.width)/100*o)+"px"}))});var d=e.layMain.width()-e.getScrollWidth(e.layMain[0])-e.layMain.children("table").outerWidth();if(e.autoColNums&&d>=-i&&d<=i){var c=function(t){var i;return t=t||e.layHeader.eq(0).find("thead th:last-child"),i=t.data("field"),!i&&t.prev()[0]?c(t.prev()):t},s=c(),u=s.data("key");e.getCssRule(u,function(t){var i=t.style.width||s.outerWidth();t.style.width=parseFloat(i)+d+"px",e.layMain.height()-e.layMain.prop("clientHeight")>0&&(t.style.width=parseFloat(t.style.width)-1+"px")})}e.loading(!0)},H.prototype.resize=function(){var e=this;e.fullSize(),e.setColsWidth(),e.scrollPatch()},H.prototype.reload=function(e,i){var a=this;e=e||{},delete a.haveInit,layui.each(e,function(e,t){"array"===layui._typeof(t)&&delete a.config[e]}),a.config=t.extend(i,{},a.config,e),a.render()},H.prototype.errorView=function(e){var i=this,a=i.layMain.find("."+v),l=t('
                                                '+(e||"Error")+"
                                                ");a[0]&&(i.layNone.remove(),a.remove()),i.layFixed.addClass(p),i.layMain.find("tbody").html(""),i.layMain.append(i.layNone=l),c.cache[i.key]=[]},H.prototype.page=1,H.prototype.pullData=function(e){var i=this,a=i.config,l=a.request,n=a.response,o=function(){"object"==typeof a.initSort&&i.sort(a.initSort.field,a.initSort.type)};if(i.startTime=(new Date).getTime(),a.url){var r={};r[l.pageName]=e,r[l.limitName]=a.limit;var d=t.extend(r,a.where);a.contentType&&0==a.contentType.indexOf("application/json")&&(d=JSON.stringify(d)),i.loading(),t.ajax({type:a.method||"get",url:a.url,contentType:a.contentType,data:d,dataType:"json",headers:a.headers||{},success:function(t){"function"==typeof a.parseData&&(t=a.parseData(t)||t),t[n.statusName]!=n.statusCode?(i.renderForm(),i.errorView(t[n.msgName]||'\u8fd4\u56de\u7684\u6570\u636e\u4e0d\u7b26\u5408\u89c4\u8303\uff0c\u6b63\u786e\u7684\u6210\u529f\u72b6\u6001\u7801\u5e94\u4e3a\uff1a"'+n.statusName+'": '+n.statusCode)):(i.renderData(t,e,t[n.countName]),o(),a.time=(new Date).getTime()-i.startTime+" ms"),i.setColsWidth(),"function"==typeof a.done&&a.done(t,e,t[n.countName])},error:function(e,t){i.errorView("\u8bf7\u6c42\u5f02\u5e38\uff0c\u9519\u8bef\u63d0\u793a\uff1a"+t),i.renderForm(),i.setColsWidth(),"function"==typeof a.error&&a.error(e,t)}})}else if("array"===layui._typeof(a.data)){var c={},s=e*a.limit-a.limit;c[n.dataName]=a.data.concat().splice(s,a.limit),c[n.countName]=a.data.length,"object"==typeof a.totalRow&&(c[n.totalRowName]=t.extend({},a.totalRow)),i.renderData(c,e,c[n.countName]),o(),i.setColsWidth(),"function"==typeof a.done&&a.done(c,e,c[n.countName])}},H.prototype.eachCols=function(e){var t=this;return c.eachCols(null,e,t.config.cols),t},H.prototype.renderData=function(e,n,o,r){var d=this,s=d.config,u=e[s.response.dataName]||[],h=e[s.response.totalRowName],f=[],m=[],g=[],b=function(){var e;return!r&&d.sortKey?d.sort(d.sortKey.field,d.sortKey.sort,!0):(layui.each(u,function(a,l){var o=[],u=[],h=[],v=a+s.limit*(n-1)+1;"array"===layui._typeof(l)&&0===l.length||(r||(l[c.config.indexName]=a),d.eachCols(function(n,r){var f=r.field||n,m=s.index+"-"+r.key,g=l[f];if(void 0!==g&&null!==g||(g=""),!r.colGroup){var b=['','
                                                '+function(){var n=t.extend(!0,{LAY_INDEX:v,LAY_COL:r},l),o=c.config.checkName;switch(r.type){case"checkbox":return'";case"radio":return n[o]&&(e=a),'';case"numbers":return v}return r.toolbar?i(t(r.toolbar).html()||"").render(n):y.call(d,r,g,n)}(),"
                                                "].join("");o.push(b),r.fixed&&"right"!==r.fixed&&u.push(b),"right"===r.fixed&&h.push(b)}}),f.push(''+o.join("")+""),m.push(''+u.join("")+""),g.push(''+h.join("")+""))}),d.layBody.scrollTop(0),d.layMain.find("."+v).remove(),d.layMain.find("tbody").html(f.join("")),d.layFixLeft.find("tbody").html(m.join("")),d.layFixRight.find("tbody").html(g.join("")),d.renderForm(),"number"==typeof e&&d.setThisRowChecked(e),d.syncCheckAll(),d.haveInit?d.scrollPatch():setTimeout(function(){d.scrollPatch()},50),d.haveInit=!0,l.close(d.tipsIndex),s.HAS_SET_COLS_PATCH||d.setColsPatch(),void(s.HAS_SET_COLS_PATCH=!0))};return c.cache[d.key]=u,d.layPage[0==o||0===u.length&&1==n?"addClass":"removeClass"](p),0===u.length?(d.renderForm(),d.errorView(s.text.none)):(d.layFixed.removeClass(p),r?b():(b(),d.renderTotal(u,h),void(s.page&&(s.page=t.extend({elem:"layui-table-page"+s.index,count:o,limit:s.limit,limits:s.limits||[10,20,30,40,50,60,70,80,90],groups:3,layout:["prev","page","next","skip","count","limit"],prev:'',next:'',jump:function(e,t){t||(d.page=e.curr,s.limit=e.limit,d.pullData(e.curr))}},s.page),s.page.count=o,a.render(s.page)))))},H.prototype.renderTotal=function(e,a){var l=this,n=l.config,o={};if(n.totalRow){layui.each(e,function(e,t){"array"===layui._typeof(t)&&0===t.length||l.eachCols(function(e,i){var a=i.field||e,l=t[a];i.totalRow&&(o[a]=(o[a]||0)+(parseFloat(l)||0))})}),l.dataTotal={};var r=[];l.eachCols(function(e,d){var c=d.field||e,s=function(){var e,t=d.totalRowText||"",i=parseFloat(o[c]).toFixed(2),n={};return n[c]=i,e=d.totalRow?y.call(l,d,i,n)||t:t,a?a[d.field]||e:e}(),u=['','
                                                '+function(){var e=d.totalRow||n.totalRow;return"string"==typeof e?i(e).render(t.extend({TOTAL_NUMS:s},d)):s}(),"
                                                "].join("");d.field&&(l.dataTotal[c]=s),r.push(u)}),l.layTotal.find("tbody").html(""+r.join("")+"")}},H.prototype.getColElem=function(e,t){var i=this,a=i.config;return e.eq(0).find(".laytable-cell-"+(a.index+"-"+t)+":eq(0)")},H.prototype.renderForm=function(e){var t=this,i=(t.config,t.elem.attr("lay-filter"));n.render(e,i)},H.prototype.setThisRowChecked=function(e){var t=this,i=(t.config,"layui-table-click"),a=t.layBody.find('tr[data-index="'+e+'"]');a.addClass(i).siblings("tr").removeClass(i)},H.prototype.sort=function(e,i,a,l){var n,o,d=this,s={},u=d.config,y=u.elem.attr("lay-filter"),f=c.cache[d.key];"string"==typeof e&&(n=e,d.layHeader.find("th").each(function(i,a){var l=t(this),o=l.data("field");if(o===e)return e=l,n=o,!1}));try{var n=n||e.data("field"),p=e.data("key");if(d.sortKey&&!a&&n===d.sortKey.field&&i===d.sortKey.sort)return;var v=d.layHeader.find("th .laytable-cell-"+p).find(A);d.layHeader.find("th").find(A).removeAttr("lay-sort"),v.attr("lay-sort",i||null),d.layFixed.find("th")}catch(m){r.error("Table modules: sort field '"+n+"' not matched")}d.sortKey={field:n,sort:i},u.autoSort&&("asc"===i?o=layui.sort(f,n):"desc"===i?o=layui.sort(f,n,!0):(o=layui.sort(f,c.config.indexName),delete d.sortKey)),s[u.response.dataName]=o||f,d.renderData(s,d.page,d.count,!0),l&&layui.event.call(e,h,"sort("+y+")",{field:n,type:i})},H.prototype.loading=function(e){var i=this,a=i.config;a.loading&&(e?(i.layInit&&i.layInit.remove(),delete i.layInit,i.layBox.find(x).remove()):(i.layInit=t(['
                                                ','',"
                                                "].join("")),i.layBox.append(i.layInit)))},H.prototype.setCheckData=function(e,t){var i=this,a=i.config,l=c.cache[i.key];l[e]&&"array"!==layui._typeof(l[e])&&(l[e][a.checkName]=t)},H.prototype.syncCheckAll=function(){var e=this,t=e.config,i=e.layHeader.find('input[name="layTableCheckbox"]'),a=function(i){return e.eachCols(function(e,a){"checkbox"===a.type&&(a[t.checkName]=i)}),i};i[0]&&(c.checkStatus(e.key).isAll?(i[0].checked||(i.prop("checked",!0),e.renderForm("checkbox")),a(!0)):(i[0].checked&&(i.prop("checked",!1),e.renderForm("checkbox")),a(!1)))},H.prototype.getCssRule=function(e,t){var i=this,a=i.elem.find("style")[0],l=a.sheet||a.styleSheet||{},n=l.cssRules||l.rules;layui.each(n,function(i,a){if(a.selectorText===".laytable-cell-"+e)return t(a),!0})},H.prototype.fullSize=function(){var e,t=this,i=t.config,a=i.height;t.fullHeightGap&&(a=I.height()-t.fullHeightGap,a<135&&(a=135),t.elem.css("height",a)),a&&(e=parseFloat(a)-(t.layHeader.outerHeight()||38),i.toolbar&&(e-=t.layTool.outerHeight()||50),i.totalRow&&(e-=t.layTotal.outerHeight()||40),i.page&&(e-=t.layPage.outerHeight()||41),t.layMain.css("height",e-2))},H.prototype.getScrollWidth=function(e){var t=0;return e?t=e.offsetWidth-e.clientWidth:(e=document.createElement("div"),e.style.width="100px",e.style.height="100px",e.style.overflowY="scroll",document.body.appendChild(e),t=e.offsetWidth-e.clientWidth,document.body.removeChild(e)),t},H.prototype.scrollPatch=function(){var e=this,i=e.layMain.children("table"),a=e.layMain.width()-e.layMain.prop("clientWidth"),l=e.layMain.height()-e.layMain.prop("clientHeight"),n=(e.getScrollWidth(e.layMain[0]),i.outerWidth()-e.layMain.width()),o=function(e){if(a&&l){if(e=e.eq(0),!e.find(".layui-table-patch")[0]){var i=t('
                                                ');i.find("div").css({width:a}),e.find("tr").append(i)}}else e.find(".layui-table-patch").remove()};o(e.layHeader),o(e.layTotal);var r=e.layMain.height(),d=r-l;e.layFixed.find(C).css("height",i.height()>=d?d:"auto"),e.layFixRight[n>0?"removeClass":"addClass"](p),e.layFixRight.css("right",a-1)},H.prototype.events=function(){var e,i=this,a=i.config,o=t("body"),r={},s=i.layHeader.find("th"),u=".layui-table-cell",f=a.elem.attr("lay-filter");i.layTool.on("click","*[lay-event]",function(e){var o=t(this),r=o.attr("lay-event"),s=function(e){var l=t(e.list),n=t('
                                                  ');n.html(l),a.height&&n.css("max-height",a.height-(i.layTool.outerHeight()||50)),o.find(".layui-table-tool-panel")[0]||o.append(n),i.renderForm(),n.on("click",function(e){layui.stope(e)}),e.done&&e.done(n,l)};switch(layui.stope(e),j.trigger("table.tool.panel.remove"),l.close(i.tipsIndex),r){case"LAYTABLE_COLS":s({list:function(){var e=[];return i.eachCols(function(t,i){i.field&&"normal"==i.type&&e.push('
                                                • ')}),e.join("")}(),done:function(){n.on("checkbox(LAY_TABLE_TOOL_COLS)",function(e){var l=t(e.elem),n=this.checked,o=l.data("key"),r=l.data("parentkey");layui.each(a.cols,function(e,t){layui.each(t,function(t,l){if(e+"-"+t===o){var d=l.hide;l.hide=!n,i.elem.find('*[data-key="'+a.index+"-"+o+'"]')[n?"removeClass":"addClass"](p),d!=l.hide&&i.setParentCol(!n,r),i.resize()}})})})}});break;case"LAYTABLE_EXPORT":d.ie?l.tips("\u5bfc\u51fa\u529f\u80fd\u4e0d\u652f\u6301 IE\uff0c\u8bf7\u7528 Chrome \u7b49\u9ad8\u7ea7\u6d4f\u89c8\u5668\u5bfc\u51fa",this,{tips:3}):s({list:function(){return['
                                                • \u5bfc\u51fa\u5230 Csv \u6587\u4ef6
                                                • ','
                                                • \u5bfc\u51fa\u5230 Excel \u6587\u4ef6
                                                • '].join("")}(),done:function(e,l){l.on("click",function(){var e=t(this).data("type");c.exportFile.call(i,a.id,null,e)})}});break;case"LAYTABLE_PRINT":var u=window.open("\u6253\u5370\u7a97\u53e3","_blank"),y=[""].join(""),v=t(i.layHeader.html());v.append(i.layMain.find("table").html()),v.append(i.layTotal.find("table").html()),v.find("th.layui-table-patch").remove(),v.find(".layui-table-col-special").remove(),u.document.write(y+v.prop("outerHTML")),u.document.close(),u.print(),u.close()}layui.event.call(this,h,"toolbar("+f+")",t.extend({event:r,config:a},{}))}),s.on("mousemove",function(e){var i=t(this),a=i.offset().left,l=e.clientX-a;i.data("unresize")||r.resizeStart||(r.allowResize=i.width()-l<=10,o.css("cursor",r.allowResize?"col-resize":""))}).on("mouseleave",function(){t(this);r.resizeStart||o.css("cursor","")}).on("mousedown",function(e){var l=t(this);if(r.allowResize){var n=l.data("key");e.preventDefault(),r.resizeStart=!0,r.offset=[e.clientX,e.clientY],i.getCssRule(n,function(e){var t=e.style.width||l.outerWidth();r.rule=e,r.ruleWidth=parseFloat(t),r.minWidth=l.data("minwidth")||a.cellMinWidth})}}),j.on("mousemove",function(t){if(r.resizeStart){if(t.preventDefault(),r.rule){var a=r.ruleWidth+t.clientX-r.offset[0];a');return n[0].value=i.data("content")||l.text(),i.find("."+R)[0]||i.append(n),n.focus(),void layui.stope(e)}}).on("mouseenter","td",function(){b.call(this)}).on("mouseleave","td",function(){b.call(this,"hide")});var g="layui-table-grid-down",b=function(e){var i=t(this),a=i.children(u);if(!i.data("off"))if(e)i.find(".layui-table-grid-down").remove();else if(a.prop("scrollWidth")>a.outerWidth()){if(a.find("."+g)[0])return;i.append('
                                                  ')}};i.layBody.on("click","."+g,function(e){var n=t(this),o=n.parent(),r=o.children(u);i.tipsIndex=l.tips(['
                                                  ',r.html(),"
                                                  ",''].join(""),r[0],{tips:[3,""],time:-1,anim:-1,maxWidth:d.ios||d.android?300:i.elem.width()/2,isOutAnim:!1,skin:"layui-table-tips",success:function(e,t){e.find(".layui-table-tips-c").on("click",function(){l.close(t)})}}),layui.stope(e)}),i.layBody.on("click","*[lay-event]",function(){var e=t(this),a=e.parents("tr").eq(0).data("index");layui.event.call(this,h,"tool("+f+")",v.call(this,{event:e.attr("lay-event")})),i.setThisRowChecked(a)}),i.layMain.on("scroll",function(){var e=t(this),a=e.scrollLeft(),n=e.scrollTop();i.layHeader.scrollLeft(a),i.layTotal.scrollLeft(a),i.layFixed.find(C).scrollTop(n),l.close(i.tipsIndex)}),I.on("resize",function(){i.resize()})},function(){j.on("click",function(){j.trigger("table.remove.tool.panel")}),j.on("table.remove.tool.panel",function(){t(".layui-table-tool-panel").remove()})}(),c.init=function(e,i){i=i||{};var a=this,l=t(e?'table[lay-filter="'+e+'"]':f+"[lay-data]"),n="Table element property lay-data configuration item has a syntax error: ";return l.each(function(){var a=t(this),l=a.attr("lay-data");try{l=new Function("return "+l)()}catch(o){r.error(n+l,"error")}var d=[],s=t.extend({elem:this,cols:[],data:[],skin:a.attr("lay-skin"),size:a.attr("lay-size"),even:"string"==typeof a.attr("lay-even")},c.config,i,l);e&&a.hide(),a.find("thead>tr").each(function(e){s.cols[e]=[],t(this).children().each(function(i){var a=t(this),l=a.attr("lay-data");try{l=new Function("return "+l)()}catch(o){return r.error(n+l)}var c=t.extend({title:a.text(),colspan:a.attr("colspan")||0,rowspan:a.attr("rowspan")||0},l);c.colspan<2&&d.push(c),s.cols[e].push(c)})}),a.find("tbody>tr").each(function(e){var i=t(this),a={};i.children("td").each(function(e,i){var l=t(this),n=l.data("field");if(n)return a[n]=l.html()}),layui.each(d,function(e,t){var l=i.children("td").eq(e);a[t.field]=l.html()}),s.data[e]=a}),c.render(s)}),a},s.that={},s.config={},c.eachCols=function(e,i,a){var l=s.config[e]||{},n=[],o=0;a=t.extend(!0,[],a||l.cols),layui.each(a,function(e,t){layui.each(t,function(t,i){if(i.colGroup){var l=0;o++,i.CHILD_COLS=[],layui.each(a[e+1],function(e,t){t.PARENT_COL_INDEX||l>1&&l==i.colspan||(t.PARENT_COL_INDEX=o,i.CHILD_COLS.push(t),l+=parseInt(t.colspan>1?t.colspan:1))})}i.PARENT_COL_INDEX||n.push(i)})});var r=function(e){layui.each(e||n,function(e,t){return t.CHILD_COLS?r(t.CHILD_COLS):void("function"==typeof i&&i(e,t))})};r()},c.checkStatus=function(e){var t=0,i=0,a=[],l=c.cache[e]||[];return layui.each(l,function(e,l){return"array"===layui._typeof(l)?void i++:void(l[c.config.checkName]&&(t++,a.push(c.clearCacheKey(l))))}),{data:a,isAll:!!l.length&&t===l.length-i}},c.getData=function(e){var t=[],i=c.cache[e]||[];return layui.each(i,function(e,i){"array"!==layui._typeof(i)&&t.push(c.clearCacheKey(i))}),t},c.exportFile=function(e,t,i){var a=this;t=t||c.clearCacheKey(c.cache[e]),i=i||"csv";var l=s.that[e],n=s.config[e]||{},o={csv:"text/csv",xls:"application/vnd.ms-excel"}[i],u=document.createElement("a");return d.ie?r.error("IE_NOT_SUPPORT_EXPORTS"):(u.href="data:"+o+";charset=utf-8,\ufeff"+encodeURIComponent(function(){var i=[],n=[],o=[];return layui.each(t,function(t,a){var o=[];"object"==typeof e?(layui.each(e,function(e,a){0==t&&i.push(a||"")}),layui.each(c.clearCacheKey(a),function(e,t){o.push('"'+(t||"")+'"')})):c.eachCols(e,function(e,n){if(n.field&&"normal"==n.type&&!n.hide){ -var r=a[n.field];void 0!==r&&null!==r||(r=""),0==t&&i.push(n.title||""),o.push('"'+y.call(l,n,r,a,"text")+'"')}}),n.push(o.join(","))}),layui.each(a.dataTotal,function(e,t){o.push(t)}),i.join(",")+"\r\n"+n.join("\r\n")+"\r\n"+o.join(",")}()),u.download=(n.title||"table_"+(n.index||""))+"."+i,document.body.appendChild(u),u.click(),void document.body.removeChild(u))},c.resize=function(e){if(e){var t=u(e);if(!t)return;s.that[e].resize()}else layui.each(s.that,function(){this.resize()})},c.reload=function(e,t,i){var a=u(e);if(a){var l=s.that[e];return l.reload(t,i),s.call(l)}},c.render=function(e){var t=new H(e);return s.call(t)},c.clearCacheKey=function(e){return e=t.extend({},e),delete e[c.config.checkName],delete e[c.config.indexName],e},t(function(){c.init()}),e(h,c)});layui.define("jquery",function(e){"use strict";var i=layui.$,n=(layui.hint(),layui.device(),{config:{},set:function(e){var n=this;return n.config=i.extend({},n.config,e),n},on:function(e,i){return layui.onevent.call(this,t,e,i)}}),t="carousel",a="layui-this",l=">*[carousel-item]>*",o="layui-carousel-left",r="layui-carousel-right",d="layui-carousel-prev",s="layui-carousel-next",u="layui-carousel-arrow",c="layui-carousel-ind",m=function(e){var t=this;t.config=i.extend({},t.config,n.config,e),t.render()};m.prototype.config={width:"600px",height:"280px",full:!1,arrow:"hover",indicator:"inside",autoplay:!0,interval:3e3,anim:"",trigger:"click",index:0},m.prototype.render=function(){var e=this,n=e.config;n.elem=i(n.elem),n.elem[0]&&(e.elemItem=n.elem.find(l),n.index<0&&(n.index=0),n.index>=e.elemItem.length&&(n.index=e.elemItem.length-1),n.interval<800&&(n.interval=800),n.full?n.elem.css({position:"fixed",width:"100%",height:"100%",zIndex:9999}):n.elem.css({width:n.width,height:n.height}),n.elem.attr("lay-anim",n.anim),e.elemItem.eq(n.index).addClass(a),e.elemItem.length<=1||(e.indicator(),e.arrow(),e.autoplay(),e.events()))},m.prototype.reload=function(e){var n=this;clearInterval(n.timer),n.config=i.extend({},n.config,e),n.render()},m.prototype.prevIndex=function(){var e=this,i=e.config,n=i.index-1;return n<0&&(n=e.elemItem.length-1),n},m.prototype.nextIndex=function(){var e=this,i=e.config,n=i.index+1;return n>=e.elemItem.length&&(n=0),n},m.prototype.addIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index+e,n.index>=i.elemItem.length&&(n.index=0)},m.prototype.subIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index-e,n.index<0&&(n.index=i.elemItem.length-1)},m.prototype.autoplay=function(){var e=this,i=e.config;i.autoplay&&(clearInterval(e.timer),e.timer=setInterval(function(){e.slide()},i.interval))},m.prototype.arrow=function(){var e=this,n=e.config,t=i(['",'"].join(""));n.elem.attr("lay-arrow",n.arrow),n.elem.find("."+u)[0]&&n.elem.find("."+u).remove(),n.elem.append(t),t.on("click",function(){var n=i(this),t=n.attr("lay-type");e.slide(t)})},m.prototype.indicator=function(){var e=this,n=e.config,t=e.elemInd=i(['
                                                    ',function(){var i=[];return layui.each(e.elemItem,function(e){i.push("")}),i.join("")}(),"
                                                  "].join(""));n.elem.attr("lay-indicator",n.indicator),n.elem.find("."+c)[0]&&n.elem.find("."+c).remove(),n.elem.append(t),"updown"===n.anim&&t.css("margin-top",-(t.height()/2)),t.find("li").on("hover"===n.trigger?"mouseover":n.trigger,function(){var t=i(this),a=t.index();a>n.index?e.slide("add",a-n.index):al.length&&(l.value=l.length),parseInt(l.value)!==l.value&&(l.half||(l.value=Math.ceil(l.value)-l.value<.5?Math.ceil(l.value):Math.floor(l.value)));for(var n='
                                                    ",s=1;s<=l.length;s++){var r='
                                                  • ";l.half&&parseInt(l.value)!==l.value&&s==Math.ceil(l.value)?n=n+'
                                                  • ":n+=r}n+="
                                                  "+(l.text?''+l.value+"\u661f":"")+"";var c=l.elem,f=c.next("."+t);f[0]&&f.remove(),e.elemTemp=a(n),l.span=e.elemTemp.next("span"),l.setText&&l.setText(l.value),c.html(e.elemTemp),c.addClass("layui-inline"),l.readonly||e.action()},v.prototype.setvalue=function(e){var a=this,l=a.config;l.value=e,a.render()},v.prototype.action=function(){var e=this,l=e.config,i=e.elemTemp,n=i.find("i").width();i.children("li").each(function(e){var t=e+1,v=a(this);v.on("click",function(e){if(l.value=t,l.half){var o=e.pageX-a(this).offset().left;o<=n/2&&(l.value=l.value-.5)}l.text&&i.next("span").text(l.value+"\u661f"),l.choose&&l.choose(l.value),l.setText&&l.setText(l.value)}),v.on("mousemove",function(e){if(i.find("i").each(function(){a(this).addClass(o).removeClass(r)}),i.find("i:lt("+t+")").each(function(){a(this).addClass(u).removeClass(f)}),l.half){var c=e.pageX-a(this).offset().left;c<=n/2&&v.children("i").addClass(s).removeClass(u)}}),v.on("mouseleave",function(){i.find("i").each(function(){a(this).addClass(o).removeClass(r)}),i.find("i:lt("+Math.floor(l.value)+")").each(function(){a(this).addClass(u).removeClass(f)}),l.half&&parseInt(l.value)!==l.value&&i.children("li:eq("+Math.floor(l.value)+")").children("i").addClass(s).removeClass(c)})})},v.prototype.events=function(){var e=this;e.config},l.render=function(e){var a=new v(e);return i.call(a)},e(n,l)});layui.define("jquery",function(e){"use strict";var l=layui.$,o=function(e){},t='';o.prototype.load=function(e){var o,i,n,r,a=this,c=0;e=e||{};var m=l(e.elem);if(m[0]){var f=l(e.scrollElem||document),u=e.mb||50,s=!("isAuto"in e)||e.isAuto,y=e.end||"\u6ca1\u6709\u66f4\u591a\u4e86",v=e.scrollElem&&e.scrollElem!==document,d="\u52a0\u8f7d\u66f4\u591a",h=l('");m.find(".layui-flow-more")[0]||m.append(h);var p=function(e,t){e=l(e),h.before(e),t=0==t||null,t?h.html(y):h.find("a").html(d),i=t,o=null,n&&n()},g=function(){o=!0,h.find("a").html(t),"function"==typeof e.done&&e.done(++c,p)};if(g(),h.find("a").on("click",function(){l(this);i||o||g()}),e.isLazyimg)var n=a.lazyimg({elem:e.elem+" img",scrollElem:e.scrollElem});return s?(f.on("scroll",function(){var e=l(this),t=e.scrollTop();r&&clearTimeout(r),!i&&m.width()&&(r=setTimeout(function(){var i=v?e.height():l(window).height(),n=v?e.prop("scrollHeight"):document.documentElement.scrollHeight;n-t-i<=u&&(o||g())},100))}),a):a}},o.prototype.lazyimg=function(e){var o,t=this,i=0;e=e||{};var n=l(e.scrollElem||document),r=e.elem||"img",a=e.scrollElem&&e.scrollElem!==document,c=function(e,l){var o=n.scrollTop(),r=o+l,c=a?function(){return e.offset().top-n.offset().top+o}():e.offset().top;if(c>=o&&c<=r&&e.attr("lay-src")){var f=e.attr("lay-src");layui.img(f,function(){var l=t.lazyimg.elem.eq(i);e.attr("src",f).removeAttr("lay-src"),l[0]&&m(l),i++},function(){t.lazyimg.elem.eq(i);e.removeAttr("lay-src")})}},m=function(e,o){var m=a?(o||n).height():l(window).height(),f=n.scrollTop(),u=f+m;if(t.lazyimg.elem=l(r),e)c(e,m);else for(var s=0;su)break}};if(m(),!o){var f;n.on("scroll",function(){var e=l(this);f&&clearTimeout(f),f=setTimeout(function(){m(null,e)},50)}),o=!0}return m},e("flow",new o)});layui.define(["layer","form"],function(t){"use strict";var e=layui.$,i=layui.layer,a=layui.form,l=(layui.hint(),layui.device()),n="layedit",o="layui-show",r="layui-disabled",c=function(){var t=this;t.index=0,t.config={tool:["strong","italic","underline","del","|","left","center","right","|","link","unlink","face","image"],hideTool:[],height:280}};c.prototype.set=function(t){var i=this;return e.extend(!0,i.config,t),i},c.prototype.on=function(t,e){return layui.onevent(n,t,e)},c.prototype.build=function(t,i){i=i||{};var a=this,n=a.config,r="layui-layedit",c=e("string"==typeof t?"#"+t:t),u="LAY_layedit_"+ ++a.index,d=c.next("."+r),y=e.extend({},n,i),f=function(){var t=[],e={};return layui.each(y.hideTool,function(t,i){e[i]=!0}),layui.each(y.tool,function(i,a){C[a]&&!e[a]&&t.push(C[a])}),t.join("")}(),m=e(['
                                                  ','
                                                  '+f+"
                                                  ",'
                                                  ','',"
                                                  ","
                                                  "].join(""));return l.ie&&l.ie<8?c.removeClass("layui-hide").addClass(o):(d[0]&&d.remove(),s.call(a,m,c[0],y),c.addClass("layui-hide").after(m),a.index)},c.prototype.getContent=function(t){var e=u(t);if(e[0])return d(e[0].document.body.innerHTML)},c.prototype.getText=function(t){var i=u(t);if(i[0])return e(i[0].document.body).text()},c.prototype.setContent=function(t,i,a){var l=u(t);l[0]&&(a?e(l[0].document.body).append(i):e(l[0].document.body).html(i),layedit.sync(t))},c.prototype.sync=function(t){var i=u(t);if(i[0]){var a=e("#"+i[1].attr("textarea"));a.val(d(i[0].document.body.innerHTML))}},c.prototype.getSelection=function(t){var e=u(t);if(e[0]){var i=m(e[0].document);return document.selection?i.text:i.toString()}};var s=function(t,i,a){var l=this,n=t.find("iframe");n.css({height:a.height}).on("load",function(){var o=n.contents(),r=n.prop("contentWindow"),c=o.find("head"),s=e([""].join("")),u=o.find("body");c.append(s),u.attr("contenteditable","true").css({"min-height":a.height}).html(i.value||""),y.apply(l,[r,n,i,a]),g.call(l,r,t,a)})},u=function(t){var i=e("#LAY_layedit_"+t),a=i.prop("contentWindow");return[a,i]},d=function(t){return 8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),t},y=function(t,a,n,o){var r=t.document,c=e(r.body);c.on("keydown",function(t){var e=t.keyCode;if(13===e){var a=m(r),l=p(a),n=l.parentNode;if("pre"===n.tagName.toLowerCase()){if(t.shiftKey)return;return i.msg("\u8bf7\u6682\u65f6\u7528shift+enter"),!1}r.execCommand("formatBlock",!1,"

                                                  ")}}),e(n).parents("form").on("submit",function(){var t=c.html();8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),n.value=t}),c.on("paste",function(e){r.execCommand("formatBlock",!1,"

                                                  "),setTimeout(function(){f.call(t,c),n.value=c.html()},100)})},f=function(t){var i=this;i.document;t.find("*[style]").each(function(){var t=this.style.textAlign;this.removeAttribute("style"),e(this).css({"text-align":t||""})}),t.find("table").addClass("layui-table"),t.find("script,link").remove()},m=function(t){return t.selection?t.selection.createRange():t.getSelection().getRangeAt(0)},p=function(t){return t.endContainer||t.parentElement().childNodes[0]},v=function(t,i,a){var l=this.document,n=document.createElement(t);for(var o in i)n.setAttribute(o,i[o]);if(n.removeAttribute("text"),l.selection){var r=a.text||i.text;if("a"===t&&!r)return;r&&(n.innerHTML=r),a.pasteHTML(e(n).prop("outerHTML")),a.select()}else{var r=a.toString()||i.text;if("a"===t&&!r)return;r&&(n.innerHTML=r),a.deleteContents(),a.insertNode(n)}},h=function(t,i){var a=this.document,l="layedit-tool-active",n=p(m(a)),o=function(e){return t.find(".layedit-tool-"+e)};i&&i[i.hasClass(l)?"removeClass":"addClass"](l),t.find(">i").removeClass(l),o("unlink").addClass(r),e(n).parents().each(function(){var t=this.tagName.toLowerCase(),e=this.style.textAlign;"b"!==t&&"strong"!==t||o("b").addClass(l),"i"!==t&&"em"!==t||o("i").addClass(l),"u"===t&&o("u").addClass(l),"strike"===t&&o("d").addClass(l),"p"===t&&("center"===e?o("center").addClass(l):"right"===e?o("right").addClass(l):o("left").addClass(l)),"a"===t&&(o("link").addClass(l),o("unlink").removeClass(r))})},g=function(t,a,l){var n=t.document,o=e(n.body),c={link:function(i){var a=p(i),l=e(a).parent();b.call(o,{href:l.attr("href"),target:l.attr("target")},function(e){var a=l[0];"A"===a.tagName?a.href=e.url:v.call(t,"a",{target:e.target,href:e.url,text:e.url},i)})},unlink:function(t){n.execCommand("unlink")},face:function(e){x.call(this,function(i){v.call(t,"img",{src:i.src,alt:i.alt},e)})},image:function(a){var n=this;layui.use("upload",function(o){var r=l.uploadImage||{};o.render({url:r.url,method:r.type,elem:e(n).find("input")[0],done:function(e){0==e.code?(e.data=e.data||{},v.call(t,"img",{src:e.data.src,alt:e.data.title},a)):i.msg(e.msg||"\u4e0a\u4f20\u5931\u8d25")}})})},code:function(e){k.call(o,function(i){v.call(t,"pre",{text:i.code,"lay-lang":i.lang},e)})},help:function(){i.open({type:2,title:"\u5e2e\u52a9",area:["600px","380px"],shadeClose:!0,shade:.1,skin:"layui-layer-msg",content:["","no"]})}},s=a.find(".layui-layedit-tool"),u=function(){var i=e(this),a=i.attr("layedit-event"),l=i.attr("lay-command");if(!i.hasClass(r)){o.focus();var u=m(n);u.commonAncestorContainer;l?(n.execCommand(l),/justifyLeft|justifyCenter|justifyRight/.test(l)&&n.execCommand("formatBlock",!1,"

                                                  "),setTimeout(function(){o.focus()},10)):c[a]&&c[a].call(this,u),h.call(t,s,i)}},d=/image/;s.find(">i").on("mousedown",function(){var t=e(this),i=t.attr("layedit-event");d.test(i)||u.call(this)}).on("click",function(){var t=e(this),i=t.attr("layedit-event");d.test(i)&&u.call(this)}),o.on("click",function(){h.call(t,s),i.close(x.index)})},b=function(t,e){var l=this,n=i.open({type:1,id:"LAY_layedit_link",area:"350px",shade:.05,shadeClose:!0,moveType:1,title:"\u8d85\u94fe\u63a5",skin:"layui-layer-msg",content:['

                                                    ','
                                                  • ','','
                                                    ','',"
                                                    ","
                                                  • ",'
                                                  • ','','
                                                    ','",'","
                                                    ","
                                                  • ",'
                                                  • ','','',"
                                                  • ","
                                                  "].join(""),success:function(t,n){var o="submit(layedit-link-yes)";a.render("radio"),t.find(".layui-btn-primary").on("click",function(){i.close(n),l.focus()}),a.on(o,function(t){i.close(b.index),e&&e(t.field)})}});b.index=n},x=function(t){var a=function(){var t=["[\u5fae\u7b11]","[\u563b\u563b]","[\u54c8\u54c8]","[\u53ef\u7231]","[\u53ef\u601c]","[\u6316\u9f3b]","[\u5403\u60ca]","[\u5bb3\u7f9e]","[\u6324\u773c]","[\u95ed\u5634]","[\u9119\u89c6]","[\u7231\u4f60]","[\u6cea]","[\u5077\u7b11]","[\u4eb2\u4eb2]","[\u751f\u75c5]","[\u592a\u5f00\u5fc3]","[\u767d\u773c]","[\u53f3\u54fc\u54fc]","[\u5de6\u54fc\u54fc]","[\u5618]","[\u8870]","[\u59d4\u5c48]","[\u5410]","[\u54c8\u6b20]","[\u62b1\u62b1]","[\u6012]","[\u7591\u95ee]","[\u998b\u5634]","[\u62dc\u62dc]","[\u601d\u8003]","[\u6c57]","[\u56f0]","[\u7761]","[\u94b1]","[\u5931\u671b]","[\u9177]","[\u8272]","[\u54fc]","[\u9f13\u638c]","[\u6655]","[\u60b2\u4f24]","[\u6293\u72c2]","[\u9ed1\u7ebf]","[\u9634\u9669]","[\u6012\u9a82]","[\u4e92\u7c89]","[\u5fc3]","[\u4f24\u5fc3]","[\u732a\u5934]","[\u718a\u732b]","[\u5154\u5b50]","[ok]","[\u8036]","[good]","[NO]","[\u8d5e]","[\u6765]","[\u5f31]","[\u8349\u6ce5\u9a6c]","[\u795e\u9a6c]","[\u56e7]","[\u6d6e\u4e91]","[\u7ed9\u529b]","[\u56f4\u89c2]","[\u5a01\u6b66]","[\u5965\u7279\u66fc]","[\u793c\u7269]","[\u949f]","[\u8bdd\u7b52]","[\u8721\u70db]","[\u86cb\u7cd5]"],e={};return layui.each(t,function(t,i){e[i]=layui.cache.dir+"images/face/"+t+".gif"}),e}();return x.hide=x.hide||function(t){"face"!==e(t.target).attr("layedit-event")&&i.close(x.index)},x.index=i.tips(function(){var t=[];return layui.each(a,function(e,i){t.push('
                                                • '+e+'
                                                • ')}),'
                                                    '+t.join("")+"
                                                  "}(),this,{tips:1,time:0,skin:"layui-box layui-util-face",maxWidth:500,success:function(l,n){l.css({marginTop:-4,marginLeft:-10}).find(".layui-clear>li").on("click",function(){t&&t({src:a[this.title],alt:this.title}),i.close(n)}),e(document).off("click",x.hide).on("click",x.hide)}})},k=function(t){var e=this,l=i.open({type:1,id:"LAY_layedit_code",area:"550px",shade:.05,shadeClose:!0,moveType:1,title:"\u63d2\u5165\u4ee3\u7801",skin:"layui-layer-msg",content:['
                                                    ','
                                                  • ','','
                                                    ','","
                                                    ","
                                                  • ",'
                                                  • ','','
                                                    ','',"
                                                    ","
                                                  • ",'
                                                  • ','','',"
                                                  • ","
                                                  "].join(""),success:function(l,n){var o="submit(layedit-code-yes)";a.render("select"),l.find(".layui-btn-primary").on("click",function(){i.close(n),e.focus()}),a.on(o,function(e){i.close(k.index),t&&t(e.field)})}});k.index=l},C={html:'',strong:'',italic:'',underline:'',del:'',"|":'',left:'',center:'',right:'',link:'',unlink:'',face:'',image:'',code:'',help:''},L=new c;t(n,L)});layui.define("jquery",function(a){"use strict";var e=layui.$;a("code",function(a){var l=[];a=a||{},a.elem=e(a.elem||".layui-code"),a.lang="lang"in a?a.lang:"code",a.elem.each(function(){l.push(this)}),layui.each(l.reverse(),function(l,i){var t=e(i),c=t.html();(t.attr("lay-encode")||a.encode)&&(c=c.replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,""")),t.html('
                                                  1. '+c.replace(/[\r\t\n]+/g,"
                                                  2. ")+"
                                                  "),t.find(">.layui-code-h3")[0]||t.prepend('

                                                  '+(t.attr("lay-title")||a.title||"</>")+''+(t.attr("lay-lang")||a.lang||"")+"

                                                  ");var n=t.find(">.layui-code-ol");t.addClass("layui-box layui-code-view"),(t.attr("lay-skin")||a.skin)&&t.addClass("layui-code-"+(t.attr("lay-skin")||a.skin)),(n.find("li").length/100|0)>0&&n.css("margin-left",(n.find("li").length/100|0)+"px"),(t.attr("lay-height")||a.height)&&n.css("max-height",t.attr("lay-height")||a.height)})})}).addcss("modules/code.css?v=2","skincodecss"); \ No newline at end of file diff --git a/iot-server/server-starter/src/main/webapp/pages/index.html b/iot-server/server-starter/src/main/webapp/pages/index.html deleted file mode 100644 index c8a39831..00000000 --- a/iot-server/server-starter/src/main/webapp/pages/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - Title - - -123 ${word!""} - - \ No newline at end of file From 57ec54f757bad333280f0571df1abe023087ddff Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 15 Dec 2021 15:14:30 +0800 Subject: [PATCH 726/763] [fix]: remove build ui --- iot-server/server-starter/pom.xml | 55 ------------------------------- 1 file changed, 55 deletions(-) diff --git a/iot-server/server-starter/pom.xml b/iot-server/server-starter/pom.xml index 0653f39d..dad2bf41 100644 --- a/iot-server/server-starter/pom.xml +++ b/iot-server/server-starter/pom.xml @@ -83,61 +83,6 @@ - - com.github.eirslett - frontend-maven-plugin - ${frontend-maven-plugin.version} - - ${ui.path} - v8.17.0 - - - - install node and npm - - install-node-and-npm - - - - npm install - - npm - - - install --registry=https://registry.npm.taobao.org/ --unsafe-perm - - - - npm install gulp - - npm - - - install --global gulp-cli - - - - build - - gulp - - - - - - - org.apache.maven.plugins - maven-resources-plugin - - - - - ${project.basedir}/ - src/main/webapp - - - - com.alipay.sofa sofa-ark-maven-plugin From fa2626bfcb147d38436f4e690112388d62708617 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 20 Dec 2021 10:34:49 +0800 Subject: [PATCH 727/763] [fix]: fix scene time interval --- ...\265\350\241\250\347\273\223\346\236\204-yefei.sql" | 3 +++ .../iot/domain/product/ProductEventTimeInterval.java | 2 ++ .../com/zmops/iot/web/analyse/service/HomeService.java | 2 +- .../iot/web/device/dto/MultipleDeviceEventRule.java | 10 ++++++++++ .../device/service/MultipleDeviceEventRuleService.java | 2 ++ 5 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 "sql/v1.0/structure/2021-12-16 1653-\344\277\256\346\224\271\345\234\272\346\231\257\347\224\237\346\225\210\346\227\266\351\227\264\346\256\265\350\241\250\347\273\223\346\236\204-yefei.sql" diff --git "a/sql/v1.0/structure/2021-12-16 1653-\344\277\256\346\224\271\345\234\272\346\231\257\347\224\237\346\225\210\346\227\266\351\227\264\346\256\265\350\241\250\347\273\223\346\236\204-yefei.sql" "b/sql/v1.0/structure/2021-12-16 1653-\344\277\256\346\224\271\345\234\272\346\231\257\347\224\237\346\225\210\346\227\266\351\227\264\346\256\265\350\241\250\347\273\223\346\236\204-yefei.sql" new file mode 100644 index 00000000..ff661781 --- /dev/null +++ "b/sql/v1.0/structure/2021-12-16 1653-\344\277\256\346\224\271\345\234\272\346\231\257\347\224\237\346\225\210\346\227\266\351\227\264\346\256\265\350\241\250\347\273\223\346\236\204-yefei.sql" @@ -0,0 +1,3 @@ +ALTER table product_event_time_interval ADD COLUMN day_of_weeks varchar(16) DEFAULT null; +ALTER table product_event_time_interval ALTER COLUMN start_time type int4; +ALTER table product_event_time_interval ALTER COLUMN end_time type int4; \ No newline at end of file diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventTimeInterval.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventTimeInterval.java index 9d494083..0129a378 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventTimeInterval.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventTimeInterval.java @@ -25,4 +25,6 @@ public class ProductEventTimeInterval { private Integer startTime; private Integer endTime; + + private String dayOfWeeks; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java index e53de728..846375df 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -224,7 +224,7 @@ public Map getDeviceNum(Integer timeFrom, Integer timeTill) { public Map getAlarmNum(long timeFrom, long timeTill) { List alarmList = new QProblem().clock.ge(LocalDateTimeUtils.getLDTBySeconds((int) timeFrom)) - .clock.lt(LocalDateTimeUtils.getLDTBySeconds((int) timeTill)).orderBy().clock.asc().findList(); + .clock.lt(LocalDateTimeUtils.getLDTBySeconds((int) timeTill)).rClock.isNull().orderBy().clock.asc().findList(); Map alarmMap = new ConcurrentHashMap<>(3); Map> initMap = new ConcurrentHashMap<>(5); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java index 40d88ef6..8420116b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java @@ -11,7 +11,9 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; /** * @author nantian created at 2021/9/14 14:47 @@ -143,11 +145,19 @@ public static class DeviceService { @Getter @Setter public static class TimeInterval { + private String dayOfWeeks; private Integer startTime; private Integer endTime; @Override public String toString() { + String weekExpression = ""; + if (ToolUtil.isNotEmpty(dayOfWeeks)) { + weekExpression = Arrays.asList(dayOfWeeks.split(",")).parallelStream().map(day -> "dayofweek()=" + day).collect(Collectors.joining(" or ")); + } + if (ToolUtil.isNotEmpty(weekExpression)) { + return "((" + weekExpression + ") and time()>= " + startTime + " and " + " time()< " + endTime + " )"; + } return "(time()>= " + startTime + " and " + " time()< " + endTime + " )"; } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index 11349ec6..d2f19e7c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -249,6 +249,7 @@ public void createDeviceEventRule(MultipleDeviceEventRule eventRule) { timeExp.setEventRuleId(eventRule.getEventRuleId()); timeExp.setStartTime(i.getStartTime()); timeExp.setEndTime(i.getEndTime()); + timeExp.setDayOfWeeks(i.getDayOfWeeks()); timeExpList.add(timeExp); }); DB.insertAll(timeExpList); @@ -352,6 +353,7 @@ public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { timeExp.setEventRuleId(eventRule.getEventRuleId()); timeExp.setStartTime(i.getStartTime()); timeExp.setEndTime(i.getEndTime()); + timeExp.setDayOfWeeks(i.getDayOfWeeks()); timeExpList.add(timeExp); }); DB.insertAll(timeExpList); From ccaf4513181a5a39ebe51ce55d17cd16a58a42e1 Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 20 Dec 2021 10:38:27 +0800 Subject: [PATCH 728/763] [fix]: fix device event trigger --- .../iot/web/device/controller/DeviceEventTriggerController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java index 33605fa5..f7e5a939 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -218,7 +218,7 @@ public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseE ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(eventRule.getDeviceId()) .eventRuleId.eq(eventRule.getEventRuleId()).findOne(); - if (productEventRelation != null && productEventRelation.getInherit().equals(InheritStatus.YES.getCode())) { + if (productEventRelation != null && InheritStatus.YES.getCode().equals(productEventRelation.getInherit())) { throw new ServiceException(BizExceptionEnum.EVENT_PRODUCT_CANNOT_DELETE); } From f43c68e3bd798978181706676ca48158cf1609ce Mon Sep 17 00:00:00 2001 From: yefei Date: Mon, 20 Dec 2021 11:38:57 +0800 Subject: [PATCH 729/763] [fix]: fix alarm list --- .../main/java/com/zmops/iot/web/alarm/service/AlarmService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 4aeef6e1..2f7b787e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -41,7 +41,7 @@ public class AlarmService { @Autowired DeviceService deviceService; - private static final String PROBLEM_RESOLVE = "已解決"; + private static final String PROBLEM_RESOLVE = "已解决"; public void alarm(Map alarmInfo) { From d2b55de918db7a75244cc5d20c64a04f2ed386b6 Mon Sep 17 00:00:00 2001 From: yefei Date: Tue, 21 Dec 2021 10:56:10 +0800 Subject: [PATCH 730/763] [fix]:fix tdengine table name --- .../plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java index 7f46d118..2257a077 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java @@ -21,12 +21,12 @@ public class TDEngineSqlExecutor { protected SQLExecutor getInsertExecutor(String modelName, T metrics) { - SQLBuilder sqlBuilder = new SQLBuilder().append("h_").append(metrics.itemid() + " USING "); + SQLBuilder sqlBuilder = new SQLBuilder(); if (modelName.equals("history")) { History history = (History) metrics; - sqlBuilder.append("history (deviceid, itemid) TAGS") + sqlBuilder.append("h_").append(metrics.itemid() + " USING ").append("history (deviceid, itemid) TAGS") .append("('").append(history.getDeviceId()).append("'") .append(",").append(history.getItemid() + " )") .append(" VALUES (") @@ -35,7 +35,7 @@ protected SQLExecutor getInsertExecutor(String modelName } else if (modelName.equals("history_uint")) { UIntHistory uihistory = (UIntHistory) metrics; - sqlBuilder.append("history_uint (deviceid, itemid) TAGS") + sqlBuilder.append("huint_").append(metrics.itemid() + " USING ").append("history_uint (deviceid, itemid) TAGS") .append(" ('").append(uihistory.getDeviceId()).append("'") .append(",").append(uihistory.getItemid() + " )") .append(" VALUES (") @@ -45,7 +45,7 @@ protected SQLExecutor getInsertExecutor(String modelName TextHistory textHistory = (TextHistory) metrics; String value = textHistory.getValue().replaceAll(",", "\\,"); - sqlBuilder.append("history_text (deviceid, itemid) TAGS") + sqlBuilder.append("htxt_").append(metrics.itemid() + " USING ").append("history_text (deviceid, itemid) TAGS") .append(" ('").append(textHistory.getDeviceId()).append("'") .append(",").append(textHistory.getItemid() + " )") .append(" VALUES (") @@ -54,7 +54,7 @@ protected SQLExecutor getInsertExecutor(String modelName StrHistory strHistory = (StrHistory) metrics; String value = strHistory.getValue().replaceAll(",", "\\,"); - sqlBuilder.append("history_str (deviceid, itemid) TAGS") + sqlBuilder.append("hstr_").append(metrics.itemid() + " USING ").append("history_str (deviceid, itemid) TAGS") .append(" ('").append(strHistory.getDeviceId()).append("'") .append(",").append(strHistory.getItemid() + " )") .append(" VALUES (") From 5012901767dbee9fbe75df4f5f72613e3c140560 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 21 Dec 2021 10:58:04 +0800 Subject: [PATCH 731/763] [fix]: mqtt protocol --- iot-server/server-camel-receiver/pom.xml | 4 ++ .../routes/MqttClientRouteBuilder.java | 8 ++-- .../service/CamelContextHolderService.java | 42 +++++-------------- 3 files changed, 18 insertions(+), 36 deletions(-) diff --git a/iot-server/server-camel-receiver/pom.xml b/iot-server/server-camel-receiver/pom.xml index 67617da7..72347dbd 100644 --- a/iot-server/server-camel-receiver/pom.xml +++ b/iot-server/server-camel-receiver/pom.xml @@ -34,6 +34,10 @@ 1.0.3-RELEASE + + org.apache.camel + camel-paho-mqtt5 + org.apache.camel camel-netty-http diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttClientRouteBuilder.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttClientRouteBuilder.java index 19c01321..cbfcbe10 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttClientRouteBuilder.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttClientRouteBuilder.java @@ -21,10 +21,10 @@ public MqttClientRouteBuilder(String routeId, Map options) { @Override public void configure() throws Exception { - fromF("mqtt:zeus-iot-mqtt?host=tcp://%s:%s&subscribeTopicNames=%s", options.get("hostIp"), options.get("port"), options.get("topicNames")) + fromF("paho-mqtt5:%s?brokerUrl=tcp://%s:%s", options.get("topicNames"), options.get("hostIp"), options.get("port")) .routeId(routeId) .log(LoggingLevel.DEBUG, log, ">>> Message received from Mqtt Client : \n${body}") - .dynamicRouter(method(RouteJudge.class, "slip")).to("Zabbix"); + .dynamicRouter(method(RouteJudge.class, "slip")).to("Zabbix:mqtt"); } @@ -36,12 +36,12 @@ public static String slip(Exchange exchange) { return null; } - String topicName = exchange.getIn().getHeader("CamelMQTTSubscribeTopic").toString(); + String topicName = exchange.getIn().getHeader("CamelMqttTopic").toString(); //TODO 这里需要动态加载规则 if (topicName.equals("zeusiot/123")) { - return "ArkBiz?uniqueId=198909118"; + return "ArkBiz:mqtt?uniqueId=19890918"; } if (topicName.equals("zeusiot/1234")) { diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/CamelContextHolderService.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/CamelContextHolderService.java index 6dbc2370..49a86081 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/CamelContextHolderService.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/CamelContextHolderService.java @@ -6,9 +6,6 @@ import org.apache.camel.CamelContext; import org.apache.camel.Route; import org.apache.camel.RoutesBuilder; -import org.apache.camel.model.FromDefinition; - -import java.util.List; /** * @author nantian created at 2021/8/17 0:24 @@ -46,37 +43,18 @@ public void addRoutes(RoutesBuilder builder) { * @param routeId 路由ID */ public void routeShutDown(String routeId) { -// EventDrivenConsumerRoute route = (EventDrivenConsumerRoute) camelContext.getRoute(routeId); -// List fromDefinitions = camelContext.getRouteDefinition(routeId).getInputs(); -// -// -// try { -// camelContext.stopRoute(routeId); -// camelContext.removeRoute(routeId); -//// camelContext.removeRouteDefinition(camelContext.getRouteDefinition(routeId)); -// } catch (Exception e) { -// e.printStackTrace(); -// } + Route route = camelContext.getRoute(routeId); + if (route == null) { + return; + } -// if (route == null) { -// log.error("当前 routeId : {} 对应的路由不存在", routeId); -// return; -// } -// try { -// route.getEndpoint().stop(); -// route.getConsumer().stop(); -// -// } catch (Exception e) { -// e.printStackTrace(); -// } -// -// -// try { -// camelContext.removeRoute(routeId); -// } catch (Exception e) { -// e.printStackTrace(); -// } + try { + camelContext.getRouteController().stopRoute(routeId); + camelContext.removeRoute(routeId); + } catch (Exception e) { + e.printStackTrace(); + } } From 3e70d44501f71e2f5195a8e7f894e779c5708bec Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 21 Dec 2021 10:58:44 +0800 Subject: [PATCH 732/763] [pom]: add log4j-web dependency --- iot-server/server-web/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/iot-server/server-web/pom.xml b/iot-server/server-web/pom.xml index 9cdcd773..45914888 100644 --- a/iot-server/server-web/pom.xml +++ b/iot-server/server-web/pom.xml @@ -29,6 +29,11 @@ 1.0.3-RELEASE + + org.apache.logging.log4j + log4j-web + + com.zmops zeus-commons From dff7a69482fd0c005af3430aac93e3b62692f82e Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 21 Dec 2021 10:59:25 +0800 Subject: [PATCH 733/763] [pom]: update log4j version to 2.17.0 --- iot-server-bom/pom.xml | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/iot-server-bom/pom.xml b/iot-server-bom/pom.xml index 312516d1..6c4beee9 100644 --- a/iot-server-bom/pom.xml +++ b/iot-server-bom/pom.xml @@ -18,7 +18,7 @@ 3.11.4 1.18.20 - 2.13.3 + 2.17.0 25.1-jre 4.1.65.Final 2.8.7 @@ -38,6 +38,7 @@ lombok ${lombok.version} + org.apache.logging.log4j log4j-api @@ -49,16 +50,22 @@ ${log4j.version} - com.google.guava - guava - ${guava.version} + org.apache.logging.log4j + log4j-core + ${log4j.version} - org.apache.logging.log4j - log4j-core + log4j-web ${log4j.version} + + + com.google.guava + guava + ${guava.version} + + org.apache.camel camel-core From 76b8fe10350695788ab0f535cb6046a312f07044 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 21 Dec 2021 11:02:58 +0800 Subject: [PATCH 734/763] [feat]: update zeus ui --- zeus-iot-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeus-iot-ui b/zeus-iot-ui index e4d2f536..f4c3a9df 160000 --- a/zeus-iot-ui +++ b/zeus-iot-ui @@ -1 +1 @@ -Subproject commit e4d2f5366566beacd8d04347f35a423de891b246 +Subproject commit f4c3a9df88db57e80d3a6f8cee993cf1e1e2fd10 From fd61d6e3e97f053083e1506d4f35271e7bb8e196 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 21 Dec 2021 12:50:11 +0800 Subject: [PATCH 735/763] [fix]: tdengine driver adapter --- .../plugin/jdbc/tdengine/TDEngineStorageProvider.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java index b6c280b0..79e525bc 100644 --- a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java @@ -1,12 +1,11 @@ package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine; +import com.zmops.zeus.iot.server.client.jdbc.hikaricp.JDBCHikariCPClient; import com.zmops.zeus.iot.server.core.CoreModule; import com.zmops.zeus.iot.server.core.storage.IBatchDAO; import com.zmops.zeus.iot.server.core.storage.StorageDAO; import com.zmops.zeus.iot.server.core.storage.StorageException; import com.zmops.zeus.iot.server.core.storage.StorageModule; -import com.zmops.zeus.iot.server.client.jdbc.hikaricp.JDBCHikariCPClient; - import com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine.dao.TDEngineStorageDAO; import com.zmops.zeus.iot.server.telemetry.TelemetryModule; import com.zmops.zeus.iot.server.telemetry.api.HealthCheckMetrics; @@ -45,10 +44,8 @@ public ModuleConfig createConfigBeanIfAbsent() { @Override public void prepare() throws ServiceNotProvidedException, ModuleStartException { - Properties settings = new Properties(); - settings.setProperty("dataSourceClassName", config.getDriver()); - settings.setProperty("dataSource.url", config.getUrl()); + settings.setProperty("jdbcUrl", config.getUrl()); settings.setProperty("dataSource.user", config.getUser()); settings.setProperty("dataSource.password", config.getPassword()); client = new JDBCHikariCPClient(settings); From 91a5f4c3bcec476a6be87e844f18a54e61665211 Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 21 Dec 2021 13:09:16 +0800 Subject: [PATCH 736/763] [style]: code format --- .../com/zmops/zeus/iot/server/core/CoreModuleProvider.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java index 2266a7e1..d74eacc5 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java @@ -62,12 +62,9 @@ public void prepare() throws ServiceNotProvidedException, ModuleStartException { .jettyHttpMaxRequestHeaderSize(moduleConfig.getHttpMaxRequestHeaderSize()) .build(); - jettyServer = new JettyServer(jettyServerConfig); jettyServer.initialize(); - jettyServer.setFilterInitParameter("configClass", "com.zmops.zeus.iot.web.config.IoTConfig"); - } @Override From 2e7b15cb0848220cdf4a70310995c6a7cf65ddba Mon Sep 17 00:00:00 2001 From: nantian Date: Tue, 21 Dec 2021 15:42:21 +0800 Subject: [PATCH 737/763] [feat]: cache RefrenceClient --- .../receiver/handler/ark/ArkBizProducer.java | 25 +++----- .../receiver/module/CamelReceiverModule.java | 2 + .../provider/CamelReceiverProvider.java | 16 ++++++ .../service/ReferenceClientService.java | 57 +++++++++++++++++++ 4 files changed, 83 insertions(+), 17 deletions(-) create mode 100644 iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/ReferenceClientService.java diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizProducer.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizProducer.java index 0dab47c3..6d38188f 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizProducer.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizProducer.java @@ -3,10 +3,9 @@ import com.zmops.zeus.dto.DataMessage; import com.zmops.zeus.dto.ItemValue; import com.zmops.zeus.facade.DynamicProcotol; +import com.zmops.zeus.iot.server.receiver.module.CamelReceiverModule; +import com.zmops.zeus.iot.server.receiver.service.ReferenceClientService; import com.zmops.zeus.server.library.module.ModuleManager; -import com.zmops.zeus.server.runtime.SofaStarter; -import com.zmops.zeus.server.runtime.api.client.ReferenceClient; -import com.zmops.zeus.server.runtime.api.client.param.ReferenceParam; import org.apache.camel.Endpoint; import org.apache.camel.Exchange; import org.apache.camel.support.DefaultProducer; @@ -20,25 +19,17 @@ @SuppressWarnings("all") public class ArkBizProducer extends DefaultProducer { - private final SofaStarter sofaStarter; - private final ReferenceClient referenceClient; - - private final String methodName; private final ModuleManager moduleManager; - private final DynamicProcotol dynamicClient; + private final DynamicProcotol dynamicProcotol; public ArkBizProducer(Endpoint endpoint, ModuleManager moduleManager, String uniqueId, String methodName) { super(endpoint); this.moduleManager = moduleManager; - this.sofaStarter = new SofaStarter(); - this.referenceClient = this.sofaStarter.getSofaRuntimeContext().getClientFactory().getClient(ReferenceClient.class); - this.methodName = methodName; - - ReferenceParam referenceParam = new ReferenceParam<>(); - referenceParam.setInterfaceType(DynamicProcotol.class); - referenceParam.setUniqueId(uniqueId); - dynamicClient = referenceClient.reference(referenceParam); + + ReferenceClientService referenceClientService = moduleManager.find(CamelReceiverModule.NAME) + .provider().getService(ReferenceClientService.class); + dynamicProcotol = referenceClientService.getDynamicProtocolClient(uniqueId); } @Override @@ -48,7 +39,7 @@ public void process(Exchange exchange) throws Exception { message.setBody(exchange.getMessage().getBody()); message.setHeaders(exchange.getMessage().getHeaders()); - List itemValueList = dynamicClient.protocolHandler(message); + List itemValueList = dynamicProcotol.protocolHandler(message); if (itemValueList == null) { itemValueList = Collections.emptyList(); diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/module/CamelReceiverModule.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/module/CamelReceiverModule.java index 70365a11..d13d0359 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/module/CamelReceiverModule.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/module/CamelReceiverModule.java @@ -1,6 +1,7 @@ package com.zmops.zeus.iot.server.receiver.module; import com.zmops.zeus.iot.server.receiver.service.CamelContextHolderService; +import com.zmops.zeus.iot.server.receiver.service.ReferenceClientService; import com.zmops.zeus.server.library.module.ModuleDefine; import java.util.ArrayList; @@ -23,6 +24,7 @@ public CamelReceiverModule() { public Class[] services() { List> classes = new ArrayList<>(); classes.add(CamelContextHolderService.class); + classes.add(ReferenceClientService.class); return classes.toArray(new Class[]{}); } } diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverProvider.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverProvider.java index 07baa5e1..97dbd58f 100644 --- a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverProvider.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverProvider.java @@ -5,9 +5,14 @@ import com.zmops.zeus.iot.server.receiver.handler.zabbix.ZabbixSenderComponent; import com.zmops.zeus.iot.server.receiver.module.CamelReceiverModule; import com.zmops.zeus.iot.server.receiver.service.CamelContextHolderService; +import com.zmops.zeus.iot.server.receiver.service.ReferenceClientService; import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; import com.zmops.zeus.server.library.module.*; +import com.zmops.zeus.server.runtime.SofaStarter; +import com.zmops.zeus.server.runtime.api.client.ReferenceClient; +import org.apache.camel.ExtendedCamelContext; import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.impl.engine.PooledExchangeFactory; import org.apache.camel.model.ModelCamelContext; /** @@ -19,6 +24,8 @@ public class CamelReceiverProvider extends ModuleProvider { private ModelCamelContext camelContext; + private ReferenceClient referenceClient; + public CamelReceiverProvider() { this.camelReceiverConfig = new CamelReceiverConfig(); } @@ -41,7 +48,16 @@ public ModuleConfig createConfigBeanIfAbsent() { @Override public void prepare() throws ServiceNotProvidedException, ModuleStartException { camelContext = new DefaultCamelContext(); // master 只有一个 CamelContext + camelContext.disableJMX(); + camelContext.setTracing(true); + camelContext.adapt(ExtendedCamelContext.class).setExchangeFactory(new PooledExchangeFactory()); + + // biz-ark JVM 通信客户端 + SofaStarter sofaStarter = new SofaStarter(); + this.referenceClient = sofaStarter.getSofaRuntimeContext().getClientFactory().getClient(ReferenceClient.class); + this.registerServiceImplementation(CamelContextHolderService.class, new CamelContextHolderService(camelContext, getManager())); + this.registerServiceImplementation(ReferenceClientService.class, new ReferenceClientService(referenceClient, getManager())); } @Override diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/ReferenceClientService.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/ReferenceClientService.java new file mode 100644 index 00000000..325f51bc --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/ReferenceClientService.java @@ -0,0 +1,57 @@ +package com.zmops.zeus.iot.server.receiver.service; + +import com.zmops.zeus.facade.DynamicProcotol; +import com.zmops.zeus.server.library.module.ModuleManager; +import com.zmops.zeus.server.library.module.Service; +import com.zmops.zeus.server.runtime.api.client.ReferenceClient; +import com.zmops.zeus.server.runtime.api.client.param.ReferenceParam; + +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author nantian created at 2021/12/21 15:20 + *

                                                  + * 动态协议代理 + */ +public class ReferenceClientService implements Service { + + private final ReferenceClient referenceClient; + private final ModuleManager moduleManager; + + // 缓存调用 客户端 + private static final ConcurrentHashMap dynamicProtoMap = new ConcurrentHashMap<>(); + + public ReferenceClientService(ReferenceClient client, ModuleManager moduleManager) { + this.referenceClient = client; + this.moduleManager = moduleManager; + } + + + public ReferenceClient getReferenceClient() { + return referenceClient; + } + + + /** + * 根据服务ID,动态获取代理客户端 + * + * @param serviceId - + * @return DynamicProcotol + */ + public DynamicProcotol getDynamicProtocolClient(String serviceId) { + + DynamicProcotol client = dynamicProtoMap.get(serviceId); + if (client != null) { + return client; + } + + ReferenceParam referenceParam = new ReferenceParam<>(); + referenceParam.setInterfaceType(DynamicProcotol.class); + referenceParam.setUniqueId(serviceId); + + DynamicProcotol client2 = referenceClient.reference(referenceParam); + dynamicProtoMap.put(serviceId, client2); + + return client2; + } +} From 41550b2782928dba70f2c5c5f410766bf389be62 Mon Sep 17 00:00:00 2001 From: yefei Date: Wed, 22 Dec 2021 16:43:14 +0800 Subject: [PATCH 738/763] [fix]: remove unused code --- iot-server/server-bootstrap/pom.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/iot-server/server-bootstrap/pom.xml b/iot-server/server-bootstrap/pom.xml index 1d469c5a..53874525 100644 --- a/iot-server/server-bootstrap/pom.xml +++ b/iot-server/server-bootstrap/pom.xml @@ -87,12 +87,12 @@ - - - - - - + + + + + + - - - - - + + + + + + + + + org.springframework.boot spring-boot-starter-websocket diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java index 0dadabe9..daed9d8a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java @@ -103,7 +103,7 @@ public List queryHistory(String deviceId, List attrIds, Long ti //取出属性对应的ItemID List zbxIds = list.parallelStream().map(ProductAttribute::getZbxId).collect(Collectors.toList()); Map> valueTypeMap = list.parallelStream().collect(Collectors.groupingBy(ProductAttribute::getValueType)); - Map itemIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getZbxId, o -> o)); + Map itemIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getZbxId, o -> o, (a, b) -> a)); List latestDtos = new ArrayList<>(); if (null == timeFrom) { timeFrom = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); @@ -121,7 +121,7 @@ public List queryHistory(String deviceId, List attrIds, Long ti String res = zbxValueMap.valueMapGet(valuemapids.toString()); List mappingList = JSONObject.parseArray(res, ValueMap.class); if (!CollectionUtils.isEmpty(mappingList)) { - mappings = mappingList.stream().collect(Collectors.toMap(ValueMap::getValuemapid, ValueMap::getMappings)); + mappings = mappingList.stream().collect(Collectors.toMap(ValueMap::getValuemapid, ValueMap::getMappings, (a, b) -> a)); } } @@ -137,7 +137,7 @@ public List queryHistory(String deviceId, List attrIds, Long ti if (null != valueMapid) { List mappingList = finalMappings.get(valueMapid); if (!CollectionUtils.isEmpty(mappingList)) { - Map mappingMap = mappingList.parallelStream().collect(Collectors.toMap(Mapping::getValue, Mapping::getNewvalue)); + Map mappingMap = mappingList.parallelStream().collect(Collectors.toMap(Mapping::getValue, Mapping::getNewvalue, (a, b) -> a)); latestDto.setValue(mappingMap.get(latestDto.getValue())); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java index 385805f2..6f583b7d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java @@ -78,7 +78,7 @@ public List qeuryLatest(String deviceId, List attrIds) { } Map> valueTypeMap = list.parallelStream().collect(Collectors.groupingBy(ProductAttribute::getValueType)); - Map itemIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getZbxId, o -> o)); + Map itemIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getZbxId, o -> o, (a, b) -> a)); List latestDtos; if (checkTDengine()) { latestDtos = queryLatestFromTD(deviceId, valueTypeMap); @@ -94,7 +94,7 @@ public List qeuryLatest(String deviceId, List attrIds) { String res = zbxValueMap.valueMapGet(valuemapids.toString()); List mappingList = JSONObject.parseArray(res, ValueMap.class); if (!CollectionUtils.isEmpty(mappingList)) { - mappings = mappingList.stream().collect(Collectors.toMap(ValueMap::getValuemapid, ValueMap::getMappings)); + mappings = mappingList.stream().collect(Collectors.toMap(ValueMap::getValuemapid, ValueMap::getMappings, (a, b) -> a)); } } @@ -112,7 +112,7 @@ public List qeuryLatest(String deviceId, List attrIds) { if (null != valueMapid) { List mappingList = finalMappings.get(valueMapid); if (!CollectionUtils.isEmpty(mappingList)) { - Map mappingMap = mappingList.parallelStream().collect(Collectors.toMap(Mapping::getValue, Mapping::getNewvalue)); + Map mappingMap = mappingList.parallelStream().collect(Collectors.toMap(Mapping::getValue, Mapping::getNewvalue, (a, b) -> a)); latestDto.setValue(mappingMap.get(latestDto.getValue())); } } @@ -240,6 +240,6 @@ public Map queryMap(String deviceId) { if (ToolUtil.isEmpty(latestDtos)) { return new HashMap<>(0); } - return latestDtos.parallelStream().collect(Collectors.toMap(LatestDto::getKey, LatestDto::getValue)); + return latestDtos.parallelStream().collect(Collectors.toMap(LatestDto::getKey, LatestDto::getValue, (a, b) -> a)); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java index ade86cee..ec4eaf77 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java @@ -11,7 +11,6 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; -import javax.validation.constraints.Pattern; import java.time.LocalDateTime; import java.util.List; @@ -79,4 +78,8 @@ public class DeviceDto { private Interface deviceInterface; private LocalDateTime latestOnline; + + private String productCode; + + private String method; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java index 8420116b..71b5a329 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java @@ -146,8 +146,8 @@ public static class DeviceService { @Setter public static class TimeInterval { private String dayOfWeeks; - private Integer startTime; - private Integer endTime; + private String startTime; + private String endTime; @Override public String toString() { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventPublisher.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventPublisher.java new file mode 100644 index 00000000..3b4cb0ad --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventPublisher.java @@ -0,0 +1,28 @@ +package com.zmops.iot.web.device.service; + +import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.event.applicationEvent.DeviceDeleteEvent; +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; +import com.zmops.iot.web.event.applicationEvent.dto.DeviceDeleteEventData; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.stereotype.Component; + +@Component +@EnableAsync +public class DeviceEventPublisher { + + @Autowired + ApplicationEventPublisher publisher; + + @Async + public void DeviceSaveEventPublish(DeviceDto deviceDto) { + publisher.publishEvent(new DeviceSaveEvent(this, deviceDto)); + } + + public void DeviceDeleteEventPublish(String deviceId, String zbxId) { + publisher.publishEvent(new DeviceDeleteEvent(this, DeviceDeleteEventData.builder().deviceId(deviceId).zbxId(zbxId).build())); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java index be59694e..48a4727e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -269,7 +269,7 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S * @return 触发器ID */ public String[] createZbxTrigger(String triggerName, String expression, Byte level) { - String res = zbxTrigger.triggerCreate(triggerName, expression, level); + String res = zbxTrigger.triggerCreate(triggerName, expression, level,0); return JSON.parseObject(res, TriggerIds.class).getTriggerids(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java index 2ec0a9e2..46f918be 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java @@ -20,19 +20,16 @@ import com.zmops.iot.web.device.dto.DeviceLogDto; import com.zmops.iot.web.device.dto.DeviceRelationDto; import com.zmops.iot.web.device.dto.param.DeviceLogParam; -import com.zmops.iot.web.device.service.work.DeviceServiceLogWorker; -import com.zmops.iot.web.device.service.work.ScenesLogWorker; -import com.zmops.zeus.server.async.callback.ICallback; -import com.zmops.zeus.server.async.executor.Async; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; +import com.zmops.iot.web.event.applicationEvent.DeviceSceneLogEvent; +import com.zmops.iot.web.event.applicationEvent.DeviceServiceLogEvent; +import com.zmops.iot.web.event.applicationEvent.dto.LogEventData; import io.ebean.DB; import io.ebean.PagedList; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; /** @@ -41,19 +38,16 @@ @Service public class DeviceLogService { - private static final String LOG_TYPE_ALARM = "告警日志"; - private static final String LOG_TYPE_EVENT = "事件日志"; + private static final String LOG_TYPE_ALARM = "告警日志"; + private static final String LOG_TYPE_EVENT = "事件日志"; private static final String LOG_TYPE_SERVICE = "服务日志"; - private static final String LOG_TYPE_SCENES = "联动日志"; + private static final String LOG_TYPE_SCENES = "联动日志"; @Autowired AlarmService alarmService; @Autowired - DeviceServiceLogWorker deviceServiceLogWorker; - - @Autowired - ScenesLogWorker scenesLogWorker; + ApplicationEventPublisher publisher; public List list(String deviceId, String logType, Long timeFrom, Long timeTill) { List deviceLogDtoList = new ArrayList<>(); @@ -340,31 +334,10 @@ private Pager getScenesLog(DeviceLogParam deviceLogParam) { * 记录场景日志 */ public void recordSceneLog(Long eventRuleId, String type, Long userId) { - Map serviceLogInfo = new ConcurrentHashMap<>(3); - serviceLogInfo.put("eventRuleId", eventRuleId); - serviceLogInfo.put("triggerType", "自动".equals(type) ? "场景联动" : type); - if (null != userId) { - serviceLogInfo.put("triggerUser", userId); - } - WorkerWrapper, Boolean> deviceServiceLogWork = new WorkerWrapper.Builder, Boolean>().id("deviceServiceLogWorker") - .worker(deviceServiceLogWorker).param(serviceLogInfo).callback(ICallback.PRINT_EXCEPTION_STACK_TRACE) - .build(); + publisher.publishEvent(new DeviceServiceLogEvent(this, LogEventData.builder().eventRuleId(eventRuleId).triggerType("自动".equals(type) ? "场景联动" : type).triggerUser(userId).build())); + + publisher.publishEvent(new DeviceSceneLogEvent(this, LogEventData.builder().eventRuleId(eventRuleId).triggerType(type).triggerUser(userId).build())); - Map scenesLogInfo = new ConcurrentHashMap<>(3); - scenesLogInfo.put("eventRuleId", eventRuleId); - scenesLogInfo.put("triggerType", type); - if (null != userId) { - scenesLogInfo.put("triggerUser", userId); - } - WorkerWrapper, Boolean> scenesLogWork = new WorkerWrapper.Builder, Boolean>().id("scenesLogWorker") - .worker(scenesLogWorker).param(scenesLogInfo).callback(ICallback.PRINT_EXCEPTION_STACK_TRACE) - .build(); - - try { - Async.beginWork(1000, deviceServiceLogWork, scenesLogWork); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index f1f3ce4d..0a4f1dd1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -8,7 +8,8 @@ import com.zmops.iot.domain.device.query.QDevicesGroups; import com.zmops.iot.domain.device.query.QTag; import com.zmops.iot.domain.product.Product; -import com.zmops.iot.domain.product.query.*; +import com.zmops.iot.domain.product.query.QProduct; +import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.DefinitionsUtil; @@ -16,16 +17,12 @@ import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.iot.web.device.dto.param.DeviceParam; import com.zmops.iot.web.device.dto.param.DeviceParams; -import com.zmops.iot.web.device.service.work.*; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductTag; import com.zmops.zeus.driver.entity.Interface; import com.zmops.zeus.driver.service.ZbxHost; import com.zmops.zeus.driver.service.ZbxInterface; import com.zmops.zeus.driver.service.ZbxValueMap; -import com.zmops.zeus.server.async.callback.ICallback; -import com.zmops.zeus.server.async.executor.Async; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import io.ebean.DtoQuery; import io.ebean.Query; @@ -34,7 +31,6 @@ import org.springframework.stereotype.Service; import java.util.*; -import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; /** @@ -43,30 +39,6 @@ @Service public class DeviceService implements CommandLineRunner { - @Autowired - private SaveDeviceWorker saveDeviceWorker; - - @Autowired - private SaveAttributeWorker saveAttributeWorker; - - @Autowired - private SaveDeviceGrpWorker saveDeviceGrpWorker; - - @Autowired - private SaveTagWorker saveTagWorker; - - @Autowired - private SaveZbxHostWorker saveZbxHostWorker; - - @Autowired - private UpdateAttrZbxIdWorker updateAttrZbxIdWorker; - - @Autowired - private UpdateDeviceZbxIdWorker updateDeviceZbxIdWorker; - - @Autowired - private SaveOtherWorker saveOtherWorker; - @Autowired private ZbxHost zbxHost; @@ -79,6 +51,9 @@ public class DeviceService implements CommandLineRunner { @Autowired ZbxInterface zbxInterface; + @Autowired + DeviceEventPublisher deviceEventPublisher; + /** * 设备列表 * @@ -104,11 +79,13 @@ public List deviceList(DeviceParams deviceParams) { qDevice.productId.in(deviceParams.getProductIds()); } if (ToolUtil.isEmpty(deviceParams.getProductIds()) && ToolUtil.isNotEmpty(deviceParams.getProdTypes())) { - List productIdList = new QProduct().select(QProduct.Alias.productId).groupId.in(deviceParams.getProdTypes()).findSingleAttributeList(); + List productIdList = new QProduct().select(QProduct.Alias.productId).groupId.in( + deviceParams.getProdTypes()).findSingleAttributeList(); qDevice.productId.in(productIdList); } if (ToolUtil.isNotEmpty(deviceParams.getDeviceGroupIds())) { - List deviceList = new QDevicesGroups().select(QDevicesGroups.Alias.deviceId).deviceGroupId.in(deviceParams.getDeviceGroupIds()).findSingleAttributeList(); + List deviceList = new QDevicesGroups().select(QDevicesGroups.Alias.deviceId).deviceGroupId.in( + deviceParams.getDeviceGroupIds()).findSingleAttributeList(); qDevice.deviceId.in(deviceList); } return qDevice.findList(); @@ -121,7 +98,8 @@ public List deviceList(DeviceParams deviceParams) { */ public List getDeviceIds() { List devGroupIds = deviceGroupService.getDevGroupIds(); - return new QDevicesGroups().select(QDevicesGroups.alias().deviceId).deviceGroupId.in(devGroupIds).findSingleAttributeList(); + return new QDevicesGroups().select(QDevicesGroups.alias().deviceId).deviceGroupId.in(devGroupIds) + .findSingleAttributeList(); } /** @@ -201,7 +179,6 @@ public Pager devicePageList(DeviceParam deviceParam) { count.setParameter("deviceGroupIds", devGroupIds); } - List list = dto.setFirstRow((deviceParam.getPage() - 1) * deviceParam.getMaxRow()) .setMaxRows(deviceParam.getMaxRow()).findList(); @@ -229,8 +206,10 @@ private StringBuilder generateBaseSql() { " d.tenant_id," + " d.proxy_id," + " P.NAME product_name, " + + " P.product_code product_code, " + " ds.group_name, " + - " ds.groupIds " + + " ds.groupIds," + + " m.method " + "FROM " + " device d ") .append(" LEFT JOIN product P ON P.product_id = d.product_id ") @@ -245,7 +224,8 @@ private StringBuilder generateBaseSql() { " LEFT JOIN device_group dg ON dg.device_group_id = dgs.device_group_id " + " where dg.device_group_id in (:deviceGroupIds) " + " GROUP BY d.device_id " + - " ) ds ON ds.device_id = d.device_id "); + " ) ds ON ds.device_id = d.device_id ") + .append(" left join device_service_method m on m.device_id = d.device_id "); } /** @@ -256,45 +236,13 @@ private StringBuilder generateBaseSql() { */ public String create(DeviceDto deviceDto) { - WorkerWrapper saveTagWork = new WorkerWrapper.Builder().id("saveTagWork") - .worker(saveTagWorker).param(deviceDto).build(); - - WorkerWrapper saveAttributeWork = new WorkerWrapper.Builder().id("saveAttributeWork") - .worker(saveAttributeWorker).param(deviceDto).build(); + Device device = new Device(); + ToolUtil.copyProperties(deviceDto, device); - WorkerWrapper saveDeviceGrpWork = new WorkerWrapper.Builder().id("saveDeviceGrpWork") - .worker(saveDeviceGrpWorker).param(deviceDto) - .build(); + device.setStatus(CommonStatus.ENABLE.getCode()); + DB.insert(device); - WorkerWrapper updateAttrZbxIdWork = new WorkerWrapper.Builder().id("updateAttrZbxIdWork") - .worker(updateAttrZbxIdWorker).param(deviceDto) - .build(); - - WorkerWrapper updateDeviceZbxIdWork = new WorkerWrapper.Builder().id("updateDeviceZbxIdWork") - .worker(updateDeviceZbxIdWorker).param(deviceDto.getDeviceId()) - .build(); - - WorkerWrapper saveOtherWork = new WorkerWrapper.Builder().id("saveOtherWork") - .worker(saveOtherWorker).param(deviceDto) - .build(); - - WorkerWrapper saveZbxHostWork = new WorkerWrapper.Builder().id("saveZbxHostWork") - .worker(saveZbxHostWorker).param(deviceDto) - .next(updateAttrZbxIdWork, updateDeviceZbxIdWork, saveOtherWork) - .callback(ICallback.PRINT_EXCEPTION_STACK_TRACE) - .build(); - - WorkerWrapper deviceWork = new WorkerWrapper.Builder().id("saveDvice") - .worker(saveDeviceWorker).param(deviceDto) - .next(saveTagWork, saveAttributeWork, saveDeviceGrpWork, saveZbxHostWork) - .build(); - - try { - - Async.beginWork(10000, deviceWork); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } + deviceEventPublisher.DeviceSaveEventPublish(deviceDto); updateDeviceNameCache(deviceDto.getDeviceId(), deviceDto.getName()); return deviceDto.getDeviceId(); @@ -311,45 +259,16 @@ public String update(DeviceDto deviceDto) { if (null == device) { throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); } + ToolUtil.copyProperties(deviceDto, device); deviceDto.setOldProductId(device.getProductId()); deviceDto.setZbxId(device.getZbxId()); - WorkerWrapper saveTagWork = new WorkerWrapper.Builder().id("saveTagWork") - .worker(saveTagWorker).param(deviceDto).build(); - - WorkerWrapper saveAttributeWork = new WorkerWrapper.Builder().id("saveAttributeWork") - .worker(saveAttributeWorker).param(deviceDto).build(); - - WorkerWrapper saveDeviceGrpWork = new WorkerWrapper.Builder().id("saveDeviceGrpWork") - .worker(saveDeviceGrpWorker).param(deviceDto) - .build(); - - WorkerWrapper updateAttrZbxIdWork = new WorkerWrapper.Builder().id("updateAttrZbxIdWork") - .worker(updateAttrZbxIdWorker) - .build(); + DB.update(device); - WorkerWrapper saveOtherWork = new WorkerWrapper.Builder().id("saveOtherWork") - .worker(saveOtherWorker).param(deviceDto) - .build(); + deviceEventPublisher.DeviceSaveEventPublish(deviceDto); - WorkerWrapper saveZbxHostWork = new WorkerWrapper.Builder().id("saveZbxHostWork") - .worker(saveZbxHostWorker).param(deviceDto) - .next(updateAttrZbxIdWork, saveOtherWork) - .build(); - - WorkerWrapper deviceWork = new WorkerWrapper.Builder().id("saveDvice") - .worker(saveDeviceWorker).param(deviceDto) - .next(saveTagWork, saveAttributeWork, saveDeviceGrpWork, saveZbxHostWork) - .build(); - - try { - - Async.beginWork(10000, deviceWork); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } updateDeviceNameCache(deviceDto.getDeviceId(), deviceDto.getName()); - return deviceWork.getWorkResult().getResult().getDeviceId(); + return deviceDto.getDeviceId(); } /** @@ -371,66 +290,8 @@ public String delete(DeviceDto deviceDto) { return deviceDto.getDeviceId(); } String zbxId = device.getZbxId(); - //删除标签 - WorkerWrapper delTagWork = new WorkerWrapper.Builder().id("delTagWork") - .worker((deviceId, allWrappers) -> { - new QTag().sid.eq(deviceId).delete(); - return true; - }).param(deviceDto.getDeviceId()).build(); - - //删除属性 - WorkerWrapper delAttrWork = new WorkerWrapper.Builder().id("delAttrWork") - .worker((deviceId, allWrappers) -> { - new QProductAttribute().productId.eq(deviceId).delete(); - return true; - }).param(deviceDto.getDeviceId()).build(); - - //删除设备组关联关系 - WorkerWrapper delGropusWork = new WorkerWrapper.Builder().id("delGropusWork") - .worker((deviceId, allWrappers) -> { - new QDevicesGroups().deviceId.eq(deviceId).delete(); - return true; - }).param(deviceDto.getDeviceId()).build(); - - //删除Zbx主机 - WorkerWrapper delZbxWork = new WorkerWrapper.Builder().id("delZbxWork") - .worker((zbxid, allWrappers) -> { - if (ToolUtil.isNotEmpty(zbxid)) { - JSONArray jsonArray = JSONObject.parseArray(zbxHost.hostDetail(zbxId)); - if (jsonArray.size() > 0) { - zbxHost.hostDelete(Collections.singletonList(zbxid)); - } - } - return true; - }).param(zbxId).build(); - - //删除其它关联信息 - WorkerWrapper delOtherWork = new WorkerWrapper.Builder().id("delOtherWork") - .worker((deviceId, allWrappers) -> { - new QProductStatusFunctionRelation().relationId.eq(deviceId).delete(); - new QProductServiceRelation().relationId.eq(deviceId).delete(); - new QProductEventRelation().relationId.eq(deviceId).delete(); - new QProductEventService().deviceId.eq(deviceId).delete(); - new QProductServiceParam().deviceId.eq(deviceId).delete(); - return true; - }).param(deviceDto.getDeviceId()).build(); - - //删除设备 - WorkerWrapper delDeviceWork = new WorkerWrapper.Builder() - .id("delDeviceWork") - .worker((deviceId, allWrappers) -> { - new QDevice().deviceId.eq(deviceId).delete(); - return true; - }) - .param(deviceDto.getDeviceId()) - .next(delTagWork, delAttrWork, delGropusWork, delZbxWork, delOtherWork).build(); - - try { - - Async.beginWork(5000, delDeviceWork); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } + + deviceEventPublisher.DeviceDeleteEventPublish(device.getDeviceId(), zbxId); //更新设备名称缓存 removeDeviceNameCache(deviceDto.getDeviceId()); @@ -463,7 +324,7 @@ public void deviceTagCreate(ProductTag productTag, String zbxId) { if (ToolUtil.isEmpty(zbxId)) { return; } - + //同步到Zbx List list = new QTag().sid.eq(productTag.getProductId()).findList(); @@ -525,7 +386,9 @@ public DeviceDto deviceDetail(String deviceId) { } StringBuilder sql = generateBaseSql(); sql.append(" where d.device_id=:deviceId"); - DeviceDto deviceDto = DB.findDto(DeviceDto.class, sql.toString()).setParameter("deviceId", deviceId).setParameter("deviceGroupIds", devGroupIds).findOne(); + DeviceDto deviceDto = DB.findDto(DeviceDto.class, sql.toString()).setParameter("deviceId", deviceId) + .setParameter("deviceGroupIds", devGroupIds).findOne(); + if (deviceDto == null) { throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); } @@ -588,7 +451,8 @@ public void status(String status, String deviceId, String zbxId) { if (ToolUtil.isNotEmpty(zbxId)) { zbxHost.hostStatusUpdate(zbxId, "ENABLE".equals(status) ? "0" : "1"); } - DB.update(Device.class).where().eq("device_id", deviceId).asUpdate().set("status", status).setNull("online").update(); + DB.update(Device.class).where().eq("device_id", deviceId).asUpdate().set("status", status).setNull("online") + .update(); } /** @@ -596,7 +460,8 @@ public void status(String status, String deviceId, String zbxId) { */ private void updateDeviceCache() { List deviceList = new QDevice().select(QDevice.Alias.deviceId, QDevice.Alias.name).findList(); - Map map = deviceList.parallelStream().collect(Collectors.toMap(Device::getDeviceId, Device::getName)); + Map map = deviceList.parallelStream() + .collect(Collectors.toMap(Device::getDeviceId, Device::getName, (a, b) -> a)); DefinitionsUtil.updateDeviceCache(map); } @@ -618,7 +483,6 @@ private void removeDeviceNameCache(String deviceId) { DefinitionsUtil.updateDeviceCache(all); } - @Override public void run(String... args) throws Exception { updateDeviceCache(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java index a97a1eab..37f09230 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java @@ -20,7 +20,6 @@ import java.time.LocalDateTime; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -58,12 +57,12 @@ public void execute(String deviceId, Long serviceId, List serviceP serviceMap.put("name", productService.getName()); List paramList = DefinitionsUtil.getServiceParam(serviceId); - Map paramStr = new HashMap<>(paramList.size()); + Map paramStr = null; if (ToolUtil.isNotEmpty(paramList)) { - paramStr = paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue)); + paramStr = paramList.parallelStream().filter(o -> deviceId.equals(o.getDeviceId())).collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue, (a, b) -> a)); if (ToolUtil.isNotEmpty(serviceParams)) { - Map userParam = serviceParams.parallelStream().collect(Collectors.toMap(ServiceParam::getKey, ServiceParam::getValue)); + Map userParam = serviceParams.parallelStream().collect(Collectors.toMap(ServiceParam::getKey, ServiceParam::getValue, (a, b) -> a)); for (Map.Entry param : paramStr.entrySet()) { if (userParam.get(param.getKey()) != null) { param.setValue(userParam.get(param.getKey())); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java index 8b6c0444..5f674f23 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -186,7 +186,7 @@ private String generateExecuteParam(MultipleDeviceEventRule eventRule) { List paramList = DefinitionsUtil.getServiceParam(val.getServiceId()); if (ToolUtil.isNotEmpty(paramList)) { - serviceMap.put("param", paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue))); + serviceMap.put("param", paramList.parallelStream().filter(o->key.equals(o.getDeviceId())).collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue, (a, b) -> a))); } serviceList.add(serviceMap); }); @@ -332,6 +332,7 @@ public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { eventRule.getExpList().forEach(i -> { ProductEventExpression exp = initEventExpression(i); + exp.setEventExpId(i.getEventExpId()); exp.setEventRuleId(eventRule.getEventRuleId()); expList.add(exp); }); @@ -399,7 +400,6 @@ private ProductEvent initEventRule(MultipleDeviceEventRule eventRule) { private ProductEventExpression initEventExpression(MultipleDeviceEventRule.Expression exp) { ProductEventExpression eventExpression = new ProductEventExpression(); - eventExpression.setEventExpId(exp.getEventExpId()); eventExpression.setCondition(exp.getCondition()); eventExpression.setFunction(exp.getFunction()); eventExpression.setScope(exp.getScope()); @@ -525,7 +525,7 @@ public void execute(Long eventRuleId, String type, Long userId) { List paramList = DefinitionsUtil.getServiceParam(val.getServiceId()); if (ToolUtil.isNotEmpty(paramList)) { - serviceMap.put("param", paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue))); + serviceMap.put("param", paramList.parallelStream().filter(o->key.equals(o.getDeviceId())).collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue, (a, b) -> a))); } serviceList.add(serviceMap); }); @@ -557,7 +557,8 @@ public void checkParam(MultipleDeviceEventRule eventRule) { } } - long count = eventRule.getDeviceServices().parallelStream().map(MultipleDeviceEventRule.DeviceService::getServiceId).distinct().count(); +// long count = eventRule.getDeviceServices().parallelStream().map(MultipleDeviceEventRule.DeviceService::getServiceId).distinct().count(); + long count = eventRule.getDeviceServices().parallelStream().map(o-> (o.getExecuteDeviceId()+o.getServiceId()).hashCode()).distinct().count(); if (count < eventRule.getDeviceServices().size()) { throw new ServiceException(BizExceptionEnum.SERVICE_HAS_DUPLICATE); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/DeleteDeviceEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/DeleteDeviceEventHandler.java new file mode 100644 index 00000000..89c7d3b9 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/DeleteDeviceEventHandler.java @@ -0,0 +1,59 @@ +package com.zmops.iot.web.device.service.event; + + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.device.query.QDevicesGroups; +import com.zmops.iot.domain.device.query.QTag; +import com.zmops.iot.domain.product.query.*; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.DeviceDeleteEvent; +import com.zmops.zeus.driver.service.ZbxHost; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.stereotype.Component; + +import java.util.Collections; + +@Slf4j +@Component +@EnableAsync +public class DeleteDeviceEventHandler { + + @Autowired + private ZbxHost zbxHost; + + @Async + @EventListener(classes = {DeviceDeleteEvent.class}) + public void onApplicationEvent(DeviceDeleteEvent event) { + String deviceId = event.getEventData().getDeviceId(); + String zbxId = event.getEventData().getZbxId(); + + new QTag().sid.eq(deviceId).delete(); + + new QProductAttribute().productId.eq(deviceId).delete(); + + new QDevicesGroups().deviceId.eq(deviceId).delete(); + + if (ToolUtil.isNotEmpty(zbxId)) { + JSONArray jsonArray = JSONObject.parseArray(zbxHost.hostDetail(zbxId)); + if (jsonArray.size() > 0) { + zbxHost.hostDelete(Collections.singletonList(zbxId)); + } + } + + new QProductStatusFunctionRelation().relationId.eq(deviceId).delete(); + new QProductServiceRelation().relationId.eq(deviceId).delete(); + new QProductEventRelation().relationId.eq(deviceId).delete(); + new QProductEventService().deviceId.eq(deviceId).delete(); + new QProductServiceParam().deviceId.eq(deviceId).delete(); +// new QDeviceServiceMethod().deviceId.eq(deviceId).delete(); + + new QDevice().deviceId.eq(deviceId).delete(); + + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveActionMethodEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveActionMethodEventHandler.java new file mode 100644 index 00000000..84f5afd4 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveActionMethodEventHandler.java @@ -0,0 +1,40 @@ +package com.zmops.iot.web.device.service.event; + +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +/** + * @author yefei + *

                                                  + * 处理设备服务下发 方法 + */ +@Slf4j +@Component +@Order(1) +public class SaveActionMethodEventHandler implements ApplicationListener { + + @Override + public void onApplicationEvent(DeviceSaveEvent event) { + log.debug("step 2:SaveActionMethodWorker----DEVICEID:{}…………", event.getEventData().getDeviceId()); +// if (null == event.getEventData()) { +// return; +// } +// DeviceDto deviceDto = event.getEventData(); +// if (ToolUtil.isEmpty(deviceDto.getMethod())) { +// return; +// } +// +// //保存设备服务下发 执行方法 +// DeviceServiceMethod deviceServiceMethod = new DeviceServiceMethod(); +// deviceServiceMethod.setDeviceId(deviceDto.getDeviceId()); +// deviceServiceMethod.setMethod(deviceDto.getMethod()); +// +// DB.save(deviceServiceMethod); +// log.debug("step 2:SaveActionMethodWorker----DEVICEID:{} complete…………", deviceDto.getDeviceId()); + return; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveAttributeEventHandler.java similarity index 80% rename from zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveAttributeEventHandler.java index 4819fbaf..9b02bad0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveAttributeEventHandler.java @@ -1,5 +1,4 @@ -package com.zmops.iot.web.device.service.work; - +package com.zmops.iot.web.device.service.event; import cn.hutool.core.util.IdUtil; import com.zmops.iot.domain.product.ProductAttribute; @@ -8,10 +7,11 @@ import com.zmops.iot.domain.product.query.QProductAttributeEvent; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import java.util.ArrayList; @@ -26,28 +26,35 @@ */ @Slf4j @Component -public class SaveAttributeWorker implements IWorker { +@Order(1) +public class SaveAttributeEventHandler implements ApplicationListener { + + private static final String ATTR_TYPE_RELY = "18"; @Override - public Boolean action(DeviceDto deviceDto, Map map) { - log.debug("step 3:saveAttributeWorker----DEVICEID:{}…………", deviceDto.getDeviceId()); - + public void onApplicationEvent(DeviceSaveEvent event) { + log.debug("step 3:saveAttributeWorker----DEVICEID:{}…………", event.getEventData().getDeviceId()); + if (null == event.getEventData()) { + return; + } + DeviceDto deviceDto = event.getEventData(); String deviceId = deviceDto.getDeviceId(); if (ToolUtil.isNotEmpty(deviceDto.getEdit()) && "true".equals(deviceDto.getEdit())) { //修改 //没有修改关联的产品 不做处理 if (deviceDto.getProductId().equals(deviceDto.getOldProductId())) { - return true; + return; } new QProductAttribute().productId.eq(deviceId).templateId.isNotNull().delete(); new QProductAttributeEvent().productId.eq(deviceId).templateId.isNotNull().delete(); } //属性 - List productAttributeList = new QProductAttribute().productId.eq(deviceDto.getProductId() + "").orderBy(" source::int ").findList(); + List productAttributeList = new QProductAttribute().productId.eq( + deviceDto.getProductId() + "").orderBy(" source::int ").findList(); List newProductAttributeList = new ArrayList<>(); @@ -83,7 +90,8 @@ public Boolean action(DeviceDto deviceDto, Map map) { DB.saveAll(newProductAttributeList); //属性事件 - List productAttributeEventList = new QProductAttributeEvent().productId.eq(deviceDto.getProductId() + "").findList(); + List productAttributeEventList = new QProductAttributeEvent().productId.eq( + deviceDto.getProductId() + "").findList(); List newProductAttributeEventList = new ArrayList<>(); for (ProductAttributeEvent productAttributeEvent : productAttributeEventList) { @@ -97,14 +105,8 @@ public Boolean action(DeviceDto deviceDto, Map map) { } DB.saveAll(newProductAttributeEventList); - log.debug("step 3:saveAttributeWorker----DEVICEID:{}…………", deviceDto.getDeviceId()); - return true; - } - - - @Override - public Boolean defaultValue() { - return true; + log.debug("step 3:saveAttributeWorker----DEVICEID:{} complete…………", deviceDto.getDeviceId()); + return; } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveDeviceGrpEventHandler.java similarity index 52% rename from zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveDeviceGrpEventHandler.java index b93f857e..43c7878c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveDeviceGrpEventHandler.java @@ -1,18 +1,17 @@ -package com.zmops.iot.web.device.service.work; - +package com.zmops.iot.web.device.service.event; import com.zmops.iot.domain.device.DevicesGroups; import com.zmops.iot.domain.device.query.QDevicesGroups; import com.zmops.iot.web.device.dto.DeviceDto; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; -import java.util.Map; /** * @author yefei @@ -21,13 +20,16 @@ */ @Slf4j @Component -public class SaveDeviceGrpWorker implements IWorker { - +@Order(1) +public class SaveDeviceGrpEventHandler implements ApplicationListener { @Override - public Boolean action(DeviceDto deviceDto, Map map) { - log.debug("step 4:SaveDeviceGrpWorker----DEVICEID:{}…………", deviceDto.getDeviceId()); - + public void onApplicationEvent(DeviceSaveEvent event) { + log.debug("step 4:SaveDeviceGrpWorker----DEVICEID:{}…………", event.getEventData().getDeviceId()); + if (null == event.getEventData()) { + return; + } + DeviceDto deviceDto = event.getEventData(); //修改模式 先清空关联关系 if (null != deviceDto.getDeviceId()) { new QDevicesGroups().deviceId.eq(deviceDto.getDeviceId()).delete(); @@ -36,17 +38,11 @@ public Boolean action(DeviceDto deviceDto, Map map) { //保存设备与设备组关系 List devicesGroupsList = new ArrayList<>(); for (Long deviceGroupId : deviceDto.getDeviceGroupIds()) { - devicesGroupsList.add(DevicesGroups.builder().deviceId(deviceDto.getDeviceId()).deviceGroupId(deviceGroupId).build()); + devicesGroupsList.add( + DevicesGroups.builder().deviceId(deviceDto.getDeviceId()).deviceGroupId(deviceGroupId).build()); } DB.saveAll(devicesGroupsList); - log.debug("step 4:SaveDeviceGrpWorker----DEVICEID:{}…………", deviceDto.getDeviceId()); - return true; - } - - - @Override - public Boolean defaultValue() { - return true; + log.debug("step 4:SaveDeviceGrpWorker----DEVICEID:{} complate…………", deviceDto.getDeviceId()); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveOtherEventHandler.java similarity index 61% rename from zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveOtherEventHandler.java index 3cfa5278..f97003a1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveOtherWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveOtherEventHandler.java @@ -1,5 +1,4 @@ -package com.zmops.iot.web.device.service.work; - +package com.zmops.iot.web.device.service.event; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.product.ProductEventRelation; @@ -8,14 +7,15 @@ import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; import com.zmops.iot.web.product.dto.ZbxTriggerInfo; import com.zmops.iot.web.product.service.ProductEventRuleService; import com.zmops.zeus.driver.service.ZbxTrigger; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import java.util.ArrayList; @@ -31,15 +31,19 @@ */ @Slf4j @Component -public class SaveOtherWorker implements IWorker { +@Order(2) +public class SaveOtherEventHandler implements ApplicationListener { @Autowired ZbxTrigger zbxTrigger; @Override - public Boolean action(DeviceDto deviceDto, Map allWrappers) { - log.debug("step 8:SaveOtherWorker----DEVICEID:{}…………", deviceDto.getDeviceId()); - + public void onApplicationEvent(DeviceSaveEvent event) { + log.debug("step 6:SaveOtherWorker----DEVICEID:{}…………", event.getEventData().getDeviceId()); + if (null == event.getEventData()) { + return; + } + DeviceDto deviceDto = event.getEventData(); String deviceId = deviceDto.getDeviceId(); if (ToolUtil.isNotEmpty(deviceDto.getEdit()) && "true".equals(deviceDto.getEdit())) { @@ -47,7 +51,7 @@ public Boolean action(DeviceDto deviceDto, Map allWrapper //没有修改关联的产品 不做处理 if (deviceDto.getProductId().equals(deviceDto.getOldProductId())) { - return true; + return; } //删除服务关联 new QProductServiceRelation().relationId.eq(deviceId).delete(); @@ -62,27 +66,33 @@ public Boolean action(DeviceDto deviceDto, Map allWrapper } //服务关联 - DB.sqlUpdate("insert into product_service_relation (relation_id,service_id,inherit) SELECT :deviceId,service_id,1 from product_service_relation where relation_id=:relationId") + DB.sqlUpdate( + "insert into product_service_relation (relation_id,service_id,inherit) SELECT :deviceId,service_id,1 from product_service_relation where relation_id=:relationId") .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "").execute(); //服务参数 - DB.sqlUpdate("insert into product_service_param (device_id,service_id,key,name,value,remark) SELECT :deviceId,service_id,key,name,value,remark from product_service_param where device_id=:relationId") + DB.sqlUpdate( + "insert into product_service_param (device_id,service_id,key,name,value,remark) SELECT :deviceId,service_id,key,name,value,remark from product_service_param where device_id=:relationId") .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "").execute(); //上下线规则关联 - ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().relationId.eq(deviceDto.getProductId() + "").findOne(); + ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().relationId.eq( + deviceDto.getProductId() + "").findOne(); if (null != relation) { String triggerRes = zbxTrigger.triggerGetByName(relation.getRuleId() + ""); List zbxTriggerInfoList = JSONObject.parseArray(triggerRes, ZbxTriggerInfo.class); - Map hostTriggerMap = zbxTriggerInfoList.parallelStream().filter(o -> o.getTags().parallelStream().anyMatch(t -> "__offline__".equals(t.getTag()))) - .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid)); - Map hostRecoveryTriggerMap = zbxTriggerInfoList.parallelStream().filter(o -> o.getTags().parallelStream().anyMatch(t -> "__online__".equals(t.getTag()))) - .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid)); + Map hostTriggerMap = zbxTriggerInfoList.parallelStream() + .filter(o -> o.getTags().parallelStream().anyMatch(t -> "__offline__".equals(t.getTag()))) + .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid, (a, b) -> a)); + Map hostRecoveryTriggerMap = zbxTriggerInfoList.parallelStream() + .filter(o -> o.getTags().parallelStream().anyMatch(t -> "__online__".equals(t.getTag()))) + .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid, (a, b) -> a)); String zbxId = Optional.ofNullable(hostTriggerMap.get(deviceDto.getDeviceId())).orElse(""); String zbxIdRecovery = Optional.ofNullable(hostRecoveryTriggerMap.get(deviceDto.getDeviceId())).orElse(""); - DB.sqlUpdate("insert into product_status_function_relation (relation_id,rule_id,inherit,zbx_id,zbx_id_recovery) SELECT :deviceId,rule_id,1,:zbxId,:zbxIdRecovery from product_status_function_relation where relation_id=:relationId") + DB.sqlUpdate( + "insert into product_status_function_relation (relation_id,rule_id,inherit,zbx_id,zbx_id_recovery) SELECT :deviceId,rule_id,1,:zbxId,:zbxIdRecovery from product_status_function_relation where relation_id=:relationId") .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "") .setParameter("zbxId", zbxId) .setParameter("zbxIdRecovery", zbxIdRecovery).execute(); @@ -90,11 +100,15 @@ public Boolean action(DeviceDto deviceDto, Map allWrapper } //告警规则关联 并 回填zbx triggerId - List triggers = JSONObject.parseArray(zbxTrigger.triggerGetByHost(deviceId), ProductEventRuleService.Triggers.class); + List triggers = JSONObject.parseArray(zbxTrigger.triggerGetByHost(deviceId), + ProductEventRuleService.Triggers.class); - Map map = triggers.parallelStream().collect(Collectors.toMap(ProductEventRuleService.Triggers::getDescription, ProductEventRuleService.Triggers::getTriggerid)); + Map map = triggers.parallelStream().collect( + Collectors.toMap(ProductEventRuleService.Triggers::getDescription, + ProductEventRuleService.Triggers::getTriggerid, (a, b) -> a)); - List productEventRelationList = new QProductEventRelation().status.eq(CommonStatus.ENABLE.getCode()).relationId.eq(deviceDto.getProductId() + "").findList(); + List productEventRelationList = new QProductEventRelation().status.eq( + CommonStatus.ENABLE.getCode()).relationId.eq(deviceDto.getProductId() + "").findList(); List newRelationList = new ArrayList<>(); for (ProductEventRelation productEventRelation : productEventRelationList) { ProductEventRelation newEventRelation = new ProductEventRelation(); @@ -109,15 +123,13 @@ public Boolean action(DeviceDto deviceDto, Map allWrapper DB.saveAll(newRelationList); //告警执行动作关联 - DB.sqlUpdate("insert into product_event_service (service_id,device_id,execute_device_id,event_rule_id,inherit) SELECT service_id,:deviceId,:executeDeviceId,event_rule_id,1 from product_event_service where relation_id=:relationId") - .setParameter("deviceId", deviceId).setParameter("executeDeviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "").execute(); + DB.sqlUpdate( + "insert into product_event_service (service_id,device_id,execute_device_id,event_rule_id) SELECT service_id,:deviceId,:executeDeviceId,event_rule_id from product_event_service where device_id=:relationId") + .setParameter("deviceId", deviceId).setParameter("executeDeviceId", deviceId) + .setParameter("relationId", deviceDto.getProductId() + "").execute(); - log.debug("step 8:SaveOtherWorker----DEVICEID:{}…………", deviceDto.getDeviceId()); - return true; + log.debug("step 6:SaveOtherWorker----DEVICEID:{} complate…………", deviceDto.getDeviceId()); + return; } - @Override - public Boolean defaultValue() { - return true; - } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveTagEventHandler.java similarity index 51% rename from zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveTagEventHandler.java index 331d70ad..7fcc7438 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveTagEventHandler.java @@ -1,17 +1,15 @@ -package com.zmops.iot.web.device.service.work; - +package com.zmops.iot.web.device.service.event; import com.zmops.iot.domain.device.query.QTag; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; -import java.util.Map; - /** * @author yefei *

                                                  @@ -19,12 +17,16 @@ */ @Slf4j @Component -public class SaveTagWorker implements IWorker { +@Order(2) +public class SaveTagEventHandler implements ApplicationListener { @Override - public Boolean action(DeviceDto deviceDto, Map allWrappers) { - log.debug("step 2:SaveTagWorker----DEVICEID:{}…………", deviceDto.getDeviceId()); - + public void onApplicationEvent(DeviceSaveEvent event) { + log.debug("step 5:SaveTagWorker----DEVICEID:{}…………", event.getEventData().getDeviceId()); + if (null == event.getEventData()) { + return; + } + DeviceDto deviceDto = event.getEventData(); String deviceId = deviceDto.getDeviceId(); if (ToolUtil.isNotEmpty(deviceDto.getEdit()) && "true".equals(deviceDto.getEdit())) { @@ -32,20 +34,16 @@ public Boolean action(DeviceDto deviceDto, Map allWrapper //没有修改关联的产品 不做处理 if (deviceDto.getProductId().equals(deviceDto.getOldProductId())) { - return true; + return; } new QTag().sid.eq(deviceId).delete(); } //继承产品中的标签 - DB.sqlUpdate("insert into tag (sid,tag,value,template_id) SELECT :deviceId,tag,value,id template_id from tag where sid=:sid") + DB.sqlUpdate( + "insert into tag (sid,tag,value,template_id) SELECT :deviceId,tag,value,id template_id from tag where sid=:sid") .setParameter("deviceId", deviceId).setParameter("sid", deviceDto.getProductId() + "").execute(); - log.debug("step 2:SaveTagWorker----DEVICEID:{} complete", deviceDto.getDeviceId()); - return true; + log.debug("step 5:SaveTagWorker----DEVICEID:{} complete", deviceDto.getDeviceId()); } - @Override - public Boolean defaultValue() { - return true; - } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveZbxHostEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveZbxHostEventHandler.java new file mode 100644 index 00000000..a4010a61 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveZbxHostEventHandler.java @@ -0,0 +1,73 @@ +package com.zmops.iot.web.device.service.event; + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.constant.ConstantsContext; +import com.zmops.iot.domain.device.query.QDeviceGroup; +import com.zmops.iot.domain.product.query.QProduct; +import com.zmops.iot.domain.proxy.query.QProxy; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; +import com.zmops.zeus.driver.service.ZbxHost; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.util.List; + +import static com.zmops.iot.web.init.DeviceSatusScriptInit.GLOBAL_HOST_GROUP_CODE; + +/** + * @author yefei + *

                                                  + * 保存至zbx + */ +@Slf4j +@Component +@Order(0) +public class SaveZbxHostEventHandler implements ApplicationListener { + + @Autowired + ZbxHost zbxHost; + + @Override + public void onApplicationEvent(DeviceSaveEvent event) { + log.debug("事件step 1:SaveZbxHostWorker----DEVICEID:{}…………", event.getEventData().getDeviceId()); + if (null == event.getEventData()) { + return; + } + DeviceDto deviceDto = event.getEventData(); + //设备ID 作为zbx HOST name + String host = deviceDto.getDeviceId(); + + //取出 设备对应的 zbx主机组ID,模板ID + List hostGrpIds = new QDeviceGroup().select(QDeviceGroup.alias().zbxId).deviceGroupId.in( + deviceDto.getDeviceGroupIds()).findSingleAttributeList(); + log.debug("step 1-1:SaveZbxHostWorker----hostGrpIds:{}…………", hostGrpIds.toString()); + String templateId = new QProduct().select(QProduct.alias().zbxId).productId.eq(deviceDto.getProductId()) + .findSingleAttribute(); + log.debug("step 1-2:SaveZbxHostWorker----templateId:{}…………", templateId); + hostGrpIds.add(ConstantsContext.getConstntsMap().get(GLOBAL_HOST_GROUP_CODE).toString()); + log.debug("step 1-3:SaveZbxHostWorker----hostGrpIds:{}…………", hostGrpIds.toString()); + //保存 zbx主机 + String result = ""; + Long proxyId = deviceDto.getProxyId(); + String zbxProxyId = null; + if (null != proxyId) { + zbxProxyId = new QProxy().select(QProxy.alias().zbxId).id.eq(proxyId).findSingleAttribute(); + } + log.debug("step 1-4:SaveZbxHostWorker----zbxProxyId:{}…………", zbxProxyId); + if (ToolUtil.isNotEmpty(deviceDto.getZbxId())) { + result = zbxHost.hostUpdate(deviceDto.getZbxId(), hostGrpIds, templateId, zbxProxyId, + deviceDto.getDeviceInterface()); + } else { + result = zbxHost.hostCreate(host, hostGrpIds, templateId, zbxProxyId, deviceDto.getDeviceInterface()); + } + String hostid = JSONObject.parseObject(result).getJSONArray("hostids").getString(0); + deviceDto.setZbxId(hostid); + log.debug("step 1:SaveZbxHostWorker----DEVICEID:{} complete,hostid:{}", deviceDto.getDeviceId(), hostid); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/ScenesLogEventHandler.java similarity index 55% rename from zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/ScenesLogEventHandler.java index 06c5e2c9..859f605b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/ScenesLogWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/ScenesLogEventHandler.java @@ -1,39 +1,37 @@ -package com.zmops.iot.web.device.service.work; - +package com.zmops.iot.web.device.service.event; import com.zmops.iot.domain.device.ScenesTriggerRecord; import com.zmops.iot.domain.product.ProductEvent; import com.zmops.iot.domain.product.query.QProductEvent; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; +import com.zmops.iot.web.event.applicationEvent.DeviceSceneLogEvent; +import com.zmops.iot.web.event.applicationEvent.dto.LogEventData; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.stereotype.Component; import java.time.LocalDateTime; -import java.util.Map; -import java.util.Optional; - -/** - * @author yefei - *

                                                  - * 记录 场景 日志 - */ + @Slf4j @Component -public class ScenesLogWorker implements IWorker, Boolean> { +@EnableAsync +public class ScenesLogEventHandler { - @Override - public Boolean action(Map param, Map allWrappers) { + @Async + @EventListener(classes = {DeviceSceneLogEvent.class}) + public void onApplicationEvent(DeviceSceneLogEvent event) { log.debug("insert into ScenesLogWorker…………"); + LogEventData eventData = event.getEventData(); - long eventRuleId = (long) param.get("eventRuleId"); - String triggerType = (String) param.get("triggerType"); - Long triggerUser = Optional.ofNullable(param.get("triggerUser")).map(Object::toString).map(Long::parseLong).orElse(null); + long eventRuleId = eventData.getEventRuleId(); + String triggerType = eventData.getTriggerType(); + Long triggerUser = eventData.getTriggerUser(); ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRuleId).findOne(); if (productEvent == null) { - return true; + return; } ScenesTriggerRecord scenesTriggerRecord = new ScenesTriggerRecord(); @@ -45,14 +43,5 @@ public Boolean action(Map param, Map allW scenesTriggerRecord.setTriggerUser(triggerUser); DB.save(scenesTriggerRecord); - - return true; } - - - @Override - public Boolean defaultValue() { - return true; - } - } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/ServiceLogEventHandler.java similarity index 78% rename from zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/ServiceLogEventHandler.java index 384316dc..faf0c241 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceServiceLogWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/ServiceLogEventHandler.java @@ -1,5 +1,4 @@ -package com.zmops.iot.web.device.service.work; - +package com.zmops.iot.web.device.service.event; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.device.Device; @@ -12,10 +11,13 @@ import com.zmops.iot.domain.product.query.QProductService; import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; +import com.zmops.iot.web.event.applicationEvent.DeviceSceneLogEvent; +import com.zmops.iot.web.event.applicationEvent.dto.LogEventData; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.stereotype.Component; import java.time.LocalDateTime; @@ -25,32 +27,30 @@ import java.util.Optional; import java.util.stream.Collectors; -/** - * @author yefei - *

                                                  - * 记录服务执行日志 - */ @Slf4j @Component -public class DeviceServiceLogWorker implements IWorker, Boolean> { +@EnableAsync +public class ServiceLogEventHandler { - @Override - public Boolean action(Map param, Map allWrappers) { + @Async + @EventListener(classes = {DeviceSceneLogEvent.class}) + public void onApplicationEvent(DeviceSceneLogEvent event) { log.debug("insert into service log…………"); + LogEventData eventData = event.getEventData(); - long eventRuleId = (long) param.get("eventRuleId"); - String executeType = (String) param.get("triggerType"); - Long executeUser = Optional.ofNullable(param.get("triggerUser")).map(Object::toString).map(Long::parseLong).orElse(null); + long eventRuleId = eventData.getEventRuleId(); + String executeType = eventData.getTriggerType(); + Long executeUser = eventData.getTriggerUser(); List productEventServiceList = new QProductEventService().eventRuleId.eq(eventRuleId).findList(); List serviceIds = productEventServiceList.parallelStream().map(ProductEventService::getServiceId).collect(Collectors.toList()); List productServiceList = new QProductService().id.in(serviceIds).findList(); - Map productServiceMap = productServiceList.parallelStream().collect(Collectors.toMap(ProductService::getId, o -> o)); + Map productServiceMap = productServiceList.parallelStream().collect(Collectors.toMap(ProductService::getId, o -> o, (a, b) -> a)); List deviceIds = productEventServiceList.parallelStream().map(ProductEventService::getExecuteDeviceId).collect(Collectors.toList()); List deviceList = new QDevice().deviceId.in(deviceIds).tenantId.isNotNull().findList(); - Map deviceIdMap = deviceList.parallelStream().collect(Collectors.toMap(Device::getDeviceId, Device::getTenantId)); + Map deviceIdMap = deviceList.parallelStream().collect(Collectors.toMap(Device::getDeviceId, Device::getTenantId, (a, b) -> a)); List serviceExecuteRecordList = new ArrayList<>(); productEventServiceList.forEach(productEventService -> { @@ -58,7 +58,7 @@ public Boolean action(Map param, Map allW serviceExecuteRecord.setDeviceId(productEventService.getExecuteDeviceId()); List paramList = DefinitionsUtil.getServiceParam(productEventService.getServiceId()); if (ToolUtil.isNotEmpty(paramList)) { - serviceExecuteRecord.setParam(JSONObject.toJSONString(paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue)))); + serviceExecuteRecord.setParam(JSONObject.toJSONString(paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue, (a, b) -> a)))); } serviceExecuteRecord.setServiceName(Optional.ofNullable(productServiceMap.get(productEventService.getServiceId())).map(ProductService::getName).orElse("")); if (deviceIdMap.get(productEventService.getExecuteDeviceId()) != null) { @@ -72,14 +72,5 @@ public Boolean action(Map param, Map allW serviceExecuteRecordList.add(serviceExecuteRecord); }); DB.saveAll(serviceExecuteRecordList); - - return true; - } - - - @Override - public Boolean defaultValue() { - return true; } - } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/UpdateAttrZbxIdEventHandler.java similarity index 68% rename from zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/UpdateAttrZbxIdEventHandler.java index 47b6ed6e..fa1f647f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/UpdateAttrZbxIdEventHandler.java @@ -1,7 +1,5 @@ -package com.zmops.iot.web.device.service.work; +package com.zmops.iot.web.device.service.event; - -import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.ProductAttributeEvent; @@ -9,13 +7,14 @@ import com.zmops.iot.domain.product.query.QProductAttributeEvent; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.service.ZbxItem; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import java.util.List; @@ -29,14 +28,19 @@ */ @Slf4j @Component -public class UpdateAttrZbxIdWorker implements IWorker { +@Order(2) +public class UpdateAttrZbxIdEventHandler implements ApplicationListener { @Autowired ZbxItem zbxItem; @Override - public Boolean action(DeviceDto deviceDto, Map map) { - log.debug("step 6:resolve Attr zbxID async----deviceid: {} …………", deviceDto.getDeviceId()); + public void onApplicationEvent(DeviceSaveEvent event) { + log.debug("step 7:resolve Attr zbxID async----deviceid: {} …………", event.getEventData().getDeviceId()); + if (null == event.getEventData()) { + return; + } + DeviceDto deviceDto = event.getEventData(); String deviceId = deviceDto.getDeviceId(); if (ToolUtil.isNotEmpty(deviceDto.getEdit()) && "true".equals(deviceDto.getEdit())) { @@ -44,21 +48,21 @@ public Boolean action(DeviceDto deviceDto, Map map) { //没有修改关联的产品 不做处理 if (deviceDto.getProductId().equals(deviceDto.getOldProductId())) { - return true; + return; } } //取出 ZBX hostid - Object result = map.get("saveZbxHostWork").getWorkResult().getResult(); - JSONArray hostid = JSONObject.parseObject(result.toString()).getJSONArray("hostids"); //根据hostid 取出监控项 - List itemInfos = JSONObject.parseArray(zbxItem.getItemInfo(null, hostid.get(0).toString()), ZbxItemInfo.class); + List itemInfos = JSONObject.parseArray(zbxItem.getItemInfo(null, deviceDto.getZbxId()), + ZbxItemInfo.class); if (ToolUtil.isEmpty(itemInfos)) { - return true; + return; } - Map itemMap = itemInfos.parallelStream().collect(Collectors.toMap(ZbxItemInfo::getName, o -> o)); + Map itemMap = itemInfos.parallelStream() + .collect(Collectors.toMap(ZbxItemInfo::getName, o -> o, (a, b) -> a)); //取出继承的属性 并塞入对应的 itemId List productAttributeList = new QProductAttribute().productId.eq(deviceId).findList(); for (ProductAttribute productAttribute : productAttributeList) { @@ -67,21 +71,15 @@ public Boolean action(DeviceDto deviceDto, Map map) { DB.updateAll(productAttributeList); - //取出继承的属性事件 并塞入对应的 itemId - List productAttributeEventList = new QProductAttributeEvent().productId.eq(deviceId).findList(); + List productAttributeEventList = new QProductAttributeEvent().productId.eq(deviceId) + .findList(); for (ProductAttributeEvent productAttributeEvent : productAttributeEventList) { productAttributeEvent.setZbxId(itemMap.get(productAttributeEvent.getTemplateId() + "").getItemid()); } DB.updateAll(productAttributeEventList); - log.debug("step 6:resolve Attr zbxID async----deviceid: {} complete", deviceDto.getDeviceId()); - return true; - } - - @Override - public Boolean defaultValue() { - return true; + log.debug("step 7:resolve Attr zbxID async----deviceid: {} complete", deviceDto.getDeviceId()); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/UpdateDeviceZbxIdEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/UpdateDeviceZbxIdEventHandler.java new file mode 100644 index 00000000..6f797a08 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/UpdateDeviceZbxIdEventHandler.java @@ -0,0 +1,39 @@ +package com.zmops.iot.web.device.service.event; + +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +/** + * @author yefei + *

                                                  + * 更新设备中zbxID + */ +@Slf4j +@Component +@Order(2) +public class UpdateDeviceZbxIdEventHandler implements ApplicationListener { + + @Override + public void onApplicationEvent(DeviceSaveEvent event) { + if (null == event.getEventData()) { + return; + } + DeviceDto deviceDto = event.getEventData(); + + log.debug("step 8:resolve zbxID async----DEVICEID:{}, HOSTID:{}…………", deviceDto.getDeviceId(), + deviceDto.getZbxId()); + + DB.update(Device.class).where().eq("deviceId", deviceDto.getDeviceId()).asUpdate() + .set("zbxId", deviceDto.getZbxId()).update(); + + log.debug("step 8:resolve zbxID async----DEVICEID:{}, HOSTID:{} 完成", deviceDto.getDeviceId(), + deviceDto.getZbxId()); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/UpdateZbxTagEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/UpdateZbxTagEventHandler.java new file mode 100644 index 00000000..358fd414 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/UpdateZbxTagEventHandler.java @@ -0,0 +1,52 @@ +package com.zmops.iot.web.device.service.event; + +import com.zmops.iot.domain.device.Tag; +import com.zmops.iot.domain.device.query.QTag; +import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; +import com.zmops.zeus.driver.service.ZbxHost; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author yefei + *

                                                  + * 同步设备标签到zbx + */ +@Slf4j +@Component +@Order(2) +public class UpdateZbxTagEventHandler implements ApplicationListener { + + @Autowired + ZbxHost zbxHost; + + @Override + public void onApplicationEvent(DeviceSaveEvent event) { + log.debug("step 9: UpdateZbxTagWorker ……"); + if (null == event.getEventData()) { + return; + } + DeviceDto deviceDto = event.getEventData(); + + //查询出本地tag + List list = new QTag().sid.eq(deviceDto.getDeviceId()).findList(); + Map tagMap = new HashMap<>(list.size()); + for (Tag tag : list) { + tagMap.put(tag.getTag(), tag.getValue()); + } + + //保存 + zbxHost.hostTagUpdate(deviceDto.getZbxId(), tagMap); + log.debug("step 9:resolve zbxID async----DEVICEID:{}, HOSTID:{} 完成", deviceDto.getDeviceId(), + deviceDto.getZbxId()); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceEventLogWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceEventLogWorker.java deleted file mode 100644 index b80f2803..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/DeviceEventLogWorker.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.zmops.iot.web.device.service.work; - - -import com.zmops.iot.domain.device.Device; -import com.zmops.iot.domain.device.query.QDevice; -import com.zmops.iot.util.ToolUtil; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.util.Map; - -/** - * @author yefei - *

                                                  - * 更新设备 在线状态 - */ -@Slf4j -@Component -public class DeviceEventLogWorker implements IWorker, Boolean> { - - - @Override - public Boolean action(Map object, Map allWrappers) { - log.debug("insert into event log…………"); - - String deviceId = object.get("hostname"); - if (ToolUtil.isEmpty(deviceId)) { - return false; - } - Device device = new QDevice().deviceId.eq(deviceId).findOne(); - if (null == device) { - return false; - } - - return true; - } - - - @Override - public Boolean defaultValue() { - return true; - } - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java deleted file mode 100644 index 66e99df0..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.zmops.iot.web.device.service.work; - -import com.zmops.iot.domain.device.Device; -import com.zmops.iot.enums.CommonStatus; -import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.device.dto.DeviceDto; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; -import io.ebean.DB; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.util.Map; - -/** - * @author yefei - *

                                                  - * 保存设备 - */ -@Slf4j -@Component -public class SaveDeviceWorker implements IWorker { - - @Override - public Device action(DeviceDto deviceDto, Map allWrappers) { - log.debug("step 1:SaveDeviceWorker----DEVICEID:{}…………",deviceDto.getDeviceId()); - - Device device = new Device(); - ToolUtil.copyProperties(deviceDto, device); - - if (ToolUtil.isNotEmpty(deviceDto.getEdit()) && "true".equals(deviceDto.getEdit())) { - DB.update(device); - } else { - device.setStatus(CommonStatus.ENABLE.getCode()); - DB.insert(device); - } - log.debug("step 1:SaveDeviceWorker----DEVICEID:{} complete",deviceDto.getDeviceId()); - return device; - } - - - @Override - public Device defaultValue() { - return new Device(); - } - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java deleted file mode 100644 index e400ea54..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.zmops.iot.web.device.service.work; - - -import com.zmops.iot.constant.ConstantsContext; -import com.zmops.iot.domain.device.query.QDeviceGroup; -import com.zmops.iot.domain.product.query.QProduct; -import com.zmops.iot.domain.proxy.query.QProxy; -import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.device.dto.DeviceDto; -import com.zmops.zeus.driver.service.ZbxHost; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.List; -import java.util.Map; - -import static com.zmops.iot.web.init.DeviceSatusScriptInit.GLOBAL_HOST_GROUP_CODE; - -/** - * @author yefei - *

                                                  - * 保存至zbx - */ -@Slf4j -@Component -public class SaveZbxHostWorker implements IWorker { - - @Autowired - ZbxHost zbxHost; - - @Override - public String action(DeviceDto deviceDto, Map map) { - log.debug("step 5:SaveZbxHostWorker----DEVICEID:{}…………", deviceDto.getDeviceId()); - //设备ID 作为zbx HOST name - String host = deviceDto.getDeviceId(); - - //取出 设备对应的 zbx主机组ID,模板ID - List hostGrpIds = new QDeviceGroup().select(QDeviceGroup.alias().zbxId).deviceGroupId.in(deviceDto.getDeviceGroupIds()).findSingleAttributeList(); - log.debug("step 5-1:SaveZbxHostWorker----hostGrpIds:{}…………", hostGrpIds.toString()); - String templateId = new QProduct().select(QProduct.alias().zbxId).productId.eq(deviceDto.getProductId()).findSingleAttribute(); - log.debug("step 5-2:SaveZbxHostWorker----templateId:{}…………", templateId); - hostGrpIds.add(ConstantsContext.getConstntsMap().get(GLOBAL_HOST_GROUP_CODE).toString()); - log.debug("step 5-3:SaveZbxHostWorker----hostGrpIds:{}…………", hostGrpIds.toString()); - //保存 zbx主机 - String s = ""; - Long proxyId = deviceDto.getProxyId(); - String zbxProxyId = null; - if (null != proxyId) { - zbxProxyId = new QProxy().select(QProxy.alias().zbxId).id.eq(proxyId).findSingleAttribute(); - } - log.debug("step 5-4:SaveZbxHostWorker----zbxProxyId:{}…………", zbxProxyId); - if (ToolUtil.isNotEmpty(deviceDto.getZbxId())) { - s = zbxHost.hostUpdate(deviceDto.getZbxId(), hostGrpIds, templateId, zbxProxyId, deviceDto.getDeviceInterface()); - } else { - s = zbxHost.hostCreate(host, hostGrpIds, templateId, zbxProxyId, deviceDto.getDeviceInterface()); - } - log.debug("step 5:SaveZbxHostWorker----DEVICEID:{} complete", deviceDto.getDeviceId()); - return s; - } - - @Override - public String defaultValue() { - return ""; - } - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java deleted file mode 100644 index 592998a1..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.zmops.iot.web.device.service.work; - - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.domain.device.Device; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; -import io.ebean.DB; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.util.Map; - -/** - * @author yefei - *

                                                  - * 更新设备中zbxID - */ -@Slf4j -@Component -public class UpdateDeviceZbxIdWorker implements IWorker { - - - @Override - public Boolean action(String deviceId, Map map) { - - Object result = map.get("saveZbxHostWork").getWorkResult().getResult(); - - JSONArray hostid = JSONObject.parseObject(result.toString()).getJSONArray("hostids"); - - log.debug("step 7:resolve zbxID async----DEVICEID:{}, HOSTID:{}…………", deviceId, hostid.get(0).toString()); - - DB.update(Device.class).where().eq("deviceId", deviceId).asUpdate().set("zbxId", hostid.get(0).toString()).update(); - - log.debug("step 7:resolve zbxID async----DEVICEID:{}, HOSTID:{} 完成", deviceId, hostid.get(0).toString()); - return true; - } - - @Override - public Boolean defaultValue() { - return true; - } - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java deleted file mode 100644 index 035d896b..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.zmops.iot.web.device.service.work; - - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.domain.device.Device; -import com.zmops.iot.domain.device.Tag; -import com.zmops.iot.domain.device.query.QTag; -import com.zmops.iot.web.device.dto.DeviceDto; -import com.zmops.zeus.driver.service.ZbxHost; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * @author yefei - *

                                                  - * 同步设备标签到zbx - */ -@Slf4j -@Component -public class UpdateZbxTagWorker implements IWorker { - - @Autowired - ZbxHost zbxHost; - - @Override - public Boolean action(DeviceDto deviceDto, Map map) { - log.debug("UpdateZbxTagWorker……"); - //取出 ZBX hostid - Object result = map.get("saveZbxHostWork").getWorkResult().getResult(); - JSONArray hostid = JSONObject.parseObject(result.toString()).getJSONArray("hostids"); - - //取 设备ID - Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); - String deviceId = device.getDeviceId(); - - //查询出本地tag - List list = new QTag().sid.eq(deviceId).findList(); - Map tagMap = new HashMap<>(list.size()); - for (Tag tag : list) { - tagMap.put(tag.getTag(), tag.getValue()); - } - - //保存 - zbxHost.hostTagUpdate(hostid.getString(0), tagMap); - return true; - } - - @Override - public Boolean defaultValue() { - return true; - } - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceDeleteEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceDeleteEvent.java new file mode 100644 index 00000000..2c25c940 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceDeleteEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.event.applicationEvent.dto.DeviceDeleteEventData; + +/** + * @author yefei + **/ +public class DeviceDeleteEvent extends BaseEvent { + public DeviceDeleteEvent(Object source, DeviceDeleteEventData eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceSaveEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceSaveEvent.java new file mode 100644 index 00000000..e5c286a2 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceSaveEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.device.dto.DeviceDto; + +/** + * @author yefei + **/ +public class DeviceSaveEvent extends BaseEvent { + public DeviceSaveEvent(Object source, DeviceDto eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceSceneLogEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceSceneLogEvent.java new file mode 100644 index 00000000..4b258b84 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceSceneLogEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.event.applicationEvent.dto.LogEventData; + +/** + * @author yefei + **/ +public class DeviceSceneLogEvent extends BaseEvent { + public DeviceSceneLogEvent(Object source, LogEventData eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceServiceLogEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceServiceLogEvent.java new file mode 100644 index 00000000..845afc58 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceServiceLogEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.event.applicationEvent.dto.LogEventData; + +/** + * @author yefei + **/ +public class DeviceServiceLogEvent extends BaseEvent { + public DeviceServiceLogEvent(Object source, LogEventData eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductAttrCreateEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductAttrCreateEvent.java new file mode 100644 index 00000000..58c3b881 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductAttrCreateEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.product.dto.ProductAttr; + +/** + * @author yefei + **/ +public class ProductAttrCreateEvent extends BaseEvent { + public ProductAttrCreateEvent(Object source, ProductAttr eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductAttrUpdateEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductAttrUpdateEvent.java new file mode 100644 index 00000000..ed1f32c2 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductAttrUpdateEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.product.dto.ProductAttr; + +/** + * @author yefei + **/ +public class ProductAttrUpdateEvent extends BaseEvent { + public ProductAttrUpdateEvent(Object source, ProductAttr eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductEventTriggerCreateEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductEventTriggerCreateEvent.java new file mode 100644 index 00000000..82a62241 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductEventTriggerCreateEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.product.dto.ProductEventRule; + +/** + * @author yefei + **/ +public class ProductEventTriggerCreateEvent extends BaseEvent { + public ProductEventTriggerCreateEvent(Object source, ProductEventRule eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductEventTriggerUpdateEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductEventTriggerUpdateEvent.java new file mode 100644 index 00000000..09796102 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductEventTriggerUpdateEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.product.dto.ProductEventRule; + +/** + * @author yefei + **/ +public class ProductEventTriggerUpdateEvent extends BaseEvent { + public ProductEventTriggerUpdateEvent(Object source, ProductEventRule eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductModelCreateEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductModelCreateEvent.java new file mode 100644 index 00000000..1dc8f265 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductModelCreateEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.product.dto.ProductAttr; + +/** + * @author yefei + **/ +public class ProductModelCreateEvent extends BaseEvent { + public ProductModelCreateEvent(Object source, ProductAttr eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductModelUpdateEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductModelUpdateEvent.java new file mode 100644 index 00000000..68e936df --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductModelUpdateEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.product.dto.ProductAttr; + +/** + * @author yefei + **/ +public class ProductModelUpdateEvent extends BaseEvent { + public ProductModelUpdateEvent(Object source, ProductAttr eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductServiceCreateEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductServiceCreateEvent.java new file mode 100644 index 00000000..9a6f0dc6 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductServiceCreateEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.product.dto.ProductServiceDto; + +/** + * @author yefei + **/ +public class ProductServiceCreateEvent extends BaseEvent { + public ProductServiceCreateEvent(Object source, ProductServiceDto eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductServiceUpdateEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductServiceUpdateEvent.java new file mode 100644 index 00000000..83a3caec --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductServiceUpdateEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.product.dto.ProductServiceDto; + +/** + * @author yefei + **/ +public class ProductServiceUpdateEvent extends BaseEvent { + public ProductServiceUpdateEvent(Object source, ProductServiceDto eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/dto/DeviceDeleteEventData.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/dto/DeviceDeleteEventData.java new file mode 100644 index 00000000..c936829f --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/dto/DeviceDeleteEventData.java @@ -0,0 +1,15 @@ +package com.zmops.iot.web.event.applicationEvent.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DeviceDeleteEventData { + private String deviceId; + private String zbxId; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/dto/LogEventData.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/dto/LogEventData.java new file mode 100644 index 00000000..b3d80156 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/dto/LogEventData.java @@ -0,0 +1,22 @@ +package com.zmops.iot.web.event.applicationEvent.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author yefei + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class LogEventData { + + private Long eventRuleId; + private String relationId; + private String triggerType; + private Long triggerUser; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/ServiceEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/ServiceEventProcess.java index 9ddc2367..1634430d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/ServiceEventProcess.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/ServiceEventProcess.java @@ -9,20 +9,19 @@ import com.zmops.iot.domain.product.query.QProductEventService; import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.device.service.work.DeviceServiceLogWorker; +import com.zmops.iot.web.event.applicationEvent.DeviceServiceLogEvent; +import com.zmops.iot.web.event.applicationEvent.dto.LogEventData; import com.zmops.iot.web.event.pgEvent.EventProcess; import com.zmops.iot.web.event.pgEvent.dto.EventDataDto; -import com.zmops.zeus.server.async.executor.Async; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; /** @@ -35,7 +34,7 @@ public class ServiceEventProcess implements EventProcess { @Autowired - DeviceServiceLogWorker deviceServiceLogWorker; + ApplicationEventPublisher publisher; @Override public void process(EventDataDto eventData) { @@ -48,22 +47,9 @@ public void process(EventDataDto eventData) { return; } - alarmInfo.put("eventRuleId", productEventRelationList.get(0).getEventRuleId()); - alarmInfo.put("relationId", productEventRelationList.get(0).getRelationId()); - alarmInfo.put("triggerType", "自动"); - //记录服务日志 - WorkerWrapper, Boolean> deviceServiceLogWork = new WorkerWrapper.Builder, Boolean>() - .id("deviceServiceLogWorker") - .worker(deviceServiceLogWorker) - .param(alarmInfo) - .build(); - - try { - Async.beginWork(1000, deviceServiceLogWork); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } + publisher.publishEvent(new DeviceServiceLogEvent(this, LogEventData.builder().eventRuleId(productEventRelationList.get(0).getEventRuleId()) + .relationId(productEventRelationList.get(0).getRelationId()).triggerType("自动").build())); //查询 告警规则 关联的 服务 List productEventServiceList = new QProductEventService() @@ -89,8 +75,8 @@ public void process(EventDataDto eventData) { List paramList = DefinitionsUtil.getServiceParam(val.getServiceId()); if (ToolUtil.isNotEmpty(paramList)) { - serviceMap.put("param", paramList.parallelStream() - .collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue))); + serviceMap.put("param", paramList.parallelStream().filter(o -> key.equals(o.getDeviceId())) + .collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue, (a, b) -> a))); } serviceList.add(serviceMap); }); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index 29744610..be5166c4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -162,6 +162,7 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { SERVICE_NOT_EXISTS(1602, "服务不存在"), PRODUCT_EVENT_HAS_DEPTED(1605, "服务已用于告警规则或场景联动,不能删除"), SERVICE_HAS_DUPLICATE(1606, "存在相同的动作服务"), + SERVICE_PARAM_NOT_EXISTS(1607, "服务未配置参数"), /** * 触发规则相关 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java index 3ae0e840..acb30692 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java @@ -126,7 +126,7 @@ public ResponseData getUserMacro(@Validated(BaseEntity.Get.class) @RequestBody U }); // 主机宏 List hostMacroList = JSONObject.parseArray(zbxMacro.macroGet(zbxId + ""), UserMacro.class); - Map hostMacroMap = hostMacroList.parallelStream().collect(Collectors.toMap(UserMacro::getMacro, o -> o)); + Map hostMacroMap = hostMacroList.parallelStream().collect(Collectors.toMap(UserMacro::getMacro, o -> o, (a, b) -> a)); //过滤模板宏中相同的KEY tempMacroList.removeIf(macro -> null != hostMacroMap.get(macro.getMacro())); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index e45f50bc..eccfe510 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -15,19 +15,18 @@ import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.ProductEventTriggerCreateEvent; +import com.zmops.iot.web.event.applicationEvent.ProductEventTriggerUpdateEvent; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductEventDto; import com.zmops.iot.web.product.dto.ProductEventRule; import com.zmops.iot.web.product.dto.param.EventParm; import com.zmops.iot.web.product.service.ProductEventRuleService; -import com.zmops.iot.web.product.service.work.SaveProductEventTriggerWorker; -import com.zmops.iot.web.product.service.work.UpdateProductEventTriggerWorker; import com.zmops.zeus.driver.service.ZbxTrigger; -import com.zmops.zeus.server.async.executor.Async; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import io.ebean.annotation.Transactional; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -35,7 +34,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; /** @@ -59,10 +57,7 @@ public class ProductEventTriggerController { private static final String EXECUTE_TAG_NAME = "__execute__"; @Autowired - SaveProductEventTriggerWorker saveProductEventTriggerWorker; - - @Autowired - UpdateProductEventTriggerWorker updateProductEventTriggerWorker; + ApplicationEventPublisher publisher; /** * 触发器 分页列表 @@ -136,18 +131,7 @@ public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseE productEventRuleService.updateProductEventRuleZbxId(eventRuleId, triggerIds); //step 6: 同步到产品下的设备 - WorkerWrapper saveProductEventTriggerWork = - new WorkerWrapper.Builder().worker(saveProductEventTriggerWorker).param(eventRule).build(); - - try { - try { - Async.beginWork(1000, saveProductEventTriggerWork); - } catch (ExecutionException e) { - e.printStackTrace(); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } + publisher.publishEvent(new ProductEventTriggerCreateEvent(this,eventRule)); // 返回触发器ID @@ -204,16 +188,9 @@ public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseE zbxTrigger.triggerTagCreate(list.get(0).getZbxId(), tags); - //step 4: 同步到产品下的设备 - WorkerWrapper updateProductEventTriggerWork = - new WorkerWrapper.Builder().worker(updateProductEventTriggerWorker).param(eventRule).build(); + publisher.publishEvent(new ProductEventTriggerUpdateEvent(this,eventRule)); - try { - Async.beginWork(1000, updateProductEventTriggerWork); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } return ResponseData.success(eventRule.getEventRuleId()); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java index ea64f74c..ad96650c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java @@ -54,6 +54,7 @@ public class ProductAttrDto { private List tags; //预处理 + @JsonIgnore private List processStepList; private Long templateId; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java index fa858720..8c24338e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -12,22 +12,20 @@ import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.ProductAttrCreateEvent; +import com.zmops.iot.web.event.applicationEvent.ProductAttrUpdateEvent; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.iot.web.product.dto.ProductAttrDto; import com.zmops.iot.web.product.dto.ProductTag; import com.zmops.iot.web.product.dto.param.ProductAttrParam; -import com.zmops.iot.web.product.service.work.AsyncAttrEventZbxIdWorker; -import com.zmops.iot.web.product.service.work.SaveProdAttrEventTriggerWorker; -import com.zmops.iot.web.product.service.work.SaveProdAttrEventWorker; -import com.zmops.iot.web.product.service.work.UpdateAttributeEventWorker; import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.entity.ZbxProcessingStep; import com.zmops.zeus.driver.service.ZbxItem; -import com.zmops.zeus.server.async.executor.Async; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import java.util.*; @@ -37,22 +35,14 @@ * @author yefei **/ @Service +@Slf4j public class ProductAttributeEventService { @Autowired private ZbxItem zbxItem; @Autowired - SaveProdAttrEventWorker saveProdAttrEventWorker; - - @Autowired - AsyncAttrEventZbxIdWorker asyncAttrEventZbxIdWorker; - - @Autowired - UpdateAttributeEventWorker updateAttributeEventWorker; - - @Autowired - SaveProdAttrEventTriggerWorker saveProdAttrEventTriggerWorker; + ApplicationEventPublisher publisher; /** * 产品属性分页列表 @@ -173,20 +163,9 @@ public void createProductAttr(ProductAttr productAttr, String zbxId) { productAttributeEvent.setZbxId(zbxId); productAttributeEvent.save(); + publisher.publishEvent(new ProductAttrCreateEvent(this, productAttr)); - WorkerWrapper saveProdAttrEventTriggerWork = new WorkerWrapper.Builder() - .worker(saveProdAttrEventTriggerWorker).param(productAttr).build(); - - WorkerWrapper asyncAttrEventZbxIdWork = new WorkerWrapper.Builder() - .worker(asyncAttrEventZbxIdWorker).param(productAttr).build(); - WorkerWrapper saveProdAttrEventWork = new WorkerWrapper.Builder() - .worker(saveProdAttrEventWorker).param(productAttr).next(asyncAttrEventZbxIdWork).build(); - - try { - Async.beginWork(10000, saveProdAttrEventWork, saveProdAttrEventTriggerWork); - } catch (Exception e) { - e.printStackTrace(); - } + log.debug("------------------"); } @@ -291,14 +270,9 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { DB.update(productAttributeEvent); - WorkerWrapper updateProdAttrWork = new WorkerWrapper.Builder().worker(updateAttributeEventWorker).param(productAttr).build(); - - try { - Async.beginWork(100, updateProdAttrWork); - } catch (Exception e) { - e.printStackTrace(); - } + publisher.publishEvent(new ProductAttrUpdateEvent(this, productAttr)); + log.debug("----------------------"); return productAttr; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java index 5fd70f95..8aa3ae6b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -191,7 +191,7 @@ public void updateProductEventRuleZbxId(Long eventRuleId, String[] zbxId) { List triggers = JSONObject.parseArray(s, Triggers.class); - Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.get(0).host, Triggers::getTriggerid)); + Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.get(0).host, Triggers::getTriggerid, (a, b) -> a)); List productEventRelationList = new QProductEventRelation().eventRuleId.eq(eventRuleId).findList(); @@ -214,7 +214,7 @@ public void updateProductEventRuleZbxId(Long eventRuleId, String[] zbxId) { * @return 触发器ID */ public String[] createZbxTrigger(String triggerName, String expression, Byte level) { - String res = zbxTrigger.triggerCreate(triggerName, expression, level); + String res = zbxTrigger.triggerCreate(triggerName, expression, level,0); return JSON.parseObject(res, TriggerIds.class).getTriggerids(); } @@ -242,7 +242,7 @@ public Pager getEventByPage(EventParm eventParm) { if (ToolUtil.isNotEmpty(eventRuleIdList)) { query.eventRuleId.in(eventRuleIdList); } - Map productEventRelationMap = productEventRelationList.parallelStream().collect(Collectors.toMap(ProductEventRelation::getEventRuleId, o -> o)); + Map productEventRelationMap = productEventRelationList.parallelStream().collect(Collectors.toMap(ProductEventRelation::getEventRuleId, o -> o, (a, b) -> a)); List list = query.setFirstRow((eventParm.getPage() - 1) * eventParm.getMaxRow()) @@ -297,7 +297,7 @@ public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, S public void updateProductEvent() { List deviceList = new QProductEvent().findList(); - Map map = deviceList.parallelStream().collect(Collectors.toMap(ProductEvent::getEventRuleId, ProductEvent::getEventRuleName)); + Map map = deviceList.parallelStream().collect(Collectors.toMap(ProductEvent::getEventRuleId, ProductEvent::getEventRuleName, (a, b) -> a)); DefinitionsUtil.updateProductEventCache(map); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelEventPublisher.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelEventPublisher.java new file mode 100644 index 00000000..9f3effae --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelEventPublisher.java @@ -0,0 +1,28 @@ +package com.zmops.iot.web.product.service; + +import com.zmops.iot.web.event.applicationEvent.ProductModelCreateEvent; +import com.zmops.iot.web.event.applicationEvent.ProductModelUpdateEvent; +import com.zmops.iot.web.product.dto.ProductAttr; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.stereotype.Component; + +@Component +@EnableAsync +public class ProductModelEventPublisher { + + @Autowired + ApplicationEventPublisher publisher; + + @Async + public void productModelCreateEventPublish(ProductAttr productAttr) { + publisher.publishEvent(new ProductModelCreateEvent(this, productAttr)); + } + + @Async + public void productModelUpdateEventPublish(ProductAttr productAttr) { + publisher.publishEvent(new ProductModelUpdateEvent(this, productAttr)); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index 632d04ea..55a7ddb8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -15,21 +15,15 @@ import com.zmops.iot.web.product.dto.ProductAttrDto; import com.zmops.iot.web.product.dto.ProductTag; import com.zmops.iot.web.product.dto.param.ProductAttrParam; -import com.zmops.iot.web.product.service.work.AsyncAttrZbxIdWorker; -import com.zmops.iot.web.product.service.work.SaveProdAttrWorker; -import com.zmops.iot.web.product.service.work.UpdateAttributeWorker; import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.entity.ZbxProcessingStep; import com.zmops.zeus.driver.service.ZbxItem; -import com.zmops.zeus.server.async.executor.Async; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import io.ebean.DtoQuery; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.*; -import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; /** @@ -42,13 +36,7 @@ public class ProductModelService { private ZbxItem zbxItem; @Autowired - SaveProdAttrWorker saveProdAttrWorker; - - @Autowired - AsyncAttrZbxIdWorker asyncAttrZbxIdWorker; - - @Autowired - UpdateAttributeWorker updateProdAttrWorker; + ProductModelEventPublisher productModelEventPublisher; /** * 产品属性分页列表 @@ -143,6 +131,8 @@ public ProductAttrDto detail(Long attrId) { JSONArray itemInfo = JSONObject.parseArray(zbxItem.getItemInfo(attr.getZbxId(), null)); attr.setTags(JSONObject.parseArray(itemInfo.getJSONObject(0).getString("tags"), ProductTag.Tag.class)); attr.setProcessStepList(formatProcessStep(itemInfo.getJSONObject(0).getString("preprocessing"))); + + // String valuemap = itemInfo.getJSONObject(0).getString("valuemap"); // // if (ToolUtil.isNotEmpty(valuemap) && !"[]".equals(valuemap)) { @@ -179,21 +169,23 @@ public void createProductAttr(ProductAttr productAttr, String zbxId) { productAttribute.setZbxId(zbxId); productAttribute.save(); + productModelEventPublisher.productModelCreateEventPublish(productAttr); - WorkerWrapper asyncAttrZbxIdWork = new WorkerWrapper.Builder() - .worker(asyncAttrZbxIdWorker).param(productAttr).build(); - WorkerWrapper saveProdAttrWork = new WorkerWrapper.Builder() - .worker(saveProdAttrWorker).param(productAttr).next(asyncAttrZbxIdWork).build(); - try { - Async.beginWork(10000, saveProdAttrWork); - } catch (ExecutionException | InterruptedException e) { - e.printStackTrace(); - } +// WorkerWrapper asyncAttrZbxIdWork = new WorkerWrapper.Builder() +// .worker(asyncAttrZbxIdWorker).param(productAttr).build(); +// WorkerWrapper saveProdAttrWork = new WorkerWrapper.Builder() +// .worker(saveProdAttrWorker).param(productAttr).next(asyncAttrZbxIdWork).build(); +// +// try { +// Async.beginWork(10000, saveProdAttrWork); +// } catch (ExecutionException | InterruptedException e) { +// e.printStackTrace(); +// } } - private ProductAttribute buildProdAttribute(ProductAttribute prodAttribute, ProductAttr productAttr) { + private void buildProdAttribute(ProductAttribute prodAttribute, ProductAttr productAttr) { prodAttribute.setProductId(productAttr.getProductId()); prodAttribute.setName(productAttr.getAttrName()); prodAttribute.setKey(productAttr.getKey()); @@ -205,8 +197,6 @@ private ProductAttribute buildProdAttribute(ProductAttribute prodAttribute, Prod prodAttribute.setDepAttrId(productAttr.getDepAttrId()); prodAttribute.setValuemapid(productAttr.getValuemapid()); prodAttribute.setUnit(productAttr.getUnit()); - - return prodAttribute; } /** @@ -231,7 +221,7 @@ public String createTrapperItem(ProductAttr productAttr) { ZbxProcessingStep step = new ZbxProcessingStep(); step.setType(i.getType()); - step.setParams(i.getParams().replaceAll("\n","").replaceAll("\"", "\\\\\\\\\"")); + step.setParams(i.getParams().replaceAll("\n", "").replaceAll("\"", "\\\\\\\\\"")); processingSteps.add(step); }); @@ -246,7 +236,7 @@ public String createTrapperItem(ProductAttr productAttr) { delay = productAttr.getDelay() + productAttr.getUnit(); } return zbxItem.createTrapperItem(itemName, productAttr.getKey(), - hostId, productAttr.getSource(), delay, productAttr.getMasterItemId(), productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap,null); + hostId, productAttr.getSource(), delay, productAttr.getMasterItemId(), productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap, null); } /** @@ -257,6 +247,9 @@ public String createTrapperItem(ProductAttr productAttr) { */ public ProductAttr updateTrapperItem(ProductAttr productAttr) { ProductAttribute productAttribute = new QProductAttribute().attrId.eq(productAttr.getAttrId()).findOne(); + if (null == productAttribute) { + productAttribute = new ProductAttribute(); + } buildProdAttribute(productAttribute, productAttr); Product prod = new QProduct().productId.eq(Long.parseLong(productAttr.getProductId())).findOne(); if (null == prod) { @@ -269,7 +262,7 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { ZbxProcessingStep step = new ZbxProcessingStep(); step.setType(i.getType()); - step.setParams(i.getParams().replaceAll("\n","").replaceAll("\"", "\\\\\\\\\"")); + step.setParams(i.getParams().replaceAll("\n", "").replaceAll("\"", "\\\\\\\\\"")); processingSteps.add(step); }); @@ -286,17 +279,19 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { delay = productAttr.getDelay() + productAttr.getUnit(); } zbxItem.updateTrapperItem(productAttribute.getZbxId(), productAttr.getAttrId() + "", productAttr.getKey(), - hostId, productAttr.getSource(), delay, productAttr.getMasterItemId(), productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap,null); + hostId, productAttr.getSource(), delay, productAttr.getMasterItemId(), productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap, null); DB.update(productAttribute); - WorkerWrapper updateProdAttrWork = new WorkerWrapper.Builder().worker(updateProdAttrWorker).param(productAttr).build(); + productModelEventPublisher.productModelUpdateEventPublish(productAttr); - try { - Async.beginWork(100, updateProdAttrWork); - } catch (ExecutionException | InterruptedException e) { - e.printStackTrace(); - } +// WorkerWrapper updateProdAttrWork = new WorkerWrapper.Builder().worker(updateProdAttrWorker).param(productAttr).build(); +// +// try { +// Async.beginWork(100, updateProdAttrWork); +// } catch (ExecutionException | InterruptedException e) { +// e.printStackTrace(); +// } return productAttr; } @@ -316,8 +311,9 @@ public void deleteTrapperItem(ProductAttr productAttr) { } //检查属性是否被告警规则引入 - List attrIds = new QProductAttribute().select(QProductAttribute.alias().attrId).templateId.in(productAttr.getAttrIds()).findSingleAttributeList(); - count = new QProductEventExpression().productAttrId.in(attrIds).findCount(); +// List attrIds = new QProductAttribute().select(QProductAttribute.alias().attrId).templateId.in(productAttr.getAttrIds()).findSingleAttributeList(); +// attrIds.addAll(productAttr.getAttrIds()); + count = new QProductEventExpression().productAttrId.in(productAttr.getAttrIds()).findCount(); if (count > 0) { throw new ServiceException(BizExceptionEnum.PRODUCT_EVENT_HASDEPTED); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java index ee65acb0..6fa25915 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java @@ -98,7 +98,7 @@ public Pager getProductByPage(ProductBasicInfo prodBasicInfo) { if (ToolUtil.isNotEmpty(list)) { List productIds = list.parallelStream().map(ProductDto::getProductId).collect(Collectors.toList()); List deviceList = new QDevice().select(QDevice.alias().productId, QDevice.alias().totalCount).productId.in(productIds).findList(); - Map map = deviceList.parallelStream().collect(Collectors.toMap(Device::getProductId, Device::getTotalCount)); + Map map = deviceList.parallelStream().collect(Collectors.toMap(Device::getProductId, Device::getTotalCount, (a, b) -> a)); for (ProductDto productDto : list) { productDto.setDeviceNum(Optional.ofNullable(map.get(productDto.getProductId())).orElse(0L)); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java index 0894154d..bcb1627d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -11,24 +11,22 @@ import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.ProductServiceCreateEvent; +import com.zmops.iot.web.event.applicationEvent.ProductServiceUpdateEvent; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductServiceDto; import com.zmops.iot.web.product.dto.param.ProductSvcParam; -import com.zmops.iot.web.product.service.work.SaveProdSvcWorker; -import com.zmops.iot.web.product.service.work.UpdateProdSvcWorker; -import com.zmops.zeus.server.async.executor.Async; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import io.ebean.DtoQuery; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; /** @@ -40,10 +38,7 @@ public class ProductSvcService implements CommandLineRunner { @Autowired - SaveProdSvcWorker saveProdSvcWorker; - - @Autowired - UpdateProdSvcWorker updateProdSvcWorker; + ApplicationEventPublisher publisher; /** * 服务分页列表 @@ -164,14 +159,9 @@ public ProductServiceDto create(ProductServiceDto productServiceDto) { } //同步到设备 + if (ToolUtil.isNum(productServiceDto.getRelationId())) { - WorkerWrapper saveProdAttrWork = - new WorkerWrapper.Builder().worker(saveProdSvcWorker).param(productServiceDto).build(); - try { - Async.beginWork(100, saveProdAttrWork); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } + publisher.publishEvent(new ProductServiceCreateEvent(this, productServiceDto)); } updateService(); return productServiceDto; @@ -210,14 +200,10 @@ public ProductServiceDto update(ProductServiceDto productServiceDto) { } //同步到设备 + + if (ToolUtil.isNum(productServiceDto.getRelationId())) { - WorkerWrapper updateProdSvcWork = - new WorkerWrapper.Builder().worker(updateProdSvcWorker).param(productServiceDto).build(); - try { - Async.beginWork(1000, updateProdSvcWork); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } + publisher.publishEvent(new ProductServiceUpdateEvent(this, productServiceDto)); } updateService(); return productServiceDto; @@ -259,7 +245,7 @@ public List paramList(long serviceId) { */ private void updateService() { List serviceList = new QProductService().findList(); - Map map = serviceList.parallelStream().collect(Collectors.toMap(ProductService::getId, ProductService::getName)); + Map map = serviceList.parallelStream().collect(Collectors.toMap(ProductService::getId, ProductService::getName, (a, b) -> a)); DefinitionsUtil.updateServiceCache(map); List serviceParamList = new QProductServiceParam().findList(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java index 1f41a2a1..f719a095 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java @@ -73,8 +73,12 @@ public Long createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { long ruleId = IdUtil.getSnowflake().nextId(); judgeRule.setRuleId(ruleId); //step 1:保存到zbx 建立上线及下线规则 + String ruleCondition = judgeRule.getRuleCondition(); + if(!ToolUtil.isNum(ruleCondition)){ + ruleCondition = "\""+ruleCondition+"\""; + } String res = deviceStatusTrigger.createDeviceStatusTrigger(judgeRule.getRuleId() + "", judgeRule.getRelationId(), - judgeRule.getProductAttrKey(), judgeRule.getRuleCondition() + judgeRule.getUnit(), judgeRule.getRuleFunction(), judgeRule.getProductAttrKeyRecovery(), + judgeRule.getProductAttrKey(), ruleCondition + judgeRule.getUnit(), judgeRule.getRuleFunction(), judgeRule.getProductAttrKeyRecovery(), judgeRule.getRuleConditionRecovery() + judgeRule.getUnitRecovery(), judgeRule.getRuleFunctionRecovery()); String[] triggerIds = getTriggerId(res); @@ -112,9 +116,9 @@ public Long createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { } List zbxTriggerInfoList = JSONObject.parseArray(triggerRes, ZbxTriggerInfo.class); Map hostTriggerMap = zbxTriggerInfoList.parallelStream().filter(o -> o.getTags().parallelStream().anyMatch(t -> "__offline__".equals(t.getTag()))) - .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid)); + .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid, (a, b) -> a)); Map hostRecoveryTriggerMap = zbxTriggerInfoList.parallelStream().filter(o -> o.getTags().parallelStream().anyMatch(t -> "__online__".equals(t.getTag()))) - .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid)); + .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid, (a, b) -> a)); //保存 设备与规则的关系 deviceDtoList.forEach(deviceDto -> { @@ -144,8 +148,12 @@ public Long updateDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { if (null == relation) { return judgeRule.getRuleId(); } + String ruleCondition = judgeRule.getRuleCondition(); + if(!ToolUtil.isNum(ruleCondition)){ + ruleCondition = "\""+ruleCondition+"\""; + } deviceStatusTrigger.updateDeviceStatusTrigger(relation.getZbxId(), judgeRule.getRuleId() + "", judgeRule.getRelationId(), - judgeRule.getProductAttrKey(), judgeRule.getRuleCondition() + judgeRule.getUnit(), judgeRule.getRuleFunction(), judgeRule.getProductAttrKeyRecovery(), + judgeRule.getProductAttrKey(), ruleCondition + judgeRule.getUnit(), judgeRule.getRuleFunction(), judgeRule.getProductAttrKeyRecovery(), judgeRule.getRuleConditionRecovery() + judgeRule.getUnitRecovery(), judgeRule.getRuleFunctionRecovery(), relation.getZbxIdRecovery()); ProductStatusFunction productStatusFunction = new ProductStatusFunction(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTypeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTypeService.java index 661c4669..10ab73cd 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTypeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTypeService.java @@ -139,7 +139,7 @@ private void updateProductType() { if (ToolUtil.isEmpty(list)) { return; } - DefinitionsUtil.updateProductType(list.parallelStream().collect(Collectors.toMap(ProductType::getId, ProductType::getName))); + DefinitionsUtil.updateProductType(list.parallelStream().collect(Collectors.toMap(ProductType::getId, ProductType::getName, (a, b) -> a))); } @Override diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/AsyncAttrEventZbxIdEventHandler.java similarity index 75% rename from zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/AsyncAttrEventZbxIdEventHandler.java index a0608e98..be47bad0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrEventZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/AsyncAttrEventZbxIdEventHandler.java @@ -1,18 +1,20 @@ -package com.zmops.iot.web.product.service.work; +package com.zmops.iot.web.product.service.event; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.domain.product.query.QProductAttributeEvent; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.ProductAttrCreateEvent; import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.service.ZbxItem; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.stereotype.Component; import java.util.List; @@ -26,20 +28,23 @@ */ @Slf4j @Component -public class AsyncAttrEventZbxIdWorker implements IWorker { +@EnableAsync +public class AsyncAttrEventZbxIdEventHandler implements ApplicationListener { @Autowired ZbxItem zbxItem; @Override - public Boolean action(ProductAttr productAttr, Map map) { + @Async + public void onApplicationEvent(ProductAttrCreateEvent event) { log.debug("AsyncAttrEventZbxIdWorker……"); + ProductAttr productAttr = event.getEventData(); Long attrId = productAttr.getAttrId(); //根据name 取出监控项 List itemInfos = JSONObject.parseArray(zbxItem.getItemListByName(attrId + ""), ZbxItemInfo.class); if (ToolUtil.isEmpty(itemInfos)) { - return true; + return; } Map itemMap = itemInfos.parallelStream().collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), o -> o)); @@ -53,12 +58,6 @@ public Boolean action(ProductAttr productAttr, Map map) { } DB.updateAll(productAttributeEventList); - return true; - } - @Override - public Boolean defaultValue() { - return true; } - } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/AsyncAttrZbxIdEventHandler.java similarity index 76% rename from zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/AsyncAttrZbxIdEventHandler.java index 8b8aca0f..37bf9770 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/AsyncAttrZbxIdWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/AsyncAttrZbxIdEventHandler.java @@ -1,18 +1,19 @@ -package com.zmops.iot.web.product.service.work; +package com.zmops.iot.web.product.service.event; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.ProductModelCreateEvent; import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.service.ZbxItem; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import java.util.List; @@ -26,20 +27,22 @@ */ @Slf4j @Component -public class AsyncAttrZbxIdWorker implements IWorker { +@Order(1) +public class AsyncAttrZbxIdEventHandler implements ApplicationListener { @Autowired ZbxItem zbxItem; @Override - public Boolean action(ProductAttr productAttr, Map map) { + public void onApplicationEvent(ProductModelCreateEvent event) { log.debug("AsyncAttrZbxIdWorker……"); + ProductAttr productAttr = event.getEventData(); Long attrId = productAttr.getAttrId(); //根据name 取出监控项 List itemInfos = JSONObject.parseArray(zbxItem.getItemListByName(attrId + ""), ZbxItemInfo.class); if (ToolUtil.isEmpty(itemInfos)) { - return true; + return; } Map itemMap = itemInfos.parallelStream().collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), o -> o)); @@ -50,12 +53,6 @@ public Boolean action(ProductAttr productAttr, Map map) { } DB.updateAll(productAttributeList); - return true; - } - - @Override - public Boolean defaultValue() { - return true; } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdAttrEventEventHandler.java similarity index 76% rename from zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdAttrEventEventHandler.java index 760d77b8..924734f4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdAttrEventEventHandler.java @@ -1,20 +1,20 @@ -package com.zmops.iot.web.product.service.work; +package com.zmops.iot.web.product.service.event; import cn.hutool.core.util.IdUtil; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductAttributeEvent; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.ProductAttrCreateEvent; import com.zmops.iot.web.product.dto.ProductAttr; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; -import java.util.Map; /** * @author yefei @@ -23,18 +23,19 @@ */ @Slf4j @Component -public class SaveProdAttrEventWorker implements IWorker { +public class SaveProdAttrEventEventHandler implements ApplicationListener { @Override - public Boolean action(ProductAttr productAttr, Map map) { + @Async + public void onApplicationEvent(ProductAttrCreateEvent event) { log.debug("SaveProdAttrEventTriggerWorker…………"); - + ProductAttr productAttr = event.getEventData(); String prodId = productAttr.getProductId(); int count = new QDevice().deviceId.eq(prodId).findCount(); if (count > 0) { - return true; + return; } List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); @@ -52,13 +53,6 @@ public Boolean action(ProductAttr productAttr, Map map) { } DB.saveAll(productAttributeEventList); - return true; - } - - - @Override - public Boolean defaultValue() { - return true; } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdAttrEventHandler.java similarity index 83% rename from zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdAttrEventHandler.java index 3220e283..02c91704 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdAttrEventHandler.java @@ -1,4 +1,4 @@ -package com.zmops.iot.web.product.service.work; +package com.zmops.iot.web.product.service.event; import cn.hutool.core.util.IdUtil; @@ -6,11 +6,12 @@ import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.event.applicationEvent.ProductModelCreateEvent; import com.zmops.iot.web.product.dto.ProductAttr; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import java.util.ArrayList; @@ -26,13 +27,15 @@ */ @Slf4j @Component -public class SaveProdAttrWorker implements IWorker { +@Order(0) +public class SaveProdAttrEventHandler implements ApplicationListener { private static final String ATTR_SOURCE_DEPEND = "18"; @Override - public Boolean action(ProductAttr productAttr, Map map) { + public void onApplicationEvent(ProductModelCreateEvent event) { log.debug("SaveProdAttrWorker…………"); + ProductAttr productAttr = event.getEventData(); String sql = "select device_id from device " + " where product_id = :productId and device_id not in (" + @@ -44,14 +47,14 @@ public Boolean action(ProductAttr productAttr, Map map) { List productAttributeList = new ArrayList<>(); if (ToolUtil.isEmpty(deviceDtoList)) { - return true; + return; } //处理依赖属性 Map attrIdMap = new ConcurrentHashMap<>(deviceDtoList.size()); if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { List list = new QProductAttribute().templateId.eq(productAttr.getDepAttrId()).findList(); - attrIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getProductId, ProductAttribute::getAttrId)); + attrIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getProductId, ProductAttribute::getAttrId, (a, b) -> a)); } for (DeviceDto deviceDto : deviceDtoList) { @@ -68,13 +71,6 @@ public Boolean action(ProductAttr productAttr, Map map) { } DB.saveAll(productAttributeList); - return true; - } - - - @Override - public Boolean defaultValue() { - return true; } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdAttrEventTriggerEventHandler.java similarity index 67% rename from zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdAttrEventTriggerEventHandler.java index 682daf7b..17a71967 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrEventTriggerWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdAttrEventTriggerEventHandler.java @@ -1,14 +1,15 @@ -package com.zmops.iot.web.product.service.work; +package com.zmops.iot.web.product.service.event; import com.alibaba.fastjson.JSON; +import com.zmops.iot.web.event.applicationEvent.ProductAttrCreateEvent; import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.zeus.driver.service.ZbxTrigger; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import java.util.Map; @@ -21,16 +22,17 @@ */ @Slf4j @Component -public class SaveProdAttrEventTriggerWorker implements IWorker { +public class SaveProdAttrEventTriggerEventHandler implements ApplicationListener { @Autowired - private ZbxTrigger zbxTrigger; - private static final String EVENT_TAG_NAME = "__event__"; + private ZbxTrigger zbxTrigger; + private static final String EVENT_TAG_NAME = "__event__"; @Override - public Boolean action(ProductAttr productAttr, Map map) { + @Async + public void onApplicationEvent(ProductAttrCreateEvent event) { log.debug("SaveProdAttrEventTriggerWorker…………"); - + ProductAttr productAttr = event.getEventData(); String prodId = productAttr.getProductId(); StringBuilder expression = new StringBuilder(); expression.append("count(/"); @@ -39,20 +41,13 @@ public Boolean action(ProductAttr productAttr, Map map) { expression.append(productAttr.getKey()); expression.append(",#1"); expression.append(") >0 "); - String res = zbxTrigger.triggerCreate(productAttr.getAttrName(), expression.toString(), productAttr.getEventLevel()); + String res = zbxTrigger.triggerCreate(productAttr.getAttrName(), expression.toString(), productAttr.getEventLevel(),1); String[] triggerids = JSON.parseObject(res, TriggerIds.class).getTriggerids(); Map tags = new ConcurrentHashMap<>(1); tags.put(EVENT_TAG_NAME, "{HOST.HOST}##" + productAttr.getKey()); zbxTrigger.triggerTagCreate(triggerids[0], tags); - return true; - } - - - @Override - public Boolean defaultValue() { - return true; } @Data diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdStatusTriggerEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdStatusTriggerEventHandler.java new file mode 100644 index 00000000..f36d1e89 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdStatusTriggerEventHandler.java @@ -0,0 +1,42 @@ +package com.zmops.iot.web.product.service.event; + + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @author yefei + *

                                                  + * 产品服务创建 同步到设备 步骤 + */ +@Slf4j +@Component +public class SaveProdStatusTriggerEventHandler {//implements IWorker + + +// @Override +// public Boolean action(ProductServiceDto productServiceDto, Map map) { +// +// String prodId = productServiceDto.getRelationId(); +// +// List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); +// List productStatusFunctionRelationList = new ArrayList<>(); +// for (String deviceId : deviceIds) { +// ProductStatusFunctionRelation productStatusFunctionRelation = new ProductStatusFunctionRelation(); +// productStatusFunctionRelation.setRelationId(deviceId); +// productStatusFunctionRelation.setRuleId(productServiceDto.getId()); +// productStatusFunctionRelation.setInherit("1"); +// productStatusFunctionRelationList.add(productStatusFunctionRelation); +// } +// DB.saveAll(productStatusFunctionRelationList); +// +// return true; +// } +// +// +// @Override +// public Boolean defaultValue() { +// return true; +// } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdSvcEventHandler.java similarity index 78% rename from zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdSvcEventHandler.java index 41a4fc2e..fd9d539e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdSvcEventHandler.java @@ -1,20 +1,21 @@ -package com.zmops.iot.web.product.service.work; +package com.zmops.iot.web.product.service.event; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.product.ProductServiceRelation; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.ProductServiceCreateEvent; import com.zmops.iot.web.product.dto.ProductServiceDto; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; -import java.util.Map; /** * @author yefei @@ -23,18 +24,20 @@ */ @Slf4j @Component -public class SaveProdSvcWorker implements IWorker { +@EnableAsync +public class SaveProdSvcEventHandler implements ApplicationListener { @Override - public Boolean action(ProductServiceDto productServiceDto, Map map) { - + @Async + public void onApplicationEvent(ProductServiceCreateEvent event) { + ProductServiceDto productServiceDto = event.getEventData(); String prodId = productServiceDto.getRelationId(); //查询出 继承了此产品的设备 List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); if (ToolUtil.isEmpty(deviceIds)) { - return true; + return; } List productServiceRelationList = new ArrayList<>(); @@ -60,13 +63,6 @@ public Boolean action(ProductServiceDto productServiceDto, Map { +@EnableAsync +public class SaveProductEventTriggerEventHandler implements ApplicationListener { @Autowired ZbxTrigger zbxTrigger; @Override - public Boolean action(ProductEventRule productEventRule, Map map) { + @Async + public void onApplicationEvent(ProductEventTriggerCreateEvent event) { log.debug("SaveProductEventTriggerWorker…………"); - + ProductEventRule productEventRule = event.getEventData(); String prodId = productEventRule.getProductId(); List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); List triggers = JSONObject.parseArray(zbxTrigger.triggerGetByName(productEventRule.getEventRuleId() + ""), ProductEventRuleService.Triggers.class); - Map treiggerMap = triggers.parallelStream().collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ProductEventRuleService.Triggers::getTriggerid)); + Map treiggerMap = triggers.parallelStream().collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ProductEventRuleService.Triggers::getTriggerid, (a, b) -> a)); List productEventRelationList = new ArrayList<>(); List addProductEventServiceList = new ArrayList<>(); @@ -74,13 +78,6 @@ public Boolean action(ProductEventRule productEventRule, Map { +public class UpdateAttributeEventEventHandler implements ApplicationListener { @Override - public Boolean action(ProductAttr productAttr, Map map) { + @Async + public void onApplicationEvent(ProductAttrCreateEvent event) { log.debug("UpdateAttributeEventWorker…………"); + ProductAttr productAttr = event.getEventData(); - Long attrId = productAttr.getAttrId(); - - List list = new QProductAttributeEvent().templateId.eq(attrId).findList(); + List list = new QProductAttributeEvent().templateId.eq(productAttr.getAttrId()).findList(); for (ProductAttributeEvent productAttributeEvent : list) { productAttributeEvent.setName(productAttr.getAttrName()); @@ -39,13 +39,6 @@ public Boolean action(ProductAttr productAttr, Map map) { } DB.updateAll(list); - return true; - } - - - @Override - public Boolean defaultValue() { - return true; } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/UpdateProdSvcEventHandler.java similarity index 76% rename from zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java rename to zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/UpdateProdSvcEventHandler.java index 2b670cc7..36f577b3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateProdSvcWorker.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/UpdateProdSvcEventHandler.java @@ -1,20 +1,20 @@ -package com.zmops.iot.web.product.service.work; +package com.zmops.iot.web.product.service.event; import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.product.query.QProductServiceParam; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.ProductServiceCreateEvent; import com.zmops.iot.web.product.dto.ProductServiceDto; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; import io.ebean.DB; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; -import java.util.Map; /** * @author yefei @@ -23,19 +23,20 @@ */ @Slf4j @Component -public class UpdateProdSvcWorker implements IWorker { +public class UpdateProdSvcEventHandler implements ApplicationListener { @Override - public Boolean action(ProductServiceDto productServiceDto, Map map) { + @Async + public void onApplicationEvent(ProductServiceCreateEvent event) { log.debug("UpdateProdSvcWorker…………"); - + ProductServiceDto productServiceDto = event.getEventData(); String prodId = productServiceDto.getRelationId(); //查询出继承了此产品的设备 List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); if (ToolUtil.isEmpty(deviceIds)) { - return true; + return; } new QProductServiceParam().serviceId.eq(productServiceDto.getId()).deviceId.in(deviceIds).delete(); @@ -53,13 +54,6 @@ public Boolean action(ProductServiceDto productServiceDto, Map { - +@EnableAsync +public class UpdateProductEventTriggerEventHandler implements ApplicationListener { @Autowired ZbxTrigger zbxTrigger; @Override - public Boolean action(ProductEventRule productEventRule, Map map) { + @Async + public void onApplicationEvent(ProductEventTriggerCreateEvent event) { log.debug("UpdateProductEventTriggerWorker…………"); - + ProductEventRule productEventRule = event.getEventData(); String prodId = productEventRule.getProductId(); List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); @@ -52,13 +54,6 @@ public Boolean action(ProductEventRule productEventRule, Map - * 产品服务创建 同步到设备 步骤 - */ -@Slf4j -@Component -public class SaveProdStatusTriggerWorker implements IWorker { - - - @Override - public Boolean action(ProductServiceDto productServiceDto, Map map) { - - String prodId = productServiceDto.getRelationId(); - - List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); - List productStatusFunctionRelationList = new ArrayList<>(); - for (String deviceId : deviceIds) { - ProductStatusFunctionRelation productStatusFunctionRelation = new ProductStatusFunctionRelation(); - productStatusFunctionRelation.setRelationId(deviceId); - productStatusFunctionRelation.setRuleId(productServiceDto.getId()); - productStatusFunctionRelation.setInherit("1"); - productStatusFunctionRelationList.add(productStatusFunctionRelation); - } - DB.saveAll(productStatusFunctionRelationList); - - return true; - } - - - @Override - public Boolean defaultValue() { - return true; - } - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java deleted file mode 100644 index c141334b..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.zmops.iot.web.product.service.work; - - -import com.zmops.iot.domain.product.ProductAttribute; -import com.zmops.iot.domain.product.query.QProductAttribute; -import com.zmops.iot.web.product.dto.ProductAttr; -import com.zmops.zeus.server.async.callback.IWorker; -import com.zmops.zeus.server.async.wrapper.WorkerWrapper; -import io.ebean.DB; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -/** - * @author yefei - *

                                                  - * 产品属性修改 同步到设备 步骤 - */ -@Slf4j -@Component -public class UpdateAttributeWorker implements IWorker { - - private static final String ATTR_SOURCE_DEPEND = "18"; - - @Override - public Boolean action(ProductAttr productAttr, Map map) { - log.debug("UpdateAttributeWorker…………"); - - Long attrId = productAttr.getAttrId(); - - List list = new QProductAttribute().templateId.eq(attrId).findList(); - - //处理依赖属性 - Map attrIdMap = new ConcurrentHashMap<>(list.size()); - if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { - List productAttributeList = new QProductAttribute().templateId.eq(productAttr.getDepAttrId()).findList(); - attrIdMap = productAttributeList.parallelStream().collect(Collectors.toMap(ProductAttribute::getProductId, ProductAttribute::getAttrId)); - } - - for (ProductAttribute productAttribute : list) { - productAttribute.setName(productAttr.getAttrName()); - productAttribute.setKey(productAttr.getKey()); - productAttribute.setUnits(productAttr.getUnits()); - productAttribute.setSource(productAttr.getSource()); - productAttribute.setValueType(productAttr.getValueType()); - productAttribute.setValuemapid(productAttr.getValuemapid()); - if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource()) && null != attrIdMap.get(productAttribute.getProductId())) { - productAttribute.setDepAttrId(attrIdMap.get(productAttribute.getProductId())); - } - } - DB.updateAll(list); - - return true; - } - - - @Override - public Boolean defaultValue() { - return true; - } - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolGatewayService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolGatewayService.java index 5d67da0c..f6762610 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolGatewayService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolGatewayService.java @@ -74,12 +74,12 @@ public List list(ProtocolGatewayParam protocolGatewayParam) { @Transactional public ProtocolGateway create(ProtocolGatewayParam protocolGatewayParam) { - ProtocolGateway ProtocolGateway = new ProtocolGateway(); - ToolUtil.copyProperties(protocolGatewayParam, ProtocolGateway); - ProtocolGateway.setStatus("0"); - DB.insert(ProtocolGateway); + ProtocolGateway protocolGateway = new ProtocolGateway(); + ToolUtil.copyProperties(protocolGatewayParam, protocolGateway); + protocolGateway.setStatus("0"); + DB.insert(protocolGateway); - saveMqtt(protocolGatewayParam.getProtocolGatewayMqttList(), ProtocolGateway.getProtocolGatewayId()); + saveMqtt(protocolGatewayParam.getProtocolGatewayMqttList(), protocolGateway.getProtocolGatewayId()); Map option = initOptionMap(protocolGatewayParam); @@ -89,17 +89,17 @@ public ProtocolGateway create(ProtocolGatewayParam protocolGatewayParam) { // protocolOption.setOptions(option); Map params = new HashMap<>(7); - params.put("routeId", ProtocolGateway.getProtocolGatewayId() + ""); - params.put("name", ProtocolGateway.getName()); + params.put("routeId", protocolGateway.getProtocolGatewayId() + ""); + params.put("name", protocolGateway.getName()); params.put("protocolServiceId", protocolGatewayParam.getProtocolServiceId() + ""); params.put("protocolComponentId", protocolGatewayParam.getProtocolComponentId() + ""); - params.put("status", ProtocolGateway.getStatus()); + params.put("status", protocolGateway.getStatus()); params.put("protocol", ProtocolEnum.getDescription(protocolGatewayParam.getProtocolType())); params.put("option", JSON.toJSONString(option)); params.put("mqttList", JSON.toJSONString(protocolGatewayParam.getProtocolGatewayMqttList())); Forest.post("/protocol/gateway/createProtocolGateway").host("127.0.0.1").port(12800).addBody(params, "text/html;charset=utf-8").execute(); - return ProtocolGateway; + return protocolGateway; } private Map initOptionMap(ProtocolGatewayParam protocolGatewayParam) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolSvrService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolSvrService.java index 0c34bae3..2190cdbb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolSvrService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolSvrService.java @@ -117,13 +117,13 @@ public void delete(List protocolServiceIds) { public void updateProtocolServiceEvent() { List serviceList = new QProtocolService().findList(); - Map map = serviceList.parallelStream().collect(Collectors.toMap(ProtocolService::getProtocolServiceId, ProtocolService::getName)); + Map map = serviceList.parallelStream().collect(Collectors.toMap(ProtocolService::getProtocolServiceId, ProtocolService::getName, (a, b) -> a)); DefinitionsUtil.updateProtocolServiceCache(map); } @Override public void run(String... args) throws Exception { - updateProtocolServiceEvent(); + //updateProtocolServiceEvent(); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictService.java index 064163a7..a16e8fa0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictService.java @@ -139,7 +139,7 @@ public Map> groupDictByCode(String dictTypeCode) { private void updateDictionaries() { List dictTypes = new QSysDictType().findList(); - Map map = dictTypes.parallelStream().collect(Collectors.toMap(SysDictType::getDictTypeId, SysDictType::getCode)); + Map map = dictTypes.parallelStream().collect(Collectors.toMap(SysDictType::getDictTypeId, SysDictType::getCode, (a, b) -> a)); List collect = dictTypes.stream().map(SysDictType::getDictTypeId).collect(Collectors.toList()); List dictList = new QSysDict().dictTypeId.in(collect).findList(); Table dictionaryValues = HashBasedTable.create(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/Tenantervice.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/Tenantervice.java index 5f70a269..fe4e8ef8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/Tenantervice.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/Tenantervice.java @@ -15,7 +15,6 @@ import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.device.dto.DeviceGroupDto; import com.zmops.iot.web.device.dto.param.DeviceGroupParam; import com.zmops.iot.web.device.service.DeviceGroupService; import com.zmops.iot.web.exception.enums.BizExceptionEnum; @@ -197,7 +196,7 @@ private void updateTenantName() { if (ToolUtil.isEmpty(list)) { return; } - DefinitionsUtil.updateTenantName(list.parallelStream().collect(Collectors.toMap(TenantInfo::getTenantId, TenantInfo::getName))); + DefinitionsUtil.updateTenantName(list.parallelStream().collect(Collectors.toMap(TenantInfo::getTenantId, TenantInfo::getName, (a, b) -> a))); } @Override From c0fc85d75345ed19caacaa58bafac16ac120621c Mon Sep 17 00:00:00 2001 From: "yefei@zmops.com" Date: Wed, 1 Jun 2022 16:37:39 +0800 Subject: [PATCH 760/763] fix pom --- iot-server/server-camel-receiver/pom.xml | 6 ++ zeus-starter/pom.xml | 104 +++++++++++------------ 2 files changed, 58 insertions(+), 52 deletions(-) diff --git a/iot-server/server-camel-receiver/pom.xml b/iot-server/server-camel-receiver/pom.xml index 72347dbd..fa384fa5 100644 --- a/iot-server/server-camel-receiver/pom.xml +++ b/iot-server/server-camel-receiver/pom.xml @@ -63,6 +63,12 @@ 1.0.3-RELEASE compile + + com.zmops + server-localdb + 1.0-beta + compile + diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index 40aa8e4b..8884572a 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -72,58 +72,58 @@ false - - com.github.eirslett - frontend-maven-plugin - ${frontend-maven-plugin.version} - - ${ui.path} - v8.17.0 - - - - install node and npm - - install-node-and-npm - - - - npm install - - npm - - - install --registry=https://registry.npm.taobao.org/ --unsafe-perm - - - - npm run build - - npm - - - run build - - - - - - maven-resources-plugin - - ${project.build.sourceEncoding} - ${project.build.directory}/classes - - - ${basedir}/target/classes/public - ${ui.path}/dist - - - ${basedir}/target/classes - src/main/resources - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.springframework.boot spring-boot-maven-plugin From 58c48aab9e84c5ae0051bdd8c32762d806820629 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Wed, 28 Dec 2022 16:54:45 +0800 Subject: [PATCH 761/763] [fix]: centos script --- docs/centos/install.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/centos/install.sh b/docs/centos/install.sh index 1c1f8411..7bd48463 100755 --- a/docs/centos/install.sh +++ b/docs/centos/install.sh @@ -4,11 +4,11 @@ ROOT_UID=0 release=Centos basename=$(pwd) -zabbixsrc=$basename/zabbix-5.4.3 +zabbixsrc=$basename/zabbix-5.0.30 INSTALLDIR=/opt/zeus ZABBIX_HOME=$INSTALLDIR/zabbix PHP_CONF=/etc/opt/rh/rh-php73 -sqldir=$basename/zabbix-5.4.3/database/postgresql +sqldir=$basename/zabbix-5.0.30/database/postgresql PGDATA=$INSTALLDIR/pgdata zeusurl= @@ -209,7 +209,7 @@ function ZbxInstall() { groupadd --system zabbix || true useradd --system -g zabbix -d $INSTALLDIR/zabbix -s /sbin/nologin -c "Zabbix Monitoring System" zabbix || true - wget -c https://cdn.zabbix.com/zabbix/sources/stable/5.4/zabbix-5.4.3.tar.gz -o /dev/null -O - | tar -xz + wget -c https://cdn.zabbix.com/zabbix/sources/stable/5.0/zabbix-5.0.30.tar.gz -o /dev/null -O - | tar -xz logprint "下载zabbix源码失败,请检查网络。。。" cd "$zabbixsrc" && ./configure --prefix=$ZABBIX_HOME \ From b314c05a497dc0901cb658f8704e2efa62953cb4 Mon Sep 17 00:00:00 2001 From: "chunyu@zmops.com" Date: Fri, 30 Dec 2022 17:49:35 +0800 Subject: [PATCH 762/763] [fix]: zabbix Cannot start session problem --- docs/centos/install.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/centos/install.sh b/docs/centos/install.sh index 7bd48463..1bb445af 100755 --- a/docs/centos/install.sh +++ b/docs/centos/install.sh @@ -324,6 +324,7 @@ function PHPInstall() { sed -i 's/;listen.owner = nobody/listen.owner = zeus/g' $PHP_CONF/php-fpm.d/www.conf sed -i 's/;listen.group = nobody/listen.group = zeus/g' $PHP_CONF/php-fpm.d/www.conf sed -i 's/\(^listen =\).*/\1\/var\/run\/php-fpm.sock/g' $PHP_CONF/php-fpm.d/www.conf + chmod 777 /var/opt/rh/rh-php73/lib/php/session -R echo -e "\033[32m [ OK ] \033[0m" } From f12794a70bc3af07955bbfb46d73206ec4e43e71 Mon Sep 17 00:00:00 2001 From: wooyea Date: Fri, 18 Aug 2023 09:10:48 +0800 Subject: [PATCH 763/763] fix compile issues Signed-off-by: wooyea --- .../core/servlet/DeviceTriggerActionHandler.java | 4 +--- .../server/core/servlet/HttpItemTrapperHandler.java | 7 ++++++- .../zmops/zeus/server/jetty/JettyJsonHandler.java | 13 +++++++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 iot-server/server-core/src/main/java/com/zmops/zeus/server/jetty/JettyJsonHandler.java diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java index 673f972e..85671250 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java @@ -37,11 +37,9 @@ public String pathSpec() { * * @param req * @return JsonElement - * @throws ArgumentsParseException ex - * @throws IOException ex */ @Override - protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException, IOException { + public JsonElement doPost(HttpServletRequest req) throws IOException { String request = getJsonBody(req); log.info("action command : {}", request); diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/HttpItemTrapperHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/HttpItemTrapperHandler.java index 50cf9f05..48c16a18 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/HttpItemTrapperHandler.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/HttpItemTrapperHandler.java @@ -40,7 +40,7 @@ public String pathSpec() { } @Override - protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException, IOException { + public JsonElement doPost(HttpServletRequest req) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(req.getInputStream())); String line; @@ -61,4 +61,9 @@ protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseExcept zabbixSenderService.sendData(gson.toJson(zabbixTrapper)); return requestJson; } + + @Override + public String getJsonBody(HttpServletRequest req) throws IOException { + return null; + } } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/server/jetty/JettyJsonHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/server/jetty/JettyJsonHandler.java new file mode 100644 index 00000000..d2c54e03 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/server/jetty/JettyJsonHandler.java @@ -0,0 +1,13 @@ +package com.zmops.zeus.server.jetty; + +import com.google.gson.JsonElement; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +public abstract class JettyJsonHandler { + public abstract String pathSpec(); + public abstract JsonElement doPost(HttpServletRequest req) throws IOException; + public abstract String getJsonBody(HttpServletRequest req) throws IOException; + +}